--3e03 0003a5c949b40100002 Page 1 of MANIFEST
88872c 1 test-file
e80832 2 MANIFEST
f1c295 3 sortpages.patch
53881e 4 shasum
cb6938 5 libhashes.asc
985df8 6 PGPChangeHistory.txt
181b95 D clients/pgp/
73ec2e D clients/pgp/shared/
26a816 D clients/pgp/shared/JPEG/
9bc42d 7 README
e2d0ae D clients/pgp/shared/JPEG/common/
d16145 8 cderror.h
ee08e3 9 ckconfig.c
87cfd8 10 jcapimin.c
3ca5fd 11 jcapistd.c
5a7aaa 12 jccoefct.c
e0b3fb 13 jccolor.c
67d477 14 jcdctmgr.c
6933c5 15 jchuff.c
f529de 16 jchuff.h
c8f88c 17 jcinit.c
1c2782 18 jcmainct.c
1a85e1 19 jcmarker.c
7acef6 20 jcmaster.c
ed5bb9 21 jcomapi.c
0ac726 22 jconfig.h
728177 23 jcparam.c
47aece 24 jcphuff.c
7273ab 25 jcprepct.c
f311f9 26 jcsample.c
7ac6aa 27 jctrans.c
e7a57b 28 jdapimin.c
14cf5e 29 jdapistd.c
63fc5f 30 jdatadst.c
153857 31 jdatasrc.c
2c438b 32 jdcoefct.c
685143 33 jdcolor.c
abd2c0 34 jdct.h
aee8fb 35 jddctmgr.c
8553c3 36 jdhuff.c
fae2fa 37 jdhuff.h
7fa571 38 jdinput.c
9d1b0e 39 jdmainct.c
e7e482 40 jdmarker.c
4901c3 41 jdmaster.c
70a0bd 42 jdmerge.c
52d85a 43 jdphuff.c
4ca093 44 jdpostct.c
00d596 45 jdsample.c
cab7f3 46 jdtrans.c
d2a513 47 jerror.c
b85df7 48 jerror.h
54dabd 49 jfdctflt.c
b6522e 50 jfdctfst.c
2ea23e 51 jfdctint.c
da2a14 52 jidctflt.c
1df105 53 jidctfst.c
de1cfb 54 jidctint.c
39f28e 55 jidctred.c
029cea 56 jinclude.h
e506c1 57 jmemansi.c
51e471 58 jmemdos.c
42e64e 59 jmemmac.c
fa8382 60 jmemmgr.c
4ffea0 61 jmemname.c
b82b32 62 jmemnobs.c
d75295 63 jmemsys.h
5107a5 64 jmorecfg.h
caf64a 65 jpegint.h
d6ddc4 66 jpeglib.h
04472b 67 jpegtran.c
3a4abc 68 jquant1.c
--5f66 0008519c81940100002 Page 2 of MANIFEST
b8ea24 69 jquant2.c
fdef4c 70 jutils.c
302d79 71 jversion.h
304da0 72 pgpJPEG.c
5c2c5d 73 pgpJPEG.h
65684b 74 rdcolmap.c
b1d3ad 75 rdjpgcom.c
794dd0 76 rdswitch.c
227ff3 77 rdtarga.c
53dc98 78 wrjpgcom.c
62ec2e D clients/pgp/shared/
e187ed 79 pgpAdminPrefs.h
3d0ce8 80 pgpBuildFlags.h
4920dc 81 pgpClientErrors.c
7bad9f 82 pgpClientErrors.h
39b7f2 83 pgpClientPrefs.h
3a22bd 84 pgpClientShared.h
5c624e 85 pgpDiskWiper.c
81b6f7 86 pgpDiskWiper.h
42384e 87 pgpKeyServerPrefs.c
2ff8fb 88 pgpKeyServerPrefs.h
497c44 89 pgpPassBuffer.c
1c0c0d 90 pgpPassBuffer.h
caf52d 91 pgpSKEP.c
95966b 92 pgpSKEP.h
5cebcc 93 pgpShare.c
a21727 94 pgpShare.h
152170 95 pgpShareFile.c
91f5c9 96 pgpShareFile.h
7ba76f 97 pgpSharePriv.h
6f0cc2 98 pgpVersionHeader.c
62df06 99 pgpVersionHeader.h
d096b1 D libs/
fc8acf D libs/network/
95f770 D libs/network/ldaplib/
0e03d6 100 Make-common
48a895 101 Makefile
f0561e D libs/network/ldaplib/build/
7b3cc0 102 Make-append
836fda 103 Make-template
2ba351 104 Makefile
d8f29f 105 PORTS
9d52e3 106 README-unproto
9ea381 107 db.1.85.patch
2130cc 108 install.sh
79a432 109 mkdep
4f55fb 110 uname.sh
a8a30e 111 version
ecad31 D libs/network/ldaplib/include/
acf1c5 112 Make-template
ce86e2 113 Makefile
66c1d3 114 disptmpl.h
623118 115 lber.h
42eb83 116 ldap.h
6f6189 117 ldapconfig-win32.h
3086b0 118 ldapconfig.h
4abfa8 119 ldapconfig.h.edit
2f2e76 120 ldapconfig.h.um
5be750 121 pgpSrvStd.h
ed8112 122 portable.h
1ccca5 123 proto-lber.h
a130fe 124 proto-ldap.h
14f570 125 regex.h
0c80a3 126 srchpref.h
bf889a 127 sysexits-compat.h
844d45 D libs/network/ldaplib/liblber/
f58521 128 Make-template
9a1684 129 Makefile
7faf06 130 Version.c
93a4b9 131 bprint.c
b19358 132 decode.c
85d0f4 133 dtest.c
--2bbe 0009f8ae16f40100002 Page 3 of MANIFEST
028cbe 134 encode.c
deb999 135 etest.c
954139 136 idtest.c
f89eb7 137 io.c
0fe72e 138 pgpSrvMem.c
f7b189 D libs/network/ldaplib/libldap/
531b3e 139 Make-template
fef872 140 Makefile
e03210 141 Version.c
bb99ff 142 abandon.c
2e7625 143 add.c
770c32 144 addentry.c
8d2dd8 145 bind.c
c20181 146 cache.c
61ac37 147 charset.c
b24e76 148 cldap.c
eb554d 149 compare.c
37bb0d 150 delete.c
71c5db 151 disptmpl.c
54289c 152 dsparse.c
a92a7a 153 error.c
cf17b6 154 free.c
287789 155 friendly.c
86a870 156 getattr.c
3ce8db 157 getdn.c
6f8b9a 158 getdxbyname.c
226a6d 159 getentry.c
0dade4 160 getfilter.c
1c0f54 161 getopt.c
189a88 162 getvalues.c
56bde7 163 kbind.c
7f4cd9 164 ldap-int.h
05423f 165 ldapfilter.conf
20af22 166 ldapfriendly
a69bdf 167 ldapsearchprefs.conf
f13d39 168 ldaptemplates.conf
bfd879 169 modify.c
6a598a 170 modrdn.c
88b49a 171 open.c
676b7f 172 os-ip.c
30f2ce 173 regex.c
4d9f7b 174 request.c
0f360e 175 result.c
d00209 176 sbind.c
63701b 177 search.c
236654 178 sort.c
16dc73 179 srchpref.c
7e5110 180 test.c
e7dab2 181 tmplout.c
0dc435 182 tmpltest.c
96ae30 183 ufn.c
be2914 184 unbind.c
b313a7 185 url.c
57e5a9 D libs/network/ldaplib/pgpsockets/
d27a48 186 pgpSockets-ip.c
16fdb4 187 pgpSocketsLDAP.h
6806ed D libs/pfl/
0025f3 188 Makefile.in
21eb2f 189 aclocal.m4
76077f 190 configure.in
2a881d D libs/pfl/common/
27fc50 191 Makefile.in
52c26c 192 pflTypes.h
ae5522 193 pgpBase.h
886179 194 pgpBinaryTree.c
757d36 195 pgpBinaryTree.h
0cb32c 196 pgpDebug.c
f95229 197 pgpDebug.h
eadf98 198 pgpException.h
88c373 199 pgpLeaks.c
6b46e9 200 pgpLeaks.h
9f51e1 201 pgpMem.c
--935a 000e8e9c34e40100002 Page 4 of MANIFEST
de4bfa 202 pgpMem.h
f3266e 203 pgpMemoryMgr.c
57b2eb 204 pgpMemoryMgr.h
3ebfe7 205 pgpMemoryMgrMac.c
ba6321 206 pgpMemoryMgrPriv.h
46b77d 207 pgpMemoryMgrStd.c
028067 208 pgpMemoryMgrWin32.c
85070e 209 pgpPFLErrors.h
199e2e 210 pgpRMWOLock.c
33f496 211 pgpRMWOLock.h
c37aac 212 pgpTemplate.c
f61014 213 pgpTemplate.h
387b03 214 pgpTypes.h
be1fe7 D libs/pfl/common/classes/
d1a7b2 215 CComboError.h
177b91 D libs/pfl/common/file/
674784 216 Makefile.in
b55a05 217 pgpFileIO.c
422149 218 pgpFileIO.h
830848 219 pgpFileIOPriv.h
8fa101 220 pgpFileSpec.c
d4cbb9 221 pgpFileSpec.h
18ccfc 222 pgpFileSpecMac.c
61bb1d 223 pgpFileSpecMac.h
b4081a 224 pgpFileSpecMacPriv.h
8c9834 225 pgpFileSpecPriv.h
9f2fdd 226 pgpFileSpecStd.c
e0583c 227 pgpFileSpecStd.h
6b133b 228 pgpFileSpecStdPriv.h
64a157 229 pgpFileSpecVTBL.c
b36713 230 pgpFileSpecVTBL.h
e03e1d 231 pgpFileSpecWin32.c
656f88 232 pgpFileUtilities.c
f9bc4c 233 pgpFileUtilities.h
4b8147 234 pgpIO.c
6c49c8 235 pgpIO.h
8e81cb 236 pgpIOPriv.h
9399a8 237 pgpIOSample.c
c6e77f 238 pgpIOUtilities.c
6d909e 239 pgpIOUtilities.h
ba7f33 240 pgpLineEndIO.c
488b94 241 pgpLineEndIO.h
c7a641 242 pgpLineEndIOPriv.h
847d63 243 pgpMemoryIO.c
592b88 244 pgpMemoryIO.h
8f7be1 245 pgpMemoryIOPriv.h
035929 246 pgpProxyIO.c
68f5ab 247 pgpProxyIO.h
8ecbfd 248 pgpProxyIOPriv.h
b91a98 249 pgpStdFileIO.c
8c96a0 250 pgpStdFileIO.h
dd8c6d 251 pgpStdFileIOPriv.h
7c4ebd D libs/pfl/common/lthread/
a49c84 252 Makefile.in
607b90 253 pgpCond.c
58fa4a 254 pgpMutex.c
822cf9 255 pgpSemaphore.c
48a2e9 256 pgpThreads.c
6e0e6b 257 pgpThreads.h
afa7d2 D libs/pfl/common/prefs/
b08e33 258 Makefile.in
39dc71 259 pflPrefTypes.c
e5a996 260 pflPrefTypes.h
b6440e 261 pflPrefs.c
00ae51 262 pflPrefs.h
bab5dc D libs/pfl/common/sorting/
49a132 263 pgpHeapSort.h
aef3cd 264 pgpInsertionSort.h
ad0f21 D libs/pfl/common/util/
79347d 265 Makefile.in
43bf70 266 pgpBitUtils.c
e8d5c8 267 pgpBitUtils.h
--2c80 000a0e52b5f40100002 Page 5 of MANIFEST
ece33b 268 pgpEndianConversion.c
e25cd7 269 pgpEndianConversion.h
6a3f99 270 pgpHex.c
bd8ea0 271 pgpHex.h
13a50b 272 pgpPassphraseUtils.c
4fc86a 273 pgpPassphraseUtils.h
77cc1d 274 pgpStrings.c
2b609f 275 pgpStrings.h
e908c5 276 pgpWordWrap.c
03627d 277 pgpWordWrap.h
a8ec61 D libs/pgpcdk/
a11e67 278 Makefile.in
c4b493 279 SDKChangeHistory
071b94 280 aclocal.m4
68f154 281 configure.in
435f1a D libs/pgpcdk/priv/
34ad65 282 Makefile.in
ea1771 D libs/pgpcdk/priv/clientlib/
f5d38f 283 Makefile.in
90ca30 284 pgpClientEncode.c
7426c3 285 pgpClientKeyDB.c
59e580 D libs/pgpcdk/priv/crypto/
6e5edc 286 Makefile.in
c779d7 D libs/pgpcdk/priv/crypto/cipher/
ea2036 287 Makefile.in
aff18b 288 pgpCAST5.c
08108e 289 pgpCAST5.h
5dcab7 290 pgpCASTBox5.h
e996a6 291 pgpCBC.c
9a05c0 292 pgpCBCPriv.h
4b0c2f 293 pgpCFB.c
bb0377 294 pgpCFBPriv.h
ba0665 295 pgpDES3.c
5a6523 296 pgpDES3.h
a40898 297 pgpDES3_68K.c
534a25 298 pgpIDEA.c
392bd8 299 pgpIDEA.h
fecac5 300 pgpSymmetricCipher.c
60159f 301 pgpSymmetricCipherPriv.h
685952 D libs/pgpcdk/priv/crypto/compress/
997207 302 Makefile.in
f2839b 303 pgpCompress.h
640204 304 pgpZInflate.c
d168bc 305 pgpZInflate.h
30c63e D libs/pgpcdk/priv/crypto/hash/
0581be 306 Makefile.in
103abe 307 pgpHMAC.c
198b41 308 pgpHash.c
8ecaef 309 pgpHashPriv.h
e388b2 310 pgpMD2.c
31398b 311 pgpMD2.h
b974b1 312 pgpMD5.c
c5c588 313 pgpMD5.h
3e3965 314 pgpRIPEMD160.c
98cdc2 315 pgpRIPEMD160.h
ab0e6f 316 pgpSHA.c
1fbf56 317 pgpSHA.h
e69162 D libs/pgpcdk/priv/crypto/bignum/
54289a 318 Makefile.in
a0d354 319 bn.c
3afc15 320 bn.h
c6fe3c 321 bn00.c
3c68e5 322 bn16.c
0dc1b0 323 bn16.h
d9a89e 324 bn32.c
5901cb 325 bn32.h
665eaa 326 bn64.c
5ef7ff 327 bn64.h
cef956 328 bn68000.c
31d711 329 bn8086.c
831cb5 330 bndsaprime.c
a0b037 331 bndsaprime.h
--b9e2 0004ef842ab40100002 Page 6 of MANIFEST
0b80c7 332 bngermain.c
751a85 333 bngermain.h
a07475 334 bni.h
f3f2f3 335 bni00.c
ccc644 336 bni16.c
140ecb 337 bni16.h
b923db 338 bni32.c
4eeb54 339 bni32.h
e287da 340 bni64.c
b34f55 341 bni64.h
c1f7d6 342 bni68000.c
2f16d3 343 bni68000.h
fdfcb0 344 bni68020.c
7c1db5 345 bni68020.h
1b4d52 346 bni80386.asm
44f341 347 bni80386.h
75b753 348 bni80386.s
0bc3ae 349 bni80386_aout.s
003b53 350 bni80386c.c
5fa111 351 bni80386c.h
b7b83d 352 bni8086.asm
9d163e 353 bni8086.h
82fc75 354 bni960jx.s
8d2ed7 355 bnialpha.h
dc5119 356 bnialpha.s
0a98e5 357 bnimem.c
ff6001 358 bnimem.h
60062f 359 bninit16.c
55c9b0 360 bninit32.c
f4a1d3 361 bninit64.c
405ff6 362 bnippc.c
8aeecf 363 bnippc.h
447b05 364 bnisparc.h
930f91 365 bnisparc.s
a45e0c 366 bnjacobi.c
b2bf09 367 bnjacobi.h
9a0c43 368 bnkludge.h
064ed9 369 bnlegal.c
4c2065 370 bnlegal.h
76e924 371 bnppcasm.h
3a634c 372 bnprime.c
f402b1 373 bnprime.h
21a657 374 bnprint.c
c6c7aa 375 bnprint.h
1eedf9 376 bnsieve.c
f08c04 377 bnsieve.h
4c86b6 378 bnsize00.h
8ce855 379 lbn00.c
89492c 380 pgpBigNum.c
562544 D libs/pgpcdk/priv/crypto/pipe/
baa04b 381 Makefile.in
8c8e99 D libs/pgpcdk/priv/crypto/pipe/crypt/
342375 382 Makefile.in
9078d3 383 pgpCiphrMod.c
402e38 384 pgpCiphrMod.h
d2792e 385 pgpConvMod.c
0345f8 386 pgpConvMod.h
c49094 387 pgpMakePKE.c
6bd589 388 pgpMakePKE.h
1f589a 389 pgpPKEMod.c
546591 390 pgpPKEMod.h
767625 D libs/pgpcdk/priv/crypto/pipe/file/
b4e861 391 Makefile.in
fab8eb 392 pgpArmor.c
2859ee 393 pgpArmor.h
fc03df 394 pgpArmrFil.c
aeaf5d 395 pgpArmrFil.h
4a87ad 396 pgpCRC.c
e93694 397 pgpCRC.h
41e8b3 398 pgpFileMod.c
dc4431 399 pgpFileMod.h
4e44f4 400 pgpHeader.c
--10a9 000591b2ffc40100002 Page 7 of MANIFEST
6bdeb6 401 pgpHeader.h
22bd5f 402 pgpPrsAsc.c
49271d 403 pgpPrsAsc.h
1c9ce4 404 pgpRadix64.c
453066 405 pgpRadix64.h
4fa477 D libs/pgpcdk/priv/crypto/pipe/parser/
fa33fd 406 Makefile.in
874f16 407 pgpPrsBin.c
f7345a 408 pgpPrsBin.h
e7ef97 409 pgpReadAnn.c
1e9c77 410 pgpReadAnn.h
5f7442 411 pgpVerifyRa.c
dc0acb 412 pgpVerifyRa.h
1f829a 413 pgpVrfySig.c
e496f5 414 pgpVrfySig.h
5cfc24 D libs/pgpcdk/priv/crypto/pipe/sig/
97f8e9 415 Makefile.in
7e1b71 416 pgpHashMod.c
d7b7f3 417 pgpHashMod.h
b0b2cb 418 pgpSigMod.c
9f2889 419 pgpSigMod.h
9725f7 D libs/pgpcdk/priv/crypto/pipe/text/
60adc4 420 Makefile.in
feb752 421 pgpCompMod.c
ba8b84 422 pgpCompMod.h
b4b429 423 pgpDefMod.c
4a2006 424 pgpDefMod.h
0510fa 425 pgpInfMod.c
f4776c 426 pgpInfMod.h
dbca54 427 pgpLiteral.c
da8f49 428 pgpLiteral.h
d0838c 429 pgpTextFilt.c
8aa9ff 430 pgpTextFilt.h
358189 431 pgpZBits.c
c8a88e 432 pgpZDeflate.c
5f9d4f 433 pgpZMatch.asm
604da7 434 pgpZTailor.h
221cb7 435 pgpZTrees.c
c1eed0 436 pgpZip.h
6717b7 D libs/pgpcdk/priv/crypto/pipe/utils/
259569 437 Makefile.in
a08f12 438 pgpAddHdr.c
e51550 439 pgpAddHdr.h
6b709d 440 pgpBufMod.c
fdeadf 441 pgpBufMod.h
9df3e3 442 pgpCopyMod.c
365f61 443 pgpCopyMod.h
ce79b4 444 pgpDevNull.c
f4d536 445 pgpDevNull.h
055d38 446 pgpJoin.c
063cc5 447 pgpJoin.h
eb242c 448 pgpMemMod.c
e3be6e 449 pgpMemMod.h
f4a876 450 pgpPipeline.h
fe94fa 451 pgpProtoMod.c
4ce5a5 452 pgpRot13Mod.c
708f1d 453 pgpRot13Mod.h
ee5a9d 454 pgpSplit.c
e7bb98 455 pgpSplit.h
bc61c6 456 pgpVMemMod.c
59cd44 457 pgpVMemMod.h
c56222 D libs/pgpcdk/priv/crypto/random/
0fb260 458 Makefile.in
1e5507 459 pgpRandomContext.h
36a49e 460 pgpRandomPool.c
1beedf 461 pgpRandomPoolPriv.h
884474 462 pgpRandomX9_17.c
093395 463 pgpRandomX9_17.h
7f6518 464 pgpRnd.h
42fdeb 465 pgpRndMSDOS.c
7fec06 466 pgpRndMac.c
591b2b 467 pgpRndSeed.c
--dd0b 00081843ea940100002 Page 8 of MANIFEST
935e36 468 pgpRndSeed.h
daa4f9 469 pgpRndUnix.c
3f9e87 470 pgpRndVMS.c
4eccc2 471 pgpRndWin32.c
9bfe0a D libs/pgpcdk/priv/crypto/secshare/
c13083 472 Makefile.in
1589ca 473 pgpShamir.c
84c072 D libs/pgpcdk/priv/debug/
4e3eee 474 Makefile.in
be6120 475 pgpDEBUGStartup.c
45ec63 476 pgpDEBUGStartup.h
974198 D libs/pgpcdk/priv/encrypt/
63bdd0 477 Makefile.in
829e25 478 pgpDecode.c
8b0c5a 479 pgpEncSubr.c
8a3a62 480 pgpEncode.c
55c618 481 pgpEncodePriv.h
c32ee8 482 pgpEvent.c
0439c4 483 pgpEventPriv.h
df6391 D libs/pgpcdk/priv/include/
3b9f5b 484 Makefile.in
798e69 485 pgpAnnotate.h
1029a9 486 pgpConvKey.h
a6dc65 487 pgpKeyFilterPriv.h
3c3cfe 488 pgpKludge.h
134d97 489 pgpMsg.h
25660a 490 pgpPktByte.h
d59043 491 pgpSDKBuildFlags.h
9a1592 492 pgpUI.h
c20d52 493 pgpUsuals.h
55e88f D libs/pgpcdk/priv/include/opaque/
135e0d 494 pgpBigNumOpaqueStructs.h
d9b690 495 pgpKeyDBOpaqueStructs.h
8d3c4e 496 pgpOpaqueStructs.h
659c9d 497 pgpPipelineOpaqueStructs.h
67bc54 498 pgpRingOpaqueStructs.h
ba5841 D libs/pgpcdk/priv/keys/
8fb541 499 Makefile.in
c83dee D libs/pgpcdk/priv/keys/keys/
fcb380 500 Makefile.in
84ddca 501 pgpMemPool.c
73e11c 502 pgpMemPool.h
ed01ba 503 pgpRngMnt.c
aa9595 504 pgpRngMnt.h
7b852d 505 pgpRngPars.c
1eb9fb 506 pgpRngPars.h
3aa338 507 pgpRngPkt.c
93d874 508 pgpRngPkt.h
f52fd0 509 pgpRngPriv.c
b45c30 510 pgpRngPriv.h
4ab8bc 511 pgpRngPub.c
bfdf2a 512 pgpRngPub.h
f6a9cb 513 pgpRngRead.c
68bda4 514 pgpRngRead.h
c76cf9 515 pgpTrstPkt.c
7e502f 516 pgpTrstPkt.h
63db67 517 pgpTrust.c
4f0ae4 518 pgpTrust.h
0bfbc3 D libs/pgpcdk/priv/keys/pubkey/
a36a23 519 Makefile.in
ec7dc4 520 pgpAltRSAGlu.c
86ea26 521 pgpBSRSAGlue.c
e90c0d 522 pgpDSAKey.c
00964f 523 pgpDSAKey.h
094a05 524 pgpESK.c
6ffb3c 525 pgpESK.h
95b6be 526 pgpElGKey.c
732cfc 527 pgpElGKey.h
b52f8b 528 pgpFixedKey.c
a04533 529 pgpFixedKey.h
445840 530 pgpKeyMisc.c
81f4c2 531 pgpKeyMisc.h
--9d20 00085f25df640100002 Page 9 of MANIFEST
9a13e7 532 pgpKeySpec.c
31bf65 533 pgpKeySpec.h
e8ca86 534 pgpMSRSAGlue.c
113e21 535 pgpMSRSAGlue.h
93be38 536 pgpMakeSig.c
ed12ba 537 pgpMakeSig.h
2bac7d 538 pgpPktList.c
0a00ff 539 pgpPktList.h
94e9e9 540 pgpPubKey.c
1873ab 541 pgpPubKey.h
c6d666 542 pgpPublicKey.c
214475 543 pgpRSAGlue.c
fd501a 544 pgpRSAGlue.h
ef9fec 545 pgpRSAKey.c
c5f87a 546 pgpRSAKey.h
bf692f 547 pgpSig.c
3691cb 548 pgpSig.h
1d9115 D libs/pgpcdk/priv/keys/keydb/
aa0ab0 549 Makefile.in
c77c73 550 pgpDearmor.c
a96961 551 pgpEnumeratedSet.c
1bba57 552 pgpFileDB.c
81fbb0 553 pgpFilteredSet.c
e02b0a 554 pgpKDBInt.h
6e8da6 555 pgpKeyDB.h
2c7881 556 pgpKeyFilter.c
a155ba 557 pgpKeyID.c
c29c80 558 pgpKeyIDPriv.h
be3590 559 pgpKeyIter.c
61df82 560 pgpKeyLib.c
036857 561 pgpKeyMan.c
77a264 562 pgpKeySet.c
7b95c1 563 pgpKeyUpd.c
aea030 564 pgpMemDB.c
2600b1 565 pgpUnionDB.c
d9dda9 566 pgpUnionSet.c
e9aa1d 567 pgpX509Keys.c
62eb0f 568 pgpX509Priv.h
d66a79 D libs/pgpcdk/priv/networklib/
f59ae4 569 Makefile.in
ce20ab D libs/pgpcdk/priv/networklib/keyserver/
a652c9 570 CHTTPKeyServer.cpp
0c85e2 571 CHTTPKeyServer.h
f7a695 572 CKeyServer.cpp
8af99c 573 CKeyServer.h
b37bcd 574 CLDAPKeyServer.cpp
6909e6 575 CLDAPKeyServer.h
8d4d2a 576 Makefile.in
f36f09 577 pgpKeyServer.cpp
2e89a4 D libs/pgpcdk/priv/networklib/pgpsockets/
57ac24 578 Makefile.in
933609 D libs/pgpcdk/priv/networklib/pgpsockets/common/
d6d2ce 579 Makefile.in
1c4982 580 pgpSockets.c
76cf97 D libs/pgpcdk/priv/networklib/tls/
809c18 581 Makefile.in
33097b 582 pgpTLS.c
c2f33e 583 pgpTLSPrimes.c
3767bb 584 pgpTLSPrimes.h
669d30 585 pgpTLSPriv.h
f9fcf6 D libs/pgpcdk/priv/regexp/
f9ec9f 586 Makefile.in
fdd871 587 pgpRegExp.c
37a33d 588 pgpRegExp.h
4d2d0a D libs/pgpcdk/priv/utilities/
04737b 589 Makefile.in
3a2331 590 pgpContext.c
428fb3 591 pgpContext.h
ef01d7 592 pgpFeatures.c
664fc9 593 pgpGroups.c
d51f25 594 pgpGroupsPriv.h
85f43c 595 pgpGroupsUtil.c
--a0cc 0009a76e7a640100002 Page 10 of MANIFEST
74377b 596 pgpOptionList.c
58521f 597 pgpOptionListPriv.h
4ecebe 598 pgpOptionMem.c
b5b10f 599 pgpTimeBomb.c
821a3c 600 pgpTimeBomb.h
1f4ba9 601 pgpUtilities.c
7f4683 602 pgpUtilitiesPriv.h
5a189a D libs/pgpcdk/priv/utilities/errors/
8faa9f 603 Makefile.in
77c17d 604 pgpErrors.c
4d12d2 605 pgpErrorsPriv.h
1cbb64 D libs/pgpcdk/priv/utilities/helper/
fa27cc 606 Makefile.in
c90757 607 pgpAnnotate.c
38e4de 608 pgpByteFIFO.c
648e66 609 pgpByteFIFO.h
b17089 610 pgpCharMap.c
f4dc0b 611 pgpCharMap.h
0d0306 612 pgpFIFO.c
5d62fb 613 pgpFIFO.h
8efe6f 614 pgpFile.c
039f92 615 pgpFile.h
ac941f 616 pgpFileFIFO.c
2a56c5 617 pgpFileNames.c
e24238 618 pgpFileNames.h
43aa89 619 pgpFileRef.c
afcd58 620 pgpFileRef.h
fc5964 621 pgpFlexFIFO.c
32dfad 622 pgpMacBinary.c
912b0a 623 pgpMacBinary.h
9987c0 624 pgpMacFile.c
5d2b42 625 pgpMacFile.h
eaf033 626 pgpMacFileMapping.c
6dbdc6 627 pgpMacFileMapping.h
160b67 628 pgpMacUtils.c
c961df 629 pgpMacUtils.h
5f2e81 630 pgpMemFile.c
b593cd 631 pgpMsg.c
759421 632 pgpPassCach.c
c4fe99 633 pgpPassCach.h
ab611d 634 pgpPipeFile.c
f5b3e5 635 pgpStr2Key.c
d58f33 636 pgpStr2Key.h
92afac 637 pgpTimeDate.c
75a983 638 pgpTimeDate.h
f73523 D libs/pgpcdk/priv/utilities/prefs/
f36056 639 Makefile.in
a90914 640 pgpSDKPrefs.c
bf76e4 D libs/pgpcdk/priv/utilities/utils/
977ff2 641 Makefile.in
7131a7 642 pgpConf.c
ba505a 643 pgpConf.h
daef0c 644 pgpDecPipe.c
b8438e 645 pgpDecPipe.h
4cfab2 646 pgpEncPipe.c
e65630 647 pgpEncPipe.h
85ce18 648 pgpEnv.c
507f21 649 pgpEnv.h
9c1166 650 pgpFileType.c
047bde 651 pgpFileType.h
5599a7 652 pgpSigPipe.c
813525 653 pgpSigPipe.h
9b3769 654 pgpSigSpec.c
7d9beb 655 pgpSigSpec.h
3cd89e D libs/pgpcdk/priv/ui/
38475f 656 Makefile.in
9d644b 657 pgpDialogOptions.c
b6e5df 658 pgpDialogs.cpp
7f8c98 659 pgpDialogs.h
79fa71 660 pgpKeyServerDialogCommon.cpp
127f86 661 pgpKeyServerDialogCommon.h
9a0ffc 662 pgpRecipientDialogCommon.cpp
--3c84 001665ee0cc40100002 Page 11 of MANIFEST
093cb4 663 pgpRecipientDialogCommon.h
42fb40 D libs/pgpcdk/pub/
dd62f5 664 Makefile.in
72f123 D libs/pgpcdk/pub/include/
391c1f 665 Makefile.in
ccec04 666 pgpBigNum.h
b019b9 667 pgpCBC.h
28345e 668 pgpCFB.h
f8b2ed 669 pgpEncode.h
de26ab 670 pgpErrors.h
ca9e3c 671 pgpFeatures.h
eea635 672 pgpGroups.h
f14e70 673 pgpHMAC.h
58f563 674 pgpHash.h
d9657d 675 pgpKeyServer.h
0f0006 676 pgpKeys.h
098b56 677 pgpOptionList.h
68cfb3 678 pgpPubTypes.h
d93e55 679 pgpPublicKey.h
333f02 680 pgpRandomPool.h
27a3e8 681 pgpSDKPrefs.h
870d6f 682 pgpSockets.h
4763b2 683 pgpSymmetricCipher.h
f21653 684 pgpTLS.h
aaa7fd 685 pgpUserInterface.h
662063 686 pgpUtilities.h
--c98a 001687614e240100003 Page 1 of sortpages.patch
b62b54 Index: sortpages
e79fb9 ===================================================================
2b1f59 RCS file: /pgpsrc/books/tools/sortpages,v
cb02ff retrieving revision 1.6
dd98ef retrieving revision 1.8
f91743 diff -c -r1.6 -r1.8
e8075e *** sortpages¤  1997/11/14 03:52:55¤1.6
c601b9 --- sortpages¤  1997/12/11 19:20:58¤1.8
d837aa ***************
8a547b *** 1,6 ****
f6fba9 ··#!/usr/bin/perl
3296fb ··#
d8bf27 ! # $Id: sortpages,v 1.6 1997/11/14 03:52:55 mhw Exp $
4896fb ··#
fede7b ··
f9a7f3 ··@fileNameFromNumber = ();
b1c8b6 --- 1,6 ----
fefba9 ··#!/usr/bin/perl
b896fb ··#
bf1d48 ! # $Id: sortpages,v 1.8 1997/12/11 19:20:58 mhw Exp $
5296fb ··#
40de7b ··
c5a7f3 ··@fileNameFromNumber = ();
7137aa ***************
ab4445 *** 15,21 ****
39d827 ··¤ {
9e6e80 ··¤ ¤   $filePos = tell(FILE);
3d063b ··¤ ¤   $_ = <FILE>;
c51386 ! ¤ ¤   if (/^\f?--/)
18f292 ··¤ ¤   {
06d62e ··¤ ¤   ¤   my ($versionHex, $flagsHex, $pageCRCHex, $tabWidthHex,
a68492 ··¤ ¤   ¤   ¤   $productNumberHex, $fileNumberHex, $pageNumber, $name)
087ab6 --- 15,21 ----
8ad827 ··¤ {
b36e80 ··¤ ¤   $filePos = tell(FILE);
5a063b ··¤ ¤   $_ = <FILE>;
084233 ! ¤ ¤   if (/^\f?-\S/)
93f292 ··¤ ¤   {
09d62e ··¤ ¤   ¤   my ($versionHex, $flagsHex, $pageCRCHex, $tabWidthHex,
8d8492 ··¤ ¤   ¤   ¤   $productNumberHex, $fileNumberHex, $pageNumber, $name)
a437aa ***************
b68c26 *** 143,149 ****
5a06ae ··¤ print;
78c97e ··¤ while (<FILE>)
7dd827 ··¤ {
772bd9 ! ¤ ¤   last if /^\f?--/;
822d83 ··¤ ¤   print;
698cf7 ··¤ }
81de7b ··
41187f --- 143,149 ----
3a06ae ··¤ print;
dec97e ··¤ while (<FILE>)
5cd827 ··¤ {
3d7e75 ! ¤ ¤   last if /^\f?-\S/;
f92d83 ··¤ ¤   print;
fb8cf7 ··¤ }
68de7b ··
--57b4 0012716f8c640100004 Page 1 of shasum
63b0b7 #!/usr/bin/perl
10a601 #
93a0d7 # Usage: shasum [ <filename> ... ]
4aa601 #
2c7e50 # $Id: shasum,v 1.3 1997/12/10 21:21:13 mhw Exp $
1da601 #
a6af5a
997c88 use SHA 1.1;
3eaf5a
3a56b4 @fileList = ();
d2af5a
01e66a for $fileName (@ARGV)
cabb36 {
64e103 ¤   if (-d $fileName)
fdc7a1 ¤   {
fb3cc5 ¤   ¤   open(FIND, "find \"$fileName\" -type f -print | sort |") || die($!);
9fbe44 ¤   ¤   while (<FIND>)
a35b34 ¤   ¤   {
bc93a8 ¤   ¤   ¤   chop;
2362e2 ¤   ¤   ¤   push @fileList, $_;
f00fe4 ¤   ¤   }
a0e82a ¤   ¤   close(FIND) || die($!);
379371 ¤   }
fc0e24 ¤   else
c7c7a1 ¤   {
f5ba0a ¤   ¤   push @fileList, $fileName;
e99371 ¤   }
2cefe6 }
d2af5a
245139 $sha = new SHA;
9daf5a
3cd4a3 for $fileName (@fileList)
1ebb36 {
3754e7 ¤   open(FILE, "<$fileName") || die("$fileName: $!");
21b743 ¤   $sha->reset();
45ffd6 ¤   # $sha->addfile(FILE);
968f9e ¤   while (<FILE>)
64c7a1 ¤   {
51195f ¤   ¤   $sha->add($_);
b99371 ¤   }
965c66 ¤   $digest = $sha->hexdigest();
1bf859 ¤   $digest =~ s/ //g;
05300b ¤   print "$digest ·$fileName\n";
12196f ¤   close(FILE) || die($!);
96efe6 }
faaf5a
12a601 #
ddf1a9 # vi: ai ts=4
b8887e # vim: si
27a601 #
--807f 0003701df9640100005 Page 1 of libhashes.asc
2a0fa4 -----BEGIN PGP SIGNED MESSAGE-----
851b04 Hash: SHA1
6caf5a
f917b7 e09d439880278901b4cd3872067d84695f3b6e8a ·MANIFEST
399d6f 2d4edddc52263a8bc69072a3ececcf2f2067e4ed ·PGPChangeHistory.txt
6fa70e a3dc342fe958e745ed6e510413fd2ebbd51f93d8 ·clients/pgp/shared/JPEG/README
d1fa90 729cb01dd026496dd8b3d5ca954176b14ff01722 ·clients/pgp/shared/JPEG/common/cderro¶
c374dc r.h
3acb28 1dc0387d584bf9c39dd28782d130482357933623 ·clients/pgp/shared/JPEG/common/ckconf¶
68cd55 ig.c
4d547a a4272efd1d3bf7c089f3f9fb89626357c6e25e5c ·clients/pgp/shared/JPEG/common/jcapim¶
823436 in.c
a35ab9 2da43bbec11a814cde795fdb75a9cba6b6c31b7b ·clients/pgp/shared/JPEG/common/jcapis¶
ba20ac td.c
ff4e17 3f54a6290b0568024d295a7ae0cb8f8fd1f7f594 ·clients/pgp/shared/JPEG/common/jccoef¶
c46791 ct.c
a68b7d 6050333754a73ac6def0ff8860d80e4f93c01d95 ·clients/pgp/shared/JPEG/common/jccolo¶
1b9074 r.c
23a29d 5ac41fd7b4cf719b26eb9e7e5df0e64072ab387c ·clients/pgp/shared/JPEG/common/jcdctm¶
db011b gr.c
bfb1d8 3e15c63af65a39baea6e59e799d7b0d9e5c1fce8 ·clients/pgp/shared/JPEG/common/jchuff¶
a8f347 .c
b55cc7 ce5d2dd87967db684aeb1502297242a9341e6fc7 ·clients/pgp/shared/JPEG/common/jchuff¶
ea17ef .h
67b924 ec7669a11e9cc6e7bb271837ddaf4fa97d2408d0 ·clients/pgp/shared/JPEG/common/jcinit¶
49f347 .c
55e315 e109512824f1401496caf0f78574d0ca5a0454ad ·clients/pgp/shared/JPEG/common/jcmain¶
816791 ct.c
06c223 79611773da5a34660515815e27156982109d506d ·clients/pgp/shared/JPEG/common/jcmark¶
f41793 er.c
b1c1da 9563a384e860a7e9bf966feb1cce969c223a98af ·clients/pgp/shared/JPEG/common/jcmast¶
bb1793 er.c
c6351a e8238d21e87f7ef17b0d22fb67bd0dd832a5365b ·clients/pgp/shared/JPEG/common/jcomap¶
1493c0 i.c
abef53 76acf3d2cfc7c6f7dc9299b9bdc101d822823548 ·clients/pgp/shared/JPEG/common/jconfi¶
44d92a g.h
d70d14 f6b37ebd16775b2785c5a74c2e179c8c59b829dd ·clients/pgp/shared/JPEG/common/jcpara¶
58e12c m.c
ec079e 72b1944b01ea47cf46354d5b67deb64ce11ecf79 ·clients/pgp/shared/JPEG/common/jcphuf¶
6e2139 f.c
99953d 7f52b0f67f9eebfa3b57347bb09fef16da452d5f ·clients/pgp/shared/JPEG/common/jcprep¶
2e6791 ct.c
762fe8 cc8d11224bd0f32b3b184b5fb26f03882a476452 ·clients/pgp/shared/JPEG/common/jcsamp¶
68d277 le.c
a37954 02d1959682cd2d01e4c2538f44d5e9af9df39104 ·clients/pgp/shared/JPEG/common/jctran¶
9f8ccf s.c
c17c0c a03c948edbb2f03e6661803c10db88e61fb7faec ·clients/pgp/shared/JPEG/common/jdapim¶
183436 in.c
0726c0 cc762411f718e7d7607fb9ea1b844498c2967540 ·clients/pgp/shared/JPEG/common/jdapis¶
ab20ac td.c
cff51d f298be6137c08dd145c3556be8e84805094b64a9 ·clients/pgp/shared/JPEG/common/jdatad¶
ebd3d1 st.c
297926 33c637eec290444aa73ae90395070c864de033b7 ·clients/pgp/shared/JPEG/common/jdatas¶
5f4c15 rc.c
58d9a6 ed0cad139bf5a68cf79127553c0aa4461b50db84 ·clients/pgp/shared/JPEG/common/jdcoef¶
756791 ct.c
758ac9 81297e5984068eda721577bdb119f9d27f36d5c9 ·clients/pgp/shared/JPEG/common/jdcolo¶
b39074 r.c
7af8db 3c3716c51b41da36c50a13826e7d8d7a1f430b9c ·clients/pgp/shared/JPEG/common/jdct.h
4f7efd 4050307344f7bda78f89a1006c9ab4a3deadab62 ·clients/pgp/shared/JPEG/common/jddctm¶
ad011b gr.c
c9378d 88f451a0d1309bd809b74bba81e37c44f2cb4301 ·clients/pgp/shared/JPEG/common/jdhuff¶
bcf347 .c
c0c65e 0ba9ccf7e10074246d78b8447be342a93595e1f0 ·clients/pgp/shared/JPEG/common/jdhuff¶
3117ef .h
0809e8 66ebd84fd9db1ac2c641fb41adc4b7c9f6b946cd ·clients/pgp/shared/JPEG/common/jdinpu¶
45dbee t.c
24338f c2f36ee10d793e1d7600931f34f9d8dbe5f735c6 ·clients/pgp/shared/JPEG/common/jdmain¶
c76791 ct.c
41c882 f017ca7dbef7b237e69562f23baffb6b6743d46c ·clients/pgp/shared/JPEG/common/jdmark¶
5e1793 er.c
377760 3968139baece8edf7df24029a6fd7f0bcf91c66a ·clients/pgp/shared/JPEG/common/jdmast¶
--45dd 0001fc4f0c540100005 Page 2 of libhashes.asc
0c1793 er.c
400fa2 031f37b551c132a5edc2594a07bdfc889f8a69c4 ·clients/pgp/shared/JPEG/common/jdmerg¶
d504f4 e.c
edd242 ae756bf7eb119e01527883bd65417503bfeaa391 ·clients/pgp/shared/JPEG/common/jdphuf¶
682139 f.c
694286 47457796a19b3eb086d53b43374e1f43650f26ed ·clients/pgp/shared/JPEG/common/jdpost¶
916791 ct.c
d9aa41 77cb4e66286b6459e2a0c0744ea5aba52cef4d2d ·clients/pgp/shared/JPEG/common/jdsamp¶
ccd277 le.c
701938 b5907c75ecba1f96a0f10857b95a264de9803d1f ·clients/pgp/shared/JPEG/common/jdtran¶
4c8ccf s.c
60d6d6 d34c3933bbfa069ac32bea371da0b33f6dc27c81 ·clients/pgp/shared/JPEG/common/jerror¶
5ef347 .c
2aa5f2 95286d0e178e782c3844ba23b0a94bafe2d21bde ·clients/pgp/shared/JPEG/common/jerror¶
0717ef .h
137459 0a341b2fe95f937a0263e9b60f0f608005aab15f ·clients/pgp/shared/JPEG/common/jfdctf¶
dc0d6d lt.c
96ca60 8df22470a0a855fa1ce35d79d86e2f06aaeb934f ·clients/pgp/shared/JPEG/common/jfdctf¶
5cd3d1 st.c
fbb095 efc47fd6d78308e84c71d78edcea5a80b305f710 ·clients/pgp/shared/JPEG/common/jfdcti¶
301be5 nt.c
36172d 4aa2f9c8ee5a6ec792cbb2f351a65899c3b17bf9 ·clients/pgp/shared/JPEG/common/jidctf¶
f70d6d lt.c
6fa865 b7e7f8dcea611b276247384edbb4c7cc5048f1fd ·clients/pgp/shared/JPEG/common/jidctf¶
a2d3d1 st.c
2e8615 2535f1ec4b361de03c536719288bf0a817eb35b3 ·clients/pgp/shared/JPEG/common/jidcti¶
f71be5 nt.c
6477f4 0a2a3794073a1bec6ed27037976d71aeac78d147 ·clients/pgp/shared/JPEG/common/jidctr¶
649fa8 ed.c
72fb9a 31ab682733b096b3a98c0a35f9b54a7936e480d5 ·clients/pgp/shared/JPEG/common/jinclu¶
bb6cff de.h
d3c545 b51ed0c5816ad800a5f8b6590ec7f59604f2de7c ·clients/pgp/shared/JPEG/common/jmeman¶
9d9bff si.c
e444c6 492e8df2814f0c5bf437d911ec8822c97769558a ·clients/pgp/shared/JPEG/common/jmemdo¶
198ccf s.c
7467b1 7dc211278799bac19db4cb2052584b6251ffe50d ·clients/pgp/shared/JPEG/common/jmemma¶
cd4f6e c.c
eb9af0 3a06d17cff9b61fc33ecceaf2ca0499ad8a2241a ·clients/pgp/shared/JPEG/common/jmemmg¶
0d9074 r.c
09f5c1 e096b648b468a51227e8f9a161a75b81cbad285d ·clients/pgp/shared/JPEG/common/jmemna¶
7cd933 me.c
70b98e be0a1e39cd9c9a715070e2e677e57178c81bfb48 ·clients/pgp/shared/JPEG/common/jmemno¶
1c3bf4 bs.c
9f455b ed2412e7db0773a42d161122bcd8be0b06d95d2c ·clients/pgp/shared/JPEG/common/jmemsy¶
d66867 s.h
4a73f1 b33bbca1175f2a115061a9931830981da681c6c7 ·clients/pgp/shared/JPEG/common/jmorec¶
554301 fg.h
808ca9 715279c1073e5f88ff120148619ea9df0fd6b73c ·clients/pgp/shared/JPEG/common/jpegin¶
a73f46 t.h
98c4df 225550ea230e457e2185c37d216cfb29d598c8e4 ·clients/pgp/shared/JPEG/common/jpegli¶
ceb77d b.h
71b79e e3d79ce3c8d75ed23aae0e64acde5648e02d104e ·clients/pgp/shared/JPEG/common/jpegtr¶
ea6e16 an.c
257efb fe6e415e102dffb92857bcdd0aa6d232a88be9c9 ·clients/pgp/shared/JPEG/common/jquant¶
85a30e 1.c
bd176d abd65ed7c4efc6f121997e42d396c218c1fcb9a0 ·clients/pgp/shared/JPEG/common/jquant¶
e786c3 2.c
24164d 052847eb62d4e89e3c6c8d7fadf0d8012f692bb4 ·clients/pgp/shared/JPEG/common/jutils¶
53f347 .c
2d4bd9 830b35a5edd90aca39169363077ed1e71b4cb5c2 ·clients/pgp/shared/JPEG/common/jversi¶
e2eb06 on.h
80bd67 20dc64e977615e8ef62b62c98384f60ca71af639 ·clients/pgp/shared/JPEG/common/pgpJPE¶
a3b2d1 G.c
6448a2 2b48e5bd74853d3e95f3425956e15ef349d96fbb ·clients/pgp/shared/JPEG/common/pgpJPE¶
175679 G.h
0209b9 754c35f0b218ca71075ba541ec9aebf5503dfa12 ·clients/pgp/shared/JPEG/common/rdcolm¶
d603f5 ap.c
df7157 766555774536b50ba0ef84ec6dc13ac1b20d7b54 ·clients/pgp/shared/JPEG/common/rdjpgc¶
4d2a63 om.c
b49d7a 2523378f4543a6215fd33abf15d48ecc40a28392 ·clients/pgp/shared/JPEG/common/rdswit¶
c93304 ch.c
1f525a 486a47d75f2057f6bd21fb00b6d87f213513c572 ·clients/pgp/shared/JPEG/common/rdtarg¶
--0eb1 000ca0f814d40100005 Page 3 of libhashes.asc
1f7618 a.c
055e1c f05103d24b8314e0459bc7b953c4f2b4c052a01f ·clients/pgp/shared/JPEG/common/wrjpgc¶
e72a63 om.c
2ffa58 67a9c02524271d692e81598ab10c66d082b3d34e ·clients/pgp/shared/pgpAdminPrefs.h
6bcd43 ffb99fdcb240cc3c07c01d651cb581be90ada49e ·clients/pgp/shared/pgpBuildFlags.h
c435f7 88aa4cb0b8b4d33d46995b511bfbf0e14363ffc4 ·clients/pgp/shared/pgpClientErrors.c
8cd7b8 93f1e466263ade5dd63b244bfdb10170c7513c56 ·clients/pgp/shared/pgpClientErrors.h
4ebdd1 fde34c3db7d661cbd4934eb0458c1053f423f6a5 ·clients/pgp/shared/pgpClientPrefs.h
5036c8 202c2f582faa38108d50f2b85fe4c2009d92b9e0 ·clients/pgp/shared/pgpClientShared.h
3a41fc 1e6244a592ac08603394941c1178a90621007049 ·clients/pgp/shared/pgpDiskWiper.c
dfb2b3 aa2aa25b4610fb87fc2bd00696863b44b2ac2345 ·clients/pgp/shared/pgpDiskWiper.h
2aa414 739d50ec9dadcf45c28fc381868fb00db5d823db ·clients/pgp/shared/pgpKeyServerPrefs.c
56d902 4973c82f1b712d66fb4afcc7e836faaa86ff387d ·clients/pgp/shared/pgpKeyServerPrefs.h
c1e79a 9a3a683a3b2d775fd2156bbeadd259cfbe9643d4 ·clients/pgp/shared/pgpPassBuffer.c
4ef293 e467942042a15ac40717284b74cec794ce36ec7f ·clients/pgp/shared/pgpPassBuffer.h
79011f 61d53df7bb263056fd8f28d2c3dc5e5f18dea1a8 ·clients/pgp/shared/pgpSKEP.c
63cd2d bb2826cd59faf0a54acf90f7ccadf8fa380c56fd ·clients/pgp/shared/pgpSKEP.h
5f33f3 4f2959d7cf111a62452d1d2c425625bfaa43d5c7 ·clients/pgp/shared/pgpShare.c
3a1e1d 61d834d229292e6d7e815dee6940c4ce82704d4b ·clients/pgp/shared/pgpShare.h
b242fd fccbf0ba913bc5a0ec727c4dbe743ded6e178150 ·clients/pgp/shared/pgpShareFile.c
dacd9f 8e2d970bb76265d0bc01a6e8e2ee5b235f7f26a9 ·clients/pgp/shared/pgpShareFile.h
90ef00 fe75b4c83627df80ede8f213bc044d693ad295bd ·clients/pgp/shared/pgpSharePriv.h
0592a2 b7cf9d9ca65f39621119f5ada6413089b134760e ·clients/pgp/shared/pgpVersionHeader.c
7413df d6f64d99ac5c7171411a820e49e9f0d533ac78ba ·clients/pgp/shared/pgpVersionHeader.h
464f42 75f624f864d1387add7db40a2ec80b28aea65e1d ·libs/network/ldaplib/Make-common
2620ed 14614ae4bdd998f021de1d32531a37dc55fe4d94 ·libs/network/ldaplib/Makefile
b542f7 133414762dbcc14cc9257d1c7b6083ace96d5de3 ·libs/network/ldaplib/build/Make-append
02502f c51665565724d5153315fe9821671c186c0e863a ·libs/network/ldaplib/build/Make-templ¶
08d251 ate
1b18bb e19a0db08567023df98cd6a9f541ff16d906f8cf ·libs/network/ldaplib/build/Makefile
108ac8 d7648c011521eff862e7d83d3f38d2716733fef2 ·libs/network/ldaplib/build/PORTS
f01d42 c8ee84d166fc09ac7f0970572c8e69d0ae17ab71 ·libs/network/ldaplib/build/README-unp¶
e08218 roto
b52485 e47556434a7a7ff7907b1e10bfa3f9d63ec6116e ·libs/network/ldaplib/build/db.1.85.pa¶
31c64f tch
745c3c 28041362321a6039bada81353b05cf05abfdeff4 ·libs/network/ldaplib/build/install.sh
b3bcf4 105cdc7b31cfc9766276d26e8595b2ffd8b8c15f ·libs/network/ldaplib/build/mkdep
26b3c0 859863df48465873c5f4fdf94949957eb6a3bc15 ·libs/network/ldaplib/build/uname.sh
5d17f7 7f3a823ef77a1874be9ce0f7f001391ce2894da6 ·libs/network/ldaplib/build/version
d8b196 0f9f01e04202cd50074efb4d606faf9f81156af1 ·libs/network/ldaplib/include/Make-tem¶
60c1d3 plate
348e3a 72c5b33b1eb456def2e100685da1378f74e8df8b ·libs/network/ldaplib/include/Makefile
5d4902 f5a0fa85347440aa984d1b65fe9770d9b52fd65c ·libs/network/ldaplib/include/disptmpl¶
5e17ef .h
00829c ed99f6c8bb2ddb68125aaba6f15afa42bc5c4ccf ·libs/network/ldaplib/include/lber.h
14e2de 8cd82b9c72de1d50a467ef6024e5f1f764ffbf94 ·libs/network/ldaplib/include/ldap.h
833552 5c84a7bfef409fd5d19c44971a4a97b89b6dd91b ·libs/network/ldaplib/include/ldapconf¶
6ce1ca ig-win32.h
26c7b3 cf35ca40aa20d7229b8f3a8b7d06dbb0bfc816f4 ·libs/network/ldaplib/include/ldapconf¶
4b29fd ig.h
df5084 ed27a80fea3ab495d59b742f9caa1c6c289bdb52 ·libs/network/ldaplib/include/ldapconf¶
fecd6c ig.h.edit
51bd47 eff531298a4ff8f6825cb942387748899fe453c4 ·libs/network/ldaplib/include/ldapconf¶
37b9cd ig.h.um
29a6d2 4819759d5214bc7a39e32e7f8ce202a827ac2613 ·libs/network/ldaplib/include/pgpSrvSt¶
3efce7 d.h
00b3e7 5b9b44966fac0da3049fcbe2a6cf5d0d59f83112 ·libs/network/ldaplib/include/portable¶
8717ef .h
211633 cf48b2158852ae3939c8b43cac1c017e775ddad9 ·libs/network/ldaplib/include/proto-lb¶
d7f33b er.h
bd3835 54569bfba0ee8644cf194121f167935a69da7a0a ·libs/network/ldaplib/include/proto-ld¶
f1e75d ap.h
f553b1 6f3a33440d412b2b134ffcb2126394a562810d50 ·libs/network/ldaplib/include/regex.h
ec2371 e8a139ce5951c42e10618a6c45f00520e2092f8f ·libs/network/ldaplib/include/srchpref¶
b817ef .h
e9b070 1b155123d1c4345881e26e0822a9a06443f27824 ·libs/network/ldaplib/include/sysexits¶
f526b3 -compat.h
b007d6 dcb62e5bb0471877c06c1d0bc92b1261d0ae53a4 ·libs/network/ldaplib/liblber/Make-tem¶
d6c1d3 plate
6c345c 9f611fe292a6051d3fc31190aaeed5714b5a7cb2 ·libs/network/ldaplib/liblber/Makefile
3bda1f fb0a2e6a74bac60552a81950c7d191eb793858e2 ·libs/network/ldaplib/liblber/Version.c
ca21dd a6b31f9be40e29686378d14addf723fb078acc67 ·libs/network/ldaplib/liblber/bprint.c
--5c78 00034f532a340100005 Page 4 of libhashes.asc
a810c7 bc7235c053768401f399d837dcb8ced9be02e93d ·libs/network/ldaplib/liblber/decode.c
4dc7b9 a039d125a546630e08745887471ec0a400338cd5 ·libs/network/ldaplib/liblber/dtest.c
3cd981 4207a5ed4fb706b0c597ddf1ddffc2b714848db4 ·libs/network/ldaplib/liblber/encode.c
f9bc13 941b1cce89d155c86b176025c12bf3f377197dd4 ·libs/network/ldaplib/liblber/etest.c
11d5e6 4c4fdca769c91392f37307a3f9b05be26e1a97e2 ·libs/network/ldaplib/liblber/idtest.c
8c8623 9d7c88c5b167e10b0306a9da93723e28733c4100 ·libs/network/ldaplib/liblber/io.c
b7dfae bddea09424e525a2acdcba801f47a928c723eb3c ·libs/network/ldaplib/liblber/pgpSrvMe¶
08e12c m.c
292256 25cdbce7c808d0dd62b0443608f2f406551fdad4 ·libs/network/ldaplib/libldap/Make-tem¶
f0c1d3 plate
8d12a6 e5e2504d8067588f3701c35a43009f2f97537073 ·libs/network/ldaplib/libldap/Makefile
a9ac54 a098c523e9f05ceaae7de756e4e1d4a4259f057c ·libs/network/ldaplib/libldap/Version.c
2ec3d3 956c6a147e540a6e4af9d3b51f8fbdff0e5126ba ·libs/network/ldaplib/libldap/abandon.c
d1295a 83c66befa093263f0180dde273f1dd17403690d6 ·libs/network/ldaplib/libldap/add.c
ce91bb b4bff8a96797aba6644deed88fe1d6138d45827a ·libs/network/ldaplib/libldap/addentry¶
44f347 .c
48fdef cb1e56c55c1a240607571aee6ca2a23f62bfe202 ·libs/network/ldaplib/libldap/bind.c
d09dd2 18217efeda7c2fe170bc70aa254bb0cb32be361b ·libs/network/ldaplib/libldap/cache.c
044ff3 d6e56059853bdc3b30054f82bf9a412616ab7cba ·libs/network/ldaplib/libldap/charset.c
0ebcf1 21d382e25d704cb34030a51ca37c95de1e6ee20c ·libs/network/ldaplib/libldap/cldap.c
fa547f f03f70cb3582a6ba135fd251f73b179a96852e0e ·libs/network/ldaplib/libldap/compare.c
3b3229 9935d4e02093b022c08367a7401556e4c7ce77d7 ·libs/network/ldaplib/libldap/delete.c
0e500c bb677476c90ae796bbcf29b5628463f2d2c12f45 ·libs/network/ldaplib/libldap/disptmpl¶
19f347 .c
2c276e dc2ea2ecd4db278cfdec3a082aff0c9315d481aa ·libs/network/ldaplib/libldap/dsparse.c
9215f8 7ec2e2410369fd717858722b9e7b45605940dfb0 ·libs/network/ldaplib/libldap/error.c
60c846 c62e0e8292e6c9106918c0d9deadc61b1cc96e0a ·libs/network/ldaplib/libldap/free.c
78e9cb 062a37dcea7ccdc22cce9ba6f5169c1c8bb9cfb5 ·libs/network/ldaplib/libldap/friendly¶
78f347 .c
0933e8 45ac53348fce393290ba3ea9d4d0260dc707bb33 ·libs/network/ldaplib/libldap/getattr.c
d53f81 242686f0f0f253a341eb9d15189ff1af3b1f5545 ·libs/network/ldaplib/libldap/getdn.c
6238b1 5384a01703df6b62dd0c60646a9c09e2f4c1987a ·libs/network/ldaplib/libldap/getdxbyn¶
6d5aa9 ame.c
7162a0 4fd745cacf922b8e1deb39c40d9708308ec4d62c ·libs/network/ldaplib/libldap/getentry¶
20f347 .c
a8ebd3 40379529f57c70cbdecf82b351a8680f2f69697e ·libs/network/ldaplib/libldap/getfilte¶
879074 r.c
bdb7b5 d3afbe93f432ec69aa72bc95172de0eaaeeab5a8 ·libs/network/ldaplib/libldap/getopt.c
877353 d4d0659ce19fe5003b8b5e1e3d648ebf67d7d84d ·libs/network/ldaplib/libldap/getvalue¶
fd8ccf s.c
24ea08 1e15314354324de41e9ed802d767fbfbe6c9656b ·libs/network/ldaplib/libldap/kbind.c
eb7961 3b53eb204a0422c5f4f204a97bc35eba73541818 ·libs/network/ldaplib/libldap/ldap-int¶
4017ef .h
d48e4c 1eea49d356a6524bc35330bdbafd1a75c44614a4 ·libs/network/ldaplib/libldap/ldapfilt¶
76c2be er.conf
a0341a f13b654832ffaedc118e59c26ba73372dedace5c ·libs/network/ldaplib/libldap/ldapfrie¶
8f036b ndly
4a6d8f 3f9c79fe3b79d5bbb4f55139e7b01df8af9fd0b0 ·libs/network/ldaplib/libldap/ldapsear¶
5a33db chprefs.conf
48c185 e07edc535228a68b16aa9cf4f37d138052565140 ·libs/network/ldaplib/libldap/ldaptemp¶
7790d9 lates.conf
5df26f 51dff226f3cbce30a64c9af44091e82bce0d568a ·libs/network/ldaplib/libldap/modify.c
1754ee b031a0e014dcf21359380f36b828ef263cbd9018 ·libs/network/ldaplib/libldap/modrdn.c
4a56ba ade9a4cca681c0c945f2236ea874518d731dbee8 ·libs/network/ldaplib/libldap/open.c
5d422d cd4a403eee256e3f069bdd9f41ee21047add6047 ·libs/network/ldaplib/libldap/os-ip.c
4772ed 9ae55b15bbdfea77e5dea745e71c5a805d43ce08 ·libs/network/ldaplib/libldap/regex.c
d624e1 d54dd01c458fbd076c6d97de327dda310ec9e31b ·libs/network/ldaplib/libldap/request.c
ee60bd fb5f0f0c4d6be68b95c14639677bf44f95f8c781 ·libs/network/ldaplib/libldap/result.c
9222e9 867108fba7dacdcb5b49cf8e8537ae79731668f7 ·libs/network/ldaplib/libldap/sbind.c
c48a35 35c8d983a89a43739435a004e22fbedf1e96be39 ·libs/network/ldaplib/libldap/search.c
65daf3 a345678150e644a81f5e49df13e3444b94c29eab ·libs/network/ldaplib/libldap/sort.c
3ba6af cefe94ba22a18a3e7665c39bf6c569a45d5aa519 ·libs/network/ldaplib/libldap/srchpref¶
3cf347 .c
1662b1 05f6081609ea8877a1694513616cf3f649faa9f6 ·libs/network/ldaplib/libldap/test.c
16a9dd bce2404eac97211382945a6fba1d48a8e873182e ·libs/network/ldaplib/libldap/tmplout.c
1162a9 13ad7bf0417363eff4a0f44a9b0bf85ca0a873bb ·libs/network/ldaplib/libldap/tmpltest¶
96f347 .c
615ed1 c1b75ca02a1d870c16444c5dd78b81e988cdb86f ·libs/network/ldaplib/libldap/ufn.c
d46b6b c6543beee3f537b41202ab4b96d4d54f8e34939c ·libs/network/ldaplib/libldap/unbind.c
c44a53 9a4c1ebc6ca66cbeab56978b4e0c3a963028b0f2 ·libs/network/ldaplib/libldap/url.c
905833 bc55f6016f5ef2974d81bd124ce18e2e7f040c9c ·libs/network/ldaplib/pgpsockets/pgpSo¶
349c1f ckets-ip.c
--ee50 000662f4fcf40100005 Page 5 of libhashes.asc
f8f47e 88739ffe20bd5f6200d5113dc8393eb09cd3c92a ·libs/network/ldaplib/pgpsockets/pgpSo¶
044821 cketsLDAP.h
b60eca 19ba406c622f7818bdb7554f9e87821122d099ef ·libs/pfl/Makefile.in
d33f79 8a6cd88d98e9bebcff8c6e352e7bd0e076e65ad9 ·libs/pfl/aclocal.m4
dee11d ba049a987e81fbbe9a3ef6255b2dd46396e88035 ·libs/pfl/common/Makefile.in
cc07d0 039981ce68d4b53196ef1b65ce793a3dea598fc8 ·libs/pfl/common/classes/CComboError.h
6d7e27 0ae2c6f678d2c75679678b1671f8ca9fbf62aebe ·libs/pfl/common/file/Makefile.in
f6f7f9 f432ee7a3fcb2019fda5d6f130ed7457cd3f006c ·libs/pfl/common/file/pgpFileIO.c
e6dbfd e0bc9e6345cf4eaaa5d5f8a6f854568a6313b92a ·libs/pfl/common/file/pgpFileIO.h
c5b144 cd4d1d9c85958ff7e679dcff6858e50da2783ad5 ·libs/pfl/common/file/pgpFileIOPriv.h
4ca0ea 27bdccd2d55ba50a98834306de946dbb2020b14c ·libs/pfl/common/file/pgpFileSpec.c
f36402 344729b9357697885a119113916e03690d50c495 ·libs/pfl/common/file/pgpFileSpec.h
f686d9 fd06d0bcc99c9c43e0f96720264c1199d32e6466 ·libs/pfl/common/file/pgpFileSpecMac.c
172587 c6b24023cb10d31f6aa72a3d1609a5f8e3feb839 ·libs/pfl/common/file/pgpFileSpecMac.h
b16ee1 629f29160c6ff386fd193cfbc0fc6fcdf08ecfa4 ·libs/pfl/common/file/pgpFileSpecMacPr¶
34f6e7 iv.h
7a20f5 026d3ccb85f51840707fbe070cee1ed38ee7a657 ·libs/pfl/common/file/pgpFileSpecPriv.h
084917 31d40e44fb3d613680d2818dce121310416d967a ·libs/pfl/common/file/pgpFileSpecStd.c
318025 139c6965904bf33498ffb44f9644566d211ef457 ·libs/pfl/common/file/pgpFileSpecStd.h
1e0c23 5c01919ae1ec0f3eaac30b1fecc4d49a2a59233e ·libs/pfl/common/file/pgpFileSpecStdPr¶
ddf6e7 iv.h
494299 71ee4278d3cef0a937bcb9687d0009b12929be6b ·libs/pfl/common/file/pgpFileSpecVTBL.c
9482e3 0175ecc31af52230daa645d7d8a733cb9e4e1ccd ·libs/pfl/common/file/pgpFileSpecVTBL.h
f6cf15 ca92b7630f947b9259e52b1e2d2817cec5444b65 ·libs/pfl/common/file/pgpFileSpecWin32¶
8bf347 .c
86c7bf 2689f97450a73954e93df565a53be8aa106a250d ·libs/pfl/common/file/pgpFileUtilities¶
d8f347 .c
3be4e7 b72ac740747a71591debe4fd3eabe25d352c1123 ·libs/pfl/common/file/pgpFileUtilities¶
dc17ef .h
e6ed3c ea058aa98cff3c9d039ae130451f2ab9a144c4b1 ·libs/pfl/common/file/pgpIO.c
4ecc6a e30319619c97ec456fb8a26af7da3cad841afd44 ·libs/pfl/common/file/pgpIO.h
8e13bf c766574b43745e50cc516c4060fc1f4d07b3dceb ·libs/pfl/common/file/pgpIOPriv.h
fb5673 f1045827b2ced9d76e7001bf4bdf324c4d32c698 ·libs/pfl/common/file/pgpIOSample.c
3404ce ed689dba2077d2ad5e6c2645bc0d57e9005bd303 ·libs/pfl/common/file/pgpIOUtilities.c
66f4d4 894bd2446a68a32986e3f77feecce8d8adf2db80 ·libs/pfl/common/file/pgpIOUtilities.h
9da0ff 4f54e10bf2e9643cbbf3a4a0c27a79dff12a31fd ·libs/pfl/common/file/pgpLineEndIO.c
0d063e fb078283b4a635ae848a04127140645303c2999f ·libs/pfl/common/file/pgpLineEndIO.h
66188c 0fa13a426dbe1d5db91a3b7a7d1e0133e15af042 ·libs/pfl/common/file/pgpLineEndIOPriv¶
8317ef .h
ec784c 5cfca419e40bcd7c4a91f9f8dc1465f0c1f43b47 ·libs/pfl/common/file/pgpMemoryIO.c
c29ceb 98b6fa63a27e46b81ae75151d15051bf374df7a9 ·libs/pfl/common/file/pgpMemoryIO.h
a40eaf c3b19d75dd78e3518a242cc8d1975bc3d7d529ff ·libs/pfl/common/file/pgpMemoryIOPriv.h
0da062 cba0a7f30e651beeeec0c4cbaf991967019dae48 ·libs/pfl/common/file/pgpProxyIO.c
e3e32a 003cedbcd283e756b6a4dfe00a835e3487ad3ba2 ·libs/pfl/common/file/pgpProxyIO.h
6fbe37 2fda62616013b49878e74ebe00c9ffdc249747a8 ·libs/pfl/common/file/pgpProxyIOPriv.h
cd3a97 b558e3d2b431bea9f366c060ac55160e1af83e76 ·libs/pfl/common/file/pgpStdFileIO.c
72e473 2e718d845909f2ba96735817e72955f6a7edca30 ·libs/pfl/common/file/pgpStdFileIO.h
20cd16 3ac009e7efc6daf64118eb74e5f7a7935a6629db ·libs/pfl/common/file/pgpStdFileIOPriv¶
dc17ef .h
6cf012 8bad777b081849b775e96de6105e93b7d693b053 ·libs/pfl/common/lthread/Makefile.in
044a90 829e1ea2d8f5d72df115beec734ba77f7b27eada ·libs/pfl/common/lthread/pgpCond.c
798a84 61e9edb505cd6676aa0fdac53fda0ea4b2e31703 ·libs/pfl/common/lthread/pgpMutex.c
d34a06 e4b975304bbdd32db8cf61245042f85c9788028b ·libs/pfl/common/lthread/pgpSemaphore.c
dac4c1 30e08c0c3b9da0220b62912ede5b2e677e90ca14 ·libs/pfl/common/lthread/pgpThreads.c
3ad95b 858e7e21050debf3d894b018fe4c45d98079b67b ·libs/pfl/common/lthread/pgpThreads.h
6ea2e5 3f57b4ce8adf5aa5dc0f183e51102f047aa55a8f ·libs/pfl/common/pflTypes.h
012987 b1cc397ea7aee4a7db80757e4815c001ed515bf0 ·libs/pfl/common/pgpBase.h
8ea065 a9c364363c36d97fe666fbb13fd01ad7f13e1dab ·libs/pfl/common/pgpBinaryTree.c
3cbf8c 6631c1ef283b444f8a3daf1d4d0d4f022d0bf512 ·libs/pfl/common/pgpBinaryTree.h
f21837 ea804fa68494ec4f22edc9ad296aae032a0e5709 ·libs/pfl/common/pgpDebug.c
4014a1 78bc290e3e2220b892d71668a48a31681456aea0 ·libs/pfl/common/pgpDebug.h
472af4 72e3e57a1453c8f5bff357ff39048bd4904d4710 ·libs/pfl/common/pgpException.h
e581b1 18c667018124c92e25ba0110a4000d7c0114b796 ·libs/pfl/common/pgpLeaks.c
2abee5 212f2b1bb346fa901acba24f09e91affb6200d0f ·libs/pfl/common/pgpLeaks.h
b16558 79268320cd1e803274c1be7104e049776b0ffdac ·libs/pfl/common/pgpMem.c
42408c 9d7c26cfd529a4c0e8e73a1a5b386bcf2ef796bd ·libs/pfl/common/pgpMem.h
1e3d5b c178daa394fc086a50b0902797913379ef9a39bd ·libs/pfl/common/pgpMemoryMgr.c
a1bda6 4dbb304dcb74634eb933bc1ad71e6f07598c557b ·libs/pfl/common/pgpMemoryMgr.h
e3dbac cc913496ae3786882434bf8fd14de13a4e9f77a7 ·libs/pfl/common/pgpMemoryMgrMac.c
ff8e4f 53ca6f72b330a99fb5f49acb273dc007165713f2 ·libs/pfl/common/pgpMemoryMgrPriv.h
5e3eed bfcb4cb101c4ae1c7a31a8ee03917d254f7bc49c ·libs/pfl/common/pgpMemoryMgrStd.c
66a78f 7a095a9fed019c2a97ba9c1be844d77ab992bfb9 ·libs/pfl/common/pgpMemoryMgrWin32.c
--3efd 000111b96d240100005 Page 6 of libhashes.asc
4953a0 4efd4245f8585d6065f3dc012ee878a5fe27bdca ·libs/pfl/common/pgpPFLErrors.h
b0a43e d9a1547bac9c131702861a421b408904382b363c ·libs/pfl/common/pgpRMWOLock.c
2e8d91 a15867144fccffe2949df05e0d33cbbb855d570d ·libs/pfl/common/pgpRMWOLock.h
70ebfc 16bb63e3a7579644223545a1010acaa23d35cc3e ·libs/pfl/common/pgpTemplate.c
3c5f1e 0153032e1c8a27abf6f46e3abef174b50ae99faf ·libs/pfl/common/pgpTemplate.h
16d764 675e6f4ace62ace4424d08340c436fb6e36e5575 ·libs/pfl/common/pgpTypes.h
69b439 9d10035bfa7962fed6324aba414ef26cf9a5d578 ·libs/pfl/common/prefs/Makefile.in
a44744 13b393712280b8f938b3cc1c32a546d849d8a8a1 ·libs/pfl/common/prefs/pflPrefTypes.c
c69ca3 d1cb250b657c71f4c91e008c315b99d02963db6f ·libs/pfl/common/prefs/pflPrefTypes.h
528fe2 1bdf62d1219117ce43b82e806661529834475cb2 ·libs/pfl/common/prefs/pflPrefs.c
ed9e0c a3da9a5a439afce4621437a9dd098dcc8c738450 ·libs/pfl/common/prefs/pflPrefs.h
48357a 303ed7b56f3d45ad3df3990398f7ab6604068358 ·libs/pfl/common/sorting/pgpHeapSort.h
c7215f d67cd6a0ed9ddf2a30427669550e6c94ae3bdce5 ·libs/pfl/common/sorting/pgpInsertionS¶
898605 ort.h
454233 9430fe1912bcdcd2e4c10cad2e4387f428a6818f ·libs/pfl/common/util/Makefile.in
db03d3 76e5b87122d614629232fb09dfbf166a5082d31a ·libs/pfl/common/util/pgpBitUtils.c
56fb61 cea14e4766716f027734c61e715bf56077ed5e8e ·libs/pfl/common/util/pgpBitUtils.h
208bba 1ec84632981c87747f61156e20241a31936ac797 ·libs/pfl/common/util/pgpEndianConvers¶
e3ad6c ion.c
1ac39a 125f711991f447c470b8ded04f3c5eafd4a82b59 ·libs/pfl/common/util/pgpEndianConvers¶
a249c4 ion.h
c1940f 9f62b8d0c6e8867db82ff253be5c3e8ef447935a ·libs/pfl/common/util/pgpHex.c
457f84 a1fe5bc2ef748ad9ea4f5ddf8c99678c6daa20f7 ·libs/pfl/common/util/pgpHex.h
1f1196 232e00804a6a52b54e7077f7bf88b9d447de751b ·libs/pfl/common/util/pgpPassphraseUti¶
eb5a4c ls.c
3069d8 8b0906436732d4377068266db8627e1f5a331d3a ·libs/pfl/common/util/pgpPassphraseUti¶
c3bee4 ls.h
03c36a f0b7cbdf04ff13747aa6434c622aad9a383b336b ·libs/pfl/common/util/pgpStrings.c
d9ef4f 4c7108d6de02461b2fc8a033cdfda7f922be319f ·libs/pfl/common/util/pgpStrings.h
51f104 a314893742c42b301c6324af3c0d02f4c975135a ·libs/pfl/common/util/pgpWordWrap.c
467ddf 77c428785192b7b05772fdbb2d8cf7fd10c9c32a ·libs/pfl/common/util/pgpWordWrap.h
5a1741 617f4105676b21e8d757af6a90fbbf87be825b1a ·libs/pfl/configure.in
d0374d 1983ad6df159d9e883248a10b34ef70855bf5f3a ·libs/pgpcdk/Makefile.in
d979d4 d5a67da1731351a6535ba0255393fbdfa2427838 ·libs/pgpcdk/SDKChangeHistory
6b3a30 7d894a2e769806f51586924492f1ea1bfc6a1c0e ·libs/pgpcdk/aclocal.m4
83a7ae df20658e618a3c6f6a390b7e6be04f035eac91ac ·libs/pgpcdk/configure.in
a452e2 ab56f7e36bd46ba0694faa8130dca51934bd6752 ·libs/pgpcdk/priv/Makefile.in
9fb0db fed55786baa6a3e35b893aeb014371d436a4a126 ·libs/pgpcdk/priv/clientlib/Makefile.in
5c71b9 a22fb7013d29ba8e048cad86254d7549429c683c ·libs/pgpcdk/priv/clientlib/pgpClientE¶
aedd88 ncode.c
173389 ba6326078150ec229f2771425f26ecedbddb2b1e ·libs/pgpcdk/priv/clientlib/pgpClientK¶
2084e0 eyDB.c
21b894 6a4be0047f25f6e387edef39391a5326ad27b74d ·libs/pgpcdk/priv/crypto/Makefile.in
53621d 6c51076e295306faf2299cff2b1990366511c73e ·libs/pgpcdk/priv/crypto/bignum/Makefi¶
5ad9ff le.in
48dd0e c0af9da759840d236c301e9335d6fec890ae9a0c ·libs/pgpcdk/priv/crypto/bignum/bn.c
27708a ecd71f37a06810b23c6fd62356af99b7c7af7ec0 ·libs/pgpcdk/priv/crypto/bignum/bn.h
4b1dfc 4558eb7fab4a668b3be815267d40bf069da5cf87 ·libs/pgpcdk/priv/crypto/bignum/bn00.c
5e501f d142b1e7b29862d886382d3e00aa817ad2977122 ·libs/pgpcdk/priv/crypto/bignum/bn16.c
3f3c45 85e97562f9211bf26163359b0c7ecb09a36b07ce ·libs/pgpcdk/priv/crypto/bignum/bn16.h
a23170 283aa14f9910f818c0e3a5e50d6b15c55fe98665 ·libs/pgpcdk/priv/crypto/bignum/bn32.c
26b34c 1674d2b1b67cfd35e44b6106e2d982f9e5079fbc ·libs/pgpcdk/priv/crypto/bignum/bn32.h
618588 70eedba2e2c1e3af645fd038d9863db4fdcf71e7 ·libs/pgpcdk/priv/crypto/bignum/bn64.c
c09893 077e4f43859a27a7f6cce02a6b6f03147fee98a4 ·libs/pgpcdk/priv/crypto/bignum/bn64.h
b44e3d eac927e3f3b5b3c7058462d4c16f58f1650dbdf9 ·libs/pgpcdk/priv/crypto/bignum/bn6800¶
51bfb5 0.c
930d51 5edb511befe4b1fe9abd2d74089097949d0e106d ·libs/pgpcdk/priv/crypto/bignum/bn8086¶
fcf347 .c
100c24 c0c1d7b9fd1a8d0003f5862dc592ebcf1143d3c4 ·libs/pgpcdk/priv/crypto/bignum/bndsap¶
b65d06 rime.c
a0cd1c 0ad7834135d71af951ebb71f775db9f14e1b8d2b ·libs/pgpcdk/priv/crypto/bignum/bndsap¶
9eb9ae rime.h
be2e72 bcab4402974da2b30b8ef55bfee2e1a65f66dbc1 ·libs/pgpcdk/priv/crypto/bignum/bngerm¶
84b7ac ain.c
fb9ab7 65f7932252d1ae4f580eacdb264755872183afc9 ·libs/pgpcdk/priv/crypto/bignum/bngerm¶
ba5304 ain.h
46a788 54c28b6f847183b8c9d715074d846be7126437dc ·libs/pgpcdk/priv/crypto/bignum/bni.h
833472 ef96f6429a03d9a64dd9bf3d0d0116b47761119a ·libs/pgpcdk/priv/crypto/bignum/bni00.c
a39d31 f110230d304efd605755bec5433c6fcca8a958e6 ·libs/pgpcdk/priv/crypto/bignum/bni16.c
1f8cd8 fa6a5919206206e9154557e53cf5ab9c5f1e1c2c ·libs/pgpcdk/priv/crypto/bignum/bni16.h
44b012 744676abd0485eca9e657da80747d8809232dc6a ·libs/pgpcdk/priv/crypto/bignum/bni32.c
11ed14 5a022e3f28cd5f7a7657e1583f7204b2212de465 ·libs/pgpcdk/priv/crypto/bignum/bni32.h
--d0dc 0005088a0a240100005 Page 7 of libhashes.asc
5909a5 eca9632b8500e0b5125f98f41d6568a70917a621 ·libs/pgpcdk/priv/crypto/bignum/bni64.c
8c29cc 6c3d1e6a4d2bf46a4d65701ddd87577ec6663c7e ·libs/pgpcdk/priv/crypto/bignum/bni64.h
133a91 bc657d44a2fb789f701f41fe6c3df4673588ba8a ·libs/pgpcdk/priv/crypto/bignum/bni680¶
306b64 00.c
fc809b 569244f3847a13d2389f19504e7b32f969031896 ·libs/pgpcdk/priv/crypto/bignum/bni680¶
558fcc 00.h
1ee80a a843abbf2bd482a8362f61ab16ac34dcf9ef2067 ·libs/pgpcdk/priv/crypto/bignum/bni680¶
947dec 20.c
6f2e82 bc9eb345fc16793880483ee1aef800a684127219 ·libs/pgpcdk/priv/crypto/bignum/bni680¶
c39944 20.h
25a6d3 2aefc97a47506ba18b6013a65519852393d0f08b ·libs/pgpcdk/priv/crypto/bignum/bni803¶
0f4631 86.asm
ffdcb6 28447bc4f022135ff700c95bb0abec3672389a94 ·libs/pgpcdk/priv/crypto/bignum/bni803¶
249e76 86.h
76c41f 1db16c17ac746a6932b00b1301777b5554e18ee5 ·libs/pgpcdk/priv/crypto/bignum/bni803¶
5eef4f 86.s
ab8483 862675378a08a85da2571bd701c388ff673eeb6b ·libs/pgpcdk/priv/crypto/bignum/bni803¶
b7c8f7 86_aout.s
4d29c4 5a86c8b1c046c8faa37de2b7196eab0be3f5a632 ·libs/pgpcdk/priv/crypto/bignum/bni803¶
af46af 86c.c
157729 2cfa66ef5d53abf55295c10031e23b4f35b411ff ·libs/pgpcdk/priv/crypto/bignum/bni803¶
d6a207 86c.h
1c881f 496144bd980030fde5ef4d22fdf532e5fd551b15 ·libs/pgpcdk/priv/crypto/bignum/bni808¶
714e97 6.asm
7fa7d7 e7c6ea16d4e44c09c999c5f10d04ff4207f87256 ·libs/pgpcdk/priv/crypto/bignum/bni808¶
281087 6.h
bc3fe8 04b9b989e7f5018fb686ccbbf8a69764db05229f ·libs/pgpcdk/priv/crypto/bignum/bni960¶
643450 jx.s
a8c6e2 0333c6264a60a8f2b3851cddcc4ae84aa857df8c ·libs/pgpcdk/priv/crypto/bignum/bnialp¶
9c6923 ha.h
42e391 6279066ca0024e74e882ec9e9b6ca726171dc811 ·libs/pgpcdk/priv/crypto/bignum/bnialp¶
bf181a ha.s
0fb2ee 94cb83306e640f433fa451f854356c85db70915f ·libs/pgpcdk/priv/crypto/bignum/bnimem¶
63f347 .c
2fa97c d78756bcfcf6af8b74b049b694df9822bfaf95b4 ·libs/pgpcdk/priv/crypto/bignum/bnimem¶
6417ef .h
1b6737 fec2f21230eb8a40dfdf7b2e8669a9af662d8e38 ·libs/pgpcdk/priv/crypto/bignum/bninit¶
9b2bba 16.c
05a558 7ce6686ad46c99726d96a4e97992144b319098df ·libs/pgpcdk/priv/crypto/bignum/bninit¶
624fde 32.c
744a54 9ef05f8f63d48685caba3605efd18e4e7584a834 ·libs/pgpcdk/priv/crypto/bignum/bninit¶
322210 64.c
0828ba e05fcf33d8c7b0e11e96d9175d5e0384016babd7 ·libs/pgpcdk/priv/crypto/bignum/bnippc¶
90f347 .c
bd5907 cd0c819edaaceb72bebaf44e33054714b52db231 ·libs/pgpcdk/priv/crypto/bignum/bnippc¶
2117ef .h
e14433 563e2b3ca740634b3b79a7e8779640a0ac82cd9f ·libs/pgpcdk/priv/crypto/bignum/bnispa¶
e0a8bd rc.h
a6ae7f a7499d66740a68659ce7873c13b2dc2495ac47ab ·libs/pgpcdk/priv/crypto/bignum/bnispa¶
95d984 rc.s
d7b6d8 affc3e045d9d0ff93022f47ca687c4c8ce111a1d ·libs/pgpcdk/priv/crypto/bignum/bnjaco¶
8424fb bi.c
daf440 6cc28f107c1e554b43fa7e226693566a01aae14f ·libs/pgpcdk/priv/crypto/bignum/bnjaco¶
30c053 bi.h
f40d42 94e083e2c5f441be175d95567d37066e44401461 ·libs/pgpcdk/priv/crypto/bignum/bnklud¶
637133 ge.h
8557d6 e66d0612725a48b25d462b944ca0c68a5ee4049c ·libs/pgpcdk/priv/crypto/bignum/bnlega¶
b5fd97 l.c
5336a9 4a6b1375b94944b195e0b59951eb7168bab2b6f2 ·libs/pgpcdk/priv/crypto/bignum/bnlega¶
41193f l.h
d3362b adc180f1623c7a189316ce984ffb2009a3998637 ·libs/pgpcdk/priv/crypto/bignum/bnppca¶
da0dbb sm.h
97aec4 0b82356c8b639d3f4a9fc8a1a7f7e7d390309714 ·libs/pgpcdk/priv/crypto/bignum/bnprim¶
0204f4 e.c
f4a28b ac8c72d60328d5095c791ca24383f53c96a8f9f9 ·libs/pgpcdk/priv/crypto/bignum/bnprim¶
a1e05c e.h
d03a48 a0807b72ed17edf5317c8cc73f57569242eea066 ·libs/pgpcdk/priv/crypto/bignum/bnprin¶
28dbee t.c
05f165 20f944f951fc238666f95108223ae89b9a2ae5b1 ·libs/pgpcdk/priv/crypto/bignum/bnprin¶
1e3f46 t.h
0a4a2c 2078a85d6acfa9c19b634b8f60ac35a2a7476c9a ·libs/pgpcdk/priv/crypto/bignum/bnsiev¶
5004f4 e.c
--76b9 00051b18b1240100005 Page 8 of libhashes.asc
1e9aea c0982e6f759752d2c85187a65dc810f9492f7ef0 ·libs/pgpcdk/priv/crypto/bignum/bnsiev¶
cee05c e.h
e6ebd2 b3efe98cbfccdd79efb022f52cc9b743c3b6e3a3 ·libs/pgpcdk/priv/crypto/bignum/bnsize¶
598fcc 00.h
99dcf4 ed8f41f123b2e1bc9a22ce656a5e05fad796c790 ·libs/pgpcdk/priv/crypto/bignum/lbn00.c
7816e6 a71b49bcd0b70450d5d2ccf22a202e8bdd06978a ·libs/pgpcdk/priv/crypto/bignum/pgpBig¶
3fe9f8 Num.c
44e748 905e5845fd9b08e85b9f58a7aeed7138a365f6c6 ·libs/pgpcdk/priv/crypto/cipher/Makefi¶
54d9ff le.in
62aee3 e89f451953e7c1aa5dd76529d08dd90561ca07f5 ·libs/pgpcdk/priv/crypto/cipher/pgpCAS¶
018990 T5.c
05ded0 0961b1839d11529cfb9bc1582fbd03e416bef81b ·libs/pgpcdk/priv/crypto/cipher/pgpCAS¶
4f6d38 T5.h
f1f871 f4a5574ac92c0067f5825a8b52bc912c618a7be9 ·libs/pgpcdk/priv/crypto/cipher/pgpCAS¶
f6184b TBox5.h
10b9ce 6efca83750cd29aed3ccfbe4cf53a9bde10a2088 ·libs/pgpcdk/priv/crypto/cipher/pgpCBC¶
f4f347 .c
cbba59 29476bc8ffd396d17da905f2f51eaf86e4ceebe2 ·libs/pgpcdk/priv/crypto/cipher/pgpCBC¶
94497f Priv.h
d7ebb0 6d1560c7021330d871dcaa4d3964d1866555093e ·libs/pgpcdk/priv/crypto/cipher/pgpCFB¶
88f347 .c
f417ad 951e286c1bb1820ef6dbf1da21bd10d44e115f0f ·libs/pgpcdk/priv/crypto/cipher/pgpCFB¶
c9497f Priv.h
ff4bb7 93e01f198f0b9bea09f6d2611d286b531f04efd1 ·libs/pgpcdk/priv/crypto/cipher/pgpDES¶
969a78 3.c
475135 b6b8bd2cc23e7ad3fcd7236bc54c8c5fb21fb575 ·libs/pgpcdk/priv/crypto/cipher/pgpDES¶
387ed0 3.h
aebbf1 01f7f5419907af3f24b387f01cf84137fb8d4742 ·libs/pgpcdk/priv/crypto/cipher/pgpDES¶
f4785d 3_68K.c
e2e9ee 7f2174b580c087e40606d43d7819b3992a25e22e ·libs/pgpcdk/priv/crypto/cipher/pgpIDE¶
62f94b A.c
c94ab6 6964d42065d418a37d4e40644327c53423c15296 ·libs/pgpcdk/priv/crypto/cipher/pgpIDE¶
f01de3 A.h
76a3ea d5689feb5ef5cfedc213b069c68a00fe27b9542c ·libs/pgpcdk/priv/crypto/cipher/pgpSym¶
51dd6c metricCipher.c
220589 79c8b453ceeb0545bd1b556af2d87d5328196e15 ·libs/pgpcdk/priv/crypto/cipher/pgpSym¶
951519 metricCipherPriv.h
5c1c99 71b1ee6113031e1f8da1074f8aa0ba6b0bcb4798 ·libs/pgpcdk/priv/crypto/compress/Make¶
6df2f3 file.in
b2076b bffe52255a23810c6c07f8115f77087697f49c86 ·libs/pgpcdk/priv/crypto/compress/pgpC¶
68117a ompress.h
0b91a0 804854a41af672c9f63148f001097b48f637ec08 ·libs/pgpcdk/priv/crypto/compress/pgpZ¶
5fbad8 Inflate.c
06a31a aa5dc34f7ea040f21cd7fca964fcc204d68ccefa ·libs/pgpcdk/priv/crypto/compress/pgpZ¶
265e70 Inflate.h
ca2148 de21c77b90871eba4aefc1ac64aedd2666844895 ·libs/pgpcdk/priv/crypto/hash/Makefile¶
2de85d .in
6e8657 b126f48bc1e116c741f4c63741467851658dc320 ·libs/pgpcdk/priv/crypto/hash/pgpHMAC.c
6fd7b8 dae13ce4503e036d5d71e225cd59002c2371bf51 ·libs/pgpcdk/priv/crypto/hash/pgpHash.c
0a59a9 33d51262e6ead9f4a6e5a3cf883b8de5afa74d38 ·libs/pgpcdk/priv/crypto/hash/pgpHashP¶
3b3bb0 riv.h
c67ecd f428051edcee2cccfdf70f82b94507323c8e16ec ·libs/pgpcdk/priv/crypto/hash/pgpMD2.c
469993 1c3c95fca7fb52b148adebda42bf47ec44034c59 ·libs/pgpcdk/priv/crypto/hash/pgpMD2.h
6b4c6e 0d4e98fd2b62a14cc8351c47ee712d922b6137b5 ·libs/pgpcdk/priv/crypto/hash/pgpMD5.c
d7142d 396ae0ba0f83b009aad1fc93d4f1b22050c76923 ·libs/pgpcdk/priv/crypto/hash/pgpMD5.h
5bf0fb 2713e3798aedeef2bfdc6051e4df0702b28b75c4 ·libs/pgpcdk/priv/crypto/hash/pgpRIPEM¶
603b77 D160.c
d1e05d fa1abbb7d6fbb534838bfcf35d42262c72a06b97 ·libs/pgpcdk/priv/crypto/hash/pgpRIPEM¶
9fdfdf D160.h
654b20 46cbafc8ad7f1ef46d724cb3d4b1f40ba08031a1 ·libs/pgpcdk/priv/crypto/hash/pgpSHA.c
021cd7 9ebebd9003d05f152bc5aa48f438d29231d8364e ·libs/pgpcdk/priv/crypto/hash/pgpSHA.h
a9f79b c515294756bdd57ac90ece331d1603a2006c6f8b ·libs/pgpcdk/priv/crypto/pipe/Makefile¶
fde85d .in
6ff373 d91220d6733232f119c93785d587f51a2667ab63 ·libs/pgpcdk/priv/crypto/pipe/crypt/Ma¶
7f713f kefile.in
45a018 934cb3f04bec614c643a795d3f7ee2385b2789d4 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
8030f4 pCiphrMod.c
490445 c73eed5db0c115b1b60b698edb8f604005c6aa33 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
11d45c pCiphrMod.h
b5b611 4cf0de7beca1e8c1ec4ef96135b4d4203da87b28 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
8ab229 pConvMod.c
51878a 161b058de6be6dd158a4253f0ae134312ebdec77 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
--2415 00007239ab840100005 Page 9 of libhashes.asc
215681 pConvMod.h
420425 7cc0d1ceb2a69fff4b0f78b1fd896f6e2393e341 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
f4cbc7 pMakePKE.c
8425af 7640e9261920248f96f9546e36aef29662501f58 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
2d2f6f pMakePKE.h
9b94e4 c64c202f0285fc8fac977a340fe958ef2b9e99e0 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
eb275d pPKEMod.c
dc6556 fb28ff3d8e3cb130e52dbd595a4377044f5e54e8 ·libs/pgpcdk/priv/crypto/pipe/crypt/pg¶
0ec3f5 pPKEMod.h
98115f 716b06403ae086a416cb5a7227ad55262d4bcdef ·libs/pgpcdk/priv/crypto/pipe/file/Mak¶
5991b1 efile.in
7a17d7 f59f8aa2f833016c1a97551d75787497bd3b416e ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
f52bec Armor.c
2913c5 21bc7867bd37b1761c56a256b38c14a4bcbf5cb1 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
c1cf44 Armor.h
f6e63b b4d71bf251e2c439e6b11e805b32aa8370e8ab68 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
af5028 ArmrFil.c
062bda 8e3eeab82e40ca7a7d66e59cffe1a12631defccf ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
26b480 ArmrFil.h
587ba3 8174a719a0ad71fef7a3367f99a6f1e658ba7d96 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
e1ad7b CRC.c
99c237 2fe97f4393b82db8557c278dbd105b6ec11dcc1c ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
b249d3 CRC.h
ceca8d 524f17806d72d081f089235a050e9b5f26f01d0e ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
e2c28f FileMod.c
dc4f68 718540013714e09345dcc64cee1fad99ad8b8a14 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
7b2627 FileMod.h
f35ce6 7b3e98bac0db8ef33533a57005fea0ba8cf68017 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
c06617 Header.c
a6d1b8 f1a02743535e8a049a604f374c98ab56508d6ec4 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
7a82bf Header.h
7d0783 ec5304fc6c16b8fca9084d3ed1ec6ebbe1da4e53 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
dc6268 PrsAsc.c
4bdd36 a1cc1bec922d2ee31a8f93d3cb73f9d9e7d7a1dd ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
1486c0 PrsAsc.h
3be083 254ab8ee70ab585498a4bc397a326bbad6f3ae3f ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
4061ea Radix64.c
69c307 b993707cc5927503126c30fdf423342aaeab4995 ·libs/pgpcdk/priv/crypto/pipe/file/pgp¶
8e8542 Radix64.h
5b6c56 92dd67aeb6e67086aa1c96d7a97ece2b1de7e483 ·libs/pgpcdk/priv/crypto/pipe/parser/M¶
a70b21 akefile.in
0bd197 36bd10f00a7352839d731cf6eb40f9383488e2dc ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
85bd87 gpPrsBin.c
01db97 3b055e86204accb6618ec454825a75a5db2428ea ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
23592f gpPrsBin.h
948ec3 89fe7561dca2bbf48360118002f8d69b9d11130e ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
6383fa gpReadAnn.c
701bb7 fc77907e110cf7034c37242c32ccff41f0863791 ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
916752 gpReadAnn.h
c9386f ff2562ad5097509263139bb00d37e978f0c13987 ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
ef8c06 gpVerifyRa.c
d40fdd ff8c4abafe0fc4bbb9ffe1a94cf2d0748911f506 ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
cc68ae gpVerifyRa.h
4c6a13 f41724bb62f7f5584592bc195600f869b718dd8f ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
fca1c1 gpVrfySig.c
07edf5 c05d830ec2e9f2269f3afe8a897220b5e03f59aa ·libs/pgpcdk/priv/crypto/pipe/parser/p¶
ea4569 gpVrfySig.h
d72a3a 5936c7ed04fa8e9859c5dfa6cf658e19fa73f2f1 ·libs/pgpcdk/priv/crypto/pipe/sig/Make¶
53f2f3 file.in
53627b 64cd7339dc408d5e8dea9bf4295d1fdac6c4eb95 ·libs/pgpcdk/priv/crypto/pipe/sig/pgpH¶
bfc069 ashMod.c
28b1fd f8d09239b3e7dcaa358e2bdc53c2330e58d48581 ·libs/pgpcdk/priv/crypto/pipe/sig/pgpH¶
3224c1 ashMod.h
9b5710 ffe96d7b251c84a535d4aa77aca7100ff73b3fec ·libs/pgpcdk/priv/crypto/pipe/sig/pgpS¶
7ff891 igMod.c
f40470 dec75cd03adf320aa78fcfc38037929a9047dffa ·libs/pgpcdk/priv/crypto/pipe/sig/pgpS¶
271c39 igMod.h
12814d f5ec888ed2c4f3bd2ffa2949dea4db6afad67108 ·libs/pgpcdk/priv/crypto/pipe/text/Mak¶
0b91b1 efile.in
61c80b a77bc7a1de64f7da2c3be633df633d10d32335e7 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
9b3efe CompMod.c
078d28 1b0807a7686353116d660894d9afd0ade69e29a4 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
--3064 0001475394f40100005 Page 10 of libhashes.asc
32da56 CompMod.h
89665e 311efbbb621c6720437ea5ee34bfbe5698d23fb5 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
cd85a0 DefMod.c
066287 fc2fc3bbeeb94ffc95240552a8dfb997023cedf5 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
bc6108 DefMod.h
c4a8ca b6ce7acde19e2b80a11100f76c8f2eccd8a97c7b ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
1a2f1e InfMod.c
7d5f92 84fb0e59f4b272fa7641840ac003de56f73a84dc ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
53cbb6 InfMod.h
f94739 d052ba82c168c7f3c1b567ef50b51c0e417af30e ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
1bfb15 Literal.c
b8b547 99c768795aaaae7fccd29f6713c3060e46932985 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
971fbd Literal.h
24283d 80181722245ea47e75e22611815e744d4b466da2 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
ccbca7 TextFilt.c
46c958 4509aced1fd0666eb30f39a4dc76d06502d4aa37 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
5e580f TextFilt.h
800e3f 2ea223373f78799c5e1cf810278af656e13f2bfb ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
43fe09 ZBits.c
0be597 63f78751ebdac23279d5216fbecc51650ec6aa67 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
b74d4f ZDeflate.c
e8bcc0 21f5f90d4a30d5d7f0a8d8215f48f39c9e37a4c9 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
3ff69e ZMatch.asm
8f3193 4453028be37c84ed12d6f1e455386ee8e49c5ec5 ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
452a88 ZTailor.h
0f9540 d2e9d0653067c2951c10dd3dfe8235fe12be6e4b ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
ae6b79 ZTrees.c
8f9d67 05e559dae5874b04960a74f6e79065588905971b ·libs/pgpcdk/priv/crypto/pipe/text/pgp¶
69d412 Zip.h
13d0a9 38c4318a6680d52b06ef2ca08fc2372adafa8b88 ·libs/pgpcdk/priv/crypto/pipe/utils/Ma¶
26713f kefile.in
87b12a bab408e77b2bb54c6b022dd5850761aa6a513630 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
e8b570 pAddHdr.c
fad165 ac5363620786b4cc4d038396c2b52c09f5557dde ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
cc51d8 pAddHdr.h
4ea36c 7bc9a5d10fd7431d94f361f202a4d8afe6250067 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
cc555b pBufMod.c
741400 1af507e5794990c671f07103c8ebefec1203350f ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
d3b1f3 pBufMod.h
4ccb0b 5bb23deb79286be58a3a68ea72d94194203d0706 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
6cc0a8 pCopyMod.c
6b8fa2 404b1d6ce6aeffe109a9b79c2c4223dbc34248d0 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
ba2400 pCopyMod.h
fbfef3 c657f09e4ce1c1e7ec7cbbf816a48cf9425333d3 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
e9f212 pDevNull.c
89bcc2 8ecfd1ba0e1709b3ff9ed4aefa5783b9f55f6a13 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
5416ba pDevNull.h
18cb10 3d8dc8e043dc8ada1a8b8a39b0ee8d54244d1fd1 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
632826 pJoin.c
6ab4c6 50703c81dadd75c55d1c8586a47e5deb5ede2e74 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
7dcc8e pJoin.h
60ea11 f1b19d3b15538a9dc3bb351e727e0040e6419e81 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
f3ee89 pMemMod.c
a02905 8c32080e15de4a9621a12d3228b2ece4c35ef9e2 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
080a21 pMemMod.h
54bf5c 99d8e674f15ad9af0c69bebe95302eeb6cb3521a ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
5950ac pPipeline.h
8968b6 dd6f4674b54cc4fe5a32dbefbbe6adc49386d7d3 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
57e230 pProtoMod.c
8e935d 8269eb3ec6635d546b6e5dadfdcb0e2a751f0949 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
23094e pRot13Mod.c
9e5369 7af9c5a77cdc99bba91a2fdd1e534716377327f1 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
b3ede6 pRot13Mod.h
c1369a d754d66f7c989699b8204b2487c36e533398dafb ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
cbd6a7 pSplit.c
d159b5 562b90dcc17553e8c8abe360252d52cb2afe529a ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
d8320f pSplit.h
a51fc0 6f453283621f3e8c72cc450a75b736c16982a7c0 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
baf424 pVMemMod.c
02242e 8515835008c647f897ca47d1ad491c7bf4af7973 ·libs/pgpcdk/priv/crypto/pipe/utils/pg¶
e9108c pVMemMod.h
14f05b cd2fe5d17da2650d00e6faf57608d970c0454796 ·libs/pgpcdk/priv/crypto/random/Makefi¶
--3c48 0001f50abb340100005 Page 11 of libhashes.asc
32d9ff le.in
0c7226 b48df7cbc99c56f77827543df77bc30648864114 ·libs/pgpcdk/priv/crypto/random/pgpRan¶
1d70f5 domContext.h
858002 c0979baa3336fad1419329cac081d9a5b3668a42 ·libs/pgpcdk/priv/crypto/random/pgpRan¶
695dd3 domPool.c
35f668 83d23587c8ab29a1ff987e31650c9b23bc92d234 ·libs/pgpcdk/priv/crypto/random/pgpRan¶
74ca90 domPoolPriv.h
3cacdf 36ea2727e7a77a15cb929208734ba5a03ce91ea1 ·libs/pgpcdk/priv/crypto/random/pgpRan¶
43f3ef domX9_17.c
69a75d 7387af8bb594dee3e2addc0b56da3e53494f07dc ·libs/pgpcdk/priv/crypto/random/pgpRan¶
f21747 domX9_17.h
d9c9a6 0d37e8c9005e97f862e6da6180225712459a3182 ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
6c17ef .h
85d3a2 6ddeddb6065838c78a588d231e3ae1f9ad1a8563 ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
0ebfb2 MSDOS.c
2ee11f e7e01c052d307a976f76f47bd20383b3ce73f331 ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
8fd297 Mac.c
c84c6c 86d2c730efec508adf7c92fee06a0da78283e8b1 ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
4cd63f Seed.c
4fa7a7 13d13f638aab7a37f94ec568a0a05e3f3b8a29c9 ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
3c3297 Seed.h
8e3671 ba24cd36787e03a2d069f5addfa0291836bc7c7a ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
048072 Unix.c
102605 d0596dc178e6e605b629f297ec0548ab369527ec ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
57e651 VMS.c
344635 60c8a1a57510408e9eaa24d6f286005799ded080 ·libs/pgpcdk/priv/crypto/random/pgpRnd¶
3db6f6 Win32.c
67b8de 64b8eff58d58c3ccef8bd2a0e6f06ba8257c58d3 ·libs/pgpcdk/priv/crypto/secshare/Make¶
3af2f3 file.in
640267 dbe75d608c3bb4a772cc1fdf424677e7e8f4d164 ·libs/pgpcdk/priv/crypto/secshare/pgpS¶
e91720 hamir.c
7a36fc 4c4446a719bdc34779b790b09c333603533bba6b ·libs/pgpcdk/priv/debug/Makefile.in
847ab9 fd24fb8c3a3f6371c4f0edf295ff75b9cbce0fa9 ·libs/pgpcdk/priv/debug/pgpDEBUGStartu¶
e5a902 p.c
54f3ae 2863275c73e82b97be8ea71ffb704a6645f3be7a ·libs/pgpcdk/priv/debug/pgpDEBUGStartu¶
a84daa p.h
4294bd 770d5c93a8a73ee5e56d0dd766823b20eae91a9b ·libs/pgpcdk/priv/encrypt/Makefile.in
1104d8 8174b883c4d6e166e91ad3717b38d3f1b02ef8f2 ·libs/pgpcdk/priv/encrypt/pgpDecode.c
1aa93b 1849199f32ab010b46751f13ba53f4e1f2906f0b ·libs/pgpcdk/priv/encrypt/pgpEncSubr.c
238b43 0e10e0dd1cc4b9a5252f774117533f8edebb1bdf ·libs/pgpcdk/priv/encrypt/pgpEncode.c
782039 26cc85aadc266faf9ab959595b74a1badf296d47 ·libs/pgpcdk/priv/encrypt/pgpEncodePri¶
fb0630 v.h
655a9f d6adc4dbff54f512607a796e77b2645348edae63 ·libs/pgpcdk/priv/encrypt/pgpEvent.c
5edc3d 80449d9f3d199eae1a85e263bc8c484b73152d5f ·libs/pgpcdk/priv/encrypt/pgpEventPriv¶
9d17ef .h
005108 a30b90533757851d538494825157cd4199e2c4eb ·libs/pgpcdk/priv/include/Makefile.in
432d97 07f3d31c0205329e0a187a375432ece16831432f ·libs/pgpcdk/priv/include/opaque/pgpBi¶
4b1b4d gNumOpaqueStructs.h
374856 935c03e6a7e25dcd0c4b27cc82b41765058cfc8c ·libs/pgpcdk/priv/include/opaque/pgpKe¶
172c57 yDBOpaqueStructs.h
344b19 70d8604f170918d8f4bdebc6c6932780174fb6bc ·libs/pgpcdk/priv/include/opaque/pgpOp¶
52430c aqueStructs.h
785a23 eddb48a41fbc5f1f19a22e86ab1740b28ab4d4b2 ·libs/pgpcdk/priv/include/opaque/pgpPi¶
01e68d pelineOpaqueStructs.h
d25fc6 9707d90b2e02be7457187823e58acd43fc0c2170 ·libs/pgpcdk/priv/include/opaque/pgpRi¶
f3db52 ngOpaqueStructs.h
4d6e60 3c803920d72010664771d725affe64022e06c119 ·libs/pgpcdk/priv/include/pgpAnnotate.h
b60b10 3415ce0029d541aee2417ce35acddaa647b26284 ·libs/pgpcdk/priv/include/pgpConvKey.h
d43c15 98f974e07dc81be28490ddf023995bf9f916fe44 ·libs/pgpcdk/priv/include/pgpKeyFilter¶
c0497f Priv.h
0aca3b 552204930bd344792eced4b112b7e86752f801c4 ·libs/pgpcdk/priv/include/pgpKludge.h
1cd85d b75ec4358623c519376383e60b66a973e660cd2d ·libs/pgpcdk/priv/include/pgpMsg.h
373dc4 ffe5df4db2faf64a4b66df184065cbb9c1ce400a ·libs/pgpcdk/priv/include/pgpPktByte.h
524ea1 1d35dde05e74d896eb09291a50e4998c1a6f60fb ·libs/pgpcdk/priv/include/pgpSDKBuildF¶
7a6f8d lags.h
24d921 40e2871cd72869d5245ce9d9c309bc9b1b8093a5 ·libs/pgpcdk/priv/include/pgpUI.h
9b7f28 0aa19fbf606f50a86922ae5aaaabfbddd4a9aad4 ·libs/pgpcdk/priv/include/pgpUsuals.h
7aa736 fc567bd3dd02c24b8ecdfb28c880778755af55ce ·libs/pgpcdk/priv/keys/Makefile.in
061f71 ce0936e87a3a904f36aa7da6036cfebf254d873c ·libs/pgpcdk/priv/keys/keydb/Makefile.¶
3bc94c in
e8e4e9 2cad0138d85f3c81fe1350571ef87b1189fec63a ·libs/pgpcdk/priv/keys/keydb/pgpDearmo¶
1f9074 r.c
--19c7 0003952208740100005 Page 12 of libhashes.asc
4dd6c2 acf8eab7483d5afa4926cd3d0be9f062329e3525 ·libs/pgpcdk/priv/keys/keydb/pgpEnumer¶
bc9f44 atedSet.c
c66fd2 b3b7c4594bd14721705b2274e2d8ac12ef5d3879 ·libs/pgpcdk/priv/keys/keydb/pgpFileDB¶
2bf347 .c
a3ba93 7a3bb237c5b64d97ecaa0d7fa83607175440707b ·libs/pgpcdk/priv/keys/keydb/pgpFilter¶
dc9f86 edSet.c
922862 92dde8d0178a698bbea0bfcee2c55ea05dc25ae6 ·libs/pgpcdk/priv/keys/keydb/pgpKDBInt¶
c417ef .h
5648d2 6949af8f6654856a46b5890c6c4fcc5fe934f666 ·libs/pgpcdk/priv/keys/keydb/pgpKeyDB.h
9ea349 1002612cd3bbce02ef0b4bbcae935b75798fac01 ·libs/pgpcdk/priv/keys/keydb/pgpKeyFil¶
1ac23e ter.c
858731 70d06289f214e5bad0e2090413427d692c14646d ·libs/pgpcdk/priv/keys/keydb/pgpKeyID.c
6a6879 2ca243c2961b86e502285d6354e3f445cd49a6dd ·libs/pgpcdk/priv/keys/keydb/pgpKeyIDP¶
1b3bb0 riv.h
a6ba29 b37cf7127628ac1828158c2dfb7cfba28bd0ae05 ·libs/pgpcdk/priv/keys/keydb/pgpKeyIte¶
e99074 r.c
5edd49 da6fe8076d60e57fab059f37480111a0240cd681 ·libs/pgpcdk/priv/keys/keydb/pgpKeyLib¶
3af347 .c
f70ffd cc09c181586159ad0f78e8f8f574ea248cd8ea93 ·libs/pgpcdk/priv/keys/keydb/pgpKeyMan¶
7bf347 .c
629652 7648b2b1e5170079df16d66ddab103b8a90574ae ·libs/pgpcdk/priv/keys/keydb/pgpKeySet¶
f1f347 .c
2ed7ff 022ad880b4c99975f0d7f95fbad0b8df4f7284fa ·libs/pgpcdk/priv/keys/keydb/pgpKeyUpd¶
adf347 .c
08ab93 086efc58bb05be635f4d185c88982eaeee720c49 ·libs/pgpcdk/priv/keys/keydb/pgpMemDB.c
12d828 374a6c7dd0f97bb67c5cc801a590e1702411fc61 ·libs/pgpcdk/priv/keys/keydb/pgpUnionD¶
f5dc86 B.c
35cd0d 99a88680dda7a3da352b8d1b7fbe777b5209f582 ·libs/pgpcdk/priv/keys/keydb/pgpUnionS¶
5b5c09 et.c
d64921 1bd5104983f4cef34985092455084b7c62ea6631 ·libs/pgpcdk/priv/keys/keydb/pgpX509Ke¶
9fc858 ys.c
3a0e7f 42721cde66e48a45eba01a60887f52f459c66273 ·libs/pgpcdk/priv/keys/keydb/pgpX509Pr¶
83f6e7 iv.h
bb684b d452a6cb1e4845137359dae7c3d21b0933a5d181 ·libs/pgpcdk/priv/keys/keys/Makefile.in
772420 b1b2b325cf2aa01b2f7db644f475064910cb2659 ·libs/pgpcdk/priv/keys/keys/pgpMemPool¶
edf347 .c
afb698 4fcb42b154da8b4db265a011d80eb656a257512c ·libs/pgpcdk/priv/keys/keys/pgpMemPool¶
1517ef .h
e327e8 0ae894fe66966863cba072d508b18a495121495a ·libs/pgpcdk/priv/keys/keys/pgpRngMnt.c
325d56 aea545b18d9f98e8dacab2ee1e107a1b4c65d86a ·libs/pgpcdk/priv/keys/keys/pgpRngMnt.h
12073d 857a6cbd877094b3fca68fac4bbef3264fd826d9 ·libs/pgpcdk/priv/keys/keys/pgpRngPars¶
00f347 .c
8fe868 bb2fe749e2a9fb2b3e86eba55bf52fce48701593 ·libs/pgpcdk/priv/keys/keys/pgpRngPars¶
d517ef .h
2eebc1 ab2a6a8b2d1f23d908676d728f4d3e057e2afb04 ·libs/pgpcdk/priv/keys/keys/pgpRngPkt.c
53bcbb c6bca1c9e393044c0603c76f93c2f7bfced5494c ·libs/pgpcdk/priv/keys/keys/pgpRngPkt.h
14de31 0efd5d75f7a637ff81f83ed6977306af7fe15bf3 ·libs/pgpcdk/priv/keys/keys/pgpRngPriv¶
b4f347 .c
92eae3 da112aa36ab0f22f034428ef2394d76d34e1a489 ·libs/pgpcdk/priv/keys/keys/pgpRngPriv¶
3217ef .h
764cc3 2d98e93a2ace0857da013927801a840f2634e609 ·libs/pgpcdk/priv/keys/keys/pgpRngPub.c
3eb339 2e1cb76acdec4b87ee92585439d58b0417945fdc ·libs/pgpcdk/priv/keys/keys/pgpRngPub.h
0782b7 69e0b78b4ea25e933cadf0ae5a78e3da767a384d ·libs/pgpcdk/priv/keys/keys/pgpRngRead¶
12f347 .c
fcb991 b6965432d5f73dff4a74ca5d403841ff91ea45d8 ·libs/pgpcdk/priv/keys/keys/pgpRngRead¶
6017ef .h
ac4424 f7c156acd5577263d8337e07014904040cfea485 ·libs/pgpcdk/priv/keys/keys/pgpTrstPkt¶
9bf347 .c
6bc3ff 2f01f26392058bbc1e2a02673affa9f5499ba7ab ·libs/pgpcdk/priv/keys/keys/pgpTrstPkt¶
8b17ef .h
4bd527 1bf0ec15f8af024eec83f53323daf07c0708ad7a ·libs/pgpcdk/priv/keys/keys/pgpTrust.c
579a4a e1fb4b5344f5f67bd7feefd1a61398f07a77a691 ·libs/pgpcdk/priv/keys/keys/pgpTrust.h
df046e 1f6d100c512be2a0c52950d54de605790e660d81 ·libs/pgpcdk/priv/keys/pubkey/Makefile¶
c2e85d .in
e3e5a9 aca223c7b43d6f4488d1fa82537528f570169222 ·libs/pgpcdk/priv/keys/pubkey/pgpAltRS¶
6e5705 AGlu.c
683078 d7ff90bdc8ec427f8468894ef2b030fd19a528d4 ·libs/pgpcdk/priv/keys/pubkey/pgpBSRSA¶
2c8108 Glue.c
7ea1e4 845f0469ec8d60339e0e7decd415e216d5ae59e0 ·libs/pgpcdk/priv/keys/pubkey/pgpDSAKe¶
075061 y.c
d03212 f3e528e378d7db6489a0b124aea3886a78d9c403 ·libs/pgpcdk/priv/keys/pubkey/pgpDSAKe¶
39b4c9 y.h
--3256 00027ce921f40100005 Page 13 of libhashes.asc
071434 c1b4a891131ad16ee9afccd501ebba526a7022a7 ·libs/pgpcdk/priv/keys/pubkey/pgpESK.c
fbec1c f56c4ec4f294795345dcee2db88a9b65a4f6b26e ·libs/pgpcdk/priv/keys/pubkey/pgpESK.h
555559 3030989d69578427982241a71ab87b0c3a76361d ·libs/pgpcdk/priv/keys/pubkey/pgpElGKe¶
675061 y.c
eea05d e24f979c8991cebe74533e579f0add223cea6ec0 ·libs/pgpcdk/priv/keys/pubkey/pgpElGKe¶
89b4c9 y.h
9ad024 2cccec6011e0602a3e821252fc7b0781069d5d34 ·libs/pgpcdk/priv/keys/pubkey/pgpFixed¶
40f872 Key.c
faf66e e971103a6dc865362ac66143b94badf8909cd683 ·libs/pgpcdk/priv/keys/pubkey/pgpFixed¶
d61cda Key.h
581eb4 f67dbee1d5aac90a7e4515119af52f5a61cbd0d5 ·libs/pgpcdk/priv/keys/pubkey/pgpKeyMi¶
8f4751 sc.c
f523ed 861aa3acf8eb615b0dcd880c669ffb22cc0f76a8 ·libs/pgpcdk/priv/keys/pubkey/pgpKeyMi¶
8aa3f9 sc.h
111ab9 6b311944353f37729d7b815b50dc0d5baad4fd91 ·libs/pgpcdk/priv/keys/pubkey/pgpKeySp¶
c6c889 ec.c
5eeca7 af40aabfc7aa57de08fdfabb7cf6f7c468c6ce3c ·libs/pgpcdk/priv/keys/pubkey/pgpKeySp¶
a22c21 ec.h
a7f37b bfcb6efea44e17db0708836948e34c8f531d916a ·libs/pgpcdk/priv/keys/pubkey/pgpMSRSA¶
2d8108 Glue.c
aac3f8 452d6a50b18f9334603cfcee3dd26bd5f6d6ed42 ·libs/pgpcdk/priv/keys/pubkey/pgpMSRSA¶
9065a0 Glue.h
78940a f28f9551d4a1545098d1684b737affa04a68a9c9 ·libs/pgpcdk/priv/keys/pubkey/pgpMakeS¶
b7cd55 ig.c
512744 7bd7d2eab0bb406ed38fadff209098f19f857dce ·libs/pgpcdk/priv/keys/pubkey/pgpMakeS¶
0029fd ig.h
182d01 c742b5645b4c2ce4283d0c7757c3376f36a22bc0 ·libs/pgpcdk/priv/keys/pubkey/pgpPktLi¶
93d3d1 st.c
a4d34b 79de72c6a71eac6a66d39998fb71fd779f3e2bd3 ·libs/pgpcdk/priv/keys/pubkey/pgpPktLi¶
9b3779 st.h
b03c9c c26c0cb2255a8eecd56d373112cae9a922e96d8d ·libs/pgpcdk/priv/keys/pubkey/pgpPubKe¶
9b5061 y.c
15bde1 0455525c336d7f2eb813ffddf78c8158e4ad7ccf ·libs/pgpcdk/priv/keys/pubkey/pgpPubKe¶
0ab4c9 y.h
abacd6 158d2efbea9f7854154b8fa097abe6a909c5b5b5 ·libs/pgpcdk/priv/keys/pubkey/pgpPubli¶
15f499 cKey.c
a04f12 8791d0c01ba5b195dcf3a12c8caa263dbf6f562d ·libs/pgpcdk/priv/keys/pubkey/pgpRSAGl¶
ae3753 ue.c
194c30 14b88f21b5ab840be8e4ef508d4e27a82121333d ·libs/pgpcdk/priv/keys/pubkey/pgpRSAGl¶
ecd3fb ue.h
2b69eb 7a88ac61520ceeb95f9d0311c74c56614f3caf22 ·libs/pgpcdk/priv/keys/pubkey/pgpRSAKe¶
2e5061 y.c
238724 b692bbb3f6e51142ec58314a41f8d3af1d4c304f ·libs/pgpcdk/priv/keys/pubkey/pgpRSAKe¶
f1b4c9 y.h
079d53 f76f8a09fe3f5d7b62dff6ce5888926fdee84a3f ·libs/pgpcdk/priv/keys/pubkey/pgpSig.c
21724e 126ad1635e24f2783e616c35fbfecdd07b8338d8 ·libs/pgpcdk/priv/keys/pubkey/pgpSig.h
91d2c4 98c50a5c3811ebd9fb6629ac83b69912f4201fff ·libs/pgpcdk/priv/networklib/Makefile.¶
eec94c in
39feea 542742bc9ad77a314412364cb185282c2de5fbec ·libs/pgpcdk/priv/networklib/keyserver¶
6df443 /CHTTPKeyServer.cpp
5b8c7b 6ca35e04260369e522a404e29ba3324eff64fd50 ·libs/pgpcdk/priv/networklib/keyserver¶
606cf7 /CHTTPKeyServer.h
01befd 878756667a4a111e7c1566f064ad884b9509b633 ·libs/pgpcdk/priv/networklib/keyserver¶
0ade6c /CKeyServer.cpp
786d6f 2c96afd1cc108a455e98f8dd5a689c10698b0ad6 ·libs/pgpcdk/priv/networklib/keyserver¶
0740e1 /CKeyServer.h
9392df b2d4bc20764418794dcdd0031247c209839164ec ·libs/pgpcdk/priv/networklib/keyserver¶
b200f7 /CLDAPKeyServer.cpp
6c264e 8543f67cc3eaa893053462e04960d361e1de9942 ·libs/pgpcdk/priv/networklib/keyserver¶
73bdf5 /CLDAPKeyServer.h
5cc590 ca336873de0d5b95f4c65d12829fa88e0673f60c ·libs/pgpcdk/priv/networklib/keyserver¶
5d5605 /Makefile.in
20c3f9 5e808a81264b2c8b03043da8d777ed4fb4ce5859 ·libs/pgpcdk/priv/networklib/keyserver¶
e3f599 /pgpKeyServer.cpp
c865f7 903f3b51d3947e7a84ce50fed750a9c241722ba6 ·libs/pgpcdk/priv/networklib/pgpsocket¶
82e53c s/Makefile.in
65a7f2 37aec1c40aa6c84b9800081f741445171c9f97d7 ·libs/pgpcdk/priv/networklib/pgpsocket¶
5edcc9 s/common/Makefile.in
97d065 bbbc548eb6de33782a75da9c2a78d16604d33cdb ·libs/pgpcdk/priv/networklib/pgpsocket¶
16c6ec s/common/pgpSockets.c
797c11 24fc953b81a8098c309c3202bc9f8af7114b74c8 ·libs/pgpcdk/priv/networklib/tls/Makef¶
273c43 ile.in
--d8e5 000e255bb3c40100005 Page 14 of libhashes.asc
a85d27 56a40a79f46df6e92c454f4bf050c6d031ed29a5 ·libs/pgpcdk/priv/networklib/tls/pgpTL¶
27039c S.c
b0d54e a7a35c4b9d1c9ec9eb2481a71dcb15007628d831 ·libs/pgpcdk/priv/networklib/tls/pgpTL¶
46315b SPrimes.c
52b9b3 359e290ab19b434e46429ce022f3c3450a89fd54 ·libs/pgpcdk/priv/networklib/tls/pgpTL¶
abd5f3 SPrimes.h
84a19f f853ee9c42c53063aa04bff534781ec6616af994 ·libs/pgpcdk/priv/networklib/tls/pgpTL¶
a8fd26 SPriv.h
fb3634 a2c9e905b8b7203e495584954e7e4c27f7b804d0 ·libs/pgpcdk/priv/regexp/Makefile.in
5883f3 f4647170147503cafb7c492ae65b397be2ae545c ·libs/pgpcdk/priv/regexp/pgpRegExp.c
4461fa 271f2242aa9840f546cee5ae0201ffb41aaa858f ·libs/pgpcdk/priv/regexp/pgpRegExp.h
6c8b12 95d24b941f8c467ef5a539ca202deb98f5d09f73 ·libs/pgpcdk/priv/ui/Makefile.in
a45d29 7f66750d2d2e7940879d7aaa3ea6de8165aa1c9f ·libs/pgpcdk/priv/ui/pgpDialogOptions.c
16096b 532340d10b8e619c42ce6b680ae8fce04794d871 ·libs/pgpcdk/priv/ui/pgpDialogs.cpp
84ff65 fc28bb1bd5f88ddc0db2cf016abc4316f9b66905 ·libs/pgpcdk/priv/ui/pgpDialogs.h
748bc5 e85f98da4f8f08ccf47c5b7b1ca9f2db9e4ad8c8 ·libs/pgpcdk/priv/ui/pgpKeyServerDialo¶
8b899c gCommon.cpp
5df6a3 beeedb45b66c437e494f6c6aeff5b0b55d1d3460 ·libs/pgpcdk/priv/ui/pgpKeyServerDialo¶
6bb84e gCommon.h
c5e2c8 49cfb2835121d4e0d6901e42b1ecb82854abfd20 ·libs/pgpcdk/priv/ui/pgpRecipientDialo¶
bb899c gCommon.cpp
6358f6 851c45e1220de0d141115cd64bf198d83fbc7fb4 ·libs/pgpcdk/priv/ui/pgpRecipientDialo¶
b1b84e gCommon.h
4e5c66 f5e456e7cb7038edcf11110e078a959e295ef1b7 ·libs/pgpcdk/priv/utilities/Makefile.in
7b4f2e f538754ac6c522ca8408530a5818d1b4ccc68a06 ·libs/pgpcdk/priv/utilities/errors/Mak¶
ee91b1 efile.in
88ff7f 43b5f7ff20d2b6bc9ed2144f292006e008376517 ·libs/pgpcdk/priv/utilities/errors/pgp¶
c30416 Errors.c
8e8a20 8518059c32213eb2c850cd0c12b80e36fb825766 ·libs/pgpcdk/priv/utilities/errors/pgp¶
5880e3 ErrorsPriv.h
4661b4 1d9e1a07317bfc459ad0694232673b7a7ba25657 ·libs/pgpcdk/priv/utilities/helper/Mak¶
a791b1 efile.in
7a0dd9 ffec47b584689712ad2069a8d2d0b6bf306bc9df ·libs/pgpcdk/priv/utilities/helper/pgp¶
388d2a Annotate.c
cad3a1 26f7d9fc351c583f84df0ed17d493ba030634683 ·libs/pgpcdk/priv/utilities/helper/pgp¶
cd8c24 ByteFIFO.c
8dfa62 16e2dfb918cd8fd6c7d4b29b3fad95b530bad793 ·libs/pgpcdk/priv/utilities/helper/pgp¶
6b688c ByteFIFO.h
4b1fb6 af98353dd96dffe0894908d3196ca6fddcca79ce ·libs/pgpcdk/priv/utilities/helper/pgp¶
a00b30 CharMap.c
8ec224 51dd61d7355095204e9e29faca2bae70ebd482f6 ·libs/pgpcdk/priv/utilities/helper/pgp¶
31ef98 CharMap.h
ffc679 1a93d902940920abfb58f571a1d62879e77b885d ·libs/pgpcdk/priv/utilities/helper/pgp¶
4e15da FIFO.c
d9546c 8b9fa6a903ecf78153e599426082e4f91c687323 ·libs/pgpcdk/priv/utilities/helper/pgp¶
74f172 FIFO.h
032fb6 f3850831ae4f11675778d5a90e11aa80f6c42c34 ·libs/pgpcdk/priv/utilities/helper/pgp¶
68ef7e File.c
2ae4d3 6e6ccb1b38cfb8ebb0bbd84994f383f718cb0a93 ·libs/pgpcdk/priv/utilities/helper/pgp¶
ea0bd6 File.h
d4b338 534a25f3ce9ec0769332b193bc5b5ec87efa97d2 ·libs/pgpcdk/priv/utilities/helper/pgp¶
83807d FileFIFO.c
2c407a 7e5e1d2f2b7fc773cdcb567d898ab36b14750011 ·libs/pgpcdk/priv/utilities/helper/pgp¶
6006ca FileNames.c
48c911 7fa3454c070f14e4789735f042011d85be57e4cd ·libs/pgpcdk/priv/utilities/helper/pgp¶
64e262 FileNames.h
1a65d5 734ddfb041e189caef520a5328ad9b944b860686 ·libs/pgpcdk/priv/utilities/helper/pgp¶
22c868 FileRef.c
5dfbfe e8afafb5fd523bbb6ae98322303319db2df8b58f ·libs/pgpcdk/priv/utilities/helper/pgp¶
672cc0 FileRef.h
3dd272 c44b1bcee11da12ef097bb975fd4df7d6ef2ee12 ·libs/pgpcdk/priv/utilities/helper/pgp¶
10cf54 FlexFIFO.c
4e7ac2 f4e16afd4d6bbb4d5e7f97e31f93d46f7dc4246c ·libs/pgpcdk/priv/utilities/helper/pgp¶
06dea9 MacBinary.c
4eb23e ca85f541cc6124a1e9c7b97cdd4b803d4f2776b4 ·libs/pgpcdk/priv/utilities/helper/pgp¶
a93a01 MacBinary.h
835662 ef83b22f8eba208856b9903b0728a9751c482bd4 ·libs/pgpcdk/priv/utilities/helper/pgp¶
c14ee1 MacFile.c
08ba73 090e9f89ef65da5d191514eee1d0898465e84415 ·libs/pgpcdk/priv/utilities/helper/pgp¶
9faa49 MacFile.h
163494 527d20b5385940626442c55c97e6fde998d563a1 ·libs/pgpcdk/priv/utilities/helper/pgp¶
e274ce MacFileMapping.c
--a7ed 000513f771340100005 Page 15 of libhashes.asc
23f0dd 80d8b1750b173d1091fa0cbafc76dfc710db8b5f ·libs/pgpcdk/priv/utilities/helper/pgp¶
f29066 MacFileMapping.h
2dd137 e69535b9a4b108cade57136e100ed488a7ea33e9 ·libs/pgpcdk/priv/utilities/helper/pgp¶
5e4383 MacUtils.c
50ca12 915d17aff96d7829ec5ba88b0c9fe0218d805107 ·libs/pgpcdk/priv/utilities/helper/pgp¶
93a72b MacUtils.h
4ddc72 70d0a579980c6a2e98e8b016cfff3e32c7c39c5d ·libs/pgpcdk/priv/utilities/helper/pgp¶
424109 MemFile.c
708177 ac6fa4ab4a42cf1d12d6cfdc6ab5a15e25de8efb ·libs/pgpcdk/priv/utilities/helper/pgp¶
3202b3 Msg.c
1330f3 5ed09b866dbd959847c84e73f6902491c2f63a9c ·libs/pgpcdk/priv/utilities/helper/pgp¶
24883f PassCach.c
83424e 762aa33d1a1d48725da5beb7f008ba6ab8a9932d ·libs/pgpcdk/priv/utilities/helper/pgp¶
266c97 PassCach.h
6b6a36 3d99a1380279f3cf9511253d3d804683b88f857c ·libs/pgpcdk/priv/utilities/helper/pgp¶
054150 PipeFile.c
856bf2 3cf42e865ecf6bd5829de53db31c448d706fdbfb ·libs/pgpcdk/priv/utilities/helper/pgp¶
acbcfe Str2Key.c
24413b 24b00068b374cb19b229c8c2c945deeef6090982 ·libs/pgpcdk/priv/utilities/helper/pgp¶
005856 Str2Key.h
1aff10 905143459b31abd3fa5615f8988936bdd5ec23a9 ·libs/pgpcdk/priv/utilities/helper/pgp¶
8415c0 TimeDate.c
210f54 b9fafff9e211c2963789dd20549aff089d85cd52 ·libs/pgpcdk/priv/utilities/helper/pgp¶
09f168 TimeDate.h
4fa7d3 7208e302e0482cd5027d74b14a0c2bd6444e7077 ·libs/pgpcdk/priv/utilities/pgpContext¶
b4f347 .c
6ca805 3f8b8fe7bc73f01d15af8a74c6d93e48f0791291 ·libs/pgpcdk/priv/utilities/pgpContext¶
e617ef .h
a40517 bdb3b7acbd8a34dec93d2dbafb3c1790bea5995d ·libs/pgpcdk/priv/utilities/pgpFeature¶
8b8ccf s.c
878148 142818fb356fd51ba8b28ef892470b4c3f2c5168 ·libs/pgpcdk/priv/utilities/pgpGroups.c
b7a4eb 215ebd7efc8438e6f0e3c12eb2b1bf1ace30545e ·libs/pgpcdk/priv/utilities/pgpGroupsP¶
653bb0 riv.h
24697d 21c6f19e45095c672c4834323271f23a184f7ab6 ·libs/pgpcdk/priv/utilities/pgpGroupsU¶
5dd8ed til.c
e71c91 5b931f332a5cc8f07a1ab0d1c37ed9e1d6197653 ·libs/pgpcdk/priv/utilities/pgpOptionL¶
507113 ist.c
1414c6 3c08f75fd350f203043523fb08771fe72fe3fa63 ·libs/pgpcdk/priv/utilities/pgpOptionL¶
9157d1 istPriv.h
da36d0 8efe17f812762c6980e03ea435af9f2a4e995222 ·libs/pgpcdk/priv/utilities/pgpOptionM¶
5e66cb em.c
9d5b9a e54fe59af1598d6f865fa50ab7a163dabfde5a8e ·libs/pgpcdk/priv/utilities/pgpTimeBom¶
3553d5 b.c
741381 d2411a53a2d6e98556da14b348200fd34e1c941b ·libs/pgpcdk/priv/utilities/pgpTimeBom¶
8eb77d b.h
d25b69 277a8652690e85681d0abcb88f1a083a01ab6142 ·libs/pgpcdk/priv/utilities/pgpUtiliti¶
2a0b28 es.c
c8c018 44832a089bd8a31c6fd9daca8d7fee3bef75918c ·libs/pgpcdk/priv/utilities/pgpUtiliti¶
3b2894 esPriv.h
b21e80 189ddd386eb977b5e2fe27b787b353a45bd44d7b ·libs/pgpcdk/priv/utilities/prefs/Make¶
c3f2f3 file.in
9b7e34 8e74dfc01764edd359341432f8c2298212c66d2e ·libs/pgpcdk/priv/utilities/prefs/pgpS¶
3c33e5 DKPrefs.c
78f645 9e9d2c868151b91346ff04bd0c20ba106a64ff8c ·libs/pgpcdk/priv/utilities/utils/Make¶
59f2f3 file.in
2954e6 2ac44cc0286c65e71851b5c6432409eb20b42e10 ·libs/pgpcdk/priv/utilities/utils/pgpC¶
535b0a onf.c
05fa1b fc5e10e402990a25b580221e936cf908675872fd ·libs/pgpcdk/priv/utilities/utils/pgpC¶
7abfa2 onf.h
7baf4e c90d3a79acda0fd3dcb41d464f05e69bb3a468c5 ·libs/pgpcdk/priv/utilities/utils/pgpD¶
b1fb99 ecPipe.c
e4ddf8 a184ced4a6ed6c580fbf59954bb543b1becfb681 ·libs/pgpcdk/priv/utilities/utils/pgpD¶
4a1f31 ecPipe.h
5e0310 c28c6fe99611b0c9ed6d1be1aaeb6ea0e4eb7b1f ·libs/pgpcdk/priv/utilities/utils/pgpE¶
635254 ncPipe.c
5c55b3 784b22d658b594e068022948c6d53d5ab9d1e779 ·libs/pgpcdk/priv/utilities/utils/pgpE¶
b1b6fc ncPipe.h
30efe7 5b12c2e9710f94ee3a8d999fc3b6163593e21629 ·libs/pgpcdk/priv/utilities/utils/pgpE¶
132293 nv.c
cf6ed8 7a9570ad08e1968438daf15797ce8800e2e2a277 ·libs/pgpcdk/priv/utilities/utils/pgpE¶
16c63b nv.h
51071b d1f8d2763bf997b6409253225ebef290870555d8 ·libs/pgpcdk/priv/utilities/utils/pgpF¶
--8778 001162c317340100005 Page 16 of libhashes.asc
9d4119 ileType.c
db5c91 a20a95bc0bb53a64f362fbb410b666c1d877d800 ·libs/pgpcdk/priv/utilities/utils/pgpF¶
56a5b1 ileType.h
e03bd3 3cfe6ddafb327fee12d944bed1e122ca10f5d7c3 ·libs/pgpcdk/priv/utilities/utils/pgpS¶
f8ad68 igPipe.c
270919 98d1d226d28be9268a7863a933cc22501844052b ·libs/pgpcdk/priv/utilities/utils/pgpS¶
6e49c0 igPipe.h
93a427 87b2a09f2e7dbe9c6bc667f4ca4a11b146279220 ·libs/pgpcdk/priv/utilities/utils/pgpS¶
1bbb4b igSpec.c
e7bfa5 666c4cc2ae71dd0e452bc7839eb4d10c5a1c8e29 ·libs/pgpcdk/priv/utilities/utils/pgpS¶
715fe3 igSpec.h
20fce6 f47a8dec28e22d4b85d3a3b095b4c0e926783cf7 ·libs/pgpcdk/pub/Makefile.in
feff89 916187ab5dbc971f33641933d4f5f0dc4f8eaca8 ·libs/pgpcdk/pub/include/Makefile.in
945c15 66e247e149c607c53d7aa3adc8f1bd3247c81faf ·libs/pgpcdk/pub/include/pgpBigNum.h
3e7fdc 3998f5cd00928b118b5f5b2aaeb73fd446c47387 ·libs/pgpcdk/pub/include/pgpCBC.h
723f57 ea7ca13bfec3b818854fc4d7d953691aa9ff65a0 ·libs/pgpcdk/pub/include/pgpCFB.h
9f0209 bbf76f11415b6b25a4b64b8ae3919b2bb14c637d ·libs/pgpcdk/pub/include/pgpEncode.h
72c0cf 80830f10e17e3ee9ff5b925849c439110c50e51d ·libs/pgpcdk/pub/include/pgpErrors.h
2f941c 0ab3453935ba0676d4d787421662c0a03f480eeb ·libs/pgpcdk/pub/include/pgpFeatures.h
8141f6 3e71eb88c1a27524bf4caa45eab3d0491e933762 ·libs/pgpcdk/pub/include/pgpGroups.h
07e71a 40357acdb7a72ba8f1a7f5cef97bc326421faa23 ·libs/pgpcdk/pub/include/pgpHMAC.h
47fd6a 33e09a3e9b392ad2f3b617d5949dd2c8ff10e1a0 ·libs/pgpcdk/pub/include/pgpHash.h
76ef84 cbfee0c8fc9bd6c655211aabe4da166f29eda84c ·libs/pgpcdk/pub/include/pgpKeyServer.h
2c82e1 e06cc5319cba5afa0bcc811e56969d294add4006 ·libs/pgpcdk/pub/include/pgpKeys.h
291e5f da70f911fcb81a3a781f21b643db9e0239b9473c ·libs/pgpcdk/pub/include/pgpOptionList¶
d917ef .h
16c2d6 062c700b267d8430fbe99b7bf179a4b7d01b43bd ·libs/pgpcdk/pub/include/pgpPubTypes.h
d09d6a 9f3fe8abd545d601c52c9a1bc455f9212c1971ab ·libs/pgpcdk/pub/include/pgpPublicKey.h
b2d5c4 c7f997c01f8fb2aa9325725963256fb450f0c3fb ·libs/pgpcdk/pub/include/pgpRandomPool¶
7f17ef .h
846d3c 7631d88d76e19b4020cd7a1a7916302ced94027b ·libs/pgpcdk/pub/include/pgpSDKPrefs.h
650a15 ad99f6377c9338bf301d42cc2e713faaccdf54da ·libs/pgpcdk/pub/include/pgpSockets.h
91ad36 c190ef8e0f391f0a23ba71f6cbfa0e7836a71fd9 ·libs/pgpcdk/pub/include/pgpSymmetricC¶
fe3b9c ipher.h
c8602c 9d2cff602c43fe8cbef4c1bf5e7fd09b09227366 ·libs/pgpcdk/pub/include/pgpTLS.h
439acb 614b34c579a8f002bd66f42050b231ca6334f075 ·libs/pgpcdk/pub/include/pgpUserInterf¶
75dfb9 ace.h
62626f b454b9d2d0f452e941ba1257504dabdf674f4f5c ·libs/pgpcdk/pub/include/pgpUtilities.h
aafad1 66411677aab9a301e9a4a493a9c2dc33c5c15adb ·shasum
27767c ac301236ed55164a697ee1a248453cf5c5639f70 ·sortpages.patch
a52940 c6b5c49af48c6096bd52475fa69332363030fd37 ·test-file
b3af5a
c0e38f -----BEGIN PGP SIGNATURE-----
36d11c Version: PGP 6.0.2
1faf5a
2e5b59 iQA/AwUBNk314hOghfzXeyCUEQIapwCgggqIN2KfScDaG6Dy0cIDaRHO84cAoODY
055f01 CSIfGZ/n7Kd6vq/4mywVjp4r
f54f55 =caUI
16e726 -----END PGP SIGNATURE-----
--2e9e 0001966541040100006 Page 1 of PGPChangeHistory.txt
2f7017 PGP 6.0.2 Change History
66af5a
12af5a
a687d3 Windows & Macintosh
71af5a
6f0de5 Added: The last PGP 2.X feature that never made it into modern PGP has finally ¶
cd6f05 been added to 6.0.2: For Your Eyes Only. ·However, we can't call it that for le¶
351647 gal reasons, so the name of the feature is Secure Viewer. ·It is however compat¶
89e91b ible with the feature previously known as FYEO in old versions. ·Secure Viewer ¶
4861a6 has been written to handle the issues of modern OSs, and even uses a TEMPEST at¶
96097b tack prevention font to display the message.
35af5a
ca392b Added: Forcing the Recipient Dialog can now be accomplished by holding down a m¶
d5c7a9 odifier key in the email plugin to show the recipient dialog even in cases wher¶
afbebd e the recipients are all valid. ·This key varies by plugin, but is either Shift¶
52a747 ·or Control.
70af5a
18b976 Fixed: Key pairs with implicit trust turned off could sometimes become default ¶
807da5 keys. [2877, Win/Mac]
52af5a
3623e2 Fixed: Revoked or expired sub-keys appear in the Recipient dialog. [2902, Win/M¶
79a3a3 ac]
61af5a
3bd152 Fixed: PGPkeys sometimes creates RSA keys that are displayed as split keys. [30¶
74d10b 99, Win/Mac]
4faf5a
cbd335 Fixed: PGPadmin has "Allow RSA key generation" enabled in Diffie-Hellman builds¶
3200ec . [2976, Win/Mac]
99af5a
21abd6 Changed: When a signature is bad, the signing key's validity is no longer displ¶
cc6cdb ayed since the green dot used for validity was potentially misleading. [1967, W¶
dbfbba in/Mac]
edaf5a
c701e5 Changed: SKEP authentication error dialog re-worded. [2954, Win/Mac]
7caf5a
3daf5a
6c27bd Windows
e9af5a
bf6d51 Fixed: An internal security review of PGPdisk revealed serious security flaws i¶
1ab9b6 n previous versions of PGPdisk for Windows. ·The Installer will scan for any PG¶
b2acab Pdisks you may have so that you may upgrade them. ·PGPdisk will also automatica¶
19dbe5 lly upgrade your disks when attempting to mount them. ·It is strongly recommend¶
8abd19 ed that you immediately update your PGPdisks to the new version.
59af5a
57a66c Fixed: Outlook 97/98 will crash if you encrypt a message to a "Contact." [3042,¶
f84708 ·Windows]
ceaf5a
26cf83 Fixed: Eudora will crash if key rings are on an unmounted volume. [3061, Window¶
16a369 s]
e1af5a
d2ad22 Fixed: Outlook 97/98 will crash if you try to sign and send a message that has ¶
16c191 no text (only a Subject), and then try to sign and send again with text in the ¶
789dec message. [3096, Windows]
26af5a
08ee09 Fixed: Attempting to create a PGPdisk on a mapped network drive under Win95 and¶
a7eeca ·Win98 results in a crash. [3030, Windows]
79af5a
d340f8 Fixed: PGPdisk shell extension will occasionally crash the Explorer. [3009, Win¶
eff25f dows]
95af5a
e400dd Fixed: PGP fails to continue a search if one of the servers is down. [2873, Win¶
eff25f dows]
ebaf5a
e72da1 Changed: Text is now wrapped when clear-signing in Eudora using the Message Plu¶
e1cf6d gins sub-menu. [1970, Windows]
ceaf5a
ed56b2 Changed: User is now warned when using the "Wipe Original" feature while encryp¶
b6b5f3 ting files to keys other than the user's key pair. [2003, Windows]
78af5a
a6bd0e Changed: Outlook 97/98 plugin now recognizes Personal Distribution lists. [2809¶
0af32c , Windows]
19af5a
--7e3b 000fb85700040100006 Page 2 of PGPChangeHistory.txt
9b7a72 Fixed: PGPdisk does not support long file names the first time a disk is used. ¶
459cbd [3006, Windows]
46af5a
182d0d Fixed: If no Trusted Introducers are on the server an empty import dialog will ¶
06b7a4 appear after doing an automatic update. [3073, Windows]
a6af5a
90e465 Fixed: "Wrong Version" error when using PGP with the Comctl32.dll from IE5. [30¶
250de7 82, Windows]
1daf5a
1b8a03 Fixed: Outlook 97/98 plugin, "Strike-out" recipients appear when using Sync wit¶
49f936 h Unknown Keys, even though a successful match has been made. [3081, Windows]
d3af5a
abb189 Fixed: Mouse can disappear "behind" the Recipient Dialog if Windows' preference¶
93ace7 ·"Hide Pointer When Typing" is enabled. [3002, Windows]
81af5a
38fb83 Changed: PGP no longer caches conventional encryption passphrases when the "Cac¶
3f6492 he Decryption Passphrases" preference is enabled. [2959, Windows]
36af5a
43c957 Fixed: PGPdisk "GB" radio button is sometimes disabled. [3083, Windows]
21af5a
22bea3 Fixed: The Free Space Wiper cancel button is enabled but doesn't work during th¶
af20be e initial scanning of the hard drive. [3084, Windows]
bcaf5a
1b4d2d Changed: Recipient dialog now puts the initial keyboard focus in the key select¶
35eaf4 ion list. [3088, Windows]
eeaf5a
5f0799 Changed: PGPdisk menu item in PGPtray is now disabled when PGPdisk is not insta¶
b5dadd lled. [3089, Windows]
17af5a
bddb3b Fixed: PGPadmin doesn't respond to Page Up and Page Down buttons in the options¶
851d58 ·review window. [2890, Windows]
25af5a
8560fc Fixed: Passphrase Quality bar is not refreshed if you go to the previous panel ¶
2b5d64 and use Next to return to the Passphrase panel. [3023, Windows]
d4af5a
cba4e3 Fixed: Passphrase Quality bar now displays when a passphrase does not meet the ¶
8ac2b7 minimum quality score. [3038, Windows]
98af5a
ff8872 Fixed: Status bar still reads "connecting to server" even though a search has f¶
bd29e4 ailed. [3048, Windows]
bdaf5a
65ee2b Changed: Automatic updates in configured client builds no longer show a dialog ¶
e1b3c0 to the user asking them to Update or Cancel. [3090, Windows]
36af5a
959b2c Fixed: Alert message text (from Use Current Window feature) is truncated. [2938¶
86f32c , Windows]
8daf5a
c374b9 Fixed: Long passphrases are sometimes reported as incorrect even though they ar¶
eaafcc e typed correctly. [3092, Windows]
d4af5a
b5a31d Changed: Bad Signature icon in PGP Log has been changed. [3093, Windows]
46af5a
00af5a
3282bd Macintosh
a2af5a
f03be4 Fixed: Word 98, Decrypt/Verify command via PGPmenu causes computer to freeze. [¶
33b21b 3052, MacOS]
eaaf5a
a59473 Fixed: PGPtools doesn't accept any file type dropped onto it for scanning when ¶
545321 the file is not within a folder. [3207, MacOS]
cbaf5a
a5d449 Fixed: Text files with 10 character file names are garbled upon decryption. [30¶
e04621 87, MacOS]
1eaf5a
33a009 Fixed: Key not imported when you drag and drop a text clipping into PGPkeys. [3¶
41cf27 057, MacOS]
40af5a
2101ae Fixed: Random Seed File location can be lost from PGP Preferences after a Syste¶
2e9545 m Software upgrade. [2047, MacOS]
adaf5a
2a47c8 Fixed: MacOS 8.5 File Exchange control panel doesn't recognize PGPkeys' file ty¶
fb2b2f pes. [3050, MacOS]
--ebdf 0015d70a57140100006 Page 3 of PGPChangeHistory.txt
e0af5a
5f5441 Fixed: Disabled key pairs can be enabled by selecting Implicit Trust but are st¶
0a0585 ill invalid. [2930, MacOS]
60af5a
9e8541 Fixed: Configured client installs shouldn't have the menu item "Send Group List¶
f5c88c s" enabled. [3001, MacOS]
d4af5a
5bace3 Fixed: PGPdisk has an extraneous registration dialog. [3051, MacOS]
d2af5a
10b2d1 Fixed: PGPadmin prompts the user to save the configured installer with the same¶
1833aa ·name as the source installer, this could lead to the accidental deletion of th¶
4cab7c e original installer. [3085, MacOS]
2baf5a
e83212 Fixed: A hidden passphrase entry box will appear if you uncheck Hide Typing. [2¶
b43d9d 637, MacOS]
27af5a
db88eb Fixed: Key pair is still enabled even after the Enabled check box is cleared. [¶
764a7d 2913, MacOS]
70af5a
47f722 Fixed: One of PGPadmin's panels is displayed in the wrong order. [2977, MacOS]
eeaf5a
cc75e4 Fixed: Incorrect icon displayed for split key pair in the Import dialog box. [3¶
60b08a 004, MacOS]
72af5a
e205ae Changed: Error message text changed when PGP is unable to wipe files. [3021, Ma¶
19b863 cOS]
3faf5a
811727 Fixed: PGPkeys now always imports Photo IDs when keys are dragged from the Sear¶
5d306d ch window. [3035, MacOS]
--5508 0003dcb932240100007 Page 1 of README
438303 The Independent JPEG Group's JPEG software
847e36 ==========================================
b6af5a
362d33 README for release 6a of 7-Feb-96
2c06ad =================================
1faf5a
1e83fd This distribution contains the sixth public release of the Independent JPEG
cda262 Group's free JPEG software. ·You are welcome to redistribute this software and
f39c4c to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
cdaf5a
813007 Serious users of this software (particularly those incorporating it into
d1cab8 larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
646afd our electronic mailing list. ·Mailing list members are notified of updates
76aa15 and have a chance to participate in technical discussions, etc.
b8af5a
970cef This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Jim
5a68e9 Boucher, Lee Crocker, Julian Minguillon, George Phillips, Davide Rossi,
9f442d Ge' Weijers, and other members of the Independent JPEG Group.
09af5a
57b093 IJG is not affiliated with the official ISO JPEG standards committee.
e1af5a
d0af5a
a15fd4 DOCUMENTATION ROADMAP
8e257b =====================
e1af5a
805005 This file contains the following sections:
4eaf5a
d83eec OVERVIEW ···········General description of JPEG and the IJG software.
56b7e5 LEGAL ISSUES ·······Copyright, lack of warranty, terms of distribution.
844aae REFERENCES ·········Where to learn more about JPEG.
66c7ad ARCHIVE LOCATIONS ··Where to find newer versions of this software.
a5d1fa RELATED SOFTWARE ···Other stuff you should get.
6475f5 FILE FORMAT WARS ···Software *not* to get.
24d780 TO DO ··············Plans for future IJG releases.
54af5a
4f345a Other documentation files in the distribution are:
82af5a
da2adc User documentation:
477cf2 ··install.doc ······How to configure and install the IJG software.
8a4fcc ··usage.doc ········Usage instructions for cjpeg, djpeg, jpegtran,
0674a7 ····················rdjpgcom, and wrjpgcom.
87a48a ··*.1 ··············Unix-style man pages for programs (same info as usage.doc).
7a36d5 ··wizard.doc ·······Advanced usage instructions for JPEG wizards only.
6ea14d ··change.log ·······Version-to-version change highlights.
ba12d9 Programmer and internal documentation:
29b555 ··libjpeg.doc ······How to use the JPEG library in your own programs.
b2d627 ··example.c ········Sample code for calling the JPEG library.
110032 ··structure.doc ····Overview of the JPEG library's internal structure.
b301ec ··filelist.doc ·····Road map of IJG files.
19c50b ··coderules.doc ····Coding style rules --- please read if you contribute code.
a6af5a
b55558 Please read at least the files install.doc and usage.doc. ·Useful information
3b8d2d can also be found in the JPEG FAQ (Frequently Asked Questions) article. ·See
a3ea36 ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
9baf5a
46919e If you want to understand how the JPEG code works, we suggest reading one or
f1503d more of the REFERENCES, then looking at the documentation files (in roughly
3f66a5 the order listed) before diving into the code.
43af5a
8aaf5a
d883a1 OVERVIEW
65e7a9 ========
e4af5a
1cb784 This package contains C software to implement JPEG image compression and
18a757 decompression. ·JPEG (pronounced "jay-peg") is a standardized compression
c78189 method for full-color and gray-scale images. ·JPEG is intended for compressing
8fdc89 "real-world" scenes; line drawings, cartoons and other non-realistic images
32f989 are not its strong suit. ·JPEG is lossy, meaning that the output image is not
6af752 exactly identical to the input image. ·Hence you must not use JPEG if you
bc1356 have to have identical output bits. ·However, on typical photographic images,
a385b3 very good compression levels can be obtained with no visible change, and
3d337a remarkably high compression levels are possible if you can tolerate a
--c863 0001b5ae40540100007 Page 2 of README
28e3ef low-quality image. ·For more details, see the references, or just experiment
a2b701 with various compression settings.
ddaf5a
44205e This software implements JPEG baseline, extended-sequential, and progressive
da67c4 compression processes. ·Provision is made for supporting all variants of these
35e4f8 processes, although some uncommon parameter settings aren't implemented yet.
b8dc86 For legal reasons, we are not distributing code for the arithmetic-coding
90f87f variants of JPEG; see LEGAL ISSUES. ·We have made no provision for supporting
3fa96a the hierarchical or lossless processes defined in the standard.
9eaf5a
1d19ed We provide a set of library routines for reading and writing JPEG image files,
f02981 plus two sample applications "cjpeg" and "djpeg", which use the library to
2c87bb perform conversion between JPEG and some other popular image file formats.
df73ca The library is intended to be reused in other applications.
ebaf5a
24ba13 In order to support file conversion and viewing software, we have included
876e64 considerable functionality beyond the bare JPEG coding/decoding capability;
f2c846 for example, the color quantization modules are not strictly part of JPEG
eb940e decoding, but they are essential for output to colormapped file formats or
c0e1e6 colormapped displays. ·These extra functions can be compiled out of the
7f708e library if not required for a particular application. ·We have also included
d09035 "jpegtran", a utility for lossless transcoding between different JPEG
b824b2 processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
520253 inserting and extracting textual comments in JFIF files.
bfaf5a
d8b0f2 The emphasis in designing this software has been on achieving portability and
21e440 flexibility, while also making it fast enough to be useful. ·In particular,
7de0ac the software is not intended to be read as a tutorial on JPEG. ·(See the
671c64 REFERENCES section for introductory material.) ·Rather, it is intended to
3acd94 be reliable, portable, industrial-strength code. ·We do not claim to have
a6446d achieved that goal in every aspect of the software, but we strive for it.
62af5a
82ef28 We welcome the use of this software as a component of commercial products.
d0d15a No royalty is required, but we do ask for an acknowledgement in product
df8af8 documentation, as described under LEGAL ISSUES.
ffaf5a
f5af5a
8fff0f LEGAL ISSUES
792ddb ============
68af5a
bb321a In plain English:
d2af5a
8d3f15 1. We don't promise that this software works. ·(But if you find any bugs,
d614ad ···please let us know!)
8ff523 2. You can use this software for whatever you want. ·You don't have to pay us.
e63c0f 3. You may not pretend that you wrote this software. ·If you use it in a
9d4f39 ···program, you must acknowledge somewhere in your documentation that
47f72c ···you've used the IJG code.
2caf5a
2a7ddb In legalese:
e0af5a
f369ee The authors make NO WARRANTY or representation, either express or implied,
0a13be with respect to this software, its quality, accuracy, merchantability, or
8b96d4 fitness for a particular purpose. ·This software is provided "AS IS", and you,
62f1d4 its user, assume the entire risk as to its quality and accuracy.
69af5a
a8b274 This software is copyright (C) 1991-1996, Thomas G. Lane.
98529a All Rights Reserved except as specified below.
33af5a
92a7fa Permission is hereby granted to use, copy, modify, and distribute this
ff306c software (or portions thereof) for any purpose, without fee, subject to these
404e50 conditions:
850422 (1) If any part of the source code for this software is distributed, then this
cca3aa README file must be included, with this copyright and no-warranty notice
1c2e08 unaltered; and any additions, deletions, or changes to the original files
d04752 must be clearly indicated in accompanying documentation.
b8676b (2) If only executable code is distributed, then the accompanying
fb1243 documentation must state that "this software is based in part on the work of
bfa04a the Independent JPEG Group".
30f84e (3) Permission for use of this software is granted only if the user accepts
8d8eb5 full responsibility for any undesirable consequences; the authors accept
1b9e7b NO LIABILITY for damages of any kind.
--3854 0002361a71440100007 Page 3 of README
e0af5a
ba2a4e These conditions apply to any software derived from or based on the IJG code,
ab0903 not just to the unmodified library. ·If you use our work, you ought to
49647f acknowledge us.
04af5a
d8de36 Permission is NOT granted for the use of any IJG author's name or company name
52d4ba in advertising or publicity relating to this software or products derived from
1f63f4 it. ·This software may be referred to only as "the Independent JPEG Group's
edda75 software".
fcaf5a
75fdac We specifically permit and encourage the use of this software as the basis of
bda809 commercial products, provided that all warranty or liability claims are
58d12f assumed by the product vendor.
dcaf5a
00af5a
6adc92 ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
99d51a sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
582561 ansi2knr.c is NOT covered by the above copyright and conditions, but instead
d6d16f by the usual distribution terms of the Free Software Foundation; principally,
fe9f96 that you must include source code if you redistribute it. ·(See the file
f6fea3 ansi2knr.c for full details.) ·However, since ansi2knr.c is not needed as part
bee5d7 of any program generated from the IJG code, this does not limit you more than
72395c the foregoing paragraphs do.
91af5a
6fe786 The configuration script "configure" was produced with GNU Autoconf. ·It
443c90 is copyright by the Free Software Foundation but is freely distributable.
a8af5a
dc44ff It appears that the arithmetic coding option of the JPEG spec is covered by
f643b6 patents owned by IBM, AT&T, and Mitsubishi. ·Hence arithmetic coding cannot
55ec00 legally be used without obtaining one or more licenses. ·For this reason,
894055 support for arithmetic coding has been removed from the free JPEG software.
a3e765 (Since arithmetic coding provides only a marginal gain over the unpatented
55e544 Huffman mode, it is unlikely that very many implementations will support it.)
2369b4 So far as we are aware, there are no patent restrictions on the remaining
748102 code.
3baf5a
9905ae WARNING: Unisys has begun to enforce their patent on LZW compression against
80e7f9 GIF encoders and decoders. ·You will need a license from Unisys to use the
cd95fa included rdgif.c or wrgif.c files in a commercial or shareware application.
caabf1 At this time, Unisys is not enforcing their patent against freeware, so
1b99ab distribution of this package remains legal. ·However, we intend to remove
fa783c GIF support from the IJG package as soon as a suitable replacement format
323df9 becomes reasonably popular.
acaf5a
4db7e0 We are required to state that
3b794c ····"The Graphics Interchange Format(c) is the Copyright property of
ab49c0 ····CompuServe Incorporated. ·GIF(sm) is a Service Mark property of
63d867 ····CompuServe Incorporated."
79af5a
17af5a
74c382 REFERENCES
1f487d ==========
4eaf5a
87db54 We highly recommend reading one or more of these references before trying to
3b0410 understand the innards of the JPEG software.
eaaf5a
69dac4 The best short technical introduction to the JPEG compression algorithm is
430945 ¤   Wallace, Gregory K. ·"The JPEG Still Picture Compression Standard",
08321b ¤   Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
3660ee (Adjacent articles in that issue discuss MPEG motion picture compression,
1c75d2 applications of JPEG, and related topics.) ·If you don't have the CACM issue
34e30d handy, a PostScript file containing a revised version of Wallace's article
a2ec4f is available at ftp.uu.net, graphics/jpeg/wallace.ps.gz. ·The file (actually
306af8 a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
4d13de omits the sample images that appeared in CACM, but it includes corrections
bf7cbe and some added material. ·Note: the Wallace article is copyright ACM and
8544b6 IEEE, and it may not be used for commercial purposes.
a6af5a
0bb71a A somewhat less technical, more leisurely introduction to JPEG can be found in
e3ee05 "The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood
f75f1a City, CA), 1991, ISBN 1-55851-216-0. ·This book provides good explanations and
23eb9f example C code for a multitude of compression methods including JPEG. ·It is
--3027 00009f9a03340100007 Page 4 of README
278f60 an excellent source if you are comfortable reading C code but don't know much
e4526d about data compression in general. ·The book's JPEG sample code is far from
2b6adb industrial-strength, but when you are ready to look at a full implementation,
6e090b you've got one here...
a4af5a
a7a902 The best full description of JPEG is the textbook "JPEG Still Image Data
41d0d5 Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
b47073 by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. ·Price US$59.95, 638 pp.
7ddd27 The book includes the complete text of the ISO JPEG standards (DIS 10918-1
b215b4 and draft DIS 10918-2). ·This is by far the most complete exposition of JPEG
780ba5 in existence, and we highly recommend it.
38af5a
f4ffc3 The JPEG standard itself is not available electronically; you must order a
ec1f19 paper copy through ISO or ITU. ·(Unless you feel a need to own a certified
b87d11 official copy, we recommend buying the Pennebaker and Mitchell book instead;
dd631e it's much cheaper and includes a great deal of useful explanatory material.)
d4fc82 In the USA, copies of the standard may be ordered from ANSI Sales at (212)
19302a 642-4900, or from Global Engineering Documents at (800) 854-7179. ·(ANSI
47d188 doesn't take credit card orders, but Global does.) ·It's not cheap: as of
74ba0d 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
7193c9 shipping/handling. ·The standard is divided into two parts, Part 1 being the
45e8d2 actual specification, while Part 2 covers compliance testing methods. ·Part 1
903567 is titled "Digital Compression and Coding of Continuous-tone Still Images,
60cfc8 Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
bdb4e6 10918-1, ITU-T T.81. ·Part 2 is titled "Digital Compression and Coding of
e67db7 Continuous-tone Still Images, Part 2: Compliance testing" and has document
d76540 numbers ISO/IEC IS 10918-2, ITU-T T.83.
6eaf5a
22ac33 Extensions to the original JPEG standard are defined in JPEG Part 3, a new ISO
4149e0 document. ·Part 3 is undergoing ISO balloting and is expected to be approved
975175 by the end of 1995; it will have document numbers ISO/IEC IS 10918-3, ITU-T
1ade59 T.84. ·IJG currently does not support any Part 3 extensions.
4caf5a
3dff18 The JPEG standard does not specify all details of an interchangeable file
606ba6 format. ·For the omitted details we follow the "JFIF" conventions, revision
b9e3ca 1.02. ·A copy of the JFIF spec is available from:
1a4714 ¤   Literature Department
cfc65a ¤   C-Cube Microsystems, Inc.
45f17f ¤   1778 McCarthy Blvd.
a961be ¤   Milpitas, CA 95035
2667ba ¤   phone (408) 944-6300, ·fax (408) 944-6314
9bf691 A PostScript version of this document is available at ftp.uu.net, file
df5e8b graphics/jpeg/jfif.ps.gz. ·It can also be obtained by e-mail from the C-Cube
88190b mail server, netlib@c3.pla.ca.us. ·Send the message "send jfif_ps from jpeg"
cad139 to the server to obtain the JFIF document; send the message "help" if you have
86ada8 trouble.
93af5a
5ca187 The TIFF 6.0 file format specification can be obtained by FTP from sgi.com
3ef2b4 (192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed
760eea copy from Aldus Corp. at (206) 628-6593. ·The JPEG incorporation scheme
8e51f9 found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
20abf8 IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
022b5a Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
c5cf95 (Compression tag 7). ·Copies of this Note can be obtained from sgi.com or
428252 from ftp.uu.net:/graphics/jpeg/. ·It is expected that the next revision of
897e9d the TIFF spec will replace the 6.0 JPEG design with the Note's design.
68f3aa Although IJG's own code does not support TIFF/JPEG, the free libtiff library
48d961 uses our library to implement TIFF/JPEG per the Note. ·libtiff is available
714956 from sgi.com:/graphics/tiff/.
86af5a
79af5a
e65f2a ARCHIVE LOCATIONS
1dd88f =================
4eaf5a
eb7340 The "official" archive site for this software is ftp.uu.net (Internet
d1804d address 192.48.96.9). ·The most recent released version can always be found
50c9a0 there in directory graphics/jpeg. ·This particular version will be archived
17fa7a as graphics/jpeg/jpegsrc.v6a.tar.gz. ·If you are on the Internet, you
d227fc can retrieve files from ftp.uu.net by standard anonymous FTP. ·If you don't
9a8a89 have FTP access, UUNET's archives are also available via UUCP; contact
4fe52b help@uunet.uu.net for information on retrieving files that way.
09af5a
--c8f2 000b17d899a40100007 Page 5 of README
8a368e Numerous Internet sites maintain copies of the UUNET files. ·However, only
968761 ftp.uu.net is guaranteed to have the latest official version.
dbaf5a
8632b1 You can also obtain this software in DOS-compatible "zip" archive format from
5a088f the SimTel archives (ftp.coast.net:/SimTel/msdos/graphics/), or on CompuServe
a128e4 in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 "JPEG Tools".
438511 Again, these versions may sometimes lag behind the ftp.uu.net release.
9aaf5a
4bc1d3 The JPEG FAQ (Frequently Asked Questions) article is a useful source of
a0b292 general information about JPEG. ·It is updated constantly and therefore is
92265a not included in this distribution. ·The FAQ is posted every two weeks to
46fea6 Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
4c2044 You can always obtain the latest version from the news.answers archive at
9f8b0a rtfm.mit.edu. ·By FTP, fetch /pub/usenet/news.answers/jpeg-faq/part1 and
2a5223 .../part2. ·If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu
f9db26 with body
a3c3b1 ¤   send usenet/news.answers/jpeg-faq/part1
9ee9d9 ¤   send usenet/news.answers/jpeg-faq/part2
2caf5a
7aaf5a
2519bc RELATED SOFTWARE
553708 ================
44af5a
883bd8 Numerous viewing and image manipulation programs now support JPEG. ·(Quite a
708eb9 few of them use this library to do so.) ·The JPEG FAQ described above lists
26faef some of the more popular free and shareware viewers, and tells where to
68c0e4 obtain them on Internet.
f5af5a
4c23a9 If you are on a Unix machine, we highly recommend Jef Poskanzer's free
0a6536 PBMPLUS image software, which provides many useful operations on PPM-format
418fd9 image files. ·In particular, it can convert PPM images to and from a wide
5cc4ed range of other formats. ·You can obtain this package by FTP from ftp.x.org
8c4cb3 (contrib/pbmplus*.tar.Z) or ftp.ee.lbl.gov (pbmplus*.tar.Z). ·There is also
6fd401 a newer update of this package called NETPBM, available from
9b0e9c wuarchive.wustl.edu under directory /graphics/graphics/packages/NetPBM/.
d0f846 Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software
87bf18 is; you are likely to have difficulty making it work on any non-Unix machine.
8daf5a
960ec3 A different free JPEG implementation, written by the PVRG group at Stanford,
17cf95 is available from havefun.stanford.edu in directory pub/jpeg. ·This program
f63659 is designed for research and experimentation rather than production use;
52985c it is slower, harder to use, and less portable than the IJG code, but it
3b95ca is easier to read and modify. ·Also, the PVRG code supports lossless JPEG,
e336c1 which we do not.
f1af5a
e5af5a
9e701c FILE FORMAT WARS
0e3708 ================
90af5a
a92d60 Some JPEG programs produce files that are not compatible with our library.
62429c The root of the problem is that the ISO JPEG committee failed to specify a
3df345 concrete file format. ·Some vendors "filled in the blanks" on their own,
0cd132 creating proprietary formats that no one else could read. ·(For example, none
4533c7 of the early commercial JPEG implementations for the Macintosh were able to
beabb8 exchange compressed files.)
f9af5a
7cdf4e The file format we have adopted is called JFIF (see REFERENCES). ·This format
3cf22d has been agreed to by a number of major commercial JPEG vendors, and it has
428771 become the de facto standard. ·JFIF is a minimal or "low end" representation.
17fa26 We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
6b43f3 Technical Note #2) for "high end" applications that need to record a lot of
5e6f6a additional data about an image. ·TIFF/JPEG is fairly new and not yet widely
e4f934 supported, unfortunately.
efaf5a
530544 The upcoming JPEG Part 3 standard defines a file format called SPIFF.
fe8847 SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
2b9a44 be able to read the most common variant of SPIFF. ·SPIFF has some technical
c1bda8 advantages over JFIF, but its major claim to fame is simply that it is an
058ad6 official standard rather than an informal one. ·At this point it is unclear
c8ac31 whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
a5bc7b standard. ·IJG intends to support SPIFF once the standard is frozen, but we
b1fab3 have not decided whether it should become our default output format or not.
--3392 0015d1c3a8c40100007 Page 6 of README
c3289a (In any case, our decoder will remain capable of reading JFIF indefinitely.)
8baf5a
71d030 Various proprietary file formats incorporating JPEG compression also exist.
5ebbef We have little or no sympathy for the existence of these formats. ·Indeed,
4e6605 one of the original reasons for developing this free software was to help
a40f8e force convergence on common, open format standards for JPEG files. ·Don't
ac55fd use a proprietary file format!
83af5a
43af5a
197ba3 TO DO
3e4d86 =====
2baf5a
8dda2a In future versions, we are considering supporting some of the upcoming JPEG
13ccf5 Part 3 extensions --- principally, variable quantization and the SPIFF file
3513ce format.
36af5a
5ba679 Tuning the software for better behavior at low quality/high compression
a2b9c6 settings is also of interest. ·The current method for scaling the
78170d quantization tables is known not to be very good at low Q values.
eaaf5a
e4fc99 As always, speeding things up is high on our priority list.
1eaf5a
5db53e Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
--5592 000d807851f40100008 Page 1 of cderror.h
bc38e5 /*
3147b7 ·* cderror.h
39775e ·*
c3390e ·* Copyright (C) 1994, Thomas G. Lane.
a5fb07 ·* This file is part of the Independent JPEG Group's software.
d5a0d6 ·* For conditions of distribution and use, see the accompanying README file.
7e775e ·*
f5402a ·* This file defines the error and message codes for the cjpeg/djpeg
c8f364 ·* applications. ·These strings are not needed as part of the JPEG library
4a1e36 ·* proper.
489990 ·* Edit this file to add new codes, or to translate the message strings to
69699d ·* some other language.
d5495d ·*/
9daf5a
aa38e5 /*
5caf09 ·* To define the enum list of message codes, include this file without
19163d ·* defining macro JMESSAGE. ·To create a message string table, include it
531f24 ·* again with a suitable JMESSAGE definition (see jerror.c for an example).
23495d ·*/
0ed834 #ifndef JMESSAGE
fe7b95 #ifndef CDERROR_H
84a6cc #define CDERROR_H
edb757 /* First time through, define the enum list */
3751ef #define JMAKE_ENUM_LIST
efdb21 #else
ac58d3 /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
543c98 #define JMESSAGE(code,string)
c755c9 #endif /* CDERROR_H */
c1f142 #endif /* JMESSAGE */
edaf5a
d7e0f9 #ifdef JMAKE_ENUM_LIST
70af5a
fded84 typedef enum {
46af5a
7eb723 #define JMESSAGE(code,string)¤  code ,
02af5a
d8b694 #endif /* JMAKE_ENUM_LIST */
c7af5a
f4be92 JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
f7af5a
7f3e87 #ifdef BMP_SUPPORTED
460662 JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
45ab0e JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
961662 JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
214166 JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
0cc420 JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
8d81ef JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
188c1c JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
d11854 JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
c0d462 JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
6a1aea JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
1f0918 JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
680bab #endif /* BMP_SUPPORTED */
20af5a
0fb775 #ifdef GIF_SUPPORTED
31a11b JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
763050 JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
b840ec JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
a4599e JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
62604d JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
17b83b JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
136b3e JMESSAGE(JTRC_GIF_BADVERSION,
c26730 ¤   ·"Warning: unexpected GIF version number '%c%c%c'")
49c2ae JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
1b6730 JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
10271c JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
40672f JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
22fd00 JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
1282ed JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
0a69f3 #endif /* GIF_SUPPORTED */
d4af5a
d8ee32 #ifdef PPM_SUPPORTED
--106d 0012212ad5740100008 Page 2 of cderror.h
37b6b0 JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
364eab JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
82396c JMESSAGE(JERR_PPM_NOT, "Not a PPM file")
e3b7a7 JMESSAGE(JTRC_PGM, "%ux%u PGM image")
eba988 JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
071f50 JMESSAGE(JTRC_PPM, "%ux%u PPM image")
d89767 JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
d3e76f #endif /* PPM_SUPPORTED */
daaf5a
ec7806 #ifdef RLE_SUPPORTED
e7578f JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
bc30bb JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
b0e10e JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
9bc2b0 JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
009f68 JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
546ea2 JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
4e9ce0 JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
bb748b JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
01a968 JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
b11a8c JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
358e54 JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
6c9206 JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
5a7bc8 JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
300b22 JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
554f2d #endif /* RLE_SUPPORTED */
a6af5a
bc46eb #ifdef TARGA_SUPPORTED
4cb308 JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
b9b2c9 JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
1ca795 JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
09970e JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
f98798 JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
8587fe JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
22db21 #else
f6d4f1 JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
4e7d96 #endif /* TARGA_SUPPORTED */
0daf5a
8011fd JMESSAGE(JERR_BAD_CMAP_FILE,
d5fa76 ¤   ·"Color map file is invalid or of unsupported format")
096b49 JMESSAGE(JERR_TOO_MANY_COLORS,
234cfb ¤   ·"Output file format cannot handle %d colormap entries")
8f8858 JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
6746eb #ifdef TARGA_SUPPORTED
d532e3 JMESSAGE(JERR_UNKNOWN_FORMAT,
f45203 ¤   ·"Unrecognized input file format --- perhaps you need -targa")
f9db21 #else
b7d942 JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
be7454 #endif
6568ad JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
22af5a
39e0f9 #ifdef JMAKE_ENUM_LIST
3daf5a
9c6469 ··JMSG_LASTADDONCODE
1243d6 } ADDON_MESSAGE_CODE;
91af5a
e14119 #undef JMAKE_ENUM_LIST
e3b694 #endif /* JMAKE_ENUM_LIST */
beaf5a
3a36e5 /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
22518a #undef JMESSAGE
--1e1e 0008aafc83040100009 Page 1 of ckconfig.c
bc38e5 /*
97d9f5 ·* ckconfig.c
c0775e ·*
e98ee3 ·* Copyright (C) 1991-1994, Thomas G. Lane.
b4fb07 ·* This file is part of the Independent JPEG Group's software.
44a0d6 ·* For conditions of distribution and use, see the accompanying README file.
f6495d ·*/
a4af5a
5a38e5 /*
b94242 ·* This program is intended to help you determine how to configure the JPEG
2a947e ·* software for installation on a particular system. ·The idea is to try to
e9643c ·* compile and execute this program. ·If your compiler fails to compile the
a0bc2d ·* program, make changes as indicated in the comments below. ·Once you can
61fe47 ·* compile the program, run it, and it will produce a "jconfig.h" file for
326881 ·* your system.
1a775e ·*
5116b8 ·* As a general rule, each time you try to compile this program,
af7fa4 ·* pay attention only to the *first* error message you get from the compiler.
ec6fe2 ·* Many C compilers will issue lots of spurious error messages once they
5d5a99 ·* have gotten confused. ·Go to the line indicated in the first error message,
e2311e ·* and read the comments preceding that line to see what to change.
0c775e ·*
8789e8 ·* Almost all of the edits you may need to make to this program consist of
9d08b9 ·* changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
a62293 ·* or vice versa. ·This is called defining or undefining that symbol.
c6495d ·*/
ffaf5a
7faf5a
04d995 /* First we must see if your system has the include files we need.
ae9f4c ·* We start out with the assumption that your system has all the ANSI-standard
655b66 ·* include files. ·If you get any error trying to include one of these files,
c37d11 ·* undefine the corresponding HAVE_xxx symbol.
83495d ·*/
06af5a
00e60c #define HAVE_STDDEF_H¤  ¤   /* replace 'define' by 'undef' if error here */
a14f35 #ifdef HAVE_STDDEF_H¤   ¤   /* next line will be skipped if you undef... */
807cab #include <stddef.h>
6d7454 #endif
32af5a
0007d6 #define HAVE_STDLIB_H¤  ¤   /* same thing for stdlib.h */
a7ef82 #ifdef HAVE_STDLIB_H
e0bea3 #include <stdlib.h>
057454 #endif
d1af5a
61e160 #include <stdio.h>¤ ¤   /* If you ain't got this, you ain't got C. */
d1af5a
625eb7 /* We have to see if your string functions are defined by
554826 ·* strings.h (old BSD convention) or string.h (everybody else).
1ac436 ·* We try the non-BSD convention first; define NEED_BSD_STRINGS
e45c0f ·* if the compiler says it can't find string.h.
29495d ·*/
19af5a
a677bb #undef NEED_BSD_STRINGS
50af5a
b39014 #ifdef NEED_BSD_STRINGS
35f7c3 #include <strings.h>
57db21 #else
ab324c #include <string.h>
5a7454 #endif
deaf5a
edbf88 /* On some systems (especially older Unix machines), type size_t is
dae605 ·* defined only in the include file <sys/types.h>. ·If you get a failure
f2cdf3 ·* on the size_t test below, try defining NEED_SYS_TYPES_H.
b5495d ·*/
ddaf5a
ae4713 #undef NEED_SYS_TYPES_H¤¤   /* start by assuming we don't need it */
47b6d1 #ifdef NEED_SYS_TYPES_H
c4f15e #include <sys/types.h>
9f7454 #endif
6daf5a
52af5a
8aa9ab /* Usually type size_t is defined in one of the include files we've included
--8600 0003e0e558f40100009 Page 2 of ckconfig.c
4304c2 ·* above. ·If not, you'll get an error on the "typedef size_t my_size_t;" line.
7f509a ·* In that case, first try defining NEED_SYS_TYPES_H just above.
5be513 ·* If that doesn't work, you'll have to search through your system library
891ef4 ·* to figure out which include file defines "size_t". ·Look for a line that
fae91e ·* says "typedef something-or-other size_t;". ·Then, change the line below
980112 ·* that says "#include <someincludefile.h>" to instead include the file
307886 ·* you found size_t in, and define NEED_SPECIAL_INCLUDE. ·If you can't find
5c2d2a ·* type size_t anywhere, try replacing "#include <someincludefile.h>" with
1926ce ·* "typedef unsigned int size_t;".
a1495d ·*/
ecaf5a
4592a0 #undef NEED_SPECIAL_INCLUDE¤/* assume we DON'T need it, for starters */
19af5a
e893f7 #ifdef NEED_SPECIAL_INCLUDE
e41aea #include <someincludefile.h>
747454 #endif
c6af5a
9bb6b8 typedef size_t my_size_t;¤  /* The payoff: do we have size_t now? */
dbaf5a
68af5a
6901f2 /* The next question is whether your compiler supports ANSI-style function
ba0f24 ·* prototypes. ·You need to know this in order to choose between using
ac4a55 ·* makefile.ansi and using makefile.unix.
4e6e7d ·* The #define line below is set to assume you have ANSI function prototypes.
4d74b9 ·* If you get an error in this group of lines, undefine HAVE_PROTOTYPES.
54495d ·*/
d1af5a
79dde9 #define HAVE_PROTOTYPES
caaf5a
4d6cff #ifdef HAVE_PROTOTYPES
dabe67 int testfunction (int arg1, int * arg2); /* check prototypes */
3eaf5a
fa1ca3 struct methods_struct {¤¤   /* check method-pointer declarations */
8f8943 ··int (*error_exit) (char *msgtext);
fb84e1 ··int (*trace_message) (char *msgtext);
9dd40e ··int (*another_method) (void);
9382f7 };
6faf5a
f20635 int testfunction (int arg1, int * arg2) /* check definitions */
42bb36 {
213e6b ··return arg2[arg1];
16efe6 }
83af5a
276805 int test2function (void)¤   /* check void arg list */
a4bb36 {
bf212b ··return 0;
deefe6 }
b17454 #endif
feaf5a
7faf5a
94ec0b /* Now we want to find out if your compiler knows what "unsigned char" means.
81ac49 ·* If you get an error on the "unsigned char un_char;" line,
d462c3 ·* then undefine HAVE_UNSIGNED_CHAR.
fb495d ·*/
1faf5a
0a616a #define HAVE_UNSIGNED_CHAR
beaf5a
8a1190 #ifdef HAVE_UNSIGNED_CHAR
8056fd unsigned char un_char;
147454 #endif
44af5a
e1af5a
dd31e3 /* Now we want to find out if your compiler knows what "unsigned short" means.
027bef ·* If you get an error on the "unsigned short un_short;" line,
91382f ·* then undefine HAVE_UNSIGNED_SHORT.
59495d ·*/
2daf5a
e9c672 #define HAVE_UNSIGNED_SHORT
a6af5a
549ed7 #ifdef HAVE_UNSIGNED_SHORT
efbbec unsigned short un_short;
3e7454 #endif
--c559 00079dc57d140100009 Page 3 of ckconfig.c
e0af5a
1aaf5a
42e1a2 /* Now we want to find out if your compiler understands type "void".
39bbf7 ·* If you get an error anywhere in here, undefine HAVE_VOID.
6a495d ·*/
e6af5a
e308d4 #define HAVE_VOID
c5af5a
9f01ad #ifdef HAVE_VOID
00b1cc /* Caution: a C++ compiler will insist on complete prototypes */
034070 typedef void * void_ptr;¤   /* check void * */
59bbc7 #ifdef HAVE_PROTOTYPES¤ ¤   /* check ptr to function returning void */
0f0a82 typedef void (*void_func) (int a, int b);
bcdb21 #else
b163bb typedef void (*void_func) ();
997454 #endif
a7af5a
3bd973 #ifdef HAVE_PROTOTYPES¤ ¤   /* check void function result */
80b97a void test3function (void_ptr arg1, void_func arg2)
d4db21 #else
420080 void test3function (arg1, arg2)
ef277b ·····void_ptr arg1;
46b344 ·····void_func arg2;
b97454 #endif
eebb36 {
6df383 ··char * locptr = (char *) arg1; /* check casting to and from void * */
4c5fee ··arg1 = (void *) locptr;
8c4676 ··(*arg2) (1, 2);¤  ¤   /* check call of fcn returning void */
f1efe6 }
b97454 #endif
22af5a
dcaf5a
6c30ce /* Now we want to find out if your compiler knows what "const" means.
37dd7f ·* If you get an error here, undefine HAVE_CONST.
69495d ·*/
56af5a
9e7e9a #define HAVE_CONST
00af5a
e490d5 #ifdef HAVE_CONST
29e145 static const int carray[3] = {1, 2, 3};
28af5a
ce6cff #ifdef HAVE_PROTOTYPES
d9bd75 int test4function (const int arg1)
b5db21 #else
9c1e05 int test4function (arg1)
4f3b9f ·····const int arg1;
dd7454 #endif
d8bb36 {
119d20 ··return carray[arg1];
b1efe6 }
617454 #endif
1aaf5a
f4af5a
be0954 /* If you get an error or warning about this structure definition,
7857c0 ·* define INCOMPLETE_TYPES_BROKEN.
58495d ·*/
ebaf5a
a7e0cc #undef INCOMPLETE_TYPES_BROKEN
e0af5a
43ce4c #ifndef INCOMPLETE_TYPES_BROKEN
a32ed9 typedef struct undefined_structure * undef_struct_ptr;
ce7454 #endif
acaf5a
26af5a
215d8f /* If you get an error about duplicate names,
971b9d ·* define NEED_SHORT_EXTERNAL_NAMES.
6e495d ·*/
dcaf5a
07fcf2 #undef NEED_SHORT_EXTERNAL_NAMES
f1af5a
00b842 #ifndef NEED_SHORT_EXTERNAL_NAMES
79af5a
--3b2a 0008b52b91b40100009 Page 4 of ckconfig.c
273132 int possibly_duplicate_function ()
3fbb36 {
d1212b ··return 0;
78efe6 }
4eaf5a
7ea417 int possibly_dupli_function ()
6dbb36 {
cf7bf7 ··return 1;
55efe6 }
d4af5a
3b7454 #endif
28af5a
10af5a
f9af5a
f01cf3 /************************************************************************
b27041 ·* ·OK, that's it. ·You should not have to change anything beyond this
6f2558 ·* ·point in order to compile and execute this program. ·(You might get
f2d584 ·* ·some warnings, but you can ignore them.)
03a899 ·* ·When you run the program, it will make a couple more tests that it
d5e760 ·* ·can do automatically, and then it will create jconfig.h and print out
c06314 ·* ·any additional suggestions it has.
9f39e4 ·************************************************************************
5f495d ·*/
8aaf5a
b8af5a
3c6cff #ifdef HAVE_PROTOTYPES
0bb5aa int is_char_signed (int arg)
a4db21 #else
e502c6 int is_char_signed (arg)
4499a1 ·····int arg;
437454 #endif
bcbb36 {
0428e4 ··if (arg == 189) {¤¤   /* expected result for unsigned char */
67a9bc ····return 0;¤  ¤   ¤   /* type char is unsigned */
6fdf1c ··}
f1363b ··else if (arg != -67) {¤   /* expected result for signed char */
0b9d7a ····printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
6863e7 ····printf("I fear the JPEG software will not work at all.\n\n");
85df1c ··}
c1f8b3 ··return 1;¤¤   ¤   /* assume char is signed otherwise */
35efe6 }
b7af5a
9aaf5a
766cff #ifdef HAVE_PROTOTYPES
57e2a6 int is_shifting_signed (long arg)
c3db21 #else
65d491 int is_shifting_signed (arg)
c53c09 ·····long arg;
787454 #endif
f6cdbb /* See whether right-shift on a long is signed or not. */
dcbb36 {
7b4fc0 ··long res = arg >> 4;
e7af5a
6e1b1e ··if (res == -0x7F7E80CL) {¤/* expected result for signed shift */
969999 ····return 1;¤  ¤   ¤   /* right shift is signed */
09df1c ··}
b21221 ··/* see if unsigned-shift hack will fix it. */
29a4cf ··/* we can't just test exact value since it depends on width of long... */
501ce2 ··res |= (~0L) << (32-4);
3d2a0a ··if (res == -0x7F7E80CL) {¤/* expected result now? */
2c6e59 ····return 0;¤  ¤   ¤   /* right shift is unsigned */
f5df1c ··}
829866 ··printf("Right shift isn't acting as I expect it to.\n");
05d114 ··printf("I fear the JPEG software will not work at all.\n\n");
9d046d ··return 0;¤¤   ¤   /* try it with unsigned anyway */
f5efe6 }
20af5a
65af5a
346cff #ifdef HAVE_PROTOTYPES
ef9c3f int main (int argc, char ** argv)
75db21 #else
8bd8d1 int main (argc, argv)
--18e9 000001e31a840100009 Page 5 of ckconfig.c
d6f11b ·····int argc;
19b091 ·····char ** argv;
e17454 #endif
4ebb36 {
260343 ··char signed_char_check = (char) (-67);
f6154a ··FILE *outfile;
fbaf5a
5f7631 ··/* Attempt to write jconfig.h */
32eb21 ··if ((outfile = fopen("jconfig.h", "w")) == NULL) {
fadfae ····printf("Failed to write jconfig.h\n");
0ccf57 ····return 1;
3adf1c ··}
9baf5a
24f591 ··/* Write out all the info */
bc86c2 ··fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n");
6bfc11 ··fprintf(outfile, "/* see jconfig.doc for explanations */\n\n");
436cff #ifdef HAVE_PROTOTYPES
4eb864 ··fprintf(outfile, "#define HAVE_PROTOTYPES\n");
49db21 #else
112c70 ··fprintf(outfile, "#undef HAVE_PROTOTYPES\n");
807454 #endif
6d1190 #ifdef HAVE_UNSIGNED_CHAR
cd3d27 ··fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n");
c6db21 #else
15a5ee ··fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n");
507454 #endif
129ed7 #ifdef HAVE_UNSIGNED_SHORT
98a870 ··fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n");
56db21 #else
8af325 ··fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n");
047454 #endif
4a01ad #ifdef HAVE_VOID
596aab ··fprintf(outfile, "/* #define void char */\n");
70db21 #else
c2600b ··fprintf(outfile, "#define void char\n");
497454 #endif
c790d5 #ifdef HAVE_CONST
f17f51 ··fprintf(outfile, "/* #define const */\n");
e9db21 #else
f3c630 ··fprintf(outfile, "#define const\n");
3f7454 #endif
a36178 ··if (is_char_signed((int) signed_char_check))
90fb2a ····fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n");
661bd0 ··else
b41719 ····fprintf(outfile, "#define CHAR_IS_UNSIGNED\n");
77cb06 #ifdef HAVE_STDDEF_H
c9d680 ··fprintf(outfile, "#define HAVE_STDDEF_H\n");
6cdb21 #else
018789 ··fprintf(outfile, "#undef HAVE_STDDEF_H\n");
8b7454 #endif
a4ef82 #ifdef HAVE_STDLIB_H
308c7a ··fprintf(outfile, "#define HAVE_STDLIB_H\n");
c3db21 #else
10dd73 ··fprintf(outfile, "#undef HAVE_STDLIB_H\n");
2c7454 #endif
359014 #ifdef NEED_BSD_STRINGS
44f32c ··fprintf(outfile, "#define NEED_BSD_STRINGS\n");
b5db21 #else
c9a51d ··fprintf(outfile, "#undef NEED_BSD_STRINGS\n");
b17454 #endif
ebb6d1 #ifdef NEED_SYS_TYPES_H
605ac6 ··fprintf(outfile, "#define NEED_SYS_TYPES_H\n");
a8db21 #else
3a0cf7 ··fprintf(outfile, "#undef NEED_SYS_TYPES_H\n");
9b7454 #endif
c42e0f ··fprintf(outfile, "#undef NEED_FAR_POINTERS\n");
95ddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
922a02 ··fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n");
c3db21 #else
fa4c6a ··fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n");
157454 #endif
008264 #ifdef INCOMPLETE_TYPES_BROKEN
--241b 001ebc98d5d40100009 Page 6 of ckconfig.c
be4b72 ··fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n");
52db21 #else
945a76 ··fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n");
c97454 #endif
15c6d8 ··fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n");
ac76bb ··if (is_shifting_signed(-0x7F7E80B1L))
ac1352 ····fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n");
671bd0 ··else
5ede91 ····fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n");
2e569f ··fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n");
47e932 ··fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n");
5124d6 ··fprintf(outfile, "#define BMP_SUPPORTED¤  ¤   /* BMP image file format */\n");
213259 ··fprintf(outfile, "#define GIF_SUPPORTED¤  ¤   /* GIF image file format */\n");
ebab0a ··fprintf(outfile, "#define PPM_SUPPORTED¤  ¤   /* PBMPLUS PPM/PGM image file f¶
6195ed ormat */\n");
ddfce9 ··fprintf(outfile, "#undef RLE_SUPPORTED¤   ¤   /* Utah RLE image file format *¶
561fb9 /\n");
efcae7 ··fprintf(outfile, "#define TARGA_SUPPORTED¤¤   /* Targa image file format */\n¶
7465ce \n");
5b28ee ··fprintf(outfile, "#undef TWO_FILE_COMMANDLINE¤/* You may need this on non-Uni¶
aada97 x systems */\n");
e13ee5 ··fprintf(outfile, "#undef NEED_SIGNAL_CATCHER¤ /* Define this if you use jmemn¶
c3d61a ame.c */\n");
3ee3b3 ··fprintf(outfile, "#undef DONT_USE_B_MODE\n");
5056fe ··fprintf(outfile, "/* #define PROGRESS_REPORT */¤  /* optional */\n");
fddc37 ··fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n");
0aaf5a
4e05d3 ··/* Close the jconfig.h file */
ac55cf ··fclose(outfile);
b4af5a
856b96 ··/* User report */
7d0dc2 ··printf("Configuration check for Independent JPEG Group's software done.\n");
06cf75 ··printf("\nI have written the jconfig.h file for you.\n\n");
d16cff #ifdef HAVE_PROTOTYPES
a61bc7 ··printf("You should use makefile.ansi as the starting point for your Makefile.¶
2365ce \n");
83db21 #else
730048 ··printf("You should use makefile.unix as the starting point for your Makefile.¶
c465ce \n");
687454 #endif
84af5a
da93f7 #ifdef NEED_SPECIAL_INCLUDE
1b17ea ··printf("\nYou'll need to change jconfig.h to include the system include file\¶
87145b n");
2108ec ··printf("that you found type size_t in, or add a direct definition of type\n");
c56d0a ··printf("size_t if that's what you used. ·Just add it to the end.\n");
a77454 #endif
1eaf5a
6c212b ··return 0;
ebefe6 }
--8ff4 0000dc165cc4010000a Page 1 of jcapimin.c
bc38e5 /*
a63b89 ·* jcapimin.c
10775e ·*
789e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
64fb07 ·* This file is part of the Independent JPEG Group's software.
a0a0d6 ·* For conditions of distribution and use, see the accompanying README file.
81775e ·*
a4fa87 ·* This file contains application interface code for the compression half
c19df1 ·* of the JPEG library. ·These are the "minimum" API routines that may be
65a908 ·* needed in either the normal full-compression case or the transcoding-only
72a202 ·* case.
ac775e ·*
52304d ·* Most of the routines intended to be called directly by an application
7b0dc1 ·* are in this file or in jcapistd.c. ·But also see jcparam.c for
be270f ·* parameter-setup helper routines, jcomapi.c for routines shared by
d8b58a ·* compression and decompression, and jctrans.c for the transcoding case.
86495d ·*/
43af5a
f52bb6 #define JPEG_INTERNALS
ad36a7 #include "jinclude.h"
7b6c8f #include "jpeglib.h"
e4af5a
b7af5a
2538e5 /*
0d445c ·* Initialization of a JPEG compression object.
c29213 ·* The error manager must already be set up (in case memory manager fails).
09495d ·*/
16af5a
6df898 GLOBAL(void)
35eded jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
07bb36 {
2117e0 ··int i;
e7af5a
258935 ··/* Guard against version mismatches between library and caller. */
b1962d ··cinfo->mem = NULL;¤   ¤   /* so jpeg_destroy knows mem mgr not called */
757a94 ··if (version != JPEG_LIB_VERSION)
72ab37 ····ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
d3796a ··if (structsize != SIZEOF(struct jpeg_compress_struct))
52f695 ····ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,·
1824c0 ¤   ·····(int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
ecaf5a
9de883 ··/* For debugging purposes, zero the whole master structure.
15bc85 ···* But error manager pointer is already there, so save and restore it.
38f9a6 ···*/
6e8bcc ··{
1bde0a ····struct jpeg_error_mgr * err = cinfo->err;
ee2faf ····MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
3eea0e ····cinfo->err = err;
bbdf1c ··}
64d57b ··cinfo->is_decompressor = FALSE;
2aaf5a
0e1275 ··/* Initialize a memory manager instance for this object */
cfd00c ··jinit_memory_mgr((j_common_ptr) cinfo);
28af5a
21a71f ··/* Zero out pointers to permanent structures. */
e631d3 ··cinfo->progress = NULL;
b779e5 ··cinfo->dest = NULL;
44af5a
b8df41 ··cinfo->comp_info = NULL;
84af5a
86dce1 ··for (i = 0; i < NUM_QUANT_TBLS; i++)
c5d301 ····cinfo->quant_tbl_ptrs[i] = NULL;
ebaf5a
e872db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
1e5c2e ····cinfo->dc_huff_tbl_ptrs[i] = NULL;
55b27b ····cinfo->ac_huff_tbl_ptrs[i] = NULL;
dddf1c ··}
5daf5a
9715aa ··cinfo->input_gamma = 1.0;¤/* in case application forgets */
1faf5a
34dfd2 ··/* OK, I'm ready */
0d36af ··cinfo->global_state = CSTATE_START;
--a4a0 0006cf11d144010000a Page 2 of jcapimin.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
e8fb74 ·* Destruction of a JPEG compression object
4e495d ·*/
3faf5a
68f898 GLOBAL(void)
799af9 jpeg_destroy_compress (j_compress_ptr cinfo)
36bb36 {
599b5e ··jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
67efe6 }
48af5a
03af5a
1238e5 /*
d15688 ·* Abort processing of a JPEG compression operation,
e8292b ·* but don't destroy the object itself.
52495d ·*/
3caf5a
b6f898 GLOBAL(void)
d2b173 jpeg_abort_compress (j_compress_ptr cinfo)
91bb36 {
64093b ··jpeg_abort((j_common_ptr) cinfo); /* use common routine */
bfefe6 }
48af5a
98af5a
a738e5 /*
541444 ·* Forcibly suppress or un-suppress all quantization and Huffman tables.
44b9d6 ·* Marks all currently defined tables as already written (if suppress)
5c106c ·* or not written (if !suppress). ·This will control whether they get emitted
330bb6 ·* by a subsequent jpeg_start_compress call.
a1775e ·*
a5cda4 ·* This routine is exported for use by applications that want to produce
95d68d ·* abbreviated JPEG datastreams. ·It logically belongs in jcparam.c, but
08e932 ·* since it is called by jpeg_start_compress, we put it here --- otherwise
9201d0 ·* jcparam.o would be linked whether the application used it or not.
d1495d ·*/
4faf5a
bff898 GLOBAL(void)
ad3b45 jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
64bb36 {
6717e0 ··int i;
6c4504 ··JQUANT_TBL * qtbl;
7fa9a2 ··JHUFF_TBL * htbl;
e9af5a
c627d7 ··for (i = 0; i < NUM_QUANT_TBLS; i++) {
e1168f ····if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
32f37e ······qtbl->sent_table = suppress;
20df1c ··}
82af5a
5872db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
0e363d ····if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
6e105f ······htbl->sent_table = suppress;
d89502 ····if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
b9105f ······htbl->sent_table = suppress;
32df1c ··}
28efe6 }
baaf5a
0daf5a
5938e5 /*
49b978 ·* Finish JPEG compression.
60775e ·*
0f843b ·* If a multipass operating mode was selected, this may do a great deal of
c6a8ed ·* work including most of the actual output.
14495d ·*/
ddaf5a
06f898 GLOBAL(void)
14a5c3 jpeg_finish_compress (j_compress_ptr cinfo)
dcbb36 {
b94f89 ··JDIMENSION iMCU_row;
2caf5a
6cb981 ··if (cinfo->global_state == CSTATE_SCANNING ||
--fe71 0004c063fb34010000a Page 3 of jcapimin.c
8c6e04 ······cinfo->global_state == CSTATE_RAW_OK) {
3c394a ····/* Terminate first pass */
4880a6 ····if (cinfo->next_scanline < cinfo->image_height)
0d726f ······ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
29daaa ····(*cinfo->master->finish_pass) (cinfo);
db9ca1 ··} else if (cinfo->global_state != CSTATE_WRCOEFS)
42918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
a5badb ··/* Perform any remaining passes */
e97c0e ··while (! cinfo->master->is_last_pass) {
812f2d ····(*cinfo->master->prepare_for_pass) (cinfo);
4e1a26 ····for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
eec37e ······if (cinfo->progress != NULL) {
1eb14b ¤   cinfo->progress->pass_counter = (long) iMCU_row;
4cb838 ¤   cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
9c798e ¤   (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
5242cc ······}
6aef7c ······/* We bypass the main controller and invoke coef controller directly;
ce3686 ·······* all work is being done from the coefficient buffer.
dee9f1 ·······*/
fa21e3 ······if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
2fd4ad ¤   ERREXIT(cinfo, JERR_CANT_SUSPEND);
4a6fe7 ····}
8edaaa ····(*cinfo->master->finish_pass) (cinfo);
26df1c ··}
97f715 ··/* Write EOI, do final cleanup */
39accb ··(*cinfo->marker->write_file_trailer) (cinfo);
67b4c1 ··(*cinfo->dest->term_destination) (cinfo);
e6617f ··/* We can use jpeg_abort to release memory and reset global_state */
3836ea ··jpeg_abort((j_common_ptr) cinfo);
71efe6 }
0faf5a
3eaf5a
de38e5 /*
6b1d6d ·* Write a special marker.
49403c ·* This is only recommended for writing COM or APPn markers.
99f441 ·* Must be called after jpeg_start_compress() and before
3cd519 ·* first call to jpeg_write_scanlines() or jpeg_write_raw_data().
0f495d ·*/
7daf5a
77f898 GLOBAL(void)
a2e131 jpeg_write_marker (j_compress_ptr cinfo, int marker,
02c772 ¤   ¤   ···const JOCTET *dataptr, unsigned int datalen)
b1bb36 {
6f7e44 ··if (cinfo->next_scanline != 0 ||
37b909 ······(cinfo->global_state != CSTATE_SCANNING &&
05faaf ·······cinfo->global_state != CSTATE_RAW_OK &&
b95415 ·······cinfo->global_state != CSTATE_WRCOEFS))
65918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
13af5a
ec86d7 ··(*cinfo->marker->write_any_marker) (cinfo, marker, dataptr, datalen);
45efe6 }
faaf5a
e7af5a
3538e5 /*
e1b6fb ·* Alternate compression function: just write an abbreviated table file.
eddfd1 ·* Before calling this, all parameters and a data destination must be set up.
e3775e ·*
eac7fa ·* To produce a pair of files containing abbreviated tables and abbreviated
8f8220 ·* image data, one would proceed as follows:
8f775e ·*
302cee ·*¤ ¤   initialize JPEG object
fac5f7 ·*¤ ¤   set JPEG parameters
998e46 ·*¤ ¤   set destination to table file
da12d0 ·*¤ ¤   jpeg_write_tables(cinfo);
8de0b3 ·*¤ ¤   set destination to image file
d4a765 ·*¤ ¤   jpeg_start_compress(cinfo, FALSE);
91fb11 ·*¤ ¤   write data...
b40e6f ·*¤ ¤   jpeg_finish_compress(cinfo);
fd775e ·*
e05a7e ·* jpeg_write_tables has the side effect of marking all tables written
2f9687 ·* (same as jpeg_suppress_tables(..., TRUE)). ·Thus a subsequent start_compress
4c1140 ·* will not re-emit the tables unless it is passed write_all_tables=TRUE.
--cacb 00187206f924010000a Page 4 of jcapimin.c
47495d ·*/
44af5a
06f898 GLOBAL(void)
e7fbe5 jpeg_write_tables (j_compress_ptr cinfo)
17bb36 {
ff5278 ··if (cinfo->global_state != CSTATE_START)
cd918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
e9af5a
4fa69f ··/* (Re)initialize error mgr and destination modules */
cfc167 ··(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
5f49be ··(*cinfo->dest->init_destination) (cinfo);
b9a7e2 ··/* Initialize the marker writer ... bit of a crock to do it here. */
b76557 ··jinit_marker_writer(cinfo);
80d1d1 ··/* Write them tables! */
3ac847 ··(*cinfo->marker->write_tables_only) (cinfo);
64100b ··/* And clean up. */
b4b4c1 ··(*cinfo->dest->term_destination) (cinfo);
3bfee3 ··/* We can use jpeg_abort to release memory. */
ce36ea ··jpeg_abort((j_common_ptr) cinfo);
87efe6 }
--2aed 0001dda9cd54010000b Page 1 of jcapistd.c
bc38e5 /*
685401 ·* jcapistd.c
37775e ·*
0a9e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
c5fb07 ·* This file is part of the Independent JPEG Group's software.
a4a0d6 ·* For conditions of distribution and use, see the accompanying README file.
b2775e ·*
acfa87 ·* This file contains application interface code for the compression half
aabf5c ·* of the JPEG library. ·These are the "standard" API routines that are
7b2c20 ·* used in the normal full-compression case. ·They are not used by a
2c3ade ·* transcoding-only application. ·Note that if an application links in
1a692c ·* jpeg_start_compress, it will end up linking in the entire compressor.
950ad5 ·* We thus must separate this file from jcapimin.c to avoid linking the
7a49ef ·* whole compression library into a transcoder.
cf495d ·*/
d9af5a
6a2bb6 #define JPEG_INTERNALS
7d36a7 #include "jinclude.h"
936c8f #include "jpeglib.h"
83af5a
1daf5a
3638e5 /*
4f5ffc ·* Compression initialization.
74dfd1 ·* Before calling this, all parameters and a data destination must be set up.
61775e ·*
505510 ·* We require a write_all_tables parameter as a failsafe check when writing
c5e83e ·* multiple datastreams from the same compression object. ·Since prior runs
1ddc0d ·* will have left all the tables marked sent_table=TRUE, a subsequent run
7dfba0 ·* would emit an abbreviated stream (no tables) by default. ·This may be what
7b51bf ·* is wanted, but for safety's sake it should not be the default behavior:
2b25d5 ·* programmers should have to make a deliberate choice to emit abbreviated
6a2895 ·* images. ·Therefore the documentation and examples should encourage people
94b6c4 ·* to pass write_all_tables=TRUE; then it will take active thought to do the
a02b63 ·* wrong thing.
6b495d ·*/
30af5a
a8f898 GLOBAL(void)
32654c jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
20bb36 {
775278 ··if (cinfo->global_state != CSTATE_START)
69918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
5daf5a
16bcf1 ··if (write_all_tables)
848c85 ····jpeg_suppress_tables(cinfo, FALSE);¤/* mark all tables to be written */
3caf5a
1fa69f ··/* (Re)initialize error mgr and destination modules */
46c167 ··(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
9f49be ··(*cinfo->dest->init_destination) (cinfo);
f1322e ··/* Perform master selection of active modules */
4c23fc ··jinit_compress_master(cinfo);
735477 ··/* Set up for the first pass */
10b8ae ··(*cinfo->master->prepare_for_pass) (cinfo);
bf9317 ··/* Ready for application to drive first pass through jpeg_write_scanlines
b33b42 ···* or jpeg_write_raw_data.
4cf9a6 ···*/
f07a6f ··cinfo->next_scanline = 0;
57f347 ··cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
f4efe6 }
83af5a
96af5a
6c38e5 /*
166348 ·* Write some scanlines of data to the JPEG compressor.
58775e ·*
bba9f3 ·* The return value will be the number of lines actually written.
e440f4 ·* This should be less than the supplied num_lines only in case that
d53249 ·* the data destination module has requested suspension of the compressor,
749740 ·* or if more than image_height scanlines are passed in.
d1775e ·*
d554e1 ·* Note: we warn about excess calls to jpeg_write_scanlines() since
f2e0bf ·* this likely signals an application programmer error. ·However,
a8d564 ·* excess scanlines passed in the last valid call are *silently* ignored,
1d70f3 ·* so that the application need not adjust num_lines for end-of-image
--10be 000cc8fb0b54010000b Page 2 of jcapistd.c
91ab10 ·* when using a multiple-scanline buffer.
68495d ·*/
8daf5a
4e2e0d GLOBAL(JDIMENSION)
847208 jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
84c252 ¤   ¤   ······JDIMENSION num_lines)
95bb36 {
320af3 ··JDIMENSION row_ctr, rows_left;
43af5a
4bcb2c ··if (cinfo->global_state != CSTATE_SCANNING)
0c918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
c22bce ··if (cinfo->next_scanline >= cinfo->image_height)
4444d3 ····WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
d3af5a
942358 ··/* Call progress monitor hook if present */
d9feda ··if (cinfo->progress != NULL) {
8d3852 ····cinfo->progress->pass_counter = (long) cinfo->next_scanline;
771ef5 ····cinfo->progress->pass_limit = (long) cinfo->image_height;
e424e5 ····(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
45df1c ··}
88af5a
e8153a ··/* Give master control module another chance if this is first call to
7b9a27 ···* jpeg_write_scanlines. ·This lets output of the frame/scan headers be
02abf0 ···* delayed so that application can write COM, etc, markers between
21277b ···* jpeg_start_compress and jpeg_write_scanlines.
31f9a6 ···*/
25c406 ··if (cinfo->master->call_pass_startup)
d23e68 ····(*cinfo->master->pass_startup) (cinfo);
77af5a
08d4fe ··/* Ignore any extra scanlines at bottom of image. */
9e3892 ··rows_left = cinfo->image_height - cinfo->next_scanline;
b725d8 ··if (num_lines > rows_left)
1497b9 ····num_lines = rows_left;
93af5a
b6a0dd ··row_ctr = 0;
7209a4 ··(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
4b307c ··cinfo->next_scanline += row_ctr;
da8853 ··return row_ctr;
56efe6 }
c2af5a
0eaf5a
db38e5 /*
a08178 ·* Alternate entry point to write raw data.
bd07f5 ·* Processes exactly one iMCU row per call, unless suspended.
81495d ·*/
a6af5a
612e0d GLOBAL(JDIMENSION)
e6fbf7 jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
1ca49e ¤   ¤   ·····JDIMENSION num_lines)
a0bb36 {
3d2af5 ··JDIMENSION lines_per_iMCU_row;
f1af5a
ea0836 ··if (cinfo->global_state != CSTATE_RAW_OK)
2d918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
e5041c ··if (cinfo->next_scanline >= cinfo->image_height) {
9944d3 ····WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
7a958b ····return 0;
4bdf1c ··}
64af5a
722358 ··/* Call progress monitor hook if present */
a0feda ··if (cinfo->progress != NULL) {
163852 ····cinfo->progress->pass_counter = (long) cinfo->next_scanline;
381ef5 ····cinfo->progress->pass_limit = (long) cinfo->image_height;
0824e5 ····(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
88df1c ··}
24af5a
37153a ··/* Give master control module another chance if this is first call to
41e087 ···* jpeg_write_raw_data. ·This lets output of the frame/scan headers be
aaabf0 ···* delayed so that application can write COM, etc, markers between
8df278 ···* jpeg_start_compress and jpeg_write_raw_data.
d4f9a6 ···*/
ccc406 ··if (cinfo->master->call_pass_startup)
--6842 001e91ca9c44010000b Page 3 of jcapistd.c
663e68 ····(*cinfo->master->pass_startup) (cinfo);
dbaf5a
3eb65a ··/* Verify that at least one iMCU row has been passed. */
88e5b2 ··lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
7d4792 ··if (num_lines < lines_per_iMCU_row)
0d53f5 ····ERREXIT(cinfo, JERR_BUFFER_SIZE);
44af5a
0e2636 ··/* Directly compress the row. */
4b2c37 ··if (! (*cinfo->coef->compress_data) (cinfo, data)) {
5cb732 ····/* If compressor did not consume the whole row, suspend processing. */
01958b ····return 0;
5edf1c ··}
30af5a
ca03b6 ··/* OK, we processed one iMCU row. */
6ab5d1 ··cinfo->next_scanline += lines_per_iMCU_row;
66fe2f ··return lines_per_iMCU_row;
e9efe6 }
--1b72 00006a064454010000c Page 1 of jccoefct.c
bc38e5 /*
f585a1 ·* jccoefct.c
0b775e ·*
759e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
9dfb07 ·* This file is part of the Independent JPEG Group's software.
04a0d6 ·* For conditions of distribution and use, see the accompanying README file.
38775e ·*
8ede91 ·* This file contains the coefficient buffer controller for compression.
d22834 ·* This controller is the top level of the JPEG compressor proper.
91023d ·* The coefficient buffer lies between forward-DCT and entropy encoding steps.
55495d ·*/
6daf5a
e02bb6 #define JPEG_INTERNALS
a236a7 #include "jinclude.h"
226c8f #include "jpeglib.h"
80af5a
11af5a
0e0017 /* We use a full-image coefficient buffer when doing Huffman optimization,
8ee995 ·* and also for writing multiple-scan JPEG files. ·In all cases, the DCT
c6b1cc ·* step is run during the first pass, and subsequent passes need only read
ba1a0e ·* the buffered coefficients.
5b495d ·*/
4b26f0 #ifdef ENTROPY_OPT_SUPPORTED
99e7f8 #define FULL_COEF_BUFFER_SUPPORTED
05db21 #else
56da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
0ce7f8 #define FULL_COEF_BUFFER_SUPPORTED
9d7454 #endif
687454 #endif
37af5a
51af5a
f98416 /* Private buffer controller object */
67af5a
63f0f7 typedef struct {
5f0f8d ··struct jpeg_c_coef_controller pub; /* public fields */
9eaf5a
553f4e ··JDIMENSION iMCU_row_num;¤ /* iMCU row # within image */
00a8a6 ··JDIMENSION mcu_ctr;¤  ¤   /* counts MCUs processed in current row */
85c7f6 ··int MCU_vert_offset;¤ ¤   /* counts MCU rows within iMCU row */
550fac ··int MCU_rows_per_iMCU_row;¤   /* number of such rows needed */
4caf5a
fad6a4 ··/* For single-pass compression, it's sufficient to buffer just one MCU
df2337 ···* (although this may prove a bit slow in practice). ·We allocate a
a1973d ···* workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
c8c4e5 ···* MCU constructed and sent. ·(On 80x86, the workspace is FAR even though
830c12 ···* it's not really very big; this is to keep the module interfaces unchanged
c56a98 ···* when a large coefficient buffer is necessary.)
ea4ae3 ···* In multi-pass modes, this array points to the current MCU's blocks
9bf61a ···* within the virtual arrays.
84f9a6 ···*/
fd7d86 ··JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
c3af5a
d1523e ··/* In multi-pass modes, we need a virtual block array for each component. */
7993fc ··jvirt_barray_ptr whole_image[MAX_COMPONENTS];
02c38c } my_coef_controller;
fbaf5a
5bcf47 typedef my_coef_controller * my_coef_ptr;
86af5a
1baf5a
dc6a43 /* Forward declarations */
3eea05 METHODDEF(boolean) compress_data
c3730d ····JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
5393fc #ifdef FULL_COEF_BUFFER_SUPPORTED
a925a9 METHODDEF(boolean) compress_first_pass
1d730d ····JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
933f89 METHODDEF(boolean) compress_output
a8730d ····JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
7c7454 #endif
30af5a
abaf5a
a4afad LOCAL(void)
06adc8 start_iMCU_row (j_compress_ptr cinfo)
--357b 000443ffab14010000c Page 2 of jccoefct.c
1078a6 /* Reset within-iMCU-row counters for a new row */
79bb36 {
fe7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
d5af5a
fb57ee ··/* In an interleaved scan, an MCU row is the same as an iMCU row.
1d9ae6 ···* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
195867 ···* But at the bottom of the image, process only what's left.
5df9a6 ···*/
621aae ··if (cinfo->comps_in_scan > 1) {
4833a9 ····coef->MCU_rows_per_iMCU_row = 1;
a249d8 ··} else {
1a7392 ····if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
3a1b09 ······coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
bc842c ····else
c2ced2 ······coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
6adf1c ··}
99af5a
d90b2e ··coef->mcu_ctr = 0;
00f553 ··coef->MCU_vert_offset = 0;
b0efe6 }
52af5a
36af5a
dd38e5 /*
215b80 ·* Initialize for a processing pass.
76495d ·*/
60af5a
560434 METHODDEF(void)
6755be start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
c8bb36 {
0b7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
50af5a
3c9dd8 ··coef->iMCU_row_num = 0;
513d6b ··start_iMCU_row(cinfo);
99af5a
061eec ··switch (pass_mode) {
fe972e ··case JBUF_PASS_THRU:
77d6bf ····if (coef->whole_image[0] != NULL)
670c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
7a4940 ····coef->pub.compress_data = compress_data;
79ab40 ····break;
5d93fc #ifdef FULL_COEF_BUFFER_SUPPORTED
9ae8d2 ··case JBUF_SAVE_AND_PASS:
a96904 ····if (coef->whole_image[0] == NULL)
cd0c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
347487 ····coef->pub.compress_data = compress_first_pass;
5cab40 ····break;
256409 ··case JBUF_CRANK_DEST:
0c6904 ····if (coef->whole_image[0] == NULL)
c60c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
c68e12 ····coef->pub.compress_data = compress_output;
abab40 ····break;
397454 #endif
25969d ··default:
96650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
01ab40 ····break;
17df1c ··}
7defe6 }
baaf5a
37af5a
ad38e5 /*
135624 ·* Process some data in the single-pass case.
544e35 ·* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
08ed29 ·* per call, ie, v_samp_factor block rows for each component in the image.
e2ea83 ·* Returns TRUE if the iMCU row is completed, FALSE if suspended.
0a775e ·*
09c467 ·* NB: input_buf contains a plane for each component in image.
06ac4a ·* For single pass, this is the same as the components in the scan.
75495d ·*/
3faf5a
a79a8f METHODDEF(boolean)
b9e91d compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
44bb36 {
--8831 000f28745d54010000c Page 3 of jccoefct.c
e27924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
4a2df3 ··JDIMENSION MCU_col_num;¤  /* index of current MCU within row */
75b9a6 ··JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
bfe5c0 ··JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
c56256 ··int blkn, bi, ci, yindex, yoffset, blockcnt;
459974 ··JDIMENSION ypos, xpos;
3433b0 ··jpeg_component_info *compptr;
29af5a
dbefb8 ··/* Loop to write as much as one whole iMCU row */
11a27a ··for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
7bbd1b ·······yoffset++) {
041e36 ····for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
6d2288 ¤   ·MCU_col_num++) {
8c9e14 ······/* Determine where data comes from in input_buf and do the DCT thing.
467096 ·······* Each call on forward_DCT processes a horizontal row of DCT blocks
5d2a6d ·······* as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
2d274d ·······* sequentially. ·Dummy blocks at the right or bottom edge are filled in
879029 ·······* specially. ·The data in them does not matter for image reconstruction,
e49838 ·······* so we fill them with values that will encode to the smallest amount of
6f04fe ·······* data, viz: all zeroes in the AC entries, DC entries equal to previous
d2bf95 ·······* block's DC value. ·(Thanks to Thomas Kinsman for this idea.)
bfe9f1 ·······*/
b020a6 ······blkn = 0;
236064 ······for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
5108f5 ¤   compptr = cinfo->cur_comp_info[ci];
c3458b ¤   blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
207d55 ¤   ¤   ¤   ¤   ¤   ¤   : compptr->last_col_width;
a83a36 ¤   xpos = MCU_col_num * compptr->MCU_sample_width;
50a09e ¤   ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
3076a3 ¤   for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
14b7d4 ¤   ··if (coef->iMCU_row_num < last_iMCU_row ||
e7553a ¤   ······yoffset+yindex < compptr->last_row_height) {
8d4f85 ¤   ····(*cinfo->fdct->forward_DCT) (cinfo, compptr,
14b672 ¤   ¤   ¤   ¤   ¤   ·input_buf[ci], coef->MCU_buffer[blkn],
9a8fde ¤   ¤   ¤   ¤   ¤   ·ypos, xpos, (JDIMENSION) blockcnt);
c8e9ac ¤   ····if (blockcnt < compptr->MCU_width) {
bff7a2 ¤   ······/* Create some dummy blocks at the right edge of the image. */
fd5275 ¤   ······jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
7ae470 ¤   ¤   ¤   (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
9cd1ab ¤   ······for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
a37aa9 ¤   ¤   coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
e67bcc ¤   ······}
36f372 ¤   ····}
5b2862 ¤   ··} else {
15e9fd ¤   ····/* Create a row of dummy blocks at the bottom of the image. */
3cf7c9 ¤   ····jzero_far((void FAR *) coef->MCU_buffer[blkn],
ecc81e ¤   ¤   ······compptr->MCU_width * SIZEOF(JBLOCK));
5572f6 ¤   ····for (bi = 0; bi < compptr->MCU_width; bi++) {
e6af63 ¤   ······coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
7bf372 ¤   ····}
6f32a2 ¤   ··}
e2dec3 ¤   ··blkn += compptr->MCU_width;
ed7780 ¤   ··ypos += DCTSIZE;
289371 ¤   }
2a42cc ······}
97d828 ······/* Try to write the MCU. ·In event of a suspension failure, we will
65c6ab ·······* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
b9e9f1 ·······*/
6b5379 ······if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
8c3fee ¤   /* Suspension forced; update state counters and exit */
edebe8 ¤   coef->MCU_vert_offset = yoffset;
ffeece ¤   coef->mcu_ctr = MCU_col_num;
fea230 ¤   return FALSE;
e242cc ······}
1a6fe7 ····}
cbb67f ····/* Completed an MCU row, but perhaps not an iMCU row */
610874 ····coef->mcu_ctr = 0;
ccdf1c ··}
2677d6 ··/* Completed the iMCU row, advance counters for next one */
4db60b ··coef->iMCU_row_num++;
493d6b ··start_iMCU_row(cinfo);
f2d2c8 ··return TRUE;
--6fc6 0001c0af90b4010000c Page 4 of jccoefct.c
7aefe6 }
46af5a
8eaf5a
db93fc #ifdef FULL_COEF_BUFFER_SUPPORTED
32af5a
2638e5 /*
c581bf ·* Process some data in the first pass of a multi-pass case.
3a4e35 ·* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
65ed29 ·* per call, ie, v_samp_factor block rows for each component in the image.
be59ed ·* This amount of data is read from the source buffer, DCT'd and quantized,
a787a4 ·* and saved into the virtual arrays. ·We also generate suitable dummy blocks
68ca63 ·* as needed at the right and lower edges. ·(The dummy blocks are constructed
eb1962 ·* in the virtual arrays, which have been padded appropriately.) ·This makes
89164d ·* it possible for subsequent passes not to worry about real vs. dummy blocks.
a8775e ·*
4e7e78 ·* We must also emit the data to the entropy encoder. ·This is conveniently
973858 ·* done by calling compress_output() after we've loaded the current strip
316b9a ·* of the virtual arrays.
02775e ·*
78d321 ·* NB: input_buf contains a plane for each component in image. ·All
d9bfc2 ·* components are DCT'd and loaded into the virtual arrays in this pass.
89b659 ·* However, it may be that only a subset of the components are emitted to
741a2d ·* the entropy encoder during this first pass; be careful about looking
00f5eb ·* at the scan-dependent variables (MCU dimensions, etc).
00495d ·*/
2baf5a
ce9a8f METHODDEF(boolean)
258582 compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
94bb36 {
9a7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
a9e5c0 ··JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
f473ff ··JDIMENSION blocks_across, MCUs_across, MCUindex;
8e679a ··int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
1c65de ··JCOEF lastDC;
b133b0 ··jpeg_component_info *compptr;
b0602e ··JBLOCKARRAY buffer;
21516a ··JBLOCKROW thisblockrow, lastblockrow;
70af5a
c7958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
efaa07 ·······ci++, compptr++) {
b9ac66 ····/* Align the virtual buffer for this component. */
44e56b ····buffer = (*cinfo->mem->access_virt_barray)
ac4d02 ······((j_common_ptr) cinfo, coef->whole_image[ci],
43f5ef ·······coef->iMCU_row_num * compptr->v_samp_factor,
e9c9b7 ·······(JDIMENSION) compptr->v_samp_factor, TRUE);
d92c22 ····/* Count non-dummy DCT block rows in this iMCU row. */
e765e1 ····if (coef->iMCU_row_num < last_iMCU_row)
bd1d98 ······block_rows = compptr->v_samp_factor;
0d83c8 ····else {
a6fc36 ······/* NB: can't use last_row_height here, since may not be set! */
dcad33 ······block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
b6837b ······if (block_rows == 0) block_rows = compptr->v_samp_factor;
3d6fe7 ····}
8960e8 ····blocks_across = compptr->width_in_blocks;
26a68d ····h_samp_factor = compptr->h_samp_factor;
05cda5 ····/* Count number of dummy blocks to be added at the right margin. */
b30796 ····ndummy = (int) (blocks_across % h_samp_factor);
881cc6 ····if (ndummy > 0)
5fd980 ······ndummy = h_samp_factor - ndummy;
49bb47 ····/* Perform DCT for all non-dummy blocks in this iMCU row. ·Each call
df6f35 ·····* on forward_DCT processes a complete horizontal row of DCT blocks.
79d48d ·····*/
847bcb ····for (block_row = 0; block_row < block_rows; block_row++) {
6cc97e ······thisblockrow = buffer[block_row];
a2ab43 ······(*cinfo->fdct->forward_DCT) (cinfo, compptr,
f7ec9e ¤   ¤   ¤   ¤   ···input_buf[ci], thisblockrow,
190f3f ¤   ¤   ¤   ¤   ···(JDIMENSION) (block_row * DCTSIZE),
211d26 ¤   ¤   ¤   ¤   ···(JDIMENSION) 0, blocks_across);
35723c ······if (ndummy > 0) {
a2dde9 ¤   /* Create dummy blocks at the right edge of the image. */
04c641 ¤   thisblockrow += blocks_across; /* => first dummy block */
1c198b ¤   jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
--4d9e 0000428d96b4010000c Page 5 of jccoefct.c
78136d ¤   lastDC = thisblockrow[-1][0];
8da188 ¤   for (bi = 0; bi < ndummy; bi++) {
4d8061 ¤   ··thisblockrow[bi][0] = lastDC;
759371 ¤   }
9142cc ······}
f86fe7 ····}
5a5bde ····/* If at end of image, create dummy block rows as needed.
848393 ·····* The tricky part here is that within each MCU, we want the DC values
2cc289 ·····* of the dummy blocks to match the last real block's DC value.
461b11 ·····* This squeezes a few more bytes out of the resulting file...
04d48d ·····*/
4abc8b ····if (coef->iMCU_row_num == last_iMCU_row) {
21a7cf ······blocks_across += ndummy;¤ /* include lower right corner */
976a60 ······MCUs_across = blocks_across / h_samp_factor;
a94331 ······for (block_row = block_rows; block_row < compptr->v_samp_factor;
a26a3f ¤   ···block_row++) {
5dd43c ¤   thisblockrow = buffer[block_row];
b9cf0b ¤   lastblockrow = buffer[block_row-1];
158a52 ¤   jzero_far((void FAR *) thisblockrow,
7dfae3 ¤   ¤   ··(size_t) (blocks_across * SIZEOF(JBLOCK)));
874b3c ¤   for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
6911a9 ¤   ··lastDC = lastblockrow[h_samp_factor-1][0];
7c07f5 ¤   ··for (bi = 0; bi < h_samp_factor; bi++) {
f13b4f ¤   ····thisblockrow[bi][0] = lastDC;
6432a2 ¤   ··}
bbfc17 ¤   ··thisblockrow += h_samp_factor; /* advance to next MCU in row */
005c4b ¤   ··lastblockrow += h_samp_factor;
3a9371 ¤   }
d442cc ······}
886fe7 ····}
cfdf1c ··}
a92f6d ··/* NB: compress_output will increment iMCU_row_num if successful.
02720e ···* A suspension return will result in redoing all the work above next time.
dbf9a6 ···*/
3baf5a
235318 ··/* Emit data to the entropy encoder, sharing code with subsequent passes */
c4e136 ··return compress_output(cinfo, input_buf);
89efe6 }
d6af5a
d4af5a
b638e5 /*
a090f1 ·* Process some data in subsequent passes of a multi-pass case.
0a4e35 ·* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
d924b0 ·* per call, ie, v_samp_factor block rows for each component in the scan.
470916 ·* The data is obtained from the virtual arrays and fed to the entropy coder.
69ea83 ·* Returns TRUE if the iMCU row is completed, FALSE if suspended.
26775e ·*
0aef1a ·* NB: input_buf is ignored; it is likely to be a NULL pointer.
af495d ·*/
00af5a
b49a8f METHODDEF(boolean)
157c53 compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
0fbb36 {
2a7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
7a2df3 ··JDIMENSION MCU_col_num;¤  /* index of current MCU within row */
b66ca8 ··int blkn, ci, xindex, yindex, yoffset;
e9f9ae ··JDIMENSION start_col;
16a37f ··JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
07065a ··JBLOCKROW buffer_ptr;
a233b0 ··jpeg_component_info *compptr;
32af5a
fc31aa ··/* Align the virtual buffers for the components used in this scan.
d569ac ···* NB: during first pass, this is safe only because the buffers will
95b4bf ···* already be aligned properly, so jmemmgr.c won't need to do any I/O.
faf9a6 ···*/
316aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
a8a7cc ····compptr = cinfo->cur_comp_info[ci];
98917c ····buffer[ci] = (*cinfo->mem->access_virt_barray)
e07fe4 ······((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
43f5ef ·······coef->iMCU_row_num * compptr->v_samp_factor,
7c5a8b ·······(JDIMENSION) compptr->v_samp_factor, FALSE);
04df1c ··}
--ef6e 000d9c8444b4010000c Page 6 of jccoefct.c
e0af5a
652174 ··/* Loop to process one whole iMCU row */
56a27a ··for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
30bd1b ·······yoffset++) {
9549d7 ····for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
8a2288 ¤   ·MCU_col_num++) {
e05139 ······/* Construct list of pointers to DCT blocks belonging to this MCU */
0d5fdc ······blkn = 0;¤¤   ¤   /* index of current DCT block within MCU */
b66064 ······for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
2608f5 ¤   compptr = cinfo->cur_comp_info[ci];
cd8a61 ¤   start_col = MCU_col_num * compptr->MCU_width;
6076a3 ¤   for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
eb01a1 ¤   ··buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
f5c9d6 ¤   ··for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
08c078 ¤   ····coef->MCU_buffer[blkn++] = buffer_ptr++;
7f32a2 ¤   ··}
819371 ¤   }
7442cc ······}
7d72ff ······/* Try to write the MCU. */
d55379 ······if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
743fee ¤   /* Suspension forced; update state counters and exit */
2cebe8 ¤   coef->MCU_vert_offset = yoffset;
04eece ¤   coef->mcu_ctr = MCU_col_num;
01a230 ¤   return FALSE;
cc42cc ······}
5a6fe7 ····}
55b67f ····/* Completed an MCU row, but perhaps not an iMCU row */
3f0874 ····coef->mcu_ctr = 0;
38df1c ··}
6877d6 ··/* Completed the iMCU row, advance counters for next one */
78b60b ··coef->iMCU_row_num++;
393d6b ··start_iMCU_row(cinfo);
8bd2c8 ··return TRUE;
55efe6 }
9faf5a
283b5f #endif /* FULL_COEF_BUFFER_SUPPORTED */
8aaf5a
5eaf5a
d638e5 /*
567e1c ·* Initialize coefficient buffer controller.
fc495d ·*/
bfaf5a
bbf898 GLOBAL(void)
e8aaf6 jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
68bb36 {
0cb982 ··my_coef_ptr coef;
1daf5a
2870bd ··coef = (my_coef_ptr)
af3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
9389b6 ¤   ¤   ¤   ¤   SIZEOF(my_coef_controller));
809ebf ··cinfo->coef = (struct jpeg_c_coef_controller *) coef;
8b93ac ··coef->pub.start_pass = start_pass_coef;
e0af5a
7634c3 ··/* Create the coefficient buffer. */
41baf2 ··if (need_full_buffer) {
bd93fc #ifdef FULL_COEF_BUFFER_SUPPORTED
2571db ····/* Allocate a full-image virtual array for each component, */
2a1c01 ····/* padded to a multiple of samp_factor DCT blocks in each direction. */
47bece ····int ci;
aaec11 ····jpeg_component_info *compptr;
47af5a
6c6090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
c6b5ed ¤   ·ci++, compptr++) {
5206f9 ······coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
2ad16b ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
b17183 ¤   ·(JDIMENSION) jround_up((long) compptr->width_in_blocks,
58a6ca ¤   ¤   ¤   ¤   (long) compptr->h_samp_factor),
0a954d ¤   ·(JDIMENSION) jround_up((long) compptr->height_in_blocks,
f66bd5 ¤   ¤   ¤   ¤   (long) compptr->v_samp_factor),
332e3d ¤   ·(JDIMENSION) compptr->v_samp_factor);
926fe7 ····}
d9db21 #else
--f539 0017eb10fae4010000c Page 7 of jccoefct.c
64650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
077454 #endif
6049d8 ··} else {
70e24f ····/* We only need a single-MCU buffer. */
780091 ····JBLOCKROW buffer;
7eae36 ····int i;
a8af5a
cd8be0 ····buffer = (JBLOCKROW)
073ff1 ······(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
224681 ¤   ¤   ¤   ¤   ··C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
278322 ····for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
c0f509 ······coef->MCU_buffer[i] = buffer + i;
8a6fe7 ····}
f9882b ····coef->whole_image[0] = NULL; /* flag for no virtual arrays */
73df1c ··}
7eefe6 }
--3e17 000b02b30b44010000d Page 1 of jccolor.c
bc38e5 /*
b3f2d6 ·* jccolor.c
e3775e ·*
a7a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
45fb07 ·* This file is part of the Independent JPEG Group's software.
52a0d6 ·* For conditions of distribution and use, see the accompanying README file.
5b775e ·*
12dea6 ·* This file contains input colorspace conversion routines.
f9495d ·*/
45af5a
8c2bb6 #define JPEG_INTERNALS
e836a7 #include "jinclude.h"
056c8f #include "jpeglib.h"
c1af5a
70af5a
9cdedc /* Private subobject */
c8af5a
43f0f7 typedef struct {
21f53e ··struct jpeg_color_converter pub; /* public fields */
ebaf5a
7b355c ··/* Private state for RGB->YCC conversion */
9676c8 ··INT32 * rgb_ycc_tab;¤ ¤   /* => table for RGB to YCbCr conversion */
874ef9 } my_color_converter;
16af5a
e0c4fa typedef my_color_converter * my_cconvert_ptr;
04af5a
53af5a
bf83d5 /**************** RGB -> YCbCr conversion: most common case **************/
91af5a
9c38e5 /*
45e7db ·* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
c1d404 ·* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
1ce056 ·* The conversion equations to be implemented are therefore
08f942 ·*¤ Y ·= ·0.29900 * R + 0.58700 * G + 0.11400 * B
ded784 ·*¤ Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B ·+ CENTERJSAMPLE
eb91d2 ·*¤ Cr = ·0.50000 * R - 0.41869 * G - 0.08131 * B ·+ CENTERJSAMPLE
23bc70 ·* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
67adba ·* Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
b18f3c ·* rather than CENTERJSAMPLE, for Cb and Cr. ·This gave equal positive and
5ebef3 ·* negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
5d309f ·* were not represented exactly. ·Now we sacrifice exact representation of
20cd29 ·* maximum red and maximum blue in order to get exact grayscales.
e1775e ·*
1d24a1 ·* To avoid floating-point arithmetic, we represent the fractional constants
f684de ·* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
5a4355 ·* the products by 2^16, with appropriate rounding, to get the correct answer.
c0775e ·*
cbec9d ·* For even more speed, we avoid doing any multiplications in the inner loop
c0b6e1 ·* by precalculating the constants times R,G,B for all possible values.
1bcc69 ·* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
4713e8 ·* for 12-bit samples it is still acceptable. ·It's not very reasonable for
e73cee ·* 16-bit samples, but if you want lossless storage you shouldn't be changing
f4248f ·* colorspace anyway.
5c78ac ·* The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
4edd03 ·* in the tables to save adding them separately in the inner loop.
a8495d ·*/
68af5a
0d81d9 #define SCALEBITS¤  16¤ /* speediest right-shift on some machines */
24507b #define CBCR_OFFSET¤((INT32) CENTERJSAMPLE << SCALEBITS)
655746 #define ONE_HALF¤   ((INT32) 1 << (SCALEBITS-1))
5439c8 #define FIX(x)¤ ¤   ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
c5af5a
2cd770 /* We allocate one big table and divide it up into eight parts, instead of
745f8b ·* doing eight alloc_small requests. ·This lets us use a single table base
b31410 ·* address, which can be held in a register in the inner loops on many
4b1650 ·* machines (more than can hold all eight addresses, anyway).
12495d ·*/
47af5a
6b70d4 #define R_Y_OFF¤¤   0¤  ¤   ¤   /* offset to R => Y section */
999c10 #define G_Y_OFF¤¤   (1*(MAXJSAMPLE+1))¤ /* offset to G => Y section */
85ee25 #define B_Y_OFF¤¤   (2*(MAXJSAMPLE+1))¤ /* etc. */
b04f7e #define R_CB_OFF¤   (3*(MAXJSAMPLE+1))
--218b 000e7cff4934010000d Page 2 of jccolor.c
104fb2 #define G_CB_OFF¤   (4*(MAXJSAMPLE+1))
0d7e82 #define B_CB_OFF¤   (5*(MAXJSAMPLE+1))
536903 #define R_CR_OFF¤   B_CB_OFF¤   ¤   /* B=>Cb, R=>Cr are the same */
c93741 #define G_CR_OFF¤   (6*(MAXJSAMPLE+1))
840671 #define B_CR_OFF¤   (7*(MAXJSAMPLE+1))
7ad88b #define TABLE_SIZE¤ (8*(MAXJSAMPLE+1))
28af5a
40af5a
1038e5 /*
0e261e ·* Initialize for RGB->YCC colorspace conversion.
16495d ·*/
b6af5a
bb0434 METHODDEF(void)
28c54b rgb_ycc_start (j_compress_ptr cinfo)
1dbb36 {
d883d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
7e0ceb ··INT32 * rgb_ycc_tab;
08c763 ··INT32 i;
6baf5a
09a5cd ··/* Allocate and fill in the conversion tables. */
6000b0 ··cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
e13f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
379f16 ¤   ¤   ¤   ¤   (TABLE_SIZE * SIZEOF(INT32)));
1daf5a
57ad7d ··for (i = 0; i <= MAXJSAMPLE; i++) {
ee08c6 ····rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
7ab01d ····rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
61605c ····rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i ····+ ONE_HALF;
db3bae ····rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
a63127 ····rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
3b4d9e ····/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
fd15ec ·····* This ensures that the maximum output will round to MAXJSAMPLE
b0935d ·····* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
2ed48d ·····*/
6986f6 ····rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i ···+ CBCR_OFFSET + ONE_HALF-1;
250641 /* ·B=>Cb and R=>Cr tables are the same
e9085a ····rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i ···+ CBCR_OFFSET + ONE_HALF-1;
1f7fe0 */
5efb42 ····rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
d921fb ····rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
f5df1c ··}
e5efe6 }
18af5a
58af5a
1238e5 /*
ece5a5 ·* Convert some rows of samples to the JPEG colorspace.
3f775e ·*
cec777 ·* Note that we change from the application's interleaved-pixel format
666e81 ·* to our internal noninterleaved, one-plane-per-component format.
b980e8 ·* The input buffer is therefore three times as wide as the output buffer.
46775e ·*
f5ba0f ·* A starting row offset is provided only for the output buffer. ·The caller
826662 ·* can easily adjust the passed input_buf value to accommodate any row
3a4504 ·* offset required on that side.
fe495d ·*/
70af5a
460434 METHODDEF(void)
5c1068 rgb_ycc_convert (j_compress_ptr cinfo,
fdc85c ¤   ¤   ·JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
1479f8 ¤   ¤   ·JDIMENSION output_row, int num_rows)
73bb36 {
bd83d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
847f4f ··register int r, g, b;
78da53 ··register INT32 * ctab = cconvert->rgb_ycc_tab;
f37609 ··register JSAMPROW inptr;
a456bf ··register JSAMPROW outptr0, outptr1, outptr2;
e12043 ··register JDIMENSION col;
219b87 ··JDIMENSION num_cols = cinfo->image_width;
7faf5a
1dd9ef ··while (--num_rows >= 0) {
3347a5 ····inptr = *input_buf++;
e73a05 ····outptr0 = output_buf[0][output_row];
--5779 000a61e22894010000d Page 3 of jccolor.c
c37121 ····outptr1 = output_buf[1][output_row];
1bac4d ····outptr2 = output_buf[2][output_row];
b80faa ····output_row++;
f57a19 ····for (col = 0; col < num_cols; col++) {
b18cc0 ······r = GETJSAMPLE(inptr[RGB_RED]);
2f4b2a ······g = GETJSAMPLE(inptr[RGB_GREEN]);
624aea ······b = GETJSAMPLE(inptr[RGB_BLUE]);
3ae731 ······inptr += RGB_PIXELSIZE;
e5abf0 ······/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
e827a8 ·······* must be too; we do not need an explicit range-limiting operation.
0d0960 ·······* Hence the value being shifted is never negative, and we don't
19d0fb ·······* need the general RIGHT_SHIFT macro.
8de9f1 ·······*/
72e69d ······/* Y */
fde939 ······outptr0[col] = (JSAMPLE)
50739c ¤   ¤   ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
94729f ¤   ¤   ·>> SCALEBITS);
34e45c ······/* Cb */
457a70 ······outptr1[col] = (JSAMPLE)
f5f7cb ¤   ¤   ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
8a729f ¤   ¤   ·>> SCALEBITS);
a5501c ······/* Cr */
a4c7ba ······outptr2[col] = (JSAMPLE)
1a168e ¤   ¤   ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
7f729f ¤   ¤   ·>> SCALEBITS);
346fe7 ····}
72df1c ··}
f7efe6 }
edaf5a
22af5a
9630ee /**************** Cases other than RGB -> YCbCr **************/
a2af5a
daaf5a
a438e5 /*
43e5a5 ·* Convert some rows of samples to the JPEG colorspace.
832765 ·* This version handles RGB->grayscale conversion, which is the same
c32432 ·* as the RGB->Y portion of RGB->YCbCr.
209321 ·* We assume rgb_ycc_start has been called (we only use the Y tables).
1a495d ·*/
a6af5a
520434 METHODDEF(void)
8c6074 rgb_gray_convert (j_compress_ptr cinfo,
810a68 ¤   ¤   ··JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
70d105 ¤   ¤   ··JDIMENSION output_row, int num_rows)
0bbb36 {
e883d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
887f4f ··register int r, g, b;
77da53 ··register INT32 * ctab = cconvert->rgb_ycc_tab;
537609 ··register JSAMPROW inptr;
5aaf23 ··register JSAMPROW outptr;
242043 ··register JDIMENSION col;
449b87 ··JDIMENSION num_cols = cinfo->image_width;
97af5a
a9d9ef ··while (--num_rows >= 0) {
f947a5 ····inptr = *input_buf++;
b991df ····outptr = output_buf[0][output_row];
830faa ····output_row++;
897a19 ····for (col = 0; col < num_cols; col++) {
068cc0 ······r = GETJSAMPLE(inptr[RGB_RED]);
464b2a ······g = GETJSAMPLE(inptr[RGB_GREEN]);
fc4aea ······b = GETJSAMPLE(inptr[RGB_BLUE]);
56e731 ······inptr += RGB_PIXELSIZE;
f1e69d ······/* Y */
a239b9 ······outptr[col] = (JSAMPLE)
e0739c ¤   ¤   ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
07729f ¤   ¤   ·>> SCALEBITS);
e56fe7 ····}
64df1c ··}
e2efe6 }
36af5a
28af5a
a638e5 /*
--e57f 000dd13293e4010000d Page 4 of jccolor.c
1ee5a5 ·* Convert some rows of samples to the JPEG colorspace.
e01565 ·* This version handles Adobe-style CMYK->YCCK conversion,
eccd75 ·* where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
d2a068 ·* conversion as above, while passing K (black) unchanged.
3e5d87 ·* We assume rgb_ycc_start has been called.
e2495d ·*/
d0af5a
120434 METHODDEF(void)
ace896 cmyk_ycck_convert (j_compress_ptr cinfo,
0e7d0d ¤   ¤   ···JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
abfdc7 ¤   ¤   ···JDIMENSION output_row, int num_rows)
0cbb36 {
6283d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
277f4f ··register int r, g, b;
9fda53 ··register INT32 * ctab = cconvert->rgb_ycc_tab;
2e7609 ··register JSAMPROW inptr;
b6d900 ··register JSAMPROW outptr0, outptr1, outptr2, outptr3;
d22043 ··register JDIMENSION col;
169b87 ··JDIMENSION num_cols = cinfo->image_width;
b4af5a
64d9ef ··while (--num_rows >= 0) {
9947a5 ····inptr = *input_buf++;
cc3a05 ····outptr0 = output_buf[0][output_row];
717121 ····outptr1 = output_buf[1][output_row];
14ac4d ····outptr2 = output_buf[2][output_row];
c4e769 ····outptr3 = output_buf[3][output_row];
af0faa ····output_row++;
ed7a19 ····for (col = 0; col < num_cols; col++) {
5346df ······r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
92aa78 ······g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
bbdef3 ······b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
06f010 ······/* K passes through as-is */
e6e374 ······outptr3[col] = inptr[3];¤ /* don't need GETJSAMPLE here */
92bfdb ······inptr += 4;
f7abf0 ······/* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
1827a8 ·······* must be too; we do not need an explicit range-limiting operation.
7c0960 ·······* Hence the value being shifted is never negative, and we don't
06d0fb ·······* need the general RIGHT_SHIFT macro.
a7e9f1 ·······*/
c0e69d ······/* Y */
04e939 ······outptr0[col] = (JSAMPLE)
4c739c ¤   ¤   ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
3d729f ¤   ¤   ·>> SCALEBITS);
f0e45c ······/* Cb */
617a70 ······outptr1[col] = (JSAMPLE)
0ef7cb ¤   ¤   ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
58729f ¤   ¤   ·>> SCALEBITS);
58501c ······/* Cr */
a9c7ba ······outptr2[col] = (JSAMPLE)
12168e ¤   ¤   ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
ab729f ¤   ¤   ·>> SCALEBITS);
ca6fe7 ····}
6fdf1c ··}
45efe6 }
69af5a
dfaf5a
0238e5 /*
2ae5a5 ·* Convert some rows of samples to the JPEG colorspace.
94aab8 ·* This version handles grayscale output with no conversion.
f51a63 ·* The source can be either plain grayscale or YCbCr (since Y == gray).
12495d ·*/
41af5a
740434 METHODDEF(void)
cc8f34 grayscale_convert (j_compress_ptr cinfo,
737d0d ¤   ¤   ···JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
c5fdc7 ¤   ¤   ···JDIMENSION output_row, int num_rows)
a8bb36 {
1a7609 ··register JSAMPROW inptr;
9baf23 ··register JSAMPROW outptr;
0c2043 ··register JDIMENSION col;
209b87 ··JDIMENSION num_cols = cinfo->image_width;
ddffce ··int instride = cinfo->input_components;
--730b 000dd8c700a4010000d Page 5 of jccolor.c
e0af5a
a7d9ef ··while (--num_rows >= 0) {
e847a5 ····inptr = *input_buf++;
3a91df ····outptr = output_buf[0][output_row];
710faa ····output_row++;
c17a19 ····for (col = 0; col < num_cols; col++) {
a6a015 ······outptr[col] = inptr[0];¤  /* don't need GETJSAMPLE() here */
bd2d97 ······inptr += instride;
846fe7 ····}
50df1c ··}
8befe6 }
84af5a
65af5a
b538e5 /*
51e5a5 ·* Convert some rows of samples to the JPEG colorspace.
7c4fe2 ·* This version handles multi-component colorspaces without conversion.
fd1e05 ·* We assume input_components == num_components.
f5495d ·*/
c9af5a
e00434 METHODDEF(void)
52bf0f null_convert (j_compress_ptr cinfo,
15d303 ¤   ······JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
51e782 ¤   ······JDIMENSION output_row, int num_rows)
50bb36 {
e27609 ··register JSAMPROW inptr;
d5af23 ··register JSAMPROW outptr;
3b2043 ··register JDIMENSION col;
13b331 ··register int ci;
f0f4d1 ··int nc = cinfo->num_components;
4f9b87 ··JDIMENSION num_cols = cinfo->image_width;
8caf5a
9fd9ef ··while (--num_rows >= 0) {
8b9430 ····/* It seems fastest to make a separate pass for each component. */
79f248 ····for (ci = 0; ci < nc; ci++) {
a9008d ······inptr = *input_buf;
64c630 ······outptr = output_buf[ci][output_row];
bcd31a ······for (col = 0; col < num_cols; col++) {
f73803 ¤   outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
039f1a ¤   inptr += nc;
a042cc ······}
766fe7 ····}
d48b47 ····input_buf++;
2b0faa ····output_row++;
48df1c ··}
71efe6 }
a1af5a
70af5a
6238e5 /*
1b997b ·* Empty method for start_pass.
00495d ·*/
abaf5a
940434 METHODDEF(void)
9ab85f null_method (j_compress_ptr cinfo)
3abb36 {
ce1b6b ··/* no work needed */
32efe6 }
85af5a
b7af5a
5d38e5 /*
262cff ·* Module initialization routine for input colorspace conversion.
0d495d ·*/
82af5a
2cf898 GLOBAL(void)
4c6291 jinit_color_converter (j_compress_ptr cinfo)
60bb36 {
429184 ··my_cconvert_ptr cconvert;
53af5a
d1e959 ··cconvert = (my_cconvert_ptr)
973f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
a75827 ¤   ¤   ¤   ¤   SIZEOF(my_color_converter));
286f1c ··cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
dd1921 ··/* set start_pass to null method until we find out differently */
--4c0f 000111f161b4010000d Page 6 of jccolor.c
b46f15 ··cconvert->pub.start_pass = null_method;
64af5a
46c1c5 ··/* Make sure input_components agrees with in_color_space */
deb475 ··switch (cinfo->in_color_space) {
35b88c ··case JCS_GRAYSCALE:
a32717 ····if (cinfo->input_components != 1)
a76798 ······ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
f6ab40 ····break;
0eaf5a
a0b3fb ··case JCS_RGB:
a0de55 #if RGB_PIXELSIZE != 3
01a34e ····if (cinfo->input_components != RGB_PIXELSIZE)
9c6798 ······ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
5dab40 ····break;
decf19 #endif /* else share code with YCbCr */
dbaf5a
1418bb ··case JCS_YCbCr:
8192af ····if (cinfo->input_components != 3)
5c6798 ······ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
e8ab40 ····break;
fcaf5a
ca8394 ··case JCS_CMYK:
23969d ··case JCS_YCCK:
dc1eaa ····if (cinfo->input_components != 4)
8a6798 ······ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
22ab40 ····break;
66af5a
af5002 ··default:¤ ¤   ¤   /* JCS_UNKNOWN can be anything */
0d32d7 ····if (cinfo->input_components < 1)
ed6798 ······ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
52ab40 ····break;
7ddf1c ··}
29af5a
af0c2f ··/* Check num_components, set conversion method based on requested space */
178e60 ··switch (cinfo->jpeg_color_space) {
2fb88c ··case JCS_GRAYSCALE:
9026f8 ····if (cinfo->num_components != 1)
4accfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
e96ba2 ····if (cinfo->in_color_space == JCS_GRAYSCALE)
a1c418 ······cconvert->pub.color_convert = grayscale_convert;
2667dc ····else if (cinfo->in_color_space == JCS_RGB) {
18870d ······cconvert->pub.start_pass = rgb_ycc_start;
ea0856 ······cconvert->pub.color_convert = rgb_gray_convert;
b900f0 ····} else if (cinfo->in_color_space == JCS_YCbCr)
cfc418 ······cconvert->pub.color_convert = grayscale_convert;
99842c ····else
9cb463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
7fab40 ····break;
93af5a
15b3fb ··case JCS_RGB:
959340 ····if (cinfo->num_components != 3)
3bccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
0c7d53 ····if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
bfff2e ······cconvert->pub.color_convert = null_convert;
eb842c ····else
c1b463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
08ab40 ····break;
ebaf5a
8818bb ··case JCS_YCbCr:
ca9340 ····if (cinfo->num_components != 3)
e1ccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
1b4f1f ····if (cinfo->in_color_space == JCS_RGB) {
97870d ······cconvert->pub.start_pass = rgb_ycc_start;
c882b0 ······cconvert->pub.color_convert = rgb_ycc_convert;
9e00f0 ····} else if (cinfo->in_color_space == JCS_YCbCr)
99ff2e ······cconvert->pub.color_convert = null_convert;
cc842c ····else
c0b463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
5aab40 ····break;
42af5a
1e8394 ··case JCS_CMYK:
111f45 ····if (cinfo->num_components != 4)
--a2c1 0016c40e9b24010000d Page 7 of jccolor.c
c9ccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
747ff3 ····if (cinfo->in_color_space == JCS_CMYK)
0bff2e ······cconvert->pub.color_convert = null_convert;
be842c ····else
37b463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
3dab40 ····break;
09af5a
43969d ··case JCS_YCCK:
151f45 ····if (cinfo->num_components != 4)
2dccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
281667 ····if (cinfo->in_color_space == JCS_CMYK) {
e6870d ······cconvert->pub.start_pass = rgb_ycc_start;
ff6de8 ······cconvert->pub.color_convert = cmyk_ycck_convert;
cd81e6 ····} else if (cinfo->in_color_space == JCS_YCCK)
88ff2e ······cconvert->pub.color_convert = null_convert;
10842c ····else
e4b463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
6bab40 ····break;
a9af5a
8f86d9 ··default:¤ ¤   ¤   /* allow null conversion of JCS_UNKNOWN */
6c7c9d ····if (cinfo->jpeg_color_space != cinfo->in_color_space ||
d0d18e ¤   cinfo->num_components != cinfo->input_components)
c5b463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
d3b9bc ····cconvert->pub.color_convert = null_convert;
57ab40 ····break;
15df1c ··}
6cefe6 }
--e4d1 00046f2f34b4010000e Page 1 of jcdctmgr.c
bc38e5 /*
bd3692 ·* jcdctmgr.c
d8775e ·*
139e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
97fb07 ·* This file is part of the Independent JPEG Group's software.
d7a0d6 ·* For conditions of distribution and use, see the accompanying README file.
47775e ·*
bd0bfb ·* This file contains the forward-DCT management logic.
5d53b3 ·* This code selects a particular DCT implementation to be used,
40e8c6 ·* and it performs related housekeeping chores including coefficient
9706f6 ·* quantization.
12495d ·*/
e1af5a
092bb6 #define JPEG_INTERNALS
8a36a7 #include "jinclude.h"
af6c8f #include "jpeglib.h"
85ef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
9aaf5a
4aaf5a
6965b9 /* Private subobject for this module */
0eaf5a
0cf0f7 typedef struct {
a0a405 ··struct jpeg_forward_dct pub;¤ /* public fields */
faaf5a
f550f9 ··/* Pointer to the DCT routine actually in use */
022ada ··forward_DCT_method_ptr do_dct;
9faf5a
c7da2c ··/* The actual post-DCT divisors --- not identical to the quant table
ff74e0 ···* entries, because of scaling (especially for an unnormalized DCT).
ca6330 ···* Each table is given in normal array order.
90f9a6 ···*/
1d91d7 ··DCTELEM * divisors[NUM_QUANT_TBLS];
c4af5a
d36fd6 #ifdef DCT_FLOAT_SUPPORTED
5d60d5 ··/* Same as above for the floating-point case. */
27c223 ··float_DCT_method_ptr do_float_dct;
5614c7 ··FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
cc7454 #endif
12cab4 } my_fdct_controller;
daaf5a
22d13c typedef my_fdct_controller * my_fdct_ptr;
e6af5a
61af5a
4738e5 /*
375b80 ·* Initialize for a processing pass.
f10505 ·* Verify that all referenced Q-tables are present, and set up
41910d ·* the divisor table for each one.
e27ad7 ·* In the current implementation, DCT of all components is done during
e724ee ·* the first pass, even if only some components will be output in the
e587ab ·* first scan. ·Hence all components should be examined here.
df495d ·*/
a6af5a
180434 METHODDEF(void)
75990c start_pass_fdctmgr (j_compress_ptr cinfo)
93bb36 {
190a9b ··my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
a8bbf2 ··int ci, qtblno, i;
e133b0 ··jpeg_component_info *compptr;
f94504 ··JQUANT_TBL * qtbl;
5ccc62 ··DCTELEM * dtbl;
37af5a
e6958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
7aaa07 ·······ci++, compptr++) {
3bed10 ····qtblno = compptr->quant_tbl_no;
946031 ····/* Make sure specified quantization table is present */
7e4153 ····if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
f36d78 ¤   cinfo->quant_tbl_ptrs[qtblno] == NULL)
c290fe ······ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
731b61 ····qtbl = cinfo->quant_tbl_ptrs[qtblno];
ca81a3 ····/* Compute divisors for this quant table */
9625a2 ····/* We may do this more than once for same table, but it's not a big deal */
46bce4 ····switch (cinfo->dct_method) {
--06c3 000e54850f54010000e Page 2 of jcdctmgr.c
42ba56 #ifdef DCT_ISLOW_SUPPORTED
189e2f ····case JDCT_ISLOW:
666c04 ······/* For LL&M IDCT method, divisors are equal to raw quantization
d48f06 ·······* coefficients multiplied by 8 (to counteract scaling).
40e9f1 ·······*/
4a8cb1 ······if (fdct->divisors[qtblno] == NULL) {
f024e0 ¤   fdct->divisors[qtblno] = (DCTELEM *)
1170e0 ¤   ··(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
ea0641 ¤   ¤   ¤   ¤   ······DCTSIZE2 * SIZEOF(DCTELEM));
f342cc ······}
f871f9 ······dtbl = fdct->divisors[qtblno];
ad31c6 ······for (i = 0; i < DCTSIZE2; i++) {
0abfbb ¤   dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
9b42cc ······}
0d88e1 ······break;
307454 #endif
34fcf3 #ifdef DCT_IFAST_SUPPORTED
300f9d ····case JDCT_IFAST:
9a161c ······{
089153 ¤   /* For AA&N IDCT method, divisors are equal to quantization
2792c8 ¤   ·* coefficients scaled by scalefactor[row]*scalefactor[col], where
89cf29 ¤   ·* ··scalefactor[0] = 1
f1dda5 ¤   ·* ··scalefactor[k] = cos(k*PI/16) * sqrt(2) ···for k=1..7
14ab9a ¤   ·* We apply a further scale factor of 8.
95a4e3 ¤   ·*/
7e552e #define CONST_BITS 14
8922fc ¤   static const INT16 aanscales[DCTSIZE2] = {
c1b896 ¤   ··/* precomputed values scaled up by 14 bits */
8807a8 ¤   ··16384, 22725, 21407, 19266, 16384, 12873, ·8867, ·4520,
9beec6 ¤   ··22725, 31521, 29692, 26722, 22725, 17855, 12299, ·6270,
680ef0 ¤   ··21407, 29692, 27969, 25172, 21407, 16819, 11585, ·5906,
aa7192 ¤   ··19266, 26722, 25172, 22654, 19266, 15137, 10426, ·5315,
7a07a8 ¤   ··16384, 22725, 21407, 19266, 16384, 12873, ·8867, ·4520,
e078e8 ¤   ··12873, 17855, 16819, 15137, 12873, 10114, ·6967, ·3552,
945553 ¤   ···8867, 12299, 11585, 10426, ·8867, ·6967, ·4799, ·2446,
290703 ¤   ···4520, ·6270, ·5906, ·5315, ·4520, ·3552, ·2446, ·1247
1162bd ¤   };
154489 ¤   SHIFT_TEMPS
e3af5a
89d99a ¤   if (fdct->divisors[qtblno] == NULL) {
fa8440 ¤   ··fdct->divisors[qtblno] = (DCTELEM *)
ad2c8f ¤   ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
22b703 ¤   ¤   ¤   ¤   ¤   DCTSIZE2 * SIZEOF(DCTELEM));
c39371 ¤   }
c9a46b ¤   dtbl = fdct->divisors[qtblno];
609a0b ¤   for (i = 0; i < DCTSIZE2; i++) {
b50aa2 ¤   ··dtbl[i] = (DCTELEM)
25b758 ¤   ····DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
875c94 ¤   ¤   ¤   ¤   ··(INT32) aanscales[i]),
de4522 ¤   ¤   ····CONST_BITS-3);
929371 ¤   }
cd42cc ······}
e588e1 ······break;
e87454 #endif
f86fd6 #ifdef DCT_FLOAT_SUPPORTED
e0a408 ····case JDCT_FLOAT:
b9161c ······{
771ad8 ¤   /* For float AA&N IDCT method, divisors are equal to quantization
e992c8 ¤   ·* coefficients scaled by scalefactor[row]*scalefactor[col], where
3ecf29 ¤   ·* ··scalefactor[0] = 1
54dda5 ¤   ·* ··scalefactor[k] = cos(k*PI/16) * sqrt(2) ···for k=1..7
90ab9a ¤   ·* We apply a further scale factor of 8.
0ef56d ¤   ·* What's actually stored is 1/divisor so that the inner loop can
439950 ¤   ·* use a multiplication rather than a division.
31a4e3 ¤   ·*/
189202 ¤   FAST_FLOAT * fdtbl;
77e31d ¤   int row, col;
342a63 ¤   static const double aanscalefactor[DCTSIZE] = {
faf7b4 ¤   ··1.0, 1.387039845, 1.306562965, 1.175875602,
8e0c4a ¤   ··1.0, 0.785694958, 0.541196100, 0.275899379
9d62bd ¤   };
e5af5a
--2acc 000e812abaf4010000e Page 3 of jcdctmgr.c
034736 ¤   if (fdct->float_divisors[qtblno] == NULL) {
2882ad ¤   ··fdct->float_divisors[qtblno] = (FAST_FLOAT *)
652c8f ¤   ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cc6046 ¤   ¤   ¤   ¤   ¤   DCTSIZE2 * SIZEOF(FAST_FLOAT));
ff9371 ¤   }
131e8c ¤   fdtbl = fdct->float_divisors[qtblno];
77ff6c ¤   i = 0;
bcc87a ¤   for (row = 0; row < DCTSIZE; row++) {
238482 ¤   ··for (col = 0; col < DCTSIZE; col++) {
45d2a0 ¤   ····fdtbl[i] = (FAST_FLOAT)
9d2dc9 ¤   ······(1.0 / (((double) qtbl->quantval[i] *
89d4c7 ¤   ¤   ·······aanscalefactor[row] * aanscalefactor[col] * 8.0)));
64be75 ¤   ····i++;
8132a2 ¤   ··}
fd9371 ¤   }
c942cc ······}
5388e1 ······break;
257454 #endif
03b53c ····default:
6e9015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
9e88e1 ······break;
736fe7 ····}
9ddf1c ··}
aeefe6 }
19af5a
1baf5a
4638e5 /*
144040 ·* Perform forward DCT on one or more blocks of a component.
f6775e ·*
3ff6ab ·* The input samples are taken from the sample_data[] array starting at
8e8ac4 ·* position start_row/start_col, and moving to the right for any additional
c6413d ·* blocks. The quantized coefficients are returned in coef_blocks[].
60495d ·*/
7baf5a
c40434 METHODDEF(void)
51e0ae forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
683d81 ¤   ·····JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
39cb09 ¤   ·····JDIMENSION start_row, JDIMENSION start_col,
7f7953 ¤   ·····JDIMENSION num_blocks)
156d79 /* This version is used for integer DCT implementations. */
b2bb36 {
3b4578 ··/* This routine is heavily used, so it's worth coding it tightly. */
c20a9b ··my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
83afb5 ··forward_DCT_method_ptr do_dct = fdct->do_dct;
dacd7e ··DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
a2d982 ··DCTELEM workspace[DCTSIZE2];¤ /* work area for FDCT subroutine */
307f62 ··JDIMENSION bi;
5baf5a
a04e66 ··sample_data += start_row;¤/* fold in the vertical offset once */
71af5a
505716 ··for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
1a7438 ····/* Load data into workspace, applying unsigned->signed conversion */
8f59da ····{ register DCTELEM *workspaceptr;
4375b1 ······register JSAMPROW elemptr;
f6b53c ······register int elemr;
28af5a
b51d49 ······workspaceptr = workspace;
24bf63 ······for (elemr = 0; elemr < DCTSIZE; elemr++) {
f52c0b ¤   elemptr = sample_data[elemr] + start_col;
d6006f #if DCTSIZE == 8¤   ¤   /* unroll the inner loop */
c1d58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
a6d58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
22d58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
3fd58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
31d58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
9dd58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
bfd58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
2fd58e ¤   *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
9bdb21 #else
bece37 ¤   { register int elemc;
2cfd75 ¤   ··for (elemc = DCTSIZE; elemc > 0; elemc--) {
e860d0 ¤   ····*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
--6a72 000bb5c08834010000e Page 4 of jcdctmgr.c
1d32a2 ¤   ··}
089371 ¤   }
3f7454 #endif
cb42cc ······}
a56fe7 ····}
0baf5a
66df86 ····/* Perform the DCT */
492db5 ····(*do_dct) (workspace);
aaaf5a
adfcda ····/* Quantize/descale the coefficients, and store into coef_blocks[] */
bcd1a1 ····{ register DCTELEM temp, qval;
bc888e ······register int i;
47a4db ······register JCOEFPTR output_ptr = coef_blocks[bi];
b5af5a
cc31c6 ······for (i = 0; i < DCTSIZE2; i++) {
9239eb ¤   qval = divisors[i];
d06804 ¤   temp = workspace[i];
c2ad11 ¤   /* Divide the coefficient value by qval, ensuring proper rounding.
2ca4bf ¤   ·* Since C does not specify the direction of rounding for negative
b39313 ¤   ·* quotients, we have to force the dividend positive for portability.
ab9714 ¤   ·*
cc0dee ¤   ·* In most files, at least half of the output values will be zero
19fdcb ¤   ·* (at default quantization settings, more like three-quarters...)
cd3bbc ¤   ·* so we should ensure that this case is fast. ·On many machines,
ef0b09 ¤   ·* a comparison is enough cheaper than a divide to make a special test
552a99 ¤   ·* a win. ·Since both inputs will be nonnegative, we need only test
f61fe9 ¤   ·* for a < b to discover whether a/b is 0.
bfe804 ¤   ·* If your machine's division is fast enough, define FAST_DIVIDE.
cda4e3 ¤   ·*/
8263af #ifdef FAST_DIVIDE
325b5c #define DIVIDE_BY(a,b)¤ a /= b
54db21 #else
d47cd0 #define DIVIDE_BY(a,b)¤ if (a >= b) a /= b; else a = 0
517454 #endif
04275e ¤   if (temp < 0) {
0a0aff ¤   ··temp = -temp;
4d1164 ¤   ··temp += qval>>1;¤ /* for rounding */
a0be57 ¤   ··DIVIDE_BY(temp, qval);
350aff ¤   ··temp = -temp;
c8f037 ¤   } else {
da1164 ¤   ··temp += qval>>1;¤ /* for rounding */
fdbe57 ¤   ··DIVIDE_BY(temp, qval);
319371 ¤   }
bbae1d ¤   output_ptr[i] = (JCOEF) temp;
4542cc ······}
a96fe7 ····}
86df1c ··}
c6efe6 }
ccaf5a
31af5a
736fd6 #ifdef DCT_FLOAT_SUPPORTED
8daf5a
800434 METHODDEF(void)
2a559d forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
6dc884 ¤   ¤   ···JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
c8e783 ¤   ¤   ···JDIMENSION start_row, JDIMENSION start_col,
327656 ¤   ¤   ···JDIMENSION num_blocks)
96dd25 /* This version is used for floating-point DCT implementations. */
76bb36 {
de4578 ··/* This routine is heavily used, so it's worth coding it tightly. */
c70a9b ··my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
e6e6d4 ··float_DCT_method_ptr do_dct = fdct->do_float_dct;
89cdfc ··FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
bb870e ··FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
d37f62 ··JDIMENSION bi;
b6af5a
c24e66 ··sample_data += start_row;¤/* fold in the vertical offset once */
32af5a
e55716 ··for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
347438 ····/* Load data into workspace, applying unsigned->signed conversion */
1a1c2f ····{ register FAST_FLOAT *workspaceptr;
bb75b1 ······register JSAMPROW elemptr;
--31ea 0002b7bc1c94010000e Page 5 of jcdctmgr.c
dab53c ······register int elemr;
d5af5a
e41d49 ······workspaceptr = workspace;
eebf63 ······for (elemr = 0; elemr < DCTSIZE; elemr++) {
762c0b ¤   elemptr = sample_data[elemr] + start_col;
ea006f #if DCTSIZE == 8¤   ¤   /* unroll the inner loop */
95c1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
f8c1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
afc1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
b9c1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
15c1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
31c1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
d4c1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
3ac1c9 ¤   *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
73db21 #else
35ce37 ¤   { register int elemc;
d8fd75 ¤   ··for (elemc = DCTSIZE; elemc > 0; elemc--) {
1b6e29 ¤   ····*workspaceptr++ = (FAST_FLOAT)
b0a212 ¤   ······(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
6e32a2 ¤   ··}
7f9371 ¤   }
5a7454 #endif
8f42cc ······}
8c6fe7 ····}
5caf5a
4bdf86 ····/* Perform the DCT */
d62db5 ····(*do_dct) (workspace);
7faf5a
57fcda ····/* Quantize/descale the coefficients, and store into coef_blocks[] */
cf2631 ····{ register FAST_FLOAT temp;
47888e ······register int i;
b6a4db ······register JCOEFPTR output_ptr = coef_blocks[bi];
cbaf5a
1431c6 ······for (i = 0; i < DCTSIZE2; i++) {
d87843 ¤   /* Apply the quantization and scaling factor */
66cd4e ¤   temp = workspace[i] * divisors[i];
6b6274 ¤   /* Round to nearest integer.
42a4bf ¤   ·* Since C does not specify the direction of rounding for negative
0e9313 ¤   ·* quotients, we have to force the dividend positive for portability.
a8fda6 ¤   ·* The maximum coefficient size is +-16K (for 12-bit data), so this
868af9 ¤   ·* code should work for either 16-bit or 32-bit ints.
81a4e3 ¤   ·*/
e67e30 ¤   output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
5142cc ······}
3b6fe7 ····}
d0df1c ··}
ccefe6 }
05af5a
44e923 #endif /* DCT_FLOAT_SUPPORTED */
71af5a
28af5a
3038e5 /*
143bdc ·* Initialize FDCT manager.
7d495d ·*/
e2af5a
80f898 GLOBAL(void)
e5e02b jinit_forward_dct (j_compress_ptr cinfo)
a6bb36 {
ce971d ··my_fdct_ptr fdct;
3317e0 ··int i;
2aaf5a
4def3c ··fdct = (my_fdct_ptr)
0e3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
706c15 ¤   ¤   ¤   ¤   SIZEOF(my_fdct_controller));
3543ae ··cinfo->fdct = (struct jpeg_forward_dct *) fdct;
a861bf ··fdct->pub.start_pass = start_pass_fdctmgr;
efaf5a
6cd8ad ··switch (cinfo->dct_method) {
5fba56 #ifdef DCT_ISLOW_SUPPORTED
95a96f ··case JDCT_ISLOW:
9727ae ····fdct->pub.forward_DCT = forward_DCT;
2b3927 ····fdct->do_dct = jpeg_fdct_islow;
--fc2c 001ce4fa9ca4010000e Page 6 of jcdctmgr.c
faab40 ····break;
f47454 #endif
71fcf3 #ifdef DCT_IFAST_SUPPORTED
ce38dd ··case JDCT_IFAST:
f627ae ····fdct->pub.forward_DCT = forward_DCT;
a0a895 ····fdct->do_dct = jpeg_fdct_ifast;
8eab40 ····break;
8d7454 #endif
d76fd6 #ifdef DCT_FLOAT_SUPPORTED
069348 ··case JDCT_FLOAT:
01df51 ····fdct->pub.forward_DCT = forward_DCT_float;
f9f771 ····fdct->do_float_dct = jpeg_fdct_float;
92ab40 ····break;
507454 #endif
4b969d ··default:
469214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
aeab40 ····break;
36df1c ··}
58af5a
3350b2 ··/* Mark divisor tables unallocated */
c227d7 ··for (i = 0; i < NUM_QUANT_TBLS; i++) {
ed6446 ····fdct->divisors[i] = NULL;
1d6fd6 #ifdef DCT_FLOAT_SUPPORTED
4da520 ····fdct->float_divisors[i] = NULL;
6e7454 #endif
f9df1c ··}
ceefe6 }
--37bd 00098c53a714010000f Page 1 of jchuff.c
bc38e5 /*
32f7c1 ·* jchuff.c
b8775e ·*
5ea060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
61fb07 ·* This file is part of the Independent JPEG Group's software.
09a0d6 ·* For conditions of distribution and use, see the accompanying README file.
2d775e ·*
15bd40 ·* This file contains Huffman entropy encoding routines.
69775e ·*
5ed012 ·* Much of the complexity here has to do with supporting output suspension.
d66180 ·* If the data destination module demands suspension, we want to be able to
162e15 ·* back up to the start of the current MCU. ·To do this, we copy state
697624 ·* variables into local working storage, and update them back to the
91baad ·* permanent JPEG objects only upon successful completion of an MCU.
85495d ·*/
2aaf5a
4a2bb6 #define JPEG_INTERNALS
2c36a7 #include "jinclude.h"
3b6c8f #include "jpeglib.h"
c64c04 #include "jchuff.h"¤¤   /* Declarations shared with jcphuff.c */
e4af5a
79af5a
ddd8b0 /* Expanded entropy encoder object for Huffman encoding.
fb775e ·*
798e84 ·* The savable_state subrecord contains fields that change within an MCU,
61ea98 ·* but must not be updated permanently until we complete the MCU.
70495d ·*/
cbaf5a
4ff0f7 typedef struct {
87c30b ··INT32 put_buffer;¤¤   /* current bit-accumulation buffer */
070ceb ··int put_bits;¤¤   ¤   /* # of bits now in it */
b06041 ··int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
ec9eb2 } savable_state;
20af5a
65f232 /* This macro is to work around compilers with missing or broken
091491 ·* structure assignment. ·You'll need to fix this code if you have
749eb0 ·* such a compiler and you change MAX_COMPS_IN_SCAN.
ec495d ·*/
1faf5a
127994 #ifndef NO_STRUCT_ASSIGN
8aa795 #define ASSIGN_STATE(dest,src) ·((dest) = (src))
b1db21 #else
5cca2d #if MAX_COMPS_IN_SCAN == 4
bc679e #define ASSIGN_STATE(dest,src) ·\
7ab0f4 ¤   ((dest).put_buffer = (src).put_buffer, \
0d85e6 ¤   ·(dest).put_bits = (src).put_bits, \
89d3b6 ¤   ·(dest).last_dc_val[0] = (src).last_dc_val[0], \
732eac ¤   ·(dest).last_dc_val[1] = (src).last_dc_val[1], \
672193 ¤   ·(dest).last_dc_val[2] = (src).last_dc_val[2], \
dd358a ¤   ·(dest).last_dc_val[3] = (src).last_dc_val[3])
097454 #endif
a57454 #endif
14af5a
13af5a
3bf0f7 typedef struct {
149ae8 ··struct jpeg_entropy_encoder pub; /* public fields */
c6af5a
3daa19 ··savable_state saved;¤ ¤   /* Bit buffer & DC state at start of MCU */
76af5a
b2f17f ··/* These fields are NOT loaded into local working state. */
af8e4c ··unsigned int restarts_to_go;¤ /* MCUs left in this restart interval */
858418 ··int next_restart_num;¤¤   /* next restart number to write (0-7) */
9caf5a
42e6a8 ··/* Pointers to derived tables (these workspaces have image lifespan) */
7e8b5c ··c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
3e29a7 ··c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
7eaf5a
fadaa6 #ifdef ENTROPY_OPT_SUPPORTED¤   /* Statistics tables for optimization */
61f9b9 ··long * dc_count_ptrs[NUM_HUFF_TBLS];
125a86 ··long * ac_count_ptrs[NUM_HUFF_TBLS];
a97454 #endif
989f57 } huff_entropy_encoder;
--c6fc 0009ce8f79a4010000f Page 2 of jchuff.c
e0af5a
b146f3 typedef huff_entropy_encoder * huff_entropy_ptr;
adaf5a
d57375 /* Working state while writing an MCU.
e436cb ·* This struct contains all the fields that are needed by subroutines.
97495d ·*/
95af5a
3df0f7 typedef struct {
4f1f80 ··JOCTET * next_output_byte;¤   /* => next byte to write in buffer */
48a28a ··size_t free_in_buffer;¤   /* # of byte spaces remaining in buffer */
33539d ··savable_state cur;¤   ¤   /* Current bit buffer & DC state */
85dde6 ··j_compress_ptr cinfo;¤¤   /* dump_buffer needs access to this */
1cc84b } working_state;
b9af5a
24af5a
576a43 /* Forward declarations */
99db1e METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo,
cd1038 ¤   ¤   ¤   ¤   ¤   JBLOCKROW *MCU_data));
155491 METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
e926f0 #ifdef ENTROPY_OPT_SUPPORTED
8573d7 METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo,
7a881b ¤   ¤   ¤   ¤   ¤   ··JBLOCKROW *MCU_data));
84655e METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
ad7454 #endif
72af5a
79af5a
7c38e5 /*
2b3637 ·* Initialize for a Huffman-compressed scan.
46a9e8 ·* If gather_statistics is TRUE, we do not output anything during the scan,
b06436 ·* just count the Huffman symbols used and generate Huffman code tables.
58495d ·*/
9faf5a
d20434 METHODDEF(void)
da1d60 start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
38bb36 {
f62609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
070d5c ··int ci, dctbl, actbl;
6ebcae ··jpeg_component_info * compptr;
11af5a
bbe686 ··if (gather_statistics) {
7226f0 #ifdef ENTROPY_OPT_SUPPORTED
2412a3 ····entropy->pub.encode_mcu = encode_mcu_gather;
0283e9 ····entropy->pub.finish_pass = finish_pass_gather;
0fdb21 #else
8d9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
217454 #endif
8b49d8 ··} else {
5a5b05 ····entropy->pub.encode_mcu = encode_mcu_huff;
d1f029 ····entropy->pub.finish_pass = finish_pass_huff;
f3df1c ··}
17af5a
0b6aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
34a7cc ····compptr = cinfo->cur_comp_info[ci];
cd80fc ····dctbl = compptr->dc_tbl_no;
a0656d ····actbl = compptr->ac_tbl_no;
a0e9a9 ····/* Make sure requested tables are present */
664700 ····/* (In gather mode, tables need not be allocated yet) */
85331d ····if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
895c80 ¤   (cinfo->dc_huff_tbl_ptrs[dctbl] == NULL && !gather_statistics))
8557a3 ······ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
e7ba79 ····if (actbl < 0 || actbl >= NUM_HUFF_TBLS ||
7e65b9 ¤   (cinfo->ac_huff_tbl_ptrs[actbl] == NULL && !gather_statistics))
dac0c2 ······ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
8b9225 ····if (gather_statistics) {
4f26f0 #ifdef ENTROPY_OPT_SUPPORTED
e46e10 ······/* Allocate and zero the statistics tables */
9f6de3 ······/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
148342 ······if (entropy->dc_count_ptrs[dctbl] == NULL)
d14b98 ¤   entropy->dc_count_ptrs[dctbl] = (long *)
e770e0 ¤   ··(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
c8e92f ¤   ¤   ¤   ¤   ······257 * SIZEOF(long));
9c2009 ······MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
--5af1 0005e28be0e4010000f Page 3 of jchuff.c
13860f ······if (entropy->ac_count_ptrs[actbl] == NULL)
12ea2b ¤   entropy->ac_count_ptrs[actbl] = (long *)
df70e0 ¤   ··(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
62e92f ¤   ¤   ¤   ¤   ······257 * SIZEOF(long));
c5fd0a ······MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
097454 #endif
a86a79 ····} else {
5d4c14 ······/* Compute derived values for Huffman tables */
bf413b ······/* We may do this more than once for a table, but it's not expensive */
34293c ······jpeg_make_c_derived_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[dctbl],
6ad937 ¤   ¤   ¤   ······& entropy->dc_derived_tbls[dctbl]);
92abca ······jpeg_make_c_derived_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[actbl],
aabeb8 ¤   ¤   ¤   ······& entropy->ac_derived_tbls[actbl]);
446fe7 ····}
369302 ····/* Initialize DC predictions to 0 */
b44f55 ····entropy->saved.last_dc_val[ci] = 0;
4cdf1c ··}
6caf5a
37cc17 ··/* Initialize bit buffer to empty */
cb6d9b ··entropy->saved.put_buffer = 0;
fadda0 ··entropy->saved.put_bits = 0;
dbaf5a
a6c005 ··/* Initialize restart stuff */
957047 ··entropy->restarts_to_go = cinfo->restart_interval;
7d68bf ··entropy->next_restart_num = 0;
87efe6 }
75af5a
2aaf5a
9038e5 /*
966c87 ·* Compute the derived values for a Huffman table.
57b656 ·* Note this is also used by jcphuff.c.
ae495d ·*/
1baf5a
6ff898 GLOBAL(void)
2d2d77 jpeg_make_c_derived_tbl (j_compress_ptr cinfo, JHUFF_TBL * htbl,
abefe3 ¤   ¤   ¤   ·c_derived_tbl ** pdtbl)
1fbb36 {
975e1b ··c_derived_tbl *dtbl;
21765e ··int p, i, l, lastp, si;
333528 ··char huffsize[257];
c80a58 ··unsigned int huffcode[257];
25cc89 ··unsigned int code;
b4af5a
6cbf27 ··/* Allocate a workspace if we haven't already done so. */
7fcefb ··if (*pdtbl == NULL)
436f59 ····*pdtbl = (c_derived_tbl *)
42558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
ebdf81 ¤   ¤   ¤   ¤   ··SIZEOF(c_derived_tbl));
c38c2f ··dtbl = *pdtbl;
6ade7b ··
d191c2 ··/* Figure C.1: make table of Huffman code length for each symbol */
00dde6 ··/* Note that this is in code-length order. */
6faf5a
8c57d8 ··p = 0;
e58b25 ··for (l = 1; l <= 16; l++) {
3330bf ····for (i = 1; i <= (int) htbl->bits[l]; i++)
c1dfbd ······huffsize[p++] = (char) l;
36df1c ··}
c7f36b ··huffsize[p] = 0;
0a5704 ··lastp = p;
e0de7b ··
634996 ··/* Figure C.2: generate the codes themselves */
4ddde6 ··/* Note that this is in code-length order. */
efde7b ··
c8f546 ··code = 0;
2ebfb2 ··si = huffsize[0];
0257d8 ··p = 0;
4c7f22 ··while (huffsize[p]) {
9c6555 ····while (((int) huffsize[p]) == si) {
4ec25c ······huffcode[p++] = code;
ab560f ······code++;
5e6fe7 ····}
--67d9 000a6f977a74010000f Page 4 of jchuff.c
692fcd ····code <<= 1;
3fb177 ····si++;
66df1c ··}
bade7b ··
36d68f ··/* Figure C.3: generate encoding tables */
dd27e1 ··/* These are code and size indexed by symbol value */
71af5a
c93f0a ··/* Set any codeless symbols to have code length 0;
4f2cde ···* this allows emit_bits to detect any attempt to emit such symbols.
8cf9a6 ···*/
98748f ··MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));
64af5a
679c5c ··for (p = 0; p < lastp; p++) {
0daeca ····dtbl->ehufco[htbl->huffval[p]] = huffcode[p];
75c5cb ····dtbl->ehufsi[htbl->huffval[p]] = huffsize[p];
03df1c ··}
27efe6 }
1baf5a
b8af5a
238774 /* Outputting bytes to the file */
92af5a
16ee4e /* Emit a byte, taking 'action' if must suspend. */
0cfe63 #define emit_byte(state,val,action) ·\
6309f9 ¤   { *(state)->next_output_byte++ = (JOCTET) (val); ·\
b1a6e8 ¤   ··if (--(state)->free_in_buffer == 0) ·\
bfb20b ¤   ····if (! dump_buffer(state)) ·\
af14a6 ¤   ······{ action; } }
09af5a
93af5a
a0c4bf LOCAL(boolean)
5ed11d dump_buffer (working_state * state)
dc88d6 /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
cbbb36 {
5a6708 ··struct jpeg_destination_mgr * dest = state->cinfo->dest;
5eaf5a
e74951 ··if (! (*dest->empty_output_buffer) (state->cinfo))
4430cb ····return FALSE;
407290 ··/* After a successful buffer dump, must reset buffer pointers */
fab8f9 ··state->next_output_byte = dest->next_output_byte;
11661b ··state->free_in_buffer = dest->free_in_buffer;
78d2c8 ··return TRUE;
0defe6 }
cfaf5a
03af5a
31b280 /* Outputting bits to the file */
74af5a
12b746 /* Only the right 24 bits of put_buffer are used; the valid bits are
3f303a ·* left-justified in this part. ·At most 16 bits can be passed to emit_bits
a3ddc4 ·* in one call, and we never retain more than 7 bits in put_buffer
0770f8 ·* between calls, so 24 bits are sufficient.
b6495d ·*/
caaf5a
c96563 INLINE
c6c4bf LOCAL(boolean)
b170ed emit_bits (working_state * state, unsigned int code, int size)
f85cc6 /* Emit some bits; return TRUE if successful, FALSE if must suspend */
9abb36 {
55a048 ··/* This routine is heavily used, so it's worth coding tightly. */
f0ef3f ··register INT32 put_buffer = (INT32) code;
e44494 ··register int put_bits = state->cur.put_bits;
14af5a
bf3b85 ··/* if size is 0, caller used an invalid Huffman table entry */
abdc29 ··if (size == 0)
31db6a ····ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
5baf5a
2afa73 ··put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
b2de7b ··
cd8629 ··put_bits += size;¤¤   /* new number of bits in buffer */
30de7b ··
2d9408 ··put_buffer <<= 24 - put_bits; /* align incoming bits */
dfaf5a
a6b48c ··put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
--8593 0002478c94c4010000f Page 5 of jchuff.c
8bde7b ··
f6b565 ··while (put_bits >= 8) {
404647 ····int c = (int) ((put_buffer >> 16) & 0xFF);
f6869e ····
299d42 ····emit_byte(state, c, return FALSE);
b02bc3 ····if (c == 0xFF) {¤   ¤   /* need to stuff a zero byte? */
4caafb ······emit_byte(state, 0, return FALSE);
2b6fe7 ····}
d64a22 ····put_buffer <<= 8;
6694f6 ····put_bits -= 8;
ecdf1c ··}
73af5a
b5869b ··state->cur.put_buffer = put_buffer; /* update state variables */
fbee2b ··state->cur.put_bits = put_bits;
a2af5a
84d2c8 ··return TRUE;
2defe6 }
65af5a
29af5a
94c4bf LOCAL(boolean)
d19920 flush_bits (working_state * state)
bfbb36 {
c523d4 ··if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
1b30cb ····return FALSE;
1405de ··state->cur.put_buffer = 0;¤   /* and reset bit-buffer to empty */
362248 ··state->cur.put_bits = 0;
73d2c8 ··return TRUE;
f9efe6 }
31af5a
f7af5a
7fbe40 /* Encode a single block's worth of coefficients */
78af5a
e7c4bf LOCAL(boolean)
11e7de encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
4b1978 ¤   ¤   ··c_derived_tbl *dctbl, c_derived_tbl *actbl)
13bb36 {
565601 ··register int temp, temp2;
40ca1f ··register int nbits;
8dcd7d ··register int k, r, i;
a2de7b ··
37aeab ··/* Encode the DC coefficient difference per section F.1.2.1 */
8ede7b ··
ed3be8 ··temp = temp2 = block[0] - last_dc_val;
7aaf5a
41fb33 ··if (temp < 0) {
dfe0c2 ····temp = -temp;¤  ¤   /* temp is abs value of input */
4e48fb ····/* For a negative input, want temp2 = bitwise complement of abs(input) */
66a0f8 ····/* This code assumes we are on a two's complement machine */
418766 ····temp2--;
27df1c ··}
b5de7b ··
94a9b9 ··/* Find the number of bits needed for the magnitude of the coefficient */
7e3df3 ··nbits = 0;
74f170 ··while (temp) {
ac2833 ····nbits++;
ee586a ····temp >>= 1;
82df1c ··}
9bde7b ··
0a2278 ··/* Emit the Huffman-coded symbol for the number of bits */
ec6c39 ··if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
7530cb ····return FALSE;
daaf5a
0ab2ed ··/* Emit that number of bits of the value, if positive, */
9b16d5 ··/* or the complement of its magnitude, if negative. */
331bda ··if (nbits)¤   ¤   ¤   /* emit_bits rejects calls with size 0 */
f77c2b ····if (! emit_bits(state, (unsigned int) temp2, nbits))
eec39d ······return FALSE;
b2af5a
c11b81 ··/* Encode the AC coefficients per section F.1.2.2 */
70de7b ··
9ba209 ··r = 0;¤   ¤   ¤   /* r = run length of zeros */
24de7b ··
--3dab 000224869aa4010000f Page 6 of jchuff.c
f78535 ··for (k = 1; k < DCTSIZE2; k++) {
305510 ····if ((temp = block[jpeg_natural_order[k]]) == 0) {
8cf436 ······r++;
ff6a79 ····} else {
6e7d49 ······/* if run length > 15, must emit special run-length-16 codes (0xF0) */
fb4e0c ······while (r > 15) {
14b85c ¤   if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
0aeca6 ¤   ··return FALSE;
55e1c1 ¤   r -= 16;
d342cc ······}
c9af5a
bd9274 ······temp2 = temp;
2d4a56 ······if (temp < 0) {
77e405 ¤   temp = -temp;¤  ¤   /* temp is abs value of input */
ecfd93 ¤   /* This code assumes we are on a two's complement machine */
a61d28 ¤   temp2--;
8a42cc ······}
95cf72 ······
745406 ······/* Find the number of bits needed for the magnitude of the coefficient */
0dbbeb ······nbits = 1;¤   ¤   /* there must be at least one 1 bit */
9b3af3 ······while ((temp >>= 1))
96b27d ¤   nbits++;
40cf72 ······
377dc7 ······/* Emit Huffman symbol for run length / number of bits */
4e10ee ······i = (r << 4) + nbits;
fcb3c7 ······if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
51a230 ¤   return FALSE;
89af5a
51e05e ······/* Emit that number of bits of the value, if positive, */
ce3ff9 ······/* or the complement of its magnitude, if negative. */
2ba4d2 ······if (! emit_bits(state, (unsigned int) temp2, nbits))
cea230 ¤   return FALSE;
f7cf72 ······
68fa14 ······r = 0;
f56fe7 ····}
a5df1c ··}
66af5a
87db58 ··/* If the last coef(s) were zero, emit an end-of-block code */
06d80e ··if (r > 0)
ad76bc ····if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
28c39d ······return FALSE;
58af5a
6dd2c8 ··return TRUE;
0aefe6 }
49af5a
56af5a
1c38e5 /*
0633b9 ·* Emit a restart marker & resynchronize predictions.
f8495d ·*/
4eaf5a
61c4bf LOCAL(boolean)
128271 emit_restart (working_state * state, int restart_num)
3ebb36 {
560dcc ··int ci;
85af5a
e90afd ··if (! flush_bits(state))
5130cb ····return FALSE;
2faf5a
8c5ef5 ··emit_byte(state, 0xFF, return FALSE);
da0922 ··emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
84af5a
fbbee5 ··/* Re-initialize DC predictions to 0 */
a1a319 ··for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
e0c774 ····state->cur.last_dc_val[ci] = 0;
cfaf5a
d0c54d ··/* The restart counter is not updated until we successfully write the MCU. */
b3af5a
b6d2c8 ··return TRUE;
69efe6 }
79af5a
bcaf5a
2238e5 /*
--c676 000033976d64010000f Page 7 of jchuff.c
c142de ·* Encode and output one MCU's worth of Huffman-compressed coefficients.
cb495d ·*/
d9af5a
149a8f METHODDEF(boolean)
fe690c encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
d9bb36 {
b92609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
3a5187 ··working_state state;
64ed99 ··int blkn, ci;
47bcae ··jpeg_component_info * compptr;
53af5a
0e185b ··/* Load up working state */
d5c874 ··state.next_output_byte = cinfo->dest->next_output_byte;
62d312 ··state.free_in_buffer = cinfo->dest->free_in_buffer;
b59051 ··ASSIGN_STATE(state.cur, entropy->saved);
46cdb9 ··state.cinfo = cinfo;
15af5a
9b480a ··/* Emit restart marker if needed */
39cdfb ··if (cinfo->restart_interval) {
4d8a4f ····if (entropy->restarts_to_go == 0)
1ea953 ······if (! emit_restart(&state, entropy->next_restart_num))
dca230 ¤   return FALSE;
f5df1c ··}
5daf5a
538371 ··/* Encode the MCU data blocks */
867685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
4c153d ····ci = cinfo->MCU_membership[blkn];
11a7cc ····compptr = cinfo->cur_comp_info[ci];
14cacd ····if (! encode_one_block(&state,
6f61a8 ¤   ¤   ¤   ···MCU_data[blkn][0], state.cur.last_dc_val[ci],
2653f9 ¤   ¤   ¤   ···entropy->dc_derived_tbls[compptr->dc_tbl_no],
78f772 ¤   ¤   ¤   ···entropy->ac_derived_tbls[compptr->ac_tbl_no]))
5ac39d ······return FALSE;
293b99 ····/* Update last_dc_val */
ec6538 ····state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
66df1c ··}
50af5a
e34c4d ··/* Completed MCU, so update state */
3baeaa ··cinfo->dest->next_output_byte = state.next_output_byte;
12cfc1 ··cinfo->dest->free_in_buffer = state.free_in_buffer;
4acd9a ··ASSIGN_STATE(entropy->saved, state.cur);
32af5a
e641f1 ··/* Update restart-interval state too */
eecdfb ··if (cinfo->restart_interval) {
50258b ····if (entropy->restarts_to_go == 0) {
ac1bb3 ······entropy->restarts_to_go = cinfo->restart_interval;
294311 ······entropy->next_restart_num++;
7c6f84 ······entropy->next_restart_num &= 7;
6e6fe7 ····}
995a6d ····entropy->restarts_to_go--;
26df1c ··}
26af5a
d3d2c8 ··return TRUE;
9fefe6 }
90af5a
b0af5a
8538e5 /*
c5e17c ·* Finish up at the end of a Huffman-compressed scan.
23495d ·*/
57af5a
270434 METHODDEF(void)
5f1899 finish_pass_huff (j_compress_ptr cinfo)
11bb36 {
132609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
5f5187 ··working_state state;
42af5a
a47d29 ··/* Load up working state ... flush_bits needs it */
02c874 ··state.next_output_byte = cinfo->dest->next_output_byte;
2ed312 ··state.free_in_buffer = cinfo->dest->free_in_buffer;
4e9051 ··ASSIGN_STATE(state.cur, entropy->saved);
8fcdb9 ··state.cinfo = cinfo;
03af5a
--d5f5 0008bfe87124010000f Page 8 of jchuff.c
e807ca ··/* Flush out the last data */
14505a ··if (! flush_bits(&state))
21b7a7 ····ERREXIT(cinfo, JERR_CANT_SUSPEND);
07af5a
f19fca ··/* Update state */
d0aeaa ··cinfo->dest->next_output_byte = state.next_output_byte;
a9cfc1 ··cinfo->dest->free_in_buffer = state.free_in_buffer;
f4cd9a ··ASSIGN_STATE(entropy->saved, state.cur);
06efe6 }
68af5a
52af5a
9238e5 /*
6fa4d6 ·* Huffman coding optimization.
2c775e ·*
374f57 ·* This actually is optimization, in the sense that we find the best possible
e49264 ·* Huffman table(s) for the given data. ·We first scan the supplied data and
086644 ·* count the number of uses of each symbol that is to be Huffman-coded.
b08974 ·* (This process must agree with the code above.) ·Then we build an
13fc01 ·* optimal Huffman coding tree for the observed counts.
ca775e ·*
d7e147 ·* The JPEG standard requires Huffman codes to be no more than 16 bits long.
a48087 ·* If some symbols have a very small but nonzero probability, the Huffman tree
4af4a4 ·* must be adjusted to meet the code length restriction. ·We currently use
e5679f ·* the adjustment method suggested in the JPEG spec. ·This method is *not*
c9b49f ·* optimal; it may not choose the best possible limited-length code. ·But
882d5a ·* since the symbols involved are infrequently used, it's not clear that
f1a40b ·* going to extra trouble is worthwhile.
5a495d ·*/
8caf5a
e726f0 #ifdef ENTROPY_OPT_SUPPORTED
cdaf5a
26af5a
a86b5d /* Process a single block's worth of coefficients */
05af5a
b0afad LOCAL(void)
177b22 htest_one_block (JCOEFPTR block, int last_dc_val,
6a4b9d ¤   ¤   ·long dc_counts[], long ac_counts[])
e3bb36 {
4a9145 ··register int temp;
caca1f ··register int nbits;
f956ba ··register int k, r;
36de7b ··
3daeab ··/* Encode the DC coefficient difference per section F.1.2.1 */
f4de7b ··
abf882 ··temp = block[0] - last_dc_val;
f56559 ··if (temp < 0)
acd692 ····temp = -temp;
95de7b ··
0ea9b9 ··/* Find the number of bits needed for the magnitude of the coefficient */
e53df3 ··nbits = 0;
5cf170 ··while (temp) {
222833 ····nbits++;
27586a ····temp >>= 1;
5bdf1c ··}
b3af5a
4bb419 ··/* Count the Huffman symbol for the number of bits */
7af527 ··dc_counts[nbits]++;
3bde7b ··
601b81 ··/* Encode the AC coefficients per section F.1.2.2 */
52de7b ··
92a209 ··r = 0;¤   ¤   ¤   /* r = run length of zeros */
5ede7b ··
ef8535 ··for (k = 1; k < DCTSIZE2; k++) {
365510 ····if ((temp = block[jpeg_natural_order[k]]) == 0) {
85f436 ······r++;
e56a79 ····} else {
cd7d49 ······/* if run length > 15, must emit special run-length-16 codes (0xF0) */
ff4e0c ······while (r > 15) {
e708d0 ¤   ac_counts[0xF0]++;
35e1c1 ¤   r -= 16;
a242cc ······}
8bcf72 ······
--4a7a 000d998bbb74010000f Page 9 of jchuff.c
865406 ······/* Find the number of bits needed for the magnitude of the coefficient */
c6dd11 ······if (temp < 0)
b14469 ¤   temp = -temp;
24cf72 ······
b45406 ······/* Find the number of bits needed for the magnitude of the coefficient */
08bbeb ······nbits = 1;¤   ¤   /* there must be at least one 1 bit */
fe3af3 ······while ((temp >>= 1))
82b27d ¤   nbits++;
17cf72 ······
80b562 ······/* Count Huffman symbol for run length / number of bits */
adebf3 ······ac_counts[(r << 4) + nbits]++;
08cf72 ······
01fa14 ······r = 0;
e36fe7 ····}
1ddf1c ··}
afaf5a
6bdb58 ··/* If the last coef(s) were zero, emit an end-of-block code */
78d80e ··if (r > 0)
3e6b09 ····ac_counts[0]++;
77efe6 }
7baf5a
31af5a
0038e5 /*
08ba3a ·* Trial-encode one MCU's worth of Huffman-compressed coefficients.
1bee4d ·* No data is actually output, so no suspension return is possible.
36495d ·*/
c8af5a
cc9a8f METHODDEF(boolean)
755771 encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
8cbb36 {
512609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
b6ed99 ··int blkn, ci;
b1bcae ··jpeg_component_info * compptr;
55af5a
c5b194 ··/* Take care of restart intervals if needed */
0fcdfb ··if (cinfo->restart_interval) {
b2258b ····if (entropy->restarts_to_go == 0) {
46e5bb ······/* Re-initialize DC predictions to 0 */
2618ca ······for (ci = 0; ci < cinfo->comps_in_scan; ci++)
3ae06c ¤   entropy->saved.last_dc_val[ci] = 0;
49aebb ······/* Update restart state */
c01bb3 ······entropy->restarts_to_go = cinfo->restart_interval;
946fe7 ····}
a65a6d ····entropy->restarts_to_go--;
43df1c ··}
39af5a
bc7685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
8f153d ····ci = cinfo->MCU_membership[blkn];
9fa7cc ····compptr = cinfo->cur_comp_info[ci];
be56ff ····htest_one_block(MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
16e4b9 ¤   ¤   ····entropy->dc_count_ptrs[compptr->dc_tbl_no],
a00f7b ¤   ¤   ····entropy->ac_count_ptrs[compptr->ac_tbl_no]);
214a43 ····entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
4edf1c ··}
e4af5a
09d2c8 ··return TRUE;
73efe6 }
36af5a
58af5a
cc38e5 /*
fa5f1e ·* Generate the optimal coding for the given counts, fill htbl.
25b656 ·* Note this is also used by jcphuff.c.
94495d ·*/
2eaf5a
a2f898 GLOBAL(void)
024ae4 jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
afbb36 {
c11cfe #define MAX_CLEN 32¤¤   /* assumed maximum initial code length */
a30340 ··UINT8 bits[MAX_CLEN+1];¤  /* bits[k] = # of symbols with code length k */
2a0674 ··int codesize[257];¤   ¤   /* codesize[k] = code length of symbol k */
395812 ··int others[257];¤ ¤   /* next symbol in current branch of tree */
d9ff86 ··int c1, c2;
--3ea1 000a4ebbb414010000f Page 10 of jchuff.c
9e37d9 ··int p, i, j;
8c6310 ··long v;
95af5a
a115d8 ··/* This algorithm is explained in section K.2 of the JPEG standard */
0eaf5a
1ddf8b ··MEMZERO(bits, SIZEOF(bits));
ab40ca ··MEMZERO(codesize, SIZEOF(codesize));
0be5bd ··for (i = 0; i < 257; i++)
8809c5 ····others[i] = -1;¤¤   /* init links to empty */
74de7b ··
10931a ··freq[256] = 1;¤   ¤   /* make sure there is a nonzero count */
af4f20 ··/* Including the pseudo-symbol 256 in the Huffman procedure guarantees
2f3d5e ···* that no real symbol is given code-value of all ones, because 256
fc83c6 ···* will be placed in the largest codeword category.
42f9a6 ···*/
15af5a
9dd9ca ··/* Huffman's basic algorithm to assign optimal code lengths to symbols */
90af5a
6e6015 ··for (;;) {
94cc3a ····/* Find the smallest nonzero frequency, set c1 = its symbol */
98406f ····/* In case of ties, take the larger symbol number */
8ee5fe ····c1 = -1;
f4af97 ····v = 1000000000L;
f3d41d ····for (i = 0; i <= 256; i++) {
b08c22 ······if (freq[i] && freq[i] <= v) {
03f760 ¤   v = freq[i];
70efdb ¤   c1 = i;
c242cc ······}
af6fe7 ····}
ffaf5a
78665c ····/* Find the next smallest nonzero frequency, set c2 = its symbol */
4b406f ····/* In case of ties, take the larger symbol number */
896f2e ····c2 = -1;
d0af97 ····v = 1000000000L;
d6d41d ····for (i = 0; i <= 256; i++) {
6d7fbe ······if (freq[i] && freq[i] <= v && i != c1) {
ddf760 ¤   v = freq[i];
6947b5 ¤   c2 = i;
f042cc ······}
bd6fe7 ····}
b3af5a
4bbaab ····/* Done if we've merged everything into one frequency */
31290a ····if (c2 < 0)
4e88e1 ······break;
40869e ····
9b885a ····/* Else merge the two counts/trees */
5d6798 ····freq[c1] += freq[c2];
4db51b ····freq[c2] = 0;
e1af5a
abb383 ····/* Increment the codesize of everything in c1's tree branch */
fdcab6 ····codesize[c1]++;
8e57c9 ····while (others[c1] >= 0) {
d87b55 ······c1 = others[c1];
348885 ······codesize[c1]++;
966fe7 ····}
65869e ····
57189a ····others[c1] = c2;¤   ¤   /* chain c2 onto c1's tree branch */
7f869e ····
420e49 ····/* Increment the codesize of everything in c2's tree branch */
8dc6cb ····codesize[c2]++;
eca97a ····while (others[c2] >= 0) {
23c4b9 ······c2 = others[c2];
5f84f8 ······codesize[c2]++;
d16fe7 ····}
3edf1c ··}
f8af5a
165b8b ··/* Now count the number of symbols of each code length */
deb054 ··for (i = 0; i <= 256; i++) {
bc4e1b ····if (codesize[i]) {
680bb7 ······/* The JPEG standard seems to think that this can't happen, */
74d577 ······/* but I'm paranoid... */
a4d93d ······if (codesize[i] > MAX_CLEN)
--157d 000b708fcb14010000f Page 11 of jchuff.c
078afd ¤   ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);
f5af5a
0efe3b ······bits[codesize[i]]++;
4a6fe7 ····}
f9df1c ··}
15af5a
fa40ab ··/* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
a29940 ···* Huffman procedure assigned any such lengths, we must adjust the coding.
53559a ···* Here is what the JPEG spec says about how this next bit works:
d14e9f ···* Since symbols are paired for the longest Huffman code, the symbols are
47998e ···* removed from this length category two at a time. ·The prefix for the pair
c33987 ···* (which is one bit shorter) is allocated to one of the pair; then,
e63c98 ···* skipping the BITS entry for that prefix length, a code word from the next
39df79 ···* shortest nonzero BITS entry is converted into a prefix for two code words
fcf9c0 ···* one bit longer.
80f9a6 ···*/
e9de7b ··
53abf7 ··for (i = MAX_CLEN; i > 16; i--) {
a71162 ····while (bits[i] > 0) {
c98232 ······j = i - 2;¤   ¤   /* find length of new prefix to be used */
9a70a5 ······while (bits[j] == 0)
63b4cb ¤   j--;
24cf72 ······
a664fc ······bits[i] -= 2;¤¤   /* remove two symbols */
3af098 ······bits[i-1]++;¤ ¤   /* one goes in this length */
48148b ······bits[j+1] += 2;¤  ¤   /* two new symbols in this length */
9d86dd ······bits[j]--;¤   ¤   /* symbol of this length is now a prefix */
ae6fe7 ····}
e7df1c ··}
cfaf5a
c830d9 ··/* Remove the count for the pseudo-symbol 256 from the largest codelength */
8ad077 ··while (bits[i] == 0)¤ ¤   /* find largest codelength still in use */
a6230f ····i--;
a9661f ··bits[i]--;
6cde7b ··
407681 ··/* Return final symbol counts (only for lengths 0..16) */
ef139d ··MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits));
a6de7b ··
40be09 ··/* Return a list of the symbols sorted by code length */
568ad0 ··/* It's not real clear to me why we don't need to consider the codelength
8952e5 ···* changes made above, but the JPEG spec seems to think this works.
09f9a6 ···*/
9657d8 ··p = 0;
0373b6 ··for (i = 1; i <= MAX_CLEN; i++) {
50d5c7 ····for (j = 0; j <= 255; j++) {
0dfcd2 ······if (codesize[j] == i) {
6fc546 ¤   htbl->huffval[p] = (UINT8) j;
4dd160 ¤   p++;
3b42cc ······}
0b6fe7 ····}
8fdf1c ··}
eaaf5a
1901a8 ··/* Set sent_table FALSE so updated table will be written to JPEG file. */
3153a0 ··htbl->sent_table = FALSE;
7aefe6 }
0baf5a
91af5a
8738e5 /*
c32a39 ·* Finish up a statistics-gathering pass and create the new Huffman tables.
89495d ·*/
cbaf5a
280434 METHODDEF(void)
bb6b63 finish_pass_gather (j_compress_ptr cinfo)
88bb36 {
872609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
ce0d5c ··int ci, dctbl, actbl;
51bcae ··jpeg_component_info * compptr;
004916 ··JHUFF_TBL **htblptr;
703e5d ··boolean did_dc[NUM_HUFF_TBLS];
e7f012 ··boolean did_ac[NUM_HUFF_TBLS];
74af5a
b788e1 ··/* It's important not to apply jpeg_gen_optimal_table more than once
--e2f6 001f73ebf3d4010000f Page 12 of jchuff.c
99b07d ···* per table, because it clobbers the input frequency counts!
14f9a6 ···*/
50a631 ··MEMZERO(did_dc, SIZEOF(did_dc));
df586a ··MEMZERO(did_ac, SIZEOF(did_ac));
d1af5a
f16aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
6aa7cc ····compptr = cinfo->cur_comp_info[ci];
1080fc ····dctbl = compptr->dc_tbl_no;
12656d ····actbl = compptr->ac_tbl_no;
73b942 ····if (! did_dc[dctbl]) {
823f86 ······htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
e2f366 ······if (*htblptr == NULL)
18f814 ¤   *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
d35c98 ······jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
eb6bc2 ······did_dc[dctbl] = TRUE;
7c6fe7 ····}
6536e0 ····if (! did_ac[actbl]) {
0abd70 ······htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
edf366 ······if (*htblptr == NULL)
53f814 ¤   *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
7d904f ······jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
be0819 ······did_ac[actbl] = TRUE;
4a6fe7 ····}
1fdf1c ··}
a2efe6 }
66af5a
f3af5a
fd856b #endif /* ENTROPY_OPT_SUPPORTED */
44af5a
bdaf5a
5538e5 /*
f6e585 ·* Module initialization routine for Huffman entropy encoding.
92495d ·*/
8eaf5a
67f898 GLOBAL(void)
c01a75 jinit_huff_encoder (j_compress_ptr cinfo)
f8bb36 {
3850ef ··huff_entropy_ptr entropy;
3017e0 ··int i;
e1af5a
9ac76a ··entropy = (huff_entropy_ptr)
573f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
31f9ac ¤   ¤   ¤   ¤   SIZEOF(huff_entropy_encoder));
aa5c82 ··cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
d97674 ··entropy->pub.start_pass = start_pass_huff;
54af5a
1e4d66 ··/* Mark tables unallocated */
a472db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
805166 ····entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
1a26f0 #ifdef ENTROPY_OPT_SUPPORTED
bafc32 ····entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
777454 #endif
5bdf1c ··}
f7efe6 }
--77fd 001b24d651040100010 Page 1 of jchuff.h
bc38e5 /*
d11369 ·* jchuff.h
cf775e ·*
b5a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
67fb07 ·* This file is part of the Independent JPEG Group's software.
eea0d6 ·* For conditions of distribution and use, see the accompanying README file.
60775e ·*
d4df9d ·* This file contains declarations for Huffman entropy encoding routines
882504 ·* that are shared between the sequential encoder (jchuff.c) and the
96b2f3 ·* progressive encoder (jcphuff.c). ·No other modules need to see these.
11495d ·*/
efaf5a
e59079 /* Derived data constructed for each Huffman table */
86af5a
00f0f7 typedef struct {
4ca9fc ··unsigned int ehufco[256];¤/* code for each symbol */
8c5cf6 ··char ehufsi[256];¤¤   /* length of code for each symbol */
1a669c ··/* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
1da95f } c_derived_tbl;
24af5a
4b4b22 /* Short forms of external names for systems with brain-damaged linkers. */
e2af5a
5fddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
c589a1 #define jpeg_make_c_derived_tbl¤jMkCDerived
f0a9ca #define jpeg_gen_optimal_table¤ jGenOptTbl
505892 #endif /* NEED_SHORT_EXTERNAL_NAMES */
a1af5a
a08943 /* Expand a Huffman table definition into the derived format */
0badb6 EXTERN(void) jpeg_make_c_derived_tbl
ac8c13 ¤   JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, c_derived_tbl ** pdtbl));
56af5a
b715e9 /* Generate an optimal table definition given the specified counts */
1f5ec8 EXTERN(void) jpeg_gen_optimal_table
b20d3b ¤   JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));
--b7f5 0012b7878c840100011 Page 1 of jcinit.c
bc38e5 /*
8597aa ·* jcinit.c
50775e ·*
78a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
cefb07 ·* This file is part of the Independent JPEG Group's software.
d9a0d6 ·* For conditions of distribution and use, see the accompanying README file.
5f775e ·*
422705 ·* This file contains initialization logic for the JPEG compressor.
57fde3 ·* This routine is in charge of selecting the modules to be executed and
037114 ·* making an initialization call to each one.
1a775e ·*
fe1c29 ·* Logically, this code belongs in jcmaster.c. ·It's split out because
222a6f ·* linking this routine implies linking the entire compression library.
2c6bff ·* For a transcoding-only application, we want to be able to use jcmaster.c
4ddd6b ·* without linking in the whole library.
49495d ·*/
2aaf5a
1e2bb6 #define JPEG_INTERNALS
e036a7 #include "jinclude.h"
b86c8f #include "jpeglib.h"
d2af5a
7faf5a
2538e5 /*
768d9b ·* Master selection of compression modules.
06ed40 ·* This is done once at the start of processing an image. ·We determine
7d76d2 ·* which modules will be used and give them appropriate initialization calls.
96495d ·*/
68af5a
d8f898 GLOBAL(void)
4ef4c6 jinit_compress_master (j_compress_ptr cinfo)
3ebb36 {
34cc00 ··/* Initialize master control (includes parameter checking/processing) */
0dc3e6 ··jinit_c_master_control(cinfo, FALSE /* full compression */);
dfaf5a
763839 ··/* Preprocessing */
a3d61e ··if (! cinfo->raw_data_in) {
229b5d ····jinit_color_converter(cinfo);
06a006 ····jinit_downsampler(cinfo);
0ec281 ····jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
42df1c ··}
11443a ··/* Forward DCT */
75d3e8 ··jinit_forward_dct(cinfo);
9d4fff ··/* Entropy encoding: either Huffman or arithmetic coding. */
f9a4f1 ··if (cinfo->arith_code) {
223fef ····ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
d749d8 ··} else {
e78aef ····if (cinfo->progressive_mode) {
e268ad #ifdef C_PROGRESSIVE_SUPPORTED
93ff89 ······jinit_phuff_encoder(cinfo);
d8db21 #else
6f9015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
9c7454 #endif
4cce75 ····} else
b7b182 ······jinit_huff_encoder(cinfo);
57df1c ··}
4baf5a
d45bc6 ··/* Need a full-image coefficient buffer in any multi-pass mode. */
92df43 ··jinit_c_coef_controller(cinfo,
422de8 ¤   ¤   ¤   ··(cinfo->num_scans > 1 || cinfo->optimize_coding));
9477ca ··jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
a4af5a
6b6557 ··jinit_marker_writer(cinfo);
d0af5a
405924 ··/* We can now tell the memory manager to allocate virtual arrays. */
eda9b1 ··(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
24af5a
6fa7ac ··/* Write the datastream header (SOI) immediately.
0f2402 ···* Frame and scan headers are postponed till later.
fc4f45 ···* This lets application insert special markers after the SOI.
aaf9a6 ···*/
2e89a9 ··(*cinfo->marker->write_file_header) (cinfo);
2befe6 }
--2ef2 00056df616d40100012 Page 1 of jcmainct.c
bc38e5 /*
03febb ·* jcmainct.c
11775e ·*
989e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
92fb07 ·* This file is part of the Independent JPEG Group's software.
5ea0d6 ·* For conditions of distribution and use, see the accompanying README file.
c7775e ·*
27a41e ·* This file contains the main buffer controller for compression.
c4d2a6 ·* The main buffer lies between the pre-processor and the JPEG
5fd673 ·* compressor proper; it holds downsampled data in the JPEG colorspace.
89495d ·*/
51af5a
032bb6 #define JPEG_INTERNALS
ee36a7 #include "jinclude.h"
2e6c8f #include "jpeglib.h"
64af5a
d2af5a
aff8b8 /* Note: currently, there is no operating mode in which a full-image buffer
81a0eb ·* is needed at this step. ·If there were, that mode could not be used with
ac4776 ·* "raw data" input, since this module is bypassed in that case. ·However,
917b56 ·* we've left the code here for possible use in special applications.
dc495d ·*/
1594e4 #undef FULL_MAIN_BUFFER_SUPPORTED
4aaf5a
77af5a
668416 /* Private buffer controller object */
9caf5a
a4f0f7 typedef struct {
12c812 ··struct jpeg_c_main_controller pub; /* public fields */
ebaf5a
d39bab ··JDIMENSION cur_iMCU_row;¤ /* number of current iMCU row */
994f0f ··JDIMENSION rowgroup_ctr;¤ /* counts row groups received in iMCU row */
246008 ··boolean suspended;¤   ¤   /* remember if we suspended output */
64774f ··J_BUF_MODE pass_mode;¤¤   /* current operating mode */
54af5a
6385b5 ··/* If using just a strip buffer, this points to the entire set of buffers
f194a1 ···* (we allocate one for each component). ·In the full-image case, this
660e9a ···* points to the currently accessible strips of the virtual arrays.
73f9a6 ···*/
980d09 ··JSAMPARRAY buffer[MAX_COMPONENTS];
1baf5a
500b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
b3d57f ··/* If using full-image storage, this array holds pointers to virtual-array
a19562 ···* control blocks for each component. ·Unused if not full-image storage.
57f9a6 ···*/
517e66 ··jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
227454 #endif
c9d9e9 } my_main_controller;
02af5a
186786 typedef my_main_controller * my_main_ptr;
03af5a
5faf5a
806a43 /* Forward declarations */
867e0e METHODDEF(void) process_data_simple_main
7b7349 ¤   JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
64a05c ¤   ·····JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
b20b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
4fe520 METHODDEF(void) process_data_buffer_main
b47349 ¤   JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
4ea05c ¤   ·····JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
9f7454 #endif
29af5a
e8af5a
4338e5 /*
335b80 ·* Initialize for a processing pass.
15495d ·*/
96af5a
9e0434 METHODDEF(void)
72cac8 start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
bbbb36 {
6cb438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
56af5a
--f892 0008fa506a740100012 Page 2 of jcmainct.c
36300e ··/* Do nothing in raw-data mode. */
435172 ··if (cinfo->raw_data_in)
073471 ····return;
4daf5a
31e793 ··main->cur_iMCU_row = 0;¤  /* initialize counters */
a618f1 ··main->rowgroup_ctr = 0;
0ad772 ··main->suspended = FALSE;
464e55 ··main->pass_mode = pass_mode;¤ /* save mode for use by process_data */
8caf5a
0e1eec ··switch (pass_mode) {
b6972e ··case JBUF_PASS_THRU:
120b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
8e0ed8 ····if (main->whole_image[0] != NULL)
260c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
e87454 #endif
9f15b4 ····main->pub.process_data = process_data_simple_main;
a9ab40 ····break;
f40b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
9d1aa2 ··case JBUF_SAVE_SOURCE:
746409 ··case JBUF_CRANK_DEST:
65e8d2 ··case JBUF_SAVE_AND_PASS:
5db163 ····if (main->whole_image[0] == NULL)
2b0c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
16dd53 ····main->pub.process_data = process_data_buffer_main;
33ab40 ····break;
8d7454 #endif
ba969d ··default:
34650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
2fab40 ····break;
abdf1c ··}
dbefe6 }
bfaf5a
6daf5a
ac38e5 /*
9f3bfc ·* Process some data.
17f98c ·* This routine handles the simple pass-through mode,
c5ba53 ·* where we have only a strip buffer.
d6495d ·*/
f3af5a
710434 METHODDEF(void)
be2547 process_data_simple_main (j_compress_ptr cinfo,
cc87c0 ¤   ¤   ¤   ··JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
f3072c ¤   ¤   ¤   ··JDIMENSION in_rows_avail)
17bb36 {
d3b438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
84af5a
76e95f ··while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
f592e4 ····/* Read input data if we haven't filled the main buffer yet */
30163f ····if (main->rowgroup_ctr < DCTSIZE)
608201 ······(*cinfo->prep->pre_process_data) (cinfo,
14dacd ¤   ¤   ¤   ¤   ¤   input_buf, in_row_ctr, in_rows_avail,
bfcc6d ¤   ¤   ¤   ¤   ¤   main->buffer, &main->rowgroup_ctr,
fd8c2b ¤   ¤   ¤   ¤   ¤   (JDIMENSION) DCTSIZE);
9baf5a
10f7d7 ····/* If we don't have a full iMCU row buffered, return to application for
26fd77 ·····* more data. ·Note that preprocessor will always pad to fill the iMCU row
306c31 ·····* at the bottom of the image.
a9d48d ·····*/
1f8105 ····if (main->rowgroup_ctr != DCTSIZE)
7180d1 ······return;
f3af5a
c97c5a ····/* Send the completed row to the compressor */
a4e09a ····if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
9ed9f6 ······/* If compressor did not consume the whole row, then we must need to
28dbf2 ·······* suspend processing and return to the application. ·In this situation
03e3b5 ·······* we pretend we didn't yet consume the last input row; otherwise, if
5c47a4 ·······* it happened to be the last row of the image, the application would
ff6d45 ·······* think we were done.
14e9f1 ·······*/
d9be70 ······if (! main->suspended) {
edf9c5 ¤   (*in_row_ctr)--;
8f1b65 ¤   main->suspended = TRUE;
--62c8 0001564cc6440100012 Page 3 of jcmainct.c
a642cc ······}
5f80d1 ······return;
546fe7 ····}
445c6f ····/* We did finish the row. ·Undo our little suspension hack if a previous
f08433 ·····* call suspended; then mark the main buffer empty.
8ed48d ·····*/
afa99a ····if (main->suspended) {
6fe8a3 ······(*in_row_ctr)++;
cc13e5 ······main->suspended = FALSE;
4d6fe7 ····}
4a04f6 ····main->rowgroup_ctr = 0;
221df8 ····main->cur_iMCU_row++;
e4df1c ··}
8fefe6 }
91af5a
c1af5a
a20b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
92af5a
f138e5 /*
903bfc ·* Process some data.
9db020 ·* This routine handles all of the modes that use a full-size buffer.
4e495d ·*/
34af5a
cb0434 METHODDEF(void)
119868 process_data_buffer_main (j_compress_ptr cinfo,
a787c0 ¤   ¤   ¤   ··JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
c7072c ¤   ¤   ¤   ··JDIMENSION in_rows_avail)
46bb36 {
e7b438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
6d0dcc ··int ci;
4333b0 ··jpeg_component_info *compptr;
313f17 ··boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
44af5a
37e95f ··while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
b2742a ····/* Realign the virtual buffers if at the start of an iMCU row. */
3dc5ca ····if (main->rowgroup_ctr == 0) {
1db18b ······for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
6f4a9f ¤   ···ci++, compptr++) {
aa05ff ¤   main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
6ffbd0 ¤   ··((j_common_ptr) cinfo, main->whole_image[ci],
4cdbbb ¤   ···main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE),
e7f827 ¤   ···(JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing);
f942cc ······}
d26ffa ······/* In a read pass, pretend we just read some source data. */
2522be ······if (! writing) {
cb95bf ¤   *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
95fd8e ¤   main->rowgroup_ctr = DCTSIZE;
3c42cc ······}
086fe7 ····}
82af5a
3c16df ····/* If a write pass, read input data until the current iMCU row is full. */
ca85f5 ····/* Note: preprocessor will pad if necessary to fill the last iMCU row. */
7d28d6 ····if (writing) {
0a8201 ······(*cinfo->prep->pre_process_data) (cinfo,
89dacd ¤   ¤   ¤   ¤   ¤   input_buf, in_row_ctr, in_rows_avail,
cdcc6d ¤   ¤   ¤   ¤   ¤   main->buffer, &main->rowgroup_ctr,
558c2b ¤   ¤   ¤   ¤   ¤   (JDIMENSION) DCTSIZE);
a48178 ······/* Return to application if we need more data to fill the iMCU row. */
4c071d ······if (main->rowgroup_ctr < DCTSIZE)
5b830f ¤   return;
9b6fe7 ····}
30af5a
177755 ····/* Emit data, unless this is a sink-only pass. */
b7b355 ····if (main->pass_mode != JBUF_SAVE_SOURCE) {
c3253c ······if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
772000 ¤   /* If compressor did not consume the whole row, then we must need to
0c2a0f ¤   ·* suspend processing and return to the application. ·In this situation
2771f5 ¤   ·* we pretend we didn't yet consume the last input row; otherwise, if
88d5e4 ¤   ·* it happened to be the last row of the image, the application would
9101c7 ¤   ·* think we were done.
15a4e3 ¤   ·*/
15a866 ¤   if (! main->suspended) {
--57a9 0004275255840100012 Page 4 of jcmainct.c
637a13 ¤   ··(*in_row_ctr)--;
77bea5 ¤   ··main->suspended = TRUE;
359371 ¤   }
06830f ¤   return;
5a42cc ······}
e68a08 ······/* We did finish the row. ·Undo our little suspension hack if a previous
ba800d ·······* call suspended; then mark the main buffer empty.
57e9f1 ·······*/
05dd39 ······if (main->suspended) {
9b6486 ¤   (*in_row_ctr)++;
7f05f3 ¤   main->suspended = FALSE;
ff42cc ······}
806fe7 ····}
c7af5a
90b4bb ····/* If get here, we are done with this iMCU row. ·Mark buffer empty. */
0204f6 ····main->rowgroup_ctr = 0;
7f1df8 ····main->cur_iMCU_row++;
19df1c ··}
49efe6 }
4aaf5a
3e23a1 #endif /* FULL_MAIN_BUFFER_SUPPORTED */
2faf5a
d1af5a
4838e5 /*
a62bab ·* Initialize main buffer controller.
2c495d ·*/
b4af5a
e6f898 GLOBAL(void)
55a979 jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
adbb36 {
b189cf ··my_main_ptr main;
4a0dcc ··int ci;
0033b0 ··jpeg_component_info *compptr;
c5af5a
d6ce41 ··main = (my_main_ptr)
f73f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
7a2d80 ¤   ¤   ¤   ¤   SIZEOF(my_main_controller));
9a8e9d ··cinfo->main = (struct jpeg_c_main_controller *) main;
ec0191 ··main->pub.start_pass = start_pass_main;
2caf5a
f64f93 ··/* We don't need to create a buffer in raw-data mode. */
d05172 ··if (cinfo->raw_data_in)
e03471 ····return;
82af5a
c1d7e0 ··/* Create the buffer. ·It holds downsampled data, so each component
21b9da ···* may be of a different size.
fcf9a6 ···*/
ecbaf2 ··if (need_full_buffer) {
0d0b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
52a001 ····/* Allocate a full-image virtual array for each component */
b9bc52 ····/* Note we pad the bottom to a multiple of the iMCU height */
d86090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
7eb5ed ¤   ·ci++, compptr++) {
d5b7c7 ······main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
c8d16b ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
6c1822 ¤   ·compptr->width_in_blocks * DCTSIZE,
0c954d ¤   ·(JDIMENSION) jround_up((long) compptr->height_in_blocks,
34a0a8 ¤   ¤   ¤   ¤   (long) compptr->v_samp_factor) * DCTSIZE,
6e2e51 ¤   ·(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
b56fe7 ····}
63db21 #else
ff650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
9b7454 #endif
f349d8 ··} else {
1a0b14 #ifdef FULL_MAIN_BUFFER_SUPPORTED
1119fc ····main->whole_image[0] = NULL; /* flag for no virtual arrays */
e87454 #endif
beb9ec ····/* Allocate a strip buffer for each component */
226090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
beb5ed ¤   ·ci++, compptr++) {
7cba87 ······main->buffer[ci] = (*cinfo->mem->alloc_sarray)
42ee7d ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE,
--4415 00141a1465e40100012 Page 5 of jcmainct.c
f91822 ¤   ·compptr->width_in_blocks * DCTSIZE,
922e51 ¤   ·(JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
c86fe7 ····}
36df1c ··}
41efe6 }
--679b 000c65d606340100013 Page 1 of jcmarker.c
bc38e5 /*
9c5975 ·* jcmarker.c
21775e ·*
45a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
dffb07 ·* This file is part of the Independent JPEG Group's software.
5aa0d6 ·* For conditions of distribution and use, see the accompanying README file.
b4775e ·*
1d94ef ·* This file contains routines to write JPEG datastream markers.
f0495d ·*/
f1af5a
b72bb6 #define JPEG_INTERNALS
9036a7 #include "jinclude.h"
676c8f #include "jpeglib.h"
64af5a
84af5a
66c4b8 typedef enum {¤ ¤   ¤   /* JPEG marker codes */
d91a61 ··M_SOF0 ·= 0xc0,
e5152c ··M_SOF1 ·= 0xc1,
8a04fb ··M_SOF2 ·= 0xc2,
6e0bb6 ··M_SOF3 ·= 0xc3,
eade7b ··
552818 ··M_SOF5 ·= 0xc5,
9239cf ··M_SOF6 ·= 0xc6,
093682 ··M_SOF7 ·= 0xc7,
bcde7b ··
c6b447 ··M_JPG ··= 0xc8,
bd6f44 ··M_SOF9 ·= 0xc9,
8d963c ··M_SOF10 = 0xca,
33557f ··M_SOF11 = 0xcb,
c8de7b ··
eddbe8 ··M_SOF13 = 0xcd,
a245c1 ··M_SOF14 = 0xce,
8d8682 ··M_SOF15 = 0xcf,
d3de7b ··
181564 ··M_DHT ··= 0xc4,
b1de7b ··
a2a507 ··M_DAC ··= 0xcc,
d6de7b ··
8445c5 ··M_RST0 ·= 0xd0,
dd4a88 ··M_RST1 ·= 0xd1,
645b5f ··M_RST2 ·= 0xd2,
545412 ··M_RST3 ·= 0xd3,
7178f1 ··M_RST4 ·= 0xd4,
bb77bc ··M_RST5 ·= 0xd5,
99666b ··M_RST6 ·= 0xd6,
b36926 ··M_RST7 ·= 0xd7,
46de7b ··
7bc6e2 ··M_SOI ··= 0xd8,
1a4484 ··M_EOI ··= 0xd9,
16c490 ··M_SOS ··= 0xda,
f1656a ··M_DQT ··= 0xdb,
ee4f79 ··M_DNL ··= 0xdc,
c42253 ··M_DRI ··= 0xdd,
d59e0c ··M_DHP ··= 0xde,
d85552 ··M_EXP ··= 0xdf,
08de7b ··
270716 ··M_APP0 ·= 0xe0,
68085b ··M_APP1 ·= 0xe1,
b5198c ··M_APP2 ·= 0xe2,
7116c1 ··M_APP3 ·= 0xe3,
c93a22 ··M_APP4 ·= 0xe4,
a4356f ··M_APP5 ·= 0xe5,
1524b8 ··M_APP6 ·= 0xe6,
e72bf5 ··M_APP7 ·= 0xe7,
f77d7e ··M_APP8 ·= 0xe8,
2e7233 ··M_APP9 ·= 0xe9,
648b4b ··M_APP10 = 0xea,
2b4808 ··M_APP11 = 0xeb,
0c66bd ··M_APP12 = 0xec,
1fc69f ··M_APP13 = 0xed,
4e58b6 ··M_APP14 = 0xee,
c69bf5 ··M_APP15 = 0xef,
--25e9 00037223f9040100013 Page 2 of jcmarker.c
8bde7b ··
82d9c6 ··M_JPG0 ·= 0xf0,
99184f ··M_JPG13 = 0xfd,
0850a9 ··M_COM ··= 0xfe,
0ade7b ··
7aaec5 ··M_TEM ··= 0x01,
60de7b ··
c08170 ··M_ERROR = 0x100
5ec177 } JPEG_MARKER;
45af5a
63af5a
1338e5 /*
d2baad ·* Basic output routines.
8e775e ·*
94bc1a ·* Note that we do not support suspension while writing a marker.
2c4496 ·* Therefore, an application using suspension must ensure that there is
f4d8b8 ·* enough buffer space for the initial markers (typ. 600-700 bytes) before
0e5f03 ·* calling jpeg_start_compress, and enough space to write the trailing EOI
6a1630 ·* (a few bytes) before calling jpeg_finish_compress. ·Multipass compression
4ae05a ·* modes are not supported at all with suspension, so those two are the only
55053b ·* points where markers will be written.
67495d ·*/
33af5a
cdafad LOCAL(void)
4865e7 emit_byte (j_compress_ptr cinfo, int val)
b41941 /* Emit a byte */
abbb36 {
6a292d ··struct jpeg_destination_mgr * dest = cinfo->dest;
17af5a
5728fe ··*(dest->next_output_byte)++ = (JOCTET) val;
ee3e3f ··if (--dest->free_in_buffer == 0) {
cc3561 ····if (! (*dest->empty_output_buffer) (cinfo))
f3b5a6 ······ERREXIT(cinfo, JERR_CANT_SUSPEND);
7ddf1c ··}
29efe6 }
c4af5a
0eaf5a
aaafad LOCAL(void)
2c8227 emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
ce2f0d /* Emit a marker code */
cbbb36 {
856bc7 ··emit_byte(cinfo, 0xFF);
5e46ad ··emit_byte(cinfo, (int) mark);
d6efe6 }
e3af5a
d7af5a
55afad LOCAL(void)
b0cadf emit_2bytes (j_compress_ptr cinfo, int value)
9e7433 /* Emit a 2-byte integer; these are always MSB first in JPEG files */
fabb36 {
927e4d ··emit_byte(cinfo, (value >> 8) & 0xFF);
5cb8f0 ··emit_byte(cinfo, value & 0xFF);
99efe6 }
99af5a
ddaf5a
b638e5 /*
d3979a ·* Routines to write specific marker types.
22495d ·*/
cdaf5a
87aa6a LOCAL(int)
7e3cbf emit_dqt (j_compress_ptr cinfo, int index)
2d0908 /* Emit a DQT marker */
d21a9d /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
57bb36 {
fe7c11 ··JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
bb1ad9 ··int prec;
f117e0 ··int i;
2faf5a
4e3d2d ··if (qtbl == NULL)
0a5d78 ····ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
a7af5a
377849 ··prec = 0;
--2e34 0004981bf5b40100013 Page 3 of jcmarker.c
06133f ··for (i = 0; i < DCTSIZE2; i++) {
82bcff ····if (qtbl->quantval[i] > 255)
9cca65 ······prec = 1;
70df1c ··}
77af5a
36d001 ··if (! qtbl->sent_table) {
1337a6 ····emit_marker(cinfo, M_DQT);
abaf5a
e46576 ····emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
09af5a
c52027 ····emit_byte(cinfo, index + (prec<<4));
1eaf5a
0c9ac7 ····for (i = 0; i < DCTSIZE2; i++) {
96033e ······/* The table entries must be emitted in zigzag order. */
918e75 ······unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
77dd79 ······if (prec)
08e98b ¤   emit_byte(cinfo, qval >> 8);
af9080 ······emit_byte(cinfo, qval & 0xFF);
736fe7 ····}
b1af5a
0ff9c1 ····qtbl->sent_table = TRUE;
e5df1c ··}
cfaf5a
45be85 ··return prec;
f4efe6 }
83af5a
c1af5a
beafad LOCAL(void)
893e01 emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
a17b1d /* Emit a DHT marker */
e6bb36 {
10a9a2 ··JHUFF_TBL * htbl;
e326b6 ··int length, i;
3dde7b ··
c9bca6 ··if (is_ac) {
54f35c ····htbl = cinfo->ac_huff_tbl_ptrs[index];
bbcaa4 ····index += 0x10;¤ ¤   /* output index has AC bit set */
8249d8 ··} else {
14e6cb ····htbl = cinfo->dc_huff_tbl_ptrs[index];
5adf1c ··}
fcaf5a
5a7a73 ··if (htbl == NULL)
e14682 ····ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
b5de7b ··
32583c ··if (! htbl->sent_table) {
7ad282 ····emit_marker(cinfo, M_DHT);
0c869e ····
8506da ····length = 0;
49903a ····for (i = 1; i <= 16; i++)
9b462c ······length += htbl->bits[i];
84869e ····
70a0b2 ····emit_2bytes(cinfo, length + 2 + 1 + 16);
48b03e ····emit_byte(cinfo, index);
e6869e ····
1e903a ····for (i = 1; i <= 16; i++)
057911 ······emit_byte(cinfo, htbl->bits[i]);
d9869e ····
c3de6a ····for (i = 0; i < length; i++)
15805c ······emit_byte(cinfo, htbl->huffval[i]);
82869e ····
4b99d2 ····htbl->sent_table = TRUE;
03df1c ··}
1fefe6 }
02af5a
f2af5a
11afad LOCAL(void)
51e7bb emit_dac (j_compress_ptr cinfo)
ddc498 /* Emit a DAC marker */
b8b93c /* Since the useful info is so small, we want to emit all the tables in */
2a9d4e /* one DAC marker. ·Therefore this routine does its own scan of the table. */
5dbb36 {
498f52 #ifdef C_ARITH_CODING_SUPPORTED
--8c9a 000e205b60640100013 Page 4 of jcmarker.c
e048b5 ··char dc_in_use[NUM_ARITH_TBLS];
135bcc ··char ac_in_use[NUM_ARITH_TBLS];
c726b6 ··int length, i;
6833b0 ··jpeg_component_info *compptr;
e0de7b ··
29925d ··for (i = 0; i < NUM_ARITH_TBLS; i++)
38d7e6 ····dc_in_use[i] = ac_in_use[i] = 0;
74de7b ··
bf23fc ··for (i = 0; i < cinfo->comps_in_scan; i++) {
05fe66 ····compptr = cinfo->cur_comp_info[i];
1f5ac0 ····dc_in_use[compptr->dc_tbl_no] = 1;
28c56f ····ac_in_use[compptr->ac_tbl_no] = 1;
5bdf1c ··}
9bde7b ··
f35a8a ··length = 0;
08925d ··for (i = 0; i < NUM_ARITH_TBLS; i++)
1515c6 ····length += dc_in_use[i] + ac_in_use[i];
f8de7b ··
a4a752 ··emit_marker(cinfo, M_DAC);
b1de7b ··
e83875 ··emit_2bytes(cinfo, length*2 + 2);
5dde7b ··
851f63 ··for (i = 0; i < NUM_ARITH_TBLS; i++) {
f0880e ····if (dc_in_use[i]) {
a805f3 ······emit_byte(cinfo, i);
22d2f4 ······emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
a56fe7 ····}
bf2e7c ····if (ac_in_use[i]) {
10c200 ······emit_byte(cinfo, i + 0x10);
5030a7 ······emit_byte(cinfo, cinfo->arith_ac_K[i]);
d56fe7 ····}
7ddf1c ··}
8da00e #endif /* C_ARITH_CODING_SUPPORTED */
48efe6 }
c6af5a
81af5a
c8afad LOCAL(void)
4326b8 emit_dri (j_compress_ptr cinfo)
6798e8 /* Emit a DRI marker */
90bb36 {
41d270 ··emit_marker(cinfo, M_DRI);
dede7b ··
f16b07 ··emit_2bytes(cinfo, 4);¤   /* fixed length */
9caf5a
6bf1e6 ··emit_2bytes(cinfo, (int) cinfo->restart_interval);
59efe6 }
f4af5a
68af5a
96afad LOCAL(void)
67ccfa emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
67d26d /* Emit a SOF marker */
fabb36 {
a20dcc ··int ci;
f233b0 ··jpeg_component_info *compptr;
5ade7b ··
0c07c8 ··emit_marker(cinfo, code);
96de7b ··
782cbb ··emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
24af5a
b9be5e ··/* Make sure image isn't bigger than SOF field can handle */
003c9a ··if ((long) cinfo->image_height > 65535L ||
5a0252 ······(long) cinfo->image_width > 65535L)
e27c17 ····ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
c6af5a
d0015d ··emit_byte(cinfo, cinfo->data_precision);
50ca34 ··emit_2bytes(cinfo, (int) cinfo->image_height);
3765b2 ··emit_2bytes(cinfo, (int) cinfo->image_width);
a8af5a
0afd9d ··emit_byte(cinfo, cinfo->num_components);
edaf5a
b5958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
e2aa07 ·······ci++, compptr++) {
--5845 00020ff638040100013 Page 5 of jcmarker.c
1bb74c ····emit_byte(cinfo, compptr->component_id);
3477e8 ····emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
c311c2 ····emit_byte(cinfo, compptr->quant_tbl_no);
42df1c ··}
a5efe6 }
21af5a
32af5a
01afad LOCAL(void)
16fe13 emit_sos (j_compress_ptr cinfo)
414796 /* Emit a SOS marker */
50bb36 {
b264a5 ··int i, td, ta;
d333b0 ··jpeg_component_info *compptr;
edde7b ··
7f5b2a ··emit_marker(cinfo, M_SOS);
d8de7b ··
64d678 ··emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
fade7b ··
3928d0 ··emit_byte(cinfo, cinfo->comps_in_scan);
d9de7b ··
f523fc ··for (i = 0; i < cinfo->comps_in_scan; i++) {
d7fe66 ····compptr = cinfo->cur_comp_info[i];
b4b74c ····emit_byte(cinfo, compptr->component_id);
1cb84b ····td = compptr->dc_tbl_no;
ea8dca ····ta = compptr->ac_tbl_no;
918aef ····if (cinfo->progressive_mode) {
1437b3 ······/* Progressive mode: only DC or only AC tables are used in one scan;
40907f ·······* furthermore, Huffman coding of DC refinement uses no table at all.
c66383 ·······* We emit 0 for unused field(s); this is recommended by the P&M text
ec04da ·······* but does not seem to be specified in the standard.
c2e9f1 ·······*/
dc9786 ······if (cinfo->Ss == 0) {
a54093 ¤   ta = 0;¤¤   ¤   /* DC scan */
16b454 ¤   if (cinfo->Ah != 0 && !cinfo->arith_code)
0c8cf2 ¤   ··td = 0;¤  ¤   /* no DC table either */
d1cfc7 ······} else {
c14e91 ¤   td = 0;¤¤   ¤   /* AC scan */
6942cc ······}
276fe7 ····}
fafdd0 ····emit_byte(cinfo, (td << 4) + ta);
86df1c ··}
b6af5a
02c616 ··emit_byte(cinfo, cinfo->Ss);
424e2d ··emit_byte(cinfo, cinfo->Se);
a59ac4 ··emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
6befe6 }
77af5a
bcaf5a
41afad LOCAL(void)
dd15db emit_jfif_app0 (j_compress_ptr cinfo)
b1ad9b /* Emit a JFIF-compliant APP0 marker */
3cbb36 {
e86000 ··/*
8a4062 ···* Length of APP0 block¤  (2 bytes)
8fe6dc ···* Block ID¤  ¤   ¤   (4 bytes - ASCII "JFIF")
3aa076 ···* Zero byte¤ ¤   ¤   (1 byte to terminate the ID string)
9d0a90 ···* Version Major, Minor¤  (2 bytes - 0x01, 0x01)
d5fdeb ···* Units¤ ¤   ¤   (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
ef3d6f ···* Xdpu¤  ¤   ¤   (2 bytes - dots per unit horizontal)
3b40ae ···* Ydpu¤  ¤   ¤   (2 bytes - dots per unit vertical)
f0a185 ···* Thumbnail X size¤  ¤   (1 byte)
bc08d8 ···* Thumbnail Y size¤  ¤   (1 byte)
49f9a6 ···*/
7bde7b ··
18644b ··emit_marker(cinfo, M_APP0);
b5de7b ··
7b86a3 ··emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
36af5a
36e260 ··emit_byte(cinfo, 0x4A);¤  /* Identifier: ASCII "JFIF" */
a432f9 ··emit_byte(cinfo, 0x46);
cb8000 ··emit_byte(cinfo, 0x49);
2032f9 ··emit_byte(cinfo, 0x46);
--989a 000ad93557c40100013 Page 6 of jcmarker.c
78d346 ··emit_byte(cinfo, 0);
f20ccb ··/* We currently emit version code 1.01 since we use no 1.02 features.
620d6e ···* This may avoid complaints from some older decoders.
7af9a6 ···*/
e11e1d ··emit_byte(cinfo, 1);¤ ¤   /* Major version */
b36660 ··emit_byte(cinfo, 1);¤ ¤   /* Minor version */
a0ba22 ··emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
f398cd ··emit_2bytes(cinfo, (int) cinfo->X_density);
a41d98 ··emit_2bytes(cinfo, (int) cinfo->Y_density);
ad6a76 ··emit_byte(cinfo, 0);¤ ¤   /* No thumbnail image */
c4d346 ··emit_byte(cinfo, 0);
19efe6 }
51af5a
41af5a
8fafad LOCAL(void)
e69e73 emit_adobe_app14 (j_compress_ptr cinfo)
fbee31 /* Emit an Adobe APP14 marker */
a1bb36 {
116000 ··/*
6f5256 ···* Length of APP14 block¤ (2 bytes)
01f502 ···* Block ID¤  ¤   ¤   (5 bytes - ASCII "Adobe")
3b880f ···* Version Number¤¤   (2 bytes - currently 100)
170a6e ···* Flags0¤¤   ¤   (2 bytes - currently 0)
3f5bb3 ···* Flags1¤¤   ¤   (2 bytes - currently 0)
d23a4c ···* Color transform¤   ¤   (1 byte)
922fbb ···*
629580 ···* Although Adobe TN 5116 mentions Version = 101, all the Adobe files
cd7b4a ···* now in circulation seem to use Version = 100, so that's what we write.
fd2fbb ···*
afa1a3 ···* We write the color transform byte as 1 if the JPEG color space is
2e5c22 ···* YCbCr, 2 if it's YCCK, 0 otherwise. ·Adobe's definition has to do with
a01afd ···* whether the encoder performed a transformation, which is pretty useless.
55f9a6 ···*/
dbde7b ··
608fd4 ··emit_marker(cinfo, M_APP14);
61de7b ··
c46299 ··emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
94af5a
414e6d ··emit_byte(cinfo, 0x41);¤  /* Identifier: ASCII "Adobe" */
bb1d07 ··emit_byte(cinfo, 0x64);
be7e34 ··emit_byte(cinfo, 0x6F);
24569d ··emit_byte(cinfo, 0x62);
8c01bc ··emit_byte(cinfo, 0x65);
93bdcb ··emit_2bytes(cinfo, 100);¤ /* Version */
c4c377 ··emit_2bytes(cinfo, 0);¤   /* Flags0 */
7ec833 ··emit_2bytes(cinfo, 0);¤   /* Flags1 */
a78e60 ··switch (cinfo->jpeg_color_space) {
1918bb ··case JCS_YCbCr:
65b3b2 ····emit_byte(cinfo, 1);¤   /* Color transform = 1 */
3cab40 ····break;
b3969d ··case JCS_YCCK:
db6edb ····emit_byte(cinfo, 2);¤   /* Color transform = 2 */
94ab40 ····break;
24969d ··default:
bef895 ····emit_byte(cinfo, 0);¤   /* Color transform = 0 */
4cab40 ····break;
addf1c ··}
ceefe6 }
7caf5a
6eaf5a
fb38e5 /*
19774d ·* This routine is exported for possible use by applications.
a791d0 ·* The intended use is to emit COM or APPn markers after calling
164ae3 ·* jpeg_start_compress() and before the first jpeg_write_scanlines() call
c85b72 ·* (hence, after write_file_header but before write_frame_header).
caf026 ·* Other uses are not guaranteed to produce desirable results.
d1495d ·*/
40af5a
c70434 METHODDEF(void)
a890af write_any_marker (j_compress_ptr cinfo, int marker,
46b017 ¤   ¤   ··const JOCTET *dataptr, unsigned int datalen)
adc3be /* Emit an arbitrary marker with parameters */
--ffd5 000ae27492240100013 Page 7 of jcmarker.c
2cbb36 {
98e6f5 ··if (datalen <= (unsigned int) 65533) { /* safety check */
d07c22 ····emit_marker(cinfo, (JPEG_MARKER) marker);
45de7b ··
d8aecf ····emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
cbaf5a
40d2fa ····while (datalen--) {
e93ea0 ······emit_byte(cinfo, *dataptr);
dea871 ······dataptr++;
b96fe7 ····}
bddf1c ··}
8aefe6 }
01af5a
3faf5a
7b38e5 /*
4a8eeb ·* Write datastream header.
0c77c0 ·* This consists of an SOI and optional APPn markers.
0dfc26 ·* We recommend use of the JFIF marker, but not the Adobe marker,
4882de ·* when using YCbCr or grayscale data. ·The JFIF marker should NOT
4abe7f ·* be used for any other JPEG colorspace. ·The Adobe marker is helpful
55c1cb ·* to distinguish RGB, CMYK, and YCCK colorspaces.
b71110 ·* Note that an application can write additional header markers after
34e95e ·* jpeg_start_compress returns.
e6495d ·*/
5daf5a
d60434 METHODDEF(void)
2d8c43 write_file_header (j_compress_ptr cinfo)
a5bb36 {
00bf00 ··emit_marker(cinfo, M_SOI);¤   /* first the SOI */
94af5a
53c798 ··if (cinfo->write_JFIF_header)¤/* next an optional JFIF APP0 */
1b230a ····emit_jfif_app0(cinfo);
b88b8e ··if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
1fb88d ····emit_adobe_app14(cinfo);
97efe6 }
44af5a
16af5a
da38e5 /*
015efd ·* Write frame header.
d09eaa ·* This consists of DQT and SOFn markers.
f62838 ·* Note that we do not emit the SOF until we have emitted the DQT(s).
416c4d ·* This avoids compatibility problems with incorrect implementations that
eddf1b ·* try to error-check the quant table numbers as soon as they see the SOF.
d0495d ·*/
c9af5a
b30434 METHODDEF(void)
7df779 write_frame_header (j_compress_ptr cinfo)
5ebb36 {
f221e1 ··int ci, prec;
01ed9a ··boolean is_baseline;
e233b0 ··jpeg_component_info *compptr;
c6de7b ··
955efb ··/* Emit DQT for each quantization table.
419c0c ···* Note that emit_dqt() suppresses any duplicate tables.
9ef9a6 ···*/
b87849 ··prec = 0;
cc958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
6baa07 ·······ci++, compptr++) {
c27e39 ····prec += emit_dqt(cinfo, compptr->quant_tbl_no);
24df1c ··}
6b38a9 ··/* now prec is nonzero iff there are any 16-bit quant tables. */
4baf5a
7dd843 ··/* Check for a non-baseline specification.
d8af4b ···* Note we assume that Huffman table numbers won't be changed later.
56f9a6 ···*/
c260f3 ··if (cinfo->arith_code || cinfo->progressive_mode ||
7c9ce8 ······cinfo->data_precision != 8) {
e6756e ····is_baseline = FALSE;
7c49d8 ··} else {
431926 ····is_baseline = TRUE;
ab6090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
aeb5ed ¤   ·ci++, compptr++) {
--431b 000a5225d8440100013 Page 8 of jcmarker.c
5ba797 ······if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
41dbf9 ¤   is_baseline = FALSE;
706fe7 ····}
4a6f8f ····if (prec && is_baseline) {
7593b2 ······is_baseline = FALSE;
d315bc ······/* If it's baseline except for quantizer size, warn the user */
fa0cc4 ······TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
d16fe7 ····}
eadf1c ··}
5baf5a
5fd717 ··/* Emit the proper SOF marker */
62a4f1 ··if (cinfo->arith_code) {
eb8c07 ····emit_sof(cinfo, M_SOF9);¤   /* SOF code for arithmetic coding */
0c49d8 ··} else {
0e7b80 ····if (cinfo->progressive_mode)
3b6559 ······emit_sof(cinfo, M_SOF2);¤ /* SOF code for progressive Huffman */
7873c9 ····else if (is_baseline)
18a6c5 ······emit_sof(cinfo, M_SOF0);¤ /* SOF code for baseline implementation */
89842c ····else
f49387 ······emit_sof(cinfo, M_SOF1);¤ /* SOF code for non-baseline Huffman file */
48df1c ··}
a2efe6 }
79af5a
baaf5a
0d38e5 /*
737960 ·* Write scan header.
ff5215 ·* This consists of DHT or DAC markers, optional DRI, and SOS.
4048f3 ·* Compressed data will be written following the SOS.
14495d ·*/
01af5a
840434 METHODDEF(void)
103b3f write_scan_header (j_compress_ptr cinfo)
dfbb36 {
c617e0 ··int i;
a933b0 ··jpeg_component_info *compptr;
05af5a
72a4f1 ··if (cinfo->arith_code) {
40827f ····/* Emit arith conditioning info. ·We may have some duplication
02ca32 ·····* if the file has multiple scans, but it's so small it's hardly
d00aa2 ·····* worth worrying about.
d0d48d ·····*/
b254c2 ····emit_dac(cinfo);
bc49d8 ··} else {
3b190e ····/* Emit Huffman tables.
66452e ·····* Note that emit_dht() suppresses any duplicate tables.
2cd48d ·····*/
0e95f8 ····for (i = 0; i < cinfo->comps_in_scan; i++) {
43fc67 ······compptr = cinfo->cur_comp_info[i];
720317 ······if (cinfo->progressive_mode) {
b91882 ¤   /* Progressive mode: only DC or only AC tables are used in one scan */
316b19 ¤   if (cinfo->Ss == 0) {
6b31e1 ¤   ··if (cinfo->Ah == 0)¤  /* DC needs no table for refinement scan */
8ce233 ¤   ····emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
63f037 ¤   } else {
e7091e ¤   ··emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
be9371 ¤   }
06cfc7 ······} else {
b9f116 ¤   /* Sequential mode: need both DC and AC tables */
90c993 ¤   emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
9a6318 ¤   emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
0242cc ······}
956fe7 ····}
dbdf1c ··}
b3af5a
f71b64 ··/* Emit DRI if required --- note that DRI value could change for each scan.
622243 ···* If it doesn't, a tiny amount of space is wasted in multiple-scan files.
3cd17e ···* We assume DRI will never be nonzero for one scan and zero for a later one.
dcf9a6 ···*/
5ba529 ··if (cinfo->restart_interval)
4eea53 ····emit_dri(cinfo);
5baf5a
a56f4d ··emit_sos(cinfo);
--045f 00163b45a1e40100013 Page 9 of jcmarker.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
8d1cec ·* Write datastream trailer.
4c495d ·*/
90af5a
4a0434 METHODDEF(void)
c500d1 write_file_trailer (j_compress_ptr cinfo)
6abb36 {
ed1e6f ··emit_marker(cinfo, M_EOI);
67efe6 }
8faf5a
28af5a
e638e5 /*
a07c3c ·* Write an abbreviated table-specification datastream.
7397cc ·* This consists of SOI, DQT and DHT tables, and EOI.
2a5e39 ·* Any table that is defined and not marked sent_table = TRUE will be
0a56d8 ·* emitted. ·Note that all tables will be marked sent_table = TRUE at exit.
d1495d ·*/
6daf5a
a70434 METHODDEF(void)
da7ea3 write_tables_only (j_compress_ptr cinfo)
47bb36 {
b517e0 ··int i;
87af5a
364425 ··emit_marker(cinfo, M_SOI);
5caf5a
c227d7 ··for (i = 0; i < NUM_QUANT_TBLS; i++) {
9f1e01 ····if (cinfo->quant_tbl_ptrs[i] != NULL)
2f917e ······(void) emit_dqt(cinfo, i);
86df1c ··}
73af5a
4174f8 ··if (! cinfo->arith_code) {
f96350 ····for (i = 0; i < NUM_HUFF_TBLS; i++) {
54e3b7 ······if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
dbf105 ¤   emit_dht(cinfo, i, FALSE);
15e671 ······if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
e53df9 ¤   emit_dht(cinfo, i, TRUE);
dc6fe7 ····}
cddf1c ··}
46af5a
771e6f ··emit_marker(cinfo, M_EOI);
90efe6 }
57af5a
23af5a
fd38e5 /*
5d0295 ·* Initialize the marker writer module.
72495d ·*/
b6af5a
f4f898 GLOBAL(void)
c7f9c4 jinit_marker_writer (j_compress_ptr cinfo)
0bbb36 {
489190 ··/* Create the subobject */
84f83c ··cinfo->marker = (struct jpeg_marker_writer *)
a13f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
57fa92 ¤   ¤   ¤   ¤   SIZEOF(struct jpeg_marker_writer));
b6a3de ··/* Initialize method pointers */
47ec4f ··cinfo->marker->write_any_marker = write_any_marker;
28c9ee ··cinfo->marker->write_file_header = write_file_header;
7c4604 ··cinfo->marker->write_frame_header = write_frame_header;
47bebe ··cinfo->marker->write_scan_header = write_scan_header;
d2560f ··cinfo->marker->write_file_trailer = write_file_trailer;
8b9d15 ··cinfo->marker->write_tables_only = write_tables_only;
63efe6 }
--f279 000d27e941840100014 Page 1 of jcmaster.c
bc38e5 /*
c8b999 ·* jcmaster.c
bd775e ·*
27a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
60fb07 ·* This file is part of the Independent JPEG Group's software.
8da0d6 ·* For conditions of distribution and use, see the accompanying README file.
a1775e ·*
defed9 ·* This file contains master control logic for the JPEG compressor.
e27161 ·* These routines are concerned with parameter validation, initial setup,
7d224a ·* and inter-pass control (determining the number of passes and the work·
1112d7 ·* to be done in each pass).
c3495d ·*/
6eaf5a
782bb6 #define JPEG_INTERNALS
5936a7 #include "jinclude.h"
946c8f #include "jpeglib.h"
09af5a
d8af5a
62c632 /* Private state */
32af5a
53ed84 typedef enum {
ad360f ¤   main_pass,¤ ¤   /* input data, also do first output step */
db5165 ¤   huff_opt_pass,¤ ¤   /* Huffman code optimization pass */
07888b ¤   output_pass¤¤   /* data output pass */
c426bc } c_pass_type;
30af5a
4ef0f7 typedef struct {
a7b813 ··struct jpeg_comp_master pub;¤ /* public fields */
f3af5a
55ce65 ··c_pass_type pass_type;¤   /* the type of the current pass */
0eaf5a
a63cb0 ··int pass_number;¤ ¤   /* # of passes completed */
236f1d ··int total_passes;¤¤   /* total # of passes needed */
23af5a
5a2771 ··int scan_number;¤ ¤   /* current index in scan_info[] */
d1f8e4 } my_comp_master;
b6af5a
92e0d1 typedef my_comp_master * my_master_ptr;
a7af5a
baaf5a
2e38e5 /*
fd5c00 ·* Support routines that do various essential calculations.
79495d ·*/
e1af5a
7bafad LOCAL(void)
3b3223 initial_setup (j_compress_ptr cinfo)
169ba1 /* Do computations that are needed before master selection phase */
aebb36 {
b90dcc ··int ci;
b133b0 ··jpeg_component_info *compptr;
d8d8ed ··long samplesperrow;
215021 ··JDIMENSION jd_samplesperrow;
0daf5a
3d8cfa ··/* Sanity check on image dimensions */
47e515 ··if (cinfo->image_height <= 0 || cinfo->image_width <= 0
1b36e2 ······|| cinfo->num_components <= 0 || cinfo->input_components <= 0)
1f06c0 ····ERREXIT(cinfo, JERR_EMPTY_IMAGE);
17af5a
f9efb3 ··/* Make sure image isn't bigger than I can handle */
792b9a ··if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
651144 ······(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
a2dab3 ····ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
59af5a
cb815d ··/* Width of an input scanline must be representable as JDIMENSION. */
d432f7 ··samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
1d7929 ··jd_samplesperrow = (JDIMENSION) samplesperrow;
d5e8a0 ··if ((long) jd_samplesperrow != samplesperrow)
547d39 ····ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
e8af5a
9a94f9 ··/* For now, precision must match compiled-in value... */
a662a5 ··if (cinfo->data_precision != BITS_IN_JSAMPLE)
d2c3a4 ····ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
--3440 000df5e8aed40100014 Page 2 of jcmaster.c
e0af5a
2953b8 ··/* Check that number of components won't exceed internal array sizes */
395295 ··if (cinfo->num_components > MAX_COMPONENTS)
522023 ····ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
cb3220 ¤   ·····MAX_COMPONENTS);
77af5a
95ecca ··/* Compute maximum sampling factors; check factor validity */
b7a629 ··cinfo->max_h_samp_factor = 1;
ae13a9 ··cinfo->max_v_samp_factor = 1;
67958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
06aa07 ·······ci++, compptr++) {
ad9c0c ····if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
ee936e ¤   compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
8b24bb ······ERREXIT(cinfo, JERR_BAD_SAMPLING);
0cb611 ····cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
a48895 ¤   ¤   ¤   ¤   ···compptr->h_samp_factor);
972b91 ····cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
5e458a ¤   ¤   ¤   ¤   ···compptr->v_samp_factor);
bcdf1c ··}
32af5a
85c9c3 ··/* Compute dimensions of components */
96958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
59aa07 ·······ci++, compptr++) {
a7acc8 ····/* Fill in the correct component_index value; don't rely on application */
418484 ····compptr->component_index = ci;
c37501 ····/* For compression, we never do DCT scaling. */
9d72b3 ····compptr->DCT_scaled_size = DCTSIZE;
257fb6 ····/* Size in DCT blocks */
7f6652 ····compptr->width_in_blocks = (JDIMENSION)
45e3c2 ······jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
1ed601 ¤   ¤   ····(long) (cinfo->max_h_samp_factor * DCTSIZE));
d9dcc7 ····compptr->height_in_blocks = (JDIMENSION)
328cf6 ······jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
95bd17 ¤   ¤   ····(long) (cinfo->max_v_samp_factor * DCTSIZE));
6a269c ····/* Size in samples */
3bb513 ····compptr->downsampled_width = (JDIMENSION)
b6e3c2 ······jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
160add ¤   ¤   ····(long) cinfo->max_h_samp_factor);
b9abac ····compptr->downsampled_height = (JDIMENSION)
448cf6 ······jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
58c7c2 ¤   ¤   ····(long) cinfo->max_v_samp_factor);
deb627 ····/* Mark component needed (this flag isn't actually used for compression) */
8f64a8 ····compptr->component_needed = TRUE;
45df1c ··}
faaf5a
ec6c51 ··/* Compute number of fully interleaved MCU rows (number of times that
22ca0e ···* main controller will call coefficient controller).
6af9a6 ···*/
1dbd4d ··cinfo->total_iMCU_rows = (JDIMENSION)
7f89b3 ····jdiv_round_up((long) cinfo->image_height,
deba45 ¤   ¤   ··(long) (cinfo->max_v_samp_factor*DCTSIZE));
c5efe6 }
98af5a
62af5a
76da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
edaf5a
a9afad LOCAL(void)
5996d3 validate_script (j_compress_ptr cinfo)
dc8cfc /* Verify that the scan script in cinfo->scan_info[] is valid; also
bc627d ·* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
fa495d ·*/
adbb36 {
7457ee ··const jpeg_scan_info * scanptr;
583ebd ··int scanno, ncomps, ci, coefi, thisi;
c38369 ··int Ss, Se, Ah, Al;
5f5f75 ··boolean component_sent[MAX_COMPONENTS];
bb68ad #ifdef C_PROGRESSIVE_SUPPORTED
e61ea2 ··int * last_bitpos_ptr;
0645d1 ··int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
b1c5c4 ··/* -1 until that coefficient has been seen; then last Al for it */
3e7454 #endif
dfaf5a
--27b9 000c204e5f040100014 Page 3 of jcmaster.c
70d817 ··if (cinfo->num_scans <= 0)
12f0aa ····ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
40af5a
f69f3b ··/* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
6704b0 ···* for progressive JPEG, no scan can have this.
e9f9a6 ···*/
2f3539 ··scanptr = cinfo->scan_info;
747ad6 ··if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
ec68ad #ifdef C_PROGRESSIVE_SUPPORTED
d94de7 ····cinfo->progressive_mode = TRUE;
c5c1bd ····last_bitpos_ptr = & last_bitpos[0][0];
12515f ····for (ci = 0; ci < cinfo->num_components; ci++)·
5b9832 ······for (coefi = 0; coefi < DCTSIZE2; coefi++)
c4228e ¤   *last_bitpos_ptr++ = -1;
67db21 #else
3f9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
5d7454 #endif
7349d8 ··} else {
f7a2bf ····cinfo->progressive_mode = FALSE;
4a515f ····for (ci = 0; ci < cinfo->num_components; ci++)·
6526f5 ······component_sent[ci] = FALSE;
28df1c ··}
93af5a
38a39d ··for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
b0f6a0 ····/* Validate component indexes */
9d8124 ····ncomps = scanptr->comps_in_scan;
84602a ····if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
b06377 ······ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
1d5e32 ····for (ci = 0; ci < ncomps; ci++) {
519bf5 ······thisi = scanptr->component_index[ci];
e42b90 ······if (thisi < 0 || thisi >= cinfo->num_components)
effe8c ¤   ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
af910b ······/* Components must appear in SOF order within each scan */
7e146a ······if (ci > 0 && thisi <= scanptr->component_index[ci-1])
89fe8c ¤   ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
766fe7 ····}
e6126e ····/* Validate progression parameters */
9ff0b5 ····Ss = scanptr->Ss;
aacb3a ····Se = scanptr->Se;
461189 ····Ah = scanptr->Ah;
9232d4 ····Al = scanptr->Al;
4e8aef ····if (cinfo->progressive_mode) {
b268ad #ifdef C_PROGRESSIVE_SUPPORTED
080562 ······if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
d4d137 ¤   ··Ah < 0 || Ah > 13 || Al < 0 || Al > 13)
9b64a0 ¤   ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
b0f1bc ······if (Ss == 0) {
b7f878 ¤   if (Se != 0)¤   ¤   /* DC and AC together not OK */
ee590d ¤   ··ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
dfcfc7 ······} else {
94ad24 ¤   if (ncomps != 1)¤   /* AC scans must be for only one component */
c1590d ¤   ··ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
6442cc ······}
cd4f10 ······for (ci = 0; ci < ncomps; ci++) {
0b3511 ¤   last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
67a4b7 ¤   if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
9a590d ¤   ··ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
fab450 ¤   for (coefi = Ss; coefi <= Se; coefi++) {
e00881 ¤   ··if (last_bitpos_ptr[coefi] < 0) {
9101b1 ¤   ····/* first scan of this coefficient */
5c5911 ¤   ····if (Ah != 0)
a5fc8f ¤   ······ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
a42862 ¤   ··} else {
d07f9c ¤   ····/* not first scan */
1ca50b ¤   ····if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
2cfc8f ¤   ······ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
cf32a2 ¤   ··}
862025 ¤   ··last_bitpos_ptr[coefi] = Al;
159371 ¤   }
8b42cc ······}
b97454 #endif
c26a79 ····} else {
--b679 0005b06f6c740100014 Page 4 of jcmaster.c
8c4838 ······/* For sequential JPEG, all progression parameters must be these: */
a63225 ······if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
f664a0 ¤   ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
85531c ······/* Make sure components are not sent twice */
664f10 ······for (ci = 0; ci < ncomps; ci++) {
45cede ¤   thisi = scanptr->component_index[ci];
5ea536 ¤   if (component_sent[thisi])
adc321 ¤   ··ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
8c646c ¤   component_sent[thisi] = TRUE;
ab42cc ······}
f26fe7 ····}
4edf1c ··}
8daf5a
740ccb ··/* Now verify that everything got sent. */
0e3eb3 ··if (cinfo->progressive_mode) {
0d68ad #ifdef C_PROGRESSIVE_SUPPORTED
903311 ····/* For progressive mode, we only check that at least some DC data
ff704f ·····* got sent for each component; the spec does not require that all bits
30a2ee ·····* of all coefficients be transmitted. ·Would it be wiser to enforce
0fbe9b ·····* transmission of all coefficient bits??
23d48d ·····*/
9ae919 ····for (ci = 0; ci < cinfo->num_components; ci++) {
54b087 ······if (last_bitpos[ci][0] < 0)
87943a ¤   ERREXIT(cinfo, JERR_MISSING_DATA);
b96fe7 ····}
8a7454 #endif
af49d8 ··} else {
aae919 ····for (ci = 0; ci < cinfo->num_components; ci++) {
9ea20c ······if (! component_sent[ci])
0f943a ¤   ERREXIT(cinfo, JERR_MISSING_DATA);
a26fe7 ····}
2ddf1c ··}
c0efe6 }
f0af5a
820f79 #endif /* C_MULTISCAN_FILES_SUPPORTED */
f1af5a
e9af5a
3aafad LOCAL(void)
35c374 select_scan_parameters (j_compress_ptr cinfo)
ec09b5 /* Set up the scan parameters for the current scan */
81bb36 {
fd0dcc ··int ci;
0daf5a
f8da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
7eea40 ··if (cinfo->scan_info != NULL) {
25db3e ····/* Prepare for current scan --- the script is already validated */
6464ac ····my_master_ptr master = (my_master_ptr) cinfo->master;
1d9534 ····const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
d2af5a
4bf1ac ····cinfo->comps_in_scan = scanptr->comps_in_scan;
e7c40d ····for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
355aaa ······cinfo->cur_comp_info[ci] =
ae0a48 ¤   &cinfo->comp_info[scanptr->component_index[ci]];
b26fe7 ····}
832afc ····cinfo->Ss = scanptr->Ss;
081173 ····cinfo->Se = scanptr->Se;
67cbc0 ····cinfo->Ah = scanptr->Ah;
e6e89d ····cinfo->Al = scanptr->Al;
33df1c ··}
d21bd0 ··else
dc7454 #endif
588bcc ··{
4c7c9d ····/* Prepare for single sequential-JPEG scan containing all components */
43ca99 ····if (cinfo->num_components > MAX_COMPS_IN_SCAN)
cee585 ······ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
73f105 ¤   ·······MAX_COMPS_IN_SCAN);
4eacd0 ····cinfo->comps_in_scan = cinfo->num_components;
60e919 ····for (ci = 0; ci < cinfo->num_components; ci++) {
729e4f ······cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
486fe7 ····}
3a22c4 ····cinfo->Ss = 0;
5bddb2 ····cinfo->Se = DCTSIZE2-1;
--4f19 0002617140040100014 Page 5 of jcmaster.c
acb198 ····cinfo->Ah = 0;
7bdeee ····cinfo->Al = 0;
fbdf1c ··}
58efe6 }
f4af5a
49af5a
6dafad LOCAL(void)
e354fd per_scan_setup (j_compress_ptr cinfo)
841b37 /* Do computations that are needed before processing a JPEG scan */
cba0d9 /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
58bb36 {
dad772 ··int ci, mcublks, tmp;
5e33b0 ··jpeg_component_info *compptr;
69de7b ··
d3e0a3 ··if (cinfo->comps_in_scan == 1) {
b4869e ····
729cc9 ····/* Noninterleaved (single-component) scan */
f4d213 ····compptr = cinfo->cur_comp_info[0];
ad869e ····
536e1d ····/* Overall image size in MCUs */
d50a5e ····cinfo->MCUs_per_row = compptr->width_in_blocks;
80b708 ····cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
3d869e ····
8e2473 ····/* For noninterleaved scan, always one block per MCU */
699a95 ····compptr->MCU_width = 1;
766e4e ····compptr->MCU_height = 1;
c115dd ····compptr->MCU_blocks = 1;
f5bd01 ····compptr->MCU_sample_width = DCTSIZE;
805fb0 ····compptr->last_col_width = 1;
4abf2d ····/* For noninterleaved scans, it is convenient to define last_row_height
f5da4b ·····* as the number of block rows present in the last iMCU row.
bcd48d ·····*/
2ead7f ····tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
f98e29 ····if (tmp == 0) tmp = compptr->v_samp_factor;
ceca97 ····compptr->last_row_height = tmp;
1d869e ····
32b764 ····/* Prepare array describing MCU composition */
aa3d02 ····cinfo->blocks_in_MCU = 1;
0ec782 ····cinfo->MCU_membership[0] = 0;
68869e ····
3449d8 ··} else {
cb869e ····
733e3f ····/* Interleaved (multi-component) scan */
9ccc37 ····if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
cd5c1f ······ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
caf105 ¤   ·······MAX_COMPS_IN_SCAN);
57869e ····
da6e1d ····/* Overall image size in MCUs */
91afac ····cinfo->MCUs_per_row = (JDIMENSION)
4b9f26 ······jdiv_round_up((long) cinfo->image_width,
307266 ¤   ¤   ····(long) (cinfo->max_h_samp_factor*DCTSIZE));
6ca73f ····cinfo->MCU_rows_in_scan = (JDIMENSION)
621e30 ······jdiv_round_up((long) cinfo->image_height,
0c0f14 ¤   ¤   ····(long) (cinfo->max_v_samp_factor*DCTSIZE));
b9869e ····
a167de ····cinfo->blocks_in_MCU = 0;
0b869e ····
e36772 ····for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
33b647 ······compptr = cinfo->cur_comp_info[ci];
32863a ······/* Sampling factors give # of blocks of component in each MCU */
c19d6a ······compptr->MCU_width = compptr->h_samp_factor;
565494 ······compptr->MCU_height = compptr->v_samp_factor;
273a17 ······compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
409e72 ······compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
d0c105 ······/* Figure number of non-dummy blocks in last MCU column & row */
f47e2b ······tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
4d680d ······if (tmp == 0) tmp = compptr->MCU_width;
0c6eec ······compptr->last_col_width = tmp;
adfdb3 ······tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
cb501f ······if (tmp == 0) tmp = compptr->MCU_height;
afb1d9 ······compptr->last_row_height = tmp;
269913 ······/* Prepare array describing MCU composition */
--c3f4 000435eb73140100014 Page 6 of jcmaster.c
1c76b7 ······mcublks = compptr->MCU_blocks;
0512a9 ······if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
bd1891 ¤   ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
c12664 ······while (mcublks-- > 0) {
5bf6d4 ¤   cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
0042cc ······}
566fe7 ····}
7b869e ····
83df1c ··}
e5af5a
e4ac66 ··/* Convert restart specified in rows to actual MCU count. */
8acebf ··/* Note that count must fit in 16 bits, so we provide limiting. */
dee842 ··if (cinfo->restart_in_rows > 0) {
1b342d ····long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
5103c9 ····cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
32df1c ··}
99efe6 }
84af5a
22af5a
dc38e5 /*
4adf1f ·* Per-pass setup.
8e9779 ·* This is called at the beginning of each pass. ·We determine which modules
5d0c4b ·* will be active during this pass and give them appropriate start_pass calls.
001a4e ·* We also set is_last_pass to indicate whether any more passes will be
522a1a ·* required.
2b495d ·*/
a5af5a
220434 METHODDEF(void)
aead9d prepare_for_pass (j_compress_ptr cinfo)
94bb36 {
556092 ··my_master_ptr master = (my_master_ptr) cinfo->master;
97af5a
7bbd7a ··switch (master->pass_type) {
14b604 ··case main_pass:
37e6d2 ····/* Initial pass: will collect input data, and do either Huffman
367924 ·····* optimization or data output for the first scan.
0ed48d ·····*/
3e1fbc ····select_scan_parameters(cinfo);
69eba3 ····per_scan_setup(cinfo);
c4a109 ····if (! cinfo->raw_data_in) {
92c1e8 ······(*cinfo->cconvert->start_pass) (cinfo);
aea881 ······(*cinfo->downsample->start_pass) (cinfo);
bc4c7d ······(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
566fe7 ····}
66b218 ····(*cinfo->fdct->start_pass) (cinfo);
9d34a8 ····(*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
732e1b ····(*cinfo->coef->start_pass) (cinfo,
42991f ¤   ¤   ¤   ¤   (master->total_passes > 1 ?
3c82b8 ¤   ¤   ¤   ¤   ·JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
78a452 ····(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
d101ee ····if (cinfo->optimize_coding) {
72f5a6 ······/* No immediate data output; postpone writing frame/scan headers */
75035b ······master->pub.call_pass_startup = FALSE;
4c6a79 ····} else {
465c2b ······/* Will write frame/scan headers at first jpeg_write_scanlines call */
6c8303 ······master->pub.call_pass_startup = TRUE;
f16fe7 ····}
ffab40 ····break;
cc26f0 #ifdef ENTROPY_OPT_SUPPORTED
3eee81 ··case huff_opt_pass:
c07a3d ····/* Do Huffman optimization for a scan after the first one. */
e01fbc ····select_scan_parameters(cinfo);
aeeba3 ····per_scan_setup(cinfo);
c7d60c ····if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) {
b95a54 ······(*cinfo->entropy->start_pass) (cinfo, TRUE);
ee84d9 ······(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
8f035b ······master->pub.call_pass_startup = FALSE;
1488e1 ······break;
db6fe7 ····}
8ffba6 ····/* Special case: Huffman DC refinement scans need no Huffman table
391dac ·····* and therefore we can skip the optimization pass for them.
43d48d ·····*/
--e312 000f86cc4e840100014 Page 7 of jcmaster.c
5c137d ····master->pass_type = output_pass;
2bb3e4 ····master->pass_number++;
1ba950 ····/*FALLTHROUGH*/
137454 #endif
97d538 ··case output_pass:
c87638 ····/* Do a data-output pass. */
8f2706 ····/* We need not repeat per-scan setup if prior optimization pass did it. */
c9ef0e ····if (! cinfo->optimize_coding) {
b89644 ······select_scan_parameters(cinfo);
509f00 ······per_scan_setup(cinfo);
c96fe7 ····}
e98252 ····(*cinfo->entropy->start_pass) (cinfo, FALSE);
765c20 ····(*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
192678 ····/* We emit frame/scan headers now */
f65529 ····if (master->scan_number == 0)
2615d4 ······(*cinfo->marker->write_frame_header) (cinfo);
8f4c58 ····(*cinfo->marker->write_scan_header) (cinfo);
ccaa58 ····master->pub.call_pass_startup = FALSE;
8fab40 ····break;
17969d ··default:
5f9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
51df1c ··}
bbaf5a
8de1a5 ··master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
87af5a
9f5b51 ··/* Set up progress monitor's pass info if present */
cefeda ··if (cinfo->progress != NULL) {
8982ae ····cinfo->progress->completed_passes = master->pass_number;
0de377 ····cinfo->progress->total_passes = master->total_passes;
c0df1c ··}
a0efe6 }
3eaf5a
54af5a
b038e5 /*
ffdd9f ·* Special start-of-pass hook.
effd15 ·* This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
922eee ·* In single-pass processing, we need this hook because we don't want to
db3127 ·* write frame/scan headers during jpeg_start_compress; we want to let the
a7e0d7 ·* application write COM markers etc. between jpeg_start_compress and the
10b2fd ·* jpeg_write_scanlines loop.
91ee4b ·* In multi-pass processing, this routine is not used.
50495d ·*/
2baf5a
4b0434 METHODDEF(void)
4bb2fe pass_startup (j_compress_ptr cinfo)
66bb36 {
3a04ad ··cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
d4af5a
345e99 ··(*cinfo->marker->write_frame_header) (cinfo);
f8fa5c ··(*cinfo->marker->write_scan_header) (cinfo);
f4efe6 }
60af5a
9faf5a
0838e5 /*
bd7ed8 ·* Finish up at end of pass.
9d495d ·*/
e7af5a
ae0434 METHODDEF(void)
ad90f2 finish_pass_master (j_compress_ptr cinfo)
12bb36 {
ec6092 ··my_master_ptr master = (my_master_ptr) cinfo->master;
76af5a
cfd559 ··/* The entropy coder always needs an end-of-pass call,
35236b ···* either to analyze statistics or to flush its output buffer.
bbf9a6 ···*/
43b7d5 ··(*cinfo->entropy->finish_pass) (cinfo);
73af5a
7899db ··/* Update state for next pass */
1bbd7a ··switch (master->pass_type) {
ceb604 ··case main_pass:
f838a4 ····/* next pass is either output of scan 0 (after optimization)
f82adb ·····* or output of scan 1 (if no optimization).
--da10 000a58fd53440100014 Page 8 of jcmaster.c
dbd48d ·····*/
1d137d ····master->pass_type = output_pass;
94f841 ····if (! cinfo->optimize_coding)
1d2c70 ······master->scan_number++;
acab40 ····break;
beee81 ··case huff_opt_pass:
8c8a8e ····/* next pass is always output of current scan */
e4137d ····master->pass_type = output_pass;
1cab40 ····break;
f5d538 ··case output_pass:
e3375b ····/* next pass is either optimization or output of next scan */
aa93d2 ····if (cinfo->optimize_coding)
737207 ······master->pass_type = huff_opt_pass;
1f58d3 ····master->scan_number++;
aaab40 ····break;
56df1c ··}
0caf5a
8b5538 ··master->pass_number++;
f8efe6 }
f1af5a
c2af5a
2a38e5 /*
50c229 ·* Initialize master compression control.
bb495d ·*/
e5af5a
08f898 GLOBAL(void)
0ad070 jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
6dbb36 {
56420d ··my_master_ptr master;
f5af5a
a3cc94 ··master = (my_master_ptr)
81558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
e86055 ¤   ¤   ¤   ¤   ··SIZEOF(my_comp_master));
c05423 ··cinfo->master = (struct jpeg_comp_master *) master;
7c90ba ··master->pub.prepare_for_pass = prepare_for_pass;
5b2fbd ··master->pub.pass_startup = pass_startup;
e129a2 ··master->pub.finish_pass = finish_pass_master;
642d5e ··master->pub.is_last_pass = FALSE;
54af5a
eae12c ··/* Validate parameters, determine derived values */
7db061 ··initial_setup(cinfo);
1eaf5a
abea40 ··if (cinfo->scan_info != NULL) {
32da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
672186 ····validate_script(cinfo);
77db21 #else
3a9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
2f7454 #endif
c049d8 ··} else {
3da2bf ····cinfo->progressive_mode = FALSE;
9de79c ····cinfo->num_scans = 1;
88df1c ··}
e8af5a
4d08f5 ··if (cinfo->progressive_mode)¤ /* ·TEMPORARY HACK ??? */
e9e969 ····cinfo->optimize_coding = TRUE; /* assume default tables no good for progres¶
6e78aa sive mode */
2faf5a
0129d0 ··/* Initialize my private state */
ab3549 ··if (transcode_only) {
bc3756 ····/* no main pass in transcoding */
9693d2 ····if (cinfo->optimize_coding)
bb7207 ······master->pass_type = huff_opt_pass;
27842c ····else
14b87c ······master->pass_type = output_pass;
3749d8 ··} else {
b1927e ····/* for normal compression, first pass is always this type: */
ef3326 ····master->pass_type = main_pass;
d0df1c ··}
8d76f0 ··master->scan_number = 0;
19d487 ··master->pass_number = 0;
4ce4c5 ··if (cinfo->optimize_coding)
a53f3d ····master->total_passes = cinfo->num_scans * 2;
--4f88 001868ad18740100014 Page 9 of jcmaster.c
6c1bd0 ··else
b0c765 ····master->total_passes = cinfo->num_scans;
86efe6 }
--6fa5 000723c3f8540100015 Page 1 of jcomapi.c
bc38e5 /*
aa16d8 ·* jcomapi.c
dc775e ·*
729e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
fafb07 ·* This file is part of the Independent JPEG Group's software.
20a0d6 ·* For conditions of distribution and use, see the accompanying README file.
56775e ·*
df8642 ·* This file contains application interface routines that are used for both
755d54 ·* compression and decompression.
14495d ·*/
8caf5a
7a2bb6 #define JPEG_INTERNALS
2536a7 #include "jinclude.h"
b56c8f #include "jpeglib.h"
dbaf5a
fbaf5a
7438e5 /*
a6097d ·* Abort processing of a JPEG compression or decompression operation,
52292b ·* but don't destroy the object itself.
c3775e ·*
100077 ·* For this, we merely clean up all the nonpermanent memory pools.
83fad6 ·* Note that temp files (virtual arrays) are not allowed to belong to
b0b66f ·* the permanent pool, so we will be able to close all temp files here.
67498a ·* Closing a data source or destination, if necessary, is the application's
7f3c93 ·* responsibility.
fe495d ·*/
6aaf5a
e2f898 GLOBAL(void)
c2cf14 jpeg_abort (j_common_ptr cinfo)
cdbb36 {
6f4484 ··int pool;
a1af5a
2c8058 ··/* Releasing pools in reverse order might help avoid fragmentation
dd4be7 ···* with some (brain-damaged) malloc libraries.
04f9a6 ···*/
edc26b ··for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
7dd4b6 ····(*cinfo->mem->free_pool) (cinfo, pool);
8adf1c ··}
d7af5a
f00b29 ··/* Reset overall state for possible reuse of object */
d95001 ··cinfo->global_state = (cinfo->is_decompressor ? DSTATE_START : CSTATE_START);
33efe6 }
57af5a
94af5a
f738e5 /*
a343e8 ·* Destruction of a JPEG object.
79775e ·*
f847ef ·* Everything gets deallocated except the master jpeg_compress_struct itself
645e3d ·* and the error manager struct. ·Both of these are supplied by the application
eea714 ·* and must be freed, if necessary, by the application. ·(Often they are on
99bdd6 ·* the stack and so don't need to be freed anyway.)
a1498a ·* Closing a data source or destination, if necessary, is the application's
d53c93 ·* responsibility.
0b495d ·*/
67af5a
7af898 GLOBAL(void)
9073e8 jpeg_destroy (j_common_ptr cinfo)
b6bb36 {
9d0a53 ··/* We need only tell the memory manager to release everything. */
5496e9 ··/* NB: mem pointer is NULL if memory mgr failed to initialize. */
eff09d ··if (cinfo->mem != NULL)
83473e ····(*cinfo->mem->self_destruct) (cinfo);
9e29f3 ··cinfo->mem = NULL;¤   ¤   /* be safe if jpeg_destroy is called twice */
abff9c ··cinfo->global_state = 0;¤ /* mark it destroyed */
36efe6 }
f6af5a
77af5a
8138e5 /*
8ae19b ·* Convenience routines for allocating quantization and Huffman tables.
695860 ·* (Would jutils.c be a more reasonable place to put these?)
3b495d ·*/
72af5a
--6c9d 001a9e468fe40100015 Page 2 of jcomapi.c
30ed0e GLOBAL(JQUANT_TBL *)
0d2c08 jpeg_alloc_quant_table (j_common_ptr cinfo)
5fbb36 {
600904 ··JQUANT_TBL *tbl;
58af5a
81eadf ··tbl = (JQUANT_TBL *)
4b24b9 ····(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
57f264 ··tbl->sent_table = FALSE;¤ /* make sure this is false in any new table */
b71993 ··return tbl;
a6efe6 }
fbaf5a
62af5a
2bdf59 GLOBAL(JHUFF_TBL *)
c35828 jpeg_alloc_huff_table (j_common_ptr cinfo)
48bb36 {
8cdf41 ··JHUFF_TBL *tbl;
0baf5a
ed362e ··tbl = (JHUFF_TBL *)
7029a5 ····(*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
3bf264 ··tbl->sent_table = FALSE;¤ /* make sure this is false in any new table */
ae1993 ··return tbl;
a9efe6 }
--d1a3 000e15e062440100016 Page 1 of jconfig.h
bc38e5 /*
73e8a1 ·* jconfig.doc
d8775e ·*
e28ee3 ·* Copyright (C) 1991-1994, Thomas G. Lane.
dbfb07 ·* This file is part of the Independent JPEG Group's software.
f3a0d6 ·* For conditions of distribution and use, see the accompanying README file.
83775e ·*
116463 ·* This file documents the configuration options that are required to
0ecaf8 ·* customize the JPEG software for a particular system.
db775e ·*
83b011 ·* The actual configuration options for a particular installation are stored
9e80d2 ·* in jconfig.h. ·On many machines, jconfig.h can be generated automatically
8f069d ·* or copied from one of the "canned" jconfig files that we supply. ·But if
f321bf ·* you need to generate a jconfig.h file by hand, this file tells you how.
7e495d ·*/
5baf5a
7aaf5a
3731fd #if !( defined(PGP_MACINTOSH) || defined(PGP_UNIX) || defined(PGP_WIN32) )
9d593c #error one of {PGP_MACINTOSH, PGP_UNIX, PGP_WIN32} must be defined
0d7454 #endif
8caf5a
5238e5 /*
26fe5b ·* These symbols indicate the properties of your machine or compiler.
8fafd4 ·* #define the symbol if yes, #undef it if no.
ca495d ·*/
9eaf5a
1561ce /* Does your compiler support function prototypes?
4c3d3a ·* (If not, you also need to use ansi2knr, see install.doc)
07495d ·*/
c0dde9 #define HAVE_PROTOTYPES
03af5a
cdff83 /* Does your compiler support the declaration "unsigned char" ?
577140 ·* How about "unsigned short" ?
00495d ·*/
c3616a #define HAVE_UNSIGNED_CHAR
59c672 #define HAVE_UNSIGNED_SHORT
64af5a
71ca98 /* Define "void" as "char" if your compiler doesn't know about type void.
1c559d ·* NOTE: be sure to define void such that "void *" represents the most general
d66100 ·* pointer type, e.g., that returned by malloc().
57495d ·*/
ec209f /* #define void char */
51af5a
486f9d /* Define "const" as empty if your compiler doesn't know the "const" keyword.
e8495d ·*/
057705 /* #define const */
5aaf5a
48308c /* Define this if an ordinary "char" type is unsigned.
82eb53 ·* If you're not sure, leaving it undefined will work at some cost in speed.
fcb283 ·* If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
c0495d ·*/
3042d4 #undef CHAR_IS_UNSIGNED
d4af5a
eb905c /* Define this if your system has an ANSI-conforming <stdlib.h> file.
f5495d ·*/
918cbf #ifndef HAVE_STDLIB_H
4d170f ¤   #define HAVE_STDLIB_H
e37454 #endif
60af5a
e1806e /* Define this if your system does not have an ANSI/SysV <string.h>,
c0a1de ·* but does have a BSD-style <strings.h>.
67495d ·*/
f077bb #undef NEED_BSD_STRINGS
d2af5a
22a20f /* Define this if your system does not provide typedef size_t in any of the
c27d2d ·* ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
d61ffe ·* <sys/types.h> instead.
02495d ·*/
13517e #undef NEED_SYS_TYPES_H
d2af5a
c8fef5 /* For 80x86 machines, you need to define NEED_FAR_POINTERS,
e14af5 ·* unless you are using a large-data memory model or 80386 flat-memory mode.
--503f 000e993b07840100016 Page 2 of jconfig.h
044a7c ·* On less brain-damaged CPUs this symbol must not be defined.
105453 ·* (Defining this symbol causes large data structures to be referenced through
5a23fc ·* "far" pointers and to be allocated with a special version of malloc.)
67495d ·*/
d44bb4 #undef NEED_FAR_POINTERS
9caf5a
fc28b6 /* Define this if your linker needs global names to be unique in less
de3e8f ·* than the first 15 characters.
4e495d ·*/
56fcf2 #undef NEED_SHORT_EXTERNAL_NAMES
e9af5a
8ec9e5 /* Although a real ANSI C compiler can deal perfectly well with pointers to
3c2afc ·* unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
aac0b1 ·* and pseudo-ANSI compilers get confused. ·To keep one of these bozos happy,
c56159 ·* define INCOMPLETE_TYPES_BROKEN. ·This is not recommended unless you
df0100 ·* actually get "missing structure definition" warnings or errors while
fac6ce ·* compiling the JPEG code.
2a495d ·*/
7ce0cc #undef INCOMPLETE_TYPES_BROKEN
cbaf5a
d3af5a
b938e5 /*
7d1bd6 ·* The following options affect code selection within the JPEG library,
d50679 ·* but they don't need to be visible to applications using the library.
16c8c7 ·* To minimize application namespace pollution, the symbols won't be
b3be3d ·* defined unless JPEG_INTERNALS has been defined.
b8495d ·*/
aaaf5a
579642 #ifdef JPEG_INTERNALS
57af5a
fd71ec /* Define this if your compiler implements ">>" on signed values as a logical
8d6f16 ·* (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
184b8e ·* which is the normal and rational definition.
0a495d ·*/
850462 #undef RIGHT_SHIFT_IS_UNSIGNED
e4af5a
01af5a
0aee3e #endif /* JPEG_INTERNALS */
e0af5a
8aaf5a
ce38e5 /*
55f376 ·* The remaining options do not affect the JPEG library proper,
19b35c ·* but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
3b4504 ·* Other applications can ignore these.
bc495d ·*/
13af5a
c766a5 #ifdef JPEG_CJPEG_DJPEG
96af5a
92ad0e /* These defines indicate which image (non-JPEG) file formats are allowed. */
54af5a
6d15e8 #define BMP_SUPPORTED¤  ¤   /* BMP image file format */
0b7213 #define GIF_SUPPORTED¤  ¤   /* GIF image file format */
7a26f2 #define PPM_SUPPORTED¤  ¤   /* PBMPLUS PPM/PGM image file format */
95868a #undef RLE_SUPPORTED¤   ¤   /* Utah RLE image file format */
8d8bb6 #define TARGA_SUPPORTED¤¤   /* Targa image file format */
baaf5a
05dde8 /* Define this if you want to name both input and output files on the command
623171 ·* line, rather than using stdout and optionally stdin. ·You MUST do this if
f3e1ac ·* your system can't cope with binary I/O to stdin/stdout. ·See comments at
518433 ·* head of cjpeg.c or djpeg.c.
47495d ·*/
840ccc #if PGP_MACINTOSH
8f06fa ¤   #define TWO_FILE_COMMANDLINE
73db21 #else
22776d ¤   #undef TWO_FILE_COMMANDLINE
637454 #endif
aeaf5a
45076a /* Define this if your system needs explicit cleanup of temporary files.
fb5d43 ·* This is crucial under MS-DOS, where the temporary "files" may be areas
1764f7 ·* of extended memory; on most other systems it's not as important.
90495d ·*/
e9588f #undef NEED_SIGNAL_CATCHER
--a4e2 00176bc6f2240100016 Page 3 of jconfig.h
e0af5a
06cb1c /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
836777 ·* This is necessary on systems that distinguish text files from binary files,
9fc011 ·* and is harmless on most systems that don't. ·If you have one of the rare
d8a447 ·* systems that complains about the "b" spec, define this symbol.
d5495d ·*/
392eaf #undef DONT_USE_B_MODE
e9af5a
64891c /* Define this if you want percent-done progress reports from cjpeg/djpeg.
2b495d ·*/
9e77ca #undef PROGRESS_REPORT
82af5a
13af5a
60b548 #endif /* JPEG_CJPEG_DJPEG */
76af5a
--34a1 000d241632e40100017 Page 1 of jcparam.c
bc38e5 /*
9fcead ·* jcparam.c
2a775e ·*
27a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
fafb07 ·* This file is part of the Independent JPEG Group's software.
8aa0d6 ·* For conditions of distribution and use, see the accompanying README file.
23775e ·*
e51bf2 ·* This file contains optional default-setting code for the JPEG compressor.
71c285 ·* Applications do not have to use this file, but those that don't use it
25d99c ·* must know a lot more about the innards of the JPEG code.
0d495d ·*/
a0af5a
ff2bb6 #define JPEG_INTERNALS
0036a7 #include "jinclude.h"
f36c8f #include "jpeglib.h"
d4af5a
aaaf5a
ec38e5 /*
a506be ·* Quantization table setup routines
2d495d ·*/
88af5a
87f898 GLOBAL(void)
b389e5 jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
80081b ¤   ¤   ······const unsigned int *basic_table,
0f2fa1 ¤   ¤   ······int scale_factor, boolean force_baseline)
3fcca8 /* Define a quantization table equal to the basic_table times
a44578 ·* a scale factor (given as a percentage).
f9ec9f ·* If force_baseline is TRUE, the computed quantization table entries
657b3b ·* are limited to 1..255 for JPEG baseline compatibility.
7c495d ·*/
c1bb36 {
460693 ··JQUANT_TBL ** qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
5e17e0 ··int i;
be6569 ··long temp;
b3af5a
06820c ··/* Safety check to ensure start_compress not called yet. */
5a5278 ··if (cinfo->global_state != CSTATE_START)
7f918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
a7af5a
b6ad06 ··if (*qtblptr == NULL)
549eb8 ····*qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
82af5a
3c133f ··for (i = 0; i < DCTSIZE2; i++) {
491945 ····temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
2f8aac ····/* limit the values to the valid range */
fc6e00 ····if (temp <= 0L) temp = 1L;
4ac8be ····if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
f2303e ····if (force_baseline && temp > 255L)
73ea10 ······temp = 255L;¤ ¤   /* limit to baseline range if requested */
fd22e9 ····(*qtblptr)->quantval[i] = (UINT16) temp;
98df1c ··}
6daf5a
db4985 ··/* Initialize sent_table FALSE so table will be written to JPEG file. */
599701 ··(*qtblptr)->sent_table = FALSE;
c9efe6 }
aeaf5a
eaaf5a
50f898 GLOBAL(void)
367d4d jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
46c5f4 ¤   ¤   ¤   ·boolean force_baseline)
8ecf6e /* Set or change the 'quality' (quantization) setting, using default tables
4177e4 ·* and a straight percentage-scaling quality scale. ·In most cases it's better
32355b ·* to use jpeg_set_quality (below); this entry point is provided for
936d32 ·* applications that insist on a linear percentage scaling.
59495d ·*/
34bb36 {
2b64dd ··/* These are the sample quantization tables given in JPEG spec section K.1.
db06fa ···* The spec says that the values given produce "good" quality, and
3339dc ···* when divided by 2, "very good" quality.
99f9a6 ···*/
4a0db9 ··static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
d27d2a ····16, ·11, ·10, ·16, ·24, ·40, ·51, ·61,
--8ff2 000d548f5a840100017 Page 2 of jcparam.c
5956cf ····12, ·12, ·14, ·19, ·26, ·58, ·60, ·55,
4b5eb4 ····14, ·13, ·16, ·24, ·40, ·57, ·69, ·56,
779c07 ····14, ·17, ·22, ·29, ·51, ·87, ·80, ·62,
4fce47 ····18, ·22, ·37, ·56, ·68, 109, 103, ·77,
3b0233 ····24, ·35, ·55, ·64, ·81, 104, 113, ·92,
62124a ····49, ·64, ·78, ·87, 103, 121, 120, 101,
9d8cb4 ····72, ·92, ·95, ·98, 112, 100, 103, ·99
15da12 ··};
aa6617 ··static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
8ab8a2 ····17, ·18, ·24, ·47, ·99, ·99, ·99, ·99,
4980ae ····18, ·21, ·26, ·66, ·99, ·99, ·99, ·99,
402589 ····24, ·26, ·56, ·99, ·99, ·99, ·99, ·99,
a91c36 ····47, ·66, ·99, ·99, ·99, ·99, ·99, ·99,
3e537f ····99, ·99, ·99, ·99, ·99, ·99, ·99, ·99,
a7537f ····99, ·99, ·99, ·99, ·99, ·99, ·99, ·99,
e5537f ····99, ·99, ·99, ·99, ·99, ·99, ·99, ·99,
f9b67f ····99, ·99, ·99, ·99, ·99, ·99, ·99, ·99
0bda12 ··};
c1af5a
589668 ··/* Set up two quantization tables using the specified scaling */
f82180 ··jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
1a7c6f ¤   ¤   ·······scale_factor, force_baseline);
f1b4ca ··jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
687c6f ¤   ¤   ·······scale_factor, force_baseline);
daefe6 }
fbaf5a
1faf5a
88326f GLOBAL(int)
8938e6 jpeg_quality_scaling (int quality)
af4900 /* Convert a user-specified quality rating to a percentage scaling factor
37af69 ·* for an underlying quantization table, using our recommended scaling curve.
41029f ·* The input 'quality' factor should be 0 (terrible) to 100 (very good).
78495d ·*/
24bb36 {
dae0d8 ··/* Safety limit on quality factor. ·Convert 0 to 1 to avoid zero divide. */
7b4267 ··if (quality <= 0) quality = 1;
873b04 ··if (quality > 100) quality = 100;
78af5a
91f049 ··/* The basic table is used as-is (scaling 100) for a quality of 50.
792264 ···* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
3e02a7 ···* note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
e25c70 ···* to make all the table entries 1 (hence, minimum quantization loss).
faf07e ···* Qualities 1..50 are converted to scaling percentage 5000/Q.
c6f9a6 ···*/
4b74cd ··if (quality < 50)
681ab8 ····quality = 5000 / quality;
4e1bd0 ··else
3f9d9a ····quality = 200 - quality*2;
22af5a
ef6058 ··return quality;
c2efe6 }
adaf5a
3eaf5a
fdf898 GLOBAL(void)
b01728 jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
b061be /* Set or change the 'quality' (quantization) setting, using default tables.
739fe4 ·* This is the standard quality-adjusting entry point for typical user
bf3300 ·* interfaces; only those who want detailed control over quantization tables
0fe095 ·* would use the preceding three routines directly.
d2495d ·*/
42bb36 {
95af37 ··/* Convert user 0-100 rating to percentage scaling */
3d94a4 ··quality = jpeg_quality_scaling(quality);
00af5a
03c6dd ··/* Set up standard quality tables */
e8d1a6 ··jpeg_set_linear_quality(cinfo, quality, force_baseline);
a1efe6 }
46af5a
16af5a
8f38e5 /*
49f940 ·* Huffman table setup routines
d5495d ·*/
--d55e 00095dbc89a40100017 Page 3 of jcparam.c
e0af5a
1fafad LOCAL(void)
91461a add_huff_table (j_compress_ptr cinfo,
175e57 ¤   ¤   JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
6bfa1c /* Define a Huffman table */
29bb36 {
023590 ··if (*htblptr == NULL)
6c19eb ····*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
65de7b ··
c2c9af ··MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
142e4e ··MEMCOPY((*htblptr)->huffval, val, SIZEOF((*htblptr)->huffval));
89af5a
384985 ··/* Initialize sent_table FALSE so table will be written to JPEG file. */
43a769 ··(*htblptr)->sent_table = FALSE;
45efe6 }
ddaf5a
b5af5a
2dafad LOCAL(void)
01771e std_huff_tables (j_compress_ptr cinfo)
173bd4 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
f2528b /* IMPORTANT: these are only valid for 8-bit data precision! */
e6bb36 {
ac0486 ··static const UINT8 bits_dc_luminance[17] =
625fff ····{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
6c6416 ··static const UINT8 val_dc_luminance[] =
8c435c ····{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
dfde7b ··
ed984f ··static const UINT8 bits_dc_chrominance[17] =
681520 ····{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
803afa ··static const UINT8 val_dc_chrominance[] =
2c435c ····{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
4fde7b ··
90cac9 ··static const UINT8 bits_ac_luminance[17] =
dc77ee ····{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
153425 ··static const UINT8 val_ac_luminance[] =
bb3aab ····{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
e72646 ······0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
c7d822 ······0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
c76a76 ······0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
5cb9d5 ······0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
d63473 ······0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
60c227 ······0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
a6dc0d ······0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
bbee24 ······0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
2ce32b ······0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
88fcb8 ······0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
52e831 ······0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
4a8d98 ······0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
71fdc0 ······0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
2e059e ······0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
6d1aae ······0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
9a2a5a ······0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
875f06 ······0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
ed93cd ······0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
163cb8 ······0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
96afd9 ······0xf9, 0xfa };
a3de7b ··
ea7293 ··static const UINT8 bits_ac_chrominance[17] =
a7ac28 ····{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
38f4b5 ··static const UINT8 val_ac_chrominance[] =
7c02b2 ····{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
824aa3 ······0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
2522c1 ······0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
aa3db0 ······0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
94740c ······0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0033be ······0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
c40003 ······0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
80a52c ······0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
46b399 ······0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
38a2e2 ······0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
12a105 ······0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
95ff62 ······0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
--aef3 00074148ddd40100017 Page 4 of jcparam.c
b22a6d ······0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
459c03 ······0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
dcd2d4 ······0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
b0e479 ······0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
08dc0f ······0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
a79a83 ······0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
8371d3 ······0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
2f389d ······0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
f9afd9 ······0xf9, 0xfa };
91de7b ··
333f2b ··add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
2fb594 ¤   ¤   ·bits_dc_luminance, val_dc_luminance);
b3d5f7 ··add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
279cf9 ¤   ¤   ·bits_ac_luminance, val_ac_luminance);
9c2390 ··add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
adbbd7 ¤   ¤   ·bits_dc_chrominance, val_dc_chrominance);
47c94c ··add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
1da8e5 ¤   ¤   ·bits_ac_chrominance, val_ac_chrominance);
dfefe6 }
67af5a
65af5a
7338e5 /*
1abfbf ·* Default parameter setup for compression.
21775e ·*
1ca437 ·* Applications that don't choose to use this routine must do their
fe06f7 ·* own setup of all these parameters. ·Alternately, you can call this
f51d87 ·* to establish defaults and then alter parameters selectively. ·This
65beeb ·* is the recommended approach since, if we add any new parameters,
868e04 ·* your code will still work (they'll be set to reasonable defaults).
e2495d ·*/
49af5a
c9f898 GLOBAL(void)
6ae531 jpeg_set_defaults (j_compress_ptr cinfo)
07bb36 {
e417e0 ··int i;
e2af5a
ea820c ··/* Safety check to ensure start_compress not called yet. */
605278 ··if (cinfo->global_state != CSTATE_START)
56918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
f4af5a
1fb687 ··/* Allocate comp_info array large enough for maximum component count.
b67d23 ···* Array is made permanent in case application wants to compress
6bfe6b ···* multiple images at same param settings.
f5f9a6 ···*/
91497d ··if (cinfo->comp_info == NULL)
164409 ····cinfo->comp_info = (jpeg_component_info *)
bdd459 ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
3be216 ¤   ¤   ¤   ¤   ··MAX_COMPONENTS * SIZEOF(jpeg_component_info));
2caf5a
7e4cc5 ··/* Initialize everything not dependent on the color space */
f3af5a
17a28a ··cinfo->data_precision = BITS_IN_JSAMPLE;
7ffb63 ··/* Set up two quantization tables using default quality of 75 */
686d8b ··jpeg_set_quality(cinfo, 75, TRUE);
041bce ··/* Set up two Huffman tables */
0adbb4 ··std_huff_tables(cinfo);
b9af5a
3d394b ··/* Initialize default arithmetic coding conditioning */
651f63 ··for (i = 0; i < NUM_ARITH_TBLS; i++) {
ff72cf ····cinfo->arith_dc_L[i] = 0;
96bf4f ····cinfo->arith_dc_U[i] = 1;
c19c9e ····cinfo->arith_ac_K[i] = 5;
5bdf1c ··}
91af5a
779a31 ··/* Default is no multiple-scan output */
07da57 ··cinfo->scan_info = NULL;
0c67b1 ··cinfo->num_scans = 0;
3aaf5a
68c15e ··/* Expect normal source image, not raw downsampled data */
b1679e ··cinfo->raw_data_in = FALSE;
30af5a
74bcee ··/* Use Huffman coding, not arithmetic coding, by default */
--6eec 000af27e02f40100017 Page 5 of jcparam.c
a1a9a3 ··cinfo->arith_code = FALSE;
1faf5a
60d284 ··/* By default, don't do extra passes to optimize entropy coding */
e4bb20 ··cinfo->optimize_coding = FALSE;
684e03 ··/* The standard Huffman tables are only valid for 8-bit data precision.
7d7210 ···* If the precision is higher, force optimization on so that usable
543373 ···* tables will be computed. ·This test can be removed if default tables
bec112 ···* are supplied that are valid for the desired precision.
7df9a6 ···*/
86343e ··if (cinfo->data_precision > 8)
42af32 ····cinfo->optimize_coding = TRUE;
59af5a
51fe63 ··/* By default, use the simpler non-cosited sampling alignment */
4feb0a ··cinfo->CCIR601_sampling = FALSE;
76af5a
c3a95c ··/* No input smoothing */
71ed8e ··cinfo->smoothing_factor = 0;
d7af5a
d17343 ··/* DCT algorithm preference */
a50329 ··cinfo->dct_method = JDCT_DEFAULT;
42af5a
e7a28a ··/* No restart markers */
51378b ··cinfo->restart_interval = 0;
398deb ··cinfo->restart_in_rows = 0;
27af5a
be1421 ··/* Fill in default JFIF marker parameters. ·Note that whether the marker
933588 ···* will actually be written is determined by jpeg_set_colorspace.
adf9a6 ···*/
b8f123 ··cinfo->density_unit = 0;¤ /* Pixel size is unknown by default */
f5e24b ··cinfo->X_density = 1;¤¤   /* Pixel aspect ratio is square by default */
1f742a ··cinfo->Y_density = 1;
e4af5a
eadb5b ··/* Choose JPEG colorspace based on input space, set defaults accordingly */
60af5a
404365 ··jpeg_default_colorspace(cinfo);
5befe6 }
d6af5a
18af5a
b038e5 /*
576c5f ·* Select an appropriate JPEG colorspace for in_color_space.
bb495d ·*/
7daf5a
89f898 GLOBAL(void)
123278 jpeg_default_colorspace (j_compress_ptr cinfo)
73bb36 {
10b475 ··switch (cinfo->in_color_space) {
6eb88c ··case JCS_GRAYSCALE:
54e885 ····jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
b4ab40 ····break;
c8b3fb ··case JCS_RGB:
bf660f ····jpeg_set_colorspace(cinfo, JCS_YCbCr);
83ab40 ····break;
b018bb ··case JCS_YCbCr:
32660f ····jpeg_set_colorspace(cinfo, JCS_YCbCr);
4eab40 ····break;
c38394 ··case JCS_CMYK:
2082a7 ····jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
56ab40 ····break;
cb969d ··case JCS_YCCK:
16835c ····jpeg_set_colorspace(cinfo, JCS_YCCK);
90ab40 ····break;
2994c9 ··case JCS_UNKNOWN:
14c67a ····jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
1aab40 ····break;
d4969d ··default:
2955aa ····ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
8cdf1c ··}
bfefe6 }
6eaf5a
a4af5a
a338e5 /*
af4071 ·* Set the JPEG colorspace, and choose colorspace-dependent default values.
--effd 000c8c4201f40100017 Page 6 of jcparam.c
47495d ·*/
44af5a
06f898 GLOBAL(void)
b72845 jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
98bb36 {
02bcae ··jpeg_component_info * compptr;
c30dcc ··int ci;
aeaf5a
5fbfad #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) ·\
d6956f ··(compptr = &cinfo->comp_info[index], \
5eed7b ···compptr->component_id = (id), \
e6ca5b ···compptr->h_samp_factor = (hsamp), \
70f2e4 ···compptr->v_samp_factor = (vsamp), \
630dbf ···compptr->quant_tbl_no = (quant), \
3af253 ···compptr->dc_tbl_no = (dctbl), \
d4dfb4 ···compptr->ac_tbl_no = (actbl) )
06af5a
30820c ··/* Safety check to ensure start_compress not called yet. */
225278 ··if (cinfo->global_state != CSTATE_START)
c6918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
82af5a
c0a0cb ··/* For all colorspaces, we use Q and Huff tables 0 for luminance components,
36018a ···* tables 1 for chrominance components.
40f9a6 ···*/
7faf5a
3799c3 ··cinfo->jpeg_color_space = colorspace;
95af5a
679f71 ··cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
23eca5 ··cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
a8af5a
ec9a82 ··switch (colorspace) {
2ab88c ··case JCS_GRAYSCALE:
c07363 ····cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
840cad ····cinfo->num_components = 1;
8c1ab1 ····/* JFIF specifies component ID 1 */
bfdc1b ····SET_COMP(0, 1, 1,1, 0, 0,0);
f1ab40 ····break;
57b3fb ··case JCS_RGB:
870b64 ····cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
88b915 ····cinfo->num_components = 3;
504024 ····SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
6d590f ····SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
7e600f ····SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
80ab40 ····break;
0f18bb ··case JCS_YCbCr:
237363 ····cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
27b915 ····cinfo->num_components = 3;
716623 ····/* JFIF specifies component IDs 1,2,3 */
c7e648 ····/* We default to 2x2 subsamples of chrominance */
d8d8cb ····SET_COMP(0, 1, 2,2, 0, 0,0);
0a6631 ····SET_COMP(1, 2, 1,1, 1, 1,1);
381fd5 ····SET_COMP(2, 3, 1,1, 1, 1,1);
c1ab40 ····break;
f48394 ··case JCS_CMYK:
1a88b1 ····cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
aa3510 ····cinfo->num_components = 4;
ac85ed ····SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
e15455 ····SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
d55e9d ····SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
d7825a ····SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
e7ab40 ····break;
a2969d ··case JCS_YCCK:
051885 ····cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
bd3510 ····cinfo->num_components = 4;
52d8cb ····SET_COMP(0, 1, 2,2, 0, 0,0);
666631 ····SET_COMP(1, 2, 1,1, 1, 1,1);
d91fd5 ····SET_COMP(2, 3, 1,1, 1, 1,1);
48e113 ····SET_COMP(3, 4, 2,2, 0, 0,0);
9eab40 ····break;
c394c9 ··case JCS_UNKNOWN:
179084 ····cinfo->num_components = cinfo->input_components;
c8f9d2 ····if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
--b24b 0009a02139940100017 Page 7 of jcparam.c
7fe585 ······ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
affe2c ¤   ·······MAX_COMPONENTS);
a3e919 ····for (ci = 0; ci < cinfo->num_components; ci++) {
d49f82 ······SET_COMP(ci, ci, 1,1, 0, 0,0);
6b6fe7 ····}
0aab40 ····break;
e8969d ··default:
2165f9 ····ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
b8df1c ··}
72efe6 }
a3af5a
9baf5a
1468ad #ifdef C_PROGRESSIVE_SUPPORTED
29af5a
1e8ce4 LOCAL(jpeg_scan_info *)
b64719 fill_a_scan (jpeg_scan_info * scanptr, int ci,
e02729 ¤   ·····int Ss, int Se, int Ah, int Al)
ada3d8 /* Support routine: generate one scan for specified component */
fabb36 {
547f28 ··scanptr->comps_in_scan = 1;
5ac700 ··scanptr->component_index[0] = ci;
8b78fb ··scanptr->Ss = Ss;
d56d7e ··scanptr->Se = Se;
90b665 ··scanptr->Ah = Ah;
83c3da ··scanptr->Al = Al;
4aeac5 ··scanptr++;
9a79bf ··return scanptr;
b9efe6 }
efaf5a
548ce4 LOCAL(jpeg_scan_info *)
f8a700 fill_scans (jpeg_scan_info * scanptr, int ncomps,
db05dc ¤   ····int Ss, int Se, int Ah, int Al)
df4b0b /* Support routine: generate one scan for each component */
5bbb36 {
4b0dcc ··int ci;
f4af5a
3b257c ··for (ci = 0; ci < ncomps; ci++) {
26083f ····scanptr->comps_in_scan = 1;
12bc4e ····scanptr->component_index[0] = ci;
393ac8 ····scanptr->Ss = Ss;
582f4d ····scanptr->Se = Se;
6af456 ····scanptr->Ah = Ah;
5381e9 ····scanptr->Al = Al;
ed4f7b ····scanptr++;
ffdf1c ··}
f379bf ··return scanptr;
7fefe6 }
30af5a
5f8ce4 LOCAL(jpeg_scan_info *)
5f525c fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
7355cf /* Support routine: generate interleaved DC scan if possible, else N scans */
1dbb36 {
5d0dcc ··int ci;
deaf5a
f816eb ··if (ncomps <= MAX_COMPS_IN_SCAN) {
8898e4 ····/* Single interleaved DC scan */
8bfeb5 ····scanptr->comps_in_scan = ncomps;
ea9de2 ····for (ci = 0; ci < ncomps; ci++)
4a81b9 ······scanptr->component_index[ci] = ci;
9c4508 ····scanptr->Ss = scanptr->Se = 0;
0bf456 ····scanptr->Ah = Ah;
a181e9 ····scanptr->Al = Al;
e34f7b ····scanptr++;
c749d8 ··} else {
dd0479 ····/* Noninterleaved DC scan for each component */
cf20ef ····scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
b3df1c ··}
ea79bf ··return scanptr;
46efe6 }
37af5a
6aaf5a
9a38e5 /*
--b4d6 001bda42a1940100017 Page 8 of jcparam.c
6f748c ·* Create a recommended progressive-JPEG script.
70f6f2 ·* cinfo->num_components and cinfo->jpeg_color_space must be correct.
0b495d ·*/
14af5a
d5f898 GLOBAL(void)
9cfc32 jpeg_simple_progression (j_compress_ptr cinfo)
4bbb36 {
9c35a6 ··int ncomps = cinfo->num_components;
5597fd ··int nscans;
fbf279 ··jpeg_scan_info * scanptr;
caaf5a
60820c ··/* Safety check to ensure start_compress not called yet. */
195278 ··if (cinfo->global_state != CSTATE_START)
73918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
82af5a
c0ad53 ··/* Figure space needed for script. ·Calculation must match code below! */
dc1b8a ··if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
65f10e ····/* Custom script for YCbCr color images. */
63edaf ····nscans = 10;
7b49d8 ··} else {
9f1800 ····/* All-purpose script for other color spaces. */
c35d38 ····if (ncomps > MAX_COMPS_IN_SCAN)
efb93e ······nscans = 6 * ncomps;¤ /* 2 DC + 4 AC scans per component */
2c842c ····else
82840d ······nscans = 2 + 4 * ncomps;¤ /* 2 DC scans; 4 AC scans per component */
d5df1c ··}
ddaf5a
c84762 ··/* Allocate space for script. */
c146d7 ··/* We use permanent pool just in case application re-uses script. */
1c2dca ··scanptr = (jpeg_scan_info *)
a72142 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
22f654 ¤   ¤   ¤   ¤   nscans * SIZEOF(jpeg_scan_info));
f422e8 ··cinfo->scan_info = scanptr;
602114 ··cinfo->num_scans = nscans;
4daf5a
271b8a ··if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
d7f10e ····/* Custom script for YCbCr color images. */
8822e9 ····/* Initial DC scan */
bd24df ····scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
a78b8e ····/* Initial AC scan: get some luma data out in a hurry */
a853f7 ····scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
4ec21a ····/* Chroma data is too small to be worth expending many scans on */
9ab80c ····scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
42881d ····scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
fa1384 ····/* Complete spectral selection for luma AC */
3ccd58 ····scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
1f95e0 ····/* Refine next bit of luma AC */
d1afa9 ····scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
ae4666 ····/* Finish DC successive approximation */
56a7b1 ····scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
338fb1 ····/* Finish AC successive approximation */
773b62 ····scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
b50b73 ····scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
ed7db7 ····/* Luma bottom bit comes last since it's usually largest scan */
2a1b7c ····scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
cf49d8 ··} else {
021800 ····/* All-purpose script for other color spaces. */
7120ba ····/* Successive approximation first pass */
0424df ····scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
cfe305 ····scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
391975 ····scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
a83867 ····/* Successive approximation second pass */
3d7b84 ····scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
a45be4 ····/* Successive approximation final pass */
f0a7b1 ····scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
c3cf51 ····scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
52df1c ··}
4defe6 }
10af5a
bdb090 #endif /* C_PROGRESSIVE_SUPPORTED */
--5861 0006cff6ea840100018 Page 1 of jcphuff.c
bc38e5 /*
72638c ·* jcphuff.c
ba775e ·*
45c561 ·* Copyright (C) 1995-1996, Thomas G. Lane.
2afb07 ·* This file is part of the Independent JPEG Group's software.
06a0d6 ·* For conditions of distribution and use, see the accompanying README file.
a5775e ·*
f79eee ·* This file contains Huffman entropy encoding routines for progressive JPEG.
57775e ·*
97c667 ·* We do not support output suspension in this module, since the library
580cd8 ·* currently does not allow multiple-scan files to be written with output
405ba9 ·* suspension.
39495d ·*/
14af5a
8c2bb6 #define JPEG_INTERNALS
ed36a7 #include "jinclude.h"
4a6c8f #include "jpeglib.h"
683ef9 #include "jchuff.h"¤¤   /* Declarations shared with jchuff.c */
78af5a
be68ad #ifdef C_PROGRESSIVE_SUPPORTED
deaf5a
f1808a /* Expanded entropy encoder object for progressive Huffman encoding. */
dcaf5a
6cf0f7 typedef struct {
2b9ae8 ··struct jpeg_entropy_encoder pub; /* public fields */
eeaf5a
bd79cf ··/* Mode flag: TRUE for optimization, FALSE for actual data output */
61af06 ··boolean gather_statistics;
3daf5a
a9f07a ··/* Bit-level coding status.
4cc918 ···* next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
2df9a6 ···*/
681f80 ··JOCTET * next_output_byte;¤   /* => next byte to write in buffer */
cfa28a ··size_t free_in_buffer;¤   /* # of byte spaces remaining in buffer */
59c30b ··INT32 put_buffer;¤¤   /* current bit-accumulation buffer */
880ceb ··int put_bits;¤¤   ¤   /* # of bits now in it */
617365 ··j_compress_ptr cinfo;¤¤   /* link to cinfo (needed for dump_buffer) */
2baf5a
647a1f ··/* Coding status for DC components */
7d6041 ··int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
a3af5a
672a2c ··/* Coding status for AC components */
59a5e0 ··int ac_tbl_no;¤   ¤   /* the table number of the single component */
9b18a5 ··unsigned int EOBRUN;¤ ¤   /* run length of EOBs */
2af2e3 ··unsigned int BE;¤ ¤   /* # of buffered correction bits before MCU */
05375c ··char * bit_buffer;¤   ¤   /* buffer for correction bits (1 per char) */
8dbece ··/* packing correction bits tightly would save some space but cost time... */
67af5a
7e8e4c ··unsigned int restarts_to_go;¤ /* MCUs left in this restart interval */
b08418 ··int next_restart_num;¤¤   /* next restart number to write (0-7) */
78af5a
181226 ··/* Pointers to derived tables (these workspaces have image lifespan).
f0fd82 ···* Since any one scan codes only DC or only AC, we only need one set
8bca92 ···* of tables, not one for DC and one for AC.
b1f9a6 ···*/
1b7b10 ··c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
16af5a
6f44b1 ··/* Statistics tables for optimization; again, one set is enough */
aeb567 ··long * count_ptrs[NUM_HUFF_TBLS];
03cb76 } phuff_entropy_encoder;
b3af5a
b480de typedef phuff_entropy_encoder * phuff_entropy_ptr;
11af5a
98ff99 /* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
e90064 ·* buffer can hold. ·Larger sizes may slightly improve compression, but
14f0f9 ·* 1000 is already well into the realm of overkill.
98e059 ·* The minimum safe size is 64 bits.
1d495d ·*/
4daf5a
d1ae4e #define MAX_CORR_BITS ·1000¤/* Max # of correction bits I can buffer */
45af5a
6c4ff9 /* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
--9ee6 000f826734040100018 Page 2 of jcphuff.c
00b497 ·* We assume that int right shift is unsigned if INT32 right shift is,
0efed5 ·* which should be safe.
65495d ·*/
47af5a
c666ca #ifdef RIGHT_SHIFT_IS_UNSIGNED
2603df #define ISHIFT_TEMPS¤   int ishift_temp;
f2dbb4 #define IRIGHT_SHIFT(x,shft) ·\
bf97cc ¤   ((ishift_temp = (x)) < 0 ? \
30cf41 ¤   ·(ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
c1024d ¤   ·(ishift_temp >> (shft)))
2ddb21 #else
e24ad3 #define ISHIFT_TEMPS
c98fda #define IRIGHT_SHIFT(x,shft)¤   ((x) >> (shft))
de7454 #endif
d6af5a
496a43 /* Forward declarations */
63252f METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo,
a69981 ¤   ¤   ¤   ¤   ¤   ····JBLOCKROW *MCU_data));
8c287e METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo,
039981 ¤   ¤   ¤   ¤   ¤   ····JBLOCKROW *MCU_data));
4fb247 METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo,
287409 ¤   ¤   ¤   ¤   ¤   ·····JBLOCKROW *MCU_data));
40f146 METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo,
cf7409 ¤   ¤   ¤   ¤   ¤   ·····JBLOCKROW *MCU_data));
c7a7bd METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo));
d78632 METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
dcaf5a
cbaf5a
9f38e5 /*
fe33ae ·* Initialize for a Huffman-compressed scan using progressive JPEG.
89495d ·*/
d7af5a
b20434 METHODDEF(void)
ea5049 start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
c24157 { ·
c92069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
39d5f3 ··boolean is_DC_band;
5facb8 ··int ci, tbl;
80bcae ··jpeg_component_info * compptr;
6aaf5a
97072c ··entropy->cinfo = cinfo;
dad376 ··entropy->gather_statistics = gather_statistics;
70af5a
a07c62 ··is_DC_band = (cinfo->Ss == 0);
42af5a
dd9297 ··/* We assume jcmaster.c already validated the scan parameters. */
ffaf5a
d2f0c7 ··/* Select execution routines */
7b4405 ··if (cinfo->Ah == 0) {
5be7fc ····if (is_DC_band)
2c14d9 ······entropy->pub.encode_mcu = encode_mcu_DC_first;
ec842c ····else
878862 ······entropy->pub.encode_mcu = encode_mcu_AC_first;
6149d8 ··} else {
6be7fc ····if (is_DC_band)
d69147 ······entropy->pub.encode_mcu = encode_mcu_DC_refine;
6583c8 ····else {
ed9a83 ······entropy->pub.encode_mcu = encode_mcu_AC_refine;
374f9b ······/* AC refinement needs a correction bit buffer */
2c34a5 ······if (entropy->bit_buffer == NULL)
e4bdad ¤   entropy->bit_buffer = (char *)
9570e0 ¤   ··(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
30292b ¤   ¤   ¤   ¤   ······MAX_CORR_BITS * SIZEOF(char));
806fe7 ····}
6edf1c ··}
415de7 ··if (gather_statistics)
3864c9 ····entropy->pub.finish_pass = finish_pass_gather_phuff;
6f1bd0 ··else
757549 ····entropy->pub.finish_pass = finish_pass_phuff;
e1af5a
5ae077 ··/* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
f8daac ···* for AC coefficients.
--e6fd 0006cd0f9c040100018 Page 3 of jcphuff.c
e2f9a6 ···*/
b16aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
eaa7cc ····compptr = cinfo->cur_comp_info[ci];
189302 ····/* Initialize DC predictions to 0 */
d6033d ····entropy->last_dc_val[ci] = 0;
9ee9a9 ····/* Make sure requested tables are present */
dd4700 ····/* (In gather mode, tables need not be allocated yet) */
e68d6e ····if (is_DC_band) {
424f63 ······if (cinfo->Ah != 0)¤  /* DC refinement needs no table */
59a8da ¤   continue;
977e4d ······tbl = compptr->dc_tbl_no;
e739aa ······if (tbl < 0 || tbl >= NUM_HUFF_TBLS ||
196f24 ¤   ··(cinfo->dc_huff_tbl_ptrs[tbl] == NULL && !gather_statistics))
d94db5 ¤   ERREXIT1(cinfo,JERR_NO_HUFF_TABLE, tbl);
386a79 ····} else {
3f915e ······entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
5139aa ······if (tbl < 0 || tbl >= NUM_HUFF_TBLS ||
ebd5a2 ··········(cinfo->ac_huff_tbl_ptrs[tbl] == NULL && !gather_statistics))
487c63 ········ERREXIT1(cinfo,JERR_NO_HUFF_TABLE, tbl);
f36fe7 ····}
969225 ····if (gather_statistics) {
746e10 ······/* Allocate and zero the statistics tables */
d26de3 ······/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
f5b2a8 ······if (entropy->count_ptrs[tbl] == NULL)
a2fe35 ¤   entropy->count_ptrs[tbl] = (long *)
d870e0 ¤   ··(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
19e92f ¤   ¤   ¤   ¤   ······257 * SIZEOF(long));
ec5fd3 ······MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
cf6a79 ····} else {
344c14 ······/* Compute derived values for Huffman tables */
cf413b ······/* We may do this more than once for a table, but it's not expensive */
07a5cf ······if (is_DC_band)
24e4b7 ········jpeg_make_c_derived_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[tbl],
c8cc05 ¤   ¤   ¤   ¤   & entropy->derived_tbls[tbl]);
443dfa ······else
cf5a78 ········jpeg_make_c_derived_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[tbl],
9ecc05 ¤   ¤   ¤   ¤   & entropy->derived_tbls[tbl]);
ac6fe7 ····}
0bdf1c ··}
c6af5a
9c9a94 ··/* Initialize AC stuff */
1db5db ··entropy->EOBRUN = 0;
ee8c9f ··entropy->BE = 0;
12af5a
c4cc17 ··/* Initialize bit buffer to empty */
d9b3ab ··entropy->put_buffer = 0;
b75afa ··entropy->put_bits = 0;
0aaf5a
f6c005 ··/* Initialize restart stuff */
287047 ··entropy->restarts_to_go = cinfo->restart_interval;
5d68bf ··entropy->next_restart_num = 0;
1fefe6 }
25af5a
a1af5a
c33c2a /* Outputting bytes to the file.
27e8e4 ·* NB: these must be called only when actually outputting,
bb709d ·* that is, entropy->gather_statistics == FALSE.
a6495d ·*/
ceaf5a
351941 /* Emit a byte */
a3c8d4 #define emit_byte(entropy,val) ·\
48614e ¤   { *(entropy)->next_output_byte++ = (JOCTET) (val); ·\
256865 ¤   ··if (--(entropy)->free_in_buffer == 0) ·\
56365f ¤   ····dump_buffer(entropy); }
bbaf5a
81af5a
89afad LOCAL(void)
a27468 dump_buffer (phuff_entropy_ptr entropy)
eb91af /* Empty the output buffer; we do not support suspension in this module. */
86bb36 {
d613cf ··struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
6caf5a
--c159 0001df9735f40100018 Page 4 of jcphuff.c
9511a2 ··if (! (*dest->empty_output_buffer) (entropy->cinfo))
06e738 ····ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
1a7290 ··/* After a successful buffer dump, must reset buffer pointers */
41779d ··entropy->next_output_byte = dest->next_output_byte;
55e432 ··entropy->free_in_buffer = dest->free_in_buffer;
a0efe6 }
00af5a
34af5a
5cb280 /* Outputting bits to the file */
ecaf5a
ffb746 /* Only the right 24 bits of put_buffer are used; the valid bits are
8f303a ·* left-justified in this part. ·At most 16 bits can be passed to emit_bits
d6ddc4 ·* in one call, and we never retain more than 7 bits in put_buffer
3d70f8 ·* between calls, so 24 bits are sufficient.
cd495d ·*/
67af5a
b16563 INLINE
3bafad LOCAL(void)
9b8a6d emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
4ccd89 /* Emit some bits, unless we are in gather mode */
a6bb36 {
cea048 ··/* This routine is heavily used, so it's worth coding tightly. */
e9ef3f ··register INT32 put_buffer = (INT32) code;
02997c ··register int put_bits = entropy->put_bits;
74af5a
3d3b85 ··/* if size is 0, caller used an invalid Huffman table entry */
70dc29 ··if (size == 0)
23b021 ····ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
53af5a
fc58c0 ··if (entropy->gather_statistics)
a8d9a5 ····return;¤¤   ¤   /* do nothing if we're only getting stats */
f2af5a
83fa73 ··put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
d6de7b ··
748629 ··put_bits += size;¤¤   /* new number of bits in buffer */
c6de7b ··
0f9408 ··put_buffer <<= 24 - put_bits; /* align incoming bits */
6faf5a
94757b ··put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
8aaf5a
b8b565 ··while (put_bits >= 8) {
414647 ····int c = (int) ((put_buffer >> 16) & 0xFF);
94869e ····
4dbef5 ····emit_byte(entropy, c);
bc2bc3 ····if (c == 0xFF) {¤   ¤   /* need to stuff a zero byte? */
3f3a8d ······emit_byte(entropy, 0);
5c6fe7 ····}
514a22 ····put_buffer <<= 8;
4a94f6 ····put_bits -= 8;
10df1c ··}
c7af5a
5c40d7 ··entropy->put_buffer = put_buffer; /* update variables */
b26d9e ··entropy->put_bits = put_bits;
3aefe6 }
deaf5a
6eaf5a
8dafad LOCAL(void)
3a73a1 flush_bits (phuff_entropy_ptr entropy)
06bb36 {
e11288 ··emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
801a96 ··entropy->put_buffer = 0; ····/* and reset bit-buffer to empty */
b15afa ··entropy->put_bits = 0;
0cefe6 }
0caf5a
87af5a
8b38e5 /*
c2da67 ·* Emit (or just count) a Huffman symbol.
5c495d ·*/
6eaf5a
b76563 INLINE
85afad LOCAL(void)
1d1c9b emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
--5682 000dce6410540100018 Page 5 of jcphuff.c
2cbb36 {
6658c0 ··if (entropy->gather_statistics)
7893ba ····entropy->count_ptrs[tbl_no][symbol]++;
653a1e ··else {
c4de4c ····c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
92f422 ····emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
28df1c ··}
78efe6 }
e6af5a
93af5a
f438e5 /*
c1c8c8 ·* Emit bits from a correction bit buffer.
f9495d ·*/
c7af5a
f2afad LOCAL(void)
159555 emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
0161a9 ¤   ¤   ····unsigned int nbits)
8bbb36 {
5958c0 ··if (entropy->gather_statistics)
fa12d3 ····return;¤¤   ¤   /* no real work */
d7af5a
8e1230 ··while (nbits > 0) {
f2732e ····emit_bits(entropy, (unsigned int) (*bufstart), 1);
2d2688 ····bufstart++;
eab570 ····nbits--;
afdf1c ··}
7befe6 }
e3af5a
24af5a
6538e5 /*
ab8d62 ·* Emit any pending EOBRUN symbol.
90495d ·*/
8aaf5a
67afad LOCAL(void)
6fe82a emit_eobrun (phuff_entropy_ptr entropy)
13bb36 {
fd1518 ··register int temp, nbits;
e9af5a
03ac04 ··if (entropy->EOBRUN > 0) {¤   /* if there is any pending EOBRUN */
9d3e65 ····temp = entropy->EOBRUN;
a1984d ····nbits = 0;
01dc2f ····while ((temp >>= 1))
8b8d8d ······nbits++;
ddaf5a
4bd081 ····emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
4f7832 ····if (nbits)
48cb2a ······emit_bits(entropy, entropy->EOBRUN, nbits);
6daf5a
01a9c7 ····entropy->EOBRUN = 0;
a8af5a
12b5c6 ····/* Emit any buffered correction bits */
8a598a ····emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
66bbdf ····entropy->BE = 0;
9adf1c ··}
52efe6 }
91af5a
fbaf5a
bc38e5 /*
0233b9 ·* Emit a restart marker & resynchronize predictions.
1a495d ·*/
c9af5a
43afad LOCAL(void)
8380e2 emit_restart (phuff_entropy_ptr entropy, int restart_num)
b7bb36 {
870dcc ··int ci;
65af5a
9712f4 ··emit_eobrun(entropy);
a0af5a
f4184c ··if (! entropy->gather_statistics) {
b65bf7 ····flush_bits(entropy);
43016d ····emit_byte(entropy, 0xFF);
dc61a6 ····emit_byte(entropy, JPEG_RST0 + restart_num);
--159f 00068bf7f3a40100018 Page 6 of jcphuff.c
3adf1c ··}
64af5a
e55e25 ··if (entropy->cinfo->Ss == 0) {
81d789 ····/* Re-initialize DC predictions to 0 */
9c842e ····for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
6d9b60 ······entropy->last_dc_val[ci] = 0;
5449d8 ··} else {
3834e4 ····/* Re-initialize all AC-related fields to 0 */
4ca9c7 ····entropy->EOBRUN = 0;
d1bbdf ····entropy->BE = 0;
a9df1c ··}
19efe6 }
50af5a
38af5a
0d38e5 /*
bd017f ·* MCU encoding for DC initial scan (either spectral selection,
cefce4 ·* or first pass of successive approximation).
07495d ·*/
fbaf5a
a99a8f METHODDEF(boolean)
d1867a encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
e5bb36 {
d82069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
fc5601 ··register int temp, temp2;
f8ca1f ··register int nbits;
43ed99 ··int blkn, ci;
779a28 ··int Al = cinfo->Al;
c25fd5 ··JBLOCKROW block;
83bcae ··jpeg_component_info * compptr;
57b013 ··ISHIFT_TEMPS
9caf5a
6ac182 ··entropy->next_output_byte = cinfo->dest->next_output_byte;
92778f ··entropy->free_in_buffer = cinfo->dest->free_in_buffer;
0aaf5a
c3480a ··/* Emit restart marker if needed */
07a529 ··if (cinfo->restart_interval)
2a8a4f ····if (entropy->restarts_to_go == 0)
95ff87 ······emit_restart(entropy, entropy->next_restart_num);
06af5a
5e8371 ··/* Encode the MCU data blocks */
ac7685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
03d6bd ····block = MCU_data[blkn];
d6153d ····ci = cinfo->MCU_membership[blkn];
c1a7cc ····compptr = cinfo->cur_comp_info[ci];
4baf5a
9b1160 ····/* Compute the DC value after the required point transform by Al.
fa6c68 ·····* This is simply an arithmetic right shift.
6dd48d ·····*/
748f1e ····temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
97af5a
c94482 ····/* DC differences are figured on the point-transformed values. */
fefee9 ····temp = temp2 - entropy->last_dc_val[ci];
77fcc6 ····entropy->last_dc_val[ci] = temp2;
c5af5a
cb3e9c ····/* Encode the DC coefficient difference per section G.1.2.1 */
9c6122 ····temp2 = temp;
310865 ····if (temp < 0) {
8d85d3 ······temp = -temp;¤¤   /* temp is abs value of input */
685f94 ······/* For a negative input, want temp2 = bitwise complement of abs(input) */
83655e ······/* This code assumes we are on a two's complement machine */
cb22d8 ······temp2--;
7a6fe7 ····}
99869e ····
db4369 ····/* Find the number of bits needed for the magnitude of the coefficient */
72984d ····nbits = 0;
4b08c4 ····while (temp) {
a68d8d ······nbits++;
781374 ······temp >>= 1;
156fe7 ····}
46869e ····
ce4678 ····/* Count/emit the Huffman-coded symbol for the number of bits */
685dd5 ····emit_symbol(entropy, compptr->dc_tbl_no, nbits);
--d6fd 00032cf851b40100018 Page 7 of jcphuff.c
a9869e ····
e0333c ····/* Emit that number of bits of the value, if positive, */
eece2c ····/* or the complement of its magnitude, if negative. */
069839 ····if (nbits)¤ ¤   ¤   /* emit_bits rejects calls with size 0 */
92c911 ······emit_bits(entropy, (unsigned int) temp2, nbits);
b3df1c ··}
2caf5a
295397 ··cinfo->dest->next_output_byte = entropy->next_output_byte;
d3ec99 ··cinfo->dest->free_in_buffer = entropy->free_in_buffer;
e6af5a
4341f1 ··/* Update restart-interval state too */
25cdfb ··if (cinfo->restart_interval) {
63258b ····if (entropy->restarts_to_go == 0) {
851bb3 ······entropy->restarts_to_go = cinfo->restart_interval;
914311 ······entropy->next_restart_num++;
ce6f84 ······entropy->next_restart_num &= 7;
396fe7 ····}
5b5a6d ····entropy->restarts_to_go--;
b7df1c ··}
9aaf5a
37d2c8 ··return TRUE;
c6efe6 }
7baf5a
dbaf5a
6438e5 /*
719006 ·* MCU encoding for AC initial scan (either spectral selection,
0bfce4 ·* or first pass of successive approximation).
25495d ·*/
0eaf5a
5f9a8f METHODDEF(boolean)
754ba6 encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
f8bb36 {
db2069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
455601 ··register int temp, temp2;
b6ca1f ··register int nbits;
c928f2 ··register int r, k;
645000 ··int Se = cinfo->Se;
dc9a28 ··int Al = cinfo->Al;
285fd5 ··JBLOCKROW block;
14af5a
f8c182 ··entropy->next_output_byte = cinfo->dest->next_output_byte;
36778f ··entropy->free_in_buffer = cinfo->dest->free_in_buffer;
eeaf5a
cb480a ··/* Emit restart marker if needed */
c2a529 ··if (cinfo->restart_interval)
608a4f ····if (entropy->restarts_to_go == 0)
22ff87 ······emit_restart(entropy, entropy->next_restart_num);
82af5a
1bca4b ··/* Encode the MCU data block */
bc5de5 ··block = MCU_data[0];
64af5a
86fabc ··/* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
bfde7b ··
4ea209 ··r = 0;¤   ¤   ¤   /* r = run length of zeros */
d0e8c6 ···
df572e ··for (k = cinfo->Ss; k <= Se; k++) {
95faa1 ····if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
29f436 ······r++;
a45f6a ······continue;
0a6fe7 ····}
e716a5 ····/* We must apply the point transform by Al. ·For AC coefficients this
92c3a1 ·····* is an integer division with rounding towards 0. ·To do this portably
7d8a76 ·····* in C, we shift after obtaining the absolute value; so the code is
a65584 ·····* interwoven with finding the abs value (temp) and output bits (temp2).
48d48d ·····*/
990865 ····if (temp < 0) {
3a85d3 ······temp = -temp;¤¤   /* temp is abs value of input */
9c62c8 ······temp >>= Al;¤ ¤   /* apply the point transform */
78db2c ······/* For a negative coef, want temp2 = bitwise complement of abs(coef) */
70a703 ······temp2 = ~temp;
4c6a79 ····} else {
3262c8 ······temp >>= Al;¤ ¤   /* apply the point transform */
--9779 000750c4b3240100018 Page 8 of jcphuff.c
549274 ······temp2 = temp;
ef6fe7 ····}
a58738 ····/* Watch out for case that nonzero coef is zero after point transform */
f59c6e ····if (temp == 0) {
27f436 ······r++;
515f6a ······continue;
196fe7 ····}
6faf5a
3fb2fc ····/* Emit any pending EOBRUN */
01f2bc ····if (entropy->EOBRUN > 0)
7dd402 ······emit_eobrun(entropy);
cbcb74 ····/* if run length > 15, must emit special run-length-16 codes (0xF0) */
644d56 ····while (r > 15) {
5b1d8e ······emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
5bde31 ······r -= 16;
206fe7 ····}
2baf5a
a44369 ····/* Find the number of bits needed for the magnitude of the coefficient */
a9f98d ····nbits = 1;¤ ¤   ¤   /* there must be at least one 1 bit */
5cdc2f ····while ((temp >>= 1))
e28d8d ······nbits++;
62af5a
221163 ····/* Count/emit Huffman symbol for run length / number of bits */
206dc4 ····emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
dfaf5a
a6333c ····/* Emit that number of bits of the value, if positive, */
d0ce2c ····/* or the complement of its magnitude, if negative. */
2abca1 ····emit_bits(entropy, (unsigned int) temp2, nbits);
72af5a
2309e2 ····r = 0;¤ ¤   ¤   /* reset zero run length */
1fdf1c ··}
d4af5a
5c8584 ··if (r > 0) {¤ ¤   ¤   /* If there are trailing zeroes, */
0f9c12 ····entropy->EOBRUN++;¤ ¤   /* count an EOB */
4f7a8b ····if (entropy->EOBRUN == 0x7FFF)
0bf693 ······emit_eobrun(entropy);¤/* force it out to avoid overflow */
8cdf1c ··}
41af5a
2b5397 ··cinfo->dest->next_output_byte = entropy->next_output_byte;
16ec99 ··cinfo->dest->free_in_buffer = entropy->free_in_buffer;
7aaf5a
7741f1 ··/* Update restart-interval state too */
cacdfb ··if (cinfo->restart_interval) {
25258b ····if (entropy->restarts_to_go == 0) {
a81bb3 ······entropy->restarts_to_go = cinfo->restart_interval;
3e4311 ······entropy->next_restart_num++;
366f84 ······entropy->next_restart_num &= 7;
826fe7 ····}
9d5a6d ····entropy->restarts_to_go--;
bfdf1c ··}
d1af5a
72d2c8 ··return TRUE;
4fefe6 }
37af5a
f4af5a
f438e5 /*
a0756d ·* MCU encoding for DC successive approximation refinement scan.
f44ad9 ·* Note: we assume such scans can be multi-component, although the spec
2db2d5 ·* is not very clear on the point.
47495d ·*/
b6af5a
339a8f METHODDEF(boolean)
3b91e6 encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
cabb36 {
f12069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
e59145 ··register int temp;
7fd4fa ··int blkn;
ba9a28 ··int Al = cinfo->Al;
6f5fd5 ··JBLOCKROW block;
bbaf5a
fbc182 ··entropy->next_output_byte = cinfo->dest->next_output_byte;
75778f ··entropy->free_in_buffer = cinfo->dest->free_in_buffer;
--95b6 000d086232040100018 Page 9 of jcphuff.c
e0af5a
7e480a ··/* Emit restart marker if needed */
a1a529 ··if (cinfo->restart_interval)
af8a4f ····if (entropy->restarts_to_go == 0)
fbff87 ······emit_restart(entropy, entropy->next_restart_num);
9baf5a
a48371 ··/* Encode the MCU data blocks */
397685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
57d6bd ····block = MCU_data[blkn];
ceaf5a
700ccb ····/* We simply emit the Al'th bit of the DC coefficient value. */
1445d0 ····temp = (*block)[0];
d86977 ····emit_bits(entropy, (unsigned int) (temp >> Al), 1);
dedf1c ··}
1faf5a
8b5397 ··cinfo->dest->next_output_byte = entropy->next_output_byte;
a9ec99 ··cinfo->dest->free_in_buffer = entropy->free_in_buffer;
1daf5a
bb41f1 ··/* Update restart-interval state too */
79cdfb ··if (cinfo->restart_interval) {
27258b ····if (entropy->restarts_to_go == 0) {
e91bb3 ······entropy->restarts_to_go = cinfo->restart_interval;
174311 ······entropy->next_restart_num++;
1a6f84 ······entropy->next_restart_num &= 7;
f56fe7 ····}
315a6d ····entropy->restarts_to_go--;
8fdf1c ··}
61af5a
71d2c8 ··return TRUE;
f6efe6 }
90af5a
beaf5a
9f38e5 /*
d09bba ·* MCU encoding for AC successive approximation refinement scan.
ea495d ·*/
91af5a
fe9a8f METHODDEF(boolean)
a78dca encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
e5bb36 {
e22069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
929145 ··register int temp;
7428f2 ··register int r, k;
418f4b ··int EOB;
09820c ··char *BR_buffer;
d2d42f ··unsigned int BR;
d85000 ··int Se = cinfo->Se;
539a28 ··int Al = cinfo->Al;
8a5fd5 ··JBLOCKROW block;
7f65b5 ··int absvalues[DCTSIZE2];
09af5a
68c182 ··entropy->next_output_byte = cinfo->dest->next_output_byte;
07778f ··entropy->free_in_buffer = cinfo->dest->free_in_buffer;
a9af5a
0c480a ··/* Emit restart marker if needed */
8ca529 ··if (cinfo->restart_interval)
018a4f ····if (entropy->restarts_to_go == 0)
3fff87 ······emit_restart(entropy, entropy->next_restart_num);
daaf5a
f8ca4b ··/* Encode the MCU data block */
595de5 ··block = MCU_data[0];
4faf5a
7c5034 ··/* It is convenient to make a pre-pass to determine the transformed
deb4e3 ···* coefficients' absolute values and the EOB position.
79f9a6 ···*/
9cd03b ··EOB = 0;
e7572e ··for (k = cinfo->Ss; k <= Se; k++) {
d31ea0 ····temp = (*block)[jpeg_natural_order[k]];
2916a5 ····/* We must apply the point transform by Al. ·For AC coefficients this
2ec3a1 ·····* is an integer division with rounding towards 0. ·To do this portably
57e898 ·····* in C, we shift after obtaining the absolute value.
8ed48d ·····*/
d02e47 ····if (temp < 0)
--cfd1 000ee19177340100018 Page 10 of jcphuff.c
9485d3 ······temp = -temp;¤¤   /* temp is abs value of input */
fe79b6 ····temp >>= Al;¤   ¤   /* apply the point transform */
be05b0 ····absvalues[k] = temp;¤   /* save abs value for main pass */
06dc7d ····if (temp == 1)
8d2cd1 ······EOB = k;¤ ¤   ¤   /* EOB = index of last newly-nonzero coef */
eadf1c ··}
f7af5a
669f86 ··/* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
69de7b ··
a8a209 ··r = 0;¤   ¤   ¤   /* r = run length of zeros */
d2c8ac ··BR = 0;¤  ¤   ¤   /* BR = count of buffered bits added now */
63b713 ··BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
fcaf5a
5b572e ··for (k = cinfo->Ss; k <= Se; k++) {
ede849 ····if ((temp = absvalues[k]) == 0) {
c1f436 ······r++;
aa5f6a ······continue;
686fe7 ····}
b4af5a
5da22c ····/* Emit any required ZRLs, but not if they can be folded into EOB */
722bd2 ····while (r > 15 && k <= EOB) {
dfc86b ······/* emit any pending EOBRUN and the BE correction bits */
8ed402 ······emit_eobrun(entropy);
25775e ······/* Emit ZRL */
5c1d8e ······emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
93de31 ······r -= 16;
4cdba2 ······/* Emit buffered correction bits that must be associated with ZRL */
966e24 ······emit_buffered_bits(entropy, BR_buffer, BR);
6f0bfb ······BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
dec85c ······BR = 0;
ee6fe7 ····}
e6af5a
f77df7 ····/* If the coef was previously nonzero, it only needs a correction bit.
6e167b ·····* NOTE: a straight translation of the spec's figure G.7 would suggest
bd63b3 ·····* that we also need to test r > 15. ·But if r > 15, we can only get here
af013a ·····* if k > EOB, which implies that this coefficient is not 1.
89d48d ·····*/
a6349a ····if (temp > 1) {
acdf20 ······/* The correction bit is the next bit of the absolute value. */
fe2d8f ······BR_buffer[BR++] = (char) (temp & 1);
215f6a ······continue;
aa6fe7 ····}
70af5a
5a7464 ····/* Emit any pending EOBRUN and the BE correction bits */
98c805 ····emit_eobrun(entropy);
83af5a
fd1163 ····/* Count/emit Huffman symbol for run length / number of bits */
4b216f ····emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
8eaf5a
9ca77f ····/* Emit output bit for newly-nonzero coef */
a82a1f ····temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
779676 ····emit_bits(entropy, (unsigned int) temp, 1);
6caf5a
160872 ····/* Emit buffered correction bits that must be associated with this code */
fc28b6 ····emit_buffered_bits(entropy, BR_buffer, BR);
50b908 ····BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
b37cfc ····BR = 0;
4809e2 ····r = 0;¤ ¤   ¤   /* reset zero run length */
cddf1c ··}
62af5a
b1e78f ··if (r > 0 || BR > 0) {¤   /* If there are trailing zeroes, */
cf9c12 ····entropy->EOBRUN++;¤ ¤   /* count an EOB */
1d1d87 ····entropy->BE += BR;¤ ¤   /* concat my correction bits to older ones */
280934 ····/* We force out the EOB if we risk either:
0b93b6 ·····* 1. overflow of the EOB counter;
da6876 ·····* 2. overflow of the correction bit buffer during the next MCU.
3cd48d ·····*/
ba65ea ····if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
f1d402 ······emit_eobrun(entropy);
15df1c ··}
a9af5a
ee5397 ··cinfo->dest->next_output_byte = entropy->next_output_byte;
--79b6 0001016a9c940100018 Page 11 of jcphuff.c
56ec99 ··cinfo->dest->free_in_buffer = entropy->free_in_buffer;
29af5a
e641f1 ··/* Update restart-interval state too */
26cdfb ··if (cinfo->restart_interval) {
66258b ····if (entropy->restarts_to_go == 0) {
021bb3 ······entropy->restarts_to_go = cinfo->restart_interval;
c64311 ······entropy->next_restart_num++;
646f84 ······entropy->next_restart_num &= 7;
a66fe7 ····}
0a5a6d ····entropy->restarts_to_go--;
d1df1c ··}
08af5a
d5d2c8 ··return TRUE;
5eefe6 }
cbaf5a
8aaf5a
7c38e5 /*
71e028 ·* Finish up at the end of a Huffman-compressed progressive scan.
3f495d ·*/
c7af5a
1a0434 METHODDEF(void)
3382e9 finish_pass_phuff (j_compress_ptr cinfo)
250337 { ··
582069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
91af5a
e0c182 ··entropy->next_output_byte = cinfo->dest->next_output_byte;
30778f ··entropy->free_in_buffer = cinfo->dest->free_in_buffer;
57af5a
dfdb8b ··/* Flush out any buffered data */
e012f4 ··emit_eobrun(entropy);
e547eb ··flush_bits(entropy);
1faf5a
af5397 ··cinfo->dest->next_output_byte = entropy->next_output_byte;
f5ec99 ··cinfo->dest->free_in_buffer = entropy->free_in_buffer;
e2efe6 }
07af5a
e1af5a
1638e5 /*
9f2a39 ·* Finish up a statistics-gathering pass and create the new Huffman tables.
8e495d ·*/
14af5a
6a0434 METHODDEF(void)
31c189 finish_pass_gather_phuff (j_compress_ptr cinfo)
cdbb36 {
732069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
ded5f3 ··boolean is_DC_band;
0bacb8 ··int ci, tbl;
22bcae ··jpeg_component_info * compptr;
4b4916 ··JHUFF_TBL **htblptr;
c85b48 ··boolean did[NUM_HUFF_TBLS];
b8af5a
49511e ··/* Flush out buffered data (all we care about is counting the EOB symbol) */
7712f4 ··emit_eobrun(entropy);
bbaf5a
a97c62 ··is_DC_band = (cinfo->Ss == 0);
9baf5a
cb88e1 ··/* It's important not to apply jpeg_gen_optimal_table more than once
67b07d ···* per table, because it clobbers the input frequency counts!
a2f9a6 ···*/
f51cd8 ··MEMZERO(did, SIZEOF(did));
ddaf5a
5c6aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
d9a7cc ····compptr = cinfo->cur_comp_info[ci];
f98d6e ····if (is_DC_band) {
b24f63 ······if (cinfo->Ah != 0)¤  /* DC refinement needs no table */
0fa8da ¤   continue;
7b7e4d ······tbl = compptr->dc_tbl_no;
c76a79 ····} else {
de7589 ······tbl = compptr->ac_tbl_no;
fd6fe7 ····}
87c47b ····if (! did[tbl]) {
10a5cf ······if (is_DC_band)
--444c 0017781f62040100018 Page 12 of jcphuff.c
513e9e ········htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
0f3dfa ······else
008051 ········htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
bcf366 ······if (*htblptr == NULL)
d94b58 ········*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
84c9a1 ······jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
b36d13 ······did[tbl] = TRUE;
596fe7 ····}
afdf1c ··}
b6efe6 }
e2af5a
bdaf5a
ea38e5 /*
f233d8 ·* Module initialization routine for progressive Huffman entropy encoding.
b0495d ·*/
9daf5a
ecf898 GLOBAL(void)
2cf061 jinit_phuff_encoder (j_compress_ptr cinfo)
cfbb36 {
4f1e60 ··phuff_entropy_ptr entropy;
2717e0 ··int i;
d0af5a
2d6f2d ··entropy = (phuff_entropy_ptr)
e83f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
7e97d1 ¤   ¤   ¤   ¤   SIZEOF(phuff_entropy_encoder));
ab5c82 ··cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
4afcaf ··entropy->pub.start_pass = start_pass_phuff;
cfaf5a
8d4d66 ··/* Mark tables unallocated */
0972db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
172088 ····entropy->derived_tbls[i] = NULL;
b95d4f ····entropy->count_ptrs[i] = NULL;
1bdf1c ··}
97a31d ··entropy->bit_buffer = NULL;¤  /* needed only in AC refinement scan */
22efe6 }
4baf5a
77b090 #endif /* C_PROGRESSIVE_SUPPORTED */
--2cf7 0001057a82d40100019 Page 1 of jcprepct.c
bc38e5 /*
5217dd ·* jcprepct.c
ca775e ·*
209e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
02fb07 ·* This file is part of the Independent JPEG Group's software.
59a0d6 ·* For conditions of distribution and use, see the accompanying README file.
f2775e ·*
986572 ·* This file contains the compression preprocessing controller.
e76814 ·* This controller manages the color conversion, downsampling,
dafedc ·* and edge expansion steps.
d3775e ·*
1525c5 ·* Most of the complexity here is associated with buffering input rows
fdb70a ·* as required by the downsampler. ·See the comments at the head of
e3d312 ·* jcsample.c for the downsampler's needs.
11495d ·*/
4baf5a
2f2bb6 #define JPEG_INTERNALS
e536a7 #include "jinclude.h"
586c8f #include "jpeglib.h"
a5af5a
3eaf5a
4cafa4 /* At present, jcsample.c can request context rows only for smoothing.
4e6463 ·* In the future, we might also need context rows for CCIR601 sampling
3a559d ·* or other more-complex downsampling procedures. ·The code to support
2db4f0 ·* context rows should be compiled only if needed.
88495d ·*/
b661bb #ifdef INPUT_SMOOTHING_SUPPORTED
f73765 #define CONTEXT_ROWS_SUPPORTED
ed7454 #endif
9faf5a
d8af5a
0638e5 /*
20f4a8 ·* For the simple (no-context-row) case, we just need to buffer one
e54b0e ·* row group's worth of pixels for the downsampling step. ·At the bottom of
ca2696 ·* the image, we pad to a full row group by replicating the last pixel row.
9a169c ·* The downsampler's last output row is then replicated if needed to pad
153739 ·* out to a full iMCU row.
0e775e ·*
e02a4d ·* When providing context rows, we must buffer three row groups' worth of
5e0a41 ·* pixels. ·Three row groups are physically allocated, but the row pointer
9aea82 ·* arrays are made five row groups high, with the extra pointers above and
2a3d76 ·* below "wrapping around" to point to the last and first real row groups.
880839 ·* This allows the downsampler to access the proper context rows.
d0f338 ·* At the top and bottom of the image, we create dummy context rows by
b64b7d ·* copying the first or last real pixel row. ·This copying could be avoided
37f494 ·* by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
aa4928 ·* trouble on the compression side.
93495d ·*/
67af5a
3aaf5a
578416 /* Private buffer controller object */
d3af5a
68f0f7 typedef struct {
b2bf07 ··struct jpeg_c_prep_controller pub; /* public fields */
ddaf5a
52d890 ··/* Downsampling input buffer. ·This buffer holds color-converted data
2a6109 ···* until we have enough to do a downsample step.
92f9a6 ···*/
7122ce ··JSAMPARRAY color_buf[MAX_COMPONENTS];
dbaf5a
4aef1b ··JDIMENSION rows_to_go;¤   /* counts rows remaining in source image */
bd7fe8 ··int next_buf_row;¤¤   /* index of next row to store in color_buf */
dcaf5a
adf6e6 #ifdef CONTEXT_ROWS_SUPPORTED¤  /* only needed for context case */
415d6a ··int this_row_group;¤  ¤   /* starting row index of group to process */
249459 ··int next_buf_stop;¤   ¤   /* downsample when we reach this index */
6b7454 #endif
fd74f8 } my_prep_controller;
3faf5a
da8411 typedef my_prep_controller * my_prep_ptr;
8daf5a
10af5a
--6933 0002c0d927940100019 Page 2 of jcprepct.c
bc38e5 /*
155b80 ·* Initialize for a processing pass.
c9495d ·*/
6baf5a
0c0434 METHODDEF(void)
315333 start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
f6bb36 {
f9d517 ··my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
5eaf5a
669d84 ··if (pass_mode != JBUF_PASS_THRU)
34650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
70af5a
dbdac9 ··/* Initialize total-height counter for detecting bottom of image */
b4d09c ··prep->rows_to_go = cinfo->image_height;
6141d4 ··/* Mark the conversion buffer empty */
6a8ef6 ··prep->next_buf_row = 0;
9a1c38 #ifdef CONTEXT_ROWS_SUPPORTED
6f4c7e ··/* Preset additional state variables for context mode.
67d7f4 ···* These aren't used in non-context mode, so we needn't test which mode.
81f9a6 ···*/
0e7d7d ··prep->this_row_group = 0;
7d831b ··/* Set next_buf_stop to stop after two row groups have been read in. */
d67ab6 ··prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
db7454 #endif
57efe6 }
c9af5a
5faf5a
f338e5 /*
fab7eb ·* Expand an image vertically from height input_rows to height output_rows,
1e57e1 ·* by duplicating the bottom row.
7d495d ·*/
1faf5a
76afad LOCAL(void)
30c267 expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
affb0a ¤   ¤   ····int input_rows, int output_rows)
c3bb36 {
ac77d2 ··register int row;
9eaf5a
f50e67 ··for (row = input_rows; row < output_rows; row++) {
7f16de ····jcopy_sample_rows(image_data, input_rows-1, image_data, row,
8cfbac ¤   ¤   ······1, num_cols);
2adf1c ··}
4fefe6 }
0faf5a
8caf5a
e038e5 /*
9f3444 ·* Process some data in the simple no-context case.
a6775e ·*
96a385 ·* Preprocessor output data is counted in "row groups". ·A row group
6f7f9f ·* is defined to be v_samp_factor sample rows of each component.
77ba36 ·* Downsampling will produce this much data from each max_v_samp_factor
fe8bcb ·* input rows.
1a495d ·*/
52af5a
860434 METHODDEF(void)
6692b0 pre_process_data (j_compress_ptr cinfo,
630897 ¤   ¤   ··JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
32bcc1 ¤   ¤   ··JDIMENSION in_rows_avail,
f0d011 ¤   ¤   ··JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
f68c21 ¤   ¤   ··JDIMENSION out_row_groups_avail)
31bb36 {
74d517 ··my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
c6d5ff ··int numrows, ci;
3d3534 ··JDIMENSION inrows;
e7bcae ··jpeg_component_info * compptr;
a7af5a
73d7a0 ··while (*in_row_ctr < in_rows_avail &&
ce21e0 ¤   ·*out_row_group_ctr < out_row_groups_avail) {
71122d ····/* Do color conversion to fill the conversion buffer. */
d95904 ····inrows = in_rows_avail - *in_row_ctr;
4ba344 ····numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
2c228b ····numrows = (int) MIN((JDIMENSION) numrows, inrows);
--7edd 000ecca41e940100019 Page 3 of jcprepct.c
b6d834 ····(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
dfccca ¤   ¤   ¤   ¤   ·······prep->color_buf,
cd9c69 ¤   ¤   ¤   ¤   ·······(JDIMENSION) prep->next_buf_row,
6d2787 ¤   ¤   ¤   ¤   ·······numrows);
e702ab ····*in_row_ctr += numrows;
c400d2 ····prep->next_buf_row += numrows;
e50fe3 ····prep->rows_to_go -= numrows;
56ac14 ····/* If at bottom of image, pad to fill the conversion buffer. */
8c7f8b ····if (prep->rows_to_go == 0 &&
45db65 ¤   prep->next_buf_row < cinfo->max_v_samp_factor) {
4e9ca9 ······for (ci = 0; ci < cinfo->num_components; ci++) {
213ac1 ¤   expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
38c096 ¤   ¤   ¤   ···prep->next_buf_row, cinfo->max_v_samp_factor);
d942cc ······}
e63ec4 ······prep->next_buf_row = cinfo->max_v_samp_factor;
286fe7 ····}
019409 ····/* If we've filled the conversion buffer, empty it. */
ff644d ····if (prep->next_buf_row == cinfo->max_v_samp_factor) {
8d2d88 ······(*cinfo->downsample->downsample) (cinfo,
9dcc10 ¤   ¤   ¤   ¤   ¤   prep->color_buf, (JDIMENSION) 0,
eb894a ¤   ¤   ¤   ¤   ¤   output_buf, *out_row_group_ctr);
7d0514 ······prep->next_buf_row = 0;
bfb34b ······(*out_row_group_ctr)++;
666fe7 ····}
2be11b ····/* If at bottom of image, pad the output to a full iMCU height.
5841e4 ·····* Note we assume the caller is providing a one-iMCU-height output buffer!
55d48d ·····*/
817f8b ····if (prep->rows_to_go == 0 &&
8ec47e ¤   *out_row_group_ctr < out_row_groups_avail) {
a1b18b ······for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
344a9f ¤   ···ci++, compptr++) {
2a40bc ¤   expand_bottom_edge(output_buf[ci],
23f1a8 ¤   ¤   ¤   ···compptr->width_in_blocks * DCTSIZE,
65249b ¤   ¤   ¤   ···(int) (*out_row_group_ctr * compptr->v_samp_factor),
ae5f8a ¤   ¤   ¤   ···(int) (out_row_groups_avail * compptr->v_samp_factor));
9442cc ······}
57090b ······*out_row_group_ctr = out_row_groups_avail;
4254b3 ······break;¤   ¤   ¤   /* can exit outer loop without test */
016fe7 ····}
c8df1c ··}
f1efe6 }
41af5a
89af5a
3a1c38 #ifdef CONTEXT_ROWS_SUPPORTED
17af5a
f238e5 /*
02072f ·* Process some data in the context case.
b1495d ·*/
58af5a
b90434 METHODDEF(void)
ad0614 pre_process_context (j_compress_ptr cinfo,
93a1a2 ¤   ¤   ·····JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
554b41 ¤   ¤   ·····JDIMENSION in_rows_avail,
810e5f ¤   ¤   ·····JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
4dd64e ¤   ¤   ·····JDIMENSION out_row_groups_avail)
00bb36 {
22d517 ··my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
46d5ff ··int numrows, ci;
046cc9 ··int buf_height = cinfo->max_v_samp_factor * 3;
353534 ··JDIMENSION inrows;
dbaf5a
33b977 ··while (*out_row_group_ctr < out_row_groups_avail) {
38a9f3 ····if (*in_row_ctr < in_rows_avail) {
c2d5a8 ······/* Do color conversion to fill the conversion buffer. */
a53068 ······inrows = in_rows_avail - *in_row_ctr;
34c3e8 ······numrows = prep->next_buf_stop - prep->next_buf_row;
e83ccf ······numrows = (int) MIN((JDIMENSION) numrows, inrows);
602d2f ······(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
7539e1 ¤   ¤   ¤   ¤   ¤   ·prep->color_buf,
3d36e4 ¤   ¤   ¤   ¤   ¤   ·(JDIMENSION) prep->next_buf_row,
0ec229 ¤   ¤   ¤   ¤   ¤   ·numrows);
ec7658 ······/* Pad at top of image, if first time through */
--b96f 000d076fd2240100019 Page 4 of jcprepct.c
706b83 ······if (prep->rows_to_go == cinfo->image_height) {
ac23a8 ¤   for (ci = 0; ci < cinfo->num_components; ci++) {
f73abc ¤   ··int row;
5d458f ¤   ··for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
cba52c ¤   ····jcopy_sample_rows(prep->color_buf[ci], 0,
5da283 ¤   ¤   ¤   ······prep->color_buf[ci], -row,
c78cab ¤   ¤   ¤   ······1, cinfo->image_width);
c532a2 ¤   ··}
219371 ¤   }
3e42cc ······}
37954e ······*in_row_ctr += numrows;
23892a ······prep->next_buf_row += numrows;
a4bbbf ······prep->rows_to_go -= numrows;
f76a79 ····} else {
3fefa9 ······/* Return for more data, unless we are at the bottom of the image. */
22e3c2 ······if (prep->rows_to_go != 0)
ea4ed2 ¤   break;
61f9cc ······/* When at bottom of image, pad to fill the conversion buffer. */
f3755a ······if (prep->next_buf_row < prep->next_buf_stop) {
1423a8 ¤   for (ci = 0; ci < cinfo->num_components; ci++) {
b7c315 ¤   ··expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
22a832 ¤   ¤   ¤   ·····prep->next_buf_row, prep->next_buf_stop);
149371 ¤   }
eba6e4 ¤   prep->next_buf_row = prep->next_buf_stop;
3342cc ······}
466fe7 ····}
53ef15 ····/* If we've gotten enough data, downsample a row group. */
54a94f ····if (prep->next_buf_row == prep->next_buf_stop) {
812d88 ······(*cinfo->downsample->downsample) (cinfo,
b7b2c0 ¤   ¤   ¤   ¤   ¤   prep->color_buf,
285245 ¤   ¤   ¤   ¤   ¤   (JDIMENSION) prep->this_row_group,
10894a ¤   ¤   ¤   ¤   ¤   output_buf, *out_row_group_ctr);
0fb34b ······(*out_row_group_ctr)++;
368fd6 ······/* Advance pointers with wraparound as necessary. */
8becf8 ······prep->this_row_group += cinfo->max_v_samp_factor;
a621bf ······if (prep->this_row_group >= buf_height)
4ee82e ¤   prep->this_row_group = 0;
ec45db ······if (prep->next_buf_row >= buf_height)
1ba262 ¤   prep->next_buf_row = 0;
938a46 ······prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
c76fe7 ····}
7adf1c ··}
f6efe6 }
a8af5a
66af5a
3e38e5 /*
883c64 ·* Create the wrapped-around downsampling input buffer needed for context mode.
b5495d ·*/
06af5a
43afad LOCAL(void)
53da4d create_context_buffer (j_compress_ptr cinfo)
7cbb36 {
90d517 ··my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
a82a92 ··int rgroup_height = cinfo->max_v_samp_factor;
11ac23 ··int ci, i;
66bcae ··jpeg_component_info * compptr;
9f9355 ··JSAMPARRAY true_buffer, fake_buffer;
ccaf5a
d4feca ··/* Grab enough space for fake row pointers for all the components;
c8aa32 ···* we need five row groups' worth of pointers for each component.
cbf9a6 ···*/
dfa1ed ··fake_buffer = (JSAMPARRAY)
323f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
f98768 ¤   ¤   ¤   ¤   (cinfo->num_components * 5 * rgroup_height) *
9677c7 ¤   ¤   ¤   ¤   SIZEOF(JSAMPROW));
c0af5a
f2958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
68aa07 ·······ci++, compptr++) {
8ca54e ····/* Allocate the actual buffer space (3 row groups) for this component.
f08ee5 ·····* We make the buffer wide enough to allow the downsampler to edge-expand
1b366a ·····* horizontally within the buffer, if it so chooses.
d0d48d ·····*/
--dac6 0015812d6b340100019 Page 5 of jcprepct.c
ada5a3 ····true_buffer = (*cinfo->mem->alloc_sarray)
e050cf ······((j_common_ptr) cinfo, JPOOL_IMAGE,
bca0c6 ·······(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
ad9ea8 ¤   ¤   ······cinfo->max_h_samp_factor) / compptr->h_samp_factor),
f458a9 ·······(JDIMENSION) (3 * rgroup_height));
cc68c1 ····/* Copy true buffer row pointers into the middle of the fake row array */
70a790 ····MEMCOPY(fake_buffer + rgroup_height, true_buffer,
95ea5a ¤   ····3 * rgroup_height * SIZEOF(JSAMPROW));
179c36 ····/* Fill in the above and below wraparound pointers */
9378cc ····for (i = 0; i < rgroup_height; i++) {
c1dbec ······fake_buffer[i] = true_buffer[2 * rgroup_height + i];
019b42 ······fake_buffer[4 * rgroup_height + i] = true_buffer[i];
846fe7 ····}
aa6391 ····prep->color_buf[ci] = fake_buffer + rgroup_height;
16093b ····fake_buffer += 5 * rgroup_height; /* point to space for next component */
84df1c ··}
83efe6 }
f7af5a
fae491 #endif /* CONTEXT_ROWS_SUPPORTED */
0aaf5a
1caf5a
b838e5 /*
9de9dd ·* Initialize preprocessing controller.
da495d ·*/
c4af5a
78f898 GLOBAL(void)
4daa0f jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
0cbb36 {
adb05f ··my_prep_ptr prep;
440dcc ··int ci;
f5bcae ··jpeg_component_info * compptr;
8aaf5a
16c279 ··if (need_full_buffer)¤¤   /* safety check */
98650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
f6af5a
59e72a ··prep = (my_prep_ptr)
f83f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cadf26 ¤   ¤   ¤   ¤   SIZEOF(my_prep_controller));
7d30ca ··cinfo->prep = (struct jpeg_c_prep_controller *) prep;
8e6ffc ··prep->pub.start_pass = start_pass_prep;
80af5a
3ed13e ··/* Allocate the color conversion buffer.
ee6435 ···* We make the buffer wide enough to allow the downsampler to edge-expand
ae282e ···* horizontally within the buffer, if it so chooses.
6bf9a6 ···*/
a3ea4a ··if (cinfo->downsample->need_context_rows) {
8ee307 ····/* Set up to provide context rows */
311c38 #ifdef CONTEXT_ROWS_SUPPORTED
3f1118 ····prep->pub.pre_process_data = pre_process_context;
ed58d7 ····create_context_buffer(cinfo);
9adb21 #else
be9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
117454 #endif
8849d8 ··} else {
2b395a ····/* No context, just make it tall enough for one row group */
2d4b17 ····prep->pub.pre_process_data = pre_process_data;
d36090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
8ab5ed ¤   ·ci++, compptr++) {
7c09b2 ······prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
75ee7d ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE,
bf849a ¤   ·(JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
ba3314 ¤   ¤   ¤   cinfo->max_h_samp_factor) / compptr->h_samp_factor),
2222ec ¤   ·(JDIMENSION) cinfo->max_v_samp_factor);
7f6fe7 ····}
f0df1c ··}
58efe6 }
--a487 00037d0afae4010001a Page 1 of jcsample.c
bc38e5 /*
c07b78 ·* jcsample.c
81775e ·*
29a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
effb07 ·* This file is part of the Independent JPEG Group's software.
07a0d6 ·* For conditions of distribution and use, see the accompanying README file.
51775e ·*
78e114 ·* This file contains downsampling routines.
e9775e ·*
afb8bc ·* Downsampling input data is counted in "row groups". ·A row group
30a67f ·* is defined to be max_v_samp_factor pixel rows of each component,
5a1054 ·* from which the downsampler produces v_samp_factor sample rows.
8fdabd ·* A single row group is processed in each call to the downsampler module.
c4775e ·*
f5d492 ·* The downsampler is responsible for edge-expansion of its output data
133119 ·* to fill an integral number of DCT blocks horizontally. ·The source buffer
fe413a ·* may be modified if it is helpful for this purpose (the source buffer is
3216fa ·* allocated wide enough to correspond to the desired output width).
9e21b5 ·* The caller (the prep controller) is responsible for vertical padding.
da775e ·*
3cc2d3 ·* The downsampler may request "context rows" by setting need_context_rows
b68fe3 ·* during startup. ·In this case, the input arrays will contain at least
72fca7 ·* one row group's worth of pixels above and below the passed-in data;
fbb2cd ·* the caller will create dummy rows at image top and bottom by replicating
78788d ·* the first or last real pixel row.
1d775e ·*
d1eba2 ·* An excellent reference for image resampling is
2639c1 ·* ··Digital Image Warping, George Wolberg, 1990.
529923 ·* ··Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
c0775e ·*
2e3bd7 ·* The downsampling algorithm used here is a simple average of the source
f3e7b7 ·* pixels covered by the output pixel. ·The hi-falutin sampling literature
ce8aff ·* refers to this as a "box filter". ·In general the characteristics of a box
183846 ·* filter are not very good, but for the specific cases we normally use (1:1
7b7fef ·* and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
a60396 ·* nearly so bad. ·If you intend to use other sampling ratios, you'd be well
2b8b4a ·* advised to improve this code.
f8775e ·*
b9a3f6 ·* A simple input-smoothing capability is provided. ·This is mainly intended
30c611 ·* for cleaning up color-dithered GIF input files (if you find it inadequate,
56a002 ·* we suggest using an external filtering program such as pnmconvol). ·When
351791 ·* enabled, each input pixel P is replaced by a weighted sum of itself and its
93db04 ·* eight neighbors. ·P's weight is 1-8*SF and each neighbor's weight is SF,
b1ed4f ·* where SF = (smoothing_factor / 1024).
6a545b ·* Currently, smoothing is only supported for 2h2v sampling factors.
62495d ·*/
8caf5a
6a2bb6 #define JPEG_INTERNALS
0836a7 #include "jinclude.h"
5f6c8f #include "jpeglib.h"
feaf5a
cdaf5a
6f0c53 /* Pointer to routine to downsample a single component */
af0e0a typedef JMETHOD(void, downsample1_ptr,
e5306d ¤   ¤   (j_compress_ptr cinfo, jpeg_component_info * compptr,
53d2d6 ¤   ¤   ·JSAMPARRAY input_data, JSAMPARRAY output_data));
5aaf5a
35dedc /* Private subobject */
4faf5a
3bf0f7 typedef struct {
1b6f00 ··struct jpeg_downsampler pub;¤ /* public fields */
d7af5a
b2a6a2 ··/* Downsampling method pointers, one per component */
b72f79 ··downsample1_ptr methods[MAX_COMPONENTS];
6f0a30 } my_downsampler;
8daf5a
613d88 typedef my_downsampler * my_downsample_ptr;
b0af5a
3eaf5a
7538e5 /*
738656 ·* Initialize for a downsampling pass.
37495d ·*/
--45be 000f6df9def4010001a Page 2 of jcsample.c
e0af5a
6a0434 METHODDEF(void)
d77451 start_pass_downsample (j_compress_ptr cinfo)
12bb36 {
c43c81 ··/* no work for now */
e8efe6 }
e5af5a
48af5a
9a38e5 /*
063420 ·* Expand a component horizontally from width input_cols to width output_cols,
60856b ·* by duplicating the rightmost samples.
25495d ·*/
adaf5a
36afad LOCAL(void)
de2142 expand_right_edge (JSAMPARRAY image_data, int num_rows,
5fd56f ¤   ¤   ···JDIMENSION input_cols, JDIMENSION output_cols)
e3bb36 {
de485a ··register JSAMPROW ptr;
0a1ff9 ··register JSAMPLE pixval;
2b81f5 ··register int count;
175b06 ··int row;
d2d42b ··int numcols = (int) (output_cols - input_cols);
c6af5a
14f62d ··if (numcols > 0) {
45eba5 ····for (row = 0; row < num_rows; row++) {
b38ba7 ······ptr = image_data[row] + input_cols;
5d95cc ······pixval = ptr[-1];¤¤   /* don't need GETJSAMPLE() here */
715f88 ······for (count = numcols; count > 0; count--)
5ecc1c ¤   *ptr++ = pixval;
a46fe7 ····}
a9df1c ··}
4befe6 }
0daf5a
e8af5a
e638e5 /*
de946d ·* Do downsampling for a whole row group (all components).
33775e ·*
00c06f ·* In this version we simply downsample each component independently.
33495d ·*/
c1af5a
ea0434 METHODDEF(void)
97b8ae sep_downsample (j_compress_ptr cinfo,
7bfaad ¤   ¤   JSAMPIMAGE input_buf, JDIMENSION in_row_index,
ec217e ¤   ¤   JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
b4bb36 {
9ba361 ··my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
000dcc ··int ci;
21bcae ··jpeg_component_info * compptr;
bff1cf ··JSAMPARRAY in_ptr, out_ptr;
acaf5a
1a958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ecaa07 ·······ci++, compptr++) {
908a7a ····in_ptr = input_buf[ci] + in_row_index;
381909 ····out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
983fd1 ····(*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
7edf1c ··}
64efe6 }
7aaf5a
e2af5a
7138e5 /*
8db4cc ·* Downsample pixel values of a single component.
23e1ac ·* One row group is processed per call.
81bf8f ·* This version handles arbitrary integral sampling ratios, without smoothing.
814676 ·* Note that this version is not actually used for customary sampling ratios.
19495d ·*/
23af5a
b50434 METHODDEF(void)
5c8047 int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
943d3f ¤   ¤   JSAMPARRAY input_data, JSAMPARRAY output_data)
53bb36 {
7264cb ··int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
f66fc1 ··JDIMENSION outcol, outcol_h;¤ /* outcol_h == outcol*h_expand */
--361d 000aae4c7504010001a Page 3 of jcsample.c
ef1f33 ··JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
37d448 ··JSAMPROW inptr, outptr;
fc9373 ··INT32 outvalue;
fbaf5a
c7b5d5 ··h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
6164f7 ··v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
261f14 ··numpix = h_expand * v_expand;
6c90da ··numpix2 = numpix/2;
aaaf5a
27da08 ··/* Expand input data enough to let all the output samples be generated
05d2a7 ···* by the standard loop. ·Special-casing padded output would be more
8971fb ···* efficient.
43f9a6 ···*/
d92d01 ··expand_right_edge(input_data, cinfo->max_v_samp_factor,
4f7a5a ¤   ¤   ····cinfo->image_width, output_cols * h_expand);
b0af5a
a2819b ··inrow = 0;
7619b7 ··for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
87a315 ····outptr = output_data[outrow];
5d261f ····for (outcol = 0, outcol_h = 0; outcol < output_cols;
a2b710 ¤   ·outcol++, outcol_h += h_expand) {
46d71d ······outvalue = 0;
8f4eee ······for (v = 0; v < v_expand; v++) {
942769 ¤   inptr = input_data[inrow+v] + outcol_h;
222546 ¤   for (h = 0; h < h_expand; h++) {
39a483 ¤   ··outvalue += (INT32) GETJSAMPLE(*inptr++);
3c9371 ¤   }
7a42cc ······}
3b902e ······*outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
826fe7 ····}
d103e2 ····inrow += v_expand;
dddf1c ··}
76efe6 }
f5af5a
c7af5a
b038e5 /*
fcb4cc ·* Downsample pixel values of a single component.
9853df ·* This version handles the special case of a full-size component,
b5d463 ·* without smoothing.
e2495d ·*/
deaf5a
290434 METHODDEF(void)
b63c26 fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
371801 ¤   ¤   ·····JSAMPARRAY input_data, JSAMPARRAY output_data)
f3bb36 {
466a5d ··/* Copy the data */
ae7ce0 ··jcopy_sample_rows(input_data, 0, output_data, 0,
cb32b1 ¤   ¤   ····cinfo->max_v_samp_factor, cinfo->image_width);
cfe192 ··/* Edge-expand */
083435 ··expand_right_edge(output_data, cinfo->max_v_samp_factor,
0423f7 ¤   ¤   ····cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
0cefe6 }
8caf5a
6caf5a
fe38e5 /*
f9b4cc ·* Downsample pixel values of a single component.
f21a6d ·* This version handles the common case of 2:1 horizontal and 1:1 vertical,
09d463 ·* without smoothing.
42775e ·*
9f2846 ·* A note about the "bias" calculations: when rounding fractional values to
9127d9 ·* integer, we do not want to always round 0.5 up to the next integer.
d59b35 ·* If we did that, we'd introduce a noticeable bias towards larger values.
302e90 ·* Instead, this code is arranged so that 0.5 will be rounded up or down at
5795bb ·* alternate pixel locations (a simple ordered dither pattern).
90495d ·*/
a6af5a
ad0434 METHODDEF(void)
80a4cb h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
664a5a ¤   ¤   ·JSAMPARRAY input_data, JSAMPARRAY output_data)
38bb36 {
a9c6b8 ··int outrow;
aa6d2f ··JDIMENSION outcol;
--d011 0002b427ecd4010001a Page 4 of jcsample.c
ef1f33 ··JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
c543b7 ··register JSAMPROW inptr, outptr;
d8c46f ··register int bias;
9eaf5a
89da08 ··/* Expand input data enough to let all the output samples be generated
dad2a7 ···* by the standard loop. ·Special-casing padded output would be more
c271fb ···* efficient.
44f9a6 ···*/
ac2d01 ··expand_right_edge(input_data, cinfo->max_v_samp_factor,
474071 ¤   ¤   ····cinfo->image_width, output_cols * 2);
32af5a
1819b7 ··for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
daa315 ····outptr = output_data[outrow];
9f1146 ····inptr = input_data[outrow];
242de6 ····bias = 0;¤  ¤   ¤   /* bias = 0,1,0,1,... for successive samples */
b5b68d ····for (outcol = 0; outcol < output_cols; outcol++) {
9cc0d3 ······*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
a943fe ¤   ¤   ¤   ······+ bias) >> 1);
1f01c9 ······bias ^= 1;¤   ¤   /* 0=>1, 1=>0 */
b66902 ······inptr += 2;
a06fe7 ····}
f5df1c ··}
d6efe6 }
40af5a
eaaf5a
1a38e5 /*
d5b4cc ·* Downsample pixel values of a single component.
dcb6aa ·* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
45d463 ·* without smoothing.
d5495d ·*/
daaf5a
a20434 METHODDEF(void)
90d721 h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
484a5a ¤   ¤   ·JSAMPARRAY input_data, JSAMPARRAY output_data)
58bb36 {
80bdba ··int inrow, outrow;
0a6d2f ··JDIMENSION outcol;
8e1f33 ··JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
e03b2a ··register JSAMPROW inptr0, inptr1, outptr;
41c46f ··register int bias;
05af5a
01da08 ··/* Expand input data enough to let all the output samples be generated
ecd2a7 ···* by the standard loop. ·Special-casing padded output would be more
1571fb ···* efficient.
32f9a6 ···*/
4c2d01 ··expand_right_edge(input_data, cinfo->max_v_samp_factor,
d44071 ¤   ¤   ····cinfo->image_width, output_cols * 2);
66af5a
97819b ··inrow = 0;
d519b7 ··for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
39a315 ····outptr = output_data[outrow];
b9640a ····inptr0 = input_data[inrow];
74dc5a ····inptr1 = input_data[inrow+1];
00c429 ····bias = 1;¤  ¤   ¤   /* bias = 1,2,1,2,... for successive samples */
deb68d ····for (outcol = 0; outcol < output_cols; outcol++) {
849547 ······*outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
2bea52 ¤   ¤   ¤   ······GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
116633 ¤   ¤   ¤   ······+ bias) >> 2);
12a494 ······bias ^= 3;¤   ¤   /* 1=>2, 2=>1 */
d64ad3 ······inptr0 += 2; inptr1 += 2;
216fe7 ····}
14bb6a ····inrow += 2;
cddf1c ··}
16efe6 }
41af5a
a3af5a
b261bb #ifdef INPUT_SMOOTHING_SUPPORTED
79af5a
8f38e5 /*
58b4cc ·* Downsample pixel values of a single component.
ceb6aa ·* This version handles the standard case of 2:1 horizontal and 2:1 vertical,
2beedf ·* with smoothing. ·One row of context is required.
--4f51 000a80b2b384010001a Page 5 of jcsample.c
47495d ·*/
44af5a
d70434 METHODDEF(void)
080dcf h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
213a04 ¤   ¤   ¤   JSAMPARRAY input_data, JSAMPARRAY output_data)
61bb36 {
06bdba ··int inrow, outrow;
a9ff01 ··JDIMENSION colctr;
e21f33 ··JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
fc69d2 ··register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
fad07d ··INT32 membersum, neighsum, memberscale, neighscale;
12af5a
d9da08 ··/* Expand input data enough to let all the output samples be generated
8dd2a7 ···* by the standard loop. ·Special-casing padded output would be more
c271fb ···* efficient.
76f9a6 ···*/
a5af0d ··expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
484071 ¤   ¤   ····cinfo->image_width, output_cols * 2);
98af5a
c26e03 ··/* We don't bother to form the individual "smoothed" input pixel values;
0fbc71 ···* we can directly compute the output which is the average of the four
2bde97 ···* smoothed values. ·Each of the four member pixels contributes a fraction
aea45c ···* (1-8*SF) to its own smoothed image and a fraction SF to each of the three
c1a59c ···* other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
3790f8 ···* output. ·The four corner-adjacent neighbor pixels contribute a fraction
98022e ···* SF to just one smoothed pixel, or SF/4 to the final output; while the
85e71b ···* eight edge-adjacent neighbors contribute SF to each of two smoothed
310772 ···* pixels, or SF/2 overall. ·In order to use integer arithmetic, these
79c2fd ···* factors are scaled by 2^16 = 65536.
e33eeb ···* Also recall that SF = smoothing_factor / 1024.
0ff9a6 ···*/
d4af5a
3adfde ··memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
4e8677 ··neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
64af5a
65819b ··inrow = 0;
3319b7 ··for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
0ca315 ····outptr = output_data[outrow];
27640a ····inptr0 = input_data[inrow];
58dc5a ····inptr1 = input_data[inrow+1];
808b1b ····above_ptr = input_data[inrow-1];
0a7f6d ····below_ptr = input_data[inrow+2];
c7af5a
1342bd ····/* Special case for first column: pretend column -1 is same as column 0 */
f19a1e ····membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
4c755f ¤   ¤   GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
94abe5 ····neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
3e778f ¤   ·······GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
5dac4a ¤   ·······GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
cb184a ¤   ·······GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
61150b ····neighsum += neighsum;
7a9eb3 ····neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
770103 ¤   ¤   GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
1a9ef2 ····membersum = membersum * memberscale + neighsum * neighscale;
dcd1a5 ····*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
800656 ····inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
4aaf5a
959283 ····for (colctr = output_cols - 2; colctr > 0; colctr--) {
df7974 ······/* sum of pixels directly mapped to this output element */
f5497c ······membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
74afef ¤   ¤   ··GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
bf2daa ······/* sum of edge-neighbor pixels */
29c16b ······neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
e18de6 ¤   ¤   ·GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
f070b4 ¤   ¤   ·GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
c4824c ¤   ¤   ·GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
3bcb4e ······/* The edge-neighbors count twice as much as corner-neighbors */
85090c ······neighsum += neighsum;
85d76b ······/* Add in the corner-neighbors */
060d80 ······neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
40d1ea ¤   ¤   ··GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
a846e9 ······/* form final output scaled up by 2^16 */
--4527 0009d9649154010001a Page 6 of jcsample.c
325b54 ······membersum = membersum * memberscale + neighsum * neighscale;
86ad39 ······/* round, descale and output it */
abcfe1 ······*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
72d534 ······inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
846fe7 ····}
a8af5a
bac30e ····/* Special case for last column */
e19a1e ····membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
94755f ¤   ¤   GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
1dabe5 ····neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
6b778f ¤   ·······GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
73e1df ¤   ·······GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
974889 ¤   ·······GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
09150b ····neighsum += neighsum;
fef4e6 ····neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
d4d3e4 ¤   ¤   GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
b29ef2 ····membersum = membersum * memberscale + neighsum * neighscale;
231ec9 ····*outptr = (JSAMPLE) ((membersum + 32768) >> 16);
bdaf5a
b6bb6a ····inrow += 2;
cbdf1c ··}
3fefe6 }
c3af5a
3daf5a
4338e5 /*
55b4cc ·* Downsample pixel values of a single component.
7e53df ·* This version handles the special case of a full-size component,
66eedf ·* with smoothing. ·One row of context is required.
80495d ·*/
e3af5a
2e0434 METHODDEF(void)
393538 fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
31e38d ¤   ¤   ¤   ····JSAMPARRAY input_data, JSAMPARRAY output_data)
fdbb36 {
90c6b8 ··int outrow;
8eff01 ··JDIMENSION colctr;
261f33 ··JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
a27a11 ··register JSAMPROW inptr, above_ptr, below_ptr, outptr;
d4d07d ··INT32 membersum, neighsum, memberscale, neighscale;
f006d3 ··int colsum, lastcolsum, nextcolsum;
29af5a
5ada08 ··/* Expand input data enough to let all the output samples be generated
e0d2a7 ···* by the standard loop. ·Special-casing padded output would be more
eb71fb ···* efficient.
3ff9a6 ···*/
f3af0d ··expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
dcd603 ¤   ¤   ····cinfo->image_width, output_cols);
b9af5a
e2ea22 ··/* Each of the eight neighbor pixels contributes a fraction SF to the
f2d02e ···* smoothed pixel, while the main pixel contributes (1-8*SF). ·In order
c45f47 ···* to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
5f3eeb ···* Also recall that SF = smoothing_factor / 1024.
75f9a6 ···*/
dcaf5a
b6281f ··memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
b4693d ··neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
e0af5a
8119b7 ··for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
5da315 ····outptr = output_data[outrow];
ad1146 ····inptr = input_data[outrow];
08cd58 ····above_ptr = input_data[outrow-1];
96e5b3 ····below_ptr = input_data[outrow+1];
96af5a
b9c622 ····/* Special case for first column */
11042b ····colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
c2ec01 ¤   ·····GETJSAMPLE(*inptr);
55d31b ····membersum = GETJSAMPLE(*inptr++);
f0a059 ····nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
3d4296 ¤   ¤   ·GETJSAMPLE(*inptr);
2483dd ····neighsum = colsum + (colsum - membersum) + nextcolsum;
ac9ef2 ····membersum = membersum * memberscale + neighsum * neighscale;
9dd1a5 ····*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
--4147 000ef9d97454010001a Page 7 of jcsample.c
85312f ····lastcolsum = colsum; colsum = nextcolsum;
41af5a
029283 ····for (colctr = output_cols - 2; colctr > 0; colctr--) {
ebc239 ······membersum = GETJSAMPLE(*inptr++);
860eff ······above_ptr++; below_ptr++;
22cad7 ······nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
053289 ¤   ¤   ···GETJSAMPLE(*inptr);
e89230 ······neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
d95b54 ······membersum = membersum * memberscale + neighsum * neighscale;
4ccfe1 ······*outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
bea6ac ······lastcolsum = colsum; colsum = nextcolsum;
d56fe7 ····}
96af5a
93c30e ····/* Special case for last column */
fc6f80 ····membersum = GETJSAMPLE(*inptr);
55a2da ····neighsum = lastcolsum + (colsum - membersum) + colsum;
d59ef2 ····membersum = membersum * memberscale + neighsum * neighscale;
1f1ec9 ····*outptr = (JSAMPLE) ((membersum + 32768) >> 16);
08af5a
57df1c ··}
10efe6 }
46af5a
ad7ba9 #endif /* INPUT_SMOOTHING_SUPPORTED */
abaf5a
c6af5a
a538e5 /*
faef6c ·* Module initialization routine for downsampling.
695294 ·* Note that we must select a routine for each component.
0d495d ·*/
d8af5a
b1f898 GLOBAL(void)
f6fa90 jinit_downsampler (j_compress_ptr cinfo)
3dbb36 {
5de5a3 ··my_downsample_ptr downsample;
400dcc ··int ci;
33bcae ··jpeg_component_info * compptr;
6c954c ··boolean smoothok = TRUE;
08af5a
7c5b30 ··downsample = (my_downsample_ptr)
4f3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
5d0a29 ¤   ¤   ¤   ¤   SIZEOF(my_downsampler));
22d9a3 ··cinfo->downsample = (struct jpeg_downsampler *) downsample;
4c5330 ··downsample->pub.start_pass = start_pass_downsample;
f09bb3 ··downsample->pub.downsample = sep_downsample;
1c38fa ··downsample->pub.need_context_rows = FALSE;
8aaf5a
45c76c ··if (cinfo->CCIR601_sampling)
f14065 ····ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
f9af5a
f69f06 ··/* Verify we can handle the sampling factors, and set up method pointers */
d3958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ffaa07 ·······ci++, compptr++) {
31e20c ····if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
57d902 ¤   compptr->v_samp_factor == cinfo->max_v_samp_factor) {
7d61bb #ifdef INPUT_SMOOTHING_SUPPORTED
f49a40 ······if (cinfo->smoothing_factor) {
b8a507 ¤   downsample->methods[ci] = fullsize_smooth_downsample;
7aa130 ¤   downsample->pub.need_context_rows = TRUE;
faedd4 ······} else
7c7454 #endif
2a4ded ¤   downsample->methods[ci] = fullsize_downsample;
bff4b2 ····} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
375c6c ¤   ·······compptr->v_samp_factor == cinfo->max_v_samp_factor) {
729515 ······smoothok = FALSE;
491720 ······downsample->methods[ci] = h2v1_downsample;
03f4b2 ····} else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
283cca ¤   ·······compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
1f61bb #ifdef INPUT_SMOOTHING_SUPPORTED
e39a40 ······if (cinfo->smoothing_factor) {
b0ebbe ¤   downsample->methods[ci] = h2v2_smooth_downsample;
48a130 ¤   downsample->pub.need_context_rows = TRUE;
efedd4 ······} else
--b1f7 00142a8f4b14010001a Page 8 of jcsample.c
a07454 #endif
4d0822 ¤   downsample->methods[ci] = h2v2_downsample;
29a14e ····} else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
1cb2eb ¤   ·······(cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
459515 ······smoothok = FALSE;
41f099 ······downsample->methods[ci] = int_downsample;
26ce75 ····} else
e3fd7c ······ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
d6df1c ··}
86af5a
8261bb #ifdef INPUT_SMOOTHING_SUPPORTED
c74748 ··if (cinfo->smoothing_factor && !smoothok)
ef5fc9 ····TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
b67454 #endif
42efe6 }
--d82d 0000e1c04114010001b Page 1 of jctrans.c
bc38e5 /*
fa8c06 ·* jctrans.c
2d775e ·*
c0c561 ·* Copyright (C) 1995-1996, Thomas G. Lane.
44fb07 ·* This file is part of the Independent JPEG Group's software.
62a0d6 ·* For conditions of distribution and use, see the accompanying README file.
02775e ·*
998da5 ·* This file contains library routines for transcoding compression,
a9cc72 ·* that is, writing raw DCT coefficient arrays to an output JPEG file.
4ef9b6 ·* The routines in jcapimin.c will also be needed by a transcoder.
fc495d ·*/
abaf5a
b62bb6 #define JPEG_INTERNALS
f736a7 #include "jinclude.h"
c36c8f #include "jpeglib.h"
94af5a
b8af5a
8c6a43 /* Forward declarations */
cb3c6c LOCAL(void) transencode_master_selection
4bf410 ¤   JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
b43c59 LOCAL(void) transencode_coef_controller
cff410 ¤   JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
3eaf5a
97af5a
4a38e5 /*
9314ef ·* Compression initialization for writing raw-coefficient data.
14dfd1 ·* Before calling this, all parameters and a data destination must be set up.
aed212 ·* Call jpeg_finish_compress() to actually write the data.
51775e ·*
f0fd45 ·* The number of passed virtual arrays must match cinfo->num_components.
f87e2a ·* Note that the virtual arrays need not be filled or even realized at
84642b ·* the time write_coefficients is called; indeed, if the virtual arrays
95496b ·* were requested from this compression object's memory manager, they
91eec8 ·* typically will be realized during this routine and filled afterwards.
83495d ·*/
41af5a
6df898 GLOBAL(void)
cfa725 jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
10bb36 {
bc5278 ··if (cinfo->global_state != CSTATE_START)
d8918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
b79e14 ··/* Mark all tables to be written */
60d393 ··jpeg_suppress_tables(cinfo, FALSE);
2aa69f ··/* (Re)initialize error mgr and destination modules */
36c167 ··(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
4549be ··(*cinfo->dest->init_destination) (cinfo);
87322e ··/* Perform master selection of active modules */
5f5352 ··transencode_master_selection(cinfo, coef_arrays);
3f5262 ··/* Wait for jpeg_finish_compress() call */
c09f24 ··cinfo->next_scanline = 0;¤/* so jpeg_write_marker works */
9f9661 ··cinfo->global_state = CSTATE_WRCOEFS;
67efe6 }
39af5a
38af5a
ba38e5 /*
7d2162 ·* Initialize the compression object with default parameters,
923d57 ·* then copy from the source object all parameters needed for lossless
87eb99 ·* transcoding. ·Parameters that can be varied without loss (such as
0d2684 ·* scan script and Huffman optimization) are left in their default states.
5a495d ·*/
f1af5a
ecf898 GLOBAL(void)
3d6aab jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
da73ea ¤   ¤   ¤   ·······j_compress_ptr dstinfo)
8cbb36 {
bfa223 ··JQUANT_TBL ** qtblptr;
a56968 ··jpeg_component_info *incomp, *outcomp;
3d87ee ··JQUANT_TBL *c_quant, *slot_quant;
5913db ··int tblno, ci, coefi;
e2af5a
a0820c ··/* Safety check to ensure start_compress not called yet. */
0ee867 ··if (dstinfo->global_state != CSTATE_START)
--287e 00004b419814010001b Page 2 of jctrans.c
9551cf ····ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
2e8790 ··/* Copy fundamental image dimensions */
56257e ··dstinfo->image_width = srcinfo->image_width;
4db86e ··dstinfo->image_height = srcinfo->image_height;
5907be ··dstinfo->input_components = srcinfo->num_components;
0b40e9 ··dstinfo->in_color_space = srcinfo->jpeg_color_space;
76264f ··/* Initialize all parameters to default values */
d93fb1 ··jpeg_set_defaults(dstinfo);
b42a3d ··/* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
3b879c ···* Fix it to get the right header markers for the image colorspace.
b2f9a6 ···*/
4e5908 ··jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
5028ea ··dstinfo->data_precision = srcinfo->data_precision;
aac4d8 ··dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
927241 ··/* Copy the source's quantization tables. */
12ee0a ··for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
8af1bd ····if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
eafa95 ······qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
ea6bf0 ······if (*qtblptr == NULL)
731de5 ¤   *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
1cc595 ······MEMCOPY((*qtblptr)->quantval,
2bc987 ¤   ······srcinfo->quant_tbl_ptrs[tblno]->quantval,
25749d ¤   ······SIZEOF((*qtblptr)->quantval));
9a7412 ······(*qtblptr)->sent_table = FALSE;
a36fe7 ····}
b3df1c ··}
2105d1 ··/* Copy the source's per-component info.
ca23cd ···* Note we assume jpeg_set_defaults has allocated the dest comp_info array.
56f9a6 ···*/
aaa765 ··dstinfo->num_components = srcinfo->num_components;
354895 ··if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
0e5039 ····ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
f43220 ¤   ·····MAX_COMPONENTS);
ba99e2 ··for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
9b3425 ·······ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
3c1e66 ····outcomp->component_id = incomp->component_id;
3494f8 ····outcomp->h_samp_factor = incomp->h_samp_factor;
d8a000 ····outcomp->v_samp_factor = incomp->v_samp_factor;
7f1526 ····outcomp->quant_tbl_no = incomp->quant_tbl_no;
575f13 ····/* Make sure saved quantization table for component matches the qtable
d8fc3b ·····* slot. ·If not, the input file re-used this qtable slot.
6b92d8 ·····* IJG encoder currently cannot duplicate this.
68d48d ·····*/
6fa301 ····tblno = outcomp->quant_tbl_no;
3fb4d2 ····if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
a411c3 ¤   srcinfo->quant_tbl_ptrs[tblno] == NULL)
04dd0d ······ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
9b99d0 ····slot_quant = srcinfo->quant_tbl_ptrs[tblno];
a1b787 ····c_quant = incomp->quant_table;
eb827c ····if (c_quant != NULL) {
df56a4 ······for (coefi = 0; coefi < DCTSIZE2; coefi++) {
d496f0 ¤   if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
af98b0 ¤   ··ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
ac42cc ······}
636fe7 ····}
feb40b ····/* Note: we do not copy the source's Huffman table assignments;
9e607d ·····* instead we rely on jpeg_set_colorspace to have made a suitable choice.
39d48d ·····*/
42df1c ··}
0defe6 }
64af5a
37af5a
ac38e5 /*
f0d408 ·* Master selection of compression modules for transcoding.
0388d1 ·* This substitutes for jcinit.c's initialization of the full compressor.
c3495d ·*/
a5af5a
86afad LOCAL(void)
a4d39c transencode_master_selection (j_compress_ptr cinfo,
8a4a6d ¤   ¤   ¤   ······jvirt_barray_ptr * coef_arrays)
08bb36 {
04ad39 ··/* Although we don't actually use input_components for transcoding,
--1e74 0006dba07f24010001b Page 3 of jctrans.c
353241 ···* jcmaster.c's initial_setup will complain if input_components is 0.
a2f9a6 ···*/
ab5448 ··cinfo->input_components = 1;
21cc00 ··/* Initialize master control (includes parameter checking/processing) */
e1c962 ··jinit_c_master_control(cinfo, TRUE /* transcode only */);
38af5a
624fff ··/* Entropy encoding: either Huffman or arithmetic coding. */
01a4f1 ··if (cinfo->arith_code) {
a73fef ····ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
8a49d8 ··} else {
d28aef ····if (cinfo->progressive_mode) {
8668ad #ifdef C_PROGRESSIVE_SUPPORTED
e3ff89 ······jinit_phuff_encoder(cinfo);
79db21 #else
ab9015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
627454 #endif
efce75 ····} else
63b182 ······jinit_huff_encoder(cinfo);
a7df1c ··}
4baf5a
0aa389 ··/* We need a special coefficient buffer controller. */
35fa6b ··transencode_coef_controller(cinfo, coef_arrays);
acaf5a
736557 ··jinit_marker_writer(cinfo);
21af5a
9e5924 ··/* We can now tell the memory manager to allocate virtual arrays. */
0ba9b1 ··(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
65af5a
f9a7ac ··/* Write the datastream header (SOI) immediately.
732402 ···* Frame and scan headers are postponed till later.
8e4f45 ···* This lets application insert special markers after the SOI.
64f9a6 ···*/
4b89a9 ··(*cinfo->marker->write_file_header) (cinfo);
6befe6 }
67af5a
adaf5a
b438e5 /*
c27c59 ·* The rest of this file is a special implementation of the coefficient
d77545 ·* buffer controller. ·This is similar to jccoefct.c, but it handles only
d8ba46 ·* output from presupplied virtual arrays. ·Furthermore, we generate any
23a9ba ·* dummy padding blocks on-the-fly rather than expecting them to be present
db42ed ·* in the arrays.
5e495d ·*/
85af5a
c18416 /* Private buffer controller object */
91af5a
10f0f7 typedef struct {
620f8d ··struct jpeg_c_coef_controller pub; /* public fields */
a2af5a
8e3f4e ··JDIMENSION iMCU_row_num;¤ /* iMCU row # within image */
60a8a6 ··JDIMENSION mcu_ctr;¤  ¤   /* counts MCUs processed in current row */
94c7f6 ··int MCU_vert_offset;¤ ¤   /* counts MCU rows within iMCU row */
b30fac ··int MCU_rows_per_iMCU_row;¤   /* number of such rows needed */
94af5a
1ad23a ··/* Virtual block array for each component. */
a51e9c ··jvirt_barray_ptr * whole_image;
3faf5a
b42412 ··/* Workspace for constructing dummy blocks at right/bottom edges. */
b043f9 ··JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
86c38c } my_coef_controller;
beaf5a
7acf47 typedef my_coef_controller * my_coef_ptr;
6baf5a
bcaf5a
54afad LOCAL(void)
faadc8 start_iMCU_row (j_compress_ptr cinfo)
6178a6 /* Reset within-iMCU-row counters for a new row */
c4bb36 {
257924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
77af5a
2d57ee ··/* In an interleaved scan, an MCU row is the same as an iMCU row.
6d9ae6 ···* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
--d591 000f5d0f2394010001b Page 4 of jctrans.c
7d5867 ···* But at the bottom of the image, process only what's left.
fff9a6 ···*/
1d1aae ··if (cinfo->comps_in_scan > 1) {
f533a9 ····coef->MCU_rows_per_iMCU_row = 1;
a949d8 ··} else {
877392 ····if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
d41b09 ······coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
d2842c ····else
20ced2 ······coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
02df1c ··}
c3af5a
a90b2e ··coef->mcu_ctr = 0;
b3f553 ··coef->MCU_vert_offset = 0;
b5efe6 }
03af5a
ebaf5a
9e38e5 /*
825b80 ·* Initialize for a processing pass.
09495d ·*/
c4af5a
5f0434 METHODDEF(void)
9655be start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
7ebb36 {
0a7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
cfaf5a
59bb5b ··if (pass_mode != JBUF_CRANK_DEST)
f1650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
04af5a
819dd8 ··coef->iMCU_row_num = 0;
0d3d6b ··start_iMCU_row(cinfo);
7befe6 }
e4af5a
89af5a
3738e5 /*
1b3bfc ·* Process some data.
aa4e35 ·* We process the equivalent of one fully interleaved MCU row ("iMCU" row)
0124b0 ·* per call, ie, v_samp_factor block rows for each component in the scan.
010916 ·* The data is obtained from the virtual arrays and fed to the entropy coder.
d5ea83 ·* Returns TRUE if the iMCU row is completed, FALSE if suspended.
7b775e ·*
64ef1a ·* NB: input_buf is ignored; it is likely to be a NULL pointer.
02495d ·*/
d6af5a
cf9a8f METHODDEF(boolean)
f67c53 compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
ecbb36 {
0f7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
f32df3 ··JDIMENSION MCU_col_num;¤  /* index of current MCU within row */
15b9a6 ··JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
23e5c0 ··JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
e7f154 ··int blkn, ci, xindex, yindex, yoffset, blockcnt;
22f9ae ··JDIMENSION start_col;
2aa37f ··JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
ff7d86 ··JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
a1065a ··JBLOCKROW buffer_ptr;
8133b0 ··jpeg_component_info *compptr;
62af5a
f3ffca ··/* Align the virtual buffers for the components used in this scan. */
216aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
f8a7cc ····compptr = cinfo->cur_comp_info[ci];
ea917c ····buffer[ci] = (*cinfo->mem->access_virt_barray)
d67fe4 ······((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
4ff5ef ·······coef->iMCU_row_num * compptr->v_samp_factor,
345a8b ·······(JDIMENSION) compptr->v_samp_factor, FALSE);
29df1c ··}
7caf5a
422174 ··/* Loop to process one whole iMCU row */
b8a27a ··for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
78bd1b ·······yoffset++) {
eb49d7 ····for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
842288 ¤   ·MCU_col_num++) {
f55139 ······/* Construct list of pointers to DCT blocks belonging to this MCU */
--574b 00024aebec54010001b Page 5 of jctrans.c
785fdc ······blkn = 0;¤¤   ¤   /* index of current DCT block within MCU */
bf6064 ······for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
d708f5 ¤   compptr = cinfo->cur_comp_info[ci];
d88a61 ¤   start_col = MCU_col_num * compptr->MCU_width;
d0458b ¤   blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
c27d55 ¤   ¤   ¤   ¤   ¤   ¤   : compptr->last_col_width;
8a76a3 ¤   for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
50b7d4 ¤   ··if (coef->iMCU_row_num < last_iMCU_row ||
3f9618 ¤   ······yindex+yoffset < compptr->last_row_height) {
16dba6 ¤   ····/* Fill in pointers to real blocks in this row */
343e6b ¤   ····buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
1d8cb9 ¤   ····for (xindex = 0; xindex < blockcnt; xindex++)
46a64c ¤   ······MCU_buffer[blkn++] = buffer_ptr++;
652862 ¤   ··} else {
8e08e6 ¤   ····/* At bottom of image, need a whole row of dummy blocks */
15daf1 ¤   ····xindex = 0;
d532a2 ¤   ··}
38390a ¤   ··/* Fill in any dummy blocks needed in this row.
011bb6 ¤   ···* Dummy blocks are filled in the same way as in jccoefct.c:
f3d53e ¤   ···* all zeroes in the AC entries, DC entries equal to previous
ce71c1 ¤   ···* block's DC value. ·The init routine has already zeroed the
5b0cb0 ¤   ···* AC entries, so we need only set the DC entries correctly.
486533 ¤   ···*/
a47765 ¤   ··for (; xindex < compptr->MCU_width; xindex++) {
ceb3c3 ¤   ····MCU_buffer[blkn] = coef->dummy_buffer[blkn];
c86ec3 ¤   ····MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
d1abab ¤   ····blkn++;
5f32a2 ¤   ··}
ee9371 ¤   }
a142cc ······}
1072ff ······/* Try to write the MCU. */
27462a ······if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
d03fee ¤   /* Suspension forced; update state counters and exit */
dcebe8 ¤   coef->MCU_vert_offset = yoffset;
35eece ¤   coef->mcu_ctr = MCU_col_num;
56a230 ¤   return FALSE;
0542cc ······}
4e6fe7 ····}
4db67f ····/* Completed an MCU row, but perhaps not an iMCU row */
e90874 ····coef->mcu_ctr = 0;
aedf1c ··}
1677d6 ··/* Completed the iMCU row, advance counters for next one */
afb60b ··coef->iMCU_row_num++;
333d6b ··start_iMCU_row(cinfo);
e5d2c8 ··return TRUE;
deefe6 }
abaf5a
5daf5a
8338e5 /*
a57e1c ·* Initialize coefficient buffer controller.
3f775e ·*
1aea21 ·* Each passed coefficient array must be the right size for that
33606b ·* coefficient: width_in_blocks wide and height_in_blocks high,
233b63 ·* with unitheight at least v_samp_factor.
c3495d ·*/
8daf5a
e1afad LOCAL(void)
4ca38c transencode_coef_controller (j_compress_ptr cinfo,
0fc8b3 ¤   ¤   ¤   ·····jvirt_barray_ptr * coef_arrays)
19bb36 {
36b982 ··my_coef_ptr coef;
3442a2 ··JBLOCKROW buffer;
8617e0 ··int i;
56af5a
1b70bd ··coef = (my_coef_ptr)
d93f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
ad89b6 ¤   ¤   ¤   ¤   SIZEOF(my_coef_controller));
629ebf ··cinfo->coef = (struct jpeg_c_coef_controller *) coef;
3093ac ··coef->pub.start_pass = start_pass_coef;
419cb1 ··coef->pub.compress_data = compress_output;
b2af5a
24235a ··/* Save pointer to virtual arrays */
--0e7b 0018098af224010001b Page 6 of jctrans.c
66898b ··coef->whole_image = coef_arrays;
97af5a
8cd5ef ··/* Allocate and pre-zero space for dummy DCT blocks. */
3897fc ··buffer = (JBLOCKROW)
f7557f ····(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
ac7acc ¤   ¤   ¤   ¤   C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
0bef94 ··jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
cd14a1 ··for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
bafcf0 ····coef->dummy_buffer[i] = buffer + i;
aadf1c ··}
80efe6 }
--e0d2 000f30ae8f54010001c Page 1 of jdapimin.c
bc38e5 /*
44ff7c ·* jdapimin.c
6d775e ·*
339e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
25fb07 ·* This file is part of the Independent JPEG Group's software.
39a0d6 ·* For conditions of distribution and use, see the accompanying README file.
34775e ·*
61aab3 ·* This file contains application interface code for the decompression half
3d9df1 ·* of the JPEG library. ·These are the "minimum" API routines that may be
b918ea ·* needed in either the normal full-decompression case or the
b1da30 ·* transcoding-only case.
6d775e ·*
3a304d ·* Most of the routines intended to be called directly by an application
4e762f ·* are in this file or in jdapistd.c. ·But also see jcomapi.c for routines
2af1a4 ·* shared by compression and decompression, and jdtrans.c for the transcoding
73a202 ·* case.
5a495d ·*/
4aaf5a
dd2bb6 #define JPEG_INTERNALS
7336a7 #include "jinclude.h"
f16c8f #include "jpeglib.h"
58af5a
ccaf5a
3338e5 /*
9393a4 ·* Initialization of a JPEG decompression object.
219213 ·* The error manager must already be set up (in case memory manager fails).
e9495d ·*/
b5af5a
85f898 GLOBAL(void)
33f947 jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
5bbb36 {
c817e0 ··int i;
eaaf5a
2a8935 ··/* Guard against version mismatches between library and caller. */
1f962d ··cinfo->mem = NULL;¤   ¤   /* so jpeg_destroy knows mem mgr not called */
307a94 ··if (version != JPEG_LIB_VERSION)
eeab37 ····ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
c240dc ··if (structsize != SIZEOF(struct jpeg_decompress_struct))
1cf695 ····ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,·
cfa29c ¤   ·····(int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
d5af5a
d2e883 ··/* For debugging purposes, zero the whole master structure.
43bc85 ···* But error manager pointer is already there, so save and restore it.
8cf9a6 ···*/
e08bcc ··{
e8de0a ····struct jpeg_error_mgr * err = cinfo->err;
7e9b9b ····MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
b6ea0e ····cinfo->err = err;
45df1c ··}
d82ed3 ··cinfo->is_decompressor = TRUE;
8daf5a
3f1275 ··/* Initialize a memory manager instance for this object */
60d00c ··jinit_memory_mgr((j_common_ptr) cinfo);
c8af5a
3fa71f ··/* Zero out pointers to permanent structures. */
e931d3 ··cinfo->progress = NULL;
a010eb ··cinfo->src = NULL;
efaf5a
8adce1 ··for (i = 0; i < NUM_QUANT_TBLS; i++)
48d301 ····cinfo->quant_tbl_ptrs[i] = NULL;
61af5a
b072db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
495c2e ····cinfo->dc_huff_tbl_ptrs[i] = NULL;
a4b27b ····cinfo->ac_huff_tbl_ptrs[i] = NULL;
ebdf1c ··}
a5af5a
6ed9df ··/* Initialize marker processor so application can override methods
903cec ···* for COM, APPn markers before calling jpeg_read_header.
adf9a6 ···*/
0c9b24 ··jinit_marker_reader(cinfo);
58af5a
f3ed92 ··/* And initialize the overall input controller. */
--04af 0004e6a0da64010001c Page 2 of jdapimin.c
8f5cbb ··jinit_input_controller(cinfo);
a3af5a
5fdfd2 ··/* OK, I'm ready */
cd4628 ··cinfo->global_state = DSTATE_START;
9cefe6 }
47af5a
52af5a
4038e5 /*
9fa9b4 ·* Destruction of a JPEG decompression object
57495d ·*/
0baf5a
d0f898 GLOBAL(void)
482814 jpeg_destroy_decompress (j_decompress_ptr cinfo)
65bb36 {
479b5e ··jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
64efe6 }
0daf5a
2baf5a
fb38e5 /*
c02852 ·* Abort processing of a JPEG decompression operation,
b9292b ·* but don't destroy the object itself.
fe495d ·*/
8eaf5a
bff898 GLOBAL(void)
faf349 jpeg_abort_decompress (j_decompress_ptr cinfo)
50bb36 {
c2093b ··jpeg_abort((j_common_ptr) cinfo); /* use common routine */
1fefe6 }
32af5a
afaf5a
1a38e5 /*
c53a11 ·* Install a special processing method for COM or APPn markers.
4b495d ·*/
98af5a
07f898 GLOBAL(void)
37c092 jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
dd53fb ¤   ¤   ¤   ···jpeg_marker_parser_method routine)
d1bb36 {
30727b ··if (marker_code == JPEG_COM)
425b6f ····cinfo->marker->process_COM = routine;
b7fcd7 ··else if (marker_code >= JPEG_APP0 && marker_code <= JPEG_APP0+15)
089581 ····cinfo->marker->process_APPn[marker_code-JPEG_APP0] = routine;
7a1bd0 ··else
3612a9 ····ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
68efe6 }
adaf5a
faaf5a
d638e5 /*
b7c0cd ·* Set default decompression parameters.
62495d ·*/
58af5a
8aafad LOCAL(void)
65ed24 default_decompress_parms (j_decompress_ptr cinfo)
69bb36 {
5cc4a7 ··/* Guess the input colorspace, and set output colorspace accordingly. */
5091e9 ··/* (Wish JPEG committee had provided a real way to specify this...) */
9c0ba6 ··/* Note application may override our guesses. */
0aad65 ··switch (cinfo->num_components) {
8fa6cf ··case 1:
7d9baf ····cinfo->jpeg_color_space = JCS_GRAYSCALE;
ee0f7e ····cinfo->out_color_space = JCS_GRAYSCALE;
edab40 ····break;
8e869e ····
af1377 ··case 3:
eb2cbf ····if (cinfo->saw_JFIF_marker) {
f7342d ······cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
ebbf8b ····} else if (cinfo->saw_Adobe_marker) {
b47402 ······switch (cinfo->Adobe_transform) {
befbb1 ······case 0:
52e0ea ¤   cinfo->jpeg_color_space = JCS_RGB;
4d4ed2 ¤   break;
4ea16d ······case 1:
--741c 000609ced1d4010001c Page 3 of jdapimin.c
6ef18f ¤   cinfo->jpeg_color_space = JCS_YCbCr;
784ed2 ¤   break;
8a1082 ······default:
4aea00 ¤   WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
06937e ¤   cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
504ed2 ¤   break;
2842cc ······}
0c6a79 ····} else {
d89b12 ······/* Saw no special markers, try to guess from the component IDs */
3f2bd5 ······int cid0 = cinfo->comp_info[0].component_id;
f59112 ······int cid1 = cinfo->comp_info[1].component_id;
1c564a ······int cid2 = cinfo->comp_info[2].component_id;
50af5a
c2d4d6 ······if (cid0 == 1 && cid1 == 2 && cid2 == 3)
ba390c ¤   cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
4e8e20 ······else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
0899b7 ¤   cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
5ea069 ······else {
646725 ¤   TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
44937e ¤   cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
8e42cc ······}
666fe7 ····}
d6e716 ····/* Always guess RGB is proper output colorspace. */
6a80c3 ····cinfo->out_color_space = JCS_RGB;
54ab40 ····break;
b5869e ····
c99f72 ··case 4:
32a4df ····if (cinfo->saw_Adobe_marker) {
db7402 ······switch (cinfo->Adobe_transform) {
0ffbb1 ······case 0:
e8c1cb ¤   cinfo->jpeg_color_space = JCS_CMYK;
314ed2 ¤   break;
bc4e09 ······case 2:
91d4c2 ¤   cinfo->jpeg_color_space = JCS_YCCK;
c64ed2 ¤   break;
911082 ······default:
45ea00 ¤   WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
cea5f5 ¤   cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
b14ed2 ¤   break;
3142cc ······}
a46a79 ····} else {
f017b6 ······/* No special markers, assume straight CMYK. */
447f79 ······cinfo->jpeg_color_space = JCS_CMYK;
1f6fe7 ····}
717d68 ····cinfo->out_color_space = JCS_CMYK;
b2ab40 ····break;
ab869e ····
70969d ··default:
d30c20 ····cinfo->jpeg_color_space = JCS_UNKNOWN;
a349da ····cinfo->out_color_space = JCS_UNKNOWN;
f2ab40 ····break;
8fdf1c ··}
dbaf5a
246bf0 ··/* Set defaults for other decompression parameters. */
a95dec ··cinfo->scale_num = 1;¤¤   /* 1:1 scaling */
66e1f9 ··cinfo->scale_denom = 1;
00ef2e ··cinfo->output_gamma = 1.0;
c479a0 ··cinfo->buffered_image = FALSE;
f63524 ··cinfo->raw_data_out = FALSE;
4d0329 ··cinfo->dct_method = JDCT_DEFAULT;
61ec59 ··cinfo->do_fancy_upsampling = TRUE;
d68475 ··cinfo->do_block_smoothing = TRUE;
84f151 ··cinfo->quantize_colors = FALSE;
94fded ··/* We set these in case application only sets quantize_colors. */
3a9285 ··cinfo->dither_mode = JDITHER_FS;
ae4df6 #ifdef QUANT_2PASS_SUPPORTED
7fa7f3 ··cinfo->two_pass_quantize = TRUE;
7cdb21 #else
0bf4f0 ··cinfo->two_pass_quantize = FALSE;
e47454 #endif
65dcf9 ··cinfo->desired_number_of_colors = 256;
60cde2 ··cinfo->colormap = NULL;
--fb87 000e823accd4010001c Page 4 of jdapimin.c
beadb8 ··/* Initialize for no mode change in buffered-image mode. */
8fa767 ··cinfo->enable_1pass_quant = FALSE;
9349a5 ··cinfo->enable_external_quant = FALSE;
4bfed3 ··cinfo->enable_2pass_quant = FALSE;
d7efe6 }
94af5a
6aaf5a
0d38e5 /*
dfc0d2 ·* Decompression startup: read start of JPEG datastream to see what's there.
87cb92 ·* Need only initialize JPEG object and supply a data source before calling.
46775e ·*
3f6cd8 ·* This routine will read as far as the first SOS marker (ie, actual start of
6170c3 ·* compressed data), and will save all tables and parameters in the JPEG
a7d134 ·* object. ·It will also initialize the decompression parameters to default
8427e2 ·* values, and finally return JPEG_HEADER_OK. ·On return, the application may
6abea9 ·* adjust the decompression parameters and then call jpeg_start_decompress.
5d9e61 ·* (Or, if the application only wanted to determine the image parameters,
296a01 ·* the data need not be decompressed. ·In that case, call jpeg_abort or
2ecadf ·* jpeg_destroy to release any temporary space.)
98e8dd ·* If an abbreviated (tables only) datastream is presented, the routine will
520cc5 ·* return JPEG_HEADER_TABLES_ONLY upon reaching EOI. ·The application may then
bc7bf7 ·* re-use the JPEG object to read the abbreviated image datastream(s).
2c2956 ·* It is unnecessary (but OK) to call jpeg_abort in this case.
b0d89f ·* The JPEG_SUSPENDED return code only occurs if the data source module
689fa7 ·* requests suspension of the decompressor. ·In this case the application
4351b5 ·* should load more source data and then re-call jpeg_read_header to resume
ab45f6 ·* processing.
f63cde ·* If a non-suspending data source is used and require_image is TRUE, then the
fd1a64 ·* return code need not be inspected since only JPEG_HEADER_OK is possible.
1b775e ·*
710477 ·* This routine is now just a front end to jpeg_consume_input, with some
3f701e ·* extra error checking.
fc495d ·*/
c5af5a
3a326f GLOBAL(int)
da142f jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
d1bb36 {
19a314 ··int retcode;
33af5a
927a92 ··if (cinfo->global_state != DSTATE_START &&
3e4bee ······cinfo->global_state != DSTATE_INHEADER)
8b918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
49af5a
92cdd0 ··retcode = jpeg_consume_input(cinfo);
87af5a
b6c7ef ··switch (retcode) {
30225a ··case JPEG_REACHED_SOS:
d07063 ····retcode = JPEG_HEADER_OK;
4aab40 ····break;
005b6d ··case JPEG_REACHED_EOI:
a2ffc8 ····if (require_image)¤ ¤   /* Complain if application wanted an image */
76b8d3 ······ERREXIT(cinfo, JERR_NO_IMAGE);
98770f ····/* Reset to start state; it would be safer to require the application to
8eac39 ·····* call jpeg_abort, but we can't change it now for compatibility reasons.
41da64 ·····* A side effect is to free any temporary memory (there shouldn't be any).
ecd48d ·····*/
1f22ff ····jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
aa8791 ····retcode = JPEG_HEADER_TABLES_ONLY;
ebab40 ····break;
806b90 ··case JPEG_SUSPENDED:
7b26f3 ····/* no work */
25ab40 ····break;
6bdf1c ··}
fcaf5a
9b4dcb ··return retcode;
d6efe6 }
f5af5a
eeaf5a
4538e5 /*
84fcaf ·* Consume data in advance of what the decompressor requires.
f03008 ·* This can be called at any time once the decompressor object has
e84086 ·* been created and a data source has been set up.
--d177 000188fce794010001c Page 5 of jdapimin.c
4f775e ·*
89b3fe ·* This routine is essentially a state machine that handles a couple
3f833e ·* of critical state-transition actions, namely initial setup and
21f88d ·* transition from header scanning to ready-for-start_decompress.
830dcf ·* All the actual input is done via the input controller's consume_input
778355 ·* method.
d5495d ·*/
a1af5a
4c326f GLOBAL(int)
ef0fb5 jpeg_consume_input (j_decompress_ptr cinfo)
b5bb36 {
d706ea ··int retcode = JPEG_SUSPENDED;
59af5a
3a2b44 ··/* NB: every possible DSTATE value should be listed in this switch */
3bad38 ··switch (cinfo->global_state) {
74b13b ··case DSTATE_START:
3d6347 ····/* Start-of-datastream actions: reset appropriate modules */
c0a319 ····(*cinfo->inputctl->reset_input_controller) (cinfo);
8f72fc ····/* Initialize application's data source module */
589c91 ····(*cinfo->src->init_source) (cinfo);
8f8dbb ····cinfo->global_state = DSTATE_INHEADER;
16a950 ····/*FALLTHROUGH*/
1afe1c ··case DSTATE_INHEADER:
329fa8 ····retcode = (*cinfo->inputctl->consume_input) (cinfo);
3296c6 ····if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
ce8b8b ······/* Set up default parameters based on header data */
ba2d1a ······default_decompress_parms(cinfo);
ce6650 ······/* Set global state: ready for start_decompress */
54e88b ······cinfo->global_state = DSTATE_READY;
366fe7 ····}
17ab40 ····break;
ea1f31 ··case DSTATE_READY:
0e7464 ····/* Can't advance past first SOS until start_decompress is called */
9eeb96 ····retcode = JPEG_REACHED_SOS;
feab40 ····break;
70b2c3 ··case DSTATE_PRELOAD:
dfc9b0 ··case DSTATE_PRESCAN:
2df7ba ··case DSTATE_SCANNING:
daad42 ··case DSTATE_RAW_OK:
2213d4 ··case DSTATE_BUFIMAGE:
cceecb ··case DSTATE_BUFPOST:
87993b ··case DSTATE_STOPPING:
969fa8 ····retcode = (*cinfo->inputctl->consume_input) (cinfo);
f6ab40 ····break;
be969d ··default:
da918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
20df1c ··}
674dcb ··return retcode;
34efe6 }
42af5a
3daf5a
3438e5 /*
870dae ·* Have we finished reading the input file?
26495d ·*/
f6af5a
ade553 GLOBAL(boolean)
3769df jpeg_input_complete (j_decompress_ptr cinfo)
d4bb36 {
2a4d34 ··/* Check for valid jpeg object */
8364c9 ··if (cinfo->global_state < DSTATE_START ||
fc5874 ······cinfo->global_state > DSTATE_STOPPING)
2c918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
a1a0ea ··return cinfo->inputctl->eoi_reached;
36efe6 }
38af5a
acaf5a
1638e5 /*
f24dfc ·* Is there more than one scan?
0a495d ·*/
48af5a
dce553 GLOBAL(boolean)
18df4a jpeg_has_multiple_scans (j_decompress_ptr cinfo)
--199e 00179b226514010001c Page 6 of jdapimin.c
2cbb36 {
9a17ec ··/* Only valid after jpeg_read_header completes */
35d5cd ··if (cinfo->global_state < DSTATE_READY ||
ab5874 ······cinfo->global_state > DSTATE_STOPPING)
c4918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
74035c ··return cinfo->inputctl->has_multiple_scans;
27efe6 }
01af5a
28af5a
0038e5 /*
ca149f ·* Finish JPEG decompression.
85775e ·*
fd4c32 ·* This will normally just verify the file trailer and release temp storage.
2d775e ·*
8e6d35 ·* Returns FALSE if suspended. ·The return value need be inspected only if
cb6f4f ·* a suspending data source is used.
98495d ·*/
e2af5a
f2e553 GLOBAL(boolean)
9d7421 jpeg_finish_decompress (j_decompress_ptr cinfo)
c0bb36 {
c8a432 ··if ((cinfo->global_state == DSTATE_SCANNING ||
2cc833 ·······cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
e66f14 ····/* Terminate final pass of non-buffered mode */
e561dd ····if (cinfo->output_scanline < cinfo->output_height)
b7726f ······ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
03d139 ····(*cinfo->master->finish_output_pass) (cinfo);
43ea9c ····cinfo->global_state = DSTATE_STOPPING;
d366ba ··} else if (cinfo->global_state == DSTATE_BUFIMAGE) {
5402d7 ····/* Finishing after a buffered-image operation */
d4ea9c ····cinfo->global_state = DSTATE_STOPPING;
2e3528 ··} else if (cinfo->global_state != DSTATE_STOPPING) {
19ed20 ····/* STOPPING = repeat call after a suspension, anything else is error */
c3918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
2adf1c ··}
792094 ··/* Read until EOI */
326fc9 ··while (! cinfo->inputctl->eoi_reached) {
669b45 ····if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
d6204a ······return FALSE;¤¤   /* Suspend, come back later */
5edf1c ··}
1a5e04 ··/* Do final cleanup */
0eb776 ··(*cinfo->src->term_source) (cinfo);
e1617f ··/* We can use jpeg_abort to release memory and reset global_state */
7436ea ··jpeg_abort((j_common_ptr) cinfo);
f5d2c8 ··return TRUE;
79efe6 }
--fcd9 0007d700e774010001d Page 1 of jdapistd.c
bc38e5 /*
8a90f4 ·* jdapistd.c
4a775e ·*
419e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
84fb07 ·* This file is part of the Independent JPEG Group's software.
3da0d6 ·* For conditions of distribution and use, see the accompanying README file.
07775e ·*
67aab3 ·* This file contains application interface code for the decompression half
a2bf5c ·* of the JPEG library. ·These are the "standard" API routines that are
db0433 ·* used in the normal full-decompression case. ·They are not used by a
b73ade ·* transcoding-only application. ·Note that if an application links in
a0bdd5 ·* jpeg_start_decompress, it will end up linking in the entire decompressor.
31417b ·* We thus must separate this file from jdapimin.c to avoid linking the
6e17f7 ·* whole decompression library into a transcoder.
82495d ·*/
05af5a
ba2bb6 #define JPEG_INTERNALS
6636a7 #include "jinclude.h"
126c8f #include "jpeglib.h"
77af5a
6daf5a
7a6a43 /* Forward declarations */
4c286c LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
b5af5a
9baf5a
ab38e5 /*
f4cd3c ·* Decompression initialization.
845a35 ·* jpeg_read_header must be completed before calling this.
fa775e ·*
9e9960 ·* If a multipass operating mode was selected, this will do all but the
ddd640 ·* last pass, and thus may take a great deal of time.
18775e ·*
e66d35 ·* Returns FALSE if suspended. ·The return value need be inspected only if
b36f4f ·* a suspending data source is used.
cd495d ·*/
1baf5a
26e553 GLOBAL(boolean)
bf6a0e jpeg_start_decompress (j_decompress_ptr cinfo)
ebbb36 {
db1ca0 ··if (cinfo->global_state == DSTATE_READY) {
31cd66 ····/* First call: initialize master control, select active modules */
d1935c ····jinit_master_decompress(cinfo);
6f103a ····if (cinfo->buffered_image) {
c85747 ······/* No more work here; expecting jpeg_start_output next */
ecc970 ······cinfo->global_state = DSTATE_BUFIMAGE;
9e79a5 ······return TRUE;
486fe7 ····}
cb9ae2 ····cinfo->global_state = DSTATE_PRELOAD;
d8df1c ··}
5f3a97 ··if (cinfo->global_state == DSTATE_PRELOAD) {
756864 ····/* If file has multiple scans, absorb them all into the coef buffer */
3be095 ····if (cinfo->inputctl->has_multiple_scans) {
ffa01c #ifdef D_MULTISCAN_FILES_SUPPORTED
169772 ······for (;;) {
33b33b ¤   int retcode;
51093a ¤   /* Call progress monitor hook if present */
ce0f8c ¤   if (cinfo->progress != NULL)
dee9de ¤   ··(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
7b5c5a ¤   /* Absorb some more input */
729b6f ¤   retcode = (*cinfo->inputctl->consume_input) (cinfo);
51566e ¤   if (retcode == JPEG_SUSPENDED)
3feca6 ¤   ··return FALSE;
0a0e86 ¤   if (retcode == JPEG_REACHED_EOI)
f912af ¤   ··break;
a2ef8e ¤   /* Advance progress counter if appropriate */
275ad9 ¤   if (cinfo->progress != NULL &&
3b9c85 ¤   ····(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
3160ed ¤   ··if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
a54c7c ¤   ····/* jdmaster underestimated number of scans; ratchet up one scan */
9c1905 ¤   ····cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
9232a2 ¤   ··}
7d9371 ¤   }
--2e63 0006cafd06e4010001d Page 2 of jdapistd.c
a642cc ······}
3ddb21 #else
b29015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
6744d7 #endif /* D_MULTISCAN_FILES_SUPPORTED */
586fe7 ····}
63ffb1 ····cinfo->output_scan_number = cinfo->input_scan_number;
2efada ··} else if (cinfo->global_state != DSTATE_PRESCAN)
61918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
dd2b11 ··/* Perform any dummy output passes, and set up for the final pass */
e69810 ··return output_pass_setup(cinfo);
d9efe6 }
ffaf5a
f4af5a
3138e5 /*
7904f9 ·* Set up for an output pass, and perform any dummy pass(es) needed.
4085a3 ·* Common subroutine for jpeg_start_decompress and jpeg_start_output.
364bc3 ·* Entry: global_state = DSTATE_PRESCAN only if previously suspended.
9d90f8 ·* Exit: If done, returns TRUE and sets global_state for proper output mode.
603055 ·* ······If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
6a495d ·*/
40af5a
aac4bf LOCAL(boolean)
068ab5 output_pass_setup (j_decompress_ptr cinfo)
c3bb36 {
7d2d5d ··if (cinfo->global_state != DSTATE_PRESCAN) {
25b077 ····/* First call: do pass setup */
b54418 ····(*cinfo->master->prepare_for_output_pass) (cinfo);
85c793 ····cinfo->output_scanline = 0;
0be191 ····cinfo->global_state = DSTATE_PRESCAN;
67df1c ··}
b5a3ae ··/* Loop over any required dummy passes */
d10322 ··while (cinfo->master->is_dummy_pass) {
ea4df6 #ifdef QUANT_2PASS_SUPPORTED
bfecb6 ····/* Crank through the dummy pass */
7a2060 ····while (cinfo->output_scanline < cinfo->output_height) {
6d36d9 ······JDIMENSION last_scanline;
56f249 ······/* Call progress monitor hook if present */
00c37e ······if (cinfo->progress != NULL) {
d08228 ¤   cinfo->progress->pass_counter = (long) cinfo->output_scanline;
d7a8bc ¤   cinfo->progress->pass_limit = (long) cinfo->output_height;
28798e ¤   (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
6a42cc ······}
e33fc8 ······/* Process some data */
6fa4b2 ······last_scanline = cinfo->output_scanline;
7943a1 ······(*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
49144c ¤   ¤   ¤   ¤   ····&cinfo->output_scanline, (JDIMENSION) 0);
abab66 ······if (cinfo->output_scanline == last_scanline)
e6f094 ¤   return FALSE;¤  ¤   /* No progress made, must suspend */
a76fe7 ····}
51fa75 ····/* Finish up dummy pass, and set up for another one */
92d139 ····(*cinfo->master->finish_output_pass) (cinfo);
3b4418 ····(*cinfo->master->prepare_for_output_pass) (cinfo);
53c793 ····cinfo->output_scanline = 0;
04db21 #else
d69214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
6fd24f #endif /* QUANT_2PASS_SUPPORTED */
2bdf1c ··}
efce75 ··/* Ready for application to drive output pass through
469dde ···* jpeg_read_scanlines or jpeg_read_raw_data.
4df9a6 ···*/
1dde6d ··cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
cbd2c8 ··return TRUE;
7eefe6 }
80af5a
e2af5a
8a38e5 /*
9af402 ·* Read some scanlines of data from the JPEG decompressor.
78775e ·*
c836fd ·* The return value will be the number of lines actually read.
39bb1b ·* This may be less than the number requested in several cases,
b30f7c ·* including bottom of image, data source suspension, and operating
6c87b1 ·* modes that emit multiple scanlines at a time.
--533f 00082808c324010001d Page 3 of jdapistd.c
4f775e ·*
13bc00 ·* Note: we warn about excess calls to jpeg_read_scanlines() since
ece0bf ·* this likely signals an application programmer error. ·However,
9881c2 ·* an oversize buffer (max_lines > scanlines remaining) is not an error.
0e495d ·*/
b3af5a
862e0d GLOBAL(JDIMENSION)
16d10a jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
77b56f ¤   ¤   ·····JDIMENSION max_lines)
23bb36 {
b5c33e ··JDIMENSION row_ctr;
7caf5a
6ebb01 ··if (cinfo->global_state != DSTATE_SCANNING)
df918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
16bc61 ··if (cinfo->output_scanline >= cinfo->output_height) {
6344d3 ····WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
b4958b ····return 0;
a8df1c ··}
48af5a
b32358 ··/* Call progress monitor hook if present */
21feda ··if (cinfo->progress != NULL) {
3f8ab5 ····cinfo->progress->pass_counter = (long) cinfo->output_scanline;
989e0e ····cinfo->progress->pass_limit = (long) cinfo->output_height;
0424e5 ····(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
19df1c ··}
60af5a
26b42a ··/* Process some data */
88a0dd ··row_ctr = 0;
58efb3 ··(*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
654a1b ··cinfo->output_scanline += row_ctr;
a18853 ··return row_ctr;
69efe6 }
1caf5a
7eaf5a
2b38e5 /*
a2e6f8 ·* Alternate entry point to read raw data.
bc07f5 ·* Processes exactly one iMCU row per call, unless suspended.
8a495d ·*/
adaf5a
322e0d GLOBAL(JDIMENSION)
16fb33 jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
c3575a ¤   ¤   ····JDIMENSION max_lines)
0ebb36 {
a32af5 ··JDIMENSION lines_per_iMCU_row;
0baf5a
9bf8f1 ··if (cinfo->global_state != DSTATE_RAW_OK)
6c918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
e7bc61 ··if (cinfo->output_scanline >= cinfo->output_height) {
ee44d3 ····WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
2b958b ····return 0;
bcdf1c ··}
e3af5a
f52358 ··/* Call progress monitor hook if present */
a1feda ··if (cinfo->progress != NULL) {
208ab5 ····cinfo->progress->pass_counter = (long) cinfo->output_scanline;
4e9e0e ····cinfo->progress->pass_limit = (long) cinfo->output_height;
b824e5 ····(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
f3df1c ··}
aaaf5a
10f75f ··/* Verify that at least one iMCU row can be returned. */
4aa506 ··lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;
9e5d76 ··if (max_lines < lines_per_iMCU_row)
9c53f5 ····ERREXIT(cinfo, JERR_BUFFER_SIZE);
ccaf5a
dfb4f9 ··/* Decompress directly into user's buffer. */
de192c ··if (! (*cinfo->coef->decompress_data) (cinfo, data))
fa9d60 ····return 0;¤  ¤   ¤   /* suspension forced, can do nothing more */
0caf5a
1f03b6 ··/* OK, we processed one iMCU row. */
592443 ··cinfo->output_scanline += lines_per_iMCU_row;
70fe2f ··return lines_per_iMCU_row;
82efe6 }
--d61c 00168206cdc4010001d Page 4 of jdapistd.c
e0af5a
1aaf5a
f0bb3f /* Additional entry points for buffered-image mode. */
76af5a
99a01c #ifdef D_MULTISCAN_FILES_SUPPORTED
1daf5a
0e38e5 /*
cad29b ·* Initialize for an output pass in buffered-image mode.
20495d ·*/
25af5a
41e553 GLOBAL(boolean)
452d9c jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
cbbb36 {
46cbad ··if (cinfo->global_state != DSTATE_BUFIMAGE &&
842de3 ······cinfo->global_state != DSTATE_PRESCAN)
6b918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
12aa74 ··/* Limit scan number to valid range */
b21c98 ··if (scan_number <= 0)
045175 ····scan_number = 1;
3bac15 ··if (cinfo->inputctl->eoi_reached &&
1878c4 ······scan_number > cinfo->input_scan_number)
8db6e4 ····scan_number = cinfo->input_scan_number;
4dc6cb ··cinfo->output_scan_number = scan_number;
dd9a29 ··/* Perform any dummy output passes, and set up for the real pass */
229810 ··return output_pass_setup(cinfo);
d2efe6 }
3faf5a
48af5a
6838e5 /*
f1439c ·* Finish up after an output pass in buffered-image mode.
f0775e ·*
b86d35 ·* Returns FALSE if suspended. ·The return value need be inspected only if
bc6f4f ·* a suspending data source is used.
1a495d ·*/
d8af5a
e6e553 GLOBAL(boolean)
d962ea jpeg_finish_output (j_decompress_ptr cinfo)
43bb36 {
86a432 ··if ((cinfo->global_state == DSTATE_SCANNING ||
906c11 ·······cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
76f4df ····/* Terminate this pass. */
70a219 ····/* We do not require the whole pass to have been completed. */
cad139 ····(*cinfo->master->finish_output_pass) (cinfo);
edc6ea ····cinfo->global_state = DSTATE_BUFPOST;
ab7038 ··} else if (cinfo->global_state != DSTATE_BUFPOST) {
49c385 ····/* BUFPOST = repeat call after a suspension, anything else is error */
c4918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
0adf1c ··}
3dc96a ··/* Read markers looking for SOS or EOI */
6d86e3 ··while (cinfo->input_scan_number <= cinfo->output_scan_number &&
8a3bcb ¤   ·! cinfo->inputctl->eoi_reached) {
459b45 ····if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
40204a ······return FALSE;¤¤   /* Suspend, come back later */
63df1c ··}
fd5ab9 ··cinfo->global_state = DSTATE_BUFIMAGE;
30d2c8 ··return TRUE;
e5efe6 }
d8af5a
6844d7 #endif /* D_MULTISCAN_FILES_SUPPORTED */
--1560 0000cb908d24010001e Page 1 of jdatadst.c
bc38e5 /*
c1f5da ·* jdatadst.c
4c775e ·*
349e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
b9fb07 ·* This file is part of the Independent JPEG Group's software.
b3a0d6 ·* For conditions of distribution and use, see the accompanying README file.
a9775e ·*
fcdc54 ·* This file contains compression data destination routines for the case of
689b3f ·* emitting JPEG data to a file (or any stdio stream). ·While these routines
3d95d6 ·* are sufficient for most applications, some will want to use a different
4f306b ·* destination manager.
8ea13a ·* IMPORTANT: we assume that fwrite() will correctly transcribe an array of
450ae9 ·* JOCTETs into 8-bit-wide elements on external storage. ·If char is wider
2f7f8c ·* than 8 bits on your machine, you may need to do some tweaking.
22495d ·*/
9faf5a
869596 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
4436a7 #include "jinclude.h"
746c8f #include "jpeglib.h"
1b46a4 #include "jerror.h"
22af5a
cfaf5a
405f82 /* Expanded data destination object for stdio output */
6eaf5a
f9f0f7 typedef struct {
146a50 ··struct jpeg_destination_mgr pub; /* public fields */
fcaf5a
e591fd ··FILE * outfile;¤  ¤   /* target stream */
b68a51 ··JOCTET * buffer;¤ ¤   /* start of buffer */
f8614e } my_destination_mgr;
feaf5a
786b04 typedef my_destination_mgr * my_dest_ptr;
88af5a
987145 #define OUTPUT_BUF_SIZE ·4096¤  /* choose an efficiently fwrite'able size */
b0af5a
4eaf5a
3138e5 /*
bf7a5b ·* Initialize destination --- called by jpeg_start_compress
7c9930 ·* before any data is actually written.
52495d ·*/
37af5a
c00434 METHODDEF(void)
2f2c41 init_destination (j_compress_ptr cinfo)
c7bb36 {
3d6346 ··my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
9caf5a
9b3ecf ··/* Allocate the output buffer --- it will be released when done with image */
74f417 ··dest->buffer = (JOCTET *)
ff558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
db966c ¤   ¤   ¤   ¤   ··OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
58af5a
9a32b2 ··dest->pub.next_output_byte = dest->buffer;
655acd ··dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
78efe6 }
e5af5a
59af5a
0e38e5 /*
a9da6c ·* Empty the output buffer --- called whenever buffer fills up.
6d775e ·*
99e5fb ·* In typical applications, this should write the entire output buffer
089ca6 ·* (ignoring the current state of next_output_byte & free_in_buffer),
753488 ·* reset the pointer & count to the start of the buffer, and return TRUE
397bdb ·* indicating that the buffer has been dumped.
78775e ·*
50f45f ·* In applications that need to be able to suspend compression due to output
ebcdba ·* overrun, a FALSE return indicates that the buffer cannot be emptied now.
b20d36 ·* In this situation, the compressor will return to its caller (possibly with
e50a23 ·* an indication that it has not accepted all the supplied scanlines). ·The
5463a8 ·* application should resume compression after it has made more room in the
d57a2f ·* output buffer. ·Note that there are substantial restrictions on the use of
7f4930 ·* suspension --- see the documentation.
0c775e ·*
--59fb 000a2a98ac24010001e Page 2 of jdatadst.c
97a350 ·* When suspending, the compressor will back up to a convenient restart point
addd6e ·* (typically the start of the current MCU). next_output_byte & free_in_buffer
63a9e2 ·* indicate where the restart point will be if the current call returns FALSE.
6186fe ·* Data beyond this point will be regenerated after resumption, so do not
91f8b4 ·* write it out when emptying the buffer externally.
82495d ·*/
4eaf5a
9e9a8f METHODDEF(boolean)
235724 empty_output_buffer (j_compress_ptr cinfo)
95bb36 {
bf6346 ··my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
3caf5a
02d316 ··if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
9c8c78 ······(size_t) OUTPUT_BUF_SIZE)
a641c1 ····ERREXIT(cinfo, JERR_FILE_WRITE);
9aaf5a
0632b2 ··dest->pub.next_output_byte = dest->buffer;
b85acd ··dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
63af5a
76d2c8 ··return TRUE;
67efe6 }
4eaf5a
43af5a
2938e5 /*
7d3af2 ·* Terminate destination --- called by jpeg_finish_compress
569958 ·* after all data has been written. ·Usually needs to flush buffer.
49775e ·*
4bcc23 ·* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
9fef9e ·* application must deal with any cleanup that should happen even
b8d080 ·* for error exit.
db495d ·*/
37af5a
f00434 METHODDEF(void)
1ad84c term_destination (j_compress_ptr cinfo)
45bb36 {
de6346 ··my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
73318b ··size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
15af5a
21de4d ··/* Write any data remaining in the buffer */
c3c585 ··if (datacount > 0) {
d242bd ····if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
b3eac0 ······ERREXIT(cinfo, JERR_FILE_WRITE);
00df1c ··}
862c0a ··fflush(dest->outfile);
135af9 ··/* Make sure we wrote the output file OK */
248cc0 ··if (ferror(dest->outfile))
0841c1 ····ERREXIT(cinfo, JERR_FILE_WRITE);
ceefe6 }
3eaf5a
82af5a
6c38e5 /*
976915 ·* Prepare for output to a stdio stream.
bc35f0 ·* The caller must have already opened the stream, and is responsible
875777 ·* for closing it after finishing compression.
58495d ·*/
10af5a
adf898 GLOBAL(void)
0968ee jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
38bb36 {
69e3c0 ··my_dest_ptr dest;
e5af5a
caef08 ··/* The destination object is made permanent so that multiple JPEG images
3a12ed ···* can be written to the same file without re-executing jpeg_stdio_dest.
e4a480 ···* This makes it dangerous to use this manager and a different destination
4c1a6d ···* manager serially with the same JPEG object, because their private object
ae1696 ···* sizes may be different. ·Caveat programmer.
33f9a6 ···*/
0704ff ··if (cinfo->dest == NULL) {¤   /* first time for this JPEG object? */
8f1f54 ····cinfo->dest = (struct jpeg_destination_mgr *)
94d459 ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
0b91b3 ¤   ¤   ¤   ¤   ··SIZEOF(my_destination_mgr));
a2df1c ··}
--be1f 0015f1efab44010001e Page 3 of jdatadst.c
e0af5a
08baed ··dest = (my_dest_ptr) cinfo->dest;
484a73 ··dest->pub.init_destination = init_destination;
46dcd0 ··dest->pub.empty_output_buffer = empty_output_buffer;
3d85c8 ··dest->pub.term_destination = term_destination;
735c04 ··dest->outfile = outfile;
5fefe6 }
--26bc 000888c0d1d4010001f Page 1 of jdatasrc.c
bc38e5 /*
2f347f ·* jdatasrc.c
ea775e ·*
709e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
cbfb07 ·* This file is part of the Independent JPEG Group's software.
65a0d6 ·* For conditions of distribution and use, see the accompanying README file.
c6775e ·*
ba819a ·* This file contains decompression data source routines for the case of
cd3ef3 ·* reading JPEG data from a file (or any stdio stream). ·While these routines
6f95d6 ·* are sufficient for most applications, some will want to use a different
c21ca7 ·* source manager.
390c86 ·* IMPORTANT: we assume that fread() will correctly transcribe an array of
f6d4ce ·* JOCTETs from 8-bit-wide elements on external storage. ·If char is wider
047f8c ·* than 8 bits on your machine, you may need to do some tweaking.
10495d ·*/
dbaf5a
259596 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
6836a7 #include "jinclude.h"
7b6c8f #include "jpeglib.h"
da46a4 #include "jerror.h"
38af5a
a8af5a
43e6c3 /* Expanded data source object for stdio input */
49af5a
01f0f7 typedef struct {
5818f7 ··struct jpeg_source_mgr pub;¤  /* public fields */
e0af5a
346dbe ··FILE * infile;¤   ¤   /* source stream */
cb8a51 ··JOCTET * buffer;¤ ¤   /* start of buffer */
c47cf2 ··boolean start_of_file;¤   /* have we gotten any data yet? */
e75b58 } my_source_mgr;
b2af5a
33d7d7 typedef my_source_mgr * my_src_ptr;
63af5a
65c1f3 #define INPUT_BUF_SIZE ·4096¤   /* choose an efficiently fread'able size */
e0af5a
d9af5a
c838e5 /*
50439b ·* Initialize source --- called by jpeg_read_header
206beb ·* before any data is actually read.
12495d ·*/
3eaf5a
750434 METHODDEF(void)
90ebd9 init_source (j_decompress_ptr cinfo)
3ebb36 {
ac09e0 ··my_src_ptr src = (my_src_ptr) cinfo->src;
43af5a
9ed8da ··/* We reset the empty-input-file flag for each image,
711afc ···* but we don't clear the input buffer.
5e955b ···* This is correct behavior for reading a series of images from one source.
e3f9a6 ···*/
da53e5 ··src->start_of_file = TRUE;
4befe6 }
bbaf5a
0eaf5a
1238e5 /*
925973 ·* Fill the input buffer --- called whenever buffer is emptied.
ff775e ·*
439ca4 ·* In typical applications, this should read fresh data into the buffer
2862a9 ·* (ignoring the current state of next_input_byte & bytes_in_buffer),
fc3488 ·* reset the pointer & count to the start of the buffer, and return TRUE
151ea1 ·* indicating that the buffer has been reloaded. ·It is not necessary to
53af8f ·* fill the buffer entirely, only to obtain at least one more byte.
ae775e ·*
f652ee ·* There is no such thing as an EOF return. ·If the end of the file has been
d6227e ·* reached, the routine has a choice of ERREXIT() or inserting fake data into
fd8d61 ·* the buffer. ·In most cases, generating a warning message and inserting a
379c8a ·* fake EOI marker is the best course of action --- this will allow the
3fd593 ·* decompressor to output however much of the image is there. ·However,
13eb12 ·* the resulting error message is misleading if the real problem is an empty
d9878b ·* input file, so we handle that case specially.
88775e ·*
--92a1 0002e0c8b894010001f Page 2 of jdatasrc.c
2febef ·* In applications that need to be able to suspend compression due to input
67fffc ·* not being available yet, a FALSE return indicates that no more data can be
133816 ·* obtained right now, but more may be forthcoming later. ·In this situation,
b99c02 ·* the decompressor will return to its caller (with an indication of the
999cf5 ·* number of scanlines it has read, if any). ·The application should resume
8559cb ·* decompression after it has loaded more data into the input buffer. ·Note
591b7c ·* that there are substantial restrictions on the use of suspension --- see
33d4d1 ·* the documentation.
18775e ·*
97ae2d ·* When suspending, the decompressor will back up to a convenient restart point
42c840 ·* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
7ca9e2 ·* indicate where the restart point will be if the current call returns FALSE.
996b69 ·* Data beyond this point must be rescanned after resumption, so move it to
4fc791 ·* the front of the buffer rather than discarding it.
a3495d ·*/
adaf5a
649a8f METHODDEF(boolean)
726224 fill_input_buffer (j_decompress_ptr cinfo)
03bb36 {
5909e0 ··my_src_ptr src = (my_src_ptr) cinfo->src;
b5da58 ··size_t nbytes;
63af5a
c4760c ··nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
e9af5a
c6e4db ··if (nbytes <= 0) {
1f8c42 ····if (src->start_of_file)¤/* Treat empty input file as fatal error */
60252c ······ERREXIT(cinfo, JERR_INPUT_EMPTY);
279332 ····WARNMS(cinfo, JWRN_JPEG_EOF);
0e21f0 ····/* Insert a fake EOI marker */
9615cb ····src->buffer[0] = (JOCTET) 0xFF;
bd6018 ····src->buffer[1] = (JOCTET) JPEG_EOI;
ca3787 ····nbytes = 2;
dfdf1c ··}
7daf5a
484f27 ··src->pub.next_input_byte = src->buffer;
60a35e ··src->pub.bytes_in_buffer = nbytes;
7581b3 ··src->start_of_file = FALSE;
06af5a
1dd2c8 ··return TRUE;
1befe6 }
c2af5a
e2af5a
4c38e5 /*
c360ee ·* Skip data --- used to skip over a potentially large amount of
fd3f32 ·* uninteresting data (such as an APPn marker).
7f775e ·*
8d8ae8 ·* Writers of suspendable-input applications must note that skip_input_data
c7f5a5 ·* is not granted the right to give a suspension return. ·If the skip extends
a2daaf ·* beyond the data currently in the buffer, the buffer can be marked empty so
339b1e ·* that the next read will cause a fill_input_buffer call that can suspend.
58f8bc ·* Arranging for additional bytes to be discarded before reloading the input
fc6535 ·* buffer is the application writer's problem.
57495d ·*/
83af5a
df0434 METHODDEF(void)
c5b989 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
7dbb36 {
bf09e0 ··my_src_ptr src = (my_src_ptr) cinfo->src;
cdaf5a
a35039 ··/* Just a dumb implementation for now. ·Could use fseek() except
eebd41 ···* it doesn't work on pipes. ·Not clear that being smart is worth
b68ac5 ···* any trouble anyway --- large skips are infrequent.
7cf9a6 ···*/
ee7358 ··if (num_bytes > 0) {
e0845a ····while (num_bytes > (long) src->pub.bytes_in_buffer) {
349e6c ······num_bytes -= (long) src->pub.bytes_in_buffer;
3f5f0f ······(void) fill_input_buffer(cinfo);
875c8b ······/* note we assume that fill_input_buffer will never return FALSE,
6186fb ·······* so suspension need not be handled.
c8e9f1 ·······*/
3c6fe7 ····}
2e19c6 ····src->pub.next_input_byte += (size_t) num_bytes;
--fb47 001b4d05a6d4010001f Page 3 of jdatasrc.c
1cc2bb ····src->pub.bytes_in_buffer -= (size_t) num_bytes;
efdf1c ··}
52efe6 }
c6af5a
b2af5a
db38e5 /*
f0c8f3 ·* An additional method that can be provided by data source modules is the
d83709 ·* resync_to_restart method for error recovery in the presence of RST markers.
291d40 ·* For the moment, this source module just uses the default resync method
1e2bb8 ·* provided by the JPEG library. ·That method assumes that no backtracking
398502 ·* is possible.
18495d ·*/
71af5a
96af5a
d838e5 /*
ff1533 ·* Terminate source --- called by jpeg_finish_decompress
39fd78 ·* after all data has been read. ·Often a no-op.
f9775e ·*
80cc23 ·* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
b6ef9e ·* application must deal with any cleanup that should happen even
add080 ·* for error exit.
07495d ·*/
3aaf5a
7c0434 METHODDEF(void)
104e52 term_source (j_decompress_ptr cinfo)
b9bb36 {
e6e3c3 ··/* no work necessary here */
b9efe6 }
04af5a
feaf5a
c638e5 /*
17aa47 ·* Prepare for input from a stdio stream.
3135f0 ·* The caller must have already opened the stream, and is responsible
5f9927 ·* for closing it after finishing decompression.
52495d ·*/
78af5a
75f898 GLOBAL(void)
e2787f jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
31bb36 {
32be07 ··my_src_ptr src;
3faf5a
154517 ··/* The source object and input buffer are made permanent so that a series
932b82 ···* of JPEG images can be read from the same file by calling jpeg_stdio_src
8a2e56 ···* only before the first one. ·(If we discarded the buffer at the end of
4af785 ···* one image, we'd likely lose the start of the next one.)
c429e2 ···* This makes it unsafe to use this manager and a different source
a8d298 ···* manager serially with the same JPEG object. ·Caveat programmer.
1bf9a6 ···*/
eba9ab ··if (cinfo->src == NULL) {¤/* first time for this JPEG object? */
339d97 ····cinfo->src = (struct jpeg_source_mgr *)
73d459 ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
ed4614 ¤   ¤   ¤   ¤   ··SIZEOF(my_source_mgr));
c06996 ····src = (my_src_ptr) cinfo->src;
248f3d ····src->buffer = (JOCTET *)
d3d459 ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
550b8e ¤   ¤   ¤   ¤   ··INPUT_BUF_SIZE * SIZEOF(JOCTET));
ffdf1c ··}
c8af5a
0bddca ··src = (my_src_ptr) cinfo->src;
52774c ··src->pub.init_source = init_source;
4848fd ··src->pub.fill_input_buffer = fill_input_buffer;
1fdbc7 ··src->pub.skip_input_data = skip_input_data;
54085d ··src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
4ac790 ··src->pub.term_source = term_source;
3c0cee ··src->infile = infile;
c964f8 ··src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
5f95e5 ··src->pub.next_input_byte = NULL; /* until buffer loaded */
b4efe6 }
--2e8e 00034ad3b4c40100020 Page 1 of jdcoefct.c
bc38e5 /*
174154 ·* jdcoefct.c
76775e ·*
3e9e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
dcfb07 ·* This file is part of the Independent JPEG Group's software.
9da0d6 ·* For conditions of distribution and use, see the accompanying README file.
8d775e ·*
1e3da7 ·* This file contains the coefficient buffer controller for decompression.
d65a82 ·* This controller is the top level of the JPEG decompressor proper.
df02d2 ·* The coefficient buffer lies between entropy decoding and inverse-DCT steps.
cb775e ·*
21c5c6 ·* In buffered-image mode, this controller is the interface between
5db73d ·* input-oriented processing and output-oriented processing.
dc3ece ·* Also, the input side (only) is used when reading a file for transcoding.
fb495d ·*/
e5af5a
872bb6 #define JPEG_INTERNALS
f036a7 #include "jinclude.h"
9f6c8f #include "jpeglib.h"
dfaf5a
350632 /* Block smoothing is only applicable for progressive JPEG, so: */
5eac48 #ifndef D_PROGRESSIVE_SUPPORTED
228241 #undef BLOCK_SMOOTHING_SUPPORTED
e87454 #endif
0daf5a
2a8416 /* Private buffer controller object */
d8af5a
fff0f7 typedef struct {
1c08c0 ··struct jpeg_d_coef_controller pub; /* public fields */
d6af5a
12f6bb ··/* These variables keep track of the current location of the input side. */
aa1f95 ··/* cinfo->input_iMCU_row is also used for this. */
29270a ··JDIMENSION MCU_ctr;¤  ¤   /* counts MCUs processed in current row */
81c7f6 ··int MCU_vert_offset;¤ ¤   /* counts MCU rows within iMCU row */
6f0fac ··int MCU_rows_per_iMCU_row;¤   /* number of such rows needed */
16af5a
b1b169 ··/* The output side's location is represented by cinfo->output_iMCU_row. */
22af5a
fabe2a ··/* In single-pass modes, it's sufficient to buffer just one MCU.
7f7877 ···* We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
9c3a8f ···* and let the entropy decoder write into that workspace each time.
54299b ···* (On 80x86, the workspace is FAR even though it's not really very big;
0045e6 ···* this is to keep the module interfaces unchanged when a large coefficient
b7fb0f ···* buffer is necessary.)
bb4ae3 ···* In multi-pass modes, this array points to the current MCU's blocks
6ab48d ···* within the virtual arrays; it is used only by the input side.
74f9a6 ···*/
883b26 ··JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
38af5a
cba01c #ifdef D_MULTISCAN_FILES_SUPPORTED
51523e ··/* In multi-pass modes, we need a virtual block array for each component. */
9193fc ··jvirt_barray_ptr whole_image[MAX_COMPONENTS];
e47454 #endif
51af5a
9da36a #ifdef BLOCK_SMOOTHING_SUPPORTED
82584d ··/* When doing block smoothing, we latch coefficient Al values here */
0c95d5 ··int * coef_bits_latch;
94915c #define SAVED_COEFS ·6¤ ¤   /* we save coef_bits[0..5] */
937454 #endif
07c38c } my_coef_controller;
baaf5a
e2cf47 typedef my_coef_controller * my_coef_ptr;
91af5a
d06a43 /* Forward declarations */
71ea98 METHODDEF(int) decompress_onepass
e19f76 ¤   JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
6ea01c #ifdef D_MULTISCAN_FILES_SUPPORTED
8ed634 METHODDEF(int) decompress_data
a59f76 ¤   JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
e97454 #endif
5aa36a #ifdef BLOCK_SMOOTHING_SUPPORTED
342529 LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
--7cce 000f750bc5d40100020 Page 2 of jdcoefct.c
79031a METHODDEF(int) decompress_smooth_data
a09f76 ¤   JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
0a7454 #endif
c3af5a
a2af5a
4bafad LOCAL(void)
aac8b8 start_iMCU_row (j_decompress_ptr cinfo)
db3867 /* Reset within-iMCU-row counters for a new row (input side) */
b0bb36 {
937924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
21af5a
ee57ee ··/* In an interleaved scan, an MCU row is the same as an iMCU row.
d29ae6 ···* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
505867 ···* But at the bottom of the image, process only what's left.
dcf9a6 ···*/
f71aae ··if (cinfo->comps_in_scan > 1) {
6f33a9 ····coef->MCU_rows_per_iMCU_row = 1;
c349d8 ··} else {
6237e4 ····if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
7f1b09 ······coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
93842c ····else
92ced2 ······coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
7bdf1c ··}
a2af5a
9377b4 ··coef->MCU_ctr = 0;
cbf553 ··coef->MCU_vert_offset = 0;
98efe6 }
bbaf5a
c1af5a
0138e5 /*
7c2527 ·* Initialize for an input processing pass.
7f495d ·*/
e1af5a
f40434 METHODDEF(void)
fa1208 start_input_pass (j_decompress_ptr cinfo)
87bb36 {
c862cd ··cinfo->input_iMCU_row = 0;
873d6b ··start_iMCU_row(cinfo);
4defe6 }
e6af5a
49af5a
6138e5 /*
43e468 ·* Initialize for an output processing pass.
1b495d ·*/
d5af5a
120434 METHODDEF(void)
c01dae start_output_pass (j_decompress_ptr cinfo)
60bb36 {
faa36a #ifdef BLOCK_SMOOTHING_SUPPORTED
187924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
c2af5a
fed21a ··/* If multipass, check to see whether to use block smoothing on this pass */
59e31f ··if (coef->pub.coef_arrays != NULL) {
8985c7 ····if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
684950 ······coef->pub.decompress_data = decompress_smooth_data;
be842c ····else
077ac4 ······coef->pub.decompress_data = decompress_data;
0bdf1c ··}
1e7454 #endif
6e5605 ··cinfo->output_iMCU_row = 0;
1fefe6 }
f3af5a
b9af5a
ca38e5 /*
330d53 ·* Decompress and return some data in the single-pass case.
adc7e9 ·* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
b5f46d ·* Input and output must run in lockstep since we have only a one-MCU buffer.
dafb7b ·* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
f5775e ·*
bc122b ·* NB: output_buf contains a plane for each component in image.
d0ac4a ·* For single pass, this is the same as the components in the scan.
f7495d ·*/
--6f43 000ec9af87940100020 Page 3 of jdcoefct.c
e0af5a
bc4924 METHODDEF(int)
44648d decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
1abb36 {
607924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
592df3 ··JDIMENSION MCU_col_num;¤  /* index of current MCU within row */
44b9a6 ··JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
73e5c0 ··JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
5e24b8 ··int blkn, ci, xindex, yindex, yoffset, useful_width;
8565c2 ··JSAMPARRAY output_ptr;
a79e0b ··JDIMENSION start_col, output_col;
2d33b0 ··jpeg_component_info *compptr;
40f10e ··inverse_DCT_method_ptr inverse_DCT;
f6af5a
f2a1bf ··/* Loop to process as much as one whole iMCU row */
06a27a ··for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
77bd1b ·······yoffset++) {
053c51 ····for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
cc2288 ¤   ·MCU_col_num++) {
182975 ······/* Try to fetch an MCU. ·Entropy decoder expects buffer to be zeroed. */
9d2b88 ······jzero_far((void FAR *) coef->MCU_buffer[0],
4b0956 ¤   ¤   (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
60ae30 ······if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
373fee ¤   /* Suspension forced; update state counters and exit */
9debe8 ¤   coef->MCU_vert_offset = yoffset;
a901ec ¤   coef->MCU_ctr = MCU_col_num;
fa6030 ¤   return JPEG_SUSPENDED;
e042cc ······}
1aaa93 ······/* Determine where data should go in output_buf and do the IDCT thing.
9677d5 ·······* We skip dummy blocks at the right and bottom edges (but blkn gets
4ba104 ·······* incremented past them!). ·Note the inner loop relies on having
fe9a20 ·······* allocated the MCU_buffer[] blocks sequentially.
aee9f1 ·······*/
945fdc ······blkn = 0;¤¤   ¤   /* index of current DCT block within MCU */
886064 ······for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
1908f5 ¤   compptr = cinfo->cur_comp_info[ci];
c26b51 ¤   /* Don't bother to IDCT an uninteresting component. */
7a272c ¤   if (! compptr->component_needed) {
248413 ¤   ··blkn += compptr->MCU_blocks;
4dad2a ¤   ··continue;
bf9371 ¤   }
679a99 ¤   inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
782bf2 ¤   useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
00bccd ¤   ¤   ¤   ¤   ¤   ¤   ····: compptr->last_col_width;
817ff5 ¤   output_ptr = output_buf[ci] + yoffset * compptr->DCT_scaled_size;
142dd4 ¤   start_col = MCU_col_num * compptr->MCU_sample_width;
7676a3 ¤   for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
f0c2e2 ¤   ··if (cinfo->input_iMCU_row < last_iMCU_row ||
6c553a ¤   ······yoffset+yindex < compptr->last_row_height) {
01baa3 ¤   ····output_col = start_col;
f2193f ¤   ····for (xindex = 0; xindex < useful_width; xindex++) {
55d140 ¤   ······(*inverse_DCT) (cinfo, compptr,
f40ca2 ¤   ¤   ¤   ······(JCOEFPTR) coef->MCU_buffer[blkn+xindex],
7166a8 ¤   ¤   ¤   ······output_ptr, output_col);
071772 ¤   ······output_col += compptr->DCT_scaled_size;
99f372 ¤   ····}
9732a2 ¤   ··}
e4dec3 ¤   ··blkn += compptr->MCU_width;
6b0c04 ¤   ··output_ptr += compptr->DCT_scaled_size;
439371 ¤   }
f242cc ······}
a46fe7 ····}
26b67f ····/* Completed an MCU row, but perhaps not an iMCU row */
a074ee ····coef->MCU_ctr = 0;
5cdf1c ··}
3277d6 ··/* Completed the iMCU row, advance counters for next one */
b24077 ··cinfo->output_iMCU_row++;
ead2da ··if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
58dbb7 ····start_iMCU_row(cinfo);
ea7ac6 ····return JPEG_ROW_COMPLETED;
e1df1c ··}
ec82b4 ··/* Completed the scan */
--7cb0 0009cf9738440100020 Page 4 of jdcoefct.c
2e0d2a ··(*cinfo->inputctl->finish_input_pass) (cinfo);
5df8c6 ··return JPEG_SCAN_COMPLETED;
98efe6 }
05af5a
e0af5a
d538e5 /*
3f7c70 ·* Dummy consume-input routine for single-pass operation.
d3495d ·*/
b5af5a
4d4924 METHODDEF(int)
8bd48e dummy_consume_data (j_decompress_ptr cinfo)
b1bb36 {
2a2c6e ··return JPEG_SUSPENDED;¤   /* Always indicate nothing was done */
13efe6 }
51af5a
e4af5a
eaa01c #ifdef D_MULTISCAN_FILES_SUPPORTED
b9af5a
a538e5 /*
1a485c ·* Consume input data and store it in the full-image coefficient buffer.
302a38 ·* We read as much as one fully interleaved MCU row ("iMCU" row) per call,
e2eb6a ·* ie, v_samp_factor block rows for each component in the scan.
7afb7b ·* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
87495d ·*/
36af5a
d34924 METHODDEF(int)
5bd6a5 consume_data (j_decompress_ptr cinfo)
e4bb36 {
447924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
402df3 ··JDIMENSION MCU_col_num;¤  /* index of current MCU within row */
4e6ca8 ··int blkn, ci, xindex, yindex, yoffset;
0ef9ae ··JDIMENSION start_col;
8ea37f ··JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
9a065a ··JBLOCKROW buffer_ptr;
c533b0 ··jpeg_component_info *compptr;
6caf5a
12ffca ··/* Align the virtual buffers for the components used in this scan. */
d96aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
6ba7cc ····compptr = cinfo->cur_comp_info[ci];
a9917c ····buffer[ci] = (*cinfo->mem->access_virt_barray)
087fe4 ······((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
2de5fb ·······cinfo->input_iMCU_row * compptr->v_samp_factor,
94c9b7 ·······(JDIMENSION) compptr->v_samp_factor, TRUE);
1f4898 ····/* Note: entropy decoder expects buffer to be zeroed,
385f02 ·····* but this is handled automatically by the memory manager
d9af1f ·····* because we requested a pre-zeroed array.
98d48d ·····*/
d2df1c ··}
daaf5a
b12174 ··/* Loop to process one whole iMCU row */
f7a27a ··for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
ffbd1b ·······yoffset++) {
f3a4ae ····for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
6d2288 ¤   ·MCU_col_num++) {
d75139 ······/* Construct list of pointers to DCT blocks belonging to this MCU */
315fdc ······blkn = 0;¤¤   ¤   /* index of current DCT block within MCU */
296064 ······for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
9a08f5 ¤   compptr = cinfo->cur_comp_info[ci];
b88a61 ¤   start_col = MCU_col_num * compptr->MCU_width;
c976a3 ¤   for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
d601a1 ¤   ··buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
90c9d6 ¤   ··for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
c7c078 ¤   ····coef->MCU_buffer[blkn++] = buffer_ptr++;
e032a2 ¤   ··}
d19371 ¤   }
9142cc ······}
de6376 ······/* Try to fetch the MCU. */
71ae30 ······if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
b63fee ¤   /* Suspension forced; update state counters and exit */
5cebe8 ¤   coef->MCU_vert_offset = yoffset;
ae01ec ¤   coef->MCU_ctr = MCU_col_num;
9c6030 ¤   return JPEG_SUSPENDED;
--2d0e 00032b3f24440100020 Page 5 of jdcoefct.c
a642cc ······}
ad6fe7 ····}
fbb67f ····/* Completed an MCU row, but perhaps not an iMCU row */
3a74ee ····coef->MCU_ctr = 0;
6ddf1c ··}
8377d6 ··/* Completed the iMCU row, advance counters for next one */
28d2da ··if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
67dbb7 ····start_iMCU_row(cinfo);
db7ac6 ····return JPEG_ROW_COMPLETED;
cedf1c ··}
4982b4 ··/* Completed the scan */
2e0d2a ··(*cinfo->inputctl->finish_input_pass) (cinfo);
7af8c6 ··return JPEG_SCAN_COMPLETED;
67efe6 }
ddaf5a
2daf5a
4e38e5 /*
0dbea9 ·* Decompress and return some data in the multi-pass case.
13c7e9 ·* Always attempts to emit one fully interleaved MCU row ("iMCU" row).
e9fb7b ·* Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
04775e ·*
02122b ·* NB: output_buf contains a plane for each component in image.
5d495d ·*/
0faf5a
f24924 METHODDEF(int)
514254 decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
48bb36 {
e87924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
89e5c0 ··JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
91f289 ··JDIMENSION block_num;
4c4e8e ··int ci, block_row, block_rows;
c7602e ··JBLOCKARRAY buffer;
7e065a ··JBLOCKROW buffer_ptr;
c665c2 ··JSAMPARRAY output_ptr;
50e9ec ··JDIMENSION output_col;
fa33b0 ··jpeg_component_info *compptr;
7bf10e ··inverse_DCT_method_ptr inverse_DCT;
97af5a
9149a8 ··/* Force some input to be done if we are getting ahead of the input. */
3ce3b7 ··while (cinfo->input_scan_number < cinfo->output_scan_number ||
806777 ¤   ·(cinfo->input_scan_number == cinfo->output_scan_number &&
7c4945 ¤   ··cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
2d02c0 ····if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
f30cb2 ······return JPEG_SUSPENDED;
b4df1c ··}
a2af5a
66ce59 ··/* OK, output from the virtual arrays. */
05958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
7caa07 ·······ci++, compptr++) {
b9aad7 ····/* Don't bother to IDCT an uninteresting component. */
803311 ····if (! compptr->component_needed)
955f6a ······continue;
07ac66 ····/* Align the virtual buffer for this component. */
73e56b ····buffer = (*cinfo->mem->access_virt_barray)
d54d02 ······((j_common_ptr) cinfo, coef->whole_image[ci],
06a5b1 ·······cinfo->output_iMCU_row * compptr->v_samp_factor,
465a8b ·······(JDIMENSION) compptr->v_samp_factor, FALSE);
b72c22 ····/* Count non-dummy DCT block rows in this iMCU row. */
157f95 ····if (cinfo->output_iMCU_row < last_iMCU_row)
061d98 ······block_rows = compptr->v_samp_factor;
9f83c8 ····else {
37d2d3 ······/* NB: can't use last_row_height here; it is input-side-dependent! */
37ad33 ······block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
be837b ······if (block_rows == 0) block_rows = compptr->v_samp_factor;
ed6fe7 ····}
789cac ····inverse_DCT = cinfo->idct->inverse_DCT[ci];
5fbd4c ····output_ptr = output_buf[ci];
6a2a1b ····/* Loop over all DCT blocks to be processed. */
0a7bcb ····for (block_row = 0; block_row < block_rows; block_row++) {
1246ac ······buffer_ptr = buffer[block_row];
1630a4 ······output_col = 0;
320cd6 ······for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
--b156 000d12be3ef40100020 Page 6 of jdcoefct.c
4b4677 ¤   (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
9d3540 ¤   ¤   ¤   output_ptr, output_col);
f76407 ¤   buffer_ptr++;
209aff ¤   output_col += compptr->DCT_scaled_size;
bf42cc ······}
166e9f ······output_ptr += compptr->DCT_scaled_size;
d16fe7 ····}
84df1c ··}
24af5a
9461e5 ··if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
a87ac6 ····return JPEG_ROW_COMPLETED;
c0f8c6 ··return JPEG_SCAN_COMPLETED;
39efe6 }
deaf5a
d444d7 #endif /* D_MULTISCAN_FILES_SUPPORTED */
93af5a
8aaf5a
67a36a #ifdef BLOCK_SMOOTHING_SUPPORTED
61af5a
2e38e5 /*
b0cb85 ·* This code applies interblock smoothing as described by section K.8
907a00 ·* of the JPEG standard: the first 5 AC coefficients are estimated from
e016a2 ·* the DC values of a DCT block and its 8 neighboring blocks.
972ed3 ·* We apply smoothing only for progressive JPEG decoding, and only if
56eec8 ·* the coefficients it can estimate are not yet known to full precision.
4d495d ·*/
dfaf5a
48437d /* Natural-order array positions of the first 5 zigzag-order coefficients */
edcdb7 #define Q01_POS ·1
f27b75 #define Q10_POS ·8
15f6a4 #define Q20_POS ·16
c12f50 #define Q11_POS ·9
1b31d8 #define Q02_POS ·2
1faf5a
e738e5 /*
c795df ·* Determine whether block smoothing is applicable and safe.
e6fb62 ·* We also latch the current states of the coef_bits[] entries for the
09ef8c ·* AC coefficients; otherwise, if the input side of the decompressor
0647a2 ·* advances into a new scan, we might think the coefficients are known
6c8844 ·* more accurately than they really are.
75495d ·*/
bdaf5a
77c4bf LOCAL(boolean)
3394df smoothing_ok (j_decompress_ptr cinfo)
bfbb36 {
d97924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
ab4990 ··boolean smoothing_useful = FALSE;
67c442 ··int ci, coefi;
7833b0 ··jpeg_component_info *compptr;
b02fe1 ··JQUANT_TBL * qtable;
cf2928 ··int * coef_bits;
de95d5 ··int * coef_bits_latch;
78af5a
323a60 ··if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
3630cb ····return FALSE;
8eaf5a
0d4545 ··/* Allocate latch area if not already done */
8c1655 ··if (coef->coef_bits_latch == NULL)
7905dd ····coef->coef_bits_latch = (int *)
b6558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cfdec0 ¤   ¤   ¤   ¤   ··cinfo->num_components *
eaf61f ¤   ¤   ¤   ¤   ··(SAVED_COEFS * SIZEOF(int)));
d7507c ··coef_bits_latch = coef->coef_bits_latch;
35af5a
e2958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
91aa07 ·······ci++, compptr++) {
ee8219 ····/* All components' quantization values must already be latched. */
509f6b ····if ((qtable = compptr->quant_table) == NULL)
26c39d ······return FALSE;
7dcf0c ····/* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
a62b7b ····if (qtable->quantval[0] == 0 ||
d1def6 ¤   qtable->quantval[Q01_POS] == 0 ||
--748c 000e006be9740100020 Page 7 of jdcoefct.c
1118cc ¤   qtable->quantval[Q10_POS] == 0 ||
bd82ed ¤   qtable->quantval[Q20_POS] == 0 ||
2650e6 ¤   qtable->quantval[Q11_POS] == 0 ||
e04eb8 ¤   qtable->quantval[Q02_POS] == 0)
aec39d ······return FALSE;
a048c6 ····/* DC values must be at least partly known for all components. */
6f7d6a ····coef_bits = cinfo->coef_bits[ci];
e234c2 ····if (coef_bits[0] < 0)
03c39d ······return FALSE;
df1813 ····/* Block smoothing is helpful if some AC coefficients remain inaccurate. */
2dff18 ····for (coefi = 1; coefi <= 5; coefi++) {
601100 ······coef_bits_latch[coefi] = coef_bits[coefi];
d9d65f ······if (coef_bits[coefi] != 0)
233d55 ¤   smoothing_useful = TRUE;
7d6fe7 ····}
12eab4 ····coef_bits_latch += SAVED_COEFS;
72df1c ··}
54af5a
41462c ··return smoothing_useful;
ffefe6 }
65af5a
12af5a
2438e5 /*
7783fa ·* Variant of decompress_data for use when doing block smoothing.
71495d ·*/
d7af5a
7f4924 METHODDEF(int)
828c6e decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
93bb36 {
8b7924 ··my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
cde5c0 ··JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
dc092f ··JDIMENSION block_num, last_block_column;
4e19ae ··int ci, block_row, block_rows, access_rows;
95602e ··JBLOCKARRAY buffer;
4645c0 ··JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
1465c2 ··JSAMPARRAY output_ptr;
77e9ec ··JDIMENSION output_col;
a133b0 ··jpeg_component_info *compptr;
45f10e ··inverse_DCT_method_ptr inverse_DCT;
c08afb ··boolean first_row, last_row;
094fe5 ··JBLOCK workspace;
6ea056 ··int *coef_bits;
275f63 ··JQUANT_TBL *quanttbl;
6edef7 ··INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
0e8a1b ··int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
a52b07 ··int Al, pred;
09af5a
c849a8 ··/* Force some input to be done if we are getting ahead of the input. */
f886e3 ··while (cinfo->input_scan_number <= cinfo->output_scan_number &&
cc3bcb ¤   ·! cinfo->inputctl->eoi_reached) {
f466cb ····if (cinfo->input_scan_number == cinfo->output_scan_number) {
6091e1 ······/* If input is working on current scan, we ordinarily want it to
0ec456 ·······* have completed the current row. ·But if input scan is DC,
0a8290 ·······* we want it to keep one row ahead so that next block row's DC
18a45a ·······* values are up to date.
14e9f1 ·······*/
8b196a ······JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
eab996 ······if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
054ed2 ¤   break;
bc6fe7 ····}
9e02c0 ····if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
1b0cb2 ······return JPEG_SUSPENDED;
6fdf1c ··}
b6af5a
cbce59 ··/* OK, output from the virtual arrays. */
43958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
24aa07 ·······ci++, compptr++) {
86aad7 ····/* Don't bother to IDCT an uninteresting component. */
923311 ····if (! compptr->component_needed)
e75f6a ······continue;
502c22 ····/* Count non-dummy DCT block rows in this iMCU row. */
e027e2 ····if (cinfo->output_iMCU_row < last_iMCU_row) {
--1df2 0003871bd6840100020 Page 8 of jdcoefct.c
901d98 ······block_rows = compptr->v_samp_factor;
e36c67 ······access_rows = block_rows * 2; /* this and next iMCU row */
3c727a ······last_row = FALSE;
d66a79 ····} else {
67d2d3 ······/* NB: can't use last_row_height here; it is input-side-dependent! */
b8ad33 ······block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
c4837b ······if (block_rows == 0) block_rows = compptr->v_samp_factor;
fc2dc5 ······access_rows = block_rows; /* this iMCU row only */
d13551 ······last_row = TRUE;
8e6fe7 ····}
3bac66 ····/* Align the virtual buffer for this component. */
3a88db ····if (cinfo->output_iMCU_row > 0) {
c34baa ······access_rows += compptr->v_samp_factor; /* prior iMCU row too */
83536f ······buffer = (*cinfo->mem->access_virt_barray)
8ddef2 ¤   ((j_common_ptr) cinfo, coef->whole_image[ci],
e8ca42 ¤   ·(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
7e2a52 ¤   ·(JDIMENSION) access_rows, FALSE);
6f24f3 ······buffer += compptr->v_samp_factor;¤/* point to current iMCU row */
d75edf ······first_row = FALSE;
726a79 ····} else {
44536f ······buffer = (*cinfo->mem->access_virt_barray)
a3def2 ¤   ((j_common_ptr) cinfo, coef->whole_image[ci],
3b577e ¤   ·(JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
edfaac ······first_row = TRUE;
016fe7 ····}
8490f0 ····/* Fetch component-dependent info */
48e558 ····coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
aa3ac2 ····quanttbl = compptr->quant_table;
fe8e7c ····Q00 = quanttbl->quantval[0];
c4ac0d ····Q01 = quanttbl->quantval[Q01_POS];
0f71f1 ····Q10 = quanttbl->quantval[Q10_POS];
b15591 ····Q20 = quanttbl->quantval[Q20_POS];
eeb02d ····Q11 = quanttbl->quantval[Q11_POS];
6ce678 ····Q02 = quanttbl->quantval[Q02_POS];
989cac ····inverse_DCT = cinfo->idct->inverse_DCT[ci];
a1bd4c ····output_ptr = output_buf[ci];
d32a1b ····/* Loop over all DCT blocks to be processed. */
707bcb ····for (block_row = 0; block_row < block_rows; block_row++) {
c946ac ······buffer_ptr = buffer[block_row];
bbf45f ······if (first_row && block_row == 0)
83b407 ¤   prev_block_row = buffer_ptr;
b43dfa ······else
b44648 ¤   prev_block_row = buffer[block_row-1];
6655b1 ······if (last_row && block_row == block_rows-1)
595cb8 ¤   next_block_row = buffer_ptr;
683dfa ······else
0e12dd ¤   next_block_row = buffer[block_row+1];
f01fa3 ······/* We fetch the surrounding DC values using a sliding-register approach.
8ce6dc ·······* Initialize all nine here so as to do the right thing on narrow pics.
2be9f1 ·······*/
24aef4 ······DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
183462 ······DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
0eb83e ······DC7 = DC8 = DC9 = (int) next_block_row[0][0];
9a30a4 ······output_col = 0;
7208d9 ······last_block_column = compptr->width_in_blocks - 1;
e38208 ······for (block_num = 0; block_num <= last_block_column; block_num++) {
b70f1c ¤   /* Fetch current DCT block into workspace so we can modify it. */
f73a8b ¤   jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
42c49b ¤   /* Update DC values */
8af0fb ¤   if (block_num < last_block_column) {
f65beb ¤   ··DC3 = (int) prev_block_row[1][0];
5645b9 ¤   ··DC6 = (int) buffer_ptr[1][0];
397714 ¤   ··DC9 = (int) next_block_row[1][0];
4e9371 ¤   }
bf9c17 ¤   /* Compute coefficient estimates per K.8.
d3d7b5 ¤   ·* An estimate is applied only if coefficient is still zero,
ff6dff ¤   ·* and is not known to be fully accurate.
d2a4e3 ¤   ·*/
819647 ¤   /* AC01 */
ea22d7 ¤   if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
81741d ¤   ··num = 36 * Q00 * (DC4 - DC6);
384034 ¤   ··if (num >= 0) {
--3b8a 000df57580a40100020 Page 9 of jdcoefct.c
6194e2 ¤   ····pred = (int) (((Q01<<7) + num) / (Q01<<8));
795763 ¤   ····if (Al > 0 && pred >= (1<<Al))
27c352 ¤   ······pred = (1<<Al)-1;
e72862 ¤   ··} else {
da4734 ¤   ····pred = (int) (((Q01<<7) - num) / (Q01<<8));
6d5763 ¤   ····if (Al > 0 && pred >= (1<<Al))
f4c352 ¤   ······pred = (1<<Al)-1;
5defc2 ¤   ····pred = -pred;
1232a2 ¤   ··}
ba65a5 ¤   ··workspace[1] = (JCOEF) pred;
429371 ¤   }
5c9928 ¤   /* AC10 */
020b49 ¤   if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
c7328d ¤   ··num = 36 * Q00 * (DC2 - DC8);
5f4034 ¤   ··if (num >= 0) {
bfc7b8 ¤   ····pred = (int) (((Q10<<7) + num) / (Q10<<8));
fa5763 ¤   ····if (Al > 0 && pred >= (1<<Al))
8bc352 ¤   ······pred = (1<<Al)-1;
7e2862 ¤   ··} else {
08146e ¤   ····pred = (int) (((Q10<<7) - num) / (Q10<<8));
b95763 ¤   ····if (Al > 0 && pred >= (1<<Al))
e3c352 ¤   ······pred = (1<<Al)-1;
10efc2 ¤   ····pred = -pred;
1b32a2 ¤   ··}
254ce0 ¤   ··workspace[8] = (JCOEF) pred;
d39371 ¤   }
b09555 ¤   /* AC20 */
496d06 ¤   if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
c367c7 ¤   ··num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
fd4034 ¤   ··if (num >= 0) {
b0e767 ¤   ····pred = (int) (((Q20<<7) + num) / (Q20<<8));
e15763 ¤   ····if (Al > 0 && pred >= (1<<Al))
3fc352 ¤   ······pred = (1<<Al)-1;
412862 ¤   ··} else {
db34b1 ¤   ····pred = (int) (((Q20<<7) - num) / (Q20<<8));
c25763 ¤   ····if (Al > 0 && pred >= (1<<Al))
39c352 ¤   ······pred = (1<<Al)-1;
09efc2 ¤   ····pred = -pred;
7432a2 ¤   ··}
6c593c ¤   ··workspace[16] = (JCOEF) pred;
c19371 ¤   }
c7926c ¤   /* AC11 */
05d783 ¤   if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
81f3e6 ¤   ··num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
a14034 ¤   ··if (num >= 0) {
2e8b57 ¤   ····pred = (int) (((Q11<<7) + num) / (Q11<<8));
bc5763 ¤   ····if (Al > 0 && pred >= (1<<Al))
5ac352 ¤   ······pred = (1<<Al)-1;
232862 ¤   ··} else {
295881 ¤   ····pred = (int) (((Q11<<7) - num) / (Q11<<8));
525763 ¤   ····if (Al > 0 && pred >= (1<<Al))
e4c352 ¤   ······pred = (1<<Al)-1;
a2efc2 ¤   ····pred = -pred;
7632a2 ¤   ··}
b2dfa9 ¤   ··workspace[9] = (JCOEF) pred;
109371 ¤   }
068b8b ¤   /* AC02 */
a8d5f9 ¤   if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
4e6896 ¤   ··num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
564034 ¤   ··if (num >= 0) {
0141d3 ¤   ····pred = (int) (((Q02<<7) + num) / (Q02<<8));
d15763 ¤   ····if (Al > 0 && pred >= (1<<Al))
00c352 ¤   ······pred = (1<<Al)-1;
8d2862 ¤   ··} else {
ba9205 ¤   ····pred = (int) (((Q02<<7) - num) / (Q02<<8));
a55763 ¤   ····if (Al > 0 && pred >= (1<<Al))
fbc352 ¤   ······pred = (1<<Al)-1;
54efc2 ¤   ····pred = -pred;
7432a2 ¤   ··}
9cd86f ¤   ··workspace[2] = (JCOEF) pred;
979371 ¤   }
dfcadd ¤   /* OK, do the IDCT */
--a44f 000482b01ee40100020 Page 10 of jdcoefct.c
35d4db ¤   (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
d13540 ¤   ¤   ¤   output_ptr, output_col);
c2b1a8 ¤   /* Advance for next column */
67d39b ¤   DC1 = DC2; DC2 = DC3;
7ac97e ¤   DC4 = DC5; DC5 = DC6;
0285b0 ¤   DC7 = DC8; DC8 = DC9;
50fe7d ¤   buffer_ptr++, prev_block_row++, next_block_row++;
729aff ¤   output_col += compptr->DCT_scaled_size;
cf42cc ······}
696e9f ······output_ptr += compptr->DCT_scaled_size;
bb6fe7 ····}
a2df1c ··}
5daf5a
8361e5 ··if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
767ac6 ····return JPEG_ROW_COMPLETED;
d1f8c6 ··return JPEG_SCAN_COMPLETED;
faefe6 }
a2af5a
c65760 #endif /* BLOCK_SMOOTHING_SUPPORTED */
11af5a
66af5a
d438e5 /*
a37e1c ·* Initialize coefficient buffer controller.
ee495d ·*/
75af5a
aaf898 GLOBAL(void)
c5ef70 jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
64bb36 {
18b982 ··my_coef_ptr coef;
8baf5a
df70bd ··coef = (my_coef_ptr)
263f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
1289b6 ¤   ¤   ¤   ¤   SIZEOF(my_coef_controller));
132956 ··cinfo->coef = (struct jpeg_d_coef_controller *) coef;
8cefdc ··coef->pub.start_input_pass = start_input_pass;
125009 ··coef->pub.start_output_pass = start_output_pass;
2da36a #ifdef BLOCK_SMOOTHING_SUPPORTED
578582 ··coef->coef_bits_latch = NULL;
9e7454 #endif
77af5a
8b34c3 ··/* Create the coefficient buffer. */
63baf2 ··if (need_full_buffer) {
e0a01c #ifdef D_MULTISCAN_FILES_SUPPORTED
6d71db ····/* Allocate a full-image virtual array for each component, */
be1c01 ····/* padded to a multiple of samp_factor DCT blocks in each direction. */
faa4e3 ····/* Note we ask for a pre-zeroed array. */
2dbd37 ····int ci, access_rows;
77ec11 ····jpeg_component_info *compptr;
9eaf5a
e06090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
aab5ed ¤   ·ci++, compptr++) {
1d8b5c ······access_rows = compptr->v_samp_factor;
a8a36a #ifdef BLOCK_SMOOTHING_SUPPORTED
cb893e ······/* If block smoothing could be used, need a bigger window */
a2cfdc ······if (cinfo->progressive_mode)
07312d ¤   access_rows *= 3;
257454 #endif
3f06f9 ······coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
c2a230 ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
e67183 ¤   ·(JDIMENSION) jround_up((long) compptr->width_in_blocks,
18a6ca ¤   ¤   ¤   ¤   (long) compptr->h_samp_factor),
da954d ¤   ·(JDIMENSION) jround_up((long) compptr->height_in_blocks,
566bd5 ¤   ¤   ¤   ¤   (long) compptr->v_samp_factor),
6d45c5 ¤   ·(JDIMENSION) access_rows);
d76fe7 ····}
3ac97e ····coef->pub.consume_data = consume_data;
c8cd19 ····coef->pub.decompress_data = decompress_data;
1a4ba6 ····coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
d8db21 #else
729214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
797454 #endif
4849d8 ··} else {
--f8a1 0010524f42d40100020 Page 11 of jdcoefct.c
53e24f ····/* We only need a single-MCU buffer. */
b00091 ····JBLOCKROW buffer;
35ae36 ····int i;
3eaf5a
e58be0 ····buffer = (JBLOCKROW)
f93ff1 ······(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
8fba1a ¤   ¤   ¤   ¤   ··D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
d0f95a ····for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
dbf509 ······coef->MCU_buffer[i] = buffer + i;
436fe7 ····}
c788b5 ····coef->pub.consume_data = dummy_consume_data;
401fa1 ····coef->pub.decompress_data = decompress_onepass;
35ac7c ····coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
17df1c ··}
05efe6 }
--b700 0006d872bf740100021 Page 1 of jdcolor.c
bc38e5 /*
d71b34 ·* jdcolor.c
97775e ·*
f7a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
8bfb07 ·* This file is part of the Independent JPEG Group's software.
bea0d6 ·* For conditions of distribution and use, see the accompanying README file.
b1775e ·*
6dc2e0 ·* This file contains output colorspace conversion routines.
6f495d ·*/
94af5a
502bb6 #define JPEG_INTERNALS
b036a7 #include "jinclude.h"
8f6c8f #include "jpeglib.h"
fcaf5a
b5af5a
9cdedc /* Private subobject */
7baf5a
e9f0f7 typedef struct {
c7c0aa ··struct jpeg_color_deconverter pub; /* public fields */
59af5a
7f7b7b ··/* Private state for YCC->RGB conversion */
4dec41 ··int * Cr_r_tab;¤  ¤   /* => table for Cr to R conversion */
b65e06 ··int * Cb_b_tab;¤  ¤   /* => table for Cb to B conversion */
9fdd7c ··INT32 * Cr_g_tab;¤¤   /* => table for Cr to G conversion */
cde84f ··INT32 * Cb_g_tab;¤¤   /* => table for Cb to G conversion */
1e00a4 } my_color_deconverter;
9faf5a
58f90f typedef my_color_deconverter * my_cconvert_ptr;
7caf5a
b5af5a
6fd78e /**************** YCbCr -> RGB conversion: most common case **************/
53af5a
df38e5 /*
e4e7db ·* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
f6d404 ·* normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
4be056 ·* The conversion equations to be implemented are therefore
dacf7b ·*¤ R = Y ···············+ 1.40200 * Cr
849f5c ·*¤ G = Y - 0.34414 * Cb - 0.71414 * Cr
2bd0c3 ·*¤ B = Y + 1.77200 * Cb
65ee4b ·* where Cb and Cr represent the incoming values less CENTERJSAMPLE.
9fbc70 ·* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
df775e ·*
1e24a1 ·* To avoid floating-point arithmetic, we represent the fractional constants
b284de ·* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
f84355 ·* the products by 2^16, with appropriate rounding, to get the correct answer.
fcac91 ·* Notice that Y, being an integral input, does not contribute any fraction
95d09b ·* so it need not participate in the rounding.
41775e ·*
d3ec9d ·* For even more speed, we avoid doing any multiplications in the inner loop
9166d2 ·* by precalculating the constants times Cb and Cr for all possible values.
12cc69 ·* For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
3413e8 ·* for 12-bit samples it is still acceptable. ·It's not very reasonable for
6e3cee ·* 16-bit samples, but if you want lossless storage you shouldn't be changing
50248f ·* colorspace anyway.
90e0d4 ·* The Cr=>R and Cb=>B values can be rounded to integers in advance; the
ae7ba1 ·* values for the G calculation are left scaled up, since we must add them
cad171 ·* together before rounding.
89495d ·*/
31af5a
fd81d9 #define SCALEBITS¤  16¤ /* speediest right-shift on some machines */
695746 #define ONE_HALF¤   ((INT32) 1 << (SCALEBITS-1))
9339c8 #define FIX(x)¤ ¤   ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
e1af5a
40af5a
df38e5 /*
5bf2a9 ·* Initialize tables for YCC->RGB colorspace conversion.
dc495d ·*/
9eaf5a
3eafad LOCAL(void)
da0e32 build_ycc_rgb_table (j_decompress_ptr cinfo)
ffbb36 {
6d83d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
--e1a5 000812177fe40100021 Page 2 of jdcolor.c
eb17e0 ··int i;
ef182a ··INT32 x;
4bea99 ··SHIFT_TEMPS
81af5a
34518b ··cconvert->Cr_r_tab = (int *)
243f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
ea5b78 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(int));
8b068c ··cconvert->Cb_b_tab = (int *)
fe3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
b35b78 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(int));
c9fd61 ··cconvert->Cr_g_tab = (INT32 *)
103f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
d683d2 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(INT32));
7260dc ··cconvert->Cb_g_tab = (INT32 *)
383f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
9e83d2 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(INT32));
33af5a
f3cc39 ··for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
6a8598 ····/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
afc9a9 ····/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
af65e4 ····/* Cr=>R value is nearest int to 1.40200 * x */
067095 ····cconvert->Cr_r_tab[i] = (int)
5f54fc ¤   ¤   ····RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
f0089a ····/* Cb=>B value is nearest int to 1.77200 * x */
f6047d ····cconvert->Cb_b_tab[i] = (int)
1cfeb5 ¤   ¤   ····RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
c42392 ····/* Cr=>G value is scaled-up -0.71414 * x */
d05eee ····cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
1b56a5 ····/* Cb=>G value is scaled-up -0.34414 * x */
a07c96 ····/* We also add in ONE_HALF so that need not do it in inner loop */
f4b3b4 ····cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
b8df1c ··}
48efe6 }
20af5a
21af5a
2838e5 /*
cc039a ·* Convert some rows of samples to the output colorspace.
9d775e ·*
89fb57 ·* Note that we change from noninterleaved, one-plane-per-component format
8e562e ·* to interleaved-pixel format. ·The output buffer is therefore three times
b7fc41 ·* as wide as the input buffer.
d11125 ·* A starting row offset is provided only for the input buffer. ·The caller
39bfcf ·* can easily adjust the passed output_buf value to accommodate any row
ce4504 ·* offset required on that side.
2d495d ·*/
f7af5a
470434 METHODDEF(void)
42862e ycc_rgb_convert (j_decompress_ptr cinfo,
44604f ¤   ¤   ·JSAMPIMAGE input_buf, JDIMENSION input_row,
31754f ¤   ¤   ·JSAMPARRAY output_buf, int num_rows)
48bb36 {
cf83d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
5b36e4 ··register int y, cb, cr;
c4af23 ··register JSAMPROW outptr;
6e9580 ··register JSAMPROW inptr0, inptr1, inptr2;
632043 ··register JDIMENSION col;
ef500e ··JDIMENSION num_cols = cinfo->output_width;
3ef430 ··/* copy these pointers into registers if possible */
82ba42 ··register JSAMPLE * range_limit = cinfo->sample_range_limit;
1fea76 ··register int * Crrtab = cconvert->Cr_r_tab;
3d2dd2 ··register int * Cbbtab = cconvert->Cb_b_tab;
c9b86a ··register INT32 * Crgtab = cconvert->Cr_g_tab;
8cc6d2 ··register INT32 * Cbgtab = cconvert->Cb_g_tab;
e4ea99 ··SHIFT_TEMPS
45af5a
4ed9ef ··while (--num_rows >= 0) {
e22386 ····inptr0 = input_buf[0][input_row];
c8929d ····inptr1 = input_buf[1][input_row];
9749a1 ····inptr2 = input_buf[2][input_row];
c8ea34 ····input_row++;
6cfcc3 ····outptr = *output_buf++;
817a19 ····for (col = 0; col < num_cols; col++) {
--f373 0005035e24940100021 Page 3 of jdcolor.c
68499f ······y ·= GETJSAMPLE(inptr0[col]);
dfca93 ······cb = GETJSAMPLE(inptr1[col]);
07f77b ······cr = GETJSAMPLE(inptr2[col]);
54d7c9 ······/* Range-limiting is essential due to noise introduced by DCT losses. */
00c09b ······outptr[RGB_RED] = ··range_limit[y + Crrtab[cr]];
357302 ······outptr[RGB_GREEN] = range_limit[y +
d878d1 ¤   ¤   ¤   ······((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
53aa68 ¤   ¤   ¤   ¤   ¤   ¤   ·SCALEBITS))];
0af956 ······outptr[RGB_BLUE] = ·range_limit[y + Cbbtab[cb]];
eba9e0 ······outptr += RGB_PIXELSIZE;
076fe7 ····}
9edf1c ··}
94efe6 }
0daf5a
e6af5a
af240c /**************** Cases other than YCbCr -> RGB **************/
93af5a
98af5a
af38e5 /*
da021e ·* Color conversion for no colorspace change: just copy the data,
596b66 ·* converting from separate-planes to interleaved representation.
f6495d ·*/
0aaf5a
dd0434 METHODDEF(void)
556c66 null_convert (j_decompress_ptr cinfo,
cee6e4 ¤   ······JSAMPIMAGE input_buf, JDIMENSION input_row,
f8eb35 ¤   ······JSAMPARRAY output_buf, int num_rows)
6cbb36 {
0543b7 ··register JSAMPROW inptr, outptr;
097efa ··register JDIMENSION count;
2205d6 ··register int num_components = cinfo->num_components;
b8500e ··JDIMENSION num_cols = cinfo->output_width;
8a0dcc ··int ci;
1faf5a
67d9ef ··while (--num_rows >= 0) {
7a78e4 ····for (ci = 0; ci < num_components; ci++) {
1f65e4 ······inptr = input_buf[ci][input_row];
dcd21c ······outptr = output_buf[0] + ci;
b1c546 ······for (count = num_cols; count > 0; count--) {
621d6c ¤   *outptr = *inptr++;¤/* needn't bother with GETJSAMPLE() here */
366a24 ¤   outptr += num_components;
3842cc ······}
146fe7 ····}
d9ea34 ····input_row++;
8c6ed9 ····output_buf++;
50df1c ··}
acefe6 }
15af5a
c8af5a
2438e5 /*
d30075 ·* Color conversion for grayscale: just copy the data.
8f7335 ·* This also works for YCbCr -> grayscale conversion, in which
db9f72 ·* we just copy the Y (luminance) component and ignore chrominance.
19495d ·*/
33af5a
b30434 METHODDEF(void)
6e0fef grayscale_convert (j_decompress_ptr cinfo,
2abaff ¤   ¤   ···JSAMPIMAGE input_buf, JDIMENSION input_row,
f8f170 ¤   ¤   ···JSAMPARRAY output_buf, int num_rows)
fdbb36 {
420022 ··jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
48aa2a ¤   ¤   ····num_rows, cinfo->output_width);
a8efe6 }
afaf5a
09af5a
3a38e5 /*
76d844 ·* Adobe-style YCCK->CMYK conversion.
1f7a24 ·* We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
76a068 ·* conversion as above, while passing K (black) unchanged.
00c39f ·* We assume build_ycc_rgb_table has been called.
30495d ·*/
50af5a
--e388 0006ffb58de40100021 Page 4 of jdcolor.c
580434 METHODDEF(void)
7973fa ycck_cmyk_convert (j_decompress_ptr cinfo,
38baff ¤   ¤   ···JSAMPIMAGE input_buf, JDIMENSION input_row,
7bf170 ¤   ¤   ···JSAMPARRAY output_buf, int num_rows)
f7bb36 {
4883d4 ··my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
3336e4 ··register int y, cb, cr;
69af23 ··register JSAMPROW outptr;
7f5ad6 ··register JSAMPROW inptr0, inptr1, inptr2, inptr3;
6c2043 ··register JDIMENSION col;
f5500e ··JDIMENSION num_cols = cinfo->output_width;
fef430 ··/* copy these pointers into registers if possible */
24ba42 ··register JSAMPLE * range_limit = cinfo->sample_range_limit;
7cea76 ··register int * Crrtab = cconvert->Cr_r_tab;
522dd2 ··register int * Cbbtab = cconvert->Cb_b_tab;
c5b86a ··register INT32 * Crgtab = cconvert->Cr_g_tab;
a0c6d2 ··register INT32 * Cbgtab = cconvert->Cb_g_tab;
fdea99 ··SHIFT_TEMPS
a6af5a
9bd9ef ··while (--num_rows >= 0) {
342386 ····inptr0 = input_buf[0][input_row];
70929d ····inptr1 = input_buf[1][input_row];
e649a1 ····inptr2 = input_buf[2][input_row];
99f8ba ····inptr3 = input_buf[3][input_row];
7eea34 ····input_row++;
b3fcc3 ····outptr = *output_buf++;
6b7a19 ····for (col = 0; col < num_cols; col++) {
32499f ······y ·= GETJSAMPLE(inptr0[col]);
52ca93 ······cb = GETJSAMPLE(inptr1[col]);
b6f77b ······cr = GETJSAMPLE(inptr2[col]);
ccd7c9 ······/* Range-limiting is essential due to noise introduced by DCT losses. */
e33dd4 ······outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];¤  /* red */
47d6bf ······outptr[1] = range_limit[MAXJSAMPLE - (y +¤¤   ¤   /* green */
cd78d1 ¤   ¤   ¤   ······((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
5814f9 ¤   ¤   ¤   ¤   ¤   ¤   ·SCALEBITS)))];
7b4daf ······outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];¤  /* blue */
12f7a5 ······/* K passes through unchanged */
bfc139 ······outptr[3] = inptr3[col];¤ /* don't need GETJSAMPLE here */
7a8db3 ······outptr += 4;
de6fe7 ····}
b3df1c ··}
83efe6 }
c0af5a
67af5a
5938e5 /*
31997b ·* Empty method for start_pass.
1f495d ·*/
4eaf5a
460434 METHODDEF(void)
83a45a start_pass_dcolor (j_decompress_ptr cinfo)
b4bb36 {
451b6b ··/* no work needed */
4fefe6 }
8eaf5a
c4af5a
af38e5 /*
ae4d1c ·* Module initialization routine for output colorspace conversion.
c1495d ·*/
31af5a
04f898 GLOBAL(void)
e0cb29 jinit_color_deconverter (j_decompress_ptr cinfo)
12bb36 {
5e9184 ··my_cconvert_ptr cconvert;
1b0dcc ··int ci;
57af5a
c5e959 ··cconvert = (my_cconvert_ptr)
433f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
31c3b2 ¤   ¤   ¤   ¤   SIZEOF(my_color_deconverter));
9fefb9 ··cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
839a10 ··cconvert->pub.start_pass = start_pass_dcolor;
1daf5a
6f1d41 ··/* Make sure num_components agrees with jpeg_color_space */
--d1f1 000b849869640100021 Page 5 of jdcolor.c
2c8e60 ··switch (cinfo->jpeg_color_space) {
22b88c ··case JCS_GRAYSCALE:
5526f8 ····if (cinfo->num_components != 1)
62ccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
35ab40 ····break;
b2af5a
5db3fb ··case JCS_RGB:
2918bb ··case JCS_YCbCr:
269340 ····if (cinfo->num_components != 3)
19ccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
92ab40 ····break;
b9af5a
ef8394 ··case JCS_CMYK:
73969d ··case JCS_YCCK:
e41f45 ····if (cinfo->num_components != 4)
a5ccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
48ab40 ····break;
ebaf5a
505002 ··default:¤ ¤   ¤   /* JCS_UNKNOWN can be anything */
e0d5c6 ····if (cinfo->num_components < 1)
3bccfa ······ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
f1ab40 ····break;
addf1c ··}
65af5a
3dc44f ··/* Set out_color_components and conversion method based on requested space.
8b56e0 ···* Also clear the component_needed flags for any unused components,
6afc5b ···* so that earlier pipeline stages can avoid useless computation.
a6f9a6 ···*/
88af5a
87a765 ··switch (cinfo->out_color_space) {
24b88c ··case JCS_GRAYSCALE:
c11dbf ····cinfo->out_color_components = 1;
5e784f ····if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
2fe23a ¤   cinfo->jpeg_color_space == JCS_YCbCr) {
cbc418 ······cconvert->pub.color_convert = grayscale_convert;
d20ce3 ······/* For color->grayscale conversion, only the Y (0) component is needed */
b4382f ······for (ci = 1; ci < cinfo->num_components; ci++)
44b423 ¤   cinfo->comp_info[ci].component_needed = FALSE;
2ece75 ····} else
e9b463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
d0ab40 ····break;
08af5a
08b3fb ··case JCS_RGB:
8025b7 ····cinfo->out_color_components = RGB_PIXELSIZE;
ea4e43 ····if (cinfo->jpeg_color_space == JCS_YCbCr) {
0321e9 ······cconvert->pub.color_convert = ycc_rgb_convert;
20a631 ······build_ycc_rgb_table(cinfo);
0f74cb ····} else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
eaff2e ······cconvert->pub.color_convert = null_convert;
e2ce75 ····} else
0ab463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
d9ab40 ····break;
d6af5a
3f8394 ··case JCS_CMYK:
412402 ····cinfo->out_color_components = 4;
b120a1 ····if (cinfo->jpeg_color_space == JCS_YCCK) {
ac39bf ······cconvert->pub.color_convert = ycck_cmyk_convert;
08a631 ······build_ycc_rgb_table(cinfo);
fbc407 ····} else if (cinfo->jpeg_color_space == JCS_CMYK) {
b2ff2e ······cconvert->pub.color_convert = null_convert;
69ce75 ····} else
6fb463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
84ab40 ····break;
f8af5a
96969d ··default:
54dc9d ····/* Permit null conversion to same output space */
b135e4 ····if (cinfo->out_color_space == cinfo->jpeg_color_space) {
c36de9 ······cinfo->out_color_components = cinfo->num_components;
bdff2e ······cconvert->pub.color_convert = null_convert;
b46c2a ····} else¤ ¤   ¤   /* unsupported non-null conversion */
0ab463 ······ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
b8ab40 ····break;
--c10d 0014a55c65540100021 Page 6 of jdcolor.c
3adf1c ··}
64af5a
a5c248 ··if (cinfo->quantize_colors)
8c7320 ····cinfo->output_components = 1; /* single colormapped output component */
f41bd0 ··else
0646da ····cinfo->output_components = cinfo->out_color_components;
4aefe6 }
--d345 00023478bef40100022 Page 1 of jdct.h
bc38e5 /*
ffe4eb ·* jdct.h
3f775e ·*
aa9e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
c1fb07 ·* This file is part of the Independent JPEG Group's software.
85a0d6 ·* For conditions of distribution and use, see the accompanying README file.
f9775e ·*
92dff6 ·* This include file contains common declarations for the forward and
e7d9e9 ·* inverse DCT modules. ·These declarations are private to the DCT managers
4dbde7 ·* (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
a45dd9 ·* The individual DCT algorithms are kept in separate files to ease·
81fc3e ·* machine-dependent tuning (e.g., assembly coding).
06495d ·*/
7eaf5a
90af5a
7538e5 /*
3c5a38 ·* A forward DCT routine is given a pointer to a work area of type DCTELEM[];
77b29d ·* the DCT is to be performed in-place in that buffer. ·Type DCTELEM is int
650fba ·* for 8-bit samples, INT32 for 12-bit samples. ·(NOTE: Floating-point DCT
231a63 ·* implementations use an array of type FAST_FLOAT, instead.)
aa5025 ·* The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
a6549c ·* The DCT outputs are returned scaled up by a factor of 8; they therefore
39155b ·* have a range of +-8K for 8-bit data, +-128K for 12-bit data. ·This
327e86 ·* convention improves accuracy in integer implementations and saves some
15cb2a ·* work in floating-point ones.
ff3482 ·* Quantization of the output coefficients is done by jcdctmgr.c.
ce495d ·*/
34af5a
246f80 #if BITS_IN_JSAMPLE == 8
852473 typedef int DCTELEM;¤   ¤   /* 16 or 32 bits is fine */
e5db21 #else
78be27 typedef INT32 DCTELEM;¤ ¤   /* must have 32 bits */
b17454 #endif
9eaf5a
63c3eb typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
b4fff5 typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
e3af5a
bfaf5a
4238e5 /*
a2b01b ·* An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
f525c5 ·* to an output sample array. ·The routine must dequantize the input data as
003ad3 ·* well as perform the IDCT; for dequantization, it uses the multiplier table
554a42 ·* pointed to by compptr->dct_table. ·The output data is to be placed into the
c97aa8 ·* sample array starting at a specified column. ·(Any row offset needed will
be718a ·* be applied to the array pointer before it is passed to the IDCT code.)
20dc46 ·* Note that the number of samples emitted by the IDCT routine is
5c3a0d ·* DCT_scaled_size * DCT_scaled_size.
7b495d ·*/
e6af5a
170862 /* typedef inverse_DCT_method_ptr is declared in jpegint.h */
bbaf5a
f038e5 /*
53de5d ·* Each IDCT routine has its own ideas about the best dct_table element type.
72495d ·*/
45af5a
3052de typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
466f80 #if BITS_IN_JSAMPLE == 8
22f9a6 typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
d6c814 #define IFAST_SCALE_BITS ·2¤/* fractional bits in scale factors */
dbdb21 #else
4679d9 typedef INT32 IFAST_MULT_TYPE;¤ /* need 32 bits for scaled quantizers */
327945 #define IFAST_SCALE_BITS ·13¤   /* fractional bits in scale factors */
7e7454 #endif
d6487b typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
0eaf5a
46af5a
8238e5 /*
be3c99 ·* Each IDCT routine is responsible for range-limiting its results and
15115a ·* converting them to unsigned form (0..MAXJSAMPLE). ·The raw outputs could
b013f9 ·* be quite far out of range if the input data is corrupt, so a bulletproof
2df17f ·* range-limiting step is required. ·We use a mask-and-table-lookup method
236a55 ·* to do the combined operations quickly. ·See the comments with
--98c6 000b2acdcd440100022 Page 2 of jdct.h
127ad3 ·* prepare_range_limit_table (in jdmaster.c) for more info.
be495d ·*/
37af5a
d494e9 #define IDCT_range_limit(cinfo) ·((cinfo)->sample_range_limit + CENTERJSAMPLE)
4faf5a
57d919 #define RANGE_MASK ·(MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
34af5a
c0af5a
614b22 /* Short forms of external names for systems with brain-damaged linkers. */
b7af5a
8fddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
08b83e #define jpeg_fdct_islow¤¤   jFDislow
698f27 #define jpeg_fdct_ifast¤¤   jFDifast
6369da #define jpeg_fdct_float¤¤   jFDfloat
3eb757 #define jpeg_idct_islow¤¤   jRDislow
d7804e #define jpeg_idct_ifast¤¤   jRDifast
4666b3 #define jpeg_idct_float¤¤   jRDfloat
ece0c9 #define jpeg_idct_4x4¤  ¤   jRD4x4
65274c #define jpeg_idct_2x2¤  ¤   jRD2x2
5fc086 #define jpeg_idct_1x1¤  ¤   jRD1x1
9a5892 #endif /* NEED_SHORT_EXTERNAL_NAMES */
7aaf5a
0ef5ae /* Extern declarations for the forward and inverse DCT routines. */
e0af5a
d77875 EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
da48c3 EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
530ab7 EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
2aaf5a
7e10bb EXTERN(void) jpeg_idct_islow
9815ac ····JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
74ed3d ¤   ·JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
53037e EXTERN(void) jpeg_idct_ifast
5f15ac ····JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
69ed3d ¤   ·JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
70ec30 EXTERN(void) jpeg_idct_float
3d15ac ····JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
c5ed3d ¤   ·JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
6d9f5f EXTERN(void) jpeg_idct_4x4
3015ac ····JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
f0ed3d ¤   ·JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
928015 EXTERN(void) jpeg_idct_2x2
5c15ac ····JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
14ed3d ¤   ·JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
1e8fb0 EXTERN(void) jpeg_idct_1x1
a715ac ····JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
e5ed3d ¤   ·JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
2faf5a
dcaf5a
f538e5 /*
e1beb2 ·* Macros for handling fixed-point arithmetic; these are used by many
b347cb ·* but not all of the DCT/IDCT modules.
f3775e ·*
da31bb ·* All values are expected to be of type INT32.
d4b3f0 ·* Fractional constants are scaled left by CONST_BITS bits.
1c0aff ·* CONST_BITS is defined within each module using these macros,
12f65a ·* and may differ from one module to the next.
e2495d ·*/
f4af5a
ee9b31 #define ONE¤((INT32) 1)
c85778 #define CONST_SCALE (ONE << CONST_BITS)
79af5a
9f8853 /* Convert a positive real constant to an integer scaled by CONST_SCALE.
2586df ·* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
a28a43 ·* thus causing a lot of useless floating-point operations at run time.
8c495d ·*/
0aaf5a
3a5b27 #define FIX(x)¤ ((INT32) ((x) * CONST_SCALE + 0.5))
0baf5a
96d875 /* Descale and correctly round an INT32 value that's scaled by N bits.
3bd333 ·* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
f86175 ·* the fudge factor is correct for either sign of X.
b2495d ·*/
--cbd5 001ac6d07a440100022 Page 3 of jdct.h
e0af5a
8a3328 #define DESCALE(x,n) ·RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
32af5a
dc0109 /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
e1dd0c ·* This macro is used only when the two inputs will actually be no more than
33ca4a ·* 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
6a5c98 ·* full 32x32 multiply. ·This provides a useful speedup on many machines.
337100 ·* Unfortunately there is no way to specify a 16x16->32 multiply portably
f6f3c9 ·* in C, but some C compilers will do the right thing if you provide the
187b32 ·* correct combination of casts.
dd495d ·*/
62af5a
5af653 #ifdef SHORTxSHORT_32¤  ¤   /* may work if 'int' is 32 bits */
2df069 #define MULTIPLY16C16(var,const) ·(((INT16) (var)) * ((INT16) (const)))
bb7454 #endif
4a4957 #ifdef SHORTxLCONST_32¤ ¤   /* known to work with Microsoft C 6.0 */
401b09 #define MULTIPLY16C16(var,const) ·(((INT16) (var)) * ((INT32) (const)))
d87454 #endif
5aaf5a
564687 #ifndef MULTIPLY16C16¤  ¤   /* default definition */
beefb9 #define MULTIPLY16C16(var,const) ·((var) * (const))
517454 #endif
18af5a
ac392e /* Same except both inputs are variables. */
beaf5a
f1f653 #ifdef SHORTxSHORT_32¤  ¤   /* may work if 'int' is 32 bits */
bee54e #define MULTIPLY16V16(var1,var2) ·(((INT16) (var1)) * ((INT16) (var2)))
047454 #endif
c6af5a
74acca #ifndef MULTIPLY16V16¤  ¤   /* default definition */
d503b6 #define MULTIPLY16V16(var1,var2) ·((var1) * (var2))
ac7454 #endif
--2ae5 00008bb362e40100023 Page 1 of jddctmgr.c
bc38e5 /*
5ff267 ·* jddctmgr.c
a5775e ·*
589e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
d6fb07 ·* This file is part of the Independent JPEG Group's software.
4ea0d6 ·* For conditions of distribution and use, see the accompanying README file.
f2775e ·*
ad2286 ·* This file contains the inverse-DCT management logic.
e654ce ·* This code selects a particular IDCT implementation to be used,
1c2286 ·* and it performs related housekeeping chores. ·No code in this file
e619f3 ·* is executed per IDCT step, only during output pass setup.
82775e ·*
358009 ·* Note that the IDCT routines are responsible for performing coefficient
df7bfd ·* dequantization as well as the IDCT proper. ·This module sets up the
ec6894 ·* dequantization multiplier table needed by the IDCT routine.
3a495d ·*/
feaf5a
192bb6 #define JPEG_INTERNALS
6d36a7 #include "jinclude.h"
df6c8f #include "jpeglib.h"
e2ef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
b7af5a
5baf5a
1b38e5 /*
61e2ee ·* The decompressor input side (jdinput.c) saves away the appropriate
3ff8ef ·* quantization table for each component at the start of the first scan
7cf94b ·* involving that component. ·(This is necessary in order to correctly
980bd3 ·* decode files that reuse Q-table slots.)
d64ee3 ·* When we are ready to make an output pass, the saved Q-table is converted
2aedaf ·* to a multiplier table that will actually be used by the IDCT routine.
d8f648 ·* The multiplier table contents are IDCT-method-dependent. ·To support
e76c59 ·* application changes in IDCT method between scans, we can remake the
bdbc3b ·* multiplier tables if necessary.
dbc458 ·* In buffered-image mode, the first output pass may occur before any data
43e6a0 ·* has been seen for some components, and thus before their Q-tables have
91cdc7 ·* been saved away. ·To handle this case, multiplier tables are preset
f5b719 ·* to zeroes; the result of the IDCT will be a neutral gray level.
3d495d ·*/
20af5a
f8af5a
0b65b9 /* Private subobject for this module */
0eaf5a
e9f0f7 typedef struct {
f6b41b ··struct jpeg_inverse_dct pub;¤ /* public fields */
b3af5a
b4bb0c ··/* This array contains the IDCT method code that each multiplier table
1256fb ···* is currently set up for, or -1 if it's not yet set up.
c89fd1 ···* The actual multiplier tables are pointed to by dct_table in the
57aeb5 ···* per-component comp_info structures.
92f9a6 ···*/
e0220d ··int cur_method[MAX_COMPONENTS];
ab3ae1 } my_idct_controller;
8aaf5a
1f2e88 typedef my_idct_controller * my_idct_ptr;
4baf5a
25af5a
cc8b2d /* Allocated multiplier tables: big enough for any supported variant */
bcaf5a
10a883 typedef union {
b24993 ··ISLOW_MULT_TYPE islow_array[DCTSIZE2];
f8fcf3 #ifdef DCT_IFAST_SUPPORTED
7d7aeb ··IFAST_MULT_TYPE ifast_array[DCTSIZE2];
847454 #endif
1d6fd6 #ifdef DCT_FLOAT_SUPPORTED
618170 ··FLOAT_MULT_TYPE float_array[DCTSIZE2];
117454 #endif
bc58ee } multiplier_table;
39af5a
98af5a
28e64d /* The current scaled-IDCT routines require ISLOW-style multiplier tables,
b46900 ·* so be sure to compile that code if either ISLOW or SCALING is requested.
08495d ·*/
--372a 000f7fc95fb40100023 Page 2 of jddctmgr.c
42ba56 #ifdef DCT_ISLOW_SUPPORTED
0c2d89 #define PROVIDE_ISLOW_TABLES
c9db21 #else
1325de #ifdef IDCT_SCALING_SUPPORTED
082d89 #define PROVIDE_ISLOW_TABLES
217454 #endif
5f7454 #endif
23af5a
7aaf5a
eb38e5 /*
89f2bd ·* Prepare for an output pass.
be492f ·* Here we select the proper IDCT routine for each component and build
a4f2fd ·* a matching multiplier table.
02495d ·*/
5eaf5a
bd0434 METHODDEF(void)
4ee260 start_pass (j_decompress_ptr cinfo)
fabb36 {
2cbec4 ··my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
b6ac23 ··int ci, i;
c733b0 ··jpeg_component_info *compptr;
8152cf ··int method = 0;
f7b748 ··inverse_DCT_method_ptr method_ptr = NULL;
4a4504 ··JQUANT_TBL * qtbl;
64af5a
72958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
c0aa07 ·······ci++, compptr++) {
cb1596 ····/* Select the proper IDCT routine for this component's scaling */
b924d8 ····switch (compptr->DCT_scaled_size) {
1125de #ifdef IDCT_SCALING_SUPPORTED
e215cd ····case 1:
fa8813 ······method_ptr = jpeg_idct_1x1;
b5cb6a ······method = JDCT_ISLOW;¤ /* jidctred uses islow-style table */
3788e1 ······break;
a0faa9 ····case 2:
0d7abb ······method_ptr = jpeg_idct_2x2;
43cb6a ······method = JDCT_ISLOW;¤ /* jidctred uses islow-style table */
8988e1 ······break;
e72c70 ····case 4:
3c97fa ······method_ptr = jpeg_idct_4x4;
5fcb6a ······method = JDCT_ISLOW;¤ /* jidctred uses islow-style table */
7288e1 ······break;
4c7454 #endif
5be25b ····case DCTSIZE:
5d08b8 ······switch (cinfo->dct_method) {
32ba56 #ifdef DCT_ISLOW_SUPPORTED
139d75 ······case JDCT_ISLOW:
451d47 ¤   method_ptr = jpeg_idct_islow;
c62466 ¤   method = JDCT_ISLOW;
dc4ed2 ¤   break;
827454 #endif
edfcf3 #ifdef DCT_IFAST_SUPPORTED
2b0cc7 ······case JDCT_IFAST:
f28cf5 ¤   method_ptr = jpeg_idct_ifast;
e0b5d4 ¤   method = JDCT_IFAST;
df4ed2 ¤   break;
ad7454 #endif
f76fd6 #ifdef DCT_FLOAT_SUPPORTED
70a752 ······case JDCT_FLOAT:
ea2760 ¤   method_ptr = jpeg_idct_float;
131e41 ¤   method = JDCT_FLOAT;
b24ed2 ¤   break;
eb7454 #endif
e81082 ······default:
24f11e ¤   ERREXIT(cinfo, JERR_NOT_COMPILED);
484ed2 ¤   break;
4e42cc ······}
fb88e1 ······break;
59b53c ····default:
66bd35 ······ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size);
c788e1 ······break;
f76fe7 ····}
--32ae 0000f15b2f540100023 Page 3 of jddctmgr.c
9e2a85 ····idct->pub.inverse_DCT[ci] = method_ptr;
9001bd ····/* Create multiplier table from quant table.
707dd1 ·····* However, we can skip this if the component is uninteresting
b727b8 ·····* or if we already built the table. ·Also, if no quant table
35c829 ·····* has yet been saved for the component, we leave the
0a379f ·····* multiplier table all-zero; we'll be reading zeroes from the
760cf2 ·····* coefficient controller's buffer anyway.
c3d48d ·····*/
5a9d55 ····if (! compptr->component_needed || idct->cur_method[ci] == method)
715f6a ······continue;
84c76e ····qtbl = compptr->quant_table;
51383a ····if (qtbl == NULL)¤  ¤   /* happens if no data yet for component */
ba5f6a ······continue;
9a57e2 ····idct->cur_method[ci] = method;
6de828 ····switch (method) {
45df76 #ifdef PROVIDE_ISLOW_TABLES
b99e2f ····case JDCT_ISLOW:
cb161c ······{
7858a5 ¤   /* For LL&M IDCT method, multipliers are equal to raw quantization
595632 ¤   ·* coefficients, but are stored as ints to ensure access efficiency.
32a4e3 ¤   ·*/
40f567 ¤   ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
569a0b ¤   for (i = 0; i < DCTSIZE2; i++) {
33cff3 ¤   ··ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
8b9371 ¤   }
6642cc ······}
0b88e1 ······break;
1f7454 #endif
bafcf3 #ifdef DCT_IFAST_SUPPORTED
700f9d ····case JDCT_IFAST:
4e161c ······{
5014ce ¤   /* For AA&N IDCT method, multipliers are equal to quantization
d992c8 ¤   ·* coefficients scaled by scalefactor[row]*scalefactor[col], where
2bcf29 ¤   ·* ··scalefactor[0] = 1
31dda5 ¤   ·* ··scalefactor[k] = cos(k*PI/16) * sqrt(2) ···for k=1..7
3ae5a8 ¤   ·* For integer operation, the multiplier table is to be scaled by
3cb877 ¤   ·* IFAST_SCALE_BITS.
57a4e3 ¤   ·*/
0e7269 ¤   IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
a0552e #define CONST_BITS 14
7722fc ¤   static const INT16 aanscales[DCTSIZE2] = {
1cb896 ¤   ··/* precomputed values scaled up by 14 bits */
4807a8 ¤   ··16384, 22725, 21407, 19266, 16384, 12873, ·8867, ·4520,
f6eec6 ¤   ··22725, 31521, 29692, 26722, 22725, 17855, 12299, ·6270,
a00ef0 ¤   ··21407, 29692, 27969, 25172, 21407, 16819, 11585, ·5906,
567192 ¤   ··19266, 26722, 25172, 22654, 19266, 15137, 10426, ·5315,
f507a8 ¤   ··16384, 22725, 21407, 19266, 16384, 12873, ·8867, ·4520,
2378e8 ¤   ··12873, 17855, 16819, 15137, 12873, 10114, ·6967, ·3552,
955553 ¤   ···8867, 12299, 11585, 10426, ·8867, ·6967, ·4799, ·2446,
a80703 ¤   ···4520, ·6270, ·5906, ·5315, ·4520, ·3552, ·2446, ·1247
4e62bd ¤   };
ea4489 ¤   SHIFT_TEMPS
eeaf5a
2c9a0b ¤   for (i = 0; i < DCTSIZE2; i++) {
f57aeb ¤   ··ifmtbl[i] = (IFAST_MULT_TYPE)
40b758 ¤   ····DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
215c94 ¤   ¤   ¤   ¤   ··(INT32) aanscales[i]),
1040c5 ¤   ¤   ····CONST_BITS-IFAST_SCALE_BITS);
709371 ¤   }
1642cc ······}
e588e1 ······break;
fd7454 #endif
0d6fd6 #ifdef DCT_FLOAT_SUPPORTED
54a408 ····case JDCT_FLOAT:
39161c ······{
f059e0 ¤   /* For float AA&N IDCT method, multipliers are equal to quantization
7692c8 ¤   ·* coefficients scaled by scalefactor[row]*scalefactor[col], where
9dcf29 ¤   ·* ··scalefactor[0] = 1
dcdda5 ¤   ·* ··scalefactor[k] = cos(k*PI/16) * sqrt(2) ···for k=1..7
90a4e3 ¤   ·*/
ff2290 ¤   FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
0fe31d ¤   int row, col;
--b359 001dbd3232840100023 Page 4 of jddctmgr.c
cf2a63 ¤   static const double aanscalefactor[DCTSIZE] = {
4cf7b4 ¤   ··1.0, 1.387039845, 1.306562965, 1.175875602,
940c4a ¤   ··1.0, 0.785694958, 0.541196100, 0.275899379
7162bd ¤   };
21af5a
39ff6c ¤   i = 0;
13c87a ¤   for (row = 0; row < DCTSIZE; row++) {
db8482 ¤   ··for (col = 0; col < DCTSIZE; col++) {
62743f ¤   ····fmtbl[i] = (FLOAT_MULT_TYPE)
036a09 ¤   ······((double) qtbl->quantval[i] *
32b36f ¤   ·······aanscalefactor[row] * aanscalefactor[col]);
c1be75 ¤   ····i++;
8532a2 ¤   ··}
f49371 ¤   }
b042cc ······}
a888e1 ······break;
757454 #endif
c6b53c ····default:
869015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
2188e1 ······break;
2a6fe7 ····}
19df1c ··}
3aefe6 }
0faf5a
1daf5a
ec38e5 /*
7fa438 ·* Initialize IDCT manager.
45495d ·*/
c9af5a
29f898 GLOBAL(void)
370db8 jinit_inverse_dct (j_decompress_ptr cinfo)
6bbb36 {
dc0b21 ··my_idct_ptr idct;
5d0dcc ··int ci;
9e33b0 ··jpeg_component_info *compptr;
bdaf5a
507595 ··idct = (my_idct_ptr)
fd3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
b336d5 ¤   ¤   ¤   ¤   SIZEOF(my_idct_controller));
b32c72 ··cinfo->idct = (struct jpeg_inverse_dct *) idct;
942548 ··idct->pub.start_pass = start_pass;
0caf5a
28958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
afaa07 ·······ci++, compptr++) {
cb118d ····/* Allocate and pre-zero a multiplier table for each component */
0e95fb ····compptr->dct_table =
94558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
2dcc63 ¤   ¤   ¤   ¤   ··SIZEOF(multiplier_table));
502123 ····MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
dce3fa ····/* Mark multiplier table not yet set up for any method */
b55515 ····idct->cur_method[ci] = -1;
37df1c ··}
dbefe6 }
--875d 0000817fa1540100024 Page 1 of jdhuff.c
bc38e5 /*
386bcf ·* jdhuff.c
91775e ·*
b0a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
fefb07 ·* This file is part of the Independent JPEG Group's software.
dda0d6 ·* For conditions of distribution and use, see the accompanying README file.
31775e ·*
59d07e ·* This file contains Huffman entropy decoding routines.
0d775e ·*
2f0784 ·* Much of the complexity here has to do with supporting input suspension.
515cb0 ·* If the data source module demands suspension, we want to be able to back
5af537 ·* up to the start of the current MCU. ·To do this, we copy state variables
741028 ·* into local working storage, and update them back to the permanent
678e4d ·* storage only upon successful completion of an MCU.
e2495d ·*/
6daf5a
202bb6 #define JPEG_INTERNALS
5f36a7 #include "jinclude.h"
a96c8f #include "jpeglib.h"
1f7002 #include "jdhuff.h"¤¤   /* Declarations shared with jdphuff.c */
deaf5a
c7af5a
da38e5 /*
fe5d1a ·* Expanded entropy decoder object for Huffman decoding.
3b775e ·*
6a8e84 ·* The savable_state subrecord contains fields that change within an MCU,
1aea98 ·* but must not be updated permanently until we complete the MCU.
5c495d ·*/
7caf5a
cbf0f7 typedef struct {
866041 ··int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
809eb2 } savable_state;
30af5a
a9f232 /* This macro is to work around compilers with missing or broken
d01491 ·* structure assignment. ·You'll need to fix this code if you have
b69eb0 ·* such a compiler and you change MAX_COMPS_IN_SCAN.
cd495d ·*/
b1af5a
bc7994 #ifndef NO_STRUCT_ASSIGN
42a795 #define ASSIGN_STATE(dest,src) ·((dest) = (src))
bddb21 #else
51ca2d #if MAX_COMPS_IN_SCAN == 4
84679e #define ASSIGN_STATE(dest,src) ·\
1287e2 ¤   ((dest).last_dc_val[0] = (src).last_dc_val[0], \
7a2eac ¤   ·(dest).last_dc_val[1] = (src).last_dc_val[1], \
c02193 ¤   ·(dest).last_dc_val[2] = (src).last_dc_val[2], \
f3358a ¤   ·(dest).last_dc_val[3] = (src).last_dc_val[3])
107454 #endif
817454 #endif
beaf5a
aaaf5a
2ef0f7 typedef struct {
d2e00e ··struct jpeg_entropy_decoder pub; /* public fields */
a2af5a
6c12fc ··/* These fields are loaded into local variables at start of each MCU.
88a8c3 ···* In case of suspension, we exit WITHOUT updating them.
b6f9a6 ···*/
24beb9 ··bitread_perm_state bitstate;¤ /* Bit buffer at start of MCU */
314b28 ··savable_state saved;¤ ¤   /* Other state at start of MCU */
dcaf5a
dbf17f ··/* These fields are NOT loaded into local working state. */
708e4c ··unsigned int restarts_to_go;¤ /* MCUs left in this restart interval */
c1af5a
a7e6a8 ··/* Pointers to derived tables (these workspaces have image lifespan) */
55612b ··d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
aec3d0 ··d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
4675c6 } huff_entropy_decoder;
3daf5a
6dfc57 typedef huff_entropy_decoder * huff_entropy_ptr;
67af5a
05af5a
0838e5 /*
--19ec 000fcc01acc40100024 Page 2 of jdhuff.c
233637 ·* Initialize for a Huffman-compressed scan.
59495d ·*/
97af5a
8f0434 METHODDEF(void)
5a74d8 start_pass_huff_decoder (j_decompress_ptr cinfo)
8fbb36 {
8e2609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
8b0d5c ··int ci, dctbl, actbl;
81bcae ··jpeg_component_info * compptr;
4baf5a
d63a12 ··/* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
f8cc65 ···* This ought to be an error condition, but we make it a warning because
021dd5 ···* there are some baseline files out there with all zeroes in these bytes.
75f9a6 ···*/
1c6e0c ··if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
82095f ······cinfo->Ah != 0 || cinfo->Al != 0)
c62dd8 ····WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
03af5a
d16aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
9ba7cc ····compptr = cinfo->cur_comp_info[ci];
8b80fc ····dctbl = compptr->dc_tbl_no;
84656d ····actbl = compptr->ac_tbl_no;
59e9a9 ····/* Make sure requested tables are present */
af331d ····if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
851ccc ¤   cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
0257a3 ······ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
1aba79 ····if (actbl < 0 || actbl >= NUM_HUFF_TBLS ||
bbf340 ¤   cinfo->ac_huff_tbl_ptrs[actbl] == NULL)
57c0c2 ······ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
2b4b02 ····/* Compute derived values for Huffman tables */
56abeb ····/* We may do this more than once for a table, but it's not expensive */
510eb9 ····jpeg_make_d_derived_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[dctbl],
781631 ¤   ¤   ¤   ····& entropy->dc_derived_tbls[dctbl]);
218c4f ····jpeg_make_d_derived_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[actbl],
2071be ¤   ¤   ¤   ····& entropy->ac_derived_tbls[actbl]);
1a9302 ····/* Initialize DC predictions to 0 */
c14f55 ····entropy->saved.last_dc_val[ci] = 0;
a8df1c ··}
feaf5a
47b914 ··/* Initialize bitread state variables */
d95662 ··entropy->bitstate.bits_left = 0;
a04944 ··entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
3bf820 ··entropy->bitstate.printed_eod = FALSE;
b8af5a
942e5a ··/* Initialize restart counter */
507047 ··entropy->restarts_to_go = cinfo->restart_interval;
48efe6 }
54af5a
9faf5a
c038e5 /*
da6c87 ·* Compute the derived values for a Huffman table.
ce72a3 ·* Note this is also used by jdphuff.c.
c7495d ·*/
09af5a
3ff898 GLOBAL(void)
76d53b jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, JHUFF_TBL * htbl,
a6672e ¤   ¤   ¤   ·d_derived_tbl ** pdtbl)
50bb36 {
c5da1f ··d_derived_tbl *dtbl;
063aae ··int p, i, l, si;
16d56b ··int lookbits, ctr;
983528 ··char huffsize[257];
490a58 ··unsigned int huffcode[257];
83cc89 ··unsigned int code;
f4af5a
83bf27 ··/* Allocate a workspace if we haven't already done so. */
4ccefb ··if (*pdtbl == NULL)
de1f74 ····*pdtbl = (d_derived_tbl *)
8e558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
67afac ¤   ¤   ¤   ¤   ··SIZEOF(d_derived_tbl));
a08c2f ··dtbl = *pdtbl;
fc3b8c ··dtbl->pub = htbl;¤¤   /* fill in back link */
--2db5 00001be4e0a40100024 Page 3 of jdhuff.c
8bde7b ··
8a91c2 ··/* Figure C.1: make table of Huffman code length for each symbol */
26dde6 ··/* Note that this is in code-length order. */
7eaf5a
ba57d8 ··p = 0;
488b25 ··for (l = 1; l <= 16; l++) {
3830bf ····for (i = 1; i <= (int) htbl->bits[l]; i++)
bddfbd ······huffsize[p++] = (char) l;
addf1c ··}
2ff36b ··huffsize[p] = 0;
e9de7b ··
174996 ··/* Figure C.2: generate the codes themselves */
4fdde6 ··/* Note that this is in code-length order. */
88de7b ··
18f546 ··code = 0;
4ebfb2 ··si = huffsize[0];
9a57d8 ··p = 0;
ef7f22 ··while (huffsize[p]) {
fa6555 ····while (((int) huffsize[p]) == si) {
c5c25c ······huffcode[p++] = code;
90560f ······code++;
4f6fe7 ····}
6f2fcd ····code <<= 1;
f1b177 ····si++;
0ddf1c ··}
c9af5a
3a3de2 ··/* Figure F.15: generate decoding tables for bit-sequential decoding */
5aaf5a
2557d8 ··p = 0;
268b25 ··for (l = 1; l <= 16; l++) {
27e9ef ····if (htbl->bits[l]) {
a3ad15 ······dtbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
9b0fb8 ······dtbl->mincode[l] = huffcode[p]; /* minimum code of length l */
9073d5 ······p += htbl->bits[l];
d50f57 ······dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
116a79 ····} else {
c48a49 ······dtbl->maxcode[l] = -1;¤   /* -1 if no codes of this length */
1f6fe7 ····}
0bdf1c ··}
2b488a ··dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
5caf5a
163d79 ··/* Compute lookahead tables to speed up decoding.
5370b2 ···* First we set all the table entries to 0, indicating "too long";
8b1d8f ···* then we iterate through the Huffman codes that are short enough and
d1abea ···* fill in all the entries that correspond to bit sequences starting
4fff24 ···* with that code.
abf9a6 ···*/
f3af5a
1b2a09 ··MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
84af5a
0b57d8 ··p = 0;
3ef79d ··for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
4a3c01 ····for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
2cb875 ······/* l = current code's length, p = its index in huffcode[] & huffval[]. */
51d2c7 ······/* Generate left-justified code followed by all possible bit sequences */
1423c7 ······lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
1c9218 ······for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
878a5b ¤   dtbl->look_nbits[lookbits] = l;
537019 ¤   dtbl->look_sym[lookbits] = htbl->huffval[p];
b0ca77 ¤   lookbits++;
1942cc ······}
2b6fe7 ····}
28df1c ··}
05efe6 }
11af5a
2daf5a
e238e5 /*
bb299a ·* Out-of-line code for bit fetching (shared with jdphuff.c).
ddfe22 ·* See jdhuff.h for info about usage.
bae662 ·* Note: current values of get_buffer and bits_left are passed as parameters,
b02b07 ·* but are returned in the corresponding fields of the state struct.
01775e ·*
--5e26 000799037b240100024 Page 4 of jdhuff.c
86f8ac ·* On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
b7246e ·* of get_buffer to be used. ·(On machines with wider words, an even larger
737892 ·* buffer could be used.) ·However, on some machines 32-bit shifts are
f00f65 ·* quite slow and take time proportional to the number of places shifted.
819892 ·* (This is true with most PC compilers, for instance.) ·In this case it may
56016b ·* be a win to set MIN_GET_BITS to the minimum value of 15. ·This reduces the
d95952 ·* average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
c4495d ·*/
43af5a
bc6164 #ifdef SLOW_SHIFT_32
2893f6 #define MIN_GET_BITS ·15¤   /* minimum allowable value */
6fdb21 #else
5e74fd #define MIN_GET_BITS ·(BIT_BUF_SIZE-7)
837454 #endif
a2af5a
71af5a
13e553 GLOBAL(boolean)
95dde7 jpeg_fill_bit_buffer (bitread_working_state * state,
2880df ¤   ¤   ······register bit_buf_type get_buffer, register int bits_left,
7ab836 ¤   ¤   ······int nbits)
7dcb3d /* Load up the bit buffer to a depth of at least nbits */
a8bb36 {
ab3d6f ··/* Copy heavily used state fields into locals (hopefully registers) */
af24be ··register const JOCTET * next_input_byte = state->next_input_byte;
5c5ef9 ··register size_t bytes_in_buffer = state->bytes_in_buffer;
5c4a91 ··register int c;
f7af5a
c65a4b ··/* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
f9c7dc ··/* (It is assumed that no request will be for more than that many bits.) */
2baf5a
b7cf58 ··while (bits_left < MIN_GET_BITS) {
4204fa ····/* Attempt to read a byte */
ccebc2 ····if (state->unread_marker != 0)
5a063a ······goto no_more_data;¤   /* can't advance past a marker */
6baf5a
a589eb ····if (bytes_in_buffer == 0) {
b45d2b ······if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo))
f8a230 ¤   return FALSE;
696ab0 ······next_input_byte = state->cinfo->src->next_input_byte;
e6fde2 ······bytes_in_buffer = state->cinfo->src->bytes_in_buffer;
0d6fe7 ····}
68da3c ····bytes_in_buffer--;
b61b05 ····c = GETJOCTET(*next_input_byte++);
ecaf5a
76ba08 ····/* If it's 0xFF, check and discard stuffed zero byte */
772d4f ····if (c == 0xFF) {
ae7075 ······do {
40c447 ¤   if (bytes_in_buffer == 0) {
fa124f ¤   ··if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo))
ca0a51 ¤   ····return FALSE;
138b4f ¤   ··next_input_byte = state->cinfo->src->next_input_byte;
631c1d ¤   ··bytes_in_buffer = state->cinfo->src->bytes_in_buffer;
329371 ¤   }
c2d5cf ¤   bytes_in_buffer--;
43780f ¤   c = GETJOCTET(*next_input_byte++);
8f8d9d ······} while (c == 0xFF);
6eaf5a
32638c ······if (c == 0) {
ff00f9 ¤   /* Found FF/00, which represents an FF data byte */
b51edb ¤   c = 0xFF;
cfcfc7 ······} else {
05672e ¤   /* Oops, it's actually a marker indicating end of compressed data. */
e18f3b ¤   /* Better put it back for use later */
f08aea ¤   state->unread_marker = c;
e5af5a
4cf616 ······no_more_data:
18a764 ¤   /* There should be enough bits still left in the data segment; */
497220 ¤   /* if so, just break out of the outer while loop. */
e79cb9 ¤   if (bits_left >= nbits)
e112af ¤   ··break;
ff3243 ¤   /* Uh-oh. ·Report corrupted data to user and stuff zeroes into
79ff20 ¤   ·* the data stream, so that we can produce some kind of image.
--3fba 000373b805840100024 Page 5 of jdhuff.c
3b5bfc ¤   ·* Note that this code will be repeated for each byte demanded
d879cb ¤   ·* for the rest of the segment. ·We use a nonvolatile flag to ensure
e7db3f ¤   ·* that only one warning message appears.
1ba4e3 ¤   ·*/
b9577c ¤   if (! *(state->printed_eod_ptr)) {
017b60 ¤   ··WARNMS(state->cinfo, JWRN_HIT_MARKER);
dbf594 ¤   ··*(state->printed_eod_ptr) = TRUE;
549371 ¤   }
568b17 ¤   c = 0;¤ ¤   ¤   /* insert a zero byte into bit buffer */
3042cc ······}
596fe7 ····}
6caf5a
0da377 ····/* OK, load c into get_buffer */
e5b51e ····get_buffer = (get_buffer << 8) | c;
d8e306 ····bits_left += 8;
bbdf1c ··}
71af5a
480718 ··/* Unload the local registers */
d4eeec ··state->next_input_byte = next_input_byte;
2b4125 ··state->bytes_in_buffer = bytes_in_buffer;
f55e39 ··state->get_buffer = get_buffer;
743495 ··state->bits_left = bits_left;
ffaf5a
44d2c8 ··return TRUE;
49efe6 }
a7af5a
44af5a
8f38e5 /*
c22bf9 ·* Out-of-line code for Huffman code decoding.
f4fe22 ·* See jdhuff.h for info about usage.
05495d ·*/
2aaf5a
dc326f GLOBAL(int)
7bdb5e jpeg_huff_decode (bitread_working_state * state,
375807 ¤   ¤   ··register bit_buf_type get_buffer, register int bits_left,
b4173e ¤   ¤   ··d_derived_tbl * htbl, int min_bits)
f3bb36 {
fc0871 ··register int l = min_bits;
d98c0c ··register INT32 code;
c0af5a
b41dd8 ··/* HUFF_DECODE has determined that the code is at least min_bits */
14def6 ··/* bits long, so fetch that many bits in one swoop. */
55af5a
7f6fc5 ··CHECK_BIT_BUFFER(*state, l, return -1);
8d7951 ··code = GET_BITS(l);
58af5a
acf499 ··/* Collect the rest of the Huffman code one bit at a time. */
965d75 ··/* This is per Figure F.16 in the JPEG spec. */
a9af5a
2848af ··while (code > htbl->maxcode[l]) {
542fcd ····code <<= 1;
e70e1e ····CHECK_BIT_BUFFER(*state, 1, return -1);
b12135 ····code |= GET_BITS(1);
e39818 ····l++;
62df1c ··}
50af5a
940718 ··/* Unload the local registers */
9f5e39 ··state->get_buffer = get_buffer;
623495 ··state->bits_left = bits_left;
1daf5a
1d68dc ··/* With garbage input we may reach the sentinel value l = 17. */
40af5a
fa1a4d ··if (l > 16) {
7a1171 ····WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
2704d7 ····return 0;¤  ¤   ¤   /* fake a zero as the safest result */
63df1c ··}
caaf5a
241aca ··return htbl->pub->huffval[ htbl->valptr[l] +
097180 ¤   ¤   ¤   ····((int) (code - htbl->mincode[l])) ];
d8efe6 }
e3af5a
37af5a
--c152 00049e322c940100024 Page 6 of jdhuff.c
bc38e5 /*
430aa3 ·* Figure F.12: extend sign bit.
fd195b ·* On some machines, a shift and add will be faster than a table lookup.
71495d ·*/
2faf5a
f100cc #ifdef AVOID_TABLES
34af5a
8c24f2 #define HUFF_EXTEND(x,s) ·((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
c7af5a
6fdb21 #else
a5af5a
3f0b5e #define HUFF_EXTEND(x,s) ·((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
a1af5a
af9a7b static const int extend_test[16] = ··/* entry n is 2**(n-1) */
535785 ··{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
00e950 ····0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
f3af5a
818ca1 static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
4ba64a ··{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
efaf52 ····((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
572860 ····((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
8df883 ····((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
d3af5a
051e5b #endif /* AVOID_TABLES */
44af5a
35af5a
9738e5 /*
26aeaa ·* Check for a restart marker & resynchronize decoder.
fd0522 ·* Returns FALSE if must suspend.
5c495d ·*/
99af5a
50c4bf LOCAL(boolean)
08acd0 process_restart (j_decompress_ptr cinfo)
8ebb36 {
df2609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
f20dcc ··int ci;
03af5a
cb017d ··/* Throw away any unused bits remaining in bit buffer; */
5b5a67 ··/* include any full bytes in next_marker's count of discarded bytes */
4531cf ··cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
425662 ··entropy->bitstate.bits_left = 0;
dbaf5a
cf1aa7 ··/* Advance past the RSTn marker */
bf736a ··if (! (*cinfo->marker->read_restart_marker) (cinfo))
fc30cb ····return FALSE;
caaf5a
c2bee5 ··/* Re-initialize DC predictions to 0 */
f35387 ··for (ci = 0; ci < cinfo->comps_in_scan; ci++)
b14f55 ····entropy->saved.last_dc_val[ci] = 0;
bfaf5a
a70d37 ··/* Reset restart counter */
ad7047 ··entropy->restarts_to_go = cinfo->restart_interval;
7baf5a
e80f77 ··/* Next segment can get another out-of-data warning */
3df820 ··entropy->bitstate.printed_eod = FALSE;
ebaf5a
c6d2c8 ··return TRUE;
a0efe6 }
f2af5a
6faf5a
1a38e5 /*
ab5d3f ·* Decode and return one MCU's worth of Huffman-compressed coefficients.
d77e7d ·* The coefficients are reordered from zigzag order into natural array order,
507783 ·* but are not dequantized.
e3775e ·*
5a6b07 ·* The i'th block of the MCU is stored into the block pointed to by
b8a559 ·* MCU_data[i]. ·WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
3a3203 ·* (Wholesale zeroing is usually a little faster than retail...)
f3775e ·*
d98e31 ·* Returns FALSE if data source requested suspension. ·In that case no
518c55 ·* changes have been made to permanent state. ·(Exception: some output
499033 ·* coefficients may already have been assigned. ·This is harmless for
--cdb4 0001c483dd640100024 Page 7 of jdhuff.c
fbec25 ·* this module, since we'll just re-assign them on the next call.)
68495d ·*/
e5af5a
cb9a8f METHODDEF(boolean)
51a389 decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
31bb36 {
462609 ··huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
9086d3 ··register int s, k, r;
03ed99 ··int blkn, ci;
435fd5 ··JBLOCKROW block;
29d204 ··BITREAD_STATE_VARS;
b3faad ··savable_state state;
954192 ··d_derived_tbl * dctbl;
b5b131 ··d_derived_tbl * actbl;
5fbcae ··jpeg_component_info * compptr;
6baf5a
6cb91b ··/* Process restart marker if needed; may have to suspend */
c4cdfb ··if (cinfo->restart_interval) {
1c8a4f ····if (entropy->restarts_to_go == 0)
1d7293 ······if (! process_restart(cinfo))
aea230 ¤   return FALSE;
83df1c ··}
0faf5a
1c185b ··/* Load up working state */
c7efd3 ··BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
4a66cc ··ASSIGN_STATE(state, entropy->saved);
9eaf5a
342881 ··/* Outer loop handles each block in the MCU */
c6af5a
527685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
18d6bd ····block = MCU_data[blkn];
90153d ····ci = cinfo->MCU_membership[blkn];
55a7cc ····compptr = cinfo->cur_comp_info[ci];
f0282c ····dctbl = entropy->dc_derived_tbls[compptr->dc_tbl_no];
edf722 ····actbl = entropy->ac_derived_tbls[compptr->ac_tbl_no];
39af5a
767c44 ····/* Decode a single block's worth of coefficients */
c7af5a
6dba23 ····/* Section F.2.2.1: decode the DC coefficient difference */
40aeff ····HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
117613 ····if (s) {
aa7afc ······CHECK_BIT_BUFFER(br_state, s, return FALSE);
224546 ······r = GET_BITS(s);
b7610f ······s = HUFF_EXTEND(r, s);
c76fe7 ····}
e7af5a
900583 ····/* Shortcut if component's values are not interesting */
6f3311 ····if (! compptr->component_needed)
4dd43a ······goto skip_ACs;
7baf5a
607b32 ····/* Convert DC difference to actual value, update last_dc_val */
e9a67b ····s += state.last_dc_val[ci];
9ad1f0 ····state.last_dc_val[ci] = s;
3db1ef ····/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
8094ef ····(*block)[0] = (JCOEF) s;
90af5a
ebaade ····/* Do we need to decode the AC coefficients for this component? */
f6af74 ····if (compptr->DCT_scaled_size > 1) {
c3af5a
089d01 ······/* Section F.2.2.2: decode the AC coefficients */
014d86 ······/* Since zeroes are skipped, output area must be cleared beforehand */
dfa7cc ······for (k = 1; k < DCTSIZE2; k++) {
16e98b ¤   HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
3dcf72 ······
595238 ¤   r = s >> 4;
f735da ¤   s &= 15;
c1cf72 ······
57ec5d ¤   if (s) {
8fc153 ¤   ··k += r;
23a397 ¤   ··CHECK_BIT_BUFFER(br_state, s, return FALSE);
f14ab5 ¤   ··r = GET_BITS(s);
1cc72d ¤   ··s = HUFF_EXTEND(r, s);
--a895 001f2bad25b40100024 Page 8 of jdhuff.c
b59559 ¤   ··/* Output coefficient in natural (dezigzagged) order.
6a44f1 ¤   ···* Note: the extra entries in jpeg_natural_order[] will save us
37929c ¤   ···* if k >= DCTSIZE2, which could happen if the data is corrupted.
8e6533 ¤   ···*/
d61eee ¤   ··(*block)[jpeg_natural_order[k]] = (JCOEF) s;
21f037 ¤   } else {
1cfc05 ¤   ··if (r != 15)
73cafa ¤   ····break;
b6439e ¤   ··k += 15;
c79371 ¤   }
2b42cc ······}
8daf5a
976a79 ····} else {
9d82ec skip_ACs:
58af5a
119d01 ······/* Section F.2.2.2: decode the AC coefficients */
d9874a ······/* In this path we just discard the values */
bda7cc ······for (k = 1; k < DCTSIZE2; k++) {
60f530 ¤   HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
b7cf72 ······
e05238 ¤   r = s >> 4;
8c35da ¤   s &= 15;
60cf72 ······
b7ec5d ¤   if (s) {
1ec153 ¤   ··k += r;
5ca397 ¤   ··CHECK_BIT_BUFFER(br_state, s, return FALSE);
93c60d ¤   ··DROP_BITS(s);
baf037 ¤   } else {
d1fc05 ¤   ··if (r != 15)
56cafa ¤   ····break;
bd439e ¤   ··k += 15;
d39371 ¤   }
ea42cc ······}
2baf5a
fc6fe7 ····}
3cdf1c ··}
d0af5a
d44c4d ··/* Completed MCU, so update state */
4fcdc5 ··BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
5066e4 ··ASSIGN_STATE(entropy->saved, state);
8caf5a
16d5b5 ··/* Account for restart interval (no-op if not using restarts) */
0fea59 ··entropy->restarts_to_go--;
a7af5a
02d2c8 ··return TRUE;
e5efe6 }
5eaf5a
3daf5a
7138e5 /*
77606f ·* Module initialization routine for Huffman entropy decoding.
fe495d ·*/
54af5a
dff898 GLOBAL(void)
c8f97c jinit_huff_decoder (j_decompress_ptr cinfo)
55bb36 {
d550ef ··huff_entropy_ptr entropy;
b117e0 ··int i;
e9af5a
66c76a ··entropy = (huff_entropy_ptr)
703f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
0db17d ¤   ¤   ¤   ¤   SIZEOF(huff_entropy_decoder));
018412 ··cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
791168 ··entropy->pub.start_pass = start_pass_huff_decoder;
301207 ··entropy->pub.decode_mcu = decode_mcu;
26af5a
e74d66 ··/* Mark tables unallocated */
bb72db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
cb5166 ····entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
dfdf1c ··}
f2efe6 }
--4974 000f54d02b840100025 Page 1 of jdhuff.h
bc38e5 /*
db8f67 ·* jdhuff.h
e6775e ·*
5ba060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
f8fb07 ·* This file is part of the Independent JPEG Group's software.
3aa0d6 ·* For conditions of distribution and use, see the accompanying README file.
7c775e ·*
469713 ·* This file contains declarations for Huffman entropy decoding routines
9e0266 ·* that are shared between the sequential decoder (jdhuff.c) and the
fc455f ·* progressive decoder (jdphuff.c). ·No other modules need to see these.
01495d ·*/
38af5a
614b22 /* Short forms of external names for systems with brain-damaged linkers. */
4caf5a
92ddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
6f12d1 #define jpeg_make_d_derived_tbl¤jMkDDerived
b13899 #define jpeg_fill_bit_buffer¤   jFilBitBuf
d9b221 #define jpeg_huff_decode¤   jHufDecode
e45892 #endif /* NEED_SHORT_EXTERNAL_NAMES */
23af5a
d1af5a
d09079 /* Derived data constructed for each Huffman table */
82af5a
83ec3d #define HUFF_LOOKAHEAD¤ 8¤  /* # of bits of lookahead */
97af5a
d0f0f7 typedef struct {
0efb17 ··/* Basic tables: (element [0] of each array is unused) */
5ab530 ··INT32 mincode[17];¤   ¤   /* smallest code of length k */
a0908c ··INT32 maxcode[18];¤   ¤   /* largest code of length k (-1 if none) */
8dd9f0 ··/* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
e1fb23 ··int valptr[17];¤  ¤   /* huffval[] index of 1st symbol of length k */
d8af5a
8528ab ··/* Link to public Huffman table (needed only in jpeg_huff_decode) */
3776ca ··JHUFF_TBL *pub;
27af5a
366629 ··/* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
2927db ···* the input data stream. ·If the next Huffman code is no more
628d08 ···* than HUFF_LOOKAHEAD bits long, we can obtain its length and
74915c ···* the corresponding symbol directly from these tables.
d7f9a6 ···*/
dcdff0 ··int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
48657a ··UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
ed5998 } d_derived_tbl;
e4af5a
a88943 /* Expand a Huffman table definition into the derived format */
30b7ca EXTERN(void) jpeg_make_d_derived_tbl JPP((j_decompress_ptr cinfo,
d9f2b7 ¤   ¤   ¤   ¤   JHUFF_TBL * htbl, d_derived_tbl ** pdtbl));
f7af5a
a1af5a
0638e5 /*
c568af ·* Fetching the next N bits from the input stream is a time-critical operation
a3a172 ·* for the Huffman decoders. ·We implement it with a combination of inline
112a65 ·* macros and out-of-line subroutines. ·Note that N (the number of bits
3f20c8 ·* demanded at one time) never exceeds 15 for JPEG use.
5a775e ·*
df1028 ·* We read source bytes into get_buffer and dole out bits as needed.
e4a9fb ·* If get_buffer already contains enough bits, they are fetched in-line
ab4d25 ·* by the macros CHECK_BIT_BUFFER and GET_BITS. ·When there aren't enough
e4f43f ·* bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
c0e804 ·* as full as possible (not just to the number of bits needed; this
bc060b ·* prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
fc4a55 ·* Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
c4401d ·* On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
09fe52 ·* at least the requested number of bits --- dummy zeroes are inserted if
b30a2c ·* necessary.
3a495d ·*/
e1af5a
fd6675 typedef INT32 bit_buf_type;¤/* type of bit-extraction buffer */
1eaadd #define BIT_BUF_SIZE ·32¤   /* size of buffer in bits */
79af5a
3d225e /* If long is > 32 bits on your machine, and shifting/masking longs is
f5f3ea ·* reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
--dc96 000f9d11aa340100025 Page 2 of jdhuff.h
0f70da ·* appropriately should be a win. ·Unfortunately we can't do this with
f31369 ·* something like ·#define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
7c823e ·* because not all machines measure sizeof in 8-bit bytes.
79495d ·*/
0eaf5a
73f716 typedef struct {¤   ¤   /* Bitreading state saved across MCUs */
16477a ··bit_buf_type get_buffer;¤ /* current bit-extraction buffer */
157b89 ··int bits_left;¤   ¤   /* # of unused bits in it */
068ab2 ··boolean printed_eod;¤ ¤   /* flag to suppress multiple warning msgs */
8c694f } bitread_perm_state;
10af5a
bf0415 typedef struct {¤   ¤   /* Bitreading working state within an MCU */
fe3035 ··/* current data source state */
8ba7bf ··const JOCTET * next_input_byte; /* => next byte to read from source */
d3177a ··size_t bytes_in_buffer;¤  /* # of bytes remaining in source buffer */
71eeb9 ··int unread_marker;¤   ¤   /* nonzero if we have hit a marker */
c197af ··/* bit input buffer --- note these values are kept in register variables,
13f395 ···* not in this struct, inside the inner loops.
fbf9a6 ···*/
d4477a ··bit_buf_type get_buffer;¤ /* current bit-extraction buffer */
767b89 ··int bits_left;¤   ¤   /* # of unused bits in it */
370f11 ··/* pointers needed by jpeg_fill_bit_buffer */
1ac13a ··j_decompress_ptr cinfo;¤  /* back link to decompress master record */
129cb2 ··boolean * printed_eod_ptr;¤   /* => flag in permanent state */
a223c1 } bitread_working_state;
b3af5a
06c615 /* Macros to declare and load/save bitread local variables. */
6b7687 #define BITREAD_STATE_VARS ·\
b90b26 ¤   register bit_buf_type get_buffer; ·\
f5e318 ¤   register int bits_left; ·\
ff3779 ¤   bitread_working_state br_state
fdaf5a
8c995a #define BITREAD_LOAD_STATE(cinfop,permstate) ·\
6fc0b6 ¤   br_state.cinfo = cinfop; \
634d83 ¤   br_state.next_input_byte = cinfop->src->next_input_byte; \
dd631c ¤   br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
298006 ¤   br_state.unread_marker = cinfop->unread_marker; \
2f91b2 ¤   get_buffer = permstate.get_buffer; \
553487 ¤   bits_left = permstate.bits_left; \
b63386 ¤   br_state.printed_eod_ptr = & permstate.printed_eod
79af5a
69abb7 #define BITREAD_SAVE_STATE(cinfop,permstate) ·\
ff6d41 ¤   cinfop->src->next_input_byte = br_state.next_input_byte; \
b8eff5 ¤   cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
6efd95 ¤   cinfop->unread_marker = br_state.unread_marker; \
403c92 ¤   permstate.get_buffer = get_buffer; \
20a376 ¤   permstate.bits_left = bits_left
c5af5a
2e38e5 /*
381b2d ·* These macros provide the in-line portion of bit fetching.
b8e4f3 ·* Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
e8cc06 ·* before using GET_BITS, PEEK_BITS, or DROP_BITS.
f58e54 ·* The variables get_buffer and bits_left are assumed to be locals,
129594 ·* but the state struct might not be (jpeg_huff_decode needs this).
77025f ·*¤ CHECK_BIT_BUFFER(state,n,action);
bafdd4 ·*¤ ¤   Ensure there are N bits in get_buffer; if suspend, take action.
67c8a4 ·* ·····val = GET_BITS(n);
9bef05 ·*¤ ¤   Fetch next N bits.
00319e ·* ·····val = PEEK_BITS(n);
35b745 ·*¤ ¤   Fetch next N bits without removing them from the buffer.
fa9b13 ·*¤ DROP_BITS(n);
d0ceef ·*¤ ¤   Discard next N bits.
a7313c ·* The value N should be a simple variable, not an expression, because it
a6a68e ·* is evaluated multiple times.
c0495d ·*/
92af5a
1df6cc #define CHECK_BIT_BUFFER(state,nbits,action) \
648425 ¤   { if (bits_left < (nbits)) { ·\
93df96 ¤   ····if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) ·\
fb91b5 ¤   ······{ action; } ·\
682e89 ¤   ····get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
f9af5a
--eb1b 00183e28e7540100025 Page 3 of jdhuff.h
2060c7 #define GET_BITS(nbits) \
25384f ¤   (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
67af5a
18aeb2 #define PEEK_BITS(nbits) \
7c240d ¤   (((int) (get_buffer >> (bits_left - ·(nbits)))) & ((1<<(nbits))-1))
01af5a
cc48ae #define DROP_BITS(nbits) \
c43f14 ¤   (bits_left -= (nbits))
42af5a
d7cb3d /* Load up the bit buffer to a depth of at least nbits */
023531 EXTERN(boolean) jpeg_fill_bit_buffer
3726c6 ¤   JPP((bitread_working_state * state, register bit_buf_type get_buffer,
eb390e ¤   ·····register int bits_left, int nbits));
25af5a
11af5a
0a38e5 /*
a27578 ·* Code for extracting next Huffman-coded symbol from input bit stream.
5fd9f8 ·* Again, this is time-critical and we make the main paths be macros.
3f775e ·*
014d87 ·* We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
67b469 ·* without looping. ·Usually, more than 95% of the Huffman codes will be 8
f7d84d ·* or fewer bits long. ·The few overlength codes are handled with a loop,
4a5a0c ·* which need not be inline code.
29775e ·*
b84c21 ·* Notes about the HUFF_DECODE macro:
a7ed62 ·* 1. Near the end of the data segment, we may fail to get enough bits
9a8416 ·* ···for a lookahead. ·In that case, we do it the hard way.
99a2e7 ·* 2. If the lookahead table contains no entry, the next code must be
920451 ·* ···more than HUFF_LOOKAHEAD bits long.
a5415f ·* 3. jpeg_huff_decode returns -1 if forced to suspend.
90495d ·*/
89af5a
aa8bd8 #define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
48dd16 { register int nb, look; \
b15743 ··if (bits_left < HUFF_LOOKAHEAD) { \
a1353d ····if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
b34241 ····get_buffer = state.get_buffer; bits_left = state.bits_left; \
224661 ····if (bits_left < HUFF_LOOKAHEAD) { \
ff6c02 ······nb = 1; goto slowlabel; \
f59a2c ····} \
e9b707 ··} \
93e4fb ··look = PEEK_BITS(HUFF_LOOKAHEAD); \
50a1ac ··if ((nb = htbl->look_nbits[look]) != 0) { \
ddfd69 ····DROP_BITS(nb); \
dcae39 ····result = htbl->look_sym[look]; \
7eeb72 ··} else { \
86d4e8 ····nb = HUFF_LOOKAHEAD+1; \
55ba1c slowlabel: \
735708 ····if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
4eb89e ¤   { failaction; } \
384241 ····get_buffer = state.get_buffer; bits_left = state.bits_left; \
68b707 ··} \
adefe6 }
fcaf5a
2f32c7 /* Out-of-line case for Huffman code fetching */
c6a0aa EXTERN(int) jpeg_huff_decode
af26c6 ¤   JPP((bitread_working_state * state, register bit_buf_type get_buffer,
833b49 ¤   ·····register int bits_left, d_derived_tbl * htbl, int min_bits));
--c2f9 000bb1f29df40100026 Page 1 of jdinput.c
bc38e5 /*
9b6204 ·* jdinput.c
5e775e ·*
49a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
dcfb07 ·* This file is part of the Independent JPEG Group's software.
eba0d6 ·* For conditions of distribution and use, see the accompanying README file.
6b775e ·*
63959b ·* This file contains input control logic for the JPEG decompressor.
a0cd7c ·* These routines are concerned with controlling the decompressor's input
cd3cf7 ·* processing (marker reading and coefficient decoding). ·The actual input
56354a ·* reading is done in jdmarker.c, jdhuff.c, and jdphuff.c.
58495d ·*/
abaf5a
ea2bb6 #define JPEG_INTERNALS
4636a7 #include "jinclude.h"
026c8f #include "jpeglib.h"
23af5a
37af5a
34c632 /* Private state */
71af5a
4bf0f7 typedef struct {
e23133 ··struct jpeg_input_controller pub; /* public fields */
1daf5a
c87ec9 ··boolean inheaders;¤   ¤   /* TRUE until first SOS is reached */
543350 } my_input_controller;
e2af5a
f64e6c typedef my_input_controller * my_inputctl_ptr;
fdaf5a
f6af5a
586a43 /* Forward declarations */
845f4a METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
dbaf5a
5daf5a
7338e5 /*
1f83f6 ·* Routines to calculate various quantities related to the size of the image.
d7495d ·*/
deaf5a
19afad LOCAL(void)
8fa9f7 initial_setup (j_decompress_ptr cinfo)
3463ce /* Called once, when first SOS marker is reached */
6bbb36 {
4a0dcc ··int ci;
1933b0 ··jpeg_component_info *compptr;
4daf5a
30efb3 ··/* Make sure image isn't bigger than I can handle */
112b9a ··if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
431144 ······(long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
04dab3 ····ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
64af5a
bc94f9 ··/* For now, precision must match compiled-in value... */
0f62a5 ··if (cinfo->data_precision != BITS_IN_JSAMPLE)
03c3a4 ····ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
6caf5a
ba53b8 ··/* Check that number of components won't exceed internal array sizes */
3f5295 ··if (cinfo->num_components > MAX_COMPONENTS)
5e2023 ····ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
ca3220 ¤   ·····MAX_COMPONENTS);
2eaf5a
d7ecca ··/* Compute maximum sampling factors; check factor validity */
9ea629 ··cinfo->max_h_samp_factor = 1;
3513a9 ··cinfo->max_v_samp_factor = 1;
a9958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
85aa07 ·······ci++, compptr++) {
689c0c ····if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
d2936e ¤   compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
b924bb ······ERREXIT(cinfo, JERR_BAD_SAMPLING);
a8b611 ····cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
e48895 ¤   ¤   ¤   ¤   ···compptr->h_samp_factor);
3b2b91 ····cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
d0458a ¤   ¤   ¤   ¤   ···compptr->v_samp_factor);
14df1c ··}
bbaf5a
--bdd1 0004246f52940100026 Page 2 of jdinput.c
fa3ce4 ··/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
d16d33 ···* In the full decompressor, this will be overridden by jdmaster.c;
8bec7a ···* but in the transcoder, jdmaster.c is not used, so we must do it here.
53f9a6 ···*/
198f9c ··cinfo->min_DCT_scaled_size = DCTSIZE;
f1af5a
09c9c3 ··/* Compute dimensions of components */
d3958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
81aa07 ·······ci++, compptr++) {
ea72b3 ····compptr->DCT_scaled_size = DCTSIZE;
287fb6 ····/* Size in DCT blocks */
6b6652 ····compptr->width_in_blocks = (JDIMENSION)
f3e3c2 ······jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
dcd601 ¤   ¤   ····(long) (cinfo->max_h_samp_factor * DCTSIZE));
f9dcc7 ····compptr->height_in_blocks = (JDIMENSION)
9e8cf6 ······jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
36bd17 ¤   ¤   ····(long) (cinfo->max_v_samp_factor * DCTSIZE));
d66962 ····/* downsampled_width and downsampled_height will also be overridden by
ce7176 ·····* jdmaster.c if we are doing full decompression. ·The transcoder library
7ee6b0 ·····* doesn't use these values, but the calling application might.
5bd48d ·····*/
9c269c ····/* Size in samples */
f0b513 ····compptr->downsampled_width = (JDIMENSION)
67e3c2 ······jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
b70add ¤   ¤   ····(long) cinfo->max_h_samp_factor);
a8abac ····compptr->downsampled_height = (JDIMENSION)
3b8cf6 ······jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
70c7c2 ¤   ¤   ····(long) cinfo->max_v_samp_factor);
0cb7e0 ····/* Mark component needed, until color conversion says otherwise */
9d64a8 ····compptr->component_needed = TRUE;
41d539 ····/* Mark no quantization table yet saved for component */
ffc4f0 ····compptr->quant_table = NULL;
c3df1c ··}
b8af5a
89482d ··/* Compute number of fully interleaved MCU rows. */
bbbd4d ··cinfo->total_iMCU_rows = (JDIMENSION)
bb89b3 ····jdiv_round_up((long) cinfo->image_height,
54ba45 ¤   ¤   ··(long) (cinfo->max_v_samp_factor*DCTSIZE));
48af5a
c413b1 ··/* Decide whether file contains multiple scans */
320c5a ··if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
12ac54 ····cinfo->inputctl->has_multiple_scans = TRUE;
a41bd0 ··else
e1254e ····cinfo->inputctl->has_multiple_scans = FALSE;
71efe6 }
d6af5a
93af5a
47afad LOCAL(void)
906aec per_scan_setup (j_decompress_ptr cinfo)
7f1b37 /* Do computations that are needed before processing a JPEG scan */
cc3ab3 /* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
eabb36 {
3ad772 ··int ci, mcublks, tmp;
9833b0 ··jpeg_component_info *compptr;
b3de7b ··
dde0a3 ··if (cinfo->comps_in_scan == 1) {
f8869e ····
0d9cc9 ····/* Noninterleaved (single-component) scan */
fad213 ····compptr = cinfo->cur_comp_info[0];
ec869e ····
aa6e1d ····/* Overall image size in MCUs */
000a5e ····cinfo->MCUs_per_row = compptr->width_in_blocks;
49b708 ····cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
ca869e ····
362473 ····/* For noninterleaved scan, always one block per MCU */
ad9a95 ····compptr->MCU_width = 1;
e56e4e ····compptr->MCU_height = 1;
be15dd ····compptr->MCU_blocks = 1;
196fff ····compptr->MCU_sample_width = compptr->DCT_scaled_size;
eb5fb0 ····compptr->last_col_width = 1;
a5bf2d ····/* For noninterleaved scans, it is convenient to define last_row_height
42da4b ·····* as the number of block rows present in the last iMCU row.
--d600 0006d28634c40100026 Page 3 of jdinput.c
dbd48d ·····*/
72ad7f ····tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
638e29 ····if (tmp == 0) tmp = compptr->v_samp_factor;
1eca97 ····compptr->last_row_height = tmp;
a6869e ····
f2b764 ····/* Prepare array describing MCU composition */
a13d02 ····cinfo->blocks_in_MCU = 1;
ebc782 ····cinfo->MCU_membership[0] = 0;
68869e ····
2f49d8 ··} else {
c2869e ····
203e3f ····/* Interleaved (multi-component) scan */
2fcc37 ····if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
9b5c1f ······ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
1bf105 ¤   ·······MAX_COMPS_IN_SCAN);
48869e ····
636e1d ····/* Overall image size in MCUs */
24afac ····cinfo->MCUs_per_row = (JDIMENSION)
0a9f26 ······jdiv_round_up((long) cinfo->image_width,
f87266 ¤   ¤   ····(long) (cinfo->max_h_samp_factor*DCTSIZE));
60a73f ····cinfo->MCU_rows_in_scan = (JDIMENSION)
1a1e30 ······jdiv_round_up((long) cinfo->image_height,
440f14 ¤   ¤   ····(long) (cinfo->max_v_samp_factor*DCTSIZE));
1a869e ····
d967de ····cinfo->blocks_in_MCU = 0;
ec869e ····
d56772 ····for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
aab647 ······compptr = cinfo->cur_comp_info[ci];
38863a ······/* Sampling factors give # of blocks of component in each MCU */
8e9d6a ······compptr->MCU_width = compptr->h_samp_factor;
1c5494 ······compptr->MCU_height = compptr->v_samp_factor;
a73a17 ······compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
d3b469 ······compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size;
94c105 ······/* Figure number of non-dummy blocks in last MCU column & row */
fb7e2b ······tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
95680d ······if (tmp == 0) tmp = compptr->MCU_width;
676eec ······compptr->last_col_width = tmp;
cdfdb3 ······tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
70501f ······if (tmp == 0) tmp = compptr->MCU_height;
fdb1d9 ······compptr->last_row_height = tmp;
189913 ······/* Prepare array describing MCU composition */
7e76b7 ······mcublks = compptr->MCU_blocks;
b796ad ······if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
9d1891 ¤   ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
702664 ······while (mcublks-- > 0) {
a0f6d4 ¤   cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
f142cc ······}
076fe7 ····}
9b869e ····
50df1c ··}
33efe6 }
d2af5a
ccaf5a
4138e5 /*
f75410 ·* Save away a copy of the Q-table referenced by each component present
f4de73 ·* in the current scan, unless already saved during a prior scan.
1c775e ·*
5c8ce7 ·* In a multiple-scan JPEG file, the encoder could assign different components
ae82ae ·* the same Q-table slot number, but change table definitions between scans
5baf78 ·* so that each component uses a different Q-table. ·(The IJG encoder is not
477612 ·* currently capable of doing this, but other encoders might.) ·Since we want
a2c281 ·* to be able to dequantize all the components at the end of the file, this
acb646 ·* means that we have to save away the table actually used for each component.
41b622 ·* We do this by copying the table at the start of the first scan containing
0e775c ·* the component.
c4d8a9 ·* The JPEG spec prohibits the encoder from changing the contents of a Q-table
45a430 ·* slot between scans of a component using that slot. ·If the encoder does so
3933f1 ·* anyway, this decoder will simply use the Q-table values that were current
e7ab5f ·* at the start of the first scan for the component.
55775e ·*
08d49e ·* The decompressor output side looks only at the saved quant tables,
6dc85f ·* not at the current Q-table slots.
--7f0b 000d164e1e540100026 Page 4 of jdinput.c
47495d ·*/
44af5a
51afad LOCAL(void)
7cd30b latch_quant_tables (j_decompress_ptr cinfo)
dfbb36 {
661574 ··int ci, qtblno;
6133b0 ··jpeg_component_info *compptr;
124504 ··JQUANT_TBL * qtbl;
a5af5a
746aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
5ba7cc ····compptr = cinfo->cur_comp_info[ci];
c15d93 ····/* No work if we already saved Q-table for this component */
db2c23 ····if (compptr->quant_table != NULL)
0c5f6a ······continue;
166031 ····/* Make sure specified quantization table is present */
beed10 ····qtblno = compptr->quant_tbl_no;
094153 ····if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
746d78 ¤   cinfo->quant_tbl_ptrs[qtblno] == NULL)
3490fe ······ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
570846 ····/* OK, save away the quantization table */
b52db1 ····qtbl = (JQUANT_TBL *)
ff558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
c18037 ¤   ¤   ¤   ¤   ··SIZEOF(JQUANT_TBL));
e79aa5 ····MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
5b7756 ····compptr->quant_table = qtbl;
51df1c ··}
50efe6 }
edaf5a
daaf5a
6d38e5 /*
a078b7 ·* Initialize the input modules to read a scan of compressed data.
2e1f84 ·* The first call to this is done by jdmaster.c after initializing
e158d8 ·* the entire decompressor (during jpeg_start_decompress).
e8a67b ·* Subsequent calls come from consume_markers, below.
48495d ·*/
31af5a
6c0434 METHODDEF(void)
df1208 start_input_pass (j_decompress_ptr cinfo)
b1bb36 {
a30d7f ··per_scan_setup(cinfo);
7133a8 ··latch_quant_tables(cinfo);
4d1b35 ··(*cinfo->entropy->start_pass) (cinfo);
54287b ··(*cinfo->coef->start_input_pass) (cinfo);
cad129 ··cinfo->inputctl->consume_input = cinfo->coef->consume_data;
dbefe6 }
b4af5a
eaaf5a
0438e5 /*
6c2e4b ·* Finish up after inputting a compressed-data scan.
e299aa ·* This is called by the coefficient controller after it's read all
194de9 ·* the expected data of the scan.
9a495d ·*/
feaf5a
220434 METHODDEF(void)
078cc8 finish_input_pass (j_decompress_ptr cinfo)
9abb36 {
2f69bf ··cinfo->inputctl->consume_input = consume_markers;
89efe6 }
c6af5a
b5af5a
7a38e5 /*
fc945f ·* Read JPEG markers before, between, or after compressed-data scans.
67bb00 ·* Change state as necessary when a new scan is reached.
d38470 ·* Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
d6775e ·*
17db7a ·* The consume_input method pointer points either here or to the
9625c2 ·* coefficient controller's consume_data routine, depending on whether
8922a5 ·* we are reading a compressed data segment or inter-segment markers.
67495d ·*/
80af5a
a24924 METHODDEF(int)
d1ca1b consume_markers (j_decompress_ptr cinfo)
--d718 000c360597040100026 Page 5 of jdinput.c
2cbb36 {
586755 ··my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
687467 ··int val;
d6af5a
57f941 ··if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
99e900 ····return JPEG_REACHED_EOI;
a9af5a
7cb55f ··val = (*cinfo->marker->read_markers) (cinfo);
95af5a
bfd7e9 ··switch (val) {
612136 ··case JPEG_REACHED_SOS:¤   /* Found SOS */
6733d1 ····if (inputctl->inheaders) {¤ /* 1st SOS */
8f7697 ······initial_setup(cinfo);
5eaad2 ······inputctl->inheaders = FALSE;
470276 ······/* Note: start_input_pass must be called by jdmaster.c
a6e598 ·······* before any more input can be consumed. ·jdapi.c is
175e30 ·······* responsible for enforcing this sequencing.
7ce9f1 ·······*/
fd1437 ····} else {¤   ¤   ¤   /* 2nd or later SOS marker */
cea36f ······if (! inputctl->pub.has_multiple_scans)
538f74 ¤   ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
c56a00 ······start_input_pass(cinfo);
9c6fe7 ····}
c7ab40 ····break;
94862a ··case JPEG_REACHED_EOI:¤   /* Found EOI */
0c9e5a ····inputctl->pub.eoi_reached = TRUE;
b821fe ····if (inputctl->inheaders) {¤ /* Tables-only datastream, apparently */
365e6e ······if (cinfo->marker->saw_SOF)
80017f ¤   ERREXIT(cinfo, JERR_SOF_NO_SOS);
4f6a79 ····} else {
676f9b ······/* Prevent infinite loop in coef ctlr's decompress_data routine
8f9b1f ·······* if user set output_scan_number larger than number of scans.
52e9f1 ·······*/
588b26 ······if (cinfo->output_scan_number > cinfo->input_scan_number)
1d4d06 ¤   cinfo->output_scan_number = cinfo->input_scan_number;
456fe7 ····}
48ab40 ····break;
696b90 ··case JPEG_SUSPENDED:
1bab40 ····break;
e3df1c ··}
22af5a
972ad6 ··return val;
37efe6 }
2caf5a
e1af5a
b738e5 /*
01e49a ·* Reset state to begin a fresh datastream.
8f495d ·*/
99af5a
b30434 METHODDEF(void)
ef2da8 reset_input_controller (j_decompress_ptr cinfo)
32bb36 {
226755 ··my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
adaf5a
ac42b8 ··inputctl->pub.consume_input = consume_markers;
76a60e ··inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
686703 ··inputctl->pub.eoi_reached = FALSE;
98c8d9 ··inputctl->inheaders = TRUE;
2cdcf3 ··/* Reset other modules */
9cc167 ··(*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
57b44e ··(*cinfo->marker->reset_marker_reader) (cinfo);
e0d40a ··/* Reset progression state -- would be cleaner if entropy decoder did this */
bbe50b ··cinfo->coef_bits = NULL;
b0efe6 }
3eaf5a
60af5a
5538e5 /*
0b8ee1 ·* Initialize the input controller module.
dcc5b3 ·* This is called only once, when the decompression object is created.
59495d ·*/
bbaf5a
c3f898 GLOBAL(void)
--4004 001e48fe10b40100026 Page 6 of jdinput.c
2ba0df jinit_input_controller (j_decompress_ptr cinfo)
e4bb36 {
7a6e11 ··my_inputctl_ptr inputctl;
eeaf5a
e0b606 ··/* Create subobject in permanent pool */
499d4d ··inputctl = (my_inputctl_ptr)
6c2142 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
76f8a0 ¤   ¤   ¤   ¤   SIZEOF(my_input_controller));
3feea7 ··cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
34a3de ··/* Initialize method pointers */
e842b8 ··inputctl->pub.consume_input = consume_markers;
62f062 ··inputctl->pub.reset_input_controller = reset_input_controller;
dff190 ··inputctl->pub.start_input_pass = start_input_pass;
d7acd3 ··inputctl->pub.finish_input_pass = finish_input_pass;
7d43d7 ··/* Initialize state: can't use reset_input_controller since we don't
b5ac85 ···* want to try to reset other modules yet.
51f9a6 ···*/
0ea60e ··inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
366703 ··inputctl->pub.eoi_reached = FALSE;
90c8d9 ··inputctl->inheaders = TRUE;
e4efe6 }
--297a 000f9a72c7140100027 Page 1 of jdmainct.c
bc38e5 /*
e13a4e ·* jdmainct.c
6c775e ·*
d39e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
d3fb07 ·* This file is part of the Independent JPEG Group's software.
c7a0d6 ·* For conditions of distribution and use, see the accompanying README file.
72775e ·*
7bee7e ·* This file contains the main buffer controller for decompression.
36ca22 ·* The main buffer lies between the JPEG decompressor proper and the
65365c ·* post-processor; it holds downsampled data in the JPEG colorspace.
43775e ·*
f74ca2 ·* Note that this code is bypassed in raw-data mode, since the application
439965 ·* supplies the equivalent of the main buffer in that case.
e7495d ·*/
9aaf5a
762bb6 #define JPEG_INTERNALS
cf36a7 #include "jinclude.h"
d96c8f #include "jpeglib.h"
e3af5a
e8af5a
5f38e5 /*
64ea25 ·* In the current system design, the main buffer need never be a full-image
ded557 ·* buffer; any full-height buffers will be found inside the coefficient or
e53b15 ·* postprocessing controllers. ·Nonetheless, the main controller is not
a503c5 ·* trivial. ·Its responsibility is to provide context rows for upsampling/
8cd480 ·* rescaling, and doing this in an efficient fashion is a bit tricky.
fc775e ·*
05e0d9 ·* Postprocessor input data is counted in "row groups". ·A row group
eff53c ·* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
3d0171 ·* sample rows of each component. ·(We require DCT_scaled_size values to be
a3ad0c ·* chosen such that these numbers are integers. ·In practice DCT_scaled_size
521540 ·* values will likely be powers of two, so we actually have the stronger
64e62e ·* condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
ad6dca ·* Upsampling will typically produce max_v_samp_factor pixel rows from each
061d11 ·* row group (times any additional scale factor that the upsampler is
001b19 ·* applying).
2a775e ·*
a3f02b ·* The coefficient controller will deliver data to us one iMCU row at a time;
990897 ·* each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
c5fbc1 ·* exactly min_DCT_scaled_size row groups. ·(This amount of data corresponds
ec50f8 ·* to one row of MCUs when the image is fully interleaved.) ·Note that the
264780 ·* number of sample rows varies across components, but the number of row
8c073e ·* groups does not. ·Some garbage sample rows may be included in the last iMCU
68e7c9 ·* row at the bottom of the image.
59775e ·*
30cc37 ·* Depending on the vertical scaling algorithm used, the upsampler may need
7e8b24 ·* access to the sample row(s) above and below its current input row group.
97b05c ·* The upsampler is required to set need_context_rows TRUE at global selection
3c1341 ·* time if so. ·When need_context_rows is FALSE, this controller can simply
f6d000 ·* obtain one iMCU row at a time from the coefficient controller and dole it
b50ef9 ·* out as row groups to the postprocessor.
37775e ·*
5dc0b3 ·* When need_context_rows is TRUE, this controller guarantees that the buffer
5b225b ·* passed to postprocessing contains at least one row group's worth of samples
58c5ae ·* above and below the row group(s) being processed. ·Note that the context
0f2844 ·* rows "above" the first passed row group appear at negative row offsets in
58a1f0 ·* the passed buffer. ·At the top and bottom of the image, the required
d04916 ·* context rows are manufactured by duplicating the first or last real sample
d5cc0c ·* row; this avoids having special cases in the upsampling inner loops.
67775e ·*
f8aa4a ·* The amount of context is fixed at one row group just because that's a
ef4e2c ·* convenient number for this controller to work with. ·The existing
30286c ·* upsamplers really only need one sample row of context. ·An upsampler
2b1fa5 ·* supporting arbitrary output rescaling might wish for more than one row
e334f2 ·* group of context when shrinking the image; tough, we don't handle that.
190026 ·* (This is justified by the assumption that downsizing will be handled mostly
eca52a ·* by adjusting the DCT_scaled_size values, so that the actual scale factor at
475733 ·* the upsample step needn't be much less than one.)
5c775e ·*
3acd48 ·* To provide the desired context, we have to retain the last two row groups
6c6132 ·* of one iMCU row while reading in the next iMCU row. ·(The last row group
f98e08 ·* can't be processed until we have another row group for its below-context,
--ff8a 0003fcecf8240100027 Page 2 of jdmainct.c
cef6c7 ·* and so we have to save the next-to-last group too for its above-context.)
700ed8 ·* We could do this most simply by copying data around in our buffer, but
adc024 ·* that'd be very slow. ·We can avoid copying any data by creating a rather
017ba2 ·* strange pointer structure. ·Here's how it works. ·We allocate a workspace
585143 ·* consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
989940 ·* of row groups per iMCU row). ·We create two sets of redundant pointers to
6033a1 ·* the workspace. ·Labeling the physical row groups 0 to M+1, the synthesized
1a1b30 ·* pointer lists look like this:
dd6d63 ·* ··················M+1 ·························M-1
c8c7bb ·* master pointer --> 0 ········master pointer --> 0
b771e5 ·* ···················1 ···························1
a4fef5 ·* ··················... ·························...
ace7f7 ·* ··················M-3 ·························M-3
0cef40 ·* ··················M-2 ··························M
5b80e7 ·* ··················M-1 ·························M+1
037957 ·* ···················M ··························M-2
e86d63 ·* ··················M+1 ·························M-1
70ad09 ·* ···················0 ···························0
c90653 ·* We read alternate iMCU rows using each master pointer; thus the last two
48d534 ·* row groups of the previous iMCU row remain un-overwritten in the workspace.
41b08e ·* The pointer lists are set up so that the required context rows appear to
e5fab1 ·* be adjacent to the proper places when we pass the pointer lists to the
5f6014 ·* upsampler.
ed775e ·*
feabf4 ·* The above pictures describe the normal state of the pointer lists.
6f470f ·* At top and bottom of the image, we diddle the pointer lists to duplicate
00ad76 ·* the first or last sample row as necessary (this is cheaper than copying
b3c9de ·* sample rows around).
88775e ·*
93f76a ·* This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. ·In that
5e46f2 ·* situation each iMCU row provides only one row group so the buffering logic
40f687 ·* must be different (eg, we must read two iMCU rows before we can emit the
5a8e61 ·* first row group). ·For now, we simply do not support providing context
204865 ·* rows when min_DCT_scaled_size is 1. ·That combination seems unlikely to
2e673c ·* be worth providing --- if someone wants a 1/8th-size preview, they probably
8939e5 ·* want it quick and dirty, so a context-free upsampler is sufficient.
4c495d ·*/
98af5a
d8af5a
f08416 /* Private buffer controller object */
08af5a
44f0f7 typedef struct {
e8cf5f ··struct jpeg_d_main_controller pub; /* public fields */
eeaf5a
6fb594 ··/* Pointer to allocated workspace (M or M+2 row groups). */
030d09 ··JSAMPARRAY buffer[MAX_COMPONENTS];
6eaf5a
395f51 ··boolean buffer_full;¤ ¤   /* Have we gotten an iMCU row from decoder? */
364221 ··JDIMENSION rowgroup_ctr;¤ /* counts row groups output to postprocessor */
3caf5a
e139b0 ··/* Remaining fields are only used in the context case. */
0daf5a
b051f8 ··/* These are the master pointers to the funny-order pointer lists. */
51c359 ··JSAMPIMAGE xbuffer[2];¤   /* pointers to weird pointer lists */
60af5a
ecfa14 ··int whichptr;¤¤   ¤   /* indicates which pointer set is now in use */
2916f0 ··int context_state;¤   ¤   /* process_data state machine status */
202f53 ··JDIMENSION rowgroups_avail;¤  /* row groups available to postprocessor */
31fdf4 ··JDIMENSION iMCU_row_ctr;¤ /* counts iMCU rows to detect image top/bot */
06d9e9 } my_main_controller;
03af5a
006786 typedef my_main_controller * my_main_ptr;
13af5a
bf3431 /* context_state values: */
7e0d79 #define CTX_PREPARE_FOR_IMCU¤   0¤  /* need to prepare for MCU row */
27d06f #define CTX_PROCESS_IMCU¤   1¤  /* feeding iMCU to postprocessor */
e831a0 #define CTX_POSTPONED_ROW¤  2¤  /* feeding postponed row group */
bbaf5a
15af5a
f66a43 /* Forward declarations */
997e0e METHODDEF(void) process_data_simple_main
3f182a ¤   JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
--0d41 000fd7be59e40100027 Page 3 of jdmainct.c
64205b ¤   ·····JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
8340a5 METHODDEF(void) process_data_context_main
0e182a ¤   JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
38205b ¤   ·····JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
0f4df6 #ifdef QUANT_2PASS_SUPPORTED
7a5e91 METHODDEF(void) process_data_crank_post
9c182a ¤   JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
54205b ¤   ·····JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
d77454 #endif
9aaf5a
e2af5a
eaafad LOCAL(void)
00fc95 alloc_funny_pointers (j_decompress_ptr cinfo)
e36011 /* Allocate space for the funny pointer lists.
9c6052 ·* This is done only once, not once per pass.
73495d ·*/
68bb36 {
92b438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
f61199 ··int ci, rgroup;
2f6422 ··int M = cinfo->min_DCT_scaled_size;
c933b0 ··jpeg_component_info *compptr;
ad11a8 ··JSAMPARRAY xbuf;
fcaf5a
752958 ··/* Get top-level space for component array pointers.
004242 ···* We alloc both arrays with one call to save a few cycles.
44f9a6 ···*/
fa553d ··main->xbuffer[0] = (JSAMPIMAGE)
983f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
150deb ¤   ¤   ¤   ¤   cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
5c2f71 ··main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
deaf5a
08958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
85aa07 ·······ci++, compptr++) {
8e0e96 ····rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
caf8e6 ······cinfo->min_DCT_scaled_size; /* height of a row group of component */
50281e ····/* Get space for pointer lists --- M+4 row groups in each list.
fa4b08 ·····* We alloc both pointer lists with one call to save a few cycles.
7bd48d ·····*/
d633ba ····xbuf = (JSAMPARRAY)
3c558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
4a3926 ¤   ¤   ¤   ¤   ··2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
af50df ····xbuf += rgroup;¤¤   /* want one row group at negative offsets */
178f51 ····main->xbuffer[0][ci] = xbuf;
e552d9 ····xbuf += rgroup * (M + 4);
f0c77b ····main->xbuffer[1][ci] = xbuf;
f2df1c ··}
38efe6 }
0baf5a
92af5a
2cafad LOCAL(void)
443854 make_funny_pointers (j_decompress_ptr cinfo)
ae9d62 /* Create the funny pointer lists discussed in the comments above.
0fd4ab ·* The actual workspace is already allocated (in main->buffer),
2d5a92 ·* and the space for the pointer lists is allocated too.
0de495 ·* This routine just fills in the curiously ordered lists.
c9963f ·* This will be repeated at the beginning of each pass.
25495d ·*/
12bb36 {
feb438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
2dc283 ··int ci, i, rgroup;
dc6422 ··int M = cinfo->min_DCT_scaled_size;
1933b0 ··jpeg_component_info *compptr;
c83780 ··JSAMPARRAY buf, xbuf0, xbuf1;
84af5a
7f958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
10aa07 ·······ci++, compptr++) {
830e96 ····rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
fbf8e6 ······cinfo->min_DCT_scaled_size; /* height of a row group of component */
e3a322 ····xbuf0 = main->xbuffer[0][ci];
7defcd ····xbuf1 = main->xbuffer[1][ci];
707979 ····/* First copy the workspace pointers as-is */
fd0553 ····buf = main->buffer[ci];
--bb0a 0001bcbe8cd40100027 Page 4 of jdmainct.c
8d0d13 ····for (i = 0; i < rgroup * (M + 2); i++) {
140857 ······xbuf0[i] = xbuf1[i] = buf[i];
cb6fe7 ····}
ef0a6d ····/* In the second list, put the last four row groups in swapped order */
d04993 ····for (i = 0; i < rgroup * 2; i++) {
15df4d ······xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
670103 ······xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
3a6fe7 ····}
29c2d9 ····/* The wraparound pointers at top and bottom will be filled later
6589bd ·····* (see set_wraparound_pointers, below). ·Initially we want the "above"
86af4e ·····* pointers to duplicate the first actual data line. ·This only needs
846bc5 ·····* to happen in xbuffer[0].
54d48d ·····*/
6c5f04 ····for (i = 0; i < rgroup; i++) {
966f7f ······xbuf0[i - rgroup] = xbuf0[0];
1e6fe7 ····}
82df1c ··}
97efe6 }
14af5a
6daf5a
f5afad LOCAL(void)
e23df8 set_wraparound_pointers (j_decompress_ptr cinfo)
bc545f /* Set up the "wraparound" pointers at top and bottom of the pointer lists.
564f58 ·* This changes the pointer list state from top-of-image to the normal state.
74495d ·*/
86bb36 {
5ab438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
6ac283 ··int ci, i, rgroup;
056422 ··int M = cinfo->min_DCT_scaled_size;
8b33b0 ··jpeg_component_info *compptr;
930298 ··JSAMPARRAY xbuf0, xbuf1;
9baf5a
87958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
85aa07 ·······ci++, compptr++) {
320e96 ····rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
74f8e6 ······cinfo->min_DCT_scaled_size; /* height of a row group of component */
52a322 ····xbuf0 = main->xbuffer[0][ci];
0befcd ····xbuf1 = main->xbuffer[1][ci];
ac5f04 ····for (i = 0; i < rgroup; i++) {
94efde ······xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
764665 ······xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
6fdc5b ······xbuf0[rgroup*(M+2) + i] = xbuf0[i];
77af12 ······xbuf1[rgroup*(M+2) + i] = xbuf1[i];
1e6fe7 ····}
5edf1c ··}
23efe6 }
75af5a
c0af5a
bfafad LOCAL(void)
e4acde set_bottom_pointers (j_decompress_ptr cinfo)
699f8d /* Change the pointer lists to duplicate the last sample row at the bottom
c6b0f0 ·* of the image. ·whichptr indicates which xbuffer holds the final iMCU row.
f10bbf ·* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
2e495d ·*/
30bb36 {
6cb438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
c27ba7 ··int ci, i, rgroup, iMCUheight, rows_left;
4b33b0 ··jpeg_component_info *compptr;
fe11a8 ··JSAMPARRAY xbuf;
f5af5a
38958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ffaa07 ·······ci++, compptr++) {
df4c13 ····/* Count sample rows in one iMCU row and in one row group */
4b5f0f ····iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size;
e20c7f ····rgroup = iMCUheight / cinfo->min_DCT_scaled_size;
593e74 ····/* Count nondummy sample rows remaining for this component */
36e434 ····rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
a37a88 ····if (rows_left == 0) rows_left = iMCUheight;
804cd5 ····/* Count nondummy row groups. ·Should get same answer for each component,
3a9d9f ·····* so we need only do it once.
61d48d ·····*/
1bb606 ····if (ci == 0) {
--96a2 000c2324dd040100027 Page 5 of jdmainct.c
cb5d72 ······main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
2d6fe7 ····}
dd666b ····/* Duplicate the last real sample row rgroup*2 times; this pads out the
cb6dee ·····* last partial rowgroup and ensures at least one full rowgroup of context.
dfd48d ·····*/
274bd3 ····xbuf = main->xbuffer[main->whichptr][ci];
474993 ····for (i = 0; i < rgroup * 2; i++) {
e8e2a8 ······xbuf[rows_left + i] = xbuf[rows_left-1];
426fe7 ····}
4adf1c ··}
8defe6 }
d8af5a
69af5a
e038e5 /*
165b80 ·* Initialize for a processing pass.
82495d ·*/
47af5a
3b0434 METHODDEF(void)
62383d start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
72bb36 {
b9b438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
dcaf5a
dd1eec ··switch (pass_mode) {
ee972e ··case JBUF_PASS_THRU:
34f84f ····if (cinfo->upsample->need_context_rows) {
d024a8 ······main->pub.process_data = process_data_context_main;
d8e926 ······make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
24308c ······main->whichptr = 0;¤  /* Read first iMCU row into xbuffer[0] */
42ebad ······main->context_state = CTX_PREPARE_FOR_IMCU;
5309f2 ······main->iMCU_row_ctr = 0;
c36a79 ····} else {
982d6d ······/* Simple case with no context needed */
190bf0 ······main->pub.process_data = process_data_simple_main;
d06fe7 ····}
0c6d12 ····main->buffer_full = FALSE;¤ /* Mark buffer empty */
6004f6 ····main->rowgroup_ctr = 0;
2bab40 ····break;
ac4df6 #ifdef QUANT_2PASS_SUPPORTED
8c6409 ··case JBUF_CRANK_DEST:
f9addb ····/* For last pass of 2-pass quantization, just crank the postprocessor */
afc635 ····main->pub.process_data = process_data_crank_post;
1fab40 ····break;
9b7454 #endif
54969d ··default:
a9650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
f2ab40 ····break;
7cdf1c ··}
dbefe6 }
5caf5a
6faf5a
f438e5 /*
9a3bfc ·* Process some data.
dac4c6 ·* This handles the simple case where no context is required.
95495d ·*/
0baf5a
c80434 METHODDEF(void)
b3df13 process_data_simple_main (j_decompress_ptr cinfo,
07d504 ¤   ¤   ¤   ··JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
a0b71b ¤   ¤   ¤   ··JDIMENSION out_rows_avail)
b5bb36 {
b5b438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
78a126 ··JDIMENSION rowgroups_avail;
e7af5a
f45742 ··/* Read input data if we haven't filled the main buffer yet */
5f4446 ··if (! main->buffer_full) {
f7b6d1 ····if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
dda5b2 ······return;¤  ¤   ¤   /* suspension forced, can do nothing more */
1cb34b ····main->buffer_full = TRUE;¤  /* OK, we have an iMCU row to work with */
4fdf1c ··}
d8af5a
80ad5c ··/* There are always min_DCT_scaled_size row groups in an iMCU row. */
c2f17d ··rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size;
--49ee 00009fca7bf40100027 Page 6 of jdmainct.c
f4129f ··/* Note: at the bottom of the image, we may pass extra garbage row groups
fbbfb7 ···* to the postprocessor. ·The postprocessor has to check for bottom
536d12 ···* of image anyway (at row resolution), so no point in us doing it too.
2df9a6 ···*/
09af5a
f79e51 ··/* Feed the postprocessor */
8e3593 ··(*cinfo->post->post_process_data) (cinfo, main->buffer,
76fa0c ¤   ¤   ¤   ¤   ·····&main->rowgroup_ctr, rowgroups_avail,
aab868 ¤   ¤   ¤   ¤   ·····output_buf, out_row_ctr, out_rows_avail);
eeaf5a
1680ea ··/* Has postprocessor consumed all the data yet? If so, mark buffer empty */
60dc87 ··if (main->rowgroup_ctr >= rowgroups_avail) {
663696 ····main->buffer_full = FALSE;
bf04f6 ····main->rowgroup_ctr = 0;
87df1c ··}
d5efe6 }
28af5a
5faf5a
0038e5 /*
723bfc ·* Process some data.
068318 ·* This handles the case where context rows must be provided.
a8495d ·*/
53af5a
140434 METHODDEF(void)
b36cf9 process_data_context_main (j_decompress_ptr cinfo,
28b6da ¤   ¤   ¤   ···JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
f6eb22 ¤   ¤   ¤   ···JDIMENSION out_rows_avail)
3ebb36 {
6db438 ··my_main_ptr main = (my_main_ptr) cinfo->main;
58af5a
c45742 ··/* Read input data if we haven't filled the main buffer yet */
a04446 ··if (! main->buffer_full) {
4a2661 ····if (! (*cinfo->coef->decompress_data) (cinfo,
eb636e ¤   ¤   ¤   ¤   ¤   ···main->xbuffer[main->whichptr]))
3ba5b2 ······return;¤  ¤   ¤   /* suspension forced, can do nothing more */
43b34b ····main->buffer_full = TRUE;¤  /* OK, we have an iMCU row to work with */
1e321c ····main->iMCU_row_ctr++;¤  /* count rows received */
8ddf1c ··}
abaf5a
66e419 ··/* Postprocessor typically will not swallow all the input data it is handed
fd5312 ···* in one call (due to filling the output buffer first). ·Must be prepared
d3f950 ···* to exit and restart. ·This switch lets us keep track of how far we got.
0f618a ···* Note that each case falls through to the next on successful completion.
88f9a6 ···*/
682c26 ··switch (main->context_state) {
032fc3 ··case CTX_POSTPONED_ROW:
250998 ····/* Call postprocessor using previously set pointers for postponed row */
469680 ····(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
afbe96 ¤   ¤   ¤   &main->rowgroup_ctr, main->rowgroups_avail,
691f1e ¤   ¤   ¤   output_buf, out_row_ctr, out_rows_avail);
70e88e ····if (main->rowgroup_ctr < main->rowgroups_avail)
85c206 ······return;¤  ¤   ¤   /* Need to suspend */
17ad3f ····main->context_state = CTX_PREPARE_FOR_IMCU;
821590 ····if (*out_row_ctr >= out_rows_avail)
49564e ······return;¤  ¤   ¤   /* Postprocessor exactly filled output buf */
6fa950 ····/*FALLTHROUGH*/
fef2b2 ··case CTX_PREPARE_FOR_IMCU:
7fc81a ····/* Prepare to process first M-1 row groups of this iMCU row */
5504f6 ····main->rowgroup_ctr = 0;
a09b17 ····main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1);
adbd2e ····/* Check for bottom of image: if so, tweak pointers to "duplicate"
4497bb ·····* the last sample row, and adjust rowgroups_avail to ignore padding rows.
bbd48d ·····*/
fd7253 ····if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
b1cddd ······set_bottom_pointers(cinfo);
c7d8dd ····main->context_state = CTX_PROCESS_IMCU;
65a950 ····/*FALLTHROUGH*/
cf08a1 ··case CTX_PROCESS_IMCU:
3e593e ····/* Call postprocessor using previously set pointers */
419680 ····(*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
89be96 ¤   ¤   ¤   &main->rowgroup_ctr, main->rowgroups_avail,
091f1e ¤   ¤   ¤   output_buf, out_row_ctr, out_rows_avail);
--8b1e 000ceb1d5fc40100027 Page 7 of jdmainct.c
6be88e ····if (main->rowgroup_ctr < main->rowgroups_avail)
e0c206 ······return;¤  ¤   ¤   /* Need to suspend */
86b6d8 ····/* After the first iMCU, change wraparound pointers to normal state */
6216ba ····if (main->iMCU_row_ctr == 1)
b65351 ······set_wraparound_pointers(cinfo);
1bda12 ····/* Prepare to load new iMCU row using other xbuffer list */
be413d ····main->whichptr ^= 1;¤   /* 0=>1 or 1=>0 */
763696 ····main->buffer_full = FALSE;
34f2b5 ····/* Still need to process last row group of this iMCU row, */
9cf3c3 ····/* which is saved at index M+1 of the other xbuffer */
d766e5 ····main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1);
5ea620 ····main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2);
d0d5fc ····main->context_state = CTX_POSTPONED_ROW;
d1df1c ··}
faefe6 }
03af5a
b8af5a
f338e5 /*
eb3bfc ·* Process some data.
10b6f4 ·* Final pass of two-pass quantization: just call the postprocessor.
3019dc ·* Source data will be the postprocessor controller's internal buffer.
e9495d ·*/
beaf5a
9c4df6 #ifdef QUANT_2PASS_SUPPORTED
f1af5a
cc0434 METHODDEF(void)
b113fc process_data_crank_post (j_decompress_ptr cinfo,
f20d64 ¤   ¤   ¤   ·JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
627ba5 ¤   ¤   ¤   ·JDIMENSION out_rows_avail)
f4bb36 {
8514df ··(*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
7e6c6e ¤   ¤   ¤   ¤   ·····(JDIMENSION *) NULL, (JDIMENSION) 0,
f6b868 ¤   ¤   ¤   ¤   ·····output_buf, out_row_ctr, out_rows_avail);
39efe6 }
3faf5a
b5d24f #endif /* QUANT_2PASS_SUPPORTED */
72af5a
d8af5a
c238e5 /*
3e2bab ·* Initialize main buffer controller.
fb495d ·*/
28af5a
55f898 GLOBAL(void)
7bd2ef jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
45bb36 {
ce89cf ··my_main_ptr main;
a17d83 ··int ci, rgroup, ngroups;
2c33b0 ··jpeg_component_info *compptr;
abaf5a
f1ce41 ··main = (my_main_ptr)
ef3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
252d80 ¤   ¤   ¤   ¤   SIZEOF(my_main_controller));
153974 ··cinfo->main = (struct jpeg_d_main_controller *) main;
ca0191 ··main->pub.start_pass = start_pass_main;
e2af5a
8758e8 ··if (need_full_buffer)¤¤   /* shouldn't happen */
9d650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
e3af5a
ea3f4f ··/* Allocate the workspace.
7dc3e0 ···* ngroups is the number of row groups we need.
95f9a6 ···*/
24ca7d ··if (cinfo->upsample->need_context_rows) {
f31aef ····if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */
7bcedf ······ERREXIT(cinfo, JERR_NOTIMPL);
57c5df ····alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
8b5b56 ····ngroups = cinfo->min_DCT_scaled_size + 2;
d149d8 ··} else {
5d34cb ····ngroups = cinfo->min_DCT_scaled_size;
abdf1c ··}
81af5a
f4958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ceaa07 ·······ci++, compptr++) {
--4c79 0015c064bdb40100027 Page 8 of jdmainct.c
630e96 ····rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
f3f8e6 ······cinfo->min_DCT_scaled_size; /* height of a row group of component */
7994f0 ····main->buffer[ci] = (*cinfo->mem->alloc_sarray)
4a7e4b ¤   ¤   ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE,
489d0f ¤   ¤   ¤   ·compptr->width_in_blocks * compptr->DCT_scaled_size,
30629a ¤   ¤   ¤   ·(JDIMENSION) (rgroup * ngroups));
f1df1c ··}
5cefe6 }
--f703 000faba63d940100028 Page 1 of jdmarker.c
bc38e5 /*
7e9d80 ·* jdmarker.c
5c775e ·*
0ea060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
9efb07 ·* This file is part of the Independent JPEG Group's software.
c3a0d6 ·* For conditions of distribution and use, see the accompanying README file.
01775e ·*
dffab4 ·* This file contains routines to decode JPEG datastream markers.
04ac9e ·* Most of the complexity arises from our desire to support input
4feef2 ·* suspension: if not all of the data for a marker is available,
ad6649 ·* we must exit back to the application. ·On resumption, we reprocess
c2e61e ·* the marker.
c0495d ·*/
fcaf5a
d62bb6 #define JPEG_INTERNALS
ec36a7 #include "jinclude.h"
546c8f #include "jpeglib.h"
1baf5a
5eaf5a
17c4b8 typedef enum {¤ ¤   ¤   /* JPEG marker codes */
5b1a61 ··M_SOF0 ·= 0xc0,
a4152c ··M_SOF1 ·= 0xc1,
2c04fb ··M_SOF2 ·= 0xc2,
5d0bb6 ··M_SOF3 ·= 0xc3,
51de7b ··
1a2818 ··M_SOF5 ·= 0xc5,
9739cf ··M_SOF6 ·= 0xc6,
163682 ··M_SOF7 ·= 0xc7,
72de7b ··
92b447 ··M_JPG ··= 0xc8,
c96f44 ··M_SOF9 ·= 0xc9,
79963c ··M_SOF10 = 0xca,
a8557f ··M_SOF11 = 0xcb,
a0de7b ··
9adbe8 ··M_SOF13 = 0xcd,
ee45c1 ··M_SOF14 = 0xce,
0d8682 ··M_SOF15 = 0xcf,
01de7b ··
881564 ··M_DHT ··= 0xc4,
89de7b ··
eca507 ··M_DAC ··= 0xcc,
ebde7b ··
ed45c5 ··M_RST0 ·= 0xd0,
284a88 ··M_RST1 ·= 0xd1,
0e5b5f ··M_RST2 ·= 0xd2,
a75412 ··M_RST3 ·= 0xd3,
3878f1 ··M_RST4 ·= 0xd4,
1b77bc ··M_RST5 ·= 0xd5,
13666b ··M_RST6 ·= 0xd6,
9d6926 ··M_RST7 ·= 0xd7,
47de7b ··
fac6e2 ··M_SOI ··= 0xd8,
234484 ··M_EOI ··= 0xd9,
28c490 ··M_SOS ··= 0xda,
f7656a ··M_DQT ··= 0xdb,
934f79 ··M_DNL ··= 0xdc,
882253 ··M_DRI ··= 0xdd,
be9e0c ··M_DHP ··= 0xde,
d65552 ··M_EXP ··= 0xdf,
14de7b ··
ed0716 ··M_APP0 ·= 0xe0,
9a085b ··M_APP1 ·= 0xe1,
dd198c ··M_APP2 ·= 0xe2,
df16c1 ··M_APP3 ·= 0xe3,
d23a22 ··M_APP4 ·= 0xe4,
dd356f ··M_APP5 ·= 0xe5,
0a24b8 ··M_APP6 ·= 0xe6,
652bf5 ··M_APP7 ·= 0xe7,
997d7e ··M_APP8 ·= 0xe8,
f77233 ··M_APP9 ·= 0xe9,
6a8b4b ··M_APP10 = 0xea,
fa4808 ··M_APP11 = 0xeb,
--c6f8 000ac8001f240100028 Page 2 of jdmarker.c
0f66bd ··M_APP12 = 0xec,
5fc69f ··M_APP13 = 0xed,
f158b6 ··M_APP14 = 0xee,
639bf5 ··M_APP15 = 0xef,
bcde7b ··
3dd9c6 ··M_JPG0 ·= 0xf0,
b6184f ··M_JPG13 = 0xfd,
4850a9 ··M_COM ··= 0xfe,
46de7b ··
c3aec5 ··M_TEM ··= 0x01,
30de7b ··
448170 ··M_ERROR = 0x100
e0c177 } JPEG_MARKER;
f7af5a
56af5a
b238e5 /*
2784a0 ·* Macros for fetching data from the data source module.
94775e ·*
ffef46 ·* At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
d4dfd8 ·* the current restart point; we update them only when we have reached a
6b8aa9 ·* suitable place to restart if a suspension occurs.
2e495d ·*/
8eaf5a
147197 /* Declare and initialize local copies of input pointer/count */
29e130 #define INPUT_VARS(cinfo) ·\
46a90e ¤   struct jpeg_source_mgr * datasrc = (cinfo)->src; ·\
a5a858 ¤   const JOCTET * next_input_byte = datasrc->next_input_byte; ·\
2d2b6e ¤   size_t bytes_in_buffer = datasrc->bytes_in_buffer
e9af5a
2dfc1f /* Unload the local copies --- do this only at a restart boundary */
d7ccc3 #define INPUT_SYNC(cinfo) ·\
6564f0 ¤   ( datasrc->next_input_byte = next_input_byte, ·\
d483d9 ¤   ··datasrc->bytes_in_buffer = bytes_in_buffer )
2caf5a
ac47b9 /* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */
ec57c6 #define INPUT_RELOAD(cinfo) ·\
04a7f5 ¤   ( next_input_byte = datasrc->next_input_byte, ·\
b0c37d ¤   ··bytes_in_buffer = datasrc->bytes_in_buffer )
58af5a
b8fe4e /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
42163b ·* Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
d479d9 ·* but we must reload the local copies after a successful fill.
0d495d ·*/
ab0c0b #define MAKE_BYTE_AVAIL(cinfo,action) ·\
aea70e ¤   if (bytes_in_buffer == 0) { ·\
a82a3c ¤   ··if (! (*datasrc->fill_input_buffer) (cinfo)) ·\
9b2ccd ¤   ····{ action; } ·\
f58b12 ¤   ··INPUT_RELOAD(cinfo); ·\
816986 ¤   } ·\
727ae3 ¤   bytes_in_buffer--
76af5a
f20aa7 /* Read a byte into variable V.
a19a48 ·* If must suspend, take the specified action (typically "return FALSE").
46495d ·*/
3e9ed7 #define INPUT_BYTE(cinfo,V,action) ·\
294265 ¤   MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
9d2ac2 ¤   ¤   ··V = GETJOCTET(*next_input_byte++); )
09af5a
c44ba8 /* As above, but read two bytes interpreted as an unsigned 16-bit integer.
6cf469 ·* V should be declared unsigned int or perhaps INT32.
18495d ·*/
903639 #define INPUT_2BYTES(cinfo,V,action) ·\
514265 ¤   MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
e6f308 ¤   ¤   ··V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
41fedc ¤   ¤   ··MAKE_BYTE_AVAIL(cinfo,action); \
19bcfe ¤   ¤   ··V += GETJOCTET(*next_input_byte++); )
e5af5a
11af5a
5938e5 /*
ba9d22 ·* Routines to process JPEG markers.
22775e ·*
acbe0b ·* Entry condition: JPEG marker itself has been read and its code saved
--da16 000fd69ea8840100028 Page 3 of jdmarker.c
b7a174 ·* ··in cinfo->unread_marker; input restart point is just after the marker.
d5775e ·*
f37359 ·* Exit: if return TRUE, have read and processed any parameters, and have
b80148 ·* ··updated the restart point to point after the parameters.
cceb2c ·* ··If return FALSE, was forced to suspend before reaching end of
55e3fc ·* ··marker parameters; restart point has not been moved. ·Same routine
10eb60 ·* ··will be called again after application supplies more input data.
5b775e ·*
40a338 ·* This approach to suspension assumes that all of a marker's parameters can
f1d30b ·* fit into a single input bufferload. ·This should hold for "normal"
dc1972 ·* markers. ·Some COM/APPn markers might have large parameter segments,
1b15f2 ·* but we use skip_input_data to get past those, and thereby put the problem
15581d ·* on the source manager's shoulders.
5f775e ·*
ec13b5 ·* Note that we don't bother to avoid duplicate trace messages if a
3c426e ·* suspension occurs within marker parameters. ·Other side effects
67b104 ·* require more care.
56495d ·*/
b3af5a
92af5a
6ec4bf LOCAL(boolean)
a07ff2 get_soi (j_decompress_ptr cinfo)
4ae865 /* Process an SOI marker */
17bb36 {
c317e0 ··int i;
97de7b ··
5bb3f2 ··TRACEMS(cinfo, 1, JTRC_SOI);
bcaf5a
90bc1f ··if (cinfo->marker->saw_SOI)
a64a05 ····ERREXIT(cinfo, JERR_SOI_DUPLICATE);
d2af5a
20afd1 ··/* Reset all parameters that are defined to be reset by SOI */
78af5a
cd1f63 ··for (i = 0; i < NUM_ARITH_TBLS; i++) {
f672cf ····cinfo->arith_dc_L[i] = 0;
aebf4f ····cinfo->arith_dc_U[i] = 1;
3f9c9e ····cinfo->arith_ac_K[i] = 5;
ffdf1c ··}
ab378b ··cinfo->restart_interval = 0;
57af5a
18a8fd ··/* Set initial assumptions for colorspace etc */
a4af5a
1936ea ··cinfo->jpeg_color_space = JCS_UNKNOWN;
d44c5c ··cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
5eaf5a
9fe38f ··cinfo->saw_JFIF_marker = FALSE;
ec6359 ··cinfo->density_unit = 0;¤ /* set default JFIF APP0 values */
423c00 ··cinfo->X_density = 1;
6f742a ··cinfo->Y_density = 1;
bfedbe ··cinfo->saw_Adobe_marker = FALSE;
a606be ··cinfo->Adobe_transform = 0;
86af5a
2267d2 ··cinfo->marker->saw_SOI = TRUE;
c6af5a
19d2c8 ··return TRUE;
25efe6 }
31af5a
98af5a
50c4bf LOCAL(boolean)
b0d1fc get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
57f5e1 /* Process a SOFn marker */
eebb36 {
c4a30c ··INT32 length;
a2fe3f ··int c, ci;
1ebcae ··jpeg_component_info * compptr;
0b3798 ··INPUT_VARS(cinfo);
c6af5a
18c366 ··cinfo->progressive_mode = is_prog;
864800 ··cinfo->arith_code = is_arith;
61af5a
0be6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
fdaf5a
--5be4 000fc831a3740100028 Page 4 of jdmarker.c
48878a ··INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
e6be0f ··INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
b03ecc ··INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
8b3364 ··INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
f6af5a
d28d69 ··length -= 8;
34af5a
c19e6a ··TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
5fec08 ¤   ···(int) cinfo->image_width, (int) cinfo->image_height,
487340 ¤   ···cinfo->num_components);
a5af5a
1cf6d8 ··if (cinfo->marker->saw_SOF)
a3d5e1 ····ERREXIT(cinfo, JERR_SOF_DUPLICATE);
faaf5a
150655 ··/* We don't support files in which the image height is initially specified */
de321e ··/* as 0 and is later redefined by DNL. ·As long as we have to check that, ·*/
b7579c ··/* might as well have a general sanity check. */
3ae515 ··if (cinfo->image_height <= 0 || cinfo->image_width <= 0
95da2b ······|| cinfo->num_components <= 0)
2906c0 ····ERREXIT(cinfo, JERR_EMPTY_IMAGE);
9daf5a
74485a ··if (length != (cinfo->num_components * 3))
07cdfc ····ERREXIT(cinfo, JERR_BAD_LENGTH);
4faf5a
0bebbe ··if (cinfo->comp_info == NULL)¤/* do only once, even if suspend */
477083 ····cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
d47e4b ¤   ¤   ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE,
7c495c ¤   ¤   ¤   ·cinfo->num_components * SIZEOF(jpeg_component_info));
18de7b ··
49958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
dfaa07 ·······ci++, compptr++) {
708484 ····compptr->component_index = ci;
16a9e4 ····INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
81c5f7 ····INPUT_BYTE(cinfo, c, return FALSE);
56e8c9 ····compptr->h_samp_factor = (c >> 4) & 15;
33b0c1 ····compptr->v_samp_factor = (c ····) & 15;
74a0d8 ····INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
03af5a
1e0d12 ····TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
d1a11c ¤   ·····compptr->component_id, compptr->h_samp_factor,
52a608 ¤   ·····compptr->v_samp_factor, compptr->quant_tbl_no);
82df1c ··}
2eaf5a
e4ca0e ··cinfo->marker->saw_SOF = TRUE;
a4af5a
da7a5d ··INPUT_SYNC(cinfo);
e1d2c8 ··return TRUE;
27efe6 }
0faf5a
dbaf5a
35c4bf LOCAL(boolean)
cf55d5 get_sos (j_decompress_ptr cinfo)
d38456 /* Process a SOS marker */
64bb36 {
e3a30c ··INT32 length;
dceebe ··int i, ci, n, c, cc;
46bcae ··jpeg_component_info * compptr;
693798 ··INPUT_VARS(cinfo);
99af5a
b535fd ··if (! cinfo->marker->saw_SOF)
90d6c4 ····ERREXIT(cinfo, JERR_SOS_NO_SOF);
e0af5a
45e6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
6baf5a
37e9a9 ··INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
71af5a
98debf ··if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
b6cdfc ····ERREXIT(cinfo, JERR_BAD_LENGTH);
d6af5a
f3d3d2 ··TRACEMS1(cinfo, 1, JTRC_SOS, n);
c5af5a
fc5215 ··cinfo->comps_in_scan = n;
--a3eb 0004f1233df40100028 Page 5 of jdmarker.c
e0af5a
e7848e ··/* Collect the component-spec parameters */
9faf5a
40ecee ··for (i = 0; i < n; i++) {
e150f4 ····INPUT_BYTE(cinfo, cc, return FALSE);
16c5f7 ····INPUT_BYTE(cinfo, c, return FALSE);
3b869e ····
0c6090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
9cb5ed ¤   ·ci++, compptr++) {
16e8d5 ······if (cc == compptr->component_id)
97f1c9 ¤   goto id_found;
e16fe7 ····}
08af5a
a9f970 ····ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
2aaf5a
8c6a93 ··id_found:
6baf5a
31d078 ····cinfo->cur_comp_info[i] = compptr;
17c90b ····compptr->dc_tbl_no = (c >> 4) & 15;
6026aa ····compptr->ac_tbl_no = (c ····) & 15;
8b869e ····
195f54 ····TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
48d859 ¤   ·····compptr->dc_tbl_no, compptr->ac_tbl_no);
5fdf1c ··}
23af5a
1463f1 ··/* Collect the additional scan parameters Ss, Se, Ah/Al. */
2bd4d5 ··INPUT_BYTE(cinfo, c, return FALSE);
4cb7f7 ··cinfo->Ss = c;
ded4d5 ··INPUT_BYTE(cinfo, c, return FALSE);
075af3 ··cinfo->Se = c;
d1d4d5 ··INPUT_BYTE(cinfo, c, return FALSE);
41ab8d ··cinfo->Ah = (c >> 4) & 15;
ee0a53 ··cinfo->Al = (c ····) & 15;
f8af5a
faa233 ··TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
fafb69 ¤   ···cinfo->Ah, cinfo->Al);
23af5a
120bb2 ··/* Prepare to scan data & restart markers */
d99303 ··cinfo->marker->next_restart_num = 0;
32af5a
e083f9 ··/* Count another SOS marker */
162eef ··cinfo->input_scan_number++;
e8af5a
797a5d ··INPUT_SYNC(cinfo);
e7d2c8 ··return TRUE;
41efe6 }
57af5a
79af5a
209a8f METHODDEF(boolean)
764430 get_app0 (j_decompress_ptr cinfo)
b7f953 /* Process an APP0 marker */
0abb36 {
fbc013 #define JFIF_LEN 14
47a30c ··INT32 length;
542422 ··UINT8 b[JFIF_LEN];
c8899e ··int buffp;
c03798 ··INPUT_VARS(cinfo);
7caf5a
1ee6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
aefe13 ··length -= 2;
5faf5a
9b06d9 ··/* See if a JFIF APP0 marker is present */
f3af5a
09f0ac ··if (length >= JFIF_LEN) {
312dca ····for (buffp = 0; buffp < JFIF_LEN; buffp++)
af17d6 ······INPUT_BYTE(cinfo, b[buffp], return FALSE);
28941e ····length -= JFIF_LEN;
b8af5a
12191d ····if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && b[4]==0) {
5ae820 ······/* Found JFIF APP0 marker: check version */
f1d81e ······/* Major version must be 1, anything else signals an incompatible change.
4fa144 ·······* We used to treat this as an error, but now it's a nonfatal warning,
--c5ac 00087b2293a40100028 Page 6 of jdmarker.c
ea572f ·······* because some bozo at Hijaak couldn't read the spec.
43b261 ·······* Minor version should be 0..2, but process anyway if newer.
63e9f1 ·······*/
838947 ······if (b[5] != 1)
390981 ¤   WARNMS2(cinfo, JWRN_JFIF_MAJOR, b[5], b[6]);
9c5e78 ······else if (b[6] > 2)
0493de ¤   TRACEMS2(cinfo, 1, JTRC_JFIF_MINOR, b[5], b[6]);
9670ae ······/* Save info */
755c30 ······cinfo->saw_JFIF_marker = TRUE;
c07f61 ······cinfo->density_unit = b[7];
c0a719 ······cinfo->X_density = (b[8] << 8) + b[9];
7dfd7e ······cinfo->Y_density = (b[10] << 8) + b[11];
aacaf2 ······TRACEMS3(cinfo, 1, JTRC_JFIF,
719dd4 ¤   ·······cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
969770 ······if (b[12] | b[13])
c2881c ¤   TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, b[12], b[13]);
95ac45 ······if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3))
ac49e9 ¤   TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) length);
0d6a79 ····} else {
a748a4 ······/* Start of APP0 does not match "JFIF" */
200d27 ······TRACEMS1(cinfo, 1, JTRC_APP0, (int) length + JFIF_LEN);
a86fe7 ····}
9949d8 ··} else {
f7528f ····/* Too short to be JFIF marker */
b70799 ····TRACEMS1(cinfo, 1, JTRC_APP0, (int) length);
e8df1c ··}
91af5a
277a5d ··INPUT_SYNC(cinfo);
1db2dd ··if (length > 0)¤  ¤   /* skip any remaining data -- could be lots */
93ad94 ····(*cinfo->src->skip_input_data) (cinfo, (long) length);
04af5a
4dd2c8 ··return TRUE;
4aefe6 }
c0af5a
c3af5a
e59a8f METHODDEF(boolean)
d09acf get_app14 (j_decompress_ptr cinfo)
08a4ba /* Process an APP14 marker */
cdbb36 {
9f1191 #define ADOBE_LEN 12
43a30c ··INT32 length;
dcc468 ··UINT8 b[ADOBE_LEN];
b1899e ··int buffp;
f7604b ··unsigned int version, flags0, flags1, transform;
1b3798 ··INPUT_VARS(cinfo);
61af5a
16e6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
9ffe13 ··length -= 2;
b1af5a
2480ad ··/* See if an Adobe APP14 marker is present */
f5af5a
b52946 ··if (length >= ADOBE_LEN) {
36e499 ····for (buffp = 0; buffp < ADOBE_LEN; buffp++)
5a17d6 ······INPUT_BYTE(cinfo, b[buffp], return FALSE);
fc6b9a ····length -= ADOBE_LEN;
4daf5a
a909eb ····if (b[0]==0x41 && b[1]==0x64 && b[2]==0x6F && b[3]==0x62 && b[4]==0x65) {
b2d69b ······/* Found Adobe APP14 marker */
b3a09d ······version = (b[5] << 8) + b[6];
9a4acc ······flags0 = (b[7] << 8) + b[8];
1565d5 ······flags1 = (b[9] << 8) + b[10];
8f0937 ······transform = b[11];
8f9299 ······TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
a5c369 ······cinfo->saw_Adobe_marker = TRUE;
7f446d ······cinfo->Adobe_transform = (UINT8) transform;
dc6a79 ····} else {
8f3288 ······/* Start of APP14 does not match "Adobe" */
8b0ce6 ······TRACEMS1(cinfo, 1, JTRC_APP14, (int) length + ADOBE_LEN);
0a6fe7 ····}
1a49d8 ··} else {
35651e ····/* Too short to be Adobe marker */
8716e7 ····TRACEMS1(cinfo, 1, JTRC_APP14, (int) length);
--039c 000deab49a540100028 Page 7 of jdmarker.c
3adf1c ··}
64af5a
b87a5d ··INPUT_SYNC(cinfo);
8eb2dd ··if (length > 0)¤  ¤   /* skip any remaining data -- could be lots */
5cad94 ····(*cinfo->src->skip_input_data) (cinfo, (long) length);
c4af5a
dfd2c8 ··return TRUE;
1cefe6 }
aeaf5a
c4af5a
83c4bf LOCAL(boolean)
b0b9aa get_dac (j_decompress_ptr cinfo)
d80758 /* Process a DAC marker */
21bb36 {
dfa30c ··INT32 length;
73be3e ··int index, val;
f93798 ··INPUT_VARS(cinfo);
37af5a
00e6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
73fe13 ··length -= 2;
4ede7b ··
c16e5d ··while (length > 0) {
f41571 ····INPUT_BYTE(cinfo, index, return FALSE);
966e21 ····INPUT_BYTE(cinfo, val, return FALSE);
32af5a
05acca ····length -= 2;
e8af5a
7c08cb ····TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
0caf5a
c67c9b ····if (index < 0 || index >= (2*NUM_ARITH_TBLS))
27053d ······ERREXIT1(cinfo, JERR_DAC_INDEX, index);
65af5a
cd0b98 ····if (index >= NUM_ARITH_TBLS) { /* define AC table */
728e38 ······cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
1244f6 ····} else {¤   ¤   ¤   /* define DC table */
8af324 ······cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
024e60 ······cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
6b0e80 ······if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
51f43b ¤   ERREXIT1(cinfo, JERR_DAC_VALUE, val);
856fe7 ····}
e1df1c ··}
d8af5a
967a5d ··INPUT_SYNC(cinfo);
00d2c8 ··return TRUE;
d8efe6 }
48af5a
97af5a
01c4bf LOCAL(boolean)
fa8c1e get_dht (j_decompress_ptr cinfo)
06b8dd /* Process a DHT marker */
abbb36 {
d8a30c ··INT32 length;
488af0 ··UINT8 bits[17];
188ae6 ··UINT8 huffval[256];
f19a02 ··int i, index, count;
0f4916 ··JHUFF_TBL **htblptr;
673798 ··INPUT_VARS(cinfo);
ccaf5a
81e6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
52fe13 ··length -= 2;
fbde7b ··
036e5d ··while (length > 0) {
041571 ····INPUT_BYTE(cinfo, index, return FALSE);
5faf5a
e634d6 ····TRACEMS1(cinfo, 1, JTRC_DHT, index);
e2cf72 ······
ff5a95 ····bits[0] = 0;
0edfb9 ····count = 0;
26142c ····for (i = 1; i <= 16; i++) {
94413b ······INPUT_BYTE(cinfo, bits[i], return FALSE);
6e8406 ······count += bits[i];
de6fe7 ····}
--e997 000e041d8df40100028 Page 8 of jdmarker.c
e0af5a
3b67f9 ····length -= 1 + 16;
2caf5a
b41f3b ····TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
25df2a ¤   ·····bits[1], bits[2], bits[3], bits[4],
27d10c ¤   ·····bits[5], bits[6], bits[7], bits[8]);
841f3b ····TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
cd818e ¤   ·····bits[9], bits[10], bits[11], bits[12],
22fad3 ¤   ·····bits[13], bits[14], bits[15], bits[16]);
73af5a
358c37 ····if (count > 256 || ((INT32) count) > length)
e4d098 ······ERREXIT(cinfo, JERR_DHT_COUNTS);
baaf5a
c3ef11 ····for (i = 0; i < count; i++)
285e88 ······INPUT_BYTE(cinfo, huffval[i], return FALSE);
74af5a
f0a694 ····length -= count;
a6af5a
2b9590 ····if (index & 0x10) {¤¤   /* AC table definition */
384b2a ······index -= 0x10;
852d8e ······htblptr = &cinfo->ac_huff_tbl_ptrs[index];
67ef5a ····} else {¤   ¤   ¤   /* DC table definition */
8c3819 ······htblptr = &cinfo->dc_huff_tbl_ptrs[index];
236fe7 ····}
80af5a
36a378 ····if (index < 0 || index >= NUM_HUFF_TBLS)
2f7a59 ······ERREXIT1(cinfo, JERR_DHT_INDEX, index);
beaf5a
9eef61 ····if (*htblptr == NULL)
58983a ······*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
08de7b ··
670e2a ····MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
ee1c94 ····MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
87df1c ··}
f4af5a
d07a5d ··INPUT_SYNC(cinfo);
b4d2c8 ··return TRUE;
3cefe6 }
7daf5a
deaf5a
2ec4bf LOCAL(boolean)
4183ba get_dqt (j_decompress_ptr cinfo)
6fcac8 /* Process a DQT marker */
06bb36 {
3ca30c ··INT32 length;
f537de ··int n, i, prec;
89e793 ··unsigned int tmp;
71e77e ··JQUANT_TBL *quant_ptr;
7b3798 ··INPUT_VARS(cinfo);
ebaf5a
bfe6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
defe13 ··length -= 2;
08af5a
eb6e5d ··while (length > 0) {
7739f0 ····INPUT_BYTE(cinfo, n, return FALSE);
5eee79 ····prec = n >> 4;
b6c206 ····n &= 0x0F;
16af5a
5f9340 ····TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
4aaf5a
52dd16 ····if (n >= NUM_QUANT_TBLS)
00b5be ······ERREXIT1(cinfo, JERR_DQT_INDEX, n);
3fcf72 ······
002322 ····if (cinfo->quant_tbl_ptrs[n] == NULL)
691fc5 ······cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
fc3086 ····quant_ptr = cinfo->quant_tbl_ptrs[n];
1baf5a
a49ac7 ····for (i = 0; i < DCTSIZE2; i++) {
abdd79 ······if (prec)
ae1787 ¤   INPUT_2BYTES(cinfo, tmp, return FALSE);
563dfa ······else
e0f1be ¤   INPUT_BYTE(cinfo, tmp, return FALSE);
--7dfc 000cda73ef140100028 Page 9 of jdmarker.c
003a14 ······/* We convert the zigzag-order table to natural array order. */
aceea3 ······quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
6b6fe7 ····}
5baf5a
245c92 ····if (cinfo->err->trace_level >= 2) {
38ce36 ······for (i = 0; i < DCTSIZE2; i += 8) {
e3d3b2 ¤   TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
402661 ¤   ¤   ·quant_ptr->quantval[i], ··quant_ptr->quantval[i+1],
55c137 ¤   ¤   ·quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
014887 ¤   ¤   ·quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
735d93 ¤   ¤   ·quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
e542cc ······}
d06fe7 ····}
68af5a
dd2972 ····length -= DCTSIZE2+1;
2cc1a2 ····if (prec) length -= DCTSIZE2;
cddf1c ··}
71af5a
8f7a5d ··INPUT_SYNC(cinfo);
bfd2c8 ··return TRUE;
70efe6 }
b4af5a
83af5a
63c4bf LOCAL(boolean)
c84447 get_dri (j_decompress_ptr cinfo)
cc5b28 /* Process a DRI marker */
96bb36 {
5aa30c ··INT32 length;
cbe793 ··unsigned int tmp;
bb3798 ··INPUT_VARS(cinfo);
f9af5a
6be6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
ddde7b ··
47a771 ··if (length != 4)
f7cdfc ····ERREXIT(cinfo, JERR_BAD_LENGTH);
cdaf5a
038e6a ··INPUT_2BYTES(cinfo, tmp, return FALSE);
e8af5a
58257b ··TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
8faf5a
c15114 ··cinfo->restart_interval = tmp;
b0af5a
6d7a5d ··INPUT_SYNC(cinfo);
d3d2c8 ··return TRUE;
5eefe6 }
b5af5a
02af5a
749a8f METHODDEF(boolean)
8b8e97 skip_variable (j_decompress_ptr cinfo)
92703f /* Skip over an unknown or uninteresting variable-length marker */
d9bb36 {
3ea30c ··INT32 length;
2f3798 ··INPUT_VARS(cinfo);
36af5a
32e6e4 ··INPUT_2BYTES(cinfo, length, return FALSE);
b8de7b ··
e428f8 ··TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
19af5a
6e69b5 ··INPUT_SYNC(cinfo);¤   ¤   /* do before skip_input_data */
7b2513 ··(*cinfo->src->skip_input_data) (cinfo, (long) length - 2L);
99af5a
6bd2c8 ··return TRUE;
88efe6 }
e4af5a
82af5a
c638e5 /*
07741d ·* Find the next JPEG marker, save it in cinfo->unread_marker.
568cc5 ·* Returns FALSE if had to suspend before reaching a marker;
a0236a ·* in that case cinfo->unread_marker is unchanged.
bd775e ·*
3a535d ·* Note that the result might not be a valid marker code,
cdd3c7 ·* but it will never be 0 or FF.
--382a 00012aafa6040100028 Page 10 of jdmarker.c
47495d ·*/
44af5a
b8c4bf LOCAL(boolean)
06f3e4 next_marker (j_decompress_ptr cinfo)
acbb36 {
c6649a ··int c;
703798 ··INPUT_VARS(cinfo);
23af5a
056015 ··for (;;) {
acc5f7 ····INPUT_BYTE(cinfo, c, return FALSE);
321cba ····/* Skip any non-FF bytes.
72f2c5 ·····* This may look a bit inefficient, but it will not occur in a valid file.
5a2b9f ·····* We sync after each discarded byte so that a suspending data source
eba27b ·····* can discard the byte from its buffer.
61d48d ·····*/
bf5bff ····while (c != 0xFF) {
a337b8 ······cinfo->marker->discarded_bytes++;
fe651b ······INPUT_SYNC(cinfo);
39d47c ······INPUT_BYTE(cinfo, c, return FALSE);
ae6fe7 ····}
bdb81a ····/* This loop swallows any duplicate FF bytes. ·Extra FFs are legal as
839a39 ·····* pad bytes, so don't count them in discarded_bytes. ·We assume there
ee14b7 ·····* will not be so many consecutive FF bytes as to overflow a suspending
f6f4e0 ·····* data source's input buffer.
e6d48d ·····*/
bcc9a3 ····do {
aed47c ······INPUT_BYTE(cinfo, c, return FALSE);
206b41 ····} while (c == 0xFF);
96a417 ····if (c != 0)
726086 ······break;¤   ¤   ¤   /* found a valid marker, exit loop */
cc70b9 ····/* Reach here if we found a stuffed-zero data sequence (FF/00).
b2aa9f ·····* Discard it and loop back to try again.
62d48d ·····*/
475d41 ····cinfo->marker->discarded_bytes += 2;
0d7907 ····INPUT_SYNC(cinfo);
76df1c ··}
73af5a
dac838 ··if (cinfo->marker->discarded_bytes != 0) {
57c5b1 ····WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
dc09d4 ····cinfo->marker->discarded_bytes = 0;
d7df1c ··}
39af5a
0f66c8 ··cinfo->unread_marker = c;
31af5a
897a5d ··INPUT_SYNC(cinfo);
a4d2c8 ··return TRUE;
32efe6 }
bcaf5a
3aaf5a
04c4bf LOCAL(boolean)
f48510 first_marker (j_decompress_ptr cinfo)
c5e643 /* Like next_marker, but used to obtain the initial SOI marker. */
14febe /* For this marker, we do not allow preceding garbage or fill; otherwise,
6bda4d ·* we might well scan an entire input file before realizing it ain't JPEG.
5b1836 ·* If an application wants to process non-JFIF files, it must seek to the
1f7f7d ·* SOI before calling the JPEG library.
79495d ·*/
6dbb36 {
0a547a ··int c, c2;
9e3798 ··INPUT_VARS(cinfo);
bdaf5a
20d4d5 ··INPUT_BYTE(cinfo, c, return FALSE);
919e92 ··INPUT_BYTE(cinfo, c2, return FALSE);
428a54 ··if (c != 0xFF || c2 != (int) M_SOI)
5f0a37 ····ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
9faf5a
bfd61c ··cinfo->unread_marker = c2;
d0af5a
947a5d ··INPUT_SYNC(cinfo);
f1d2c8 ··return TRUE;
1defe6 }
12af5a
--25c0 000fda3e1d140100028 Page 11 of jdmarker.c
e0af5a
d338e5 /*
3b9bbf ·* Read markers until SOS or EOI.
ec775e ·*
54ea5f ·* Returns same codes as are defined for jpeg_consume_input:
b25466 ·* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
82495d ·*/
24af5a
fc4924 METHODDEF(int)
2fd8e7 read_markers (j_decompress_ptr cinfo)
6abb36 {
c13415 ··/* Outer loop repeats once for each marker. */
916015 ··for (;;) {
4f80d8 ····/* Collect the marker proper, unless we already did. */
ff6a87 ····/* NB: first_marker() enforces the requirement that SOI appear first. */
b1f672 ····if (cinfo->unread_marker == 0) {
67e8c6 ······if (! cinfo->marker->saw_SOI) {
502e7c ¤   if (! first_marker(cinfo))
83aa90 ¤   ··return JPEG_SUSPENDED;
71cfc7 ······} else {
0d8476 ¤   if (! next_marker(cinfo))
c8aa90 ¤   ··return JPEG_SUSPENDED;
0542cc ······}
8c6fe7 ····}
21f32d ····/* At this point cinfo->unread_marker contains the marker code and the
b0f7d6 ·····* input point is just past the marker proper, but before any parameters.
5e34ec ·····* A suspension will cause us to return with this state still true.
23d48d ·····*/
bc74c5 ····switch (cinfo->unread_marker) {
b0c136 ····case M_SOI:
ee535e ······if (! get_soi(cinfo))
0e6030 ¤   return JPEG_SUSPENDED;
f688e1 ······break;
35af5a
b3b49c ····case M_SOF0:¤   ¤   /* Baseline */
177f59 ····case M_SOF1:¤   ¤   /* Extended sequential, Huffman */
dd4e9b ······if (! get_sof(cinfo, FALSE, FALSE))
0e6030 ¤   return JPEG_SUSPENDED;
7c88e1 ······break;
77af5a
93d42e ····case M_SOF2:¤   ¤   /* Progressive, Huffman */
74bf99 ······if (! get_sof(cinfo, TRUE, FALSE))
f56030 ¤   return JPEG_SUSPENDED;
4e88e1 ······break;
56af5a
5e9b87 ····case M_SOF9:¤   ¤   /* Extended sequential, arithmetic */
2ced51 ······if (! get_sof(cinfo, FALSE, TRUE))
0b6030 ¤   return JPEG_SUSPENDED;
4e88e1 ······break;
97af5a
f5f1d5 ····case M_SOF10:¤  ¤   /* Progressive, arithmetic */
eb50c7 ······if (! get_sof(cinfo, TRUE, TRUE))
976030 ¤   return JPEG_SUSPENDED;
f288e1 ······break;
fbaf5a
602460 ····/* Currently unsupported SOFn types */
301bff ····case M_SOF3:¤   ¤   /* Lossless, Huffman */
9c167c ····case M_SOF5:¤   ¤   /* Differential sequential, Huffman */
8ca7cc ····case M_SOF6:¤   ¤   /* Differential progressive, Huffman */
e86e99 ····case M_SOF7:¤   ¤   /* Differential lossless, Huffman */
15f16d ····case M_JPG:¤¤   ¤   /* Reserved for JPEG extensions */
142278 ····case M_SOF11:¤  ¤   /* Lossless, arithmetic */
fa7b15 ····case M_SOF13:¤  ¤   /* Differential sequential, arithmetic */
31e98b ····case M_SOF14:¤  ¤   /* Differential progressive, arithmetic */
9f255c ····case M_SOF15:¤  ¤   /* Differential lossless, arithmetic */
3c7de1 ······ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
6388e1 ······break;
a5af5a
af37d9 ····case M_SOS:
0cb06b ······if (! get_sos(cinfo))
196030 ¤   return JPEG_SUSPENDED;
fdff7e ······cinfo->unread_marker = 0;¤/* processed the marker */
--2b56 000e1c1d1bb40100028 Page 12 of jdmarker.c
8c2003 ······return JPEG_REACHED_SOS;
d4869e ····
774eee ····case M_EOI:
d939ad ······TRACEMS(cinfo, 1, JTRC_EOI);
3aff7e ······cinfo->unread_marker = 0;¤/* processed the marker */
e25934 ······return JPEG_REACHED_EOI;
aecf72 ······
559892 ····case M_DAC:
52bca4 ······if (! get_dac(cinfo))
e26030 ¤   return JPEG_SUSPENDED;
f888e1 ······break;
fdcf72 ······
ec6861 ····case M_DHT:
504338 ······if (! get_dht(cinfo))
736030 ¤   return JPEG_SUSPENDED;
0088e1 ······break;
47cf72 ······
be52a3 ····case M_DQT:
b2db46 ······if (! get_dqt(cinfo))
9b6030 ¤   return JPEG_SUSPENDED;
7188e1 ······break;
14cf72 ······
240d84 ····case M_DRI:
350235 ······if (! get_dri(cinfo))
946030 ¤   return JPEG_SUSPENDED;
e588e1 ······break;
08cf72 ······
18906e ····case M_APP0:
d5cab2 ····case M_APP1:
af25d6 ····case M_APP2:
447f0a ····case M_APP3:
f5f30f ····case M_APP4:
79a9d3 ····case M_APP5:
6f46b7 ····case M_APP6:
311c6b ····case M_APP7:
5e56ac ····case M_APP8:
3e0c70 ····case M_APP9:
20fcd1 ····case M_APP10:
c0a60d ····case M_APP11:
294969 ····case M_APP12:
bf13b5 ····case M_APP13:
469fb0 ····case M_APP14:
11c56c ····case M_APP15:
31c756 ······if (! (*cinfo->marker->process_APPn[cinfo->unread_marker - (int) M_APP0])¶
3be70b ·(cinfo))
816030 ¤   return JPEG_SUSPENDED;
d688e1 ······break;
8acf72 ······
a21617 ····case M_COM:
f63790 ······if (! (*cinfo->marker->process_COM) (cinfo))
2c6030 ¤   return JPEG_SUSPENDED;
1e88e1 ······break;
efaf5a
9210c4 ····case M_RST0:¤   ¤   /* these are all parameterless */
8deb5f ····case M_RST1:
a0043b ····case M_RST2:
ff5ee7 ····case M_RST3:
ddd2e2 ····case M_RST4:
22883e ····case M_RST5:
82675a ····case M_RST6:
593d86 ····case M_RST7:
854e25 ····case M_TEM:
42514c ······TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
c588e1 ······break;
fcaf5a
5b56be ····case M_DNL:¤¤   ¤   /* Ignore DNL ... perhaps the wrong thing */
1a20fe ······if (! skip_variable(cinfo))
136030 ¤   return JPEG_SUSPENDED;
af88e1 ······break;
beaf5a
6dab44 ····default:¤   ¤   ¤   /* must be DHP, EXP, JPGn, or RESn */
e119ff ······/* For now, we treat the reserved markers as fatal errors since they are
--53a3 000bdf4ec0540100028 Page 13 of jdmarker.c
9fe20f ·······* likely to be used to signal incompatible JPEG Part 3 extensions.
84ae53 ·······* Once the JPEG 3 version-number marker is well defined, this code
71a5bf ·······* ought to change!
f2e9f1 ·······*/
e39fe3 ······ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
ad88e1 ······break;
3c6fe7 ····}
773fec ····/* Successfully processed marker, so reset state variable */
ac9daa ····cinfo->unread_marker = 0;
5e9c3d ··} /* end loop */
d3efe6 }
bbaf5a
f3af5a
f738e5 /*
d00a10 ·* Read a restart marker, which is expected to appear next in the datastream;
e5cdf4 ·* if the marker is not there, take appropriate recovery action.
e9111b ·* Returns FALSE if suspension is required.
1a775e ·*
3dc2b8 ·* This is called by the entropy decoder after it has read an appropriate
c8163b ·* number of MCUs. ·cinfo->unread_marker may be nonzero if the entropy decoder
e4fba7 ·* has already read a marker from the data source. ·Under normal conditions
5390bd ·* cinfo->unread_marker will be reset to 0 before returning; if not reset,
472409 ·* it holds a marker which the decoder will be unable to read past.
a3495d ·*/
c7af5a
b89a8f METHODDEF(boolean)
f8d0f0 read_restart_marker (j_decompress_ptr cinfo)
4cbb36 {
9b5939 ··/* Obtain a marker unless we already did. */
3e135f ··/* Note that next_marker will complain if it skips any data. */
017f8a ··if (cinfo->unread_marker == 0) {
7c86c0 ····if (! next_marker(cinfo))
85c39d ······return FALSE;
cedf1c ··}
14af5a
e83fcd ··if (cinfo->unread_marker ==
fa87b7 ······((int) M_RST0 + cinfo->marker->next_restart_num)) {
62f733 ····/* Normal case --- swallow the marker and let entropy decoder continue */
ce02ba ····TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
a19daa ····cinfo->unread_marker = 0;
5449d8 ··} else {
b86ee5 ····/* Uh-oh, the restart markers have been messed up. */
b2493a ····/* Let the data source manager determine how to resync. */
9ab098 ····if (! (*cinfo->src->resync_to_restart) (cinfo,
b06536 ¤   ¤   ¤   ¤   ¤   ····cinfo->marker->next_restart_num))
20c39d ······return FALSE;
efdf1c ··}
29af5a
eb22eb ··/* Update next-restart state */
7e0a84 ··cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
fbaf5a
eed2c8 ··return TRUE;
f0efe6 }
dfaf5a
34af5a
7938e5 /*
db9000 ·* This is the default resync_to_restart method for data source managers
c3d67f ·* to use if they don't have any better approach. ·Some data source managers
bdeba7 ·* may be able to back up, or may have additional knowledge about the data
aa9619 ·* which permits a more intelligent recovery strategy; such managers would
8b6db7 ·* presumably supply their own resync method.
fa775e ·*
67b962 ·* read_restart_marker calls resync_to_restart if it finds a marker other than
e033dc ·* the restart marker it was expecting. ·(This code is *not* used unless
3c5984 ·* a nonzero restart interval has been declared.) ·cinfo->unread_marker is
14d0fd ·* the marker code actually found (might be anything, except 0 or FF).
972541 ·* The desired restart marker number (0..7) is passed as a parameter.
d9e667 ·* This routine is supposed to apply whatever error recovery strategy seems
4312c3 ·* appropriate in order to position the input stream to the next data segment.
19927a ·* Note that cinfo->unread_marker is treated as a marker appearing before
8c3b7e ·* the current data-source input point; usually it should be reset to zero
bd7c0d ·* before returning.
--98f7 0000df3b14e40100028 Page 14 of jdmarker.c
19111b ·* Returns FALSE if suspension is required.
09775e ·*
cc86c4 ·* This implementation is substantially constrained by wanting to treat the
203f16 ·* input as a data stream; this means we can't back up. ·Therefore, we have
db7692 ·* only the following actions to work with:
ec97e5 ·* ··1. Simply discard the marker and let the entropy decoder resume at next
1b98ab ·* ·····byte of file.
7514a8 ·* ··2. Read forward until we find another marker, discarding intervening
4419fd ·* ·····data. ·(In theory we could look ahead within the current bufferload,
ae3840 ·* ·····without having to discard data if we don't find the desired marker.
5f5bcd ·* ·····This idea is not implemented here, in part because it makes behavior
4eb69e ·* ·····dependent on buffer size and chance buffer-boundary positions.)
f00ff0 ·* ··3. Leave the marker unread (by failing to zero cinfo->unread_marker).
c600d3 ·* ·····This will cause the entropy decoder to process an empty data segment,
e6ac89 ·* ·····inserting dummy zeroes, and then we will reprocess the marker.
22775e ·*
541eed ·* #2 is appropriate if we think the desired marker lies ahead, while #3 is
645e58 ·* appropriate if the found marker is a future restart marker (indicating
ff6c9c ·* that we have missed the desired restart marker, probably because it got
96d676 ·* corrupted).
26a065 ·* We apply #2 or #3 if the found marker is a restart marker no more than
33087d ·* two counts behind or ahead of the expected one. ·We also apply #2 if the
819fcb ·* found marker is not a legal JPEG marker code (it's certainly bogus data).
af3a2a ·* If the found marker is a restart marker more than 2 counts away, we do #1
a79517 ·* (too much risk that the marker is erroneous; with luck we will be able to
acc7eb ·* resync at some future point).
f65a04 ·* For any valid non-restart JPEG marker, we apply #3. ·This keeps us from
376cb1 ·* overrunning the end of a scan. ·An implementation limited to single-scan
35d172 ·* files might find it better to apply #2 for markers other than EOI, since
9d74e7 ·* any other marker would have to be bogus data in that case.
7a495d ·*/
54af5a
3ee553 GLOBAL(boolean)
b449cd jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
8fbb36 {
495c12 ··int marker = cinfo->unread_marker;
6e5654 ··int action = 1;
44de7b ··
68a149 ··/* Always put up a warning. */
b1b5e2 ··WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
48de7b ··
e94d7e ··/* Outer loop handles repeated decision after scanning forward. */
b86015 ··for (;;) {
79c62e ····if (marker < (int) M_SOF0)
f1f696 ······action = 2;¤  ¤   /* invalid marker */
783044 ····else if (marker < (int) M_RST0 || marker > (int) M_RST7)
d3f412 ······action = 3;¤  ¤   /* valid non-restart marker */
ba83c8 ····else {
b95c1c ······if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
ddf936 ¤   ··marker == ((int) M_RST0 + ((desired+2) & 7)))
e16f49 ¤   action = 3;¤¤   /* one of the next two expected restarts */
f9a227 ······else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
04a780 ¤   ·······marker == ((int) M_RST0 + ((desired-2) & 7)))
ecd0db ¤   action = 2;¤¤   /* a prior restart, so advance */
0a3dfa ······else
7d71fa ¤   action = 1;¤¤   /* desired restart or too far away */
786fe7 ····}
d91a67 ····TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
c546ff ····switch (action) {
8d15cd ····case 1:
a4f8a9 ······/* Discard marker and let entropy decoder resume processing. */
57eabd ······cinfo->unread_marker = 0;
6879a5 ······return TRUE;
09faa9 ····case 2:
956842 ······/* Scan to the next marker, and repeat the decision loop. */
2bf1d7 ······if (! next_marker(cinfo))
74a230 ¤   return FALSE;
56b8c0 ······marker = cinfo->unread_marker;
f388e1 ······break;
3ea075 ····case 3:
5712df ······/* Return without advancing past this marker. */
0d83b1 ······/* Entropy decoder will be forced to process an empty segment. */
--cfe0 0013f71e24840100028 Page 15 of jdmarker.c
1d79a5 ······return TRUE;
246fe7 ····}
539c3d ··} /* end loop */
cbefe6 }
6daf5a
b5af5a
4b38e5 /*
04511f ·* Reset marker processing state to begin a fresh datastream.
47495d ·*/
b2af5a
a80434 METHODDEF(void)
526f59 reset_marker_reader (j_decompress_ptr cinfo)
67bb36 {
52f83a ··cinfo->comp_info = NULL;¤ ¤   /* until allocated by get_sof */
7c55d9 ··cinfo->input_scan_number = 0;¤¤   /* no SOS seen yet */
889570 ··cinfo->unread_marker = 0;¤¤   /* no pending marker */
5fa07c ··cinfo->marker->saw_SOI = FALSE;¤  /* set internal state too */
d3d8f7 ··cinfo->marker->saw_SOF = FALSE;
9918f6 ··cinfo->marker->discarded_bytes = 0;
36efe6 }
68af5a
01af5a
2f38e5 /*
1efce6 ·* Initialize the marker reader module.
6dc5b3 ·* This is called only once, when the decompression object is created.
e8495d ·*/
68af5a
31f898 GLOBAL(void)
064b06 jinit_marker_reader (j_decompress_ptr cinfo)
45bb36 {
6d17e0 ··int i;
2baf5a
d6b606 ··/* Create subobject in permanent pool */
03ea84 ··cinfo->marker = (struct jpeg_marker_reader *)
e12142 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
72e82a ¤   ¤   ¤   ¤   SIZEOF(struct jpeg_marker_reader));
f4a3de ··/* Initialize method pointers */
7ceeeb ··cinfo->marker->reset_marker_reader = reset_marker_reader;
ad5077 ··cinfo->marker->read_markers = read_markers;
4f3acf ··cinfo->marker->read_restart_marker = read_restart_marker;
5b1c32 ··cinfo->marker->process_COM = skip_variable;
c1bebe ··for (i = 0; i < 16; i++)
fe7369 ····cinfo->marker->process_APPn[i] = skip_variable;
d1a21f ··cinfo->marker->process_APPn[0] = get_app0;
fa491a ··cinfo->marker->process_APPn[14] = get_app14;
d817e3 ··/* Reset marker processing state */
85a4f0 ··reset_marker_reader(cinfo);
3fefe6 }
--78c1 0009af3e10840100029 Page 1 of jdmaster.c
bc38e5 /*
2a7d6c ·* jdmaster.c
c0775e ·*
6ca060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
21fb07 ·* This file is part of the Independent JPEG Group's software.
14a0d6 ·* For conditions of distribution and use, see the accompanying README file.
14775e ·*
901c99 ·* This file contains master control logic for the JPEG decompressor.
559a56 ·* These routines are concerned with selecting the modules to be executed
975ec4 ·* and with determining the number of passes and the work to be done in each
80bf83 ·* pass.
3c495d ·*/
16af5a
e42bb6 #define JPEG_INTERNALS
a836a7 #include "jinclude.h"
d36c8f #include "jpeglib.h"
a7af5a
0faf5a
8fc632 /* Private state */
95af5a
28f0f7 typedef struct {
cc95b3 ··struct jpeg_decomp_master pub; /* public fields */
c5af5a
a43cb0 ··int pass_number;¤ ¤   /* # of passes completed */
cbaf5a
a0c4fb ··boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
73af5a
21b4d8 ··/* Saved references to initialized quantizer modules,
822da9 ···* in case we need to switch modes.
22f9a6 ···*/
fd7ada ··struct jpeg_color_quantizer * quantizer_1pass;
85d2b4 ··struct jpeg_color_quantizer * quantizer_2pass;
49f9e2 } my_decomp_master;
f3af5a
97a6d4 typedef my_decomp_master * my_master_ptr;
e9af5a
4faf5a
4138e5 /*
bc722c ·* Determine whether merged upsample/color conversion should be used.
9b74d0 ·* CRUCIAL: this must match the actual capabilities of jdmerge.c!
d0495d ·*/
ebaf5a
f5c4bf LOCAL(boolean)
6fb138 use_merged_upsample (j_decompress_ptr cinfo)
4cbb36 {
4c55e7 #ifdef UPSAMPLE_MERGING_SUPPORTED
bd7cb0 ··/* Merging is the equivalent of plain box-filter upsampling */
07bcaf ··if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
f730cb ····return FALSE;
3f5a0f ··/* jdmerge.c only supports YCC=>RGB color conversion */
4c3bf2 ··if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
b0dd8a ······cinfo->out_color_space != JCS_RGB ||
f63c9b ······cinfo->out_color_components != RGB_PIXELSIZE)
ac30cb ····return FALSE;
d6ce25 ··/* and it only handles 2h1v or 2h2v sampling ratios */
f73f89 ··if (cinfo->comp_info[0].h_samp_factor != 2 ||
48dd0e ······cinfo->comp_info[1].h_samp_factor != 1 ||
dbd183 ······cinfo->comp_info[2].h_samp_factor != 1 ||
04a60c ······cinfo->comp_info[0].v_samp_factor > ·2 ||
b19534 ······cinfo->comp_info[1].v_samp_factor != 1 ||
b5532f ······cinfo->comp_info[2].v_samp_factor != 1)
0d30cb ····return FALSE;
6fd666 ··/* furthermore, it doesn't work if we've scaled the IDCTs differently */
3f974a ··if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
036fb2 ······cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size ||
444ec9 ······cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size)
4430cb ····return FALSE;
e436f6 ··/* ??? also need to test for upsample-time rescaling, when & if supported */
c3948c ··return TRUE;¤ ¤   ¤   /* by golly, it'll work... */
75db21 #else
777bd5 ··return FALSE;
9a7454 #endif
--18ef 000e643d10540100029 Page 2 of jdmaster.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
37f31c ·* Compute output image dimensions and related values.
2ecc02 ·* NOTE: this is exported for possible use by application.
006aff ·* Hence it mustn't do anything that can't be done twice.
36fa5b ·* Also note that it may be called before the master module is initialized!
ec495d ·*/
a8af5a
34f898 GLOBAL(void)
c76c03 jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
7c9ba1 /* Do computations that are needed before master selection phase */
e6bb36 {
ef0dcc ··int ci;
c333b0 ··jpeg_component_info *compptr;
44af5a
dc752c ··/* Prevent application from calling me at wrong times */
158cf5 ··if (cinfo->global_state != DSTATE_READY)
f3918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
28af5a
6125de #ifdef IDCT_SCALING_SUPPORTED
6baf5a
eac834 ··/* Compute actual output image dimensions and DCT scaling choices. */
3530a6 ··if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
bdbd62 ····/* Provide 1/8 scaling */
1c0f60 ····cinfo->output_width = (JDIMENSION)
5ac656 ······jdiv_round_up((long) cinfo->image_width, 8L);
21ea0a ····cinfo->output_height = (JDIMENSION)
7c785b ······jdiv_round_up((long) cinfo->image_height, 8L);
25dd30 ····cinfo->min_DCT_scaled_size = 1;
28d4f4 ··} else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
e786be ····/* Provide 1/4 scaling */
dd0f60 ····cinfo->output_width = (JDIMENSION)
37b166 ······jdiv_round_up((long) cinfo->image_width, 4L);
50ea0a ····cinfo->output_height = (JDIMENSION)
6e0f6b ······jdiv_round_up((long) cinfo->image_height, 4L);
5d3254 ····cinfo->min_DCT_scaled_size = 2;
9e3155 ··} else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
579b50 ····/* Provide 1/2 scaling */
350f60 ····cinfo->output_width = (JDIMENSION)
418afe ······jdiv_round_up((long) cinfo->image_width, 2L);
a6ea0a ····cinfo->output_height = (JDIMENSION)
6434f3 ······jdiv_round_up((long) cinfo->image_height, 2L);
b9e48d ····cinfo->min_DCT_scaled_size = 4;
fe49d8 ··} else {
4a95a7 ····/* Provide 1/1 scaling */
28b796 ····cinfo->output_width = cinfo->image_width;
3b5d73 ····cinfo->output_height = cinfo->image_height;
f49e17 ····cinfo->min_DCT_scaled_size = DCTSIZE;
24df1c ··}
6f261d ··/* In selecting the actual DCT scaling for each component, we try to
0b2779 ···* scale up the chroma components via IDCT scaling rather than upsampling.
78ab4d ···* This saves time if the upsampler gets to use 1:1 scaling.
a88d59 ···* Note this code assumes that the supported DCT scalings are powers of 2.
75f9a6 ···*/
fe958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
1aaa07 ·······ci++, compptr++) {
848961 ····int ssize = cinfo->min_DCT_scaled_size;
f86c33 ····while (ssize < DCTSIZE &&
d400c0 ¤   ···(compptr->h_samp_factor * ssize * 2 <=
bd1b14 ¤   ····cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) &&
0d1c54 ¤   ···(compptr->v_samp_factor * ssize * 2 <=
541eab ¤   ····cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) {
d580cd ······ssize = ssize * 2;
926fe7 ····}
77e827 ····compptr->DCT_scaled_size = ssize;
6bdf1c ··}
1eaf5a
3c4712 ··/* Recompute downsampled dimensions of components;
6d94f4 ···* application needs to know these if using raw downsampled data.
e6f9a6 ···*/
--d51b 000b2e0fab940100029 Page 3 of jdmaster.c
25958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
6aaa07 ·······ci++, compptr++) {
ffec27 ····/* Size in samples, after IDCT scaling */
fcb513 ····compptr->downsampled_width = (JDIMENSION)
196d61 ······jdiv_round_up((long) cinfo->image_width *
394a04 ¤   ¤   ····(long) (compptr->h_samp_factor * compptr->DCT_scaled_size),
28d601 ¤   ¤   ····(long) (cinfo->max_h_samp_factor * DCTSIZE));
f6abac ····compptr->downsampled_height = (JDIMENSION)
b01857 ······jdiv_round_up((long) cinfo->image_height *
2188b8 ¤   ¤   ····(long) (compptr->v_samp_factor * compptr->DCT_scaled_size),
6cbd17 ¤   ¤   ····(long) (cinfo->max_v_samp_factor * DCTSIZE));
8bdf1c ··}
a1af5a
3b4ed0 #else /* !IDCT_SCALING_SUPPORTED */
96af5a
a920b4 ··/* Hardwire it to "no scaling" */
d385a4 ··cinfo->output_width = cinfo->image_width;
f7caf0 ··cinfo->output_height = cinfo->image_height;
0bc630 ··/* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
b5cc46 ···* and has computed unscaled downsampled_width and downsampled_height.
72f9a6 ···*/
8faf5a
df5a53 #endif /* IDCT_SCALING_SUPPORTED */
35af5a
c11864 ··/* Report number of components in selected colorspace. */
d84824 ··/* Probably this should be in the color conversion module... */
aba765 ··switch (cinfo->out_color_space) {
0db88c ··case JCS_GRAYSCALE:
2b1dbf ····cinfo->out_color_components = 1;
88ab40 ····break;
e9b3fb ··case JCS_RGB:
aede55 #if RGB_PIXELSIZE != 3
cf25b7 ····cinfo->out_color_components = RGB_PIXELSIZE;
afab40 ····break;
78cf19 #endif /* else share code with YCbCr */
8818bb ··case JCS_YCbCr:
b6a807 ····cinfo->out_color_components = 3;
ddab40 ····break;
db8394 ··case JCS_CMYK:
84969d ··case JCS_YCCK:
1e2402 ····cinfo->out_color_components = 4;
fbab40 ····break;
1278b2 ··default:¤ ¤   ¤   /* else must be same colorspace as in file */
afb510 ····cinfo->out_color_components = cinfo->num_components;
dfab40 ····break;
a6df1c ··}
de681a ··cinfo->output_components = (cinfo->quantize_colors ? 1 :
5baae8 ¤   ¤   ¤   ······cinfo->out_color_components);
1faf5a
3199ac ··/* See if upsampler will want to emit more than one row at a time */
5b50bc ··if (use_merged_upsample(cinfo))
4e4bf6 ····cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
da1bd0 ··else
ee1280 ····cinfo->rec_outbuf_height = 1;
5cefe6 }
27af5a
2aaf5a
aa38e5 /*
b1be37 ·* Several decompression processes need to range-limit values to the range
440325 ·* 0..MAXJSAMPLE; the input value may fall somewhat outside this range
b693cb ·* due to noise introduced by quantization, roundoff error, etc. ·These
683b0d ·* processes are inner loops and need to be as fast as possible. ·On most
566d2a ·* machines, particularly CPUs with pipelines or instruction prefetch,
9a7b29 ·* a (subscript-check-less) C table lookup
603c58 ·*¤ ¤   x = sample_range_limit[x];
305299 ·* is faster than explicit tests
b98fb6 ·*¤ ¤   if (x < 0) ·x = 0;
cffd27 ·*¤ ¤   else if (x > MAXJSAMPLE) ·x = MAXJSAMPLE;
705964 ·* These processes all use a common table prepared by the routine below.
1e775e ·*
5cdd3c ·* For most steps we can mathematically guarantee that the initial value
b249e3 ·* of x is within MAXJSAMPLE+1 of the legal range, so a table running from
--a97c 000b19d34a540100029 Page 4 of jdmaster.c
334542 ·* -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. ·But for the initial
17a026 ·* limiting step (just after the IDCT), a wildly out-of-range value is·
3bef26 ·* possible if the input data is corrupt. ·To avoid any chance of indexing
1094f1 ·* off the end of memory and getting a bad-pointer trap, we perform the
f49c4c ·* post-IDCT limiting thus:
66e448 ·*¤ ¤   x = range_limit[x & MASK];
77d052 ·* where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
0614c8 ·* samples. ·Under normal circumstances this is more than enough range and
8fb537 ·* a correct output will be generated; with bogus input data the mask will
a3ad4c ·* cause wraparound, and we will safely generate a bogus-but-in-range output.
d8b4cc ·* For the post-IDCT step, we want to convert the data from signed to unsigned
d55d94 ·* representation by adding CENTERJSAMPLE at the same time that we limit it.
092ba7 ·* So the post-IDCT limiting table ends up looking like this:
27bd1c ·* ··CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
fd18f1 ·* ··MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
d714cb ·* ··0 ·········(repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
ed11fe ·* ··0,1,...,CENTERJSAMPLE-1
a19254 ·* Negative inputs select values from the upper half of the table after
4a4e47 ·* masking.
7d775e ·*
1f647c ·* We can save some space by overlapping the start of the post-IDCT table
22696b ·* with the simpler range limiting table. ·The post-IDCT table begins at
04093a ·* sample_range_limit + CENTERJSAMPLE.
6f775e ·*
475787 ·* Note that the table is allocated in near data space on PCs; it's small
6021d5 ·* enough and used often enough to justify this.
24495d ·*/
74af5a
ceafad LOCAL(void)
7d26fa prepare_range_limit_table (j_decompress_ptr cinfo)
4b0f11 /* Allocate and fill in the sample_range_limit table */
cabb36 {
a60e27 ··JSAMPLE * table;
4417e0 ··int i;
adaf5a
4ab867 ··table = (JSAMPLE *)
913f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
10f380 ¤   ¤   (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
d29b65 ··table += (MAXJSAMPLE+1);¤ /* allow negative subscripts of simple table */
317010 ··cinfo->sample_range_limit = table;
98bfb6 ··/* First segment of "simple" table: limit[x] = 0 for x < 0 */
dd893f ··MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
48adae ··/* Main part of "simple" table: limit[x] = x */
a11f75 ··for (i = 0; i <= MAXJSAMPLE; i++)
b0fbe2 ····table[i] = (JSAMPLE) i;
ad9afc ··table += CENTERJSAMPLE;¤  /* Point to where post-IDCT table starts */
009353 ··/* End of simple table, rest of first half of post-IDCT table */
adbdb6 ··for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
5edb09 ····table[i] = MAXJSAMPLE;
8ad29d ··/* Second half of post-IDCT table */
387766 ··MEMZERO(table + (2 * (MAXJSAMPLE+1)),
318d4e ¤   ··(2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
339c1f ··MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
bfdc2d ¤   ··cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
3defe6 }
0faf5a
a6af5a
5038e5 /*
4b8787 ·* Master selection of decompression modules.
07124e ·* This is done once at jpeg_start_decompress time. ·We determine
3776d2 ·* which modules will be used and give them appropriate initialization calls.
cc9d33 ·* We also initialize the decompressor input side to begin consuming data.
2e775e ·*
4a2d80 ·* Since jpeg_read_header has finished, we know what is in the SOF
7b4514 ·* and (first) SOS markers. ·We also have all the application parameter
e5fd1f ·* settings.
6e495d ·*/
c7af5a
efafad LOCAL(void)
a268d7 master_selection (j_decompress_ptr cinfo)
4ebb36 {
b16092 ··my_master_ptr master = (my_master_ptr) cinfo->master;
--0807 000a1fcc2da40100029 Page 5 of jdmaster.c
b899ea ··boolean use_c_buffer;
e5d8ed ··long samplesperrow;
3e5021 ··JDIMENSION jd_samplesperrow;
9daf5a
c71608 ··/* Initialize dimensions and other stuff */
6ff8a0 ··jpeg_calc_output_dimensions(cinfo);
e2b991 ··prepare_range_limit_table(cinfo);
26af5a
bdda4b ··/* Width of an output scanline must be representable as JDIMENSION. */
c3be4c ··samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_componen¶
a8ba45 ts;
047929 ··jd_samplesperrow = (JDIMENSION) samplesperrow;
53e8a0 ··if ((long) jd_samplesperrow != samplesperrow)
427d39 ····ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
07af5a
be29d0 ··/* Initialize my private state */
dcd487 ··master->pass_number = 0;
c1dd69 ··master->using_merged_upsample = use_merged_upsample(cinfo);
93af5a
e9f652 ··/* Color quantizer selection */
33561a ··master->quantizer_1pass = NULL;
91d524 ··master->quantizer_2pass = NULL;
aca6e6 ··/* No mode changes if not using buffered-image mode. */
9593f5 ··if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
1a0c66 ····cinfo->enable_1pass_quant = FALSE;
a9582e ····cinfo->enable_external_quant = FALSE;
6555d2 ····cinfo->enable_2pass_quant = FALSE;
0adf1c ··}
a2a6cf ··if (cinfo->quantize_colors) {
38c6d6 ····if (cinfo->raw_data_out)
9dcedf ······ERREXIT(cinfo, JERR_NOTIMPL);
5eff93 ····/* 2-pass quantizer only works in 3-component color space. */
ed55aa ····if (cinfo->out_color_components != 3) {
83d7de ······cinfo->enable_1pass_quant = TRUE;
c63142 ······cinfo->enable_external_quant = FALSE;
6c57d3 ······cinfo->enable_2pass_quant = FALSE;
fb4600 ······cinfo->colormap = NULL;
595808 ····} else if (cinfo->colormap != NULL) {
020100 ······cinfo->enable_external_quant = TRUE;
9eaebf ····} else if (cinfo->two_pass_quantize) {
f4be35 ······cinfo->enable_2pass_quant = TRUE;
7c6a79 ····} else {
1dd7de ······cinfo->enable_1pass_quant = TRUE;
ed6fe7 ····}
82af5a
46bd6f ····if (cinfo->enable_1pass_quant) {
11d7d7 #ifdef QUANT_1PASS_SUPPORTED
2695f4 ······jinit_1pass_quantizer(cinfo);
0f32d8 ······master->quantizer_1pass = cinfo->cquantize;
9edb21 #else
959015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
d87454 #endif
a26fe7 ····}
4eaf5a
9ac7b6 ····/* We use the 2-pass code to map to external colormaps. */
8dc8dc ····if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
d14df6 #ifdef QUANT_2PASS_SUPPORTED
097838 ······jinit_2pass_quantizer(cinfo);
476d39 ······master->quantizer_2pass = cinfo->cquantize;
9bdb21 #else
5f9015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
887454 #endif
4a6fe7 ····}
d2f5f6 ····/* If both quantizers are initialized, the 2-pass one is left active;
b53fd1 ·····* this is necessary for starting with quantization to an external map.
86d48d ·····*/
55df1c ··}
13af5a
11beaf ··/* Post-processing: in particular, color conversion first */
61d207 ··if (! cinfo->raw_data_out) {
a10ad4 ····if (master->using_merged_upsample) {
a155e7 #ifdef UPSAMPLE_MERGING_SUPPORTED
--e3ea 00034d0393240100029 Page 6 of jdmaster.c
ba7a12 ······jinit_merged_upsampler(cinfo); /* does color conversion too */
6ddb21 #else
b09015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
5d7454 #endif
736a79 ····} else {
eb5493 ······jinit_color_deconverter(cinfo);
5138fb ······jinit_upsampler(cinfo);
446fe7 ····}
a50386 ····jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
84df1c ··}
ad749e ··/* Inverse DCT */
c058ce ··jinit_inverse_dct(cinfo);
2f62ed ··/* Entropy decoding: either Huffman or arithmetic coding. */
10a4f1 ··if (cinfo->arith_code) {
1e3fef ····ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
e149d8 ··} else {
8b8aef ····if (cinfo->progressive_mode) {
3fe060 #ifdef D_PROGRESSIVE_SUPPORTED
09f895 ······jinit_phuff_decoder(cinfo);
7bdb21 #else
f69015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
4b7454 #endif
cece75 ····} else
dfb69e ······jinit_huff_decoder(cinfo);
47df1c ··}
28af5a
824801 ··/* Initialize principal buffer controllers. */
f211a0 ··use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
abcdce ··jinit_d_coef_controller(cinfo, use_c_buffer);
cbaf5a
3d627c ··if (! cinfo->raw_data_out)
18f08a ····jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
d5af5a
b45924 ··/* We can now tell the memory manager to allocate virtual arrays. */
65a9b1 ··(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
f5af5a
8bab3e ··/* Initialize input side of decompressor to consume first scan. */
f51eb6 ··(*cinfo->inputctl->start_input_pass) (cinfo);
c1af5a
04a01c #ifdef D_MULTISCAN_FILES_SUPPORTED
d55ef1 ··/* If jpeg_start_decompress will read the whole file, initialize
be53bd ···* progress monitoring appropriately. ·The input step is counted
9f1574 ···* as one pass.
8bf9a6 ···*/
6c2f01 ··if (cinfo->progress != NULL && ! cinfo->buffered_image &&
a74428 ······cinfo->inputctl->has_multiple_scans) {
83cbad ····int nscans;
9e5648 ····/* Estimate number of scans to set pass_limit. */
568aef ····if (cinfo->progressive_mode) {
dad25e ······/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
6f6f32 ······nscans = 2 + 3 * cinfo->num_components;
356a79 ····} else {
6fc6b7 ······/* For a nonprogressive multiscan file, estimate 1 scan per component. */
5907c0 ······nscans = cinfo->num_components;
4d6fe7 ····}
4e4747 ····cinfo->progress->pass_counter = 0L;
e6f6fd ····cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
a359b9 ····cinfo->progress->completed_passes = 0;
6856ed ····cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
a6e54f ····/* Count the input pass as done */
dcb3e4 ····master->pass_number++;
6edf1c ··}
6f44d7 #endif /* D_MULTISCAN_FILES_SUPPORTED */
c7efe6 }
abaf5a
80af5a
df38e5 /*
b9df1f ·* Per-pass setup.
bc873e ·* This is called at the beginning of each output pass. ·We determine which
534708 ·* modules will be active during this pass and give them appropriate
ee7d6f ·* start_pass calls. ·We also set is_dummy_pass to indicate whether this
3490c2 ·* is a "real" output pass or a dummy pass for color quantization.
--8a2f 000f055edd040100029 Page 7 of jdmaster.c
42e203 ·* (In the latter case, jdapi.c will crank the pass to completion.)
ff495d ·*/
e0af5a
df0434 METHODDEF(void)
06f011 prepare_for_output_pass (j_decompress_ptr cinfo)
3fbb36 {
216092 ··my_master_ptr master = (my_master_ptr) cinfo->master;
ccaf5a
1d2b3a ··if (master->pub.is_dummy_pass) {
d44df6 #ifdef QUANT_2PASS_SUPPORTED
272d84 ····/* Final pass of 2-pass quantization */
c067c7 ····master->pub.is_dummy_pass = FALSE;
8f6a9a ····(*cinfo->cquantize->start_pass) (cinfo, FALSE);
7fade7 ····(*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
af183c ····(*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
51db21 #else
5f9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
25d24f #endif /* QUANT_2PASS_SUPPORTED */
8f49d8 ··} else {
35c3d0 ····if (cinfo->quantize_colors && cinfo->colormap == NULL) {
2abf3a ······/* Select new quantization method */
ed9da7 ······if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
817f55 ¤   cinfo->cquantize = master->quantizer_2pass;
b02d74 ¤   master->pub.is_dummy_pass = TRUE;
c09598 ······} else if (cinfo->enable_1pass_quant) {
39d73b ¤   cinfo->cquantize = master->quantizer_1pass;
10cfc7 ······} else {
1d8026 ¤   ERREXIT(cinfo, JERR_MODE_CHANGE);
5a42cc ······}
316fe7 ····}
528793 ····(*cinfo->idct->start_pass) (cinfo);
cd57b3 ····(*cinfo->coef->start_output_pass) (cinfo);
3cb64e ····if (! cinfo->raw_data_out) {
0e2d47 ······if (! master->using_merged_upsample)
eb035b ¤   (*cinfo->cconvert->start_pass) (cinfo);
d54953 ······(*cinfo->upsample->start_pass) (cinfo);
fc6afe ······if (cinfo->quantize_colors)
81db50 ¤   (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
464e30 ······(*cinfo->post->start_pass) (cinfo,
265cad ¤   ····(master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
9ca06c ······(*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
446fe7 ····}
dbdf1c ··}
02af5a
085b51 ··/* Set up progress monitor's pass info if present */
4dfeda ··if (cinfo->progress != NULL) {
9a82ae ····cinfo->progress->completed_passes = master->pass_number;
97b547 ····cinfo->progress->total_passes = master->pass_number +
ec2146 ¤   ¤   ¤   ¤   ····(master->pub.is_dummy_pass ? 2 : 1);
07ed02 ····/* In buffered-image mode, we assume one more output pass if EOI not
29fcd9 ·····* yet reached, but no more passes if EOI has been reached.
39d48d ·····*/
aed390 ····if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
88f71d ······cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
d16fe7 ····}
62df1c ··}
adefe6 }
7caf5a
5faf5a
9238e5 /*
847b32 ·* Finish up at end of an output pass.
e1495d ·*/
3baf5a
080434 METHODDEF(void)
21db3c finish_output_pass (j_decompress_ptr cinfo)
17bb36 {
786092 ··my_master_ptr master = (my_master_ptr) cinfo->master;
44af5a
50c248 ··if (cinfo->quantize_colors)
4607a8 ····(*cinfo->cquantize->finish_pass) (cinfo);
7b5538 ··master->pass_number++;
f0efe6 }
--f372 0012c88666040100029 Page 8 of jdmaster.c
e0af5a
1aaf5a
03a01c #ifdef D_MULTISCAN_FILES_SUPPORTED
a7af5a
0138e5 /*
e00d79 ·* Switch to a new external colormap between output passes.
d8495d ·*/
c1af5a
65f898 GLOBAL(void)
14b4dd jpeg_new_colormap (j_decompress_ptr cinfo)
0ebb36 {
d46092 ··my_master_ptr master = (my_master_ptr) cinfo->master;
d8af5a
4f752c ··/* Prevent application from calling me at wrong times */
345f6f ··if (cinfo->global_state != DSTATE_BUFIMAGE)
63918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
10af5a
bb34a3 ··if (cinfo->quantize_colors && cinfo->enable_external_quant &&
fa531b ······cinfo->colormap != NULL) {
8e7d14 ····/* Select 2-pass quantizer for external colormap use */
78c2b4 ····cinfo->cquantize = master->quantizer_2pass;
8c8d56 ····/* Notify quantizer of colormap change */
ab4ac5 ····(*cinfo->cquantize->new_color_map) (cinfo);
1d3c7d ····master->pub.is_dummy_pass = FALSE; /* just in case */
ee77a3 ··} else
f58c46 ····ERREXIT(cinfo, JERR_MODE_CHANGE);
fbefe6 }
b3af5a
6844d7 #endif /* D_MULTISCAN_FILES_SUPPORTED */
77af5a
b6af5a
4e38e5 /*
ab1021 ·* Initialize master decompression control and select active modules.
7f1347 ·* This is performed at the start of jpeg_start_decompress.
c7495d ·*/
70af5a
18f898 GLOBAL(void)
422a14 jinit_master_decompress (j_decompress_ptr cinfo)
2fbb36 {
61420d ··my_master_ptr master;
9eaf5a
e2cc94 ··master = (my_master_ptr)
f2558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
08d140 ¤   ¤   ¤   ¤   ··SIZEOF(my_decomp_master));
fd53ec ··cinfo->master = (struct jpeg_decomp_master *) master;
b36ff2 ··master->pub.prepare_for_output_pass = prepare_for_output_pass;
c21eab ··master->pub.finish_output_pass = finish_output_pass;
cdaf5a
01ccc6 ··master->pub.is_dummy_pass = FALSE;
52af5a
26b40a ··master_selection(cinfo);
2cefe6 }
--aded 000040dc71d4010002a Page 1 of jdmerge.c
bc38e5 /*
a277dc ·* jdmerge.c
c7775e ·*
fd9e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
a0fb07 ·* This file is part of the Independent JPEG Group's software.
39a0d6 ·* For conditions of distribution and use, see the accompanying README file.
e1775e ·*
fdef77 ·* This file contains code for merged upsampling/color conversion.
13775e ·*
7c5e69 ·* This file combines functions from jdsample.c and jdcolor.c;
42be71 ·* read those files first to understand what's going on.
f2775e ·*
47952c ·* When the chroma components are to be upsampled by simple replication
cdb8a0 ·* (ie, box filtering), we can save some work in color conversion by
eb4362 ·* calculating all the output pixels corresponding to a pair of chroma
2f6876 ·* samples at one time. ·In the conversion equations
872112 ·*¤ R = Y ··········+ K1 * Cr
9e5efb ·*¤ G = Y + K2 * Cb + K3 * Cr
77cf59 ·*¤ B = Y + K4 * Cb
8bff3e ·* only the Y term varies among the group of pixels corresponding to a pair
0e7df0 ·* of chroma samples, so the rest of the terms can be calculated just once.
8c3fe9 ·* At typical sampling ratios, this eliminates half or three-quarters of the
23c06b ·* multiplications needed for color conversion.
5e775e ·*
ebf46c ·* This file currently provides implementations for the following cases:
efa95a ·*¤ YCbCr => RGB color conversion only.
5cac20 ·*¤ Sampling ratios of 2h1v or 2h2v.
47c7a0 ·*¤ No scaling needed at upsample time.
3be8e6 ·*¤ Corner-aligned (non-CCIR601) sampling alignment.
1a4423 ·* Other special cases could be added, but in most applications these are
5f9ace ·* the only common cases. ·(For uncommon cases we fall back on the more
1d29bc ·* general code in jdsample.c and jdcolor.c.)
d8495d ·*/
deaf5a
7f2bb6 #define JPEG_INTERNALS
8636a7 #include "jinclude.h"
916c8f #include "jpeglib.h"
6caf5a
be55e7 #ifdef UPSAMPLE_MERGING_SUPPORTED
2eaf5a
efaf5a
bbdedc /* Private subobject */
b6af5a
4bf0f7 typedef struct {
036883 ··struct jpeg_upsampler pub;¤   /* public fields */
adaf5a
9f05af ··/* Pointer to routine to do actual upsampling/conversion of one row group */
7ca039 ··JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
a3c2d9 ¤   ¤   ¤   ···JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
b402ae ¤   ¤   ¤   ···JSAMPARRAY output_buf));
38af5a
457b7b ··/* Private state for YCC->RGB conversion */
5fec41 ··int * Cr_r_tab;¤  ¤   /* => table for Cr to R conversion */
445e06 ··int * Cb_b_tab;¤  ¤   /* => table for Cb to B conversion */
c5dd7c ··INT32 * Cr_g_tab;¤¤   /* => table for Cr to G conversion */
6be84f ··INT32 * Cb_g_tab;¤¤   /* => table for Cb to G conversion */
0faf5a
fb109b ··/* For 2:1 vertical sampling, we produce two output rows at a time.
aaaa56 ···* We need a "spare" row buffer to hold the second output row if the
8925e6 ···* application provides just a one-row buffer; we also use the spare
5eb70e ···* to discard the dummy last row if the image height is odd.
9df9a6 ···*/
7e405f ··JSAMPROW spare_row;
7264b1 ··boolean spare_full;¤  ¤   /* T if spare buffer is occupied */
dbaf5a
1883b1 ··JDIMENSION out_row_width;¤/* samples per output row */
43ed18 ··JDIMENSION rows_to_go;¤   /* counts rows remaining in image */
e29b02 } my_upsampler;
03af5a
6355d9 typedef my_upsampler * my_upsample_ptr;
eeaf5a
0481d9 #define SCALEBITS¤  16¤ /* speediest right-shift on some machines */
--0932 00052bbf0b74010002a Page 2 of jdmerge.c
075746 #define ONE_HALF¤   ((INT32) 1 << (SCALEBITS-1))
ac39c8 #define FIX(x)¤ ¤   ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
f1af5a
37af5a
5738e5 /*
a3f2a9 ·* Initialize tables for YCC->RGB colorspace conversion.
900fc9 ·* This is taken directly from jdcolor.c; see that file for more info.
81495d ·*/
03af5a
81afad LOCAL(void)
8e0e32 build_ycc_rgb_table (j_decompress_ptr cinfo)
e4bb36 {
d6426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
4117e0 ··int i;
bf182a ··INT32 x;
e1ea99 ··SHIFT_TEMPS
cdaf5a
a7b80e ··upsample->Cr_r_tab = (int *)
1d3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
e15b78 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(int));
83ef09 ··upsample->Cb_b_tab = (int *)
a03f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
f15b78 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(int));
f275da ··upsample->Cr_g_tab = (INT32 *)
703f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
8283d2 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(INT32));
45e867 ··upsample->Cb_g_tab = (INT32 *)
303f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
cb83d2 ¤   ¤   ¤   ¤   (MAXJSAMPLE+1) * SIZEOF(INT32));
bbaf5a
4acc39 ··for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
838598 ····/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
efc9a9 ····/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
dc65e4 ····/* Cr=>R value is nearest int to 1.40200 * x */
77a3d9 ····upsample->Cr_r_tab[i] = (int)
9154fc ¤   ¤   ····RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
6f089a ····/* Cb=>B value is nearest int to 1.77200 * x */
96d731 ····upsample->Cb_b_tab[i] = (int)
cdfeb5 ¤   ¤   ····RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
832392 ····/* Cr=>G value is scaled-up -0.71414 * x */
e16e17 ····upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
0356a5 ····/* Cb=>G value is scaled-up -0.34414 * x */
c67c96 ····/* We also add in ONE_HALF so that need not do it in inner loop */
f9e8b9 ····upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
34df1c ··}
dfefe6 }
0aaf5a
dbaf5a
5338e5 /*
e70b58 ·* Initialize for an upsampling pass.
c3495d ·*/
01af5a
9c0434 METHODDEF(void)
d28622 start_pass_merged_upsample (j_decompress_ptr cinfo)
7dbb36 {
d5426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
2daf5a
c5a638 ··/* Mark the spare buffer empty */
319197 ··upsample->spare_full = FALSE;
b0dac9 ··/* Initialize total-height counter for detecting bottom of image */
a61311 ··upsample->rows_to_go = cinfo->output_height;
a9efe6 }
19af5a
8aaf5a
6a38e5 /*
21a099 ·* Control routine to do upsampling (and color conversion).
92775e ·*
b1e107 ·* The control routine just handles the row buffering considerations.
43495d ·*/
e2af5a
b20434 METHODDEF(void)
5287f2 merged_2v_upsample (j_decompress_ptr cinfo,
--e797 0005132e2204010002a Page 3 of jdmerge.c
5680d8 ¤   ¤   ····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
11d9b2 ¤   ¤   ····JDIMENSION in_row_groups_avail,
fc4d56 ¤   ¤   ····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
754970 ¤   ¤   ····JDIMENSION out_rows_avail)
6ba0f8 /* 2:1 vertical sampling case: may need a spare row. */
d4bb36 {
3f426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
5f2817 ··JSAMPROW work_ptrs[2];
c7838b ··JDIMENSION num_rows;¤ ¤   /* number of rows returned to caller */
bdaf5a
ceeec9 ··if (upsample->spare_full) {
b8f2fa ····/* If we have a spare row saved from a previous cycle, just return it. */
892840 ····jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
5a7384 ¤   ¤   ······1, upsample->out_row_width);
3507fa ····num_rows = 1;
f94e36 ····upsample->spare_full = FALSE;
5949d8 ··} else {
abee9a ····/* Figure number of rows to return to caller. */
0de89e ····num_rows = 2;
fc8998 ····/* Not more than the distance to the end of the image. */
144676 ····if (num_rows > upsample->rows_to_go)
13a7db ······num_rows = upsample->rows_to_go;
0e3a20 ····/* And not more than what the client can accept: */
dbcdc9 ····out_rows_avail -= *out_row_ctr;
d3bc23 ····if (num_rows > out_rows_avail)
b30b7d ······num_rows = out_rows_avail;
8845bb ····/* Create output pointer array for upsampler. */
e0e95b ····work_ptrs[0] = output_buf[*out_row_ctr];
8e2c84 ····if (num_rows > 1) {
baba57 ······work_ptrs[1] = output_buf[*out_row_ctr + 1];
316a79 ····} else {
856258 ······work_ptrs[1] = upsample->spare_row;
2026e0 ······upsample->spare_full = TRUE;
a26fe7 ····}
e9bd68 ····/* Now do the upsampling. */
c504dd ····(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
b3df1c ··}
bdaf5a
614005 ··/* Adjust counts */
53c101 ··*out_row_ctr += num_rows;
722858 ··upsample->rows_to_go -= num_rows;
f70416 ··/* When the buffer is emptied, declare this input row group consumed */
693009 ··if (! upsample->spare_full)
e20916 ····(*in_row_group_ctr)++;
82efe6 }
6daf5a
a5af5a
d80434 METHODDEF(void)
784102 merged_1v_upsample (j_decompress_ptr cinfo,
8280d8 ¤   ¤   ····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
75d9b2 ¤   ¤   ····JDIMENSION in_row_groups_avail,
dc4d56 ¤   ¤   ····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
044970 ¤   ¤   ····JDIMENSION out_rows_avail)
beb3fb /* 1:1 vertical sampling case: much easier, never need a spare row. */
3abb36 {
61426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
2eaf5a
635b0d ··/* Just do the upsampling. */
f1343f ··(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
f2641b ¤   ¤   ¤   ·output_buf + *out_row_ctr);
4e4005 ··/* Adjust counts */
97c33a ··(*out_row_ctr)++;
bbefca ··(*in_row_group_ctr)++;
b1efe6 }
08af5a
0caf5a
f538e5 /*
b52d99 ·* These are the routines invoked by the control routines to do
25ae8a ·* the actual upsampling/conversion. ·One row group is processed per call.
2d775e ·*
f93fe1 ·* Note: since we may be writing directly into application-supplied buffers,
51af1d ·* we have to be honest about the output width; we can't assume the buffer
--c417 00060092b7c4010002a Page 4 of jdmerge.c
49c60a ·* has been rounded up to an even width.
b3495d ·*/
60af5a
9caf5a
9638e5 /*
c3f5bb ·* Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
22495d ·*/
b1af5a
610434 METHODDEF(void)
3e9cfe h2v1_merged_upsample (j_decompress_ptr cinfo,
331637 ¤   ¤   ······JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
4b8f25 ¤   ¤   ······JSAMPARRAY output_buf)
00bb36 {
1e426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
b0d4ac ··register int y, cred, cgreen, cblue;
de2351 ··int cb, cr;
5baf23 ··register JSAMPROW outptr;
ea2525 ··JSAMPROW inptr0, inptr1, inptr2;
5f0f73 ··JDIMENSION col;
54f430 ··/* copy these pointers into registers if possible */
45ba42 ··register JSAMPLE * range_limit = cinfo->sample_range_limit;
0bc296 ··int * Crrtab = upsample->Cr_r_tab;
210532 ··int * Cbbtab = upsample->Cb_b_tab;
2db26e ··INT32 * Crgtab = upsample->Cr_g_tab;
1eccd6 ··INT32 * Cbgtab = upsample->Cb_g_tab;
c9ea99 ··SHIFT_TEMPS
37af5a
71c989 ··inptr0 = input_buf[0][in_row_group_ctr];
6bcc9b ··inptr1 = input_buf[1][in_row_group_ctr];
13c3ad ··inptr2 = input_buf[2][in_row_group_ctr];
f43010 ··outptr = output_buf[0];
af618d ··/* Loop for each pair of output pixels */
063d77 ··for (col = cinfo->output_width >> 1; col > 0; col--) {
ca8b0b ····/* Do the chroma part of the calculation */
af342e ····cb = GETJSAMPLE(*inptr1++);
1e3486 ····cr = GETJSAMPLE(*inptr2++);
6dae49 ····cred = Crrtab[cr];
7748f1 ····cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
8d6754 ····cblue = Cbbtab[cb];
1a3f40 ····/* Fetch 2 Y values and emit 2 pixels */
f1b33d ····y ·= GETJSAMPLE(*inptr0++);
89487f ····outptr[RGB_RED] = ··range_limit[y + cred];
19bf42 ····outptr[RGB_GREEN] = range_limit[y + cgreen];
334ed2 ····outptr[RGB_BLUE] = ·range_limit[y + cblue];
a919d4 ····outptr += RGB_PIXELSIZE;
47b33d ····y ·= GETJSAMPLE(*inptr0++);
4b487f ····outptr[RGB_RED] = ··range_limit[y + cred];
1dbf42 ····outptr[RGB_GREEN] = range_limit[y + cgreen];
464ed2 ····outptr[RGB_BLUE] = ·range_limit[y + cblue];
1c19d4 ····outptr += RGB_PIXELSIZE;
3ddf1c ··}
7179c3 ··/* If image width is odd, do the last output column separately */
d8d4bd ··if (cinfo->output_width & 1) {
c55c1a ····cb = GETJSAMPLE(*inptr1);
7f3e67 ····cr = GETJSAMPLE(*inptr2);
7eae49 ····cred = Crrtab[cr];
cd48f1 ····cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
f06754 ····cblue = Cbbtab[cb];
52f729 ····y ·= GETJSAMPLE(*inptr0);
7e487f ····outptr[RGB_RED] = ··range_limit[y + cred];
35bf42 ····outptr[RGB_GREEN] = range_limit[y + cgreen];
244ed2 ····outptr[RGB_BLUE] = ·range_limit[y + cblue];
fbdf1c ··}
34efe6 }
24af5a
21af5a
c138e5 /*
b37685 ·* Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
bf495d ·*/
1faf5a
100434 METHODDEF(void)
602cb2 h2v2_merged_upsample (j_decompress_ptr cinfo,
--5560 000ebb41a364010002a Page 5 of jdmerge.c
d61637 ¤   ¤   ······JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
268f25 ¤   ¤   ······JSAMPARRAY output_buf)
89bb36 {
4b426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
c4d4ac ··register int y, cred, cgreen, cblue;
f02351 ··int cb, cr;
4612f3 ··register JSAMPROW outptr0, outptr1;
7cab6f ··JSAMPROW inptr00, inptr01, inptr1, inptr2;
db0f73 ··JDIMENSION col;
a0f430 ··/* copy these pointers into registers if possible */
eeba42 ··register JSAMPLE * range_limit = cinfo->sample_range_limit;
bcc296 ··int * Crrtab = upsample->Cr_r_tab;
490532 ··int * Cbbtab = upsample->Cb_b_tab;
62b26e ··INT32 * Crgtab = upsample->Cr_g_tab;
1cccd6 ··INT32 * Cbgtab = upsample->Cb_g_tab;
6bea99 ··SHIFT_TEMPS
0daf5a
bfe2ad ··inptr00 = input_buf[0][in_row_group_ctr*2];
7fb708 ··inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
76cc9b ··inptr1 = input_buf[1][in_row_group_ctr];
ffc3ad ··inptr2 = input_buf[2][in_row_group_ctr];
3cafe5 ··outptr0 = output_buf[0];
6f2017 ··outptr1 = output_buf[1];
bc4866 ··/* Loop for each group of output pixels */
7b3d77 ··for (col = cinfo->output_width >> 1; col > 0; col--) {
058b0b ····/* Do the chroma part of the calculation */
3a342e ····cb = GETJSAMPLE(*inptr1++);
c23486 ····cr = GETJSAMPLE(*inptr2++);
3cae49 ····cred = Crrtab[cr];
de48f1 ····cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
4d6754 ····cblue = Cbbtab[cb];
ac03d0 ····/* Fetch 4 Y values and emit 4 pixels */
298c3b ····y ·= GETJSAMPLE(*inptr00++);
b1f81d ····outptr0[RGB_RED] = ··range_limit[y + cred];
865c2c ····outptr0[RGB_GREEN] = range_limit[y + cgreen];
d10e76 ····outptr0[RGB_BLUE] = ·range_limit[y + cblue];
385a2f ····outptr0 += RGB_PIXELSIZE;
3a8c3b ····y ·= GETJSAMPLE(*inptr00++);
46f81d ····outptr0[RGB_RED] = ··range_limit[y + cred];
a05c2c ····outptr0[RGB_GREEN] = range_limit[y + cgreen];
c00e76 ····outptr0[RGB_BLUE] = ·range_limit[y + cblue];
065a2f ····outptr0 += RGB_PIXELSIZE;
648810 ····y ·= GETJSAMPLE(*inptr01++);
0252d5 ····outptr1[RGB_RED] = ··range_limit[y + cred];
e15216 ····outptr1[RGB_GREEN] = range_limit[y + cgreen];
134498 ····outptr1[RGB_BLUE] = ·range_limit[y + cblue];
458579 ····outptr1 += RGB_PIXELSIZE;
3a8810 ····y ·= GETJSAMPLE(*inptr01++);
fd52d5 ····outptr1[RGB_RED] = ··range_limit[y + cred];
d65216 ····outptr1[RGB_GREEN] = range_limit[y + cgreen];
ae4498 ····outptr1[RGB_BLUE] = ·range_limit[y + cblue];
f18579 ····outptr1 += RGB_PIXELSIZE;
13df1c ··}
a479c3 ··/* If image width is odd, do the last output column separately */
cfd4bd ··if (cinfo->output_width & 1) {
9e5c1a ····cb = GETJSAMPLE(*inptr1);
263e67 ····cr = GETJSAMPLE(*inptr2);
87ae49 ····cred = Crrtab[cr];
8b48f1 ····cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
206754 ····cblue = Cbbtab[cb];
99b6fb ····y ·= GETJSAMPLE(*inptr00);
d5f81d ····outptr0[RGB_RED] = ··range_limit[y + cred];
705c2c ····outptr0[RGB_GREEN] = range_limit[y + cgreen];
540e76 ····outptr0[RGB_BLUE] = ·range_limit[y + cblue];
16aa40 ····y ·= GETJSAMPLE(*inptr01);
1352d5 ····outptr1[RGB_RED] = ··range_limit[y + cred];
b95216 ····outptr1[RGB_GREEN] = range_limit[y + cgreen];
154498 ····outptr1[RGB_BLUE] = ·range_limit[y + cblue];
91df1c ··}
fcefe6 }
baaf5a
ebaf5a
--b6c6 00173cab6934010002a Page 6 of jdmerge.c
bc38e5 /*
2f1458 ·* Module initialization routine for merged upsampling/color conversion.
e0775e ·*
950c95 ·* NB: this is called under the conditions determined by use_merged_upsample()
a12823 ·* in jdmaster.c. ·That routine MUST correspond to the actual capabilities
a05018 ·* of this module; no safety checks are made here.
f1495d ·*/
1baf5a
18f898 GLOBAL(void)
839237 jinit_merged_upsampler (j_decompress_ptr cinfo)
10bb36 {
04fd0c ··my_upsample_ptr upsample;
4eaf5a
9c89b8 ··upsample = (my_upsample_ptr)
6a3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
903a5b ¤   ¤   ¤   ¤   SIZEOF(my_upsampler));
665c58 ··cinfo->upsample = (struct jpeg_upsampler *) upsample;
bb9760 ··upsample->pub.start_pass = start_pass_merged_upsample;
3b7ab8 ··upsample->pub.need_context_rows = FALSE;
75af5a
732f43 ··upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
d0af5a
6b3862 ··if (cinfo->max_v_samp_factor == 2) {
1b6ebd ····upsample->pub.upsample = merged_2v_upsample;
abe914 ····upsample->upmethod = h2v2_merged_upsample;
b751e7 ····/* Allocate a spare row buffer */
b6ac99 ····upsample->spare_row = (JSAMPROW)
5f3ff1 ······(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
be4026 ¤   ¤   (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
6249d8 ··} else {
d3604a ····upsample->pub.upsample = merged_1v_upsample;
2d54de ····upsample->upmethod = h2v1_merged_upsample;
947e97 ····/* No spare row needed */
88eb03 ····upsample->spare_row = NULL;
22df1c ··}
d1af5a
690e87 ··build_ycc_rgb_table(cinfo);
40efe6 }
3aaf5a
730916 #endif /* UPSAMPLE_MERGING_SUPPORTED */
--660d 000b8c469834010002b Page 1 of jdphuff.c
bc38e5 /*
168a6e ·* jdphuff.c
ce775e ·*
15c561 ·* Copyright (C) 1995-1996, Thomas G. Lane.
e4fb07 ·* This file is part of the Independent JPEG Group's software.
eaa0d6 ·* For conditions of distribution and use, see the accompanying README file.
4f775e ·*
7a08b4 ·* This file contains Huffman entropy decoding routines for progressive JPEG.
af775e ·*
2b0784 ·* Much of the complexity here has to do with supporting input suspension.
e55cb0 ·* If the data source module demands suspension, we want to be able to back
35f537 ·* up to the start of the current MCU. ·To do this, we copy state variables
921028 ·* into local working storage, and update them back to the permanent
198e4d ·* storage only upon successful completion of an MCU.
13495d ·*/
4caf5a
952bb6 #define JPEG_INTERNALS
6336a7 #include "jinclude.h"
286c8f #include "jpeglib.h"
83d314 #include "jdhuff.h"¤¤   /* Declarations shared with jdhuff.c */
a3af5a
41af5a
aee060 #ifdef D_PROGRESSIVE_SUPPORTED
44af5a
4838e5 /*
6173b3 ·* Expanded entropy decoder object for progressive Huffman decoding.
c2775e ·*
ee8e84 ·* The savable_state subrecord contains fields that change within an MCU,
43ea98 ·* but must not be updated permanently until we complete the MCU.
dd495d ·*/
78af5a
3df0f7 typedef struct {
f67424 ··unsigned int EOBRUN;¤ ¤   ¤   /* remaining EOBs in EOBRUN */
1bb2b1 ··int last_dc_val[MAX_COMPS_IN_SCAN];¤  /* last DC coef for each component */
fe9eb2 } savable_state;
19af5a
98f232 /* This macro is to work around compilers with missing or broken
371491 ·* structure assignment. ·You'll need to fix this code if you have
e09eb0 ·* such a compiler and you change MAX_COMPS_IN_SCAN.
ad495d ·*/
a5af5a
317994 #ifndef NO_STRUCT_ASSIGN
eda795 #define ASSIGN_STATE(dest,src) ·((dest) = (src))
87db21 #else
1dca2d #if MAX_COMPS_IN_SCAN == 4
c6679e #define ASSIGN_STATE(dest,src) ·\
3de676 ¤   ((dest).EOBRUN = (src).EOBRUN, \
b5d3b6 ¤   ·(dest).last_dc_val[0] = (src).last_dc_val[0], \
a52eac ¤   ·(dest).last_dc_val[1] = (src).last_dc_val[1], \
592193 ¤   ·(dest).last_dc_val[2] = (src).last_dc_val[2], \
30358a ¤   ·(dest).last_dc_val[3] = (src).last_dc_val[3])
ab7454 #endif
487454 #endif
11af5a
cfaf5a
20f0f7 typedef struct {
08e00e ··struct jpeg_entropy_decoder pub; /* public fields */
ccaf5a
7212fc ··/* These fields are loaded into local variables at start of each MCU.
d2a8c3 ···* In case of suspension, we exit WITHOUT updating them.
52f9a6 ···*/
d1beb9 ··bitread_perm_state bitstate;¤ /* Bit buffer at start of MCU */
d24b28 ··savable_state saved;¤ ¤   /* Other state at start of MCU */
74af5a
15f17f ··/* These fields are NOT loaded into local working state. */
898e4c ··unsigned int restarts_to_go;¤ /* MCUs left in this restart interval */
c4af5a
ace6a8 ··/* Pointers to derived tables (these workspaces have image lifespan) */
52f9b1 ··d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
d0af5a
17ed8b ··d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
b821e7 } phuff_entropy_decoder;
--e49e 0007275a73b4010002b Page 2 of jdphuff.c
e0af5a
2a634a typedef phuff_entropy_decoder * phuff_entropy_ptr;
9baf5a
a46a43 /* Forward declarations */
2f046a METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo,
ed9981 ¤   ¤   ¤   ¤   ¤   ····JBLOCKROW *MCU_data));
8f15a0 METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo,
149981 ¤   ¤   ¤   ¤   ¤   ····JBLOCKROW *MCU_data));
b31237 METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo,
687409 ¤   ¤   ¤   ¤   ¤   ·····JBLOCKROW *MCU_data));
bc7b70 METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
e57409 ¤   ¤   ¤   ¤   ¤   ·····JBLOCKROW *MCU_data));
8caf5a
1eaf5a
bc38e5 /*
c23637 ·* Initialize for a Huffman-compressed scan.
01495d ·*/
45af5a
ff0434 METHODDEF(void)
2ea07a start_pass_phuff_decoder (j_decompress_ptr cinfo)
f0bb36 {
c52069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
9663e2 ··boolean is_DC_band, bad;
6585ef ··int ci, coefi, tbl;
a6f4a8 ··int *coef_bit_ptr;
1bbcae ··jpeg_component_info * compptr;
bcaf5a
ac7c62 ··is_DC_band = (cinfo->Ss == 0);
d1af5a
48b9cc ··/* Validate scan parameters */
53f213 ··bad = FALSE;
eccf5d ··if (is_DC_band) {
387138 ····if (cinfo->Se != 0)
6963db ······bad = TRUE;
7249d8 ··} else {
32625e ····/* need not check Ss/Se < 0 since they came from unsigned bytes */
0bc8c9 ····if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2)
d563db ······bad = TRUE;
d74d35 ····/* AC scans may have only one component */
4c55ba ····if (cinfo->comps_in_scan != 1)
e463db ······bad = TRUE;
85df1c ··}
10241f ··if (cinfo->Ah != 0) {
9b3f76 ····/* Successive approximation refinement scan: must have Al = Ah-1. */
32408d ····if (cinfo->Al != cinfo->Ah-1)
5b63db ······bad = TRUE;
53df1c ··}
31ffb3 ··if (cinfo->Al > 13)¤  ¤   /* need not check for < 0 */
3e28c5 ····bad = TRUE;
269c89 ··if (bad)
83ea76 ····ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
1e77e4 ¤   ·····cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
7f0d96 ··/* Update progression status, and verify that scan order is legal.
d1b0bb ···* Note that inter-scan inconsistencies are treated as warnings
666711 ···* not fatal errors ... not clear if this is right way to behave.
fff9a6 ···*/
1b6aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
25dee9 ····int cindex = cinfo->cur_comp_info[ci]->component_index;
f1db28 ····coef_bit_ptr = & cinfo->coef_bits[cindex][0];
5c0727 ····if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
5cebac ······WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
0c782b ····for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
a5e635 ······int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
06e148 ······if (cinfo->Ah != expected)
36a37d ¤   WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
854e9f ······coef_bit_ptr[coefi] = cinfo->Al;
3c6fe7 ····}
fcdf1c ··}
d8af5a
791c2c ··/* Select MCU decoding routine */
324405 ··if (cinfo->Ah == 0) {
72e7fc ····if (is_DC_band)
--25c1 000c995a9674010002b Page 3 of jdphuff.c
5e02ca ······entropy->pub.decode_mcu = decode_mcu_DC_first;
70842c ····else
529e71 ······entropy->pub.decode_mcu = decode_mcu_AC_first;
8649d8 ··} else {
12e7fc ····if (is_DC_band)
c4b34b ······entropy->pub.decode_mcu = decode_mcu_DC_refine;
72842c ····else
7db88f ······entropy->pub.decode_mcu = decode_mcu_AC_refine;
31df1c ··}
47af5a
be6aad ··for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
f1a7cc ····compptr = cinfo->cur_comp_info[ci];
282044 ····/* Make sure requested tables are present, and compute derived tables.
6d0b00 ·····* We may build same derived table more than once, but it's not expensive.
bbd48d ·····*/
a88d6e ····if (is_DC_band) {
173ff1 ······if (cinfo->Ah == 0) {¤/* DC refinement needs no table */
680bec ¤   tbl = compptr->dc_tbl_no;
67a62e ¤   if (tbl < 0 || tbl >= NUM_HUFF_TBLS ||
5ff7c4 ¤   ····cinfo->dc_huff_tbl_ptrs[tbl] == NULL)
a30f0f ¤   ··ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
f10ec0 ¤   jpeg_make_d_derived_tbl(cinfo, cinfo->dc_huff_tbl_ptrs[tbl],
60cc05 ¤   ¤   ¤   ¤   & entropy->derived_tbls[tbl]);
f142cc ······}
ff6a79 ····} else {
267589 ······tbl = compptr->ac_tbl_no;
c839aa ······if (tbl < 0 || tbl >= NUM_HUFF_TBLS ||
19cb0b ··········cinfo->ac_huff_tbl_ptrs[tbl] == NULL)
cff47c ········ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
9028c2 ······jpeg_make_d_derived_tbl(cinfo, cinfo->ac_huff_tbl_ptrs[tbl],
929678 ¤   ¤   ¤   ······& entropy->derived_tbls[tbl]);
c88a9c ······/* remember the single active table */
82274f ······entropy->ac_derived_tbl = entropy->derived_tbls[tbl];
756fe7 ····}
399302 ····/* Initialize DC predictions to 0 */
994f55 ····entropy->saved.last_dc_val[ci] = 0;
c2df1c ··}
5eaf5a
edb914 ··/* Initialize bitread state variables */
1f5662 ··entropy->bitstate.bits_left = 0;
6a4944 ··entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
5af820 ··entropy->bitstate.printed_eod = FALSE;
03af5a
826c7f ··/* Initialize private state variables */
114213 ··entropy->saved.EOBRUN = 0;
72af5a
0c2e5a ··/* Initialize restart counter */
417047 ··entropy->restarts_to_go = cinfo->restart_interval;
5cefe6 }
f8af5a
78af5a
0f38e5 /*
fb0aa3 ·* Figure F.12: extend sign bit.
e1195b ·* On some machines, a shift and add will be faster than a table lookup.
fd495d ·*/
6aaf5a
df00cc #ifdef AVOID_TABLES
86af5a
c824f2 #define HUFF_EXTEND(x,s) ·((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
8caf5a
eedb21 #else
69af5a
5e0b5e #define HUFF_EXTEND(x,s) ·((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
dcaf5a
8d9a7b static const int extend_test[16] = ··/* entry n is 2**(n-1) */
895785 ··{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
04e950 ····0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
cdaf5a
5f8ca1 static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
a8a64a ··{ 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
47af52 ····((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
c92860 ····((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
--7926 000c270db2f4010002b Page 4 of jdphuff.c
19f883 ····((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
12af5a
cd1e5b #endif /* AVOID_TABLES */
86af5a
33af5a
8438e5 /*
b5aeaa ·* Check for a restart marker & resynchronize decoder.
1f0522 ·* Returns FALSE if must suspend.
e6495d ·*/
4caf5a
edc4bf LOCAL(boolean)
62acd0 process_restart (j_decompress_ptr cinfo)
49bb36 {
b22069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
820dcc ··int ci;
92af5a
f9017d ··/* Throw away any unused bits remaining in bit buffer; */
ff5a67 ··/* include any full bytes in next_marker's count of discarded bytes */
ef31cf ··cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
6e5662 ··entropy->bitstate.bits_left = 0;
faaf5a
ac1aa7 ··/* Advance past the RSTn marker */
76736a ··if (! (*cinfo->marker->read_restart_marker) (cinfo))
7430cb ····return FALSE;
8caf5a
d0bee5 ··/* Re-initialize DC predictions to 0 */
2a5387 ··for (ci = 0; ci < cinfo->comps_in_scan; ci++)
f04f55 ····entropy->saved.last_dc_val[ci] = 0;
95088b ··/* Re-init EOB run count, too */
694213 ··entropy->saved.EOBRUN = 0;
0daf5a
120d37 ··/* Reset restart counter */
557047 ··entropy->restarts_to_go = cinfo->restart_interval;
79af5a
f50f77 ··/* Next segment can get another out-of-data warning */
d3f820 ··entropy->bitstate.printed_eod = FALSE;
aaaf5a
00d2c8 ··return TRUE;
07efe6 }
47af5a
86af5a
ac38e5 /*
3c183e ·* Huffman MCU decoding.
351c1d ·* Each of these routines decodes and returns one MCU's worth of
d849fd ·* Huffman-compressed coefficients.·
e47e7d ·* The coefficients are reordered from zigzag order into natural array order,
887783 ·* but are not dequantized.
57775e ·*
486b07 ·* The i'th block of the MCU is stored into the block pointed to by
1f1fd8 ·* MCU_data[i]. ·WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
d7775e ·*
a9bee5 ·* We return FALSE if data source requested suspension. ·In that case no
f98c55 ·* changes have been made to permanent state. ·(Exception: some output
db9033 ·* coefficients may already have been assigned. ·This is harmless for
d8207d ·* spectral selection, since we'll just re-assign them on the next call.
916f00 ·* Successive approximation AC refinement has to be more careful, however.)
23495d ·*/
59af5a
3038e5 /*
8033b2 ·* MCU decoding for DC initial scan (either spectral selection,
d8fce4 ·* or first pass of successive approximation).
e1495d ·*/
70af5a
0c9a8f METHODDEF(boolean)
8997d1 decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
fd0337 { ··
6d2069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
aa9a28 ··int Al = cinfo->Al;
4d3552 ··register int s, r;
23ed99 ··int blkn, ci;
225fd5 ··JBLOCKROW block;
c2d204 ··BITREAD_STATE_VARS;
--67e9 0004441dfa04010002b Page 5 of jdphuff.c
86faad ··savable_state state;
4cc862 ··d_derived_tbl * tbl;
bdbcae ··jpeg_component_info * compptr;
84af5a
48b91b ··/* Process restart marker if needed; may have to suspend */
8fcdfb ··if (cinfo->restart_interval) {
9c8a4f ····if (entropy->restarts_to_go == 0)
637293 ······if (! process_restart(cinfo))
4aa230 ¤   return FALSE;
f7df1c ··}
b3af5a
aa185b ··/* Load up working state */
18efd3 ··BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
d466cc ··ASSIGN_STATE(state, entropy->saved);
51af5a
f02881 ··/* Outer loop handles each block in the MCU */
e4af5a
ce7685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
b3d6bd ····block = MCU_data[blkn];
e8153d ····ci = cinfo->MCU_membership[blkn];
b2a7cc ····compptr = cinfo->cur_comp_info[ci];
aba2b1 ····tbl = entropy->derived_tbls[compptr->dc_tbl_no];
66af5a
9a7c44 ····/* Decode a single block's worth of coefficients */
84af5a
b3ba23 ····/* Section F.2.2.1: decode the DC coefficient difference */
73d4c9 ····HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
8c7613 ····if (s) {
697afc ······CHECK_BIT_BUFFER(br_state, s, return FALSE);
2b4546 ······r = GET_BITS(s);
d0610f ······s = HUFF_EXTEND(r, s);
806fe7 ····}
bfaf5a
117b32 ····/* Convert DC difference to actual value, update last_dc_val */
d8a67b ····s += state.last_dc_val[ci];
27d1f0 ····state.last_dc_val[ci] = s;
9130be ····/* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */
47b268 ····(*block)[0] = (JCOEF) (s << Al);
4adf1c ··}
1baf5a
f24c4d ··/* Completed MCU, so update state */
d9cdc5 ··BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
3266e4 ··ASSIGN_STATE(entropy->saved, state);
37af5a
2ad5b5 ··/* Account for restart interval (no-op if not using restarts) */
ffea59 ··entropy->restarts_to_go--;
64af5a
5bd2c8 ··return TRUE;
e7efe6 }
b9af5a
84af5a
e338e5 /*
19a2cb ·* MCU decoding for AC initial scan (either spectral selection,
73fce4 ·* or first pass of successive approximation).
ac495d ·*/
e1af5a
c59a8f METHODDEF(boolean)
df7ca3 decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
600337 { ··
fc2069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
665000 ··int Se = cinfo->Se;
e99a28 ··int Al = cinfo->Al;
5b86d3 ··register int s, k, r;
974900 ··unsigned int EOBRUN;
3d5fd5 ··JBLOCKROW block;
80d204 ··BITREAD_STATE_VARS;
35c862 ··d_derived_tbl * tbl;
c1af5a
ddb91b ··/* Process restart marker if needed; may have to suspend */
adcdfb ··if (cinfo->restart_interval) {
218a4f ····if (entropy->restarts_to_go == 0)
447293 ······if (! process_restart(cinfo))
--114e 000a93579244010002b Page 6 of jdphuff.c
6ba230 ¤   return FALSE;
06df1c ··}
e2af5a
d3d043 ··/* Load up working state.
6738a8 ···* We can avoid loading/saving bitread state if in an EOB run.
04f9a6 ···*/
9379dc ··EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we care about */
82af5a
2579c9 ··/* There is always only one block per MCU */
29af5a
983399 ··if (EOBRUN > 0)¤  ¤   /* if it's a band of zeroes... */
9dba0e ····EOBRUN--;¤  ¤   ¤   /* ...process it now (we do nothing) */
dc3a1e ··else {
7059d7 ····BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
6941f9 ····block = MCU_data[0];
5154a2 ····tbl = entropy->ac_derived_tbl;
ebaf5a
51460c ····for (k = cinfo->Ss; k <= Se; k++) {
4f29fd ······HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
85eb66 ······r = s >> 4;
0d0a2a ······s &= 15;
39d3ad ······if (s) {
1836e3 ········k += r;
12548b ········CHECK_BIT_BUFFER(br_state, s, return FALSE);
7e595a ········r = GET_BITS(s);
a3d13b ········s = HUFF_EXTEND(r, s);
89b2a5 ¤   /* Scale and output coefficient in natural (dezigzagged) order */
a36cce ········(*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
ddcfc7 ······} else {
850a71 ········if (r == 15) {¤ ¤   /* ZRL */
64847c ··········k += 15;¤ ¤   /* skip 15 zeroes in band */
d30206 ········} else {¤   ¤   /* EOBr, run length is 2^r + appended bits */
45a0db ··········EOBRUN = 1 << r;
0f9df8 ··········if (r) {¤ ¤   /* EOBr, r > 0 */
1266dd ¤   ····CHECK_BIT_BUFFER(br_state, r, return FALSE);
4cd79e ············r = GET_BITS(r);
f82eda ············EOBRUN += r;
41ccb2 ··········}
913476 ¤   ··EOBRUN--;¤¤   /* this band is processed at this moment */
f5e2da ¤   ··break;¤   ¤   /* force end-of-band */
709371 ¤   }
9142cc ······}
416fe7 ····}
40af5a
dc7bc1 ····BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
fadf1c ··}
55af5a
d84c4d ··/* Completed MCU, so update state */
d1971c ··entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we care about */
6daf5a
e9d5b5 ··/* Account for restart interval (no-op if not using restarts) */
1dea59 ··entropy->restarts_to_go--;
e8af5a
31d2c8 ··return TRUE;
beefe6 }
9caf5a
cfaf5a
0a38e5 /*
2968b6 ·* MCU decoding for DC successive approximation refinement scan.
914ad9 ·* Note: we assume such scans can be multi-component, although the spec
06b2d5 ·* is not very clear on the point.
2b495d ·*/
e7af5a
699a8f METHODDEF(boolean)
261fdb decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
c20337 { ··
452069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
99596e ··int p1 = 1 << cinfo->Al;¤ /* 1 in the bit position being coded */
a6d4fa ··int blkn;
4f5fd5 ··JBLOCKROW block;
89d204 ··BITREAD_STATE_VARS;
a9af5a
--55e7 0005a93d2694010002b Page 7 of jdphuff.c
b2b91b ··/* Process restart marker if needed; may have to suspend */
01cdfb ··if (cinfo->restart_interval) {
0e8a4f ····if (entropy->restarts_to_go == 0)
4a7293 ······if (! process_restart(cinfo))
8ba230 ¤   return FALSE;
e1df1c ··}
6daf5a
d9185b ··/* Load up working state */
b7efd3 ··BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
09af5a
a52881 ··/* Outer loop handles each block in the MCU */
feaf5a
717685 ··for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
e1d6bd ····block = MCU_data[blkn];
daaf5a
92f75e ····/* Encoded data is simply the next bit of the two's-complement DC value */
c7f6f1 ····CHECK_BIT_BUFFER(br_state, 1, return FALSE);
7fa143 ····if (GET_BITS(1))
4e1669 ······(*block)[0] |= p1;
0d4360 ····/* Note: since we use |=, repeating the assignment later is safe */
32df1c ··}
c2af5a
ad4c4d ··/* Completed MCU, so update state */
47cdc5 ··BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
b7af5a
76d5b5 ··/* Account for restart interval (no-op if not using restarts) */
a9ea59 ··entropy->restarts_to_go--;
54af5a
ecd2c8 ··return TRUE;
9befe6 }
03af5a
b3af5a
6638e5 /*
938661 ·* MCU decoding for AC successive approximation refinement scan.
0e495d ·*/
53af5a
399a8f METHODDEF(boolean)
b74fa5 decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
300337 { ··
8f2069 ··phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
ff5000 ··int Se = cinfo->Se;
a8596e ··int p1 = 1 << cinfo->Al;¤ /* 1 in the bit position being coded */
e0f400 ··int m1 = (-1) << cinfo->Al;¤  /* -1 in the bit position being coded */
f786d3 ··register int s, k, r;
f74900 ··unsigned int EOBRUN;
2a5fd5 ··JBLOCKROW block;
eeee73 ··JCOEFPTR thiscoef;
3ad204 ··BITREAD_STATE_VARS;
08c862 ··d_derived_tbl * tbl;
2ac03e ··int num_newnz;
c6b082 ··int newnz_pos[DCTSIZE2];
99af5a
fab91b ··/* Process restart marker if needed; may have to suspend */
d4cdfb ··if (cinfo->restart_interval) {
388a4f ····if (entropy->restarts_to_go == 0)
537293 ······if (! process_restart(cinfo))
dca230 ¤   return FALSE;
45df1c ··}
d9af5a
39185b ··/* Load up working state */
8aefd3 ··BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
7379dc ··EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we care about */
a2af5a
3b79c9 ··/* There is always only one block per MCU */
ad5de5 ··block = MCU_data[0];
6de0fe ··tbl = entropy->ac_derived_tbl;
beaf5a
7a0dab ··/* If we are forced to suspend, we must undo the assignments to any newly
da05a7 ···* nonzero coefficients in the block, because otherwise we'd get confused
06de85 ···* next time about which coefficients were already nonzero.
a59e56 ···* But we need not undo addition of bits to already-nonzero coefficients;
5acd97 ···* instead, we can test the current bit position to see if we already did it.
--5539 000d32d8a664010002b Page 8 of jdphuff.c
e2f9a6 ···*/
d73041 ··num_newnz = 0;
4aaf5a
b879b3 ··/* initialize coefficient loop counter to start of band */
99e5e3 ··k = cinfo->Ss;
65af5a
279e16 ··if (EOBRUN == 0) {
132e6c ····for (; k <= Se; k++) {
6de1af ······HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
96eb66 ······r = s >> 4;
a90a2a ······s &= 15;
f6d3ad ······if (s) {
aa2fa2 ¤   if (s != 1)¤¤   /* size of new coef should always be 1 */
2255f8 ¤   ··WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
a1ae97 ········CHECK_BIT_BUFFER(br_state, 1, goto undoit);
debe05 ········if (GET_BITS(1))
243e27 ¤   ··s = p1;¤  ¤   /* newly nonzero coef is positive */
240e24 ¤   else
f36e19 ¤   ··s = m1;¤  ¤   /* newly nonzero coef is negative */
4acfc7 ······} else {
a679dd ¤   if (r != 15) {
697a07 ¤   ··EOBRUN = 1 << r;¤ /* EOBr, run length is 2^r + appended bits */
b83f4c ¤   ··if (r) {
22600e ¤   ····CHECK_BIT_BUFFER(br_state, r, goto undoit);
22eb76 ¤   ····r = GET_BITS(r);
b1bee3 ¤   ····EOBRUN += r;
db32a2 ¤   ··}
818e8a ¤   ··break;¤   ¤   /* rest of block is handled by EOB logic */
709371 ¤   }
6fe08f ¤   /* note s = 0 for processing ZRL */
fc42cc ······}
c814d7 ······/* Advance over already-nonzero coefs and r still-zero coefs,
ecdc99 ·······* appending correction bits to the nonzeroes. ·A correction bit is 1
7952c5 ·······* if the absolute value of the coefficient must be increased.
03e9f1 ·······*/
2d7075 ······do {
61dc17 ¤   thiscoef = *block + jpeg_natural_order[k];
74fd8e ¤   if (*thiscoef != 0) {
0c3d67 ¤   ··CHECK_BIT_BUFFER(br_state, 1, goto undoit);
d8a171 ¤   ··if (GET_BITS(1)) {
85db17 ¤   ····if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
28aac7 ¤   ······if (*thiscoef >= 0)
4b3144 ¤   ¤   *thiscoef += p1;
a25c40 ¤   ······else
44796a ¤   ¤   *thiscoef += m1;
5df372 ¤   ····}
2c32a2 ¤   ··}
45f037 ¤   } else {
c5411e ¤   ··if (--r < 0)
ce2adf ¤   ····break;¤ ¤   /* reached target zero coefficient */
b39371 ¤   }
1c22cc ¤   k++;
adc638 ······} while (k <= Se);
ddd3ad ······if (s) {
11fe5d ¤   int pos = jpeg_natural_order[k];
c8482f ¤   /* Output newly nonzero coefficient */
477d72 ¤   (*block)[pos] = (JCOEF) s;
30ad46 ¤   /* Remember its position in case we have to suspend */
11c6e3 ¤   newnz_pos[num_newnz++] = pos;
a842cc ······}
6b6fe7 ····}
a6df1c ··}
4aaf5a
9357fc ··if (EOBRUN > 0) {
489ef5 ····/* Scan any remaining coefficient positions after the end-of-band
b16d55 ·····* (the last newly nonzero coefficient, if any). ·Append a correction
c547b2 ·····* bit to each already-nonzero coefficient. ·A correction bit is 1
f4384b ·····* if the absolute value of the coefficient must be increased.
7bd48d ·····*/
572e6c ····for (; k <= Se; k++) {
5c402b ······thiscoef = *block + jpeg_natural_order[k];
d30111 ······if (*thiscoef != 0) {
--2232 0010015cc5b4010002b Page 9 of jdphuff.c
57583b ¤   CHECK_BIT_BUFFER(br_state, 1, goto undoit);
9a1c09 ¤   if (GET_BITS(1)) {
93527a ¤   ··if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
b30f07 ¤   ····if (*thiscoef >= 0)
b7ee51 ¤   ······*thiscoef += p1;
5d8415 ¤   ····else
dca67f ¤   ······*thiscoef += m1;
ca32a2 ¤   ··}
0c9371 ¤   }
3a42cc ······}
576fe7 ····}
e9fdfb ····/* Count one block completed in EOB run */
cc6077 ····EOBRUN--;
fadf1c ··}
41af5a
dd4c4d ··/* Completed MCU, so update state */
99cdc5 ··BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
44971c ··entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we care about */
39af5a
57d5b5 ··/* Account for restart interval (no-op if not using restarts) */
c2ea59 ··entropy->restarts_to_go--;
27af5a
cad2c8 ··return TRUE;
33af5a
990658 undoit:
32bdeb ··/* Re-zero any output coefficients that we made newly nonzero */
2a7c58 ··while (num_newnz > 0)
377cee ····(*block)[newnz_pos[--num_newnz]] = 0;
62af5a
9f7bd5 ··return FALSE;
9aefe6 }
48af5a
79af5a
fb38e5 /*
3cb632 ·* Module initialization routine for progressive Huffman entropy decoding.
b2495d ·*/
9caf5a
bbf898 GLOBAL(void)
6743d9 jinit_phuff_decoder (j_decompress_ptr cinfo)
bcbb36 {
a51e60 ··phuff_entropy_ptr entropy;
f9f4a8 ··int *coef_bit_ptr;
37ac23 ··int ci, i;
9daf5a
506f2d ··entropy = (phuff_entropy_ptr)
923f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
46df00 ¤   ¤   ¤   ¤   SIZEOF(phuff_entropy_decoder));
d68412 ··cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
3c2c25 ··entropy->pub.start_pass = start_pass_phuff_decoder;
0caf5a
f2f960 ··/* Mark derived tables unallocated */
d372db ··for (i = 0; i < NUM_HUFF_TBLS; i++) {
9d2088 ····entropy->derived_tbls[i] = NULL;
5ddf1c ··}
9caf5a
07b705 ··/* Create progression status table */
d42297 ··cinfo->coef_bits = (int (*)[DCTSIZE2])
1d3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
d1b438 ¤   ¤   ¤   ¤   cinfo->num_components*DCTSIZE2*SIZEOF(int));
15e448 ··coef_bit_ptr = & cinfo->coef_bits[0][0];
215c80 ··for (ci = 0; ci < cinfo->num_components; ci++)·
2801ec ····for (i = 0; i < DCTSIZE2; i++)
f5594e ······*coef_bit_ptr++ = -1;
7fefe6 }
e5af5a
000779 #endif /* D_PROGRESSIVE_SUPPORTED */
--58a6 000240e88c54010002c Page 1 of jdpostct.c
bc38e5 /*
c8cf25 ·* jdpostct.c
a5775e ·*
789e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
dafb07 ·* This file is part of the Independent JPEG Group's software.
dba0d6 ·* For conditions of distribution and use, see the accompanying README file.
95775e ·*
bd557b ·* This file contains the decompression postprocessing controller.
735185 ·* This controller manages the upsampling, color conversion, and color
12915d ·* quantization/reduction steps; specifically, it controls the buffering
39eeea ·* between upsample/color conversion and color quantization/reduction.
cf775e ·*
7d7e91 ·* If no color quantization/reduction is required, then this module has no
0781f6 ·* work to do, and it just hands off to the upsample/color conversion code.
ccd992 ·* An integrated upsample/convert/quantize process would replace this module
836ec2 ·* entirely.
78495d ·*/
e3af5a
212bb6 #define JPEG_INTERNALS
6036a7 #include "jinclude.h"
bb6c8f #include "jpeglib.h"
6daf5a
24af5a
108416 /* Private buffer controller object */
a0af5a
2cf0f7 typedef struct {
ff9f3b ··struct jpeg_d_post_controller pub; /* public fields */
62af5a
9a1aa1 ··/* Color quantization source buffer: this holds output data from
d01ecf ···* the upsample/color conversion step to be passed to the quantizer.
68af24 ···* For two-pass color quantization, we need a full-image buffer;
aaa878 ···* for one-pass operation, a strip buffer is sufficient.
84f9a6 ···*/
484f80 ··jvirt_sarray_ptr whole_image;¤/* virtual array, or NULL if one-pass */
a0bbc7 ··JSAMPARRAY buffer;¤   ¤   /* strip buffer, or current strip of virtual */
4e419e ··JDIMENSION strip_height;¤ /* buffer size in rows */
d497e4 ··/* for two-pass mode only: */
17d410 ··JDIMENSION starting_row;¤ /* row # of first row in current strip */
b0971e ··JDIMENSION next_row;¤ ¤   /* index of next row to fill/empty in strip */
3cca76 } my_post_controller;
d3af5a
0a216c typedef my_post_controller * my_post_ptr;
86af5a
13af5a
836a43 /* Forward declarations */
661e2f METHODDEF(void) post_process_1pass
1aa39f ¤   JPP((j_decompress_ptr cinfo,
b62dc4 ¤   ·····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
997321 ¤   ·····JDIMENSION in_row_groups_avail,
b5e160 ¤   ·····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
dbae4c ¤   ·····JDIMENSION out_rows_avail));
c44df6 #ifdef QUANT_2PASS_SUPPORTED
6d1476 METHODDEF(void) post_process_prepass
aea39f ¤   JPP((j_decompress_ptr cinfo,
482dc4 ¤   ·····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
007321 ¤   ·····JDIMENSION in_row_groups_avail,
2de160 ¤   ·····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
36ae4c ¤   ·····JDIMENSION out_rows_avail));
ad1252 METHODDEF(void) post_process_2pass
9ea39f ¤   JPP((j_decompress_ptr cinfo,
f32dc4 ¤   ·····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
5a7321 ¤   ·····JDIMENSION in_row_groups_avail,
cbe160 ¤   ·····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
0fae4c ¤   ·····JDIMENSION out_rows_avail));
a37454 #endif
b4af5a
72af5a
6438e5 /*
f55b80 ·* Initialize for a processing pass.
d7495d ·*/
ecaf5a
240434 METHODDEF(void)
--97c5 00048cfbbe64010002c Page 2 of jdpostct.c
7cd2af start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
aebb36 {
f74cbd ··my_post_ptr post = (my_post_ptr) cinfo->post;
93af5a
4f1eec ··switch (pass_mode) {
49972e ··case JBUF_PASS_THRU:
63796e ····if (cinfo->quantize_colors) {
15ee63 ······/* Single-pass processing with color quantization. */
340402 ······post->pub.post_process_data = post_process_1pass;
498035 ······/* We could be doing buffered-image output before starting a 2-pass
34ce92 ·······* color quantization; in that case, jinit_d_post_controller did not
50adb5 ·······* allocate a strip buffer. ·Use the virtual-array buffer as workspace.
50e9f1 ·······*/
15227e ······if (post->buffer == NULL) {
aa6814 ¤   post->buffer = (*cinfo->mem->access_virt_sarray)
51531c ¤   ··((j_common_ptr) cinfo, post->whole_image,
01c773 ¤   ···(JDIMENSION) 0, post->strip_height, TRUE);
ba42cc ······}
176a79 ····} else {
a2bda0 ······/* For single-pass processing without color quantization,
a19e0e ·······* I have no work to do; just call the upsampler directly.
4fe9f1 ·······*/
adaf85 ······post->pub.post_process_data = cinfo->upsample->upsample;
766fe7 ····}
c9ab40 ····break;
cb4df6 #ifdef QUANT_2PASS_SUPPORTED
05e8d2 ··case JBUF_SAVE_AND_PASS:
2c0049 ····/* First pass of 2-pass quantization */
30d09f ····if (post->whole_image == NULL)
430c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
9d0261 ····post->pub.post_process_data = post_process_prepass;
27ab40 ····break;
526409 ··case JBUF_CRANK_DEST:
0f777c ····/* Second pass of 2-pass quantization */
03d09f ····if (post->whole_image == NULL)
8e0c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
361992 ····post->pub.post_process_data = post_process_2pass;
77ab40 ····break;
ced24f #endif /* QUANT_2PASS_SUPPORTED */
17969d ··default:
94650a ····ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
ddab40 ····break;
66df1c ··}
4964d6 ··post->starting_row = post->next_row = 0;
14efe6 }
f5af5a
acaf5a
9538e5 /*
825b11 ·* Process some data in the one-pass (strip buffer) case.
4de232 ·* This is used for color precision reduction as well as one-pass quantization.
43495d ·*/
1daf5a
fe0434 METHODDEF(void)
2ce18d post_process_1pass (j_decompress_ptr cinfo,
4680d8 ¤   ¤   ····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
51d9b2 ¤   ¤   ····JDIMENSION in_row_groups_avail,
144d56 ¤   ¤   ····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
014970 ¤   ¤   ····JDIMENSION out_rows_avail)
64bb36 {
f14cbd ··my_post_ptr post = (my_post_ptr) cinfo->post;
ad7d17 ··JDIMENSION num_rows, max_rows;
00af5a
5fc849 ··/* Fill the buffer, but not more than what we can dump out in one go. */
d1e0d4 ··/* Note we rely on the upsampler to detect bottom of image. */
b507df ··max_rows = out_rows_avail - *out_row_ctr;
824105 ··if (max_rows > post->strip_height)
1df228 ····max_rows = post->strip_height;
a61638 ··num_rows = 0;
6f1c6d ··(*cinfo->upsample->upsample) (cinfo,
38c6a5 ¤   ¤   input_buf, in_row_group_ctr, in_row_groups_avail,
30f8f6 ¤   ¤   post->buffer, &num_rows, max_rows);
4896a1 ··/* Quantize and emit data. */
--573a 00011611b3c4010002c Page 3 of jdpostct.c
45a8da ··(*cinfo->cquantize->color_quantize) (cinfo,
5d78b9 ¤   ¤   post->buffer, output_buf + *out_row_ctr, (int) num_rows);
57c101 ··*out_row_ctr += num_rows;
45efe6 }
35af5a
f0af5a
af4df6 #ifdef QUANT_2PASS_SUPPORTED
20af5a
5638e5 /*
39bf13 ·* Process some data in the first pass of 2-pass quantization.
f7495d ·*/
8caf5a
3a0434 METHODDEF(void)
a86b52 post_process_prepass (j_decompress_ptr cinfo,
ff91b4 ¤   ¤   ······JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
87eae4 ¤   ¤   ······JDIMENSION in_row_groups_avail,
8c71cc ¤   ¤   ······JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
70d830 ¤   ¤   ······JDIMENSION out_rows_avail)
5ebb36 {
a04cbd ··my_post_ptr post = (my_post_ptr) cinfo->post;
0de312 ··JDIMENSION old_next_row, num_rows;
86af5a
e34dbc ··/* Reposition virtual buffer if at start of strip. */
5deebf ··if (post->next_row == 0) {
02a2a5 ····post->buffer = (*cinfo->mem->access_virt_sarray)
711be5 ¤   ((j_common_ptr) cinfo, post->whole_image,
afb15f ¤   ·post->starting_row, post->strip_height, TRUE);
9bdf1c ··}
f1af5a
c576f0 ··/* Upsample some data (up to a strip height's worth). */
27faa0 ··old_next_row = post->next_row;
d61c6d ··(*cinfo->upsample->upsample) (cinfo,
78c6a5 ¤   ¤   input_buf, in_row_group_ctr, in_row_groups_avail,
3f8787 ¤   ¤   post->buffer, &post->next_row, post->strip_height);
b4af5a
23a866 ··/* Allow quantizer to scan new data. ·No data is emitted, */
09d128 ··/* but we advance out_row_ctr so outer loop can tell when we're done. */
78c30a ··if (post->next_row > old_next_row) {
96c09c ····num_rows = post->next_row - old_next_row;
c2d249 ····(*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
64080e ¤   ¤   ¤   ¤   ¤   ·(JSAMPARRAY) NULL, (int) num_rows);
0956e4 ····*out_row_ctr += num_rows;
fedf1c ··}
eeaf5a
2e4783 ··/* Advance if we filled the strip. */
30efcf ··if (post->next_row >= post->strip_height) {
cc46f3 ····post->starting_row += post->strip_height;
2eab32 ····post->next_row = 0;
2cdf1c ··}
e8efe6 }
1baf5a
12af5a
d538e5 /*
f5e142 ·* Process some data in the second pass of 2-pass quantization.
ba495d ·*/
a6af5a
450434 METHODDEF(void)
45a6c0 post_process_2pass (j_decompress_ptr cinfo,
0f80d8 ¤   ¤   ····JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
98d9b2 ¤   ¤   ····JDIMENSION in_row_groups_avail,
274d56 ¤   ¤   ····JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
2d4970 ¤   ¤   ····JDIMENSION out_rows_avail)
56bb36 {
fe4cbd ··my_post_ptr post = (my_post_ptr) cinfo->post;
f97d17 ··JDIMENSION num_rows, max_rows;
78af5a
b74dbc ··/* Reposition virtual buffer if at start of strip. */
a2eebf ··if (post->next_row == 0) {
fda2a5 ····post->buffer = (*cinfo->mem->access_virt_sarray)
1c1be5 ¤   ((j_common_ptr) cinfo, post->whole_image,
e831b5 ¤   ·post->starting_row, post->strip_height, FALSE);
11df1c ··}
--6b49 00092fb52504010002c Page 4 of jdpostct.c
e0af5a
ecf14b ··/* Determine number of rows to emit. */
f85459 ··num_rows = post->strip_height - post->next_row; /* available in strip */
9d3af1 ··max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
0c01cb ··if (num_rows > max_rows)
51b431 ····num_rows = max_rows;
7d4c42 ··/* We have to check bottom of image here, can't depend on upsampler. */
c73d49 ··max_rows = cinfo->output_height - post->starting_row;
4f01cb ··if (num_rows > max_rows)
9eb431 ····num_rows = max_rows;
37af5a
9296a1 ··/* Quantize and emit data. */
4ea8da ··(*cinfo->cquantize->color_quantize) (cinfo,
80fb9a ¤   ¤   post->buffer + post->next_row, output_buf + *out_row_ctr,
85ca73 ¤   ¤   (int) num_rows);
59c101 ··*out_row_ctr += num_rows;
47af5a
594783 ··/* Advance if we filled the strip. */
ce5783 ··post->next_row += num_rows;
10efcf ··if (post->next_row >= post->strip_height) {
8346f3 ····post->starting_row += post->strip_height;
0eab32 ····post->next_row = 0;
56df1c ··}
7cefe6 }
d3af5a
c4d24f #endif /* QUANT_2PASS_SUPPORTED */
58af5a
d9af5a
8338e5 /*
d62a62 ·* Initialize postprocessing controller.
92495d ·*/
d7af5a
76f898 GLOBAL(void)
990a66 jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
aabb36 {
90659e ··my_post_ptr post;
cfaf5a
ad25a6 ··post = (my_post_ptr)
7d3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
20950f ¤   ¤   ¤   ¤   SIZEOF(my_post_controller));
3c18b3 ··cinfo->post = (struct jpeg_d_post_controller *) post;
96ede0 ··post->pub.start_pass = start_pass_dpost;
c22034 ··post->whole_image = NULL;¤/* flag for no virtual arrays */
9fe79f ··post->buffer = NULL;¤ ¤   /* flag for no strip buffer */
3aaf5a
232338 ··/* Create the quantization buffer, if needed */
7ea6cf ··if (cinfo->quantize_colors) {
53480b ····/* The buffer strip height is max_v_samp_factor, which is typically
113245 ·····* an efficient number of rows for upsampling to return.
dc1084 ·····* (In the presence of output rescaling, we might want to be smarter?)
0cd48d ·····*/
f66e4b ····post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
d4a6f5 ····if (need_full_buffer) {
3ac26f ······/* Two-pass color quantization: need full-image storage. */
809346 ······/* We round up the number of rows to a multiple of the strip height. */
af4df6 #ifdef QUANT_2PASS_SUPPORTED
bcb358 ······post->whole_image = (*cinfo->mem->request_virt_sarray)
acd16b ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
610052 ¤   ·cinfo->output_width * cinfo->out_color_components,
b424e3 ¤   ·(JDIMENSION) jround_up((long) cinfo->output_height,
088316 ¤   ¤   ¤   ¤   (long) post->strip_height),
d66c4d ¤   ·post->strip_height);
c1db21 #else
b60c66 ······ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
42d24f #endif /* QUANT_2PASS_SUPPORTED */
d26a79 ····} else {
bcf1c3 ······/* One-pass color quantization: just make a strip buffer. */
136028 ······post->buffer = (*cinfo->mem->alloc_sarray)
98ee7d ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE,
200052 ¤   ·cinfo->output_width * cinfo->out_color_components,
076c4d ¤   ·post->strip_height);
926fe7 ····}
--5dfe 0014baee4fb4010002c Page 5 of jdpostct.c
3adf1c ··}
4befe6 }
--0f47 0009adacca94010002d Page 1 of jdsample.c
bc38e5 /*
22bf8d ·* jdsample.c
fc775e ·*
62a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
aefb07 ·* This file is part of the Independent JPEG Group's software.
9ea0d6 ·* For conditions of distribution and use, see the accompanying README file.
e4775e ·*
668df6 ·* This file contains upsampling routines.
e1775e ·*
c5e000 ·* Upsampling input data is counted in "row groups". ·A row group
41f53c ·* is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
cfb804 ·* sample rows of each component. ·Upsampling will normally produce
7110e7 ·* max_v_samp_factor pixel rows from each row group (but this could vary
a2185e ·* if the upsampler is applying a scale factor of its own).
d4775e ·*
46eba2 ·* An excellent reference for image resampling is
5a39c1 ·* ··Digital Image Warping, George Wolberg, 1990.
ca9923 ·* ··Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
7b495d ·*/
87af5a
c92bb6 #define JPEG_INTERNALS
3f36a7 #include "jinclude.h"
4e6c8f #include "jpeglib.h"
a9af5a
e1af5a
eeb6b0 /* Pointer to routine to upsample a single component */
c731cf typedef JMETHOD(void, upsample1_ptr,
0365d1 ¤   ¤   (j_decompress_ptr cinfo, jpeg_component_info * compptr,
3c6c78 ¤   ¤   ·JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
6faf5a
e8dedc /* Private subobject */
22af5a
daf0f7 typedef struct {
8a6883 ··struct jpeg_upsampler pub;¤   /* public fields */
e3af5a
36dee2 ··/* Color conversion buffer. ·When using separate upsampling and color
54c66f ···* conversion steps, this buffer holds one upsampled row group until it
ab4999 ···* has been color converted and output.
598b56 ···* Note: we do not allocate any storage for component(s) which are full-size,
9a9b84 ···* ie do not need rescaling. ·The corresponding entry of color_buf[] is
925315 ···* simply set to point to the input data array, thereby avoiding copying.
d0f9a6 ···*/
5c22ce ··JSAMPARRAY color_buf[MAX_COMPONENTS];
c0af5a
587492 ··/* Per-component upsampling method pointers */
ca4b7d ··upsample1_ptr methods[MAX_COMPONENTS];
13af5a
2fc4b2 ··int next_row_out;¤¤   /* counts rows emitted from color_buf */
84ed18 ··JDIMENSION rows_to_go;¤   /* counts rows remaining in image */
a3af5a
ec48de ··/* Height of an input row group for each component. */
d2e90c ··int rowgroup_height[MAX_COMPONENTS];
47af5a
4c2cdf ··/* These arrays save pixel expansion factors so that int_expand need not
f81061 ···* recompute them each time. ·They are unused for other upsampling methods.
1bf9a6 ···*/
a44c45 ··UINT8 h_expand[MAX_COMPONENTS];
1d1cad ··UINT8 v_expand[MAX_COMPONENTS];
fb9b02 } my_upsampler;
90af5a
8655d9 typedef my_upsampler * my_upsample_ptr;
c3af5a
daaf5a
b538e5 /*
690b58 ·* Initialize for an upsampling pass.
62495d ·*/
b8af5a
520434 METHODDEF(void)
62b46c start_pass_upsample (j_decompress_ptr cinfo)
1abb36 {
65426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
9aaf5a
--bff8 0004ba9576e4010002d Page 2 of jdsample.c
5741d4 ··/* Mark the conversion buffer empty */
04239a ··upsample->next_row_out = cinfo->max_v_samp_factor;
52dac9 ··/* Initialize total-height counter for detecting bottom of image */
261311 ··upsample->rows_to_go = cinfo->output_height;
76efe6 }
51af5a
39af5a
b438e5 /*
f0a099 ·* Control routine to do upsampling (and color conversion).
5f775e ·*
e1f49c ·* In this version we upsample each component independently.
801f7a ·* We upsample one row group into the conversion buffer, then apply
08e187 ·* color conversion a row at a time.
83495d ·*/
94af5a
8c0434 METHODDEF(void)
f17893 sep_upsample (j_decompress_ptr cinfo,
f12dad ¤   ······JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
aed321 ¤   ······JDIMENSION in_row_groups_avail,
9693cc ¤   ······JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
e8dddd ¤   ······JDIMENSION out_rows_avail)
3dbb36 {
ca426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
440dcc ··int ci;
f4bcae ··jpeg_component_info * compptr;
77ae22 ··JDIMENSION num_rows;
01af5a
1450e6 ··/* Fill the conversion buffer, if it's empty */
ff437c ··if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
da6090 ····for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
7bb5ed ¤   ·ci++, compptr++) {
45d75d ······/* Invoke per-component upsample method. ·Notice we pass a POINTER
303c7b ·······* to color_buf[ci], so that fullsize_upsample can change it.
eee9f1 ·······*/
ac1628 ······(*upsample->methods[ci]) (cinfo, compptr,
12783f ¤   input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
f79aea ¤   upsample->color_buf + ci);
546fe7 ····}
734816 ····upsample->next_row_out = 0;
eedf1c ··}
0faf5a
ad639e ··/* Color-convert and emit rows */
ecaf5a
5e58bd ··/* How many we have in the buffer: */
632041 ··num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
25a120 ··/* Not more than the distance to the end of the image. ·Need this test
67ddd7 ···* in case the image height is not a multiple of max_v_samp_factor:
cef9a6 ···*/
9a2230 ··if (num_rows > upsample->rows_to_go)·
e70cda ····num_rows = upsample->rows_to_go;
7a8fde ··/* And not more than what the client can accept: */
705594 ··out_rows_avail -= *out_row_ctr;
3c087f ··if (num_rows > out_rows_avail)
476f34 ····num_rows = out_rows_avail;
0faf5a
cc0954 ··(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
2160c1 ¤   ¤   ¤   ¤   ·····(JDIMENSION) upsample->next_row_out,
f7a635 ¤   ¤   ¤   ¤   ·····output_buf + *out_row_ctr,
4e78ce ¤   ¤   ¤   ¤   ·····(int) num_rows);
6caf5a
1a4005 ··/* Adjust counts */
31c101 ··*out_row_ctr += num_rows;
842858 ··upsample->rows_to_go -= num_rows;
f11b6e ··upsample->next_row_out += num_rows;
7b0416 ··/* When the buffer is emptied, declare this input row group consumed */
0e4a60 ··if (upsample->next_row_out >= cinfo->max_v_samp_factor)
060916 ····(*in_row_group_ctr)++;
c9efe6 }
3eaf5a
efaf5a
7938e5 /*
4b4dd0 ·* These are the routines invoked by sep_upsample to upsample pixel values
--af30 000ca0f0ca84010002d Page 3 of jdsample.c
b493e8 ·* of a single component. ·One row group is processed per call.
e9495d ·*/
a7af5a
7faf5a
6f38e5 /*
82a861 ·* For full-size components, we just make color_buf[ci] point at the
420b3a ·* input buffer, and thus avoid copying any data. ·Note that this is
e0af4a ·* safe only because sep_upsample doesn't declare the input row group
3eda41 ·* "consumed" until we are done color converting and emitting it.
27495d ·*/
01af5a
480434 METHODDEF(void)
783c7b fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
d2a906 ¤   ¤   ···JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
82bb36 {
89a681 ··*output_data_ptr = input_data;
beefe6 }
3daf5a
4baf5a
2c38e5 /*
88e166 ·* This is a no-op version used for "uninteresting" components.
e0b0a1 ·* These components will not be referenced by color conversion.
e6495d ·*/
98af5a
060434 METHODDEF(void)
5a5765 noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
9b48f9 ¤   ·······JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
8ebb36 {
54bfea ··*output_data_ptr = NULL;¤ /* safety check */
faefe6 }
28af5a
cdaf5a
c638e5 /*
aa0f80 ·* This version handles any integral sampling ratios.
ff81ce ·* This is not used for typical JPEG files, so it need not be fast.
aa1033 ·* Nor, for that matter, is it particularly accurate: the algorithm is
73198e ·* simple replication of the input pixel onto the corresponding output
4a51d2 ·* pixels. ·The hi-falutin sampling literature refers to this as a
35bd24 ·* "box filter". ·A box filter tends to introduce visible artifacts,
588ada ·* so if you are actually going to use 3:1 or 4:1 sampling ratios
38b9d9 ·* you would be well advised to improve this code.
4e495d ·*/
f7af5a
210434 METHODDEF(void)
e7801a int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
dafab4 ¤   ······JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
c3bb36 {
50426e ··my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
9e257f ··JSAMPARRAY output_data = *output_data_ptr;
ee43b7 ··register JSAMPROW inptr, outptr;
ab36d2 ··register JSAMPLE invalue;
066337 ··register int h;
fa40d8 ··JSAMPROW outend;
cc9f79 ··int h_expand, v_expand;
cdbdba ··int inrow, outrow;
73af5a
aed055 ··h_expand = upsample->h_expand[compptr->component_index];
9fb876 ··v_expand = upsample->v_expand[compptr->component_index];
52af5a
6e201b ··inrow = outrow = 0;
fe08c6 ··while (outrow < cinfo->max_v_samp_factor) {
330f4a ····/* Generate one output row with proper horizontal expansion */
a88688 ····inptr = input_data[inrow];
19a315 ····outptr = output_data[outrow];
941b5c ····outend = outptr + cinfo->output_width;
782696 ····while (outptr < outend) {
ac918a ······invalue = *inptr++;¤  /* don't need GETJSAMPLE() here */
f16308 ······for (h = h_expand; h > 0; h--) {
2de593 ¤   *outptr++ = invalue;
5242cc ······}
166fe7 ····}
ca9fd2 ····/* Generate any additional output rows by duplicating the first one */
--b134 000a1fe32724010002d Page 4 of jdsample.c
2dd9fb ····if (v_expand > 1) {
587efe ······jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
5ee0d1 ¤   ¤   ¤   v_expand-1, cinfo->output_width);
a76fe7 ····}
117b7d ····inrow++;
a870e0 ····outrow += v_expand;
74df1c ··}
fbefe6 }
cfaf5a
64af5a
7a38e5 /*
dc9146 ·* Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
917751 ·* It's still a box filter.
e6495d ·*/
7baf5a
910434 METHODDEF(void)
4fa496 h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
9348f9 ¤   ·······JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
94bb36 {
07257f ··JSAMPARRAY output_data = *output_data_ptr;
d543b7 ··register JSAMPROW inptr, outptr;
ba36d2 ··register JSAMPLE invalue;
5440d8 ··JSAMPROW outend;
df7cbf ··int inrow;
89af5a
9a98b2 ··for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
818688 ····inptr = input_data[inrow];
61664f ····outptr = output_data[inrow];
431b5c ····outend = outptr + cinfo->output_width;
9e2696 ····while (outptr < outend) {
c7918a ······invalue = *inptr++;¤  /* don't need GETJSAMPLE() here */
6badd8 ······*outptr++ = invalue;
22add8 ······*outptr++ = invalue;
ac6fe7 ····}
fedf1c ··}
05efe6 }
1daf5a
b0af5a
d138e5 /*
091278 ·* Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
727751 ·* It's still a box filter.
9b495d ·*/
97af5a
5f0434 METHODDEF(void)
5ed77c h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
db48f9 ¤   ·······JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
5cbb36 {
84257f ··JSAMPARRAY output_data = *output_data_ptr;
ec43b7 ··register JSAMPROW inptr, outptr;
4736d2 ··register JSAMPLE invalue;
1c40d8 ··JSAMPROW outend;
cfbdba ··int inrow, outrow;
13af5a
3a201b ··inrow = outrow = 0;
1608c6 ··while (outrow < cinfo->max_v_samp_factor) {
5d8688 ····inptr = input_data[inrow];
10a315 ····outptr = output_data[outrow];
461b5c ····outend = outptr + cinfo->output_width;
5a2696 ····while (outptr < outend) {
1a918a ······invalue = *inptr++;¤  /* don't need GETJSAMPLE() here */
97add8 ······*outptr++ = invalue;
f6add8 ······*outptr++ = invalue;
756fe7 ····}
48be07 ····jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
64fc71 ¤   ¤   ······1, cinfo->output_width);
c57b7d ····inrow++;
273ba8 ····outrow += 2;
07df1c ··}
8eefe6 }
c9af5a
11af5a
a138e5 /*
--4fdf 000b9d2f9554010002d Page 5 of jdsample.c
2f1609 ·* Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
43775e ·*
cef86a ·* The upsampling algorithm is linear interpolation between pixel centers,
afab5c ·* also known as a "triangle filter". ·This is a good compromise between
5b50b5 ·* speed and visual quality. ·The centers of the output pixels are 1/4 and 3/4
e7c62f ·* of the way between input pixel centers.
28775e ·*
762846 ·* A note about the "bias" calculations: when rounding fractional values to
cc27d9 ·* integer, we do not want to always round 0.5 up to the next integer.
939b35 ·* If we did that, we'd introduce a noticeable bias towards larger values.
992e90 ·* Instead, this code is arranged so that 0.5 will be rounded up or down at
c295bb ·* alternate pixel locations (a simple ordered dither pattern).
d0495d ·*/
e3af5a
f10434 METHODDEF(void)
a88d66 h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
6ab86a ¤   ¤   ·····JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
cfbb36 {
39257f ··JSAMPARRAY output_data = *output_data_ptr;
b943b7 ··register JSAMPROW inptr, outptr;
d38316 ··register int invalue;
d6d954 ··register JDIMENSION colctr;
867cbf ··int inrow;
70af5a
4798b2 ··for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
348688 ····inptr = input_data[inrow];
60664f ····outptr = output_data[inrow];
50c622 ····/* Special case for first column */
99616c ····invalue = GETJSAMPLE(*inptr++);
58cd8a ····*outptr++ = (JSAMPLE) invalue;
5effdd ····*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
11af5a
096805 ····for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
c22729 ······/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
e25407 ······invalue = GETJSAMPLE(*inptr++) * 3;
f8b145 ······*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
824c03 ······*outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
646fe7 ····}
03af5a
42c30e ····/* Special case for last column */
80b462 ····invalue = GETJSAMPLE(*inptr);
4ea476 ····*outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
d6cd8a ····*outptr++ = (JSAMPLE) invalue;
b9df1c ··}
1fefe6 }
12af5a
ddaf5a
d438e5 /*
919537 ·* Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
f46294 ·* Again a triangle filter; see comments for h2v1 case, above.
cd775e ·*
82fd10 ·* It is OK for us to reference the adjacent input rows because we demanded
457167 ·* context from the main buffer controller (see initialization code).
6d495d ·*/
caaf5a
ae0434 METHODDEF(void)
c72e44 h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
4fb86a ¤   ¤   ·····JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
cabb36 {
ea257f ··JSAMPARRAY output_data = *output_data_ptr;
0f3b2a ··register JSAMPROW inptr0, inptr1, outptr;
fe6f80 #if BITS_IN_JSAMPLE == 8
b6c9aa ··register int thiscolsum, lastcolsum, nextcolsum;
0bdb21 #else
189fed ··register INT32 thiscolsum, lastcolsum, nextcolsum;
a47454 #endif
b9d954 ··register JDIMENSION colctr;
250f1e ··int inrow, outrow, v;
4baf5a
2f201b ··inrow = outrow = 0;
5308c6 ··while (outrow < cinfo->max_v_samp_factor) {
b99d1f ····for (v = 0; v < 2; v++) {
--cb13 000f11be98a4010002d Page 6 of jdsample.c
733e38 ······/* inptr0 points to nearest input row, inptr1 points to next nearest */
29bbab ······inptr0 = input_data[inrow];
50840c ······if (v == 0)¤  ¤   /* next nearest is row above */
38787c ¤   inptr1 = input_data[inrow-1];
a81291 ······else¤ ¤   ¤   /* next nearest is row below */
fc43e4 ¤   inptr1 = input_data[inrow+1];
cc188a ······outptr = output_data[outrow++];
d8af5a
afd7a9 ······/* Special case for first column */
bd3f52 ······thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
c86846 ······nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
d35025 ······*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
7bc4d3 ······*outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
626434 ······lastcolsum = thiscolsum; thiscolsum = nextcolsum;
29af5a
09c686 ······for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
72e5a1 ¤   /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
c245ff ¤   /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
594a3e ¤   nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
fe0f67 ¤   *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
a4e6ab ¤   *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
127502 ¤   lastcolsum = thiscolsum; thiscolsum = nextcolsum;
e142cc ······}
baaf5a
eac10f ······/* Special case for last column */
772d1f ······*outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
c6fdf9 ······*outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
e66fe7 ····}
d07b7d ····inrow++;
95df1c ··}
68efe6 }
eeaf5a
90af5a
e938e5 /*
84d483 ·* Module initialization routine for upsampling.
f1495d ·*/
a6af5a
b3f898 GLOBAL(void)
cab1c2 jinit_upsampler (j_decompress_ptr cinfo)
1dbb36 {
d0fd0c ··my_upsample_ptr upsample;
bc0dcc ··int ci;
9ebcae ··jpeg_component_info * compptr;
50ee97 ··boolean need_buffer, do_fancy;
a6f010 ··int h_in_group, v_in_group, h_out_group, v_out_group;
11af5a
5a89b8 ··upsample = (my_upsample_ptr)
3d3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
543a5b ¤   ¤   ¤   ¤   SIZEOF(my_upsampler));
485c58 ··cinfo->upsample = (struct jpeg_upsampler *) upsample;
1e8351 ··upsample->pub.start_pass = start_pass_upsample;
71ef15 ··upsample->pub.upsample = sep_upsample;
c6814b ··upsample->pub.need_context_rows = FALSE; /* until we find out differently */
33af5a
bb4441 ··if (cinfo->CCIR601_sampling)¤ /* this isn't supported */
3a4065 ····ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
aeaf5a
be9238 ··/* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
972a13 ···* so don't ask for it.
77f9a6 ···*/
0209e0 ··do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
2baf5a
fa77a3 ··/* Verify we can handle the sampling factors, select per-component methods,
31448e ···* and create storage as needed.
9df9a6 ···*/
f0958b ··for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
6daa07 ·······ci++, compptr++) {
84ff12 ····/* Compute size of an "input group" after IDCT scaling. ·This many samples
7e0f0a ·····* are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
8ad48d ·····*/
261270 ····h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
f1828d ¤   ¤   ·cinfo->min_DCT_scaled_size;
--faa5 00166fc98114010002d Page 7 of jdsample.c
db0de2 ····v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
f5828d ¤   ¤   ·cinfo->min_DCT_scaled_size;
464c30 ····h_out_group = cinfo->max_h_samp_factor;
2eb1a7 ····v_out_group = cinfo->max_v_samp_factor;
0b38cb ····upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
782fe7 ····need_buffer = TRUE;
694426 ····if (! compptr->component_needed) {
6f0c45 ······/* Don't bother to upsample an uninteresting component. */
40d636 ······upsample->methods[ci] = noop_upsample;
944401 ······need_buffer = FALSE;
8e453b ····} else if (h_in_group == h_out_group && v_in_group == v_out_group) {
27fea0 ······/* Fullsize components can be processed without any work. */
6b1dcf ······upsample->methods[ci] = fullsize_upsample;
9e4401 ······need_buffer = FALSE;
a77f59 ····} else if (h_in_group * 2 == h_out_group &&
87c599 ¤   ·······v_in_group == v_out_group) {
11b33f ······/* Special cases for 2h1v upsampling */
d5f753 ······if (do_fancy && compptr->downsampled_width > 2)
0a65eb ¤   upsample->methods[ci] = h2v1_fancy_upsample;
9b3dfa ······else
39a6f7 ¤   upsample->methods[ci] = h2v1_upsample;
287f59 ····} else if (h_in_group * 2 == h_out_group &&
ff6665 ¤   ·······v_in_group * 2 == v_out_group) {
6f832e ······/* Special cases for 2h2v upsampling */
07b1d8 ······if (do_fancy && compptr->downsampled_width > 2) {
0964d3 ¤   upsample->methods[ci] = h2v2_fancy_upsample;
a12e34 ¤   upsample->pub.need_context_rows = TRUE;
aeedd4 ······} else
6f2119 ¤   upsample->methods[ci] = h2v2_upsample;
4abf5c ····} else if ((h_out_group % h_in_group) == 0 &&
a49e01 ¤   ·······(v_out_group % v_in_group) == 0) {
88fd8f ······/* Generic integral-factors upsampling method */
171722 ······upsample->methods[ci] = int_upsample;
0deee5 ······upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
cc840d ······upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
d6ce75 ····} else
aefd7c ······ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
082fe4 ····if (need_buffer) {
c38cd0 ······upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
12ee7d ¤   ((j_common_ptr) cinfo, JPOOL_IMAGE,
8797ad ¤   ·(JDIMENSION) jround_up((long) cinfo->output_width,
06911a ¤   ¤   ¤   ¤   (long) cinfo->max_h_samp_factor),
6222ec ¤   ·(JDIMENSION) cinfo->max_v_samp_factor);
116fe7 ····}
acdf1c ··}
66efe6 }
--d08b 0000922eb8d4010002e Page 1 of jdtrans.c
bc38e5 /*
9e65e4 ·* jdtrans.c
59775e ·*
90c561 ·* Copyright (C) 1995-1996, Thomas G. Lane.
8afb07 ·* This file is part of the Independent JPEG Group's software.
8ea0d6 ·* For conditions of distribution and use, see the accompanying README file.
e8775e ·*
bf86bd ·* This file contains library routines for transcoding decompression,
fd5260 ·* that is, reading raw DCT coefficient arrays from an input JPEG file.
d0e88b ·* The routines in jdapimin.c will also be needed by a transcoder.
60495d ·*/
37af5a
892bb6 #define JPEG_INTERNALS
b536a7 #include "jinclude.h"
d36c8f #include "jpeglib.h"
ceaf5a
53af5a
166a43 /* Forward declarations */
ad9800 LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
43af5a
ceaf5a
8638e5 /*
b85dd9 ·* Read the coefficient arrays from a JPEG file.
075a35 ·* jpeg_read_header must be completed before calling this.
d1775e ·*
9c69cc ·* The entire image is read into a set of virtual coefficient-block arrays,
52b297 ·* one per component. ·The return value is a pointer to the array of
b04466 ·* virtual-array descriptors. ·These can be manipulated directly via the
a9102a ·* JPEG memory manager, or handed off to jpeg_write_coefficients().
08ca4c ·* To release the memory occupied by the virtual arrays, call
1c162d ·* jpeg_finish_decompress() when done with the data.
8e775e ·*
432319 ·* Returns NULL if suspended. ·This case need be checked only if
8a6f4f ·* a suspending data source is used.
9c495d ·*/
7caf5a
6cf826 GLOBAL(jvirt_barray_ptr *)
002092 jpeg_read_coefficients (j_decompress_ptr cinfo)
59bb36 {
fa1ca0 ··if (cinfo->global_state == DSTATE_READY) {
cab931 ····/* First call: initialize active modules */
2c4db3 ····transdecode_master_selection(cinfo);
780178 ····cinfo->global_state = DSTATE_RDCOEFS;
ec1a33 ··} else if (cinfo->global_state != DSTATE_RDCOEFS)
fc918e ····ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
beab8c ··/* Absorb whole file into the coef buffer */
676015 ··for (;;) {
5cf1cd ····int retcode;
d1b4db ····/* Call progress monitor hook if present */
4360a7 ····if (cinfo->progress != NULL)
d1e143 ······(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
d73371 ····/* Absorb some more input */
cd9fa8 ····retcode = (*cinfo->inputctl->consume_input) (cinfo);
160a04 ····if (retcode == JPEG_SUSPENDED)
a6841b ······return NULL;
0a0e4a ····if (retcode == JPEG_REACHED_EOI)
f888e1 ······break;
bd71a1 ····/* Advance progress counter if appropriate */
ef06b3 ····if (cinfo->progress != NULL &&
9b32f5 ¤   (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
df7bc0 ······if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
852a57 ¤   /* startup underestimated number of scans; ratchet up one scan */
cad1ae ¤   cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
5142cc ······}
1b6fe7 ····}
c0df1c ··}
8fce36 ··/* Set state so that jpeg_finish_decompress does the right thing */
94d056 ··cinfo->global_state = DSTATE_STOPPING;
680835 ··return cinfo->coef->coef_arrays;
c3efe6 }
94af5a
09af5a
--961a 0016e731ade4010002e Page 2 of jdtrans.c
bc38e5 /*
59cc00 ·* Master selection of decompression modules for transcoding.
b858d5 ·* This substitutes for jdmaster.c's initialization of the full decompressor.
88495d ·*/
67af5a
03afad LOCAL(void)
61f86d transdecode_master_selection (j_decompress_ptr cinfo)
efbb36 {
d762ed ··/* Entropy decoding: either Huffman or arithmetic coding. */
16a4f1 ··if (cinfo->arith_code) {
933fef ····ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
3149d8 ··} else {
d48aef ····if (cinfo->progressive_mode) {
2ee060 #ifdef D_PROGRESSIVE_SUPPORTED
17f895 ······jinit_phuff_decoder(cinfo);
c3db21 #else
019015 ······ERREXIT(cinfo, JERR_NOT_COMPILED);
dd7454 #endif
dbce75 ····} else
1ab69e ······jinit_huff_decoder(cinfo);
9bdf1c ··}
31af5a
d83625 ··/* Always get a full-image coefficient buffer. */
e1d713 ··jinit_d_coef_controller(cinfo, TRUE);
70af5a
665924 ··/* We can now tell the memory manager to allocate virtual arrays. */
43a9b1 ··(*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
0daf5a
3aab3e ··/* Initialize input side of decompressor to consume first scan. */
091eb6 ··(*cinfo->inputctl->start_input_pass) (cinfo);
bbaf5a
d4c9be ··/* Initialize progress monitoring. */
5efeda ··if (cinfo->progress != NULL) {
2ecbad ····int nscans;
9f5648 ····/* Estimate number of scans to set pass_limit. */
0d8aef ····if (cinfo->progressive_mode) {
fdd25e ······/* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
916f32 ······nscans = 2 + 3 * cinfo->num_components;
259407 ····} else if (cinfo->inputctl->has_multiple_scans) {
1ac6b7 ······/* For a nonprogressive multiscan file, estimate 1 scan per component. */
e807c0 ······nscans = cinfo->num_components;
056a79 ····} else {
247efc ······nscans = 1;
556fe7 ····}
5c4747 ····cinfo->progress->pass_counter = 0L;
25f6fd ····cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
d759b9 ····cinfo->progress->completed_passes = 0;
c0f0b2 ····cinfo->progress->total_passes = 1;
abdf1c ··}
6eefe6 }
--da19 0001f5ba4da4010002f Page 1 of jerror.c
bc38e5 /*
f84a16 ·* jerror.c
88775e ·*
3fa060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
4dfb07 ·* This file is part of the Independent JPEG Group's software.
d2a0d6 ·* For conditions of distribution and use, see the accompanying README file.
b7775e ·*
683a44 ·* This file contains simple error-reporting and trace-message routines.
ced770 ·* These are suitable for Unix-like systems and others where writing to
e86878 ·* stderr is the right thing to do. ·Many applications will want to replace
7b64ee ·* some or all of these routines.
d5775e ·*
bbabbf ·* These routines are used by both the compression and decompression code.
96495d ·*/
45af5a
fa9596 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
b536a7 #include "jinclude.h"
576c8f #include "jpeglib.h"
2870d7 #include "jversion.h"
df46a4 #include "jerror.h"
e8af5a
ffc093 #ifndef EXIT_FAILURE¤   ¤   /* define exit() codes if not provided */
f7c447 #define EXIT_FAILURE ·1
da7454 #endif
a3af5a
bfaf5a
5b38e5 /*
a82219 ·* Create the message string table.
45b7ee ·* We do this from the master message list in jerror.h by re-reading
8a5939 ·* jerror.h with a suitable definition for macro JMESSAGE.
69d4e5 ·* The message table is made an external symbol just in case any applications
ab9efa ·* want to refer to it directly.
37495d ·*/
38af5a
bdddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
230854 #define jpeg_std_message_table¤ jMsgTable
c27454 #endif
59af5a
4e34af #define JMESSAGE(code,string)¤  string ,
56af5a
e58d1f const char * const jpeg_std_message_table[] = {
9846a4 #include "jerror.h"
63b17e ··NULL
cf82f7 };
edaf5a
faaf5a
e838e5 /*
c74e16 ·* Error exit handler: must not return to caller.
61775e ·*
093fa4 ·* Applications may override this if they want to get control back after
60e626 ·* an error. ·Typically one would longjmp somewhere instead of exiting.
f9f721 ·* The setjmp buffer can be made a private field within an expanded error
a520e7 ·* handler object. ·Note that the info needed to generate an error message
b64fe2 ·* is stored in the error object, so you can generate the message now or
672d35 ·* later, at your convenience.
e4630d ·* You should make sure that the JPEG object is cleaned up (with jpeg_abort
918fb2 ·* or jpeg_destroy) at some point.
8b495d ·*/
94af5a
260434 METHODDEF(void)
c4ebeb error_exit (j_common_ptr cinfo)
51bb36 {
e018fb ··/* Always display the message */
7759c4 ··(*cinfo->err->output_message) (cinfo);
deaf5a
5a7656 ··/* Let the memory manager delete any temp files before we die */
c7b11e ··jpeg_destroy(cinfo);
37af5a
94870b ··exit(EXIT_FAILURE);
99efe6 }
81af5a
1faf5a
--2bbf 000b1fd8aa44010002f Page 2 of jerror.c
bc38e5 /*
688397 ·* Actual output of an error or trace message.
f84580 ·* Applications may override this method to send JPEG messages somewhere
06e0b9 ·* other than stderr.
c5495d ·*/
c3af5a
5a0434 METHODDEF(void)
e3158c output_message (j_common_ptr cinfo)
adbb36 {
565eac ··char buffer[JMSG_LENGTH_MAX];
6aaf5a
aceb5f ··/* Create the message */
11a108 ··(*cinfo->err->format_message) (cinfo, buffer);
39af5a
52d8b0 ··/* Send it to stderr, adding a newline */
80af43 ··fprintf(stderr, "%s\n", buffer);
f4efe6 }
99af5a
04af5a
9b38e5 /*
1289de ·* Decide whether to emit a trace or warning message.
36c94c ·* msg_level is one of:
60631e ·* ··-1: recoverable corrupt-data warning, may want to abort.
5067e0 ·* ···0: important advisory messages (always display to user).
eb4606 ·* ···1: first level of tracing detail.
5a4077 ·* ···2,3,...: successively more detailed tracing messages.
a7e7da ·* An application might override this method if it wanted to abort on warnings
d383af ·* or change the policy about which messages to display.
a4495d ·*/
88af5a
bc0434 METHODDEF(void)
7dfff9 emit_message (j_common_ptr cinfo, int msg_level)
3fbb36 {
d7ec38 ··struct jpeg_error_mgr * err = cinfo->err;
1aaf5a
dc61dd ··if (msg_level < 0) {
205ab6 ····/* It's a warning message. ·Since corrupt files may generate many warnings,
58b4dc ·····* the policy implemented here is to show only the first warning,
9220ee ·····* unless trace_level >= 3.
05d48d ·····*/
0d1fab ····if (err->num_warnings == 0 || err->trace_level >= 3)
9ac53b ······(*err->output_message) (cinfo);
e39062 ····/* Always count warnings in num_warnings. */
c700a3 ····err->num_warnings++;
9549d8 ··} else {
8b1ec8 ····/* It's a trace message. ·Show it if trace_level >= msg_level. */
a2895f ····if (err->trace_level >= msg_level)
d9c53b ······(*err->output_message) (cinfo);
c1df1c ··}
abefe6 }
f3af5a
61af5a
7938e5 /*
b23671 ·* Format a message string for the most recent JPEG error or message.
d992a4 ·* The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
eec1fe ·* characters. ·Note that no '\n' character is added to the string.
829a34 ·* Few applications should need to override this method.
6e495d ·*/
9faf5a
f50434 METHODDEF(void)
3c018f format_message (j_common_ptr cinfo, char * buffer)
67bb36 {
b6ec38 ··struct jpeg_error_mgr * err = cinfo->err;
3b0d9c ··int msg_code = err->msg_code;
0af7f9 ··const char * msgtext = NULL;
420661 ··const char * msgptr;
629456 ··char ch;
9fd6be ··boolean isstring;
9faf5a
ea29f9 ··/* Look up message string in proper table */
567db6 ··if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
b1f0e9 ····msgtext = err->jpeg_message_table[msg_code];
--ed93 00087b4fec74010002f Page 3 of jerror.c
4912db ··} else if (err->addon_message_table != NULL &&
18d411 ¤   ·····msg_code >= err->first_addon_message &&
a46070 ¤   ·····msg_code <= err->last_addon_message) {
035794 ····msgtext = err->addon_message_table[msg_code - err->first_addon_message];
b8df1c ··}
41af5a
45b155 ··/* Defend against bogus message number */
a1c9ac ··if (msgtext == NULL) {
40b3d7 ····err->msg_parm.i[0] = msg_code;
05b3ee ····msgtext = err->jpeg_message_table[0];
94df1c ··}
6faf5a
3a68eb ··/* Check for string parameter, as indicated by %s in the message text */
49acf2 ··isstring = FALSE;
5e50cb ··msgptr = msgtext;
904e5b ··while ((ch = *msgptr++) != '\0') {
0955d6 ····if (ch == '%') {
03dc9d ······if (*msgptr == 's') isstring = TRUE;
5f88e1 ······break;
5c6fe7 ····}
1cdf1c ··}
50af5a
185635 ··/* Format the message into the passed buffer */
c5b103 ··if (isstring)
521c2c ····sprintf(buffer, msgtext, err->msg_parm.s);
bb1bd0 ··else
cc672d ····sprintf(buffer, msgtext,
39a67b ¤   ····err->msg_parm.i[0], err->msg_parm.i[1],
2c2985 ¤   ····err->msg_parm.i[2], err->msg_parm.i[3],
97b196 ¤   ····err->msg_parm.i[4], err->msg_parm.i[5],
dcd6ed ¤   ····err->msg_parm.i[6], err->msg_parm.i[7]);
7befe6 }
5aaf5a
03af5a
7438e5 /*
3aebcc ·* Reset error state variables at start of a new image.
fb6bba ·* This is called during compression startup to reset trace/error
8416bb ·* processing to default state, without losing any application-specific
c907ec ·* method pointers. ·An application might possibly want to override
e95d80 ·* this method if it has additional error processing state.
32495d ·*/
f9af5a
720434 METHODDEF(void)
125b48 reset_error_mgr (j_common_ptr cinfo)
56bb36 {
b6476b ··cinfo->err->num_warnings = 0;
da289b ··/* trace_level is not reset since it is an application-supplied parameter */
d3e480 ··cinfo->err->msg_code = 0;¤/* may be useful as a flag for "no error" */
d4efe6 }
b3af5a
38af5a
ae38e5 /*
935976 ·* Fill in the standard error-handling methods in a jpeg_error_mgr object.
8dd165 ·* Typical call is:
c146c9 ·*¤ struct jpeg_compress_struct cinfo;
7ffc44 ·*¤ struct jpeg_error_mgr err;
03775e ·*
e6e742 ·*¤ cinfo.err = jpeg_std_error(&err);
e45569 ·* after which the application may override some of the methods.
4d495d ·*/
14af5a
623248 GLOBAL(struct jpeg_error_mgr *)
a53da1 jpeg_std_error (struct jpeg_error_mgr * err)
75bb36 {
e902cf ··err->error_exit = error_exit;
77951a ··err->emit_message = emit_message;
e96878 ··err->output_message = output_message;
8bd5c3 ··err->format_message = format_message;
5dab0f ··err->reset_error_mgr = reset_error_mgr;
d8af5a
581132 ··err->trace_level = 0;¤¤   /* default = no tracing */
87c9da ··err->num_warnings = 0;¤   /* no warnings emitted yet */
--7530 001f74d15a44010002f Page 4 of jerror.c
0de6b9 ··err->msg_code = 0;¤   ¤   /* may be useful as a flag for "no error" */
c3af5a
daea35 ··/* Initialize message table pointers */
1c6cae ··err->jpeg_message_table = jpeg_std_message_table;
693ebc ··err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
8faf5a
ba1287 ··err->addon_message_table = NULL;
a2f25d ··err->first_addon_message = 0;¤/* for safety */
18ce01 ··err->last_addon_message = 0;
8eaf5a
2df0b8 ··return err;
f7efe6 }
--ca68 000b01b467640100030 Page 1 of jerror.h
bc38e5 /*
1baebe ·* jerror.h
ff775e ·*
9f23ef ·* Copyright (C) 1994-1995, Thomas G. Lane.
bcfb07 ·* This file is part of the Independent JPEG Group's software.
13a0d6 ·* For conditions of distribution and use, see the accompanying README file.
3e775e ·*
aea67e ·* This file defines the error and message codes for the JPEG library.
9e9990 ·* Edit this file to add new codes, or to translate the message strings to
d1699d ·* some other language.
677836 ·* A set of error-reporting macros are defined too. ·Some applications using
8acd71 ·* the JPEG library may wish to include this file to get the error codes
065559 ·* and/or the macros.
7b495d ·*/
b4af5a
d238e5 /*
63af09 ·* To define the enum list of message codes, include this file without
70163d ·* defining macro JMESSAGE. ·To create a message string table, include it
f41f24 ·* again with a suitable JMESSAGE definition (see jerror.c for an example).
ae495d ·*/
56d834 #ifndef JMESSAGE
395541 #ifndef JERROR_H
4ab757 /* First time through, define the enum list */
9e51ef #define JMAKE_ENUM_LIST
f5db21 #else
b158d3 /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
803c98 #define JMESSAGE(code,string)
157493 #endif /* JERROR_H */
33f142 #endif /* JMESSAGE */
10af5a
57e0f9 #ifdef JMAKE_ENUM_LIST
7baf5a
46ed84 typedef enum {
baaf5a
edb723 #define JMESSAGE(code,string)¤  code ,
38af5a
b0b694 #endif /* JMAKE_ENUM_LIST */
e3af5a
64e6a8 JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
58af5a
5069a3 /* For maintenance convenience, list is alphabetical by message code name */
07356e JMESSAGE(JERR_ARITH_NOTIMPL,
a459de ¤   ·"Sorry, there are legal restrictions on arithmetic coding")
d2a373 JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
94eb8b JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
ed682b JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
8b7791 JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
4f20c4 JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
00c2f0 JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
05795b JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
e92c9b JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
6d2118 JMESSAGE(JERR_BAD_LIB_VERSION,
3fa85f ¤   ·"Wrong JPEG library version: library is %d, caller expects %d")
bf3c20 JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
600563 JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
5de7ff JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
6174eb JMESSAGE(JERR_BAD_PROGRESSION,
5d834f ¤   ·"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
9c09a5 JMESSAGE(JERR_BAD_PROG_SCRIPT,
681f03 ¤   ·"Invalid progressive parameters at scan script entry %d")
734f95 JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
9c0e18 JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
017480 JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
276c82 JMESSAGE(JERR_BAD_STRUCT_SIZE,
ed2274 ¤   ·"JPEG parameter struct mismatch: library thinks size is %u, caller expects¶
9a4186 ·%u")
794d9c JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
50fdad JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
378080 JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
8f57ac JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
fdba84 JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
b009ce JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
--4d44 000b887b01f40100030 Page 2 of jerror.h
491ece JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
4de20a JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
3cfe0f JMESSAGE(JERR_DHT_COUNTS, "Bogus DHT counts")
8b61b7 JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
87bcff JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
e21331 JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
2f17ba JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
8c2dbf JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
06575f JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
cc298d JMESSAGE(JERR_FILE_READ, "Input file read error")
8e6a28 JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
7557fa JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
573297 JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
3b9d46 JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
6f8954 JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
672903 JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
3d93b6 JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
619b24 JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
09e578 ¤   ·"Cannot transcode due to multiple use of quantization table %d")
1537bf JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
7a585c JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
f76dda JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
86d7ba JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
84afea JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
842d58 JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
7bd2bf JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
3d3f93 JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
03b97e JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
712f56 JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
68ea00 JMESSAGE(JERR_QUANT_COMPONENTS,
b5bc07 ¤   ·"Cannot quantize more than %d color components")
d163ac JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
03a693 JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
ad74e6 JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
eee9a6 JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
0eb72b JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
c61764 JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
b2761a JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
968c7b JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
ae172c JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
f3498b JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
1e7e88 JMESSAGE(JERR_TFILE_WRITE,
990f92 ¤   ·"Write failed on temporary file --- out of disk space?")
bc586f JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
39f529 JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
c524c5 JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
832109 JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
4ec6ec JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
f8fce9 JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
0c6369 JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
682474 JMESSAGE(JMSG_VERSION, JVERSION)
1bf04b JMESSAGE(JTRC_16BIT_TABLES,
c2ec77 ¤   ·"Caution: quantization tables are too coarse for baseline JPEG")
0b48c5 JMESSAGE(JTRC_ADOBE,
a56edd ¤   ·"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
d3fe59 JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
67a32c JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
a580e2 JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
5cd17e JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
0553f1 JMESSAGE(JTRC_DQT, "Define Quantization Table %d ·precision %d")
66f499 JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
6a252b JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
bdf22a JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
b371c2 JMESSAGE(JTRC_EOI, "End Of Image")
f684b7 JMESSAGE(JTRC_HUFFBITS, " ·······%3d %3d %3d %3d %3d %3d %3d %3d")
214b13 JMESSAGE(JTRC_JFIF, "JFIF APP0 marker, density %dx%d ·%d")
3e961c JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
4fcfde ¤   ·"Warning: thumbnail image size does not match data length %u")
646f47 JMESSAGE(JTRC_JFIF_MINOR, "Unknown JFIF minor revision number %d.%02d")
8d3493 JMESSAGE(JTRC_JFIF_THUMBNAIL, " ···with %d x %d thumbnail image")
1e0414 JMESSAGE(JTRC_MISC_MARKER, "Skipping marker 0x%02x, length %u")
b8c0fc JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
--c292 00005c7492940100030 Page 3 of jerror.h
b1c195 JMESSAGE(JTRC_QUANTVALS, " ·······%4u %4u %4u %4u %4u %4u %4u %4u")
b68ad2 JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
c95b08 JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
d85324 JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
6883ac JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
4b1805 JMESSAGE(JTRC_RST, "RST%d")
da4906 JMESSAGE(JTRC_SMOOTH_NOTIMPL,
e69d34 ¤   ·"Smoothing not supported with nonstandard sampling ratios")
2507d9 JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
073fa1 JMESSAGE(JTRC_SOF_COMPONENT, " ···Component %d: %dhx%dv q=%d")
3fd3d1 JMESSAGE(JTRC_SOI, "Start of Image")
fc2b84 JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
dc5680 JMESSAGE(JTRC_SOS_COMPONENT, " ···Component %d: dc=%d ac=%d")
ba3806 JMESSAGE(JTRC_SOS_PARAMS, " ·Ss=%d, Se=%d, Ah=%d, Al=%d")
fe61e7 JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
d11937 JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
4fe8cb JMESSAGE(JTRC_UNKNOWN_IDS,
cb798c ¤   ·"Unrecognized component IDs %d %d %d, assuming YCbCr")
81c7e2 JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
937632 JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
9cb088 JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
c4400e JMESSAGE(JWRN_BOGUS_PROGRESSION,
81d54e ¤   ·"Inconsistent progression sequence for component %d coefficient %d")
55487b JMESSAGE(JWRN_EXTRANEOUS_DATA,
a8087c ¤   ·"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
b2819f JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
89b6b1 JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
f10a68 JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
0a38d1 JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
cbea7b JMESSAGE(JWRN_MUST_RESYNC,
1fe8ea ¤   ·"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
ca1930 JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
a8b179 JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
07af5a
f8e0f9 #ifdef JMAKE_ENUM_LIST
d4af5a
88440a ··JMSG_LASTMSGCODE
aa4828 } J_MESSAGE_CODE;
2aaf5a
7c4119 #undef JMAKE_ENUM_LIST
f8b694 #endif /* JMAKE_ENUM_LIST */
96af5a
d836e5 /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
d6518a #undef JMESSAGE
dfaf5a
3aaf5a
6c5541 #ifndef JERROR_H
28d92a #define JERROR_H
72af5a
965bd4 /* Macros to simplify using the error and trace message stuff */
ff920b /* The first parameter is either type of cinfo pointer */
d9af5a
d82a3d /* Fatal errors (print message and exit) */
63b31a #define ERREXIT(cinfo,code) ·\
4b2b73 ··((cinfo)->err->msg_code = (code), \
344acf ···(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
734d4e #define ERREXIT1(cinfo,code,p1) ·\
d22b73 ··((cinfo)->err->msg_code = (code), \
614299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
bb4acf ···(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
bd35a2 #define ERREXIT2(cinfo,code,p1,p2) ·\
f22b73 ··((cinfo)->err->msg_code = (code), \
674299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
384b49 ···(cinfo)->err->msg_parm.i[1] = (p2), \
214acf ···(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
3ffc95 #define ERREXIT3(cinfo,code,p1,p2,p3) ·\
ad2b73 ··((cinfo)->err->msg_code = (code), \
7d4299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
6e4b49 ···(cinfo)->err->msg_parm.i[1] = (p2), \
704195 ···(cinfo)->err->msg_parm.i[2] = (p3), \
c04acf ···(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
05c5b8 #define ERREXIT4(cinfo,code,p1,p2,p3,p4) ·\
--668e 001b6eb540940100030 Page 4 of jerror.h
572b73 ··((cinfo)->err->msg_code = (code), \
f14299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
a44b49 ···(cinfo)->err->msg_parm.i[1] = (p2), \
0b4195 ···(cinfo)->err->msg_parm.i[2] = (p3), \
2158e9 ···(cinfo)->err->msg_parm.i[3] = (p4), \
be4acf ···(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
219b15 #define ERREXITS(cinfo,code,str) ·\
4f2b73 ··((cinfo)->err->msg_code = (code), \
c163c2 ···strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
154acf ···(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
b0af5a
45cce5 #define MAKESTMT(stuff)¤¤   do { stuff } while (0)
1aaf5a
87508e /* Nonfatal errors (we can keep going, but the data is probably corrupt) */
f5c061 #define WARNMS(cinfo,code) ·\
b52b73 ··((cinfo)->err->msg_code = (code), \
f97211 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
5fb8a2 #define WARNMS1(cinfo,code,p1) ·\
c22b73 ··((cinfo)->err->msg_code = (code), \
2f4299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
507211 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
d59b10 #define WARNMS2(cinfo,code,p1,p2) ·\
de2b73 ··((cinfo)->err->msg_code = (code), \
624299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
904b49 ···(cinfo)->err->msg_parm.i[1] = (p2), \
507211 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
13af5a
20f2cc /* Informational/debugging messages */
b9cf57 #define TRACEMS(cinfo,lvl,code) ·\
9c2b73 ··((cinfo)->err->msg_code = (code), \
952388 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
f79e17 #define TRACEMS1(cinfo,lvl,code,p1) ·\
d32b73 ··((cinfo)->err->msg_code = (code), \
d44299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
242388 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
6a3b9e #define TRACEMS2(cinfo,lvl,code,p1,p2) ·\
3e2b73 ··((cinfo)->err->msg_code = (code), \
fa4299 ···(cinfo)->err->msg_parm.i[0] = (p1), \
e34b49 ···(cinfo)->err->msg_parm.i[1] = (p2), \
4f2388 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
38a82b #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) ·\
c665cf ··MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
d63b77 ¤   ···_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
bb8220 ¤   ···(cinfo)->err->msg_code = (code); \
33ce05 ¤   ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
7dddfb #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) ·\
7165cf ··MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
2cc828 ¤   ···_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
b38220 ¤   ···(cinfo)->err->msg_code = (code); \
02ce05 ¤   ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
0d00ef #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) ·\
6e65cf ··MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
0dc828 ¤   ···_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
7edf67 ¤   ···_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
2d8220 ¤   ···(cinfo)->err->msg_code = (code); \
f5ce05 ¤   ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
abc526 #define TRACEMSS(cinfo,lvl,code,str) ·\
7d2b73 ··((cinfo)->err->msg_code = (code), \
2163c2 ···strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
7b2388 ···(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
5daf5a
b67493 #endif /* JERROR_H */
--58c3 0006e363c9e40100031 Page 1 of jfdctflt.c
bc38e5 /*
638b7a ·* jfdctflt.c
79775e ·*
399e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
4efb07 ·* This file is part of the Independent JPEG Group's software.
7ea0d6 ·* For conditions of distribution and use, see the accompanying README file.
4a775e ·*
9a6e71 ·* This file contains a floating-point implementation of the
4a6eae ·* forward DCT (Discrete Cosine Transform).
57775e ·*
8c239c ·* This implementation should be more accurate than either of the integer
3a21ab ·* DCT implementations. ·However, it may not give the same results on all
fcdd80 ·* machines because of differences in roundoff behavior. ·Speed will depend
709742 ·* on the hardware's floating point capacity.
d5775e ·*
9177ab ·* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
92054f ·* on each column. ·Direct algorithms are also available, but they are
40dbb5 ·* much more complex and seem not to be any faster when reduced to code.
29775e ·*
3be291 ·* This implementation is based on Arai, Agui, and Nakajima's algorithm for
1247b3 ·* scaled DCT. ·Their original paper (Trans. IEICE E-71(11):1095) is in
b70273 ·* Japanese, but the algorithm is described in the Pennebaker & Mitchell
6b8fd4 ·* JPEG textbook (see REFERENCES section in file README). ·The following code
4eedb5 ·* is based directly on figure 4-8 in P&M.
31f36a ·* While an 8-point DCT cannot be done in less than 11 multiplies, it is
1d24d7 ·* possible to arrange the computation so that many of the multiplies are
b298d4 ·* simple scalings of the final outputs. ·These multiplies can then be
24cd69 ·* folded into the multiplications or divisions by the JPEG quantization
e9a9c0 ·* table entries. ·The AA&N method leaves only 5 multiplies and 29 adds
158471 ·* to be done in the DCT itself.
203c35 ·* The primary disadvantage of this method is that with a fixed-point
1d833c ·* implementation, accuracy is lost due to imprecise representation of the
62826f ·* scaled quantization values. ·However, that problem does not arise if
b03de0 ·* we use floating point arithmetic.
69495d ·*/
80af5a
cd2bb6 #define JPEG_INTERNALS
ef36a7 #include "jinclude.h"
f56c8f #include "jpeglib.h"
8eef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
a5af5a
346fd6 #ifdef DCT_FLOAT_SUPPORTED
41af5a
22af5a
2a38e5 /*
a2f914 ·* This module is specialized to the case DCTSIZE = 8.
09495d ·*/
66af5a
0d5f63 #if DCTSIZE != 8
925f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
577454 #endif
e6af5a
d8af5a
cc38e5 /*
8c79d7 ·* Perform the forward DCT on one block of samples.
fa495d ·*/
46af5a
b0f898 GLOBAL(void)
513792 jpeg_fdct_float (FAST_FLOAT * data)
aabb36 {
609b6d ··FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
f75a28 ··FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
8452e8 ··FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
e62984 ··FAST_FLOAT *dataptr;
c9de0b ··int ctr;
49af5a
99494e ··/* Pass 1: process rows. */
63af5a
7d5af4 ··dataptr = data;
26b327 ··for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
aa95ae ····tmp0 = dataptr[0] + dataptr[7];
6e6476 ····tmp7 = dataptr[0] - dataptr[7];
--21d4 00074e6299640100031 Page 2 of jfdctflt.c
47602b ····tmp1 = dataptr[1] + dataptr[6];
6991f3 ····tmp6 = dataptr[1] - dataptr[6];
3876b5 ····tmp2 = dataptr[2] + dataptr[5];
52876d ····tmp5 = dataptr[2] - dataptr[5];
0a8330 ····tmp3 = dataptr[3] + dataptr[4];
b172e8 ····tmp4 = dataptr[3] - dataptr[4];
36869e ····
f03f6a ····/* Even part */
19869e ····
6d1653 ····tmp10 = tmp0 + tmp3;¤   /* phase 2 */
c57bf4 ····tmp13 = tmp0 - tmp3;
a530a0 ····tmp11 = tmp1 + tmp2;
ee1d00 ····tmp12 = tmp1 - tmp2;
b7869e ····
4e7404 ····dataptr[0] = tmp10 + tmp11; /* phase 3 */
10b7c9 ····dataptr[4] = tmp10 - tmp11;
2d869e ····
ac89ce ····z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
2b41dc ····dataptr[2] = tmp13 + z1;¤   /* phase 5 */
c98dae ····dataptr[6] = tmp13 - z1;
04869e ····
2de722 ····/* Odd part */
44af5a
ea84b4 ····tmp10 = tmp4 + tmp5;¤   /* phase 2 */
83e35d ····tmp11 = tmp5 + tmp6;
2cfdf9 ····tmp12 = tmp6 + tmp7;
13af5a
cae7d8 ····/* The rotator is modified from fig 4-8 to avoid extra negations. */
dcae0e ····z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
a46715 ····z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
4bb6d1 ····z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
b0235a ····z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
f4af5a
ded456 ····z11 = tmp7 + z3;¤   ¤   /* phase 5 */
1a6eb6 ····z13 = tmp7 - z3;
94af5a
78befd ····dataptr[5] = z13 + z2;¤ /* phase 6 */
ab3129 ····dataptr[3] = z13 - z2;
766431 ····dataptr[1] = z11 + z4;
40c426 ····dataptr[7] = z11 - z4;
6aaf5a
5a9e99 ····dataptr += DCTSIZE;¤¤   /* advance pointer to next row */
87df1c ··}
c8af5a
170294 ··/* Pass 2: process columns. */
a0af5a
fd5af4 ··dataptr = data;
0cb327 ··for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
9a1132 ····tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
4b7c6e ····tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
783fc9 ····tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
8a5295 ····tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
714cc4 ····tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
df2198 ····tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
03623f ····tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
080f63 ····tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
2c869e ····
843f6a ····/* Even part */
0d869e ····
511653 ····tmp10 = tmp0 + tmp3;¤   /* phase 2 */
717bf4 ····tmp13 = tmp0 - tmp3;
d130a0 ····tmp11 = tmp1 + tmp2;
b31d00 ····tmp12 = tmp1 - tmp2;
e7869e ····
ec4ac7 ····dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
dd7149 ····dataptr[DCTSIZE*4] = tmp10 - tmp11;
a2869e ····
e089ce ····z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
af2518 ····dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
54ede2 ····dataptr[DCTSIZE*6] = tmp13 - z1;
43869e ····
74e722 ····/* Odd part */
--02fd 00106860b8f40100031 Page 3 of jfdctflt.c
e0af5a
fc84b4 ····tmp10 = tmp4 + tmp5;¤   /* phase 2 */
6de35d ····tmp11 = tmp5 + tmp6;
abfdf9 ····tmp12 = tmp6 + tmp7;
ccaf5a
e8e7d8 ····/* The rotator is modified from fig 4-8 to avoid extra negations. */
bdae0e ····z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
3a6715 ····z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
c4b6d1 ····z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
5b235a ····z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
ecaf5a
38d456 ····z11 = tmp7 + z3;¤   ¤   /* phase 5 */
c66eb6 ····z13 = tmp7 - z3;
2aaf5a
0528d5 ····dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
e6e779 ····dataptr[DCTSIZE*3] = z13 - z2;
84b261 ····dataptr[DCTSIZE*1] = z11 + z4;
d01276 ····dataptr[DCTSIZE*7] = z11 - z4;
2aaf5a
f3685b ····dataptr++;¤ ¤   ¤   /* advance pointer to next column */
2bdf1c ··}
29efe6 }
d3af5a
06e923 #endif /* DCT_FLOAT_SUPPORTED */
--93e5 0006951e1e740100032 Page 1 of jfdctfst.c
bc38e5 /*
8155c6 ·* jfdctfst.c
dc775e ·*
2d9e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
c3fb07 ·* This file is part of the Independent JPEG Group's software.
1ba0d6 ·* For conditions of distribution and use, see the accompanying README file.
d3775e ·*
aa1aef ·* This file contains a fast, not so accurate integer implementation of the
306eae ·* forward DCT (Discrete Cosine Transform).
53775e ·*
a477ab ·* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
15054f ·* on each column. ·Direct algorithms are also available, but they are
08dbb5 ·* much more complex and seem not to be any faster when reduced to code.
53775e ·*
b2e291 ·* This implementation is based on Arai, Agui, and Nakajima's algorithm for
1747b3 ·* scaled DCT. ·Their original paper (Trans. IEICE E-71(11):1095) is in
ec0273 ·* Japanese, but the algorithm is described in the Pennebaker & Mitchell
2d8fd4 ·* JPEG textbook (see REFERENCES section in file README). ·The following code
62edb5 ·* is based directly on figure 4-8 in P&M.
56f36a ·* While an 8-point DCT cannot be done in less than 11 multiplies, it is
af24d7 ·* possible to arrange the computation so that many of the multiplies are
5998d4 ·* simple scalings of the final outputs. ·These multiplies can then be
d7cd69 ·* folded into the multiplications or divisions by the JPEG quantization
f3a9c0 ·* table entries. ·The AA&N method leaves only 5 multiplies and 29 adds
b88471 ·* to be done in the DCT itself.
bd3bf5 ·* The primary disadvantage of this method is that with fixed-point math,
342042 ·* accuracy is lost due to imprecise representation of the scaled
93b88c ·* quantization values. ·The smaller the quantization table entry, the less
28df57 ·* precise the scaled value, so this implementation does worse with high-
9b239f ·* quality-setting files than with low-quality ones.
5c495d ·*/
5daf5a
1a2bb6 #define JPEG_INTERNALS
1c36a7 #include "jinclude.h"
466c8f #include "jpeglib.h"
36ef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
56af5a
06fcf3 #ifdef DCT_IFAST_SUPPORTED
a7af5a
84af5a
fb38e5 /*
9ff914 ·* This module is specialized to the case DCTSIZE = 8.
96495d ·*/
faaf5a
285f63 #if DCTSIZE != 8
ba5f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
837454 #endif
f1af5a
a2af5a
e332b2 /* Scaling decisions are generally the same as in the LL&M algorithm;
d87a00 ·* see jfdctint.c for more details. ·However, we choose to descale
a637c3 ·* (right shift) multiplication products as soon as they are formed,
ae6061 ·* rather than carrying additional fractional bits into subsequent additions.
bad3a2 ·* This compromises accuracy slightly, but it lets us save a few shifts.
95f0ad ·* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
dd5f63 ·* everywhere except in the multiplications proper; this saves a good deal
cee9d6 ·* of work on 16-bit-int machines.
af775e ·*
bc9a1f ·* Again to save a few shifts, the intermediate results between pass 1 and
00e8b0 ·* pass 2 are not upscaled, but are represented only to integral precision.
8d775e ·*
2b09c2 ·* A final compromise is to represent the multiplicative constants to only
a1afa0 ·* 8 fractional bits, rather than 13. ·This saves some shifting work on some
c08019 ·* machines, and may also reduce the cost of multiplication (since there
d8d63a ·* are fewer one-bits in the constants).
0e495d ·*/
ceaf5a
6626bb #define CONST_BITS ·8
00af5a
88af5a
4e23ff /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
69f4ab ·* causing a lot of useless floating-point operations at run time.
--abfe 000a5563d6640100032 Page 2 of jfdctfst.c
7ee9b9 ·* To get around this we use the following pre-calculated constants.
e6c135 ·* If you change CONST_BITS you may want to add appropriate values.
a5e109 ·* (With a reasonable C compiler, you can just rely on the FIX() macro...)
75495d ·*/
f9af5a
d8128d #if CONST_BITS == 8
ff9bc2 #define FIX_0_382683433 ·((INT32) ··98)¤¤   /* FIX(0.382683433) */
311795 #define FIX_0_541196100 ·((INT32) ·139)¤¤   /* FIX(0.541196100) */
10303f #define FIX_0_707106781 ·((INT32) ·181)¤¤   /* FIX(0.707106781) */
780a0f #define FIX_1_306562965 ·((INT32) ·334)¤¤   /* FIX(1.306562965) */
85db21 #else
7a5cd1 #define FIX_0_382683433 ·FIX(0.382683433)
78a1df #define FIX_0_541196100 ·FIX(0.541196100)
3fa399 #define FIX_0_707106781 ·FIX(0.707106781)
dc9701 #define FIX_1_306562965 ·FIX(1.306562965)
f47454 #endif
9caf5a
f5af5a
7e4ad2 /* We can gain a little more speed, with a further compromise in accuracy,
e7c333 ·* by omitting the addition in a descaling shift. ·This yields an incorrectly
e31e1e ·* rounded result half the time...
65495d ·*/
f2af5a
6c3f2c #ifndef USE_ACCURATE_ROUNDING
ec9b69 #undef DESCALE
09d4bd #define DESCALE(x,n) ·RIGHT_SHIFT(x, n)
777454 #endif
f9af5a
36af5a
ef1831 /* Multiply a DCTELEM variable by an INT32 constant, and immediately
110292 ·* descale to yield a DCTELEM result.
13495d ·*/
d6af5a
ce7685 #define MULTIPLY(var,const) ·((DCTELEM) DESCALE((var) * (const), CONST_BITS))
01af5a
3eaf5a
ba38e5 /*
4879d7 ·* Perform the forward DCT on one block of samples.
22495d ·*/
66af5a
53f898 GLOBAL(void)
3b4a01 jpeg_fdct_ifast (DCTELEM * data)
58bb36 {
701cd1 ··DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
bf51fa ··DCTELEM tmp10, tmp11, tmp12, tmp13;
cf80b0 ··DCTELEM z1, z2, z3, z4, z5, z11, z13;
8fc46b ··DCTELEM *dataptr;
1ade0b ··int ctr;
efea99 ··SHIFT_TEMPS
78af5a
82494e ··/* Pass 1: process rows. */
e4af5a
7a5af4 ··dataptr = data;
5bb327 ··for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
9b95ae ····tmp0 = dataptr[0] + dataptr[7];
ce6476 ····tmp7 = dataptr[0] - dataptr[7];
01602b ····tmp1 = dataptr[1] + dataptr[6];
7691f3 ····tmp6 = dataptr[1] - dataptr[6];
af76b5 ····tmp2 = dataptr[2] + dataptr[5];
6a876d ····tmp5 = dataptr[2] - dataptr[5];
7d8330 ····tmp3 = dataptr[3] + dataptr[4];
8f72e8 ····tmp4 = dataptr[3] - dataptr[4];
0b869e ····
983f6a ····/* Even part */
67869e ····
781653 ····tmp10 = tmp0 + tmp3;¤   /* phase 2 */
897bf4 ····tmp13 = tmp0 - tmp3;
cb30a0 ····tmp11 = tmp1 + tmp2;
d31d00 ····tmp12 = tmp1 - tmp2;
fe869e ····
427404 ····dataptr[0] = tmp10 + tmp11; /* phase 3 */
a5b7c9 ····dataptr[4] = tmp10 - tmp11;
--fe7b 0008932a8f540100032 Page 3 of jfdctfst.c
a9869e ····
af67f5 ····z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
7241dc ····dataptr[2] = tmp13 + z1;¤   /* phase 5 */
ce8dae ····dataptr[6] = tmp13 - z1;
e5869e ····
30e722 ····/* Odd part */
f7af5a
d984b4 ····tmp10 = tmp4 + tmp5;¤   /* phase 2 */
d2e35d ····tmp11 = tmp5 + tmp6;
d9fdf9 ····tmp12 = tmp6 + tmp7;
d7af5a
83e7d8 ····/* The rotator is modified from fig 4-8 to avoid extra negations. */
1a6334 ····z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
906359 ····z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
809dbd ····z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
18c742 ····z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
3daf5a
66d456 ····z11 = tmp7 + z3;¤   ¤   /* phase 5 */
ee6eb6 ····z13 = tmp7 - z3;
c4af5a
3bbefd ····dataptr[5] = z13 + z2;¤ /* phase 6 */
f93129 ····dataptr[3] = z13 - z2;
4d6431 ····dataptr[1] = z11 + z4;
d7c426 ····dataptr[7] = z11 - z4;
90af5a
fe9e99 ····dataptr += DCTSIZE;¤¤   /* advance pointer to next row */
0cdf1c ··}
4daf5a
950294 ··/* Pass 2: process columns. */
5caf5a
305af4 ··dataptr = data;
37b327 ··for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
f71132 ····tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
d47c6e ····tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
503fc9 ····tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
be5295 ····tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
754cc4 ····tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
812198 ····tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
7b623f ····tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
fa0f63 ····tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
90869e ····
0e3f6a ····/* Even part */
ed869e ····
431653 ····tmp10 = tmp0 + tmp3;¤   /* phase 2 */
b17bf4 ····tmp13 = tmp0 - tmp3;
5b30a0 ····tmp11 = tmp1 + tmp2;
521d00 ····tmp12 = tmp1 - tmp2;
bd869e ····
8e4ac7 ····dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
3c7149 ····dataptr[DCTSIZE*4] = tmp10 - tmp11;
18869e ····
a567f5 ····z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
fd2518 ····dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
13ede2 ····dataptr[DCTSIZE*6] = tmp13 - z1;
98869e ····
d0e722 ····/* Odd part */
1daf5a
0a84b4 ····tmp10 = tmp4 + tmp5;¤   /* phase 2 */
77e35d ····tmp11 = tmp5 + tmp6;
effdf9 ····tmp12 = tmp6 + tmp7;
ecaf5a
41e7d8 ····/* The rotator is modified from fig 4-8 to avoid extra negations. */
d66334 ····z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
626359 ····z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
bd9dbd ····z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
c2c742 ····z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
7eaf5a
a0d456 ····z11 = tmp7 + z3;¤   ¤   /* phase 5 */
be6eb6 ····z13 = tmp7 - z3;
8faf5a
9428d5 ····dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
89e779 ····dataptr[DCTSIZE*3] = z13 - z2;
--6d15 001f0d391f140100032 Page 4 of jfdctfst.c
f1b261 ····dataptr[DCTSIZE*1] = z11 + z4;
d01276 ····dataptr[DCTSIZE*7] = z11 - z4;
00af5a
b9685b ····dataptr++;¤ ¤   ¤   /* advance pointer to next column */
25df1c ··}
abefe6 }
d6af5a
f0e090 #endif /* DCT_IFAST_SUPPORTED */
--ef40 000d485ba3640100033 Page 1 of jfdctint.c
bc38e5 /*
e8a07b ·* jfdctint.c
e4775e ·*
e1a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
b7fb07 ·* This file is part of the Independent JPEG Group's software.
cda0d6 ·* For conditions of distribution and use, see the accompanying README file.
54775e ·*
8dbb73 ·* This file contains a slow-but-accurate integer implementation of the
886eae ·* forward DCT (Discrete Cosine Transform).
21775e ·*
e377ab ·* A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
ed054f ·* on each column. ·Direct algorithms are also available, but they are
34dbb5 ·* much more complex and seem not to be any faster when reduced to code.
1f775e ·*
fb7007 ·* This implementation is based on an algorithm described in
e6035c ·* ··C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
c3463e ·* ··Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
db29ff ·* ··Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
a069cf ·* The primary algorithm described there uses 11 multiplies and 29 adds.
f72c9a ·* We use their alternate method with 12 multiplies and 32 adds.
b9de71 ·* The advantage of this method is that no data path contains more than one
a20e3d ·* multiplication; this allows a very simple and accurate implementation in
0a144c ·* scaled fixed-point arithmetic, with a minimal number of shifts.
3f495d ·*/
5faf5a
762bb6 #define JPEG_INTERNALS
7c36a7 #include "jinclude.h"
5a6c8f #include "jpeglib.h"
59ef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
ceaf5a
c6ba56 #ifdef DCT_ISLOW_SUPPORTED
0faf5a
81af5a
7638e5 /*
62f914 ·* This module is specialized to the case DCTSIZE = 8.
89495d ·*/
ccaf5a
665f63 #if DCTSIZE != 8
1c5f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
557454 #endif
94af5a
8faf5a
5a38e5 /*
96a3dc ·* The poop on this scaling stuff is as follows:
2e775e ·*
472ab3 ·* Each 1-D DCT step produces outputs which are a factor of sqrt(N)
48f304 ·* larger than the true DCT outputs. ·The final outputs are therefore
261330 ·* a factor of N larger than desired; since N=8 this can be cured by
5be39d ·* a simple right shift at the end of the algorithm. ·The advantage of
0c7ca3 ·* this arrangement is that we save two multiplications per 1-D DCT,
3e2c58 ·* because the y0 and y4 outputs need not be divided by sqrt(N).
0e53bc ·* In the IJG code, this factor of 8 is removed by the quantization step
89f463 ·* (in jcdctmgr.c), NOT in this module.
45775e ·*
a39785 ·* We have to do addition and subtraction of the integer inputs, which
c94cde ·* is no problem, and multiplication by fractional constants, which is
ae110a ·* a problem to do in integer arithmetic. ·We multiply all the constants
62b6fb ·* by CONST_SCALE and convert them to integer constants (thus retaining
007ff0 ·* CONST_BITS bits of precision in the constants). ·After doing a
1113e4 ·* multiplication we have to divide the product by CONST_SCALE, with proper
fd278f ·* rounding, to produce the correct output. ·This division can be done
88a860 ·* cheaply as a right shift of CONST_BITS bits. ·We postpone shifting
23d3a1 ·* as long as possible so that partial sums can be added together with
8d3709 ·* full fractional precision.
d2775e ·*
ee069d ·* The outputs of the first pass are scaled up by PASS1_BITS bits so that
3e1f81 ·* they are represented to better-than-integral precision. ·These outputs
992695 ·* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
4748ab ·* with the recommended scaling. ·(For 12-bit sample data, the intermediate
6cacbb ·* array is INT32 anyway.)
8c775e ·*
d45e30 ·* To avoid overflow of the 32-bit intermediate results in pass 2, we must
--3e83 000bd01894f40100033 Page 2 of jfdctint.c
a5a859 ·* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. ·Error analysis
d46f5a ·* shows that the values given below are the most effective.
4b495d ·*/
8aaf5a
386f80 #if BITS_IN_JSAMPLE == 8
cf5980 #define CONST_BITS ·13
c940c6 #define PASS1_BITS ·2
9bdb21 #else
345980 #define CONST_BITS ·13
43aa57 #define PASS1_BITS ·1¤  ¤   /* lose a little precision to avoid overflow */
4f7454 #endif
40af5a
8423ff /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
acf4ab ·* causing a lot of useless floating-point operations at run time.
afe9b9 ·* To get around this we use the following pre-calculated constants.
1fc135 ·* If you change CONST_BITS you may want to add appropriate values.
27e109 ·* (With a reasonable C compiler, you can just rely on the FIX() macro...)
71495d ·*/
9faf5a
b10d01 #if CONST_BITS == 13
ce59d6 #define FIX_0_298631336 ·((INT32) ·2446)¤   /* FIX(0.298631336) */
48bbb5 #define FIX_0_390180644 ·((INT32) ·3196)¤   /* FIX(0.390180644) */
67d72b #define FIX_0_541196100 ·((INT32) ·4433)¤   /* FIX(0.541196100) */
b95e2f #define FIX_0_765366865 ·((INT32) ·6270)¤   /* FIX(0.765366865) */
7a0a06 #define FIX_0_899976223 ·((INT32) ·7373)¤   /* FIX(0.899976223) */
e0eb99 #define FIX_1_175875602 ·((INT32) ·9633)¤   /* FIX(1.175875602) */
02917c #define FIX_1_501321110 ·((INT32) ·12299)¤  /* FIX(1.501321110) */
a1d534 #define FIX_1_847759065 ·((INT32) ·15137)¤  /* FIX(1.847759065) */
bf00c5 #define FIX_1_961570560 ·((INT32) ·16069)¤  /* FIX(1.961570560) */
9be39b #define FIX_2_053119869 ·((INT32) ·16819)¤  /* FIX(2.053119869) */
f43252 #define FIX_2_562915447 ·((INT32) ·20995)¤  /* FIX(2.562915447) */
b5f7b2 #define FIX_3_072711026 ·((INT32) ·25172)¤  /* FIX(3.072711026) */
58db21 #else
2c2233 #define FIX_0_298631336 ·FIX(0.298631336)
6e2b2e #define FIX_0_390180644 ·FIX(0.390180644)
05a1df #define FIX_0_541196100 ·FIX(0.541196100)
25c9cc #define FIX_0_765366865 ·FIX(0.765366865)
a05702 #define FIX_0_899976223 ·FIX(0.899976223)
3e95fc #define FIX_1_175875602 ·FIX(1.175875602)
2ab5b3 #define FIX_1_501321110 ·FIX(1.501321110)
e4b361 #define FIX_1_847759065 ·FIX(1.847759065)
21362e #define FIX_1_961570560 ·FIX(1.961570560)
7d7019 #define FIX_2_053119869 ·FIX(2.053119869)
8c0f60 #define FIX_2_562915447 ·FIX(2.562915447)
fb799b #define FIX_3_072711026 ·FIX(3.072711026)
f77454 #endif
c8af5a
c9af5a
c70109 /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
f63435 ·* For 8-bit samples with the recommended scaling, all the variable
20d3ec ·* and constant values involved are no more than 16 bits wide, so a
a36108 ·* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
3b0f0c ·* For 12-bit samples, a full 32-bit multiplication will be needed.
3f495d ·*/
a3af5a
586f80 #if BITS_IN_JSAMPLE == 8
cfedd8 #define MULTIPLY(var,const) ·MULTIPLY16C16(var,const)
f8db21 #else
b39398 #define MULTIPLY(var,const) ·((var) * (const))
a67454 #endif
fbaf5a
a4af5a
ba38e5 /*
3279d7 ·* Perform the forward DCT on one block of samples.
fe495d ·*/
dcaf5a
c8f898 GLOBAL(void)
ed4517 jpeg_fdct_islow (DCTELEM * data)
9abb36 {
dbc95e ··INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
1d3c89 ··INT32 tmp10, tmp11, tmp12, tmp13;
bd5694 ··INT32 z1, z2, z3, z4, z5;
--c2ed 000f7be1c9c40100033 Page 3 of jfdctint.c
24c46b ··DCTELEM *dataptr;
cade0b ··int ctr;
03ea99 ··SHIFT_TEMPS
b0af5a
13494e ··/* Pass 1: process rows. */
32ed8b ··/* Note results are scaled up by sqrt(8) compared to a true DCT; */
5cd465 ··/* furthermore, we scale the results by 2**PASS1_BITS. */
43af5a
4b5af4 ··dataptr = data;
2ab327 ··for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
9c95ae ····tmp0 = dataptr[0] + dataptr[7];
d46476 ····tmp7 = dataptr[0] - dataptr[7];
66602b ····tmp1 = dataptr[1] + dataptr[6];
ab91f3 ····tmp6 = dataptr[1] - dataptr[6];
8e76b5 ····tmp2 = dataptr[2] + dataptr[5];
4f876d ····tmp5 = dataptr[2] - dataptr[5];
2a8330 ····tmp3 = dataptr[3] + dataptr[4];
1972e8 ····tmp4 = dataptr[3] - dataptr[4];
9b869e ····
86db98 ····/* Even part per LL&M figure 1 --- note that published figure is faulty;
b70c98 ·····* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
56d48d ·····*/
9f869e ····
7a5654 ····tmp10 = tmp0 + tmp3;
cd7bf4 ····tmp13 = tmp0 - tmp3;
4430a0 ····tmp11 = tmp1 + tmp2;
b41d00 ····tmp12 = tmp1 - tmp2;
9d869e ····
25b743 ····dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
6593a0 ····dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
8f869e ····
23f75f ····z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
c4915c ····dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
eb9bb0 ¤   ¤   ¤   ¤   ···CONST_BITS-PASS1_BITS);
563eb2 ····dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
809bb0 ¤   ¤   ¤   ¤   ···CONST_BITS-PASS1_BITS);
a7869e ····
6c23f9 ····/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
0535d1 ·····* cK represents cos(K*pi/16).
406679 ·····* i0..i3 in the paper are tmp4..tmp7 here.
bcd48d ·····*/
c1869e ····
af83fd ····z1 = tmp4 + tmp7;
0bc517 ····z2 = tmp5 + tmp6;
c9f93f ····z3 = tmp4 + tmp6;
a8ffe9 ····z4 = tmp5 + tmp7;
5fdccc ····z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
76869e ····
5c31d7 ····tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
379d6c ····tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
b91353 ····tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
0c44a4 ····tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
7f2ce9 ····z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
c9ca9a ····z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
0c3192 ····z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
48fe7b ····z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
de869e ····
263234 ····z3 += z5;
37dbd6 ····z4 += z5;
31869e ····
ebcaf2 ····dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
9c7f1f ····dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
a36c01 ····dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
85d9ec ····dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
1d869e ····
139e99 ····dataptr += DCTSIZE;¤¤   /* advance pointer to next row */
eadf1c ··}
47af5a
0a2b43 ··/* Pass 2: process columns.
5824bf ···* We remove the PASS1_BITS scaling, but leave the results scaled up
58cddd ···* by an overall factor of 8.
f7f9a6 ···*/
--ded3 001baad69e840100033 Page 4 of jfdctint.c
e0af5a
595af4 ··dataptr = data;
93b327 ··for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
e51132 ····tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
897c6e ····tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
b73fc9 ····tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
7d5295 ····tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
424cc4 ····tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
732198 ····tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
f7623f ····tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
1c0f63 ····tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
0b869e ····
87db98 ····/* Even part per LL&M figure 1 --- note that published figure is faulty;
4d0c98 ·····* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
c2d48d ·····*/
8b869e ····
105654 ····tmp10 = tmp0 + tmp3;
a57bf4 ····tmp13 = tmp0 - tmp3;
a230a0 ····tmp11 = tmp1 + tmp2;
811d00 ····tmp12 = tmp1 - tmp2;
0d869e ····
49b5a9 ····dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
014ca4 ····dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
97869e ····
24f75f ····z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
afb32b ····dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865¶
febaec ),
ae0445 ¤   ¤   ¤   ¤   ¤   ···CONST_BITS+PASS1_BITS);
08e399 ····dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_8477590¶
ba7700 65),
ba0445 ¤   ¤   ¤   ¤   ¤   ···CONST_BITS+PASS1_BITS);
95869e ····
2123f9 ····/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
cd35d1 ·····* cK represents cos(K*pi/16).
136679 ·····* i0..i3 in the paper are tmp4..tmp7 here.
38d48d ·····*/
49869e ····
b883fd ····z1 = tmp4 + tmp7;
edc517 ····z2 = tmp5 + tmp6;
e2f93f ····z3 = tmp4 + tmp6;
ebffe9 ····z4 = tmp5 + tmp7;
eadccc ····z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
11869e ····
7b31d7 ····tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
1c9d6c ····tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
281353 ····tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
6044a4 ····tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
3b2ce9 ····z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
dfca9a ····z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
fe3192 ····z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
94fe7b ····z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
cd869e ····
aa3234 ····z3 += z5;
97dbd6 ····z4 += z5;
6c869e ····
38fb27 ····dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
2f0445 ¤   ¤   ¤   ¤   ¤   ···CONST_BITS+PASS1_BITS);
1b6d83 ····dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
090445 ¤   ¤   ¤   ¤   ¤   ···CONST_BITS+PASS1_BITS);
185904 ····dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
160445 ¤   ¤   ¤   ¤   ¤   ···CONST_BITS+PASS1_BITS);
49cfa0 ····dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
e10445 ¤   ¤   ¤   ¤   ¤   ···CONST_BITS+PASS1_BITS);
ab869e ····
80685b ····dataptr++;¤ ¤   ¤   /* advance pointer to next column */
fddf1c ··}
d8efe6 }
b5af5a
bac44c #endif /* DCT_ISLOW_SUPPORTED */
--d6f6 000d9a8faf940100034 Page 1 of jidctflt.c
bc38e5 /*
9226a6 ·* jidctflt.c
5e775e ·*
b79e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
5cfb07 ·* This file is part of the Independent JPEG Group's software.
2fa0d6 ·* For conditions of distribution and use, see the accompanying README file.
c7775e ·*
0b6e71 ·* This file contains a floating-point implementation of the
9a1ae9 ·* inverse DCT (Discrete Cosine Transform). ·In the IJG code, this routine
307f06 ·* must also perform dequantization of the input coefficients.
01775e ·*
16239c ·* This implementation should be more accurate than either of the integer
87ad6b ·* IDCT implementations. ·However, it may not give the same results on all
9fdd80 ·* machines because of differences in roundoff behavior. ·Speed will depend
649742 ·* on the hardware's floating point capacity.
82775e ·*
d67b7a ·* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
600b22 ·* on each row (or vice versa, but it's more convenient to emit a row at
79897b ·* a time). ·Direct algorithms are also available, but they are much more
34af10 ·* complex and seem not to be any faster when reduced to code.
fd775e ·*
57e291 ·* This implementation is based on Arai, Agui, and Nakajima's algorithm for
4d47b3 ·* scaled DCT. ·Their original paper (Trans. IEICE E-71(11):1095) is in
5a0273 ·* Japanese, but the algorithm is described in the Pennebaker & Mitchell
9f8fd4 ·* JPEG textbook (see REFERENCES section in file README). ·The following code
16edb5 ·* is based directly on figure 4-8 in P&M.
00f36a ·* While an 8-point DCT cannot be done in less than 11 multiplies, it is
ad24d7 ·* possible to arrange the computation so that many of the multiplies are
9798d4 ·* simple scalings of the final outputs. ·These multiplies can then be
12cd69 ·* folded into the multiplications or divisions by the JPEG quantization
b1a9c0 ·* table entries. ·The AA&N method leaves only 5 multiplies and 29 adds
f78471 ·* to be done in the DCT itself.
d33c35 ·* The primary disadvantage of this method is that with a fixed-point
0f833c ·* implementation, accuracy is lost due to imprecise representation of the
b3826f ·* scaled quantization values. ·However, that problem does not arise if
2e3de0 ·* we use floating point arithmetic.
7d495d ·*/
85af5a
fb2bb6 #define JPEG_INTERNALS
a936a7 #include "jinclude.h"
a66c8f #include "jpeglib.h"
21ef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
d7af5a
6f6fd6 #ifdef DCT_FLOAT_SUPPORTED
fbaf5a
f7af5a
e938e5 /*
caf914 ·* This module is specialized to the case DCTSIZE = 8.
1c495d ·*/
e2af5a
1c5f63 #if DCTSIZE != 8
9b5f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
867454 #endif
0eaf5a
67af5a
2111ef /* Dequantize a coefficient by multiplying it by the multiplier-table
1f2ffe ·* entry; produce a float result.
0e495d ·*/
f5af5a
4fca0e #define DEQUANTIZE(coef,quantval) ·(((FAST_FLOAT) (coef)) * (quantval))
13af5a
93af5a
7438e5 /*
086575 ·* Perform dequantization and inverse DCT on one block of coefficients.
50495d ·*/
afaf5a
aff898 GLOBAL(void)
e80ea9 jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
1d2655 ¤   ¤   ·JCOEFPTR coef_block,
341e8c ¤   ¤   ·JSAMPARRAY output_buf, JDIMENSION output_col)
cbbb36 {
d99b6d ··FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
--9156 000eac2a73e40100034 Page 2 of jidctflt.c
e85a28 ··FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
6bb4d3 ··FAST_FLOAT z5, z10, z11, z12, z13;
033386 ··JCOEFPTR inptr;
9a7735 ··FLOAT_MULT_TYPE * quantptr;
91ee1d ··FAST_FLOAT * wsptr;
099e8f ··JSAMPROW outptr;
8e0b97 ··JSAMPLE *range_limit = IDCT_range_limit(cinfo);
e2de0b ··int ctr;
8b724b ··FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
a1ea99 ··SHIFT_TEMPS
21af5a
679a02 ··/* Pass 1: process columns from input, store into work array. */
c3af5a
6ff17f ··inptr = coef_block;
abf281 ··quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
c7aab4 ··wsptr = workspace;
456d3c ··for (ctr = DCTSIZE; ctr > 0; ctr--) {
1854fa ····/* Due to quantization, we will usually find that many of the input
1c7d9b ·····* coefficients are zero, especially the AC terms. ·We can exploit this
6c078d ·····* by short-circuiting the IDCT calculation for any column in which all
d63dd5 ·····* the AC terms are zero. ·In that case each output is equal to the
a49749 ·····* DC coefficient (with scale factor as needed).
3734d3 ·····* With typical images and quantization tables, half or more of the
3d1e42 ·····* column DCT calculations can be simplified this way.
8dd48d ·····*/
2a869e ····
df1d3f ····if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
3a258f ¤   ·inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
327ee9 ¤   ·inptr[DCTSIZE*7]) == 0) {
ac3d5e ······/* AC terms all zero */
11a0ca ······FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
d4cf72 ······
f27654 ······wsptr[DCTSIZE*0] = dcval;
25f301 ······wsptr[DCTSIZE*1] = dcval;
6674ef ······wsptr[DCTSIZE*2] = dcval;
99f1ba ······wsptr[DCTSIZE*3] = dcval;
db7322 ······wsptr[DCTSIZE*4] = dcval;
a4f677 ······wsptr[DCTSIZE*5] = dcval;
287199 ······wsptr[DCTSIZE*6] = dcval;
0df4cc ······wsptr[DCTSIZE*7] = dcval;
dacf72 ······
d08132 ······inptr++;¤ ¤   ¤   /* advance pointers to next column */
6cc06d ······quantptr++;
a4655d ······wsptr++;
085f6a ······continue;
0d6fe7 ····}
6a869e ····
5a3f6a ····/* Even part */
93af5a
1a3c47 ····tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
a5776b ····tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
36aa1f ····tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
01e133 ····tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
b2af5a
d6c241 ····tmp10 = tmp0 + tmp2;¤   /* phase 3 */
a00136 ····tmp11 = tmp0 - tmp2;
38af5a
3862f4 ····tmp13 = tmp1 + tmp3;¤   /* phases 5-3 */
02342f ····tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
ddaf5a
446d60 ····tmp0 = tmp10 + tmp13;¤  /* phase 2 */
40f8c1 ····tmp3 = tmp10 - tmp13;
d27d10 ····tmp1 = tmp11 + tmp12;
ad64c5 ····tmp2 = tmp11 - tmp12;
d1869e ····
04e722 ····/* Odd part */
d5af5a
22de34 ····tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
b49518 ····tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
41486c ····tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
170340 ····tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
eaaf5a
--253c 000af7ad25040100034 Page 3 of jidctflt.c
c1707b ····z13 = tmp6 + tmp5;¤ ¤   /* phase 6 */
0e3213 ····z10 = tmp6 - tmp5;
fed25b ····z11 = tmp4 + tmp7;
96fffb ····z12 = tmp4 - tmp7;
faaf5a
9793ca ····tmp7 = z11 + z13;¤  ¤   /* phase 5 */
63ea33 ····tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
18af5a
265e79 ····z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
a3330b ····tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
349903 ····tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
12af5a
faefca ····tmp6 = tmp12 - tmp7;¤   /* phase 2 */
447a9d ····tmp5 = tmp11 - tmp6;
b55c88 ····tmp4 = tmp10 + tmp5;
05af5a
9eda54 ····wsptr[DCTSIZE*0] = tmp0 + tmp7;
a53d72 ····wsptr[DCTSIZE*7] = tmp0 - tmp7;
bc5448 ····wsptr[DCTSIZE*1] = tmp1 + tmp6;
b9b36e ····wsptr[DCTSIZE*6] = tmp1 - tmp6;
e8ce7d ····wsptr[DCTSIZE*2] = tmp2 + tmp5;
d7295b ····wsptr[DCTSIZE*5] = tmp2 - tmp5;
aabaf6 ····wsptr[DCTSIZE*4] = tmp3 + tmp4;
a85dd0 ····wsptr[DCTSIZE*3] = tmp3 - tmp4;
ffaf5a
d742ab ····inptr++;¤   ¤   ¤   /* advance pointers to next column */
c28b73 ····quantptr++;
acc0e3 ····wsptr++;
3bdf1c ··}
35de7b ··
b9bf3b ··/* Pass 2: process rows from work array, store into output array. */
56519a ··/* Note that we must descale the results by a factor of 8 == 2**3. */
99af5a
6eaab4 ··wsptr = workspace;
877b7e ··for (ctr = 0; ctr < DCTSIZE; ctr++) {
2131c4 ····outptr = output_buf[ctr] + output_col;
d0b392 ····/* Rows of zeroes can be exploited in the same way as we did with columns.
0b0e3c ·····* However, the column calculation has created many nonzero AC terms, so
e25b5b ·····* the simplification applies less often (typically 5% to 10% of the time).
f6e065 ·····* And testing floats for zero is relatively expensive, so we don't bother.
a8d48d ·····*/
3f869e ····
e53f6a ····/* Even part */
71af5a
9cf8cd ····tmp10 = wsptr[0] + wsptr[4];
4bfb7b ····tmp11 = wsptr[0] - wsptr[4];
75af5a
7d5d62 ····tmp13 = wsptr[2] + wsptr[6];
182ae5 ····tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
5daf5a
ace114 ····tmp0 = tmp10 + tmp13;
73f8c1 ····tmp3 = tmp10 - tmp13;
8f7d10 ····tmp1 = tmp11 + tmp12;
df64c5 ····tmp2 = tmp11 - tmp12;
72af5a
c3e722 ····/* Odd part */
20af5a
413aaa ····z13 = wsptr[5] + wsptr[3];
0831ea ····z10 = wsptr[5] - wsptr[3];
1d6809 ····z11 = wsptr[1] + wsptr[7];
8d6349 ····z12 = wsptr[1] - wsptr[7];
b5af5a
e7a0fc ····tmp7 = z11 + z13;
a095ec ····tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
adaf5a
875e79 ····z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
1a330b ····tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
7c9903 ····tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
f1af5a
1a5510 ····tmp6 = tmp12 - tmp7;
097a9d ····tmp5 = tmp11 - tmp6;
af5c88 ····tmp4 = tmp10 + tmp5;
--8d90 0016dac6e3340100034 Page 4 of jidctflt.c
e0af5a
cd2aec ····/* Final output stage: scale down by a factor of 8 and range-limit */
83af5a
8404db ····outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
4e0c4d ¤   ¤   ¤   ····& RANGE_MASK];
013a0a ····outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
090c4d ¤   ¤   ¤   ····& RANGE_MASK];
363036 ····outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
1f0c4d ¤   ¤   ¤   ····& RANGE_MASK];
280ee7 ····outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
130c4d ¤   ¤   ¤   ····& RANGE_MASK];
a26d01 ····outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
ec0c4d ¤   ¤   ¤   ····& RANGE_MASK];
5a53d0 ····outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
e20c4d ¤   ¤   ¤   ····& RANGE_MASK];
6760f0 ····outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
a00c4d ¤   ¤   ¤   ····& RANGE_MASK];
5e5e21 ····outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
f80c4d ¤   ¤   ¤   ····& RANGE_MASK];
4b869e ····
305817 ····wsptr += DCTSIZE;¤  ¤   /* advance pointer to next row */
eadf1c ··}
ddefe6 }
65af5a
6de923 #endif /* DCT_FLOAT_SUPPORTED */
--0521 0005d2b063e40100035 Page 1 of jidctfst.c
bc38e5 /*
70f81a ·* jidctfst.c
fb775e ·*
a39e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
d1fb07 ·* This file is part of the Independent JPEG Group's software.
4aa0d6 ·* For conditions of distribution and use, see the accompanying README file.
5e775e ·*
ba1aef ·* This file contains a fast, not so accurate integer implementation of the
7b1ae9 ·* inverse DCT (Discrete Cosine Transform). ·In the IJG code, this routine
917f06 ·* must also perform dequantization of the input coefficients.
b6775e ·*
5b7b7a ·* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
920b22 ·* on each row (or vice versa, but it's more convenient to emit a row at
bd897b ·* a time). ·Direct algorithms are also available, but they are much more
79af10 ·* complex and seem not to be any faster when reduced to code.
20775e ·*
8ce291 ·* This implementation is based on Arai, Agui, and Nakajima's algorithm for
6e47b3 ·* scaled DCT. ·Their original paper (Trans. IEICE E-71(11):1095) is in
090273 ·* Japanese, but the algorithm is described in the Pennebaker & Mitchell
d38fd4 ·* JPEG textbook (see REFERENCES section in file README). ·The following code
62edb5 ·* is based directly on figure 4-8 in P&M.
7cf36a ·* While an 8-point DCT cannot be done in less than 11 multiplies, it is
b124d7 ·* possible to arrange the computation so that many of the multiplies are
5398d4 ·* simple scalings of the final outputs. ·These multiplies can then be
81cd69 ·* folded into the multiplications or divisions by the JPEG quantization
78a9c0 ·* table entries. ·The AA&N method leaves only 5 multiplies and 29 adds
e88471 ·* to be done in the DCT itself.
a43bf5 ·* The primary disadvantage of this method is that with fixed-point math,
132042 ·* accuracy is lost due to imprecise representation of the scaled
64b88c ·* quantization values. ·The smaller the quantization table entry, the less
d1df57 ·* precise the scaled value, so this implementation does worse with high-
98239f ·* quality-setting files than with low-quality ones.
08495d ·*/
52af5a
482bb6 #define JPEG_INTERNALS
2236a7 #include "jinclude.h"
eb6c8f #include "jpeglib.h"
89ef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
b7af5a
90fcf3 #ifdef DCT_IFAST_SUPPORTED
bbaf5a
caaf5a
e738e5 /*
b7f914 ·* This module is specialized to the case DCTSIZE = 8.
e8495d ·*/
92af5a
655f63 #if DCTSIZE != 8
035f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
207454 #endif
d6af5a
aaaf5a
e132b2 /* Scaling decisions are generally the same as in the LL&M algorithm;
8bbf5c ·* see jidctint.c for more details. ·However, we choose to descale
2b37c3 ·* (right shift) multiplication products as soon as they are formed,
f26061 ·* rather than carrying additional fractional bits into subsequent additions.
c7d3a2 ·* This compromises accuracy slightly, but it lets us save a few shifts.
59f0ad ·* More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
fc5f63 ·* everywhere except in the multiplications proper; this saves a good deal
41e9d6 ·* of work on 16-bit-int machines.
57775e ·*
8af815 ·* The dequantized coefficients are not integers because the AA&N scaling
c93a3f ·* factors have been incorporated. ·We represent them scaled up by PASS1_BITS,
697411 ·* so that the first and second IDCT rounds have the same input scaling.
ab2d51 ·* For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
0d3701 ·* avoid a descaling shift; this compromises accuracy rather drastically
53aa8c ·* for small quantization table entries, but it saves a lot of shifts.
b467c4 ·* For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
8d855c ·* so we use a much larger scaling factor to preserve accuracy.
c4775e ·*
2609c2 ·* A final compromise is to represent the multiplicative constants to only
a8afa0 ·* 8 fractional bits, rather than 13. ·This saves some shifting work on some
5d8019 ·* machines, and may also reduce the cost of multiplication (since there
--195f 0003bcfaf9940100035 Page 2 of jidctfst.c
50d63a ·* are fewer one-bits in the constants).
c6495d ·*/
f6af5a
086f80 #if BITS_IN_JSAMPLE == 8
d726bb #define CONST_BITS ·8
d040c6 #define PASS1_BITS ·2
b1db21 #else
dc26bb #define CONST_BITS ·8
d7aa57 #define PASS1_BITS ·1¤  ¤   /* lose a little precision to avoid overflow */
787454 #endif
94af5a
4523ff /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
69f4ab ·* causing a lot of useless floating-point operations at run time.
8be9b9 ·* To get around this we use the following pre-calculated constants.
e5c135 ·* If you change CONST_BITS you may want to add appropriate values.
72e109 ·* (With a reasonable C compiler, you can just rely on the FIX() macro...)
ac495d ·*/
49af5a
39128d #if CONST_BITS == 8
07e421 #define FIX_1_082392200 ·((INT32) ·277)¤¤   /* FIX(1.082392200) */
a1533a #define FIX_1_414213562 ·((INT32) ·362)¤¤   /* FIX(1.414213562) */
4efafd #define FIX_1_847759065 ·((INT32) ·473)¤¤   /* FIX(1.847759065) */
1bc943 #define FIX_2_613125930 ·((INT32) ·669)¤¤   /* FIX(2.613125930) */
d3db21 #else
2a3819 #define FIX_1_082392200 ·FIX(1.082392200)
7359bd #define FIX_1_414213562 ·FIX(1.414213562)
7ab361 #define FIX_1_847759065 ·FIX(1.847759065)
1442f5 #define FIX_2_613125930 ·FIX(2.613125930)
be7454 #endif
caaf5a
f2af5a
244ad2 /* We can gain a little more speed, with a further compromise in accuracy,
6dc333 ·* by omitting the addition in a descaling shift. ·This yields an incorrectly
801e1e ·* rounded result half the time...
a6495d ·*/
48af5a
c33f2c #ifndef USE_ACCURATE_ROUNDING
dd9b69 #undef DESCALE
4dd4bd #define DESCALE(x,n) ·RIGHT_SHIFT(x, n)
d97454 #endif
46af5a
b4af5a
2e1831 /* Multiply a DCTELEM variable by an INT32 constant, and immediately
120292 ·* descale to yield a DCTELEM result.
41495d ·*/
04af5a
e07685 #define MULTIPLY(var,const) ·((DCTELEM) DESCALE((var) * (const), CONST_BITS))
a5af5a
03af5a
9f11ef /* Dequantize a coefficient by multiplying it by the multiplier-table
e206aa ·* entry; produce a DCTELEM result. ·For 8-bit data a 16x16->16
fd18c0 ·* multiplication will do. ·For 12-bit data, the multiplier table is
5cb369 ·* declared INT32, so a 32-bit multiply will be used.
a4495d ·*/
dcaf5a
646f80 #if BITS_IN_JSAMPLE == 8
50b67a #define DEQUANTIZE(coef,quantval) ·(((IFAST_MULT_TYPE) (coef)) * (quantval))
27db21 #else
37fc08 #define DEQUANTIZE(coef,quantval) ·\
336922 ¤   DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
d77454 #endif
92af5a
95af5a
f16dba /* Like DESCALE, but applies to a DCTELEM and produces an int.
698727 ·* We assume that int right shift is unsigned if INT32 right shift is.
41495d ·*/
46af5a
2966ca #ifdef RIGHT_SHIFT_IS_UNSIGNED
a2b556 #define ISHIFT_TEMPS¤   DCTELEM ishift_temp;
786f80 #if BITS_IN_JSAMPLE == 8
ce87fe #define DCTELEMBITS ·16¤¤   /* DCTELEM may be 16 or 32 bits */
3bdb21 #else
--1e78 00014e15fac40100035 Page 3 of jidctfst.c
0b9257 #define DCTELEMBITS ·32¤¤   /* DCTELEM must be 32 bits */
967454 #endif
f3dbb4 #define IRIGHT_SHIFT(x,shft) ·\
e2f8e7 ····((ishift_temp = (x)) < 0 ? \
dadf34 ·····(ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
1b00fb ·····(ishift_temp >> (shft)))
7bdb21 #else
c64ad3 #define ISHIFT_TEMPS
8e8fda #define IRIGHT_SHIFT(x,shft)¤   ((x) >> (shft))
c47454 #endif
6eaf5a
d66492 #ifdef USE_ACCURATE_ROUNDING
9dc970 #define IDESCALE(x,n) ·((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
bbdb21 #else
5c0a28 #define IDESCALE(x,n) ·((int) IRIGHT_SHIFT(x, n))
a17454 #endif
96af5a
16af5a
a338e5 /*
cc6575 ·* Perform dequantization and inverse DCT on one block of coefficients.
da495d ·*/
ffaf5a
d1f898 GLOBAL(void)
a82c51 jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
7a2655 ¤   ¤   ·JCOEFPTR coef_block,
601e8c ¤   ¤   ·JSAMPARRAY output_buf, JDIMENSION output_col)
c5bb36 {
521cd1 ··DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
5451fa ··DCTELEM tmp10, tmp11, tmp12, tmp13;
ee651b ··DCTELEM z5, z10, z11, z12, z13;
3e3386 ··JCOEFPTR inptr;
dbc14b ··IFAST_MULT_TYPE * quantptr;
67c9ea ··int * wsptr;
119e8f ··JSAMPROW outptr;
5f0b97 ··JSAMPLE *range_limit = IDCT_range_limit(cinfo);
90de0b ··int ctr;
d87803 ··int workspace[DCTSIZE2];¤ /* buffers data between passes */
634e2a ··SHIFT_TEMPS¤  ¤   ¤   /* for DESCALE */
5f50eb ··ISHIFT_TEMPS¤ ¤   ¤   /* for IDESCALE */
0caf5a
589a02 ··/* Pass 1: process columns from input, store into work array. */
a2af5a
cbf17f ··inptr = coef_block;
7ad155 ··quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
60aab4 ··wsptr = workspace;
446d3c ··for (ctr = DCTSIZE; ctr > 0; ctr--) {
f454fa ····/* Due to quantization, we will usually find that many of the input
7b7d9b ·····* coefficients are zero, especially the AC terms. ·We can exploit this
36078d ·····* by short-circuiting the IDCT calculation for any column in which all
e63dd5 ·····* the AC terms are zero. ·In that case each output is equal to the
a69749 ·····* DC coefficient (with scale factor as needed).
d434d3 ·····* With typical images and quantization tables, half or more of the
6a1e42 ·····* column DCT calculations can be simplified this way.
06d48d ·····*/
ce869e ····
eb1d3f ····if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
a8258f ¤   ·inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
5b7ee9 ¤   ·inptr[DCTSIZE*7]) == 0) {
223d5e ······/* AC terms all zero */
e12199 ······int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
8caf5a
047654 ······wsptr[DCTSIZE*0] = dcval;
2cf301 ······wsptr[DCTSIZE*1] = dcval;
1674ef ······wsptr[DCTSIZE*2] = dcval;
52f1ba ······wsptr[DCTSIZE*3] = dcval;
117322 ······wsptr[DCTSIZE*4] = dcval;
ebf677 ······wsptr[DCTSIZE*5] = dcval;
e47199 ······wsptr[DCTSIZE*6] = dcval;
e7f4cc ······wsptr[DCTSIZE*7] = dcval;
7acf72 ······
288132 ······inptr++;¤ ¤   ¤   /* advance pointers to next column */
14c06d ······quantptr++;
--879b 0005695579b40100035 Page 4 of jidctfst.c
42655d ······wsptr++;
7b5f6a ······continue;
1a6fe7 ····}
0d869e ····
9d3f6a ····/* Even part */
90af5a
543c47 ····tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
ed776b ····tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
0eaa1f ····tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
b2e133 ····tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
2aaf5a
abc241 ····tmp10 = tmp0 + tmp2;¤   /* phase 3 */
980136 ····tmp11 = tmp0 - tmp2;
29af5a
bd62f4 ····tmp13 = tmp1 + tmp3;¤   /* phases 5-3 */
87992a ····tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
81af5a
9f6d60 ····tmp0 = tmp10 + tmp13;¤  /* phase 2 */
09f8c1 ····tmp3 = tmp10 - tmp13;
477d10 ····tmp1 = tmp11 + tmp12;
6564c5 ····tmp2 = tmp11 - tmp12;
13869e ····
99e722 ····/* Odd part */
a3af5a
2ade34 ····tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
aa9518 ····tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
b7486c ····tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
280340 ····tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
daaf5a
1b707b ····z13 = tmp6 + tmp5;¤ ¤   /* phase 6 */
cc3213 ····z10 = tmp6 - tmp5;
a5d25b ····z11 = tmp4 + tmp7;
0bfffb ····z12 = tmp4 - tmp7;
87af5a
aa93ca ····tmp7 = z11 + z13;¤  ¤   /* phase 5 */
2e44a5 ····tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
b8af5a
f299a8 ····z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
a13718 ····tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
319be2 ····tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
d3af5a
1defca ····tmp6 = tmp12 - tmp7;¤   /* phase 2 */
877a9d ····tmp5 = tmp11 - tmp6;
505c88 ····tmp4 = tmp10 + tmp5;
8daf5a
a8a757 ····wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
6971da ····wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
b4232d ····wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
4ff5a0 ····wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
15a7b2 ····wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
cd713f ····wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
6d515a ····wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
d587d7 ····wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
64af5a
3442ab ····inptr++;¤   ¤   ¤   /* advance pointers to next column */
098b73 ····quantptr++;
14c0e3 ····wsptr++;
8edf1c ··}
96de7b ··
bbbf3b ··/* Pass 2: process rows from work array, store into output array. */
024712 ··/* Note that we must descale the results by a factor of 8 == 2**3, */
d6012d ··/* and also undo the PASS1_BITS scaling. */
02af5a
eeaab4 ··wsptr = workspace;
b57b7e ··for (ctr = 0; ctr < DCTSIZE; ctr++) {
7731c4 ····outptr = output_buf[ctr] + output_col;
e8b392 ····/* Rows of zeroes can be exploited in the same way as we did with columns.
c60e3c ·····* However, the column calculation has created many nonzero AC terms, so
d05b5b ·····* the simplification applies less often (typically 5% to 10% of the time).
22cbdb ·····* On machines with very fast multiplication, it's possible that the
8aa947 ·····* test takes more time than it's worth. ·In that case this section
560c9f ·····* may be commented out.
--f712 000ad8ff6ad40100035 Page 5 of jidctfst.c
dbd48d ·····*/
b5869e ····
10d020 #ifndef NO_ZERO_ROW_TEST
1dd32b ····if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[4] | wsptr[5] | wsptr[6] |
40e81b ¤   ·wsptr[7]) == 0) {
403d5e ······/* AC terms all zero */
c82865 ······JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
824788 ¤   ¤   ¤   ¤   ··& RANGE_MASK];
c0cf72 ······
3fb104 ······outptr[0] = dcval;
3d3451 ······outptr[1] = dcval;
08b3bf ······outptr[2] = dcval;
7036ea ······outptr[3] = dcval;
28b472 ······outptr[4] = dcval;
0b3127 ······outptr[5] = dcval;
30b6c9 ······outptr[6] = dcval;
c0339c ······outptr[7] = dcval;
c0af5a
411820 ······wsptr += DCTSIZE;¤¤   /* advance pointer to next row */
385f6a ······continue;
bc6fe7 ····}
327454 #endif
b9869e ····
ea3f6a ····/* Even part */
3aaf5a
3961f9 ····tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
5d4bc3 ····tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
9daf5a
a0ee01 ····tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
40ecaa ····tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
cd7e89 ¤   ····- tmp13;
c9af5a
46e114 ····tmp0 = tmp10 + tmp13;
c4f8c1 ····tmp3 = tmp10 - tmp13;
207d10 ····tmp1 = tmp11 + tmp12;
9564c5 ····tmp2 = tmp11 - tmp12;
41af5a
e8e722 ····/* Odd part */
2caf5a
35a6d2 ····z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
3e1362 ····z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
cba9a4 ····z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
5d1c14 ····z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
a3af5a
8f93ca ····tmp7 = z11 + z13;¤  ¤   /* phase 5 */
4444a5 ····tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
22af5a
cb99a8 ····z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
3d3718 ····tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
b39be2 ····tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
55af5a
58efca ····tmp6 = tmp12 - tmp7;¤   /* phase 2 */
0e7a9d ····tmp5 = tmp11 - tmp6;
095c88 ····tmp4 = tmp10 + tmp5;
0aaf5a
7f2aec ····/* Final output stage: scale down by a factor of 8 and range-limit */
efaf5a
c7d1a9 ····outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
9a0c4d ¤   ¤   ¤   ····& RANGE_MASK];
d5735f ····outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
870c4d ¤   ¤   ¤   ····& RANGE_MASK];
255e81 ····outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
310c4d ¤   ¤   ¤   ····& RANGE_MASK];
67fc77 ····outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
860c4d ¤   ¤   ¤   ····& RANGE_MASK];
65c7e8 ····outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
e20c4d ¤   ¤   ¤   ····& RANGE_MASK];
92651e ····outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
c60c4d ¤   ¤   ¤   ····& RANGE_MASK];
6205cb ····outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
e10c4d ¤   ¤   ¤   ····& RANGE_MASK];
ada73d ····outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
--2fa0 0011fdff69f40100035 Page 6 of jidctfst.c
a80c4d ¤   ¤   ¤   ····& RANGE_MASK];
52af5a
a55817 ····wsptr += DCTSIZE;¤  ¤   /* advance pointer to next row */
89df1c ··}
09efe6 }
2caf5a
1fe090 #endif /* DCT_IFAST_SUPPORTED */
--b837 00017935c4840100036 Page 1 of jidctint.c
bc38e5 /*
190da7 ·* jidctint.c
c3775e ·*
6fa060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
a5fb07 ·* This file is part of the Independent JPEG Group's software.
9ca0d6 ·* For conditions of distribution and use, see the accompanying README file.
d9775e ·*
75bb73 ·* This file contains a slow-but-accurate integer implementation of the
881ae9 ·* inverse DCT (Discrete Cosine Transform). ·In the IJG code, this routine
267f06 ·* must also perform dequantization of the input coefficients.
fd775e ·*
e27b7a ·* A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
970b22 ·* on each row (or vice versa, but it's more convenient to emit a row at
5f897b ·* a time). ·Direct algorithms are also available, but they are much more
8baf10 ·* complex and seem not to be any faster when reduced to code.
5e775e ·*
e77007 ·* This implementation is based on an algorithm described in
a8035c ·* ··C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
34463e ·* ··Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
1b29ff ·* ··Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
1f69cf ·* The primary algorithm described there uses 11 multiplies and 29 adds.
9a2c9a ·* We use their alternate method with 12 multiplies and 32 adds.
5ede71 ·* The advantage of this method is that no data path contains more than one
510e3d ·* multiplication; this allows a very simple and accurate implementation in
90144c ·* scaled fixed-point arithmetic, with a minimal number of shifts.
51495d ·*/
2baf5a
542bb6 #define JPEG_INTERNALS
b436a7 #include "jinclude.h"
ca6c8f #include "jpeglib.h"
dbef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
f2af5a
93ba56 #ifdef DCT_ISLOW_SUPPORTED
a0af5a
d4af5a
2338e5 /*
f7f914 ·* This module is specialized to the case DCTSIZE = 8.
16495d ·*/
86af5a
2a5f63 #if DCTSIZE != 8
7d5f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
ed7454 #endif
79af5a
08af5a
2f38e5 /*
f5a3dc ·* The poop on this scaling stuff is as follows:
ae775e ·*
5587e3 ·* Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
ff9da2 ·* larger than the true IDCT outputs. ·The final outputs are therefore
991330 ·* a factor of N larger than desired; since N=8 this can be cured by
97e39d ·* a simple right shift at the end of the algorithm. ·The advantage of
3d98cd ·* this arrangement is that we save two multiplications per 1-D IDCT,
129acf ·* because the y0 and y4 inputs need not be divided by sqrt(N).
bb775e ·*
429785 ·* We have to do addition and subtraction of the integer inputs, which
0c4cde ·* is no problem, and multiplication by fractional constants, which is
1f110a ·* a problem to do in integer arithmetic. ·We multiply all the constants
d8b6fb ·* by CONST_SCALE and convert them to integer constants (thus retaining
987ff0 ·* CONST_BITS bits of precision in the constants). ·After doing a
b413e4 ·* multiplication we have to divide the product by CONST_SCALE, with proper
fd278f ·* rounding, to produce the correct output. ·This division can be done
24a860 ·* cheaply as a right shift of CONST_BITS bits. ·We postpone shifting
94d3a1 ·* as long as possible so that partial sums can be added together with
1b3709 ·* full fractional precision.
31775e ·*
ed069d ·* The outputs of the first pass are scaled up by PASS1_BITS bits so that
c21f81 ·* they are represented to better-than-integral precision. ·These outputs
0c2695 ·* require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
1ba96f ·* with the recommended scaling. ·(To scale up 12-bit sample data further, an
b801c1 ·* intermediate INT32 array would be needed.)
fa775e ·*
175e30 ·* To avoid overflow of the 32-bit intermediate results in pass 2, we must
--fede 0005d5dbabb40100036 Page 2 of jidctint.c
a5a859 ·* have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. ·Error analysis
d46f5a ·* shows that the values given below are the most effective.
4b495d ·*/
8aaf5a
386f80 #if BITS_IN_JSAMPLE == 8
cf5980 #define CONST_BITS ·13
c940c6 #define PASS1_BITS ·2
9bdb21 #else
345980 #define CONST_BITS ·13
43aa57 #define PASS1_BITS ·1¤  ¤   /* lose a little precision to avoid overflow */
4f7454 #endif
40af5a
8423ff /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
acf4ab ·* causing a lot of useless floating-point operations at run time.
afe9b9 ·* To get around this we use the following pre-calculated constants.
1fc135 ·* If you change CONST_BITS you may want to add appropriate values.
27e109 ·* (With a reasonable C compiler, you can just rely on the FIX() macro...)
71495d ·*/
9faf5a
b10d01 #if CONST_BITS == 13
ce59d6 #define FIX_0_298631336 ·((INT32) ·2446)¤   /* FIX(0.298631336) */
48bbb5 #define FIX_0_390180644 ·((INT32) ·3196)¤   /* FIX(0.390180644) */
67d72b #define FIX_0_541196100 ·((INT32) ·4433)¤   /* FIX(0.541196100) */
b95e2f #define FIX_0_765366865 ·((INT32) ·6270)¤   /* FIX(0.765366865) */
7a0a06 #define FIX_0_899976223 ·((INT32) ·7373)¤   /* FIX(0.899976223) */
e0eb99 #define FIX_1_175875602 ·((INT32) ·9633)¤   /* FIX(1.175875602) */
02917c #define FIX_1_501321110 ·((INT32) ·12299)¤  /* FIX(1.501321110) */
a1d534 #define FIX_1_847759065 ·((INT32) ·15137)¤  /* FIX(1.847759065) */
bf00c5 #define FIX_1_961570560 ·((INT32) ·16069)¤  /* FIX(1.961570560) */
9be39b #define FIX_2_053119869 ·((INT32) ·16819)¤  /* FIX(2.053119869) */
f43252 #define FIX_2_562915447 ·((INT32) ·20995)¤  /* FIX(2.562915447) */
b5f7b2 #define FIX_3_072711026 ·((INT32) ·25172)¤  /* FIX(3.072711026) */
58db21 #else
2c2233 #define FIX_0_298631336 ·FIX(0.298631336)
6e2b2e #define FIX_0_390180644 ·FIX(0.390180644)
05a1df #define FIX_0_541196100 ·FIX(0.541196100)
25c9cc #define FIX_0_765366865 ·FIX(0.765366865)
a05702 #define FIX_0_899976223 ·FIX(0.899976223)
3e95fc #define FIX_1_175875602 ·FIX(1.175875602)
2ab5b3 #define FIX_1_501321110 ·FIX(1.501321110)
e4b361 #define FIX_1_847759065 ·FIX(1.847759065)
21362e #define FIX_1_961570560 ·FIX(1.961570560)
7d7019 #define FIX_2_053119869 ·FIX(2.053119869)
8c0f60 #define FIX_2_562915447 ·FIX(2.562915447)
fb799b #define FIX_3_072711026 ·FIX(3.072711026)
f77454 #endif
c8af5a
c9af5a
c70109 /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
f63435 ·* For 8-bit samples with the recommended scaling, all the variable
20d3ec ·* and constant values involved are no more than 16 bits wide, so a
a36108 ·* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
3b0f0c ·* For 12-bit samples, a full 32-bit multiplication will be needed.
3f495d ·*/
a3af5a
586f80 #if BITS_IN_JSAMPLE == 8
cfedd8 #define MULTIPLY(var,const) ·MULTIPLY16C16(var,const)
f8db21 #else
b39398 #define MULTIPLY(var,const) ·((var) * (const))
a67454 #endif
fbaf5a
a4af5a
7a11ef /* Dequantize a coefficient by multiplying it by the multiplier-table
cd349c ·* entry; produce an int result. ·In this module, both inputs and result
77e0d2 ·* are 16 bits or less, so either int or short multiply will work.
2d495d ·*/
6faf5a
c78a14 #define DEQUANTIZE(coef,quantval) ·(((ISLOW_MULT_TYPE) (coef)) * (quantval))
4baf5a
c5af5a
b838e5 /*
5d6575 ·* Perform dequantization and inverse DCT on one block of coefficients.
--3d1a 0009daf430a40100036 Page 3 of jidctint.c
47495d ·*/
44af5a
06f898 GLOBAL(void)
aa26de jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
222655 ¤   ¤   ·JCOEFPTR coef_block,
e91e8c ¤   ¤   ·JSAMPARRAY output_buf, JDIMENSION output_col)
c0bb36 {
4ebaee ··INT32 tmp0, tmp1, tmp2, tmp3;
1c3c89 ··INT32 tmp10, tmp11, tmp12, tmp13;
1e5694 ··INT32 z1, z2, z3, z4, z5;
db3386 ··JCOEFPTR inptr;
15fc6a ··ISLOW_MULT_TYPE * quantptr;
83c9ea ··int * wsptr;
669e8f ··JSAMPROW outptr;
ab0b97 ··JSAMPLE *range_limit = IDCT_range_limit(cinfo);
83de0b ··int ctr;
277803 ··int workspace[DCTSIZE2];¤ /* buffers data between passes */
49ea99 ··SHIFT_TEMPS
a5af5a
529a02 ··/* Pass 1: process columns from input, store into work array. */
26876d ··/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
95d465 ··/* furthermore, we scale the results by 2**PASS1_BITS. */
54af5a
c9f17f ··inptr = coef_block;
4bed3b ··quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
21aab4 ··wsptr = workspace;
a16d3c ··for (ctr = DCTSIZE; ctr > 0; ctr--) {
4c54fa ····/* Due to quantization, we will usually find that many of the input
8c7d9b ·····* coefficients are zero, especially the AC terms. ·We can exploit this
17078d ·····* by short-circuiting the IDCT calculation for any column in which all
243dd5 ·····* the AC terms are zero. ·In that case each output is equal to the
a69749 ·····* DC coefficient (with scale factor as needed).
c434d3 ·····* With typical images and quantization tables, half or more of the
941e42 ·····* column DCT calculations can be simplified this way.
19d48d ·····*/
5e869e ····
7c1d3f ····if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
9a258f ¤   ·inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] |
687ee9 ¤   ·inptr[DCTSIZE*7]) == 0) {
ff3d5e ······/* AC terms all zero */
cb4539 ······int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BI¶
10362d TS;
cdcf72 ······
277654 ······wsptr[DCTSIZE*0] = dcval;
baf301 ······wsptr[DCTSIZE*1] = dcval;
8674ef ······wsptr[DCTSIZE*2] = dcval;
ddf1ba ······wsptr[DCTSIZE*3] = dcval;
b17322 ······wsptr[DCTSIZE*4] = dcval;
dbf677 ······wsptr[DCTSIZE*5] = dcval;
aa7199 ······wsptr[DCTSIZE*6] = dcval;
07f4cc ······wsptr[DCTSIZE*7] = dcval;
eacf72 ······
fb8132 ······inptr++;¤ ¤   ¤   /* advance pointers to next column */
9ac06d ······quantptr++;
b5655d ······wsptr++;
f75f6a ······continue;
3f6fe7 ····}
a0869e ····
796d26 ····/* Even part: reverse the even part of the forward DCT. */
a84f04 ····/* The rotator is sqrt(2)*c(-6). */
cd869e ····
77bb81 ····z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
1474f7 ····z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
b7869e ····
1dbb68 ····z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
3b346b ····tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
cd7be4 ····tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
e2869e ····
7e3fb8 ····z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
37f0ce ····z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
5eaf5a
9dec11 ····tmp0 = (z2 + z3) << CONST_BITS;
--42da 000bd91d56040100036 Page 4 of jidctint.c
49a648 ····tmp1 = (z2 - z3) << CONST_BITS;
75869e ····
985654 ····tmp10 = tmp0 + tmp3;
b87bf4 ····tmp13 = tmp0 - tmp3;
bb30a0 ····tmp11 = tmp1 + tmp2;
f91d00 ····tmp12 = tmp1 - tmp2;
fe869e ····
522a57 ····/* Odd part per figure 8; the matrix is unitary and hence its
47b5f5 ·····* transpose is its inverse. ·i0..i3 are y7,y5,y3,y1 respectively.
fdd48d ·····*/
07869e ····
2c7e09 ····tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
353525 ····tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
2be851 ····tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
f9a37d ····tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
55869e ····
495000 ····z1 = tmp0 + tmp3;
aa16ea ····z2 = tmp1 + tmp2;
b12ac2 ····z3 = tmp0 + tmp2;
212c14 ····z4 = tmp1 + tmp3;
0adccc ····z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
73869e ····
3b263a ····tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
3c8a81 ····tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
4a04be ····tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
4d5349 ····tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
512ce9 ····z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
1bca9a ····z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
103192 ····z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
a9fe7b ····z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
ee869e ····
bb3234 ····z3 += z5;
efdbd6 ····z4 += z5;
17869e ····
4bdcd4 ····tmp0 += z1 + z3;
2ea4eb ····tmp1 += z2 + z4;
5eabd0 ····tmp2 += z2 + z3;
bcd3ef ····tmp3 += z1 + z4;
17869e ····
172ad4 ····/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
3a869e ····
584f75 ····wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
af4d34 ····wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
c89932 ····wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
909b73 ····wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
b6ebea ····wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
60e9ab ····wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
e33dad ····wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
9c3fec ····wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
b5869e ····
ab42ab ····inptr++;¤   ¤   ¤   /* advance pointers to next column */
9b8b73 ····quantptr++;
08c0e3 ····wsptr++;
06df1c ··}
adde7b ··
e6bf3b ··/* Pass 2: process rows from work array, store into output array. */
004712 ··/* Note that we must descale the results by a factor of 8 == 2**3, */
e1012d ··/* and also undo the PASS1_BITS scaling. */
33af5a
2caab4 ··wsptr = workspace;
847b7e ··for (ctr = 0; ctr < DCTSIZE; ctr++) {
b931c4 ····outptr = output_buf[ctr] + output_col;
52b392 ····/* Rows of zeroes can be exploited in the same way as we did with columns.
e20e3c ·····* However, the column calculation has created many nonzero AC terms, so
ae5b5b ·····* the simplification applies less often (typically 5% to 10% of the time).
75cbdb ·····* On machines with very fast multiplication, it's possible that the
67a947 ·····* test takes more time than it's worth. ·In that case this section
1a0c9f ·····* may be commented out.
e3d48d ·····*/
a2869e ····
c8d020 #ifndef NO_ZERO_ROW_TEST
bdd32b ····if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[4] | wsptr[5] | wsptr[6] |
--cc58 0002a7fb79540100036 Page 5 of jidctint.c
1ae81b ¤   ·wsptr[7]) == 0) {
103d5e ······/* AC terms all zero */
434c18 ······JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
884788 ¤   ¤   ¤   ¤   ··& RANGE_MASK];
5acf72 ······
00b104 ······outptr[0] = dcval;
f63451 ······outptr[1] = dcval;
6bb3bf ······outptr[2] = dcval;
9436ea ······outptr[3] = dcval;
08b472 ······outptr[4] = dcval;
423127 ······outptr[5] = dcval;
eab6c9 ······outptr[6] = dcval;
d3339c ······outptr[7] = dcval;
d8af5a
e21820 ······wsptr += DCTSIZE;¤¤   /* advance pointer to next row */
245f6a ······continue;
d56fe7 ····}
dc7454 #endif
d2869e ····
7b6d26 ····/* Even part: reverse the even part of the forward DCT. */
dc4f04 ····/* The rotator is sqrt(2)*c(-6). */
ee869e ····
06539c ····z2 = (INT32) wsptr[2];
35882d ····z3 = (INT32) wsptr[6];
df869e ····
d6bb68 ····z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
e0346b ····tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
1d7be4 ····tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
f8869e ····
6af9f4 ····tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
a402b0 ····tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS;
3e869e ····
6c5654 ····tmp10 = tmp0 + tmp3;
9f7bf4 ····tmp13 = tmp0 - tmp3;
8e30a0 ····tmp11 = tmp1 + tmp2;
7a1d00 ····tmp12 = tmp1 - tmp2;
1f869e ····
072a57 ····/* Odd part per figure 8; the matrix is unitary and hence its
81b5f5 ·····* transpose is its inverse. ·i0..i3 are y7,y5,y3,y1 respectively.
42d48d ·····*/
0a869e ····
ae11b7 ····tmp0 = (INT32) wsptr[7];
7c819c ····tmp1 = (INT32) wsptr[5];
0f39f0 ····tmp2 = (INT32) wsptr[3];
0ba9db ····tmp3 = (INT32) wsptr[1];
7f869e ····
c45000 ····z1 = tmp0 + tmp3;
fc16ea ····z2 = tmp1 + tmp2;
bc2ac2 ····z3 = tmp0 + tmp2;
3e2c14 ····z4 = tmp1 + tmp3;
75dccc ····z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
7a869e ····
76263a ····tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
bc8a81 ····tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
0404be ····tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
b55349 ····tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
bf2ce9 ····z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
29ca9a ····z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
173192 ····z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
9cfe7b ····z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
47869e ····
4c3234 ····z3 += z5;
acdbd6 ····z4 += z5;
d2869e ····
81dcd4 ····tmp0 += z1 + z3;
e9a4eb ····tmp1 += z2 + z4;
55abd0 ····tmp2 += z2 + z3;
ead3ef ····tmp3 += z1 + z4;
cd869e ····
6c2ad4 ····/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
5c869e ····
2a47e6 ····outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
--bb84 001a3b45eb240100036 Page 6 of jidctint.c
63a190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
1b0c4d ¤   ¤   ¤   ····& RANGE_MASK];
59d8f6 ····outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
cda190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
b40c4d ¤   ¤   ¤   ····& RANGE_MASK];
ea0726 ····outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
dfa190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
c90c4d ¤   ¤   ¤   ····& RANGE_MASK];
ca9836 ····outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
27a190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
200c4d ¤   ¤   ¤   ····& RANGE_MASK];
2fc666 ····outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
4da190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
fd0c4d ¤   ¤   ¤   ····& RANGE_MASK];
5d5976 ····outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
1ba190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
7a0c4d ¤   ¤   ¤   ····& RANGE_MASK];
eb86a6 ····outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
fda190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
360c4d ¤   ¤   ¤   ····& RANGE_MASK];
1119b6 ····outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
67a190 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3)
4d0c4d ¤   ¤   ¤   ····& RANGE_MASK];
3f869e ····
5d5817 ····wsptr += DCTSIZE;¤  ¤   /* advance pointer to next row */
cedf1c ··}
b9efe6 }
0baf5a
a3c44c #endif /* DCT_ISLOW_SUPPORTED */
--74da 000e5a6c0ec40100037 Page 1 of jidctred.c
bc38e5 /*
57e67f ·* jidctred.c
d7775e ·*
939e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
f8fb07 ·* This file is part of the Independent JPEG Group's software.
58a0d6 ·* For conditions of distribution and use, see the accompanying README file.
2f775e ·*
232a94 ·* This file contains inverse-DCT routines that produce reduced-size output:
9d54e6 ·* either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block.
a6775e ·*
f32be3 ·* The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M)
eeafa6 ·* algorithm used in jidctint.c. ·We simply replace each 8-to-8 1-D IDCT step
312b3c ·* with an 8-to-4 step that produces the four averages of two adjacent outputs
7c4daf ·* (or an 8-to-2 step producing two averages of four outputs, for 2x2 output).
3e2b24 ·* These steps were derived by computing the corresponding values at the end
022244 ·* of the normal LL&M code, then simplifying as much as possible.
c2775e ·*
aeaf85 ·* 1x1 is trivial: just take the DC coefficient divided by 8.
48775e ·*
574b68 ·* See jidctint.c for additional comments.
df495d ·*/
18af5a
3a2bb6 #define JPEG_INTERNALS
9d36a7 #include "jinclude.h"
fe6c8f #include "jpeglib.h"
1eef10 #include "jdct.h"¤  ¤   /* Private declarations for DCT subsystem */
48af5a
1625de #ifdef IDCT_SCALING_SUPPORTED
eaaf5a
29af5a
d838e5 /*
51f914 ·* This module is specialized to the case DCTSIZE = 8.
27495d ·*/
afaf5a
4e5f63 #if DCTSIZE != 8
8b5f24 ··Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
297454 #endif
6baf5a
e5af5a
08865a /* Scaling is the same as in jidctint.c. */
70af5a
376f80 #if BITS_IN_JSAMPLE == 8
a95980 #define CONST_BITS ·13
b740c6 #define PASS1_BITS ·2
32db21 #else
ff5980 #define CONST_BITS ·13
bfaa57 #define PASS1_BITS ·1¤  ¤   /* lose a little precision to avoid overflow */
807454 #endif
5eaf5a
a923ff /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
4df4ab ·* causing a lot of useless floating-point operations at run time.
2de9b9 ·* To get around this we use the following pre-calculated constants.
41c135 ·* If you change CONST_BITS you may want to add appropriate values.
5ce109 ·* (With a reasonable C compiler, you can just rely on the FIX() macro...)
7f495d ·*/
daaf5a
900d01 #if CONST_BITS == 13
4c7d3a #define FIX_0_211164243 ·((INT32) ·1730)¤   /* FIX(0.211164243) */
881e5e #define FIX_0_509795579 ·((INT32) ·4176)¤   /* FIX(0.509795579) */
fb9d04 #define FIX_0_601344887 ·((INT32) ·4926)¤   /* FIX(0.601344887) */
6c781b #define FIX_0_720959822 ·((INT32) ·5906)¤   /* FIX(0.720959822) */
215e2f #define FIX_0_765366865 ·((INT32) ·6270)¤   /* FIX(0.765366865) */
c9913c #define FIX_0_850430095 ·((INT32) ·6967)¤   /* FIX(0.850430095) */
c20a06 #define FIX_0_899976223 ·((INT32) ·7373)¤   /* FIX(0.899976223) */
04d3fd #define FIX_1_061594337 ·((INT32) ·8697)¤   /* FIX(1.061594337) */
808394 #define FIX_1_272758580 ·((INT32) ·10426)¤  /* FIX(1.272758580) */
13e591 #define FIX_1_451774981 ·((INT32) ·11893)¤  /* FIX(1.451774981) */
afd534 #define FIX_1_847759065 ·((INT32) ·15137)¤  /* FIX(1.847759065) */
dd1083 #define FIX_2_172734803 ·((INT32) ·17799)¤  /* FIX(2.172734803) */
143252 #define FIX_2_562915447 ·((INT32) ·20995)¤  /* FIX(2.562915447) */
b0f1fc #define FIX_3_624509785 ·((INT32) ·29692)¤  /* FIX(3.624509785) */
e5db21 #else
--1bfb 0001121e3bf40100037 Page 2 of jidctred.c
cc7b84 #define FIX_0_211164243 ·FIX(0.211164243)
0f2d3f #define FIX_0_509795579 ·FIX(0.509795579)
2e721e #define FIX_0_601344887 ·FIX(0.601344887)
cc3b15 #define FIX_0_720959822 ·FIX(0.720959822)
60c9cc #define FIX_0_765366865 ·FIX(0.765366865)
013903 #define FIX_0_850430095 ·FIX(0.850430095)
275702 #define FIX_0_899976223 ·FIX(0.899976223)
e739f6 #define FIX_1_061594337 ·FIX(1.061594337)
69fabe #define FIX_1_272758580 ·FIX(1.272758580)
48020b #define FIX_1_451774981 ·FIX(1.451774981)
8ab361 #define FIX_1_847759065 ·FIX(1.847759065)
150082 #define FIX_2_172734803 ·FIX(2.172734803)
0b0f60 #define FIX_2_562915447 ·FIX(2.562915447)
b6d53d #define FIX_3_624509785 ·FIX(3.624509785)
687454 #endif
19af5a
99af5a
b40109 /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
eb3435 ·* For 8-bit samples with the recommended scaling, all the variable
61d3ec ·* and constant values involved are no more than 16 bits wide, so a
866108 ·* 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
720f0c ·* For 12-bit samples, a full 32-bit multiplication will be needed.
55495d ·*/
51af5a
906f80 #if BITS_IN_JSAMPLE == 8
48edd8 #define MULTIPLY(var,const) ·MULTIPLY16C16(var,const)
93db21 #else
fd9398 #define MULTIPLY(var,const) ·((var) * (const))
b47454 #endif
8faf5a
67af5a
d111ef /* Dequantize a coefficient by multiplying it by the multiplier-table
d0349c ·* entry; produce an int result. ·In this module, both inputs and result
e8e0d2 ·* are 16 bits or less, so either int or short multiply will work.
ec495d ·*/
65af5a
bd8a14 #define DEQUANTIZE(coef,quantval) ·(((ISLOW_MULT_TYPE) (coef)) * (quantval))
d8af5a
5baf5a
2138e5 /*
6d56c5 ·* Perform dequantization and inverse DCT on one block of coefficients,
0bd9db ·* producing a reduced-size 4x4 output block.
c2495d ·*/
c2af5a
59f898 GLOBAL(void)
191db8 jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
ecfec0 ¤   ·······JCOEFPTR coef_block,
ce9784 ¤   ·······JSAMPARRAY output_buf, JDIMENSION output_col)
0cbb36 {
71fa86 ··INT32 tmp0, tmp2, tmp10, tmp12;
f606b7 ··INT32 z1, z2, z3, z4;
0e3386 ··JCOEFPTR inptr;
79fc6a ··ISLOW_MULT_TYPE * quantptr;
58c9ea ··int * wsptr;
699e8f ··JSAMPROW outptr;
010b97 ··JSAMPLE *range_limit = IDCT_range_limit(cinfo);
4ede0b ··int ctr;
fb7ea0 ··int workspace[DCTSIZE*4];¤/* buffers data between passes */
15ea99 ··SHIFT_TEMPS
11af5a
4d9a02 ··/* Pass 1: process columns from input, store into work array. */
69af5a
ebf17f ··inptr = coef_block;
15ed3b ··quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
dfaab4 ··wsptr = workspace;
1c3ce3 ··for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
9f68ce ····/* Don't bother to process column 4, because second pass won't use it */
dbcbb1 ····if (ctr == DCTSIZE-4)
795f6a ······continue;
8a1d3f ····if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] |
fc529a ¤   ·inptr[DCTSIZE*5] | inptr[DCTSIZE*6] | inptr[DCTSIZE*7]) == 0) {
1185eb ······/* AC terms all zero; we need not examine term 4 for 4x4 output */
--9973 0007f8f0c4440100037 Page 3 of jidctred.c
c84539 ······int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BI¶
3c362d TS;
e5cf72 ······
177654 ······wsptr[DCTSIZE*0] = dcval;
0af301 ······wsptr[DCTSIZE*1] = dcval;
6274ef ······wsptr[DCTSIZE*2] = dcval;
3af1ba ······wsptr[DCTSIZE*3] = dcval;
87cf72 ······
ef5f6a ······continue;
186fe7 ····}
9f869e ····
d83f6a ····/* Even part */
ae869e ····
643c47 ····tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
a7d5d8 ····tmp0 <<= (CONST_BITS+1);
23869e ····
0abb81 ····z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
3874f7 ····z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
2eaf5a
7cbff7 ····tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
ab869e ····
460c88 ····tmp10 = tmp0 + tmp2;
a23127 ····tmp12 = tmp0 - tmp2;
80869e ····
4ce722 ····/* Odd part */
b0869e ····
ca24d8 ····z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
5cf9cf ····z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
66b280 ····z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
cc4bf0 ····z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
70869e ····
f44fec ····tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
595719 ¤   ·+ MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
00a543 ¤   ·+ MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
df8102 ¤   ·+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
fd869e ····
43fd37 ····tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
b63ee7 ¤   ·+ MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
98b407 ¤   ·+ MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
6ac7e8 ¤   ·+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
82af5a
2c6acb ····/* Final output stage */
47869e ····
8c1697 ····wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
c9c4a4 ····wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
b651c0 ····wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
c683f3 ····wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
65df1c ··}
c0de7b ··
9162e9 ··/* Pass 2: process 4 rows from work array, store into output array. */
e9af5a
23aab4 ··wsptr = workspace;
489e4d ··for (ctr = 0; ctr < 4; ctr++) {
cb31c4 ····outptr = output_buf[ctr] + output_col;
adddd1 ····/* It's not clear whether a zero row test is worthwhile here ... */
8caf5a
cfd020 #ifndef NO_ZERO_ROW_TEST
197018 ····if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[5] | wsptr[6] |
49e81b ¤   ·wsptr[7]) == 0) {
b53d5e ······/* AC terms all zero */
ac4c18 ······JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
0d4788 ¤   ¤   ¤   ¤   ··& RANGE_MASK];
61cf72 ······
17b104 ······outptr[0] = dcval;
6d3451 ······outptr[1] = dcval;
0ab3bf ······outptr[2] = dcval;
6836ea ······outptr[3] = dcval;
59cf72 ······
4c1820 ······wsptr += DCTSIZE;¤¤   /* advance pointer to next row */
ce5f6a ······continue;
006fe7 ····}
7f7454 #endif
--51c3 000fdc0f48f40100037 Page 4 of jidctred.c
a9869e ····
d83f6a ····/* Even part */
c3869e ····
0b2a7b ····tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1);
c2869e ····
81d06c ····tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065)
3e47ee ¤   ·+ MULTIPLY((INT32) wsptr[6], - FIX_0_765366865);
00869e ····
a00c88 ····tmp10 = tmp0 + tmp2;
d73127 ····tmp12 = tmp0 - tmp2;
d3869e ····
59e722 ····/* Odd part */
ff869e ····
99ce3d ····z1 = (INT32) wsptr[7];
b604bd ····z2 = (INT32) wsptr[5];
3ee67a ····z3 = (INT32) wsptr[3];
8099ac ····z4 = (INT32) wsptr[1];
0d869e ····
254fec ····tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
ee5719 ¤   ·+ MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
6aa543 ¤   ·+ MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
2e8102 ¤   ·+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
61869e ····
0efd37 ····tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
053ee7 ¤   ·+ MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
6eb407 ¤   ·+ MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
b3c7e8 ¤   ·+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
08af5a
946acb ····/* Final output stage */
ad869e ····
0c1d3a ····outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
2e60d1 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3+1)
d10c4d ¤   ¤   ¤   ····& RANGE_MASK];
2c5ac6 ····outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
1760d1 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3+1)
620c4d ¤   ¤   ¤   ····& RANGE_MASK];
8cc6f7 ····outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
1660d1 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3+1)
070c4d ¤   ¤   ¤   ····& RANGE_MASK];
e5810b ····outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
c060d1 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3+1)
fc0c4d ¤   ¤   ¤   ····& RANGE_MASK];
d3869e ····
ae5817 ····wsptr += DCTSIZE;¤  ¤   /* advance pointer to next row */
81df1c ··}
4aefe6 }
38af5a
fbaf5a
7438e5 /*
5b56c5 ·* Perform dequantization and inverse DCT on one block of coefficients,
36e7f8 ·* producing a reduced-size 2x2 output block.
3a495d ·*/
1baf5a
aaf898 GLOBAL(void)
e6689e jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
effec0 ¤   ·······JCOEFPTR coef_block,
9c9784 ¤   ·······JSAMPARRAY output_buf, JDIMENSION output_col)
40bb36 {
64479c ··INT32 tmp0, tmp10, z1;
673386 ··JCOEFPTR inptr;
4efc6a ··ISLOW_MULT_TYPE * quantptr;
f3c9ea ··int * wsptr;
5d9e8f ··JSAMPROW outptr;
760b97 ··JSAMPLE *range_limit = IDCT_range_limit(cinfo);
96de0b ··int ctr;
d79823 ··int workspace[DCTSIZE*2];¤/* buffers data between passes */
59ea99 ··SHIFT_TEMPS
14af5a
6a9a02 ··/* Pass 1: process columns from input, store into work array. */
2daf5a
05f17f ··inptr = coef_block;
fded3b ··quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
--99aa 000346861f940100037 Page 5 of jidctred.c
dfaab4 ··wsptr = workspace;
473ce3 ··for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
0e7891 ····/* Don't bother to process columns 2,4,6 */
87f5b7 ····if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
285f6a ······continue;
abfc19 ····if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*3] |
dabde5 ¤   ·inptr[DCTSIZE*5] | inptr[DCTSIZE*7]) == 0) {
551a59 ······/* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
124539 ······int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BI¶
93362d TS;
ebcf72 ······
9a7654 ······wsptr[DCTSIZE*0] = dcval;
08f301 ······wsptr[DCTSIZE*1] = dcval;
d6cf72 ······
6c5f6a ······continue;
726fe7 ····}
d0869e ····
513f6a ····/* Even part */
b0869e ····
5d6696 ····z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
172882 ····tmp10 = z1 << (CONST_BITS+2);
95869e ····
95e722 ····/* Odd part */
dbaf5a
e824d8 ····z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
a243d5 ····tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
cda0e1 ····z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
a2d78d ····tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
9224bb ····z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
ba41cf ····tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
aaa082 ····z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
8b9936 ····tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
b8af5a
566acb ····/* Final output stage */
10869e ····
79c929 ····wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
62c85d ····wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
37df1c ··}
acde7b ··
596ab4 ··/* Pass 2: process 2 rows from work array, store into output array. */
28af5a
7aaab4 ··wsptr = workspace;
419980 ··for (ctr = 0; ctr < 2; ctr++) {
5a31c4 ····outptr = output_buf[ctr] + output_col;
a9ddd1 ····/* It's not clear whether a zero row test is worthwhile here ... */
b5af5a
66d020 #ifndef NO_ZERO_ROW_TEST
32cb8e ····if ((wsptr[1] | wsptr[3] | wsptr[5] | wsptr[7]) == 0) {
6e3d5e ······/* AC terms all zero */
a44c18 ······JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
234788 ¤   ¤   ¤   ¤   ··& RANGE_MASK];
ddcf72 ······
2fb104 ······outptr[0] = dcval;
0f3451 ······outptr[1] = dcval;
f4cf72 ······
4f1820 ······wsptr += DCTSIZE;¤¤   /* advance pointer to next row */
655f6a ······continue;
3f6fe7 ····}
f07454 #endif
3b869e ····
3e3f6a ····/* Even part */
47869e ····
890bf2 ····tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2);
19869e ····
74e722 ····/* Odd part */
4aaf5a
5f5af8 ····tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3¶
68027b -c1) */
30d731 ¤   ·+ MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) ¶
fc7fe0 */
b66be4 ¤   ·+ MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7¶
34c146 ) */
--5b44 0011c4708f840100037 Page 6 of jidctred.c
b5e8df ¤   ·+ MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) ¶
d87fe0 */
ffaf5a
6d6acb ····/* Final output stage */
2b869e ····
faa882 ····outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
628fb5 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3+2)
440c4d ¤   ¤   ¤   ····& RANGE_MASK];
928308 ····outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
168fb5 ¤   ¤   ¤   ¤   ¤   ··CONST_BITS+PASS1_BITS+3+2)
1c0c4d ¤   ¤   ¤   ····& RANGE_MASK];
b3869e ····
3e5817 ····wsptr += DCTSIZE;¤  ¤   /* advance pointer to next row */
bddf1c ··}
1defe6 }
0faf5a
89af5a
b038e5 /*
2a56c5 ·* Perform dequantization and inverse DCT on one block of coefficients,
a27ce1 ·* producing a reduced-size 1x1 output block.
28495d ·*/
e8af5a
46f898 GLOBAL(void)
06520d jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
9afec0 ¤   ·······JCOEFPTR coef_block,
c69784 ¤   ·······JSAMPARRAY output_buf, JDIMENSION output_col)
e0bb36 {
33484e ··int dcval;
65fc6a ··ISLOW_MULT_TYPE * quantptr;
080b97 ··JSAMPLE *range_limit = IDCT_range_limit(cinfo);
f2ea99 ··SHIFT_TEMPS
f2af5a
2ea307 ··/* We hardly need an inverse DCT routine for this: just take the
e10dbc ···* average pixel value, which is one-eighth of the DC coefficient.
23f9a6 ···*/
9eed3b ··quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
aa5b6a ··dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
c66b0c ··dcval = (int) DESCALE((INT32) dcval, 3);
2faf5a
e66088 ··output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
a6efe6 }
b8af5a
1c5a53 #endif /* IDCT_SCALING_SUPPORTED */
--136e 00046d1755c40100038 Page 1 of jinclude.h
bc38e5 /*
ed86ec ·* jinclude.h
70775e ·*
248ee3 ·* Copyright (C) 1991-1994, Thomas G. Lane.
55fb07 ·* This file is part of the Independent JPEG Group's software.
52a0d6 ·* For conditions of distribution and use, see the accompanying README file.
f2775e ·*
44c5f0 ·* This file exists to provide a single place to fix any problems with
816d6c ·* including the wrong system include files. ·(Common problems are taken
899965 ·* care of by the standard jconfig symbols, but on really weird systems
ff9f12 ·* you may have to edit this file.)
39775e ·*
6df041 ·* NOTE: this file is NOT intended to be included by applications using the
e3ee36 ·* JPEG library. ·Most applications need only include jpeglib.h.
ba495d ·*/
b7af5a
11af5a
2593ed /* Include auto-config file to find out which system include files we need. */
75af5a
aad5a7 #include "jconfig.h"¤   ¤   /* auto configuration options */
3e8744 #define JCONFIG_INCLUDED¤   /* so that jpeglib.h doesn't do it again */
3eaf5a
4138e5 /*
9d8050 ·* We need the NULL macro and size_t typedef.
fc7899 ·* On an ANSI-conforming system it is sufficient to include <stddef.h>.
8e4faf ·* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
206efd ·* pull in <sys/types.h> as well.
6738e6 ·* Note that the core JPEG library does not require <stdio.h>;
d5d4ac ·* only the default error handler and data source/destination modules do.
33c79d ·* But we must pull it in because of the references to FILE in jpeglib.h.
39c681 ·* You can remove those references if you want to compile without <stdio.h>.
c7495d ·*/
c1af5a
41cb06 #ifdef HAVE_STDDEF_H
6c7cab #include <stddef.h>
227454 #endif
8eaf5a
c9ef82 #ifdef HAVE_STDLIB_H
42bea3 #include <stdlib.h>
b97454 #endif
68af5a
83b6d1 #ifdef NEED_SYS_TYPES_H
73f15e #include <sys/types.h>
c77454 #endif
22af5a
e7feb2 #include <stdio.h>
29af5a
1b38e5 /*
c5eba4 ·* We need memory copying and zeroing functions, plus strncpy().
c7ef04 ·* ANSI and System V implementations declare these in <string.h>.
f4452a ·* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
dcddce ·* Some systems may declare memset and memcpy in <memory.h>.
d8775e ·*
3fc58c ·* NOTE: we assume the size parameters to these functions are of type size_t.
0c7059 ·* Change the casts in these macros if not!
1e495d ·*/
f2af5a
329014 #ifdef NEED_BSD_STRINGS
a7af5a
54f7c3 #include <strings.h>
46e73b #define MEMZERO(target,size)¤   bzero((void *)(target), (size_t)(size))
4e9f29 #define MEMCOPY(dest,src,size)¤ bcopy((const void *)(src), (void *)(dest), (siz¶
a8ece1 e_t)(size))
e4af5a
1dc121 #else /* not BSD, assume ANSI/SysV string lib */
e0af5a
a4324c #include <string.h>
5e171d #define MEMZERO(target,size)¤   memset((void *)(target), 0, (size_t)(size))
c408ca #define MEMCOPY(dest,src,size)¤ memcpy((void *)(dest), (const void *)(src), (si¶
c446f2 ze_t)(size))
9daf5a
467454 #endif
--b41e 0011c06671940100038 Page 2 of jinclude.h
e0af5a
d338e5 /*
6dff4f ·* In ANSI C, and indeed any rational implementation, size_t is also the
3e0eec ·* type returned by sizeof(). ·However, it seems there are some irrational
54ddbd ·* implementations out there, in which sizeof() returns an int even though
e32af1 ·* size_t is defined as long or unsigned long. ·To ensure consistent results
83c21c ·* we always use this SIZEOF() macro in place of using sizeof() directly.
87495d ·*/
f8af5a
119cb3 #define SIZEOF(object)¤ ((size_t) sizeof(object))
8aaf5a
b238e5 /*
27b4c0 ·* The modules that use fread() and fwrite() always invoke them through
19edbd ·* these macros. ·On some systems you may need to twiddle the argument casts.
58587e ·* CAUTION: argument order is different from underlying functions!
f8495d ·*/
c6af5a
bd5d0e #define JFREAD(file,buf,sizeofbuf) ·\
b1faed ··((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
82fcad #define JFWRITE(file,buf,sizeofbuf) ·\
23fe2d ··((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (fil¶
1c3583 e)))
--d977 000aa9b42db40100039 Page 1 of jmemansi.c
bc38e5 /*
00196a ·* jmemansi.c
8e775e ·*
904dac ·* Copyright (C) 1992-1996, Thomas G. Lane.
22fb07 ·* This file is part of the Independent JPEG Group's software.
9ca0d6 ·* For conditions of distribution and use, see the accompanying README file.
d4775e ·*
030b87 ·* This file provides a simple generic implementation of the system-
db6811 ·* dependent portion of the JPEG memory manager. ·This implementation
b1d2c4 ·* assumes that you have the ANSI-standard library routine tmpfile().
5675b4 ·* Also, the problem of determining the amount of memory available
7b691f ·* is shoved onto the user.
a4495d ·*/
87af5a
dd2bb6 #define JPEG_INTERNALS
4736a7 #include "jinclude.h"
f26c8f #include "jpeglib.h"
d4ad99 #include "jmemsys.h"¤   ¤   /* import the system-dependent declarations */
10af5a
f52eee #ifndef HAVE_STDLIB_H¤  ¤   /* <stdlib.h> should declare malloc(),free() */
5514e9 extern void * malloc JPP((size_t size));
757757 extern void free JPP((void *ptr));
f57454 #endif
faaf5a
c474a4 #ifndef SEEK_SET¤   ¤   /* pre-ANSI systems may not define this; */
9fd978 #define SEEK_SET ·0¤¤   /* if not, assume 0 is correct */
277454 #endif
71af5a
c9af5a
0c38e5 /*
215c23 ·* Memory allocation and freeing are controlled by the regular library
73f3bc ·* routines malloc() and free().
5f495d ·*/
60af5a
e10d73 GLOBAL(void *)
81dd1d jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
78bb36 {
a7b34f ··return (void *) malloc(sizeofobject);
c5efe6 }
e2af5a
03f898 GLOBAL(void)
10689f jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
a4bb36 {
7f59e9 ··free(object);
65efe6 }
08af5a
5faf5a
b238e5 /*
1dff4f ·* "Large" objects are treated the same as "small" ones.
811d0b ·* NB: although we include FAR keywords in the routine declarations,
1c0d9e ·* this file won't actually work in 80x86 small/medium model; at least,
314054 ·* you probably won't be able to process useful-size images in only 64KB.
df495d ·*/
86af5a
07b820 GLOBAL(void FAR *)
acfa94 jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
1abb36 {
b4e2cb ··return (void FAR *) malloc(sizeofobject);
66efe6 }
b0af5a
aef898 GLOBAL(void)
af4b37 jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
a6bb36 {
ff59e9 ··free(object);
a5efe6 }
95af5a
afaf5a
8838e5 /*
326605 ·* This routine computes the total memory space available for allocation.
8b12fd ·* It's impossible to do this in a portable way; our current solution is
12e86d ·* to make the user tell us (with a default value set at compile time).
aa20d1 ·* If you can actually get the available space, it's a good idea to subtract
--9d1c 000d26c483940100039 Page 2 of jmemansi.c
4ffd52 ·* a slop factor of 5% or so.
fa495d ·*/
c9af5a
4f3176 #ifndef DEFAULT_MAX_MEM¤¤   /* so can override from makefile */
15421a #define DEFAULT_MAX_MEM¤¤   1000000L /* default: one megabyte */
b17454 #endif
2caf5a
2f2b63 GLOBAL(long)
6eee2d jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
3a4fe9 ¤   ¤   ····long max_bytes_needed, long already_allocated)
09bb36 {
18c5a4 ··return cinfo->mem->max_memory_to_use - already_allocated;
2fefe6 }
43af5a
f8af5a
f538e5 /*
930fbc ·* Backing store (temporary file) management.
a516ad ·* Backing store objects are only used when the value returned by
147c99 ·* jpeg_mem_available is less than the total space needed. ·You can dispense
d49cac ·* with these routines if you have plenty of virtual memory; see jmemnobs.c.
ff495d ·*/
f5af5a
f8af5a
df0434 METHODDEF(void)
c0ce2b read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
bfa8ab ¤   ¤   ····void FAR * buffer_address,
186885 ¤   ¤   ····long file_offset, long byte_count)
97bb36 {
46e814 ··if (fseek(info->temp_file, file_offset, SEEK_SET))
ba5f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
638eae ··if (JFREAD(info->temp_file, buffer_address, byte_count)
47ef53 ······!= (size_t) byte_count)
de5fb6 ····ERREXIT(cinfo, JERR_TFILE_READ);
b1efe6 }
8eaf5a
29af5a
a00434 METHODDEF(void)
1ecc29 write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
3cd7d2 ¤   ¤   ·····void FAR * buffer_address,
7f4447 ¤   ¤   ·····long file_offset, long byte_count)
abbb36 {
f4e814 ··if (fseek(info->temp_file, file_offset, SEEK_SET))
965f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
870c71 ··if (JFWRITE(info->temp_file, buffer_address, byte_count)
54ef53 ······!= (size_t) byte_count)
ed9e97 ····ERREXIT(cinfo, JERR_TFILE_WRITE);
34efe6 }
a9af5a
90af5a
890434 METHODDEF(void)
c42787 close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
cabb36 {
1a455f ··fclose(info->temp_file);
5a3079 ··/* Since this implementation uses tmpfile() to create the file,
066945 ···* no explicit file deletion is needed.
2df9a6 ···*/
1cefe6 }
adaf5a
4daf5a
c638e5 /*
9b83c1 ·* Initial opening of a backing-store object.
9d775e ·*
a32092 ·* This version uses tmpfile(), which constructs a suitable file name
2ba522 ·* behind the scenes. ·We don't have to use info->temp_name[] at all;
97fd48 ·* indeed, we can't even find out the actual name of the temp file.
cf495d ·*/
fcaf5a
f5f898 GLOBAL(void)
9c78ae jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
e2c744 ¤   ¤   ¤   ·long total_bytes_needed)
45bb36 {
d23e3c ··if ((info->temp_file = tmpfile()) == NULL)
--909a 001196ef5f140100039 Page 3 of jmemansi.c
93a91d ····ERREXITS(cinfo, JERR_TFILE_CREATE, "");
98c927 ··info->read_backing_store = read_backing_store;
48de99 ··info->write_backing_store = write_backing_store;
7fffb1 ··info->close_backing_store = close_backing_store;
68efe6 }
82af5a
90af5a
5138e5 /*
0b4a87 ·* These routines take care of any system-dependent initialization and
b41720 ·* cleanup required.
52495d ·*/
1faf5a
c22b63 GLOBAL(long)
7147b0 jpeg_mem_init (j_common_ptr cinfo)
12bb36 {
73ea9c ··return DEFAULT_MAX_MEM;¤  /* default for max_memory_to_use */
1befe6 }
40af5a
3ef898 GLOBAL(void)
86e7ea jpeg_mem_term (j_common_ptr cinfo)
5ebb36 {
ae6ded ··/* no work */
19efe6 }
--168b 00051e90cab4010003a Page 1 of jmemdos.c
bc38e5 /*
7e3eea ·* jmemdos.c
fb775e ·*
1b4dac ·* Copyright (C) 1992-1996, Thomas G. Lane.
77fb07 ·* This file is part of the Independent JPEG Group's software.
efa0d6 ·* For conditions of distribution and use, see the accompanying README file.
fa775e ·*
5ea730 ·* This file provides an MS-DOS-compatible implementation of the system-
ee9271 ·* dependent portion of the JPEG memory manager. ·Temporary data can be
3ba911 ·* stored in extended or expanded memory as well as in regular DOS files.
63775e ·*
e8b32b ·* If you use this file, you must be sure that NEED_FAR_POINTERS is defined
061408 ·* if you compile in a small-data memory model; it should NOT be defined if
f3f795 ·* you use a large-data memory model. ·This file is not recommended if you
95cc7b ·* are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
ea1ddb ·* Also, this code will NOT work if struct fields are aligned on greater than
3bd156 ·* 2-byte boundaries.
55775e ·*
bdc4a5 ·* Based on code contributed by Ge' Weijers.
e6495d ·*/
daaf5a
8a38e5 /*
1b360c ·* If you have both extended and expanded memory, you may want to change the
96122f ·* order in which they are tried in jopen_backing_store. ·On a 286 machine
4ca068 ·* expanded memory is usually faster, since extended memory access involves
9180cc ·* an expensive protected-mode-and-back switch. ·On 386 and better, extended
6effdf ·* memory is usually faster. ·As distributed, the code tries extended memory
1f64e9 ·* first (what? not everyone has a 386? :-).
ec775e ·*
2acdc4 ·* You can disable use of extended/expanded memory entirely by altering these
6c82ce ·* definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
43495d ·*/
57af5a
b11e34 #ifndef XMS_SUPPORTED
c6fc3e #define XMS_SUPPORTED ·1
227454 #endif
b4aad3 #ifndef EMS_SUPPORTED
292494 #define EMS_SUPPORTED ·1
ca7454 #endif
6daf5a
1aaf5a
562bb6 #define JPEG_INTERNALS
4236a7 #include "jinclude.h"
816c8f #include "jpeglib.h"
bead99 #include "jmemsys.h"¤   ¤   /* import the system-dependent declarations */
ceaf5a
dda08a #ifndef HAVE_STDLIB_H¤  ¤   /* <stdlib.h> should declare these */
f114e9 extern void * malloc JPP((size_t size));
e27757 extern void free JPP((void *ptr));
4e1683 extern char * getenv JPP((const char * name));
2f7454 #endif
33af5a
7716ae #ifdef NEED_FAR_POINTERS
8eaf5a
0e32bd #ifdef __TURBOC__
0b8391 /* These definitions work for Borland C (Turbo C) */
48d903 #include <alloc.h>¤ ¤   /* need farmalloc(), farfree() */
23ab84 #define far_malloc(x)¤  farmalloc(x)
70c908 #define far_free(x)¤farfree(x)
ebdb21 #else
ab5c93 /* These definitions work for Microsoft C and compatible compilers */
444d37 #include <malloc.h>¤¤   /* need _fmalloc(), _ffree() */
fe9db5 #define far_malloc(x)¤  _fmalloc(x)
08a02b #define far_free(x)¤_ffree(x)
a47454 #endif
b4af5a
8182a9 #else /* not NEED_FAR_POINTERS */
59af5a
e91efc #define far_malloc(x)¤  malloc(x)
260afa #define far_free(x)¤free(x)
d2af5a
51e8df #endif /* NEED_FAR_POINTERS */
--18e3 0004bf53fc24010003a Page 2 of jmemdos.c
e0af5a
1c7a86 #ifdef DONT_USE_B_MODE¤ ¤   /* define mode parameters for fopen() */
25ea4e #define READ_BINARY¤"r"
04db21 #else
aaef4f #define READ_BINARY¤"rb"
5e7454 #endif
41af5a
b847dd #if MAX_ALLOC_CHUNK >= 65535L¤  /* make sure jconfig.h got this right */
d3c770 ··MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
dd7454 #endif
12af5a
ddaf5a
4038e5 /*
7c6877 ·* Declarations for assembly-language support routines (see jmemdosa.asm).
78775e ·*
a3e3af ·* The functions are declared "far" as are all their pointer arguments;
a86133 ·* this ensures the assembly source code will work regardless of the
f486f9 ·* compiler memory model. ·We assume "short" is 16 bits, "long" is 32.
28495d ·*/
a7af5a
03cd3e typedef void far * XMSDRIVER;¤  /* actually a pointer to code */
610ef7 typedef struct {¤   ¤   /* registers for calling XMS driver */
82d397 ¤   unsigned short ax, dx, bx;
87bb68 ¤   void far * ds_si;
55b284 ······} XMScontext;
31ba10 typedef struct {¤   ¤   /* registers for calling EMS driver */
8cd397 ¤   unsigned short ax, dx, bx;
95bb68 ¤   void far * ds_si;
6c2d93 ······} EMScontext;
a6af5a
fc5679 extern short far jdos_open JPP((short far * handle, char far * filename));
910875 extern short far jdos_close JPP((short handle));
92b9bb extern short far jdos_seek JPP((short handle, long offset));
81ae5e extern short far jdos_read JPP((short handle, void far * buffer,
4ff4f5 ¤   ¤   ¤   ¤   unsigned short count));
7af4c4 extern short far jdos_write JPP((short handle, void far * buffer,
69aefa ¤   ¤   ¤   ¤   ·unsigned short count));
9dc864 extern void far jxms_getdriver JPP((XMSDRIVER far *));
93545e extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
aabe10 extern short far jems_available JPP((void));
b534dd extern void far jems_calldriver JPP((EMScontext far *));
c5af5a
4caf5a
3938e5 /*
50d96d ·* Selection of a file name for a temporary file.
c6b5bc ·* This is highly system-dependent, and you may want to customize it.
48495d ·*/
89af5a
b25b96 static int next_file_num;¤  /* to distinguish among several temp files */
ecaf5a
0cafad LOCAL(void)
924eb7 select_file_name (char * fname)
adbb36 {
f01294 ··const char * env;
493448 ··char * ptr;
4b1367 ··FILE * tfile;
74af5a
cafee8 ··/* Keep generating file names till we find one that's not in use */
786015 ··for (;;) {
c91666 ····/* Get temp directory name from environment TMP or TEMP variable;
382bf9 ·····* if none, use "."
67d48d ·····*/
e572be ····if ((env = (const char *) getenv("TMP")) == NULL)
bc72f4 ······if ((env = (const char *) getenv("TEMP")) == NULL)
bca45b ¤   env = ".";
5b53b8 ····if (*env == '\0')¤  ¤   /* null string means "." */
571127 ······env = ".";
965848 ····ptr = fname;¤   ¤   /* copy name to fname */
28b2e9 ····while (*env != '\0')
94f3d9 ······*ptr++ = *env++;
5cb426 ····if (ptr[-1] != '\\' && ptr[-1] != '/')
4b21db ······*ptr++ = '\\';¤   ¤   /* append backslash if not in env variable */
--e0c1 000c30f82d94010003a Page 3 of jmemdos.c
ab0a6f ····/* Append a suitable file name */
6531fc ····next_file_num++;¤   ¤   /* advance counter */
2d5a42 ····sprintf(ptr, "JPG%03d.TMP", next_file_num);
77b70c ····/* Probe to see if file name is already in use */
3abffe ····if ((tfile = fopen(fname, READ_BINARY)) == NULL)
8888e1 ······break;
e29391 ····fclose(tfile);¤ ¤   /* oops, it's there; close tfile & try again */
05df1c ··}
94efe6 }
dfaf5a
91af5a
f038e5 /*
855351 ·* Near-memory allocation and freeing are controlled by the regular library
d6f3bc ·* routines malloc() and free().
e6495d ·*/
36af5a
5b0d73 GLOBAL(void *)
dddd1d jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
a7bb36 {
50b34f ··return (void *) malloc(sizeofobject);
8defe6 }
caaf5a
46f898 GLOBAL(void)
34689f jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
a6bb36 {
a259e9 ··free(object);
fdefe6 }
29af5a
4faf5a
d738e5 /*
282cee ·* "Large" objects are allocated in far memory, if possible
46495d ·*/
19af5a
2bb820 GLOBAL(void FAR *)
9cfa94 jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
59bb36 {
44881b ··return (void FAR *) far_malloc(sizeofobject);
25efe6 }
91af5a
17f898 GLOBAL(void)
9f4b37 jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
72bb36 {
92018f ··far_free(object);
8befe6 }
d7af5a
1aaf5a
4038e5 /*
626605 ·* This routine computes the total memory space available for allocation.
1812fd ·* It's impossible to do this in a portable way; our current solution is
76e86d ·* to make the user tell us (with a default value set at compile time).
af20d1 ·* If you can actually get the available space, it's a good idea to subtract
42fd52 ·* a slop factor of 5% or so.
92495d ·*/
f7af5a
453176 #ifndef DEFAULT_MAX_MEM¤¤   /* so can override from makefile */
7f983d #define DEFAULT_MAX_MEM¤¤   300000L /* for total usage about 450K */
777454 #endif
3faf5a
372b63 GLOBAL(long)
ebee2d jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
c24fe9 ¤   ¤   ····long max_bytes_needed, long already_allocated)
93bb36 {
d2c5a4 ··return cinfo->mem->max_memory_to_use - already_allocated;
3cefe6 }
97af5a
44af5a
c938e5 /*
5c0fbc ·* Backing store (temporary file) management.
7016ad ·* Backing store objects are only used when the value returned by
2e7c99 ·* jpeg_mem_available is less than the total space needed. ·You can dispense
129cac ·* with these routines if you have plenty of virtual memory; see jmemnobs.c.
c3495d ·*/
--b57f 000344997014010003a Page 4 of jmemdos.c
e0af5a
d338e5 /*
4ed9e6 ·* For MS-DOS we support three types of backing storage:
b84814 ·* ··1. Conventional DOS files. ·We access these by direct DOS calls rather
ffcebf ·* ·····than via the stdio package. ·This provides a bit better performance,
da78d5 ·* ·····but the real reason is that the buffers to be read or written are FAR.
35f0f7 ·* ·····The stdio library for small-data memory models can't cope with that.
34381e ·* ··2. Extended memory, accessed per the XMS V2.0 specification.
f451cf ·* ··3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
7ff870 ·* You'll need copies of those specs to make sense of the related code.
9e38d0 ·* The specs are available by Internet FTP from the SIMTEL archives·
4bf00d ·* (oak.oakland.edu and its various mirror sites). ·See files
fe845d ·* pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
e0495d ·*/
5caf5a
04af5a
9738e5 /*
88b1cb ·* Access methods for a DOS file.
3c495d ·*/
3eaf5a
b7af5a
040434 METHODDEF(void)
cb5606 read_file_store (j_common_ptr cinfo, backing_store_ptr info,
f15f2b ¤   ¤   ·void FAR * buffer_address,
7ef32e ¤   ¤   ·long file_offset, long byte_count)
f5bb36 {
ddf6d2 ··if (jdos_seek(info->handle.file_handle, file_offset))
375f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
b84b86 ··/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
804ecc ··if (byte_count > 65535L)¤ /* safety check */
bf89a0 ····ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
4d9015 ··if (jdos_read(info->handle.file_handle, buffer_address,
8e60e6 ¤   ¤   (unsigned short) byte_count))
f45fb6 ····ERREXIT(cinfo, JERR_TFILE_READ);
67efe6 }
2baf5a
76af5a
090434 METHODDEF(void)
8bdfd0 write_file_store (j_common_ptr cinfo, backing_store_ptr info,
77532d ¤   ¤   ··void FAR * buffer_address,
df5f05 ¤   ¤   ··long file_offset, long byte_count)
89bb36 {
90f6d2 ··if (jdos_seek(info->handle.file_handle, file_offset))
cd5f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
394b86 ··/* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
954ecc ··if (byte_count > 65535L)¤ /* safety check */
5f89a0 ····ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
db2678 ··if (jdos_write(info->handle.file_handle, buffer_address,
4afe5a ¤   ¤   ·(unsigned short) byte_count))
cc9e97 ····ERREXIT(cinfo, JERR_TFILE_WRITE);
99efe6 }
b5af5a
36af5a
1a0434 METHODDEF(void)
a08378 close_file_store (j_common_ptr cinfo, backing_store_ptr info)
47bb36 {
e03858 ··jdos_close(info->handle.file_handle);¤/* close the file */
cfa097 ··remove(info->temp_name);¤ /* delete the file */
6c8a76 /* If your system doesn't have remove(), try unlink() instead.
90dafa ·* remove() is the ANSI-standard name for this function, but
81dca9 ·* unlink() was more common in pre-ANSI systems.
08495d ·*/
90f219 ··TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
f3efe6 }
f2af5a
ebaf5a
f3c4bf LOCAL(boolean)
0503b7 open_file_store (j_common_ptr cinfo, backing_store_ptr info,
332837 ¤   ¤   ·long total_bytes_needed)
7dbb36 {
2745a8 ··short handle;
34af5a
--2df1 0006c15f46f4010003a Page 5 of jmemdos.c
529620 ··select_file_name(info->temp_name);
b69cdc ··if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
6db4df ····/* might as well exit since jpeg_open_backing_store will fail anyway */
e616d7 ····ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
8630cb ····return FALSE;
f7df1c ··}
f9d79a ··info->handle.file_handle = handle;
bf2fd4 ··info->read_backing_store = read_file_store;
3ab559 ··info->write_backing_store = write_file_store;
cae1b0 ··info->close_backing_store = close_file_store;
510e85 ··TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
a84084 ··return TRUE;¤ ¤   ¤   /* succeeded */
02efe6 }
5daf5a
a7af5a
ad38e5 /*
8a851a ·* Access methods for extended memory.
85495d ·*/
c7af5a
6d3218 #if XMS_SUPPORTED
b1af5a
20784e static XMSDRIVER xms_driver;¤   /* saved address of XMS driver */
45af5a
4c38a6 typedef union {¤¤   ¤   /* either long offset or real-mode pointer */
39e49d ¤   long offset;
2d0ed2 ¤   void far * ptr;
ccd936 ······} XMSPTR;
9aaf5a
14b3fb typedef struct {¤   ¤   /* XMS move specification structure */
6f8107 ¤   long length;
1a57fd ¤   XMSH src_handle;
41520e ¤   XMSPTR src;
82838b ¤   XMSH dst_handle;
aec3b9 ¤   XMSPTR dst;
33ce22 ······} XMSspec;
56af5a
d694d7 #define ODD(X)¤ (((X) & 1L) != 0)
b8af5a
70af5a
250434 METHODDEF(void)
648bee read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
3839e7 ¤   ¤   void FAR * buffer_address,
619a17 ¤   ¤   long file_offset, long byte_count)
06bb36 {
e85734 ··XMScontext ctx;
1d544d ··XMSspec spec;
a5b252 ··char endbuffer[2];
e1af5a
b6b0b7 ··/* The XMS driver can't cope with an odd length, so handle the last byte
02e41d ···* specially if byte_count is odd. ·We don't expect this to be common.
c2f9a6 ···*/
7eaf5a
1dd8a3 ··spec.length = byte_count & (~ 1L);
bba435 ··spec.src_handle = info->handle.xms_handle;
02c086 ··spec.src.offset = file_offset;
9b26ef ··spec.dst_handle = 0;
5e70a7 ··spec.dst.ptr = buffer_address;
18de7b ··
b031f5 ··ctx.ds_si = (void far *) & spec;
5c9f66 ··ctx.ax = 0x0b00;¤ ¤   /* EMB move */
2886d8 ··jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
927dd9 ··if (ctx.ax != 1)
d07003 ····ERREXIT(cinfo, JERR_XMS_READ);
92af5a
2ebccc ··if (ODD(byte_count)) {
3dd7d0 ····read_xms_store(cinfo, info, (void FAR *) endbuffer,
384e5e ¤   ¤   ···file_offset + byte_count - 1L, 2L);
bbc6a7 ····((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
65df1c ··}
0defe6 }
13af5a
6caf5a
--66da 0007d2f0fa64010003a Page 6 of jmemdos.c
580434 METHODDEF(void)
033db3 write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
5b5f2b ¤   ¤   ·void FAR * buffer_address,
76f32e ¤   ¤   ·long file_offset, long byte_count)
d8bb36 {
585734 ··XMScontext ctx;
1f544d ··XMSspec spec;
c7b252 ··char endbuffer[2];
8baf5a
c4b0b7 ··/* The XMS driver can't cope with an odd length, so handle the last byte
a7e41d ···* specially if byte_count is odd. ·We don't expect this to be common.
9df9a6 ···*/
eeaf5a
bed8a3 ··spec.length = byte_count & (~ 1L);
8fdb5e ··spec.src_handle = 0;
a7a75a ··spec.src.ptr = buffer_address;
39678f ··spec.dst_handle = info->handle.xms_handle;
1d177b ··spec.dst.offset = file_offset;
eeaf5a
2831f5 ··ctx.ds_si = (void far *) & spec;
179f66 ··ctx.ax = 0x0b00;¤ ¤   /* EMB move */
b586d8 ··jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
da7dd9 ··if (ctx.ax != 1)
f97c9e ····ERREXIT(cinfo, JERR_XMS_WRITE);
48af5a
a9bccc ··if (ODD(byte_count)) {
21d7d0 ····read_xms_store(cinfo, info, (void FAR *) endbuffer,
b64e5e ¤   ¤   ···file_offset + byte_count - 1L, 2L);
b7a034 ····endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
fa8c59 ····write_xms_store(cinfo, info, (void FAR *) endbuffer,
e2629c ¤   ¤   ····file_offset + byte_count - 1L, 2L);
aedf1c ··}
36efe6 }
07af5a
24af5a
ef0434 METHODDEF(void)
8a4918 close_xms_store (j_common_ptr cinfo, backing_store_ptr info)
ffbb36 {
415734 ··XMScontext ctx;
92af5a
254c59 ··ctx.dx = info->handle.xms_handle;
45983b ··ctx.ax = 0x0a00;
3186d8 ··jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
cff960 ··TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle);
298591 ··/* we ignore any error return from the driver */
40efe6 }
c3af5a
edaf5a
45c4bf LOCAL(boolean)
5f87c9 open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
853b82 ¤   ¤   long total_bytes_needed)
57bb36 {
cd5734 ··XMScontext ctx;
97af5a
2184eb ··/* Get address of XMS driver */
2efba8 ··jxms_getdriver((XMSDRIVER far *) & xms_driver);
640c03 ··if (xms_driver == NULL)
01ca83 ····return FALSE;¤  ¤   /* no driver to be had */
72af5a
e3ba6c ··/* Get version number, must be >= 2.00 */
29e61d ··ctx.ax = 0x0000;
2f86d8 ··jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
c4949c ··if (ctx.ax < (unsigned short) 0x0200)
4b30cb ····return FALSE;
28af5a
e75984 ··/* Try to get space (expressed in kilobytes) */
636cd0 ··ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
a1b779 ··ctx.ax = 0x0900;
0686d8 ··jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
0d7dd9 ··if (ctx.ax != 1)
2830cb ····return FALSE;
7daf5a
--0aa2 000932a744e4010003a Page 7 of jmemdos.c
4cce7f ··/* Succeeded, save the handle and away we go */
c25057 ··info->handle.xms_handle = ctx.dx;
c19910 ··info->read_backing_store = read_xms_store;
eeed6e ··info->write_backing_store = write_xms_store;
d1b158 ··info->close_backing_store = close_xms_store;
bf4b20 ··TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
854084 ··return TRUE;¤ ¤   ¤   /* succeeded */
68efe6 }
c5af5a
e97b52 #endif /* XMS_SUPPORTED */
94af5a
a5af5a
4538e5 /*
915e1a ·* Access methods for expanded memory.
2c495d ·*/
eaaf5a
d986ff #if EMS_SUPPORTED
04af5a
bff554 /* The EMS move specification structure requires word and long fields aligned
ca9d3b ·* at odd byte boundaries. ·Some compilers will align struct fields at even
c36ca7 ·* byte boundaries. ·While it's usually possible to force byte alignment,
6dd910 ·* that causes an overall performance penalty and may pose problems in merging
c8f7e6 ·* JPEG into a larger application. ·Instead we accept some rather dirty code
2da279 ·* here. ·Note this code would fail if the hardware did not allow odd-byte
5fa501 ·* word & long accesses, but all 80x86 CPUs do.
74495d ·*/
e6af5a
5a6214 typedef void far * EMSPTR;
d7af5a
e694f4 typedef union {¤¤   ¤   /* EMS move specification structure */
457bca ¤   long length;¤   ¤   /* It's easy to access first 4 bytes */
f9f61b ¤   char bytes[18];¤¤   /* Misaligned fields in here! */
5e3c64 ······} EMSspec;
b6af5a
1f0be8 /* Macros for accessing misaligned fields */
15203a #define FIELD_AT(spec,offset,type) ·(*((type *) &(spec.bytes[offset])))
94fe31 #define SRC_TYPE(spec)¤ ¤   FIELD_AT(spec,4,char)
261b72 #define SRC_HANDLE(spec)¤   FIELD_AT(spec,5,EMSH)
5037d3 #define SRC_OFFSET(spec)¤   FIELD_AT(spec,7,unsigned short)
b794b7 #define SRC_PAGE(spec)¤ ¤   FIELD_AT(spec,9,unsigned short)
8ef388 #define SRC_PTR(spec)¤  ¤   FIELD_AT(spec,7,EMSPTR)
c5f7ea #define DST_TYPE(spec)¤ ¤   FIELD_AT(spec,11,char)
36e31e #define DST_HANDLE(spec)¤   FIELD_AT(spec,12,EMSH)
4c74e8 #define DST_OFFSET(spec)¤   FIELD_AT(spec,14,unsigned short)
e8613f #define DST_PAGE(spec)¤ ¤   FIELD_AT(spec,16,unsigned short)
faac00 #define DST_PTR(spec)¤  ¤   FIELD_AT(spec,14,EMSPTR)
91af5a
ac2be5 #define EMSPAGESIZE¤16384L¤ /* gospel, see the EMS specs */
66af5a
e3caf0 #define HIBYTE(W) ·(((W) >> 8) & 0xFF)
3fc20a #define LOBYTE(W) ·((W) & 0xFF)
48af5a
35af5a
4a0434 METHODDEF(void)
17b9ce read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
d739e7 ¤   ¤   void FAR * buffer_address,
359a17 ¤   ¤   long file_offset, long byte_count)
3bbb36 {
e7000a ··EMScontext ctx;
a2e0aa ··EMSspec spec;
b9af5a
c454c3 ··spec.length = byte_count;
2d8d39 ··SRC_TYPE(spec) = 1;
818e19 ··SRC_HANDLE(spec) = info->handle.ems_handle;
2dbb35 ··SRC_PAGE(spec) ··= (unsigned short) (file_offset / EMSPAGESIZE);
aa643e ··SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
d9d989 ··DST_TYPE(spec) = 0;
608667 ··DST_HANDLE(spec) = 0;
0571d6 ··DST_PTR(spec) ···= buffer_address;
43de7b ··
ff31f5 ··ctx.ds_si = (void far *) & spec;
939fc2 ··ctx.ax = 0x5700;¤ ¤   /* move memory region */
--5a27 000d6f3b3ff4010003a Page 8 of jmemdos.c
2ae67b ··jems_calldriver((EMScontext far *) & ctx);
522fa2 ··if (HIBYTE(ctx.ax) != 0)
3fb628 ····ERREXIT(cinfo, JERR_EMS_READ);
80efe6 }
a3af5a
32af5a
2a0434 METHODDEF(void)
a50f93 write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
045f2b ¤   ¤   ·void FAR * buffer_address,
72f32e ¤   ¤   ·long file_offset, long byte_count)
53bb36 {
ff000a ··EMScontext ctx;
04e0aa ··EMSspec spec;
7caf5a
bf54c3 ··spec.length = byte_count;
58d7e5 ··SRC_TYPE(spec) = 0;
82a3ec ··SRC_HANDLE(spec) = 0;
d63f78 ··SRC_PTR(spec) ···= buffer_address;
6f8355 ··DST_TYPE(spec) = 1;
0033de ··DST_HANDLE(spec) = info->handle.ems_handle;
1bf0d6 ··DST_PAGE(spec) ··= (unsigned short) (file_offset / EMSPAGESIZE);
e02fdd ··DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
3cde7b ··
1031f5 ··ctx.ds_si = (void far *) & spec;
189fc2 ··ctx.ax = 0x5700;¤ ¤   /* move memory region */
26e67b ··jems_calldriver((EMScontext far *) & ctx);
982fa2 ··if (HIBYTE(ctx.ax) != 0)
dbe389 ····ERREXIT(cinfo, JERR_EMS_WRITE);
78efe6 }
62af5a
a1af5a
3f0434 METHODDEF(void)
027b38 close_ems_store (j_common_ptr cinfo, backing_store_ptr info)
e5bb36 {
7b000a ··EMScontext ctx;
75af5a
29d0e5 ··ctx.ax = 0x4500;
25d34e ··ctx.dx = info->handle.ems_handle;
f3e67b ··jems_calldriver((EMScontext far *) & ctx);
1ed926 ··TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle);
148591 ··/* we ignore any error return from the driver */
1befe6 }
e7af5a
d3af5a
afc4bf LOCAL(boolean)
36b5e9 open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
e33b82 ¤   ¤   long total_bytes_needed)
b9bb36 {
d9000a ··EMScontext ctx;
e8af5a
24e3eb ··/* Is EMS driver there? */
0da962 ··if (! jems_available())
6530cb ····return FALSE;
d3af5a
26d8a2 ··/* Get status, make sure EMS is OK */
24f6b1 ··ctx.ax = 0x4000;
65e67b ··jems_calldriver((EMScontext far *) & ctx);
f22fa2 ··if (HIBYTE(ctx.ax) != 0)
7f30cb ····return FALSE;
b3af5a
086cb7 ··/* Get version, must be >= 4.0 */
cacd29 ··ctx.ax = 0x4600;
dde67b ··jems_calldriver((EMScontext far *) & ctx);
b1425d ··if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
1b30cb ····return FALSE;
9eaf5a
3361fe ··/* Try to allocate requested space */
1aeb7d ··ctx.ax = 0x4300;
9803a6 ··ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZ¶
981a95 E);
e2e67b ··jems_calldriver((EMScontext far *) & ctx);
d62fa2 ··if (HIBYTE(ctx.ax) != 0)
--274b 001864125594010003a Page 9 of jmemdos.c
f430cb ····return FALSE;
35af5a
c4ce7f ··/* Succeeded, save the handle and away we go */
fd6709 ··info->handle.ems_handle = ctx.dx;
595f3b ··info->read_backing_store = read_ems_store;
162b45 ··info->write_backing_store = write_ems_store;
227773 ··info->close_backing_store = close_ems_store;
ba436a ··TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
3a4084 ··return TRUE;¤ ¤   ¤   /* succeeded */
b4efe6 }
26af5a
3ba3f8 #endif /* EMS_SUPPORTED */
74af5a
beaf5a
3f38e5 /*
d683c1 ·* Initial opening of a backing-store object.
0c495d ·*/
26af5a
7bf898 GLOBAL(void)
5d78ae jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
45c744 ¤   ¤   ¤   ·long total_bytes_needed)
65bb36 {
f177c4 ··/* Try extended memory, then expanded memory, then regular file. */
9a3218 #if XMS_SUPPORTED
4cfaa8 ··if (open_xms_store(cinfo, info, total_bytes_needed))
f73471 ····return;
557454 #endif
0a86ff #if EMS_SUPPORTED
860d55 ··if (open_ems_store(cinfo, info, total_bytes_needed))
bc3471 ····return;
f47454 #endif
6b5795 ··if (open_file_store(cinfo, info, total_bytes_needed))
233471 ····return;
c7c071 ··ERREXITS(cinfo, JERR_TFILE_CREATE, "");
57efe6 }
a4af5a
a8af5a
ce38e5 /*
d74a87 ·* These routines take care of any system-dependent initialization and
c11720 ·* cleanup required.
99495d ·*/
abaf5a
842b63 GLOBAL(long)
e547b0 jpeg_mem_init (j_common_ptr cinfo)
6bbb36 {
fa9652 ··next_file_num = 0;¤   ¤   /* initialize temp file name generator */
02ea9c ··return DEFAULT_MAX_MEM;¤  /* default for max_memory_to_use */
baefe6 }
56af5a
88f898 GLOBAL(void)
5be7ea jpeg_mem_term (j_common_ptr cinfo)
4cbb36 {
513fe1 ··/* Microsoft C, at least in v6.00A, will not successfully reclaim freed
d12d60 ···* blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
58f9a6 ···*/
fb2721 #ifdef NEED_FHEAPMIN
51147a ··_fheapmin();
257454 #endif
86efe6 }
--1988 000cb578e0c4010003b Page 1 of jmemmac.c
bc38e5 /*
b6b980 ·* jmemmac.c
25775e ·*
674dac ·* Copyright (C) 1992-1996, Thomas G. Lane.
d3fb07 ·* This file is part of the Independent JPEG Group's software.
45a0d6 ·* For conditions of distribution and use, see the accompanying README file.
a5775e ·*
9c9537 ·* jmemmac.c provides an Apple Macintosh implementation of the system-
535a05 ·* dependent portion of the JPEG memory manager.
63775e ·*
bc6838 ·* jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr
408dba ·* instead of malloc and free. ·It accurately determines the amount of
0d5677 ·* memory available by using CompactMem. ·Notice that if left to its
0fdd34 ·* own devices, this code can chew up all available space in the
2be0ec ·* application's zone, with the exception of the rather small "slop"
e96b6a ·* factor computed in jpeg_mem_available(). ·The application can ensure
2f33fd ·* that more space is left over by reducing max_memory_to_use.
5a775e ·*
af7dbe ·* Large images are swapped to disk using temporary files created with
8394da ·* tmpfile(); that part of the module is the same as in jmemansi.c.
6ae899 ·* Metrowerks CodeWarrior's implementation of tmpfile() isn't quite what
4cf2aa ·* we want: it puts the files in the local directory and makes them
8111a9 ·* user-visible -- and only deletes them when the application quits,
77cc50 ·* which means they stick around in the event of a crash.
e09f4c ·* It would be better to create the temp files in the system's temporary
673bd1 ·* items folder. ·Perhaps someday we'll get around to doing that.
e5775e ·*
cc1f7c ·* Contributed by Sam Bushell (jsam@iagu.on.net).
5b495d ·*/
02af5a
3a2bb6 #define JPEG_INTERNALS
4036a7 #include "jinclude.h"
a66c8f #include "jpeglib.h"
a1ad99 #include "jmemsys.h"¤   ¤   /* import the system-dependent declarations */
e1af5a
37e0f2 #include <Memory.h>¤¤   /* we use the MacOS memory manager */
5baf5a
9674a4 #ifndef SEEK_SET¤   ¤   /* pre-ANSI systems may not define this; */
3bd978 #define SEEK_SET ·0¤¤   /* if not, assume 0 is correct */
667454 #endif
7eaf5a
08af5a
3438e5 /*
9e9c12 ·* Memory allocation and freeing are controlled by the MacOS library
c99a71 ·* routines NewPtr() and DisposePtr(), which allocate fixed-address
3d8649 ·* storage. ·Unfortunately, the IJG library isn't smart enough to cope
8c4416 ·* with relocatable storage.
13495d ·*/
34af5a
3f0d73 GLOBAL(void *)
3fdd1d jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
48bb36 {
61526b ··return (void *) NewPtr(sizeofobject);
f5efe6 }
2faf5a
9cf898 GLOBAL(void)
41689f jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
81bb36 {
da775f ··DisposePtr((Ptr) object);
2fefe6 }
50af5a
6eaf5a
d938e5 /*
acff4f ·* "Large" objects are treated the same as "small" ones.
70c693 ·* NB: we include FAR keywords in the routine declarations simply for
a0a80e ·* consistency with the rest of the IJG code; FAR should expand to empty
dd75df ·* on rational architectures like the Mac.
61495d ·*/
0baf5a
eeb820 GLOBAL(void FAR *)
3efa94 jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
cbbb36 {
--b83b 000f67bb08a4010003b Page 2 of jmemmac.c
2203ef ··return (void FAR *) NewPtr(sizeofobject);
b5efe6 }
46af5a
4ef898 GLOBAL(void)
d74b37 jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
b5bb36 {
56775f ··DisposePtr((Ptr) object);
48efe6 }
76af5a
3baf5a
1b38e5 /*
046605 ·* This routine computes the total memory space available for allocation.
8a495d ·*/
47af5a
a72b63 GLOBAL(long)
8cee2d jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
944fe9 ¤   ¤   ····long max_bytes_needed, long already_allocated)
4ebb36 {
5e7dd0 ··long limit = cinfo->mem->max_memory_to_use - already_allocated;
b18adf ··long slop, mem;
8baf5a
5befd3 ··/* Don't ask for more than what application has told us we may use */
b90c50 ··if (max_bytes_needed > limit && limit > 0)
85622e ····max_bytes_needed = limit;
34c95c ··/* Find whether there's a big enough free block in the heap.
c1474d ···* CompactMem tries to create a contiguous block of the requested size,
d27b2e ···* and then returns the size of the largest free block (which could be
8118ae ···* much more or much less than we asked for).
41eeac ···* We add some slop to ensure we don't use up all available memory.
b5f9a6 ···*/
2ca387 ··slop = max_bytes_needed / 16 + 32768L;
95a0d2 ··mem = CompactMem(max_bytes_needed + slop) - slop;
72a1ae ··if (mem < 0)
d2c1cb ····mem = 0;¤   ¤   ¤   /* sigh, couldn't even get the slop */
5e8454 ··/* Don't take more than the application says we can have */
84e5e3 ··if (mem > limit && limit > 0)
0670bb ····mem = limit;
88f14a ··return mem;
0aefe6 }
bbaf5a
96af5a
9938e5 /*
b20fbc ·* Backing store (temporary file) management.
b716ad ·* Backing store objects are only used when the value returned by
637c99 ·* jpeg_mem_available is less than the total space needed. ·You can dispense
259cac ·* with these routines if you have plenty of virtual memory; see jmemnobs.c.
81495d ·*/
65af5a
84af5a
c40434 METHODDEF(void)
88ce2b read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
eea8ab ¤   ¤   ····void FAR * buffer_address,
396885 ¤   ¤   ····long file_offset, long byte_count)
42bb36 {
99e814 ··if (fseek(info->temp_file, file_offset, SEEK_SET))
7d5f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
e08eae ··if (JFREAD(info->temp_file, buffer_address, byte_count)
beef53 ······!= (size_t) byte_count)
0f5fb6 ····ERREXIT(cinfo, JERR_TFILE_READ);
8fefe6 }
34af5a
1faf5a
bb0434 METHODDEF(void)
63cc29 write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
12d7d2 ¤   ¤   ·····void FAR * buffer_address,
7a4447 ¤   ¤   ·····long file_offset, long byte_count)
30bb36 {
73e814 ··if (fseek(info->temp_file, file_offset, SEEK_SET))
855f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
a00c71 ··if (JFWRITE(info->temp_file, buffer_address, byte_count)
caef53 ······!= (size_t) byte_count)
f69e97 ····ERREXIT(cinfo, JERR_TFILE_WRITE);
--7246 001772ebceb4010003b Page 3 of jmemmac.c
7aefe6 }
46af5a
8eaf5a
7c0434 METHODDEF(void)
212787 close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
e0bb36 {
ff455f ··fclose(info->temp_file);
353079 ··/* Since this implementation uses tmpfile() to create the file,
cc6945 ···* no explicit file deletion is needed.
16f9a6 ···*/
1defe6 }
51af5a
e4af5a
b638e5 /*
2783c1 ·* Initial opening of a backing-store object.
04775e ·*
482092 ·* This version uses tmpfile(), which constructs a suitable file name
25a522 ·* behind the scenes. ·We don't have to use info->temp_name[] at all;
45fd48 ·* indeed, we can't even find out the actual name of the temp file.
6a495d ·*/
5baf5a
05f898 GLOBAL(void)
4a78ae jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
55c744 ¤   ¤   ¤   ·long total_bytes_needed)
2bbb36 {
743e3c ··if ((info->temp_file = tmpfile()) == NULL)
dea91d ····ERREXITS(cinfo, JERR_TFILE_CREATE, "");
edc927 ··info->read_backing_store = read_backing_store;
b7de99 ··info->write_backing_store = write_backing_store;
a9ffb1 ··info->close_backing_store = close_backing_store;
4defe6 }
d7af5a
06af5a
c938e5 /*
3e4a87 ·* These routines take care of any system-dependent initialization and
ea1720 ·* cleanup required.
3b495d ·*/
48af5a
542b63 GLOBAL(long)
0747b0 jpeg_mem_init (j_common_ptr cinfo)
97bb36 {
5f1601 ··/* max_memory_to_use will be initialized to FreeMem()'s result;
0877f8 ···* the calling application might later reduce it, for example
05c317 ···* to leave room to invoke multiple JPEG objects.
bbf5b2 ···* Note that FreeMem returns the total number of free bytes;
6eef39 ···* it may not be possible to allocate a single block of this size.
86f9a6 ···*/
e43e56 ··return FreeMem();
f2efe6 }
d1af5a
55f898 GLOBAL(void)
dae7ea jpeg_mem_term (j_common_ptr cinfo)
a0bb36 {
556ded ··/* no work */
77efe6 }
--73d5 0000fce3fdc4010003c Page 1 of jmemmgr.c
bc38e5 /*
d15d02 ·* jmemmgr.c
22775e ·*
4fa060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
5cfb07 ·* This file is part of the Independent JPEG Group's software.
2aa0d6 ·* For conditions of distribution and use, see the accompanying README file.
84775e ·*
410493 ·* This file contains the JPEG system-independent memory management
ea9241 ·* routines. ·This code is usable across a wide variety of machines; most
26f859 ·* of the system dependencies have been isolated in a separate file.
1e9f9b ·* The major functions provided here are:
d09906 ·* ··* pool-based allocation and freeing of memory;
49718c ·* ··* policy decisions about how to divide available memory among the
9a7c77 ·* ····virtual arrays;
308d61 ·* ··* control logic for swapping virtual arrays between main memory and
1d9c89 ·* ····backing storage.
ae2718 ·* The separate system-dependent file provides the actual backing-storage
f4a038 ·* access code, and it contains the policy decision about how much total
9d4935 ·* main memory to use.
f7b038 ·* This file is system-dependent in the sense that some of its functions
f1c1c0 ·* are unnecessary in some systems. ·For example, if there is enough virtual
0955ac ·* memory so that backing storage will never be used, much of the virtual
7edf1b ·* array control logic could be removed. ·(Of course, if you have that much
a34172 ·* memory then you shouldn't care about a little bit of unused code...)
6b495d ·*/
aaaf5a
1b2bb6 #define JPEG_INTERNALS
47cc09 #define AM_MEMORY_MANAGER¤  /* we define jvirt_Xarray_control structs */
a236a7 #include "jinclude.h"
a96c8f #include "jpeglib.h"
16ad99 #include "jmemsys.h"¤   ¤   /* import the system-dependent declarations */
84af5a
69f68e #ifndef NO_GETENV
c4c272 #ifndef HAVE_STDLIB_H¤  ¤   /* <stdlib.h> should declare getenv() */
cd1683 extern char * getenv JPP((const char * name));
4c7454 #endif
d77454 #endif
1daf5a
11af5a
9b38e5 /*
21ba99 ·* Some important notes:
5fd913 ·* ··The allocation routines provided here must never return NULL.
78429f ·* ··They should exit to error_exit if unsuccessful.
ed775e ·*
a6b8bd ·* ··It's not a good idea to try to merge the sarray and barray routines,
84fd1a ·* ··even though they are textually almost the same, because samples are
aca780 ·* ··usually stored as bytes while coefficients are shorts or ints. ·Thus,
5f17da ·* ··in machines where byte pointers have a different representation from
c1caef ·* ··word pointers, the resulting machine code could not be the same.
a7495d ·*/
13af5a
16af5a
5138e5 /*
ae1bc0 ·* Many machines require storage alignment: longs must start on 4-byte
ee732b ·* boundaries, doubles on 8-byte boundaries, etc. ·On such machines, malloc()
9a552f ·* always returns pointers that are multiples of the worst-case alignment
4a40f2 ·* requirement, and we had better do so too.
17849f ·* There isn't any really portable way to determine the worst-case alignment
5336a4 ·* requirement. ·This module assumes that the alignment requirement is
ff8987 ·* multiples of sizeof(ALIGN_TYPE).
ce34c6 ·* By default, we define ALIGN_TYPE as double. ·This is necessary on some
52057b ·* workstations (where doubles really do need 8-byte alignment) and will work
7246d1 ·* fine on nearly everything. ·If your machine has lesser alignment needs,
babce6 ·* you can save a few bytes by making ALIGN_TYPE smaller.
e5147c ·* The only place I know of where this will NOT work is certain Macintosh
e6173b ·* 680x0 compilers that define double as a 10-byte IEEE extended float.
40d51b ·* Doing 10-byte alignment is counterproductive because longwords won't be
47cf0b ·* aligned well. ·Put "#define ALIGN_TYPE long" in jconfig.h if you have
b94980 ·* such a compiler.
0f495d ·*/
64af5a
0faf16 #ifndef ALIGN_TYPE¤ ¤   /* so can override from jconfig.h */
--3cdd 0006fbeefa74010003c Page 2 of jmemmgr.c
9e8923 #define ALIGN_TYPE ·double
507454 #endif
00af5a
20af5a
cd38e5 /*
7304cc ·* We allocate objects from "pools", where each pool is gotten with a single
975e77 ·* request to jpeg_get_small() or jpeg_get_large(). ·There is no per-object
de4a02 ·* overhead within a pool, except for alignment padding. ·Each pool has a
60fcfc ·* header with a link to the next pool of the same class.
890ea2 ·* Small and large pool headers are identical except that the latter's
11326f ·* link pointer must be FAR on 80x86 machines.
572a38 ·* Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE
32f4a6 ·* field. ·This forces the compiler to make SIZEOF(small_pool_hdr) a multiple
32482e ·* of the alignment requirement of ALIGN_TYPE.
24495d ·*/
caaf5a
0d0b03 typedef union small_pool_struct * small_pool_ptr;
a1af5a
0cd823 typedef union small_pool_struct {
15c412 ··struct {
71925a ····small_pool_ptr next;¤   /* next in list of pools */
3eff0c ····size_t bytes_used;¤ ¤   /* how many bytes already used within pool */
dbe3cf ····size_t bytes_left;¤ ¤   /* bytes still available in this pool */
37fd34 ··} hdr;
0f77ec ··ALIGN_TYPE dummy;¤¤   /* included in union to ensure alignment */
55e13a } small_pool_hdr;
cdaf5a
e985a8 typedef union large_pool_struct FAR * large_pool_ptr;
0aaf5a
7dfdc8 typedef union large_pool_struct {
0ec412 ··struct {
40c969 ····large_pool_ptr next;¤   /* next in list of pools */
51ff0c ····size_t bytes_used;¤ ¤   /* how many bytes already used within pool */
aee3cf ····size_t bytes_left;¤ ¤   /* bytes still available in this pool */
d7fd34 ··} hdr;
c677ec ··ALIGN_TYPE dummy;¤¤   /* included in union to ensure alignment */
272231 } large_pool_hdr;
e5af5a
9eaf5a
cc38e5 /*
18830f ·* Here is the full definition of a memory manager object.
d4495d ·*/
46af5a
65f0f7 typedef struct {
79ff30 ··struct jpeg_memory_mgr pub;¤  /* public fields */
ffaf5a
cbbaba ··/* Each pool identifier (lifetime class) names a linked list of pools. */
debe82 ··small_pool_ptr small_list[JPOOL_NUMPOOLS];
3df851 ··large_pool_ptr large_list[JPOOL_NUMPOOLS];
aeaf5a
b94de1 ··/* Since we only have one lifetime class of virtual arrays, only one
16cad4 ···* linked list is necessary (for each datatype). ·Note that the virtual
8d89f1 ···* array control blocks being linked together are actually stored somewhere
d6e3c8 ···* in the small-pool list.
1ff9a6 ···*/
eb8943 ··jvirt_sarray_ptr virt_sarray_list;
1cc4e0 ··jvirt_barray_ptr virt_barray_list;
36af5a
87bf2f ··/* This counts total space obtained from jpeg_get_small/large */
952e23 ··long total_space_allocated;
11af5a
115093 ··/* alloc_sarray and alloc_barray set this value for use by virtual
8689f0 ···* array routines.
24f9a6 ···*/
5269d3 ··JDIMENSION last_rowsperchunk;¤/* from most recent alloc_sarray/barray */
5ec380 } my_memory_mgr;
38af5a
05d17e typedef my_memory_mgr * my_mem_ptr;
eeaf5a
18af5a
dd38e5 /*
6fa03f ·* The control blocks for virtual arrays.
--ab8c 00030ba0ca24010003c Page 3 of jmemmgr.c
ef7028 ·* Note that these blocks are allocated in the "small" pool area.
85fbab ·* System-dependent info for the associated backing store (if any) is hidden
30cb76 ·* inside the backing_store_info struct.
97495d ·*/
adaf5a
6033d2 struct jvirt_sarray_control {
afcdb1 ··JSAMPARRAY mem_buffer;¤   /* => the in-memory buffer */
9442a6 ··JDIMENSION rows_in_array;¤/* total virtual array height */
f1bcc1 ··JDIMENSION samplesperrow;¤/* width of array (and of memory buffer) */
108eb7 ··JDIMENSION maxaccess;¤¤   /* max rows accessed by access_virt_sarray */
a2ac3e ··JDIMENSION rows_in_mem;¤  /* height of memory buffer */
e8e095 ··JDIMENSION rowsperchunk;¤ /* allocation chunk size in mem_buffer */
bca7e2 ··JDIMENSION cur_start_row;¤/* first logical row # in the buffer */
964bdf ··JDIMENSION first_undef_row;¤  /* row # of first uninitialized row */
bc6bbd ··boolean pre_zero;¤¤   /* pre-zero mode requested? */
f4e9f3 ··boolean dirty;¤   ¤   /* do current buffer contents need written? */
38fd7c ··boolean b_s_open;¤¤   /* is backing-store data valid? */
b6f593 ··jvirt_sarray_ptr next;¤   /* link to next virtual sarray control block */
263c28 ··backing_store_info b_s_info;¤ /* System-dependent control info */
bc82f7 };
f3af5a
c22b3c struct jvirt_barray_control {
da28e6 ··JBLOCKARRAY mem_buffer;¤  /* => the in-memory buffer */
e842a6 ··JDIMENSION rows_in_array;¤/* total virtual array height */
7d9fd5 ··JDIMENSION blocksperrow;¤ /* width of array (and of memory buffer) */
5670c2 ··JDIMENSION maxaccess;¤¤   /* max rows accessed by access_virt_barray */
bbac3e ··JDIMENSION rows_in_mem;¤  /* height of memory buffer */
33e095 ··JDIMENSION rowsperchunk;¤ /* allocation chunk size in mem_buffer */
89a7e2 ··JDIMENSION cur_start_row;¤/* first logical row # in the buffer */
134bdf ··JDIMENSION first_undef_row;¤  /* row # of first uninitialized row */
cd6bbd ··boolean pre_zero;¤¤   /* pre-zero mode requested? */
0ce9f3 ··boolean dirty;¤   ¤   /* do current buffer contents need written? */
65fd7c ··boolean b_s_open;¤¤   /* is backing-store data valid? */
cb933c ··jvirt_barray_ptr next;¤   /* link to next virtual barray control block */
233c28 ··backing_store_info b_s_info;¤ /* System-dependent control info */
ff82f7 };
afaf5a
e6af5a
f0ca8b #ifdef MEM_STATS¤   ¤   /* optional extra stuff for statistics */
a2af5a
1fafad LOCAL(void)
86f260 print_mem_stats (j_common_ptr cinfo, int pool_id)
82bb36 {
527003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
757834 ··small_pool_ptr shdr_ptr;
b68ab4 ··large_pool_ptr lhdr_ptr;
07af5a
7a5d35 ··/* Since this is only a debugging stub, we can cheat a little by using
519d30 ···* fprintf directly rather than going through the trace message code.
7f1877 ···* This is helpful because message parm array can't handle longs.
84f9a6 ···*/
3989f4 ··fprintf(stderr, "Freeing pool %d, total space = %ld\n",
a43de9 ¤   ··pool_id, mem->total_space_allocated);
c0af5a
26c497 ··for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
143ea5 ·······lhdr_ptr = lhdr_ptr->hdr.next) {
f6d8b1 ····fprintf(stderr, " ·Large chunk used %ld\n",
b5d9d3 ¤   ····(long) lhdr_ptr->hdr.bytes_used);
d3df1c ··}
3daf5a
508a06 ··for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
e223b4 ·······shdr_ptr = shdr_ptr->hdr.next) {
47368f ····fprintf(stderr, " ·Small chunk used %ld free %ld\n",
4ae52f ¤   ····(long) shdr_ptr->hdr.bytes_used,
44905a ¤   ····(long) shdr_ptr->hdr.bytes_left);
4edf1c ··}
f7efe6 }
20af5a
c7dbe5 #endif /* MEM_STATS */
9faf5a
4daf5a
30afad LOCAL(void)
--10c8 0004b65c5614010003c Page 4 of jmemmgr.c
d88a6b out_of_memory (j_common_ptr cinfo, int which)
2219a6 /* Report an out-of-memory error and stop execution */
1a1056 /* If we compiled MEM_STATS support, report alloc requests before dying */
ddbb36 {
172934 #ifdef MEM_STATS
8d28ee ··cinfo->err->trace_level = 2;¤ /* force self_destruct to report stats */
167454 #endif
c2a68d ··ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
1fefe6 }
9baf5a
f9af5a
2538e5 /*
dd4dee ·* Allocation of "small" objects.
95775e ·*
a529c4 ·* For these, we use pooled storage. ·When a new pool must be created,
ac251b ·* we try to get enough space for the current request plus a "slop" factor,
19e688 ·* where the slop will be the amount of leftover space in the new pool.
205b0d ·* The speed vs. space tradeoff is largely determined by the slop values.
ae59d3 ·* A different slop value is provided for each pool class (lifetime),
0430fb ·* and we also distinguish the first pool of a class from later ones.
69ea00 ·* NOTE: the values given work fairly well on both 16- and 32-bit-int
510ec0 ·* machines, but may be too small if longs are 64 bits or more.
6e495d ·*/
80af5a
6c7bb7 static const size_t first_pool_slop[JPOOL_NUMPOOLS] =·
14bb36 {
65aeb2 ¤   1600,¤  ¤   ¤   /* first PERMANENT pool */
f07fba ¤   16000¤  ¤   ¤   /* first IMAGE pool */
7182f7 };
07af5a
d60cc6 static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =·
e1bb36 {
8f97ba ¤   0,¤ ¤   ¤   /* additional PERMANENT pools */
907df4 ¤   5000¤   ¤   ¤   /* additional IMAGE pools */
a682f7 };
91af5a
f859f0 #define MIN_SLOP ·50¤   ¤   /* greater than 0 to avoid futile looping */
faaf5a
80af5a
2636cf METHODDEF(void *)
f2e92c alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
6f3256 /* Allocate a "small" object */
61bb36 {
927003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
e3636e ··small_pool_ptr hdr_ptr, prev_hdr_ptr;
046dfb ··char * data_ptr;
d245bd ··size_t odd_bytes, min_request, slop;
bcaf5a
66ec30 ··/* Check for unsatisfiable request (do now to ensure no overflow below) */
20b0fd ··if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
b06218 ····out_of_memory(cinfo, 1);¤   /* request exceeds malloc's ability */
91af5a
dc84b4 ··/* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
10b39e ··odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
22f9b8 ··if (odd_bytes > 0)
a96eb4 ····sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
1daf5a
8c75f0 ··/* See if space is available in any existing pool */
30b1c1 ··if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
101496 ····ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);¤/* safety check */
16630d ··prev_hdr_ptr = NULL;
67de50 ··hdr_ptr = mem->small_list[pool_id];
ddd7b1 ··while (hdr_ptr != NULL) {
ac0e16 ····if (hdr_ptr->hdr.bytes_left >= sizeofobject)
6a6e34 ······break;¤   ¤   ¤   /* found pool with enough space */
7d370b ····prev_hdr_ptr = hdr_ptr;
e93ebf ····hdr_ptr = hdr_ptr->hdr.next;
88df1c ··}
6faf5a
1daa79 ··/* Time to make a new pool? */
41118e ··if (hdr_ptr == NULL) {
4bd6ff ····/* min_request is what we need now, slop is what will be leftover */
--5b92 0007ad707ac4010003c Page 5 of jmemmgr.c
a7c276 ····min_request = sizeofobject + SIZEOF(small_pool_hdr);
791914 ····if (prev_hdr_ptr == NULL)¤  /* first pool in class? */
10eae3 ······slop = first_pool_slop[pool_id];
31842c ····else
cd75f8 ······slop = extra_pool_slop[pool_id];
c27d49 ····/* Don't ask for more than MAX_ALLOC_CHUNK */
31f56f ····if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
caaaf4 ······slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
9a9b3d ····/* Try to get space, if fail reduce slop and try again */
2dc5ab ····for (;;) {
6a0e8a ······hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
5ff82f ······if (hdr_ptr != NULL)
674ed2 ¤   break;
bd6d15 ······slop /= 2;
67b87c ······if (slop < MIN_SLOP)¤ /* give up when it gets real small */
a0ef52 ¤   out_of_memory(cinfo, 2); /* jpeg_get_small failed */
386fe7 ····}
57afcc ····mem->total_space_allocated += min_request + slop;
2c5869 ····/* Success, initialize the new pool header and add to end of list */
af870b ····hdr_ptr->hdr.next = NULL;
8fa663 ····hdr_ptr->hdr.bytes_used = 0;
bbd051 ····hdr_ptr->hdr.bytes_left = sizeofobject + slop;
e81914 ····if (prev_hdr_ptr == NULL)¤  /* first pool in class? */
6c4b3c ······mem->small_list[pool_id] = hdr_ptr;
cc842c ····else
bf3b5d ······prev_hdr_ptr->hdr.next = hdr_ptr;
0ddf1c ··}
deaf5a
670ed3 ··/* OK, allocate the object from the current pool */
1fcbd6 ··data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */
411f64 ··data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */
49e49e ··hdr_ptr->hdr.bytes_used += sizeofobject;
61425f ··hdr_ptr->hdr.bytes_left -= sizeofobject;
57af5a
6daf44 ··return (void *) data_ptr;
b1efe6 }
d7af5a
5baf5a
5b38e5 /*
5b8ee5 ·* Allocation of "large" objects.
ed775e ·*
e8c429 ·* The external semantics of these are the same as "small" objects,
ba36db ·* except that FAR pointers are used on 80x86. ·However the pool
c0463c ·* management heuristics are quite different. ·We assume that each
70a614 ·* request is large enough that it may as well be passed directly to
416603 ·* jpeg_get_large; the pool management just links everything together
11ca9a ·* so that we can free it all on demand.
8ee403 ·* Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
2e27d3 ·* structures. ·The routines that create these structures (see below)
e45636 ·* deliberately bunch rows together to ensure a large request size.
df495d ·*/
cdaf5a
9be180 METHODDEF(void FAR *)
cfae63 alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
6b8c46 /* Allocate a "large" object */
52bb36 {
ed7003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
e18a74 ··large_pool_ptr hdr_ptr;
a145ca ··size_t odd_bytes;
28af5a
36ec30 ··/* Check for unsatisfiable request (do now to ensure no overflow below) */
40a0c2 ··if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
fe74c5 ····out_of_memory(cinfo, 3);¤   /* request exceeds malloc's ability */
b9af5a
0284b4 ··/* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
03b39e ··odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
ecf9b8 ··if (odd_bytes > 0)
e96eb4 ····sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
6daf5a
ae2bc7 ··/* Always make a new pool */
81b1c1 ··if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
7a1496 ····ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);¤/* safety check */
--9720 000a2ef24e04010003c Page 6 of jmemmgr.c
e0af5a
fa8a16 ··hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
c64cbc ¤   ¤   ¤   ¤   ¤   ····SIZEOF(large_pool_hdr));
ffbd54 ··if (hdr_ptr == NULL)
5687a0 ····out_of_memory(cinfo, 4);¤   /* jpeg_get_large failed */
b31e46 ··mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
f7af5a
ca925f ··/* Success, initialize the new pool header and add to list */
7bb024 ··hdr_ptr->hdr.next = mem->large_list[pool_id];
249d7a ··/* We maintain space counts in each pool header for statistical purposes,
361b19 ···* even though they are not needed for allocation.
f8f9a6 ···*/
157e4a ··hdr_ptr->hdr.bytes_used = sizeofobject;
9431e4 ··hdr_ptr->hdr.bytes_left = 0;
c98416 ··mem->large_list[pool_id] = hdr_ptr;
4daf5a
aa67af ··return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */
80efe6 }
4aaf5a
49af5a
f538e5 /*
04df37 ·* Creation of 2-D sample arrays.
1e0fae ·* The pointers are in near heap, the samples themselves in FAR heap.
bd775e ·*
18a731 ·* To minimize allocation overhead and to allow I/O of large contiguous
8f5e4d ·* blocks, we allocate the sample rows in groups of as many rows as possible
44bd39 ·* without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
eb8bab ·* NB: the virtual array control routines, later in this file, know about
d01b4e ·* this chunking of rows. ·The rowsperchunk value is left in the mem manager
20a1e0 ·* object so that it can be saved away if this sarray is the workspace for
e7c6e0 ·* a virtual array.
2a495d ·*/
b5af5a
ea4a9f METHODDEF(JSAMPARRAY)
f5d35f alloc_sarray (j_common_ptr cinfo, int pool_id,
cb49f3 ¤   ······JDIMENSION samplesperrow, JDIMENSION numrows)
ad29ba /* Allocate a 2-D sample array */
d6bb36 {
8d7003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
06df2e ··JSAMPARRAY result;
f4e414 ··JSAMPROW workspace;
e8c5b7 ··JDIMENSION rowsperchunk, currow, i;
fbeee2 ··long ltemp;
6eaf5a
2dac2e ··/* Calculate max # of rows allowed in one allocation chunk */
ecc2f8 ··ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
dd128c ¤   ··((long) samplesperrow * SIZEOF(JSAMPLE));
e6f2e7 ··if (ltemp <= 0)
f67d39 ····ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
704b6f ··if (ltemp < (long) numrows)
3ac052 ····rowsperchunk = (JDIMENSION) ltemp;
861bd0 ··else
02d8e1 ····rowsperchunk = numrows;
df00e3 ··mem->last_rowsperchunk = rowsperchunk;
a5af5a
087768 ··/* Get space for row pointers (small object) */
7db6b5 ··result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
1967f6 ¤   ¤   ¤   ¤   ····(size_t) (numrows * SIZEOF(JSAMPROW)));
72af5a
5bb395 ··/* Get the rows themselves (large objects) */
bf75f9 ··currow = 0;
cb6576 ··while (currow < numrows) {
d0edba ····rowsperchunk = MIN(rowsperchunk, numrows - currow);
04a4cd ····workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
7c3241 ¤   (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
579e82 ¤   ¤   ··* SIZEOF(JSAMPLE)));
fdc0a2 ····for (i = rowsperchunk; i > 0; i--) {
8378c4 ······result[currow++] = workspace;
95a356 ······workspace += samplesperrow;
896fe7 ····}
88df1c ··}
a2af5a
--c995 000cbdb145e4010003c Page 7 of jmemmgr.c
0ded09 ··return result;
0eefe6 }
98af5a
6baf5a
b638e5 /*
8008b1 ·* Creation of 2-D coefficient-block arrays.
2ef261 ·* This is essentially the same as the code for sample arrays, above.
bd495d ·*/
5faf5a
b9a852 METHODDEF(JBLOCKARRAY)
4fe861 alloc_barray (j_common_ptr cinfo, int pool_id,
c46d3a ¤   ······JDIMENSION blocksperrow, JDIMENSION numrows)
ad081e /* Allocate a 2-D coefficient-block array */
21bb36 {
e07003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
c75e9e ··JBLOCKARRAY result;
2e511e ··JBLOCKROW workspace;
d6c5b7 ··JDIMENSION rowsperchunk, currow, i;
abeee2 ··long ltemp;
d1af5a
1aac2e ··/* Calculate max # of rows allowed in one allocation chunk */
27c2f8 ··ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
5995c0 ¤   ··((long) blocksperrow * SIZEOF(JBLOCK));
bdf2e7 ··if (ltemp <= 0)
5e7d39 ····ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
2c4b6f ··if (ltemp < (long) numrows)
dcc052 ····rowsperchunk = (JDIMENSION) ltemp;
0c1bd0 ··else
15d8e1 ····rowsperchunk = numrows;
1200e3 ··mem->last_rowsperchunk = rowsperchunk;
dbaf5a
ea7768 ··/* Get space for row pointers (small object) */
4f08ac ··result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
64718d ¤   ¤   ¤   ¤   ·····(size_t) (numrows * SIZEOF(JBLOCKROW)));
77af5a
7db395 ··/* Get the rows themselves (large objects) */
2475f9 ··currow = 0;
a06576 ··while (currow < numrows) {
12edba ····rowsperchunk = MIN(rowsperchunk, numrows - currow);
95061a ····workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
155e95 ¤   (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
85f226 ¤   ¤   ··* SIZEOF(JBLOCK)));
f4c0a2 ····for (i = rowsperchunk; i > 0; i--) {
6478c4 ······result[currow++] = workspace;
acbddd ······workspace += blocksperrow;
e76fe7 ····}
0fdf1c ··}
85af5a
14ed09 ··return result;
97efe6 }
6caf5a
9faf5a
4e38e5 /*
2cca59 ·* About virtual array management:
0c775e ·*
cc8896 ·* The above "normal" array routines are only used to allocate strip buffers
cb3343 ·* (as wide as the image, but just a few rows high). ·Full-image-sized buffers
c2c8d0 ·* are handled as "virtual" arrays. ·The array is still accessed a strip at a
121f16 ·* time, but the memory manager must save the whole array for repeated
603f33 ·* accesses. ·The intended implementation is that there is a strip buffer in
4eb784 ·* memory (as high as is possible given the desired memory limit), plus a
2196c5 ·* backing file that holds the rest of the array.
64775e ·*
0a2401 ·* The request_virt_array routines are told the total size of the image and
1c13d3 ·* the maximum number of rows that will be accessed at once. ·The in-memory
a8772e ·* buffer must be at least as large as the maxaccess value.
1c775e ·*
db12a7 ·* The request routines create control blocks but not the in-memory buffers.
8da5c8 ·* That is postponed until realize_virt_arrays is called. ·At that time the
99567d ·* total amount of space needed is known (approximately, anyway), so free
e38170 ·* memory can be divided up fairly.
cb775e ·*
--6f7d 0001518bbfe4010003c Page 8 of jmemmgr.c
e9eab7 ·* The access_virt_array routines are responsible for making a specific strip
6660a5 ·* area accessible (after reading or writing the backing file, if necessary).
d515bf ·* Note that the access routines are told whether the caller intends to modify
94acb6 ·* the accessed strip; during a read-only pass this saves having to rewrite
228354 ·* data to disk. ·The access routines are also responsible for pre-zeroing
97d00f ·* any newly accessed rows, if pre-zeroing was requested.
ad775e ·*
9db9dd ·* In current usage, the access requests are usually for nonoverlapping
b4b5db ·* strips; that is, successive access start_row numbers differ by exactly
1a20cf ·* num_rows = maxaccess. ·This means we can get good performance with simple
bbcea7 ·* buffer dump/reload logic, by making the in-memory buffer be a multiple
8cf32d ·* of the access height; then there will never be accesses across bufferload
611602 ·* boundaries. ·The code will still work with overlapping access requests,
c308bf ·* but it doesn't handle bufferload overlaps very efficiently.
d0495d ·*/
1daf5a
6aaf5a
f872dd METHODDEF(jvirt_sarray_ptr)
db0967 request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
324372 ¤   ¤   ·····JDIMENSION samplesperrow, JDIMENSION numrows,
0897c7 ¤   ¤   ·····JDIMENSION maxaccess)
608316 /* Request a virtual 2-D sample array */
febb36 {
ab7003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
060f44 ··jvirt_sarray_ptr result;
e3af5a
2e405b ··/* Only IMAGE-lifetime virtual arrays are currently supported */
9a4912 ··if (pool_id != JPOOL_IMAGE)
fc1496 ····ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);¤/* safety check */
90af5a
73bfc7 ··/* get control block */
e4dbef ··result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
6bc3c9 ¤   ¤   ¤   ¤   ¤   ··SIZEOF(struct jvirt_sarray_control));
d2af5a
cdde34 ··result->mem_buffer = NULL;¤   /* marks array not yet realized */
4bf3ac ··result->rows_in_array = numrows;
be5a02 ··result->samplesperrow = samplesperrow;
d829e8 ··result->maxaccess = maxaccess;
226165 ··result->pre_zero = pre_zero;
eb78f2 ··result->b_s_open = FALSE;¤/* no associated backing-store object */
bbe60b ··result->next = mem->virt_sarray_list; /* add to list of virtual arrays */
17a054 ··mem->virt_sarray_list = result;
f1af5a
90ed09 ··return result;
38efe6 }
68af5a
b0af5a
9fe250 METHODDEF(jvirt_barray_ptr)
7d4e92 request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
ac9585 ¤   ¤   ·····JDIMENSION blocksperrow, JDIMENSION numrows,
b497c7 ¤   ¤   ·····JDIMENSION maxaccess)
aba554 /* Request a virtual 2-D coefficient-block array */
48bb36 {
f97003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
b9e004 ··jvirt_barray_ptr result;
9faf5a
dd405b ··/* Only IMAGE-lifetime virtual arrays are currently supported */
064912 ··if (pool_id != JPOOL_IMAGE)
271496 ····ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);¤/* safety check */
8eaf5a
25bfc7 ··/* get control block */
743675 ··result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
f2cda1 ¤   ¤   ¤   ¤   ¤   ··SIZEOF(struct jvirt_barray_control));
f0af5a
e4de34 ··result->mem_buffer = NULL;¤   /* marks array not yet realized */
75f3ac ··result->rows_in_array = numrows;
38ba21 ··result->blocksperrow = blocksperrow;
0b29e8 ··result->maxaccess = maxaccess;
d36165 ··result->pre_zero = pre_zero;
c078f2 ··result->b_s_open = FALSE;¤/* no associated backing-store object */
399b46 ··result->next = mem->virt_barray_list; /* add to list of virtual arrays */
15cc73 ··mem->virt_barray_list = result;
--1961 0003afa93714010003c Page 9 of jmemmgr.c
e0af5a
1fed09 ··return result;
59efe6 }
59af5a
fcaf5a
a30434 METHODDEF(void)
73ffa2 realize_virt_arrays (j_common_ptr cinfo)
ead84b /* Allocate the in-memory buffers for any unrealized virtual arrays */
61bb36 {
a87003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
e40c5a ··long space_per_minheight, maximum_space, avail_mem;
a52fbf ··long minheights, max_minheights;
1057cb ··jvirt_sarray_ptr sptr;
9809be ··jvirt_barray_ptr bptr;
1aaf5a
220c84 ··/* Compute the minimum space needed (maxaccess rows in each buffer)
f7a021 ···* and the maximum space needed (full image height in each buffer).
0790fb ···* These may be of use to the system-dependent jpeg_mem_available routine.
c6f9a6 ···*/
8dc637 ··space_per_minheight = 0;
2e5a84 ··maximum_space = 0;
3fc549 ··for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
aa4317 ····if (sptr->mem_buffer == NULL) { /* if not realized yet */
7cddc6 ······space_per_minheight += (long) sptr->maxaccess *
11f9b6 ¤   ¤   ¤   ·····(long) sptr->samplesperrow * SIZEOF(JSAMPLE);
26900e ······maximum_space += (long) sptr->rows_in_array *
6b88b9 ¤   ¤   ·······(long) sptr->samplesperrow * SIZEOF(JSAMPLE);
956fe7 ····}
28df1c ··}
697506 ··for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
e62f8b ····if (bptr->mem_buffer == NULL) { /* if not realized yet */
f6d3ae ······space_per_minheight += (long) bptr->maxaccess *
d68bfa ¤   ¤   ¤   ·····(long) bptr->blocksperrow * SIZEOF(JBLOCK);
3afc29 ······maximum_space += (long) bptr->rows_in_array *
2c30a6 ¤   ¤   ·······(long) bptr->blocksperrow * SIZEOF(JBLOCK);
856fe7 ····}
58df1c ··}
a2af5a
d03ca0 ··if (space_per_minheight <= 0)
4c2cc0 ····return;¤¤   ¤   /* no unrealized arrays, no work */
87af5a
0a6e95 ··/* Determine amount of memory to actually use; this is system-dependent. */
ab63d8 ··avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
7ddcc4 ¤   ¤   ¤   ¤   ·mem->total_space_allocated);
efaf5a
127ac9 ··/* If the maximum space needed is available, make all the buffers full
6e37fd ···* height; otherwise parcel it out with the same number of minheights
73a6e9 ···* in each buffer.
c9f9a6 ···*/
df8912 ··if (avail_mem >= maximum_space)
ffdcf7 ····max_minheights = 1000000000L;
f33a1e ··else {
75f278 ····max_minheights = avail_mem / space_per_minheight;
193592 ····/* If there doesn't seem to be enough space, try to get the minimum
978cdd ·····* anyway. ·This allows a "stub" implementation of jpeg_mem_available().
bdd48d ·····*/
45f349 ····if (max_minheights <= 0)
b0f7ca ······max_minheights = 1;
18df1c ··}
59af5a
de7e43 ··/* Allocate the in-memory buffers and initialize backing store as needed. */
20af5a
c7c549 ··for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
dd4317 ····if (sptr->mem_buffer == NULL) { /* if not realized yet */
06c0e1 ······minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
ae4199 ······if (minheights <= max_minheights) {
41c39c ¤   /* This buffer fits in memory */
67afce ¤   sptr->rows_in_mem = sptr->rows_in_array;
e4cfc7 ······} else {
61080f ¤   /* It doesn't fit in memory, create backing store. */
ede3da ¤   sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
3a0876 ¤   jpeg_open_backing_store(cinfo, & sptr->b_s_info,
--b860 000abe689e64010003c Page 10 of jmemmgr.c
6b589b ¤   ¤   ¤   ¤   (long) sptr->rows_in_array *
5a310f ¤   ¤   ¤   ¤   (long) sptr->samplesperrow *
63a729 ¤   ¤   ¤   ¤   (long) SIZEOF(JSAMPLE));
b1c5e8 ¤   sptr->b_s_open = TRUE;
fb42cc ······}
63c68f ······sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
320b46 ¤   ¤   ¤   ¤   ······sptr->samplesperrow, sptr->rows_in_mem);
2a1da6 ······sptr->rowsperchunk = mem->last_rowsperchunk;
966d6e ······sptr->cur_start_row = 0;
ae0d5a ······sptr->first_undef_row = 0;
03f12f ······sptr->dirty = FALSE;
f16fe7 ····}
8fdf1c ··}
fcaf5a
637506 ··for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
8e2f8b ····if (bptr->mem_buffer == NULL) { /* if not realized yet */
eb355a ······minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
e14199 ······if (minheights <= max_minheights) {
5bc39c ¤   /* This buffer fits in memory */
6bcd6f ¤   bptr->rows_in_mem = bptr->rows_in_array;
d2cfc7 ······} else {
8f080f ¤   /* It doesn't fit in memory, create backing store. */
cdf3e2 ¤   bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
8a27ee ¤   jpeg_open_backing_store(cinfo, & bptr->b_s_info,
0634bc ¤   ¤   ¤   ¤   (long) bptr->rows_in_array *
fa0b47 ¤   ¤   ¤   ¤   (long) bptr->blocksperrow *
39fa6d ¤   ¤   ¤   ¤   (long) SIZEOF(JBLOCK));
4e9039 ¤   bptr->b_s_open = TRUE;
8242cc ······}
1521a7 ······bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
3f8b03 ¤   ¤   ¤   ¤   ······bptr->blocksperrow, bptr->rows_in_mem);
10501e ······bptr->rowsperchunk = mem->last_rowsperchunk;
8a2ea5 ······bptr->cur_start_row = 0;
8753c7 ······bptr->first_undef_row = 0;
01a8b0 ······bptr->dirty = FALSE;
076fe7 ····}
46df1c ··}
deefe6 }
cbaf5a
cfaf5a
80afad LOCAL(void)
c83b90 do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
ca0331 /* Do backing store read or write of a virtual sample array */
f3bb36 {
300a65 ··long bytesperrow, file_offset, byte_count, rows, thisrow, i;
ffaf5a
8d5c5e ··bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
3e010f ··file_offset = ptr->cur_start_row * bytesperrow;
5b16b4 ··/* Loop to read or write each allocation chunk in mem_buffer */
b61630 ··for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
c0c9fa ····/* One chunk, but check for short chunk at end of buffer */
1a0c6d ····rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
fbcb94 ····/* Transfer no more than is currently defined */
a76130 ····thisrow = (long) ptr->cur_start_row + i;
78243f ····rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
6b40a5 ····/* Transfer no more than fits in file */
3c44b9 ····rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
9865ed ····if (rows <= 0)¤ ¤   /* this chunk might be past end of file! */
6288e1 ······break;
6543d3 ····byte_count = rows * bytesperrow;
baf43b ····if (writing)
55a493 ······(*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
57cd79 ¤   ¤   ¤   ¤   ¤   ····(void FAR *) ptr->mem_buffer[i],
a37857 ¤   ¤   ¤   ¤   ¤   ····file_offset, byte_count);
fd842c ····else
51fe90 ······(*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
39d45a ¤   ¤   ¤   ¤   ¤   ···(void FAR *) ptr->mem_buffer[i],
c306b0 ¤   ¤   ¤   ¤   ¤   ···file_offset, byte_count);
69d0bb ····file_offset += byte_count;
82df1c ··}
37efe6 }
abaf5a
--ac37 000ff1b467a4010003c Page 11 of jmemmgr.c
e0af5a
1fafad LOCAL(void)
b10f1c do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
7345ce /* Do backing store read or write of a virtual coefficient-block array */
d8bb36 {
af0a65 ··long bytesperrow, file_offset, byte_count, rows, thisrow, i;
2aaf5a
524a5b ··bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
47010f ··file_offset = ptr->cur_start_row * bytesperrow;
b916b4 ··/* Loop to read or write each allocation chunk in mem_buffer */
a71630 ··for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
20c9fa ····/* One chunk, but check for short chunk at end of buffer */
960c6d ····rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
a4cb94 ····/* Transfer no more than is currently defined */
c06130 ····thisrow = (long) ptr->cur_start_row + i;
40243f ····rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
7840a5 ····/* Transfer no more than fits in file */
aa44b9 ····rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
6065ed ····if (rows <= 0)¤ ¤   /* this chunk might be past end of file! */
4788e1 ······break;
3b43d3 ····byte_count = rows * bytesperrow;
3df43b ····if (writing)
aaa493 ······(*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
e0cd79 ¤   ¤   ¤   ¤   ¤   ····(void FAR *) ptr->mem_buffer[i],
457857 ¤   ¤   ¤   ¤   ¤   ····file_offset, byte_count);
2d842c ····else
98fe90 ······(*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
49d45a ¤   ¤   ¤   ¤   ¤   ···(void FAR *) ptr->mem_buffer[i],
3a06b0 ¤   ¤   ¤   ¤   ¤   ···file_offset, byte_count);
0dd0bb ····file_offset += byte_count;
86df1c ··}
45efe6 }
4baf5a
baaf5a
934a9f METHODDEF(JSAMPARRAY)
bb6027 access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
c40c4f ¤   ¤   ····JDIMENSION start_row, JDIMENSION num_rows,
af9a5d ¤   ¤   ····boolean writable)
e8a855 /* Access the part of a virtual sample array starting at start_row */
577d99 /* and extending for num_rows rows. ·writable is true if ·*/
986b28 /* caller intends to modify the accessed area. */
2cbb36 {
74c15d ··JDIMENSION end_row = start_row + num_rows;
a7cbc7 ··JDIMENSION undef_row;
63af5a
b935cc ··/* debugging check */
fdae16 ··if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
269545 ······ptr->mem_buffer == NULL)
1d89f6 ····ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
aaaf5a
e5e6a6 ··/* Make the desired part of the virtual array accessible */
7ac13f ··if (start_row < ptr->cur_start_row ||
ded6cb ······end_row > ptr->cur_start_row+ptr->rows_in_mem) {
7ec520 ····if (! ptr->b_s_open)
7e2920 ······ERREXIT(cinfo, JERR_VIRTUAL_BUG);
ca3138 ····/* Flush old buffer contents if necessary */
d5d797 ····if (ptr->dirty) {
3ded99 ······do_sarray_io(cinfo, ptr, TRUE);
5834d7 ······ptr->dirty = FALSE;
986fe7 ····}
935e4c ····/* Decide what part of virtual array to access.
5e44b4 ·····* Algorithm: if target address > current window, assume forward scan,
c9a570 ·····* load starting at target address. ·If target address < current window,
b76065 ·····* assume backward scan, load so that target area is top of window.
86af81 ·····* Note that when switching from forward write to forward read, will have
bde7c1 ·····* start_row = 0, so the limiting case applies and we load from 0 anyway.
73d48d ·····*/
64f417 ····if (start_row > ptr->cur_start_row) {
0fde91 ······ptr->cur_start_row = start_row;
236a79 ····} else {
72af63 ······/* use long arithmetic here to avoid overflow & unsigned problems */
fff9ac ······long ltemp;
--81b6 000571730744010003c Page 12 of jmemmgr.c
e0af5a
fd934d ······ltemp = (long) end_row - (long) ptr->rows_in_mem;
a112f0 ······if (ltemp < 0)
5d06ca ¤   ltemp = 0;¤ ¤   /* don't fall off front end of file */
058ce9 ······ptr->cur_start_row = (JDIMENSION) ltemp;
906fe7 ····}
fa5ca7 ····/* Read in the selected part of the array.
481760 ·····* During the initial write pass, we will do no actual read
4bbacb ·····* because the selected part is all undefined.
a6d48d ·····*/
1c39d2 ····do_sarray_io(cinfo, ptr, FALSE);
76df1c ··}
15a3a1 ··/* Ensure the accessed part of the array is defined; prezero if needed.
4b0fea ···* To improve locality of access, we only prezero the part of the array
246d77 ···* that the caller is about to access, not the entire in-memory array.
d1f9a6 ···*/
8515b2 ··if (ptr->first_undef_row < end_row) {
dfee7a ····if (ptr->first_undef_row < start_row) {
fc1660 ······if (writable)¤¤   /* writer skipped over a section of array */
2c1c87 ¤   ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
3e656a ······undef_row = start_row;¤   /* but reader is allowed to read ahead */
1a6a79 ····} else {
413728 ······undef_row = ptr->first_undef_row;
4e6fe7 ····}
731c0d ····if (writable)
2bc845 ······ptr->first_undef_row = end_row;
d84356 ····if (ptr->pre_zero) {
1e2d9a ······size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
862a4e ······undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
deb6f0 ······end_row -= ptr->cur_start_row;
9a8d37 ······while (undef_row < end_row) {
86be6c ¤   jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
2650e2 ¤   undef_row++;
7c42cc ······}
9c6a79 ····} else {
b50012 ······if (! writable)¤  ¤   /* reader looking at undefined data */
771c87 ¤   ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
c16fe7 ····}
72df1c ··}
c752bb ··/* Flag the buffer dirty if caller will write in it */
305713 ··if (writable)
cda049 ····ptr->dirty = TRUE;
68874d ··/* Return address of proper part of the buffer */
615d8a ··return ptr->mem_buffer + (start_row - ptr->cur_start_row);
6defe6 }
fcaf5a
53af5a
31a852 METHODDEF(JBLOCKARRAY)
bbd623 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
060c4f ¤   ¤   ····JDIMENSION start_row, JDIMENSION num_rows,
939a5d ¤   ¤   ····boolean writable)
fe5361 /* Access the part of a virtual block array starting at start_row */
e67d99 /* and extending for num_rows rows. ·writable is true if ·*/
446b28 /* caller intends to modify the accessed area. */
dbbb36 {
c1c15d ··JDIMENSION end_row = start_row + num_rows;
08cbc7 ··JDIMENSION undef_row;
bcaf5a
8c35cc ··/* debugging check */
d8ae16 ··if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
dd9545 ······ptr->mem_buffer == NULL)
f389f6 ····ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
18af5a
c8e6a6 ··/* Make the desired part of the virtual array accessible */
f6c13f ··if (start_row < ptr->cur_start_row ||
63d6cb ······end_row > ptr->cur_start_row+ptr->rows_in_mem) {
0dc520 ····if (! ptr->b_s_open)
ad2920 ······ERREXIT(cinfo, JERR_VIRTUAL_BUG);
553138 ····/* Flush old buffer contents if necessary */
84d797 ····if (ptr->dirty) {
7fff47 ······do_barray_io(cinfo, ptr, TRUE);
5734d7 ······ptr->dirty = FALSE;
--5768 000d7d2fdf64010003c Page 13 of jmemmgr.c
9f6fe7 ····}
225e4c ····/* Decide what part of virtual array to access.
d244b4 ·····* Algorithm: if target address > current window, assume forward scan,
0ca570 ·····* load starting at target address. ·If target address < current window,
166065 ·····* assume backward scan, load so that target area is top of window.
b5af81 ·····* Note that when switching from forward write to forward read, will have
b4e7c1 ·····* start_row = 0, so the limiting case applies and we load from 0 anyway.
7ed48d ·····*/
46f417 ····if (start_row > ptr->cur_start_row) {
29de91 ······ptr->cur_start_row = start_row;
6c6a79 ····} else {
28af63 ······/* use long arithmetic here to avoid overflow & unsigned problems */
61f9ac ······long ltemp;
93af5a
78934d ······ltemp = (long) end_row - (long) ptr->rows_in_mem;
5c12f0 ······if (ltemp < 0)
a306ca ¤   ltemp = 0;¤ ¤   /* don't fall off front end of file */
f08ce9 ······ptr->cur_start_row = (JDIMENSION) ltemp;
6a6fe7 ····}
195ca7 ····/* Read in the selected part of the array.
2a1760 ·····* During the initial write pass, we will do no actual read
2abacb ·····* because the selected part is all undefined.
3bd48d ·····*/
7f0633 ····do_barray_io(cinfo, ptr, FALSE);
8fdf1c ··}
79a3a1 ··/* Ensure the accessed part of the array is defined; prezero if needed.
f30fea ···* To improve locality of access, we only prezero the part of the array
306d77 ···* that the caller is about to access, not the entire in-memory array.
abf9a6 ···*/
2515b2 ··if (ptr->first_undef_row < end_row) {
a5ee7a ····if (ptr->first_undef_row < start_row) {
f31660 ······if (writable)¤¤   /* writer skipped over a section of array */
b01c87 ¤   ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
d8656a ······undef_row = start_row;¤   /* but reader is allowed to read ahead */
b26a79 ····} else {
3a3728 ······undef_row = ptr->first_undef_row;
616fe7 ····}
581c0d ····if (writable)
cbc845 ······ptr->first_undef_row = end_row;
744356 ····if (ptr->pre_zero) {
00951a ······size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
372a4e ······undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
bab6f0 ······end_row -= ptr->cur_start_row;
7d8d37 ······while (undef_row < end_row) {
9abe6c ¤   jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
5c50e2 ¤   undef_row++;
f542cc ······}
836a79 ····} else {
050012 ······if (! writable)¤  ¤   /* reader looking at undefined data */
fa1c87 ¤   ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
0b6fe7 ····}
52df1c ··}
0e52bb ··/* Flag the buffer dirty if caller will write in it */
875713 ··if (writable)
f0a049 ····ptr->dirty = TRUE;
98874d ··/* Return address of proper part of the buffer */
d45d8a ··return ptr->mem_buffer + (start_row - ptr->cur_start_row);
dcefe6 }
83af5a
c0af5a
5b38e5 /*
aede45 ·* Release all objects belonging to a specified pool.
19495d ·*/
e9af5a
190434 METHODDEF(void)
1fee2a free_pool (j_common_ptr cinfo, int pool_id)
80bb36 {
db7003 ··my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
f17834 ··small_pool_ptr shdr_ptr;
c18ab4 ··large_pool_ptr lhdr_ptr;
df7d7d ··size_t space_freed;
d7af5a
--a8d3 000b7a6d9cc4010003c Page 14 of jmemmgr.c
f7b1c1 ··if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
8e1496 ····ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);¤/* safety check */
2aaf5a
972934 #ifdef MEM_STATS
339ae9 ··if (cinfo->err->trace_level > 1)
4295a6 ····print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
f67454 #endif
d7af5a
02e791 ··/* If freeing IMAGE pool, close any virtual arrays first */
5b40fc ··if (pool_id == JPOOL_IMAGE) {
45b117 ····jvirt_sarray_ptr sptr;
01ef62 ····jvirt_barray_ptr bptr;
17af5a
e26bee ····for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
148c91 ······if (sptr->b_s_open) {¤/* there may be no backing store */
13c95c ¤   sptr->b_s_open = FALSE;¤/* prevent recursive close if error */
8a34c5 ¤   (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
c742cc ······}
b06fe7 ····}
294df7 ····mem->virt_sarray_list = NULL;
8edba1 ····for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
41e00d ······if (bptr->b_s_open) {¤/* there may be no backing store */
0b5a53 ¤   bptr->b_s_open = FALSE;¤/* prevent recursive close if error */
31bf24 ¤   (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
0f42cc ······}
976fe7 ····}
360f1c ····mem->virt_barray_list = NULL;
7ddf1c ··}
b0af5a
1836dc ··/* Release large objects */
814b8c ··lhdr_ptr = mem->large_list[pool_id];
5ff0f3 ··mem->large_list[pool_id] = NULL;
9caf5a
d0cf88 ··while (lhdr_ptr != NULL) {
cc215c ····large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
6bedbb ····space_freed = lhdr_ptr->hdr.bytes_used +
6db6c2 ¤   ¤   ··lhdr_ptr->hdr.bytes_left +
0b9f15 ¤   ¤   ··SIZEOF(large_pool_hdr);
3112c7 ····jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
fbe771 ····mem->total_space_allocated -= space_freed;
11a4f9 ····lhdr_ptr = next_lhdr_ptr;
12df1c ··}
91af5a
6488cc ··/* Release small objects */
152a3c ··shdr_ptr = mem->small_list[pool_id];
93dc5c ··mem->small_list[pool_id] = NULL;
bbaf5a
cb9463 ··while (shdr_ptr != NULL) {
fde59a ····small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
a9d4e5 ····space_freed = shdr_ptr->hdr.bytes_used +
ed8f9c ¤   ¤   ··shdr_ptr->hdr.bytes_left +
702105 ¤   ¤   ··SIZEOF(small_pool_hdr);
6731d0 ····jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
6ee771 ····mem->total_space_allocated -= space_freed;
5546cf ····shdr_ptr = next_shdr_ptr;
eedf1c ··}
5defe6 }
6baf5a
bcaf5a
fd38e5 /*
35f9ca ·* Close up shop entirely.
47eccd ·* Note that this cannot be called unless cinfo->mem is non-NULL.
04495d ·*/
59af5a
4e0434 METHODDEF(void)
796cc5 self_destruct (j_common_ptr cinfo)
2fbb36 {
b54484 ··int pool;
b4af5a
01bb15 ··/* Close all backing store, release all memory.
421553 ···* Releasing pools in reverse order might help avoid fragmentation
b74be7 ···* with some (brain-damaged) malloc libraries.
--78b1 00073d2c3c54010003c Page 15 of jmemmgr.c
e2f9a6 ···*/
252ae7 ··for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
083866 ····free_pool(cinfo, pool);
ffdf1c ··}
13af5a
853163 ··/* Release the memory manager control block too. */
f9741b ··jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
faa3c1 ··cinfo->mem = NULL;¤   ¤   /* ensures I will be called only once */
8baf5a
6fb399 ··jpeg_mem_term(cinfo);¤¤   /* system-dependent cleanup */
d3efe6 }
a3af5a
26af5a
c138e5 /*
d60f69 ·* Memory manager initialization.
1beffc ·* When this is called, only the error manager pointer is valid in cinfo!
3f495d ·*/
71af5a
aaf898 GLOBAL(void)
31c600 jinit_memory_mgr (j_common_ptr cinfo)
d8bb36 {
915baf ··my_mem_ptr mem;
a9beeb ··long max_to_use;
1f4484 ··int pool;
bd1e79 ··size_t test_mac;
9baf5a
031811 ··cinfo->mem = NULL;¤   ¤   /* for safety if init fails */
d8af5a
b2fe14 ··/* Check for configuration errors.
36ea87 ···* SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
6f913c ···* doesn't reflect any real hardware alignment requirement.
214455 ···* The test is a little tricky: for X>0, X and X-1 have no one-bits
129ac8 ···* in common if and only if X is a power of 2, ie has only one one-bit.
e0211d ···* Some compilers may give an "unreachable code" warning here; ignore it.
e2f9a6 ···*/
91cfe6 ··if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
fa4bbd ····ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
63f156 ··/* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
c99b0b ···* a multiple of SIZEOF(ALIGN_TYPE).
528294 ···* Again, an "unreachable code" warning may be ignored here.
84a18b ···* But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
e3f9a6 ···*/
2f563d ··test_mac = (size_t) MAX_ALLOC_CHUNK;
1dc6f9 ··if ((long) test_mac != MAX_ALLOC_CHUNK ||
6c17a4 ······(MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
2289a0 ····ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
8faf5a
22161b ··max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
a9af5a
e72904 ··/* Attempt to allocate memory manager's control block */
d64157 ··mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
34af5a
02ba1b ··if (mem == NULL) {
9649b4 ····jpeg_mem_term(cinfo);¤  /* system-dependent cleanup */
a89d9e ····ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
44df1c ··}
36af5a
f1cdaa ··/* OK, fill in the method pointers */
63c9d2 ··mem->pub.alloc_small = alloc_small;
01f864 ··mem->pub.alloc_large = alloc_large;
ef019e ··mem->pub.alloc_sarray = alloc_sarray;
b08e88 ··mem->pub.alloc_barray = alloc_barray;
e0eb3f ··mem->pub.request_virt_sarray = request_virt_sarray;
660e19 ··mem->pub.request_virt_barray = request_virt_barray;
f965b1 ··mem->pub.realize_virt_arrays = realize_virt_arrays;
9b2139 ··mem->pub.access_virt_sarray = access_virt_sarray;
9de920 ··mem->pub.access_virt_barray = access_virt_barray;
a8d29f ··mem->pub.free_pool = free_pool;
05161c ··mem->pub.self_destruct = self_destruct;
aeaf5a
a6e093 ··/* Initialize working state */
73abed ··mem->pub.max_memory_to_use = max_to_use;
--4632 001325567564010003c Page 16 of jmemmgr.c
e0af5a
d52ae7 ··for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
21a393 ····mem->small_list[pool] = NULL;
f12e9d ····mem->large_list[pool] = NULL;
81df1c ··}
359256 ··mem->virt_sarray_list = NULL;
72d0bd ··mem->virt_barray_list = NULL;
78af5a
a409fa ··mem->total_space_allocated = SIZEOF(my_memory_mgr);
65af5a
5777e5 ··/* Declare ourselves open for business */
3577a6 ··cinfo->mem = & mem->pub;
a3af5a
434757 ··/* Check for an environment variable JPEGMEM; if found, override the
35d5d4 ···* default max_memory setting from jpeg_mem_init. ·Note that the
2ccb67 ···* surrounding application may again override this value.
5cbfab ···* If your system doesn't support getenv(), define NO_GETENV to disable
8237d8 ···* this feature.
28f9a6 ···*/
88f68e #ifndef NO_GETENV
ec9bd7 ··{ char * memenv;
1eaf5a
e5ff19 ····if ((memenv = getenv("JPEGMEM")) != NULL) {
6070f2 ······char ch = 'x';
6baf5a
e436ba ······if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
f60098 ¤   if (ch == 'm' || ch == 'M')
77310f ¤   ··max_to_use *= 1000L;
a113d6 ¤   mem->pub.max_memory_to_use = max_to_use * 1000L;
6342cc ······}
3a6fe7 ····}
c2df1c ··}
0e7454 #endif
03af5a
32efe6 }
--ff33 0002bac68d94010003d Page 1 of jmemname.c
bc38e5 /*
927fdb ·* jmemname.c
0e775e ·*
7e4dac ·* Copyright (C) 1992-1996, Thomas G. Lane.
09fb07 ·* This file is part of the Independent JPEG Group's software.
73a0d6 ·* For conditions of distribution and use, see the accompanying README file.
74775e ·*
b3fa3c ·* This file provides a generic implementation of the system-dependent
3b540c ·* portion of the JPEG memory manager. ·This implementation assumes that
82ece8 ·* you must explicitly construct a name for each temp file.
6f75b4 ·* Also, the problem of determining the amount of memory available
16691f ·* is shoved onto the user.
b2495d ·*/
37af5a
9c2bb6 #define JPEG_INTERNALS
8736a7 #include "jinclude.h"
f46c8f #include "jpeglib.h"
acad99 #include "jmemsys.h"¤   ¤   /* import the system-dependent declarations */
08af5a
3d2eee #ifndef HAVE_STDLIB_H¤  ¤   /* <stdlib.h> should declare malloc(),free() */
aa14e9 extern void * malloc JPP((size_t size));
017757 extern void free JPP((void *ptr));
347454 #endif
6baf5a
0b74a4 #ifndef SEEK_SET¤   ¤   /* pre-ANSI systems may not define this; */
88d978 #define SEEK_SET ·0¤¤   /* if not, assume 0 is correct */
d27454 #endif
d3af5a
477a86 #ifdef DONT_USE_B_MODE¤ ¤   /* define mode parameters for fopen() */
bdea4e #define READ_BINARY¤"r"
4e8f39 #define RW_BINARY¤  "w+"
21db21 #else
deef4f #define READ_BINARY¤"rb"
93e812 #define RW_BINARY¤  "w+b"
bf7454 #endif
4daf5a
e4af5a
0638e5 /*
b3d96d ·* Selection of a file name for a temporary file.
38c361 ·* This is system-dependent!
8e775e ·*
331ff1 ·* The code as given is suitable for most Unix systems, and it is easily
9b35c0 ·* modified for most non-Unix systems. ·Some notes:
d9976d ·* ·1. ·The temp file is created in the directory named by TEMP_DIRECTORY.
e0d9aa ·* ·····The default value is /usr/tmp, which is the conventional place for
e0fc5d ·* ·····creating large temp files on Unix. ·On other systems you'll probably
6817c1 ·* ·····want to change the file location. ·You can do this by editing the
2d60bc ·* ·····#define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h.
c8775e ·*
9a1785 ·* ·2. ·If you need to change the file name as well as its location,
1a184d ·* ·····you can override the TEMP_FILE_NAME macro. ·(Note that this is
e7a809 ·* ·····actually a printf format string; it must contain %s and %d.)
67d160 ·* ·····Few people should need to do this.
8e775e ·*
c99247 ·* ·3. ·mktemp() is used to ensure that multiple processes running
89ea38 ·* ·····simultaneously won't select the same file names. ·If your system
5c3574 ·* ·····doesn't have mktemp(), define NO_MKTEMP to do it the hard way.
f9ee92 ·* ·····(If you don't have <errno.h>, also define NO_ERRNO_H.)
1d775e ·*
48cc7b ·* ·4. ·You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c
98d0d2 ·* ·····will cause the temp files to be removed if you stop the program early.
a4495d ·*/
49af5a
27e406 #ifndef TEMP_DIRECTORY¤ ¤   /* can override from jconfig.h or Makefile */
b92e33 #define TEMP_DIRECTORY ·"/usr/tmp/" /* recommended setting for Unix */
9a7454 #endif
30af5a
df5b96 static int next_file_num;¤  /* to distinguish among several temp files */
06af5a
7f49ef #ifdef NO_MKTEMP
7caf5a
2b4c31 #ifndef TEMP_FILE_NAME¤ ¤   /* can override from jconfig.h or Makefile */
--9266 000dcdd3e454010003d Page 2 of jmemname.c
3a1c7c #define TEMP_FILE_NAME ·"%sJPG%03d.TMP"
0d7454 #endif
d9af5a
451101 #ifndef NO_ERRNO_H
ca191f #include <errno.h>¤ ¤   /* to define ENOENT */
0a7454 #endif
89af5a
27ae6d /* ANSI C specifies that errno is a macro, but on older systems it's more
80a80b ·* likely to be a plain int variable. ·And not all versions of errno.h
2a3896 ·* bother to declare it, so we have to in order to be most portable. ·Thus:
ee495d ·*/
b8e936 #ifndef errno
38bebe extern int errno;
387454 #endif
5caf5a
84af5a
90afad LOCAL(void)
994eb7 select_file_name (char * fname)
ddbb36 {
e61367 ··FILE * tfile;
d8af5a
60fee8 ··/* Keep generating file names till we find one that's not in use */
326015 ··for (;;) {
1c31fc ····next_file_num++;¤   ¤   /* advance counter */
51aa9f ····sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
ca6013 ····if ((tfile = fopen(fname, READ_BINARY)) == NULL) {
c0e280 ······/* fopen could have failed for a reason other than the file not
bf4773 ·······* being there; for example, file there but unreadable.
5c33e5 ·······* If <errno.h> isn't available, then we cannot test the cause.
99e9f1 ·······*/
3d62fa #ifdef ENOENT
b5f5ed ······if (errno != ENOENT)
a4a8da ¤   continue;
b27454 #endif
0f88e1 ······break;
176fe7 ····}
8b9391 ····fclose(tfile);¤ ¤   /* oops, it's there; close tfile & try again */
dddf1c ··}
cbefe6 }
30af5a
c27dea #else /* ! NO_MKTEMP */
40af5a
26d9f7 /* Note that mktemp() requires the initial filename to end in six X's */
da4c31 #ifndef TEMP_FILE_NAME¤ ¤   /* can override from jconfig.h or Makefile */
f1e82c #define TEMP_FILE_NAME ·"%sJPG%dXXXXXX"
687454 #endif
7daf5a
b0afad LOCAL(void)
bf4eb7 select_file_name (char * fname)
14bb36 {
c55b60 ··next_file_num++;¤ ¤   /* advance counter */
a86f39 ··sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
1348bb ··mktemp(fname);¤   ¤   /* make sure file name is unique */
5f313f ··/* mktemp replaces the trailing XXXXXX with a unique string of characters */
bdefe6 }
c6af5a
ac1819 #endif /* NO_MKTEMP */
36af5a
3baf5a
5838e5 /*
a75c23 ·* Memory allocation and freeing are controlled by the regular library
dbf3bc ·* routines malloc() and free().
63495d ·*/
c5af5a
a40d73 GLOBAL(void *)
92dd1d jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
e1bb36 {
b1b34f ··return (void *) malloc(sizeofobject);
1befe6 }
b1af5a
b5f898 GLOBAL(void)
dc689f jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
--cbf7 000ae737a5e4010003d Page 3 of jmemname.c
2cbb36 {
9b59e9 ··free(object);
2fefe6 }
ffaf5a
7faf5a
0038e5 /*
96ff4f ·* "Large" objects are treated the same as "small" ones.
941d0b ·* NB: although we include FAR keywords in the routine declarations,
aa0d9e ·* this file won't actually work in 80x86 small/medium model; at least,
4e4054 ·* you probably won't be able to process useful-size images in only 64KB.
dc495d ·*/
03af5a
25b820 GLOBAL(void FAR *)
f2fa94 jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
6ebb36 {
1ae2cb ··return (void FAR *) malloc(sizeofobject);
bdefe6 }
3daf5a
c3f898 GLOBAL(void)
344b37 jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
00bb36 {
b859e9 ··free(object);
bcefe6 }
31af5a
e0af5a
2238e5 /*
606605 ·* This routine computes the total memory space available for allocation.
f512fd ·* It's impossible to do this in a portable way; our current solution is
6fe86d ·* to make the user tell us (with a default value set at compile time).
7620d1 ·* If you can actually get the available space, it's a good idea to subtract
6bfd52 ·* a slop factor of 5% or so.
38495d ·*/
00af5a
b33176 #ifndef DEFAULT_MAX_MEM¤¤   /* so can override from makefile */
51421a #define DEFAULT_MAX_MEM¤¤   1000000L /* default: one megabyte */
b17454 #endif
bcaf5a
1e2b63 GLOBAL(long)
78ee2d jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
6e4fe9 ¤   ¤   ····long max_bytes_needed, long already_allocated)
56bb36 {
2dc5a4 ··return cinfo->mem->max_memory_to_use - already_allocated;
78efe6 }
7baf5a
d5af5a
e738e5 /*
740fbc ·* Backing store (temporary file) management.
9c16ad ·* Backing store objects are only used when the value returned by
237c99 ·* jpeg_mem_available is less than the total space needed. ·You can dispense
e19cac ·* with these routines if you have plenty of virtual memory; see jmemnobs.c.
62495d ·*/
a8af5a
aaaf5a
830434 METHODDEF(void)
f4ce2b read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
bda8ab ¤   ¤   ····void FAR * buffer_address,
106885 ¤   ¤   ····long file_offset, long byte_count)
a2bb36 {
4ee814 ··if (fseek(info->temp_file, file_offset, SEEK_SET))
4b5f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
d48eae ··if (JFREAD(info->temp_file, buffer_address, byte_count)
80ef53 ······!= (size_t) byte_count)
0b5fb6 ····ERREXIT(cinfo, JERR_TFILE_READ);
a3efe6 }
7daf5a
eeaf5a
de0434 METHODDEF(void)
1fcc29 write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
5cd7d2 ¤   ¤   ·····void FAR * buffer_address,
774447 ¤   ¤   ·····long file_offset, long byte_count)
ddbb36 {
aee814 ··if (fseek(info->temp_file, file_offset, SEEK_SET))
--f867 0019b37566f4010003d Page 4 of jmemname.c
865f8a ····ERREXIT(cinfo, JERR_TFILE_SEEK);
d20c71 ··if (JFWRITE(info->temp_file, buffer_address, byte_count)
8cef53 ······!= (size_t) byte_count)
e79e97 ····ERREXIT(cinfo, JERR_TFILE_WRITE);
65efe6 }
0caf5a
ccaf5a
2e0434 METHODDEF(void)
fd2787 close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
bebb36 {
1752b1 ··fclose(info->temp_file);¤ /* close the file */
16273b ··unlink(info->temp_name);¤ /* delete the file */
a2c1cc /* If your system doesn't have unlink(), use remove() instead.
650974 ·* remove() is the ANSI-standard name for this function, but if
c0cee4 ·* your system was ANSI you'd be using jmemansi.c, right?
47495d ·*/
94f219 ··TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
ddefe6 }
c2af5a
54af5a
4538e5 /*
4a83c1 ·* Initial opening of a backing-store object.
6e495d ·*/
2faf5a
05f898 GLOBAL(void)
e878ae jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
02c744 ¤   ¤   ¤   ·long total_bytes_needed)
46bb36 {
e49620 ··select_file_name(info->temp_name);
bb89e0 ··if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL)
4716d7 ····ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
8bc927 ··info->read_backing_store = read_backing_store;
afde99 ··info->write_backing_store = write_backing_store;
62ffb1 ··info->close_backing_store = close_backing_store;
530e85 ··TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
c7efe6 }
3eaf5a
80af5a
a738e5 /*
a44a87 ·* These routines take care of any system-dependent initialization and
5e1720 ·* cleanup required.
82495d ·*/
1baf5a
e72b63 GLOBAL(long)
0f47b0 jpeg_mem_init (j_common_ptr cinfo)
e6bb36 {
7a9652 ··next_file_num = 0;¤   ¤   /* initialize temp file name generator */
4fea9c ··return DEFAULT_MAX_MEM;¤  /* default for max_memory_to_use */
f1efe6 }
9daf5a
3df898 GLOBAL(void)
45e7ea jpeg_mem_term (j_common_ptr cinfo)
38bb36 {
276ded ··/* no work */
9befe6 }
--a8a1 0007dff6e814010003e Page 1 of jmemnobs.c
bc38e5 /*
5fa4be ·* jmemnobs.c
1b775e ·*
194dac ·* Copyright (C) 1992-1996, Thomas G. Lane.
35fb07 ·* This file is part of the Independent JPEG Group's software.
5ea0d6 ·* For conditions of distribution and use, see the accompanying README file.
fe775e ·*
b81663 ·* This file provides a really simple implementation of the system-
356811 ·* dependent portion of the JPEG memory manager. ·This implementation
23b366 ·* assumes that no backing-store files are needed: all required space
b4a3ab ·* can be obtained from malloc().
942704 ·* This is very portable in the sense that it'll compile on almost anything,
121287 ·* but you'd better have lots of main memory (or virtual memory) if you want
d38793 ·* to process big images.
ff8b57 ·* Note that the max_memory_to_use option is ignored by this implementation.
57495d ·*/
f1af5a
702bb6 #define JPEG_INTERNALS
0536a7 #include "jinclude.h"
b36c8f #include "jpeglib.h"
28ad99 #include "jmemsys.h"¤   ¤   /* import the system-dependent declarations */
baaf5a
da2eee #ifndef HAVE_STDLIB_H¤  ¤   /* <stdlib.h> should declare malloc(),free() */
8d14e9 extern void * malloc JPP((size_t size));
257757 extern void free JPP((void *ptr));
d37454 #endif
98af5a
57af5a
1738e5 /*
9b5c23 ·* Memory allocation and freeing are controlled by the regular library
19f3bc ·* routines malloc() and free().
21495d ·*/
63af5a
790d73 GLOBAL(void *)
0bdd1d jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
0cbb36 {
eeb34f ··return (void *) malloc(sizeofobject);
1defe6 }
41af5a
0af898 GLOBAL(void)
bd689f jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
12bb36 {
e259e9 ··free(object);
b8efe6 }
dbaf5a
e8af5a
8538e5 /*
3bff4f ·* "Large" objects are treated the same as "small" ones.
851d0b ·* NB: although we include FAR keywords in the routine declarations,
d00d9e ·* this file won't actually work in 80x86 small/medium model; at least,
db4054 ·* you probably won't be able to process useful-size images in only 64KB.
bd495d ·*/
a5af5a
30b820 GLOBAL(void FAR *)
cbfa94 jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
61bb36 {
33e2cb ··return (void FAR *) malloc(sizeofobject);
fbefe6 }
2faf5a
62f898 GLOBAL(void)
864b37 jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
0bbb36 {
9b59e9 ··free(object);
daefe6 }
c1af5a
9daf5a
8d38e5 /*
c26605 ·* This routine computes the total memory space available for allocation.
c38d2e ·* Here we always say, "we got all you want bud!"
1f495d ·*/
f7af5a
7d2b63 GLOBAL(long)
--e10b 001de683e844010003e Page 2 of jmemnobs.c
48ee2d jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
934fe9 ¤   ¤   ····long max_bytes_needed, long already_allocated)
2dbb36 {
224bd2 ··return max_bytes_needed;
bdefe6 }
a6af5a
25af5a
3138e5 /*
700fbc ·* Backing store (temporary file) management.
da2119 ·* Since jpeg_mem_available always promised the moon,
38235a ·* this should never be called and we can just error out.
5b495d ·*/
87af5a
aaf898 GLOBAL(void)
7678ae jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
15c744 ¤   ¤   ¤   ·long total_bytes_needed)
b4bb36 {
36e51d ··ERREXIT(cinfo, JERR_NO_BACKING_STORE);
ebefe6 }
0eaf5a
21af5a
8038e5 /*
994a87 ·* These routines take care of any system-dependent initialization and
259468 ·* cleanup required. ·Here, there isn't any.
b6495d ·*/
5aaf5a
c92b63 GLOBAL(long)
2e47b0 jpeg_mem_init (j_common_ptr cinfo)
f8bb36 {
241d02 ··return 0;¤¤   ¤   /* just set max_memory_to_use to 0 */
60efe6 }
0faf5a
2af898 GLOBAL(void)
c3e7ea jpeg_mem_term (j_common_ptr cinfo)
50bb36 {
766ded ··/* no work */
deefe6 }
--7a8b 0006e722c344010003f Page 1 of jmemsys.h
bc38e5 /*
6c0bfb ·* jmemsys.h
fe775e ·*
564dac ·* Copyright (C) 1992-1996, Thomas G. Lane.
d7fb07 ·* This file is part of the Independent JPEG Group's software.
f8a0d6 ·* For conditions of distribution and use, see the accompanying README file.
ac775e ·*
6dc083 ·* This include file defines the interface between the system-independent
24917c ·* and system-dependent portions of the JPEG memory manager. ·No other
1575f9 ·* modules need include it. ·(The system-independent portion is jmemmgr.c;
7bdcc7 ·* there are several different versions of the system-dependent portion.)
9f775e ·*
fc947d ·* This file works as-is for the system-dependent memory managers supplied
3c6317 ·* in the IJG distribution. ·You may need to modify it if you write a
26e12c ·* custom memory manager. ·If system-dependent changes are needed in
900877 ·* this file, the best method is to #ifdef them based on a configuration
b714d3 ·* symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR.
b0495d ·*/
abaf5a
f7af5a
904b22 /* Short forms of external names for systems with brain-damaged linkers. */
d6af5a
fdddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
46349b #define jpeg_get_small¤ ¤   jGetSmall
369992 #define jpeg_free_small¤¤   jFreeSmall
d47db8 #define jpeg_get_large¤ ¤   jGetLarge
a2d0b1 #define jpeg_free_large¤¤   jFreeLarge
496713 #define jpeg_mem_available¤ jMemAvail
ecc864 #define jpeg_open_backing_store¤jOpenBackStore
7f9b3c #define jpeg_mem_init¤  ¤   jMemInit
3c0759 #define jpeg_mem_term¤  ¤   jMemTerm
f75892 #endif /* NEED_SHORT_EXTERNAL_NAMES */
fcaf5a
abaf5a
a238e5 /*
af4509 ·* These two functions are used to allocate and release small chunks of
225be5 ·* memory. ·(Typically the total amount requested through jpeg_get_small is
b5a0c6 ·* no more than 20K or so; this will be requested in chunks of a few K each.)
ac0a10 ·* Behavior should be the same as for the standard library functions malloc
ef1cc9 ·* and free; in particular, jpeg_get_small must return NULL on failure.
4e98ad ·* On most systems, these ARE malloc and free. ·jpeg_free_small is passed the
545c3a ·* size of the object being freed, just in case it's needed.
be4f66 ·* On an 80x86 machine using small-data memory model, these manage near heap.
aa495d ·*/
feaf5a
9642a3 EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
2c6287 EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object,
db9222 ¤   ¤   ¤   ¤   ··size_t sizeofobject));
f3af5a
3938e5 /*
aa8602 ·* These two functions are used to allocate and release large chunks of
ba9343 ·* memory (up to the total free space designated by jpeg_mem_available).
a709a3 ·* The interface is the same as above, except that on an 80x86 machine,
f4754b ·* far pointers are used. ·On most other machines these are identical to
2d5b3d ·* the jpeg_get/free_small routines; but we keep them separate anyway,
a8a784 ·* in case a different allocation strategy is desirable for large chunks.
4a495d ·*/
7eaf5a
befdc2 EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo,
9051fc ¤   ¤   ¤   ¤   ·······size_t sizeofobject));
7e875e EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
489222 ¤   ¤   ¤   ¤   ··size_t sizeofobject));
9caf5a
0b38e5 /*
d088ca ·* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
77cf70 ·* be requested in a single call to jpeg_get_large (and jpeg_get_small for that
a92ca1 ·* matter, but that case should never come into play). ·This macro is needed
0e45c1 ·* to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
718ebb ·* On those machines, we expect that jconfig.h will provide a proper value.
685117 ·* On machines with 32-bit flat address spaces, any large constant may be used.
67775e ·*
6ea88d ·* NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
--ce41 000fb78884c4010003f Page 2 of jmemsys.h
8386c9 ·* size_t and will be a multiple of sizeof(align_type).
e6495d ·*/
98af5a
02579c #ifndef MAX_ALLOC_CHUNK¤¤   /* may be overridden in jconfig.h */
b667cf #define MAX_ALLOC_CHUNK ·1000000000L
6c7454 #endif
54af5a
bc38e5 /*
18a508 ·* This routine computes the total space still available for allocation by
b4da70 ·* jpeg_get_large. ·If more space than this is needed, backing store will be
23b766 ·* used. ·NOTE: any memory already allocated must not be counted.
d1775e ·*
458b3d ·* There is a minimum space requirement, corresponding to the minimum
62570f ·* feasible buffer sizes; jmemmgr.c will request that much space even if
ce6ac5 ·* jpeg_mem_available returns zero. ·The maximum space needed, enough to hold
7276aa ·* all working storage in memory, is also passed in case it is useful.
d73c6c ·* Finally, the total space already allocated is passed. ·If no better
483b0e ·* method is available, cinfo->mem->max_memory_to_use - already_allocated
b91b7c ·* is often a suitable calculation.
81775e ·*
c4d6df ·* It is OK for jpeg_mem_available to underestimate the space available
c790e2 ·* (that'll just lead to more backing-store access than is really necessary).
98cb46 ·* However, an overestimate will lead to failure. ·Hence it's wise to subtract
f970c7 ·* a slop factor from the true available space. ·5% should be enough.
99775e ·*
56e2b8 ·* On machines with lots of virtual memory, any large constant may be returned.
404bba ·* Conversely, zero may be returned to always use the minimum amount of memory.
60495d ·*/
cbaf5a
5031ed EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo,
81c369 ¤   ¤   ¤   ¤   ·····long min_bytes_needed,
eadeca ¤   ¤   ¤   ¤   ·····long max_bytes_needed,
f62886 ¤   ¤   ¤   ¤   ·····long already_allocated));
f7af5a
0aaf5a
aa38e5 /*
cae503 ·* This structure holds whatever state is needed to access a single
0c98fe ·* backing-store object. ·The read/write/close method pointers are called
445b58 ·* by jmemmgr.c to manipulate the backing-store object; all other fields
4048de ·* are private to the system-dependent backing store routines.
17495d ·*/
a9af5a
7aaa0d #define TEMP_NAME_LENGTH ··64¤  /* max length of a temporary file's name */
30af5a
360127 #ifdef USE_MSDOS_MEMMGR¤¤   /* DOS-specific junk */
adaf5a
608b17 typedef unsigned short XMSH;¤   /* type of extended-memory handles */
b1bdb1 typedef unsigned short EMSH;¤   /* type of expanded-memory handles */
59af5a
76a883 typedef union {
764645 ··short file_handle;¤   ¤   /* DOS file handle if it's a temp file */
a921d4 ··XMSH xms_handle;¤ ¤   /* handle if it's a chunk of XMS */
cdc425 ··EMSH ems_handle;¤ ¤   /* handle if it's a chunk of EMS */
bab912 } handle_union;
80af5a
74c789 #endif /* USE_MSDOS_MEMMGR */
6faf5a
bacde3 typedef struct backing_store_struct * backing_store_ptr;
43af5a
7dfe0b typedef struct backing_store_struct {
d2d42e ··/* Methods for reading/writing/closing this backing-store object */
aec33d ··JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
99f381 ¤   ¤   ¤   ¤   ·····backing_store_ptr info,
da47e4 ¤   ¤   ¤   ¤   ·····void FAR * buffer_address,
42b337 ¤   ¤   ¤   ¤   ·····long file_offset, long byte_count));
a04dab ··JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
ef90c5 ¤   ¤   ¤   ¤   ······backing_store_ptr info,
726dce ¤   ¤   ¤   ¤   ······void FAR * buffer_address,
0f3dec ¤   ¤   ¤   ¤   ······long file_offset, long byte_count));
6d5880 ··JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
ac5fc3 ¤   ¤   ¤   ¤   ······backing_store_ptr info));
fbaf5a
--ffde 00127c88f854010003f Page 3 of jmemsys.h
764126 ··/* Private fields for system-dependent backing-store management */
36c2f0 #ifdef USE_MSDOS_MEMMGR
39db3a ··/* For the MS-DOS manager (jmemdos.c), we need: */
01f8ae ··handle_union handle;¤ ¤   /* reference to backing-store storage object */
3382da ··char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
25db21 #else
9957ce ··/* For a typical implementation with temp files, we need: */
7a4389 ··FILE * temp_file;¤¤   /* stdio reference to temp file */
d287f6 ··char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
ff7454 #endif
987dda } backing_store_info;
eeaf5a
1c38e5 /*
94b096 ·* Initial opening of a backing-store object. ·This must fill in the
306300 ·* read/write/close pointers in the object. ·The read/write routines
15e348 ·* may take an error exit if the specified maximum file size is exceeded.
2c7286 ·* (If jpeg_mem_available always returns a large value, this routine can
741810 ·* just take an error exit.)
bb495d ·*/
1faf5a
e1194a EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo,
589273 ¤   ¤   ¤   ¤   ¤   ··backing_store_ptr info,
c11a21 ¤   ¤   ¤   ¤   ¤   ··long total_bytes_needed));
13af5a
2caf5a
2f38e5 /*
094a87 ·* These routines take care of any system-dependent initialization and
cfc5db ·* cleanup required. ·jpeg_mem_init will be called before anything is
a76c73 ·* allocated (and, therefore, nothing in cinfo is of use except the error
5ff06d ·* manager pointer). ·It should return a suitable default value for
6a0b5a ·* max_memory_to_use; this may subsequently be overridden by the surrounding
4183ba ·* application. ·(Note that max_memory_to_use is only important if
55fb5b ·* jpeg_mem_available chooses to consult it ... no one else will.)
3962f7 ·* jpeg_mem_term may assume that all requested memory has been freed and that
2bbc35 ·* all opened backing-store objects have been closed.
5f495d ·*/
3aaf5a
cda9a7 EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
277303 EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));
--83df 0005f561e7240100040 Page 1 of jmorecfg.h
bc38e5 /*
d395c7 ·* jmorecfg.h
b2775e ·*
8da060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
42fb07 ·* This file is part of the Independent JPEG Group's software.
23a0d6 ·* For conditions of distribution and use, see the accompanying README file.
bd775e ·*
383e4d ·* This file contains additional configuration options that customize the
132792 ·* JPEG software for special applications or support machine-dependent
a07fe9 ·* optimizations. ·Most users will not need to touch this file.
6e495d ·*/
4aaf5a
45af5a
9238e5 /*
d3f65d ·* Define BITS_IN_JSAMPLE as either
868485 ·* ··8 ··for 8-bit sample values (the usual setting)
4b7f66 ·* ··12 ·for 12-bit sample values
7350cc ·* Only 8 and 12 are legal data precisions for lossy JPEG according to the
45daba ·* JPEG standard, and the IJG code does not support anything else!
7fa14c ·* We do not support run-time selection of data precision, sorry.
31495d ·*/
12af5a
c73a9c #define BITS_IN_JSAMPLE ·8¤ /* use 8 or 12 */
b8af5a
92af5a
2b38e5 /*
9d4888 ·* Maximum number of components (color channels) allowed in JPEG image.
eed42c ·* To meet the letter of the JPEG spec, set this to 255. ·However, darn
fb5e17 ·* few applications need more than 4 channels (maybe 5 for CMYK + alpha
59fdef ·* mask). ·We recommend 10 as a reasonable compromise; use 4 if you are
dbcbb8 ·* really short on memory. ·(Each allowed component costs a hundred or so
d82a23 ·* bytes of storage, whether actually used in an image or not.)
8c495d ·*/
bcaf5a
69640a #define MAX_COMPONENTS ·10¤ /* maximum number of image components */
60af5a
edaf5a
ea38e5 /*
757cc4 ·* Basic data types.
43f8c9 ·* You may need to change these if you have a machine with unusual data
d7fb6c ·* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
2634c5 ·* or "long" not 32 bits. ·We don't care whether "int" is 16 or 32 bits,
adbc40 ·* but it had better be at least 16.
24495d ·*/
02af5a
79924e /* Representation of a single sample (pixel element value).
19ddfa ·* We frequently allocate large arrays of these, so it's important to keep
d0f8af ·* them small. ·But if you have memory to burn and access to char or short
8bbbba ·* arrays is very slow on your hardware, you might want to change these.
6f495d ·*/
ccaf5a
f16f80 #if BITS_IN_JSAMPLE == 8
ba661a /* JSAMPLE should be the smallest type that will hold the values 0..255.
cd1780 ·* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
cc495d ·*/
8aaf5a
5b1190 #ifdef HAVE_UNSIGNED_CHAR
28af5a
609804 typedef unsigned char JSAMPLE;
5dd551 #define GETJSAMPLE(value) ·((int) (value))
55af5a
f5851f #else /* not HAVE_UNSIGNED_CHAR */
09af5a
4cbefe typedef char JSAMPLE;
79a57b #ifdef CHAR_IS_UNSIGNED
12d551 #define GETJSAMPLE(value) ·((int) (value))
56db21 #else
233e88 #define GETJSAMPLE(value) ·((int) (value) & 0xFF)
9eca9e #endif /* CHAR_IS_UNSIGNED */
5faf5a
5393c4 #endif /* HAVE_UNSIGNED_CHAR */
5faf5a
--48ae 0006ae15b2540100040 Page 2 of jmorecfg.h
ab98aa #define MAXJSAMPLE¤ 255
04dca2 #define CENTERJSAMPLE¤  128
dcaf5a
196c02 #endif /* BITS_IN_JSAMPLE == 8 */
b7af5a
20af5a
b1cf41 #if BITS_IN_JSAMPLE == 12
b8511d /* JSAMPLE should be the smallest type that will hold the values 0..4095.
16fffb ·* On nearly all machines "short" will do nicely.
bf495d ·*/
c3af5a
9d5320 typedef short JSAMPLE;
43d551 #define GETJSAMPLE(value) ·((int) (value))
3aaf5a
156094 #define MAXJSAMPLE¤ 4095
da2d95 #define CENTERJSAMPLE¤  2048
42af5a
57b307 #endif /* BITS_IN_JSAMPLE == 12 */
52af5a
c9af5a
cd5765 /* Representation of a DCT frequency coefficient.
e3c81a ·* This should be a signed value of at least 16 bits; "short" is usually OK.
f57f0b ·* Again, we allocate large arrays of these, but you can change to int
2181bb ·* if you have memory to burn and "short" is really slow.
fd495d ·*/
d1af5a
3893b0 typedef short JCOEF;
6baf5a
28af5a
b44c04 /* Compressed datastreams are represented as arrays of JOCTET.
89e6fb ·* These must be EXACTLY 8 bits wide, at least once they are written to
647510 ·* external storage. ·Note that when using the stdio data source/destination
bf7c7e ·* managers, this is also the data type passed to fread/fwrite.
4d495d ·*/
5caf5a
421190 #ifdef HAVE_UNSIGNED_CHAR
c5af5a
82a008 typedef unsigned char JOCTET;
d160d0 #define GETJOCTET(value) ·(value)
7aaf5a
06851f #else /* not HAVE_UNSIGNED_CHAR */
a4af5a
75605f typedef char JOCTET;
61a57b #ifdef CHAR_IS_UNSIGNED
0060d0 #define GETJOCTET(value) ·(value)
bedb21 #else
3494cf #define GETJOCTET(value) ·((value) & 0xFF)
52ca9e #endif /* CHAR_IS_UNSIGNED */
75af5a
7e93c4 #endif /* HAVE_UNSIGNED_CHAR */
54af5a
77af5a
f4432b /* These typedefs are used for various table entries and so forth.
a8c26a ·* They must be at least as wide as specified; but making them too big
92acd2 ·* won't cost a huge amount of memory, so we don't provide special
9179ed ·* extraction code like we did for JSAMPLE. ·(In other words, these
b80aef ·* typedefs live at a different point on the speed/space tradeoff curve.)
0d495d ·*/
f9af5a
9a52f4 /* UINT8 must hold at least the values 0..255. */
c7af5a
e01190 #ifdef HAVE_UNSIGNED_CHAR
1d5b7c typedef unsigned char UINT8;
ee851f #else /* not HAVE_UNSIGNED_CHAR */
3ea57b #ifdef CHAR_IS_UNSIGNED
d930da typedef char UINT8;
a1f267 #else /* not CHAR_IS_UNSIGNED */
1e521e typedef short UINT8;
6dca9e #endif /* CHAR_IS_UNSIGNED */
cc93c4 #endif /* HAVE_UNSIGNED_CHAR */
54af5a
6a6a16 /* UINT16 must hold at least the values 0..65535. */
--95d9 000f6dd196340100040 Page 3 of jmorecfg.h
e0af5a
989ed7 #ifdef HAVE_UNSIGNED_SHORT
4bd96b typedef unsigned short UINT16;
7cbe67 #else /* not HAVE_UNSIGNED_SHORT */
287262 typedef unsigned int UINT16;
88d62f #endif /* HAVE_UNSIGNED_SHORT */
a8af5a
c0e053 /* INT16 must hold at least the values -32768..32767. */
d2af5a
5b3d3a #ifndef XMD_H¤  ¤   ¤   /* X11/xmd.h correctly defines INT16 */
df55dc typedef short INT16;
e97454 #endif
1caf5a
e409ed /* INT32 must hold at least signed 32-bit values. */
7caf5a
ee187c #ifndef XMD_H¤  ¤   ¤   /* X11/xmd.h correctly defines INT32 */
3c65cd typedef long INT32;
e77454 #endif
7aaf5a
a3c709 /* Datatype used for image dimensions. ·The JPEG standard only supports
8a6795 ·* images up to 64K*64K due to 16-bit fields in SOF markers. ·Therefore
ac8129 ·* "unsigned int" is sufficient on all machines. ·However, if you need to
f65fa8 ·* handle larger images and you don't mind deviating from the spec, you
711098 ·* can change this datatype.
63495d ·*/
44af5a
6ad215 typedef unsigned int JDIMENSION;
34af5a
090229 #define JPEG_MAX_DIMENSION ·65500L ·/* a tad under 64K to prevent overflows */
92af5a
baaf5a
4de786 /* These macros are used in all function definitions and extern declarations.
936e64 ·* You could modify them if you need to change function linkage conventions;
3db343 ·* in particular, you'll need to do that to make the library a Windows DLL.
6f4ee9 ·* Another application is to make all functions global for use with debuggers
25b8f4 ·* or code profilers that require it.
26495d ·*/
7eaf5a
2dd157 /* a function called through method pointers: */
49e951 #define METHODDEF(type)¤¤   static type
7f8f9e /* a function used only in its module: */
125a0b #define LOCAL(type)¤¤   static type
ab88af /* a function referenced thru EXTERNs: */
5e7679 #define GLOBAL(type)¤   ¤   type
cfee82 /* a reference to a GLOBAL function: */
bc75ba #define EXTERN(type)¤   ¤   extern type
78af5a
a1af5a
9e1126 /* This macro is used to declare a "method", that is, a function pointer.
6f4711 ·* We want to supply prototype parameters if the compiler can cope.
ef02b5 ·* Note that the arglist parameter must be parenthesized!
cb7c8b ·* Again, you can customize this if you need special linkage keywords.
47495d ·*/
c7af5a
766cff #ifdef HAVE_PROTOTYPES
2ce319 #define JMETHOD(type,methodname,arglist) ·type (*methodname) arglist
dfdb21 #else
c88ca4 #define JMETHOD(type,methodname,arglist) ·type (*methodname) ()
b07454 #endif
7baf5a
10af5a
9b9af6 /* Here is the pseudo-keyword for declaring pointers that must be "far"
99c2bb ·* on 80x86 machines. ·Most of the specialized coding for 80x86 is handled
186a2a ·* by just saying "FAR *" where such a pointer is needed. ·In a few places
377718 ·* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
f0495d ·*/
d1af5a
507b5a #ifndef FAR // added by elrod 2/23/98 to stop warning
6316ae #ifdef NEED_FAR_POINTERS
246473 #define FAR ·far
d8db21 #else
f6e92f #define FAR
--717c 00091128d8540100040 Page 4 of jmorecfg.h
a07454 #endif
b07454 #endif
ccaf5a
2aaf5a
bc38e5 /*
27c3da ·* On a few systems, type boolean and/or its values FALSE, TRUE may appear
57d4c5 ·* in standard header files. ·Or you may have conflicts with application-
e9682c ·* specific header files that you want to include together with these files.
a34a94 ·* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
5a495d ·*/
51af5a
ea56a4 #ifndef HAVE_BOOLEAN
d02664 #ifdef WIN32
66b390 #ifndef __RPCNDR_H__¤   /* don't conflict if rpcndr.h already read */
7b7e30 typedef unsigned char boolean;
f87454 #endif
87db21 #else
04b0da typedef int boolean;
027454 #endif
297454 #endif
70af5a
440d64 #ifndef FALSE¤  ¤   ¤   /* in case these macros already exist */
c46107 #define FALSE¤  0¤  ¤   /* values of boolean */
9b7454 #endif
e164cc #ifndef TRUE
285faf #define TRUE¤   1
177454 #endif
35af5a
c6af5a
0b38e5 /*
e71121 ·* The remaining options affect code selection within the JPEG library,
4638cd ·* but they don't need to be visible to most applications using the library.
40c8c7 ·* To minimize application namespace pollution, the symbols won't be
8c5b29 ·* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
ab495d ·*/
22af5a
3a9642 #ifdef JPEG_INTERNALS
0d44c2 #define JPEG_INTERNAL_OPTIONS
ce7454 #endif
e5af5a
054b48 #ifdef JPEG_INTERNAL_OPTIONS
63af5a
c4af5a
8538e5 /*
8f31e8 ·* These defines indicate whether to include various optional functions.
23f4ec ·* Undefining some of these symbols will produce a smaller but less capable
46cbde ·* library. ·Note that you can leave certain source files out of the
36af15 ·* compilation/linking process if you've #undef'd the corresponding symbols.
354216 ·* (You may HAVE to do that if your compiler doesn't like null source files.)
58495d ·*/
62af5a
fc3b5f /* Arithmetic coding is unsupported for legal reasons. ·Complaints to IBM. */
82af5a
24ca86 /* Capability options common to encoder and decoder: */
2baf5a
d34a95 #define DCT_ISLOW_SUPPORTED¤/* slow but accurate integer algorithm */
3ca9a1 #define DCT_IFAST_SUPPORTED¤/* faster, less accurate integer method */
2d4efd #define DCT_FLOAT_SUPPORTED¤/* floating-point: accurate, fast on fast HW */
7aaf5a
03a3c7 /* Encoder capability options: */
d5af5a
75d272 #undef ·C_ARITH_CODING_SUPPORTED ···/* Arithmetic coding back end? */
570770 #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
2b1e02 #define C_PROGRESSIVE_SUPPORTED¤ ···/* Progressive JPEG? (Requires MULTISCAN)*/
89a667 #define ENTROPY_OPT_SUPPORTED¤  ····/* Optimization of entropy coding parms? */
e2f318 /* Note: if you selected 12-bit data precision, it is dangerous to turn off
3a0376 ·* ENTROPY_OPT_SUPPORTED. ·The standard Huffman tables are only good for 8-bit
325c8a ·* precision, so jchuff.c normally uses entropy optimization to compute
81d405 ·* usable tables for higher precision. ·If you don't want to do optimization,
8bfc37 ·* you'll have to supply different default Huffman tables.
6c7e7a ·* The exact same statements apply for progressive JPEG: the default tables
912960 ·* don't work for progressive mode. ·(This may get fixed, however.)
--95a7 000949e528c40100040 Page 5 of jmorecfg.h
47495d ·*/
88e23c #define INPUT_SMOOTHING_SUPPORTED ··/* Input image smoothing option? */
8faf5a
34086f /* Decoder capability options: */
76af5a
89a493 #undef ·D_ARITH_CODING_SUPPORTED ···/* Arithmetic coding back end? */
e446fc #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
0527cc #define D_PROGRESSIVE_SUPPORTED¤ ···/* Progressive JPEG? (Requires MULTISCAN)*/
5da35a #define BLOCK_SMOOTHING_SUPPORTED ··/* Block smoothing? (Progressive only) */
6726b5 #define IDCT_SCALING_SUPPORTED¤ ····/* Output rescaling via IDCT? */
f356d5 #undef ·UPSAMPLE_SCALING_SUPPORTED ·/* Output rescaling at upsample stage? */
2684c6 #define UPSAMPLE_MERGING_SUPPORTED ·/* Fast path for sloppy upsampling? */
07a17e #define QUANT_1PASS_SUPPORTED¤  ····/* 1-pass color quantization? */
5c9945 #define QUANT_2PASS_SUPPORTED¤  ····/* 2-pass color quantization? */
87af5a
64d8b8 /* more capability options later, no doubt */
a6af5a
ecaf5a
5238e5 /*
28cbdb ·* Ordering of RGB data in scanlines passed to or from the application.
f35ee3 ·* If your application wants to deal with data in the order B,G,R, just
c6445d ·* change these macros. ·You can also deal with formats such as R,G,B,X
43f60c ·* (one extra byte per pixel) by changing RGB_PIXELSIZE. ·Note that changing
0824a3 ·* the offsets will also change the order in which colormap data is organized.
231261 ·* RESTRICTIONS:
7e2e08 ·* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
16d2ea ·* 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
480af0 ·* ···useful if you are using JPEG color spaces other than YCbCr or grayscale.
ae9ede ·* 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
5ed2de ·* ···is not 3 (they don't understand about dummy color components!). ·So you
ffc1b8 ·* ···can't use color quantization if you change that value.
b3495d ·*/
e5af5a
de38a2 #define RGB_RED¤¤   0¤  /* Offset of Red in an RGB scanline element */
7e8e33 #define RGB_GREEN¤  1¤  /* Offset of Green */
81e3fb #define RGB_BLUE¤   2¤  /* Offset of Blue */
3c8b91 #define RGB_PIXELSIZE¤  3¤  /* JSAMPLEs per RGB scanline element */
56af5a
6faf5a
010bc3 /* Definitions for speed-related optimizations. */
80af5a
19af5a
c0deae /* If your compiler supports inline functions, define INLINE
700aa5 ·* as the inline keyword; otherwise define it as empty.
41495d ·*/
efaf5a
af2e69 #ifndef INLINE
ac078d #ifdef __GNUC__¤¤   ¤   /* for instance, GNU C knows about inline */
6278b6 #define INLINE __inline__
6b7454 #endif
992e69 #ifndef INLINE
801dcd #define INLINE¤ ¤   ¤   /* default is to define it as empty */
397454 #endif
ac7454 #endif
aeaf5a
daaf5a
c02ac3 /* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
ac88c7 ·* two 16-bit shorts is faster than multiplying two ints. ·Define MULTIPLIER
7e1ac4 ·* as short on such a machine. ·MULTIPLIER must be at least 16 bits wide.
7d495d ·*/
f9af5a
10f7d2 #ifndef MULTIPLIER
043638 #define MULTIPLIER ·int¤¤   /* type for fastest integer multiply */
027454 #endif
b4af5a
f0af5a
2f53cf /* FAST_FLOAT should be either float or double, whichever is done faster
c40ad1 ·* by your compiler. ·(Note that this type is only used in the floating point
19e032 ·* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
25795f ·* Typically, float is faster in ANSI C compilers, while double is faster in
688d7a ·* pre-ANSI compilers (because they insist on converting to double anyway).
94e7c2 ·* The code below therefore chooses float if we have ANSI-style prototypes.
--af04 00169888f6440100040 Page 6 of jmorecfg.h
47495d ·*/
44af5a
3975dc #ifndef FAST_FLOAT
d66cff #ifdef HAVE_PROTOTYPES
e4de0f #define FAST_FLOAT ·float
2fdb21 #else
86145a #define FAST_FLOAT ·double
527454 #endif
fc7454 #endif
88af5a
8e1cc6 #endif /* JPEG_INTERNAL_OPTIONS */
69af5a
--83ef 0000918fd1b40100041 Page 1 of jpegint.h
bc38e5 /*
78a8e9 ·* jpegint.h
f1775e ·*
4fa060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
a2fb07 ·* This file is part of the Independent JPEG Group's software.
cfa0d6 ·* For conditions of distribution and use, see the accompanying README file.
23775e ·*
b20597 ·* This file provides common declarations for the various JPEG modules.
940dc7 ·* These declarations are considered internal to the JPEG library; most
49381d ·* applications using the library shouldn't need to include this file.
d2495d ·*/
7faf5a
cdaf5a
99e355 /* Declarations for both compression & decompression */
efaf5a
26553c typedef enum {¤ ¤   ¤   /* Operating modes for buffer controllers */
23d412 ¤   JBUF_PASS_THRU,¤¤   /* Plain stripwise operation */
17e335 ¤   /* Remaining modes require a full-image buffer to have been created */
8fca2b ¤   JBUF_SAVE_SOURCE,¤  /* Run source subobject only, save output */
76c8d0 ¤   JBUF_CRANK_DEST,¤   /* Run dest subobject only, using saved data */
94adf4 ¤   JBUF_SAVE_AND_PASS¤ /* Run both subobjects, save output */
04531d } J_BUF_MODE;
d2af5a
24a93b /* Values of global_state field (jdapi.c has some dependencies on ordering!) */
99547f #define CSTATE_START¤   100¤/* after create_compress */
e21f43 #define CSTATE_SCANNING¤101¤/* start_compress done, write_scanlines OK */
222890 #define CSTATE_RAW_OK¤  102¤/* start_compress done, write_raw_data OK */
90a070 #define CSTATE_WRCOEFS¤ 103¤/* jpeg_write_coefficients done */
921e0f #define DSTATE_START¤   200¤/* after create_decompress */
7b9638 #define DSTATE_INHEADER¤201¤/* reading header markers, no SOS yet */
55288c #define DSTATE_READY¤   202¤/* found SOS, ready for start_decompress */
d369d5 #define DSTATE_PRELOAD¤ 203¤/* reading multiscan file in start_decompress*/
7cb500 #define DSTATE_PRESCAN¤ 204¤/* performing dummy pass for 2-pass quant */
15befb #define DSTATE_SCANNING¤205¤/* start_decompress done, read_scanlines OK */
f8f35e #define DSTATE_RAW_OK¤  206¤/* start_decompress done, read_raw_data OK */
f340f3 #define DSTATE_BUFIMAGE¤207¤/* expecting jpeg_start_output */
f63461 #define DSTATE_BUFPOST¤ 208¤/* looking for SOS/EOI in jpeg_finish_output */
d99840 #define DSTATE_RDCOEFS¤ 209¤/* reading file in jpeg_read_coefficients */
482a4b #define DSTATE_STOPPING¤210¤/* looking for EOI in jpeg_finish_decompress */
75af5a
3faf5a
648cc1 /* Declarations for compression modules */
2eaf5a
cef0d4 /* Master control module */
047d70 struct jpeg_comp_master {
dbf4aa ··JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
9745f7 ··JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
adea3c ··JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
cdaf5a
f157b2 ··/* State variables made visible to other modules */
f9c430 ··boolean call_pass_startup;¤   /* True if pass_startup must be called */
6f4a26 ··boolean is_last_pass;¤¤   /* True during last pass */
c482f7 };
6caf5a
21ef37 /* Main buffer control (downsampled-data buffer) */
d41d0f struct jpeg_c_main_controller {
4c5d4e ··JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
071139 ··JMETHOD(void, process_data, (j_compress_ptr cinfo,
240a66 ¤   ¤   ¤   ·······JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
178ecf ¤   ¤   ¤   ·······JDIMENSION in_rows_avail));
3a82f7 };
6baf5a
af2afd /* Compression preprocessing (downsampling input buffer control) */
941caa struct jpeg_c_prep_controller {
c15d4e ··JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
c28483 ··JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
9d81d2 ¤   ¤   ¤   ¤   ···JSAMPARRAY input_buf,
f67ed6 ¤   ¤   ¤   ¤   ···JDIMENSION *in_row_ctr,
26b392 ¤   ¤   ¤   ¤   ···JDIMENSION in_rows_avail,
c5e44d ¤   ¤   ¤   ¤   ···JSAMPIMAGE output_buf,
cf5ad4 ¤   ¤   ¤   ¤   ···JDIMENSION *out_row_group_ctr,
091bc2 ¤   ¤   ¤   ¤   ···JDIMENSION out_row_groups_avail));
--c1e9 000c5914aaa40100041 Page 2 of jpegint.h
8082f7 };
abaf5a
857802 /* Coefficient buffer control */
8829be struct jpeg_c_coef_controller {
e45d4e ··JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
34c048 ··JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
b41085 ¤   ¤   ¤   ¤   ···JSAMPIMAGE input_buf));
1d82f7 };
94af5a
d03392 /* Colorspace conversion */
9f7f5b struct jpeg_color_converter {
7c063f ··JMETHOD(void, start_pass, (j_compress_ptr cinfo));
6b7fb3 ··JMETHOD(void, color_convert, (j_compress_ptr cinfo,
93995e ¤   ¤   ¤   ¤   JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
5fa8d6 ¤   ¤   ¤   ¤   JDIMENSION output_row, int num_rows));
a982f7 };
7baf5a
b09fbc /* Downsampling */
6ded2b struct jpeg_downsampler {
a3063f ··JMETHOD(void, start_pass, (j_compress_ptr cinfo));
d283bf ··JMETHOD(void, downsample, (j_compress_ptr cinfo,
bd1b8f ¤   ¤   ¤   ·····JSAMPIMAGE input_buf, JDIMENSION in_row_index,
67767c ¤   ¤   ¤   ·····JSAMPIMAGE output_buf,
3c4e04 ¤   ¤   ¤   ·····JDIMENSION out_row_group_index));
c2af5a
a6db5a ··boolean need_context_rows;¤   /* TRUE if need rows above & below */
aa82f7 };
3daf5a
0a5c56 /* Forward DCT (also controls coefficient quantization) */
ff2c03 struct jpeg_forward_dct {
aa063f ··JMETHOD(void, start_pass, (j_compress_ptr cinfo));
41553c ··/* perhaps this should be an array??? */
e89f9c ··JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
a8085b ¤   ¤   ¤   ······jpeg_component_info * compptr,
1ce27c ¤   ¤   ¤   ······JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
965aef ¤   ¤   ¤   ······JDIMENSION start_row, JDIMENSION start_col,
c67955 ¤   ¤   ¤   ······JDIMENSION num_blocks));
b482f7 };
96af5a
db0d55 /* Entropy encoding */
f5ecd8 struct jpeg_entropy_encoder {
e7397c ··JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
934538 ··JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
65ea3c ··JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
f382f7 };
76af5a
2ebf12 /* Marker writing */
7617ae struct jpeg_marker_writer {
2188f7 ··/* write_any_marker is exported for use by applications */
a0e6f7 ··/* Probably only COM and APPn markers should be written */
5d31fc ··JMETHOD(void, write_any_marker, (j_compress_ptr cinfo, int marker,
e53ed1 ¤   ¤   ¤   ¤   ···const JOCTET *dataptr, unsigned int datalen));
47c76c ··JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
188a00 ··JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
399571 ··JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
c87215 ··JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
ba8175 ··JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
dd82f7 };
8caf5a
b0af5a
50c417 /* Declarations for decompression modules */
99af5a
cff0d4 /* Master control module */
006816 struct jpeg_decomp_master {
ef50fb ··JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
a7a4d2 ··JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
c7af5a
5457b2 ··/* State variables made visible to other modules */
401c63 ··boolean is_dummy_pass;¤   /* True during 1st pass for 2-pass quant */
6a82f7 };
b3af5a
c54a32 /* Input control module */
--d65d 00090bdb3b340100041 Page 3 of jpegint.h
807040 struct jpeg_input_controller {
d01088 ··JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
288376 ··JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
9e9b97 ··JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
f98245 ··JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
6faf5a
c357b2 ··/* State variables made visible to other modules */
41b07e ··boolean has_multiple_scans;¤  /* True if file has multiple scans */
048361 ··boolean eoi_reached;¤ ¤   /* True when EOI has been consumed */
5a82f7 };
9caf5a
2eef37 /* Main buffer control (downsampled-data buffer) */
68118f struct jpeg_d_main_controller {
43da29 ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
8ec260 ··JMETHOD(void, process_data, (j_decompress_ptr cinfo,
ae71c6 ¤   ¤   ¤   ·······JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
be8c01 ¤   ¤   ¤   ·······JDIMENSION out_rows_avail));
c782f7 };
c3af5a
1c7802 /* Coefficient buffer control */
cb253e struct jpeg_d_coef_controller {
ac9b97 ··JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
02a20c ··JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
ee5154 ··JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
b04174 ··JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
31323b ¤   ¤   ¤   ¤   ·JSAMPIMAGE output_buf));
7c42d6 ··/* Pointer to array of coefficient virtual arrays, or NULL if none */
e0d97b ··jvirt_barray_ptr *coef_arrays;
7d82f7 };
12af5a
479e14 /* Decompression postprocessing (color quantization buffer control) */
417de2 struct jpeg_d_post_controller {
50da29 ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
26b270 ··JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
d5aff3 ¤   ¤   ¤   ¤   ····JSAMPIMAGE input_buf,
1270c7 ¤   ¤   ¤   ¤   ····JDIMENSION *in_row_group_ctr,
1c57a3 ¤   ¤   ¤   ¤   ····JDIMENSION in_row_groups_avail,
0dd4e8 ¤   ¤   ¤   ¤   ····JSAMPARRAY output_buf,
64c6ab ¤   ¤   ¤   ¤   ····JDIMENSION *out_row_ctr,
a96a2b ¤   ¤   ¤   ¤   ····JDIMENSION out_rows_avail));
3482f7 };
8faf5a
dd81c1 /* Marker reading & parsing */
d13e9c struct jpeg_marker_reader {
bf2f1d ··JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
f70c94 ··/* Read markers until SOS or EOI.
d72dda ···* Returns same codes as are defined for jpeg_consume_input:
d83ef0 ···* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
d9f9a6 ···*/
7e8bd2 ··JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
f07b57 ··/* Read a restart marker --- exported for use by entropy decoder only */
8da01d ··jpeg_marker_parser_method read_restart_marker;
35a74d ··/* Application-overridable marker processing methods */
7676ea ··jpeg_marker_parser_method process_COM;
6e39d1 ··jpeg_marker_parser_method process_APPn[16];
33af5a
880dd9 ··/* State of marker reader --- nominally internal, but applications
bd8568 ···* supplying COM or APPn handlers might like to know the state.
e7f9a6 ···*/
21d77c ··boolean saw_SOI;¤ ¤   /* found SOI? */
ccd44c ··boolean saw_SOF;¤ ¤   /* found SOF? */
77fe06 ··int next_restart_num;¤¤   /* next restart number expected (0-7) */
f2e583 ··unsigned int discarded_bytes;¤/* # of bytes skipped looking for a marker */
d682f7 };
cfaf5a
c7ca19 /* Entropy decoding */
c06932 struct jpeg_entropy_decoder {
d253d0 ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
c4a179 ··JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
3c1e74 ¤   ¤   ¤   ¤   JBLOCKROW *MCU_data));
0282f7 };
90af5a
--51cd 00032b0823840100041 Page 4 of jpegint.h
997c55 /* Inverse DCT (also performs dequantization) */
11ad8a typedef JMETHOD(void, inverse_DCT_method_ptr,
5965d1 ¤   ¤   (j_decompress_ptr cinfo, jpeg_component_info * compptr,
612655 ¤   ¤   ·JCOEFPTR coef_block,
16cd9c ¤   ¤   ·JSAMPARRAY output_buf, JDIMENSION output_col));
08af5a
2a0322 struct jpeg_inverse_dct {
7a53d0 ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
a6ef6b ··/* It is useful to allow each component to have a separate IDCT method. */
802a70 ··inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
4582f7 };
abaf5a
6541f7 /* Upsampling (note that upsampler must also call color converter) */
5ff063 struct jpeg_upsampler {
5e53d0 ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
69fb0c ··JMETHOD(void, upsample, (j_decompress_ptr cinfo,
4752b3 ¤   ¤   ¤   ···JSAMPIMAGE input_buf,
feac28 ¤   ¤   ¤   ···JDIMENSION *in_row_group_ctr,
142113 ¤   ¤   ¤   ···JDIMENSION in_row_groups_avail,
eb9611 ¤   ¤   ¤   ···JSAMPARRAY output_buf,
d40cad ¤   ¤   ¤   ···JDIMENSION *out_row_ctr,
ee5851 ¤   ¤   ¤   ···JDIMENSION out_rows_avail));
04af5a
0ddb5a ··boolean need_context_rows;¤   /* TRUE if need rows above & below */
1882f7 };
17af5a
bd3392 /* Colorspace conversion */
e1bf00 struct jpeg_color_deconverter {
ce53d0 ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
db39a4 ··JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
4cff2c ¤   ¤   ¤   ¤   JSAMPIMAGE input_buf, JDIMENSION input_row,
1f15dc ¤   ¤   ¤   ¤   JSAMPARRAY output_buf, int num_rows));
7082f7 };
69af5a
dc80a4 /* Color quantization or color precision reduction */
4d0359 struct jpeg_color_quantizer {
d214cf ··JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
0a5385 ··JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
e76799 ¤   ¤   ¤   ¤   ·JSAMPARRAY input_buf, JSAMPARRAY output_buf,
5f43db ¤   ¤   ¤   ¤   ·int num_rows));
7f54da ··JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
9d0766 ··JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
cf82f7 };
20af5a
abaf5a
b845f3 /* Miscellaneous useful macros */
caaf5a
dc784d #undef MAX
16dfe2 #define MAX(a,b)¤   ((a) > (b) ? (a) : (b))
607fce #undef MIN
5441f3 #define MIN(a,b)¤   ((a) < (b) ? (a) : (b))
f8af5a
55af5a
809e95 /* We assume that right shift corresponds to signed division by 2 with
bf7a3b ·* rounding towards minus infinity. ·This is correct for typical "arithmetic
78c190 ·* shift" instructions that shift in copies of the sign bit. ·But some
da2054 ·* C compilers implement >> with an unsigned shift. ·For these machines you
7b0ec7 ·* must define RIGHT_SHIFT_IS_UNSIGNED.
1a9a48 ·* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
a1071e ·* It is only applied with constant shift counts. ·SHIFT_TEMPS must be
ef2171 ·* included in the variables of any routine using RIGHT_SHIFT.
bb495d ·*/
1faf5a
3066ca #ifdef RIGHT_SHIFT_IS_UNSIGNED
92b4ba #define SHIFT_TEMPS¤INT32 shift_temp;
4d32de #define RIGHT_SHIFT(x,shft) ·\
07cee8 ¤   ((shift_temp = (x)) < 0 ? \
d710e0 ¤   ·(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
ccf23f ¤   ·(shift_temp >> (shft)))
61db21 #else
65cdb4 #define SHIFT_TEMPS
32940e #define RIGHT_SHIFT(x,shft)¤((x) >> (shft))
--80f0 000c3d23faf40100041 Page 5 of jpegint.h
a07454 #endif
e0af5a
f6af5a
3c4b22 /* Short forms of external names for systems with brain-damaged linkers. */
68af5a
b0ddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
247131 #define jinit_compress_master¤  jICompress
120e63 #define jinit_c_master_control¤ jICMaster
ad4707 #define jinit_c_main_controller¤jICMainC
898a48 #define jinit_c_prep_controller¤jICPrepC
755615 #define jinit_c_coef_controller¤jICCoefC
bcd801 #define jinit_color_converter¤  jICColor
d6a4bc #define jinit_downsampler¤  jIDownsampler
f114e6 #define jinit_forward_dct¤  jIFDCT
3a3031 #define jinit_huff_encoder¤ jIHEncoder
e7243b #define jinit_phuff_encoder¤jIPHEncoder
455478 #define jinit_marker_writer¤jIMWriter
cfc2c9 #define jinit_master_decompress¤jIDMaster
3837f6 #define jinit_d_main_controller¤jIDMainC
4426e4 #define jinit_d_coef_controller¤jIDCoefC
3ef44e #define jinit_d_post_controller¤jIDPostC
91dc33 #define jinit_input_controller¤ jIInCtlr
fea766 #define jinit_marker_reader¤jIMReader
431f9c #define jinit_huff_decoder¤ jIHDecoder
c30b96 #define jinit_phuff_decoder¤jIPHDecoder
723aa5 #define jinit_inverse_dct¤  jIIDCT
70943d #define jinit_upsampler¤¤   jIUpsampler
7bd294 #define jinit_color_deconverter¤jIDColor
cc6ba3 #define jinit_1pass_quantizer¤  jI1Quant
493515 #define jinit_2pass_quantizer¤  jI2Quant
8cb287 #define jinit_merged_upsampler¤ jIMUpsampler
3037ff #define jinit_memory_mgr¤   jIMemMgr
ee9f52 #define jdiv_round_up¤  ¤   jDivRound
a9186f #define jround_up¤  ¤   jRound
2bf8b7 #define jcopy_sample_rows¤  jCopySamples
103a53 #define jcopy_block_row¤¤   jCopyBlocks
581c00 #define jzero_far¤  ¤   jZeroFar
0cfe65 #define jpeg_zigzag_order¤  jZIGTable
430978 #define jpeg_natural_order¤ jZAGTable
215892 #endif /* NEED_SHORT_EXTERNAL_NAMES */
88af5a
c4af5a
2f1057 /* Compression module initialization routines */
759364 EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
fe847b EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
d3044e ¤   ¤   ¤   ¤   ¤   ·boolean transcode_only));
1e2d99 EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
0434bc ¤   ¤   ¤   ¤   ¤   ··boolean need_full_buffer));
62c188 EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
cc34bc ¤   ¤   ¤   ¤   ¤   ··boolean need_full_buffer));
2f05bf EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
b434bc ¤   ¤   ¤   ¤   ¤   ··boolean need_full_buffer));
76ca59 EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
9ee453 EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
dff3ec EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
fe9bbc EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
3de140 EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
bf2461 EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
0cda24 /* Decompression module initialization routines */
811584 EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
64874d EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
f934bc ¤   ¤   ¤   ¤   ¤   ··boolean need_full_buffer));
035de4 EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
4f34bc ¤   ¤   ¤   ¤   ¤   ··boolean need_full_buffer));
a9efa6 EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
c634bc ¤   ¤   ¤   ¤   ¤   ··boolean need_full_buffer));
46eb91 EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
5352b5 EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
9679aa EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
5270df EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
ec90f8 EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
c3d870 EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
--8417 001c9c841dd40100041 Page 6 of jpegint.h
47c729 EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
17bcce EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
0fb70f EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
478a83 EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
57b481 /* Memory manager initialization */
abe877 EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
f0af5a
ae0dab /* Utility routines in jutils.c */
1b773e EXTERN(long) jdiv_round_up JPP((long a, long b));
1b93fb EXTERN(long) jround_up JPP((long a, long b));
beb35f EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
8f8870 ¤   ¤   ¤   ¤   ····JSAMPARRAY output_array, int dest_row,
f1d9be ¤   ¤   ¤   ¤   ····int num_rows, JDIMENSION num_cols));
e92748 EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
8ea9ea ¤   ¤   ¤   ¤   ··JDIMENSION num_blocks));
e05169 EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
67456d /* Constant tables in jutils.c */
b59086 extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
61efb6 extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
94af5a
eb8077 /* Suppress undefined-structure complaints if necessary. */
fbaf5a
4e8264 #ifdef INCOMPLETE_TYPES_BROKEN
c7bb41 #ifndef AM_MEMORY_MANAGER¤  /* only jmemmgr.c defines these */
2b098d struct jvirt_sarray_control { long dummy; };
b430b8 struct jvirt_barray_control { long dummy; };
df7454 #endif
c932fd #endif /* INCOMPLETE_TYPES_BROKEN */
--d9ff 0007fc5bc3c40100042 Page 1 of jpeglib.h
bc38e5 /*
ef0489 ·* jpeglib.h
b5775e ·*
13a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
e5fb07 ·* This file is part of the Independent JPEG Group's software.
3ca0d6 ·* For conditions of distribution and use, see the accompanying README file.
05775e ·*
05c8eb ·* This file defines the application interface for the JPEG library.
7baf66 ·* Most applications using the library need only include this file,
f64e65 ·* and perhaps jerror.h if they want to know the exact error codes.
fa495d ·*/
09af5a
2038ab #ifndef JPEGLIB_H
39e5f2 #define JPEGLIB_H
98af5a
6038e5 /*
53c973 ·* First we include the configuration files that record how this
45a654 ·* installation of the JPEG library is set up. ·jconfig.h can be
4bc84c ·* generated automatically for many systems. ·jmorecfg.h contains
f042c1 ·* manual configuration options that most people need not worry about.
b0495d ·*/
49af5a
1b28f5 #ifndef JCONFIG_INCLUDED¤   /* in case jinclude.h already did */
708052 #include "jconfig.h"¤   ¤   /* widely used configuration options */
857454 #endif
37d4cf #include "jmorecfg.h"¤  ¤   /* seldom changed options */
10af5a
24af5a
38af10 /* Version ID for the JPEG library.
90d535 ·* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
2d495d ·*/
1faf5a
c0c213 #define JPEG_LIB_VERSION ·61¤   /* Version 6a */
beaf5a
c5af5a
82cbb3 /* Various constants determining the sizes of things.
92efc9 ·* All of these are specified by the JPEG standard, so don't change them
b112e7 ·* if you want to be compatible.
c9495d ·*/
37af5a
ea1680 #define DCTSIZE¤¤   ····8¤  /* The basic DCT block is 8x8 samples */
f5b1e7 #define DCTSIZE2¤   ····64¤ /* DCTSIZE squared; # of elements in a block */
2b3bdb #define NUM_QUANT_TBLS ·····4¤  /* Quantization tables are numbered 0..3 */
cd3939 #define NUM_HUFF_TBLS ······4¤  /* Huffman tables are numbered 0..3 */
10a14d #define NUM_ARITH_TBLS ·····16¤ /* Arith-coding tables are numbered 0..15 */
1f6a38 #define MAX_COMPS_IN_SCAN ··4¤  /* JPEG limit on # of components in one scan */
9894c0 #define MAX_SAMP_FACTOR ····4¤  /* JPEG limit on sampling factors */
2aed69 /* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
d58326 ·* the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
2319b9 ·* If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
3e9d02 ·* to handle it. ·We even let you do this from the jconfig.h file. ·However,
e24c01 ·* we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
69984b ·* sometimes emits noncompliant files doesn't mean you should too.
8c495d ·*/
d5e7f1 #define C_MAX_BLOCKS_IN_MCU ··10 /* compressor's limit on blocks per MCU */
0601b6 #ifndef D_MAX_BLOCKS_IN_MCU
df384e #define D_MAX_BLOCKS_IN_MCU ··10 /* decompressor's limit on blocks per MCU */
d47454 #endif
45af5a
a7af5a
a2318c /* Data structures for images (arrays of samples and of DCT coefficients).
162122 ·* On 80x86 machines, the image arrays are too big for near pointers,
40fc5d ·* but the pointer arrays can fit in near memory.
bc495d ·*/
6caf5a
222eef typedef JSAMPLE FAR *JSAMPROW;¤ /* ptr to one image row of pixel samples. */
bda125 typedef JSAMPROW *JSAMPARRAY;¤  /* ptr to some rows (a 2-D sample array) */
9942e3 typedef JSAMPARRAY *JSAMPIMAGE;¤/* a 3-D sample array: top index is color */
12af5a
7a2852 typedef JCOEF JBLOCK[DCTSIZE2];¤/* one block of coefficients */
b100a6 typedef JBLOCK FAR *JBLOCKROW;¤ /* pointer to one row of coefficient blocks */
7fe1b6 typedef JBLOCKROW *JBLOCKARRAY;¤¤   /* a 2-D array of coefficient blocks */
--c44d 000415f0eb840100042 Page 2 of jpeglib.h
110a9b typedef JBLOCKARRAY *JBLOCKIMAGE;¤  /* a 3-D array of coefficient blocks */
7faf5a
6d25d8 typedef JCOEF FAR *JCOEFPTR;¤   /* useful in a couple of places */
37af5a
d0af5a
3d5305 /* Types for JPEG compression parameters and working tables. */
98af5a
0eaf5a
afabd7 /* DCT coefficient quantization tables. */
5aaf5a
c9f0f7 typedef struct {
9b5351 ··/* This array gives the coefficient quantizers in natural array order
18da9f ···* (not the zigzag order in which they are stored in a JPEG DQT marker).
b8af74 ···* CAUTION: IJG versions prior to v6a kept this array in zigzag order.
75f9a6 ···*/
cb45dc ··UINT16 quantval[DCTSIZE2];¤   /* quantization step for each coefficient */
01cce3 ··/* This field is used only during compression. ·It's initialized FALSE when
5cbd8e ···* the table is created, and set TRUE when it's been output to the file.
c52b72 ···* You could suppress output of a table by setting this to TRUE.
8a610a ···* (See jpeg_suppress_tables for an example.)
c3f9a6 ···*/
a0c9d7 ··boolean sent_table;¤  ¤   /* TRUE when table has been output */
4af9e6 } JQUANT_TBL;
7daf5a
f8af5a
cac82c /* Huffman coding tables. */
23af5a
55f0f7 typedef struct {
beb1be ··/* These two fields directly represent the contents of a JPEG DHT marker */
5df0be ··UINT8 bits[17];¤  ¤   /* bits[k] = # of symbols with codes of */
cd861c ¤   ¤   ¤   ¤   /* length k bits; bits[0] is unused */
c794fc ··UINT8 huffval[256];¤  ¤   /* The symbols, in order of incr code length */
e9cce3 ··/* This field is used only during compression. ·It's initialized FALSE when
6abd8e ···* the table is created, and set TRUE when it's been output to the file.
c12b72 ···* You could suppress output of a table by setting this to TRUE.
99610a ···* (See jpeg_suppress_tables for an example.)
bdf9a6 ···*/
47c9d7 ··boolean sent_table;¤  ¤   /* TRUE when table has been output */
a5a385 } JHUFF_TBL;
ccaf5a
59af5a
b8a60f /* Basic info about one component (color channel). */
bfaf5a
e8f0f7 typedef struct {
2b8484 ··/* These values are fixed over the whole image. */
6c2490 ··/* For compression, they must be supplied by parameter setup; */
f39949 ··/* for decompression, they are read from the SOF marker. */
3c4c60 ··int component_id;¤¤   /* identifier for this component (0..255) */
8e25f9 ··int component_index;¤ ¤   /* its index in SOF or cinfo->comp_info[] */
6728b2 ··int h_samp_factor;¤   ¤   /* horizontal sampling factor (1..4) */
1958a2 ··int v_samp_factor;¤   ¤   /* vertical sampling factor (1..4) */
e1e3c2 ··int quant_tbl_no;¤¤   /* quantization table selector (0..3) */
b98da5 ··/* These values may vary between scans. */
c22490 ··/* For compression, they must be supplied by parameter setup; */
07d080 ··/* for decompression, they are read from the SOS marker. */
d6a724 ··/* The decompressor output side may not use these variables. */
e97166 ··int dc_tbl_no;¤   ¤   /* DC entropy table selector (0..3) */
10e69e ··int ac_tbl_no;¤   ¤   /* AC entropy table selector (0..3) */
28de7b ··
20189f ··/* Remaining fields should be treated as private by applications. */
cbde7b ··
774e6d ··/* These values are computed during compression or decompression startup: */
2f5bc0 ··/* Component's size in DCT blocks.
9ba6f4 ···* Any dummy blocks added to complete an MCU are not counted; therefore
ae3763 ···* these values do not depend on whether a scan is interleaved or not.
5ef9a6 ···*/
1c29cf ··JDIMENSION width_in_blocks;
facc74 ··JDIMENSION height_in_blocks;
638ea7 ··/* Size of a DCT block in samples. ·Always DCTSIZE for compression.
632da0 ···* For decompression this is the size of the output from one DCT block,
aa719d ···* reflecting any scaling we choose to apply during the IDCT step.
417655 ···* Values of 1,2,4,8 are likely to be supported. ·Note that different
--213d 000037df49940100042 Page 3 of jpeglib.h
814091 ···* components may receive different IDCT scalings.
dbf9a6 ···*/
588105 ··int DCT_scaled_size;
735498 ··/* The downsampled dimensions are the component's actual, unpadded number
025ebe ···* of samples at the main buffer (preprocessing/compression interface), thus
e0f889 ···* downsampled_width = ceil(image_width * Hi/Hmax)
a0e711 ···* and similarly for height. ·For decompression, IDCT scaling is included, so
549940 ···* downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
48f9a6 ···*/
b484bb ··JDIMENSION downsampled_width;¤ /* actual width in samples */
8fe3d1 ··JDIMENSION downsampled_height; /* actual height in samples */
690031 ··/* This flag is used only for decompression. ·In cases where some of the
e2d448 ···* components will be ignored (eg grayscale output from YCbCr image),
3d3947 ···* we can skip most computations for the unused components.
def9a6 ···*/
ab69e6 ··boolean component_needed;¤/* do we need the value of this component? */
97af5a
7048cc ··/* These values are computed before starting a scan of the component. */
93a724 ··/* The decompressor output side may not use these variables. */
6b4cd9 ··int MCU_width;¤   ¤   /* number of blocks per MCU, horizontally */
973498 ··int MCU_height;¤  ¤   /* number of blocks per MCU, vertically */
fb0e76 ··int MCU_blocks;¤  ¤   /* MCU_width * MCU_height */
cb835f ··int MCU_sample_width;¤¤   /* MCU width in samples, MCU_width*DCT_scaled_size ¶
6f7fe0 */
b45029 ··int last_col_width;¤  ¤   /* # of non-dummy blocks across in last MCU */
079262 ··int last_row_height;¤ ¤   /* # of non-dummy blocks down in last MCU */
23af5a
e4f7d1 ··/* Saved quantization table for component; NULL if none yet saved.
662e55 ···* See jdinput.c comments about the need for this information.
ab7406 ···* This field is currently used only for decompression.
0bf9a6 ···*/
8c06c0 ··JQUANT_TBL * quant_table;
05af5a
aa5409 ··/* Private per-component storage for DCT or IDCT subsystem. */
1d21a4 ··void * dct_table;
5813d1 } jpeg_component_info;
d8af5a
98af5a
91bbfa /* The script for encoding a multiple-scan file is an array of these: */
6caf5a
fff0f7 typedef struct {
63a3cf ··int comps_in_scan;¤   ¤   /* number of components encoded in this scan */
8268e8 ··int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
eb5b4b ··int Ss, Se;¤  ¤   ¤   /* progressive JPEG spectral selection parms */
de04ba ··int Ah, Al;¤  ¤   ¤   /* progressive JPEG successive approx. parms */
9741ed } jpeg_scan_info;
deaf5a
85af5a
ab5953 /* Known color spaces. */
09af5a
fded84 typedef enum {
537d5e ¤   JCS_UNKNOWN,¤   ¤   /* error/unspecified */
8355c8 ¤   JCS_GRAYSCALE,¤ ¤   /* monochrome */
0b0985 ¤   JCS_RGB,¤   ¤   /* red/green/blue */
19c809 ¤   JCS_YCbCr,¤ ¤   /* Y/Cb/Cr (also known as YUV) */
e6e030 ¤   JCS_CMYK,¤  ¤   /* C/M/Y/K */
8d7e27 ¤   JCS_YCCK¤   ¤   /* Y/Cb/Cr/K */
673cbb } J_COLOR_SPACE;
a4af5a
8a5da6 /* DCT/IDCT algorithm options. */
97af5a
98ed84 typedef enum {
030398 ¤   JDCT_ISLOW,¤¤   /* slow but accurate integer algorithm */
7e0de7 ¤   JDCT_IFAST,¤¤   /* faster, less accurate integer method */
4d88a7 ¤   JDCT_FLOAT¤ ¤   /* floating-point: accurate, fast on fast HW */
8b5813 } J_DCT_METHOD;
edaf5a
e00877 #ifndef JDCT_DEFAULT¤   ¤   /* may be overridden in jconfig.h */
861ec2 #define JDCT_DEFAULT ·JDCT_ISLOW
3c7454 #endif
e79646 #ifndef JDCT_FASTEST¤   ¤   /* may be overridden in jconfig.h */
03e970 #define JDCT_FASTEST ·JDCT_IFAST
--bee9 000b1e2eeae40100042 Page 4 of jpeglib.h
a07454 #endif
e0af5a
d0b804 /* Dithering options for decompression. */
eaaf5a
bbed84 typedef enum {
c18eb3 ¤   JDITHER_NONE,¤  ¤   /* no dithering */
ecdd82 ¤   JDITHER_ORDERED,¤   /* simple ordered dither */
7b3eac ¤   JDITHER_FS¤ ¤   /* Floyd-Steinberg error diffusion dither */
8576e8 } J_DITHER_MODE;
57af5a
35af5a
61e0ce /* Common fields between JPEG compression and decompression master structs. */
fdaf5a
878db4 #define jpeg_common_fields \
76ab7e ··struct jpeg_error_mgr * err;¤ /* Error handler module */\
f79949 ··struct jpeg_memory_mgr * mem;¤/* Memory manager module */\
16e49b ··struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
cf0b57 ··boolean is_decompressor;¤ /* so common code can tell which is which */\
65de61 ··int global_state¤ ¤   /* for checking call sequence validity */
20af5a
7b4e46 /* Routines that are to be used by both halves of the library are declared
ca1c72 ·* to receive a pointer to this structure. ·There are no actual instances of
7c2596 ·* jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
11495d ·*/
e5c8a0 struct jpeg_common_struct {
a74605 ··jpeg_common_fields;¤  ¤   /* Fields common to both master struct types */
2d1727 ··/* Additional fields follow in an actual jpeg_compress_struct or
55605c ···* jpeg_decompress_struct. ·All three structs must agree on these
179df6 ···* initial fields! ·(This would be a lot cleaner in C++.)
daf9a6 ···*/
6a82f7 };
d8af5a
1cbb95 typedef struct jpeg_common_struct * j_common_ptr;
81369f typedef struct jpeg_compress_struct * j_compress_ptr;
1c1ee8 typedef struct jpeg_decompress_struct * j_decompress_ptr;
cfaf5a
fdaf5a
61fe0e /* Master record for a compression instance */
c5af5a
0e330c struct jpeg_compress_struct {
1efdf0 ··jpeg_common_fields;¤  ¤   /* Fields shared with jpeg_decompress_struct */
73af5a
5e7d75 ··/* Destination for compressed data */
af02da ··struct jpeg_destination_mgr * dest;
91af5a
31bc3e ··/* Description of source image --- these fields must be filled in by
11db86 ···* outer application before starting compression. ·in_color_space must
219aa0 ···* be correct before you can even call jpeg_set_defaults().
e1f9a6 ···*/
dbaf5a
ccb636 ··JDIMENSION image_width;¤  /* input image width */
6af621 ··JDIMENSION image_height;¤ /* input image height */
d07948 ··int input_components;¤¤   /* # of color components in input image */
9c2c50 ··J_COLOR_SPACE in_color_space;¤/* colorspace of input image */
60af5a
626252 ··double input_gamma;¤  ¤   /* image gamma of input image */
b5af5a
4e4ec5 ··/* Compression parameters --- these fields must be set before calling
57fe85 ···* jpeg_start_compress(). ·We recommend calling jpeg_set_defaults() to
7939b9 ···* initialize everything to reasonable defaults, then changing anything
31a2a7 ···* the application specifically wants to change. ·That way you won't get
4dc527 ···* burnt when new parameters are added. ·Also note that there are several
ef07be ···* helper routines to simplify changing parameters.
2df9a6 ···*/
07af5a
4237ff ··int data_precision;¤  ¤   /* bits of precision in image data */
72af5a
406dc7 ··int num_components;¤  ¤   /* # of color components in JPEG image */
e8ac94 ··J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
8aaf5a
571b59 ··jpeg_component_info * comp_info;
b1bc2b ··/* comp_info[i] describes component that appears i'th in SOF */
--ba31 00062254fb540100042 Page 5 of jpeglib.h
8bde7b ··
f380cf ··JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
0c02b3 ··/* ptrs to coefficient quantization tables, or NULL if not defined */
c2de7b ··
aa2d38 ··JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
ae64c6 ··JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
2d87dd ··/* ptrs to Huffman coding tables, or NULL if not defined */
93de7b ··
8021eb ··UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
41332b ··UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
b9f930 ··UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
29af5a
059382 ··int num_scans;¤   ¤   /* # of entries in scan_info array */
b1a499 ··const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
16ac4e ··/* The default value of scan_info is NULL, which causes a single-scan
e1deac ···* sequential JPEG file to be emitted. ·To create a multi-scan file,
84a9be ···* set num_scans and scan_info to point to an array of scan definitions.
90f9a6 ···*/
6aaf5a
072dad ··boolean raw_data_in;¤ ¤   /* TRUE=caller supplies downsampled data */
05ce80 ··boolean arith_code;¤  ¤   /* TRUE=arithmetic coding, FALSE=Huffman */
377fb0 ··boolean optimize_coding;¤ /* TRUE=optimize entropy encoding parms */
fb8ffc ··boolean CCIR601_sampling;¤/* TRUE=first samples are cosited */
31f173 ··int smoothing_factor;¤¤   /* 1..100, or 0 for no input smoothing */
20d746 ··J_DCT_METHOD dct_method;¤ /* DCT algorithm selector */
07af5a
33333f ··/* The restart interval can be specified in absolute MCUs by setting
4b875d ···* restart_interval, or in MCU rows by setting restart_in_rows
7d6d36 ···* (in which case the correct restart_interval will be figured
784685 ···* for each scan).
e4f9a6 ···*/
f12256 ··unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
e0fbea ··int restart_in_rows;¤ ¤   /* if > 0, MCU rows per restart interval */
0aaf5a
beb563 ··/* Parameters controlling emission of special markers. */
c9af5a
eb9334 ··boolean write_JFIF_header;¤   /* should a JFIF marker be written? */
ad3ecc ··/* These three values are not used by the JPEG code, merely copied */
e41ad3 ··/* into the JFIF APP0 marker. ·density_unit can be 0 for unknown, */
cb88f3 ··/* 1 for dots/inch, or 2 for dots/cm. ·Note that the pixel aspect */
8da667 ··/* ratio is defined by X_density/Y_density even when density_unit=0. */
b474d4 ··UINT8 density_unit;¤  ¤   /* JFIF code for pixel size units */
f27dce ··UINT16 X_density;¤¤   /* Horizontal pixel density */
c1416a ··UINT16 Y_density;¤¤   /* Vertical pixel density */
34f9f7 ··boolean write_Adobe_marker;¤  /* should an Adobe marker be written? */
61de7b ··
dbf808 ··/* State variable: index of next scanline to be written to
8b411e ···* jpeg_write_scanlines(). ·Application may use this to control its
5eade6 ···* processing loop, e.g., "while (next_scanline < image_height)".
64f9a6 ···*/
91af5a
9ded4d ··JDIMENSION next_scanline;¤/* 0 .. image_height-1 ·*/
d4af5a
e686ec ··/* Remaining fields are known throughout compressor, but generally
5592a0 ···* should not be touched by a surrounding application.
ebf9a6 ···*/
75af5a
906000 ··/*
670417 ···* These fields are computed during compression startup
82f9a6 ···*/
a86086 ··boolean progressive_mode;¤/* TRUE if scan script uses progressive mode */
a093da ··int max_h_samp_factor;¤   /* largest h_samp_factor */
ebad9a ··int max_v_samp_factor;¤   /* largest v_samp_factor */
16af5a
d5d927 ··JDIMENSION total_iMCU_rows;¤  /* # of iMCU rows to be input to coef ctlr */
c7b70a ··/* The coefficient controller receives data in units of MCU rows as defined
8068cc ···* for fully interleaved scans (whether the JPEG file is interleaved or not).
63fcd0 ···* There are v_samp_factor * DCTSIZE sample rows of each component in an
efbfba ···* "iMCU" (interleaved MCU) row.
dff9a6 ···*/
2ade7b ··
626000 ··/*
--7cb5 0004ede9e9340100042 Page 6 of jpeglib.h
0d775b ···* These fields are valid during any one scan.
57a06c ···* They describe the components and MCUs actually appearing in the scan.
b0f9a6 ···*/
7df257 ··int comps_in_scan;¤   ¤   /* # of JPEG components in this scan */
a44ba9 ··jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
6a6e07 ··/* *cur_comp_info[i] describes component that appears i'th in SOS */
14de7b ··
735742 ··JDIMENSION MCUs_per_row;¤ /* # of MCUs across the image */
055da6 ··JDIMENSION MCU_rows_in_scan;¤ /* # of MCU rows in the image */
84de7b ··
aca75c ··int blocks_in_MCU;¤   ¤   /* # of DCT blocks per MCU */
50e000 ··int MCU_membership[C_MAX_BLOCKS_IN_MCU];
15bf71 ··/* MCU_membership[i] is index in cur_comp_info of component owning */
ad4f7d ··/* i'th block in an MCU */
07af5a
ef11cd ··int Ss, Se, Ah, Al;¤  ¤   /* progressive JPEG parameters for scan */
96af5a
a46000 ··/*
34008f ···* Links to compression subobjects (methods and private variables of modules)
b5f9a6 ···*/
7d0fb0 ··struct jpeg_comp_master * master;
a74165 ··struct jpeg_c_main_controller * main;
bd023d ··struct jpeg_c_prep_controller * prep;
e17711 ··struct jpeg_c_coef_controller * coef;
3cbe80 ··struct jpeg_marker_writer * marker;
87ecc0 ··struct jpeg_color_converter * cconvert;
3cff3d ··struct jpeg_downsampler * downsample;
ca40b7 ··struct jpeg_forward_dct * fdct;
90b4d6 ··struct jpeg_entropy_encoder * entropy;
4082f7 };
20af5a
b0af5a
cf79b4 /* Master record for a decompression instance */
24af5a
875d5a struct jpeg_decompress_struct {
2f27f9 ··jpeg_common_fields;¤  ¤   /* Fields shared with jpeg_compress_struct */
dfaf5a
76a0a0 ··/* Source of compressed data */
18bd0c ··struct jpeg_source_mgr * src;
5daf5a
633b1e ··/* Basic description of image --- filled in by jpeg_read_header(). */
55f519 ··/* Application may inspect these values to decide how to process image. */
75af5a
a206e2 ··JDIMENSION image_width;¤  /* nominal image width (from SOF marker) */
6e9f37 ··JDIMENSION image_height;¤ /* nominal image height */
fe6dc7 ··int num_components;¤  ¤   /* # of color components in JPEG image */
aaac94 ··J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
21af5a
8773fc ··/* Decompression processing parameters --- these fields must be set before
d3ceb6 ···* calling jpeg_start_decompress(). ·Note that jpeg_read_header() initializes
709fe8 ···* them to default values.
e3f9a6 ···*/
a4af5a
a6ad39 ··J_COLOR_SPACE out_color_space; /* colorspace for output */
8caf5a
a5ba3c ··unsigned int scale_num, scale_denom; /* fraction by which to scale image */
7faf5a
4aad23 ··double output_gamma;¤ ¤   /* image gamma wanted in output */
beaf5a
783403 ··boolean buffered_image;¤  /* TRUE=multiple output passes */
d28200 ··boolean raw_data_out;¤¤   /* TRUE=downsampled data wanted */
f3af5a
79e212 ··J_DCT_METHOD dct_method;¤ /* IDCT algorithm selector */
8d2fef ··boolean do_fancy_upsampling;¤ /* TRUE=apply fancy upsampling */
f44127 ··boolean do_block_smoothing;¤  /* TRUE=apply interblock smoothing */
49af5a
669221 ··boolean quantize_colors;¤ /* TRUE=colormapped output wanted */
432e32 ··/* the following are ignored if not quantize_colors: */
0a8400 ··J_DITHER_MODE dither_mode;¤   /* type of color dithering to use */
6736e4 ··boolean two_pass_quantize;¤   /* TRUE=use two-pass color quantization */
e4f55e ··int desired_number_of_colors;¤/* max # colors to use in created colormap */
4e314b ··/* these are significant only in buffered-image mode: */
--43f1 000522c10fc40100042 Page 7 of jpeglib.h
52071c ··boolean enable_1pass_quant;¤  /* enable future use of 1-pass quantizer */
9feb3f ··boolean enable_external_quant;/* enable future use of external colormap */
77501b ··boolean enable_2pass_quant;¤  /* enable future use of 2-pass quantizer */
e2af5a
dfb817 ··/* Description of actual output image that will be returned to application.
1ddcc5 ···* These fields are computed by jpeg_start_decompress().
26a2f5 ···* You can also use jpeg_calc_output_dimensions() to determine these values
106169 ···* in advance of calling jpeg_start_decompress().
12f9a6 ···*/
76af5a
9c3995 ··JDIMENSION output_width;¤ /* scaled image width */
b5613f ··JDIMENSION output_height;¤/* scaled image height */
7e246c ··int out_color_components;¤/* # of color components in out_color_space */
c67920 ··int output_components;¤   /* # of color components returned */
4605a0 ··/* output_components is 1 (a colormap index) when quantizing colors;
8cd174 ···* otherwise it equals out_color_components.
c9f9a6 ···*/
4f35cc ··int rec_outbuf_height;¤   /* min recommended height of scanline buffer */
a20dea ··/* If the buffer passed to jpeg_read_scanlines() is less than this many rows
e6cec4 ···* high, space and time will be wasted due to unnecessary data copying.
e66a7f ···* Usually rec_outbuf_height will be 1 or 2, at most 4.
b3f9a6 ···*/
91af5a
5aaec1 ··/* When quantizing colors, the output colormap is described by these fields.
f32330 ···* The application can supply a colormap by setting colormap non-NULL before
87f118 ···* calling jpeg_start_decompress; otherwise a colormap is created during
1a228d ···* jpeg_start_decompress or jpeg_start_output.
f5409f ···* The map has out_color_components rows and actual_number_of_colors columns.
86f9a6 ···*/
f4c415 ··int actual_number_of_colors;¤ /* number of entries in use */
a0f108 ··JSAMPARRAY colormap;¤ ¤   /* The color map as a 2-D pixel array */
7daf5a
1f3213 ··/* State variables: these variables indicate the progress of decompression.
403799 ···* The application may examine these but must not modify them.
f1f9a6 ···*/
2eaf5a
4237ab ··/* Row index of next scanline to be read from jpeg_read_scanlines().
d117f7 ···* Application may use this to control its processing loop, e.g.,
542844 ···* "while (output_scanline < output_height)".
5ef9a6 ···*/
c66bb5 ··JDIMENSION output_scanline;¤  /* 0 .. output_height-1 ·*/
95af5a
d7a4f6 ··/* Current input scan number and number of iMCU rows completed in scan.
f979ea ···* These indicate the progress of the decompressor input side.
edf9a6 ···*/
d559fd ··int input_scan_number;¤   /* Number of SOS markers seen so far */
5fb52e ··JDIMENSION input_iMCU_row;¤   /* Number of iMCU rows completed */
feaf5a
35b66d ··/* The "output scan number" is the notional scan being displayed by the
285dcd ···* output side. ·The decompressor will not allow output scan/row number
8c9edd ···* to get ahead of input scan/row, but it can fall arbitrarily far behind.
c6f9a6 ···*/
31ce1d ··int output_scan_number;¤  /* Nominal scan number being displayed */
caba99 ··JDIMENSION output_iMCU_row;¤  /* Number of iMCU rows read */
76af5a
023b4e ··/* Current progression status. ·coef_bits[c][i] indicates the precision
e3c33a ···* with which component c's DCT coefficient i (in zigzag order) is known.
046596 ···* It is -1 when no data has yet been received, otherwise it is the point
f8efff ···* transform (shift) value for the most recent scan of the coefficient
807e1c ···* (thus, 0 at completion of the progression).
c81fe9 ···* This pointer is NULL when reading a non-progressive file.
a8f9a6 ···*/
69d367 ··int (*coef_bits)[DCTSIZE2];¤  /* -1 or current Al value for each coef */
73af5a
ec018c ··/* Internal JPEG parameters --- the application usually need not look at
f103bf ···* these fields. ·Note that the decompressor output side may not use
797f51 ···* any parameters that can change between scans.
c0f9a6 ···*/
48af5a
033cda ··/* Quantization and Huffman tables are carried forward across input
9eaaa5 ···* datastreams when processing abbreviated JPEG datastreams.
52f9a6 ···*/
--a440 0009255e6ef40100042 Page 8 of jpeglib.h
e0af5a
7780cf ··JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
ab02b3 ··/* ptrs to coefficient quantization tables, or NULL if not defined */
8caf5a
e82d38 ··JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
4464c6 ··JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
2687dd ··/* ptrs to Huffman coding tables, or NULL if not defined */
c4af5a
9e8390 ··/* These parameters are never carried across datastreams, since they
434258 ···* are given in SOF/SOS markers or defined to be reset by SOI.
80f9a6 ···*/
37af5a
de37ff ··int data_precision;¤  ¤   /* bits of precision in image data */
3baf5a
051b59 ··jpeg_component_info * comp_info;
9cbc2b ··/* comp_info[i] describes component that appears i'th in SOF */
dcaf5a
d3f8e5 ··boolean progressive_mode;¤/* TRUE if SOFn specifies progressive mode */
adce80 ··boolean arith_code;¤  ¤   /* TRUE=arithmetic coding, FALSE=Huffman */
66af5a
cf21eb ··UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
47332b ··UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
def930 ··UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
8eaf5a
31471f ··unsigned int restart_interval; /* MCUs per restart interval, or 0 for no rest¶
753e57 art */
08af5a
524d0d ··/* These fields record data obtained from optional markers recognized by
8d8f6d ···* the JPEG library.
a5f9a6 ···*/
0a59dc ··boolean saw_JFIF_marker;¤ /* TRUE iff a JFIF APP0 marker was found */
ce9164 ··/* Data copied from JFIF marker: */
fe74d4 ··UINT8 density_unit;¤  ¤   /* JFIF code for pixel size units */
fc7dce ··UINT16 X_density;¤¤   /* Horizontal pixel density */
a7416a ··UINT16 Y_density;¤¤   /* Vertical pixel density */
ba3654 ··boolean saw_Adobe_marker;¤/* TRUE iff an Adobe APP14 marker was found */
bef5bb ··UINT8 Adobe_transform;¤   /* Color transform code from Adobe marker */
abaf5a
b48ffc ··boolean CCIR601_sampling;¤/* TRUE=first samples are cosited */
d8af5a
5b7e0b ··/* Remaining fields are known throughout decompressor, but generally
cd92a0 ···* should not be touched by a surrounding application.
bcf9a6 ···*/
1baf5a
e06000 ··/*
d17bd2 ···* These fields are computed during decompression startup
d2f9a6 ···*/
7393da ··int max_h_samp_factor;¤   /* largest h_samp_factor */
e4ad9a ··int max_v_samp_factor;¤   /* largest v_samp_factor */
7daf5a
61fdb9 ··int min_DCT_scaled_size;¤ /* smallest DCT_scaled_size of any component */
f4af5a
02cab6 ··JDIMENSION total_iMCU_rows;¤  /* # of iMCU rows in image */
94ccad ··/* The coefficient controller's input and output progress is measured in
d17720 ···* units of "iMCU" (interleaved MCU) rows. ·These are the same as MCU rows
5cfbfb ···* in fully interleaved JPEG scans, but are used whether the scan is
7eb3dc ···* interleaved or not. ·We define an iMCU row as v_samp_factor DCT block
62d0cf ···* rows of each component. ·Therefore, the IDCT output contains
68689b ···* v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row.
d7f9a6 ···*/
e8af5a
290769 ··JSAMPLE * sample_range_limit; /* table for fast range-limiting */
e7af5a
a26000 ··/*
44775b ···* These fields are valid during any one scan.
bea06c ···* They describe the components and MCUs actually appearing in the scan.
93ae78 ···* Note that the decompressor output side must not use these fields.
65f9a6 ···*/
29f257 ··int comps_in_scan;¤   ¤   /* # of JPEG components in this scan */
034ba9 ··jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
876e07 ··/* *cur_comp_info[i] describes component that appears i'th in SOS */
92af5a
--e307 00028328aca40100042 Page 9 of jpeglib.h
515742 ··JDIMENSION MCUs_per_row;¤ /* # of MCUs across the image */
445da6 ··JDIMENSION MCU_rows_in_scan;¤ /* # of MCU rows in the image */
1faf5a
44a75c ··int blocks_in_MCU;¤   ¤   /* # of DCT blocks per MCU */
8fa6a0 ··int MCU_membership[D_MAX_BLOCKS_IN_MCU];
bcbf71 ··/* MCU_membership[i] is index in cur_comp_info of component owning */
034f7d ··/* i'th block in an MCU */
96af5a
5211cd ··int Ss, Se, Ah, Al;¤  ¤   /* progressive JPEG parameters for scan */
bcaf5a
5342e9 ··/* This field is shared between entropy decoder and marker parser.
37d1db ···* It is either zero or the code of a JPEG marker that has been
ae9f25 ···* read from the data source, but has not yet been processed.
f3f9a6 ···*/
7d6359 ··int unread_marker;
5baf5a
2c6000 ··/*
6c6340 ···* Links to decompression subobjects (methods, private variables of modules)
98f9a6 ···*/
a06779 ··struct jpeg_decomp_master * master;
2633f7 ··struct jpeg_d_main_controller * main;
930583 ··struct jpeg_d_coef_controller * coef;
d6a82d ··struct jpeg_d_post_controller * post;
c9b08c ··struct jpeg_input_controller * inputctl;
a57add ··struct jpeg_marker_reader * marker;
a2d9e8 ··struct jpeg_entropy_decoder * entropy;
55f618 ··struct jpeg_inverse_dct * idct;
6605f1 ··struct jpeg_upsampler * upsample;
7e28fa ··struct jpeg_color_deconverter * cconvert;
d25869 ··struct jpeg_color_quantizer * cquantize;
1382f7 };
5faf5a
dbaf5a
555293 /* "Object" declarations for JPEG modules that may be supplied or called
e0753f ·* directly by the surrounding application.
569038 ·* As with all objects in the JPEG library, these structs only define the
df0868 ·* publicly visible methods and state variables of a module. ·Additional
c072ba ·* private fields may exist after the public ones.
71495d ·*/
a0af5a
d7af5a
37bd0a /* Error handler object */
ecaf5a
d33b75 struct jpeg_error_mgr {
b92ae0 ··/* Error exit handler: does not return to caller */
edb68e ··JMETHOD(void, error_exit, (j_common_ptr cinfo));
ac06f9 ··/* Conditionally emit a trace or warning message */
856cf8 ··JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
f3e15a ··/* Routine that actually outputs a trace or error message */
f71d04 ··JMETHOD(void, output_message, (j_common_ptr cinfo));
b276a2 ··/* Format a message string for the most recent JPEG error or message */
12c007 ··JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
769439 #define JMSG_LENGTH_MAX ·200¤   /* recommended size of format_message buffer */
002608 ··/* Reset error state variables at start of a new image */
f18937 ··JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
55de7b ··
5dc8c2 ··/* The message ID code and any parameters are saved here.
40b14f ···* A message can have one string parameter or up to 8 int parameters.
01f9a6 ···*/
623d00 ··int msg_code;
eb47e0 #define JMSG_STR_PARM_MAX ·80
74e6e6 ··union {
fb3063 ····int i[8];
c2de2b ····char s[JMSG_STR_PARM_MAX];
58aaeb ··} msg_parm;
6dde7b ··
040181 ··/* Standard state variables for error facility */
70de7b ··
7da397 ··int trace_level;¤ ¤   /* max msg_level that will be displayed */
e8de7b ··
d8dedb ··/* For recoverable corrupt-data errors, we emit a warning message,
28ef26 ···* but keep going unless emit_message chooses to abort. ·emit_message
--f18b 000746336ff40100042 Page 10 of jpeglib.h
5ec4a6 ···* should count warnings in num_warnings. ·The surrounding application
c48f8e ···* can check for bad data by seeing if num_warnings is nonzero at the
67b44f ···* end of processing.
6bf9a6 ···*/
3e6777 ··long num_warnings;¤   ¤   /* number of corrupt-data warnings */
c7af5a
ebbf09 ··/* These fields point to the table(s) of error message strings.
b785f9 ···* An application can change the table pointer to switch to a different
fbf8ff ···* message list (typically, to change the language in which errors are
4b8a02 ···* reported). ·Some applications may wish to add additional error codes
4dc2a1 ···* that will be handled by the JPEG library error mechanism; the second
af7f6d ···* table pointer is used for this purpose.
bc2fbb ···*
119cec ···* First table includes all errors generated by JPEG library itself.
d0aa5f ···* Error code 0 is reserved for a "no such error string" message.
ebf9a6 ···*/
9d422e ··const char * const * jpeg_message_table; /* Library errors */
2d9624 ··int last_jpeg_message; ···/* Table contains strings 0..last_jpeg_message */
6d9ae2 ··/* Second table can be added by application (see cjpeg/djpeg for example).
ef9b90 ···* It contains strings numbered first_addon_message..last_addon_message.
29f9a6 ···*/
9e7dca ··const char * const * addon_message_table; /* Non-library errors */
c11de9 ··int first_addon_message;¤ /* code for first string in addon table */
61ba6e ··int last_addon_message;¤  /* code for last string in addon table */
d682f7 };
42af5a
74af5a
19b4fc /* Progress monitor object */
0daf5a
9edf10 struct jpeg_progress_mgr {
146b0c ··JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
82af5a
dc08bb ··long pass_counter;¤   ¤   /* work units completed in this pass */
6c0473 ··long pass_limit;¤ ¤   /* total number of work units in this pass */
d537e7 ··int completed_passes;¤¤   /* passes completed so far */
be41f6 ··int total_passes;¤¤   /* total number of passes expected */
a882f7 };
e2af5a
46af5a
e6d26b /* Data destination object for compression */
2daf5a
fcbe40 struct jpeg_destination_mgr {
8f1f80 ··JOCTET * next_output_byte;¤   /* => next byte to write in buffer */
5aa28a ··size_t free_in_buffer;¤   /* # of byte spaces remaining in buffer */
deaf5a
504b12 ··JMETHOD(void, init_destination, (j_compress_ptr cinfo));
e0c66d ··JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
feaf05 ··JMETHOD(void, term_destination, (j_compress_ptr cinfo));
9d82f7 };
5faf5a
bfaf5a
8e7216 /* Data source object for decompression */
19af5a
2c58a4 struct jpeg_source_mgr {
10d51f ··const JOCTET * next_input_byte; /* => next byte to read from buffer */
5156f9 ··size_t bytes_in_buffer;¤  /* # of bytes remaining in buffer */
22af5a
a5b32a ··JMETHOD(void, init_source, (j_decompress_ptr cinfo));
4a52c5 ··JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
c6f9fe ··JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
f0ce75 ··JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
af4727 ··JMETHOD(void, term_source, (j_decompress_ptr cinfo));
b582f7 };
bfaf5a
38af5a
6c6fba /* Memory manager object.
273270 ·* Allocates "small" objects (a few K total), "large" objects (tens of K),
853c4c ·* and "really big" objects (virtual arrays with backing store if needed).
21a274 ·* The memory manager does not allow individual objects to be freed; rather,
d7f210 ·* each created object is assigned to a pool, and whole pools can be freed
5e88f4 ·* at once. ·This is faster and more convenient than remembering exactly what
74bb4a ·* to free, especially where malloc()/free() are not too speedy.
--562e 000f7ea941940100042 Page 11 of jpeglib.h
407861 ·* NB: alloc routines never return NULL. ·They exit to error_exit if not
eefba5 ·* successful.
c8495d ·*/
f2af5a
ea2618 #define JPOOL_PERMANENT¤0¤  /* lasts until master record is destroyed */
b6d9b4 #define JPOOL_IMAGE¤1¤  /* lasts until done with image/datastream */
121980 #define JPOOL_NUMPOOLS¤ 2
f9af5a
409daf typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
e0d38b typedef struct jvirt_barray_control * jvirt_barray_ptr;
93af5a
1faf5a
7f02f9 struct jpeg_memory_mgr {
3f37ab ··/* Method pointers */
594d68 ··JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
1202f5 ¤   ¤   ¤   ¤   size_t sizeofobject));
266260 ··JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
8d70d8 ¤   ¤   ¤   ¤   ·····size_t sizeofobject));
c2a9df ··JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
7d8c30 ¤   ¤   ¤   ¤   ·····JDIMENSION samplesperrow,
192b7f ¤   ¤   ¤   ¤   ·····JDIMENSION numrows));
7310df ··JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
6d11f7 ¤   ¤   ¤   ¤   ······JDIMENSION blocksperrow,
9d4f3f ¤   ¤   ¤   ¤   ······JDIMENSION numrows));
0df4f1 ··JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
0fdfeb ¤   ¤   ¤   ¤   ¤   ¤   ··int pool_id,
63a471 ¤   ¤   ¤   ¤   ¤   ¤   ··boolean pre_zero,
6b2746 ¤   ¤   ¤   ¤   ¤   ¤   ··JDIMENSION samplesperrow,
45ae06 ¤   ¤   ¤   ¤   ¤   ¤   ··JDIMENSION numrows,
a05b02 ¤   ¤   ¤   ¤   ¤   ¤   ··JDIMENSION maxaccess));
438ab3 ··JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
93dfeb ¤   ¤   ¤   ¤   ¤   ¤   ··int pool_id,
28a471 ¤   ¤   ¤   ¤   ¤   ¤   ··boolean pre_zero,
1d19fa ¤   ¤   ¤   ¤   ¤   ¤   ··JDIMENSION blocksperrow,
5fae06 ¤   ¤   ¤   ¤   ¤   ¤   ··JDIMENSION numrows,
2b5b02 ¤   ¤   ¤   ¤   ¤   ¤   ··JDIMENSION maxaccess));
38c1d9 ··JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
1bcdd6 ··JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
1bff3e ¤   ¤   ¤   ¤   ¤   ···jvirt_sarray_ptr ptr,
897b25 ¤   ¤   ¤   ¤   ¤   ···JDIMENSION start_row,
e60f40 ¤   ¤   ¤   ¤   ¤   ···JDIMENSION num_rows,
2ac36e ¤   ¤   ¤   ¤   ¤   ···boolean writable));
b5011b ··JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
ea1776 ¤   ¤   ¤   ¤   ¤   ····jvirt_barray_ptr ptr,
5cbcf5 ¤   ¤   ¤   ¤   ¤   ····JDIMENSION start_row,
98db91 ¤   ¤   ¤   ¤   ¤   ····JDIMENSION num_rows,
c18f9c ¤   ¤   ¤   ¤   ¤   ····boolean writable));
b7db9a ··JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
551c90 ··JMETHOD(void, self_destruct, (j_common_ptr cinfo));
cbaf5a
6d3561 ··/* Limit on memory allocation for this JPEG object. ·(Note that this is
334b12 ···* merely advisory, not a guaranteed maximum; it only affects the space
640359 ···* used for virtual-array buffers.) ·May be changed by outer application
77a42c ···* after creating the JPEG object.
99f9a6 ···*/
a77acf ··long max_memory_to_use;
c082f7 };
26af5a
2faf5a
a9773e /* Routine signature for application-supplied marker processing methods.
c501ee ·* Need not pass marker code since it is stored in cinfo->unread_marker.
6b495d ·*/
853c61 typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
c9af5a
9aaf5a
60ba80 /* Declarations for routines called by application.
5df638 ·* The JPP macro hides prototype parameters from compilers that can't cope.
3879ae ·* Note JPP requires double parentheses.
09495d ·*/
3baf5a
d06cff #ifdef HAVE_PROTOTYPES
f70622 #define JPP(arglist)¤   arglist
--85ae 000e452daa740100042 Page 12 of jpeglib.h
0fdb21 #else
434d96 #define JPP(arglist)¤   ()
7c7454 #endif
9eaf5a
c0af5a
08d74a /* Short forms of external names for systems with brain-damaged linkers.
aa9aee ·* We shorten external names to be unique in the first six letters, which
06347c ·* is good enough for all known systems.
e6aa42 ·* (If your compiler itself needs names to be unique in less than 15·
0530b5 ·* characters, you are out of luck. ·Get a better compiler.)
28495d ·*/
4eaf5a
dfddd9 #ifdef NEED_SHORT_EXTERNAL_NAMES
adfabe #define jpeg_std_error¤ ¤   jStdError
30f9ea #define jpeg_CreateCompress¤jCreaCompress
7ea6b6 #define jpeg_CreateDecompress¤  jCreaDecompress
872068 #define jpeg_destroy_compress¤  jDestCompress
58b8c3 #define jpeg_destroy_decompress¤jDestDecompress
814b43 #define jpeg_stdio_dest¤¤   jStdDest
709738 #define jpeg_stdio_src¤ ¤   jStdSrc
a52072 #define jpeg_set_defaults¤  jSetDefaults
ff61e7 #define jpeg_set_colorspace¤jSetColorspace
834ecb #define jpeg_default_colorspace¤jDefColorspace
848f68 #define jpeg_set_quality¤   jSetQuality
7dd29a #define jpeg_set_linear_quality¤jSetLQuality
1a892d #define jpeg_add_quant_table¤   jAddQuantTable
6e6369 #define jpeg_quality_scaling¤   jQualityScaling
1b296c #define jpeg_simple_progression¤jSimProgress
88039c #define jpeg_suppress_tables¤   jSuppressTables
a2bcf1 #define jpeg_alloc_quant_table¤ jAlcQTable
050455 #define jpeg_alloc_huff_table¤  jAlcHTable
da7062 #define jpeg_start_compress¤jStrtCompress
bd922a #define jpeg_write_scanlines¤   jWrtScanlines
4b516d #define jpeg_finish_compress¤   jFinCompress
c321e8 #define jpeg_write_raw_data¤jWrtRawData
7d9c97 #define jpeg_write_marker¤  jWrtMarker
dcd46b #define jpeg_write_tables¤  jWrtTables
67acdd #define jpeg_read_header¤   jReadHeader
3223d3 #define jpeg_start_decompress¤  jStrtDecompress
b3fbc6 #define jpeg_read_scanlines¤jReadScanlines
8aa475 #define jpeg_finish_decompress¤ jFinDecompress
4264ac #define jpeg_read_raw_data¤ jReadRawData
6f5b9c #define jpeg_has_multiple_scans¤jHasMultScn
05f2b9 #define jpeg_start_output¤  jStrtOutput
90abab #define jpeg_finish_output¤ jFinOutput
62f25f #define jpeg_input_complete¤jInComplete
b483bf #define jpeg_new_colormap¤  jNewCMap
c731a4 #define jpeg_consume_input¤ jConsumeInput
6b49a8 #define jpeg_calc_output_dimensions¤jCalcDimensions
b4e645 #define jpeg_set_marker_processor¤  jSetMarker
181312 #define jpeg_read_coefficients¤ jReadCoefs
2aa1ce #define jpeg_write_coefficients¤jWrtCoefs
98e131 #define jpeg_copy_critical_parameters¤  jCopyCrit
c170e8 #define jpeg_abort_compress¤jAbrtCompress
c64300 #define jpeg_abort_decompress¤  jAbrtDecompress
284757 #define jpeg_abort¤ ¤   jAbort
6e03bf #define jpeg_destroy¤   ¤   jDestroy
b4ee1b #define jpeg_resync_to_restart¤ jResyncRestart
fa5892 #endif /* NEED_SHORT_EXTERNAL_NAMES */
06af5a
00af5a
ac32c1 /* Default error-management setup */
72a560 EXTERN(struct jpeg_error_mgr *) jpeg_std_error
48d9ec ¤   JPP((struct jpeg_error_mgr * err));
e0af5a
0f23da /* Initialization of JPEG compression objects.
f2b219 ·* jpeg_create_compress() and jpeg_create_decompress() are the exported
3cd64a ·* names that applications should call. ·These expand to calls on
dd2066 ·* jpeg_CreateCompress and jpeg_CreateDecompress with additional information
797b80 ·* passed for version mismatch checking.
bf5cfa ·* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
e4495d ·*/
--0031 00047cb78d040100042 Page 13 of jpeglib.h
86a289 #define jpeg_create_compress(cinfo) \
d4e674 ····jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
8c93ea ¤   ¤   ¤   (size_t) sizeof(struct jpeg_compress_struct))
331d2a #define jpeg_create_decompress(cinfo) \
97d20a ····jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
5fc11a ¤   ¤   ¤   ··(size_t) sizeof(struct jpeg_decompress_struct))
7221e7 EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
2a92d4 ¤   ¤   ¤   ¤   ······int version, size_t structsize));
2103fc EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
2d3859 ¤   ¤   ¤   ¤   ¤   int version, size_t structsize));
a5e97a /* Destruction of JPEG compression objects */
16a936 EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
66030c EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
74af5a
022059 /* Standard data source and destination managers: stdio streams. */
6c21f2 /* Caller is responsible for opening the file before and closing after. */
f42569 EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
b4c495 EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
9faf5a
2e248b /* Default parameter setup for compression */
76be06 EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
38c27d /* Compression parameter setup aids */
6c8a65 EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
ec9433 ¤   ¤   ¤   ¤   ······J_COLOR_SPACE colorspace));
b182f7 EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
27811b EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
b9b3aa ¤   ¤   ¤   ¤   ···boolean force_baseline));
84ea21 EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
18bbaf ¤   ¤   ¤   ¤   ¤   ··int scale_factor,
56e99a ¤   ¤   ¤   ¤   ¤   ··boolean force_baseline));
821b95 EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
a3e734 ¤   ¤   ¤   ¤   ·······const unsigned int *basic_table,
bb24bb ¤   ¤   ¤   ¤   ·······int scale_factor,
cd8e1c ¤   ¤   ¤   ¤   ·······boolean force_baseline));
7741ce EXTERN(int) jpeg_quality_scaling JPP((int quality));
8c83e7 EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
537a29 EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
753037 ¤   ¤   ¤   ¤   ·······boolean suppress));
1ff84d EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
93d3da EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
33af5a
13f521 /* Main entry points for compression */
3a318d EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
acc0b0 ¤   ¤   ¤   ¤   ······boolean write_all_tables));
47f4e8 EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
c5f764 ¤   ¤   ¤   ¤   ¤   ·····JSAMPARRAY scanlines,
af20a4 ¤   ¤   ¤   ¤   ¤   ·····JDIMENSION num_lines));
e476d9 EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
04af5a
0991d5 /* Replaces jpeg_write_scanlines when writing raw downsampled data. */
f41eb4 EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
9403c3 ¤   ¤   ¤   ¤   ¤   ····JSAMPIMAGE data,
012809 ¤   ¤   ¤   ¤   ¤   ····JDIMENSION num_lines));
e7af5a
904a3b /* Write a special marker. ·See libjpeg.doc concerning safe usage. */
5e041a EXTERN(void) jpeg_write_marker
85191a ¤   JPP((j_compress_ptr cinfo, int marker,
7fdaf8 ¤   ·····const JOCTET * dataptr, unsigned int datalen));
2aaf5a
9c8ede /* Alternate compression function: just write an abbreviated table file */
403e91 EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
bfaf5a
036dc7 /* Decompression startup: read start of JPEG datastream to see what's there */
2068e5 EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
9ddd98 ¤   ¤   ¤   ¤   ··boolean require_image));
42d6b9 /* Return value is one of: */
60905d #define JPEG_SUSPENDED¤ ¤   0 /* Suspended due to lack of input data */
740cf2 #define JPEG_HEADER_OK¤ ¤   1 /* Found valid image datastream */
012282 #define JPEG_HEADER_TABLES_ONLY¤2 /* Found valid table-specs-only datastream */
109dcd /* If you pass require_image = TRUE (normal case), you need not check for
a02cec ·* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
4766f6 ·* JPEG_SUSPENDED is only possible if you use a data source module that can
--9ffb 000c2da050f40100042 Page 14 of jpeglib.h
5c566f ·* give a suspension return (the stdio source module doesn't).
8a495d ·*/
71af5a
1c4a03 /* Main entry points for decompression */
129a18 EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
41699a EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
bf212e ¤   ¤   ¤   ¤   ¤   ····JSAMPARRAY scanlines,
ec4cd1 ¤   ¤   ¤   ¤   ¤   ····JDIMENSION max_lines));
2d8ecb EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
f9af5a
87eb9c /* Replaces jpeg_read_scanlines when reading raw downsampled data. */
80418c EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
c93240 ¤   ¤   ¤   ¤   ¤   ···JSAMPIMAGE data,
4ba159 ¤   ¤   ¤   ¤   ¤   ···JDIMENSION max_lines));
4daf5a
28bb3f /* Additional entry points for buffered-image mode. */
376c10 EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
5fff0f EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
5ff055 ¤   ¤   ¤   ¤   ·······int scan_number));
12f668 EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
83a0a3 EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
450c2e EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
b3e34a EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
62d6b9 /* Return value is one of: */
431fd9 /* #define JPEG_SUSPENDED¤  0 ···Suspended due to lack of input data */
ddbaf3 #define JPEG_REACHED_SOS¤   1 /* Reached start of new scan */
3eaf8c #define JPEG_REACHED_EOI¤   2 /* Reached end of image */
77fa7c #define JPEG_ROW_COMPLETED¤ 3 /* Completed one iMCU row */
d8a9fd #define JPEG_SCAN_COMPLETED¤4 /* Completed last iMCU row of a scan */
eeaf5a
ac2257 /* Precalculate output dimensions for current decompression parameters. */
4abdde EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
34af5a
ee2d8d /* Install a special processing method for COM or APPn markers. */
946660 EXTERN(void) jpeg_set_marker_processor
f27e84 ¤   JPP((j_decompress_ptr cinfo, int marker_code,
6bc788 ¤   ·····jpeg_marker_parser_method routine));
8caf5a
37a0c7 /* Read or write raw DCT coefficients --- useful for lossless transcoding. */
c9e45c EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
fd3469 EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
0ad3e9 ¤   ¤   ¤   ¤   ¤   ··jvirt_barray_ptr * coef_arrays));
e1b5aa EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
be051d ¤   ¤   ¤   ¤   ¤   ¤   j_compress_ptr dstinfo));
2eaf5a
283e1d /* If you choose to abort compression or decompression before completing
a15836 ·* jpeg_finish_(de)compress, then you need to clean up to release memory,
deb41b ·* temporary files, etc. ·You can just call jpeg_destroy_(de)compress
0436bb ·* if you're done with the JPEG object, but if you want to clean it up and
98dffa ·* reuse it, call this:
27495d ·*/
5461c0 EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
00f3e5 EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
edaf5a
c040d0 /* Generic versions of jpeg_abort and jpeg_destroy that work on either
8be1b4 ·* flavor of JPEG object. ·These may be more convenient in some places.
55495d ·*/
02072f EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
809487 EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
dbaf5a
7ba440 /* Default restart-marker-resync procedure for use by data source modules */
9a0b23 EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
18a84a ¤   ¤   ¤   ¤   ¤   ····int desired));
aeaf5a
c0af5a
21e856 /* These marker codes are exported since applications and data source modules
adc06b ·* are likely to want to use them.
1a495d ·*/
f0af5a
fca64c #define JPEG_RST0¤  0xD0¤   /* RST0 marker code */
1f9528 #define JPEG_EOI¤   0xD9¤   /* EOI marker code */
c281c3 #define JPEG_APP0¤  0xE0¤   /* APP0 marker code */
--6db7 0015918df9f40100042 Page 15 of jpeglib.h
7f66d1 #define JPEG_COM¤   0xFE¤   /* COM marker code */
0baf5a
42af5a
8eba3f /* If we have a brain-damaged compiler that emits warnings (or worse, errors)
457794 ·* for structure definitions that are never filled in, keep it quiet by
10d5f2 ·* supplying dummy definitions for the various substructures.
35495d ·*/
35af5a
898264 #ifdef INCOMPLETE_TYPES_BROKEN
e168d9 #ifndef JPEG_INTERNALS¤ ¤   /* will be defined in jpegint.h */
6d098d struct jvirt_sarray_control { long dummy; };
6830b8 struct jvirt_barray_control { long dummy; };
bb4914 struct jpeg_comp_master { long dummy; };
507afe struct jpeg_c_main_controller { long dummy; };
23162b struct jpeg_c_prep_controller { long dummy; };
e9624d struct jpeg_c_coef_controller { long dummy; };
6752cf struct jpeg_marker_writer { long dummy; };
527015 struct jpeg_color_converter { long dummy; };
8fa947 struct jpeg_downsampler { long dummy; };
c80eb7 struct jpeg_forward_dct { long dummy; };
074429 struct jpeg_entropy_encoder { long dummy; };
e07c16 struct jpeg_decomp_master { long dummy; };
bc5951 struct jpeg_d_main_controller { long dummy; };
4741e2 struct jpeg_d_coef_controller { long dummy; };
2644d1 struct jpeg_d_post_controller { long dummy; };
dfc419 struct jpeg_input_controller { long dummy; };
ba1990 struct jpeg_marker_reader { long dummy; };
15679c struct jpeg_entropy_decoder { long dummy; };
df311f struct jpeg_inverse_dct { long dummy; };
01d760 struct jpeg_upsampler { long dummy; };
1e05fe struct jpeg_color_deconverter { long dummy; };
20cc9c struct jpeg_color_quantizer { long dummy; };
22ee3e #endif /* JPEG_INTERNALS */
1732fd #endif /* INCOMPLETE_TYPES_BROKEN */
bcaf5a
a6af5a
0738e5 /*
8f1c3f ·* The JPEG library modules define JPEG_INTERNALS before including this file.
4ceace ·* The internal structure declarations are read only when that is true.
40ebf2 ·* Applications using the library should not include jpegint.h, but may wish
a12b35 ·* to include jerror.h.
bc495d ·*/
94af5a
2b9642 #ifdef JPEG_INTERNALS
06bfef #include "jpegint.h"¤   ¤   /* fetch private declarations */
b4c79a #include "jerror.h"¤¤   /* fetch error codes too */
227454 #endif
41af5a
59af72 #endif /* JPEGLIB_H */
--457d 0009212c9b840100043 Page 1 of jpegtran.c
bc38e5 /*
85dbbe ·* jpegtran.c
ef775e ·*
dfc561 ·* Copyright (C) 1995-1996, Thomas G. Lane.
fffb07 ·* This file is part of the Independent JPEG Group's software.
26a0d6 ·* For conditions of distribution and use, see the accompanying README file.
93775e ·*
fd1be3 ·* This file contains a command-line user interface for JPEG transcoding.
a52af2 ·* It is very similar to cjpeg.c, but provides lossless transcoding between
f285c7 ·* different JPEG file formats.
48495d ·*/
10af5a
627409 #include "cdjpeg.h"¤¤   /* Common decls for cjpeg/djpeg applications */
8e3146 #include "jversion.h"¤  ¤   /* for version message */
aeaf5a
542caf #ifdef USE_CCOMMAND¤¤   /* command-line reader for Macintosh */
742aa1 #ifdef __MWERKS__
eb54f8 #include <SIOUX.h> ·············/* Metrowerks needs this */
af28c9 #include <console.h>¤   ¤   /* ... and this */
dd7454 #endif
cdfc7e #ifdef THINK_C
733d29 #include <console.h>¤   ¤   /* Think declares it here */
eb7454 #endif
e37454 #endif
01af5a
08af5a
db38e5 /*
1f8251 ·* Argument-parsing code.
9e5719 ·* The switch parser is designed to be useful with DOS-style command line
e098bb ·* syntax, ie, intermixed switches and file names, where only the switches
3685e5 ·* to the left of a given file name affect processing of that file.
69913d ·* The main program in this file doesn't actually use this capability...
5c495d ·*/
55af5a
ddaf5a
ea3200 static const char * progname;¤  /* program name for error messages */
34a4e5 static char * outfilename;¤ /* for -outfile switch */
d7af5a
76af5a
88afad LOCAL(void)
fa1148 usage (void)
38b5d5 /* complain about bad command line */
79bb36 {
4cc8af ··fprintf(stderr, "usage: %s [switches] ", progname);
284f53 #ifdef TWO_FILE_COMMANDLINE
4479a1 ··fprintf(stderr, "inputfile outputfile\n");
a4db21 #else
567dd4 ··fprintf(stderr, "[inputfile]\n");
f57454 #endif
d6af5a
779cf5 ··fprintf(stderr, "Switches (names may be abbreviated):\n");
a026f0 #ifdef ENTROPY_OPT_SUPPORTED
d31294 ··fprintf(stderr, " ·-optimize ·····Optimize Huffman table (smaller file, but s¶
815b76 low compression)\n");
fb7454 #endif
a968ad #ifdef C_PROGRESSIVE_SUPPORTED
90df2f ··fprintf(stderr, " ·-progressive ··Create progressive JPEG file\n");
a37454 #endif
037408 ··fprintf(stderr, "Switches for advanced users:\n");
633a03 ··fprintf(stderr, " ·-restart N ····Set restart interval in rows, or in blocks ¶
b2ff37 with B\n");
f27d52 ··fprintf(stderr, " ·-maxmemory N ··Maximum memory to use (in kbytes)\n");
d39a4b ··fprintf(stderr, " ·-outfile name ·Specify name for output file\n");
0ed40d ··fprintf(stderr, " ·-verbose ·or ·-debug ··Emit debug output\n");
6a3554 ··fprintf(stderr, "Switches for wizards:\n");
4c8f52 #ifdef C_ARITH_CODING_SUPPORTED
65e738 ··fprintf(stderr, " ·-arithmetic ···Use arithmetic coding\n");
697454 #endif
d2da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
0db2d6 ··fprintf(stderr, " ·-scans file ···Create multi-scan JPEG per script file\n");
737454 #endif
92870b ··exit(EXIT_FAILURE);
--be9c 0005af560c840100043 Page 2 of jpegtran.c
7aefe6 }
46af5a
8eaf5a
99aa6a LOCAL(int)
b106da parse_switches (j_compress_ptr cinfo, int argc, char **argv,
967e0f ¤   ¤   int last_file_arg_seen, boolean for_real)
1144b9 /* Parse optional switches.
e02a35 ·* Returns argv[] index of first file-name argument (== argc if none).
a75c8e ·* Any file names with indexes <= last_file_arg_seen are ignored;
21a5c3 ·* they have presumably been processed in a previous iteration.
91cddf ·* (Pass 0 for last_file_arg_seen on the first or only iteration.)
fcab40 ·* for_real is FALSE on the first (dummy) pass; we may skip any expensive
3945f6 ·* processing.
fb495d ·*/
36bb36 {
869a4b ··int argn;
f07cfe ··char * arg;
6f39c7 ··boolean simple_progressive;
fa2daa ··char * scansarg = NULL;¤  /* saves -scans parm if any */
20af5a
6f7654 ··/* Set up default JPEG parameters. */
222c03 ··simple_progressive = FALSE;
974ec3 ··outfilename = NULL;
db39da ··cinfo->err->trace_level = 0;
f4af5a
804e7b ··/* Scan command line options, adjust parameters */
cfaf5a
a72949 ··for (argn = 1; argn < argc; argn++) {
02c53a ····arg = argv[argn];
b8043a ····if (*arg != '-') {
3807cf ······/* Not a switch, must be a file name argument */
7d25f6 ······if (argn <= last_file_arg_seen) {
cdb616 ¤   outfilename = NULL;¤/* -outfile applies to just one input file */
06148e ¤   continue;¤  ¤   /* ignore this name if previously processed */
6542cc ······}
97db81 ······break;¤   ¤   ¤   /* else done parsing switches */
de6fe7 ····}
dae3e7 ····arg++;¤ ¤   ¤   /* advance past switch marker character */
a9af5a
2afa9b ····if (keymatch(arg, "arithmetic", 1)) {
2ec0e5 ······/* Use arithmetic coding. */
218f52 #ifdef C_ARITH_CODING_SUPPORTED
39e9ae ······cinfo->arith_code = TRUE;
99db21 #else
baa45d ······fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
379d17 ¤   ······progname);
6fa026 ······exit(EXIT_FAILURE);
a87454 #endif
00af5a
3c35fe ····} else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
0ce33e ······/* Enable debug printouts. */
c05945 ······/* On first -d, print version identification */
2eb5a1 ······static boolean printed_version = FALSE;
edaf5a
750005 ······if (! printed_version) {
eadc02 ¤   fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
ab833f ¤   ¤   JVERSION, JCOPYRIGHT);
81e71c ¤   printed_version = TRUE;
de42cc ······}
f4d376 ······cinfo->err->trace_level++;
0eaf5a
9a79db ····} else if (keymatch(arg, "maxmemory", 3)) {
e0ffbd ······/* Maximum memory in Kb (or Mb with 'm'). */
f7ef68 ······long lval;
ae70f2 ······char ch = 'x';
bdaf5a
7aab9e ······if (++argn >= argc)¤  /* advance to next argument */
00b16f ¤   usage();
65263e ······if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
9db16f ¤   usage();
3f9295 ······if (ch == 'm' || ch == 'M')
5a5741 ¤   lval *= 1000L;
--1a35 000c1e410af40100043 Page 3 of jpegtran.c
59be19 ······cinfo->mem->max_memory_to_use = lval * 1000L;
b7af5a
14c29e ····} else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
0a9a72 ······/* Enable entropy parm optimization. */
1326f0 #ifdef ENTROPY_OPT_SUPPORTED
7826ca ······cinfo->optimize_coding = TRUE;
47db21 #else
2b5034 ······fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
a19d17 ¤   ······progname);
bda026 ······exit(EXIT_FAILURE);
597454 #endif
55af5a
0e22d4 ····} else if (keymatch(arg, "outfile", 4)) {
63e452 ······/* Set output file name. */
deab9e ······if (++argn >= argc)¤  /* advance to next argument */
fcb16f ¤   usage();
75cb41 ······outfilename = argv[argn];¤/* save it away for later use */
51af5a
449e0d ····} else if (keymatch(arg, "progressive", 1)) {
114d58 ······/* Select simple progressive mode. */
a068ad #ifdef C_PROGRESSIVE_SUPPORTED
497db0 ······simple_progressive = TRUE;
914785 ······/* We must postpone execution until num_components is known. */
c2db21 #else
c639f2 ······fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
1d9d17 ¤   ······progname);
b8a026 ······exit(EXIT_FAILURE);
567454 #endif
c6af5a
522e85 ····} else if (keymatch(arg, "restart", 1)) {
828872 ······/* Restart interval in MCU rows (or in MCUs with 'b'). */
37ef68 ······long lval;
bd70f2 ······char ch = 'x';
3caf5a
c6ab9e ······if (++argn >= argc)¤  /* advance to next argument */
d3b16f ¤   usage();
65263e ······if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
07b16f ¤   usage();
931ecf ······if (lval < 0 || lval > 65535L)
7db16f ¤   usage();
727c40 ······if (ch == 'b' || ch == 'B') {
677ae4 ¤   cinfo->restart_interval = (unsigned int) lval;
9890e5 ¤   cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
d3cfc7 ······} else {
ee0e03 ¤   cinfo->restart_in_rows = (int) lval;
2d600e ¤   /* restart_interval will be computed during startup */
f042cc ······}
bfaf5a
6341c2 ····} else if (keymatch(arg, "scans", 2)) {
5b5ecc ······/* Set scan script. */
0eda64 #ifdef C_MULTISCAN_FILES_SUPPORTED
44ab9e ······if (++argn >= argc)¤  /* advance to next argument */
33b16f ¤   usage();
12c4da ······scansarg = argv[argn];
036e0a ······/* We must postpone reading the file in case -progressive appears. */
f1db21 #else
af76ee ······fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
7f9d17 ¤   ······progname);
03a026 ······exit(EXIT_FAILURE);
017454 #endif
7aaf5a
936a79 ····} else {
73391a ······usage();¤ ¤   ¤   /* bogus switch */
766fe7 ····}
f8df1c ··}
0aaf5a
18cd0d ··/* Post-switch-scanning cleanup */
3caf5a
63e7ff ··if (for_real) {
a7af5a
9868ad #ifdef C_PROGRESSIVE_SUPPORTED
c1c348 ····if (simple_progressive)¤/* process -progressive; -scans can override */
--1c24 0007376b0da40100043 Page 4 of jpegtran.c
b01768 ······jpeg_simple_progression(cinfo);
e07454 #endif
6caf5a
e2da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
e8b959 ····if (scansarg != NULL)¤  /* process -scans if it was present */
3f3b85 ······if (! read_scan_script(cinfo, scansarg))
5eb16f ¤   usage();
077454 #endif
6fdf1c ··}
71af5a
14ee59 ··return argn;¤ ¤   ¤   /* return index of next arg (file name) */
1aefe6 }
57af5a
51af5a
3438e5 /*
2eeb85 ·* The main program.
3d495d ·*/
2caf5a
564d2f int
2d73e2 main (int argc, char **argv)
e2bb36 {
df38ae ··struct jpeg_decompress_struct srcinfo;
33e0a7 ··struct jpeg_compress_struct dstinfo;
c33401 ··struct jpeg_error_mgr jsrcerr, jdsterr;
9ad62a #ifdef PROGRESS_REPORT
023536 ··struct cdjpeg_progress_mgr progress;
ba7454 #endif
51454a ··jvirt_barray_ptr * coef_arrays;
9cef7d ··int file_index;
809697 ··FILE * input_file;
1a1d0e ··FILE * output_file;
a7af5a
13209a ··/* On Mac, fetch a command line. */
168a88 #ifdef USE_CCOMMAND
61ad02 ··argc = ccommand(&argv);
cc7454 #endif
eeaf5a
36eb33 ··progname = argv[0];
4c20c8 ··if (progname == NULL || progname[0] == 0)
4bb88b ····progname = "jpegtran";¤ /* in case C library doesn't provide it */
ceaf5a
95dda5 ··/* Initialize the JPEG decompression object with default error handling. */
4099ea ··srcinfo.err = jpeg_std_error(&jsrcerr);
af79ff ··jpeg_create_decompress(&srcinfo);
a59962 ··/* Initialize the JPEG compression object with default error handling. */
f94f7b ··dstinfo.err = jpeg_std_error(&jdsterr);
33d3d7 ··jpeg_create_compress(&dstinfo);
59af5a
72bf5f ··/* Now safe to enable signal catcher.
fb8577 ···* Note: we assume only the decompression object will have virtual arrays.
a9f9a6 ···*/
13b90e #ifdef NEED_SIGNAL_CATCHER
3bd92c ··enable_signal_catcher((j_common_ptr) &srcinfo);
1b7454 #endif
a0af5a
3595b0 ··/* Scan command line to find file names.
26c39e ···* It is convenient to use just one switch-parsing routine, but the switch
b34941 ···* values read here are ignored; we will rescan the switches after opening
0dc4f2 ···* the input file.
5df9a6 ···*/
a9af5a
6e675f ··file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
1c3eaa ··jsrcerr.trace_level = jdsterr.trace_level;
9f95a1 ··srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
84af5a
244f53 #ifdef TWO_FILE_COMMANDLINE
3d4468 ··/* Must have either -outfile switch or explicit output file name */
b817f4 ··if (outfilename == NULL) {
85ea65 ····if (file_index != argc-2) {
663b59 ······fprintf(stderr, "%s: must name one input and one output file\n",
d69d17 ¤   ······progname);
738e9f ······usage();
--0e8e 00092e1ab0340100043 Page 5 of jpegtran.c
9f6fe7 ····}
f064f7 ····outfilename = argv[file_index+1];
7f49d8 ··} else {
d8f7a9 ····if (file_index != argc-1) {
423b59 ······fprintf(stderr, "%s: must name one input and one output file\n",
4f9d17 ¤   ······progname);
698e9f ······usage();
af6fe7 ····}
afdf1c ··}
0cdb21 #else
6dd20f ··/* Unix style: expect zero or one file name */
7a2f67 ··if (file_index < argc-1) {
237812 ····fprintf(stderr, "%s: only one input file\n", progname);
192b21 ····usage();
45df1c ··}
62a164 #endif /* TWO_FILE_COMMANDLINE */
d1af5a
3af8b9 ··/* Open the input file. */
1aae84 ··if (file_index < argc) {
f2f7ad ····if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
758c80 ······fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
9fa026 ······exit(EXIT_FAILURE);
786fe7 ····}
9a49d8 ··} else {
83a011 ····/* default input file is stdin */
d63b24 ····input_file = read_stdin();
98df1c ··}
b4af5a
e518be ··/* Open the output file. */
3c844e ··if (outfilename != NULL) {
03af59 ····if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
49a61a ······fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
3aa026 ······exit(EXIT_FAILURE);
0e6fe7 ····}
a049d8 ··} else {
103bda ····/* default output file is stdout */
29498e ····output_file = write_stdout();
34df1c ··}
c5af5a
66d62a #ifdef PROGRESS_REPORT
80015a ··start_progress_monitor((j_common_ptr) &dstinfo, &progress);
7a7454 #endif
d4af5a
7bf3a8 ··/* Specify data source for decompression */
8cdf55 ··jpeg_stdio_src(&srcinfo, input_file);
36af5a
7181d7 ··/* Read file header */
dd31b4 ··(void) jpeg_read_header(&srcinfo, TRUE);
76af5a
a54e7d ··/* Read source file as DCT coefficients */
5c5fd4 ··coef_arrays = jpeg_read_coefficients(&srcinfo);
47af5a
9b3390 ··/* Initialize destination compression parameters from source values */
0916f3 ··jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
0eaf5a
61cbe6 ··/* Adjust default compression parameters by re-parsing the options */
b3fe4b ··file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
71af5a
f8e6cf ··/* Specify data destination for compression */
002dfd ··jpeg_stdio_dest(&dstinfo, output_file);
37af5a
38a7a4 ··/* Start compressor */
4c8712 ··jpeg_write_coefficients(&dstinfo, coef_arrays);
62af5a
ca3114 ··/* ought to copy source comments here... */
b5af5a
22e485 ··/* Finish compression and release memory */
9e4ec8 ··jpeg_finish_compress(&dstinfo);
573ad0 ··jpeg_destroy_compress(&dstinfo);
ac4ead ··(void) jpeg_finish_decompress(&srcinfo);
334e38 ··jpeg_destroy_decompress(&srcinfo);
92af5a
--ca9c 001d231802d40100043 Page 6 of jpegtran.c
cca791 ··/* Close files, if we opened them */
703b8d ··if (input_file != stdin)
965ee3 ····fclose(input_file);
89ae7e ··if (output_file != stdout)
90729a ····fclose(output_file);
e5af5a
1ed62a #ifdef PROGRESS_REPORT
21e920 ··end_progress_monitor((j_common_ptr) &dstinfo);
8e7454 #endif
6baf5a
69b3af ··/* All done. */
87dce0 ··exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
06241d ··return 0;¤¤   ¤   /* suppress no-return-value warnings */
d2efe6 }
--3780 000491cb70d40100044 Page 1 of jquant1.c
bc38e5 /*
089ed0 ·* jquant1.c
21775e ·*
50a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
14fb07 ·* This file is part of the Independent JPEG Group's software.
4fa0d6 ·* For conditions of distribution and use, see the accompanying README file.
f6775e ·*
201da9 ·* This file contains 1-pass color quantization (color mapping) routines.
e5b304 ·* These routines provide mapping to a fixed color map using equally spaced
02a4e5 ·* color values. ·Optional Floyd-Steinberg or ordered dithering is available.
ad495d ·*/
69af5a
ec2bb6 #define JPEG_INTERNALS
f736a7 #include "jinclude.h"
cd6c8f #include "jpeglib.h"
29af5a
95d7d7 #ifdef QUANT_1PASS_SUPPORTED
2faf5a
90af5a
9838e5 /*
c94711 ·* The main purpose of 1-pass quantization is to provide a fast, if not very
9f1bf9 ·* high quality, colormapped output capability. ·A 2-pass quantizer usually
c407c3 ·* gives better visual quality; however, for quantized grayscale output this
4bfa66 ·* quantizer is perfectly adequate. ·Dithering is highly recommended with this
c23a42 ·* quantizer, though you can turn it off if you really want to.
e3775e ·*
83e853 ·* In 1-pass quantization the colormap must be chosen in advance of seeing the
74461f ·* image. ·We use a map consisting of all combinations of Ncolors[i] color
11f19c ·* values for the i'th component. ·The Ncolors[] values are chosen so that
190be3 ·* their product, the total number of colors, is no more than that requested.
9ee2e2 ·* (In most cases, the product will be somewhat less.)
5b775e ·*
b8e8e8 ·* Since the colormap is orthogonal, the representative value for each color
3cd6d6 ·* component can be determined without considering the other components;
79af96 ·* then these indexes can be combined into a colormap index by a standard
a21a3c ·* N-dimensional-array-subscript calculation. ·Most of the arithmetic involved
886a67 ·* can be precalculated and stored in the lookup table colorindex[].
174c4b ·* colorindex[i][j] maps pixel value j in component i to the nearest
3f42bf ·* representative value (grid plane) for that component; this index is
f46c9b ·* multiplied by the array stride for component i, so that the
7f699d ·* index of the colormap entry closest to a given pixel value is just
1451f2 ·* ···sum( colorindex[component-number][pixel-component-value] )
8c4f3f ·* Aside from being fast, this scheme allows for variable spacing between
95e502 ·* representative values with no additional lookup cost.
ce775e ·*
c4926a ·* If gamma correction has been applied in color conversion, it might be wise
6c0363 ·* to adjust the color grid spacing so that the representative colors are
344d09 ·* equidistant in linear space. ·At this writing, gamma correction is not
f38999 ·* implemented by jdcolor, so nothing is done here.
d8495d ·*/
62af5a
90af5a
a6e65d /* Declarations for ordered dithering.
11775e ·*
88d608 ·* We use a standard 16x16 ordered dither array. ·The basic concept of ordered
9c2ab8 ·* dithering is described in many references, for instance Dale Schumacher's
ab96cd ·* chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
5c11b3 ·* In place of Schumacher's comparisons against a "threshold" value, we add a
c6040e ·* "dither" value to the input pixel and then round the result to the nearest
6d2ffe ·* output value. ·The dither value is equivalent to (0.5 - threshold) times
92b569 ·* the distance between output values. ·For ordered dithering, we assume that
d6786a ·* the output colors are equally spaced; if not, results will probably be
6c29a6 ·* worse, since the dither may be too much or too little at a given point.
c3775e ·*
e0077d ·* The normal calculation would be to form pixel value + dither, range-limit
1db396 ·* this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
d7437c ·* We can skip the separate range-limiting step by extending the colorindex
9fe9a0 ·* table in both directions.
92495d ·*/
09af5a
1dc676 #define ODITHER_SIZE ·16¤   /* dimension of dither matrix */
49f6d2 /* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
--e123 00095bdee5c40100044 Page 2 of jquant1.c
516e27 #define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE)¤  /* # cells in matrix */
ca1d6f #define ODITHER_MASK ·(ODITHER_SIZE-1) /* mask for wrapping around counters */
57af5a
26b50d typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
09cf85 typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
7baf5a
717472 static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
ce1f2e ··/* Bayer's order-4 dither array. ·Generated by the code given in
72ceff ···* Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
3930fb ···* The values in this array must range from 0 to ODITHER_CELLS-1.
50f9a6 ···*/
388687 ··{ ··0,192, 48,240, 12,204, 60,252, ·3,195, 51,243, 15,207, 63,255 },
cccc91 ··{ 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
8e16e0 ··{ ·32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
4d2f90 ··{ 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
58fd0e ··{ ··8,200, 56,248, ·4,196, 52,244, 11,203, 59,251, ·7,199, 55,247 },
b9bd20 ··{ 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
8b3987 ··{ ·40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
1fe736 ··{ 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
9862fc ··{ ··2,194, 50,242, 14,206, 62,254, ·1,193, 49,241, 13,205, 61,253 },
3cc7e8 ··{ 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
6b763d ··{ ·34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
c94e1c ··{ 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
3a5726 ··{ ·10,202, 58,250, ·6,198, 54,246, ·9,201, 57,249, ·5,197, 53,245 },
5bd53f ··{ 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
1ad114 ··{ ·42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
9c81f4 ··{ 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
f282f7 };
92af5a
d1af5a
223996 /* Declarations for Floyd-Steinberg dithering.
40775e ·*
630ebc ·* Errors are accumulated into the array fserrors[], at a resolution of
59045f ·* 1/16th of a pixel count. ·The error at a given pixel is propagated
dbe34a ·* to its not-yet-processed neighbors using the standard F-S fractions,
c70174 ·*¤ ¤   ...¤(here)¤ 7/16
d51217 ·*¤ ¤   3/16¤   5/16¤   1/16
535479 ·* We work left-to-right on even rows, right-to-left on odd rows.
9c775e ·*
03ff68 ·* We can get away with a single array (holding one row's worth of errors)
a0101d ·* by using it to store the current row's errors at pixel columns not yet
f62fdd ·* processed, but the next row's errors at columns already processed. ·We
a5aff2 ·* need only a few extra variables to hold the errors immediately around the
64aa4f ·* current column. ·(If we are lucky, those variables are in registers, but
09d34b ·* even if not, they're probably cheaper to access than array elements are.)
cb775e ·*
4ca108 ·* The fserrors[] array is indexed [component#][position].
d59033 ·* We provide (#columns + 2) entries per component; the extra entry at each
f8ce0d ·* end saves us from special-casing the first and last pixels.
34775e ·*
7b00a1 ·* Note: on a wide image, we might not have enough room in a PC's near data
626733 ·* segment to hold the error array; so it is allocated with alloc_large.
3a495d ·*/
aaaf5a
676f80 #if BITS_IN_JSAMPLE == 8
bb3409 typedef INT16 FSERROR;¤ ¤   /* 16 bits should be enough */
cb96fe typedef int LOCFSERROR;¤¤   /* use 'int' for calculation temps */
86db21 #else
6c38b3 typedef INT32 FSERROR;¤ ¤   /* may need more than 16 bits */
500918 typedef INT32 LOCFSERROR;¤  /* be sure calculation temps are big enough */
db7454 #endif
e4af5a
41ed71 typedef FSERROR FAR *FSERRPTR;¤ /* pointer to error array (in FAR storage!) */
64af5a
88af5a
acdedc /* Private subobject */
daaf5a
7a9dd1 #define MAX_Q_COMPS 4¤  ¤   /* max components I can handle */
9caf5a
cbf0f7 typedef struct {
027312 ··struct jpeg_color_quantizer pub; /* public fields */
95af5a
--8b6d 0008e4f79cc40100044 Page 3 of jquant1.c
609cb9 ··/* Initially allocated colormap is saved here */
c55ce0 ··JSAMPARRAY sv_colormap;¤  /* The color map as a 2-D pixel array */
da20ee ··int sv_actual;¤   ¤   /* number of entries in use */
3faf5a
3aff20 ··JSAMPARRAY colorindex;¤   /* Precomputed mapping for speed */
199258 ··/* colorindex[i][j] = index of color closest to pixel value j in component i,
8d85e0 ···* premultiplied as described above. ·Since colormap indexes must fit into
250544 ···* JSAMPLEs, the entries of this array will too.
12f9a6 ···*/
90d922 ··boolean is_padded;¤   ¤   /* is the colorindex padded for odither? */
5caf5a
33d0d6 ··int Ncolors[MAX_Q_COMPS];¤/* # of values alloced to each component */
daaf5a
f195c4 ··/* Variables for ordered dithering */
eb346d ··int row_index;¤   ¤   /* cur row's vertical index in dither matrix */
821359 ··ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
6caf5a
023576 ··/* Variables for Floyd-Steinberg dithering */
ae54a3 ··FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
ccf7f0 ··boolean on_odd_row;¤  ¤   /* flag to remember which row we are on */
f3ad8a } my_cquantizer;
69af5a
ae711c typedef my_cquantizer * my_cquantize_ptr;
ebaf5a
39af5a
1f38e5 /*
61aa7f ·* Policy-making subroutines for create_colormap and create_colorindex.
a2fd9b ·* These routines determine the colormap to be used. ·The rest of the module
a1a597 ·* only assumes that the colormap is orthogonal.
b6775e ·*
3eb373 ·* ·* select_ncolors decides how to divvy up the available colors
f86738 ·* ···among the components.
2ee651 ·* ·* output_value defines the set of representative values for a component.
e8c8d9 ·* ·* largest_input_value defines the mapping from input values to
9a11a9 ·* ···representative values for a component.
e2e12a ·* Note that the latter two routines may impose different policies for
794ca1 ·* different components, though this is not currently done.
2d495d ·*/
13af5a
8faf5a
3daa6a LOCAL(int)
f84998 select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
91f33d /* Determine allocation of desired colors to components, */
52afd3 /* and fill in Ncolors[] array to indicate choice. */
e7cbe5 /* Return value is total number of colors (product of Ncolors[] values). */
75bb36 {
1d7a1a ··int nc = cinfo->out_color_components; /* number of color components */
48a79f ··int max_colors = cinfo->desired_number_of_colors;
bbdd8c ··int total_colors, iroot, i, j;
efee35 ··boolean changed;
2d6569 ··long temp;
739017 ··static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
19af5a
c4d36e ··/* We can allocate at least the nc'th root of max_colors per component. */
8834bc ··/* Compute floor(nc'th root of max_colors). */
298a88 ··iroot = 1;
2f565f ··do {
e79d2d ····iroot++;
7ced1f ····temp = iroot;¤  ¤   /* set temp = iroot ** nc */
e0623a ····for (i = 1; i < nc; i++)
c93097 ······temp *= iroot;
128332 ··} while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
1e2084 ··iroot--;¤ ¤   ¤   /* now iroot = floor(root) */
6daf5a
c317aa ··/* Must have at least 2 color values per component */
d50a83 ··if (iroot < 2)
b81023 ····ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
63af5a
c43e39 ··/* Initialize to iroot color values for each component */
d0f519 ··total_colors = 1;
a78862 ··for (i = 0; i < nc; i++) {
8eee5b ····Ncolors[i] = iroot;
--ef37 00004f901c140100044 Page 4 of jquant1.c
e27b34 ····total_colors *= iroot;
d5df1c ··}
035a7e ··/* We may be able to increment the count for one or more components without
b28798 ···* exceeding max_colors, though we know not all can be incremented.
524922 ···* Sometimes, the first component can be incremented more than once!
888b96 ···* (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
60e1f9 ···* In RGB colorspace, try to increment G first, then R, then B.
0cf9a6 ···*/
bd565f ··do {
389939 ····changed = FALSE;
813856 ····for (i = 0; i < nc; i++) {
ad04ce ······j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
c82818 ······/* calculate new total_colors if Ncolors[j] is incremented */
a387bd ······temp = total_colors / Ncolors[j];
4f2830 ······temp *= Ncolors[j]+1;¤/* done in long arith to avoid oflo */
aa8e24 ······if (temp > (long) max_colors)
9d6cbd ¤   break;¤ ¤   ¤   /* won't fit, done with this pass */
72bbc9 ······Ncolors[j]++;¤¤   /* OK, apply the increment */
519887 ······total_colors = (int) temp;
3d5a4e ······changed = TRUE;
bc6fe7 ····}
759af9 ··} while (changed);
ceaf5a
d56204 ··return total_colors;
77efe6 }
22af5a
73af5a
74aa6a LOCAL(int)
e96ac9 output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
1c952f /* Return j'th output value, where j will range from 0 to maxj */
6c7766 /* The output values must fall in 0..MAXJSAMPLE in increasing order */
cabb36 {
9eded1 ··/* We always provide values 0 and MAXJSAMPLE for each component;
b0a40e ···* any additional values are equally spaced between these limits.
101d9e ···* (Forcing the upper and lower values to the limits ensures that
c10230 ···* dithering can't produce a color outside the selected gamut.)
67f9a6 ···*/
8ff305 ··return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
d1efe6 }
3baf5a
acaf5a
3faa6a LOCAL(int)
6804f0 largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
e7b645 /* Return largest input value that should map to j'th output value */
ff3d60 /* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
75bb36 {
aefb01 ··/* Breakpoints are halfway between values returned by output_value */
0513d4 ··return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
44efe6 }
d3af5a
5caf5a
2438e5 /*
2b14db ·* Create the colormap.
4a495d ·*/
d9af5a
eeafad LOCAL(void)
3da9e8 create_colormap (j_decompress_ptr cinfo)
72bb36 {
f0a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
4dd660 ··JSAMPARRAY colormap;¤ ¤   /* Created colormap */
3c591e ··int total_colors;¤¤   /* Number of distinct output colors */
ff8760 ··int i,j,k, nci, blksize, blkdist, ptr, val;
53af5a
8f27d6 ··/* Select number of colors for each component */
557f99 ··total_colors = select_ncolors(cinfo, cquantize->Ncolors);
1baf5a
b13a55 ··/* Report selected color counts */
b3788b ··if (cinfo->out_color_components == 3)
222663 ····TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
571f41 ¤   ·····total_colors, cquantize->Ncolors[0],
e6a9af ¤   ·····cquantize->Ncolors[1], cquantize->Ncolors[2]);
041bd0 ··else
--9460 0007c56971c40100044 Page 5 of jquant1.c
3727d8 ····TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
5aaf5a
2b11c9 ··/* Allocate and fill in the colormap. */
5bc15d ··/* The colors are ordered in the map in standard row-major order, */
5d342b ··/* i.e. rightmost (highest-indexed) color changes most rapidly. */
f7af5a
8df6d4 ··colormap = (*cinfo->mem->alloc_sarray)
1c4144 ····((j_common_ptr) cinfo, JPOOL_IMAGE,
885650 ·····(JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
57af5a
f3348f ··/* blksize is number of adjacent repeated entries for a component */
771ba7 ··/* blkdist is distance between groups of identical entries for a component */
730eba ··blkdist = total_colors;
41af5a
f5f590 ··for (i = 0; i < cinfo->out_color_components; i++) {
63d13f ····/* fill in colormap entries for i'th color component */
43bcab ····nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
58bbe2 ····blksize = blkdist / nci;
ae2017 ····for (j = 0; j < nci; j++) {
21534e ······/* Compute j'th output value (out of nci) for component */
b82d3c ······val = output_value(cinfo, i, j, nci-1);
eb26f3 ······/* Fill in all colormap entries that have this value of this component */
8e6ee2 ······for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
e6ff16 ¤   /* fill in blksize entries beginning at ptr */
85bfb5 ¤   for (k = 0; k < blksize; k++)
ecb127 ¤   ··colormap[i][ptr+k] = (JSAMPLE) val;
3142cc ······}
676fe7 ····}
9f6c0d ····blkdist = blksize;¤ ¤   /* blksize of this color is blkdist of next */
83df1c ··}
6baf5a
a656dd ··/* Save the colormap in private storage,
0a87ad ···* where it will survive color quantization mode changes.
67f9a6 ···*/
d94c48 ··cquantize->sv_colormap = colormap;
b1c018 ··cquantize->sv_actual = total_colors;
4cefe6 }
eaaf5a
60af5a
0e38e5 /*
ceee2c ·* Create the color index table.
0b495d ·*/
88af5a
b6afad LOCAL(void)
01525a create_colorindex (j_decompress_ptr cinfo)
0abb36 {
3aa2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
c4ea12 ··JSAMPROW indexptr;
37d9a1 ··int i,j,k, nci, blksize, val, pad;
d8af5a
5b21c0 ··/* For ordered dither, we pad the color index tables by MAXJSAMPLE in
8a29d0 ···* each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
36854a ···* This is not necessary in the other dithering modes. ·However, we
ff6291 ···* flag whether it was done in case user changes dithering mode.
55f9a6 ···*/
79b022 ··if (cinfo->dither_mode == JDITHER_ORDERED) {
f315a5 ····pad = MAXJSAMPLE*2;
5b357b ····cquantize->is_padded = TRUE;
4b49d8 ··} else {
84349c ····pad = 0;
90fc22 ····cquantize->is_padded = FALSE;
a3df1c ··}
cbaf5a
63b367 ··cquantize->colorindex = (*cinfo->mem->alloc_sarray)
cb4144 ····((j_common_ptr) cinfo, JPOOL_IMAGE,
a3955e ·····(JDIMENSION) (MAXJSAMPLE+1 + pad),
65c68a ·····(JDIMENSION) cinfo->out_color_components);
71af5a
f0348f ··/* blksize is number of adjacent repeated entries for a component */
6fd824 ··blksize = cquantize->sv_actual;
baaf5a
7cf590 ··for (i = 0; i < cinfo->out_color_components; i++) {
--ff04 0007d8815e640100044 Page 6 of jquant1.c
ab06ad ····/* fill in colorindex entries for i'th color component */
49bcab ····nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
f9dbc5 ····blksize = blksize / nci;
f6af5a
206fb2 ····/* adjust colorindex pointers to provide padding at negative indexes. */
271de0 ····if (pad)
180094 ······cquantize->colorindex[i] += MAXJSAMPLE;
c2af5a
3f338f ····/* in loop, val = index of current output value, */
53c855 ····/* and k = largest j that maps to current val */
d2f16e ····indexptr = cquantize->colorindex[i];
604e6f ····val = 0;
e1e998 ····k = largest_input_value(cinfo, i, 0, nci-1);
c6beb0 ····for (j = 0; j <= MAXJSAMPLE; j++) {
455723 ······while (j > k)¤¤   /* advance val if past boundary */
e2f41f ¤   k = largest_input_value(cinfo, i, ++val, nci-1);
f0edaa ······/* premultiply so that no multiplication needed in main processing */
07b80a ······indexptr[j] = (JSAMPLE) (val * blksize);
8a6fe7 ····}
f56198 ····/* Pad at both ends if necessary */
991de0 ····if (pad)
edfd73 ······for (j = 1; j <= MAXJSAMPLE; j++) {
7c12dd ¤   indexptr[-j] = indexptr[0];
8747ff ¤   indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
4942cc ······}
62df1c ··}
e0efe6 }
5aaf5a
c3af5a
b738e5 /*
24fac2 ·* Create an ordered-dither array for a component having ncolors
7fb1ac ·* distinct output values.
c7495d ·*/
8caf5a
6be10c LOCAL(ODITHER_MATRIX_PTR)
17cb7f make_odither_array (j_decompress_ptr cinfo, int ncolors)
3ebb36 {
133fe3 ··ODITHER_MATRIX_PTR odither;
22a62a ··int j,k;
0a0866 ··INT32 num,den;
9aaf5a
e17a9f ··odither = (ODITHER_MATRIX_PTR)
ab3f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
fe071c ¤   ¤   ¤   ¤   SIZEOF(ODITHER_MATRIX));
2070da ··/* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
c20ed2 ···* Hence the dither value for the matrix cell with fill order f
46dee5 ···* (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
246c4d ···* On 16-bit-int machine, be careful to avoid overflow.
dbf9a6 ···*/
43e53b ··den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1));
fc117c ··for (j = 0; j < ODITHER_SIZE; j++) {
ffffb1 ····for (k = 0; k < ODITHER_SIZE; k++) {
13d1cc ······num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
5c6fea ¤   ····* MAXJSAMPLE;
160f96 ······/* Ensure round towards zero despite C's lack of consistency
5158c6 ·······* about rounding negative values in integer division...
39e9f1 ·······*/
735a0c ······odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
da6fe7 ····}
aedf1c ··}
e4de22 ··return odither;
b1efe6 }
1eaf5a
ccaf5a
8638e5 /*
d38a18 ·* Create the ordered-dither tables.
ab01e3 ·* Components having the same number of representative colors may·
e74b08 ·* share a dither table.
9f495d ·*/
c3af5a
93afad LOCAL(void)
7d18ac create_odither_tables (j_decompress_ptr cinfo)
--dbc9 0005f472be840100044 Page 7 of jquant1.c
2cbb36 {
eda2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
6b3fe3 ··ODITHER_MATRIX_PTR odither;
24d516 ··int i, j, nci;
94af5a
2bf590 ··for (i = 0; i < cinfo->out_color_components; i++) {
73bcab ····nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
22b6fd ····odither = NULL;¤¤   /* search for matching prior component */
f9cd1a ····for (j = 0; j < i; j++) {
0cc75b ······if (nci == cquantize->Ncolors[j]) {
54c428 ¤   odither = cquantize->odither[j];
564ed2 ¤   break;
3442cc ······}
ea6fe7 ····}
3b53b5 ····if (odither == NULL)¤   /* need a new table? */
af1599 ······odither = make_odither_array(cinfo, nci);
a2967c ····cquantize->odither[i] = odither;
eedf1c ··}
45efe6 }
82af5a
afaf5a
3038e5 /*
688c2c ·* Map some rows of pixels to the output colormapped representation.
17495d ·*/
d5af5a
9f0434 METHODDEF(void)
3b2e38 color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
14ea32 ¤   ¤   JSAMPARRAY output_buf, int num_rows)
27f5f4 /* General case, no dithering */
4ebb36 {
4aa2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
c684f8 ··JSAMPARRAY colorindex = cquantize->colorindex;
362c1f ··register int pixcode, ci;
1a42a7 ··register JSAMPROW ptrin, ptrout;
c95b06 ··int row;
3b0f73 ··JDIMENSION col;
d28e6b ··JDIMENSION width = cinfo->output_width;
3db592 ··register int nc = cinfo->out_color_components;
a1af5a
64d16f ··for (row = 0; row < num_rows; row++) {
7caf94 ····ptrin = input_buf[row];
48cf3b ····ptrout = output_buf[row];
085874 ····for (col = width; col > 0; col--) {
fdd5bf ······pixcode = 0;
4c6a15 ······for (ci = 0; ci < nc; ci++) {
37b01d ¤   pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
ec42cc ······}
a80b7f ······*ptrout++ = (JSAMPLE) pixcode;
486fe7 ····}
a6df1c ··}
5aefe6 }
40af5a
29af5a
000434 METHODDEF(void)
2f2328 color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
a8754f ¤   ¤   ·JSAMPARRAY output_buf, int num_rows)
d0604a /* Fast path for out_color_components==3, no dithering */
2dbb36 {
8fa2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
a39e1a ··register int pixcode;
db42a7 ··register JSAMPROW ptrin, ptrout;
3747c3 ··JSAMPROW colorindex0 = cquantize->colorindex[0];
a87b8b ··JSAMPROW colorindex1 = cquantize->colorindex[1];
fa3f53 ··JSAMPROW colorindex2 = cquantize->colorindex[2];
d55b06 ··int row;
5a0f73 ··JDIMENSION col;
7d8e6b ··JDIMENSION width = cinfo->output_width;
1baf5a
9bd16f ··for (row = 0; row < num_rows; row++) {
73af94 ····ptrin = input_buf[row];
41cf3b ····ptrout = output_buf[row];
5f5874 ····for (col = width; col > 0; col--) {
--cf66 000d217c69d40100044 Page 8 of jquant1.c
79de61 ······pixcode ·= GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
5db32a ······pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
bdeccb ······pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
6a0b7f ······*ptrout++ = (JSAMPLE) pixcode;
f26fe7 ····}
8fdf1c ··}
13efe6 }
f6af5a
acaf5a
d40434 METHODDEF(void)
ab4386 quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
d40636 ¤   ¤   ·····JSAMPARRAY output_buf, int num_rows)
2852cb /* General case, with ordered dithering */
1ebb36 {
88a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
3c58cf ··register JSAMPROW input_ptr;
b81823 ··register JSAMPROW output_ptr;
e873ab ··JSAMPROW colorindex_ci;
9a9b12 ··int * dither;¤¤   ¤   /* points to active row of dither matrix */
e8e1aa ··int row_index, col_index;¤/* current indexes into dither matrix */
44189e ··int nc = cinfo->out_color_components;
2e0dcc ··int ci;
365b06 ··int row;
ed0f73 ··JDIMENSION col;
328e6b ··JDIMENSION width = cinfo->output_width;
6caf5a
b4d16f ··for (row = 0; row < num_rows; row++) {
073213 ····/* Initialize output values to 0 so can process components separately */
623a89 ····jzero_far((void FAR *) output_buf[row],
12e9fd ¤   ······(size_t) (width * SIZEOF(JSAMPLE)));
bcc712 ····row_index = cquantize->row_index;
23f248 ····for (ci = 0; ci < nc; ci++) {
0d5ebd ······input_ptr = input_buf[row] + ci;
4dedc2 ······output_ptr = output_buf[row];
94d556 ······colorindex_ci = cquantize->colorindex[ci];
0a39d0 ······dither = cquantize->odither[ci][row_index];
0c0a7b ······col_index = 0;
dfaf5a
a549ff ······for (col = width; col > 0; col--) {
267fb3 ¤   /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
4cb670 ¤   ·* select output value, accumulate into output code for this pixel.
34e922 ¤   ·* Range-limiting need not be done explicitly, as we have extended
5e3ece ¤   ·* the colorindex table to produce the right answers for out-of-range
0c6177 ¤   ·* inputs. ·The maximum dither is +- MAXJSAMPLE; this sets the
836315 ¤   ·* required amount of padding.
92a4e3 ¤   ·*/
8ffa8e ¤   *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
536ee2 ¤   input_ptr += nc;
d2e32b ¤   output_ptr++;
d7adb3 ¤   col_index = (col_index + 1) & ODITHER_MASK;
e642cc ······}
2b6fe7 ····}
3f01a2 ····/* Advance row index for next row */
1d93bd ····row_index = (row_index + 1) & ODITHER_MASK;
c321bf ····cquantize->row_index = row_index;
49df1c ··}
5defe6 }
0baf5a
8aaf5a
030434 METHODDEF(void)
606b64 quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
423387 ¤   ¤   ······JSAMPARRAY output_buf, int num_rows)
3e467a /* Fast path for out_color_components==3, with ordered dithering */
8ebb36 {
fba2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
769e1a ··register int pixcode;
1b58cf ··register JSAMPROW input_ptr;
f01823 ··register JSAMPROW output_ptr;
d247c3 ··JSAMPROW colorindex0 = cquantize->colorindex[0];
e77b8b ··JSAMPROW colorindex1 = cquantize->colorindex[1];
fb3f53 ··JSAMPROW colorindex2 = cquantize->colorindex[2];
d2b56b ··int * dither0;¤   ¤   /* points to active row of dither matrix */
--a763 000894d5b6440100044 Page 9 of jquant1.c
923e3e ··int * dither1;
6dd15a ··int * dither2;
dbe1aa ··int row_index, col_index;¤/* current indexes into dither matrix */
015b06 ··int row;
8d0f73 ··JDIMENSION col;
cf8e6b ··JDIMENSION width = cinfo->output_width;
b1af5a
77d16f ··for (row = 0; row < num_rows; row++) {
b8c712 ····row_index = cquantize->row_index;
9af8ac ····input_ptr = input_buf[row];
75759f ····output_ptr = output_buf[row];
b03a92 ····dither0 = cquantize->odither[0][row_index];
ccd870 ····dither1 = cquantize->odither[1][row_index];
34f747 ····dither2 = cquantize->odither[2][row_index];
663d3b ····col_index = 0;
2faf5a
005874 ····for (col = width; col > 0; col--) {
bb3ed8 ······pixcode ·= GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
646e3f ¤   ¤   ¤   ¤   ¤   dither0[col_index]]);
62c425 ······pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
d6e02f ¤   ¤   ¤   ¤   ¤   dither1[col_index]]);
dec767 ······pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
1e7a0e ¤   ¤   ¤   ¤   ¤   dither2[col_index]]);
52300a ······*output_ptr++ = (JSAMPLE) pixcode;
2356c0 ······col_index = (col_index + 1) & ODITHER_MASK;
7f6fe7 ····}
9b93bd ····row_index = (row_index + 1) & ODITHER_MASK;
f021bf ····cquantize->row_index = row_index;
60df1c ··}
cdefe6 }
80af5a
beaf5a
5e0434 METHODDEF(void)
187ad3 quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
451442 ¤   ¤   ····JSAMPARRAY output_buf, int num_rows)
5702c7 /* General case, with Floyd-Steinberg dithering */
f3bb36 {
5ca2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
136244 ··register LOCFSERROR cur;¤ /* current error or pixel value */
c70c64 ··LOCFSERROR belowerr;¤ ¤   /* error for pixel below cur */
fb3da6 ··LOCFSERROR bpreverr;¤ ¤   /* error for below/prev col */
c6dcb1 ··LOCFSERROR bnexterr;¤ ¤   /* error for below/next col */
7734cf ··LOCFSERROR delta;
c1304c ··register FSERRPTR errorptr;¤  /* => fserrors[] at column before current */
3e58cf ··register JSAMPROW input_ptr;
4e1823 ··register JSAMPROW output_ptr;
5473ab ··JSAMPROW colorindex_ci;
efcae0 ··JSAMPROW colormap_ci;
eeb216 ··int pixcode;
58189e ··int nc = cinfo->out_color_components;
583cd4 ··int dir;¤ ¤   ¤   /* 1 for left-to-right, -1 for right-to-left */
e4783a ··int dirnc;¤   ¤   ¤   /* dir * nc */
ba0dcc ··int ci;
1c5b06 ··int row;
6b0f73 ··JDIMENSION col;
038e6b ··JDIMENSION width = cinfo->output_width;
756697 ··JSAMPLE *range_limit = cinfo->sample_range_limit;
e7ea99 ··SHIFT_TEMPS
daaf5a
c6d16f ··for (row = 0; row < num_rows; row++) {
fc3213 ····/* Initialize output values to 0 so can process components separately */
2f3a89 ····jzero_far((void FAR *) output_buf[row],
60e9fd ¤   ······(size_t) (width * SIZEOF(JSAMPLE)));
03f248 ····for (ci = 0; ci < nc; ci++) {
da5ebd ······input_ptr = input_buf[row] + ci;
d5edc2 ······output_ptr = output_buf[row];
a40d22 ······if (cquantize->on_odd_row) {
a9b4af ¤   /* work right to left in this row */
9cb426 ¤   input_ptr += (width-1) * nc; /* so point to rightmost pixel */
f23fe0 ¤   output_ptr += width-1;
169588 ¤   dir = -1;
893f92 ¤   dirnc = -nc;
--0b0f 0009ec9a0bc40100044 Page 10 of jquant1.c
931ea8 ¤   errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last colu¶
4782d6 mn */
9dcfc7 ······} else {
c152f7 ¤   /* work left to right in this row */
9af4c7 ¤   dir = 1;
6990ec ¤   dirnc = nc;
639454 ¤   errorptr = cquantize->fserrors[ci]; /* => entry before first column */
4d42cc ······}
38d556 ······colorindex_ci = cquantize->colorindex[ci];
d72fa6 ······colormap_ci = cquantize->sv_colormap[ci];
752191 ······/* Preset error values: no error propagated to first pixel from left */
311813 ······cur = 0;
46dfa9 ······/* and no error propagated to row below yet */
8ca692 ······belowerr = bpreverr = 0;
cfaf5a
1849ff ······for (col = width; col > 0; col--) {
36010a ¤   /* cur holds the error propagated from the previous pixel on the
db69d1 ¤   ·* current line. ·Add the error propagated from the previous line
4ed413 ¤   ·* to form the complete error correction term for this pixel, and
c81a46 ¤   ·* round the error term (which is expressed * 16) to an integer.
52fd7c ¤   ·* RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
51efe3 ¤   ·* for either sign of the error value.
3756d4 ¤   ·* Note: errorptr points to *previous* column's array entry.
35a4e3 ¤   ·*/
1a415d ¤   cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
556e4e ¤   /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
38d38a ¤   ·* The maximum error is +- MAXJSAMPLE; this sets the required size
372a18 ¤   ·* of the range_limit array.
7aa4e3 ¤   ·*/
664389 ¤   cur += GETJSAMPLE(*input_ptr);
89698e ¤   cur = GETJSAMPLE(range_limit[cur]);
d4c878 ¤   /* Select output value, accumulate into output code for this pixel */
68b41a ¤   pixcode = GETJSAMPLE(colorindex_ci[cur]);
dd772d ¤   *output_ptr += (JSAMPLE) pixcode;
24297a ¤   /* Compute actual representation error at this pixel */
08d887 ¤   /* Note: we can do this even though we don't have the final */
d32cce ¤   /* pixel code, because the colormap is orthogonal. */
aa34fe ¤   cur -= GETJSAMPLE(colormap_ci[pixcode]);
b5ffb6 ¤   /* Compute error fractions to be propagated to adjacent pixels.
d4b9be ¤   ·* Add these into the running sums, and simultaneously shift the
b1e6e6 ¤   ·* next-line error sums left by 1 column.
7ca4e3 ¤   ·*/
b06a64 ¤   bnexterr = cur;
3d4298 ¤   delta = cur * 2;
c482dc ¤   cur += delta;¤  ¤   /* form error * 3 */
4dc876 ¤   errorptr[0] = (FSERROR) (bpreverr + cur);
e6b944 ¤   cur += delta;¤  ¤   /* form error * 5 */
265325 ¤   bpreverr = belowerr + cur;
b87dbf ¤   belowerr = bnexterr;
5bafcc ¤   cur += delta;¤  ¤   /* form error * 7 */
45c9e3 ¤   /* At this point cur contains the 7/16 error value to be propagated
5e2745 ¤   ·* to the next pixel on the current line, and all the errors for the
e7be8b ¤   ·* next line have been shifted over. We are therefore ready to move on.
c3a4e3 ¤   ·*/
418b64 ¤   input_ptr += dirnc;¤/* advance input ptr to next column */
060d82 ¤   output_ptr += dir;¤ /* advance output ptr to next column */
b38cfa ¤   errorptr += dir;¤   /* advance errorptr to current column */
2442cc ······}
81ced9 ······/* Post-loop cleanup: we must unload the final error value into the
c9cfd5 ·······* final fserrors[] entry. ·Note we need not unload belowerr because
1aa5f6 ·······* it is for the dummy column before or after the actual array.
2ce9f1 ·······*/
4279a5 ······errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
0c6fe7 ····}
951969 ····cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
45df1c ··}
75efe6 }
5baf5a
dcaf5a
a638e5 /*
a6f873 ·* Allocate workspace for Floyd-Steinberg errors.
9e495d ·*/
--7e74 0006a3b0fab40100044 Page 11 of jquant1.c
e0af5a
1fafad LOCAL(void)
33624c alloc_fs_workspace (j_decompress_ptr cinfo)
ffbb36 {
f4a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
31b0fc ··size_t arraysize;
6717e0 ··int i;
a5af5a
1b1378 ··arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
41f590 ··for (i = 0; i < cinfo->out_color_components; i++) {
b7d197 ····cquantize->fserrors[i] = (FSERRPTR)
9d8435 ······(*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
c0df1c ··}
17efe6 }
23af5a
9caf5a
8738e5 /*
3f9453 ·* Initialize for one-pass color quantization.
d1495d ·*/
52af5a
740434 METHODDEF(void)
02555e start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
d4bb36 {
d3a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
d9b0fc ··size_t arraysize;
9d17e0 ··int i;
1eaf5a
7c6de7 ··/* Install my colormap. */
d68950 ··cinfo->colormap = cquantize->sv_colormap;
8e438c ··cinfo->actual_number_of_colors = cquantize->sv_actual;
12af5a
35e149 ··/* Initialize for desired dithering mode. */
64109a ··switch (cinfo->dither_mode) {
21764a ··case JDITHER_NONE:
d26900 ····if (cinfo->out_color_components == 3)
925abd ······cquantize->pub.color_quantize = color_quantize3;
34842c ····else
6c9618 ······cquantize->pub.color_quantize = color_quantize;
f0ab40 ····break;
164a55 ··case JDITHER_ORDERED:
146900 ····if (cinfo->out_color_components == 3)
3bbe52 ······cquantize->pub.color_quantize = quantize3_ord_dither;
d3842c ····else
ebec50 ······cquantize->pub.color_quantize = quantize_ord_dither;
d009ec ····cquantize->row_index = 0;¤  /* initialize state for ordered dither */
7f27c5 ····/* If user changed to ordered dither from another mode,
cad484 ·····* we must recreate the color index table with padding.
d30926 ·····* This will cost extra space, but probably isn't very likely.
4ad48d ·····*/
e0b488 ····if (! cquantize->is_padded)
7ccdd3 ······create_colorindex(cinfo);
dc719c ····/* Create ordered-dither tables if we didn't already. */
68cfa2 ····if (cquantize->odither[0] == NULL)
5e9f85 ······create_odither_tables(cinfo);
c4ab40 ····break;
12d941 ··case JDITHER_FS:
3b85cc ····cquantize->pub.color_quantize = quantize_fs_dither;
cf117d ····cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
e9bd6d ····/* Allocate Floyd-Steinberg workspace if didn't already. */
83ce77 ····if (cquantize->fserrors[0] == NULL)
93476d ······alloc_fs_workspace(cinfo);
b4a0a5 ····/* Initialize the propagated errors to zero. */
2197aa ····arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
df29ca ····for (i = 0; i < cinfo->out_color_components; i++)
9e9f62 ······jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
d3ab40 ····break;
5d969d ··default:
cc9214 ····ERREXIT(cinfo, JERR_NOT_COMPILED);
74ab40 ····break;
85df1c ··}
8befe6 }
6aaf5a
--03d5 00167942fb640100044 Page 12 of jquant1.c
e0af5a
d338e5 /*
631193 ·* Finish up at the end of the pass.
56495d ·*/
a9af5a
f60434 METHODDEF(void)
b6cc4f finish_pass_1_quant (j_decompress_ptr cinfo)
57bb36 {
946677 ··/* no work in 1-pass case */
91efe6 }
6eaf5a
c9af5a
0b38e5 /*
0e0d79 ·* Switch to a new external colormap between output passes.
50fab7 ·* Shouldn't get to this module!
ab495d ·*/
6aaf5a
d10434 METHODDEF(void)
cbd218 new_color_map_1_quant (j_decompress_ptr cinfo)
94bb36 {
b5f708 ··ERREXIT(cinfo, JERR_MODE_CHANGE);
9aefe6 }
20af5a
52af5a
5638e5 /*
f928c9 ·* Module initialization routine for 1-pass color quantization.
04495d ·*/
8eaf5a
f5f898 GLOBAL(void)
e576f1 jinit_1pass_quantizer (j_decompress_ptr cinfo)
fcbb36 {
cad87c ··my_cquantize_ptr cquantize;
1faf5a
c42dce ··cquantize = (my_cquantize_ptr)
743f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
b51a84 ¤   ¤   ¤   ¤   SIZEOF(my_cquantizer));
7b4cc0 ··cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
d322f0 ··cquantize->pub.start_pass = start_pass_1_quant;
85368e ··cquantize->pub.finish_pass = finish_pass_1_quant;
0b1089 ··cquantize->pub.new_color_map = new_color_map_1_quant;
100d07 ··cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */
b861df ··cquantize->odither[0] = NULL;¤/* Also flag odither arrays not allocated */
59af5a
85b533 ··/* Make sure my internal arrays won't overflow */
cae70b ··if (cinfo->out_color_components > MAX_Q_COMPS)
1b6b0e ····ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
7b5166 ··/* Make sure colormap indexes can be represented by JSAMPLEs */
3c5450 ··if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
5adf11 ····ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
21af5a
8413dd ··/* Create the colormap and color index table. */
0f76cf ··create_colormap(cinfo);
682d21 ··create_colorindex(cinfo);
76af5a
bcce72 ··/* Allocate Floyd-Steinberg workspace now if requested.
83137d ···* We do this now since it is FAR storage and may affect the memory
ae3771 ···* manager's space calculations. ·If the user changes to FS dither
9376fe ···* mode in a later pass, we will allocate the space then, and will
f7cf7a ···* possibly overrun the max_memory_to_use setting.
d6f9a6 ···*/
265ce1 ··if (cinfo->dither_mode == JDITHER_FS)
cc2324 ····alloc_fs_workspace(cinfo);
ecefe6 }
b7af5a
676f85 #endif /* QUANT_1PASS_SUPPORTED */
--7c7e 000bbf630c440100045 Page 1 of jquant2.c
bc38e5 /*
1abb1d ·* jquant2.c
10775e ·*
d5a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
96fb07 ·* This file is part of the Independent JPEG Group's software.
f4a0d6 ·* For conditions of distribution and use, see the accompanying README file.
ff775e ·*
769d8f ·* This file contains 2-pass color quantization (color mapping) routines.
22238d ·* These routines provide selection of a custom color map for an image,
f9b638 ·* followed by mapping of the image to that color map, with optional
276c34 ·* Floyd-Steinberg dithering.
cd1fde ·* It is also possible to use just the second pass to map to an arbitrary
754407 ·* externally-given color map.
2d775e ·*
e159b1 ·* Note: ordered dithering is not supported, since there isn't any fast
d17814 ·* way to compute intercolor distances; it's unclear that ordered dither's
165c69 ·* fundamental assumptions even hold with an irregularly spaced color map.
59495d ·*/
3baf5a
4f2bb6 #define JPEG_INTERNALS
ff36a7 #include "jinclude.h"
a36c8f #include "jpeglib.h"
e6af5a
204df6 #ifdef QUANT_2PASS_SUPPORTED
b4af5a
cdaf5a
aa38e5 /*
91bea7 ·* This module implements the well-known Heckbert paradigm for color
8e5164 ·* quantization. ·Most of the ideas used here can be traced back to
365eb3 ·* Heckbert's seminal paper
d72568 ·* ··Heckbert, Paul. ·"Color Image Quantization for Frame Buffer Display",
45d9dd ·* ··Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
fb775e ·*
6abf34 ·* In the first pass over the image, we accumulate a histogram showing the
303064 ·* usage count of each possible color. ·To keep the histogram to a reasonable
9c69ac ·* size, we reduce the precision of the input; typical practice is to retain
a0b401 ·* 5 or 6 bits per color, so that 8 or 4 different input values are counted
633c78 ·* in the same histogram cell.
db775e ·*
b4929b ·* Next, the color-selection step begins with a box representing the whole
210a44 ·* color space, and repeatedly splits the "largest" remaining box until we
e79ef6 ·* have as many boxes as desired colors. ·Then the mean color in each
72a54c ·* remaining box becomes one of the possible output colors.
d79ec0 ·*·
70045c ·* The second pass over the image maps each input pixel to the closest output
d8aac2 ·* color (optionally after applying a Floyd-Steinberg dithering correction).
cbb33f ·* This mapping is logically trivial, but making it go fast enough requires
5037a6 ·* considerable care.
d3775e ·*
27be9e ·* Heckbert-style quantizers vary a good deal in their policies for choosing
fbfb5a ·* the "largest" box and deciding where to cut it. ·The particular policies
33cb7e ·* used here have proved out well in experimental comparisons, but better ones
de51e4 ·* may yet be found.
d3775e ·*
968af8 ·* In earlier versions of the IJG code, this module quantized in YCbCr color
87edbb ·* space, processing the raw upsampled data without a color conversion step.
9d2e3d ·* This allowed the color conversion math to be done only once per colormap
206f1e ·* entry, not once per pixel. ·However, that optimization precluded other
4a67bf ·* useful optimizations (such as merging color conversion with upsampling)
1535dd ·* and it also interfered with desired capabilities such as quantizing to an
f79ea0 ·* externally-supplied colormap. ·We have therefore abandoned that approach.
eaefbb ·* The present code works in the post-conversion color space, typically RGB.
f0775e ·*
01561e ·* To improve the visual quality of the results, we actually work in scaled
862edf ·* RGB space, giving G distances more weight than R, and R in turn more than
3c618d ·* B. ·To do everything in integer math, we must use integer scale factors.
be9a94 ·* The 2/3/1 scale factors used here correspond loosely to the relative
a12208 ·* weights of the colors in the NTSC grayscale equation.
16de0e ·* If you want to use this code to quantize a non-RGB color space, you'll
f53af8 ·* probably need to change these scale factors.
fd495d ·*/
bbaf5a
--032e 0001756421d40100045 Page 2 of jquant2.c
964d51 #define R_SCALE 2¤  ¤   /* scale R distances by this much */
4eff33 #define G_SCALE 3¤  ¤   /* scale G distances by this much */
7f6483 #define B_SCALE 1¤  ¤   /* and B by this much */
6daf5a
ba2ec0 /* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
a10246 ·* in jmorecfg.h. ·As the code stands, it will do the right thing for R,G,B
2cbf57 ·* and B,G,R orders. ·If you define some other weird order in jmorecfg.h,
b46c47 ·* you'll get compile errors until you extend this logic. ·In that case
28dc10 ·* you'll probably want to tweak the histogram sizes too.
35495d ·*/
58af5a
6e6e5a #if RGB_RED == 0
0c10b8 #define C0_SCALE R_SCALE
127454 #endif
31cd69 #if RGB_BLUE == 0
634bc0 #define C0_SCALE B_SCALE
f97454 #endif
4f3cd3 #if RGB_GREEN == 1
a552b1 #define C1_SCALE G_SCALE
087454 #endif
d45dea #if RGB_RED == 2
950489 #define C2_SCALE R_SCALE
987454 #endif
7ffed9 #if RGB_BLUE == 2
5e5ff1 #define C2_SCALE B_SCALE
067454 #endif
d6af5a
b7af5a
af38e5 /*
38d162 ·* First we have the histogram data structure and routines for creating it.
e1775e ·*
28f785 ·* The number of bits of precision can be adjusted by changing these symbols.
f521da ·* We recommend keeping 6 bits for G and 5 each for R and B.
67b0aa ·* If you have plenty of memory and cycles, 6 bits all around gives marginally
855326 ·* better results; if you are short of memory, 5 bits all around will save
7ea344 ·* some space but degrade the results.
ec6f4a ·* To maintain a fully accurate histogram, we'd need to allocate a "long"
718e16 ·* (preferably unsigned long) for each cell. ·In practice this is overkill;
a98853 ·* we can get by with 16 bits per cell. ·Few of the cell counts will overflow,
d0e010 ·* and clamping those that do overflow to the maximum value will give close-
b8ff11 ·* enough results. ·This reduces the recommended histogram size from 256Kb
ff4382 ·* to 128Kb, which is a useful savings on PC-class machines.
27aa5c ·* (In the second pass the histogram space is re-used for pixel mapping data;
f93ee2 ·* in that capacity, each cell must be able to store zero to the number of
46f16f ·* desired colors. ·16 bits/cell is plenty for that too.)
45873d ·* Since the JPEG code is intended to run in small memory model on 80x86
5d4f1d ·* machines, we can't just allocate the histogram in one chunk. ·Instead
107a4c ·* of a true 3-D array, we use a row of pointers to 2-D arrays. ·Each
2f5eb5 ·* pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
937038 ·* each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. ·Note that
e22b1f ·* on 80x86 machines, the pointer row is in near memory but the actual
bf8944 ·* arrays are in far memory (same arrangement as we use for image arrays).
9d495d ·*/
90af5a
4876eb #define MAXNUMCOLORS ·(MAXJSAMPLE+1) /* maximum size of colormap */
25af5a
4c0825 /* These will do the right thing for either R,G,B or B,G,R color order,
83e99d ·* but you may not like the results for other color orders.
8b495d ·*/
213cfd #define HIST_C0_BITS ·5¤¤   /* bits of precision in R/B histogram */
0edb55 #define HIST_C1_BITS ·6¤¤   /* bits of precision in G histogram */
6e00c3 #define HIST_C2_BITS ·5¤¤   /* bits of precision in B/R histogram */
8aaf5a
1827ab /* Number of elements along histogram axes. */
3c6e3d #define HIST_C0_ELEMS ·(1<<HIST_C0_BITS)
ccbdca #define HIST_C1_ELEMS ·(1<<HIST_C1_BITS)
b3c1c2 #define HIST_C2_ELEMS ·(1<<HIST_C2_BITS)
a1af5a
164a0e /* These are the amounts to shift an input value to get a histogram index. */
b4e924 #define C0_SHIFT ·(BITS_IN_JSAMPLE-HIST_C0_BITS)
ea66a1 #define C1_SHIFT ·(BITS_IN_JSAMPLE-HIST_C1_BITS)
17fe3f #define C2_SHIFT ·(BITS_IN_JSAMPLE-HIST_C2_BITS)
--6eca 0002a12ac3140100045 Page 3 of jquant2.c
e0af5a
1aaf5a
f4d701 typedef UINT16 histcell;¤   /* histogram cell; prefer an unsigned type */
2aaf5a
dea084 typedef histcell FAR * histptr;¤/* for pointers to histogram cells */
f6af5a
762e91 typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
c8df17 typedef hist1d FAR * hist2d;¤   /* type for the 2nd-level pointers */
c56458 typedef hist2d * hist3d;¤   /* type for top-level pointer */
7baf5a
5caf5a
e93996 /* Declarations for Floyd-Steinberg dithering.
f5775e ·*
db0ebc ·* Errors are accumulated into the array fserrors[], at a resolution of
31045f ·* 1/16th of a pixel count. ·The error at a given pixel is propagated
ade34a ·* to its not-yet-processed neighbors using the standard F-S fractions,
b30174 ·*¤ ¤   ...¤(here)¤ 7/16
421217 ·*¤ ¤   3/16¤   5/16¤   1/16
c55479 ·* We work left-to-right on even rows, right-to-left on odd rows.
80775e ·*
82ff68 ·* We can get away with a single array (holding one row's worth of errors)
23101d ·* by using it to store the current row's errors at pixel columns not yet
622fdd ·* processed, but the next row's errors at columns already processed. ·We
32aff2 ·* need only a few extra variables to hold the errors immediately around the
b5aa4f ·* current column. ·(If we are lucky, those variables are in registers, but
54d34b ·* even if not, they're probably cheaper to access than array elements are.)
27775e ·*
d2cb0b ·* The fserrors[] array has (#columns + 2) entries; the extra entry at
a10ebd ·* each end saves us from special-casing the first and last pixels.
8cdf28 ·* Each entry is three values long, one value for each color component.
d5775e ·*
aa00a1 ·* Note: on a wide image, we might not have enough room in a PC's near data
3d6733 ·* segment to hold the error array; so it is allocated with alloc_large.
e8495d ·*/
79af5a
9a6f80 #if BITS_IN_JSAMPLE == 8
b13409 typedef INT16 FSERROR;¤ ¤   /* 16 bits should be enough */
5796fe typedef int LOCFSERROR;¤¤   /* use 'int' for calculation temps */
d4db21 #else
9d38b3 typedef INT32 FSERROR;¤ ¤   /* may need more than 16 bits */
ed0918 typedef INT32 LOCFSERROR;¤  /* be sure calculation temps are big enough */
d67454 #endif
02af5a
e5ed71 typedef FSERROR FAR *FSERRPTR;¤ /* pointer to error array (in FAR storage!) */
f1af5a
0caf5a
73dedc /* Private subobject */
86af5a
18f0f7 typedef struct {
ba7312 ··struct jpeg_color_quantizer pub; /* public fields */
7daf5a
3ac356 ··/* Space for the eventually created colormap is stashed here */
56acdd ··JSAMPARRAY sv_colormap;¤  /* colormap allocated at init time */
5a1753 ··int desired;¤ ¤   ¤   /* desired # of colors = size of colormap */
3daf5a
cb4fb3 ··/* Variables for accumulating image statistics */
03bbee ··hist3d histogram;¤¤   /* pointer to the histogram */
f4af5a
b2ddac ··boolean needs_zeroed;¤¤   /* TRUE if next pass must zero histogram */
d8af5a
653576 ··/* Variables for Floyd-Steinberg dithering */
2db0b0 ··FSERRPTR fserrors;¤   ¤   /* accumulated errors */
eaf7f0 ··boolean on_odd_row;¤  ¤   /* flag to remember which row we are on */
fed5e2 ··int * error_limiter;¤ ¤   /* table for clamping the applied error */
22ad8a } my_cquantizer;
53af5a
48711c typedef my_cquantizer * my_cquantize_ptr;
97af5a
9eaf5a
2438e5 /*
d84d0c ·* Prescan some rows of pixels.
2aa8ec ·* In this module the prescan simply updates the histogram, which has been
--82ad 00075e0c30f40100045 Page 4 of jquant2.c
94681a ·* initialized to zeroes by start_pass.
250740 ·* An output_buf parameter is required by the method signature, but no data
c8d9ba ·* is actually output (in fact the buffer controller is probably passing a
5a5aeb ·* NULL pointer).
7b495d ·*/
57af5a
120434 METHODDEF(void)
f8fd88 prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
32ddb2 ¤   ¤   ··JSAMPARRAY output_buf, int num_rows)
53bb36 {
a0a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
33485a ··register JSAMPROW ptr;
858944 ··register histptr histp;
d61d39 ··register hist3d histogram = cquantize->histogram;
745b06 ··int row;
420f73 ··JDIMENSION col;
448e6b ··JDIMENSION width = cinfo->output_width;
eeaf5a
07d16f ··for (row = 0; row < num_rows; row++) {
b7ee8e ····ptr = input_buf[row];
ec5874 ····for (col = width; col > 0; col--) {
e6beb1 ······/* get pixel value and index into the histogram */
9c1248 ······histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
1569ce ¤   ¤   ¤   ·[GETJSAMPLE(ptr[1]) >> C1_SHIFT]
be5a6a ¤   ¤   ¤   ·[GETJSAMPLE(ptr[2]) >> C2_SHIFT];
ede1c8 ······/* increment, check for overflow and undo increment if so. */
b85053 ······if (++(*histp) <= 0)
1df4cb ¤   (*histp)--;
055ef9 ······ptr += 3;
6d6fe7 ····}
f3df1c ··}
d1efe6 }
66af5a
74af5a
5a38e5 /*
5c0a23 ·* Next we have the really interesting routines: selection of a colormap
7ff43c ·* given the completed histogram.
7862dd ·* These routines work with a list of "boxes", each representing a rectangular
11f83e ·* subset of the input color space (to histogram precision).
94495d ·*/
2daf5a
2ef0f7 typedef struct {
c21b33 ··/* The bounds of the box (inclusive); expressed as histogram indexes */
9df7dd ··int c0min, c0max;
85f65b ··int c1min, c1max;
75f4d1 ··int c2min, c2max;
fafc68 ··/* The volume (actually 2-norm) of the box */
e458d3 ··INT32 volume;
e5363a ··/* The number of nonzero histogram cells within this box */
046ce8 ··long colorcount;
bb9d0f } box;
6aaf5a
ae088b typedef box * boxptr;
02af5a
6faf5a
8093e5 LOCAL(boxptr)
117e7e find_biggest_color_pop (boxptr boxlist, int numboxes)
77b8d6 /* Find the splittable box with the largest color population */
906b9b /* Returns NULL if no splittable boxes remain */
4fbb36 {
f5da42 ··register boxptr boxp;
1339eb ··register int i;
f9188b ··register long maxc = 0;
1da100 ··boxptr which = NULL;
65de7b ··
4c617f ··for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
e1a89b ····if (boxp->colorcount > maxc && boxp->volume > 0) {
80ace1 ······which = boxp;
617377 ······maxc = boxp->colorcount;
246fe7 ····}
11df1c ··}
75642a ··return which;
--92f6 0008020041340100045 Page 5 of jquant2.c
7aefe6 }
46af5a
8eaf5a
6193e5 LOCAL(boxptr)
679233 find_biggest_volume (boxptr boxlist, int numboxes)
ae990d /* Find the splittable box with the largest (scaled) volume */
db6b9b /* Returns NULL if no splittable boxes remain */
4ebb36 {
a7da42 ··register boxptr boxp;
c139eb ··register int i;
3766dd ··register INT32 maxv = 0;
f2a100 ··boxptr which = NULL;
7ade7b ··
53617f ··for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
17fe6c ····if (boxp->volume > maxv) {
5aace1 ······which = boxp;
6f2021 ······maxv = boxp->volume;
3c6fe7 ····}
e7df1c ··}
f6642a ··return which;
35efe6 }
14af5a
64af5a
19afad LOCAL(void)
9f7343 update_box (j_decompress_ptr cinfo, boxptr boxp)
9704ae /* Shrink the min/max bounds of a box to enclose only nonzero elements, */
6c8560 /* and recompute its volume and population */
2abb36 {
f1a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
39a71d ··hist3d histogram = cquantize->histogram;
7bcb8a ··histptr histp;
63e5cc ··int c0,c1,c2;
5efc00 ··int c0min,c0max,c1min,c1max,c2min,c2max;
db4129 ··INT32 dist0,dist1,dist2;
7fe18d ··long ccount;
2bde7b ··
44da6c ··c0min = boxp->c0min; ·c0max = boxp->c0max;
576da3 ··c1min = boxp->c1min; ·c1max = boxp->c1max;
36bde3 ··c2min = boxp->c2min; ·c2max = boxp->c2max;
c6de7b ··
684e2c ··if (c0max > c0min)
66dd60 ····for (c0 = c0min; c0 <= c0max; c0++)
f6d165 ······for (c1 = c1min; c1 <= c1max; c1++) {
a0cea7 ¤   histp = & histogram[c0][c1][c2min];
3ed6a5 ¤   for (c2 = c2min; c2 <= c2max; c2++)
3b6ac9 ¤   ··if (*histp++ != 0) {
466f6f ¤   ····boxp->c0min = c0min = c0;
322b00 ¤   ····goto have_c0min;
2032a2 ¤   ··}
2f42cc ······}
5e9121 ·have_c0min:
7c4e2c ··if (c0max > c0min)
b0223b ····for (c0 = c0max; c0 >= c0min; c0--)
f7d165 ······for (c1 = c1min; c1 <= c1max; c1++) {
bacea7 ¤   histp = & histogram[c0][c1][c2min];
f1d6a5 ¤   for (c2 = c2min; c2 <= c2max; c2++)
2c6ac9 ¤   ··if (*histp++ != 0) {
854bcf ¤   ····boxp->c0max = c0max = c0;
469d94 ¤   ····goto have_c0max;
1832a2 ¤   ··}
cc42cc ······}
2e27b5 ·have_c0max:
9f34ed ··if (c1max > c1min)
fb8f1e ····for (c1 = c1min; c1 <= c1max; c1++)
6bca26 ······for (c0 = c0min; c0 <= c0max; c0++) {
3ccea7 ¤   histp = & histogram[c0][c1][c2min];
61d6a5 ¤   for (c2 = c2min; c2 <= c2max; c2++)
a96ac9 ¤   ··if (*histp++ != 0) {
aff36b ¤   ····boxp->c1min = c1min = c1;
802f2b ¤   ····goto have_c1min;
f932a2 ¤   ··}
8042cc ······}
--ad09 000700df11340100045 Page 6 of jquant2.c
d1950a ·have_c1min:
cd34ed ··if (c1max > c1min)
997045 ····for (c1 = c1max; c1 >= c1min; c1--)
25ca26 ······for (c0 = c0min; c0 <= c0max; c0++) {
92cea7 ¤   histp = & histogram[c0][c1][c2min];
96d6a5 ¤   for (c2 = c2min; c2 <= c2max; c2++)
e96ac9 ¤   ··if (*histp++ != 0) {
4fd7cb ¤   ····boxp->c1max = c1max = c1;
7699bf ¤   ····goto have_c1max;
e332a2 ¤   ··}
6b42cc ······}
10239e ·have_c1max:
94bbae ··if (c2max > c2min)
44799c ····for (c2 = c2min; c2 <= c2max; c2++)
32ca26 ······for (c0 = c0min; c0 <= c0max; c0++) {
5ef51b ¤   histp = & histogram[c0][c1min][c2];
559c5f ¤   for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
7f9de6 ¤   ··if (*histp != 0) {
f25f76 ¤   ····boxp->c2min = c2min = c2;
a62356 ¤   ····goto have_c2min;
4832a2 ¤   ··}
eb42cc ······}
019977 ·have_c2min:
7cbbae ··if (c2max > c2min)
4b86c7 ····for (c2 = c2max; c2 >= c2min; c2--)
cfca26 ······for (c0 = c0min; c0 <= c0max; c0++) {
3df51b ¤   histp = & histogram[c0][c1min][c2];
679c5f ¤   for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
fc9de6 ¤   ··if (*histp != 0) {
937bd6 ¤   ····boxp->c2max = c2max = c2;
6995c2 ¤   ····goto have_c2max;
6832a2 ¤   ··}
4a42cc ······}
332fe3 ·have_c2max:
71af5a
c4391d ··/* Update box volume.
668a67 ···* We use 2-norm rather than real volume here; this biases the method
999f0b ···* against making long narrow boxes, and it has the side benefit that
54b09a ···* a box is splittable iff norm > 0.
c7abd2 ···* Since the differences are expressed in histogram-cell units,
3bcf81 ···* we have to shift back to JSAMPLE units to get consistent distances;
12b10e ···* after which, we scale according to the selected distance scale factors.
d0f9a6 ···*/
c2b20b ··dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
9cc826 ··dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
a04651 ··dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
9d4ed3 ··boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
fbde7b ··
fdc967 ··/* Now scan remaining volume of box and compute population */
ac1638 ··ccount = 0;
24cc42 ··for (c0 = c0min; c0 <= c0max; c0++)
5bb809 ····for (c1 = c1min; c1 <= c1max; c1++) {
7c7015 ······histp = & histogram[c0][c1][c2min];
b52899 ······for (c2 = c2min; c2 <= c2max; c2++, histp++)
90209e ¤   if (*histp != 0) {
cf7a6f ¤   ··ccount++;
049371 ¤   }
d46fe7 ····}
bffa3b ··boxp->colorcount = ccount;
96efe6 }
e8af5a
b4af5a
57aa6a LOCAL(int)
78953e median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
1fb64e ¤   ····int desired_colors)
ba77e8 /* Repeatedly select and split the largest box until we have enough boxes */
5cbb36 {
0bd6ae ··int n,lb;
cbd55b ··int c0,c1,c2,cmax;
ae2694 ··register boxptr b1,b2;
e4af5a
708840 ··while (numboxes < desired_colors) {
--e0b5 000ec58baaf40100045 Page 7 of jquant2.c
f9a884 ····/* Select box to split.
190419 ·····* Current algorithm: by population for first half, then by volume.
78d48d ·····*/
0656f7 ····if (numboxes*2 <= desired_colors) {
15abfe ······b1 = find_biggest_color_pop(boxlist, numboxes);
166a79 ····} else {
feed70 ······b1 = find_biggest_volume(boxlist, numboxes);
db6fe7 ····}
448b54 ····if (b1 == NULL)¤¤   /* no splittable boxes left! */
ac88e1 ······break;
6df595 ····b2 = &boxlist[numboxes];¤   /* where new box will go */
abc607 ····/* Copy the color bounds to the new box. */
213306 ····b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
0e7c26 ····b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
ef9aa3 ····/* Choose which axis to split the box on.
57712c ·····* Current algorithm: longest scaled axis.
68ca5f ·····* See notes in update_box about scaling distances.
ddd48d ·····*/
fea882 ····c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
c829ba ····c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
60a2e3 ····c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
d53539 ····/* We want to break any ties in favor of green, then red, blue last.
8bb5a4 ·····* This code does the right thing for R,G,B or B,G,R color orders only.
70d48d ·····*/
ff6e5a #if RGB_RED == 0
9f69cc ····cmax = c1; n = 1;
bbe0fd ····if (c0 > cmax) { cmax = c0; n = 0; }
78218c ····if (c2 > cmax) { n = 2; }
99db21 #else
5569cc ····cmax = c1; n = 1;
361a0a ····if (c2 > cmax) { cmax = c2; n = 2; }
4959dc ····if (c0 > cmax) { n = 0; }
6f7454 #endif
89c039 ····/* Choose split point along selected axis, and update box bounds.
97933d ·····* Current algorithm: split at halfway point.
5bc0ca ·····* (Since the box has been shrunk to minimum volume,
a41fd1 ·····* any split will produce two nonempty subboxes.)
5bcad0 ·····* Note that lb value is max for lower box, so must be < old max.
23d48d ·····*/
6b37f8 ····switch (n) {
ba4f11 ····case 0:
2596f5 ······lb = (b1->c0max + b1->c0min) / 2;
4da780 ······b1->c0max = lb;
b67abb ······b2->c0min = lb+1;
c888e1 ······break;
8615cd ····case 1:
644aad ······lb = (b1->c1max + b1->c1min) / 2;
eff211 ······b1->c1max = lb;
897f16 ······b2->c1min = lb+1;
7188e1 ······break;
e0faa9 ····case 2:
9b2654 ······lb = (b1->c2max + b1->c2min) / 2;
300ca2 ······b1->c2max = lb;
6f71e1 ······b2->c2min = lb+1;
2e88e1 ······break;
e56fe7 ····}
991cf0 ····/* Update stats for boxes */
155066 ····update_box(cinfo, b1);
4b75ab ····update_box(cinfo, b2);
a5e062 ····numboxes++;
a5df1c ··}
4ce7ab ··return numboxes;
f2efe6 }
b9af5a
c4af5a
3dafad LOCAL(void)
39e469 compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
ba8101 /* Compute representative color for a box, put it in colormap[icolor] */
2ebb36 {
ec4599 ··/* Current algorithm: mean weighted by pixels (not colors) */
81c371 ··/* Note it is important to get the rounding correct! */
eca2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
--eb00 00057e7942640100045 Page 8 of jquant2.c
12a71d ··hist3d histogram = cquantize->histogram;
c0cb8a ··histptr histp;
cae5cc ··int c0,c1,c2;
8bfc00 ··int c0min,c0max,c1min,c1max,c2min,c2max;
eb6a6f ··long count;
3664d6 ··long total = 0;
1ed923 ··long c0total = 0;
b05c76 ··long c1total = 0;
2adb98 ··long c2total = 0;
bdde7b ··
eada6c ··c0min = boxp->c0min; ·c0max = boxp->c0max;
776da3 ··c1min = boxp->c1min; ·c1max = boxp->c1max;
30bde3 ··c2min = boxp->c2min; ·c2max = boxp->c2max;
f0de7b ··
47cc42 ··for (c0 = c0min; c0 <= c0max; c0++)
3ab809 ····for (c1 = c1min; c1 <= c1max; c1++) {
0e7015 ······histp = & histogram[c0][c1][c2min];
88fca0 ······for (c2 = c2min; c2 <= c2max; c2++) {
e6be09 ¤   if ((count = *histp++) != 0) {
e27dd0 ¤   ··total += count;
187d0a ¤   ··c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
ec9834 ¤   ··c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
62bf67 ¤   ··c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
959371 ¤   }
0942cc ······}
106fe7 ····}
69de7b ··
c4c0a9 ··cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
89d04f ··cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
f7e165 ··cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
68efe6 }
e1af5a
fcaf5a
b3afad LOCAL(void)
cde4db select_colors (j_decompress_ptr cinfo, int desired_colors)
f9e71b /* Master routine for color selection */
4bbb36 {
1793d4 ··boxptr boxlist;
85c93f ··int numboxes;
2617e0 ··int i;
a2af5a
9218f1 ··/* Allocate workspace for box list */
1809fa ··boxlist = (boxptr) (*cinfo->mem->alloc_small)
57ce31 ····((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
1e712b ··/* Initialize one box containing whole space */
1009e4 ··numboxes = 1;
b33fc5 ··boxlist[0].c0min = 0;
ccf690 ··boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
cf13e2 ··boxlist[0].c1min = 0;
d57e59 ··boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
e8678b ··boxlist[0].c2min = 0;
0eef13 ··boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
d3088a ··/* Shrink it to actually-used volume and set its statistics */
a59231 ··update_box(cinfo, & boxlist[0]);
2cb14c ··/* Perform median-cut to produce final box list */
2d5e60 ··numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
dab210 ··/* Compute the representative color for each box, fill colormap */
ddc8b3 ··for (i = 0; i < numboxes; i++)
bea210 ····compute_color(cinfo, & boxlist[i], i);
5f0a8f ··cinfo->actual_number_of_colors = numboxes;
5dc67b ··TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
2befe6 }
70af5a
04af5a
c738e5 /*
eccc4b ·* These routines are concerned with the time-critical task of mapping input
53f1cb ·* colors to the nearest color in the selected colormap.
12775e ·*
94fa1d ·* We re-use the histogram space as an "inverse color map", essentially a
b73a34 ·* cache for the results of nearest-color searches. ·All colors within a
2f687b ·* histogram cell will be mapped to the same colormap entry, namely the one
5734c1 ·* closest to the cell's center. ·This may not be quite the closest entry to
--eb50 0000c44afc640100045 Page 9 of jquant2.c
d8561d ·* the actual input color, but it's almost as good. ·A zero in the cache
0e6448 ·* indicates we haven't found the nearest color for that cell yet; the array
537234 ·* is cleared to zeroes before starting the mapping pass. ·When we find the
116c26 ·* nearest color for a cell, its colormap index plus one is recorded in the
173d68 ·* cache for future use. ·The pass2 scanning routines call fill_inverse_cmap
0ccc79 ·* when they need to use an unfilled entry in the cache.
f5775e ·*
16eb61 ·* Our method of efficiently finding nearest colors is based on the "locally
843c41 ·* sorted search" idea described by Heckbert and on the incremental distance
acda2c ·* calculation described by Spencer W. Thomas in chapter III.1 of Graphics
6d9330 ·* Gems II (James Arvo, ed. ·Academic Press, 1991). ·Thomas points out that
1c482f ·* the distances from a given colormap entry to each cell of the histogram can
d0f2c8 ·* be computed quickly using an incremental method: the differences between
4af917 ·* distances to adjacent cells themselves differ by a constant. ·This allows a
340f4e ·* fairly fast implementation of the "brute force" approach of computing the
a4096a ·* distance from every colormap entry to every histogram cell. ·Unfortunately,
3c3f7f ·* it needs a work array to hold the best-distance-so-far for each histogram
3ea27c ·* cell (because the inner loop has to be over cells, not colormap entries).
84d4e5 ·* The work array elements have to be INT32s, so the work array would need
accc14 ·* 256Kb at our recommended precision. ·This is not feasible in DOS machines.
96775e ·*
d2590c ·* To get around these problems, we apply Thomas' method to compute the
07905c ·* nearest colors for only the cells within a small subbox of the histogram.
27d9b6 ·* The work array need be only as big as the subbox, so the memory usage
3a1ed4 ·* problem is solved. ·Furthermore, we need not fill subboxes that are never
0bde3c ·* referenced in pass2; many images use only part of the color gamut, so a
fc884b ·* fair amount of work is saved. ·An additional advantage of this
06a4aa ·* approach is that we can apply Heckbert's locality criterion to quickly
0d0c5f ·* eliminate colormap entries that are far away from the subbox; typically
78e3ec ·* three-fourths of the colormap entries are rejected by Heckbert's criterion,
2affdd ·* and we need not compute their distances to individual cells in the subbox.
016e73 ·* The speed of this approach is heavily influenced by the subbox size: too
de5441 ·* small means too much overhead, too big loses because Heckbert's criterion
061f74 ·* can't eliminate as many colormap entries. ·Empirically the best subbox
8f5b19 ·* size seems to be about 1/512th of the histogram (1/8th in each direction).
76775e ·*
a37096 ·* Thomas' article also describes a refined method which is asymptotically
60a1c8 ·* faster than the brute-force method, but it is also far more complex and
a02d12 ·* cannot efficiently be applied to small subboxes. ·It is therefore not
a822e2 ·* useful for programs intended to be portable to DOS machines. ·On machines
067b5b ·* with plenty of memory, filling the whole histogram in one shot with Thomas'
a72247 ·* refined method might be faster than the present code --- but then again,
e228c1 ·* it might not be any faster, and it's certainly more complicated.
d2495d ·*/
a1af5a
90af5a
413a8c /* log2(histogram cells in update box) for each axis; this can be adjusted */
626e49 #define BOX_C0_LOG ·(HIST_C0_BITS-3)
73192a #define BOX_C1_LOG ·(HIST_C1_BITS-3)
6c808f #define BOX_C2_LOG ·(HIST_C2_BITS-3)
12af5a
b16551 #define BOX_C0_ELEMS ·(1<<BOX_C0_LOG) /* # of hist cells in update box */
96f1ab #define BOX_C1_ELEMS ·(1<<BOX_C1_LOG)
985548 #define BOX_C2_ELEMS ·(1<<BOX_C2_LOG)
2baf5a
aac929 #define BOX_C0_SHIFT ·(C0_SHIFT + BOX_C0_LOG)
25bfc2 #define BOX_C1_SHIFT ·(C1_SHIFT + BOX_C1_LOG)
3a24ff #define BOX_C2_SHIFT ·(C2_SHIFT + BOX_C2_LOG)
54af5a
c1af5a
b938e5 /*
087309 ·* The next three routines implement inverse colormap filling. ·They could
685d20 ·* all be folded into one big routine, but splitting them up this way saves
f770bb ·* some stack space (the mindist[] and bestdist[] arrays need not coexist)
c9056a ·* and may allow some compilers to produce better code by registerizing more
7fd58d ·* inner-loop variables.
80495d ·*/
3aaf5a
bcaa6a LOCAL(int)
68040f find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
7aa8c8 ¤   ¤   ····JSAMPLE colorlist[])
0c90a6 /* Locate the colormap entries close enough to an update box to be candidates
--c008 0005150969040100045 Page 10 of jquant2.c
8f7a5f ·* for the nearest entry to some cell(s) in the update box. ·The update box
1fe39b ·* is specified by the center coordinates of its first cell. ·The number of
2742d0 ·* candidate colormap entries is returned, and their colormap indexes are
5752e2 ·* placed in colorlist[].
28fe82 ·* This routine uses Heckbert's "locally sorted search" criterion to select
584337 ·* the colors that need further consideration.
00495d ·*/
c8bb36 {
125e45 ··int numcolors = cinfo->actual_number_of_colors;
db1815 ··int maxc0, maxc1, maxc2;
f9edbb ··int centerc0, centerc1, centerc2;
345baf ··int i, x, ncolors;
f6a901 ··INT32 minmaxdist, min_dist, max_dist, tdist;
35b6f0 ··INT32 mindist[MAXNUMCOLORS];¤ /* min distance to colormap entry i */
33af5a
b84898 ··/* Compute true coordinates of update box's upper corner and center.
12991b ···* Actually we compute the coordinates of the center of the upper-corner
7d2833 ···* histogram cell, which are the upper bounds of the volume we care about.
031031 ···* Note that since ">>" rounds down, the "center" values may be closer to
95fe78 ···* min than to max; hence comparisons to them must be "<=", not "<".
7cf9a6 ···*/
c30cc8 ··maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
54e050 ··centerc0 = (minc0 + maxc0) >> 1;
935230 ··maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
fa70f2 ··centerc1 = (minc1 + maxc1) >> 1;
58b138 ··maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
0cc905 ··centerc2 = (minc2 + maxc2) >> 1;
ceaf5a
676a22 ··/* For each color in colormap, find:
4933bc ···* ·1. its minimum squared-distance to any point in the update box
c1ad6f ···* ····(zero if color is within update box);
b22641 ···* ·2. its maximum squared-distance to any point in the update box.
e03e51 ···* Both of these can be found by considering only the corners of the box.
b68978 ···* We save the minimum distance for each color in mindist[];
232cc4 ···* only the smallest maximum distance is of interest.
70f9a6 ···*/
0fabc6 ··minmaxdist = 0x7FFFFFFFL;
47af5a
676b9b ··for (i = 0; i < numcolors; i++) {
e75269 ····/* We compute the squared-c0-distance term, then add in the other two. */
90578b ····x = GETJSAMPLE(cinfo->colormap[0][i]);
110de2 ····if (x < minc0) {
2f3300 ······tdist = (x - minc0) * C0_SCALE;
2ae69a ······min_dist = tdist*tdist;
20a48c ······tdist = (x - maxc0) * C0_SCALE;
0da211 ······max_dist = tdist*tdist;
04ff07 ····} else if (x > maxc0) {
b3a48c ······tdist = (x - maxc0) * C0_SCALE;
6ae69a ······min_dist = tdist*tdist;
673300 ······tdist = (x - minc0) * C0_SCALE;
a9a211 ······max_dist = tdist*tdist;
b66a79 ····} else {
3287d4 ······/* within cell range so no contribution to min_dist */
0284f5 ······min_dist = 0;
f53589 ······if (x <= centerc0) {
9a13c2 ¤   tdist = (x - maxc0) * C0_SCALE;
ae0567 ¤   max_dist = tdist*tdist;
b5cfc7 ······} else {
7d844e ¤   tdist = (x - minc0) * C0_SCALE;
660567 ¤   max_dist = tdist*tdist;
2d42cc ······}
b76fe7 ····}
71af5a
afd634 ····x = GETJSAMPLE(cinfo->colormap[1][i]);
d206a6 ····if (x < minc1) {
e236d7 ······tdist = (x - minc1) * C1_SCALE;
b78e25 ······min_dist += tdist*tdist;
3da15b ······tdist = (x - maxc1) * C1_SCALE;
d8b4ba ······max_dist += tdist*tdist;
c2f443 ····} else if (x > maxc1) {
3aa15b ······tdist = (x - maxc1) * C1_SCALE;
518e25 ······min_dist += tdist*tdist;
--b64f 0005764d29840100045 Page 11 of jquant2.c
4c36d7 ······tdist = (x - minc1) * C1_SCALE;
38b4ba ······max_dist += tdist*tdist;
6b6a79 ····} else {
3387d4 ······/* within cell range so no contribution to min_dist */
623ecd ······if (x <= centerc1) {
551615 ¤   tdist = (x - maxc1) * C1_SCALE;
0ea2ac ¤   max_dist += tdist*tdist;
4ecfc7 ······} else {
e38199 ¤   tdist = (x - minc1) * C1_SCALE;
62a2ac ¤   max_dist += tdist*tdist;
3e42cc ······}
a36fe7 ····}
24af5a
195ce4 ····x = GETJSAMPLE(cinfo->colormap[2][i]);
601b6a ····if (x < minc2) {
6538ae ······tdist = (x - minc2) * C2_SCALE;
d28e25 ······min_dist += tdist*tdist;
3faf22 ······tdist = (x - maxc2) * C2_SCALE;
86b4ba ······max_dist += tdist*tdist;
17e98f ····} else if (x > maxc2) {
acaf22 ······tdist = (x - maxc2) * C2_SCALE;
2c8e25 ······min_dist += tdist*tdist;
9738ae ······tdist = (x - minc2) * C2_SCALE;
fcb4ba ······max_dist += tdist*tdist;
3b6a79 ····} else {
f887d4 ······/* within cell range so no contribution to min_dist */
052301 ······if (x <= centerc2) {
6e186c ¤   tdist = (x - maxc2) * C2_SCALE;
49a2ac ¤   max_dist += tdist*tdist;
1fcfc7 ······} else {
a18fe0 ¤   tdist = (x - minc2) * C2_SCALE;
70a2ac ¤   max_dist += tdist*tdist;
cd42cc ······}
ea6fe7 ····}
a0af5a
539e90 ····mindist[i] = min_dist;¤ /* save away the results */
a3298a ····if (max_dist < minmaxdist)
bc5517 ······minmaxdist = max_dist;
0bdf1c ··}
00af5a
9236e9 ··/* Now we know that no cell in the update box is more than minmaxdist
87f6ad ···* away from some colormap entry. ·Therefore, only colors that are
dab2cd ···* within minmaxdist of some part of the box need be considered.
fff9a6 ···*/
9ccb61 ··ncolors = 0;
896b9b ··for (i = 0; i < numcolors; i++) {
e3c023 ····if (mindist[i] <= minmaxdist)
750521 ······colorlist[ncolors++] = (JSAMPLE) i;
6fdf1c ··}
7aca74 ··return ncolors;
bcefe6 }
3faf5a
e8af5a
68afad LOCAL(void)
e97f21 find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
9941e1 ¤   ¤   ··int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
a3a2eb /* Find the closest colormap entry for each cell in the update box,
521d6f ·* given the list of candidate colors prepared by find_nearby_colors.
4e2ad8 ·* Return the indexes of the closest entries in the bestcolor[] array.
505671 ·* This routine uses Thomas' incremental distance calculation method to
c9dad8 ·* find the distance from a colormap entry to successive cells in the box.
e3495d ·*/
19bb36 {
ffb0e1 ··int ic0, ic1, ic2;
ab93e3 ··int i, icolor;
4d6010 ··register INT32 * bptr;¤   /* pointer into bestdist[] array */
fe9a27 ··JSAMPLE * cptr;¤  ¤   /* pointer into bestcolor[] array */
d79117 ··INT32 dist0, dist1;¤  ¤   /* initial distance values */
c26e61 ··register INT32 dist2;¤¤   /* current distance in inner loop */
5715b5 ··INT32 xx0, xx1;¤  ¤   /* distance increments */
3e1ff9 ··register INT32 xx2;
570b23 ··INT32 inc0, inc1, inc2;¤  /* initial values for increments */
--f2b2 000b6f1f06340100045 Page 12 of jquant2.c
1ec1b1 ··/* This array holds the distance to the nearest-so-far color for each cell */
7cb63c ··INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
fcaf5a
29325b ··/* Initialize best-distance for each cell of the update box */
0159f5 ··bptr = bestdist;
180131 ··for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
17df9e ····*bptr++ = 0x7FFFFFFFL;
f2de7b ··
0c2e67 ··/* For each color selected by find_nearby_colors,
94edaa ···* compute its distance to the center of each cell in the box.
f0b41c ···* If that's less than best-so-far, update best distance and color number.
7cf9a6 ···*/
81de7b ··
824ea0 ··/* Nominal steps between cell centers ("x" in Thomas article) */
a5e2bd #define STEP_C0 ·((1 << C0_SHIFT) * C0_SCALE)
9cef4e #define STEP_C1 ·((1 << C1_SHIFT) * C1_SCALE)
a4f95b #define STEP_C2 ·((1 << C2_SHIFT) * C2_SCALE)
cdde7b ··
0e6b9b ··for (i = 0; i < numcolors; i++) {
b8d0f3 ····icolor = GETJSAMPLE(colorlist[i]);
8186a5 ····/* Compute (square of) distance from minc0/c1/c2 to this color */
3a3a1b ····inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
f81861 ····dist0 = inc0*inc0;
2dce0b ····inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
02fc89 ····dist0 += inc1*inc1;
87da2a ····inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
47993d ····dist0 += inc2*inc2;
a8ef96 ····/* Form the initial difference increments */
1799b1 ····inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
fc580c ····inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
b812da ····inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
b2a6d3 ····/* Now loop over all cells in box, updating distance per Thomas method */
a96eb5 ····bptr = bestdist;
3a820d ····cptr = bestcolor;
2a7162 ····xx0 = inc0;
1726e4 ····for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
6b1033 ······dist1 = dist0;
ad4c87 ······xx1 = inc1;
2ecefc ······for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
0bcad2 ¤   dist2 = dist1;
616ed4 ¤   xx2 = inc2;
547b54 ¤   for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
93a199 ¤   ··if (dist2 < *bptr) {
6c8a13 ¤   ····*bptr = dist2;
3e1593 ¤   ····*cptr = (JSAMPLE) icolor;
5132a2 ¤   ··}
134d66 ¤   ··dist2 += xx2;
75ba45 ¤   ··xx2 += 2 * STEP_C2 * STEP_C2;
371641 ¤   ··bptr++;
cc97fe ¤   ··cptr++;
339371 ¤   }
9798fd ¤   dist1 += xx1;
b0ca06 ¤   xx1 += 2 * STEP_C1 * STEP_C1;
4042cc ······}
518fab ······dist0 += xx0;
ce5c8a ······xx0 += 2 * STEP_C0 * STEP_C0;
706fe7 ····}
1bdf1c ··}
08efe6 }
8faf5a
2caf5a
59afad LOCAL(void)
bbd21e fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
421171 /* Fill the inverse-colormap entries in the update box that contains */
a450b3 /* histogram cell c0/c1/c2. ·(Only that one cell MUST be filled, but */
19dddf /* we can fill as many others as we wish.) */
d3bb36 {
6fa2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
2ba71d ··hist3d histogram = cquantize->histogram;
af82ee ··int minc0, minc1, minc2;¤ /* lower left corner of update box */
f7b0e1 ··int ic0, ic1, ic2;
b68573 ··register JSAMPLE * cptr;¤ /* pointer into bestcolor[] array */
--81c6 0008bd8b59b40100045 Page 13 of jquant2.c
c563b8 ··register histptr cachep;¤ /* pointer into main cache array */
3c0b7f ··/* This array lists the candidate colormap indexes. */
c6da64 ··JSAMPLE colorlist[MAXNUMCOLORS];
7976ab ··int numcolors;¤   ¤   /* number of candidate colors */
398a0f ··/* This array holds the actually closest colormap index for each cell. */
a3c4b4 ··JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
43af5a
c876e1 ··/* Convert cell coordinates to update box ID */
bf6c1a ··c0 >>= BOX_C0_LOG;
8a0b28 ··c1 >>= BOX_C1_LOG;
fba27e ··c2 >>= BOX_C2_LOG;
c9af5a
95d181 ··/* Compute true coordinates of update box's origin corner.
193877 ···* Actually we compute the coordinates of the center of the corner
1c5465 ···* histogram cell, which are the lower bounds of the volume we care about.
1cf9a6 ···*/
e0a4a9 ··minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
591407 ··minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
09cde4 ··minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
1ade7b ··
0a391e ··/* Determine which colormap entries are close enough to be candidates
2283bb ···* for the nearest entry to some cell in the update box.
4df9a6 ···*/
036b94 ··numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
b2af5a
d423c0 ··/* Determine the actually nearest colors. */
a9b430 ··find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
cf0577 ¤   ¤   ···bestcolor);
4daf5a
c4dd7b ··/* Save the best color numbers (plus 1) in the main cache array */
a388ad ··c0 <<= BOX_C0_LOG;¤   ¤   /* convert ID back to base cell indexes */
de8f4d ··c1 <<= BOX_C1_LOG;
57261b ··c2 <<= BOX_C2_LOG;
9ac03e ··cptr = bestcolor;
919fcf ··for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
bf1459 ····for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
89db3b ······cachep = & histogram[c0+ic0][c1+ic1][c2];
d00113 ······for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
092896 ¤   *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
bb42cc ······}
0f6fe7 ····}
dcdf1c ··}
ffefe6 }
9caf5a
f3af5a
a338e5 /*
bb8c2c ·* Map some rows of pixels to the output colormapped representation.
b3495d ·*/
a3af5a
c40434 METHODDEF(void)
3dd3d3 pass2_no_dither (j_decompress_ptr cinfo,
6914dc ¤   ¤   ·JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
3201ec /* This version performs no dithering */
aabb36 {
87a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
50a71d ··hist3d histogram = cquantize->histogram;
0e43b7 ··register JSAMPROW inptr, outptr;
fd7eef ··register histptr cachep;
6b72ff ··register int c0, c1, c2;
c95b06 ··int row;
3f0f73 ··JDIMENSION col;
e88e6b ··JDIMENSION width = cinfo->output_width;
c7af5a
08d16f ··for (row = 0; row < num_rows; row++) {
3754a5 ····inptr = input_buf[row];
9b881c ····outptr = output_buf[row];
cd5874 ····for (col = width; col > 0; col--) {
302e5b ······/* get pixel value and index into the cache */
546ddd ······c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
048ae8 ······c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
6daba6 ······c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
8bf213 ······cachep = & histogram[c0][c1][c2];
--4bee 000111b952940100045 Page 14 of jquant2.c
5e4c2c ······/* If we have not seen this color before, find nearest colormap entry */
3c4584 ······/* and update the cache */
d43a11 ······if (*cachep == 0)
4a7204 ¤   fill_inverse_cmap(cinfo, c0,c1,c2);
494ba9 ······/* Now emit the colormap index for this cell */
d29a35 ······*outptr++ = (JSAMPLE) (*cachep - 1);
eb6fe7 ····}
4adf1c ··}
38efe6 }
89af5a
16af5a
6b0434 METHODDEF(void)
eb5e31 pass2_fs_dither (j_decompress_ptr cinfo,
6d14dc ¤   ¤   ·JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
6489c0 /* This version performs Floyd-Steinberg dithering */
9cbb36 {
50a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
53a71d ··hist3d histogram = cquantize->histogram;
023f7e ··register LOCFSERROR cur0, cur1, cur2;¤/* current error or pixel value */
5a6524 ··LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
13b25c ··LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
da304c ··register FSERRPTR errorptr;¤  /* => fserrors[] at column before current */
e629f2 ··JSAMPROW inptr;¤  ¤   /* => current input pixel */
d31ffc ··JSAMPROW outptr;¤ ¤   /* => current output pixel */
f151df ··histptr cachep;
14b88e ··int dir;¤ ¤   ¤   /* +1 or -1 depending on direction */
45488b ··int dir3;¤¤   ¤   /* 3*dir, for advancing inptr & errorptr */
7d5b06 ··int row;
9b0f73 ··JDIMENSION col;
828e6b ··JDIMENSION width = cinfo->output_width;
806697 ··JSAMPLE *range_limit = cinfo->sample_range_limit;
adbab5 ··int *error_limit = cquantize->error_limiter;
ec3d81 ··JSAMPROW colormap0 = cinfo->colormap[0];
a47a7e ··JSAMPROW colormap1 = cinfo->colormap[1];
f0b27f ··JSAMPROW colormap2 = cinfo->colormap[2];
c0ea99 ··SHIFT_TEMPS
04af5a
f1d16f ··for (row = 0; row < num_rows; row++) {
5554a5 ····inptr = input_buf[row];
9f881c ····outptr = output_buf[row];
0fb97e ····if (cquantize->on_odd_row) {
9c2288 ······/* work right to left in this row */
636505 ······inptr += (width-1) * 3;¤  /* so point to rightmost pixel */
0f14c8 ······outptr += width-1;
b16238 ······dir = -1;
a96eeb ······dir3 = -3;
9dcadb ······errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last colu¶
ec82d6 mn */
53624c ······cquantize->on_odd_row = FALSE; /* flip for next time */
4f6a79 ····} else {
b5c4d0 ······/* work left to right in this row */
41cb37 ······dir = 1;
6afef3 ······dir3 = 3;
e1da45 ······errorptr = cquantize->fserrors; /* => entry before first real column */
7e405e ······cquantize->on_odd_row = TRUE; /* flip for next time */
326fe7 ····}
e4cb41 ····/* Preset error values: no error propagated to first pixel from left */
f83890 ····cur0 = cur1 = cur2 = 0;
9ff1de ····/* and no error propagated to row below yet */
c1c1d2 ····belowerr0 = belowerr1 = belowerr2 = 0;
270874 ····bpreverr0 = bpreverr1 = bpreverr2 = 0;
96af5a
495874 ····for (col = width; col > 0; col--) {
4c0236 ······/* curN holds the error propagated from the previous pixel on the
5a55c5 ·······* current line. ·Add the error propagated from the previous line
01e807 ·······* to form the complete error correction term for this pixel, and
22e5ab ·······* round the error term (which is expressed * 16) to an integer.
de048a ·······* RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
127067 ·······* for either sign of the error value.
d5ce19 ·······* Note: errorptr points to *previous* column's array entry.
b8e9f1 ·······*/
11d870 ······cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
--07f1 00038fed63c40100045 Page 15 of jquant2.c
b3a146 ······cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
1b2a1c ······cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
d5dd9b ······/* Limit the error using transfer function set by init_error_limit.
db6046 ·······* See comments with init_error_limit for rationale.
d9e9f1 ·······*/
8bc9c7 ······cur0 = error_limit[cur0];
385cb5 ······cur1 = error_limit[cur1];
fdeb32 ······cur2 = error_limit[cur2];
740c5d ······/* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
d221de ·······* The maximum error is +- MAXJSAMPLE (or less with error limiting);
418359 ·······* this sets the required size of the range_limit array.
bfe9f1 ·······*/
2f787c ······cur0 += GETJSAMPLE(inptr[0]);
e02170 ······cur1 += GETJSAMPLE(inptr[1]);
20ca64 ······cur2 += GETJSAMPLE(inptr[2]);
de42a6 ······cur0 = GETJSAMPLE(range_limit[cur0]);
5b44db ······cur1 = GETJSAMPLE(range_limit[cur1]);
964e5c ······cur2 = GETJSAMPLE(range_limit[cur2]);
585720 ······/* Index into the cache with adjusted pixel value */
6c9d18 ······cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
04aeaf ······/* If we have not seen this color before, find nearest colormap */
801135 ······/* entry and update the cache */
413a11 ······if (*cachep == 0)
41b083 ¤   fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
0d4ba9 ······/* Now emit the colormap index for this cell */
caa345 ······{ register int pixcode = *cachep - 1;
5bd750 ¤   *outptr = (JSAMPLE) pixcode;
4f328d ¤   /* Compute representation error for this pixel */
43dcd0 ¤   cur0 -= GETJSAMPLE(colormap0[pixcode]);
0c6322 ¤   cur1 -= GETJSAMPLE(colormap1[pixcode]);
66ab25 ¤   cur2 -= GETJSAMPLE(colormap2[pixcode]);
3042cc ······}
78ddce ······/* Compute error fractions to be propagated to adjacent pixels.
924653 ·······* Add these into the running sums, and simultaneously shift the
9d13fe ·······* next-line error sums left by 1 column.
1be9f1 ·······*/
35737b ······{ register LOCFSERROR bnexterr, delta;
afaf5a
512768 ¤   bnexterr = cur0;¤   /* Process component 0 */
80ae05 ¤   delta = cur0 * 2;
f2dd42 ¤   cur0 += delta;¤ ¤   /* form error * 3 */
33d6f8 ¤   errorptr[0] = (FSERROR) (bpreverr0 + cur0);
04e6da ¤   cur0 += delta;¤ ¤   /* form error * 5 */
1f5029 ¤   bpreverr0 = belowerr0 + cur0;
dc7e4f ¤   belowerr0 = bnexterr;
16f052 ¤   cur0 += delta;¤ ¤   /* form error * 7 */
8c5b4e ¤   bnexterr = cur1;¤   /* Process component 1 */
e131d0 ¤   delta = cur1 * 2;
89778a ¤   cur1 += delta;¤ ¤   /* form error * 3 */
4a92eb ¤   errorptr[1] = (FSERROR) (bpreverr1 + cur1);
0d4c12 ¤   cur1 += delta;¤ ¤   /* form error * 5 */
908f8f ¤   bpreverr1 = belowerr1 + cur1;
1900a5 ¤   belowerr1 = bnexterr;
685a9a ¤   cur1 += delta;¤ ¤   /* form error * 7 */
e9df24 ¤   bnexterr = cur2;¤   /* Process component 2 */
4999be ¤   delta = cur2 * 2;
8180c3 ¤   cur2 += delta;¤ ¤   /* form error * 3 */
8f5ede ¤   errorptr[2] = (FSERROR) (bpreverr2 + cur2);
c2bb5b ¤   cur2 += delta;¤ ¤   /* form error * 5 */
01e774 ¤   bpreverr2 = belowerr2 + cur2;
f5839b ¤   belowerr2 = bnexterr;
56add3 ¤   cur2 += delta;¤ ¤   /* form error * 7 */
8b42cc ······}
3b8071 ······/* At this point curN contains the 7/16 error value to be propagated
f4deb3 ·······* to the next pixel on the current line, and all the errors for the
5e103e ·······* next line have been shifted over. ·We are therefore ready to move on.
45e9f1 ·······*/
59ca39 ······inptr += dir3;¤   ¤   /* Advance pixel pointers to next column */
696da3 ······outptr += dir;
a77902 ······errorptr += dir3;¤¤   /* advance errorptr to current column */
d66fe7 ····}
381e1a ····/* Post-loop cleanup: we must unload the final error values into the
--fd7a 000b083c96940100045 Page 16 of jquant2.c
c92a14 ·····* final fserrors[] entry. ·Note we need not unload belowerrN because
eac8ea ·····* it is for the dummy column before or after the actual array.
51d48d ·····*/
c4e8bb ····errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
3a1ed7 ····errorptr[1] = (FSERROR) bpreverr1;
efae52 ····errorptr[2] = (FSERROR) bpreverr2;
b0df1c ··}
e5efe6 }
8eaf5a
01af5a
3838e5 /*
422dfa ·* Initialize the error-limiting transfer function (lookup table).
73a720 ·* The raw F-S error computation can potentially compute error values of up to
0f2c0e ·* +- MAXJSAMPLE. ·But we want the maximum correction applied to a pixel to be
505c2c ·* much less, otherwise obviously wrong pixels will be created. ·(Typical
98cf27 ·* effects include weird fringes at color-area boundaries, isolated bright
25aad8 ·* pixels in a dark area, etc.) ·The standard advice for avoiding this problem
7c91c8 ·* is to ensure that the "corners" of the color cube are allocated as output
a0c28d ·* colors; then repeated errors in the same direction cannot cause cascading
4adf3c ·* error buildup. ·However, that only prevents the error from getting
7ba417 ·* completely out of hand; Aaron Giles reports that error limiting improves
11506c ·* the results even with corner colors allocated.
66a134 ·* A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
158d14 ·* well, but the smoother transfer function used below is even better. ·Thanks
274043 ·* to Aaron Giles for this idea.
87495d ·*/
90af5a
9eafad LOCAL(void)
587054 init_error_limit (j_decompress_ptr cinfo)
03ce03 /* Allocate and fill in the error_limiter table */
38bb36 {
f2a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
03a643 ··int * table;
68f0fd ··int in, out;
f8af5a
a99fba ··table = (int *) (*cinfo->mem->alloc_small)
5a7d95 ····((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int));
7e30b2 ··table += MAXJSAMPLE;¤ ¤   /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
6fe172 ··cquantize->error_limiter = table;
bfaf5a
efbe1d #define STEPSIZE ((MAXJSAMPLE+1)/16)
47abc3 ··/* Map errors 1:1 up to +- MAXJSAMPLE/16 */
9586ee ··out = 0;
5f63ca ··for (in = 0; in < STEPSIZE; in++, out++) {
d445a6 ····table[in] = out; table[-in] = -out;
2ddf1c ··}
40f699 ··/* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
f059a1 ··for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
6e45a6 ····table[in] = out; table[-in] = -out;
eedf1c ··}
5cc99b ··/* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
f41e7d ··for (; in <= MAXJSAMPLE; in++) {
2245a6 ····table[in] = out; table[-in] = -out;
c7df1c ··}
64f81d #undef STEPSIZE
ddefe6 }
7aaf5a
55af5a
cd38e5 /*
982a82 ·* Finish up at the end of each pass.
9f495d ·*/
a9af5a
9e0434 METHODDEF(void)
b71aa1 finish_pass1 (j_decompress_ptr cinfo)
37bb36 {
b5a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
a3af5a
88dba7 ··/* Select the representative colors and fill in cinfo->colormap */
488950 ··cinfo->colormap = cquantize->sv_colormap;
17cbd4 ··select_colors(cinfo, cquantize->desired);
08aa06 ··/* Force next pass to zero the color index table */
b05562 ··cquantize->needs_zeroed = TRUE;
--9cdf 000fa950c2640100045 Page 17 of jquant2.c
7aefe6 }
46af5a
8eaf5a
7c0434 METHODDEF(void)
49ec79 finish_pass2 (j_decompress_ptr cinfo)
73bb36 {
816ded ··/* no work */
f8efe6 }
aaaf5a
7baf5a
c438e5 /*
faf62f ·* Initialize for each processing pass.
f9495d ·*/
ceaf5a
a40434 METHODDEF(void)
bda6b5 start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
48bb36 {
16a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
59a71d ··hist3d histogram = cquantize->histogram;
bc17e0 ··int i;
a3af5a
9dd986 ··/* Only F-S dithering or no dithering is supported. */
6811cd ··/* If user asks for ordered dither, give him F-S. */
f49b20 ··if (cinfo->dither_mode != JDITHER_NONE)
401b7d ····cinfo->dither_mode = JDITHER_FS;
ecaf5a
dbb051 ··if (is_pre_scan) {
9fb894 ····/* Set up method pointers */
8a53dd ····cquantize->pub.color_quantize = prescan_quantize;
af0cdf ····cquantize->pub.finish_pass = finish_pass1;
1a0288 ····cquantize->needs_zeroed = TRUE; /* Always zero histogram */
3a49d8 ··} else {
eeb894 ····/* Set up method pointers */
2f4d6a ····if (cinfo->dither_mode == JDITHER_FS)
2e7a86 ······cquantize->pub.color_quantize = pass2_fs_dither;
9e842c ····else
bccdcb ······cquantize->pub.color_quantize = pass2_no_dither;
ace3bb ····cquantize->pub.finish_pass = finish_pass2;
78af5a
4b6a06 ····/* Make sure color count is acceptable */
96ed17 ····i = cinfo->actual_number_of_colors;
cdf2af ····if (i < 1)
d90431 ······ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
5138ca ····if (i > MAXNUMCOLORS)
90fb64 ······ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
58af5a
d3cab3 ····if (cinfo->dither_mode == JDITHER_FS) {
6ce4f5 ······size_t arraysize = (size_t) ((cinfo->output_width + 2) *
b70f43 ¤   ¤   ¤   ¤   ···(3 * SIZEOF(FSERROR)));
3e10f4 ······/* Allocate Floyd-Steinberg workspace if we didn't already. */
9ba256 ······if (cquantize->fserrors == NULL)
a0b583 ¤   cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
c92ed1 ¤   ··((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
f8a7b3 ······/* Initialize the propagated errors to zero. */
dc4e64 ······jzero_far((void FAR *) cquantize->fserrors, arraysize);
58a95c ······/* Make the error-limit table if we didn't already. */
c7b673 ······if (cquantize->error_limiter == NULL)
26bc1b ¤   init_error_limit(cinfo);
7bedd9 ······cquantize->on_odd_row = FALSE;
f76fe7 ····}
c9af5a
b3df1c ··}
c1a223 ··/* Zero the histogram or inverse color map, if necessary */
7ea1f0 ··if (cquantize->needs_zeroed) {
c3f48a ····for (i = 0; i < HIST_C0_ELEMS; i++) {
eff629 ······jzero_far((void FAR *) histogram[i],
1912a4 ¤   ¤   HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
c56fe7 ····}
b3f8fa ····cquantize->needs_zeroed = FALSE;
48df1c ··}
9aefe6 }
faaf5a
--8042 000ee128d4a40100045 Page 18 of jquant2.c
e0af5a
d338e5 /*
700d79 ·* Switch to a new external colormap between output passes.
29495d ·*/
fdaf5a
bf0434 METHODDEF(void)
a212bd new_color_map_2_quant (j_decompress_ptr cinfo)
c2bb36 {
94a2c9 ··my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
14af5a
673481 ··/* Reset the inverse color map */
dd5562 ··cquantize->needs_zeroed = TRUE;
75efe6 }
87af5a
46af5a
2a38e5 /*
bdde11 ·* Module initialization routine for 2-pass color quantization.
a6495d ·*/
cbaf5a
67f898 GLOBAL(void)
f5dd99 jinit_2pass_quantizer (j_decompress_ptr cinfo)
9fbb36 {
ebd87c ··my_cquantize_ptr cquantize;
7217e0 ··int i;
4faf5a
4f2dce ··cquantize = (my_cquantize_ptr)
843f03 ····(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
e01a84 ¤   ¤   ¤   ¤   SIZEOF(my_cquantizer));
a84cc0 ··cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
a9f4f7 ··cquantize->pub.start_pass = start_pass_2_quant;
f0c68e ··cquantize->pub.new_color_map = new_color_map_2_quant;
33fe5f ··cquantize->fserrors = NULL;¤  /* flag optional arrays not allocated */
b41054 ··cquantize->error_limiter = NULL;
4caf5a
94a29e ··/* Make sure jdmaster didn't give me a case I can't handle */
170bcf ··if (cinfo->out_color_components != 3)
a25682 ····ERREXIT(cinfo, JERR_NOTIMPL);
97af5a
527c60 ··/* Allocate the histogram/inverse colormap storage */
328145 ··cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
f81006 ····((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
42e501 ··for (i = 0; i < HIST_C0_ELEMS; i++) {
2986c0 ····cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
9c50cf ······((j_common_ptr) cinfo, JPOOL_IMAGE,
051c30 ·······HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
16df1c ··}
f98305 ··cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
00af5a
28c8b6 ··/* Allocate storage for the completed colormap, if required.
ebe9f6 ···* We do this now since it is FAR storage and may affect
5da198 ···* the memory manager's space calculations.
7ef9a6 ···*/
b4ece9 ··if (cinfo->enable_2pass_quant) {
2a6a06 ····/* Make sure color count is acceptable */
e5ecd7 ····int desired = cinfo->desired_number_of_colors;
ff69c3 ····/* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
a7e6f7 ····if (desired < 8)
c6fd52 ······ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
10919f ····/* Make sure colormap indexes can be represented by JSAMPLEs */
b6cb67 ····if (desired > MAXNUMCOLORS)
7dfb64 ······ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
76387e ····cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
b0218a ······((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
a7e46b ····cquantize->desired = desired;
d877a3 ··} else
00677f ····cquantize->sv_colormap = NULL;
cfaf5a
1ad986 ··/* Only F-S dithering or no dithering is supported. */
2d11cd ··/* If user asks for ordered dither, give him F-S. */
269b20 ··if (cinfo->dither_mode != JDITHER_NONE)
1c1b7d ····cinfo->dither_mode = JDITHER_FS;
eeaf5a
--9dc8 001055f27fd40100045 Page 19 of jquant2.c
55f2f6 ··/* Allocate Floyd-Steinberg workspace if necessary.
d223d6 ···* This isn't really needed until pass 2, but again it is FAR storage.
0493d3 ···* Although we will cope with a later change in dither_mode,
873c63 ···* we do not promise to honor max_memory_to_use if dither_mode changes.
96f9a6 ···*/
d1a3df ··if (cinfo->dither_mode == JDITHER_FS) {
4b232c ····cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
7c50cf ······((j_common_ptr) cinfo, JPOOL_IMAGE,
cb5017 ·······(size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
851f45 ····/* Might as well create the error-limiting table too. */
5e1a39 ····init_error_limit(cinfo);
54df1c ··}
cdefe6 }
9caf5a
05d24f #endif /* QUANT_2PASS_SUPPORTED */
--1289 0002a43500540100046 Page 1 of jutils.c
bc38e5 /*
712741 ·* jutils.c
2d775e ·*
44a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
20fb07 ·* This file is part of the Independent JPEG Group's software.
55a0d6 ·* For conditions of distribution and use, see the accompanying README file.
3c775e ·*
d579ac ·* This file contains tables and miscellaneous utility routines needed
6239e8 ·* for both compression and decompression.
b686c2 ·* Note we prefix all global names with "j" to minimize conflicts with
26f358 ·* a surrounding application.
50495d ·*/
38af5a
382bb6 #define JPEG_INTERNALS
e436a7 #include "jinclude.h"
1e6c8f #include "jpeglib.h"
90af5a
8daf5a
7938e5 /*
cee29d ·* jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
c573eb ·* of a DCT block read in natural order (left to right, top to bottom).
7b495d ·*/
c0af5a
4891fa #if 0¤  ¤   ¤   ¤   /* This table is not actually needed in v6a */
89af5a
4a6c61 const int jpeg_zigzag_order[DCTSIZE2] = {
def5ab ···0, ·1, ·5, ·6, 14, 15, 27, 28,
0bf8d5 ···2, ·4, ·7, 13, 16, 26, 29, 42,
69a5e2 ···3, ·8, 12, 17, 25, 30, 41, 43,
c11ab2 ···9, 11, 18, 24, 31, 40, 44, 53,
44af7d ··10, 19, 23, 32, 39, 45, 52, 54,
089edb ··20, 22, 33, 38, 46, 51, 55, 60,
2a6c4b ··21, 34, 37, 47, 50, 56, 59, 61,
379e01 ··35, 36, 48, 49, 57, 58, 62, 63
5482f7 };
eaaf5a
257454 #endif
30af5a
ba38e5 /*
095bc5 ·* jpeg_natural_order[i] is the natural-order position of the i'th element
3654f2 ·* of zigzag order.
17775e ·*
707fac ·* When reading corrupted data, the Huffman decoders could attempt
6d1fcc ·* to reference an entry beyond the end of this array (if the decoded
5cc24f ·* zero run length reaches past the end of the block). ·To prevent
1a58ab ·* wild stores without adding an inner-loop test, we put some extra
e60d82 ·* "63"s after the real entries. ·This will cause the extra coefficient
d476d8 ·* to be stored in location 63 of the block, not somewhere random.
f85c30 ·* The worst case would be a run-length of 15, which means we need 16
bf6364 ·* fake entries.
f3495d ·*/
aeaf5a
87c929 const int jpeg_natural_order[DCTSIZE2+16] = {
9b8c10 ··0, ·1, ·8, 16, ·9, ·2, ·3, 10,
73d1b1 ·17, 24, 32, 25, 18, 11, ·4, ·5,
a93908 ·12, 19, 26, 33, 40, 48, 41, 34,
cc5e6d ·27, 20, 13, ·6, ·7, 14, 21, 28,
69c6f6 ·35, 42, 49, 56, 57, 50, 43, 36,
1ade6f ·29, 22, 15, 23, 30, 37, 44, 51,
d7bf42 ·58, 59, 52, 45, 38, 31, 39, 46,
0df30f ·53, 60, 61, 54, 47, 55, 62, 63,
c0463d ·63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
e09077 ·63, 63, 63, 63, 63, 63, 63, 63
3482f7 };
b5af5a
68af5a
9038e5 /*
6deaf6 ·* Arithmetic utilities
e1495d ·*/
43af5a
962b63 GLOBAL(long)
2a8286 jdiv_round_up (long a, long b)
--fa48 000d79e674640100046 Page 2 of jutils.c
c5aa11 /* Compute a/b rounded up to next integer, ie, ceil(a/b) */
15f759 /* Assumes a >= 0, b > 0 */
9bbb36 {
a68815 ··return (a + b - 1L) / b;
0befe6 }
b3af5a
fbaf5a
112b63 GLOBAL(long)
503ca8 jround_up (long a, long b)
4ccf60 /* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
5ff759 /* Assumes a >= 0, b > 0 */
97bb36 {
1ae482 ··a += b - 1L;
98cb41 ··return a - (a % b);
06efe6 }
60af5a
b4af5a
1a4067 /* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
bbccdf ·* and coefficient-block arrays. ·This won't work on 80x86 because the arrays
8fc76d ·* are FAR and we're assuming a small-pointer memory model. ·However, some
8f78e0 ·* DOS compilers provide far-pointer versions of memcpy() and memset() even
2bd170 ·* in the small-model libraries. ·These will be used if USE_FMEM is defined.
2f6de0 ·* Otherwise, the routines below do it the hard way. ·(The performance cost
5f498f ·* is not all that great, because these routines aren't very heavily used.)
15495d ·*/
2aaf5a
ac2cbc #ifndef NEED_FAR_POINTERS¤  /* normal case, same as regular macros */
aad3f1 #define FMEMCOPY(dest,src,size)¤MEMCOPY(dest,src,size)
7dafcc #define FMEMZERO(target,size)¤  MEMZERO(target,size)
3a971e #else¤  ¤   ¤   ¤   /* 80x86 case, define if we can */
a128a3 #ifdef USE_FMEM
57fc8e #define FMEMCOPY(dest,src,size)¤_fmemcpy((void FAR *)(dest), (const void FAR *)¶
be923c (src), (size_t)(size))
ab9cff #define FMEMZERO(target,size)¤  _fmemset((void FAR *)(target), 0, (size_t)(size¶
cfc454 ))
f67454 #endif
517454 #endif
0baf5a
f2af5a
78f898 GLOBAL(void)
e8372b jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
9aabdd ¤   ¤   ···JSAMPARRAY output_array, int dest_row,
b81b13 ¤   ¤   ···int num_rows, JDIMENSION num_cols)
211ce0 /* Copy some rows of samples from one place to another.
811964 ·* num_rows rows are copied from input_array[source_row++]
b5950a ·* to output_array[dest_row++]; these areas may overlap for duplication.
b91133 ·* The source and destination arrays must be at least as wide as num_cols.
3b495d ·*/
dbbb36 {
9143b7 ··register JSAMPROW inptr, outptr;
ed7158 #ifdef FMEMCOPY
c36b6b ··register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
37db21 #else
197efa ··register JDIMENSION count;
447454 #endif
8a77d2 ··register int row;
95af5a
55a59a ··input_array += source_row;
cb4c29 ··output_array += dest_row;
69af5a
c0aeaf ··for (row = num_rows; row > 0; row--) {
6a5869 ····inptr = *input_array++;
6a62b4 ····outptr = *output_array++;
b17158 #ifdef FMEMCOPY
155a3f ····FMEMCOPY(outptr, inptr, count);
8fdb21 #else
394477 ····for (count = num_cols; count > 0; count--)
50232f ······*outptr++ = *inptr++;¤/* needn't bother with GETJSAMPLE() here */
477454 #endif
31df1c ··}
93efe6 }
d7af5a
--14f9 00174a48ba440100046 Page 3 of jutils.c
e0af5a
d8f898 GLOBAL(void)
0cb24d jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
7749c0 ¤   ¤   ·JDIMENSION num_blocks)
61b9a9 /* Copy a row of coefficient blocks from one place to another. */
b1bb36 {
cf7158 #ifdef FMEMCOPY
8d904b ··FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
9edb21 #else
fa99bd ··register JCOEFPTR inptr, outptr;
3c0c92 ··register long count;
4daf5a
ba51ae ··inptr = (JCOEFPTR) input_row;
615d4a ··outptr = (JCOEFPTR) output_row;
3c7f0f ··for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
57b833 ····*outptr++ = *inptr++;
ebdf1c ··}
cf7454 #endif
24efe6 }
fdaf5a
72af5a
fef898 GLOBAL(void)
3a4a3c jzero_far (void FAR * target, size_t bytestozero)
564dfd /* Zero out a chunk of FAR memory. */
9190c3 /* This might be sample-array data, block-array data, or alloc_large data. */
7bbb36 {
1c3c2b #ifdef FMEMZERO
f1417c ··FMEMZERO(target, bytestozero);
c8db21 #else
70b104 ··register char FAR * ptr = (char FAR *) target;
917b1c ··register size_t count;
ebaf5a
d3bfdb ··for (count = bytestozero; count > 0; count--) {
50a21c ····*ptr++ = 0;
54df1c ··}
837454 #endif
74efe6 }
--a7e2 0017decfc5b40100047 Page 1 of jversion.h
bc38e5 /*
4cd2e8 ·* jversion.h
3e775e ·*
f9a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
54fb07 ·* This file is part of the Independent JPEG Group's software.
aea0d6 ·* For conditions of distribution and use, see the accompanying README file.
49775e ·*
e1432e ·* This file contains software version identification.
54495d ·*/
6aaf5a
4eaf5a
98e9a7 #define JVERSION¤   "6a ·7-Feb-96"
d4af5a
7dc116 #define JCOPYRIGHT¤ "Copyright (C) 1996, Thomas G. Lane"
--07c8 000aad62cc940100048 Page 1 of pgpJPEG.c
a70335 /*____________________________________________________________________________
ecedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
bb4b0f ¤   All rights reserved.
b567c5 ¤
255eee ¤   $Id: pgpJPEG.c,v 1.2.8.1 1998/11/12 03:11:18 heller Exp $
2cf7f7 ____________________________________________________________________________*/
bbaf5a
5c0ccc #if PGP_MACINTOSH
d2156c #include <FSp_fopen.h>
ed7454 #endif
f7af5a
e836a7 #include "jinclude.h"
3b6c8f #include "jpeglib.h"
52af5a
192f8d #include "pgpErrors.h"
5808c5 #include "pgpJPEG.h"
790d08 #include "pgpMem.h"
a84919 #include "pgpUtilities.h"
d9af5a
4333c8 ¤   static void
73f83c JPEGErrorExit(j_common_ptr cinfo)
64bb36 {
ea61e0 ¤   PGPError¤   err;
9867c5 ¤
c591cf ¤   /* Always display the message */
4b5589 ¤   (*cinfo->err->output_message) (cinfo);
a7af5a
6c39b5 ¤   /* Let the memory manager delete any temp files before we die */
730395 ¤   jpeg_destroy(cinfo);
edaf5a
e06bfc ¤   pgpDebugMsg( "JPEGErrorExit(): Calling longjmp. Pray really hard..." );
7167c5 ¤
dc223e pgpFixBeforeShip( "Use better errors here" );
873895 ¤   /* Should do real error mapping here */
070eac ¤   err = cinfo->err->msg_code;
dab1f0 ¤   if( IsntPGPError( err ) )
036a43 ¤   ¤   err = -1;
1467c5 ¤
2d30d6 ¤   if( cinfo->is_decompressor )
52c7a1 ¤   {
0af3b4 ¤   ¤   JPEGDecompressionContext¤   *context;
e31b52 ¤   ¤
4ba2eb ¤   ¤   context = (JPEGDecompressionContext *) cinfo;
fa1b52 ¤   ¤
bb30da ¤   ¤   longjmp( context->exceptionBuffer, err );
e19371 ¤   }
480e24 ¤   else
b5c7a1 ¤   {
e80cb9 ¤   ¤   JPEGCompressionContext¤ *context;
dd1b52 ¤   ¤
049c09 ¤   ¤   context = (JPEGCompressionContext *) cinfo;
701b52 ¤   ¤
3530da ¤   ¤   longjmp( context->exceptionBuffer, err );
74f828 ¤   }¤
f5efe6 }
5daf5a
3a33c8 ¤   static void
c13403 JPEGOutputMessage(j_common_ptr cinfo)
4ebb36 {
fa1eb3 ¤   char buffer[JMSG_LENGTH_MAX];
b667c5 ¤
b739de ¤   /* Create the message */
e0cfbe ¤   (*cinfo->err->format_message) (cinfo, buffer);
aaaf5a
f25bc8 ¤   pgpDebugMsg( buffer );
d1efe6 }
2caf5a
c0c744 ¤   PGPError
ce9ca4 JPEGCreateCompress(JPEGCompressionContext *context)
e5bb36 {
b661e0 ¤   PGPError¤   err;
aa67c5 ¤
--d6e2 000adaa660b40100048 Page 2 of pgpJPEG.c
2777d3 ¤   err = setjmp( context->exceptionBuffer );
aab1f0 ¤   if( IsntPGPError( err ) )
49c7a1 ¤   {
5d69ca ¤   ¤   jpeg_create_compress( &context->cInfo );
2f9371 ¤   }
a967c5 ¤
1fdeb7 ¤   return( err );
e4efe6 }
b4af5a
c8c744 ¤   PGPError
303e4e JPEGCreateDecompress(JPEGDecompressionContext *context)
f9bb36 {
7161e0 ¤   PGPError¤   err;
3a67c5 ¤
1b77d3 ¤   err = setjmp( context->exceptionBuffer );
39b1f0 ¤   if( IsntPGPError( err ) )
25c7a1 ¤   {
73c132 ¤   ¤   jpeg_create_decompress( &context->dInfo );
5b9371 ¤   }
6d67c5 ¤
b2deb7 ¤   return( err );
8defe6 }
76af5a
ce6d52 ¤   void
1ae298 JPEGDestroyCompress(JPEGCompressionContext *context)
eebb36 {
6ac834 ¤   pgpAssertAddrValid( context, JPEGCompressionContext );
2c67c5 ¤
5b0a8e ¤   jpeg_destroy_compress( &context->cInfo );
84efe6 }
4caf5a
9e6d52 ¤   void
b6754b JPEGDestroyDecompress(JPEGDecompressionContext *context)
e1bb36 {
4dd6a6 ¤   pgpAssertAddrValid( context, JPEGDecompressionContext );
0667c5 ¤
4eb1a9 ¤   jpeg_destroy_decompress( &context->dInfo );
23efe6 }
baaf5a
c26d52 ¤   void
7e03ed JPEGInitCompressionContext(JPEGCompressionContext *context)
afbb36 {
6dc834 ¤   pgpAssertAddrValid( context, JPEGCompressionContext );
2767c5 ¤
838e85 ¤   pgpClearMemory( context, sizeof( *context ) );
fe67c5 ¤
941662 ¤   context->cInfo.err ¤¤   ¤   ¤   = jpeg_std_error( &context->errMgr );
d89e6d ¤   context->errMgr.error_exit¤ ¤   = JPEGErrorExit;
50e63d ¤   context->errMgr.output_message¤ = JPEGOutputMessage;
4befe6 }
adaf5a
736d52 ¤   void
b67d8e JPEGInitDecompressionContext(JPEGDecompressionContext *context)
a3bb36 {
eed6a6 ¤   pgpAssertAddrValid( context, JPEGDecompressionContext );
7f67c5 ¤
a28e85 ¤   pgpClearMemory( context, sizeof( *context ) );
9f67c5 ¤
0b5847 ¤   context->dInfo.err ¤¤   ¤   ¤   = jpeg_std_error( &context->errMgr );
939e6d ¤   context->errMgr.error_exit¤ ¤   = JPEGErrorExit;
4de63d ¤   context->errMgr.output_message¤ = JPEGOutputMessage;
a2efe6 }
f3af5a
896d52 ¤   void
a17b34 JPEGCloseCompressionFile(JPEGCompressionContext *context)
03bb36 {
b299b5 ¤   if( IsntNull( context->destFile ) )
acc7a1 ¤   {
6ff2c8 ¤   ¤   fclose( context->destFile );
7bbdb2 ¤   ¤   context->destFile = FALSE;
399371 ¤   }
adefe6 }
--0239 000628cae3140100048 Page 3 of pgpJPEG.c
e0af5a
2c6d52 ¤   void
f5926a JPEGCloseDecompressionFile(JPEGDecompressionContext *context)
67bb36 {
ba6130 ¤   if( IsntNull( context->sourceFile ) )
9bc7a1 ¤   {
ec643b ¤   ¤   fclose( context->sourceFile );
696a99 ¤   ¤   context->sourceFile = FALSE;
7c9371 ¤   }
78efe6 }
5caf5a
1866dd ¤   static PGPError
07eed8 OpenFile(
035f5a ¤   PGPFileSpecRef¤ fileSpecRef,
5257cb ¤   PGPBoolean¤ ¤   readOnly,
f5685d ¤   FILE¤   ¤   ¤   **fileRef)
a5bb36 {
5761e0 ¤   PGPError¤   err;
8567c5 ¤
f0e456 ¤   *fileRef = NULL;
c0af5a
e4c21c #if PGP_MACINTOSH¤  /* [ */
2ec7a1 ¤   {
2a1d18 ¤   ¤   FSSpec¤ fileSpec;
941b52 ¤   ¤
8157e4 ¤   ¤   err = PGPGetFSSpecFromFileSpec( fileSpecRef, &fileSpec );
ad86f8 ¤   ¤   if( IsntPGPError( err ) )
a15b34 ¤   ¤   {
bd641c ¤   ¤   ¤   *fileRef = FSp_fopen( &fileSpec, readOnly ? "rb" : "wb" );
ec0fe4 ¤   ¤   }
3a9371 ¤   }
4e68d8 #else¤  /* ][ */
e0c7a1 ¤   {
f856ef ¤   ¤   char¤   *path;
501b52 ¤   ¤
9787e3 ¤   ¤   err = PGPGetFullPathFromFileSpec( fileSpecRef, &path );
d886f8 ¤   ¤   if( IsntPGPError( err ) )
935b34 ¤   ¤   {
877c09 ¤   ¤   ¤   *fileRef = fopen( path, readOnly ? "rb" : "wb" );
6787c7 ¤   ¤   ¤
512daf ¤   ¤   ¤   PGPFreeData( path );
ce0fe4 ¤   ¤   }
659371 ¤   }
213167 #endif¤ /* ] */
91af5a
d4d1a0 ¤   if( IsntPGPError( err ) && IsNull( *fileRef ) )
ace749 ¤   ¤   err = kPGPError_FileNotFound;
a7af5a
45deb7 ¤   return( err );
44efe6 }
5267c5 ¤
f7c744 ¤   PGPError
218613 JPEGOpenCompressionFile(
ce8f36 ¤   JPEGCompressionContext ¤*context,
faf8d5 ¤   PGPFileSpecRef¤ ¤   ¤   fileSpecRef)
6bbb36 {
128e12 ¤   PGPError¤   err = kPGPError_NoErr;
42af5a
d21cec ¤   pgpAssert( IsNull( context->destFile ) );
7faf5a
fd0d64 ¤   err = OpenFile( fileSpecRef, FALSE, &context->destFile );
a1b1f0 ¤   if( IsntPGPError( err ) )
21c7a1 ¤   {
7438ed ¤   ¤   err = setjmp( context->exceptionBuffer );
26d3c7 ¤   ¤   if( err == kPGPError_NoErr )
f45b34 ¤   ¤   {
429ec8 ¤   ¤   ¤   jpeg_stdio_dest( &context->cInfo, context->destFile );
160fe4 ¤   ¤   }
6d0e1d ¤   ¤   else
6e5b34 ¤   ¤   {
3ee9a7 ¤   ¤   ¤   JPEGCloseCompressionFile( context );
620fe4 ¤   ¤   }
--cda8 0009f29866e40100048 Page 4 of pgpJPEG.c
a19371 ¤   }
0e0e24 ¤   else
96c7a1 ¤   {
fae749 ¤   ¤   err = kPGPError_FileNotFound;
5c9371 ¤   }
89af5a
40deb7 ¤   return( err );
d2efe6 }
a0af5a
a4c744 ¤   PGPError
e9bfa6 JPEGOpenDecompressionFile(
b4b799 ¤   JPEGDecompressionContext ¤  *context,
c7b7c0 ¤   PGPFileSpecRef¤ ¤   ¤   ¤   fileSpecRef,
4a41ac ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   readOnly)
a8bb36 {
8c8e12 ¤   PGPError¤   err = kPGPError_NoErr;
4e67c5 ¤
36f59f ¤   pgpAssert( IsNull( context->sourceFile ) );
3867c5 ¤
10da64 ¤   err = OpenFile( fileSpecRef, readOnly, &context->sourceFile );
37b1f0 ¤   if( IsntPGPError( err ) )
29c7a1 ¤   {
7538ed ¤   ¤   err = setjmp( context->exceptionBuffer );
dad3c7 ¤   ¤   if( err == kPGPError_NoErr )
265b34 ¤   ¤   {
a69da4 ¤   ¤   ¤   jpeg_stdio_src( &context->dInfo, context->sourceFile );
d80fe4 ¤   ¤   }
190e1d ¤   ¤   else
855b34 ¤   ¤   {
f4932f ¤   ¤   ¤   JPEGCloseDecompressionFile( context );
b00fe4 ¤   ¤   }
959371 ¤   }
ad0e24 ¤   else
a3c7a1 ¤   {
ece749 ¤   ¤   err = kPGPError_FileNotFound;
cf9371 ¤   }
77af5a
b2deb7 ¤   return( err );
55efe6 }
bbaf5a
e5c744 ¤   PGPError
9a56b9 JPEGReadHeader(
d4b799 ¤   JPEGDecompressionContext ¤  *context,
86abcd ¤   PGPBoolean ¤¤   ¤   ¤   ¤   requireImage)
7fbb36 {
bd61e0 ¤   PGPError¤   err;
ff67c5 ¤
4177d3 ¤   err = setjmp( context->exceptionBuffer );
f4b1f0 ¤   if( IsntPGPError( err ) )
09c7a1 ¤   {
794f0e ¤   ¤   int¤jpegResult;
6f1b52 ¤   ¤
4488ed ¤   ¤   jpegResult = jpeg_read_header( &context->dInfo, requireImage );
cc2305 ¤   ¤   if( jpegResult != JPEG_HEADER_OK )
ac5b34 ¤   ¤   {
f07ce1 ¤   ¤   ¤   err = kPGPError_CorruptData;
be0fe4 ¤   ¤   }
ce9371 ¤   }
3967c5 ¤
68deb7 ¤   return( err );
b2efe6 }
a4af5a
7ec744 ¤   PGPError
4d57f7 JPEGStartCompress(
fc8f36 ¤   JPEGCompressionContext ¤*context,
bea118 ¤   PGPBoolean¤ ¤   ¤   ¤   writeAllTables)
fabb36 {
c961e0 ¤   PGPError¤   err;
7967c5 ¤
4977d3 ¤   err = setjmp( context->exceptionBuffer );
9fb1f0 ¤   if( IsntPGPError( err ) )
9fc7a1 ¤   {
--d4f6 000fcfceb1b40100048 Page 5 of pgpJPEG.c
cf97f5 ¤   ¤   jpeg_start_compress( &context->cInfo, writeAllTables );
e29371 ¤   }
4f67c5 ¤
91deb7 ¤   return( err );
75efe6 }
34af5a
72c744 ¤   PGPError
4e175f JPEGStartDecompress(JPEGDecompressionContext *context)
01bb36 {
9461e0 ¤   PGPError¤   err;
3267c5 ¤
e077d3 ¤   err = setjmp( context->exceptionBuffer );
95b1f0 ¤   if( IsntPGPError( err ) )
d7c7a1 ¤   {
6aa4f9 ¤   ¤   jpeg_start_decompress( &context->dInfo );
cc9371 ¤   }
d267c5 ¤
f1deb7 ¤   return( err );
3befe6 }
7baf5a
43c744 ¤   PGPError
02e5d8 JPEGFinishCompress(JPEGCompressionContext *context)
7cbb36 {
d961e0 ¤   PGPError¤   err;
7f67c5 ¤
5777d3 ¤   err = setjmp( context->exceptionBuffer );
1db1f0 ¤   if( IsntPGPError( err ) )
77c7a1 ¤   {
a82a31 ¤   ¤   jpeg_finish_compress( &context->cInfo );
d89371 ¤   }
5167c5 ¤
23deb7 ¤   return( err );
58efe6 }
62af5a
59c744 ¤   PGPError
4ceff9 JPEGFinishDecompress(JPEGDecompressionContext *context)
26bb36 {
5061e0 ¤   PGPError¤   err;
1567c5 ¤
4c77d3 ¤   err = setjmp( context->exceptionBuffer );
3bb1f0 ¤   if( IsntPGPError( err ) )
acc7a1 ¤   {
cf290d ¤   ¤   jpeg_finish_decompress( &context->dInfo );
669371 ¤   }
5967c5 ¤
22deb7 ¤   return( err );
0befe6 }
58af5a
fbc744 ¤   PGPError
8f208d JPEGSetDefaults(JPEGCompressionContext *context)
dcbb36 {
c261e0 ¤   PGPError¤   err;
ab67c5 ¤
1e77d3 ¤   err = setjmp( context->exceptionBuffer );
53b1f0 ¤   if( IsntPGPError( err ) )
e5c7a1 ¤   {
6db428 ¤   ¤   jpeg_set_defaults( &context->cInfo );
1f9371 ¤   }
f167c5 ¤
1adeb7 ¤   return( err );
20efe6 }
acaf5a
9bc744 ¤   PGPError
cea5cd JPEGWriteScanlines(
5a8f36 ¤   JPEGCompressionContext ¤*context,
fbe03a ¤   JSAMPARRAY ¤¤   ¤   ¤   scanlines,
3b6a36 ¤   JDIMENSION ¤¤   ¤   ¤   maxScanlines,
7486f2 ¤   JDIMENSION ¤¤   ¤   ¤   *numWrittenScanlines)
31bb36 {
8f61e0 ¤   PGPError¤   err;
3267c5 ¤
fc77d3 ¤   err = setjmp( context->exceptionBuffer );
--4fc6 000eaf81fd940100048 Page 6 of pgpJPEG.c
54b1f0 ¤   if( IsntPGPError( err ) )
f1c7a1 ¤   {
2f4416 ¤   ¤   *numWrittenScanlines = jpeg_write_scanlines( &context->cInfo,
03d87b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   scanlines, maxScanlines );
d49371 ¤   }
550e24 ¤   else
dbc7a1 ¤   {
3d89e6 ¤   ¤   *numWrittenScanlines = 0;
ee9371 ¤   }
5e67c5 ¤
82deb7 ¤   return( err );
26efe6 }
32af5a
0dc744 ¤   PGPError
41be38 JPEGReadScanlines(
59b799 ¤   JPEGDecompressionContext ¤  *context,
e175d1 ¤   JSAMPARRAY ¤¤   ¤   ¤   ¤   scanlines,
603776 ¤   JDIMENSION ¤¤   ¤   ¤   ¤   maxScanlines,
ddf58f ¤   JDIMENSION ¤¤   ¤   ¤   ¤   *numReadScanlines)
cdbb36 {
1161e0 ¤   PGPError¤   err;
2d67c5 ¤
9977d3 ¤   err = setjmp( context->exceptionBuffer );
41b1f0 ¤   if( IsntPGPError( err ) )
8bc7a1 ¤   {
2d89bd ¤   ¤   *numReadScanlines = jpeg_read_scanlines( &context->dInfo,
867e01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   scanlines, maxScanlines);
cc9371 ¤   }
150e24 ¤   else
05c7a1 ¤   {
9d1afa ¤   ¤   *numReadScanlines = 0;
629371 ¤   }
6a67c5 ¤
22deb7 ¤   return( err );
efefe6 }
27af5a
9ec744 ¤   PGPError
a4ce03 JPEGCopyCriticalParameters(
03233e ¤   JPEGDecompressionContext ¤  *dContext,
51a6c9 ¤   JPEGCompressionContext ¤¤   *cContext)
34bb36 {
2661e0 ¤   PGPError¤   err;
2e67c5 ¤
42eca0 ¤   err = setjmp( dContext->exceptionBuffer );
39b1f0 ¤   if( IsntPGPError( err ) )
69c7a1 ¤   {
6dd409 ¤   ¤   jpeg_copy_critical_parameters( &dContext->dInfo, &cContext->cInfo );
af9371 ¤   }
ed67c5 ¤
73deb7 ¤   return( err );
a8efe6 }
3caf5a
38c744 ¤   PGPError
36ab87 JPEGSetColorSpace(
438f36 ¤   JPEGCompressionContext ¤*context,
bf0a1f ¤   J_COLOR_SPACE ¤ ¤   ¤   colorspace)
d3bb36 {
4d61e0 ¤   PGPError¤   err;
cb67c5 ¤
a577d3 ¤   err = setjmp( context->exceptionBuffer );
9db1f0 ¤   if( IsntPGPError( err ) )
b3c7a1 ¤   {
12e9f8 ¤   ¤   jpeg_set_colorspace( &context->cInfo, colorspace );
f69371 ¤   }
a067c5 ¤
2cdeb7 ¤   return( err );
1aefe6 }
ceaf5a
53c744 ¤   PGPError
cee5b4 JPEGDefaultColorSpace(JPEGCompressionContext *context)
0bbb36 {
ea61e0 ¤   PGPError¤   err;
--8a45 0016104381b40100048 Page 7 of pgpJPEG.c
2a67c5 ¤
fc77d3 ¤   err = setjmp( context->exceptionBuffer );
05b1f0 ¤   if( IsntPGPError( err ) )
5dc7a1 ¤   {
29941b ¤   ¤   jpeg_default_colorspace( &context->cInfo );
489371 ¤   }
f767c5 ¤
4adeb7 ¤   return( err );
d2efe6 }
9baf5a
27c744 ¤   PGPError
426084 JPEGSetQuality(
398f36 ¤   JPEGCompressionContext ¤*context,
cdbd8f ¤   PGPInt32¤   ¤   ¤   ¤   ·quality,
392e7d ¤   PGPBoolean¤ ¤   ¤   ¤   forceBaseline)
61bb36 {
e961e0 ¤   PGPError¤   err;
7b67c5 ¤
2b77d3 ¤   err = setjmp( context->exceptionBuffer );
a3b1f0 ¤   if( IsntPGPError( err ) )
18c7a1 ¤   {
e6848a ¤   ¤   jpeg_set_quality( &context->cInfo, quality, forceBaseline );
919371 ¤   }
4e67c5 ¤
b8deb7 ¤   return( err );
6fefe6 }
61af5a
--7c93 000d3a2b05440100049 Page 1 of pgpJPEG.h
a70335 /*____________________________________________________________________________
ecedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
bb4b0f ¤   All rights reserved.
b567c5 ¤
06bd6a ¤   $Id: pgpJPEG.h,v 1.2.8.1 1998/11/12 03:11:18 heller Exp $
a6f7f7 ____________________________________________________________________________*/
3baf5a
868025 #ifndef Included_pgpJPEG_h¤ /* [ */
9808d1 #define Included_pgpJPEG_h
29af5a
fcbd1b #include <setjmp.h>
2cfeb2 #include <stdio.h>
36af5a
386c8f #include "jpeglib.h"
70e82c #include "pgpPubTypes.h"
e5af5a
cfe732 #define¤kPGPDefaultJPEQQuality¤ ¤   70
ceaf5a
85933f typedef struct JPEGDecompressionContext
cfbb36 {
c3d2fe ¤   struct jpeg_decompress_struct¤  dInfo;¤ ¤   /* Must be first item */
addd53 ¤   struct jpeg_error_mgr¤  ¤   ¤   errMgr;
a2cb74 ¤   FILE¤   ¤   ¤   ¤   ¤   ¤   ¤   *sourceFile;
9062cf ¤   jmp_buf¤¤   ¤   ¤   ¤   ¤   ¤   exceptionBuffer;
cf67c5 ¤
288e92 } JPEGDecompressionContext;
f0af5a
20d3cc typedef struct JPEGCompressionContext
2bbb36 {
06a10f ¤   struct jpeg_compress_struct¤¤   cInfo;¤ ¤   /* Must be first item */
fcdd53 ¤   struct jpeg_error_mgr¤  ¤   ¤   errMgr;
3a3447 ¤   FILE¤   ¤   ¤   ¤   ¤   ¤   ¤   *destFile;
8f62cf ¤   jmp_buf¤¤   ¤   ¤   ¤   ¤   ¤   exceptionBuffer;
5a67c5 ¤
ecce49 } JPEGCompressionContext;
18af5a
c699c6 PGP_BEGIN_C_DECLARATIONS
6faf5a
a4cbcf #if PRAGMA_IMPORT_SUPPORTED
5cb981 #pragma import on
de7454 #endif
f3af5a
231bdd /* Compression: */
53af5a
9153b2 void¤   ¤   JPEGCloseCompressionFile(JPEGCompressionContext *context);
81da44 PGPError¤   JPEGCreateCompress(JPEGCompressionContext *context);
5bcb06 PGPError¤   JPEGDefaultColorSpace(JPEGCompressionContext *context);
eb7057 void¤   ¤   JPEGDestroyCompress(JPEGCompressionContext *context);
7ac3d3 PGPError¤   JPEGFinishDecompress(JPEGDecompressionContext *context);
d28798 void¤   ¤   JPEGInitCompressionContext(JPEGCompressionContext *context);
189f37 PGPError¤   JPEGOpenCompressionFile(JPEGCompressionContext *context,
4be04d ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef fileSpec);
3f697d PGPError¤   JPEGSetColorSpace(JPEGCompressionContext *context,
53b6bf ¤   ¤   ¤   ¤   ¤   J_COLOR_SPACE colorspace);
0493ec PGPError¤   JPEGSetDefaults(JPEGCompressionContext *context);
fa6740 PGPError¤   JPEGSetQuality(JPEGCompressionContext *context, PGPInt32 quality,
0012c9 ¤   ¤   ¤   ¤   ¤   PGPBoolean forceBaseline);
1a9229 PGPError¤   JPEGStartDecompress(JPEGDecompressionContext *context);
d68676 PGPError¤   JPEGWriteScanlines(JPEGCompressionContext *context,
034f3b ¤   ¤   ¤   ¤   ¤   JSAMPARRAY scanlines, JDIMENSION maxScanlines,
f48eaf ¤   ¤   ¤   ¤   ¤   JDIMENSION *numWrittenScanlines);
9b67c5 ¤
750607 /* Decompression: */
38af5a
741441 void¤   ¤   JPEGCloseDecompressionFile(JPEGDecompressionContext *context);
360236 PGPError¤   JPEGCreateDecompress(JPEGDecompressionContext *context);
5698f7 void¤   ¤   JPEGDestroyDecompress(JPEGDecompressionContext *context);
7863d6 PGPError¤   JPEGFinishCompress(JPEGCompressionContext *context);
221bd9 void¤   ¤   JPEGInitDecompressionContext(JPEGDecompressionContext *context);
2508c4 PGPError¤   JPEGOpenDecompressionFile(JPEGDecompressionContext ¤*context,
775a76 ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef fileSpec, PGPBoolean readOnly);
d3af6d PGPError¤   JPEGReadHeader(JPEGDecompressionContext *context,
--ac9b 001e177efac40100049 Page 2 of pgpJPEG.h
7edbf6 ¤   ¤   ¤   ¤   ¤   PGPBoolean requireImage);
8752ed PGPError¤   JPEGReadScanlines(JPEGDecompressionContext *context,
094f3b ¤   ¤   ¤   ¤   ¤   JSAMPARRAY scanlines, JDIMENSION maxScanlines,
8528da ¤   ¤   ¤   ¤   ¤   JDIMENSION *numReadScanlines);
529139 PGPError¤   JPEGStartCompress(JPEGCompressionContext *context,
e06e55 ¤   ¤   ¤   ¤   ¤   PGPBoolean writeAllTables);
92af5a
fbaf5a
33636c /* Other: */
2caf5a
73dcd4 PGPError¤   JPEGCopyCriticalParameters(JPEGDecompressionContext *dContext,
d9108c ¤   ¤   ¤   ¤   ¤   JPEGCompressionContext *cContext);
9f67c5 ¤
63cbcf #if PRAGMA_IMPORT_SUPPORTED
362ced #pragma import reset
eb7454 #endif
78af5a
e51254 PGP_END_C_DECLARATIONS
2eaf5a
dfaf5a
9e9896 #endif /* ] Included_pgpKeys_h */
28af5a
fd7e4d /*__Editor_settings____
a0af5a
e14126 ¤   Local Variables:
927b17 ¤   tab-width: 4
ff0e6c ¤   End:
2f5f8c ¤   vi: ts=4 sw=4
3b9e9b ¤   vim: si
e1d062 _____________________*/
--93db 0005ec8691a4010004a Page 1 of rdcolmap.c
bc38e5 /*
0984c3 ·* rdcolmap.c
eb775e ·*
f09e25 ·* Copyright (C) 1994-1996, Thomas G. Lane.
b1fb07 ·* This file is part of the Independent JPEG Group's software.
84a0d6 ·* For conditions of distribution and use, see the accompanying README file.
e4775e ·*
717a0d ·* This file implements djpeg's "-map file" switch. ·It reads a source image
9b7b6e ·* and constructs a colormap to be supplied to the JPEG decompressor.
60775e ·*
88057a ·* Currently, these file formats are supported for the map file:
15ac23 ·* ··GIF: the contents of the GIF's global colormap are used.
e907f2 ·* ··PPM (either text or raw flavor): the entire file is read and
eebc2b ·* ·····each unique pixel value is entered in the map.
3a529f ·* Note that reading a large PPM file will be horrendously slow.
2f48f5 ·* Typically, a PPM-format map file should contain just one pixel
2a1359 ·* of each desired color. ·Such a file can be extracted from an
3993ce ·* ordinary image PPM file with ppmtomap(1).
2c775e ·*
301b1c ·* Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not
e19478 ·* currently implemented.
cd495d ·*/
adaf5a
d57409 #include "cdjpeg.h"¤¤   /* Common decls for cjpeg/djpeg applications */
4faf5a
1bf94a #ifdef QUANT_2PASS_SUPPORTED¤   /* otherwise can't quantize to supplied map */
c1af5a
56209e /* Portions of this code are based on the PBMPLUS library, which is:
fd0158 **
f25d58 ** Copyright (C) 1988 by Jef Poskanzer.
b20158 **
7234f7 ** Permission to use, copy, modify, and distribute this software and its
691ff7 ** documentation for any purpose and without fee is hereby granted, provided
24fbe2 ** that the above copyright notice appear in all copies and that both that
2bc3ee ** copyright notice and this permission notice appear in supporting
39ffc9 ** documentation. ·This software is provided "as is" without express or
0ffce6 ** implied warranty.
817fe0 */
cdaf5a
52af5a
d038e5 /*
1ee7da ·* Add a (potentially) new color to the color map.
aa495d ·*/
ccaf5a
c1afad LOCAL(void)
0fcbd1 add_map_entry (j_decompress_ptr cinfo, int R, int G, int B)
acbb36 {
d23d81 ··JSAMPROW colormap0 = cinfo->colormap[0];
587a7e ··JSAMPROW colormap1 = cinfo->colormap[1];
d5b27f ··JSAMPROW colormap2 = cinfo->colormap[2];
82d255 ··int ncolors = cinfo->actual_number_of_colors;
6c650e ··int index;
dcaf5a
3b988a ··/* Check for duplicate color. */
db1447 ··for (index = 0; index < ncolors; index++) {
161ac2 ····if (GETJSAMPLE(colormap0[index]) == R &&
278c0c ¤   GETJSAMPLE(colormap1[index]) == G &&
d7a9ea ¤   GETJSAMPLE(colormap2[index]) == B)
0a8885 ······return;¤  ¤   ¤   /* color is already in map */
f9df1c ··}
26af5a
725941 ··/* Check for map overflow. */
64ce29 ··if (ncolors >= (MAXJSAMPLE+1))
a5d70c ····ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1));
46af5a
88a80d ··/* OK, add color to map. */
0e6cec ··colormap0[ncolors] = (JSAMPLE) R;
301d94 ··colormap1[ncolors] = (JSAMPLE) G;
e57bc8 ··colormap2[ncolors] = (JSAMPLE) B;
6279a6 ··cinfo->actual_number_of_colors++;
16efe6 }
5eaf5a
--6757 00015710a2e4010004a Page 2 of rdcolmap.c
e0af5a
d338e5 /*
845f04 ·* Extract color map from a GIF file.
94495d ·*/
70af5a
01afad LOCAL(void)
0ebd50 read_gif_map (j_decompress_ptr cinfo, FILE * infile)
a3bb36 {
8094b7 ··int header[13];
3af877 ··int i, colormaplen;
ff2221 ··int R, G, B;
d7af5a
1ed362 ··/* Initial 'G' has already been read by read_color_map */
1367bd ··/* Read the rest of the GIF header and logical screen descriptor */
9d53a0 ··for (i = 1; i < 13; i++) {
2483e2 ····if ((header[i] = getc(infile)) == EOF)
978852 ······ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
fbdf1c ··}
2baf5a
b1c997 ··/* Verify GIF Header */
33f254 ··if (header[1] != 'I' || header[2] != 'F')
1199d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
01af5a
fc1db9 ··/* There must be a global color map. */
2cc8d7 ··if ((header[10] & 0x80) == 0)
fe99d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
35af5a
528738 ··/* OK, fetch it. */
d89faa ··colormaplen = 2 << (header[10] & 0x07);
65af5a
d1706e ··for (i = 0; i < colormaplen; i++) {
5ecad1 ····R = getc(infile);
7f3f16 ····G = getc(infile);
493c5e ····B = getc(infile);
e130c0 ····if (R == EOF || G == EOF || B == EOF)
1d8852 ······ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
82878d ····add_map_entry(cinfo,
f179e3 ¤   ¤   ··R << (BITS_IN_JSAMPLE-8),
0f2c0c ¤   ¤   ··G << (BITS_IN_JSAMPLE-8),
d5e0a4 ¤   ¤   ··B << (BITS_IN_JSAMPLE-8));
badf1c ··}
4defe6 }
d7af5a
30af5a
fcb397 /* Support routines for reading PPM */
40af5a
d8af5a
f5aa6a LOCAL(int)
37791c pbm_getc (FILE * infile)
f200ab /* Read next char, skipping over any comments */
25d6b1 /* A comment/newline sequence is returned as a newline */
e8bb36 {
7ae9ed ··register int ch;
37de7b ··
5ee409 ··ch = getc(infile);
da7a6c ··if (ch == '#') {
6cc9a3 ····do {
5dfb4f ······ch = getc(infile);
52635d ····} while (ch != '\n' && ch != EOF);
e6df1c ··}
e2038c ··return ch;
39efe6 }
15af5a
75af5a
e59ca2 LOCAL(unsigned int)
ac58a9 read_pbm_integer (j_decompress_ptr cinfo, FILE * infile)
c704ec /* Read an unsigned decimal integer from the PPM file */
dfe2b6 /* Swallows one trailing character after the integer */
c403e8 /* Note that on a 16-bit-int machine, only values up to 64k can be read. */
fbff1f /* This should not be a problem in practice. */
a5bb36 {
15e9ed ··register int ch;
--26b2 0007eaaf7af4010004a Page 3 of rdcolmap.c
7e294e ··register unsigned int val;
40de7b ··
674147 ··/* Skip any leading whitespace */
cb565f ··do {
5020fc ····ch = pbm_getc(infile);
29482b ····if (ch == EOF)
6b8852 ······ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
c85379 ··} while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
2ade7b ··
f3401d ··if (ch < '0' || ch > '9')
c399d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
30de7b ··
2c7bba ··val = ch - '0';
77403c ··while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
f52833 ····val *= 10;
b2fad5 ····val += ch - '0';
fddf1c ··}
382ad6 ··return val;
31efe6 }
3caf5a
bbaf5a
9438e5 /*
27236c ·* Extract color map from a PPM file.
ea495d ·*/
eaaf5a
feafad LOCAL(void)
e53abb read_ppm_map (j_decompress_ptr cinfo, FILE * infile)
abbb36 {
0a649a ··int c;
1de344 ··unsigned int w, h, maxval, row, col;
892221 ··int R, G, B;
85af5a
30d18b ··/* Initial 'P' has already been read by read_color_map */
fa88e6 ··c = getc(infile);¤¤   /* save format discriminator for a sec */
5eaf5a
5dc80b ··/* while we fetch the remaining header info */
153ddc ··w = read_pbm_integer(cinfo, infile);
320594 ··h = read_pbm_integer(cinfo, infile);
980aed ··maxval = read_pbm_integer(cinfo, infile);
c9af5a
a420d9 ··if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
ab99d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
34af5a
e0f934 ··/* For now, we don't support rescaling from an unusual maxval. */
97eec8 ··if (maxval != (unsigned int) MAXJSAMPLE)
e599d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
5daf5a
331955 ··switch (c) {
c47859 ··case '3':¤¤   ¤   /* it's a text-format PPM file */
ce1ebf ····for (row = 0; row < h; row++) {
50da02 ······for (col = 0; col < w; col++) {
0522b6 ¤   R = read_pbm_integer(cinfo, infile);
709cfc ¤   G = read_pbm_integer(cinfo, infile);
bbdffd ¤   B = read_pbm_integer(cinfo, infile);
649017 ¤   add_map_entry(cinfo, R, G, B);
0a42cc ······}
b26fe7 ····}
3bab40 ····break;
f1af5a
e53345 ··case '6':¤¤   ¤   /* it's a raw-format PPM file */
a81ebf ····for (row = 0; row < h; row++) {
edda02 ······for (col = 0; col < w; col++) {
bf2838 ¤   R = pbm_getc(infile);
f0f149 ¤   G = pbm_getc(infile);
cded42 ¤   B = pbm_getc(infile);
da0c87 ¤   if (R == EOF || G == EOF || B == EOF)
85b415 ¤   ··ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
bf9017 ¤   add_map_entry(cinfo, R, G, B);
d842cc ······}
7b6fe7 ····}
1bab40 ····break;
7eaf5a
--c9a7 001185959134010004a Page 4 of rdcolmap.c
7e969d ··default:
8c99d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
54ab40 ····break;
20df1c ··}
cdefe6 }
d4af5a
3faf5a
ef38e5 /*
3425ea ·* Main entry point from djpeg.c.
4870fc ·* ·Input: opened input file (from file name argument on command line).
4e2308 ·* ·Output: colormap and actual_number_of_colors fields are set in cinfo.
b9495d ·*/
d7af5a
63f898 GLOBAL(void)
82a9fe read_color_map (j_decompress_ptr cinfo, FILE * infile)
69bb36 {
3e643f ··/* Allocate space for a color map of maximum supported size. */
74f7e0 ··cinfo->colormap = (*cinfo->mem->alloc_sarray)
f94144 ····((j_common_ptr) cinfo, JPOOL_IMAGE,
ff9816 ·····(JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3);
3e7b9e ··cinfo->actual_number_of_colors = 0; /* initialize map to empty */
ceaf5a
0439e9 ··/* Read first byte to determine file format */
9fdb56 ··switch (getc(infile)) {
31cf80 ··case 'G':
929911 ····read_gif_map(cinfo, infile);
5fab40 ····break;
045b00 ··case 'P':
63275f ····read_ppm_map(cinfo, infile);
27ab40 ····break;
ec969d ··default:
3699d9 ····ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
3aab40 ····break;
d9df1c ··}
72efe6 }
a1af5a
18d24f #endif /* QUANT_2PASS_SUPPORTED */
--503e 000b6503e944010004b Page 1 of rdjpgcom.c
bc38e5 /*
253a88 ·* rdjpgcom.c
68775e ·*
a923ef ·* Copyright (C) 1994-1995, Thomas G. Lane.
1afb07 ·* This file is part of the Independent JPEG Group's software.
aba0d6 ·* For conditions of distribution and use, see the accompanying README file.
2d775e ·*
118b3d ·* This file contains a very simple stand-alone application that displays
74ea77 ·* the text in COM (comment) markers in a JFIF file.
ff4264 ·* This may be useful as an example of the minimum logic needed to parse
654d23 ·* JPEG markers.
3b495d ·*/
28af5a
dacb27 #define JPEG_CJPEG_DJPEG¤   /* to get the command-line config symbols */
891735 #include "jinclude.h"¤  ¤   /* get auto-config symbols, <stdio.h> */
aaaf5a
18b54e #include <ctype.h>¤ ¤   /* to declare isupper(), tolower() */
cad35d #ifdef USE_SETMODE
1f4460 #include <fcntl.h>¤ ¤   /* to declare setmode()'s parameter macros */
954064 /* If you have setmode() but not <io.h>, just delete this line: */
a87878 #include <io.h>¤¤   ¤   /* to declare setmode() */
677454 #endif
8baf5a
7f2caf #ifdef USE_CCOMMAND¤¤   /* command-line reader for Macintosh */
a12aa1 #ifdef __MWERKS__
3f54f8 #include <SIOUX.h> ·············/* Metrowerks needs this */
a428c9 #include <console.h>¤   ¤   /* ... and this */
367454 #endif
6ffc7e #ifdef THINK_C
a53d29 #include <console.h>¤   ¤   /* Think declares it here */
f27454 #endif
e07454 #endif
3eaf5a
007a86 #ifdef DONT_USE_B_MODE¤ ¤   /* define mode parameters for fopen() */
19ea4e #define READ_BINARY¤"r"
4edb21 #else
baef4f #define READ_BINARY¤"rb"
187454 #endif
4faf5a
84c093 #ifndef EXIT_FAILURE¤   ¤   /* define exit() codes if not provided */
2cc447 #define EXIT_FAILURE ·1
297454 #endif
4ca95d #ifndef EXIT_SUCCESS
a04edf #ifdef VMS
188bc0 #define EXIT_SUCCESS ·1¤¤   /* VMS is very nonstandard */
fbdb21 #else
efae68 #define EXIT_SUCCESS ·0
6f7454 #endif
397454 #endif
7baf5a
c0af5a
2238e5 /*
0ab1dd ·* These macros are used to read the input file.
4b44ce ·* To reuse this code in another application, you might need to change these.
b5495d ·*/
13af5a
837ada static FILE * infile;¤  ¤   /* input JPEG file */
aeaf5a
8ab360 /* Return next input byte, or EOF if no more */
fc9e40 #define NEXTBYTE() ·getc(infile)
4eaf5a
b4af5a
a78fcc /* Error exit handler */
cc76e0 #define ERREXIT(msg) ·(fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
3aaf5a
74af5a
3b3858 /* Read one byte, testing for EOF */
ebbeb7 static int
044d2f read_1_byte (void)
96bb36 {
36649a ··int c;
b6af5a
--37bf 0004d995df94010004b Page 2 of rdjpgcom.c
0757a2 ··c = NEXTBYTE();
1909ce ··if (c == EOF)
c38493 ····ERREXIT("Premature EOF in JPEG file");
1e4dac ··return c;
7eefe6 }
6baf5a
7fc8c6 /* Read 2 bytes, convert to unsigned int */
c61c2f /* All 2-byte quantities in JPEG markers are MSB first */
778e83 static unsigned int
419fb8 read_2_bytes (void)
d3bb36 {
99ff86 ··int c1, c2;
cfaf5a
fcc4e4 ··c1 = NEXTBYTE();
da77b8 ··if (c1 == EOF)
b78493 ····ERREXIT("Premature EOF in JPEG file");
eb5ec5 ··c2 = NEXTBYTE();
0403d1 ··if (c2 == EOF)
7c8493 ····ERREXIT("Premature EOF in JPEG file");
bbe422 ··return (((unsigned int) c1) << 8) + ((unsigned int) c2);
3cefe6 }
0caf5a
ffaf5a
0438e5 /*
7b9544 ·* JPEG markers consist of one or more 0xFF bytes, followed by a marker
13b44b ·* code byte (which is not an FF). ·Here are the marker codes of interest
fa4750 ·* in this program. ·(See jdmarker.c for a more complete list.)
1b495d ·*/
62af5a
6869d4 #define M_SOF0 ·0xC0¤   ¤   /* Start Of Frame N */
3e9f95 #define M_SOF1 ·0xC1¤   ¤   /* N indicates which compression process */
11307e #define M_SOF2 ·0xC2¤   ¤   /* Only SOF0-SOF2 are now in common use */
2e5f0c #define M_SOF3 ·0xC3
ca589d #define M_SOF5 ·0xC5¤   ¤   /* NB: codes C4 and CC are NOT SOF markers */
07b6d5 #define M_SOF6 ·0xC6
fc2eb2 #define M_SOF7 ·0xC7
0684af #define M_SOF9 ·0xC9
46791d #define M_SOF10 0xCA
90cca0 #define M_SOF11 0xCB
68afcb #define M_SOF13 0xCD
bc710b #define M_SOF14 0xCE
89c4b6 #define M_SOF15 0xCF
d6113a #define M_SOI ··0xD8¤   ¤   /* Start Of Image (beginning of datastream) */
ef6da2 #define M_EOI ··0xD9¤   ¤   /* End Of Image (end of datastream) */
c22124 #define M_SOS ··0xDA¤   ¤   /* Start Of Scan (begins compressed data) */
783519 #define M_COM ··0xFE¤   ¤   /* COMment */
50af5a
72af5a
8f38e5 /*
c0c83a ·* Find the next JPEG marker and return its marker code.
930e65 ·* We expect at least one FF byte, possibly more if the compressor used FFs
ad0b6f ·* to pad the file.
259d9f ·* There could also be non-FF garbage between markers. ·The treatment of such
fc5b75 ·* garbage is unspecified; we choose to skip over it but emit a warning msg.
683797 ·* NB: this routine must not be used after seeing SOS marker, since it will
4c75d2 ·* not deal correctly with FF/00 sequences in the compressed image data...
78495d ·*/
fcaf5a
adbeb7 static int
6c9e1a next_marker (void)
8abb36 {
2b649a ··int c;
7a7afe ··int discarded_bytes = 0;
63af5a
bcd7a4 ··/* Find 0xFF byte; count and skip any non-FFs. */
f867d5 ··c = read_1_byte();
daa623 ··while (c != 0xFF) {
13e76e ····discarded_bytes++;
85648f ····c = read_1_byte();
51df1c ··}
54633b ··/* Get marker code byte, swallowing any duplicate FF bytes. ·Extra FFs
4d4e41 ···* are legal as pad bytes, so don't count them in discarded_bytes.
--ce23 000d86ca7b74010004b Page 3 of rdjpgcom.c
e2f9a6 ···*/
c1565f ··do {
d0648f ····c = read_1_byte();
ef775d ··} while (c == 0xFF);
33af5a
0183df ··if (discarded_bytes != 0) {
180175 ····fprintf(stderr, "Warning: garbage data found in JPEG file\n");
80df1c ··}
11af5a
4b4dac ··return c;
caefe6 }
edaf5a
27af5a
7438e5 /*
6f6c9c ·* Read the initial marker, which should be SOI.
b9683a ·* For a JFIF file, the first two bytes of the file should be literally
591a05 ·* 0xFF M_SOI. ·To be more general, we could use next_marker, but if the
f4c8dd ·* input file weren't actually JPEG at all, next_marker might read the whole
11daa8 ·* file and then return a misleading error message...
3b495d ·*/
6baf5a
05beb7 static int
8f44cc first_marker (void)
89bb36 {
4bff86 ··int c1, c2;
9aaf5a
4dc4e4 ··c1 = NEXTBYTE();
3e5ec5 ··c2 = NEXTBYTE();
c4f2f4 ··if (c1 != 0xFF || c2 != M_SOI)
ee391f ····ERREXIT("Not a JPEG file");
b5f315 ··return c2;
ceefe6 }
89af5a
77af5a
8838e5 /*
4eb377 ·* Most types of marker are followed by a variable-length parameter segment.
ab9baf ·* This routine skips over the parameters for any marker we don't otherwise
ff9fdc ·* want to process.
636408 ·* Note that we MUST skip the parameter segment explicitly in order not to
9b61be ·* be fooled by 0xFF bytes that might appear within the parameter segment;
67e2e6 ·* such bytes do NOT introduce new markers.
13495d ·*/
03af5a
392978 static void
771bbf skip_variable (void)
66703f /* Skip over an unknown or uninteresting variable-length marker */
c8bb36 {
ebd93c ··unsigned int length;
1baf5a
4521a0 ··/* Get the marker parameter length count */
e62d8e ··length = read_2_bytes();
290765 ··/* Length includes itself, so must be at least 2 */
19edcf ··if (length < 2)
7b161a ····ERREXIT("Erroneous JPEG marker length");
e7fe13 ··length -= 2;
75d068 ··/* Skip over the remaining bytes */
796e5d ··while (length > 0) {
3c5259 ····(void) read_1_byte();
8aebfc ····length--;
2adf1c ··}
beefe6 }
adaf5a
20af5a
d038e5 /*
89db1a ·* Process a COM marker.
974cdc ·* We want to print out the marker contents as legible text;
8fe4cf ·* we must guard against random junk and varying newline representations.
2e495d ·*/
beaf5a
212978 static void
e7f8c5 process_COM (void)
d8bb36 {
--a769 00045d15a564010004b Page 4 of rdjpgcom.c
ccd93c ··unsigned int length;
a95710 ··int ch;
9d7879 ··int lastch = 0;
beaf5a
3121a0 ··/* Get the marker parameter length count */
4b2d8e ··length = read_2_bytes();
3e0765 ··/* Length includes itself, so must be at least 2 */
2bedcf ··if (length < 2)
7f161a ····ERREXIT("Erroneous JPEG marker length");
62fe13 ··length -= 2;
0aaf5a
d76e5d ··while (length > 0) {
a2d4ea ····ch = read_1_byte();
5e3541 ····/* Emit the character in a readable form.
31ba23 ·····* Nonprintables are converted to \nnn form,
64e409 ·····* while \ is converted to \\.
91b136 ·····* Newlines in CR, CR/LF, or LF form will be printed as one newline.
77d48d ·····*/
aec3a5 ····if (ch == '\r') {
1446a0 ······printf("\n");
b33b08 ····} else if (ch == '\n') {
c2565f ······if (lastch != '\r')
a4270d ¤   printf("\n");
c5f48e ····} else if (ch == '\\') {
b98df5 ······printf("\\\\");
0276ff ····} else if (isprint(ch)) {
404ba6 ······putc(ch, stdout);
326a79 ····} else {
a95eae ······printf("\\%03o", ch);
eb6fe7 ····}
5396bd ····lastch = ch;
6debfc ····length--;
ccdf1c ··}
e4fee8 ··printf("\n");
50efe6 }
04af5a
65af5a
a238e5 /*
63e58f ·* Process a SOFn marker.
f1b2bd ·* This code is only needed if you want to know the image dimensions...
3a495d ·*/
95af5a
522978 static void
c279db process_SOFn (int marker)
e0bb36 {
cbd93c ··unsigned int length;
252234 ··unsigned int image_height, image_width;
b0c5df ··int data_precision, num_components;
51f27a ··const char * process;
7f0dcc ··int ci;
f3af5a
5ce136 ··length = read_2_bytes();¤ /* usual parameter length count */
4daf5a
206420 ··data_precision = read_1_byte();
a02476 ··image_height = read_2_bytes();
ddfc3a ··image_width = read_2_bytes();
296ae4 ··num_components = read_1_byte();
94af5a
3e86f7 ··switch (marker) {
355a96 ··case M_SOF0:¤ process = "Baseline"; ·break;
fe1906 ··case M_SOF1:¤ process = "Extended sequential"; ·break;
139b86 ··case M_SOF2:¤ process = "Progressive"; ·break;
bc6bf2 ··case M_SOF3:¤ process = "Lossless"; ·break;
5a670b ··case M_SOF5:¤ process = "Differential sequential"; ·break;
4f90f7 ··case M_SOF6:¤ process = "Differential progressive"; ·break;
486b8e ··case M_SOF7:¤ process = "Differential lossless"; ·break;
2ce125 ··case M_SOF9:¤ process = "Extended sequential, arithmetic coding"; ·break;
dd53ed ··case M_SOF10:¤process = "Progressive, arithmetic coding"; ·break;
80cc6c ··case M_SOF11:¤process = "Lossless, arithmetic coding"; ·break;
e7d791 ··case M_SOF13:¤process = "Differential sequential, arithmetic coding"; ·break;
2a7867 ··case M_SOF14:¤process = "Differential progressive, arithmetic coding"; break;
456589 ··case M_SOF15:¤process = "Differential lossless, arithmetic coding"; ·break;
--294b 000a25672794010004b Page 5 of rdjpgcom.c
f6fa57 ··default:¤ process = "Unknown"; ·break;
c7df1c ··}
8aaf5a
c84828 ··printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
11c589 ¤   ·image_width, image_height, num_components, data_precision);
b335f4 ··printf("JPEG process: %s\n", process);
28af5a
9cd82a ··if (length != (unsigned int) (8 + num_components * 3))
542a03 ····ERREXIT("Bogus SOF marker length");
e8af5a
ac4ad6 ··for (ci = 0; ci < num_components; ci++) {
e7e48c ····(void) read_1_byte();¤  /* Component ID code */
87621f ····(void) read_1_byte();¤  /* H, V sampling factors */
04217c ····(void) read_1_byte();¤  /* Quantization table number */
01df1c ··}
81efe6 }
cdaf5a
0aaf5a
7338e5 /*
62c4a4 ·* Parse the marker stream until SOS or EOI is seen;
874b32 ·* display any COM markers.
e0053f ·* While the companion program wrjpgcom will always insert COM markers before
5ae8f1 ·* SOFn, other implementations might not, so we scan to SOS before stopping.
63e3b1 ·* If we were only interested in the image dimensions, we would stop at SOFn.
cce6a0 ·* (Conversely, if we only cared about COM markers, there would be no need
888450 ·* for special code to handle SOFn; we could treat it like other markers.)
c7495d ·*/
d6af5a
66beb7 static int
2689bd scan_JPEG_header (int verbose)
72bb36 {
180fa5 ··int marker;
e8af5a
ccbac8 ··/* Expect SOI at start of file */
11f485 ··if (first_marker() != M_SOI)
3ed41a ····ERREXIT("Expected SOI marker first");
96af5a
fadf2d ··/* Scan miscellaneous markers until we reach SOS. */
c76015 ··for (;;) {
e7d908 ····marker = next_marker();
b7c4c4 ····switch (marker) {
c4b49c ····case M_SOF0:¤   ¤   /* Baseline */
e77f59 ····case M_SOF1:¤   ¤   /* Extended sequential, Huffman */
00d42e ····case M_SOF2:¤   ¤   /* Progressive, Huffman */
fc1bff ····case M_SOF3:¤   ¤   /* Lossless, Huffman */
df167c ····case M_SOF5:¤   ¤   /* Differential sequential, Huffman */
b1a7cc ····case M_SOF6:¤   ¤   /* Differential progressive, Huffman */
576e99 ····case M_SOF7:¤   ¤   /* Differential lossless, Huffman */
df9b87 ····case M_SOF9:¤   ¤   /* Extended sequential, arithmetic */
eff1d5 ····case M_SOF10:¤  ¤   /* Progressive, arithmetic */
ca2278 ····case M_SOF11:¤  ¤   /* Lossless, arithmetic */
687b15 ····case M_SOF13:¤  ¤   /* Differential sequential, arithmetic */
8de98b ····case M_SOF14:¤  ¤   /* Differential progressive, arithmetic */
4d255c ····case M_SOF15:¤  ¤   /* Differential lossless, arithmetic */
31d80b ······if (verbose)
0b6a3b ¤   process_SOFn(marker);
433dfa ······else
e517fd ¤   skip_variable();
fe88e1 ······break;
85af5a
387294 ····case M_SOS:¤¤   ¤   /* stop before hitting compressed data */
d95828 ······return marker;
44af5a
f8cf3a ····case M_EOI:¤¤   ¤   /* in case it's a tables-only JPEG stream */
cd5828 ······return marker;
2aaf5a
851617 ····case M_COM:
721041 ······process_COM();
ca88e1 ······break;
58af5a
444771 ····default:¤   ¤   ¤   /* Anything else just gets skipped */
a22a85 ······skip_variable();¤ ¤   /* we assume it has a parameter count... */
--a951 000672404bf4010004b Page 6 of rdjpgcom.c
2088e1 ······break;
fa6fe7 ····}
329c3d ··} /* end loop */
3befe6 }
7faf5a
4faf5a
f37313 /* Command line parsing code */
99af5a
063200 static const char * progname;¤  /* program name for error messages */
fbaf5a
07af5a
602978 static void
5f1148 usage (void)
b2b5d5 /* complain about bad command line */
84bb36 {
624b48 ··fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n");
6daf5a
6e132f ··fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname);
bcaf5a
a09cf5 ··fprintf(stderr, "Switches (names may be abbreviated):\n");
215de6 ··fprintf(stderr, " ·-verbose ···Also display dimensions of JPEG image\n");
c1af5a
14870b ··exit(EXIT_FAILURE);
49efe6 }
27af5a
53af5a
0fbeb7 static int
4a9b9d keymatch (char * arg, const char * keyword, int minchars)
292a88 /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
29f88e /* keyword is the constant keyword (must be lower case already), */
83d9b3 /* minchars is length of minimum legal abbreviation. */
dfbb36 {
bbf449 ··register int ca, ck;
dbd00d ··register int nmatched = 0;
d6af5a
a70558 ··while ((ca = *arg++) != '\0') {
3ea7a9 ····if ((ck = *keyword++) == '\0')
bde037 ······return 0;¤¤   ¤   /* arg longer than keyword, no good */
121201 ····if (isupper(ca))¤   ¤   /* force arg to lcase (assume ck is already) */
84112f ······ca = tolower(ca);
a81813 ····if (ca != ck)
e5f040 ······return 0;¤¤   ¤   /* no good */
f777ba ····nmatched++;¤¤   ¤   /* count matched characters */
63df1c ··}
72ed38 ··/* reached end of argument; fail if it's too short for unique abbrev */
51aca6 ··if (nmatched < minchars)
af958b ····return 0;
135b35 ··return 1;¤¤   ¤   /* A-OK */
a9efe6 }
6faf5a
b8af5a
9738e5 /*
a7eb85 ·* The main program.
91495d ·*/
8aaf5a
f04d2f int
b273e2 main (int argc, char **argv)
40bb36 {
4b9a4b ··int argn;
897cfe ··char * arg;
652659 ··int verbose = 0;
b6af5a
78209a ··/* On Mac, fetch a command line. */
268a88 #ifdef USE_CCOMMAND
07ad02 ··argc = ccommand(&argv);
dc7454 #endif
70af5a
78eb33 ··progname = argv[0];
ef20c8 ··if (progname == NULL || progname[0] == 0)
12ea46 ····progname = "rdjpgcom";¤ /* in case C library doesn't provide it */
05af5a
67e938 ··/* Parse switches, if any */
--cf09 0010d9c29304010004b Page 7 of rdjpgcom.c
542949 ··for (argn = 1; argn < argc; argn++) {
ffc53a ····arg = argv[argn];
1cb82c ····if (arg[0] != '-')
eab8f0 ······break;¤   ¤   ¤   /* not switch, must be file name */
ada72e ····arg++;¤ ¤   ¤   /* advance over '-' */
2b923f ····if (keymatch(arg, "verbose", 1)) {
40d835 ······verbose++;
0dce75 ····} else
0c8e9f ······usage();
3fdf1c ··}
83af5a
76f8b9 ··/* Open the input file. */
a1d20f ··/* Unix style: expect zero or one file name */
e8c632 ··if (argn < argc-1) {
5f7812 ····fprintf(stderr, "%s: only one input file\n", progname);
702b21 ····usage();
1ddf1c ··}
c1f20e ··if (argn < argc) {
08d483 ····if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
749afb ······fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
eda026 ······exit(EXIT_FAILURE);
906fe7 ····}
ed49d8 ··} else {
d7a011 ····/* default input file is stdin */
01c1f3 #ifdef USE_SETMODE¤ ¤   /* need to hack file mode? */
119142 ····setmode(fileno(stdin), O_BINARY);
807454 #endif
0e71bb #ifdef USE_FDOPEN¤  ¤   /* need to re-open in binary mode? */
34df7b ····if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
94c977 ······fprintf(stderr, "%s: can't open stdin\n", progname);
c7a026 ······exit(EXIT_FAILURE);
ad6fe7 ····}
eedb21 #else
54b274 ····infile = stdin;
127454 #endif
b3df1c ··}
0baf5a
d65ad8 ··/* Scan the JPEG headers. */
b98099 ··(void) scan_JPEG_header(verbose);
c7af5a
60b3af ··/* All done. */
0df77b ··exit(EXIT_SUCCESS);
97241d ··return 0;¤¤   ¤   /* suppress no-return-value warnings */
0defe6 }
--c39a 000be3bf1c34010004c Page 1 of rdswitch.c
bc38e5 /*
93aa02 ·* rdswitch.c
03775e ·*
04a060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
20fb07 ·* This file is part of the Independent JPEG Group's software.
84a0d6 ·* For conditions of distribution and use, see the accompanying README file.
3e775e ·*
bb3853 ·* This file contains routines to process some of cjpeg's more complicated
da622a ·* command-line switches. ·Switches processed here are:
24e299 ·*¤ -qtables file¤  ¤   Read quantization tables from text file
4f73d1 ·*¤ -scans file¤¤   Read scan script from text file
cd6601 ·*¤ -qslots N[,N,...]¤  Set component quantization table selectors
d63956 ·*¤ -sample HxV[,HxV,...]¤  Set component sampling factors
a1495d ·*/
47af5a
447409 #include "cdjpeg.h"¤¤   /* Common decls for cjpeg/djpeg applications */
051f4f #include <ctype.h>¤ ¤   /* to declare isdigit(), isspace() */
69af5a
d8af5a
afaa6a LOCAL(int)
2ebf4f text_getc (FILE * file)
f956f1 /* Read next char, skipping over any comments (# to end of line) */
b3d6b1 /* A comment/newline sequence is returned as a newline */
42bb36 {
c4e9ed ··register int ch;
6bde7b ··
d49bd8 ··ch = getc(file);
b77a6c ··if (ch == '#') {
35c9a3 ····do {
37afc2 ······ch = getc(file);
c2635d ····} while (ch != '\n' && ch != EOF);
cedf1c ··}
24038c ··return ch;
b4efe6 }
b5af5a
4faf5a
c9c4bf LOCAL(boolean)
5281b5 read_text_integer (FILE * file, long * result, int * termchar)
fa52bc /* Read an unsigned decimal integer from a file, store it in result */
447702 /* Reads one trailing character after the integer; returns it in termchar */
71bb36 {
19e9ed ··register int ch;
4673f5 ··register long val;
2bde7b ··
499cb9 ··/* Skip any leading whitespace, detect EOF */
1b565f ··do {
a94f4d ····ch = text_getc(file);
80c2a0 ····if (ch == EOF) {
7d5adf ······*termchar = ch;
96c39d ······return FALSE;
536fe7 ····}
25a0a8 ··} while (isspace(ch));
62de7b ··
06a0ab ··if (! isdigit(ch)) {
fb18ec ····*termchar = ch;
2030cb ····return FALSE;
bcdf1c ··}
70af5a
b47bba ··val = ch - '0';
173e7b ··while ((ch = text_getc(file)) != EOF) {
471224 ····if (! isdigit(ch))
6488e1 ······break;
aa2833 ····val *= 10;
90fad5 ····val += ch - '0';
23df1c ··}
77a5ba ··*result = val;
33ebba ··*termchar = ch;
c5d2c8 ··return TRUE;
7eefe6 }
e6af5a
2caf5a
bee553 GLOBAL(boolean)
--e89c 00006ada6354010004c Page 2 of rdswitch.c
42f9e0 read_quant_tables (j_compress_ptr cinfo, char * filename,
c28274 ¤   ¤   ···int scale_factor, boolean force_baseline)
5deebf /* Read a set of quantization tables from the specified file.
9c9ef1 ·* The file is plain ASCII text: decimal numbers with whitespace between.
af2250 ·* Comments preceded by '#' may be included in the file.
e28451 ·* There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
ad6176 ·* The tables are implicitly numbered 0,1,etc.
ed1f07 ·* NOTE: does not affect the qslots mapping, which will default to selecting
9baf51 ·* table 0 for luminance (or primary) components, 1 for chrominance components.
143a14 ·* You must use -qslots if you want a different component->table mapping.
18495d ·*/
51bb36 {
7f5bf0 ··FILE * fp;
b78fd5 ··int tblno, i, termchar;
13e370 ··long val;
fc7aaa ··unsigned int table[DCTSIZE2];
d6af5a
21dbde ··if ((fp = fopen(filename, "r")) == NULL) {
95cf10 ····fprintf(stderr, "Can't open table file %s\n", filename);
0530cb ····return FALSE;
55df1c ··}
9550de ··tblno = 0;
7faf5a
e414b1 ··while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table¶
fe495d ·*/
17dd3e ····if (tblno >= NUM_QUANT_TBLS) {
fccd6b ······fprintf(stderr, "Too many tables in file %s\n", filename);
6efa6a ······fclose(fp);
37c39d ······return FALSE;
9a6fe7 ····}
604830 ····table[0] = (unsigned int) val;
18c183 ····for (i = 1; i < DCTSIZE2; i++) {
3c5224 ······if (! read_text_integer(fp, &val, &termchar)) {
aedd7d ¤   fprintf(stderr, "Invalid table data in file %s\n", filename);
9a4334 ¤   fclose(fp);
49a230 ¤   return FALSE;
b042cc ······}
20b70a ······table[i] = (unsigned int) val;
516fe7 ····}
6ab7a9 ····jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
e66bfa ····tblno++;
bbdf1c ··}
acaf5a
6101fb ··if (termchar != EOF) {
ddf033 ····fprintf(stderr, "Non-numeric data in file %s\n", filename);
cab174 ····fclose(fp);
3430cb ····return FALSE;
bbdf1c ··}
27af5a
78ed24 ··fclose(fp);
23d2c8 ··return TRUE;
abefe6 }
dbaf5a
31af5a
23da64 #ifdef C_MULTISCAN_FILES_SUPPORTED
0eaf5a
87c4bf LOCAL(boolean)
21ce6b read_scan_integer (FILE * file, long * result, int * termchar)
53e29e /* Variant of read_text_integer that always looks for a non-space termchar;
d105a4 ·* this simplifies parsing of punctuation in scan scripts.
6e495d ·*/
f8bb36 {
36e9ed ··register int ch;
3baf5a
85fb63 ··if (! read_text_integer(file, result, termchar))
f330cb ····return FALSE;
d4e987 ··ch = *termchar;
5f8d21 ··while (ch != EOF && isspace(ch))
b54f4d ····ch = text_getc(file);
6307cf ··if (isdigit(ch)) {¤   ¤   /* oops, put it back */
5fa644 ····if (ungetc(ch, file) == EOF)
06c39d ······return FALSE;
--3cf4 0009214aea04010004c Page 3 of rdswitch.c
398670 ····ch = ' ';
0349d8 ··} else {
fb65ba ····/* Any separators other than ';' and ':' are ignored;
dbd851 ·····* this allows user to insert commas, etc, if desired.
d9d48d ·····*/
db33bb ····if (ch != EOF && ch != ';' && ch != ':')
89da20 ······ch = ' ';
2bdf1c ··}
5aebba ··*termchar = ch;
32d2c8 ··return TRUE;
c4efe6 }
d4af5a
e6af5a
42e553 GLOBAL(boolean)
b1943b read_scan_script (j_compress_ptr cinfo, char * filename)
c591fc /* Read a scan script from the specified text file.
a1d19d ·* Each entry in the file defines one scan to be emitted.
cdb8ef ·* Entries are separated by semicolons ';'.
d89987 ·* An entry contains one to four component indexes,
7507ab ·* optionally followed by a colon ':' and four progressive-JPEG parameters.
02c211 ·* The component indexes denote which component(s) are to be transmitted
3dd070 ·* in the current scan. ·The first component has index 0.
2d1d0c ·* Sequential JPEG is used if the progressive-JPEG parameters are omitted.
78950e ·* The file is free format text: any whitespace may appear between numbers
fa2e59 ·* and the ':' and ';' punctuation marks. ·Also, other punctuation (such
1d00d1 ·* as commas or dashes) can be placed between numbers if desired.
082250 ·* Comments preceded by '#' may be included in the file.
5e5dbc ·* Note: we do very little validity checking here;
1ab6a1 ·* jcmaster.c will validate the script parameters.
a2495d ·*/
24bb36 {
925bf0 ··FILE * fp;
67ea19 ··int scanno, ncomps, termchar;
11e370 ··long val;
8af279 ··jpeg_scan_info * scanptr;
8bd1db #define MAX_SCANS ·100¤ ¤   /* quite arbitrary limit */
625e5b ··jpeg_scan_info scans[MAX_SCANS];
94af5a
12dbde ··if ((fp = fopen(filename, "r")) == NULL) {
b087f5 ····fprintf(stderr, "Can't open scan definition file %s\n", filename);
8a30cb ····return FALSE;
76df1c ··}
be1a61 ··scanptr = scans;
0a1709 ··scanno = 0;
e4af5a
26215f ··while (read_scan_integer(fp, &val, &termchar)) {
a9ec60 ····if (scanno >= MAX_SCANS) {
29970c ······fprintf(stderr, "Too many scans defined in file %s\n", filename);
a7fa6a ······fclose(fp);
73c39d ······return FALSE;
a66fe7 ····}
5cbf76 ····scanptr->component_index[0] = (int) val;
19b648 ····ncomps = 1;
ca4b8d ····while (termchar == ' ') {
050963 ······if (ncomps >= MAX_COMPS_IN_SCAN) {
fa69d2 ¤   fprintf(stderr, "Too many components in one scan in file %s\n",
aa1d0b ¤   ¤   filename);
014334 ¤   fclose(fp);
90a230 ¤   return FALSE;
ef42cc ······}
d3472a ······if (! read_scan_integer(fp, &val, &termchar))
c1672e ¤   goto bogus;
d580d9 ······scanptr->component_index[ncomps] = (int) val;
b05d56 ······ncomps++;
bb6fe7 ····}
1ffeb5 ····scanptr->comps_in_scan = ncomps;
e0048f ····if (termchar == ':') {
31c180 ······if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
b7672e ¤   goto bogus;
fabc30 ······scanptr->Ss = (int) val;
6ac180 ······if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
92672e ¤   goto bogus;
--a5de 000002a60d54010004c Page 4 of rdswitch.c
6aa639 ······scanptr->Se = (int) val;
04c180 ······if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
04672e ¤   goto bogus;
332261 ······scanptr->Ah = (int) val;
82472a ······if (! read_scan_integer(fp, &val, &termchar))
cd672e ¤   goto bogus;
7b0ad8 ······scanptr->Al = (int) val;
bf6a79 ····} else {
ea7b04 ······/* set non-progressive parameters */
13525e ······scanptr->Ss = 0;
b68ab8 ······scanptr->Se = DCTSIZE2-1;
56c102 ······scanptr->Ah = 0;
0dae74 ······scanptr->Al = 0;
5d6fe7 ····}
ee1efb ····if (termchar != ';' && termchar != EOF) {
a2074f bogus:
e9575a ······fprintf(stderr, "Invalid scan entry format in file %s\n", filename);
dafa6a ······fclose(fp);
10c39d ······return FALSE;
c46fe7 ····}
0d21b0 ····scanptr++, scanno++;
1adf1c ··}
74af5a
d201fb ··if (termchar != EOF) {
7bf033 ····fprintf(stderr, "Non-numeric data in file %s\n", filename);
96b174 ····fclose(fp);
ee30cb ····return FALSE;
2ddf1c ··}
c2af5a
27a088 ··if (scanno > 0) {
d59cd8 ····/* Stash completed scan list in cinfo structure.
9d17c1 ·····* NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data,
abc776 ·····* but if you want to compress multiple images you'd want JPOOL_PERMANENT.
3ed48d ·····*/
2d4983 ····scanptr = (jpeg_scan_info *)
2a558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
c9c185 ¤   ¤   ¤   ¤   ··scanno * SIZEOF(jpeg_scan_info));
5563e3 ····MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info));
e855ff ····cinfo->scan_info = scanptr;
0987d0 ····cinfo->num_scans = scanno;
abdf1c ··}
9daf5a
84ed24 ··fclose(fp);
5ed2c8 ··return TRUE;
54efe6 }
f2af5a
7c0f79 #endif /* C_MULTISCAN_FILES_SUPPORTED */
f6af5a
c3af5a
6fe553 GLOBAL(boolean)
9b1c2e set_quant_slots (j_compress_ptr cinfo, char *arg)
203f8f /* Process a quantization-table-selectors parameter string, of the form
4f8cdf ·* ····N[,N,...]
cc30f7 ·* If there are more components than parameters, the last value is replicated.
06495d ·*/
4cbb36 {
6f2221 ··int val = 0;¤ ¤   ¤   /* default table # */
250dcc ··int ci;
719456 ··char ch;
7caf5a
1c77c3 ··for (ci = 0; ci < MAX_COMPONENTS; ci++) {
66dc51 ····if (*arg) {
c547bf ······ch = ',';¤¤   ¤   /* if not set by sscanf, will be ',' */
24aa2e ······if (sscanf(arg, "%d%c", &val, &ch) < 1)
b3a230 ¤   return FALSE;
20c2a2 ······if (ch != ',')¤   ¤   /* syntax check */
d4a230 ¤   return FALSE;
5409df ······if (val < 0 || val >= NUM_QUANT_TBLS) {
6dd64f ¤   fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
e33ca1 ¤   ¤   NUM_QUANT_TBLS-1);
39a230 ¤   return FALSE;
0042cc ······}
--6d1a 00105f5dc2a4010004c Page 5 of rdswitch.c
47b787 ······cinfo->comp_info[ci].quant_tbl_no = val;
9ee0c5 ······while (*arg && *arg++ != ',') /* advance to next segment of arg string */
ad81c7 ¤   ;
8a6a79 ····} else {
991316 ······/* reached end of parameter, set remaining components to last table */
2fb787 ······cinfo->comp_info[ci].quant_tbl_no = val;
486fe7 ····}
5cdf1c ··}
66d2c8 ··return TRUE;
a1efe6 }
82af5a
edaf5a
89e553 GLOBAL(boolean)
7003ff set_sample_factors (j_compress_ptr cinfo, char *arg)
556380 /* Process a sample-factors parameter string, of the form
d266b8 ·* ····HxV[,HxV,...]
be33b5 ·* If there are more components than parameters, "1x1" is assumed for the rest.
a1495d ·*/
2dbb36 {
f658ed ··int ci, val1, val2;
83dd66 ··char ch1, ch2;
54af5a
0f77c3 ··for (ci = 0; ci < MAX_COMPONENTS; ci++) {
90dc51 ····if (*arg) {
1b8c03 ······ch2 = ',';¤   ¤   /* if not set by sscanf, will be ',' */
0211a4 ······if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
39a230 ¤   return FALSE;
b8a9a6 ······if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
b7a230 ¤   return FALSE;
acf04a ······if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
daf4ef ¤   fprintf(stderr, "JPEG sampling factors must be 1..4\n");
daa230 ¤   return FALSE;
f042cc ······}
cb7de7 ······cinfo->comp_info[ci].h_samp_factor = val1;
01dab9 ······cinfo->comp_info[ci].v_samp_factor = val2;
d5e0c5 ······while (*arg && *arg++ != ',') /* advance to next segment of arg string */
7381c7 ¤   ;
636a79 ····} else {
f98385 ······/* reached end of parameter, set remaining components to 1x1 sampling */
4620b0 ······cinfo->comp_info[ci].h_samp_factor = 1;
439530 ······cinfo->comp_info[ci].v_samp_factor = 1;
d36fe7 ····}
22df1c ··}
84d2c8 ··return TRUE;
05efe6 }
--2fc4 00022e1ac014010004d Page 1 of rdtarga.c
bc38e5 /*
8e2646 ·* rdtarga.c
01775e ·*
bda060 ·* Copyright (C) 1991-1996, Thomas G. Lane.
3cfb07 ·* This file is part of the Independent JPEG Group's software.
c1a0d6 ·* For conditions of distribution and use, see the accompanying README file.
0d775e ·*
f0a146 ·* This file contains routines to read input images in Targa format.
f7775e ·*
5c0521 ·* These routines may need modification for non-Unix environments or
642dd4 ·* specialized applications. ·As they stand, they assume input from
f00fe7 ·* an ordinary stdio stream. ·They further assume that reading begins
00545a ·* at the start of the file; start_input may need work if the
3d0c5d ·* user interface has already read some data (e.g., to determine that
df52b1 ·* the file is indeed Targa format).
c5775e ·*
4f85b2 ·* Based on code contributed by Lee Daniel Crocker.
69495d ·*/
3baf5a
c67409 #include "cdjpeg.h"¤¤   /* Common decls for cjpeg/djpeg applications */
a2af5a
2346eb #ifdef TARGA_SUPPORTED
89af5a
f3af5a
016243 /* Macros to deal with unsigned chars as efficiently as compiler allows */
e4af5a
491190 #ifdef HAVE_UNSIGNED_CHAR
64984e typedef unsigned char U_CHAR;
5d2a56 #define UCH(x)¤ ((int) (x))
e2b8f0 #else /* !HAVE_UNSIGNED_CHAR */
bea57b #ifdef CHAR_IS_UNSIGNED
d65819 typedef char U_CHAR;
082a56 #define UCH(x)¤ ((int) (x))
b8db21 #else
7a5819 typedef char U_CHAR;
2304ba #define UCH(x)¤ ((int) (x) & 0xFF)
af7454 #endif
9993c4 #endif /* HAVE_UNSIGNED_CHAR */
c5af5a
7caf5a
42df7b #define¤ReadOK(file,buffer,len)¤(JFREAD(file,buffer,len) == ((size_t) (len)))
5aaf5a
b1af5a
c004ce /* Private version of data source object */
46af5a
046425 typedef struct _tga_source_struct * tga_source_ptr;
b2af5a
f62b6c typedef struct _tga_source_struct {
e1f5df ··struct cjpeg_source_struct pub; /* public fields */
96af5a
f50c5a ··j_compress_ptr cinfo;¤¤   /* back link saves passing separate parm */
76af5a
221dfc ··JSAMPARRAY colormap;¤ ¤   /* Targa colormap (converted to my format) */
66af5a
0e3207 ··jvirt_sarray_ptr whole_image;¤/* Needed if funny input row order */
bd5314 ··JDIMENSION current_row;¤  /* Current logical row number to read */
4eaf5a
11c14c ··/* Pointer to routine to extract next Targa pixel from input file */
9c327a ··JMETHOD(void, read_pixel, (tga_source_ptr sinfo));
20af5a
14e488 ··/* Result of read_pixel is delivered here: */
5abe4d ··U_CHAR tga_pixel[4];
95af5a
16eae0 ··int pixel_size;¤  ¤   /* Bytes per Targa pixel (1 to 4) */
bdaf5a
438dbb ··/* State info for reading RLE-coded pixels; both counts must be init to 0 */
d01f44 ··int block_count;¤ ¤   /* # of pixels remaining in RLE block */
11517b ··int dup_pixel_count;¤ ¤   /* # of times to duplicate previous pixel */
90af5a
94c0a0 ··/* This saves the correct pixel-row-expansion method for preload_image */
438943 ··JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
229c5d ¤   ¤   ¤   ¤   ·······cjpeg_source_ptr sinfo));
--a10d 000805a4ad94010004d Page 2 of rdtarga.c
a55f8e } tga_source_struct;
01af5a
3baf5a
01c0e8 /* For expanding 5-bit pixel values to 8-bit with best rounding */
6eaf5a
43f209 static const UINT8 c5to8bits[32] = {
951766 ····0, ··8, ·16, ·25, ·33, ·41, ·49, ·58,
8bd6b1 ···66, ·74, ·82, ·90, ·99, 107, 115, 123,
3985f6 ··132, 140, 148, 156, 165, 173, 181, 189,
e474d9 ··197, 206, 214, 222, 230, 239, 247, 255
7b82f7 };
13af5a
53af5a
d9af5a
91aa6a LOCAL(int)
3db9f1 read_byte (tga_source_ptr sinfo)
c268ba /* Read next byte from Targa file */
afbb36 {
fb2635 ··register FILE *infile = sinfo->pub.input_file;
7a4a91 ··register int c;
23af5a
6ba8a1 ··if ((c = getc(infile)) == EOF)
06e0ea ····ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
fc4dac ··return c;
8aefe6 }
53af5a
11af5a
1eafad LOCAL(void)
3ea2a7 read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize)
6e7db0 /* Read the colormap from a Targa file */
b8bb36 {
bd17e0 ··int i;
11af5a
c1b1ea ··/* Presently only handles 24-bit BGR format */
a0c4c1 ··if (mapentrysize != 24)
b5586c ····ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
fcaf5a
579906 ··for (i = 0; i < cmaplen; i++) {
4dc7d1 ····sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
993b11 ····sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
d5975e ····sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
5cdf1c ··}
f3efe6 }
ceaf5a
7eaf5a
3a38e5 /*
d11cea ·* read_pixel methods: get a single pixel from Targa file into tga_pixel[]
ce495d ·*/
53af5a
a30434 METHODDEF(void)
aefee4 read_non_rle_pixel (tga_source_ptr sinfo)
b9e81e /* Read one Targa pixel from the input file; no RLE expansion */
6dbb36 {
452635 ··register FILE *infile = sinfo->pub.input_file;
8939eb ··register int i;
35af5a
3dde56 ··for (i = 0; i < sinfo->pixel_size; i++) {
d5f25a ····sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
70df1c ··}
65efe6 }
4eaf5a
dcaf5a
540434 METHODDEF(void)
28cd1d read_rle_pixel (tga_source_ptr sinfo)
5ff64e /* Read one Targa pixel from the input file, expanding RLE data as needed */
56bb36 {
de2635 ··register FILE *infile = sinfo->pub.input_file;
1e39eb ··register int i;
5aaf5a
657562 ··/* Duplicate previously read pixel? */
edbc0c ··if (sinfo->dup_pixel_count > 0) {
804455 ····sinfo->dup_pixel_count--;
--3c78 0007d530e334010004d Page 3 of rdtarga.c
ff3471 ····return;
59df1c ··}
e7af5a
4a9465 ··/* Time to read RLE block header? */
66a126 ··if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
412dc4 ····i = read_byte(sinfo);
7a91d8 ····if (i & 0x80) {¤¤   /* Start of duplicate-pixel block? */
8de62f ······sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
e040a4 ······sinfo->block_count = 0;¤  /* then read new block header */
fc6a79 ····} else {
9685c4 ······sinfo->block_count = i & 0x7F; /* number of pixels after this one */
ac6fe7 ····}
39df1c ··}
95af5a
bd9a94 ··/* Read next pixel */
d6de56 ··for (i = 0; i < sinfo->pixel_size; i++) {
c6f25a ····sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
94df1c ··}
dcefe6 }
a5af5a
c3af5a
9938e5 /*
52494c ·* Read one row of pixels.
a3775e ·*
a03ddc ·* We provide several different versions depending on input file format.
8e495d ·*/
58af5a
31af5a
2b77ad METHODDEF(JDIMENSION)
95e452 get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
de76cf /* This version is for reading 8-bit grayscale pixels */
2cbb36 {
ee7df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
90485a ··register JSAMPROW ptr;
592043 ··register JDIMENSION col;
b6de7b ··
87cc76 ··ptr = source->pub.buffer[0];
0382b4 ··for (col = cinfo->image_width; col > 0; col--) {
c39a7a ····(*source->read_pixel) (source); /* Load next pixel into tga_pixel */
48320c ····*ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
7fdf1c ··}
ea7bf7 ··return 1;
a3efe6 }
8faf5a
6b77ad METHODDEF(JDIMENSION)
e88085 get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
467bff /* This version is for reading 8-bit colormap indexes */
d3bb36 {
d67df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
944301 ··register int t;
cf485a ··register JSAMPROW ptr;
6a2043 ··register JDIMENSION col;
680492 ··register JSAMPARRAY colormap = source->colormap;
28af5a
75cc76 ··ptr = source->pub.buffer[0];
3c82b4 ··for (col = cinfo->image_width; col > 0; col--) {
4b9a7a ····(*source->read_pixel) (source); /* Load next pixel into tga_pixel */
23ce7c ····t = UCH(source->tga_pixel[0]);
fa3c6b ····*ptr++ = colormap[0][t];
45a3be ····*ptr++ = colormap[1][t];
a80bd0 ····*ptr++ = colormap[2][t];
dedf1c ··}
f77bf7 ··return 1;
2eefe6 }
01af5a
4b77ad METHODDEF(JDIMENSION)
539a9f get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
e5a3b5 /* This version is for reading 16-bit pixels */
aebb36 {
de7df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
de4301 ··register int t;
7d485a ··register JSAMPROW ptr;
--81ff 000dd3575504010004d Page 4 of rdtarga.c
4a2043 ··register JDIMENSION col;
e6de7b ··
99cc76 ··ptr = source->pub.buffer[0];
dc82b4 ··for (col = cinfo->image_width; col > 0; col--) {
189a7a ····(*source->read_pixel) (source); /* Load next pixel into tga_pixel */
a3ce7c ····t = UCH(source->tga_pixel[0]);
c284fc ····t += UCH(source->tga_pixel[1]) << 8;
58e563 ····/* We expand 5 bit data to 8 bit sample width.
8fc342 ·····* The format of the 16-bit (LSB first) input word is
731437 ·····* ····xRRRRRGGGGGBBBBB
b7d48d ·····*/
8eccd3 ····ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F];
373600 ····t >>= 5;
8a3013 ····ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F];
913600 ····t >>= 5;
cb9c5c ····ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F];
cd02a9 ····ptr += 3;
83df1c ··}
1f7bf7 ··return 1;
c2efe6 }
f9af5a
1777ad METHODDEF(JDIMENSION)
54633e get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
138795 /* This version is for reading 24-bit pixels */
0dbb36 {
bf7df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
b0485a ··register JSAMPROW ptr;
172043 ··register JDIMENSION col;
b4de7b ··
6ecc76 ··ptr = source->pub.buffer[0];
7882b4 ··for (col = cinfo->image_width; col > 0; col--) {
c39a7a ····(*source->read_pixel) (source); /* Load next pixel into tga_pixel */
897c58 ····*ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */
2e3948 ····*ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]);
84320c ····*ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
72df1c ··}
9c7bf7 ··return 1;
30efe6 }
43af5a
b838e5 /*
ab18a6 ·* Targa also defines a 32-bit pixel format with order B,G,R,A.
e1f5b9 ·* We presently ignore the attribute byte, so the code for reading
4cee4f ·* these pixels is identical to the 24-bit routine above.
55579a ·* This works because the actual pixel length is only known to read_pixel.
6d495d ·*/
61af5a
b07d36 #define get_32bit_row ·get_24bit_row
7eaf5a
26af5a
3a38e5 /*
8e1975 ·* This method is for re-reading the input data in standard top-down
289111 ·* row order. ·The entire image has already been read into whole_image
e29086 ·* with proper conversion of pixel format, but it's in a funny row order.
0b495d ·*/
49af5a
e577ad METHODDEF(JDIMENSION)
fdd97b get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
3cbb36 {
a57df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
655d5c ··JDIMENSION source_row;
0baf5a
fba90c ··/* Compute row of source that maps to current_row of normal order */
63f57f ··/* For now, assume image is bottom-up and not interlaced. */
3db1dc ··/* NEEDS WORK to support interlaced images! */
e5f0d2 ··source_row = cinfo->image_height - source->current_row - 1;
f5af5a
4d3af6 ··/* Fetch that row from virtual array */
5eaa5a ··source->pub.buffer = (*cinfo->mem->access_virt_sarray)
955ed4 ····((j_common_ptr) cinfo, source->whole_image,
65b677 ·····source_row, (JDIMENSION) 1, FALSE);
86af5a
dd1308 ··source->current_row++;
--f60d 00074da13424010004d Page 5 of rdtarga.c
3d7bf7 ··return 1;
c5efe6 }
84af5a
c2af5a
5a38e5 /*
d3ee31 ·* This method loads the image into whole_image during the first call on
d03e95 ·* get_pixel_rows. ·The get_pixel_rows pointer is then adjusted to call
ad6116 ·* get_memory_row on subsequent calls.
f4495d ·*/
63af5a
a977ad METHODDEF(JDIMENSION)
c6b095 preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
d1bb36 {
267df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
291c44 ··JDIMENSION row;
da4b16 ··cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
3eaf5a
490f8d ··/* Read the data into a virtual array in input-file row order. */
9324c6 ··for (row = 0; row < cinfo->image_height; row++) {
5b76b6 ····if (progress != NULL) {
88a483 ······progress->pub.pass_counter = (long) row;
986ce6 ······progress->pub.pass_limit = (long) cinfo->image_height;
514f25 ······(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
836fe7 ····}
a372a3 ····source->pub.buffer = (*cinfo->mem->access_virt_sarray)
60d1a4 ······((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE);
7267d0 ····(*source->get_pixel_rows) (cinfo, sinfo);
e0df1c ··}
b4b25b ··if (progress != NULL)
44e6de ····progress->completed_extra_passes++;
eeaf5a
a136a8 ··/* Set up to read from the virtual array in unscrambled order */
2c8c7b ··source->pub.get_pixel_rows = get_memory_row;
e54517 ··source->current_row = 0;
5b7080 ··/* And read the first row */
98fab8 ··return get_memory_row(cinfo, sinfo);
5befe6 }
e5af5a
39af5a
b638e5 /*
9dc007 ·* Read the file header; return image size and component count.
73495d ·*/
3aaf5a
900434 METHODDEF(void)
d72f7f start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
04bb36 {
7a7df4 ··tga_source_ptr source = (tga_source_ptr) sinfo;
bdb2b4 ··U_CHAR targaheader[18];
12316c ··int idlen, cmaptype, subtype, flags, interlace_type, components;
28bc78 ··unsigned int width, height, maplen;
fb02e6 ··boolean is_bottom_up;
d0af5a
d30d40 #define GET_2B(offset)¤ ((unsigned int) UCH(targaheader[offset]) + \
77154c ¤   ¤   ¤   ·(((unsigned int) UCH(targaheader[offset+1])) << 8))
30af5a
fbc855 ··if (! ReadOK(source->pub.input_file, targaheader, 18))
0cc1f3 ····ERREXIT(cinfo, JERR_INPUT_EOF);
6daf5a
e45e45 ··/* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
6f498c ··if (targaheader[16] == 15)
85a4e9 ····targaheader[16] = 16;
b3af5a
504c49 ··idlen = UCH(targaheader[0]);
3a0060 ··cmaptype = UCH(targaheader[1]);
49bb93 ··subtype = UCH(targaheader[2]);
0b5410 ··maplen = GET_2B(5);
0db856 ··width = GET_2B(12);
5c545c ··height = GET_2B(14);
87159f ··source->pixel_size = UCH(targaheader[16]) >> 3;
2d6a1b ··flags = UCH(targaheader[17]);¤/* Image Descriptor byte */
71af5a
74a486 ··is_bottom_up = ((flags & 0x20) == 0);¤/* bit 5 set => top-down */
--add5 0002ed897964010004d Page 6 of rdtarga.c
97b49b ··interlace_type = flags >> 6;¤ /* bits 6/7 are interlace code */
d7af5a
0a7c87 ··if (cmaptype > 1 ||¤  ¤   /* cmaptype must be 0 or 1 */
55783f ······source->pixel_size < 1 || source->pixel_size > 4 ||
e9e33d ······(UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
c915d3 ······interlace_type != 0)¤ /* currently don't allow interlaced image */
b3da7f ····ERREXIT(cinfo, JERR_TGA_BADPARMS);
60de7b ··
1a493d ··if (subtype > 8) {
def55a ····/* It's an RLE-coded file */
b71131 ····source->read_pixel = read_rle_pixel;
03860a ····source->block_count = source->dup_pixel_count = 0;
d9cc71 ····subtype -= 8;
2a49d8 ··} else {
55dacc ····/* Non-RLE file */
6c1f18 ····source->read_pixel = read_non_rle_pixel;
c2df1c ··}
e0af5a
e7f1f5 ··/* Now should have subtype 1, 2, or 3 */
aaaea9 ··components = 3;¤  ¤   /* until proven different */
eb2467 ··cinfo->in_color_space = JCS_RGB;
35af5a
bd63c9 ··switch (subtype) {
41b15d ··case 1:¤  ¤   ¤   /* Colormapped image */
8f41c7 ····if (source->pixel_size == 1 && cmaptype == 1)
00ae05 ······source->get_pixel_rows = get_8bit_row;
d2842c ····else
c6d87e ······ERREXIT(cinfo, JERR_TGA_BADPARMS);
25971c ····TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
c1ab40 ····break;
1cf8c4 ··case 2:¤  ¤   ¤   /* RGB image */
31ef47 ····switch (source->pixel_size) {
8cfaa9 ····case 2:
ce2de3 ······source->get_pixel_rows = get_16bit_row;
2d88e1 ······break;
baa075 ····case 3:
8b8b1e ······source->get_pixel_rows = get_24bit_row;
b588e1 ······break;
ca2c70 ····case 4:
4e365d ······source->get_pixel_rows = get_32bit_row;
d288e1 ······break;
0db53c ····default:
95d87e ······ERREXIT(cinfo, JERR_TGA_BADPARMS);
e488e1 ······break;
b56fe7 ····}
880eb4 ····TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
40ab40 ····break;
39da64 ··case 3:¤  ¤   ¤   /* Grayscale image */
341d48 ····components = 1;
ab620e ····cinfo->in_color_space = JCS_GRAYSCALE;
a8d99f ····if (source->pixel_size == 1)
85adfd ······source->get_pixel_rows = get_8bit_gray_row;
55842c ····else
a8d87e ······ERREXIT(cinfo, JERR_TGA_BADPARMS);
a07dc0 ····TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
b7ab40 ····break;
7d969d ··default:
15da7f ····ERREXIT(cinfo, JERR_TGA_BADPARMS);
1eab40 ····break;
70df1c ··}
c6af5a
7d992e ··if (is_bottom_up) {
f4aa91 ····/* Create a virtual array to buffer the upside-down image. */
86a01b ····source->whole_image = (*cinfo->mem->request_virt_sarray)
6a4d57 ······((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
2972cb ·······(JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
c04a86 ····if (cinfo->progress != NULL) {
2a391c ······cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
e499b7 ······progress->total_extra_passes++; /* count file input as separate pass */
9a6fe7 ····}
d6b521 ····/* source->pub.buffer will point to the virtual array. */
2ec6b7 ····source->pub.buffer_height = 1; /* in case anyone looks at it */
--9feb 001107ae75c4010004d Page 7 of rdtarga.c
5e4776 ····source->pub.get_pixel_rows = preload_image;
2f49d8 ··} else {
6aed8b ····/* Don't need a virtual array, but do need a one-row input buffer. */
3938ac ····source->whole_image = NULL;
4abfa5 ····source->pub.buffer = (*cinfo->mem->alloc_sarray)
9750cf ······((j_common_ptr) cinfo, JPOOL_IMAGE,
79b9a6 ·······(JDIMENSION) width * components, (JDIMENSION) 1);
89ea20 ····source->pub.buffer_height = 1;
93c444 ····source->pub.get_pixel_rows = source->get_pixel_rows;
abdf1c ··}
c9de7b ··
0e61cd ··while (idlen--)¤  ¤   /* Throw away ID field */
aa5c47 ····(void) read_byte(source);
79af5a
48f719 ··if (maplen > 0) {
255c45 ····if (maplen > 256 || GET_2B(3) != 0)
0c3b4c ······ERREXIT(cinfo, JERR_TGA_BADCMAP);
821ca8 ····/* Allocate space to store the colormap */
6bc2d1 ····source->colormap = (*cinfo->mem->alloc_sarray)
8d4d4a ······((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
82f04b ····/* and read it from the file */
b5497e ····read_colormap(source, (int) maplen, UCH(targaheader[7]));
8149d8 ··} else {
31369c ····if (cmaptype)¤  ¤   /* but you promised a cmap! */
5bd87e ······ERREXIT(cinfo, JERR_TGA_BADPARMS);
1ff9d7 ····source->colormap = NULL;
1bdf1c ··}
a0af5a
2a6d72 ··cinfo->input_components = components;
7cffb5 ··cinfo->data_precision = 8;
a95bf5 ··cinfo->image_width = width;
4cc27d ··cinfo->image_height = height;
6aefe6 }
eeaf5a
60af5a
3a38e5 /*
2333ed ·* Finish up at the end of the file.
ad495d ·*/
26af5a
b90434 METHODDEF(void)
b6ba18 finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
7ebb36 {
4b6ded ··/* no work */
2befe6 }
57af5a
74af5a
aa38e5 /*
645206 ·* The module selection routine for Targa format input.
7a495d ·*/
faaf5a
8fe396 GLOBAL(cjpeg_source_ptr)
2bd9e2 jinit_read_targa (j_compress_ptr cinfo)
64bb36 {
1ef37a ··tga_source_ptr source;
acaf5a
cea7b7 ··/* Create module interface object */
798953 ··source = (tga_source_ptr)
aa558d ······(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
475884 ¤   ¤   ¤   ¤   ··SIZEOF(tga_source_struct));
58594a ··source->cinfo = cinfo;¤   /* make back link for subroutines */
308f0a ··/* Fill in method ptrs, except get_pixel_rows which start_input sets */
e4f9fa ··source->pub.start_input = start_input_tga;
8eed9f ··source->pub.finish_input = finish_input_tga;
1aaf5a
274b6e ··return (cjpeg_source_ptr) source;
c5efe6 }
05af5a
107d96 #endif /* TARGA_SUPPORTED */
--e1fe 000910bfb164010004e Page 1 of wrjpgcom.c
bc38e5 /*
7e0bcc ·* wrjpgcom.c
f8775e ·*
1123ef ·* Copyright (C) 1994-1995, Thomas G. Lane.
85fb07 ·* This file is part of the Independent JPEG Group's software.
1ba0d6 ·* For conditions of distribution and use, see the accompanying README file.
c6775e ·*
886059 ·* This file contains a very simple stand-alone application that inserts
54e37e ·* user-supplied text as a COM (comment) marker in a JFIF file.
0c4264 ·* This may be useful as an example of the minimum logic needed to parse
7d4d23 ·* JPEG markers.
7b495d ·*/
03af5a
09cb27 #define JPEG_CJPEG_DJPEG¤   /* to get the command-line config symbols */
7f1735 #include "jinclude.h"¤  ¤   /* get auto-config symbols, <stdio.h> */
f0af5a
a3d9e9 #ifndef HAVE_STDLIB_H¤  ¤   /* <stdlib.h> should declare malloc() */
78af22 extern void * malloc ();
427454 #endif
f9b54e #include <ctype.h>¤ ¤   /* to declare isupper(), tolower() */
dad35d #ifdef USE_SETMODE
1c4460 #include <fcntl.h>¤ ¤   /* to declare setmode()'s parameter macros */
904064 /* If you have setmode() but not <io.h>, just delete this line: */
977878 #include <io.h>¤¤   ¤   /* to declare setmode() */
0e7454 #endif
beaf5a
f32caf #ifdef USE_CCOMMAND¤¤   /* command-line reader for Macintosh */
852aa1 #ifdef __MWERKS__
1d54f8 #include <SIOUX.h> ·············/* Metrowerks needs this */
3c28c9 #include <console.h>¤   ¤   /* ... and this */
307454 #endif
93fc7e #ifdef THINK_C
a93d29 #include <console.h>¤   ¤   /* Think declares it here */
fd7454 #endif
197454 #endif
8faf5a
ab7a86 #ifdef DONT_USE_B_MODE¤ ¤   /* define mode parameters for fopen() */
faea4e #define READ_BINARY¤"r"
ec9e7e #define WRITE_BINARY¤   "w"
66db21 #else
65ef4f #define READ_BINARY¤"rb"
c6deb8 #define WRITE_BINARY¤   "wb"
b57454 #endif
0eaf5a
aac093 #ifndef EXIT_FAILURE¤   ¤   /* define exit() codes if not provided */
6fc447 #define EXIT_FAILURE ·1
4c7454 #endif
cca95d #ifndef EXIT_SUCCESS
cb4edf #ifdef VMS
208bc0 #define EXIT_SUCCESS ·1¤¤   /* VMS is very nonstandard */
55db21 #else
ecae68 #define EXIT_SUCCESS ·0
0b7454 #endif
fc7454 #endif
58af5a
99e0f6 /* Reduce this value if your malloc() can't allocate blocks up to 64K.
172a94 ·* On DOS, compiling in large model is usually a better solution.
4c495d ·*/
d7af5a
f53387 #ifndef MAX_COM_LENGTH
576674 #define MAX_COM_LENGTH 65000¤   /* must be < 65534 in any case */
697454 #endif
41af5a
86af5a
6338e5 /*
c6ca77 ·* These macros are used to read the input file and write the output file.
1244ce ·* To reuse this code in another application, you might need to change these.
8d495d ·*/
7eaf5a
3d7ada static FILE * infile;¤  ¤   /* input JPEG file */
f8af5a
91b360 /* Return next input byte, or EOF if no more */
--96d7 0006e149cf44010004e Page 2 of wrjpgcom.c
b19e40 #define NEXTBYTE() ·getc(infile)
26af5a
789703 static FILE * outfile;¤ ¤   /* output JPEG file */
b4af5a
fb2ffb /* Emit an output byte */
00be4d #define PUTBYTE(x) ·putc((x), outfile)
e9af5a
29af5a
8a8fcc /* Error exit handler */
5876e0 #define ERREXIT(msg) ·(fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
1daf5a
99af5a
f23858 /* Read one byte, testing for EOF */
86beb7 static int
164d2f read_1_byte (void)
14bb36 {
2d649a ··int c;
c5af5a
b157a2 ··c = NEXTBYTE();
d709ce ··if (c == EOF)
ff8493 ····ERREXIT("Premature EOF in JPEG file");
fc4dac ··return c;
3fefe6 }
13af5a
13c8c6 /* Read 2 bytes, convert to unsigned int */
031c2f /* All 2-byte quantities in JPEG markers are MSB first */
258e83 static unsigned int
ce9fb8 read_2_bytes (void)
0ebb36 {
b1ff86 ··int c1, c2;
e3af5a
f3c4e4 ··c1 = NEXTBYTE();
2777b8 ··if (c1 == EOF)
9a8493 ····ERREXIT("Premature EOF in JPEG file");
d05ec5 ··c2 = NEXTBYTE();
7303d1 ··if (c2 == EOF)
de8493 ····ERREXIT("Premature EOF in JPEG file");
f6e422 ··return (((unsigned int) c1) << 8) + ((unsigned int) c2);
94efe6 }
f7af5a
06af5a
fadb8d /* Routines to write data to output file */
08af5a
1e2978 static void
a688c2 write_1_byte (int c)
debb36 {
a97238 ··PUTBYTE(c);
52efe6 }
ecaf5a
372978 static void
05e298 write_2_bytes (unsigned int val)
d4bb36 {
3ece37 ··PUTBYTE((val >> 8) & 0xFF);
9a7367 ··PUTBYTE(val & 0xFF);
2eefe6 }
fdaf5a
572978 static void
7f9d85 write_marker (int marker)
93bb36 {
3a9782 ··PUTBYTE(0xFF);
09fd5e ··PUTBYTE(marker);
77efe6 }
dfaf5a
c42978 static void
230e77 copy_rest_of_file (void)
71bb36 {
d8649a ··int c;
caaf5a
62b6eb ··while ((c = NEXTBYTE()) != EOF)
112e68 ····PUTBYTE(c);
7fefe6 }
6eaf5a
--1c69 0007c782c804010004e Page 3 of wrjpgcom.c
e0af5a
d338e5 /*
059544 ·* JPEG markers consist of one or more 0xFF bytes, followed by a marker
a4b44b ·* code byte (which is not an FF). ·Here are the marker codes of interest
334750 ·* in this program. ·(See jdmarker.c for a more complete list.)
b1495d ·*/
77af5a
bd69d4 #define M_SOF0 ·0xC0¤   ¤   /* Start Of Frame N */
189f95 #define M_SOF1 ·0xC1¤   ¤   /* N indicates which compression process */
d5307e #define M_SOF2 ·0xC2¤   ¤   /* Only SOF0-SOF2 are now in common use */
b55f0c #define M_SOF3 ·0xC3
c8589d #define M_SOF5 ·0xC5¤   ¤   /* NB: codes C4 and CC are NOT SOF markers */
b0b6d5 #define M_SOF6 ·0xC6
fc2eb2 #define M_SOF7 ·0xC7
9f84af #define M_SOF9 ·0xC9
77791d #define M_SOF10 0xCA
a9cca0 #define M_SOF11 0xCB
91afcb #define M_SOF13 0xCD
7f710b #define M_SOF14 0xCE
27c4b6 #define M_SOF15 0xCF
37113a #define M_SOI ··0xD8¤   ¤   /* Start Of Image (beginning of datastream) */
9d6da2 #define M_EOI ··0xD9¤   ¤   /* End Of Image (end of datastream) */
652124 #define M_SOS ··0xDA¤   ¤   /* Start Of Scan (begins compressed data) */
9f3519 #define M_COM ··0xFE¤   ¤   /* COMment */
abaf5a
93af5a
7538e5 /*
b9c83a ·* Find the next JPEG marker and return its marker code.
590e65 ·* We expect at least one FF byte, possibly more if the compressor used FFs
92adb4 ·* to pad the file. ·(Padding FFs will NOT be replicated in the output file.)
fe9d9f ·* There could also be non-FF garbage between markers. ·The treatment of such
855b75 ·* garbage is unspecified; we choose to skip over it but emit a warning msg.
293797 ·* NB: this routine must not be used after seeing SOS marker, since it will
f975d2 ·* not deal correctly with FF/00 sequences in the compressed image data...
f9495d ·*/
d0af5a
8abeb7 static int
679e1a next_marker (void)
b9bb36 {
78649a ··int c;
c67afe ··int discarded_bytes = 0;
e2af5a
dad7a4 ··/* Find 0xFF byte; count and skip any non-FFs. */
e967d5 ··c = read_1_byte();
73a623 ··while (c != 0xFF) {
9ce76e ····discarded_bytes++;
41648f ····c = read_1_byte();
83df1c ··}
6b633b ··/* Get marker code byte, swallowing any duplicate FF bytes. ·Extra FFs
274e41 ···* are legal as pad bytes, so don't count them in discarded_bytes.
90f9a6 ···*/
0e565f ··do {
ae648f ····c = read_1_byte();
cf775d ··} while (c == 0xFF);
e1af5a
1d83df ··if (discarded_bytes != 0) {
380175 ····fprintf(stderr, "Warning: garbage data found in JPEG file\n");
06df1c ··}
a6af5a
194dac ··return c;
90efe6 }
20af5a
34af5a
cf38e5 /*
746c9c ·* Read the initial marker, which should be SOI.
79683a ·* For a JFIF file, the first two bytes of the file should be literally
211a05 ·* 0xFF M_SOI. ·To be more general, we could use next_marker, but if the
4dc8dd ·* input file weren't actually JPEG at all, next_marker might read the whole
40daa8 ·* file and then return a misleading error message...
cf495d ·*/
14af5a
7cbeb7 static int
--13f2 00026c11f284010004e Page 4 of wrjpgcom.c
e044cc first_marker (void)
98bb36 {
28ff86 ··int c1, c2;
49af5a
16c4e4 ··c1 = NEXTBYTE();
845ec5 ··c2 = NEXTBYTE();
fdf2f4 ··if (c1 != 0xFF || c2 != M_SOI)
2d391f ····ERREXIT("Not a JPEG file");
1cf315 ··return c2;
2aefe6 }
54af5a
a1af5a
5d38e5 /*
61b377 ·* Most types of marker are followed by a variable-length parameter segment.
229baf ·* This routine skips over the parameters for any marker we don't otherwise
b89fdc ·* want to process.
7a6408 ·* Note that we MUST skip the parameter segment explicitly in order not to
8061be ·* be fooled by 0xFF bytes that might appear within the parameter segment;
85e2e6 ·* such bytes do NOT introduce new markers.
d3495d ·*/
f3af5a
f12978 static void
6e42c3 copy_variable (void)
654214 /* Copy an unknown or uninteresting variable-length marker */
08bb36 {
cad93c ··unsigned int length;
99af5a
0421a0 ··/* Get the marker parameter length count */
1c2d8e ··length = read_2_bytes();
4b97d1 ··write_2_bytes(length);
270765 ··/* Length includes itself, so must be at least 2 */
3fedcf ··if (length < 2)
b5161a ····ERREXIT("Erroneous JPEG marker length");
d6fe13 ··length -= 2;
1ed068 ··/* Skip over the remaining bytes */
be6e5d ··while (length > 0) {
16de4a ····write_1_byte(read_1_byte());
1cebfc ····length--;
f6df1c ··}
fbefe6 }
aaaf5a
ac2978 static void
ee1bbf skip_variable (void)
53703f /* Skip over an unknown or uninteresting variable-length marker */
b6bb36 {
30d93c ··unsigned int length;
bdaf5a
0521a0 ··/* Get the marker parameter length count */
c82d8e ··length = read_2_bytes();
3a0765 ··/* Length includes itself, so must be at least 2 */
c5edcf ··if (length < 2)
4f161a ····ERREXIT("Erroneous JPEG marker length");
97fe13 ··length -= 2;
16d068 ··/* Skip over the remaining bytes */
d86e5d ··while (length > 0) {
1c5259 ····(void) read_1_byte();
19ebfc ····length--;
44df1c ··}
0defe6 }
2eaf5a
b9af5a
b638e5 /*
018eb1 ·* Parse the marker stream until SOFn or EOI is seen;
70e01c ·* copy data to output, but discard COM markers unless keep_COM is true.
97495d ·*/
18af5a
a9beb7 static int
768cf2 scan_JPEG_header (int keep_COM)
5ebb36 {
cf0fa5 ··int marker;
3aaf5a
26bac8 ··/* Expect SOI at start of file */
--842f 0003a7785f14010004e Page 5 of wrjpgcom.c
f0f485 ··if (first_marker() != M_SOI)
0cd41a ····ERREXIT("Expected SOI marker first");
994116 ··write_marker(M_SOI);
caaf5a
1acbf9 ··/* Scan miscellaneous markers until we reach SOFn. */
ce6015 ··for (;;) {
d1d908 ····marker = next_marker();
cdc4c4 ····switch (marker) {
01b49c ····case M_SOF0:¤   ¤   /* Baseline */
557f59 ····case M_SOF1:¤   ¤   /* Extended sequential, Huffman */
43d42e ····case M_SOF2:¤   ¤   /* Progressive, Huffman */
741bff ····case M_SOF3:¤   ¤   /* Lossless, Huffman */
e3167c ····case M_SOF5:¤   ¤   /* Differential sequential, Huffman */
f5a7cc ····case M_SOF6:¤   ¤   /* Differential progressive, Huffman */
246e99 ····case M_SOF7:¤   ¤   /* Differential lossless, Huffman */
c89b87 ····case M_SOF9:¤   ¤   /* Extended sequential, arithmetic */
37f1d5 ····case M_SOF10:¤  ¤   /* Progressive, arithmetic */
5a2278 ····case M_SOF11:¤  ¤   /* Lossless, arithmetic */
197b15 ····case M_SOF13:¤  ¤   /* Differential sequential, arithmetic */
c7e98b ····case M_SOF14:¤  ¤   /* Differential progressive, arithmetic */
6a255c ····case M_SOF15:¤  ¤   /* Differential lossless, arithmetic */
355828 ······return marker;
49af5a
538b35 ····case M_SOS:¤¤   ¤   /* should not see compressed data before SOF */
c8d452 ······ERREXIT("SOS without prior SOFn");
5688e1 ······break;
b8af5a
a8cf3a ····case M_EOI:¤¤   ¤   /* in case it's a tables-only JPEG stream */
b15828 ······return marker;
1eaf5a
ef18e2 ····case M_COM:¤¤   ¤   /* Existing COM: conditionally discard */
345c1f ······if (keep_COM) {
703e16 ¤   write_marker(marker);
7e1d4b ¤   copy_variable();
75cfc7 ······} else {
2617fd ¤   skip_variable();
0542cc ······}
5f88e1 ······break;
98af5a
84f166 ····default:¤   ¤   ¤   /* Anything else just gets copied */
1cc289 ······write_marker(marker);
08dc0a ······copy_variable();¤ ¤   /* we assume it has a parameter count... */
8888e1 ······break;
ff6fe7 ····}
6b9c3d ··} /* end loop */
22efe6 }
c3af5a
ccaf5a
847313 /* Command line parsing code */
44af5a
e93200 static const char * progname;¤  /* program name for error messages */
62af5a
eeaf5a
c92978 static void
dc1148 usage (void)
cbb5d5 /* complain about bad command line */
66bb36 {
e9058f ··fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n");
27084f ··fprintf(stderr, "You can add to or replace any existing comment(s).\n");
74af5a
e4679e ··fprintf(stderr, "Usage: %s [switches] ", progname);
314f53 #ifdef TWO_FILE_COMMANDLINE
0f79a1 ··fprintf(stderr, "inputfile outputfile\n");
3cdb21 #else
697dd4 ··fprintf(stderr, "[inputfile]\n");
677454 #endif
f8af5a
6c9cf5 ··fprintf(stderr, "Switches (names may be abbreviated):\n");
ee1f61 ··fprintf(stderr, " ·-replace ········Delete any existing comments\n");
a50d0f ··fprintf(stderr, " ·-comment \"text\" ·Insert comment with given text\n");
79a2cb ··fprintf(stderr, " ·-cfile name ·····Read comment from named file\n");
3a2819 ··fprintf(stderr, "Notice that you must put quotes around the comment text\n");
--6343 000eb6f2f544010004e Page 6 of wrjpgcom.c
eee1cd ··fprintf(stderr, "when you use -comment.\n");
cd4fa6 ··fprintf(stderr, "If you do not give either -comment or -cfile on the command ¶
af4c88 line,\n");
22abf8 ··fprintf(stderr, "then the comment text is read from standard input.\n");
14e0dc ··fprintf(stderr, "It can be multiple lines, up to %u characters total.\n",
10086b ¤   ··(unsigned int) MAX_COM_LENGTH);
383c9a #ifndef TWO_FILE_COMMANDLINE
341b74 ··fprintf(stderr, "You must specify an input JPEG file name when supplying\n");
a37465 ··fprintf(stderr, "comment text from standard input.\n");
7e7454 #endif
ceaf5a
a8870b ··exit(EXIT_FAILURE);
8eefe6 }
91af5a
79af5a
dcbeb7 static int
ec9b9d keymatch (char * arg, const char * keyword, int minchars)
a52a88 /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
d3f88e /* keyword is the constant keyword (must be lower case already), */
fdd9b3 /* minchars is length of minimum legal abbreviation. */
96bb36 {
16f449 ··register int ca, ck;
d2d00d ··register int nmatched = 0;
27af5a
9b0558 ··while ((ca = *arg++) != '\0') {
98a7a9 ····if ((ck = *keyword++) == '\0')
87e037 ······return 0;¤¤   ¤   /* arg longer than keyword, no good */
2a1201 ····if (isupper(ca))¤   ¤   /* force arg to lcase (assume ck is already) */
a7112f ······ca = tolower(ca);
3a1813 ····if (ca != ck)
2af040 ······return 0;¤¤   ¤   /* no good */
b577ba ····nmatched++;¤¤   ¤   /* count matched characters */
b6df1c ··}
98ed38 ··/* reached end of argument; fail if it's too short for unique abbrev */
6faca6 ··if (nmatched < minchars)
89958b ····return 0;
6b5b35 ··return 1;¤¤   ¤   /* A-OK */
6befe6 }
daaf5a
9aaf5a
7538e5 /*
0eeb85 ·* The main program.
9b495d ·*/
bcaf5a
0d4d2f int
2b73e2 main (int argc, char **argv)
10bb36 {
289a4b ··int argn;
e57cfe ··char * arg;
fe55a1 ··int keep_COM = 1;
adf306 ··char * comment_arg = NULL;
8c7e8d ··FILE * comment_file = NULL;
e78a59 ··unsigned int comment_length = 0;
880fa5 ··int marker;
39af5a
7e209a ··/* On Mac, fetch a command line. */
498a88 #ifdef USE_CCOMMAND
caad02 ··argc = ccommand(&argv);
e97454 #endif
22af5a
78eb33 ··progname = argv[0];
8220c8 ··if (progname == NULL || progname[0] == 0)
59d336 ····progname = "wrjpgcom";¤ /* in case C library doesn't provide it */
f0af5a
bce938 ··/* Parse switches, if any */
392949 ··for (argn = 1; argn < argc; argn++) {
58c53a ····arg = argv[argn];
0bb82c ····if (arg[0] != '-')
8db8f0 ······break;¤   ¤   ¤   /* not switch, must be file name */
f9a72e ····arg++;¤ ¤   ¤   /* advance over '-' */
790b6b ····if (keymatch(arg, "replace", 1)) {
ebf3b7 ······keep_COM = 0;
--0776 000067583f84010004e Page 7 of wrjpgcom.c
b51f42 ····} else if (keymatch(arg, "cfile", 2)) {
8a3e49 ······if (++argn >= argc) usage();
11ae4e ······if ((comment_file = fopen(argv[argn], "r")) == NULL) {
20878a ¤   fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
cdbfcc ¤   exit(EXIT_FAILURE);
9c42cc ······}
c4133b ····} else if (keymatch(arg, "comment", 1)) {
643e49 ······if (++argn >= argc) usage();
e0f6e3 ······comment_arg = argv[argn];
90f11b ······/* If the comment text starts with '"', then we are probably running
fadd90 ·······* under MS-DOG and must parse out the quoted string ourselves. ·Sigh.
5ae9f1 ·······*/
9bf36a ······if (comment_arg[0] == '"') {
b272e7 ¤   comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
ff6c86 ¤   if (comment_arg == NULL)
6334dc ¤   ··ERREXIT("Insufficient memory");
cd0a2f ¤   strcpy(comment_arg, argv[argn]+1);
59220e ¤   for (;;) {
59da9d ¤   ··comment_length = strlen(comment_arg);
a05d9b ¤   ··if (comment_length > 0 && comment_arg[comment_length-1] == '"') {
7092bc ¤   ····comment_arg[comment_length-1] = '\0'; /* zap terminating quote */
11cafa ¤   ····break;
5f32a2 ¤   ··}
7eb4a1 ¤   ··if (++argn >= argc)
2e4435 ¤   ····ERREXIT("Missing ending quote mark");
33972c ¤   ··strcat(comment_arg, " ");
0b680c ¤   ··strcat(comment_arg, argv[argn]);
e69371 ¤   }
e042cc ······}
7d2a1c ······comment_length = strlen(comment_arg);
bfce75 ····} else
5f8e9f ······usage();
dfdf1c ··}
e7af5a
cdb2f2 ··/* Cannot use both -comment and -cfile. */
540fde ··if (comment_arg != NULL && comment_file != NULL)
1c2b21 ····usage();
3abd62 ··/* If there is neither -comment nor -cfile, we will read the comment text
7fa5d5 ···* from stdin; in this case there MUST be an input JPEG file name.
b6f9a6 ···*/
e86be8 ··if (comment_arg == NULL && comment_file == NULL && argn >= argc)
a32b21 ····usage();
f1af5a
07f8b9 ··/* Open the input file. */
96f20e ··if (argn < argc) {
c7d483 ····if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
ea9afb ······fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
54a026 ······exit(EXIT_FAILURE);
c86fe7 ····}
f349d8 ··} else {
76a011 ····/* default input file is stdin */
ebc1f3 #ifdef USE_SETMODE¤ ¤   /* need to hack file mode? */
279142 ····setmode(fileno(stdin), O_BINARY);
e97454 #endif
7671bb #ifdef USE_FDOPEN¤  ¤   /* need to re-open in binary mode? */
74df7b ····if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
6ac977 ······fprintf(stderr, "%s: can't open stdin\n", progname);
0ca026 ······exit(EXIT_FAILURE);
bc6fe7 ····}
b6db21 #else
a8b274 ····infile = stdin;
b67454 #endif
f1df1c ··}
54af5a
5b18be ··/* Open the output file. */
164f53 #ifdef TWO_FILE_COMMANDLINE
4291f5 ··/* Must have explicit output file name */
c998b3 ··if (argn != argc-2) {
c8e1d9 ····fprintf(stderr, "%s: must name one input and one output file\n",
e56ce6 ¤   ····progname);
692b21 ····usage();
06df1c ··}
--bac6 001951fa4094010004e Page 8 of wrjpgcom.c
baf214 ··if ((outfile = fopen(argv[argn+1], WRITE_BINARY)) == NULL) {
173e85 ····fprintf(stderr, "%s: can't open %s\n", progname, argv[argn+1]);
367ad7 ····exit(EXIT_FAILURE);
bddf1c ··}
c7db21 #else
9dd20f ··/* Unix style: expect zero or one file name */
1bc632 ··if (argn < argc-1) {
127812 ····fprintf(stderr, "%s: only one input file\n", progname);
202b21 ····usage();
f6df1c ··}
602af8 ··/* default output file is stdout */
ebc1f3 #ifdef USE_SETMODE¤ ¤   /* need to hack file mode? */
52928e ··setmode(fileno(stdout), O_BINARY);
887454 #endif
0c71bb #ifdef USE_FDOPEN¤  ¤   /* need to re-open in binary mode? */
6b3b9b ··if ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
f39f8e ····fprintf(stderr, "%s: can't open stdout\n", progname);
427ad7 ····exit(EXIT_FAILURE);
22df1c ··}
7ddb21 #else
85730e ··outfile = stdout;
077454 #endif
72a164 #endif /* TWO_FILE_COMMANDLINE */
99af5a
7c9c8a ··/* Collect comment text from comment_file or stdin, if necessary */
e7da8a ··if (comment_arg == NULL) {
9921cb ····FILE * src_file;
d1dd4c ····int c;
a2af5a
b89318 ····comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
7acaa4 ····if (comment_arg == NULL)
7738bc ······ERREXIT("Insufficient memory");
8185ef ····comment_length = 0;
89258c ····src_file = (comment_file != NULL ? comment_file : stdin);
9cb314 ····while ((c = getc(src_file)) != EOF) {
4d938f ······if (comment_length >= (unsigned int) MAX_COM_LENGTH) {
1e7d03 ¤   fprintf(stderr, "Comment text may not exceed %u bytes\n",
d97610 ¤   ¤   (unsigned int) MAX_COM_LENGTH);
d6bfcc ¤   exit(EXIT_FAILURE);
7142cc ······}
85a144 ······comment_arg[comment_length++] = (char) c;
936fe7 ····}
4aead5 ····if (comment_file != NULL)
891799 ······fclose(comment_file);
95df1c ··}
24af5a
308c98 ··/* Copy JPEG headers until SOFn marker;
182984 ···* we will insert the new comment marker just before SOFn.
fd167f ···* This (a) causes the new comment to appear after, rather than before,
5ba553 ···* existing comments; and (b) ensures that comments come after any JFIF
4ff223 ···* or JFXX markers, as required by the JFIF specification.
14f9a6 ···*/
0adcc4 ··marker = scan_JPEG_header(keep_COM);
d546b3 ··/* Insert the new COM marker, but only if nonempty text has been supplied */
b74680 ··if (comment_length > 0) {
de6d56 ····write_marker(M_COM);
82b306 ····write_2_bytes(comment_length + 2);
45bad7 ····while (comment_length > 0) {
3a08fa ······write_1_byte(*comment_arg++);
e0c975 ······comment_length--;
7c6fe7 ····}
8fdf1c ··}
cd46f2 ··/* Duplicate the remainder of the source file.
25a287 ···* Note that any COM markers occuring after SOF will not be touched.
bcf9a6 ···*/
9b047f ··write_marker(marker);
da5075 ··copy_rest_of_file();
34af5a
ccb3af ··/* All done. */
2cf77b ··exit(EXIT_SUCCESS);
e4241d ··return 0;¤¤   ¤   /* suppress no-return-value warnings */
95efe6 }
--f0f7 000214ffb134010004f Page 1 of pgpAdminPrefs.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
663127 ¤   $Id: pgpAdminPrefs.h,v 1.17.8.1 1998/11/12 03:11:03 heller Exp $
c2f7f7 ____________________________________________________________________________*/
ad8e99 #ifndef Included_pgpAdminPrefs_h¤   /* [ */
f8819d #define Included_pgpAdminPrefs_h
d9af5a
37af5a
542e8f #define PGP_ADMINPREFVERSION¤   1
5daf5a
591722 typedef enum _PGPAdminPrefsBool
3abb36 {
134f7d ¤   kPGPAdminPrefBoolFirst¤ ¤   ¤   ¤   ¤   ¤   =¤  0,
9b3178 ¤   kPGPPrefUseOutgoingADK = kPGPAdminPrefBoolFirst,
c45e23 ¤   kPGPPrefUseDHADK¤   ¤   ¤   ¤   ¤   ¤   ¤   =¤  1,
46559c ¤   kPGPPrefEnforceIncomingADK¤ ¤   ¤   ¤   ¤   =¤  2,
ef6c90 ¤   kPGPPrefEnforceMinChars¤¤   ¤   ¤   ¤   ¤   =¤  3,
5fe494 ¤   kPGPPrefEnforceMinQuality¤  ¤   ¤   ¤   ¤   =¤  4,
575a90 ¤   kPGPPrefWarnNotCertByCorp¤  ¤   ¤   ¤   ¤   =¤  5,
51ff79 ¤   kPGPPrefAutoSignTrustCorp¤  ¤   ¤   ¤   ¤   =¤  6,
c5d11e ¤   kPGPPrefMetaIntroducerCorp¤ ¤   ¤   ¤   ¤   =¤  7,
1ffe2f ¤   kPGPPrefAllowKeyGen¤¤   ¤   ¤   ¤   ¤   ¤   =¤  8,
65a932 ¤   kPGPPrefAllowRSAKeyGen¤ ¤   ¤   ¤   ¤   ¤   =¤  9,
449a79 ¤   kPGPPrefAllowConventionalEncryption¤¤   ¤   =¤  10,
777fe8 ¤   kPGPPrefEnforceOutgoingADK¤ ¤   ¤   ¤   ¤   =¤  11,¤¤   /* 5.5.1 */
e21030 ¤   kPGPPrefEnforceRemoteADKClass¤  ¤   ¤   ¤   =¤  12,¤¤   /* 5.5.1 */
6fcc32 ¤   kPGPPrefUpdateAllKeys¤  ¤   ¤   ¤   ¤   ¤   =¤  13,
f4a6a9 ¤   kPGPPrefUpdateTrustedIntroducers¤   ¤   ¤   =¤  14,
a43bae ¤   kPGPPrefAutoAddRevoker¤ ¤   ¤   ¤   ¤   ¤   =¤  15,¤¤   /* 6.0 */
a94409 ¤   kPGPPrefUsePGPdiskADK¤  ¤   ¤   ¤   ¤   ¤   = ¤ 16,
b9523a ¤   kPGPAdminPrefBoolLast
5f7803 } PGPAdminPrefsBool;
f6af5a
4e35f7 typedef enum _PGPAdminPrefsNumber
b3bb36 {
6b733c ¤   kPGPAdminPrefNumberFirst¤   ¤   ¤   ¤   ¤   =¤  200,
441ec2 ¤   kPGPAdminPrefVersion = kPGPAdminPrefNumberFirst,
b0ad21 ¤   kPGPPrefMinChars¤   ¤   ¤   ¤   ¤   ¤   ¤   =¤  201,
883aec ¤   kPGPPrefMinQuality¤ ¤   ¤   ¤   ¤   ¤   ¤   =¤  202,
aa6e1d ¤   kPGPPrefCorpKeyPublicKeyAlgorithm¤  ¤   ¤   =¤  203,
b027fa ¤   kPGPPrefOutADKPublicKeyAlgorithm¤   ¤   ¤   =¤  204,
82a4c9 ¤   kPGPPrefMinimumKeySize¤ ¤   ¤   ¤   ¤   ¤   =¤  205,
98a50f ¤   kPGPPrefDaysUpdateAllKeys¤  ¤   ¤   ¤   ¤   =¤  206,
0c624b ¤   kPGPPrefDaysUpdateTrustedIntroducers¤   ¤   =¤  207,
5bfdd4 ¤   kPGPPrefLastAllKeysUpdate¤  ¤   ¤   ¤   ¤   =¤  208,
a67952 ¤   kPGPPrefLastTrustedIntroducersUpdate¤   ¤   =¤  209,
39d863 ¤   kPGPPrefRevokerPublicKeyAlgorithm¤  ¤   ¤   =¤  210,¤   /* 6.0 */
003ac0 ¤   kPGPPrefPGPdiskADKPublicKeyAlgorithm¤   ¤   =¤  211,
1ccbec ¤   kPGPAdminPrefNumberLast
751bab } PGPAdminPrefsNumber;
75af5a
42767c typedef enum _PGPAdminPrefsString
79bb36 {
bc0861 ¤   kPGPAdminPrefStringFirst¤   ¤   ¤   ¤   ¤   =¤  400,
1c2a51 ¤   kPGPPrefComments = kPGPAdminPrefStringFirst,
f597a1 ¤   kPGPPrefSiteLicenseNumber¤  ¤   ¤   ¤   ¤   =¤  401,¤   /* 5.5.1 */
f0c777 ¤   kPGPPrefAdminCompanyName¤   ¤   ¤   ¤   ¤   =¤  402,
decf85 ¤   kPGPAdminPrefStringLast
372133 } PGPAdminPrefsString;
0baf5a
d6e432 typedef enum _PGPAdminPrefsByte
50bb36 {
d0480a ¤   kPGPAdminPrefByteFirst¤ ¤   ¤   ¤   ¤   ¤   =¤  600,
8bef34 ¤   kPGPPrefOutgoingADKID = kPGPAdminPrefByteFirst,
ff787f ¤   kPGPPrefDHADKID¤¤   ¤   ¤   ¤   ¤   ¤   ¤   =¤  601,
368e2d ¤   kPGPPrefCorpKeyID¤  ¤   ¤   ¤   ¤   ¤   ¤   =¤  602,
779cef ¤   kPGPPrefDefaultKeys¤¤   ¤   ¤   ¤   ¤   ¤   =¤  603,
68d9cd ¤   kPGPPrefRevokerKeyID¤   ¤   ¤   ¤   ¤   ¤   =¤  604,¤   /* 6.0 */
9f316b ¤   kPGPPrefPGPdiskADKKeyID¤¤   ¤   ¤   ¤   ¤   =¤  605,
21f2cb ¤   kPGPAdminPrefByteLast
--256b 0014d496a6a4010004f Page 2 of pgpAdminPrefs.h
796871 } PGPAdminPrefsByte;
faaf5a
0ec5d5 #include "pgpBase.h"
132b62 #include "pgpPFLErrors.h"
28e8b2 #include "pflPrefs.h"
f9a076 #include "pgpKeys.h"
38af5a
fb6c6a static const PGPPrefDefault adminDefaults[] =·
b7bb36 {
04302e {kPGPPrefUseOutgoingADK,¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
3e00bc {kPGPPrefUseDHADK,¤ ¤   ¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
ca935e {kPGPPrefEnforceIncomingADK,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
5a309a {kPGPPrefEnforceMinChars,¤  ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
e17203 {kPGPPrefEnforceMinQuality,¤¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
b7a695 {kPGPPrefWarnNotCertByCorp,¤¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
935e63 {kPGPPrefAutoSignTrustCorp,¤¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
66591f {kPGPPrefMetaIntroducerCorp,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
918fbe {kPGPPrefAllowKeyGen,¤  ¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
e72922 {kPGPPrefAllowRSAKeyGen,¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
6c6a00 {kPGPPrefAllowConventionalEncryption,¤  kPGPPrefType_Boolean, (void *) TRUE},
df5358 {kPGPPrefEnforceOutgoingADK,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
e3012e {kPGPPrefEnforceRemoteADKClass,¤¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
0cf231 {kPGPPrefUpdateAllKeys,¤¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
a3a7d0 {kPGPPrefUpdateTrustedIntroducers,¤ ¤   kPGPPrefType_Boolean, (void *) FALSE},
25869b {kPGPPrefAutoAddRevoker,¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
d8afe0 {kPGPPrefUsePGPdiskADK,¤¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
9eaf5a
66c9f1 {kPGPPrefMinChars,¤ ¤   ¤   ¤   ¤   ¤   kPGPPrefType_Number, (void *) 5},
618fcf {kPGPPrefMinQuality,¤   ¤   ¤   ¤   ¤   kPGPPrefType_Number, (void *) 60},
8a7b28 {kPGPPrefCorpKeyPublicKeyAlgorithm,¤¤   kPGPPrefType_Number,·
3bfbf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) kPGPPublicKeyAlgorithm_DSA},
8608a8 {kPGPPrefOutADKPublicKeyAlgorithm,¤ ¤   kPGPPrefType_Number,·
d9fbf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) kPGPPublicKeyAlgorithm_DSA},
d89333 {kPGPPrefMinimumKeySize,¤   ¤   ¤   ¤   kPGPPrefType_Number, (void *) 768},
eb0085 {kPGPPrefDaysUpdateAllKeys,¤¤   ¤   ¤   kPGPPrefType_Number, (void *) 0},
871a3f {kPGPPrefDaysUpdateTrustedIntroducers,¤ kPGPPrefType_Number, (void *) 0},
4de9c6 {kPGPPrefLastAllKeysUpdate,¤¤   ¤   ¤   kPGPPrefType_Number, (void *) 0},
d4ab44 {kPGPPrefLastTrustedIntroducersUpdate,¤ kPGPPrefType_Number, (void *) 0},
bb0838 {kPGPPrefRevokerPublicKeyAlgorithm,¤¤   kPGPPrefType_Number,
fdfbf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) kPGPPublicKeyAlgorithm_DSA},
1c3d72 {kPGPPrefPGPdiskADKPublicKeyAlgorithm,¤ kPGPPrefType_Number,
87fbf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) kPGPPublicKeyAlgorithm_DSA},
a8af5a
8d4c68 {kPGPPrefComments,¤ ¤   ¤   kPGPPrefType_String, (void *) ""},
a1ce51 {kPGPPrefSiteLicenseNumber, kPGPPrefType_String, (void *) ""},
0b71e9 {kPGPPrefAdminCompanyName,¤ kPGPPrefType_String, (void *) ""}
3f82f7 };
bfaf5a
6a1692 static const PGPSize adminDefaultsSize =·
6790b0 ¤   ¤   ¤   ¤   ¤   ¤   sizeof(adminDefaults) / sizeof(PGPPrefDefault);
49af5a
31af5a
9abeb5 #endif /* ] Included_pgpAdminPrefs_h */
68af5a
9eaf5a
1b7e4d /*__Editor_settings____
2faf5a
df4126 ¤   Local Variables:
e57b17 ¤   tab-width: 4
b00e6c ¤   End:
e25f8c ¤   vi: ts=4 sw=4
e39e9b ¤   vim: si
4dd062 _____________________*/
--a5f0 00000d9003640100050 Page 1 of pgpBuildFlags.h
4b6438 /*_____________________________________________________________________________
cec97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
2d4b0f ¤   All rights reserved.
deaf5a
48403f ¤   $Id: pgpBuildFlags.h,v 1.83.2.49.2.2 1998/11/13 04:05:37 heller Exp $
267cb9 _____________________________________________________________________________*/
347b7d #pragma once
95af5a
77af5a
356438 /*_____________________________________________________________________________
3cf5c4 ¤   This is the common header file for the PGP client. ··It contains flags
7ae0ca ¤   that apply globally to all modules. ·Before building, make sure the flags
fde549 ¤   here are set appropriately.
aa67c5 ¤
a617ea ¤   Note: include this file in your project prefix
977cb9 _____________________________________________________________________________*/
3caf5a
43af5a
f04228 #ifndef BETA
e6ffec #define BETA¤   ¤   ¤   ¤   ¤   ¤   0¤  ¤   // zero for release
017454 #endif
f9af5a
33e9a7 #ifndef PGP_DEMO
9874f3 #define PGP_DEMO¤   ¤   ¤   ¤   ¤   0¤  ¤   // zero for regular version
4e7454 #endif
9caf5a
596908 #ifndef PGP_FREEWARE
339f6e #define PGP_FREEWARE¤   ¤   ¤   ¤   0¤  ¤   // zero for non-freeware
fc7454 #endif
85af5a
f8e1a2 #ifndef PGP_BUSINESS_SECURITY
444c04 #define PGP_BUSINESS_SECURITY¤  ¤   1¤  ¤   // zero for personal version
d57454 #endif
53af5a
3b3d44 #ifndef PGP_PERSONAL_PRIVACY
ec6622 #define PGP_PERSONAL_PRIVACY¤   ¤   0¤  ¤   // zero for business version
577454 #endif
3daf5a
ad77b3 #ifndef PGP_ADMIN_BUILD
6007c7 #define PGP_ADMIN_BUILD¤¤   ¤   ¤   1¤  ¤   ·// zero for business version
4d7454 #endif
d4af5a
adb256 #ifndef NO_RSA_KEYGEN
2a48da #define NO_RSA_KEYGEN¤  ¤   ¤   ¤   0
c57454 #endif
c5af5a
b8fea8 #ifndef NO_RSA_OPERATIONS
9c9f3b #define NO_RSA_OPERATIONS¤  ¤   ¤   0
a77454 #endif
c4af5a
2c1daa #ifndef CREDIT_RSA_BSAFE
ff6bc7 #define CREDIT_RSA_BSAFE¤   ¤   ¤   0
d57454 #endif
10af5a
c8be29 #if PGP_BUSINESS_SECURITY
9a019b ¤   #if PGP_PERSONAL_PRIVACY || PGP_FREEWARE
168ef9 ¤   ¤   #error This is not a legal build combination
1bb7ec ¤   #endif
31d86b #elif PGP_PERSONAL_PRIVACY
f44e7d ¤   #if PGP_BUSINESS_SECURITY || PGP_FREEWARE
4d8ef9 ¤   ¤   #error This is not a legal build combination
59b7ec ¤   #endif
659db4 #elif PGP_FREEWARE
7b86c7 ¤   #if PGP_BUSINESS_SECURITY || PGP_PERSONAL_PRIVACY
998ef9 ¤   ¤   #error This is not a legal build combination
cbb7ec ¤   #endif
e9db21 #else
af1138 ¤   #error Must define a primary build type!
ac7454 #endif
94af5a
58164e #if PGP_ADMIN_BUILD
00019b ¤   #if PGP_PERSONAL_PRIVACY || PGP_FREEWARE
--7a79 001ee8fcd3540100050 Page 2 of pgpBuildFlags.h
988ef9 ¤   ¤   #error This is not a legal build combination
45b7ec ¤   #endif
817454 #endif
eeaf5a
--a4a0 000a832061340100051 Page 1 of pgpClientErrors.c
a70335 /*____________________________________________________________________________
a093b0 ¤   pgpClientErrors.c
4967c5 ¤
cfc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
884b0f ¤   All rights reserved.
8667c5 ¤
1d67c5 ¤
beaf5a
b0c11f ¤   $Id: pgpClientErrors.c,v 1.7.2.1.2.1 1998/11/12 03:11:04 heller Exp $
97f7f7 ____________________________________________________________________________*/
a1feb2 #include <stdio.h>
41324c #include <string.h>
ccaf5a
50628e #include "pgpClientErrors.h"
540d08 #include "pgpMem.h"
0daf5a
a6af5a
269827 typedef struct ClientErrorEntry
9ebb36 {
7acd5c ¤   PGPError const¤ ¤   number;
e02e82 ¤   const char * const¤ string;
153b45 } ClientErrorEntry;
34af5a
1ec5d1 #define EN(number, string)¤ ¤   { number, string }
b8af5a
42af5a
95568d static const ClientErrorEntry sErrors[] =
24bb36 {
0264f8 /* Share errors */
fe8c04 EN(kPGPClientError_NotEnoughSharesInObject,
a9c26a ···"not enough shares to split"),
2e19df EN(kPGPClientError_DifferentSplitKeys,
793d14 ···"shares were not split from the same key"),
111d2a EN(kPGPClientError_DifferentSharePool,
5b3749 ···"shares were not split from the same share pool"),
2d2d80 EN(kPGPClientError_IdenticalShares,
36e9cf ···"identical shares cannot be combined"),
60af5a
621bef /* SKEP errors */
eabf24 EN(kPGPClientError_IncorrectSKEPVersion,
6084e0 ···"client SKEP version different from server SKEP version"),
0c0393 EN(kPGPClientError_RejectedSKEPAuthentication,
f46483 ···"your key was not accepted for authentication by the remote system"),
4eaf5a
f0ad75 /* Pref errors */
e22b1e EN(kPGPClientError_AdminPrefsNotFound,
422a61 ···"administrative preferences file not found"),
6faf5a
fd4ca7 EN(kPGPClientError_UnsplitPrivateKeyNotFound,
986c90 ···"unsplit private key could not be found to authenticate the connection")
4782f7 };
59af5a
aba422 #define kPGPClientErrors_NumErrorTableEntries¤  ¤   \
72dc6e ¤   ( sizeof( sErrors ) / sizeof( sErrors[ 0 ] ) )
03af5a
05a65c #undef EN
78af5a
80af5a
f967c5 ¤
0f21ab ¤   PGPError·
ceece2 PGPGetClientErrorString(
10c7e5 ¤   PGPError¤   theError,
3dc102 ¤   PGPSize¤¤   bufferSize,
a86e0a ¤   char *¤ ¤   theString )
f8bb36 {
eecdc4 ¤   PGPUInt32¤  ¤   idx;
6c3423 ¤   char¤   ¤   ¤   temp[ 256 ];
c3dc2c ¤   char const *¤   errStr¤ = NULL;
ae4e6e ¤   PGPSize¤¤   ¤   len¤= 0;
915a23 ¤   PGPBoolean¤ ¤   bufferBigEnough¤= FALSE;
cd67c5 ¤
a8c409 ¤   if (theError >= kPGPPFLErrorBase && theError <= kPGPError_Last )
--e4f6 001fdf4322c40100051 Page 2 of pgpClientErrors.c
6f44bb ¤   ¤   return PGPGetErrorString(theError, bufferSize, theString);
87af5a
54bb87 ¤   PGPValidateParam( bufferSize >= 1 );
0af382 ¤   PGPValidatePtr( theString );
e74a4b ¤   *theString¤ = '\0';
ea67c5 ¤
6a6b84 ¤   for( idx = 0; idx < kPGPClientErrors_NumErrorTableEntries; ++idx )
30c7a1 ¤   {
9bb28b ¤   ¤   const ClientErrorEntry *¤   entry;
3e1b52 ¤   ¤
ac287f ¤   ¤   entry¤  = &sErrors[ idx ];
720504 ¤   ¤   if ( entry->number == theError )
be5b34 ¤   ¤   {
fd86e4 ¤   ¤   ¤   errStr¤ = entry->string;
6fcdcb ¤   ¤   ¤   break;
770fe4 ¤   ¤   }
e09371 ¤   }
0c67c5 ¤
738dc0 ¤   if ( IsNull( errStr ) )
6cc7a1 ¤   {
43e8a8 ¤   ¤   /* Produce something for missing errors */
b67da4 ¤   ¤   sprintf( temp, "PGPClientError #%ld", (long)theError );
215187 ¤   ¤   errStr¤ = temp;
219371 ¤   }
6367c5 ¤
517128 ¤   len¤= strlen( errStr );
ad0bb4 ¤   bufferBigEnough¤= ( len + 1 <= bufferSize );
3cb274 ¤   if ( bufferBigEnough )
17c7a1 ¤   {
390262 ¤   ¤   strcpy( theString, errStr );
d39371 ¤   }
f20e24 ¤   else
1bc7a1 ¤   {
808369 ¤   ¤   pgpCopyMemory( errStr, theString, bufferSize - 1 );
8fbdfb ¤   ¤   theString[ bufferSize - 1 ]¤= '\0';
769371 ¤   }
e767c5 ¤
3811d3 ¤   return( bufferBigEnough¤? kPGPError_NoErr : kPGPError_BufferTooSmall );
fcefe6 }
80af5a
a8af5a
53af5a
dd7e4d /*__Editor_settings____
12af5a
ce4126 ¤   Local Variables:
487b17 ¤   tab-width: 4
ae0e6c ¤   End:
e35f8c ¤   vi: ts=4 sw=4
db9e9b ¤   vim: si
fdd062 _____________________*/
--351e 001421f781840100052 Page 1 of pgpClientErrors.h
a70335 /*____________________________________________________________________________
437718 ¤   pgpClientErrors.h
4baf5a
f7c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
034b0f ¤   All rights reserved.
baaf5a
41a564 ¤   Error codes for all PGP errors can be found in this file.
05af5a
e8c168 ¤   $Id: pgpClientErrors.h,v 1.7.8.1 1998/11/12 03:11:05 heller Exp $
d1f7f7 ____________________________________________________________________________*/
b57c4f #ifndef Included_pgpClientErrors_h¤ /* [ */
c36896 #define Included_pgpClientErrors_h
a4af5a
ed2f8d #include "pgpErrors.h"
8faf5a
ba8c2d enum PGPClientError_
b3bb36 {
04c671 ¤   kPGPClientError_FirstError¤ ¤   ¤   ¤   ¤   =¤  -12500,
1a80f0 ¤   kPGPClientError_Last¤   ¤   ¤   ¤   ¤   ¤   =¤  -12001,
f1af5a
035f11 ¤   /* Share errors */
b9f1b3 ¤   kPGPClientError_NotEnoughSharesInObject¤¤   =¤  -12500,
f7e558 ¤   kPGPClientError_DifferentSplitKeys¤ ¤   ¤   =¤  -12499,
e65d13 ¤   kPGPClientError_DifferentSharePool¤ ¤   ¤   =¤  -12498,
240d2b ¤   kPGPClientError_IdenticalShares¤¤   ¤   ¤   =¤  -12497,
62af5a
2f2175 ¤   /* SKEP errors */
072f04 ¤   kPGPClientError_IncorrectSKEPVersion¤   ¤   =¤  -12479,
0d78f6 ¤   kPGPClientError_RejectedSKEPAuthentication¤ =¤  -12478,
a4af5a
0f97ef ¤   /* Pref errors */
5f30c6 ¤   kPGPClientError_AdminPrefsNotFound¤ ¤   ¤   =¤  -12450,
7067c5 ¤
909101 ¤   /* Reconstitution Errors */
798ea0 ¤   kPGPClientError_UnsplitPrivateKeyNotFound¤  =¤  -12425,
d1af5a
5a88f6 ¤   kPGPClientError_Dummy
202fa1 } ;
33af5a
a1af5a
a199c6 PGP_BEGIN_C_DECLARATIONS
8fcbcf #if PRAGMA_IMPORT_SUPPORTED
1fb981 #pragma import on
c57454 #endif
b2af5a
1269fc PGPError ¤  PGPGetClientErrorString( PGPError theError,
72290d ¤   ¤   ¤   ¤   PGPSize bufferSize, char * theString );
83af5a
0ccbcf #if PRAGMA_IMPORT_SUPPORTED
582ced #pragma import reset
687454 #endif
711254 PGP_END_C_DECLARATIONS
09af5a
7faf5a
827d38 #endif /* ] Included_pgpClientErrors_h */
e2af5a
8aaf5a
ad7e4d /*__Editor_settings____
afaf5a
7e4126 ¤   Local Variables:
ff7b17 ¤   tab-width: 4
aa0e6c ¤   End:
955f8c ¤   vi: ts=4 sw=4
699e9b ¤   vim: si
42d062 _____________________*/
--77af 0001bf5fb5a40100053 Page 1 of pgpClientPrefs.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
4f2f1e ¤   $Id: pgpClientPrefs.h,v 1.37.8.1 1998/11/12 03:11:05 heller Exp $
4df7f7 ____________________________________________________________________________*/
1260f6 #ifndef Included_pgpClientPrefs_h¤  /* [ */
0a0a50 #define Included_pgpClientPrefs_h
bfaf5a
037353 enum
20bb36 {
2cff69 ¤   kPGPPrefMacBinaryOff¤   = 1,
5334a0 ¤   kPGPPrefMacBinarySmart¤ = 2,
db0191 ¤   kPGPPrefMacBinaryOn¤¤   = 3
7782f7 };
d2af5a
c5b06c typedef enum _PGPClientPrefsBool
d6bb36 {
52865a ¤   kPGPPrefBoolFirst¤  ¤   ¤   ¤   ¤   ¤   ¤   =¤  0,
d1c357 ¤   kPGPPrefEncryptToSelf = kPGPPrefBoolFirst,
df76b9 ¤   kPGPPrefWordWrapEnable¤ ¤   ¤   ¤   ¤   ¤   =¤  1,
7c6eec ¤   kPGPPrefDecryptCacheEnable¤ ¤   ¤   ¤   ¤   =¤  2,
b5e943 ¤   kPGPPrefSignCacheEnable¤¤   ¤   ¤   ¤   ¤   =¤  3,
7a8af7 ¤   kPGPPrefMailEncryptPGPMIME¤ ¤   ¤   ¤   ¤   =¤  4,
d4a880 ¤   kPGPPrefMailSignPGPMIME¤¤   ¤   ¤   ¤   ¤   =¤  5,
dfe611 ¤   kPGPPrefFastKeyGen¤ ¤   ¤   ¤   ¤   ¤   ¤   =¤  6,
d454e6 ¤   kPGPPrefWarnOnMixRSAElGamal¤¤   ¤   ¤   ¤   =¤  7,
d1db6f ¤   kPGPPrefMailEncryptDefault¤ ¤   ¤   ¤   ¤   =¤  8,
42b943 ¤   kPGPPrefMailSignDefault¤¤   ¤   ¤   ¤   ¤   =¤  9,
40d0bd ¤   kPGPPrefMarginalIsInvalid¤  ¤   ¤   ¤   ¤   =¤  10,
15a6f6 ¤   kPGPPrefDisplayMarginalValidity¤¤   ¤   ¤   =¤  11,
ec31f6 ¤   kPGPPrefFirstKeyGenerated¤  ¤   ¤   ¤   ¤   =¤  12,
50d961 ¤   kPGPPrefWarnOnRSARecipAndNonRSASigner¤  ¤   =¤  13,
2bb765 ¤   kPGPPrefKeyServerSyncUnknownKeys¤   ¤   ¤   =¤  14,
c035f8 ¤   kPGPPrefKeyServerSyncOnAdd¤ ¤   ¤   ¤   ¤   =¤  15,
3a9f2e ¤   kPGPPrefKeyServerSyncOnKeySign¤ ¤   ¤   ¤   =¤  16,
417da7 ¤   kPGPPrefKeyServerSyncOnRevocation¤  ¤   ¤   =¤  17,
20ddfc ¤   kPGPPrefWarnOnReadOnlyKeyRings¤ ¤   ¤   ¤   =¤  18,
9fb0ef ¤   kPGPPrefWarnOnWipe¤ ¤   ¤   ¤   ¤   ¤   ¤   =¤  19,
e39260 ¤   kPGPPrefAutoDecrypt¤¤   ¤   ¤   ¤   ¤   ¤   =¤  20,
af1c80 ¤   kPGPPrefWarnOnADK¤  ¤   ¤   ¤   ¤   ¤   ¤   =¤  21,
aa22d6 ¤   kPGPPrefKeyServerSyncOnVerify¤  ¤   ¤   ¤   =¤  22,¤¤   /* 6.0 */
7bc882 ¤   kPGPPrefPGPkeysMacShowToolbar¤  ¤   ¤   ¤   =¤  23,¤¤   /* 6.0 */
b4707c ¤   kPGPPrefWarnOnMemLockFailure¤   ¤   ¤   ¤   =¤  24,¤¤   /* 6.0 */
ef8cac ¤   kPGPPrefExportKeysCompatible¤   ¤   ¤   ¤   =¤  25,¤¤   /* 6.0 */
ea1997 ¤   kPGPPrefBoolLast
40cea6 } PGPClientPrefsBool;
adaf5a
843834 typedef enum _PGPClientPrefsNumber
7fbb36 {
92bd6e ¤   kPGPPrefNumberFirst¤¤   ¤   ¤   ¤   ¤   ¤   =¤  200,
da4559 ¤   kPGPPrefVersion = kPGPPrefNumberFirst,
7ab158 ¤   kPGPPrefWordWrapWidth¤  ¤   ¤   ¤   ¤   ¤   =¤  201,
fa31ff ¤   kPGPPrefDecryptCacheSeconds¤¤   ¤   ¤   ¤   =¤  202,
e7c6bc ¤   kPGPPrefSignCacheSeconds¤   ¤   ¤   ¤   ¤   =¤  203,
003780 ¤   kPGPPrefDateOfLastSplashScreen¤ ¤   ¤   ¤   =¤  204,¤   /* PGPTime */
491ecb ¤   kPGPPrefPreferredAlgorithm¤ ¤   ¤   ¤   ¤   =¤  205,
cca52a ¤   kPGPPrefAllowedAlgorithms¤  ¤   ¤   ¤   ¤   =¤  206,¤   /* OBSOLETE */
b698bf ¤   kPGPPrefMacBinaryDefault¤   ¤   ¤   ¤   ¤   =¤  207,
2eabb1 ¤   kPGPPrefDateOfLastFreewareNotice¤   ¤   ¤   =¤  208,¤   /* OBSOLETE */
c4e7f6 ¤   kPGPPrefFileWipePasses¤ ¤   ¤   ¤   ¤   ¤   =¤  209,¤   /* 6.0 */
829fcc ¤   kPGPPrefDiskWipePasses¤ ¤   ¤   ¤   ¤   ¤   =¤  210,¤   /* 6.0 */
70041e ¤   kPGPPrefLastSearchWindowSelection¤  ¤   ¤   =¤  211,¤   /* 6.0 */
8828bc ¤   kPGPPrefNumberLast
2f1a51 } PGPClientPrefsNumber;
15af5a
ec7bbf typedef enum _PGPClientPrefsString
d6bb36 {
9efd62 ¤   kPGPPrefStringFirst¤¤   ¤   ¤   ¤   ¤   ¤   =¤  400,
0738a4 ¤   kPGPPrefOwnerName = kPGPPrefStringFirst,
e14524 ¤   kPGPPrefCompanyName¤¤   ¤   ¤   ¤   ¤   ¤   =¤  401,
1b2257 ¤   kPGPPrefLicenseNumber¤  ¤   ¤   ¤   ¤   ¤   =¤  402,
--4846 0009084255640100053 Page 2 of pgpClientPrefs.h
27d60e ¤   kPGPPrefComment¤¤   ¤   ¤   ¤   ¤   ¤   ¤   =¤  403,
d22cd5 ¤   kPGPPrefStringLast
bf20c9 } PGPClientPrefsString;
07af5a
f4437c typedef enum _PGPClientPrefsByte
71bb36 {
45a810 ¤   kPGPPrefByteFirst¤  ¤   ¤   ¤   ¤   ¤   ¤   =¤  600,
364bd6 ¤   kPGPPrefPGPtoolsMacPrivateData = kPGPPrefByteFirst,
4bb145 ¤   kPGPPrefPGPmenuMacAppSignatures¤¤   ¤   ¤   =¤  601,
655647 ¤   kPGPPrefPGPkeysMacMainWinPos¤   ¤   ¤   ¤   =¤  602,
08e724 ¤   kPGPPrefPGPkeysMacColumnData¤   ¤   ¤   ¤   =¤  603,
18b9da ¤   kPGPPrefKeyServerList¤  ¤   ¤   ¤   ¤   ¤   =¤  604,
36b82d ¤   kPGPPrefPGPkeysWinMainWinPos¤   ¤   ¤   ¤   =¤  605,
e8bcf6 ¤   kPGPPrefPGPkeysWinColumnData¤   ¤   ¤   ¤   =¤  606,
ccf7a5 ¤   kPGPPrefPGPkeysWinGroupsData¤   ¤   ¤   ¤   =¤  607,
7d7f73 ¤   kPGPPrefAllowedAlgorithmsList¤  ¤   ¤   ¤   =¤  608,¤   /* 5.5.1 */
16b966 ¤   kPGPPrefByteLast
98ded4 } PGPClientPrefsByte;
38af5a
79c5d5 #include "pgpBase.h"
f82b62 #include "pgpPFLErrors.h"
94e8b2 #include "pflPrefs.h"
7fe603 #include "pgpSymmetricCipher.h"
3bed82 #include "pgpKeyServerPrefs.h"
c6af5a
7ae81a static const PGPKeyServerEntry sDefaultKeyServer[] =
c6bb36 {
d7150a ¤   { sizeof(PGPKeyServerEntry), kPGPKeyServerType_LDAP, "",·
440685 ¤   ¤   "certserver.pgp.com", 0, "", kPGPPublicKeyAlgorithm_Invalid,
6ebb06 ¤   ¤   (kKeyServerListed|kKeyServerIsRoot), "" },
71d52b ¤   /*{ sizeof(PGPKeyServerEntry), kPGPKeyServerType_LDAPS, "pgp.com",·
a87c3f ¤   ¤   "internalkeys.pgp.com", 0, "", kPGPPublicKeyAlgorithm_Invalid,
33df87 ¤   ¤   (kKeyServerListed), "" },*/
3d1481 ¤   { sizeof(PGPKeyServerEntry), kPGPKeyServerType_HTTP, "",·
32ab07 ¤   ¤   "pgpkeys.mit.edu", 11371, "", kPGPPublicKeyAlgorithm_Invalid,
77070b ¤   ¤   (kKeyServerListed), "" }
4282f7 };
dfaf5a
080625 static const PGPCipherAlgorithm sAllowedAlgorithms[] =
8bbb36 {
b98e4e ¤   kPGPCipherAlgorithm_CAST5,
4df7f6 ¤   kPGPCipherAlgorithm_3DES,
54c2b4 ¤   kPGPCipherAlgorithm_IDEA
0082f7 };
47af5a
7afe52 #if¤PGP_MACINTOSH¤  /* [ */
4daf5a
7efa23 #if PRAGMA_ALIGN_SUPPORTED
22af46 #pragma options align=mac68k
b07454 #endif
e3af5a
a2f2b1 typedef struct PGPmenuApps
fcbb36 {
9bbf13 ¤   PGPBoolean¤ privateScrap;
fa5cf1 ¤   PGPBoolean¤ useOutputDialog;
d75e98 ¤   OSType¤ ¤   creator;
c2f9ed ¤   Str31¤  ¤   appName;
ae02b5 } PGPmenuApps;
e3af5a
9bfa23 #if PRAGMA_ALIGN_SUPPORTED
617c46 #pragma options align=reset
b47454 #endif
c0af5a
42cd95 static const PGPmenuApps¤   sInitPGPmenuApps[] =
ecbb36 {
c17efa ¤   {FALSE,¤FALSE,¤ 'ttxt', "\pSimpleText"},
313e0f ¤   {TRUE,¤ TRUE,¤  'MOSS', "\pNetscape Communicator"},¤/* Verified -> 4.01 */
9ff9c0 ¤   {TRUE,¤ TRUE,¤  'AOp3', "\pAmerica Online"},¤   ¤   /* Verified -> 3.01 */
59655e ¤   {TRUE,¤ FALSE,¤ 'R*ch', "\pBBEdit"},¤   ¤   ¤   ¤   /* Verified -> 4.5¤ */
53df26 ¤   {TRUE,¤ TRUE,¤  'MSNM', "\pOutlook Express"}
3b1907 };¤
90af5a
--a102 000f64c492040100053 Page 3 of pgpClientPrefs.h
023167 #endif¤ /* ] */
29af5a
6e3adc static const PGPPrefDefault clientDefaults[] =
a1bb36 {
85d80f {kPGPPrefEncryptToSelf,¤¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
041995 {kPGPPrefWordWrapEnable,¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
1776e8 {kPGPPrefDecryptCacheEnable,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
71f97d {kPGPPrefSignCacheEnable,¤  ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
4ad3af {kPGPPrefMailEncryptPGPMIME,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
f49231 {kPGPPrefMailSignPGPMIME,¤  ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
dab7f8 {kPGPPrefFastKeyGen,¤   ¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
163411 {kPGPPrefWarnOnMixRSAElGamal,¤  ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
2a087b {kPGPPrefMailEncryptDefault,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
6ec5cc {kPGPPrefMailSignDefault,¤  ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
1c1de1 {kPGPPrefMarginalIsInvalid,¤¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
a15251 {kPGPPrefDisplayMarginalValidity,¤  ¤   kPGPPrefType_Boolean, (void *) FALSE},
ea95ef {kPGPPrefFirstKeyGenerated,¤¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
e30ddd {kPGPPrefWarnOnRSARecipAndNonRSASigner,¤kPGPPrefType_Boolean, (void *) TRUE},
87d2a9 {kPGPPrefKeyServerSyncUnknownKeys,¤ ¤   kPGPPrefType_Boolean, (void *) FALSE},
efa2a7 {kPGPPrefKeyServerSyncOnAdd,¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
de8d94 {kPGPPrefKeyServerSyncOnKeySign,¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
b691b8 {kPGPPrefKeyServerSyncOnRevocation,¤¤   kPGPPrefType_Boolean, (void *) FALSE},
d3b38f {kPGPPrefKeyServerSyncOnVerify,¤¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
5dedff {kPGPPrefWarnOnReadOnlyKeyRings,¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
aa2095 {kPGPPrefWarnOnWipe,¤   ¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
14f930 {kPGPPrefAutoDecrypt,¤  ¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) FALSE},
704b50 {kPGPPrefWarnOnADK,¤¤   ¤   ¤   ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
f8195f {kPGPPrefPGPkeysMacShowToolbar,¤¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
5dba0c {kPGPPrefWarnOnMemLockFailure,¤ ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
ff0e96 {kPGPPrefExportKeysCompatible,¤ ¤   ¤   kPGPPrefType_Boolean, (void *) TRUE},
9caf5a
4e54c8 {kPGPPrefWordWrapWidth,¤¤   ¤   ¤   kPGPPrefType_Number, (void *) 70},
aac769 {kPGPPrefDecryptCacheSeconds,¤  ¤   kPGPPrefType_Number, (void *) 120},
4c2b41 {kPGPPrefSignCacheSeconds,¤ ¤   ¤   kPGPPrefType_Number, (void *) 120},
6a08a4 {kPGPPrefDateOfLastSplashScreen,¤   kPGPPrefType_Number, (void *) 0},
88e654 {kPGPPrefPreferredAlgorithm,¤   ¤   kPGPPrefType_Number,
81a47c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) kPGPCipherAlgorithm_CAST5},
ecbb5b {kPGPPrefAllowedAlgorithms,¤¤   ¤   kPGPPrefType_Number, (void *) 0xE0000000},
5ce613 {kPGPPrefMacBinaryDefault,¤ ¤   ¤   kPGPPrefType_Number,·
31e2e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) kPGPPrefMacBinaryOn},
628595 {kPGPPrefDateOfLastFreewareNotice,¤ kPGPPrefType_Number, (void *) 0},
d5ca44 {kPGPPrefFileWipePasses,¤   ¤   ¤   kPGPPrefType_Number, (void *) 8},
f53792 {kPGPPrefDiskWipePasses,¤   ¤   ¤   kPGPPrefType_Number, (void *) 3},
5eaf5a
6dfe52 #if¤PGP_MACINTOSH¤  /* [ */
559bc7 {kPGPPrefLastSearchWindowSelection,¤kPGPPrefType_Number, (void *) 3},
5a14ea #elif PGP_WIN32
c9877c {kPGPPrefLastSearchWindowSelection,¤kPGPPrefType_Number, (void *) 2},
4d7454 #endif
e8af5a
5d516d {kPGPPrefOwnerName,¤¤   kPGPPrefType_String, (void *) ""},
b2971f {kPGPPrefCompanyName,¤  kPGPPrefType_String, (void *) ""},
bce181 {kPGPPrefLicenseNumber, kPGPPrefType_String, (void *) ""},
584ad0 {kPGPPrefComment,¤  ¤   kPGPPrefType_String, (void *) ""},
18af5a
acfe52 #if¤PGP_MACINTOSH¤  /* [ */
28af5a
0c04df {kPGPPrefPGPmenuMacAppSignatures, kPGPPrefType_Byte,·
b955fc ¤   (void *) sInitPGPmenuApps, sizeof(sInitPGPmenuApps)},
fdaf5a
c23167 #endif¤ /* ] */
caaf5a
de384e {kPGPPrefKeyServerList, kPGPPrefType_Byte,·
5eb128 ¤   (void *) sDefaultKeyServer, sizeof(sDefaultKeyServer)},
19da3b {kPGPPrefAllowedAlgorithmsList, kPGPPrefType_Byte,·
e7acc9 ¤   (void *) sAllowedAlgorithms, sizeof(sAllowedAlgorithms)},
8782f7 };
eeaf5a
dcdc9c static const PGPSize clientDefaultsSize =·
606f9c ¤   ¤   ¤   ¤   ¤   ¤   sizeof(clientDefaults) / sizeof(PGPPrefDefault);
f5af5a
f6af5a
--da1b 001f1aea2f640100053 Page 4 of pgpClientPrefs.h
8f482e #endif /* ] Included_pgpClientPrefs_h */
14af5a
e7af5a
957e4d /*__Editor_settings____
54af5a
4e4126 ¤   Local Variables:
8a7b17 ¤   tab-width: 4
100e6c ¤   End:
665f8c ¤   vi: ts=4 sw=4
af9e9b ¤   vim: si
f1d062 _____________________*/
--70b7 001aaaad61740100054 Page 1 of pgpClientShared.h
a70335 /*____________________________________________________________________________
93767e ¤   Included_pgpClientShared_h.h
61af5a
3dedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
784b0f ¤   All rights reserved.
24af5a
330190 ¤   $Id: pgpClientShared.h,v 1.1.8.1 1998/11/12 03:11:06 heller Exp $
68f7f7 ____________________________________________________________________________*/
14af5a
686c58 #ifndef Included_pgpClientShared_h¤ /* [ */
233462 #define Included_pgpClientShared_h
80af5a
d3c5d5 #include "pgpBase.h"
55af5a
defa23 #if PRAGMA_ALIGN_SUPPORTED
c6af46 #pragma options align=mac68k
3a7454 #endif
51af5a
4f7353 enum
60bb36 {
364454 ¤   kPGPPhotoIDHeaderVersion¤   = 1,
ba67c5 ¤
6ef40f ¤   kPGPPhotoIDFormat_Invalid¤  = 0,
5b3e1e ¤   kPGPPhotoIDFormat_JPEG¤ ¤   = 1
ad82f7 };
1067c5 ¤
9aab62 typedef struct PGPPhotoUserIDHeader
08bb36 {
5876d9 ¤   PGPUInt16¤  headerLength;
854aa8 ¤   PGPUInt8¤   headerVersion;¤ /* kPGPPhotoIDHeaderVersion */
1199e2 ¤   PGPUInt8¤   photoIDFormat;
c68722 ¤   PGPUInt32¤  reserved2[3];¤  /* Must be zero */
6aaf5a
95437e } PGPPhotoUserIDHeader;
13af5a
0cfa23 #if PRAGMA_ALIGN_SUPPORTED
3c7c46 #pragma options align=reset
bf7454 #endif
4faf5a
7099c6 PGP_BEGIN_C_DECLARATIONS
85af5a
98cbcf #if PRAGMA_IMPORT_SUPPORTED
2eb981 #pragma import on
a97454 #endif
56af5a
9fcbcf #if PRAGMA_IMPORT_SUPPORTED
a32ced #pragma import reset
c67454 #endif
ffaf5a
eb1254 PGP_END_C_DECLARATIONS
2baf5a
31af5a
12e83a #endif /* ] Included_pgpClientShared_h */
41af5a
24af5a
a67e4d /*__Editor_settings____
6caf5a
224126 ¤   Local Variables:
7f7b17 ¤   tab-width: 4
1a0e6c ¤   End:
e35f8c ¤   vi: ts=4 sw=4
bc9e9b ¤   vim: si
aad062 _____________________*/
--671c 000d8dea44340100055 Page 1 of pgpDiskWiper.c
a70335 /*____________________________________________________________________________
e78de7 ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.·
d94b0f ¤   All rights reserved.
8f67c5 ¤
a167c5 ¤
97af5a
cd31e5 ¤   $Id: pgpDiskWiper.c,v 1.4.8.1 1998/11/12 03:11:07 heller Exp $
3cf7f7 ____________________________________________________________________________*/
4faf5a
e53899 /* System Headers */
db5c98 #if PGP_DEBUG
26feb2 #include <stdio.h>
817454 #endif
e705fa #include <string.h> /* For memcpy(), etc. */
deaf5a
35af5a
54823b /* PGPsdk Headers */
79e2ff #include "pgpConfig.h"
142f8d #include "pgpErrors.h"
600d08 #include "pgpMem.h"
0da845 #include "pgpUtilities.h"·
2fe82c #include "pgpPubTypes.h"
794919 #include "pgpUtilities.h"
0a6773 #include "pgpMemoryMgr.h"
bdaf5a
25e839 /* Project Headers */
25e622 #include "pgpDiskWiper.h"
14af5a
94af5a
9238e5 /*
c0ed78 ·* These are the disk-wiping patterns. ·They are repeating patterns of
e38219 ·* 1, 2, 3 and 4 bits, along with some random passes. ·See Peter Gutmann's
71dd07 ·* paper, "Secure Deletion of Data from Magnetic and Solid-State Memory",
30e33b ·* first published in the Sixth USENIX Security Symposium Proceedings,
9f8315 ·* San Jose, California, July 22-25, 1996 for the gory details why.
dbadc0 ·* (http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html)
d5495d ·*/
f22cff PGPInt32 patterns[] = {
b00ca3 ¤   -1, /* Random */
4e0ca3 ¤   -1, /* Random */
051974 ¤   0x555, 0xAAA,
b7032f ¤   0x249, 0x492, 0x924,
11e5d0 ¤   0x000, 0xFFF,
d0da17 ¤   0x111, 0x222, 0x333, 0x444, 0x666, 0x777,·
1055d2 ¤   0x888, 0x999, 0xBBB, 0xCCC, 0xDDD, 0xEEE,
e9b7cb ¤   0xDB6, 0xB6D, 0x6DB,
700ca3 ¤   -1, /* Random */
3b51f9 ¤   -1 /* Random */
d182f7 };
24af5a
f1a932 #define NUMPATTERNS (sizeof(patterns)/sizeof(patterns[0]))
18af5a
dcd7a7 /* Random number code from Colin */
25af5a
e338e5 /*
ed9cbd ·* This is Bob Jenkins' ISAAC generator
4203d6 ·* (http://ourworld.compuserve.com/homepages/bob_jenkins/isaacafa.htm)
59ecb0 ·* which is designed to be cryptographically strong and very fast.
d7f07c ·* I'm not sure if I'd trust it for key material, but it should be
3405a9 ·* strong enough for this application, and the speed is nice when
3a06ba ·* you need megabytes of output.
20495d ·*/
19af5a
f95611 #define ISAAC_LOG 8
1591a2 #define ISAAC_SIZE 256
6e27cd #define ISAAC_BYTES (ISAAC_SIZE * sizeof(PGPInt32))
9eaf5a
931d51 typedef struct isaac_state isaac_state;
5caf5a
3f9cf5 struct isaac_state
9abb36 {
d85943 ¤   PGPInt32 mm[ISAAC_SIZE]; /* State */
--0dde 0000ffab14440100055 Page 2 of pgpDiskWiper.c
8df83f ¤   PGPInt32 aa, bb, cc;
3c82f7 };
4aaf5a
6a332e typedef struct PGPDiskWipe¤ ·PGPDiskWipe;
2eaf5a
965b99 struct PGPDiskWipe
63bb36 {
257925 ¤   PGPContextRef¤  ¤   context;
d135a1 ¤   PGPMemoryMgrRef¤¤   manager;
36720f ¤   PGPInt32¤   ¤   ¤   index;
684f09 ¤   PGPInt32¤   ¤   ¤   passes;
637953 ¤   isaac_state ¤   ¤   state;
cf9bad ¤   PGPInt32 ¤  ¤   ¤   patterns[NUMPATTERNS];
bd82f7 };
71af5a
30af5a
82de69 /* This index operation is more efficient on many processors */
4a44e9 #define ind(mm,x) *(unsigned *)\
4133dc ((char *)(mm) + ( (x) & (ISAAC_SIZE-1)<<2 ))
1baf5a
e122f6 /* The central step. This uses two temporaries, x and y. */
c4b933 #define isaac_step(mix,a,b,mm,m,off,r) \
eebcbd ( \
5fad5e a = (a^(mix)) + m[off], \
433aa2 x = *m, \
d37b00 *(m++) = y = ind(mm,x) + a + b, \
a26c40 *(r++) = b = ind(mm,y>>ISAAC_LOG) + x \
0c5b71 )
15af5a
cc38e5 /*
56bba3 * Refill the entire r array with one call.
687fe0 */
712978 static void
941b4c isaac_refill(struct isaac_state *s,·
47dbd3 ¤   ¤   ¤   ·PGPInt32 r[ISAAC_SIZE])
f6bb36 {
cb4f13 ¤   register PGPInt32 a, b; /* Caches of a and b */
2f7bfb ¤   register PGPInt32 x, y; /* Temps needed by isaac_step() macro */
0a5426 ¤   register PGPInt32 *m = s->mm; /* Pointer into state array */
caaf5a
8b9ff4 ¤   a = s->aa;
7aae9b ¤   b = s->bb + (++s->cc);
13af5a
919100 ¤   do·
92c7a1 ¤   {
c78f08 ¤   ¤   isaac_step(a << 13, a, b, s->mm, m, ISAAC_SIZE/2, r);
e7f51c ¤   ¤   isaac_step(a >> 6, a, b, s->mm, m, ISAAC_SIZE/2, r);
b985ea ¤   ¤   isaac_step(a << 2, a, b, s->mm, m, ISAAC_SIZE/2, r);
bee5c2 ¤   ¤   isaac_step(a >> 16, a, b, s->mm, m, ISAAC_SIZE/2, r);
370027 ¤   } while (m < s->mm+ISAAC_SIZE/2);
6867c5 ¤
349100 ¤   do·
d8c7a1 ¤   {
13d543 ¤   ¤   isaac_step(a << 13, a, b, s->mm, m, -ISAAC_SIZE/2, r);
a5839c ¤   ¤   isaac_step(a >> 6, a, b, s->mm, m, -ISAAC_SIZE/2, r);
0d1155 ¤   ¤   isaac_step(a << 2, a, b, s->mm, m, -ISAAC_SIZE/2, r);
2cbc7f ¤   ¤   isaac_step(a >> 16, a, b, s->mm, m, -ISAAC_SIZE/2, r);
4f2a25 ¤   } while (m < s->mm+ISAAC_SIZE);
8a67c5 ¤
a2efff ¤   s->bb = b;
042225 ¤   s->aa = a;
4fefe6 }
60af5a
24b3ab /* The basic seed-scrambling step */
f4c2b2 #define mix(a,b,c,d,e,f,g,h) \
8cd553 (a ^= b << 11, d += a, \
df7bbe b += c, b ^= c >> 2, e += b, \
b8623c c += d, c ^= d << 8, f += c, \
8afe42 d += e, d ^= e >> 16, g += d, \
6c162f e += f, e ^= f << 10, h += e, \
1916e5 f += g, f ^= g >> 4, a += f, \
0fb720 g += h, g ^= h << 8, b += g, \
--e2f6 000f520c72e40100055 Page 3 of pgpDiskWiper.c
3b7905 h += a, h ^= a >> 9, c += h, \
fc550a a += b)
52af5a
8eaf5a
7538e5 /*
2fe092 * Initialize the ISAAC RNG with the given 256-entry seed array.
fe922f * That array may be the mm[] array.
e97fe0 */
902978 static void
25f2f8 isaac_init(struct isaac_state *s, PGPInt32 const *seed)
60bb36 {
441d04 ¤   PGPInt32 i;
ceb07b ¤   PGPInt32 passes = (seed != 0);
c425e6 ¤   PGPInt32 a, b, c, d, e, f, g, h;
ed67c5 ¤
4fb177 #if 0
046ba7 ¤   /* The original presentation */
f555ab ¤   a = b = c = d = e = f = g = h = 0x9e3779b9; /* the golden ratio */
4b67c5 ¤
f642c9 ¤   for (i = 0; i < 4; ++i) /* scramble it */
10c7a1 ¤   {
626757 ¤   ¤   mix(a, b, c, d, e, f, g, h);
919371 ¤   }
de67c5 ¤
3ddb21 #else
c551f8 ¤   /* A smaller and faster, although more opaque version. */
ec111a ¤   a = 0x1367df5a;
04aedc ¤   b = 0x95d90059;
716f34 ¤   c = 0xc3163e4b;
66b906 ¤   d = 0x0f421ad8;
f5a830 ¤   e = 0xd92a4a78;
b9111d ¤   f = 0xa51a3c49;
90eff0 ¤   g = 0xc4efea1b;
368152 ¤   h = 0x30609119;
ea7454 #endif
8f67c5 ¤
279100 ¤   do·
38c7a1 ¤   {
ee62fc ¤   ¤   /* Fill up mm[] with messy stuff */
6e5f5b ¤   ¤   for (i = 0; i < ISAAC_SIZE; i += 8)·
2e5b34 ¤   ¤   {
2706cf ¤   ¤   ¤   if (seed)·
09f776 ¤   ¤   ¤   {
92c49e ¤   ¤   ¤   ¤   /* use all the information in the seed */
6d9ea5 ¤   ¤   ¤   ¤   a += seed[i];
da36e2 ¤   ¤   ¤   ¤   b += seed[i+1];
449d3f ¤   ¤   ¤   ¤   c += seed[i+2];
af33c7 ¤   ¤   ¤   ¤   d += seed[i+3];
17eaf6 ¤   ¤   ¤   ¤   e += seed[i+4];
5d6c6c ¤   ¤   ¤   ¤   f += seed[i+5];
7ac7b1 ¤   ¤   ¤   ¤   g += seed[i+6];
22398d ¤   ¤   ¤   ¤   h += seed[i+7];
67a3a6 ¤   ¤   ¤   }
cdaf5a
d362ba ¤   ¤   ¤   mix(a, b, c, d, e, f, g, h);
59af5a
ad7069 ¤   ¤   ¤   s->mm[i] = a;
d3ca60 ¤   ¤   ¤   s->mm[i+1] = b;
151a6c ¤   ¤   ¤   s->mm[i+2] = c;
c217d6 ¤   ¤   ¤   s->mm[i+3] = d;
15d104 ¤   ¤   ¤   s->mm[i+4] = e;
ccbfdf ¤   ¤   ¤   s->mm[i+5] = f;
626fd3 ¤   ¤   ¤   s->mm[i+6] = g;
09a4ab ¤   ¤   ¤   s->mm[i+7] = h;
d70fe4 ¤   ¤   }
901b52 ¤   ¤
0ff210 ¤   ¤   seed = s->mm;
ef1b52 ¤   ¤
411b17 ¤   ¤   /*
1c1978 ¤   ¤   ·* If we were given a seed, do a second pass to make
900e39 ¤   ¤   ·* all of the seed affect all of mm
f59de3 ¤   ¤   ·*/
--2338 0003ab6c59c40100055 Page 4 of pgpDiskWiper.c
9ca276 ¤   } while (passes--);
5aaf5a
56b9e3 ¤   s->aa = s->bb = s->cc = 0;
66efe6 }
b7af5a
bd38e5 /*
4fa923 * Seed the RNG, using 160 bits of seed material, which should be *plenty*.
c0a58e * This cheats and uses the s->mm[] array to hold the seed material,
be78b3 * which is allowed by isac_init().
3c7fe0 */
96f1ae static PGPError
d8bf32 isaac_seed(PGPDiskWipeRef ref)
09bb36 {
1517eb ¤   PGPError¤   ¤   error¤  = kPGPError_NoErr;
6e8d53 ¤   struct isaac_state* s¤  = &(ref->state);
ed67c5 ¤
74092a ¤   /* Get some good seed material. */
7263d0 ¤   error = PGPContextGetRandomBytes(ref->context, s->mm, 20);
11f0a7 ¤   isaac_init(s, s->mm);
8567c5 ¤
00c674 ¤   return error;
c7efe6 }
15af5a
e45d47 /* End RNG code */
e5af5a
5eaf5a
91af5a
e838e5 /*
2fcf2e * Shuffle an array of ints into random order.
170494 * This is done by swapping the last element in the array
00d7f0 * with a random element of the array and then repeating
7f22b0 * for the array without the last element.
347fe0 */
6e2978 static void
89802c shuffle(PGPInt32 *array,·
a89566 ¤   ¤   PGPUInt32 num,·
528866 ¤   ¤   struct isaac_state *s)
2dbb36 {
8e8f00 ¤   PGPInt32 i, t;
30c1e7 ¤   PGPInt32 r[ISAAC_SIZE];
f067c5 ¤
f8eef3 ¤   isaac_refill(s, r);
3567c5 ¤
917b0c ¤   while (--num)·
7cc7a1 ¤   {
aa2658 ¤   ¤   i = (int)(r[num] % (num+1));
b2b030 ¤   ¤   t = array[i];
885fea ¤   ¤   array[i] = array[num];
2e35e8 ¤   ¤   array[num] = t;
2a9371 ¤   }
01efe6 }
24af5a
0f32cb /* Move the random pass into the middle of the shuffle */
cd2978 static void
9d4acb tweakshuffle(PGPInt32 *array,·
1c492a ¤   ¤   ¤   ·PGPUInt32 num)
5dbb36 {
4251fc ¤   PGPUInt32 i;
bfaf5a
54d94f ¤   for (i = 0; i < num; i++)·
41c7a1 ¤   {
3e820d ¤   ¤   if (array[i] < 0)·
f25b34 ¤   ¤   {
4ea888 ¤   ¤   ¤   num /= 2;
78d395 ¤   ¤   ¤   array[i] = array[num];
290001 ¤   ¤   ¤   array[num] = -1;
c7cdcb ¤   ¤   ¤   break;
c60fe4 ¤   ¤   }
359371 ¤   }
24efe6 }
27af5a
3af492 /* Pass types:
--ac82 00024b70f5740100055 Page 5 of pgpDiskWiper.c
e69139 * 0xXXX - Repeat XXX to fill file
2c5d37 * -1 - Random
c27fe0 */
b72978 static void
ce351e filltable(struct isaac_state *s,·
6fcb03 ¤   ¤   ··PGPInt32 buf[ISAAC_SIZE],·
384707 ¤   ¤   ··PGPInt32 type)
04bb36 {
211d04 ¤   PGPInt32 i;
7caf5a
676faf ¤   if (type < 0)·
a2c7a1 ¤   {
2c1790 ¤   ¤   isaac_refill(s, (PGPInt32 *)buf);
e347d1 ¤   }·
0f0e24 ¤   else
ecc7a1 ¤   {
c56c67 ¤   ¤   ((unsigned char *)buf)[0] = 255 & (type >> 4);
5dd57f ¤   ¤   ((unsigned char *)buf)[1] = 255 & (type << 4 | type >> 8);
283cd2 ¤   ¤   ((unsigned char *)buf)[2] = 255 & type;
f01b52 ¤   ¤
8c1eb8 ¤   ¤   for (i = 3; i < ISAAC_BYTES/2; i *= 2)
025b34 ¤   ¤   {
8b3d6e ¤   ¤   ¤   memcpy((char *)buf+i, (char *)buf, i);
eb0fe4 ¤   ¤   }
a61b52 ¤   ¤
82d6ea ¤   ¤   memcpy((char *)buf+i, (char *)buf, ISAAC_BYTES-i);
cc9371 ¤   }
94efe6 }
b2af5a
e0af5a
fa8de9 PGPError·
b48628 PGPCreateDiskWiper( PGPContextRef context,·
a1c08d ¤   ¤   ¤   ¤   ¤   PGPDiskWipeRef *wipeRef,·
2117f0 ¤   ¤   ¤   ¤   ¤   PGPInt32 numPasses)
d5bb36 {
8436a8 ¤   PGPError error = kPGPError_NoErr;
d0ffe8 ¤   PGPMemoryMgrRef manager = PGPGetContextMemoryMgr (context);
00af5a
3edc63 ¤   if (IsntNull(wipeRef))
2ec7a1 ¤   {
f5b012 ¤   ¤   *wipeRef = NULL;
909371 ¤   }
e467c5 ¤
9f67c5 ¤
7b307c ¤   *wipeRef = (PGPDiskWipeRef) PGPNewData(
3f6b01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   manager,
0d79d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPDiskWipe),·
77e0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
e667c5 ¤
5d67c5 ¤
772145 ¤   if(IsntNull(*wipeRef))
dcc7a1 ¤   {
c9fe41 ¤   ¤   PGPDiskWipeRef ref = *wipeRef;
591b52 ¤   ¤
db297a ¤   ¤   /* we need this guy for random data */
c92911 ¤   ¤   ref->context = context;
26af5a
bd8b1d ¤   ¤   /* we need this guy for deleting ourselves */
7a1690 ¤   ¤   ref->manager = manager;
1baf5a
728ca5 ¤   ¤   /* keep track of which pass we are on */
023358 ¤   ¤   ref->index = 0;·
541b52 ¤   ¤
c07ca2 ¤   ¤   /* remember total # of passes */
c5f604 ¤   ¤   ref->passes = numPasses;·
671b52 ¤   ¤
075273 ¤   ¤   /* initialize random # generator */
121d42 ¤   ¤   error = isaac_seed( ref );·
d2af5a
8affd0 ¤   ¤   /* did it initialize ok? */
bc95ab ¤   ¤   if( IsPGPError(error) )
245b34 ¤   ¤   {
--ef19 0002eb6e81440100055 Page 6 of pgpDiskWiper.c
2ffe64 ¤   ¤   ¤   /* if not clean up */
9e75b7 ¤   ¤   ¤   PGPFreeData(ref);
f487c7 ¤   ¤   ¤
943b5b ¤   ¤   ¤   return error;
290fe4 ¤   ¤   }
b61b52 ¤   ¤
0459e1 ¤   ¤   /* set up the pattern array */
4db290 ¤   ¤   if(numPasses < NUMPATTERNS)
225b34 ¤   ¤   {
bdf083 ¤   ¤   ¤   PGPInt32 i;
6b87c7 ¤   ¤   ¤
6c8d74 ¤   ¤   ¤   for(i = 0; i < numPasses - 1; i++)
20f776 ¤   ¤   ¤   {
7616f6 ¤   ¤   ¤   ¤   ref->patterns[i] = ·patterns[i];
b9a3a6 ¤   ¤   ¤   }
1b87c7 ¤   ¤   ¤
1c0ef1 ¤   ¤   ¤   ref->patterns[i] = -1;
250fe4 ¤   ¤   }
7aee26 ¤   ¤   else·
285b34 ¤   ¤   {
248f12 ¤   ¤   ¤   memcpy(ref->patterns, patterns, sizeof(patterns));¤ ¤   ¤   ¤
c30fe4 ¤   ¤   }
811b52 ¤   ¤
80d53f ¤   ¤   if(numPasses > 3)
e75b34 ¤   ¤   {
60e791 ¤   ¤   ¤   if(numPasses > NUMPATTERNS)
47f776 ¤   ¤   ¤   {
6999c0 ¤   ¤   ¤   ¤   /* only wanna shake up the array*/
dbabd4 ¤   ¤   ¤   ¤   numPasses = NUMPATTERNS;
ffa3a6 ¤   ¤   ¤   }
7aaf5a
7ef8a6 ¤   ¤   ¤   /* Shuffle, leaving first & last pass alone */
56d607 ¤   ¤   ¤   shuffle(ref->patterns + 1,·
2df276 ¤   ¤   ¤   ¤   (unsigned)numPasses - 2,·
dadfaa ¤   ¤   ¤   ¤   &(ref->state));
3367c5 ¤
7f14d1 ¤   ¤   ¤   /* Force a random pass to the middle */
7bc60a ¤   ¤   ¤   tweakshuffle(ref->patterns + 1,·
9ed762 ¤   ¤   ¤   ¤   ¤   (unsigned)numPasses - 2);
920fe4 ¤   ¤   }
4994aa ¤   ¤   ¤   ¤   ¤   ¤
bc9371 ¤   }
450e24 ¤   else
25c7a1 ¤   {
49b081 ¤   ¤   error = kPGPError_OutOfMemory;
97b012 ¤   ¤   *wipeRef = NULL;
a99371 ¤   }
8367c5 ¤
b9c674 ¤   return error;
c6efe6 }
5d94aa ¤   ¤   ¤   ¤   ¤   ¤
8e8de9 PGPError·
e0d6e9 PGPGetDiskWipeBuffer(PGPDiskWipeRef wipeRef,·
94f198 ¤   ¤   ¤   ¤   ¤   ·PGPInt32 buffer[256])
55bb36 {
2936a8 ¤   PGPError error = kPGPError_NoErr;
1767c5 ¤
2ccfb7 ¤   if(¤IsntNull(wipeRef) && IsntNull(buffer))
a1c7a1 ¤   {
4a90cf ¤   ¤   if(wipeRef->index < wipeRef->passes)
a15b34 ¤   ¤   {
eb4437 ¤   ¤   ¤   if(wipeRef->index < NUMPATTERNS - 1)
f3f776 ¤   ¤   ¤   {
205c98 #if PGP_DEBUG
b7532f ¤   #if ! PGP_MACINTOSH
cce66c ¤   ¤   ¤   ¤   printf("pattern is: 0x%x\r\n",
97559a ¤   ¤   ¤   ¤   ¤   wipeRef->patterns[wipeRef->index]);
76b7ec ¤   #endif
ce9009 #endif¤ ¤   ¤   ¤
146aa5 ¤   ¤   ¤   ¤   filltable(¤ &(wipeRef->state),
2a398d ¤   ¤   ·¤  ¤   ¤   ¤   ¤   buffer,
2e640c ¤   ¤   ·¤  ¤   ¤   ¤   ¤   wipeRef->patterns[wipeRef->index++]);
--05de 00192fc9d4940100055 Page 7 of pgpDiskWiper.c
cfa3a6 ¤   ¤   ¤   }
41bb8c ¤   ¤   ¤   else
e6f776 ¤   ¤   ¤   {
775c98 #if PGP_DEBUG
32532f ¤   #if ! PGP_MACINTOSH
2cec35 ¤   ¤   ¤   ¤   printf("pattern is: 0xffffffff\r\n");
4ab7ec ¤   #endif
cb9009 #endif¤ ¤   ¤   ¤
ad6aa5 ¤   ¤   ¤   ¤   filltable(¤ &(wipeRef->state),
bf398d ¤   ¤   ·¤  ¤   ¤   ¤   ¤   buffer,
7f56e8 ¤   ¤   ·¤  ¤   ¤   ¤   ¤   -1);
781155 ¤   ¤   ·¤  ¤   ¤   ¤
47e5d7 ¤   ¤   ·¤  ¤   wipeRef->index++;
e0a3a6 ¤   ¤   ¤   }
341b52 ¤   ¤
300fe4 ¤   ¤   }
470e1d ¤   ¤   else
ee5b34 ¤   ¤   {
da3dca ¤   ¤   ¤   error = kPGPError_NoMorePatterns;
e10fe4 ¤   ¤   }
789371 ¤   }
9e0e24 ¤   else
88c7a1 ¤   {
70d5d3 ¤   ¤   error = kPGPError_BadParams;
549371 ¤   }
4aaf5a
9ac674 ¤   return error;
33efe6 }
f23ede ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
e78de9 PGPError·
69ae93 PGPDestroyDiskWiper( PGPDiskWipeRef wipeRef )
ddbb36 {
d236a8 ¤   PGPError error = kPGPError_NoErr;
b367c5 ¤
caba92 ¤   if( IsntNull(wipeRef) )
6358c8 ¤   {¤  ¤
b23c1c ¤   ¤   PGPFreeData( wipeRef );
7e9371 ¤   }
f40e24 ¤   else
0dc7a1 ¤   {
bcd5d3 ¤   ¤   error = kPGPError_BadParams;
ae9371 ¤   }
9967c5 ¤
a7c674 ¤   return error;
92efe6 }
--b14a 001c0ee1f6540100056 Page 1 of pgpDiskWiper.h
a70335 /*____________________________________________________________________________
e78de7 ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.·
d94b0f ¤   All rights reserved.
8f67c5 ¤
a167c5 ¤
97af5a
926414 ¤   $Id: pgpDiskWiper.h,v 1.2.8.1 1998/11/12 03:11:07 heller Exp $
1bf7f7 ____________________________________________________________________________*/
820a0d #ifndef Included_pgpDiskWiper_h¤/* [ */
893004 #define Included_pgpDiskWiper_h
79af5a
f0e82c #include "pgpPubTypes.h"
7eaf5a
a4c0dd #define kPGPNumPatterns 26
ebaf5a
18410e /* need to integrate this error */
bc0dee #define kPGPError_NoMorePatterns 1
80af5a
f1e6cd typedef struct PGPDiskWipe * PGPDiskWipeRef;
adaf5a
40b078 #define¤kInvalidPGPDiskWipeRef¤ ¤   ¤   ((PGPDiskWipeRef) NULL)
81e92f #define PGPDiskWipeRefIsValid( ref )¤   ( (ref) != PGPDiskWipeRef )
ffaf5a
0399c6 PGP_BEGIN_C_DECLARATIONS
7bcbcf #if PRAGMA_IMPORT_SUPPORTED
a4b981 #pragma import on
187454 #endif
18af5a
bfaf5a
848de9 PGPError·
b6ba66 PGPCreateDiskWiper(¤PGPContextRef context,·
74dfc2 ¤   ¤   ¤   ¤   ¤   PGPDiskWipeRef *wipeRef,
80f7b8 ¤   ¤   ¤   ¤   ¤   PGPInt32 numPasses);
0794aa ¤   ¤   ¤   ¤   ¤   ¤
588de9 PGPError·
99438e PGPGetDiskWipeBuffer(¤  PGPDiskWipeRef wipeRef,
23c57a ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 buffer[256]);
ee3ede ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
ab8de9 PGPError·
0f5c06 PGPDestroyDiskWiper(PGPDiskWipeRef wipeRef);
41af5a
73cbcf #if PRAGMA_IMPORT_SUPPORTED
382ced #pragma import reset
1c7454 #endif
031254 PGP_END_C_DECLARATIONS
c3af5a
3daf5a
6dd48c #endif /* ] Included_pgpDiskWiper_h */
e1af5a
afaf5a
877e4d /*__Editor_settings____
1faf5a
ac4126 ¤   Local Variables:
be7b17 ¤   tab-width: 4
db0e6c ¤   End:
365f8c ¤   vi: ts=4 sw=4
6b9e9b ¤   vim: si
c0d062 _____________________*/
--0ab3 00040cde84240100057 Page 1 of pgpKeyServerPrefs.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
512d8f ¤   $Id: pgpKeyServerPrefs.c,v 1.20.8.1 1998/11/12 03:11:08 heller Exp $
02f7f7 ____________________________________________________________________________*/
544720 #include "pflPrefTypes.h"
df81a4 #include "pgpBuildFlags.h"
af2b62 #include "pgpPFLErrors.h"
e3c97b #include "pgpClientPrefs.h"
38ed82 #include "pgpKeyServerPrefs.h"
27a146 #include "pgpDebug.h"
600d08 #include "pgpMem.h"
caaf5a
84324c #include <string.h>
85feb2 #include <stdio.h>
741b42 #include "pgpStrings.h"
94af5a
d7c744 ¤   PGPError
8fb34c PGPGetKeyServerPrefs(¤  PGPPrefRef¤ ¤   ¤   ¤   prefRef,
b204b8 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerEntry¤  ¤   **keyserverList,
9f4650 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   *keyserverCount)
48bb36 {
5c8f52 ¤   PGPError¤   ¤   ¤   err;
252e8b ¤   PGPSize¤¤   ¤   ¤   dataLength;
364f7d ¤   PGPBoolean¤ ¤   ¤   badStruct = FALSE;
7ac1c0 ¤   PGPUInt32¤  ¤   ¤   index;
c13813 ¤   PGPKeyServerEntry *¤tempList = NULL;
b3af5a
ecc111 ¤   PGPValidatePtr(keyserverList);
b66630 ¤   PGPValidatePtr(keyserverCount);
4aaf5a
3ebe79 ¤   err = PGPGetPrefData(¤  prefRef,·
ad4118 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPrefKeyServerList,·
2c37ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   &dataLength,·
6d4a89 ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyserverList);
01af5a
3b9036 ¤   *keyserverCount = dataLength / sizeof(PGPKeyServerEntry);
5aaf5a
2af69b ¤   if (IsntPGPError(err))
d1c7a1 ¤   {
587d3e ¤   ¤   for (index=0; index<*keyserverCount; index++)
683743 ¤   ¤   ¤   if ((*keyserverList)[index].structSize !=·
fa869f ¤   ¤   ¤   ¤   sizeof(PGPKeyServerEntry))
ccf776 ¤   ¤   ¤   {
8dc16c ¤   ¤   ¤   ¤   badStruct = TRUE;
d2a3a6 ¤   ¤   ¤   }
8a9371 ¤   }
c2af5a
411a58 ¤   if (badStruct)
f3c7a1 ¤   {
d3faaa ¤   ¤   PGPDisposePrefData(prefRef, *keyserverList);
9aca7d ¤   ¤   tempList = (PGPKeyServerEntry *) PGPNewData( PGPGetDefaultMemoryMgr(),
729ca8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(sDefaultKeyServer),
097e53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
55af5a
65d273 ¤   ¤   pgpCopyMemory(sDefaultKeyServer, tempList, sizeof(sDefaultKeyServer));
13af5a
7f80a6 ¤   ¤   *keyserverCount = sizeof(sDefaultKeyServer) /·
4d78b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPKeyServerEntry);
2687c7 ¤   ¤   ¤
f569a5 ¤   ¤   err = PGPSetKeyServerPrefs(prefRef, tempList, *keyserverCount);
4b077e ¤   ¤   PGPFreeData(tempList);
11af5a
89e2b3 ¤   ¤   if (IsntPGPError(err))
35fc7b ¤   ¤   ¤   err = PGPGetPrefData(prefRef,·
b6cf09 ¤   ¤   ¤   ¤   ¤   kPGPPrefKeyServerList,·
2be431 ¤   ¤   ¤   ¤   ¤   &dataLength,·
ca07ba ¤   ¤   ¤   ¤   ¤   keyserverList);
da9371 ¤   }
12af5a
405ea8 ¤   return err;
--2f84 000beb32a0d40100057 Page 2 of pgpKeyServerPrefs.c
e0af5a
77efe6 }
29af5a
82c744 ¤   PGPError
e6f6c4 PGPSetKeyServerPrefs(
1b2d2e ¤   PGPPrefRef¤ ¤   ¤   ¤   prefRef,
1c2fc2 ¤   PGPKeyServerEntry¤  ¤   *keyserverList,
2ca52a ¤   PGPUInt32¤  ¤   ¤   ¤   keyserverCount )
5fbb36 {
b161e0 ¤   PGPError¤   err;
fbf810 ¤   PGPSize¤¤   dataLength;
7fc7f9 ¤   PGPUInt32¤  index;
d1af5a
9ac111 ¤   PGPValidatePtr(keyserverList);
18af5a
01e1e1 ¤   for (index=0; index<keyserverCount; index++)
3eb560 ¤   ¤   keyserverList[index].structSize = sizeof(PGPKeyServerEntry);
b8af5a
20baf9 ¤   dataLength = keyserverCount * sizeof(PGPKeyServerEntry);
72af5a
b9e825 ¤   err = PGPSetPrefData(¤  prefRef,·
d24118 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPrefKeyServerList,·
137b60 ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataLength,·
f94a89 ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyserverList);
245ea8 ¤   return err;
74efe6 }
28af5a
d2c744 ¤   PGPError
96d6b4 PGPCreateKeyServerPath(¤PGPPrefRef¤ ¤   ¤   ¤   prefRef,
a94054 ¤   ¤   ¤   ¤   ¤   ¤   const char*¤¤   ¤   ¤   searchDomain,
c65acb ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerEntry¤  ¤   **keyserverPath,
364650 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   *keyserverCount)
c6bb36 {
aeba49 ¤   PGPError¤   ¤   ¤   ¤   err;
12f75b ¤   PGPKeyServerEntry¤  ¤   *keyserverList;
d49cad ¤   PGPUInt32¤  ¤   ¤   ¤   listCount;
e08a71 ¤   PGPUInt32¤  ¤   ¤   ¤   index;
6f5882 ¤   char¤   ¤   ¤   ¤   ¤   nullDomain[] = "";
8d67c5 ¤
248053 ¤   PGPValidatePtr(keyserverPath);
e36630 ¤   PGPValidatePtr(keyserverCount);
1b67c5 ¤
78ace3 ¤   if( IsNull( searchDomain ) )
74ef8b ¤   ¤   searchDomain = nullDomain;
4d1b52 ¤   ¤
a97c67 ¤   err = PGPGetKeyServerPrefs(prefRef, &keyserverList, &listCount);
0bbdc8 ¤   if( IsPGPError(err) )
2dc9db ¤   ¤   return err;
b8af5a
ffd23a ¤   // init pointers
55e150 ¤   *keyserverCount = 0;
5458d1 ¤   *keyserverPath = (PGPKeyServerEntry *)pgpAlloc(sizeof(PGPKeyServerEntry));
faaf5a
410c33 ¤   for(index = 0; index < listCount; index++)
7dc7a1 ¤   {
40c0df ¤   ¤   // check for a domain match
7798fd ¤   ¤   if( !pgpCompareStringsIgnoreCase(keyserverList[index].domain,
48e91e ¤   ¤   ¤   ¤   searchDomain) )
b45b34 ¤   ¤   {
c5b71f ¤   ¤   ¤   *keyserverCount = *keyserverCount + 1;
3087c7 ¤   ¤   ¤
f08b92 ¤   ¤   ¤   pgpRealloc(¤keyserverPath,·
bba4bd ¤   ¤   ¤   ¤   ¤   ¤   *keyserverCount * sizeof(PGPKeyServerEntry));
6baf5a
1c08a5 ¤   ¤   ¤   (*keyserverPath)[*keyserverCount - 1] = keyserverList[index];
a90fe4 ¤   ¤   }
509371 ¤   }
c8af5a
9d07be ¤   if( searchDomain[0] ) // add servers that do all domains
3fc7a1 ¤   {
83d481 ¤   ¤   for(index = 0; index < listCount; index++)
be5b34 ¤   ¤   {
--b4f6 000d597a3d240100057 Page 3 of pgpKeyServerPrefs.c
6a3a2f ¤   ¤   ¤   if( !keyserverList[index].domain[0] )
24f776 ¤   ¤   ¤   {
eca638 ¤   ¤   ¤   ¤   *keyserverCount = *keyserverCount + 1;
682b85 ¤   ¤   ¤   ¤
fc03f4 ¤   ¤   ¤   ¤   pgpRealloc(¤keyserverPath,·
1bb20b ¤   ¤   ¤   ¤   ¤   ¤   ¤   *keyserverCount * sizeof(PGPKeyServerEntry));
f8af5a
0671ef ¤   ¤   ¤   ¤   (*keyserverPath)[*keyserverCount - 1] = keyserverList[index];
0fa3a6 ¤   ¤   ¤   }
1a0fe4 ¤   ¤   }
549371 ¤   }
6faf5a
e0cfe9 ¤   PGPDisposePrefData(prefRef, keyserverList);
e467c5 ¤
255ea8 ¤   return err;
05efe6 }
34af5a
47c744 ¤   PGPError
400d1d PGPDisposeKeyServerPath(PGPKeyServerEntry *keyserverPath)
e4bb36 {
9a8053 ¤   PGPValidatePtr(keyserverPath);
27af5a
3f036e ¤   if( keyserverPath )
cec7a1 ¤   {
fede33 ¤   ¤   pgpFree(keyserverPath);
4d9371 ¤   }
b4151e ¤   return kPGPError_NoErr;
daefe6 }
27af5a
bcc744 ¤   PGPError
84d37b PGPGetRootKeyServer(
43d174 ¤   PGPPrefRef¤ ¤   ¤   prefRef,
71f8a4 ¤   PGPKeyServerEntry¤  *rootServer )
ccbb36 {
a37d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
0f3969 ¤   PGPKeyServerEntry¤  *keyserverList;
b02e8b ¤   PGPSize¤¤   ¤   ¤   dataLength;
fdf60e ¤   PGPUInt32¤  ¤   ¤   count;
cac1c0 ¤   PGPUInt32¤  ¤   ¤   index;
0fe73f ¤   PGPBoolean¤ ¤   ¤   found = FALSE;
af67c5 ¤
18b029 ¤   PGPValidatePtr( rootServer );
5867c5 ¤
79be79 ¤   err = PGPGetPrefData(¤  prefRef,·
de4118 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPrefKeyServerList,·
9c37ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   &dataLength,·
640a76 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyserverList);
8482f0 ¤   if (IsPGPError(err))
e6c9db ¤   ¤   return err;
bfaf5a
1bcf3c ¤   count = dataLength / sizeof(PGPKeyServerEntry);
e0af5a
4c6cee ¤   for(index = 0; index < count; index++)
66c7a1 ¤   {
02d224 ¤   ¤   if( IsKeyServerRoot( keyserverList[index].flags ) )
415b34 ¤   ¤   {
5bf8fd ¤   ¤   ¤   *rootServer = keyserverList[index];
4238c4 ¤   ¤   ¤   found = TRUE;
0bcdcb ¤   ¤   ¤   break;
360fe4 ¤   ¤   }
b49371 ¤   }
1ca9e7 ¤   if( !found )
9efd76 ¤   ¤   for(index = 0; index < count; index++)
705b34 ¤   ¤   {
b6a59e ¤   ¤   ¤   if( keyserverList[index].domain[0] == '\0' )
16f776 ¤   ¤   ¤   {
906ebc ¤   ¤   ¤   ¤   *rootServer = keyserverList[index];
50b190 ¤   ¤   ¤   ¤   found = TRUE;
63f622 ¤   ¤   ¤   ¤   break;
6da3a6 ¤   ¤   ¤   }
f70fe4 ¤   ¤   }
d5af5a
--57b4 001afc1560640100057 Page 4 of pgpKeyServerPrefs.c
55cfe9 ¤   PGPDisposePrefData(prefRef, keyserverList);
8b67c5 ¤
0ea9e7 ¤   if( !found )
942f1f ¤   ¤   err = kPGPError_ItemNotFound;
c867c5 ¤
635ea8 ¤   return err;
42efe6 }
a6af5a
ec6d52 ¤   void
85abb6 PGPGetKeyServerURL(
493341 ¤   PGPKeyServerEntry¤  *keyserver,
6ca492 ¤   char¤   ¤   ¤   ¤   *url )
7ebb36 {
5c2bf2 ¤   switch( keyserver->protocol )
7bc7a1 ¤   {
364166 ¤   ¤   case kPGPKeyServerType_LDAP:
17c263 ¤   ¤   ¤   strcpy( url, "ldap://" );
f1cdcb ¤   ¤   ¤   break;
07487c ¤   ¤   case kPGPKeyServerType_HTTP:
38f8b9 ¤   ¤   ¤   strcpy( url, "http://" );
1fcdcb ¤   ¤   ¤   break;
ef86da ¤   ¤   case kPGPKeyServerType_LDAPS:
28a32b ¤   ¤   ¤   strcpy( url, "ldaps://" );
02cdcb ¤   ¤   ¤   break;
153908 ¤   ¤   case kPGPKeyServerType_HTTPS:
2adac6 ¤   ¤   ¤   strcpy( url, "https://" );
91cdcb ¤   ¤   ¤   break;
d19371 ¤   }
5d2760 ¤   strncat( url, keyserver->serverDNS, 241 );
337347 ¤   if( keyserver->serverPort != 0 )
04b961 ¤   ¤   sprintf( url, "%s:%d", url, keyserver->serverPort );
69efe6 }
9daf5a
5f6d52 ¤   void
ddfc4f PGPFindEmailDomain(const char *emailAddress, char *domain)
37bb36 {
326deb ¤   char *p = (char *) emailAddress;
1367c5 ¤
fa0350 ¤   if (IsNull(emailAddress))
ccc7a1 ¤   {
238149 ¤   ¤   strcpy(domain, "\0");
1599bf ¤   ¤   return;
839371 ¤   }
57af5a
a837a8 ¤   while(*p && *p != '@')
08d159 ¤   ¤   p++;
1e0baa ¤   if(*p)
e1c7a1 ¤   {
93d159 ¤   ¤   p++;
988d93 ¤   ¤   strcpy(domain, p);
b192bb ¤   ¤   p = domain;
f0d787 ¤   ¤   while(*p && *p != '>')
ca64c8 ¤   ¤   ¤   p++;
af4310 ¤   ¤   if(*p == '>')
2304fe ¤   ¤   ¤   *p = '\0';
209371 ¤   }
cbefe6 }
afaf5a
--f2e9 000aa2f581940100058 Page 1 of pgpKeyServerPrefs.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
d96a16 ¤   $Id: pgpKeyServerPrefs.h,v 1.13.8.1 1998/11/12 03:11:09 heller Exp $
0ff7f7 ____________________________________________________________________________*/
75af5a
266cad #ifndef Included_pgpKeyServerPrefs_h¤   /* [ */
e142e7 #define Included_pgpKeyServerPrefs_h
58af5a
5c2b62 #include "pgpPFLErrors.h"
ece8b2 #include "pflPrefs.h"
4ceb5b #include "pgpKeyServer.h"
36a076 #include "pgpKeys.h"
c0af5a
1d02ef #define¤kMaxServerNameLength¤   255
f0af5a
8afa23 #if PRAGMA_ALIGN_SUPPORTED
30af46 #pragma options align=mac68k
e97454 #endif
92af5a
9618b5 enum ···PGPKeyServerEntryFlags
e6bb36 {
f2a321 ¤   kKeyServerListed¤   ¤   = 1,
a678c1 ¤   kKeyServerIsRoot¤   ¤   = 2
a182f7 };
5faf5a
4b5e58 typedef struct PGPKeyServerEntry
9fbb36 {
e7fc90 ¤   PGPSize¤¤   ¤   ¤   ¤   structSize;
7bfaf7 ¤   PGPKeyServerType¤   ¤   protocol;
c2a98a ¤   char¤   ¤   ¤   ¤   ¤   domain[kMaxServerNameLength + 1];
2bd90f ¤   char¤   ¤   ¤   ¤   ¤   serverDNS[kMaxServerNameLength + 1];
77c1aa ¤   PGPUInt16¤  ¤   ¤   ¤   serverPort;
324d20 ¤   char¤   ¤   ¤   ¤   ¤   authKeyIDString[kPGPMaxKeyIDStringSize];
b07fc8 ¤   PGPPublicKeyAlgorithm¤  authAlg;
4cad57 ¤   PGPUInt32¤  ¤   ¤   ¤   flags;
db4053 ¤   char¤   ¤   ¤   ¤   ¤   reserved[64];
549cd9 } PGPKeyServerEntry;
1daf5a
128afd #define IsKeyServerListed(x)¤   ((x & kKeyServerListed) != 0)
2d7a89 #define IsKeyServerRoot(x)¤ ¤   ((x & kKeyServerIsRoot) != 0)
34fc93 #define KeyServersAreEqual(x,y)¤\
f438c8 (¤  (x).protocol == (y).protocol && \
40c200 ¤   (x).serverPort == (y).serverPort && \
8d507a ¤   !strcmp((x).domain, (y).domain)¤&& \
bb709a ¤   !strcmp((x).serverDNS, (y).serverDNS) )
73af5a
a0fa23 #if PRAGMA_ALIGN_SUPPORTED
d77c46 #pragma options align=reset
fa7454 #endif
8aaf5a
9399c6 PGP_BEGIN_C_DECLARATIONS
77cbcf #if PRAGMA_IMPORT_SUPPORTED
60b981 #pragma import on
5a7454 #endif
54af5a
222a2e /*¤
30aec8 ¤   returns an array of PGPKeyServerEntry structures·
c3e0c4 ¤   describing the keyservers in the default keyserver
11566f ¤   path and the number of structures in the array.
b37fe0 */
7ac744 ¤   PGPError
67b34c PGPGetKeyServerPrefs(¤  PGPPrefRef¤ ¤   ¤   ¤   prefRef,
fa04b8 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerEntry¤  ¤   **keyserverList,
7f52e3 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   *keyserverCount);
50af5a
1e2a2e /*¤
28a00f ¤   given an array of PGPKeyServerEntry structures·
6ce0c4 ¤   describing the keyservers in the default keyserver
8ce58b ¤   path it saves them off for later retrieval.
aa317e ¤   All domains should be grouped contiguously in the array.
--8f0b 001d48d822440100058 Page 2 of pgpKeyServerPrefs.h
c77fe0 */
3ec744 ¤   PGPError
b6c3fc PGPSetKeyServerPrefs(¤  PGPPrefRef¤ ¤   ¤   ¤   prefRef,
79bf34 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerEntry¤  ¤   *keyserverList,
ca0d3c ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   keyserverCount);
1baf5a
9b2a2e /*¤
a5503a ¤   given a domain (i.e. pgp.com), returns an array of·
16c0eb ¤   PGPKeyServerEntry structures describing the keyservers·
fe27b6 ¤   in the keyserver path and the number of structures in·
be7cf8 ¤   the array. The keyservers should be searched in the order·
5a0cee ¤   returned by the function.
b17fe0 */
feaf5a
7ec744 ¤   PGPError
7dd6b4 PGPCreateKeyServerPath(¤PGPPrefRef¤ ¤   ¤   ¤   prefRef,
6d4054 ¤   ¤   ¤   ¤   ¤   ¤   const char*¤¤   ¤   ¤   searchDomain,
de5acb ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerEntry¤  ¤   **keyserverPath,
7e52e3 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   *keyserverCount);
a138e5 /*
12f4ea ¤   frees the array returned by PGPCreateKeyServerPath()
7f7fe0 */
15af5a
c1c744 ¤   PGPError
24cb49 PGPDisposeKeyServerPath(PGPKeyServerEntry *keyserverPath);
86af5a
fae70a /* Returns root server */
f1c744 ¤   PGPError
48b539 PGPGetRootKeyServer(¤   PGPPrefRef¤ ¤   ¤   prefRef,
bab28c ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerEntry¤  *rootServer );
53af5a
78b916 /* Utility returns DNS name prefixed by protocol URL identifier */
01af5a
e86d52 ¤   void
df7359 PGPGetKeyServerURL(¤PGPKeyServerEntry¤  *keyserver,
a46980 ¤   ¤   ¤   ¤   ¤   char¤   ¤   ¤   ¤   *url );
32af5a
1e8c4a /* Little utility function to extract the domain from an email address */
dbaf5a
9a6d52 ¤   void
42ba2f PGPFindEmailDomain(const char *emailAddress, char *domain);
ebaf5a
08af5a
eeaf5a
e0cbcf #if PRAGMA_IMPORT_SUPPORTED
d02ced #pragma import reset
617454 #endif
8a1254 PGP_END_C_DECLARATIONS
09af5a
1eaf5a
40bb59 #endif /* ] Included_pgpKeyServerPrefs_h */
10af5a
cd7e4d /*__Editor_settings____
89af5a
794126 ¤   Local Variables:
727b17 ¤   tab-width: 4
ec0e6c ¤   End:
bc5f8c ¤   vi: ts=4 sw=4
359e9b ¤   vim: si
d47c50 _____________________*/¶
--2323 0004cb4409640100059 Page 1 of pgpPassBuffer.c
a70335 /*____________________________________________________________________________
ecedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
bb4b0f ¤   All rights reserved.
a0af5a
cb9a4c ¤   $Id: pgpPassBuffer.c,v 1.1.8.1 1998/11/12 03:11:09 heller Exp $
3ef7f7 ____________________________________________________________________________*/
66af5a
55324c #include <string.h>
04af5a
200d08 #include "pgpMem.h"
f8fb31 #include "pgpOptionList.h"
53ee51 #include "pgpPassBuffer.h"
b9af5a
f60868 #define¤kPGPPassBufferMagic¤¤   ¤   0x50427566L¤¤   /* 'PBuf' */
78f6ea #define¤PassBufferIsValid(buffer)¤  IsntPGPError( VerifyPassBuffer( buffer ) )
22af5a
eb3182 typedef struct PGPPassBuffer
49bb36 {
633fda ¤   PGPUInt32¤  ¤   ¤   magic;¤ ¤   ¤   /* Always kPGPPassBufferMagic */
71f7f4 ¤   PGPMemoryMgrRef¤¤   memoryMgr;
f5cf00 ¤   PGPSize¤¤   ¤   ¤   bufferSize;
a5af5a
038f14 ¤   PGPPassBufferType¤  type;
d567c5 ¤
9567b7 ¤   PGPByte¤¤   ¤   ¤   *data;
1ae3eb ¤   PGPSize¤¤   ¤   ¤   dataSize;
13af5a
997cda } PGPPassBuffer;
deaf5a
ef66dd ¤   static PGPError
b7a626 VerifyPassBuffer(const PGPPassBuffer *buffer)
64bb36 {
439fe3 ¤   if( IsNull( buffer ) || buffer->magic != kPGPPassBufferMagic )
e14023 ¤   ¤   return( kPGPError_BadParams );
791b52 ¤   ¤
972d68 ¤   return( kPGPError_NoErr );
e9efe6 }
f3af5a
c066dd ¤   static PGPError
ad78b1 SetData(
51e4c1 ¤   PGPPassBuffer ¤ ¤   *buffer,
a72db9 ¤   PGPPassBufferType¤  dataType,
7fb833 ¤   const void¤ ¤   ¤   *data,
1645ca ¤   PGPSize¤¤   ¤   ¤   dataSize)
8fbb36 {
478e12 ¤   PGPError¤   err = kPGPError_NoErr;
a267c5 ¤
f4447f ¤   buffer->type = dataType;
dd67c5 ¤
ac3dcf ¤   if( IsNull( buffer->data ) )
efc7a1 ¤   {
a2ce1d ¤   ¤   pgpAssert( buffer->bufferSize == 0 );
3cc9a3 ¤   ¤   pgpAssert( buffer->dataSize == 0 );
cb1b52 ¤   ¤
eabf57 ¤   ¤   buffer->data = (PGPByte *) PGPNewSecureData( buffer->memoryMgr,
787ab2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize, 0 );
c21f86 ¤   ¤   if( IsntNull( buffer->data ) )
055b34 ¤   ¤   {
e8267a ¤   ¤   ¤   buffer->bufferSize = dataSize;
e70fe4 ¤   ¤   }
700e1d ¤   ¤   else
445b34 ¤   ¤   {
e2b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
220fe4 ¤   ¤   }
519371 ¤   }
de0e24 ¤   else
88c7a1 ¤   {
fdb1e9 ¤   ¤   if( buffer->bufferSize < dataSize )
145b34 ¤   ¤   {
a8621b ¤   ¤   ¤   err = PGPReallocData( buffer->memoryMgr, &buffer->data,
313398 ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize, 0 );
4c698b ¤   ¤   ¤   if( IsntPGPError( err ) )
--3356 000f0cf791640100059 Page 2 of pgpPassBuffer.c
99f776 ¤   ¤   ¤   {
d9b7e2 ¤   ¤   ¤   ¤   buffer->bufferSize = dataSize;
13a3a6 ¤   ¤   ¤   }
6b0fe4 ¤   ¤   }
ac0e1d ¤   ¤   else
045b34 ¤   ¤   {
2a5a6a ¤   ¤   ¤   /* Clear old contents */
1d0796 ¤   ¤   ¤   pgpClearMemory( buffer->data, buffer->bufferSize );
530fe4 ¤   ¤   }
0f9371 ¤   }
f3af5a
adb1f0 ¤   if( IsntPGPError( err ) )
d4c7a1 ¤   {
ba404b ¤   ¤   buffer->dataSize = dataSize;
6da8a5 ¤   ¤   pgpCopyMemory( data, buffer->data, dataSize );
059371 ¤   }
95af5a
eb8c1a ¤   pgpAssertNoErr( err );
ed67c5 ¤
a1deb7 ¤   return( err );
a9efe6 }
09af5a
40c744 ¤   PGPError
c08c9e PGPNewPassBuffer(
542f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
699a3d ¤   PGPPassBufferRef ¤  *bufferPtr)
12bb36 {
e13bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
a0240d ¤   PGPPassBuffer¤  *buffer;
7167c5 ¤
7eebf4 ¤   PGPValidatePtr( bufferPtr );
747632 ¤   *bufferPtr = kInvalidPGPPassBufferRef;
14a127 ¤   PGPValidateParam( PGPMemoryMgrRefIsValid( memoryMgr ) );
f967c5 ¤
97ab7f ¤   buffer = (PGPPassBuffer *) PGPNewData( memoryMgr, sizeof( **bufferPtr ),
afa90e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
0444f6 ¤   if( IsntNull( buffer ) )
d8c7a1 ¤   {
334151 ¤   ¤   buffer->magic ¤ ¤   = kPGPPassBufferMagic;
b863c8 ¤   ¤   buffer->memoryMgr¤  = memoryMgr;
b59371 ¤   }
d20e24 ¤   else
2bc7a1 ¤   {
67bce1 ¤   ¤   err = kPGPError_OutOfMemory;
519371 ¤   }
1067c5 ¤
c0f17b ¤   *bufferPtr = buffer;
8b67c5 ¤
0ddeb7 ¤   return( err );
d5efe6 }
94af5a
fb6d52 ¤   void
bd3d6d PGPFreePassBuffer(PGPPassBufferRef buffer)
0abb36 {
eb9bda ¤   if( PassBufferIsValid( buffer ) )
71c7a1 ¤   {
731f86 ¤   ¤   if( IsntNull( buffer->data ) )
18ed2c ¤   ¤   ¤   PGPFreeData( buffer->data );
0387c7 ¤   ¤   ¤
2f4edd ¤   ¤   buffer->magic = 0;
6d1b52 ¤   ¤
f8f097 ¤   ¤   PGPFreeData( buffer );
6b9371 ¤   }
76efe6 }
34af5a
f8c744 ¤   PGPError
543ac7 PGPPassBufferSetPassphrase(
b2c4c1 ¤   PGPPassBufferRef ¤  buffer,
a6973a ¤   const char¤ ¤   ¤   *passphrase)
e7bb36 {
c1ddf7 ¤   PGPValidateParam( PassBufferIsValid( buffer ) );
f0bed6 ¤   PGPValidatePtr( passphrase );
--e601 0006008b67f40100059 Page 3 of pgpPassBuffer.c
e0af5a
108405 ¤   return( SetData( buffer, kPGPPassBufferType_Passphrase,
6e707a ¤   ¤   ¤   ¤   ¤   (PGPByte *) passphrase, strlen( passphrase ) + 1 ) );
b6af5a
5befe6 }
5faf5a
5dc744 ¤   PGPError
2aa41a PGPPassBufferSetPassKey(
ddc4c1 ¤   PGPPassBufferRef ¤  buffer,
0ca23d ¤   const PGPByte¤  ¤   *passKey,
70173e ¤   PGPSize¤¤   ¤   ¤   passKeySize)
d5bb36 {
35ddf7 ¤   PGPValidateParam( PassBufferIsValid( buffer ) );
b8c350 ¤   PGPValidatePtr( passKey );
dc8a7e ¤   PGPValidateParam( passKeySize != 0 );
f6af5a
9a1174 ¤   return( SetData( buffer, kPGPPassBufferType_PassKey, passKey,
a64bce ¤   ¤   ¤   ¤   ¤   ¤   ¤   passKeySize ) );
46efe6 }
61af5a
00c744 ¤   PGPError
4b01be PGPClearPassBuffer(PGPPassBufferRef buffer)
74bb36 {
eeddf7 ¤   PGPValidateParam( PassBufferIsValid( buffer ) );
2faf5a
a05e75 ¤   if( IsntNull( buffer->data ) )
58c7a1 ¤   {
63aa9f ¤   ¤   pgpClearMemory( buffer->data, buffer->dataSize );
ba26d1 ¤   ¤   buffer->dataSize = 0;
169371 ¤   }
3567c5 ¤
3714f9 ¤   buffer->type = kPGPPassBufferType_Invalid;
c0a4ab ¤   ·
f12d68 ¤   return( kPGPError_NoErr );
c6efe6 }
c3af5a
e7c744 ¤   PGPError
70292e PGPCopyPassBuffer(
55c4c1 ¤   PGPPassBufferRef ¤  buffer,
83404a ¤   PGPPassBufferRef¤   *bufferCopy)
c0bb36 {
4f3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
bd9428 ¤   PGPPassBuffer¤  *newBuffer;
e367c5 ¤
b6469d ¤   PGPValidatePtr( bufferCopy );
5d5e7e ¤   *bufferCopy = kInvalidPGPPassBufferRef;
51ddf7 ¤   PGPValidateParam( PassBufferIsValid( buffer ) );
ed67c5 ¤
17f629 ¤   err = PGPNewPassBuffer( buffer->memoryMgr, &newBuffer );
e3b1f0 ¤   if( IsntPGPError( err ) )
4cc7a1 ¤   {
4419ed ¤   ¤   *newBuffer ¤¤   = *buffer;
adf9c5 ¤   ¤   newBuffer->data = NULL;
7e1b52 ¤   ¤
5a1f86 ¤   ¤   if( IsntNull( buffer->data ) )
b15b34 ¤   ¤   {
dbd1c3 ¤   ¤   ¤   newBuffer->data = (PGPByte *) PGPNewSecureData( buffer->memoryMgr,
d6445f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer->dataSize, 0 );
13551d ¤   ¤   ¤   if( IsntNull( newBuffer->data ) )
a4f776 ¤   ¤   ¤   {
da1ce9 ¤   ¤   ¤   ¤   pgpCopyMemory( buffer->data, newBuffer->data,
9e7590 ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer->bufferSize );
6aa3a6 ¤   ¤   ¤   }
5fbb8c ¤   ¤   ¤   else
24f776 ¤   ¤   ¤   {
e881bc ¤   ¤   ¤   ¤   PGPFreePassBuffer( newBuffer );
92c551 ¤   ¤   ¤   ¤   newBuffer = kInvalidPGPPassBufferRef;
dea3a6 ¤   ¤   ¤   }
710fe4 ¤   ¤   }
b89371 ¤   }
0367c5 ¤
603621 ¤   *bufferCopy = newBuffer;
--e22b 000d3529dcd40100059 Page 4 of pgpPassBuffer.c
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
6813fb ¤   PGPOptionListRef
f9cecc PGPOPassBuffer(
e1a1bc ¤   PGPContextRef¤  ¤   context,
15dd81 ¤   PGPPassBufferRef¤   buffer)
0abb36 {
66ece0 ¤   PGPOptionListRef¤   optionList = kInvalidPGPOptionListRef;
7567c5 ¤
8f40d7 ¤   if( PassBufferIsValid( buffer ) && IsntNull( buffer->data ) )
80c7a1 ¤   {
dd4328 ¤   ¤   if( buffer->type == kPGPPassBufferType_Passphrase )
ec5b34 ¤   ¤   {
febc7a ¤   ¤   ¤   optionList = PGPOPassphrase( context, (char *) buffer->data );
ed0fe4 ¤   ¤   }
39eef0 ¤   ¤   else if( buffer->type == kPGPPassBufferType_PassKey )
fb5b34 ¤   ¤   {
64ed04 ¤   ¤   ¤   optionList = PGPOPasskeyBuffer( context, buffer->data,
1bdf83 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer->dataSize );
e20fe4 ¤   ¤   }
cd9371 ¤   }
0367c5 ¤
bc02fa ¤   if( ! PGPOptionListRefIsValid( optionList ) )
99c7a1 ¤   {
9e1b17 ¤   ¤   /*
ab1c28 ¤   ¤   ** The semantics for PGPO calls is to never return NULL.
366cf0 ¤   ¤   ** Since we do not have access to PGPO error generation functions,
086236 ¤   ¤   ** pass back PGPONullOption() instead.
6f5c12 ¤   ¤   */
4e1b52 ¤   ¤
29474b ¤   ¤   pgpDebugMsg( "PGPOPassBuffer(): Failed to create option list" );
891b52 ¤   ¤
3374ce ¤   ¤   optionList = PGPONullOption( context );
eb9371 ¤   }
9067c5 ¤
e68233 ¤   return( optionList );
2befe6 }
a4af5a
4f5fda ¤   PGPPassBufferType
a47859 PGPGetPassBufferType(PGPPassBufferRef buffer)
94bb36 {
ad8f14 ¤   PGPPassBufferType¤  type;
6e67c5 ¤
7a9bda ¤   if( PassBufferIsValid( buffer ) )
e0c7a1 ¤   {
ddfa37 ¤   ¤   type = buffer->type;
2f9371 ¤   }
8d0e24 ¤   else
5dc7a1 ¤   {
72b6d2 ¤   ¤   type = kPGPPassBufferType_Invalid;
1b9371 ¤   }
ee67c5 ¤
474be1 ¤   return( type );
6defe6 }
cfaf5a
b5c744 ¤   PGPError
460c70 PGPPassBufferGetPassphrasePtr(
cac4c1 ¤   PGPPassBufferRef ¤  buffer,
a79df0 ¤   char¤   ¤   ¤   ¤   **passphrasePtr)
a1bb36 {
a23c94 ¤   PGPValidatePtr( passphrasePtr );
baf691 ¤   *passphrasePtr = NULL;
bcddf7 ¤   PGPValidateParam( PassBufferIsValid( buffer ) );
31af5a
eacc7f ¤   if( buffer->type == kPGPPassBufferType_Passphrase )
b7c7a1 ¤   {
55c4f4 ¤   ¤   pgpAssert( IsntNull( buffer->data ) );
0b1b52 ¤   ¤
6dbd23 ¤   ¤   *passphrasePtr = (char *) buffer->data;
d39371 ¤   }
--9ff9 001c0bf22bc40100059 Page 5 of pgpPassBuffer.c
2a67c5 ¤
fe2d68 ¤   return( kPGPError_NoErr );
b2efe6 }
78af5a
39c744 ¤   PGPError
717830 PGPPassBufferGetPassKeyPtr(
c3c4c1 ¤   PGPPassBufferRef ¤  buffer,
22627e ¤   PGPByte¤¤   ¤   ¤   **passpKeyPtr,
9df5c9 ¤   PGPSize¤¤   ¤   ¤   *passKeySize)
4abb36 {
91a8bf ¤   if( IsntNull( passpKeyPtr ) )
97e4a7 ¤   ¤   *passpKeyPtr = NULL;
c831a7 ¤   if( IsntNull( passKeySize ) )
d294c9 ¤   ¤   *passKeySize = 0;
e7af5a
99ddf7 ¤   PGPValidateParam( PassBufferIsValid( buffer ) );
622c99 ¤   PGPValidatePtr( passpKeyPtr );
e5d5d4 ¤   PGPValidatePtr( passKeySize );
f9af5a
6d1b09 ¤   if( buffer->type == kPGPPassBufferType_PassKey )
0cc7a1 ¤   {
cac4f4 ¤   ¤   pgpAssert( IsntNull( buffer->data ) );
0a1b52 ¤   ¤
162e74 ¤   ¤   *passpKeyPtr¤   = buffer->data;
6bdd79 ¤   ¤   *passKeySize¤   = buffer->dataSize;
0f9371 ¤   }
df67c5 ¤
422d68 ¤   return( kPGPError_NoErr );
c0be43 }¶
--44ef 001e89ea6824010005a Page 1 of pgpPassBuffer.h
a70335 /*____________________________________________________________________________
ecedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
bb4b0f ¤   All rights reserved.
a0af5a
30ee80 ¤   $Id: pgpPassBuffer.h,v 1.1.8.1 1998/11/12 03:11:10 heller Exp $
21f7f7 ____________________________________________________________________________*/
daaf5a
e649d6 #ifndef Included_pgpPassBuffer_h¤   /* [ */
c6c45c #define Included_pgpPassBuffer_h
06af5a
2d6773 #include "pgpMemoryMgr.h"
b6e82c #include "pgpPubTypes.h"
a5af5a
88f779 typedef struct PGPPassBuffer¤   *PGPPassBufferRef;
c3af5a
89e1e0 #define¤kInvalidPGPPassBufferRef¤   ¤   ((PGPPassBufferRef) NULL)
fb0ac3 #define PGPPassBufferRefIsValid(ref)¤   ((ref) != kInvalidPGPPassBufferRef)
e3af5a
c1e635 enum PGPPassBufferType_
debb36 {
534fda ¤   kPGPPassBufferType_Invalid¤ ¤   ¤   = 0,
e362df ¤   kPGPPassBufferType_Passphrase¤  ¤   = 1,
51a3d8 ¤   kPGPPassBufferType_PassKey¤ ¤   ¤   = 2,
f367c5 ¤
dc2346 ¤   PGP_ENUM_FORCE( PGPPassBufferType_ )
952fa1 } ;
732a93 PGPENUM_TYPEDEF( PGPPassBufferType_, PGPPassBufferType );
32af5a
3699c6 PGP_BEGIN_C_DECLARATIONS
b2af5a
30cbcf #if PRAGMA_IMPORT_SUPPORTED
19b981 #pragma import on
b47454 #endif
b5af5a
9eca0b PGPError¤   ¤   ¤   PGPNewPassBuffer(PGPMemoryMgrRef memoryMgr,
bc4afc ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPassBufferRef *buffer);
43bd45 void¤   ¤   ¤   ¤   PGPFreePassBuffer(PGPPassBufferRef buffer);
799e81 PGPError¤   ¤   ¤   PGPCopyPassBuffer(PGPPassBufferRef buffer,
af1004 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPassBufferRef *bufferCopy);
9e67c5 ¤
651d1c PGPError¤   ¤   ¤   PGPPassBufferSetPassphrase(PGPPassBufferRef buffer,
1a891b ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char *passphrase);
4e9ade PGPError¤   ¤   ¤   PGPPassBufferSetPassKey(PGPPassBufferRef buffer,
22a766 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte *passKey, PGPSize passKeySize);
b46484 PGPError¤   ¤   ¤   PGPClearPassBuffer(PGPPassBufferRef buffer);
c3af5a
c6d9a6 PGPError¤   ¤   ¤   PGPPassBufferGetPassphrasePtr(PGPPassBufferRef buffer,
c27b6d ¤   ¤   ¤   ¤   ¤   ¤   ¤   char **passphrasePtr);
5eeab5 PGPError¤   ¤   ¤   PGPPassBufferGetPassKeyPtr(PGPPassBufferRef buffer,
bb7dd3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **passpKeyPtr, PGPSize *passKeySize);
d167c5 ¤
6c72e5 PGPOptionListRef¤   PGPOPassBuffer(PGPContextRef context,
4e5e98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPassBufferRef buffer);
25323a PGPPassBufferType¤  PGPGetPassBufferType(PGPPassBufferRef buffer);
d894aa ¤   ¤   ¤   ¤   ¤   ¤
bccbcf #if PRAGMA_IMPORT_SUPPORTED
852ced #pragma import reset
6e7454 #endif
d7af5a
311254 PGP_END_C_DECLARATIONS
09af5a
f2d62d #endif /* ] Included_pgpPassBuffer_h */
c0af5a
81af5a
db7e4d /*__Editor_settings____
5baf5a
6d4126 ¤   Local Variables:
607b17 ¤   tab-width: 4
670e6c ¤   End:
c25f8c ¤   vi: ts=4 sw=4
889e9b ¤   vim: si
e8d062 _____________________*/
--b176 00089346e294010005b Page 1 of pgpSKEP.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
36038c ¤   $Id: pgpSKEP.c,v 1.39.8.1 1998/11/12 03:11:11 heller Exp $
80f7f7 ____________________________________________________________________________*/
aab869 #include "pgpSKEP.h"
cd955c #include "pgpSharePriv.h"
a65519 #include "pgpSockets.h"
46ec82 #include "pgpTLS.h"
9e0d08 #include "pgpMem.h"
b46773 #include "pgpMemoryMgr.h"
4c9f63 #include "pgpEncode.h"
414919 #include "pgpUtilities.h"
8f3d4b #include "pgpEndianConversion.h"
35628e #include "pgpClientErrors.h"
68af5a
b3afb9 #if PGP_WIN32
67a21a #include "pgpAsyncDNS.h"
2f7454 #endif
1daf5a
ff41ed typedef struct PGPskep¤ ¤   PGPskep;
7aaf5a
3012e1 #define kPGPskepMagic¤  0x156A3C91
09af5a
b7f44c struct PGPskep
85bb36 {
15fe45 ¤   PGPUInt32¤  ¤   ¤   ¤   magic;
b5429f ¤   PGPContextRef¤  ¤   ¤   context;
9889ec ¤   PGPtlsContextRef¤   ¤   tlsContext;
9037c6 ¤   PGPSocketRef¤   ¤   ¤   socketOut;
7a7751 ¤   PGPSocketRef¤   ¤   ¤   socketIn;
5e7038 ¤   PGPskepEventHandler¤¤   eventHandler;
ce7b2d ¤   PGPUserValue¤   ¤   ¤   userValue;
992584 ¤   PGPBoolean¤ ¤   ¤   ¤   cancel;
39496a ¤   PGPBoolean¤ ¤   ¤   ¤   freeTLSContext;
27afb9 #if PGP_WIN32
2a9033 ¤   PGPAsyncHostEntryRef¤   asyncHostEntryRef;
167454 #endif
2382f7 };
00af5a
710121 #define PGPValidateSKEP(ref)¤   PGPValidateParam(ref != NULL)
6baf5a
5edb84 #define kPGPskep_Port¤  ¤   ¤   ¤   14747
602a80 #define kPGPskep_ClosingMessage¤¤   0x155901C5
f69059 #define kPGPskepEndian¤ ¤   ¤   ¤   kPGPBigEndian
1baf5a
f60d28 #define kPGPskepMajor¤  0x01¤   /* SKEP major version */
24272c #define kPGPskepMinor¤  0x01¤   /* SKEP minor version */
cfaf5a
d1af5a
54f067 static PGPError sSocketSend(PGPskepRef skep, PGPSocketRef socket,·
169df9 ¤   ¤   ¤   ¤   ¤   void *data, PGPInt32 dataSize, PGPBoolean crossPlatform,
8fac61 ¤   ¤   ¤   ¤   ¤   PGPskepEventProgressData *progressData);
3daf5a
025b82 static PGPError sSocketReceive(PGPskepRef skep, PGPSocketRef socket,·
949df9 ¤   ¤   ¤   ¤   ¤   void *data, PGPInt32 dataSize, PGPBoolean crossPlatform,
b3ac61 ¤   ¤   ¤   ¤   ¤   PGPskepEventProgressData *progressData);
a0af5a
d079ec static PGPError sProcessResult(PGPskepRef skep, PGPInt32 result,
d0ac61 ¤   ¤   ¤   ¤   ¤   PGPskepEventProgressData *progressData);
83af5a
fa7f6d static PGPError sSocketCallback(PGPContextRef context,·
4db4b7 ¤   ¤   ¤   ¤   ¤   struct PGPEvent *event, PGPUserValue userValue);
5aaf5a
5aaf5a
675b4e PGPError PGPNewSKEP(PGPContextRef context,·
e25f64 ¤   ¤   ¤   ¤   PGPtlsContextRef tlsContext,
fd6503 ¤   ¤   ¤   ¤   PGPskepRef *skep)
89bb36 {
--6762 00056f4fe4c4010005b Page 2 of pgpSKEP.c
f03281 ¤   PGPMemoryMgrRef memoryMgr = NULL;
773bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
99af5a
edafff ¤   if (IsntNull(skep))
8c0458 ¤   ¤   *skep = NULL;
35af5a
014ecd ¤   PGPValidateParam(PGPContextRefIsValid(context));
8e7bfa ¤   PGPValidatePtr(skep);
8baf5a
49cc3d ¤   memoryMgr = PGPGetContextMemoryMgr(context);
d767c5 ¤
4dae4e ¤   pgpAssert(PGPMemoryMgrIsValid(memoryMgr));
bcdbbb ¤   if (!PGPMemoryMgrIsValid(memoryMgr))
7b62b5 ¤   ¤   return kPGPError_BadParams;
adaf5a
e5b980 ¤   *skep = (PGPskepRef) PGPNewData(memoryMgr, sizeof(PGPskep),·
a3e7fa ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
44af5a
8b3ccc ¤   pgpAssert(IsntNull(*skep));
194d48 ¤   if (IsNull(*skep))
a74030 ¤   ¤   return kPGPError_OutOfMemory;
d0af5a
9bdd3f ¤   if (PGPtlsContextRefIsValid(tlsContext))
efc7a1 ¤   {
fc1f89 ¤   ¤   (*skep)->tlsContext = tlsContext;
a91c41 ¤   ¤   (*skep)->freeTLSContext = FALSE;
7b9371 ¤   }
310e24 ¤   else
99c7a1 ¤   {
ec62ad ¤   ¤   PGPNewTLSContext(context, &((*skep)->tlsContext));
4660ec ¤   ¤   (*skep)->freeTLSContext = TRUE;
959371 ¤   }
08af5a
ac4af0 ¤   (*skep)->magic = kPGPskepMagic;
f30d68 ¤   (*skep)->context = context;
726060 ¤   (*skep)->socketOut = NULL;
5bf2b6 ¤   (*skep)->socketIn = NULL;
83e201 ¤   (*skep)->eventHandler = NULL;
adc6ee ¤   (*skep)->userValue = NULL;
2e14a1 ¤   (*skep)->cancel = FALSE;
c0af5a
7f5ea8 ¤   return err;
9eefe6 }
e1af5a
b4af5a
862919 PGPError PGPskepSetEventHandler(PGPskepRef skep, PGPskepEventHandler handler,
c8bab1 ¤   ¤   ¤   ¤   PGPUserValue userValue)
f7bb36 {
6d3edb ¤   PGPValidateSKEP(skep);
3b62b7 ¤   PGPValidatePtr(handler);
33dc0a ¤   pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
acaf5a
084036 ¤   skep->eventHandler = handler;
4b6f87 ¤   skep->userValue = userValue;
e2151e ¤   return kPGPError_NoErr;
94efe6 }
d6af5a
39af5a
0ed57f PGPError PGPskepSendShares(PGPskepRef skep, PGPKeyRef authKey,
6cb76a ¤   ¤   ¤   ¤   const char *passphrase, PGPShareRef shares,
d3185e ¤   ¤   ¤   ¤   const char *destSocketAddress)
16bb36 {
39c837 ¤   PGPSocketRef¤   ¤   ¤   ¤   socket = NULL;
13b950 ¤   PGPtlsSessionRef¤   ¤   ¤   tlsSession = NULL;
e1405e ¤   PGPEventHandlerProcPtr¤ ¤   oldCallback = NULL;
2684be ¤   PGPUserValue¤   ¤   ¤   ¤   oldUserValue;
fff8c0 ¤   PGPSocketAddressInternet¤   sockAddr;
53e2c2 ¤   PGPHostEntry *¤ ¤   ¤   ¤   hostEntry = NULL;
8933f7 ¤   PGPskepEvent¤   ¤   ¤   ¤   skepEvent;
179aaa ¤   PGPskepEventProgressData¤   progressData = {0,0};
af64ab ¤   PGPInt32¤   ¤   ¤   ¤   ¤   result;
56d749 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   remoteKey = NULL;
--877c 00090a8527f4010005b Page 3 of pgpSKEP.c
d06995 ¤   PGPKeyID¤   ¤   ¤   ¤   ¤   keyID;
0a2be2 ¤   PGPShareID¤ ¤   ¤   ¤   ¤   shareID;
40237a ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   inetAddress;
de729e ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   threshold;
bb74e9 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numShares;
49d02e ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   totalShares;
c54269 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   closing;
227745 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   shareDataSize;
5b2f5f ¤   PGPByte *¤  ¤   ¤   ¤   ¤   shareData = NULL;
0fe986 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   version;
2da496 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   weConfirmed;
75e939 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   theyConfirmed;
953146 ¤   PGPError¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
c6962d ¤   PGPSocketsThreadStorageRef¤ previousStorage;
13afb9 #if PGP_WIN32
081b93 ¤   char¤   ¤   ¤   ¤   ¤   ¤   h_name[256];
cd7454 #endif
d2af5a
b93edb ¤   PGPValidateSKEP(skep);
942b29 ¤   PGPValidateParam(PGPKeyRefIsValid(authKey));
f60313 ¤   PGPValidatePtr(passphrase);
2ab93e ¤   PGPValidateParam(PGPShareRefIsValid(shares));
910539 ¤   PGPValidatePtr(destSocketAddress);
25dc0a ¤   pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
a3af5a
71bc47 ¤   skep->cancel = FALSE;
15af5a
5a21fa ¤   PGPSocketsInit();
163d55 ¤   PGPSocketsCreateThreadStorage(&previousStorage);
131b1e ¤   if (IsntNull(skep->eventHandler))
dac7a1 ¤   {
76ca4e ¤   ¤   PGPGetSocketsIdleEventHandler(&oldCallback, &oldUserValue);
bcda68 ¤   ¤   PGPSetSocketsIdleEventHandler(sSocketCallback, skep);
f89371 ¤   }
cdaf5a
8562f2 ¤   inetAddress = PGPDottedToInternetAddress(destSocketAddress);
feffac ¤   if (inetAddress != kPGPSockets_Error)
91c7a1 ¤   {
0fafb9 #if PGP_WIN32
560a02 ¤   ¤   err = PGPStartAsyncGetHostByAddress(inetAddress,
bff539 ¤   ¤   ¤   ¤   ¤   &skep->asyncHostEntryRef);
131f6d ¤   ¤   if (IsntPGPError(err)) {
ef54e1 ¤   ¤   ¤   PGPWaitForGetHostByAddress(skep->asyncHostEntryRef,
891521 ¤   ¤   ¤   ¤   ¤   h_name, 256);
37924b ¤   ¤   ¤   skep->asyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
e10fe4 ¤   ¤   }
65db21 #else
6b2b6e ¤   ¤   hostEntry = PGPGetHostByAddress((char *) &inetAddress,·
718b68 ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPInternetAddress),·
72b526 ¤   ¤   ¤   ¤   ¤   ¤   kPGPProtocolFamilyInternet);
847454 #endif
b69371 ¤   }
650e24 ¤   else
fac7a1 ¤   {
4eafb9 #if PGP_WIN32
bf5dcc ¤   ¤   err = PGPStartAsyncGetHostByName(destSocketAddress,
91f539 ¤   ¤   ¤   ¤   ¤   &skep->asyncHostEntryRef);
0e1f6d ¤   ¤   if (IsntPGPError(err)) {
8517f7 ¤   ¤   ¤   PGPWaitForGetHostByName(skep->asyncHostEntryRef,
d70db5 ¤   ¤   ¤   ¤   ¤   &inetAddress);
c0924b ¤   ¤   ¤   skep->asyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
b2b346 ¤   ¤   ¤   strcpy(h_name, destSocketAddress);
710fe4 ¤   ¤   }
d4db21 #else
9a5b72 ¤   ¤   hostEntry = PGPGetHostByName(destSocketAddress);
347454 #endif
e29371 ¤   }
901b52 ¤   ¤
f3a9fa ¤   if (IsntPGPError(err) && IsNull(hostEntry))
ebd4f8 ¤   ¤   if (inetAddress == kPGPSockets_Error)
17b56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
90af5a
--6d87 0009a77b1474010005b Page 4 of pgpSKEP.c
f0f69b ¤   if (IsntPGPError(err))
dac7a1 ¤   {
355f8e ¤   ¤   socket = PGPOpenSocket(kPGPAddressFamilyInternet,·
671f15 ¤   ¤   ¤   ¤   ¤   kPGPSocketTypeStream, kPGPTCPProtocol);
091b52 ¤   ¤
f1fe7c ¤   ¤   if (IsNull(socket))
225b34 ¤   ¤   {
fab56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
71524f ¤   ¤   ¤   pgpAssertNoErr(err);
490fe4 ¤   ¤   }
2c9371 ¤   }
25af5a
48f69b ¤   if (IsntPGPError(err))
e8c7a1 ¤   {
449175 ¤   ¤   skep->socketOut = socket;
3ee5a5 ¤   ¤   sockAddr.sin_family = kPGPAddressFamilyInternet;
73a7fa ¤   ¤   sockAddr.sin_port = PGPHostToNetShort(kPGPskep_Port);
c1af5a
188ce1 ¤   ¤   /* If we were able to get the host entry, use the IP address list */
0b6543 ¤   ¤   /* from that. If not, use the IP address passed in by the caller ·*/
99af5a
dcedf5 ¤   ¤   if (IsntNull(hostEntry))
e9c123 ¤   ¤   ¤   sockAddr.sin_addr = *((PGPInternetAddress*)·
36fc6f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *hostEntry->h_addr_list);
6b0e1d ¤   ¤   else
1dde6e ¤   ¤   ¤   sockAddr.sin_addr = *((PGPInternetAddress*) &inetAddress);
bdaf5a
65488c ¤   ¤   result = PGPConnect(socket, (PGPSocketAddress *) &sockAddr,·
cf4470 ¤   ¤   ¤   ¤   ¤   sizeof(sockAddr));
dbaf5a
b1d28b ¤   ¤   if (result == kPGPSockets_Error)
52b56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
4c0e1d ¤   ¤   else
335b34 ¤   ¤   {
67abc5 ¤   ¤   ¤   skepEvent.type = kPGPskepEvent_ConnectEvent;
034224 ¤   ¤   ¤   if (skep->eventHandler != NULL)
8912c8 ¤   ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
6380ae ¤   ¤   ¤   ¤   ¤   ¤   skep->userValue);
150fe4 ¤   ¤   }
569371 ¤   }
66af5a
daf69b ¤   if (IsntPGPError(err))
57c7a1 ¤   {
7f45bf ¤   ¤   err = PGPNewTLSSession(skep->tlsContext, &tlsSession);
29e919 ¤   ¤   pgpAssertNoErr(err);
959371 ¤   }
9baf5a
1cf69b ¤   if (IsntPGPError(err))
79c7a1 ¤   {
6ed0c6 ¤   ¤   err = PGPtlsSetProtocolOptions(tlsSession, kPGPtlsFlags_ClientSide);
49e919 ¤   ¤   pgpAssertNoErr(err);
fd9371 ¤   }
c2af5a
60f69b ¤   if (IsntPGPError(err))
47c7a1 ¤   {
675e58 ¤   ¤   err = PGPtlsSetLocalPrivateKey(tlsSession, authKey,
c4e8a4 ¤   ¤   ¤   ¤   ¤   PGPOPassphrase( skep->context, passphrase ),
d0977a ¤   ¤   ¤   ¤   ¤   PGPOLastOption( skep->context ) );
54e919 ¤   ¤   pgpAssertNoErr(err);
6e9371 ¤   }
90af5a
2df69b ¤   if (IsntPGPError(err))
e3c7a1 ¤   {
1dfd23 ¤   ¤   err = PGPSocketsEstablishTLSSession(socket, tlsSession);
cdb6ad ¤   ¤   if (IsPGPError(err))
62b56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
74af5a
a0eba7 ¤   ¤   if (skep->cancel == TRUE)
604e2b ¤   ¤   ¤   err = kPGPError_UserAbort;
72af5a
ebe919 ¤   ¤   pgpAssertNoErr(err);
9a9371 ¤   }
--0758 00038f264874010005b Page 5 of pgpSKEP.c
e0af5a
fef69b ¤   if (IsntPGPError(err))
6cc7a1 ¤   {
9824bc ¤   ¤   err = PGPtlsGetRemoteAuthenticatedKey(tlsSession, &remoteKey);
3eaf5a
4feba7 ¤   ¤   if (skep->cancel == TRUE)
914e2b ¤   ¤   ¤   err = kPGPError_UserAbort;
40af5a
5de919 ¤   ¤   pgpAssertNoErr(err);
819371 ¤   }
5daf5a
1ef69b ¤   if (IsntPGPError(err))
34c7a1 ¤   {
87ab77 ¤   ¤   /* If we don't have the host name, set it to the IP address */
aeaf5a
c9edf5 ¤   ¤   if (IsntNull(hostEntry))
f9afb9 #if PGP_WIN32
569ff5 ¤   ¤   ¤   skepEvent.data.ad.remoteHostname = h_name;
b6db21 #else
42fcd2 ¤   ¤   ¤   skepEvent.data.ad.remoteHostname = hostEntry->h_name;
807454 #endif
930e1d ¤   ¤   else
803f95 ¤   ¤   ¤   skepEvent.data.ad.remoteHostname =·
0c8d5a ¤   ¤   ¤   ¤   PGPInternetAddressToDottedString(sockAddr.sin_addr);
50af5a
ba2717 ¤   ¤   skepEvent.type = kPGPskepEvent_AuthenticateEvent;
f5f329 ¤   ¤   skepEvent.data.ad.remoteKey = remoteKey;
4303ec ¤   ¤   skepEvent.data.ad.remoteIPAddress =·
cd071f ¤   ¤   ¤   PGPInternetAddressToDottedString(sockAddr.sin_addr);
c042d4 ¤   ¤   PGPtlsGetNegotiatedCipherSuite( tlsSession,
f20a20 ¤   ¤   ¤   &skepEvent.data.ad.tlsCipher );
1f1b52 ¤   ¤
0eca42 ¤   ¤   if (skep->eventHandler != NULL)
209d9f ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
40bc40 ¤   ¤   ¤   ¤   ¤   skep->userValue);
64af5a
a8e2b3 ¤   ¤   if (IsntPGPError(err))
931327 ¤   ¤   ¤   weConfirmed = TRUE;
c50e1d ¤   ¤   else
eb64ed ¤   ¤   ¤   weConfirmed = FALSE;
5faf5a
7270bb ¤   ¤   err = kPGPError_NoErr;
0b9371 ¤   }
3daf5a
6cf69b ¤   if (IsntPGPError(err))
20c7a1 ¤   {
373cbd ¤   ¤   pgpGetShareData(shares, &shareData, &shareDataSize);
6caf5a
95cb45 ¤   ¤   progressData.bytesTotal = sizeof(shareDataSize) + shareDataSize +·
1de683 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPKeyID) + sizeof(PGPShareID) +
e60991 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(threshold) + sizeof(numShares) +·
a577cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(totalShares) + 4;
a0af5a
b56b1a ¤   ¤   version = kPGPskepMajor;
06f504 ¤   ¤   err = sSocketSend(skep, socket, &version, 1, FALSE, &progressData);
4c9371 ¤   }
840e24 ¤   else
b20d20 ¤   ¤   remoteKey = NULL;
90af5a
c1f69b ¤   if (IsntPGPError(err))
b1c7a1 ¤   {
666752 ¤   ¤   version = kPGPskepMinor;
7df504 ¤   ¤   err = sSocketSend(skep, socket, &version, 1, FALSE, &progressData);
429371 ¤   }
35af5a
e5f69b ¤   if (IsntPGPError(err))
2bc7a1 ¤   {
7ab99d ¤   ¤   err = sSocketSend(skep, socket, &weConfirmed, 1, FALSE,·
f53ffe ¤   ¤   ¤   ¤   &progressData);
819371 ¤   }
c5af5a
38f69b ¤   if (IsntPGPError(err))
--df32 000ec8103ae4010005b Page 6 of pgpSKEP.c
f7c7a1 ¤   {
b90e32 ¤   ¤   err = sSocketReceive(skep, socket, &theyConfirmed, 1, FALSE,·
283ffe ¤   ¤   ¤   ¤   &progressData);
53af5a
4a202f ¤   ¤   if (!theyConfirmed)
9bb839 ¤   ¤   ¤   err = kPGPClientError_RejectedSKEPAuthentication;
a5af5a
9133d4 ¤   ¤   if (!weConfirmed)
124e2b ¤   ¤   ¤   err = kPGPError_UserAbort;
c59371 ¤   }
30af5a
42f69b ¤   if (IsntPGPError(err))
fa04bc ¤   ¤   err = sSocketSend(skep, socket, &shareDataSize,·
f98f9f ¤   ¤   ¤   ¤   sizeof(shareDataSize), TRUE, &progressData);
23af5a
b3f69b ¤   if (IsntPGPError(err))
8ec7a1 ¤   {
fb037a ¤   ¤   PGPGetKeyIDFromShares(shares, &keyID);
7eea26 ¤   ¤   err = sSocketSend(skep, socket, &keyID, sizeof(PGPKeyID),·
05db9c ¤   ¤   ¤   ¤   FALSE, &progressData);
c89371 ¤   }
e8af5a
caf69b ¤   if (IsntPGPError(err))
7fc7a1 ¤   {
e10cf6 ¤   ¤   PGPGetShareID(shares, &shareID);
3505cc ¤   ¤   err = sSocketSend(skep, socket, &shareID, sizeof(PGPShareID),·
34db9c ¤   ¤   ¤   ¤   FALSE, &progressData);
2a9371 ¤   }
2faf5a
bbf69b ¤   if (IsntPGPError(err))
6ec7a1 ¤   {
edb549 ¤   ¤   threshold = PGPGetShareThreshold(shares);
5f92e7 ¤   ¤   err = sSocketSend(skep, socket, &threshold, sizeof(threshold),·
c456d8 ¤   ¤   ¤   ¤   TRUE, &progressData);
119371 ¤   }
dbaf5a
39f69b ¤   if (IsntPGPError(err))
e4c7a1 ¤   {
11f12a ¤   ¤   numShares = PGPGetNumberOfShares(shares);
75fd18 ¤   ¤   err = sSocketSend(skep, socket, &numShares, sizeof(numShares),·
3c56d8 ¤   ¤   ¤   ¤   TRUE, &progressData);
779371 ¤   }
7eaf5a
f2f69b ¤   if (IsntPGPError(err))
b3c7a1 ¤   {
50e830 ¤   ¤   totalShares = PGPGetTotalNumberOfShares(shares);
4bc0a8 ¤   ¤   err = sSocketSend(skep, socket, &totalShares, sizeof(totalShares),·
0256d8 ¤   ¤   ¤   ¤   TRUE, &progressData);
169371 ¤   }
c5af5a
fbf69b ¤   if (IsntPGPError(err))
8ac7a1 ¤   {
d7654e ¤   ¤   err = sSocketSend(skep, socket, shareData,·
291488 ¤   ¤   ¤   ¤   shareDataSize, FALSE, &progressData);
059371 ¤   }
93af5a
6df69b ¤   if (IsntPGPError(err))
f5c7a1 ¤   {
f033db ¤   ¤   skepEvent.type = kPGPskepEvent_CloseEvent;
48ca42 ¤   ¤   if (skep->eventHandler != NULL)
119d9f ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
56bc40 ¤   ¤   ¤   ¤   ¤   skep->userValue);
509371 ¤   }
3caf5a
62f69b ¤   if (IsntPGPError(err))
5fc7a1 ¤   {
4b0a3b ¤   ¤   progressData.bytesTotal = 0;
e6f5bb ¤   ¤   err = sSocketReceive(skep, socket, &closing, sizeof(closing), TRUE,
093ffe ¤   ¤   ¤   ¤   &progressData);
ef9371 ¤   }
68af5a
ecf69b ¤   if (IsntPGPError(err))
--6856 0008471364c4010005b Page 7 of pgpSKEP.c
f7c7a1 ¤   {
7044e8 ¤   ¤   if (closing != kPGPskep_ClosingMessage)
8a5b34 ¤   ¤   {
367ce1 ¤   ¤   ¤   err = kPGPError_CorruptData;
9c524f ¤   ¤   ¤   pgpAssertNoErr(err);
330fe4 ¤   ¤   }
7e9371 ¤   }
13af5a
7f376e ¤   if (IsntNull(shareData))
fb33fc ¤   ¤   PGPFreeData(shareData);
5daf5a
5acf3b ¤   if (IsntNull(tlsSession))
74c7a1 ¤   {
5e8672 ¤   ¤   if (IsntNull(remoteKey))
d2ae80 ¤   ¤   ¤   PGPtlsClose(tlsSession, FALSE);
9a0e1d ¤   ¤   else
165574 ¤   ¤   ¤   PGPtlsClose(tlsSession, TRUE);
bc43d9 ¤   ¤   PGPFreeTLSSession(tlsSession);
149371 ¤   }
01af5a
d7dc1e ¤   if (IsntNull(socket))
07c7a1 ¤   {
2d1891 ¤   ¤   PGPCloseSocket(socket);
fe5935 ¤   ¤   skep->socketOut = NULL;
379371 ¤   }
43af5a
6e1b1e ¤   if (IsntNull(skep->eventHandler))
dc5bb3 ¤   ¤   PGPSetSocketsIdleEventHandler(oldCallback, oldUserValue);
dcaf5a
15ea41 ¤   PGPSocketsDisposeThreadStorage(previousStorage);
a1ba95 ¤   PGPSocketsCleanup();
a1af5a
9fdcaf ¤   if (skep->cancel == TRUE)
0f0fd8 ¤   ¤   err = kPGPError_UserAbort;
40af5a
9f5ea8 ¤   return err;
21efe6 }
1faf5a
55af5a
303917 PGPError PGPskepReceiveShares(PGPskepRef skep, PGPKeyRef authKey,
eb5d2a ¤   ¤   ¤   ¤   const char *passphrase)
a0bb36 {
8c29e1 ¤   PGPShareRef¤¤   ¤   ¤   ¤   shares;
9bc837 ¤   PGPSocketRef¤   ¤   ¤   ¤   socket = NULL;
49a97a ¤   PGPSocketRef¤   ¤   ¤   ¤   socketIn;
b4c215 ¤   PGPtlsSessionRef¤   ¤   ¤   tlsSession;
cd405e ¤   PGPEventHandlerProcPtr¤ ¤   oldCallback = NULL;
d984be ¤   PGPUserValue¤   ¤   ¤   ¤   oldUserValue;
e3f8c0 ¤   PGPSocketAddressInternet¤   sockAddr;
8233f7 ¤   PGPskepEvent¤   ¤   ¤   ¤   skepEvent;
32e242 ¤   PGPskepEventProgressData¤   progressData;
bc64ab ¤   PGPInt32¤   ¤   ¤   ¤   ¤   result;
fe240c ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   remoteKey;
946995 ¤   PGPKeyID¤   ¤   ¤   ¤   ¤   keyID;
ba2be2 ¤   PGPShareID¤ ¤   ¤   ¤   ¤   shareID;
79729e ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   threshold;
2d74e9 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numShares;
61d02e ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   totalShares;
2dddf2 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   closing = kPGPskep_ClosingMessage;
bfb710 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   shareDataSize;
fd3d0d ¤   PGPByte *¤  ¤   ¤   ¤   ¤   shareData;
cce986 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   version;
caa496 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   weConfirmed;
cde939 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   theyConfirmed;
1ee25a ¤   PGPHostEntry *¤ ¤   ¤   ¤   hostEntry;
aa3146 ¤   PGPError¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
52962d ¤   PGPSocketsThreadStorageRef¤ previousStorage;
0bafb9 #if PGP_WIN32
031b93 ¤   char¤   ¤   ¤   ¤   ¤   ¤   h_name[256];
577454 #endif
38af5a
843edb ¤   PGPValidateSKEP(skep);
--8c38 000eff36fce4010005b Page 8 of pgpSKEP.c
e72b29 ¤   PGPValidateParam(PGPKeyRefIsValid(authKey));
f20313 ¤   PGPValidatePtr(passphrase);
96dc0a ¤   pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
0aaf5a
e1bc47 ¤   skep->cancel = FALSE;
10af5a
6321fa ¤   PGPSocketsInit();
843d55 ¤   PGPSocketsCreateThreadStorage(&previousStorage);
09af5a
a91b1e ¤   if (IsntNull(skep->eventHandler))
4ec7a1 ¤   {
c7ca4e ¤   ¤   PGPGetSocketsIdleEventHandler(&oldCallback, &oldUserValue);
4dda68 ¤   ¤   PGPSetSocketsIdleEventHandler(sSocketCallback, skep);
069371 ¤   }
d5af5a
4558b5 ¤   socket = PGPOpenSocket(kPGPAddressFamilyInternet,·
a79042 ¤   ¤   ¤   ¤   kPGPSocketTypeStream, kPGPTCPProtocol);
3daf5a
9c0819 ¤   if (IsNull(socket))
d2c7a1 ¤   {
153d0a ¤   ¤   err = PGPGetLastSocketsError();
56e919 ¤   ¤   pgpAssertNoErr(err);
1b9371 ¤   }
56af5a
5ef69b ¤   if (IsntPGPError(err))
b0c7a1 ¤   {
e39175 ¤   ¤   skep->socketOut = socket;
d3e5a5 ¤   ¤   sockAddr.sin_family = kPGPAddressFamilyInternet;
bea7fa ¤   ¤   sockAddr.sin_port = PGPHostToNetShort(kPGPskep_Port);
5f254e ¤   ¤   sockAddr.sin_addr.s_addr = kPGPInternetAddressAny;
88af5a
76d069 ¤   ¤   result = PGPBindSocket(socket, (PGPSocketAddress *) &sockAddr,·
314470 ¤   ¤   ¤   ¤   ¤   sizeof(sockAddr));
09af5a
17d28b ¤   ¤   if (result == kPGPSockets_Error)
795b34 ¤   ¤   {
42b56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
d7524f ¤   ¤   ¤   pgpAssertNoErr(err);
ab0fe4 ¤   ¤   }
ca9371 ¤   }
42af5a
bdf69b ¤   if (IsntPGPError(err))
63c7a1 ¤   {
4f65f8 ¤   ¤   result = PGPListen(socket, 4);
dfd28b ¤   ¤   if (result == kPGPSockets_Error)
d85b34 ¤   ¤   {
80b56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
bc1b52 ¤   ¤
b304d4 ¤   ¤   ¤   if (skep->cancel == TRUE)
994067 ¤   ¤   ¤   ¤   err = kPGPError_UserAbort;
f5af5a
2a524f ¤   ¤   ¤   pgpAssertNoErr(err);
880fe4 ¤   ¤   }
7f9371 ¤   }
f8af5a
81c8b0 ¤   while (IsntPGPError(err))
e8c7a1 ¤   {
65c4c1 ¤   ¤   socketIn = NULL;
f333f9 ¤   ¤   tlsSession = NULL;
ea0a62 ¤   ¤   progressData.bytesSoFar = 0;
8f0a3b ¤   ¤   progressData.bytesTotal = 0;
230d20 ¤   ¤   remoteKey = NULL;
946a57 ¤   ¤   shareData = NULL;
f9f20c ¤   ¤   hostEntry = NULL;
70cff5 ¤   ¤   shares = NULL;
49be79 ¤   ¤   weConfirmed = TRUE;
56ee52 ¤   ¤   theyConfirmed = TRUE;
4d1b52 ¤   ¤
c1bf2d ¤   ¤   skepEvent.type = kPGPskepEvent_ListenEvent;
94ca42 ¤   ¤   if (skep->eventHandler != NULL)
579d9f ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
efbc40 ¤   ¤   ¤   ¤   ¤   skep->userValue);
--da8f 000c795d9e14010005b Page 9 of pgpSKEP.c
d99561 ¤   ¤   result = sizeof(sockAddr);
1763a7 ¤   ¤   socketIn = PGPAccept(socket, (PGPSocketAddress *) &sockAddr,·
71eb4c ¤   ¤   ¤   ¤   ¤   ¤   &result);
01af5a
3e86cd ¤   ¤   if (IsNull(socketIn) || ((int) socketIn == kPGPSockets_Error))
d75b34 ¤   ¤   {
98b56c ¤   ¤   ¤   err = PGPGetLastSocketsError();
a31b52 ¤   ¤
0104d4 ¤   ¤   ¤   if (skep->cancel == TRUE)
674067 ¤   ¤   ¤   ¤   err = kPGPError_UserAbort;
7daf5a
9b524f ¤   ¤   ¤   pgpAssertNoErr(err);
a40fe4 ¤   ¤   }
4eaf5a
60e2b3 ¤   ¤   if (IsntPGPError(err))
575b34 ¤   ¤   {
c647f6 ¤   ¤   ¤   skep->socketIn = socketIn;
b5abc5 ¤   ¤   ¤   skepEvent.type = kPGPskepEvent_ConnectEvent;
064224 ¤   ¤   ¤   if (skep->eventHandler != NULL)
9412c8 ¤   ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
6180ae ¤   ¤   ¤   ¤   ¤   ¤   skep->userValue);
2f0fe4 ¤   ¤   }
a81b52 ¤   ¤
9ee2b3 ¤   ¤   if (IsntPGPError(err))
a25b34 ¤   ¤   {
112a0c ¤   #if PGP_WIN32
8c7f96 ¤   ¤   ¤   err = PGPStartAsyncGetHostByAddress(sockAddr.sin_addr.s_addr,
ce2d8b ¤   ¤   ¤   ¤   ¤   ¤   &skep->asyncHostEntryRef);
8d2205 ¤   ¤   ¤   if (IsntPGPError(err)) {
2a698f ¤   ¤   ¤   ¤   PGPWaitForGetHostByAddress(skep->asyncHostEntryRef,
0dfa52 ¤   ¤   ¤   ¤   ¤   ¤   h_name, 256);
a7dc3c ¤   ¤   ¤   ¤   skep->asyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
59a3a6 ¤   ¤   ¤   }
ae47b4 ¤   #else
90a23c ¤   ¤   ¤   hostEntry = PGPGetHostByAddress((char *) &sockAddr.sin_addr,·
b7e45b ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPInternetAddress),·
81da15 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPProtocolFamilyInternet);
8db7ec ¤   #endif
200fe4 ¤   ¤   }
9daf5a
c8e2b3 ¤   ¤   if (IsntPGPError(err))
565b34 ¤   ¤   {
02c843 ¤   ¤   ¤   err = PGPNewTLSSession(skep->tlsContext, &tlsSession);
24524f ¤   ¤   ¤   pgpAssertNoErr(err);
c20fe4 ¤   ¤   }
a7af5a
41e2b3 ¤   ¤   if (IsntPGPError(err))
a15b34 ¤   ¤   {
82dd92 ¤   ¤   ¤   err = PGPtlsSetProtocolOptions(tlsSession,·
863dbd ¤   ¤   ¤   ¤   ¤   kPGPtlsFlags_ServerSide | kPGPtlsFlags_RequestClientCert);
73524f ¤   ¤   ¤   pgpAssertNoErr(err);
980fe4 ¤   ¤   }
a1af5a
8ee2b3 ¤   ¤   if (IsntPGPError(err))
525b34 ¤   ¤   {
959a44 ¤   ¤   ¤   err = PGPtlsSetLocalPrivateKey(tlsSession, authKey,
9a62e1 ¤   ¤   ¤   ¤   ¤   ¤   PGPOPassphrase( skep->context, passphrase ),
dd9041 ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption( skep->context ) );
47524f ¤   ¤   ¤   pgpAssertNoErr(err);
6f0fe4 ¤   ¤   }
efaf5a
e8e2b3 ¤   ¤   if (IsntPGPError(err))
ae5b34 ¤   ¤   {
517142 ¤   ¤   ¤   err = PGPSocketsEstablishTLSSession(socketIn, tlsSession);
e50dfb ¤   ¤   ¤   if (IsPGPError(err))
a2ad3c ¤   ¤   ¤   ¤   err = PGPGetLastSocketsError();
cbaf5a
5504d4 ¤   ¤   ¤   if (skep->cancel == TRUE)
df4067 ¤   ¤   ¤   ¤   err = kPGPError_UserAbort;
23af5a
8d524f ¤   ¤   ¤   pgpAssertNoErr(err);
c70fe4 ¤   ¤   }
--6266 0001f85d38b4010005b Page 10 of pgpSKEP.c
e0af5a
08e2b3 ¤   ¤   if (IsntPGPError(err))
075b34 ¤   ¤   {
eff417 ¤   ¤   ¤   err = PGPtlsGetRemoteAuthenticatedKey(tlsSession, &remoteKey);
14af5a
6704d4 ¤   ¤   ¤   if (skep->cancel == TRUE)
144067 ¤   ¤   ¤   ¤   err = kPGPError_UserAbort;
12af5a
87524f ¤   ¤   ¤   pgpAssertNoErr(err);
700fe4 ¤   ¤   }
79af5a
84e2b3 ¤   ¤   if (IsntPGPError(err))
795b34 ¤   ¤   {
abc517 ¤   ¤   ¤   skepEvent.type = kPGPskepEvent_AuthenticateEvent;
e8a032 ¤   ¤   ¤   skepEvent.data.ad.remoteKey = remoteKey;
6b5171 ¤   ¤   ¤   skepEvent.data.ad.remoteIPAddress =·
d78d5a ¤   ¤   ¤   ¤   PGPInternetAddressToDottedString(sockAddr.sin_addr);
361778 ¤   ¤   ¤   PGPtlsGetNegotiatedCipherSuite( tlsSession,
de1270 ¤   ¤   ¤   ¤   &skepEvent.data.ad.tlsCipher );
3587c7 ¤   ¤   ¤
a22177 ¤   ¤   ¤   /* If the hostname doesn't exist, set it to the ip address */
0fd09d ¤   ¤   ¤   if (IsntNull(hostEntry))
60f776 ¤   ¤   ¤   {
692a0c ¤   #if PGP_WIN32
6e98ce ¤   ¤   ¤   ¤   skepEvent.data.ad.remoteHostname = h_name;
2147b4 ¤   #else
f0e9f1 ¤   ¤   ¤   ¤   skepEvent.data.ad.remoteHostname = hostEntry->h_name;
14b7ec ¤   #endif
c2a3a6 ¤   ¤   ¤   }
4fbb8c ¤   ¤   ¤   else
bdf776 ¤   ¤   ¤   {
e6a9d4 ¤   ¤   ¤   ¤   skepEvent.data.ad.remoteHostname =·
4fc27c ¤   ¤   ¤   ¤   ¤   skepEvent.data.ad.remoteIPAddress;
71a3a6 ¤   ¤   ¤   }
e8af5a
854224 ¤   ¤   ¤   if (skep->eventHandler != NULL)
c812c8 ¤   ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
bf80ae ¤   ¤   ¤   ¤   ¤   ¤   skep->userValue);
6caf5a
df6ecc ¤   ¤   ¤   if (IsntPGPError(err))
3698db ¤   ¤   ¤   ¤   weConfirmed = TRUE;
24bb8c ¤   ¤   ¤   else
f15985 ¤   ¤   ¤   ¤   weConfirmed = FALSE;
34af5a
dbfcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
390fe4 ¤   ¤   }
e3af5a
6ce2b3 ¤   ¤   if (IsntPGPError(err))
ced514 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &version, 1, FALSE,·
9eb402 ¤   ¤   ¤   ¤   ¤   &progressData);
2a0e1d ¤   ¤   else
f58474 ¤   ¤   ¤   remoteKey = NULL;
a4af5a
d7e2b3 ¤   ¤   if (IsntPGPError(err))
a85b34 ¤   ¤   {
651446 ¤   ¤   ¤   if (version != kPGPskepMajor)
e1678b ¤   ¤   ¤   ¤   err = kPGPClientError_IncorrectSKEPVersion;
8c0fe4 ¤   ¤   }
08af5a
fce2b3 ¤   ¤   if (IsntPGPError(err))
a5d514 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &version, 1, FALSE,·
77b402 ¤   ¤   ¤   ¤   ¤   &progressData);
9aaf5a
33e2b3 ¤   ¤   if (IsntPGPError(err))
043c12 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &theyConfirmed, 1, FALSE,·
5eb402 ¤   ¤   ¤   ¤   ¤   &progressData);
3faf5a
07e2b3 ¤   ¤   if (IsntPGPError(err))
385b34 ¤   ¤   {
00c7b0 ¤   ¤   ¤   err = sSocketSend(skep, socketIn, &weConfirmed, 1, FALSE,·
5fb402 ¤   ¤   ¤   ¤   ¤   &progressData);
1faf5a
--8862 000634afd204010005b Page 11 of pgpSKEP.c
988d71 ¤   ¤   ¤   if (!theyConfirmed)
020420 ¤   ¤   ¤   ¤   err = kPGPClientError_RejectedSKEPAuthentication;
1faf5a
31ba80 ¤   ¤   ¤   if (!weConfirmed)
594067 ¤   ¤   ¤   ¤   err = kPGPError_UserAbort;
820fe4 ¤   ¤   }
3baf5a
fce2b3 ¤   ¤   if (IsntPGPError(err))
9c5b34 ¤   ¤   {
955ea8 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &shareDataSize,·
6a55b6 ¤   ¤   ¤   ¤   ¤   sizeof(shareDataSize), TRUE, &progressData);
27af5a
8d2662 ¤   ¤   ¤   progressData.bytesTotal = sizeof(shareDataSize) + shareDataSize +·
b7b3d3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPKeyID) + sizeof(PGPShareID) +
bd5b41 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(threshold) + sizeof(numShares) +·
9aade4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(totalShares) + 4;
a40fe4 ¤   ¤   }
0baf5a
8be2b3 ¤   ¤   if (IsntPGPError(err))
f05b34 ¤   ¤   {
6863eb ¤   ¤   ¤   shareData = (PGPByte *)·
a64eae ¤   ¤   ¤   ¤   ¤   ¤   PGPNewSecureData(PGPGetContextMemoryMgr(skep->context),
df05dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   shareDataSize, kPGPMemoryMgrFlags_Clear);
8eaf5a
e41dad ¤   ¤   ¤   if (shareData == NULL)
0bf776 ¤   ¤   ¤   {
cdf330 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;;
1c6f27 ¤   ¤   ¤   ¤   pgpAssertNoErr(err);
9ba3a6 ¤   ¤   ¤   }
720fe4 ¤   ¤   }
e5af5a
5ee2b3 ¤   ¤   if (IsntPGPError(err))
de5b34 ¤   ¤   {
3d752f ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &keyID, sizeof(PGPKeyID),·
f8d5d0 ¤   ¤   ¤   ¤   ¤   FALSE, &progressData);
480fe4 ¤   ¤   }
dfaf5a
16e2b3 ¤   ¤   if (IsntPGPError(err))
ae5b34 ¤   ¤   {
3c3f11 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &shareID, sizeof(PGPShareID),·
58d5d0 ¤   ¤   ¤   ¤   ¤   FALSE, &progressData);
8e0fe4 ¤   ¤   }
88af5a
86e2b3 ¤   ¤   if (IsntPGPError(err))
7a5b34 ¤   ¤   {
d60a4f ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &threshold, sizeof(threshold),
c56a36 ¤   ¤   ¤   ¤   ¤   TRUE, &progressData);
230fe4 ¤   ¤   }
87af5a
7be2b3 ¤   ¤   if (IsntPGPError(err))
445b34 ¤   ¤   {
6893e3 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &numShares, sizeof(numShares),
d16a36 ¤   ¤   ¤   ¤   ¤   TRUE, &progressData);
1d0fe4 ¤   ¤   }
51af5a
9be2b3 ¤   ¤   if (IsntPGPError(err))
ba5b34 ¤   ¤   {
39e1de ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, &totalShares,·
32bd52 ¤   ¤   ¤   ¤   ¤   sizeof(totalShares), TRUE, &progressData);
c60fe4 ¤   ¤   }
c5af5a
1de2b3 ¤   ¤   if (IsntPGPError(err))
255b34 ¤   ¤   {
bc11d4 ¤   ¤   ¤   err = sSocketReceive(skep, socketIn, shareData,·
d4ca2f ¤   ¤   ¤   ¤   ¤   (PGPInt32) shareDataSize, FALSE, &progressData);
a30fe4 ¤   ¤   }
ebaf5a
4de2b3 ¤   ¤   if (IsntPGPError(err))
c65b34 ¤   ¤   {
1c22fc ¤   ¤   ¤   skepEvent.type = kPGPskepEvent_CloseEvent;
124224 ¤   ¤   ¤   if (skep->eventHandler != NULL)
6312c8 ¤   ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
--f34e 000cdfb8a864010005b Page 12 of pgpSKEP.c
3c80ae ¤   ¤   ¤   ¤   ¤   ¤   skep->userValue);
8c0fe4 ¤   ¤   }
53af5a
d8e2b3 ¤   ¤   if (IsntPGPError(err))
6d5b34 ¤   ¤   {
600fd6 ¤   ¤   ¤   progressData.bytesTotal = 0;
a95858 ¤   ¤   ¤   err = sSocketSend(skep, socketIn, &closing, sizeof(closing), TRUE,
9cb402 ¤   ¤   ¤   ¤   ¤   &progressData);
2a0fe4 ¤   ¤   }
5aaf5a
51f833 ¤   ¤   if (IsntNull(tlsSession))
dc5b34 ¤   ¤   {
10bb1a ¤   ¤   ¤   if (IsntNull(remoteKey))
e0b6d0 ¤   ¤   ¤   ¤   PGPtlsClose(tlsSession, FALSE);
45bb8c ¤   ¤   ¤   else
fdc4ec ¤   ¤   ¤   ¤   PGPtlsClose(tlsSession, TRUE);
764d95 ¤   ¤   ¤   PGPFreeTLSSession(tlsSession);
730fe4 ¤   ¤   }
8daf5a
d4e935 ¤   ¤   if (IsntNull(socketIn))
855b34 ¤   ¤   {
5678c2 ¤   ¤   ¤   PGPCloseSocket(socketIn);
d0e871 ¤   ¤   ¤   skep->socketIn = NULL;
190fe4 ¤   ¤   }
efaf5a
a028b0 ¤   ¤   if (IsntPGPError(err) && IsntNull(shareData))
bd5b34 ¤   ¤   {
29e287 ¤   ¤   ¤   err = pgpCreateShares(skep->context, keyID, shareID, threshold,·
16ff12 ¤   ¤   ¤   ¤   ¤   numShares, totalShares, shareDataSize, shareData, &shares);
6e524f ¤   ¤   ¤   pgpAssertNoErr(err);
480fe4 ¤   ¤   }
a0af5a
fa8c38 ¤   ¤   if (IsntNull(shareData))
cbb800 ¤   ¤   ¤   PGPFreeData(shareData);
6487c7 ¤   ¤   ¤
ede2b3 ¤   ¤   if (IsntPGPError(err))
1f5b34 ¤   ¤   {
b5a577 ¤   ¤   ¤   skepEvent.type = kPGPskepEvent_ShareEvent;
69e0dd ¤   ¤   ¤   skepEvent.data.sd.shares = shares;
e9af5a
cf4224 ¤   ¤   ¤   if (skep->eventHandler != NULL)
9312c8 ¤   ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
1f80ae ¤   ¤   ¤   ¤   ¤   ¤   skep->userValue);
950fe4 ¤   ¤   }
10af5a
3033d4 ¤   ¤   if (!weConfirmed)
4afcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
e19371 ¤   }
f6af5a
93dc1e ¤   if (IsntNull(socket))
1dc7a1 ¤   {
cb1891 ¤   ¤   PGPCloseSocket(socket);
2a5935 ¤   ¤   skep->socketOut = NULL;
ff9371 ¤   }
08af5a
ad1b1e ¤   if (IsntNull(skep->eventHandler))
1c5bb3 ¤   ¤   PGPSetSocketsIdleEventHandler(oldCallback, oldUserValue);
02af5a
c2ea41 ¤   PGPSocketsDisposeThreadStorage(previousStorage);
0dba95 ¤   PGPSocketsCleanup();
3aaf5a
67dcaf ¤   if (skep->cancel == TRUE)
b570bb ¤   ¤   err = kPGPError_NoErr;
21af5a
545ea8 ¤   return err;
a3efe6 }
64af5a
cdaf5a
befca7 PGPError PGPskepCancel(PGPskepRef skep)
aebb36 {
603edb ¤   PGPValidateSKEP(skep);
cddc0a ¤   pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
--17ed 00028a4c4804010005b Page 13 of pgpSKEP.c
e0af5a
78b268 ¤   if (IsntNull(skep->socketIn))
5ac7a1 ¤   {
3cca68 ¤   ¤   PGPCloseSocket(skep->socketIn);
f7640e ¤   ¤   skep->socketIn = NULL;
5e9371 ¤   }
bdaf5a
03fc32 ¤   if (IsntNull(skep->socketOut))
43c7a1 ¤   {
746a46 ¤   ¤   PGPCloseSocket(skep->socketOut);
c15935 ¤   ¤   skep->socketOut = NULL;
349371 ¤   }
42afb9 #if PGP_WIN32
89a1c5 ¤   if (PGPAsyncHostEntryRefIsValid(skep->asyncHostEntryRef)) {
d7792f ¤   ¤   PGPCancelAsyncHostEntryRef(skep->asyncHostEntryRef);
bcaf25 ¤   ¤   skep->asyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
079371 ¤   }
147454 #endif
05af5a
964419 ¤   skep->cancel = TRUE;
00af5a
95151e ¤   return kPGPError_NoErr;
acefe6 }
36af5a
19af5a
b60f61 PGPError PGPFreeSKEP(PGPskepRef skep)
49bb36 {
a13edb ¤   PGPValidateSKEP(skep);
3bdc0a ¤   pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
e7af5a
b2785a ¤   if (IsntNull(skep->socketIn) || IsntNull(skep->socketOut))
46ea75 ¤   ¤   PGPskepCancel(skep);¤
a7af5a
568baf ¤   if (skep->freeTLSContext)
a5187e ¤   ¤   PGPFreeTLSContext(skep->tlsContext);
fbaf5a
1e904b ¤   PGPFreeData(skep);
45151e ¤   return kPGPError_NoErr;
38efe6 }
29af5a
68da57 PGPContextRef PGPGetSKEPContext(PGPskepRef skep)
48bb36 {
ff8a97 ¤   PGPContextRef¤  context;
0867c5 ¤
0fb89d ¤   if( PGPskepRefIsValid( skep ) )
a4c7a1 ¤   {
564993 ¤   ¤   if (skep->magic == kPGPskepMagic)
ccc45b ¤   ¤   ¤   context = skep->context;
fc0e1d ¤   ¤   else
9618f0 ¤   ¤   ¤   context = kInvalidPGPContextRef;
169371 ¤   }
ea0e24 ¤   else
06c7a1 ¤   {
9e1e48 ¤   ¤   context = kInvalidPGPContextRef;
589371 ¤   }
4567c5 ¤
5dc097 ¤   return context;
1defe6 }
d2af5a
b7f067 static PGPError sSocketSend(PGPskepRef skep, PGPSocketRef socket,·
b09df9 ¤   ¤   ¤   ¤   ¤   void *data, PGPInt32 dataSize, PGPBoolean crossPlatform,
5d0339 ¤   ¤   ¤   ¤   ¤   PGPskepEventProgressData *progressData)
83bb36 {
7053ac ¤   PGPByte¤¤   tempData16[sizeof(PGPUInt16)];
11d83f ¤   PGPByte¤¤   tempData32[sizeof(PGPUInt32)];
53b8a7 ¤   PGPUInt16¤  data16;
fcec9c ¤   PGPUInt32¤  data32;
97a332 ¤   PGPInt32¤   result = 0;
73af5a
7b3bd3 ¤   if (crossPlatform)
10c7a1 ¤   {
284b71 ¤   ¤   if (dataSize == sizeof(PGPUInt16))
--70e7 0000052bcbb4010005b Page 14 of pgpSKEP.c
e35b34 ¤   ¤   {
760f17 ¤   ¤   ¤   pgpCopyMemory(data, &data16, sizeof(PGPUInt16));
8994a9 ¤   ¤   ¤   PGPUInt16ToEndian(data16, kPGPskepEndian, tempData16);
af8005 ¤   ¤   ¤   result = PGPSend(socket, tempData16, dataSize, kPGPSendFlagNone);
1f0fe4 ¤   ¤   }
600e1d ¤   ¤   else
ef5b34 ¤   ¤   {
aaabdf ¤   ¤   ¤   pgpCopyMemory(data, &data32, sizeof(PGPUInt32));
af259a ¤   ¤   ¤   PGPUInt32ToEndian(data32, kPGPskepEndian, tempData32);
47d55a ¤   ¤   ¤   result = PGPSend(socket, tempData32, dataSize, kPGPSendFlagNone);
a60fe4 ¤   ¤   }
7e9371 ¤   }
bb0e24 ¤   else
030668 ¤   ¤   result = PGPSend(socket, data, dataSize, kPGPSendFlagNone);
7caf5a
154139 ¤   return sProcessResult(skep, result, progressData);
66efe6 }
35af5a
0eaf5a
a55b82 static PGPError sSocketReceive(PGPskepRef skep, PGPSocketRef socket,·
bb9df9 ¤   ¤   ¤   ¤   ¤   void *data, PGPInt32 dataSize, PGPBoolean crossPlatform,
8b0339 ¤   ¤   ¤   ¤   ¤   PGPskepEventProgressData *progressData)
03bb36 {
ff53ac ¤   PGPByte¤¤   tempData16[sizeof(PGPUInt16)];
42d83f ¤   PGPByte¤¤   tempData32[sizeof(PGPUInt32)];
37b8a7 ¤   PGPUInt16¤  data16;
1bec9c ¤   PGPUInt32¤  data32;
75a332 ¤   PGPInt32¤   result = 0;
56af5a
033bd3 ¤   if (crossPlatform)
2cc7a1 ¤   {
cb4b71 ¤   ¤   if (dataSize == sizeof(PGPUInt16))
1cb8e9 ¤   ¤   ¤   result = PGPReceive(socket, tempData16, dataSize,·
705b66 ¤   ¤   ¤   ¤   ¤   ¤   kPGPReceiveFlagNone);
9d0e1d ¤   ¤   else
c7db04 ¤   ¤   ¤   result = PGPReceive(socket, tempData32, dataSize,·
775b66 ¤   ¤   ¤   ¤   ¤   ¤   kPGPReceiveFlagNone);
50af5a
65c1a6 ¤   ¤   if (result > 0)
965b34 ¤   ¤   {
97dae9 ¤   ¤   ¤   if (dataSize == sizeof(PGPUInt16))
34f776 ¤   ¤   ¤   {
fd6dfb ¤   ¤   ¤   ¤   data16 = PGPEndianToUInt16(kPGPskepEndian, tempData16);
ad016e ¤   ¤   ¤   ¤   pgpCopyMemory(&data16, data, sizeof(PGPUInt16));
35a3a6 ¤   ¤   ¤   }
19bb8c ¤   ¤   ¤   else
97f776 ¤   ¤   ¤   {
02028c ¤   ¤   ¤   ¤   data32 = PGPEndianToUInt32(kPGPskepEndian, tempData32);
289939 ¤   ¤   ¤   ¤   pgpCopyMemory(&data32, data, sizeof(PGPUInt32));
d3a3a6 ¤   ¤   ¤   }
c10fe4 ¤   ¤   }
c29371 ¤   }
5b0e24 ¤   else
67ca8f ¤   ¤   result = PGPReceive(socket, data, dataSize, kPGPReceiveFlagNone);
70af5a
d44139 ¤   return sProcessResult(skep, result, progressData);
c1efe6 }
0baf5a
a0af5a
1879ec static PGPError sProcessResult(PGPskepRef skep, PGPInt32 result,
c00339 ¤   ¤   ¤   ¤   ¤   PGPskepEventProgressData *progressData)
c6bb36 {
31a668 ¤   PGPskepEvent¤   skepEvent;
803bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
3faf5a
b4c94e ¤   if (result == 0)
d00fd8 ¤   ¤   err = kPGPError_UserAbort;
25617f ¤   else if (result == kPGPSockets_Error)
4bc7a1 ¤   {
9d3d0a ¤   ¤   err = PGPGetLastSocketsError();
d1af5a
00eba7 ¤   ¤   if (skep->cancel == TRUE)
--2d91 0017a365e394010005b Page 15 of pgpSKEP.c
2e4e2b ¤   ¤   ¤   err = kPGPError_UserAbort;
61af5a
48e919 ¤   ¤   pgpAssertNoErr(err);
739371 ¤   }
a40e24 ¤   else
48c7a1 ¤   {
3eec13 ¤   ¤   progressData->bytesSoFar += result;
b6d225 ¤   ¤   skepEvent.type = kPGPskepEvent_ProgressEvent;
613ea8 ¤   ¤   skepEvent.data.pd.bytesSoFar = progressData->bytesSoFar;
a0fde9 ¤   ¤   skepEvent.data.pd.bytesTotal = progressData->bytesTotal;
1eaf5a
584dd3 ¤   ¤   if ((skep->eventHandler != NULL) && (progressData->bytesTotal > 0))
769d9f ¤   ¤   ¤   err = skep->eventHandler(skep, &skepEvent,·
e8bc40 ¤   ¤   ¤   ¤   ¤   skep->userValue);
c19371 ¤   }
36af5a
6e5ea8 ¤   return err;
e1efe6 }
75af5a
e7af5a
127f6d static PGPError sSocketCallback(PGPContextRef context,·
ec14a1 ¤   ¤   ¤   ¤   ¤   struct PGPEvent *event, PGPUserValue userValue)
a4bb36 {
ba9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
eb9754 ¤   PGPskepRef¤ ¤   skep;
85a668 ¤   PGPskepEvent¤   skepEvent;
85af5a
191043 ¤   pgpAssert(event != NULL);
e86d02 ¤   (void) context;
be756f ¤   (void) event;
7ebab2 ¤   skep = (PGPskepRef) userValue;
5967c5 ¤
820f17 ¤   if (skep->eventHandler != NULL)
5fc7a1 ¤   {
7f861b ¤   ¤   skepEvent.type = kPGPskepEvent_NullEvent;
24b98f ¤   ¤   err = skep->eventHandler(skep, &skepEvent, skep->userValue);
159371 ¤   }
7aaf5a
8c5ea8 ¤   return err;
64efe6 }
ebaf5a
50af5a
9c7e4d /*__Editor_settings____
a3af5a
2c4126 ¤   Local Variables:
de7b17 ¤   tab-width: 4
fd0e6c ¤   End:
215f8c ¤   vi: ts=4 sw=4
369e9b ¤   vim: si
7ad062 _____________________*/
--521b 000c767df8d4010005c Page 1 of pgpSKEP.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
3d08f5 ¤   $Id: pgpSKEP.h,v 1.10.8.1 1998/11/12 03:11:12 heller Exp $
03f7f7 ____________________________________________________________________________*/
949602 #ifndef Included_pgpSKEP_h¤ /* [ */
ca0734 #define Included_pgpSKEP_h
a3af5a
b9e2ff #include "pgpConfig.h"
47c5d5 #include "pgpBase.h"
442f8d #include "pgpErrors.h"
45afda #include "pgpShare.h"
b3a076 #include "pgpKeys.h"
faec82 #include "pgpTLS.h"
b4af5a
f18ba8 typedef struct PGPskep *¤   PGPskepRef;
19af5a
307028 #define¤kInvalidPGPskepRef¤ ¤   ¤   ((PGPskepRef) NULL)
8628be #define PGPskepRefIsValid( ref )¤   ( (ref) != kInvalidPGPskepRef )
deaf5a
d84311 typedef enum _PGPskepEventType
febb36 {
ffca87 ¤   kPGPskepEvent_NullEvent¤¤   ¤   = 0,¤   /* Nothing is happening */
b7f129 ¤   kPGPskepEvent_ListenEvent¤  ¤   = 1,¤   /* Listening for data */
2228de ¤   kPGPskepEvent_ConnectEvent¤ ¤   = 2,¤   /* Connection established */
0aa424 ¤   kPGPskepEvent_AuthenticateEvent = 3,¤   /* Remote site authenticated */
cce706 ¤   kPGPskepEvent_ProgressEvent¤¤   = 4,¤   /* Data flow progress */
9330ef ¤   kPGPskepEvent_CloseEvent¤   ¤   = 5,¤   /* Connection closing */
7c78c5 ¤   kPGPskepEvent_ShareEvent¤   ¤   = 6¤¤   /* Share received */
5bea82 } PGPskepEventType;
51af5a
309a54 typedef struct _PGPskepEventAuthenticateData
6abb36 {
cbc876 ¤   PGPKeyRef¤  ¤   ¤   ¤   remoteKey;
24576a ¤   const char *¤   ¤   ¤   remoteHostname;
59379b ¤   const char *¤   ¤   ¤   remoteIPAddress;
255db6 ¤   PGPtlsCipherSuiteNum¤   tlsCipher;
37193d } PGPskepEventAuthenticateData;
0faf5a
87ca28 typedef struct _PGPskepEventProgressData
dcbb36 {
4fd52f ¤   PGPUInt32¤  bytesSoFar;
b945e0 ¤   PGPUInt32¤  bytesTotal;
ddf784 } PGPskepEventProgressData;
b9af5a
1005e5 typedef struct _PGPskepEventShareData
10bb36 {
104d0e ¤   PGPShareRef¤shares;
8c3077 } PGPskepEventShareData;
ccaf5a
919c4b typedef union _PGPskepEventData
80bb36 {
edfbfc ¤   PGPskepEventAuthenticateData¤   ad;
88dc0d ¤   PGPskepEventProgressData¤   ¤   pd;
5f1835 ¤   PGPskepEventShareData¤  ¤   ¤   sd;
8357df } PGPskepEventData;
8faf5a
72fde4 typedef struct _PGPskepEvent
49bb36 {
dabb55 ¤   PGPskepEventType¤   type;
d1fc44 ¤   PGPskepEventData¤   data;
fc84cc } PGPskepEvent;
90af5a
186fc6 typedef PGPError (*PGPskepEventHandler)(PGPskepRef skep,
667ad6 ¤   ¤   ¤   ¤   ¤   ¤   PGPskepEvent *event, PGPUserValue userValue);
dcaf5a
06af5a
b099c6 PGP_BEGIN_C_DECLARATIONS
c7af5a
--9605 001e68cf8194010005c Page 2 of pgpSKEP.h
10cbcf #if PRAGMA_IMPORT_SUPPORTED
20b981 #pragma import on
5f7454 #endif
3aaf5a
90bfa2 PGPError ¤  ¤   PGPNewSKEP(PGPContextRef context,·
f25ee2 ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef tlsContext,
f17d61 ¤   ¤   ¤   ¤   ¤   ¤   PGPskepRef *skep);
bbaf5a
941168 PGPError¤   ¤   PGPskepSetEventHandler(PGPskepRef skep,
7deafe ¤   ¤   ¤   ¤   ¤   ¤   PGPskepEventHandler handler, PGPUserValue userValue);
8caf5a
9f9a89 PGPError ¤  ¤   PGPskepSendShares(PGPskepRef skep, PGPKeyRef authKey,
4a4e18 ¤   ¤   ¤   ¤   ¤   ¤   const char *passphrase, PGPShareRef shares,
60782e ¤   ¤   ¤   ¤   ¤   ¤   const char *destSocketAddress);
c3af5a
37a654 PGPError ¤  ¤   PGPskepReceiveShares(PGPskepRef skep, PGPKeyRef authKey,
cdda00 ¤   ¤   ¤   ¤   ¤   ¤   const char *passphrase);
66af5a
14570c PGPError ¤  ¤   PGPskepCancel(PGPskepRef skep);
54af5a
cf273e PGPError ¤  ¤   PGPFreeSKEP(PGPskepRef skep);
0daf5a
b01ce1 PGPContextRef¤  PGPGetSKEPContext(PGPskepRef skep);
37af5a
adcbcf #if PRAGMA_IMPORT_SUPPORTED
772ced #pragma import reset
a27454 #endif
abaf5a
901254 PGP_END_C_DECLARATIONS
5caf5a
5d1206 #endif /* ] Included_pgpSKEP_h */
4baf5a
ddaf5a
fc7e4d /*__Editor_settings____
34af5a
c14126 ¤   Local Variables:
df7b17 ¤   tab-width: 4
270e6c ¤   End:
fe5f8c ¤   vi: ts=4 sw=4
cd9e9b ¤   vim: si
e6d062 _____________________*/
--d3c5 000739a6a2e4010005d Page 1 of pgpShare.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
946845 ¤   $Id: pgpShare.c,v 1.9.8.1 1998/11/12 03:11:12 heller Exp $
e0f7f7 ____________________________________________________________________________*/
90955c #include "pgpSharePriv.h"
134919 #include "pgpUtilities.h"
df9f72 #include "pgpHash.h"
3e6773 #include "pgpMemoryMgr.h"
aa0d08 #include "pgpMem.h"
8fa146 #include "pgpDebug.h"
6aaf5a
00aa31 typedef struct PGPShare¤¤   PGPShare;
3eaf5a
fa9ea3 struct PGPShare
75bb36 {
3c8a97 ¤   PGPContextRef¤  context;
e5d91c ¤   PGPMemoryMgrRef¤memoryMgr;
6ac0ff ¤   PGPKeyID¤   ¤   keyID;
5f11d8 ¤   PGPShareID¤ ¤   shareID;
fe7d89 ¤   PGPUInt32¤  ¤   threshold;
3a7bfe ¤   PGPUInt32¤  ¤   numShares;
66f040 ¤   PGPUInt32¤  ¤   totalShares;
3f4500 ¤   PGPSize¤¤   ¤   shareDataSize;
05fa27 ¤   PGPByte *¤  ¤   shareData;
704182 ¤   PGPSize¤¤   ¤   shareHashSize;
8400ec ¤   PGPByte *¤  ¤   shareHash;
5582f7 };
87af5a
3de65c #define PGPValidateShare(ref)¤  PGPValidateParam(ref != NULL)
49af5a
2cf995 static PGPError sCalculateShareHash(PGPShareRef share);
bdaf5a
a1af5a
a60c59 PGPError PGPCreateShares(PGPContextRef context, PGPKeyRef key,·
2163b9 ¤   ¤   ¤   ¤   PGPUInt32 threshold, PGPUInt32 numShares,·
22da28 ¤   ¤   ¤   ¤   PGPShareRef *share)
4cbb36 {
a4d74a ¤   PGPMemoryMgrRef¤¤   memoryMgr = NULL;
e100ec ¤   PGPShareRef¤¤   ¤   newShare = NULL;
d282ab ¤   PGPInt32¤   ¤   ¤   lockBits = 0;
196b53 ¤   PGPSize¤¤   ¤   ¤   passkeySize = 0;
970bf1 ¤   PGPSize¤¤   ¤   ¤   shareSize = 0;
17cdac ¤   PGPSize¤¤   ¤   ¤   totalSharesSize = 0;
7b022f ¤   PGPByte *¤  ¤   ¤   passkey¤= NULL;
b4d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
02af5a
92861f ¤   if (IsntNull(share))
d004a1 ¤   ¤   *share = NULL;
d7af5a
284ecd ¤   PGPValidateParam(PGPContextRefIsValid(context));
db17d0 ¤   PGPValidateParam(PGPKeyRefIsValid(key));
a5ead8 ¤   PGPValidateParam(threshold > 0);
58846d ¤   PGPValidateParam(numShares > 0);
a6d7f2 ¤   PGPValidateParam(threshold <= numShares);
39476a ¤   PGPValidatePtr(share);
07af5a
d8cc3d ¤   memoryMgr = PGPGetContextMemoryMgr(context);
1567c5 ¤
fdae4e ¤   pgpAssert(PGPMemoryMgrIsValid(memoryMgr));
96dbbb ¤   if (!PGPMemoryMgrIsValid(memoryMgr))
1d62b5 ¤   ¤   return kPGPError_BadParams;
c8af5a
04ef8e ¤   newShare = (PGPShareRef) PGPNewData(memoryMgr, sizeof(PGPShare),·
dde0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
acaf5a
071f11 ¤   pgpAssert(IsntNull(newShare));
f14593 ¤   if (IsNull(newShare))
734030 ¤   ¤   return kPGPError_OutOfMemory;
--648b 00027182f294010005d Page 2 of pgpShare.c
e0af5a
58708a ¤   newShare->context¤  ¤   = context;
7bbaf8 ¤   newShare->memoryMgr¤¤   = memoryMgr;
1a3dad ¤   newShare->threshold¤¤   = threshold;
734dff ¤   newShare->numShares¤¤   = numShares;
faa96c ¤   newShare->totalShares¤  = numShares;
7f14b2 ¤   newShare->shareDataSize¤= 0;
3b4e9e ¤   newShare->shareData¤¤   = NULL;
4b76c5 ¤   newShare->shareHashSize = 0;
57ef94 ¤   newShare->shareHash¤¤   = NULL;
bcaf5a
cfb4b0 ¤   err = PGPGetKeyIDFromKey(key, &(newShare->keyID));
c8af5a
6df69b ¤   if (IsntPGPError(err))
44be22 ¤   ¤   err = PGPGetKeyNumber(key, kPGPKeyPropLockingBits, &lockBits);
ba67c5 ¤
a9f69b ¤   if (IsntPGPError(err))
4dc7a1 ¤   {
21baee ¤   ¤   passkeySize = lockBits / 8;
abb78e ¤   ¤   passkey = (PGPByte *)PGPNewSecureData(memoryMgr, passkeySize,·
072e6f ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
9d9371 ¤   }
63af5a
7ce718 ¤   if (IsNull(passkey))
85bce1 ¤   ¤   err = kPGPError_OutOfMemory;
0daf5a
e2f69b ¤   if (IsntPGPError(err))
9575f8 ¤   ¤   err = PGPContextGetRandomBytes(context, passkey, passkeySize);
3daf5a
fef69b ¤   if (IsntPGPError(err))
acc7a1 ¤   {
bf409c ¤   ¤   shareSize = kPGPShareHeaderSize + passkeySize;
325dfd ¤   ¤   totalSharesSize = shareSize * numShares;
2baf5a
8e027f ¤   ¤   newShare->shareData = (PGPByte *)PGPNewSecureData(memoryMgr,
b7f4b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   totalSharesSize,·
8d7e53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
859371 ¤   }
d6af5a
e8a62c ¤   if (IsNull(newShare->shareData))
c0bce1 ¤   ¤   err = kPGPError_OutOfMemory;
5aaf5a
f8f69b ¤   if (IsntPGPError(err))
04c7a1 ¤   {
1f5448 ¤   ¤   newShare->shareDataSize = totalSharesSize;
9faf5a
e911c6 ¤   ¤   err = PGPSecretShareData(context, passkey, passkeySize, threshold,
5d45a3 ¤   ¤   ¤   ¤   numShares, newShare->shareData);
009371 ¤   }
7aaf5a
9ff69b ¤   if (IsntPGPError(err))
592733 ¤   ¤   err = sCalculateShareHash(newShare);
5aaf5a
e5f69b ¤   if (IsntPGPError(err))
721399 ¤   ¤   err = PGPContextGetRandomBytes(context, newShare->shareID.data,·
822405 ¤   ¤   ¤   ¤   sizeof(newShare->shareID.data));
83af5a
b79373 ¤   if (IsntNull(passkey))
14c287 ¤   ¤   PGPFreeData(passkey);
83af5a
a482f0 ¤   if (IsPGPError(err))
84c7a1 ¤   {
360c1f ¤   ¤   PGPFreeShares(newShare);
4d29d4 ¤   ¤   newShare = NULL;
c89371 ¤   }
0caf5a
ce7517 ¤   *share = newShare;
69a2cd ¤   return err;¤¤
0eefe6 }
0caf5a
16af5a
27c837 PGPError pgpCreateShares(PGPContextRef context, PGPKeyID keyID,·
--37e1 0004f64b40b4010005d Page 3 of pgpShare.c
458886 ¤   ¤   ¤   ¤   PGPShareID shareID, PGPUInt32 threshold, PGPUInt32 numShares,·
60bbe6 ¤   ¤   ¤   ¤   PGPUInt32 totalShares, PGPSize shareSize,
a1e194 ¤   ¤   ¤   ¤   const PGPByte *shareData, PGPShareRef *shares)
bebb36 {
aad74a ¤   PGPMemoryMgrRef¤¤   memoryMgr = NULL;
5800ec ¤   PGPShareRef¤¤   ¤   newShare = NULL;
add591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
44af5a
b14749 ¤   if (IsntNull(shares))
93f4cc ¤   ¤   *shares = NULL;
5caf5a
b94ecd ¤   PGPValidateParam(PGPContextRefIsValid(context));
32ead8 ¤   PGPValidateParam(threshold > 0);
70846d ¤   PGPValidateParam(numShares > 0);
9fc549 ¤   PGPValidateParam(totalShares > 0);
a896cb ¤   PGPValidateParam(threshold <= totalShares);
8de0ee ¤   PGPValidateParam(numShares <= totalShares);
7bbec4 ¤   PGPValidateParam(shareSize > 0);
4bbffd ¤   PGPValidatePtr(shareData);
44f5ae ¤   PGPValidatePtr(shares);
7daf5a
2acc3d ¤   memoryMgr = PGPGetContextMemoryMgr(context);
cf67c5 ¤
fcae4e ¤   pgpAssert(PGPMemoryMgrIsValid(memoryMgr));
fbdbbb ¤   if (!PGPMemoryMgrIsValid(memoryMgr))
b862b5 ¤   ¤   return kPGPError_BadParams;
e5af5a
39ef8e ¤   newShare = (PGPShareRef) PGPNewData(memoryMgr, sizeof(PGPShare),·
3be0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
0daf5a
7b1f11 ¤   pgpAssert(IsntNull(newShare));
2e4593 ¤   if (IsNull(newShare))
c64030 ¤   ¤   return kPGPError_OutOfMemory;
a5af5a
3d708a ¤   newShare->context¤  ¤   = context;
ffbaf8 ¤   newShare->memoryMgr¤¤   = memoryMgr;
e73dad ¤   newShare->threshold¤¤   = threshold;
754dff ¤   newShare->numShares¤¤   = numShares;
a92f32 ¤   newShare->totalShares¤  = totalShares;
30a76b ¤   newShare->shareDataSize¤= shareSize;
424e9e ¤   newShare->shareData¤¤   = NULL;
5a76c5 ¤   newShare->shareHashSize = 0;
58ef94 ¤   newShare->shareHash¤¤   = NULL;
72af5a
da707b ¤   newShare->shareData = (PGPByte *) PGPNewSecureData(memoryMgr, shareSize,·
bae7fa ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
efaf5a
46a62c ¤   if (IsNull(newShare->shareData))
96bce1 ¤   ¤   err = kPGPError_OutOfMemory;
f2af5a
68f69b ¤   if (IsntPGPError(err))
80c7a1 ¤   {
9581f6 ¤   ¤   pgpCopyMemory(&keyID, &(newShare->keyID), sizeof(PGPKeyID));·
efcf51 ¤   ¤   pgpCopyMemory(&shareID, &(newShare->shareID), sizeof(PGPShareID));·
a7b4ca ¤   ¤   pgpCopyMemory(shareData, newShare->shareData, shareSize);
189371 ¤   }
44af5a
daf69b ¤   if (IsntPGPError(err))
9f2733 ¤   ¤   err = sCalculateShareHash(newShare);
e7af5a
8782f0 ¤   if (IsPGPError(err))
1ac7a1 ¤   {
000c1f ¤   ¤   PGPFreeShares(newShare);
b029d4 ¤   ¤   newShare = NULL;
ff9371 ¤   }
dbaf5a
bbffcc ¤   *shares = newShare;
a45ea8 ¤   return err;
faefe6 }
bdaf5a
21af5a
4f61d2 /* The passkey needs to be freed with PGPFreeData(passkey) */
--3801 000d51e07784010005d Page 4 of pgpShare.c
c58159 PGPError PGPGetPasskeyFromShares(PGPShareRef share, PGPByte **passkey,
08efbd ¤   ¤   ¤   ¤   PGPSize *passkeySize)
08bb36 {
74a0c5 ¤   PGPSize¤¤   shareSize = 0;
bcd73e ¤   PGPSize¤¤   newPasskeySize = 0;
e8b67c ¤   PGPByte *¤  newPasskey = NULL;
9d8e12 ¤   PGPError¤   err = kPGPError_NoErr;
7faf5a
c9c41b ¤   if (passkey != NULL)
d8597c ¤   ¤   *passkey = NULL;
b5c868 ¤   if (passkeySize != NULL)
ea2169 ¤   ¤   *passkeySize = 0;
0aaf5a
415ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
f3967c ¤   PGPValidatePtr(passkey);
14a2c8 ¤   PGPValidatePtr(passkeySize);
d1af5a
48f8fc ¤   shareSize = share->shareDataSize / share->numShares;
17a8cf ¤   newPasskeySize = shareSize - kPGPShareHeaderSize;
adaf5a
a9f742 ¤   newPasskey = (PGPByte *) PGPNewSecureData(share->memoryMgr, newPasskeySize,·
da2e6f ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
88af5a
454288 ¤   if (IsNull(newPasskey))
adbce1 ¤   ¤   err = kPGPError_OutOfMemory;
09af5a
7ff69b ¤   if (IsntPGPError(err))
8f8979 ¤   ¤   err = PGPSecretReconstructData(share->context, share->shareData,·
3844e6 ¤   ¤   ¤   ¤   newPasskeySize, share->numShares, newPasskey);
d4af5a
8282f0 ¤   if (IsPGPError(err))
88c7a1 ¤   {
21d854 ¤   ¤   PGPFreeData(newPasskey);
fa2de7 ¤   ¤   newPasskey = NULL;
d60b47 ¤   ¤   newPasskeySize = 0;
989371 ¤   }
b5af5a
e1d191 ¤   *passkey = newPasskey;
4fa44b ¤   *passkeySize = newPasskeySize;
515ea8 ¤   return err;
d7efe6 }
7aaf5a
71af5a
88a527 PGPError PGPSplitShares(PGPShareRef share, PGPUInt32 numShares,·
2fbc8d ¤   ¤   ¤   ¤   PGPShareRef *splitShares)
4abb36 {
8900ec ¤   PGPShareRef¤¤   ¤   newShare = NULL;
77c2f9 ¤   PGPUInt32¤  ¤   ¤   sharesLeft = 0;
f00bf1 ¤   PGPSize¤¤   ¤   ¤   shareSize = 0;
dbed6f ¤   PGPSize¤¤   ¤   ¤   dataSize = 0;
157d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
e0af5a
14861f ¤   if (IsntNull(share))
49d658 ¤   ¤   *splitShares = NULL;
7eaf5a
f45ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
09846d ¤   PGPValidateParam(numShares > 0);
ac54f2 ¤   PGPValidatePtr(splitShares);
beaf5a
6e45cc ¤   if (numShares > share->numShares)
cafeb0 ¤   ¤   return kPGPClientError_NotEnoughSharesInObject;
38af5a
3fe69f ¤   newShare = (PGPShareRef) PGPNewData(share->memoryMgr, sizeof(PGPShare),·
ade0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
c9af5a
ad1f11 ¤   pgpAssert(IsntNull(newShare));
734593 ¤   if (IsNull(newShare))
a34030 ¤   ¤   return kPGPError_OutOfMemory;
53af5a
4c5d51 ¤   newShare->context¤  ¤   = share->context;
ab709b ¤   newShare->memoryMgr¤¤   = share->memoryMgr;
d52649 ¤   newShare->threshold¤¤   = share->threshold;
--ecd4 000152957aa4010005d Page 5 of pgpShare.c
9b252c ¤   newShare->totalShares¤  = share->totalShares;
ecaf5a
882cde ¤   pgpCopyMemory(&(share->keyID), &(newShare->keyID), sizeof(PGPKeyID));
795887 ¤   pgpCopyMemory(&(share->shareID), &(newShare->shareID),·
804188 ¤   ¤   sizeof(PGPShareID));
b467c5 ¤
f6f8fc ¤   shareSize = share->shareDataSize / share->numShares;
1df706 ¤   dataSize = numShares * shareSize;
c93722 ¤   sharesLeft = share->numShares - numShares;
4867c5 ¤
6cc010 ¤   newShare->shareData¤= (PGPByte *) PGPNewSecureData(share->memoryMgr,·
fa4f5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize,·
8c6ddf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
ceaf5a
45a62c ¤   if (IsNull(newShare->shareData))
babce1 ¤   ¤   err = kPGPError_OutOfMemory;
2faf5a
27f69b ¤   if (IsntPGPError(err))
d4c7a1 ¤   {
042fd9 ¤   ¤   pgpCopyMemory(&(share->shareData[sharesLeft * shareSize]),·
8eee1a ¤   ¤   ¤   newShare->shareData, dataSize);
1baf5a
0b213f ¤   ¤   newShare->numShares¤= numShares;
410b40 ¤   ¤   newShare->shareDataSize¤= dataSize;
f4af5a
4b4621 ¤   ¤   share->numShares = sharesLeft;
ccf06f ¤   ¤   share->shareDataSize = sharesLeft * shareSize;
1c1b52 ¤   ¤
59d6d1 ¤   ¤   if (share->shareDataSize > 0)
f39c31 ¤   ¤   ¤   err = PGPReallocData(share->memoryMgr, &(share->shareData),·
ef50fa ¤   ¤   ¤   ¤   ¤   share->shareDataSize, 0);
200e1d ¤   ¤   else
855b34 ¤   ¤   {
db89ec ¤   ¤   ¤   PGPFreeData(share->shareData);
5ca679 ¤   ¤   ¤   share->shareData = NULL;
1a0fe4 ¤   ¤   }
509371 ¤   }
56af5a
d8be76 ¤   PGPFreeData(share->shareHash);
08af5a
97f69b ¤   if (IsntPGPError(err))
76a1ce ¤   ¤   err = sCalculateShareHash(share);
1aaf5a
63f69b ¤   if (IsntPGPError(err))
7a2733 ¤   ¤   err = sCalculateShareHash(newShare);
5daf5a
7b82f0 ¤   if (IsPGPError(err))
d6c7a1 ¤   {
0f0c1f ¤   ¤   PGPFreeShares(newShare);
b129d4 ¤   ¤   newShare = NULL;
849371 ¤   }
74af5a
f4985f ¤   *splitShares = newShare;
695ea8 ¤   return err;
9eefe6 }
02af5a
10af5a
87cff1 /* The share objects being combined are NOT freed by this function */
ae8811 PGPError PGPCombineShares(PGPShareRef firstShare, PGPShareRef secondShare,
6edd75 ¤   ¤   ¤   ¤   PGPShareRef *combinedShares)
37bb36 {
c8c22b ¤   PGPShareRef¤newShare = NULL;
75a0c5 ¤   PGPSize¤¤   shareSize = 0;
dca321 ¤   PGPSize¤¤   dataSize = 0;
918e12 ¤   PGPError¤   err = kPGPError_NoErr;
c9af5a
efeccb ¤   if (IsntNull(combinedShares))
901d28 ¤   ¤   *combinedShares = NULL;
a1af5a
db6122 ¤   PGPValidateParam(PGPShareRefIsValid(firstShare));
278d86 ¤   PGPValidateParam(PGPShareRefIsValid(secondShare));
1523f7 ¤   PGPValidatePtr(combinedShares);
--f7eb 00092b04d4c4010005d Page 6 of pgpShare.c
e0af5a
d203a4 ¤   if (PGPCompareKeyIDs(&(firstShare->keyID), &(secondShare->keyID)) != 0)
92e5ab ¤   ¤   return kPGPClientError_DifferentSplitKeys;
0caf5a
89deb1 ¤   if (PGPCompareShareIDs(firstShare->shareID, secondShare->shareID) != 0)
11e15e ¤   ¤   return kPGPClientError_DifferentSharePool;
c1af5a
b29c16 ¤   if (firstShare->threshold != secondShare->threshold)
b0e15e ¤   ¤   return kPGPClientError_DifferentSharePool;
9daf5a
e3e02e ¤   if (firstShare->totalShares != secondShare->totalShares)
b8e15e ¤   ¤   return kPGPClientError_DifferentSharePool;
c9af5a
9c881b ¤   if (IsSamePGPShares(firstShare, secondShare))
85b34b ¤   ¤   return kPGPClientError_IdenticalShares;
1caf5a
fd0e01 ¤   newShare = (PGPShareRef) PGPNewData(firstShare->memoryMgr,·
83a4d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPShare),·
00e0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
1baf5a
521f11 ¤   pgpAssert(IsntNull(newShare));
7d4593 ¤   if (IsNull(newShare))
b64030 ¤   ¤   return kPGPError_OutOfMemory;
8caf5a
0de6df ¤   newShare->context¤  ¤   = firstShare->context;
b2667e ¤   newShare->memoryMgr¤¤   = firstShare->memoryMgr;
a69402 ¤   newShare->threshold¤¤   = firstShare->threshold;
c9bf86 ¤   newShare->numShares¤¤   = firstShare->numShares + secondShare->numShares;
518e18 ¤   newShare->totalShares¤  = firstShare->totalShares;
383a82 ¤   newShare->shareDataSize = firstShare->shareDataSize +
b0bead ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   secondShare->shareDataSize;
edaf5a
83c4c9 ¤   pgpCopyMemory(&(firstShare->keyID), &(newShare->keyID), sizeof(PGPKeyID));
54d4e3 ¤   pgpCopyMemory(&(firstShare->shareID), &(newShare->shareID),·
524188 ¤   ¤   sizeof(PGPShareID));
35af5a
f6d67e ¤   newShare->shareData¤= (PGPByte *) PGPNewSecureData(firstShare->memoryMgr,·
b95d09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newShare->shareDataSize,·
ad7e53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
16af5a
49a62c ¤   if (IsNull(newShare->shareData))
40bce1 ¤   ¤   err = kPGPError_OutOfMemory;
97af5a
46f69b ¤   if (IsntPGPError(err))
50c7a1 ¤   {
ab754b ¤   ¤   pgpCopyMemory(firstShare->shareData, newShare->shareData,·
797e0f ¤   ¤   ¤   firstShare->shareDataSize);
84af5a
bad1de ¤   ¤   pgpCopyMemory(secondShare->shareData,·
3445df ¤   ¤   ¤   &(newShare->shareData[firstShare->shareDataSize]),
a200e4 ¤   ¤   ¤   secondShare->shareDataSize);
309371 ¤   }
2daf5a
58f69b ¤   if (IsntPGPError(err))
392733 ¤   ¤   err = sCalculateShareHash(newShare);
4eaf5a
6782f0 ¤   if (IsPGPError(err))
2dc7a1 ¤   {
3d0c1f ¤   ¤   PGPFreeShares(newShare);
df29d4 ¤   ¤   newShare = NULL;
109371 ¤   }
c9af5a
1bd18c ¤   *combinedShares = newShare;
ac5ea8 ¤   return err;
a9efe6 }
c6af5a
55af5a
68fb68 PGPError PGPFreeShares(PGPShareRef share)
1fbb36 {
37c55b ¤   PGPError err = kPGPError_NoErr;
cfaf5a
925ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
--a0a7 0004e0722a24010005d Page 7 of pgpShare.c
e0af5a
7f512c ¤   if (IsntNull(share->shareData))
7487a0 ¤   ¤   PGPFreeData(share->shareData);
e8af5a
b72909 ¤   if (IsntNull(share->shareHash))
fcff85 ¤   ¤   PGPFreeData(share->shareHash);
05af5a
d0e383 ¤   PGPFreeData(share);
a15ea8 ¤   return err;
c0efe6 }
4eaf5a
4baf5a
127091 PGPError PGPGetKeyIDFromShares(PGPShareRef share, PGPKeyID *id)
a7bb36 {
9bc55b ¤   PGPError err = kPGPError_NoErr;
2aaf5a
ab5ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
d34954 ¤   PGPValidatePtr(id);
0daf5a
c00c3e ¤   pgpCopyMemory(&(share->keyID), id, sizeof(PGPKeyID));
beaf5a
e55ea8 ¤   return err;
43efe6 }
baaf5a
adaf5a
e59af2 PGPError PGPGetShareID(PGPShareRef share, PGPShareID *id)
65bb36 {
b5c55b ¤   PGPError err = kPGPError_NoErr;
41af5a
575ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
6a4954 ¤   PGPValidatePtr(id);
3daf5a
f1ab95 ¤   pgpCopyMemory(&(share->shareID), id, sizeof(PGPShareID));
aaaf5a
f35ea8 ¤   return err;
8defe6 }
03af5a
67af5a
5aa222 PGPBoolean IsSamePGPShares(PGPShareRef firstShare, PGPShareRef secondShare)
b6bb36 {
c74ec1 ¤   PGPBoolean¤ result = FALSE;
b4e43a ¤   PGPSize¤¤   index1;
d20b5e ¤   PGPSize¤¤   index2;
5aac32 ¤   PGPSize¤¤   shareSize;
29af5a
45fe09 ¤   if (!PGPShareRefIsValid(firstShare))
5098aa ¤   ¤   return FALSE;
3b1a24 ¤   if (!PGPShareRefIsValid(secondShare))
0298aa ¤   ¤   return FALSE;
d2af5a
3c584b ¤   shareSize = firstShare->shareDataSize / firstShare->numShares;
51aa38 ¤   if (shareSize != (secondShare->shareDataSize / secondShare->numShares))
c398aa ¤   ¤   return FALSE;
85af5a
af6e9f ¤   if ((firstShare->numShares == secondShare->numShares) &&
e108f4 ¤   ¤   (firstShare->shareHashSize == secondShare->shareHashSize))
ccc7a1 ¤   {
e440b0 ¤   ¤   result = pgpMemoryEqual(firstShare->shareHash,·
4425db ¤   ¤   ¤   ¤   ¤   secondShare->shareHash, firstShare->shareHashSize);
af9371 ¤   }
d3af5a
2dafc2 ¤   if (result == FALSE)
64c7a1 ¤   {
416033 ¤   ¤   for (index1=0; index1<firstShare->numShares; index1++)
807973 ¤   ¤   ¤   for (index2=0; index2<secondShare->numShares; index2++)
b667c0 ¤   ¤   ¤   ¤   if (pgpMemoryEqual(&(firstShare->shareData[index1*shareSize]),
4df3e7 ¤   ¤   ¤   ¤   ¤   ¤   &(secondShare->shareData[index2*shareSize]),
0da851 ¤   ¤   ¤   ¤   ¤   ¤   shareSize))
ef72c3 ¤   ¤   ¤   ¤   {
8e9c3b ¤   ¤   ¤   ¤   ¤   result = TRUE;
45c989 ¤   ¤   ¤   ¤   ¤   index1 = firstShare->numShares;
4e2d98 ¤   ¤   ¤   ¤   ¤   index2 = secondShare->numShares;
--479e 000d4a3f96a4010005d Page 8 of pgpShare.c
862613 ¤   ¤   ¤   ¤   }
c69371 ¤   }
f0af5a
c15d73 ¤   return result;
66efe6 }
5eaf5a
baaf5a
17df99 /* The share data needs to be freed with PGPFreeData(shareData) */
52083b PGPError pgpGetShareData(PGPShareRef share, PGPByte **shareData,·
e886c7 ¤   ¤   ¤   ¤   PGPSize *shareDataSize)
e5bb36 {
748e12 ¤   PGPError¤   err = kPGPError_NoErr;
31af5a
02376e ¤   if (IsntNull(shareData))
7222ed ¤   ¤   *shareData = NULL;
30af5a
ffe1d3 ¤   if (IsntNull(shareDataSize))
47a412 ¤   ¤   *shareDataSize = 0;
f2af5a
a15ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
f4bffd ¤   PGPValidatePtr(shareData);
1b0c38 ¤   PGPValidatePtr(shareDataSize);
ddaf5a
a48290 ¤   *shareData = (PGPByte *) PGPNewSecureData(share->memoryMgr,·
8ef456 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   share->shareDataSize,·
d3e0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
c4af5a
bad4ca ¤   if (IsNull(*shareData))
6bbce1 ¤   ¤   err = kPGPError_OutOfMemory;
570e24 ¤   else
bfc7a1 ¤   {
2dca9e ¤   ¤   pgpCopyMemory(share->shareData, *shareData, share->shareDataSize);
07a7b1 ¤   ¤   *shareDataSize = share->shareDataSize;
899371 ¤   }
ee67c5 ¤
d65ea8 ¤   return err;
3cefe6 }
b0af5a
f3af5a
93f5a1 /* The share hash needs to be freed with PGPFreeData(shareHash) */
4896e1 PGPError pgpGetShareHash(PGPShareRef share, PGPByte **shareHash,·
3a8245 ¤   ¤   ¤   ¤   PGPSize *shareHashSize)
79bb36 {
d58e12 ¤   PGPError¤   err = kPGPError_NoErr;
1aaf5a
4a4f4b ¤   if (IsntNull(shareHash))
34fcd9 ¤   ¤   *shareHash = NULL;
8faf5a
1d46cd ¤   if (IsntNull(shareHashSize))
0ad36b ¤   ¤   *shareHashSize = 0;
41af5a
765ae5 ¤   PGPValidateParam(PGPShareRefIsValid(share));
9ec7d8 ¤   PGPValidatePtr(shareHash);
0fab26 ¤   PGPValidatePtr(shareHashSize);
6faf5a
f26186 ¤   *shareHash = (PGPByte *) PGPNewData(share->memoryMgr,·
6f5348 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   share->shareHashSize,·
30e0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
6eaf5a
1eacef ¤   if (IsNull(*shareHash))
a4bce1 ¤   ¤   err = kPGPError_OutOfMemory;
110e24 ¤   else
13c7a1 ¤   {
e5d513 ¤   ¤   pgpCopyMemory(share->shareHash, *shareHash, share->shareHashSize);
c2dd40 ¤   ¤   *shareHashSize = share->shareHashSize;
9e9371 ¤   }
7267c5 ¤
505ea8 ¤   return err;
45efe6 }
40af5a
81af5a
d4ea3f PGPUInt32 PGPGetShareThreshold(PGPShareRef share)
--2508 000bb95047e4010005d Page 9 of pgpShare.c
2cbb36 {
2dfc15 ¤   if (PGPShareRefIsValid(share))
f36a36 ¤   ¤   return share->threshold;
100e24 ¤   else
11bbde ¤   ¤   return 0;
1fefe6 }
cfaf5a
f6af5a
cf5d9a /* This is the number of shares contained in the share object */
753f38 PGPUInt32 PGPGetNumberOfShares(PGPShareRef share)
b1bb36 {
13fc15 ¤   if (PGPShareRefIsValid(share))
f46c41 ¤   ¤   return share->numShares;
bc0e24 ¤   else
5abbde ¤   ¤   return 0;
06efe6 }
a2af5a
acaf5a
f78d72 /* The share object may contain less than the total number of shares */
9e31b4 PGPUInt32 PGPGetTotalNumberOfShares(PGPShareRef share)
91bb36 {
b8fc15 ¤   if (PGPShareRefIsValid(share))
cf2dd8 ¤   ¤   return share->totalShares;
8d0e24 ¤   else
0fbbde ¤   ¤   return 0;
65efe6 }
9faf5a
1daf5a
30e93f PGPInt32 PGPCompareShareIDs(PGPShareID firstID, PGPShareID secondID)
c5bb36 {
1ad012 ¤   PGPInt32 index;
e50a72 ¤   PGPInt32 result = 0;
79af5a
b4a7a1 ¤   for (index=sizeof(firstID.data)-1; index>=0; index--)
37c7a1 ¤   {
461c80 ¤   ¤   if (firstID.data[index] < secondID.data[index])
475b34 ¤   ¤   {
82362c ¤   ¤   ¤   result = -1;
8a3d3a ¤   ¤   ¤   index = -1;
9f0fe4 ¤   ¤   }
6f9976 ¤   ¤   else if (firstID.data[index] > secondID.data[index])
c85b34 ¤   ¤   {
916a01 ¤   ¤   ¤   result = 1;
0d3d3a ¤   ¤   ¤   index = -1;
6b0fe4 ¤   ¤   }
ac9371 ¤   }
b2af5a
865d73 ¤   return result;
5fefe6 }
75af5a
c4af5a
f14a1e static PGPError sCalculateShareHash(PGPShareRef share)
eebb36 {
2474f1 ¤   PGPHashContextRef¤  hash = NULL;
e534db ¤   PGPByte¤¤   ¤   ¤   nullByte = 0;
e07d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
12af5a
aa181b ¤   err = PGPNewHashContext(share->memoryMgr, kPGPHashAlgorithm_SHA, &hash);
c7af5a
ebf69b ¤   if (IsntPGPError(err))
dbc7a1 ¤   {
3eb1bf ¤   ¤   PGPGetHashSize(hash, &(share->shareHashSize));
41af5a
36f29f ¤   ¤   share->shareHash = (PGPByte *) PGPNewData(share->memoryMgr,
b2f64b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   share->shareHashSize,
4e7e53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
489371 ¤   }
43af5a
c00f39 ¤   if (IsNull(share->shareHash))
07bce1 ¤   ¤   err = kPGPError_OutOfMemory;
b5af5a
bbf69b ¤   if (IsntPGPError(err))
--1f66 00137db85f24010005d Page 10 of pgpShare.c
f7c7a1 ¤   {
199479 ¤   ¤   if (IsntNull(share->shareData))
8bc13d ¤   ¤   ¤   PGPContinueHash(hash, share->shareData, share->shareDataSize);
c20e1d ¤   ¤   else
fc8b19 ¤   ¤   ¤   PGPContinueHash(hash, &nullByte, sizeof(nullByte));
f9af5a
8e25c6 ¤   ¤   PGPFinalizeHash(hash, share->shareHash);
9c9371 ¤   }
56af5a
60ec1b ¤   if (IsntNull(hash))
07694d ¤   ¤   PGPFreeHashContext(hash);
7caf5a
8b5ea8 ¤   return err;
7fefe6 }
59af5a
e6af5a
b87e4d /*__Editor_settings____
b9af5a
a14126 ¤   Local Variables:
4f7b17 ¤   tab-width: 4
830e6c ¤   End:
305f8c ¤   vi: ts=4 sw=4
509e9b ¤   vim: si
08d062 _____________________*/
03af5a
37af5a
--ff76 000f0deafce4010005e Page 1 of pgpShare.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
f6a710 ¤   $Id: pgpShare.h,v 1.5.8.1 1998/11/12 03:11:13 heller Exp $
8ff7f7 ____________________________________________________________________________*/
633f45 #ifndef Included_pgpShare_h¤/* [ */
713cd0 #define Included_pgpShare_h
9daf5a
fce2ff #include "pgpConfig.h"
00c5d5 #include "pgpBase.h"
1b628e #include "pgpClientErrors.h"
3aa076 #include "pgpKeys.h"
d7af5a
1ea776 typedef struct PGPShare *¤  PGPShareRef;
3faf5a
64097d typedef struct PGPShareID_
4cbb36 {
bbcfcb ¤   PGPByte ¤   data[8];
8e7cdb } PGPShareID;
59af5a
ab2488 #define¤kInvalidPGPShareRef¤¤   ¤   ((PGPShareRef) NULL)
a3bd25 #define PGPShareRefIsValid( ref )¤  ( (ref) != kInvalidPGPShareRef )
ddaf5a
3599c6 PGP_BEGIN_C_DECLARATIONS
56cbcf #if PRAGMA_IMPORT_SUPPORTED
06b981 #pragma import on
137454 #endif
85af5a
ac0c59 PGPError PGPCreateShares(PGPContextRef context, PGPKeyRef key,·
5863b9 ¤   ¤   ¤   ¤   PGPUInt32 threshold, PGPUInt32 numShares,·
0fadb0 ¤   ¤   ¤   ¤   PGPShareRef *share);
b1af5a
d761d2 /* The passkey needs to be freed with PGPFreeData(passkey) */
3c8159 PGPError PGPGetPasskeyFromShares(PGPShareRef share, PGPByte **passkey,
da6ea1 ¤   ¤   ¤   ¤   PGPSize *passkeySize);
55af5a
7ea527 PGPError PGPSplitShares(PGPShareRef share, PGPUInt32 numShares,·
d35f71 ¤   ¤   ¤   ¤   PGPShareRef *splitShares);
76af5a
8ecff1 /* The share objects being combined are NOT freed by this function */
048811 PGPError PGPCombineShares(PGPShareRef firstShare, PGPShareRef secondShare,
8a24d7 ¤   ¤   ¤   ¤   PGPShareRef *combinedShares);
01af5a
66ef95 PGPError PGPFreeShares(PGPShareRef share);
1aaf5a
108550 PGPError PGPGetKeyIDFromShares(PGPShareRef share, PGPKeyID *id);
b6af5a
dcd427 PGPError PGPGetShareID(PGPShareRef share, PGPShareID *id);
1daf5a
10c9be PGPUInt32 PGPGetShareThreshold(PGPShareRef share);
afaf5a
3a5d9a /* This is the number of shares contained in the share object */
76bdd4 PGPUInt32 PGPGetNumberOfShares(PGPShareRef share);
bfaf5a
a98d72 /* The share object may contain less than the total number of shares */
d5f3be PGPUInt32 PGPGetTotalNumberOfShares(PGPShareRef share);
61af5a
2e0292 PGPBoolean IsSamePGPShares(PGPShareRef firstShare, PGPShareRef secondShare);
76af5a
10ab35 /* If firstID < secondID, -1 */
863cf6 /* If firstID > secondID, ·1 */
b2368a /* If firstID = secondID, ·0 */
59c9bd PGPInt32 PGPCompareShareIDs(PGPShareID firstID, PGPShareID secondID);
b4af5a
62cbcf #if PRAGMA_IMPORT_SUPPORTED
732ced #pragma import reset
6a7454 #endif
d11254 PGP_END_C_DECLARATIONS
f0af5a
--de46 00136c028d94010005e Page 2 of pgpShare.h
b1a067 #endif /* ] Included_pgpShare_h */
09af5a
68af5a
397e4d /*__Editor_settings____
6eaf5a
394126 ¤   Local Variables:
ed7b17 ¤   tab-width: 4
4f0e6c ¤   End:
a85f8c ¤   vi: ts=4 sw=4
0b9e9b ¤   vim: si
36d062 _____________________*/
--f63e 000b71311b34010005f Page 1 of pgpShareFile.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
54637f ¤   $Id: pgpShareFile.c,v 1.7.8.1 1998/11/12 03:11:13 heller Exp $
55f7f7 ____________________________________________________________________________*/
d8add5 #include "pgpShareFile.h"
c9955c #include "pgpSharePriv.h"
f76773 #include "pgpMemoryMgr.h"
1f3427 #include "pgpFileUtilities.h"
96fb31 #include "pgpOptionList.h"
cd9f63 #include "pgpEncode.h"
820d08 #include "pgpMem.h"
83a146 #include "pgpDebug.h"
e73d4b #include "pgpEndianConversion.h"
d7af5a
ad324c #include <string.h>
caaf5a
254d5b typedef struct PGPShareFile¤¤   PGPShareFile;
39af5a
b2dc5e struct PGPShareFile
5bbb36 {
c2d91c ¤   PGPMemoryMgrRef¤memoryMgr;
5b9c2a ¤   PFLFileSpecRef¤ shareFileSpec;
d9af5a
700b26 ¤   char *¤ ¤   ¤   userID;
810913 ¤   void *¤ ¤   ¤   fingerprint;
2e1015 ¤   PGPSize¤¤   ¤   fingerprintSize;
e7c0ff ¤   PGPKeyID¤   ¤   keyID;
6a287c ¤   PGPKeyID¤   ¤   sharedKeyID;
8811d8 ¤   PGPShareID¤ ¤   shareID;
077d89 ¤   PGPUInt32¤  ¤   threshold;
ce7bfe ¤   PGPUInt32¤  ¤   numShares;
21f040 ¤   PGPUInt32¤  ¤   totalShares;
216559 ¤   PGPSize¤¤   ¤   decryptedShareSize;
784500 ¤   PGPSize¤¤   ¤   shareDataSize;
6452e0 ¤   PGPByte¤*¤  ¤   shareData;
384182 ¤   PGPSize¤¤   ¤   shareHashSize;
f900ec ¤   PGPByte *¤  ¤   shareHash;
ee82f7 };
78af5a
3af3b4 #define PGPValidateShareFile(ref)¤  PGPValidateParam(ref != NULL)
8daf5a
41c39d #define kPGPShareFileEndian¤¤   kPGPBigEndian
57d1e6 #define kPGPShareFileMagic¤ ¤   0x15607AED
3daf5a
b786cd static void sCalcShareFileSize(PGPShareFileRef shareFileRef,·
fd77c3 ¤   ¤   ¤   ¤   PGPUInt32 *fileSize);
80af5a
2d9dc4 static PGPError sIORead(PGPIORef fileIO, PGPSize dataSize,·
47cfaf ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, void *data);
6aaf5a
85b882 static PGPError sIOWrite(PGPIORef fileIO, PGPSize dataSize,·
5ade04 ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, const void *data);
9baf5a
cfaf5a
8bc460 PGPError PGPNewShareFile(PFLFileSpecRef shareFileSpec,·
23ad7c ¤   ¤   ¤   ¤   PGPShareFileRef *shareFileRef)
52bb36 {
67f0bf ¤   PGPMemoryMgrRef¤memoryMgr¤  = NULL;
af3ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
30af5a
9c4478 ¤   if (IsntNull(shareFileRef))
f1b436 ¤   ¤   *shareFileRef = NULL;
a4af5a
566480 ¤   PGPValidatePtr(shareFileRef);
758dee ¤   PFLValidateFileSpec(shareFileSpec);
d3af5a
9c482f ¤   memoryMgr = PFLGetFileSpecMemoryMgr(shareFileSpec);
b767c5 ¤
--db33 000df984cc04010005f Page 2 of pgpShareFile.c
e1ae4e ¤   pgpAssert(PGPMemoryMgrIsValid(memoryMgr));
85dbbb ¤   if (!PGPMemoryMgrIsValid(memoryMgr))
cf62b5 ¤   ¤   return kPGPError_BadParams;
6baf5a
4c21e7 ¤   *shareFileRef = (PGPShareFileRef) PGPNewData(memoryMgr,·
9826a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPShareFile),·
ce6ddf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
6aaf5a
f4cb6b ¤   pgpAssert(IsntNull(*shareFileRef));
5deb3f ¤   if (IsNull(*shareFileRef))
0c4030 ¤   ¤   return kPGPError_OutOfMemory;
79af5a
33047d ¤   (*shareFileRef)->memoryMgr¤ ¤   ¤   = memoryMgr;
62fe97 ¤   (*shareFileRef)->shareFileSpec¤ ¤   = NULL;
9e2ae2 ¤   (*shareFileRef)->userID¤¤   ¤   ¤   = NULL;
c26e05 ¤   (*shareFileRef)->fingerprint¤   ¤   = NULL;
75c87f ¤   (*shareFileRef)->fingerprintSize¤   = 0;
5eb324 ¤   (*shareFileRef)->threshold¤ ¤   ¤   = 0;
67208b ¤   (*shareFileRef)->numShares¤ ¤   ¤   = 0;
55b17f ¤   (*shareFileRef)->totalShares¤   ¤   = 0;
fa32b8 ¤   (*shareFileRef)->decryptedShareSize¤= 0;
ccd846 ¤   (*shareFileRef)->shareDataSize¤ ¤   = 0;
979bfe ¤   (*shareFileRef)->shareData¤ ¤   ¤   = NULL;
0291b5 ¤   (*shareFileRef)->shareHashSize¤ ¤   = 0;
a669d0 ¤   (*shareFileRef)->shareHash¤ ¤   ¤   = NULL;
9faf5a
816c28 ¤   err = PFLCopyFileSpec(shareFileSpec, &((*shareFileRef)->shareFileSpec));
4782f0 ¤   if (IsPGPError(err))
41c7a1 ¤   {
4264c4 ¤   ¤   PGPFreeShareFile(*shareFileRef);
c0b436 ¤   ¤   *shareFileRef = NULL;
8dc9db ¤   ¤   return err;
389371 ¤   }
24af5a
3ba2cd ¤   return err;¤¤
14efe6 }
1faf5a
44af5a
1e11f8 PGPError PGPFreeShareFile(PGPShareFileRef shareFileRef)
bdbb36 {
d18e12 ¤   PGPError¤   err = kPGPError_NoErr;
e4af5a
077823 ¤   PGPValidateShareFile(shareFileRef);
14af5a
372e75 ¤   if (pflFileSpecIsValid(shareFileRef->shareFileSpec))
07c729 ¤   ¤   PFLFreeFileSpec(shareFileRef->shareFileSpec);
65af5a
fd61ef ¤   if (shareFileRef->userID != NULL)
6a997b ¤   ¤   PGPFreeData(shareFileRef->userID);
5daf5a
28e656 ¤   if (shareFileRef->fingerprint != NULL)
9c5727 ¤   ¤   PGPFreeData(shareFileRef->fingerprint);
dbaf5a
d469ac ¤   if (shareFileRef->shareData != NULL)
3edd77 ¤   ¤   PGPFreeData(shareFileRef->shareData);
74af5a
3d1ed5 ¤   if (shareFileRef->shareHash != NULL)
68a552 ¤   ¤   PGPFreeData(shareFileRef->shareHash);
52af5a
4b974f ¤   PGPFreeData(shareFileRef);
bd5ea8 ¤   return err;
18efe6 }
68af5a
33af5a
9f8caf /* The share object needs to be freed with PGPFreeShares(shares) */
285ac1 PGPError PGPCopySharesFromFile(PGPContextRef context,·
9daf11 ¤   ¤   ¤   ¤   PGPShareFileRef shareFileRef, PGPOptionListRef optionList,
6ffb08 ¤   ¤   ¤   ¤   PGPShareRef *shares)
8fbb36 {
4e26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
11c22b ¤   PGPShareRef¤newShare = NULL;
df0038 ¤   PGPByte *¤  shareData = NULL;
--ce40 0003c8854854010005f Page 3 of pgpShareFile.c
a28a86 ¤   PGPSize¤¤   actualSize = 0;
acaf5a
ba4749 ¤   if (IsntNull(shares))
96f4cc ¤   ¤   *shares = NULL;
a1af5a
b24ecd ¤   PGPValidateParam(PGPContextRefIsValid(context));
657823 ¤   PGPValidateShareFile(shareFileRef);
d0aa70 ¤   PGPValidateParam(PGPOptionListRefIsValid(optionList));
94f5ae ¤   PGPValidatePtr(shares);
e3af5a
ab2195 ¤   if (shareFileRef->shareDataSize == 0)
4bb840 ¤   ¤   return kPGPError_NoErr;
7daf5a
e1801b ¤   shareData = (PGPByte *) PGPNewSecureData(shareFileRef->memoryMgr,
ccdc07 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   shareFileRef->decryptedShareSize,
7de0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
37af5a
478330 ¤   if (IsNull(shareData))
3bbce1 ¤   ¤   err = kPGPError_OutOfMemory;
6aaf5a
72f69b ¤   if (IsntPGPError(err))
df10d3 ¤   ¤   err = PGPDecode(context,
6805af ¤   ¤   ¤   ¤   PGPOInputBuffer(context,·
88d79a ¤   ¤   ¤   ¤   ¤   shareFileRef->shareData,·
d31d1e ¤   ¤   ¤   ¤   ¤   shareFileRef->shareDataSize),
49e07c ¤   ¤   ¤   ¤   PGPOOutputBuffer(context,·
ead980 ¤   ¤   ¤   ¤   ¤   shareData,·
818169 ¤   ¤   ¤   ¤   ¤   shareFileRef->decryptedShareSize,
0b2e6d ¤   ¤   ¤   ¤   ¤   &actualSize),
8a2d4c ¤   ¤   ¤   ¤   optionList,
e5d911 ¤   ¤   ¤   ¤   PGPOLastOption(context));
02af5a
edf69b ¤   if (IsntPGPError(err))
26c7a1 ¤   {
b0d35e ¤   ¤   pgpAssert(actualSize == shareFileRef->decryptedShareSize);
631b52 ¤   ¤
bdf084 ¤   ¤   if (actualSize == 0)
7cdf00 ¤   ¤   ¤   err = kPGPError_BadPassphrase;
4fa666 ¤   ¤   else if (actualSize != shareFileRef->decryptedShareSize)
407ce1 ¤   ¤   ¤   err = kPGPError_CorruptData;
a49371 ¤   }
9aaf5a
5af69b ¤   if (IsntPGPError(err))
22c201 ¤   ¤   pgpCreateShares(context, shareFileRef->sharedKeyID,
4e72ea ¤   ¤   ¤   shareFileRef->shareID, shareFileRef->threshold,·
1f70a6 ¤   ¤   ¤   shareFileRef->numShares, shareFileRef->totalShares,·
2ee385 ¤   ¤   ¤   shareFileRef->decryptedShareSize, shareData, &newShare);
49af5a
5282f0 ¤   if (IsPGPError(err))
2fc7a1 ¤   {
91356c ¤   ¤   if (IsntNull(newShare))
5e5b34 ¤   ¤   {
4f3177 ¤   ¤   ¤   PGPFreeShares(newShare);
431d89 ¤   ¤   ¤   newShare = NULL;
230fe4 ¤   ¤   }
659371 ¤   }
a6af5a
13376e ¤   if (IsntNull(shareData))
3f33fc ¤   ¤   PGPFreeData(shareData);
2faf5a
b4ffcc ¤   *shares = newShare;
995ea8 ¤   return err;
ffefe6 }
38af5a
04af5a
cbf10b PGPError PGPCopySharesToFile(PGPContextRef context,
55af11 ¤   ¤   ¤   ¤   PGPShareFileRef shareFileRef, PGPOptionListRef optionList,
c6c0da ¤   ¤   ¤   ¤   PGPShareRef shares)
4ebb36 {
060038 ¤   PGPByte *¤  shareData = NULL;
42a321 ¤   PGPSize¤¤   dataSize = 0;
3c26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
--97a4 00066e4a1ef4010005f Page 4 of pgpShareFile.c
e0af5a
504ecd ¤   PGPValidateParam(PGPContextRefIsValid(context));
227823 ¤   PGPValidateShareFile(shareFileRef);
3caa70 ¤   PGPValidateParam(PGPOptionListRefIsValid(optionList));
cfb93e ¤   PGPValidateParam(PGPShareRefIsValid(shares));
27af5a
1a69ac ¤   if (shareFileRef->shareData != NULL)
bdc7a1 ¤   {
bfdd77 ¤   ¤   PGPFreeData(shareFileRef->shareData);
203709 ¤   ¤   shareFileRef->shareData = NULL;
d69371 ¤   }
5caf5a
50fdac ¤   err = pgpGetShareData(shares, &shareData, &dataSize);
2daf5a
cbf69b ¤   if (IsntPGPError(err))
9d17cf ¤   ¤   err = PGPEncode(context,
ab28bd ¤   ¤   ¤   ¤   PGPOInputBuffer(context, shareData, dataSize),
fde6f1 ¤   ¤   ¤   ¤   PGPOAllocatedOutputBuffer(context,·
05d2d2 ¤   ¤   ¤   ¤   ¤   &(shareFileRef->shareData),·
d18421 ¤   ¤   ¤   ¤   ¤   INT_MAX,·
845789 ¤   ¤   ¤   ¤   ¤   &(shareFileRef->shareDataSize)),
822d4c ¤   ¤   ¤   ¤   optionList,
30d911 ¤   ¤   ¤   ¤   PGPOLastOption(context));
5baf5a
f2f69b ¤   if (IsntPGPError(err))
e1c7a1 ¤   {
290dc1 ¤   ¤   if( IsntNull( shareFileRef->shareHash ) )
cf5b34 ¤   ¤   {
5980a9 ¤   ¤   ¤   PGPFreeData( shareFileRef->shareHash );
96615b ¤   ¤   ¤   shareFileRef->shareHash = NULL;
860fe4 ¤   ¤   }
5b1b52 ¤   ¤
bb099f ¤   ¤   err = pgpGetShareHash(shares, &(shareFileRef->shareHash),
762553 ¤   ¤   ¤   ¤   &(shareFileRef->shareHashSize));
309371 ¤   }
13af5a
e382f0 ¤   if (IsPGPError(err))
cdc7a1 ¤   {
036f14 ¤   ¤   if (shareFileRef->shareData != NULL)
215b34 ¤   ¤   {
fa9249 ¤   ¤   ¤   PGPFreeData(shareFileRef->shareData);
53bf6f ¤   ¤   ¤   shareFileRef->shareData = NULL;
4d0fe4 ¤   ¤   }
2daf5a
25186d ¤   ¤   if (shareFileRef->shareHash != NULL)
765b34 ¤   ¤   {
6cea6c ¤   ¤   ¤   PGPFreeData(shareFileRef->shareHash);
b7615b ¤   ¤   ¤   shareFileRef->shareHash = NULL;
a10fe4 ¤   ¤   }
14af5a
28f5ab ¤   ¤   shareFileRef->decryptedShareSize = 0;
e2052d ¤   ¤   shareFileRef->shareDataSize = 0;
b77254 ¤   ¤   shareFileRef->shareHashSize = 0;
bbf9d2 ¤   ¤   shareFileRef->threshold = 0;
39226f ¤   ¤   shareFileRef->numShares = 0;
3ee94f ¤   ¤   shareFileRef->totalShares = 0;
429371 ¤   }
190e24 ¤   else
aec7a1 ¤   {
bef1ee ¤   ¤   shareFileRef->decryptedShareSize = dataSize;
003429 ¤   ¤   shareFileRef->threshold = PGPGetShareThreshold(shares);
4a704a ¤   ¤   shareFileRef->numShares = PGPGetNumberOfShares(shares);
794d3c ¤   ¤   shareFileRef->totalShares = PGPGetTotalNumberOfShares(shares);
471b52 ¤   ¤
7ffdde ¤   ¤   PGPGetKeyIDFromShares(shares, &(shareFileRef->sharedKeyID));
c40ae5 ¤   ¤   PGPGetShareID(shares, &(shareFileRef->shareID));
869371 ¤   }
c4af5a
749ea2 ¤   PGPFreeData(shareData);
5d5ea8 ¤   return err;
e2efe6 }
66af5a
--4792 00055e615d44010005f Page 5 of pgpShareFile.c
e0af5a
3d5f5c PGPError PGPGetShareFileUserID(PGPShareFileRef shareFileRef,
3fa7e0 ¤   ¤   ¤   ¤   PGPSize bufferSize, char *userID, PGPSize *fullSize)
2cbb36 {
948e12 ¤   PGPError¤   err = kPGPError_NoErr;
96cca1 ¤   PGPSize¤¤   userIDSize;
adaf5a
a37c46 ¤   if (IsntNull(userID))
9b4844 ¤   ¤   *userID = '\0';
162719 ¤   if (IsntNull(fullSize))
766bc3 ¤   ¤   *fullSize = 0;
b9af5a
ad7823 ¤   PGPValidateShareFile(shareFileRef);
aafb2f ¤   PGPValidateParam(bufferSize > 0);
0ccea1 ¤   PGPValidatePtr(userID);
deaf5a
c50f20 ¤   if (IsNull(shareFileRef->userID))
01b840 ¤   ¤   return kPGPError_NoErr;
71af5a
01249c ¤   if (bufferSize < strlen(shareFileRef->userID) + 1)
9224c2 ¤   ¤   userIDSize = bufferSize;
300e24 ¤   else
f8c27d ¤   ¤   userIDSize = strlen(shareFileRef->userID) + 1;
66af5a
2be2ac ¤   pgpCopyMemory(shareFileRef->userID, userID, userIDSize);
7d8e74 ¤   userID[userIDSize-1] = 0;
01af5a
86f4cf ¤   if (fullSize != NULL)
1206ff ¤   ¤   *fullSize = strlen(shareFileRef->userID) + 1;
40af5a
7e249c ¤   if (bufferSize < strlen(shareFileRef->userID) + 1)
b95974 ¤   ¤   err = kPGPError_BufferTooSmall;
f8af5a
345ea8 ¤   return err;
23efe6 }
5daf5a
39af5a
0894f2 PGPError PGPSetShareFileUserID(PGPShareFileRef shareFileRef,
fbcf58 ¤   ¤   ¤   ¤   const char *userID)
3abb36 {
528e12 ¤   PGPError¤   err = kPGPError_NoErr;
d8af5a
d47823 ¤   PGPValidateShareFile(shareFileRef);
1acea1 ¤   PGPValidatePtr(userID);
f3af5a
9761ef ¤   if (shareFileRef->userID != NULL)
11997b ¤   ¤   PGPFreeData(shareFileRef->userID);
b8af5a
5e10bd ¤   shareFileRef->userID = (char *) PGPNewData(shareFileRef->memoryMgr,
407718 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen(userID)+1,
396ddf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
c9af5a
57de54 ¤   if (shareFileRef->userID == NULL)
924030 ¤   ¤   return kPGPError_OutOfMemory;
afaf5a
52e96c ¤   pgpCopyMemory(userID, shareFileRef->userID, strlen(userID)+1);
315ea8 ¤   return err;
a4efe6 }
16af5a
86af5a
c90831 PGPError PGPOpenShareFile(PFLFileSpecRef shareFileSpec,·
8bad7c ¤   ¤   ¤   ¤   PGPShareFileRef *shareFileRef)
7ebb36 {
088e12 ¤   PGPError¤   err = kPGPError_NoErr;
bc1e95 ¤   PGPIORef¤   fileIO;
50829d ¤   PGPSize¤¤   dataSize;
d3b3cd ¤   PGPUInt32¤  magic;
f0af5a
606801 ¤   err = PGPNewShareFile(shareFileSpec, shareFileRef);
4b82f0 ¤   if (IsPGPError(err))
e3c9db ¤   ¤   return err;
55af5a
--e0bb 00060892d3e4010005f Page 6 of pgpShareFile.c
1fb7de ¤   err = PGPOpenFileSpec(¤ (*shareFileRef)->shareFileSpec,·
1f241d ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPFLFileOpenFlags_ReadOnly,·
0c58a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPFileIORef *) &fileIO);
ab82f0 ¤   if (IsPGPError(err))
73c9db ¤   ¤   return err;
c5af5a
716e34 ¤   err = sIORead(fileIO, sizeof(PGPUInt32), TRUE, &magic);
1cf621 ¤   if (magic != kPGPShareFileMagic)
57790c ¤   ¤   err = kPGPError_CorruptData;
a8af5a
c8f69b ¤   if (IsntPGPError(err))
06bfca ¤   ¤   err = sIORead(fileIO, sizeof(PGPSize), TRUE, &dataSize);
0aaf5a
c7ba09 ¤   if (IsntPGPError(err) && (dataSize > 0))
97c7a1 ¤   {
0296da ¤   ¤   (*shareFileRef)->userID = (char *)·
9575fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPNewData((*shareFileRef)->memoryMgr,
e017c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize,
b2e023 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
97af5a
623726 ¤   ¤   if ((*shareFileRef)->userID != NULL)
04e26d ¤   ¤   ¤   err = sIORead(fileIO, dataSize, FALSE,·
084d5e ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->userID);
640e1d ¤   ¤   else
03b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
359371 ¤   }
d2af5a
14f69b ¤   if (IsntPGPError(err))
65c7a1 ¤   {
41bfca ¤   ¤   err = sIORead(fileIO, sizeof(PGPSize), TRUE, &dataSize);
591851 ¤   ¤   (*shareFileRef)->fingerprintSize = dataSize;
2c9371 ¤   }
55af5a
78ba09 ¤   if (IsntPGPError(err) && (dataSize > 0))
77c7a1 ¤   {
3deb59 ¤   ¤   (*shareFileRef)->fingerprint = (char *)·
da75fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPNewData((*shareFileRef)->memoryMgr,
d117c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize,
ebe023 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
10af5a
9262c9 ¤   ¤   if ((*shareFileRef)->fingerprint != NULL)
96e26d ¤   ¤   ¤   err = sIORead(fileIO, dataSize, FALSE,·
949b76 ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->fingerprint);
fb0e1d ¤   ¤   else
fbb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
0e9371 ¤   }
c867c5 ¤
6ff69b ¤   if (IsntPGPError(err))
84b795 ¤   ¤   err = sIORead(fileIO, sizeof(PGPKeyID), FALSE,
bfb51d ¤   ¤   ¤   ¤   &((*shareFileRef)->keyID));
3daf5a
61f69b ¤   if (IsntPGPError(err))
72b795 ¤   ¤   err = sIORead(fileIO, sizeof(PGPKeyID), FALSE,
75abea ¤   ¤   ¤   ¤   &((*shareFileRef)->sharedKeyID));
a1af5a
35f69b ¤   if (IsntPGPError(err))
f8fa6e ¤   ¤   err = sIORead(fileIO, sizeof(PGPShareID), FALSE,
9178f0 ¤   ¤   ¤   ¤   &((*shareFileRef)->shareID));
3baf5a
72f69b ¤   if (IsntPGPError(err))
66ffe6 ¤   ¤   err = sIORead(fileIO, sizeof(PGPUInt32), TRUE,
d33bc8 ¤   ¤   ¤   ¤   &((*shareFileRef)->threshold));
39af5a
77f69b ¤   if (IsntPGPError(err))
c0ffe6 ¤   ¤   err = sIORead(fileIO, sizeof(PGPUInt32), TRUE,
b0e332 ¤   ¤   ¤   ¤   &((*shareFileRef)->numShares));
deaf5a
04f69b ¤   if (IsntPGPError(err))
62ffe6 ¤   ¤   err = sIORead(fileIO, sizeof(PGPUInt32), TRUE,
57b287 ¤   ¤   ¤   ¤   &((*shareFileRef)->totalShares));
bcaf5a
60f69b ¤   if (IsntPGPError(err))
--c723 00093329df14010005f Page 7 of pgpShareFile.c
008971 ¤   ¤   err = sIORead(fileIO, sizeof(PGPSize), TRUE,
0a710e ¤   ¤   ¤   ¤   &((*shareFileRef)->decryptedShareSize));
45af5a
60f69b ¤   if (IsntPGPError(err))
018971 ¤   ¤   err = sIORead(fileIO, sizeof(PGPSize), TRUE,
138e18 ¤   ¤   ¤   ¤   &((*shareFileRef)->shareDataSize));
7caf5a
afab7b ¤   if (IsntPGPError(err) && ((*shareFileRef)->shareDataSize > 0) &&
371cb4 ¤   ¤   ((*shareFileRef)->numShares > 0))
91c7a1 ¤   {
4762bd ¤   ¤   (*shareFileRef)->shareData = (PGPByte *) PGPNewData(
87c9e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->memoryMgr,·
f8890f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->shareDataSize,·
be6ddf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
d867c5 ¤
55780f ¤   ¤   if ((*shareFileRef)->shareData != NULL)
8d9db2 ¤   ¤   ¤   err = sIORead(fileIO, (*shareFileRef)->shareDataSize, FALSE,
4bdfaa ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->shareData);
750e1d ¤   ¤   else
deb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
f59371 ¤   }
cbaf5a
07f69b ¤   if (IsntPGPError(err))
cc8971 ¤   ¤   err = sIORead(fileIO, sizeof(PGPSize), TRUE,
ce7740 ¤   ¤   ¤   ¤   &((*shareFileRef)->shareHashSize));
42af5a
a19e70 ¤   if (IsntPGPError(err) && ((*shareFileRef)->shareHashSize > 0))
3fc7a1 ¤   {
8f06a5 ¤   ¤   (*shareFileRef)->shareHash = (PGPByte *) PGPNewData(
16c9e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->memoryMgr,·
9d2e11 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->shareHashSize,·
f86ddf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
b967c5 ¤
ad0f76 ¤   ¤   if ((*shareFileRef)->shareHash != NULL)
063cb8 ¤   ¤   ¤   err = sIORead(fileIO, (*shareFileRef)->shareHashSize, FALSE,
f3a78f ¤   ¤   ¤   ¤   ¤   (*shareFileRef)->shareHash);
c70e1d ¤   ¤   else
98b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
2a9371 ¤   }
f1af5a
ca9ad6 ¤   PGPFreeIO(fileIO);
5382f0 ¤   if (IsPGPError(err))
e5c7a1 ¤   {
7464c4 ¤   ¤   PGPFreeShareFile(*shareFileRef);
54b436 ¤   ¤   *shareFileRef = NULL;
33c9db ¤   ¤   return err;
ed9371 ¤   }
3caf5a
275ea8 ¤   return err;
a7efe6 }
90af5a
e6af5a
1b2d9c PGPError PGPSaveShareFile(PGPShareFileRef shareFileRef)
e3bb36 {
128e12 ¤   PGPError¤   err = kPGPError_NoErr;
6f1e95 ¤   PGPIORef¤   fileIO;
b9ae40 ¤   PGPUInt32¤  fileSize;
e4829d ¤   PGPSize¤¤   dataSize;
9db3cd ¤   PGPUInt32¤  magic;
f6af5a
847823 ¤   PGPValidateShareFile(shareFileRef);
fbaf5a
6e576d ¤   sCalcShareFileSize(shareFileRef, &fileSize);
3ad4a4 ¤   err = PGPSetFileSize(shareFileRef->shareFileSpec, fileSize);
6baf5a
a282f0 ¤   if (IsPGPError(err))
88c9db ¤   ¤   return err;
38af5a
10726a ¤   err = PGPOpenFileSpec(¤ shareFileRef->shareFileSpec,·
cbbb63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPFLFileOpenFlags_ReadWrite,·
3c58a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPFileIORef *) &fileIO);
9382f0 ¤   if (IsPGPError(err))
--8a53 000179a699b4010005f Page 8 of pgpShareFile.c
86c9db ¤   ¤   return err;
abaf5a
045520 ¤   magic = kPGPShareFileMagic;
f43cff ¤   err = sIOWrite(fileIO, sizeof(PGPUInt32), TRUE, &magic);
ddaf5a
9e9630 ¤   if (IsntNull(shareFileRef->userID))
7d58a0 ¤   ¤   dataSize = strlen(shareFileRef->userID) + 1;
000e24 ¤   else
9d98b3 ¤   ¤   dataSize = 0;
3aaf5a
35f69b ¤   if (IsntPGPError(err))
7da177 ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPSize), TRUE, &dataSize);
64af5a
6bba09 ¤   if (IsntPGPError(err) && (dataSize > 0))
0a244a ¤   ¤   err = sIOWrite(fileIO, dataSize, FALSE,
473570 ¤   ¤   ¤   ¤   shareFileRef->userID);
1e67c5 ¤
99f69b ¤   if (IsntPGPError(err))
d005c1 ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPSize), TRUE,·
d71fd4 ¤   ¤   ¤   ¤   &(shareFileRef->fingerprintSize));
eaaf5a
4ab5c2 ¤   if (IsntPGPError(err) && (shareFileRef->fingerprintSize > 0))
68d2e2 ¤   ¤   err = sIOWrite(fileIO, shareFileRef->fingerprintSize, FALSE,
8f25c2 ¤   ¤   ¤   ¤   shareFileRef->fingerprint);
af67c5 ¤
94f69b ¤   if (IsntPGPError(err))
5a188d ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPKeyID), FALSE,
d137c9 ¤   ¤   ¤   ¤   &(shareFileRef->keyID));
faaf5a
78f69b ¤   if (IsntPGPError(err))
c1188d ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPKeyID), FALSE,
8d6258 ¤   ¤   ¤   ¤   &(shareFileRef->sharedKeyID));
a6af5a
93f69b ¤   if (IsntPGPError(err))
acfcc2 ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPShareID), FALSE,
25e7b1 ¤   ¤   ¤   ¤   &(shareFileRef->shareID));
2eaf5a
84f69b ¤   if (IsntPGPError(err))
5650fe ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPUInt32), TRUE,
d70808 ¤   ¤   ¤   ¤   &(shareFileRef->threshold));
b2af5a
87f69b ¤   if (IsntPGPError(err))
ea50fe ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPUInt32), TRUE,
30d0f2 ¤   ¤   ¤   ¤   &(shareFileRef->numShares));
45af5a
22f69b ¤   if (IsntPGPError(err))
c650fe ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPUInt32), TRUE,
7f7b35 ¤   ¤   ¤   ¤   &(shareFileRef->totalShares));
4caf5a
29f69b ¤   if (IsntPGPError(err))
d88731 ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPSize), TRUE,
c434e2 ¤   ¤   ¤   ¤   &(shareFileRef->decryptedShareSize));
b6af5a
c6f69b ¤   if (IsntPGPError(err))
648731 ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPSize), TRUE,
6bdc0b ¤   ¤   ¤   ¤   &(shareFileRef->shareDataSize));
03af5a
ca8f63 ¤   if (IsntPGPError(err) && (shareFileRef->shareDataSize > 0))
129717 ¤   ¤   err = sIOWrite(fileIO, shareFileRef->shareDataSize, FALSE,
e2f28e ¤   ¤   ¤   ¤   shareFileRef->shareData);
43af5a
41f69b ¤   if (IsntPGPError(err))
198731 ¤   ¤   err = sIOWrite(fileIO, sizeof(PGPSize), TRUE,
7a2553 ¤   ¤   ¤   ¤   &(shareFileRef->shareHashSize));
76af5a
c36152 ¤   if (IsntPGPError(err) && (shareFileRef->shareHashSize > 0))
80361d ¤   ¤   err = sIOWrite(fileIO, shareFileRef->shareHashSize, FALSE,
d98aab ¤   ¤   ¤   ¤   shareFileRef->shareHash);
c8af5a
819ad6 ¤   PGPFreeIO(fileIO);
d55ea8 ¤   return err;
17efe6 }
--d514 000ce0284f54010005f Page 9 of pgpShareFile.c
e0af5a
1aaf5a
58616c PGPError PGPGetShareFileSpec(PGPShareFileRef shareFileRef,
efa7ed ¤   ¤   ¤   ¤   PFLFileSpecRef *shareFileSpec)
2abb36 {
06c55b ¤   PGPError err = kPGPError_NoErr;
d7af5a
4947bd ¤   if (IsntNull(shareFileSpec))
c1a8fd ¤   ¤   *shareFileSpec = NULL;
92af5a
0b7823 ¤   PGPValidateShareFile(shareFileRef);
7eaa56 ¤   PGPValidatePtr(shareFileSpec);
7aaf5a
fc49d6 ¤   err = PFLCopyFileSpec(shareFileRef->shareFileSpec, shareFileSpec);
3282f0 ¤   if (IsPGPError(err))
93a8fd ¤   ¤   *shareFileSpec = NULL;
50af5a
095ea8 ¤   return err;
93efe6 }
b3af5a
43af5a
badd83 PGPError PGPGetShareFileShareID(PGPShareFileRef shareFileRef,·
58c53e ¤   ¤   ¤   ¤   PGPShareID *id)
7dbb36 {
7fc55b ¤   PGPError err = kPGPError_NoErr;
0eaf5a
fc540b ¤   PGPValidateParam(PGPShareFileRefIsValid(shareFileRef));
514954 ¤   PGPValidatePtr(id);
87af5a
200585 ¤   pgpCopyMemory(&(shareFileRef->shareID), id, sizeof(PGPShareID));
aeaf5a
a85ea8 ¤   return err;
17efe6 }
75af5a
85af5a
5bb43c PGPError PGPGetShareFileOwnerKeyID(PGPShareFileRef shareFileRef,·
4cfa4d ¤   ¤   ¤   ¤   PGPKeyID *id)
febb36 {
9fc55b ¤   PGPError err = kPGPError_NoErr;
67af5a
36540b ¤   PGPValidateParam(PGPShareFileRefIsValid(shareFileRef));
0a4954 ¤   PGPValidatePtr(id);
08af5a
3f0842 ¤   pgpCopyMemory(&(shareFileRef->keyID), id, sizeof(PGPKeyID));
fcaf5a
605ea8 ¤   return err;
71efe6 }
0eaf5a
55af5a
dbc48c PGPError PGPSetShareFileOwnerKeyID(PGPShareFileRef shareFileRef,·
e9e166 ¤   ¤   ¤   ¤   const PGPKeyID id)
5abb36 {
f8c55b ¤   PGPError err = kPGPError_NoErr;
4daf5a
18540b ¤   PGPValidateParam(PGPShareFileRefIsValid(shareFileRef));
14af5a
469614 ¤   pgpCopyMemory(&id, &(shareFileRef->keyID), sizeof(PGPKeyID));
24af5a
db5ea8 ¤   return err;
d8efe6 }
06af5a
b6af5a
ec36ec PGPError PGPGetShareFileOwnerFingerprint(PGPShareFileRef shareFileRef,·
035e7d ¤   ¤   ¤   ¤   PGPSize bufferSize, void *fingerprint, PGPSize *fullSize)
f8bb36 {
8d8e12 ¤   PGPError¤   err = kPGPError_NoErr;
7ea419 ¤   PGPSize¤¤   fingerprintSize;
efaf5a
c12719 ¤   if (IsntNull(fullSize))
b66bc3 ¤   ¤   *fullSize = 0;
22af5a
ce7823 ¤   PGPValidateShareFile(shareFileRef);
--6a19 000ef2b515d4010005f Page 10 of pgpShareFile.c
dffb2f ¤   PGPValidateParam(bufferSize > 0);
64668f ¤   PGPValidatePtr(fingerprint);
57af5a
b1e4af ¤   if (IsNull(shareFileRef->fingerprint))
7fb840 ¤   ¤   return kPGPError_NoErr;
07af5a
5cff41 ¤   if (bufferSize < shareFileRef->fingerprintSize)
5e8a02 ¤   ¤   fingerprintSize = bufferSize;
5e0e24 ¤   else
23f069 ¤   ¤   fingerprintSize = shareFileRef->fingerprintSize;
8eaf5a
29fa3d ¤   pgpCopyMemory(shareFileRef->fingerprint, fingerprint, fingerprintSize);
3faf5a
edf4cf ¤   if (fullSize != NULL)
538d82 ¤   ¤   *fullSize = shareFileRef->fingerprintSize;
caaf5a
90ff41 ¤   if (bufferSize < shareFileRef->fingerprintSize)
985974 ¤   ¤   err = kPGPError_BufferTooSmall;
ceaf5a
415ea8 ¤   return err;
2fefe6 }
a4af5a
26af5a
ff3de2 PGPError PGPSetShareFileOwnerFingerprint(PGPShareFileRef shareFileRef,
5b4ee6 ¤   ¤   ¤   ¤   PGPSize bufferSize, const void *fingerprint)
27bb36 {
df8e12 ¤   PGPError¤   err = kPGPError_NoErr;
0baf5a
247823 ¤   PGPValidateShareFile(shareFileRef);
b5fb2f ¤   PGPValidateParam(bufferSize > 0);
4d668f ¤   PGPValidatePtr(fingerprint);
6aaf5a
cae656 ¤   if (shareFileRef->fingerprint != NULL)
125727 ¤   ¤   PGPFreeData(shareFileRef->fingerprint);
b6af5a
827d60 ¤   shareFileRef->fingerprint = (char *) PGPNewData(shareFileRef->memoryMgr,
717bcc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufferSize,
4f7e53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
2caf5a
2859ed ¤   if (shareFileRef->fingerprint == NULL)
c24030 ¤   ¤   return kPGPError_OutOfMemory;
a4af5a
f4969d ¤   pgpCopyMemory(fingerprint, shareFileRef->fingerprint, bufferSize);
4958f4 ¤   shareFileRef->fingerprintSize = bufferSize;
d85ea8 ¤   return err;
77efe6 }
9caf5a
c3af5a
1e7837 PGPError PGPGetShareFileSharedKeyID(PGPShareFileRef shareFileRef,·
c1fa4d ¤   ¤   ¤   ¤   PGPKeyID *id)
d2bb36 {
54c55b ¤   PGPError err = kPGPError_NoErr;
eaaf5a
99540b ¤   PGPValidateParam(PGPShareFileRefIsValid(shareFileRef));
014954 ¤   PGPValidatePtr(id);
28af5a
8bebc9 ¤   pgpCopyMemory(&(shareFileRef->sharedKeyID), id, sizeof(PGPKeyID));
eaaf5a
285ea8 ¤   return err;
16efe6 }
33af5a
e7af5a
b24e1c PGPUInt32 PGPGetShareThresholdInFile(PGPShareFileRef shareFileRef)
ddbb36 {
2a35ce ¤   pgpAssert(PGPShareFileRefIsValid(shareFileRef));
0daf5a
c62299 ¤   if (PGPShareFileRefIsValid(shareFileRef))
fd2f76 ¤   ¤   return shareFileRef->threshold;
910e24 ¤   else
d3bbde ¤   ¤   return 0;
feefe6 }
efaf5a
--9da6 0003ecc70064010005f Page 11 of pgpShareFile.c
e0af5a
14aa86 PGPUInt32 PGPGetNumSharesInFile(PGPShareFileRef shareFileRef)
26bb36 {
c035ce ¤   pgpAssert(PGPShareFileRefIsValid(shareFileRef));
1567c5 ¤
7a2299 ¤   if (PGPShareFileRefIsValid(shareFileRef))
0f2901 ¤   ¤   return shareFileRef->numShares;
430e24 ¤   else
6dbbde ¤   ¤   return 0;
f9efe6 }
e4af5a
61af5a
1578f5 PGPBoolean IsSamePGPSharesInFiles(PGPShareFileRef firstFile,·
cd70df ¤   ¤   ¤   ¤   PGPShareFileRef secondFile)
aabb36 {
d59581 ¤   PGPBoolean result = FALSE;
71af5a
798b04 ¤   if (!PGPShareFileRefIsValid(firstFile))
d198aa ¤   ¤   return FALSE;
dd91e2 ¤   if (!PGPShareFileRefIsValid(secondFile))
1798aa ¤   ¤   return FALSE;
54af5a
3d2c8c ¤   if (firstFile->shareHashSize == secondFile->shareHashSize)
bfc7a1 ¤   {
69868a ¤   ¤   if (pgpMemoryEqual(firstFile->shareHash, secondFile->shareHash,
7dc560 ¤   ¤   ¤   ¤   firstFile->shareHashSize))
475b34 ¤   ¤   {
60046c ¤   ¤   ¤   result = TRUE;
0c0fe4 ¤   ¤   }
c39371 ¤   }
1aaf5a
bc5d73 ¤   return result;
b4efe6 }
c4af5a
61af5a
4786cd static void sCalcShareFileSize(PGPShareFileRef shareFileRef,·
1b4434 ¤   ¤   ¤   ¤   PGPUInt32 *fileSize)
8cbb36 {
548762 ¤   pgpAssert(shareFileRef != NULL);
575ae6 ¤   pgpAssert(fileSize != NULL);
9faf5a
620512 ¤   *fileSize = sizeof(PGPUInt32)*4 + sizeof(PGPSize)*4 +·
722e2b ¤   ¤   ¤   ¤   ¤   sizeof(PGPKeyID)*2 + shareFileRef->shareDataSize +
fb5666 ¤   ¤   ¤   ¤   ¤   sizeof(PGPShareID) + shareFileRef->shareHashSize;
54af5a
d761ef ¤   if (shareFileRef->userID != NULL)
c16a19 ¤   ¤   *fileSize += strlen(shareFileRef->userID) + 1;
e2af5a
2ae656 ¤   if (shareFileRef->fingerprint != NULL)
0c7ea7 ¤   ¤   *fileSize += shareFileRef->fingerprintSize;
a5af5a
5f830f ¤   return;
a5efe6 }
b3af5a
95af5a
859dc4 static PGPError sIORead(PGPIORef fileIO, PGPSize dataSize,·
8dcb59 ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, void *data)
4bbb36 {
c353ac ¤   PGPByte¤¤   tempData16[sizeof(PGPUInt16)];
d1d83f ¤   PGPByte¤¤   tempData32[sizeof(PGPUInt32)];
66ec9c ¤   PGPUInt32¤  data32;
1cb8a7 ¤   PGPUInt16¤  data16;
73fb1e ¤   PGPSize¤¤   bytesRead;
318e12 ¤   PGPError¤   err = kPGPError_NoErr;
0aaf5a
014194 ¤   PGPValidateIO(fileIO);
ab207b ¤   PGPValidateParam(dataSize > 0);
6a403b ¤   PGPValidatePtr(data);
9caf5a
fb3bd3 ¤   if (crossPlatform)
36c7a1 ¤   {
3e4b71 ¤   ¤   if (dataSize == sizeof(PGPUInt16))
--07a7 001912342254010005f Page 12 of pgpShareFile.c
555695 ¤   ¤   ¤   err = PGPIORead(fileIO, dataSize, tempData16, &bytesRead);
dd0e1d ¤   ¤   else
545ee9 ¤   ¤   ¤   err = PGPIORead(fileIO, dataSize, tempData32, &bytesRead);
7baf5a
0ae2b3 ¤   ¤   if (IsntPGPError(err))
785b34 ¤   ¤   {
18dae9 ¤   ¤   ¤   if (dataSize == sizeof(PGPUInt16))
88f776 ¤   ¤   ¤   {
b73119 ¤   ¤   ¤   ¤   data16 = PGPEndianToUInt16(kPGPShareFileEndian, tempData16);
63016e ¤   ¤   ¤   ¤   pgpCopyMemory(&data16, data, sizeof(PGPUInt16));
54a3a6 ¤   ¤   ¤   }
abbb8c ¤   ¤   ¤   else
a5f776 ¤   ¤   ¤   {
633ce4 ¤   ¤   ¤   ¤   data32 = PGPEndianToUInt32(kPGPShareFileEndian, tempData32);
bd9939 ¤   ¤   ¤   ¤   pgpCopyMemory(&data32, data, sizeof(PGPUInt32));
6ba3a6 ¤   ¤   ¤   }
8a0fe4 ¤   ¤   }
8d9371 ¤   }
140e24 ¤   else
17409e ¤   ¤   err = PGPIORead(fileIO, dataSize, data, &bytesRead);
9eaf5a
6e5ea8 ¤   return err;
23efe6 }
5faf5a
79af5a
93b882 static PGPError sIOWrite(PGPIORef fileIO, PGPSize dataSize,·
aee958 ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, const void *data)
a0bb36 {
9b53ac ¤   PGPByte¤¤   tempData16[sizeof(PGPUInt16)];
5dd83f ¤   PGPByte¤¤   tempData32[sizeof(PGPUInt32)];
49ec9c ¤   PGPUInt32¤  data32;
9ab8a7 ¤   PGPUInt16¤  data16;
d68e12 ¤   PGPError¤   err = kPGPError_NoErr;
f4af5a
f94194 ¤   PGPValidateIO(fileIO);
79207b ¤   PGPValidateParam(dataSize > 0);
ea403b ¤   PGPValidatePtr(data);
66af5a
1a3bd3 ¤   if (crossPlatform)
6dc7a1 ¤   {
7a4b71 ¤   ¤   if (dataSize == sizeof(PGPUInt16))
c75b34 ¤   ¤   {
b00f17 ¤   ¤   ¤   pgpCopyMemory(data, &data16, sizeof(PGPUInt16));
15dcbb ¤   ¤   ¤   PGPUInt16ToEndian(data16, kPGPShareFileEndian, tempData16);
f68e58 ¤   ¤   ¤   err = PGPIOWrite(fileIO, dataSize, tempData16);
be0fe4 ¤   ¤   }
3f0e1d ¤   ¤   else
c65b34 ¤   ¤   {
57abdf ¤   ¤   ¤   pgpCopyMemory(data, &data32, sizeof(PGPUInt32));
856b4e ¤   ¤   ¤   PGPUInt32ToEndian(data32, kPGPShareFileEndian, tempData32);
51ea3c ¤   ¤   ¤   err = PGPIOWrite(fileIO, dataSize, tempData32);
a40fe4 ¤   ¤   }
be9371 ¤   }
390e24 ¤   else
d9ae87 ¤   ¤   err = PGPIOWrite(fileIO, dataSize, data);
c8af5a
9e5ea8 ¤   return err;
f4efe6 }
a0af5a
7daf5a
347e4d /*__Editor_settings____
6faf5a
e74126 ¤   Local Variables:
017b17 ¤   tab-width: 4
c60e6c ¤   End:
995f8c ¤   vi: ts=4 sw=4
039e9b ¤   vim: si
9cd062 _____________________*/
47af5a
91af5a
--c624 0003c1cb80d40100060 Page 1 of pgpShareFile.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
3faf0e ¤   $Id: pgpShareFile.h,v 1.4.8.1 1998/11/12 03:11:14 heller Exp $
6ef7f7 ____________________________________________________________________________*/
0e75b0 #ifndef Included_pgpShareFile_h¤/* [ */
9a8bdd #define Included_pgpShareFile_h
0daf5a
6ae2ff #include "pgpConfig.h"
fcc5d5 #include "pgpBase.h"
b72f8d #include "pgpErrors.h"
bfe82c #include "pgpPubTypes.h"
21392c #include "pflTypes.h"
5bafda #include "pgpShare.h"
3eaf5a
f0c0c0 typedef struct PGPShareFile *¤  PGPShareFileRef;
3aaf5a
9f3fcf #define¤kInvalidPGPShareFileRef¤¤   ¤   ((PGPShareFileRef) NULL)
8d7393 #define PGPShareFileRefIsValid( ref )¤  ( (ref) != kInvalidPGPShareFileRef )
6daf5a
9d99c6 PGP_BEGIN_C_DECLARATIONS
0ecbcf #if PRAGMA_IMPORT_SUPPORTED
ccb981 #pragma import on
907454 #endif
89af5a
dec460 PGPError PGPNewShareFile(PFLFileSpecRef shareFileSpec,·
6eb966 ¤   ¤   ¤   ¤   PGPShareFileRef *shareFileRef);
3eaf5a
4c7bf6 PGPError PGPFreeShareFile(PGPShareFileRef shareFileRef);
33af5a
428caf /* The share object needs to be freed with PGPFreeShares(shares) */
3d5ac1 PGPError PGPCopySharesFromFile(PGPContextRef context,·
8eaf11 ¤   ¤   ¤   ¤   PGPShareFileRef shareFileRef, PGPOptionListRef optionList,
a28c93 ¤   ¤   ¤   ¤   PGPShareRef *shares);
ebaf5a
fa9b6e PGPError PGPCopySharesToFile(PGPContextRef context,·
47af11 ¤   ¤   ¤   ¤   PGPShareFileRef shareFileRef, PGPOptionListRef optionList,
a87937 ¤   ¤   ¤   ¤   PGPShareRef shares);
31af5a
a75f5c PGPError PGPGetShareFileUserID(PGPShareFileRef shareFileRef,
bfe789 ¤   ¤   ¤   ¤   PGPSize bufferSize, char *userID, PGPSize *fullSize);
a8af5a
f394f2 PGPError PGPSetShareFileUserID(PGPShareFileRef shareFileRef,
fede22 ¤   ¤   ¤   ¤   const char *userID);
38af5a
9b0831 PGPError PGPOpenShareFile(PFLFileSpecRef shareFileSpec,·
0db966 ¤   ¤   ¤   ¤   PGPShareFileRef *shareFileRef);
22af5a
6a5ee8 PGPError PGPSaveShareFile(PGPShareFileRef shareFileRef);
50af5a
ee616c PGPError PGPGetShareFileSpec(PGPShareFileRef shareFileRef,
913c6c ¤   ¤   ¤   ¤   PFLFileSpecRef *shareFileSpec);
89af5a
61dd83 PGPError PGPGetShareFileShareID(PGPShareFileRef shareFileRef,·
5ed818 ¤   ¤   ¤   ¤   PGPShareID *id);
36af5a
b1b43c PGPError PGPGetShareFileOwnerKeyID(PGPShareFileRef shareFileRef,·
45993b ¤   ¤   ¤   ¤   PGPKeyID *id);
0caf5a
01c48c PGPError PGPSetShareFileOwnerKeyID(PGPShareFileRef shareFileRef,·
4106f1 ¤   ¤   ¤   ¤   const PGPKeyID id);
88af5a
6a36ec PGPError PGPGetShareFileOwnerFingerprint(PGPShareFileRef shareFileRef,·
2ba81c ¤   ¤   ¤   ¤   PGPSize bufferSize, void *fingerprint, PGPSize *fullSize);
d2af5a
f63de2 PGPError PGPSetShareFileOwnerFingerprint(PGPShareFileRef shareFileRef,
d58256 ¤   ¤   ¤   ¤   PGPSize bufferSize, const void *fingerprint);
c7af5a
3c7837 PGPError PGPGetShareFileSharedKeyID(PGPShareFileRef shareFileRef,·
--c4ab 001671d23d940100060 Page 2 of pgpShareFile.h
28993b ¤   ¤   ¤   ¤   PGPKeyID *id);
5baf5a
16da83 PGPUInt32 PGPGetShareThresholdInFile(PGPShareFileRef shareFileRef);
0caf5a
60e1b4 PGPUInt32 PGPGetNumSharesInFile(PGPShareFileRef shareFileRef);
2baf5a
f478f5 PGPBoolean IsSamePGPSharesInFiles(PGPShareFileRef firstFile,·
252e2a ¤   ¤   ¤   ¤   PGPShareFileRef secondFile);
33af5a
36cbcf #if PRAGMA_IMPORT_SUPPORTED
a42ced #pragma import reset
cf7454 #endif
091254 PGP_END_C_DECLARATIONS
a8af5a
d6195b #endif /* ] Included_pgpShareFile_h */
13af5a
d1af5a
ff7e4d /*__Editor_settings____
23af5a
574126 ¤   Local Variables:
cb7b17 ¤   tab-width: 4
cb0e6c ¤   End:
c45f8c ¤   vi: ts=4 sw=4
109e9b ¤   vim: si
67d062 _____________________*/
--4983 001605946c240100061 Page 1 of pgpSharePriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
167f93 ¤   $Id: pgpSharePriv.h,v 1.3.8.1 1998/11/12 03:11:15 heller Exp $
40f7f7 ____________________________________________________________________________*/
39541c #ifndef Included_pgpSharePriv_h¤/* [ */
ebc974 #define Included_pgpSharePriv_h
04af5a
d9afda #include "pgpShare.h"
deaf5a
2599c6 PGP_BEGIN_C_DECLARATIONS
c7af5a
02254a PGPError pgpCreateShares(PGPContextRef context, PGPKeyID keyID,
f58886 ¤   ¤   ¤   ¤   PGPShareID shareID, PGPUInt32 threshold, PGPUInt32 numShares,·
c3bbe6 ¤   ¤   ¤   ¤   PGPUInt32 totalShares, PGPSize shareSize,
5cd26c ¤   ¤   ¤   ¤   const PGPByte *shareData, PGPShareRef *shares);
dfaf5a
4edf99 /* The share data needs to be freed with PGPFreeData(shareData) */
48083b PGPError pgpGetShareData(PGPShareRef share, PGPByte **shareData,·
44b215 ¤   ¤   ¤   ¤   PGPSize *shareDataSize);
45af5a
34f5a1 /* The share hash needs to be freed with PGPFreeData(shareHash) */
5696e1 PGPError pgpGetShareHash(PGPShareRef share, PGPByte **shareHash,·
be150b ¤   ¤   ¤   ¤   PGPSize *shareHashSize);
11af5a
161254 PGP_END_C_DECLARATIONS
8caf5a
cbff44 #endif /* ] Included_pgpSharePriv_h */
78af5a
25af5a
0d7e4d /*__Editor_settings____
c3af5a
7f4126 ¤   Local Variables:
187b17 ¤   tab-width: 4
ff0e6c ¤   End:
9a5f8c ¤   vi: ts=4 sw=4
839e9b ¤   vim: si
60d062 _____________________*/
--40a8 0014f99701840100062 Page 1 of pgpVersionHeader.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
d07620 ¤   $Id: pgpVersionHeader.c,v 1.47.2.24.2.1 1998/11/12 03:11:15 heller Exp $
f0f7f7 ____________________________________________________________________________*/
6281a4 #include "pgpBuildFlags.h"
008e25 #include "pgpVersionHeader.h"
cbaf5a
e2df0f extern const char pgpVersionHeaderString[] =
d6be29 #if PGP_BUSINESS_SECURITY
e2bd15 ¤   "PGP 6.0.2";
f5d86b #elif PGP_PERSONAL_PRIVACY
f66625 ¤   "PGP Personal Privacy 6.0.2";
8d9db4 #elif PGP_FREEWARE
2499a9 ¤   "PGPfreeware 6.0.2 for non-commercial use <http://www.pgp.com>";
697e2d #elif PGP_DEMO
957e04 ¤   "PGP Personal Privacy 6.0.2 Trialware";
29db21 #else
fd8dda ¤   #error unknown build
fd7454 #endif
e2af5a
83af5a
05af5a
7c7e4d /*__Editor_settings____
ecaf5a
354126 ¤   Local Variables:
047b17 ¤   tab-width: 4
020e6c ¤   End:
8e5f8c ¤   vi: ts=4 sw=4
569e9b ¤   vim: si
ebd062 _____________________*/
46af5a
4faf5a
--fe4f 001d9a12f8440100063 Page 1 of pgpVersionHeader.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
6762ca ¤   $Id: pgpVersionHeader.h,v 1.2.8.1 1998/11/12 03:11:16 heller Exp $
cef7f7 ____________________________________________________________________________*/
4f438e #ifndef Included_pgpVersionHeader_h¤/* [ */
989d60 #define Included_pgpVersionHeader_h
ceaf5a
9aaf5a
953e31 extern const char ·pgpVersionHeaderString[];
2caf5a
3e9051 #endif /* ] Included_pgpVersionHeader_h */
a3af5a
69af5a
707e4d /*__Editor_settings____
47af5a
094126 ¤   Local Variables:
bb7b17 ¤   tab-width: 4
110e6c ¤   End:
c65f8c ¤   vi: ts=4 sw=4
b39e9b ¤   vim: si
d9d062 _____________________*/
--b14c 000a91e336c40100064 Page 1 of Make-common
54b0af #-----------------------------------------------------------------------------
d635f2 # Copyright (c) 1997 PGP inc.
d75a50 # All rights reserved.
4ba601 #
d9b0af #-----------------------------------------------------------------------------
6ddd01 #############################################################################
b1a917 ## Edit the following variables to have appropriate values for your system ##
a1dd01 #############################################################################
3faf5a
f1cb1a vpath %.a $(LDIR):$(PGPCDKDIR)/unix:$(DBLDIR):$(PGPCDKDIR)/priv/keyserver: \
e0aacf ¤   ··$(PGPCDKDIR)/../network/pgpsockets/unix/src
18af5a
d7dd01 #############################################################################
02736d ## LDAP install paths ·····················································##
68dd01 #############################################################################
92a601 #
f8c05e # by default, everything is installed below INSTROOT
714f10 # servers, config files, etc. are put in ETCDIR
ed54a5 # include files get put in INCLUDEDIR
ac48e9 # libraries are put in LIBDIR
12f935 # man pages are put under MANDIR
2cd9d9 # programs end-users will run are put in BINDIR
daa601 #
3db837 # Moved INSTROOT declaration to top-level Makefile
3d37ce # useful for automation.
9faf5a
668fed ETCDIR= $(INSTROOT)/etc
3e4bf1 INCLUDEDIR= $(INSTROOT)/include
ec4e47 LIBDIR= $(INSTROOT)/unix
09e906 MANDIR= $(INSTROOT)/doc
dc2d8f BINDIR= $(INSTROOT)/unix
48af5a
dea601 #
55ca77 # if you want things to run in a different directory from where they
fe2c1a # are installed, set this accordingly (this path gets compiled into a
018e97 # few binaries). otherwise, leave it alone.
0463ae RUNTIMEETCDIR= $(ETCDIR)
deaf5a
36dd01 #############################################################################
717145 ## General compiler options ···············································##
57dd01 #############################################################################
d264cf # Passed to every compile (cc or gcc). ·This is where you put -O or -g, etc.
13c073 # Added -D_REENTRANT per ldap doc. for Solaris builds <galileo>
e17adf OPT=-g
a4255c DEBUG=1
6aab6e UNFINISHED=1
d4ed5a EXTRACFLAGS=-D_REENTRANT $(OPT) -fwritable-strings \
0bca3c ············-DPGP_DEBUG=$(DEBUG) -DUNFINISHED_CODE_ALLOWED=$(UNFINISHED) \
2f17fd ¤   ····-DPGPSOCKETSLDAP=1
4eaf5a
2ae6cd # Passed to every link (ld). ·Include -g here if you did in EXTRACFLAGS.
5caf5a
e3b23e EXTRALDFLAGS=$(OPT)
87af5a
3add01 #############################################################################
cfce69 ## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ······##
25b9e8 ## If you don't want to build it, you can skip this section. ··············##
58dd01 #############################################################################
cda601 #
f911c2 # To build the ldap server, uncomment the HAVEISODE line,
db5803 # and the section describing build settings for your version of isode.
b6a601 #
77a865 HAVEISODE = yes
e3af5a
addd01 #############################################################################
4ec146 ## If you don't want to run slapd, skip this section. ·····················##
54dd01 #############################################################################
49a601 #
b4ac20 # To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
be8e0c # line and select the SLAPD_BACKENDS you want to use. If you enable the
e72d3b # LDBM backend, also select one of the LDBM backends.
a98fbf MAKESLAPD= yes
--70bd 001b0c07ed540100064 Page 2 of Make-common
5ea601 #
d4470f # remove the defines for backends you don't want to enable·
cefdc5 SLAPD_BACKENDS= -DLDAP_LDBM·
89a601 #
059374 # If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
67cee2 # to specify which low-level database package to use. ·There are
94f92f # four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
2ca601 #
4ba9bd # berkeley db btree package
ec7e82 LDBMBACKEND=-DLDBM_USE_DBBTREE21
40b496 LDBMINCLUDE=
3228ff LDBMLIB=-ldb
f2b402 # berkeley db hash package
139bc9 #LDBMBACKEND=-DLDBM_USE_DBHASH
07d345 #LDBMINCLUDE=-I/usr/local/db/include
c70e7e #LDBMLIB=-ldb
1e2a77 # gnu dbm (gdbm)
6fed29 #LDBMBACKEND=-DLDBM_USE_GDBM
239187 #LDBMINCLUDE=-I$(INSTROOT)/servers/slapd/db
096c04 #LDBMLIB=-lgdbm
b41874 # standard unix ndbm
b0bc4d #LDBMBACKEND=-DLDBM_USE_NDBM
1da601 #
467ffd # if you want to use a non-default threads package change these lines
8e42ab #THREADS=-DNO_THREADS
368180 #THREADSLIB=
dcaf5a
f4dd01 #############################################################################
fc1692 ## General options ························································##
7edd01 #############################################################################
27c8ae # uncomment this line to enable debugging code (a good idea)
5d75d8 LDAP_DEBUG=-DLDAP_DEBUG
64af5a
c0b923 # uncomment this line to turn on a few U of Michigan specific things
1b8cea #UOFM=-DUOFM
c7af5a
12bce0 # uncomment this line to delete a few printfs in the lber and ldap libraries.
51d6e3 #NO_USERINTERFACE=-DNO_USERINTERFACE
f8af5a
222982 # uncomment this line to include Connectionless LDAP support
3d1910 #CLDAP=-DCLDAP
33af5a
cd021f # uncomment this line to eliminate local caching support in the libldap
b4decc #NO_CACHE=-DNO_CACHE
c4af5a
24197d # uncomment this line to enable support for LDAP referrals in libldap
219065 #LDAP_REFERRALS=-DLDAP_REFERRALS
b7af5a
504c1c # uncomment this line to use soundex for approximate matches in slapd.
df856d # the default is to use the metaphone algorithm.
b01fa8 #PHONETIC=-DSOUNDEX
--b875 00085f12d0040100065 Page 1 of Makefile
5ea601 #
db0d81 # You will usually NOT need to edit this file at all: ·instead, edit the
0e5447 # Make-common file. ·See the LDAP INSTALL file for more information.
94a601 #
5cb0af #-----------------------------------------------------------------------------
cddb1c # Copyright (c) 1994 Regents of the University of Michigan.
1d5a50 # All rights reserved.
45a601 #
c197d6 # Redistribution and use in source and binary forms are permitted
d1d6ca # provided that this notice is preserved and that due credit is given
668ee9 # to the University of Michigan at Ann Arbor. The name of the University
573eb9 # may not be used to endorse or promote products derived from this
dc0baf # software without specific prior written permission. This software
4dfeea # is provided ``as is'' without express or implied warranty.
d4a601 #
de31e9 # ······LDAP lightweight X.500 Directory access top level makefile
90a601 #
85b0af #-----------------------------------------------------------------------------
5da601 #
a968a2 ############################################################################
bc9b5c # ·········································································#
2bd45b # Usually you will not need to edit anything in this file ·················#
b09b5c # ·········································································#
2568a2 ############################################################################
04a601 #
315a76 # Note that these definitions of standard Unix utilities are only used
3bf826 # in this Makefile. ·The Make-common (and .make-platform) files have a
19f0a3 # similar set of definitions that are used in all the other LDAP Makefiles.
eca601 #
11587c RM=rm -f
af4141 MV=mv -f
400904 CP=cp
e194dc CAT=cat
b4ca71 PWD=pwd
49920a TAIL=tail
d87e78 CHMOD=chmod
c120eb FIND=find
9ed733 SED=sed
057b1a LN=ln -s
d4e0a7 MKDIR=mkdir
a7f4e1 GREP=grep
ef8135 DIRNAME=dirname
5ff38c BASENAME=basename
538b00 TAR=tar
365957 COMPRESS=compress
03c1e1 CO=co
90aea9 CI=ci
75b6b5 UNIX_BIN=unix
412642 PGPLIBSDIR = ../../libs
4faf5a
0f11fe SRCDIRS= liblber libldap
05af5a
fcc2d3 TESTDIR=
0faf5a
40a601 #
580942 # rules to make the software
2ba601 #
3a10e1 # makedb
e8eb46 all: makeconfig
d0081c ¤   @echo "making all..."
1c26cd ¤   @for i in $(SRCDIRS); do \
ed420a ¤   ····echo; echo " ·cd $$i; $(MAKE) $(MFLAGS) all"; \
90ae47 ¤   ····( cd $$i; $(MAKE) $(MFLAGS) all ); \
5a5a47 ¤   done
32af5a
0030cb world: all
51af5a
26a601 #
45b0fb # rules to install the software
16a601 #
0eaf5a
854b99 install:¤   makeconfig
--681d 000eee52e1f40100065 Page 2 of Makefile
ec26cd ¤   @for i in $(SRCDIRS); do \
a7a620 ¤   ····echo; echo "cd $$i; $(MAKE) $(MFLAGS) install"; \
b5b1fe ¤   ····( cd $$i; $(MAKE) $(MFLAGS) install ); \
465a47 ¤   done
09af5a
f462b2 inst-lib:¤  makeconfig
09eed2 ¤   @echo "cd libraries; $(MAKE) $(MFLAGS) install"
ea9fbc ¤   @( cd libraries; $(MAKE) $(MFLAGS) install )
1caf5a
a2af5a
56a601 #
e6e712 # rules to test the LDAP software
50a601 #
d120b7 test:¤  all
4040d0 ¤   @echo " cd $(TESTDIR); $(MAKE) $(MFLAGS) all"; \
28d97c ¤   ( cd $(TESTDIR); $(MAKE) $(MFLAGS) all );
68af5a
ffa601 #
ecf215 # rules to make clean
77a601 #
5baf5a
18b5ca clean:¤ FORCE
5cc0a9 ¤   @if [ -f .makefiles ]; then \
b84d41 ¤   ····for i in $(SRCDIRS) $(TESTDIR); do \
337af4 ¤   ¤   echo; echo "cd $$i; $(MAKE) $(MFLAGS) clean"; \
bd59a0 ¤   ¤   ( cd $$i; $(MAKE) $(MFLAGS) clean ); \
208f45 ¤   ····done; \
26a9d8 ¤   fi; \
e40a51 ¤   ( for d in ./obj-*; do \
b43dcc ¤   ····if [ $$d != "./obj-*" ]; then \
1ad941 ¤   ¤   ( echo "making clean in $$d..."; \
bd9511 ¤   ¤   ··cd $$d; $(MAKE) $(MFLAGS) clean; ) \
e58c49 ¤   ····else \
49d3de ¤   ¤   exit 0; \
f68958 ¤   ····fi; \
d2dd81 ¤   done )
25af5a
8b875c veryclean:¤ clean
78aa54 ¤   @echo; echo "cd build; $(MAKE) $(MFLAGS) -f Make-template veryclean"; \
284e27 ¤   ( cd build; $(MAKE) $(MFLAGS) -f Make-template veryclean ); \
af30bf ¤   if [ -f .makefiles ]; then \
aa4d41 ¤   ····for i in $(SRCDIRS) $(TESTDIR); do \
5bee1e ¤   ¤   echo; echo "cd $$i; $(MAKE) $(MFLAGS) veryclean"; \
64a071 ¤   ¤   ( cd $$i; $(MAKE) $(MFLAGS) veryclean ); \
148f45 ¤   ····done; \
ee2f30 ¤   ····echo "finding and removing Makefiles..."; \
c58913 ¤   ····for i in `$(FIND) . -type d -print`; do \
7c759f ¤   ¤   if [ -f $$i/Make-template ]; then \
8b226d ¤   ¤   ····echo "removing file $$i/Makefile"; \
e36743 ¤   ¤   ····$(RM) $$i/Makefile; \
63059a ¤   ¤   fi; \
048f45 ¤   ····done; \
1ee5c1 ¤   ····echo "removing file .makefiles"; \
6dfcdf ¤   ····$(RM) .makefiles; \
f8a9d8 ¤   fi; \
a70a51 ¤   ( for d in ./obj-*; do \
853dcc ¤   ····if [ $$d != "./obj-*" ]; then \
b81262 ¤   ¤   echo "removing $$d..."; $(RM) -r $$d; \
448c49 ¤   ····else \
1ad3de ¤   ¤   exit 0; \
1b8958 ¤   ····fi; \
333f0c ¤   done ); \
207b46 ¤   if [ -f .make-platform ]; then \
cce1ff ¤   ····echo "removing link .make-platform"; \
71cd1d ¤   ····$(RM) .make-platform; \
500861 ¤   else \
7c783e ¤   ····exit 0; \
a52ec9 ¤   fi
08af5a
c2af5a
83a601 #
ee1552 # rules to make depend
--7a32 000c946f09440100065 Page 3 of Makefile
5ea601 #
e1a601 #
97546b depend:¤makeconfig
47efd2 ¤   @echo "making depend everywhere"; \
15f1f2 ¤   echo " ·cd include; $(MAKE) $(MFLAGS) all"; \
bb3559 ¤   ¤   ( cd include; $(MAKE) $(MFLAGS) all ); \
8888e5 ¤   for i in $(SRCDIRS); do \
77f467 ¤   ····echo; echo "cd $$i; $(MAKE) $(MFLAGS) depend"; \
b96e04 ¤   ····( cd $$i; $(MAKE) $(MFLAGS) depend ); \
e5228b ¤   done; \
163c45 ¤   $(MAKE) $(MFLAGS) makefiles
b5af5a
22a601 #
abc700 # rule to force check for change of platform
40a601 #
426166 platform:¤  FORCE
0f7f49 ¤   @if [ -f .make-platform ]; then \
34b375 ¤   ····echo "removing old link .make-platform"; \
aacd1d ¤   ····$(RM) .make-platform; \
90a9d8 ¤   fi; \
f0c4a9 ¤   $(MAKE) $(MFLAGS) .make-platform
ceaf5a
7caf5a
667566 makeconfig:¤.makefiles buildtools
5faf5a
0b7fbf .make-platform:
d605db ¤   @if [ -f /usr/bin/swconfig ]; then \
43f44d ¤   ····UNAME=./build/uname.sh; \
5bf4ff ¤   elif [ -f /bin/uname ]; then \
4e469b ¤   ····UNAME=/bin/uname; \
0dca5c ¤   elif [ -f /usr/bin/uname ]; then \
173153 ¤   ····UNAME=/usr/bin/uname; \
2e0861 ¤   else \
89f44d ¤   ····UNAME=./build/uname.sh; \
c8a9d8 ¤   fi; \
ef39a2 ¤   if [ -z "$$UNAME" ]; then \
7d6465 ¤   ····echo "unknown platform (no $$UNAME or /usr/bin/uname)"; \
3f138a ¤   ····echo "see the file ·build/PORTS ·for more information."; \
a4737a ¤   ····exit 1; \
350861 ¤   else \
e2b340 ¤   ····OS=`$$UNAME -s` ; OSRELEASE=`$$UNAME -r` ; \
47bd27 ¤   ····OSVERSION=`$$UNAME -v` ; \
75d434 ¤   ····case $$OS in \
612a5a ¤   ····SunOS) \
84c3ff ¤   ¤   if [ $$OSRELEASE -gt "5" -o $$OSRELEASE -lt "4" ]; then \
343f89 ¤   ¤   ····echo "SunOS release $$OSRELEASE unknown..."; exit 1; \
07059a ¤   ¤   fi; \
bcb7b5 ¤   ¤   if [ $$OSRELEASE -ge "5" ]; then \
869af0 ¤   ¤   ····PLATFORM="sunos5"; \
d669db ¤   ¤   else \
2e9edb ¤   ¤   ····PLATFORM="sunos4"; \
9f059a ¤   ¤   fi; \
3b95cd ¤   ¤   ;; \
14fe0c ¤   ····ULTRIX) \
99b661 ¤   ¤   PLATFORM="ultrix" \
8695cd ¤   ¤   ;; \
e4ff94 ¤   ····OSF1) \
dd1e68 ¤   ¤   PLATFORM="osf1" \
ae95cd ¤   ¤   ;; \
0ab7a5 ¤   ····AIX) \
099c90 ¤   ¤   PLATFORM="aix" \
9595cd ¤   ¤   ;; \
9a1ea8 ¤   ····HP-UX) \
e7f483 ¤   ¤   PLATFORM="hpux" \
5495cd ¤   ¤   ;; \
78ea5f ¤   ····Linux) \
db85d7 ¤   ¤   PLATFORM="linux" \
9b95cd ¤   ¤   ;; \
035fe7 ¤   ····NetBSD) \
605643 ¤   ¤   PLATFORM="netbsd" \
9f95cd ¤   ¤   ;; \
c9eab2 ¤   ····OpenBSD) \
--30cf 000189488ec40100065 Page 4 of Makefile
46580d ¤   ¤   PLATFORM="openbsd" \
1295cd ¤   ¤   ;; \
32fcab ¤   ····FreeBSD) \
f94e14 ¤   ¤   PLATFORM="freebsd" \
5295cd ¤   ¤   ;; \
56a749 ¤   ····NeXTSTEP) \
825663 ¤   ¤   PLATFORM="nextstep" \
fa95cd ¤   ¤   ;; \
5d9845 ¤   ····SCO) \
50b370 ¤   ¤   PLATFORM="sco" \
0a95cd ¤   ¤   ;; \
60b0b3 ¤   ····IRIX|IRIX64) \
8e31c3 ¤   ¤   PLATFORM="irix" \
7095cd ¤   ¤   ;; \
e86c9f ¤   ····*) echo "unknown platform ($$OS $$OSVERSION $$OSRELEASE)..."; \
842bf6 ¤   ·······echo "see the file ·build/PORTS ·for more information."; \
d0d89a ¤   ¤   exit 1; \
a395cd ¤   ¤   ;; \
440cb8 ¤   ····esac; \
bea9d8 ¤   fi; \
df2b8d ¤   CC=$(CC); \
7c4764 ¤   OLDIFS="$$IFS"; \
e0f2a6 ¤   IFS=":"; \
bb6491 ¤   for dir in $$PATH; do \
234575 ¤   ····if [ -f $$dir/gcc ]; then \
05652b ¤   ¤   CC=gcc; \
4ad72c ¤   ¤   break; \
f88958 ¤   ····fi; \
fc228b ¤   done; \
a9acb9 ¤   IFS="$$OLDIFS"; \
3522cb ¤   $(LN) ./build/platforms/$$PLATFORM-$$CC/Make-platform .make-platform; \
240208 ¤   echo ""; \
c238e9 ¤   echo "** Set platform to $$PLATFORM with compiler $$CC..."; \
449a24 ¤   echo ""
b3af5a
00a601 #
a12b0a # rule to build Makefiles by concatenating Make-template file in each
1cd19a # subdirectory with global Make-common, .make-platform, and
ba82ea # build/Make-append files
dea601 #
c4a64a .makefiles:¤Make-common .make-platform build/Make-append
4fee55 ¤   @echo "making Makefiles..."; \
5cfb07 ¤   HDRFILE=/tmp/Makehdr.$$$$; \
dc4627 ¤   DEFSFILE=/tmp/Makedefs.$$$$; \
b721ad ¤   $(CAT) build/Make-append ./.make-platform ./Make-common > $$DEFSFILE; \
ed3186 ¤   echo "# --------------------------------------------------------" > ·$$HDRF¶
1608bd ILE; \
e20f08 ¤   echo "# ·This file was automatically generated. ·Do not edit it." ·>> $$HDR¶
a770fd FILE; \
0888c1 ¤   echo "# ·Instead, edit the Make-common file (located in the root" ·>> $$HDR¶
af70fd FILE; \
ebbe74 ¤   echo "# ·(of the LDAP distribution). ·See the LDAP INSTALL file" ··>> $$HDR¶
3870fd FILE; \
6d1a62 ¤   echo "# ·for more information." >> $$HDRFILE; \
69b08e ¤   echo "# --------------------------------------------------------" >> $$HDRF¶
3708bd ILE; \
76c234 ¤   echo "#" >> $$HDRFILE; \
66a4b6 ¤   for i in `$(FIND) . -type d -print`; do \
c9daa6 ¤   ····if [ -f $$i/Make-template ]; then \
a6048f ¤   ¤   echo " ·creating $$i/Makefile"; \
25b0d3 ¤   ¤   $(RM) $$i/Makefile; \
684751 ¤   ¤   $(CAT) $$HDRFILE $$i/Make-template $$DEFSFILE > $$i/Makefile; \
4c00ae ¤   ¤   $(CHMOD) 444 $$i/Makefile; \
3f8958 ¤   ····fi; \
7f228b ¤   done; \
53cfa1 ¤   $(RM) .makefiles; \
d5da21 ¤   touch .makefiles; \
ac1e31 ¤   $(RM) $$HDRFILE $$DEFSFILE
15af5a
e3a601 #
16c2df # rule to always build makefiles
18a601 #
--b6ec 001fe0403a840100065 Page 5 of Makefile
3985fc makefiles:¤ FORCE
3fc295 ¤   $(RM) .makefiles
f3bab1 ¤   $(MAKE) $(MFLAGS) .makefiles
98af5a
ffa601 #
531489 # rule to create any tools we need to build everything else
93a601 #
482ea5 buildtools:¤FORCE
4bda03 ¤   @echo "making buildtools"
695d8d ¤   @echo " ·cd build; $(MAKE) $(MFLAGS)"
3c6c80 ¤   @( cd build; $(MAKE) $(MFLAGS) )
a4af5a
fe2b40 FORCE:
--3619 0007c6da92a40100066 Page 1 of Make-append
5ea601 #
b5ffdb # Do NOT edit this file -- it is automatically appended to all Makefiles
7969dc # except the LDAP top-level Makefile. See the LDAP INSTALL file for more
641fc7 # information.
e8a601 #
82b0af #-----------------------------------------------------------------------------
fbdb1c # Copyright (c) 1994 Regents of the University of Michigan.
205a50 # All rights reserved.
80a601 #
e297d6 # Redistribution and use in source and binary forms are permitted
57d6ca # provided that this notice is preserved and that due credit is given
068ee9 # to the University of Michigan at Ann Arbor. The name of the University
d93eb9 # may not be used to endorse or promote products derived from this
720baf # software without specific prior written permission. This software
eefeea # is provided ``as is'' without express or implied warranty.
bea601 #
623287 # ······LDAP standard Make defines (appended to all but top-level Makefile)
e3a601 #
ecb0af #-----------------------------------------------------------------------------
25af5a
58ad9f # DEFS are included in CFLAGS
3fd084 DEFS¤   = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
c50785 ¤   ¤   $(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
8bf00e ¤   ¤   $(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
8b997b ¤   ¤   $(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
bd87f1 ¤   ¤   $(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
1aaf5a
4940cd # SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
adb18b SERVERDEFS¤ = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
5814ba ¤   ¤   ¤   $(NO_SETPROCTITLE) $(PEPSY_DUMP)
55af5a
90a601 #
eb0ce2 # ISODELIBS are used in server/ldapd builds
6fa601 #
fe4e01 ISODELIBS¤  = $(ISODEBASELIBS) -lm $(ISODETURBOLIBS)
70af5a
d10558 # ACFLAGS are added to CFLAGS but not passed to mkdep, lint, etc
3a17ce ACFLAGS¤¤   = $(EXTRACFLAGS) $(UNPROTOCFLAGS)
33af5a
e42eb4 # ALDFLAGS are always placed near the beginning of all linker (cc -o) commands
ba49dd ALDFLAGS¤   = $(EXTRALDFLAGS) $(PLATFORMLDFLAGS)
78af5a
e4233d # ALIBS are always placed at the end of all linker (cc -o) commands
c3a5bb ALIBS¤  ¤   = $(PLATFORMLIBS) $(THREADSLIB)
5eaf5a
12a601 #
e8c229 # default definitions for Unix utilities (may be over-ridden in Make-platform)
53fd75 CC¤ = cc
f07e42 MAKE¤   = make
a31a1a RANLIB¤ = ranlib
0585b9 AR¤ = ar
80ba00 RM¤ = rm -f
289865 MV¤ = mv -f
e69324 CP¤ = cp
93229f CHMOD¤  = chmod
6265eb CAT¤= cat
f1d1bd LN¤ = ln -s
4b41b6 HARDLN¤ = ln
13c699 TAIL¤   = tail
84e675 SED¤= sed
4901f7 LINT¤   = lint
343a04 5LINT¤  = lint
34c291 MKDIR¤  = mkdir
3b3f60 INSTALL¤= install
560106 INSTALLFLAGS = -c
34735e BASENAME= basename
12d84e DIRNAME¤= dirname
73720b MKDEP¤  = $(LDAPSRC)/build/mkdep -c gcc -s -f Make-template
7be392 PWD¤= pwd
8e96d7 DATE¤   = date
b1a7d0 HOSTNAME= hostname
7caf5a
--186e 0016771eeac40100066 Page 2 of Make-append
e0af5a
53a601 #
ff592a # empty target used to force rules to be invoked
12a601 #
ac2b40 FORCE:
67af5a
--d076 00110f8daee40100067 Page 1 of Make-template
54b0af #-----------------------------------------------------------------------------
0cdb1c # Copyright (c) 1994 Regents of the University of Michigan.
155a50 # All rights reserved.
1aa601 #
fb97d6 # Redistribution and use in source and binary forms are permitted
69d6ca # provided that this notice is preserved and that due credit is given
4e8ee9 # to the University of Michigan at Ann Arbor. The name of the University
0e3eb9 # may not be used to endorse or promote products derived from this
440baf # software without specific prior written permission. This software
d8feea # is provided ``as is'' without express or implied warranty.
49a601 #
34c9e1 # ······LDAP buildtools makefile
c3a601 #
c5b0af #-----------------------------------------------------------------------------
e4af5a
323d8c all:¤   FORCE
0e1b97 ¤   @if [ ! -z "$(NEEDUNPROTO)" ]; then \
adb93b ¤   ····cd unproto; $(MAKE) $(MFLAGS) CC=$(CC); \
a30861 ¤   else \
8d783e ¤   ····exit 0; \
312ec9 ¤   fi
ceaf5a
4375a4 install:¤   FORCE
8faf5a
af49c8 clean:
f77721 ¤   cd unproto; $(MAKE) $(MFLAGS) clean
392791 ¤   cd platforms; $(MAKE) $(MFLAGS) clean
7eaf5a
cad24e veryclean:
d07721 ¤   cd unproto; $(MAKE) $(MFLAGS) clean
fbfa0e ¤   cd platforms; $(MAKE) $(MFLAGS) veryclean
b0af5a
3ca513 links:
ecf358 ¤   @echo "making links in `$(PWD)`"; \
6555ba ¤   $(LN) .src/version .src/platforms .src/Make-append .src/install.sh . ; \
7948de ¤   ( $(MKDIR) unproto; cd unproto; $(LN) ../.src/unproto .src; \
220de7 ¤   ··$(LN) .src/Makefile .src/*.[ch] . )
10af5a
--fc0a 000e845a17b40100068 Page 1 of Makefile
2539de # --------------------------------------------------------
324229 # ·This file was automatically generated. ·Do not edit it.
c0e6af # ·Instead, edit the Make-common file (located in the root
eef11f # ·(of the LDAP distribution). ·See the LDAP INSTALL file
a05811 # ·for more information.
ee39de # --------------------------------------------------------
05a601 #
2db0af #-----------------------------------------------------------------------------
06db1c # Copyright (c) 1994 Regents of the University of Michigan.
d95a50 # All rights reserved.
aea601 #
8c97d6 # Redistribution and use in source and binary forms are permitted
c6d6ca # provided that this notice is preserved and that due credit is given
378ee9 # to the University of Michigan at Ann Arbor. The name of the University
a83eb9 # may not be used to endorse or promote products derived from this
b10baf # software without specific prior written permission. This software
8dfeea # is provided ``as is'' without express or implied warranty.
95a601 #
d8c9e1 # ······LDAP buildtools makefile
f5a601 #
4cb0af #-----------------------------------------------------------------------------
a6af5a
783d8c all:¤   FORCE
191b97 ¤   @if [ ! -z "$(NEEDUNPROTO)" ]; then \
41b93b ¤   ····cd unproto; $(MAKE) $(MFLAGS) CC=$(CC); \
e50861 ¤   else \
b5783e ¤   ····exit 0; \
6c2ec9 ¤   fi
e1af5a
dd75a4 install:¤   FORCE
98af5a
1249c8 clean:
fd7721 ¤   cd unproto; $(MAKE) $(MFLAGS) clean
692791 ¤   cd platforms; $(MAKE) $(MFLAGS) clean
64af5a
3cd24e veryclean:
e87721 ¤   cd unproto; $(MAKE) $(MFLAGS) clean
52fa0e ¤   cd platforms; $(MAKE) $(MFLAGS) veryclean
18af5a
bda513 links:
00f358 ¤   @echo "making links in `$(PWD)`"; \
8455ba ¤   $(LN) .src/version .src/platforms .src/Make-append .src/install.sh . ; \
1348de ¤   ( $(MKDIR) unproto; cd unproto; $(LN) ../.src/unproto .src; \
e90de7 ¤   ··$(LN) .src/Makefile .src/*.[ch] . )
8eaf5a
cda601 #
91ffdb # Do NOT edit this file -- it is automatically appended to all Makefiles
fe69dc # except the LDAP top-level Makefile. See the LDAP INSTALL file for more
291fc7 # information.
0ca601 #
25b0af #-----------------------------------------------------------------------------
a7db1c # Copyright (c) 1994 Regents of the University of Michigan.
965a50 # All rights reserved.
00a601 #
2197d6 # Redistribution and use in source and binary forms are permitted
d3d6ca # provided that this notice is preserved and that due credit is given
d18ee9 # to the University of Michigan at Ann Arbor. The name of the University
233eb9 # may not be used to endorse or promote products derived from this
c30baf # software without specific prior written permission. This software
c0feea # is provided ``as is'' without express or implied warranty.
f8a601 #
483287 # ······LDAP standard Make defines (appended to all but top-level Makefile)
59a601 #
1fb0af #-----------------------------------------------------------------------------
8eaf5a
75ad9f # DEFS are included in CFLAGS
02d084 DEFS¤   = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
a80785 ¤   ¤   $(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
66f00e ¤   ¤   $(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
b0997b ¤   ¤   $(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
fd87f1 ¤   ¤   $(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
e8af5a
--71d5 0002e3b497240100068 Page 2 of Makefile
a140cd # SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
fdb18b SERVERDEFS¤ = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
de14ba ¤   ¤   ¤   $(NO_SETPROCTITLE) $(PEPSY_DUMP)
57af5a
80a601 #
430ce2 # ISODELIBS are used in server/ldapd builds
e3a601 #
154e01 ISODELIBS¤  = $(ISODEBASELIBS) -lm $(ISODETURBOLIBS)
aeaf5a
7b0558 # ACFLAGS are added to CFLAGS but not passed to mkdep, lint, etc
0f17ce ACFLAGS¤¤   = $(EXTRACFLAGS) $(UNPROTOCFLAGS)
c3af5a
612eb4 # ALDFLAGS are always placed near the beginning of all linker (cc -o) commands
8b49dd ALDFLAGS¤   = $(EXTRALDFLAGS) $(PLATFORMLDFLAGS)
83af5a
c9233d # ALIBS are always placed at the end of all linker (cc -o) commands
551ec7 ALIBS¤  ¤   = $(PLATFORMLIBS) $(THREADSLIB) -lstdc++
daaf5a
d4a601 #
76c229 # default definitions for Unix utilities (may be over-ridden in Make-platform)
62fd75 CC¤ = cc
f57e42 MAKE¤   = make
711a1a RANLIB¤ = ranlib
6085b9 AR¤ = ar
6bba00 RM¤ = rm -f
259865 MV¤ = mv -f
719324 CP¤ = cp
ae229f CHMOD¤  = chmod
8d65eb CAT¤= cat
aad1bd LN¤ = ln -s
3141b6 HARDLN¤ = ln
abc699 TAIL¤   = tail
95e675 SED¤= sed
f201f7 LINT¤   = lint
7a3a04 5LINT¤  = lint
16c291 MKDIR¤  = mkdir
0c3f60 INSTALL¤= install
130106 INSTALLFLAGS = -c
80735e BASENAME= basename
9fd84e DIRNAME¤= dirname
6d720b MKDEP¤  = $(LDAPSRC)/build/mkdep -c gcc -s -f Make-template
aae392 PWD¤= pwd
ea96d7 DATE¤   = date
d9a7d0 HOSTNAME= hostname
caaf5a
7caf5a
f0a601 #
fb592a # empty target used to force rules to be invoked
19a601 #
852b40 FORCE:
afaf5a
fba601 #
3bc8ac # LDAP SunOS5 GNU C Make-platform file
a5a601 #
16af5a
d3a601 #
81a68c # add any platform-specific overrides below here
d7a601 #
1baf5a
cdaf5a
60a601 #
ca95cf # -------------------------------------------------------------------------
26ba80 # you will probably not need to edit anything below this point
7295cf # -------------------------------------------------------------------------
964b2c CC¤ = gcc
63af5a
601dfe # ranlib not needed under SunOS5
aa7716 RANLIB¤ = ""
00af5a
3f9a13 # give full path to hostname since it may not be in user's path
8fea97 HOSTNAME=/usr/ucb/hostname
2eaf5a
--3c40 0009a6d22ce40100068 Page 3 of Makefile
ab7720 # don't count on /usr/ucb/install being present or first in path
b010f3 INSTALL=$(LDAPSRC)/build/install.sh
35af5a
69eaf0 PLATFORMCFLAGS=¤-Dsunos5 -D_REENTRANT
248289 PLATFORMLIBS= -lsocket -lnsl -lgen
431dc2 THREADS= -DTHREAD_SUNOS5_LWP
ac7e25 THREADSLIB=-lthread
40b0af #-----------------------------------------------------------------------------
4c35f2 # Copyright (c) 1997 PGP inc.
575a50 # All rights reserved.
aaa601 #
ddb0af #-----------------------------------------------------------------------------
aedd01 #############################################################################
d0a917 ## Edit the following variables to have appropriate values for your system ##
cfdd01 #############################################################################
91af5a
dd515b vpath %.a $(OUTDIR):$(LDIR):$(PGPCDKDIR)/unix:$(DBLDIR):$(PGPPFLDIR) \
d9dc18 ¤   ··$(PGPCDKDIR)/priv/keyserver: \
aeaacf ¤   ··$(PGPCDKDIR)/../network/pgpsockets/unix/src
c3af5a
d9dd01 #############################################################################
16736d ## LDAP install paths ·····················································##
f3dd01 #############################################################################
56a601 #
40c05e # by default, everything is installed below INSTROOT
7b4f10 # servers, config files, etc. are put in ETCDIR
8754a5 # include files get put in INCLUDEDIR
7848e9 # libraries are put in LIBDIR
88f935 # man pages are put under MANDIR
22d9d9 # programs end-users will run are put in BINDIR
6ba601 #
efb837 # Moved INSTROOT declaration to top-level Makefile
7237ce # useful for automation.
c4af5a
c08fed ETCDIR= $(INSTROOT)/etc
084bf1 INCLUDEDIR= $(INSTROOT)/include
274e47 LIBDIR= $(INSTROOT)/unix
dfe906 MANDIR= $(INSTROOT)/doc
872d8f BINDIR= $(INSTROOT)/unix
58af5a
b6a601 #
a6ca77 # if you want things to run in a different directory from where they
8d2c1a # are installed, set this accordingly (this path gets compiled into a
4e8e97 # few binaries). otherwise, leave it alone.
5a63ae RUNTIMEETCDIR= $(ETCDIR)
d2af5a
a7dd01 #############################################################################
fd7145 ## General compiler options ···············································##
b5dd01 #############################################################################
0364cf # Passed to every compile (cc or gcc). ·This is where you put -O or -g, etc.
eec073 # Added -D_REENTRANT per ldap doc. for Solaris builds <galileo>
847adf OPT=-g
68255c DEBUG=1
adab6e UNFINISHED=1
22ed5a EXTRACFLAGS=-D_REENTRANT $(OPT) -fwritable-strings \
4d1d76 ············-DPGP_DEBUG=$(DEBUG) -DUNFINISHED_CODE_ALLOWED=$(UNFINISHED)
e0af5a
09e6cd # Passed to every link (ld). ·Include -g here if you did in EXTRACFLAGS.
c3af5a
64b23e EXTRALDFLAGS=$(OPT)
26af5a
3fdd01 #############################################################################
dfce69 ## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ······##
d7b9e8 ## If you don't want to build it, you can skip this section. ··············##
7fdd01 #############################################################################
16a601 #
8811c2 # To build the ldap server, uncomment the HAVEISODE line,
0b5803 # and the section describing build settings for your version of isode.
b9a601 #
1da865 HAVEISODE = yes
97af5a
9add01 #############################################################################
--1ce9 001b93c0a7c40100068 Page 4 of Makefile
fac146 ## If you don't want to run slapd, skip this section. ·····················##
66dd01 #############################################################################
a2a601 #
ffac20 # To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
f38e0c # line and select the SLAPD_BACKENDS you want to use. If you enable the
8e2d3b # LDBM backend, also select one of the LDBM backends.
718fbf MAKESLAPD= yes
85a601 #
8b4d71 # remove the defines for backends you don't want to enable
05743e SLAPD_BACKENDS= -DLDAP_LDBM
f0a601 #
cb9374 # If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
8ecee2 # to specify which low-level database package to use. ·There are
40f92f # four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
83a601 #
82a9bd # berkeley db btree package
597e82 LDBMBACKEND=-DLDBM_USE_DBBTREE21
57b496 LDBMINCLUDE=
6128ff LDBMLIB=-ldb
85b402 # berkeley db hash package
a89bc9 #LDBMBACKEND=-DLDBM_USE_DBHASH
79d345 #LDBMINCLUDE=-I/usr/local/db/include
200e7e #LDBMLIB=-ldb
ed2a77 # gnu dbm (gdbm)
82ed29 #LDBMBACKEND=-DLDBM_USE_GDBM
3f9187 #LDBMINCLUDE=-I$(INSTROOT)/servers/slapd/db
f46c04 #LDBMLIB=-lgdbm
f21874 # standard unix ndbm
5abc4d #LDBMBACKEND=-DLDBM_USE_NDBM
3aa601 #
307ffd # if you want to use a non-default threads package change these lines
0f42ab #THREADS=-DNO_THREADS
788180 #THREADSLIB=
9faf5a
fcdd01 #############################################################################
001692 ## General options ························································##
7bdd01 #############################################################################
b1c8ae # uncomment this line to enable debugging code (a good idea)
5a75d8 LDAP_DEBUG=-DLDAP_DEBUG
d8af5a
0db923 # uncomment this line to turn on a few U of Michigan specific things
448cea #UOFM=-DUOFM
b6af5a
e6bce0 # uncomment this line to delete a few printfs in the lber and ldap libraries.
48d6e3 #NO_USERINTERFACE=-DNO_USERINTERFACE
52af5a
822982 # uncomment this line to include Connectionless LDAP support
181910 #CLDAP=-DCLDAP
4aaf5a
b6021f # uncomment this line to eliminate local caching support in the libldap
47decc #NO_CACHE=-DNO_CACHE
66af5a
e1197d # uncomment this line to enable support for LDAP referrals in libldap
5a1c28 LDAP_REFERRALS=-DLDAP_REFERRALS
bdaf5a
c44c1c # uncomment this line to use soundex for approximate matches in slapd.
6f856d # the default is to use the metaphone algorithm.
b91fa8 #PHONETIC=-DSOUNDEX
--aa6e 000b106a06340100069 Page 1 of PORTS
5db16e This file gives some helpful hints for building LDAP on various machines.
07af5a
05375a LDAP has been built and tested on the following platforms. ·It will
7eb103 probably build fine under similar versions of the OS (e.g. it has
344276 been built and tested under SunOS 4.1.4, but probably builds fine
337be0 under all SunOS 4.1.x systems).
aaaf5a
34b0f1 If you port LDAP to a new platform, let us know so we can add it here.
09f02b See the end of this file for some hints on doing a port. ·The following
f53730 tables give some indication of the level of support there is for various
367c5f platforms where the LDAP release has been built. ·Key:
e1af5a
b48637 ····X - all pieces are known to build and work
fdeefd ····B - all pieces build and are believed to work
b980f3 ····S - some pieces build and work
134574 ····O - an older LDAP release has been ported here; current status unknown
c43284 ····? - unknown
787b19 ····- - does not build and/or work at all
11af5a
370fd7 ** Unix and Unix-like platforms:
50af5a
f8c047 ·OS Version ····libraries ··clients ···ldapd ···slapd ···slurpd
f80217 ·---------- ····--------- ··------- ···----- ···----- ···------
b00aae ·AIX 3.2.5 ·········X ·········X ········B ·······B ·······-(1)
0faf5a
65fef9 ·HP-UX 9.05 ········X ·········X ········? ·······B ·······-(1)
31af5a
fb19b4 ·Linux 1.3.76 ······X ·········X ········O ·······X ·······-(1)
5daf5a
8d191a ·FreeBSD 2.0.5 ·····X ·········X ········? ·······B ·······?
8eaf5a
e7026a ·NETBSD 0.9a ·······O ·········O ········? ·······? ·······?
acaf5a
8b0c70 ·NeXTSTEP 3.2 ······O ·········O ········? ·······? ·······?
51af5a
9be81a ·SunOS 4.1.4 ·······X ·········X ········X ·······X ·······X
87af5a
3dc570 ·SunOS 5.5 ·········X ·········X ········B ·······X ·······X
528446 ·(Solaris 2.5)
deaf5a
01feb4 ·Ultrix 4.3 ········X ·········X ········B ·······B ·······?
aaaf5a
fd8faf ·OSF/1 3.2 ·········X ·········X ········X ·······X ·······?
43af5a
3366fd ·IRIX 5.x/6.x ······B ·········B ········? ·······B ·······?
49af5a
ae8d04 ·NCR MP-RAS 2.3 ····X ·········X ········? ·······? ·······?
13af5a
3465aa (1) - required threads support not provided by vendor
33af5a
3649ff ** Non-Unix Platforms:
8daf5a
b0c047 ·OS Version ····libraries ··clients ···ldapd ···slapd ···slurpd
c90217 ·---------- ····--------- ··------- ···----- ···----- ···------
ce47e4 ·MacOS 7.5 ·········X ·········- ········- ·······- ·······-
f90c27 ·····(see the file libraries/macintosh/README for build instructions)
7aaf5a
3d4dfd ·MSDOS ·············O ·········S ········- ·······- ·······-
bed825 ·····(see the file libraries/msdos/README for build instructions)
3baf5a
cd2161 ·MS-Windows 3.x ····O ·········- ········- ·······- ·······-
b24256 ·····(see the file libraries/msdos/README.WSA for build instructions)
0aaf5a
2c13ed ·MS-Win NT & 95 ····O ·········? ········? ·······? ·······?
73af5a
29f03c ·VMS ···············X ·········S ········X ·······X ·······?
ae4718 ·····(see the file libraries/vms/README.VMS for build instructions)
a1af5a
c1af5a
955a7c ** Hints on Porting LDAP to a New Platform
8aaf5a
b1e707 If your platform is not listed here, you will need to do a port. ·The
--09ef 001386c6c0a40100069 Page 2 of PORTS
2c9694 place to start for Unix systems is by creating a new directory under
fb527c the LDAP build/platforms directory and creating an appropriate
3f64fd Make-platform file. ·It is probably easiest to start by duplicating a
df5310 directory there that is for a platform similar to yours.
28af5a
bf670f Variables commonly set in the Make-platform files include:
1aaf5a
b85092 CC ·············- compiler to use, e.g. CC=cc or CC=gcc
41e7e3 PLATFORMCFLAGS ·- flags added to every compile
ec6352 PLATFORMLDFLAGS - flags added to every link
a8af6b PLATFORMLIBS ···- extra libraries needed (added to the end of all link commands)
3ad0ee LDBMLIB ········- ndbm library, needed if not in libc (e.g. LDBMLIB=-lndbm)
5fb464 NEEDUNPROTO=yes - set if your compiler doesn't understand prototypes; see the
319cd9 ······················sunos4-cc and hpux-cc files for example usage
f8a4e5 INSTALL ········- BSD-like install command; if necessary, you can use a script
d0fe83 ······················we provide: ·INSTALL=$(LDAPSRC)/build/install.sh
4c4b43 RANLIB ·········- command to convert libraries for efficient random access;
9a52b1 ······················if your system has no ranlib, use RANLIB = ""
ee7caa other commands ·- see the file build/Make-append for a list
00af5a
164c2f You will also need to modify the top-level LDAP Makefile .make-platform
9bdd1f rule to know about your platform. ·Finally, you should look through the
7afe06 include/portable.h file and make any necessary adjustments.
62af5a
0284f4 Please send changes via e-mail to: ·ldap-support@umich.edu so they can be
3805f4 incorporated into future releases.
--54db 001b1f2bb0b4010006a Page 1 of README-unproto
dee8d4 The unproto code was obtained from:
7faf5a
b125a3 ····ftp://ftp.win.tue.nl/pub/unix/unproto5.shar.Z
--4fad 000f1b6b1104010006b Page 1 of db.1.85.patch
0e9e6c *** ./hash/hash.h.bak¤  Fri May 12 11:00:42 1995
66607a --- ./hash/hash.h¤  Fri May 12 11:01:07 1995
bb37aa ***************
af9f8e *** 103,109 ****
3e1079 ··¤ BUFHEAD ¤   *cpage;¤¤   /* Current page */
854d1c ··¤ int¤¤   cbucket;¤   /* Current bucket */
843232 ··¤ int¤¤   cndx;¤  ¤   /* Index of next item on cpage */
84920e ! ¤ int¤¤   errno;¤ ¤   /* Error Number -- for DBM·
ebf847 ··¤ ¤   ¤   ¤   ¤   ·* compatability */
a36dfb ··¤ int¤¤   new_file;¤  /* Indicates if fd is backing store·
d6457d ··¤ ¤   ¤   ¤   ¤   ·* or no */
b90bd7 --- 103,109 ----
3f1079 ··¤ BUFHEAD ¤   *cpage;¤¤   /* Current page */
bf4d1c ··¤ int¤¤   cbucket;¤   /* Current bucket */
823232 ··¤ int¤¤   cndx;¤  ¤   /* Index of next item on cpage */
e124ea ! ¤ int¤¤   h_errno;¤   /* Error Number -- for DBM·
0ff847 ··¤ ¤   ¤   ¤   ¤   ·* compatability */
6b6dfb ··¤ int¤¤   new_file;¤  /* Indicates if fd is backing store·
1a457d ··¤ ¤   ¤   ¤   ¤   ·* or no */
5a9cb6 *** ./hash/hash.c.bak¤  Fri May 12 11:02:03 1995
6a00d3 --- ./hash/hash.c¤  Fri May 12 11:02:42 1995
7f37aa ***************
8e1cfb *** 505,511 ****
afc248 ··¤ else
7a9065 ··¤ ¤   if (wsize != sizeof(HASHHDR)) {
02665e ··¤ ¤   ¤   errno = EFTYPE;
abf349 ! ¤ ¤   ¤   hashp->errno = errno;
448a08 ··¤ ¤   ¤   return (-1);
e9a642 ··¤ ¤   }
175c96 ··¤ for (i = 0; i < NCACHED; i++)
0a88a2 --- 505,511 ----
1bc248 ··¤ else
619065 ··¤ ¤   if (wsize != sizeof(HASHHDR)) {
b4665e ··¤ ¤   ¤   errno = EFTYPE;
2d68a1 ! ¤ ¤   ¤   hashp->h_errno = errno;
5b8a08 ··¤ ¤   ¤   return (-1);
0da642 ··¤ ¤   }
f95c96 ··¤ for (i = 0; i < NCACHED; i++)
5a37aa ***************
fc5aa9 *** 536,542 ****
ddde7b ··
7cb195 ··¤ hashp = (HTAB *)dbp->internal;
5b3398 ··¤ if (flag) {
f2ca29 ! ¤ ¤   hashp->errno = errno = EINVAL;
73ea37 ··¤ ¤   return (ERROR);
698cf7 ··¤ }
1721d0 ··¤ return (hash_access(hashp, HASH_GET, (DBT *)key, data));
bbcef0 --- 536,542 ----
71de7b ··
8db195 ··¤ hashp = (HTAB *)dbp->internal;
b73398 ··¤ if (flag) {
b4e51c ! ¤ ¤   hashp->h_errno = errno = EINVAL;
d2ea37 ··¤ ¤   return (ERROR);
928cf7 ··¤ }
c121d0 ··¤ return (hash_access(hashp, HASH_GET, (DBT *)key, data));
1737aa ***************
e6c21a *** 553,563 ****
0cde7b ··
d1b195 ··¤ hashp = (HTAB *)dbp->internal;
3736bb ··¤ if (flag && flag != R_NOOVERWRITE) {
2eca29 ! ¤ ¤   hashp->errno = errno = EINVAL;
83ea37 ··¤ ¤   return (ERROR);
d88cf7 ··¤ }
1ca4ff ··¤ if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
7e2fa0 ! ¤ ¤   hashp->errno = errno = EPERM;
a8ea37 ··¤ ¤   return (ERROR);
358cf7 ··¤ }
ffbe00 ··¤ return (hash_access(hashp, flag == R_NOOVERWRITE ?
b05643 --- 553,563 ----
14de7b ··
30b195 ··¤ hashp = (HTAB *)dbp->internal;
f136bb ··¤ if (flag && flag != R_NOOVERWRITE) {
--2a61 0009a174f344010006b Page 2 of db.1.85.patch
09e51c ! ¤ ¤   hashp->h_errno = errno = EINVAL;
54ea37 ··¤ ¤   return (ERROR);
388cf7 ··¤ }
0ca4ff ··¤ if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
76686e ! ¤ ¤   hashp->h_errno = errno = EPERM;
3cea37 ··¤ ¤   return (ERROR);
258cf7 ··¤ }
0abe00 ··¤ return (hash_access(hashp, flag == R_NOOVERWRITE ?
9e37aa ***************
699752 *** 574,584 ****
22de7b ··
c4b195 ··¤ hashp = (HTAB *)dbp->internal;
c46d77 ··¤ if (flag && flag != R_CURSOR) {
f7ca29 ! ¤ ¤   hashp->errno = errno = EINVAL;
72ea37 ··¤ ¤   return (ERROR);
2d8cf7 ··¤ }
0da4ff ··¤ if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
572fa0 ! ¤ ¤   hashp->errno = errno = EPERM;
0bea37 ··¤ ¤   return (ERROR);
b88cf7 ··¤ }
e138e7 ··¤ return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
99030b --- 574,584 ----
13de7b ··
38b195 ··¤ hashp = (HTAB *)dbp->internal;
976d77 ··¤ if (flag && flag != R_CURSOR) {
0fe51c ! ¤ ¤   hashp->h_errno = errno = EINVAL;
f0ea37 ··¤ ¤   return (ERROR);
008cf7 ··¤ }
70a4ff ··¤ if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
74686e ! ¤ ¤   hashp->h_errno = errno = EPERM;
2eea37 ··¤ ¤   return (ERROR);
718cf7 ··¤ }
ac38e7 ··¤ return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
3337aa ***************
f20806 *** 729,735 ****
74de7b ··
50b195 ··¤ hashp = (HTAB *)dbp->internal;
eec1a2 ··¤ if (flag && flag != R_FIRST && flag != R_NEXT) {
1eca29 ! ¤ ¤   hashp->errno = errno = EINVAL;
7dea37 ··¤ ¤   return (ERROR);
7b8cf7 ··¤ }
2bda06 ··#ifdef HASH_STATISTICS
079c5f --- 729,735 ----
b2de7b ··
68b195 ··¤ hashp = (HTAB *)dbp->internal;
6cc1a2 ··¤ if (flag && flag != R_FIRST && flag != R_NEXT) {
54e51c ! ¤ ¤   hashp->h_errno = errno = EINVAL;
f0ea37 ··¤ ¤   return (ERROR);
238cf7 ··¤ }
a1da06 ··#ifdef HASH_STATISTICS
4ec85f *** ./hash/ndbm.c.bak¤  Fri May 12 11:02:06 1995
dd8c62 --- ./hash/ndbm.c¤  Fri May 12 11:02:54 1995
6137aa ***************
265f99 *** 180,186 ****
e87472 ··¤ HTAB *hp;
3fde7b ··
9d9a9a ··¤ hp = (HTAB *)db->internal;
bc34ef ! ¤ return (hp->errno);
15df1c ··}
07de7b ··
e2614e ··extern int
83cbc0 --- 180,186 ----
1a7472 ··¤ HTAB *hp;
3fde7b ··
149a9a ··¤ hp = (HTAB *)db->internal;
d1e1ce ! ¤ return (hp->h_errno);
d6df1c ··}
7ade7b ··
20614e ··extern int
9137aa ***************
255b73 *** 190,196 ****
9a7472 ··¤ HTAB *hp;
--e82d 001c9ef997f4010006b Page 3 of db.1.85.patch
8bde7b ··
0d9a9a ··¤ hp = (HTAB *)db->internal;
6f7d9d ! ¤ hp->errno = 0;
dc45e2 ··¤ return (0);
4fdf1c ··}
0cde7b ··
efcf2a --- 190,196 ----
a87472 ··¤ HTAB *hp;
d3de7b ··
5b9a9a ··¤ hp = (HTAB *)db->internal;
3ed187 ! ¤ hp->h_errno = 0;
9545e2 ··¤ return (0);
92df1c ··}
c9de7b ··
--5b9b 001c37fe82c4010006c Page 1 of install.sh
e7c274 #!/bin/sh
8a68d6 # simple BSD-like install replacement
8da601 #
1b7d1d # Copyright (c) 1994 The Regents of the University of Michigan
94a601 #
32af5a
cf7576 MODE=0755
4b8025 USAGE="usage: $0 [-c] [-m mode] file dir"
3eaf5a
ef3604 while [ $# != 0 ]; do
8aa246 ····case "$1" in
882854 ····-c)
01b212 ¤   ;;
7e384f ····-m)
6340ba ¤   MODE=$2
a02597 ¤   shift
3ab212 ¤   ;;
43b23c ····-*)
7ed605 ¤   echo "$USAGE"
6fa8a2 ¤   exit 1
f0b212 ¤   ;;
823a39 ····*)
60968c ¤   break
feb212 ¤   ;;
809189 ····esac
a6a955 ····shift
72065f done
85af5a
88a26d if [ $# != 2 ]; then
4544fe ····echo "$USAGE"
284d30 ····exit 1
88ce83 fi
c8af5a
ae8d2b FILE=$1
5c6157 DIR=$2
aeaf5a
4503a4 cp $FILE $DIR
f6d91e if [ -d $DIR ]; then
f6faa2 ····chmod $MODE $DIR/`basename $FILE`
1f523c else
faa601 #
ef59e7 # DIR is really the destination file
8ba601 #
4b6117 ····chmod $MODE $DIR
c3ce83 fi
--a45e 000c441c6dc4010006d Page 1 of mkdep
be3eea #!/bin/sh -
dda601 #
386f59 # Copyright (c) 1987 Regents of the University of California.
195a50 # All rights reserved.
a9a601 #
8b97d6 # Redistribution and use in source and binary forms are permitted
45d5b7 # provided that the above copyright notice and this paragraph are
9b65c4 # duplicated in all such forms and that any documentation,
d6b14a # advertising materials, and other materials related to such
6b0b20 # distribution and use acknowledge that the software was developed
2c91f0 # by the University of California, Berkeley. ·The name of the
4e5858 # University may not be used to endorse or promote products derived
0e091f # from this software without specific prior written permission.
75d36f # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2f3f02 # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
7a2388 # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
b0a601 #
ea9e79 #¤  @(#)mkdep.sh¤   5.12 (Berkeley) 6/30/88
e9a601 #
7bb938 # We now use whatever path is already set by the invoker
3390f5 #PATH=/bin:/usr/bin:/usr/ucb
f4cd76 #export PATH
3faf5a
8b1a5c set -e¤ ¤   ¤   ¤   # exit immediately if any errors occur
c1af5a
50ffb0 MAKE=Makefile¤  ¤   ¤   # default makefile name is "Makefile"
b7951a NOSLASH="no"¤   ¤   ¤   # by default, / dependencies are included
5a5da5 CC=cc¤  ¤   ¤   ¤   # default compiler is cc
82af5a
3e0a5f while :
0fe552 ¤   do case "$1" in
32ce47 ¤   ¤   # -f allows you to select a makefile name
e85887 ¤   ¤   -f)
3976d1 ¤   ¤   ¤   MAKE=$2
eb8e61 ¤   ¤   ¤   shift; shift ;;
89af5a
6c394d ¤   ¤   # -c allows you to select a compiler to use (default is cc)
b5613a ¤   ¤   -c)
9aea4f ¤   ¤   ¤   CC=$2
568e61 ¤   ¤   ¤   shift; shift ;;
3baf5a
feaed7 ¤   ¤   # the -p flag produces "program: program.c" style dependencies
c37db6 ¤   ¤   # so .o's don't get produced
4c0bcb ¤   ¤   -p)
ff24d8 ¤   ¤   ¤   SED='s;\.o;;'
36ad48 ¤   ¤   ¤   shift ;;
a3af5a
b5ad24 ¤   ¤   # the -s flag removes dependencies to files that begin with /
74e4af ¤   ¤   -s)
2ed6df ¤   ¤   ¤   NOSLASH=yes;
4cad48 ¤   ¤   ¤   shift ;;
20af5a
35f341 #¤  ¤   -*)¤shift ;;
f7af5a
c008c2 ¤   ¤   *)
ca117d ¤   ¤   ¤   break ;;
601b81 ¤   esac
c4065f done
60af5a
6c7697 if [ $# = 0 ] ; then
c082b8 ¤   echo 'usage: mkdep [-p] [-f makefile] [flags] file ...'
a4a8a2 ¤   exit 1
23ce83 fi
8eaf5a
289a6f if [ ! -w $MAKE ]; then
15360a ¤   echo "mkdep: no writeable file \"$MAKE\""
dca8a2 ¤   exit 1
78ce83 fi
1eaf5a
be634d TMP=/tmp/mkdep$$
33af5a
c461d2 trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
--4afb 001cf8009424010006d Page 2 of mkdep
e0af5a
ec73cb cp $MAKE ${MAKE}.bak
41af5a
a450b4 sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
95af5a
585c3d cat << _EOF_ >> $TMP
98a8d3 # DO NOT DELETE THIS LINE -- mkdep uses it.
e23c8b # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
ffaf5a
48111a _EOF_
56af5a
ccf16b # If your compiler doesn't have -M, add it. ·If you can't, the next two
e01b9b # lines will try and replace the "cc -M". ·The real problem is that this
b1fbc6 # hack can't deal with anything that requires a search path, and doesn't
8af315 # even try for anything using bracket (<>) syntax.
e9a601 #
f00c9f # egrep '^#include[ ¤   ]*".*"' /dev/null $* |
cea7a1 # sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
86af5a
994426 $CC -M $* |
7e1971 sed "
81399c ¤   s; \./; ;g
defacb ¤   $SED" |
ae3d1e awk '
3067e6 $1 ~ /:/ {
42e2a5 ¤   filenm=$1
a303e1 ¤   dep=$2
50efe6 }
d48029 $1 !~ /:/ {
ba2989 ¤   dep=$1
3befe6 }
de6f2b /.*/ {
ef789c ¤   if ( noslash = "yes" && dep ~ /^\// ) next
7d6906 ¤   if (filenm != prev) {
bcba17 ¤   ¤   if (rec != "")
384962 ¤   ¤   ¤   print rec;
c4b93f ¤   ¤   rec = filenm " " dep;
8c7f97 ¤   ¤   prev = filenm;
139371 ¤   }
8f665a ¤   else {
e7597a ¤   ¤   if (length(rec dep) > 78) {
834962 ¤   ¤   ¤   print rec;
478e37 ¤   ¤   ¤   rec = filenm " " dep;
180fe4 ¤   ¤   }
a60e1d ¤   ¤   else
ac1ae6 ¤   ¤   ¤   rec = rec " " dep
eb9371 ¤   }
836fe7 ····}
9e6a9a END {
37a1d4 ¤   print rec
deabf4 }' noslash="$NOSLASH" >> $TMP
6aaf5a
0e5c3d cat << _EOF_ >> $TMP
56af5a
29f6c8 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
eb111a _EOF_
17af5a
30ac69 # copy to preserve permissions
bd616c cp $TMP $MAKE
5c252d rm -f ${MAKE}.bak $TMP
cf72c2 exit 0
--2ebe 000f94a29ba4010006e Page 1 of uname.sh
e7c274 #!/bin/sh
ea8b83 # simple BSD-like uname replacement for those systems without it
13a601 #
7ffd5a # Copyright (c) 1995 The Regents of the University of Michigan
b8a601 #
16af5a
19af5a
35a601 #
eb8be5 # if /bin/uname or /usr/bin/uname exists, just use it
221ced # ...unless we are on SCO, where the provided uname is bad
71a601 #
330deb if ·[ ! -f /usr/bin/swconfig ]; then
b3759e ····if [ -f /bin/uname ]; then
c72f7e ¤   exec /bin/uname $*
e5df8a ····fi
e7af5a
24a9c7 ····if [ -f /usr/bin/uname ]; then
80f885 ¤   exec /usr/bin/uname $*
fbdf8a ····fi
a1ce83 fi
28af5a
fdaf5a
b4a601 #
1156cb # flags to keep track of what to output
b6a601 #
17417e PRINT_SYSTEM=0
0bbc1c PRINT_VERSION=0
a5a8cc PRINT_RELEASE=0
08af5a
baa601 #
be2351 # process arguments
3aa601 #
49565c USAGE="usage: $0 [-s] [-v] [-r]"
86af5a
4c3604 while [ $# != 0 ]; do
d9a246 ····case "$1" in
1cadc1 ····-s)
9bba05 ¤   PRINT_SYSTEM=1
40b212 ¤   ;;
d5947c ····-v)
7c32b7 ¤   PRINT_VERSION=1
deb212 ¤   ;;
7cf71d ····-r)
8d2667 ¤   PRINT_RELEASE=1
11b212 ¤   ;;
dc3a39 ····*)
b8d605 ¤   echo "$USAGE"
f6a8a2 ¤   exit 1
b3b212 ¤   ;;
d19189 ····esac
c8a955 ····shift
7d065f done
40af5a
09af5a
daa601 #
2d61ab # print system name by default
5aa601 #
d5ce44 if [ $PRINT_VERSION = "0" -a $PRINT_RELEASE = "0" ]; then
0cf3cb ····PRINT_SYSTEM=1
a4ce83 fi
21af5a
7aaf5a
53a601 #
141fd5 # default to unknown everything...
64a601 #
741e65 SYSTEM="Unknown-System"
d8b17f VERSION="Unknown-Version"
ba59e9 RELEASE="Unknown-Release"
7eaf5a
7da601 #
4f5935 # check to see if we are on a machine that runs NextSTEP or SCO
f9a601 #
--3ad4 0014a0149094010006e Page 2 of uname.sh
ae81b4 if [ -r /NextApps ]; then
a10062 ····SYSTEM="NeXTSTEP"
05a1e0 elif [ -f /usr/bin/swconfig ]; then
c5ea8e ····SYSTEM="SCO"
6dce83 fi
08af5a
79af5a
59a601 #
ee3a81 # output requested information
e0a601 #
de109e OUTPUT=0
fb748d if [ $PRINT_SYSTEM = "1" ]; then
7841a0 ····echo -n "$SYSTEM"
999331 ····OUTPUT=1
ccce83 fi
abaf5a
cbf27a if [ $PRINT_VERSION = "1" ]; then
3936c5 ····if [ $OUTPUT = "1" ]; then
cebb86 ¤   echo -n " $VERSION"
d6842c ····else
0397bf ¤   echo -n "$VERSION"
d2097f ¤   OUTPUT=1
7adf8a ····fi
40ce83 fi
cdaf5a
e83112 if [ $PRINT_RELEASE = "1" ]; then
8736c5 ····if [ $OUTPUT = "1" ]; then
98cad2 ¤   echo -n " $RELEASE"
6b842c ····else
61e6eb ¤   echo -n "$RELEASE"
57097f ¤   OUTPUT=1
c8df8a ····fi
7dce83 fi
50af5a
3cb186 echo
28af5a
4a72c2 exit 0
--007f 001c4f3b08b4010006f Page 1 of version
c4498f 3.3
--668b 0010f1edb9240100070 Page 1 of Make-template
54b0af #-----------------------------------------------------------------------------
0cdb1c # Copyright (c) 1994 Regents of the University of Michigan.
155a50 # All rights reserved.
1aa601 #
fb97d6 # Redistribution and use in source and binary forms are permitted
69d6ca # provided that this notice is preserved and that due credit is given
4e8ee9 # to the University of Michigan at Ann Arbor. The name of the University
0e3eb9 # may not be used to endorse or promote products derived from this
440baf # software without specific prior written permission. This software
d8feea # is provided ``as is'' without express or implied warranty.
49a601 #
145c7d # ······LDAP include file makefile
d0a601 #
e1b0af #-----------------------------------------------------------------------------
18af5a
95d756 LDAPSRC=..
45af5a
e50925 all:¤   ldapconfig.h FORCE
15291f ¤   @if [ ! -z "$(SYSEXITSPATH)" -a ! -r sysexits.h ]; then \
c6082b ¤   ····echo "$(LN) $(SYSEXITSPATH) sysexits.h"; \
91f5cd ¤   ····$(LN) $(SYSEXITSPATH) sysexits.h; \
350861 ¤   else \
b2783e ¤   ····exit 0; \
cb2ec9 ¤   fi
ebaf5a
b0d03c ldapconfig.h:¤  ldapconfig.h.edit Makefile
56eb13 ¤   @$(RM) $@
568e83 ¤   @echo "/*" > $@; ·\
9e5b83 ········echo " * This file was automatically generated. ·Do not edit it." >> $@¶
eb5ad1 ; \
c04f69 ········echo " * Instead, edit the file ldapconfig.h.edit. ·See the LDAP" >> $@¶
fd5ad1 ; \
3c23e1 ········echo " * INSTALL file for more information." >> $@; \
cb343f ········echo " */ " >> $@; \
db103f ········echo "" >> $@; \
d8ea64 ¤   $(SED) -e 's;%ETCDIR%;$(RUNTIMEETCDIR);' ldapconfig.h.edit >> $@; \
ae6998 ¤   $(CHMOD) 444 $@
c2af5a
bbd8ae install: all FORCE
349c0b ¤   ¤   -$(MKDIR) -p $(INCLUDEDIR)
ebc62a ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldap.h $(INCLUDEDIR)
b3b125 ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 lber.h $(INCLUDEDIR)
9d874d ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 proto-lber.h $(INCLUDEDIR)
edf042 ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 proto-ldap.h $(INCLUDEDIR)
7dd344 ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 disptmpl.h $(INCLUDEDIR)
867b1c ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 srchpref.h $(INCLUDEDIR)
77af5a
e9adf8 depend:¤FORCE
76af5a
3cb5ca clean:¤ FORCE
a7af5a
bc875c veryclean:¤ clean
48eeb9 ¤   $(RM) ldapconfig.h
f52755 ¤   @if [ ! -z "$(SYSEXITSPATH)" ]; then \
577882 ¤   ····echo "$(RM) sysexits.h"; \
4b39a5 ¤   ····$(RM) sysexits.h; \
940861 ¤   else \
79783e ¤   ····exit 0; \
3d2ec9 ¤   fi
3baf5a
45a513 links:
50cfbf ¤   @echo "making links in `$(PWD)`
f9266a ¤   @$(LN) .src/*.h .
fd196f ¤   @cp .src/ldapconfig.h.edit .
0f94dc ¤   @-$(RM) ldapconfig.h
--6e1a 000e912dc5c40100071 Page 1 of Makefile
2539de # --------------------------------------------------------
324229 # ·This file was automatically generated. ·Do not edit it.
c0e6af # ·Instead, edit the Make-common file (located in the root
eef11f # ·(of the LDAP distribution). ·See the LDAP INSTALL file
a05811 # ·for more information.
ee39de # --------------------------------------------------------
05a601 #
2db0af #-----------------------------------------------------------------------------
06db1c # Copyright (c) 1994 Regents of the University of Michigan.
d95a50 # All rights reserved.
aea601 #
8c97d6 # Redistribution and use in source and binary forms are permitted
c6d6ca # provided that this notice is preserved and that due credit is given
378ee9 # to the University of Michigan at Ann Arbor. The name of the University
a83eb9 # may not be used to endorse or promote products derived from this
b10baf # software without specific prior written permission. This software
8dfeea # is provided ``as is'' without express or implied warranty.
95a601 #
225c7d # ······LDAP include file makefile
e4a601 #
ebb0af #-----------------------------------------------------------------------------
63af5a
88d756 LDAPSRC=..
0faf5a
120925 all:¤   ldapconfig.h FORCE
44291f ¤   @if [ ! -z "$(SYSEXITSPATH)" -a ! -r sysexits.h ]; then \
7b082b ¤   ····echo "$(LN) $(SYSEXITSPATH) sysexits.h"; \
f3f5cd ¤   ····$(LN) $(SYSEXITSPATH) sysexits.h; \
3f0861 ¤   else \
d3783e ¤   ····exit 0; \
f72ec9 ¤   fi
23af5a
76d03c ldapconfig.h:¤  ldapconfig.h.edit Makefile
c9eb13 ¤   @$(RM) $@
0b8e83 ¤   @echo "/*" > $@; ·\
725b83 ········echo " * This file was automatically generated. ·Do not edit it." >> $@¶
f55ad1 ; \
964f69 ········echo " * Instead, edit the file ldapconfig.h.edit. ·See the LDAP" >> $@¶
2e5ad1 ; \
1723e1 ········echo " * INSTALL file for more information." >> $@; \
8c343f ········echo " */ " >> $@; \
ce103f ········echo "" >> $@; \
1aea64 ¤   $(SED) -e 's;%ETCDIR%;$(RUNTIMEETCDIR);' ldapconfig.h.edit >> $@; \
6a6998 ¤   $(CHMOD) 444 $@
39af5a
ecd8ae install: all FORCE
dc9c0b ¤   ¤   -$(MKDIR) -p $(INCLUDEDIR)
4fc62a ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldap.h $(INCLUDEDIR)
21b125 ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 lber.h $(INCLUDEDIR)
c6874d ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 proto-lber.h $(INCLUDEDIR)
3ff042 ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 proto-ldap.h $(INCLUDEDIR)
58d344 ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 disptmpl.h $(INCLUDEDIR)
3e7b1c ¤   ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 srchpref.h $(INCLUDEDIR)
86af5a
02adf8 depend:¤FORCE
dcaf5a
c2b5ca clean:¤ FORCE
0aaf5a
19875c veryclean:¤ clean
c1eeb9 ¤   $(RM) ldapconfig.h
2a2755 ¤   @if [ ! -z "$(SYSEXITSPATH)" ]; then \
437882 ¤   ····echo "$(RM) sysexits.h"; \
e939a5 ¤   ····$(RM) sysexits.h; \
e80861 ¤   else \
37783e ¤   ····exit 0; \
082ec9 ¤   fi
ccaf5a
7aa513 links:
82cfbf ¤   @echo "making links in `$(PWD)`
2a266a ¤   @$(LN) .src/*.h .
7e196f ¤   @cp .src/ldapconfig.h.edit .
e994dc ¤   @-$(RM) ldapconfig.h
--1ea0 0005443522a40100071 Page 2 of Makefile
5ea601 #
b5ffdb # Do NOT edit this file -- it is automatically appended to all Makefiles
7969dc # except the LDAP top-level Makefile. See the LDAP INSTALL file for more
641fc7 # information.
e8a601 #
82b0af #-----------------------------------------------------------------------------
fbdb1c # Copyright (c) 1994 Regents of the University of Michigan.
205a50 # All rights reserved.
80a601 #
e297d6 # Redistribution and use in source and binary forms are permitted
57d6ca # provided that this notice is preserved and that due credit is given
068ee9 # to the University of Michigan at Ann Arbor. The name of the University
d93eb9 # may not be used to endorse or promote products derived from this
720baf # software without specific prior written permission. This software
eefeea # is provided ``as is'' without express or implied warranty.
bea601 #
623287 # ······LDAP standard Make defines (appended to all but top-level Makefile)
e3a601 #
ecb0af #-----------------------------------------------------------------------------
25af5a
58ad9f # DEFS are included in CFLAGS
3fd084 DEFS¤   = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
c50785 ¤   ¤   $(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
8bf00e ¤   ¤   $(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
8b997b ¤   ¤   $(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
bd87f1 ¤   ¤   $(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
1aaf5a
4940cd # SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
adb18b SERVERDEFS¤ = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
5814ba ¤   ¤   ¤   $(NO_SETPROCTITLE) $(PEPSY_DUMP)
55af5a
90a601 #
eb0ce2 # ISODELIBS are used in server/ldapd builds
6fa601 #
fe4e01 ISODELIBS¤  = $(ISODEBASELIBS) -lm $(ISODETURBOLIBS)
70af5a
d10558 # ACFLAGS are added to CFLAGS but not passed to mkdep, lint, etc
3a17ce ACFLAGS¤¤   = $(EXTRACFLAGS) $(UNPROTOCFLAGS)
33af5a
e42eb4 # ALDFLAGS are always placed near the beginning of all linker (cc -o) commands
ba49dd ALDFLAGS¤   = $(EXTRALDFLAGS) $(PLATFORMLDFLAGS)
78af5a
e4233d # ALIBS are always placed at the end of all linker (cc -o) commands
211ec7 ALIBS¤  ¤   = $(PLATFORMLIBS) $(THREADSLIB) -lstdc++
7faf5a
9ea601 #
f5c229 # default definitions for Unix utilities (may be over-ridden in Make-platform)
f8fd75 CC¤ = cc
677e42 MAKE¤   = make
2a1a1a RANLIB¤ = ranlib
9c85b9 AR¤ = ar
70ba00 RM¤ = rm -f
b89865 MV¤ = mv -f
619324 CP¤ = cp
bc229f CHMOD¤  = chmod
eb65eb CAT¤= cat
44d1bd LN¤ = ln -s
7f41b6 HARDLN¤ = ln
a1c699 TAIL¤   = tail
e5e675 SED¤= sed
1701f7 LINT¤   = lint
b23a04 5LINT¤  = lint
92c291 MKDIR¤  = mkdir
583f60 INSTALL¤= install
c90106 INSTALLFLAGS = -c
01735e BASENAME= basename
54d84e DIRNAME¤= dirname
14720b MKDEP¤  = $(LDAPSRC)/build/mkdep -c gcc -s -f Make-template
49e392 PWD¤= pwd
e996d7 DATE¤   = date
9da7d0 HOSTNAME= hostname
54af5a
--4e0f 0006c986c6d40100071 Page 3 of Makefile
e0af5a
53a601 #
ff592a # empty target used to force rules to be invoked
12a601 #
ac2b40 FORCE:
67af5a
1ba601 #
f8c8ac # LDAP SunOS5 GNU C Make-platform file
e4a601 #
feaf5a
77a601 #
efa68c # add any platform-specific overrides below here
5ba601 #
60af5a
69af5a
18a601 #
d895cf # -------------------------------------------------------------------------
60ba80 # you will probably not need to edit anything below this point
4395cf # -------------------------------------------------------------------------
094b2c CC¤ = gcc
84af5a
5a1dfe # ranlib not needed under SunOS5
4f7716 RANLIB¤ = ""
bdaf5a
919a13 # give full path to hostname since it may not be in user's path
95ea97 HOSTNAME=/usr/ucb/hostname
07af5a
037720 # don't count on /usr/ucb/install being present or first in path
ec10f3 INSTALL=$(LDAPSRC)/build/install.sh
e1af5a
9beaf0 PLATFORMCFLAGS=¤-Dsunos5 -D_REENTRANT
318289 PLATFORMLIBS= -lsocket -lnsl -lgen
321dc2 THREADS= -DTHREAD_SUNOS5_LWP
1b7e25 THREADSLIB=-lthread
90b0af #-----------------------------------------------------------------------------
5935f2 # Copyright (c) 1997 PGP inc.
ed5a50 # All rights reserved.
63a601 #
d7b0af #-----------------------------------------------------------------------------
0fdd01 #############################################################################
17a917 ## Edit the following variables to have appropriate values for your system ##
b6dd01 #############################################################################
67af5a
9b515b vpath %.a $(OUTDIR):$(LDIR):$(PGPCDKDIR)/unix:$(DBLDIR):$(PGPPFLDIR) \
5adc18 ¤   ··$(PGPCDKDIR)/priv/keyserver: \
fdaacf ¤   ··$(PGPCDKDIR)/../network/pgpsockets/unix/src
75af5a
69dd01 #############################################################################
ac736d ## LDAP install paths ·····················································##
c7dd01 #############################################################################
cda601 #
e2c05e # by default, everything is installed below INSTROOT
574f10 # servers, config files, etc. are put in ETCDIR
6054a5 # include files get put in INCLUDEDIR
3c48e9 # libraries are put in LIBDIR
98f935 # man pages are put under MANDIR
01d9d9 # programs end-users will run are put in BINDIR
b5a601 #
f9b837 # Moved INSTROOT declaration to top-level Makefile
7137ce # useful for automation.
eaaf5a
cc8fed ETCDIR= $(INSTROOT)/etc
e34bf1 INCLUDEDIR= $(INSTROOT)/include
434e47 LIBDIR= $(INSTROOT)/unix
bce906 MANDIR= $(INSTROOT)/doc
2d2d8f BINDIR= $(INSTROOT)/unix
9daf5a
0ea601 #
52ca77 # if you want things to run in a different directory from where they
c12c1a # are installed, set this accordingly (this path gets compiled into a
ea8e97 # few binaries). otherwise, leave it alone.
6c63ae RUNTIMEETCDIR= $(ETCDIR)
--7389 00041db6d2a40100071 Page 4 of Makefile
e0af5a
dbdd01 #############################################################################
ae7145 ## General compiler options ···············································##
1cdd01 #############################################################################
ff64cf # Passed to every compile (cc or gcc). ·This is where you put -O or -g, etc.
22c073 # Added -D_REENTRANT per ldap doc. for Solaris builds <galileo>
717adf OPT=-g
ef255c DEBUG=1
d5ab6e UNFINISHED=1
69ed5a EXTRACFLAGS=-D_REENTRANT $(OPT) -fwritable-strings \
aa1d76 ············-DPGP_DEBUG=$(DEBUG) -DUNFINISHED_CODE_ALLOWED=$(UNFINISHED)
21af5a
03e6cd # Passed to every link (ld). ·Include -g here if you did in EXTRACFLAGS.
f2af5a
8cb23e EXTRALDFLAGS=$(OPT)
acaf5a
42dd01 #############################################################################
0dce69 ## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ······##
a3b9e8 ## If you don't want to build it, you can skip this section. ··············##
45dd01 #############################################################################
2ea601 #
4c11c2 # To build the ldap server, uncomment the HAVEISODE line,
855803 # and the section describing build settings for your version of isode.
93a601 #
9aa865 HAVEISODE = yes
b8af5a
e6dd01 #############################################################################
30c146 ## If you don't want to run slapd, skip this section. ·····················##
e5dd01 #############################################################################
55a601 #
c6ac20 # To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
548e0c # line and select the SLAPD_BACKENDS you want to use. If you enable the
b52d3b # LDBM backend, also select one of the LDBM backends.
7b8fbf MAKESLAPD= yes
e5a601 #
9c4d71 # remove the defines for backends you don't want to enable
28743e SLAPD_BACKENDS= -DLDAP_LDBM
7ca601 #
159374 # If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
a6cee2 # to specify which low-level database package to use. ·There are
f4f92f # four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
9aa601 #
5ea9bd # berkeley db btree package
2e7e82 LDBMBACKEND=-DLDBM_USE_DBBTREE21
d0b496 LDBMINCLUDE=
3528ff LDBMLIB=-ldb
b9b402 # berkeley db hash package
d49bc9 #LDBMBACKEND=-DLDBM_USE_DBHASH
ffd345 #LDBMINCLUDE=-I/usr/local/db/include
eb0e7e #LDBMLIB=-ldb
1a2a77 # gnu dbm (gdbm)
b0ed29 #LDBMBACKEND=-DLDBM_USE_GDBM
589187 #LDBMINCLUDE=-I$(INSTROOT)/servers/slapd/db
d56c04 #LDBMLIB=-lgdbm
041874 # standard unix ndbm
24bc4d #LDBMBACKEND=-DLDBM_USE_NDBM
8da601 #
317ffd # if you want to use a non-default threads package change these lines
f942ab #THREADS=-DNO_THREADS
e68180 #THREADSLIB=
deaf5a
fbdd01 #############################################################################
6c1692 ## General options ························································##
a8dd01 #############################################################################
7ac8ae # uncomment this line to enable debugging code (a good idea)
8275d8 LDAP_DEBUG=-DLDAP_DEBUG
98af5a
8fb923 # uncomment this line to turn on a few U of Michigan specific things
3d8cea #UOFM=-DUOFM
3caf5a
bfbce0 # uncomment this line to delete a few printfs in the lber and ldap libraries.
41d6e3 #NO_USERINTERFACE=-DNO_USERINTERFACE
--22fe 0019bfcdc6c40100071 Page 5 of Makefile
e0af5a
602982 # uncomment this line to include Connectionless LDAP support
381910 #CLDAP=-DCLDAP
4aaf5a
1a021f # uncomment this line to eliminate local caching support in the libldap
ccdecc #NO_CACHE=-DNO_CACHE
d9af5a
48197d # uncomment this line to enable support for LDAP referrals in libldap
f21c28 LDAP_REFERRALS=-DLDAP_REFERRALS
9eaf5a
f84c1c # uncomment this line to use soundex for approximate matches in slapd.
1c856d # the default is to use the metaphone algorithm.
9b1fa8 #PHONETIC=-DSOUNDEX
--07a3 0009837ebde40100072 Page 1 of disptmpl.h
bc38e5 /*
09515b ·* Copyright (c) 1993, 1994 Regents of the University of Michigan.
60599a ·* All rights reserved.
44775e ·*
22b855 ·* Redistribution and use in source and binary forms are permitted
ec9795 ·* provided that this notice is preserved and that due credit is given
bf1873 ·* to the University of Michigan at Ann Arbor. The name of the University
148805 ·* may not be used to endorse or promote products derived from this
b974fe ·* software without specific prior written permission. This software
1a2a32 ·* is provided ``as is'' without express or implied warranty.
a0775e ·*
388af2 ·* disptmpl.h: ·display template library defines
bbddde ·* 7 March 1994 by Mark C Smith
16495d ·*/
abaf5a
801614 #ifndef _DISPTMPL_H
871f93 #define _DISPTMPL_H
74af5a
893379 #ifdef __cplusplus
846dad extern "C" {
6b7454 #endif
c7af5a
c3af5a
ad1ef0 #define LDAP_TEMPLATE_VERSION¤  1
24af5a
fa38e5 /*
40d85b ·* general types of items (confined to most significant byte)
19495d ·*/
92283e #define LDAP_SYN_TYPE_TEXT¤ ¤   0x01000000L
afeba6 #define LDAP_SYN_TYPE_IMAGE¤¤   0x02000000L
d36157 #define LDAP_SYN_TYPE_BOOLEAN¤  ¤   0x04000000L
920a4d #define LDAP_SYN_TYPE_BUTTON¤   ¤   0x08000000L
275430 #define LDAP_SYN_TYPE_ACTION¤   ¤   0x10000000L
4caf5a
ddaf5a
5b38e5 /*
52d4aa ·* syntax options (confined to second most significant byte)
28495d ·*/
b96fa2 #define LDAP_SYN_OPT_DEFER¤ ¤   0x00010000L
82af5a
0daf5a
3595d7 /*·
3d88cc ·* display template item syntax ids (defined by common agreement)
15430c ·* these are the valid values for the ti_syntaxid of the tmplitem
494437 ·* struct (defined below). ·A general type is encoded in the
5c79cd ·* most-significant 8 bits, and some options are encoded in the next
03201a ·* 8 bits. ·The lower 16 bits are reserved for the distinct types.
32495d ·*/
ec6043 #define LDAP_SYN_CASEIGNORESTR¤ ( 1 | LDAP_SYN_TYPE_TEXT )
f741a0 #define LDAP_SYN_MULTILINESTR¤  ( 2 | LDAP_SYN_TYPE_TEXT )
f2ebf1 #define LDAP_SYN_DN¤¤   ( 3 | LDAP_SYN_TYPE_TEXT )
b32aa6 #define LDAP_SYN_BOOLEAN¤   ( 4 | LDAP_SYN_TYPE_BOOLEAN )
c93e0b #define LDAP_SYN_JPEGIMAGE¤ ( 5 | LDAP_SYN_TYPE_IMAGE )
ff1614 #define LDAP_SYN_JPEGBUTTON¤( 6 | LDAP_SYN_TYPE_BUTTON | LDAP_SYN_OPT_DEFER )
00601d #define LDAP_SYN_FAXIMAGE¤  ( 7 | LDAP_SYN_TYPE_IMAGE )
860136 #define LDAP_SYN_FAXBUTTON¤ ( 8 | LDAP_SYN_TYPE_BUTTON | LDAP_SYN_OPT_DEFER )
b18347 #define LDAP_SYN_AUDIOBUTTON¤   ( 9 | LDAP_SYN_TYPE_BUTTON | LDAP_SYN_OPT_DEFER¶
245d36 ·)
0a84fe #define LDAP_SYN_TIME¤  ¤   ( 10 | LDAP_SYN_TYPE_TEXT )
62cd8d #define LDAP_SYN_DATE¤  ¤   ( 11 | LDAP_SYN_TYPE_TEXT )
c106c7 #define LDAP_SYN_LABELEDURL¤( 12 | LDAP_SYN_TYPE_TEXT )
eff057 #define LDAP_SYN_SEARCHACTION¤  ( 13 | LDAP_SYN_TYPE_ACTION )
f61f09 #define LDAP_SYN_LINKACTION¤( 14 | LDAP_SYN_TYPE_ACTION )
9a2006 #define LDAP_SYN_ADDDNACTION¤   ( 15 | LDAP_SYN_TYPE_ACTION )
d17bf0 #define LDAP_SYN_VERIFYDNACTION ( 16 | LDAP_SYN_TYPE_ACTION )
0b6f77 #define LDAP_SYN_RFC822ADDR¤( 17 | LDAP_SYN_TYPE_TEXT )
a5af5a
ebaf5a
1238e5 /*
7cfaea ·* handy macros
45495d ·*/
98426f #define LDAP_GET_SYN_TYPE( syid )¤  ((syid) & 0xFF000000L )
--8db3 0001b16793640100072 Page 2 of disptmpl.h
b2fe2d #define LDAP_GET_SYN_OPTIONS( syid )¤   ((syid) & 0x00FF0000L )
04af5a
75af5a
5838e5 /*
ca8ec9 ·* display options for output routines (used by entry2text and friends)
cb495d ·*/
e638e5 /*
952833 ·* use calculated label width (based on length of longest label in
b99589 ·* template) instead of contant width
f0495d ·*/
a8a84f #define LDAP_DISP_OPT_AUTOLABELWIDTH¤   0x00000001L
63ecc5 #define LDAP_DISP_OPT_HTMLBODYONLY¤ 0x00000002L
bcaf5a
a638e5 /*
ec0095 ·* perform search actions (applies to ldap_entry2text_search only)·
d2495d ·*/
82e3a9 #define LDAP_DISP_OPT_DOSEARCHACTIONS¤  0x00000002L
b6af5a
aa38e5 /*
affeb4 ·* include additional info. relevant to "non leaf" entries only
ed6851 ·* used by ldap_entry2html and ldap_entry2html_search to include "Browse"
3c4195 ·* and "Move Up" HREFs
5f495d ·*/
4f4143 #define LDAP_DISP_OPT_NONLEAF¤  ¤   0x00000004L
7caf5a
9eaf5a
3938e5 /*
3de269 ·* display template item options (may not apply to all types)
aebcef ·* if this bit is set in ti_options, it applies.
ae495d ·*/
3c4c66 #define LDAP_DITEM_OPT_READONLY¤¤   0x00000001L
d5e0d3 #define LDAP_DITEM_OPT_SORTVALUES¤  0x00000002L
b0ade5 #define LDAP_DITEM_OPT_SINGLEVALUED¤0x00000004L
a32411 #define LDAP_DITEM_OPT_HIDEIFEMPTY¤ 0x00000008L
ee30eb #define LDAP_DITEM_OPT_VALUEREQUIRED¤   0x00000010L
e8d2f2 #define LDAP_DITEM_OPT_HIDEIFFALSE¤ 0x00000020L¤/* booleans only */
a0af5a
7aaf5a
3daf5a
fa38e5 /*
6d338c ·* display template item structure
62495d ·*/
68654e struct ldap_tmplitem {
2d93c0 ····unsigned long¤  ¤   ti_syntaxid;
df26fd ····unsigned long¤  ¤   ti_options;
104009 ····char ·¤ ¤   ¤   *ti_attrname;
a5f4c1 ····char¤   ¤   ¤   *ti_label;
91c82c ····char¤   ¤   ¤   **ti_args;
e59cef ····struct ldap_tmplitem¤   *ti_next_in_row;
8d8fd8 ····struct ldap_tmplitem¤   *ti_next_in_col;
5f2629 ····void¤   ¤   ¤   *ti_appdata;
e682f7 };
49af5a
edaf5a
5635b4 #define NULLTMPLITEM¤   ((struct ldap_tmplitem *)0)
2aaf5a
e9941f #define LDAP_SET_TMPLITEM_APPDATA( ti, datap )¤ \
04f5c1 ¤   (ti)->ti_appdata = (void *)(datap)
c4af5a
788d10 #define LDAP_GET_TMPLITEM_APPDATA( ti, type )¤  \
b207bf ¤   (type)((ti)->ti_appdata)
c8af5a
aa7c7e #define LDAP_IS_TMPLITEM_OPTION_SET( ti, option )¤  \
72f952 ¤   (((ti)->ti_options & option ) != 0 )
f6af5a
f1af5a
8538e5 /*
04a32a ·* object class array structure
98495d ·*/
8f2d0a struct ldap_oclist {
f74620 ····char¤   ¤   **oc_objclasses;
1b94e9 ····struct ldap_oclist¤ *oc_next;
--d95c 00043ea02f640100072 Page 3 of disptmpl.h
8082f7 };
abaf5a
ebe558 #define NULLOCLIST¤ ((struct ldap_oclist *)0)
31af5a
35af5a
1b38e5 /*
888afe ·* add defaults list
31495d ·*/
e33819 struct ldap_adddeflist {
a2aafb ····int¤¤   ¤   ad_source;
c0db53 #define LDAP_ADSRC_CONSTANTVALUE¤   1
e166ae #define LDAP_ADSRC_ADDERSDN¤¤   2
5fa37d ····char¤   ¤   *ad_attrname;
b995cd ····char¤   ¤   *ad_value;
517d1d ····struct ldap_adddeflist¤ *ad_next;
8782f7 };
f7af5a
3cc457 #define NULLADLIST¤ ((struct ldap_adddeflist *)0)
07af5a
c7af5a
3c38e5 /*
e7f5c2 ·* display template global options
4e2c21 ·* if this bit is set in dt_options, it applies.
11495d ·*/
3138e5 /*
1a8906 ·* users should be allowed to try to add objects of these entries
83495d ·*/
76777f #define LDAP_DTMPL_OPT_ADDABLE¤ ¤   0x00000001L
98af5a
7738e5 /*
ba068c ·* users should be allowed to do "modify RDN" operation of these entries
e4495d ·*/
977c90 #define LDAP_DTMPL_OPT_ALLOWMODRDN¤ 0x00000002L
7caf5a
6f38e5 /*
de10c0 ·* this template is an alternate view, not a primary view
b1495d ·*/
8876cd #define LDAP_DTMPL_OPT_ALTVIEW¤ ¤   0x00000004L
41af5a
e7af5a
9238e5 /*
e275bb ·* display template structure
cf495d ·*/
0f6060 struct ldap_disptmpl {
a44ca2 ····char¤   ¤   ¤   *dt_name;
6a1f21 ····char¤   ¤   ¤   *dt_pluralname;
317b0e ····char¤   ¤   ¤   *dt_iconname;
bcf50e ····unsigned long¤  ¤   dt_options;
710644 ····char¤   ¤   ¤   *dt_authattrname;
127668 ····char¤   ¤   ¤   *dt_defrdnattrname;
5f6d93 ····char¤   ¤   ¤   *dt_defaddlocation;
bbd565 ····struct ldap_oclist¤ ¤   *dt_oclist;
01bd52 ····struct ldap_adddeflist¤ *dt_adddeflist;
24dbc9 ····struct ldap_tmplitem¤   *dt_items;
75f5da ····void¤   ¤   ¤   *dt_appdata;
174137 ····struct ldap_disptmpl¤   *dt_next;
d382f7 };
aaaf5a
3d9ecd #define NULLDISPTMPL¤   ((struct ldap_disptmpl *)0)
84af5a
546765 #define LDAP_SET_DISPTMPL_APPDATA( dt, datap )¤ \
1378f4 ¤   (dt)->dt_appdata = (void *)(datap)
9baf5a
ac7e6a #define LDAP_GET_DISPTMPL_APPDATA( dt, type )¤  \
778b93 ¤   (type)((dt)->dt_appdata)
4eaf5a
28bdeb #define LDAP_IS_DISPTMPL_OPTION_SET( dt, option )¤  \
3c7467 ¤   (((dt)->dt_options & option ) != 0 )
52af5a
2e202c #define LDAP_TMPL_ERR_VERSION¤  1
7c49d7 #define LDAP_TMPL_ERR_MEM¤  2
43b135 #define LDAP_TMPL_ERR_SYNTAX¤   3
--9cbc 0000e755cf240100072 Page 4 of disptmpl.h
b470fa #define LDAP_TMPL_ERR_FILE¤ 4
7baf5a
8538e5 /*
1dbaa9 ·* buffer size needed for entry2text and vals2text
61495d ·*/
1793da #define LDAP_DTMPL_BUFSIZ¤  8192
d0af5a
e0af5a
ff719a #ifndef NEEDPROTOS
1baf5a
befe27 typedef int (*writeptype)();
59af5a
ad2812 int ldap_init_templates();
097fd3 int ldap_init_templates_buf();
308c15 void ldap_free_templates();
214e30 struct ldap_disptmpl *ldap_first_disptmpl();
e6546d struct ldap_disptmpl *ldap_next_disptmpl();
7ddcdd struct ldap_disptmpl *ldap_name2template();
b4f758 struct ldap_disptmpl *ldap_oc2template();
21ab91 char **ldap_tmplattrs();
c99c6b struct ldap_tmplitem *ldap_first_tmplrow();
9b9337 struct ldap_tmplitem *ldap_next_tmplrow();
7d45db struct ldap_tmplitem *ldap_first_tmplcol();
f04a87 struct ldap_tmplitem *ldap_next_tmplcol();
d6172c int ldap_entry2text_search();
a6dd1b int ldap_entry2text();
8f7082 int ldap_vals2text();
5b32c3 int ldap_entry2html_search();
062f4a int ldap_entry2html();
4e82d3 int ldap_vals2html();
23af5a
1b4b51 #else /* !NEEDPROTOS */
1faf5a
d0f6eb typedef int (*writeptype)( void *writeparm, char *p, int len );
8aaf5a
795c8b LDAPFUNCDECL int
afc161 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp );
e5af5a
605c8b LDAPFUNCDECL int
fefd68 ldap_init_templates_buf( char *buf, long buflen,
3617a1 ¤   struct ldap_disptmpl **tmpllistp );
09af5a
9cd275 LDAPFUNCDECL void
f95658 ldap_free_templates( struct ldap_disptmpl *tmpllist );
f8af5a
30f948 LDAPFUNCDECL struct ldap_disptmpl *
3fdfa5 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist );
67af5a
8af948 LDAPFUNCDECL struct ldap_disptmpl *
3f0811 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
518c2c ¤   struct ldap_disptmpl *tmpl );
46af5a
79f948 LDAPFUNCDECL struct ldap_disptmpl *
406f61 ldap_name2template( char *name, struct ldap_disptmpl *tmpllist );
1baf5a
ecf948 LDAPFUNCDECL struct ldap_disptmpl *
416105 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist );
06af5a
6322ca LDAPFUNCDECL char **
c33789 ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, int exclude,
cc09fe ¤   ·unsigned long syntaxmask );
e3af5a
edfc66 LDAPFUNCDECL struct ldap_tmplitem *
95dd91 ldap_first_tmplrow( struct ldap_disptmpl *tmpl );
6eaf5a
4cfc66 LDAPFUNCDECL struct ldap_tmplitem *
4043b3 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row );
80af5a
cbfc66 LDAPFUNCDECL struct ldap_tmplitem *
00111b ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row );
2daf5a
0efc66 LDAPFUNCDECL struct ldap_tmplitem *
--6dab 00131e8611240100072 Page 5 of disptmpl.h
7f33ca ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
12dcd5 ¤   struct ldap_tmplitem *col );
baaf5a
9d5c8b LDAPFUNCDECL int
4386ee ldap_entry2text( LDAP *ld, char *buf, LDAPMessage *entry,
a7e002 ¤   struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
9cd912 ¤   writeptype writeproc, void *writeparm, char *eol, int rdncount,
04aa54 ¤   unsigned long opts );
34af5a
c65c8b LDAPFUNCDECL int
af307f ldap_vals2text( LDAP *ld, char *buf, char **vals, char *label, int labelwidth,
72c0e4 ¤   unsigned long syntaxid, writeptype writeproc, void *writeparm,
36d801 ¤   char *eol, int rdncount );
5daf5a
085c8b LDAPFUNCDECL int
9c2bf7 ldap_entry2text_search( LDAP *ld, char *dn, char *base, LDAPMessage *entry,
90059d ¤   struct ldap_disptmpl *tmpllist, char **defattrs, char ***defvals,
ebd912 ¤   writeptype writeproc, void *writeparm, char *eol, int rdncount,
a1aa54 ¤   unsigned long opts );
22af5a
ae5c8b LDAPFUNCDECL int
d40844 ldap_entry2html( LDAP *ld, char *buf, LDAPMessage *entry,
efe002 ¤   struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
53d912 ¤   writeptype writeproc, void *writeparm, char *eol, int rdncount,
0f57ec ¤   unsigned long opts, char *urlprefix, char *base );
73af5a
f65c8b LDAPFUNCDECL int
d7fe88 ldap_vals2html( LDAP *ld, char *buf, char **vals, char *label, int labelwidth,
0ec0e4 ¤   unsigned long syntaxid, writeptype writeproc, void *writeparm,
c6a394 ¤   char *eol, int rdncount, char *urlprefix );
12af5a
895c8b LDAPFUNCDECL int
34e335 ldap_entry2html_search( LDAP *ld, char *dn, char *base, LDAPMessage *entry,
51059d ¤   struct ldap_disptmpl *tmpllist, char **defattrs, char ***defvals,
60d912 ¤   writeptype writeproc, void *writeparm, char *eol, int rdncount,
beb078 ¤   unsigned long opts, char *urlprefix );
613f09 #endif /* !NEEDPROTOS */
16af5a
a2af5a
5a3379 #ifdef __cplusplus
5eefe6 }
117454 #endif
315fa4 #endif /* _DISPTMPL_H */
--7afe 000e9da384c40100073 Page 1 of lber.h
bc38e5 /*
81f590 ·* Copyright (c) 1990 Regents of the University of Michigan.
c4599a ·* All rights reserved.
bf775e ·*
eeb855 ·* Redistribution and use in source and binary forms are permitted
249795 ·* provided that this notice is preserved and that due credit is given
fc1873 ·* to the University of Michigan at Ann Arbor. The name of the University
df8805 ·* may not be used to endorse or promote products derived from this
7f74fe ·* software without specific prior written permission. This software
3d2a32 ·* is provided ``as is'' without express or implied warranty.
ef495d ·*/
13af5a
56b9ff #ifndef _LBER_H
c49af7 #define _LBER_H
0daf5a
2f7e35 #if PGPSOCKETSLDAP¤ ¤   ¤   /* jason */
995519 #include "pgpSockets.h"
ebafb9 #if PGP_WIN32
d0a21a #include "pgpAsyncDNS.h"
8f7454 #endif
677454 #endif
4aaf5a
627d03 /* This is a rig to re-map the allocation routines from within the cert */
92354c /* ··server only. ·The problem is allocs need a memory mgr and the routines */
81ef33 /* ··aren't designed to take one so a global (g_MemMgr) is used. */
81cf14 #ifdef PGPKEYSERVER
90f865 #include "pgpSrvStd.h"
8a7454 #endif
02af5a
f33379 #ifdef __cplusplus
c36dad extern "C" {
3c7454 #endif
56af5a
b5b58f #if !defined( NEEDPROTOS ) && defined(__STDC__)
bc407e #define NEEDPROTOS¤ 1
fb7454 #endif
1faf5a
5bb750 /* BER classes and mask */
ec714c #define LBER_CLASS_UNIVERSAL¤   0x00
632ff1 #define LBER_CLASS_APPLICATION¤ 0x40
aa0ca0 #define LBER_CLASS_CONTEXT¤ 0x80
fa9463 #define LBER_CLASS_PRIVATE¤ 0xc0
f4eb96 #define LBER_CLASS_MASK¤¤   0xc0
13af5a
96bdc2 /* BER encoding type and mask */
b8adcf #define LBER_PRIMITIVE¤ ¤   0x00
c3af8a #define LBER_CONSTRUCTED¤   0x20
4b0e07 #define LBER_ENCODING_MASK¤ 0x20
f5af5a
fdd069 #define LBER_BIG_TAG_MASK¤  0x1f
eeed60 #define LBER_MORE_TAG_MASK¤ 0x80
6faf5a
0438e5 /*
96a08a ·* Note that LBER_ERROR and LBER_DEFAULT are values that can never appear
22adc5 ·* as valid BER tags, and so it is safe to use them to report errors. ·In
15f1b1 ·* fact, any tag for which the following is true is invalid:
fcdc11 ·* ····(( tag & 0x00000080 ) != 0 ) && (( tag & 0xFFFFFF00 ) != 0 )
96495d ·*/
b0daf0 #define LBER_ERROR¤ ¤   0xffffffffL
276f8e #define LBER_DEFAULT¤   ¤   0xffffffffL
b2af5a
a58ccb /* general BER types we know about */
b1ad53 #define LBER_BOOLEAN¤   ¤   0x01L
b4d890 #define LBER_INTEGER¤   ¤   0x02L
348798 #define LBER_BITSTRING¤ ¤   0x03L
736814 #define LBER_OCTETSTRING¤   0x04L
a61e94 #define LBER_NULL¤  ¤   0x05L
f53946 #define LBER_ENUMERATED¤¤   0x0aL
e281c8 #define LBER_SEQUENCE¤  ¤   0x30L¤  /* constructed */
99baad #define LBER_SET¤   ¤   0x31L¤  /* constructed */
8faf5a
e9c69b #define OLD_LBER_SEQUENCE¤  0x10L¤  /* w/o constructed bit - broken */
--d600 000b413dfa340100073 Page 2 of lber.h
8c5ebf #define OLD_LBER_SET¤   ¤   0x11L¤  /* w/o constructed bit - broken */
b4af5a
90504c #ifdef NEEDPROTOS
ccf305 typedef int (*BERTranslateProc)( char **bufp, unsigned long *buflenp,
be9dfb ¤   int free_input );
796133 #else /* NEEDPROTOS */
ede494 typedef int (*BERTranslateProc)();
cc8634 #endif /* NEEDPROTOS */
6aaf5a
f7af37 typedef struct berelement {
c33266 ¤   char¤   ¤   *ber_buf;
c96ae1 ¤   char¤   ¤   *ber_ptr;
fdb4b6 ¤   char¤   ¤   *ber_end;
7ec352 ¤   struct seqorset¤*ber_sos;
fd4821 ¤   unsigned long¤  ber_tag;
2248b3 ¤   unsigned long¤  ber_len;
b725b3 ¤   int¤¤   ber_usertag;
10c9d3 ¤   char¤   ¤   ber_options;
2766ea #define LBER_USE_DER¤   ¤   0x01
e02687 #define LBER_USE_INDEFINITE_LEN¤0x02
4ce20c #define LBER_TRANSLATE_STRINGS¤ 0x04
1d0e57 ¤   char¤   ¤   *ber_rwptr;
8967b1 ¤   BERTranslateProc ber_encode_translate_proc;
5b7f33 ¤   BERTranslateProc ber_decode_translate_proc;
83d52d } BerElement;
c6a0a7 #define NULLBER¤((BerElement *) 0)
87af5a
671f4a typedef struct sockbuf {
3924c3 #if PGPSOCKETSLDAP¤ /* jason */
a4da9c ¤   PGPSocketRef¤   ¤   sb_sd;
2fafb9 #if PGP_WIN32
78ad5f ¤   PGPAsyncHostEntryRef¤   ref;
317454 #endif
30db21 #else
770d62 ¤   int¤¤   ¤   ¤   ¤   sb_sd; /* Making this PGPSocketRef may affect key serve¶
a03ccd r. */
b07454 #endif
ca7f68 ¤   int¤¤   ¤   ¤   ¤   sb_bTLS;¤   /* Is this a TLS connection? */
3daf5a
f3310a ¤   BerElement¤ sb_ber;
edaf5a
a4d27b ¤   int¤¤   sb_naddr;¤  /* > 0 implies using CLDAP (UDP) */
efacf9 ¤   void¤   ¤   *sb_useaddr;¤   /* pointer to sockaddr to use next */
b08134 ¤   void¤   ¤   *sb_fromaddr;¤  /* pointer to message source sockaddr */
799ce2 ¤   void¤   ¤   **sb_addrs;¤/* actually an array of pointers to
2fd738 ¤   ¤   ¤   ¤   ¤   ¤   sockaddrs */
ceaf5a
4ae1a7 ¤   int¤¤   sb_options;¤/* to support copying ber elements */
887ef1 #define LBER_TO_FILE¤   ¤   0x01¤   /* to a file referenced by sb_fd ··*/
2d7cad #define LBER_TO_FILE_ONLY¤  0x02¤   /* only write to file, not network */
ce2c64 #define LBER_MAX_INCOMING_SIZE¤ 0x04¤   /* impose limit on incoming stuff ·*/
ee2c17 #define LBER_NO_READ_AHEAD¤ 0x08¤   /* read only as much as requested ·*/
3a933c ¤   int¤¤   sb_fd;
15c99e ¤   long¤   ¤   sb_max_incoming;
b7e3c0 } Sockbuf;
7f2d02 #define READBUFSIZ¤ 8192
44af5a
2c5590 typedef struct seqorset {
eff420 ¤   BerElement¤ *sos_ber;
190a24 ¤   unsigned long¤  sos_clen;
94434e ¤   unsigned long¤  sos_tag;
c260c4 ¤   char¤   ¤   *sos_first;
bb618e ¤   char¤   ¤   *sos_ptr;
345ded ¤   struct seqorset¤*sos_next;
5d0dca } Seqorset;
42fdb6 #define NULLSEQORSET¤   ((Seqorset *) 0)
22af5a
ff3cb3 /* structure for returning a sequence of octet strings + length */
579685 struct berval {
22de65 ¤   unsigned long¤  bv_len;
051e27 ¤   char¤   ¤   *bv_val;
b482f7 };
--1a96 00166525a7540100073 Page 3 of lber.h
e0af5a
b20ef0 //#undef WINSOCK
70af5a
8e719a #ifndef NEEDPROTOS
85f263 extern BerElement *ber_alloc();
6fef8d extern BerElement *der_alloc();
a3bc05 extern BerElement *ber_alloc_t();
4c7f33 extern BerElement *ber_dup();
966cb8 extern int lber_debug;
e902b3 extern void ber_bvfree();
7b7b6a extern void ber_bvecfree();
8c7c25 extern struct berval *ber_bvdup();
440e02 extern void ber_dump();
627ea0 extern void ber_sos_dump();
785259 extern void lber_bprint();
8268d4 extern void ber_reset();
924a28 extern void ber_init();
026133 #else /* NEEDPROTOS */
432de0 #if defined(WINSOCK) && !defined(PGPSOCKETSLDAP) /* jason */
2f1552 #include "proto-lb.h"
59db21 #else
21e86f #include "proto-lber.h"
2f7454 #endif
5d8634 #endif /* NEEDPROTOS */
c9af5a
042908 #if !defined(__alpha) || defined(VMS)
a7af5a
95543a #define LBER_HTONL( l )¤htonl( l )
382084 #define LBER_NTOHL( l )¤ntohl( l )
d8af5a
abdeb3 #else /* __alpha */
1538e5 /*
e4b3b9 ·* htonl and ntohl on the DEC Alpha under OSF 1 seem to only swap the
fd3ea7 ·* lower-order 32-bits of a (64-bit) long, so we define correct versions
2ebe8c ·* here.
7a495d ·*/
62eb29 #define LBER_HTONL( l )¤(((long)htonl( (l) & 0x00000000FFFFFFFF )) << 32 \
a6f5c9 ····¤   ¤   ¤   | htonl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
08af5a
02d395 #define LBER_NTOHL( l )¤(((long)ntohl( (l) & 0x00000000FFFFFFFF )) << 32 \
049688 ····¤   ¤   ¤   | ntohl( ( (l) & 0xFFFFFFFF00000000 ) >> 32 ))
7e25ce #endif /* __alpha */
13af5a
b0af5a
1e38e5 /*
4ec7fb ·* SAFEMEMCPY is an overlap-safe copy from s to d of n bytes
f8495d ·*/
cfc583 #ifdef MACOS
483e78 #define SAFEMEMCPY( d, s, n )¤  BlockMoveData( (Ptr)s, (Ptr)d, n )
756c94 #else /* MACOS */
c52224 #ifdef sunos4
20c731 #define SAFEMEMCPY( d, s, n )¤  bcopy( s, d, n )
897ec9 #else /* sunos4 */
71f847 #define SAFEMEMCPY( d, s, n )¤  memmove( d, s, n )
67ecf5 #endif /* sunos4 */
22e962 #endif /* MACOS */
5aaf5a
32af5a
463379 #ifdef __cplusplus
c8efe6 }
377454 #endif
6606f4 #endif /* _LBER_H */
--64ed 000da16a09940100074 Page 1 of ldap.h
bc38e5 /*
81f590 ·* Copyright (c) 1990 Regents of the University of Michigan.
c4599a ·* All rights reserved.
bf775e ·*
eeb855 ·* Redistribution and use in source and binary forms are permitted
249795 ·* provided that this notice is preserved and that due credit is given
fc1873 ·* to the University of Michigan at Ann Arbor. The name of the University
df8805 ·* may not be used to endorse or promote products derived from this
7f74fe ·* software without specific prior written permission. This software
3d2a32 ·* is provided ``as is'' without express or implied warranty.
ef495d ·*/
13af5a
dfb563 #ifndef _LDAP_H
e7966b #define _LDAP_H
daaf5a
5eb779 #include "lber.h"
a5af5a
5c3379 #ifdef __cplusplus
dd6dad extern "C" {
387454 #endif
4aaf5a
08bd3d #ifndef PGPSOCKETSLDAP /* jason */
01bf62 #if WINSOCK
f6f2ef #include "msdos.h"
3d2d5f #include <winsock.h>
8d7454 #endif
b4df0f #endif /* PGPSOCKETSLDAP */
0baf5a
57b58f #if !defined( NEEDPROTOS ) && defined(__STDC__)
5c407e #define NEEDPROTOS¤ 1
0c7454 #endif
1aaf5a
8f318c #define LDAP_PORT¤  389
d15caf #define LDAP_SECURE_PORT¤   636
9547b2 #define LDAP_VERSION1¤  1
7961a7 #define LDAP_VERSION2¤  2
118e51 #define LDAP_VERSION¤   LDAP_VERSION2
74af5a
1a87b1 #define COMPAT20
11dd6d #define COMPAT30
43d6b8 #if defined(COMPAT20) || defined(COMPAT30)
132e1f #define COMPAT
a77454 #endif
28af5a
7bb635 #define LDAP_MAX_ATTR_LEN¤  100
3eaf5a
1f8aa4 /* debugging stuff */
1b2639 #ifdef LDAP_DEBUG
1d1a14 extern int¤ ldap_debug;
e7b7b1 #ifdef LDAP_SYSLOG
30f59d extern int¤ ldap_syslog;
2fe5f8 extern int¤ ldap_syslog_level;
797454 #endif
dfa092 #define LDAP_DEBUG_TRACE¤   0x001
1a9e83 #define LDAP_DEBUG_PACKETS¤ 0x002
01fc6e #define LDAP_DEBUG_ARGS¤¤   0x004
67aa98 #define LDAP_DEBUG_CONNS¤   0x008
f17f2b #define LDAP_DEBUG_BER¤ ¤   0x010
1bb373 #define LDAP_DEBUG_FILTER¤  0x020
d5bb7b #define LDAP_DEBUG_CONFIG¤  0x040
595f70 #define LDAP_DEBUG_ACL¤ ¤   0x080
634829 #define LDAP_DEBUG_STATS¤   0x100
2f0ea0 #define LDAP_DEBUG_STATS2¤  0x200
4a88fa #define LDAP_DEBUG_SHELL¤   0x400
24603d #define LDAP_DEBUG_PARSE¤   0x800
8d6cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
3fda4f #define LDAP_DEBUG_THREADID¤0x1000
707454 #endif
a7c90a #define LDAP_DEBUG_ERROR¤   0x2000
981a86 #define LDAP_DEBUG_ANY¤ ¤   0xffff
ccaf5a
da3260 enum ErrorLogLevels_ {
--86fc 000eb5498f440100074 Page 2 of ldap.h
17a7ac ¤   kErrLevelVerbose¤   = 0x0001u,
fa9e25 ¤   kErrLevelInfo¤  ¤   = 0x0002u,
cd94f7 ¤   kErrLevelWarning¤   = 0x0004u,
cab688 ¤   kErrLevelError¤ ¤   = 0x0008u
8482f7 };
3aaf5a
3c314a void
9d3eba LogError(int lLevel, const char *pszFormat, ...);
18af5a
af2664 #ifdef WIN32
043abe #define strcasecmp¤ ¤   stricmp
73a0fb #define strncasecmp¤¤   strnicmp
5a7454 #endif
6daf5a
90b7b1 #ifdef LDAP_SYSLOG
f76cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
fbf07a extern __declspec(dllimport) unsigned long __stdcall·
3aba7d ¤   GetCurrentThreadId(void);¤  ¤   /* Defined in windows.h */
71db6e #define Debug( level, fmt, arg1, arg2, arg3 )¤  \
08a1d8 ¤   { \
93c4db ¤   ¤   if ( ldap_debug & level ) { \
67be2f ¤   ¤   ¤   if (ldap_debug & LDAP_DEBUG_THREADID) \
c4dad7 ¤   ¤   ¤   ¤   fprintf( stderr, "[% 4.4d] " fmt, GetCurrentThreadId(), \
7f180c ¤   ¤   ¤   ¤   arg1, arg2, arg3 ); \
678b78 ¤   ¤   ¤   else \
020752 ¤   ¤   ¤   ¤   fprintf( stderr, fmt, arg1, arg2, arg3 ); \
0f0e08 ¤   ¤   ¤   fflush(stderr); \
6fd342 ¤   ¤   } \
a69371 ¤   }
c7db21 #else
91db6e #define Debug( level, fmt, arg1, arg2, arg3 )¤  \
5da1d8 ¤   { \
6e0cee ¤   ¤   if ( ldap_debug & level ) \
c58805 ¤   ¤   ¤   fprintf( stderr, fmt, arg1, arg2, arg3 ); \
539371 ¤   }
f67454 #endif
1b41b4 #else /* LDAP_SYSLOG */
b698bc #ifndef WINSOCK
29cf92 #define Debug( level, fmt, arg1, arg2, arg3 ) \
9c0cee ¤   ¤   if ( ldap_debug & level ) \
a1be8a ¤   ¤   ¤   fprintf( stderr, fmt, arg1, arg2, arg3 );
881202 #else /* !WINSOCK */
2e2e81 extern void Debug( int level, char* fmt, ... );
02ba9b #endif /* !WINSOCK */
8435ec #endif /* LDAP_SYSLOG */
897c42 #else /* LDAP_DEBUG */
b450d4 #define Debug( level, fmt, arg1, arg2, arg3 )
df9b45 #endif /* LDAP_DEBUG */
6baf5a
5b95d7 /*·
d0a4e9 ·* specific LDAP instantiations of BER types we know about
1f495d ·*/
62af5a
79bcab /* general stuff */
ed3754 #define LDAP_TAG_MESSAGE¤   0x30L¤  /* tag is 16 + constructed bit */
8280e1 #define OLD_LDAP_TAG_MESSAGE¤   0x10L¤  /* forgot the constructed bit ·*/
91e9db #define LDAP_TAG_MSGID¤ ¤   0x02L
8caf5a
a9f3b8 /* possible operations a client can invoke */
c29fc2 #define LDAP_REQ_BIND¤  ¤   ¤   0x60L¤  /* application + constructed */
2074d8 #define LDAP_REQ_UNBIND¤¤   ¤   0x42L¤  /* application + primitive ··*/
58a448 #define LDAP_REQ_SEARCH¤¤   ¤   0x63L¤  /* application + constructed */
965241 #define LDAP_REQ_MODIFY¤¤   ¤   0x66L¤  /* application + constructed */
2576f2 #define LDAP_REQ_ADD¤   ¤   ¤   0x68L¤  /* application + constructed */
acf655 #define LDAP_REQ_DELETE¤¤   ¤   0x4aL¤  /* application + primitive ··*/
fd536f #define LDAP_REQ_MODRDN¤¤   ¤   0x6cL¤  /* application + constructed */
57ff1a #define LDAP_REQ_COMPARE¤   ¤   0x6eL¤  /* application + constructed */
1c7cdd #define LDAP_REQ_ABANDON¤   ¤   0x50L¤  /* application + primitive ··*/
2caf5a
9c2891 /* version 3.0 compatibility stuff */
257e0e #define LDAP_REQ_UNBIND_30¤ ¤   0x62L
eb03d5 #define LDAP_REQ_DELETE_30¤ ¤   0x6aL
--c715 0007f942b4840100074 Page 3 of ldap.h
318a3e #define LDAP_REQ_ABANDON_30¤¤   0x70L
2daf5a
7e95d7 /*·
9771c9 ·* old broken stuff for backwards compatibility - forgot application tag
9509c0 ·* and constructed/primitive bit
aa495d ·*/
4f3c9e #define OLD_LDAP_REQ_BIND¤  ¤   0x00L
0ddbdb #define OLD_LDAP_REQ_UNBIND¤¤   0x02L
ab78df #define OLD_LDAP_REQ_SEARCH¤¤   0x03L
97b4a1 #define OLD_LDAP_REQ_MODIFY¤¤   0x06L
984dc5 #define OLD_LDAP_REQ_ADD¤   ¤   0x08L
fc69a5 #define OLD_LDAP_REQ_DELETE¤¤   0x0aL
71286f #define OLD_LDAP_REQ_MODRDN¤¤   0x0cL
c2434b #define OLD_LDAP_REQ_COMPARE¤   ¤   0x0eL
7b9926 #define OLD_LDAP_REQ_ABANDON¤   ¤   0x10L
84af5a
07ba37 /* possible result types a server can return */
d08628 #define LDAP_RES_BIND¤  ¤   ¤   0x61L¤  /* application + constructed */
6b74a6 #define LDAP_RES_SEARCH_ENTRY¤  ¤   0x64L¤  /* application + constructed */
fcc7c5 #define LDAP_RES_SEARCH_RESULT¤ ¤   0x65L¤  /* application + constructed */
1d4bab #define LDAP_RES_MODIFY¤¤   ¤   0x67L¤  /* application + constructed */
e26f18 #define LDAP_RES_ADD¤   ¤   ¤   0x69L¤  /* application + constructed */
653a52 #define LDAP_RES_DELETE¤¤   ¤   0x6bL¤  /* application + constructed */
2fcf74 #define LDAP_RES_MODRDN¤¤   ¤   0x6dL¤  /* application + constructed */
ac9a5f #define LDAP_RES_COMPARE¤   ¤   0x6fL¤  /* application + constructed */
6f3577 #define LDAP_RES_ANY¤   ¤   ¤   (-1L)
14af5a
c2e61f /* old broken stuff for backwards compatibility */
f648c1 #define OLD_LDAP_RES_BIND¤  ¤   0x01L
d9c9d4 #define OLD_LDAP_RES_SEARCH_ENTRY¤  0x04L
d08d75 #define OLD_LDAP_RES_SEARCH_RESULT¤ 0x05L
d1c0fe #define OLD_LDAP_RES_MODIFY¤¤   0x07L
a9399a #define OLD_LDAP_RES_ADD¤   ¤   0x09L
2da842 #define OLD_LDAP_RES_DELETE¤¤   0x0bL
a38ae9 #define OLD_LDAP_RES_MODRDN¤¤   0x0dL
f0b7ac #define OLD_LDAP_RES_COMPARE¤   ¤   0x0fL
38af5a
625adf /* authentication methods available */
1a7da1 #define LDAP_AUTH_NONE¤ ¤   0x00L¤  /* no authentication¤   ¤   ··*/
45a753 #define LDAP_AUTH_SIMPLE¤   0x80L¤  /* context specific + primitive ··*/
8df1fe #define LDAP_AUTH_KRBV4¤¤   0xffL¤  /* means do both of the following */
7618f9 #define LDAP_AUTH_KRBV41¤   0x81L¤  /* context specific + primitive ··*/
4b43f2 #define LDAP_AUTH_KRBV42¤   0x82L¤  /* context specific + primitive ··*/
5eaf5a
eca800 /* 3.0 compatibility auth methods */
27a525 #define LDAP_AUTH_SIMPLE_30¤0xa0L¤  /* context specific + constructed */
091a8f #define LDAP_AUTH_KRBV41_30¤0xa1L¤  /* context specific + constructed */
554184 #define LDAP_AUTH_KRBV42_30¤0xa2L¤  /* context specific + constructed */
e1af5a
88802a /* old broken stuff */
4c039c #define OLD_LDAP_AUTH_SIMPLE¤   0x00L
ca3c6b #define OLD_LDAP_AUTH_KRBV4¤0x01L
da7342 #define OLD_LDAP_AUTH_KRBV42¤   0x02L
41af5a
e5347a /* filter types */
1adf9c #define LDAP_FILTER_AND¤¤   0xa0L¤  /* context specific + constructed */
520046 #define LDAP_FILTER_OR¤ ¤   0xa1L¤  /* context specific + constructed */
bce882 #define LDAP_FILTER_NOT¤¤   0xa2L¤  /* context specific + constructed */
b704c5 #define LDAP_FILTER_EQUALITY¤   0xa3L¤  /* context specific + constructed */
f70fed #define LDAP_FILTER_SUBSTRINGS¤ 0xa4L¤  /* context specific + constructed */
003842 #define LDAP_FILTER_GE¤ ¤   0xa5L¤  /* context specific + constructed */
24806d #define LDAP_FILTER_LE¤ ¤   0xa6L¤  /* context specific + constructed */
b851d4 #define LDAP_FILTER_PRESENT¤0x87L¤  /* context specific + primitive ··*/
c81a6e #define LDAP_FILTER_APPROX¤ 0xa8L¤  /* context specific + constructed */
1eaf5a
769c8f /* 3.0 compatibility filter types */
b51cbb #define LDAP_FILTER_PRESENT_30¤ 0xa7L¤  /* context specific + constructed */
60af5a
70802a /* old broken stuff */
1a2909 #define OLD_LDAP_FILTER_AND¤¤   0x00L
feed89 #define OLD_LDAP_FILTER_OR¤ ¤   0x01L
7f1320 #define OLD_LDAP_FILTER_NOT¤¤   0x02L
--d85f 00071f27bd440100074 Page 4 of ldap.h
87b300 #define OLD_LDAP_FILTER_EQUALITY¤   0x03L
8c6a56 #define OLD_LDAP_FILTER_SUBSTRINGS¤ 0x04L
ec2318 #define OLD_LDAP_FILTER_GE¤ ¤   0x05L
08a021 #define OLD_LDAP_FILTER_LE¤ ¤   0x06L
4374fa #define OLD_LDAP_FILTER_PRESENT¤¤   0x07L
5f0194 #define OLD_LDAP_FILTER_APPROX¤ ¤   0x08L
4eaf5a
9a5825 /* substring filter component types */
c712c6 #define LDAP_SUBSTRING_INITIAL¤ 0x80L¤  /* context specific */
442fcd #define LDAP_SUBSTRING_ANY¤ 0x81L¤  /* context specific */
d7ecb2 #define LDAP_SUBSTRING_FINAL¤   0x82L¤  /* context specific */
adaf5a
b55dd1 /* 3.0 compatibility substring filter component types */
ab4454 #define LDAP_SUBSTRING_INITIAL_30¤  0xa0L¤  /* context specific */
a2d3e7 #define LDAP_SUBSTRING_ANY_30¤  ¤   0xa1L¤  /* context specific */
44e727 #define LDAP_SUBSTRING_FINAL_30¤¤   0xa2L¤  /* context specific */
74af5a
7a802a /* old broken stuff */
af2f07 #define OLD_LDAP_SUBSTRING_INITIAL¤ 0x00L
0f30cf #define OLD_LDAP_SUBSTRING_ANY¤ ¤   0x01L
db823b #define OLD_LDAP_SUBSTRING_FINAL¤   0x02L
53af5a
1996a7 /* search scopes */
527884 #define LDAP_SCOPE_BASE¤¤   0x00
654be4 #define LDAP_SCOPE_ONELEVEL¤0x01
be4bf7 #define LDAP_SCOPE_SUBTREE¤ 0x02
d1af5a
f4f5c3 /* for modifications */
10fd3a typedef struct ldapmod {
f93ee3 ¤   int¤¤   mod_op;
1cc37b #define LDAP_MOD_ADD¤   ¤   0x00
139439 #define LDAP_MOD_DELETE¤¤   0x01
dcd2d1 #define LDAP_MOD_REPLACE¤   0x02
0c8bd5 #define LDAP_MOD_BVALUES¤   0x80
cb3fbe ¤   char¤   ¤   *mod_type;
e6e29a ¤   union {
f2eb1b ¤   ¤   char¤   ¤   **modv_strvals;
3c353e ¤   ¤   struct berval¤  **modv_bvals;
9fd107 ¤   } mod_vals;
b13e9e #define mod_values¤ mod_vals.modv_strvals
84985d #define mod_bvalues¤mod_vals.modv_bvals
44bdf4 ¤   struct ldapmod¤ *mod_next;
f085f7 } LDAPMod;
53af5a
b995d7 /*·
ed8161 ·* possible error codes we can return
13495d ·*/
7caf5a
01b8db #define LDAP_SUCCESS¤   ¤   ¤   0x00
4ed859 #define LDAP_OPERATIONS_ERROR¤  ¤   0x01
9f58a0 #define LDAP_PROTOCOL_ERROR¤¤   0x02
6660a4 #define LDAP_TIMELIMIT_EXCEEDED¤¤   0x03
16908a #define LDAP_SIZELIMIT_EXCEEDED¤¤   0x04
44619b #define LDAP_COMPARE_FALSE¤ ¤   0x05
031fbb #define LDAP_COMPARE_TRUE¤  ¤   0x06
852668 #define LDAP_STRONG_AUTH_NOT_SUPPORTED¤ 0x07
80fcba #define LDAP_STRONG_AUTH_REQUIRED¤  0x08
ff8506 #define LDAP_PARTIAL_RESULTS¤   ¤   0x09
c3af5a
a9793e #define LDAP_NO_SUCH_ATTRIBUTE¤ ¤   0x10
73db5a #define LDAP_UNDEFINED_TYPE¤¤   0x11
038265 #define LDAP_INAPPROPRIATE_MATCHING¤0x12
1bfc68 #define LDAP_CONSTRAINT_VIOLATION¤  0x13
d0b2db #define LDAP_TYPE_OR_VALUE_EXISTS¤  0x14
3218a0 #define LDAP_INVALID_SYNTAX¤¤   0x15
14af5a
f5e5a7 #define LDAP_NO_SUCH_OBJECT¤¤   0x20
e84aff #define LDAP_ALIAS_PROBLEM¤ ¤   0x21
9636a9 #define LDAP_INVALID_DN_SYNTAX¤ ¤   0x22
d169b8 #define LDAP_IS_LEAF¤   ¤   ¤   0x23
43bf65 #define LDAP_ALIAS_DEREF_PROBLEM¤   0x24
71af5a
--fa16 000930a131340100074 Page 5 of ldap.h
b82f7c #define NAME_ERROR(n)¤  ((n & 0xf0) == 0x20)
59af5a
c2dd87 #define LDAP_INAPPROPRIATE_AUTH¤¤   0x30
a96da1 #define LDAP_INVALID_CREDENTIALS¤   0x31
578215 #define LDAP_INSUFFICIENT_ACCESS¤   0x32
c5f042 #define LDAP_BUSY¤  ¤   ¤   0x33
b54b5a #define LDAP_UNAVAILABLE¤   ¤   0x34
a72689 #define LDAP_UNWILLING_TO_PERFORM¤  0x35
17d617 #define LDAP_LOOP_DETECT¤   ¤   0x36
66af5a
719a2b #define LDAP_NAMING_VIOLATION¤  ¤   0x40
501f65 #define LDAP_OBJECT_CLASS_VIOLATION¤0x41
3ca46b #define LDAP_NOT_ALLOWED_ON_NONLEAF¤0x42
e84424 #define LDAP_NOT_ALLOWED_ON_RDN¤¤   0x43
01e555 #define LDAP_ALREADY_EXISTS¤¤   0x44
db33cf #define LDAP_NO_OBJECT_CLASS_MODS¤  0x45
3043b9 #define LDAP_RESULTS_TOO_LARGE¤ ¤   0x46
40af5a
5b5c0d #define LDAP_OTHER¤ ¤   ¤   0x50
61f25b #define LDAP_SERVER_DOWN¤   ¤   0x51
03620c #define LDAP_LOCAL_ERROR¤   ¤   0x52
187366 #define LDAP_ENCODING_ERROR¤¤   0x53
bb996c #define LDAP_DECODING_ERROR¤¤   0x54
b03950 #define LDAP_TIMEOUT¤   ¤   ¤   0x55
e390e9 #define LDAP_AUTH_UNKNOWN¤  ¤   0x56
ccdea0 #define LDAP_FILTER_ERROR¤  ¤   0x57
d9e8c7 #define LDAP_USER_CANCELLED¤¤   0x58
dd444a #define LDAP_PARAM_ERROR¤   ¤   0x59
3877f5 #define LDAP_NO_MEMORY¤ ¤   ¤   0x5a
eaaf5a
afaf5a
a2f514 /* default limit on nesting of referrals */
551bbf #define LDAP_DEFAULT_REFHOPLIMIT¤   5
a3af5a
ce38e5 /*
1033ac ·* This structure represents both ldap messages and ldap responses.
f88ed1 ·* These are really the same, except in the case of search responses,
712246 ·* where a response has multiple messages.
92495d ·*/
5faf5a
c81b87 typedef struct ldapmsg {
da6219 ¤   int¤¤   lm_msgid;¤  /* the message id */
4d1bca ¤   int¤¤   lm_msgtype;¤/* the message type */
63be2b ¤   BerElement¤ *lm_ber;¤   /* the ber encoded message contents */
ce5a1f ¤   struct ldapmsg¤ *lm_chain;¤ /* for search - next msg in the resp */
dd875c ¤   struct ldapmsg¤ *lm_next;¤  /* next response */
f43e07 ¤   unsigned long¤  lm_time;¤   /* used to maintain cache */
968bea } LDAPMessage;
a747f8 #define NULLMSG¤((LDAPMessage *) NULL)
46af5a
edaf5a
967f8d #ifdef LDAP_REFERRALS
3338e5 /*
d1eb65 ·* structure for tracking LDAP server host, ports, DNs, etc.
ed495d ·*/
639b60 typedef struct ldap_server {
b43b43 ¤   char¤   ¤   ¤   *lsrv_host;
fbdf07 ¤   char¤   ¤   ¤   *lsrv_dn;¤  /* if NULL, use default */
7f7433 ¤   int¤¤   ¤   lsrv_port;
4a93ef ¤   struct ldap_server¤ *lsrv_next;
937456 } LDAPServer;
48af5a
daaf5a
9438e5 /*
e96374 ·* structure for representing an LDAP server connection
73495d ·*/
c5dbfb typedef struct ldap_conn {
1926ea ¤   Sockbuf¤¤   ¤   *lconn_sb;
d1c6a6 ¤   int¤¤   ¤   lconn_refcnt;
3ef51d ¤   unsigned long¤  ¤   lconn_lastused;¤/* time */
537af9 ¤   int¤¤   ¤   lconn_status;
931258 #define LDAP_CONNST_NEEDSOCKET¤ ¤   1
--c890 0002f670aa840100074 Page 6 of ldap.h
428445 #define LDAP_CONNST_CONNECTING¤ ¤   2
1790b3 #define LDAP_CONNST_CONNECTED¤  ¤   3
9bba91 ¤   LDAPServer¤ ¤   *lconn_server;
2794f8 ¤   char¤   ¤   ¤   *lconn_krbinstance;
f21202 ¤   struct ldap_conn¤   *lconn_next;
1bdcc7 } LDAPConn;
16af5a
f5af5a
e638e5 /*
314344 ·* structure used to track outstanding requests
c5495d ·*/
31635d typedef struct ldapreq {
2ac352 ¤   int¤¤   lr_msgid;¤  /* the message id */
6e74c8 ¤   int¤¤   lr_status;¤ /* status of request */
8de1e2 #define LDAP_REQST_INPROGRESS¤  1
ea6fa1 #define LDAP_REQST_CHASINGREFS¤ 2
252dcc #define LDAP_REQST_NOTCONNECTED¤3
3c6193 #define LDAP_REQST_WRITING¤ 4
4deb60 ¤   int¤¤   lr_outrefcnt;¤  /* count of outstanding referrals */
8908b6 ¤   int¤¤   lr_origid;¤ /* original request's message id */
90e267 ¤   int¤¤   lr_parentcnt;¤  /* count of parent requests */
a8a925 ¤   int¤¤   lr_res_msgtype;¤/* result message type */
1d5dbc ¤   int¤¤   lr_res_errno;¤  /* result LDAP errno */
f19b61 ¤   char¤   ¤   *lr_res_error;¤ /* result error string */
ea3cd9 ¤   char¤   ¤   *lr_res_matched;/* result matched DN string */
f3a7c8 ¤   BerElement¤ *lr_ber;¤   /* ber encoded request contents */
86e85f ¤   LDAPConn¤   *lr_conn;¤  /* connection used to send request */
0f575d ¤   struct ldapreq¤ *lr_parent;¤/* request that spawned this referral */
dad19c ¤   struct ldapreq¤ *lr_refnext;¤   /* next referral spawned */
0a7923 ¤   struct ldapreq¤ *lr_prev;¤  /* previous request */
03af1b ¤   struct ldapreq¤ *lr_next;¤  /* next request */
198e03 } LDAPRequest;
9f90e2 #endif /* LDAP_REFERRALS */
f9af5a
1aaf5a
1b38e5 /*
cada24 ·* structure for client cache
b5495d ·*/
03d947 #define LDAP_CACHE_BUCKETS¤ 31¤ /* cache hash table size */
3af0d3 typedef struct ldapcache {
d27973 ¤   LDAPMessage¤*lc_buckets[LDAP_CACHE_BUCKETS];/* hash table */
4f1e5f ¤   LDAPMessage¤*lc_requests;¤  ¤   ¤   /* unfulfilled reqs */
55064a ¤   long¤   ¤   lc_timeout;¤¤   ¤   /* request timeout */
4047af ¤   long¤   ¤   lc_maxmem;¤ ¤   ¤   /* memory to use */
64ff7c ¤   long¤   ¤   lc_memused;¤¤   ¤   /* memory in use */
a6263e ¤   int¤¤   lc_enabled;¤¤   ¤   /* enabled? */
6207ad ¤   unsigned long¤  lc_options;¤¤   ¤   /* options */
f0c360 #define LDAP_CACHE_OPT_CACHENOERRS¤ 0x00000001
e3b6d0 #define LDAP_CACHE_OPT_CACHEALLERRS¤0x00000002
9c43bc } ·LDAPCache;
c1e99c #define NULLLDCACHE ((LDAPCache *)NULL)
6aaf5a
0a38e5 /*
47516a ·* structures for ldap getfilter routines
48495d ·*/
dcaf5a
5df306 typedef struct ldap_filt_info {
02a794 ¤   char¤   ¤   ¤   *lfi_filter;
376197 ¤   char¤   ¤   ¤   *lfi_desc;
3ffe6d ¤   int¤¤   ¤   lfi_scope;¤ /* LDAP_SCOPE_BASE, etc */
772dd6 ¤   int¤¤   ¤   lfi_isexact;¤   /* exact match filter? */
2e7bd5 ¤   struct ldap_filt_info¤  *lfi_next;
180851 } LDAPFiltInfo;
8caf5a
758ed4 typedef struct ldap_filt_list {
586e38 ····char¤   ¤   ¤   *lfl_tag;
46e11c ····char¤   ¤   ¤   *lfl_pattern;
4d99c1 ····char¤   ¤   ¤   *lfl_delims;
96bccf ····LDAPFiltInfo¤   ¤   *lfl_ilist;
8bd0c9 ····struct ldap_filt_list¤  *lfl_next;
082dcf } LDAPFiltList;
2faf5a
--74dd 000ad55fadd40100074 Page 7 of ldap.h
e0af5a
e968f4 #define LDAP_FILT_MAXSIZ¤   1024
e5af5a
72f54c typedef struct ldap_filt_desc {
940012 ¤   LDAPFiltList¤   ¤   *lfd_filtlist;
8c1fde ¤   LDAPFiltInfo¤   ¤   *lfd_curfip;
5d9614 ¤   LDAPFiltInfo¤   ¤   lfd_retfi;
472344 ¤   char¤   ¤   ¤   lfd_filter[ LDAP_FILT_MAXSIZ ];
734bcc ¤   char¤   ¤   ¤   *lfd_curval;
87de30 ¤   char¤   ¤   ¤   *lfd_curvalcopy;
9f1047 ¤   char¤   ¤   ¤   **lfd_curvalwords;
8cc555 ¤   char¤   ¤   ¤   *lfd_filtprefix;
f284e0 ¤   char¤   ¤   ¤   *lfd_filtsuffix;
347237 } LDAPFiltDesc;
2caf5a
75af5a
eb38e5 /*
8911f9 ·* structure representing an ldap connection
bc495d ·*/
a9af5a
5d5c2c typedef struct ldap {
0dea9f ¤   Sockbuf¤¤   ld_sb;¤ ¤   /* socket descriptor & buffer */
9ef902 ¤   char¤   ¤   *ld_host;
8b2b92 ¤   int¤¤   ld_version;
ee3f93 ¤   char¤   ¤   ld_lberoptions;
1b6da6 ¤   int¤¤   ld_deref;
3aa467 #define LDAP_DEREF_NEVER¤   0
fd12cf #define LDAP_DEREF_SEARCHING¤   1
175592 #define LDAP_DEREF_FINDING¤ 2
f081db #define LDAP_DEREF_ALWAYS¤  3
60af5a
af9cb8 ¤   int¤¤   ld_timelimit;
802a28 ¤   int¤¤   ld_sizelimit;
7b4f33 #define LDAP_NO_LIMIT¤  ¤   0
b5af5a
60ab47 ¤   LDAPFiltDesc¤   *ld_filtd;¤ /* from getfilter for ufn searches */
9fe260 ¤   char¤   ¤   *ld_ufnprefix;¤ /* for incomplete ufn's */
5eaf5a
ccf019 ¤   int¤¤   ld_errno;
85e873 ¤   char¤   ¤   *ld_error;
881d0b ¤   char¤   ¤   *ld_matched;
53c64d ¤   int¤¤   ld_msgid;
67af5a
58b5b0 ¤   /* do not mess with these */
9c7f8d #ifdef LDAP_REFERRALS
8825c7 ¤   LDAPRequest¤*ld_requests;¤  /* list of outstanding requests */
9e4267 #else /* LDAP_REFERRALS */
58c763 ¤   LDAPMessage¤*ld_requests;¤  /* list of outstanding requests */
0290e2 #endif /* LDAP_REFERRALS */
c34a61 ¤   LDAPMessage¤*ld_responses;¤ /* list of outstanding responses */
41c9b1 ¤   int¤¤   *ld_abandoned;¤ /* array of abandoned requests */
aebeca ¤   char¤   ¤   ld_attrbuffer[LDAP_MAX_ATTR_LEN];
037b31 ¤   LDAPCache¤  *ld_cache;¤ /* non-null if cache is initialized */
01fd80 ¤   char¤   ¤   *ld_cldapdn;¤   /* DN used in connectionless search */
d9af5a
2299ce ¤   /* it is OK to change these next four values directly */
63c1d9 ¤   int¤¤   ld_cldaptries;¤ /* connectionless search retry count */
54f5df ¤   int¤¤   ld_cldaptimeout;/* time between retries */
5c12a0 ¤   int¤¤   ld_refhoplimit;¤/* limit on referral nesting */
cbeed0 ¤   unsigned long¤  ld_options;¤/* boolean options */
674ae9 #ifdef LDAP_DNS
e51057 #define LDAP_OPT_DNS¤   ¤   0x00000001¤ /* use DN & DNS */
431845 #endif /* LDAP_DNS */
8a7f8d #ifdef LDAP_REFERRALS
d60562 #define LDAP_OPT_REFERRALS¤ 0x00000002¤ /* chase referrals */
8690e2 #endif /* LDAP_REFERRALS */
b83c9c #define LDAP_OPT_RESTART¤   0x00000004¤ /* restart if EINTR occurs */
6caf5a
6d9ab7 ¤   /* do not mess with the rest though */
4f3e42 ¤   char¤   ¤   *ld_defhost;¤   /* full name of default server */
7cbc67 ¤   int¤¤   ld_defport;¤/* port of default server */
ad5f2b ¤   BERTranslateProc ld_lber_encode_translate_proc;
--23e3 000de54f56b40100074 Page 8 of ldap.h
3b47a9 ¤   BERTranslateProc ld_lber_decode_translate_proc;
ca7f8d #ifdef LDAP_REFERRALS
766f0b ¤   LDAPConn¤   *ld_defconn;¤   /* default connection */
e35ecd ¤   LDAPConn¤   *ld_conns;¤ /* list of server connections */
218523 ¤   void¤   ¤   *ld_selectinfo;¤/* platform specifics for select */
d930ed ¤   int¤¤   (*ld_rebindproc)( struct ldap *ld, char **dnp,
cbf4e5 ¤   ¤   ¤   ¤   char **passwdp, int *authmethodp, int freeit );
758ee7 ¤   ¤   ¤   ¤   /* routine to get info needed for re-bind */
3690e2 #endif /* LDAP_REFERRALS */
f3af5a
e6176b #if PGPSOCKETSLDAP /* jason */
3cf968 ¤   void *¤ tlsSession;
e97454 #endif
75fa8f } LDAP;
c8af5a
d9af5a
0938e5 /*
c7a51c ·* structure for ldap friendly mapping routines
1a495d ·*/
1aaf5a
441fe2 typedef struct friendly {
daf178 ¤   char¤   *f_unfriendly;
b5c9e3 ¤   char¤   *f_friendly;
40eda0 } FriendlyMap;
d6af5a
b3af5a
5f38e5 /*
25602b ·* handy macro to check whether LDAP struct is set up for CLDAP or not
a1495d ·*/
bed5e6 #define LDAP_IS_CLDAP( ld )¤( ld->ld_sb.sb_naddr > 0 )
06af5a
aaaf5a
8338e5 /*
9f493b ·* types for ldap URL handling
48495d ·*/
81d679 typedef struct ldap_url_desc {
28957d ····char¤   *lud_host;
9384b2 ····int¤¤   lud_port;
2c83c7 ····char¤   *lud_dn;
7af16a ····char¤   **lud_attrs;
542687 ····int¤¤   lud_scope;
42547f ····char¤   *lud_filter;
8e9f7c ····char¤   *lud_string;¤   /* for internal use only */
ac2409 } LDAPURLDesc;
295491 #define NULLLDAPURLDESC¤((LDAPURLDesc *)NULL)
6baf5a
8c1ce2 #define LDAP_URL_ERR_NOTLDAP¤   1¤  /* URL doesn't begin with "ldap://" */
0d9421 #define LDAP_URL_ERR_NODN¤  2¤  /* URL has no DN (required) */
e57078 #define LDAP_URL_ERR_BADSCOPE¤  3¤  /* URL scope string is invalid */
b16bc1 #define LDAP_URL_ERR_MEM¤   4¤  /* can't allocate memory space */
c1af5a
0aaf5a
2c719a #ifndef NEEDPROTOS
5c8586 extern LDAP *ldap_open();
6662c3 extern LDAP *ldap_init();
51f52a #ifdef STR_TRANSLATION
6c92be extern void ldap_set_string_translators();
fe8068 #ifdef LDAP_CHARSET_8859
6e572c extern int ldap_t61_to_8859();
833110 extern int ldap_8859_to_t61();
8f7911 #endif /* LDAP_CHARSET_8859 */
913dd6 #endif /* STR_TRANSLATION */
9edfbd extern LDAPMessage *ldap_first_entry();
c5e89b extern LDAPMessage *ldap_next_entry();
3fdb7b extern char *ldap_get_dn();
8ffc1d extern char *ldap_dn2ufn();
f9244e extern char **ldap_explode_dn();
be2a09 extern char *ldap_first_attribute();
97ca91 extern char *ldap_next_attribute();
f1dabd extern char **ldap_get_values();
e4375e extern struct berval **ldap_get_values_len();
de1574 extern void ldap_value_free();
--8b84 001ac03812740100074 Page 9 of ldap.h
6f4acd extern void ldap_value_free_len();
9f53bf extern int ldap_count_values();
aa61ae extern int ldap_count_values_len();
484f12 extern char *ldap_err2string();
117b67 extern void ldap_getfilter_free();
f8fad1 extern LDAPFiltDesc *ldap_init_getfilter();
8e5b70 extern LDAPFiltDesc *ldap_init_getfilter_buf();
cb7275 extern LDAPFiltInfo *ldap_getfirstfilter();
3b715d extern LDAPFiltInfo *ldap_getnextfilter();
455eff extern void ldap_setfilteraffixes();
658b89 extern void ldap_build_filter();
ed6896 extern void ldap_flush_cache();
a9772d extern void ldap_set_cache_options();
c752d0 extern void ldap_uncache_entry();
1a9b3b extern void ldap_uncache_request();
e92d6d extern char *ldap_friendly_name();
f7dd8e extern void ldap_free_friendlymap();
10aa8d extern LDAP *cldap_open();
7a7f4b extern void cldap_setretryinfo();
7c228a extern void cldap_close();
9ac848 extern LDAPFiltDesc *ldap_ufn_setfilter();
4b7395 extern int ldap_ufn_timeout();
ae8576 extern int ldap_sort_entries();
08808c extern int ldap_sort_values();
fca638 extern int ldap_sort_strcasecmp();
2cf27b void ldap_free_urldesc();
40b9a6 void ldap_set_rebind_proc();
59b166 void ldap_enable_translation();
caaf5a
3caf5a
e45593 #if defined(ultrix) || defined(VMS) || defined( nextstep )
e5ea94 extern char *strdup();
a47454 #endif
dcaf5a
5f6133 #else /* NEEDPROTOS */
4823c4 #if !defined(MACOS) && !defined(DOS) && !defined(_WIN32) && !defined(WINSOCK)
e15d8c #include <sys/time.h>
0b7454 #endif
142de0 #if defined(WINSOCK) && !defined(PGPSOCKETSLDAP) /* jason */
802eca #include "proto-ld.h"
e8db21 #else
d8b686 #include "proto-ldap.h"
0f7454 #endif
10af5a
194edf #ifdef VMS
2c9d23 extern char *strdup( const char *s );
fd7454 #endif
bced1d #if defined(ultrix) || defined( nextstep )
43ea94 extern char *strdup();
ca7454 #endif
bcaf5a
2d8634 #endif /* NEEDPROTOS */
edaf5a
8c3379 #ifdef __cplusplus
bcefe6 }
447454 #endif
ac838e #endif /* _LDAP_H */
--89df 00061bd470a40100075 Page 1 of ldapconfig-win32.h
bc38e5 /*
9fe7f7 ·* This file was automatically generated. ·Do not edit it.
b09530 ·* Instead, edit the file ldapconfig.h.edit. ·See the LDAP
74be2f ·* INSTALL file for more information.
55ac65 ·*/·
f9af5a
7b38e5 /*
dd9eee ·* Copyright (c) 1994 Regents of the University of Michigan.
4f599a ·* All rights reserved.
c2775e ·*
a5b855 ·* Redistribution and use in source and binary forms are permitted
569795 ·* provided that this notice is preserved and that due credit is given
b11873 ·* to the University of Michigan at Ann Arbor. The name of the University
7e8805 ·* may not be used to endorse or promote products derived from this
b374fe ·* software without specific prior written permission. This software
242a32 ·* is provided ``as is'' without express or implied warranty.
59495d ·*/
f9af5a
fb7f62 #ifndef _CONFIG_H
5aa23b #define _CONFIG_H
c8af5a
8538e5 /*
9e6bdf ·* config.h for LDAP -- edit this file to customize LDAP client behavior.
d577d6 ·* NO platform-specific definitions should be placed in this file.
6c431e ·* Note that this is NOT used by the LDAP or LBER libraries.
c0495d ·*/
e4af5a
f538e5 /*
df0be2 ·* SHARED DEFINITIONS - things you should change
0d495d ·*/
0371fc ¤   /* default ldap host */
c6e015 #define LDAPHOST¤   "localhost"
6c5036 ¤   /* default place to start searching */
6c83ed #define DEFAULT_BASE¤   "o=Your Organization Name, c=US"
8eaf5a
df153d /*********************************************************************
c7022e ·* ··································································*
d8efdf ·* You probably do not need to edit anything below this point ·······*
38022e ·* ··································································*
addfd6 ·*********************************************************************/
45af5a
4938e5 /*
b02527 ·* SHARED DEFINITIONS - other things you can change
1a495d ·*/
fcecb0 ¤   /* default attribute to use when sorting entries, NULL => sort by DN */
51655e #define SORT_ATTR¤  NULL
e7c11f ¤   /* default count of DN components to show in entry displays */
8c2b7f #define DEFAULT_RDNCOUNT¤   2
256459 ¤   /* default config file locations */
6c1f69 #define FILTERFILE¤ "/export/home/marcd/ldap-3.3/etc/ldapfilter.conf"
60fb67 #define TEMPLATEFILE¤   "/export/home/marcd/ldap-3.3/etc/ldaptemplates.conf"
b4e50c #define SEARCHFILE¤ "/export/home/marcd/ldap-3.3/etc/ldapsearchprefs.conf"
ceb03b #define FRIENDLYFILE¤   "/export/home/marcd/ldap-3.3/etc/ldapfriendly"
9caf5a
fb38e5 /*
3da84c ·* FINGER DEFINITIONS
56495d ·*/
272757 ¤   /* who to bind as */
7bd95b #define FINGER_BINDDN¤  ¤   NULL
d34fe5 ¤   /* where to search */
e7b05a #define FINGER_BASE¤¤   DEFAULT_BASE
170306 ¤   /* banner to print */
8941d3 #define FINGER_BANNER¤  ¤   "X.500 Finger Service...\r\n"
e244c7 ¤   /* who to report errors to */
2104ea #define FINGER_ERRORS¤  ¤   "your local system administrator"
cefd6f ¤   /* what to say if no matches are found */
59f429 #define FINGER_NOMATCH¤ ¤   "Search failed to find anything.\r\n"
ceca2c ¤   /* what to say if the service may be unavailable */
44231f #define FINGER_UNAVAILABLE¤ \
ed483b "The X.500 service may be temporarily unavailable.\r\n\
b0702c Please try again later.\r\n"
61ad48 ¤   /* printed if a match has no email address - for disptmp default */
--d1e7 000b03302d440100075 Page 2 of ldapconfig-win32.h
fabbb3 #define FINGER_NOEMAIL1¤"None registered in this service."
4c46c2 #define FINGER_NOEMAIL2¤NULL
6c9e40 #define FINGER_NOEMAIL¤ { FINGER_NOEMAIL1, FINGER_NOEMAIL2, NULL }
41c2cd ¤   /* maximum number of matches returned */
bce05b #define FINGER_SIZELIMIT¤   50
e73c15 ¤   /* max number of hits displayed in full before a list is presented */
f42f3d #define FINGER_LISTLIMIT¤   1
fca51d ¤   /* what to exec for "finger @host" */
fcd4d7 #define FINGER_CMD¤ ¤   "/usr/ucb/finger"
2d4f9b ¤   /* how to treat aliases when searching */
2e4b00 #define FINGER_DEREF¤   ¤   LDAP_DEREF_FINDING
ac054b ¤   /* attribute to use when sorting results */
d70d6d #define FINGER_SORT_ATTR¤   SORT_ATTR
49d621 ¤   /* enable ufn support */
d8ac67 #define FINGER_UFN
922dd1 ¤   /* timeout for searches */
01dedc #define FINGER_TIMEOUT¤ ¤   60
2a836b ¤   /* number of DN components to show in entry displays */
672cf7 #define FINGER_RDNCOUNT¤¤   DEFAULT_RDNCOUNT¤
4caf5a
1938e5 /*
2e8dd9 ·* GO500 GOPHER GATEWAY DEFINITIONS
72495d ·*/
5d2757 ¤   /* who to bind as */
07ee77 #define GO500_BINDDN¤   NULL
a24fe5 ¤   /* where to search */
515a9d #define GO500_BASE¤ DEFAULT_BASE
767eff ¤   /* port on which to listen */
d02e33 #define GO500_PORT¤ 5555
1da0bd ¤   /* how to handle aliases */
43d4bb #define GO500_DEREF¤LDAP_DEREF_FINDING
60054b ¤   /* attribute to use when sorting results */
e61fbf #define GO500_SORT_ATTR¤SORT_ATTR
e22dd1 ¤   /* timeout for searches */
d9b687 #define GO500_TIMEOUT¤  180
0cd621 ¤   /* enable ufn support */
0d8507 #define GO500_UFN
8fd8af ¤   /*
82e346 ¤   ·* only set and uncomment this if your hostname() does not return
7bfcf0 ¤   ·* a fully qualified hostname
cca4e3 ¤   ·*/
bd5104 /* #define GO500_HOSTNAME¤  "fully.qualified.hostname.here" */
86836b ¤   /* number of DN components to show in entry displays */
dffe2f #define GO500_RDNCOUNT¤ ¤   DEFAULT_RDNCOUNT¤
edaf5a
a938e5 /*
a38269 ·* GO500GW GOPHER GATEWAY DEFINITIONS
ff495d ·*/
652757 ¤   /* who to bind as */
777446 #define GO500GW_BINDDN¤ ¤   NULL
aba855 ¤   /* where the helpfile lives */
4fd953 #define GO500GW_HELPFILE¤   "/export/home/marcd/ldap-3.3/etc/go500gw.help"
8d7eff ¤   /* port on which to listen */
5199e9 #define GO500GW_PORT¤   ¤   7777
3200a8 ¤   /* timeout on all searches */
98469b #define GO500GW_TIMEOUT¤¤   180
2ed621 ¤   /* enable ufn support */
1fcbb7 #define GO500GW_UFN
b9054b ¤   /* attribute to use when sorting results */
0f7d23 #define GO500GW_SORT_ATTR¤  SORT_ATTR
b5d8af ¤   /*
55e346 ¤   ·* only set and uncomment this if your hostname() does not return
c5fcf0 ¤   ·* a fully qualified hostname
52a4e3 ¤   ·*/
10adc6 /* #define GO500GW_HOSTNAME¤"fully.qualified.hostname.here" */
ae836b ¤   /* number of DN components to show in entry displays */
035979 #define GO500GW_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
08af5a
bc38e5 /*
72d8b1 ·* RCPT500 MAIL RESPONDER GATEWAY DEFINITIONS
54495d ·*/
b02757 ¤   /* who to bind as */
--ed28 0002932422f40100075 Page 3 of ldapconfig-win32.h
d31b00 #define RCPT500_BINDDN¤ ¤   NULL
cea855 ¤   /* where the helpfile lives */
618c84 #define RCPT500_HELPFILE¤   "/export/home/marcd/ldap-3.3/etc/rcpt500.help"
24c2cd ¤   /* maximum number of matches returned */
7a8085 #define RCPT500_SIZELIMIT¤  50
21d8a7 ¤   /* address replies will appear to come from */
374cfc #define RCPT500_FROM¤   ¤   "\"X.500 Query Program\" <X500-Query>"
7793f8 ¤   /* command that will accept an RFC822 message text on standard
4d5bfd ¤   ···input, and send it. ·sendmail -t does this nicely. */
c0b1bf #define RCPT500_PIPEMAILCMD¤"/usr/lib/sendmail -t"
1a249f ········/* where to search */
5946cd #define RCPT500_BASE ············DEFAULT_BASE
3b054b ¤   /* attribute to use when sorting results */
fdac84 #define RCPT500_SORT_ATTR¤  SORT_ATTR
7b3c15 ¤   /* max number of hits displayed in full before a list is presented */
53b629 #define RCPT500_LISTLIMIT¤  1
2ed621 ¤   /* enable ufn support */
a4292c #define RCPT500_UFN
01836b ¤   /* number of DN components to show in entry displays */
a8d362 #define RCPT500_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
cfaf5a
2938e5 /*
b14826 ·* LDAPSEARCH TOOL
cb495d ·*/
822757 ¤   /* who to bind as */
3feabc #define LDAPSEARCH_BINDDN¤  NULL
f3b081 ¤   /* search base */
f82fb1 #define LDAPSEARCH_BASE¤¤   DEFAULT_BASE
98af5a
b738e5 /*
2a30c8 ·* LDAPMODIFY TOOL
b5495d ·*/
c42757 ¤   /* who to bind as */
f84121 #define LDAPMODIFY_BINDDN¤  NULL
7ab081 ¤   /* search base */
5a96ea #define LDAPMODIFY_BASE¤¤   DEFAULT_BASE
fcaf5a
0738e5 /*
fdd5bb ·* LDAPDELETE TOOL
bf495d ·*/
462757 ¤   /* who to bind as */
49f66a #define LDAPDELETE_BINDDN¤  NULL
aab081 ¤   /* search base */
c0c338 #define LDAPDELETE_BASE¤¤   DEFAULT_BASE
e2af5a
6938e5 /*
d71f2f ·* LDAPMODRDN TOOL
6d495d ·*/
dd2757 ¤   /* who to bind as */
fa7a0c #define LDAPMODRDN_BINDDN¤  NULL
24b081 ¤   /* search base */
083a0f #define LDAPMODRDN_BASE¤¤   DEFAULT_BASE
94af5a
a838e5 /*
f665c8 ·* MAIL500 MAILER DEFINITIONS
29495d ·*/
962757 ¤   /* who to bind as */
df489b #define MAIL500_BINDDN¤ ¤   NULL
4b13fb ¤   /* max number of ambiguous matches reported */
c2aea8 #define MAIL500_MAXAMBIGUOUS¤   10
dcacbe ¤   /* max subscribers allowed (size limit when searching for them ) */
d980a0 #define MAIL500_MAXGROUPMEMBERS¤LDAP_NO_LIMIT
043b3d ¤   /* timeout for all searches */
a97076 #define MAIL500_TIMEOUT¤¤   180
034924 ¤   /* sendmail location - mail500 needs to exec this */
f9c042 #define MAIL500_SENDMAIL¤   "/usr/lib/sendmail"
a7af5a
1238e5 /*
b0cd8a ·* UD DEFINITIONS
68495d ·*/
bb6abf ¤   /* ud configuration file */
29dd47 #define UD_CONFIG_FILE¤ ¤   "/export/home/marcd/ldap-3.3/etc/ud.conf"
--6aff 000546c48f140100075 Page 4 of ldapconfig-win32.h
7ff414 ¤   /* default editor */
624afb #define UD_DEFAULT_EDITOR¤  "/usr/ucb/vi"
8629b1 ¤   /* default bbasename of user config file */
64bcd1 #define UD_USER_CONFIG_FILE¤".udrc"
ee977c ¤   /* default user to bind as */
bf71f3 #define UD_BINDDN¤  ¤   NULL
0006a6 ¤   /* default password to bind with */
c8881d #define UD_PASSWD¤  ¤   NULL
074d57 ¤   /* default search base */
6823af #define UD_BASE¤¤   ¤   DEFAULT_BASE
56921e ¤   /* default base where groups are created */
92206e #define UD_WHERE_GROUPS_ARE_CREATED¤""
9f7a9f ¤   /* default base below which all groups live */
f9ea60 #define UD_WHERE_ALL_GROUPS_LIVE¤   ""
2baf5a
cb38e5 /*
355862 ·* FAX500 DEFINITIONS
ce495d ·*/
860dc1 ¤   /* what to bind as */
b4aa62 #define FAX_BINDDN¤ NULL
9f97de ¤   /* how long to wait for searches */
a45b5e #define FAX_TIMEOUT¤¤   180
0b3fdf ¤   /* maximum number of ambiguous matches reported */
9eacca #define FAX_MAXAMBIGUOUS¤   10
9465ef ¤   /* maximum number of members allowed */
18e4e8 #define FAX_MAXMEMBERS¤ ¤   LDAP_NO_LIMIT
735be6 ¤   /* program to send mail */
13d214 #define FAX_SENDMAIL¤   ¤   "/usr/lib/sendmail"
05af5a
9b38e5 /*
a96218 ·* RP500 DEFINITIONS
ca495d ·*/
d70dc1 ¤   /* what to bind as */
570ce3 #define RP_BINDDN¤  NULL
5dfbd2 ¤   /* prefix to add to non-fully-qualified numbers */
bb2ea0 #define RP_PHONEPREFIX¤ ""
91af5a
fb38e5 /*
ca1366 ·* SLAPD DEFINITIONS
d4495d ·*/
87a1a1 ¤   /* location of the default slapd config file */
53cf14 #ifdef PGPKEYSERVER
82821b #define SLAPD_DEFAULT_CONFIGFILE¤   "pgpcertd.conf"
4edb21 #else
75524f #define SLAPD_DEFAULT_CONFIGFILE¤   "slapd.conf"
8b7454 #endif
4491a4 ¤   /* Location of the default slapd access log file. */
64cf14 #ifdef PGPKEYSERVER
9db262 #define SLAPD_DEFAULT_ACCESS_LOG_DIR¤   "/var/opt/PGPcs10/access.log"
ab7454 #endif
3dd7a9 ¤   /* default sizelimit on number of entries from a search */
8cf900 #define SLAPD_DEFAULT_SIZELIMIT¤¤   500
bb450d ¤   /* default timelimit to spend on a search */
edcf14 #ifdef PGPKEYSERVER
c45bc6 #define SLAPD_DEFAULT_TIMELIMIT¤¤   300
55db21 #else
210c73 #define SLAPD_DEFAULT_TIMELIMIT¤¤   3600
1b7454 #endif
59d33d ¤   /* location of the slapd pid file */
ca0818 #ifndef WIN32¤  ¤   ¤   /* marcd */
7ac8de #define SLAPD_PIDFILE¤  ¤   ¤   "slapd.pid"
707454 #endif
a0f24b ¤   /* location of the slapd args file */
800114 #define SLAPD_ARGSFILE¤ ¤   ¤   "slapd.args"
3e18a8 ¤   /* dn of the special "monitor" entry */
b0a982 #define SLAPD_MONITOR_DN¤   ¤   "cn=monitor"
edfbe8 ¤   /* dn of the special "config" entry */
50abed ¤   /* Turn off for now since it doesn't give anything useful. */
aa9803 /* #define SLAPD_CONFIG_DN¤ ¤   ¤   "cn=config" */
3d346e ¤   /* minimum max ids that a single index entry can map to in ldbm */
b26643 #define SLAPD_LDBM_MIN_MAXIDS¤  ¤   4000
54af5a
--531a 00121bfcb7640100075 Page 5 of ldapconfig-win32.h
213298 #endif /* _CONFIG_H */
--e09f 000a605934240100076 Page 1 of ldapconfig.h
bc38e5 /*
9fe7f7 ·* This file was automatically generated. ·Do not edit it.
b09530 ·* Instead, edit the file ldapconfig.h.edit. ·See the LDAP
74be2f ·* INSTALL file for more information.
55ac65 ·*/·
f9af5a
7b38e5 /*
dd9eee ·* Copyright (c) 1994 Regents of the University of Michigan.
4f599a ·* All rights reserved.
c2775e ·*
a5b855 ·* Redistribution and use in source and binary forms are permitted
569795 ·* provided that this notice is preserved and that due credit is given
b11873 ·* to the University of Michigan at Ann Arbor. The name of the University
7e8805 ·* may not be used to endorse or promote products derived from this
b374fe ·* software without specific prior written permission. This software
242a32 ·* is provided ``as is'' without express or implied warranty.
59495d ·*/
f9af5a
fb7f62 #ifndef _CONFIG_H
5aa23b #define _CONFIG_H
c8af5a
8538e5 /*
9e6bdf ·* config.h for LDAP -- edit this file to customize LDAP client behavior.
d577d6 ·* NO platform-specific definitions should be placed in this file.
6c431e ·* Note that this is NOT used by the LDAP or LBER libraries.
c0495d ·*/
e4af5a
f538e5 /*
df0be2 ·* SHARED DEFINITIONS - things you should change
0d495d ·*/
0371fc ¤   /* default ldap host */
c6e015 #define LDAPHOST¤   "localhost"
6c5036 ¤   /* default place to start searching */
f79d7c #define DEFAULT_BASE¤   "o=PGP Keyspace, c=US"
afaf5a
b3153d /*********************************************************************
45022e ·* ··································································*
c5efdf ·* You probably do not need to edit anything below this point ·······*
4f022e ·* ··································································*
b8dfd6 ·*********************************************************************/
c5af5a
5a38e5 /*
ff2527 ·* SHARED DEFINITIONS - other things you can change
2c495d ·*/
f7ecb0 ¤   /* default attribute to use when sorting entries, NULL => sort by DN */
54655e #define SORT_ATTR¤  NULL
a2c11f ¤   /* default count of DN components to show in entry displays */
642b7f #define DEFAULT_RDNCOUNT¤   2
746459 ¤   /* default config file locations */
5f9b75 #define FILTERFILE¤ "/etc/ldapfilter.conf"
81af3d #define TEMPLATEFILE¤   "/etc/ldaptemplates.conf"
c47433 #define SEARCHFILE¤ "/etc/ldapsearchprefs.conf"
3c922e #define FRIENDLYFILE¤   "/etc/ldapfriendly"
06af5a
0f38e5 /*
90a84c ·* FINGER DEFINITIONS
54495d ·*/
1f2757 ¤   /* who to bind as */
29d95b #define FINGER_BINDDN¤  ¤   NULL
784fe5 ¤   /* where to search */
38b05a #define FINGER_BASE¤¤   DEFAULT_BASE
9f0306 ¤   /* banner to print */
9441d3 #define FINGER_BANNER¤  ¤   "X.500 Finger Service...\r\n"
9044c7 ¤   /* who to report errors to */
4704ea #define FINGER_ERRORS¤  ¤   "your local system administrator"
a1fd6f ¤   /* what to say if no matches are found */
90f429 #define FINGER_NOMATCH¤ ¤   "Search failed to find anything.\r\n"
3dca2c ¤   /* what to say if the service may be unavailable */
cb231f #define FINGER_UNAVAILABLE¤ \
a6483b "The X.500 service may be temporarily unavailable.\r\n\
bb702c Please try again later.\r\n"
a6ad48 ¤   /* printed if a match has no email address - for disptmp default */
--a6b8 000ac63bf4d40100076 Page 2 of ldapconfig.h
fabbb3 #define FINGER_NOEMAIL1¤"None registered in this service."
4c46c2 #define FINGER_NOEMAIL2¤NULL
6c9e40 #define FINGER_NOEMAIL¤ { FINGER_NOEMAIL1, FINGER_NOEMAIL2, NULL }
41c2cd ¤   /* maximum number of matches returned */
bce05b #define FINGER_SIZELIMIT¤   50
e73c15 ¤   /* max number of hits displayed in full before a list is presented */
f42f3d #define FINGER_LISTLIMIT¤   1
fca51d ¤   /* what to exec for "finger @host" */
fcd4d7 #define FINGER_CMD¤ ¤   "/usr/ucb/finger"
2d4f9b ¤   /* how to treat aliases when searching */
2e4b00 #define FINGER_DEREF¤   ¤   LDAP_DEREF_FINDING
ac054b ¤   /* attribute to use when sorting results */
d70d6d #define FINGER_SORT_ATTR¤   SORT_ATTR
49d621 ¤   /* enable ufn support */
d8ac67 #define FINGER_UFN
922dd1 ¤   /* timeout for searches */
01dedc #define FINGER_TIMEOUT¤ ¤   60
2a836b ¤   /* number of DN components to show in entry displays */
672cf7 #define FINGER_RDNCOUNT¤¤   DEFAULT_RDNCOUNT¤
4caf5a
1938e5 /*
2e8dd9 ·* GO500 GOPHER GATEWAY DEFINITIONS
72495d ·*/
5d2757 ¤   /* who to bind as */
07ee77 #define GO500_BINDDN¤   NULL
a24fe5 ¤   /* where to search */
515a9d #define GO500_BASE¤ DEFAULT_BASE
767eff ¤   /* port on which to listen */
d02e33 #define GO500_PORT¤ 5555
1da0bd ¤   /* how to handle aliases */
43d4bb #define GO500_DEREF¤LDAP_DEREF_FINDING
60054b ¤   /* attribute to use when sorting results */
e61fbf #define GO500_SORT_ATTR¤SORT_ATTR
e22dd1 ¤   /* timeout for searches */
d9b687 #define GO500_TIMEOUT¤  180
0cd621 ¤   /* enable ufn support */
0d8507 #define GO500_UFN
8fd8af ¤   /*
82e346 ¤   ·* only set and uncomment this if your hostname() does not return
7bfcf0 ¤   ·* a fully qualified hostname
cca4e3 ¤   ·*/
bd5104 /* #define GO500_HOSTNAME¤  "fully.qualified.hostname.here" */
86836b ¤   /* number of DN components to show in entry displays */
dffe2f #define GO500_RDNCOUNT¤ ¤   DEFAULT_RDNCOUNT¤
edaf5a
a938e5 /*
a38269 ·* GO500GW GOPHER GATEWAY DEFINITIONS
ff495d ·*/
652757 ¤   /* who to bind as */
777446 #define GO500GW_BINDDN¤ ¤   NULL
aba855 ¤   /* where the helpfile lives */
3880cd #define GO500GW_HELPFILE¤   "/etc/go500gw.help"
097eff ¤   /* port on which to listen */
5299e9 #define GO500GW_PORT¤   ¤   7777
6200a8 ¤   /* timeout on all searches */
d9469b #define GO500GW_TIMEOUT¤¤   180
c0d621 ¤   /* enable ufn support */
44cbb7 #define GO500GW_UFN
3e054b ¤   /* attribute to use when sorting results */
be7d23 #define GO500GW_SORT_ATTR¤  SORT_ATTR
41d8af ¤   /*
a9e346 ¤   ·* only set and uncomment this if your hostname() does not return
e5fcf0 ¤   ·* a fully qualified hostname
aba4e3 ¤   ·*/
2fadc6 /* #define GO500GW_HOSTNAME¤"fully.qualified.hostname.here" */
60836b ¤   /* number of DN components to show in entry displays */
ab5979 #define GO500GW_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
3aaf5a
d838e5 /*
bfd8b1 ·* RCPT500 MAIL RESPONDER GATEWAY DEFINITIONS
09495d ·*/
ac2757 ¤   /* who to bind as */
--11b6 000d6c5a67440100076 Page 3 of ldapconfig.h
d31b00 #define RCPT500_BINDDN¤ ¤   NULL
cea855 ¤   /* where the helpfile lives */
656bbc #define RCPT500_HELPFILE¤   "/etc/rcpt500.help"
c9c2cd ¤   /* maximum number of matches returned */
088085 #define RCPT500_SIZELIMIT¤  50
c8d8a7 ¤   /* address replies will appear to come from */
9b4cfc #define RCPT500_FROM¤   ¤   "\"X.500 Query Program\" <X500-Query>"
2693f8 ¤   /* command that will accept an RFC822 message text on standard
9f5bfd ¤   ···input, and send it. ·sendmail -t does this nicely. */
fcb1bf #define RCPT500_PIPEMAILCMD¤"/usr/lib/sendmail -t"
c8249f ········/* where to search */
bd46cd #define RCPT500_BASE ············DEFAULT_BASE
2d054b ¤   /* attribute to use when sorting results */
ddac84 #define RCPT500_SORT_ATTR¤  SORT_ATTR
d43c15 ¤   /* max number of hits displayed in full before a list is presented */
a5b629 #define RCPT500_LISTLIMIT¤  1
efd621 ¤   /* enable ufn support */
ad292c #define RCPT500_UFN
3a836b ¤   /* number of DN components to show in entry displays */
78d362 #define RCPT500_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
4baf5a
3438e5 /*
914826 ·* LDAPSEARCH TOOL
58495d ·*/
be2757 ¤   /* who to bind as */
43eabc #define LDAPSEARCH_BINDDN¤  NULL
6db081 ¤   /* search base */
492fb1 #define LDAPSEARCH_BASE¤¤   DEFAULT_BASE
d4af5a
7738e5 /*
e630c8 ·* LDAPMODIFY TOOL
3d495d ·*/
3c2757 ¤   /* who to bind as */
cc4121 #define LDAPMODIFY_BINDDN¤  NULL
16b081 ¤   /* search base */
1096ea #define LDAPMODIFY_BASE¤¤   DEFAULT_BASE
41af5a
8d38e5 /*
00d5bb ·* LDAPDELETE TOOL
76495d ·*/
f72757 ¤   /* who to bind as */
89f66a #define LDAPDELETE_BINDDN¤  NULL
bfb081 ¤   /* search base */
87c338 #define LDAPDELETE_BASE¤¤   DEFAULT_BASE
81af5a
dc38e5 /*
9a1f2f ·* LDAPMODRDN TOOL
f8495d ·*/
f32757 ¤   /* who to bind as */
e77a0c #define LDAPMODRDN_BINDDN¤  NULL
35b081 ¤   /* search base */
3a3a0f #define LDAPMODRDN_BASE¤¤   DEFAULT_BASE
ccaf5a
1d38e5 /*
b765c8 ·* MAIL500 MAILER DEFINITIONS
6a495d ·*/
4c2757 ¤   /* who to bind as */
68489b #define MAIL500_BINDDN¤ ¤   NULL
9613fb ¤   /* max number of ambiguous matches reported */
cfaea8 #define MAIL500_MAXAMBIGUOUS¤   10
edacbe ¤   /* max subscribers allowed (size limit when searching for them ) */
1180a0 #define MAIL500_MAXGROUPMEMBERS¤LDAP_NO_LIMIT
0e3b3d ¤   /* timeout for all searches */
aa7076 #define MAIL500_TIMEOUT¤¤   180
704924 ¤   /* sendmail location - mail500 needs to exec this */
2ec042 #define MAIL500_SENDMAIL¤   "/usr/lib/sendmail"
8baf5a
4638e5 /*
1fcd8a ·* UD DEFINITIONS
19495d ·*/
f96abf ¤   /* ud configuration file */
d64479 #define UD_CONFIG_FILE¤ ¤   "/etc/ud.conf"
--2dd7 000a8d5121540100076 Page 4 of ldapconfig.h
7ff414 ¤   /* default editor */
624afb #define UD_DEFAULT_EDITOR¤  "/usr/ucb/vi"
8629b1 ¤   /* default bbasename of user config file */
64bcd1 #define UD_USER_CONFIG_FILE¤".udrc"
ee977c ¤   /* default user to bind as */
bf71f3 #define UD_BINDDN¤  ¤   NULL
0006a6 ¤   /* default password to bind with */
c8881d #define UD_PASSWD¤  ¤   NULL
074d57 ¤   /* default search base */
6823af #define UD_BASE¤¤   ¤   DEFAULT_BASE
56921e ¤   /* default base where groups are created */
92206e #define UD_WHERE_GROUPS_ARE_CREATED¤""
9f7a9f ¤   /* default base below which all groups live */
f9ea60 #define UD_WHERE_ALL_GROUPS_LIVE¤   ""
2baf5a
cb38e5 /*
355862 ·* FAX500 DEFINITIONS
ce495d ·*/
860dc1 ¤   /* what to bind as */
b4aa62 #define FAX_BINDDN¤ NULL
9f97de ¤   /* how long to wait for searches */
a45b5e #define FAX_TIMEOUT¤¤   180
0b3fdf ¤   /* maximum number of ambiguous matches reported */
9eacca #define FAX_MAXAMBIGUOUS¤   10
9465ef ¤   /* maximum number of members allowed */
18e4e8 #define FAX_MAXMEMBERS¤ ¤   LDAP_NO_LIMIT
735be6 ¤   /* program to send mail */
13d214 #define FAX_SENDMAIL¤   ¤   "/usr/lib/sendmail"
05af5a
9b38e5 /*
a96218 ·* RP500 DEFINITIONS
ca495d ·*/
d70dc1 ¤   /* what to bind as */
570ce3 #define RP_BINDDN¤  NULL
5dfbd2 ¤   /* prefix to add to non-fully-qualified numbers */
bb2ea0 #define RP_PHONEPREFIX¤ ""
91af5a
fb38e5 /*
ca1366 ·* SLAPD DEFINITIONS
d4495d ·*/
87a1a1 ¤   /* location of the default slapd config file */
53cf14 #ifdef PGPKEYSERVER
82821b #define SLAPD_DEFAULT_CONFIGFILE¤   "pgpcertd.conf"
4edb21 #else
9b2410 #define SLAPD_DEFAULT_CONFIGFILE¤   "/export/home/marcd/ldap-3.3/etc/slapd.conf"
367454 #endif
0a91a4 ¤   /* Location of the default slapd access log file. */
6ecf14 #ifdef PGPKEYSERVER
71b262 #define SLAPD_DEFAULT_ACCESS_LOG_DIR¤   "/var/opt/PGPcs10/access.log"
d87454 #endif
13d7a9 ¤   /* default sizelimit on number of entries from a search */
87f900 #define SLAPD_DEFAULT_SIZELIMIT¤¤   500
1c450d ¤   /* default timelimit to spend on a search */
96cf14 #ifdef PGPKEYSERVER
db5bc6 #define SLAPD_DEFAULT_TIMELIMIT¤¤   300
28db21 #else
f80c73 #define SLAPD_DEFAULT_TIMELIMIT¤¤   3600
1e7454 #endif
2dd33d ¤   /* location of the slapd pid file */
b30818 #ifndef WIN32¤  ¤   ¤   /* marcd */
3c5718 #define SLAPD_PIDFILE¤  ¤   ¤   "/etc/slapd.pid"
b37454 #endif
5ff24b ¤   /* location of the slapd args file */
e569b9 #define SLAPD_ARGSFILE¤ ¤   ¤   "/etc/slapd.args"
2318a8 ¤   /* dn of the special "monitor" entry */
51a982 #define SLAPD_MONITOR_DN¤   ¤   "cn=monitor"
b1fbe8 ¤   /* dn of the special "config" entry */
a1abed ¤   /* Turn off for now since it doesn't give anything useful. */
7f9803 /* #define SLAPD_CONFIG_DN¤ ¤   ¤   "cn=config" */
88346e ¤   /* minimum max ids that a single index entry can map to in ldbm */
b26643 #define SLAPD_LDBM_MIN_MAXIDS¤  ¤   4000
a8af5a
--3d27 00121bfcb7640100076 Page 5 of ldapconfig.h
213298 #endif /* _CONFIG_H */
--2ad1 0000f7fd2a140100077 Page 1 of ldapconfig.h.edit
bc38e5 /*
979eee ·* Copyright (c) 1994 Regents of the University of Michigan.
aa599a ·* All rights reserved.
f0775e ·*
88b855 ·* Redistribution and use in source and binary forms are permitted
cc9795 ·* provided that this notice is preserved and that due credit is given
e01873 ·* to the University of Michigan at Ann Arbor. The name of the University
4e8805 ·* may not be used to endorse or promote products derived from this
a874fe ·* software without specific prior written permission. This software
112a32 ·* is provided ``as is'' without express or implied warranty.
81495d ·*/
6aaf5a
897f62 #ifndef _CONFIG_H
e7a23b #define _CONFIG_H
d0af5a
ae38e5 /*
dd6bdf ·* config.h for LDAP -- edit this file to customize LDAP client behavior.
0f77d6 ·* NO platform-specific definitions should be placed in this file.
9f431e ·* Note that this is NOT used by the LDAP or LBER libraries.
13495d ·*/
15af5a
9e38e5 /*
bb0be2 ·* SHARED DEFINITIONS - things you should change
cd495d ·*/
ce71fc ¤   /* default ldap host */
c3e015 #define LDAPHOST¤   "localhost"
eb5036 ¤   /* default place to start searching */
5f9d7c #define DEFAULT_BASE¤   "o=PGP Keyspace, c=US"
a1af5a
ed153d /*********************************************************************
d7022e ·* ··································································*
29efdf ·* You probably do not need to edit anything below this point ·······*
2a022e ·* ··································································*
63dfd6 ·*********************************************************************/
23af5a
a038e5 /*
492527 ·* SHARED DEFINITIONS - other things you can change
3d495d ·*/
a1ecb0 ¤   /* default attribute to use when sorting entries, NULL => sort by DN */
3b655e #define SORT_ATTR¤  NULL
57c11f ¤   /* default count of DN components to show in entry displays */
9e2b7f #define DEFAULT_RDNCOUNT¤   2
5e6459 ¤   /* default config file locations */
90a6d7 #define FILTERFILE¤ "%ETCDIR%/ldapfilter.conf"
2dd810 #define TEMPLATEFILE¤   "%ETCDIR%/ldaptemplates.conf"
1a62f1 #define SEARCHFILE¤ "%ETCDIR%/ldapsearchprefs.conf"
c36086 #define FRIENDLYFILE¤   "%ETCDIR%/ldapfriendly"
5aaf5a
d338e5 /*
98a84c ·* FINGER DEFINITIONS
6a495d ·*/
572757 ¤   /* who to bind as */
e3d95b #define FINGER_BINDDN¤  ¤   NULL
a14fe5 ¤   /* where to search */
c9b05a #define FINGER_BASE¤¤   DEFAULT_BASE
ff0306 ¤   /* banner to print */
ac41d3 #define FINGER_BANNER¤  ¤   "X.500 Finger Service...\r\n"
e444c7 ¤   /* who to report errors to */
e504ea #define FINGER_ERRORS¤  ¤   "your local system administrator"
8dfd6f ¤   /* what to say if no matches are found */
a5f429 #define FINGER_NOMATCH¤ ¤   "Search failed to find anything.\r\n"
c6ca2c ¤   /* what to say if the service may be unavailable */
40231f #define FINGER_UNAVAILABLE¤ \
7c483b "The X.500 service may be temporarily unavailable.\r\n\
2a702c Please try again later.\r\n"
19ad48 ¤   /* printed if a match has no email address - for disptmp default */
bfbbb3 #define FINGER_NOEMAIL1¤"None registered in this service."
0246c2 #define FINGER_NOEMAIL2¤NULL
719e40 #define FINGER_NOEMAIL¤ { FINGER_NOEMAIL1, FINGER_NOEMAIL2, NULL }
e3c2cd ¤   /* maximum number of matches returned */
27e05b #define FINGER_SIZELIMIT¤   50
0f3c15 ¤   /* max number of hits displayed in full before a list is presented */
--3dc9 0009514a0db40100077 Page 2 of ldapconfig.h.edit
162f3d #define FINGER_LISTLIMIT¤   1
a7a51d ¤   /* what to exec for "finger @host" */
98d4d7 #define FINGER_CMD¤ ¤   "/usr/ucb/finger"
654f9b ¤   /* how to treat aliases when searching */
314b00 #define FINGER_DEREF¤   ¤   LDAP_DEREF_FINDING
5a054b ¤   /* attribute to use when sorting results */
a70d6d #define FINGER_SORT_ATTR¤   SORT_ATTR
17d621 ¤   /* enable ufn support */
a2ac67 #define FINGER_UFN
502dd1 ¤   /* timeout for searches */
2fdedc #define FINGER_TIMEOUT¤ ¤   60
ce836b ¤   /* number of DN components to show in entry displays */
1a2cf7 #define FINGER_RDNCOUNT¤¤   DEFAULT_RDNCOUNT¤
8caf5a
a238e5 /*
818dd9 ·* GO500 GOPHER GATEWAY DEFINITIONS
54495d ·*/
1b2757 ¤   /* who to bind as */
1fee77 #define GO500_BINDDN¤   NULL
5e4fe5 ¤   /* where to search */
865a9d #define GO500_BASE¤ DEFAULT_BASE
627eff ¤   /* port on which to listen */
a92e33 #define GO500_PORT¤ 5555
37a0bd ¤   /* how to handle aliases */
4fd4bb #define GO500_DEREF¤LDAP_DEREF_FINDING
f2054b ¤   /* attribute to use when sorting results */
4a1fbf #define GO500_SORT_ATTR¤SORT_ATTR
dd2dd1 ¤   /* timeout for searches */
07b687 #define GO500_TIMEOUT¤  180
54d621 ¤   /* enable ufn support */
f88507 #define GO500_UFN
01d8af ¤   /*
3ce346 ¤   ·* only set and uncomment this if your hostname() does not return
ddfcf0 ¤   ·* a fully qualified hostname
8ea4e3 ¤   ·*/
c15104 /* #define GO500_HOSTNAME¤  "fully.qualified.hostname.here" */
5e836b ¤   /* number of DN components to show in entry displays */
39fe2f #define GO500_RDNCOUNT¤ ¤   DEFAULT_RDNCOUNT¤
c8af5a
2138e5 /*
a28269 ·* GO500GW GOPHER GATEWAY DEFINITIONS
fc495d ·*/
212757 ¤   /* who to bind as */
687446 #define GO500GW_BINDDN¤ ¤   NULL
eea855 ¤   /* where the helpfile lives */
0cdc68 #define GO500GW_HELPFILE¤   "%ETCDIR%/go500gw.help"
4b7eff ¤   /* port on which to listen */
7b99e9 #define GO500GW_PORT¤   ¤   7777
f700a8 ¤   /* timeout on all searches */
c6469b #define GO500GW_TIMEOUT¤¤   180
25d621 ¤   /* enable ufn support */
67cbb7 #define GO500GW_UFN
3e054b ¤   /* attribute to use when sorting results */
207d23 #define GO500GW_SORT_ATTR¤  SORT_ATTR
4bd8af ¤   /*
ebe346 ¤   ·* only set and uncomment this if your hostname() does not return
71fcf0 ¤   ·* a fully qualified hostname
b9a4e3 ¤   ·*/
dcadc6 /* #define GO500GW_HOSTNAME¤"fully.qualified.hostname.here" */
d3836b ¤   /* number of DN components to show in entry displays */
7c5979 #define GO500GW_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
f1af5a
e238e5 /*
5dd8b1 ·* RCPT500 MAIL RESPONDER GATEWAY DEFINITIONS
de495d ·*/
f12757 ¤   /* who to bind as */
7f1b00 #define RCPT500_BINDDN¤ ¤   NULL
f3a855 ¤   /* where the helpfile lives */
14c41a #define RCPT500_HELPFILE¤   "%ETCDIR%/rcpt500.help"
b6c2cd ¤   /* maximum number of matches returned */
d28085 #define RCPT500_SIZELIMIT¤  50
95d8a7 ¤   /* address replies will appear to come from */
--bd33 000db37d2f040100077 Page 3 of ldapconfig.h.edit
404cfc #define RCPT500_FROM¤   ¤   "\"X.500 Query Program\" <X500-Query>"
9d93f8 ¤   /* command that will accept an RFC822 message text on standard
965bfd ¤   ···input, and send it. ·sendmail -t does this nicely. */
48b1bf #define RCPT500_PIPEMAILCMD¤"/usr/lib/sendmail -t"
5c249f ········/* where to search */
db46cd #define RCPT500_BASE ············DEFAULT_BASE
d4054b ¤   /* attribute to use when sorting results */
31ac84 #define RCPT500_SORT_ATTR¤  SORT_ATTR
093c15 ¤   /* max number of hits displayed in full before a list is presented */
4bb629 #define RCPT500_LISTLIMIT¤  1
70d621 ¤   /* enable ufn support */
b3292c #define RCPT500_UFN
ff836b ¤   /* number of DN components to show in entry displays */
e5d362 #define RCPT500_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
33af5a
ba38e5 /*
4e4826 ·* LDAPSEARCH TOOL
5b495d ·*/
0c2757 ¤   /* who to bind as */
feeabc #define LDAPSEARCH_BINDDN¤  NULL
18b081 ¤   /* search base */
6b2fb1 #define LDAPSEARCH_BASE¤¤   DEFAULT_BASE
f0af5a
a938e5 /*
2430c8 ·* LDAPMODIFY TOOL
6d495d ·*/
452757 ¤   /* who to bind as */
c14121 #define LDAPMODIFY_BINDDN¤  NULL
fdb081 ¤   /* search base */
e096ea #define LDAPMODIFY_BASE¤¤   DEFAULT_BASE
a8af5a
0038e5 /*
5fd5bb ·* LDAPDELETE TOOL
4e495d ·*/
e92757 ¤   /* who to bind as */
bcf66a #define LDAPDELETE_BINDDN¤  NULL
8cb081 ¤   /* search base */
81c338 #define LDAPDELETE_BASE¤¤   DEFAULT_BASE
84af5a
3f38e5 /*
641f2f ·* LDAPMODRDN TOOL
75495d ·*/
d22757 ¤   /* who to bind as */
7f7a0c #define LDAPMODRDN_BINDDN¤  NULL
76b081 ¤   /* search base */
ac3a0f #define LDAPMODRDN_BASE¤¤   DEFAULT_BASE
09af5a
c938e5 /*
0365c8 ·* MAIL500 MAILER DEFINITIONS
ee495d ·*/
0c2757 ¤   /* who to bind as */
ce489b #define MAIL500_BINDDN¤ ¤   NULL
aa13fb ¤   /* max number of ambiguous matches reported */
aeaea8 #define MAIL500_MAXAMBIGUOUS¤   10
e5acbe ¤   /* max subscribers allowed (size limit when searching for them ) */
ff80a0 #define MAIL500_MAXGROUPMEMBERS¤LDAP_NO_LIMIT
093b3d ¤   /* timeout for all searches */
f17076 #define MAIL500_TIMEOUT¤¤   180
d04924 ¤   /* sendmail location - mail500 needs to exec this */
ccc042 #define MAIL500_SENDMAIL¤   "/usr/lib/sendmail"
95af5a
c238e5 /*
fccd8a ·* UD DEFINITIONS
e1495d ·*/
e26abf ¤   /* ud configuration file */
3d8483 #define UD_CONFIG_FILE¤ ¤   "%ETCDIR%/ud.conf"
38f414 ¤   /* default editor */
324afb #define UD_DEFAULT_EDITOR¤  "/usr/ucb/vi"
3529b1 ¤   /* default bbasename of user config file */
ecbcd1 #define UD_USER_CONFIG_FILE¤".udrc"
3b977c ¤   /* default user to bind as */
db71f3 #define UD_BINDDN¤  ¤   NULL
--ec69 0018c1b493340100077 Page 4 of ldapconfig.h.edit
3f06a6 ¤   /* default password to bind with */
e5881d #define UD_PASSWD¤  ¤   NULL
264d57 ¤   /* default search base */
bd23af #define UD_BASE¤¤   ¤   DEFAULT_BASE
14921e ¤   /* default base where groups are created */
d5206e #define UD_WHERE_GROUPS_ARE_CREATED¤""
6f7a9f ¤   /* default base below which all groups live */
acea60 #define UD_WHERE_ALL_GROUPS_LIVE¤   ""
36af5a
2338e5 /*
e75862 ·* FAX500 DEFINITIONS
46495d ·*/
570dc1 ¤   /* what to bind as */
39aa62 #define FAX_BINDDN¤ NULL
ba97de ¤   /* how long to wait for searches */
1d5b5e #define FAX_TIMEOUT¤¤   180
683fdf ¤   /* maximum number of ambiguous matches reported */
daacca #define FAX_MAXAMBIGUOUS¤   10
6065ef ¤   /* maximum number of members allowed */
7fe4e8 #define FAX_MAXMEMBERS¤ ¤   LDAP_NO_LIMIT
485be6 ¤   /* program to send mail */
8cd214 #define FAX_SENDMAIL¤   ¤   "/usr/lib/sendmail"
8aaf5a
8b38e5 /*
cd6218 ·* RP500 DEFINITIONS
6b495d ·*/
520dc1 ¤   /* what to bind as */
b70ce3 #define RP_BINDDN¤  NULL
77fbd2 ¤   /* prefix to add to non-fully-qualified numbers */
0a2ea0 #define RP_PHONEPREFIX¤ ""
87af5a
3338e5 /*
351366 ·* SLAPD DEFINITIONS
c2495d ·*/
1ea1a1 ¤   /* location of the default slapd config file */
47cf14 #ifdef PGPKEYSERVER
71821b #define SLAPD_DEFAULT_CONFIGFILE¤   "pgpcertd.conf"
0adb21 #else
902410 #define SLAPD_DEFAULT_CONFIGFILE¤   "/export/home/marcd/ldap-3.3/etc/slapd.conf"
d57454 #endif
0191a4 ¤   /* Location of the default slapd access log file. */
00cf14 #ifdef PGPKEYSERVER
e8b262 #define SLAPD_DEFAULT_ACCESS_LOG_DIR¤   "/var/opt/PGPcs10/access.log"
7b7454 #endif
b5d7a9 ¤   /* default sizelimit on number of entries from a search */
42f900 #define SLAPD_DEFAULT_SIZELIMIT¤¤   500
72450d ¤   /* default timelimit to spend on a search */
62cf14 #ifdef PGPKEYSERVER
e15bc6 #define SLAPD_DEFAULT_TIMELIMIT¤¤   300
48db21 #else
600c73 #define SLAPD_DEFAULT_TIMELIMIT¤¤   3600
c67454 #endif
efd33d ¤   /* location of the slapd pid file */
0b0818 #ifndef WIN32¤  ¤   ¤   /* marcd */
1101c0 #define SLAPD_PIDFILE¤  ¤   ¤   "%ETCDIR%/slapd.pid"
bf7454 #endif
02f24b ¤   /* location of the slapd args file */
9687ec #define SLAPD_ARGSFILE¤ ¤   ¤   "%ETCDIR%/slapd.args"
9818a8 ¤   /* dn of the special "monitor" entry */
00a982 #define SLAPD_MONITOR_DN¤   ¤   "cn=monitor"
c3fbe8 ¤   /* dn of the special "config" entry */
cdabed ¤   /* Turn off for now since it doesn't give anything useful. */
5d9803 /* #define SLAPD_CONFIG_DN¤ ¤   ¤   "cn=config" */
4f346e ¤   /* minimum max ids that a single index entry can map to in ldbm */
f36643 #define SLAPD_LDBM_MIN_MAXIDS¤  ¤   4000
0aaf5a
8c3298 #endif /* _CONFIG_H */
--c5e1 0009e42265640100078 Page 1 of ldapconfig.h.um
bc38e5 /*
979eee ·* Copyright (c) 1994 Regents of the University of Michigan.
aa599a ·* All rights reserved.
f0775e ·*
88b855 ·* Redistribution and use in source and binary forms are permitted
cc9795 ·* provided that this notice is preserved and that due credit is given
e01873 ·* to the University of Michigan at Ann Arbor. The name of the University
4e8805 ·* may not be used to endorse or promote products derived from this
a874fe ·* software without specific prior written permission. This software
112a32 ·* is provided ``as is'' without express or implied warranty.
81495d ·*/
6aaf5a
897f62 #ifndef _CONFIG_H
e7a23b #define _CONFIG_H
d0af5a
ae38e5 /*
dd6bdf ·* config.h for LDAP -- edit this file to customize LDAP client behavior.
0f77d6 ·* NO platform-specific definitions should be placed in this file.
9f431e ·* Note that this is NOT used by the LDAP or LBER libraries.
13495d ·*/
15af5a
9e38e5 /*
bb0be2 ·* SHARED DEFINITIONS - things you should change
cd495d ·*/
ce71fc ¤   /* default ldap host */
c4f8ae #define LDAPHOST¤   "ldap.itd.umich.edu"
415036 ¤   /* default place to start searching */
e72ec2 #define DEFAULT_BASE¤   "o=University of Michigan, c=US"
59af5a
ee153d /*********************************************************************
16022e ·* ··································································*
84efdf ·* You probably do not need to edit anything below this point ·······*
0b022e ·* ··································································*
67dfd6 ·*********************************************************************/
19af5a
a538e5 /*
262527 ·* SHARED DEFINITIONS - other things you can change
cb495d ·*/
2aecb0 ¤   /* default attribute to use when sorting entries, NULL => sort by DN */
92655e #define SORT_ATTR¤  NULL
91c11f ¤   /* default count of DN components to show in entry displays */
4d2b7f #define DEFAULT_RDNCOUNT¤   2
476459 ¤   /* default config file locations */
b3a6d7 #define FILTERFILE¤ "%ETCDIR%/ldapfilter.conf"
39d810 #define TEMPLATEFILE¤   "%ETCDIR%/ldaptemplates.conf"
fc62f1 #define SEARCHFILE¤ "%ETCDIR%/ldapsearchprefs.conf"
c66086 #define FRIENDLYFILE¤   "%ETCDIR%/ldapfriendly"
68af5a
ed38e5 /*
a8a84c ·* FINGER DEFINITIONS
76495d ·*/
c42757 ¤   /* who to bind as */
d18318 #define FINGER_BINDDN¤  ¤   "cn=finger, ou=Miscellaneous Servers, o=University ¶
0f9da4 of Michigan, c=US"
db4fe5 ¤   /* where to search */
13b05a #define FINGER_BASE¤¤   DEFAULT_BASE
8d0306 ¤   /* banner to print */
7d41d3 #define FINGER_BANNER¤  ¤   "X.500 Finger Service...\r\n"
1844c7 ¤   /* who to report errors to */
560660 #define FINGER_ERRORS¤  ¤   "x500@umich.edu"
60fd6f ¤   /* what to say if no matches are found */
d0c910 #define FINGER_NOMATCH¤ ¤   \
97ddb4 "Search failed to find anything. ·Currently, this service contains\r\n\
1d8e3c information only on University of Michigan faculty, staff, and students.\r\n\
9b63c0 Other likely places to finger are:\r\n\
ccec61 ········um.cc.umich.edu\r\n\
956655 ········azure.engin.umich.edu\r\n"
87ca2c ¤   /* what to say if the service may be unavailable */
13231f #define FINGER_UNAVAILABLE¤ \
2e483b "The X.500 service may be temporarily unavailable.\r\n\
99702c Please try again later.\r\n"
9ead48 ¤   /* printed if a match has no email address - for disptmp default */
--0c6b 000ab78d19540100078 Page 2 of ldapconfig.h.um
207116 #define FINGER_NOEMAIL1¤"None registered in this service. ·Try fingering at:"
6c46ea #define FINGER_NOEMAIL2¤"um.cc.umich.edu or azure.engin.umich.edu"
369e40 #define FINGER_NOEMAIL¤ { FINGER_NOEMAIL1, FINGER_NOEMAIL2, NULL }
8bc2cd ¤   /* maximum number of matches returned */
12e05b #define FINGER_SIZELIMIT¤   50
653c15 ¤   /* max number of hits displayed in full before a list is presented */
232f3d #define FINGER_LISTLIMIT¤   1
5ea51d ¤   /* what to exec for "finger @host" */
03d4d7 #define FINGER_CMD¤ ¤   "/usr/ucb/finger"
f64f9b ¤   /* how to treat aliases when searching */
ce4b00 #define FINGER_DEREF¤   ¤   LDAP_DEREF_FINDING
ee054b ¤   /* attribute to use when sorting results */
c70d6d #define FINGER_SORT_ATTR¤   SORT_ATTR
93d621 ¤   /* enable ufn support */
b6ac67 #define FINGER_UFN
b82dd1 ¤   /* timeout for searches */
a0dedc #define FINGER_TIMEOUT¤ ¤   60
fe836b ¤   /* number of DN components to show in entry displays */
b02cf7 #define FINGER_RDNCOUNT¤¤   DEFAULT_RDNCOUNT¤
74af5a
0638e5 /*
4a8dd9 ·* GO500 GOPHER GATEWAY DEFINITIONS
45495d ·*/
c22757 ¤   /* who to bind as */
926092 #define GO500_BINDDN¤   "cn=go500, ou=Miscellaneous Servers, o=University of Mi¶
e25c76 chigan, c=US"
334fe5 ¤   /* where to search */
2b5a9d #define GO500_BASE¤ DEFAULT_BASE
e17eff ¤   /* port on which to listen */
cf2e33 #define GO500_PORT¤ 5555
b0a0bd ¤   /* how to handle aliases */
d9d4bb #define GO500_DEREF¤LDAP_DEREF_FINDING
19054b ¤   /* attribute to use when sorting results */
bb1fbf #define GO500_SORT_ATTR¤SORT_ATTR
5a2dd1 ¤   /* timeout for searches */
17c895 #define GO500_TIMEOUT¤  60
dfd621 ¤   /* enable ufn support */
208507 #define GO500_UFN
82d8af ¤   /*
26e346 ¤   ·* only set and uncomment this if your hostname() does not return
b3fcf0 ¤   ·* a fully qualified hostname
55a4e3 ¤   ·*/
8d5104 /* #define GO500_HOSTNAME¤  "fully.qualified.hostname.here" */
2d836b ¤   /* number of DN components to show in entry displays */
04fe2f #define GO500_RDNCOUNT¤ ¤   DEFAULT_RDNCOUNT¤
ceaf5a
1a38e5 /*
c18269 ·* GO500GW GOPHER GATEWAY DEFINITIONS
b7495d ·*/
732757 ¤   /* who to bind as */
cd96ab #define GO500GW_BINDDN¤ ¤   "cn=go500gw, ou=Miscellaneous Servers, o=University¶
81f25e ·of Michigan, c=US"
06a855 ¤   /* where the helpfile lives */
d1dc68 #define GO500GW_HELPFILE¤   "%ETCDIR%/go500gw.help"
4c7eff ¤   /* port on which to listen */
8399e9 #define GO500GW_PORT¤   ¤   7777
2000a8 ¤   /* timeout on all searches */
d2469b #define GO500GW_TIMEOUT¤¤   180
70d621 ¤   /* enable ufn support */
3dcbb7 #define GO500GW_UFN
ad054b ¤   /* attribute to use when sorting results */
eb7d23 #define GO500GW_SORT_ATTR¤  SORT_ATTR
83d8af ¤   /*
21e346 ¤   ·* only set and uncomment this if your hostname() does not return
00fcf0 ¤   ·* a fully qualified hostname
0ea4e3 ¤   ·*/
64adc6 /* #define GO500GW_HOSTNAME¤"fully.qualified.hostname.here" */
c9836b ¤   /* number of DN components to show in entry displays */
3f5979 #define GO500GW_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
24af5a
dd38e5 /*
abd8b1 ·* RCPT500 MAIL RESPONDER GATEWAY DEFINITIONS
--3d25 000d7c2b02d40100078 Page 3 of ldapconfig.h.um
47495d ·*/
c92757 ¤   /* who to bind as */
03e21b #define RCPT500_BINDDN¤ ¤   "cn=Rcpt500, ou=Miscellaneous Servers, o=University¶
00f25e ·of Michigan, c=US"
94a855 ¤   /* where the helpfile lives */
6cc41a #define RCPT500_HELPFILE¤   "%ETCDIR%/rcpt500.help"
bbc2cd ¤   /* maximum number of matches returned */
e18085 #define RCPT500_SIZELIMIT¤  50
2ed8a7 ¤   /* address replies will appear to come from */
db4cfc #define RCPT500_FROM¤   ¤   "\"X.500 Query Program\" <X500-Query>"
1b93f8 ¤   /* command that will accept an RFC822 message text on standard
1a5bfd ¤   ···input, and send it. ·sendmail -t does this nicely. */
66b1bf #define RCPT500_PIPEMAILCMD¤"/usr/lib/sendmail -t"
fb249f ········/* where to search */
9246cd #define RCPT500_BASE ············DEFAULT_BASE
7f054b ¤   /* attribute to use when sorting results */
beac84 #define RCPT500_SORT_ATTR¤  SORT_ATTR
ce3c15 ¤   /* max number of hits displayed in full before a list is presented */
7f8599 #define RCPT500_LISTLIMIT¤  3
efd621 ¤   /* enable ufn support */
4b292c #define RCPT500_UFN
58836b ¤   /* number of DN components to show in entry displays */
88d362 #define RCPT500_RDNCOUNT¤   DEFAULT_RDNCOUNT¤
16af5a
4038e5 /*
0a4826 ·* LDAPSEARCH TOOL
06495d ·*/
d82757 ¤   /* who to bind as */
3125f2 #define LDAPSEARCH_BINDDN¤  "cn=LDAP Search Tool, ou=Miscellaneous Servers, o=U¶
e89586 niversity of Michigan, c=US"
9bb081 ¤   /* search base */
632fb1 #define LDAPSEARCH_BASE¤¤   DEFAULT_BASE
e3af5a
2638e5 /*
da30c8 ·* LDAPMODIFY TOOL
10495d ·*/
8c2757 ¤   /* who to bind as */
2af2b0 #define LDAPMODIFY_BINDDN¤  "cn=Manager, o=University of Michigan, c=US"
e3b081 ¤   /* search base */
d296ea #define LDAPMODIFY_BASE¤¤   DEFAULT_BASE
23af5a
1238e5 /*
79d5bb ·* LDAPDELETE TOOL
0b495d ·*/
d82757 ¤   /* who to bind as */
a8359f #define LDAPDELETE_BINDDN¤  "cn=Manager, o=University of Michigan, c=US"
38b081 ¤   /* search base */
32c338 #define LDAPDELETE_BASE¤¤   DEFAULT_BASE
67af5a
6738e5 /*
761f2f ·* LDAPMODRDN TOOL
58495d ·*/
ed2757 ¤   /* who to bind as */
e6797e #define LDAPMODRDN_BINDDN¤  "cn=Manager, o=University of Michigan, c=US"
2bb081 ¤   /* search base */
cd3a0f #define LDAPMODRDN_BASE¤¤   DEFAULT_BASE
ccaf5a
3538e5 /*
f165c8 ·* MAIL500 MAILER DEFINITIONS
83495d ·*/
472757 ¤   /* who to bind as */
44efa9 #define MAIL500_BINDDN¤ ¤   "cn=mail500, ou=Miscellaneous Servers, o=University¶
bdf25e ·of Michigan, c=US"
2c13fb ¤   /* max number of ambiguous matches reported */
29aea8 #define MAIL500_MAXAMBIGUOUS¤   10
2cacbe ¤   /* max subscribers allowed (size limit when searching for them ) */
cb80a0 #define MAIL500_MAXGROUPMEMBERS¤LDAP_NO_LIMIT
273b3d ¤   /* timeout for all searches */
227076 #define MAIL500_TIMEOUT¤¤   180
864924 ¤   /* sendmail location - mail500 needs to exec this */
cfc042 #define MAIL500_SENDMAIL¤   "/usr/lib/sendmail"
d7af5a
--bb9c 0017e47dd9b40100078 Page 4 of ldapconfig.h.um
bc38e5 /*
18cd8a ·* UD DEFINITIONS
a7495d ·*/
a56abf ¤   /* ud configuration file */
538483 #define UD_CONFIG_FILE¤ ¤   "%ETCDIR%/ud.conf"
5ff414 ¤   /* default editor */
e34afb #define UD_DEFAULT_EDITOR¤  "/usr/ucb/vi"
7329b1 ¤   /* default bbasename of user config file */
e2bcd1 #define UD_USER_CONFIG_FILE¤".udrc"
0b977c ¤   /* default user to bind as */
d6fd72 #define UD_BINDDN¤  ¤   "cn=ud, ou=Miscellaneous Servers, o=University of Michi¶
703168 gan, c=US"
dc06a6 ¤   /* default password to bind with */
6c881d #define UD_PASSWD¤  ¤   NULL
b44d57 ¤   /* default search base */
b323af #define UD_BASE¤¤   ¤   DEFAULT_BASE
2f921e ¤   /* default base where groups are created */
d76256 #define UD_WHERE_GROUPS_ARE_CREATED¤"ou=User Groups, ou=Groups, o=University of¶
6dddf7 ·Michigan, c=US"
517a9f ¤   /* default base below which all groups live */
7b1f1f #define UD_WHERE_ALL_GROUPS_LIVE¤   "ou=Groups, o=University of Michigan, c=US"
7baf5a
e638e5 /*
2f5862 ·* FAX500 DEFINITIONS
8c495d ·*/
b20dc1 ¤   /* what to bind as */
da9a03 #define FAX_BINDDN¤ "cn=mail500, ou=Miscellaneous Servers, o=University of Mich¶
16c201 igan, c=US"
3d97de ¤   /* how long to wait for searches */
8e5b5e #define FAX_TIMEOUT¤¤   180
3b3fdf ¤   /* maximum number of ambiguous matches reported */
5dacca #define FAX_MAXAMBIGUOUS¤   10
a865ef ¤   /* maximum number of members allowed */
9ce4e8 #define FAX_MAXMEMBERS¤ ¤   LDAP_NO_LIMIT
cd5be6 ¤   /* program to send mail */
0ed214 #define FAX_SENDMAIL¤   ¤   "/usr/lib/sendmail"
21af5a
6238e5 /*
dc6218 ·* RP500 DEFINITIONS
44495d ·*/
ec0dc1 ¤   /* what to bind as */
e3f08d #define RP_BINDDN¤  "cn=rp500, ou=Miscellaneous Servers, o=University of Michig¶
cdbe01 an, c=US"
d2fbd2 ¤   /* prefix to add to non-fully-qualified numbers */
c6fc3f #define RP_PHONEPREFIX¤ "1313"
1aaf5a
5c38e5 /*
1c1366 ·* SLAPD DEFINITIONS
72495d ·*/
86a1a1 ¤   /* location of the default slapd config file */
9a9f2b #define SLAPD_DEFAULT_CONFIGFILE¤   "%ETCDIR%/slapd.conf"
62d7a9 ¤   /* default sizelimit on number of entries from a search */
58f900 #define SLAPD_DEFAULT_SIZELIMIT¤¤   500
8a450d ¤   /* default timelimit to spend on a search */
d20c73 #define SLAPD_DEFAULT_TIMELIMIT¤¤   3600
45d33d ¤   /* location of the slapd pid file */
1501c0 #define SLAPD_PIDFILE¤  ¤   ¤   "%ETCDIR%/slapd.pid"
2cf24b ¤   /* location of the slapd args file */
bd87ec #define SLAPD_ARGSFILE¤ ¤   ¤   "%ETCDIR%/slapd.args"
8218a8 ¤   /* dn of the special "monitor" entry */
eba982 #define SLAPD_MONITOR_DN¤   ¤   "cn=monitor"
04fbe8 ¤   /* dn of the special "config" entry */
b4a609 #define SLAPD_CONFIG_DN¤¤   ¤   "cn=config"
7b346e ¤   /* minimum max ids that a single index entry can map to in ldbm */
cb6643 #define SLAPD_LDBM_MIN_MAXIDS¤  ¤   4000
00af5a
7e3298 #endif /* _CONFIG_H */
--a2aa 0019e63557d40100079 Page 1 of pgpSrvStd.h
adf5d5 /* ·pgpSrvStd.h
c2af5a
15fdc1 ¤   Standard defines, structures, and prototypes for all server products.
5baf5a
0bc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
d94b0f ¤   All rights reserved.
4daf5a
d38f7d ¤   $Id: pgpSrvStd.h,v 1.2.10.1 1998/11/12 03:17:31 heller Exp $
47af5a
267fe0 */
b5af5a
7fc946 #ifndef Included_CertServ_pgpSrvStd_h
442fa9 #define Included_CertServ_pgpSrvStd_h
75af5a
9a0d42 /* For now, just remap mem allocs for key server stuff. */
03cf14 #ifdef PGPKEYSERVER
3faf5a
e0bea3 #include <stdlib.h>
16c5d5 #include "pgpBase.h"
fbaf5a
4038e5 /*
f3ed8e #define malloc(size)¤   ¤   ¤   ¤   ¤   pgpMemAlloc(size)
2539be #define realloc(userPtr, newSize)¤  ¤   pgpMemRealloc(userPtr, newSize)
85582f #define free(userPtr)¤  ¤   ¤   ¤   ¤   pgpSrvFree(userPtr)
89fcee #define strdup(str)¤¤   ¤   ¤   ¤   ¤   pgpSrvStrDup(str, __FILE__, __LINE__)
f43a1c #define calloc(num, size)¤  ¤   ¤   ¤   pgpSrvCAlloc(num, size, __FILE__, __LIN¶
4512cc E__)
057fe0 */
5daf5a
f1bd16 #define malloc(size)¤   ¤   ¤   ¤   ¤   pgpSrvMalloc(size)
dea611 #define realloc(userPtr, newSize)¤  ¤   pgpSrvRealloc(userPtr, newSize)
bc582f #define free(userPtr)¤  ¤   ¤   ¤   ¤   pgpSrvFree(userPtr)
8f4672 #define strdup(str)¤¤   ¤   ¤   ¤   ¤   pgpSrvStrDup(str)
ef48fa #define calloc(num, size)¤  ¤   ¤   ¤   pgpSrvCalloc(num, size)
36af5a
9d99c6 PGP_BEGIN_C_DECLARATIONS
9aaf5a
6011e4 char *
85c43e pgpSrvMalloc(size_t ulSize);
f1af5a
a611e4 char *
731b10 pgpSrvCalloc(size_t ulNum, size_t ulSize);
d1af5a
13314a void
7f0b11 pgpSrvFree(void *pMem);
deaf5a
1f11e4 char *
92433d pgpSrvStrDup(const char *pszStr);
aeaf5a
8a11e4 char *
b1c6c5 pgpSrvRealloc(char *pszPtr, size_t ulSize);
b6af5a
0f1254 PGP_END_C_DECLARATIONS
02af5a
169cf9 #endif¤ /* PGPKEYSERVER */
077454 #endif
9eaf5a
--367e 00035ba08724010007a Page 1 of portable.h
bc38e5 /*
979eee ·* Copyright (c) 1994 Regents of the University of Michigan.
aa599a ·* All rights reserved.
f0775e ·*
88b855 ·* Redistribution and use in source and binary forms are permitted
cc9795 ·* provided that this notice is preserved and that due credit is given
e01873 ·* to the University of Michigan at Ann Arbor. The name of the University
4e8805 ·* may not be used to endorse or promote products derived from this
a874fe ·* software without specific prior written permission. This software
112a32 ·* is provided ``as is'' without express or implied warranty.
81495d ·*/
6aaf5a
59c805 #ifndef _PORTABLE_H
a5c182 #define _PORTABLE_H
53af5a
be38e5 /*
ba1804 ·* portable.h for LDAP -- this is where we define common stuff to make
4c5027 ·* life easier on various Unix systems.
b9775e ·*
680bc4 ·* Unless you are porting LDAP to a new platform, you should not need to
41b0d4 ·* edit this file.
78495d ·*/
07af5a
7aaf5a
aefd25 #ifndef SYSV
c24e1b #if defined( hpux ) || defined( sunos5 ) || defined ( sgi ) || defined( SVR4 )
ffe2a0 #define SYSV
3b7454 #endif
607454 #endif
f2af5a
afaf5a
2f38e5 /*
0bbf09 ·* under System V, use sysconf() instead of getdtablesize
92495d ·*/
0d5bf8 #if !defined( USE_SYSCONF ) && defined( SYSV )
194968 #define USE_SYSCONF
057454 #endif
1aaf5a
2aaf5a
8538e5 /*
650d62 ·* under System V, daemons should use setsid() instead of detaching from their
b8b5c9 ·* tty themselves
30495d ·*/
1e8cc2 #if !defined( USE_SETSID ) && defined( SYSV )
8b1709 #define USE_SETSID
b37454 #endif
6baf5a
c0af5a
5738e5 /*
57ccfb ·* System V has socket options in filio.h
0c495d ·*/
c5fe4c #if !defined( NEED_FILIO ) && defined( SYSV ) && !defined( hpux )
2702e2 #define NEED_FILIO
027454 #endif
bcaf5a
7038e5 /*
6f2568 ·* use lockf() under System V
96495d ·*/
86220c #if !defined( USE_LOCKF ) && ( defined( SYSV ) || defined( aix ))
ed7c99 #define USE_LOCKF
487454 #endif
eeaf5a
9238e5 /*
d5601b ·* on many systems, we should use waitpid() instead of waitN()
7d495d ·*/
cec114 #if !defined( USE_WAITPID ) && ( defined( SYSV ) || defined( sunos4 ) || \
470dbd ····defined( ultrix ) || defined( aix ))
0d155c #define USE_WAITPID
ef7454 #endif
45af5a
7baf5a
3538e5 /*
--6a84 00080eec1574010007a Page 2 of portable.h
c1d8b1 ·* define the wait status argument type
cf495d ·*/
ff29f5 #if ( defined( SunOS ) && SunOS < 40 ) || defined( nextstep )
883c82 #define WAITSTATUSTYPE¤ union wait
81db21 #else
535af9 #define WAITSTATUSTYPE¤ int
227454 #endif
18af5a
fe38e5 /*
2c7776 ·* define the flags for wait
d8495d ·*/
8e3bfc #ifdef sunos5
d3d00a #define WAIT_FLAGS¤ ( WNOHANG | WUNTRACED | WCONTINUED )
87db21 #else
d6fd9d #define WAIT_FLAGS¤ ( WNOHANG | WUNTRACED )
ac7454 #endif
86af5a
ceaf5a
1438e5 /*
8e9c50 ·* defined the options for openlog (syslog)
02495d ·*/
f2b4c5 #ifdef ultrix
5314f0 #define OPENLOG_OPTIONS¤¤   LOG_PID
7cdb21 #else
4260e1 #define OPENLOG_OPTIONS¤¤   ( LOG_PID | LOG_NOWAIT )
9b7454 #endif
57af5a
42af5a
a338e5 /*
62b7c9 ·* some systems don't have the BSD re_comp and re_exec routines
3b495d ·*/
0d7cad #ifndef NEED_BSDREGEX
444af8 #if defined( SYSV ) || defined( VMS ) || defined( netbsd ) || \
855b4d ····defined( freebsd ) || defined( linux )
b820a8 #define NEED_BSDREGEX
717454 #endif
397454 #endif
54af5a
f538e5 /*
e28a09 ·* many systems do not have the setpwfile() library routine... we just
5ec623 ·* enable use for those systems we know have it.
b4495d ·*/
4d771e #ifndef HAVE_SETPWFILE
258a06 #if defined( sunos4 ) || defined( ultrix ) || defined( __osf__ )
a820ef #define HAVE_SETPWFILE
e67454 #endif
707454 #endif
0daf5a
0838e5 /*
ebc786 ·* Are sys_errlist and sys_nerr declared in stdio.h?
6b495d ·*/
7f78b2 #ifndef SYSERRLIST_IN_STDIO
6e1344 #if defined( freebsd )·
746e67 #define SYSERRLIST_IN_STDIO
c87454 #endif
a67454 #endif
5baf5a
0838e5 /*
9ec3a7 ·* for select()
0e495d ·*/
0a81b9 #if !defined(FD_SET) && !defined(WINSOCK) && !defined(PGPSOCKETSLDAP) /* jason ¶
547fe0 */
537ff9 #define NFDBITS ········32
962ce7 #define FD_SETSIZE ·····32
d0ec32 #define FD_SET(n, p) ···((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
1b15be #define FD_CLR(n, p) ···((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
7f72b8 #define FD_ISSET(n, p) ·((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
060203 #define FD_ZERO(p) ·····bzero((char *)(p), sizeof(*(p)))
8e3e87 #endif /* FD_SET */
c7af5a
9395b9 #if defined( hpux ) && defined( __STDC__ )
8038e5 /*
--2300 000482156204010007a Page 3 of portable.h
dee4b0 ·* Under HP/UX, select seems to want (int *) instead of fd_set. ·Non-ANSI
21e679 ·* compilers don't like recursive macros, so ignore the problem if __STDC__
86a929 ·* is not defined.
59495d ·*/
cda5ea #define select(a,b,c,d,e) select(a, (int *)b, (int *)c, (int *)d, e)
ba3290 #endif /* hpux && __STDC__ */
f1af5a
3aaf5a
ca38e5 /*
eb6374 ·* for signal() -- what do signal handling functions return?
0f495d ·*/
8b839b #ifndef SIG_FN
403bfc #ifdef sunos5
b0d973 # ··define SIG_FN void ·········/* signal-catching functions return void */
dc758d #else /* sunos5 */
04e068 # ifdef BSD
dd01f7 # ·if (BSD >= 199006) || defined(NeXT) || defined(__osf__) || defined(sun) \
6b1832 ······|| defined(ultrix) || defined(apollo) || defined(POSIX_SIGNALS)
89d973 # ··define SIG_FN void ·········/* signal-catching functions return void */
5dd33c # ·else
2af082 # ··define SIG_FN int ··········/* signal-catching functions return int */
70bf38 # ·endif
31be3f # else /* BSD */
74bf5e # ·define SIG_FN void ··········/* signal-catching functions return void */
95c70a # endif /* BSD */
5de7b1 #endif /* sunos5 */
784e77 #endif /* SIG_FN */
02af5a
a038e5 /*
710833 ·* call signal or sigset (signal does not block the signal while
892d96 ·* in the handler on sys v and sigset does not exist on bsd)
40495d ·*/
6c6c20 #ifdef SYSV
7e0a7d #define SIGNAL sigset
b6db21 #else
997a63 #define SIGNAL signal
b27454 #endif
5aaf5a
0e38e5 /*
e6cc70 ·* toupper and tolower macros are different under bsd and sys v
27495d ·*/
356919 #if defined( SYSV ) && !defined( hpux )
783c77 #define TOUPPER(c)¤ (isascii(c) && islower(c) ? _toupper(c) : c)
2490df #define TOLOWER(c)¤ (isascii(c) && isupper(c) ? _tolower(c) : c)
69db21 #else
531fb6 #define TOUPPER(c)¤ (isascii(c) && islower(c) ? toupper(c) : c)
5f10ed #define TOLOWER(c)¤ (isascii(c) && isupper(c) ? tolower(c) : c)
127454 #endif
9daf5a
8038e5 /*
e69928 ·* put a cover on the tty-related ioctl calls we need to use
53495d ·*/
4cea43 #if defined( NeXT ) || (defined(SunOS) && SunOS < 40)
9c3597 #define TERMIO_TYPE struct sgttyb
445fc7 #define TERMFLAG_TYPE int
3417de #define GETATTR( fd, tiop )¤ioctl((fd), TIOCGETP, (caddr_t)(tiop))
25f801 #define SETATTR( fd, tiop )¤ioctl((fd), TIOCSETP, (caddr_t)(tiop))
14b435 #define GETFLAGS( tio )¤¤   (tio).sg_flags
cce690 #define SETFLAGS( tio, flags )¤ (tio).sg_flags = (flags)
eadb21 #else
d04ec9 #define USE_TERMIOS
440230 #define TERMIO_TYPE struct termios
fedc0e #define TERMFLAG_TYPE tcflag_t
ae2689 #define GETATTR( fd, tiop )¤tcgetattr((fd), (tiop))
9a0d6c #define SETATTR( fd, tiop )¤tcsetattr((fd), TCSANOW /* 0 */, (tiop))
31c09e #define GETFLAGS( tio )¤¤   (tio).c_lflag
14b763 #define SETFLAGS( tio, flags )¤ (tio).c_lflag = (flags)
b27454 #endif
37af5a
beaf5a
d6f5b7 #if defined( ultrix ) || defined( nextstep )
48ea94 extern char *strdup();
--7658 00147429e724010007a Page 4 of portable.h
392bbe #endif /* ultrix || nextstep */
8faf5a
4745c6 #endif /* _PORTABLE_H */
--345b 000837bb2624010007b Page 1 of proto-lber.h
bc38e5 /*
a47f0c ·* lber-proto.h
dc3856 ·* function prototypes for lber library
56495d ·*/
e5af5a
fbaf5a
782639 #ifdef LDAP_DEBUG
2f6cb8 extern int lber_debug;
e57454 #endif
3caf5a
4b27a5 #ifndef LDAPFUNCDECL
e551d3 #ifdef xx_WIN32¤¤   ¤   /* marcd */
0a9655 #define LDAPFUNCDECL¤   __declspec( dllexport )
2e88eb #else /* _WIN32 */
8dd71b #define LDAPFUNCDECL
d61ad7 #endif /* _WIN32 */
a5be74 #endif /* LDAPFUNCDECL */
faaf5a
9e38e5 /*
5cbc74 ·* in bprint.c:
58495d ·*/
f849c1 LDAPFUNCDECL void lber_bprint( char *data, int len );
7baf5a
7b38e5 /*
0dcd2a ·* in decode.c:
06495d ·*/
bc97a6 LDAPFUNCDECL unsigned long ber_get_tag( BerElement *ber );
7d600e LDAPFUNCDECL unsigned long ber_skip_tag( BerElement *ber, unsigned long *len );
4b8a73 LDAPFUNCDECL unsigned long ber_peek_tag( BerElement *ber, unsigned long *len );
a4b9e8 LDAPFUNCDECL unsigned long ber_get_int( BerElement *ber, long *num );
5ba9f8 LDAPFUNCDECL unsigned long ber_get_stringb( BerElement *ber, char *buf,
f4d238 ¤   unsigned long *len );
f60825 LDAPFUNCDECL unsigned long ber_get_stringa( BerElement *ber, char **buf );
088e6b LDAPFUNCDECL unsigned long ber_get_stringal( BerElement *ber,·
234302 ¤   struct berval **bv );
d55f32 LDAPFUNCDECL unsigned long ber_get_bitstringa( BerElement *ber, char **buf,
cbd238 ¤   unsigned long *len );
ae352f LDAPFUNCDECL unsigned long ber_get_null( BerElement *ber );
349aeb LDAPFUNCDECL unsigned long ber_get_boolean( BerElement *ber, int *boolval );
bd094f LDAPFUNCDECL unsigned long ber_first_element( BerElement *ber,·
785a5f ¤   unsigned long *len, char **last );
e4a218 LDAPFUNCDECL unsigned long ber_next_element( BerElement *ber,·
870b28 ¤   unsigned long *len, char *last );
ca2f53 #if defined(PGPSOCKETSLDAP) || defined(MACOS) || defined(BC31) || defined(_WIN3¶
da6867 2)
a726c1 LDAPFUNCDECL unsigned long ber_scanf( BerElement *ber, char *fmt, ... );
48db21 #else
183010 LDAPFUNCDECL unsigned long ber_scanf();
dd7454 #endif
3019aa LDAPFUNCDECL void ber_bvfree( struct berval *bv );
60f311 LDAPFUNCDECL void ber_bvecfree( struct berval **bv );
9913f0 LDAPFUNCDECL struct berval *ber_bvdup( struct berval *bv );
e8f52a #ifdef STR_TRANSLATION
8abda9 LDAPFUNCDECL void ber_set_string_translators( BerElement *ber,
27d4e3 ¤   BERTranslateProc encode_proc, BERTranslateProc decode_proc );
db3dd6 #endif /* STR_TRANSLATION */
efaf5a
7e38e5 /*
21a563 ·* in encode.c
41495d ·*/
3de3ee LDAPFUNCDECL int ber_put_enum( BerElement *ber, long num, unsigned long tag );
9df144 LDAPFUNCDECL int ber_put_int( BerElement *ber, long num, unsigned long tag );
7d84a4 LDAPFUNCDECL int ber_put_ostring( BerElement *ber, char *str, unsigned long len,
31e0e7 ¤   unsigned long tag );
73e3d3 LDAPFUNCDECL int ber_put_string( BerElement *ber, char *str,·
e4e0e7 ¤   unsigned long tag );
0e8096 LDAPFUNCDECL int ber_put_bitstring( BerElement *ber, char *str,
d79d7b ¤   unsigned long bitlen, unsigned long tag );
9ee718 LDAPFUNCDECL int ber_put_null( BerElement *ber, unsigned long tag );
d6c6b4 LDAPFUNCDECL int ber_put_boolean( BerElement *ber, int boolval,
d1e0e7 ¤   unsigned long tag );
83233c LDAPFUNCDECL int ber_start_seq( BerElement *ber, unsigned long tag );
--f986 001267f3bbc4010007b Page 2 of proto-lber.h
1ad695 LDAPFUNCDECL int ber_start_set( BerElement *ber, unsigned long tag );
967a17 LDAPFUNCDECL int ber_put_seq( BerElement *ber );
41661c LDAPFUNCDECL int ber_put_set( BerElement *ber );
c22f53 #if defined(PGPSOCKETSLDAP) || defined(MACOS) || defined(BC31) || defined(_WIN3¶
e66867 2)
4c7e4a LDAPFUNCDECL int ber_printf( BerElement *ber, char *fmt, ... );
fadb21 #else
7a3104 LDAPFUNCDECL int ber_printf();
8e7454 #endif
9faf5a
c038e5 /*
43ae58 ·* in io.c:
1e495d ·*/
ccdcae LDAPFUNCDECL long ber_read( BerElement *ber, char *buf, unsigned long len );
c58585 LDAPFUNCDECL long ber_write( BerElement *ber, char *buf, unsigned long len,
0cd841 ¤   int nosos );
f4aeaf LDAPFUNCDECL void ber_free( BerElement *ber, int freebuf );
23493d LDAPFUNCDECL int ber_flush( Sockbuf *sb, BerElement *ber, int freeit );
2643bf LDAPFUNCDECL BerElement *ber_alloc( void );
d7303a LDAPFUNCDECL BerElement *der_alloc( void );
c45f83 LDAPFUNCDECL BerElement *ber_alloc_t( int options );
e00bb6 LDAPFUNCDECL BerElement *ber_dup( BerElement *ber );
f30b5c LDAPFUNCDECL void ber_dump( BerElement *ber, int inout );
31e343 LDAPFUNCDECL void ber_sos_dump( Seqorset *sos );
23c21b LDAPFUNCDECL unsigned long ber_get_next( Sockbuf *sb, unsigned long *len,
594393 ¤   BerElement *ber );
f0bc63 LDAPFUNCDECL void ber_init( BerElement *ber, int options );
696663 LDAPFUNCDECL void ber_reset( BerElement *ber, int was_writing );
25af5a
cb0ebe #ifdef NEEDGETOPT
5738e5 /*
c6ad6e ·* in getopt.c
a6495d ·*/
1dbe13 int getopt( int nargc, char **nargv, char *ostr );
26f65f #endif /* NEEDGETOPT */
--aac7 000fcb058604010007c Page 1 of proto-ldap.h
bc38e5 /*
aaf0ce ·* proto-ldap.h
2f3980 ·* function prototypes for ldap library
cd495d ·*/
bbaf5a
a3e990 #include "ldap.h"
01af5a
a927a5 #ifndef LDAPFUNCDECL
21ec08 #ifdef _WIN32
af9655 #define LDAPFUNCDECL¤   __declspec( dllexport )
dc88eb #else /* _WIN32 */
f7d71b #define LDAPFUNCDECL
ea1ad7 #endif /* _WIN32 */
cfbe74 #endif /* LDAPFUNCDECL */
89af5a
d8af5a
9b3379 #ifdef __cplusplus
8b6dad extern "C" {
997454 #endif
f738e5 /*
ac28f0 ·* in abandon.c:
a2495d ·*/
a5d0a8 LDAPFUNCDECL int ldap_abandon( LDAP *ld, int msgid );
a0af5a
6f38e5 /*
f33b1d ·* in add.c:
f2495d ·*/
8f347c LDAPFUNCDECL int ldap_add( LDAP *ld, char *dn, LDAPMod **attrs );
8a1eda LDAPFUNCDECL int ldap_add_s( LDAP *ld, char *dn, LDAPMod **attrs );
86af5a
aa38e5 /*
495079 ·* in bind.c:
70495d ·*/
e9b3f9 LDAPFUNCDECL int ldap_bind( LDAP *ld, char *who, char *passwd, int authmethod );
85ed25 LDAPFUNCDECL int ldap_bind_s( LDAP *ld, char *who, char *cred, int method );
5b7f8d #ifdef LDAP_REFERRALS
854ef8 LDAPFUNCDECL void ldap_set_rebind_proc( LDAP *ld, int (*rebindproc)( LDAP *ld,
bc2dd3 ¤   char **dnp, char **passwdp, int *authmethodp, int freeit ));
c290e2 #endif /* LDAP_REFERRALS */
47af5a
9738e5 /*
2503b2 ·* in sbind.c:
bd495d ·*/
556548 LDAPFUNCDECL int ldap_simple_bind( LDAP *ld, char *who, char *passwd );
434905 LDAPFUNCDECL int ldap_simple_bind_s( LDAP *ld, char *who, char *passwd );
e4af5a
dc38e5 /*
9983ec ·* in kbind.c:
64495d ·*/
f81d2e LDAPFUNCDECL int ldap_kerberos_bind_s( LDAP *ld, char *who );
74601e LDAPFUNCDECL int ldap_kerberos_bind1( LDAP *ld, char *who );
02513f LDAPFUNCDECL int ldap_kerberos_bind1_s( LDAP *ld, char *who );
753fff LDAPFUNCDECL int ldap_kerberos_bind2( LDAP *ld, char *who );
c40b0c LDAPFUNCDECL int ldap_kerberos_bind2_s( LDAP *ld, char *who );
8fd83c ·
a0af5a
0e23e9 #ifndef NO_CACHE
6238e5 /*
026681 ·* in cache.c
35495d ·*/
4a5405 LDAPFUNCDECL int ldap_enable_cache( LDAP *ld, long timeout, long maxmem );
cc067f LDAPFUNCDECL void ldap_disable_cache( LDAP *ld );
a07d37 LDAPFUNCDECL void ldap_set_cache_options( LDAP *ld, unsigned long opts );
7afc66 LDAPFUNCDECL void ldap_destroy_cache( LDAP *ld );
a2495e LDAPFUNCDECL void ldap_flush_cache( LDAP *ld );
072f99 LDAPFUNCDECL void ldap_uncache_entry( LDAP *ld, char *dn );
2980a3 LDAPFUNCDECL void ldap_uncache_request( LDAP *ld, int msgid );
a9e842 #endif /* !NO_CACHE */
b1af5a
9438e5 /*
f29d3a ·* in compare.c:
fc495d ·*/
--c259 0001178145e4010007c Page 2 of proto-ldap.h
837be6 LDAPFUNCDECL int ldap_compare( LDAP *ld, char *dn, char *attr, char *value );
b728be LDAPFUNCDECL int ldap_compare_s( LDAP *ld, char *dn, char *attr, char *value );
1baf5a
8c38e5 /*
afd77f ·* in delete.c:
62495d ·*/
a884e5 LDAPFUNCDECL int ldap_delete( LDAP *ld, char *dn );
03f959 LDAPFUNCDECL int ldap_delete_s( LDAP *ld, char *dn );
8faf5a
c438e5 /*
de4bf9 ·* in error.c:
6d495d ·*/
3624d1 LDAPFUNCDECL int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit );
dea867 LDAPFUNCDECL char *ldap_err2string( int err );
13f3dc LDAPFUNCDECL void ldap_perror( LDAP *ld, char *s );
6caf5a
5738e5 /*
2063f1 ·* in modify.c:
00495d ·*/
abab82 LDAPFUNCDECL int ldap_modify( LDAP *ld, char *dn, LDAPMod **mods );
3de051 LDAPFUNCDECL int ldap_modify_s( LDAP *ld, char *dn, LDAPMod **mods );
30af5a
bb38e5 /*
202c70 ·* in modrdn.c:
65495d ·*/
37e633 LDAPFUNCDECL int ldap_modrdn( LDAP *ld, char *dn, char *newrdn );
426ae1 LDAPFUNCDECL int ldap_modrdn_s( LDAP *ld, char *dn, char *newrdn );
d68282 LDAPFUNCDECL int ldap_modrdn2( LDAP *ld, char *dn, char *newrdn,
3ea4b4 ¤   int deleteoldrdn );
016b66 LDAPFUNCDECL int ldap_modrdn2_s( LDAP *ld, char *dn, char *newrdn,
43ac8e ¤   int deleteoldrdn);
f9af5a
8e38e5 /*
fe7fd9 ·* in open.c:
a0495d ·*/
320137 LDAPFUNCDECL LDAP *ldap_open( char *host, int port );
fc3c5b LDAPFUNCDECL LDAP *ldap_init( char *defhost, int defport );
f4af5a
9f38e5 /*
c4fff7 ·* in getentry.c:
2a495d ·*/
bab93e LDAPFUNCDECL LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *chain );
bf20fa LDAPFUNCDECL LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
812eff LDAPFUNCDECL int ldap_count_entries( LDAP *ld, LDAPMessage *chain );
67af5a
6338e5 /*
e12f35 ·* in addentry.c
f2495d ·*/
11224a LDAPFUNCDECL LDAPMessage *ldap_delete_result_entry( LDAPMessage **list,
2fdcbc ¤   LDAPMessage *e );
b6fc65 LDAPFUNCDECL void ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e );
7daf5a
e038e5 /*
55f66d ·* in getdn.c
34495d ·*/
e4724e LDAPFUNCDECL char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );
69b024 LDAPFUNCDECL char *ldap_dn2ufn( char *dn );
77bbe0 LDAPFUNCDECL char **ldap_explode_dn( char *dn, int notypes );
e96707 LDAPFUNCDECL char **ldap_explode_dns( char *dn );
7fe625 LDAPFUNCDECL int ldap_is_dns_dn( char *dn );
caaf5a
1b38e5 /*
7cba64 ·* in getattr.c
85495d ·*/
b83777 LDAPFUNCDECL char *ldap_first_attribute( LDAP *ld, LDAPMessage *entry,
f7dde1 ¤   BerElement **ber );
571820 LDAPFUNCDECL char *ldap_next_attribute( LDAP *ld, LDAPMessage *entry,
ca4393 ¤   BerElement *ber );
ffaf5a
8938e5 /*
9d702d ·* in getvalues.c
11495d ·*/
--a2a6 000d4c96ae94010007c Page 3 of proto-ldap.h
c10235 LDAPFUNCDECL char **ldap_get_values( LDAP *ld, LDAPMessage *entry,·
0df364 ¤   char *target );
3f4727 LDAPFUNCDECL struct berval **ldap_get_values_len( LDAP *ld, LDAPMessage *entry,
b7f364 ¤   char *target );
de134f LDAPFUNCDECL int ldap_count_values( char **vals );
44bad7 LDAPFUNCDECL int ldap_count_values_len( struct berval **vals );
b7816c LDAPFUNCDECL void ldap_value_free( char **vals );
84b823 LDAPFUNCDECL void ldap_value_free_len( struct berval **vals );
1baf5a
6638e5 /*
8e6e10 ·* in result.c:
a6495d ·*/
c5a37f LDAPFUNCDECL int ldap_result( LDAP *ld, int msgid, int all,
870e4d ¤   struct timeval *timeout, LDAPMessage **result );
53922d LDAPFUNCDECL int ldap_msgfree( LDAPMessage *lm );
20be12 LDAPFUNCDECL int ldap_msgdelete( LDAP *ld, int msgid );
c8af5a
6838e5 /*
862bc1 ·* in search.c:
b0495d ·*/
fb108a LDAPFUNCDECL int ldap_search( LDAP *ld, char *base, int scope, char *filter,
75149c ¤   char **attrs, int attrsonly );
af40de LDAPFUNCDECL int ldap_search_s( LDAP *ld, char *base, int scope, char *filter,
feb93a ¤   char **attrs, int attrsonly, LDAPMessage **res );
84d4fd LDAPFUNCDECL int ldap_search_st( LDAP *ld, char *base, int scope, char *filter,
07780b ····char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res );
a4af5a
e438e5 /*
3d6729 ·* in ufn.c
87495d ·*/
25d49f LDAPFUNCDECL int ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs,
77a58e ¤   int attrsonly, LDAPMessage **res, int (*cancelproc)( void *cl ),
54c609 ¤   void *cancelparm );
952169 LDAPFUNCDECL int ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs,
37a58e ¤   int attrsonly, LDAPMessage **res, int (*cancelproc)( void *cl ),
4f3641 ¤   void *cancelparm, char *tag1, char *tag2, char *tag3 );
0028b5 LDAPFUNCDECL int ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs,
02fa12 ¤   int attrsonly, LDAPMessage **res );
e9212f LDAPFUNCDECL LDAPFiltDesc *ldap_ufn_setfilter( LDAP *ld, char *fname );
f502ce LDAPFUNCDECL void ldap_ufn_setprefix( LDAP *ld, char *prefix );
18e92b LDAPFUNCDECL int ldap_ufn_timeout( void *tvparam );
c9af5a
d5af5a
9d38e5 /*
9f8dcb ·* in unbind.c
dc495d ·*/
e4a686 LDAPFUNCDECL int ldap_unbind( LDAP *ld );
db1f58 LDAPFUNCDECL int ldap_unbind_s( LDAP *ld );
51af5a
d7af5a
3d38e5 /*
7fba95 ·* in getfilter.c
23495d ·*/
d71fcd LDAPFUNCDECL LDAPFiltDesc *ldap_init_getfilter( char *fname );
f68a14 LDAPFUNCDECL LDAPFiltDesc *ldap_init_getfilter_buf( char *buf, long buflen );
00257d LDAPFUNCDECL LDAPFiltInfo *ldap_getfirstfilter( LDAPFiltDesc *lfdp,·
ecd447 ¤   char *tagpat, char *value );
900d39 LDAPFUNCDECL LDAPFiltInfo *ldap_getnextfilter( LDAPFiltDesc *lfdp );
cfa11a LDAPFUNCDECL void ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix,·
576357 ¤   char *suffix );
1a3061 LDAPFUNCDECL void ldap_build_filter( char *buf, unsigned long buflen,
50802c ¤   char *pattern, char *prefix, char *suffix, char *attr,
870316 ¤   char *value, char **valwords );
21af5a
c538e5 /*
1e864f ·* in free.c
fb495d ·*/
471369 LDAPFUNCDECL void ldap_getfilter_free( LDAPFiltDesc *lfdp );
28fc13 LDAPFUNCDECL void ldap_mods_free( LDAPMod **mods, int freemods );
0daf5a
2f38e5 /*
d42fc9 ·* in friendly.c
--b7df 000ec7cbd234010007c Page 4 of proto-ldap.h
47495d ·*/
2201cc LDAPFUNCDECL char *ldap_friendly_name( char *filename, char *uname,
52cfd5 ¤   FriendlyMap **map );
5353f7 LDAPFUNCDECL void ldap_free_friendlymap( FriendlyMap **map );
47af5a
71af5a
bf38e5 /*
c3a88d ·* in cldap.c
51495d ·*/
7d9204 LDAPFUNCDECL LDAP *cldap_open( char *host, int port );
e1c30a LDAPFUNCDECL void cldap_close( LDAP *ld );
6faf15 LDAPFUNCDECL int cldap_search_s( LDAP *ld, char *base, int scope, char *filter,
02963f ¤   char **attrs, int attrsonly, LDAPMessage **res, char *logdn );
ddfdeb LDAPFUNCDECL void cldap_setretryinfo( LDAP *ld, int tries, int timeout );
2aaf5a
a2af5a
ff38e5 /*
c9efcc ·* in sort.c
12495d ·*/
9d6f89 LDAPFUNCDECL int ldap_sort_entries( LDAP *ld, LDAPMessage **chain, char *attr,
642b3f ¤   int (*cmp)(const void *a, const void *b) );
24e1ba LDAPFUNCDECL int ldap_sort_values( LDAP *ld, char **vals,·
e92b3f ¤   int (*cmp)(const void *a, const void *b) );
94798a LDAPFUNCDECL int ldap_sort_strcasecmp( const char **a, const char **b );
8aaf5a
afaf5a
8938e5 /*
7ec70f ·* in url.c
32495d ·*/
fb2105 LDAPFUNCDECL int ldap_is_ldap_url( char *url );
068241 LDAPFUNCDECL int ldap_url_parse( char *url, LDAPURLDesc **ludpp );
155b03 LDAPFUNCDECL void ldap_free_urldesc( LDAPURLDesc *ludp );
ba2bc8 LDAPFUNCDECL int ldap_url_search( LDAP *ld, char *url, int attrsonly );
cb5c8b LDAPFUNCDECL int ldap_url_search_s( LDAP *ld, char *url, int attrsonly,
78d1e2 ¤   LDAPMessage **res );
830f17 LDAPFUNCDECL int ldap_url_search_st( LDAP *ld, char *url, int attrsonly,
c13022 ¤   struct timeval *timeout, LDAPMessage **res );
dfaf5a
70af5a
8238e5 /*
9d3edb ·* in charset.c
bf495d ·*/
55f52a #ifdef STR_TRANSLATION
094188 LDAPFUNCDECL void ldap_set_string_translators( LDAP *ld,
a5d4e3 ¤   BERTranslateProc encode_proc, BERTranslateProc decode_proc );
0d9050 LDAPFUNCDECL int ldap_translate_from_t61( LDAP *ld, char **bufp,
8723d8 ¤   unsigned long *lenp, int free_input );
f67f96 LDAPFUNCDECL int ldap_translate_to_t61( LDAP *ld, char **bufp,
af23d8 ¤   unsigned long *lenp, int free_input );
ca66fa LDAPFUNCDECL void ldap_enable_translation( LDAP *ld, LDAPMessage *entry,
252c91 ¤   int enable );
1eaf5a
488068 #ifdef LDAP_CHARSET_8859
3c53af LDAPFUNCDECL int ldap_t61_to_8859( char **bufp, unsigned long *buflenp,
a69dfb ¤   int free_input );
4123e3 LDAPFUNCDECL int ldap_8859_to_t61( char **bufp, unsigned long *buflenp,
779dfb ¤   int free_input );
cb7911 #endif /* LDAP_CHARSET_8859 */
603dd6 #endif /* STR_TRANSLATION */
66af5a
59af5a
13a184 #ifdef WINSOCK
5e38e5 /*
2cf7ee ·* in msdos/winsock/wsa.c
5e495d ·*/
eccbe3 LDAPFUNCDECL void ldap_memfree( void *p );
e2d50d #endif /* WINSOCK */
33af5a
50c583 #ifdef MACOS
7b40c0 void¤   pgp_ldap_free(void *ptr);
1f7454 #endif
ecaf5a
--f192 001dda6b2a44010007c Page 5 of proto-ldap.h
f03379 #ifdef __cplusplus
45efe6 }
dd7454 #endif
--c70c 001aa29be494010007d Page 1 of regex.h
78d472 #if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || \
18b8f3 ····defined( NEED_BSDREGEX )
a838e5 /*
2f5ef8 ·* Copyright (c) 1993 Regents of the University of Michigan.
01599a ·* All rights reserved.
57775e ·*
c7b855 ·* Redistribution and use in source and binary forms are permitted
4e9795 ·* provided that this notice is preserved and that due credit is given
dd1873 ·* to the University of Michigan at Ann Arbor. The name of the University
ee8805 ·* may not be used to endorse or promote products derived from this
4a74fe ·* software without specific prior written permission. This software
c12a32 ·* is provided ``as is'' without express or implied warranty.
b4495d ·*/
6c38e5 /*
393fb7 ·* regex.h -- includes for regular expression matching routines
2f3eb9 ·* 13 August 1993 Mark C Smith
9d495d ·*/
78af5a
af3379 #ifdef __cplusplus
156dad extern "C" {
bc7454 #endif
19af5a
89e9c2 #if !defined( NEEDPROTOS ) && defined( __STDC__ )
e7be03 #define NEEDPROTOS
dc7454 #endif
69af5a
10504c #ifdef NEEDPROTOS
5b34b0 char *re_comp( char *pat );
e7b3cc int re_exec( char *lp );
35ec10 void re_modw( char *s );
6e6616 int re_subs( char *src, char *dst );
f86133 #else /* NEEDPROTOS */
241ac4 char *re_comp();
d5cefd int re_exec();
fdde89 void re_modw();
9f0eea int re_subs();
3d8634 #endif /* NEEDPROTOS */
deaf5a
16a674 #define re_fail( m, p )
42af5a
783379 #ifdef __cplusplus
81efe6 }
867454 #endif
aada28 #endif /* MACOS or DOS or NEED_BSDREGEX */
--2f36 0007b4a4dc74010007e Page 1 of srchpref.h
bc38e5 /*
09515b ·* Copyright (c) 1993, 1994 Regents of the University of Michigan.
60599a ·* All rights reserved.
44775e ·*
22b855 ·* Redistribution and use in source and binary forms are permitted
ec9795 ·* provided that this notice is preserved and that due credit is given
bf1873 ·* to the University of Michigan at Ann Arbor. The name of the University
148805 ·* may not be used to endorse or promote products derived from this
b974fe ·* software without specific prior written permission. This software
1a2a32 ·* is provided ``as is'' without express or implied warranty.
a0775e ·*
59cef5 ·* searchpref.h: ·display template library defines
8317b3 ·* 16 May 1994 by Gordon Good
06495d ·*/
77af5a
d9af5a
9ddf00 #ifndef _SRCHPREF_H
42d687 #define _SRCHPREF_H
3caf5a
183379 #ifdef __cplusplus
fd6dad extern "C" {
2e7454 #endif
1eaf5a
9aaf5a
b86bf6 struct ldap_searchattr {
6c2140 ¤   char¤   ¤   ¤   ¤   *sa_attrlabel;
8bcc16 ¤   char¤   ¤   ¤   ¤   *sa_attr;
9516df ¤   ¤   ¤   ¤   ¤   /* max 32 matchtypes for now */
5abbbe ¤   unsigned long¤  ¤   ¤   sa_matchtypebitmap;
17270f ¤   char¤   ¤   ¤   ¤   *sa_selectattr;
9c8fd1 ¤   char¤   ¤   ¤   ¤   *sa_selecttext;
c59c97 ¤   struct ldap_searchattr¤ ¤   *sa_next;
7782f7 };
bdaf5a
034cb2 struct ldap_searchmatch {
9796e4 ¤   char¤   ¤   ¤   ¤   *sm_matchprompt;
ce8b72 ¤   char¤   ¤   ¤   ¤   *sm_filter;
c17f9d ¤   struct ldap_searchmatch¤¤   *sm_next;
f782f7 };
00af5a
9e0871 struct ldap_searchobj {
3de45d ¤   char¤   ¤   ¤   ¤   *so_objtypeprompt;
4e0ae3 ¤   unsigned long¤  ¤   ¤   so_options;
d7c4c8 ¤   char¤   ¤   ¤   ¤   *so_prompt;
61bcad ¤   short¤  ¤   ¤   ¤   so_defaultscope;
89cb32 ¤   char¤   ¤   ¤   ¤   *so_filterprefix;
f9d069 ¤   char¤   ¤   ¤   ¤   *so_filtertag;
5793f6 ¤   char¤   ¤   ¤   ¤   *so_defaultselectattr;
cd3b28 ¤   char¤   ¤   ¤   ¤   *so_defaultselecttext;
6c014c ¤   struct ldap_searchattr¤ ¤   *so_salist;
984186 ¤   struct ldap_searchmatch¤¤   *so_smlist;
a1b19e ¤   struct ldap_searchobj¤  ¤   *so_next;
b882f7 };
c3af5a
50fca5 #define NULLSEARCHOBJ¤  ¤   ¤   ((struct ldap_searchobj *)0)
2daf5a
2638e5 /*
e8d215 ·* global search object options
08495d ·*/
a1c549 #define LDAP_SEARCHOBJ_OPT_INTERNAL¤0x00000001
adaf5a
376a0e #define LDAP_IS_SEARCHOBJ_OPTION_SET( so, option )¤ \
4086d8 ¤   (((so)->so_options & option ) != 0 )
15af5a
8d4eca #define LDAP_SEARCHPREF_VERSION_ZERO¤   0
371b92 #define LDAP_SEARCHPREF_VERSION¤¤   1
a4af5a
e36152 #define LDAP_SEARCHPREF_ERR_VERSION¤1
551a03 #define LDAP_SEARCHPREF_ERR_MEM¤¤   2
15748d #define LDAP_SEARCHPREF_ERR_SYNTAX¤ 3
fb2f4e #define LDAP_SEARCHPREF_ERR_FILE¤   4
7baf5a
--b41f 001309ccf114010007e Page 2 of srchpref.h
e0af5a
45719a #ifndef NEEDPROTOS
6d61a0 int¤¤   ¤   ldap_init_searchprefs();
3ebd51 int¤¤   ¤   ldap_init_searchprefs_buf();
8daab8 void¤   ¤   ¤   ldap_free_searchprefs();
fc3219 struct ldap_searchobj¤  *ldap_first_searchobj();
1bea01 struct ldap_searchobj¤  *ldap_next_searchobj();
63af5a
8b4b51 #else /* !NEEDPROTOS */
fbaf5a
5b5c8b LDAPFUNCDECL int
e5282a ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp );
95af5a
cd5c8b LDAPFUNCDECL int
4778c2 ldap_init_searchprefs_buf( char *buf, long buflen,
207e5b ¤   struct ldap_searchobj **solistp );
7aaf5a
b3d275 LDAPFUNCDECL void
d3d5da ldap_free_searchprefs( struct ldap_searchobj *solist );
b7af5a
2cb6b2 LDAPFUNCDECL struct ldap_searchobj *
5d35a9 ldap_first_searchobj( struct ldap_searchobj *solist );
5aaf5a
42b6b2 LDAPFUNCDECL struct ldap_searchobj *
c34deb ldap_next_searchobj( struct ldap_searchobj *sollist,
b26b38 ¤   struct ldap_searchobj *so );
7faf5a
1a3f09 #endif /* !NEEDPROTOS */
95af5a
0daf5a
603379 #ifdef __cplusplus
33efe6 }
6c7454 #endif
30a4e2 #endif /* _SRCHPREF_H */
--a48f 000da69af4e4010007f Page 1 of sysexits-compat.h
bc38e5 /*
ff3548 ·* Copyright (c) 1987 Regents of the University of California.
fb599a ·* All rights reserved.
94775e ·*
8fb855 ·* Redistribution and use in source and binary forms are permitted
dcfa34 ·* provided that the above copyright notice and this paragraph are
61abf3 ·* duplicated in all such forms and that any documentation,
7e6592 ·* advertising materials, and other materials related to such
43bd9c ·* distribution and use acknowledge that the software was developed
b4cbe1 ·* by the University of California, Berkeley. ·The name of the
902709 ·* University may not be used to endorse or promote products derived
467889 ·* from this software without specific prior written permission.
5422a1 ·* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2ccecc ·* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
4962d7 ·* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
ad775e ·*
aa8c13 ·*¤ @(#)sysexits.h¤ 4.5 (Berkeley) 7/6/88
0b495d ·*/
67af5a
4138e5 /*
c6fa12 ** ·SYSEXITS.H -- Exit status codes for system programs.
8e0158 **
2bbe39 **¤ This include file attempts to categorize possible error
415260 **¤ exit statuses for system programs, notably delivermail
457011 **¤ and the Berkeley network.
b20158 **
0f7561 **¤ Error numbers begin at EX__BASE to reduce the possibility of
63da25 **¤ clashing with other exit statuses that random programs may
33875d **¤ already return. ·The meaning of the codes is approximately
3b2a89 **¤ as follows:
1b0158 **
bc06e6 **¤ EX_USAGE -- The command was used incorrectly, e.g., with
ab99eb **¤ ¤   the wrong number of arguments, a bad flag, a bad
00edc7 **¤ ¤   syntax in a parameter, or whatever.
c1a013 **¤ EX_DATAERR -- The input data was incorrect in some way.
c23d4a **¤ ¤   This should only be used for user's data & not
396861 **¤ ¤   system files.
e7e547 **¤ EX_NOINPUT -- An input file (not a system file) did not
40cc2e **¤ ¤   exist or was not readable. ·This could also include
81eb49 **¤ ¤   errors like "No message" to a mailer (if it cared
ac7167 **¤ ¤   to catch it).
e5f976 **¤ EX_NOUSER -- The user specified did not exist. ·This might
1c6cd0 **¤ ¤   be used for mail addresses or remote logins.
13793c **¤ EX_NOHOST -- The host specified did not exist. ·This is used
6c995b **¤ ¤   in mail addresses or network requests.
cb9d6e **¤ EX_UNAVAILABLE -- A service is unavailable. ·This can occur
e4f271 **¤ ¤   if a support program or file does not exist. ·This
3d8ab8 **¤ ¤   can also be used as a catchall message when something
a8a7f8 **¤ ¤   you wanted to do doesn't work, but you don't know
913db0 **¤ ¤   why.
ea24ad **¤ EX_SOFTWARE -- An internal software error has been detected.
098243 **¤ ¤   This should be limited to non-operating system related
9b179e **¤ ¤   errors as possible.
210401 **¤ EX_OSERR -- An operating system error has been detected.
ae9003 **¤ ¤   This is intended to be used for such things as "cannot
2a33d7 **¤ ¤   fork", "cannot create pipe", or the like. ·It includes
008eaa **¤ ¤   things like getuid returning a user that does not
dc6c2b **¤ ¤   exist in the passwd file.
6cdc09 **¤ EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
dcbeee **¤ ¤   etc.) does not exist, cannot be opened, or has some
548807 **¤ ¤   sort of error (e.g., syntax error).
146153 **¤ EX_CANTCREAT -- A (user specified) output file cannot be
eb6d31 **¤ ¤   created.
5af51e **¤ EX_IOERR -- An error occurred while doing I/O on some file.
1b0c5a **¤ EX_TEMPFAIL -- temporary failure, indicating something that
72a8a4 **¤ ¤   is not really an error. ·In sendmail, this means
7ec4d3 **¤ ¤   that a mailer (e.g.) could not create a connection,
a9d17e **¤ ¤   and the request should be reattempted later.
a095d4 **¤ EX_PROTOCOL -- the remote system returned something that
e0fc31 **¤ ¤   was "not possible" during a protocol exchange.
865536 **¤ EX_NOPERM -- You did not have sufficient permission to
da485f **¤ ¤   perform the operation. ·This is not intended for
--8f6a 001eb0fc8004010007f Page 2 of sysexits-compat.h
c0f52f **¤ ¤   file system problems, which should use NOINPUT or
2e3b41 **¤ ¤   CANTCREAT, but rather for higher level permissions.
02be2e **¤ ¤   For example, kre uses this to restrict who students
d03e8a **¤ ¤   can send mail to.
ca0158 **
19eaf9 **¤ Maintained by Eric Allman (eric@berkeley, ucbvax!eric) --
7ca086 **¤ ¤   please mail changes to me.
ba0158 **
acfbb2 **¤ ¤   ¤   @(#)sysexits.h¤ 4.5¤¤   7/6/88
fa7fe0 */
31af5a
9e4506 # define EX_OK¤ ¤   0¤  /* successful termination */
87af5a
228aba # define EX__BASE¤  64¤ /* base value for error messages */
56af5a
f13567 # define EX_USAGE¤  64¤ /* command line usage error */
64ecc3 # define EX_DATAERR¤65¤ /* data format error */
778c5a # define EX_NOINPUT¤66¤ /* cannot open input */
2b360c # define EX_NOUSER¤ 67¤ /* addressee unknown */
3a31fc # define EX_NOHOST¤ 68¤ /* host name unknown */
843b19 # define EX_UNAVAILABLE¤69¤ /* service unavailable */
75a495 # define EX_SOFTWARE¤   70¤ /* internal software error */
2c4a3e # define EX_OSERR¤  71¤ /* system error (e.g., can't fork) */
2270b0 # define EX_OSFILE¤ 72¤ /* critical OS file missing */
43b308 # define EX_CANTCREAT¤  73¤ /* can't create (user) output file */
885319 # define EX_IOERR¤  74¤ /* input/output error */
f8f09d # define EX_TEMPFAIL¤   75¤ /* temp failure; user is invited to retry */
0cedba # define EX_PROTOCOL¤   76¤ /* remote error in protocol */
d1f343 # define EX_NOPERM¤ 77¤ /* permission denied */
eb5406 # define EX_CONFIG¤ 78¤ /* configuration error */
--0489 000c8eab79840100080 Page 1 of Make-template
54b0af #-----------------------------------------------------------------------------
1ab062 # Copyright (c) 1990 Regents of the University of Michigan.
445a50 # All rights reserved.
e6a601 #
d597d6 # Redistribution and use in source and binary forms are permitted
bbd6ca # provided that this notice is preserved and that due credit is given
1b8ee9 # to the University of Michigan at Ann Arbor. The name of the University
e23eb9 # may not be used to endorse or promote products derived from this
fb0baf # software without specific prior written permission. This software
bffeea # is provided ``as is'' without express or implied warranty.
77a601 #
47f7cb # ······lightweight ber library makefile
44a601 #
59b0af #-----------------------------------------------------------------------------
8faf5a
b83699 LDAPSRC¤= ..
cd8498 PGPLIBS = ../../..
637e36 OUTDIR ·= $(LDAPSRC)/unix
d3b5ca PGPCDKDIR = $(PGPLIBS)/pgpcdk
6336cd PGPPFLDIR = $(LDAPSRC)/../../pfl
22d3d9 PGPCDKINCLUDES = -I$(PGPCDKDIR)/pub/include -I$(PGPCDKDIR)/unix
bc6640 PGPPFLINCLUDES = -I$(PGPPFLDIR)/common -I$(PGPPFLDIR)/unix
2daf5a
73df23 SRCS¤   = decode.c encode.c io.c bprint.c·
5c8e2e OBJS¤   = decode.o encode.o io.o bprint.o
01af5a
0ab085 HDIR¤   = -I$(LDAPSRC)/include -I$(LDAPSRC)/pgpsockets
17af5a
af545b INCLUDES= $(HDIR) $(PGPCDKINCLUDES) $(PGPPFLINCLUDES)
04a5ca DEFINES¤= $(DEFS)
33e6b4 CFLAGS¤ = $(INCLUDES) $(DEFINES) $(ACFLAGS)
cdaf5a
029a94 all:¤   $(OUTDIR)/liblber.a DONE
b4af5a
1a3fb0 $(OUTDIR)/liblber.a: $(OBJS)
c5d59c ¤   $(AR) ruv $@ $(OBJS)
c8d81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
18f7c7 ¤   ¤   $(RANLIB) $@; \
b35bc3 ¤   fi;
08af5a
c0da15 DONE:
74c786 ¤   @set -x; echo $(OBJS) > $@
95af5a
dbc51a idtest:¤idtest.o
4c0903 ¤   $(CC) $(ALDFLAGS) -o $@ idtest.c $(ISODEINCLUDEFLAG) \
ae0d44 ¤   ¤   $(KRBINCLUDEFLAG) $(ISODELIBFLAG) $(ISODELIBS) \
d7a0a7 ¤   ¤   $(KRBLIBLFAG) $(KRBLIBS) $(ALIBS)
fdaf5a
548deb etest:¤ liblber.a etest.o
745563 ¤   $(CC) $(ALDFLAGS) -o $@ etest.o ./liblber.a $(ALIBS)
c4af5a
41c104 dtest:¤ liblber.a dtest.o
2aac52 ¤   $(CC) $(ALDFLAGS) -o $@ dtest.o ./liblber.a $(ALIBS)
7caf5a
7ac0c8 version.c: $(OBJS)
0e1613 ¤   $(RM) $@
4ac04d ¤   (u=$${USER-root} v=`$(CAT) ../../build/version` d=`$(PWD)` \
369489 ¤   h=`$(HOSTNAME)` t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
97a7ef ¤   -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
6ed31b ¤   -e "s|%VERSION%|$${v}|" \
335a66 ¤   < Version.c > $@)
6caf5a
3bf8c1 install:¤   liblber.a FORCE
034251 ¤   -$(MKDIR) -p $(LIBDIR)
58b5f8 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 liblber.a $(LIBDIR)
19d81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
6b9576 ¤   ¤   (cd /tmp; $(RANLIB) $(LIBDIR)/liblber.a) \
8c2ec9 ¤   fi
deaf5a
cac0ab lint:¤  FORCE
3d84b1 ¤   $(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
c8af5a
--5b18 0017ed6ef5d40100080 Page 2 of Make-template
d4defc 5lint:¤ FORCE
de022c ¤   $(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
e8af5a
e4b5ca clean:¤ FORCE
1a8938 ¤   $(RM) $(OUTDIR)/liblber.a *.o core a.out version.c dtest etest idtest
88af5a
f5adf8 depend:¤FORCE
eed1f9 ¤   $(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
76af5a
1ea513 links:
12da7f ¤   @$(LN) .src/ldap* .src/*.[ch] .
3caf5a
b8a8d3 # DO NOT DELETE THIS LINE -- mkdep uses it.
dc3c8b # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
9faf5a
a3dcc0 decode.o: decode.c
58012c encode.o: encode.c ../include/proto-lber.h
59d739 io.o: io.c ../include/proto-lber.h
ed6216 bprint.o: bprint.c ../include/proto-lber.h
6daf5a
7ef6c8 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
--2194 000cd97666340100081 Page 1 of Makefile
2539de # --------------------------------------------------------
324229 # ·This file was automatically generated. ·Do not edit it.
c0e6af # ·Instead, edit the Make-common file (located in the root
eef11f # ·(of the LDAP distribution). ·See the LDAP INSTALL file
a05811 # ·for more information.
ee39de # --------------------------------------------------------
05a601 #
2db0af #-----------------------------------------------------------------------------
10b062 # Copyright (c) 1990 Regents of the University of Michigan.
885a50 # All rights reserved.
52a601 #
a297d6 # Redistribution and use in source and binary forms are permitted
14d6ca # provided that this notice is preserved and that due credit is given
628ee9 # to the University of Michigan at Ann Arbor. The name of the University
443eb9 # may not be used to endorse or promote products derived from this
0e0baf # software without specific prior written permission. This software
eafeea # is provided ``as is'' without express or implied warranty.
aba601 #
2af7cb # ······lightweight ber library makefile
c4a601 #
ccb0af #-----------------------------------------------------------------------------
e7af5a
8b3699 LDAPSRC¤= ..
0d7e36 OUTDIR ·= $(LDAPSRC)/unix
5036cd PGPPFLDIR = $(LDAPSRC)/../../pfl
4f6640 PGPPFLINCLUDES = -I$(PGPPFLDIR)/common -I$(PGPPFLDIR)/unix
efaf5a
59882d SRCS¤   = decode.c encode.c io.c bprint.c
bdedbe OBJS¤   = decode.o encode.o io.o bprint.o·
2faf5a
5b9767 HDIR¤   = $(LDAPSRC)/include
95af5a
b2b228 INCLUDES= -I$(HDIR) $(PGPPFLINCLUDES)
08a5ca DEFINES¤= $(DEFS)
cae6b4 CFLAGS¤ = $(INCLUDES) $(DEFINES) $(ACFLAGS)
fdaf5a
879a94 all:¤   $(OUTDIR)/liblber.a DONE
d6af5a
743fb0 $(OUTDIR)/liblber.a: $(OBJS)
dbd59c ¤   $(AR) ruv $@ $(OBJS)
b1d81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
63f7c7 ¤   ¤   $(RANLIB) $@; \
f55bc3 ¤   fi;
b4af5a
5eda15 DONE:
03c786 ¤   @set -x; echo $(OBJS) > $@
51af5a
f5c51a idtest:¤idtest.o
df0903 ¤   $(CC) $(ALDFLAGS) -o $@ idtest.c $(ISODEINCLUDEFLAG) \
c50d44 ¤   ¤   $(KRBINCLUDEFLAG) $(ISODELIBFLAG) $(ISODELIBS) \
97a0a7 ¤   ¤   $(KRBLIBLFAG) $(KRBLIBS) $(ALIBS)
30af5a
878deb etest:¤ liblber.a etest.o
755563 ¤   $(CC) $(ALDFLAGS) -o $@ etest.o ./liblber.a $(ALIBS)
12af5a
b9c104 dtest:¤ liblber.a dtest.o
dbac52 ¤   $(CC) $(ALDFLAGS) -o $@ dtest.o ./liblber.a $(ALIBS)
bcaf5a
42c0c8 version.c: $(OBJS)
7c1613 ¤   $(RM) $@
c9c04d ¤   (u=$${USER-root} v=`$(CAT) ../../build/version` d=`$(PWD)` \
6a9489 ¤   h=`$(HOSTNAME)` t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
7da7ef ¤   -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
d1d31b ¤   -e "s|%VERSION%|$${v}|" \
8c5a66 ¤   < Version.c > $@)
4caf5a
01f8c1 install:¤   liblber.a FORCE
a54251 ¤   -$(MKDIR) -p $(LIBDIR)
c3b5f8 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 liblber.a $(LIBDIR)
5ad81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
f89576 ¤   ¤   (cd /tmp; $(RANLIB) $(LIBDIR)/liblber.a) \
cd2ec9 ¤   fi
--656e 0001bf90b6740100081 Page 2 of Makefile
e0af5a
4ac0ab lint:¤  FORCE
8584b1 ¤   $(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
e0af5a
32defc 5lint:¤ FORCE
b3022c ¤   $(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
18af5a
84b5ca clean:¤ FORCE
738938 ¤   $(RM) $(OUTDIR)/liblber.a *.o core a.out version.c dtest etest idtest
0daf5a
dfadf8 depend:¤FORCE
1fd1f9 ¤   $(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
afaf5a
f5a513 links:
65da7f ¤   @$(LN) .src/ldap* .src/*.[ch] .
dbaf5a
13a8d3 # DO NOT DELETE THIS LINE -- mkdep uses it.
b33c8b # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
f8af5a
03b8a4 decode.o: decode.c ../include/lber.h
70e359 encode.o: encode.c ../include/lber.h
bddec7 io.o: io.c ../include/lber.h
1f0545 bprint.o: bprint.c ../include/lber.h
66af5a
b6f6c8 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
38a601 #
e4ffdb # Do NOT edit this file -- it is automatically appended to all Makefiles
c369dc # except the LDAP top-level Makefile. See the LDAP INSTALL file for more
a11fc7 # information.
c4a601 #
74b0af #-----------------------------------------------------------------------------
8ddb1c # Copyright (c) 1994 Regents of the University of Michigan.
4f5a50 # All rights reserved.
8fa601 #
e197d6 # Redistribution and use in source and binary forms are permitted
abd6ca # provided that this notice is preserved and that due credit is given
aa8ee9 # to the University of Michigan at Ann Arbor. The name of the University
ac3eb9 # may not be used to endorse or promote products derived from this
2b0baf # software without specific prior written permission. This software
8bfeea # is provided ``as is'' without express or implied warranty.
c7a601 #
543287 # ······LDAP standard Make defines (appended to all but top-level Makefile)
afa601 #
afb0af #-----------------------------------------------------------------------------
5caf5a
cbad9f # DEFS are included in CFLAGS
f6d084 DEFS¤   = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
ba0785 ¤   ¤   $(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
2ff00e ¤   ¤   $(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
4e997b ¤   ¤   $(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
2187f1 ¤   ¤   $(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
f3af5a
ee40cd # SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
5cb18b SERVERDEFS¤ = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
0c14ba ¤   ¤   ¤   $(NO_SETPROCTITLE) $(PEPSY_DUMP)
0eaf5a
30a601 #
c80ce2 # ISODELIBS are used in server/ldapd builds
e7a601 #
0a4e01 ISODELIBS¤  = $(ISODEBASELIBS) -lm $(ISODETURBOLIBS)
e1af5a
d40558 # ACFLAGS are added to CFLAGS but not passed to mkdep, lint, etc
3f17ce ACFLAGS¤¤   = $(EXTRACFLAGS) $(UNPROTOCFLAGS)
c1af5a
5a2eb4 # ALDFLAGS are always placed near the beginning of all linker (cc -o) commands
cd49dd ALDFLAGS¤   = $(EXTRALDFLAGS) $(PLATFORMLDFLAGS)
61af5a
9c233d # ALIBS are always placed at the end of all linker (cc -o) commands
bd1ec7 ALIBS¤  ¤   = $(PLATFORMLIBS) $(THREADSLIB) -lstdc++
ecaf5a
02a601 #
1bc229 # default definitions for Unix utilities (may be over-ridden in Make-platform)
--932e 000ca79ffb740100081 Page 3 of Makefile
e9fd75 CC¤ = cc
4f7e42 MAKE¤   = make
d41a1a RANLIB¤ = ranlib
c185b9 AR¤ = ar
4dba00 RM¤ = rm -f
509865 MV¤ = mv -f
bc9324 CP¤ = cp
dc229f CHMOD¤  = chmod
7565eb CAT¤= cat
40d1bd LN¤ = ln -s
2041b6 HARDLN¤ = ln
c2c699 TAIL¤   = tail
f8e675 SED¤= sed
a901f7 LINT¤   = lint
253a04 5LINT¤  = lint
e2c291 MKDIR¤  = mkdir
a53f60 INSTALL¤= install
5c0106 INSTALLFLAGS = -c
37735e BASENAME= basename
9dd84e DIRNAME¤= dirname
57720b MKDEP¤  = $(LDAPSRC)/build/mkdep -c gcc -s -f Make-template
e5e392 PWD¤= pwd
c896d7 DATE¤   = date
36a7d0 HOSTNAME= hostname
07af5a
6caf5a
f1a601 #
ba592a # empty target used to force rules to be invoked
9fa601 #
742b40 FORCE:
ccaf5a
47a601 #
c9c8ac # LDAP SunOS5 GNU C Make-platform file
3da601 #
3caf5a
0ea601 #
11a68c # add any platform-specific overrides below here
c8a601 #
87af5a
feaf5a
00a601 #
5b95cf # -------------------------------------------------------------------------
c1ba80 # you will probably not need to edit anything below this point
ea95cf # -------------------------------------------------------------------------
6d4b2c CC¤ = gcc
21af5a
f81dfe # ranlib not needed under SunOS5
b37716 RANLIB¤ = ""
9baf5a
ce9a13 # give full path to hostname since it may not be in user's path
f5ea97 HOSTNAME=/usr/ucb/hostname
e3af5a
597720 # don't count on /usr/ucb/install being present or first in path
c610f3 INSTALL=$(LDAPSRC)/build/install.sh
11af5a
bceaf0 PLATFORMCFLAGS=¤-Dsunos5 -D_REENTRANT
3c8289 PLATFORMLIBS= -lsocket -lnsl -lgen
121dc2 THREADS= -DTHREAD_SUNOS5_LWP
1e7e25 THREADSLIB=-lthread
92b0af #-----------------------------------------------------------------------------
bb35f2 # Copyright (c) 1997 PGP inc.
285a50 # All rights reserved.
daa601 #
aeb0af #-----------------------------------------------------------------------------
3ddd01 #############################################################################
0fa917 ## Edit the following variables to have appropriate values for your system ##
badd01 #############################################################################
7baf5a
33515b vpath %.a $(OUTDIR):$(LDIR):$(PGPCDKDIR)/unix:$(DBLDIR):$(PGPPFLDIR) \
3bdc18 ¤   ··$(PGPCDKDIR)/priv/keyserver: \
c3aacf ¤   ··$(PGPCDKDIR)/../network/pgpsockets/unix/src
caaf5a
--ed14 0001bc14e1940100081 Page 4 of Makefile
7edd01 #############################################################################
c8736d ## LDAP install paths ·····················································##
64dd01 #############################################################################
c0a601 #
bac05e # by default, everything is installed below INSTROOT
a04f10 # servers, config files, etc. are put in ETCDIR
9e54a5 # include files get put in INCLUDEDIR
0e48e9 # libraries are put in LIBDIR
c3f935 # man pages are put under MANDIR
2ed9d9 # programs end-users will run are put in BINDIR
c4a601 #
e4b837 # Moved INSTROOT declaration to top-level Makefile
3d37ce # useful for automation.
c1af5a
218fed ETCDIR= $(INSTROOT)/etc
ef4bf1 INCLUDEDIR= $(INSTROOT)/include
564e47 LIBDIR= $(INSTROOT)/unix
6be906 MANDIR= $(INSTROOT)/doc
552d8f BINDIR= $(INSTROOT)/unix
84af5a
5ca601 #
33ca77 # if you want things to run in a different directory from where they
102c1a # are installed, set this accordingly (this path gets compiled into a
d68e97 # few binaries). otherwise, leave it alone.
e763ae RUNTIMEETCDIR= $(ETCDIR)
6eaf5a
87dd01 #############################################################################
807145 ## General compiler options ···············································##
aadd01 #############################################################################
a264cf # Passed to every compile (cc or gcc). ·This is where you put -O or -g, etc.
2dc073 # Added -D_REENTRANT per ldap doc. for Solaris builds <galileo>
fa7adf OPT=-g
92255c DEBUG=1
b3ab6e UNFINISHED=1
cded5a EXTRACFLAGS=-D_REENTRANT $(OPT) -fwritable-strings \
7f1d76 ············-DPGP_DEBUG=$(DEBUG) -DUNFINISHED_CODE_ALLOWED=$(UNFINISHED)
03af5a
34e6cd # Passed to every link (ld). ·Include -g here if you did in EXTRACFLAGS.
09af5a
9bb23e EXTRALDFLAGS=$(OPT)
6faf5a
a7dd01 #############################################################################
d1ce69 ## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ······##
f4b9e8 ## If you don't want to build it, you can skip this section. ··············##
d7dd01 #############################################################################
6ea601 #
b011c2 # To build the ldap server, uncomment the HAVEISODE line,
b55803 # and the section describing build settings for your version of isode.
60a601 #
9ea865 HAVEISODE = yes
39af5a
cfdd01 #############################################################################
f5c146 ## If you don't want to run slapd, skip this section. ·····················##
a8dd01 #############################################################################
c5a601 #
edac20 # To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
2f8e0c # line and select the SLAPD_BACKENDS you want to use. If you enable the
7b2d3b # LDBM backend, also select one of the LDBM backends.
e98fbf MAKESLAPD= yes
dba601 #
b54d71 # remove the defines for backends you don't want to enable
29743e SLAPD_BACKENDS= -DLDAP_LDBM
08a601 #
ee9374 # If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
33cee2 # to specify which low-level database package to use. ·There are
faf92f # four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
2ba601 #
0fa9bd # berkeley db btree package
da7e82 LDBMBACKEND=-DLDBM_USE_DBBTREE21
8bb496 LDBMINCLUDE=
6528ff LDBMLIB=-ldb
1bb402 # berkeley db hash package
--d0a5 0012a1dd62940100081 Page 5 of Makefile
e99bc9 #LDBMBACKEND=-DLDBM_USE_DBHASH
34d345 #LDBMINCLUDE=-I/usr/local/db/include
be0e7e #LDBMLIB=-ldb
2c2a77 # gnu dbm (gdbm)
26ed29 #LDBMBACKEND=-DLDBM_USE_GDBM
999187 #LDBMINCLUDE=-I$(INSTROOT)/servers/slapd/db
306c04 #LDBMLIB=-lgdbm
d51874 # standard unix ndbm
debc4d #LDBMBACKEND=-DLDBM_USE_NDBM
0aa601 #
c77ffd # if you want to use a non-default threads package change these lines
2b42ab #THREADS=-DNO_THREADS
838180 #THREADSLIB=
fdaf5a
77dd01 #############################################################################
171692 ## General options ························································##
6fdd01 #############################################################################
21c8ae # uncomment this line to enable debugging code (a good idea)
9275d8 LDAP_DEBUG=-DLDAP_DEBUG
6daf5a
77b923 # uncomment this line to turn on a few U of Michigan specific things
5b8cea #UOFM=-DUOFM
2caf5a
70bce0 # uncomment this line to delete a few printfs in the lber and ldap libraries.
17d6e3 #NO_USERINTERFACE=-DNO_USERINTERFACE
32af5a
eb2982 # uncomment this line to include Connectionless LDAP support
711910 #CLDAP=-DCLDAP
2baf5a
ff021f # uncomment this line to eliminate local caching support in the libldap
91decc #NO_CACHE=-DNO_CACHE
d5af5a
9b197d # uncomment this line to enable support for LDAP referrals in libldap
981c28 LDAP_REFERRALS=-DLDAP_REFERRALS
0aaf5a
144c1c # uncomment this line to use soundex for approximate matches in slapd.
6c856d # the default is to use the metaphone algorithm.
2a1fa8 #PHONETIC=-DSOUNDEX
--3db5 001be2743ee40100082 Page 1 of Version.c
bc38e5 /*
696b47 ·* Copyright (c) 1991 Regents of the University of Michigan.
44599a ·* All rights reserved.
da775e ·*
1ab855 ·* Redistribution and use in source and binary forms are permitted
f39795 ·* provided that this notice is preserved and that due credit is given
8d1873 ·* to the University of Michigan at Ann Arbor. The name of the University
168805 ·* may not be used to endorse or promote products derived from this
a774fe ·* software without specific prior written permission. This software
362a32 ·* is provided ``as is'' without express or implied warranty.
82495d ·*/
7baf5a
be49fe static char Version[] = " ·liblber.a v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";
--df92 00150b2de2e40100083 Page 1 of bprint.c
56feb2 #include <stdio.h>
9c324c #include <string.h>
d4b1cb #include <ctype.h>
33b779 #include "lber.h"
6eaf5a
d438e5 /*
d824ea ·* Print arbitrary stuff, for debugging.
c7495d ·*/
5eaf5a
502639 #ifdef LDAP_DEBUG
1baf5a
8f4eeb #ifndef NO_USERINTERFACE
d88149 #define BPLEN¤  48
bbaf5a
53314a void
b770e1 lber_bprint( char *data, int len )
5fbb36 {
3316de ····static char¤hexdig[] = "0123456789abcdef";
0f8e1d ····char¤   out[ BPLEN ];
1a867f ····int¤¤   i = 0;
7eaf5a
14d8c0 ····memset( out, 0, BPLEN );
5c4b13 ····for ( ;; ) {
bcb47c ¤   if ( len < 1 ) {
d3d30e ¤   ····fprintf( stderr, "\t%s\n", ( i == 0 ) ? "(end)" : out );
e5cafa ¤   ····break;
ad9371 ¤   }
d8af5a
bea593 #ifndef HEX
227e30 ¤   if ( isgraph( (unsigned char)*data )) {
8503f5 ¤   ····out[ i ] = ' ';
2a7cd3 ¤   ····out[ i+1 ] = *data;
34f037 ¤   } else {
dd7454 #endif
6f65f8 ¤   ····out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
af39de ¤   ····out[ i+1 ] = hexdig[ *data & 0x0f ];
08a593 #ifndef HEX
1d9371 ¤   }
657454 #endif
2a6474 ¤   i += 2;
598052 ¤   len--;
ec205e ¤   data++;
7faf5a
97ab4d ¤   if ( i > BPLEN - 2 ) {
f0a53c ¤   ····fprintf( stderr, "\t%s\n", out );
d06396 ¤   ····memset( out, 0, BPLEN );
127b44 ¤   ····i = 0;
54868f ¤   ····continue;
569371 ¤   }
b415ba ¤   out[ i++ ] = ' ';
796fe7 ····}
5defe6 }
80074d #else /* NO_USERINTERFACE */
ce314a void
2870e1 lber_bprint( char *data, int len )
b1bb36 {
7c28d2 ¤   (void) data;
ca481d ¤   (void) len;
12efe6 }
4b00a6 #endif /* NO_USERINTERFACE */
64af5a
507454 #endif
--19d5 000a0544a0140100084 Page 1 of decode.c
a9d8f9 /* decode.c - ber input decoding routines */
5338e5 /*
eaf590 ·* Copyright (c) 1990 Regents of the University of Michigan.
13599a ·* All rights reserved.
ae775e ·*
a9b855 ·* Redistribution and use in source and binary forms are permitted
e29795 ·* provided that this notice is preserved and that due credit is given
171873 ·* to the University of Michigan at Ann Arbor. The name of the University
9c8805 ·* may not be used to endorse or promote products derived from this
7d74fe ·* software without specific prior written permission. This software
062a32 ·* is provided ``as is'' without express or implied warranty.
3e495d ·*/
aeaf5a
6efeb2 #include <stdio.h>
9caf5a
4324c3 #if PGPSOCKETSLDAP¤ /* jason */
a865aa #include "pgpSocketsLDAP.h"
19af5a
ebdb21 #else
51c583 #ifdef MACOS
3fbea3 #include <stdlib.h>
2fd92d #include <stdarg.h>
4865e0 #include "macos.h"
4a6c94 #else /* MACOS */
f0dccb #if defined(NeXT) || defined(VMS)
6fbea3 #include <stdlib.h>
092192 #else /* next || vms */
295e84 #include <malloc.h>
b255ca #endif /* next || vms */
156a44 #if defined(PGPSOCKETSLDAP) || defined(BC31) || defined(_WIN32)
30d92d #include <stdarg.h>
d85ed0 #else /* BC31 || _WIN32 */
379b01 #include <varargs.h>
d38c55 #endif /* BC31 || _WIN32 */
81f15e #include <sys/types.h>
f70818 #ifndef WIN32¤  ¤   ¤   /* marcd */
f366f2 #include <sys/socket.h>
d26c19 #include <netinet/in.h>
cb7454 #endif
ddb3f5 #ifdef PCNFS
225f02 #include <tklib.h>
221b77 #endif /* PCNFS */
5de962 #endif /* MACOS */
b2af5a
a72664 #ifdef WIN32
362d5f #include <winsock.h>
cb7454 #endif
0daf5a
0e078a #if defined( DOS ) || defined( xx_WIN32 )¤  /* marcd */
84f2ef #include "msdos.h"
9bbc39 #endif /* DOS */
76df0f #endif /* PGPSOCKETSLDAP */
ebaf5a
fc324c #include <string.h>
c8b779 #include "lber.h"
72af5a
172639 #ifdef LDAP_DEBUG
335942 int¤lber_debug;
837454 #endif
84af5a
57504c #ifdef NEEDPROTOS
623a85 static int ber_getnint( BerElement *ber, long *num, int len );
728634 #endif /* NEEDPROTOS */
8eaf5a
2caf5a
ac772b /* return the tag - LBER_DEFAULT returned means trouble */
7ae5f9 unsigned long
81cf34 ber_get_tag( BerElement *ber )
1cbb36 {
9b23b7 ¤   unsigned char¤  xbyte;
d59375 ¤   unsigned long¤  tag;
a0f079 ¤   char¤   ¤   *tagp;
--4a80 000153325b940100084 Page 2 of decode.c
03e595 ¤   int¤¤   i;
cbaf5a
49a859 ¤   if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
62c117 ¤   ¤   return( LBER_DEFAULT );
0caf5a
dc99d3 ¤   if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
259211 ¤   ¤   return( (unsigned long) xbyte );
04af5a
a83fc6 ¤   tagp = (char *) &tag;
cda313 ¤   tagp[0] = xbyte;
ee2bac ¤   for ( i = 1; i < sizeof(long); i++ ) {
1dfdf5 ¤   ¤   if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
e34aeb ¤   ¤   ¤   return( LBER_DEFAULT );
21af5a
ebdfc3 ¤   ¤   tagp[i] = xbyte;
13af5a
f614bd ¤   ¤   if ( ! (xbyte & LBER_MORE_TAG_MASK) )
49cdcb ¤   ¤   ¤   break;
a59371 ¤   }
caaf5a
b3477b ¤   /* tag too big! */
2426a5 ¤   if ( i == sizeof(long) )
cdc117 ¤   ¤   return( LBER_DEFAULT );
eaaf5a
cf3789 ¤   /* want leading, not trailing 0's */
8534dd ¤   return( tag >> (sizeof(long) - i - 1) );
c9efe6 }
d1af5a
b3e5f9 unsigned long
6e491e ber_skip_tag( BerElement *ber, unsigned long *len )
f2bb36 {
cc9375 ¤   unsigned long¤  tag;
938ff9 ¤   unsigned char¤  lc;
dc7f04 ¤   int¤¤   noctets, diff;
0450e5 ¤   unsigned long¤  netlen;
1aaf5a
60d8af ¤   /*
ec71e4 ¤   ·* Any ber element looks like this: tag length contents.
100f04 ¤   ·* Assuming everything's ok, we return the tag byte (we
622068 ¤   ·* can assume a single byte), and return the length in len.
1c9714 ¤   ·*
28667c ¤   ·* Assumptions:
61fd0f ¤   ·*¤ 1) definite lengths
510ad4 ¤   ·*¤ 2) primitive encodings used whenever possible
fda4e3 ¤   ·*/
b6af5a
cfd8af ¤   /*
b0eaa1 ¤   ·* First, we read the tag.
d5a4e3 ¤   ·*/
a2af5a
0759e3 ¤   if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
59c117 ¤   ¤   return( LBER_DEFAULT );
0aaf5a
37d8af ¤   /*
7f039a ¤   ·* Next, read the length. ·The first byte contains the length of
670059 ¤   ·* the length. ·If bit 8 is set, the length is the long form,
a5ba89 ¤   ·* otherwise it's the short form. ·We don't allow a length that's
2617ce ¤   ·* greater than what we can hold in an unsigned long.
49a4e3 ¤   ·*/
fcaf5a
6b6a37 ¤   *len = netlen = 0;
c3d7ea ¤   if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
74c117 ¤   ¤   return( LBER_DEFAULT );
fc0e63 ¤   if ( lc & 0x80 ) {
5096a1 ¤   ¤   noctets = (lc & 0x7f);
499ff7 ¤   ¤   if ( noctets > sizeof(unsigned long) )
e24aeb ¤   ¤   ¤   return( LBER_DEFAULT );
b6e677 ¤   ¤   diff = sizeof(unsigned long) - noctets;
03ecac ¤   ¤   if ( ber_read( ber, (char *) &netlen + diff, noctets )
81b1a6 ¤   ¤   ····!= noctets )
224aeb ¤   ¤   ¤   return( LBER_DEFAULT );
1588e0 ¤   ¤   *len = LBER_NTOHL( netlen );
--f4b9 0000718e09140100084 Page 3 of decode.c
faf037 ¤   } else {
c13a9a ¤   ¤   *len = lc;
749371 ¤   }
04af5a
9b2872 ¤   return( tag );
86efe6 }
afaf5a
52e5f9 unsigned long
c05223 ber_peek_tag( BerElement *ber, unsigned long *len )
7fbb36 {
d28f9a ¤   char¤   ¤   *save;
e99375 ¤   unsigned long¤  tag;
faaf5a
b77693 ¤   save = ber->ber_ptr;
7d6a23 ¤   tag = ber_skip_tag( ber, len );
603c83 ¤   ber->ber_ptr = save;
0aaf5a
c02872 ¤   return( tag );
d3efe6 }
c7af5a
e6beb7 static int
8343b7 ber_getnint( BerElement *ber, long *num, int len )
8cbb36 {
8906a4 ¤   int¤diff, sign, i;
6e2498 ¤   long¤   netnum;
5caf5a
32d8af ¤   /*
2d2d82 ¤   ·* The tag and length have already been stripped off. ·We should
8c1642 ¤   ·* be sitting right before len bytes of 2's complement integer,
d26e4a ¤   ·* ready to be read straight into an int. ·We may have to sign
4a8cdb ¤   ·* extend after we read it in.
80a4e3 ¤   ·*/
b1af5a
c050f2 ¤   if ( len > sizeof(long) )
ad49fa ¤   ¤   return( -1 );
f5af5a
f9563f ¤   netnum = 0;
bd09f2 ¤   diff = sizeof(long) - len;
8e6c7d ¤   /* read into the low-order bytes of netnum */
8b57de ¤   if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len )
8149fa ¤   ¤   return( -1 );
f4af5a
c516a6 ¤   /* This was done after the sign extend. ·Caused problems with 32768 */
5a2239 ¤   /* ··operations on the same connection (or int greater than above). MDD */
015943 ¤   netnum = LBER_NTOHL( netnum );
30af5a
580ec5 ¤   /* sign extend if necessary */
45384d ¤   sign = ((0x80 << ((len - 1) * 8)) & netnum);
c0666a ¤   if ( sign && len < sizeof(long) ) {
d1ccd5 ¤   ¤   for ( i = sizeof(long) - 1; i > len - 1; i-- ) {
ad4602 ¤   ¤   ¤   netnum |= (0xffL << (i * 8));
250fe4 ¤   ¤   }
539371 ¤   }
720f9f ¤   *num = netnum;
76af5a
52029f ¤   return( len );
69efe6 }
0daf5a
d6e5f9 unsigned long
e42832 ber_get_int( BerElement *ber, long *num )
b2bb36 {
acef2c ¤   unsigned long¤  tag, len;
4aaf5a
60b024 ¤   if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
3dc117 ¤   ¤   return( LBER_DEFAULT );
23af5a
ef2bb0 ¤   if ( ber_getnint( ber, num, (int)len ) != (int) len )
eac117 ¤   ¤   return( LBER_DEFAULT );
fc0e24 ¤   else
2f139b ¤   ¤   return( tag );
75efe6 }
07af5a
--1252 0008f25689240100084 Page 4 of decode.c
12e5f9 unsigned long
220c58 ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
e0bb36 {
c3623a ¤   unsigned long¤  datalen, tag;
b3f52a #ifdef STR_TRANSLATION
57ea14 ¤   char¤   ¤   *transbuf;
923dd6 #endif /* STR_TRANSLATION */
69af5a
ef96ee ¤   if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
a6c117 ¤   ¤   return( LBER_DEFAULT );
7038af ¤   if ( datalen > (*len - 1) )
82c117 ¤   ¤   return( LBER_DEFAULT );
60af5a
62078f ¤   if ( ber_read( ber, buf, datalen ) != (long) datalen )
92c117 ¤   ¤   return( LBER_DEFAULT );
0baf5a
32f898 ¤   buf[datalen] = '\0';
96af5a
4ef52a #ifdef STR_TRANSLATION
441c1b ¤   if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
8b9fe5 ¤   ····&& ber->ber_decode_translate_proc != NULL ) {
bb29a9 ¤   ¤   transbuf = buf;
3ddae8 ¤   ¤   ++datalen;
a88992 ¤   ¤   if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
2d8397 ¤   ¤   ····0 ) != 0 ) {
5e4aeb ¤   ¤   ¤   return( LBER_DEFAULT );
3b0fe4 ¤   ¤   }
7cda20 ¤   ¤   if ( datalen > *len ) {
aeccab ¤   ¤   ¤   free( transbuf );
1a4aeb ¤   ¤   ¤   return( LBER_DEFAULT );
380fe4 ¤   ¤   }
53d8ae ¤   ¤   SAFEMEMCPY( buf, transbuf, datalen );
e145ff ¤   ¤   free( transbuf );
0dc74d ¤   ¤   --datalen;
599371 ¤   }
463dd6 #endif /* STR_TRANSLATION */
23af5a
3a51e0 ¤   *len = datalen;
652872 ¤   return( tag );
2defe6 }
feaf5a
a7e5f9 unsigned long
bc2507 ber_get_stringa( BerElement *ber, char **buf )
80bb36 {
fa623a ¤   unsigned long¤  datalen, tag;
9daf5a
9796ee ¤   if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
b3c117 ¤   ¤   return( LBER_DEFAULT );
c1af5a
65d9a1 ¤   if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
e6c117 ¤   ¤   return( LBER_DEFAULT );
0caf5a
8d2e31 ¤   if ( ber_read( ber, *buf, datalen ) != (long) datalen )
34c117 ¤   ¤   return( LBER_DEFAULT );
00e97a ¤   (*buf)[datalen] = '\0';
29af5a
71f52a #ifdef STR_TRANSLATION
871c1b ¤   if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
bb9fe5 ¤   ····&& ber->ber_decode_translate_proc != NULL ) {
acdae8 ¤   ¤   ++datalen;
edef5d ¤   ¤   if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
068903 ¤   ¤   ····!= 0 ) {
d058d7 ¤   ¤   ¤   free( *buf );
a94aeb ¤   ¤   ¤   return( LBER_DEFAULT );
8f0fe4 ¤   ¤   }
cd9371 ¤   }
c83dd6 #endif /* STR_TRANSLATION */
1faf5a
5f2872 ¤   return( tag );
6eefe6 }
5caf5a
8fe5f9 unsigned long
--04d7 000207f59e840100084 Page 5 of decode.c
d29cc9 ber_get_stringal( BerElement *ber, struct berval **bv )
0bbb36 {
ecc723 ¤   unsigned long¤  len, tag;
80af5a
f6e4f8 ¤   if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
31c117 ¤   ¤   return( LBER_DEFAULT );
22af5a
6eb024 ¤   if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
e3c117 ¤   ¤   return( LBER_DEFAULT );
8caf5a
def0c1 ¤   if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL )
49c117 ¤   ¤   return( LBER_DEFAULT );
47af5a
214fee ¤   if ( ber_read( ber, (*bv)->bv_val, len ) != (long) len )
36c117 ¤   ¤   return( LBER_DEFAULT );
014189 ¤   ((*bv)->bv_val)[len] = '\0';
ac7393 ¤   (*bv)->bv_len = len;
14af5a
18f52a #ifdef STR_TRANSLATION
04aaa5 ¤   if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
859fe5 ¤   ····&& ber->ber_decode_translate_proc != NULL ) {
63d670 ¤   ¤   ++len;
9eb405 ¤   ¤   if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
0fa9ef ¤   ¤   ····&len, 1 ) != 0 ) {
6ec31f ¤   ¤   ¤   free( (*bv)->bv_val );
384aeb ¤   ¤   ¤   return( LBER_DEFAULT );
6e0fe4 ¤   ¤   }
8f8e41 ¤   ¤   (*bv)->bv_len = len - 1;
e39371 ¤   }
8e3dd6 #endif /* STR_TRANSLATION */
c4af5a
d02872 ¤   return( tag );
c4efe6 }
caaf5a
aae5f9 unsigned long
251b69 ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
f3bb36 {
bc623a ¤   unsigned long¤  datalen, tag;
1a1be1 ¤   unsigned char¤  unusedbits;
f9af5a
0396ee ¤   if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
ebc117 ¤   ¤   return( LBER_DEFAULT );
5225ee ¤   --datalen;
09af5a
2b7360 ¤   if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
0bc117 ¤   ¤   return( LBER_DEFAULT );
3aaf5a
619964 ¤   if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
98c117 ¤   ¤   return( LBER_DEFAULT );
81af5a
482e31 ¤   if ( ber_read( ber, *buf, datalen ) != (long) datalen )
3ec117 ¤   ¤   return( LBER_DEFAULT );
0daf5a
618697 ¤   *blen = datalen * 8 - unusedbits;
b12872 ¤   return( tag );
34efe6 }
81af5a
86e5f9 unsigned long
794c9a ber_get_null( BerElement *ber )
d0bb36 {
70c723 ¤   unsigned long¤  len, tag;
70af5a
0db024 ¤   if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
65c117 ¤   ¤   return( LBER_DEFAULT );
8eaf5a
aa46ef ¤   if ( len != 0 )
83c117 ¤   ¤   return( LBER_DEFAULT );
8daf5a
ac2872 ¤   return( tag );
8cefe6 }
51af5a
20e5f9 unsigned long
--67c3 0008aacae2640100084 Page 6 of decode.c
065e7c ber_get_boolean( BerElement *ber, int *boolval )
f0bb36 {
2ef180 ¤   long¤   longbool;
f50295 ¤   int¤rc;
58af5a
fdd191 ¤   rc = ber_get_int( ber, &longbool );
ba0e2e ¤   *boolval = longbool;
43af5a
e26d62 ¤   return( rc );
4befe6 }
fcaf5a
14e5f9 unsigned long
363749 ber_first_element( BerElement *ber, unsigned long *len, char **last )
00bb36 {
f3a0c9 ¤   /* skip the sequence header, use the len to mark where to stop */
7205d6 ¤   if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
a1c117 ¤   ¤   return( LBER_DEFAULT );
4c9371 ¤   }
38af5a
86fbed ¤   *last = ber->ber_ptr + *len;
f4af5a
6b23ab ¤   if ( *last == ber->ber_ptr ) {
ebc117 ¤   ¤   return( LBER_DEFAULT );
989371 ¤   }
9baf5a
d642a3 ¤   return( ber_peek_tag( ber, len ) );
d8efe6 }
0aaf5a
dfe5f9 unsigned long
ca4396 ber_next_element( BerElement *ber, unsigned long *len, char *last )
ffbb36 {
b812b6 ¤   if ( ber->ber_ptr == last ) {
71c117 ¤   ¤   return( LBER_DEFAULT );
8f9371 ¤   }
7caf5a
3042a3 ¤   return( ber_peek_tag( ber, len ) );
96efe6 }
30af5a
0c1338 /* VARARGS */
5fe5f9 unsigned long
462155 ber_scanf(
19f1df #if defined(MACOS) || defined(BC31) || defined(_WIN32) \
e38ad6 ¤   || defined(PGPSOCKETSLDAP) /* jason */
47ebc8 ¤   BerElement *ber, char *fmt, ... )
83db21 #else
2b098e ¤   va_alist )
85b70b va_dcl
667454 #endif
9abb36 {
747be9 ¤   va_list¤¤   ap;
4e97a5 #if !defined(PGPSOCKETSLDAP) && !defined(MACOS) && !defined(BC31) && \
3e94bd ····!defined(_WIN32) /* jason */
419c95 ¤   BerElement¤ *ber;
d91344 ¤   char¤   ¤   *fmt;
507454 #endif
5441bd ¤   char¤   ¤   *last;
b00e36 ¤   char¤   ¤   *s, **ss, ***sss;
dee37a ¤   struct berval ¤ ***bv, **bvp, *bval;
9fc8e6 ¤   int¤¤   *i, j;
b4d405 ¤   long¤   ¤   *l, rc, tag;
9a93e7 ¤   unsigned long¤  len;
9aaf5a
e5ad45 #if defined(PGPSOCKETSLDAP) || defined(MACOS) || defined(BC31) \
c66b34 ¤   || defined(_WIN32) /* jason */
fcf4c3 ¤   va_start( ap, fmt );
eadb21 #else
c6f279 ¤   va_start( ap );
7e91cf ¤   ber = va_arg( ap, BerElement * );
938c2a ¤   fmt = va_arg( ap, char * );
617454 #endif
9daf5a
8a2639 #ifdef LDAP_DEBUG
--70ac 0002cb5ea6840100084 Page 7 of decode.c
412bc0 ¤   if ( lber_debug & 64 ) {
cd9a7b ¤   ¤   fprintf( stderr, "ber_scanf fmt (%s) ber:\n", fmt );
8a58ed ¤   ¤   ber_dump( ber, 1 );
e29371 ¤   }
497454 #endif
48af5a
6e70eb ¤   for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
7353d3 ¤   ¤   switch ( *fmt ) {
fd0b2f ¤   ¤   case 'a':¤  /* octet string - allocate storage as needed */
29ff42 ¤   ¤   ¤   ss = va_arg( ap, char ** );
c15cde ¤   ¤   ¤   rc = ber_get_stringa( ber, ss );
2acdcb ¤   ¤   ¤   break;
4faf5a
3064f1 ¤   ¤   case 'b':¤  /* boolean */
201a58 ¤   ¤   ¤   i = va_arg( ap, int * );
631298 ¤   ¤   ¤   rc = ber_get_boolean( ber, i );
b9cdcb ¤   ¤   ¤   break;
acaf5a
d25cb6 ¤   ¤   case 'e':¤  /* enumerated */
69c4e8 ¤   ¤   case 'i':¤  /* int */
843ecf ¤   ¤   ¤   l = va_arg( ap, long * );
57495c ¤   ¤   ¤   rc = ber_get_int( ber, l );
bacdcb ¤   ¤   ¤   break;
28af5a
b26e4c ¤   ¤   case 'l':¤  /* length of next item */
ca3ecf ¤   ¤   ¤   l = va_arg( ap, long * );
989290 ¤   ¤   ¤   rc = ber_peek_tag( ber, (unsigned long *)l );
5fcdcb ¤   ¤   ¤   break;
7baf5a
5786d2 ¤   ¤   case 'n':¤  /* null */
da9c36 ¤   ¤   ¤   rc = ber_get_null( ber );
a9cdcb ¤   ¤   ¤   break;
b8af5a
7e7ccc ¤   ¤   case 's':¤  /* octet string - in a buffer */
811391 ¤   ¤   ¤   s = va_arg( ap, char * );
953ecf ¤   ¤   ¤   l = va_arg( ap, long * );
9ab6fc ¤   ¤   ¤   rc = ber_get_stringb( ber, s, (unsigned long *)l );
c2cdcb ¤   ¤   ¤   break;
e6af5a
0dce46 ¤   ¤   case 'o':¤  /* octet string in a supplied berval */
8c56e4 ¤   ¤   ¤   bval = va_arg( ap, struct berval * );
0619cb ¤   ¤   ¤   ber_peek_tag( ber, &bval->bv_len );
25874f ¤   ¤   ¤   rc = ber_get_stringa( ber, &bval->bv_val );
2acdcb ¤   ¤   ¤   break;
05af5a
bd1b4a ¤   ¤   case 'O':¤  /* octet string - allocate & include length */
8b795a ¤   ¤   ¤   bvp = va_arg( ap, struct berval ** );
6b8804 ¤   ¤   ¤   rc = ber_get_stringal( ber, bvp );
45cdcb ¤   ¤   ¤   break;
89af5a
0ab18e ¤   ¤   case 'B':¤  /* bit string - allocate storage as needed */
fdff42 ¤   ¤   ¤   ss = va_arg( ap, char ** );
2daa05 ¤   ¤   ¤   l = va_arg( ap, long * ); /* for length, in bits */
293629 ¤   ¤   ¤   rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
76cdcb ¤   ¤   ¤   break;
f1af5a
16b42f ¤   ¤   case 't':¤  /* tag of next item */
de1a58 ¤   ¤   ¤   i = va_arg( ap, int * );
50993d ¤   ¤   ¤   *i = rc = ber_peek_tag( ber, &len );
00cdcb ¤   ¤   ¤   break;
b0af5a
8eadfd ¤   ¤   case 'T':¤  /* skip tag of next item */
6d1a58 ¤   ¤   ¤   i = va_arg( ap, int * );
c7d676 ¤   ¤   ¤   *i = rc = ber_skip_tag( ber, &len );
e7cdcb ¤   ¤   ¤   break;
f3af5a
edf6a9 ¤   ¤   case 'v':¤  /* sequence of strings */
11bf02 ¤   ¤   ¤   sss = va_arg( ap, char *** );
37b79f ¤   ¤   ¤   *sss = NULL;
96d41b ¤   ¤   ¤   j = 0;
306d6c ¤   ¤   ¤   for ( tag = ber_first_element( ber, &len, &last );
2ce1c2 ¤   ¤   ¤   ····tag != LBER_DEFAULT && rc != LBER_DEFAULT;
--c84e 0003d5b51e840100084 Page 8 of decode.c
008af1 ¤   ¤   ¤   ····tag = ber_next_element( ber, &len, last ) ) {
7f25f3 ¤   ¤   ¤   ¤   if ( *sss == NULL ) {
cbeae5 ¤   ¤   ¤   ¤   ¤   *sss = (char **) malloc(
37e2ca ¤   ¤   ¤   ¤   ¤   ····2 * sizeof(char *) );
bbb5fc ¤   ¤   ¤   ¤   } else {
dff1a3 ¤   ¤   ¤   ¤   ¤   *sss = (char **) realloc( (char *) *sss,
54af10 ¤   ¤   ¤   ¤   ¤   ····(j + 2) * sizeof(char *) );
cf2613 ¤   ¤   ¤   ¤   }
62372d ¤   ¤   ¤   ¤   rc = ber_get_stringa( ber, &((*sss)[j]) );
1fddab ¤   ¤   ¤   ¤   j++;
5da3a6 ¤   ¤   ¤   }
390cc7 ¤   ¤   ¤   if ( j > 0 )
92793a ¤   ¤   ¤   ¤   (*sss)[j] = NULL;
d0cdcb ¤   ¤   ¤   break;
6eaf5a
26a214 ¤   ¤   case 'V':¤  /* sequence of strings + lengths */
351dfd ¤   ¤   ¤   bv = va_arg( ap, struct berval *** );
57e39f ¤   ¤   ¤   *bv = NULL;
d2d41b ¤   ¤   ¤   j = 0;
b66d6c ¤   ¤   ¤   for ( tag = ber_first_element( ber, &len, &last );
bee1c2 ¤   ¤   ¤   ····tag != LBER_DEFAULT && rc != LBER_DEFAULT;
648af1 ¤   ¤   ¤   ····tag = ber_next_element( ber, &len, last ) ) {
6a1d96 ¤   ¤   ¤   ¤   if ( *bv == NULL ) {
6ff329 ¤   ¤   ¤   ¤   ¤   *bv = (struct berval **) malloc(
2b5c53 ¤   ¤   ¤   ¤   ¤   ····2 * sizeof(struct berval *) );
dcb5fc ¤   ¤   ¤   ¤   } else {
df7462 ¤   ¤   ¤   ¤   ¤   *bv = (struct berval **) realloc( (char *) *bv,
a5ba6f ¤   ¤   ¤   ¤   ¤   ····(j + 2) * sizeof(struct berval *) );
ee2613 ¤   ¤   ¤   ¤   }
c9e586 ¤   ¤   ¤   ¤   rc = ber_get_stringal( ber, &((*bv)[j]) );
92ddab ¤   ¤   ¤   ¤   j++;
6da3a6 ¤   ¤   ¤   }
7c0cc7 ¤   ¤   ¤   if ( j > 0 )
bcf185 ¤   ¤   ¤   ¤   (*bv)[j] = NULL;
22cdcb ¤   ¤   ¤   break;
5baf5a
c52573 ¤   ¤   case 'x':¤  /* skip the next element - whatever it is */
e9b930 ¤   ¤   ¤   if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
61f622 ¤   ¤   ¤   ¤   break;
1f9165 ¤   ¤   ¤   ber->ber_ptr += len;
c8cdcb ¤   ¤   ¤   break;
23af5a
155f01 ¤   ¤   case '{':¤  /* begin sequence */
b38e21 ¤   ¤   case '[':¤  /* begin set */
8be28c ¤   ¤   ¤   if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' )
a8970d ¤   ¤   ¤   ¤   rc = ber_skip_tag( ber, &len );
a4cdcb ¤   ¤   ¤   break;
faaf5a
43c97d ¤   ¤   case '}':¤  /* end sequence */
6672ae ¤   ¤   case ']':¤  /* end set */
cbcdcb ¤   ¤   ¤   break;
d7af5a
c69ae3 ¤   ¤   default:
064eeb #ifndef NO_USERINTERFACE
043355 ¤   ¤   ¤   fprintf( stderr, "unknown fmt %c\n", *fmt );
4d00a6 #endif /* NO_USERINTERFACE */
2d5dbb ¤   ¤   ¤   rc = LBER_DEFAULT;
2bcdcb ¤   ¤   ¤   break;
cb0fe4 ¤   ¤   }
fb9371 ¤   }
9aaf5a
93570e ¤   va_end( ap );
9faf5a
946d62 ¤   return( rc );
50efe6 }
acaf5a
79314a void
8f3666 ber_bvfree( struct berval *bv )
e0bb36 {
efd068 ¤   if ( bv->bv_val != NULL )
d22804 ¤   ¤   free( bv->bv_val );
3d2673 ¤   free( (char *) bv );
--29fa 0013e40cf4640100084 Page 9 of decode.c
7aefe6 }
46af5a
81314a void
c453ae ber_bvecfree( struct berval **bv )
6cbb36 {
771426 ¤   int¤i;
faaf5a
0030ff ¤   for ( i = 0; bv[i] != NULL; i++ )
796e96 ¤   ¤   ber_bvfree( bv[i] );
602673 ¤   free( (char *) bv );
18efe6 }
e2af5a
045caa struct berval *
539534 ber_bvdup( struct berval *bv )
cebb36 {
ff03e4 ¤   struct berval¤  *newBV;
92af5a
e618a8 ¤   if ( (newBV = (struct berval *) malloc( sizeof(struct berval) ))
a73c7b ¤   ····== NULL ) {
a3ef86 ¤   ¤   return( NULL );
bf9371 ¤   }
b7a0ce ¤   if ( (newBV->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
6bef86 ¤   ¤   return( NULL );
d09371 ¤   }
02af62 ¤   SAFEMEMCPY( newBV->bv_val, bv->bv_val, (size_t) bv->bv_len );
5ea069 ¤   newBV->bv_val[bv->bv_len] = '\0';
bf2096 ¤   newBV->bv_len = bv->bv_len;
40af5a
c634de ¤   return( newBV );
21efe6 }
d6af5a
bbaf5a
2bf52a #ifdef STR_TRANSLATION
29314a void
209274 ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
f2de37 ¤   BERTranslateProc decode_proc )
dbbb36 {
f4ce17 ····ber->ber_encode_translate_proc = encode_proc;
7b4a0a ····ber->ber_decode_translate_proc = decode_proc;
13efe6 }
3e3dd6 #endif /* STR_TRANSLATION */
--a4d8 0015e225e6540100085 Page 1 of dtest.c
96985c /* dtest.c - lber decoding test program */
5338e5 /*
96f590 ·* Copyright (c) 1990 Regents of the University of Michigan.
b1599a ·* All rights reserved.
87775e ·*
deb855 ·* Redistribution and use in source and binary forms are permitted
e39795 ·* provided that this notice is preserved and that due credit is given
ec1873 ·* to the University of Michigan at Ann Arbor. The name of the University
198805 ·* may not be used to endorse or promote products derived from this
5674fe ·* software without specific prior written permission. This software
5f2a32 ·* is provided ``as is'' without express or implied warranty.
83495d ·*/
79af5a
bbfeb2 #include <stdio.h>
71324c #include <string.h>
b8c583 #ifdef MACOS
b1bea3 #include <stdlib.h>
0bb6ac #include <console.h>
ed6c94 #else /* MACOS */
83f15e #include <sys/types.h>
a8a394 #ifndef WIN32¤  ¤   /* marcd */
4366f2 #include <sys/socket.h>
7d7454 #endif
95e962 #endif /* MACOS */
f6b779 #include "lber.h"
d4af5a
f8bd01 static usage( char *name )
c1bb36 {
18581e ¤   fprintf( stderr, "usage: %s fmt\n", name );
72efe6 }
97af5a
b7874e main( int argc, char **argv )
91bb36 {
0a41ba ¤   long¤   ¤   i, i2, num;
4693e7 ¤   unsigned long¤  len;
2b11a8 ¤   int¤¤   tag;
3e3153 ¤   char¤   ¤   *str, *s1, *s2;
ee28d5 ¤   BerElement¤ ber;
9c3067 ¤   Sockbuf¤¤   sb;
1ef036 ¤   extern char¤*optarg;
96af5a
e2c583 #ifdef MACOS
d8242c ¤   ccommand( &argv );
ebfadc ¤   cshow( stdout );
e4e962 #endif /* MACOS */
84af5a
16667d ¤   bzero( &sb, sizeof(sb) );
2157a2 ¤   sb.sb_sd = 0;
61d63d ¤   sb.sb_ber.ber_buf = NULL;
ede4d6 ¤   if ( (tag = ber_get_next( &sb, &len, &ber )) == -1 ) {
580a00 ¤   ¤   perror( "ber_get_next" );
6a5691 ¤   ¤   exit( 1 );
5a9371 ¤   }
0a1dbf ¤   printf( "message has tag 0x%x and length %ld\n", tag, len );
12af5a
c995dd ¤   if ( ber_scanf( &ber, "i", &i ) == -1 ) {
be363b ¤   ¤   fprintf( stderr, "ber_scanf returns -1\n" );
a05691 ¤   ¤   exit( 1 );
1e9371 ¤   }
bce4df ¤   printf( "got int %d\n", i );
06af5a
1eea61 ¤   return( 0 );
5eefe6 }
--f3a1 000c8a60ef240100086 Page 1 of encode.c
d3b80f /* encode.c - ber output encoding routines */
5038e5 /*
fcf590 ·* Copyright (c) 1990 Regents of the University of Michigan.
34599a ·* All rights reserved.
91775e ·*
e3b855 ·* Redistribution and use in source and binary forms are permitted
369795 ·* provided that this notice is preserved and that due credit is given
c81873 ·* to the University of Michigan at Ann Arbor. The name of the University
678805 ·* may not be used to endorse or promote products derived from this
2c74fe ·* software without specific prior written permission. This software
f32a32 ·* is provided ``as is'' without express or implied warranty.
f0495d ·*/
44af5a
05feb2 #include <stdio.h>
66af5a
1f24c3 #if PGPSOCKETSLDAP¤ /* jason */
b365aa #include "pgpSocketsLDAP.h"
56af5a
0ddb21 #else
94c583 #ifdef MACOS
9bbea3 #include <stdlib.h>
a5d92d #include <stdarg.h>
3165e0 #include "macos.h"
8c6c94 #else /* MACOS */
2ddccb #if defined(NeXT) || defined(VMS)
52bea3 #include <stdlib.h>
d52192 #else /* next || vms */
7a5e84 #include <malloc.h>
c755ca #endif /* next || vms */
9d6ccf #if defined(PGPSOCKETSLDAP) || defined( BC31 ) || defined( _WIN32 )
39d92d #include <stdarg.h>
cd5ed0 #else /* BC31 || _WIN32 */
d99b01 #include <varargs.h>
cf8c55 #endif /* BC31 || _WIN32 */
a1f15e #include <sys/types.h>
c10818 #ifndef WIN32¤  ¤   ¤   /* marcd */
ff66f2 #include <sys/socket.h>
066c19 #include <netinet/in.h>
c27454 #endif
e5b3f5 #ifdef PCNFS
6b5f02 #include <tklib.h>
7b1b77 #endif /* PCNFS */
bce962 #endif /* MACOS */
18ea1a #ifndef VMS
7ac737 #include <memory.h>
187454 #endif
9a2664 #ifdef WIN32
362d5f #include <winsock.h>
a07454 #endif
50df0f #endif /* PGPSOCKETSLDAP */
76af5a
62324c #include <string.h>
eeb779 #include "lber.h"
f4af5a
a5078a #if defined( DOS ) || defined( xx_WIN32 )¤  /* marcd */
3ff2ef #include "msdos.h"
5ebc39 #endif /* DOS */
e6af5a
f6504c #ifdef NEEDPROTOS
2bee38 static int ber_put_len( BerElement *ber, unsigned long len, int nosos );
0c75c2 static int ber_start_seqorset( BerElement *ber, unsigned long tag );
3c2ad0 static int ber_put_seqorset( BerElement *ber );
0c2181 static int ber_put_int_or_enum( BerElement *ber, long num, unsigned long tag );
9e8634 #endif /* NEEDPROTOS */
3baf5a
dcaf5a
1bbeb7 static int
02059a ber_calc_taglen( unsigned long tag )
bfbb36 {
751426 ¤   int¤i;
7148c2 ¤   long¤   mask;
c8af5a
--66ac 00056bf679940100086 Page 2 of encode.c
8a70dd ¤   /* find the first non-all-zero byte in the tag */
8b332c ¤   for ( i = sizeof(long) - 1; i > 0; i-- ) {
85ded9 ¤   ¤   mask = (0xffL << (i * 8));
75d243 ¤   ¤   /* not all zero */
14d838 ¤   ¤   if ( tag & mask )
d4cdcb ¤   ¤   ¤   break;
e49371 ¤   }
3eaf5a
64f271 ¤   return( i + 1 );
d4efe6 }
c7af5a
2dbeb7 static int
97cd95 ber_put_tag( BerElement¤*ber, unsigned long tag, int nosos )
b2bb36 {
75c3f9 ¤   int¤¤   taglen;
76b0e9 ¤   unsigned long¤  ntag;
c0af5a
d7f35e ¤   taglen = ber_calc_taglen( tag );
31af5a
5c29d6 ¤   ntag = LBER_HTONL( tag );
c6af5a
92380b ¤   return( ber_write( ber, ((char *) &ntag) + sizeof(long) - taglen,
af57bb ¤   ····taglen, nosos ) );
bbefe6 }
0baf5a
ddbeb7 static int
94a53c ber_calc_lenlen( unsigned long len )
0abb36 {
8ed8af ¤   /*
4d4830 ¤   ·* short len if it's less than 128 - one byte giving the len,
ad5f77 ¤   ·* with bit 8 0.
38a4e3 ¤   ·*/
d4af5a
d81b18 ¤   if ( len <= 0x7F )
9ea0ae ¤   ¤   return( 1 );
beaf5a
13d8af ¤   /*
8df397 ¤   ·* long len otherwise - one byte with bit 8 set, giving the
dc5268 ¤   ·* length of the length, followed by the length itself.
a0a4e3 ¤   ·*/
daaf5a
af05af ¤   if ( len <= 0xFF )
efbd62 ¤   ¤   return( 2 );
776acb ¤   if ( len <= 0xFFFFL )
a9b626 ¤   ¤   return( 3 );
1f8df8 ¤   if ( len <= 0xFFFFFFL )
2c86fa ¤   ¤   return( 4 );
4faf5a
7fcc35 ¤   return( 5 );
87efe6 }
11af5a
0abeb7 static int
ccfc54 ber_put_len( BerElement *ber, unsigned long len, int nosos )
c7bb36 {
f1e595 ¤   int¤¤   i;
2cd107 ¤   char¤   ¤   lenlen;
aaca2c ¤   long¤   ¤   mask;
2150e5 ¤   unsigned long¤  netlen;
22af5a
03d8af ¤   /*
fb4830 ¤   ·* short len if it's less than 128 - one byte giving the len,
705f77 ¤   ·* with bit 8 0.
f9a4e3 ¤   ·*/
74af5a
c78a2c ¤   if ( len <= 127 ) {
cde456 ¤   ¤   netlen = LBER_HTONL( len );
d558e3 ¤   ¤   return( ber_write( ber, (char *) &netlen + sizeof(long) - 1,
8ace84 ¤   ¤   ····1, nosos ) );
d89371 ¤   }
b5af5a
14d8af ¤   /*
56f397 ¤   ·* long len otherwise - one byte with bit 8 set, giving the
--d5cd 000ec840dad40100086 Page 3 of encode.c
ca5268 ¤   ·* length of the length, followed by the length itself.
73a4e3 ¤   ·*/
efaf5a
71e9df ¤   /* find the first non-all-zero byte */
be332c ¤   for ( i = sizeof(long) - 1; i > 0; i-- ) {
e4ded9 ¤   ¤   mask = (0xffL << (i * 8));
93d243 ¤   ¤   /* not all zero */
5943cd ¤   ¤   if ( len & mask )
3bcdcb ¤   ¤   ¤   break;
f69371 ¤   }
b36a81 ¤   lenlen = ++i;
45f2ce ¤   if ( lenlen > 4 )
b249fa ¤   ¤   return( -1 );
729829 ¤   lenlen |= 0x80;
e6af5a
253ed1 ¤   /* write the length of the length */
f4be59 ¤   if ( ber_write( ber, &lenlen, 1, nosos ) != 1 )
ce49fa ¤   ¤   return( -1 );
23af5a
af7f7f ¤   /* write the length itself */
786faa ¤   netlen = LBER_HTONL( len );
197d9d ¤   if ( ber_write( ber, (char *) &netlen + (sizeof(long) - i), i, nosos )
681195 ¤   ····!= i )
2a49fa ¤   ¤   return( -1 );
5baf5a
3df271 ¤   return( i + 1 );
74efe6 }
8baf5a
94beb7 static int
d46678 ber_put_int_or_enum( BerElement *ber, long num, unsigned long tag )
4cbb36 {
0cd80d ¤   int¤i, sign, taglen;
dbe015 ¤   int¤len, lenlen;
e2d0c3 ¤   long¤   netnum, mask;
2eaf5a
704b08 ¤   sign = (num < 0);
f7af5a
24d8af ¤   /*
8a4317 ¤   ·* high bit is set - look for first non-all-one byte
4c3fef ¤   ·* high bit is clear - look for first non-all-zero byte
f2a4e3 ¤   ·*/
a0332c ¤   for ( i = sizeof(long) - 1; i > 0; i-- ) {
cbded9 ¤   ¤   mask = (0xffL << (i * 8));
5aaf5a
1ceea5 ¤   ¤   if ( sign ) {
6be1e1 ¤   ¤   ¤   /* not all ones */
80d8a6 ¤   ¤   ¤   if ( (num & mask) != mask )
7ef622 ¤   ¤   ¤   ¤   break;
c045a6 ¤   ¤   } else {
8ac66b ¤   ¤   ¤   /* not all zero */
802aa8 ¤   ¤   ¤   if ( num & mask )
e1f622 ¤   ¤   ¤   ¤   break;
330fe4 ¤   ¤   }
059371 ¤   }
57af5a
71d8af ¤   /*
8f1177 ¤   ·* we now have the "leading byte". ·if the high bit on this
4e9e00 ¤   ·* byte matches the sign bit, we need to "back up" a byte.
77a4e3 ¤   ·*/
1a03b0 ¤   mask = (num & (0x80L << (i * 8)));
468331 ¤   if ( (mask && !sign) || (sign && !mask) )
a8347d ¤   ¤   i++;
39af5a
4f34f7 ¤   len = i + 1;
b2af5a
1ac33d ¤   if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
0a49fa ¤   ¤   return( -1 );
48af5a
a4998b ¤   if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 )
e849fa ¤   ¤   return( -1 );
bc3444 ¤   i++;
ec01c4 ¤   netnum = LBER_HTONL( num );
--2657 0006e6e46a340100086 Page 4 of encode.c
f77b9a ¤   if ( ber_write( ber, (char *) &netnum + (sizeof(long) - i), i, 0 )
b67d5f ¤   ···!= i )
6549fa ¤   ¤   return( -1 );
c8af5a
f8da84 ¤   /* length of tag + length + contents */
03fbed ¤   return( taglen + lenlen + i );
15efe6 }
96af5a
2d4d2f int
ffb202 ber_put_enum( BerElement *ber, long num, unsigned long tag )
a2bb36 {
9bde97 ¤   if ( tag == LBER_DEFAULT )
6f7fa2 ¤   ¤   tag = LBER_ENUMERATED;
eeaf5a
fb2e27 ¤   return( ber_put_int_or_enum( ber, num, tag ) );
24efe6 }
cdaf5a
964d2f int
edf8c6 ber_put_int( BerElement *ber, long num, unsigned long tag )
77bb36 {
c8de97 ¤   if ( tag == LBER_DEFAULT )
5a3e1f ¤   ¤   tag = LBER_INTEGER;
e9af5a
6e2e27 ¤   return( ber_put_int_or_enum( ber, num, tag ) );
89efe6 }
0aaf5a
f14d2f int
c4bded ber_put_ostring( BerElement *ber, char *str, unsigned long len,
8df197 ¤   unsigned long tag )
5bbb36 {
fbd860 ¤   int¤taglen, lenlen, rc;
adf52a #ifdef STR_TRANSLATION
96b301 ¤   int¤free_str;
a33dd6 #endif /* STR_TRANSLATION */
83af5a
14de97 ¤   if ( tag == LBER_DEFAULT )
85f6a1 ¤   ¤   tag = LBER_OCTETSTRING;
5daf5a
8fc33d ¤   if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
4249fa ¤   ¤   return( -1 );
b0af5a
b3f52a #ifdef STR_TRANSLATION
773a43 ¤   if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0 &&
53956f ¤   ····ber->ber_encode_translate_proc != NULL ) {
c562fd ¤   ¤   if ( (*(ber->ber_encode_translate_proc))( &str, &len, 0 )
9a8903 ¤   ¤   ····!= 0 ) {
5b8e4f ¤   ¤   ¤   return( -1 );
eb0fe4 ¤   ¤   }
342589 ¤   ¤   free_str = 1;
94f037 ¤   } else {
b97f55 ¤   ¤   free_str = 0;
a99371 ¤   }
313dd6 #endif /* STR_TRANSLATION */
2daf5a
de8b52 ¤   if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ||
ee464c ¤   ¤   ber_write( ber, str, len, 0 ) != (long) len ) {
4b4dae ¤   ¤   rc = -1;
9bf037 ¤   } else {
c853f3 ¤   ¤   /* return length of tag + length + contents */
0f57d5 ¤   ¤   rc = taglen + lenlen + len;
789371 ¤   }
d0af5a
eaf52a #ifdef STR_TRANSLATION
92cf66 ¤   if ( free_str ) {
17ad59 ¤   ¤   free( str );
209371 ¤   }
713dd6 #endif /* STR_TRANSLATION */
38af5a
066d62 ¤   return( rc );
71efe6 }
89af5a
6e4d2f int
--a3c2 000dab7fea840100086 Page 5 of encode.c
5b20a7 ber_put_string( BerElement *ber, char *str, unsigned long tag )
36bb36 {
514af8 ¤   return( ber_put_ostring( ber, str, strlen( str ), tag ));
c9efe6 }
dcaf5a
044d2f int
bbf467 ber_put_bitstring( BerElement *ber, char *str,
7f01d2 ¤   unsigned long blen /* in bits */, unsigned long tag )
12bb36 {
08b4d5 ¤   int¤¤   taglen, lenlen, len;
b31be1 ¤   unsigned char¤  unusedbits;
e5af5a
f0de97 ¤   if ( tag == LBER_DEFAULT )
268ea0 ¤   ¤   tag = LBER_BITSTRING;
f3af5a
95c33d ¤   if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
a749fa ¤   ¤   return( -1 );
7baf5a
fb9934 ¤   len = ( blen + 7 ) / 8;
da4034 ¤   unusedbits = (unsigned char) (len * 8 - blen);
1948d0 ¤   if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 )
9a49fa ¤   ¤   return( -1 );
6faf5a
d4d8cb ¤   if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 )
d049fa ¤   ¤   return( -1 );
aeaf5a
5eb9b4 ¤   if ( ber_write( ber, str, len, 0 ) != len )
6a49fa ¤   ¤   return( -1 );
04af5a
e807a2 ¤   /* return length of tag + length + unused bit count + contents */
882c48 ¤   return( taglen + 1 + lenlen + len );
44efe6 }
faaf5a
2a4d2f int
e9bec9 ber_put_null( BerElement *ber, unsigned long tag )
9bbb36 {
32eb21 ¤   int¤taglen;
e7af5a
0dde97 ¤   if ( tag == LBER_DEFAULT )
c1fb5a ¤   ¤   tag = LBER_NULL;
2caf5a
28c33d ¤   if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
8449fa ¤   ¤   return( -1 );
bfaf5a
e71c62 ¤   if ( ber_put_len( ber, 0, 0 ) != 1 )
f049fa ¤   ¤   return( -1 );
56af5a
037ce5 ¤   return( taglen + 1 );
41efe6 }
40af5a
f14d2f int
ae0524 ber_put_boolean( BerElement *ber, int boolval, unsigned long tag )
65bb36 {
69c3f9 ¤   int¤¤   taglen;
8b1be9 ¤   unsigned char¤  trueval = 0xff;
671112 ¤   unsigned char¤  falseval = 0x00;
2daf5a
a9de97 ¤   if ( tag == LBER_DEFAULT )
94b407 ¤   ¤   tag = LBER_BOOLEAN;
f9af5a
96c33d ¤   if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )
2949fa ¤   ¤   return( -1 );
36af5a
476288 ¤   if ( ber_put_len( ber, 1, 0 ) != 1 )
0e49fa ¤   ¤   return( -1 );
8eaf5a
c750d8 ¤   if ( ber_write( ber, (char *)(boolval ? &trueval : &falseval), 1, 0 )
cb215b ¤   ····!= 1 )
e849fa ¤   ¤   return( -1 );
34af5a
4b6129 ¤   return( taglen + 2 );
daefe6 }
--32c8 00043b9c0d640100086 Page 6 of encode.c
e0af5a
9f4915 #define FOUR_BYTE_LEN¤  5
63af5a
f6beb7 static int
090b97 ber_start_seqorset( BerElement *ber, unsigned long tag )
a3bb36 {
fad7ca ¤   Seqorset¤   *newSEQ;
e7af5a
353ccb ¤   if ( (newSEQ = (Seqorset *) calloc( sizeof(Seqorset), 1 ))
456f5b ¤   ····== NULLSEQORSET )
d149fa ¤   ¤   return( -1 );
c20ef7 ¤   newSEQ->sos_ber = ber;
2a47cb ¤   if ( ber->ber_sos == NULLSEQORSET )
f2aeb1 ¤   ¤   newSEQ->sos_first = ber->ber_ptr;
850e24 ¤   else
60922f ¤   ¤   newSEQ->sos_first = ber->ber_sos->sos_ptr;
3faf5a
4dcf99 ¤   /* Set aside room for a 4 byte length field */
7d2c79 ¤   newSEQ->sos_ptr = newSEQ->sos_first + ber_calc_taglen( tag ) +·
334083 ¤   ¤   ¤   ¤   ¤   ··FOUR_BYTE_LEN;
a2f6c9 ¤   newSEQ->sos_tag = tag;
d6af5a
2150f5 ¤   newSEQ->sos_next = ber->ber_sos;
d2e4cc ¤   ber->ber_sos = newSEQ;
d3af5a
f8ea61 ¤   return( 0 );
f0efe6 }
89af5a
f14d2f int
53b249 ber_start_seq( BerElement *ber, unsigned long tag )
82bb36 {
a5de97 ¤   if ( tag == LBER_DEFAULT )
d2805b ¤   ¤   tag = LBER_SEQUENCE;
f8af5a
e0e476 ¤   return( ber_start_seqorset( ber, tag ) );
7fefe6 }
a0af5a
f84d2f int
84849b ber_start_set( BerElement *ber, unsigned long tag )
9dbb36 {
fade97 ¤   if ( tag == LBER_DEFAULT )
746032 ¤   ¤   tag = LBER_SET;
c9af5a
f1e476 ¤   return( ber_start_seqorset( ber, tag ) );
65efe6 }
91af5a
2fbeb7 static int
2522b2 ber_put_seqorset( BerElement *ber )
8fbb36 {
cdb148 ¤   unsigned long¤  len, netlen;
43c823 ¤   int¤¤   taglen, lenlen;
a09f91 ¤   unsigned char¤  ltag = 0x80 + FOUR_BYTE_LEN - 1;
ee1ce3 ¤   Seqorset¤   *next;
6e488a ¤   Seqorset¤   **sos = &ber->ber_sos;
e5af5a
a7d8af ¤   /*
493748 ¤   ·* If this is the toplevel sequence or set, we need to actually
f4d8ad ¤   ·* write the stuff out. ·Otherwise, it's already been put in
b2e4b5 ¤   ·* the appropriate buffer and will be written when the toplevel
0d2221 ¤   ·* one is written. ·In this case all we need to do is update the
760f72 ¤   ·* length and tag.
85a4e3 ¤   ·*/
7caf5a
240e6f ¤   len = (*sos)->sos_clen;
2d6faa ¤   netlen = LBER_HTONL( len );
fbb92a ¤   if ( sizeof(long) > 4 && len > 0xFFFFFFFFL )
c649fa ¤   ¤   return( -1 );
07af5a
7c8fa8 ¤   if ( ber->ber_options & LBER_USE_DER ) {
afc891 ¤   ¤   lenlen = ber_calc_lenlen( len );
eef037 ¤   } else {
43d167 ¤   ¤   lenlen = FOUR_BYTE_LEN;
--ffda 000bdf0a04b40100086 Page 7 of encode.c
a19371 ¤   }
93af5a
dcf38d ¤   if ( (next = (*sos)->sos_next) == NULLSEQORSET ) {
e9ed6d ¤   ¤   /* write the tag */
cc2edc ¤   ¤   if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 )
a98e4f ¤   ¤   ¤   return( -1 );
fbaf5a
dcdd35 ¤   ¤   if ( ber->ber_options & LBER_USE_DER ) {
b8a738 ¤   ¤   ¤   /* Write the length in the minimum # of octets */
1d34db ¤   ¤   ¤   if ( ber_put_len( ber, len, 1 ) == -1 )
a6071b ¤   ¤   ¤   ¤   return( -1 );
1aaf5a
493e33 ¤   ¤   ¤   if (lenlen != FOUR_BYTE_LEN) {
39980e ¤   ¤   ¤   ¤   /*
26de05 ¤   ¤   ¤   ¤   ·* We set aside FOUR_BYTE_LEN bytes for
aa7c7a ¤   ¤   ¤   ¤   ·* the length field. ·Move the data if
b2b3d0 ¤   ¤   ¤   ¤   ·* we don't actually need that much
351020 ¤   ¤   ¤   ¤   ·*/
3f0b30 ¤   ¤   ¤   ¤   SAFEMEMCPY( (*sos)->sos_first + taglen +
38ffaa ¤   ¤   ¤   ¤   ····lenlen, (*sos)->sos_first + taglen +
712b37 ¤   ¤   ¤   ¤   ····FOUR_BYTE_LEN, len );
33a3a6 ¤   ¤   ¤   }
5145a6 ¤   ¤   } else {
16cfbb ¤   ¤   ¤   /* Fill FOUR_BYTE_LEN bytes for length field */
5622a7 ¤   ¤   ¤   /* one byte of length length */
316430 ¤   ¤   ¤   if ( ber_write( ber, (char *)&ltag, 1, 1 ) != 1 )
e7071b ¤   ¤   ¤   ¤   return( -1 );
6baf5a
664146 ¤   ¤   ¤   /* the length itself */
c1f1bb ¤   ¤   ¤   if ( ber_write( ber, (char *) &netlen + sizeof(long)
f79989 ¤   ¤   ¤   ····- (FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1, 1 )
f1a542 ¤   ¤   ¤   ····!= FOUR_BYTE_LEN - 1 )
cf071b ¤   ¤   ¤   ¤   return( -1 );
3d0fe4 ¤   ¤   }
d52a14 ¤   ¤   /* The ber_ptr is at the set/seq start - move it to the end */
066e1a ¤   ¤   (*sos)->sos_ber->ber_ptr += len;
e0f037 ¤   } else {
c339bd ¤   ¤   unsigned long¤  ntag;
f5af5a
28e0e0 ¤   ¤   /* the tag */
89c65f ¤   ¤   taglen = ber_calc_taglen( (*sos)->sos_tag );
04317e ¤   ¤   ntag = LBER_HTONL( (*sos)->sos_tag );
c09a0a ¤   ¤   SAFEMEMCPY( (*sos)->sos_first, (char *) &ntag +
080873 ¤   ¤   ····sizeof(long) - taglen, taglen );
b3af5a
c6dd35 ¤   ¤   if ( ber->ber_options & LBER_USE_DER ) {
f884c9 ¤   ¤   ¤   ltag = (unsigned char) ((lenlen == 1) ? len : 0x80 + (lenlen - 1));
b90fe4 ¤   ¤   }
afaf5a
0baac1 ¤   ¤   /* one byte of length length */
a60a20 ¤   ¤   SAFEMEMCPY( (*sos)->sos_first + 1, &ltag, 1 );
6eaf5a
66dd35 ¤   ¤   if ( ber->ber_options & LBER_USE_DER ) {
800bd7 ¤   ¤   ¤   if (lenlen > 1) {
be8c8d ¤   ¤   ¤   ¤   /* Write the length itself */
131dae ¤   ¤   ¤   ¤   SAFEMEMCPY( (*sos)->sos_first + 2,
ecf2eb ¤   ¤   ¤   ¤   ····(char *)&netlen + sizeof(unsigned long) -
629450 ¤   ¤   ¤   ¤   ····(lenlen - 1),
08304b ¤   ¤   ¤   ¤   ····lenlen - 1 );
34a3a6 ¤   ¤   ¤   }
103e33 ¤   ¤   ¤   if (lenlen != FOUR_BYTE_LEN) {
fe980e ¤   ¤   ¤   ¤   /*
03de05 ¤   ¤   ¤   ¤   ·* We set aside FOUR_BYTE_LEN bytes for
987c7a ¤   ¤   ¤   ¤   ·* the length field. ·Move the data if
b1b3d0 ¤   ¤   ¤   ¤   ·* we don't actually need that much
cc1020 ¤   ¤   ¤   ¤   ·*/
210b30 ¤   ¤   ¤   ¤   SAFEMEMCPY( (*sos)->sos_first + taglen +
f3ffaa ¤   ¤   ¤   ¤   ····lenlen, (*sos)->sos_first + taglen +
f22b37 ¤   ¤   ¤   ¤   ····FOUR_BYTE_LEN, len );
2da3a6 ¤   ¤   ¤   }
af45a6 ¤   ¤   } else {
bd4146 ¤   ¤   ¤   /* the length itself */
--dc06 000151db7c040100086 Page 8 of encode.c
a94717 ¤   ¤   ¤   SAFEMEMCPY( (*sos)->sos_first + taglen + 1,
b6e359 ¤   ¤   ¤   ····(char *) &netlen + sizeof(long) -
bb9b45 ¤   ¤   ¤   ····(FOUR_BYTE_LEN - 1), FOUR_BYTE_LEN - 1 );
f80fe4 ¤   ¤   }
1faf5a
ddb21d ¤   ¤   next->sos_clen += (taglen + lenlen + len);
bab6c7 ¤   ¤   next->sos_ptr += (taglen + lenlen + len);
979371 ¤   }
1caf5a
4669cd ¤   /* we're done with this seqorset, so free it up */
d40bce ¤   free( (char *) (*sos) );
22fbbc ¤   *sos = next;
49af5a
3e150d ¤   return( taglen + lenlen + len );
d6efe6 }
32af5a
bf4d2f int
780c45 ber_put_seq( BerElement *ber )
efbb36 {
188708 ¤   return( ber_put_seqorset( ber ) );
54efe6 }
ceaf5a
024d2f int
43e699 ber_put_set( BerElement *ber )
fdbb36 {
d38708 ¤   return( ber_put_seqorset( ber ) );
82efe6 }
80af5a
ae1338 /* VARARGS */
654d2f int
6ed7fe ber_printf(
9b6479 #if defined(PGPSOCKETSLDAP) || defined( MACOS ) || defined( _WIN32 ) || \
8cf021 ····defined( BC31 ) /* jason */
3debc8 ¤   BerElement *ber, char *fmt, ... )
eed409 #else /* MACOS || _WIN32 || BC31 */
41098e ¤   va_alist )
92b70b va_dcl
f79cc2 #endif /* MACOS || _WIN32 || BC31 */
a4bb36 {
da7be9 ¤   va_list¤¤   ap;
8b6de0 #if !defined(PGPSOCKETSLDAP) && !defined( MACOS ) && !defined( _WIN32 ) && \
d7e250 ····!defined( BC31 ) /* jason */
aa9c95 ¤   BerElement¤ *ber;
081344 ¤   char¤   ¤   *fmt;
a16b3c #endif /* !MACOS && !_WIN32 && !BC31 */
74b1bf ¤   char¤   ¤   *s, **ss;
71b08a ¤   struct berval¤  **bv;
bfa2af ¤   int¤¤   rc, i;
ce93e7 ¤   unsigned long¤  len;
94af5a
c16479 #if defined(PGPSOCKETSLDAP) || defined( MACOS ) || defined( _WIN32 ) || \
72f021 ····defined( BC31 ) /* jason */
97f4c3 ¤   va_start( ap, fmt );
8cd409 #else /* MACOS || _WIN32 || BC31 */
6cf279 ¤   va_start( ap );
d791cf ¤   ber = va_arg( ap, BerElement * );
678c2a ¤   fmt = va_arg( ap, char * );
0a9cc2 #endif /* MACOS || _WIN32 || BC31 */
55af5a
cafc38 ¤   for ( rc = 0; *fmt && rc != -1; fmt++ ) {
2753d3 ¤   ¤   switch ( *fmt ) {
9764f1 ¤   ¤   case 'b':¤  /* boolean */
2d5da2 ¤   ¤   ¤   i = va_arg( ap, int );
35593d ¤   ¤   ¤   rc = ber_put_boolean( ber, i, ber->ber_tag );
58cdcb ¤   ¤   ¤   break;
8eaf5a
cdc4e8 ¤   ¤   case 'i':¤  /* int */
525da2 ¤   ¤   ¤   i = va_arg( ap, int );
044cc0 ¤   ¤   ¤   rc = ber_put_int( ber, i, ber->ber_tag );
1ccdcb ¤   ¤   ¤   break;
0faf5a
15fb06 ¤   ¤   case 'e':¤  /* enumeration */
--1f0d 000cc9b037140100086 Page 9 of encode.c
165da2 ¤   ¤   ¤   i = va_arg( ap, int );
07b317 ¤   ¤   ¤   rc = ber_put_enum( ber, i, ber->ber_tag );
b6cdcb ¤   ¤   ¤   break;
ddaf5a
9186d2 ¤   ¤   case 'n':¤  /* null */
115cf9 ¤   ¤   ¤   rc = ber_put_null( ber, ber->ber_tag );
58cdcb ¤   ¤   ¤   break;
c3af5a
dbae74 ¤   ¤   case 'o':¤  /* octet string (non-null terminated) */
9a1391 ¤   ¤   ¤   s = va_arg( ap, char * );
a7f5b6 ¤   ¤   ¤   len = va_arg( ap, int );
8b76a0 ¤   ¤   ¤   rc = ber_put_ostring( ber, s, len, ber->ber_tag );
57cdcb ¤   ¤   ¤   break;
55af5a
c14c52 ¤   ¤   case 's':¤  /* string */
5a1391 ¤   ¤   ¤   s = va_arg( ap, char * );
c2f58e ¤   ¤   ¤   rc = ber_put_string( ber, s, ber->ber_tag );
59cdcb ¤   ¤   ¤   break;
eeaf5a
773a79 ¤   ¤   case 'B':¤  /* bit string */
6c1391 ¤   ¤   ¤   s = va_arg( ap, char * );
eb9cf2 ¤   ¤   ¤   len = va_arg( ap, int );¤   /* in bits */
27194a ¤   ¤   ¤   rc = ber_put_bitstring( ber, s, len, ber->ber_tag );
8acdcb ¤   ¤   ¤   break;
a9af5a
12f94b ¤   ¤   case 't':¤  /* tag for the next element */
499460 ¤   ¤   ¤   ber->ber_tag = va_arg( ap, unsigned long );
48f29d ¤   ¤   ¤   ber->ber_usertag = 1;
31cdcb ¤   ¤   ¤   break;
16af5a
15b4d1 ¤   ¤   case 'v':¤  /* vector of strings */
2298d9 ¤   ¤   ¤   if ( (ss = va_arg( ap, char ** )) == NULL )
c0f622 ¤   ¤   ¤   ¤   break;
50dcd8 ¤   ¤   ¤   for ( i = 0; ss[i] != NULL; i++ ) {
222326 ¤   ¤   ¤   ¤   if ( (rc = ber_put_string( ber, ss[i],
1ec1de ¤   ¤   ¤   ¤   ····ber->ber_tag )) == -1 )
9214c3 ¤   ¤   ¤   ¤   ¤   break;
ffa3a6 ¤   ¤   ¤   }
e1cdcb ¤   ¤   ¤   break;
38af5a
4087de ¤   ¤   case 'V':¤  /* sequences of strings + lengths */
609420 ¤   ¤   ¤   if ( (bv = va_arg( ap, struct berval ** )) == NULL )
a2f622 ¤   ¤   ¤   ¤   break;
069502 ¤   ¤   ¤   for ( i = 0; bv[i] != NULL; i++ ) {
4d8268 ¤   ¤   ¤   ¤   if ( (rc = ber_put_ostring( ber, bv[i]->bv_val,
065c67 ¤   ¤   ¤   ¤   ····bv[i]->bv_len, ber->ber_tag )) == -1 )
2114c3 ¤   ¤   ¤   ¤   ¤   break;
c8a3a6 ¤   ¤   ¤   }
dbcdcb ¤   ¤   ¤   break;
15af5a
4a5f01 ¤   ¤   case '{':¤  /* begin sequence */
60b12f ¤   ¤   ¤   rc = ber_start_seq( ber, ber->ber_tag );
88cdcb ¤   ¤   ¤   break;
71af5a
dac97d ¤   ¤   case '}':¤  /* end sequence */
e526e2 ¤   ¤   ¤   rc = ber_put_seqorset( ber );
4ccdcb ¤   ¤   ¤   break;
77af5a
508e21 ¤   ¤   case '[':¤  /* begin set */
9e8f6a ¤   ¤   ¤   rc = ber_start_set( ber, ber->ber_tag );
99cdcb ¤   ¤   ¤   break;
16af5a
d772ae ¤   ¤   case ']':¤  /* end set */
7026e2 ¤   ¤   ¤   rc = ber_put_seqorset( ber );
c8cdcb ¤   ¤   ¤   break;
07af5a
4f9ae3 ¤   ¤   default:
7a4eeb #ifndef NO_USERINTERFACE
e63355 ¤   ¤   ¤   fprintf( stderr, "unknown fmt %c\n", *fmt );
6c00a6 #endif /* NO_USERINTERFACE */
6e0c25 ¤   ¤   ¤   rc = -1;
cccdcb ¤   ¤   ¤   break;
--5c18 0014a09134440100086 Page 10 of encode.c
b50fe4 ¤   ¤   }
e6af5a
1f6d99 ¤   ¤   if ( ber->ber_usertag == 0 )
f435db ¤   ¤   ¤   ber->ber_tag = LBER_DEFAULT;
3b0e1d ¤   ¤   else
84a841 ¤   ¤   ¤   ber->ber_usertag = 0;
7e9371 ¤   }
baaf5a
69570e ¤   va_end( ap );
e8af5a
606d62 ¤   return( rc );
4aefe6 }
--1b81 000c99df9e140100087 Page 1 of etest.c
b63fcc /* test.c - lber encoding test program */
aa38e5 /*
c4f590 ·* Copyright (c) 1990 Regents of the University of Michigan.
bf599a ·* All rights reserved.
20495d ·*/
0daf5a
75feb2 #include <stdio.h>
fc324c #include <string.h>
c3c583 #ifdef MACOS
edbea3 #include <stdlib.h>
0e94b4 #include <unix.h>
6b37bc #include <fcntl.h>
20b6ac #include <console.h>
846c94 #else /* MACOS */
c1f15e #include <sys/types.h>
44a394 #ifndef WIN32¤  ¤   /* marcd */
a466f2 #include <sys/socket.h>
827454 #endif
4ce962 #endif /* MACOS */
42b779 #include "lber.h"
16af5a
52bd01 static usage( char *name )
52bb36 {
4e8de2 ¤   fprintf( stderr, "usage: %s fmtstring\n", name );
eeefe6 }
24af5a
79874e main( int argc, char **argv )
70bb36 {
e93eb8 ¤   int¤¤   i, num, len;
71c916 ¤   char¤   ¤   *s, *p;
af66ca ¤   Seqorset¤   *sos = NULLSEQORSET;
749c95 ¤   BerElement¤ *ber;
493067 ¤   Sockbuf¤¤   sb;
5af036 ¤   extern char¤*optarg;
6faf5a
352718 ¤   if ( argc < 2 ) {
3ccf0b ¤   ¤   usage( argv[0] );
3a5691 ¤   ¤   exit( 1 );
7e9371 ¤   }
cdaf5a
e5667d ¤   bzero( &sb, sizeof(sb) );
780d7e ¤   sb.sb_sd = 1;
7fd63d ¤   sb.sb_ber.ber_buf = NULL;
b3af5a
dcc583 #ifdef MACOS
fa242c ¤   ccommand( &argv );
12fadc ¤   cshow( stdout );
bfaf5a
e45850 ·······if (( sb.sb_sd = open( "lber-test", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY ))
3cffa5 ¤   ¤   < 0 ) {
d7fe28 ¤   ····perror( "open" );
04b134 ¤   ····exit( 1 );
a19371 ¤   }
7be962 #endif /* MACOS */
9baf5a
7a07bb ¤   if ( (ber = ber_alloc()) == NULLBER ) {
b6d494 ¤   ¤   perror( "ber_alloc" );
1c5691 ¤   ¤   exit( 1 );
039371 ¤   }
d8af5a
240a09 ¤   num = 7;
bc834d ¤   if ( ber_printf( ber, "{ti}", 0x1f44, num ) == -1 ) {
3810af ¤   ¤   fprintf( stderr, "ber_printf returns -1" );
2b5691 ¤   ¤   exit( 1 );
299371 ¤   }
c9af5a
654025 ¤   if ( ber_flush( &sb, ber, 1 ) == -1 ) {
72ce6c ¤   ¤   perror( "ber_flush" );
475691 ¤   ¤   exit( 1 );
959371 ¤   }
1259ea #ifdef notdef
c91c85 ¤   for ( s = argv[1]; *s; s++ ) {
--5e2e 0000e335b7240100087 Page 2 of etest.c
75ffad ¤   ¤   if ( fgets( buf, sizeof(buf), stdin ) == NULL )
51cdcb ¤   ¤   ¤   break;
7421cf ¤   ¤   if ( (p = strchr( buf, '\n' )) != NULL )
a204fe ¤   ¤   ¤   *p = '\0';
97af5a
c77500 ¤   ¤   switch ( *s ) {
d0c4e8 ¤   ¤   case 'i':¤  /* int */
5564f1 ¤   ¤   case 'b':¤  /* boolean */
b069c3 ¤   ¤   ¤   i = atoi( buf );
5bda2b ¤   ¤   ¤   if ( ber_printf( ber, "i", i ) == -1 ) {
36d815 ¤   ¤   ¤   ¤   fprintf( stderr, "ber_printf i\n" );
938f99 ¤   ¤   ¤   ¤   exit( 1 );
20a3a6 ¤   ¤   ¤   }
7ccdcb ¤   ¤   ¤   break;
d3af5a
82fb06 ¤   ¤   case 'e':¤  /* enumeration */
325da2 ¤   ¤   ¤   i = va_arg( ap, int );
81175f ¤   ¤   ¤   rc = ber_put_enum( ber, i, (char)ber->ber_tag );
eacdcb ¤   ¤   ¤   break;
2eaf5a
ef86d2 ¤   ¤   case 'n':¤  /* null */
27edf4 ¤   ¤   ¤   rc = ber_put_null( ber, (char)ber->ber_tag );
3ccdcb ¤   ¤   ¤   break;
b5af5a
02ae74 ¤   ¤   case 'o':¤  /* octet string (non-null terminated) */
c11391 ¤   ¤   ¤   s = va_arg( ap, char * );
1bf5b6 ¤   ¤   ¤   len = va_arg( ap, int );
bba4df ¤   ¤   ¤   rc = ber_put_ostring( ber, s, len, (char)ber->ber_tag );
85cdcb ¤   ¤   ¤   break;
e6af5a
b94c52 ¤   ¤   case 's':¤  /* string */
461391 ¤   ¤   ¤   s = va_arg( ap, char * );
bb8f84 ¤   ¤   ¤   rc = ber_put_string( ber, s, (char)ber->ber_tag );
e5cdcb ¤   ¤   ¤   break;
26af5a
c03a79 ¤   ¤   case 'B':¤  /* bit string */
551391 ¤   ¤   ¤   s = va_arg( ap, char * );
a89cf2 ¤   ¤   ¤   len = va_arg( ap, int );¤   /* in bits */
42c48d ¤   ¤   ¤   rc = ber_put_bitstring( ber, s, len, (char)ber->ber_tag );
9ecdcb ¤   ¤   ¤   break;
35af5a
e5f94b ¤   ¤   case 't':¤  /* tag for the next element */
842503 ¤   ¤   ¤   ber->ber_tag = va_arg( ap, int );
71f29d ¤   ¤   ¤   ber->ber_usertag = 1;
efcdcb ¤   ¤   ¤   break;
c3af5a
f5b4d1 ¤   ¤   case 'v':¤  /* vector of strings */
d498d9 ¤   ¤   ¤   if ( (ss = va_arg( ap, char ** )) == NULL )
78f622 ¤   ¤   ¤   ¤   break;
fddcd8 ¤   ¤   ¤   for ( i = 0; ss[i] != NULL; i++ ) {
8a2326 ¤   ¤   ¤   ¤   if ( (rc = ber_put_string( ber, ss[i],
4d3618 ¤   ¤   ¤   ¤   ····(char)ber->ber_tag )) == -1 )
4b14c3 ¤   ¤   ¤   ¤   ¤   break;
6fa3a6 ¤   ¤   ¤   }
6ecdcb ¤   ¤   ¤   break;
6baf5a
3a87de ¤   ¤   case 'V':¤  /* sequences of strings + lengths */
8b9420 ¤   ¤   ¤   if ( (bv = va_arg( ap, struct berval ** )) == NULL )
d5f622 ¤   ¤   ¤   ¤   break;
cf9502 ¤   ¤   ¤   for ( i = 0; bv[i] != NULL; i++ ) {
c48268 ¤   ¤   ¤   ¤   if ( (rc = ber_put_ostring( ber, bv[i]->bv_val,
a69378 ¤   ¤   ¤   ¤   ····bv[i]->bv_len, (char)ber->ber_tag )) == -1 )
3a14c3 ¤   ¤   ¤   ¤   ¤   break;
b4a3a6 ¤   ¤   ¤   }
04cdcb ¤   ¤   ¤   break;
d0af5a
da5f01 ¤   ¤   case '{':¤  /* begin sequence */
f5e75f ¤   ¤   ¤   rc = ber_start_seq( ber, (char)ber->ber_tag );
36cdcb ¤   ¤   ¤   break;
1daf5a
d3c97d ¤   ¤   case '}':¤  /* end sequence */
0e26e2 ¤   ¤   ¤   rc = ber_put_seqorset( ber );
--078c 00173b63e9940100087 Page 3 of etest.c
7ecdcb ¤   ¤   ¤   break;
f8af5a
6e8e21 ¤   ¤   case '[':¤  /* begin set */
9f4460 ¤   ¤   ¤   rc = ber_start_set( ber, (char)ber->ber_tag );
a3cdcb ¤   ¤   ¤   break;
b2af5a
7572ae ¤   ¤   case ']':¤  /* end set */
2c26e2 ¤   ¤   ¤   rc = ber_put_seqorset( ber );
2bcdcb ¤   ¤   ¤   break;
59af5a
d09ae3 ¤   ¤   default:
4c4eeb #ifndef NO_USERINTERFACE
743355 ¤   ¤   ¤   fprintf( stderr, "unknown fmt %c\n", *fmt );
2100a6 #endif /* NO_USERINTERFACE */
fa0c25 ¤   ¤   ¤   rc = -1;
f3cdcb ¤   ¤   ¤   break;
7f0fe4 ¤   ¤   }
5d0fe4 ¤   ¤   }
749371 ¤   }
daaf5a
6a7454 #endif
b8af5a
98ea61 ¤   return( 0 );
73efe6 }
--9473 0016781242040100088 Page 1 of idtest.c
527555 /* idtest.c - ber decoding test program using isode libraries */
2238e5 /*
b7f590 ·* Copyright (c) 1990 Regents of the University of Michigan.
aa599a ·* All rights reserved.
f0775e ·*
81b855 ·* Redistribution and use in source and binary forms are permitted
c39795 ·* provided that this notice is preserved and that due credit is given
851873 ·* to the University of Michigan at Ann Arbor. The name of the University
8b8805 ·* may not be used to endorse or promote products derived from this
2b74fe ·* software without specific prior written permission. This software
242a32 ·* is provided ``as is'' without express or implied warranty.
f7495d ·*/
b7af5a
c0feb2 #include <stdio.h>
6ae32b #include <psap.h>
60c999 #include <quipu/attr.h>
d5af5a
9dbd01 static usage( char *name )
30bb36 {
6a21e0 ¤   fprintf( stderr, "usage: %s\n", name );
e2efe6 }
a6af5a
96874e main( int argc, char **argv )
c2bb36 {
715b36 ¤   PE¤ pe;
ca2183 ¤   PS¤ psin, psout, pserr;
edaf5a
7833cb ¤   /* read the pe from standard in */
2fcaf9 ¤   if ( (psin = ps_alloc( std_open )) == NULLPS ) {
789df2 ¤   ¤   perror( "ps_alloc" );
935691 ¤   ¤   exit( 1 );
529371 ¤   }
96b212 ¤   if ( std_setup( psin, stdin ) == NOTOK ) {
62ed7d ¤   ¤   perror( "std_setup" );
155691 ¤   ¤   exit( 1 );
e29371 ¤   }
1dc9c6 ¤   /* write the pe to standard out */
31efa8 ¤   if ( (psout = ps_alloc( std_open )) == NULLPS ) {
379df2 ¤   ¤   perror( "ps_alloc" );
9b5691 ¤   ¤   exit( 1 );
919371 ¤   }
cb023e ¤   if ( std_setup( psout, stdout ) == NOTOK ) {
cfed7d ¤   ¤   perror( "std_setup" );
c05691 ¤   ¤   exit( 1 );
ba9371 ¤   }
52749d ¤   /* pretty print it to standard error */
f67b5e ¤   if ( (pserr = ps_alloc( std_open )) == NULLPS ) {
059df2 ¤   ¤   perror( "ps_alloc" );
525691 ¤   ¤   exit( 1 );
0b9371 ¤   }
90417e ¤   if ( std_setup( pserr, stderr ) == NOTOK ) {
71ed7d ¤   ¤   perror( "std_setup" );
0b5691 ¤   ¤   exit( 1 );
a49371 ¤   }
deaf5a
45a290 ¤   while ( (pe = ps2pe( psin )) != NULLPE ) {
0f430b ¤   ¤   pe2pl( pserr, pe );
bc7766 ¤   ¤   pe2ps( psout, pe );
ac9371 ¤   }
0daf5a
ddbf76 ¤   exit( 0 );
67efe6 }
--4a8f 00011df0ceb40100089 Page 1 of io.c
992a3a /* io.c - ber general i/o routines */
1138e5 /*
e7f590 ·* Copyright (c) 1990 Regents of the University of Michigan.
c7599a ·* All rights reserved.
e0775e ·*
d3b855 ·* Redistribution and use in source and binary forms are permitted
ab9795 ·* provided that this notice is preserved and that due credit is given
521873 ·* to the University of Michigan at Ann Arbor. The name of the University
898805 ·* may not be used to endorse or promote products derived from this
d874fe ·* software without specific prior written permission. This software
a92a32 ·* is provided ``as is'' without express or implied warranty.
07495d ·*/
67af5a
7efeb2 #include <stdio.h>
69b1cb #include <ctype.h>
4baf5a
2f71fa #if PGPSOCKETSLDAP¤ ¤   /* jason */
bf65aa #include "pgpSocketsLDAP.h"
74af5a
75db21 #else
be1157 #if defined( DOS )
34f2ef #include "msdos.h"
620cf5 #endif /* DOS || _WIN32 */
62af5a
cdc583 #ifdef MACOS
e0bea3 #include <stdlib.h>
9a65e0 #include "macos.h"
ed6c94 #else /* MACOS */
15dccb #if defined(NeXT) || defined(VMS)
97bea3 #include <stdlib.h>
bb2192 #else /* next || vms */
5b5e84 #include <malloc.h>
b855ca #endif /* next || vms */
1c495d #include <errno.h>
e9f15e #include <sys/types.h>
c30818 #ifndef WIN32¤  ¤   ¤   /* marcd */
0b66f2 #include <sys/socket.h>
a66c19 #include <netinet/in.h>
f27454 #endif
98b3f5 #ifdef PCNFS
ca5f02 #include <tklib.h>
891b77 #endif /* PCNFS */
f7e962 #endif /* MACOS */
8eaf5a
d8ea1a #ifndef VMS
8ac737 #include <memory.h>
c57454 #endif
6baf5a
d9ec08 #ifdef _WIN32
682d5f #include <winsock.h>
7e1044 #include <io.h>
b0a1f1 #define EMSGSIZE ···············WSAEMSGSIZE
151ad7 #endif /* _WIN32 */
e8c86d #endif¤ /* PGPSOCKETSLDAP */
caaf5a
42324c #include <string.h>
52b779 #include "lber.h"
31af5a
dccf14 #ifdef PGPKEYSERVER
cebdea #include "pgpSrvGlobals.h"
f67454 #endif
03af5a
48504c #ifdef NEEDPROTOS
9b1405 static int ber_realloc( BerElement *ber, unsigned long len );
b236bc static int ber_filbuf( Sockbuf *sb, long len );
baadd6 static long BerRead( Sockbuf *sb, char *buf, long len );
88b3f5 #ifdef PCNFS
1e8a1e static int BerWrite( Sockbuf *sb, char *buf, long len );
391b77 #endif /* PCNFS */
3bdb21 #else
06f0a8 int ber_filbuf();
1124c6 long BerRead();
--2f86 000460fda9a40100089 Page 2 of io.c
8f6037 static int ber_realloc();
378634 #endif /* NEEDPROTOS */
9baf5a
145a66 #define bergetc( sb, len ) ···( sb->sb_ber.ber_end > sb->sb_ber.ber_ptr ? \
b4ba69 ¤   ¤   ¤   ··(unsigned char)*sb->sb_ber.ber_ptr++ : \
cf834f ¤   ¤   ¤   ··ber_filbuf( sb, len ))
43af5a
6871fa #if PGPSOCKETSLDAP¤ ¤   /* jason */
ace79c #define read( s, b, l ) ¤   PGPReceive( s, b, l, kPGPReceiveFlagNone )
738039 #define MAX_WRITE¤  MAX_PGPInt32
282c46 #define BerWrite( sb, b, l ) ··PGPSend( sb->sb_sd, b, l, kPGPSendFlagNone )
9eaf5a
f8db21 #else
9bc583 #ifdef MACOS
5938e5 /*
5f7ff2 ·* MacTCP/OpenTransport
2c495d ·*/
7ae79c #define read( s, b, l ) ¤   PGPReceive( s, b, l, kPGPReceiveFlagNone )
808039 #define MAX_WRITE¤  MAX_PGPInt32
b02c46 #define BerWrite( sb, b, l ) ··PGPSend( sb->sb_sd, b, l, kPGPSendFlagNone )
986c94 #else /* MACOS */
ab01b0 #ifdef DOS
7fb3f5 #ifdef PCNFS
b038e5 /*
4e0cf4 ·* PCNFS (under DOS)
ad495d ·*/
728ad5 #define read( s, b, l ) recv( s, b, l, 0 )
925c91 #define BerWrite( s, b, l ) send( s->sb_sd, b, (int) l, 0 )
551b77 #endif /* PCNFS */
516382 #ifdef NCSA
3938e5 /*
f4901e ·* NCSA Telnet TCP/IP stack (under DOS)
e7495d ·*/
efe7a3 #define read( s, b, l ) nread( s, b, l )
72700b #define BerWrite( s, b, l ) netwrite( s->sb_sd, b, l )
8e8682 #endif /* NCSA */
73a184 #ifdef WINSOCK
0938e5 /*
a82c69 ·* Windows Socket API (under DOS/Windows 3.x)
1b495d ·*/
0e8ad5 #define read( s, b, l ) recv( s, b, l, 0 )
0e2114 #define BerWrite( s, b, l ) send( s->sb_sd, b, l, 0 )
36d50d #endif /* WINSOCK */
c4aad8 #else /* DOS */
9cec08 #ifdef _WIN32
b838e5 /*
4c12cc ·* 32-bit Windows Socket API (under Windows NT or Windows 95)
46495d ·*/
b72f1c #define read( s, b, l )¤¤   recv( s, b, l, 0 )
4e068d #define BerWrite( s, b, l )¤send( s->sb_sd, b, l, 0 )
8188eb #else /* _WIN32 */
944edf #ifdef VMS
f438e5 /*
2eb38f ·* VMS -- each write must be 64K or smaller
50495d ·*/
b97017 #define MAX_WRITE 65535
dfe991 #define BerWrite( sb, b, l ) write( sb->sb_sd, b, (l<MAX_WRITE)? l : MAX_WRITE)
ba20fc #else /* VMS */
f438e5 /*
3a13d3 ·* everything else (Unix/BSD 4.3 socket API)
3d495d ·*/
2200a6 #define BerWrite( sb, b, l )¤   write( sb->sb_sd, b, l )
23361d #endif /* VMS */
cf1a04 #define udp_read( sb, b, l, al ) recvfrom(sb->sb_sd, (char *)b, l, 0, \
e4d481 ¤   ¤   (struct sockaddr *)sb->sb_fromaddr, \
fc1e57 ¤   ¤   (al = sizeof(struct sockaddr), &al))
52710e #define udp_write( sb, b, l ) sendto(sb->sb_sd, (char *)(b), l, 0, \
38b84f ¤   ¤   (struct sockaddr *)sb->sb_useaddr, sizeof(struct sockaddr))
7d1ad7 #endif /* _WIN32 */
19bc39 #endif /* DOS */
17e962 #endif /* MACOS */
46df0f #endif /* PGPSOCKETSLDAP */
--5c43 00048e46cf140100089 Page 3 of io.c
e0af5a
fd323c #ifndef udp_read
abe121 #define udp_read( sb, b, l, al )¤   CLDAP NOT SUPPORTED
25b5fb #define udp_write( sb, b, l )¤  ¤   CLDAP NOT SUPPORTED
a52369 #endif /* udp_read */
4daf5a
4c95bf #define EXBUFSIZ¤   1024
13af5a
1f4d2f int
6caf6e ber_filbuf( Sockbuf *sb, long len )
7ebb36 {
c9c7a1 ¤   short¤  rc;
25ed07 #ifdef CLDAP
9ad2fe ¤   int¤addrlen;
f26b1c #endif /* CLDAP */
40af5a
a66ed0 ¤   if ( sb->sb_ber.ber_buf == NULL ) {
39a860 ¤   ¤   if ( (sb->sb_ber.ber_buf = (char *) malloc( READBUFSIZ )) ==
56df29 ¤   ¤   ····NULL )
448e4f ¤   ¤   ¤   return( -1 );
9a4a30 ¤   ¤   sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf;
8e3cdd ¤   ¤   sb->sb_ber.ber_end = sb->sb_ber.ber_buf;
d39371 ¤   }
91af5a
9e5ebb ¤   if ( sb->sb_naddr > 0 ) {
fced07 #ifdef CLDAP
9b3c27 ¤   ¤   rc = udp_read(sb, sb->sb_ber.ber_buf, READBUFSIZ, addrlen );
5d2639 #ifdef LDAP_DEBUG
431814 ¤   ¤   if ( lber_debug ) {
33aa67 ¤   ¤   ¤   fprintf( stderr, "ber_filbuf udp_read %d bytes\n",
7513f6 ¤   ¤   ¤   ¤   rc );
d8d6ae ¤   ¤   ¤   if ( lber_debug > 1 && rc > 0 )
ce5ec0 ¤   ¤   ¤   ¤   lber_bprint( sb->sb_ber.ber_buf, rc );
5e0fe4 ¤   ¤   }
129b45 #endif /* LDAP_DEBUG */
78eeea #else /* CLDAP */
ee4dae ¤   ¤   rc = -1;
af6b1c #endif /* CLDAP */
b7f037 ¤   } else {
baaf5a
89cf14 #ifdef PGPKEYSERVER
d0af5a
0f244c ¤   ¤   PGPSocketsTimeValue¤timeWait;
28402c ¤   ¤   PGPSocketSet¤   ¤   ReadFDSet;
1eaf5a
64db80 ¤   ¤   if (!sb->sb_bTLS) {
2dec2d ¤   ¤   ¤   timeWait.tv_sec = pgpMax(g->timeTimeLimit * 2, 300);
863ebc ¤   ¤   ¤   timeWait.tv_usec = 0;
9f1bfc ¤   ¤   ¤   PGPSOCKETSET_ZERO(&ReadFDSet);
1f4d1b ¤   ¤   ¤   PGPSOCKETSET_SET(sb->sb_sd, &ReadFDSet);
d17d02 ¤   ¤   ¤   rc = PGPSelect(SocketRefToSocketNumber(sb->sb_sd) + 1, &ReadFDSet,·
44946e ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL, &timeWait);
6ea0b4 ¤   ¤   ¤   if (rc == 0)
1aef9c ¤   ¤   ¤   ¤   return kPGPError_SocketsTimedOut;
2b8722 ¤   ¤   ¤   else if (rc < 0)
70dd34 ¤   ¤   ¤   ¤   return -1;
e60fe4 ¤   ¤   }
aaaf5a
6a7454 #endif
daaf5a
1d1f71 ¤   ¤   rc = read( sb->sb_sd, sb->sb_ber.ber_buf,
362657 ¤   ¤   ····((sb->sb_options & LBER_NO_READ_AHEAD) &&
d9c54e ¤   ¤   ····(len < READBUFSIZ)) ?
7392d0 ¤   ¤   ····len : READBUFSIZ );
81dabf ¤   ¤   ····
690d89 #if defined(WIN32) && !defined(PGPSOCKETSLDAP) /* jason */
2399c2 ¤   ¤   if (rc == -1)
975b34 ¤   ¤   {
1d9962 ¤   ¤   ¤   errno = WSAGetLastError();
2c0fe4 ¤   ¤   }
2f7454 #endif
489371 ¤   }
--aa1c 00059aaa9cf40100089 Page 4 of io.c
e0af5a
5eb0e9 ¤   if ( rc > 0 ) {
f793cf ¤   ¤   sb->sb_ber.ber_ptr = sb->sb_ber.ber_buf + 1;
d00e5e ¤   ¤   sb->sb_ber.ber_end = sb->sb_ber.ber_buf + rc;
0c62fb ¤   ¤   return( (unsigned char)*sb->sb_ber.ber_buf );
cf9371 ¤   }
37af5a
137360 ¤   return( -1 );
c0efe6 }
39af5a
daaf5a
296fcf long
bebf12 BerRead( Sockbuf *sb, char *buf, long len )
90bb36 {
c4675c ¤   int¤c;
cb101d ¤   long¤   nread = 0;
48af5a
f51456 ¤   while ( len > 0 ) {
db0dbe ¤   ¤   if ( (c = bergetc( sb, len )) < 0 ) {
6ba00f ¤   ¤   ¤   if ( nread > 0 )
14f622 ¤   ¤   ¤   ¤   break;
787295 ¤   ¤   ¤   return( c );
f80fe4 ¤   ¤   }
b99d99 ¤   ¤   *buf++ = c;
353fa5 ¤   ¤   nread++;
bfe1e8 ¤   ¤   len--;
749371 ¤   }
47af5a
4b3a9e ¤   return( nread );
9befe6 }
07af5a
f9af5a
576fcf long
2b50bf ber_read( BerElement *ber, char *buf, unsigned long len )
26bb36 {
ebad70 ¤   unsigned long¤  actuallen, nleft;
15af5a
7a77de ¤   nleft = ber->ber_end - ber->ber_ptr;
6c2aa8 ¤   actuallen = nleft < len ? nleft : len;
3eaf5a
f0d3a3 ¤   SAFEMEMCPY( buf, ber->ber_ptr, (size_t)actuallen );
b7af5a
83d77b ¤   ber->ber_ptr += actuallen;
79af5a
ba2b49 ¤   return( (long)actuallen );
93efe6 }
9daf5a
4f6fcf long
832510 ber_write( BerElement *ber, char *buf, unsigned long len, int nosos )
59bb36 {
b38b80 ¤   if ( nosos || ber->ber_sos == NULL ) {
26b3b0 ¤   ¤   if ( ber->ber_ptr + len > ber->ber_end ) {
819e34 ¤   ¤   ¤   if ( ber_realloc( ber, len ) != 0 )
91071b ¤   ¤   ¤   ¤   return( -1 );
710fe4 ¤   ¤   }
382e82 ¤   ¤   SAFEMEMCPY( ber->ber_ptr, buf, (size_t)len );
332a33 ¤   ¤   ber->ber_ptr += len;
d33976 ¤   ¤   return( len );
37f037 ¤   } else {
d25583 ¤   ¤   if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) {
d59e34 ¤   ¤   ¤   if ( ber_realloc( ber, len ) != 0 )
15071b ¤   ¤   ¤   ¤   return( -1 );
ea0fe4 ¤   ¤   }
fff908 ¤   ¤   SAFEMEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len );
ff8331 ¤   ¤   ber->ber_sos->sos_ptr += len;
5c0611 ¤   ¤   ber->ber_sos->sos_clen += len;
ad3976 ¤   ¤   return( len );
5d9371 ¤   }
9eefe6 }
06af5a
63beb7 static int
595ba8 ber_realloc( BerElement *ber, unsigned long len )
--75c8 00027bedf4640100089 Page 5 of io.c
2cbb36 {
0c7452 ¤   unsigned long¤  need, have, total;
b5762c ¤   Seqorset¤   *s;
854e7a ¤   long¤   ¤   off;
5d49f6 ¤   char¤   ¤   *oldbuf;
24af5a
d0c97c ¤   have = (ber->ber_end - ber->ber_buf) / EXBUFSIZ;
a1e4e2 ¤   need = (len < EXBUFSIZ ? 1 : (len + (EXBUFSIZ - 1)) / EXBUFSIZ);
fc2b03 ¤   total = have * EXBUFSIZ + need * EXBUFSIZ;
38af5a
67092d ¤   oldbuf = ber->ber_buf;
e1af5a
9174e8 ¤   if ( ber->ber_buf == NULL ) {
8614a3 ¤   ¤   if ( (ber->ber_buf = (char *) malloc( (size_t)total )) == NULL )
d68e4f ¤   ¤   ¤   return( -1 );
dc9ab3 ¤   } else if ( (ber->ber_buf = (char *) realloc( ber->ber_buf,
895ba5 ¤   ····(size_t)total )) == NULL )
f249fa ¤   ¤   return( -1 );
31af5a
f75b1e ¤   ber->ber_end = ber->ber_buf + total;
22af5a
7cd8af ¤   /*
cfff29 ¤   ·* If the stinking thing was moved, we need to go through and
210ee4 ¤   ·* reset all the sos and ber pointers. ·Offsets would've been
34edf4 ¤   ·* a better idea... oh well.
ada4e3 ¤   ·*/
b3af5a
52c028 ¤   if ( ber->ber_buf != oldbuf ) {
c1a619 ¤   ¤   ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf);
3caf5a
fa3ab0 ¤   ¤   for ( s = ber->ber_sos; s != NULLSEQORSET; s = s->sos_next ) {
c00832 ¤   ¤   ¤   off = s->sos_first - oldbuf;
9b5a93 ¤   ¤   ¤   s->sos_first = ber->ber_buf + off;
49af5a
94a86d ¤   ¤   ¤   off = s->sos_ptr - oldbuf;
35874e ¤   ¤   ¤   s->sos_ptr = ber->ber_buf + off;
110fe4 ¤   ¤   }
a99371 ¤   }
4daf5a
bfea61 ¤   return( 0 );
7befe6 }
90af5a
62314a void
0181a6 ber_free( BerElement *ber, int freebuf )
50bb36 {
7ddcb3 ¤   if ( freebuf && ber->ber_buf != NULL )
514abb ¤   ¤   free( ber->ber_buf );
e6a573 ¤   free( (char *) ber );
61efe6 }
9daf5a
3e4d2f int
6f9cd2 ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
c5bb36 {
ccd92d ¤   long¤   nwritten, towrite, rc;
94af5a
f7b183 ¤   if ( ber->ber_rwptr == NULL ) {
ca2559 ¤   ¤   ber->ber_rwptr = ber->ber_buf;
cd9371 ¤   }
fa2a80 ¤   towrite = ber->ber_ptr - ber->ber_rwptr;
09af5a
382639 #ifdef LDAP_DEBUG
90ee71 ¤   if ( lber_debug ) {
a28704 ¤   ¤   fprintf( stderr, "ber_flush: %ld bytes to sd %ld%s\n", towrite,
7aaee5 ¤   ¤   ····sb->sb_sd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)"
3bbd6c ¤   ¤   ····: "" );
c6d170 ¤   ¤   if ( lber_debug > 1 )
13efec ¤   ¤   ¤   lber_bprint( ber->ber_rwptr, towrite );
ae9371 ¤   }
7c7454 #endif
beae9d #if !defined(MACOS) && !defined(DOS) && !defined(PGPSOCKETSLDAP) /* jason */
b84fa1 ¤   if ( sb->sb_options & (LBER_TO_FILE | LBER_TO_FILE_ONLY) ) {
271fd5 ¤   ¤   rc = write( sb->sb_fd, ber->ber_buf, towrite );
--c767 0002cd27a8d40100089 Page 6 of io.c
cf9dde ¤   ¤   if ( sb->sb_options & LBER_TO_FILE_ONLY ) {
4347a6 ¤   ¤   ¤   return( (int)rc );
150fe4 ¤   ¤   }
ce9371 ¤   }
127454 #endif
90af5a
9e4a89 ¤   nwritten = 0;
d243ab ¤   do {
ea681b ¤   ¤   if (sb->sb_naddr > 0) {
c4ed07 #ifdef CLDAP
f0e569 ¤   ¤   ¤   rc = udp_write( sb, ber->ber_buf + nwritten,
884a15 ¤   ¤   ¤   ····(size_t)towrite );
1aeeea #else /* CLDAP */
200c25 ¤   ¤   ¤   rc = -1;
806b1c #endif /* CLDAP */
7d8dda ¤   ¤   ¤   if ( rc <= 0 )
1a071b ¤   ¤   ¤   ¤   return( -1 );
d5e2b6 ¤   ¤   ¤   /* fake error if write was not atomic */
80f795 ¤   ¤   ¤   if (rc < towrite) {
81afd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
c8bec5 ¤   ¤   ¤   ····errno = EMSGSIZE;
967454 #endif
e295e0 ¤   ¤   ¤   ····return( -1 );
9ea3a6 ¤   ¤   ¤   }
ef45a6 ¤   ¤   } else {
6e3e80 ¤   ¤   ¤   if ( (rc = BerWrite( sb, ber->ber_rwptr, towrite )) <= 0 ) {
650d89 #if defined(WIN32) && !defined(PGPSOCKETSLDAP) /* jason */
c7972e ¤   ¤   ¤   ¤   errno = WSAGetLastError();
0f7454 #endif
de071b ¤   ¤   ¤   ¤   return( -1 );
40a3a6 ¤   ¤   ¤   }
1a0fe4 ¤   ¤   }
502487 ¤   ¤   towrite -= rc;
e66982 ¤   ¤   nwritten += rc;
20195e ¤   ¤   ber->ber_rwptr += rc;
5efb5e ¤   } while ( towrite > 0 );
6caf5a
e091a1 ¤   if ( freeit )
fe1ab1 ¤   ¤   ber_free( ber, 1 );
61af5a
b2ea61 ¤   return( 0 );
77efe6 }
b6af5a
b23ab9 BerElement *
ed1f2c ber_alloc_t( int options )
79bb36 {
939c95 ¤   BerElement¤ *ber;
8faf5a
c4fbed ¤   if ( (ber = (BerElement *) calloc( 1, sizeof(BerElement) )) == NULLBER )
b05440 ¤   ¤   return( NULLBER );
c50d5e ¤   ber->ber_tag = LBER_DEFAULT;
c78c0a ¤   ber->ber_options = options;
03af5a
8947ce ¤   return( ber );
70efe6 }
caaf5a
2b3ab9 BerElement *
b1ba27 ber_alloc()
d0bb36 {
7afb87 ¤   return( ber_alloc_t( 0 ) );
feefe6 }
afaf5a
2d3ab9 BerElement *
05bdea der_alloc()
febb36 {
43ee67 ¤   return( ber_alloc_t( LBER_USE_DER ) );
78efe6 }
e4af5a
623ab9 BerElement *
809f1a ber_dup( BerElement *ber )
8fbb36 {
2cd218 ¤   BerElement¤ *new;
--0b64 00059437c1840100089 Page 7 of io.c
e0af5a
1d1651 ¤   if ( (new = ber_alloc()) == NULLBER )
b05440 ¤   ¤   return( NULLBER );
c3af5a
3e7fe9 ¤   *new = *ber;
82af5a
6dd000 ¤   return( new );
dcefe6 }
09af5a
76af5a
21314a void
8edc94 ber_init( BerElement *ber, int options )
72bb36 {
29d0f8 ¤   (void) memset( (char *)ber, '\0', sizeof( BerElement ));
c00d5e ¤   ber->ber_tag = LBER_DEFAULT;
3c8c0a ¤   ber->ber_options = options;
f0efe6 }
d0af5a
47af5a
bf314a void
120de7 ber_reset( BerElement *ber, int was_writing )
f4bb36 {
18deef ¤   if ( was_writing ) {
c6f21d ¤   ¤   ber->ber_end = ber->ber_ptr;
889163 ¤   ¤   ber->ber_ptr = ber->ber_buf;
51f037 ¤   } else {
d917b3 ¤   ¤   ber->ber_ptr = ber->ber_end;
9e9371 ¤   }
92af5a
caad8c ¤   ber->ber_rwptr = NULL;
23efe6 }
dbaf5a
0caf5a
792639 #ifdef LDAP_DEBUG
edaf5a
82314a void
a4ce51 ber_dump( BerElement *ber, int inout )
42bb36 {
25edd4 ¤   fprintf( stderr, "ber_dump: buf 0x%lx, ptr 0x%lx, end 0x%lx\n",
d3ea21 ¤   ····ber->ber_buf, ber->ber_ptr, ber->ber_end );
924417 ¤   if ( inout == 1 ) {
8ad543 ¤   ¤   fprintf( stderr, " ·········current len %ld, contents:\n",
d84766 ¤   ¤   ····ber->ber_end - ber->ber_ptr );
1208f9 ¤   ¤   lber_bprint( ber->ber_ptr, ber->ber_end - ber->ber_ptr );
58f037 ¤   } else {
35d543 ¤   ¤   fprintf( stderr, " ·········current len %ld, contents:\n",
017c2f ¤   ¤   ····ber->ber_ptr - ber->ber_buf );
3480bc ¤   ¤   lber_bprint( ber->ber_buf, ber->ber_ptr - ber->ber_buf );
f49371 ¤   }
69efe6 }
6baf5a
f4314a void
be8e5e ber_sos_dump( Seqorset *sos )
23bb36 {
827657 ¤   fprintf( stderr, "*** sos dump ***\n" );
fb894d ¤   while ( sos != NULLSEQORSET ) {
8431cf ¤   ¤   fprintf(stderr,"ber_sos_dump: clen %ld first 0x%lx ptr 0x%lx\n",
82acfe ¤   ¤   ····sos->sos_clen, sos->sos_first, sos->sos_ptr );
482cc3 ¤   ¤   fprintf( stderr, " ·············current len %ld contents:\n",
91a310 ¤   ¤   ····sos->sos_ptr - sos->sos_first );
e52af4 ¤   ¤   lber_bprint( sos->sos_first, sos->sos_ptr - sos->sos_first );
32af5a
19e872 ¤   ¤   sos = sos->sos_next;
309371 ¤   }
f2f9f0 ¤   fprintf( stderr, "*** end dump ***\n" );
e8efe6 }
52af5a
337454 #endif
beaf5a
f7772b /* return the tag - LBER_DEFAULT returned means trouble */
19006a static unsigned long
594fee get_tag( Sockbuf *sb )
--25e8 0005a1dfff340100089 Page 8 of io.c
2cbb36 {
7e23b7 ¤   unsigned char¤  xbyte;
ca9375 ¤   unsigned long¤  tag;
51f079 ¤   char¤   ¤   *tagp;
62e595 ¤   int¤¤   i;
abaf5a
45655f ¤   if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
1cc117 ¤   ¤   return( LBER_DEFAULT );
7aaf5a
c399d3 ¤   if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
099211 ¤   ¤   return( (unsigned long) xbyte );
bcaf5a
593fc6 ¤   tagp = (char *) &tag;
d7a313 ¤   tagp[0] = xbyte;
172bac ¤   for ( i = 1; i < sizeof(long); i++ ) {
c9cb5e ¤   ¤   if ( BerRead( sb, (char *) &xbyte, 1 ) != 1 )
e44aeb ¤   ¤   ¤   return( LBER_DEFAULT );
a3af5a
1edfc3 ¤   ¤   tagp[i] = xbyte;
3aaf5a
eb14bd ¤   ¤   if ( ! (xbyte & LBER_MORE_TAG_MASK) )
afcdcb ¤   ¤   ¤   break;
e99371 ¤   }
99af5a
2f477b ¤   /* tag too big! */
5126a5 ¤   if ( i == sizeof(long) )
0cc117 ¤   ¤   return( LBER_DEFAULT );
1aaf5a
8d3789 ¤   /* want leading, not trailing 0's */
9a34dd ¤   return( tag >> (sizeof(long) - i - 1) );
66efe6 }
24af5a
06e5f9 unsigned long
461ead ber_get_next( Sockbuf *sb, unsigned long *len, BerElement *ber )
a5bb36 {
0a6488 ¤   unsigned long¤  tag, netlen, toread;
888ff9 ¤   unsigned char¤  lc;
162c90 ¤   long¤   ¤   rc;
307f04 ¤   int¤¤   noctets, diff;
6baf5a
5d2639 #ifdef LDAP_DEBUG
fa4e75 ¤   if ( lber_debug )
a76740 ¤   ¤   fprintf( stderr, "ber_get_next\n" );
d87454 #endif
18af5a
a2d8af ¤   /*
f971e4 ¤   ·* Any ber element looks like this: tag length contents.
660f04 ¤   ·* Assuming everything's ok, we return the tag byte (we
fe9a9b ¤   ·* can assume a single byte), return the length in len,
e91f8c ¤   ·* and the rest of the undecoded element in buf.
429714 ¤   ·*
a8667c ¤   ·* Assumptions:
53dae8 ¤   ·*¤ 1) small tags (less than 128)
b394e4 ¤   ·*¤ 2) definite lengths
4785b2 ¤   ·*¤ 3) primitive encodings used whenever possible
2aa4e3 ¤   ·*/
2aaf5a
0ed8af ¤   /*
b45976 ¤   ·* first time through - malloc the buffer, set up ptrs, and
b78d21 ¤   ·* read the tag and the length and as much of the rest as we can
d9a4e3 ¤   ·*/
9faf5a
dab183 ¤   if ( ber->ber_rwptr == NULL ) {
d91b17 ¤   ¤   /*
8366de ¤   ¤   ·* First, we read the tag.
919de3 ¤   ¤   ·*/
52af5a
6a7f89 ¤   ¤   if ( (tag = get_tag( sb )) == LBER_DEFAULT ) {
974aeb ¤   ¤   ¤   return( LBER_DEFAULT );
a40fe4 ¤   ¤   }
1885ca ¤   ¤   ber->ber_tag = tag;
5aaf5a
--ac2b 00069b4ae2b40100089 Page 9 of io.c
1c1b17 ¤   ¤   /*
401305 ¤   ¤   ·* Next, read the length. ·The first byte contains the length
108d30 ¤   ¤   ·* of the length. ·If bit 8 is set, the length is the long
9cc893 ¤   ¤   ·* form, otherwise it's the short form. ·We don't allow a
4ecdfe ¤   ¤   ·* length that's greater than what we can hold in an unsigned
5fb60d ¤   ¤   ·* long.
4f9de3 ¤   ¤   ·*/
6aaf5a
0288d6 ¤   ¤   *len = netlen = 0;
0a7ccc ¤   ¤   if ( BerRead( sb, (char *) &lc, 1 ) != 1 ) {
294aeb ¤   ¤   ¤   return( LBER_DEFAULT );
2d0fe4 ¤   ¤   }
69ec82 ¤   ¤   if ( lc & 0x80 ) {
761ade ¤   ¤   ¤   noctets = (lc & 0x7f);
784745 ¤   ¤   ¤   if ( noctets > sizeof(unsigned long) )
528fbe ¤   ¤   ¤   ¤   return( LBER_DEFAULT );
ee7036 ¤   ¤   ¤   diff = sizeof(unsigned long) - noctets;
42cb08 ¤   ¤   ¤   if ( BerRead( sb, (char *) &netlen + diff, noctets ) !=
bfb426 ¤   ¤   ¤   ····noctets ) {
108fbe ¤   ¤   ¤   ¤   return( LBER_DEFAULT );
29a3a6 ¤   ¤   ¤   }
e18d0d ¤   ¤   ¤   *len = LBER_NTOHL( netlen );
0645a6 ¤   ¤   } else {
850173 ¤   ¤   ¤   *len = lc;
770fe4 ¤   ¤   }
c9eb03 ¤   ¤   ber->ber_len = *len;
31af5a
621b17 ¤   ¤   /*
f9dec3 ¤   ¤   ·* Finally, malloc a buffer for the contents and read it in.
78b65d ¤   ¤   ·* It's this buffer that's passed to all the other ber decoding
1d79db ¤   ¤   ·* routines.
1a9de3 ¤   ¤   ·*/
c2af5a
01d75e #if defined( DOS ) && !defined( xx_WIN32 )¤ ¤   /* marcd */
9f87cc ¤   ¤   if ( *len > 65535 ) {¤  /* DOS can't allocate > 64K */
b07a78 ¤   ¤   ····return( LBER_DEFAULT );
ed0fe4 ¤   ¤   }
5870c1 #endif /* DOS && !_WIN32 */
73af5a
e3f17b ¤   ¤   if ( ( sb->sb_options & LBER_MAX_INCOMING_SIZE ) &&
e74106 ¤   ¤   ····*len > (unsigned long) sb->sb_max_incoming ) {
ef4aeb ¤   ¤   ¤   return( LBER_DEFAULT );
1e0fe4 ¤   ¤   }
62af5a
9d6624 ¤   ¤   if ( (ber->ber_buf = (char *) malloc( (size_t)*len )) == NULL ) {
c94aeb ¤   ¤   ¤   return( LBER_DEFAULT );
310fe4 ¤   ¤   }
089163 ¤   ¤   ber->ber_ptr = ber->ber_buf;
291482 ¤   ¤   ber->ber_end = ber->ber_buf + *len;
6a2559 ¤   ¤   ber->ber_rwptr = ber->ber_buf;
579371 ¤   }
9caf5a
b02314 ¤   toread = (unsigned long)ber->ber_end - (unsigned long)ber->ber_rwptr;
3343ab ¤   do {
e169c4 ¤   ¤   if ( (rc = BerRead( sb, ber->ber_rwptr, (long)toread )) <= 0 ) {
4e4aeb ¤   ¤   ¤   return( LBER_DEFAULT );
8a0fe4 ¤   ¤   }
aaaf5a
0d320d ¤   ¤   toread -= rc;
17195e ¤   ¤   ber->ber_rwptr += rc;
d2a1b5 ¤   } while ( toread > 0 );
08af5a
d62639 #ifdef LDAP_DEBUG
7aee71 ¤   if ( lber_debug ) {
c8c231 ¤   ¤   fprintf( stderr, "ber_get_next: tag 0x%lx len %ld contents:\n",
40694a ¤   ¤   ····tag, ber->ber_len );
f4d170 ¤   ¤   if ( lber_debug > 1 )
13f5b3 ¤   ¤   ¤   ber_dump( ber, 1 );
e79371 ¤   }
e57454 #endif
44af5a
695ca3 ¤   *len = ber->ber_len;
--0fdb 00179b340f040100089 Page 10 of io.c
f1ad8c ¤   ber->ber_rwptr = NULL;
48d720 ¤   return( ber->ber_tag );
79efe6 }
--1ef5 00145a03e684010008a Page 1 of pgpSrvMem.c
572c08 /* ·pgpSrvMem.c
3caf5a
25ae61 ¤   Standard memory routines for server apps.
7caf5a
a4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
a94b0f ¤   All rights reserved.
21af5a
d2ca4c ¤   $Id: pgpSrvMem.c,v 1.2.18.1 1998/11/12 03:17:32 heller Exp $
1aaf5a
b47fe0 */
cdaf5a
45cf14 #ifdef PGPKEYSERVER
c6f865 #include "pgpSrvStd.h"
9faf5a
7711e4 char *
b95443 pgpSrvStrDup(char *pszStr, char const *pszFile, long lLine)
dabb36 {
d0f549 ¤   char¤   *pszNew;
95af5a
8e691c #if PGP_DEBUG_FIND_LEAKS
b780ae ¤   pszNew = (char *) PGP_INTERNAL_MEMALLOC(strlen(pszStr) + 1, pszFile,·
fcb84b ¤   ¤   ¤   ·lLine);
05db21 #else
9e7719 ¤   pszNew = (char *) PGP_INTERNAL_MEMALLOC(strlen(pszStr) + 1);
717454 #endif
963dbb ¤   if (pszNew != NULL) {
56c130 ¤   ¤   strcpy(pszNew, pszStr);
5e9371 ¤   }
13af5a
af1a33 ¤   return(pszNew);
6defe6 }
3faf5a
189a44 void *
71f4d7 pgpSrvCAlloc(size_t ulNum, size_t ulSize, char const *pszFile, long lLine)
a9bb36 {
93118d ¤   void¤   *pMem;
ab67c5 ¤
4b691c #if PGP_DEBUG_FIND_LEAKS
7ea0c7 ¤   pMem = PGP_INTERNAL_MEMALLOC(ulNum * ulSize, pszFile, lLine);
f2db21 #else
2e2b31 ¤   pMem = PGP_INTERNAL_MEMALLOC(ulNum * ulSize);
ec7454 #endif
f51478 ¤   if (pMem != NULL) {
88a302 ¤   ¤   pgpClearMemory(pMem, ulNum * ulSize);
e89371 ¤   }
1967c5 ¤
144354 ¤   return(pMem);
d5efe6 }
c7af5a
8c314a void
5869bb pgpSrvFree(void *pMem)
26bb36 {
6f250c ¤   if (pMem != NULL)
4e5a36 ¤   ¤   pgpFree(pMem);
54efe6 }
ffaf5a
7f7454 #endif
45af5a
--1b6b 00000725f5b4010008b Page 1 of Make-template
54b0af #-----------------------------------------------------------------------------
0cdb1c # Copyright (c) 1994 Regents of the University of Michigan.
155a50 # All rights reserved.
1aa601 #
fb97d6 # Redistribution and use in source and binary forms are permitted
69d6ca # provided that this notice is preserved and that due credit is given
4e8ee9 # to the University of Michigan at Ann Arbor. The name of the University
0e3eb9 # may not be used to endorse or promote products derived from this
440baf # software without specific prior written permission. This software
d8feea # is provided ``as is'' without express or implied warranty.
49a601 #
7fef5a # ······LDAP library makefile
d7a601 #
52b0af #-----------------------------------------------------------------------------
b4af5a
5b3699 LDAPSRC¤= ..
9e8498 PGPLIBS = ../../..
cc7e36 OUTDIR ·= $(LDAPSRC)/unix
4eb5ca PGPCDKDIR = $(PGPLIBS)/pgpcdk
9836cd PGPPFLDIR = $(LDAPSRC)/../../pfl
3bd3d9 PGPCDKINCLUDES = -I$(PGPCDKDIR)/pub/include -I$(PGPCDKDIR)/unix
9c6640 PGPPFLINCLUDES = -I$(PGPPFLDIR)/common -I$(PGPPFLDIR)/unix
f3af5a
0adae7 SRCS¤   = bind.c open.c result.c error.c compare.c search.c \
c8098b ¤   ··modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
a8cd79 ¤   ··getfilter.c regex.c sbind.c kbind.c unbind.c friendly.c cldap.c \
a890d6 ¤   ··free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
93536d ¤   ··getdn.c getentry.c getattr.c getvalues.c addentry.c \
25a040 ¤   ··request.c getdxbyname.c os-ip.c url.c charset.c
42af5a
570eaa OBJS¤   = bind.o open.o result.o error.o compare.o search.o \
91909f ¤   ··modify.o add.o modrdn.o delete.o abandon.o ufn.o cache.o \
5a4df3 ¤   ··getfilter.o regex.o sbind.o kbind.o unbind.o friendly.o cldap.o \
f6239f ¤   ··free.o disptmpl.o srchpref.o dsparse.o tmplout.o sort.o \
d93b39 ¤   ··getdn.o getentry.o getattr.o getvalues.o addentry.o \
033c37 ¤   ··request.o getdxbyname.o os-ip.o url.o charset.o
a3af5a
d2b085 HDIR¤   = -I$(LDAPSRC)/include -I$(LDAPSRC)/pgpsockets
8baf5a
66545b INCLUDES= $(HDIR) $(PGPCDKINCLUDES) $(PGPPFLINCLUDES)
0daf5a
ad4691 DEFINES¤= $(DEFS) -DFILTERFILE="\"$(RUNTIMEETCDIR)/ldapfilter.conf\"" \
00b167 ¤   ··-DTEMPLATEFILE="\"$(RUNTIMEETCDIR)/ldaptemplates.conf\""
8daf5a
c8e6b4 CFLAGS¤ = $(INCLUDES) $(DEFINES) $(ACFLAGS)
e141d8 LDFLAGS = -L$(OUTDIR)
b8293f LIBS¤   = -lldap -llber
cdaf5a
3c4485 all:¤   $(OUTDIR)/libldap.a DONE
9caf5a
527fbe $(OUTDIR)/libldap.a: $(OBJS)
9cd59c ¤   $(AR) ruv $@ $(OBJS)
c6d81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
73f7c7 ¤   ¤   $(RANLIB) $@; \
555bc3 ¤   fi;
d1af5a
41da15 DONE:
29c786 ¤   @set -x; echo $(OBJS) > $@
f9af5a
6d6363 ltest:¤ libldap.a test.o ../liblber/liblber.a
fd37e4 ¤   $(CC) $(ALDFLAGS) -o $@ test.o $(LIBS) $(ALIBS)
10af5a
9eaf2b ttest:¤ libldap.a tmpltest.o ../liblber/liblber.a
4951b8 ¤   $(CC) $(ALDFLAGS) -o $@ tmpltest.o $(LIBS) $(ALIBS)
e9af5a
983f6a version.c:¤ $(OBJS)
6a1613 ¤   $(RM) $@
96c04d ¤   (u=$${USER-root} v=`$(CAT) ../../build/version` d=`$(PWD)` \
b19489 ¤   h=`$(HOSTNAME)` t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
1aa7ef ¤   -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
7ed31b ¤   -e "s|%VERSION%|$${v}|" \
005a66 ¤   < Version.c > $@)
--0e4d 0002e9982d24010008b Page 2 of Make-template
e0af5a
db6786 install:¤   libldap.a ldapfilter.conf ldapfriendly ldaptemplates.conf ldapsearc¶
cdb5c1 hprefs.conf FORCE
b14251 ¤   -$(MKDIR) -p $(LIBDIR)
b95cc6 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 libldap.a $(LIBDIR)
ead81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
35100c ¤   ¤   (cd /tmp; $(RANLIB) $(LIBDIR)/libldap.a) \
272ec9 ¤   fi
d471ff ¤   -$(MKDIR) -p $(ETCDIR)
513c3b ¤   -$(MV) $(ETCDIR)/ldapfriendly $(ETCDIR)/ldapfriendly-
98d997 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfriendly $(ETCDIR)
38bc33 ¤   -$(MV) $(ETCDIR)/ldapfilter.conf $(ETCDIR)/ldapfilter.conf-
b7848d ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfilter.conf $(ETCDIR)
0881ce ¤   -$(MV) $(ETCDIR)/ldaptemplates.conf $(ETCDIR)/ldaptemplates.conf-
f73785 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldaptemplates.conf $(ETCDIR)
dd63cd ¤   -$(MV) $(ETCDIR)/ldapsearchprefs.conf $(ETCDIR)/ldapsearchprefs.conf-
a006d3 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldapsearchprefs.conf $(ETCDIR)
3faf5a
0cc0ab lint:¤  FORCE
1c84b1 ¤   $(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
f0af5a
71defc 5lint:¤ FORCE
c0022c ¤   $(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
eaaf5a
b8b5ca clean:¤ FORCE
869714 ¤   $(RM) $(OUTDIR)/libldap.a ltest ttest *.o core a.out *.log version.c
f6af5a
1cadf8 depend:¤FORCE
5ad1f9 ¤   $(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
dcaf5a
d8a513 links:
df016a ¤   @$(LN) .src/*.[ch] .src/ldapfriendly .src/ldapfilter.conf \
f5f14d ¤   ¤   .src/ldaptemplates.conf .src/ldapsearchprefs.conf .
12af5a
1fa8d3 # DO NOT DELETE THIS LINE -- mkdep uses it.
6e3c8b # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
82af5a
91be6a bind.o: bind.c ../include/lber.h ../include/proto-ldap.h
5c75d9 open.o: open.c ../include/lber.h ../include/proto-ldap.h
52592e result.o: result.c ../include/proto-lber.h ldap-int.h
0a5e94 error.o: error.c ../include/lber.h ../include/proto-ldap.h
2f0e02 compare.o: compare.c ../include/lber.h ../include/proto-ldap.h
b487b7 search.o: search.c ../include/proto-lber.h ldap-int.h
0cb0da modify.o: modify.c ../include/lber.h ../include/proto-ldap.h
3da262 add.o: add.c ../include/lber.h ../include/proto-ldap.h
566f1b modrdn.o: modrdn.c ../include/lber.h ../include/proto-ldap.h
31c9bb delete.o: delete.c ../include/lber.h ../include/proto-ldap.h
3878f6 abandon.o: abandon.c ../include/lber.h ../include/proto-ldap.h
56ac48 ufn.o: ufn.c ../include/lber.h ../include/proto-ldap.h
b8cf65 cache.o: cache.c ../include/lber.h ../include/proto-ldap.h
e8a59a getfilter.o: getfilter.c ../include/lber.h ../include/proto-ldap.h
89a728 regex.o: regex.c
fa0173 sbind.o: sbind.c ../include/lber.h ../include/proto-ldap.h
0f738b kbind.o: kbind.c
8dcc1b unbind.o: unbind.c ../include/lber.h ../include/proto-ldap.h
61c32e friendly.o: friendly.c ../include/lber.h ../include/proto-ldap.h
6d38f6 cldap.o: cldap.c
c7a0fe free.o: free.c ../include/ldap.h
45cc91 disptmpl.o: disptmpl.c ../include/ldap.h
8671da srchpref.o: srchpref.c ../include/ldap.h
e9871c dsparse.o: dsparse.c ../include/ldap.h
2450ac tmplout.o: tmplout.c ../include/lber.h ../include/proto-ldap.h
238442 sort.o: sort.c ../include/ldap.h ../include/proto-ldap.h
96521a getdn.o: getdn.c ../include/lber.h ../include/proto-ldap.h
077592 getentry.o: getentry.c ../include/lber.h ../include/proto-ldap.h
7488f3 getattr.o: getattr.c ../include/lber.h ../include/proto-ldap.h
8cc900 getvalues.o: getvalues.c ../include/lber.h ../include/proto-ldap.h
874010 addentry.o: addentry.c ../include/lber.h ../include/proto-ldap.h
f4359f request.o: request.c ../include/proto-lber.h ldap-int.h
cb26d2 getdxbyname.o: getdxbyname.c
b3660e os-ip.o: os-ip.c ../include/portable.h ../include/ldap.h
2e3bfe url.o: url.c ../include/lber.h ../include/proto-ldap.h
--65ca 001a92a60ca4010008b Page 3 of Make-template
6b4bfe charset.o: charset.c
79af5a
a9f6c8 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
--ecbf 00047a8232c4010008c Page 1 of Makefile
2539de # --------------------------------------------------------
324229 # ·This file was automatically generated. ·Do not edit it.
c0e6af # ·Instead, edit the Make-common file (located in the root
eef11f # ·(of the LDAP distribution). ·See the LDAP INSTALL file
a05811 # ·for more information.
ee39de # --------------------------------------------------------
05a601 #
2db0af #-----------------------------------------------------------------------------
06db1c # Copyright (c) 1994 Regents of the University of Michigan.
d95a50 # All rights reserved.
aea601 #
8c97d6 # Redistribution and use in source and binary forms are permitted
c6d6ca # provided that this notice is preserved and that due credit is given
378ee9 # to the University of Michigan at Ann Arbor. The name of the University
a83eb9 # may not be used to endorse or promote products derived from this
b10baf # software without specific prior written permission. This software
8dfeea # is provided ``as is'' without express or implied warranty.
95a601 #
a1ef5a # ······LDAP library makefile
cea601 #
a6b0af #-----------------------------------------------------------------------------
c1af5a
633699 LDAPSRC¤= ..
bc7e36 OUTDIR ·= $(LDAPSRC)/unix
9e36cd PGPPFLDIR = $(LDAPSRC)/../../pfl
e26640 PGPPFLINCLUDES = -I$(PGPPFLDIR)/common -I$(PGPPFLDIR)/unix
1daf5a
d3dae7 SRCS¤   = bind.c open.c result.c error.c compare.c search.c \
3e098b ¤   ··modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
97cd79 ¤   ··getfilter.c regex.c sbind.c kbind.c unbind.c friendly.c cldap.c \
0a90d6 ¤   ··free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
b0536d ¤   ··getdn.c getentry.c getattr.c getvalues.c addentry.c \
6aa040 ¤   ··request.c getdxbyname.c os-ip.c url.c charset.c
aaaf5a
fa0eaa OBJS¤   = bind.o open.o result.o error.o compare.o search.o \
3b909f ¤   ··modify.o add.o modrdn.o delete.o abandon.o ufn.o cache.o \
914df3 ¤   ··getfilter.o regex.o sbind.o kbind.o unbind.o friendly.o cldap.o \
90239f ¤   ··free.o disptmpl.o srchpref.o dsparse.o tmplout.o sort.o \
103b39 ¤   ··getdn.o getentry.o getattr.o getvalues.o addentry.o \
f83c37 ¤   ··request.o getdxbyname.o os-ip.o url.o charset.o
d2af5a
b29767 HDIR¤   = $(LDAPSRC)/include
4eaf5a
96b228 INCLUDES= -I$(HDIR) $(PGPPFLINCLUDES)
5aaf5a
964691 DEFINES¤= $(DEFS) -DFILTERFILE="\"$(RUNTIMEETCDIR)/ldapfilter.conf\"" \
e7b167 ¤   ··-DTEMPLATEFILE="\"$(RUNTIMEETCDIR)/ldaptemplates.conf\""
3faf5a
fce6b4 CFLAGS¤ = $(INCLUDES) $(DEFINES) $(ACFLAGS)
3041d8 LDFLAGS = -L$(OUTDIR)
3c293f LIBS¤   = -lldap -llber
7daf5a
c54485 all:¤   $(OUTDIR)/libldap.a DONE
45af5a
947fbe $(OUTDIR)/libldap.a: $(OBJS)
f5d59c ¤   $(AR) ruv $@ $(OBJS)
42d81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
87f7c7 ¤   ¤   $(RANLIB) $@; \
805bc3 ¤   fi;
c1af5a
47da15 DONE:
f6c786 ¤   @set -x; echo $(OBJS) > $@
fcaf5a
396363 ltest:¤ libldap.a test.o ../liblber/liblber.a
7237e4 ¤   $(CC) $(ALDFLAGS) -o $@ test.o $(LIBS) $(ALIBS)
17af5a
07af2b ttest:¤ libldap.a tmpltest.o ../liblber/liblber.a
3351b8 ¤   $(CC) $(ALDFLAGS) -o $@ tmpltest.o $(LIBS) $(ALIBS)
86af5a
163f6a version.c:¤ $(OBJS)
841613 ¤   $(RM) $@
47c04d ¤   (u=$${USER-root} v=`$(CAT) ../../build/version` d=`$(PWD)` \
--24b7 000ef2e56924010008c Page 2 of Makefile
4e9489 ¤   h=`$(HOSTNAME)` t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
eda7ef ¤   -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
88d31b ¤   -e "s|%VERSION%|$${v}|" \
745a66 ¤   < Version.c > $@)
74af5a
526786 install:¤   libldap.a ldapfilter.conf ldapfriendly ldaptemplates.conf ldapsearc¶
4ab5c1 hprefs.conf FORCE
4e4251 ¤   -$(MKDIR) -p $(LIBDIR)
ed5cc6 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 libldap.a $(LIBDIR)
93d81d ¤   @if [ ! -z "$(RANLIB)" ]; then \
ef100c ¤   ¤   (cd /tmp; $(RANLIB) $(LIBDIR)/libldap.a) \
322ec9 ¤   fi
ee71ff ¤   -$(MKDIR) -p $(ETCDIR)
2e3c3b ¤   -$(MV) $(ETCDIR)/ldapfriendly $(ETCDIR)/ldapfriendly-
37d997 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfriendly $(ETCDIR)
eebc33 ¤   -$(MV) $(ETCDIR)/ldapfilter.conf $(ETCDIR)/ldapfilter.conf-
82848d ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfilter.conf $(ETCDIR)
a681ce ¤   -$(MV) $(ETCDIR)/ldaptemplates.conf $(ETCDIR)/ldaptemplates.conf-
c73785 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldaptemplates.conf $(ETCDIR)
d163cd ¤   -$(MV) $(ETCDIR)/ldapsearchprefs.conf $(ETCDIR)/ldapsearchprefs.conf-
2c06d3 ¤   $(INSTALL) $(INSTALLFLAGS) -m 644 ldapsearchprefs.conf $(ETCDIR)
7faf5a
28c0ab lint:¤  FORCE
8a84b1 ¤   $(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
ebaf5a
d6defc 5lint:¤ FORCE
5c022c ¤   $(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
60af5a
ebb5ca clean:¤ FORCE
5b9714 ¤   $(RM) $(OUTDIR)/libldap.a ltest ttest *.o core a.out *.log version.c
b7af5a
9aadf8 depend:¤FORCE
1bd1f9 ¤   $(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
86af5a
06a513 links:
74016a ¤   @$(LN) .src/*.[ch] .src/ldapfriendly .src/ldapfilter.conf \
91f14d ¤   ¤   .src/ldaptemplates.conf .src/ldapsearchprefs.conf .
72af5a
d1a8d3 # DO NOT DELETE THIS LINE -- mkdep uses it.
b93c8b # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
bfaf5a
e1be6a bind.o: bind.c ../include/lber.h ../include/proto-ldap.h
5f75d9 open.o: open.c ../include/lber.h ../include/proto-ldap.h
55592e result.o: result.c ../include/proto-lber.h ldap-int.h
2b5e94 error.o: error.c ../include/lber.h ../include/proto-ldap.h
e40e02 compare.o: compare.c ../include/lber.h ../include/proto-ldap.h
9fe81b search.o: search.c ../include/lber.h ../include/proto-ldap.h
65b0da modify.o: modify.c ../include/lber.h ../include/proto-ldap.h
c5a262 add.o: add.c ../include/lber.h ../include/proto-ldap.h
506f1b modrdn.o: modrdn.c ../include/lber.h ../include/proto-ldap.h
0dc9bb delete.o: delete.c ../include/lber.h ../include/proto-ldap.h
e278f6 abandon.o: abandon.c ../include/lber.h ../include/proto-ldap.h
c5ac48 ufn.o: ufn.c ../include/lber.h ../include/proto-ldap.h
79cf65 cache.o: cache.c ../include/lber.h ../include/proto-ldap.h
0ea59a getfilter.o: getfilter.c ../include/lber.h ../include/proto-ldap.h
b4a728 regex.o: regex.c
600173 sbind.o: sbind.c ../include/lber.h ../include/proto-ldap.h
3c738b kbind.o: kbind.c
b5cc1b unbind.o: unbind.c ../include/lber.h ../include/proto-ldap.h
5bc32e friendly.o: friendly.c ../include/lber.h ../include/proto-ldap.h
9e38f6 cldap.o: cldap.c
118877 free.o: free.c ../include/lber.h ../include/proto-ldap.h
da1b8d disptmpl.o: disptmpl.c ../include/lber.h ../include/proto-ldap.h
503069 srchpref.o: srchpref.c ../include/lber.h ../include/proto-ldap.h
81bb33 dsparse.o: dsparse.c ../include/lber.h ../include/proto-ldap.h
3050ac tmplout.o: tmplout.c ../include/lber.h ../include/proto-ldap.h
cd2eb2 sort.o: sort.c ../include/lber.h ../include/proto-ldap.h
85521a getdn.o: getdn.c ../include/lber.h ../include/proto-ldap.h
707592 getentry.o: getentry.c ../include/lber.h ../include/proto-ldap.h
1b88f3 getattr.o: getattr.c ../include/lber.h ../include/proto-ldap.h
afc900 getvalues.o: getvalues.c ../include/lber.h ../include/proto-ldap.h
ef4010 addentry.o: addentry.c ../include/lber.h ../include/proto-ldap.h
--3495 00079807d594010008c Page 3 of Makefile
f2359f request.o: request.c ../include/proto-lber.h ldap-int.h
ec26d2 getdxbyname.o: getdxbyname.c
e36f77 os-ip.o: os-ip.c ../include/proto-lber.h
5e3bfe url.o: url.c ../include/lber.h ../include/proto-ldap.h
534bfe charset.o: charset.c
f5af5a
75f6c8 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
b6a601 #
daffdb # Do NOT edit this file -- it is automatically appended to all Makefiles
0269dc # except the LDAP top-level Makefile. See the LDAP INSTALL file for more
201fc7 # information.
2ba601 #
67b0af #-----------------------------------------------------------------------------
61db1c # Copyright (c) 1994 Regents of the University of Michigan.
335a50 # All rights reserved.
21a601 #
bd97d6 # Redistribution and use in source and binary forms are permitted
52d6ca # provided that this notice is preserved and that due credit is given
b18ee9 # to the University of Michigan at Ann Arbor. The name of the University
a43eb9 # may not be used to endorse or promote products derived from this
2c0baf # software without specific prior written permission. This software
bcfeea # is provided ``as is'' without express or implied warranty.
56a601 #
163287 # ······LDAP standard Make defines (appended to all but top-level Makefile)
60a601 #
7bb0af #-----------------------------------------------------------------------------
e6af5a
16ad9f # DEFS are included in CFLAGS
3fd084 DEFS¤   = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
400785 ¤   ¤   $(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
b0f00e ¤   ¤   $(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
5c997b ¤   ¤   $(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
fc87f1 ¤   ¤   $(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
2baf5a
dc40cd # SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
9ab18b SERVERDEFS¤ = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
6e14ba ¤   ¤   ¤   $(NO_SETPROCTITLE) $(PEPSY_DUMP)
a4af5a
d9a601 #
740ce2 # ISODELIBS are used in server/ldapd builds
2ba601 #
344e01 ISODELIBS¤  = $(ISODEBASELIBS) -lm $(ISODETURBOLIBS)
34af5a
670558 # ACFLAGS are added to CFLAGS but not passed to mkdep, lint, etc
8817ce ACFLAGS¤¤   = $(EXTRACFLAGS) $(UNPROTOCFLAGS)
2aaf5a
402eb4 # ALDFLAGS are always placed near the beginning of all linker (cc -o) commands
7249dd ALDFLAGS¤   = $(EXTRALDFLAGS) $(PLATFORMLDFLAGS)
6eaf5a
d5233d # ALIBS are always placed at the end of all linker (cc -o) commands
d91ec7 ALIBS¤  ¤   = $(PLATFORMLIBS) $(THREADSLIB) -lstdc++
23af5a
a0a601 #
39c229 # default definitions for Unix utilities (may be over-ridden in Make-platform)
3ffd75 CC¤ = cc
b77e42 MAKE¤   = make
dc1a1a RANLIB¤ = ranlib
8d85b9 AR¤ = ar
3fba00 RM¤ = rm -f
5c9865 MV¤ = mv -f
ee9324 CP¤ = cp
dd229f CHMOD¤  = chmod
6e65eb CAT¤= cat
7ad1bd LN¤ = ln -s
bb41b6 HARDLN¤ = ln
1fc699 TAIL¤   = tail
cbe675 SED¤= sed
8e01f7 LINT¤   = lint
923a04 5LINT¤  = lint
eec291 MKDIR¤  = mkdir
213f60 INSTALL¤= install
790106 INSTALLFLAGS = -c
--56a8 000b8ddc19e4010008c Page 4 of Makefile
d2735e BASENAME= basename
d4d84e DIRNAME¤= dirname
65720b MKDEP¤  = $(LDAPSRC)/build/mkdep -c gcc -s -f Make-template
d1e392 PWD¤= pwd
b896d7 DATE¤   = date
a6a7d0 HOSTNAME= hostname
abaf5a
84af5a
69a601 #
35592a # empty target used to force rules to be invoked
84a601 #
b52b40 FORCE:
b1af5a
baa601 #
8ac8ac # LDAP SunOS5 GNU C Make-platform file
04a601 #
acaf5a
8ca601 #
32a68c # add any platform-specific overrides below here
2aa601 #
8caf5a
51af5a
69a601 #
a295cf # -------------------------------------------------------------------------
8fba80 # you will probably not need to edit anything below this point
4095cf # -------------------------------------------------------------------------
734b2c CC¤ = gcc
01af5a
4a1dfe # ranlib not needed under SunOS5
697716 RANLIB¤ = ""
e5af5a
fa9a13 # give full path to hostname since it may not be in user's path
f5ea97 HOSTNAME=/usr/ucb/hostname
33af5a
fb7720 # don't count on /usr/ucb/install being present or first in path
f010f3 INSTALL=$(LDAPSRC)/build/install.sh
18af5a
f3eaf0 PLATFORMCFLAGS=¤-Dsunos5 -D_REENTRANT
ef8289 PLATFORMLIBS= -lsocket -lnsl -lgen
841dc2 THREADS= -DTHREAD_SUNOS5_LWP
2c7e25 THREADSLIB=-lthread
d9b0af #-----------------------------------------------------------------------------
cd35f2 # Copyright (c) 1997 PGP inc.
205a50 # All rights reserved.
03a601 #
10b0af #-----------------------------------------------------------------------------
23dd01 #############################################################################
86a917 ## Edit the following variables to have appropriate values for your system ##
c8dd01 #############################################################################
42af5a
c4515b vpath %.a $(OUTDIR):$(LDIR):$(PGPCDKDIR)/unix:$(DBLDIR):$(PGPPFLDIR) \
7cdc18 ¤   ··$(PGPCDKDIR)/priv/keyserver: \
54aacf ¤   ··$(PGPCDKDIR)/../network/pgpsockets/unix/src
40af5a
e0dd01 #############################################################################
3e736d ## LDAP install paths ·····················································##
f6dd01 #############################################################################
39a601 #
a5c05e # by default, everything is installed below INSTROOT
ad4f10 # servers, config files, etc. are put in ETCDIR
b654a5 # include files get put in INCLUDEDIR
2a48e9 # libraries are put in LIBDIR
65f935 # man pages are put under MANDIR
1dd9d9 # programs end-users will run are put in BINDIR
82a601 #
0db837 # Moved INSTROOT declaration to top-level Makefile
d737ce # useful for automation.
86af5a
c88fed ETCDIR= $(INSTROOT)/etc
1c4bf1 INCLUDEDIR= $(INSTROOT)/include
f64e47 LIBDIR= $(INSTROOT)/unix
b8e906 MANDIR= $(INSTROOT)/doc
--9178 00005c3a5684010008c Page 5 of Makefile
332d8f BINDIR= $(INSTROOT)/unix
5eaf5a
4ba601 #
81ca77 # if you want things to run in a different directory from where they
be2c1a # are installed, set this accordingly (this path gets compiled into a
528e97 # few binaries). otherwise, leave it alone.
6963ae RUNTIMEETCDIR= $(ETCDIR)
caaf5a
0add01 #############################################################################
637145 ## General compiler options ···············································##
e1dd01 #############################################################################
0564cf # Passed to every compile (cc or gcc). ·This is where you put -O or -g, etc.
34c073 # Added -D_REENTRANT per ldap doc. for Solaris builds <galileo>
5e7adf OPT=-g
d8255c DEBUG=1
15ab6e UNFINISHED=1
afed5a EXTRACFLAGS=-D_REENTRANT $(OPT) -fwritable-strings \
a41d76 ············-DPGP_DEBUG=$(DEBUG) -DUNFINISHED_CODE_ALLOWED=$(UNFINISHED)
28af5a
c7e6cd # Passed to every link (ld). ·Include -g here if you did in EXTRACFLAGS.
2eaf5a
3fb23e EXTRALDFLAGS=$(OPT)
97af5a
f2dd01 #############################################################################
3fce69 ## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ······##
c1b9e8 ## If you don't want to build it, you can skip this section. ··············##
a7dd01 #############################################################################
6ba601 #
ff11c2 # To build the ldap server, uncomment the HAVEISODE line,
9e5803 # and the section describing build settings for your version of isode.
e0a601 #
9ea865 HAVEISODE = yes
e5af5a
99dd01 #############################################################################
4fc146 ## If you don't want to run slapd, skip this section. ·····················##
5ddd01 #############################################################################
b6a601 #
8eac20 # To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
188e0c # line and select the SLAPD_BACKENDS you want to use. If you enable the
2c2d3b # LDBM backend, also select one of the LDBM backends.
728fbf MAKESLAPD= yes
3ca601 #
d54d71 # remove the defines for backends you don't want to enable
2f743e SLAPD_BACKENDS= -DLDAP_LDBM
1ba601 #
739374 # If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
0ecee2 # to specify which low-level database package to use. ·There are
14f92f # four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
7ba601 #
c8a9bd # berkeley db btree package
8b7e82 LDBMBACKEND=-DLDBM_USE_DBBTREE21
34b496 LDBMINCLUDE=
af28ff LDBMLIB=-ldb
feb402 # berkeley db hash package
639bc9 #LDBMBACKEND=-DLDBM_USE_DBHASH
68d345 #LDBMINCLUDE=-I/usr/local/db/include
db0e7e #LDBMLIB=-ldb
d02a77 # gnu dbm (gdbm)
06ed29 #LDBMBACKEND=-DLDBM_USE_GDBM
439187 #LDBMINCLUDE=-I$(INSTROOT)/servers/slapd/db
a26c04 #LDBMLIB=-lgdbm
781874 # standard unix ndbm
88bc4d #LDBMBACKEND=-DLDBM_USE_NDBM
72a601 #
9e7ffd # if you want to use a non-default threads package change these lines
a442ab #THREADS=-DNO_THREADS
898180 #THREADSLIB=
a1af5a
dedd01 #############################################################################
721692 ## General options ························································##
a2dd01 #############################################################################
05c8ae # uncomment this line to enable debugging code (a good idea)
--4a9a 0013d5994104010008c Page 6 of Makefile
1a75d8 LDAP_DEBUG=-DLDAP_DEBUG
42af5a
63b923 # uncomment this line to turn on a few U of Michigan specific things
148cea #UOFM=-DUOFM
f8af5a
8dbce0 # uncomment this line to delete a few printfs in the lber and ldap libraries.
4bd6e3 #NO_USERINTERFACE=-DNO_USERINTERFACE
d3af5a
7f2982 # uncomment this line to include Connectionless LDAP support
4d1910 #CLDAP=-DCLDAP
4baf5a
cb021f # uncomment this line to eliminate local caching support in the libldap
02decc #NO_CACHE=-DNO_CACHE
5aaf5a
6e197d # uncomment this line to enable support for LDAP referrals in libldap
ef1c28 LDAP_REFERRALS=-DLDAP_REFERRALS
13af5a
e44c1c # uncomment this line to use soundex for approximate matches in slapd.
1e856d # the default is to use the metaphone algorithm.
3d1fa8 #PHONETIC=-DSOUNDEX
--b4a6 0011a9c22244010008d Page 1 of Version.c
bc38e5 /*
696b47 ·* Copyright (c) 1991 Regents of the University of Michigan.
44599a ·* All rights reserved.
da775e ·*
1ab855 ·* Redistribution and use in source and binary forms are permitted
f39795 ·* provided that this notice is preserved and that due credit is given
8d1873 ·* to the University of Michigan at Ann Arbor. The name of the University
168805 ·* may not be used to endorse or promote products derived from this
a774fe ·* software without specific prior written permission. This software
362a32 ·* is provided ``as is'' without express or implied warranty.
82495d ·*/
7baf5a
1a8103 static char Version[] = " ·libldap.a v3.3 ()\n\tlibldap\n";
--f056 000ed065b0f4010008e Page 1 of abandon.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
c72fc1 ·* ·abandon.c
cf495d ·*/
e4af5a
8b0c68 #ifndef lint·
bc7587 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University"
15ff43 ¤   ¤   ¤   ··" of Michigan.\nAll rights reserved.\n";
b87454 #endif
3faf5a
2afeb2 #include <stdio.h>
bc324c #include <string.h>
ceaf5a
b824c3 #if PGPSOCKETSLDAP¤ /* jason */
0265aa #include "pgpSocketsLDAP.h"
acaf5a
cddb21 #else
ff1330 #if !defined( MACOS ) && !defined( DOS )
7af15e #include <sys/types.h>
c5a394 #ifndef WIN32¤  ¤   /* marcd */
5766f2 #include <sys/socket.h>
aa7454 #endif
e67454 #endif
ddaf5a
c1fdef #if defined( DOS ) || defined( _WIN32 )
cb5e84 #include <malloc.h>
1d01b0 #ifdef DOS
68f2ef #include "msdos.h"
4b7454 #endif
01bc39 #endif /* DOS */
11af5a
98c583 #ifdef MACOS
00bea3 #include <stdlib.h>
a365e0 #include "macos.h"
cfe962 #endif /* MACOS */
48df0f #endif /* PGPSOCKETSLDAP */
5eaf5a
9bb779 #include "lber.h"
1ce990 #include "ldap.h"
d3745c #include "ldap-int.h"
1baf5a
d6504c #ifdef NEEDPROTOS
5181c3 static int do_abandon( LDAP *ld, int origid, int msgid );
936133 #else /* NEEDPROTOS */
b9f5ee static int do_abandon();
b08634 #endif /* NEEDPROTOS */
3238e5 /*
8379fc ·* ldap_abandon - perform an ldap (and X.500) abandon operation. Parameters:
33775e ·*
904f03 ·*¤ ld¤ ¤   LDAP descriptor
7f63b3 ·*¤ msgid¤  ¤   The message id of the operation to abandon
af775e ·*
9e8716 ·* ldap_abandon returns 0 if everything went ok, -1 otherwise.
9f775e ·*
a1305c ·* Example:
270eeb ·*¤ ldap_abandon( ld, msgid );
4e495d ·*/
ef4d2f int
eead85 ldap_abandon( LDAP *ld, int msgid )
0ebb36 {
52fc99 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
3734c8 ¤   return( do_abandon( ld, msgid, msgid ));
70efe6 }
67af5a
55af5a
69beb7 static int
7a9173 do_abandon( LDAP *ld, int origid, int msgid )
4abb36 {
609c95 ¤   BerElement¤ *ber;
ed7de4 ¤   int¤¤   i, err, sendabandon;
--75ad 000191c0a3d4010008e Page 2 of abandon.c
cff348 ¤   Sockbuf¤¤   *sb;
e67f8d #ifdef LDAP_REFERRALS
194939 ¤   LDAPRequest¤*lr;
1390e2 #endif /* LDAP_REFERRALS */
f2af5a
43339b ¤   (void) origid;
df67c5 ¤
61d8af ¤   /*
afba50 ¤   ·* An abandon request looks like this:
3abf09 ¤   ·*¤ AbandonRequest ::= MessageID
43a4e3 ¤   ·*/
6aaf5a
1e461c ¤   Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
6b39b5 ¤   ¤   origid, msgid, 0 );
abaf5a
e35cd1 ¤   sendabandon = 1;
ebaf5a
f47f8d #ifdef LDAP_REFERRALS
0657b9 ¤   /* find the request that we are abandoning */
f1c91b ¤   for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
7073e9 ¤   ¤   if ( lr->lr_msgid == msgid ) {¤ /* this message */
b2cdcb ¤   ¤   ¤   break;
670fe4 ¤   ¤   }
ae7a3a ¤   ¤   if ( lr->lr_origid == msgid ) {¤/* child: ·abandon it */
0c15f9 ¤   ¤   ¤   do_abandon( ld, msgid, lr->lr_msgid );
2f0fe4 ¤   ¤   }
fb9371 ¤   }
c3af5a
8ef8b6 ¤   if ( lr != NULL ) {
31bd14 ¤   ¤   if ( origid == msgid && lr->lr_parent != NULL ) {
fa3247 ¤   ¤   ¤   /* don't let caller abandon child requests! */
ebb96a ¤   ¤   ¤   ld->ld_errno = LDAP_PARAM_ERROR;
3a8e4f ¤   ¤   ¤   return( -1 );
030fe4 ¤   ¤   }
0dbe79 ¤   ¤   if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
adbb3c ¤   ¤   ¤   /* no need to send abandon message */
768381 ¤   ¤   ¤   sendabandon = 0;
370fe4 ¤   ¤   }
299371 ¤   }
7d90e2 #endif /* LDAP_REFERRALS */
4daf5a
afef5d ¤   if ( ldap_msgdelete( ld, msgid ) == 0 ) {
024448 ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
51abea ¤   ¤   return( 0 );
db9371 ¤   }
d8af5a
ea1ff2 ¤   err = 0;
fbb79a ¤   if ( sendabandon ) {
a10622 ¤   ¤   /* create a message to send */
c2b20f ¤   ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
8d50d9 ¤   ¤   ¤   err = -1;
916150 ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
9645a6 ¤   ¤   } else {
53ed07 #ifdef CLDAP
f8f871 ¤   ¤   ¤   if ( ld->ld_sb.sb_naddr > 0 ) {
28a18a ¤   ¤   ¤   ¤   err = ber_printf( ber, "{isti}",
0f0264 ¤   ¤   ¤   ¤   ····++ld->ld_msgid, ld->ld_cldapdn,
ccd13a ¤   ¤   ¤   ¤   ····LDAP_REQ_ABANDON, msgid );
b4042d ¤   ¤   ¤   } else {
2f6b1c #endif /* CLDAP */
77fdd5 ¤   ¤   ¤   ¤   err = ber_printf( ber, "{iti}", ++ld->ld_msgid,
ddd13a ¤   ¤   ¤   ¤   ····LDAP_REQ_ABANDON, msgid );
afed07 #ifdef CLDAP
55a3a6 ¤   ¤   ¤   }
a86b1c #endif /* CLDAP */
dfaf5a
7afb4c ¤   ¤   ¤   if ( err == -1 ) {
6db805 ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
733c13 ¤   ¤   ¤   ¤   ber_free( ber, 1 );
eb042d ¤   ¤   ¤   } else {
1104bb ¤   ¤   ¤   ¤   /* send the message */
197f8d #ifdef LDAP_REFERRALS
--021b 001b1039df64010008e Page 3 of abandon.c
0e2871 ¤   ¤   ¤   ¤   if ( lr != NULL ) {
feb9a8 ¤   ¤   ¤   ¤   ¤   sb = lr->lr_conn->lconn_sb;
c7b5fc ¤   ¤   ¤   ¤   } else {
b04c1c ¤   ¤   ¤   ¤   ¤   sb = &ld->ld_sb;
9a2613 ¤   ¤   ¤   ¤   }
084267 #else /* LDAP_REFERRALS */
747174 ¤   ¤   ¤   ¤   sb = &ld->ld_sb;
9190e2 #endif /* LDAP_REFERRALS */
2e7161 ¤   ¤   ¤   ¤   if ( ber_flush( sb, ber, 1 ) != 0 ) {
81a872 ¤   ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_SERVER_DOWN;
c21e38 ¤   ¤   ¤   ¤   ¤   err = -1;
acb5fc ¤   ¤   ¤   ¤   } else {
046e64 ¤   ¤   ¤   ¤   ¤   err = 0;
762613 ¤   ¤   ¤   ¤   }
41a3a6 ¤   ¤   ¤   }
7a0fe4 ¤   ¤   }
fa9371 ¤   }
95af5a
d27f8d #ifdef LDAP_REFERRALS
6ff8b6 ¤   if ( lr != NULL ) {
8d83c7 ¤   ¤   if ( sendabandon ) {
47d8e4 ¤   ¤   ¤   free_connection( ld, lr->lr_conn, 0, 1 );
0a0fe4 ¤   ¤   }
03e0c6 ¤   ¤   if ( origid == msgid ) {
d200fe ¤   ¤   ¤   free_request( ld, lr );
8c0fe4 ¤   ¤   }
7c9371 ¤   }
9690e2 #endif /* LDAP_REFERRALS */
8aaf5a
68af5a
a883a3 ¤   if ( ld->ld_abandoned == NULL ) {
b885d5 ¤   ¤   if ( (ld->ld_abandoned = (int *) malloc( 2 * sizeof(int) ))
c7468f ¤   ¤   ····== NULL ) {
576150 ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
398e4f ¤   ¤   ¤   return( -1 );
f20fe4 ¤   ¤   }
fe9ed6 ¤   ¤   i = 0;
3bf037 ¤   } else {
db7819 ¤   ¤   for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
b3256b ¤   ¤   ¤   ;¤  /* NULL */
2b83ca ¤   ¤   if ( (ld->ld_abandoned = (int *) realloc( (char *)
6709c8 ¤   ¤   ····ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) {
a26150 ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
5d8e4f ¤   ¤   ¤   return( -1 );
5f0fe4 ¤   ¤   }
439371 ¤   }
4307a1 ¤   ld->ld_abandoned[i] = msgid;
d6d27d ¤   ld->ld_abandoned[i + 1] = -1;
32af5a
db0662 ¤   if ( err != -1 ) {
744448 ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
099371 ¤   }
19deb7 ¤   return( err );
b1efe6 }
--52fc 000105df3664010008f Page 1 of add.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
fa3d24 ·* ·add.c
f4495d ·*/
54af5a
b10c68 #ifndef lint·
2007d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
193efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
647454 #endif
a1af5a
a8feb2 #include <stdio.h>
7f324c #include <string.h>
efaf5a
6324c3 #if PGPSOCKETSLDAP¤ /* jason */
a165aa #include "pgpSocketsLDAP.h"
9baf5a
60db21 #else
24c583 #ifdef MACOS
4965e0 #include "macos.h"
8fe962 #endif /* MACOS */
e3af5a
9dfdef #if defined( DOS ) || defined( _WIN32 )
365e84 #include <malloc.h>
5c01b0 #ifdef DOS
1af2ef #include "msdos.h"
5f7454 #endif
78bc39 #endif /* DOS */
09af5a
f31330 #if !defined( MACOS ) && !defined( DOS )
f7f15e #include <sys/types.h>
efa394 #ifndef WIN32¤  ¤   /* marcd */
3a66f2 #include <sys/socket.h>
0f7454 #endif
fca3ea #endif /* !MACOS && !DOS */
cadf0f #endif /* PGPSOCKETSLDAP */
15af5a
6bb779 #include "lber.h"
c9e990 #include "ldap.h"
99745c #include "ldap-int.h"
43af5a
5338e5 /*
b24f96 ·* ldap_add - initiate an ldap (and X.500) add operation. ·Parameters:
e0775e ·*
754f03 ·*¤ ld¤ ¤   LDAP descriptor
6d61c4 ·*¤ dn¤ ¤   DN of the entry to add
0658ed ·*¤ mods¤   ¤   List of attributes for the entry. ·This is a null-
b7fcda ·*¤ ¤   ¤   terminated array of pointers to LDAPMod structures.
822e76 ·*¤ ¤   ¤   only the type and values in the structures need be
ff6783 ·*¤ ¤   ¤   filled in.
4e775e ·*
cf305c ·* Example:
2328ca ·*¤ LDAPMod¤*attrs[] = {·
e7fcf7 ·*¤ ¤   ¤   { 0, "cn", { "babs jensen", "babs", 0 } },
5db014 ·*¤ ¤   ¤   { 0, "sn", { "jensen", 0 } },
680be5 ·*¤ ¤   ¤   { 0, "objectClass", { "person", 0 } },
f48dd5 ·*¤ ¤   ¤   0
fd90d3 ·*¤ ¤   }
b8ac0b ·*¤ msgid = ldap_add( ld, dn, attrs );
8b495d ·*/
0f4d2f int
0e1117 ldap_add( LDAP *ld, char *dn, LDAPMod **attrs )
96bb36 {
a49c95 ¤   BerElement¤ *ber;
e8b696 ¤   int¤¤   i, rc;
01af5a
b1d8af ¤   /*
877d93 ¤   ·* An add request looks like this:
76f4bb ¤   ·*¤ AddRequest ::= SEQUENCE {
9b2c25 ¤   ·*¤ ¤   entry¤  DistinguishedName,
10ebcb ¤   ·*¤ ¤   attrs¤  SEQUENCE OF SEQUENCE {
--59b2 0015adc8c264010008f Page 2 of add.c
87cca4 ¤   ·*¤ ¤   ¤   type¤   AttributeType,
a9ae88 ¤   ·*¤ ¤   ¤   values¤ SET OF AttributeValue
733c91 ¤   ·*¤ ¤   }
ec5203 ¤   ·*¤ }
26a4e3 ¤   ·*/
c2af5a
89ad76 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_add\n", 0, 0, 0 );
cdaf5a
cd47d1 ¤   /* create a message to send */
cc6826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
8949fa ¤   ¤   return( -1 );
fc9371 ¤   }
10af5a
740ebe ¤   if ( ber_printf( ber, "{it{s{", ++ld->ld_msgid, LDAP_REQ_ADD, dn )
9c9a76 ¤   ····== -1 ) {
533614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
011ab1 ¤   ¤   ber_free( ber, 1 );
2e49fa ¤   ¤   return( -1 );
4a9371 ¤   }
e5af5a
843506 ¤   /* for each attribute in the entry... */
903e78 ¤   for ( i = 0; attrs[i] != NULL; i++ ) {
9e7903 ¤   ¤   if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
22b3b4 ¤   ¤   ¤   rc = ber_printf( ber, "{s[V]}", attrs[i]->mod_type,
f0943e ¤   ¤   ¤   ····attrs[i]->mod_values );
5445a6 ¤   ¤   } else {
8ad03d ¤   ¤   ¤   rc = ber_printf( ber, "{s[v]}", attrs[i]->mod_type,
0f943e ¤   ¤   ¤   ····attrs[i]->mod_values );
c00fe4 ¤   ¤   }
c2fb58 ¤   ¤   if ( rc == -1 ) {
962e44 ¤   ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
d2b7ef ¤   ¤   ¤   ber_free( ber, 1 );
518e4f ¤   ¤   ¤   return( -1 );
860fe4 ¤   ¤   }
289371 ¤   }
56af5a
d2602f ¤   if ( ber_printf( ber, "}}}" ) == -1 ) {
fe3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
e91ab1 ¤   ¤   ber_free( ber, 1 );
2f49fa ¤   ¤   return( -1 );
ce9371 ¤   }
34af5a
f3dd1f ¤   /* send the message */
e6a6ec ¤   return( send_initial_request( ld, LDAP_REQ_ADD, dn, ber ));
d7efe6 }
43af5a
254d2f int
794ab2 ldap_add_s( LDAP *ld, char *dn, LDAPMod **attrs )
11bb36 {
1dda47 ¤   int¤¤   msgid;
9a3932 ¤   LDAPMessage¤*res;
45af5a
004154 ¤   if ( (msgid = ldap_add( ld, dn, attrs )) == -1 )
d1df73 ¤   ¤   return( ld->ld_errno );
96af5a
5d19a3 ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
2cdf73 ¤   ¤   return( ld->ld_errno );
4faf5a
029595 ¤   return( ldap_result2error( ld, res, 1 ) );
d9efe6 }
5aaf5a
--fa29 0018557768940100090 Page 1 of addentry.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
3dc997 ·* ·addentry.c
1b495d ·*/
faaf5a
f00c68 #ifndef lint·
2607d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
6b3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
627454 #endif
74af5a
78feb2 #include <stdio.h>
13b1cb #include <ctype.h>
47324c #include <string.h>
bfaf5a
d324c3 #if PGPSOCKETSLDAP¤ /* jason */
9b65aa #include "pgpSocketsLDAP.h"
6eaf5a
56db21 #else
a1c583 #ifdef MACOS
87bea3 #include <stdlib.h>
7765e0 #include "macos.h"
c86c94 #else /* MACOS */
0ffdef #if defined( DOS ) || defined( _WIN32 )
ad5e84 #include <malloc.h>
6401b0 #ifdef DOS
fcf2ef #include "msdos.h"
cd7454 #endif
5caad8 #else /* DOS */
8cf15e #include <sys/types.h>
8a66f2 #include <sys/socket.h>
24bc39 #endif /* DOS */
8be962 #endif /* MACOS */
49df0f #endif /* PGPSOCKETSLDAP */
6eaf5a
3cb779 #include "lber.h"
76e990 #include "ldap.h"
0aaf5a
00af61 LDAPMessage *
1b1a22 ldap_delete_result_entry( LDAPMessage **list, LDAPMessage *e )
1bbb36 {
f4add5 ¤   LDAPMessage¤*tmp, *prev = NULL;
21af5a
8459d0 ¤   for ( tmp = *list; tmp != NULL && tmp != e; tmp = tmp->lm_chain )
4ca612 ¤   ¤   prev = tmp;
c9af5a
1e9279 ¤   if ( tmp == NULL )
3cef86 ¤   ¤   return( NULL );
20af5a
6dc4c4 ¤   if ( prev == NULL )
527617 ¤   ¤   *list = tmp->lm_chain;
d40e24 ¤   else
87c5ed ¤   ¤   prev->lm_chain = tmp->lm_chain;
504d54 ¤   tmp->lm_chain = NULL;
41af5a
169d1a ¤   return( tmp );
1defe6 }
b5af5a
c1314a void
b4aa08 ldap_add_result_entry( LDAPMessage **list, LDAPMessage *e )
84bb36 {
48dc18 ¤   e->lm_chain = *list;
9e8c0b ¤   *list = e;
85efe6 }
--f797 00087145a1b40100091 Page 1 of bind.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
de9805 ·* ·bind.c
56495d ·*/
4aaf5a
9e0c68 #ifndef lint·
e407d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
6b3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
d37454 #endif
9baf5a
42feb2 #include <stdio.h>
a1324c #include <string.h>
04af5a
b424c3 #if PGPSOCKETSLDAP¤ /* jason */
d465aa #include "pgpSocketsLDAP.h"
88af5a
d3db21 #else
b0c583 #ifdef MACOS
e2bea3 #include <stdlib.h>
2965e0 #include "macos.h"
d96c94 #else /* MACOS */
7601b0 #ifdef DOS
7df2ef #include "msdos.h"
766382 #ifdef NCSA
1c30d1 #include "externs.h"
aa8682 #endif /* NCSA */
28aad8 #else /* DOS */
2ff15e #include <sys/types.h>
9ea394 #ifndef WIN32¤  ¤   /* marcd */
ce66f2 #include <sys/socket.h>
0b5d8c #include <sys/time.h>
187454 #endif
1fbc39 #endif /* DOS */
78e962 #endif /* MACOS */
cc6cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
662d5f #include <winsock.h>
f97454 #endif
59df0f #endif /* PGPSOCKETSLDAP */
ccaf5a
01b779 #include "lber.h"
d1e990 #include "ldap.h"
60af5a
2eaf5a
a038e5 /*
9dd0bf ·* ldap_bind - bind to the ldap server (and X.500). ·The dn and password
3287ee ·* of the entry to which to bind are supplied, along with the authentication
7e64db ·* method to use. ·The msgid of the bind request is returned on success,
807f16 ·* -1 if there's trouble. ·Note, the kerberos support assumes the user already
a1e3c9 ·* has a valid tgt for now. ·ldap_result() should be called to find out the
bbf186 ·* outcome of the bind request.
cd775e ·*
7d305c ·* Example:
930a3f ·*¤ ldap_bind( ld, "cn=manager, o=university of michigan, c=us", "secret",
1e5489 ·*¤ ····LDAP_AUTH_SIMPLE )
8a495d ·*/
90af5a
b74d2f int
7116e6 ldap_bind( LDAP *ld, char *dn, char *passwd, int authmethod )
62bb36 {
69d8af ¤   /*
dfc5cb ¤   ·* The bind request looks like this:
7f8a87 ¤   ·*¤ BindRequest ::= SEQUENCE {
059904 ¤   ·*¤ ¤   version¤¤   INTEGER,
213656 ¤   ·*¤ ¤   name¤   ¤   DistinguishedName,¤ ·-- who
6d0e2e ¤   ·*¤ ¤   authentication¤ CHOICE {
40d08e ¤   ·*¤ ¤   ¤   simple¤ ¤   [0] OCTET STRING -- passwd
c55ffa #ifdef KERBEROS
4bafb7 ¤   ·*¤ ¤   ¤   krbv42ldap¤ [1] OCTET STRING
282e91 ¤   ·*¤ ¤   ¤   krbv42dsa¤  [2] OCTET STRING
877454 #endif
--5782 00025f81a1240100091 Page 2 of bind.c
413c91 ¤   ·*¤ ¤   }
135203 ¤   ·*¤ }
676bb5 ¤   ·* all wrapped up in an LDAPMessage sequence.
20a4e3 ¤   ·*/
4eaf5a
891c31 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_bind\n", 0, 0, 0 );
7caf5a
bfcbc6 ¤   switch ( authmethod ) {
a1952e ¤   case LDAP_AUTH_SIMPLE:
cb2728 ¤   ¤   return( ldap_simple_bind( ld, dn, passwd ) );
99af5a
fe5ffa #ifdef KERBEROS
167a94 ¤   case LDAP_AUTH_KRBV41:
aaeb0f ¤   ¤   return( ldap_kerberos_bind1( ld, dn ) );
83af5a
5295f0 ¤   case LDAP_AUTH_KRBV42:
253371 ¤   ¤   return( ldap_kerberos_bind2( ld, dn ) );
497454 #endif
b3af5a
c32f72 ¤   default:
8e6669 ¤   ¤   ld->ld_errno = LDAP_AUTH_UNKNOWN;
bd49fa ¤   ¤   return( -1 );
469371 ¤   }
8cefe6 }
dcaf5a
6138e5 /*
3e73d8 ·* ldap_bind_s - bind to the ldap server (and X.500). ·The dn and password
8387ee ·* of the entry to which to bind are supplied, along with the authentication
ee483e ·* method to use. ·This routine just calls whichever bind routine is
c0392f ·* appropriate and returns the result of the bind (e.g. LDAP_SUCCESS or
2d6df0 ·* some other error indication). ·Note, the kerberos support assumes the
150528 ·* user already has a valid tgt for now.
51775e ·*
d71b49 ·* Examples:
a04866 ·*¤ ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us",
552d7c ·*¤ ····"secret", LDAP_AUTH_SIMPLE )
c84866 ·*¤ ldap_bind_s( ld, "cn=manager, o=university of michigan, c=us",
e2965b ·*¤ ····NULL, LDAP_AUTH_KRBV4 )
1a495d ·*/
874d2f int
2c1d9d ldap_bind_s( LDAP *ld, char *dn, char *passwd, int authmethod )
61bb36 {
fbb684 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_bind_s\n", 0, 0, 0 );
c7af5a
a4cbc6 ¤   switch ( authmethod ) {
c4952e ¤   case LDAP_AUTH_SIMPLE:
8ec822 ¤   ¤   return( ldap_simple_bind_s( ld, dn, passwd ) );
5faf5a
b45ffa #ifdef KERBEROS
628ec8 ¤   case LDAP_AUTH_KRBV4:
59efc1 ¤   ¤   return( ldap_kerberos_bind_s( ld, dn ) );
e9af5a
607a94 ¤   case LDAP_AUTH_KRBV41:
0a9098 ¤   ¤   return( ldap_kerberos_bind1_s( ld, dn ) );
72af5a
0395f0 ¤   case LDAP_AUTH_KRBV42:
b5a089 ¤   ¤   return( ldap_kerberos_bind2_s( ld, dn ) );
137454 #endif
a3af5a
012f72 ¤   default:
83ae0c ¤   ¤   return( ld->ld_errno = LDAP_AUTH_UNKNOWN );
549371 ¤   }
68efe6 }
3daf5a
a9af5a
467f8d #ifdef LDAP_REFERRALS
b2314a void
dcc1d4 ldap_set_rebind_proc( LDAP *ld, int (*rebindproc)( LDAP *ld, char **dnp,
f54c23 ¤   char **passwdp, int *authmethodp, int freeit ))
c7bb36 {
1aa97a ¤   ld->ld_rebindproc = rebindproc;
25efe6 }
--5962 00114c9deed40100091 Page 3 of bind.c
1490e2 #endif /* LDAP_REFERRALS */
--7f03 0000f055ed540100092 Page 1 of cache.c
bc38e5 /*
fa9218 ·* ·Copyright (c) 1993 The Regents of the University of Michigan.
cae4d4 ·* ·All rights reserved.
02775e ·*
e03185 ·* ·cache.c - local caching support for LDAP
68495d ·*/
26af5a
c923e9 #ifndef NO_CACHE
f8af5a
c50c68 #ifndef lint·
7781a6 static char copyright[] = "@(#) Copyright (c) 1993 The Regents of the "
68f59d ¤   ¤   ¤   ··"University of Michigan.\nAll rights reserved.\n";
b77454 #endif
2caf5a
abfeb2 #include <stdio.h>
4c324c #include <string.h>
04c583 #ifdef MACOS
31bea3 #include <stdlib.h>
7a0a8b #include <time.h>
b265e0 #include "macos.h"
326c94 #else /* MACOS */
eefdef #if defined( DOS ) || defined( _WIN32 )
685e84 #include <malloc.h>
8901b0 #ifdef DOS
f1f2ef #include "msdos.h"
477454 #endif
be6382 #ifdef NCSA
4d30d1 #include "externs.h"
808682 #endif /* NCSA */
f9a184 #ifdef WINSOCK
9b0a8b #include <time.h>
49d50d #endif /* WINSOCK */
e7aad8 #else /* DOS */
6ff15e #include <sys/types.h>
c166f2 #include <sys/socket.h>
edbc39 #endif /* DOS */
7ae962 #endif /* MACOS */
336cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
fb0a8b #include <time.h>
da7454 #endif
17b779 #include "lber.h"
f7e990 #include "ldap.h"
a8745c #include "ldap-int.h"
ffaf5a
23504c #ifdef NEEDPROTOS
353a5f static int¤ ¤   cache_hash( BerElement *ber );
27c4fc static LDAPMessage¤ *msg_dup( LDAPMessage *msg );
3ef162 static int¤ ¤   request_cmp( BerElement¤*req1, BerElement *req2 );
f0bee6 static int¤ ¤   chain_contains_dn( LDAPMessage *msg, char *dn );
282bc4 static long¤¤   msg_size( LDAPMessage *msg );
05daf9 static void¤¤   check_cache_memused( LDAPCache *lc );
afad07 static void¤¤   uncache_entry_or_req( LDAP *ld, char *dn, int msgid );
6c6133 #else /* NEEDPROTOS */
ebab83 static int¤ ¤   cache_hash();
17cce5 static LDAPMessage¤ *msg_dup();
dcd456 static int¤ ¤   request_cmp();
4fe8fb static int¤ ¤   chain_contains_dn();
7ee2c1 static long¤¤   msg_size();
3f4132 static void¤¤   check_cache_memused();
eed42b static void¤¤   uncache_entry_or_req();
348634 #endif /* NEEDPROTOS */
37af5a
2aaf5a
e84d2f int
95e050 ldap_enable_cache( LDAP *ld, long timeout, long maxmem )
85bb36 {
5493b8 ¤   if ( ld->ld_cache == NULLLDCACHE ) {
aa7f87 ¤   ¤   if (( ld->ld_cache = (LDAPCache *)malloc( sizeof( LDAPCache )))
1d63b1 ¤   ¤   ····== NULLLDCACHE ) {
956150 ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
a88e4f ¤   ¤   ¤   return( -1 );
0f0fe4 ¤   ¤   }
--4c18 000445b84f640100092 Page 2 of cache.c
22ea75 ¤   ¤   (void) memset( ld->ld_cache, 0, sizeof( LDAPCache ));
2963fa ¤   ¤   ld->ld_cache->lc_memused = sizeof( LDAPCache );
9e9371 ¤   }
91af5a
dcf905 ¤   ld->ld_cache->lc_timeout = timeout;
da372f ¤   ld->ld_cache->lc_maxmem = maxmem;
7c7184 ¤   check_cache_memused( ld->ld_cache );
7a23c0 ¤   ld->ld_cache->lc_enabled = 1;
5cea61 ¤   return( 0 );
93efe6 }
7caf5a
6aaf5a
88314a void
843770 ldap_disable_cache( LDAP *ld )
78bb36 {
d608bb ¤   if ( ld->ld_cache != NULLLDCACHE ) {
96966f ¤   ¤   ld->ld_cache->lc_enabled = 0;
1c9371 ¤   }
5cefe6 }
f8af5a
9baf5a
98af5a
7a314a void
ee7545 ldap_set_cache_options( LDAP *ld, unsigned long opts )
94bb36 {
b608bb ¤   if ( ld->ld_cache != NULLLDCACHE ) {
c23b0f ¤   ¤   ld->ld_cache->lc_options = opts;
519371 ¤   }
c0efe6 }
2367c5 ¤
5baf5a
bc314a void
4bc95d ldap_destroy_cache( LDAP *ld )
09bb36 {
2108bb ¤   if ( ld->ld_cache != NULLLDCACHE ) {
9a29bb ¤   ¤   ldap_flush_cache( ld );
bd84fc ¤   ¤   free( (char *)ld->ld_cache );
1909f1 ¤   ¤   ld->ld_cache = NULLLDCACHE;
569371 ¤   }
1fefe6 }
54af5a
baaf5a
a2314a void
8bfc6e ldap_flush_cache( LDAP *ld )
b7bb36 {
a8e595 ¤   int¤¤   i;
88f3d9 ¤   LDAPMessage¤*m, *next;
34af5a
42f8da ¤   Debug( LDAP_DEBUG_TRACE, "ldap_flush_cache\n", 0, 0, 0 );
21af5a
8608bb ¤   if ( ld->ld_cache != NULLLDCACHE ) {
77f8f8 ¤   ¤   /* delete all requests in the queue */
f13155 ¤   ¤   for ( m = ld->ld_cache->lc_requests; m != NULLMSG; m = next ) {
97b024 ¤   ¤   ¤   next = m->lm_next;
d24a1b ¤   ¤   ¤   ldap_msgfree( m );
e90fe4 ¤   ¤   }
5438c9 ¤   ¤   ld->ld_cache->lc_requests = NULLMSG;
0eaf5a
a7b9c3 ¤   ¤   /* delete all messages in the cache */
bc5931 ¤   ¤   for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
a8199c ¤   ¤   ¤   for ( m = ld->ld_cache->lc_buckets[ i ];
b46e8c ¤   ¤   ¤   ····m != NULLMSG; m = next ) {
883c5b ¤   ¤   ¤   ¤   next = m->lm_next;
e3c664 ¤   ¤   ¤   ¤   ldap_msgfree( m );
b9a3a6 ¤   ¤   ¤   }
f37a3b ¤   ¤   ¤   ld->ld_cache->lc_buckets[ i ] = NULLMSG;
760fe4 ¤   ¤   }
bf63fa ¤   ¤   ld->ld_cache->lc_memused = sizeof( LDAPCache );
9c9371 ¤   }
acefe6 }
5faf5a
44af5a
--6954 00081aee5f440100092 Page 3 of cache.c
b3314a void
f6a4ae ldap_uncache_request( LDAP *ld, int msgid )
27bb36 {
487bf3 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_uncache_request %d ld_cache %x\n",
04aba4 ¤   ····msgid, ld->ld_cache, 0 );
60af5a
89b149 ¤   uncache_entry_or_req( ld, NULL, msgid );
9eefe6 }
6faf5a
5aaf5a
2e314a void
099773 ldap_uncache_entry( LDAP *ld, char *dn )
96bb36 {
b18f76 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_uncache_entry %s ld_cache %x\n",
420521 ¤   ····dn, ld->ld_cache, 0 );
8caf5a
f59278 ¤   uncache_entry_or_req( ld, dn, 0 );
a0efe6 }
45af5a
b2af5a
382978 static void
976761 uncache_entry_or_req( LDAP *ld,
fee2ac ¤   char *dn,¤  ¤   /* if non-NULL, uncache entry */
a89acf ¤   int msgid )¤¤   /* request to uncache (if dn == NULL) */
6dbb36 {
9fe595 ¤   int¤¤   i;
658e47 ¤   LDAPMessage¤*m, *prev, *next;
c5af5a
a04030 ¤   Debug( LDAP_DEBUG_TRACE,
0e9f2a ¤   ····"ldap_uncache_entry_or_req ·dn %s ·msgid %d ·ld_cache %x\n",
8463b1 ¤   ····dn, msgid, ld->ld_cache );
2eaf5a
a893b8 ¤   if ( ld->ld_cache == NULLLDCACHE ) {
9a2ec1 ¤   ····return;
009371 ¤   }
05af5a
ecc47f ¤   /* first check the request queue */
aebd82 ¤   prev = NULLMSG;
887f22 ¤   for ( m = ld->ld_cache->lc_requests; m != NULLMSG; m = next ) {
21a40c ¤   ¤   next = m->lm_next;
803486 ¤   ¤   if (( dn != NULL && chain_contains_dn( m, dn )) ||
e4dc15 ¤   ¤   ¤   ( dn == NULL && m->lm_msgid == msgid )) {
59a109 ¤   ¤   ¤   if ( prev == NULLMSG ) {
3890f9 ¤   ¤   ¤   ¤   ld->ld_cache->lc_requests = next;
1c042d ¤   ¤   ¤   } else {
ecc66c ¤   ¤   ¤   ¤   prev->lm_next = next;
d6a3a6 ¤   ¤   ¤   }
61f984 ¤   ¤   ¤   ld->ld_cache->lc_memused -= msg_size( m );
834a1b ¤   ¤   ¤   ldap_msgfree( m );
5345a6 ¤   ¤   } else {
dfe1d0 ¤   ¤   ¤   prev = m;
cd0fe4 ¤   ¤   }
f99371 ¤   }
3baf5a
f789d5 ¤   /* now check the rest of the cache */
d90a2a ¤   for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
4ac776 ¤   ¤   prev = NULLMSG;
5ac33d ¤   ¤   for ( m = ld->ld_cache->lc_buckets[ i ]; m != NULLMSG;
487657 ¤   ¤   ····m = next ) {
46b024 ¤   ¤   ¤   next = m->lm_next;
3a3464 ¤   ¤   ¤   if (( dn != NULL && chain_contains_dn( m, dn )) ||
38df62 ¤   ¤   ¤   ¤   ( dn == NULL && m->lm_msgid == msgid )) {
32a4e4 ¤   ¤   ¤   ¤   if ( prev == NULLMSG ) {
0daea5 ¤   ¤   ¤   ¤   ¤   ld->ld_cache->lc_buckets[ i ] = next;
cdb5fc ¤   ¤   ¤   ¤   } else {
06fa82 ¤   ¤   ¤   ¤   ¤   prev->lm_next = next;
b62613 ¤   ¤   ¤   ¤   }
b6febf ¤   ¤   ¤   ¤   ld->ld_cache->lc_memused -= msg_size( m );
55c664 ¤   ¤   ¤   ¤   ldap_msgfree( m );
10042d ¤   ¤   ¤   } else {
462665 ¤   ¤   ¤   ¤   prev = m;
81a3a6 ¤   ¤   ¤   }
--a06e 000f40d32d140100092 Page 4 of cache.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
6cefe6 }
99af5a
3caf5a
e8314a void
4dd9fe add_request_to_cache( LDAP *ld, unsigned long msgtype, BerElement *request )
d7bb36 {
509923 ¤   LDAPMessage¤*new;
2eb0b9 ¤   long¤   ¤   len;
9daf5a
6392a5 ¤   Debug( LDAP_DEBUG_TRACE, "add_request_to_cache\n", 0, 0, 0 );
73af5a
df7920 ¤   ld->ld_errno = LDAP_SUCCESS;
ddabea ¤   if ( ld->ld_cache == NULLLDCACHE ||
752a88 ¤   ····( ld->ld_cache->lc_enabled == 0 )) {
e999bf ¤   ¤   return;
ad9371 ¤   }
5daf5a
1bb145 ¤   if (( new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) ))
d22639 ¤   ····!= NULL ) {
473876 ¤   ¤   if (( new->lm_ber = alloc_ber_with_options( ld )) == NULLBER) {
55ffca ¤   ¤   ¤   free( (char *)new );
610ecc ¤   ¤   ¤   return;
670fe4 ¤   ¤   }
fec4ea ¤   ¤   len = request->ber_ptr - request->ber_buf;
9e4c60 ¤   ¤   if (( new->lm_ber->ber_buf = (char *) malloc( (size_t)len ))
5e468f ¤   ¤   ····== NULL ) {
823e50 ¤   ¤   ¤   ber_free( new->lm_ber, 0 );
b8ffca ¤   ¤   ¤   free( (char *)new );
3e6150 ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
e40ecc ¤   ¤   ¤   return;
cd0fe4 ¤   ¤   }
a78573 ¤   ¤   SAFEMEMCPY( new->lm_ber->ber_buf, request->ber_buf,
0b28fe ¤   ¤   ····(size_t)len );
90c6fb ¤   ¤   new->lm_ber->ber_ptr = new->lm_ber->ber_buf;
463ac2 ¤   ¤   new->lm_ber->ber_end = new->lm_ber->ber_buf + len;
32bd36 ¤   ¤   new->lm_msgid = ld->ld_msgid;
694c40 ¤   ¤   new->lm_msgtype = msgtype;;
affbaf ¤   ¤   new->lm_next = ld->ld_cache->lc_requests;
fbab98 ¤   ¤   ld->ld_cache->lc_requests = new;
72f037 ¤   } else {
d66f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
2c9371 ¤   }
37efe6 }
f3af5a
1baf5a
e0314a void
c14e32 add_result_to_cache( LDAP *ld, LDAPMessage *result )
d2bb36 {
91466a ¤   LDAPMessage¤*m, **mp, *req, *new, *prev;
cbfb17 ¤   int¤¤   err, keep;
20af5a
57041d ¤   Debug( LDAP_DEBUG_TRACE, "add_result_to_cache: id %d, type %d\n",·
49a3be ¤   ¤   result->lm_msgid, result->lm_msgtype, 0 );
1eaf5a
b7abea ¤   if ( ld->ld_cache == NULLLDCACHE ||
e82a88 ¤   ····( ld->ld_cache->lc_enabled == 0 )) {
1fe313 ¤   ¤   Debug( LDAP_DEBUG_TRACE, "artc: cache disabled\n", 0, 0, 0 );
0d99bf ¤   ¤   return;
4c9371 ¤   }
77af5a
be35aa ¤   if ( result->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
657681 ¤   ····result->lm_msgtype != LDAP_RES_SEARCH_RESULT &&
9a2576 ¤   ····result->lm_msgtype != LDAP_RES_COMPARE ) {
e41b17 ¤   ¤   /*
c34be4 ¤   ¤   ·* only cache search and compare operations
fd9de3 ¤   ¤   ·*/
a8fb66 ¤   ¤   Debug( LDAP_DEBUG_TRACE,
78eb48 ¤   ¤   ····"artc: only caching search & compare operations\n",
02cda5 ¤   ¤   ····0, 0, 0 );
f499bf ¤   ¤   return;
--152e 000b90f49db40100092 Page 5 of cache.c
a19371 ¤   }
93af5a
14d8af ¤   /*
8f16ba ¤   ·* if corresponding request is in the lc_requests list, add this
7ca34b ¤   ·* result to it. ·if this result completes the results for the
b73a27 ¤   ·* request, add the request/result chain to the cache proper.
5da4e3 ¤   ·*/
1fbd82 ¤   prev = NULLMSG;
4dbfc2 ¤   for ( m = ld->ld_cache->lc_requests; m != NULL; m = m->lm_next ) {
b8a7f7 ¤   ¤   if ( m->lm_msgid == result->lm_msgid ) {
91cdcb ¤   ¤   ¤   break;
ba0fe4 ¤   ¤   }
17db4a ¤   ¤   prev = m;
c19371 ¤   }
ffaf5a
f272d2 ¤   if ( m != NULLMSG ) {¤  /* found request; add to end of chain */
5eaf91 ¤   ¤   req = m;
d7e4ae ¤   ¤   for ( ; m->lm_chain != NULLMSG; m = m->lm_chain )
bbb110 ¤   ¤   ¤   ;
7e2564 ¤   ¤   if (( new = msg_dup( result )) != NULLMSG ) {
bee64f ¤   ¤   ¤   new->lm_chain = NULLMSG;
63ba8d ¤   ¤   ¤   m->lm_chain = new;
78c60e ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
d8af78 ¤   ¤   ¤   ····"artc: result added to cache request chain\n",
2f2f44 ¤   ¤   ¤   ····0, 0, 0 );
280fe4 ¤   ¤   }
d0f0d2 ¤   ¤   if ( result->lm_msgtype == LDAP_RES_SEARCH_RESULT ||
2e0747 ¤   ¤   ····result->lm_msgtype == LDAP_RES_COMPARE ) {
fd7aad ¤   ¤   ¤   /*
98629d ¤   ¤   ¤   ·* this result completes the chain of results
62c96b ¤   ¤   ¤   ·* add to cache proper if appropriate
4e8753 ¤   ¤   ¤   ·*/
bad654 ¤   ¤   ¤   keep = 0;¤  /* pessimistic */
30e8d7 ¤   ¤   ¤   err = ldap_result2error( ld, result, 0 );
5a3887 ¤   ¤   ¤   if ( err == LDAP_SUCCESS ||
ac6bdf ¤   ¤   ¤   ····( result->lm_msgtype == LDAP_RES_COMPARE &&
68d62a ¤   ¤   ¤   ····( err == LDAP_COMPARE_FALSE ||
d44f82 ¤   ¤   ¤   ····err == LDAP_COMPARE_TRUE ||
0d8888 ¤   ¤   ¤   ····err == LDAP_NO_SUCH_ATTRIBUTE ))) {
ef818c ¤   ¤   ¤   ¤   keep = 1;
3aa3a6 ¤   ¤   ¤   }
e8af5a
3e113a ¤   ¤   ¤   if ( ld->ld_cache->lc_options == 0 ) {
9cf95c ¤   ¤   ¤   ¤   if ( err == LDAP_SIZELIMIT_EXCEEDED ) {
17a338 ¤   ¤   ¤   ¤   ····keep = 1;
f22613 ¤   ¤   ¤   ¤   }
ef0596 ¤   ¤   ¤   } else if (( ld->ld_cache->lc_options &
9d85e6 ¤   ¤   ¤   ¤   LDAP_CACHE_OPT_CACHEALLERRS ) != 0 ) {
9e818c ¤   ¤   ¤   ¤   keep = 1;
12a3a6 ¤   ¤   ¤   }
86af5a
aaa109 ¤   ¤   ¤   if ( prev == NULLMSG ) {
647f1a ¤   ¤   ¤   ¤   ld->ld_cache->lc_requests = req->lm_next;
06042d ¤   ¤   ¤   } else {
6752e3 ¤   ¤   ¤   ¤   prev->lm_next = req->lm_next;
8ea3a6 ¤   ¤   ¤   }
d5af5a
d629bd ¤   ¤   ¤   if ( !keep ) {
63c3e3 ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
6b629c ¤   ¤   ¤   ¤   ····"artc: not caching result with error %d\n",
3fd2ba ¤   ¤   ¤   ¤   ····err, 0, 0 );
f3269d ¤   ¤   ¤   ¤   ldap_msgfree( req );
ab042d ¤   ¤   ¤   } else {
34232b ¤   ¤   ¤   ¤   mp = &ld->ld_cache->lc_buckets[
5530a7 ¤   ¤   ¤   ¤   ····cache_hash( req->lm_ber ) ];
9b1998 ¤   ¤   ¤   ¤   req->lm_next = *mp;
c45188 ¤   ¤   ¤   ¤   *mp = req;
a31671 ¤   ¤   ¤   ¤   req->lm_time = (long) time( NULL );
2bf313 ¤   ¤   ¤   ¤   ld->ld_cache->lc_memused += msg_size( req );
0376ba ¤   ¤   ¤   ¤   check_cache_memused( ld->ld_cache );
3fc3e3 ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
b9fc63 ¤   ¤   ¤   ¤   ····"artc: cached result with error %d\n",
--1e79 00040e42b5f40100092 Page 6 of cache.c
57d2ba ¤   ¤   ¤   ¤   ····err, 0, 0 );
81a3a6 ¤   ¤   ¤   }
7c0fe4 ¤   ¤   }
c4f037 ¤   } else {
50b036 ¤   ¤   Debug( LDAP_DEBUG_TRACE, "artc: msgid not in request list\n",
b8cda5 ¤   ¤   ····0, 0, 0 );
3d9371 ¤   }
24efe6 }
88af5a
6daf5a
7338e5 /*
cc1500 ·* look in the cache for this request
5acaee ·* return 0 if found, -1 if not
379d00 ·* if found, the corresponding result messages are added to the incoming
b85aca ·* queue with the correct (new) msgid so that subsequent ldap_result calls
5668b0 ·* will find them.
dd495d ·*/
0d4d2f int
be8af6 check_cache( LDAP *ld, unsigned long msgtype, BerElement *request )
68bb36 {
1599a9 ¤   LDAPMessage¤*m, *new, *prev, *next;
92cb6f ¤   BerElement¤ reqber;
45f544 ¤   int¤¤   first, hash;
1e1143 ¤   unsigned long¤  validtime;
91af5a
f38c5e ¤   Debug( LDAP_DEBUG_TRACE, "check_cache\n", 0, 0, 0 );
feaf5a
86abea ¤   if ( ld->ld_cache == NULLLDCACHE ||
1c2a88 ¤   ····( ld->ld_cache->lc_enabled == 0 )) {
2649fa ¤   ¤   return( -1 );
099371 ¤   }
74af5a
83e22b ¤   reqber.ber_buf = reqber.ber_ptr = request->ber_buf;
eafff7 ¤   reqber.ber_end = request->ber_ptr;
ccaf5a
d6ac79 ¤   validtime = (long)time( NULL ) - ld->ld_cache->lc_timeout;
6eaf5a
e4bd82 ¤   prev = NULLMSG;
78038f ¤   hash = cache_hash( &reqber );
eb67ec ¤   for ( m = ld->ld_cache->lc_buckets[ hash ]; m != NULLMSG; m = next ) {
b09dfb ¤   ¤   Debug( LDAP_DEBUG_TRACE,"cc: examining id %d,type %d\n",
899518 ¤   ¤   ····m->lm_msgid, m->lm_msgtype, 0 );
1c8ea2 ¤   ¤   if ( m->lm_time < validtime ) {
79e848 ¤   ¤   ¤   /* delete expired message */
d4b024 ¤   ¤   ¤   next = m->lm_next;
2b58c9 ¤   ¤   ¤   if ( prev == NULL ) {
75140e ¤   ¤   ¤   ¤   ld->ld_cache->lc_buckets[ hash ] = next;
08042d ¤   ¤   ¤   } else {
69c66c ¤   ¤   ¤   ¤   prev->lm_next = next;
47a3a6 ¤   ¤   ¤   }
bf01d6 ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "cc: expired id %d\n",
f599cc ¤   ¤   ¤   ····m->lm_msgid, 0, 0 );
b0f984 ¤   ¤   ¤   ld->ld_cache->lc_memused -= msg_size( m );
db4a1b ¤   ¤   ¤   ldap_msgfree( m );
2645a6 ¤   ¤   } else {
5e91a8 ¤   ¤   ····if ( m->lm_msgtype == (int)msgtype &&
0136e8 ¤   ¤   ¤   request_cmp( m->lm_ber, &reqber ) == 0 ) {
9013b0 ¤   ¤   ¤   ····break;
505f30 ¤   ¤   ····}
80bfd7 ¤   ¤   ····next = m->lm_next;
fa4a30 ¤   ¤   ····prev = m;
b40fe4 ¤   ¤   }
bf9371 ¤   }
34af5a
9a6f0c ¤   if ( m == NULLMSG ) {
1049fa ¤   ¤   return( -1 );
7c9371 ¤   }
3baf5a
05d8af ¤   /*
4ae17c ¤   ·* add duplicates of responses to incoming queue
fca4e3 ¤   ·*/
408991 ¤   first = 1;
--9f28 000504bf27e40100092 Page 7 of cache.c
7db8b9 ¤   for ( m = m->lm_chain; m != NULLMSG; m = m->lm_chain ) {
6733f3 ¤   ¤   if (( new = msg_dup( m )) == NULLMSG ) {
958e4f ¤   ¤   ¤   return( -1 );
040fe4 ¤   ¤   }
50af5a
d0bd36 ¤   ¤   new->lm_msgid = ld->ld_msgid;
62db27 ¤   ¤   new->lm_chain = NULLMSG;
9cfff6 ¤   ¤   if ( first ) {
279213 ¤   ¤   ¤   new->lm_next = ld->ld_responses;
cc82ab ¤   ¤   ¤   ld->ld_responses = new;
570a07 ¤   ¤   ¤   first = 0;
2145a6 ¤   ¤   } else {
9dbe5f ¤   ¤   ¤   prev->lm_chain = new;
c80fe4 ¤   ¤   }
913727 ¤   ¤   prev = new;
e77f5a ¤   ¤   Debug( LDAP_DEBUG_TRACE, "cc: added type %d\n",
988152 ¤   ¤   ····new->lm_msgtype, 0, 0 );
449371 ¤   }
5aaf5a
f520fe ¤   Debug( LDAP_DEBUG_TRACE, "cc: result returned from cache\n", 0, 0, 0 );
58ea61 ¤   return( 0 );
95efe6 }
97af5a
b4af5a
68beb7 static int
a15e74 cache_hash( BerElement *ber )
84bb36 {
8d137e ¤   BerElement¤ bercpy;
2b93e7 ¤   unsigned long¤  len;
30af5a
a0d8af ¤   /*
7c46eb ·········* just take the length of the packet and mod with # of buckets
a7a4e3 ¤   ·*/
d8603b ¤   bercpy = *ber;
7f7c42 ¤   if ( ber_skip_tag( &bercpy, &len ) == LBER_ERROR
8e9809 ¤   ¤   || ber_scanf( &bercpy, "x" ) == LBER_ERROR ) {
936a5c ¤   ····len = 0;¤   /* punt: just return zero */
28f037 ¤   } else {
450aa0 ¤   ····len = bercpy.ber_end - bercpy.ber_ptr;
aa9371 ¤   }
36af5a
c5faa9 ¤   Debug( LDAP_DEBUG_TRACE, "cache_hash: len is %ld, returning %ld\n",
eeb88a ¤   ····len, len % LDAP_CACHE_BUCKETS, 0 );
779e37 ¤   return( (int) ( len % LDAP_CACHE_BUCKETS ));
3befe6 }
b9af5a
5faf5a
644af2 static LDAPMessage *
bffe88 msg_dup( LDAPMessage *msg )
f5bb36 {
3a9923 ¤   LDAPMessage¤*new;
dbb0b9 ¤   long¤   ¤   len;
0baf5a
0381c4 ¤   if (( new = (LDAPMessage *)malloc( sizeof(LDAPMessage))) != NULL ) {
3056da ¤   ¤   *new = *msg;¤   /* struct copy */
f43c55 ¤   ¤   if (( new->lm_ber = ber_dup( msg->lm_ber )) == NULLBER ) {
f5ffca ¤   ¤   ¤   free( (char *)new );
4391c2 ¤   ¤   ¤   return( NULLMSG );
be0fe4 ¤   ¤   }
24ac38 ¤   ¤   len = msg->lm_ber->ber_end - msg->lm_ber->ber_buf;
da195a ¤   ¤   if (( new->lm_ber->ber_buf = (char *) malloc(
8a6fa0 ¤   ¤   ····(size_t)len )) == NULL ) {
f13e50 ¤   ¤   ¤   ber_free( new->lm_ber, 0 );
86ffca ¤   ¤   ¤   free( (char *)new );
4b91c2 ¤   ¤   ¤   return( NULLMSG );
760fe4 ¤   ¤   }
aca959 ¤   ¤   SAFEMEMCPY( new->lm_ber->ber_buf, msg->lm_ber->ber_buf,
a928fe ¤   ¤   ····(size_t)len );
847018 ¤   ¤   new->lm_ber->ber_ptr = new->lm_ber->ber_buf +
dc1297 ¤   ¤   ¤   ( msg->lm_ber->ber_ptr - msg->lm_ber->ber_buf );
f73ac2 ¤   ¤   new->lm_ber->ber_end = new->lm_ber->ber_buf + len;
509371 ¤   }
--c88a 0002c04ab5640100092 Page 8 of cache.c
e0af5a
2cd000 ¤   return( new );
86efe6 }
a0af5a
0aaf5a
41beb7 static int
28092f request_cmp( BerElement *req1, BerElement *req2 )
d7bb36 {
0693e7 ¤   unsigned long¤  len;
17e634 ¤   BerElement¤ r1, r2;
51af5a
d33d22 ¤   r1 = *req1;¤/* struct copies */
501e08 ¤   r2 = *req2;
81af5a
44d8af ¤   /*
643e74 ¤   ·* skip the enclosing tags (sequence markers) and the msg ids
caa4e3 ¤   ·*/
253d4f ¤   if ( ber_skip_tag( &r1, &len ) == LBER_ERROR || ber_scanf( &r1, "x" )
1395f9 ¤   ····== LBER_ERROR ) {
2cdb01 ¤   ····return( -1 );
a89371 ¤   }
0a5f05 ¤   if ( ber_skip_tag( &r2, &len ) == LBER_ERROR || ber_scanf( &r2, "x" )·
5595f9 ¤   ····== LBER_ERROR ) {
50db01 ¤   ····return( -1 );
b19371 ¤   }
82af5a
d1d8af ¤   /*
5c34cc ¤   ·* check remaining length and bytes if necessary
92a4e3 ¤   ·*/
5096f1 ¤   if (( len = r1.ber_end - r1.ber_ptr ) !=·
d82ce6 ¤   ¤   (unsigned long) (r2.ber_end - r2.ber_ptr) ) {
6a09a2 ¤   ¤   return( -1 );¤  /* different lengths */
659371 ¤   }
37bba6 ¤   return( memcmp( r1.ber_ptr, r2.ber_ptr, (size_t)len ));
891862 }¤
f2af5a
03af5a
69beb7 static int
78909a chain_contains_dn( LDAPMessage *msg, char *dn )
3abb36 {
08655e ¤   LDAPMessage¤*m;
8028d5 ¤   BerElement¤ ber;
31c860 ¤   long¤   ¤   msgid;
6c5da6 ¤   char¤   ¤   *s;
4c8574 ¤   int¤¤   rc;
f3af5a
e1af5a
dad8af ¤   /*
2d5710 ¤   ·* first check the base or dn of the request
2da4e3 ¤   ·*/
33f30f ¤   ber = *msg->lm_ber;¤/* struct copy */
b67880 ¤   if ( ber_scanf( &ber, "{i{a", &msgid, &s ) != LBER_ERROR ) {
9af683 ¤   ····rc = ( strcasecmp( dn, s ) == 0 ) ? 1 : 0;
f133a2 ¤   ····free( s );
917fb5 ¤   ····if ( rc != 0 ) {
5257f8 ¤   ¤   return( rc );
91f372 ¤   ····}
7a9371 ¤   }
c7af5a
fb35bc ¤   if ( msg->lm_msgtype == LDAP_REQ_COMPARE ) {
62abea ¤   ¤   return( 0 );
c69371 ¤   }
30af5a
96d8af ¤   /*
e87508 ¤   ·* now check the dn of each search result
9ea4e3 ¤   ·*/
026f95 ¤   rc = 0;
c09f87 ¤   for ( m = msg->lm_chain; m != NULLMSG && rc == 0 ; m = m->lm_chain ) {
4ffe5a ¤   ¤   if ( m->lm_msgtype != LDAP_RES_SEARCH_ENTRY ) {
d617f5 ¤   ¤   ¤   continue;
a40fe4 ¤   ¤   }
2c4718 ¤   ¤   ber = *m->lm_ber;¤  /* struct copy */
--214f 0009bb4e2ee40100092 Page 9 of cache.c
36cec8 ¤   ¤   if ( ber_scanf( &ber, "{a", &s ) != LBER_ERROR ) {
1fcd9c ¤   ¤   ¤   rc = ( strcasecmp( dn, s ) == 0 ) ? 1 : 0;
51efee ¤   ¤   ¤   free( s );
230fe4 ¤   ¤   }
e29371 ¤   }
c2af5a
e36d62 ¤   return( rc );
e9efe6 }
fbaf5a
89af5a
0977fd static long
548d48 msg_size( LDAPMessage *msg )
f6bb36 {
69655e ¤   LDAPMessage¤*m;
450266 ¤   long¤   ¤   size;
ddaf5a
4cf73e ¤   size = 0;
3497a2 ¤   for ( m = msg; m != NULLMSG; m = m->lm_chain ) {
b133b5 ¤   ¤   size += ( sizeof( LDAPMessage ) + m->lm_ber->ber_end -
569c9d ¤   ¤   ····m->lm_ber->ber_buf );
dd9371 ¤   }
d6af5a
7c4b28 ¤   return( size );
91efe6 }
e0af5a
90af5a
3fcf17 #define THRESHOLD_FACTOR¤   3 / 4
c54ed2 #define SIZE_FACTOR¤¤   2 / 3
3eaf5a
572978 static void
4ee343 check_cache_memused( LDAPCache *lc )
41bb36 {
bd38e5 /*
b37f82 ·* this routine is called to check if the cache is too big (lc_maxmem >
c7a7b2 ·* minimum cache size and lc_memused > lc_maxmem). ·If too big, it reduces
60590d ·* the cache size to < SIZE_FACTOR * lc_maxmem. The algorithm is as follows:
3c7ef2 ·* ···remove_threshold = lc_timeout seconds;
2c27e2 ·* ···do {
144378 ·* ·······remove everything older than remove_threshold seconds;
46d950 ·* ·······remove_threshold = remove_threshold * THRESHOLD_FACTOR;
e86db0 ·* ···} while ( cache size is > SIZE_FACTOR * lc_maxmem )
57495d ·*/
3fe595 ¤   int¤¤   i;
8077ab ¤   unsigned long¤  remove_threshold, validtime;
bf8e47 ¤   LDAPMessage¤*m, *prev, *next;
59af5a
d0148f ¤   Debug( LDAP_DEBUG_TRACE,·
9b6fac ¤   ····"check_cache_memused: %ld bytes in use (%ld max)\n",
a5424b ¤   ····lc->lc_memused, lc->lc_maxmem, 0 );
1caf5a
1b64bb ¤   if ( lc->lc_maxmem <= sizeof( LDAPCache )
db3574 ¤   ····|| lc->lc_memused <= lc->lc_maxmem * SIZE_FACTOR ) {
6b99bf ¤   ¤   return;
429371 ¤   }
fcaf5a
7dc3c8 ¤   remove_threshold = lc->lc_timeout;
ce246a ¤   while ( lc->lc_memused > lc->lc_maxmem * SIZE_FACTOR ) {
728d70 ¤   ¤   validtime = (long)time( NULL ) - remove_threshold;
795931 ¤   ¤   for ( i = 0; i < LDAP_CACHE_BUCKETS; ++i ) {
f93113 ¤   ¤   ¤   prev = NULLMSG;
025eb3 ¤   ¤   ¤   for ( m = lc->lc_buckets[ i ]; m != NULLMSG;
bd420a ¤   ¤   ¤   ····m = next ) {
a63c5b ¤   ¤   ¤   ¤   next = m->lm_next;
f91e94 ¤   ¤   ¤   ¤   if ( m->lm_time < validtime ) {
c6a25c ¤   ¤   ¤   ¤   ¤   if ( prev == NULLMSG ) {
eec96f ¤   ¤   ¤   ¤   ¤   ¤   lc->lc_buckets[ i ] = next;
5081a1 ¤   ¤   ¤   ¤   ¤   } else {
03c347 ¤   ¤   ¤   ¤   ¤   ¤   prev->lm_next = next;
cb1c89 ¤   ¤   ¤   ¤   ¤   }
9d5874 ¤   ¤   ¤   ¤   ¤   lc->lc_memused -= msg_size( m );
67c55b ¤   ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
9bd6ce ¤   ¤   ¤   ¤   ¤   ····"ccm: removed %d\n",
--b9ee 0010b0315ff40100092 Page 10 of cache.c
8b9a99 ¤   ¤   ¤   ¤   ¤   ····m->lm_msgid, 0, 0 );
b18797 ¤   ¤   ¤   ¤   ¤   ldap_msgfree( m );
bcb5fc ¤   ¤   ¤   ¤   } else {
b3af31 ¤   ¤   ¤   ¤   ¤   prev = m;
bd2613 ¤   ¤   ¤   ¤   }
c5a3a6 ¤   ¤   ¤   }
c50fe4 ¤   ¤   }
e91914 ¤   ¤   remove_threshold *= THRESHOLD_FACTOR;
c09371 ¤   }
a9af5a
86a693 ¤   Debug( LDAP_DEBUG_TRACE, "ccm: reduced usage to %ld bytes\n",
4d2a56 ¤   ····lc->lc_memused, 0, 0 );
cbefe6 }
b6af5a
0be842 #endif /* !NO_CACHE */
--6da6 000a77deada40100093 Page 1 of charset.c
bc38e5 /*
5ce36d ·* ·Copyright (c) 1995 Regents of the University of Michigan.
a8e4d4 ·* ·All rights reserved.
42775e ·*
829a2a ·* ·charset.c
7a495d ·*/
edaf5a
bf1157 #if defined( DOS )
9f38e5 /*
5cc167 ·* This MUST precede "#ifdef STR_TRANSLATION"
8afa5d ·* because STR_TRANSLATION and friends are defined in msdos.h.
b3495d ·*/
f6f2ef #include "msdos.h"
dbbc39 #endif /* DOS */
8eaf5a
ccf52a #ifdef STR_TRANSLATION
89af5a
9f0c68 #ifndef lint·
01a4ec static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University "
6b3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
0a7454 #endif
8caf5a
64feb2 #include <stdio.h>
26324c #include <string.h>
b6af5a
79c583 #ifdef MACOS
f1bea3 #include <stdlib.h>
6265e0 #include "macos.h"
74e962 #endif /* MACOS */
d2af5a
1486ae #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 ) && !defined(VMS)
765d8c #include <sys/time.h>
5bf15e #include <sys/types.h>
6266f2 #include <sys/socket.h>
7c4a90 #include <sys/param.h>
ab7454 #endif
05b779 #include "lber.h"
94e990 #include "ldap.h"
ed745c #include "ldap-int.h"
a5af5a
12af5a
8c314a void
194a9c ldap_set_string_translators( LDAP *ld, BERTranslateProc encode_proc,
b3de37 ¤   BERTranslateProc decode_proc )
02bb36 {
b86960 ¤   ld->ld_lber_encode_translate_proc = encode_proc;
75ed7d ¤   ld->ld_lber_decode_translate_proc = decode_proc;
95efe6 }
35af5a
20af5a
51314a void
89294f ldap_enable_translation( LDAP *ld, LDAPMessage *entry, int enable )
a8bb36 {
873df4 ¤   char¤   *optionsp;
4daf5a
88410d ¤   optionsp = ( entry == NULLMSG ) ? &ld->ld_lberoptions :
b216b0 ¤   ····&entry->lm_ber->ber_options;
c91b52 ¤   ¤
8318d7 ¤   if ( enable ) {
fbd9eb ¤   ¤   *optionsp |= LBER_TRANSLATE_STRINGS;
0af037 ¤   } else {
e531e1 ¤   ¤   *optionsp &= ~LBER_TRANSLATE_STRINGS;
409371 ¤   }
1befe6 }
77af5a
dfaf5a
f14d2f int
89eb05 ldap_translate_from_t61( LDAP *ld, char **bufp, unsigned long *lenp,
ef9576 ····int free_input )
f0bb36 {
6127d1 ¤   if ( ld->ld_lber_decode_translate_proc == NULL ) {
a701b3 ¤   ¤   return( LDAP_SUCCESS );
--0b9b 0003aca615b40100093 Page 2 of charset.c
a19371 ¤   }
29da86 ¤   ····
c8b104 ¤   return( (*ld->ld_lber_decode_translate_proc)( bufp, lenp, free_input ));
ceefe6 }
b3af5a
5caf5a
d64d2f int
6c0459 ldap_translate_to_t61( LDAP *ld, char **bufp, unsigned long *lenp,
229576 ····int free_input )
79bb36 {
87a593 ¤   if ( ld->ld_lber_encode_translate_proc == NULL ) {
3701b3 ¤   ¤   return( LDAP_SUCCESS );
8d9371 ¤   }
53da86 ¤   ····
0382ba ¤   return( (*ld->ld_lber_encode_translate_proc)( bufp, lenp, free_input ));
a6efe6 }
f5af5a
e0af5a
1638e5 /*
e08b52 ·** Character translation routine notes:
41775e ·*
3807c6 ·* On entry: ·bufp points to a "string" to be converted (not necessarily
65d51f ·* ·zero-terminated) and buflenp points to the length of the buffer.
e4775e ·*
7e168d ·* On exit: ·bufp should point to a malloc'd result. ·If free_input is
14bbe2 ·* ·non-zero then the original bufp will be freed. ·*buflenp should be
c62702 ·* ·set to the new length. ·Zero bytes in the input buffer must be left
464c6b ·* ·as zero bytes.
ae775e ·*
a89298 ·* Return values: any ldap error code (LDAP_SUCCESS if all goes well).
27495d ·*/
98af5a
8faf5a
6c8068 #ifdef LDAP_CHARSET_8859
fcaf5a
97d92c #if LDAP_CHARSET_8859 == 88591
07bac8 #define ISO_8859 1
19ec49 #elif LDAP_CHARSET_8859 == 88592
7090a0 #define ISO_8859 2
3af591 #elif LDAP_CHARSET_8859 == 88593
b58978 #define ISO_8859 3
85b899 #elif LDAP_CHARSET_8859 == 88594
64c470 #define ISO_8859 4
f4a141 #elif LDAP_CHARSET_8859 == 88595
4bdda8 #define ISO_8859 5
e08b29 #elif LDAP_CHARSET_8859 == 88596
faf7c0 #define ISO_8859 6
e292f1 #elif LDAP_CHARSET_8859 == 88597
1eee18 #define ISO_8859 7
431139 #elif LDAP_CHARSET_8859 == 88598
e66dd0 #define ISO_8859 8
2c08e1 #elif LDAP_CHARSET_8859 == 88599
207408 #define ISO_8859 9
5ed4c5 #elif LDAP_CHARSET_8859 == 885910
05ae76 #define ISO_8859 10
9fdb21 #else
d1a310 #define ISO_8859 0
797454 #endif
2baf5a
df38e5 /*
1d95e7 ·* the following ISO_8859 to/afrom T.61 character set translation code is
353e61 ·* based on the code found in Enrique Silvestre Mora's iso-t61.c, found
e52e43 ·* as part of this package:
513fd9 ·* ··ftp://pereiii.uji.es/pub/uji-ftp/unix/ldap/iso-t61.translation.tar.Z
654712 ·* Enrique is now (10/95) at this address: enrique.silvestre@uv.es
82775e ·*
aaa49c ·* changes made by mcs@umich.edu 12 October 1995:
aded6d ·* ··Change calling conventions of iso8859_t61() and t61_iso8859() to
eebed3 ·*¤ match libldap conventions; rename to ldap_8859_to_t61() and
8ee4f9 ·*¤ ldap_t61_to_8859().
a0354b ·* ··Change conversion routines to deal with non-zero terminated strings.
3aafdd ·* ··ANSI-ize functions and include prototypes.
--08a6 00025a1a40a40100093 Page 3 of charset.c
47495d ·*/
44af5a
9c42c1 /* iso-t61.c - ISO-T61 translation routines (version: 0.2.1, July-1994) */
9438e5 /*
6c058a ·* Copyright (c) 1994 Enrique Silvestre Mora, Universitat Jaume I, Spain.
84599a ·* All rights reserved.
c5775e ·*
52b855 ·* Redistribution and use in source and binary forms are permitted
0b9795 ·* provided that this notice is preserved and that due credit is given
57d8ad ·* to the Universitat Jaume I. The name of the University
7e8805 ·* may not be used to endorse or promote products derived from this
3974fe ·* software without specific prior written permission. This software
332a32 ·* is provided ``as is'' without express or implied warranty.
677fe0 */
eaaf5a
82af5a
c4feb2 #include <stdio.h>
c3bea3 #include <stdlib.h>
48324c #include <string.h>
0baf5a
a999cc /* Character set used: ISO 8859-1, ISO 8859-2, ISO 8859-3, ... */
4c913b /* #define ·ISO_8859 ·····1 */
79af5a
cd9498 #ifndef ISO_8859
14b9fd # ·define ISO_8859 ····0
e17454 #endif
d8af5a
2374b8 typedef unsigned char ·Byte;
20fca7 typedef struct { Byte ·a, b; } Couple;
b4af5a
e6504c #ifdef NEEDPROTOS
091e20 static Byte *c_to_hh( Byte *o, Byte c );
0def58 static Byte *c_to_cc( Byte *o, Couple *cc, Byte c );
e68588 static int hh_to_c( Byte *h );
abdc29 static Byte *cc_to_t61( Byte *o, Byte *s );
4c6133 #else /* NEEDPROTOS */
c383e5 static Byte *c_to_hh();
bfe92c static Byte *c_to_cc();
53bd9d static int hh_to_c();
5b60a8 static Byte *cc_to_t61();
f18634 #endif /* NEEDPROTOS */
37af5a
f838e5 /*
0472ad ···Character choosed as base in diacritics alone: NO-BREAK SPACE.
0f80b7 ···(The standard say it must be a blank space, 0x20.)
477fe0 */
56339f #define ·ALONE ·0xA0
40af5a
de3afe static Couple diacritic[16] = {
366f6b #if (ISO_8859 == 1) || (ISO_8859 == 9)
24bd42 ¤   {0,0}, ······{'`',0}, ····{0xb4,0}, ···{'^',0},
60bbc5 ¤   {'~',0}, ····{0xaf,0}, ···{'(',ALONE}, {'.',ALONE},
20a7a2 ¤   {0xa8,0}, ···{0,0}, ······{'0',ALONE}, {0xb8,0},
f6c1a5 ¤   {0,0}, ······{'"',ALONE}, {';',ALONE}, {'<',ALONE},
9fdcb3 #elif (ISO_8859 == 2)
f5bd42 ¤   {0,0}, ······{'`',0}, ····{0xb4,0}, ···{'^',0},
efc660 ¤   {'~',0}, ····{'-',ALONE}, {0xa2,0}, ···{0xff,0},
e6a7a2 ¤   {0xa8,0}, ···{0,0}, ······{'0',ALONE}, {0xb8,0},
b631b3 ¤   {0,0}, ······{0xbd,0}, ···{0xb2,0}, ···{0xb7,0}
2c866f #elif (ISO_8859 == 3)
4bbd42 ¤   {0,0}, ······{'`',0}, ····{0xb4,0}, ···{'^',0},
a6c660 ¤   {'~',0}, ····{'-',ALONE}, {0xa2,0}, ···{0xff,0},
5fa7a2 ¤   {0xa8,0}, ···{0,0}, ······{'0',ALONE}, {0xb8,0},
1cd589 ¤   {0,0}, ······{'"',ALONE}, {';',ALONE}, {'<',ALONE}
030a6a #elif (ISO_8859 == 4)
2ebd42 ¤   {0,0}, ······{'`',0}, ····{0xb4,0}, ···{'^',0},
563083 ¤   {'~',0}, ····{0xaf,0}, ···{'(',ALONE}, {0xff,0},
56a7a2 ¤   {0xa8,0}, ···{0,0}, ······{'0',ALONE}, {0xb8,0},
f4a657 ¤   {0,0}, ······{'"',ALONE}, {0xb2,0}, ···{0xb7,0}
44db21 #else
1668c9 ¤   {0,0}, ······{'`',0}, ····{'\'',ALONE}, {'^',0},
25cf87 ¤   {'~',0}, ····{'-',ALONE}, {'(',ALONE}, ·{'.',ALONE},
--5aae 000934830c840100093 Page 4 of charset.c
69903b ¤   {':',ALONE}, {0,0}, ······{'0',ALONE}, ·{',',ALONE},
ca4dd7 ¤   {0,0}, ······{'"',ALONE}, {';',ALONE}, ·{'<',ALONE}
567454 #endif
3682f7 };
e2af5a
4538e5 /*
99d59f ···--- T.61 (T.51) letters with diacritics: conversion to ISO 8859-n -----
8d2bb5 ·······A, ··C, ··D, ··E, ··G, ··H, ··I, ··J, ··K,
5114e6 ·······L, ··N, ··O, ··R, ··S, ··T, ··U, ··W, ··Y, ··Z.
27a977 ···-----------------------------------------------------------------------
677fe0 */
92aa3c static int letter_w_diacritic[16][38] = {
7866a3 #if (ISO_8859 == 1)
cb950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
b9b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
7d950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
9db6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
550d0a ¤   0xc0,0, ··0, ··0xc8,0, ··0, ··0xcc,0, ··0,
87e83f ¤   0, ··0, ··0xd2,0, ··0, ··0, ··0xd9,0, ··0, ··0,
6a197e ¤   0xe0,0, ··0, ··0xe8,0, ··0, ··0xec,0, ··0,
ccac81 ¤   0, ··0, ··0xf2,0, ··0, ··0, ··0xf9,0, ··0, ··0,
b5a346 ¤   0xc1,-1, ·0, ··0xc9,0, ··0, ··0xcd,0, ··0,
cc74d2 ¤   -1, ·-1, ·0xd3,-1, ·-1, ·0, ··0xda,0, ··0xdd,-1,
efb732 ¤   0xe1,-1, ·0, ··0xe9,0, ··0, ··0xed,0, ··0,
b41fd8 ¤   -1, ·-1, ·0xf3,-1, ·-1, ·0, ··0xfa,0, ··0xfd,-1,
21e81d ¤   0xc2,-1, ·0, ··0xca,-1, ·-1, ·0xce,-1, ·0,
d42c32 ¤   0, ··0, ··0xd4,0, ··-1, ·0, ··0xdb,-1, ·-1, ·0,
61fc69 ¤   0xe2,-1, ·0, ··0xea,-1, ·-1, ·0xee,-1, ·0,
71688c ¤   0, ··0, ··0xf4,0, ··-1, ·0, ··0xfb,-1, ·-1, ·0,
6a4b86 ¤   0xc3,0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
819c37 ¤   0, ··0xd1,0xd5,0, ··0, ··0, ··-1, ·0, ··0, ··0,
2e1547 ¤   0xe3,0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
ebf907 ¤   0, ··0xf1,0xf5,0, ··0, ··0, ··-1, ·0, ··0, ··0,
b3d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
5311e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
25d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
8811e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
1f4c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
60711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
f94c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
6f711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
436f6e ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··-1, ·0, ··0,
11e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
37c276 ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··0, ··0, ··0,
83e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
e7d316 ¤   0xc4,0, ··0, ··0xcb,0, ··0, ··0xcf,0, ··0,
ae61b5 ¤   0, ··0, ··0xd6,0, ··0, ··0, ··0xdc,0, ··-1, ·0,
18c762 ¤   0xe4,0, ··0, ··0xeb,0, ··0, ··0xef,0, ··0,
c5bd2e ¤   0, ··0, ··0xf6,0, ··0, ··0, ··0xfc,0, ··0xff,0,
63950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
62b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
5f950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
deb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
90c202 ¤   0xc5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
67711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
519cc3 ¤   0xe5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
af711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
803295 ¤   0, ··0xc7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
e80b76 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0,
2ab764 ¤   0, ··0xe7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
950b76 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0,
a1950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
48b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
dd950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
9db6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
6d950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f611e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
80950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
b411e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
bfd6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
90711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
93d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
--d8cc 00046a799d740100093 Page 5 of charset.c
e1711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
776470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
87fcc7 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1,
3b6470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
525475 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1
7edcb3 #elif (ISO_8859 == 2)
2d950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
10b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
a5950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
11b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
e8d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
b711e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
73d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
d811e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
facbf0 ¤   0xc1,0xc6,0, ··0xc9,0, ··0, ··0xcd,0, ··0,
a729e4 ¤   0xc5,0xd1,0xd3,0xc0,0xa6,0, ··0xda,0, ··0xdd,0xac,
252e15 ¤   0xe1,0xe6,0, ··0xe9,0, ··0, ··0xed,0, ··0,
fb10cc ¤   0xe5,0xf1,0xf3,0xe0,0xb6,0, ··0xfa,0, ··0xfd,0xbc,
9aa277 ¤   0xc2,-1, ·0, ··-1, ·-1, ·-1, ·0xce,-1, ·0,
32643d ¤   0, ··0, ··0xd4,0, ··-1, ·0, ··-1, ·-1, ·-1, ·0,
1409c1 ¤   0xe2,-1, ·0, ··-1, ·-1, ·-1, ·0xee,-1, ·0,
1334b2 ¤   0, ··0, ··0xf4,0, ··-1, ·0, ··-1, ·-1, ·-1, ·0,
f26474 ¤   -1, ·0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
534d84 ¤   0, ··-1, ·-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
0d6474 ¤   -1, ·0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
fe4d84 ¤   0, ··-1, ·-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
21d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
9211e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
6dd6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
5d11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
4263d9 ¤   0xc3,0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
fd711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
ac3d18 ¤   0xe3,0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
ce711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
c86f6e ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··-1, ·0, ··0,
803659 ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0xaf,
7bc276 ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··0, ··0, ··0,
7b1394 ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0xbf,
c69500 ¤   0xc4,0, ··0, ··0xcb,0, ··0, ··-1, ·0, ··0,
2461b5 ¤   0, ··0, ··0xd6,0, ··0, ··0, ··0xdc,0, ··-1, ·0,
b87403 ¤   0xe4,0, ··0, ··0xeb,0, ··0, ··-1, ·0, ··0,
06250b ¤   0, ··0, ··0xf6,0, ··0, ··0, ··0xfc,0, ··-1, ·0,
aa950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f4b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
31950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
a7b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
00c96c ¤   -1, ·0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
9d894b ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xd9,0, ··0, ··0,
2ac96c ¤   -1, ·0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
c39d7a ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xf9,0, ··0, ··0,
0e3295 ¤   0, ··0xc7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
1e46be ¤   -1, ·-1, ·0, ··-1, ·0xaa,0xde,0, ··0, ··0, ··0,
f2b764 ¤   0, ··0xe7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
ad7787 ¤   -1, ·-1, ·0, ··-1, ·0xba,0xfe,0, ··0, ··0, ··0,
30950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
1db6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
65950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
53b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
48950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
247bca ¤   0, ··0, ··0xd5,0, ··0, ··0, ··0xdb,0, ··0, ··0,
17950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
c23f74 ¤   0, ··0, ··0xf5,0, ··0, ··0, ··0xfb,0, ··0, ··0,
739ae0 ¤   0xa1,0, ··0, ··0xca,0, ··0, ··-1, ·0, ··0,
0f711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
ed8e4a ¤   0xb1,0, ··0, ··0xea,0, ··0, ··-1, ·0, ··0,
9f711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
82ccdf ¤   0, ··0xc8,0xcf,0xcc,0, ··0, ··0, ··0, ··0,
311fe2 ¤   0xa5,0xd2,0, ··0xd8,0xa9,0xab,0, ··0, ··0, ··0xae,
ba0c16 ¤   0, ··0xe8,0xef,0xec,0, ··0, ··0, ··0, ··0,
aff00c ¤   0xb5,0xf2,0, ··0xf8,0xb9,0xbb,0, ··0, ··0, ··0xbe
68866f #elif (ISO_8859 == 3)
46950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
--ddb7 0000ced49d340100093 Page 6 of charset.c
0fb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
a2950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f4b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
740d0a ¤   0xc0,0, ··0, ··0xc8,0, ··0, ··0xcc,0, ··0,
8ce83f ¤   0, ··0, ··0xd2,0, ··0, ··0, ··0xd9,0, ··0, ··0,
e7197e ¤   0xe0,0, ··0, ··0xe8,0, ··0, ··0xec,0, ··0,
daac81 ¤   0, ··0, ··0xf2,0, ··0, ··0, ··0xf9,0, ··0, ··0,
1aa346 ¤   0xc1,-1, ·0, ··0xc9,0, ··0, ··0xcd,0, ··0,
403d08 ¤   -1, ·-1, ·0xd3,-1, ·-1, ·0, ··0xda,0, ··-1, ·-1,
0eb732 ¤   0xe1,-1, ·0, ··0xe9,0, ··0, ··0xed,0, ··0,
8d61b9 ¤   -1, ·-1, ·0xf3,-1, ·-1, ·0, ··0xfa,0, ··-1, ·-1,
44c30a ¤   0xc2,0xc6,0, ··0xca,0xd8,0xa6,0xce,0xac,0,
220526 ¤   0, ··0, ··0xd4,0, ··0xde,0, ··0xdb,-1, ·-1, ·0,
87de6b ¤   0xe2,0xe6,0, ··0xea,0xf8,0xb6,0xee,0xbc,0,
47d329 ¤   0, ··0, ··0xf4,0, ··0xfe,0, ··0xfb,-1, ·-1, ·0,
176474 ¤   -1, ·0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
f3be14 ¤   0, ··0xd1,-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
bf6474 ¤   -1, ·0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
cf8bab ¤   0, ··0xf1,-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
2dd6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
ae11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
92d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
fc11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
6b3f64 ¤   -1, ·0, ··0, ··0, ··0xab,0, ··0, ··0, ··0,
4381fc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xdd,0, ··0, ··0,
8d66d0 ¤   -1, ·0, ··0, ··0, ··0xbb,0, ··0, ··0, ··0,
a595cd ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xfd,0, ··0, ··0,
d6bd2a ¤   0, ··0xc5,0, ··-1, ·0xd5,0, ··0xa9,0, ··0,
e13659 ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0xaf,
974cba ¤   0, ··0xe5,0, ··-1, ·0xf5,0, ··0, ··0, ··0,
581394 ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0xbf,
10d316 ¤   0xc4,0, ··0, ··0xcb,0, ··0, ··0xcf,0, ··0,
cf61b5 ¤   0, ··0, ··0xd6,0, ··0, ··0, ··0xdc,0, ··-1, ·0,
90c762 ¤   0xe4,0, ··0, ··0xeb,0, ··0, ··0xef,0, ··0,
2d250b ¤   0, ··0, ··0xf6,0, ··0, ··0, ··0xfc,0, ··-1, ·0,
a4950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
66b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
c3950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f7b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
62c96c ¤   -1, ·0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
72711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
13c96c ¤   -1, ·0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
dc711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
413295 ¤   0, ··0xc7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
13d3ad ¤   -1, ·-1, ·0, ··-1, ·0xaa,-1, ·0, ··0, ··0, ··0,
b4b764 ¤   0, ··0xe7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
f88c4c ¤   -1, ·-1, ·0, ··-1, ·0xba,-1, ·0, ··0, ··0, ··0,
44950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
04b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f2950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
c3b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
44950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
3711e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
39950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
8c11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
6bd6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
3f711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
91d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
a2711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
876470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
04fcc7 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1,
836470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
095475 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1
620a6a #elif (ISO_8859 == 4)
6c950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
82b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
9e950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
41b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
23d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
e511e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
ead6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
0c11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
--bc7e 0005b113ea740100093 Page 7 of charset.c
aea346 ¤   0xc1,-1, ·0, ··0xc9,0, ··0, ··0xcd,0, ··0,
1fdf22 ¤   -1, ·-1, ·-1, ·-1, ·-1, ·0, ··0xda,0, ··-1, ·-1,
14b732 ¤   0xe1,-1, ·0, ··0xe9,0, ··0, ··0xed,0, ··0,
53ff3c ¤   -1, ·-1, ·-1, ·-1, ·-1, ·0, ··0xfa,0, ··-1, ·-1,
c6a277 ¤   0xc2,-1, ·0, ··-1, ·-1, ·-1, ·0xce,-1, ·0,
a22c32 ¤   0, ··0, ··0xd4,0, ··-1, ·0, ··0xdb,-1, ·-1, ·0,
7209c1 ¤   0xe2,-1, ·0, ··-1, ·-1, ·-1, ·0xee,-1, ·0,
b8688c ¤   0, ··0, ··0xf4,0, ··-1, ·0, ··0xfb,-1, ·-1, ·0,
9b51f2 ¤   0xc3,0, ··0, ··0, ··0, ··0, ··0xa5,0, ··0,
8a9f45 ¤   0, ··-1, ·0xd5,0, ··0, ··0, ··0xdd,0, ··0, ··0,
ddf180 ¤   0xe3,0, ··0, ··0, ··0, ··0, ··0xb5,0, ··0,
bedbfb ¤   0, ··-1, ·0xf5,0, ··0, ··0, ··0xfd,0, ··0, ··0,
f575c2 ¤   0xc0,0, ··0, ··0xaa,0, ··0, ··0xcf,0, ··0,
56a8a2 ¤   0, ··0, ··0xd2,0, ··0, ··0, ··0xde,0, ··0, ··0,
e68195 ¤   0xe0,0, ··0, ··0xba,0, ··0, ··0xef,0, ··0,
59ec1c ¤   0, ··0, ··0xf2,0, ··0, ··0, ··0xfe,0, ··0, ··0,
1c4c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
b3711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
da4c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
f8711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
6e2df2 ¤   0, ··-1, ·0, ··0xcc,-1, ·0, ··-1, ·0, ··0,
1ce6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
763f28 ¤   0, ··-1, ·0, ··0xec,-1, ·0, ··0, ··0, ··0,
ece6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
289500 ¤   0xc4,0, ··0, ··0xcb,0, ··0, ··-1, ·0, ··0,
d761b5 ¤   0, ··0, ··0xd6,0, ··0, ··0, ··0xdc,0, ··-1, ·0,
237403 ¤   0xe4,0, ··0, ··0xeb,0, ··0, ··-1, ·0, ··0,
8d250b ¤   0, ··0, ··0xf6,0, ··0, ··0, ··0xfc,0, ··-1, ·0,
38950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
47b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
36950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
9cb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
5bc202 ¤   0xc5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
60711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
349cc3 ¤   0xe5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
8c711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
559590 ¤   0, ··-1, ·0, ··0, ··0xab,0, ··0, ··0, ··0xd3,
c833af ¤   0xa6,0xd1,0, ··0xa3,-1, ·-1, ·0, ··0, ··0, ··0,
fe412a ¤   0, ··-1, ·0, ··0, ··0xbb,0, ··0, ··0, ··0xf3,
47d8e6 ¤   0xb6,0xf1,0, ··0xb3,-1, ·-1, ·0, ··0, ··0, ··0,
6c950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
d4b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
e6950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
2cb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f9950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
2111e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
94950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
bb11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
e873f8 ¤   0xa1,0, ··0, ··0xca,0, ··0, ··0xc7,0, ··0,
3d894b ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xd9,0, ··0, ··0,
9f9225 ¤   0xb1,0, ··0, ··0xea,0, ··0, ··0xe7,0, ··0,
8c9d7a ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xf9,0, ··0, ··0,
fe4b98 ¤   0, ··0xc8,-1, ·-1, ·0, ··0, ··0, ··0, ··0,
5f4869 ¤   -1, ·-1, ·0, ··-1, ·0xa9,-1, ·0, ··0, ··0, ··0xae,
0aba09 ¤   0, ··0xe8,-1, ·-1, ·0, ··0, ··0, ··0, ··0,
becc83 ¤   -1, ·-1, ·0, ··-1, ·0xb9,-1, ·0, ··0, ··0, ··0xbe
bcf515 #elif (ISO_8859 == 9)
51950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
7eb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
5a950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
61b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
2a0d0a ¤   0xc0,0, ··0, ··0xc8,0, ··0, ··0xcc,0, ··0,
e4e83f ¤   0, ··0, ··0xd2,0, ··0, ··0, ··0xd9,0, ··0, ··0,
6c36a4 ¤   0xe0,0, ··0, ··0xe8,0, ··0, ··-1, ·0, ··0,
5fac81 ¤   0, ··0, ··0xf2,0, ··0, ··0, ··0xf9,0, ··0, ··0,
7ba346 ¤   0xc1,-1, ·0, ··0xc9,0, ··0, ··0xcd,0, ··0,
e23d08 ¤   -1, ·-1, ·0xd3,-1, ·-1, ·0, ··0xda,0, ··-1, ·-1,
7fb732 ¤   0xe1,-1, ·0, ··0xe9,0, ··0, ··0xed,0, ··0,
7961b9 ¤   -1, ·-1, ·0xf3,-1, ·-1, ·0, ··0xfa,0, ··-1, ·-1,
79e81d ¤   0xc2,-1, ·0, ··0xca,-1, ·-1, ·0xce,-1, ·0,
e82c32 ¤   0, ··0, ··0xd4,0, ··-1, ·0, ··0xdb,-1, ·-1, ·0,
5b09c1 ¤   0xe2,-1, ·0, ··-1, ·-1, ·-1, ·0xee,-1, ·0,
--ac92 0007bf03de540100093 Page 8 of charset.c
14688c ¤   0, ··0, ··0xf4,0, ··-1, ·0, ··0xfb,-1, ·-1, ·0,
1e4b86 ¤   0xc3,0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
329c37 ¤   0, ··0xd1,0xd5,0, ··0, ··0, ··-1, ·0, ··0, ··0,
811547 ¤   0xe3,0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
adf907 ¤   0, ··0xf1,0xf5,0, ··0, ··0, ··-1, ·0, ··0, ··0,
60d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
8411e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
ae65d2 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··0xef,0, ··0,
6211e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
99986e ¤   -1, ·0, ··0, ··0, ··0xd0,0, ··0, ··0, ··0,
75711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
eff6b6 ¤   -1, ·0, ··0, ··0, ··0xf0,0, ··0, ··0, ··0,
0a711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
c1d1d0 ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··0xdd,0, ··0,
b7e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
123f28 ¤   0, ··-1, ·0, ··0xec,-1, ·0, ··0, ··0, ··0,
74e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
45d316 ¤   0xc4,0, ··0, ··0xcb,0, ··0, ··0xcf,0, ··0,
9161b5 ¤   0, ··0, ··0xd6,0, ··0, ··0, ··0xdc,0, ··-1, ·0,
0f7403 ¤   0xe4,0, ··0, ··0xeb,0, ··0, ··-1, ·0, ··0,
f8bd2e ¤   0, ··0, ··0xf6,0, ··0, ··0, ··0xfc,0, ··0xff,0,
b5950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
adb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
2b950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
8fb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
c1c202 ¤   0xc5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
4c711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
399cc3 ¤   0xe5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
2e711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
c83295 ¤   0, ··0xc7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
702262 ¤   -1, ·-1, ·0, ··-1, ·0xde,-1, ·0, ··0, ··0, ··0,
2eb764 ¤   0, ··0xe7,0, ··0, ··-1, ·0, ··0, ··0, ··-1,
bab0d3 ¤   -1, ·-1, ·0, ··-1, ·0xfe,-1, ·0, ··0, ··0, ··0,
ff950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
e4b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
75950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
a6b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
2c950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
3d11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
e9950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
8711e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
3cd6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
95711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
05231b ¤   -1, ·0, ··0, ··0xea,0, ··0, ··-1, ·0, ··0,
4d711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
3d6470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
ccfcc7 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1,
126470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
5b5475 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1
571d8b #elif (ISO_8859 == 10)
f0950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
efb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
18950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
a7b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
18d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
9011e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
d2d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
0711e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
cca346 ¤   0xc1,-1, ·0, ··0xc9,0, ··0, ··0xcd,0, ··0,
8774d2 ¤   -1, ·-1, ·0xd3,-1, ·-1, ·0, ··0xda,0, ··0xdd,-1,
88b732 ¤   0xe1,-1, ·0, ··0xe9,0, ··0, ··0xed,0, ··0,
791fd8 ¤   -1, ·-1, ·0xf3,-1, ·-1, ·0, ··0xfa,0, ··0xfd,-1,
f3a277 ¤   0xc2,-1, ·0, ··-1, ·-1, ·-1, ·0xce,-1, ·0,
0d2c32 ¤   0, ··0, ··0xd4,0, ··-1, ·0, ··0xdb,-1, ·-1, ·0,
d509c1 ¤   0xe2,-1, ·0, ··-1, ·-1, ·-1, ·0xee,-1, ·0,
62688c ¤   0, ··0, ··0xf4,0, ··-1, ·0, ··0xfb,-1, ·-1, ·0,
a251f2 ¤   0xc3,0, ··0, ··0, ··0, ··0, ··0xa5,0, ··0,
be7e6d ¤   0, ··-1, ·0xd5,0, ··0, ··0, ··0xd7,0, ··0, ··0,
3cf180 ¤   0xe3,0, ··0, ··0, ··0, ··0, ··0xb5,0, ··0,
cb3ad3 ¤   0, ··-1, ·0xf5,0, ··0, ··0, ··0xf7,0, ··0, ··0,
0f586b ¤   0xc0,0, ··0, ··0xa2,0, ··0, ··0xa4,0, ··0,
7b0ed0 ¤   0, ··0, ··0xd2,0, ··0, ··0, ··0xae,0, ··0, ··0,

--8315 000b55f678040100093 Page 9 of charset.c
08a7f8 ¤   0xe0,0, ··0, ··0xb2,0, ··0, ··0xb4,0, ··0,
c2c47e ¤   0, ··0, ··0xf2,0, ··0, ··0, ··0xbe,0, ··0, ··0,
674c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
6a711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
e84c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
86711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
482df2 ¤   0, ··-1, ·0, ··0xcc,-1, ·0, ··-1, ·0, ··0,
15e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
803f28 ¤   0, ··-1, ·0, ··0xec,-1, ·0, ··0, ··0, ··0,
dde6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
9bd316 ¤   0xc4,0, ··0, ··0xcb,0, ··0, ··0xcf,0, ··0,
6761b5 ¤   0, ··0, ··0xd6,0, ··0, ··0, ··0xdc,0, ··-1, ·0,
8ac762 ¤   0xe4,0, ··0, ··0xeb,0, ··0, ··0xef,0, ··0,
86250b ¤   0, ··0, ··0xf6,0, ··0, ··0, ··0xfc,0, ··-1, ·0,
4d950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
76b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
10950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
3bb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
02c202 ¤   0xc5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
80711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
a79cc3 ¤   0xe5,0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
49711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
79fff8 ¤   0, ··-1, ·0, ··0, ··0xa3,0, ··0, ··0, ··0xa6,
b7b93b ¤   0xa8,0xd1,0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0,
ed37f9 ¤   0, ··-1, ·0, ··0, ··0xb3,0, ··0, ··0, ··0xb6,
98153f ¤   0xb8,0xf1,0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0,
4e950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
1fb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
cf950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
00b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
72950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
4e11e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
fd950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
f811e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
3873f8 ¤   0xa1,0, ··0, ··0xca,0, ··0, ··0xc7,0, ··0,
5e894b ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xd9,0, ··0, ··0,
099225 ¤   0xb1,0, ··0, ··0xea,0, ··0, ··0xe7,0, ··0,
749d7a ¤   0, ··0, ··0, ··0, ··0, ··0, ··0xf9,0, ··0, ··0,
0a4b98 ¤   0, ··0xc8,-1, ·-1, ·0, ··0, ··0, ··0, ··0,
9c4b98 ¤   -1, ·-1, ·0, ··-1, ·0xaa,-1, ·0, ··0, ··0, ··0xac,
2bba09 ¤   0, ··0xe8,-1, ·-1, ·0, ··0, ··0, ··0, ··0,
bd25b0 ¤   -1, ·-1, ·0, ··-1, ·0xba,-1, ·0, ··0, ··0, ··0xbc
b9db21 #else
2d950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
cab6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
e0950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
72b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
b3d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
8311e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
d6d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
6211e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
88b64b ¤   -1, ·-1, ·0, ··-1, ·0, ··0, ··-1, ·0, ··0,
30bdbc ¤   -1, ·-1, ·-1, ·-1, ·-1, ·0, ··-1, ·0, ··-1, ·-1,
e2b64b ¤   -1, ·-1, ·0, ··-1, ·0, ··0, ··-1, ·0, ··0,
2dbdbc ¤   -1, ·-1, ·-1, ·-1, ·-1, ·0, ··-1, ·0, ··-1, ·-1,
38b1c0 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·-1, ·-1, ·0,
a54b27 ¤   0, ··0, ··-1, ·0, ··-1, ·0, ··-1, ·-1, ·-1, ·0,
a4b1c0 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·-1, ·-1, ·0,
0a4b27 ¤   0, ··0, ··-1, ·0, ··-1, ·0, ··-1, ·-1, ·-1, ·0,
9b6474 ¤   -1, ·0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
9b4d84 ¤   0, ··-1, ·-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
656474 ¤   -1, ·0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0,
5e4d84 ¤   0, ··-1, ·-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
08d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
9711e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
edd6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
0411e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
564c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
d9711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
ae4c2b ¤   -1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0, ··0,
2a711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
b56f6e ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··-1, ·0, ··0,

--aefe 000b3a8ad2c40100093 Page 10 of charset.c
82e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
40c276 ¤   0, ··-1, ·0, ··-1, ·-1, ·0, ··0, ··0, ··0,
95e6ab ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··-1,
e1d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
2054f8 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··-1, ·0,
b0d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
e254f8 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··-1, ·0,
d2950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
5eb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
49950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
3ab6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
8cc96c ¤   -1, ·0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
6c711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
74c96c ¤   -1, ·0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
fc711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
0b4e0f ¤   0, ··-1, ·0, ··0, ··-1, ·0, ··0, ··0, ··-1,
f00b76 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0,
324e0f ¤   0, ··-1, ·0, ··0, ··-1, ·0, ··0, ··0, ··-1,
100b76 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0,
02950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
70b6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
9f950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
dbb6cc ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
31950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
8211e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
6a950e ¤   0, ··0, ··0, ··0, ··0, ··0, ··0, ··0, ··0,
6111e6 ¤   0, ··0, ··-1, ·0, ··0, ··0, ··-1, ·0, ··0, ··0,
f2d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
4a711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
95d6b3 ¤   -1, ·0, ··0, ··-1, ·0, ··0, ··-1, ·0, ··0,
45711e ¤   0, ··0, ··0, ··0, ··0, ··0, ··-1, ·0, ··0, ··0,
566470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
b7fcc7 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1,
936470 ¤   0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··0, ··0,
035475 ¤   -1, ·-1, ·0, ··-1, ·-1, ·-1, ·0, ··0, ··0, ··-1
bd7454 #endif
b382f7 };
15af5a
3d38e5 /*
2d0cd3 --- T.61 characters [0xA0 .. 0xBF] -----------------
2f7fe0 */
8e709c static Couple trans_t61a_iso8859[32] = {
416f6b #if (ISO_8859 == 1) || (ISO_8859 == 9)
4ee83f ¤   {'N','S'}, {0xa1,0}, ·{0xa2,0}, ·{0xa3,0},
a539c2 ¤   {'D','O'}, {0xa5,0}, ·{'C','u'}, {0xa7,0},
c1ed87 ¤   {0xa4,0}, ·{'\'','6'},{'"','6'}, {0xab,0},
493de8 ¤   {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
83aded ¤   {0xb0,0}, ·{0xb1,0}, ·{0xb2,0}, ·{0xb3,0},
f10531 ¤   {0xd7,0}, ·{0xb5,0}, ·{0xb6,0}, ·{0xb7,0},
0c2f71 ¤   {0xf7,0}, ·{'\'','9'},{'"','9'}, {0xbb,0},
81fae9 ¤   {0xbc,0}, ·{0xbd,0}, ·{0xbe,0}, ·{0xbf,0}
e47502 #elif (ISO_8859 == 2) || (ISO_8859 == 4)
8501e3 ¤   {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'},
e21bd1 ¤   {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0},
275437 ¤   {0xa4,0}, ·{'\'','6'},{'"','6'}, {'<','<'},
c73de8 ¤   {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
af9f02 ¤   {0xb0,0}, ·{'+','-'}, {'2','S'}, {'3','S'},
e193a4 ¤   {0xd7,0}, ·{'M','y'}, {'P','I'}, {'.','M'},
d1c1ee ¤   {0xf7,0}, ·{'\'','9'},{'"','9'}, {'>','>'},
06d6bb ¤   {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'},
f4866f #elif (ISO_8859 == 3)
af1847 ¤   {'N','S'}, {'!','I'}, {'C','t'}, {0xa3,0},
ef1bd1 ¤   {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0},
785437 ¤   {0xa4,0}, ·{'\'','6'},{'"','6'}, {'<','<'},
613de8 ¤   {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
b42d9b ¤   {0xb0,0}, ·{'+','-'}, {0xb2,0}, ·{0xb3,0},
5eefe1 ¤   {0xd7,0}, ·{0xb5,0}, ·{'P','I'}, {0xb7,0},
00c1ee ¤   {0xf7,0}, ·{'\'','9'},{'"','9'}, {'>','>'},
6d45b6 ¤   {'1','4'}, {0xbd,0}, ·{'3','4'}, {'?','I'}
2d1d8b #elif (ISO_8859 == 10)
9601e3 ¤   {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'},
b31bd1 ¤   {'D','O'}, {'Y','e'}, {'C','u'}, {0xa7,0},
--5926 000edbd6eac40100093 Page 11 of charset.c
3677af ¤   {'C','u'}, {'\'','6'},{'"','6'}, {'<','<'},
513de8 ¤   {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
7a9f02 ¤   {0xb0,0}, ·{'+','-'}, {'2','S'}, {'3','S'},
a13490 ¤   {'*','X'}, {'M','y'}, {'P','I'}, {0xb7,0},
9d1568 ¤   {'-',':'}, {'\'','9'},{'"','9'}, {'>','>'},
6572ee ¤   {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'}
26db21 #else
3201e3 ¤   {'N','S'}, {'!','I'}, {'C','t'}, {'P','d'},
9f22fb ¤   {'D','O'}, {'Y','e'}, {'C','u'}, {'S','E'},
e2f0ee ¤   {'X','O'}, {'\'','6'},{'"','6'}, {'<','<'},
e23de8 ¤   {'<','-'}, {'-','!'}, {'-','>'}, {'-','v'},
620b83 ¤   {'D','G'}, {'+','-'}, {'2','S'}, {'3','S'},
1842b5 ¤   {'*','X'}, {'M','y'}, {'P','I'}, {'.','M'},
721568 ¤   {'-',':'}, {'\'','9'},{'"','9'}, {'>','>'},
2772ee ¤   {'1','4'}, {'1','2'}, {'3','4'}, {'?','I'}
9f7454 #endif
3682f7 };
3faf5a
1a38e5 /*
363a49 --- T.61 characters [0xE0 .. 0xFF] -----------------
537fe0 */
c904fd static Couple trans_t61b_iso8859[48] = {
9966a3 #if (ISO_8859 == 1)
5e3497 ¤   {'-','M'}, {0xb9,0}, ·{0xae,0}, ·{0xa9,0},
a155f2 ¤   {'T','M'}, {'M','8'}, {0xac,0}, ·{0xa6,0},
ce1530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
147d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
4aed12 ¤   {'O','m'}, {0xc6,0}, ·{0xd0,0}, ·{0xaa,0},
aba46c ¤   {'H','/'}, {0,0}, ····{'I','J'}, {'L','.'},
07a361 ¤   {'L','/'}, {0xd8,0}, ·{'O','E'}, {0xba,0},
0851e8 ¤   {0xde,0}, ·{'T','/'}, {'N','G'}, {'\'','n'},
66fa91 ¤   {'k','k'}, {0xe6,0}, ·{'d','/'}, {0xf0,0},
310ef9 ¤   {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
b6eb06 ¤   {'l','/'}, {0xf8,0}, ·{'o','e'}, {0xdf,0},
6345d7 ¤   {0xfe,0}, ·{'t','/'}, {'n','g'}, {'-','-'}
74dcb3 #elif (ISO_8859 == 2)
e89141 ¤   {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
3ac8c7 ¤   {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
401530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
f87d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
7cd77e ¤   {'O','m'}, {'A','E'}, {0xd0,0}, ·{'-','a'},
27a46c ¤   {'H','/'}, {0,0}, ····{'I','J'}, {'L','.'},
5885ef ¤   {0xa3,0}, ·{'O','/'}, {'O','E'}, {'-','o'},
f7b30f ¤   {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
d56dcc ¤   {'k','k'}, {'a','e'}, {0xf0,0}, ·{'d','-'},
400ef9 ¤   {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
27d392 ¤   {0xb3,0}, ·{'o','/'}, {'o','e'}, {0xdf,0},
496950 ¤   {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'}
e7866f #elif (ISO_8859 == 3)
b09141 ¤   {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
76c8c7 ¤   {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
0b1530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
4a7d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
6f696a ¤   {'O','m'}, {'A','E'}, {'D','/'}, {'-','a'},
7d54d3 ¤   {0xa1,0}, ·{0,0}, ····{'I','J'}, {'L','.'},
94f3b6 ¤   {'L','/'}, {'O','/'}, {'O','E'}, {'-','o'},
21b30f ¤   {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
4fce30 ¤   {'k','k'}, {'a','e'}, {'d','/'}, {'d','-'},
0afca5 ¤   {0xb1,0}, ·{0xb9,0}, ·{'i','j'}, {'l','.'},
92743a ¤   {'l','/'}, {'o','/'}, {'o','e'}, {0xdf,0},
4a6950 ¤   {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'}
d30a6a #elif (ISO_8859 == 4)
859141 ¤   {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
93c8c7 ¤   {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
641530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
107d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
998402 ¤   {'O','m'}, {0xc6,0}, ·{0xd0,0}, ·{'-','a'},
47a46c ¤   {'H','/'}, {0,0}, ····{'I','J'}, {'L','.'},
b82e38 ¤   {'L','/'}, {0xd8,0}, ·{'O','E'}, {'-','o'},
c55d07 ¤   {'T','H'}, {0xac,0}, ·{0xbd,0}, ·{'\'','n'},
6b2871 ¤   {0xa2,0}, ·{0xe6,0}, ·{0xf0,0}, ·{'d','-'},
ed0ef9 ¤   {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
--4d78 000db4f191040100093 Page 12 of charset.c
e5eb06 ¤   {'l','/'}, {0xf8,0}, ·{'o','e'}, {0xdf,0},
53dc6f ¤   {'t','h'}, {0xbc,0}, ·{0xbf,0}, ·{'-','-'}
7bf515 #elif (ISO_8859 == 9)
393497 ¤   {'-','M'}, {0xb9,0}, ·{0xae,0}, ·{0xa9,0},
4755f2 ¤   {'T','M'}, {'M','8'}, {0xac,0}, ·{0xa6,0},
bb1530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
377d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
502a19 ¤   {'O','m'}, {0xc6,0}, ·{'D','/'}, {0xaa,0},
2ea46c ¤   {'H','/'}, {0,0}, ····{'I','J'}, {'L','.'},
6aa361 ¤   {'L','/'}, {0xd8,0}, ·{'O','E'}, {0xba,0},
cfb30f ¤   {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
a121d4 ¤   {'k','k'}, {0xe6,0}, ·{'d','/'}, {'d','-'},
4c7833 ¤   {'h','/'}, {0xfd,0}, ·{'i','j'}, {'l','.'},
7eeb06 ¤   {'l','/'}, {0xf8,0}, ·{'o','e'}, {0xdf,0},
a76950 ¤   {'t','h'}, {'t','/'}, {'n','g'}, {'-','-'}
791d8b #elif (ISO_8859 == 10)
e3e15b ¤   {0xbd,0}, ·{'1','S'}, {'R','g'}, {'C','o'},
01c8c7 ¤   {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
c01530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
477d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
704de5 ¤   {'O','m'}, {0xc6,0}, ·{0xa9,0}, ·{'-','a'},
fea46c ¤   {'H','/'}, {0,0}, ····{'I','J'}, {'L','.'},
e92e38 ¤   {'L','/'}, {0xd8,0}, ·{'O','E'}, {'-','o'},
c3d87b ¤   {0xde,0}, ·{0xab,0}, ·{0xaf,0}, ·{'\'','n'},
a1d1c9 ¤   {0xff,0}, ·{0xe6,0}, ·{0xb9,0}, ·{0xf0,0},
9b0ef9 ¤   {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
30eb06 ¤   {'l','/'}, {0xf8,0}, ·{'o','e'}, {0xdf,0},
4f3ef6 ¤   {0xfe,0}, ·{0xbb,0}, ·{0xbf,0}, ·{'-','-'}
20db21 #else
ee9141 ¤   {'-','M'}, {'1','S'}, {'R','g'}, {'C','o'},
58c8c7 ¤   {'T','M'}, {'M','8'}, {'N','O'}, {'B','B'},
491530 ¤   {0,0}, ····{0,0}, ····{0,0}, ····{0,0},
827d2a ¤   {'1','8'}, {'3','8'}, {'5','8'}, {'7','8'},
21696a ¤   {'O','m'}, {'A','E'}, {'D','/'}, {'-','a'},
03a46c ¤   {'H','/'}, {0,0}, ····{'I','J'}, {'L','.'},
76f3b6 ¤   {'L','/'}, {'O','/'}, {'O','E'}, {'-','o'},
b2b30f ¤   {'T','H'}, {'T','/'}, {'N','G'}, {'\'','n'},
03ce30 ¤   {'k','k'}, {'a','e'}, {'d','/'}, {'d','-'},
120ef9 ¤   {'h','/'}, {'i','.'}, {'i','j'}, {'l','.'},
b21942 ¤   {'l','/'}, {'o','/'}, {'o','e'}, {'s','s'},
96fbe1 ¤   {'t','h'}, {'t','-'}, {'n','g'}, {'-','-'}
c47454 #endif
3682f7 };
12af5a
1c38e5 /*
03c69d --- ISO 8859-n characters <0xA0 .. 0xFF> -------------------
ae7fe0 */
0366a3 #if (ISO_8859 == 1)
578c41 static Couple trans_iso8859_t61[96] = {
5d4e98 ¤   {0xa0,0}, ····{0xa1,0}, ····{0xa2,0}, ····{0xa3,0},
fd3a42 ¤   {0xa8,0}, ····{0xa5,0}, ····{0xd7,0}, ····{0xa7,0},
27d1b1 ¤   {0xc8,ALONE}, {0xd3,0}, ····{0xe3,0}, ····{0xab,0},
4c2fd4 ¤   {0xd6,0}, ····{0xff,0}, ····{0xd2,0}, ····{0xc5,ALONE},
dac5a8 ¤   {0xb0,0}, ····{0xb1,0}, ····{0xb2,0}, ····{0xb3,0},
31304f ¤   {0xc2,ALONE}, {0xb5,0}, ····{0xb6,0}, ····{0xb7,0},
082f19 ¤   {0xcb,ALONE}, {0xd1,0}, ····{0xeb,0}, ····{0xbb,0},
f07c45 ¤   {0xbc,0}, ····{0xbd,0}, ····{0xbe,0}, ····{0xbf,0},
3dc7c1 ¤   {0xc1,'A'}, ··{0xc2,'A'}, ··{0xc3,'A'}, ··{0xc4,'A'},
c66e6d ¤   {0xc8,'A'}, ··{0xca,'A'}, ··{0xe1,0}, ····{0xcb,'C'},
8b9fd4 ¤   {0xc1,'E'}, ··{0xc2,'E'}, ··{0xc3,'E'}, ··{0xc8,'E'},
2a3a4d ¤   {0xc1,'I'}, ··{0xc2,'I'}, ··{0xc3,'I'}, ··{0xc8,'I'},
516f54 ¤   {0xe2,0}, ····{0xc4,'N'}, ··{0xc1,'O'}, ··{0xc2,'O'},
44ab54 ¤   {0xc3,'O'}, ··{0xc4,'O'}, ··{0xc8,'O'}, ··{0xb4,0},
f4c3cb ¤   {0xe9,0}, ····{0xc1,'U'}, ··{0xc2,'U'}, ··{0xc3,'U'},
e86b1c ¤   {0xc8,'U'}, ··{0xc2,'Y'}, ··{0xec,0}, ····{0xfb,0},
f8c44a ¤   {0xc1,'a'}, ··{0xc2,'a'}, ··{0xc3,'a'}, ··{0xc4,'a'},
4a07be ¤   {0xc8,'a'}, ··{0xca,'a'}, ··{0xf1,0}, ····{0xcb,'c'},
ad9c5f ¤   {0xc1,'e'}, ··{0xc2,'e'}, ··{0xc3,'e'}, ··{0xc8,'e'},
f539c6 ¤   {0xc1,'i'}, ··{0xc2,'i'}, ··{0xc3,'i'}, ··{0xc8,'i'},
4821ae ¤   {0xf3,0}, ····{0xc4,'n'}, ··{0xc1,'o'}, ··{0xc2,'o'},
c41b7c ¤   {0xc3,'o'}, ··{0xc4,'o'}, ··{0xc8,'o'}, ··{0xb8,0},
db1964 ¤   {0xf9,0}, ····{0xc1,'u'}, ··{0xc2,'u'}, ··{0xc3,'u'},
--6179 00068c4ecdd40100093 Page 13 of charset.c
ab11a6 ¤   {0xc8,'u'}, ··{0xc2,'y'}, ··{0xfc,0}, ····{0xc8,'y'}
5682f7 };
aedcb3 #elif (ISO_8859 == 2)
108c41 static Couple trans_iso8859_t61[96] = {
35be27 ¤   {0xa0,0}, ····{0xce,'A'}, ··{0xc6,ALONE}, {0xe8,0},
a4b27c ¤   {0xa8,0}, ····{0xcf,'L'}, ··{0xc2,'S'}, ··{0xa7,0},
8a7129 ¤   {0xc8,ALONE}, {0xcf,'S'}, ··{0xcb,'S'}, ··{0xcf,'T'},
1fd22f ¤   {0xc2,'Z'}, ··{0xff,0}, ····{0xcf,'Z'}, ··{0xc7,'Z'},
e48e70 ¤   {0xb0,0}, ····{0xce,'a'}, ··{0xce,ALONE}, {0xf8,0},
e51a73 ¤   {0xc2,ALONE}, {0xcf,'l'}, ··{0xc2,'s'}, ··{0xcf,ALONE},
2d3df8 ¤   {0xcb,ALONE}, {0xcf,'s'}, ··{0xcb,'s'}, ··{0xcf,'t'},
5d2777 ¤   {0xc2,'z'}, ··{0xcd,ALONE}, {0xcf,'z'}, ··{0xc7,'z'},
fe1871 ¤   {0xc2,'R'}, ··{0xc2,'A'}, ··{0xc3,'A'}, ··{0xc6,'A'},
4239d2 ¤   {0xc8,'A'}, ··{0xc2,'L'}, ··{0xc2,'C'}, ··{0xcb,'C'},
05607f ¤   {0xcf,'C'}, ··{0xc2,'E'}, ··{0xce,'E'}, ··{0xc8,'E'},
12a8cc ¤   {0xcf,'E'}, ··{0xc2,'I'}, ··{0xc3,'I'}, ··{0xcf,'D'},
16838d ¤   {0xe2,0}, ····{0xc2,'N'}, ··{0xcf,'N'}, ··{0xc2,'O'},
cf48c5 ¤   {0xc3,'O'}, ··{0xcd,'O'}, ··{0xc8,'O'}, ··{0xb4,0},
654137 ¤   {0xcf,'R'}, ··{0xca,'U'}, ··{0xc2,'U'}, ··{0xcd,'U'},
daf0b8 ¤   {0xc8,'U'}, ··{0xc2,'Y'}, ··{0xcb,'T'}, ··{0xfb,0},
1d1bfa ¤   {0xc2,'r'}, ··{0xc2,'a'}, ··{0xc3,'a'}, ··{0xc6,'a'},
003a59 ¤   {0xc8,'a'}, ··{0xc2,'l'}, ··{0xc2,'c'}, ··{0xcb,'c'},
8363f4 ¤   {0xcf,'c'}, ··{0xc2,'e'}, ··{0xce,'e'}, ··{0xc8,'e'},
82ab47 ¤   {0xcf,'e'}, ··{0xc2,'i'}, ··{0xc3,'i'}, ··{0xcf,'d'},
d65922 ¤   {0xf2,0}, ····{0xc2,'n'}, ··{0xcf,'n'}, ··{0xc2,'o'},
8cf8ed ¤   {0xc3,'o'}, ··{0xcd,'o'}, ··{0xc8,'o'}, ··{0xb8,0},
6942bc ¤   {0xcf,'r'}, ··{0xca,'u'}, ··{0xc2,'u'}, ··{0xcd,'u'},
fb3d0f ¤   {0xc8,'u'}, ··{0xc2,'y'}, ··{0xcb,'t'}, ··{0xc7,ALONE}
e382f7 };
ca866f #elif (ISO_8859 == 3)
d18c41 static Couple trans_iso8859_t61[96] = {
5b8a8b ¤   {0xa0,0}, ····{0xe4,0}, ····{0xc6,ALONE}, {0xa3,0},
4c25fa ¤   {0xa8,0}, ····{0,0}, ·······{0xc3,'H'}, ··{0xa7,0},
952afb ¤   {0xc8,ALONE}, {0xc7,'I'}, ··{0xcb,'S'}, ··{0xc6,'G'},
5fda03 ¤   {0xc3,'J'}, ··{0xff,0}, ····{0,0}, ·······{0xc7,'Z'},
27eff4 ¤   {0xb0,0}, ····{0xf4,0}, ····{0xb2,0}, ····{0xb3,0},
bd93e3 ¤   {0xc2,ALONE}, {0xb5,0}, ····{0xc3,'h'}, ··{0xb7,0},
7d3fa9 ¤   {0xcb,ALONE}, {0xf5,0}, ····{0xcb,'s'}, ··{0xc6,'g'},
4fc4a3 ¤   {0xc3,'j'}, ··{0xbd,0}, ····{0,0}, ·······{0xc7,'z'},
f51584 ¤   {0xc1,'A'}, ··{0xc2,'A'}, ··{0xc3,'A'}, ··{0,0},
bf47dc ¤   {0xc8,'A'}, ··{0xc7,'C'}, ··{0xc3,'C'}, ··{0xcb,'C'},
d49fd4 ¤   {0xc1,'E'}, ··{0xc2,'E'}, ··{0xc3,'E'}, ··{0xc8,'E'},
d63a4d ¤   {0xc1,'I'}, ··{0xc2,'I'}, ··{0xc3,'I'}, ··{0xc8,'I'},
55c903 ¤   {0,0}, ·······{0xc4,'N'}, ··{0xc1,'O'}, ··{0xc2,'O'},
a140f5 ¤   {0xc3,'O'}, ··{0xc7,'G'}, ··{0xc8,'O'}, ··{0xb4,0},
baaedd ¤   {0xc3,'G'}, ··{0xc1,'U'}, ··{0xc2,'U'}, ··{0xc3,'U'},
bcfee8 ¤   {0xc8,'U'}, ··{0xc6,'U'}, ··{0xc3,'S'}, ··{0xfb,0},
974ea6 ¤   {0xc1,'a'}, ··{0xc2,'a'}, ··{0xc3,'a'}, ··{0,0},
894457 ¤   {0xc8,'a'}, ··{0xc7,'c'}, ··{0xc3,'c'}, ··{0xcb,'c'},
d29c5f ¤   {0xc1,'e'}, ··{0xc2,'e'}, ··{0xc3,'e'}, ··{0xc8,'e'},
cb39c6 ¤   {0xc1,'i'}, ··{0xc2,'i'}, ··{0xc3,'i'}, ··{0xc8,'i'},
cb1d68 ¤   {0,0}, ·······{0xc4,'n'}, ··{0xc1,'o'}, ··{0xc2,'o'},
3bf0dd ¤   {0xc3,'o'}, ··{0xc7,'g'}, ··{0xc8,'o'}, ··{0xb8,0},
5dad56 ¤   {0xc3,'g'}, ··{0xc1,'u'}, ··{0xc2,'u'}, ··{0xc3,'u'},
d024fc ¤   {0xc8,'u'}, ··{0xc6,'u'}, ··{0xc3,'s'}, ··{0xc7,ALONE}
dc82f7 };
280a6a #elif (ISO_8859 == 4)
5b8c41 static Couple trans_iso8859_t61[96] = {
ca07bf ¤   {0xa0,0}, ····{0xce,'A'}, ··{0xf0,0}, ····{0xcb,'R'},
43385f ¤   {0xa8,0}, ····{0xc4,'I'}, ··{0xcb,'L'}, ··{0xa7,0},
994ff6 ¤   {0xc8,ALONE}, {0xcf,'S'}, ··{0xc5,'E'}, ··{0xcb,'G'},
636501 ¤   {0xed,0}, ····{0xff,0}, ····{0xcf,'Z'}, ··{0xc5,ALONE},
0a2a6c ¤   {0xb0,0}, ····{0xce,'a'}, ··{0xce,ALONE}, {0xcb,'r'},
a6cf7b ¤   {0xc2,ALONE}, {0xc4,'i'}, ··{0xcb,'l'}, ··{0xcf,ALONE},
e10327 ¤   {0xcb,ALONE}, {0xcf,'s'}, ··{0xc5,'e'}, ··{0xcb,'g'},
1eb5bd ¤   {0xfd,0}, ····{0xee,0}, ····{0xcf,'z'}, ··{0xfe,0},
1486b7 ¤   {0xc5,'A'}, ··{0xc2,'A'}, ··{0xc3,'A'}, ··{0xc4,'A'},
04becb ¤   {0xc8,'A'}, ··{0xca,'A'}, ··{0xe1,0}, ····{0xce,'I'},
f3607f ¤   {0xcf,'C'}, ··{0xc2,'E'}, ··{0xce,'E'}, ··{0xc8,'E'},
d4ce59 ¤   {0xc7,'E'}, ··{0xc2,'I'}, ··{0xc3,'I'}, ··{0xc5,'I'},
05ed1a ¤   {0xe2,0}, ····{0xcb,'N'}, ··{0xc5,'O'}, ··{0xcb,'K'},
68ab54 ¤   {0xc3,'O'}, ··{0xc4,'O'}, ··{0xc8,'O'}, ··{0xb4,0},
--3f1a 00033b4669340100093 Page 14 of charset.c
feb7c5 ¤   {0xe9,0}, ····{0xce,'U'}, ··{0xc2,'U'}, ··{0xc3,'U'},
1ceea6 ¤   {0xc8,'U'}, ··{0xc4,'U'}, ··{0xc5,'U'}, ··{0xfb,0},
df853c ¤   {0xc5,'a'}, ··{0xc2,'a'}, ··{0xc3,'a'}, ··{0xc4,'a'},
6fd718 ¤   {0xc8,'a'}, ··{0xca,'a'}, ··{0xf1,0}, ····{0xce,'i'},
f663f4 ¤   {0xcf,'c'}, ··{0xc2,'e'}, ··{0xce,'e'}, ··{0xc8,'e'},
dacdd2 ¤   {0xc7,'e'}, ··{0xc2,'i'}, ··{0xc3,'i'}, ··{0xc5,'i'},
c637b5 ¤   {0xf2,0}, ····{0xcb,'n'}, ··{0xc5,'o'}, ··{0xcb,'k'},
bb1b7c ¤   {0xc3,'o'}, ··{0xc4,'o'}, ··{0xc8,'o'}, ··{0xb8,0},
516d6a ¤   {0xf9,0}, ····{0xce,'u'}, ··{0xc2,'u'}, ··{0xc3,'u'},
08a700 ¤   {0xc8,'u'}, ··{0xc4,'u'}, ··{0xc5,'u'}, ··{0xc7,ALONE}
4582f7 };
f4f515 #elif (ISO_8859 == 9)
1a8c41 static Couple trans_iso8859_t61[96] = {
034e98 ¤   {0xa0,0}, ····{0xa1,0}, ····{0xa2,0}, ····{0xa3,0},
af3a42 ¤   {0xa8,0}, ····{0xa5,0}, ····{0xd7,0}, ····{0xa7,0},
c0d1b1 ¤   {0xc8,ALONE}, {0xd3,0}, ····{0xe3,0}, ····{0xab,0},
4b2fd4 ¤   {0xd6,0}, ····{0xff,0}, ····{0xd2,0}, ····{0xc5,ALONE},
4ec5a8 ¤   {0xb0,0}, ····{0xb1,0}, ····{0xb2,0}, ····{0xb3,0},
51304f ¤   {0xc2,ALONE}, {0xb5,0}, ····{0xb6,0}, ····{0xb7,0},
3c2f19 ¤   {0xcb,ALONE}, {0xd1,0}, ····{0xeb,0}, ····{0xbb,0},
617c45 ¤   {0xbc,0}, ····{0xbd,0}, ····{0xbe,0}, ····{0xbf,0},
37c7c1 ¤   {0xc1,'A'}, ··{0xc2,'A'}, ··{0xc3,'A'}, ··{0xc4,'A'},
796e6d ¤   {0xc8,'A'}, ··{0xca,'A'}, ··{0xe1,0}, ····{0xcb,'C'},
089fd4 ¤   {0xc1,'E'}, ··{0xc2,'E'}, ··{0xc3,'E'}, ··{0xc8,'E'},
3d3a4d ¤   {0xc1,'I'}, ··{0xc2,'I'}, ··{0xc3,'I'}, ··{0xc8,'I'},
62e163 ¤   {0xc6,'G'}, ··{0xc4,'N'}, ··{0xc1,'O'}, ··{0xc2,'O'},
0eab54 ¤   {0xc3,'O'}, ··{0xc4,'O'}, ··{0xc8,'O'}, ··{0xb4,0},
07c3cb ¤   {0xe9,0}, ····{0xc1,'U'}, ··{0xc2,'U'}, ··{0xc3,'U'},
fcada1 ¤   {0xc8,'U'}, ··{0xc7,'I'}, ··{0xcb,'S'}, ··{0xfb,0},
43c44a ¤   {0xc1,'a'}, ··{0xc2,'a'}, ··{0xc3,'a'}, ··{0xc4,'a'},
f807be ¤   {0xc8,'a'}, ··{0xca,'a'}, ··{0xf1,0}, ····{0xcb,'c'},
63bb03 ¤   {0xc1,'e'}, ··{0xc2,'e'}, ··{0xce,'e'}, ··{0xc8,'e'},
12cdd2 ¤   {0xc7,'e'}, ··{0xc2,'i'}, ··{0xc3,'i'}, ··{0xc5,'i'},
0fe2e8 ¤   {0xc6,'g'}, ··{0xc4,'n'}, ··{0xc1,'o'}, ··{0xc2,'o'},
1a1b7c ¤   {0xc3,'o'}, ··{0xc4,'o'}, ··{0xc8,'o'}, ··{0xb8,0},
c31964 ¤   {0xf9,0}, ····{0xc1,'u'}, ··{0xc2,'u'}, ··{0xc3,'u'},
3f371c ¤   {0xc8,'u'}, ··{0xf5,0}, ····{0xcb,'s'}, ··{0xc8,'y'}
1382f7 };
801d8b #elif (ISO_8859 == 10)
dc8c41 static Couple trans_iso8859_t61[96] = {
f4bf32 ¤   {0xa0,0}, ····{0xce,'A'}, ··{0xc5,'E'}, ··{0xcb,'G'},
ab5576 ¤   {0xc5,'I'}, ··{0xc4,'I'}, ··{0xcb,'K'}, ··{0xa7,0},
199ea3 ¤   {0xcb,'L'}, ··{0xe2,0}, ····{0xcf,'S'}, ··{0xed,0},
6f2175 ¤   {0xcf,'Z'}, ··{0xff,0}, ····{0xc5,'U'}, ··{0xee,0},
20659d ¤   {0xb0,0}, ····{0xce,'a'}, ··{0xc5,'e'}, ··{0xcb,'g'},
a57cc4 ¤   {0xc5,'i'}, ··{0xc4,'i'}, ··{0xcb,'k'}, ··{0xb7,0},
34c742 ¤   {0xcb,'l'}, ··{0xf2,0}, ····{0xcf,'s'}, ··{0xfd,0},
2e7ae3 ¤   {0xcf,'z'}, ··{0xd0,0}, ····{0xc5,'u'}, ··{0xfe,0},
ee86b7 ¤   {0xc5,'A'}, ··{0xc2,'A'}, ··{0xc3,'A'}, ··{0xc4,'A'},
f2becb ¤   {0xc8,'A'}, ··{0xca,'A'}, ··{0xe1,0}, ····{0xce,'I'},
b9607f ¤   {0xcf,'C'}, ··{0xc2,'E'}, ··{0xce,'E'}, ··{0xc8,'E'},
917484 ¤   {0xc7,'E'}, ··{0xc2,'I'}, ··{0xc3,'I'}, ··{0xc8,'I'},
8658d4 ¤   {0,0}, ·······{0xcb,'N'}, ··{0xc5,'O'}, ··{0xc2,'O'},
886f62 ¤   {0xc3,'O'}, ··{0xc4,'O'}, ··{0xc8,'O'}, ··{0xc4,'U'},
9db7c5 ¤   {0xe9,0}, ····{0xce,'U'}, ··{0xc2,'U'}, ··{0xc3,'U'},
5e6b1c ¤   {0xc8,'U'}, ··{0xc2,'Y'}, ··{0xec,0}, ····{0xfb,0},
00853c ¤   {0xc5,'a'}, ··{0xc2,'a'}, ··{0xc3,'a'}, ··{0xc4,'a'},
87d718 ¤   {0xc8,'a'}, ··{0xca,'a'}, ··{0xf1,0}, ····{0xce,'i'},
e563f4 ¤   {0xcf,'c'}, ··{0xc2,'e'}, ··{0xce,'e'}, ··{0xc8,'e'},
04770f ¤   {0xc7,'e'}, ··{0xc2,'i'}, ··{0xc3,'i'}, ··{0xc8,'i'},
d3b079 ¤   {0xf3,0}, ····{0xcb,'n'}, ··{0xc5,'o'}, ··{0xc2,'o'},
ac6ce9 ¤   {0xc3,'o'}, ··{0xc4,'o'}, ··{0xc8,'o'}, ··{0xc4,'u'},
d66d6a ¤   {0xf9,0}, ····{0xce,'u'}, ··{0xc2,'u'}, ··{0xc3,'u'},
71a303 ¤   {0xc8,'u'}, ··{0xc2,'y'}, ··{0xfc,0}, ····{0xf0,0}
9b82f7 };
2a7454 #endif
80af5a
2caf5a
feb466 static Byte *
6838cb c_to_hh( Byte *o, Byte c )
38bb36 {
333688 ··Byte n;
--b7aa 0002b6275f940100093 Page 15 of charset.c
e0af5a
79eec7 ··*o++ = '{'; *o++ = 'x';
2bbd12 ··n = c >> 4;
221917 ··*o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
1be751 ··n = c & 0x0F;
011917 ··*o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
0a73f9 ··*o++ = '}';
bde80f ··return o;
67efe6 }
c5af5a
35af5a
ebb466 static Byte *
ad3e06 c_to_cc( Byte *o, Couple *cc, Byte c )
3bbb36 {
518faf ··if ( (*cc).a != 0 ) {
175fd3 ····if ( (*cc).b == 0 )
ea53fa ······*o++ = (*cc).a;
b383c8 ····else {
d92f2d ······*o++ = '{';
9d53fa ······*o++ = (*cc).a;
24bc9e ······*o++ = (*cc).b;
1f64b7 ······*o++ = '}';
186fe7 ····}
225caf ····return o;
15df1c ··}
e81bd0 ··else
74d05c ····return c_to_hh( o, c );
efefe6 }
e1af5a
93a6ae /* --- routine to convert from T.61 to ISO 8859-n --- */
caaf5a
c54d2f int
d8eda8 ldap_t61_to_8859( char **bufp, unsigned long *buflenp, int free_input )
7bbb36 {
18f93c ··Byte¤ ¤   *s, *oo, *o;
b6ee5e ··unsigned int ·n;
051063 ··int ··········c;
324607 ··unsigned long len;
3ccd64 ··Couple ·······*cc;
7faf5a
03dc90 ··Debug( LDAP_DEBUG_TRACE, "ldap_t61_to_8859 input length: %ld\n",
916ec4 ¤   *buflenp, 0, 0 );
e6af5a
9133be ··len = *buflenp;
85a780 ··s = (Byte *) *bufp;
42af5a
373e14 ··if ( (o = oo = (Byte *)malloc( 2 * len + 64 )) == NULL ) {
346d27 ········return( 1 );
87df1c ··}
7eaf5a
f1394f ··while ( (char *)s - *(char **)bufp < len ) {
8e8748 ····switch ( *s >> 4 ) {
fcaf5a
0b51e1 ····case 0xA: case 0xB:
9fcef7 ······o = c_to_cc( o, &trans_t61a_iso8859[ *s - 0xA0 ], *s );
65ff72 ······s++;
1088e1 ······break;
86af5a
542d1f ····case 0xD: case 0xE: case 0xF:
022fc1 ······o = c_to_cc( o, &trans_t61b_iso8859[ *s - 0xD0 ], *s );
a2ff72 ······s++;
3e88e1 ······break;
47af5a
d1679b ····case 0xC:
c3ad98 ······if ( (*s == 0xC0) || (*s == 0xC9) || (*s == 0xCC) ) {
2378cb ········o = c_to_hh( o, *s++ );
ad2d5f ········break;
2f42cc ······}
5eaf5a
681831 ······n = (*s++) - 0xC0;
d662fc ······switch ( *s ) {
2baf5a
--8cb8 000ba31d3bc40100093 Page 16 of charset.c
a47523 ······case 'A': ·c = letter_w_diacritic[n][0]; break;
476dfb ······case 'C': ·c = letter_w_diacritic[n][1]; break;
61e63f ······case 'D': ·c = letter_w_diacritic[n][2]; break;
301102 ······case 'E': ·c = letter_w_diacritic[n][3]; break;
abfcad ······case 'G': ·c = letter_w_diacritic[n][4]; break;
6ae17e ······case 'H': ·c = letter_w_diacritic[n][5]; break;
09bd61 ······case 'I': ·c = letter_w_diacritic[n][6]; break;
cd0715 ······case 'J': ·c = letter_w_diacritic[n][7]; break;
1bb9f5 ······case 'K': ·c = letter_w_diacritic[n][8]; break;
1a9913 ······case 'L': ·c = letter_w_diacritic[n][9]; break;
d3db08 ······case 'N': ·c = letter_w_diacritic[n][10]; break;
12e15d ······case 'O': ·c = letter_w_diacritic[n][11]; break;
776d1e ······case 'R': ·c = letter_w_diacritic[n][12]; break;
8f574b ······case 'S': ·c = letter_w_diacritic[n][13]; break;
2af0e0 ······case 'T': ·c = letter_w_diacritic[n][14]; break;
facab5 ······case 'U': ·c = letter_w_diacritic[n][15]; break;
43eb8e ······case 'W': ·c = letter_w_diacritic[n][16]; break;
f5b085 ······case 'Y': ·c = letter_w_diacritic[n][17]; break;
9c1c85 ······case 'Z': ·c = letter_w_diacritic[n][18]; break;
53af5a
efc330 ······case 'a': ·c = letter_w_diacritic[n][19]; break;
d2726d ······case 'c': ·c = letter_w_diacritic[n][20]; break;
fe20b1 ······case 'd': ·c = letter_w_diacritic[n][21]; break;
15b1c6 ······case 'e': ·c = letter_w_diacritic[n][22]; break;
f33bdf ······case 'g': ·c = letter_w_diacritic[n][23]; break;
a1fa67 ······case 'h': ·c = letter_w_diacritic[n][24]; break;
eec032 ······case 'i': ·c = letter_w_diacritic[n][25]; break;
928ecd ······case 'j': ·c = letter_w_diacritic[n][26]; break;
f6b498 ······case 'k': ·c = letter_w_diacritic[n][27]; break;
adaf99 ······case 'l': ·c = letter_w_diacritic[n][28]; break;
4c2580 ······case 'n': ·c = letter_w_diacritic[n][29]; break;
94262a ······case 'o': ·c = letter_w_diacritic[n][30]; break;
f4014b ······case 'r': ·c = letter_w_diacritic[n][31]; break;
e6903c ······case 's': ·c = letter_w_diacritic[n][32]; break;
ffc2e0 ······case 't': ·c = letter_w_diacritic[n][33]; break;
ab0dc2 ······case 'u': ·c = letter_w_diacritic[n][34]; break;
fd87db ······case 'w': ·c = letter_w_diacritic[n][35]; break;
a077f2 ······case 'y': ·c = letter_w_diacritic[n][36]; break;
33922f ······case 'z': ·c = letter_w_diacritic[n][37]; break;
50af5a
db4b9c ······case ALONE: ·c = (( !diacritic[n].b ) ? diacritic[n].a : -1);
7a8cd6 ···················break;
c5af5a
35d3f8 ······default: ··c = 0;
aa42cc ······}
cfaf5a
c26431 ······if ( c > 0 ) {
1423d9 ········*o++ = c; ·s++;
82cfc7 ······} else {
44dc7b ········*o++ = '{';
bb21a3 ········if ( c == -1 ) {
defc51 ··········*o++ = ( ( *s == ALONE ) ? ' ' : *s );
b1796d ··········s++;
a79d1e ········} else {
61b23d ··········*o++ = '"';
bf7fb0 ········}
bcf3b5 ········*o++ = diacritic[n].a;
0197e1 ········*o++ = '}';
f542cc ······}
2288e1 ······break;
5daf5a
763c7f #if (ISO_8859 == 0)
8e5c7b ····case 0x8: case 0x9:
af8d84 ······*o++ = 0x1B; /* <ESC> */
0bc32e ······*o++ = *s++ - 0x40;
f688e1 ······break;
457454 #endif
8caf5a
a81082 ······default:
5cb0f6 ········*o++ = *s++;
bf6fe7 ····}
badf1c ··}
--b6bb 000e6296b7440100093 Page 17 of charset.c
e0af5a
d6c45c ··len = o - oo;
6e3715 ··o = oo;
93af5a
2276fb ··if ( (oo = (Byte *)realloc( o, len )) == NULL ) {
981271 ····free( o );
7aa3d3 ····return( 1 );
d9df1c ··}
65af5a
e01482 ··if ( free_input ) {
458ea0 ····free( *bufp );
3edf1c ··}
3d4cae ··*bufp = (char *) oo;
7eb3c7 ··*buflenp = len;
30fa4e ··return( 0 );
99efe6 }
2faf5a
82af5a
2bbeb7 static int
44198d hh_to_c( Byte *h )
09bb36 {
1ac9f7 ··Byte c;
6aaf5a
c38b06 ··if ( (*h >= '0') && (*h <= '9') ) ·····c = *h++ - '0';
e3d63e ··else if ( (*h >= 'A') && (*h <= 'F') ) c = *h++ - 'A' + 10;
36cc79 ··else if ( (*h >= 'a') && (*h <= 'f') ) c = *h++ - 'a' + 10;
df458b ··else return -1;
8daf5a
a666e6 ··c <<= 4;
b0af5a
2cac4c ··if ( (*h >= '0') && (*h <= '9') ) ·····c |= *h - '0';
a89351 ··else if ( (*h >= 'A') && (*h <= 'F') ) c |= *h - 'A' + 10;
304422 ··else if ( (*h >= 'a') && (*h <= 'f') ) c |= *h - 'a' + 10;
d7458b ··else return -1;
33af5a
a54dac ··return c;
9cefe6 }
01af5a
ceaf5a
ebb466 static Byte *
ab76db cc_to_t61( Byte *o, Byte *s )
6fbb36 {
02ebda ··int n, c = 0;
90af5a
58d682 ··switch ( *(s + 1) ) {
04af5a
9c27f7 ··case '`': ·c = -1; ··break; ···/* <grave-accent> */
b6af5a
a91dfe ··case '!':
b720cf ····switch ( *s ) {
f1125c ····case '!': ·c = 0x7C; ·break; ·/* <vertical-line> */
52ee25 ····case '(': ·c = 0x7B; ·break; ·/* <left-curly-bracket> */
c748ad ····case '-': ·c = 0xAD; ·break; ·/* <upwards-arrow> */
f00509 ····default: ··c = -1; ···········/* <grave-accent> */
ec6fe7 ····}
68ab40 ····break;
4caf5a
53c79c #if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
8fed3d ····(ISO_8859 == 4) || (ISO_8859 == 9)
599adb ··case 0xB4:
6f7454 #endif
74b52a ··case '\'': c = -2; ·break; ···/* <acute-accent> */
7eaf5a
61452c ··case '^': ·c = -3; ·break; ···/* <circumflex-acent> */
b3af5a
366ca6 ··case '>':
6020cf ····switch ( *s ) {
b8bb4e ····case ')': ·c = 0x5D; ·break; ·/* <right-square-bracket> */
32e2e2 ····case '>': ·c = 0xBB; ·break; ·/* <right-angle-quotation> */
5075cb ····case '-': ·c = 0xAE; ·break; ·/* <rightwards-arrow> */
b6a6a3 ····default: ··c = -3; ···········/* <circumflex-acent> */
e66fe7 ····}
--c2b2 000db58b44540100093 Page 18 of charset.c
faab40 ····break;
fdaf5a
737a11 ··case '~':
f1aab0 ··case '?': ·c = -4; ·break; ·······/* <tilde> */
4aaf5a
91ac37 #if (ISO_8859 == 1) || (ISO_8859 == 4) || (ISO_8859 == 9)
a2f4b4 ··case 0xAF: ·c = -5; ·break; ······/* <macron> */
c27454 #endif
7faf5a
cb8aca ··case '-':
2120cf ····switch ( *s ) {
fcb70b ····case '-': ·c = 0xFF; break; /* <soft-hyphen> */
007832 ····case '<': ·c = 0xAC; break; /* <leftwards arrow> */
33160a ····case '+': ·c = 0xB1; break; /* <plus-minus> */
676a53 ····case 'd': ·c = 0xF3; break; /* <eth> */
4184d0 ····default: ··c = -5; ·········/* <macron> */
d36fe7 ····}
7aab40 ····break;
46af5a
d0efe7 #if (ISO_8859 == 2) || (ISO_8859 == 3)
719bcd ··case 0xA2: ·c = -6; ·break; ···········/* <breve> */
0f7454 #endif
daaf5a
b7e49d ··case '(':
94ac68 ····if ( *s == '<' ) c = 0x5B; ·/* <left-square-bracket> */
81f4ae ····else ············c = -6; ···/* <breve> */
ecab40 ····break;
4baf5a
16be80 #if (ISO_8859 == 2) || (ISO_8859 == 3) || (ISO_8859 == 4)
6902e4 ··case 0xFF: ·c = -7; ·break; ···/* <dot-accent> */
7e7454 #endif
ceaf5a
5eaf07 ··case '.':
c920cf ····switch ( *s ) {
fef88e ····case 'i': ·c = 0xF5; break; /* <dotless-i> */
7eea5c ····case 'L': ·c = 0xE7; break; /* <L-middle-dot> */
b2f265 ····case 'l': ·c = 0xF7; break; /* <l-middle-dot> */
7ef339 ····default: ··c = -7; ·········/* <dot-accent> */
bc6fe7 ····}
8dab40 ····break;
6aaf5a
bdc79c #if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
41ed3d ····(ISO_8859 == 4) || (ISO_8859 == 9)
d30418 ··case 0xA8: ·c = -8; break; /* <diaeresis> */
987454 #endif
0daf5a
2e1e4a ··case ':':
43bba5 ····if ( *s == '-') ·c = 0xB8; /* <division-sign> */
d4d8fd ····else ············c = -8; ··/* <diaeresis> */
7bab40 ····break;
b2af5a
61c79c #if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
663144 ····(ISO_8859 == 4) || (ISO_8859 == 9) || (ISO_8859 == 10)
13f9ba ··case 0xB0:
237454 #endif
ff0689 ··case '0': ·c = -10; ·break; ·/* <ring-above> */
a6af5a
24c79c #if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
aaed3d ····(ISO_8859 == 4) || (ISO_8859 == 9)
083f78 ··case 0xB8:
7e7454 #endif
32bc0e ··case ',': ·c = -11; break; /* <cedilla> */
99af5a
6f89c7 #if (ISO_8859 == 2)
a71a03 ··case 0xBD:
d97454 #endif
d31ec2 ··case '"': ·c = -13; break; /* <double-acute-accent> */
eaaf5a
6b63e2 #if (ISO_8859 == 2) || (ISO_8859 == 4)
2d4c02 ··case 0xB2:
cb7454 #endif
dbcaba ··case ';': ·c = -14; break; /* <ogonek> */
--f19a 000611fa0bd40100093 Page 19 of charset.c
e0af5a
1663e2 #if (ISO_8859 == 2) || (ISO_8859 == 4)
d12194 ··case 0xB7: ·c = -15; ·break; ·/* <caron> */
a47454 #endif
79af5a
c6f826 ··case ')':
a26ac1 ····if ( *s == '!' ) ·c = 0x7D; ·/* <left-curly-bracket> */
20ab40 ····break;
a0af5a
4055d0 ··case '<':
3e5e33 ····if ( *s == '<' ) ·c = 0xAB; ·/* <left-angle-quotation> */
ed5c54 ····else ·············c = -15; ··/* <caron> */
1cab40 ····break;
ffaf5a
bab3bc ··case '/':
bb20cf ····switch ( *s ) {
ee22f4 ····case '/': ·c = 0x5C; break; /* <reverse-solidus> */
013985 ····case 'D': ·c = 0xE2; break; /* <D-stroke> */
15c34f ····case 'd': ·c = 0xF2; break; /* <d-stroke> */
5e8303 ····case 'H': ·c = 0xE4; break; /* <H-stroke> */
ee79c9 ····case 'h': ·c = 0xF4; break; /* <h-stroke> */
ce754d ····case 'L': ·c = 0xE8; break; /* <L-stroke> */
d78f87 ····case 'l': ·c = 0xF8; break; /* <l-stroke> */
49f6c0 ····case 'O': ·c = 0xE9; break; /* <O-stroke> */
c20c0a ····case 'o': ·c = 0xF9; break; /* <o-stroke> */
d32e7b ····case 'T': ·c = 0xED; break; /* <T-stroke> */
5bd4b1 ····case 't': ·c = 0xFD; break; /* <t-stroke> */
256fe7 ····}
a8ab40 ····break;
5daf5a
1ffb92 ··case '2':
55490c ····if ( *s == '1' ) ·c = 0xBD; ···/* <one-half> */
74ab40 ····break;
7baf5a
1cb008 ··case '4':
9a20cf ····switch ( *s ) {
727eb2 ····case '1': ·c = 0xBC; break; /* <one-quarter> */
30bddb ····case '3': ·c = 0xBE; break; /* <three-quarters> */
da6fe7 ····}
33ab40 ····break;
53af5a
c3897e ··case '6':
8020cf ····switch ( *s ) {
4d80ed ····case '\'': c = 0xA9; break; /* <left-single-quotation> */
cea2e8 ····case '"': ·c = 0xAA; break; /* <left-double-quotation> */
566fe7 ····}
15ab40 ····break;
08af5a
a7273c ··case '8':
e620cf ····switch ( *s ) {
a8f78d ····case '1': ·c = 0xDC; break; /* <one-eighth> */
4b1fd5 ····case '3': ·c = 0xDD; break; /* <three-eighths> */
b64993 ····case '5': ·c = 0xDE; break; /* <five-eighths> */
448ecc ····case '7': ·c = 0xDF; break; /* <seven-eighths> */
6a6766 ····case 'M': ·c = 0xD5; break; /* <eighth-note> */
346fe7 ····}
20ab40 ····break;
feaf5a
063b87 ··case '9':
7f20cf ····switch ( *s ) {
9f415b ····case '\'': c = 0xB9; break; /* <right-single-quotation> */
2b970f ····case '"': ·c = 0xBA; break; /* <right-double-quotation> */
456fe7 ····}
feab40 ····break;
08af5a
0f841a ··case 'A':
628d5c ····if ( *s == 'A' ) ·c = -10; ·/* <ring-above> + <A> */
f1ab40 ····break;
deaf5a
f10b49 ··case 'a':
0720cf ····switch ( *s ) {
61b15d ····case '-': ·c = 0xE3; break; /* <femenine-ordinal-a> */
--268a 0006690934240100093 Page 20 of charset.c
4cd9ec ····case 'a': ·c = -10; ·break; /* <ring-above> + <a> */
406fe7 ····}
46ab40 ····break;
4eaf5a
56a1d7 ··case 'B':
f1ef33 ····if ( *s == 'B' ) ·c = 0xD7; /* <broken-bar> */
92ab40 ····break;
9aaf5a
852e84 ··case 'b':
bca17f ····if ( *s == 'N' ) ·c = 0xA6; ·/* <number-sign> */
9dab40 ····break;
5faf5a
05651e ··case 'd':
6a37ad ····if ( *s == 'P' ) ·c = 0xA3; ·/* <pound-sign> */
39ab40 ····break;
16af5a
5bf6f6 ··case 'E':
ed20cf ····switch ( *s ) {
800ddb ····case 'S': ·c = 0xA7; break; /* <section-sign> */
2912b1 ····case 'A': ·c = 0xE1; break; /* <AE> */
c00e39 ····case 'O': ·c = 0xEA; break; /* <OE> */
e16fe7 ····}
23ab40 ····break;
ceaf5a
bb79a5 ··case 'e':
ad20cf ····switch ( *s ) {
274b4c ····case 'a': ·c = 0xF1; break; /* <ae> */
6b57c4 ····case 'o': ·c = 0xFA; break; /* <oe> */
1c5071 ····case 'Y': ·c = 0xA5; ·break; ·/* <yen-sign> */
7f6fe7 ····}
c5ab40 ····break;
92af5a
6bcf80 ··case 'G':
7220cf ····switch ( *s ) {
f8a6f5 ····case 'D': ·c = 0xB0; break; /* <degree-sign> */
b5dc3d ····case 'N': ·c = 0xEE; break; /* <Eng> */
c96fe7 ····}
72ab40 ····break;
f1af5a
9c40d3 ··case 'g':
4d20cf ····switch ( *s ) {
4177e3 ····case 'R': ·c = 0xD2; break; ·/* <registered-sign> */
e6938d ····case 'n': ·c = 0xFE; break; /* <eng> */
646fe7 ····}
ebab40 ····break;
ddaf5a
977d79 ··case 'H':
c3d81c ····if ( *s == 'T' ) ·c = 0xEC; ·/* <Thorn> */
1bab40 ····break;
f7af5a
40f22a ··case 'h':
af8e46 ····if ( *s == 't' ) ·c = 0xFC; /* <thorn> */
8eab40 ····break;
07af5a
6261c2 ··case 'I':
9c20cf ····switch ( *s ) {
c57c7d ····case 'P': ·c = 0xB6; break; ·/* <pilcrow-sign> */
e7f4b7 ····case '!': ·c = 0xA1; break; /* <inverted-exclamation> */
1fc356 ····case '?': ·c = 0xBF; break; /* <inverted-question> */
5b6fe7 ····}
37ab40 ····break;
24af5a
48440f ··case 'J':
5405b0 ····if ( *s == 'I' ) ·c = 0xE6; /* <IJ> */
3bab40 ····break;
c0af5a
a4cb5c ··case 'j':
235708 ····if ( *s == 'i' ) ·c = 0xF6; ·/* <ij> */
deab40 ····break;
d5af5a
e2d7e7 ··case 'k':
6603cd ····if ( *s == 'k' ) ·c = 0xF0; /* <kra> */
--0c56 0004f7cf5e140100093 Page 21 of charset.c
faab40 ····break;
fdaf5a
91132e ··case 'M':
b720cf ····switch ( *s ) {
6d7deb ····case '.': ·c = 0xB7; break; /* <middle-dot> */
ee2968 ····case '-': ·c = 0xD0; break; /* <em-dash> */
663f32 ····case 'T': ·c = 0xD4; break; /* <trade-mark-sign> */
136fe7 ····}
7fab40 ····break;
70af5a
b09c7d ··case 'm':
2f20cf ····switch ( *s ) {
74c14b ····case '\'': ·················/* <macron> RFC 1345 */
73117a ····case ' ': ·c = -5; ··break; /* <macron> */
963677 ····case 'O': ·c = 0xE0; break; /* <Ohm sign> */
0e6fe7 ····}
56ab40 ····break;
6aaf5a
ebb9b0 ··case 'n':
91b054 ····if ( *s == '\'' ) ·c = 0xEF; /* <n-preceded-by-apostrophe> */
e2ab40 ····break;
80af5a
f52a58 ··case 'O':
3820cf ····switch ( *s ) {
cd718c ····case 'D': ·c = 0xA4; break; /* <dollar-sign> */
19085f ····case 'N': ·c = 0xD6; break; /* <not-sign> */
7b6fe7 ····}
daab40 ····break;
faaf5a
40a50b ··case 'o':
dd20cf ····switch ( *s ) {
7a50c4 ····case 'C': ·c = 0xD3; break; /* <copyright-sign> */
e3363a ····case '-': ·c = 0xEB; break; /* <masculine-ordinal-o> */
7f6fe7 ····}
a1ab40 ····break;
59af5a
597ecd ··case 'S':
f420cf ····switch ( *s ) {
a3c748 ····case '1': ·c = 0xD1; break; /* <superscript-1> */
e95310 ····case '2': ·c = 0xB2; break; /* <superscript-2> */
55a01e ····case '3': ·c = 0xB3; break; /* <superscript-3> */
de555c ····case 'N': ·c = 0xA0; break; /* <no-break-space> */
fb6fe7 ····}
2bab40 ····break;
0faf5a
d1f19e ··case 's':
e8be28 ····if ( *s == 's' ) ·c = 0xFB; /* <sharp-s> */
48ab40 ····break;
faaf5a
2aa6bf ··case 't':
8bdac0 ····if ( *s == 'C' ) ·c = 0xA2; /* <cent-sign> */
f6ab40 ····break;
83af5a
a3ba04 ··case 'u':
109c52 ····if ( *s == 'C' ) ·c = 0xA8; /* <currency-sign> */
d5ab40 ····break;
faaf5a
9e9fc9 ··case 'v':
85acbd ····if ( *s == '-' ) ·c = 0xAF; /* <downwards-arrow> */
26ab40 ····break;
d0af5a
19bed8 ··case 'X':
ecea36 ····if ( *s == '*' ) ·c = 0xB4; /* <multiplication-sign> */
cbab40 ····break;
2daf5a
952d30 ··case 'y':
c515a5 ····if ( *s == 'M' ) ·c = 0xB5; /* <micro-sign> */
acab40 ····break;
fadf1c ··}
f7af5a
e2aac5 ··if ( c > 0 ) {
4fac70 ····*o++ = c;
--870f 000e29da8d540100093 Page 22 of charset.c
cc5caf ····return o;
6084c8 ··} else if ( !c )
f67daf ····return NULL;
f3af5a
3d447e ··/* else: c < 0 */
d33cc8 ··n = -c;
ecd399 ··switch ( *s ) {
c1af5a
797fea ··case 'A': ·c = letter_w_diacritic[n][0]; break;
3a6732 ··case 'C': ·c = letter_w_diacritic[n][1]; break;
98ecf6 ··case 'D': ·c = letter_w_diacritic[n][2]; break;
f91bcb ··case 'E': ·c = letter_w_diacritic[n][3]; break;
4df664 ··case 'G': ·c = letter_w_diacritic[n][4]; break;
b9ebb7 ··case 'H': ·c = letter_w_diacritic[n][5]; break;
01b7a8 ··case 'I': ·c = letter_w_diacritic[n][6]; break;
860ddc ··case 'J': ·c = letter_w_diacritic[n][7]; break;
00b33c ··case 'K': ·c = letter_w_diacritic[n][8]; break;
4793da ··case 'L': ·c = letter_w_diacritic[n][9]; break;
7d80cf ··case 'N': ·c = letter_w_diacritic[n][10]; break;
50ba9a ··case 'O': ·c = letter_w_diacritic[n][11]; break;
be36d9 ··case 'R': ·c = letter_w_diacritic[n][12]; break;
280c8c ··case 'S': ·c = letter_w_diacritic[n][13]; break;
b6ab27 ··case 'T': ·c = letter_w_diacritic[n][14]; break;
f69172 ··case 'U': ·c = letter_w_diacritic[n][15]; break;
f9b049 ··case 'W': ·c = letter_w_diacritic[n][16]; break;
d1eb42 ··case 'Y': ·c = letter_w_diacritic[n][17]; break;
394742 ··case 'Z': ·c = letter_w_diacritic[n][18]; break;
7faf5a
6a98f7 ··case 'a': ·c = letter_w_diacritic[n][19]; break;
6529aa ··case 'c': ·c = letter_w_diacritic[n][20]; break;
197b76 ··case 'd': ·c = letter_w_diacritic[n][21]; break;
14ea01 ··case 'e': ·c = letter_w_diacritic[n][22]; break;
796018 ··case 'g': ·c = letter_w_diacritic[n][23]; break;
52a1a0 ··case 'h': ·c = letter_w_diacritic[n][24]; break;
3a9bf5 ··case 'i': ·c = letter_w_diacritic[n][25]; break;
c4d50a ··case 'j': ·c = letter_w_diacritic[n][26]; break;
e5ef5f ··case 'k': ·c = letter_w_diacritic[n][27]; break;
abf45e ··case 'l': ·c = letter_w_diacritic[n][28]; break;
dd7e47 ··case 'n': ·c = letter_w_diacritic[n][29]; break;
6d7ded ··case 'o': ·c = letter_w_diacritic[n][30]; break;
da5a8c ··case 'r': ·c = letter_w_diacritic[n][31]; break;
e8cbfb ··case 's': ·c = letter_w_diacritic[n][32]; break;
fd9927 ··case 't': ·c = letter_w_diacritic[n][33]; break;
b05605 ··case 'u': ·c = letter_w_diacritic[n][34]; break;
f1dc1c ··case 'w': ·c = letter_w_diacritic[n][35]; break;
ba2c35 ··case 'y': ·c = letter_w_diacritic[n][36]; break;
0ac9e8 ··case 'z': ·c = letter_w_diacritic[n][37]; break;
c8af5a
6d1479 ··case '\'':
7379e4 ··case ' ': ·c = -1; break;
1eaf5a
fd6c17 ··default: ··c = 0;
3adf1c ··}
70af5a
65bfce ··if ( !c )
277daf ····return NULL;
17af5a
f1a0ba ··*o++ = n + 0xC0;
bcb1c1 ··*o++ = ( ( (*s == ' ') || (*s == '\'') ) ? ALONE : *s );
8ce80f ··return o;
a8efe6 }
6caf5a
33af5a
732071 /* --- routine to convert from ISO 8859-n to T.61 --- */
82af5a
8b4d2f int
4572e3 ldap_8859_to_t61( char **bufp, unsigned long *buflenp, int free_input )
15bb36 {
5dfc85 ··Byte¤ ¤   *s, *oo, *o, *aux;
5122c1 ··int¤  ¤   c;
e851b5 ··unsigned long len;·
e2e965 ··Couple¤   *cc;
--443f 0004075994d40100093 Page 23 of charset.c
e0af5a
9f9af1 ··Debug( LDAP_DEBUG_TRACE, "ldap_8859_to_t61 input length: %ld\n",
836ec4 ¤   *buflenp, 0, 0 );
38af5a
da33be ··len = *buflenp;
e6a780 ··s = (Byte *) *bufp;
44af5a
7d3e14 ··if ( (o = oo = (Byte *)malloc( 2 * len + 64 )) == NULL ) {
d96d27 ········return( 1 );
86df1c ··}
eaaf5a
28394f ··while ( (char *)s - *(char **)bufp < len ) {
5fd83c ····switch( *s >> 5 ) {
b8af5a
01faa9 ····case 2:
df62fc ······switch ( *s ) {
20af5a
a1f1a7 ······case '^': ·*o++ = 0xC3; *o++ = ALONE; s++; break;
72af5a
61794e ······case '\\':
55dcd3 ········s++;
5eec59 ········if ( (c = hh_to_c( s )) != -1 ) {
a54868 ··········*o++ = c;
8e0d4f ··········s += 2;
fb486a ········} else
6124d9 ··········*o++ = '\\';
1e2d5f ········break;
63af5a
4ca171 ······default: ·*o++ = *s++;
da42cc ······}
e988e1 ······break;
67af5a
92a075 ····case 3:
ee62fc ······switch ( *s ) {
9faf5a
3efd01 ······case '`': ·*o++ = 0xC1; *o++ = ALONE; s++; break;
2687e2 ······case '~': ·*o++ = 0xC4; *o++ = ALONE; s++; break;
a0af5a
47fcb6 ······case '{':
2edcd3 ········s++;
0db479 ········if ( *(s + 2) == '}' ) {
bdf1a0 ··········if ( (aux = cc_to_t61( o, s )) != NULL ) {
3ecaac ············o = aux;
c6a4c5 ············s += 3;
2e64aa ··········} else {
7b6394 ············*o++ = '{';
04ccb2 ··········}
7d2a76 ········} else if ( (*(s + 3) == '}') && ( (*s == 'x') || (*s == 'X') ) &&
fe1167 ····················( (c = hh_to_c( s + 1 )) != -1 ) ) {
de4868 ··········*o++ = c;
b3db96 ··········s += 4;
ca9d1e ········} else {
3d9e48 ··········*o++ = '{';
827fb0 ········}
f02d5f ········break;
3faf5a
d11082 ······default:
22b0f6 ········*o++ = *s++;
7942cc ······}
c088e1 ······break;
fdaf5a
613c7f #if (ISO_8859 == 0)
6c3ad6 ····case 4: case 5: case 6: case 7:
12ff72 ······s++;
6088e1 ······break;
74db21 #else
b47d1d ····case 5: case 6: case 7:
761863 # if (ISO_8859 == 1) || (ISO_8859 == 2) || (ISO_8859 == 3) || \
7d47f7 ·····(ISO_8859 == 4) || (ISO_8859 == 9) || (ISO_8859 == 10)
03914a ······if ( (*(cc = &trans_iso8859_t61[ *s - 0xA0 ])).a ) {
353ef2 ¤   *o++ = (*cc).a;
40e068 ¤   if ( (*cc).b ) ·*o++ = (*cc).b;
--aa76 000d6695d1840100093 Page 24 of charset.c
a642cc ······}
d8e01a # endif
14ff72 ······s++;
1888e1 ······break;
527454 #endif
ffaf5a
6cb53c ····default:
7487b6 ······*o++ = *s++;
c76fe7 ····}
7adf1c ··}
5baf5a
e8c45c ··len = o - oo;
f03715 ··o = oo;
82af5a
9176fb ··if ( (oo = (Byte *)realloc( o, len )) == NULL ) {
db1271 ····free( o );
5ba3d3 ····return( 1 );
acdf1c ··}
edaf5a
121482 ··if ( free_input ) {
5c8ea0 ····free( *bufp );
81df1c ··}
544cae ··*bufp = (char *) oo;
b1b3c7 ··*buflenp = len;
53fa4e ··return( 0 );
f3efe6 }
92af5a
c5af5a
81598a #ifdef NOT_NEEDED_IN_LIBLDAP¤   /* mcs@umich.edu 12 Oct 1995 */
041cdb /* --- routine to convert "escaped" (\hh) characters to 8bits --- */
ddaf5a
0a4fd4 void convert_escaped_to_8bit( s )
5ae069 char¤   *s;
40bb36 {
299a84 ··char¤ *o = s;
b66f58 ··int¤  c;
4eaf5a
2109a5 ··while ( *s ) {
76ea69 ····if ( *s == '\\' ) {
a8cf26 ······if ( (c = hh_to_c( ++s )) != -1 ) {
d50790 ¤   *o++ = c;
e519df ¤   s += 2;
c2edd4 ······} else
8b2783 ········*o++ = '\\';
8ece75 ····} else
0487b6 ······*o++ = *s++;
84df1c ··}
c1e021 ··*o = '\0';
0defe6 }
d2af5a
6c57f6 /* --- routine to convert 8bits characters to the "escaped" (\hh) form --- */
3caf5a
207c8c char *convert_8bit_to_escaped( s )
753564 Byte ·*s;
02bb36 {
998f9b ··Byte¤ *o, *oo;
87adb8 ··Byte¤ n;
ddaf5a
4edbcf ··if ( (o = oo = (Byte *)malloc( 2 * strlen( s ) + 64 )) == NULL ) {
4e05a6 ········return( NULL );
cfdf1c ··}
13af5a
3309a5 ··while ( *s ) {
f44633 ····if ( *s < 0x80 )
c187b6 ······*o++ = *s++;
4083c8 ····else {
7c10c3 ······*o++ = '\\';
35e5f4 ······n = *s >> 4;
3cbca6 ······*o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
349537 ······n = *s++ & 0x0F;
48bca6 ······*o++ = ((n < 0xA) ? '0' : 'A' - 0xA) + n;
d66fe7 ····}
--20d4 00038447bc340100093 Page 25 of charset.c
3adf1c ··}
e0e021 ··*o = '\0';
3eaf5a
803715 ··o = oo;
daaf5a
f7b072 ··if ( (oo = (Byte *)realloc( o, strlen( o ) + 1 )) == NULL ) {
891271 ····free( o );
f9ba49 ····return( NULL );
bddf1c ··}
edaf5a
e1ea55 ··return( (char *)oo );
68efe6 }
9daf5a
2dbacb /* --- routine to convert from T.61 to printable characters --- */
29af5a
8338e5 /*
507871 ···printable characters [RFC 1488]: 'A'..'Z', 'a'..'z', '0'..'9',
80e260 ·······'\'', '(', ')', '+', ',', '-', '.', '/', ':', '?, ' '.
71af5a
6c9d54 ···that conversion is language dependent.
427fe0 */
f0af5a
337d57 static Couple last_t61_printabled[32] = {
bd3e20 ¤   {0,0}, ····{'A','E'}, {'D',0}, ··{0,0},
6c3ab4 ¤   {'H',0}, ··{0,0}, ····{'I','J'}, {'L',0},
4449b2 ¤   {'L',0}, ··{'O',0}, ··{'O','E'}, {0,0},
0efa84 ¤   {'T','H'}, {'T',0}, ··{'N','G'}, {'n',0},
e29907 ¤   {'k',0}, ··{'a','e'}, {'d',0}, ··{'d',0},
27787b ¤   {'h',0}, ··{'i',0}, ··{'i','j'}, {'l',0},
27719e ¤   {'l',0}, ··{'o',0}, ··{'o','e'}, {'s','s'},
bfcad3 ¤   {'t','h'}, {'t',0}, ··{'n','g'}, {0,0}
2482f7 };
54af5a
f80259 char *t61_printable( s )
c53564 Byte ·*s;
3cbb36 {
c6a3f7 ··Byte ··*o, *oo;
dd99cc ··Byte ··n;
8db448 ··Couple *cc;
98af5a
18dbcf ··if ( (o = oo = (Byte *)malloc( 2 * strlen( s ) + 64 )) == NULL ) {
7305a6 ········return( NULL );
ffdf1c ··}
32af5a
9709a5 ··while ( *s ) {
d80478 ····if ( ( (*s >= 'A') && (*s <= 'Z') ) ||
f3e95f ·········( (*s >= 'a') && (*s <= 'z') ) ||
d27e1c ·········( (*s >= '0') && (*s <= '9') ) ||
a6dbd7 ·········( (*s >= '\'') && (*s <= ')') ) ||
af9e4c ·········( (*s >= '+') && (*s <= '/') ) ||
ceeaf3 ·········( *s == '?' ) || ( *s == ' ' ) )
3e87b6 ······*o++ = *s++;
4483c8 ····else {
d6abbf ······if ( *s >= 0xE0 ) {
01b626 ¤   if ( (*(cc = &last_t61_printabled[ *s - 0xE0 ])).a ) {
e474d7 ··········*o++ = (*cc).a;
45578f ··········if ( (*cc).b ) ·*o++ = (*cc).b;
887fb0 ········}
d442cc ······}
9d9a84 ······else if ( (*s >> 4) == 0xC ) {
bc9f20 ········switch ( *s ) {
50a3be ¤   case 0xCA:¤ ¤   ¤   /* ring */
8a20e7 ¤   ··switch ( *(s + 1) ) {
06c7c0 ¤   ··case 'A': ·*o++ = 'A'; *o++ = 'A'; s++; break; /* Swedish */
f72619 ¤   ··case 'a': ·*o++ = 'a'; *o++ = 'a'; s++; break; /* Swedish */
1232a2 ¤   ··}
6d12af ¤   ··break;
3eaf5a
164cd4 ¤   case 0xC8:¤ ¤   ¤   /* diaeresis */
4a20e7 ¤   ··switch ( *(s + 1) ) {
845875 ¤   ··case 'Y': ·*o++ = 'I'; *o++ = 'J'; s++; break; /* Dutch */
38d095 ¤   ··case 'y': ·*o++ = 'i'; *o++ = 'j'; s++; break; /* Dutch */
--ce0d 0010410fb5040100093 Page 26 of charset.c
90ccb2 ··········}
1412af ¤   ··break;
057fb0 ········}
2542cc ······}
72ff72 ······s++;
fc6fe7 ····}
6bdf1c ··}
bbe021 ··*o = '\0';
8aaf5a
033715 ··o = oo;
d0af5a
32b072 ··if ( (oo = (Byte *)realloc( o, strlen( o ) + 1 )) == NULL ) {
4c1271 ····free( o );
81ba49 ····return( NULL );
cddf1c ··}
14af5a
f2ea55 ··return( (char *)oo );
d2efe6 }
b39959 #endif /* NOT_NEEDED_IN_LIBLDAP */¤ /* mcs@umich.edu 12 Oct 1995 */
edaf5a
857911 #endif /* LDAP_CHARSET_8859 */
043dd6 #endif /* STR_TRANSLATION */
--e7ac 00094ae036b40100094 Page 1 of cldap.c
bc38e5 /*
3a3c7d ·* ·Copyright (c) 1990, 1994 Regents of the University of Michigan.
31e4d4 ·* ·All rights reserved.
4e775e ·*
fb1f24 ·* ·cldap.c - synchronous, retrying interface to the cldap protocol
bc495d ·*/
6baf5a
2caf5a
f4ed07 #ifdef CLDAP
3daf5a
a066a8 #ifndef lint
4cef12 static char copyright[] = "@(#) Copyright (c) 1990, 1994 Regents of the "
5cf59d ¤   ¤   ¤   ··"University of Michigan.\nAll rights reserved.\n";
567454 #endif
82af5a
a8feb2 #include <stdio.h>
4c324c #include <string.h>
ad495d #include <errno.h>
29c583 #ifdef MACOS
9ebea3 #include <stdlib.h>
6e65e0 #include "macos.h"
136c94 #else /* MACOS */
2701b0 #ifdef DOS
bbf2ef #include "msdos.h"
1caad8 #else /* DOS */
eda394 #ifndef WIN32¤  ¤   /* marcd */
d55d8c #include <sys/time.h>
1e7454 #endif
39f15e #include <sys/types.h>
0da394 #ifndef WIN32¤  ¤   /* marcd */
0366f2 #include <sys/socket.h>
7b7454 #endif
b56c19 #include <netinet/in.h>
c52a51 #include <netdb.h>
debc39 #endif /* DOS */
a5e962 #endif /* MACOS */
48af5a
80b779 #include "lber.h"
d9e990 #include "ldap.h"
66745c #include "ldap-int.h"
90af5a
47c9e1 #define DEF_CLDAP_TIMEOUT¤  3
dd0851 #define DEF_CLDAP_TRIES¤¤   4
90af5a
54ea0b #ifndef INADDR_LOOPBACK
15cbf0 #define INADDR_LOOPBACK¤((unsigned long) 0x7f000001)
d37454 #endif
e7af5a
ccaf5a
1ecc00 struct cldap_retinfo {
4bfed3 ¤   int¤¤   cri_maxtries;
cfb8a0 ¤   int¤¤   cri_try;
a0acf0 ¤   int¤¤   cri_useaddr;
8227b0 ¤   long¤   ¤   cri_timeout;
af82f7 };
ccaf5a
22504c #ifdef NEEDPROTOS
03b7a0 static int add_addr( LDAP *ld, struct sockaddr *sap );
20388d static int cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
6582a3 ¤   struct cldap_retinfo *crip, char *base );
be729f static int cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber,
859ebd ¤   LDAPMessage **res, char *base );
436133 #else /* NEEDPROTOS */
2e86ac static int add_addr();
bd6291 static int cldap_result();
3af609 static int cldap_parsemsg();
038634 #endif /* NEEDPROTOS */
98af5a
7938e5 /*
6b1613 ·* cldap_open - initialize and connect to an ldap server. ·A magic cookie to
25597d ·* be used for future communication is returned on success, NULL on failure.
94775e ·*
--9423 0000d5c63aa40100094 Page 2 of cldap.c
5a305c ·* Example:
032af3 ·*¤ LDAP¤   *ld;
842b39 ·*¤ ld = cldap_open( hostname, port );
f1495d ·*/
05af5a
a009b3 LDAP *
c85427 cldap_open( char *host, int port )
dabb36 {
c763bb ····int ¤   ¤   s;
b64727 ····unsigned long¤  address;
e90fbe ····struct sockaddr_in ¤sock;
f36314 ····struct hostent¤ *hp;
1130c0 ····LDAP¤   ¤   *ld;
879df9 ····char¤   ¤   *p;
173ee2 ····int¤¤   ¤   i;
7aaf5a
a32d67 ····Debug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 );
96af5a
be3347 ····if ( port == 0 ) {
4b24f2 ¤   ····port = LDAP_PORT;
786fe7 ····}
f6af5a
78e2bb ····if ( (s = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
7a9572 ¤   return( NULL );
ee6fe7 ····}
66af5a
7eff08 ····sock.sin_addr.s_addr = 0;
780d53 ····sock.sin_family = AF_INET;
3c768b ····sock.sin_port = 0;
19acf4 ····if ( bind(s, (struct sockaddr *) &sock, sizeof(sock)) < 0) ·{
a2dd53 ¤   close( s );
609572 ¤   return( NULL );
f96fe7 ····}
c8af5a
1ba048 ····if (( ld = ldap_init( host, port )) == NULL ) {
22dd53 ¤   close( s );
669572 ¤   return( NULL );
486fe7 ····}
1ff62d ····if ( (ld->ld_sb.sb_fromaddr = (void *) calloc( 1,
38d561 ¤   ····sizeof( struct sockaddr ))) == NULL ) {
64b97d ¤   free( ld );
c7dd53 ¤   close( s );
349572 ¤   return( NULL );
6b096b ····}¤
92e901 ····ld->ld_sb.sb_sd = s;
096f32 ····ld->ld_sb.sb_naddr = 0;
1cb58d ····ld->ld_version = LDAP_VERSION;
31af5a
ca0d53 ····sock.sin_family = AF_INET;
dc962b ····sock.sin_port = PGPHostToNetShort( port );
77af5a
5429ec ····/*
e0f2b7 ·····* 'host' may be a space-separated list.
7cd48d ·····*/
c72435 ····if ( host != NULL ) {
df268f ¤   for ( ; host != NULL; host = p ) {
cc8402 ¤   ····if (( p = strchr( host, ' ' )) != NULL ) {
936234 ¤   ¤   for (*p++ = '\0'; *p == ' '; p++) {
814d86 ¤   ¤   ····;
770fe4 ¤   ¤   }
e8f372 ¤   ····}
11af5a
32eb27 ¤   ····if ( (address = inet_addr( host )) == -1 ) {
3107ab ¤   ¤   if ( (hp = gethostbyname( host )) == NULL ) {
5f3625 ¤   ¤   ····errno = EHOSTUNREACH;
08bc15 ¤   ¤   ····continue;
e40fe4 ¤   ¤   }
d7af5a
5cbff9 ¤   ¤   for ( i = 0; hp->h_addr_list[ i ] != 0; ++i ) {
31eccf ¤   ¤   ····SAFEMEMCPY( (char *)&sock.sin_addr.s_addr,
c94872 ¤   ¤   ¤   ····(char *)hp->h_addr_list[ i ],
0d2e9f ¤   ¤   ¤   ····sizeof(sock.sin_addr.s_addr));
--8474 0005d5bf6da40100094 Page 3 of cldap.c
288aaf ¤   ¤   ····if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
9330d4 ¤   ¤   ¤   close( s );
e354fa ¤   ¤   ¤   free( ld );
b119e3 ¤   ¤   ¤   return( NULL );
a45f30 ¤   ¤   ····}
980fe4 ¤   ¤   }
41af5a
7adfe8 ¤   ····} else {
ec8316 ¤   ¤   sock.sin_addr.s_addr = address;
028401 ¤   ¤   if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
6bc294 ¤   ¤   ····close( s );
9ca6ba ¤   ¤   ····free( ld );
0036d8 ¤   ¤   ····return( NULL );
550fe4 ¤   ¤   }
5df372 ¤   ····}
c2af5a
085132 ¤   ····if ( ld->ld_host == NULL ) {
46905a ¤   ¤   ····ld->ld_host = strdup( host );
c5f372 ¤   ····}
539371 ¤   }
4faf5a
8e6a79 ····} else {
477764 ¤   address = INADDR_LOOPBACK;
9d4dbb ¤   sock.sin_addr.s_addr = PGPHostToNetLong( address );
be6601 ¤   if ( add_addr( ld, (struct sockaddr *)&sock ) < 0 ) {
6db860 ¤   ····close( s );
b3dc4e ¤   ····free( ld );
aac0bd ¤   ····return( NULL );
059371 ¤   }
a56fe7 ····}
8faf5a
9c5872 ····if ( ld->ld_sb.sb_addrs == NULL
597f8d #ifdef LDAP_REFERRALS
5df685 ¤   ····|| ( ld->ld_defconn = new_connection( ld, NULL, 1,0,0 )) == NULL
5e90e2 #endif /* LDAP_REFERRALS */
9c6aed ¤   ····) {
c0b97d ¤   free( ld );
6a9572 ¤   return( NULL );
926fe7 ····}
d5af5a
c04c78 ····ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ 0 ];
0383ca ····cldap_setretryinfo( ld, 0, 0 );
9aaf5a
452639 #ifdef LDAP_DEBUG
2938f0 ····putchar( '\n' );
8b3e59 ····for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) {
cdc41e ¤   Debug( LDAP_DEBUG_TRACE, "end of cldap_open address %d is %s\n",
bf05a0 ¤   ¤   i, inet_ntoa( ((struct sockaddr_in *)
7393d0 ¤   ¤   ld->ld_sb.sb_addrs[ i ])->sin_addr ), 0 );
7b6fe7 ····}
3a7454 #endif
9faf5a
8fb457 ····return( ld );
16efe6 }
60af5a
3baf5a
5baf5a
ae314a void
8f27a8 cldap_close( LDAP *ld )
d9bb36 {
cf0032 ¤   ldap_ld_free( ld, 0 );
32efe6 }
08af5a
21af5a
00314a void
568181 cldap_setretryinfo( LDAP *ld, int tries, int timeout )
14bb36 {
64b1e9 ····ld->ld_cldaptries = ( tries <= 0 ) ? DEF_CLDAP_TRIES : tries;
15d804 ····ld->ld_cldaptimeout = ( timeout <= 0 ) ? DEF_CLDAP_TIMEOUT : timeout;
eeefe6 }
33af5a
5daf5a
--a0e1 000c09849f440100094 Page 4 of cldap.c
af4d2f int
5229ca cldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
e29458 ¤   int attrsonly, LDAPMessage **res, char *logdn )
29bb36 {
a0bd9d ····int¤¤   ¤   ¤   ret, msgid;
753e16 ····struct cldap_retinfo¤   cri;
d5af5a
cef2df ····*res = NULLMSG;
e2af5a
34c4fe ····(void) memset( &cri, 0, sizeof( cri ));
25af5a
d7e258 ····if ( logdn != NULL ) {
db4fca ¤   ld->ld_cldapdn = logdn;
df7ccd ····} else if ( ld->ld_cldapdn == NULL ) {
44192c ¤   ld->ld_cldapdn = "";
ad6fe7 ····}
4baf5a
45c9a3 ····do {
4e8ccf ¤   if ( cri.cri_try != 0 ) {
83fc7b ¤   ¤   --ld->ld_msgid;¤/* use same id as before */
a79371 ¤   }
82a838 ¤   ld->ld_sb.sb_useaddr = ld->ld_sb.sb_addrs[ cri.cri_useaddr ];
6eaf5a
1c0dd2 ¤   Debug( LDAP_DEBUG_TRACE, "cldap_search_s try %d (to %s)\n",
be2ac6 ¤   ····cri.cri_try, inet_ntoa( ((struct sockaddr_in *)
679539 ¤   ····ld->ld_sb.sb_useaddr)->sin_addr ), 0 );
56af5a
7775e1 ¤   ····if ( (msgid = ldap_search( ld, base, scope, filter, attrs,
0764cf ¤   ¤   attrsonly )) == -1 ) {
5d641c ¤   ¤   ····return( ld->ld_errno );
baf372 ¤   ····}
be23e9 #ifndef NO_CACHE
3b8b36 ¤   ····if ( ld->ld_cache != NULL && ld->ld_responses != NULL ) {
9ced18 ¤   ¤   Debug( LDAP_DEBUG_TRACE, "cldap_search_s res from cache\n",
8d2a00 ¤   ¤   ¤   0, 0, 0 );
442570 ¤   ¤   *res = ld->ld_responses;
0ca07a ¤   ¤   ld->ld_responses = ld->ld_responses->lm_next;
459a46 ¤   ¤   return( ldap_result2error( ld, *res, 0 ));
59f372 ¤   ····}
1e1992 #endif /* NO_CACHE */
c416ef ¤   ····ret = cldap_result( ld, msgid, res, &cri, base );
6d3041 ¤   } while (ret == -1);
e6af5a
71c99f ¤   return( ret );
11efe6 }
95af5a
71af5a
febeb7 static int
121dd2 add_addr( LDAP *ld, struct sockaddr *sap )
68bb36 {
7a1770 ····struct sockaddr¤*newsap, **addrs;
18af5a
08231c ····if (( newsap = (struct sockaddr *)malloc( sizeof( struct sockaddr )))
9c3c7b ¤   ····== NULL ) {
b12eef ¤   ld->ld_errno = LDAP_NO_MEMORY;
1a7360 ¤   return( -1 );
c16fe7 ····}
f9af5a
82e5b0 ····if ( ld->ld_sb.sb_naddr == 0 ) {
bec4ca ¤   addrs = (struct sockaddr **)malloc( sizeof(struct sockaddr *));
9e6a79 ····} else {
bbaff2 ¤   addrs = (struct sockaddr **)realloc( ld->ld_sb.sb_addrs,
4b6255 ¤   ¤   ( ld->ld_sb.sb_naddr + 1 ) * sizeof(struct sockaddr *));
9b6fe7 ····}
c9af5a
6380bb ····if ( addrs == NULL ) {
b73628 ¤   free( newsap );
6f2eef ¤   ld->ld_errno = LDAP_NO_MEMORY;
1d7360 ¤   return( -1 );
fd6fe7 ····}
ecaf5a
c0b78a ····SAFEMEMCPY( (char *)newsap, (char *)sap, sizeof( struct sockaddr ));
--e0c4 000f139ab8e40100094 Page 5 of cldap.c
6e1c4e ····addrs[ ld->ld_sb.sb_naddr++ ] = newsap;
d9fede ····ld->ld_sb.sb_addrs = (void **)addrs;
21a897 ····return( 0 );
f0efe6 }
aeaf5a
35af5a
fabeb7 static int
2b1d5a cldap_result( LDAP *ld, int msgid, LDAPMessage **res,
c5bbe6 ¤   struct cldap_retinfo *crip, char *base )
74bb36 {
461858 ····Sockbuf ¤   ¤   *sb = &ld->ld_sb;
3f678b ····BerElement¤ ¤   ber;
0c7219 ····char¤   ¤   *logdn;
60a492 ····int¤¤   ¤   ret, id, fromaddr, i;
c92d5c ····struct timeval¤ tv;
4aaf5a
bf53fb ····fromaddr = -1;
b6af5a
bc47de ····if ( crip->cri_try == 0 ) {
33437f ¤   crip->cri_maxtries = ld->ld_cldaptries * sb->sb_naddr;
ab098d ¤   crip->cri_timeout = ld->ld_cldaptimeout;
58c7ff ¤   crip->cri_useaddr = 0;
53423c ¤   Debug( LDAP_DEBUG_TRACE, "cldap_result tries %d timeout %d\n",
611f7c ¤   ¤   ld->ld_cldaptries, ld->ld_cldaptimeout, 0 );
b26fe7 ····}
96af5a
aee3d0 ····if ((tv.tv_sec = crip->cri_timeout / sb->sb_naddr) < 1 ) {
071f19 ¤   tv.tv_sec = 1;
506fe7 ····}
822a23 ····tv.tv_usec = 0;
5eaf5a
f9e612 ····Debug( LDAP_DEBUG_TRACE,
ab6fcd ¤   ····"cldap_result waiting up to %d seconds for a response\n",
8ce945 ¤   ····tv.tv_sec, 0, 0 );
cf0327 ····ber_init( &ber, 0 );
a7e0cd ····set_ber_options( ld, &ber );
37af5a
5fa172 ····if ( cldap_getmsg( ld, &tv, &ber ) == -1 ) {
3f7b8e ¤   ret = ld->ld_errno;
5cce5f ¤   Debug( LDAP_DEBUG_TRACE, "cldap_getmsg returned -1 (%d)\n",
858e32 ¤   ¤   ret, 0, 0 );
f037df ····} else if ( ld->ld_errno == LDAP_TIMEOUT ) {
934030 ¤   Debug( LDAP_DEBUG_TRACE,
5f5633 ¤   ····"cldap_result timed out\n", 0, 0, 0 );
f1d8af ¤   /*
c0dc18 ¤   ·* It timed out; is it time to give up?
eba4e3 ¤   ·*/
d69f6e ¤   if ( ++crip->cri_try >= crip->cri_maxtries ) {
d8e439 ¤   ····ret = LDAP_TIMEOUT;
c89b40 ¤   ····--crip->cri_try;
52f037 ¤   } else {
2efc54 ¤   ····if ( ++crip->cri_useaddr >= sb->sb_naddr ) {
c81b17 ¤   ¤   /*
c8e958 ¤   ¤   ·* new round: reset address to first one and
414793 ¤   ¤   ·* double the timeout
f59de3 ¤   ¤   ·*/
95d3d7 ¤   ¤   crip->cri_useaddr = 0;
998b0b ¤   ¤   crip->cri_timeout <<= 1;
c4f372 ¤   ····}
f4dcc3 ¤   ····ret = -1;
279371 ¤   }
6daf5a
3d6a79 ····} else {
34d8af ¤   /*
e6bfb6 ¤   ·* Got a response. ·It should look like:
ea6b57 ¤   ·* { msgid, logdn, { searchresponse...}}
daa4e3 ¤   ·*/
8f1b6e ¤   logdn = NULL;
8caf5a
dee891 ¤   if ( ber_scanf( &ber, "ia", &id, &logdn ) == LBER_ERROR ) {
adfc80 ¤   ····free( ber.ber_buf );¤   /* gack! */
f1930a ¤   ····ret = LDAP_DECODING_ERROR;
--3f8f 0009b3f0e0c40100094 Page 6 of cldap.c
2b5d44 ¤   ····Debug( LDAP_DEBUG_TRACE,
1c3cdc ¤   ¤   ····"cldap_result: ber_scanf returned LBER_ERROR (%d)\n",
d87d15 ¤   ¤   ····ret, 0, 0 );
4d2de1 ¤   } else if ( id != msgid ) {
f2fc80 ¤   ····free( ber.ber_buf );¤   /* gack! */
d85d44 ¤   ····Debug( LDAP_DEBUG_TRACE,
9d3473 ¤   ¤   ····"cldap_result: looking for msgid %d; got %d\n",
ba86a4 ¤   ¤   ····msgid, id, 0 );
d4d655 ¤   ····ret = -1;¤  /* ignore and keep looking */
d9f037 ¤   } else {
2cea54 ¤   ····/*
f017c6 ¤   ·····* got a result: determine which server it came from
0bab7c ¤   ·····* decode into ldap message chain
23ed8d ¤   ·····*/
5eed89 ¤   ····for ( fromaddr = 0; fromaddr < sb->sb_naddr; ++fromaddr ) {
b24aba ¤   ¤   ····if ( memcmp( &((struct sockaddr_in *)
7b680c ¤   ¤   ¤   ····sb->sb_addrs[ fromaddr ])->sin_addr,
09e2fa ¤   ¤   ¤   ····&((struct sockaddr_in *)sb->sb_fromaddr)->sin_addr,
f508b3 ¤   ¤   ¤   ····sizeof( struct in_addr )) == 0 ) {
15cdcb ¤   ¤   ¤   break;
f25f30 ¤   ¤   ····}
2cf372 ¤   ····}
852bf7 ¤   ····ret = cldap_parsemsg( ld, msgid, &ber, res, base );
e4fc80 ¤   ····free( ber.ber_buf );¤   /* gack! */
e15d44 ¤   ····Debug( LDAP_DEBUG_TRACE,
c06ac9 ¤   ¤   "cldap_result got result (%d)\n", ret, 0, 0 );
8e9371 ¤   }
8daf5a
18fa79 ¤   if ( logdn != NULL ) {
8d5bfa ¤   ¤   free( logdn );
cf9371 ¤   }
766fe7 ····}
28af5a
d1af5a
bc29ec ····/*
1fbcb2 ·····* If we are giving up (successfully or otherwise) then
c521b8 ·····* abandon any outstanding requests.
0bd48d ·····*/
a2ea9f ····if ( ret != -1 ) {
6fedb6 ¤   i = crip->cri_try;
a6374a ¤   if ( i >= sb->sb_naddr ) {
288112 ¤   ····i = sb->sb_naddr - 1;
a69371 ¤   }
5daf5a
703a07 ¤   for ( ; i >= 0; --i ) {
6e91a0 ¤   ····if ( i == fromaddr ) {
2e2d6f ¤   ¤   continue;
25f372 ¤   ····}
2308aa ¤   ····sb->sb_useaddr = sb->sb_addrs[ i ];
99b859 ¤   ····Debug( LDAP_DEBUG_TRACE, "cldap_result abandoning id %d (to %s)\n",
f8821e ¤   ¤   msgid, inet_ntoa( ((struct sockaddr_in *)
01b394 ¤   ¤   sb->sb_useaddr)->sin_addr ), 0 );
fbc072 ¤   ····(void) ldap_abandon( ld, msgid );
0c9371 ¤   }
ca6fe7 ····}
e6af5a
1a994c ····return( ld->ld_errno = ret );
43efe6 }
5baf5a
e3af5a
fabeb7 static int
8c5748 cldap_parsemsg( LDAP *ld, int msgid, BerElement *ber,
38443a ¤   LDAPMessage **res, char *base )
14bb36 {
6fed9a ····unsigned long¤  tag, len;
8b270d ····int¤¤   ¤   baselen, slen, rc;
df504e ····char¤   ¤   *dn, *p, *cookie;
6e003b ····LDAPMessage¤¤   *chain, *prev, *ldm;
ad44f7 ····struct berval¤  *bv;
3aaf5a
680633 ····rc = LDAP_DECODING_ERROR;¤  /* pessimistic */
9b1fdb ····ldm = chain = prev = NULLMSG;
--bd1c 000861dec7940100094 Page 7 of cldap.c
067293 ····baselen = ( base == NULL ) ? 0 : strlen( base );
d7b150 ····bv = NULL;
3eaf5a
85b568 ····for ( tag = ber_first_element( ber, &len, &cookie );
f9b882 ¤   ····tag != LBER_DEFAULT && rc != LDAP_SUCCESS;
09e8a9 ¤   ····tag = ber_next_element( ber, &len, cookie )) {
e15e6e ¤   if (( ldm = (LDAPMessage *)calloc( 1, sizeof(LDAPMessage)))
d97c56 ¤   ¤   == NULL || ( ldm->lm_ber = alloc_ber_with_options( ld ))
66df89 ¤   ¤   == NULLBER ) {
206159 ¤   ····rc = LDAP_NO_MEMORY;
2cb60f ¤   ····break;¤ /* return w/error*/
919371 ¤   }
275a3f ¤   ldm->lm_msgid = msgid;
2f7bf4 ¤   ldm->lm_msgtype = tag;
efaf5a
8aede6 ¤   if ( tag == LDAP_RES_SEARCH_RESULT ) {
c1f81a ¤   ····Debug( LDAP_DEBUG_TRACE, "cldap_parsemsg got search result\n",
95cda5 ¤   ¤   ····0, 0, 0 );
67af5a
9ff41e ¤   ····if ( ber_get_stringal( ber, &bv ) == LBER_DEFAULT ) {
8380a8 ¤   ¤   break;¤ /* return w/error */
c5f372 ¤   ····}
b2af5a
bc61c5 ¤   ····if ( ber_printf( ldm->lm_ber, "to", tag, bv->bv_val,
d8eee8 ¤   ¤   ····bv->bv_len ) == -1 ) {
7180a8 ¤   ¤   break;¤ /* return w/error */
2af372 ¤   ····}
62884f ¤   ····ber_bvfree( bv );
ab53f3 ¤   ····bv = NULL;
21093c ¤   ····rc = LDAP_SUCCESS;
03af5a
c4ba95 ¤   } else if ( tag == LDAP_RES_SEARCH_ENTRY ) {
21d82a ¤   ····if ( ber_scanf( ber, "{aO", &dn, &bv ) == LBER_ERROR ) {
7780a8 ¤   ¤   break;¤ /* return w/error */
d3f372 ¤   ····}
68a983 ¤   ····Debug( LDAP_DEBUG_TRACE, "cldap_parsemsg entry %s\n", dn, 0, 0 );
8fe469 ¤   ····if ( dn != NULL && *(dn + ( slen = strlen(dn)) - 1) == '*' &&
091e0c ¤   ¤   ····baselen > 0 ) {
181b17 ¤   ¤   /*
278102 ¤   ¤   ·* substitute original searchbase for trailing '*'
1b9de3 ¤   ¤   ·*/
fb1881 ¤   ¤   if (( p = (char *)malloc( slen + baselen )) == NULL ) {
e0da0f ¤   ¤   ····rc = LDAP_NO_MEMORY;
7fcb4a ¤   ¤   ····free( dn );
0cea6e ¤   ¤   ····break;¤ /* return w/error */
6c0fe4 ¤   ¤   }
d70dda ¤   ¤   strcpy( p, dn );
ee76b5 ¤   ¤   strcpy( p + slen - 1, base );
df43fe ¤   ¤   free( dn );
6d1bd5 ¤   ¤   dn = p;
98f372 ¤   ····}
b3af5a
4c2ed2 ¤   ····if ( ber_printf( ldm->lm_ber, "t{so}", tag, dn, bv->bv_val,
95eee8 ¤   ¤   ····bv->bv_len ) == -1 ) {
c480a8 ¤   ¤   break;¤ /* return w/error */
54f372 ¤   ····}
08b1be ¤   ····free( dn );
e8884f ¤   ····ber_bvfree( bv );
3c53f3 ¤   ····bv = NULL;
a91b52 ¤   ¤
11f037 ¤   } else {
cb7c6a ¤   ····Debug( LDAP_DEBUG_TRACE, "cldap_parsemsg got unknown tag %d\n",
3dea7b ¤   ¤   ····tag, 0, 0 );
d5d900 ¤   ····rc = LDAP_PROTOCOL_ERROR;
eeef83 ¤   ····break;¤ /* return w/error */
a79371 ¤   }
9faf5a
d791a9 ¤   /* Reset message ber so we can read from it later. ·Gack! */
8a97aa ¤   ldm->lm_ber->ber_end = ldm->lm_ber->ber_ptr;
55807d ¤   ldm->lm_ber->ber_ptr = ldm->lm_ber->ber_buf;
9caf5a
862639 #ifdef LDAP_DEBUG
--0260 001572c463f40100094 Page 8 of cldap.c
74925b ¤   if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
071db3 ¤   ····fprintf( stderr, "cldap_parsemsg add message id %d type %d:\n",
0c201a ¤   ¤   ····ldm->lm_msgid, ldm->lm_msgtype ·);
b24416 ¤   ····ber_dump( ldm->lm_ber, 1 );
509371 ¤   }
3d9b45 #endif /* LDAP_DEBUG */
b4af5a
d223e9 #ifndef NO_CACHE
dc2fe8 ¤   ····if ( ld->ld_cache != NULL ) {
b78a73 ¤   ¤   add_result_to_cache( ld, ldm );
bff372 ¤   ····}
ab1992 #endif /* NO_CACHE */
44af5a
ed987c ¤   if ( chain == NULL ) {
69e1fb ¤   ····chain = ldm;
bbf037 ¤   } else {
749513 ¤   ····prev->lm_chain = ldm;
d49371 ¤   }
2c5c88 ¤   prev = ldm;
1464d0 ¤   ldm = NULL;
df6fe7 ····}
3daf5a
c2adf1 ····/* dispose of any leftovers */
bbb316 ····if ( ldm != NULL ) {
763e00 ¤   if ( ldm->lm_ber != NULLBER ) {
6eb140 ¤   ····ber_free( ldm->lm_ber, 1 );
9f9371 ¤   }
4bdce3 ¤   free( ldm );
b76fe7 ····}
98278b ····if ( bv != NULL ) {
f0c405 ¤   ber_bvfree( bv );
7f6fe7 ····}
4daf5a
57017a ····/* return chain, calling result2error if we got anything at all */
4cecf9 ····*res = chain;
6ab684 ····return(( *res == NULLMSG ) ? rc : ldap_result2error( ld, *res, 0 ));
53efe6 }
576b1c #endif /* CLDAP */
--0809 000991535b740100095 Page 1 of compare.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
4d6e71 ·* ·compare.c
76495d ·*/
a5af5a
490c68 #ifndef lint·
b807d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
d13efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
e67454 #endif
00af5a
3efeb2 #include <stdio.h>
38324c #include <string.h>
0faf5a
3d24c3 #if PGPSOCKETSLDAP¤ /* jason */
6a65aa #include "pgpSocketsLDAP.h"
c3af5a
d7db21 #else
c5c583 #ifdef MACOS
d165e0 #include "macos.h"
8fe962 #endif /* MACOS */
ddaf5a
e31330 #if !defined( MACOS ) && !defined( DOS )
c3f15e #include <sys/types.h>
17a394 #ifndef WIN32¤  ¤   /* marcd */
6366f2 #include <sys/socket.h>
bc7454 #endif
e37454 #endif
e6df0f #endif /* PGPSOCKETSLDAP */
5caf5a
38b779 #include "lber.h"
f2e990 #include "ldap.h"
55745c #include "ldap-int.h"
91af5a
b538e5 /*
d2db05 ·* ldap_compare - perform an ldap (and X.500) compare operation. ·The dn
bb3dfe ·* of the entry to compare to and the attribute and value to compare (in
c89ead ·* attr and value) are supplied. ·The msgid of the response is returned.
19775e ·*
3c305c ·* Example:
656fa9 ·*¤ ldap_compare( ld, "c=us@cn=bob", "userPassword", "secret" )
98495d ·*/
bc4d2f int
ce22a8 ldap_compare( LDAP *ld, char *dn, char *attr, char *value )
c9bb36 {
429c95 ¤   BerElement¤ *ber;
fbaf5a
5fc5cc ¤   /* The compare request looks like this:
8d8666 ¤   ·*¤ CompareRequest ::= SEQUENCE {
db2c25 ¤   ·*¤ ¤   entry¤  DistinguishedName,
336e81 ¤   ·*¤ ¤   ava¤SEQUENCE {
bbcca4 ¤   ·*¤ ¤   ¤   type¤   AttributeType,
dfaf80 ¤   ·*¤ ¤   ¤   value¤  AttributeValue
c53c91 ¤   ·*¤ ¤   }
585203 ¤   ·*¤ }
1193a1 ¤   ·* and must be wrapped in an LDAPMessage.
9ba4e3 ¤   ·*/
37af5a
70b1a3 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_compare\n", 0, 0, 0 );
5aaf5a
e947d1 ¤   /* create a message to send */
2c6826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
4d49fa ¤   ¤   return( -1 );
249371 ¤   }
3eaf5a
400fa9 ¤   if ( ber_printf( ber, "{it{s{ss}}}", ++ld->ld_msgid, LDAP_REQ_COMPARE,
728eb2 ¤   ····dn, attr, value ) == -1 ) {
a73614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
4a1ab1 ¤   ¤   ber_free( ber, 1 );
6149fa ¤   ¤   return( -1 );
999371 ¤   }
--817b 0013c5a02e840100095 Page 2 of compare.c
e0af5a
6023e9 #ifndef NO_CACHE
695f25 ¤   if ( ld->ld_cache != NULL ) {
32c151 ¤   ¤   if ( check_cache( ld, LDAP_REQ_COMPARE, ber ) == 0 ) {
a5b7ef ¤   ¤   ¤   ber_free( ber, 1 );
cb41a5 ¤   ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
c1b4ad ¤   ¤   ¤   return( ld->ld_msgid );
8c0fe4 ¤   ¤   }
f11b5b ¤   ¤   add_request_to_cache( ld, LDAP_REQ_COMPARE, ber );
049371 ¤   }
4d1992 #endif /* NO_CACHE */
38af5a
f5dd1f ¤   /* send the message */
11e3d0 ¤   return ( send_initial_request( ld, LDAP_REQ_COMPARE, dn, ber ));
79efe6 }
0aaf5a
fd4d2f int
0114d7 ldap_compare_s( LDAP *ld, char *dn, char *attr, char *value )
75bb36 {
06da47 ¤   int¤¤   msgid;
8d3932 ¤   LDAPMessage¤*res;
62af5a
90a29f ¤   if ( (msgid = ldap_compare( ld, dn, attr, value )) == -1 )
b8df73 ¤   ¤   return( ld->ld_errno );
4daf5a
c319a3 ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
96df73 ¤   ¤   return( ld->ld_errno );
36af5a
559595 ¤   return( ldap_result2error( ld, res, 1 ) );
3cefe6 }
--be27 00063545ba840100096 Page 1 of delete.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
3738f9 ·* ·delete.c
1b495d ·*/
53af5a
770c68 #ifndef lint·
2c07d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
583efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
197454 #endif
4caf5a
b0feb2 #include <stdio.h>
e6324c #include <string.h>
f1af5a
8a24c3 #if PGPSOCKETSLDAP¤ /* jason */
1e65aa #include "pgpSocketsLDAP.h"
d1af5a
e3db21 #else
00c583 #ifdef MACOS
4265e0 #include "macos.h"
1fe962 #endif /* MACOS */
fdaf5a
1a1157 #if defined( DOS )
2af2ef #include "msdos.h"
f8bc39 #endif /* DOS */
36af5a
e01330 #if !defined( MACOS ) && !defined( DOS )
84f15e #include <sys/types.h>
cca394 #ifndef WIN32¤  ¤   /* marcd */
4566f2 #include <sys/socket.h>
747454 #endif
c27454 #endif
41df0f #endif /* PGPSOCKETSLDAP */
2aaf5a
ffb779 #include "lber.h"
99e990 #include "ldap.h"
5c745c #include "ldap-int.h"
8aaf5a
fa38e5 /*
0c58c6 ·* ldap_delete - initiate an ldap (and X.500) delete operation. Parameters:
21775e ·*
db4f03 ·*¤ ld¤ ¤   LDAP descriptor
709fdc ·*¤ dn¤ ¤   DN of the object to delete
29775e ·*
21305c ·* Example:
bc01b7 ·*¤ msgid = ldap_delete( ld, dn );
8f495d ·*/
bb4d2f int
b97c9c ldap_delete( LDAP *ld, char *dn )
74bb36 {
199c95 ¤   BerElement¤ *ber;
b1af5a
a7d8af ¤   /*
e3d3ed ¤   ·* A delete request looks like this:
a15fe1 ¤   ·*¤ DelRequet ::= DistinguishedName,
a2a4e3 ¤   ·*/
20af5a
2a61f7 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_delete\n", 0, 0, 0 );
ddaf5a
4647d1 ¤   /* create a message to send */
e36826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
ed49fa ¤   ¤   return( -1 );
ea9371 ¤   }
14af5a
e8021f ¤   if ( ber_printf( ber, "{its}", ++ld->ld_msgid, LDAP_REQ_DELETE, dn )
8d9a76 ¤   ····== -1 ) {
543614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
861ab1 ¤   ¤   ber_free( ber, 1 );
8e49fa ¤   ¤   return( -1 );
529371 ¤   }
63af5a
--1e01 0015a91793440100096 Page 2 of delete.c
d3dd1f ¤   /* send the message */
623809 ¤   return ( send_initial_request( ld, LDAP_REQ_DELETE, dn, ber ));
4eefe6 }
7eaf5a
1caf5a
ca4d2f int
eb1e2d ldap_delete_s( LDAP *ld, char *dn )
69bb36 {
68da47 ¤   int¤¤   msgid;
c63932 ¤   LDAPMessage¤*res;
1daf5a
ce0f61 ¤   if ( (msgid = ldap_delete( ld, dn )) == -1 )
85df73 ¤   ¤   return( ld->ld_errno );
76af5a
9119a3 ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
40df73 ¤   ¤   return( ld->ld_errno );
ebaf5a
c29595 ¤   return( ldap_result2error( ld, res, 1 ) );
5aefe6 }
--11d5 000df75fdb640100097 Page 1 of disptmpl.c
bc38e5 /*
09515b ·* Copyright (c) 1993, 1994 Regents of the University of Michigan.
60599a ·* All rights reserved.
44775e ·*
22b855 ·* Redistribution and use in source and binary forms are permitted
ec9795 ·* provided that this notice is preserved and that due credit is given
bf1873 ·* to the University of Michigan at Ann Arbor. The name of the University
148805 ·* may not be used to endorse or promote products derived from this
b974fe ·* software without specific prior written permission. This software
1a2a32 ·* is provided ``as is'' without express or implied warranty.
a0775e ·*
1b5e00 ·* disptmpl.c: ·display template library routines for LDAP clients
9dddde ·* 7 March 1994 by Mark C Smith
5f495d ·*/
11af5a
76feb2 #include <stdio.h>
99b1cb #include <ctype.h>
94324c #include <string.h>
a5bea3 #include <stdlib.h>
7cc583 #ifdef MACOS
c565e0 #include "macos.h"
9c6c94 #else /* MACOS */
cad581 #if defined(DOS) || defined(WIN32)¤ ¤   /* marcd */
8a5e84 #include <malloc.h>
1001b0 #ifdef DOS
67f2ef #include "msdos.h"
807454 #endif
5aaad8 #else /* DOS */
bdf15e #include <sys/types.h>
7a09b0 #include <sys/file.h>
eeea1a #ifndef VMS
0717c2 #include <unistd.h>
75361d #endif /* VMS */
f7bc39 #endif /* DOS */
aae962 #endif /* MACOS */
42af5a
3fb779 #include "lber.h"
19e990 #include "ldap.h"
912b4c #include "disptmpl.h"
96af5a
83719a #ifndef NEEDPROTOS
3f22a2 static void free_disptmpl();
9cbd66 static int read_next_tmpl();
da9e1d int next_line_tokens();
1640f5 void free_strarray();
8d4b51 #else /* !NEEDPROTOS */
2b298a static void free_disptmpl( struct ldap_disptmpl *tmpl );
b70d77 static int read_next_tmpl( char **bufp, long *blenp,
4030c9 ¤   struct ldap_disptmpl **tmplp, int dtversion );
ddec27 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
49d559 void free_strarray( char **sap );
7e3f09 #endif /* !NEEDPROTOS */
8daf5a
98f368 static char¤¤   *tmploptions[] = {
f55434 ····"addable", "modrdn",
182306 ····"altview",
532e82 ····NULL
9782f7 };
7faf5a
93af5a
3b74e9 static unsigned long¤   tmploptvals[] = {
2ad79d ····LDAP_DTMPL_OPT_ADDABLE, LDAP_DTMPL_OPT_ALLOWMODRDN,
fdfebb ····LDAP_DTMPL_OPT_ALTVIEW,
da82f7 };
4aaf5a
c7af5a
d12477 static char¤¤   *itemtypes[] = {
3dd4d1 ····"cis",¤ ¤   ¤   "mls",¤ ¤   ¤   "dn",
b6d075 ····"bool",¤¤   ¤   "jpeg",¤¤   ¤   "jpegbtn",
d481e0 ····"fax",¤ ¤   ¤   "faxbtn",¤  ¤   "audiobtn",
2285a6 ····"time",¤¤   ¤   "date",¤¤   ¤   "url",
df3a18 ····"searchact",¤   ¤   "linkact",¤ ¤   "adddnact",
--2cf6 000b845962940100097 Page 2 of disptmpl.c
d65adc ····"addact",¤  ¤   ¤   "verifyact",¤   ¤   "mail",
9b2e82 ····NULL
0c82f7 };
34af5a
0589c5 static unsigned long¤   itemsynids[] = {
23e737 ····LDAP_SYN_CASEIGNORESTR,¤LDAP_SYN_MULTILINESTR,¤ LDAP_SYN_DN,
ff15eb ····LDAP_SYN_BOOLEAN,¤  ¤   LDAP_SYN_JPEGIMAGE,¤LDAP_SYN_JPEGBUTTON,
9d5d63 ····LDAP_SYN_FAXIMAGE,¤ ¤   LDAP_SYN_FAXBUTTON,¤LDAP_SYN_AUDIOBUTTON,
993e1b ····LDAP_SYN_TIME,¤ ¤   LDAP_SYN_DATE,¤ ¤   LDAP_SYN_LABELEDURL,
01dd5e ····LDAP_SYN_SEARCHACTION,¤ LDAP_SYN_LINKACTION,¤   LDAP_SYN_ADDDNACTION,
cc9123 ····LDAP_SYN_ADDDNACTION,¤  LDAP_SYN_VERIFYDNACTION,LDAP_SYN_RFC822ADDR,
d482f7 };
5daf5a
5baf5a
162ea6 static char¤¤   *itemoptions[] = {
d85ef3 ····"ro",¤  ¤   ·······¤¤   "sort",
0d5d4c ····"1val",¤¤   ¤   ¤   "hide",
2c7c8e ····"required",¤¤   ¤   ¤   "hideiffalse",
902e82 ····NULL
d882f7 };
82af5a
e9af5a
55a927 static unsigned long¤   itemoptvals[] = {
761143 ····LDAP_DITEM_OPT_READONLY,¤   ¤   LDAP_DITEM_OPT_SORTVALUES,
6e7655 ····LDAP_DITEM_OPT_SINGLEVALUED,¤   LDAP_DITEM_OPT_HIDEIFEMPTY,
3caf22 ····LDAP_DITEM_OPT_VALUEREQUIRED,¤  LDAP_DITEM_OPT_HIDEIFFALSE,
a582f7 };
b6af5a
f3af5a
7bc9f9 #define ADDEF_CONSTANT¤ "constant"
fe1e96 #define ADDEF_ADDERSDN¤ "addersdn"
e8af5a
faaf5a
384d2f int
8a75b7 ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp )
54bb36 {
166cec ····FILE¤   *fp;
171842 ····char¤   *buf;
4ee29b ····long¤   rlen, len;
45a824 ····int¤¤   rc, eof;
27af5a
feec7a ····*tmpllistp = NULLDISPTMPL;
9caf5a
ba4bfd ····if (( fp = fopen( file, "r" )) == NULL ) {
772cfb ¤   return( LDAP_TMPL_ERR_FILE );
0b6fe7 ····}
8baf5a
cfba4a ····if ( fseek( fp, 0L, SEEK_END ) != 0 ) {¤/* move to end to get len */
ba5261 ¤   fclose( fp );
6c2cfb ¤   return( LDAP_TMPL_ERR_FILE );
586fe7 ····}
bcaf5a
6a7c74 ····len = ftell( fp );
e0af5a
1f8486 ····if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {¤/* back to start of file */
085261 ¤   fclose( fp );
de2cfb ¤   return( LDAP_TMPL_ERR_FILE );
316fe7 ····}
8aaf5a
13d046 ····if (( buf = malloc( (size_t)len )) == NULL ) {
9f5261 ¤   fclose( fp );
ec3043 ¤   return( LDAP_TMPL_ERR_MEM );
a96fe7 ····}
3caf5a
60d0ba ····rlen = fread( buf, 1, (size_t)len, fp );
757a1f ····eof = feof( fp );
54c09a ····fclose( fp );
c4af5a
6570f9 ····if ( rlen != len && !eof ) {¤   /* error: ·didn't get the whole file */
a25bb5 ¤   free( buf );
eb2cfb ¤   return( LDAP_TMPL_ERR_FILE );
b86fe7 ····}
--c714 000eb63654140100097 Page 3 of disptmpl.c
e0af5a
ca7db4 ····rc = ldap_init_templates_buf( buf, rlen, tmpllistp );
d21943 ····free( buf );
4eaf5a
54ff99 ····return( rc );
eeefe6 }
18af5a
baaf5a
254d2f int
61fd68 ldap_init_templates_buf( char *buf, long buflen,
5c3867 ¤   struct ldap_disptmpl **tmpllistp )
b6bb36 {
72b6b5 ····int¤¤   ¤   ¤   rc, version;
37feb1 ····char¤   ¤   ¤   **toks;
23f9e8 ····struct ldap_disptmpl¤   *prevtmpl, *tmpl;
14af5a
f099ad ····*tmpllistp = prevtmpl = NULLDISPTMPL;
3caf5a
09f06e ····if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
96904c ¤   ····strcasecmp( toks[ 0 ], "version" ) != 0 ) {
b9b597 ¤   free_strarray( toks );
696c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
976fe7 ····}
48b741 ····version = atoi( toks[ 1 ] );
f0adb6 ····free_strarray( toks );
c13466 ····if ( version != LDAP_TEMPLATE_VERSION ) {
1a9da1 ¤   return( LDAP_TMPL_ERR_VERSION );
2e6fe7 ····}
f0af5a
6ced47 ····while ( buflen > 0 && ( rc = read_next_tmpl( &buf, &buflen, &tmpl,
011f6c ¤   ····version )) == 0 && tmpl != NULLDISPTMPL ) {
1db68a ¤   if ( prevtmpl == NULLDISPTMPL ) {
c5a8c5 ¤   ····*tmpllistp = tmpl;
29f037 ¤   } else {
7c32e4 ¤   ····prevtmpl->dt_next = tmpl;
d79371 ¤   }
f24141 ¤   prevtmpl = tmpl;
116fe7 ····}
39af5a
94ce64 ····if ( rc != 0 ) {
2e8f31 ¤   ldap_free_templates( *tmpllistp );
206fe7 ····}
f3af5a
d9ff99 ····return( rc );
c9efe6 }
d9da86 ¤   ····
5caf5a
f6af5a
e2314a void
5fdd14 ldap_free_templates( struct ldap_disptmpl *tmpllist )
10bb36 {
9f5b7e ····struct ldap_disptmpl¤   *tp, *nexttp;
adaf5a
1781f7 ····if ( tmpllist != NULL ) {
d59862 ¤   for ( tp = tmpllist; tp != NULL; tp = nexttp ) {
eb313d ¤   ····nexttp = tp->dt_next;
f0e36e ¤   ····free_disptmpl( tp );
db9371 ¤   }
c56fe7 ····}
4befe6 }
baaf5a
5eaf5a
372978 static void
6ca71e free_disptmpl( struct ldap_disptmpl *tmpl )
39bb36 {
e5196b ····if ( tmpl != NULL ) {
1aa546 ¤   if ( tmpl->dt_name != NULL ) {
1d8225 ¤   ····free( ·tmpl->dt_name );
1f9371 ¤   }
02af5a
551cd9 ¤   if ( tmpl->dt_pluralname != NULL ) {
ebc883 ¤   ····free( tmpl->dt_pluralname );
--e28b 000860a89b240100097 Page 4 of disptmpl.c
a19371 ¤   }
93af5a
40db1b ¤   if ( tmpl->dt_iconname != NULL ) {
9ed33d ¤   ····free( tmpl->dt_iconname );
3f9371 ¤   }
96af5a
a81d4a ¤   if ( tmpl->dt_authattrname != NULL ) {
200b84 ¤   ····free( tmpl->dt_authattrname );
9e9371 ¤   }
e1af5a
f74f96 ¤   if ( tmpl->dt_defrdnattrname != NULL ) {
b7a537 ¤   ····free( tmpl->dt_defrdnattrname );
2e9371 ¤   }
44af5a
bf0e4c ¤   if ( tmpl->dt_defaddlocation != NULL ) {
7693c5 ¤   ····free( tmpl->dt_defaddlocation );
c29371 ¤   }
b6af5a
5131e2 ¤   if ( ·tmpl->dt_oclist != NULL ) {
f61861 ¤   ····struct ldap_oclist¤ *ocp, *nextocp;
2daf5a
0e9b54 ¤   ····for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = nextocp ) {
c371b6 ¤   ¤   nextocp = ocp->oc_next;
6697f9 ¤   ¤   free_strarray( ocp->oc_objclasses );
4be1e3 ¤   ¤   free( ocp );
16f372 ¤   ····}
af9371 ¤   }
9eaf5a
08576c ¤   if ( ·tmpl->dt_adddeflist != NULL ) {
931443 ¤   ····struct ldap_adddeflist¤ *adp, *nextadp;
92af5a
0892b5 ¤   ····for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = nextadp ) {
b536ec ¤   ¤   nextadp = adp->ad_next;
a8dead ¤   ¤   if( adp->ad_attrname != NULL ) {
777eb1 ¤   ¤   ····free( adp->ad_attrname );
3a0fe4 ¤   ¤   }
577fc4 ¤   ¤   if( adp->ad_value != NULL ) {
3ae1ba ¤   ¤   ····free( adp->ad_value );
1e0fe4 ¤   ¤   }
c27b13 ¤   ¤   free( adp );
b1f372 ¤   ····}
1e9371 ¤   }
45af5a
e3d735 ¤   if ( ·tmpl->dt_items != NULL ) {
2bf4f8 ¤   ····struct ldap_tmplitem¤   *rowp, *nextrowp, *colp, *nextcolp;
68af5a
ce135f ¤   ····for ( rowp = tmpl->dt_items; rowp != NULL; rowp = nextrowp ) {
0c1d11 ¤   ¤   nextrowp = rowp->ti_next_in_col;
d6a46e ¤   ¤   for ( colp = rowp; colp != NULL; colp = nextcolp ) {
0c3044 ¤   ¤   ····nextcolp = colp->ti_next_in_row;
703528 ¤   ¤   ····if ( colp->ti_attrname != NULL ) {
cccab2 ¤   ¤   ¤   free( colp->ti_attrname );
725f30 ¤   ¤   ····}
fbf861 ¤   ¤   ····if ( colp->ti_label != NULL ) {
6ecbb6 ¤   ¤   ¤   free( colp->ti_label );
2f5f30 ¤   ¤   ····}
a088a8 ¤   ¤   ····if ( colp->ti_args != NULL ) {
8a519c ¤   ¤   ¤   free_strarray( colp->ti_args );
a65f30 ¤   ¤   ····}
a8c58a ¤   ¤   ····free( colp );
0c0fe4 ¤   ¤   }
6bf372 ¤   ····}
799371 ¤   }
d1af5a
82eaa7 ¤   free( tmpl );
bc6fe7 ····}
deefe6 }
4caf5a
8aaf5a
01aa4f struct ldap_disptmpl *
8d4049 ldap_first_disptmpl( struct ldap_disptmpl *tmpllist )
86bb36 {
--d079 000f014839d40100097 Page 5 of disptmpl.c
147cac ····return( tmpllist );
07efe6 }
c0af5a
63af5a
5aaa4f struct ldap_disptmpl *
5e0811 ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
a84408 ¤   struct ldap_disptmpl *tmpl )
0ebb36 {
638822 ····return( tmpl == NULLDISPTMPL ? tmpl : tmpl->dt_next );
00efe6 }
f7af5a
e3af5a
b8aa4f struct ldap_disptmpl *
5427ac ldap_name2template( char *name, struct ldap_disptmpl *tmpllist )
39bb36 {
eaaf9e ····struct ldap_disptmpl¤   *dtp;
51af5a
9e98bb ····for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
d5942f ¤   ····dtp = ldap_next_disptmpl( tmpllist, dtp )) {
5fe9f6 ¤   if ( strcasecmp( name, dtp->dt_name ) == 0 ) {
1c3d37 ¤   ····return( dtp );
789371 ¤   }
066fe7 ····}
12af5a
2a95b0 ····return( NULLDISPTMPL );
d7efe6 }
53af5a
6daf5a
0aaa4f struct ldap_disptmpl *
643342 ldap_oc2template( char **oclist, struct ldap_disptmpl *tmpllist )
eabb36 {
0eaf9e ····struct ldap_disptmpl¤   *dtp;
f52fce ····struct ldap_oclist¤ ¤   *oclp;
dedde1 ····int¤¤   ¤   ¤   i, j, needcnt, matchcnt;
29af5a
2cacbe ····if ( tmpllist == NULL || oclist == NULL || oclist[ 0 ] == NULL ) {
95a523 ¤   return( NULLDISPTMPL );
5c6fe7 ····}
a6af5a
9798bb ····for ( dtp = ldap_first_disptmpl( tmpllist ); dtp != NULLDISPTMPL;
5f6215 ¤   ¤   dtp = ldap_next_disptmpl( tmpllist, dtp )) {
9671fd ¤   for ( oclp = dtp->dt_oclist; oclp != NULLOCLIST;
a07d88 ¤   ¤   oclp = oclp->oc_next ) {
ac068b ¤   ····needcnt = matchcnt = 0;
51a682 ¤   ····for ( i = 0; oclp->oc_objclasses[ i ] != NULL; ++i ) {
eaeae5 ¤   ¤   for ( j = 0; oclist[ j ] != NULL; ++j ) {
2146f2 ¤   ¤   ····if ( strcasecmp( oclist[ j ], oclp->oc_objclasses[ i ] )
dd8769 ¤   ¤   ¤   ····== 0 ) {
020478 ¤   ¤   ¤   ++matchcnt;
915f30 ¤   ¤   ····}
3b0fe4 ¤   ¤   }
9c4a9b ¤   ¤   ++needcnt;
b8f372 ¤   ····}
faaf5a
5418ac ¤   ····if ( matchcnt == needcnt ) {
d174f9 ¤   ¤   return( dtp );
0cf372 ¤   ····}
379371 ¤   }
456fe7 ····}
85af5a
b395b0 ····return( NULLDISPTMPL );
f8efe6 }
09af5a
b1af5a
06af61 struct ldap_tmplitem *
c0646b ldap_first_tmplrow( struct ldap_disptmpl *tmpl )
5dbb36 {
710294 ····return( tmpl->dt_items );
25efe6 }
0aaf5a
deaf5a
f0af61 struct ldap_tmplitem *
--4719 0000c30563a40100097 Page 6 of disptmpl.c
519f51 ldap_next_tmplrow( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
40bb36 {
d61583 ····return( row == NULLTMPLITEM ? row : row->ti_next_in_col );
dfefe6 }
10af5a
61af5a
b2af61 struct ldap_tmplitem *
afb201 ldap_first_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row )
03bb36 {
e8b493 ····return( row );
4aefe6 }
25af5a
40af5a
8caf61 struct ldap_tmplitem *
0033ca ldap_next_tmplcol( struct ldap_disptmpl *tmpl, struct ldap_tmplitem *row,
a8287a ¤   struct ldap_tmplitem *col )
7dbb36 {
b73183 ····return( col == NULLTMPLITEM ? col : col->ti_next_in_row );
deefe6 }
32af5a
6aaf5a
d62d52 char **
996a1e ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
085c36 ¤   int exclude, unsigned long syntaxmask )
5bbb36 {
3538e5 /*
4f0abc ·* this routine should filter out duplicate attributes...
fe495d ·*/
1f6dec ····struct ldap_tmplitem¤   *tirowp, *ticolp;
02c370 ····int¤¤   ¤   i, attrcnt, memerr;
5e1ddf ····char¤   ¤   **attrs;
00af5a
e3bc0b ····attrcnt = 0;
292d33 ····memerr = 0;
57af5a
e18f51 ····if (( attrs = (char **)malloc( sizeof( char * ))) == NULL ) {
8e9572 ¤   return( NULL );
d36fe7 ····}
5caf5a
0ae292 ····if ( includeattrs != NULL ) {
8e7227 ¤   for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) {
a012cd ¤   ····if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
919240 ¤   ¤   ····sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
d6f13d ¤   ¤   ····strdup( includeattrs[ i ] )) == NULL ) {
5e12dc ¤   ¤   memerr = 1;
7edfe8 ¤   ····} else {
e57b17 ¤   ¤   attrs[ attrcnt ] = NULL;
68f372 ¤   ····}
d89371 ¤   }
5f6fe7 ····}
0baf5a
722824 ····for ( tirowp = ldap_first_tmplrow( tmpl );
819dba ¤   ····!memerr && tirowp != NULLTMPLITEM;
446bdf ¤   ····tirowp = ldap_next_tmplrow( tmpl, tirowp )) {
e4cc57 ¤   for ( ticolp = ldap_first_tmplcol( tmpl, tirowp );
b6b7d8 ¤   ¤   ticolp != NULLTMPLITEM;
caca15 ¤   ¤   ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) {
50af5a
3724bd ¤   ····if ( syntaxmask != 0 ) {
15399b ¤   ¤   if (( exclude &&
e1a920 ¤   ¤   ¤   ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) ||
7117de ¤   ¤   ¤   ( !exclude &&
fa30ec ¤   ¤   ¤   ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) {
96bc15 ¤   ¤   ····continue;
be0fe4 ¤   ¤   }
18f372 ¤   ····}
1faf5a
756548 ¤   ····if ( ticolp->ti_attrname != NULL ) {
fd1d54 ¤   ¤   if (( attrs = (char **)realloc( attrs, ( attrcnt + 2 ) *
7b9687 ¤   ¤   ¤   sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] =
f6efe4 ¤   ¤   ¤   strdup( ticolp->ti_attrname )) == NULL ) {
0c9a68 ¤   ¤   ····memerr = 1;
--62b0 0009a09b38640100097 Page 7 of disptmpl.c
4f45a6 ¤   ¤   } else {
4ce05d ¤   ¤   ····attrs[ attrcnt ] = NULL;
6f0fe4 ¤   ¤   }
4cf372 ¤   ····}
c69371 ¤   }
8d6fe7 ····}
58af5a
554c21 ····if ( memerr || attrcnt == 0 ) {
c06c3c ¤   for ( i = 0; i < attrcnt; ++i ) {
fd8929 ¤   ····if ( attrs[ i ] != NULL ) {
b00a9c ¤   ¤   free( attrs[ i ] );
e9f372 ¤   ····}
7b9371 ¤   }
9daf5a
9d2732 ¤   free( (char *)attrs );
639572 ¤   return( NULL );
b56fe7 ····}
21af5a
62de35 ····return( attrs );
f6efe6 }
8faf5a
f6af5a
76beb7 static int
200778 read_next_tmpl( char **bufp, long *blenp, struct ldap_disptmpl **tmplp,
623c2e ¤   int dtversion )
6cbb36 {
c024b7 ····int¤¤   ¤   ¤   i, j, tokcnt, samerow, adsource;
4c7e6d ····char¤   ¤   ¤   **toks, *itemopts;
61d50a ····struct ldap_disptmpl¤   *tmpl;
7fa30f ····struct ldap_oclist¤ ¤   *ocp, *prevocp;
077cf4 ····struct ldap_adddeflist¤ *adp, *prevadp;
6eda86 ····struct ldap_tmplitem¤   *rowp, *ip, *previp;
26af5a
2ef3e4 ····*tmplp = NULL;
daaf5a
6c29ec ····/*
2309d1 ·····* template name comes first
c2d48d ·····*/
6883ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
26b597 ¤   free_strarray( toks );
7a7e6c ¤   return( tokcnt == 0 ? 0 : LDAP_TMPL_ERR_SYNTAX );
a36fe7 ····}
9daf5a
6cf869 ····if (( tmpl = (struct ldap_disptmpl *)calloc( 1,
c65e87 ¤   ····sizeof( struct ldap_disptmpl ))) == NULL ) {
4fb597 ¤   free_strarray( toks );
9deb2c ¤   return( ·LDAP_TMPL_ERR_MEM );
976fe7 ····}
3e7d58 ····tmpl->dt_name = toks[ 0 ];
3a7115 ····free( (char *)toks );
a9af5a
da29ec ····/*
1cf642 ·····* template plural name comes next
08d48d ·····*/
9883ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
7eb597 ¤   free_strarray( toks );
3908f3 ¤   free_disptmpl( tmpl );
df6c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
296fe7 ····}
c1c0cf ····tmpl->dt_pluralname = toks[ 0 ];
487115 ····free( (char *)toks );
40af5a
db29ec ····/*
98fc45 ·····* template icon name is next
5cd48d ·····*/
3b83ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
d6b597 ¤   free_strarray( toks );
c908f3 ¤   free_disptmpl( tmpl );
dc6c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
0d6fe7 ····}
80120f ····tmpl->dt_iconname = toks[ 0 ];
9a7115 ····free( (char *)toks );
--dbf5 0000bda1f3240100097 Page 8 of disptmpl.c
e0af5a
ed29ec ····/*
0e8faf ·····* template options come next
73d48d ·····*/
4c2e6d ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
20b597 ¤   free_strarray( toks );
2508f3 ¤   free_disptmpl( tmpl );
fa6c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
e96fe7 ····}
c92125 ····for ( i = 0; toks[ i ] != NULL; ++i ) {
476c4d ¤   for ( j = 0; tmploptions[ j ] != NULL; ++j ) {
8040d0 ¤   ····if ( strcasecmp( toks[ i ], tmploptions[ j ] ) == 0 ) {
89002b ¤   ¤   tmpl->dt_options |= tmploptvals[ j ];
7df372 ¤   ····}
9a9371 ¤   }
d06fe7 ····}
faadb6 ····free_strarray( toks );
7faf5a
3f29ec ····/*
9bf50e ·····* object class list is next
a0d48d ·····*/
545767 ····while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
e0e853 ¤   if (( ocp = (struct ldap_oclist *)calloc( 1,
d45579 ¤   ¤   sizeof( struct ldap_oclist ))) == NULL ) {
67b99e ¤   ····free_strarray( toks );
f204fa ¤   ····free_disptmpl( tmpl );
9f6200 ¤   ····return( LDAP_TMPL_ERR_MEM );
b19371 ¤   }
5a0645 ¤   ocp->oc_objclasses = toks;
cf3eba ¤   if ( tmpl->dt_oclist == NULL ) {
cd5533 ¤   ····tmpl->dt_oclist = ocp;
a1f037 ¤   } else {
6e3d57 ¤   ····prevocp->oc_next = ocp;
bd9371 ¤   }
3f6503 ¤   prevocp = ocp;
0c6fe7 ····}
a74ae8 ····if ( tokcnt < 0 ) {
3508f3 ¤   free_disptmpl( tmpl );
c96c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
da6fe7 ····}
85af5a
c929ec ····/*
4ffb7b ·····* read name of attribute to authenticate as
1cd48d ·····*/
c583ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
f2b597 ¤   free_strarray( toks );
9a08f3 ¤   free_disptmpl( tmpl );
ce6c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
ae6fe7 ····}
ef2706 ····if ( toks[ 0 ][ 0 ] != '\0' ) {
790263 ¤   tmpl->dt_authattrname = toks[ 0 ];
f56a79 ····} else {
7b2989 ¤   free( toks[ 0 ] );
cc6fe7 ····}
6c7115 ····free( (char *)toks );
51af5a
8b29ec ····/*
c0252b ·····* read default attribute to use for RDN
01d48d ·····*/
2183ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
46b597 ¤   free_strarray( toks );
7f08f3 ¤   free_disptmpl( tmpl );
ef6c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
d66fe7 ····}
e64db3 ····tmpl->dt_defrdnattrname = toks[ 0 ];
ec7115 ····free( (char *)toks );
b4af5a
4429ec ····/*
9f064f ·····* read default location for new entries
7dd48d ·····*/
3c83ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
0bb597 ¤   free_strarray( toks );
--1130 00047db45a540100097 Page 9 of disptmpl.c
9008f3 ¤   free_disptmpl( tmpl );
596c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
376fe7 ····}
812706 ····if ( toks[ 0 ][ 0 ] != '\0' ) {
9e98c8 ¤   tmpl->dt_defaddlocation = toks[ 0 ];
326a79 ····} else {
762989 ¤   free( toks[ 0 ] );
eb6fe7 ····}
9c7115 ····free( (char *)toks );
2baf5a
9d29ec ····/*
4f92e8 ·····* read list of rules used to define default values for new entries
e2d48d ·····*/
765767 ····while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
9aa958 ¤   if ( strcasecmp( ADDEF_CONSTANT, toks[ 0 ] ) == 0 ) {
2f33ea ¤   ····adsource = LDAP_ADSRC_CONSTANTVALUE;
3a4ab6 ¤   } else if ( strcasecmp( ADDEF_ADDERSDN, toks[ 0 ] ) == 0 ) {
e4c7e7 ¤   ····adsource = LDAP_ADSRC_ADDERSDN;
2cf037 ¤   } else {
17ba02 ¤   ····adsource = 0;
849371 ¤   }
699cdd ¤   if ( adsource == 0 || tokcnt < 2 ||
49d37c ¤   ¤   ( adsource == LDAP_ADSRC_CONSTANTVALUE && tokcnt != 3 ) ||
ea08e9 ¤   ¤   ( adsource == LDAP_ADSRC_ADDERSDN && tokcnt != 2 )) {
00b99e ¤   ····free_strarray( toks );
0e04fa ¤   ····free_disptmpl( tmpl );
ff6503 ¤   ····return( LDAP_TMPL_ERR_SYNTAX );
169371 ¤   }
331b52 ¤   ¤
a749df ¤   if (( adp = (struct ldap_adddeflist *)calloc( 1,
11afdf ¤   ¤   sizeof( struct ldap_adddeflist ))) == NULL ) {
0ab99e ¤   ····free_strarray( toks );
6404fa ¤   ····free_disptmpl( tmpl );
a26200 ¤   ····return( LDAP_TMPL_ERR_MEM );
009371 ¤   }
b5f19d ¤   adp->ad_source = adsource;
cbb6f6 ¤   adp->ad_attrname = toks[ 1 ];
c6d01f ¤   if ( adsource == LDAP_ADSRC_CONSTANTVALUE ) {
7a93b7 ¤   ····adp->ad_value = toks[ 2 ];
b59371 ¤   }
8f2989 ¤   free( toks[ 0 ] );
27918d ¤   free( (char *)toks );
a3af5a
02ee09 ¤   if ( tmpl->dt_adddeflist == NULL ) {
3ab4b2 ¤   ····tmpl->dt_adddeflist = adp;
1af037 ¤   } else {
396b1a ¤   ····prevadp->ad_next = adp;
e69371 ¤   }
2fdeb2 ¤   prevadp = adp;
056fe7 ····}
46af5a
3029ec ····/*
5f4f81 ·····* item list is next
03d48d ·····*/
4f6d1b ····samerow = 0;
435767 ····while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
0e2e88 ¤   if ( strcasecmp( toks[ 0 ], "item" ) == 0 ) {
9fac21 ¤   ····if ( tokcnt < 4 ) {
30a1bf ¤   ¤   free_strarray( toks );
f51cdb ¤   ¤   free_disptmpl( tmpl );
b0a903 ¤   ¤   return( LDAP_TMPL_ERR_SYNTAX );
fff372 ¤   ····}
77af5a
42d49a ¤   ····if (( ip = (struct ldap_tmplitem *)calloc( 1,
78661c ¤   ¤   ····sizeof( struct ldap_tmplitem ))) == NULL ) {
efa1bf ¤   ¤   free_strarray( toks );
861cdb ¤   ¤   free_disptmpl( tmpl );
2a0d2b ¤   ¤   return( LDAP_TMPL_ERR_MEM );
2ff372 ¤   ····}
a1af5a
daea54 ¤   ····/*
477e8b ¤   ·····* find syntaxid from config file string
--f79e 000baf3931640100097 Page 10 of disptmpl.c
ebed8d ¤   ·····*/
95deef ¤   ····while (( itemopts = strrchr( toks[ 1 ], ',' )) != NULL ) {
2ecd4f ¤   ¤   *itemopts++ = '\0';
2a6a89 ¤   ¤   for ( i = 0; itemoptions[ i ] != NULL; ++i ) {
403a60 ¤   ¤   ····if ( strcasecmp( itemopts, itemoptions[ i ] ) == 0 ) {
63cdcb ¤   ¤   ¤   break;
da5f30 ¤   ¤   ····}
1e0fe4 ¤   ¤   }
628556 ¤   ¤   if ( itemoptions[ i ] == NULL ) {
8735e1 ¤   ¤   ····free_strarray( toks );
6d8885 ¤   ¤   ····free_disptmpl( tmpl );
3bed65 ¤   ¤   ····return( LDAP_TMPL_ERR_SYNTAX );
b10fe4 ¤   ¤   }
ad20bd ¤   ¤   ip->ti_options |= itemoptvals[ i ];
00f372 ¤   ····}
73af5a
c57a05 ¤   ····for ( i = 0; itemtypes[ i ] != NULL; ++i ) {
b971db ¤   ¤   if ( strcasecmp( toks[ 1 ], itemtypes[ i ] ) == 0 ) {
a42859 ¤   ¤   ····break;
510fe4 ¤   ¤   }
55f372 ¤   ····}
2820b7 ¤   ····if ( itemtypes[ i ] == NULL ) {
c1a1bf ¤   ¤   free_strarray( toks );
391cdb ¤   ¤   free_disptmpl( tmpl );
f4a903 ¤   ¤   return( LDAP_TMPL_ERR_SYNTAX );
47f372 ¤   ····}
dfaf5a
4ac49b ¤   ····free( toks[ 0 ] );
855b4e ¤   ····free( toks[ 1 ] );
4dec9a ¤   ····ip->ti_syntaxid = itemsynids[ i ];
4a9516 ¤   ····ip->ti_label = toks[ 2 ];
14a1a5 ¤   ····if ( toks[ 3 ][ 0 ] == '\0' ) {
ca11db ¤   ¤   ip->ti_attrname = NULL;
f26306 ¤   ¤   free( toks[ 3 ] );
e4dfe8 ¤   ····} else {
f8218e ¤   ¤   ip->ti_attrname = toks[ 3 ];
3ef372 ¤   ····}
8bd54c ¤   ····if ( toks[ 4 ] != NULL ) {¤ /* extra args. */
f57a02 ¤   ¤   for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
694d86 ¤   ¤   ····;
ee0fe4 ¤   ¤   }
137725 ¤   ¤   if (( ip->ti_args = (char **) calloc( i + 1, sizeof( char * )))
18b4cf ¤   ¤   ¤   == NULL ) {
f18885 ¤   ¤   ····free_disptmpl( tmpl );
3467ed ¤   ¤   ····return( LDAP_TMPL_ERR_MEM );
eb0fe4 ¤   ¤   }
7d7a02 ¤   ¤   for ( i = 0; toks[ i + 4 ] != NULL; ++i ) {
736cc3 ¤   ¤   ····ip->ti_args[ i ] = toks[ i + 4 ];
1e0fe4 ¤   ¤   }
44f372 ¤   ····}
82f841 ¤   ····free( (char *)toks );
12af5a
867767 ¤   ····if ( tmpl->dt_items == NULL ) {
12d708 ¤   ¤   tmpl->dt_items = rowp = ip;
44bdec ¤   ····} else if ( samerow ) {
3ee7f4 ¤   ¤   previp->ti_next_in_row = ip;
77dfe8 ¤   ····} else {
1f97bd ¤   ¤   rowp->ti_next_in_col = ip;
9c45a4 ¤   ¤   rowp = ip;
d1f372 ¤   ····}
72f57d ¤   ····previp = ip;
1b2c90 ¤   ····samerow = 0;
ad0ec6 ¤   } else if ( strcasecmp( toks[ 0 ], "samerow" ) == 0 ) {
34b99e ¤   ····free_strarray( toks );
b3764c ¤   ····samerow = 1;
62f037 ¤   } else {
9fb99e ¤   ····free_strarray( toks );
2604fa ¤   ····free_disptmpl( tmpl );
9c6503 ¤   ····return( LDAP_TMPL_ERR_SYNTAX );
7d9371 ¤   }
a96fe7 ····}
ba4ae8 ····if ( tokcnt < 0 ) {
--df95 0018005ba2f40100097 Page 11 of disptmpl.c
9008f3 ¤   free_disptmpl( tmpl );
596c56 ¤   return( LDAP_TMPL_ERR_SYNTAX );
376fe7 ····}
08af5a
c04b36 ····*tmplp = tmpl;
6da897 ····return( 0 );
80efe6 }
--b114 000d8a89de040100098 Page 1 of dsparse.c
bc38e5 /*
09515b ·* Copyright (c) 1993, 1994 Regents of the University of Michigan.
60599a ·* All rights reserved.
44775e ·*
22b855 ·* Redistribution and use in source and binary forms are permitted
ec9795 ·* provided that this notice is preserved and that due credit is given
bf1873 ·* to the University of Michigan at Ann Arbor. The name of the University
148805 ·* may not be used to endorse or promote products derived from this
b974fe ·* software without specific prior written permission. This software
1a2a32 ·* is provided ``as is'' without express or implied warranty.
a0775e ·*
aa07e6 ·* dsparse.c: ·parsing routines used by display template and search·
598e52 ·* preference file library routines for LDAP clients.
6b775e ·*
e9ddde ·* 7 March 1994 by Mark C Smith
d4495d ·*/
9baf5a
36feb2 #include <stdio.h>
65b1cb #include <ctype.h>
9f324c #include <string.h>
a3af5a
c824c3 #if PGPSOCKETSLDAP¤ /* jason */
6865aa #include "pgpSocketsLDAP.h"
e7af5a
8edb21 #else
b6c583 #ifdef MACOS
80bea3 #include <stdlib.h>
af65e0 #include "macos.h"
536c94 #else /* MACOS */
81d581 #if defined(DOS) || defined(WIN32)¤ ¤   /* marcd */
125e84 #include <malloc.h>
9901b0 #ifdef DOS
28f2ef #include "msdos.h"
477454 #endif
11aad8 #else /* DOS */
2df15e #include <sys/types.h>
5709b0 #include <sys/file.h>
0fbea3 #include <stdlib.h>
5fbc39 #endif /* DOS */
53e962 #endif /* MACOS */
34df0f #endif /* PGPSOCKETSLDAP */
eaaf5a
d7b779 #include "lber.h"
75e990 #include "ldap.h"
d2af5a
73719a #ifndef NEEDPROTOS
af9e1d int next_line_tokens();
3140f5 void free_strarray();
49cffe static int next_line();
db77e4 static char *next_token();
e34b51 #else /* !NEEDPROTOS */
dfec27 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
0ed559 void free_strarray( char **sap );
132633 static int next_line( char **bufp, long *blenp, char **linep );
2ce6ba static char *next_token( char ** sp );
6d3f09 #endif /* !NEEDPROTOS */
c8af5a
68af5a
41af5a
624d2f int
3ad540 next_line_tokens( char **bufp, long *blenp, char ***toksp )
e8bb36 {
a5cdea ····char¤   *p, *line, *token, **toks;
b734de ····int¤¤   rc, tokcnt;
64af5a
d70d6d ····*toksp = NULL;
baaf5a
f96f0e ····if (( rc = next_line( bufp, blenp, &line )) <= 0 ) {
d56d62 ¤   return( rc );
d96fe7 ····}
ebaf5a
d80ed9 ····if (( toks = (char **)calloc( 1, sizeof( char * ))) == NULL ) {
--2579 000d012c20740100098 Page 2 of dsparse.c
19d963 ¤   free( line );
b67360 ¤   return( -1 );
946fe7 ····}
c3d4c0 ····tokcnt = 0;
c3af5a
b55b45 ····p = line;
96d19d ····while (( token = next_token( &p )) != NULL ) {
6b98d1 ¤   if (( toks = (char **)realloc( toks, ( tokcnt + 2 ) *
dd1455 ¤   ¤   sizeof( char * ))) == NULL ) {
cef841 ¤   ····free( (char *)toks );
fe7102 ¤   ····free( line );
64db01 ¤   ····return( -1 );
949371 ¤   }
87c584 ¤   toks[ tokcnt ] = token;
67819a ¤   toks[ ++tokcnt ] = NULL;
4b6fe7 ····}
26af5a
aacb8d ····if ( tokcnt == 1 && strcasecmp( toks[ 0 ], "END" ) == 0 ) {
b42680 ¤   tokcnt = 0;
bcb597 ¤   free_strarray( toks );
f0996f ¤   toks = NULL;
646fe7 ····}
c6af5a
5c4b98 ····free( line );
23af5a
687429 ····if ( tokcnt == 0 ) {
378f19 ¤   if ( toks != NULL ) {
a8f841 ¤   ····free( (char *)toks );
589371 ¤   }
ff6a79 ····} else {
a1261f ¤   *toksp = toks;
d76fe7 ····}
a5af5a
d758e5 ····return( tokcnt );
a8efe6 }
a7af5a
adaf5a
0abeb7 static int
33d285 next_line( char **bufp, long *blenp, char **linep )
49bb36 {
ad3a8f ····char¤   *linestart, *line, *p;
d860a4 ····long¤   plen;
e9af5a
c50b95 ····linestart = *bufp;
d35e8d ····p = *bufp;
8877a6 ····plen = *blenp;
e5af5a
40c9a3 ····do {
aa39ed ¤   for ( linestart = p; plen > 0; ++p, --plen ) {
087a90 ¤   ····if ( *p == '\r' ) {
4e6d04 ¤   ¤   if ( plen > 1 && *(p+1) == '\n' ) {
d9760b ¤   ¤   ····++p;
674e6b ¤   ¤   ····--plen;
300fe4 ¤   ¤   }
e72f68 ¤   ¤   break;
b4f372 ¤   ····}
4daf5a
6d7ec3 ¤   ····if ( *p == '\n' ) {
c06957 ¤   ¤   if ( plen > 1 && *(p+1) == '\r' ) {
62760b ¤   ¤   ····++p;
f94e6b ¤   ¤   ····--plen;
9f0fe4 ¤   ¤   }
d42f68 ¤   ¤   break;
9ff372 ¤   ····}
2a9371 ¤   }
a049ab ¤   ++p;
7a74d6 ¤   --plen;
d929ef ····} while ( plen > 0 && ( *linestart == '#' || linestart + 1 == p ));
f2af5a
48af5a
ed4aa9 ····*bufp = p;
d0ab5e ····*blenp = plen;
--4a94 000f83f9ecd40100098 Page 3 of dsparse.c
e0af5a
1aaf5a
3d81c0 ····if ( plen <= 0 ) {
a064e8 ¤   *linep = NULL;
edc4fb ¤   return( 0 );¤   /* end of file */
ee6fe7 ····}
deaf5a
be9ef6 ····if (( line = malloc( p - linestart )) == NULL ) {
0f64e8 ¤   *linep = NULL;
788c3c ¤   return( -1 );¤  /* fatal error */
836fe7 ····}
b1af5a
d8d421 ····(void) memcpy( line, linestart, p - linestart );
f47fa7 ····line[ p - linestart - 1 ] = '\0';
002af1 ····*linep = line;
aa272c ····return( strlen( line ));
c5efe6 }
9aaf5a
35af5a
60083f static char *
608b5d next_token( char **sp )
a6bb36 {
d00f65 ····int¤¤   in_quote = 0;
784700 ····char¤   *p, *tokstart, *t;
faaf5a
187b08 ····if ( **sp == '\0' ) {
a09572 ¤   return( NULL );
6a6fe7 ····}
47af5a
399115 ····p = *sp;
6faf5a
aa35a0 ····while ( isspace( *p )) {¤   ¤   /* skip leading white space */
ac49ab ¤   ++p;
d26fe7 ····}
e8af5a
6e7c48 ····if ( *p == '\0' ) {
459572 ¤   return( NULL );
766fe7 ····}
61af5a
24fe3a ····if ( *p == '\"' ) {
71a86c ¤   in_quote = 1;
bd49ab ¤   ++p;
146fe7 ····}
d54b3b ····t = tokstart = p;
caaf5a
ac4b13 ····for ( ;; ) {
ac4667 ¤   if ( *p == '\0' || ( isspace( *p ) && !in_quote )) {
6e906f ¤   ····if ( *p != '\0' ) {
4b4992 ¤   ¤   ++p;
66f372 ¤   ····}
64d173 ¤   ····*t++ = '\0';¤   ¤   /* end of token */
e2cafa ¤   ····break;
979371 ¤   }
6aaf5a
673b21 ¤   if ( *p == '\"' ) {
e9cc22 ¤   ····in_quote = !in_quote;
e4c39a ¤   ····++p;
7ff037 ¤   } else {
d2ba9f ¤   ····*t++ = *p++;
f89371 ¤   }
bb6fe7 ····}
e0af5a
f64585 ····*sp = p;
fbaf5a
f9a372 ····if ( t == tokstart ) {
6d9572 ¤   return( NULL );
876fe7 ····}
9eaf5a
9481ef ····return( strdup( tokstart ));
58efe6 }
5daf5a
f8af5a
--7a41 001a042ce3f40100098 Page 4 of dsparse.c
b3314a void
25bfbe free_strarray( char **sap )
26bb36 {
5d0230 ····int¤¤   i;
3faf5a
51246d ····if ( sap != NULL ) {
4a8812 ¤   for ( i = 0; sap[ i ] != NULL; ++i ) {
a942ae ¤   ····free( sap[ i ] );
b49371 ¤   }
4dcb37 ¤   free( (char *)sap );
9e6fe7 ····}
a0efe6 }
--a4f8 000db7a965a40100099 Page 1 of error.c
56feb2 #include <stdio.h>
9c324c #include <string.h>
93af5a
7324c3 #if PGPSOCKETSLDAP¤ /* jason */
2f65aa #include "pgpSocketsLDAP.h"
f8af5a
0fdb21 #else
56c583 #ifdef MACOS
9ebea3 #include <stdlib.h>
686c94 #else /* MACOS */
32fdef #if defined( DOS ) || defined( _WIN32 )
0b5e84 #include <malloc.h>
b101b0 #ifdef DOS
d5f2ef #include "msdos.h"
fd7454 #endif
f4aad8 #else /* DOS */
4df15e #include <sys/types.h>
1166f2 #include <sys/socket.h>
8cbc39 #endif /* DOS */
31e962 #endif /* MACOS */
44df0f #endif /* PGPSOCKETSLDAP */
54af5a
42b779 #include "lber.h"
99e990 #include "ldap.h"
b4af5a
08d189 struct ldaperror {
fa59f0 ¤   int¤e_code;
0df124 ¤   char¤   *e_reason;
1982f7 };
ceaf5a
9d36da static struct ldaperror ldap_errlist[] = {
b3d598 ¤   LDAP_SUCCESS, ¤ ¤   ¤   "Success",
34fcd2 ¤   LDAP_OPERATIONS_ERROR, ¤¤   "Operations error",
b0bfcd ¤   LDAP_PROTOCOL_ERROR, ¤  ¤   "Protocol error",
d87e5c ¤   LDAP_TIMELIMIT_EXCEEDED,¤   "Timelimit exceeded",
d7b85f ¤   LDAP_SIZELIMIT_EXCEEDED, ¤  "Sizelimit exceeded",
fe802f ¤   LDAP_COMPARE_FALSE, ¤   ¤   "Compare false",
083d0e ¤   LDAP_COMPARE_TRUE, ¤¤   "Compare true",
cb6edb ¤   LDAP_STRONG_AUTH_NOT_SUPPORTED, "Strong authentication not supported",
affac4 ¤   LDAP_STRONG_AUTH_REQUIRED, ¤"Strong authentication required",
bcf91a ¤   LDAP_PARTIAL_RESULTS, ¤ ¤   "Partial results and referral received",
81ab25 ¤   LDAP_NO_SUCH_ATTRIBUTE, ¤   "No such attribute",
28b284 ¤   LDAP_UNDEFINED_TYPE, ¤  ¤   "Undefined attribute type",
d55982 ¤   LDAP_INAPPROPRIATE_MATCHING, ¤  "Inappropriate matching",
e9871b ¤   LDAP_CONSTRAINT_VIOLATION, ¤"Constraint violation",
17ca9c ¤   LDAP_TYPE_OR_VALUE_EXISTS, ¤"Type or value exists",
5675f7 ¤   LDAP_INVALID_SYNTAX, ¤  ¤   "Invalid syntax",
562b90 ¤   LDAP_NO_SUCH_OBJECT, ¤  ¤   "No such object",
afa6b4 ¤   LDAP_ALIAS_PROBLEM, ¤   ¤   "Alias problem",
fe0fa6 ¤   LDAP_INVALID_DN_SYNTAX,¤¤   "Invalid DN syntax",
f928f6 ¤   LDAP_IS_LEAF, ¤ ¤   ¤   "Object is a leaf",
a8ea84 ¤   LDAP_ALIAS_DEREF_PROBLEM, ¤ "Alias dereferencing problem",
cbbe25 ¤   LDAP_INAPPROPRIATE_AUTH, ¤  "Inappropriate authentication",
54ecfe ¤   LDAP_INVALID_CREDENTIALS, ¤ "Invalid credentials",
41ab19 ¤   LDAP_INSUFFICIENT_ACCESS, ¤ "Insufficient access",
bc6fee ¤   LDAP_BUSY, ¤¤   ¤   "DSA is busy",
d4c5b2 ¤   LDAP_UNAVAILABLE, ¤ ¤   "DSA is unavailable",
085e15 ¤   LDAP_UNWILLING_TO_PERFORM, ¤"DSA is unwilling to perform",
dd4e1f ¤   LDAP_LOOP_DETECT, ¤ ¤   "Loop detected",
9d66d1 ¤   LDAP_NAMING_VIOLATION, ¤¤   "Naming violation",
25a6d2 ¤   LDAP_OBJECT_CLASS_VIOLATION, ¤  "Object class violation",
076e68 ¤   LDAP_NOT_ALLOWED_ON_NONLEAF, ¤  "Operation not allowed on nonleaf",
522ed3 ¤   LDAP_NOT_ALLOWED_ON_RDN, ¤  "Operation not allowed on RDN",
a0b117 ¤   LDAP_ALREADY_EXISTS, ¤  ¤   "Already exists",
ca8ddd ¤   LDAP_NO_OBJECT_CLASS_MODS, ¤"Cannot modify object class",
0f711b ¤   LDAP_RESULTS_TOO_LARGE,¤¤   "Results too large",
2bb38b ¤   LDAP_OTHER, ¤   ¤   ¤   "Unknown error",
6f1021 ¤   LDAP_SERVER_DOWN,¤  ¤   "Can't contact LDAP server",
5296a5 ¤   LDAP_LOCAL_ERROR,¤  ¤   "Local error",
76a55f ¤   LDAP_ENCODING_ERROR,¤   ¤   "Encoding error",
7682fc ¤   LDAP_DECODING_ERROR,¤   ¤   "Decoding error",
db7f15 ¤   LDAP_TIMEOUT,¤  ¤   ¤   "Timed out",
--3d20 00032dc946340100099 Page 2 of error.c
09d3f5 ¤   LDAP_AUTH_UNKNOWN,¤ ¤   "Unknown authentication method",
b13166 ¤   LDAP_FILTER_ERROR,¤ ¤   "Bad search filter",
a5afdd ¤   LDAP_USER_CANCELLED,¤   ¤   "User cancelled operation",
f87221 ¤   LDAP_PARAM_ERROR,¤  ¤   "Bad parameter to an ldap routine",
5b6b8b ¤   LDAP_NO_MEMORY,¤¤   ¤   "Out of memory",
08f11b ¤   -1, 0
cf82f7 };
eaaf5a
8611e4 char *
5f449c ldap_err2string( int err )
c7bb36 {
641426 ¤   int¤i;
5daf5a
eee37d ¤   Debug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 );
31af5a
ebe8ba ¤   for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
f21eec ¤   ¤   if ( err == ldap_errlist[i].e_code )
7d995b ¤   ¤   ¤   return( ldap_errlist[i].e_reason );
219371 ¤   }
deaf5a
fcb684 ¤   return( "Unknown error" );
1aefe6 }
91af5a
864eeb #ifndef NO_USERINTERFACE
33314a void
684c38 ldap_perror( LDAP *ld, char *s )
5ebb36 {
f91426 ¤   int¤i;
a0af5a
677997 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 );
c6af5a
c93a4e ¤   if ( ld == NULL ) {
f0df80 ¤   ¤   perror( s );
5499bf ¤   ¤   return;
8e9371 ¤   }
2daf5a
eee8ba ¤   for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
25736d ¤   ¤   if ( ld->ld_errno == ldap_errlist[i].e_code ) {
23ba50 ¤   ¤   ¤   fprintf( stderr, "%s: %s\n", s,
e72f8a ¤   ¤   ¤   ····ldap_errlist[i].e_reason );
39667f ¤   ¤   ¤   if ( ld->ld_matched != NULL && *ld->ld_matched != '\0' )
f8daf7 ¤   ¤   ¤   ¤   fprintf( stderr, "%s: matched: %s\n", s,
6e74db ¤   ¤   ¤   ¤   ····ld->ld_matched );
44dd1c ¤   ¤   ¤   if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
c1acca ¤   ¤   ¤   ¤   fprintf( stderr, "%s: additional info: %s\n",
e9c33b ¤   ¤   ¤   ¤   ····s, ld->ld_error );
5e018d ¤   ¤   ¤   fflush( stderr );
800ecc ¤   ¤   ¤   return;
2b0fe4 ¤   ¤   }
449371 ¤   }
14af5a
a2c38c ¤   fprintf( stderr, "%s: Not an LDAP errno %d\n", s, ld->ld_errno );
564f6c ¤   fflush( stderr );
53efe6 }
60af5a
a1db21 #else
dbaf5a
16314a void
c24c38 ldap_perror( LDAP *ld, char *s )
01bb36 {
6d9e79 ¤   (void) ld;
a61f57 ¤   (void) s;
55efe6 }
4aaf5a
a000a6 #endif /* NO_USERINTERFACE */
74af5a
00af5a
284d2f int
96dd35 ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit )
4cbb36 {
7ff23f ¤   LDAPMessage¤*lm;
3228d5 ¤   BerElement¤ ber;
--dab7 001c602642140100099 Page 3 of error.c
3ce4a6 ¤   long¤   ¤   along;
2b8574 ¤   int¤¤   rc;
e3af5a
79eebb ¤   Debug( LDAP_DEBUG_TRACE, "ldap_result2error\n", 0, 0, 0 );
9daf5a
bd658b ¤   if ( r == NULLMSG )
3873de ¤   ¤   return( LDAP_PARAM_ERROR );
83af5a
020689 ¤   for ( lm = r; lm->lm_chain != NULL; lm = lm->lm_chain )
46c78a ¤   ¤   ;¤  /* NULL */
02af5a
ab5e25 ¤   if ( ld->ld_error ) {
1197f5 ¤   ¤   free( ld->ld_error );
b2ff38 ¤   ¤   ld->ld_error = NULL;
b49371 ¤   }
d29180 ¤   if ( ld->ld_matched ) {
54824f ¤   ¤   free( ld->ld_matched );
585b33 ¤   ¤   ld->ld_matched = NULL;
4f9371 ¤   }
81af5a
544644 ¤   ber = *(lm->lm_ber);
2c4eab ¤   if ( ld->ld_version == LDAP_VERSION2 ) {
3668bb ¤   ¤   rc = ber_scanf( &ber, "{iaa}", &along, &ld->ld_matched,
b6c735 ¤   ¤   ····&ld->ld_error );
9ef037 ¤   } else {
ebc2e3 ¤   ¤   rc = ber_scanf( &ber, "{ia}", &along, &ld->ld_error );
ca9371 ¤   }
bf1f5c ¤   if ( rc == LBER_ERROR ) {
6e3108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
91f037 ¤   } else {
4580e3 ¤   ¤   ld->ld_errno = (int) along;
fc9371 ¤   }
2aaf5a
6d91a1 ¤   if ( freeit )
f2808f ¤   ¤   ldap_msgfree( r );
28af5a
66722d ¤   return( ld->ld_errno );
c6efe6 }
--1918 000c28ee8174010009a Page 1 of free.c
bc38e5 /*
2610b9 ·* ·Copyright (c) 1994 The Regents of the University of Michigan.
9fe4d4 ·* ·All rights reserved.
a8775e ·*
eb59d7 ·* ·free.c - some free routines are included here to avoid having to
eaa457 ·* ··········link in lots of extra code when not using certain features
81495d ·*/
b2af5a
3d0c68 #ifndef lint·
ca24ea static char copyright[] = "@(#) Copyright (c) 1994 The Regents of the "
a2f59d ¤   ¤   ¤   ··"University of Michigan.\nAll rights reserved.\n";
c37454 #endif
ebaf5a
71af5a
10feb2 #include <stdio.h>
25324c #include <string.h>
dab1cb #include <ctype.h>
3baf5a
6824c3 #if PGPSOCKETSLDAP¤ /* jason */
a665aa #include "pgpSocketsLDAP.h"
edaf5a
1edb21 #else
9bc583 #ifdef MACOS
aabea3 #include <stdlib.h>
2965e0 #include "macos.h"
ef6c94 #else /* MACOS */
c301b0 #ifdef DOS
545e84 #include <malloc.h>
0301b0 #ifdef DOS
74f2ef #include "msdos.h"
607454 #endif
1daad8 #else /* DOS */
b9f15e #include <sys/types.h>
4dbea3 #include <stdlib.h>
0cbc39 #endif /* DOS */
05e962 #endif /* MACOS */
01df0f #endif /* PGPSOCKETSLDAP */
1caf5a
e4b779 #include "lber.h"
51e990 #include "ldap.h"
42af5a
8b314a void
b0be11 ldap_getfilter_free( LDAPFiltDesc *lfdp )
eebb36 {
18b601 ····LDAPFiltList¤   *flp, *nextflp;
2b934b ····LDAPFiltInfo¤   *fip, *nextfip;
a4af5a
4edbf3 ····for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = nextflp ) {
696273 ¤   for ( fip = flp->lfl_ilist; fip != NULL; fip = nextfip ) {
390414 ¤   ····nextfip = fip->lfi_next;
7f16ad ¤   ····free( fip->lfi_filter );
046cb2 ¤   ····free( fip->lfi_desc );
6bcb22 ¤   ····free( fip );
a89371 ¤   }
abb96f ¤   nextflp = flp->lfl_next;
5892a0 ¤   free( flp->lfl_pattern );
dc2149 ¤   free( flp->lfl_delims );
d1a2a8 ¤   free( flp->lfl_tag );
66dcd8 ¤   free( flp );
8a6fe7 ····}
24af5a
b73790 ····if ( lfdp->lfd_curvalcopy != NULL ) {
9fa0cd ¤   free( lfdp->lfd_curvalcopy );
246fe7 ····}
61febe ····if ( lfdp->lfd_curvalwords != NULL ) {
f53c2c ¤   free( lfdp->lfd_curvalwords );
276fe7 ····}
fadcc9 ····if ( lfdp->lfd_filtprefix != NULL ) {
8a1572 ¤   free( lfdp->lfd_filtprefix );
366fe7 ····}
49ab85 ····if ( lfdp->lfd_filtsuffix != NULL ) {
c20229 ¤   free( lfdp->lfd_filtsuffix );
--933a 001ed417dee4010009a Page 2 of free.c
9f6fe7 ····}
86af5a
d0e976 ····free( lfdp );
36efe6 }
8faf5a
2938e5 /*
7d4c14 ·* free a null-terminated array of pointers to mod structures. the
d3470e ·* structures are freed, not the array itself, unless the freemods
da10da ·* flag is set.
bf495d ·*/
58af5a
75314a void
0f11b4 ldap_mods_free( LDAPMod **mods, int freemods )
55bb36 {
bd1426 ¤   int¤i;
d5af5a
8866a8 ¤   if ( mods == NULL )
f299bf ¤   ¤   return;
35af5a
58b06d ¤   for ( i = 0; mods[i] != NULL; i++ ) {
08e1e9 ¤   ¤   if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) {
2de4e7 ¤   ¤   ¤   ber_bvecfree( mods[i]->mod_bvalues );
c445a6 ¤   ¤   } else {
c79c88 ¤   ¤   ¤   ldap_value_free( mods[i]->mod_values );
6e0fe4 ¤   ¤   }
587a4b ¤   ¤   free( (char *) mods[i] );
b09371 ¤   }
79af5a
d1fd7e ¤   if ( freemods )
47f6fe ¤   ¤   free( (char *) mods );
edefe6 }
--940e 000d51b393e4010009b Page 1 of friendly.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
13c96b ·* ·friendly.c
1a495d ·*/
41af5a
1d0c68 #ifndef lint·
9566c6 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University "
883efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
777454 #endif
fbaf5a
02feb2 #include <stdio.h>
c1b1cb #include <ctype.h>
a6324c #include <string.h>
bdaf5a
4124c3 #if PGPSOCKETSLDAP¤ /* jason */
0165aa #include "pgpSocketsLDAP.h"
2faf5a
8ddb21 #else
d1c583 #ifdef MACOS
45bea3 #include <stdlib.h>
5865e0 #include "macos.h"
53e962 #endif /* MACOS */
e0af5a
26fdef #if defined( DOS ) || defined( _WIN32 )
0c5e84 #include <malloc.h>
1801b0 #ifdef DOS
00f2ef #include "msdos.h"
7c7454 #endif
2bbc39 #endif /* DOS */
83af5a
2d1330 #if !defined( MACOS ) && !defined( DOS )
6e495d #include <errno.h>
e8f15e #include <sys/types.h>
10a394 #ifndef WIN32¤  ¤   /* marcd */
bd66f2 #include <sys/socket.h>
cb7454 #endif
a27454 #endif
74df0f #endif /* PGPSOCKETSLDAP */
06af5a
a1b779 #include "lber.h"
8be990 #include "ldap.h"
2daf5a
6f11e4 char *
327a5c ldap_friendly_name( char *filename, char *uname, FriendlyMap **map )
e1bb36 {
d7f45a ¤   int¤i, entries;
762e1a ¤   FILE¤   *fp;
98fad9 ¤   char¤   *s;
45781f ¤   char¤   buf[BUFSIZ];
c5af5a
265da7 ¤   if ( map == NULL ) {
01afd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
fc6644 ¤   ¤   errno = EINVAL;
337454 #endif
05e8ca ¤   ¤   return( uname );
a09371 ¤   }
69af5a
0b084d ¤   if ( *map == NULL ) {
4a1a5c ¤   ¤   if ( (fp = fopen( filename, "r" )) == NULL )
43dc97 ¤   ¤   ¤   return( uname );
8aaf5a
df3009 ¤   ¤   entries = 0;
a8ab20 ¤   ¤   while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
c4fdbf ¤   ¤   ¤   if ( buf[0] != '#' )
e1b66c ¤   ¤   ¤   ¤   entries++;
9b0fe4 ¤   ¤   }
2b57eb ¤   ¤   rewind( fp );
c4af5a
e6316b ¤   ¤   if ( (*map = (FriendlyMap *) malloc( (entries + 1) *
d52752 ¤   ¤   ····sizeof(FriendlyMap) )) == NULL ) {
--43d7 001ab4fc0954010009b Page 2 of friendly.c
69af4e ¤   ¤   ¤   fclose( fp );
b9dc97 ¤   ¤   ¤   return( uname );
120fe4 ¤   ¤   }
2daf5a
6f9ed6 ¤   ¤   i = 0;
432dd1 ¤   ¤   while ( fgets( buf, sizeof(buf), fp ) != NULL && i < entries ) {
954204 ¤   ¤   ¤   if ( buf[0] == '#' )
70d040 ¤   ¤   ¤   ¤   continue;
92af5a
3a659f ¤   ¤   ¤   if ( (s = strchr( buf, '\n' )) != NULL )
0a9276 ¤   ¤   ¤   ¤   *s = '\0';
41af5a
6f8b05 ¤   ¤   ¤   if ( (s = strchr( buf, '\t' )) == NULL )
6dd040 ¤   ¤   ¤   ¤   continue;
b44f49 ¤   ¤   ¤   *s++ = '\0';
3baf5a
3589b4 ¤   ¤   ¤   if ( *s == '"' ) {
68a7fa ¤   ¤   ¤   ¤   int¤esc = 0, found = 0;
6baf5a
a3f7ce ¤   ¤   ¤   ¤   for ( ++s; *s && !found; s++ ) {
5ea5c7 ¤   ¤   ¤   ¤   ¤   switch ( *s ) {
38e3b1 ¤   ¤   ¤   ¤   ¤   case '\\':
89244d ¤   ¤   ¤   ¤   ¤   ¤   esc = 1;
6800eb ¤   ¤   ¤   ¤   ¤   ¤   break;
6dd6bd ¤   ¤   ¤   ¤   ¤   case '"':
621feb ¤   ¤   ¤   ¤   ¤   ¤   if ( !esc )
a43ec2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   found = 1;
12037c ¤   ¤   ¤   ¤   ¤   ¤   /* FALL */
3e5ee4 ¤   ¤   ¤   ¤   ¤   default:
be7e91 ¤   ¤   ¤   ¤   ¤   ¤   esc = 0;
f900eb ¤   ¤   ¤   ¤   ¤   ¤   break;
c31c89 ¤   ¤   ¤   ¤   ¤   }
dd2613 ¤   ¤   ¤   ¤   }
e3a3a6 ¤   ¤   ¤   }
3daf5a
6609ec ¤   ¤   ¤   (*map)[i].f_unfriendly = strdup( buf );
d024a5 ¤   ¤   ¤   (*map)[i].f_friendly = strdup( s );
af81ec ¤   ¤   ¤   i++;
250fe4 ¤   ¤   }
8faf5a
9368fb ¤   ¤   fclose( fp );
fcd362 ¤   ¤   (*map)[i].f_unfriendly = NULL;
2d9371 ¤   }
23af5a
09cbd8 ¤   for ( i = 0; (*map)[i].f_unfriendly != NULL; i++ ) {
c45246 ¤   ¤   if ( strcasecmp( uname, (*map)[i].f_unfriendly ) == 0 )
8c06bb ¤   ¤   ¤   return( (*map)[i].f_friendly );
d39371 ¤   }
e8591b ¤   return( uname );
8cefe6 }
03af5a
19af5a
9e314a void
5d48be ldap_free_friendlymap( FriendlyMap **map )
afbb36 {
9bd9bf ¤   struct friendly* pF = *map;
7caf5a
5dc6a5 ¤   if ( pF == NULL )
eb99bf ¤   ¤   return;
e0af5a
5aa0cb ¤   while ( pF->f_unfriendly )
86c7a1 ¤   {
9da5d4 ¤   ¤   free( pF->f_unfriendly );
007e3c ¤   ¤   free( pF->f_friendly );
bf97e7 ¤   ¤   pF++;
c69371 ¤   }
0661c8 ¤   free( *map );
99f132 ¤   *map = NULL;
abefe6 }
--cd6f 000d889dc284010009c Page 1 of getattr.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
621e95 ·* ·getattr.c
6f495d ·*/
43af5a
6e0c68 #ifndef lint·
7f07d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
c73efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
377454 #endif
e8af5a
f1feb2 #include <stdio.h>
32b1cb #include <ctype.h>
1b324c #include <string.h>
dfaf5a
8a24c3 #if PGPSOCKETSLDAP¤ /* jason */
3e65aa #include "pgpSocketsLDAP.h"
90af5a
cadb21 #else
e4c583 #ifdef MACOS
30bea3 #include <stdlib.h>
0565e0 #include "macos.h"
266c94 #else /* MACOS */
07fdef #if defined( DOS ) || defined( _WIN32 )
a85e84 #include <malloc.h>
2601b0 #ifdef DOS
40f2ef #include "msdos.h"
557454 #endif
7aaad8 #else /* DOS */
8ef15e #include <sys/types.h>
c566f2 #include <sys/socket.h>
2dbc39 #endif /* DOS */
b1e962 #endif /* MACOS */
5adf0f #endif /* PGPSOCKETSLDAP */
42af5a
7db779 #include "lber.h"
c7e990 #include "ldap.h"
64745c #include "ldap-int.h"
60af5a
f611e4 char *
3ae7e1 ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **ber )
25bb36 {
13665f ¤   long¤   len;
86af5a
b4eb0d ¤   Debug( LDAP_DEBUG_TRACE, "ldap_first_attribute\n", 0, 0, 0 );
60af5a
1552d2 ¤   if ( (*ber = alloc_ber_with_options( ld )) == NULLBER ) {
64ef86 ¤   ¤   return( NULL );
9d9371 ¤   }
45af5a
b4b341 ¤   **ber = *entry->lm_ber;
86af5a
8d7869 ¤   /*·
e22415 ¤   ·* Skip past the sequence, dn, sequence of sequence, snarf the
25ecf4 ¤   ·* attribute type, and skip the set of values, leaving us
bf53c9 ¤   ·* positioned right before the next attribute type/value sequence.
aaa4e3 ¤   ·*/
f4af5a
3a4bd1 ¤   len = LDAP_MAX_ATTR_LEN;
584200 ¤   if ( ber_scanf( *ber, "{x{{sx}", ld->ld_attrbuffer, &len )
7a95f9 ¤   ····== LBER_ERROR ) {
733108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
92839f ¤   ¤   ber_free( *ber, 0 );
ebef86 ¤   ¤   return( NULL );
a49371 ¤   }
6caf5a
d3472d ¤   return( ld->ld_attrbuffer );
beefe6 }
88af5a
ed0873 /* ARGSUSED */
d811e4 char *
--a634 0013576f3554010009c Page 2 of getattr.c
3ea2f0 ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber )
41bb36 {
77665f ¤   long¤   len;
67af5a
540269 ¤   (void) entry;
bc67c5 ¤
a79218 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_next_attribute\n", 0, 0, 0 );
dcaf5a
469b05 ¤   /* skip sequence, snarf attribute type, skip values */
c74bd1 ¤   len = LDAP_MAX_ATTR_LEN;
28baf0 ¤   if ( ber_scanf( ber, "{sx}", ld->ld_attrbuffer, &len )·
9995f9 ¤   ····== LBER_ERROR ) {
cd3108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
db11f5 ¤   ¤   ber_free( ber, 0 );
f8ef86 ¤   ¤   return( NULL );
719371 ¤   }
f6af5a
57472d ¤   return( ld->ld_attrbuffer );
35efe6 }
--daf0 000e05e6ab64010009d Page 1 of getdn.c
bc38e5 /*
b47dba ·* ·Copyright (c) 1994 Regents of the University of Michigan.
e1e4d4 ·* ·All rights reserved.
97775e ·*
6ce8d9 ·* ·getdn.c
ac495d ·*/
54af5a
6b0c68 #ifndef lint·
c607d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
423efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
667454 #endif
dfaf5a
9cfeb2 #include <stdio.h>
b8b1cb #include <ctype.h>
1f324c #include <string.h>
cdaf5a
ff24c3 #if PGPSOCKETSLDAP¤ /* jason */
0d65aa #include "pgpSocketsLDAP.h"
3faf5a
badb21 #else
33c583 #ifdef MACOS
8fbea3 #include <stdlib.h>
9665e0 #include "macos.h"
5b6c94 #else /* MACOS */
d4fdef #if defined( DOS ) || defined( _WIN32 )
e25e84 #include <malloc.h>
1f01b0 #ifdef DOS
3df2ef #include "msdos.h"
fb7454 #endif
15aad8 #else /* DOS */
2bf15e #include <sys/types.h>
e766f2 #include <sys/socket.h>
fabc39 #endif /* DOS */
cbe962 #endif /* MACOS */
13df0f #endif /* PGPSOCKETSLDAP */
28af5a
fdb779 #include "lber.h"
68e990 #include "ldap.h"
44af5a
3311e4 char *
a4d733 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
34bb36 {
aeee9f ¤   char¤   ¤   *dn;
39f76d ¤   BerElement¤ tmp;
5eaf5a
1b9318 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
cfaf5a
a6706c ¤   if ( entry == NULL ) {
65bfd2 ¤   ¤   ld->ld_errno = LDAP_PARAM_ERROR;
77ef86 ¤   ¤   return( NULL );
b09371 ¤   }
0faf5a
d2fa93 ¤   tmp = *entry->lm_ber;¤  /* struct copy */
c9729d ¤   if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) {
f23108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
daef86 ¤   ¤   return( NULL );
039371 ¤   }
b4af5a
394b5c ¤   return( dn );
7aefe6 }
8faf5a
8011e4 char *
53039e ldap_dn2ufn( char *dn )
e0bb36 {
bd6495 ¤   char¤   *p, *ufn, *r;
b14ead ¤   int¤state;
17af5a
e0aa69 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
bfaf5a
8b2f94 ¤   if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL )
8b534e ¤   ¤   return( strdup( dn ));
e0af5a
--1f83 000134dd79e4010009d Page 2 of getdn.c
bce3f4 ¤   ufn = strdup( ++p );
5faf5a
c5b584 #define INQUOTE¤¤   1
f5e45e #define OUTQUOTE¤   2
88dfc1 ¤   state = OUTQUOTE;
8c1093 ¤   for ( p = ufn, r = ufn; *p; p++ ) {
fc797d ¤   ¤   switch ( *p ) {
b92e91 ¤   ¤   case '\\':
fccc59 ¤   ¤   ¤   if ( *++p == '\0' )
21b800 ¤   ¤   ¤   ¤   p--;
c6e543 ¤   ¤   ¤   else {
47f091 ¤   ¤   ¤   ¤   *r++ = '\\';
8248c1 ¤   ¤   ¤   ¤   *r++ = *p;
cea3a6 ¤   ¤   ¤   }
68cdcb ¤   ¤   ¤   break;
4aa2c6 ¤   ¤   case '"':
d76034 ¤   ¤   ¤   if ( state == INQUOTE )
7fa628 ¤   ¤   ¤   ¤   state = OUTQUOTE;
48bb8c ¤   ¤   ¤   else
7cec56 ¤   ¤   ¤   ¤   state = INQUOTE;
caaa20 ¤   ¤   ¤   *r++ = *p;
1acdcb ¤   ¤   ¤   break;
cf9804 ¤   ¤   case ';':
3f0c84 ¤   ¤   case ',':
c068c7 ¤   ¤   ¤   if ( state == OUTQUOTE )
b8c98d ¤   ¤   ¤   ¤   *r++ = ',';
80bb8c ¤   ¤   ¤   else
5e48c1 ¤   ¤   ¤   ¤   *r++ = *p;
e3cdcb ¤   ¤   ¤   break;
29d39e ¤   ¤   case '=':
626034 ¤   ¤   ¤   if ( state == INQUOTE )
b848c1 ¤   ¤   ¤   ¤   *r++ = *p;
eee543 ¤   ¤   ¤   else {
2c89b5 ¤   ¤   ¤   ¤   char¤   *rsave = r;
e8af5a
73e3e4 ¤   ¤   ¤   ¤   *r-- = '\0';
8ba588 ¤   ¤   ¤   ¤   while ( !isspace( *r ) && *r != ';'
bceb89 ¤   ¤   ¤   ¤   ····&& *r != ',' && r > ufn )
051f59 ¤   ¤   ¤   ¤   ¤   r--;
4433cb ¤   ¤   ¤   ¤   r++;
a2af5a
c012dd ¤   ¤   ¤   ¤   if ( strcasecmp( r, "c" )
e187cd ¤   ¤   ¤   ¤   ····&& strcasecmp( r, "o" )
f05bb9 ¤   ¤   ¤   ¤   ····&& strcasecmp( r, "ou" )
ea23b9 ¤   ¤   ¤   ¤   ····&& strcasecmp( r, "st" )
179a01 ¤   ¤   ¤   ¤   ····&& strcasecmp( r, "l" )
ad5f52 ¤   ¤   ¤   ¤   ····&& strcasecmp( r, "cn" ) ) {
2031e8 ¤   ¤   ¤   ¤   ¤   r = rsave;
ebbbc9 ¤   ¤   ¤   ¤   ¤   *r++ = '=';
fd2613 ¤   ¤   ¤   ¤   }
4ca3a6 ¤   ¤   ¤   }
0fcdcb ¤   ¤   ¤   break;
019ae3 ¤   ¤   default:
41aa20 ¤   ¤   ¤   *r++ = *p;
23cdcb ¤   ¤   ¤   break;
c80fe4 ¤   ¤   }
0f9371 ¤   }
0d85fa ¤   *r = '\0';
5baf5a
9cfa12 ¤   return( ufn );
0befe6 }
39af5a
8f2d52 char **
4e5e9f ldap_explode_dns( char *dn )
f9bb36 {
c63bd9 ¤   int¤ncomps, maxcomps;
9bfad9 ¤   char¤   *s;
108f40 ¤   char¤   **rdns;
b2af5a
d2abc3 ¤   if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) {
dbef86 ¤   ¤   return( NULL );
139371 ¤   }
--3cc5 000e48f0c484010009d Page 3 of getdn.c
e0af5a
c302ba ¤   maxcomps = 8;
4e1ed4 ¤   ncomps = 0;
eb0765 ¤   for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) {
d52478 ¤   ¤   if ( ncomps == maxcomps ) {
6fefc9 ¤   ¤   ¤   maxcomps *= 2;
469629 ¤   ¤   ¤   if ( (rdns = (char **) realloc( rdns, maxcomps *
395d3a ¤   ¤   ¤   ····sizeof(char *) )) == NULL ) {
d7b4bd ¤   ¤   ¤   ¤   return( NULL );
38a3a6 ¤   ¤   ¤   }
7b0fe4 ¤   ¤   }
89f075 ¤   ¤   rdns[ncomps++] = strdup( s );
a29371 ¤   }
3e8851 ¤   rdns[ncomps] = NULL;
72af5a
e0391c ¤   return( rdns );
8fefe6 }
01af5a
aa2d52 char **
c786f8 ldap_explode_dn( char *dn, int notypes )
48bb36 {
554e89 ¤   char¤   *p, *q, *rdnstart, **rdns = NULL;
a49d08 ¤   int¤state, count = 0, endquote, len;
29af5a
ce043f ¤   Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
c9af5a
9d9fd3 ¤   if ( ldap_is_dns_dn( dn ) ) {
c8a6f7 ¤   ¤   return( ldap_explode_dns( dn ) );
c09371 ¤   }
ceaf5a
74d376 ¤   rdnstart = dn;
d832d9 ¤   p = dn-1;
67dfc1 ¤   state = OUTQUOTE;
b3af5a
ce43ab ¤   do {
c8af5a
504992 ¤   ¤   ++p;
fb797d ¤   ¤   switch ( *p ) {
302e91 ¤   ¤   case '\\':
e8cc59 ¤   ¤   ¤   if ( *++p == '\0' )
55b800 ¤   ¤   ¤   ¤   p--;
0ccdcb ¤   ¤   ¤   break;
71a2c6 ¤   ¤   case '"':
686034 ¤   ¤   ¤   if ( state == INQUOTE )
a9a628 ¤   ¤   ¤   ¤   state = OUTQUOTE;
b4bb8c ¤   ¤   ¤   else
a4ec56 ¤   ¤   ¤   ¤   state = INQUOTE;
f8cdcb ¤   ¤   ¤   break;
9b9804 ¤   ¤   case ';':
a60c84 ¤   ¤   case ',':
c72041 ¤   ¤   case '\0':
9ca39b ¤   ¤   ¤   if ( state == OUTQUOTE ) {
baa6a1 ¤   ¤   ¤   ¤   ++count;
db0e20 ¤   ¤   ¤   ¤   if ( rdns == NULL ) {
3db427 ¤   ¤   ¤   ¤   ¤   if (( rdns = (char **)malloc( 8
152712 ¤   ¤   ¤   ¤   ¤   ¤   ·* sizeof( char *))) == NULL )
a1fa14 ¤   ¤   ¤   ¤   ¤   ¤   return( NULL );
d93ea9 ¤   ¤   ¤   ¤   } else if ( count >= 8 ) {
74b6bc ¤   ¤   ¤   ¤   ¤   if (( rdns = (char **)realloc( rdns,
732dbf ¤   ¤   ¤   ¤   ¤   ¤   (count+1) * sizeof( char *)))
de2864 ¤   ¤   ¤   ¤   ¤   ¤   == NULL )
1dfa14 ¤   ¤   ¤   ¤   ¤   ¤   return( NULL );
c22613 ¤   ¤   ¤   ¤   }
6e84ae ¤   ¤   ¤   ¤   rdns[ count ] = NULL;
9a297b ¤   ¤   ¤   ¤   endquote = 0;
a234d1 ¤   ¤   ¤   ¤   if ( notypes ) {
b670c7 ¤   ¤   ¤   ¤   ¤   for ( q = rdnstart;
f6ccb3 ¤   ¤   ¤   ¤   ¤   ····q < p && *q != '='; ++q ) {
d3c98a ¤   ¤   ¤   ¤   ¤   ¤   ;
611c89 ¤   ¤   ¤   ¤   ¤   }
0bd842 ¤   ¤   ¤   ¤   ¤   if ( q < p ) {
e4df16 ¤   ¤   ¤   ¤   ¤   ¤   rdnstart = ++q;
--0bb5 00109ab12964010009d Page 4 of getdn.c
b61c89 ¤   ¤   ¤   ¤   ¤   }
93df43 ¤   ¤   ¤   ¤   ¤   if ( *rdnstart == '"' ) {
f42012 ¤   ¤   ¤   ¤   ¤   ¤   ++rdnstart;
bd1c89 ¤   ¤   ¤   ¤   ¤   }
89ae30 ¤   ¤   ¤   ¤   ¤
c26ec3 ¤   ¤   ¤   ¤   ¤   if ( *(p-1) == '"' ) {
f5abdc ¤   ¤   ¤   ¤   ¤   ¤   endquote = 1;
1b4806 ¤   ¤   ¤   ¤   ¤   ¤   --p;
fe1c89 ¤   ¤   ¤   ¤   ¤   }
dd2613 ¤   ¤   ¤   ¤   }
0caf5a
88c3d1 ¤   ¤   ¤   ¤   len = p - rdnstart;
5479e5 ¤   ¤   ¤   ¤   if (( rdns[ count-1 ] = (char *)calloc( 1,
17b677 ¤   ¤   ¤   ¤   ····len + 1 )) != NULL ) {
20041a ¤   ¤   ¤   ¤   ····¤   SAFEMEMCPY( rdns[ count-1 ], rdnstart,
acc317 ¤   ¤   ¤   ¤   ¤   ····len );
cd8530 ¤   ¤   ¤   ¤   ¤   rdns[ count-1 ][ len ] = '\0';
c82613 ¤   ¤   ¤   ¤   }
ffaf5a
ff980e ¤   ¤   ¤   ¤   /*
292c44 ¤   ¤   ¤   ¤   ·* ·Don't forget to increment 'p' back to where
3412c4 ¤   ¤   ¤   ¤   ·* ·it should be. ·If we don't, then we will
1d15a7 ¤   ¤   ¤   ¤   ·* ·never get past an "end quote."
bf1020 ¤   ¤   ¤   ¤   ·*/
58b6cd ¤   ¤   ¤   ¤   if ( endquote == 1 )
259492 ¤   ¤   ¤   ¤   ¤   p++;
09af5a
0c1d76 ¤   ¤   ¤   ¤   rdnstart = *p ? p + 1 : p;
d60a87 ¤   ¤   ¤   ¤   while ( isspace( *rdnstart ))
e3abee ¤   ¤   ¤   ¤   ¤   ++rdnstart;
e7a3a6 ¤   ¤   ¤   }
b4cdcb ¤   ¤   ¤   break;
ef0fe4 ¤   ¤   }
f0efaf ¤   } while ( *p );
bfaf5a
67391c ¤   return( rdns );
b0efe6 }
34af5a
a4af5a
584d2f int
ffca5a ldap_is_dns_dn( char *dn )
8cbb36 {
bfa877 ¤   return( dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL &&
b62d85 ¤   ····strchr( dn, ',' ) == NULL );
f2efe6 }
2baf5a
dcaf5a
6e8c60 #if defined( ultrix ) || defined( NeXT )
c9af5a
4ccf78 char *strdup( char *s )
b4bb36 {
9315bd ¤   char¤   *p;
3aaf5a
db4116 ¤   if ( (p = (char *) malloc( strlen( s ) + 1 )) == NULL )
3cef86 ¤   ¤   return( NULL );
62af5a
18ee7f ¤   strcpy( p, s );
92af5a
762b43 ¤   return( p );
18efe6 }
e8af5a
09f205 #endif /* ultrix */
--b0b1 0002359a48a4010009e Page 1 of getdxbyname.c
294ae9 #ifdef LDAP_DNS
e038e5 /*
75e36d ·* ·Copyright (c) 1995 Regents of the University of Michigan.
cde4d4 ·* ·All rights reserved.
25775e ·*
4c227c ·* getdxbyname - retrieve DX records from the DNS (from TXT records for now)
e1495d ·*/
4ffeb2 #include <stdio.h>
85324c #include <string.h>
ddb1cb #include <ctype.h>
1aaf5a
36c583 #ifdef MACOS
04bea3 #include <stdlib.h>
bb65e0 #include "macos.h"
8fe962 #endif /* MACOS */
4aaf5a
f63faf #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
bbf15e #include <sys/types.h>
ca6c19 #include <netinet/in.h>
85a18e #include <arpa/nameser.h>
d0a394 #ifndef WIN32¤  ¤   /* marcd */
ac5d8c #include <sys/time.h>
f87454 #endif
e8f15e #include <sys/types.h>
6e66f2 #include <sys/socket.h>
572a51 #include <netdb.h>
60c222 #include <resolv.h>
c47454 #endif
5bb779 #include "lber.h"
7ee990 #include "ldap.h"
d8745c #include "ldap-int.h"
c5af5a
d11157 #if defined( DOS )
d9f2ef #include "msdos.h"
76bc39 #endif /* DOS */
faaf5a
ebaf5a
83504c #ifdef NEEDPROTOS
082e25 static char ** decode_answer( unsigned char *answer, int len );
b36133 #else /* NEEDPROTOS */
80e905 static char **decode_answer();
d28634 #endif /* NEEDPROTOS */
ccaf5a
654e34 extern int h_errno;
2691d4 extern char *h_errlist[];
35af5a
f7af5a
46f185 #define MAX_TO_SORT¤32
bcaf5a
daaf5a
5e38e5 /*
b45fb3 ·* getdxbyname - lookup DNS DX records for domain and return an ordered
00fc87 ·*¤ array.
da495d ·*/
c02d52 char **
aad97a getdxbyname( char *domain )
40bb36 {
e64b0a ····unsigned char¤  buf[ PACKETSZ ];
583e21 ····char¤   ¤   **dxs;
2e8297 ····int¤¤   ¤   rc;
09af5a
12e9da ····Debug( LDAP_DEBUG_TRACE, "getdxbyname( %s )\n", domain, 0, 0 );
9faf5a
3c0c6b ····memset( buf, 0, sizeof( buf ));
deaf5a
84dddf ····if (( rc = res_search( domain, C_IN, T_TXT, buf, sizeof( buf ))) < 0
3d084b ¤   ¤   || ( dxs = decode_answer( buf, rc )) == NULL ) {
d2d8af ¤   /*
ee85d5 ¤   ·* punt: ·return list conisting of the original domain name only
e2a4e3 ¤   ·*/
54633c ¤   if (( dxs = (char **)malloc( 2 * sizeof( char * ))) == NULL ||
2312fd ¤   ¤   ( dxs[ 0 ] = strdup( domain )) == NULL ) {
--4291 000de9c91104010009e Page 2 of getdxbyname.c
8c3b79 ¤   ····if ( dxs != NULL ) {
99e538 ¤   ¤   free( dxs );
0cf372 ¤   ····}
a8cb1c ¤   ····dxs = NULL;
0ff037 ¤   } else {
7b9a04 ¤   ····dxs[ 1 ] = NULL;
fb9371 ¤   }
586fe7 ····}
69af5a
812ae6 ····return( dxs );
0defe6 }
0eaf5a
c2af5a
244515 static char **
656d56 decode_answer( unsigned char *answer, int len )
13bb36 {
9dfd99 ····HEADER¤ ¤   *hp;
1e7748 ····char¤   ¤   buf[ 256 ], **dxs;
33abc3 ····unsigned char¤  *eom, *p;
78702f ····int¤¤   ¤   ancount, err, rc, type, class, dx_count, rr_len;
45ebe5 ····int¤¤   ¤   dx_pref[ MAX_TO_SORT ];
5baf5a
192639 #ifdef LDAP_DEBUG
f1072a ····if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
bae61b /*¤ __p_query( answer );¤   /* */
c86fe7 ····}
f19b45 #endif /* LDAP_DEBUG */
1aaf5a
6f5c6f ····dxs = NULL;
fc3e66 ····hp = (HEADER *)answer;
5a04ca ····eom = answer + len;
c7af5a
88ad59 ····if ( PGPNetToHostShort( hp->qdcount ) != 1 ) {
17dbba ¤   h_errno = NO_RECOVERY;
559572 ¤   return( NULL );
746fe7 ····}
39af5a
68e219 ····ancount = PGPNetToHostShort( hp->ancount );
1e5536 ····if ( ancount < 1 ) {
b445fb ¤   h_errno = NO_DATA;
df9572 ¤   return( NULL );
af6fe7 ····}
88af5a
ad29ec ····/*
ae18cc ·····* skip over the query
15d48d ·····*/
73ba89 ····p = answer + HFIXEDSZ;
99fbe2 ····if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
e1dbba ¤   h_errno = NO_RECOVERY;
539572 ¤   return( NULL );
696fe7 ····}
e5f424 ····p += ( rc + QFIXEDSZ );
cbaf5a
fc29ec ····/*
c54287 ·····* pull out the answers we are interested in
1ed48d ·····*/
7c4dfc ····err = dx_count = 0;
c4730a ····while ( ancount > 0 && err == 0 && p < eom ) {
715860 ¤   if (( rc = dn_expand( answer, eom, p, buf, sizeof( buf ))) < 0 ) {
adf938 ¤   ····err = NO_RECOVERY;
38868f ¤   ····continue;
919371 ¤   }
51651e ¤   p += rc;¤   /* skip over name */
a5bd19 ¤   type = _getshort( p );
8f6305 ¤   p += INT16SZ;
fa1610 ¤   class = _getshort( p );
a56305 ¤   p += INT16SZ;
fec4f2 ¤   p += INT32SZ;¤  ¤   /* skip over TTL */
567586 ¤   rr_len = _getshort( p );
d56305 ¤   p += INT16SZ;
a9fb79 ¤   if ( class == C_IN && type == T_TXT ) {
de0dcb ¤   ····int ¤   i, n, pref, txt_len;
--ec67 000eec0d6094010009e Page 3 of getdxbyname.c
7c75b4 ¤   ····char¤   *q, *r;
24af5a
a29c90 ¤   ····q = (char *)p;
de9d7e ¤   ····while ( q < (char *)p + rr_len && err == 0 ) {
001285 ¤   ¤   if ( *q >= 3 && strncasecmp( q + 1, "dx:", 3 ) == 0 ) {
28ef52 ¤   ¤   ····txt_len = *q - 3;
110ecf ¤   ¤   ····r = q + 4;
bd100c ¤   ¤   ····while ( isspace( *r )) {
cd49bb ¤   ¤   ¤   ++r;
d60a39 ¤   ¤   ¤   --txt_len;
d35f30 ¤   ¤   ····}
548365 ¤   ¤   ····pref = 0;
5e341c ¤   ¤   ····while ( isdigit( *r )) {
e03aea ¤   ¤   ¤   pref *= 10;
3ac320 ¤   ¤   ¤   pref += ( *r - '0' );
6249bb ¤   ¤   ¤   ++r;
210a39 ¤   ¤   ¤   --txt_len;
3e5f30 ¤   ¤   ····}
94816b ¤   ¤   ····if ( dx_count < MAX_TO_SORT - 1 ) {
8c6208 ¤   ¤   ¤   dx_pref[ dx_count ] = pref;
905f30 ¤   ¤   ····}
78100c ¤   ¤   ····while ( isspace( *r )) {
1549bb ¤   ¤   ¤   ++r;
e40a39 ¤   ¤   ¤   --txt_len;
335f30 ¤   ¤   ····}
ec3fc0 ¤   ¤   ····if ( dx_count == 0 ) {
a8519f ¤   ¤   ¤   dxs = (char **)malloc( 2 * sizeof( char * ));
f89e63 ¤   ¤   ····} else {
899abe ¤   ¤   ¤   dxs = (char **)realloc( dxs,
8330ab ¤   ¤   ¤   ¤   ( dx_count + 2 ) * sizeof( char * ));
6b5f30 ¤   ¤   ····}
1eb370 ¤   ¤   ····if ( dxs == NULL || ( dxs[ dx_count ] =
7b7bf9 ¤   ¤   ¤   ¤   (char *)calloc( 1, txt_len + 1 )) == NULL ) {
5ae2e3 ¤   ¤   ¤   err = NO_RECOVERY;
0c17f5 ¤   ¤   ¤   continue;
315f30 ¤   ¤   ····}
630a2b ¤   ¤   ····memcpy( dxs[ dx_count ], r, txt_len );
1c244c ¤   ¤   ····dxs[ ++dx_count ] = NULL;
860fe4 ¤   ¤   }
4bc8fd ¤   ¤   q += ( *q + 1 );¤   /* move past last TXT record */
06f372 ¤   ····}
c79371 ¤   }
20dfe0 ¤   p += rr_len;
1e6fe7 ····}
6faf5a
129e6f ····if ( err == 0 ) {
bebfb6 ¤   if ( dx_count == 0 ) {
8393a5 ¤   ····err = NO_DATA;
cbf037 ¤   } else {
2aea54 ¤   ····/*
6745ae ¤   ·····* sort records based on associated preference value
6ded8d ¤   ·····*/
eaf888 ¤   ····int¤¤   i, j, sort_count, tmp_pref;
2b2ea7 ¤   ····char¤   *tmp_dx;
92af5a
dac969 ¤   ····sort_count = ( dx_count < MAX_TO_SORT ) ? dx_count : MAX_TO_SORT;
085680 ¤   ····for ( i = 0; i < sort_count; ++i ) {
58ae61 ¤   ¤   for ( j = i + 1; j < sort_count; ++j ) {
72640b ¤   ¤   ····if ( dx_pref[ i ] > dx_pref[ j ] ) {
3a6178 ¤   ¤   ¤   tmp_pref = dx_pref[ i ];
c2b37f ¤   ¤   ¤   dx_pref[ i ] = dx_pref[ j ];
b19fc1 ¤   ¤   ¤   dx_pref[ j ] = tmp_pref;
b4bb04 ¤   ¤   ¤   tmp_dx = dxs[ i ];
b5730b ¤   ¤   ¤   dxs[ i ] = dxs[ j ];
da8d07 ¤   ¤   ¤   dxs[ j ] = tmp_dx;
2b5f30 ¤   ¤   ····}
040fe4 ¤   ¤   }
67f372 ¤   ····}
d29371 ¤   }
136fe7 ····}
3aaf5a
ee61ad ····h_errno = err;
--7086 001edd367874010009e Page 4 of getdxbyname.c
8e2ae6 ····return( dxs );
6fefe6 }
aaaf5a
ed1845 #endif /* LDAP_DNS */
--abbb 00092577b164010009f Page 1 of getentry.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
96ef53 ·* ·getentry.c
10495d ·*/
76af5a
010c68 #ifndef lint·
a807d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
f03efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
7f7454 #endif
9baf5a
0dfeb2 #include <stdio.h>
24b1cb #include <ctype.h>
b5324c #include <string.h>
24af5a
b524c3 #if PGPSOCKETSLDAP¤ /* jason */
5165aa #include "pgpSocketsLDAP.h"
98af5a
fddb21 #else
79c583 #ifdef MACOS
1bbea3 #include <stdlib.h>
0f65e0 #include "macos.h"
906c94 #else /* MACOS */
ebfdef #if defined( DOS ) || defined( _WIN32 )
785e84 #include <malloc.h>
9501b0 #ifdef DOS
e0f2ef #include "msdos.h"
167454 #endif
6eaad8 #else /* DOS */
84f15e #include <sys/types.h>
1866f2 #include <sys/socket.h>
77bc39 #endif /* DOS */
ede962 #endif /* MACOS */
d1df0f #endif /* PGPSOCKETSLDAP */
9daf5a
f6b779 #include "lber.h"
79e990 #include "ldap.h"
a9af5a
fa0873 /* ARGSUSED */
c8af61 LDAPMessage *
54565e ldap_first_entry( LDAP *ld, LDAPMessage *chain )
fdbb36 {
709e79 ¤   (void) ld;
8767c5 ¤
bd484d ¤   return( chain == NULLMSG || chain->lm_msgtype == LDAP_RES_SEARCH_RESULT
e1deda ¤   ····? NULLMSG : chain );
1befe6 }
15af5a
410873 /* ARGSUSED */
104ade LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry )
22bb36 {
329e79 ¤   (void) ld;
6467c5 ¤
6ed475 ¤   if ( entry == NULLMSG || entry->lm_chain == NULLMSG
dceb86 ¤   ····|| entry->lm_chain->lm_msgtype == LDAP_RES_SEARCH_RESULT )
fa85ea ¤   ¤   return( NULLMSG );
77af5a
af9469 ¤   return( entry->lm_chain );
2eefe6 }
20af5a
2a0873 /* ARGSUSED */
474d2f int
6a2df6 ldap_count_entries( LDAP *ld, LDAPMessage *chain )
afbb36 {
9b1426 ¤   int¤i;
b1af5a
c49e79 ¤   (void) ld;
ab67c5 ¤
6d61ac ¤   for ( i = 0; chain != NULL && chain->lm_msgtype
1a4412 ¤   ····!= LDAP_RES_SEARCH_RESULT; chain = chain->lm_chain )
92347d ¤   ¤   i++;
--7a48 0012aa7501a4010009f Page 2 of getentry.c
e0af5a
acce67 ¤   return( i );
2aefe6 }
--efae 000abdb21c7401000a0 Page 1 of getfilter.c
bc38e5 /*
41bdac ·* ·Copyright (c) 1993 Regents of the University of Michigan.
c7e4d4 ·* ·All rights reserved.
d1775e ·*
2d98a0 ·* ·getfilter.c -- optional add-on to libldap
84495d ·*/
72af5a
4b0c68 #ifndef lint·
9066c6 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University "
7e3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
a47454 #endif
06af5a
8cfeb2 #include <stdio.h>
b4324c #include <string.h>
9db1cb #include <ctype.h>
c2af5a
9524c3 #if PGPSOCKETSLDAP¤ /* jason */
6465aa #include "pgpSocketsLDAP.h"
51af5a
21db21 #else
0ed7c9 #if defined(NeXT)
45748e #include <regex.h>
747454 #endif
00c583 #ifdef MACOS
27bea3 #include <stdlib.h>
2c65e0 #include "macos.h"
ab6c94 #else /* MACOS */
a32664 #ifdef WIN32
dd495d #include <errno.h>
447454 #endif
68af69 #if defined(DOS) || defined(WIN32)
6c5e84 #include <malloc.h>
0801b0 #ifdef DOS
85f2ef #include "msdos.h"
ce7454 #endif
36aad8 #else /* DOS */
1df15e #include <sys/types.h>
5109b0 #include <sys/file.h>
cebea3 #include <stdlib.h>
c03db5 #include <sys/errno.h>
d6ea1a #ifndef VMS
a817c2 #include <unistd.h>
d1361d #endif /* VMS */
1cbc39 #endif /* DOS */
f6e962 #endif /* MACOS */
85df0f #endif /* PGPSOCKETSLDAP */
18af5a
0bb779 #include "lber.h"
bfe990 #include "ldap.h"
a21b16 #include "regex.h"
99af5a
d3504c #ifdef NEEDPROTOS
a5764a static int break_into_words( char *str, char *delims, char ***wordsp );
1bec27 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
e4d559 void free_strarray( char **sap );
426133 #else /* NEEDPROTOS */
aad627 static int break_into_words();
4e9e1d int next_line_tokens();
bc40f5 void free_strarray();
298634 #endif /* NEEDPROTOS */
fbaf5a
1fafd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
0b1851 extern int¤ errno;
0ee755 extern char¤*re_comp();
b27454 #endif
56af5a
7c0974 #define FILT_MAX_LINE_LEN¤  1024
08af5a
59c4f9 LDAPFiltDesc *
780062 ldap_init_getfilter( char *fname )
3ebb36 {
ab362f ····FILE¤   ¤   *fp;
--5fe7 000e2137e06401000a0 Page 2 of getfilter.c
5fa3ff ····char¤   ¤   *buf;
63ab0f ····long¤   ¤   rlen, len;
5ffac7 ····int ¤   ¤   eof;
7053df ····LDAPFiltDesc¤   *lfdp;
dcaf5a
efe76f ····if (( fp = fopen( fname, "r" )) == NULL ) {
eb9572 ¤   return( NULL );
906fe7 ····}
69af5a
68ba4a ····if ( fseek( fp, 0L, SEEK_END ) != 0 ) {¤/* move to end to get len */
ae5261 ¤   fclose( fp );
e09572 ¤   return( NULL );
6e6fe7 ····}
47af5a
527c74 ····len = ftell( fp );
a6af5a
258486 ····if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {¤/* back to start of file */
855261 ¤   fclose( fp );
659572 ¤   return( NULL );
276fe7 ····}
dcaf5a
43d046 ····if (( buf = malloc( (size_t)len )) == NULL ) {
9b5261 ¤   fclose( fp );
fb9572 ¤   return( NULL );
ef6fe7 ····}
9daf5a
d4d0ba ····rlen = fread( buf, 1, (size_t)len, fp );
217a1f ····eof = feof( fp );
a0c09a ····fclose( fp );
afaf5a
5370f9 ····if ( rlen != len && !eof ) {¤   /* error: ·didn't get the whole file */
2e5bb5 ¤   free( buf );
0e9572 ¤   return( NULL );
3b6fe7 ····}
1eaf5a
48af5a
2c860a ····lfdp = ldap_init_getfilter_buf( buf, rlen );
3a1943 ····free( buf );
a3af5a
c97e2b ····return( lfdp );
efefe6 }
79af5a
83af5a
2ac4f9 LDAPFiltDesc *
776794 ldap_init_getfilter_buf( char *buf, long buflen )
39bb36 {
e153df ····LDAPFiltDesc¤   *lfdp;
c7b601 ····LDAPFiltList¤   *flp, *nextflp;
51934b ····LDAPFiltInfo¤   *fip, *nextfip;
717192 ····char¤   ¤   *tag, **tok;
a1b8f7 ····int¤¤   ¤   tokcnt, i;
adaf5a
d3d380 ····if (( lfdp = (LDAPFiltDesc *)calloc( 1, sizeof( LDAPFiltDesc))) == NULL ) {
029572 ¤   return( NULL );
466fe7 ····}
16af5a
a12683 ····flp = nextflp = NULL;
c20e69 ····fip = NULL;
8eb307 ····tag = NULL;
b4af5a
a52dec ····while ( buflen > 0 && ( tokcnt = next_line_tokens( &buf, &buflen, &tok ))
b843b4 ¤   ····> 0 ) {
22af5a
ff7b7d ¤   switch( tokcnt ) {
96a62f ¤   case 1:¤¤   /* tag line */
2c0423 ¤   ····if ( tag != NULL ) {
c6ae62 ¤   ¤   free( tag );
fdf372 ¤   ····}
474ab2 ¤   ····tag = tok[ 0 ];
53a206 ¤   ····free( tok );
a8cafa ¤   ····break;
e29b0e ¤   case 4:
--dd99 0001cd2f28d401000a0 Page 3 of getfilter.c
c2a3fa ¤   case 5:¤¤   /* start of filter info. list */
3eb2cf ¤   ····if (( nextflp = (LDAPFiltList *)calloc( 1, sizeof( LDAPFiltList )))
8c468f ¤   ¤   ····== NULL ) {
d3a687 ¤   ¤   ldap_getfilter_free( lfdp );
0fef86 ¤   ¤   return( NULL );
0ff372 ¤   ····}
885ab8 ¤   ····nextflp->lfl_tag = strdup( tag );
1ec608 ¤   ····nextflp->lfl_pattern = tok[ 0 ];
4b470d ¤   ····if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
3f4eeb #ifndef NO_USERINTERFACE
a7a687 ¤   ¤   ldap_getfilter_free( lfdp );
1785c6 ¤   ¤   fprintf( stderr, "bad regular expresssion %s\n",
e6e96c ¤   ¤   ¤   nextflp->lfl_pattern );
60afd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
7c6644 ¤   ¤   errno = EINVAL;
b57454 #endif
8400a6 #endif /* NO_USERINTERFACE */
7c7f00 ¤   ¤   free_strarray( tok );
11ef86 ¤   ¤   return( NULL );
6ef372 ¤   ····}
cb1b52 ¤   ¤
287b6f ¤   ····nextflp->lfl_delims = tok[ 1 ];
38d91f ¤   ····nextflp->lfl_ilist = NULL;
582b74 ¤   ····nextflp->lfl_next = NULL;
41d05a ¤   ····if ( flp == NULL ) {¤   /* first one */
98fb84 ¤   ¤   lfdp->lfd_filtlist = nextflp;
5edfe8 ¤   ····} else {
ee5601 ¤   ¤   flp->lfl_next = nextflp;
e8f372 ¤   ····}
a4561c ¤   ····flp = nextflp;
3a991a ¤   ····fip = NULL;
14bead ¤   ····for ( i = 2; i < 5; ++i ) {
b9f6a7 ¤   ¤   tok[ i - 2 ] = tok[ i ];
85f372 ¤   ····}
1137a2 ¤   ····/* fall through */
acaf5a
904dd7 ¤   case 2:
f4339f ¤   case 3:¤¤   /* filter, desc, and optional search scope */
1a0de4 ¤   ····if ( nextflp != NULL ) { /* add to info list */
f1062b ¤   ¤   if (( nextfip = (LDAPFiltInfo *)calloc( 1,
e8c41f ¤   ¤   ¤   sizeof( LDAPFiltInfo ))) == NULL ) {
ddcc41 ¤   ¤   ····ldap_getfilter_free( lfdp );
afa890 ¤   ¤   ····free_strarray( tok );
da36d8 ¤   ¤   ····return( NULL );
1c0fe4 ¤   ¤   }
eb3e63 ¤   ¤   if ( fip == NULL ) {¤   /* first one */
bcf62d ¤   ¤   ····nextflp->lfl_ilist = nextfip;
0045a6 ¤   ¤   } else {
429e11 ¤   ¤   ····fip->lfi_next = nextfip;
930fe4 ¤   ¤   }
aefcd6 ¤   ¤   fip = nextfip;
dda38d ¤   ¤   nextfip->lfi_next = NULL;
5b174b ¤   ¤   nextfip->lfi_filter = tok[ 0 ];
24c06d ¤   ¤   nextfip->lfi_desc = tok[ 1 ];
c55b9d ¤   ¤   if ( tok[ 2 ] != NULL ) {
cb6fe2 ¤   ¤   ····if ( strcasecmp( tok[ 2 ], "subtree" ) == 0 ) {
6779bd ¤   ¤   ¤   nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;
fc2d5a ¤   ¤   ····} else if ( strcasecmp( tok[ 2 ], "onelevel" ) == 0 ) {
243f92 ¤   ¤   ¤   nextfip->lfi_scope = LDAP_SCOPE_ONELEVEL;
9491ac ¤   ¤   ····} else if ( strcasecmp( tok[ 2 ], "base" ) == 0 ) {
b6cc59 ¤   ¤   ¤   nextfip->lfi_scope = LDAP_SCOPE_BASE;
a09e63 ¤   ¤   ····} else {
ef4808 ¤   ¤   ¤   free_strarray( tok );
89a36a ¤   ¤   ¤   ldap_getfilter_free( lfdp );
76afd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
bb9021 ¤   ¤   ¤   errno = EINVAL;
297454 #endif
6719e3 ¤   ¤   ¤   return( NULL );
c35f30 ¤   ¤   ····}
dfcbe0 ¤   ¤   ····free( tok[ 2 ] );
98c10b ¤   ¤   ····tok[ 2 ] = NULL;
1c45a6 ¤   ¤   } else {
--de52 0001e80022f401000a0 Page 4 of getfilter.c
774c8a ¤   ¤   ····nextfip->lfi_scope = LDAP_SCOPE_SUBTREE;¤   /* default */
db0fe4 ¤   ¤   }
17d175 ¤   ¤   nextfip->lfi_isexact = ( strchr( tok[ 0 ], '*' ) == NULL &&
0b0e18 ¤   ¤   ¤   strchr( tok[ 0 ], '~' ) == NULL );
a8e0f0 ¤   ¤   free( tok );
96f372 ¤   ····}
24cafa ¤   ····break;
25af5a
f32f72 ¤   default:
4f9f98 ¤   ····free_strarray( tok );
9ec9ac ¤   ····ldap_getfilter_free( lfdp );
84afd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
98497f ¤   ····errno = EINVAL;
ca7454 #endif
f2c0bd ¤   ····return( NULL );
849371 ¤   }
5a6fe7 ····}
3daf5a
ba307e ····if ( tag != NULL ) {
1eefe9 ¤   free( tag );
de6fe7 ····}
59af5a
587e2b ····return( lfdp );
47efe6 }
0aaf5a
55af5a
6b314a void
ed281f ldap_setfilteraffixes( LDAPFiltDesc *lfdp, char *prefix, char *suffix )
90bb36 {
61dcc9 ····if ( lfdp->lfd_filtprefix != NULL ) {
591572 ¤   free( lfdp->lfd_filtprefix );
286fe7 ····}
fb4aca ····lfdp->lfd_filtprefix = ( prefix == NULL ) ? NULL : strdup( prefix );
abaf5a
b1ab85 ····if ( lfdp->lfd_filtsuffix != NULL ) {
ce0229 ¤   free( lfdp->lfd_filtsuffix );
5e6fe7 ····}
f09ee5 ····lfdp->lfd_filtsuffix = ( suffix == NULL ) ? NULL : strdup( suffix );
daefe6 }
62af5a
91af5a
8bc2b3 LDAPFiltInfo *
19e7c3 ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
34bb36 {
cba361 ····LDAPFiltList¤   *flp;
85af5a
ec3790 ····if ( lfdp->lfd_curvalcopy != NULL ) {
a0a0cd ¤   free( lfdp->lfd_curvalcopy );
d33c2c ¤   free( lfdp->lfd_curvalwords );
676fe7 ····}
f3af5a
1ce5c4 ····lfdp->lfd_curval = value;
569b1a ····lfdp->lfd_curfip = NULL;
04af5a
87e0b8 ····for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
d91b46 ¤   if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
94eb45 ¤   ¤   && re_comp( flp->lfl_pattern ) == NULL
4a73e2 ¤   ¤   && re_exec( lfdp->lfd_curval ) == 1 ) {
5a7d7f ¤   ····lfdp->lfd_curfip = flp->lfl_ilist;
85cafa ¤   ····break;
629371 ¤   }
3a6fe7 ····}
b8af5a
4f5a68 ····if ( lfdp->lfd_curfip == NULL ) {
509572 ¤   return( NULL );
cc6fe7 ····}
58af5a
fd9a47 ····if (( lfdp->lfd_curvalcopy = strdup( value )) == NULL ) {
b19572 ¤   return( NULL );
ea6fe7 ····}
d6af5a
1e0333 ····if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims,
--6d70 00090e90494401000a0 Page 5 of getfilter.c
dc3c52 ¤   ¤   &lfdp->lfd_curvalwords ) < 0 ) {
68a0cd ¤   free( lfdp->lfd_curvalcopy );
2250ea ¤   lfdp->lfd_curvalcopy = NULL;
ed9572 ¤   return( NULL );
2f6fe7 ····}
d9af5a
b420d4 ····return( ldap_getnextfilter( lfdp ));
49efe6 }
c9af5a
14af5a
94c2b3 LDAPFiltInfo *
439592 ldap_getnextfilter( LDAPFiltDesc *lfdp )
0abb36 {
9efe81 ····LDAPFiltInfo¤   *fip;
48af5a
fcba69 ····fip = lfdp->lfd_curfip;
f8af5a
de68a7 ····if ( fip == NULL ) {
209572 ¤   return( NULL );
ab6fe7 ····}
4daf5a
335546 ····lfdp->lfd_curfip = fip->lfi_next;
2eaf5a
cfb01b ····ldap_build_filter( lfdp->lfd_filter, LDAP_FILT_MAXSIZ, fip->lfi_filter,
1a28ac ¤   ····lfdp->lfd_filtprefix, lfdp->lfd_filtsuffix, NULL,
5d980a ¤   ····lfdp->lfd_curval, lfdp->lfd_curvalwords );
5b0628 ····lfdp->lfd_retfi.lfi_filter = lfdp->lfd_filter;
228e9c ····lfdp->lfd_retfi.lfi_desc = fip->lfi_desc;
e607e6 ····lfdp->lfd_retfi.lfi_scope = fip->lfi_scope;
1ad2e7 ····lfdp->lfd_retfi.lfi_isexact = fip->lfi_isexact;
a7af5a
b53e0c ····return( &lfdp->lfd_retfi );
d2efe6 }
51af5a
09af5a
b5314a void
591086 ldap_build_filter( char *filtbuf, unsigned long buflen, char *pattern,
b51a0e ¤   char *prefix, char *suffix, char *attr, char *value, char **valwords )
52bb36 {
f1595a ¤   char¤   *p, *f;
bf7a77 ¤   size_t¤ slen;
e45294 ¤   int¤i, wordcount, wordnum, endwordnum;
1667c5 ¤
d6b245 ¤   if ( valwords == NULL ) {
dbca83 ¤   ····wordcount = 0;
33f037 ¤   } else {
108d82 ¤   ····for ( wordcount = 0; valwords[ wordcount ] != NULL; ++wordcount ) {
281d52 ¤   ¤   ;
b3f372 ¤   ····}
3d9371 ¤   }
0baf5a
ce7a32 ¤   f = filtbuf;
70af5a
063796 ¤   if ( prefix != NULL ) {
2e657d ¤   ····strcpy( f, prefix );
474855 ¤   ····f += strlen( prefix );
359371 ¤   }
35af5a
e9d295 ¤   for ( p = pattern; *p != '\0'; ++p ) {
255b80 ¤   ····if ( *p == '%' ) {
6d4992 ¤   ¤   ++p;
848ed2 ¤   ¤   if ( *p == 'v' ) {
6f5272 ¤   ¤   ····if ( isdigit( *(p+1))) {
aefc03 ¤   ¤   ¤   ++p;
4f584d ¤   ¤   ¤   wordnum = *p - '1';
908065 ¤   ¤   ¤   if ( *(p+1) == '-' ) {
403780 ¤   ¤   ¤   ····++p;
df579f ¤   ¤   ¤   ····if ( isdigit( *(p+1))) {
10bd88 ¤   ¤   ¤   ¤   ++p;
5f4c10 ¤   ¤   ¤   ¤   endwordnum = *p - '1';¤ /* e.g., "%v2-4" */
653dec ¤   ¤   ¤   ¤   if ( endwordnum > wordcount - 1 ) {
9045d3 ¤   ¤   ¤   ¤   ····endwordnum = wordcount - 1;
--26c9 0001396e31a401000a0 Page 6 of getfilter.c
862613 ¤   ¤   ¤   ¤   }
2f2fb2 ¤   ¤   ¤   ····} else {
d38f1e ¤   ¤   ¤   ¤   endwordnum = wordcount - 1; ·/* e.g., "%v2-" */
89da85 ¤   ¤   ¤   ····}
91042d ¤   ¤   ¤   } else {
b498f6 ¤   ¤   ¤   ····endwordnum = wordnum;¤  /* e.g., "%v2" */
1ba3a6 ¤   ¤   ¤   }
4eaf5a
2230e6 ¤   ¤   ¤   if ( wordcount > 0 ) {
ef10b2 ¤   ¤   ¤   ····for ( i = wordnum; i <= endwordnum; ++i ) {
3918fa ¤   ¤   ¤   ¤   if ( i > wordnum ) { ·/* add blank btw words */
b22eb7 ¤   ¤   ¤   ¤   ····*f++ = ' ';
072613 ¤   ¤   ¤   ¤   }
911e38 ¤   ¤   ¤   ¤   slen = strlen( valwords[ i ] );
e98e84 ¤   ¤   ¤   ¤   SAFEMEMCPY( f, valwords[ i ], slen );
b94634 ¤   ¤   ¤   ¤   f += slen;
61da85 ¤   ¤   ¤   ····}
b6a3a6 ¤   ¤   ¤   }
de054e ¤   ¤   ····} else if ( *(p+1) == '$' ) {
29fc03 ¤   ¤   ¤   ++p;
c430e6 ¤   ¤   ¤   if ( wordcount > 0 ) {
a05e49 ¤   ¤   ¤   ····wordnum = wordcount - 1;
3dfde4 ¤   ¤   ¤   ····slen = strlen( valwords[ wordnum ] );
93344a ¤   ¤   ¤   ····SAFEMEMCPY( f, valwords[ wordnum ], slen );
bea191 ¤   ¤   ¤   ····f += slen;
b5a3a6 ¤   ¤   ¤   }
94fa0f ¤   ¤   ····} else if ( value != NULL ) {
521b35 ¤   ¤   ¤   slen = strlen( value );
8a484f ¤   ¤   ¤   SAFEMEMCPY( f, value, slen );
37a4d5 ¤   ¤   ¤   f += slen;
0e5f30 ¤   ¤   ····}
433727 ¤   ¤   } else if ( *p == 'a' && attr != NULL ) {
8f477d ¤   ¤   ····slen = strlen( attr );
5fa8e1 ¤   ¤   ····SAFEMEMCPY( f, attr, slen );
744370 ¤   ¤   ····f += slen;
2645a6 ¤   ¤   } else {
7b2f4b ¤   ¤   ····*f++ = *p;
590fe4 ¤   ¤   }
abdfe8 ¤   ····} else {
68f307 ¤   ¤   *f++ = *p;
dbf372 ¤   ····}
151b52 ¤   ¤
56de97 ¤   ····if ( (unsigned long) (f - filtbuf) > buflen ) {
f78f5a ¤   ¤   /* sanity check */
ad6adc ¤   ¤   --f;
642f68 ¤   ¤   break;
a2f372 ¤   ····}
7a9371 ¤   }
5daf5a
b08f0f ¤   if ( suffix != NULL && (unsigned long) ( f - filtbuf ) < buflen ) {
5c7226 ¤   ····strcpy( f, suffix );
6ff037 ¤   } else {
dfe232 ¤   ····*f = '\0';
cc9371 ¤   }
5defe6 }
e6af5a
33af5a
c9beb7 static int
3bdaf2 break_into_words( char *str, char *delims, char ***wordsp )
40bb36 {
4a2745 ····char¤   *word, **words;
a21690 ····int¤¤   count;
b767c5 ¤
14ef5d ····if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) {
167360 ¤   return( -1 );
7f6fe7 ····}
4edfb9 ····count = 0;
8a53ee ····words[ count ] = NULL;
51af5a
65156d ····word = strtok( str, delims );
90d409 ····while ( word != NULL ) {
137bff ¤   if (( words = (char **)realloc( words,
--4c77 001d268ab4d401000a0 Page 7 of getfilter.c
5fae87 ¤   ¤   ( count + 2 ) * sizeof( char * ))) == NULL ) {
e7db01 ¤   ····return( -1 );
689371 ¤   }
87af5a
f0165c ¤   words[ count ] = word;
b564e9 ¤   words[ ++count ] = NULL;
9d19d8 ¤   word = strtok( NULL, delims );
5f6fe7 ····}
3c67c5 ¤
cb7235 ····*wordsp = words;
9e6596 ····return( count );
d2efe6 }
--00e3 0008dcc334d401000a1 Page 1 of getopt.c
bc38e5 /*
4226c0 ·*¤ getopt.c
87495d ·*/
2aaf5a
816cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
025e5d #if defined( BSD )
abf7c3 #include <strings.h>
5edb21 #else
c3324c #include <string.h>
7a7454 #endif
c4af5a
338955 /* LINTLIBRARY */
a77b3f #define EOF¤(-1)
5bd7ea #define ERR(s, c)¤  if(opterr) {\
1c404f ¤   ¤   ¤   ¤   ¤   ¤   extern int write();\
d9b2ce ¤   ¤   ¤   ¤   ¤   ¤   char errbuf[2];\
5d86eb ¤   ¤   ¤   ¤   ¤   ¤   errbuf[0] = c; errbuf[1] = '\n';\
284ffa ¤   ¤   ¤   ¤   ¤   ¤   (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
9fe950 ¤   ¤   ¤   ¤   ¤   ¤   (void) write(2, s, (unsigned)strlen(s));\
2ae2b8 ¤   ¤   ¤   ¤   ¤   ¤   (void) write(2, errbuf, 2);}
bcaf5a
57af5a
2fdf8c int¤¤   opterr = 1;
1d12bd int¤¤   optind = 1;
ba8a9a int¤¤   optopt;
7ad4bc char¤   *optarg;
fdaf5a
f45dbc int getopt( int argc, char **argv, char *opts)
3fbb36 {
d6777f ¤   static¤ ¤   int¤¤   sp = 1;
8ab3db ¤   register¤   int¤¤   c;
7d008a ¤   register¤   char¤   *cp;
4aaf5a
c7d208 ¤   if ( sp == 1 )
67fd57 ¤   ¤   if ( optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0¶
2a9e70 ') {
a04a7f ¤   ¤   ¤   optind = 1;
4e6ff2 ¤   ¤   ¤   return( EOF );
8a0fe4 ¤   ¤   }
440e1d ¤   ¤   else
ff6139 ¤   ¤   ¤   if ( strcmp(argv[optind], "--") == 0 ) {
aebb24 ¤   ¤   ¤   ¤   optind++;
6c1021 ¤   ¤   ¤   ¤   return(EOF);
27a3a6 ¤   ¤   ¤   }
8aaf5a
6ccb3c ¤   optopt = c = argv[optind][sp];
d28e73 ¤   if (c == ':' || ( cp = strchr(opts, c) ) == NULL) {
ceffda ¤   ¤   ERR(": illegal option -- ", c);
6ee342 ¤   ¤   if ( argv[optind][++sp] == '\0' ) {
3d7c91 ¤   ¤   ¤   optind++;
852492 ¤   ¤   ¤   sp = 1;
550fe4 ¤   ¤   }
fd8ae6 ¤   ¤   return('?');
579371 ¤   }
8d8056 ¤   if (*++cp == ':') {
3fd43c ¤   ¤   if (argv[optind][sp+1] != '\0')
063e5a ¤   ¤   ¤   optarg = &argv[optind++][sp+1];
e76c22 ¤   ¤   else if (++optind >= argc) {
89cc55 ¤   ¤   ¤   ERR(": option requires an argument -- ", c);
e22492 ¤   ¤   ¤   sp = 1;
0c3b37 ¤   ¤   ¤   return('?');
474a5d ¤   ¤   } else
5f6c94 ¤   ¤   ¤   optarg = argv[optind++];
deb3e1 ¤   ¤   sp = 1;
6bf037 ¤   } else {
1cd4b5 ¤   ¤   if (argv[optind][++sp] == '\0') {
c22492 ¤   ¤   ¤   sp = 1;
847c91 ¤   ¤   ¤   optind++;
190fe4 ¤   ¤   }
4745fc ¤   ¤   optarg = NULL;
e19371 ¤   }
8d471d ¤   return(c);
--b480 00176ec3369401000a1 Page 2 of getopt.c
7aefe6 }
307454 #endif
76af5a
--75bf 000c6c9ecad401000a2 Page 1 of getvalues.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
66f6d3 ·* ·getvalues.c
3c495d ·*/
92af5a
bb0c68 #ifndef lint·
7b07d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
4f3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
a27454 #endif
69af5a
d7feb2 #include <stdio.h>
e4b1cb #include <ctype.h>
c9324c #include <string.h>
01af5a
1a24c3 #if PGPSOCKETSLDAP¤ /* jason */
c465aa #include "pgpSocketsLDAP.h"
78af5a
f4db21 #else
dec583 #ifdef MACOS
47bea3 #include <stdlib.h>
4365e0 #include "macos.h"
ae6c94 #else /* MACOS */
40fdef #if defined( DOS ) || defined( _WIN32 )
425e84 #include <malloc.h>
8601b0 #ifdef DOS
14f2ef #include "msdos.h"
117454 #endif
05aad8 #else /* DOS */
44f15e #include <sys/types.h>
7666f2 #include <sys/socket.h>
97bc39 #endif /* DOS */
d1e962 #endif /* MACOS */
38df0f #endif /* PGPSOCKETSLDAP */
3daf5a
40b779 #include "lber.h"
dee990 #include "ldap.h"
ccaf5a
b42d52 char **
6e183a ldap_get_values( LDAP *ld, LDAPMessage *entry, char *target )
8bbb36 {
ce28d5 ¤   BerElement¤ ber;
a05842 ¤   char¤   ¤   attr[LDAP_MAX_ATTR_LEN];
d37348 ¤   int¤¤   found = 0;
6bb0b9 ¤   long¤   ¤   len;
f5eba0 ¤   char¤   ¤   **vals;
87af5a
ffc115 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_get_values\n", 0, 0, 0 );
bbaf5a
3e0b8e ¤   ber = *entry->lm_ber;
dbaf5a
221b5e ¤   /* skip sequence, dn, sequence of, and snag the first attr */
8275dd ¤   len = sizeof(attr);
f11d41 ¤   if ( ber_scanf( &ber, "{x{{s", attr, &len ) == LBER_ERROR ) {
0f3108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
98ef86 ¤   ¤   return( NULL );
649371 ¤   }
71af5a
0af032 ¤   if ( strcasecmp( target, attr ) == 0 )
573e6e ¤   ¤   found = 1;
8baf5a
5bc6d0 ¤   /* break out on success, return out on error */
4cc52d ¤   while ( ! found ) {
0483b8 ¤   ¤   len = sizeof(attr);
6570ec ¤   ¤   if ( ber_scanf( &ber, "x}{s", attr, &len ) == LBER_ERROR ) {
e92958 ¤   ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
4319e3 ¤   ¤   ¤   return( NULL );
680fe4 ¤   ¤   }
56af5a
1e61aa ¤   ¤   if ( strcasecmp( target, attr ) == 0 )
c6cdcb ¤   ¤   ¤   break;
--b031 000c184678d401000a2 Page 2 of getvalues.c
a19371 ¤   }
93af5a
3c7869 ¤   /*·
8a0f23 ¤   ·* if we get this far, we've found the attribute and are sitting
615e67 ¤   ·* just before the set of values.
aea4e3 ¤   ·*/
deaf5a
85788c ¤   if ( ber_scanf( &ber, "[v]", &vals ) == LBER_ERROR ) {
513108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
2eef86 ¤   ¤   return( NULL );
0e9371 ¤   }
89af5a
35d737 ¤   return( vals );
2aefe6 }
cdaf5a
908665 struct berval **
62114f ldap_get_values_len( LDAP *ld, LDAPMessage *entry, char *target )
3dbb36 {
ae28d5 ¤   BerElement¤ ber;
d75842 ¤   char¤   ¤   attr[LDAP_MAX_ATTR_LEN];
b47348 ¤   int¤¤   found = 0;
21b0b9 ¤   long¤   ¤   len;
aa7116 ¤   struct berval¤  **vals;
68af5a
a29ebe ¤   Debug( LDAP_DEBUG_TRACE, "ldap_get_values_len\n", 0, 0, 0 );
81af5a
d00b8e ¤   ber = *entry->lm_ber;
ccaf5a
231b5e ¤   /* skip sequence, dn, sequence of, and snag the first attr */
4675dd ¤   len = sizeof(attr);
c61d41 ¤   if ( ber_scanf( &ber, "{x{{s", attr, &len ) == LBER_ERROR ) {
fe3108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
47ef86 ¤   ¤   return( NULL );
459371 ¤   }
c5af5a
aef032 ¤   if ( strcasecmp( target, attr ) == 0 )
4d3e6e ¤   ¤   found = 1;
52af5a
e3c6d0 ¤   /* break out on success, return out on error */
40c52d ¤   while ( ! found ) {
1c83b8 ¤   ¤   len = sizeof(attr);
1970ec ¤   ¤   if ( ber_scanf( &ber, "x}{s", attr, &len ) == LBER_ERROR ) {
f32958 ¤   ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
3d19e3 ¤   ¤   ¤   return( NULL );
680fe4 ¤   ¤   }
08af5a
7961aa ¤   ¤   if ( strcasecmp( target, attr ) == 0 )
1dcdcb ¤   ¤   ¤   break;
cc9371 ¤   }
c9af5a
017869 ¤   /*·
360f23 ¤   ·* if we get this far, we've found the attribute and are sitting
ad5e67 ¤   ·* just before the set of values.
c6a4e3 ¤   ·*/
21af5a
7d1f94 ¤   if ( ber_scanf( &ber, "[V]", &vals ) == LBER_ERROR ) {
293108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
cbef86 ¤   ¤   return( NULL );
7e9371 ¤   }
9faf5a
59d737 ¤   return( vals );
9befe6 }
81af5a
ad4d2f int
ce41d7 ldap_count_values( char **vals )
6ebb36 {
881426 ¤   int¤i;
77af5a
568126 ¤   if ( vals == NULL )
c2abea ¤   ¤   return( 0 );
49af5a
c13304 ¤   for ( i = 0; vals[i] != NULL; i++ )
--626d 00179f18147401000a2 Page 3 of getvalues.c
d3c78a ¤   ¤   ;¤  /* NULL */
a2af5a
11ce67 ¤   return( i );
38efe6 }
1aaf5a
8a4d2f int
cd4a48 ldap_count_values_len( struct berval **vals )
9abb36 {
f90917 ¤   return( ldap_count_values( (char **) vals ) );
a3efe6 }
34af5a
ab314a void
c134c3 ldap_value_free( char **vals )
95bb36 {
b71426 ¤   int¤i;
90af5a
4c8126 ¤   if ( vals == NULL )
6499bf ¤   ¤   return;
5d3304 ¤   for ( i = 0; vals[i] != NULL; i++ )
9ccfb0 ¤   ¤   free( vals[i] );
8cb9bb ¤   free( (char *) vals );
5cefe6 }
1caf5a
45314a void
14ef07 ldap_value_free_len( struct berval **vals )
23bb36 {
4d1426 ¤   int¤i;
d2af5a
438126 ¤   if ( vals == NULL )
1c99bf ¤   ¤   return;
33af0f ¤   for ( i = 0; vals[i] != NULL; i++ ) {
3533aa ¤   ¤   free( vals[i]->bv_val );
10cfb0 ¤   ¤   free( vals[i] );
459371 ¤   }
3bb9bb ¤   free( (char *) vals );
79efe6 }
--49bc 000dbabe401401000a3 Page 1 of kbind.c
bc38e5 /*
41bdac ·* ·Copyright (c) 1993 Regents of the University of Michigan.
c7e4d4 ·* ·All rights reserved.
d1775e ·*
bef3ca ·* ·kbind.c
64495d ·*/
2eaf5a
4f0c68 #ifndef lint·
2e66c6 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University "
683efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
887454 #endif
9faf5a
c55ffa #ifdef KERBEROS
35af5a
f5feb2 #include <stdio.h>
4a324c #include <string.h>
68af5a
c3c583 #ifdef MACOS
d0bea3 #include <stdlib.h>
a865e0 #include "macos.h"
df6c94 #else /* MACOS */
5d01b0 #ifdef DOS
f8f2ef #include "msdos.h"
d1bc39 #endif /* DOS */
8f8479 #include <krb.h>
09bea3 #include <stdlib.h>
020298 #if !defined(DOS) && !defined( _WIN32 )
c4f15e #include <sys/types.h>
54a1e0 #endif /* !DOS && !_WIN32 */
0ca394 #ifndef WIN32¤  ¤   /* marcd */
115d8c #include <sys/time.h>
6a66f2 #include <sys/socket.h>
8b7454 #endif
00e962 #endif /* MACOS */
94af5a
f7b779 #include "lber.h"
b4e990 #include "ldap.h"
ff745c #include "ldap-int.h"
c1af5a
f8af5a
3eaf5a
e538e5 /*
452738 ·* ldap_kerberos_bind1 - initiate a bind to the ldap server using
62a8df ·* kerberos authentication. ·The dn is supplied. ·It is assumed the user
d105d6 ·* already has a valid ticket granting ticket. ·The msgid of the
0c046e ·* request is returned on success (suitable for passing to ldap_result()),
0b7daf ·* -1 is returned if there's trouble.
c5775e ·*
69305c ·* Example:
dbbe69 ·*¤ ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" )
0b495d ·*/
894d2f int
469c85 ldap_kerberos_bind1( LDAP *ld, char *dn )
e8bb36 {
299c95 ¤   BerElement¤ *ber;
07d816 ¤   char¤   ¤   *cred;
8b8f9f ¤   int¤¤   rc, credlen;
276427 ¤   char¤   ¤   *get_kerberosv4_credentials();
11f52a #ifdef STR_TRANSLATION
f3bba3 ¤   int¤¤   str_translation_on;
4c3dd6 #endif /* STR_TRANSLATION */
b3af5a
79d8af ¤   /*
7bc5cb ¤   ·* The bind request looks like this:
eb8a87 ¤   ·*¤ BindRequest ::= SEQUENCE {
759904 ¤   ·*¤ ¤   version¤¤   INTEGER,
eba183 ¤   ·*¤ ¤   name¤   ¤   DistinguishedName,
920e2e ¤   ·*¤ ¤   authentication¤ CHOICE {
f9afb7 ¤   ·*¤ ¤   ¤   krbv42ldap¤ [1] OCTET STRING
402e91 ¤   ·*¤ ¤   ¤   krbv42dsa¤  [2] OCTET STRING
de3c91 ¤   ·*¤ ¤   }
db5203 ¤   ·*¤ }
--7c8e 00031abf1b0401000a3 Page 2 of kbind.c
ec6bb5 ¤   ·* all wrapped up in an LDAPMessage sequence.
31a4e3 ¤   ·*/
19af5a
8014e2 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 );
f1af5a
04ab9d ¤   if ( dn == NULL )
4f74f0 ¤   ¤   dn = "";
31af5a
03ccd1 ¤   if ( (cred = get_kerberosv4_credentials( ld, dn, "ldapserver",
b2aa6b ¤   ····&credlen )) == NULL ) {
8fb94c ¤   ¤   return( -1 );¤  /* ld_errno should already be set */
909371 ¤   }
f1af5a
1d47d1 ¤   /* create a message to send */
426826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
7cb761 ¤   ¤   free( cred );
3c49fa ¤   ¤   return( -1 );
159371 ¤   }
3faf5a
abf52a #ifdef STR_TRANSLATION
bb088d ¤   if (( str_translation_on = (( ber->ber_options &
159c32 ¤   ····LBER_TRANSLATE_STRINGS ) != 0 ))) {¤/* turn translation off */
427790 ¤   ¤   ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
889371 ¤   }
683dd6 #endif /* STR_TRANSLATION */
dcaf5a
5aaa04 ¤   /* fill it in */
cb925e ¤   rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
bfc6fd ¤   ····ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen );
0baf5a
bdf52a #ifdef STR_TRANSLATION
c74df5 ¤   if ( str_translation_on ) {¤/* restore translation */
5a8cef ¤   ¤   ber->ber_options |= LBER_TRANSLATE_STRINGS;
4e9371 ¤   }
373dd6 #endif /* STR_TRANSLATION */
eaaf5a
3c3ced ¤   if ( rc == -1 ) {
a1b761 ¤   ¤   free( cred );
521ab1 ¤   ¤   ber_free( ber, 1 );
473614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
5d49fa ¤   ¤   return( -1 );
c79371 ¤   }
e2af5a
0b8dfb ¤   free( cred );
1eaf5a
2823e9 #ifndef NO_CACHE
115f25 ¤   if ( ld->ld_cache != NULL ) {
d429bb ¤   ¤   ldap_flush_cache( ld );
579371 ¤   }
43e842 #endif /* !NO_CACHE */
4caf5a
2fdd1f ¤   /* send the message */
a52c96 ¤   return ( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
c8efe6 }
efaf5a
4b4d2f int
56bbaa ldap_kerberos_bind1_s( LDAP *ld, char *dn )
44bb36 {
a4da47 ¤   int¤¤   msgid;
373932 ¤   LDAPMessage¤*res;
4caf5a
9c4f9f ¤   Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1_s\n", 0, 0, 0 );
f1af5a
4883f2 ¤   /* initiate the bind */
e403e9 ¤   if ( (msgid = ldap_kerberos_bind1( ld, dn )) == -1 )
22df73 ¤   ¤   return( ld->ld_errno );
6baf5a
f3a34c ¤   /* wait for a result */
bd44e9 ¤   if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
bf9a76 ¤   ····== -1 ) {
eb75f2 ¤   ¤   return( ld->ld_errno );¤/* ldap_result sets ld_errno */
319371 ¤   }
--7485 000c82c6021401000a3 Page 3 of kbind.c
e0af5a
669595 ¤   return( ldap_result2error( ld, res, 1 ) );
4aefe6 }
59af5a
1a38e5 /*
00a85a ·* ldap_kerberos_bind2 - initiate a bind to the X.500 server using
8aa8df ·* kerberos authentication. ·The dn is supplied. ·It is assumed the user
fb05d6 ·* already has a valid ticket granting ticket. ·The msgid of the
be046e ·* request is returned on success (suitable for passing to ldap_result()),
527daf ·* -1 is returned if there's trouble.
58775e ·*
46305c ·* Example:
344d82 ·*¤ ldap_kerberos_bind2( ld, "cn=manager, o=university of michigan, c=us" )
b6495d ·*/
314d2f int
937149 ldap_kerberos_bind2( LDAP *ld, char *dn )
e9bb36 {
ed9c95 ¤   BerElement¤ *ber;
2ed816 ¤   char¤   ¤   *cred;
108f9f ¤   int¤¤   rc, credlen;
5f6427 ¤   char¤   ¤   *get_kerberosv4_credentials();
2df52a #ifdef STR_TRANSLATION
7dbba3 ¤   int¤¤   str_translation_on;
b03dd6 #endif /* STR_TRANSLATION */
55af5a
8b24f3 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2\n", 0, 0, 0 );
67af5a
1bab9d ¤   if ( dn == NULL )
ff74f0 ¤   ¤   dn = "";
98af5a
49d458 ¤   if ( (cred = get_kerberosv4_credentials( ld, dn, "x500dsa", &credlen ))
ea3c7b ¤   ····== NULL ) {
14b94c ¤   ¤   return( -1 );¤  /* ld_errno should already be set */
4a9371 ¤   }
75af5a
d247d1 ¤   /* create a message to send */
116826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
7ab761 ¤   ¤   free( cred );
d649fa ¤   ¤   return( -1 );
499371 ¤   }
13af5a
8bf52a #ifdef STR_TRANSLATION
09088d ¤   if (( str_translation_on = (( ber->ber_options &
299c32 ¤   ····LBER_TRANSLATE_STRINGS ) != 0 ))) {¤/* turn translation off */
087790 ¤   ¤   ber->ber_options &= ~LBER_TRANSLATE_STRINGS;
d09371 ¤   }
bf3dd6 #endif /* STR_TRANSLATION */
c1af5a
87aa04 ¤   /* fill it in */
da925e ¤   rc = ber_printf( ber, "{it{isto}}", ++ld->ld_msgid, LDAP_REQ_BIND,
a7af16 ¤   ····ld->ld_version, dn, LDAP_AUTH_KRBV42, cred, credlen );
42af5a
e5af5a
68f52a #ifdef STR_TRANSLATION
d44df5 ¤   if ( str_translation_on ) {¤/* restore translation */
218cef ¤   ¤   ber->ber_options |= LBER_TRANSLATE_STRINGS;
fb9371 ¤   }
c23dd6 #endif /* STR_TRANSLATION */
89af5a
bc8dfb ¤   free( cred );
1daf5a
b43ced ¤   if ( rc == -1 ) {
2c1ab1 ¤   ¤   ber_free( ber, 1 );
af3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
e849fa ¤   ¤   return( -1 );
939371 ¤   }
e4af5a
7ddd1f ¤   /* send the message */
792c96 ¤   return ( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
71efe6 }
8aaf5a
c8ed24 /* synchronous bind to DSA using kerberos */
--b754 000d1f33bfe401000a3 Page 4 of kbind.c
af4d2f int
2de44b ldap_kerberos_bind2_s( LDAP *ld, char *dn )
8ebb36 {
afda47 ¤   int¤¤   msgid;
6d3932 ¤   LDAPMessage¤*res;
3baf5a
b0f255 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind2_s\n", 0, 0, 0 );
53af5a
4883f2 ¤   /* initiate the bind */
5c5a5d ¤   if ( (msgid = ldap_kerberos_bind2( ld, dn )) == -1 )
76df73 ¤   ¤   return( ld->ld_errno );
20af5a
c4a34c ¤   /* wait for a result */
3744e9 ¤   if ( ldap_result( ld, ld->ld_msgid, 1, (struct timeval *) 0, &res )
1d9a76 ¤   ····== -1 ) {
5875f2 ¤   ¤   return( ld->ld_errno );¤/* ldap_result sets ld_errno */
eb9371 ¤   }
e8af5a
1c9595 ¤   return( ldap_result2error( ld, res, 1 ) );
36efe6 }
34af5a
dd7a1c /* synchronous bind to ldap and DSA using kerberos */
344d2f int
7db1a2 ldap_kerberos_bind_s( LDAP *ld, char *dn )
92bb36 {
df02e8 ¤   int¤err;
03af5a
9d77ee ¤   Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind_s\n", 0, 0, 0 );
00af5a
f78a58 ¤   if ( (err = ldap_kerberos_bind1_s( ld, dn )) != LDAP_SUCCESS )
c7e55e ¤   ¤   return( err );
caaf5a
76783b ¤   return( ldap_kerberos_bind2_s( ld, dn ) );
c1efe6 }
3aaf5a
1aaf5a
03b042 #ifndef AUTHMAN
1638e5 /*
33b968 ·* get_kerberosv4_credentials - obtain kerberos v4 credentials for ldap.
aefee9 ·* The dn of the entry to which to bind is supplied. ·It's assumed the
85eeea ·* user already has a tgt.
5e495d ·*/
43af5a
b911e4 char *
ddff9a get_kerberosv4_credentials( LDAP *ld, char *who, char *service, int *len )
f9bb36 {
b2d791 ¤   KTEXT_ST¤   ktxt;
4ff4e8 ¤   int¤¤   err;
4db223 ¤   char¤   ¤   realm[REALM_SZ], *cred, *krbinstance;
d1af5a
941be4 ¤   Debug( LDAP_DEBUG_TRACE, "get_kerberosv4_credentials\n", 0, 0, 0 );
9eaf5a
408398 ¤   if ( (err = krb_get_tf_realm( tkt_string(), realm )) != KSUCCESS ) {
8c4eeb #ifndef NO_USERINTERFACE
a8c961 ¤   ¤   fprintf( stderr, "krb_get_tf_realm failed (%s)\n",
daf111 ¤   ¤   ····krb_err_txt[err] );
b900a6 #endif /* NO_USERINTERFACE */
b037c0 ¤   ¤   ld->ld_errno = LDAP_INVALID_CREDENTIALS;
7fef86 ¤   ¤   return( NULL );
889371 ¤   }
a8af5a
b27f8d #ifdef LDAP_REFERRALS
5bc50b ¤   krbinstance = ld->ld_defconn->lconn_krbinstance;
084267 #else /* LDAP_REFERRALS */
1f9db8 ¤   krbinstance = ld->ld_host;
6290e2 #endif /* LDAP_REFERRALS */
e7af5a
1870d1 ¤   if ( (err = krb_mk_req( &ktxt, service, krbinstance, realm, 0 ))
169125 ¤   ····!= KSUCCESS ) {
f44eeb #ifndef NO_USERINTERFACE
fb40d3 ¤   ¤   fprintf( stderr, "krb_mk_req failed (%s)\n", krb_err_txt[err] );
d100a6 #endif /* NO_USERINTERFACE */
--d7b8 001e81beda8401000a3 Page 5 of kbind.c
7d37c0 ¤   ¤   ld->ld_errno = LDAP_INVALID_CREDENTIALS;
30ef86 ¤   ¤   return( NULL );
7d9371 ¤   }
c2af5a
d1c2c2 ¤   if ( ( cred = malloc( ktxt.length )) == NULL ) {
c26f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
6bef86 ¤   ¤   return( NULL );
679371 ¤   }
89af5a
62593c ¤   *len = ktxt.length;
2b2124 ¤   memcpy( cred, ktxt.dat, ktxt.length );
a3af5a
27a766 ¤   return( cred );
47efe6 }
59af5a
5fcb47 #endif /* !AUTHMAN */
e8999d #endif /* KERBEROS */
--a79d 00018ab7919401000a4 Page 1 of ldap-int.h
bc38e5 /*
5ce36d ·* ·Copyright (c) 1995 Regents of the University of Michigan.
a8e4d4 ·* ·All rights reserved.
42775e ·*
0ef606 ·* ·ldap-int.h - defines & prototypes internal to the LDAP library
91495d ·*/
55af5a
94af5a
39615e #define LDAP_URL_PREFIX ········"ldap://"
3a155d #define LDAP_URL_PREFIX_LEN ····7
9f3f71 #define LDAP_URL_URLCOLON¤  "URL:"
446b65 #define LDAP_URL_URLCOLON_LEN¤  4
68af5a
5d7f8d #ifdef LDAP_REFERRALS
15bd4c #define LDAP_REF_STR¤   ¤   "Referral:\n"
713025 #define LDAP_REF_STR_LEN¤   10
2fb174 #define LDAP_LDAP_REF_STR¤  LDAP_URL_PREFIX
a7c01e #define LDAP_LDAP_REF_STR_LEN¤  LDAP_URL_PREFIX_LEN
7a4ae9 #ifdef LDAP_DNS
284245 #define LDAP_DX_REF_STR¤¤   "dx://"
829ed6 #define LDAP_DX_REF_STR_LEN¤5
301845 #endif /* LDAP_DNS */
1490e2 #endif /* LDAP_REFERRALS */
abaf5a
e4af5a
9838e5 /*
4a6681 ·* in cache.c
40495d ·*/
c9504c #ifdef NEEDPROTOS
bea5f4 void add_request_to_cache( LDAP *ld, unsigned long msgtype,
d03c74 ········BerElement *request );
578708 void add_result_to_cache( LDAP *ld, LDAPMessage *result );
871976 int check_cache( LDAP *ld, unsigned long msgtype, BerElement *request );
8d6133 #else /* NEEDPROTOS */
234301 void add_request_to_cache();
f75d64 void add_result_to_cache();
c8082c int check_cache();
938634 #endif /* NEEDPROTOS */
e8af5a
05af5a
3f5ffa #ifdef KERBEROS
a438e5 /*
3da9fd ·* in kerberos.c
05495d ·*/
73504c #ifdef NEEDPROTOS
1d1556 char *get_kerberosv4_credentials( LDAP *ld, char *who, char *service,
23969d ········int *len );
e26133 #else /* NEEDPROTOS */
41ea37 char *get_kerberosv4_credentials();
b28634 #endif /* NEEDPROTOS */
80af5a
c6999d #endif /* KERBEROS */
c7af5a
e4af5a
8938e5 /*
5c0f35 ·* in open.c
13495d ·*/
48504c #ifdef NEEDPROTOS
8e9d11 int open_ldap_connection( LDAP *ld, Sockbuf *sb, char *host, int defport,
5ecbee ¤   char **krbinstancep, int async );
b66133 #else /* NEEDPROTOS */
337b22 int open_ldap_connection();
a68634 #endif /* NEEDPROTOS */
41af5a
d0af5a
5438e5 /*
0f4250 ·* in os-ip.c
13495d ·*/
8d504c #ifdef NEEDPROTOS
c66b55 int connect_to_host( Sockbuf *sb, char *host, unsigned long address, int port,
88774f ¤   int async );
18c999 void close_connection( Sockbuf *sb );
--58a5 0000fc447f9401000a4 Page 2 of ldap-int.h
026133 #else /* NEEDPROTOS */
38c9d7 int connect_to_host();
4e234e void close_connection();
fc8634 #endif /* NEEDPROTOS */
1daf5a
b95ffa #ifdef KERBEROS
a2504c #ifdef NEEDPROTOS
45b414 char *host_connected_to( Sockbuf *sb );
846133 #else /* NEEDPROTOS */
6d09e6 char *host_connected_to();
aa8634 #endif /* NEEDPROTOS */
ef999d #endif /* KERBEROS */
a2af5a
917f8d #ifdef LDAP_REFERRALS
ec504c #ifdef NEEDPROTOS
058003 int do_ldap_select( LDAP *ld, struct timeval *timeout );
846ce6 void *new_select_info( void );
dea3ce void free_select_info( void *sip );
d132ea void mark_select_write( LDAP *ld, Sockbuf *sb );
cff78f void mark_select_read( LDAP *ld, Sockbuf *sb );
2d94cc void mark_select_clear( LDAP *ld, Sockbuf *sb );
b41a6f int is_read_ready( LDAP *ld, Sockbuf *sb );
a88764 int is_write_ready( LDAP *ld, Sockbuf *sb );
9e6133 #else /* NEEDPROTOS */
172b86 int do_ldap_select();
0426d2 void *new_select_info();
515c45 void free_select_info();
80c946 void mark_select_write();
410352 void mark_select_read();
aa0173 void mark_select_clear();
72c125 int is_read_ready();
f78089 int is_write_ready();
0f8634 #endif /* NEEDPROTOS */
be90e2 #endif /* LDAP_REFERRALS */
67af5a
18af5a
5738e5 /*
99848e ·* in request.c
7a495d ·*/
1b504c #ifdef NEEDPROTOS
760bea int send_initial_request( LDAP *ld, unsigned long msgtype,
daa3a4 ¤   char *dn, BerElement *ber );
5fe98e BerElement *alloc_ber_with_options( LDAP *ld );
10c85d void set_ber_options( LDAP *ld, BerElement *ber );
9f6133 #else /* NEEDPROTOS */
015557 int send_initial_request();
27fe4e BerElement *alloc_ber_with_options();
945339 void set_ber_options();
3e8634 #endif /* NEEDPROTOS */
d8af5a
208b9e #if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
16504c #ifdef NEEDPROTOS
2bd3fa int send_server_request( LDAP *ld, BerElement *ber, int msgid,
57468b ¤   LDAPRequest *parentreq, LDAPServer *srvlist, LDAPConn *lc,
c005f6 ¤   int bind );
939f18 LDAPConn *new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
12af17 ¤   int connect, int bind );
3c6a77 LDAPRequest *find_request_by_msgid( LDAP *ld, int msgid );
b3cb82 void free_request( LDAP *ld, LDAPRequest *lr );
92fc8a void free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
c57fa8 void dump_connection( LDAP *ld, LDAPConn *lconns, int all );
d410d0 void dump_requests_and_responses( LDAP *ld );
f96133 #else /* NEEDPROTOS */
d4747f int send_server_request();
d92023 LDAPConn *new_connection();
e07a8c LDAPRequest *find_request_by_msgid();
3f2099 void free_request();
982ca1 void free_connection();
c27f37 void dump_connection();
8abf7f void dump_requests_and_responses();
478634 #endif /* NEEDPROTOS */
0f1c7e #endif /* LDAP_REFERRALS || LDAP_DNS */
--c661 0018a34e959401000a4 Page 3 of ldap-int.h
e0af5a
f47f8d #ifdef LDAP_REFERRALS
49504c #ifdef NEEDPROTOS
b7a65e int chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp );
e1ce1d int append_referral( LDAP *ld, char **referralsp, char *s );
b46133 #else /* NEEDPROTOS */
7575cc int chase_referrals();
de377a int append_referral();
608634 #endif /* NEEDPROTOS */
c690e2 #endif /* LDAP_REFERRALS */
65af5a
00af5a
4d38e5 /*
6fa203 ·* in search.c
87495d ·*/
bd504c #ifdef NEEDPROTOS
584f09 BerElement *ldap_build_search_req( LDAP *ld, char *base, int scope,
de091d ¤   char *filter, char **attrs, int attrsonly );
d66133 #else /* NEEDPROTOS */
48ff00 BerElement *ldap_build_search_req();
268634 #endif /* NEEDPROTOS */
0caf5a
34af5a
8638e5 /*
fd8dcb ·* in unbind.c
8c495d ·*/
ba504c #ifdef NEEDPROTOS
6b3ad5 int ldap_ld_free( LDAP *ld, int close );
f3fe7d int send_unbind( LDAP *ld, Sockbuf *sb );
626133 #else /* NEEDPROTOS */
d0cc44 int ldap_ld_free();
7f445c int send_unbind();
e98634 #endif /* NEEDPROTOS */
10af5a
16af5a
7d4ae9 #ifdef LDAP_DNS
e438e5 /*
66666d ·* in getdxbyname.c
68495d ·*/
68504c #ifdef NEEDPROTOS
505e8a char **getdxbyname( char *domain );
756133 #else /* NEEDPROTOS */
5ff2b5 char **getdxbyname();
c18634 #endif /* NEEDPROTOS */
8a1845 #endif /* LDAP_DNS */
--5c0b 000a60e0a54401000a5 Page 1 of ldapfilter.conf
f6fda9 # ldap filter file
78a601 #
6faf2c # lines like this that start with # or empty lines are ignored
da3463 #·
6edc04 # syntax:
56a601 #
5a1e9b # <tag>
b4f1c4 # ··<pattern1>¤ <delimiters>¤   <filter1-1>¤<desc1-1>¤  [<scope>]
6dffb8 # ¤ ¤   ···¤¤   <filter1-2>¤<desc1-2>¤  [<scope>]
fea601 #
719e9a # ··<pattern2>¤ <delimiters>¤   <filter2-1>¤<desc2-1>¤  [<scope>] ...
3fa601 #
e56e4f # The "desc" should describe the filter and it should correctly complete
bea511 # both of the following phrases:
d5a601 #
3fcc82 #¤  One <desc> match was found for...
cb6519 #¤  Three <desc> matches were found for...
1ea601 #
ea692e # The scope is optional, and should be one of:
706ea6 #¤  "base"
480cfc #¤  "onelevel"
046855 #¤  "subtree"
b146ad # if it is included.
74a601 #
9caf5a
82ee69 "finger and ud and go500 and go500gw subtree and web500gw subtree and rp500 and¶
6b25f6 ·rcpt500 and ufn last"
23a05d ····"="¤¤   " "¤"%v"¤   ¤   ¤   ¤   "arbitrary filter"
a9af5a
67dbfc ····"^[0-9][0-9-]*$"¤   " "¤"(telephoneNumber=*%v)"¤"phone number"
11af5a
0f6908 ····"@"¤¤   " "¤"(mail=%v)"¤¤   ¤   "email address"
2bf853 ¤   ¤   ¤   "(mail=%v*)"¤   ¤   ¤   "start of email address"
1baf5a
6f3540 ····"^.[. _].*"¤". _"¤  "(cn=%v1* %v2-)"¤   ¤   "first initial"
ccaf5a
7ae1ec ····".*[. _].$"¤". _"¤  "(cn=%v1-*)"¤   ¤   ¤   "last initial"
61af5a
a21c81 ····"[. _]"¤". _"¤  "(|(sn=%v1-)(cn=%v1-))"¤¤   "exact"
156de2 ¤   ¤   ¤   "(|(sn~=%v1-)(cn~=%v1-))"¤  "approximate"
05af5a
43f3b3 ····".*"¤   ". "¤   "(|(cn=%v1)(sn=%v1)(uid=%v1))"¤ "exact"
3b4d01 ¤   ¤   ¤   "(|(cn~=%v1)(sn~=%v1))"¤¤   "approximate"
a0af5a
b3ca3c "go500gw onelevel and web500gw onelevel and ufn first and ufn intermediate"
59a05d ····"="¤¤   " "¤"%v"¤   ¤   ¤   ¤   "arbitrary filter"
67af5a
73477e ····"^..$"¤ " "¤"(|(o=%v)(c=%v)(l=%v)(co=%v))"¤ ¤   "exact"
8c250f ····¤   ¤   ¤   "(|(o~=%v)(c~=%v)(l~=%v)(co~=%v))"¤ "approximate"
54af5a
acc274 ····" "¤¤   " "¤"(|(o=%v)(l=%v)(co=%v)(ou=%v))"¤¤   "exact"
d99d0a ····¤   ¤   ¤   "(|(o~=%v)(l~=%v)(co~=%v)(ou~=%v))"¤"approximate"
a1af5a
3b57c7 ····"\."¤   " "¤"(associatedDomain=%v)"¤¤   ¤   "exact"
71af5a
ee1495 ····".*"¤   " "¤"(|(o=%v)(l=%v)(co=%v)(ou=%v))"¤¤   "exact"
409d0a ····¤   ¤   ¤   "(|(o~=%v)(l~=%v)(co~=%v)(ou~=%v))"¤"approximate"
05af5a
3faf5a
82a601 #
4529d4 # xax500
07a601 #
75af5a
76910f "xax500"
4db51a ····"="¤¤   ¤   " "¤"(%v)"¤ ¤   ¤   "arbitrary filter"
c4af5a
a0dbfc ····"^[0-9][0-9-]*$"¤   " "¤"(telephoneNumber=*%v)"¤"phone number"
d7af5a
46225d ····"@"¤¤   ¤   " "¤"(mail=%v)"¤¤   "email address"
fea777 ¤   ¤   ¤   ¤   "(mail=%v*)"¤   ¤   "start of email address"
6faf5a
a6c4ca ····"^.[. _].*"¤¤   ". _"¤  "(cn=%v1* %v2-)"¤   "first initial"
--fca5 001675ce674401000a5 Page 2 of ldapfilter.conf
e0af5a
9d75b1 ····".*[. _].$"¤¤   ". _"¤  "(cn=%v1-*)"¤   ¤   "last initial"
24af5a
991c48 ····"[. _]"¤¤   ". _"¤  "(|(sn=%v1-)(cn=%v1-))"¤¤   "exact"
946e95 ¤   ¤   ¤   ¤   "(|(sn~=%v1-)(cn~=%v1-))"¤  "approximate"
56af5a
e12abe ····".*"¤   ¤   ". "¤   "(|(cn=%v1)(sn=%v1)(uid=%v1))"¤ "exact"
bcd2cc ¤   ¤   ¤   "(|(cn=%v1)(sn~=%v1))"¤ ¤   ¤   "approximate"
46af5a
b6af5a
e64cb0 "xax500-auth"
e8b51a ····"="¤¤   ¤   " "¤"(%v)"¤ ¤   ¤   "arbitrary filter"
d4af5a
4ddbfc ····"^[0-9][0-9-]*$"¤   " "¤"(telephoneNumber=*%v)"¤"phone number"
6faf5a
7b225d ····"@"¤¤   ¤   " "¤"(mail=%v)"¤¤   "email address"
b3a777 ¤   ¤   ¤   ¤   "(mail=%v*)"¤   ¤   "start of email address"
48af5a
dec4ca ····"^.[. _].*"¤¤   ". _"¤  "(cn=%v1* %v2-)"¤   "first initial"
eaaf5a
ce75b1 ····".*[. _].$"¤¤   ". _"¤  "(cn=%v1-*)"¤   ¤   "last initial"
38af5a
1f71c4 ····"[. _]"¤¤   ". _"¤  "(|(sn=%v1-)(cn=%v1-))"¤"exact"
cc6de2 ¤   ¤   ¤   "(|(sn~=%v1-)(cn~=%v1-))"¤  "approximate"
e3af5a
ad2abe ····".*"¤   ¤   ". "¤   "(|(cn=%v1)(sn=%v1)(uid=%v1))"¤ "exact"
e4d2cc ¤   ¤   ¤   "(|(cn=%v1)(sn~=%v1))"¤ ¤   ¤   "approximate"
52af5a
fc3103 "list500"
ea1c81 ····"[. _]"¤". _"¤  "(|(sn=%v1-)(cn=%v1-))"¤¤   "exact"
866de2 ¤   ¤   ¤   "(|(sn~=%v1-)(cn~=%v1-))"¤  "approximate"
aeaf5a
78f3b3 ····".*"¤   ". "¤   "(|(cn=%v1)(sn=%v1)(uid=%v1))"¤ "exact"
674d01 ¤   ¤   ¤   "(|(cn~=%v1)(sn~=%v1))"¤¤   "approximate"
--3cd7 000fad24050401000a6 Page 1 of ldapfriendly
5317bf AD¤ Andorra
1f4e4a AE¤ United Arab Emirates
69fc93 AF¤ Afghanistan
bd22c0 AG¤ Antigua and Barbuda
f04be3 AI¤ Anguilla
fe1d4a AL¤ Albania
ce6baa AM¤ Armenia
0eb067 AN¤ Netherlands Antilles
abf143 AO¤ Angola
eedd59 AQ¤ Antarctica
f35e65 AR¤ Argentina
0401f6 AS¤ American Samoa
c0a44f AT¤ Austria
5acb7c AU¤ Australia
d9d7b7 AW¤ Aruba
73d61d AZ¤ Azerbaijan
f9e2cf BA¤ Bosnia and Herzegowina
c44215 BB¤ Barbados
4b419e BD¤ Bangladesh
5c64fb BE¤ Belgium
91e5e8 BF¤ Burkina Faso
a4503c BG¤ Bulgaria
b1d1dd BH¤ Bahrain
6b051f BI¤ Burundi
9a70a3 BJ¤ Benin
f3cd97 BM¤ Bermuda
402463 BN¤ Brunei Darussalam
940352 BO¤ Bolivia
81ecb1 BR¤ Brazil
e53f12 BS¤ Bahamas
60adbd BT¤ Bhutan
4fc7c7 BV¤ Bouvet Island
e4e4c7 BW¤ Botswana
a4c0ec BY¤ Belarus
bafc08 BZ¤ Belize
15e84c CA¤ Canada
96c66b CC¤ Cocos (Keeling) Islands
07d2a2 CF¤ Central African Republic
4b1016 CG¤ Congo
3f2d34 CH¤ Switzerland
4dc8fa CI¤ Cote d'Ivoire
d345b0 CK¤ Cook Islands
b50af0 CL¤ Chile
ea7ead CM¤ Cameroon
cf43d2 CN¤ China
3afae2 CO¤ Colombia
aa24cf CR¤ Costa Rica
8db196 CS¤ Former Czechoslovakia
171dda CU¤ Cuba
f9d3b9 CV¤ Cape Verde
5de35b CX¤ Christmas Island
927a23 CY¤ Cyprus
6c8c5a CZ¤ Czech Republic
4678f7 DE¤ Germany
60ef5f DJ¤ Djibouti
534ea9 DK¤ Denmark
442074 DM¤ Dominica
a82985 DO¤ Dominican Republic
ad7459 DZ¤ Algeria
57e0b5 EC¤ Ecuador
027016 EE¤ Estonia
925637 EG¤ Egypt
c1f4d1 EH¤ Western Sahara
174b95 ER¤ Eritrea
e41f83 ES¤ Spain
b5bc0e ET¤ Ethiopia
41f57f FI¤ Finland
b3ffcb FJ¤ Fiji
816625 FK¤ Falkland Islands (Malvinas)
e77b6f FM¤ Micronesia
8d017d FO¤ Faroe Islands
fac8bd FR¤ France
--5b32 0008c61e3d2401000a6 Page 2 of ldapfriendly
05364d FX¤ France, Metropolitan
113daf GA¤ Gabon
25fa07 GB¤ United Kingdom
afb3df GD¤ Grenada
3eca04 GE¤ Georgia
01121f GF¤ French Guiana
f9a225 GH¤ Ghana
b41c85 GI¤ Gibraltar
92ace3 GL¤ Greenland
5fc7a4 GM¤ Gambia
23fe56 GN¤ Guinea
51de26 GP¤ Guadeloupe
f12f11 GQ¤ Equatorial Guinea
abeffc GR¤ Greece
c8c1ad GS¤ South Georgia and the South Sandwich Islands
4ee31a GT¤ Guatemala
f849eb GU¤ Guam
003a14 GW¤ Guinea-Bissau
6cc7ee GY¤ Guyana
870b1d HK¤ Hong Kong
c4c592 HM¤ Heard and McDonald Islands
16a259 HN¤ Honduras
5bb83c HR¤ Croatia
b80158 HT¤ Haiti
bb1d89 HU¤ Hungary
e26f23 ID¤ Indonesia
89c028 IE¤ Ireland
b88033 IL¤ Israel
2e67a9 IN¤ India
591ad2 IO¤ British Indian Ocean Territory
b88e48 IQ¤ Iraq
1c12c1 IR¤ Iran
f66e06 IS¤ Iceland
25885e IT¤ Italy
385528 JM¤ Jamaica
62ef45 JO¤ Jordan
03a547 JP¤ Japan
2380ab KE¤ Kenya
702387 KG¤ Kyrgyzstan
bd9207 KH¤ Cambodia
4c6235 KI¤ Kiribati
b29bd1 KM¤ Comoros
e521c7 KN¤ Saint Kitts and Nevis
be59d2 KP¤ Korea, Democratic People's Republic of
6c2e26 KR¤ Korea, Republic of
7213e4 KW¤ Kuwait
27a12d KY¤ Cayman Islands
7e86f4 KZ¤ Kazakhstan
b644bb LA¤ Laos
6170ad LB¤ Lebanon
ab0e1c LC¤ Saint Lucia
b51f95 LI¤ Liechtenstein
89b24a LK¤ Sri Lanka
b69ce6 LR¤ Liberia
edf988 LS¤ Lesotho
415b32 LT¤ Lithuania
d7b53a LU¤ Luxembourg
786844 LV¤ Latvia
440730 LY¤ Libya
4b775f MA¤ Morocco
e45049 MC¤ Monaco
a4f169 MD¤ Moldova
a36790 MG¤ Madagascar
5b5d1e MH¤ Marshall Islands
66d7d4 MK¤ Macedonia
ff3f5a ML¤ Mali
0c033e MM¤ Myanmar
8f3acd MN¤ Mongolia
78838a MO¤ Macau
46c249 MP¤ Northern Mariana Islands
14af42 MQ¤ Martinique
8cdfbf MR¤ Mauritania
--1258 000a4d3ac81401000a6 Page 3 of ldapfriendly
02a1b1 MS¤ Montserrat
b029f3 MT¤ Malta
fa9edf MU¤ Mauritius
ae0927 MV¤ Maldives
c2af89 MW¤ Malawi
05dc55 MX¤ Mexico
304c41 MY¤ Malaysia
ebafb5 MZ¤ Mozambique
bc4d30 NA¤ Namibia
baac19 NC¤ New Caledonia
8c190b NE¤ Niger
7de632 NF¤ Norfolk Island
0dfb34 NG¤ Nigeria
e6d9c2 NI¤ Nicaragua
89a857 NL¤ Netherlands
f5e093 NO¤ Norway
941bd7 NP¤ Nepal
f8eb12 NR¤ Nauru
b15619 NU¤ Niue
3821c4 NZ¤ New Zealand
4016d4 OM¤ Oman
94e603 PA¤ Panama
db7278 PE¤ Peru
aab671 PF¤ French Polynesia
4aebe6 PG¤ Papua New Guinea
b28522 PH¤ Philippines
637506 PK¤ Pakistan
e4ad67 PL¤ Poland
d83517 PM¤ St. Pierre and Miquelon
84ddbd PN¤ Pitcairn
bcfe32 PR¤ Puerto Rico
8cb57c PT¤ Portugal
33e182 PW¤ Palau
a4eabf PY¤ Paraguay
8ef974 QA¤ Qatar
12c07b RE¤ Reunion
bd3580 RO¤ Romania
d2f81a RU¤ Russian Federation
d95e4b RW¤ Rwanda
d16a9b SA¤ Saudi Arabia
d70230 SB¤ Solomon Islands
dcb1db SC¤ Seychelles
a2bdb4 SD¤ Sudan
aa36b9 SE¤ Sweden
d56707 SG¤ Singapore
5b29a0 SH¤ St. Helena
c6d002 SI¤ Slovenia
a18cbe SJ¤ Svalbard and Jan Mayen Islands
25e7ed SK¤ Slovakia (Slovak Republic)
3be7cb SL¤ Sierra Leone
fb34aa SM¤ San Marino
932318 SN¤ Senegal
d9081c SO¤ Somalia
b1aa08 SR¤ Suriname
452269 ST¤ Sao Tome and Principe
a45051 SU¤ Former Soviet Union
32c81f SV¤ El Salvador
8ff5f3 SY¤ Syria
147857 SZ¤ Swaziland
dd1350 TC¤ Turks and Caicos Islands
440899 TD¤ Chad
25dc43 TF¤ French Southern Territories
2d6385 TG¤ Togo
0e5a10 TH¤ Thailand
3fe878 TJ¤ Tajikistan
384906 TK¤ Tokelau
1dd0a9 TM¤ Turkmenistan
473880 TN¤ Tunisia
2ebd0a TO¤ Tonga
5d8941 TP¤ East Timor
11a14a TR¤ Turkey
a49011 TT¤ Trinidad and Tobago
--190d 0010ece8566401000a6 Page 4 of ldapfriendly
b6d5d6 TV¤ Tuvalu
0b732c TW¤ Taiwan
cb8a79 TZ¤ Tanzania
cdcec0 UA¤ Ukraine
b1a957 UG¤ Uganda
b2af25 UK¤ United Kingdom
4d077c UM¤ United States Minor Outlying Islands
8bbe92 US¤ United States of America
10f2f5 UY¤ Uruguay
60a8ae UZ¤ Uzbekistan
0aa1a2 VA¤ Vatican City State (Holy See)
da500f VC¤ Saint Vincent and the Grenadines
126da0 VE¤ Venezuela
e04b9b VG¤ Virgin Islands (British)
69e368 VI¤ Virgin Islands (U.S.)
5842bc VN¤ Viet Nam
48690b VU¤ Vanuatu
1a727e WF¤ Wallis and Futuna Islands
39e8be WS¤ Samoa
a2c662 YE¤ Yemen
a9d614 YT¤ Mayotte
9af47f YU¤ Yugoslavia
0a209d ZA¤ South Africa
d29a09 ZM¤ Zambia
171ac4 ZR¤ Zaire
0e6805 ZW¤ Zimbabwe
--4426 000f4a9ab29401000a7 Page 1 of ldapsearchprefs.conf
b62fe2 # Version should be 1 now
a86fbd Version 1
87a601 #
23a601 #
7f9971 # Name for this search object
6264aa People
da24c3 # options (the only one supported right now is "internal" which means that
c72b30 # ··this search object should not be presented directly to the user)
acb327 # ··use "" for none
27095a ""
83269a # Label to place before text box user types in
de3c1b "Search For:"
63fc49 # Filter prefix to append to all "More Choices" searches
f46b03 "(&(objectClass=person)"
3f087f # Tag to use for "Fewer Choices" searches - from ldapfilter.conf file
50910f "xax500"
94cdc9 # If a search results in > 1 match, retrieve this attribute to help
a2673e # user disambiguate the entries...
7e198a title
196416 # ...and label it with this string:
23b7fe "Title"
1e9f17 # Search scope to use when searching
f2bf36 subtree
ee8a97 # Follows a list of "More Choices" search options. ·Format is:
533b05 # Label, attribute, select-bitmap, extra attr display name, extra attr ldap name
83a5e7 # If last two are null, "Fewer Choices" name/attributes used
8eb62d "Common Name" ··················cn ················11111 ·"" ·""
f3a35b "Surname" ······················sn ················11111 ·"" ·""
61517a "Business Phone" ···············"telephoneNumber" ·11101 ·"" ·""
6f289a "E-Mail Address" ···············"mail" ············11111 ·"" ·""
bd070f "Uniqname" ·····················"uid" ·············11111 ·"" ·""
c83c90 "Title" ························title ·············11111 "" ""
b7e0d1 END
67738a # Match types
fa995d "exactly matches" ··············"(%a=%v))"
a2e0ac "approximately matches" ········"(%a~=%v))"
a2d8f5 "starts with" ··················"(%a=%v*))"
075d0d "ends with" ····················"(%a=*%v))"
1192bf "contains" ·····················"(%a=*%v*))"
32e0d1 END
dea601 #
61a601 #
0ca601 #
e5c73a Groups
58095a ""
1d3c1b "Search For:"
7e1dbb "(&(objectClass=rfc822MailGroup)"
64910f "xax500"
588c98 multilineDescription
224731 "Description"
f5bf36 subtree
973178 "Common Name" ··················cn ···················11111 ·"" ······""
537151 "Description" ··················multilineDescription ·11101 ·"" ······""
0bf76a "Owner" ························"owner" ··············00001 ·"owner" ·"Owner"
485dfd "X.500 Member" ·················"member" ·············00001 ·"" ······""
2d2d31 "E-Mail Member" ················"mail" ···············00101 ·"" ······""
2fe0d1 END
0f995d "exactly matches" ··············"(%a=%v))"
56e0ac "approximately matches" ········"(%a~=%v))"
28d8f5 "starts with" ··················"(%a=%v*))"
545d0d "ends with" ····················"(%a=*%v))"
8392bf "contains" ·····················"(%a=*%v*))"
21e0d1 END
dea601 #
08a601 #
54a601 #
7d42e7 "Joinable Groups"
8c095a ""
e23c1b "Search For:"
31789c "(&(&(objectClass=rfc822MailGroup)(joinable=TRUE))"
f2910f "xax500"
f48c98 multilineDescription
--f67b 00069e43958401000a7 Page 2 of ldapsearchprefs.conf
234731 "Description"
9ebf36 subtree
9c3178 "Common Name" ··················cn ···················11111 ·"" ······""
517151 "Description" ··················multilineDescription ·11101 ·"" ······""
c7f76a "Owner" ························"owner" ··············00001 ·"owner" ·"Owner"
c25dfd "X.500 Member" ·················"member" ·············00001 ·"" ······""
122d31 "E-Mail Member" ················"mail" ···············00101 ·"" ······""
1ae0d1 END
0f995d "exactly matches" ··············"(%a=%v))"
ebe0ac "approximately matches" ········"(%a~=%v))"
99d8f5 "starts with" ··················"(%a=%v*))"
cb5d0d "ends with" ····················"(%a=*%v))"
a892bf "contains" ·····················"(%a=*%v*))"
79e0d1 END
99a601 #
17a601 #
0ca601 #
057564 Services
a4095a ""
dc3c1b "Search For:"
0d3838 "(&(objectClass=service)"
ba910f "xax500"
ee8c98 multilineDescription
d64731 "Description"
b6bf36 subtree
433178 "Common Name" ··················cn ···················11111 ·"" ······""
0d7151 "Description" ··················multilineDescription ·11101 ·"" ······""
61f76a "Owner" ························"owner" ··············00001 ·"owner" ·"Owner"
8aac0a "Keywords" ·····················"keywords" ···········11111 ·"" ······""
54cc7f "Hours" ························"hoursOfOperation" ···11111 ·"" ······""
7be0d1 END
58995d "exactly matches" ··············"(%a=%v))"
42e0ac "approximately matches" ········"(%a~=%v))"
99d8f5 "starts with" ··················"(%a=%v*))"
e95d0d "ends with" ····················"(%a=*%v))"
7692bf "contains" ·····················"(%a=*%v*))"
01e0d1 END
d3a601 #
d7a601 #
f2a601 #
fb7bc3 Organizations
92095a ""
cb3c1b "Search For:"
b64986 "(&(objectClass=organization)"
29910f "xax500"
1c8c98 multilineDescription
954731 "Description"
e3bf36 subtree
a79b07 "Name" ·························organizationName ·····01111 ·"" ······""
2aff69 "Location" ·····················localityName ·········11111 ·"" ······""
ec56db "Phone Number" ·················"telephoneNumber" ····10111 ·"" ······""
5e262e "Description" ··················description ··········10111 ·"" ······""
e9e0d1 END
a3995d "exactly matches" ··············"(%a=%v))"
59e0ac "approximately matches" ········"(%a~=%v))"
f8d8f5 "starts with" ··················"(%a=%v*))"
f15d0d "ends with" ····················"(%a=*%v))"
6a92bf "contains" ·····················"(%a=*%v*))"
f7e0d1 END
40a601 #
83a601 #
93a601 #
234acb Documents
29095a ""
293c1b "Search For:"
4f6078 "(&(objectClass=document)"
76910f "xax500"
e28c98 multilineDescription
804731 "Description"
83bf36 subtree
4cb587 "Document Title" ················cn ··················11111 ·"" ······""
690dd4 "Keyword" ······················"keywords" ···········11111 ·"" ······""
--7a95 0018801e099401000a7 Page 3 of ldapsearchprefs.conf
32d24d "Category" ·····················"category" ···········11111 ·"" ······""
3445a6 "Document Number" ··············"documentIdentifier" ·11111 ·"" ······""
bae0d1 END
dc995d "exactly matches" ··············"(%a=%v))"
92e0ac "approximately matches" ········"(%a~=%v))"
c3d8f5 "starts with" ··················"(%a=%v*))"
c75d0d "ends with" ····················"(%a=*%v))"
8792bf "contains" ·····················"(%a=*%v*))"
88e0d1 END
--348b 0006ad92fdf401000a8 Page 1 of ldaptemplates.conf
5ebaab ##########################################################################
ff85d3 # LDAP display templates
abbaab ##########################################################################
e4af5a
b7a601 #
131b4e # Version must be 1
9ea601 #
3c6fbd Version 1
e1af5a
12baab ##########################################################################
47605e # U-M Person template
e7baab ##########################################################################
d8a601 #
4cf8fa # template name and plural name come first
995400 "U-M Person"
ee32c8 "U-M People"
a7af5a
372089 # name of the icon that is associated with this template
281e76 "person icon"
4baf5a
ccd93e # blank-separated list of template options ("" for none)
e67ceb # ··addable¤- end-user should be allowed to add these types of entries
8042b7 # ··modrdn¤ - end-user can change the name of these entries
03ae1a # ··altview¤- this template is referred to in another template's
d143ca #¤  ¤   ¤   "linkact" item
fd1f28 "addable"
d6af5a
2ba601 #
c0150d # objectclass list
9a5d87 umichPerson person
aae0d1 END
caaf5a
94a601 #
b2c5b7 # name of attribute to authenticate as ("" means auth as this entry)
34095a ""
33af5a
f7a601 #
d71a61 # default attribute name to use when forming RDN of a new entry
87a601 #
b5ba36 cn
72af5a
9aa601 #
bf800f # default location when adding new entries (DN; "" means no default)
8b5fb7 "o=University of Michigan, c=US"
beaf5a
7ea601 #
3f4fc9 # rules used to define default values for new entries
68e0d1 END
90af5a
c6a601 #
18a601 #
6dbea9 # list of items for display
499a33 # each line is either:
c7caf5 # ···item (type) (attribute) (attr name) (extra args...)
657d1c # to define an item or
063ef6 # ···samerow
c069af # to keep the next item on the same row as the previous
96a601 #
f57710 # valid types are:
e660b9 # ···cis¤   - case ignore string
a24391 # ···mls¤   - multiline string
ab9aa8 # ···dn¤¤   -·
e8eb06 # ···mail¤  - case ignore string that contains an RFC822 mail address
27ed27 # ···bool¤  - boolean value
cf1d50 # ···jpeg¤  - inlined JPEG image
2a24a1 # ···jpegbtn¤   - JPEG image button
f79232 # ···fax¤   - inlined Fax image
43cd3a # ···faxbtn¤- Fax image button
81572c # ···audiobtn¤  - audio button
812d06 # ···time¤  - time value
45b48f # ···date¤  - time value displayed as a date only
6af69b # ···url¤   - labeled URL for links to items in WWW
--e6ec 0001a2928f5401000a8 Page 2 of ldaptemplates.conf
f25a7e # ···searchact ·- search action
abb1c5 # ···linkact ···- link to another template
86a601 #
057892 # valid options (comma separated list appended to the type) are:
f4c633 # ·ro¤  ¤   - attribute is read only; don't let user edit it
38d4a8 # ·sort¤¤   - order the values of this attribute
066fda # ·1val¤¤   - disallow entry of multiple values
ff5e1c # ·required¤- this attribute should have at least one value
5fe7af # ·hide¤¤   - don't show this item if attribute has no values
1ba5db # ·hideiffalse¤ - hide item if value is FALSE (for type 'bool' only)
7ca601 #
414673 item jpegbtn¤   "View Photo"¤   ¤   jpegPhoto¤  "Next Photo"
68e7a8 item audiobtn¤  "Play Sound"¤   ¤   audio
79fa00 item cis,ro,sort¤   "Also Known As"¤¤   cn
afaedf item mail¤  "E-Mail Address"¤   mail
e96b73 item cis¤   "Work Phone"¤   ¤   telephoneNumber
cd0354 item cis¤   "Fax Number"¤   ¤   facsimileTelephoneNumber
b15bae item cis¤   "Pager Number"¤ ¤   pager
d149b5 item mls¤   "Work Address"¤ ¤   postalAddress
938781 item cis,sort¤  "Title"¤¤   ¤   title
46fa5d item cis,ro¤"Uniqname"¤ ¤   uid
759cd3 item mls¤   "Description"¤  ¤   multiLineDescription
aeb7f8 item cis¤   "Home Phone"¤   ¤   homePhone
30b0b5 item mls¤   "Home Address"¤ ¤   homePostalAddress
836553 item url¤   "More Info (URL)"¤  labeledURL
2e245a item dn,sort¤   "See Also"¤ ¤   seeAlso
6d71ac item cis¤   "Favorite Beverage"¤drink
adb81d item cis¤   "Notice"¤   ¤   notice
5cf2e5 item bool,hideiffalse¤  "On Vacation"¤  ¤   onVacation
6287b3 item mls,1val¤  "Vacation Message"¤ vacationMessage
7c6675 item bool,hideiffalse¤  "Do Not Allow Updates"¤ noBatchUpdates
cc25b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
151088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
bda646 item searchact ·"Find Groups Added To" ·"" ·····"-dnt" "(&(objectclass=rfc822ma¶
d25859 ilgroup)(member=%v))" "multiLineDescription" "Description" ""
03e18e item searchact¤ "List Owned Groups"¤""¤ "-dnt" "(&(objectclass=rfc822mailgroup)¶
100b98 (owner=%v))" "title" "Title" ""
315de9 item linkact¤   "Other Addresses"¤  ""¤ "other addresses"
fce0d1 END
b8af5a
66af5a
75baab ##########################################################################
b9db93 # Person template
41baab ##########################################################################
0b4296 "Person"
67245e "People"
2b1e76 "person icon"
bdaf5a
75e9f3 # template options
e1106c addable
7ea601 #
77150d # objectclass list
6be11c person
1ae0d1 END
a134ce # name of attribute to authenticate as
25095a ""
60af5a
f41a61 # default attribute name to use when forming RDN of a new entry
72a601 #
25ba36 cn
65af5a
4280ce # default location when adding new entries
6c095a ""
1eaf5a
a4a601 #
e84fc9 # rules used to define default values for new entries
0ae0d1 END
fbaf5a
aca601 #
d9bea9 # list of items for display
fd4673 item jpegbtn¤   "View Photo"¤   ¤   jpegPhoto¤  "Next Photo"
1ae7a8 item audiobtn¤  "Play Sound"¤   ¤   audio
--965e 00067211a9f401000a8 Page 3 of ldaptemplates.conf
986fb7 item cis,sort¤  "Also Known As"¤¤   cn
5f8781 item cis,sort¤  "Title"¤¤   ¤   title
3249b5 item mls¤   "Work Address"¤ ¤   postalAddress
ab6b73 item cis¤   "Work Phone"¤   ¤   telephoneNumber
4a0354 item cis¤   "Fax Number"¤   ¤   facsimileTelephoneNumber
245bae item cis¤   "Pager Number"¤ ¤   pager
ecb0b5 item mls¤   "Home Address"¤ ¤   homePostalAddress
fdb7f8 item cis¤   "Home Phone"¤   ¤   homePhone
799121 item cis¤   "User ID"¤  ¤   uid
97aedf item mail¤  "E-Mail Address"¤   mail
b0cfb0 item cis¤   "Description"¤  ¤   description
6d71ac item cis¤   "Favorite Beverage"¤drink
b2245a item dn,sort¤   "See Also"¤ ¤   seeAlso
6b25b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
861088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
58e0d1 END
baaf5a
9baf5a
e8baab ##########################################################################
d6eaa8 # Group template
6fbaab ##########################################################################
12b08a "Group"
e0b074 "Groups"
210d4b "group icon"
8daf5a
f9e9f3 # template options
2f2edd addable modrdn
72af5a
b0150d # objectclass list
66e73a rfc822MailGroup
8ce0d1 END
98af5a
7634ce # name of attribute to authenticate as
c0643f "owner"
f3af5a
a81a61 # default attribute name to use when forming RDN of a new entry
a4a601 #
04ba36 cn
d6af5a
5b80ce # default location when adding new entries
c2c73d "ou=User Groups, ou=Groups, o=University of Michigan, c=US"
27af5a
93a601 #
7e4fc9 # rules used to define default values for new entries
7b4f60 constant¤   "associatedDomain"¤ "umich.edu"
040f9f constant¤   "joinable"¤ ¤   "FALSE"
31037a addersdn¤   "owner"
ce3ca8 addersdn¤   "member"
20e6d9 addersdn¤   "errorsTo"
fb30a5 addersdn¤   "requestsTo"
e5e0d1 END
73af5a
7fa601 #
12a601 #
c3bea9 # list of items for display
909a33 # each line is either:
7acaf5 # ···item (type) (attribute) (attr name) (extra args...)
4f7d1c # to define an item or
ab3ef6 # ···samerow
26a601 #
16bea9 # list of items for display
4a6fb7 item cis,sort¤  "Also Known As"¤¤   cn
e79cd3 item mls¤   "Description"¤  ¤   multiLineDescription
96284f item cis¤   "Phone Number"¤ ¤   telephoneNumber
af0354 item cis¤   "Fax Number"¤   ¤   facsimileTelephoneNumber
3ae6e6 item mls¤   "Address"¤  ¤   postalAddress
931e71 item dn,required,sort¤  "Owner"¤¤   owner
ad6553 item url¤   "More Info (URL)"¤  labeledURL
08245a item dn,sort¤   "See Also"¤ ¤   seeAlso
4bbfa5 item dn,sort¤   "Errors To"¤¤   errorsTo
e92df1 item dn,sort¤   "Requests To"¤  ¤   requestsTo
6770f8 item cis¤   "Associated Domain"¤associatedDomain
--f6b6 00045a1051e401000a8 Page 4 of ldaptemplates.conf
43d825 item cis¤   "Moderator"¤¤   moderator
a0ca28 item bool¤  "Suppress 'No E-Mail Address' Errors"¤  suppressNoEmailError
a40a1a item bool¤  "Others May Join"¤  joinable
4b348e item dn,sort¤   "X.500 Members"¤¤   member
f7321b item mail,sort¤ "E-Mail Errors To"¤ rfc822ErrorsTo
37755f item mail,sort¤ "E-Mail Requests To"¤   rfc822RequestsTo
b3107c item mail,sort¤ "E-Mail Members"¤   mail
16b81d item cis¤   "Notice"¤   ¤   notice
ba25b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
531088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
29484b item searchact ·"Subscribers" ··········"" "-dnt" "memberOfGroup=%v" "title" "T¶
81413c itle" "joinable"
e4e644 item verifyact¤ "Verify Members"¤   "member"¤   "mail" "E-Mail Address"
ede0d1 END
5caf5a
46baab ##########################################################################
96e3f9 # Organization template
a1baab ##########################################################################
9c6c61 "Organization"
1ce975 "Organizations"
d7ddaf "organization icon"
24af5a
7ee9f3 # template options
7f095a ""
f9af5a
bc150d # objectclass list
b45f14 organization
a4e0d1 END
0daf5a
0b34ce # name of attribute to authenticate as
c1095a ""
71af5a
791a61 # default attribute name to use when forming RDN of a new entry
c549c7 o
b3af5a
1180ce # default location when adding new entries
7d095a ""
51af5a
744fc9 # rules used to define default values for new entries
6369fb constant¤   "o"¤"foo"
08e0d1 END
0caf5a
1ca601 #
77a601 #
ebbea9 # list of items for display
919a33 # each line is either:
c8caf5 # ···item (type) (attribute) (attr name) (extra args...)
f47d1c # to define an item or
fa3ef6 # ···samerow
e1a601 #
a4bea9 # list of items for display
790eb5 item cis,sort¤  "Name"¤ ¤   ¤   o
fdc924 item cis¤   "Location"¤ ¤   l
e3e6e6 item mls¤   "Address"¤  ¤   postalAddress
f5284f item cis¤   "Phone Number"¤ ¤   telephoneNumber
9b0354 item cis¤   "Fax Number"¤   ¤   facsimileTelephoneNumber
46cfb0 item cis¤   "Description"¤  ¤   description
79245a item dn,sort¤   "See Also"¤ ¤   seeAlso
5325b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
761088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
97e0d1 END
c1af5a
79af5a
b9baab ##########################################################################
8349c5 # Service template
2dbaab ##########################################################################
c44bb0 "Service"
cd2e56 "Services"
6aac03 "service icon"
17af5a
0ee9f3 # template options
451f28 "addable"
--7bfd 000960a5fa8401000a8 Page 5 of ldaptemplates.conf
e0af5a
6b150d # objectclass list
e48baa service
2be0d1 END
8eaf5a
a434ce # name of attribute to authenticate as
f9643f "owner"
bbaf5a
a81a61 # default attribute name to use when forming RDN of a new entry
cdba36 cn
5faf5a
9380ce # default location when adding new entries
93390c "ou=Services, o=University of Michigan, c=US"
caaf5a
854fc9 # rules used to define default values for new entries
0d037a addersdn¤   "owner"
8ee0d1 END
04af5a
e3a601 #
56a601 #
e0bea9 # list of items for display
df9a33 # each line is either:
56caf5 # ···item (type) (attribute) (attr name) (extra args...)
a47d1c # to define an item or
a13ef6 # ···samerow
41a601 #
4dbea9 # list of items for display
3617cb item jpegbtn¤   "View Photo"¤   ¤   jpegPhoto
efeae4 item cis,sort¤  "Name"¤ ¤   ¤   cn
d1d7d2 item mls¤   "Description"¤  ¤   multilineDescription
4b4af1 item cis¤   "Provider"¤ ¤   provider
c9a3bd item cis,sort¤  "Service Area"¤ ¤   serviceArea
3b2c3a item mail¤  "E-mail Address"¤   mail
8fe9f1 item cis¤   "Phone"¤¤   ¤   telephoneNumber
ca0354 item cis¤   "Fax Number"¤   ¤   facsimileTelephoneNumber
daf426 item mls¤   "Postal Address"¤   postalAddress
ca38ba item cis¤   "Hours"¤¤   ¤   hoursOfOperation
c66553 item url¤   "More Info (URL)"¤  labeledURL
1bc843 item dn,sort¤   "Depends On"¤   ¤   dependentUpon
47245a item dn,sort¤   "See Also"¤ ¤   seeAlso
becbc3 item cis,sort¤  "Platform"¤ ¤   platform
0def5e item cis,sort¤  "Product"¤  ¤   product
29b0a5 item cis,sort¤  "Keywords"¤ ¤   keywords
d274f7 item cis¤   "FCE Rating"¤   ¤   serviceRating
71d0e7 item date¤  "Date Rated"¤   ¤   ratingTime
6bec7a item mls¤   "Rating Description"¤   ratingDescription
a625b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
891088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
201e71 item dn,required,sort¤  "Owner"¤¤   owner
dee0d1 END
c7af5a
03af5a
febaab ##########################################################################
7114b4 # Organizational Role template
55baab ##########################################################################
281ec3 "Organizational Role"
0c6f1f "Organizational Roles"
081e76 "person icon"
83af5a
42e9f3 # template options
91095a ""
32af5a
b7150d # objectclass list
9c756e organizationalRole
3fe0d1 END
3caf5a
ad34ce # name of attribute to authenticate as
3b095a ""
d4af5a
8c1a61 # default attribute name to use when forming RDN of a new entry
03ba36 cn
96af5a
--c101 000089c7906401000a8 Page 6 of ldaptemplates.conf
4280ce # default location when adding new entries
89095a ""
02af5a
ce4fc9 # rules used to define default values for new entries
33e0d1 END
8daf5a
4ea601 #
5ca601 #
ddbea9 # list of items for display
909a33 # each line is either:
34caf5 # ···item (type) (attribute) (attr name) (extra args...)
947d1c # to define an item or
753ef6 # ···samerow
40a601 #
46bea9 # list of items for display
27eae4 item cis,sort¤  "Name"¤ ¤   ¤   cn
accfb0 item cis¤   "Description"¤  ¤   description
3d7962 item dn¤¤   "Role Occupant"¤¤   roleOccupant
4e245a item dn,sort¤   "See Also"¤ ¤   seeAlso
9725b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
7f1088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
39e0d1 END
24af5a
63af5a
d9baab ##########################################################################
89c569 # Organizational Unit template
debaab ##########################################################################
c4b848 "Organizational Unit"
2e5562 "Organizational Units"
9fddaf "organization icon"
5eaf5a
eae9f3 # template options
6b095a ""
f3af5a
f0150d # objectclass list
36ecfd organizationalUnit
73e0d1 END
53af5a
e534ce # name of attribute to authenticate as
5d095a ""
73af5a
d61a61 # default attribute name to use when forming RDN of a new entry
66ba36 cn
1caf5a
0a80ce # default location when adding new entries
6f095a ""
9caf5a
134fc9 # rules used to define default values for new entries
8ae0d1 END
f2af5a
da2106 # Item list
34e5cb item cis¤   "Organization Unit Name"¤   ou
17aa5e item cis¤   "Title"¤¤   ¤   ¤   title
ad25b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
971088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
aae0d1 END
30af5a
23af5a
54af5a
4bbaab ##########################################################################
62fce2 # Application Entity template
5ebaab ##########################################################################
ac6f2e "Application Entity"
19741b "Application Entities"
3c96ad "application icon"
6aaf5a
1ce9f3 # template options
c3095a ""
0caf5a
e7150d # objectclass list
c4067d applicationEntity
08e0d1 END
--53c3 00087b4d2b5401000a8 Page 7 of ldaptemplates.conf
e0af5a
3134ce # name of attribute to authenticate as
34095a ""
c8af5a
1e1a61 # default attribute name to use when forming RDN of a new entry
e0ba36 cn
daaf5a
5580ce # default location when adding new entries
91095a ""
17af5a
d84fc9 # rules used to define default values for new entries
5ce0d1 END
8aaf5a
362106 # Item list
30eae4 item cis,sort¤  "Name"¤ ¤   ¤   cn
7cc924 item cis¤   "Location"¤ ¤   l
93cfb0 item cis¤   "Description"¤  ¤   description
e725b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
db1088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
2fe0d1 END
75af5a
43baab ##########################################################################
38489e # Document template
24baab ##########################################################################
dcc94c "Document"
461337 "Documents"
06b8eb "document icon"
88af5a
20e9f3 # template options
66095a ""
89af5a
52150d # objectclass list
e596bd document
4182e2 umichDocument
efe0d1 END
11af5a
9534ce # name of attribute to authenticate as
5a095a ""
eeaf5a
c01a61 # default attribute name to use when forming RDN of a new entry
49ba36 cn
fbaf5a
1880ce # default location when adding new entries
ff095a ""
e4af5a
974fc9 # rules used to define default values for new entries
22e0d1 END
55af5a
d0a601 #
0b2106 # Item list
da089e item cis¤   "Document ID"¤  ¤   documentIdentifier
2471b1 item cis¤   "Title"¤¤   ¤   documentTitle
bd31a4 item cis¤   "Series Title"¤ ¤   documentSeriesTitle
432fb6 item cis¤   "Version"¤  ¤   documentVersion
6ba3bd item cis,sort¤  "Service Area"¤ ¤   serviceArea
9817e4 item mls¤   "Abstract"¤ ¤   multiLineAbstract
cb6553 item url¤   "More Info (URL)"¤  labeledURL
1f8c35 item dn,sort¤   "Availability"¤ ¤   documentAvailable
1a245a item dn,sort¤   "See Also"¤ ¤   seeAlso
6acbc3 item cis,sort¤  "Platform"¤ ¤   platform
78ef5e item cis,sort¤  "Product"¤  ¤   product
ad8445 item cis,sort¤  "Keyword"¤  ¤   keywords
bea762 item dn,sort¤   "Author"¤   ¤   documentAuthor
5125b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
a11088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
311801 item dn,required¤   "Owner"¤¤   owner
30e0d1 END
88af5a
a3baab ##########################################################################
c9ebbe # Document description template
dabaab ##########################################################################
87308e "DocumentDescription"
--b87f 000c9f81065401000a8 Page 8 of ldaptemplates.conf
0ff6d0 "DocumentDescriptions"
c192bd "document description icon"
6daf5a
89e9f3 # template options
74095a ""
c6af5a
55150d # objectclass list
162834 documentDescription
86e0d1 END
fdaf5a
cd34ce # name of attribute to authenticate as
8f095a ""
e4af5a
671a61 # default attribute name to use when forming RDN of a new entry
78ba36 cn
2eaf5a
2380ce # default location when adding new entries
fa095a ""
6baf5a
224fc9 # rules used to define default values for new entries
6ee0d1 END
78af5a
42a601 #
f82106 # Item list
84d7d2 item mls¤   "Description"¤  ¤   multilineDescription
0b6553 item url¤   "More Info (URL)"¤  labeledURL
2b25b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
b51088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
ad1801 item dn,required¤   "Owner"¤¤   owner
90e0d1 END
b9af5a
f5baab ##########################################################################
ec1760 # Image template
ccbaab ##########################################################################
916ed5 "Image"
521ad8 "Images"
0d44ef "image icon"
53af5a
15e9f3 # template options
20095a ""
8faf5a
a6150d # objectclass list
0ac7a5 image
dae0d1 END
97af5a
6834ce # name of attribute to authenticate as
90095a ""
07af5a
0b1a61 # default attribute name to use when forming RDN of a new entry
8cba36 cn
5baf5a
5d80ce # default location when adding new entries
d7095a ""
75af5a
544fc9 # rules used to define default values for new entries
eee0d1 END
7eaf5a
1aa601 #
732106 # Item list
4fe945 item cis¤   "Name"¤ ¤   ¤   cn
ebd7d2 item mls¤   "Description"¤  ¤   multilineDescription
0552d6 item jpegbtn¤   "View Photo(s)"¤¤   jpegPhoto
43b6cd item cis¤   "Citation"¤ ¤   citation
10265f item cis¤   "Copyright"¤¤   copyright
372980 item cis¤   "Keywords"¤ ¤   keywords
5825b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
a01088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
621801 item dn,required¤   "Owner"¤¤   owner
58e0d1 END
e4af5a
f4af5a
c9af5a
--f785 000ee327671401000a8 Page 9 of ldaptemplates.conf
5ebaab ##########################################################################
d6ab34 # Country template
81baab ##########################################################################
92011f "Country"
085119 "Countries"
82e622 "country icon"
0daf5a
0ce9f3 # template options
78095a ""
bbaf5a
14150d # objectclass list
119901 friendlyCountry
fae0d1 END
3aaf5a
c234ce # name of attribute to authenticate as
17095a ""
30af5a
6b1a61 # default attribute name to use when forming RDN of a new entry
55e067 c
44af5a
cf80ce # default location when adding new entries
4e095a ""
24af5a
3f4fc9 # rules used to define default values for new entries
c1e0d1 END
5daf5a
202106 # Item list
09affa item cis¤   "Country Name"¤ ¤   co
ed4ec0 item cis¤   "Country Code"¤ ¤   c
86cfb0 item cis¤   "Description"¤  ¤   description
d625b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
4f1088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
7ae0d1 END
46af5a
24baab ##########################################################################
28d25b # Locality template
95baab ##########################################################################
b0e9b1 "Locality"
c70fb0 "Localities"
4cd46a "locality icon"
9caf5a
c9e9f3 # template options
ec095a ""
69af5a
bf150d # objectclass list
a9618c locality
89e0d1 END
67af5a
8c34ce # name of attribute to authenticate as
54095a ""
49af5a
2f1a61 # default attribute name to use when forming RDN of a new entry
4563af l
5aaf5a
1280ce # default location when adding new entries
1a095a ""
45af5a
a34fc9 # rules used to define default values for new entries
1ce0d1 END
ecaf5a
4da601 #
7f2106 # Item list
fcfa16 item cis¤   "Name" ¤¤   ¤   l
ba25b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
741088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
79e0d1 END
73af5a
a7af5a
26baab ##########################################################################
982cc1 # "Other Addresses" template
bcbaab ##########################################################################
eefe8b "Others Addresses"
--ab4d 001bc2f6e75401000a8 Page 10 of ldaptemplates.conf
581165 "Other Addresses"
1eac32 "other addr icon"
caaf5a
2ae9f3 # template options
b5579e "altview"
87af5a
b6150d # objectclass list
65e0d1 END
d9af5a
bc34ce # name of attribute to authenticate as
9a095a ""
1eaf5a
6a1a61 # default attribute name to use when forming RDN of a new entry
21095a ""
c5af5a
b180ce # default location when adding new entries
9d095a ""
18af5a
be4fc9 # rules used to define default values for new entries
c0e0d1 END
94af5a
ca2106 # Item list
e35214 item cis¤   "Street Address"¤   streetAddress
c79b67 item cis¤   "Locality"¤ ¤   l
d6ccd7 item cis¤   "State or Province"¤st
e68931 item cis¤   "Postal Code"¤  ¤   postalCode
890422 item cis,hide¤  "X.400 Address"¤¤   mhsORAddresses
82f09e item cis,hide¤  "X.400 Address"¤¤   textEncodedORAddress
8f45cc Item cis¤   "Other Mailbox"¤¤   otherMailbox
c625b2 item time,ro¤   "Last Modified"¤¤   lastModifiedTime
be1088 item dn,ro¤ "Modified By"¤  ¤   lastModifiedBy
bce0d1 END
--ab7d 000b8a09278401000a9 Page 1 of modify.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
4e3558 ·* ·modify.c
7f495d ·*/
a2af5a
410c68 #ifndef lint·
d907d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
cc3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
d07454 #endif
0eaf5a
86feb2 #include <stdio.h>
2f324c #include <string.h>
8daf5a
8e24c3 #if PGPSOCKETSLDAP¤ /* jason */
7565aa #include "pgpSocketsLDAP.h"
65af5a
ebdb21 #else
96c583 #ifdef MACOS
dd65e0 #include "macos.h"
b1e962 #endif /* MACOS */
bfaf5a
811330 #if !defined( MACOS ) && !defined( DOS )
d9f15e #include <sys/types.h>
b6a394 #ifndef WIN32¤  ¤   /* marcd */
b766f2 #include <sys/socket.h>
e77454 #endif
5f7454 #endif
40df0f #endif /* PGPSOCKETSLDAP */
60af5a
78b779 #include "lber.h"
d9e990 #include "ldap.h"
f7745c #include "ldap-int.h"
07af5a
2e38e5 /*
cacbc3 ·* ldap_modify - initiate an ldap (and X.500) modify operation. ·Parameters:
b6775e ·*
044f03 ·*¤ ld¤ ¤   LDAP descriptor
4936e3 ·*¤ dn¤ ¤   DN of the object to modify
d7e14a ·*¤ mods¤   ¤   List of modifications to make. ·This is null-terminated
db5d34 ·*¤ ¤   ¤   array of struct ldapmod's, specifying the modifications
2ff9ac ·*¤ ¤   ¤   to perform.
c2775e ·*
37305c ·* Example:
3a37be ·*¤ LDAPMod¤*mods[] = {·
4adb37 ·*¤ ¤   ¤   { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
220a5a ·*¤ ¤   ¤   { LDAP_MOD_REPLACE, "sn", { "jensen", 0 } },
b78dd5 ·*¤ ¤   ¤   0
ad90d3 ·*¤ ¤   }
3163c9 ·*¤ msgid = ldap_modify( ld, dn, mods );
23495d ·*/
934d2f int
809902 ldap_modify( LDAP *ld, char *dn, LDAPMod **mods )
debb36 {
039c95 ¤   BerElement¤ *ber;
deb696 ¤   int¤¤   i, rc;
18af5a
b5d8af ¤   /*
1a4415 ¤   ·* A modify request looks like this:
88927c ¤   ·*¤ ModifyRequet ::= SEQUENCE {
077be1 ¤   ·*¤ ¤   object¤ ¤   DistinguishedName,
2b86e9 ¤   ·*¤ ¤   modifications¤  SEQUENCE OF SEQUENCE {
ae3ada ¤   ·*¤ ¤   ¤   operation¤  ENUMERATED {
4daff2 ¤   ·*¤ ¤   ¤   ¤   add¤(0),
820b2b ¤   ·*¤ ¤   ¤   ¤   delete¤ (1),
2bc3ed ¤   ·*¤ ¤   ¤   ¤   replace¤(2)
9542be ¤   ·*¤ ¤   ¤   },
cd8c33 ¤   ·*¤ ¤   ¤   modification¤   SEQUENCE {
c2501c ¤   ·*¤ ¤   ¤   ¤   type¤   AttributeType,
5356d5 ¤   ·*¤ ¤   ¤   ¤   values¤ SET OF AttributeValue
b8fe7e ¤   ·*¤ ¤   ¤   }
--41a6 0016e641e4d401000a9 Page 2 of modify.c
413c91 ¤   ·*¤ ¤   }
135203 ¤   ·*¤ }
c3a4e3 ¤   ·*/
fbaf5a
029d97 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 );
a1af5a
4247d1 ¤   /* create a message to send */
016826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
4649fa ¤   ¤   return( -1 );
b99371 ¤   }
8daf5a
f3cb5b ¤   if ( ber_printf( ber, "{it{s{", ++ld->ld_msgid, LDAP_REQ_MODIFY, dn )
329a76 ¤   ····== -1 ) {
4b3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
291ab1 ¤   ¤   ber_free( ber, 1 );
d149fa ¤   ¤   return( -1 );
f79371 ¤   }
4baf5a
8cdba2 ¤   /* for each modification to be performed... */
03b06d ¤   for ( i = 0; mods[i] != NULL; i++ ) {
94fed7 ¤   ¤   if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
375500 ¤   ¤   ¤   rc = ber_printf( ber, "{e{s[V]}}",
c573b2 ¤   ¤   ¤   ····mods[i]->mod_op & ~LDAP_MOD_BVALUES,
a07f62 ¤   ¤   ¤   ····mods[i]->mod_type, mods[i]->mod_bvalues );
7845a6 ¤   ¤   } else {
e5681a ¤   ¤   ¤   rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op,
c798a5 ¤   ¤   ¤   ····mods[i]->mod_type, mods[i]->mod_values );
190fe4 ¤   ¤   }
b6af5a
83fb58 ¤   ¤   if ( rc == -1 ) {
a92e44 ¤   ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
28b7ef ¤   ¤   ¤   ber_free( ber, 1 );
5d8e4f ¤   ¤   ¤   return( -1 );
620fe4 ¤   ¤   }
b29371 ¤   }
1eaf5a
c2602f ¤   if ( ber_printf( ber, "}}}" ) == -1 ) {
873614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
061ab1 ¤   ¤   ber_free( ber, 1 );
e049fa ¤   ¤   return( -1 );
149371 ¤   }
bbaf5a
48dd1f ¤   /* send the message */
5a4f58 ¤   return( send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber ));
b9efe6 }
ceaf5a
e14d2f int
6cfbdc ldap_modify_s( LDAP *ld, char *dn, LDAPMod **mods )
afbb36 {
c2da47 ¤   int¤¤   msgid;
003932 ¤   LDAPMessage¤*res;
45af5a
4711d4 ¤   if ( (msgid = ldap_modify( ld, dn, mods )) == -1 )
45df73 ¤   ¤   return( ld->ld_errno );
41af5a
5f19a3 ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
1cdf73 ¤   ¤   return( ld->ld_errno );
30af5a
e49595 ¤   return( ldap_result2error( ld, res, 1 ) );
0fefe6 }
6eaf5a
--fa16 000bab8435b401000aa Page 1 of modrdn.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
90d8c5 ·* ·modrdn.c
f8495d ·*/
e3af5a
ae0c68 #ifndef lint·
7007d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
ed3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
847454 #endif
69af5a
0efeb2 #include <stdio.h>
97324c #include <string.h>
95af5a
9c24c3 #if PGPSOCKETSLDAP¤ /* jason */
8365aa #include "pgpSocketsLDAP.h"
9daf5a
5bdb21 #else
a1c583 #ifdef MACOS
0465e0 #include "macos.h"
fae962 #endif /* MACOS */
ffaf5a
751330 #if !defined( MACOS ) && !defined( DOS )
f7f15e #include <sys/types.h>
4aa394 #ifndef WIN32¤  ¤   /* marcd */
2566f2 #include <sys/socket.h>
df7454 #endif
817454 #endif
0adf0f #endif /* PGPSOCKETSLDAP */
1eaf5a
ddb779 #include "lber.h"
42e990 #include "ldap.h"
5c745c #include "ldap-int.h"
bcaf5a
a838e5 /*
b686dc ·* ldap_modrdn2 - initiate an ldap (and X.500) modifyRDN operation. Parameters:
6a775e ·*
b14f03 ·*¤ ld¤ ¤   LDAP descriptor
a736e3 ·*¤ dn¤ ¤   DN of the object to modify
7cfa1f ·*¤ newrdn¤ ¤   RDN to give the object
c235dc ·*¤ deleteoldrdn¤   nonzero means to delete old rdn values from the entry
64775e ·*
7d305c ·* Example:
aff331 ·*¤ msgid = ldap_modrdn( ld, dn, newrdn );
e4495d ·*/
5b4d2f int
fbbaa2 ldap_modrdn2( LDAP *ld, char *dn, char *newrdn, int deleteoldrdn )
85bb36 {
d79c95 ¤   BerElement¤ *ber;
18af5a
13d8af ¤   /*
3772bb ¤   ·* A modify rdn request looks like this:
99976d ¤   ·*¤ ModifyRDNRequest ::= SEQUENCE {
fa6959 ¤   ·*¤ ¤   entry¤  ¤   DistinguishedName,
33bbda ¤   ·*¤ ¤   newrdn¤ ¤   RelativeDistinguishedName,
166e2b ¤   ·*¤ ¤   deleteoldrdn¤   BOOLEAN
5c5203 ¤   ·*¤ }
f1a4e3 ¤   ·*/
f8af5a
a9674b ¤   Debug( LDAP_DEBUG_TRACE, "ldap_modrdn\n", 0, 0, 0 );
08af5a
7747d1 ¤   /* create a message to send */
b06826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
0a49fa ¤   ¤   return( -1 );
3c9371 ¤   }
3aaf5a
4a825c ¤   if ( ber_printf( ber, "{it{ssb}}", ++ld->ld_msgid, LDAP_REQ_MODRDN, dn,
0fc51f ¤   ····newrdn, deleteoldrdn ) == -1 ) {
ed3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
ee1ab1 ¤   ¤   ber_free( ber, 1 );
ba49fa ¤   ¤   return( -1 );
--f42f 001274d4821401000aa Page 2 of modrdn.c
a19371 ¤   }
93af5a
b3dd1f ¤   /* send the message */
2a1601 ¤   return ( send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber ));
6cefe6 }
34af5a
0e4d2f int
eff383 ldap_modrdn( LDAP *ld, char *dn, char *newrdn )
ccbb36 {
de2957 ¤   return( ldap_modrdn2( ld, dn, newrdn, 1 ) );
28efe6 }
12af5a
3c4d2f int
556d5a ldap_modrdn2_s( LDAP *ld, char *dn, char *newrdn, int deleteoldrdn )
58bb36 {
fbda47 ¤   int¤¤   msgid;
043932 ¤   LDAPMessage¤*res;
56af5a
b0385e ¤   if ( (msgid = ldap_modrdn2( ld, dn, newrdn, deleteoldrdn )) == -1 )
79df73 ¤   ¤   return( ld->ld_errno );
3faf5a
3b19a3 ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 )
72df73 ¤   ¤   return( ld->ld_errno );
b4af5a
769595 ¤   return( ldap_result2error( ld, res, 1 ) );
d2efe6 }
35af5a
9c4d2f int
10ceb5 ldap_modrdn_s( LDAP *ld, char *dn, char *newrdn )
5bbb36 {
d604b2 ¤   return( ldap_modrdn2_s( ld, dn, newrdn, 1 ) );
27efe6 }
--e8bc 000ff56e789401000ab Page 1 of open.c
bc38e5 /*
5ce36d ·* ·Copyright (c) 1995 Regents of the University of Michigan.
a8e4d4 ·* ·All rights reserved.
42775e ·*
ef4acb ·* ·open.c
bc495d ·*/
49af5a
0b66a8 #ifndef lint
5ba4ec static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University "
383efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
ab7454 #endif
b1af5a
2cfeb2 #include <stdio.h>
56324c #include <string.h>
2aaf5a
8f71fa #if PGPSOCKETSLDAP¤ ¤   /* jason */
1665aa #include "pgpSocketsLDAP.h"
5eaf5a
c5db21 #else
aec583 #ifdef MACOS
cdbea3 #include <stdlib.h>
c465e0 #include "macos.h"
88e962 #endif /* MACOS */
aaaf5a
ddfdef #if defined( DOS ) || defined( _WIN32 )
be01b0 #ifdef DOS
e1f2ef #include "msdos.h"
ab7454 #endif
3bbea3 #include <stdlib.h>
a5bc39 #endif /* DOS */
7caf5a
926cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
7d2d5f #include <winsock.h>
607454 #endif
29af5a
6b3faf #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
705d8c #include <sys/time.h>
6af15e #include <sys/types.h>
7166f2 #include <sys/socket.h>
b6ea1a #ifndef VMS
a04a90 #include <sys/param.h>
cd7454 #endif
cd6c19 #include <netinet/in.h>
c27454 #endif
f7df0f #endif /* PGPSOCKETSLDAP */
59af5a
39b779 #include "lber.h"
dde990 #include "ldap.h"
3e745c #include "ldap-int.h"
3baf5a
902639 #ifdef LDAP_DEBUG
f78753 int¤ldap_debug;
1a7454 #endif
70af5a
7bea0b #ifndef INADDR_LOOPBACK
64cbf0 #define INADDR_LOOPBACK¤((unsigned long) 0x7f000001)
fd7454 #endif
b2af5a
1059cc #ifndef MAXHOSTNAMELEN
c9e30d #define MAXHOSTNAMELEN ·64
fa7454 #endif
20af5a
44af5a
dd38e5 /*
815758 ·* ldap_open - initialize and connect to an ldap server. ·A magic cookie to
bd597d ·* be used for future communication is returned on success, NULL on failure.
501c23 ·* "host" may be a space-separated list of hosts or IP addresses
ce775e ·*
1b305c ·* Example:
012af3 ·*¤ LDAP¤   *ld;
b96987 ·*¤ ld = ldap_open( hostname, port );
ff495d ·*/
--a4b8 00022a78282401000ab Page 2 of open.c
e0af5a
9f09b3 LDAP *
c0ba2e ldap_open( char *host, int port )
0ebb36 {
0bbfbf ¤   LDAP¤   ¤   *ld;
db7f8d #ifdef LDAP_REFERRALS
70ddd4 ¤   LDAPServer¤ *srv;
2390e2 #endif /* LDAP_REFERRALS */
58af5a
0f6787 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_open\n", 0, 0, 0 );
faaf5a
2d7d44 ¤   if (( ld = ldap_init( host, port )) == NULL ) {
19ef86 ¤   ¤   return( NULL );
bb9371 ¤   }
3caf5a
197f8d #ifdef LDAP_REFERRALS
b65ea5 ¤   if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer ))) ==
0724f5 ¤   ····NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host =
683574 ¤   ····strdup( ld->ld_defhost )) == NULL )) {
4d141a ¤   ¤   ldap_ld_free( ld, 0 );
92ef86 ¤   ¤   return( NULL );
ea9371 ¤   }
eaf2af ¤   srv->lsrv_port = ld->ld_defport;
e7af5a
742e00 ¤   if (( ld->ld_defconn = new_connection( ld, &srv, 1,1,0 )) == NULL ) {
be5ac8 ¤   ¤   if ( ld->ld_defhost != NULL ) free( srv->lsrv_host );
658a3f ¤   ¤   free( (char *)srv );
3d141a ¤   ¤   ldap_ld_free( ld, 0 );
e6ef86 ¤   ¤   return( NULL );
119371 ¤   }
705700 ¤   ++ld->ld_defconn->lconn_refcnt;¤/* so it never gets closed/freed */
c3af5a
804267 #else /* LDAP_REFERRALS */
574ba1 ¤   if ( open_ldap_connection( ld, &ld->ld_sb, ld->ld_defhost,
249c82 ¤   ····ld->ld_defport, &ld->ld_host, 0 ) < 0 ) {
6d141a ¤   ¤   ldap_ld_free( ld, 0 );
01ef86 ¤   ¤   return( NULL );
639371 ¤   }
5c90e2 #endif /* LDAP_REFERRALS */
cdaf5a
490667 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_open successful, ld_host is %s\n",
ea45d7 ¤   ¤   ( ld->ld_host == NULL ) ? "(null)" : ld->ld_host, 0, 0 );
5baf5a
2e26ac ¤   return( ld );
70efe6 }
c9af5a
c1af5a
d938e5 /*
7acf8b ·* ldap_init - initialize the LDAP library. ·A magic cookie to be used for
6f1f56 ·* future communication is returned on success, NULL on failure.
73391a ·* "defhost" may be a space-separated list of hosts or IP addresses
02775e ·*
71305c ·* Example:
6c2af3 ·*¤ LDAP¤   *ld;
2cf8a2 ·*¤ ld = ldap_open( default_hostname, default_port );
02495d ·*/
5909b3 LDAP *
e3a624 ldap_init( char *defhost, int defport )
78bb36 {
1c60a9 ¤   LDAP¤   ¤   ¤   *ld;
adaf5a
9aadb6 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 );
fbaf5a
47af5a
cab17d ¤   if ( (ld = (LDAP *) calloc( 1, sizeof(LDAP) )) == NULL ) {
1eef86 ¤   ¤   return( NULL );
af9371 ¤   }
64af5a
727f8d #ifdef LDAP_REFERRALS
3b4094 ¤   if (( ld->ld_selectinfo = new_select_info()) == NULL ) {
ee13bd ¤   ¤   free( (char*)ld );
22ef86 ¤   ¤   return( NULL );
--3774 000d2ce72af401000ab Page 3 of open.c
a19371 ¤   }
4e7e44 ¤   ld->ld_options = LDAP_OPT_REFERRALS;
1890e2 #endif /* LDAP_REFERRALS */
bfaf5a
66d470 ¤   if ( defhost != NULL &&
4c7dfa ¤   ····( ld->ld_defhost = strdup( defhost )) == NULL ) {
457f8d #ifdef LDAP_REFERRALS
21db61 ¤   ¤   free_select_info( ld->ld_selectinfo );
4a90e2 #endif /* LDAP_REFERRALS */
2a13bd ¤   ¤   free( (char*)ld );
b4ef86 ¤   ¤   return( NULL );
1e9371 ¤   }
40af5a
31af5a
67f64e ¤   ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport;
3ce9e7 ¤   ld->ld_version = LDAP_VERSION;
b7dcaf ¤   ld->ld_lberoptions = LBER_USE_DER;
c8d5a5 ¤   ld->ld_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
e4af5a
5eb00a #if defined( STR_TRANSLATION ) && defined( LDAP_DEFAULT_CHARSET )
addea2 ¤   ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS;
34e3e3 #if LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET
8b0433 ¤   ldap_set_string_translators( ld, ldap_8859_to_t61, ldap_t61_to_8859 );
91e5a7 #endif /* LDAP_CHARSET_8859 == LDAP_DEFAULT_CHARSET */
c35a01 #endif /* STR_TRANSLATION && LDAP_DEFAULT_CHARSET */
a8af5a
8726ac ¤   return( ld );
a9efe6 }
9caf5a
37af5a
104d2f int
89a931 open_ldap_connection( LDAP *ld, Sockbuf *sb, char *host, int defport,
89aa1d ¤   char **krbinstancep, int async )
eebb36 {
fb3e15 ¤   int ¤   ¤   ¤   rc, port;
05a747 ¤   char¤   ¤   ¤   *p, *q, *r;
6bed88 ¤   char¤   ¤   ¤   *curhost, hostname[ 2*MAXHOSTNAMELEN ];
82af5a
0a9e79 ¤   (void) ld;
6267c5 ¤
600ade ¤   Debug( LDAP_DEBUG_TRACE, "open_ldap_connection\n", 0, 0, 0 );
7baf5a
935289 ¤   defport = PGPHostToNetShort( (short) defport );
05af5a
f5c4ad ¤   if ( host != NULL ) {
b07155 ¤   ¤   for ( p = host; p != NULL && *p != '\0'; p = q ) {
84d267 ¤   ¤   ¤   if (( q = strchr( p, ' ' )) != NULL ) {
4401bd ¤   ¤   ¤   ¤   strncpy( hostname, p, q - p );
eb1baa ¤   ¤   ¤   ¤   hostname[ q - p ] = '\0';
40a505 ¤   ¤   ¤   ¤   curhost = hostname;
94b00b ¤   ¤   ¤   ¤   while ( *q == ' ' ) {
badc8d ¤   ¤   ¤   ¤   ····++q;
a52613 ¤   ¤   ¤   ¤   }
7a042d ¤   ¤   ¤   } else {
634818 ¤   ¤   ¤   ¤   curhost = p;¤   /* avoid copy if possible */
e9a3cf ¤   ¤   ¤   ¤   q = NULL;
7ca3a6 ¤   ¤   ¤   }
e7af5a
de2398 ¤   ¤   ¤   if (( r = strchr( curhost, ':' )) != NULL ) {
a38ded ¤   ¤   ¤   ····if ( curhost != hostname ) {
56573a ¤   ¤   ¤   ¤   strcpy( hostname, curhost );¤   /* now copy */
0f119d ¤   ¤   ¤   ¤   r = hostname + ( r - curhost );
eea505 ¤   ¤   ¤   ¤   curhost = hostname;
77da85 ¤   ¤   ¤   ····}
cabcb7 ¤   ¤   ¤   ····*r++ = '\0';
42f6ce ¤   ¤   ¤   ····port = PGPHostToNetShort( (short)atoi( r ));
75042d ¤   ¤   ¤   } else {
128333 ¤   ¤   ¤   ····port = defport;
dba3a6 ¤   ¤   ¤   }
d8af5a
b2e588 ¤   ¤   ¤   if (( rc = connect_to_host( sb, curhost, 0L,
d286cf ¤   ¤   ¤   ····port, async )) != -1 ) {
--f0fe 00163aed8db401000ab Page 4 of open.c
72f622 ¤   ¤   ¤   ¤   break;
36a3a6 ¤   ¤   ¤   }
7b0fe4 ¤   ¤   }
c2f037 ¤   } else {
994a3f ¤   ¤   rc = connect_to_host( sb, NULL, PGPHostToNetLong( INADDR_LOOPBACK ),
ca0b41 ¤   ¤   ····defport, async );
6a9371 ¤   }
e4af5a
e53ced ¤   if ( rc == -1 ) {
b157f8 ¤   ¤   return( rc );
9a9371 ¤   }
23af5a
044314 ¤   if ( krbinstancep != NULL ) {
065ffa #ifdef KERBEROS
21f42a ¤   ¤   if (( *krbinstancep = host_connected_to( sb )) != NULL &&
1f717f ¤   ¤   ····( p = strchr( *krbinstancep, '.' )) != NULL ) {
5604fe ¤   ¤   ¤   *p = '\0';
960fe4 ¤   ¤   }
c53104 #else /* KERBEROS */
1ee34b ¤   ¤   krbinstancep = NULL;
74999d #endif /* KERBEROS */
5d9371 ¤   }
cdaf5a
d3ea61 ¤   return( 0 );
63efe6 }
--04af 000e1e5cc7b401000ac Page 1 of os-ip.c
bc38e5 /*
5ce36d ·* ·Copyright (c) 1995 Regents of the University of Michigan.
a8e4d4 ·* ·All rights reserved.
42775e ·*
4311d2 ·* ·os-ip.c -- platform-specific TCP & UDP related code
c0495d ·*/
c9af5a
c466a8 #ifndef lint
e3a4ec static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University "
553efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
607454 #endif
48af5a
0efeb2 #include <stdio.h>
15324c #include <string.h>
0e495d #include <errno.h>
b7af5a
20ec08 #ifdef _WIN32
be1044 #include <io.h>
605332 #include <winsock.h>¤   ¤   /* marcd */
6aae98 #define EHOSTUNREACH ···········WSAEHOSTUNREACH
5888eb #else /* _WIN32 */
a55d8c #include <sys/time.h>
d5f15e #include <sys/types.h>
d866f2 #include <sys/socket.h>
a26c19 #include <netinet/in.h>
962a51 #include <netdb.h>
831ad7 #endif /* _WIN32 */
5b5196 #ifdef _AIX
e9adab #include <sys/select.h>
44e564 #endif /* _AIX */
764edf #ifdef VMS
e97ba6 #include "ucx_select.h"
36361d #endif /* VMS */
922a9a #include "portable.h"
fdb779 #include "lber.h"
6de990 #include "ldap.h"
89af5a
9a7f8d #ifdef LDAP_REFERRALS
bcf375 #ifdef USE_SYSCONF
9417c2 #include <unistd.h>
247d11 #endif /* USE_SYSCONF */
6bb7e5 #ifdef notyet
79ecad #ifdef NEED_FILIO
57389f #include <sys/filio.h>
83a180 #else /* NEED_FILIO */
93c051 #include <sys/ioctl.h>
df4687 #endif /* NEED_FILIO */
9fdb56 #endif /* notyet */
c890e2 #endif /* LDAP_REFERRALS */
95af5a
4eb3e6 #if defined(WINSOCK) || defined(WIN32)¤ ¤   /* marcd */
2acc04 #define tcp_close( s )¤ ¤   closesocket( s ); /*WSACleanup();*/
9473e0 #else /* WINSOCK || WIN32 */
7bc583 #ifdef MACOS
ecd777 #define tcp_close( s )¤ ¤   tcpclose( s )
a66c94 #else /* MACOS */
fb01b0 #ifdef DOS
85b3f5 #ifdef PCNFS
11fc34 #define tcp_close( s )¤ ¤   close( s )
b11b77 #endif /* PCNFS */
556382 #ifdef NCSA
f7d13d #define tcp_close( s )¤ ¤   netclose( s ); netshut()
818682 #endif /* NCSA */
26aad8 #else /* DOS */
39fc34 #define tcp_close( s )¤ ¤   close( s )
4abc39 #endif /* DOS */
4ee962 #endif /* MACOS */
cb740b #endif /* WINSOCK || WIN32 */
c3af5a
984d2f int
1bfba8 connect_to_host( Sockbuf *sb, char *host, unsigned long address,
e14161 ¤   int port, int async )
--c617 000233f4b79401000ac Page 2 of os-ip.c
bc38e5 /*
f95f6a ·* if host == NULL, connect using address
d04add ·* "address" and "port" must be in network byte order
377f4f ·* zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
465732 ·* async is only used ifdef LDAP_REFERRALS (non-0 means don't wait for connect)
716d2c ·* XXX async is not used yet!
67495d ·*/
d3bb36 {
46bd79 ¤   int¤¤   ¤   rc, i, s, connected, use_hp;
b6dbaa ¤   struct sockaddr_in¤ sin;
6bd676 ¤   struct hostent¤ ¤   *hp;
9cb7e5 #ifdef notyet
277f8d #ifdef LDAP_REFERRALS
88fc6e ¤   int¤¤   ¤   status;¤/* for ioctl call */
b290e2 #endif /* LDAP_REFERRALS */
43db56 #endif /* notyet */
d3af5a
880c85 ¤   Debug( LDAP_DEBUG_TRACE, "connect_to_host: %s:%d\n",
1b7e65 ¤   ····(host == NULL ) ? "(by address)" : host,
842047 ¤   ¤   PGPNetToHostShort( (short) port ), 0);
ebaf5a
32a393 ¤   connected = use_hp = 0;
e5af5a
c87f4a ¤   if ( host != NULL && ( address = inet_addr( host )) == -1 ) {
f407ab ¤   ¤   if ( (hp = gethostbyname( host )) == NULL ) {
6c4f11 ¤   ¤   ¤   errno = EHOSTUNREACH;¤  /* not exactly right, but... */
4a8e4f ¤   ¤   ¤   return( -1 );
5c0fe4 ¤   ¤   }
cd467e ¤   ¤   use_hp = 1;
4a9371 ¤   }
2baf5a
f5f83f ¤   rc = -1;
04bbee ¤   for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ ) {
24a322 ¤   ¤   if (( s = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
158e4f ¤   ¤   ¤   return( -1 );
630fe4 ¤   ¤   }
f6b7e5 #ifdef notyet
6c7f8d #ifdef LDAP_REFERRALS
b546f6 ¤   ¤   status = 1;
b76a96 ¤   ¤   if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
e11c37 ¤   ¤   ¤   Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
811cf2 ¤   ¤   ¤   ····s, 0, 0 );
f40fe4 ¤   ¤   }
9190e2 #endif /* LDAP_REFERRALS */
9ddb56 #endif /* notyet */
1d39bc ¤   ¤   (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
f47059 ¤   ¤   sin.sin_family = AF_INET;
10d38c ¤   ¤   sin.sin_port = port;
359de9 ¤   ¤   SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
758cb9 ¤   ¤   ····( use_hp ? (char *) hp->h_addr_list[ i ] :
d306a5 ¤   ¤   ····(char *) &address ), sizeof( sin.sin_addr.s_addr) );
59af5a
88586a ¤   ¤   if ( connect( s, (struct sockaddr *)&sin,
6560fc ¤   ¤   ····sizeof( struct sockaddr_in )) >= 0 ) {
f6abec ¤   ¤   ¤   connected = 1;
68e256 ¤   ¤   ¤   rc = 0;
d7cdcb ¤   ¤   ¤   break;
3445a6 ¤   ¤   } else {
5cb7e5 #ifdef notyet
a77f8d #ifdef LDAP_REFERRALS
86935b #ifdef EAGAIN
3c3e65 ¤   ¤   ¤   if ( errno == EINPROGRESS || errno == EAGAIN ) {
649760 #else /* EAGAIN */
c6ff24 ¤   ¤   ¤   if ( errno == EINPROGRESS ) {
62055c #endif /* EAGAIN */
70c3e3 ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
05eab5 ¤   ¤   ¤   ¤   ¤   "connect would block...\n", 0, 0, 0 );
cb5290 ¤   ¤   ¤   ¤   rc = -2;
5af622 ¤   ¤   ¤   ¤   break;
06a3a6 ¤   ¤   ¤   }
da90e2 #endif /* LDAP_REFERRALS */
23db56 #endif /* notyet */
--81a3 000ef4dc12b401000ac Page 3 of os-ip.c
e0af5a
3000a2 #ifdef LDAP_DEBUG¤  ¤
750f7f ¤   ¤   ¤   if ( ldap_debug & LDAP_DEBUG_TRACE ) {
04687f ¤   ¤   ¤   ¤   perror( (char *)inet_ntoa( sin.sin_addr ));
fca3a6 ¤   ¤   ¤   }
6d7454 #endif
ed30d4 ¤   ¤   ¤   close( s );
246860 ¤   ¤   ¤   if ( !use_hp ) {
cdf622 ¤   ¤   ¤   ¤   break;
a0a3a6 ¤   ¤   ¤   }
180fe4 ¤   ¤   }
899371 ¤   }
a7af5a
f09ec8 ¤   sb->sb_sd = s;
efaf5a
0db4aa ¤   if ( connected ) {
77b7e5 #ifdef notyet
fa7f8d #ifdef LDAP_REFERRALS
ff1c2a ¤   ¤   status = 0;
37ca15 ¤   ¤   if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
501c37 ¤   ¤   ¤   Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
601cf2 ¤   ¤   ¤   ····s, 0, 0 );
af0fe4 ¤   ¤   }
1c90e2 #endif /* LDAP_REFERRALS */
ccdb56 #endif /* notyet */
20af5a
7bd9d7 ¤   ¤   Debug( LDAP_DEBUG_TRACE, "sd %d connected to: %s\n",
3a5a04 ¤   ¤   ····s, inet_ntoa( sin.sin_addr ), 0 );
e49371 ¤   }
7daf5a
fc6d62 ¤   return( rc );
73efe6 }
0eaf5a
aaaf5a
b3314a void
aaff21 close_connection( Sockbuf *sb )
e7bb36 {
bfc1d8 ····tcp_close( sb->sb_sd );
69efe6 }
79af5a
97af5a
f25ffa #ifdef KERBEROS
9911e4 char *
0fc805 host_connected_to( Sockbuf *sb )
19bb36 {
f7d676 ¤   struct hostent¤ ¤   *hp;
65d9ac ¤   char¤   ¤   ¤   *p;
e54bd7 ¤   int¤¤   ¤   len;
fddbaa ¤   struct sockaddr_in¤ sin;
44af5a
b72c9f ¤   (void)memset( (char *)&sin, 0, sizeof( struct sockaddr_in ));
a3533a ¤   len = sizeof( sin );
30648e ¤   if ( getpeername( sb->sb_sd, (struct sockaddr *)&sin, &len ) == -1 ) {
dbef86 ¤   ¤   return( NULL );
259371 ¤   }
89af5a
3cd8af ¤   /*
49cd84 ¤   ·* do a reverse lookup on the addr to get the official hostname.
d11ce4 ¤   ·* this is necessary for kerberos to work right, since the official
446b28 ¤   ·* hostname is used as the kerberos instance.
8ba4e3 ¤   ·*/
329833 ¤   if (( hp = gethostbyaddr( (char *) &sin.sin_addr,
6dda78 ¤   ····sizeof( sin.sin_addr ), AF_INET )) != NULL ) {
ff236c ¤   ¤   if ( hp->h_name != NULL ) {
2fa2dd ¤   ¤   ¤   return( strdup( hp->h_name ));
b10fe4 ¤   ¤   }
c89371 ¤   }
cbaf5a
639572 ¤   return( NULL );
35efe6 }
98999d #endif /* KERBEROS */
efaf5a
--1b0b 00053b7f811401000ac Page 4 of os-ip.c
e0af5a
f47f8d #ifdef LDAP_REFERRALS
03366d /* for UNIX */
60a5e2 struct selectinfo {
87a01e ¤   fd_set¤ si_readfds;
cda506 ¤   fd_set¤ si_writefds;
4344a3 ¤   fd_set¤ si_use_readfds;
0bcb8c ¤   fd_set¤ si_use_writefds;
9782f7 };
6daf5a
baaf5a
3d314a void
8e4f32 mark_select_write( LDAP *ld, Sockbuf *sb )
03bb36 {
1e9edc ¤   struct selectinfo¤  *sip;
60af5a
1a0ea5 ¤   sip = (struct selectinfo *)ld->ld_selectinfo;
c3af5a
5ccc25 ¤   if ( !FD_ISSET( sb->sb_sd, &sip->si_writefds )) {
19185b ¤   ¤   FD_SET( sb->sb_sd, &sip->si_writefds );
d89371 ¤   }
1befe6 }
a0af5a
61af5a
c2314a void
f5e00e mark_select_read( LDAP *ld, Sockbuf *sb )
03bb36 {
cf9edc ¤   struct selectinfo¤  *sip;
f2af5a
2f0ea5 ¤   sip = (struct selectinfo *)ld->ld_selectinfo;
e8af5a
81e84f ¤   if ( !FD_ISSET( sb->sb_sd, &sip->si_readfds )) {
b56d09 ¤   ¤   FD_SET( sb->sb_sd, &sip->si_readfds );
759371 ¤   }
6befe6 }
09af5a
44af5a
f9314a void
357ba1 mark_select_clear( LDAP *ld, Sockbuf *sb )
42bb36 {
1c9edc ¤   struct selectinfo¤  *sip;
3baf5a
070ea5 ¤   sip = (struct selectinfo *)ld->ld_selectinfo;
f9af5a
c235b4 ¤   FD_CLR( sb->sb_sd, &sip->si_writefds );
87e0e5 ¤   FD_CLR( sb->sb_sd, &sip->si_readfds );
27efe6 }
7faf5a
beaf5a
584d2f int
2a64b3 is_write_ready( LDAP *ld, Sockbuf *sb )
b1bb36 {
aa9edc ¤   struct selectinfo¤  *sip;
a5af5a
6e0ea5 ¤   sip = (struct selectinfo *)ld->ld_selectinfo;
f7af5a
d7ae89 ¤   return( FD_ISSET( sb->sb_sd, &sip->si_use_writefds ));
ffefe6 }
3eaf5a
90af5a
954d2f int
c0159b is_read_ready( LDAP *ld, Sockbuf *sb )
32bb36 {
5b9edc ¤   struct selectinfo¤  *sip;
16af5a
b90ea5 ¤   sip = (struct selectinfo *)ld->ld_selectinfo;
75af5a
27e8c0 ¤   return( FD_ISSET( sb->sb_sd, &sip->si_use_readfds ));
dfefe6 }
89af5a
35af5a
539a44 void *
--2e34 0011b2e2392401000ac Page 5 of os-ip.c
d86c17 new_select_info()
85bb36 {
449edc ¤   struct selectinfo¤  *sip;
3faf5a
025ef6 ¤   if (( sip = (struct selectinfo *)calloc( 1,
037f07 ¤   ····sizeof( struct selectinfo ))) != NULL ) {
c1e044 ¤   ¤   FD_ZERO( &sip->si_readfds );
9d8137 ¤   ¤   FD_ZERO( &sip->si_writefds );
349371 ¤   }
d1af5a
6a9683 ¤   return( (void *)sip );
13efe6 }
89af5a
13af5a
e6314a void
47d757 free_select_info( void *sip )
95bb36 {
6e8d35 ¤   free( sip );
fbefe6 }
c7af5a
e1af5a
a74d2f int
06980b do_ldap_select( LDAP *ld, struct timeval *timeout )
65bb36 {
9c9edc ¤   struct selectinfo¤  *sip;
8af437 ¤   static int¤ ¤   tblsize;
f9af5a
b510c3 ¤   Debug( LDAP_DEBUG_TRACE, "do_ldap_select\n", 0, 0, 0 );
61af5a
f02a32 ¤   if ( tblsize == 0 ) {
bbf375 #ifdef USE_SYSCONF
43ddf0 ¤   ¤   tblsize = sysconf( _SC_OPEN_MAX );
050949 #else /* USE_SYSCONF */
54f88a ¤   ¤   tblsize = getdtablesize();
347d11 #endif /* USE_SYSCONF */
b49371 ¤   }
76af5a
8c0ea5 ¤   sip = (struct selectinfo *)ld->ld_selectinfo;
9d112e ¤   sip->si_use_readfds = sip->si_readfds;
63035a ¤   sip->si_use_writefds = sip->si_writefds;
0067c5 ¤
015e0f ¤   return( select( tblsize, &sip->si_use_readfds, &sip->si_use_writefds,
87d15f ¤   ····NULL, timeout ));
88efe6 }
1b90e2 #endif /* LDAP_REFERRALS */
--f130 000eb5f564d401000ad Page 1 of regex.c
a82a9a #include "portable.h"
3caf5a
51d472 #if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || \
75b62b ····defined( NEED_BSDREGEX ) || defined(PGPSOCKETSLDAP) /* jason */
531b16 #include "regex.h"
7eaf5a
c538e5 /*
934ce8 ·* regex - Regular expression pattern matching ·and replacement
1d775e ·*
db239e ·* By: ·Ozan S. Yigit (oz)
541204 ·* ·····Dept. of Computer Science
d329d9 ·* ·····York University
f2775e ·*
1ebee3 ·* These routines are the PUBLIC DOMAIN equivalents of regex
bb9c89 ·* routines as found in 4.nBSD UN*X, with minor extensions.
d5775e ·*
e41662 ·* These routines are derived from various implementations found
6076da ·* in software tools books, and Conroy's grep. They are NOT derived
482475 ·* from licensed/restricted software.
5e0dc6 ·* For more interesting/academic/complicated implementations,
0b6736 ·* see Henry Spencer's regexp routines, or GNU Emacs pattern
979a40 ·* matching module.
92775e ·*
8847d0 ·* Modification history:
fe775e ·*
9feff9 ·* $Log: regex.c,v $
268d0d ·* Revision 1.3 ·1998/02/18 13:19:59 ·jason
bef4dd ·* Complete Keyserver API
89775e ·*
86c5f6 ·* Revision 1.2 ·1997/10/21 01:07:12 ·marcd
d3b6a1 ·* Reformated for 80 char margins
93775e ·*
4dda37 ·* Revision 1.1.1.1 ·1997/10/04 19:17:00 ·marcd
313e6c ·* Src tree restructuring after r1.0
c3775e ·*
c04f0f ·* Revision 1.3 ·1997/06/09 18:25:50 ·heller
dcf4c3 ·* Minor changes for Mac client compilation.
05775e ·*
0d2a7d ·* Revision 1.2 ·1997/06/05 17:53:12 ·marcd
90b2fa ·* Port to NT and initial keyserver functions
3f775e ·*
2b1fc2 ·* Revision 1.12 ·1996/04/25 ·16:20:59 ·mcs
a57663 ·* make re_exec() match "" with ".*" and similar patterns
266e6c ·* hopefully this change doesn't break anything else!
a8775e ·*
cc782e ·* Revision 1.11 ·1994/12/14 ·21:33:45 ·mcs
489d77 ·* use new NEED_BSDREGEX
bdddbb ·* fix pmatch() prototype
08775e ·*
8450cb ·* Revision 1.10 ·1994/12/12 ·18:16:39 ·mcs
7d4655 ·* use on NetBSD
39775e ·*
ee2b5c ·* Revision 1.9 ·1994/11/15 ·19:16:35 ·mcs
ec9d0d ·* add (CHAR) cast to make VisualC++ happy
ed775e ·*
cdcbc1 ·* Revision 1.8 ·1994/11/08 ·21:14:32 ·mcs
93c3c7 ·* WIN32 changes
73775e ·*
e0dd4d ·* Revision 1.7 ·1994/07/23 ·19:51:24 ·mcs
a12c8e ·* use ANSI-style inline function parameters
05775e ·*
deb32d ·* Revision 1.6 ·1993/10/18 ·01:52:32 ·tim
a23beb ·* include for VMS
12775e ·*
2304e6 ·* Revision 1.5 ·1993/09/28 ·21:37:54 ·mcs
16c731 ·* HP/UX needs the regex we include (not in its libc)
a8775e ·*
ae6b1f ·* Revision 1.4 ·1993/08/27 ·15:59:52 ·mcs
371fdf ·* use CHAR for deftab
2d775e ·*
57b027 ·* Revision 1.3 ·1993/08/27 ·15:49:47 ·mcs
ebb1a6 ·* added missing 0 to octal constants
--6658 000e0c45715401000ad Page 2 of regex.c
8c0aa9 ·* use unsigned char for CHAR under DOS
98775e ·*
4e8125 ·* Revision 1.2 ·1993/08/27 ·14:57:48 ·mcs
9ca03d ·* add proto. for pmatch
6d775e ·*
0378b7 ·* Revision 1.1 ·1993/08/18 ·21:20:02 ·mcs
ec23cc ·* Initial revision
a4775e ·*
3544e8 ·* Revision 1.4 ·1991/10/17 ·03:56:42 ·oz
5d55cc ·* miscellaneous changes, small cleanups etc.
60775e ·*
ffd5c7 ·* Revision 1.3 ·1989/04/01 ·14:18:09 ·oz
05b049 ·* Change all references to a dfa: this is actually an nfa.
3d775e ·*
e466fa ·* Revision 1.2 ·88/08/28 ·15:36:04 ·oz
3c8e0b ·* Use a complement bitmap to represent NCL.
480d1d ·* This removes the need to have seperate·
c523d6 ·* code in the pmatch case block - it is·
5a803d ·* just CCL code now.
6b9ec0 ·*·
f82bf8 ·* Use the actual CCL code in the CLO
2cb7fd ·* section of pmatch. No need for a recursive
8909a0 ·* pmatch call.
d49ec0 ·*·
01f5da ·* Use a bitmap table to set char bits in an
b8f9df ·* 8-bit chunk.
539ec0 ·*·
795cd2 ·* Interfaces:
c0ad86 ·* ·····re_comp: ·······compile a regular expression into a NFA.
af775e ·*
2593f4 ·*¤ ¤   ¤   char *re_comp(s)
867415 ·*¤ ¤   ¤   char *s;
28775e ·*
460c13 ·* ·····re_exec: ·······execute the NFA to match a pattern.
da775e ·*
3eadfa ·*¤ ¤   ¤   int re_exec(s)
e57415 ·*¤ ¤   ¤   char *s;
93775e ·*
67c33a ·*¤ re_modw¤¤   change re_exec's understanding of what a "word"
ca8dbc ·*¤ ¤   ¤   looks like (for \< and \>) by adding into the
ff7859 ·*¤ ¤   ¤   hidden word-syntax table.
d4775e ·*
6cc578 ·*¤ ¤   ¤   void re_modw(s)
867415 ·*¤ ¤   ¤   char *s;
da775e ·*
e80123 ·* ·····re_subs:¤   substitute the matched portions in a new string.
ed775e ·*
196d1b ·*¤ ¤   ¤   int re_subs(src, dst)
e0555d ·*¤ ¤   ¤   char *src;
a6c4ea ·*¤ ¤   ¤   char *dst;
1b775e ·*
0623fc ·*¤ re_fail:¤   failure routine for re_exec.
d5775e ·*
09fe52 ·*¤ ¤   ¤   void re_fail(msg, op)
ebff7f ·*¤ ¤   ¤   char *msg;
bbe391 ·*¤ ¤   ¤   char op;
06e6a2 ·* ·
ed1a09 ·* Regular Expressions:
67775e ·*
7d91fb ·* ·····[1] ····char ···matches itself, unless it is a special
d175ed ·* ·····················character (metachar): . \ [ ] * + ^ $
aa775e ·*
fbdab8 ·* ·····[2] ····. ······matches any character.
b9775e ·*
55ee29 ·* ·····[3] ····\ ······matches the character following it, except
d2103b ·*¤ ¤   ¤   when followed by a left or right round bracket,
f130ef ·*¤ ¤   ¤   a digit 1 to 9 or a left or right angle bracket.·
f36e78 ·*¤ ¤   ¤   (see [7], [8] and [9])
3af833 ·*¤ ¤   ¤   It is used as an escape character for all·
aa63f3 ·*¤ ¤   ¤   other meta-characters, and itself. When used
655cf4 ·*¤ ¤   ¤   in a set ([4]), it is treated as an ordinary
e0ba10 ·*¤ ¤   ¤   character.
--fb08 000ccc60325401000ad Page 3 of regex.c
4f775e ·*
e46924 ·* ·····[4] ····[set] ··matches one of the characters in the set.
8fab85 ·* ·····················If the first character in the set is "^",
b425c2 ·* ·····················it matches a character NOT in the set, i.e.·
344657 ·*¤ ¤   ¤   complements the set. A shorthand S-E is·
89ca46 ·*¤ ¤   ¤   used to specify a set of characters S upto·
5f3454 ·*¤ ¤   ¤   E, inclusive. The special characters "]" and·
ebc75d ·*¤ ¤   ¤   "-" have no special meaning if they appear·
3ab829 ·*¤ ¤   ¤   as the first chars in the set.
41930c ·* ·····················examples: ·······match:
ef775e ·*
e19022 ·* ·····························[a-z] ···any lowercase alpha
62775e ·*
8b2c4c ·* ·····························[^]-] ···any char except ] and -
e3775e ·*
152e30 ·* ·····························[^A-Z] ··any char except uppercase
a71585 ·* ······································alpha
18775e ·*
e109c7 ·* ·····························[a-zA-Z] any alpha
cd775e ·*
c25b31 ·* ·····[5] ····* ······any regular expression form [1] to [4], followed by
a7ada2 ·* ·····················closure char (*) matches zero or more matches of
3bdc9e ·* ·····················that form.
b9775e ·*
951cca ·* ·····[6] ····+ ······same as [5], except it matches one or more.
2e775e ·*
c87878 ·* ·····[7] ············a regular expression in the form [1] to [10], enclosed
4c1c1d ·* ·····················as \(form\) matches what form matches. The enclosure
bbd50e ·* ·····················creates a set of tags, used for [8] and for
4eea69 ·* ·····················pattern substution. The tagged forms are numbered
37d909 ·*¤ ¤   ¤   starting from 1.
a7775e ·*
62cdaa ·* ·····[8] ············a \ followed by a digit 1 to 9 matches whatever a
6b3992 ·* ·····················previously tagged regular expression ([7]) matched.
db775e ·*
b280da ·*¤ [9]¤\<¤ a regular expression starting with a \< construct
495877 ·*¤ ¤   \>¤ and/or ending with a \> construct, restricts the
e2f07a ·*¤ ¤   ¤   pattern matching to the beginning of a word, and/or
0cb13f ·*¤ ¤   ¤   the end of a word. A word is defined to be a character
8ba22c ·*¤ ¤   ¤   string beginning and/or ending with the characters
0f8eeb ·*¤ ¤   ¤   A-Z a-z 0-9 and _. It must also be preceded and/or
f119f0 ·*¤ ¤   ¤   followed by any character outside those mentioned.
c5775e ·*
c8c319 ·* ·····[10] ···········a composite regular expression xy where x and y
4f1b9e ·* ·····················are in the form [1] to [10] matches the longest
997ce7 ·* ·····················match of x followed by a match for y.
e7775e ·*
d6cee1 ·* ·····[11]¤   ^¤  a regular expression starting with a ^ character
f1bbf3 ·*¤ ¤   $¤  and/or ending with a $ character, restricts the
71bee5 ·* ·····················pattern matching to the beginning of the line,
f95531 ·* ·····················or the end of line. [anchors] Elsewhere in the
322d6c ·*¤ ¤   ¤   pattern, ^ and $ are treated as ordinary characters.
06775e ·*
63775e ·*
e0ceb2 ·* Acknowledgements:
0c775e ·*
3499c7 ·*¤ HCR's Hugh Redelmeier has been most helpful in various
b6a65a ·*¤ stages of development. He convinced me to include BOW
87820f ·*¤ and EOW constructs, originally invented by Rob Pike at
5f2599 ·*¤ the University of Toronto.
25775e ·*
db99ea ·* References:
f93a09 ·* ·············Software tools¤ ¤   ¤   Kernighan & Plauger
34e1c4 ·* ·············Software tools in Pascal ·······Kernighan & Plauger
40a116 ·* ·············Grep [rsx-11 C dist] ···········David Conroy
7f669d ·*¤ ¤   ed - text editor¤   ¤   Un*x Programmer's Manual
26ce41 ·*¤ ¤   Advanced editing on Un*x¤   B. W. Kernighan
54fc54 ·*¤ ¤   RegExp routines¤¤   ¤   Henry Spencer
05775e ·*
ed0266 ·* Notes:
ea775e ·*
cc3cd0 ·*¤ This implementation uses a bit-set representation for character
--7a98 000ca9e84c8401000ad Page 4 of regex.c
ce4b9a ·*¤ classes for speed and compactness. Each character is represented·
971cc1 ·*¤ by one bit in a 128-bit block. Thus, CCL always takes a·
8b43fc ·*¤ constant 16 bytes in the internal nfa, and re_exec does a single
52fb24 ·*¤ bit comparison to locate the character in the set.
70775e ·*
1c1b49 ·* Examples:
7c775e ·*
a1a62d ·*¤ pattern:¤   foo*.*
45e3b4 ·*¤ compile:¤   CHR f CHR o CLO CHR o END CLO ANY END END
eb3967 ·*¤ matches:¤   fo foo fooo foobar fobar foxx ...
f2775e ·*
93f208 ·*¤ pattern:¤   fo[ob]a[rz]¤
04f63d ·*¤ compile:¤   CHR f CHR o CCL bitset CHR a CCL bitset END
e545fe ·*¤ matches:¤   fobar fooar fobaz fooaz
98775e ·*
1a9b4a ·*¤ pattern:¤   foo\\+
8dc743 ·*¤ compile:¤   CHR f CHR o CHR o CHR \ CLO CHR \ END END
f8b9d3 ·*¤ matches:¤   foo\ foo\\ foo\\\ ·...
eb775e ·*
96785f ·*¤ pattern:¤   \(foo\)[1-3]\1¤ (same as foo[1-3]foo)
c50715 ·*¤ compile:¤   BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
f27f8e ·*¤ matches:¤   foo1foo foo2foo foo3foo
88775e ·*
3f3439 ·*¤ pattern:¤   \(fo.*\)-\1
ffa2da ·*¤ compile:¤   BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
56a580 ·*¤ matches:¤   foo-foo fo-fo fob-fob foobar-foobar ...
a1495d ·*/
acaf5a
a3c5fa #define MAXNFA ·1024
c6a0cf #define MAXTAG ·10
62af5a
0e62cf #define OKP ····1
c068d5 #define NOP ····0
a0af5a
706612 #define CHR ····1
291747 #define ANY ····2
3c971a #define CCL ····3
dab61a #define BOL ····4
676b37 #define EOL ····5
9df36e #define BOT ····6
3c2e43 #define EOT ····7
790d83 #define BOW¤8
d3088a #define EOW¤9
30c64a #define REF ····10
de8c7f #define CLO ····11
c0af5a
5e75ce #define END ····0
03af5a
4838e5 /*
90e4ce ·* The following defines are not meant to be changeable.
1acff2 ·* They are for readability only.
49495d ·*/
354573 #define MAXCHR¤ 128
b30e0f #define CHRBIT¤ 8
90cdb8 #define BITBLK¤ MAXCHR/CHRBIT
91223c #define BLKIND¤ 0170
db68d6 #define BITIND¤ 07
53af5a
a9b496 #define ASCIIB¤ 0177
69af5a
bffdef #if defined( DOS ) || defined( _WIN32 )
268e8f typedef unsigned char CHAR;
f2aad8 #else /* DOS */
9fef48 typedef /*unsigned*/ char CHAR;
3cbc39 #endif /* DOS */
33af5a
2b38e6 static int ·tagstk[MAXTAG]; ············/* subpat tag stack..*/
cb192a static CHAR nfa[MAXNFA];¤   ¤   /* automaton.. ······*/
65fc28 static int ·sta = NOP; ··············¤  /* status of lastpat */
fbaf5a
70ae12 static CHAR bittab[BITBLK];¤¤   /* bit table for CCL */
ca116e ¤   ¤   ¤   ¤   ¤   /* pre-set bits... ··*/
--2a6a 0003b632eff401000ad Page 5 of regex.c
2377b0 static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
c7af5a
b62978 static void
7aeef9 chset(CHAR c)
bbbb36 {
7232f4 ¤   bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
5befe6 }
b0af5a
8ecec3 #define badpat(x)¤  (*nfa = END, x)
10ff3c #define store(x)¤   *mp++ = x
a7d83c ·
5bf31c char * ····
b1f4f6 re_comp( char *pat )
afbb36 {
980f18 ¤   register char *p; ··············/* pattern pointer ··*/
75555b ¤   register CHAR *mp=nfa; ·········/* nfa pointer ······*/
5305ec ¤   register CHAR *lp; ·············/* saved pointer.. ··*/
3e679a ¤   register CHAR *sp=nfa; ·········/* another one.. ····*/
0daf5a
561cb1 ¤   register int tagi = 0; ·········/* tag stack index ··*/
75d66b ¤   register int tagc = 1; ·········/* actual tag count ·*/
6baf5a
de6983 ¤   register int n;
2341ff ¤   register CHAR mask;¤¤   /* xor mask -CCL/NCL */
3d5196 ¤   int c1, c2;
9d1b52 ¤   ¤
e7c3c4 ¤   if (!pat || !*pat)
eabbb8 ¤   ¤   if (sta)
728144 ¤   ¤   ¤   return 0;
5a0e1d ¤   ¤   else
70602b ¤   ¤   ¤   return badpat("No previous regular expression");
3eb396 ¤   sta = NOP;
05af5a
05c0d4 ¤   for (p = pat; *p; p++) {
69f25a ¤   ¤   lp = mp;
4e37c7 ¤   ¤   switch(*p) {
f9af5a
317b1e ¤   ¤   case '.': ··············/* match any char.. ·*/
e02d07 ¤   ¤   ¤   store(ANY);
d0cdcb ¤   ¤   ¤   break;
c7af5a
730cb0 ¤   ¤   case '^': ··············/* match beginning.. */
886bbd ¤   ¤   ¤   if (p == pat)
d271ad ¤   ¤   ¤   ¤   store(BOL);
cde543 ¤   ¤   ¤   else {
dc28b9 ¤   ¤   ¤   ¤   store(CHR);
f4851b ¤   ¤   ¤   ¤   store(*p);
3ea3a6 ¤   ¤   ¤   }
bfcdcb ¤   ¤   ¤   break;
efaf5a
d65534 ¤   ¤   case '$': ··············/* match endofline.. */
5b061d ¤   ¤   ¤   if (!*(p+1))
cf6d7c ¤   ¤   ¤   ¤   store(EOL);
f6e543 ¤   ¤   ¤   else {
7828b9 ¤   ¤   ¤   ¤   store(CHR);
36851b ¤   ¤   ¤   ¤   store(*p);
faa3a6 ¤   ¤   ¤   }
68cdcb ¤   ¤   ¤   break;
78af5a
9a2803 ¤   ¤   case '[': ··············/* match char class..*/
43f4d3 ¤   ¤   ¤   store(CCL);
8baf5a
7ae847 ¤   ¤   ¤   if (*++p == '^') {
3910cc ¤   ¤   ¤   ¤   mask = 0377;¤
572543 ¤   ¤   ¤   ¤   p++;
0aa3a6 ¤   ¤   ¤   }
71bb8c ¤   ¤   ¤   else
7889e5 ¤   ¤   ¤   ¤   mask = 0;
10af5a
78f749 ¤   ¤   ¤   if (*p == '-')¤ ¤   /* real dash */
3a115c ¤   ¤   ¤   ¤   chset(*p++);
3b2454 ¤   ¤   ¤   if (*p == ']')¤ ¤   /* real brac */
--6d6c 000c9ca4d80401000ad Page 6 of regex.c
98115c ¤   ¤   ¤   ¤   chset(*p++);
df90cf ¤   ¤   ¤   while (*p && *p != ']') {
027327 ¤   ¤   ¤   ¤   if (*p == '-' && *(p+1) && *(p+1) != ']') {
1a9492 ¤   ¤   ¤   ¤   ¤   p++;
47ad57 ¤   ¤   ¤   ¤   ¤   c1 = *(p-2) + 1;
1e5b55 ¤   ¤   ¤   ¤   ¤   c2 = *p++;
595b32 ¤   ¤   ¤   ¤   ¤   while (c1 <= c2)
f4157a ¤   ¤   ¤   ¤   ¤   ¤   chset((CHAR)c1++);
952613 ¤   ¤   ¤   ¤   }
935e8d #ifdef EXTEND
eb2f39 ¤   ¤   ¤   ¤   else if (*p == '\\' && *(p+1)) {
e09492 ¤   ¤   ¤   ¤   ¤   p++;
34aa0a ¤   ¤   ¤   ¤   ¤   chset(*p++);
c72613 ¤   ¤   ¤   ¤   }
9e7454 #endif
43fa07 ¤   ¤   ¤   ¤   else
8daa0a ¤   ¤   ¤   ¤   ¤   chset(*p++);
36a3a6 ¤   ¤   ¤   }
da3dc4 ¤   ¤   ¤   if (!*p)
145669 ¤   ¤   ¤   ¤   return badpat("Missing ]");
7aaf5a
93af98 ¤   ¤   ¤   for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
3e2e17 ¤   ¤   ¤   ¤   store(mask ^ bittab[n]);
9867c5 ¤
a8cdcb ¤   ¤   ¤   break;
b4af5a
6d28a6 ¤   ¤   case '*': ··············/* match 0 or more.. */
f1c220 ¤   ¤   case '+': ··············/* match 1 or more.. */
a96bbd ¤   ¤   ¤   if (p == pat)
4634dd ¤   ¤   ¤   ¤   return badpat("Empty closure");
f5fade ¤   ¤   ¤   lp = sp;¤   ¤   /* previous opcode */
c31c83 ¤   ¤   ¤   if (*lp == CLO)¤¤   /* equivalence.. ··*/
fef622 ¤   ¤   ¤   ¤   break;
3b3713 ¤   ¤   ¤   switch(*lp) {
eeaf5a
3b213b ¤   ¤   ¤   case BOL:
ed626c ¤   ¤   ¤   case BOT:
a152b0 ¤   ¤   ¤   case EOT:
3d8d08 ¤   ¤   ¤   case BOW:
a6bdd4 ¤   ¤   ¤   case EOW:
653aaf ¤   ¤   ¤   case REF:
401406 ¤   ¤   ¤   ¤   return badpat("Illegal closure");
74db68 ¤   ¤   ¤   default:
4cf622 ¤   ¤   ¤   ¤   break;
f0a3a6 ¤   ¤   ¤   }
24af5a
76440a ¤   ¤   ¤   if (*p == '+')
ad4347 ¤   ¤   ¤   ¤   for (sp = mp; lp < sp; lp++)
a9dc81 ¤   ¤   ¤   ¤   ¤   store(*lp);
edaf5a
587585 ¤   ¤   ¤   store(END);
367585 ¤   ¤   ¤   store(END);
b5da6d ¤   ¤   ¤   sp = mp;
dd0e7e ¤   ¤   ¤   while (--mp > lp)
0e813c ¤   ¤   ¤   ¤   *mp = mp[-1];
0bbbe2 ¤   ¤   ¤   store(CLO);
3493cf ¤   ¤   ¤   mp = sp;
9ccdcb ¤   ¤   ¤   break;
bbaf5a
046cca ¤   ¤   case '\\': ·············/* tags, backrefs .. */
2e7e11 ¤   ¤   ¤   switch(*++p) {
44af5a
5844f2 ¤   ¤   ¤   case '(':
bab97d ¤   ¤   ¤   ¤   if (tagc < MAXTAG) {
b5761c ¤   ¤   ¤   ¤   ¤   tagstk[++tagi] = tagc;
00fa8a ¤   ¤   ¤   ¤   ¤   store(BOT);
ccc487 ¤   ¤   ¤   ¤   ¤   store(tagc++);
fc2613 ¤   ¤   ¤   ¤   }
0afa07 ¤   ¤   ¤   ¤   else
2104e5 ¤   ¤   ¤   ¤   ¤   return badpat("Too many \\(\\) pairs");
09f622 ¤   ¤   ¤   ¤   break;
c95849 ¤   ¤   ¤   case ')':
--ce66 00021cb187b401000ad Page 7 of regex.c
ea5f86 ¤   ¤   ¤   ¤   if (*sp == BOT)
b05d87 ¤   ¤   ¤   ¤   ¤   return badpat("Null pattern inside \\(\\)");
3093bb ¤   ¤   ¤   ¤   if (tagi > 0) {
02e65b ¤   ¤   ¤   ¤   ¤   store(EOT);
437f41 ¤   ¤   ¤   ¤   ¤   store(tagstk[tagi--]);
f72613 ¤   ¤   ¤   ¤   }
cafa07 ¤   ¤   ¤   ¤   else
d524cb ¤   ¤   ¤   ¤   ¤   return badpat("Unmatched \\)");
9af622 ¤   ¤   ¤   ¤   break;
58f5bf ¤   ¤   ¤   case '<':
fd7219 ¤   ¤   ¤   ¤   store(BOW);
44f622 ¤   ¤   ¤   ¤   break;
18ccc9 ¤   ¤   ¤   case '>':
1ab0e2 ¤   ¤   ¤   ¤   if (*sp == BOW)
d794bd ¤   ¤   ¤   ¤   ¤   return badpat("Null pattern inside \\<\\>");
926ec8 ¤   ¤   ¤   ¤   store(EOW);
4af622 ¤   ¤   ¤   ¤   break;
367e30 ¤   ¤   ¤   case '1':
685bfd ¤   ¤   ¤   case '2':
6e4746 ¤   ¤   ¤   case '3':
9a1067 ¤   ¤   ¤   case '4':
e10cdc ¤   ¤   ¤   case '5':
962911 ¤   ¤   ¤   case '6':
9435aa ¤   ¤   ¤   case '7':
8f8753 ¤   ¤   ¤   case '8':
489be8 ¤   ¤   ¤   case '9':
bfb164 ¤   ¤   ¤   ¤   n = *p-'0';
c72531 ¤   ¤   ¤   ¤   if (tagi > 0 && tagstk[tagi] == n)
e59a3b ¤   ¤   ¤   ¤   ¤   return badpat("Cyclical reference");
656351 ¤   ¤   ¤   ¤   if (tagc > n) {
2b0e45 ¤   ¤   ¤   ¤   ¤   store(REF);
0b6f42 ¤   ¤   ¤   ¤   ¤   store(n);
3f2613 ¤   ¤   ¤   ¤   }
aefa07 ¤   ¤   ¤   ¤   else
46b02b ¤   ¤   ¤   ¤   ¤   return badpat("Undetermined reference");
2ff622 ¤   ¤   ¤   ¤   break;
485e8d #ifdef EXTEND
2c8eeb ¤   ¤   ¤   case 'b':
a728b9 ¤   ¤   ¤   ¤   store(CHR);
7ffb13 ¤   ¤   ¤   ¤   store('\b');
17f622 ¤   ¤   ¤   ¤   break;
9d19df ¤   ¤   ¤   case 'n':
4828b9 ¤   ¤   ¤   ¤   store(CHR);
7a8c23 ¤   ¤   ¤   ¤   store('\n');
5bf622 ¤   ¤   ¤   ¤   break;
5cfc07 ¤   ¤   ¤   case 'f':
8c28b9 ¤   ¤   ¤   ¤   store(CHR);
80d603 ¤   ¤   ¤   ¤   store('\f');
03f622 ¤   ¤   ¤   ¤   break;
d44d4a ¤   ¤   ¤   case 'r':
5828b9 ¤   ¤   ¤   ¤   store(CHR);
134f53 ¤   ¤   ¤   ¤   store('\r');
48f622 ¤   ¤   ¤   ¤   break;
4006d0 ¤   ¤   ¤   case 't':
8d28b9 ¤   ¤   ¤   ¤   store(CHR);
6574cb ¤   ¤   ¤   ¤   store('\t');
15f622 ¤   ¤   ¤   ¤   break;
027454 #endif
54db68 ¤   ¤   ¤   default:
6f28b9 ¤   ¤   ¤   ¤   store(CHR);
5f851b ¤   ¤   ¤   ¤   store(*p);
faa3a6 ¤   ¤   ¤   }
64cdcb ¤   ¤   ¤   break;
1daf5a
1f4eba ¤   ¤   default : ··············/* an ordinary char ·*/
18dedc ¤   ¤   ¤   store(CHR);
2767fa ¤   ¤   ¤   store(*p);
cbcdcb ¤   ¤   ¤   break;
b30fe4 ¤   ¤   }
36875d ¤   ¤   sp = lp;
679371 ¤   }
2147f2 ¤   if (tagi > 0)
--a343 000b5b99f7f401000ad Page 8 of regex.c
f329f8 ¤   ¤   return badpat("Unmatched \\(");
ba9802 ¤   store(END);
b9ca3e ¤   sta = OKP;
613e6b ¤   return 0;
ddefe6 }
dcaf5a
6faf5a
e1b5f9 static char *bol;
f82098 char *bopat[MAXTAG];
24d05f char *eopat[MAXTAG];
c9504c #ifdef NEEDPROTOS
25a0db static char *pmatch( char *lp, CHAR *ap );
ff6133 #else /* NEEDPROTOS */
71e56f static char *pmatch();
b68634 #endif /* NEEDPROTOS */
98af5a
4d38e5 /*
c3341f ·* re_exec:
eb0373 ·* ¤execute nfa to find a match.
2c775e ·*
806cd6 ·*¤ special cases: (nfa[0])¤
686086 ·*¤ ¤   BOL
634913 ·*¤ ¤   ¤   Match only once, starting from the
f2da3a ·*¤ ¤   ¤   beginning.
7fffb9 ·*¤ ¤   CHR
5b4aae ·*¤ ¤   ¤   First locate the character without
1c0e79 ·*¤ ¤   ¤   calling pmatch, and if found, call
338d53 ·*¤ ¤   ¤   pmatch for the remaining string.
28a3bb ·*¤ ¤   END
ad8b7f ·*¤ ¤   ¤   re_comp failed, poor luser did not
9ff5d0 ·*¤ ¤   ¤   check for it. Fail fast.
56775e ·*
660423 ·*¤ If a match is found, bopat[0] and eopat[0] are set
8bab8e ·*¤ to the beginning and the end of the matched fragment,
f1e544 ·*¤ respectively.
61775e ·*
c5495d ·*/
8daf5a
c54d2f int
b12ed2 re_exec( char *lp )
4dbb36 {
3c00cd ¤   register char c;
06c90f ¤   register char *ep = 0;
b5e5a6 ¤   register CHAR *ap = nfa;
e7af5a
32e496 ¤   bol = lp;
caaf5a
282927 ¤   bopat[0] = 0;
eea898 ¤   bopat[1] = 0;
542248 ¤   bopat[2] = 0;
5aa3f7 ¤   bopat[3] = 0;
553ff9 ¤   bopat[4] = 0;
b7be46 ¤   bopat[5] = 0;
f93496 ¤   bopat[6] = 0;
28b529 ¤   bopat[7] = 0;
44049b ¤   bopat[8] = 0;
618524 ¤   bopat[9] = 0;
e2af5a
5effe3 ¤   switch(*ap) {
07af5a
2f9c14 ¤   case BOL:¤  ¤   ¤   /* anchored: match from BOL only */
902540 ¤   ¤   ep = pmatch(lp,ap);
c92f68 ¤   ¤   break;
34b2b9 ¤   case CHR:¤  ¤   ¤   /* ordinary char: locate it fast */
42eced ¤   ¤   c = *(ap+1);
957316 ¤   ¤   while (*lp && *lp != c)
828e5f ¤   ¤   ¤   lp++;
c00c29 ¤   ¤   if (!*lp)¤  ¤   /* if EOS, fail, else fall thru. */
db8144 ¤   ¤   ¤   return 0;
a20b4d ¤   default:¤   ¤   ¤   /* regular matching all the way. */
664392 ¤   ¤   do {
b5636d ¤   ¤   ¤   if ((ep = pmatch(lp,ap)) != 0)
--08f6 00080d7c0d5401000ad Page 9 of regex.c
72f622 ¤   ¤   ¤   ¤   break;
d88e5f ¤   ¤   ¤   lp++;
de130a ¤   ¤   } while (*lp);
f6af5a
9c2f68 ¤   ¤   break;
ee8f24 ¤   case END:¤  ¤   ¤   /* munged automaton. fail always */
27bbde ¤   ¤   return 0;
009371 ¤   }
7c6d90 ¤   if (!ep)
7fbbde ¤   ¤   return 0;
65af5a
b63846 ¤   bopat[0] = lp;
c531e2 ¤   eopat[0] = ep;
dd64b7 ¤   return 1;
a4efe6 }
45af5a
4695d7 /*·
c3a265 ·* pmatch: internal routine for the hard part
77775e ·*
1b7be3 ·* ¤This code is partly snarfed from an early grep written by
f2b279 ·*¤ David Conroy. The backref and tag stuff, and various other
db59f6 ·*¤ innovations are by oz.
a2775e ·*
6668a6 ·*¤ special case optimizations: (nfa[n], nfa[n+1])
2fddf8 ·*¤ ¤   CLO ANY
2f7366 ·*¤ ¤   ¤   We KNOW .* will match everything upto the
ca4a37 ·*¤ ¤   ¤   end of line. Thus, directly go to the end of
7ae44d ·*¤ ¤   ¤   line, without recursive pmatch calls. As in
43a8a2 ·*¤ ¤   ¤   the other closure cases, the remaining pattern
bf7b63 ·*¤ ¤   ¤   must be matched by moving backwards on the
fd7981 ·*¤ ¤   ¤   string recursively, to find a match for xy
bed869 ·*¤ ¤   ¤   (x is ".*" and y is the remaining pattern)
5b105c ·*¤ ¤   ¤   where the match satisfies the LONGEST match for
4a2ee6 ·*¤ ¤   ¤   x followed by a match for y.
2dd6ff ·*¤ ¤   CLO CHR
9b8d9c ·*¤ ¤   ¤   We can again scan the string forward for the
c07d48 ·*¤ ¤   ¤   single char and at the point of failure, we
6b55ca ·*¤ ¤   ¤   execute the remaining nfa recursively, same as
65c468 ·*¤ ¤   ¤   above.
46775e ·*
54770e ·*¤ At the end of a successful match, bopat[n] and eopat[n]
cd10f3 ·*¤ are set to the beginning and end of subpatterns matched
8e4c97 ·*¤ by tagged expressions (n = 1 to 9).¤
13775e ·*
c3495d ·*/
f7af5a
a4e041 #ifndef re_fail
c2dc5b extern void re_fail();
879842 #endif /* re_fail */
f9af5a
3838e5 /*
05840e ·* character classification table for word boundary operators BOW
174393 ·* and EOW. the reason for not using ctype macros is that we can
3f2567 ·* let the user add into our own table. see re_modw. This table
425ac4 ·* is not in the bitset form, since we may wish to extend it in the
991c68 ·* future for other character classifications.·
12775e ·*
089eff ·*¤ TRUE for 0-9 A-Z a-z _
e9495d ·*/
1647ba static char chrtyp[MAXCHR] = {
e2ce90 ¤   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,·
3ace90 ¤   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,·
75ce90 ¤   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,·
26ce90 ¤   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,·
5a4dfe ¤   0, 0, 0, 0, 0, 0, 0, 0, 1, 1,·
0f5c4f ¤   1, 1, 1, 1, 1, 1, 1, 1, 0, 0,·
8bea64 ¤   0, 0, 0, 0, 0, 1, 1, 1, 1, 1,·
6edf21 ¤   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,·
83df21 ¤   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,·
8b2afd ¤   1, 0, 0, 0, 0, 1, 0, 1, 1, 1,·
d8df21 ¤   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,·
80df21 ¤   1, 1, 1, 1, 1, 1, 1, 1, 1, 1,·
--d886 000eecf8edd401000ad Page 10 of regex.c
c1d8ea ¤   1, 1, 1, 0, 0, 0, 0, 0
c162bd ¤   };
6eaf5a
164610 #define inascii(x)¤ (0177&(x))
293f35 #define iswordc(x) ¤chrtyp[inascii(x)]
d1cb77 #define isinset(x,y) ¤  ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
c7af5a
cf38e5 /*
20f750 ·* skip values for CLO XXX to skip past the closure
3f495d ·*/
f6af5a
76906c #define ANYSKIP¤2 ¤ /* [CLO] ANY END ...¤   ·····*/
880b4c #define CHRSKIP¤3¤  /* [CLO] CHR chr END ... ····*/
60b896 #define CCLSKIP 18¤ /* [CLO] CCL 16bytes END ... */
caaf5a
78083f static char *
cc6a0d pmatch( char *lp, CHAR *ap)
10bb36 {
88dcc2 ¤   register int op, c, n;
026b67 ¤   register char *e;¤  ¤   /* extra pointer for CLO */
34837d ¤   register char *bp;¤ ¤   /* beginning of subpat.. */
724fda ¤   register char *ep;¤ ¤   /* ending of subpat..¤  ·*/
7d7b18 ¤   char *are;¤ ¤   ¤   /* to save the line ptr. */
36af5a
be0b28 ¤   while ((op = *ap++) != END)
ce2191 ¤   ¤   switch(op) {
4daf5a
e3d24a ¤   ¤   case CHR:
bc35bb ¤   ¤   ¤   if (*lp++ != *ap++)
8c46f1 ¤   ¤   ¤   ¤   return 0;
83cdcb ¤   ¤   ¤   break;
65a6fe ¤   ¤   case ANY:
2bda67 ¤   ¤   ¤   if (!*lp++)
7646f1 ¤   ¤   ¤   ¤   return 0;
c6cdcb ¤   ¤   ¤   break;
8387d1 ¤   ¤   case CCL:
7dc71f ¤   ¤   ¤   c = *lp++;
484add ¤   ¤   ¤   if (!isinset(ap,c))
4d46f1 ¤   ¤   ¤   ¤   return 0;
b4a72b ¤   ¤   ¤   ap += BITBLK;
9ccdcb ¤   ¤   ¤   break;
f61ba1 ¤   ¤   case BOL:
fab09f ¤   ¤   ¤   if (lp != bol)
3846f1 ¤   ¤   ¤   ¤   return 0;
77cdcb ¤   ¤   ¤   break;
d62b7d ¤   ¤   case EOL:
6a2705 ¤   ¤   ¤   if (*lp)
0d46f1 ¤   ¤   ¤   ¤   return 0;
0bcdcb ¤   ¤   ¤   break;
3158f6 ¤   ¤   case BOT:
dcd0f6 ¤   ¤   ¤   bopat[*ap++] = lp;
9ecdcb ¤   ¤   ¤   break;
d5682a ¤   ¤   case EOT:
6e303a ¤   ¤   ¤   eopat[*ap++] = lp;
2bcdcb ¤   ¤   ¤   break;
1b4711 ·¤  ¤   case BOW:
4276c6 ¤   ¤   ¤   if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
b546f1 ¤   ¤   ¤   ¤   return 0;
83cdcb ¤   ¤   ¤   break;
46874e ¤   ¤   case EOW:
4d5216 ¤   ¤   ¤   if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
a446f1 ¤   ¤   ¤   ¤   return 0;
77cdcb ¤   ¤   ¤   break;
2c0035 ¤   ¤   case REF:
eb45ae ¤   ¤   ¤   n = *ap++;
e56e8c ¤   ¤   ¤   bp = bopat[n];
8d5abe ¤   ¤   ¤   ep = eopat[n];
bec857 ¤   ¤   ¤   while (bp < ep)
cb6207 ¤   ¤   ¤   ¤   if (*bp++ != *lp++)
2acfa5 ¤   ¤   ¤   ¤   ¤   return 0;
2bcdcb ¤   ¤   ¤   break;
eeda4c ¤   ¤   case CLO:
--72b6 000c2704c4e401000ad Page 11 of regex.c
347195 ¤   ¤   ¤   are = lp;
9b02cc ¤   ¤   ¤   switch(*ap) {
42af5a
df9c64 ¤   ¤   ¤   case ANY:
30eac9 ¤   ¤   ¤   ¤   while (*lp)
897370 ¤   ¤   ¤   ¤   ¤   lp++;
71a264 ¤   ¤   ¤   ¤   n = ANYSKIP;
6bf622 ¤   ¤   ¤   ¤   break;
76e8d0 ¤   ¤   ¤   case CHR:
976961 ¤   ¤   ¤   ¤   c = *(ap+1);
fda0e9 ¤   ¤   ¤   ¤   while (*lp && c == *lp)
387370 ¤   ¤   ¤   ¤   ¤   lp++;
2452ad ¤   ¤   ¤   ¤   n = CHRSKIP;
18f622 ¤   ¤   ¤   ¤   break;
b3bd4b ¤   ¤   ¤   case CCL:
33434c ¤   ¤   ¤   ¤   while ((c = *lp) != 0 && isinset(ap+1,c))
fb7370 ¤   ¤   ¤   ¤   ¤   lp++;
c1c629 ¤   ¤   ¤   ¤   n = CCLSKIP;
6cf622 ¤   ¤   ¤   ¤   break;
11db68 ¤   ¤   ¤   default:
496f52 ¤   ¤   ¤   ¤   re_fail("closure: bad nfa.", *ap);
a146f1 ¤   ¤   ¤   ¤   return 0;
9ca3a6 ¤   ¤   ¤   }
08af5a
cf24cb ¤   ¤   ¤   ap += n;
05af5a
dd645b ¤   ¤   ¤   while (lp >= are) {
de7bab ¤   ¤   ¤   ¤   if ((e = pmatch(lp, ap)) != 0)
ab75fb ¤   ¤   ¤   ¤   ¤   return e;
c950fa ¤   ¤   ¤   ¤   --lp;
9ba3a6 ¤   ¤   ¤   }
f88144 ¤   ¤   ¤   return 0;
599ae3 ¤   ¤   default:
b8f504 ¤   ¤   ¤   re_fail("re_exec: bad nfa.", op);
dc8144 ¤   ¤   ¤   return 0;
930fe4 ¤   ¤   }
94b039 ¤   return lp;
f7efe6 }
d2af5a
9f38e5 /*
966b94 ·* re_modw:
577cb3 ·*¤ add new characters into the word table to change re_exec's
87d199 ·*¤ understanding of what a word should look like. Note that we
46f4f2 ·*¤ only accept additions into the word definition.
a4775e ·*
3a8dbd ·*¤ If the string parameter is 0 or null string, the table is
ea7dfd ·*¤ reset back to the default containing A-Z a-z 0-9 _. [We use
6b3fe1 ·*¤ the compact bitset representation for the default table]
46495d ·*/
8eaf5a
f5ab92 static CHAR deftab[16] = {¤
f0dc81 ¤   0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207, ·
404ea0 ¤   0376, 0377, 0377, 007·
91a6fe };·
60af5a
e5314a void
58ae86 re_modw( char *s )
fbbb36 {
a4e586 ¤   register int i;
7caf5a
e9c18c ¤   if (!s || !*s) {
2febaa ¤   ¤   for (i = 0; i < MAXCHR; i++)
e04f37 ¤   ¤   ¤   if (!isinset(deftab,i))
0d252d ¤   ¤   ¤   ¤   iswordc(i) = 0;
2b9371 ¤   }
d50e24 ¤   else
5508a4 ¤   ¤   while(*s)
1a0982 ¤   ¤   ¤   iswordc(*s++) = 1;
10efe6 }
77af5a
1a38e5 /*
c2c095 ·* re_subs:
--563b 0001d942419401000ad Page 12 of regex.c
4337f6 ·*¤ substitute the matched portions of the src in dst.
6a775e ·*
cf35e5 ·*¤ &¤  substitute the entire matched pattern.
96775e ·*
89b7d2 ·*¤ \digit¤ substitute a subpattern, with the given¤tag number.
2f07cd ·*¤ ¤   Tags are numbered from 1 to 9. If the particular
eba327 ·*¤ ¤   tagged subpattern does not exist, null is substituted.
5f495d ·*/
cd4d2f int
8404d4 re_subs( char *src, char *dst)
b2bb36 {
5b00cd ¤   register char c;
13e394 ¤   register int ·pin;
bac813 ¤   register char *bp;
259f32 ¤   register char *ep;
24af5a
af75d2 ¤   if (!*src || !bopat[0])
babbde ¤   ¤   return 0;
3caf5a
06ecb7 ¤   while ((c = *src++) != 0) {
760120 ¤   ¤   switch(c) {
85af5a
8bd02a ¤   ¤   case '&':
b99e23 ¤   ¤   ¤   pin = 0;
1bcdcb ¤   ¤   ¤   break;
17af5a
5b2e91 ¤   ¤   case '\\':
db526d ¤   ¤   ¤   c = *src++;
3b72b1 ¤   ¤   ¤   if (c >= '0' && c <= '9') {
90be56 ¤   ¤   ¤   ¤   pin = c - '0';
59f622 ¤   ¤   ¤   ¤   break;
8fa3a6 ¤   ¤   ¤   }
b687c7 ¤   ¤   ¤
ec9ae3 ¤   ¤   default:
7e9ea6 ¤   ¤   ¤   *dst++ = c;
3217f5 ¤   ¤   ¤   continue;
b60fe4 ¤   ¤   }
daaf5a
231c9c ¤   ¤   if ((bp = bopat[pin]) != 0 && (ep = eopat[pin]) != 0) {
261c44 ¤   ¤   ¤   while (*bp && bp < ep)
e8ff66 ¤   ¤   ¤   ¤   *dst++ = *bp++;
a33c01 ¤   ¤   ¤   if (bp < ep)
8c46f1 ¤   ¤   ¤   ¤   return 0;
bd0fe4 ¤   ¤   }
d49371 ¤   }
2746af ¤   *dst = (char) 0;
8764b7 ¤   return 1;
5defe6 }
7e87c7 ¤   ¤   ¤
13d545 #ifdef DEBUG
f438e5 /*
61e79b ·* symbolic - produce a symbolic dump of the nfa
44495d ·*/
3dc5a6 symbolic( char *s )·
1cbb36 {
c5ca78 ¤   printf("pattern: %s\n", s);
2b5018 ¤   printf("nfacode:\n");
3b9880 ¤   nfadump(nfa);
d8efe6 }
2faf5a
4c2a81 static¤
430ed3 nfadump( CHAR *ap)
24bb36 {
946983 ¤   register int n;
8faf5a
0359cc ¤   while (*ap != END)
79ded0 ¤   ¤   switch(*ap++) {
27da4c ¤   ¤   case CLO:
3e09a4 ¤   ¤   ¤   printf("CLOSURE");
4f3d54 ¤   ¤   ¤   nfadump(ap);
ac02cc ¤   ¤   ¤   switch(*ap) {
1de8d0 ¤   ¤   ¤   case CHR:
--baea 001da5e8b9a401000ad Page 13 of regex.c
8252ad ¤   ¤   ¤   ¤   n = CHRSKIP;
4df622 ¤   ¤   ¤   ¤   break;
f29c64 ¤   ¤   ¤   case ANY:
fca264 ¤   ¤   ¤   ¤   n = ANYSKIP;
08f622 ¤   ¤   ¤   ¤   break;
d7bd4b ¤   ¤   ¤   case CCL:
c0c629 ¤   ¤   ¤   ¤   n = CCLSKIP;
ddf622 ¤   ¤   ¤   ¤   break;
d8a3a6 ¤   ¤   ¤   }
b324cb ¤   ¤   ¤   ap += n;
6fcdcb ¤   ¤   ¤   break;
73d24a ¤   ¤   case CHR:
ede731 ¤   ¤   ¤   printf("\tCHR %c\n",*ap++);
92cdcb ¤   ¤   ¤   break;
53a6fe ¤   ¤   case ANY:
c35792 ¤   ¤   ¤   printf("\tANY .\n");
5ccdcb ¤   ¤   ¤   break;
371ba1 ¤   ¤   case BOL:
bea0e4 ¤   ¤   ¤   printf("\tBOL -\n");
c4cdcb ¤   ¤   ¤   break;
452b7d ¤   ¤   case EOL:
100002 ¤   ¤   ¤   printf("\tEOL -\n");
63cdcb ¤   ¤   ¤   break;
9958f6 ¤   ¤   case BOT:
a24ec6 ¤   ¤   ¤   printf("BOT: %d\n",*ap++);
5ccdcb ¤   ¤   ¤   break;
cd682a ¤   ¤   case EOT:
c9ae0a ¤   ¤   ¤   printf("EOT: %d\n",*ap++);
83cdcb ¤   ¤   ¤   break;
04b792 ¤   ¤   case BOW:
b76c67 ¤   ¤   ¤   printf("BOW\n");
7acdcb ¤   ¤   ¤   break;
72874e ¤   ¤   case EOW:
708585 ¤   ¤   ¤   printf("EOW\n");
15cdcb ¤   ¤   ¤   break;
620035 ¤   ¤   case REF:
901ca0 ¤   ¤   ¤   printf("REF: %d\n",*ap++);
74cdcb ¤   ¤   ¤   break;
df87d1 ¤   ¤   case CCL:
80846b ¤   ¤   ¤   printf("\tCCL [");
37267b ¤   ¤   ¤   for (n = 0; n < MAXCHR; n++)
4410cb ¤   ¤   ¤   ¤   if (isinset(ap,(CHAR)n)) {
81fd61 ¤   ¤   ¤   ¤   ¤   if (n < ' ')
2fc00d ¤   ¤   ¤   ¤   ¤   ¤   printf("^%c", n ^ 0x040);
014bd6 ¤   ¤   ¤   ¤   ¤   else
d89f69 ¤   ¤   ¤   ¤   ¤   ¤   printf("%c", n);
822613 ¤   ¤   ¤   ¤   }
9f1493 ¤   ¤   ¤   printf("]\n");
39a72b ¤   ¤   ¤   ap += BITBLK;
1ccdcb ¤   ¤   ¤   break;
2a9ae3 ¤   ¤   default:
54101d ¤   ¤   ¤   printf("bad nfa. opcode %o\n", ap[-1]);
470a38 ¤   ¤   ¤   exit(1);
8ecdcb ¤   ¤   ¤   break;
950fe4 ¤   ¤   }
caefe6 }
7f7454 #endif
dada28 #endif /* MACOS or DOS or NEED_BSDREGEX */
--c348 000aeae9d49401000ae Page 1 of request.c
bc38e5 /*
5ce36d ·* ·Copyright (c) 1995 Regents of the University of Michigan.
a8e4d4 ·* ·All rights reserved.
42775e ·*
facd98 ·* ·request.c - sending of ldap requests; handling of referrals
9b495d ·*/
69af5a
ad0c68 #ifndef lint·
83a4ec static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University "
263efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
cc7454 #endif
8baf5a
f3feb2 #include <stdio.h>
7b324c #include <string.h>
11af5a
d0176b #if PGPSOCKETSLDAP /* jason */
3c65aa #include "pgpSocketsLDAP.h"
dfaf5a
98db21 #else
8bc583 #ifdef MACOS
a2bea3 #include <stdlib.h>
460a8b #include <time.h>
5465e0 #include "macos.h"
916c94 #else /* MACOS */
ccfdef #if defined( DOS ) || defined( _WIN32 )
ad01b0 #ifdef DOS
cdf2ef #include "msdos.h"
4e7454 #endif
ed0a8b #include <time.h>
58bea3 #include <stdlib.h>
3eb3f5 #ifdef PCNFS
305f02 #include <tklib.h>
1aec0f #include <tk_errno.h>
30cbcc #include <bios.h>
981b77 #endif /* PCNFS */
d76382 #ifdef NCSA
fd30d1 #include "externs.h"
4e8682 #endif /* NCSA */
9baad8 #else /* DOS */
6e5d8c #include <sys/time.h>
d3f15e #include <sys/types.h>
1466f2 #include <sys/socket.h>
6d495d #include <errno.h>
ac5196 #ifdef _AIX
b2adab #include <sys/select.h>
68e564 #endif /* _AIX */
0b2a9a #include "portable.h"
9bbc39 #endif /* DOS */
78e962 #endif /* MACOS */
984edf #ifdef VMS
3f7ba6 #include "ucx_select.h"
777454 #endif
96df0f #endif /* PGPSOCKETSLDAP */
2eaf5a
5fb779 #include "lber.h"
90e990 #include "ldap.h"
74745c #include "ldap-int.h"
b6af5a
15f375 #ifdef USE_SYSCONF
6817c2 #include <unistd.h>
fc7d11 #endif /* USE_SYSCONF */
46af5a
c1af5a
5f8b9e #if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
70504c #ifdef NEEDPROTOS
3e4603 static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any );
2960f2 static void use_connection( LDAP *ld, LDAPConn *lc );
2dc75b static void free_servers( LDAPServer *srvlist );
836133 #else /* NEEDPROTOS */
83e56e static LDAPConn *find_connection();
2fc662 static void use_connection();
ae1006 static void free_servers();
--7ff4 0002f54bd0c401000ae Page 2 of request.c
fd8634 #endif /* NEEDPROTOS */
9e1c7e #endif /* LDAP_REFERRALS || LDAP_DNS */
2aaf5a
41af5a
3c4ae9 #ifdef LDAP_DNS
06504c #ifdef NEEDPROTOS
813fc4 static LDAPServer *dn2servers( LDAP *ld, char *dn );
816133 #else /* NEEDPROTOS */
b1f241 static LDAPServer *dn2servers();
0a8634 #endif /* NEEDPROTOS */
711845 #endif /* LDAP_DNS */
eeaf5a
207f8d #ifdef LDAP_REFERRALS
c4504c #ifdef NEEDPROTOS
ee8e15 static BerElement *re_encode_request( LDAP *ld, BerElement *origber,
43bea8 ····int msgid, char **dnp );
b66133 #else /* NEEDPROTOS */
d92c40 static BerElement *re_encode_request();
a78634 #endif /* NEEDPROTOS */
c990e2 #endif /* LDAP_REFERRALS */
3baf5a
e6af5a
013ab9 BerElement *
e96f75 alloc_ber_with_options( LDAP *ld )
babb36 {
9f9c95 ¤   BerElement¤ *ber;
c1af5a
3228f6 ····¤   if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) {
426f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
5bf52a #ifdef STR_TRANSLATION
97f037 ¤   } else {
25fba5 ¤   ¤   set_ber_options( ld, ber );
043dd6 #endif /* STR_TRANSLATION */
829371 ¤   }
1daf5a
6647ce ¤   return( ber );
20efe6 }
a0af5a
1eaf5a
5a314a void
8657ab set_ber_options( LDAP *ld, BerElement *ber )
9cbb36 {
5e17bc ¤   ber->ber_options = ld->ld_lberoptions;
6af52a #ifdef STR_TRANSLATION
3738e4 ¤   if (( ld->ld_lberoptions & LBER_TRANSLATE_STRINGS ) != 0 ) {
76c4b7 ¤   ¤   ber_set_string_translators( ber,
a8c696 ¤   ¤   ····ld->ld_lber_encode_translate_proc,
7e4b39 ¤   ¤   ····ld->ld_lber_decode_translate_proc );
249371 ¤   }
373dd6 #endif /* STR_TRANSLATION */
08efe6 }
2daf5a
15af5a
404d2f int
0a7f0e send_initial_request( LDAP *ld, unsigned long msgtype, char *dn,
eebf51 ¤   BerElement *ber )
eebb36 {
4d8b9e #if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
0e5f7a ¤   LDAPServer¤ *servers;
831c7e #endif /* LDAP_REFERRALS || LDAP_DNS */
6faf5a
966e15 ¤   (void) msgtype;
5008db ¤   (void) dn;
6067c5 ¤
dd48a2 ¤   Debug( LDAP_DEBUG_TRACE, "send_initial_request\n", 0, 0, 0 );
d2af5a
b35afd #if !defined( LDAP_REFERRALS ) && !defined( LDAP_DNS )
438408 ¤   if ( ber_flush( &ld->ld_sb, ber, 1 ) != 0 ) {
0faf4c ¤   ¤   ld->ld_errno = LDAP_SERVER_DOWN;
0849fa ¤   ¤   return( -1 );
3b9371 ¤   }
2faf5a
--6631 0008cf94404401000ae Page 3 of request.c
9e7920 ¤   ld->ld_errno = LDAP_SUCCESS;
e5920f ¤   return( ld->ld_msgid );
89cb1a #else /* !LDAP_REFERRALS && !LDAP_DNS */
d4af5a
534ae9 #ifdef LDAP_DNS
c4f6e9 ¤   if (( ld->ld_options & LDAP_OPT_DNS ) != 0 && ldap_is_dns_dn( dn )) {
1b1874 ¤   ¤   if (( servers = dn2servers( ld, dn )) == NULL ) {
ceb7ef ¤   ¤   ¤   ber_free( ber, 1 );
4d8e4f ¤   ¤   ¤   return( -1 );
2f0fe4 ¤   ¤   }
4aaf5a
992639 #ifdef LDAP_DEBUG
ffd7cd ¤   ¤   if ( ldap_debug & LDAP_DEBUG_TRACE ) {
989335 ¤   ¤   ¤   LDAPServer¤ *srv;
8aaf5a
903ec1 ¤   ¤   ¤   for ( srv = servers; srv != NULL;
606e64 ¤   ¤   ¤   ····srv = srv->lsrv_next ) {
07bf9b ¤   ¤   ¤   ¤   fprintf( stderr,
811eef ¤   ¤   ¤   ¤   ····"LDAP server %s: ·dn %s, port %d\n",
d40cfc ¤   ¤   ¤   ¤   ····srv->lsrv_host, ( srv->lsrv_dn == NULL ) ?
37b4e8 ¤   ¤   ¤   ¤   ····"(default)" : srv->lsrv_dn,
5bd05f ¤   ¤   ¤   ¤   ····srv->lsrv_port );
22a3a6 ¤   ¤   ¤   }
220fe4 ¤   ¤   }
849b45 #endif /* LDAP_DEBUG */
3ef037 ¤   } else {
db1845 #endif /* LDAP_DNS */
171b17 ¤   ¤   /*
e2063b ¤   ¤   ·* use of DNS is turned off or this is an X.500 DN...
ebf56a ¤   ¤   ·* use our default connection
5d9de3 ¤   ¤   ·*/
09c78b ¤   ¤   servers = NULL;
334ae9 #ifdef LDAP_DNS
10f828 ¤   }¤
b11845 #endif /* LDAP_DNS */
fbaf5a
7fff90 ¤   return( send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
f5e1d1 ¤   ····NULL, 0 ));
9f34ee #endif /* !LDAP_REFERRALS && !LDAP_DNS */
1befe6 }
0aaf5a
57af5a
d4af5a
2e8b9e #if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
744d2f int
35316e send_server_request( LDAP *ld, BerElement *ber, int msgid, LDAPRequest
5f0c27 ¤   *parentreq, LDAPServer *srvlist, LDAPConn *lc, int bind )
f3bb36 {
454939 ¤   LDAPRequest¤*lr;
c5af5a
85e73b ¤   Debug( LDAP_DEBUG_TRACE, "send_server_request\n", 0, 0, 0 );
85af5a
3abfeb ¤   ld->ld_errno = LDAP_SUCCESS;¤   /* optimistic */
a5af5a
b24ac9 ¤   if ( lc == NULL ) {
617739 ¤   ¤   if ( srvlist == NULL ) {
cb62fe ¤   ¤   ¤   lc = ld->ld_defconn;
d845a6 ¤   ¤   } else {
d15b68 ¤   ¤   ¤   if (( lc = find_connection( ld, srvlist, 1 )) ==
9ca0f7 ¤   ¤   ¤   ····NULL ) {
89e949 ¤   ¤   ¤   ¤   lc = new_connection( ld, &srvlist, 0, 1, bind );
39a3a6 ¤   ¤   ¤   }
ef596a ¤   ¤   ¤   free_servers( srvlist );
be0fe4 ¤   ¤   }
389371 ¤   }
15af5a
dfc95d ¤   if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
a81ab1 ¤   ¤   ber_free( ber, 1 );
9c1678 ¤   ¤   if ( ld->ld_errno == LDAP_SUCCESS ) {
73a9f4 ¤   ¤   ¤   ld->ld_errno = LDAP_SERVER_DOWN;
9d0fe4 ¤   ¤   }
8c49fa ¤   ¤   return( -1 );
--9c25 000fa073aaa401000ae Page 4 of request.c
a19371 ¤   }
93af5a
93f9a3 ¤   use_connection( ld, lc );
35f15f ¤   if (( lr = (LDAPRequest *)calloc( 1, sizeof( LDAPRequest ))) ==
4050ad ¤   ····NULL ) {
b06f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
7d9779 ¤   ¤   free_connection( ld, lc, 0, 0 );
271ab1 ¤   ¤   ber_free( ber, 1 );
de49fa ¤   ¤   return( -1 );
e947d1 ¤   }·
b73d9c ¤   lr->lr_msgid = msgid;
5a5c70 ¤   lr->lr_status = LDAP_REQST_INPROGRESS;
e626e9 ¤   lr->lr_res_errno = LDAP_SUCCESS;¤   /* optimistic */
fddcaa ¤   lr->lr_ber = ber;
fb4f72 ¤   lr->lr_conn = lc;
114632 ¤   if ( parentreq != NULL ) {¤ /* sub-request */
58d535 ¤   ¤   ++parentreq->lr_outrefcnt;
85f05e ¤   ¤   lr->lr_origid = parentreq->lr_origid;
1f5b43 ¤   ¤   lr->lr_parentcnt = parentreq->lr_parentcnt + 1;
b3bc5f ¤   ¤   lr->lr_parent = parentreq;
1465a7 ¤   ¤   lr->lr_refnext = parentreq->lr_refnext;
901b3d ¤   ¤   parentreq->lr_refnext = lr;
e482b5 ¤   } else {¤   ¤   ¤   /* original request */
ecf688 ¤   ¤   lr->lr_origid = lr->lr_msgid;
ca9371 ¤   }
edaf5a
f31ff0 ¤   if (( lr->lr_next = ld->ld_requests ) != NULL ) {
08b713 ¤   ¤   lr->lr_next->lr_prev = lr;
169371 ¤   }
abd250 ¤   ld->ld_requests = lr;
b60931 ¤   lr->lr_prev = NULL;
44af5a
7063f1 ¤   if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
32b7e5 #ifdef notyet
42c159 ¤   ¤   extern int¤ errno;
78af5a
f9f7aa ¤   ¤   if ( errno == EWOULDBLOCK ) {
56220c ¤   ¤   ¤   /* need to continue write later */
92cad6 ¤   ¤   ¤   lr->lr_status = LDAP_REQST_WRITING;
38558d ¤   ¤   ¤   mark_select_write( ld, lc->lconn_sb );
1445a6 ¤   ¤   } else {
47496a #else /* notyet */
3aa9f4 ¤   ¤   ¤   ld->ld_errno = LDAP_SERVER_DOWN;
b000fe ¤   ¤   ¤   free_request( ld, lr );
6391c1 ¤   ¤   ¤   free_connection( ld, lc, 0, 0 );
cb8e4f ¤   ¤   ¤   return( -1 );
21db56 #endif /* notyet */
42b7e5 #ifdef notyet
8f0fe4 ¤   ¤   }
f0db56 #endif /* notyet */
88f037 ¤   } else {
3bd937 ¤   ¤   if ( parentreq == NULL ) {
43f7f0 ¤   ¤   ¤   ber->ber_end = ber->ber_ptr;
a7948e ¤   ¤   ¤   ber->ber_ptr = ber->ber_buf;
590fe4 ¤   ¤   }
cbaf5a
052028 ¤   ¤   /* sent -- waiting for a response */
c59b2f ¤   ¤   mark_select_read( ld, lc->lconn_sb );
cf9371 ¤   }
6eaf5a
ac7920 ¤   ld->ld_errno = LDAP_SUCCESS;
e57bc5 ¤   return( msgid );
c5efe6 }
80af5a
29af5a
650bd5 LDAPConn *
536a81 new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
d56d0a ¤   int connect, int bind )
04bb36 {
fcb0e6 ¤   LDAPConn¤   *lc;
431897 ¤   LDAPServer¤ *prevsrv, *srv;
faf348 ¤   Sockbuf¤¤   *sb;
--46c9 000f77c5c1d401000ae Page 5 of request.c
e0af5a
f8d8af ¤   /*
7d9d02 ¤   ·* make a new LDAP server connection
3abe9a ¤   ·* XXX open connection synchronously for now
64a4e3 ¤   ·*/
557f99 ¤   if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL ||
c3122a ¤   ····( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf )))
d2d808 ¤   ····== NULL )) {
09a6ee ¤   ¤   if ( lc != NULL ) {
2caebe ¤   ¤   ¤   free( (char *)lc );
860fe4 ¤   ¤   }
a06f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
d5ef86 ¤   ¤   return( NULL );
a49371 ¤   }
58af5a
9cfc7c ¤   lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
8eaf5a
66fd82 ¤   if ( connect ) {
062777 ¤   ¤   prevsrv = NULL;
2daf5a
86275e ¤   ¤   for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) {
500969 ¤   ¤   ¤   if ( open_ldap_connection( ld, lc->lconn_sb,
665cbe ¤   ¤   ¤   ····srv->lsrv_host, srv->lsrv_port,
deba35 ¤   ¤   ¤   ····&lc->lconn_krbinstance, 0 ) != -1 ) {
14f622 ¤   ¤   ¤   ¤   break;
68a3a6 ¤   ¤   ¤   }
4fbf68 ¤   ¤   ¤   prevsrv = srv;
b40fe4 ¤   ¤   }
62af5a
29d012 ¤   ¤   if ( srv == NULL ) {
ba25e9 ¤   ¤   ····if ( !use_ldsb ) {
63122d ¤   ¤   ¤   free( (char *)lc->lconn_sb );
a85f30 ¤   ¤   ····}
456ba5 ¤   ¤   ····free( (char *)lc );
55a938 ¤   ¤   ····ld->ld_errno = LDAP_SERVER_DOWN;
1d36d8 ¤   ¤   ····return( NULL );
fd0fe4 ¤   ¤   }
53af5a
ff1161 ¤   ¤   if ( prevsrv == NULL ) {
4d8f82 ¤   ¤   ····*srvlistp = srv->lsrv_next;
c645a6 ¤   ¤   } else {
6921d7 ¤   ¤   ····prevsrv->lsrv_next = srv->lsrv_next;
b10fe4 ¤   ¤   }
e1961a ¤   ¤   lc->lconn_server = srv;
119371 ¤   }
d1af5a
2ef81d ¤   lc->lconn_status = LDAP_CONNST_CONNECTED;
c7f7fd ¤   lc->lconn_next = ld->ld_conns;
0965c5 ¤   ld->ld_conns = lc;
9caf5a
c6d8af ¤   /*
62cd19 ¤   ·* XXX for now, we always do a synchronous bind. ·This will have
7bd79d ¤   ·* to change in the long run...
53a4e3 ¤   ·*/
1b0e61 ¤   if ( bind ) {
411430 ¤   ¤   int¤¤   err, freepasswd, authmethod;
bdff6e ¤   ¤   char¤   ¤   *binddn, *passwd;
7f2e7d ¤   ¤   LDAPConn¤   *savedefconn;
17af5a
6ee4ed ¤   ¤   freepasswd = err = 0;
d0af5a
759191 ¤   ¤   if ( ld->ld_rebindproc == NULL ) {
fd2927 ¤   ¤   ¤   binddn = passwd = "";
664446 ¤   ¤   ¤   authmethod = LDAP_AUTH_SIMPLE;
8745a6 ¤   ¤   } else {
74f4d4 ¤   ¤   ¤   if (( err = (*ld->ld_rebindproc)( ld, &binddn, &passwd,
815e71 ¤   ¤   ¤   ····&authmethod, 0 )) == LDAP_SUCCESS ) {
803146 ¤   ¤   ¤   ¤   freepasswd = 1;
23042d ¤   ¤   ¤   } else {
dafbcd ¤   ¤   ¤   ¤   ld->ld_errno = err;
25976c ¤   ¤   ¤   ¤   err = -1;
f7a3a6 ¤   ¤   ¤   }
--13ef 000e8c81bc4401000ae Page 6 of request.c
b50fe4 ¤   ¤   }
e6af5a
99af5a
96d225 ¤   ¤   if ( err == 0 ) {
627e9f ¤   ¤   ¤   savedefconn = ld->ld_defconn;
ed181d ¤   ¤   ¤   ld->ld_defconn = lc;
189b4e ¤   ¤   ¤   ++lc->lconn_refcnt;¤/* avoid premature free */
b8af5a
45ee51 ¤   ¤   ¤   if ( ldap_bind_s( ld, binddn, passwd, authmethod ) !=
3f4a21 ¤   ¤   ¤   ····LDAP_SUCCESS ) {
3f976c ¤   ¤   ¤   ¤   err = -1;
c5a3a6 ¤   ¤   ¤   }
7ceae7 ¤   ¤   ¤   --lc->lconn_refcnt;
36ca0f ¤   ¤   ¤   ld->ld_defconn = savedefconn;
7d0fe4 ¤   ¤   }
08af5a
d34052 ¤   ¤   if ( freepasswd ) {
4db002 ¤   ¤   ¤   (*ld->ld_rebindproc)( ld, &binddn, &passwd,
d3ae55 ¤   ¤   ¤   ¤   &authmethod, 1 );
9e0fe4 ¤   ¤   }
25af5a
476d9e ¤   ¤   if ( err != 0 ) {
af107e ¤   ¤   ¤   free_connection( ld, lc, 1, 0 );
47888b ¤   ¤   ¤   lc = NULL;
3a0fe4 ¤   ¤   }
2f9371 ¤   }
80af5a
c41670 ¤   return( lc );
e8efe6 }
93af5a
51af5a
392a33 static LDAPConn *
498cb4 find_connection( LDAP *ld, LDAPServer *srv, int any )
3a38e5 /*
968561 ·* return an existing connection (if any) to the server srv
170952 ·* if "any" is non-zero, check for any server in the "srv" chain
dc495d ·*/
bebb36 {
4cb0e6 ¤   LDAPConn¤   *lc;
30fcf1 ¤   LDAPServer¤ *ls;
a4af5a
745a36 ¤   for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
2d5521 ¤   ¤   for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) {
3e1c6b ¤   ¤   ¤   if ( lc->lconn_server->lsrv_host != NULL &&
3bdf3b ¤   ¤   ¤   ····ls->lsrv_host != NULL && strcasecmp(
dc97f4 ¤   ¤   ¤   ····ls->lsrv_host, lc->lconn_server->lsrv_host ) == 0
3b8ca1 ¤   ¤   ¤   ····&& ls->lsrv_port == lc->lconn_server->lsrv_port ) {
5b620b ¤   ¤   ¤   ¤   return( lc );
c4a3a6 ¤   ¤   ¤   }
0299f9 ¤   ¤   ¤   if ( !any ) {
9cf622 ¤   ¤   ¤   ¤   break;
28a3a6 ¤   ¤   ¤   }
610fe4 ¤   ¤   }
c59371 ¤   }
20af5a
969572 ¤   return( NULL );
97efe6 }
0baf5a
3aaf5a
89af5a
3c2978 static void
2e4f10 use_connection( LDAP *ld, LDAPConn *lc )
ffbb36 {
ad9e79 ¤   (void) ld;
7367c5 ¤
be118f ¤   ++lc->lconn_refcnt;
8136aa ¤   lc->lconn_lastused = time( 0 );
75efe6 }
34af5a
b5af5a
31314a void
e8fd63 free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
--0106 0006ac4e913401000ae Page 7 of request.c
2cbb36 {
d0667a ¤   LDAPConn¤   *tmplc, *prevlc;
11af5a
425d28 ¤   Debug( LDAP_DEBUG_TRACE, "free_connection\n", 0, 0, 0 );
ddaf5a
60c4c4 ¤   if ( force || --lc->lconn_refcnt <= 0 ) {
035933 ¤   ¤   if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
1da1b1 ¤   ¤   ¤   mark_select_clear( ld, lc->lconn_sb );
b6a7f8 ¤   ¤   ¤   if ( unbind ) {
8b157c ¤   ¤   ¤   ¤   send_unbind( ld, lc->lconn_sb );
8da3a6 ¤   ¤   ¤   }
040f37 ¤   ¤   ¤   close_connection( lc->lconn_sb );
4840f1 ¤   ¤   ¤   if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) {
ee482d ¤   ¤   ¤   ¤   free( lc->lconn_sb->sb_ber.ber_buf );
80a3a6 ¤   ¤   ¤   }
880fe4 ¤   ¤   }
97fb40 ¤   ¤   prevlc = NULL;
ab455f ¤   ¤   for ( tmplc = ld->ld_conns; tmplc != NULL;
277f62 ¤   ¤   ····tmplc = tmplc->lconn_next ) {
afde7f ¤   ¤   ¤   if ( tmplc == lc ) {
09b5b2 ¤   ¤   ¤   ¤   if ( prevlc == NULL ) {
183014 ¤   ¤   ¤   ¤   ····ld->ld_conns = tmplc->lconn_next;
18b5fc ¤   ¤   ¤   ¤   } else {
f4be24 ¤   ¤   ¤   ¤   ····prevlc->lconn_next = tmplc->lconn_next;
882613 ¤   ¤   ¤   ¤   }
7df622 ¤   ¤   ¤   ¤   break;
5da3a6 ¤   ¤   ¤   }
5f0fe4 ¤   ¤   }
2ddcc7 ¤   ¤   free_servers( lc->lconn_server );
ec4bc7 ¤   ¤   if ( lc->lconn_krbinstance != NULL ) {
605b12 ¤   ¤   ¤   free( lc->lconn_krbinstance );
660fe4 ¤   ¤   }
d0803a ¤   ¤   if ( lc->lconn_sb != &ld->ld_sb ) {
cc122d ¤   ¤   ¤   free( (char *)lc->lconn_sb );
8b0fe4 ¤   ¤   }
871ed2 ¤   ¤   free( lc );
236489 ¤   ¤   Debug( LDAP_DEBUG_TRACE, "free_connection: actually freed\n",
edcda5 ¤   ¤   ····0, 0, 0 );
f1f037 ¤   } else {
19f3ff ¤   ¤   lc->lconn_lastused = time( 0 );
94605c ¤   ¤   Debug( LDAP_DEBUG_TRACE, "free_connection: refcnt %d\n",
6055df ¤   ¤   ····lc->lconn_refcnt, 0, 0 );
9a9371 ¤   }
75efe6 }
70af5a
f1af5a
282639 #ifdef LDAP_DEBUG
e3314a void
a6ec19 dump_connection( LDAP *ld, LDAPConn *lconns, int all )
87bb36 {
f0b0e6 ¤   LDAPConn¤   *lc;
1caf5a
01bb00 ¤   fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
cae2ae ¤   for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
29c778 ¤   ¤   if ( lc->lconn_server != NULL ) {
5aa11b ¤   ¤   ¤   fprintf( stderr, "* host: %s ·port: %d%s\n",
04b523 ¤   ¤   ¤   ····( lc->lconn_server->lsrv_host == NULL ) ? "(null)"
ba8478 ¤   ¤   ¤   ····: lc->lconn_server->lsrv_host,
36e6ab ¤   ¤   ¤   ····lc->lconn_server->lsrv_port, ( lc->lconn_sb ==
d82023 ¤   ¤   ¤   ····&ld->ld_sb ) ? " ·(default)" : "" );
410fe4 ¤   ¤   }
cf8a5d ¤   ¤   fprintf( stderr, " ·refcnt: %d ·status: %s\n", lc->lconn_refcnt,
1b9e14 ¤   ¤   ····( lc->lconn_status == LDAP_CONNST_NEEDSOCKET ) ?
82449b ¤   ¤   ····"NeedSocket" : ( lc->lconn_status ==
72a024 ¤   ¤   ····LDAP_CONNST_CONNECTING ) ? "Connecting" : "Connected" );
34a946 ¤   ¤   fprintf( stderr, " ·last used: %s\n",
4a5887 ¤   ¤   ····ctime( &lc->lconn_lastused ));
4c3fc0 ¤   ¤   if ( !all ) {
b5cdcb ¤   ¤   ¤   break;
810fe4 ¤   ¤   }
789371 ¤   }
6aefe6 }
--0fc8 0005e7a3d5f401000ae Page 8 of request.c
e0af5a
1aaf5a
b6314a void
5efb94 dump_requests_and_responses( LDAP *ld )
67bb36 {
2a4939 ¤   LDAPRequest¤*lr;
b1bb9c ¤   LDAPMessage¤*lm, *l;
8eaf5a
d78297 ¤   fprintf( stderr, "** Outstanding Requests:\n" );
429efb ¤   if (( lr = ld->ld_requests ) == NULL ) {
030e5b ¤   ¤   fprintf( stderr, " ··Empty\n" );
519371 ¤   }
77f6c7 ¤   for ( ; lr != NULL; lr = lr->lr_next ) {
733d66 ¤   ····fprintf( stderr, " * msgid %d, ·origid %d, status %s\n",
d5462e ¤   ¤   lr->lr_msgid, lr->lr_origid, ( lr->lr_status ==
098da9 ¤   ¤   LDAP_REQST_INPROGRESS ) ? "InProgress" :
3306b3 ¤   ¤   ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" :
080bfe ¤   ¤   ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" :
6c4b3a ¤   ¤   "Writing" );
d1364b ¤   ····fprintf( stderr, " ··outstanding referrals %d, parent count %d\n",
06030d ¤   ¤   ····lr->lr_outrefcnt, lr->lr_parentcnt );
ea9371 ¤   }
60af5a
0c772f ¤   fprintf( stderr, "** Response Queue:\n" );
e2403c ¤   if (( lm = ld->ld_responses ) == NULLMSG ) {
4e0e5b ¤   ¤   fprintf( stderr, " ··Empty\n" );
249371 ¤   }
883728 ¤   for ( ; lm != NULLMSG; lm = lm->lm_next ) {
c51cad ¤   ¤   fprintf( stderr, " * msgid %d, ·type %d\n",
72feea ¤   ¤   ····lm->lm_msgid, lm->lm_msgtype );
13a3ad ¤   ¤   if (( l = lm->lm_chain ) != NULL ) {
8225f8 ¤   ¤   ¤   fprintf( stderr, " ··chained responses:\n" );
db1bd7 ¤   ¤   ¤   for ( ; l != NULLMSG; l = l->lm_chain ) {
1fbf9b ¤   ¤   ¤   ¤   fprintf( stderr,
a33b95 ¤   ¤   ¤   ¤   ····" ·* msgid %d, ·type %d\n",
4e1f0d ¤   ¤   ¤   ¤   ····l->lm_msgid, l->lm_msgtype );
04a3a6 ¤   ¤   ¤   }
8e0fe4 ¤   ¤   }
b19371 ¤   }
2befe6 }
d89b45 #endif /* LDAP_DEBUG */
5daf5a
44af5a
62314a void
5a06e3 free_request( LDAP *ld, LDAPRequest *lr )
8cbb36 {
e1fad5 ¤   LDAPRequest¤*tmplr, *nextlr;
d2af5a
59bf15 ¤   Debug( LDAP_DEBUG_TRACE, "free_request (origid %d, msgid %d)\n",
e6f47d ¤   ¤   lr->lr_origid, lr->lr_msgid, 0 );
83af5a
e5c3c5 ¤   if ( lr->lr_parent != NULL ) {
0c1045 ¤   ¤   --lr->lr_parent->lr_outrefcnt;
bff037 ¤   } else {
94d8b5 ¤   ¤   /* free all referrals (child requests) */
6f097a ¤   ¤   for ( tmplr = lr->lr_refnext; tmplr != NULL; tmplr = nextlr ) {
e46bd2 ¤   ¤   ¤   nextlr = tmplr->lr_refnext;
7433ec ¤   ¤   ¤   free_request( ld, tmplr );
7e0fe4 ¤   ¤   }
959371 ¤   }
52af5a
20c41a ¤   if ( lr->lr_prev == NULL ) {
afcd91 ¤   ¤   ld->ld_requests = lr->lr_next;
2cf037 ¤   } else {
a12237 ¤   ¤   lr->lr_prev->lr_next = lr->lr_next;
f19371 ¤   }
95af5a
734bf9 ¤   if ( lr->lr_next != NULL ) {
8ffa7e ¤   ¤   lr->lr_next->lr_prev = lr->lr_prev;
5a9371 ¤   }
aeaf5a
5ee51c ¤   if ( lr->lr_ber != NULL ) {
--a1c8 000958ab030401000ae Page 9 of request.c
5c60de ¤   ¤   ber_free( lr->lr_ber, 1 );
cb9371 ¤   }
74af5a
a28d12 ¤   if ( lr->lr_res_error != NULL ) {
fe22c5 ¤   ¤   free( lr->lr_res_error );
af9371 ¤   }
0baf5a
91df98 ¤   if ( lr->lr_res_matched != NULL ) {
47d6cb ¤   ¤   free( lr->lr_res_matched );
809371 ¤   }
1aaf5a
fc36a5 ¤   free( lr );
bdefe6 }
0caf5a
03af5a
422978 static void
f57f0c free_servers( LDAPServer *srvlist )
b9bb36 {
4d1ac0 ····LDAPServer¤ *nextsrv;
f1af5a
1284e7 ····while ( srvlist != NULL ) {
133d3d ¤   nextsrv = srvlist->lsrv_next;
8aec61 ¤   if ( srvlist->lsrv_dn != NULL ) {
13e730 ¤   ¤   free( srvlist->lsrv_dn );
029371 ¤   }
3cd96d ¤   if ( srvlist->lsrv_host != NULL ) {
1bd615 ¤   ¤   free( srvlist->lsrv_host );
ab9371 ¤   }
36994a ¤   free( srvlist );
df3cf9 ¤   srvlist = nextsrv;
376fe7 ····}
94efe6 }
eb1c7e #endif /* LDAP_REFERRALS || LDAP_DNS */
97af5a
7daf5a
6b7f8d #ifdef LDAP_REFERRALS
c738e5 /*
3a32bd ·* XXX merging of errors in this routine needs to be improved
72495d ·*/
e04d2f int
53321c chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *hadrefp )
69bb36 {
55a23f ¤   int¤¤   rc, count, len, newdn;
9e4ae9 #ifdef LDAP_DNS
026e0e ¤   int¤¤   ldapref;
ff1845 #endif /* LDAP_DNS */
406288 ¤   char¤   ¤   *p, *ports, *ref, *tmpref, *refdn, *unfollowed;
2c98e0 ¤   LDAPRequest¤*origreq;
3bddd4 ¤   LDAPServer¤ *srv;
8a9c95 ¤   BerElement¤ *ber;
00af5a
ec4f88 ¤   Debug( LDAP_DEBUG_TRACE, "chase_referrals\n", 0, 0, 0 );
fbaf5a
69bfeb ¤   ld->ld_errno = LDAP_SUCCESS;¤   /* optimistic */
99537f ¤   *hadrefp = 0;
64af5a
81bfc8 ¤   if ( *errstrp == NULL ) {
deabea ¤   ¤   return( 0 );
a99371 ¤   }
5aaf5a
bd6667 ¤   len = strlen( *errstrp );
ed365d ¤   for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) {
131040 ¤   ¤   if (( *p == 'R' || *p == 'r' ) && strncasecmp( p,
76b62b ¤   ¤   ····LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) {
8e04fe ¤   ¤   ¤   *p = '\0';
766a91 ¤   ¤   ¤   p += LDAP_REF_STR_LEN;
4dcdcb ¤   ¤   ¤   break;
da0fe4 ¤   ¤   }
f19371 ¤   }
acaf5a
4e0a77 ¤   if ( len < LDAP_REF_STR_LEN ) {
95abea ¤   ¤   return( 0 );
--8f17 0008797736a401000ae Page 10 of request.c
a19371 ¤   }
93af5a
0f2d6f ¤   if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) {
588fc9 ¤   ¤   Debug( LDAP_DEBUG_ANY,
349c2f ¤   ¤   ····"more than %d referral hops (dropping)\n",
693a1f ¤   ¤   ····ld->ld_refhoplimit, 0, 0 );
1df726 ¤   ¤   ····/* XXX report as error in ld->ld_errno? */
8458cd ¤   ¤   ····return( 0 );
599371 ¤   }
2daf5a
854140 ¤   /* find original request */
d77e58 ¤   for ( origreq = lr; origreq->lr_parent != NULL;
8e1881 ¤   ·····origreq = origreq->lr_parent ) {
041d52 ¤   ¤   ;
719371 ¤   }
51af5a
3b7e02 ¤   unfollowed = NULL;
71f774 ¤   rc = count = 0;
4baf5a
a6fa92 ¤   /* parse out & follow referrals */
4eafc9 ¤   for ( ref = p; rc == 0 && ref != NULL; ref = p ) {
594ae9 #ifdef LDAP_DNS
ab2167 ¤   ¤   ldapref = 0;
e81845 #endif /* LDAP_DNS */
b3af5a
56507c ¤   ¤   if (( p = strchr( ref, '\n' )) != NULL ) {
0ac8a7 ¤   ¤   ¤   *p++ = '\0';
6f45a6 ¤   ¤   } else {
fe485d ¤   ¤   ¤   p = NULL;
ef0fe4 ¤   ¤   }
96af5a
0afbf1 ¤   ¤   len = strlen( ref );
8dda56 ¤   ¤   if ( len > LDAP_LDAP_REF_STR_LEN && strncasecmp( ref,
35683f ¤   ¤   ····LDAP_LDAP_REF_STR, LDAP_LDAP_REF_STR_LEN ) == 0 ) {
fbc60e ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
e76482 ¤   ¤   ¤   ····"chasing LDAP referral: <%s>\n", ref, 0, 0 );
0a4ae9 #ifdef LDAP_DNS
91ca6a ¤   ¤   ¤   ldapref = 1;
201845 #endif /* LDAP_DNS */
e5b5d4 ¤   ¤   ¤   tmpref = ref + LDAP_LDAP_REF_STR_LEN;
ae4ae9 #ifdef LDAP_DNS
ac5633 ¤   ¤   } else if ( len > LDAP_DX_REF_STR_LEN && strncasecmp( ref,
45adf0 ¤   ¤   ····LDAP_DX_REF_STR, LDAP_DX_REF_STR_LEN ) == 0 ) {
e4c60e ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
8d37cc ¤   ¤   ¤   ····"chasing DX referral: <%s>\n", ref, 0, 0 );
dbb8df ¤   ¤   ¤   tmpref = ref + LDAP_DX_REF_STR_LEN;
c21845 #endif /* LDAP_DNS */
4b45a6 ¤   ¤   } else {
39c60e ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
49bfbc ¤   ¤   ¤   ····"ignoring unknown referral <%s>\n", ref, 0, 0 );
de2e5c ¤   ¤   ¤   rc = append_referral( ld, &unfollowed, ref );
c7f48c ¤   ¤   ¤   *hadrefp = 1;
a217f5 ¤   ¤   ¤   continue;
6e0fe4 ¤   ¤   }
b4af5a
003339 ¤   ¤   *hadrefp = 1;
58a43d ¤   ¤   if (( refdn = strchr( tmpref, '/' )) != NULL ) {
b6851e ¤   ¤   ¤   *refdn++ = '\0';
acdc34 ¤   ¤   ¤   newdn = 1;
7845a6 ¤   ¤   } else {
db86e8 ¤   ¤   ¤   newdn = 0;
7d0fe4 ¤   ¤   }
bdaf5a
b10ed6 ¤   ¤   if (( ber = re_encode_request( ld, origreq->lr_ber,
0d7142 ¤   ¤   ····++ld->ld_msgid, &refdn )) == NULL ) {
888e4f ¤   ¤   ¤   return( -1 );
910fe4 ¤   ¤   }
18af5a
fb4ae9 #ifdef LDAP_DNS
83dafe ¤   ¤   if ( ldapref ) {
b01845 #endif /* LDAP_DNS */
870b0b ¤   ¤   ¤   if (( srv = (LDAPServer *)calloc( 1,
--c240 00003d3e5bb401000ae Page 11 of request.c
20da45 ¤   ¤   ¤   ····sizeof( LDAPServer ))) == NULL ) {
383c13 ¤   ¤   ¤   ¤   ber_free( ber, 1 );
daf0c8 ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
e7071b ¤   ¤   ¤   ¤   return( -1 );
5fa3a6 ¤   ¤   ¤   }
d7af5a
bc30ef ¤   ¤   ¤   if (( srv->lsrv_host = strdup( tmpref )) == NULL ) {
770c01 ¤   ¤   ¤   ¤   free( (char *)srv );
263c13 ¤   ¤   ¤   ¤   ber_free( ber, 1 );
34f0c8 ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
e8071b ¤   ¤   ¤   ¤   return( -1 );
36a3a6 ¤   ¤   ¤   }
9faf5a
23d67c ¤   ¤   ¤   if (( ports = strchr( srv->lsrv_host, ':' )) != NULL ) {
ad0bf6 ¤   ¤   ¤   ¤   *ports++ = '\0';
a8684f ¤   ¤   ¤   ¤   srv->lsrv_port = atoi( ports );
c5042d ¤   ¤   ¤   } else {
004f23 ¤   ¤   ¤   ¤   srv->lsrv_port = LDAP_PORT;
79a3a6 ¤   ¤   ¤   }
414ae9 #ifdef LDAP_DNS
2a45a6 ¤   ¤   } else {
131739 ¤   ¤   ¤   srv = dn2servers( ld, tmpref );
750fe4 ¤   ¤   }
461845 #endif /* LDAP_DNS */
6eaf5a
84b036 ¤   ¤   if ( srv != NULL && send_server_request( ld, ber, ld->ld_msgid,
13a014 ¤   ¤   ····lr, srv, NULL, 1 ) >= 0 ) {
341770 ¤   ¤   ¤   ++count;
be45a6 ¤   ¤   } else {
d903b6 ¤   ¤   ¤   Debug( LDAP_DEBUG_ANY,
07858a ¤   ¤   ¤   ····"Unable to chase referral (%s)\n",·
088f30 ¤   ¤   ¤   ····ldap_err2string( ld->ld_errno ), 0, 0 );
bc2e5c ¤   ¤   ¤   rc = append_referral( ld, &unfollowed, ref );
e50fe4 ¤   ¤   }
27af5a
494a82 ¤   ¤   if ( !newdn && refdn != NULL ) {
98245c ¤   ¤   ¤   free( refdn );
750fe4 ¤   ¤   }
e29371 ¤   }
7aaf5a
2f7bfd ¤   free( *errstrp );
17d3b3 ¤   *errstrp = unfollowed;
e7af5a
74483c ¤   return(( rc == 0 ) ? count : rc );
15efe6 }
ceaf5a
b9af5a
e14d2f int
7e9e75 append_referral( LDAP *ld, char **referralsp, char *s )
1fbb36 {
5c5d4c ¤   int¤first;
0eaf5a
b6bbc1 ¤   if ( *referralsp == NULL ) {
ee6b32 ¤   ¤   first = 1;
a7a447 ¤   ¤   *referralsp = (char *)malloc( strlen( s ) + LDAP_REF_STR_LEN
9807e1 ¤   ¤   ····+ 1 );
0cf037 ¤   } else {
0f31ee ¤   ¤   first = 0;
28ac4a ¤   ¤   *referralsp = (char *)realloc( *referralsp,
26dff0 ¤   ¤   ····strlen( *referralsp ) + strlen( s ) + 2 );
5f9371 ¤   }
99af5a
c2bbc1 ¤   if ( *referralsp == NULL ) {
cb6f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
5a49fa ¤   ¤   return( -1 );
049371 ¤   }
9caf5a
66c41f ¤   if ( first ) {
05174c ¤   ¤   strcpy( *referralsp, LDAP_REF_STR );
41f037 ¤   } else {
51cfef ¤   ¤   strcat( *referralsp, "\n" );
039371 ¤   }
--b940 00004596bb6401000ae Page 12 of request.c
04f57c ¤   strcat( *referralsp, s );
c7af5a
8bea61 ¤   return( 0 );
40efe6 }
54af5a
8daf5a
f1af5a
17b77b static BerElement *
b3edee re_encode_request( LDAP *ld, BerElement *origber, int msgid, char **dnp )
b3bb36 {
3138e5 /*
24fd7a ·* XXX this routine knows way too much about how the lber library works!
1c495d ·*/
d97dd2 ¤   unsigned long¤  along, tag;
2b6867 ¤   long¤   ¤   ver;
ba8574 ¤   int¤¤   rc;
297987 ¤   BerElement¤ tmpber, *ber;
006c7c ¤   char¤   ¤   *orig_dn;
d1af5a
2a4030 ¤   Debug( LDAP_DEBUG_TRACE,
df0fbd ¤   ····"re_encode_request: new msgid %d, new dn <%s>\n",
59ccee ¤   ····msgid, ( *dnp == NULL ) ? "NONE" : *dnp, 0 );
cdaf5a
82c527 ¤   tmpber = *origber;
d0af5a
73d8af ¤   /*
0beebc ¤   ·* all LDAP requests are sequences that start with a message id,
e3b14e ¤   ·* followed by a sequence that is tagged with the operation code
7fa4e3 ¤   ·*/
3e60a5 ¤   if ( ber_scanf( &tmpber, "{i", &along ) != LDAP_TAG_MSGID ||
9d93b8 ¤   ····( tag = ber_skip_tag( &tmpber, &along )) == LBER_DEFAULT ) {
5a804c ················ld->ld_errno = LDAP_DECODING_ERROR;
fcef86 ¤   ¤   return( NULL );
079371 ¤   }
80af5a
3c14a0 ········if (( ber = alloc_ber_with_options( ld )) == NULLBER ) {
8b23a2 ················return( NULL );
6e7fb0 ········}
16af5a
f8c72c ¤   /* bind requests have a version number before the DN & other stuff */
1b5e0c ¤   if ( tag == LDAP_REQ_BIND && ber_get_int( &tmpber, (long *)&ver ) ==
ba26c4 ¤   ····LBER_DEFAULT ) {
cb804c ················ld->ld_errno = LDAP_DECODING_ERROR;
4a1ab1 ¤   ¤   ber_free( ber, 1 );
afef86 ¤   ¤   return( NULL );
409371 ¤   }
05af5a
0facee ¤   /* the rest of the request is the DN followed by other stuff */
6148b5 ¤   if ( ber_get_stringa( &tmpber, &orig_dn ) == LBER_DEFAULT ) {
431ab1 ¤   ¤   ber_free( ber, 1 );
4fef86 ¤   ¤   return( NULL );
369371 ¤   }
2daf5a
f9772c ¤   if ( *dnp == NULL ) {
3d52d2 ¤   ¤   *dnp = orig_dn;
06f037 ¤   } else {
915dff ¤   ¤   free( orig_dn );
229371 ¤   }
45af5a
09d414 ¤   if ( tag == LDAP_REQ_BIND ) {
ed1743 ¤   ¤   rc = ber_printf( ber, "{it{is", msgid, tag, ver, *dnp );
72f037 ¤   } else {
8f9c6a ¤   ¤   rc = ber_printf( ber, "{it{s", msgid, tag, *dnp );
bc9371 ¤   }
27af5a
e03ced ¤   if ( rc == -1 ) {
fa1ab1 ¤   ¤   ber_free( ber, 1 );
24ef86 ¤   ¤   return( NULL );
119371 ¤   }
31af5a
9205c5 ¤   if ( ber_write( ber, tmpber.ber_ptr, ( tmpber.ber_end -
04d2cb ¤   ····tmpber.ber_ptr ), 0 ) != ( tmpber.ber_end - tmpber.ber_ptr ) ||
--d7b9 000f622b606401000ae Page 13 of request.c
74681e ¤   ····ber_printf( ber, "}}" ) == -1 ) {
3f3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
411ab1 ¤   ¤   ber_free( ber, 1 );
e1ef86 ¤   ¤   return( NULL );
249371 ¤   }
f0af5a
f02639 #ifdef LDAP_DEBUG
0c925b ¤   if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
812053 ¤   ¤   Debug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n",
35cda5 ¤   ¤   ····0, 0, 0 );
4053a9 ¤   ¤   ber_dump( ber, 0 );
c89371 ¤   }
609b45 #endif /* LDAP_DEBUG */
e9af5a
5847ce ¤   return( ber );
b2efe6 }
53af5a
22af5a
74d5ab LDAPRequest *
f9b5ee find_request_by_msgid( LDAP *ld, int msgid )
79bb36 {
a3567f ····¤   LDAPRequest¤*lr;
fcaf5a
6ec91b ¤   for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
e64248 ¤   ¤   if ( msgid == lr->lr_msgid ) {
a4cdcb ¤   ¤   ¤   break;
1e0fe4 ¤   ¤   }
c39371 ¤   }
ddaf5a
74a974 ¤   return( lr );
84efe6 }
a590e2 #endif /* LDAP_REFERRALS */
f6af5a
35af5a
6d4ae9 #ifdef LDAP_DNS
4a7a8e static LDAPServer *
0123bc dn2servers( LDAP *ld, char *dn )¤   /* dn can also be a domain.... */
92bb36 {
da1c6e ¤   char¤   ¤   *p, *domain, *host, *server_dn, **dxs;
da6011 ¤   int¤¤   i, port;
c19015 ¤   LDAPServer¤ *srvlist, *prevsrv, *srv;
c6af5a
288d7e ¤   if (( domain = strrchr( dn, '@' )) != NULL ) {
f42e40 ¤   ¤   ++domain;
f2f037 ¤   } else {
48bb81 ¤   ¤   domain = dn;
a89371 ¤   }
47af5a
3a7c74 ¤   if (( dxs = getdxbyname( domain )) == NULL ) {
736f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
eaef86 ¤   ¤   return( NULL );
839371 ¤   }
9daf5a
4afef9 ¤   srvlist = NULL;
c1af5a
d1c293 ¤   for ( i = 0; dxs[ i ] != NULL; ++i ) {
beaf0d ¤   ¤   port = LDAP_PORT;
efb442 ¤   ¤   server_dn = NULL;
720a66 ¤   ¤   if ( strchr( dxs[ i ], ':' ) == NULL ) {
bb64e5 ¤   ¤   ¤   host = dxs[ i ];
3cb5c7 ¤   ¤   } else if ( strlen( dxs[ i ] ) >= 7 &&
4d51f1 ¤   ¤   ····strncmp( dxs[ i ], "ldap://", 7 ) == 0 ) {
cec019 ¤   ¤   ¤   host = dxs[ i ] + 7;
1d5540 ¤   ¤   ¤   if (( p = strchr( host, ':' )) == NULL ) {
ec346c ¤   ¤   ¤   ¤   p = host;
00042d ¤   ¤   ¤   } else {
9dfcfa ¤   ¤   ¤   ¤   *p++ = '\0';
e7e6d9 ¤   ¤   ¤   ¤   port = atoi( p );
6ca3a6 ¤   ¤   ¤   }
4e8662 ¤   ¤   ¤   if (( p = strchr( p, '/' )) != NULL ) {
0f838b ¤   ¤   ¤   ¤   server_dn = ++p;
f623fe ¤   ¤   ¤   ¤   if ( *server_dn == '\0' ) {
--3301 00150197771401000ae Page 14 of request.c
01e56d ¤   ¤   ¤   ¤   ¤   server_dn = NULL;
262613 ¤   ¤   ¤   ¤   }
aba3a6 ¤   ¤   ¤   }
4145a6 ¤   ¤   } else {
430123 ¤   ¤   ¤   host = NULL;
320fe4 ¤   ¤   }
b5af5a
4b5ad2 ¤   ¤   if ( host != NULL ) {¤  /* found a server we can use */
590b0b ¤   ¤   ¤   if (( srv = (LDAPServer *)calloc( 1,
b3da45 ¤   ¤   ¤   ····sizeof( LDAPServer ))) == NULL ) {
a45c87 ¤   ¤   ¤   ¤   free_servers( srvlist );
eedf36 ¤   ¤   ¤   ¤   srvlist = NULL;
ba7d4a ¤   ¤   ¤   ¤   break;¤ ¤   /* exit loop & return */
76a3a6 ¤   ¤   ¤   }
06af5a
75cb95 ¤   ¤   ¤   /* add to end of list of servers */
304a51 ¤   ¤   ¤   if ( srvlist == NULL ) {
25eb86 ¤   ¤   ¤   ¤   srvlist = srv;
a9042d ¤   ¤   ¤   } else {
d34943 ¤   ¤   ¤   ¤   prevsrv->lsrv_next = srv;
50a3a6 ¤   ¤   ¤   }
2dbf68 ¤   ¤   ¤   prevsrv = srv;
4887c7 ¤   ¤   ¤
924e17 ¤   ¤   ¤   /* copy in info. */
af3e3f ¤   ¤   ¤   if (( srv->lsrv_host = strdup( host )) == NULL ||
32cd54 ¤   ¤   ¤   ····( server_dn != NULL && ( srv->lsrv_dn =
a7636f ¤   ¤   ¤   ····strdup( server_dn )) == NULL )) {
265c87 ¤   ¤   ¤   ¤   free_servers( srvlist );
4bdf36 ¤   ¤   ¤   ¤   srvlist = NULL;
497d4a ¤   ¤   ¤   ¤   break;¤ ¤   /* exit loop & return */
62a3a6 ¤   ¤   ¤   }
ed640f ¤   ¤   ¤   srv->lsrv_port = port;
3c0fe4 ¤   ¤   }
e59371 ¤   }
b5af5a
56a8f8 ¤   ldap_value_free( dxs );
10af5a
0acc6f ¤   if ( srvlist == NULL ) {
54af4c ¤   ¤   ld->ld_errno = LDAP_SERVER_DOWN;
769371 ¤   }
54af5a
c7310f ¤   return( srvlist );
a4efe6 }
501845 #endif /* LDAP_DNS */
--959f 0000b8b89c5401000af Page 1 of result.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
b5d181 ·* ·result.c - wait for an ldap result
6c495d ·*/
02af5a
480c68 #ifndef lint·
a707d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
0c3efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
cc7454 #endif
e0af5a
45feb2 #include <stdio.h>
c8324c #include <string.h>
b40a8b #include <time.h>
b7af5a
e571fa #if PGPSOCKETSLDAP¤ ¤   /* jason */
6865aa #include "pgpSocketsLDAP.h"
31af5a
8fdb21 #else
4ac583 #ifdef MACOS
de0a8b #include <time.h>
18bea3 #include <stdlib.h>
0265e0 #include "macos.h"
906c94 #else /* MACOS */
726cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
ca495d #include <errno.h>
a07454 #endif
3afdef #if defined( DOS ) || defined( _WIN32 )
e80a8b #include <time.h>
1c01b0 #ifdef DOS
e4f2ef #include "msdos.h"
ae7454 #endif
90b3f5 #ifdef PCNFS
a85f02 #include <tklib.h>
13ec0f #include <tk_errno.h>
7bcbcc #include <bios.h>
331b77 #endif /* PCNFS */
1a6382 #ifdef NCSA
5430d1 #include "externs.h"
158682 #endif /* NCSA */
beaad8 #else /* DOS */
ca5d8c #include <sys/time.h>
55f15e #include <sys/types.h>
8266f2 #include <sys/socket.h>
2a3db5 #include <sys/errno.h>
a25196 #ifdef _AIX
08adab #include <sys/select.h>
e5e564 #endif /* _AIX */
ee2a9a #include "portable.h"
a6bc39 #endif /* DOS */
3ce962 #endif /* MACOS */
284edf #ifdef VMS
417ba6 #include "ucx_select.h"
067454 #endif
1c2e98 #ifdef WIN32¤   ¤   /* marcd */
4f2d5f #include <winsock.h>
ae7454 #endif
07df0f #endif /* PGPSOCKETSLDAP */
e8af5a
4bb779 #include "lber.h"
c5e990 #include "ldap.h"
89745c #include "ldap-int.h"
a4af5a
0af375 #ifdef USE_SYSCONF
9717c2 #include <unistd.h>
be7d11 #endif /* USE_SYSCONF */
38af5a
83504c #ifdef NEEDPROTOS
7e60ef static int ldap_abandoned( LDAP *ld, int msgid );
68eb50 static int ldap_mark_abandoned( LDAP *ld, int msgid );
0b8746 static int wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
--cfb4 000d3bded4a401000af Page 2 of result.c
72f496 ¤   LDAPMessage **result );
587f8d #ifdef LDAP_REFERRALS
6e0002 static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb, LDAPConn *lc,
84f496 ¤   LDAPMessage **result );
fa52ed static int build_result_ber( LDAP *ld, BerElement *ber, LDAPRequest *lr );
d3ae1f static void merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr );
a24267 #else /* LDAP_REFERRALS */
25780d static int read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
d1f496 ¤   LDAPMessage **result );
7790e2 #endif /* LDAP_REFERRALS */
cfa7b3 #if defined( CLDAP ) || !defined( LDAP_REFERRALS )
6ab323 static int ldap_select1( LDAP *ld, struct timeval *timeout );
a57454 #endif
926133 #else /* NEEDPROTOS */
0c1971 static int ldap_abandoned();
cb66a0 static int ldap_mark_abandoned();
be10bf static int wait4msg();
c6cf15 static int read1msg();
847f8d #ifdef LDAP_REFERRALS
7df620 static int build_result_ber();
3efc80 static void merge_error_info();
e190e2 #endif /* LDAP_REFERRALS */
eca7b3 #if defined( CLDAP ) || !defined( LDAP_REFERRALS )
ecab38 static int ldap_select1();
717454 #endif
e38634 #endif /* NEEDPROTOS */
f7af5a
8eafd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
511851 extern int¤ errno;
207454 #endif
d2af5a
36af5a
ac38e5 /*
d13217 ·* ldap_result - wait for an ldap result response to a message from the
b0f5e6 ·* ldap server. ·If msgid is -1, any message will be accepted, otherwise
5a1c01 ·* ldap_result will wait for a response with msgid. ·If all is 0 the
2472c3 ·* first message with id msgid will be accepted, otherwise, ldap_result
89f6d7 ·* will wait for all responses with id msgid and then return a pointer to
906116 ·* the entire list of messages. ·This is only useful for search responses,
0bfe61 ·* which can be of two message types (zero or more entries, followed by an
1ee89e ·* ldap result). ·The type of the first message received is returned.
8a896c ·* When waiting, any messages that have been abandoned are discarded.
82775e ·*
df305c ·* Example:
1b2342 ·*¤ ldap_result( s, msgid, all, timeout, result )
30495d ·*/
9b4d2f int
0c891c ldap_result( LDAP *ld, int msgid, int all, struct timeval *timeout,
0721c3 ¤   LDAPMessage **result )
acbb36 {
f15d51 ¤   LDAPMessage¤*lm, *lastlm, *nextlm;
4faf5a
bcd8af ¤   /*
f3b723 ¤   ·* First, look through the list of responses we have received on
8f29f0 ¤   ·* this association and see if the response we're interested in
a9780f ¤   ·* is there. ·If it is, return it. ·If not, call wait4msg() to
18edbb ¤   ·* wait until it arrives or timeout occurs.
95a4e3 ¤   ·*/
00af5a
b47dbc ¤   Debug( LDAP_DEBUG_TRACE, "ldap_result\n", 0, 0, 0 );
afaf5a
65c795 ¤   *result = NULLMSG;
75dbc8 ¤   lastlm = NULLMSG;
996e55 ¤   for ( lm = ld->ld_responses; lm != NULLMSG; lm = nextlm ) {
1b60d1 ¤   ¤   nextlm = lm->lm_next;
2aaf5a
8018a9 ¤   ¤   if ( ldap_abandoned( ld, lm->lm_msgid ) ) {
a5ae9f ¤   ¤   ¤   ldap_mark_abandoned( ld, lm->lm_msgid );
caaf5a
46fabe ¤   ¤   ¤   if ( lastlm == NULLMSG ) {
ad6a6f ¤   ¤   ¤   ¤   ld->ld_responses = lm->lm_next;
d3042d ¤   ¤   ¤   } else {
--9375 00074c99305401000af Page 3 of result.c
8821e8 ¤   ¤   ¤   ¤   lastlm->lm_next = nextlm;
6aa3a6 ¤   ¤   ¤   }
46af5a
93de0b ¤   ¤   ¤   ldap_msgfree( lm );
86af5a
c317f5 ¤   ¤   ¤   continue;
460fe4 ¤   ¤   }
52af5a
599728 ¤   ¤   if ( msgid == LDAP_RES_ANY || lm->lm_msgid == msgid ) {
b746f7 ¤   ¤   ¤   LDAPMessage¤*tmp;
19af5a
b74c59 ¤   ¤   ¤   if ( all == 0
e23e1c ¤   ¤   ¤   ····|| (lm->lm_msgtype != LDAP_RES_SEARCH_RESULT
b0fd51 ¤   ¤   ¤   ····&& lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY) )
63f622 ¤   ¤   ¤   ¤   break;
83af5a
a604d6 ¤   ¤   ¤   for ( tmp = lm; tmp != NULLMSG; tmp = tmp->lm_chain ) {
176579 ¤   ¤   ¤   ¤   if ( tmp->lm_msgtype == LDAP_RES_SEARCH_RESULT )
5a14c3 ¤   ¤   ¤   ¤   ¤   break;
fba3a6 ¤   ¤   ¤   }
47af5a
0ebde9 ¤   ¤   ¤   if ( tmp == NULLMSG ) {
e1a723 ¤   ¤   ¤   ¤   return( wait4msg( ld, msgid, all, timeout,
64197d ¤   ¤   ¤   ¤   ····result ) );
19a3a6 ¤   ¤   ¤   }
c2af5a
51cdcb ¤   ¤   ¤   break;
560fe4 ¤   ¤   }
961fcd ¤   ¤   lastlm = lm;
f19371 ¤   }
9ae772 ¤   if ( lm == NULLMSG ) {
f136fa ¤   ¤   return( wait4msg( ld, msgid, all, timeout, result ) );
fc9371 ¤   }
fbaf5a
083732 ¤   if ( lastlm == NULLMSG ) {
4192d2 ¤   ¤   ld->ld_responses = (all == 0 && lm->lm_chain != NULLMSG
e0f997 ¤   ¤   ····? lm->lm_chain : lm->lm_next);
02f037 ¤   } else {
bad201 ¤   ¤   lastlm->lm_next = (all == 0 && lm->lm_chain != NULLMSG
a4f997 ¤   ¤   ····? lm->lm_chain : lm->lm_next);
9f9371 ¤   }
752b26 ¤   if ( all == 0 )
b894b5 ¤   ¤   lm->lm_chain = NULLMSG;
e24ce6 ¤   lm->lm_next = NULLMSG;
1daf5a
2e6d16 ¤   *result = lm;
297920 ¤   ld->ld_errno = LDAP_SUCCESS;
aa120a ¤   return( lm->lm_msgtype );
1eefe6 }
33af5a
65beb7 static int
c739f5 wait4msg( LDAP *ld, int msgid, int all, struct timeval *timeout,
8a21c3 ¤   LDAPMessage **result )
f0bb36 {
9f8574 ¤   int¤¤   rc;
56dabe ¤   struct timeval¤ tv, *tvp;
1ed297 ¤   long¤   ¤   start_time, tmp_time;
f27f8d #ifdef LDAP_REFERRALS
2f7ab9 ¤   LDAPConn¤   *lc, *nextlc;
9690e2 #endif /* LDAP_REFERRALS */
1faf5a
702639 #ifdef LDAP_DEBUG
2da711 ¤   if ( timeout == NULL ) {
b0523e ¤   ¤   Debug( LDAP_DEBUG_TRACE, "wait4msg (infinite timeout)\n",
78cda5 ¤   ¤   ····0, 0, 0 );
45f037 ¤   } else {
98c997 ¤   ¤   Debug(LDAP_DEBUG_TRACE,"wait4msg (timeout %ld sec, %ld usec)\n",
d066eb ¤   ¤   ····timeout->tv_sec, timeout->tv_usec, 0 );
949371 ¤   }
769b45 #endif /* LDAP_DEBUG */
4daf5a
74a711 ¤   if ( timeout == NULL ) {
--79a2 00019a177ae401000af Page 4 of result.c
261130 ¤   ¤   tvp = NULL;
f3f037 ¤   } else {
329328 ¤   ¤   tv = *timeout;
dab962 ¤   ¤   tvp = &tv;
76eb8d ¤   ¤   start_time = (long)time( NULL );
a09371 ¤   }
10dabf ¤   ¤   ····
b6175b ¤   rc = -2;
8fba47 ¤   while ( rc == -2 ) {
169588 #ifndef LDAP_REFERRALS
f10b35 ¤   ¤   /* hack attack */
e5c81f ¤   ¤   if ( ld->ld_sb.sb_ber.ber_ptr >= ld->ld_sb.sb_ber.ber_end ) {
4940ee ¤   ¤   ¤   rc = ldap_select1( ld, tvp );
eaaf5a
65afd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
6d2d7a ¤   ¤   ¤   if ( rc == 0 || ( rc == -1 && (( ld->ld_options &
8d70f3 ¤   ¤   ¤   ····LDAP_OPT_RESTART ) == 0 || errno != EINTR ))) {
93db21 #else
b5192c ¤   ¤   ¤   if ( rc == -1 || rc == 0 ) {
537454 #endif
217dd7 ¤   ¤   ¤   ¤   ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
679a5c ¤   ¤   ¤   ¤   ····LDAP_TIMEOUT);
e91919 ¤   ¤   ¤   ¤   return( rc );
aea3a6 ¤   ¤   ¤   }
00af5a
c80fe4 ¤   ¤   }
b6fb58 ¤   ¤   if ( rc == -1 ) {
e5333b ¤   ¤   ¤   rc = -2;¤   /* select interrupted: loop */
1545a6 ¤   ¤   } else {
8d9916 ¤   ¤   ¤   rc = read1msg( ld, msgid, all, &ld->ld_sb, result );
4d0fe4 ¤   ¤   }
d492b4 #else /* !LDAP_REFERRALS */
322639 #ifdef LDAP_DEBUG
95d7cd ¤   ¤   if ( ldap_debug & LDAP_DEBUG_TRACE ) {
586495 ¤   ¤   ¤   dump_connection( ld, ld->ld_conns, 1 );
e5d626 ¤   ¤   ¤   dump_requests_and_responses( ld );
9b0fe4 ¤   ¤   }
f29b45 #endif /* LDAP_DEBUG */
79d073 ¤   ¤   for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
9a72a5 ¤   ¤   ¤   if ( lc->lconn_sb->sb_ber.ber_ptr <
40d0db ¤   ¤   ¤   ····lc->lconn_sb->sb_ber.ber_end ) {
411222 ¤   ¤   ¤   ¤   rc = read1msg( ld, msgid, all, lc->lconn_sb,
4d24c7 ¤   ¤   ¤   ¤   ····lc, result );
17f622 ¤   ¤   ¤   ¤   break;
32a3a6 ¤   ¤   ¤   }
660fe4 ¤   ¤   }
b8af5a
a4bcac ¤   ¤   if ( lc == NULL ) {
a59a26 ¤   ¤   ¤   rc = do_ldap_select( ld, tvp );
ebaf5a
64af5a
1155b5 #if defined( LDAP_DEBUG ) && !defined( MACOS ) && !defined( DOS ) && !defined(P¶
a27ac8 GPSOCKETSLDAP) /* jason */
ef720c ¤   ¤   ¤   if ( rc == -1 ) {
d065c1 ¤   ¤   ¤   ····Debug( LDAP_DEBUG_TRACE,
984f08 ¤   ¤   ¤   ¤   ····"do_ldap_select returned -1: errno %d\n",
71556f ¤   ¤   ¤   ¤   ····errno, 0, 0 );
8ca3a6 ¤   ¤   ¤   }
767454 #endif
c1af5a
0fafd1 #if !defined( MACOS ) && !defined( DOS ) && !defined(PGPSOCKETSLDAP) /* jason */
062d7a ¤   ¤   ¤   if ( rc == 0 || ( rc == -1 && (( ld->ld_options &
c870f3 ¤   ¤   ¤   ····LDAP_OPT_RESTART ) == 0 || errno != EINTR ))) {
bedb21 #else
de192c ¤   ¤   ¤   if ( rc == -1 || rc == 0 ) {
f27454 #endif
9f7dd7 ¤   ¤   ¤   ¤   ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
059a5c ¤   ¤   ¤   ¤   ····LDAP_TIMEOUT);
1d1919 ¤   ¤   ¤   ¤   return( rc );
4ea3a6 ¤   ¤   ¤   }
f1af5a
19720c ¤   ¤   ¤   if ( rc == -1 ) {
--3877 000884121d7401000af Page 5 of result.c
263400 ¤   ¤   ¤   ¤   rc = -2;¤   /* select interrupted: loop */
c5042d ¤   ¤   ¤   } else {
865290 ¤   ¤   ¤   ¤   rc = -2;
175a69 ¤   ¤   ¤   ¤   for ( lc = ld->ld_conns; rc == -2 && lc != NULL;
22de3e ¤   ¤   ¤   ¤   ····lc = nextlc ) {
cd4857 ¤   ¤   ¤   ¤   ¤   nextlc = lc->lconn_next;
49630c ¤   ¤   ¤   ¤   ¤   if ( lc->lconn_status ==
3db820 ¤   ¤   ¤   ¤   ¤   ····LDAP_CONNST_CONNECTED &&
8dbb0b ¤   ¤   ¤   ¤   ¤   ····is_read_ready( ld,
03299c ¤   ¤   ¤   ¤   ¤   ····lc->lconn_sb )) {
0293e5 ¤   ¤   ¤   ¤   ¤   ¤   rc = read1msg( ld, msgid, all,
205aa3 ¤   ¤   ¤   ¤   ¤   ¤   ····lc->lconn_sb, lc, result );
671c89 ¤   ¤   ¤   ¤   ¤   }
df2613 ¤   ¤   ¤   ¤   }
cfa3a6 ¤   ¤   ¤   }
580fe4 ¤   ¤   }
8c41c3 #endif /* !LDAP_REFERRALS */
dcaf5a
cd28cb ¤   ¤   if ( rc == -2 && tvp != NULL ) {
04e1e2 ¤   ¤   ¤   tmp_time = (long)time( NULL );
3928cf ¤   ¤   ¤   if (( tv.tv_sec -= ·( tmp_time - start_time )) <= 0 ) {
472d10 ¤   ¤   ¤   ¤   rc = 0;¤/* timed out */
6edb09 ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_TIMEOUT;
baf622 ¤   ¤   ¤   ¤   break;
fea3a6 ¤   ¤   ¤   }
06af5a
a317a9 ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "wait4msg: ·%ld secs to go\n",
947ee1 ¤   ¤   ¤   ¤   tv.tv_sec, 0, 0 );
4ba4ad ¤   ¤   ¤   start_time = tmp_time;
cc0fe4 ¤   ¤   }
cc9371 ¤   }
7baf5a
ea6d62 ¤   return( rc );
82efe6 }
f7af5a
dbaf5a
85beb7 static int
c98d69 read1msg( LDAP *ld, int msgid, int all, Sockbuf *sb,
cc7f8d #ifdef LDAP_REFERRALS
b158ca ····LDAPConn *lc,
d590e2 #endif /* LDAP_REFERRALS */
e539e2 ····LDAPMessage **result )
0dbb36 {
e528d5 ¤   BerElement¤ ber;
34b1c5 ¤   LDAPMessage¤*new, *l, *prev, *tmp;
e0a321 ¤   long¤   ¤   id;
e9ef2c ¤   unsigned long¤  tag, len;
86f133 ¤   int¤¤   foundit = 0;
e67f8d #ifdef LDAP_REFERRALS
824939 ¤   LDAPRequest¤*lr;
e30c19 ¤   BerElement¤ tmpber;
115452 ¤   int¤¤   rc, refer_cnt, hadref, simple_request;
1e15da ¤   unsigned long¤  lderr;
e790e2 #endif /* LDAP_REFERRALS */
84af5a
6185dc ¤   Debug( LDAP_DEBUG_TRACE, "read1msg\n", 0, 0, 0 );
78af5a
22adb0 ¤   ber_init( &ber, 0 );
2a8fe6 ¤   set_ber_options( ld, &ber );
b6af5a
d0df09 ¤   /* get the next message */
b646a4 ¤   if ( (tag = ber_get_next( sb, &len, &ber ))
06e8e3 ¤   ····!= LDAP_TAG_MESSAGE ) {
03cc4d ¤   ¤   ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
c6e472 ¤   ¤   ····LDAP_LOCAL_ERROR);
f249fa ¤   ¤   return( -1 );
7b9371 ¤   }
e1af5a
583dc6 ¤   /* message id */
37177c ¤   if ( ber_get_int( &ber, &id ) == LBER_ERROR ) {
6f3108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
8849fa ¤   ¤   return( -1 );
--2bb9 00080e464fd401000af Page 6 of result.c
a19371 ¤   }
93af5a
6983a8 ¤   /* if it's been abandoned, toss it */
7100af ¤   if ( ldap_abandoned( ld, (int)id ) ) {
5e53b9 ¤   ¤   free( ber.ber_buf );¤   /* gack! */
da162b ¤   ¤   return( -2 );¤  /* continue looking */
f49371 ¤   }
c0af5a
b77f8d #ifdef LDAP_REFERRALS
6feaa7 ¤   if (( lr = find_request_by_msgid( ld, id )) == NULL ) {
238fc9 ¤   ¤   Debug( LDAP_DEBUG_ANY,
d620f1 ¤   ¤   ····"no request for response with msgid %ld (tossing)\n",
a986fb ¤   ¤   ····id, 0, 0 );
8953b9 ¤   ¤   free( ber.ber_buf );¤   /* gack! */
39162b ¤   ¤   return( -2 );¤  /* continue looking */
259371 ¤   }
f6c438 ¤   Debug( LDAP_DEBUG_TRACE, "got %s msgid %ld, original id %d\n",
1ffb61 ¤   ····( tag == LDAP_RES_SEARCH_ENTRY ) ? "entry" : "result", id,
c8d7af ¤   ····lr->lr_origid );
96630a ¤   id = lr->lr_origid;
f390e2 #endif /* LDAP_REFERRALS */
6daf5a
69ecda ¤   /* the message type */
73e226 ¤   if ( (tag = ber_peek_tag( &ber, &len )) == LBER_ERROR ) {
4f3108 ¤   ¤   ld->ld_errno = LDAP_DECODING_ERROR;
3849fa ¤   ¤   return( -1 );
289371 ¤   }
32af5a
4e7f8d #ifdef LDAP_REFERRALS
c50209 ¤   refer_cnt = 0;
75346c ¤   hadref = simple_request = 0;
c8e6ba ¤   rc = -2;¤   /* default is to keep looking (no response found) */
8fcba6 ¤   lr->lr_res_msgtype = tag;
e3af5a
1fe423 ¤   if ( tag != LDAP_RES_SEARCH_ENTRY ) {
61c224 ¤   ¤   if ( ld->ld_version >= LDAP_VERSION2 &&
577a5c ¤   ¤   ¤   ····( lr->lr_parent != NULL ||
b8738b ¤   ¤   ¤   ····( ld->ld_options & LDAP_OPT_REFERRALS ) != 0 )) {
19ba8f ¤   ¤   ¤   tmpber = ber;¤  /* struct copy */
ec13ba ¤   ¤   ¤   if ( ber_scanf( &tmpber, "{iaa}", &lderr,
58cfe2 ¤   ¤   ¤   ····&lr->lr_res_matched, &lr->lr_res_error )
d7d9ca ¤   ¤   ¤   ····!= LBER_ERROR ) {
448fa0 ¤   ¤   ¤   ¤   if ( lderr != LDAP_SUCCESS ) {
de8845 ¤   ¤   ¤   ¤   ¤   /* referrals are in error string */
2d08f4 ¤   ¤   ¤   ¤   ¤   refer_cnt = chase_referrals( ld, lr,
e95ef8 ¤   ¤   ¤   ¤   ¤   ····&lr->lr_res_error, &hadref );
082613 ¤   ¤   ¤   ¤   }
feaf5a
3058ad ¤   ¤   ¤   ¤   /* save errno, message, and matched string */
987c0e ¤   ¤   ¤   ¤   if ( !hadref || lr->lr_res_error == NULL ) {
c76697 ¤   ¤   ¤   ¤   ¤   lr->lr_res_errno = ( lderr ==
53acec ¤   ¤   ¤   ¤   ¤   LDAP_PARTIAL_RESULTS ) ? LDAP_SUCCESS
bf8524 ¤   ¤   ¤   ¤   ¤   : lderr;
15bf71 ¤   ¤   ¤   ¤   } else if ( ld->ld_errno != LDAP_SUCCESS ) {
de606e ¤   ¤   ¤   ¤   ¤   lr->lr_res_errno = ld->ld_errno;
e6b5fc ¤   ¤   ¤   ¤   } else {
34bd21 ¤   ¤   ¤   ¤   ¤   lr->lr_res_errno = LDAP_PARTIAL_RESULTS;
212613 ¤   ¤   ¤   ¤   }
f5746d Debug( LDAP_DEBUG_TRACE,
4e1711 ····"new result: ·res_errno: %d, res_error: <%s>, res_matched: <%s>\n",
66dbe2 ····lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "",
798ad4 ····lr->lr_res_matched ? lr->lr_res_matched : "" );
aaa3a6 ¤   ¤   ¤   }
e90fe4 ¤   ¤   }
bcaf5a
2efb66 ¤   ¤   Debug( LDAP_DEBUG_TRACE,
da4298 ¤   ¤   ····"read1msg: ·%d new referrals\n", refer_cnt, 0, 0 );
a0af5a
1b6642 ¤   ¤   if ( refer_cnt != 0 ) {¤/* chasing referrals */
314be9 ¤   ¤   ¤   free( ber.ber_buf );¤   /* gack! */
3e2109 ¤   ¤   ¤   ber.ber_buf = NULL;
800c3f ¤   ¤   ¤   if ( refer_cnt < 0 ) {
--405f 00078fd2ae6401000af Page 7 of result.c
07c629 ¤   ¤   ¤   ¤   return( -1 );¤  /* fatal error */
f2a3a6 ¤   ¤   ¤   }
122650 ¤   ¤   ¤   lr->lr_status = LDAP_REQST_CHASINGREFS;
4f45a6 ¤   ¤   } else {
48e8c4 ¤   ¤   ¤   if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
1719bc ¤   ¤   ¤   ¤   /* request without any referrals */
cce55e ¤   ¤   ¤   ¤   simple_request = ( hadref ? 0 : 1 );
22042d ¤   ¤   ¤   } else {
5013a8 ¤   ¤   ¤   ¤   /* request with referrals or child request */
d5dda8 ¤   ¤   ¤   ¤   free( ber.ber_buf );¤   /* gack! */
b0aaf5 ¤   ¤   ¤   ¤   ber.ber_buf = NULL;
e0a3a6 ¤   ¤   ¤   }
c1af5a
b98719 ¤   ¤   ¤   while ( lr->lr_parent != NULL ) {
8083ec ¤   ¤   ¤   ¤   merge_error_info( ld, lr->lr_parent, lr );
72af5a
c35ab8 ¤   ¤   ¤   ¤   lr = lr->lr_parent;
3e6a31 ¤   ¤   ¤   ¤   if ( --lr->lr_outrefcnt > 0 ) {
b33c87 ¤   ¤   ¤   ¤   ¤   break;¤ /* not completely done yet */
df2613 ¤   ¤   ¤   ¤   }
c7a3a6 ¤   ¤   ¤   }
4baf5a
c2e8c4 ¤   ¤   ¤   if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
ff05fc ¤   ¤   ¤   ¤   id = lr->lr_msgid;
bec1d8 ¤   ¤   ¤   ¤   tag = lr->lr_res_msgtype;
eb43ef ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_ANY, "request %ld done\n",
c6ddc0 ¤   ¤   ¤   ¤   ····id, 0, 0 );
2c746d Debug( LDAP_DEBUG_TRACE,
5ba4eb "res_errno: %d, res_error: <%s>, res_matched: <%s>\n",
f08951 lr->lr_res_errno, lr->lr_res_error ? lr->lr_res_error : "",
d2c199 lr->lr_res_matched ? lr->lr_res_matched : "" );
550a6f ¤   ¤   ¤   ¤   if ( !simple_request ) {
0df889 ¤   ¤   ¤   ¤   ¤   if ( ber.ber_buf != NULL ) {
c6e448 ¤   ¤   ¤   ¤   ¤   ¤   free( ber.ber_buf ); /* gack! */
bee7c6 ¤   ¤   ¤   ¤   ¤   ¤   ber.ber_buf = NULL;
571c89 ¤   ¤   ¤   ¤   ¤   }
0df275 ¤   ¤   ¤   ¤   ¤   if ( build_result_ber( ld, &ber, lr )
05f838 ¤   ¤   ¤   ¤   ¤   ····== LBER_ERROR ) {
71395d ¤   ¤   ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
2a6cb0 ¤   ¤   ¤   ¤   ¤   ¤   rc = -1; /* fatal error */
931c89 ¤   ¤   ¤   ¤   ¤   }
c02613 ¤   ¤   ¤   ¤   }
57af5a
4ac5ab ¤   ¤   ¤   ¤   free_request( ld, lr );
21a3a6 ¤   ¤   ¤   }
9daf5a
f10bb0 ¤   ¤   ¤   if ( lc != NULL ) {
69c818 ¤   ¤   ¤   ¤   free_connection( ld, lc, 0, 1 );
b6a3a6 ¤   ¤   ¤   }
330fe4 ¤   ¤   }
a89371 ¤   }
a5af5a
638e6b ¤   if ( ber.ber_buf == NULL ) {
1957f8 ¤   ¤   return( rc );
019371 ¤   }
32af5a
a090e2 #endif /* LDAP_REFERRALS */
dab353 ¤   /* make a new ldap message */
f1bd94 ¤   if ( (new = (LDAPMessage *) calloc( 1, sizeof(LDAPMessage) ))
da3c7b ¤   ····== NULL ) {
9a6f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
5849fa ¤   ¤   return( -1 );
639371 ¤   }
fa5426 ¤   new->lm_msgid = (int)id;
ed7a70 ¤   new->lm_msgtype = tag;
38a47b ¤   new->lm_ber = ber_dup( &ber );
a8af5a
0023e9 #ifndef NO_CACHE
61b056 ¤   ¤   if ( ld->ld_cache != NULL ) {
91c96d ¤   ¤   ¤   add_result_to_cache( ld, new );
660fe4 ¤   ¤   }
781992 #endif /* NO_CACHE */
--c3cb 000939ef1e9401000af Page 8 of result.c
e0af5a
3ff072 ¤   /* is this the one we're looking for? */
c37e37 ¤   if ( msgid == LDAP_RES_ANY || id == msgid ) {
248bec ¤   ¤   if ( all == 0
526831 ¤   ¤   ····|| (new->lm_msgtype != LDAP_RES_SEARCH_RESULT
2365a7 ¤   ¤   ····&& new->lm_msgtype != LDAP_RES_SEARCH_ENTRY) ) {
20fc77 ¤   ¤   ¤   *result = new;
7e41a5 ¤   ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
5af17a ¤   ¤   ¤   return( tag );
54bbc1 ¤   ¤   } else if ( new->lm_msgtype == LDAP_RES_SEARCH_RESULT) {
4553af ¤   ¤   ¤   foundit = 1;¤   /* return the chain later */
5f0fe4 ¤   ¤   }
e39371 ¤   }
4aaf5a
817869 ¤   /*·
9214b1 ¤   ·* if not, we must add it to the list of responses. ·if
53d3ae ¤   ·* the msgid is already there, it must be part of an existing
55da3e ¤   ·* search response.
97a4e3 ¤   ·*/
79af5a
8fbd82 ¤   prev = NULLMSG;
29aaea ¤   for ( l = ld->ld_responses; l != NULLMSG; l = l->lm_next ) {
8e436a ¤   ¤   if ( l->lm_msgid == new->lm_msgid )
f9cdcb ¤   ¤   ¤   break;
ac8196 ¤   ¤   prev = l;
339371 ¤   }
0eaf5a
6ba5bc ¤   /* not part of an existing search response */
df7f03 ¤   if ( l == NULLMSG ) {
e96b8a ¤   ¤   if ( foundit ) {
17fc77 ¤   ¤   ¤   *result = new;
c141a5 ¤   ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
cdf17a ¤   ¤   ¤   return( tag );
900fe4 ¤   ¤   }
55af5a
8e94ab ¤   ¤   new->lm_next = ld->ld_responses;
3a0957 ¤   ¤   ld->ld_responses = new;
af162b ¤   ¤   return( -2 );¤  /* continue looking */
ca9371 ¤   }
caaf5a
a56436 ¤   Debug( LDAP_DEBUG_TRACE, "adding response id %d type %d:\n",
d1fa63 ¤   ····new->lm_msgid, new->lm_msgtype, 0 );
aeaf5a
b5ddd2 ¤   /* part of a search response - add to end of list of entries */
82c987 ¤   for ( tmp = l; tmp->lm_chain != NULLMSG &&
b90ec4 ¤   ····tmp->lm_chain->lm_msgtype == LDAP_RES_SEARCH_ENTRY;
8ce6bc ¤   ····tmp = tmp->lm_chain )
edc78a ¤   ¤   ;¤  /* NULL */
263618 ¤   tmp->lm_chain = new;
a7af5a
2c128f ¤   /* return the whole chain if that's what we were looking for */
23da5b ¤   if ( foundit ) {
8ffe5e ¤   ¤   if ( prev == NULLMSG )
d3b528 ¤   ¤   ¤   ld->ld_responses = l->lm_next;
b30e1d ¤   ¤   else
5f3dfb ¤   ¤   ¤   prev->lm_next = l->lm_next;
678622 ¤   ¤   *result = l;
654448 ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
b2139b ¤   ¤   return( tag );
9c9371 ¤   }
70af5a
c987b3 ¤   return( -2 );¤  /* continue looking */
d4efe6 }
38af5a
1baf5a
8e7f8d #ifdef LDAP_REFERRALS
c7beb7 static int
a95d03 build_result_ber( LDAP *ld, BerElement *ber, LDAPRequest *lr )
3ebb36 {
3693e7 ¤   unsigned long¤  len;
97e4a6 ¤   long¤   ¤   along;
93af5a
--a3b8 00059fd0663401000af Page 9 of result.c
749d9f ¤   ber_init( ber, 0 );
8a7059 ¤   set_ber_options( ld, ber );
7a7366 ¤   if ( ber_printf( ber, "{it{ess}}", lr->lr_msgid,
628d90 ¤   ····(long)lr->lr_res_msgtype, lr->lr_res_errno,
9c323a ¤   ····lr->lr_res_matched ? lr->lr_res_matched : "",
4e35b5 ¤   ····lr->lr_res_error ? lr->lr_res_error : "" ) == LBER_ERROR ) {
50e5a4 ¤   ¤   return( LBER_ERROR );
659371 ¤   }
0eaf5a
12e2a0 ¤   ber_reset( ber, 1 );
789661 ¤   if ( ber_skip_tag( ber, &len ) == LBER_ERROR ) {
9be5a4 ¤   ¤   return( LBER_ERROR );
489371 ¤   }
03af5a
31707a ¤   if ( ber_get_int( ber, &along ) == LBER_ERROR ) {
a1e5a4 ¤   ¤   return( LBER_ERROR );
269371 ¤   }
69af5a
f60905 ¤   return( ber_peek_tag( ber, &len ));
08efe6 }
b2af5a
8caf5a
a72978 static void
3e7143 merge_error_info( LDAP *ld, LDAPRequest *parentr, LDAPRequest *lr )
66bb36 {
9f38e5 /*
f4a7e7 ·* Merge error information in "lr" with "parentr" error code and string.
60495d ·*/
f702d4 ¤   if ( lr->lr_res_errno == LDAP_PARTIAL_RESULTS ) {
49a638 ¤   ¤   parentr->lr_res_errno = lr->lr_res_errno;
b3b1fc ¤   ¤   if ( lr->lr_res_error != NULL ) {
c94866 ¤   ¤   ¤   (void)append_referral( ld, &parentr->lr_res_error,
620b14 ¤   ¤   ¤   ····lr->lr_res_error );
b80fe4 ¤   ¤   }
4cc8cd ¤   } else if ( lr->lr_res_errno != LDAP_SUCCESS &&
9c9a01 ¤   ····parentr->lr_res_errno == LDAP_SUCCESS ) {
c4a638 ¤   ¤   parentr->lr_res_errno = lr->lr_res_errno;
28112f ¤   ¤   if ( parentr->lr_res_error != NULL ) {
bc9902 ¤   ¤   ¤   free( parentr->lr_res_error );
e30fe4 ¤   ¤   }
baf26c ¤   ¤   parentr->lr_res_error = lr->lr_res_error;
afd742 ¤   ¤   lr->lr_res_error = NULL;
d865b1 ¤   ¤   if ( NAME_ERROR( lr->lr_res_errno )) {
d4d4bc ¤   ¤   ¤   if ( parentr->lr_res_matched != NULL ) {
c408ac ¤   ¤   ¤   ¤   free( parentr->lr_res_matched );
fda3a6 ¤   ¤   ¤   }
045e1e ¤   ¤   ¤   parentr->lr_res_matched = lr->lr_res_matched;
0aba3e ¤   ¤   ¤   lr->lr_res_matched = NULL;
370fe4 ¤   ¤   }
839371 ¤   }
38af5a
a07e5a ¤   Debug( LDAP_DEBUG_TRACE, "merged parent (id %d) error info: ·",
9d4fc5 ¤   ····parentr->lr_msgid, 0, 0 );
457622 ¤   Debug( LDAP_DEBUG_TRACE, "result errno %d, error <%s>, matched <%s>\n",
e760cc ¤   ····parentr->lr_res_errno, parentr->lr_res_error ?
566d36 ¤   ····parentr->lr_res_error : "", parentr->lr_res_matched ?
ae465d ¤   ····parentr->lr_res_matched : "" );
cbefe6 }
7d90e2 #endif /* LDAP_REFERRALS */
a9af5a
ebaf5a
04af5a
953fa8 #if defined(MACOS) || defined(PGPSOCKETSLDAP) /* jason */
afaf5a
3e8e21 #define SocketRefToSocketNumber(a)¤ ((int) a)
aaaf5a
dabeb7 static int
ee672a ldap_select1( LDAP *ld, struct timeval *timeout )
1bbb36 {
74eaa1 /*¤ (void) ld;
3f4f17 ¤   (void) timeout;
5967c5 ¤
--0608 00066a737e3401000af Page 10 of result.c
83ef00 ¤   return( tcpselect( ld->ld_sb.sb_sd, timeout ));
22af5a
62ea61 ¤   return( 0 );
187fe0 */
f5af5a
fafa88 ¤   PGPSocketSet¤   readSet;
6367c5 ¤
83871d ¤   PGPSOCKETSET_ZERO(&readSet);
599321 ¤   PGPSOCKETSET_SET(ld->ld_sb.sb_sd, &readSet);
ccaf5a
f562f5 ¤   return PGPSelect(SocketRefToSocketNumber(ld->ld_sb.sb_sd) + 1, &readSet,·
0f2cc4 ¤   ¤   ¤   ¤   ¤   ·0, 0, (PGPSocketsTimeValue *) timeout);
88af5a
44efe6 }
87af5a
c0db21 #else
9aa7b3 #if defined( CLDAP ) || !defined( LDAP_REFERRALS )
9f63da #if !defined( MACOS ) && !defined( DOS ) && !defined( _WIN32)
edbeb7 static int
78672a ldap_select1( LDAP *ld, struct timeval *timeout )
bebb36 {
57e5c6 ¤   fd_set¤ ¤   readfds;
4349d9 ¤   static int¤ tblsize;
dbaf5a
322a32 ¤   if ( tblsize == 0 ) {
9df375 #ifdef USE_SYSCONF
44ddf0 ¤   ¤   tblsize = sysconf( _SC_OPEN_MAX );
290949 #else /* USE_SYSCONF */
bef88a ¤   ¤   tblsize = getdtablesize();
3a7d11 #endif /* USE_SYSCONF */
ec9371 ¤   }
2baf5a
f76496 ¤   FD_ZERO( &readfds );
ab84e0 ¤   FD_SET( ld->ld_sb.sb_sd, &readfds );
a7af5a
9bff5a ¤   return( select( tblsize, &readfds, 0, 0, timeout ) );
52efe6 }
c4f2e5 #endif /* !MACOS */
cdaf5a
57af5a
905449 #if ( defined( DOS ) && defined( WINSOCK )) || defined( _WIN32 )
18beb7 static int
aa672a ldap_select1( LDAP *ld, struct timeval *timeout )
9ebb36 {
f14661 ····fd_set ·········readfds;
5b828a ····int ············rc;
c0af5a
1aca01 ····FD_ZERO( &readfds );
37280d ····FD_SET( ld->ld_sb.sb_sd, &readfds );
0eaf5a
dd9176 ····rc = select( 1, &readfds, 0, 0, timeout );
efaf5a
2fa358 ¤   if (rc == -1)
38c7a1 ¤   {
51d891 ¤   ¤   errno = WSAGetLastError();
199371 ¤   }
5a78be ····return( rc == SOCKET_ERROR ? -1 : rc );
a8efe6 }
f1e1e3 #endif /* WINSOCK || _WIN32 */
2baf5a
bdaf5a
5d01b0 #ifdef DOS
05b3f5 #ifdef PCNFS
90beb7 static int
8b672a ldap_select1( LDAP *ld, struct timeval *timeout )
d5bb36 {
2a9865 ¤   fd_set¤ readfds;
e04828 ¤   int¤res;
10af5a
476496 ¤   FD_ZERO( &readfds );
a184e0 ¤   FD_SET( ld->ld_sb.sb_sd, &readfds );
66af5a
--a10a 000de1fe012401000af Page 11 of result.c
8ed630 ¤   res = select( FD_SETSIZE, &readfds, NULL, NULL, timeout );
c5af5a
b984b0 ¤   if ( res == -1 && errno == EINTR) {
91ab06 ¤   ¤   /* We've been CTRL-C'ed at this point. ·It'd be nice to
f0f8a9 ¤   ¤   ···carry on but PC-NFS currently won't let us! */
ec136a ¤   ¤   printf("\n*** CTRL-C ***\n");
fd525f ¤   ¤   exit(-1);
099371 ¤   }
eef943 ¤   return( res );
1defe6 }
781b77 #endif /* PCNFS */
7caf5a
326382 #ifdef NCSA
45beb7 static int
20672a ldap_select1( LDAP *ld, struct timeval *timeout )
d0bb36 {
bfa5d0 ¤   int rc;
eac8a7 ¤   clock_t¤endtime;
09af5a
b2bd53 ¤   if ( timeout != NULL ) {
fab52b ¤   ¤   endtime = timeout->tv_sec * CLK_TCK +
88c701 ¤   ¤   ¤   timeout->tv_usec * CLK_TCK / 1000000 + clock();
519371 ¤   }
27af5a
1443ab ¤   do {
c1f872 ¤   ¤   Stask();
881788 ¤   ¤   rc = netqlen( ld->ld_sb.sb_sd );
de5d4b ¤   } while ( rc <= 0 && ( timeout == NULL || clock() < endtime ));
11af5a
27bfcd ¤   return( rc > 0 ? 1 : 0 );
35efe6 }
ef8682 #endif /* NCSA */
39bc39 #endif /* DOS */
d841c3 #endif /* !LDAP_REFERRALS */
27df0f #endif /* PGPSOCKETSLDAP */
9daf5a
9daf5a
f74d2f int
fedb64 ldap_msgfree( LDAPMessage *lm )
8bbb36 {
5eed68 ¤   LDAPMessage¤*next;
022c5e ¤   int¤¤   type = 0;
55af5a
1dbfa2 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_msgfree\n", 0, 0, 0 );
43af5a
b20f47 ¤   for ( ; lm != NULLMSG; lm = next ) {
e6fe53 ¤   ¤   next = lm->lm_chain;
3f4575 ¤   ¤   type = lm->lm_msgtype;
2cbe7d ¤   ¤   ber_free( lm->lm_ber, 1 );
62d820 ¤   ¤   free( (char *) lm );
d99371 ¤   }
6caf5a
da4be1 ¤   return( type );
01efe6 }
acaf5a
bb38e5 /*
b97ac2 ·* ldap_msgdelete - delete a message. ·It returns:
d69a71 ·*¤ 0¤  if the entire message was deleted
083596 ·*¤ -1¤ if the message was not found, or only part of it was found
fb495d ·*/
c64d2f int
866500 ldap_msgdelete( LDAP *ld, int msgid )
41bb36 {
b49152 ¤   LDAPMessage¤*lm, *prev;
56af5a
73c447 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_msgdelete\n", 0, 0, 0 );
57af5a
66bd82 ¤   prev = NULLMSG;
4df96b ¤   for ( lm = ld->ld_responses; lm != NULLMSG; lm = lm->lm_next ) {
bb0a75 ¤   ¤   if ( lm->lm_msgid == msgid )
2bcdcb ¤   ¤   ¤   break;
dea424 ¤   ¤   prev = lm;
--4cb8 000aff456a8401000af Page 12 of result.c
a19371 ¤   }
93af5a
949bac ¤   if ( lm == NULLMSG )
a349fa ¤   ¤   return( -1 );
b0af5a
b4ea76 ¤   if ( prev == NULLMSG )
5bfa59 ¤   ¤   ld->ld_responses = lm->lm_next;
070e24 ¤   else
6a934c ¤   ¤   prev->lm_next = lm->lm_next;
b3af5a
2cd70b ¤   if ( ldap_msgfree( lm ) == LDAP_RES_SEARCH_ENTRY )
3249fa ¤   ¤   return( -1 );
36af5a
41ea61 ¤   return( 0 );
a4efe6 }
9faf5a
17af5a
3838e5 /*
026173 ·* return 1 if message msgid is waiting to be abandoned, 0 otherwise
01495d ·*/
7ebeb7 static int
b62d38 ldap_abandoned( LDAP *ld, int msgid )
e5bb36 {
f71426 ¤   int¤i;
73af5a
f7c2c4 ¤   if ( ld->ld_abandoned == NULL )
21abea ¤   ¤   return( 0 );
37af5a
44d618 ¤   for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
218f49 ¤   ¤   if ( ld->ld_abandoned[i] == msgid )
77117f ¤   ¤   ¤   return( 1 );
7aaf5a
d4ea61 ¤   return( 0 );
54efe6 }
17af5a
8aaf5a
0cbeb7 static int
53186c ldap_mark_abandoned( LDAP *ld, int msgid )
7abb36 {
da1426 ¤   int¤i;
36af5a
b9c2c4 ¤   if ( ld->ld_abandoned == NULL )
8149fa ¤   ¤   return( -1 );
7faf5a
63d618 ¤   for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
ad8f49 ¤   ¤   if ( ld->ld_abandoned[i] == msgid )
49cdcb ¤   ¤   ¤   break;
f5af5a
58fa4c ¤   if ( ld->ld_abandoned[i] == -1 )
db49fa ¤   ¤   return( -1 );
63af5a
b23ac8 ¤   for ( ; ld->ld_abandoned[i] != -1; i++ ) {
424d45 ¤   ¤   ld->ld_abandoned[i] = ld->ld_abandoned[i + 1];
a49371 ¤   }
35af5a
48ea61 ¤   return( 0 );
e7efe6 }
34af5a
8eaf5a
b5ed07 #ifdef CLDAP
2f4d2f int
6b0dcb cldap_getmsg( LDAP *ld, struct timeval *timeout, BerElement *ber )
33bb36 {
4c8574 ¤   int¤¤   rc;
f0ef2c ¤   unsigned long¤  tag, len;
0daf5a
46dd3c ¤   if ( ld->ld_sb.sb_ber.ber_ptr >= ld->ld_sb.sb_ber.ber_end ) {
ca67f6 ¤   ¤   rc = ldap_select1( ld, timeout );
1e1cc1 ¤   ¤   if ( rc == -1 || rc == 0 ) {
799fd7 ¤   ¤   ¤   ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
f21623 ¤   ¤   ¤   ····LDAP_TIMEOUT);
af904d ¤   ¤   ¤   return( rc );
--e57d 00192990f29401000af Page 13 of result.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
b4af5a
bfdf09 ¤   /* get the next message */
92ba3a ¤   if ( (tag = ber_get_next( &ld->ld_sb, &len, ber ))
0fe8e3 ¤   ····!= LDAP_TAG_MESSAGE ) {
e9cc4d ¤   ¤   ld->ld_errno = (tag == LBER_DEFAULT ? LDAP_SERVER_DOWN :
22e472 ¤   ¤   ····LDAP_LOCAL_ERROR);
3349fa ¤   ¤   return( -1 );
1b9371 ¤   }
e6af5a
e42872 ¤   return( tag );
feefe6 }
926b1c #endif /* CLDAP */
--316f 000b045e6f8401000b0 Page 1 of sbind.c
bc38e5 /*
41bdac ·* ·Copyright (c) 1993 Regents of the University of Michigan.
c7e4d4 ·* ·All rights reserved.
d1775e ·*
11850e ·* ·sbind.c
6e495d ·*/
c0af5a
d30c68 #ifndef lint·
7b66c6 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University "
f13efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
ee7454 #endif
d7af5a
6efeb2 #include <stdio.h>
3f324c #include <string.h>
0caf5a
1d24c3 #if PGPSOCKETSLDAP¤ /* jason */
8d65aa #include "pgpSocketsLDAP.h"
6eaf5a
5adb21 #else
92c583 #ifdef MACOS
2b65e0 #include "macos.h"
4ae962 #endif /* MACOS */
a2af5a
cf1330 #if !defined( MACOS ) && !defined( DOS )
87f15e #include <sys/types.h>
b5a394 #ifndef WIN32¤  ¤   /* marcd */
6066f2 #include <sys/socket.h>
837454 #endif
377454 #endif
c8df0f #endif /* PGPSOCKETSLDAP */
f4af5a
56b779 #include "lber.h"
4ae990 #include "ldap.h"
2f745c #include "ldap-int.h"
b5af5a
45af5a
6838e5 /*
6fdc71 ·* ldap_simple_bind - bind to the ldap server (and X.500). ·The dn and
2a3b41 ·* password of the entry to which to bind are supplied. ·The message id
e484a2 ·* of the request initiated is returned.
9a775e ·*
f0305c ·* Example:
f04d7b ·*¤ ldap_simple_bind( ld, "cn=manager, o=university of michigan, c=us",
3cef58 ·*¤ ····"secret" )
fc495d ·*/
d5af5a
354d2f int
5ccb82 ldap_simple_bind( LDAP *ld, char *dn, char *passwd )
fdbb36 {
9c9c95 ¤   BerElement¤ *ber;
b4af5a
3ed8af ¤   /*
1cc5cb ¤   ·* The bind request looks like this:
678a87 ¤   ·*¤ BindRequest ::= SEQUENCE {
649904 ¤   ·*¤ ¤   version¤¤   INTEGER,
0d3656 ¤   ·*¤ ¤   name¤   ¤   DistinguishedName,¤ ·-- who
6f0e2e ¤   ·*¤ ¤   authentication¤ CHOICE {
1fd08e ¤   ·*¤ ¤   ¤   simple¤ ¤   [0] OCTET STRING -- passwd
683c91 ¤   ·*¤ ¤   }
325203 ¤   ·*¤ }
2a6bb5 ¤   ·* all wrapped up in an LDAPMessage sequence.
3ea4e3 ¤   ·*/
aaaf5a
3df4b1 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_simple_bind\n", 0, 0, 0 );
32af5a
47ab9d ¤   if ( dn == NULL )
3574f0 ¤   ¤   dn = "";
22f190 ¤   if ( passwd == NULL )
b2b42a ¤   ¤   passwd = "";
feaf5a
6f47d1 ¤   /* create a message to send */
b06826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
--c34e 001b5b7b28d401000b0 Page 2 of sbind.c
2649fa ¤   ¤   return( -1 );
c59371 ¤   }
4caf5a
c4aa04 ¤   /* fill it in */
368f0d ¤   if ( ber_printf( ber, "{it{ists}}", ++ld->ld_msgid, LDAP_REQ_BIND,
a829d5 ¤   ····ld->ld_version, dn, LDAP_AUTH_SIMPLE, passwd ) == -1 ) {
bb3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
3e1ab1 ¤   ¤   ber_free( ber, 1 );
e449fa ¤   ¤   return( -1 );
729371 ¤   }
47af5a
ee23e9 #ifndef NO_CACHE
1b5f25 ¤   if ( ld->ld_cache != NULL ) {
d829bb ¤   ¤   ldap_flush_cache( ld );
979371 ¤   }
9ce842 #endif /* !NO_CACHE */
5daf5a
06dd1f ¤   /* send the message */
b05bb9 ¤   return( send_initial_request( ld, LDAP_REQ_BIND, dn, ber ));
4fefe6 }
06af5a
e238e5 /*
031c94 ·* ldap_simple_bind - bind to the ldap server (and X.500) using simple
4e49a0 ·* authentication. ·The dn and password of the entry to which to bind are
d56a1c ·* supplied. ·LDAP_SUCCESS is returned upon success, the ldap error code
65e1d1 ·* otherwise.
97775e ·*
1c305c ·* Example:
7ab26e ·*¤ ldap_simple_bind_s( ld, "cn=manager, o=university of michigan, c=us",
a7ef58 ·*¤ ····"secret" )
81495d ·*/
2daf5a
694d2f int
4444b1 ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd )
31bb36 {
66da47 ¤   int¤¤   msgid;
893ea1 ¤   LDAPMessage¤*result;
2faf5a
64510e ¤   Debug( LDAP_DEBUG_TRACE, "ldap_simple_bind_s\n", 0, 0, 0 );
baaf5a
ed7524 ¤   if ( (msgid = ldap_simple_bind( ld, dn, passwd )) == -1 )
00df73 ¤   ¤   return( ld->ld_errno );
a0af5a
6c7a1f ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 )
1775f2 ¤   ¤   return( ld->ld_errno );¤/* ldap_result sets ld_errno */
feaf5a
a08819 ¤   return( ldap_result2error( ld, result, 1 ) );
b5efe6 }
--fc97 000148343e4401000b1 Page 1 of search.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
a051b2 ·* ·search.c
8f495d ·*/
7daf5a
b30c68 #ifndef lint·
2207d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
d13efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
bd7454 #endif
3caf5a
08feb2 #include <stdio.h>
6a324c #include <string.h>
f5b1cb #include <ctype.h>
28af5a
f224c3 #if PGPSOCKETSLDAP¤ /* jason */
e065aa #include "pgpSocketsLDAP.h"
38af5a
addb21 #else
5ec583 #ifdef MACOS
9bbea3 #include <stdlib.h>
7b65e0 #include "macos.h"
9ae962 #endif /* MACOS */
6caf5a
4a1157 #if defined( DOS )
89f2ef #include "msdos.h"
3abc39 #endif /* DOS */
31af5a
f66cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
285e84 #include <malloc.h>
257454 #endif
7faf5a
9b3faf #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
695d8c #include <sys/time.h>
73f15e #include <sys/types.h>
f166f2 #include <sys/socket.h>
d67454 #endif
cfdf0f #endif /* PGPSOCKETSLDAP */
5faf5a
b8b779 #include "lber.h"
f8e990 #include "ldap.h"
d7745c #include "ldap-int.h"
96af5a
29504c #ifdef NEEDPROTOS
496667 static char *find_right_paren( char *s );
f7267a static char *put_complex_filter( BerElement *ber, char *str,
bde05b ¤   unsigned long tag, int not );
0ece46 static int put_filter( BerElement *ber, char *str );
77c8e1 static int put_simple_filter( BerElement *ber, char *str );
51b60e static int put_substring_filter( BerElement *ber, char *type, char *str );
3d06b3 static int put_filter_list( BerElement *ber, char *str );
81db21 #else
964b9c static char *find_right_paren();
1bdae7 static char *put_complex_filter();
c84b4c static int put_filter();
cead13 static int put_simple_filter();
375dc3 static int put_substring_filter();
8d0017 static int put_filter_list();
378634 #endif /* NEEDPROTOS */
8eaf5a
6638e5 /*
fc017e ·* ldap_search - initiate an ldap (and X.500) search operation. ·Parameters:
18775e ·*
9e4f03 ·*¤ ld¤ ¤   LDAP descriptor
3ab514 ·*¤ base¤   ¤   DN of the base object
9440e8 ·*¤ scope¤  ¤   the search scope - one of LDAP_SCOPE_BASE,
16ac80 ·*¤ ¤   ¤   ····LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
93e44a ·*¤ filter¤ ¤   a string containing the search filter
f24958 ·*¤ ¤   ¤   (e.g., "(|(cn=bob)(sn=bob))")
78167c ·*¤ attrs¤  ¤   list of attribute types to return for matches
148340 ·*¤ attrsonly¤  1 => attributes only 0 => attributes and values
--e202 00014cdb692401000b1 Page 2 of search.c
4f775e ·*
66305c ·* Example:
71b49c ·*¤ char¤   *attrs[] = { "mail", "title", 0 };
ad6a36 ·*¤ msgid = ldap_search( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob",
d65c39 ·*¤ ····attrs, attrsonly );
30495d ·*/
5a4d2f int
6a33da ldap_search( LDAP *ld, char *base, int scope, char *filter,
a01d54 ¤   char **attrs, int attrsonly )
4dbb36 {
db9c95 ¤   BerElement¤ *ber;
8daf5a
81d250 ¤   Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
8faf5a
2c581e ¤   if (( ber = ldap_build_search_req( ld, base, scope, filter, attrs,
2d0d62 ¤   ····attrsonly )) == NULLBER ) {
9a49fa ¤   ¤   return( -1 );
4a9371 ¤   }
deaf5a
c323e9 #ifndef NO_CACHE
a55f25 ¤   if ( ld->ld_cache != NULL ) {
8c271c ¤   ¤   if ( check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
65b7ef ¤   ¤   ¤   ber_free( ber, 1 );
9741a5 ¤   ¤   ¤   ld->ld_errno = LDAP_SUCCESS;
65b4ad ¤   ¤   ¤   return( ld->ld_msgid );
590fe4 ¤   ¤   }
bec528 ¤   ¤   add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
719371 ¤   }
eb1992 #endif /* NO_CACHE */
ecaf5a
91dd1f ¤   /* send the message */
2711e1 ¤   return ( send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
43efe6 }
e4af5a
a6af5a
963ab9 BerElement *
cba935 ldap_build_search_req( LDAP *ld, char *base, int scope, char *filter,
db1d54 ¤   char **attrs, int attrsonly )
02bb36 {
6e9c95 ¤   BerElement¤ *ber;
67f4e8 ¤   int¤¤   err;
6aaf5a
c2d8af ¤   /*
ddcb2d ¤   ·* Create the search request. ·It looks like this:
8ff6ba ¤   ·*¤ SearchRequest := [APPLICATION 3] SEQUENCE {
8974e4 ¤   ·*¤ ¤   baseObject¤ DistinguishedName,
2eabbc ¤   ·*¤ ¤   scope¤  ¤   ENUMERATED {
900959 ¤   ·*¤ ¤   ¤   baseObject¤ (0),
95c099 ¤   ·*¤ ¤   ¤   singleLevel¤(1),
40bd05 ¤   ·*¤ ¤   ¤   wholeSubtree¤   (2)
e65d85 ¤   ·*¤ ¤   },
5b1ef8 ¤   ·*¤ ¤   derefAliases¤   ENUMERATED {
e0ab3b ¤   ·*¤ ¤   ¤   neverDerefaliases¤  (0),
a05dc9 ¤   ·*¤ ¤   ¤   derefInSearching¤   (1),
2cf7de ¤   ·*¤ ¤   ¤   derefFindingBaseObj¤(2),
cc24cd ¤   ·*¤ ¤   ¤   alwaysDerefAliases¤ (3)
535d85 ¤   ·*¤ ¤   },
450b66 ¤   ·*¤ ¤   sizelimit¤  INTEGER (0 .. 65535),
67b40c ¤   ·*¤ ¤   timelimit¤  INTEGER (0 .. 65535),
e193d2 ¤   ·*¤ ¤   attrsOnly¤  BOOLEAN,
65b684 ¤   ·*¤ ¤   filter¤ ¤   Filter,
bf286e ¤   ·*¤ ¤   attributes¤ SEQUENCE OF AttributeType
985203 ¤   ·*¤ }
50d005 ¤   ·* wrapped in an ldap message.
1aa4e3 ¤   ·*/
83af5a
ec47d1 ¤   /* create a message to send */
046826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
c75440 ¤   ¤   return( NULLBER );
8d9371 ¤   }
e7af5a
14ba23 ¤   if ( base == NULL ) {
--a1a5 000bc4ef175401000b1 Page 3 of search.c
8341ba ¤   ····base = "";
169371 ¤   }
9daf5a
17ed07 #ifdef CLDAP
55b542 ¤   if ( ld->ld_sb.sb_naddr > 0 ) {
2dd189 ¤   ····err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid,
b583cf ¤   ¤   ld->ld_cldapdn, LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
2bc4ad ¤   ¤   ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
76f037 ¤   } else {
806b1c #endif /* CLDAP */
768934 ¤   ¤   err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
7c5259 ¤   ¤   ····LDAP_REQ_SEARCH, base, scope, ld->ld_deref,
5328a9 ¤   ¤   ····ld->ld_sizelimit, ld->ld_timelimit, attrsonly );
65ed07 #ifdef CLDAP
119371 ¤   }
816b1c #endif /* CLDAP */
d9af5a
090d85 ¤   if ( err == -1 ) {
363614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
321ab1 ¤   ¤   ber_free( ber, 1 );
b75440 ¤   ¤   return( NULLBER );
789371 ¤   }
fdaf5a
f774b9 ¤   filter = strdup( filter );
6c7676 ¤   err = put_filter( ber, filter );
642206 ¤   free( filter );
6baf5a
38186c ¤   if ( err ·== -1 ) {
ab1062 ¤   ¤   ld->ld_errno = LDAP_FILTER_ERROR;
7d1ab1 ¤   ¤   ber_free( ber, 1 );
0c5440 ¤   ¤   return( NULLBER );
419371 ¤   }
d0af5a
4b31a7 ¤   if ( ber_printf( ber, "{v}}}", attrs ) == -1 ) {
7c3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
db1ab1 ¤   ¤   ber_free( ber, 1 );
f75440 ¤   ¤   return( NULLBER );
719371 ¤   }
ceaf5a
d747ce ¤   return( ber );
7eefe6 }
b3af5a
52083f static char *
42c79c find_right_paren( char *s )
8cbb36 {
c92ebb ¤   int¤balance, escape;
34af5a
cac9ea ¤   balance = 1;
9d960d ¤   escape = 0;
e6b84d ¤   while ( *s && balance ) {
34c240 ¤   ¤   if ( escape == 0 ) {
fb0879 ¤   ¤   ¤   if ( *s == '(' )
45ba9a ¤   ¤   ¤   ¤   balance++;
6ba790 ¤   ¤   ¤   else if ( *s == ')' )
a727d9 ¤   ¤   ¤   ¤   balance--;
3c0fe4 ¤   ¤   }
2eecb6 ¤   ¤   if ( *s == '\\' && ! escape )
802156 ¤   ¤   ¤   escape = 1;
c90e1d ¤   ¤   else
587b8a ¤   ¤   ¤   escape = 0;
f30f33 ¤   ¤   if ( balance )
ab7904 ¤   ¤   ¤   s++;
5b9371 ¤   }
21af5a
e92492 ¤   return( *s ? s : NULL );
17efe6 }
f8af5a
67083f static char *
cd6997 put_complex_filter( BerElement *ber, char *str, unsigned long tag, int not )
85bb36 {
288c06 ¤   char¤   *next;
bcaf5a
--7e8a 00036c7f76d401000b1 Page 4 of search.c
7274d4 ¤   (void) not;
fd67c5 ¤
0ad8af ¤   /*
00e310 ¤   ·* We have (x(filter)...) with str sitting on
3db8f3 ¤   ·* the x. ·We have to find the paren matching
90802d ¤   ·* the one before the x and put the intervening
e7b5f5 ¤   ·* filters by calling put_filter_list().
b1a4e3 ¤   ·*/
bcaf5a
3d5d82 ¤   /* put explicit tag */
7f12c9 ¤   if ( ber_printf( ber, "t{", tag ) == -1 )
3def86 ¤   ¤   return( NULL );
1238e5 /*
124476 ¤   if ( !not && ber_printf( ber, "{" ) == -1 )
8aef86 ¤   ¤   return( NULL );
537fe0 */
68af5a
c734c7 ¤   str++;
99f8ae ¤   if ( (next = find_right_paren( str )) == NULL )
25ef86 ¤   ¤   return( NULL );
74af5a
4a33c9 ¤   *next = '\0';
c110e4 ¤   if ( put_filter_list( ber, str ) == -1 )
deef86 ¤   ¤   return( NULL );
debf96 ¤   *next++ = ')';
b9af5a
ffefc3 ¤   /* flush explicit tagged thang */
89127b ¤   if ( ber_printf( ber, "}" ) == -1 )
aaef86 ¤   ¤   return( NULL );
4d38e5 /*
4f5998 ¤   if ( !not && ber_printf( ber, "}" ) == -1 )
e7ef86 ¤   ¤   return( NULL );
2b7fe0 */
a8af5a
abac45 ¤   return( next );
dbefe6 }
0daf5a
bcbeb7 static int
c2d30b put_filter( BerElement *ber, char *str )
eebb36 {
d25ed3 ¤   char¤   *next, *tmp, *s, *d;
a7c5c5 ¤   int¤parens, balance, escape, gotescape;
3baf5a
97d8af ¤   /*
c4b28b ¤   ·* A Filter looks like this:
f67b55 ¤   ·* ·····Filter ::= CHOICE {
5a5901 ¤   ·* ·············and ············[0] ····SET OF Filter,
6e6717 ¤   ·* ·············or ·············[1] ····SET OF Filter,
d84a62 ¤   ·* ·············not ············[2] ····Filter,
b17fde ¤   ·* ·············equalityMatch ··[3] ····AttributeValueAssertion,
6a36cb ¤   ·* ·············substrings ·····[4] ····SubstringFilter,
254bed ¤   ·* ·············greaterOrEqual ·[5] ····AttributeValueAssertion,
964ffe ¤   ·* ·············lessOrEqual ····[6] ····AttributeValueAssertion,
6990e6 ¤   ·* ·············present ········[7] ····AttributeType,,
991aee ¤   ·* ·············approxMatch ····[8] ····AttributeValueAssertion
22e9f7 ¤   ·* ·····}
109714 ¤   ·*
2caa40 ¤   ·* ·····SubstringFilter ::= SEQUENCE {
7ef080 ¤   ·* ·············type ··············AttributeType,
b67371 ¤   ·* ·············SEQUENCE OF CHOICE {
0a47d8 ¤   ·* ·····················initial ·········[0] IA5String,
1357e9 ¤   ·* ·····················any ·············[1] IA5String,
f00595 ¤   ·* ·····················final ···········[2] IA5String
c8fdba ¤   ·* ·············}
b7e9f7 ¤   ·* ·····}
f6c72e ¤   ·* Note: tags in a choice are always explicit
16a4e3 ¤   ·*/
6aaf5a
161edd ¤   Debug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 );
22af5a
84a9f4 ¤   gotescape = parens = 0;
36a353 ¤   while ( *str ) {
--1359 000901085f9401000b1 Page 5 of search.c
2873c0 ¤   ¤   switch ( *str ) {
727e68 ¤   ¤   case '(':
90b7de ¤   ¤   ¤   str++;
3e99c1 ¤   ¤   ¤   parens++;
c4fa94 ¤   ¤   ¤   switch ( *str ) {
16eab0 ¤   ¤   ¤   case '&':
47f6fd ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
4f3b6c ¤   ¤   ¤   ¤   ····0, 0, 0 );
cdaf5a
2c8bbe ¤   ¤   ¤   ¤   if ( (str = put_complex_filter( ber, str,
a2c3f5 ¤   ¤   ¤   ¤   ····LDAP_FILTER_AND, 0 )) == NULL )
bf3013 ¤   ¤   ¤   ¤   ¤   return( -1 );
ebaf5a
fec337 ¤   ¤   ¤   ¤   parens--;
09f622 ¤   ¤   ¤   ¤   break;
90af5a
e2e308 ¤   ¤   ¤   case '|':
0d699b ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
dd3b6c ¤   ¤   ¤   ¤   ····0, 0, 0 );
cbaf5a
7c8bbe ¤   ¤   ¤   ¤   if ( (str = put_complex_filter( ber, str,
8f9f33 ¤   ¤   ¤   ¤   ····LDAP_FILTER_OR, 0 )) == NULL )
123013 ¤   ¤   ¤   ¤   ¤   return( -1 );
c5af5a
80c337 ¤   ¤   ¤   ¤   parens--;
67f622 ¤   ¤   ¤   ¤   break;
0faf5a
aebd91 ¤   ¤   ¤   case '!':
2a9a2a ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
d13b6c ¤   ¤   ¤   ¤   ····0, 0, 0 );
13af5a
108bbe ¤   ¤   ¤   ¤   if ( (str = put_complex_filter( ber, str,
2f284f ¤   ¤   ¤   ¤   ····LDAP_FILTER_NOT, 1 )) == NULL )
593013 ¤   ¤   ¤   ¤   ¤   return( -1 );
ffaf5a
82c337 ¤   ¤   ¤   ¤   parens--;
e5f622 ¤   ¤   ¤   ¤   break;
9faf5a
ccdb68 ¤   ¤   ¤   default:
8a07a8 ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
8e3b6c ¤   ¤   ¤   ¤   ····0, 0, 0 );
f8af5a
100ded ¤   ¤   ¤   ¤   balance = 1;
e58def ¤   ¤   ¤   ¤   escape = 0;
09e045 ¤   ¤   ¤   ¤   next = str;
b3b661 ¤   ¤   ¤   ¤   while ( *next && balance ) {
3f4193 ¤   ¤   ¤   ¤   ¤   if ( escape == 0 ) {
8c78bd ¤   ¤   ¤   ¤   ¤   ¤   if ( *next == '(' )
4f633e ¤   ¤   ¤   ¤   ¤   ¤   ¤   balance++;
96dcc9 ¤   ¤   ¤   ¤   ¤   ¤   else if ( *next == ')' )
26fe7d ¤   ¤   ¤   ¤   ¤   ¤   ¤   balance--;
791c89 ¤   ¤   ¤   ¤   ¤   }
0e6524 ¤   ¤   ¤   ¤   ¤   if ( *next == '\\' && ! escape )
4e8894 ¤   ¤   ¤   ¤   ¤   ¤   gotescape = escape = 1;
164bd6 ¤   ¤   ¤   ¤   ¤   else
0dab4d ¤   ¤   ¤   ¤   ¤   ¤   escape = 0;
c97585 ¤   ¤   ¤   ¤   ¤   if ( balance )
506617 ¤   ¤   ¤   ¤   ¤   ¤   next++;
112613 ¤   ¤   ¤   ¤   }
b32c82 ¤   ¤   ¤   ¤   if ( balance != 0 )
963013 ¤   ¤   ¤   ¤   ¤   return( -1 );
53af5a
ab47b2 ¤   ¤   ¤   ¤   *next = '\0';
25b705 ¤   ¤   ¤   ¤   tmp = strdup( str );
58d5eb ¤   ¤   ¤   ¤   if ( gotescape ) {
2b20b1 ¤   ¤   ¤   ¤   ¤   escape = 0;
b649da ¤   ¤   ¤   ¤   ¤   for ( s = d = tmp; *s; s++ ) {
450b3a ¤   ¤   ¤   ¤   ¤   ¤   if ( *s != '\\' || escape ) {
214481 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *d++ = *s;
336e18 ¤   ¤   ¤   ¤   ¤   ¤   ¤   escape = 0;
143af7 ¤   ¤   ¤   ¤   ¤   ¤   } else {
9034c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   escape = 1;
--3b9d 000357ab897401000b1 Page 6 of search.c
0ddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
fc1c89 ¤   ¤   ¤   ¤   ¤   }
2590f9 ¤   ¤   ¤   ¤   ¤   *d = '\0';
7b2613 ¤   ¤   ¤   ¤   }
c56472 ¤   ¤   ¤   ¤   if ( put_simple_filter( ber, tmp ) == -1 ) {
5c25d0 ¤   ¤   ¤   ¤   ¤   free( tmp );
aa3013 ¤   ¤   ¤   ¤   ¤   return( -1 );
c12613 ¤   ¤   ¤   ¤   }
d19e86 ¤   ¤   ¤   ¤   free( tmp );
9a72b6 ¤   ¤   ¤   ¤   *next++ = ')';
a3c396 ¤   ¤   ¤   ¤   str = next;
87c337 ¤   ¤   ¤   ¤   parens--;
4af622 ¤   ¤   ¤   ¤   break;
b7a3a6 ¤   ¤   ¤   }
87cdcb ¤   ¤   ¤   break;
32af5a
a862d3 ¤   ¤   case ')':
6fd2ab ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0,
ce1bc4 ¤   ¤   ¤   ····0 );
2837ed ¤   ¤   ¤   if ( ber_printf( ber, "]" ) == -1 )
63071b ¤   ¤   ¤   ¤   return( -1 );
dcb7de ¤   ¤   ¤   str++;
5b0482 ¤   ¤   ¤   parens--;
30cdcb ¤   ¤   ¤   break;
12af5a
129bb0 ¤   ¤   case ' ':
a0b7de ¤   ¤   ¤   str++;
eccdcb ¤   ¤   ¤   break;
8caf5a
f7c55c ¤   ¤   default:¤   /* assume it's a simple type=value filter */
f49415 ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0,
941bc4 ¤   ¤   ¤   ····0 );
1b5358 ¤   ¤   ¤   next = strchr( str, '\0' );
418a6d ¤   ¤   ¤   tmp = strdup( str );
74bd3b ¤   ¤   ¤   if ( strchr( tmp, '\\' ) != NULL ) {
6e8def ¤   ¤   ¤   ¤   escape = 0;
eb9168 ¤   ¤   ¤   ¤   for ( s = d = tmp; *s; s++ ) {
45a53b ¤   ¤   ¤   ¤   ¤   if ( *s != '\\' || escape ) {
920572 ¤   ¤   ¤   ¤   ¤   ¤   *d++ = *s;
bcab4d ¤   ¤   ¤   ¤   ¤   ¤   escape = 0;
6681a1 ¤   ¤   ¤   ¤   ¤   } else {
f6f191 ¤   ¤   ¤   ¤   ¤   ¤   escape = 1;
661c89 ¤   ¤   ¤   ¤   ¤   }
752613 ¤   ¤   ¤   ¤   }
2c84d1 ¤   ¤   ¤   ¤   *d = '\0';
7ba3a6 ¤   ¤   ¤   }
a142c7 ¤   ¤   ¤   if ( put_simple_filter( ber, tmp ) == -1 ) {
859e86 ¤   ¤   ¤   ¤   free( tmp );
95071b ¤   ¤   ¤   ¤   return( -1 );
69a3a6 ¤   ¤   ¤   }
71aadb ¤   ¤   ¤   free( tmp );
3335f3 ¤   ¤   ¤   str = next;
2ecdcb ¤   ¤   ¤   break;
7b0fe4 ¤   ¤   }
059371 ¤   }
98af5a
172947 ¤   return( parens ? -1 : 0 );
60efe6 }
fcaf5a
0638e5 /*
9c2be7 ·* Put a list of filters like this "(filter1)(filter2)..."
14495d ·*/
78af5a
c3beb7 static int
d5f1c0 put_filter_list( BerElement *ber, char *str )
9ebb36 {
398c06 ¤   char¤   *next;
7838ce ¤   char¤   save;
9caf5a
8475e1 ¤   Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 );
a3af5a
35a353 ¤   while ( *str ) {
--3567 000e2e77d76401000b1 Page 7 of search.c
93a921 ¤   ¤   while ( *str && isspace( *str ) )
4eb7de ¤   ¤   ¤   str++;
e315cd ¤   ¤   if ( *str == '\0' )
96cdcb ¤   ¤   ¤   break;
55af5a
3ce627 ¤   ¤   if ( (next = find_right_paren( str + 1 )) == NULL )
128e4f ¤   ¤   ¤   return( -1 );
81425e ¤   ¤   save = *++next;
7aaf5a
fbe587 ¤   ¤   /* now we have "(filter)" with str pointing to it */
d60953 ¤   ¤   *next = '\0';
ab3a1b ¤   ¤   if ( put_filter( ber, str ) == -1 )
288e4f ¤   ¤   ¤   return( -1 );
321fd8 ¤   ¤   *next = save;
3baf5a
ca4f07 ¤   ¤   str = next;
b79371 ¤   }
1faf5a
34ea61 ¤   return( 0 );
bcefe6 }
19af5a
2dbeb7 static int
fb3796 put_simple_filter( BerElement *ber, char *str )
7bbb36 {
025da6 ¤   char¤   ¤   *s;
f022a6 ¤   char¤   ¤   *value, savechar;
9e4dab ¤   unsigned long¤  ftype;
b38574 ¤   int¤¤   rc;
4eaf5a
ce394c ¤   Debug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 );
2eaf5a
a851a4 ¤   if ( (s = strchr( str, '=' )) == NULL )
2849fa ¤   ¤   return( -1 );
ec3cc2 ¤   value = s + 1;
c8a2b6 ¤   *s-- = '\0';
a01132 ¤   savechar = *s;
c6af5a
d00ff4 ¤   switch ( *s ) {
4f4a90 ¤   case '<':
549147 ¤   ¤   ftype = LDAP_FILTER_LE;
f64b7e ¤   ¤   *s = '\0';
7f2f68 ¤   ¤   break;
c473e6 ¤   case '>':
ad5152 ¤   ¤   ftype = LDAP_FILTER_GE;
f54b7e ¤   ¤   *s = '\0';
542f68 ¤   ¤   break;
236551 ¤   case '~':
65f46d ¤   ¤   ftype = LDAP_FILTER_APPROX;
024b7e ¤   ¤   *s = '\0';
e62f68 ¤   ¤   break;
662f72 ¤   default:
fba99c ¤   ¤   if ( strchr( value, '*' ) == NULL ) {
0f267c ¤   ¤   ¤   ftype = LDAP_FILTER_EQUALITY;
3dc84c ¤   ¤   } else if ( strcmp( value, "*" ) == 0 ) {
8fce84 ¤   ¤   ¤   ftype = LDAP_FILTER_PRESENT;
dd45a6 ¤   ¤   } else {
d3f20d ¤   ¤   ¤   rc = put_substring_filter( ber, str, value );
6fade7 ¤   ¤   ¤   *(value-1) = '=';
b9904d ¤   ¤   ¤   return( rc );
fb0fe4 ¤   ¤   }
9f2f68 ¤   ¤   break;
a39371 ¤   }
9faf5a
d375ae ¤   if ( ftype == LDAP_FILTER_PRESENT ) {
e31c2e ¤   ¤   rc = ber_printf( ber, "ts", ftype, str );
50f037 ¤   } else {
83dd83 ¤   ¤   rc = ber_printf( ber, "t{ss}", ftype, str, value );
519371 ¤   }
ffaf5a
c9c564 ¤   *s = savechar;
93e306 ¤   *(value-1) = '=';
e2b550 ¤   return( rc == -1 ? rc : 0 );
--0fc6 0005a2248ed401000b1 Page 8 of search.c
7aefe6 }
46af5a
88beb7 static int
fc43a0 put_substring_filter( BerElement *ber, char *type, char *val )
bcbb36 {
fd7ac3 ¤   char¤   ¤   *nextstar, gotstar = 0;
ce4dab ¤   unsigned long¤  ftype;
5eaf5a
7750e4 ¤   Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type,
079f13 ¤   ····val, 0 );
eeaf5a
85a4af ¤   if ( ber_printf( ber, "t{s{", LDAP_FILTER_SUBSTRINGS, type ) == -1 )
c749fa ¤   ¤   return( -1 );
c0af5a
d09433 ¤   while ( val != NULL ) {
4e29ae ¤   ¤   if ( (nextstar = strchr( val, '*' )) != NULL )
91cd49 ¤   ¤   ¤   *nextstar++ = '\0';
d4af5a
bcb36e ¤   ¤   if ( gotstar == 0 ) {
a1f136 ¤   ¤   ¤   ftype = LDAP_SUBSTRING_INITIAL;
2283fc ¤   ¤   } else if ( nextstar == NULL ) {
697752 ¤   ¤   ¤   ftype = LDAP_SUBSTRING_FINAL;
5645a6 ¤   ¤   } else {
5ae502 ¤   ¤   ¤   ftype = LDAP_SUBSTRING_ANY;
6b0fe4 ¤   ¤   }
f0bf17 ¤   ¤   if ( *val != '\0' ) {
185e41 ¤   ¤   ¤   if ( ber_printf( ber, "ts", ftype, val ) == -1 )
50071b ¤   ¤   ¤   ¤   return( -1 );
000fe4 ¤   ¤   }
edaf5a
1cb3b0 ¤   ¤   gotstar = 1;
79ce23 ¤   ¤   if ( nextstar != NULL )
126b39 ¤   ¤   ¤   *(nextstar-1) = '*';
5d52e1 ¤   ¤   val = nextstar;
589371 ¤   }
d0af5a
981508 ¤   if ( ber_printf( ber, "}}" ) == -1 )
ca49fa ¤   ¤   return( -1 );
48af5a
c1ea61 ¤   return( 0 );
c1efe6 }
acaf5a
a34d2f int
690919 ldap_search_st( LDAP *ld, char *base, int scope, char *filter, char **attrs,
64c9f2 ¤   int attrsonly, struct timeval *timeout, LDAPMessage **res )
95bb36 {
6c48fe ¤   int¤msgid;
d6af5a
fe0cc4 ¤   if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
72aa18 ¤   ····== -1 )
55df73 ¤   ¤   return( ld->ld_errno );
ccaf5a
bc3c28 ¤   if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
6fdf73 ¤   ¤   return( ld->ld_errno );
f8af5a
1c79b4 ¤   if ( ld->ld_errno == LDAP_TIMEOUT ) {
bbcc12 ¤   ¤   (void) ldap_abandon( ld, msgid );
49d85c ¤   ¤   ld->ld_errno = LDAP_TIMEOUT;
54df73 ¤   ¤   return( ld->ld_errno );
e69371 ¤   }
9faf5a
117887 ¤   return( ldap_result2error( ld, *res, 0 ) );
1defe6 }
a7af5a
374d2f int
74fd36 ldap_search_s( LDAP *ld, char *base, int scope, char *filter, char **attrs,
7dd52d ¤   int attrsonly, LDAPMessage **res )
49bb36 {
b248fe ¤   int¤msgid;
41af5a
c50cc4 ¤   if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
5aaa18 ¤   ····== -1 )
--cd2d 001568c79f7401000b1 Page 9 of search.c
23df73 ¤   ¤   return( ld->ld_errno );
e3af5a
71cc2d ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
33df73 ¤   ¤   return( ld->ld_errno );
1daf5a
bf7887 ¤   return( ldap_result2error( ld, *res, 0 ) );
3fefe6 }
56af5a
--8e4b 00007211c18401000b2 Page 1 of sort.c
bc38e5 /*
979eee ·* Copyright (c) 1994 Regents of the University of Michigan.
aa599a ·* All rights reserved.
f0775e ·*
88b855 ·* Redistribution and use in source and binary forms are permitted
cc9795 ·* provided that this notice is preserved and that due credit is given
e01873 ·* to the University of Michigan at Ann Arbor. The name of the University
4e8805 ·* may not be used to endorse or promote products derived from this
a874fe ·* software without specific prior written permission. This software
112a32 ·* is provided ``as is'' without express or implied warranty.
53775e ·*
32592d ·* sort.c: ·LDAP library entry and value sort routines
33495d ·*/
87af5a
f2feb2 #include <stdio.h>
5db1cb #include <ctype.h>
c1324c #include <string.h>
31bea3 #include <stdlib.h>
f3af5a
ba24c3 #if PGPSOCKETSLDAP¤ /* jason */
0265aa #include "pgpSocketsLDAP.h"
cdaf5a
cadb21 #else
89c583 #ifdef MACOS
2265e0 #include "macos.h"
446c94 #else /* MACOS */
28af69 #if defined(DOS) || defined(WIN32)
3d5e84 #include <malloc.h>
de01b0 #ifdef DOS
d0f2ef #include "msdos.h"
377454 #endif
80bc39 #endif /* DOS */
07e962 #endif /* MACOS */
09df0f #endif /* PGPSOCKETSLDAP */
e6af5a
f6b779 #include "lber.h"
c6e990 #include "ldap.h"
67af5a
f893ce struct entrything {
baf497 ¤   char¤   ¤   **et_vals;
a29296 ¤   LDAPMessage¤*et_msg;
1582f7 };
c0af5a
7f719a #ifndef NEEDPROTOS
1466d5 static int¤ (*et_cmp_fn)();
400aee static int¤ et_cmp();
b74b51 #else /* !NEEDPROTOS */
13f8f9 static int¤ (*et_cmp_fn)(const void *a, const void *b);
241635 static int¤ et_cmp( void *aa, void *bb);
493f09 #endif /* !NEEDPROTOS */
29af5a
624d2f int
027807 ldap_sort_strcasecmp(
2e5eb1 ····const char¤ **a,
b63aca ····const char¤ **b
d45b71 )
dcbb36 {
a902b6 ¤   return( strcasecmp( (char *) *a, (char *) *b ) );
05efe6 }
3aaf5a
23beb7 static int
7d2bd7 et_cmp(
5bd43a ¤   void¤   *aa,
9a26c0 ¤   void¤   *bb
5b5b71 )
40bb36 {
9512a8 ¤   int¤¤   ¤   i, rc;
05aee5 ¤   struct entrything¤  *a = (struct entrything *)aa;
64670e ¤   struct entrything¤  *b = (struct entrything *)bb;
d9af5a
d5fc9f ¤   if ( a->et_vals == NULL && b->et_vals == NULL )
07abea ¤   ¤   return( 0 );
--4221 000a2cbd6f3401000b2 Page 2 of sort.c
647d43 ¤   if ( a->et_vals == NULL )
1149fa ¤   ¤   return( -1 );
0724f7 ¤   if ( b->et_vals == NULL )
7ba0ae ¤   ¤   return( 1 );
76af5a
7b70a7 ¤   for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
a460d2 ¤   ¤   if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] ))
aa8903 ¤   ¤   ····!= 0 ) {
b2904d ¤   ¤   ¤   return( rc );
f10fe4 ¤   ¤   }
7f9371 ¤   }
8daf5a
7fd567 ¤   if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL )
3babea ¤   ¤   return( 0 );
381faa ¤   if ( a->et_vals[i] == NULL )
8a49fa ¤   ¤   return( -1 );
78e125 ¤   return( 1 );
a9efe6 }
0aaf5a
c34d2f int
58f1cb ldap_sort_entries(
87db55 ····LDAP¤   *ld,
2c6d2a ····LDAPMessage¤**chain,
67703e ····char¤   *attr,¤ ¤   /* NULL => sort by DN */
a6a8c0 ····int¤¤   (*cmp)(const void *a, const void *b)
d85b71 )
51bb36 {
bd21a7 ¤   int¤¤   ¤   i, count;
5465ec ¤   struct entrything¤  *et;
3f5b63 ¤   LDAPMessage¤¤   *e, *last;
474a34 ¤   LDAPMessage¤¤   **ep;
08af5a
85ec39 ¤   count = ldap_count_entries( ld, *chain );
a1af5a
53f005 ¤   if ( (et = (struct entrything *) malloc( count *
7947ba ¤   ····sizeof(struct entrything) )) == NULL ) {
5a6f1c ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
8c49fa ¤   ¤   return( -1 );
f89371 ¤   }
a3af5a
1e60d2 ¤   e = *chain;
813009 ¤   for ( i = 0; i < count; i++ ) {
4b2f1d ¤   ¤   et[i].et_msg = e;
d1520b ¤   ¤   if ( attr == NULL ) {
469512 ¤   ¤   ¤   char¤   *dn;
5faf5a
d43d7c ¤   ¤   ¤   dn = ldap_get_dn( ld, e );
1e5d0b ¤   ¤   ¤   et[i].et_vals = ldap_explode_dn( dn, 1 );
21390a ¤   ¤   ¤   free( dn );
af45a6 ¤   ¤   } else {
8c543b ¤   ¤   ¤   et[i].et_vals = ldap_get_values( ld, e, attr );
cf0fe4 ¤   ¤   }
85af5a
cb2374 ¤   ¤   e = e->lm_chain;
1b9371 ¤   }
fecb3b ¤   last = e;
62af5a
a46c04 ¤   et_cmp_fn = cmp;
98225a ¤   qsort( et, count, sizeof(struct entrything), (void *) et_cmp );
11af5a
f02fc7 ¤   ep = chain;
d43009 ¤   for ( i = 0; i < count; i++ ) {
e1aff8 ¤   ¤   *ep = et[i].et_msg;
740783 ¤   ¤   ep = &(*ep)->lm_chain;
dfaf5a
01e3db ¤   ¤   ldap_value_free( et[i].et_vals );
da9371 ¤   }
d38cbc ¤   *ep = last;
012c2a ¤   free( (char *) et );
79af5a
1bea61 ¤   return( 0 );
a2efe6 }
--2b7c 0018ae3290c401000b2 Page 3 of sort.c
e0af5a
e54d2f int
111ec3 ldap_sort_values(
15db55 ····LDAP¤   *ld,
40776c ····char¤   **vals,
d0a8c0 ····int¤¤   (*cmp)(const void *a, const void *b)
ac5b71 )
87bb36 {
fe440a ¤   int¤nel;
07af5a
849e79 ¤   (void) ld;
7267c5 ¤
a38ecc ¤   for ( nel = 0; vals[nel] != NULL; nel++ )
ffc78a ¤   ¤   ;¤  /* NULL */
a9af5a
770497 ¤   qsort( vals, nel, sizeof(char *), cmp );
c9af5a
33ea61 ¤   return( 0 );
8aefe6 }
--2a78 000ad315f3d401000b3 Page 1 of srchpref.c
bc38e5 /*
09515b ·* Copyright (c) 1993, 1994 Regents of the University of Michigan.
60599a ·* All rights reserved.
44775e ·*
22b855 ·* Redistribution and use in source and binary forms are permitted
ec9795 ·* provided that this notice is preserved and that due credit is given
bf1873 ·* to the University of Michigan at Ann Arbor. The name of the University
148805 ·* may not be used to endorse or promote products derived from this
b974fe ·* software without specific prior written permission. This software
1a2a32 ·* is provided ``as is'' without express or implied warranty.
a0775e ·*
732da0 ·* searchpref.c: ·search preferences library routines for LDAP clients
a4dae3 ·* 17 May 1994 by Gordon Good
d3495d ·*/
49af5a
b6feb2 #include <stdio.h>
a5b1cb #include <ctype.h>
27324c #include <string.h>
31bea3 #include <stdlib.h>
24c583 #ifdef MACOS
6865e0 #include "macos.h"
ce6c94 #else /* MACOS */
ccaf69 #if defined(DOS) || defined(WIN32)
be5e84 #include <malloc.h>
9a01b0 #ifdef DOS
2af2ef #include "msdos.h"
f37454 #endif
4caad8 #else /* DOS */
b6f15e #include <sys/types.h>
cf09b0 #include <sys/file.h>
4dea1a #ifndef VMS
a417c2 #include <unistd.h>
b9361d #endif /* VMS */
febc39 #endif /* DOS */
7be962 #endif /* MACOS */
bbaf5a
55b779 #include "lber.h"
cce990 #include "ldap.h"
7a7d20 #include "srchpref.h"
09af5a
2b719a #ifndef NEEDPROTOS
ff9e1d int next_line_tokens();
9940f5 void free_strarray();
e6a68e static void free_searchobj();
a7e0bf static int read_next_searchobj();
824b51 #else /* !NEEDPROTOS */
ebec27 int next_line_tokens( char **bufp, long *blenp, char ***toksp );
c5d559 void free_strarray( char **sap );
4db627 static void free_searchobj( struct ldap_searchobj *so );
7ac436 static int read_next_searchobj( char **bufp, long *blenp,
148919 ¤   struct ldap_searchobj **sop, int soversion );
8f3f09 #endif /* !NEEDPROTOS */
21af5a
07af5a
1b24b5 static char¤¤   *sobjoptions[] = {
cb41b8 ····"internal",
6a2e82 ····NULL
8d82f7 };
e9af5a
d9af5a
2aa334 static unsigned long¤   sobjoptvals[] = {
b96563 ····LDAP_SEARCHOBJ_OPT_INTERNAL,
4a82f7 };
6baf5a
b1af5a
d24d2f int
9b40b9 ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp )
d4bb36 {
ea6cec ····FILE¤   *fp;
911842 ····char¤   *buf;
99e29b ····long¤   rlen, len;
ada824 ····int¤¤   rc, eof;
--2235 00016e32b99401000b3 Page 2 of srchpref.c
e0af5a
ce4bfd ····if (( fp = fopen( file, "r" )) == NULL ) {
cf84b2 ¤   return( LDAP_SEARCHPREF_ERR_FILE );
d16fe7 ····}
22af5a
f7ba4a ····if ( fseek( fp, 0L, SEEK_END ) != 0 ) {¤/* move to end to get len */
8b5261 ¤   fclose( fp );
e084b2 ¤   return( LDAP_SEARCHPREF_ERR_FILE );
6b6fe7 ····}
09af5a
0d7c74 ····len = ftell( fp );
16af5a
ab8486 ····if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {¤/* back to start of file */
575261 ¤   fclose( fp );
0784b2 ¤   return( LDAP_SEARCHPREF_ERR_FILE );
4e6fe7 ····}
caaf5a
33d046 ····if (( buf = malloc( (size_t)len )) == NULL ) {
4e5261 ¤   fclose( fp );
bc1b3e ¤   return( LDAP_SEARCHPREF_ERR_MEM );
1b6fe7 ····}
5daf5a
6ed0ba ····rlen = fread( buf, 1, (size_t)len, fp );
b57a1f ····eof = feof( fp );
aac09a ····fclose( fp );
eaaf5a
2870f9 ····if ( rlen != len && !eof ) {¤   /* error: ·didn't get the whole file */
8a5bb5 ¤   free( buf );
7c84b2 ¤   return( LDAP_SEARCHPREF_ERR_FILE );
db6fe7 ····}
51af5a
bb6eec ····rc = ldap_init_searchprefs_buf( buf, rlen, solistp );
831943 ····free( buf );
53af5a
51ff99 ····return( rc );
8aefe6 }
88af5a
a1af5a
d54d2f int
ce78c2 ldap_init_searchprefs_buf( char *buf, long buflen,
7a94ad ¤   struct ldap_searchobj **solistp )
26bb36 {
6bb6b5 ····int¤¤   ¤   ¤   rc, version;
e4feb1 ····char¤   ¤   ¤   **toks;
e84a7f ····struct ldap_searchobj¤  *prevso, *so;
f0af5a
f757af ····*solistp = prevso = NULLSEARCHOBJ;
a9af5a
4cf06e ····if ( next_line_tokens( &buf, &buflen, &toks ) != 2 ||
e2904c ¤   ····strcasecmp( toks[ 0 ], "version" ) != 0 ) {
4bb597 ¤   free_strarray( toks );
07d46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
db6fe7 ····}
d9b741 ····version = atoi( toks[ 1 ] );
3aadb6 ····free_strarray( toks );
214ac7 ····if ( version != LDAP_SEARCHPREF_VERSION &&
67397a ¤   ····version != LDAP_SEARCHPREF_VERSION_ZERO ) {
3266f6 ¤   return( LDAP_SEARCHPREF_ERR_VERSION );
236fe7 ····}
c0af5a
fab3b8 ····while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so,
f0a7bf ¤   ····version )) == 0 && so != NULLSEARCHOBJ ) {
bfb0e2 ¤   if ( prevso == NULLSEARCHOBJ ) {
cdc78e ¤   ····*solistp = so;
79f037 ¤   } else {
996d53 ¤   ····prevso->so_next = so;
3d9371 ¤   }
71d733 ¤   prevso = so;
196fe7 ····}
efaf5a
e2ce64 ····if ( rc != 0 ) {
161ca7 ¤   ldap_free_searchprefs( *solistp );
--3f18 0007a67986e401000b3 Page 3 of srchpref.c
9f6fe7 ····}
86af5a
9fff99 ····return( rc );
10efe6 }
15da86 ¤   ····
49af5a
32af5a
3a314a void
b46fe3 ldap_free_searchprefs( struct ldap_searchobj *solist )
f3bb36 {
a3cdf9 ····struct ldap_searchobj¤  *so, *nextso;
7baf5a
d5bdaf ····if ( solist != NULL ) {
893f16 ¤   for ( so = solist; so != NULL; so = nextso ) {
ab5c93 ¤   ····nextso = so->so_next;
f24886 ¤   ····free_searchobj( so );
d19371 ¤   }
246fe7 ····}
048b5f ····/* XXX XXX need to do some work here */
c2efe6 }
49af5a
aaaf5a
952978 static void
b1db35 free_searchobj( struct ldap_searchobj *so )
68bb36 {
3f8a1b ····if ( so != NULL ) {
aee996 ¤   if ( so->so_objtypeprompt != NULL ) {
3f145b ¤   ····free( ·so->so_objtypeprompt );
699371 ¤   }
c5cd19 ¤   if ( so->so_prompt != NULL ) {
d52be7 ¤   ····free( ·so->so_prompt );
089371 ¤   }
7462e6 ¤   if ( so->so_filterprefix != NULL ) {
d2b694 ¤   ····free( ·so->so_filterprefix );
b19371 ¤   }
f26299 ¤   if ( so->so_filtertag != NULL ) {
c269e3 ¤   ····free( ·so->so_filtertag );
0a9371 ¤   }
8ae091 ¤   if ( so->so_defaultselectattr != NULL ) {
b58d6a ¤   ····free( ·so->so_defaultselectattr );
d79371 ¤   }
d9e07d ¤   if ( so->so_defaultselecttext != NULL ) {
586103 ¤   ····free( ·so->so_defaultselecttext );
dc9371 ¤   }
f24769 ¤   if ( so->so_salist != NULL ) {
b3bd08 ¤   ····struct ldap_searchattr *sa, *nextsa;
58c1cf ¤   ····for ( sa = so->so_salist; sa != NULL; sa = nextsa ) {
79617d ¤   ¤   nextsa = sa->sa_next;
5f007b ¤   ¤   if ( sa->sa_attrlabel != NULL ) {
96fb76 ¤   ¤   ····free( sa->sa_attrlabel );
100fe4 ¤   ¤   }
0bd45a ¤   ¤   if ( sa->sa_attr != NULL ) {
876650 ¤   ¤   ····free( sa->sa_attr );
100fe4 ¤   ¤   }
80f7b1 ¤   ¤   if ( sa->sa_selectattr != NULL ) {
b4e553 ¤   ¤   ····free( sa->sa_selectattr );
9f0fe4 ¤   ¤   }
e9f75d ¤   ¤   if ( sa->sa_selecttext != NULL ) {
d0093a ¤   ¤   ····free( sa->sa_selecttext );
350fe4 ¤   ¤   }
0b7763 ¤   ¤   free( sa );
a1f372 ¤   ····}
669371 ¤   }
5b4389 ¤   if ( so->so_smlist != NULL ) {
70919f ¤   ····struct ldap_searchmatch *sm, *nextsm;
14388b ¤   ····for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) {
a295c1 ¤   ¤   nextsm = sm->sm_next;
b1378d ¤   ¤   if ( sm->sm_matchprompt != NULL ) {
7a4c71 ¤   ¤   ····free( sm->sm_matchprompt );
c30fe4 ¤   ¤   }
876ee7 ¤   ¤   if ( sm->sm_filter != NULL ) {
7a8c22 ¤   ¤   ····free( sm->sm_filter );
--ca41 00056ff205c401000b3 Page 4 of srchpref.c
b50fe4 ¤   ¤   }
1f0053 ¤   ¤   free( sm );
28f372 ¤   ····}
259371 ¤   }
ef81a8 ¤   free( so );
606fe7 ····}
d2efe6 }
8caf5a
72af5a
a7af5a
e1c25e struct ldap_searchobj *
8c2a74 ldap_first_searchobj( struct ldap_searchobj *solist )
4abb36 {
6f9e26 ····return( solist );
51efe6 }
4eaf5a
8baf5a
74c25e struct ldap_searchobj *
86020d ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so )
8cbb36 {
0aa15a ····return( so == NULLSEARCHOBJ ? so : so->so_next );
04efe6 }
cfaf5a
cbaf5a
b8af5a
23beb7 static int
a6e8b9 read_next_searchobj( char **bufp, long *blenp, struct ldap_searchobj **sop,
d79832 ¤   int soversion )
fcbb36 {
63d757 ····int¤¤   ¤   ¤   i, j, tokcnt;
98feb1 ····char¤   ¤   ¤   **toks;
b7bb66 ····struct ldap_searchobj¤  *so;
81f818 ····struct ldap_searchattr¤ **sa;
bee6d3 ····struct ldap_searchmatch¤**sm;
a3af5a
92e2e0 ····*sop = NULL;
61af5a
3e29ec ····/*
3f15bc ·····* Object type prompt comes first
b3d48d ·····*/
a683ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
c9b597 ¤   free_strarray( toks );
52987c ¤   return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX );
6b6fe7 ····}
27af5a
609e0a ····if (( so = (struct ldap_searchobj *)calloc( 1,
268744 ¤   ····sizeof( struct ldap_searchobj ))) == NULL ) {
e2b597 ¤   free_strarray( toks );
3019dd ¤   return( ·LDAP_SEARCHPREF_ERR_MEM );
1c6fe7 ····}
35b6d4 ····so->so_objtypeprompt = toks[ 0 ];
e77115 ····free( (char *)toks );
a7af5a
dd29ec ····/*
2c46cb ·····* if this is post-version zero, options come next
63d48d ·····*/
08ddbb ····if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) {
6126f0 ¤   if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) < 1 ) {
afb99e ¤   ····free_strarray( toks );
cc5319 ¤   ····ldap_free_searchprefs( so );
6ad1e8 ¤   ····return( LDAP_SEARCHPREF_ERR_SYNTAX );
f99371 ¤   }
86d1a4 ¤   for ( i = 0; toks[ i ] != NULL; ++i ) {
f8b7cc ¤   ····for ( j = 0; sobjoptions[ j ] != NULL; ++j ) {
5141a0 ¤   ¤   if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) {
0e55a1 ¤   ¤   ····so->so_options |= sobjoptvals[ j ];
440fe4 ¤   ¤   }
24f372 ¤   ····}
a39371 ¤   }
8eb597 ¤   free_strarray( toks );
4c6fe7 ····}
56af5a
--899b 000aaf67e0a401000b3 Page 5 of srchpref.c
7c29ec ····/*
8483ce ·····* "Fewer choices" prompt is next
70d48d ·····*/
6e83ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
95b597 ¤   free_strarray( toks );
db015a ¤   ldap_free_searchprefs( so );
d0d46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
766fe7 ····}
58d742 ····so->so_prompt = toks[ 0 ];
967115 ····free( (char *)toks );
e7af5a
3529ec ····/*
6fe317 ·····* Filter prefix for "More Choices" searching is next
a7d48d ·····*/
db83ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
a4b597 ¤   free_strarray( toks );
3f015a ¤   ldap_free_searchprefs( so );
b9d46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
196fe7 ····}
1b09c5 ····so->so_filterprefix = toks[ 0 ];
9c7115 ····free( (char *)toks );
11af5a
5a29ec ····/*
850e85 ·····* "Fewer Choices" filter tag comes next
6cd48d ·····*/
2183ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
22b597 ¤   free_strarray( toks );
44015a ¤   ldap_free_searchprefs( so );
6bd46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
256fe7 ····}
6f6989 ····so->so_filtertag = toks[ 0 ];
fb7115 ····free( (char *)toks );
36af5a
1d29ec ····/*
e2ba65 ·····* Selection (disambiguation) attribute comes next
b1d48d ·····*/
f983ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
f1b597 ¤   free_strarray( toks );
59015a ¤   ldap_free_searchprefs( so );
d3d46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
356fe7 ····}
5fdeb4 ····so->so_defaultselectattr = toks[ 0 ];
527115 ····free( (char *)toks );
f1af5a
6529ec ····/*
5d9ac6 ·····* Label for selection (disambiguation) attribute
dad48d ·····*/
5683ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
eeb597 ¤   free_strarray( toks );
80015a ¤   ldap_free_searchprefs( so );
70d46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
d76fe7 ····}
2df3d6 ····so->so_defaultselecttext = toks[ 0 ];
b17115 ····free( (char *)toks );
08af5a
5a29ec ····/*
b62ade ·····* Search scope is next
d9d48d ·····*/
4483ad ····if (( tokcnt = next_line_tokens( bufp, blenp, &toks )) != 1 ) {
3db597 ¤   free_strarray( toks );
f7015a ¤   ldap_free_searchprefs( so );
27d46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
ef6fe7 ····}
4a4a26 ····if ( !strcasecmp(toks[ 0 ], "subtree" )) {
eb9360 ¤   so->so_defaultscope = LDAP_SCOPE_SUBTREE;
9db08f ····} else if ( !strcasecmp(toks[ 0 ], "onelevel" )) {
173210 ¤   so->so_defaultscope = LDAP_SCOPE_ONELEVEL;
1a43b8 ····} else if ( !strcasecmp(toks[ 0 ], "base" )) {
039e99 ¤   so->so_defaultscope = LDAP_SCOPE_BASE;
e46a79 ····} else {
5e015a ¤   ldap_free_searchprefs( so );
aad46a ¤   return( LDAP_SEARCHPREF_ERR_SYNTAX );
--1db2 001f8f37c8f401000b3 Page 6 of srchpref.c
9f6fe7 ····}
87adb6 ····free_strarray( toks );
28af5a
e7af5a
1129ec ····/*
f2cc81 ·····* "More Choices" search option list comes next
3ed48d ·····*/
db439e ····sa = &( so->so_salist );
4f5767 ····while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
fa9b74 ¤   if ( tokcnt < 5 ) {
6bb99e ¤   ····free_strarray( toks );
b95319 ¤   ····ldap_free_searchprefs( so );
8bd1e8 ¤   ····return( LDAP_SEARCHPREF_ERR_SYNTAX );
b39371 ¤   }
29a681 ¤   if (( *sa = ( struct ldap_searchattr * ) calloc( 1,
7e6743 ¤   ¤   sizeof( struct ldap_searchattr ))) == NULL ) {
b8b99e ¤   ····free_strarray( toks );
425319 ¤   ····ldap_free_searchprefs( so );
d33e82 ¤   ····return( ·LDAP_SEARCHPREF_ERR_MEM );
4b9371 ¤   }
6e6a28 ¤   ( *sa )->sa_attrlabel = toks[ 0 ];
98c73f ¤   ( *sa )->sa_attr = toks[ 1 ];
2d2b02 ¤   ( *sa )->sa_selectattr = toks[ 3 ];
5736bc ¤   ( *sa )->sa_selecttext = toks[ 4 ];
b85ccc ¤   /* Deal with bitmap */
e4bee2 ¤   ( *sa )->sa_matchtypebitmap = 0;
8448ca ¤   for ( i = strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) {
36a4ed ¤   ····if ( toks[ 2 ][ i ] == '1' ) {
bc7838 ¤   ¤   ( *sa )->sa_matchtypebitmap |= (1 << j);
73f372 ¤   ····}
639371 ¤   }
421e32 ¤   free( toks[ 2 ] );
0b1b55 ¤   free( ( char * ) toks );
6ed222 ¤   sa = &(( *sa )->sa_next);
cc6fe7 ····}
77ce2b ····*sa = NULL;
4faf5a
a929ec ····/*
8370c9 ·····* Match types are last
3ed48d ·····*/
52acb2 ····sm = &( so->so_smlist );
e95767 ····while (( tokcnt = next_line_tokens( bufp, blenp, &toks )) > 0 ) {
6787a5 ¤   if ( tokcnt < 2 ) {
13b99e ¤   ····free_strarray( toks );
565319 ¤   ····ldap_free_searchprefs( so );
30d1e8 ¤   ····return( LDAP_SEARCHPREF_ERR_SYNTAX );
5d9371 ¤   }
b291a1 ¤   if (( *sm = ( struct ldap_searchmatch * ) calloc( 1,
047d1e ¤   ¤   sizeof( struct ldap_searchmatch ))) == NULL ) {
2eb99e ¤   ····free_strarray( toks );
955319 ¤   ····ldap_free_searchprefs( so );
153e82 ¤   ····return( ·LDAP_SEARCHPREF_ERR_MEM );
309371 ¤   }
4bf4ed ¤   ( *sm )->sm_matchprompt = toks[ 0 ];
a07379 ¤   ( *sm )->sm_filter = toks[ 1 ];
de1b55 ¤   free( ( char * ) toks );
0d1d2a ¤   sm = &(( *sm )->sm_next );
606fe7 ····}
e0179e ····*sm = NULL;
f9af5a
5b1bac ····*sop = so;
b6a897 ····return( 0 );
f8efe6 }
--be92 000733406de401000b4 Page 1 of test.c
56feb2 #include <stdio.h>
46b1cb #include <ctype.h>
92324c #include <string.h>
06c583 #ifdef MACOS
3fbea3 #include <stdlib.h>
f7fc7e #ifdef THINK_C
beb6ac #include <console.h>
b494b4 #include <unix.h>
4437bc #include <fcntl.h>
e349cc #endif /* THINK_C */
1465e0 #include "macos.h"
f26c94 #else /* MACOS */
9dfdef #if defined( DOS ) || defined( _WIN32 )
1d01b0 #ifdef DOS
85f2ef #include "msdos.h"
157454 #endif
5af830 #if defined( WINSOCK ) || defined( _WIN32 )
089264 #include "console.h"
e7d50d #endif /* WINSOCK */
64aad8 #else /* DOS */
99f15e #include <sys/types.h>
5866f2 #include <sys/socket.h>
d15d8c #include <sys/time.h>
20d4f4 #include <sys/stat.h>
2609b0 #include <sys/file.h>
dbea1a #ifndef VMS
4937bc #include <fcntl.h>
8017c2 #include <unistd.h>
0e361d #endif /* VMS */
d6bc39 #endif /* DOS */
1be962 #endif /* MACOS */
a3af5a
43b779 #include "lber.h"
76e990 #include "ldap.h"
c1af5a
39c381 #if !defined( PCNFS ) && !defined( WINSOCK ) && !defined( MACOS )
b3ed31 #define MOD_USE_BVALS
9b7be4 #endif /* !PCNFS && !WINSOCK && !MACOS */
c8af5a
79504c #ifdef NEEDPROTOS
2f8860 static void handle_result( LDAP *ld, LDAPMessage *lm );
c9ad8a static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s );
cb7341 static void print_search_entry( LDAP *ld, LDAPMessage *res );
24464b static void free_list( char **list );
76db21 #else
a1c779 static void handle_result();
88dc00 static void print_ldap_result();
4f9ecc static void print_search_entry();
3e2cbb static void free_list();
e48634 #endif /* NEEDPROTOS */
52af5a
b3e6cb #define NOCACHEERRMSG \
af3600 ¤   ¤   "don't compile with -DNO_CACHE if you desire local caching"
02af5a
01bbfe char *dnsuffix;
b1af5a
f598bc #ifndef WINSOCK
e6083f static char *
2c2ddc getline( char *line, int len, FILE *fp, char *prompt )
8ebb36 {
9cd0ff ¤   printf(prompt);
06af5a
2866a5 ¤   if ( fgets( line, len, fp ) == NULL )
86ef86 ¤   ¤   return( NULL );
88af5a
13e256 ¤   line[ strlen( line ) - 1 ] = '\0';
f1af5a
73f3fe ¤   return( line );
f1efe6 }
1cd50d #endif /* WINSOCK */
bdaf5a
734515 static char **
--6cc4 000381bff22401000b4 Page 2 of test.c
768376 get_list( char *prompt )
4dbb36 {
0fb8c3 ¤   static char¤buf[256];
d32b77 ¤   int¤¤   num;
5e248f ¤   char¤   ¤   **result;
ebaf5a
fd860c ¤   num = 0;
e32832 ¤   result = (char **) 0;
5f0361 ¤   while ( 1 ) {
8a1de0 ¤   ¤   getline( buf, sizeof(buf), stdin, prompt );
beaf5a
91a8f3 ¤   ¤   if ( *buf == '\0' )
00cdcb ¤   ¤   ¤   break;
04af5a
83da14 ¤   ¤   if ( result == (char **) 0 )
cf6002 ¤   ¤   ¤   result = (char **) malloc( sizeof(char *) );
6b0e1d ¤   ¤   else
4364f3 ¤   ¤   ¤   result = (char **) realloc( result,
37ccf0 ¤   ¤   ¤   ····sizeof(char *) * (num + 1) );
deaf5a
8e4920 ¤   ¤   result[num++] = (char *) strdup( buf );
3e9371 ¤   }
e1e77c ¤   if ( result == (char **) 0 )
55ef86 ¤   ¤   return( NULL );
ed4d09 ¤   result = (char **) realloc( result, sizeof(char *) * (num + 1) );
76e5de ¤   result[num] = NULL;
9caf5a
fa4c6e ¤   return( result );
b0efe6 }
ebaf5a
7daf5a
bf2978 static void
45b87e free_list( char **list )
ddbb36 {
fc1426 ¤   int¤i;
55af5a
82b8c2 ¤   if ( list != NULL ) {
b61424 ¤   ¤   for ( i = 0; list[ i ] != NULL; ++i ) {
bb95d9 ¤   ¤   ¤   free( list[ i ] );
1a0fe4 ¤   ¤   }
8e65e4 ¤   ¤   free( (char *)list );
349371 ¤   }
70efe6 }
84af5a
13af5a
53d209 #ifdef MOD_USE_BVALS
39beb7 static int
be541f file_read( char *path, struct berval *bv )
7fbb36 {
79b950 ¤   FILE¤   ¤   *fp;
c678e7 ¤   long¤   ¤   rlen;
fc5a32 ¤   int¤¤   eof;
efaf5a
4e39cf ¤   if (( fp = fopen( path, "r" )) == NULL ) {
fa1dfa ¤   ····¤   perror( path );
2849fa ¤   ¤   return( -1 );
ef9371 ¤   }
2eaf5a
1cbe5a ¤   if ( fseek( fp, 0L, SEEK_END ) != 0 ) {
202e84 ¤   ¤   perror( path );
ce68fb ¤   ¤   fclose( fp );
9249fa ¤   ¤   return( -1 );
499371 ¤   }
6eaf5a
2281cf ¤   bv->bv_len = ftell( fp );
4faf5a
d328ee ¤   if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) {
99e8a4 ¤   ¤   perror( "malloc" );
fc68fb ¤   ¤   fclose( fp );
0049fa ¤   ¤   return( -1 );
c39371 ¤   }
38af5a
--1278 000bcd5e9c8401000b4 Page 3 of test.c
ab92de ¤   if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
db2e84 ¤   ¤   perror( path );
ae68fb ¤   ¤   fclose( fp );
2f49fa ¤   ¤   return( -1 );
139371 ¤   }
2baf5a
e0328b ¤   rlen = fread( bv->bv_val, 1, bv->bv_len, fp );
dcf1e0 ¤   eof = feof( fp );
6a5261 ¤   fclose( fp );
3faf5a
3e45a6 ¤   if ( rlen != bv->bv_len ) {
a72e84 ¤   ¤   perror( path );
522804 ¤   ¤   free( bv->bv_val );
b449fa ¤   ¤   return( -1 );
d09371 ¤   }
48af5a
e3da2f ¤   return( bv->bv_len );
24efe6 }
c45765 #endif /* MOD_USE_BVALS */
f4af5a
48af5a
a72b35 static LDAPMod **
e6bb05 get_modlist( char *prompt1, char *prompt2, char *prompt3 )
e4bb36 {
1fb8c3 ¤   static char¤buf[256];
e42b77 ¤   int¤¤   num;
bc3792 ¤   LDAPMod¤¤   tmp;
bd0270 ¤   LDAPMod¤¤   **result;
acd209 #ifdef MOD_USE_BVALS
c23ca0 ¤   struct berval¤  **bvals;
0f5765 #endif /* MOD_USE_BVALS */
14af5a
d6860c ¤   num = 0;
fa20da ¤   result = NULL;
140361 ¤   while ( 1 ) {
614af0 ¤   ¤   if ( prompt1 ) {
06fe4a ¤   ¤   ¤   getline( buf, sizeof(buf), stdin, prompt1 );
6cad63 ¤   ¤   ¤   tmp.mod_op = atoi( buf );
b4af5a
1a66f5 ¤   ¤   ¤   if ( tmp.mod_op == -1 || buf[0] == '\0' )
08f622 ¤   ¤   ¤   ¤   break;
3c0fe4 ¤   ¤   }
9baf5a
058cb5 ¤   ¤   getline( buf, sizeof(buf), stdin, prompt2 );
666044 ¤   ¤   if ( buf[0] == '\0' )
edcdcb ¤   ¤   ¤   break;
b67240 ¤   ¤   tmp.mod_type = strdup( buf );
a5af5a
a3c6eb ¤   ¤   tmp.mod_values = get_list( prompt3 );
55d209 #ifdef MOD_USE_BVALS
fcb859 ¤   ¤   if ( tmp.mod_values != NULL ) {
76973f ¤   ¤   ¤   int¤i;
26af5a
f781dd ¤   ¤   ¤   for ( i = 0; tmp.mod_values[i] != NULL; ++i )
2e34a5 ¤   ¤   ¤   ¤   ;
a78e31 ¤   ¤   ¤   bvals = (struct berval **)calloc( i + 1,
d79fb2 ¤   ¤   ¤   ····sizeof( struct berval *));
d9b1b5 ¤   ¤   ¤   for ( i = 0; tmp.mod_values[i] != NULL; ++i ) {
348051 ¤   ¤   ¤   ¤   bvals[i] = (struct berval *)malloc(
95f902 ¤   ¤   ¤   ¤   ····sizeof( struct berval ));
29306c ¤   ¤   ¤   ¤   if ( strncmp( tmp.mod_values[i], "{FILE}",
29aec9 ¤   ¤   ¤   ¤   ····6 ) == 0 ) {
5551e9 ¤   ¤   ¤   ¤   ¤   if ( file_read( tmp.mod_values[i] + 6,
d638ee ¤   ¤   ¤   ¤   ¤   ····bvals[i] ) < 0 ) {
93fa14 ¤   ¤   ¤   ¤   ¤   ¤   return( NULL );
ad1c89 ¤   ¤   ¤   ¤   ¤   }
35b5fc ¤   ¤   ¤   ¤   } else {
deb3d4 ¤   ¤   ¤   ¤   ¤   bvals[i]->bv_val = tmp.mod_values[i];
026b58 ¤   ¤   ¤   ¤   ¤   bvals[i]->bv_len =
5b9c74 ¤   ¤   ¤   ¤   ¤   ····strlen( tmp.mod_values[i] );
902613 ¤   ¤   ¤   ¤   }
bca3a6 ¤   ¤   ¤   }
--95b3 000060457ed401000b4 Page 4 of test.c
388802 ¤   ¤   ¤   tmp.mod_bvalues = bvals;
8457ef ¤   ¤   ¤   tmp.mod_op |= LDAP_MOD_BVALUES;
720fe4 ¤   ¤   }
7d5765 #endif /* MOD_USE_BVALS */
d7af5a
3b1242 ¤   ¤   if ( result == NULL )
5ee62e ¤   ¤   ¤   result = (LDAPMod **) malloc( sizeof(LDAPMod *) );
610e1d ¤   ¤   else
74bf14 ¤   ¤   ¤   result = (LDAPMod **) realloc( result,
cf653a ¤   ¤   ¤   ····sizeof(LDAPMod *) * (num + 1) );
cdaf5a
b32d51 ¤   ¤   result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) );
809619 ¤   ¤   *(result[num]) = tmp;¤  /* struct copy */
71146c ¤   ¤   num++;
0c9371 ¤   }
6c9b16 ¤   if ( result == NULL )
c9ef86 ¤   ¤   return( NULL );
d815a2 ¤   result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) );
84e5de ¤   result[num] = NULL;
70af5a
224c6e ¤   return( result );
a7efe6 }
d6af5a
8caf5a
877f8d #ifdef LDAP_REFERRALS
544d2f int
f1990b bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp,
90e709 ¤   int freeit )
d2bb36 {
41d1e8 ¤   static char¤dn[256], passwd[256];
35af5a
d40a1f ¤   if ( !freeit ) {
b85ffa #ifdef KERBEROS
32867b ¤   ¤   getline( dn, sizeof(dn), stdin, "re-bind method (0->simple, "
1c9724 ¤   ¤   ¤   "1->krbv41, 2->krbv42, 3->krbv41&2)? " );
aa9b4e ¤   ¤   if (( *authmethodp = atoi( dn )) == 3 ) {
fcfe29 ¤   ¤   ¤   *authmethodp = LDAP_AUTH_KRBV4;
5345a6 ¤   ¤   } else {
bb750d ¤   ¤   ¤   *authmethodp |= 0x80;
d10fe4 ¤   ¤   }
ee3104 #else /* KERBEROS */
2c2665 ¤   ¤   *authmethodp = LDAP_AUTH_SIMPLE;
1c999d #endif /* KERBEROS */
f1af5a
3cbdc8 ¤   ¤   getline( dn, sizeof(dn), stdin, "re-bind dn? " );
ace2aa ¤   ¤   strcat( dn, dnsuffix );
cc8bac ¤   ¤   *dnp = dn;
d0af5a
29cebb ¤   ¤   if ( *authmethodp == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) {
8d0e2a ¤   ¤   ¤   getline( passwd, sizeof(passwd), stdin,
b3cdb2 ¤   ¤   ¤   ····"re-bind password? " );
f045a6 ¤   ¤   } else {
66017d ¤   ¤   ¤   passwd[0] = '\0';
070fe4 ¤   ¤   }
459f71 ¤   ¤   *passwdp = passwd;
899371 ¤   }
2baf5a
6aaced ¤   return( LDAP_SUCCESS );
21efe6 }
ac90e2 #endif /* LDAP_REFERRALS */
39af5a
91af5a
e14d2f int
90a184 #ifdef WINSOCK
2c66d7 ldapmain(
832e70 #else /* WINSOCK */
272fe1 main(
4dd50d #endif /* WINSOCK */
4565e1 ¤   int argc, char **argv )
4ebb36 {
fabfbf ¤   LDAP¤   ¤   *ld;
068806 ¤   int¤¤   i, c, port, cldapflg, errflg, method, id, msgtype;
--c7aa 00053373211401000b4 Page 5 of test.c
62d983 ¤   char¤   ¤   line[256], command1, command2, command3;
4a84bc ¤   char¤   ¤   passwd[64], dn[256], rdn[64], attr[64], value[256];
3a79dc ¤   char¤   ¤   filter[256], *host, **types;
b8df7b ¤   char¤   ¤   **exdn;
17ddbf ¤   char¤   ¤   *usage = "usage: %s [-u] [-h host] [-d level] "
22b240 ¤   ¤   ¤   ¤   "[-s dnsuffix] [-p port] [-t file] [-T file]\n";
1238a1 ¤   int¤¤   bound, all, scope, attrsonly;
7f3932 ¤   LDAPMessage¤*res;
2a904a ¤   LDAPMod¤¤   **mods, **attrs;
293be8 ¤   struct timeval¤ timeout;
fa8fc1 ¤   char¤   ¤   *copyfname = NULL;
b74300 ¤   int¤¤   copyoptions = 0;
a568dc ¤   LDAPURLDesc¤*ludp;
afaf5a
00f036 ¤   extern char¤*optarg;
20d511 ¤   extern int¤ optind;
22af5a
a8c583 #ifdef MACOS
7b0a63 ¤   if (( argv = get_list( "cmd line arg?" )) == NULL ) {
2c5691 ¤   ¤   exit( 1 );
a39371 ¤   }
2b9369 ¤   for ( argc = 0; argv[ argc ] != NULL; ++argc ) {
241d52 ¤   ¤   ;
8e9371 ¤   }
7ee962 #endif /* MACOS */
2faf5a
71f179 ¤   host = NULL;
1c68b8 ¤   port = LDAP_PORT;
0d35f5 ¤   dnsuffix = "";
867d4b ¤   cldapflg = errflg = 0;
ffaf5a
6bfb98 ¤   while (( c = getopt( argc, argv, "uh:d:s:p:t:T:" )) != -1 ) {
bf511a ¤   ¤   switch( c ) {
b520f1 ¤   ¤   case 'u':
1ced07 #ifdef CLDAP
ee1b1c ¤   ¤   ¤   cldapflg++;
6aeeea #else /* CLDAP */
5816ad ¤   ¤   ¤   printf( "Compile with -DCLDAP for UDP support\n" );
fe6b1c #endif /* CLDAP */
94cdcb ¤   ¤   ¤   break;
5caf5a
33ffeb ¤   ¤   case 'd':
c22639 #ifdef LDAP_DEBUG
130cee ¤   ¤   ¤   ldap_debug = atoi( optarg );
3d93dd ¤   ¤   ¤   if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
80b72b ¤   ¤   ¤   ¤   lber_debug = ldap_debug;
43a3a6 ¤   ¤   ¤   }
8fdb21 #else
8cbc7a ¤   ¤   ¤   printf( "Compile with -DLDAP_DEBUG for debugging\n" );
867454 #endif
edcdcb ¤   ¤   ¤   break;
b0af5a
2168df ¤   ¤   case 'h':
fdae66 ¤   ¤   ¤   host = optarg;
f1cdcb ¤   ¤   ¤   break;
70af5a
9a6b6b ¤   ¤   case 's':
7604d2 ¤   ¤   ¤   dnsuffix = optarg;
6bcdcb ¤   ¤   ¤   break;
a9af5a
dd4ea6 ¤   ¤   case 'p':
26f115 ¤   ¤   ¤   port = atoi( optarg );
15cdcb ¤   ¤   ¤   break;
7daf5a
f6f4f6 #if !defined(MACOS) && !defined(DOS)
c3b446 ¤   ¤   case 't':¤  /* copy ber's to given file */
1a7fac ¤   ¤   ¤   copyfname = strdup( optarg );
6210e0 ¤   ¤   ¤   copyoptions = LBER_TO_FILE;
bbcdcb ¤   ¤   ¤   break;
c6af5a
0c3ee3 ¤   ¤   case 'T':¤  /* only output ber's to given file */
537fac ¤   ¤   ¤   copyfname = strdup( optarg );
--fd0b 000d1e47c68401000b4 Page 6 of test.c
177c9f ¤   ¤   ¤   copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY);
f5cdcb ¤   ¤   ¤   break;
857454 #endif
46af5a
909ae3 ¤   ¤   default:
0b18af ¤   ¤   ····++errflg;
050fe4 ¤   ¤   }
eb9371 ¤   }
68af5a
b97108 ¤   if ( host == NULL && optind == argc - 1 ) {
8a7d5c ¤   ¤   host = argv[ optind ];
e03ca9 ¤   ¤   ++optind;
e99371 ¤   }
deaf5a
58b2a0 ¤   if ( errflg || optind < argc - 1 ) {
9351d4 ¤   ¤   fprintf( stderr, usage, argv[ 0 ] );
ef5691 ¤   ¤   exit( 1 );
a89371 ¤   }
e067c5 ¤
f2d138 ¤   printf( "%sldap_open( %s, %d )\n", cldapflg ? "c" : "",
6feb46 ¤   ¤   host == NULL ? "(null)" : host, port );
c3af5a
10b191 ¤   if ( cldapflg ) {
22ed07 #ifdef CLDAP
7d23cb ¤   ¤   ld = cldap_open( host, port );
906b1c #endif /* CLDAP */
aef037 ¤   } else {
01e412 ¤   ¤   ld = ldap_open( host, port );
d39371 ¤   }
daaf5a
3c3a4e ¤   if ( ld == NULL ) {
cac94e ¤   ¤   perror( "ldap_open" );
ba4bb3 ¤   ¤   exit(1);
349371 ¤   }
efaf5a
cbf4f6 #if !defined(MACOS) && !defined(DOS)
874c5c ¤   if ( copyfname != NULL ) {
e2d8e3 ¤   ¤   if ( (ld->ld_sb.sb_fd = open( copyfname, O_WRONLY | O_CREAT,
a4d2fb ¤   ¤   ····0600 )) ·== -1 ) {
01159e ¤   ¤   ¤   perror( copyfname );
f33c03 ¤   ¤   ¤   exit ( 1 );
e90fe4 ¤   ¤   }
6e2f48 ¤   ¤   ld->ld_sb.sb_options = copyoptions;
909371 ¤   }
df7454 #endif
51af5a
dbd844 ¤   bound = 0;
906a93 ¤   timeout.tv_sec = 0;
6d3284 ¤   timeout.tv_usec = 0;
9daf5a
5c4fae ¤   (void) memset( line, '\0', sizeof(line) );
3b3ca4 ¤   while ( getline( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) {
eb8388 ¤   ¤   command1 = line[0];
d691c4 ¤   ¤   command2 = line[1];
aeb1a4 ¤   ¤   command3 = line[2];
c3af5a
5fd189 ¤   ¤   switch ( command1 ) {
eaf581 ¤   ¤   case 'a':¤  /* add or abandon */
f9eafc ¤   ¤   ¤   switch ( command2 ) {
e946f4 ¤   ¤   ¤   case 'd':¤  /* add */
6fa248 ¤   ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
68ac03 ¤   ¤   ¤   ¤   strcat( dn, dnsuffix );
9eef6c ¤   ¤   ¤   ¤   if ( (attrs = get_modlist( NULL, "attr? ",
c0550e ¤   ¤   ¤   ¤   ····"value? " )) == NULL )
6f14c3 ¤   ¤   ¤   ¤   ¤   break;
38b730 ¤   ¤   ¤   ¤   if ( (id = ldap_add( ld, dn, attrs )) == -1 )
c56329 ¤   ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_add" );
2bfa07 ¤   ¤   ¤   ¤   else
797441 ¤   ¤   ¤   ¤   ¤   printf( "Add initiated with id %d\n",
728e9c ¤   ¤   ¤   ¤   ¤   ····id );
5ff622 ¤   ¤   ¤   ¤   break;
d1af5a
--44f1 000c32c24ec401000b4 Page 7 of test.c
96f66e ¤   ¤   ¤   case 'b':¤  /* abandon */
509c7c ¤   ¤   ¤   ¤   getline( line, sizeof(line), stdin, "msgid? " );
c92fa1 ¤   ¤   ¤   ¤   id = atoi( line );
7892fc ¤   ¤   ¤   ¤   if ( ldap_abandon( ld, id ) != 0 )
dc3c0c ¤   ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_abandon" );
cdfa07 ¤   ¤   ¤   ¤   else
a3b9e3 ¤   ¤   ¤   ¤   ¤   printf( "Abandon successful\n" );
86f622 ¤   ¤   ¤   ¤   break;
9adb68 ¤   ¤   ¤   default:
464838 ¤   ¤   ¤   ¤   printf( "Possibilities: [ad]d, [ab]ort\n" );
15a3a6 ¤   ¤   ¤   }
15cdcb ¤   ¤   ¤   break;
63af5a
25e031 ¤   ¤   case 'b':¤  /* asynch bind */
795ffa #ifdef KERBEROS
ecbcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
c45144 ¤   ¤   ¤   ····"method (0->simple, 1->krbv41, 2->krbv42)? " );
9f9a8d ¤   ¤   ¤   method = atoi( line ) | 0x80;
853104 #else /* KERBEROS */
83ed6a ¤   ¤   ¤   method = LDAP_AUTH_SIMPLE;
94999d #endif /* KERBEROS */
ffa13f ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
806956 ¤   ¤   ¤   strcat( dn, dnsuffix );
1eaf5a
a8eb8a ¤   ¤   ¤   if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' )
305b86 ¤   ¤   ¤   ¤   getline( passwd, sizeof(passwd), stdin,
8302fa ¤   ¤   ¤   ¤   ····"password? " );
6cbb8c ¤   ¤   ¤   else
3f3675 ¤   ¤   ¤   ¤   passwd[0] = '\0';
07af5a
987239 ¤   ¤   ¤   if ( ldap_bind( ld, dn, passwd, method ) == -1 ) {
2edc08 ¤   ¤   ¤   ¤   fprintf( stderr, "ldap_bind failed\n" );
236aa1 ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_bind" );
98042d ¤   ¤   ¤   } else {
6814c2 ¤   ¤   ¤   ¤   printf( "Bind initiated\n" );
adb933 ¤   ¤   ¤   ¤   bound = 1;
00a3a6 ¤   ¤   ¤   }
d3cdcb ¤   ¤   ¤   break;
eaaf5a
f84919 ¤   ¤   case 'B':¤  /* synch bind */
dc5ffa #ifdef KERBEROS
ebbcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
e25656 ¤   ¤   ¤   ····"method 0->simple 1->krbv41 2->krbv42 3->krb? " );
9ebe5a ¤   ¤   ¤   method = atoi( line );
d0ab0c ¤   ¤   ¤   if ( method == 3 )
0921bc ¤   ¤   ¤   ¤   method = LDAP_AUTH_KRBV4;
a4bb8c ¤   ¤   ¤   else
223f96 ¤   ¤   ¤   ¤   method = method | 0x80;
163104 #else /* KERBEROS */
6fed6a ¤   ¤   ¤   method = LDAP_AUTH_SIMPLE;
76999d #endif /* KERBEROS */
b4a13f ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
306956 ¤   ¤   ¤   strcat( dn, dnsuffix );
6daf5a
ebe500 ¤   ¤   ¤   if ( dn[0] != '\0' )
7f5b86 ¤   ¤   ¤   ¤   getline( passwd, sizeof(passwd), stdin,
c402fa ¤   ¤   ¤   ¤   ····"password? " );
41bb8c ¤   ¤   ¤   else
cf3675 ¤   ¤   ¤   ¤   passwd[0] = '\0';
d4af5a
8da316 ¤   ¤   ¤   if ( ldap_bind_s( ld, dn, passwd, method ) !=
644a21 ¤   ¤   ¤   ····LDAP_SUCCESS ) {
0462ed ¤   ¤   ¤   ¤   fprintf( stderr, "ldap_bind_s failed\n" );
225c33 ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_bind_s" );
7d042d ¤   ¤   ¤   } else {
99eb75 ¤   ¤   ¤   ¤   printf( "Bind successful\n" );
d7b933 ¤   ¤   ¤   ¤   bound = 1;
c2a3a6 ¤   ¤   ¤   }
28cdcb ¤   ¤   ¤   break;
88af5a
317381 ¤   ¤   case 'c':¤  /* compare */
c3a13f ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
--2f41 00047c9f9dc401000b4 Page 8 of test.c
526956 ¤   ¤   ¤   strcat( dn, dnsuffix );
a491e0 ¤   ¤   ¤   getline( attr, sizeof(attr), stdin, "attr? " );
f13b52 ¤   ¤   ¤   getline( value, sizeof(value), stdin, "value? " );
ecaf5a
1d2fbc ¤   ¤   ¤   if ( (id = ldap_compare( ld, dn, attr, value )) == -1 )
4044c8 ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_compare" );
f0bb8c ¤   ¤   ¤   else
a68030 ¤   ¤   ¤   ¤   printf( "Compare initiated with id %d\n", id );
4ccdcb ¤   ¤   ¤   break;
deaf5a
823e06 ¤   ¤   case 'd':¤  /* turn on debugging */
342639 #ifdef LDAP_DEBUG
013230 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "debug level? " );
733e32 ¤   ¤   ¤   ldap_debug = atoi( line );
a993dd ¤   ¤   ¤   if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
22b72b ¤   ¤   ¤   ¤   lber_debug = ldap_debug;
f0a3a6 ¤   ¤   ¤   }
d0db21 #else
b2bc7a ¤   ¤   ¤   printf( "Compile with -DLDAP_DEBUG for debugging\n" );
597454 #endif
3ccdcb ¤   ¤   ¤   break;
7baf5a
fc0fa9 ¤   ¤   case 'E':¤  /* explode a dn */
400b5a ¤   ¤   ¤   getline( line, sizeof(line), stdin, "dn? " );
8e9230 ¤   ¤   ¤   exdn = ldap_explode_dn( line, 0 );
1bc6ca ¤   ¤   ¤   for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) {
5cec28 ¤   ¤   ¤   ¤   printf( "\t%s\n", exdn[i] );
9ea3a6 ¤   ¤   ¤   }
a8cdcb ¤   ¤   ¤   break;
a3af5a
a7f4d8 ¤   ¤   case 'g':¤  /* set next msgid */
974655 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "msgid? " );
241d2e ¤   ¤   ¤   ld->ld_msgid = atoi( line );
0dcdcb ¤   ¤   ¤   break;
8faf5a
80b612 ¤   ¤   case 'v':¤  /* set version number */
eaf3b7 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "version? " );
e88eba ¤   ¤   ¤   ld->ld_version = atoi( line );
b9cdcb ¤   ¤   ¤   break;
9daf5a
355013 ¤   ¤   case 'm':¤  /* modify or modifyrdn */
c8b4e5 ¤   ¤   ¤   if ( strncmp( line, "modify", 4 ) == 0 ) {
3ca248 ¤   ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
cbac03 ¤   ¤   ¤   ¤   strcat( dn, dnsuffix );
857400 ¤   ¤   ¤   ¤   if ( (mods = get_modlist(
5ae640 ¤   ¤   ¤   ¤   ····"mod (0=>add, 1=>delete, 2=>replace -1=>done)? ",
5249fb ¤   ¤   ¤   ¤   ····"attribute type? ", "attribute value? " ))
73b48c ¤   ¤   ¤   ¤   ····== NULL )
2914c3 ¤   ¤   ¤   ¤   ¤   break;
e98158 ¤   ¤   ¤   ¤   if ( (id = ldap_modify( ld, dn, mods )) == -1 )
15e63c ¤   ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_modify" );
0dfa07 ¤   ¤   ¤   ¤   else
779044 ¤   ¤   ¤   ¤   ¤   printf( "Modify initiated with id %d\n",
3c8e9c ¤   ¤   ¤   ¤   ¤   ····id );
dc9cb9 ¤   ¤   ¤   } else if ( strncmp( line, "modrdn", 4 ) == 0 ) {
fea248 ¤   ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
28ac03 ¤   ¤   ¤   ¤   strcat( dn, dnsuffix );
06308b ¤   ¤   ¤   ¤   getline( rdn, sizeof(rdn), stdin, "newrdn? " );
41721f ¤   ¤   ¤   ¤   if ( (id = ldap_modrdn( ld, dn, rdn )) == -1 )
6273f2 ¤   ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_modrdn" );
02fa07 ¤   ¤   ¤   ¤   else
f0a607 ¤   ¤   ¤   ¤   ¤   printf( "Modrdn initiated with id %d\n",
b28e9c ¤   ¤   ¤   ¤   ¤   ····id );
82042d ¤   ¤   ¤   } else {
66fe44 ¤   ¤   ¤   ¤   printf( "Possibilities: [modi]fy, [modr]dn\n" );
a4a3a6 ¤   ¤   ¤   }
9fcdcb ¤   ¤   ¤   break;
8daf5a
1f6e4b ¤   ¤   case 'q':¤  /* quit */
cced07 #ifdef CLDAP
312739 ¤   ¤   ¤   if ( cldapflg )
470fdf ¤   ¤   ¤   ¤   cldap_close( ld );
--46f5 0005d950cdf401000b4 Page 9 of test.c
596b1c #endif /* CLDAP */
5b7f8d #ifdef LDAP_REFERRALS
2ddc6b ¤   ¤   ¤   if ( !cldapflg )
c44267 #else /* LDAP_REFERRALS */
862f3b ¤   ¤   ¤   if ( !cldapflg && bound )
0e90e2 #endif /* LDAP_REFERRALS */
db2285 ¤   ¤   ¤   ¤   ldap_unbind( ld );
76663c ¤   ¤   ¤   exit( 0 );
becdcb ¤   ¤   ¤   break;
6baf5a
adcd4a ¤   ¤   case 'r':¤  /* result or remove */
0aeed7 ¤   ¤   ¤   switch ( command3 ) {
e2cb42 ¤   ¤   ¤   case 's':¤  /* result */
752a89 ¤   ¤   ¤   ¤   getline( line, sizeof(line), stdin,
760abb ¤   ¤   ¤   ¤   ····"msgid (-1=>any)? " );
7ebbb0 ¤   ¤   ¤   ¤   if ( line[0] == '\0' )
3043fe ¤   ¤   ¤   ¤   ¤   id = -1;
0efa07 ¤   ¤   ¤   ¤   else
c96e52 ¤   ¤   ¤   ¤   ¤   id = atoi( line );
d62a89 ¤   ¤   ¤   ¤   getline( line, sizeof(line), stdin,
90e2e4 ¤   ¤   ¤   ¤   ····"all (0=>any, 1=>all)? " );
43bbb0 ¤   ¤   ¤   ¤   if ( line[0] == '\0' )
6853c0 ¤   ¤   ¤   ¤   ¤   all = 1;
bbfa07 ¤   ¤   ¤   ¤   else
3dba73 ¤   ¤   ¤   ¤   ¤   all = atoi( line );
8ff936 ¤   ¤   ¤   ¤   if (( msgtype = ldap_result( ld, id, all,
fc798c ¤   ¤   ¤   ¤   ····&timeout, &res )) < 1 ) {
4410b6 ¤   ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_result" );
bd14c3 ¤   ¤   ¤   ¤   ¤   break;
5f2613 ¤   ¤   ¤   ¤   }
1c556e ¤   ¤   ¤   ¤   printf( "\nresult: msgtype %d msgid %d\n",
494b92 ¤   ¤   ¤   ¤   ····msgtype, res->lm_msgid );
05e11b ¤   ¤   ¤   ¤   handle_result( ld, res );
506ae0 ¤   ¤   ¤   ¤   res = NULLMSG;
6af622 ¤   ¤   ¤   ¤   break;
87af5a
619d93 ¤   ¤   ¤   case 'm':¤  /* remove */
f6a248 ¤   ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "dn? " );
8cac03 ¤   ¤   ¤   ¤   strcat( dn, dnsuffix );
d760f6 ¤   ¤   ¤   ¤   if ( (id = ldap_delete( ld, dn )) == -1 )
898bfe ¤   ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_delete" );
85fa07 ¤   ¤   ¤   ¤   else
cacde4 ¤   ¤   ¤   ¤   ¤   printf( "Remove initiated with id %d\n",
018e9c ¤   ¤   ¤   ¤   ¤   ····id );
4cf622 ¤   ¤   ¤   ¤   break;
2baf5a
e6db68 ¤   ¤   ¤   default:
b2a723 ¤   ¤   ¤   ¤   printf( "Possibilities: [rem]ove, [res]ult\n" );
99f622 ¤   ¤   ¤   ¤   break;
17a3a6 ¤   ¤   ¤   }
67cdcb ¤   ¤   ¤   break;
81af5a
36b3fb ¤   ¤   case 's':¤  /* search */
be63a7 ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "searchbase? " );
656956 ¤   ¤   ¤   strcat( dn, dnsuffix );
b6bcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
f0fc4b ¤   ¤   ¤   ····"scope (0=Base, 1=One Level, 2=Subtree)? " );
51a76a ¤   ¤   ¤   scope = atoi( line );
678fab ¤   ¤   ¤   getline( filter, sizeof(filter), stdin,
e13ea3 ¤   ¤   ¤   ····"search filter (e.g. sn=jones)? " );
4ada56 ¤   ¤   ¤   types = get_list( "attrs to return? " );
b2bcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
efcb18 ¤   ¤   ¤   ····"attrsonly (0=attrs&values, 1=attrs only)? " );
8a47c1 ¤   ¤   ¤   attrsonly = atoi( line );
5aaf5a
51ff70 ¤   ¤   ¤   if ( cldapflg ) {
a9ed07 #ifdef CLDAP
ce85b0 ¤   ¤   ¤   ····getline( line, sizeof(line), stdin,
70cd14 ¤   ¤   ¤   ¤   "Requestor DN (for logging)? " );
6957ac ¤   ¤   ¤   ····if ( cldap_search_s( ld, dn, scope, filter, types,
74e4b5 ¤   ¤   ¤   ¤   ····attrsonly, &res, line ) != 0 ) {
5d9e43 ¤   ¤   ¤   ¤   ldap_perror( ld, "cldap_search_s" );
--e3cc 000614de6a8401000b4 Page 10 of test.c
c92fb2 ¤   ¤   ¤   ····} else {
71cc44 ¤   ¤   ¤   ¤   printf( "\nresult: msgid %d\n",
2063a3 ¤   ¤   ¤   ¤   ····res->lm_msgid );
10e11b ¤   ¤   ¤   ¤   handle_result( ld, res );
546ae0 ¤   ¤   ¤   ¤   res = NULLMSG;
9eda85 ¤   ¤   ¤   ····}
926b1c #endif /* CLDAP */
5c042d ¤   ¤   ¤   } else {
d7a79f ¤   ¤   ¤   ····if (( id = ldap_search( ld, dn, scope, filter,
07d90b ¤   ¤   ¤   ¤   ····types, attrsonly ·)) == -1 ) {
9079f6 ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_search" );
2a2fb2 ¤   ¤   ¤   ····} else {
23d254 ¤   ¤   ¤   ¤   printf( "Search initiated with id %d\n", id );
20da85 ¤   ¤   ¤   ····}
1ba3a6 ¤   ¤   ¤   }
6b30cf ¤   ¤   ¤   free_list( types );
5fcdcb ¤   ¤   ¤   break;
55af5a
74bed1 ¤   ¤   case 't':¤  /* set timeout value */
a6a2fc ¤   ¤   ¤   getline( line, sizeof(line), stdin, "timeout? " );
7ef23c ¤   ¤   ¤   timeout.tv_sec = atoi( line );
11cdcb ¤   ¤   ¤   break;
23af5a
e50464 ¤   ¤   case 'U':¤  /* set ufn search prefix */
68cf6e ¤   ¤   ¤   getline( line, sizeof(line), stdin, "ufn prefix? " );
be71f7 ¤   ¤   ¤   ldap_ufn_setprefix( ld, line );
a4cdcb ¤   ¤   ¤   break;
73af5a
fe2fe2 ¤   ¤   case 'u':¤  /* user friendly search w/optional timeout */
578cd1 ¤   ¤   ¤   getline( dn, sizeof(dn), stdin, "ufn? " );
ba6956 ¤   ¤   ¤   strcat( dn, dnsuffix );
b8da56 ¤   ¤   ¤   types = get_list( "attrs to return? " );
cfbcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
05cb18 ¤   ¤   ¤   ····"attrsonly (0=attrs&values, 1=attrs only)? " );
0b47c1 ¤   ¤   ¤   attrsonly = atoi( line );
8aaf5a
32d0b1 ¤   ¤   ¤   if ( command2 == 't' ) {
537ebd ¤   ¤   ¤   ¤   id = ldap_ufn_search_c( ld, dn, types,
a842ff ¤   ¤   ¤   ¤   ····attrsonly, &res, ldap_ufn_timeout,
fa2bb4 ¤   ¤   ¤   ¤   ····&timeout );
00042d ¤   ¤   ¤   } else {
708832 ¤   ¤   ¤   ¤   id = ldap_ufn_search_s( ld, dn, types,
282a99 ¤   ¤   ¤   ¤   ····attrsonly, &res );
24a3a6 ¤   ¤   ¤   }
ebc05b ¤   ¤   ¤   if ( res == NULL )
00bb7f ¤   ¤   ¤   ¤   ldap_perror( ld, "ldap_ufn_search" );
80e543 ¤   ¤   ¤   else {
0b30a2 ¤   ¤   ¤   ¤   printf( "\nresult: err %d\n", id );
e9e11b ¤   ¤   ¤   ¤   handle_result( ld, res );
4d6ae0 ¤   ¤   ¤   ¤   res = NULLMSG;
8fa3a6 ¤   ¤   ¤   }
5f30cf ¤   ¤   ¤   free_list( types );
e2cdcb ¤   ¤   ¤   break;
50af5a
f0ccfc ¤   ¤   case 'l':¤  /* URL search */
29bcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
f3cb18 ¤   ¤   ¤   ····"attrsonly (0=attrs&values, 1=attrs only)? " );
be47c1 ¤   ¤   ¤   attrsonly = atoi( line );
172348 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "LDAP URL? " );
1aa51a ¤   ¤   ¤   if (( id = ldap_url_search( ld, line, attrsonly ·))
c5ccb9 ¤   ¤   ¤   ¤   == -1 ) {
eda90c ¤   ¤   ¤   ····ldap_perror( ld, "ldap_url_search" );
a5042d ¤   ¤   ¤   } else {
a30436 ¤   ¤   ¤   ····printf( "URL search initiated with id %d\n", id );
41a3a6 ¤   ¤   ¤   }
71cdcb ¤   ¤   ¤   break;
b4af5a
113625 ¤   ¤   case 'p':¤  /* parse LDAP URL */
392348 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "LDAP URL? " );
639631 ¤   ¤   ¤   if (( i = ldap_url_parse( line, &ludp )) != 0 ) {
c7c9b4 ¤   ¤   ¤   ····fprintf( stderr, "ldap_url_parse: error %d\n", i );
61042d ¤   ¤   ¤   } else {
--7a03 000ffd99bc6401000b4 Page 11 of test.c
e1369f ¤   ¤   ¤   ····printf( "\t ·host: " );
a0aa20 ¤   ¤   ¤   ····if ( ludp->lud_host == NULL ) {
9af562 ¤   ¤   ¤   ¤   printf( "DEFAULT\n" );
772fb2 ¤   ¤   ¤   ····} else {
7e3bcb ¤   ¤   ¤   ¤   printf( "<%s>\n", ludp->lud_host );
98da85 ¤   ¤   ¤   ····}
62b68d ¤   ¤   ¤   ····printf( "\t ·port: " );
dc96e8 ¤   ¤   ¤   ····if ( ludp->lud_port == 0 ) {
2cf562 ¤   ¤   ¤   ¤   printf( "DEFAULT\n" );
212fb2 ¤   ¤   ¤   ····} else {
c08554 ¤   ¤   ¤   ¤   printf( "%d\n", ludp->lud_port );
d8da85 ¤   ¤   ¤   ····}
79eaa8 ¤   ¤   ¤   ····printf( "\t ···dn: <%s>\n", ludp->lud_dn );
bdd1b3 ¤   ¤   ¤   ····printf( "\t attrs:" );
5f0f7c ¤   ¤   ¤   ····if ( ludp->lud_attrs == NULL ) {
73461b ¤   ¤   ¤   ¤   printf( " ALL" );
e72fb2 ¤   ¤   ¤   ····} else {
89c35b ¤   ¤   ¤   ¤   for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) {
e9ca1d ¤   ¤   ¤   ¤   ····printf( " <%s>", ludp->lud_attrs[ i ] );
442613 ¤   ¤   ¤   ¤   }
d7da85 ¤   ¤   ¤   ····}
fed890 ¤   ¤   ¤   ····printf( "\n\t scope: %s\n",·
648634 ¤   ¤   ¤   ¤   ludp->lud_scope == LDAP_SCOPE_ONELEVEL ? "ONE"
b07a37 ¤   ¤   ¤   ¤   : ludp->lud_scope == LDAP_SCOPE_BASE ? "BASE" :
4baedb ¤   ¤   ¤   ¤   ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "SUB" :
75373f ¤   ¤   ¤   ¤   "**invalid**" );
0f7e23 ¤   ¤   ¤   ····printf( "\tfilter: <%s>\n", ludp->lud_filter );
e041dc ¤   ¤   ¤   ····ldap_free_urldesc( ludp );
03a3a6 ¤   ¤   ¤   }
e913b0 ¤   ¤   ¤   ····break;
13af5a
50f414 ¤   ¤   case 'n':¤  /* set dn suffix, for convenience */
c71a2f ¤   ¤   ¤   getline( line, sizeof(line), stdin, "DN suffix? " );
d6ba38 ¤   ¤   ¤   strcpy( dnsuffix, line );
15cdcb ¤   ¤   ¤   break;
c2af5a
2f34d0 ¤   ¤   case 'e':¤  /* enable cache */
019e1b #ifdef NO_CACHE
442b26 ¤   ¤   ¤   printf( NOCACHEERRMSG );
3db10b #else /* NO_CACHE */
6e6fb4 ¤   ¤   ¤   getline( line, sizeof(line), stdin,·
0baeda ¤   ¤   ¤   ¤   ¤   "Cache timeout (secs)? " );
a5cfe0 ¤   ¤   ¤   i = atoi( line );
716fb4 ¤   ¤   ¤   getline( line, sizeof(line), stdin,·
57df14 ¤   ¤   ¤   ¤   ¤   "Maximum memory to use (bytes)? " );
66b555 ¤   ¤   ¤   if ( ldap_enable_cache( ld, i, atoi( line )) == 0 ) {
bab0a3 ¤   ¤   ¤   ¤   printf( "local cache is on\n" );·
dd042d ¤   ¤   ¤   } else {
4eb03d ¤   ¤   ¤   ¤   printf( "ldap_enable_cache failed\n" );·
43a3a6 ¤   ¤   ¤   }
a71992 #endif /* NO_CACHE */
84cdcb ¤   ¤   ¤   break;
5faf5a
7372c2 ¤   ¤   case 'x':¤  /* uncache entry */
bb9e1b #ifdef NO_CACHE
2e2b26 ¤   ¤   ¤   printf( NOCACHEERRMSG );
dcb10b #else /* NO_CACHE */
a34a93 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "DN? " );
c1cffd ¤   ¤   ¤   ldap_uncache_entry( ld, line );
d41992 #endif /* NO_CACHE */
6bcdcb ¤   ¤   ¤   break;
c5af5a
e063c5 ¤   ¤   case 'X':¤  /* uncache request */
bc9e1b #ifdef NO_CACHE
202b26 ¤   ¤   ¤   printf( NOCACHEERRMSG );
2db10b #else /* NO_CACHE */
48a0b4 ¤   ¤   ¤   getline( line, sizeof(line), stdin, "request msgid? " );
177aba ¤   ¤   ¤   ldap_uncache_request( ld, atoi( line ));
c01992 #endif /* NO_CACHE */
73cdcb ¤   ¤   ¤   break;
30af5a
fffd12 ¤   ¤   case 'o':¤  /* set ldap options */
--72df 0002477a411401000b4 Page 12 of test.c
2c6fb4 ¤   ¤   ¤   getline( line, sizeof(line), stdin,·
7d4b61 ¤   ¤   ¤   ¤   ¤   "alias deref (0=never, 1=searching, 2"
59ace2 ¤   ¤   ¤   ¤   ¤   "=finding, 3=always)?" );
de3200 ¤   ¤   ¤   ld->ld_deref = atoi( line );
6b93be ¤   ¤   ¤   getline( line, sizeof(line), stdin, "timelimit?" );
f4ccc3 ¤   ¤   ¤   ld->ld_timelimit = atoi( line );
5d21ea ¤   ¤   ¤   getline( line, sizeof(line), stdin, "sizelimit?" );
3faa89 ¤   ¤   ¤   ld->ld_sizelimit = atoi( line );
82af5a
39010d ¤   ¤   ¤   ld->ld_options = 0;
2daf5a
66f52a #ifdef STR_TRANSLATION
e6bcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
0290e0 ¤   ¤   ¤   ¤   "Automatic translation of T.61 strings "
cfaaa5 ¤   ¤   ¤   ¤   "(0=no, 1=yes)?" );
b3cb80 ¤   ¤   ¤   if ( atoi( line ) == 0 ) {
d8f8dd ¤   ¤   ¤   ¤   ld->ld_lberoptions &= ~LBER_TRANSLATE_STRINGS;
a3042d ¤   ¤   ¤   } else {
0891d4 ¤   ¤   ¤   ¤   ld->ld_lberoptions |= LBER_TRANSLATE_STRINGS;
a18068 #ifdef LDAP_CHARSET_8859
b92a89 ¤   ¤   ¤   ¤   getline( line, sizeof(line), stdin,
c9ac27 ¤   ¤   ¤   ¤   ¤   "Translate to/from ISO-8859 "
56279b ¤   ¤   ¤   ¤   ¤   "(0=no, 1=yes?" );
687a77 ¤   ¤   ¤   ¤   if ( atoi( line ) != 0 ) {
899a70 ¤   ¤   ¤   ¤   ¤   ldap_set_string_translators( ld,
4a25e4 ¤   ¤   ¤   ¤   ¤   ····ldap_8859_to_t61,
e41851 ¤   ¤   ¤   ¤   ¤   ····ldap_t61_to_8859 );
be2613 ¤   ¤   ¤   ¤   }
027911 #endif /* LDAP_CHARSET_8859 */
65a3a6 ¤   ¤   ¤   }
eb3dd6 #endif /* STR_TRANSLATION */
6eaf5a
944ae9 #ifdef LDAP_DNS
6bbcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
b10e70 ¤   ¤   ¤   ¤   "Use DN & DNS to determine where to send "
f96d76 ¤   ¤   ¤   ¤   "requests (0=no, 1=yes)?" );
e0743b ¤   ¤   ¤   if ( atoi( line ) != 0 ) {
4ab90b ¤   ¤   ¤   ¤   ld->ld_options |= LDAP_OPT_DNS;
e8a3a6 ¤   ¤   ¤   }
a61845 #endif /* LDAP_DNS */
20af5a
cd7f8d #ifdef LDAP_REFERRALS
aabcc8 ¤   ¤   ¤   getline( line, sizeof(line), stdin,
10c6d5 ¤   ¤   ¤   ¤   "Recognize and chase referrals (0=no, 1=yes)?");
2d743b ¤   ¤   ¤   if ( atoi( line ) != 0 ) {
fdb069 ¤   ¤   ¤   ¤   ld->ld_options |= LDAP_OPT_REFERRALS;
3d2a89 ¤   ¤   ¤   ¤   getline( line, sizeof(line), stdin,
6de42d ¤   ¤   ¤   ¤   ¤   "Prompt for bind credentials when "
4e117f ¤   ¤   ¤   ¤   ¤   "chasing referrals (0=no, 1=yes)?" );
0a7a77 ¤   ¤   ¤   ¤   if ( atoi( line ) != 0 ) {
f037d8 ¤   ¤   ¤   ¤   ¤   ldap_set_rebind_proc( ld, bind_prompt );
932613 ¤   ¤   ¤   ¤   }
03a3a6 ¤   ¤   ¤   }
4290e2 #endif /* LDAP_REFERRALS */
48cdcb ¤   ¤   ¤   break;
eaaf5a
8cf865 ¤   ¤   case 'O':¤  /* set cache options */
c09e1b #ifdef NO_CACHE
0b2b26 ¤   ¤   ¤   printf( NOCACHEERRMSG );
dfb10b #else /* NO_CACHE */
116fb4 ¤   ¤   ¤   getline( line, sizeof(line), stdin,·
88aeee ¤   ¤   ¤   ¤   "cache errors (0=smart, 1=never, 2=always)?" );
dcc54b ¤   ¤   ¤   switch( atoi( line )) {
0875ac ¤   ¤   ¤   case 0:
0591c7 ¤   ¤   ¤   ¤   ldap_set_cache_options( ld, 0 );
88f622 ¤   ¤   ¤   ¤   break;
6c2f70 ¤   ¤   ¤   case 1:
4ba51d ¤   ¤   ¤   ¤   ldap_set_cache_options( ld,
123c82 ¤   ¤   ¤   ¤   ¤   LDAP_CACHE_OPT_CACHENOERRS );
a5f622 ¤   ¤   ¤   ¤   break;
82c014 ¤   ¤   ¤   case 2:
24a51d ¤   ¤   ¤   ¤   ldap_set_cache_options( ld,
--97ba 00089becadf401000b4 Page 13 of test.c
53ff38 ¤   ¤   ¤   ¤   ¤   LDAP_CACHE_OPT_CACHEALLERRS );
1ff622 ¤   ¤   ¤   ¤   break;
17db68 ¤   ¤   ¤   default:
191195 ¤   ¤   ¤   ¤   printf( "not a valid cache option\n" );
7da3a6 ¤   ¤   ¤   }
ed1992 #endif /* NO_CACHE */
aecdcb ¤   ¤   ¤   break;
99af5a
9ad6b0 ¤   ¤   case '?':¤  /* help */
79a727 ····printf( "Commands: [ad]d ········[ab]andon ········[b]ind\n" );
5bda46 ····printf( " ·········[B]ind async ·[c]ompare ········[l]URL search\n" );
c88731 ····printf( " ·········[modi]fy ·····[modr]dn ·········[rem]ove\n" );
5a2a8d ····printf( " ·········[res]ult ·····[s]earch ·········[q]uit/unbind\n\n" );
f71952 ····printf( " ·········[u]fn search ·[ut]fn search with timeout\n" );
201830 ····printf( " ·········[d]ebug ······[e]nable cache ···set ms[g]id\n" );
12d4a7 ····printf( " ·········d[n]suffix ···[t]imeout ········[v]ersion\n" );
548fad ····printf( " ·········[U]fn prefix ·[x]uncache entry ·[X]uncache request\n" );
517f76 ····printf( " ·········[?]help ······[o]ptions ········[O]cache options\n" );
afce3a ····printf( " ·········[E]xplode dn ·[p]arse LDAP URL\n" );
b0cdcb ¤   ¤   ¤   break;
24af5a
2a9ae3 ¤   ¤   default:
15865c ¤   ¤   ¤   printf( "Invalid command. ·Type ? for help.\n" );
48cdcb ¤   ¤   ¤   break;
af0fe4 ¤   ¤   }
d3af5a
54971c ¤   ¤   (void) memset( line, '\0', sizeof(line) );
679371 ¤   }
92af5a
03ea61 ¤   return( 0 );
e7efe6 }
dfaf5a
b32978 static void
a7f2d1 handle_result( LDAP *ld, LDAPMessage *lm )
e2bb36 {
3f3bf3 ¤   switch ( lm->lm_msgtype ) {
4977cf ¤   case LDAP_RES_COMPARE:
05cbce ¤   ¤   printf( "Compare result\n" );
f4df01 ¤   ¤   print_ldap_result( ld, lm, "compare" );
2c2f68 ¤   ¤   break;
8aaf5a
0a7fbe ¤   case LDAP_RES_SEARCH_RESULT:
67abb0 ¤   ¤   printf( "Search result\n" );
1e4199 ¤   ¤   print_ldap_result( ld, lm, "search" );
e92f68 ¤   ¤   break;
79af5a
be1351 ¤   case LDAP_RES_SEARCH_ENTRY:
6919ab ¤   ¤   printf( "Search entry\n" );
908d73 ¤   ¤   print_search_entry( ld, lm );
9c2f68 ¤   ¤   break;
3eaf5a
7ff75b ¤   case LDAP_RES_ADD:
b6c1c8 ¤   ¤   printf( "Add result\n" );
7470d5 ¤   ¤   print_ldap_result( ld, lm, "add" );
a62f68 ¤   ¤   break;
abaf5a
486db1 ¤   case LDAP_RES_DELETE:
589c6c ¤   ¤   printf( "Delete result\n" );
071d90 ¤   ¤   print_ldap_result( ld, lm, "delete" );
472f68 ¤   ¤   break;
07af5a
eb6726 ¤   case LDAP_RES_MODRDN:
eda57e ¤   ¤   printf( "ModRDN result\n" );
b9e59c ¤   ¤   print_ldap_result( ld, lm, "modrdn" );
472f68 ¤   ¤   break;
9aaf5a
9ec93d ¤   case LDAP_RES_BIND:
e020e9 ¤   ¤   printf( "Bind result\n" );
a7c110 ¤   ¤   print_ldap_result( ld, lm, "bind" );
6e2f68 ¤   ¤   break;
37af5a
892f72 ¤   default:
--aa1e 000146a727d401000b4 Page 14 of test.c
dcecd2 ¤   ¤   printf( "Unknown result type 0x%x\n", lm->lm_msgtype );
1bb99d ¤   ¤   print_ldap_result( ld, lm, "unknown" );
ba9371 ¤   }
7aefe6 }
9aaf5a
c72978 static void
12a604 print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s )
fabb36 {
e41dd3 ¤   ldap_result2error( ld, lm, 1 );
cedf9e ¤   ldap_perror( ld, s );
1c38e5 /*
972180 ¤   if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
3dcd5c ¤   ¤   fprintf( stderr, "Additional info: %s\n", ld->ld_error );
5f6484 ¤   if ( NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL )
d8f1e7 ¤   ¤   fprintf( stderr, "Matched DN: %s\n", ld->ld_matched );
bd7fe0 */
0defe6 }
9aaf5a
3b2978 static void
e52722 print_search_entry( LDAP *ld, LDAPMessage *res )
26bb36 {
119c95 ¤   BerElement¤ *ber;
478055 ¤   char¤   ¤   *a, *dn, *ufn;
157116 ¤   struct berval¤  **vals;
96e595 ¤   int¤¤   i;
07a39c ¤   LDAPMessage¤*e;
29af5a
4acfeb ¤   for ( e = ldap_first_entry( ld, res ); e != NULLMSG;
ea058e ¤   ····e = ldap_next_entry( ld, e ) ) {
90b8c1 ¤   ¤   if ( e->lm_msgtype == LDAP_RES_SEARCH_RESULT )
bccdcb ¤   ¤   ¤   break;
2baf5a
3e7c8f ¤   ¤   dn = ldap_get_dn( ld, e );
aa47de ¤   ¤   printf( "\tDN: %s\n", dn );
62af5a
defc98 ¤   ¤   ufn = ldap_dn2ufn( dn );
af9c43 ¤   ¤   printf( "\tUFN: %s\n", ufn );
6aa184 #ifdef WINSOCK
10b149 ¤   ¤   ldap_memfree( dn );
d4bdc4 ¤   ¤   ldap_memfree( ufn );
892e70 #else /* WINSOCK */
4243fe ¤   ¤   free( dn );
807c02 ¤   ¤   free( ufn );
e9d50d #endif /* WINSOCK */
42af5a
8315f8 ¤   ¤   for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
344268 ¤   ¤   ····a = ldap_next_attribute( ld, e, ber ) ) {
4f361d ¤   ¤   ¤   printf( "\t\tATTR: %s\n", a );
4754be ¤   ¤   ¤   if ( (vals = ldap_get_values_len( ld, e, a ))
98b0ea ¤   ¤   ¤   ····== NULL ) {
55c13e ¤   ¤   ¤   ¤   printf( "\t\t\t(no values)\n" );
db042d ¤   ¤   ¤   } else {
6177f5 ¤   ¤   ¤   ¤   for ( i = 0; vals[i] != NULL; i++ ) {
36b98d ¤   ¤   ¤   ¤   ¤   int¤j, nonascii;
97af5a
0df653 ¤   ¤   ¤   ¤   ¤   nonascii = 0;
8d464c ¤   ¤   ¤   ¤   ¤   for ( j = 0; j < vals[i]->bv_len; j++ )
5d1bf4 ¤   ¤   ¤   ¤   ¤   ¤   if ( !isascii( vals[i]->bv_val[j] ) ) {
757f12 ¤   ¤   ¤   ¤   ¤   ¤   ¤   nonascii = 1;
598c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
a2db3c ¤   ¤   ¤   ¤   ¤   ¤   }
eeaf5a
71017b ¤   ¤   ¤   ¤   ¤   if ( nonascii ) {
ce9005 ¤   ¤   ¤   ¤   ¤   ¤   printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv¶
79243f _len );
362e66 #ifdef BPRINT_NONASCII
699587 ¤   ¤   ¤   ¤   ¤   ¤   lber_bprint( vals[i]->bv_val,
78249f ¤   ¤   ¤   ¤   ¤   ¤   ····vals[i]->bv_len );
d62590 #endif /* BPRINT_NONASCII */
c66e1c ¤   ¤   ¤   ¤   ¤   ¤   continue;
631c89 ¤   ¤   ¤   ¤   ¤   }
14a471 ¤   ¤   ¤   ¤   ¤   printf( "\t\t\tlength (%ld) %s\n",
--c8d2 001f15d2aad401000b4 Page 15 of test.c
990861 ¤   ¤   ¤   ¤   ¤   ····vals[i]->bv_len, vals[i]->bv_val );
a92613 ¤   ¤   ¤   ¤   }
34ee88 ¤   ¤   ¤   ¤   ber_bvecfree( vals );
9ca3a6 ¤   ¤   ¤   }
410fe4 ¤   ¤   }
069371 ¤   }
b5af5a
91eb7b ¤   if ( res->lm_msgtype == LDAP_RES_SEARCH_RESULT
915366 ¤   ····|| res->lm_chain != NULLMSG )
76bcb9 ¤   ¤   print_ldap_result( ld, res, "search" );
5cefe6 }
60af5a
38af5a
1ea184 #ifdef WINSOCK
11314a void
c54c38 ldap_perror( LDAP *ld, char *s )
49bb36 {
8f7514 ¤   char¤   *errs;
09af5a
873a4e ¤   if ( ld == NULL ) {
43df80 ¤   ¤   perror( s );
0c99bf ¤   ¤   return;
ec9371 ¤   }
cbaf5a
90a287 ¤   errs = ldap_err2string( ld->ld_errno );
269c73 ¤   printf( "%s: %s\n", s, errs == NULL ? "unknown error" : errs );
427730 ¤   if ( ld->ld_error != NULL && *ld->ld_error != '\0' ) {
f055bb ¤   ¤   printf( "%s: additional info: %s\n", s, ld->ld_error );
f69371 ¤   }
afefe6 }
f1d50d #endif /* WINSOCK */
--1deb 000b7065e0d401000b5 Page 1 of tmplout.c
bc38e5 /*
e4624b ·* tmplout.c: ·display template library output routines for LDAP clients
533905 ·* 12 April 1994 by Mark C Smith
eb495d ·*/
9eaf5a
b1feb2 #include <stdio.h>
79324c #include <string.h>
9cb1cb #include <ctype.h>
a50a8b #include <time.h>
d0bea3 #include <stdlib.h>
85c583 #ifdef MACOS
9665e0 #include "macos.h"
b26c94 #else /* MACOS */
fcaf69 #if defined(DOS) || defined(WIN32)
8b5e84 #include <malloc.h>
8801b0 #ifdef DOS
bff2ef #include "msdos.h"
307454 #endif
e6aad8 #else /* DOS */
bd5d8c #include <sys/time.h>
c5f15e #include <sys/types.h>
3609b0 #include <sys/file.h>
9fbc39 #endif /* DOS */
eee962 #endif /* MACOS */
73af5a
1c6cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
b82d5f #include <winsock.h>
d7cafc #define TEMPLATEFILE¤   "etc/ldaptemplates.conf"
bd7454 #endif
79af5a
354edf #ifdef VMS
1e66f2 #include <sys/socket.h>
a8361d #endif /* VMS */
edaf5a
dbb779 #include "lber.h"
6ae990 #include "ldap.h"
ce2b4c #include "disptmpl.h"
53af5a
9e504c #ifdef NEEDPROTOS
7643b7 static int do_entry2text( LDAP *ld, char *buf, char *base, LDAPMessage *entry,
6be002 ¤   struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
88d912 ¤   writeptype writeproc, void *writeparm, char *eol, int rdncount,
c5b078 ¤   unsigned long opts, char *urlprefix );
b018a4 static int do_entry2text_search( LDAP *ld, char *dn, char *base,
2e05be ¤   LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
b02a0c ¤   char ***defvals, writeptype writeproc, void *writeparm, char *eol,
9697b4 ¤   int rdncount, unsigned long opts, char *urlprefix );
091b17 static int do_vals2text( LDAP *ld, char *buf, char **vals, char *label,
976769 ¤   int labelwidth, unsigned long syntaxid, writeptype writeproc,
66aab7 ¤   void *writeparm, char *eol, int rdncount, char *urlprefix );
374ed5 static int max_label_len( struct ldap_disptmpl *tmpl );
e1633c static int output_label( char *buf, char *label, int width,
793097 ¤   writeptype writeproc, void *writeparm, char *eol, int html );
0b2733 static int output_dn( char *buf, char *dn, int width, int rdncount,
91acf8 ¤   writeptype writeproc, void *writeparm, char *eol, char *urlprefix );
081b27 static void strcat_escaped( char *s1, char *s2 );
c814be static char *time2text( char *ldtimestr, int dateonly );
95266c static long gtime( struct tm *tm );
d46c78 static int searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry,
15e780 ¤   char *dn, struct ldap_tmplitem *tip, int labelwidth, int rdncount,
9aacf8 ¤   writeptype writeproc, void *writeparm, char *eol, char *urlprefix );
5b6133 #else /* NEEDPROTOS */
f449ed static int do_entry2text();
f68f0e static int do_entry2text_search();
d50f12 static int do_vals2text();
5f90cf static int max_label_len();
118a54 static int output_label();
570840 static int output_dn();
802b72 static void strcat_escaped();
02317e static char *time2text();
5410ba static long gtime();
b7ccc6 static int searchaction();
--2a76 000c5c14904401000b5 Page 2 of tmplout.c
fd8634 #endif /* NEEDPROTOS */
ceaf5a
715c4e #define DEF_LABEL_WIDTH¤¤   15
10297b #define SEARCH_TIMEOUT_SECS¤120
4cc546 #define OCATTRNAME¤ ¤   "objectClass"
55af5a
10af5a
91d7bb #define NONFATAL_LDAP_ERR( err )¤   ( err == LDAP_SUCCESS || \
611868 ¤   err == LDAP_TIMELIMIT_EXCEEDED || err == LDAP_SIZELIMIT_EXCEEDED )
33af5a
094a6f #define DEF_LDAP_URL_PREFIX¤"ldap:///"
68af5a
c6d83c ·
204d2f int
045c56 ldap_entry2text(
40b830 ¤   LDAP¤   ¤   ¤   *ld,
f9edfb ¤   char¤   ¤   ¤   *buf,¤  ¤   /* NULL for "use internal" */
5f47fa ¤   LDAPMessage¤¤   *entry,
8e51f9 ¤   struct ldap_disptmpl¤   *tmpl,
2ac03c ¤   char¤   ¤   ¤   **defattrs,
fae728 ¤   char¤   ¤   ¤   ***defvals,
431bf8 ¤   writeptype¤ ¤   writeproc,
234536 ¤   void¤   ¤   ¤   *writeparm,
d78ea0 ¤   char¤   ¤   ¤   *eol,
c9fa79 ¤   int¤¤   ¤   rdncount,
da4f07 ¤   unsigned long¤  ¤   opts
0b5b71 )
57bb36 {
a9e2ca ····Debug( LDAP_DEBUG_TRACE, "ldap_entry2text\n", 0, 0, 0 );
e7af5a
61fe81 ····return( do_entry2text( ld, buf, NULL, entry, tmpl, defattrs, defvals,
44b0e6 ¤   ¤   writeproc, writeparm, eol, rdncount, opts, NULL ));
d4af5a
62efe6 }
cdaf5a
7aaf5a
beaf5a
ab4d2f int
d77eb7 ldap_entry2html(
edb830 ¤   LDAP¤   ¤   ¤   *ld,
94edfb ¤   char¤   ¤   ¤   *buf,¤  ¤   /* NULL for "use internal" */
4c47fa ¤   LDAPMessage¤¤   *entry,
9651f9 ¤   struct ldap_disptmpl¤   *tmpl,
0cc03c ¤   char¤   ¤   ¤   **defattrs,
d9e728 ¤   char¤   ¤   ¤   ***defvals,
bf1bf8 ¤   writeptype¤ ¤   writeproc,
974536 ¤   void¤   ¤   ¤   *writeparm,
dd8ea0 ¤   char¤   ¤   ¤   *eol,
9ffa79 ¤   int¤¤   ¤   rdncount,
0cac49 ¤   unsigned long¤  ¤   opts,
b6eb64 ¤   char¤   ¤   ¤   *base,
423364 ¤   char¤   ¤   ¤   *urlprefix
405b71 )
73bb36 {
7b42d4 ····Debug( LDAP_DEBUG_TRACE, "ldap_entry2html\n", 0, 0, 0 );
40af5a
fb1369 ····if ( urlprefix == NULL ) {
dde01c ¤   urlprefix = DEF_LDAP_URL_PREFIX;
686fe7 ····}
0aaf5a
a3558d ····return( do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals,
63cc2b ¤   ¤   writeproc, writeparm, eol, rdncount, opts, urlprefix ));
3cefe6 }
f1af5a
8daf5a
85beb7 static int
667295 do_entry2text(
88b830 ¤   LDAP¤   ¤   ¤   *ld,
75af18 ¤   char¤   ¤   ¤   *buf,¤  ¤   /* NULL for use-internal */
13efd8 ¤   char¤   ¤   ¤   *base,¤ ¤   /* used for search actions */
d547fa ¤   LDAPMessage¤¤   *entry,
c551f9 ¤   struct ldap_disptmpl¤   *tmpl,
--2102 00039af9339401000b5 Page 3 of tmplout.c
0ec03c ¤   char¤   ¤   ¤   **defattrs,
93e728 ¤   char¤   ¤   ¤   ***defvals,
551bf8 ¤   writeptype¤ ¤   writeproc,
414536 ¤   void¤   ¤   ¤   *writeparm,
458ea0 ¤   char¤   ¤   ¤   *eol,
7afa79 ¤   int¤¤   ¤   rdncount,
67ac49 ¤   unsigned long¤  ¤   opts,
76b2a0 ¤   char¤   ¤   ¤   *urlprefix¤ /* if non-NULL, do HTML */
115b71 )
59bb36 {
867d68 ····int¤¤   ¤   ¤   i, err, html, show, labelwidth;
90f3c0 ····int¤¤   ¤   ¤   freebuf, ·freevals;
93a031 ····char¤   ¤   ¤   *dn, **vals;
9b1a08 ····struct ldap_tmplitem¤   *rowp, *colp;
99af5a
bcfb96 ····if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
8a722d ¤   return( ld->ld_errno );
c26fe7 ····}
c5af5a
504350 ····if ( buf == NULL ) {
3c60ef ¤   if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
b83376 ¤   ····ld->ld_errno = LDAP_NO_MEMORY;
3cb1be ¤   ····free( dn );
44efe0 ¤   ····return( ld->ld_errno );
a99371 ¤   }
95ba47 ¤   freebuf = 1;
6e6a79 ····} else {
a5e09b ¤   freebuf = 0;
d36fe7 ····}
d8af5a
c71668 ····html = ( urlprefix != NULL );
9baf5a
831039 ····if ( html ) {
f3d8af ¤   /*
2336ab ¤   ·* add HTML intro. and title
27a4e3 ¤   ·*/
5b48c4 ¤   if (!(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) {
8d0bb0 ¤   ····sprintf( buf, "<HTML>%s<HEAD>%s<TITLE>%s%s - ", eol, eol, eol,
a41f5d ¤   ¤   ····( tmpl == NULL ) ? "Entry" : tmpl->dt_name );
a14747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
cc3676 ¤   ····output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL );
20c98d ¤   ····sprintf( buf, "%s</TITLE>%s</HEAD>%s<BODY>%s<H3>%s - ", eol, eol,
a22589 ¤   ¤   ····eol, eol, ( tmpl == NULL ) ? "Entry" : tmpl->dt_name );
154747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
ab3676 ¤   ····output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL );
1f9ad6 ¤   ····sprintf( buf, "</H3>%s", eol );
2a4747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
dd9371 ¤   }
ffaf5a
e2dc41 ¤   if (( opts & LDAP_DISP_OPT_NONLEAF ) != 0 &&
23bfd5 ¤   ¤   ( vals = ldap_explode_dn( dn, 0 )) != NULL ) {
91d78d ¤   ····char¤   *untagged;
44af5a
d4ea54 ¤   ····/*
40b766 ¤   ·····* add "Move Up" link
d3ed8d ¤   ·····*/
091cdf ¤   ····sprintf( buf, "<A HREF=\"%s", urlprefix );
c54553 ¤   ····for ( i = 1; vals[ i ] != NULL; ++i ) {
86141a ¤   ¤   if ( i > 1 ) {
c9ca3a ¤   ¤   ·····strcat_escaped( buf, ", " );
c70fe4 ¤   ¤   }
0f7612 ¤   ¤   strcat_escaped( buf, vals[ i ] );
d1f372 ¤   ····}
5d42f0 ¤   ····if ( vals[ 1 ] != NULL ) {
97775c ¤   ¤   untagged = strchr( vals[ 1 ], '=' );
cadfe8 ¤   ····} else {
6a9681 ¤   ¤   untagged = "=The World";
fbf372 ¤   ····}
9f46a7 ¤   ····sprintf( buf + strlen( buf ),
37d6e4 ¤   ¤   ····"%s\">Move Up To <EM>%s</EM></A>%s<BR>",
4b10ff ¤   ¤   ····( vals[ 1 ] == NULL ) ? "??one" : "",
39bca2 ¤   ¤   ····( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol, eol );
--aa0e 000666cdf1c401000b5 Page 4 of tmplout.c
514747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
64af5a
dcea54 ¤   ····/*
c472eb ¤   ·····* add "Browse" link
a5ed8d ¤   ·····*/
bb5ee4 ¤   ····untagged = strchr( vals[ 0 ], '=' );
8f1cdf ¤   ····sprintf( buf, "<A HREF=\"%s", urlprefix );
251b22 ¤   ····strcat_escaped( buf, dn );
6af4bf ¤   ····sprintf( buf + strlen( buf ),·
21bdc0 ¤   ¤   "??one?(!(objectClass=dsa))\">Browse Below <EM>%s</EM></A>%s%s",
bcacad ¤   ¤   ····( untagged != NULL ) ? untagged + 1 : vals[ 0 ], eol, eol );
5f4747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
44af5a
451c05 ¤   ····ldap_value_free( vals );
a39371 ¤   }
5caf5a
d12b77 ¤   (*writeproc)( writeparm, "<HR>", 4 );¤  /* horizontal rule */
146a79 ····} else {
77991a ¤   (*writeproc)( writeparm, "\"", 1 );
72455f ¤   output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL );
d9f976 ¤   sprintf( buf, "\"%s", eol );
c07769 ¤   (*writeproc)( writeparm, buf, strlen( buf ));
bb6fe7 ····}
3faf5a
6d11f7 ····if ( tmpl != NULL && ( opts & LDAP_DISP_OPT_AUTOLABELWIDTH ) != 0 ) {
3d4a80 ¤   labelwidth = max_label_len( tmpl ) + 3;
4a6a79 ····} else {
350e27 ¤   labelwidth = DEF_LABEL_WIDTH;;
0d6fe7 ····}
a4af5a
3481c0 ····err = LDAP_SUCCESS;
bcaf5a
1c0329 ····if ( tmpl == NULL ) {
259c95 ¤   BerElement¤ *ber;
d1678e ¤   char¤   ¤   *attr;
f4af5a
5443ee ¤   ber = NULL;
6e3d52 ¤   for ( attr = ldap_first_attribute( ld, entry, &ber );
b22488 ¤   ¤   NONFATAL_LDAP_ERR( err ) && attr != NULL;
4f853b ¤   ¤   attr = ldap_next_attribute( ld, entry, ber )) {
db1179 ¤   ····if (( vals = ldap_get_values( ld, entry, attr )) == NULL ) {
331b91 ¤   ¤   freevals = 0;
e704ed ¤   ¤   if ( defattrs != NULL ) {
9c84bb ¤   ¤   ····for ( i = 0; defattrs[ i ] != NULL; ++i ) {
8d2489 ¤   ¤   ¤   if ( strcasecmp( attr, defattrs[ i ] ) == 0 ) {
1d13b0 ¤   ¤   ¤   ····break;
15a3a6 ¤   ¤   ¤   }
b25f30 ¤   ¤   ····}
3122a7 ¤   ¤   ····if ( defattrs[ i ] != NULL ) {
f68d5e ¤   ¤   ¤   vals = defvals[ i ];
405f30 ¤   ¤   ····}
6b0fe4 ¤   ¤   }
80dfe8 ¤   ····} else {
cd414d ¤   ¤   freevals = 1;
cef372 ¤   ····}
09af5a
d23e4a ¤   ····if ( islower( *attr )) {¤   /* cosmetic -- upcase attr. name */
9ad7aa ¤   ¤   *attr = toupper( *attr );
97f372 ¤   ····}
22af5a
65d612 ¤   ····err = do_vals2text( ld, buf, vals, attr, labelwidth,
c4c2fd ¤   ¤   ····LDAP_SYN_CASEIGNORESTR, writeproc, writeparm, eol,·
0b5156 ¤   ¤   ····rdncount, urlprefix );
91793b ¤   ····if ( freevals ) {
4dba27 ¤   ¤   ldap_value_free( vals );
5cf372 ¤   ····}
f19371 ¤   }
556a79 ····} else {
82d929 ¤   for ( rowp = ldap_first_tmplrow( tmpl );
990b96 ¤   ¤   NONFATAL_LDAP_ERR( err ) && rowp != NULLTMPLITEM;
df349e ¤   ¤   rowp = ldap_next_tmplrow( tmpl, rowp )) {
66a57e ¤   ····for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
--09a3 000acf43959401000b5 Page 5 of tmplout.c
9e9ed8 ¤   ¤   ····colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
d87e79 ¤   ¤   vals = NULL;
5bc0be ¤   ¤   if ( colp->ti_attrname == NULL || ( vals = ldap_get_values( ld,
e62774 ¤   ¤   ¤   entry, colp->ti_attrname )) == NULL ) {
6d4edf ¤   ¤   ····freevals = 0;
cfce76 ¤   ¤   ····if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp,
288842 ¤   ¤   ¤   ····LDAP_DITEM_OPT_HIDEIFEMPTY ) && defattrs != NULL
e7393e ¤   ¤   ¤   ····&& colp->ti_attrname != NULL ) {
9f395a ¤   ¤   ¤   for ( i = 0; defattrs[ i ] != NULL; ++i ) {
886951 ¤   ¤   ¤   ····if ( strcasecmp( colp->ti_attrname, defattrs[ i ] )
a4b334 ¤   ¤   ¤   ¤   ····== 0 ) {
5ff622 ¤   ¤   ¤   ¤   break;
5cda85 ¤   ¤   ¤   ····}
aca3a6 ¤   ¤   ¤   }
437ecd ¤   ¤   ¤   if ( defattrs[ i ] != NULL ) {
9c1ea1 ¤   ¤   ¤   ····vals = defvals[ i ];
f2a3a6 ¤   ¤   ¤   }
245f30 ¤   ¤   ····}
2f45a6 ¤   ¤   } else {
961403 ¤   ¤   ····freevals = 1;
fdc9e7 ¤   ¤   ····if ( LDAP_IS_TMPLITEM_OPTION_SET( colp,
5673a3 ¤   ¤   ¤   ····LDAP_DITEM_OPT_SORTVALUES ) && vals[ 0 ] != NULL
cefaa8 ¤   ¤   ¤   ····&& vals[ 1 ] != NULL ) {
f5be97 ¤   ¤   ¤   ldap_sort_values( ld, vals, ldap_sort_strcasecmp );
e55f30 ¤   ¤   ····}
860fe4 ¤   ¤   }
53af5a
891b17 ¤   ¤   /*
443ec6 ¤   ¤   ·* don't bother even calling do_vals2text() if no values
7ec615 ¤   ¤   ·* or boolean with value false and "hide if false" option set
8c9de3 ¤   ¤   ·*/
bf621e ¤   ¤   show = ( vals != NULL && vals[ 0 ] != NULL );
82d599 ¤   ¤   if ( show && LDAP_GET_SYN_TYPE( colp->ti_syntaxid )
0245bd ¤   ¤   ¤   == LDAP_SYN_TYPE_BOOLEAN && LDAP_IS_TMPLITEM_OPTION_SET(
232720 ¤   ¤   ¤   colp, LDAP_DITEM_OPT_HIDEIFFALSE ) &&
1761f1 ¤   ¤   ¤   toupper( vals[ 0 ][ 0 ] ) != 'T' ) {
fee067 ¤   ¤   ····show = 0;
810fe4 ¤   ¤   }
edaf5a
60ec45 ¤   ¤   if ( colp->ti_syntaxid == LDAP_SYN_SEARCHACTION ) {
3cdc1d ¤   ¤   ····if (( opts & LDAP_DISP_OPT_DOSEARCHACTIONS ) != 0 ) {
40b037 ¤   ¤   ¤   if ( colp->ti_attrname == NULL || ( show &&
d54744 ¤   ¤   ¤   ¤   toupper( vals[ 0 ][ 0 ] ) == 'T' )) {
0517d3 ¤   ¤   ¤   ····err = searchaction( ld, buf, base, entry, dn, colp,
589f55 ¤   ¤   ¤   ¤   ····labelwidth, rdncount, writeproc,
da528a ¤   ¤   ¤   ¤   ····writeparm, eol, urlprefix );
eda3a6 ¤   ¤   ¤   }
665f30 ¤   ¤   ····}
7ce067 ¤   ¤   ····show = 0;
7c0fe4 ¤   ¤   }
adaf5a
8bd635 ¤   ¤   if ( show ) {
9ec2dc ¤   ¤   ····err = do_vals2text( ld, buf, vals, colp->ti_label,
656d4a ¤   ¤   ¤   labelwidth, colp->ti_syntaxid, writeproc, writeparm,
4961ac ¤   ¤   ¤   eol, rdncount, urlprefix );
250fe4 ¤   ¤   }
0baf5a
faf2c4 ¤   ¤   if ( freevals ) {
13216d ¤   ¤   ····ldap_value_free( vals );
ce0fe4 ¤   ¤   }
66f372 ¤   ····}
469371 ¤   }
b66fe7 ····}
feaf5a
84f2df ····if ( html ·&& !(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) {
a792ad ¤   sprintf( buf, "</BODY>%s</HTML>%s", eol, eol );
e17769 ¤   (*writeproc)( writeparm, buf, strlen( buf ));
716fe7 ····}
f6af5a
6726cd ····free( dn );
ddbb94 ····if ( freebuf ) {
ac5bb5 ¤   free( buf );
--bf65 00055bebba2401000b5 Page 6 of tmplout.c
9f6fe7 ····}
86af5a
9c9779 ····return( err );
d1efe6 }
66af5a
7267c5 ¤
9e4d2f int
b69109 ldap_entry2text_search(
c2b830 ¤   LDAP¤   ¤   ¤   *ld,
5326ae ¤   char¤   ¤   ¤   *dn,¤   ¤   /* if NULL, use entry */
e4527d ¤   char¤   ¤   ¤   *base,¤ ¤   /* if NULL, no search actions */
5f4d04 ¤   LDAPMessage¤¤   *entry, ¤   /* if NULL, use dn */
eb0084 ¤   struct ldap_disptmpl*¤  tmpllist,¤  /* if NULL, load default file */
cdc03c ¤   char¤   ¤   ¤   **defattrs,
75e728 ¤   char¤   ¤   ¤   ***defvals,
d91bf8 ¤   writeptype¤ ¤   writeproc,
944536 ¤   void¤   ¤   ¤   *writeparm,
cf8ea0 ¤   char¤   ¤   ¤   *eol,
097cc0 ¤   int¤¤   ¤   rdncount,¤  /* if 0, display full DN */
024f07 ¤   unsigned long¤  ¤   opts
ee5b71 )
37bb36 {
e4d348 ····Debug( LDAP_DEBUG_TRACE, "ldap_entry2text_search\n", 0, 0, 0 );
faaf5a
5b59db ····return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs,
8d7e33 ¤   ····defvals, writeproc, writeparm, eol, rdncount, opts, NULL ));
68efe6 }
dbaf5a
0aaf5a
4baf5a
444d2f int
32a172 ldap_entry2html_search(
81b830 ¤   LDAP¤   ¤   ¤   *ld,
a126ae ¤   char¤   ¤   ¤   *dn,¤   ¤   /* if NULL, use entry */
dd527d ¤   char¤   ¤   ¤   *base,¤ ¤   /* if NULL, no search actions */
ac4d04 ¤   LDAPMessage¤¤   *entry, ¤   /* if NULL, use dn */
650084 ¤   struct ldap_disptmpl*¤  tmpllist,¤  /* if NULL, load default file */
13c03c ¤   char¤   ¤   ¤   **defattrs,
a2e728 ¤   char¤   ¤   ¤   ***defvals,
0b1bf8 ¤   writeptype¤ ¤   writeproc,
d34536 ¤   void¤   ¤   ¤   *writeparm,
828ea0 ¤   char¤   ¤   ¤   *eol,
6d7cc0 ¤   int¤¤   ¤   rdncount,¤  /* if 0, display full DN */
9fac49 ¤   unsigned long¤  ¤   opts,
603364 ¤   char¤   ¤   ¤   *urlprefix
e95b71 )
b5bb36 {
2f6062 ····Debug( LDAP_DEBUG_TRACE, "ldap_entry2html_search\n", 0, 0, 0 );
23af5a
1359db ····return( do_entry2text_search( ld, dn, base, entry, tmpllist, defattrs,
9880d3 ¤   ····defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix ));
02efe6 }
b3af5a
69af5a
babeb7 static int
fcc4be do_entry2text_search(
62b830 ¤   LDAP¤   ¤   ¤   *ld,
9826ae ¤   char¤   ¤   ¤   *dn,¤   ¤   /* if NULL, use entry */
06527d ¤   char¤   ¤   ¤   *base,¤ ¤   /* if NULL, no search actions */
bd4d04 ¤   LDAPMessage¤¤   *entry, ¤   /* if NULL, use dn */
100084 ¤   struct ldap_disptmpl*¤  tmpllist,¤  /* if NULL, load default file */
91c03c ¤   char¤   ¤   ¤   **defattrs,
ece728 ¤   char¤   ¤   ¤   ***defvals,
121bf8 ¤   writeptype¤ ¤   writeproc,
a64536 ¤   void¤   ¤   ¤   *writeparm,
058ea0 ¤   char¤   ¤   ¤   *eol,
327cc0 ¤   int¤¤   ¤   rdncount,¤  /* if 0, display full DN */
d4ac49 ¤   unsigned long¤  ¤   opts,
1e3364 ¤   char¤   ¤   ¤   *urlprefix
b85b71 )
b2bb36 {
55343e ····int¤¤   ¤   ¤   err, freedn, freetmpls, html;
--acd1 00068b09763401000b5 Page 7 of tmplout.c
b047a3 ····char¤   ¤   ¤   *buf, **fetchattrs, **vals;
90f523 ····LDAPMessage¤¤   ¤   *ldmp;
50d50a ····struct ldap_disptmpl¤   *tmpl;
a8174c ····struct timeval¤ ¤   timeout;
f4af5a
af0dc3 ····if ( dn == NULL && entry == NULLMSG ) {
daba3f ¤   ld->ld_errno = LDAP_PARAM_ERROR;
63722d ¤   return( ld->ld_errno );
a86fe7 ····}
ebaf5a
a11668 ····html = ( urlprefix != NULL );
6faf5a
4ea754 ····timeout.tv_sec = SEARCH_TIMEOUT_SECS;
be9c13 ····timeout.tv_usec = 0;
ecaf5a
696428 ····if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
422eef ¤   ld->ld_errno = LDAP_NO_MEMORY;
6f722d ¤   return( ld->ld_errno );
7d6fe7 ····}
a6af5a
fd277d ····freedn = freetmpls = 0;
8395f0 ····tmpl = NULL;
1caf5a
039bb5 ····if ( tmpllist == NULL ) {
a92d8b ¤   if (( err = ldap_init_templates( TEMPLATEFILE, &tmpllist )) != 0 ) {
b0dacf ¤   ····sprintf( buf, "%sUnable to read template file %s (error %d)%s%s",
27fdf6 ¤   ¤   ····html ? "<!-- " : "", TEMPLATEFILE, err,
a40955 ¤   ¤   ····html ? "-->" : "", eol );
114747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
1f9371 ¤   }
4c4c15 ¤   freetmpls = 1;
046fe7 ····}
2baf5a
35bc90 ····if ( dn == NULL ) {
d33127 ¤   if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
b258c8 ¤   ····free( buf );
a95377 ¤   ····if ( freetmpls ) {
f21c6e ¤   ¤   ldap_free_templates( tmpllist );
ccf372 ¤   ····}
ddefe0 ¤   ····return( ld->ld_errno );
bc9371 ¤   }
b1f2bd ¤   freedn = 1;
236fe7 ····}
5aaf5a
c8af5a
6f81f7 ····if ( tmpllist != NULL ) {
618c28 ¤   ldmp = NULLMSG;
13af5a
21706c ¤   if ( entry == NULL ) {
d58c72 ¤   ····char¤   *ocattrs[2];
00af5a
ac7098 ¤   ····ocattrs[0] = OCATTRNAME;
f7c444 ¤   ····ocattrs[1] = NULL;
3fed07 #ifdef CLDAP
a9d1d9 ¤   ····if ( LDAP_IS_CLDAP( ld ))
e99021 ¤   ¤   ····err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE,
9ea566 ¤   ¤   ¤   "objectClass=*", ocattrs, 0, &ldmp, NULL );
368415 ¤   ····else
726b1c #endif /* CLDAP */
766cf0 ¤   ¤   ····err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE,
5e07d2 ¤   ¤   ¤   ····"objectClass=*", ocattrs, 0, &timeout, &ldmp );
caaf5a
8b410e ¤   ····if ( err == LDAP_SUCCESS ) {
713b96 ¤   ¤   entry = ldap_first_entry( ld, ldmp );
87f372 ¤   ····}
289371 ¤   }
30af5a
d86a2e ¤   if ( entry != NULL ) {
e9e770 ¤   ····vals = ldap_get_values( ld, entry, OCATTRNAME );
a766d8 ¤   ····tmpl = ldap_oc2template( vals, tmpllist );
ca5a9b ¤   ····if ( vals != NULL ) {
68ba27 ¤   ¤   ldap_value_free( vals );
--0489 000bf7b03e9401000b5 Page 8 of tmplout.c
8bf372 ¤   ····}
6d9371 ¤   }
daf6b6 ¤   if ( ldmp != NULL ) {
204c41 ¤   ····ldap_msgfree( ldmp );
3a9371 ¤   }
e66fe7 ····}
09af5a
181d12 ····entry = NULL;
61af5a
3d0329 ····if ( tmpl == NULL ) {
3b62c3 ¤   fetchattrs = NULL;
836a79 ····} else {
b5734e ¤   fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER );
a66fe7 ····}
88af5a
5eed07 #ifdef CLDAP
44e6d1 ····if ( LDAP_IS_CLDAP( ld ))
89c109 ¤   err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
f351e5 ¤   ¤   fetchattrs, 0, &ldmp, NULL );
a4842c ····else
746b1c #endif /* CLDAP */
649d53 ¤   err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*",
b0f934 ¤   ¤   fetchattrs, 0, &timeout, &ldmp );
8eaf5a
23929a ····if ( freedn ) {
a6d48d ¤   free( dn );
906fe7 ····}
0e365e ····if ( fetchattrs != NULL ) {
e0aee7 ¤   ldap_value_free( fetchattrs );
ab6fe7 ····}
9daf5a
e1a081 ····if ( err != LDAP_SUCCESS ||
5ed2bf ¤   ····( entry = ldap_first_entry( ld, ldmp )) == NULL ) {
f8be65 ¤   if ( freetmpls ) {
332386 ············ldap_free_templates( tmpllist );
747fb0 ········}
315bb5 ¤   free( buf );
ab722d ¤   return( ld->ld_errno );
5b6fe7 ····}
eeaf5a
f76b46 ····err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals,
ef10b4 ¤   ····writeproc, writeparm, eol, rdncount, opts, urlprefix );
42af5a
ac1943 ····free( buf );
0fb196 ····if ( freetmpls ) {
2c1983 ¤   ldap_free_templates( tmpllist );
e56fe7 ····}
0fc515 ····ldap_msgfree( ldmp );
ed9779 ····return( err );
03efe6 }
2cda86 ¤   ····
26af5a
4e4d2f int
63011e ldap_vals2text(
2db830 ¤   LDAP¤   ¤   ¤   *ld,
b0edfb ¤   char¤   ¤   ¤   *buf,¤  ¤   /* NULL for "use internal" */
3e2874 ¤   char¤   ¤   ¤   **vals,
c2c223 ¤   char¤   ¤   ¤   *label,
58f234 ¤   int¤¤   ¤   labelwidth,¤/* 0 means use default */
bad1d4 ¤   unsigned long¤  ¤   syntaxid,
df1bf8 ¤   writeptype¤ ¤   writeproc,
e04536 ¤   void¤   ¤   ¤   *writeparm,
618ea0 ¤   char¤   ¤   ¤   *eol,
71da13 ¤   int¤¤   ¤   rdncount
835b71 )
debb36 {
f80a13 ····Debug( LDAP_DEBUG_TRACE, "ldap_vals2text\n", 0, 0, 0 );
edaf5a
8edd61 ····return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid,
a40a71 ¤   ¤   writeproc, writeparm, eol, rdncount, NULL ));
abefe6 }
bfaf5a
--a966 0007600a2fd401000b5 Page 9 of tmplout.c
e0af5a
e54d2f int
f823ff ldap_vals2html(
adb830 ¤   LDAP¤   ¤   ¤   *ld,
e4edfb ¤   char¤   ¤   ¤   *buf,¤  ¤   /* NULL for "use internal" */
5f2874 ¤   char¤   ¤   ¤   **vals,
cdc223 ¤   char¤   ¤   ¤   *label,
2bf234 ¤   int¤¤   ¤   labelwidth,¤/* 0 means use default */
12d1d4 ¤   unsigned long¤  ¤   syntaxid,
b51bf8 ¤   writeptype¤ ¤   writeproc,
7b4536 ¤   void¤   ¤   ¤   *writeparm,
1a8ea0 ¤   char¤   ¤   ¤   *eol,
6dfa79 ¤   int¤¤   ¤   rdncount,
b83364 ¤   char¤   ¤   ¤   *urlprefix
405b71 )
5bbb36 {
36aa0d ····Debug( LDAP_DEBUG_TRACE, "ldap_vals2html\n", 0, 0, 0 );
47af5a
861369 ····if ( urlprefix == NULL ) {
63e01c ¤   urlprefix = DEF_LDAP_URL_PREFIX;
986fe7 ····}
dfaf5a
01dd61 ····return( do_vals2text( ld, buf, vals, label, labelwidth, syntaxid,
fc7fd0 ¤   ¤   writeproc, writeparm, eol, rdncount, urlprefix ));
42efe6 }
4aaf5a
abaf5a
97beb7 static int
35b8c1 do_vals2text(
2bb830 ¤   LDAP¤   ¤   ¤   *ld,
0aedfb ¤   char¤   ¤   ¤   *buf,¤  ¤   /* NULL for "use internal" */
862874 ¤   char¤   ¤   ¤   **vals,
fbc223 ¤   char¤   ¤   ¤   *label,
f7f234 ¤   int¤¤   ¤   labelwidth,¤/* 0 means use default */
18d1d4 ¤   unsigned long¤  ¤   syntaxid,
5b1bf8 ¤   writeptype¤ ¤   writeproc,
df4536 ¤   void¤   ¤   ¤   *writeparm,
cc8ea0 ¤   char¤   ¤   ¤   *eol,
12fa79 ¤   int¤¤   ¤   rdncount,
b03364 ¤   char¤   ¤   ¤   *urlprefix
ca5b71 )
dabb36 {
590e7b ····int¤¤   i, html, writeoutval, freebuf, notascii;
61a397 ····char¤   *p, *s, *outval;
25af5a
3aaf5a
6bc98d ····if ( vals == NULL ) {
42aced ¤   return( LDAP_SUCCESS );
c96fe7 ····}
72af5a
661668 ····html = ( urlprefix != NULL );
5aaf5a
733ac0 ····switch( LDAP_GET_SYN_TYPE( syntaxid )) {
dd2772 ····case LDAP_SYN_TYPE_TEXT:
ca6c72 ····case LDAP_SYN_TYPE_BOOLEAN:
b30955 ¤   break;¤ ¤   /* we only bother with these two types... */
d6b53c ····default:
3caced ¤   return( LDAP_SUCCESS );
496fe7 ····}
66af5a
8b5376 ····if ( labelwidth == 0 || labelwidth < 0 ) {
a977ee ¤   labelwidth = DEF_LABEL_WIDTH;
816fe7 ····}
5caf5a
634350 ····if ( buf == NULL ) {
ee60ef ¤   if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
783376 ¤   ····ld->ld_errno = LDAP_NO_MEMORY;
8aefe0 ¤   ····return( ld->ld_errno );
779371 ¤   }
35ba47 ¤   freebuf = 1;
976a79 ····} else {
76e09b ¤   freebuf = 0;
--4e0e 0007b2b2bd7401000b5 Page 10 of tmplout.c
9f6fe7 ····}
86af5a
5cb202 ····output_label( buf, label, labelwidth, writeproc, writeparm, eol, html );
37af5a
097df0 ····for ( i = 0; vals[ i ] != NULL; ++i ) {
794616 ¤   for ( p = vals[ i ]; *p != '\0'; ++p ) {
203d67 ¤   ····if ( !isascii( *p )) {
f42f68 ¤   ¤   break;
3cf372 ¤   ····}
ee9371 ¤   }
754978 ¤   notascii = ( *p != '\0' );
560990 ¤   outval = notascii ? "(unable to display non-ASCII text value)"
054005 ¤   ¤   : vals[ i ];
8daf5a
02f25d ¤   writeoutval = 0;¤   /* if non-zero, write outval after switch */
06af5a
7da1b1 ¤   switch( syntaxid ) {
b75b9e ¤   case LDAP_SYN_CASEIGNORESTR:
72f8ef ¤   ····++writeoutval;
edcafa ¤   ····break;
6baf5a
0b2279 ¤   case LDAP_SYN_RFC822ADDR:
322aa3 ¤   ····if ( html ) {
ff1b1a ¤   ¤   strcpy( buf, "<DD><A HREF=\"mailto:" );
94506b ¤   ¤   strcat_escaped( buf, outval );
4a2487 ¤   ¤   sprintf( buf + strlen( buf ), "\">%s</A><BR>%s", outval, eol );
28d968 ¤   ¤   (*writeproc)( writeparm, buf, strlen( buf ));
d5dfe8 ¤   ····} else {
b6b121 ¤   ¤   ++writeoutval;
97f372 ¤   ····}
25cafa ¤   ····break;
06af5a
9a7a55 ¤   case LDAP_SYN_DN:¤  /* for now */
dffd12 ¤   ····output_dn( buf, outval, labelwidth, rdncount, writeproc,
5006af ¤   ¤   ····writeparm, eol, urlprefix );
efcafa ¤   ····break;
beaf5a
d32790 ¤   case LDAP_SYN_MULTILINESTR:
fd31e5 ¤   ····if ( i > 0 && !html ) {
8232e0 ¤   ¤   output_label( buf, label, labelwidth, writeproc,
9589bc ¤   ¤   ¤   writeparm, eol, html );
23f372 ¤   ····}
5eaf5a
ff874d ¤   ····p = s = outval;
8022aa ¤   ····while (( s = strchr( s, '$' )) != NULL ) {
45fe98 ¤   ¤   *s++ = '\0';
331493 ¤   ¤   while ( isspace( *s )) {
28996f ¤   ¤   ····++s;
280fe4 ¤   ¤   }
38b858 ¤   ¤   if ( html ) {
b75224 ¤   ¤   ····sprintf( buf, "<DD>%s<BR>%s", p, eol );
a445a6 ¤   ¤   } else {
c71782 ¤   ¤   ····sprintf( buf, "%-*s%s%s", labelwidth, " ", p, eol );
220fe4 ¤   ¤   }
9bd968 ¤   ¤   (*writeproc)( writeparm, buf, strlen( buf ));
f48334 ¤   ¤   p = s;
d4f372 ¤   ····}
019347 ¤   ····outval = p;
93f8ef ¤   ····++writeoutval;
1ecafa ¤   ····break;
48af5a
5d45d3 ¤   case LDAP_SYN_BOOLEAN:
98bbdc ¤   ····outval = toupper( outval[ 0 ] ) == 'T' ? "TRUE" : "FALSE";
45f8ef ¤   ····++writeoutval;
7acafa ¤   ····break;
f1af5a
509e5f ¤   case LDAP_SYN_TIME:
f8bc0d ¤   case LDAP_SYN_DATE:
4ba190 ¤   ····outval = time2text( outval, syntaxid == LDAP_SYN_DATE );
c0f8ef ¤   ····++writeoutval;
9acafa ¤   ····break;
7baf5a
--3645 000ff0546c9401000b5 Page 11 of tmplout.c
fb8d4b ¤   case LDAP_SYN_LABELEDURL:
00bf60 ¤   ····if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) {
c47976 ¤   ¤   *p++ = '\0';
82bcfd ¤   ¤   while ( isspace( *p )) {
65760b ¤   ¤   ····++p;
da0fe4 ¤   ¤   }
115d98 ¤   ¤   s = outval;
e8cd2d ¤   ····} else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) {
fcfe98 ¤   ¤   *s++ = '\0';
711493 ¤   ¤   while ( isspace( *s )) {
89996f ¤   ¤   ····++s;
9d0fe4 ¤   ¤   }
dfda76 ¤   ¤   p = outval;
79dfe8 ¤   ····} else {
b0953e ¤   ¤   s = "URL";
23da76 ¤   ¤   p = outval;
87f372 ¤   ····}
baaf5a
e3ea54 ¤   ····/*
2e0aa2 ¤   ·····* at this point `s' points to the label & `p' to the URL
a4ed8d ¤   ·····*/
1e2aa3 ¤   ····if ( html ) {
cfab73 ¤   ¤   sprintf( buf, "<DD><A HREF=\"%s\">%s</A><BR>%s", p, s, eol );
6bdfe8 ¤   ····} else {
ac406d ¤   ¤   sprintf( buf, "%-*s%s%s%-*s%s%s", labelwidth, " ",
acc3ce ¤   ¤   ····s, eol, labelwidth + 2, " ",p , eol );
fff372 ¤   ····}
dd4747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
12cafa ¤   ····break;
b7af5a
6e2f72 ¤   default:
3d67e4 ¤   ····sprintf( buf, " Can't display item type %ld%s",
1af0d8 ¤   ¤   ····syntaxid, eol );
f44747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
ad9371 ¤   }
4faf5a
9bf29e ¤   if ( writeoutval ) {
452aa3 ¤   ····if ( html ) {
5f7b07 ¤   ¤   sprintf( buf, "<DD>%s<BR>%s", outval, eol );
11dfe8 ¤   ····} else {
0f57d6 ¤   ¤   sprintf( buf, "%-*s%s%s", labelwidth, " ", outval, eol );
87f372 ¤   ····}
8a4747 ¤   ····(*writeproc)( writeparm, buf, strlen( buf ));
cd9371 ¤   }
6b6fe7 ····}
c2af5a
5bbb94 ····if ( freebuf ) {
3f5bb5 ¤   free( buf );
d06fe7 ····}
2caf5a
fd9c7e ····return( LDAP_SUCCESS );
35efe6 }
87af5a
5faf5a
81beb7 static int
0fd38e max_label_len( struct ldap_disptmpl *tmpl )
e7bb36 {
511a08 ····struct ldap_tmplitem¤   *rowp, *colp;
2c3e90 ····int¤¤   ¤   ¤   len, maxlen;
74af5a
81cc9d ····maxlen = 0;
b6af5a
0d9a04 ····for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM;
885605 ¤   ····rowp = ldap_next_tmplrow( tmpl, rowp )) {
1c1049 ¤   for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
c8cc83 ¤   ¤   colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
73e048 ¤   ····if (( len = strlen( colp->ti_label )) > maxlen ) {
e1ef5e ¤   ¤   maxlen = len;
5ef372 ¤   ····}
1d9371 ¤   }
0a6fe7 ····}
ffaf5a
--b3cf 000858fb9aa401000b5 Page 12 of tmplout.c
6209fd ····return( maxlen );
17efe6 }
e2af5a
63af5a
16beb7 static int
702b9c output_label( char *buf, char *label, int width, writeptype writeproc,
dfd749 ¤   void *writeparm, char *eol, int html )
f6bb36 {
fee7fd ····char¤   *p;
51af5a
341039 ····if ( html ) {
7fa04e ¤   sprintf( buf, "<DT><B>%s</B>", label );
956a79 ····} else {
c08d71 ¤   sprintf( buf, " %s:", label );
c22217 ¤   p = buf + strlen( buf );
c0af5a
c78b45 ¤   while ( p - buf < width ) {
638b4a ¤   ····*p++ = ' ';
c19371 ¤   }
12af5a
46ddb4 ¤   *p = '\0';
e9ca4d ¤   strcat( buf, eol );
e36fe7 ····}
b4af5a
7a9055 ····return ((*writeproc)( writeparm, buf, strlen( buf )));
a9efe6 }
c7af5a
68af5a
91beb7 static int
1179b2 output_dn( char *buf, char *dn, int width, int rdncount,
039a39 ¤   writeptype writeproc, void *writeparm, char *eol, char *urlprefix )
51bb36 {
f2b3f7 ····char¤   **dnrdns;
0f0230 ····int¤¤   i;
03af5a
177852 ····if (( dnrdns = ldap_explode_dn( dn, 1 )) == NULL ) {
797360 ¤   return( -1 );
d06fe7 ····}
b0af5a
df092b ····if ( urlprefix != NULL ) {
5adc47 ¤   sprintf( buf, "<DD><A HREF=\"%s", urlprefix );
2a47e2 ¤   strcat_escaped( buf, dn );
0898f3 ¤   strcat( buf, "\">" );
6e76bb ····} else if ( width > 0 ) {
94db68 ¤   sprintf( buf, "%-*s", width, " " );
a26a79 ····} else {
c57eea ¤   *buf = '\0';
5c6fe7 ····}
1aaf5a
5d5e55 ····for ( i = 0; dnrdns[ i ] != NULL && ( rdncount == 0 || i < rdncount );
269c3d ¤   ····++i ) {
632bd8 ¤   if ( i > 0 ) {
a179b5 ¤   ····strcat( buf, ", " );
8b9371 ¤   }
004a47 ¤   strcat( buf, dnrdns[ i ] );
336fe7 ····}
31af5a
55092b ····if ( urlprefix != NULL ) {
23fe0b ¤   strcat( buf, "</A><BR>" );
916fe7 ····}
19af5a
c33db8 ····ldap_value_free( dnrdns );
c6af5a
ee0f56 ····strcat( buf, eol );
f5af5a
929055 ····return ((*writeproc)( writeparm, buf, strlen( buf )));
a6efe6 }
7faf5a
63af5a
dcaf5a
35b112 #define HREF_CHAR_ACCEPTABLE( c )¤  (( c >= '-' && c <= '9' ) ||¤   \
856ac6 ¤   ¤   ¤   ¤   ¤   ·( c >= '@' && c <= 'Z' ) ||¤   \
--b5ca 000d3bb8dc4401000b5 Page 13 of tmplout.c
c4f022 ¤   ¤   ¤   ¤   ¤   ·( c == '_' ) ||¤   ¤   \
1672cb ¤   ¤   ¤   ¤   ¤   ·( c >= 'a' && c <= 'z' ))
17af5a
382978 static void
9cd3c3 strcat_escaped( char *s1, char *s2 )
46bb36 {
c47ff1 ····char¤   *p, *q;
024f5b ····char¤   *hexdig = "0123456789ABCDEF";
d1af5a
8e7575 ····p = s1 + strlen( s1 );
4a8efa ····for ( q = s2; *q != '\0'; ++q ) {
e2e4cd ¤   if ( HREF_CHAR_ACCEPTABLE( *q )) {
7d74fe ¤   ····*p++ = *q;
91f037 ¤   } else {
74e51d ¤   ····*p++ = '%';
178ed6 ¤   ····*p++ = hexdig[ *q >> 4 ];
1d945d ¤   ····*p++ = hexdig[ *q & 0x0F ];
209371 ¤   }
786fe7 ····}
8caf5a
f13a11 ····*p = '\0';
45efe6 }
d9af5a
1daf5a
23c98e #define GET2BYTENUM( p )¤   (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
93af5a
21083f static char *
2396cf time2text( char *ldtimestr, int dateonly )
94bb36 {
b292bf ····struct tm¤  ¤   t;
7fe395 ····char¤   ¤   *p, *timestr, zone, *fmterr = "badly formatted time";
9cbb8a ····time_t¤ ¤   gmttime;
55af5a
69eb15 ····memset( (char *)&t, 0, sizeof( struct tm ));
d0ae81 ····if ( (int) strlen( ldtimestr ) < 13 ) {
1b3827 ¤   return( fmterr );
4e6fe7 ····}
94af5a
2ce1a2 ····for ( p = ldtimestr; p - ldtimestr < 12; ++p ) {
0d4502 ¤   if ( !isdigit( *p )) {
f5746d ¤   ····return( fmterr );
4b9371 ¤   }
0a6fe7 ····}
2baf5a
065fbd ····p = ldtimestr;
c4223b ····t.tm_year = GET2BYTENUM( p ); p += 2;
ce0bf4 ····t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
af142c ····t.tm_mday = GET2BYTENUM( p ); p += 2;
1336a4 ····t.tm_hour = GET2BYTENUM( p ); p += 2;
142bd5 ····t.tm_min = GET2BYTENUM( p ); p += 2;
42446f ····t.tm_sec = GET2BYTENUM( p ); p += 2;
faaf5a
3a4f63 ····if (( zone = *p ) == 'Z' ) {¤   /* GMT */
c2dd87 ¤   zone = '\0';¤   /* no need to indicate on screen, so we make it null */
656fe7 ····}
04af5a
f219e1 ····gmttime = gtime( &t );
59753b ····timestr = ctime( &gmttime );
36af5a
2d968f ····timestr[ strlen( timestr ) - 1 ] = zone;¤   /* replace trailing newline */
f65629 ····if ( dateonly ) {
601b66 ¤   strcpy( timestr + 11, timestr + 20 );
966fe7 ····}
d9af5a
c7d085 ····return( timestr );
ddefe6 }
c1af5a
13af5a
4aaf5a
ac4df8 /* gtime.c - inverse gmtime */
99af5a
d364a8 #if !defined( MACOS ) && !defined( _WIN32 ) && !defined( DOS )
--dd3d 00062ecfe00401000b5 Page 14 of tmplout.c
d35d8c #include <sys/time.h>
8cf2e5 #endif /* !MACOS */
5eaf5a
09e294 /* gtime(): the inverse of localtime().
cb2d1e ¤   This routine was supplied by Mike Accetta at CMU many years ago.
c5495d ·*/
cbaf5a
1bac86 static int¤ dmsize[] = {
740543 ····31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
bb82f7 };
9caf5a
d69c97 #define¤dysize(y)¤  \
be52f2 ¤   (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
f3af5a
1bcd07 #define¤YEAR(y)¤¤   ((y) >= 100 ? (y) : (y) + 1900)
5aaf5a
b724b6 /* ¥
23495d ·*/
4baf5a
bbffda static long¤gtime ( struct tm *tm )
01bb36 {
fc956a ····register int ···i,
ea5ade ····················sec,
f1a999 ····················mins,
03dfee ····················hour,
e4146e ····················mday,
33acf7 ····················mon,
f4bc09 ····················year;
8d209f ····register long ··result;
2aaf5a
bc976d ····if ((sec = tm -> tm_sec) < 0 || sec > 59
12a414 ¤   ····|| (mins = tm -> tm_min) < 0 || mins > 59
9f074b ¤   ····|| (hour = tm -> tm_hour) < 0 || hour > 24
73084e ¤   ····|| (mday = tm -> tm_mday) < 1 || mday > 31
cc06ca ¤   ····|| (mon = tm -> tm_mon + 1) < 1 || mon > 12)
c65011 ¤   return ((long) -1);
5807cf ····if (hour == 24) {
bf5f50 ¤   hour = 0;
3dc4a9 ¤   mday++;
c56fe7 ····}
cd26af ····year = YEAR (tm -> tm_year);
3baf5a
48b309 ····result = 0L;
b90890 ····for (i = 1970; i < year; i++)
a2c300 ¤   result += dysize (i);
94cc21 ····if (dysize (year) == 366 && mon >= 3)
034db9 ¤   result++;
f2dac0 ····while (--mon)
d6f0e3 ¤   result += dmsize[mon - 1];
253afb ····result += mday - 1;
a75631 ····result = 24 * result + hour;
d7182b ····result = 60 * result + mins;
c9ff8d ····result = 60 * result + sec;
c7af5a
8314bd ····return result;
67efe6 }
c1af5a
e3beb7 static int
635c3d searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, char *dn,
5c6a13 ¤   struct ldap_tmplitem *tip, int labelwidth, int rdncount,
669a39 ¤   writeptype writeproc, void *writeparm, char *eol, char *urlprefix )
fcbb36 {
39d6f1 ····int¤¤   ¤   err, lderr, i, count, html;
554cda ····char¤   ¤   **vals, **members;
890b9b ····char¤   ¤   *value, *filtpattern, *attr, *selectname;
44b4af ····char¤   ¤   *retattrs[2], filter[ 256 ];
d3197d ····LDAPMessage¤¤   *ldmp;
679dca ····struct timeval¤ timeout;
82af5a
a91668 ····html = ( urlprefix != NULL );
bdaf5a
628e9a ····for ( i = 0; tip->ti_args != NULL && tip->ti_args[ i ] != NULL; ++i ) {
--e9ed 0007548fcbf401000b5 Page 15 of tmplout.c
0781c7 ¤   ;
d36fe7 ····}
5d6504 ····if ( i < 3 ) {
cff822 ¤   return( LDAP_PARAM_ERROR );
026fe7 ····}
ea1b88 ····attr = tip->ti_args[ 0 ];
0c953b ····filtpattern = tip->ti_args[ 1 ];
1d47e7 ····retattrs[ 0 ] = tip->ti_args[ 2 ];
3e0e35 ····retattrs[ 1 ] = NULL;
3d5ebe ····selectname = tip->ti_args[ 3 ];
5daf5a
457d04 ····vals = NULL;
1d3bc7 ····if ( attr == NULL ) {
555b1e ¤   value = NULL;
6c41b1 ····} else if ( strcasecmp( attr, "-dnb" ) == 0 ) {
18f822 ¤   return( LDAP_PARAM_ERROR );
63990b ····} else if ( strcasecmp( attr, "-dnt" ) == 0 ) {
4500b5 ¤   value = dn;
4c78ba ····} else if (( vals = ldap_get_values( ld, entry, attr )) != NULL ) {
6d5843 ¤   value = vals[ 0 ];
b56a79 ····} else {
1c5b1e ¤   value = NULL;
ac6fe7 ····}
f8af5a
6ac655 ····ldap_build_filter( filter, sizeof( filter ), filtpattern, NULL, NULL, NULL,
bbd929 ¤   ····value, NULL );
b0af5a
8e1039 ····if ( html ) {
64d8af ¤   /*
643b2e ¤   ·* if we are generating HTML, we add an HREF link that embodies this
f609e3 ¤   ·* search action as an LDAP URL, instead of actually doing the search
607d62 ¤   ·* now.
2fa4e3 ¤   ·*/
f5c355 ¤   sprintf( buf, "<DT><A HREF=\"%s", urlprefix );
82a061 ¤   if ( base != NULL ) {
f15221 ¤   ····strcat_escaped( buf, base );
559371 ¤   }
66755c ¤   strcat( buf, "??sub?" );
6c6f06 ¤   strcat_escaped( buf, filter );
d84168 ¤   sprintf( buf + strlen( buf ), "\"><B>%s</B></A><DD><BR>%s",
0893c4 ¤   ¤   tip->ti_label, eol );
22b164 ¤   if ((*writeproc)( writeparm, buf, strlen( buf )) < 0 ) {
6d0ebf ¤   ····return( LDAP_LOCAL_ERROR );
439371 ¤   }
1baced ¤   return( LDAP_SUCCESS );
6a6fe7 ····}
a1af5a
65a754 ····timeout.tv_sec = SEARCH_TIMEOUT_SECS;
079c13 ····timeout.tv_usec = 0;
f3af5a
eeed07 #ifdef CLDAP
cae6d1 ····if ( LDAP_IS_CLDAP( ld ))
688e61 ¤   lderr = cldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs,
ee2e3e ¤   ¤   0, &ldmp, NULL );
89842c ····else
f36b1c #endif /* CLDAP */
e7e55c ¤   lderr = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs,
600b46 ¤   ¤   0, &timeout, &ldmp );
d3af5a
fdeedc ····if ( lderr == LDAP_SUCCESS || NONFATAL_LDAP_ERR( lderr )) {
22c176 ¤   if (( count = ldap_count_entries( ld, ldmp )) > 0 ) {
958b11 ¤   ····if (( members = (char **)malloc( (count + 1) * sizeof(char *)))
8f468f ¤   ¤   ····== NULL ) {
22d57d ¤   ¤   err = LDAP_NO_MEMORY;
40dfe8 ¤   ····} else {
476611 ¤   ¤   for ( i = 0, entry = ldap_first_entry( ld, ldmp );
cf59be ¤   ¤   ¤   entry != NULL;
b8d0ce ¤   ¤   ¤   entry = ldap_next_entry( ld, entry ), ++i ) {
740ed5 ¤   ¤   ····members[ i ] = ldap_get_dn( ld, entry );
4a0fe4 ¤   ¤   }
220eae ¤   ¤   members[ i ] = NULL;
75af5a
--08a3 00128caaec2401000b5 Page 16 of tmplout.c
91d637 ¤   ¤   ldap_sort_values( ld, members, ldap_sort_strcasecmp );
63af5a
600f89 ¤   ¤   err = do_vals2text( ld, NULL, members, tip->ti_label,
7daea0 ¤   ¤   ¤   html ? -1 : 0, LDAP_SYN_DN, writeproc, writeparm,
8661ac ¤   ¤   ¤   eol, rdncount, urlprefix );
b1af5a
a6acb1 ¤   ¤   ldap_value_free( members );
88f372 ¤   ····}
7e9371 ¤   }
f9258d ¤   ldap_msgfree( ldmp );
706fe7 ····}
84af5a
c5869e ····
ecd3cf ····if ( vals != NULL ) {
6a0171 ¤   ldap_value_free( vals );
056fe7 ····}
2daf5a
c18559 ····return(( err == LDAP_SUCCESS ) ? lderr : err );
28efe6 }
--a322 00074f09724401000b6 Page 1 of tmpltest.c
56feb2 #include <stdio.h>
daf15e #include <sys/types.h>
b86cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
66bea3 #include <stdlib.h>
6a7454 #endif
a4b779 #include "lber.h"
39e990 #include "ldap.h"
2c2b4c #include "disptmpl.h"
e17d20 #include "srchpref.h"
baaf5a
6cc583 #ifdef MACOS
ddbea3 #include <stdlib.h>
0cb6ac #include <console.h>
dee962 #endif /* MACOS */
0daf5a
5b504c #ifdef NEEDPROTOS
1d9819 void dump_tmpl( struct ldap_disptmpl *tmpl );
b03090 void dump_srchpref( struct ldap_searchobj *sp );
526133 #else /* NEEDPROTOS */
9b578b void dump_tmpl();
d22414 void dump_srchpref();
9f8634 #endif /* NEEDPROTOS */
48af5a
7baf5a
4eb85c #define NULLSTRINGIFNULL( s )¤  ( s == NULL ? "(null)" : s )
c4af5a
03af5a
164d2f int
e0874e main( int argc, char **argv )
24bb36 {
42b1ee ····struct ldap_disptmpl¤   *templates, *dtp;
023945 ····struct ldap_searchobj¤  *so, *sop;
88cf0e ····int¤¤   ¤   ¤   err;
4aaf5a
20c583 #ifdef MACOS
4d242c ¤   ccommand( &argv );
1c9369 ¤   for ( argc = 0; argv[ argc ] != NULL; ++argc ) {
a1e1c4 ¤   ····;
429371 ¤   }
f1fadc ¤   cshow( stdout );
7ee962 #endif /* MACOS */
47af5a
067fb9 ····if (( err = ldap_init_templates( "ldaptemplates.conf", &templates ))
0bc888 ¤   ····!= 0 ) {
0199a0 ¤   fprintf( stderr, "ldap_init_templates failed (%d)\n", err );
1db432 ¤   exit( 1 );
236fe7 ····}
0faf5a
e8766f ····if (( err = ldap_init_searchprefs( "ldapsearchprefs.conf", &so ))
2ec888 ¤   ····!= 0 ) {
4c936b ¤   fprintf( stderr, "ldap_init_searchprefs failed (%d)\n", err );
08b432 ¤   exit( 1 );
8e6fe7 ····}
45af5a
4abfa8 ····if ( argc == 1 ) {
8b1276 ¤   printf( "*** Display Templates:\n" );
f7e080 ¤   for ( dtp = ldap_first_disptmpl( templates ); dtp != NULLDISPTMPL;
f523a5 ¤   ¤   dtp = ldap_next_disptmpl( templates, dtp )) {
225b3e ¤   ····dump_tmpl( dtp );
52e2e4 ¤   ····printf( "\n\n" );
ff9371 ¤   }
f3af5a
841fca ¤   printf( "\n\n*** Search Objects:\n" );
d28d7e ¤   for ( sop = ldap_first_searchobj( so ); sop != NULLSEARCHOBJ;
8e044b ¤   ¤   ····sop = ldap_next_searchobj( so, sop )) {
d76086 ¤   ····dump_srchpref( sop );
0ee2e4 ¤   ····printf( "\n\n" );
259371 ¤   }
78af5a
696a79 ····} else {
03b14b ¤   if (( dtp = ldap_oc2template( ++argv, templates )) == NULL ) {
7483c1 ¤   ····fprintf( stderr, "no matching template found\n" );
--94f7 000019f0e44401000b6 Page 2 of tmpltest.c
faf037 ¤   } else {
6c5b3e ¤   ····dump_tmpl( dtp );
419371 ¤   }
776fe7 ····}
2eaf5a
c4af5a
517035 ····ldap_free_templates( templates );
636e71 ····ldap_free_searchprefs( so );
5aaf5a
e058d3 ····exit( 0 );
b23e6b ¤   return 0;
5cefe6 }
e5af5a
7eaf5a
10a047 static char *syn_name[] = {
b3eeea ····"?", "CIS", "MLS", "DN", "BOOL", "JPEG", "JPEGBTN", "FAX", "FAXBTN",
5cfc47 ····"AUDIOBTN", "TIME", "DATE", "URL", "SEARCHACT", "LINKACT", "ADDDNACT",
546008 ····"VERIFYACT",
d682f7 };
35af5a
608fb7 static char *syn_type[] = {
3764ea ····"?", "txt", "img", "?", "bool", "?", "?", "?", "btn",
ba8c9f ····"?", "?", "?", "?", "?", "?", "?",
d5fece ····"action", "?"
2982f7 };
f9af5a
27ec7b static char *includeattrs[] = { "objectClass", "sn", NULL };
96af5a
ee52ff static char *item_opts[] = {
dd10b0 ····"ro", "sort", "1val", "hide", "required", "hideiffalse", NULL
0e82f7 };
3baf5a
dd0bde static unsigned long item_opt_vals[] = {
991143 ····LDAP_DITEM_OPT_READONLY,¤   ¤   LDAP_DITEM_OPT_SORTVALUES,
2e7655 ····LDAP_DITEM_OPT_SINGLEVALUED,¤   LDAP_DITEM_OPT_HIDEIFEMPTY,
a1af22 ····LDAP_DITEM_OPT_VALUEREQUIRED,¤  LDAP_DITEM_OPT_HIDEIFFALSE,
b582f7 };
03af5a
11af5a
d8314a void
875ad8 dump_tmpl( struct ldap_disptmpl *tmpl )
fdbb36 {
161a08 ····struct ldap_tmplitem¤   *rowp, *colp;
720632 ····int¤¤   ¤   ¤   i, rowcnt, colcnt;
2ec279 ····char¤   ¤   ¤   **fetchattrs;
9b1e36 ····struct ldap_oclist¤ ¤   *ocp;
db84de ····struct ldap_adddeflist¤ *adp;
e6af5a
1931aa ····printf( "** Template \"%s\" (plural \"%s\", icon \"%s\")\n",
b0928f ¤   ····NULLSTRINGIFNULL( tmpl->dt_name ),
638201 ¤   ····NULLSTRINGIFNULL( tmpl->dt_pluralname ),
44784e ¤   ····NULLSTRINGIFNULL( tmpl->dt_iconname ));
9baf5a
c16f5f ····printf( "object class list:\n" );
0031b1 ····for ( ocp = tmpl->dt_oclist; ocp != NULL; ocp = ocp->oc_next ) {
e7efc1 ¤   for ( i = 0; ocp->oc_objclasses[ i ] != NULL; ++i ) {
cdf867 ¤   ····printf( "%s%s", i == 0 ? " ·" : " & ",
f3878c ¤   ¤   ····NULLSTRINGIFNULL( ocp->oc_objclasses[ i ] ));
cf9371 ¤   }
56b78f ¤   putchar( '\n' );
156fe7 ····}
6138f0 ····putchar( '\n' );
3baf5a
844edd ····printf( "template options: ·········" );
205228 ····if ( tmpl->dt_options == 0L ) {
97afd5 ¤   printf( "NONE\n" );
776a79 ····} else {
da3188 ¤   printf( "%s %s %s\n", LDAP_IS_DISPTMPL_OPTION_SET( tmpl,
2e8b8f ¤   ¤   LDAP_DTMPL_OPT_ADDABLE ) ? "addable" : "",
b1f63b ¤   ¤   LDAP_IS_DISPTMPL_OPTION_SET( tmpl, LDAP_DTMPL_OPT_ALLOWMODRDN )
509635 ¤   ¤   ? "modrdn" : "",
0181c3 ¤   ¤   LDAP_IS_DISPTMPL_OPTION_SET( tmpl, LDAP_DTMPL_OPT_ALTVIEW )
--9ce8 000659c2de3401000b6 Page 3 of tmpltest.c
e4a49b ¤   ¤   ? "altview" : "" );
fa6fe7 ····}
ddaf5a
431ddd ····printf( "authenticate as attribute: %s\n", tmpl->dt_authattrname != NULL ?
151c1f ¤   ····tmpl->dt_authattrname : "<default>" );
07af5a
3bff45 ····printf( "default RDN attribute: ····%s\n", tmpl->dt_defrdnattrname != NULL ?
fd6ff5 ¤   ····tmpl->dt_defrdnattrname : "NONE" );
57af5a
b88c56 ····printf( "default add location: ·····%s\n", tmpl->dt_defaddlocation != NULL ?
7f2e2f ¤   ····tmpl->dt_defaddlocation : "NONE" );
daaf5a
9f2807 ····printf( "\nnew entry value default rules:\n" );
f63f1c ····for ( adp = tmpl->dt_adddeflist; adp != NULL; adp = adp->ad_next ) {
a3d7c5 ¤   if ( adp->ad_source == LDAP_ADSRC_CONSTANTVALUE ) {
16bd45 ¤   ····printf( " ·attribute %s <-- constant value \"%s\"\n",
128b93 ¤   ¤   NULLSTRINGIFNULL( adp->ad_attrname),
5f0b5a ¤   ¤   NULLSTRINGIFNULL( adp->ad_value ));
4ff037 ¤   } else {
9337db ¤   ····printf( " ·attribute %s <-- adder's DN\n",
9bc9e7 ¤   ¤   ····NULLSTRINGIFNULL( adp->ad_attrname ));
3a9371 ¤   }
5f6fe7 ····}
fe38f0 ····putchar( '\n' );
75af5a
a9adaa ····printf( "\nfetch attributes & values:\n" );
c1e25e ····if (( fetchattrs = ldap_tmplattrs( tmpl, includeattrs, 1,
22aec5 ¤   ¤   LDAP_SYN_OPT_DEFER )) == NULL ) {
ffffae ¤   printf( " ·<none>\n" );
fc6a79 ····} else {
cb7dc9 ¤   for ( i = 0; fetchattrs[ i ] != NULL; ++i ) {
6112a8 ¤   ····printf( " ·%s\n", fetchattrs[ i ] );
40d486 ¤   ····free( fetchattrs[ i ] );
589371 ¤   }
d72e6f ¤   free( (char *)fetchattrs );
666fe7 ····}
a4af5a
2fde79 ····printf( "\nfetch attributes only:\n" );
620436 ····if (( fetchattrs = ldap_tmplattrs( tmpl, NULL, 0,
baaec5 ¤   ¤   LDAP_SYN_OPT_DEFER )) == NULL ) {
5dffae ¤   printf( " ·<none>\n" );
e16a79 ····} else {
5f7dc9 ¤   for ( i = 0; fetchattrs[ i ] != NULL; ++i ) {
5d12a8 ¤   ····printf( " ·%s\n", fetchattrs[ i ] );
b9d486 ¤   ····free( fetchattrs[ i ] );
399371 ¤   }
ac2e6f ¤   free( (char *)fetchattrs );
e36fe7 ····}
11af5a
b79518 ····printf( "\ntemplate items:\n" );
aed8ea ····rowcnt = 0;
fa9a04 ····for ( rowp = ldap_first_tmplrow( tmpl ); rowp != NULLTMPLITEM;
6a5605 ¤   ····rowp = ldap_next_tmplrow( tmpl, rowp )) {
3931c4 ¤   ++rowcnt;
987535 ¤   colcnt = 0;
e91049 ¤   for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM;
7ecc83 ¤   ¤   colp = ldap_next_tmplcol( tmpl, rowp, colp )) {
7daac3 ¤   ····++colcnt;
573a48 ¤   ····printf( " ·%2d-%d: %s (%s%s", rowcnt, colcnt,
5e00d5 ¤   ¤   syn_name[ colp->ti_syntaxid & 0x0000FFFF ],
25e24f ¤   ¤   syn_type[ LDAP_GET_SYN_TYPE( colp->ti_syntaxid ) >> 24 ],
93cc28 ¤   ¤   (( LDAP_GET_SYN_OPTIONS( colp->ti_syntaxid ) &
7b0da5 ¤   ¤   LDAP_SYN_OPT_DEFER ) != 0 ) ? ",defer" : "" );
73af5a
4bc056 ¤   ····for ( i = 0; item_opts[ i ] != NULL; ++i ) {
f84eb2 ¤   ¤   if ( LDAP_IS_TMPLITEM_OPTION_SET( colp, item_opt_vals[ i ] )) {
00cebb ¤   ¤   ····printf( ",%s", NULLSTRINGIFNULL( item_opts[ i ] ));
ad0fe4 ¤   ¤   }
09f372 ¤   ····}
d9af5a
7cc27d ¤   ····printf( "), %s, %s", NULLSTRINGIFNULL( colp->ti_attrname ),
65afb1 ¤   ¤   ····NULLSTRINGIFNULL( colp->ti_label ));
--7b22 0011821fe66401000b6 Page 4 of tmpltest.c
f686e4 ¤   ····if ( colp->ti_args != NULL ) {
4a3325 ¤   ¤   printf( ",args=" );
2b08e0 ¤   ¤   for ( i = 0; colp->ti_args[ i ] != NULL; ++i ) {
0fe8a1 ¤   ¤   ····printf( "<%s>", NULLSTRINGIFNULL( colp->ti_args[ i ] ));
520fe4 ¤   ¤   }
47f372 ¤   ····}
6baf5a
298921 ¤   ····putchar( '\n' );
479371 ¤   }
876fe7 ····}
5cefe6 }
c4af5a
1baf5a
04314a void
805448 dump_srchpref( struct ldap_searchobj *so )
84bb36 {
ddae36 ····int i;
2b4423 ····struct ldap_searchattr *sa;
7bde23 ····struct ldap_searchmatch *sm;
3aaf5a
942e98 ····printf( "Object type prompt: ·%s\n",
a924e0 ¤   ····NULLSTRINGIFNULL( so->so_objtypeprompt ));
30a4bf ····printf( "Options: ············%s\n",
31da11 ¤   ····LDAP_IS_SEARCHOBJ_OPTION_SET( so, LDAP_SEARCHOBJ_OPT_INTERNAL ) ?
c8e274 ¤   ····"internal" : "NONE" );
91fc34 ····printf( "Prompt: ·············%s\n", NULLSTRINGIFNULL( so->so_prompt ));
c6a636 ····printf( "Scope: ··············" );
e0e67e ····switch ( so->so_defaultscope ) {
e1fe76 ····case LDAP_SCOPE_BASE:
4090df ¤   printf( "LDAP_SCOPE_BASE" );
bc4ed2 ¤   break;
e22cdd ····case LDAP_SCOPE_ONELEVEL:
3bc2e9 ¤   printf( "LDAP_SCOPE_ONELEVEL" );
364ed2 ¤   break;
0ca7cf ····case LDAP_SCOPE_SUBTREE:
8e91a2 ¤   printf( "LDAP_SCOPE_SUBTREE" );
8e4ed2 ¤   break;
34b53c ····default:
496b37 ¤   printf("*** unknown!" );
de6fe7 ····}
061d35 ····puts( "\n" );
4a6961 ····printf( "Filter prefix: ······%s\n",
21ba19 ¤   ····NULLSTRINGIFNULL( so->so_filterprefix ));
1d931d ····printf( "Filter tag: ·········%s\n",
ec4096 ¤   ····NULLSTRINGIFNULL( so->so_filtertag ));
b89179 ····printf( "Default select attr: %s\n",
95a6ee ¤   ····NULLSTRINGIFNULL( so->so_defaultselectattr ));
c14210 ····printf( "Default select text: %s\n",
9e58c5 ¤   ····NULLSTRINGIFNULL( so->so_defaultselecttext ));
f02b88 ····printf( "Searchable attributes ---- \n" );
f62c2a ····for ( sa = so->so_salist; sa != NULL; sa = sa->sa_next ) {
d8dc21 ¤   printf( " ·Label: %s\n", NULLSTRINGIFNULL( sa->sa_attrlabel ));
80fc42 ¤   printf( " ·Attribute: %s\n", NULLSTRINGIFNULL( sa->sa_attr ));
3b597c ¤   printf( " ·Select attr: %s\n", NULLSTRINGIFNULL( sa->sa_selectattr ));
f5af1f ¤   printf( " ·Select text: %s\n", NULLSTRINGIFNULL( sa->sa_selecttext ));
82c68e ¤   printf( " ·Match types ---- \n" );
a3b186 ¤   for ( i = 0, sm = so->so_smlist; sm != NULL; i++, sm = sm->sm_next ) {
daa8ff ¤   ····if (( sa->sa_matchtypebitmap >> i ) & 1 ) {
12b551 ¤   ¤   printf( " ···%s (%s)\n",
fd958b ¤   ¤   ¤   NULLSTRINGIFNULL( sm->sm_matchprompt ),
330ba6 ¤   ¤   ¤   NULLSTRINGIFNULL( sm->sm_filter ));
def372 ¤   ····}
729371 ¤   }
b06fe7 ····}
18efe6 }
--cf4c 000a675bc8c401000b7 Page 1 of ufn.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
77a51e ·* ·ufn.c
65495d ·*/
dbaf5a
260c68 #ifndef lint·
8d66c6 static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University "
863efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
cc7454 #endif
6baf5a
bffeb2 #include <stdio.h>
78324c #include <string.h>
24b1cb #include <ctype.h>
9baf5a
f724c3 #if PGPSOCKETSLDAP¤ /* jason */
e265aa #include "pgpSocketsLDAP.h"
e26103 #if WIN32
dee3c0 #define FILTERFILE¤ ¤   "etc/ldapfilter.conf"
ac7454 #endif
37af5a
58db21 #else
1cc583 #ifdef MACOS
4dbea3 #include <stdlib.h>
c565e0 #include "macos.h"
5d6c94 #else /* MACOS */
4dfdef #if defined( DOS ) || defined( _WIN32 )
2001b0 #ifdef DOS
90f2ef #include "msdos.h"
327454 #endif
b6aad8 #else /* DOS */
e75d8c #include <sys/time.h>
42f15e #include <sys/types.h>
2466f2 #include <sys/socket.h>
85bc39 #endif /* DOS */
d6e962 #endif /* MACOS */
e2af5a
126cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
ae2d5f #include <winsock.h>
7be3c0 #define FILTERFILE¤ ¤   "etc/ldapfilter.conf"
267454 #endif
55df0f #endif /* PGPSOCKETSLDAP */
16af5a
18b779 #include "lber.h"
0ee990 #include "ldap.h"
28af5a
51504c #ifdef NEEDPROTOS
a0292a typedef int (*cancelptype)( void *cancelparm );
456133 #else /* NEEDPROTOS */
48476d typedef int (*cancelptype)();
9e8634 #endif /* NEEDPROTOS */
3eaf5a
5c504c #ifdef NEEDPROTOS
323af2 static int ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp,·
5a0102 ¤   char *prefix, char **attrs, int attrsonly, LDAPMessage **res,·
643f08 ¤   cancelptype cancelproc, void *cancelparm, char *tag1, char *tag2,
d1b2bf ¤   char *tag3 );
b27cb6 static LDAPMessage *ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b );
5eb4cf static LDAPMessage *ldap_ufn_expand( LDAP *ld, cancelptype cancelproc,
8e9d8f ¤   void *cancelparm, char **dns, char *filter, int scope,
f4c4c8 ¤   char **attrs, int aonly, int *err );
b2ee59 LDAPFiltDesc *ldap_ufn_setfilter( LDAP *ld, char *fname );
e06133 #else /* NEEDPROTOS */
0a3810 static LDAPMessage *ldap_msg_merge();
ae9031 static LDAPMessage *ldap_ufn_expand();
10c9f7 LDAPFiltDesc *ldap_ufn_setfilter();
a28634 #endif /* NEEDPROTOS */
e6af5a
3f38e5 /*
9412cf ·* ldap_ufn_search_ctx - do user friendly searching; provide cancel feature;
a63795 ·*¤ ¤   ¤   specify ldapfilter.conf tags for each phase of search
--6c5c 000052ef762401000b7 Page 2 of ufn.c
4f775e ·*
b04f03 ·*¤ ld¤ ¤   LDAP descriptor
b5ab46 ·*¤ ufncomp¤¤   the exploded user friendly name to look for
db1a9c ·*¤ ncomp¤  ¤   number of elements in ufncomp
639a2a ·*¤ prefix¤ ¤   where to start searching
c7167c ·*¤ attrs¤  ¤   list of attribute types to return for matches
af8340 ·*¤ attrsonly¤  1 => attributes only 0 => attributes and values
e5fb5c ·*¤ res¤¤   will contain the result of the search
20240b ·*¤ cancelproc¤ routine that returns non-zero if operation should be
0d6bf3 ·*¤ ¤   ¤   cancelled. ·This can be NULL. ·If it is non-NULL, the
370ce2 ·*¤ ¤   ¤   routine will be called periodically.
3acfc9 ·*¤ cancelparm¤ void * that is passed to cancelproc
9864b0 ·*¤ tag[123]¤   the ldapfilter.conf tag that will be used in phases
86170c ·*¤ ¤   ¤   1, 2, and 3 of the search, respectively
39775e ·*
ac305c ·* Example:
aed2ff ·*¤ char¤   ¤   *attrs[] = { "mail", "title", 0 };
bd2a43 ·*¤ char¤   ¤   *ufncomp[] = { "howes", "umich", "us", 0 }
647ad0 ·*¤ LDAPMessage¤*res;
a00771 ·*¤ error = ldap_ufn_search_ctx( ld, ufncomp, 3, NULL, attrs, attrsonly,
453d0a ·*¤ ¤   ¤   &res, acancelproc, along, "ufn first",
a5fd76 ·*¤ ¤   ¤   "ufn intermediate", "ufn last" );
32495d ·*/
e6af5a
0fbeb7 static int
98828f ldap_ufn_search_ctx( LDAP *ld, char **ufncomp, int ncomp, char *prefix,
85b242 ¤   char **attrs, int attrsonly, LDAPMessage **res, cancelptype cancelproc,
ecda47 ¤   void *cancelparm, char *tag1, char *tag2, char *tag3 )
43bb36 {
0ccbff ¤   char¤   ¤   *dn, *ftag;
9eb9e9 ¤   char¤   ¤   **dns;
54e301 ¤   int¤¤   max, i, err, scope, phase, tries;
156a30 ¤   LDAPFiltInfo¤   *fi;
716545 ¤   LDAPMessage¤*tmpcand;
b62991 ¤   LDAPMessage¤*candidates;
28473a ¤   LDAPMessage¤*ldap_msg_merge(), *ldap_ufn_expand();
1175c9 ¤   static char¤*objattrs[] = { "objectClass", NULL };
93af5a
517869 ¤   /*·
3a2a15 ¤   ·* look up ufn components from most to least significant.
d56349 ¤   ·* there are 3 phases. ·
3dc5c4 ¤   ·* ¤phase 1¤search the root for orgs or countries
6bdf84 ¤   ·* ¤phase 2¤search for orgs
cdda71 ¤   ·* ¤phase 3¤search for a person
6bb8f2 ¤   ·* in phases 1 and 2, we are building a list of candidate DNs,
c356c1 ¤   ·* below which we will search for the final component of the ufn.
11992e ¤   ·* for each component we try the filters listed in the
4a26af ¤   ·* filterconfig file, first one-level (except the last compoment),
63c682 ¤   ·* then subtree. ·if any of them produce any results, we go on to
8484fc ¤   ·* the next component.
dea4e3 ¤   ·*/
8daf5a
0046a2 ¤   *res = NULL;
7910f4 ¤   candidates = NULL;
1c220b ¤   phase = 1;
43135e ¤   for ( ncomp--; ncomp != -1; ncomp-- ) {
649dc5 ¤   ¤   if ( *ufncomp[ncomp] == '"' ) {
0810e2 ¤   ¤   ¤   char¤   *quote;
b3af5a
377954 ¤   ¤   ¤   if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL )
fe8177 ¤   ¤   ¤   ¤   *quote = '\0';
b0283f ¤   ¤   ¤   strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 );
7a0fe4 ¤   ¤   }
007d3d ¤   ¤   if ( ncomp == 0 )
204ef9 ¤   ¤   ¤   phase = 3;
11af5a
ec23f6 ¤   ¤   switch ( phase ) {
14b803 ¤   ¤   case 1:
bdf2dd ¤   ¤   ¤   ftag = tag1;
edd66d ¤   ¤   ¤   scope = LDAP_SCOPE_ONELEVEL;
6fcdcb ¤   ¤   ¤   break;
055767 ¤   ¤   case 2:
--7fb9 0006a34a2f3401000b7 Page 3 of ufn.c
e01db9 ¤   ¤   ¤   ftag = tag2;
10d66d ¤   ¤   ¤   scope = LDAP_SCOPE_ONELEVEL;
e7cdcb ¤   ¤   ¤   break;
b50dbb ¤   ¤   case 3:
804765 ¤   ¤   ¤   ftag = tag3;
2bf8b3 ¤   ¤   ¤   scope = LDAP_SCOPE_SUBTREE;
cfcdcb ¤   ¤   ¤   break;
e50fe4 ¤   ¤   }
4baf5a
801b17 ¤   ¤   /*
f03c1d ¤   ¤   ·* construct an array of DN's to search below from the
94c2d7 ¤   ¤   ·* list of candidates.
bb9de3 ¤   ¤   ·*/
c6af5a
f4c4ff ¤   ¤   if ( candidates == NULL ) {
7a1134 ¤   ¤   ¤   if ( prefix != NULL ) {
a3b69a ¤   ¤   ¤   ¤   if ( (dns = (char **) malloc( sizeof(char *)
c4621e ¤   ¤   ¤   ¤   ····* 2 )) == NULL ) {
627661 ¤   ¤   ¤   ¤   ¤   return( ld->ld_errno = LDAP_NO_MEMORY );
db2613 ¤   ¤   ¤   ¤   }
a0f90e ¤   ¤   ¤   ¤   dns[0] = strdup( prefix );
c25faa ¤   ¤   ¤   ¤   dns[1] = NULL;
8c042d ¤   ¤   ¤   } else {
1731ff ¤   ¤   ¤   ¤   dns = NULL;
17a3a6 ¤   ¤   ¤   }
0a45a6 ¤   ¤   } else {
573b42 ¤   ¤   ¤   i = 0, max = 0;
2e6bf9 ¤   ¤   ¤   for ( tmpcand = candidates; tmpcand != NULL &&
ccbd12 ¤   ¤   ¤   ····tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT;
8c56c5 ¤   ¤   ¤   ····tmpcand = tmpcand->lm_chain )
c9f776 ¤   ¤   ¤   {
647caf ¤   ¤   ¤   ¤   if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL )
cc5914 ¤   ¤   ¤   ¤   ¤   continue;
43af5a
c1139b ¤   ¤   ¤   ¤   if ( dns == NULL ) {
2f2892 ¤   ¤   ¤   ¤   ¤   if ( (dns = (char **) malloc(
acd542 ¤   ¤   ¤   ¤   ¤   ····sizeof(char *) * 8 )) == NULL ) {
e0395d ¤   ¤   ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
fe6abf ¤   ¤   ¤   ¤   ¤   ¤   return( LDAP_NO_MEMORY );
bf1c89 ¤   ¤   ¤   ¤   ¤   }
99ef93 ¤   ¤   ¤   ¤   ¤   max = 8;
1bf407 ¤   ¤   ¤   ¤   } else if ( i >= max ) {
6f764e ¤   ¤   ¤   ¤   ¤   if ( (dns = (char **) realloc( dns,
9abce2 ¤   ¤   ¤   ¤   ¤   ····sizeof(char *) * 2 * max ))
ff8384 ¤   ¤   ¤   ¤   ¤   ····== NULL )
664859 ¤   ¤   ¤   ¤   ¤   {
d6395d ¤   ¤   ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
4a6abf ¤   ¤   ¤   ¤   ¤   ¤   return( LDAP_NO_MEMORY );
fe1c89 ¤   ¤   ¤   ¤   ¤   }
9c8aef ¤   ¤   ¤   ¤   ¤   max *= 2;
e52613 ¤   ¤   ¤   ¤   }
47c411 ¤   ¤   ¤   ¤   dns[i++] = dn;
da5f40 ¤   ¤   ¤   ¤   dns[i] = NULL;
0ea3a6 ¤   ¤   ¤   }
f61ace ¤   ¤   ¤   ldap_msgfree( candidates );
36e63d ¤   ¤   ¤   candidates = NULL;
d60fe4 ¤   ¤   }
c8f313 ¤   ¤   tries = 0;
e2f992 ¤   tryagain:
9401ab ¤   ¤   tries++;
e70cb7 ¤   ¤   for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag,
121f60 ¤   ¤   ····ufncomp[ncomp] ); fi != NULL;
5ed535 ¤   ¤   ····fi = ldap_getnextfilter( ld->ld_filtd ) )
9c5b34 ¤   ¤   {
500489 ¤   ¤   ¤   if ( (candidates = ldap_ufn_expand( ld, cancelproc,
7afeab ¤   ¤   ¤   ····cancelparm, dns, fi->lfi_filter, scope,
132f58 ¤   ¤   ¤   ····phase == 3 ? attrs : objattrs,
b6935f ¤   ¤   ¤   ····phase == 3 ? attrsonly : 1, &err )) != NULL )
3cf776 ¤   ¤   ¤   {
9cf622 ¤   ¤   ¤   ¤   break;
84a3a6 ¤   ¤   ¤   }
6aaf5a
--7f32 000496cbe83401000b7 Page 4 of ufn.c
d51acc ¤   ¤   ¤   if ( err == -1 || err == LDAP_USER_CANCELLED ) {
0f09d9 ¤   ¤   ¤   ¤   if ( dns != NULL ) {
a59923 ¤   ¤   ¤   ¤   ¤   ldap_value_free( dns );
239ca1 ¤   ¤   ¤   ¤   ¤   dns = NULL;
a22613 ¤   ¤   ¤   ¤   }
0d1397 ¤   ¤   ¤   ¤   return( err );
65a3a6 ¤   ¤   ¤   }
c70fe4 ¤   ¤   }
37af5a
cbc4ff ¤   ¤   if ( candidates == NULL ) {
16e73f ¤   ¤   ¤   if ( tries < 2 && phase != 3 ) {
1670d5 ¤   ¤   ¤   ¤   scope = LDAP_SCOPE_SUBTREE;
c1b0a8 ¤   ¤   ¤   ¤   goto tryagain;
f9042d ¤   ¤   ¤   } else {
2e09d9 ¤   ¤   ¤   ¤   if ( dns != NULL ) {
0c9923 ¤   ¤   ¤   ¤   ¤   ldap_value_free( dns );
709ca1 ¤   ¤   ¤   ¤   ¤   dns = NULL;
412613 ¤   ¤   ¤   ¤   }
4e1397 ¤   ¤   ¤   ¤   return( err );
6ea3a6 ¤   ¤   ¤   }
570fe4 ¤   ¤   }
77af5a
c9a8dd ¤   ¤   /* go on to the next component */
08112a ¤   ¤   if ( phase == 1 )
ee0910 ¤   ¤   ¤   phase++;
4e8fe7 ¤   ¤   if ( dns != NULL ) {
42d410 ¤   ¤   ¤   ldap_value_free( dns );
0ac79a ¤   ¤   ¤   dns = NULL;
ec0fe4 ¤   ¤   }
689371 ¤   }
2faba7 ¤   *res = candidates;
19af5a
87deb7 ¤   return( err );
57efe6 }
bdaf5a
5e4d2f int
1883a0 ldap_ufn_search_ct( LDAP *ld, char *ufn, char **attrs, int attrsonly,
0912b8 ¤   LDAPMessage **res, cancelptype cancelproc, void *cancelparm,
11bcbc ¤   char *tag1, char *tag2, char *tag3 )
9dbb36 {
8934b0 ¤   char¤   **ufncomp, **prefixcomp;
837c6a ¤   char¤   *pbuf;
23a26c ¤   int¤ncomp, pcomp, i, err;
77af5a
d4800e ¤   /* initialize the getfilter stuff if it's not already */
c2b1b1 ¤   if ( ld->ld_filtd == NULL && ldap_ufn_setfilter( ld, FILTERFILE )
4a3c7b ¤   ····== NULL ) {
118909 ¤   ¤   return( ld->ld_errno = LDAP_LOCAL_ERROR );
8e9371 ¤   }
1aaf5a
5798d3 ¤   /* call ldap_explode_dn() to break the ufn into its components */
b0b9dc ¤   if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL )
d58909 ¤   ¤   return( ld->ld_errno = LDAP_LOCAL_ERROR );
f4aed7 ¤   for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ )
26c78a ¤   ¤   ;¤  /* NULL */
c0af5a
1473db ¤   /* more than two components => try it fully qualified first */
a195bb ¤   if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) {
4dddf8 ¤   ¤   err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs,
a90ce2 ¤   ¤   ····attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 );
12af5a
27e0f9 ¤   ¤   if ( ldap_count_entries( ld, *res ) > 0 ) {
370c78 ¤   ¤   ¤   ldap_value_free( ufncomp );
7007bf ¤   ¤   ¤   return( err );
f645a6 ¤   ¤   } else {
673201 ¤   ¤   ¤   ldap_msgfree( *res );
51b6f8 ¤   ¤   ¤   *res = NULL;
000fe4 ¤   ¤   }
429371 ¤   }
8baf5a
3dea72 ¤   if ( ld->ld_ufnprefix == NULL ) {
49c92d ¤   ¤   ldap_value_free( ufncomp );
--1358 0007195f699401000b7 Page 5 of ufn.c
a3e55e ¤   ¤   return( err );
6d9371 ¤   }
b9af5a
b0c7ed ¤   /* if that failed, or < 2 components, use the prefix */
aeb2be ¤   if ( (prefixcomp = ldap_explode_dn( ld->ld_ufnprefix, 0 )) == NULL ) {
84c92d ¤   ¤   ldap_value_free( ufncomp );
a08909 ¤   ¤   return( ld->ld_errno = LDAP_LOCAL_ERROR );
df9371 ¤   }
4924e4 ¤   for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ )
93c78a ¤   ¤   ;¤  /* NULL */
252cc7 ¤   if ( (pbuf = (char *) malloc( strlen( ld->ld_ufnprefix ) + 1 ))
5157dd ¤   ····== NULL ) {¤
34c92d ¤   ¤   ldap_value_free( ufncomp );
ed6938 ¤   ¤   ldap_value_free( prefixcomp );
c96cfc ¤   ¤   return( ld->ld_errno = LDAP_NO_MEMORY );
ac9371 ¤   }
9caf5a
58f310 ¤   for ( i = 0; i < pcomp; i++ ) {
929af8 ¤   ¤   int¤j;
0aaf5a
3adcef ¤   ¤   *pbuf = '\0';
615dff ¤   ¤   for ( j = i; j < pcomp; j++ ) {
d4a8bc ¤   ¤   ¤   strcat( pbuf, prefixcomp[j] );
29e1d4 ¤   ¤   ¤   if ( j + 1 < pcomp )
b684a9 ¤   ¤   ¤   ¤   strcat( pbuf, "," );
8a0fe4 ¤   ¤   }
6c59d8 ¤   ¤   err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs,
9e0ce2 ¤   ¤   ····attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 );
d9af5a
f8e0f9 ¤   ¤   if ( ldap_count_entries( ld, *res ) > 0 ) {
b9cdcb ¤   ¤   ¤   break;
0345a6 ¤   ¤   } else {
2e3201 ¤   ¤   ¤   ldap_msgfree( *res );
44b6f8 ¤   ¤   ¤   *res = NULL;
180fe4 ¤   ¤   }
f69371 ¤   }
1eaf5a
f442d1 ¤   ldap_value_free( ufncomp );
6228cb ¤   ldap_value_free( prefixcomp );
e4bda2 ¤   free( pbuf );
36af5a
3ddeb7 ¤   return( err );
06efe6 }
8caf5a
4e38e5 /*
c1f298 ·* same as ldap_ufn_search_ct, except without the ability to specify
a1836b ·* ldapfilter.conf tags.
70495d ·*/
554d2f int
97ccfd ldap_ufn_search_c( LDAP *ld, char *ufn, char **attrs, int attrsonly,
963a73 ¤   LDAPMessage **res, cancelptype cancelproc, void *cancelparm )
5abb36 {
54d004 ¤   return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc,
ef215a ¤   ····cancelparm, "ufn first", "ufn intermediate", "ufn last" ) );
4defe6 }
ffaf5a
f638e5 /*
a0d6c5 ·* same as ldap_ufn_search_c without the cancel function
a3495d ·*/
394d2f int
b8ea01 ldap_ufn_search_s( LDAP *ld, char *ufn, char **attrs, int attrsonly,
9d77a7 ¤   LDAPMessage **res )
71bb36 {
6ce847 ¤   struct timeval¤ tv;
ebaf5a
821a98 ¤   tv.tv_sec = ld->ld_timelimit;
0eaf5a
434ae2 ¤   return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res,
062c2b ¤   ¤   ld->ld_timelimit ? ldap_ufn_timeout : NULL,
04a88c ¤   ¤   ld->ld_timelimit ? (void *) &tv : NULL,
c74d5e ¤   ¤   "ufn first", "ufn intermediate", "ufn last" ) );
71efe6 }
--26a7 00050183270401000b7 Page 6 of ufn.c
e0af5a
1aaf5a
9938e5 /*
0f6068 ·* ldap_msg_merge - merge two ldap search result chains. ·the more
df5f1a ·* serious of the two error result codes is kept.
b7495d ·*/
70af5a
704af2 static LDAPMessage *
a548a1 ldap_msg_merge( LDAP *ld, LDAPMessage *a, LDAPMessage *b )
efbb36 {
55bec5 ¤   LDAPMessage¤*end, *aprev, *aend, *bprev, *bend;
aaaf5a
88e9a0 ¤   if ( a == NULL )
3cc800 ¤   ¤   return( b );
17af5a
8c6e4e ¤   if ( b == NULL )
72d5cc ¤   ¤   return( a );
5faf5a
a01302 ¤   /* find the ends of the a and b chains */
416db4 ¤   aprev = NULL;
b6cda8 ¤   for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain )
9d48ca ¤   ¤   aprev = aend;
28ee8a ¤   bprev = NULL;
f7def0 ¤   for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain )
0ec789 ¤   ¤   bprev = bend;
b3af5a
c80dfc ¤   /* keep result a */
5093b9 ¤   if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) {
89be7a ¤   ¤   /* remove result b */
dc962c ¤   ¤   ldap_msgfree( bend );
c16a9f ¤   ¤   if ( bprev != NULL )
fb37d3 ¤   ¤   ¤   bprev->lm_chain = NULL;
d90e1d ¤   ¤   else
50c241 ¤   ¤   ¤   b = NULL;
153178 ¤   ¤   end = aend;
9bf0be ¤   ¤   if ( aprev != NULL )
f6da1f ¤   ¤   ¤   aprev->lm_chain = NULL;
be0e1d ¤   ¤   else
1bb628 ¤   ¤   ¤   a = NULL;
c81030 ¤   /* keep result b */
f7f037 ¤   } else {
2da3b6 ¤   ¤   /* remove result a */
0d1cfc ¤   ¤   ldap_msgfree( aend );
bcf0be ¤   ¤   if ( aprev != NULL )
1ada1f ¤   ¤   ¤   aprev->lm_chain = NULL;
e10e1d ¤   ¤   else
2eb628 ¤   ¤   ¤   a = NULL;
183d05 ¤   ¤   end = bend;
166a9f ¤   ¤   if ( bprev != NULL )
2b37d3 ¤   ¤   ¤   bprev->lm_chain = NULL;
c60e1d ¤   ¤   else
c1c241 ¤   ¤   ¤   b = NULL;
6b9371 ¤   }
dfaf5a
4221c1 ¤   if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) ||
9fe87c ¤   ····(b == NULL && aprev == NULL) )
2119c2 ¤   ¤   return( end );
75af5a
e81e47 ¤   if ( a == NULL ) {
3a1f86 ¤   ¤   bprev->lm_chain = end;
4bc800 ¤   ¤   return( b );
baea78 ¤   } else if ( b == NULL ) {
b98dcc ¤   ¤   aprev->lm_chain = end;
51d5cc ¤   ¤   return( a );
faf037 ¤   } else {
a11f86 ¤   ¤   bprev->lm_chain = end;
bff001 ¤   ¤   aprev->lm_chain = b;
c8d5cc ¤   ¤   return( a );
449371 ¤   }
53efe6 }
2aaf5a
504af2 static LDAPMessage *
--a5d4 000db87c692401000b7 Page 7 of ufn.c
6bcc15 ldap_ufn_expand( LDAP *ld, cancelptype cancelproc, void *cancelparm,
c85748 ¤   char **dns, char *filter, int scope, char **attrs, int aonly,
839d00 ¤   int *err )
18bb36 {
0c382b ¤   LDAPMessage¤*tmpcand, *tmpres;
daee9f ¤   char¤   ¤   *dn;
16fa94 ¤   int¤¤   i, msgid;
24e847 ¤   struct timeval¤ tv;
31af5a
b7d106 ¤   /* search for this component below the current candidates */
8a6a38 ¤   tmpcand = NULL;
dcff6c ¤   i = 0;
bb43ab ¤   do {
f624b1 ¤   ¤   if ( dns != NULL )
81977b ¤   ¤   ¤   dn = dns[i];
4c0e1d ¤   ¤   else
da357b ¤   ¤   ¤   dn = "";
ebaf5a
8519c2 ¤   ¤   if (( msgid = ldap_search( ld, dn, scope, filter, attrs,
090f33 ¤   ¤   ····aonly )) == -1 ) {
77ebec ¤   ¤   ¤   ldap_msgfree( tmpcand );
a53067 ¤   ¤   ¤   *err = ld->ld_errno;
0819e3 ¤   ¤   ¤   return( NULL );
3d0fe4 ¤   ¤   }
d0af5a
4a7e2c ¤   ¤   tv.tv_sec = 0;
66ee16 ¤   ¤   tv.tv_usec = 100000;¤   /* 1/10 of a second */
92af5a
024392 ¤   ¤   do {
ea7bad ¤   ¤   ¤   *err = ldap_result( ld, msgid, 1, &tv, &tmpres );
74e884 ¤   ¤   ¤   if ( *err == 0 && cancelproc != NULL &&
676b74 ¤   ¤   ¤   ····(*cancelproc)( cancelparm ) != 0 ) {
286c7d ¤   ¤   ¤   ¤   ldap_abandon( ld, msgid );
d4050f ¤   ¤   ¤   ¤   *err = LDAP_USER_CANCELLED;
63b1ef ¤   ¤   ¤   ¤   ld->ld_errno = LDAP_USER_CANCELLED;
41a3a6 ¤   ¤   ¤   }
e22865 ¤   ¤   } while ( *err == 0 );
f4af5a
d9e760 ¤   ¤   if ( *err == LDAP_USER_CANCELLED || *err < 0 ||
40eecb ¤   ¤   ····( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) {
c2ebec ¤   ¤   ¤   ldap_msgfree( tmpcand );
6619e3 ¤   ¤   ¤   return( NULL );
cf0fe4 ¤   ¤   }
7e1b52 ¤   ¤
afc100 ¤   ¤   tmpcand = ldap_msg_merge( ld, tmpcand, tmpres );
94af5a
02347d ¤   ¤   i++;
f91330 ¤   } while ( dns != NULL && dns[i] != NULL );
0caf5a
ada2e3 ¤   if ( ldap_count_entries( ld, tmpcand ) > 0 ) {
d604e8 ¤   ¤   return( tmpcand );
f5f037 ¤   } else {
3cd684 ¤   ¤   ldap_msgfree( tmpcand );
52ef86 ¤   ¤   return( NULL );
1b9371 ¤   }
cdefe6 }
edaf5a
d538e5 /*
6d7500 ·* ldap_ufn_setfilter - set the filter config file used in ufn searching
e7495d ·*/
d8af5a
51c4f9 LDAPFiltDesc *
628983 ldap_ufn_setfilter( LDAP *ld, char *fname )
f9bb36 {
5af9b0 ¤   if ( ld->ld_filtd != NULL )
3c1b59 ¤   ¤   ldap_getfilter_free( ld->ld_filtd );
55af5a
6364b5 ¤   return( ld->ld_filtd = ldap_init_getfilter( fname ) );
3befe6 }
5eaf5a
e0314a void
db3271 ldap_ufn_setprefix( LDAP *ld, char *prefix )
--c4f4 0011d38c020401000b7 Page 8 of ufn.c
2cbb36 {
951390 ¤   if ( ld->ld_ufnprefix != NULL )
173042 ¤   ¤   free( ld->ld_ufnprefix );
0eaf5a
4d02ae ¤   ld->ld_ufnprefix = strdup( prefix );
73efe6 }
bfaf5a
ea4d2f int
f3c412 ldap_ufn_timeout( void *tvparam )
1bbb36 {
d5e2d6 ¤   struct timeval¤ *tv;
b7af5a
635455 ¤   tv = (struct timeval *)tvparam;
49af5a
10b0b0 ¤   if ( tv->tv_sec != 0 ) {
4cccee ¤   ¤   tv->tv_usec = tv->tv_sec * 1000000;¤/* sec => micro sec */
4a2d69 ¤   ¤   tv->tv_sec = 0;
9c9371 ¤   }
b5efec ¤   tv->tv_usec -= 100000;¤ /* 1/10 of a second */
a4af5a
b5f645 ¤   return( tv->tv_usec <= 0 ? 1 : 0 );
1defe6 }
--b310 0005be3e3de401000b8 Page 1 of unbind.c
bc38e5 /*
a216c4 ·* ·Copyright (c) 1990 Regents of the University of Michigan.
1de4d4 ·* ·All rights reserved.
75775e ·*
647e7a ·* ·unbind.c
be495d ·*/
8baf5a
4e0c68 #ifndef lint·
a007d3 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University "
233efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
4b7454 #endif
57af5a
3efeb2 #include <stdio.h>
38324c #include <string.h>
7caf5a
e5176b #if PGPSOCKETSLDAP /* jason */
9f65aa #include "pgpSocketsLDAP.h"
97ec82 #include "pgpTLS.h"
92af5a
b9db21 #else
07c583 #ifdef MACOS
93bea3 #include <stdlib.h>
2665e0 #include "macos.h"
066c94 #else /* MACOS */
17fdef #if defined( DOS ) || defined( _WIN32 )
bf01b0 #ifdef DOS
7af2ef #include "msdos.h"
7b7454 #endif
ad6382 #ifdef NCSA
5330d1 #include "externs.h"
608682 #endif /* NCSA */
51aad8 #else /* DOS */
08f15e #include <sys/types.h>
135d8c #include <sys/time.h>
2b66f2 #include <sys/socket.h>
c7bc39 #endif /* DOS */
79e962 #endif /* MACOS */
67af5a
da6cbf #ifdef WIN32¤   ¤   ¤   /* marcd */
3f5e84 #include <malloc.h>
8a7454 #endif
45df0f #endif /* PGPSOCKETSLDAP */
6baf5a
cbb779 #include "lber.h"
fde990 #include "ldap.h"
9f745c #include "ldap-int.h"
d1af5a
a8af5a
824d2f int
8a1abe ldap_unbind( LDAP *ld )
78bb36 {
91f90f ¤   Debug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 );
5aaf5a
ee9e92 ¤   return( ldap_ld_free( ld, 1 ));
09efe6 }
1aaf5a
3daf5a
6b4d2f int
176b3e ldap_ld_free( LDAP *ld, int close )
cabb36 {
2e934a ¤   LDAPMessage¤*lm, *next;
68bbe1 ¤   int¤¤   err = LDAP_SUCCESS;
757f8d #ifdef LDAP_REFERRALS
c80160 ¤   LDAPRequest¤*lr, *nextlr;
9b90e2 #endif /* LDAP_REFERRALS */
9eaf5a
fde57c ¤   if ( ld->ld_sb.sb_naddr == 0 ) {
197f8d #ifdef LDAP_REFERRALS
eff9fc ¤   ¤   /* free LDAP structure and outstanding requests/responses */
8e1306 ¤   ¤   for ( lr = ld->ld_requests; lr != NULL; lr = nextlr ) {
bad80b ¤   ¤   ¤   nextlr = lr->lr_next;
5b00fe ¤   ¤   ¤   free_request( ld, lr );
--bf4d 0003e5e3ac9401000b8 Page 2 of unbind.c
b50fe4 ¤   ¤   }
e6af5a
ec5c59 ¤   ¤   /* free and unbind from all open connections */
6bc700 ¤   ¤   while ( ld->ld_conns != NULL ) {
d190ed ¤   ¤   ¤   free_connection( ld, ld->ld_conns, 1, close );
7d0fe4 ¤   ¤   }
7b4267 #else /* LDAP_REFERRALS */
a6b66b ¤   ¤   if ( close ) {
6c25b6 ¤   ¤   ¤   err = send_unbind( ld, &ld->ld_sb );
3e87c7 ¤   ¤   ¤
b7176b #if PGPSOCKETSLDAP /* jason */
c70128 ¤   ¤   if (PGPtlsSessionRefIsValid(ld->tlsSession)) {
e4bba3 ¤   ¤   ¤   PGPtlsClose(ld->tlsSession, FALSE);
f80fe4 ¤   ¤   }
f8df0f #endif /* PGPSOCKETSLDAP */
40af5a
6b6ba7 ¤   ¤   ¤   close_connection( &ld->ld_sb );
b20fe4 ¤   ¤   }
6590e2 #endif /* LDAP_REFERRALS */
02f037 ¤   } else {
59759c ¤   ¤   int¤i;
30af5a
fb9b78 ¤   ¤   for ( i = 0; i < ld->ld_sb.sb_naddr; ++i ) {
d63685 ¤   ¤   ¤   free( ld->ld_sb.sb_addrs[ i ] );
720fe4 ¤   ¤   }
98e151 ¤   ¤   free( ld->ld_sb.sb_addrs );
99358f ¤   ¤   free( ld->ld_sb.sb_fromaddr );
bf9371 ¤   }
36af5a
be637e ¤   for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
fd10a5 ¤   ¤   next = lm->lm_next;
827355 ¤   ¤   ldap_msgfree( lm );
c19371 ¤   }
8aaf5a
b323e9 #ifndef NO_CACHE
53750d ¤   if ( ld->ld_cache != NULL )
0adbbc ¤   ¤   ldap_destroy_cache( ld );
9ee842 #endif /* !NO_CACHE */
9414fa ¤   if ( ld->ld_error != NULL )
fb97f5 ¤   ¤   free( ld->ld_error );
13a134 ¤   if ( ld->ld_matched != NULL )
b1824f ¤   ¤   free( ld->ld_matched );
afea0e ¤   if ( ld->ld_host != NULL )
044420 ¤   ¤   free( ld->ld_host );
011390 ¤   if ( ld->ld_ufnprefix != NULL )
d83042 ¤   ¤   free( ld->ld_ufnprefix );
13f9b0 ¤   if ( ld->ld_filtd != NULL )
981b59 ¤   ¤   ldap_getfilter_free( ld->ld_filtd );
a99588 #ifndef LDAP_REFERRALS
fe5a4d ¤   if ( ld->ld_sb.sb_ber.ber_buf != NULL )
d98873 ¤   ¤   free( ld->ld_sb.sb_ber.ber_buf );
b641c3 #endif /* !LDAP_REFERRALS */
7cc923 ¤   if ( ld->ld_abandoned != NULL )
466785 ¤   ¤   free( ld->ld_abandoned );
88af5a
cc7f8d #ifdef LDAP_REFERRALS
9e1920 ¤   if ( ld->ld_selectinfo != NULL )
7fdb61 ¤   ¤   free_select_info( ld->ld_selectinfo );
ba90e2 #endif /* LDAP_REFERRALS */
b6af5a
b1f874 ¤   if ( ld->ld_defhost != NULL )
2c31f8 ¤   ¤   free( ld->ld_defhost );
29af5a
5fbd19 ¤   free( (char *) ld );
78af5a
6adeb7 ¤   return( err );
14efe6 }
3baf5a
9f4d2f int
865ed0 ldap_unbind_s( LDAP *ld )
cfbb36 {
3e9e92 ¤   return( ldap_ld_free( ld, 1 ));
--9b48 001da3c1c0c401000b8 Page 3 of unbind.c
7aefe6 }
46af5a
8eaf5a
d74d2f int
8a780a send_unbind( LDAP *ld, Sockbuf *sb )
b0bb36 {
359c95 ¤   BerElement¤ *ber;
8aaf5a
eecaac ¤   Debug( LDAP_DEBUG_TRACE, "send_unbind\n", 0, 0, 0 );
02af5a
b347d1 ¤   /* create a message to send */
e16826 ¤   if ( (ber = alloc_ber_with_options( ld )) == NULLBER ) {
e3df73 ¤   ¤   return( ld->ld_errno );
bd9371 ¤   }
00af5a
4caa04 ¤   /* fill it in */
2f6226 ¤   if ( ber_printf( ber, "{itn}", ++ld->ld_msgid,
9ef67a ¤   ····LDAP_REQ_UNBIND ) == -1 ) {
ef3614 ¤   ¤   ld->ld_errno = LDAP_ENCODING_ERROR;
441ab1 ¤   ¤   ber_free( ber, 1 );
9edf73 ¤   ¤   return( ld->ld_errno );
9a9371 ¤   }
e9af5a
2add1f ¤   /* send the message */
a1b80d ¤   if ( ber_flush( sb, ber, 1 ) == -1 ) {
08af4c ¤   ¤   ld->ld_errno = LDAP_SERVER_DOWN;
671ab1 ¤   ¤   ber_free( ber, 1 );
17df73 ¤   ¤   return( ld->ld_errno );
049371 ¤   }
51af5a
17aced ¤   return( LDAP_SUCCESS );
daefe6 }
--da55 000defb55e3401000b9 Page 1 of url.c
bc38e5 /*
bf4805 ·* ·Copyright (c) 1996 Regents of the University of Michigan.
72e4d4 ·* ·All rights reserved.
e6775e ·*
2e0843 ·* ·LIBLDAP url.c -- LDAP URL related routines
33775e ·*
b065db ·* ·LDAP URLs look like this:
4cddc6 ·* ···l d a p : / / hostport / dn [ ? attributes [ ? scope [ ? filter ] ] ]
c2775e ·*
fc3dac ·* ·where:
b205ac ·* ··attributes is a comma separated list
fc3a8b ·* ··scope is one of these three strings: ·base one sub (default=base)
d0918f ·* ··filter is an string-represented filter as in RFC 1558
ee775e ·*
85a698 ·* ·e.g., ·ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich
ab775e ·*
d54d8c ·* ·We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
cf495d ·*/
12af5a
940c68 #ifndef lint·
87c5f9 static char copyright[] = "@(#) Copyright (c) 1996 Regents of the University "
063efd ¤   ¤   ¤   ··"of Michigan.\nAll rights reserved.\n";
8f7454 #endif
b0af5a
51feb2 #include <stdio.h>
79324c #include <string.h>
a4b1cb #include <ctype.h>
85af5a
fc24c3 #if PGPSOCKETSLDAP¤ /* jason */
8565aa #include "pgpSocketsLDAP.h"
66af5a
f3db21 #else
dcc583 #ifdef MACOS
3ebea3 #include <stdlib.h>
bf65e0 #include "macos.h"
e6e962 #endif /* MACOS */
a4af5a
b9fdef #if defined( DOS ) || defined( _WIN32 )
23bea3 #include <stdlib.h>
3c5e84 #include <malloc.h>
ea01b0 #ifdef DOS
21f2ef #include "msdos.h"
777454 #endif
730cf5 #endif /* DOS || _WIN32 */
40af5a
ea3faf #if !defined(MACOS) && !defined(DOS) && !defined( _WIN32 )
8d5d8c #include <sys/time.h>
78f15e #include <sys/types.h>
0666f2 #include <sys/socket.h>
2adfa7 #endif /* !MACOS && !DOS && !_WIN32 */
ecdf0f #endif /* PGPSOCKETSLDAP */
2faf5a
b5b779 #include "lber.h"
f5e990 #include "ldap.h"
f1745c #include "ldap-int.h"
62af5a
25af5a
0f504c #ifdef NEEDPROTOS
9c389b static int skip_url_prefix( char **urlp, int *enclosedp );
0b5019 static void hex_unescape( char *s );
0d7dd0 static int unhex( char c );
856133 #else /* NEEDPROTOS */
da01d0 static int skip_url_prefix();
9ddfc7 static void hex_unescape();
c17f85 static int unhex();
9c8634 #endif /* NEEDPROTOS */
c8af5a
97af5a
4b4d2f int
7f1ce3 ldap_is_ldap_url( char *url )
8dbb36 {
de6fdd ¤   int¤enclosed;
--c613 0004dcb7420401000b9 Page 2 of url.c
e0af5a
cfb39a ¤   return( url != NULL && skip_url_prefix( &url, &enclosed ));
89efe6 }
7caf5a
eaaf5a
96beb7 static int
2db0c7 skip_url_prefix( char **urlp, int *enclosedp )
f6bb36 {
0838e5 /*
931016 ·* return non-zero if this looks like a LDAP URL; zero if not
b687a1 ·* if non-zero returned, *urlp will be moved past "ldap://" part of URL
2c495d ·*/
a1e992 ¤   if ( *urlp == NULL ) {
e2abea ¤   ¤   return( 0 );
f79371 ¤   }
7eaf5a
78c8af ¤   /* skip leading '<' (if any) */
9a7280 ¤   if ( **urlp == '<' ) {
a7a44a ¤   ¤   *enclosedp = 1;
15d1b1 ¤   ¤   ++*urlp;
fcf037 ¤   } else {
fdfe96 ¤   ¤   *enclosedp = 0;
839371 ¤   }
1faf5a
72a5cd ¤   /* skip leading "URL:" (if any) */
5fab7d ¤   if ( strlen( *urlp ) >= LDAP_URL_URLCOLON_LEN && strncasecmp(
0a9bb9 ¤   ····*urlp, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
3e2fe6 ¤   ¤   *urlp += LDAP_URL_URLCOLON_LEN;
5a9371 ¤   }
0aaf5a
1c865a ¤   /* check for missing "ldap://" prefix */
f86b77 ¤   if ( strlen( *urlp ) < LDAP_URL_PREFIX_LEN ||
f08e2e ¤   ····strncasecmp( *urlp, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) != 0 ) {
dfabea ¤   ¤   return( 0 );
d29371 ¤   }
b5af5a
8eb917 ¤   /* skip over "ldap://" prefix and return success */
ee4298 ¤   *urlp += LDAP_URL_PREFIX_LEN;
61e125 ¤   return( 1 );
e7efe6 }
64af5a
03af5a
f5af5a
5b4d2f int
ab0995 ldap_url_parse( char *url, LDAPURLDesc **ludpp )
7cbb36 {
fe38e5 /*
b70a97 ·* ·Pick apart the pieces of an LDAP URL.
33495d ·*/
68af5a
7268dc ¤   LDAPURLDesc¤*ludp;
20b33f ¤   char¤   ¤   *attrs, *p, *q;
29db04 ¤   int¤¤   enclosed, i, nattrs;
06af5a
2a33ba ¤   Debug( LDAP_DEBUG_TRACE, "ldap_url_parse(%s)\n", url, 0, 0 );
73af5a
268803 ¤   *ludpp = NULL;¤ /* pessimistic */
60af5a
74bb9f ¤   if ( !skip_url_prefix( &url, &enclosed )) {
aeb32b ¤   ¤   return( LDAP_URL_ERR_NOTLDAP );
0e9371 ¤   }
f2af5a
3f1f3b ¤   /* allocate return struct */
8eb74c ¤   if (( ludp = (LDAPURLDesc *)calloc( 1, sizeof( LDAPURLDesc )))
33f37c ¤   ····== NULLLDAPURLDESC ) {
5c8a17 ¤   ¤   return( LDAP_URL_ERR_MEM );
e29371 ¤   }
31af5a
c5feba ¤   /* make working copy of the remainder of the URL */
1a1fad ¤   if (( url = strdup( url )) == NULL ) {
e7dedc ¤   ¤   ldap_free_urldesc( ludp );
4d8a17 ¤   ¤   return( LDAP_URL_ERR_MEM );
--447b 000d069fe45401000b9 Page 3 of url.c
a19371 ¤   }
93af5a
2a1d84 ¤   if ( enclosed && *((p = url + strlen( url ) - 1)) == '>' ) {
f03f17 ¤   ¤   *p = '\0';
629371 ¤   }
5aaf5a
b67e5a ¤   /* set defaults */
e0c98c ¤   ludp->lud_scope = LDAP_SCOPE_BASE;
b6d0dc ¤   ludp->lud_filter = "(objectClass=*)";
42af5a
4152d3 ¤   /* lud_string is the only malloc'd string space we use */
e06553 ¤   ludp->lud_string = url;
22af5a
32ff3e ¤   /* scan forward for '/' that marks end of hostport and begin. of dn */
164b4e ¤   if (( ludp->lud_dn = strchr( url, '/' )) == NULL ) {
bbdedc ¤   ¤   ldap_free_urldesc( ludp );
132b25 ¤   ¤   return( LDAP_URL_ERR_NODN );
899371 ¤   }
08af5a
1f2a1d ¤   /* terminate hostport; point to start of dn */
4a6eb1 ¤   *ludp->lud_dn++ = '\0';
3aaf5a
bb6f7f ¤   if (( p = strchr( url, ':' )) != NULL ) {
d37976 ¤   ¤   *p++ = '\0';
392992 ¤   ¤   ludp->lud_port = atoi( p );
429371 ¤   }
20af5a
12ccba ¤   if ( *url == '\0' ) {
efa006 ¤   ¤   ludp->lud_host = NULL;
fff037 ¤   } else {
daf14d ¤   ¤   ludp->lud_host = url;
41c289 ¤   ¤   hex_unescape( ludp->lud_host );
379371 ¤   }
8aaf5a
3e8659 ¤   /* scan for '?' that marks end of dn and beginning of attributes */
9ddc72 ¤   if (( attrs = strchr( ludp->lud_dn, '?' )) != NULL ) {
aef577 ¤   ¤   /* terminate dn; point to start of attrs. */
3b930e ¤   ¤   *attrs++ = '\0';
6aaf5a
a92b22 ¤   ¤   /* scan for '?' that marks end of attrs and begin. of scope */
246b7f ¤   ¤   if (( p = strchr( attrs, '?' )) != NULL ) {
307aad ¤   ¤   ¤   /*
332659 ¤   ¤   ¤   ·* terminate attrs; point to start of scope and scan for
f87145 ¤   ¤   ¤   ·* '?' that marks end of scope and begin. of filter
578753 ¤   ¤   ¤   ·*/
b7c8a7 ¤   ¤   ¤   *p++ = '\0';
9faf5a
362130 ¤   ¤   ¤   if (( q = strchr( p, '?' )) != NULL ) {
3fb822 ¤   ¤   ¤   ¤   /* terminate scope; point to start of filter */
4979af ¤   ¤   ¤   ¤   *q++ = '\0';
560d3c ¤   ¤   ¤   ¤   if ( *q != '\0' ) {
9db3ea ¤   ¤   ¤   ¤   ¤   ludp->lud_filter = q;
6b9f7d ¤   ¤   ¤   ¤   ¤   hex_unescape( ludp->lud_filter );
832613 ¤   ¤   ¤   ¤   }
c2a3a6 ¤   ¤   ¤   }
18af5a
8b5dc5 ¤   ¤   ¤   if ( strcasecmp( p, "one" ) == 0 ) {
b2c80d ¤   ¤   ¤   ¤   ludp->lud_scope = LDAP_SCOPE_ONELEVEL;
5c6093 ¤   ¤   ¤   } else if ( strcasecmp( p, "base" ) == 0 ) {
9c8eea ¤   ¤   ¤   ¤   ludp->lud_scope = LDAP_SCOPE_BASE;
d1fa21 ¤   ¤   ¤   } else if ( strcasecmp( p, "sub" ) == 0 ) {
17694d ¤   ¤   ¤   ¤   ludp->lud_scope = LDAP_SCOPE_SUBTREE;
ec7f63 ¤   ¤   ¤   } else if ( *p != '\0' ) {
8f9163 ¤   ¤   ¤   ¤   ldap_free_urldesc( ludp );
776248 ¤   ¤   ¤   ¤   return( LDAP_URL_ERR_BADSCOPE );
42a3a6 ¤   ¤   ¤   }
080fe4 ¤   ¤   }
4b9371 ¤   }
2baf5a
a78957 ¤   if ( *ludp->lud_dn == '\0' ) {
875d4c ¤   ¤   ludp->lud_dn = NULL;
d0f037 ¤   } else {
--cafd 0005ad98d8b401000b9 Page 4 of url.c
a550cc ¤   ¤   hex_unescape( ludp->lud_dn );
469371 ¤   }
7baf5a
e6d8af ¤   /*
68cd7b ¤   ·* if attrs list was included, turn it into a null-terminated array
39a4e3 ¤   ·*/
dc3eb3 ¤   if ( attrs != NULL && *attrs != '\0' ) {
b43ffc ¤   ¤   for ( nattrs = 1, p = attrs; *p != '\0'; ++p ) {
5d0e91 ¤   ¤   ····if ( *p == ',' ) {
c654f4 ¤   ¤   ¤   ····++nattrs;
0d5f30 ¤   ¤   ····}
1a0fe4 ¤   ¤   }
30af5a
8d4d53 ¤   ¤   if (( ludp->lud_attrs = (char **)calloc( nattrs + 1,
c44673 ¤   ¤   ····sizeof( char * ))) == NULL ) {
f19f2f ¤   ¤   ¤   ldap_free_urldesc( ludp );
5a4f42 ¤   ¤   ¤   return( LDAP_URL_ERR_MEM );
3e0fe4 ¤   ¤   }
ffaf5a
ba7dad ¤   ¤   for ( i = 0, p = attrs; i < nattrs; ++i ) {
3499d9 ¤   ¤   ¤   ludp->lud_attrs[ i ] = p;
d8875a ¤   ¤   ¤   if (( p = strchr( p, ',' )) != NULL ) {
4b78f4 ¤   ¤   ¤   ¤   *p++ ='\0';
3ca3a6 ¤   ¤   ¤   }
b3bee2 ¤   ¤   ¤   hex_unescape( ludp->lud_attrs[ i ] );
b70fe4 ¤   ¤   }
559371 ¤   }
58af5a
4cd313 ¤   *ludpp = ludp;
8aaf5a
9eea61 ¤   return( 0 );
e6efe6 }
20af5a
7caf5a
b4314a void
1a0423 ldap_free_urldesc( LDAPURLDesc *ludp )
61bb36 {
dc10cd ¤   if ( ludp != NULLLDAPURLDESC ) {
cdadc9 ¤   ¤   if ( ludp->lud_string != NULL ) {
3e2e40 ¤   ¤   ¤   free( ludp->lud_string );
830fe4 ¤   ¤   }
ae41d7 ¤   ¤   if ( ludp->lud_attrs != NULL ) {
66fa74 ¤   ¤   ¤   free( ludp->lud_attrs );
ff0fe4 ¤   ¤   }
c85cb0 ¤   ¤   free( ludp );
f59371 ¤   }
22efe6 }
f7af5a
70af5a
31af5a
284d2f int
db67a3 ldap_url_search( LDAP *ld, char *url, int attrsonly )
d5bb36 {
1df4e8 ¤   int¤¤   err;
2668dc ¤   LDAPURLDesc¤*ludp;
a19c95 ¤   BerElement¤ *ber;
037f8d #ifdef LDAP_REFERRALS
0418a7 ¤   LDAPServer¤ *srv = NULL;
6d90e2 #endif /* LDAP_REFERRALS */
33af5a
f6c02f ¤   if ( ldap_url_parse( url, &ludp ) != 0 ) {
7dbfd2 ¤   ¤   ld->ld_errno = LDAP_PARAM_ERROR;
bc49fa ¤   ¤   return( -1 );
d39371 ¤   }
49af5a
fda642 ¤   if (( ber = ldap_build_search_req( ld, ludp->lud_dn, ludp->lud_scope,
07cdab ¤   ····ludp->lud_filter, ludp->lud_attrs, attrsonly )) == NULLBER ) {
d849fa ¤   ¤   return( -1 );
379371 ¤   }
52af5a
dc1ff2 ¤   err = 0;
5aaf5a
--7e61 000f14694a2401000b9 Page 5 of url.c
0c4d44 ¤   if ( ludp->lud_host != NULL || ludp->lud_port != 0 ) {
e17f8d #ifdef LDAP_REFERRALS
d2d4ed ¤   ¤   if (( srv = (LDAPServer *)calloc( 1, sizeof( LDAPServer )))
279fac ¤   ¤   ····== NULL || ( srv->lsrv_host = strdup( ludp->lud_host ==
60851a ¤   ¤   ····NULL ? ld->ld_defhost : ludp->lud_host )) == NULL ) {
147106 ¤   ¤   ¤   if ( srv != NULL ) {
8d1d3f ¤   ¤   ¤   ¤   free( srv );
d2a3a6 ¤   ¤   ¤   }
bf6150 ¤   ¤   ¤   ld->ld_errno = LDAP_NO_MEMORY;
a050d9 ¤   ¤   ¤   err = -1;
1745a6 ¤   ¤   } else {
0eff7b ¤   ¤   ¤   if ( ludp->lud_port == 0 ) {
924f23 ¤   ¤   ¤   ¤   srv->lsrv_port = LDAP_PORT;
d0042d ¤   ¤   ¤   } else {
78913c ¤   ¤   ¤   ¤   ·srv->lsrv_port = ludp->lud_port;
3ca3a6 ¤   ¤   ¤   }
120fe4 ¤   ¤   }
9d4267 #else /* LDAP_REFERRALS */
d9bad6 ¤   ¤   ld->ld_errno = LDAP_LOCAL_ERROR;
0b6a43 ¤   ¤   err = -1;
1990e2 #endif /* LDAP_REFERRALS */
af9371 ¤   }
6daf5a
80aa2b ¤   if ( err != 0 ) {
431ab1 ¤   ¤   ber_free( ber, 1 );
54f037 ¤   } else {
5b7f8d #ifdef LDAP_REFERRALS
d0a6e3 ¤   ¤   err = send_server_request( ld, ber, ld->ld_msgid, NULL, srv,
97590a ¤   ¤   ····NULL, 1 );
464267 #else /* LDAP_REFERRALS */
6a7a61 ¤   ¤   err = send_initial_request( ld, LDAP_REQ_SEARCH,
c1d392 ¤   ¤   ····ludp->lud_dn, ber );
9690e2 #endif /* LDAP_REFERRALS */
2f9371 ¤   }
1aaf5a
5f52a3 ¤   ldap_free_urldesc( ludp );
32af5a
37deb7 ¤   return( err );
5aefe6 }
46af5a
4caf5a
584d2f int
1df654 ldap_url_search_st( LDAP *ld, char *url, int attrsonly,
ab8921 ¤   struct timeval *timeout, LDAPMessage **res )
eebb36 {
e448fe ¤   int¤msgid;
33af5a
54c022 ¤   if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) {
1edf73 ¤   ¤   return( ld->ld_errno );
659371 ¤   }
d9af5a
b3dd6b ¤   if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) {
66df73 ¤   ¤   return( ld->ld_errno );
4c9371 ¤   }
5daf5a
b479b4 ¤   if ( ld->ld_errno == LDAP_TIMEOUT ) {
e9cc12 ¤   ¤   (void) ldap_abandon( ld, msgid );
a9d85c ¤   ¤   ld->ld_errno = LDAP_TIMEOUT;
6cdf73 ¤   ¤   return( ld->ld_errno );
b49371 ¤   }
31af5a
6642f4 ¤   return( ldap_result2error( ld, *res, 0 ));
f1efe6 }
b8af5a
d7af5a
2d4d2f int
ab1f6c ldap_url_search_s( LDAP *ld, char *url, int attrsonly, LDAPMessage **res )
79bb36 {
0748fe ¤   int¤msgid;
2eaf5a
b1c022 ¤   if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) {
f1df73 ¤   ¤   return( ld->ld_errno );
--ab29 00173b14d3e401000b9 Page 6 of url.c
a19371 ¤   }
93af5a
45ec9d ¤   if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, res ) == -1 ) {
d3df73 ¤   ¤   return( ld->ld_errno );
aa9371 ¤   }
8aaf5a
dd42f4 ¤   return( ldap_result2error( ld, *res, 0 ));
80efe6 }
7eaf5a
6faf5a
4d2978 static void
4d5982 hex_unescape( char *s )
51bb36 {
5b38e5 /*
8bcc0a ·* Remove URL hex escapes from s... done in place. ·The basic concept for
372696 ·* this routine is borrowed from the WWW library HTUnEscape() routine.
c5495d ·*/
dc15bd ¤   char¤   *p;
cfaf5a
695012 ¤   for ( p = s; *s != '\0'; ++s ) {
e85a84 ¤   ¤   if ( *s == '%' ) {
985a84 ¤   ¤   ¤   if ( *++s != '\0' ) {
f0fa29 ¤   ¤   ¤   ¤   *p = unhex( *s ) << 4;
ada3a6 ¤   ¤   ¤   }
725a84 ¤   ¤   ¤   if ( *++s != '\0' ) {
eef831 ¤   ¤   ¤   ¤   *p++ += unhex( *s );
81a3a6 ¤   ¤   ¤   }
7345a6 ¤   ¤   } else {
921d0a ¤   ¤   ¤   *p++ = *s;
bf0fe4 ¤   ¤   }
e79371 ¤   }
9eaf5a
5dddb4 ¤   *p = '\0';
73efe6 }
7eaf5a
a2af5a
ebbeb7 static int
42f332 unhex( char c )
0abb36 {
83ea0d ¤   return( c >= '0' && c <= '9' ? c - '0'
d3422e ¤   ····: c >= 'A' && c <= 'F' ? c - 'A' + 10
86ce8a ¤   ····: c - 'a' + 10 );
73efe6 }
--5d2a 000f6d5bce4401000ba Page 1 of pgpSockets-ip.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
aa9d5b ¤   $Id: pgpSockets-ip.c,v 1.6.10.1 1998/11/12 03:17:46 heller Exp $
29f7f7 ____________________________________________________________________________*/
42af5a
4eb1cb #include <ctype.h>
20feb2 #include <stdio.h>
73324c #include <string.h>
fabea3 #include <stdlib.h>
996b82 #include <Memory.h>
e365aa #include "pgpSocketsLDAP.h"
96b779 #include "lber.h"
cde990 #include "ldap.h"
3c745c #include "ldap-int.h"
a8af5a
7e2a9a #include "portable.h"
f5af5a
e16eb6 #include "PGPSockets.h"
fbaf5a
09af5a
3c7f8d #ifdef LDAP_REFERRALS
d6f375 #ifdef USE_SYSCONF
7a17c2 #include <unistd.h>
b27d11 #endif /* USE_SYSCONF */
12b7e5 #ifdef notyet
1decad #ifdef NEED_FILIO
20389f #include <sys/filio.h>
1aa180 #else /* NEED_FILIO */
10c051 #include <sys/ioctl.h>
484687 #endif /* NEED_FILIO */
0adb56 #endif /* notyet */
ac90e2 #endif /* LDAP_REFERRALS */
6daf5a
22af5a
36af5a
e438e5 /*
cde131 ·* Check whether "cp" is a valid ascii representation
99c2ad ·* of an Internet address and convert to a binary address.
2fa0a3 ·* Returns 1 if the address is valid, 0 if not.
de6da6 ·* This replaces inet_addr, the return value from which
575a0e ·* cannot distinguish between failure and a local broadcast address.
2f495d ·*/
97af5a
60d63c static inet_aton(cp, addr)
c6d4a8 ¤   register char *cp;
31fe88 ¤   ulong *addr;
86bb36 {
f8bb50 ¤   register ulong val, base, n;
8200cd ¤   register char c;
89da75 ¤   ulong parts[4], *pp = parts;
69af5a
b0220e ¤   for (;;) {
2e1b17 ¤   ¤   /*
46125e ¤   ¤   ·* Collect number up to ``.''.
dc57a6 ¤   ¤   ·* Values are specified as for C:
9fc0ae ¤   ¤   ·* 0x=hex, 0=octal, other=decimal.
9f9de3 ¤   ¤   ·*/
04009d ¤   ¤   val = 0; base = 10;
63f904 ¤   ¤   if (*cp == '0') {
546853 ¤   ¤   ¤   if (*++cp == 'x' || *cp == 'X')
140c32 ¤   ¤   ¤   ¤   base = 16, cp++;
f5bb8c ¤   ¤   ¤   else
6564da ¤   ¤   ¤   ¤   base = 8;
ef0fe4 ¤   ¤   }
146591 ¤   ¤   while ((c = *cp) != '\0') {
e49f31 ¤   ¤   ¤   if (isascii(c) && isdigit(c)) {
44f606 ¤   ¤   ¤   ¤   val = (val * base) + (c - '0');
f6894c ¤   ¤   ¤   ¤   cp++;
--cb31 000eb786536401000ba Page 2 of pgpSockets-ip.c
1bd040 ¤   ¤   ¤   ¤   continue;
faa3a6 ¤   ¤   ¤   }
092dd5 ¤   ¤   ¤   if (base == 16 && isascii(c) && isxdigit(c)) {
96dc73 ¤   ¤   ¤   ¤   val = (val << 4) +
3dd1ba ¤   ¤   ¤   ¤   ¤   (c + 10 - (islower(c) ? 'a' : 'A'));
fc894c ¤   ¤   ¤   ¤   cp++;
75d040 ¤   ¤   ¤   ¤   continue;
eca3a6 ¤   ¤   ¤   }
96cdcb ¤   ¤   ¤   break;
4a0fe4 ¤   ¤   }
528216 ¤   ¤   if (*cp == '.') {
9e7aad ¤   ¤   ¤   /*
4fa9b2 ¤   ¤   ¤   ·* Internet format:
226257 ¤   ¤   ¤   ·*¤ a.b.c.d
4b3c9b ¤   ¤   ¤   ·*¤ a.b.c¤  (with c treated as 16-bits)
4060db ¤   ¤   ¤   ·*¤ a.b¤(with b treated as 24 bits)
118753 ¤   ¤   ¤   ·*/
46f96f ¤   ¤   ¤   if (pp >= parts + 3 || val > 0xff)
6b7d98 ¤   ¤   ¤   ¤   return (0);
55932e ¤   ¤   ¤   *pp++ = val, cp++;
ce4a5d ¤   ¤   } else
aecdcb ¤   ¤   ¤   break;
119371 ¤   }
b9d8af ¤   /*
0e1399 ¤   ·* Check for trailing characters.
46a4e3 ¤   ·*/
05a5cf ¤   if (*cp && (!isascii(*cp) || !isspace(*cp)))
5bf109 ¤   ¤   return (0);
27d8af ¤   /*
f8ef46 ¤   ·* Concoct the address according to
3c5397 ¤   ·* the number of parts specified.
96a4e3 ¤   ·*/
18ec3a ¤   n = pp - parts + 1;
aa750e ¤   switch (n) {
f5af5a
2c2e24 ¤   case 1:¤¤   ¤   ¤   /* a -- 32 bits */
772f68 ¤   ¤   break;
7aaf5a
7cc60b ¤   case 2:¤¤   ¤   ¤   /* a.b -- 8.24 bits */
3d09ab ¤   ¤   if (val > 0xffffff)
5f8bfd ¤   ¤   ¤   return (0);
f14bca ¤   ¤   val |= parts[0] << 24;
6d2f68 ¤   ¤   break;
38af5a
4a4989 ¤   case 3:¤¤   ¤   ¤   /* a.b.c -- 8.8.16 bits */
8dd149 ¤   ¤   if (val > 0xffff)
238bfd ¤   ¤   ¤   return (0);
423108 ¤   ¤   val |= (parts[0] << 24) | (parts[1] << 16);
e02f68 ¤   ¤   break;
66af5a
b57c0f ¤   case 4:¤¤   ¤   ¤   /* a.b.c.d -- 8.8.8.8 bits */
1116a6 ¤   ¤   if (val > 0xff)
088bfd ¤   ¤   ¤   return (0);
28a888 ¤   ¤   val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
672f68 ¤   ¤   break;
bd9371 ¤   }
e52078 ¤   if (addr)
9897bf ¤   ¤   *addr = PGPHostToNetLong(val);
947ac1 ¤   return (1);
a3efe6 }
96af5a
b5e1df #define¤INADDR_NONE¤0xffffffff¤ ¤   /* -1 return */
18af5a
1638e5 /*
2d072f ·* Ascii internet address interpretation routine.
2cd83b ·* The value returned is in network order.
cb775e ·*
f2c38b ·* I changed the name since the definition conflicted with the system
b65cdb ·* ··supplied function. ·marcd 4/3/98
55495d ·*/
9077fd static long
ebd4f1 inet_addr_internal(cp)
--0e8f 0004b2f0b78401000ba Page 3 of pgpSockets-ip.c
127629 ¤   register const char *cp;
3cbb36 {
8464c6 ¤   ulong val;
3baf5a
7808ab ¤   if (inet_aton(cp, &val))
31230f ¤   ¤   return (val);
17af5a
4a09a4 ¤   return (INADDR_NONE);
d5efe6 }
45af5a
13af5a
b9af5a
984d2f int
46fba8 connect_to_host( Sockbuf *sb, char *host, unsigned long address,
e84161 ¤   int port, int async )
c738e5 /*
8c5f6a ·* if host == NULL, connect using address
364add ·* "address" and "port" must be in network byte order
557f4f ·* zero is returned upon success, -1 if fatal error, -2 EINPROGRESS
835732 ·* async is only used ifdef LDAP_REFERRALS (non-0 means don't wait for connect)
586d2c ·* XXX async is not used yet!
8c495d ·*/
a7bb36 {
3ba46b ¤   int¤¤   ¤   ¤   ¤   ¤   ¤   rc, i, connected, use_hp;
762de6 ¤   PGPSocketAddressInternet¤   sin;
fb83f7 ¤   PGPHostEntry¤   ¤   ¤   ¤   *hp;
429371 ¤   PGPSocketRef¤   ¤   ¤   ¤   socketRef;
ed2225 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   connectResult;
0dfd25 ¤   PGPError¤   ¤   ¤   ¤   ¤   pgpErr = kPGPError_NoErr;
d367c5 ¤
71c47e ¤   (void) async;
7b67c5 ¤
1cb7e5 #ifdef notyet
6f7f8d #ifdef LDAP_REFERRALS
6afc6e ¤   int¤¤   ¤   status;¤/* for ioctl call */
4190e2 #endif /* LDAP_REFERRALS */
6bdb56 #endif /* notyet */
44af5a
360c85 ¤   Debug( LDAP_DEBUG_TRACE, "connect_to_host: %s:%d\n",
ecb44c ¤   ····( host == NULL ) ? "(by address)" : host,
6a9634 ¤   ¤   PGPNetToHostShort( (short)port ), 0 );
6faf5a
ffa393 ¤   connected = use_hp = 0;
d3af5a
63c733 ¤   if ( host != NULL && ( address = inet_addr_internal( host )) == -1 ) {
8eafb9 #if PGP_WIN32
9d9907 ¤   ¤   pgpErr = PGPStartAsyncGetHostByName(host, &sb->ref);
4ad757 ¤   ¤   if (pgpErr != kPGPError_NoErr) {
41c36a ¤   ¤   ¤   return ( -1 );
390fe4 ¤   ¤   }
7c8009 ¤   ¤   pgpErr = PGPWaitForGetHostByName(sb->ref, &address);
a04514 ¤   ¤   sb->ref = kPGPInvalidAsyncHostEntryRef;
08d757 ¤   ¤   if (pgpErr != kPGPError_NoErr) {
05c36a ¤   ¤   ¤   return ( -1 );
0c0fe4 ¤   ¤   }
b8db21 #else
b6c723 ¤   ¤   if ( (hp = PGPGetHostByName( host )) == NULL ) {
c68e4f ¤   ¤   ¤   return( -1 );
200fe4 ¤   ¤   }
ad467e ¤   ¤   use_hp = 1;
8a7454 #endif
a89371 ¤   }
2eaf5a
18f83f ¤   rc = -1;
557366 ¤   for ( i = 0; !use_hp || ( hp->h_addr_list[ i ] != 0 ); i++ )
72c7a1 ¤   {
76844f ¤   ¤   socketRef = PGPOpenSocket( kPGPAddressFamilyInternet, kPGPSocketTypeStr¶
1128a6 eam, kPGPTCPProtocol );
558cae ¤   ¤   if( socketRef == kInvalidPGPSocketRef )
a85b34 ¤   ¤   {
df8e4f ¤   ¤   ¤   return( -1 );
4b0fe4 ¤   ¤   }
--b1bf 000a513cfd7401000ba Page 4 of pgpSockets-ip.c
23b7e5 #ifdef notyet
b77f8d #ifdef LDAP_REFERRALS
3746f6 ¤   ¤   status = 1;
836a96 ¤   ¤   if ( async && ioctl( s, FIONBIO, (caddr_t)&status ) == -1 ) {
f61c37 ¤   ¤   ¤   Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
791cf2 ¤   ¤   ¤   ····s, 0, 0 );
aa0fe4 ¤   ¤   }
b390e2 #endif /* LDAP_REFERRALS */
f9db56 #endif /* notyet */
8bd9b3 ¤   ¤   (void)memset( (char *)&sin, 0, sizeof( sin ));
a08fbd ¤   ¤   sin.sin_family = kPGPAddressFamilyInternet;
74d38c ¤   ¤   sin.sin_port = port;
389de9 ¤   ¤   SAFEMEMCPY( (char *) &sin.sin_addr.s_addr,
598cb9 ¤   ¤   ····( use_hp ? (char *) hp->h_addr_list[ i ] :
5e06a5 ¤   ¤   ····(char *) &address ), sizeof( sin.sin_addr.s_addr) );
31af5a
c52438 ¤   ¤   connectResult = PGPConnect( socketRef, (PGPSocketAddress *)&sin,
f8cb33 ¤   ¤   ····sizeof( sin ));
0faf5a
573f1b ¤   ¤   if ( connectResult >= 0 ) {
14abec ¤   ¤   ¤   connected = 1;
a7e256 ¤   ¤   ¤   rc = 0;
47cdcb ¤   ¤   ¤   break;
0845a6 ¤   ¤   } else {
60b7e5 #ifdef notyet
a27f8d #ifdef LDAP_REFERRALS
b2935b #ifdef EAGAIN
d63e65 ¤   ¤   ¤   if ( errno == EINPROGRESS || errno == EAGAIN ) {
1e9760 #else /* EAGAIN */
e5ff24 ¤   ¤   ¤   if ( errno == EINPROGRESS ) {
15055c #endif /* EAGAIN */
ebc3e3 ¤   ¤   ¤   ¤   Debug( LDAP_DEBUG_TRACE,
9beab5 ¤   ¤   ¤   ¤   ¤   "connect would block...\n", 0, 0, 0 );
b95290 ¤   ¤   ¤   ¤   rc = -2;
08f622 ¤   ¤   ¤   ¤   break;
25a3a6 ¤   ¤   ¤   }
1090e2 #endif /* LDAP_REFERRALS */
12db56 #endif /* notyet */
09af5a
084d30 ¤   ¤   ¤   PGPCloseSocket( socketRef );
6d6860 ¤   ¤   ¤   if ( !use_hp ) {
32f622 ¤   ¤   ¤   ¤   break;
b1a3a6 ¤   ¤   ¤   }
890fe4 ¤   ¤   }
9f9371 ¤   }
32af5a
d969f9 ¤   sb->sb_sd = socketRef;
2c4f08 //¤ sb->sb_options |= LBER_NO_READ_AHEAD; /* jason */
1aaf5a
80b4aa ¤   if ( connected ) {
b4b7e5 #ifdef notyet
ad7f8d #ifdef LDAP_REFERRALS
d91c2a ¤   ¤   status = 0;
f3ca15 ¤   ¤   if ( !async && ioctl( s, FIONBIO, (caddr_t)&on ) == -1 ) {
7f1c37 ¤   ¤   ¤   Debug( LDAP_DEBUG_ANY, "FIONBIO ioctl failed on %d\n",
4e1cf2 ¤   ¤   ¤   ····s, 0, 0 );
820fe4 ¤   ¤   }
db90e2 #endif /* LDAP_REFERRALS */
6fdb56 #endif /* notyet */
98af5a
739371 ¤   }
04af5a
c06d62 ¤   return( rc );
aeefe6 }
e7af5a
72af5a
b5af5a
50314a void
64ff21 close_connection( Sockbuf *sb )
63bb36 {
1674d4 ····PGPCloseSocket( sb->sb_sd );
a5efe6 }
--c966 0011a3a0194401000ba Page 5 of pgpSockets-ip.c
e0af5a
1aaf5a
--4f5a 001b8985098401000bb Page 1 of pgpSocketsLDAP.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
d24a30 ¤   $Id: pgpSocketsLDAP.h,v 1.4.10.1 1998/11/12 03:17:47 heller Exp $
7bf7f7 ____________________________________________________________________________*/
46af5a
a247f5 #ifndef Included_pgpSocketsLDAP_h
2e9969 #define Included_pgpSocketsLDAP_h
96af5a
92eb0f #ifdef PGP_WIN32
ca2d5f #include <winsock.h>
b57454 #endif
d7af5a
b943dd #ifdef PGP_MACINTOSH
77bea3 #include <stdlib.h>
09af5a
3397da #include "PGPldapLibUtils.h"
49af5a
b14b15 #include <TextUtils.h>
47af5a
59d2cb #define strcasecmp( s1, s2 )¤   IdenticalText( s1, s2, strlen( s1 ), \
ccc7f1 ¤   ¤   ¤   ¤   ¤   strlen( s2 ), nil )
b7af5a
93af5a
c07c9d #include <Memory.h>¤/* to get BlockMove() */
8eaf5a
1ddaf9 #ifndef isascii
f6b978 #define isascii(c)¤ ((unsigned)(c)<=0177)¤  /* for those who don't have this in¶
7aeb48 ·ctype.h */
0c308c #endif isascii
76af5a
20a513 #define ntohl( l )¤ PGPNetToHostLong(l)
190139 #define htonl( l )¤ PGPHostToNetLong(l)
6d5663 #define ntohs( s )¤ PGPNetToHostShort(s)
6ad89f #define htons( s )¤ PGPHostToNetShort(s)
63af5a
2e1164 struct timeval {
fe9cf0 ¤   PGPInt32¤   tv_sec;
b86eaa ¤   PGPInt32¤   tv_usec;
7e82f7 };
cd7454 #endif
9baf5a
09af5a
b82841 #endif¶
--bd52 0019d5c7dcf401000bc Page 1 of Makefile.in
5ea601 #
f91455 # Top level makefile
8ba601 #
459908 # $Id: Makefile.in,v 1.3 1997/07/28 01:53:24 mhw Exp $
8ca601 #
72af5a
b9d2ae SUBDIRS= common
fcaf5a
00f70b LIBDONE= common/LIBDONE
4daf5a
2059bc LIBTARGET= libpfl.a
f941e7 LIBTDEPS= LIBDONE
04af5a
859f6e INSTALLLIBS= $(LIBTARGET)
16af5a
90b34c all:: LIBDONE $(LIBTARGET)
0caf5a
184886 world::
8b6b63 ¤   $(MAKE) $(MFLAGS) headers
633166 ¤   $(MAKE) $(MFLAGS) depend
d1d992 ¤   $(MAKE) $(MFLAGS) all
38af5a
8d53f5 clean::
8e1b0f ¤   rm -f $(LIBTARGET)
9daf5a
--590b 000b3b61435401000bd Page 1 of aclocal.m4
df9df1 dnl
fb2692 dnl Local autoconf configuration macros for PGP 3
c79df1 dnl
78b27c dnl $Id: aclocal.m4,v 1.1 1997/07/17 00:28:36 mhw Exp $
a39df1 dnl
a0af5a
ac9df1 dnl
5734e3 dnl The big finish.
4ec5f4 dnl Produce config.status, config.h, and links, and configure subdirs.
3a15cf dnl PGP_AC_OUTPUT([FILE...] [, PRE.IN] [, POST.IN] [, EXTRA-CMDS]·
77818e dnl ¤   [, INIT-CMDS])
697429 define(PGP_AC_OUTPUT,
87cef8 [trap '' 1 2 15
a6467d AC_CACHE_SAVE
76bbd5 trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' \
87f97f ¤   1 2 15
feaf5a
5b6c40 test "x$prefix" = xNONE && prefix=$ac_default_prefix
5fbd2e # Let make expand exec_prefix.
da1d0d test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
50af5a
d64b0d # Any assignment to VPATH causes Sun make to only execute
c9798f # the first set of double-colon rules, so remove it if not needed.
801003 # If there is a colon in the path, we need to keep it.
eec767 if test "x$srcdir" = x.; then
f97447 changequote(, )dnl
34d9ad ··ac_vpsub='/^[ ¤   ]*VPATH[ ¤  ]*=[^:]*$/d'
ceb0bc changequote([, ])dnl
83ce83 fi
beaf5a
4d1b66 trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
e0af5a
4d109c ifdef([AC_LIST_HEADER], [DEFS=-DHAVE_CONFIG_H], [AC_OUTPUT_MAKE_DEFS()])
d9af5a
e23f7c # Without the "./", some shells look in PATH for config.status.
448a5f : ${CONFIG_STATUS=./config.status}
63af5a
42b3f7 echo creating $CONFIG_STATUS
07bde5 rm -f $CONFIG_STATUS
69a54d cat > $CONFIG_STATUS <<EOF
66cbfe #! /bin/sh
b3c6e6 # Generated automatically by configure.
7df233 # Run this file to recreate the current configuration.
fc730d # This directory was configured as follows,
58b7e7 dnl hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
185512 dnl so uname gets run too.
a7d1ef # on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
38a601 #
0873a8 [#] [$]0 [$]ac_configure_args
c8a601 #
90f973 # Compiler output produced by configure, useful for debugging
37f544 # configure, is in ./config.log if it exists.
0eaf5a
547447 changequote(, )dnl
074af9 ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
62b0bc changequote([, ])dnl
af2450 for ac_option
6d2feb do
30af84 ··case "[\$]ac_option" in
e9f722 ··-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
4a069b ····echo "running [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args" \
43bbe9 ¤   ¤   "--no-create --no-recursion"
f8c724 ····exec [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create \
bf08e1 ¤   ¤   --no-recursion ;;
9bb252 ··-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
fad947 ····echo "$CONFIG_STATUS generated by autoconf version AC_ACVERSION"
ca7a51 ····exit 0 ;;
af5939 ··-help | --help | --hel | --he | --h)
22509c ····echo "[\$]ac_cs_usage"; exit 0 ;;
850eb9 ··*) echo "[\$]ac_cs_usage"; exit 1 ;;
cf0e75 ··esac
b3065f done
--7856 000c2ce00b4401000bd Page 2 of aclocal.m4
e0af5a
d029b7 ac_given_srcdir=$srcdir
5af2de ifdef([AC_PROVIDE_AC_PROG_INSTALL], [ac_given_INSTALL="$INSTALL"
26d9ba ])dnl
25af5a
2c03ee changequote(<<, >>)dnl
435465 ifdef(<<AC_LIST_HEADER>>,
42753f <<trap 'rm -fr `echo "$1 AC_LIST_HEADER" | sed "s/:[^ ]*//g"` conftest*; \
e3bf03 ¤   exit 1' 1 2 15>>,
66ae70 <<trap 'rm -fr `echo "$1" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15>>)
34b0bc changequote([, ])dnl
bfaf5a
d080ca PGP_AC_OUTPUT_FILES($1, $2, $3)
b21b1b ifdef([AC_LIST_HEADER], [AC_OUTPUT_HEADER(AC_LIST_HEADER)])dnl
93d588 ifdef([AC_LIST_LINKS], [AC_OUTPUT_LINKS(AC_LIST_FILES, AC_LIST_LINKS)])dnl
3c5c2e ifelse([$5], , ,·
a0bb33 [EOF
d5d5c9 cat >> $CONFIG_STATUS <<EOF
f7071a $5
2689bd EOF
259df3 cat >> $CONFIG_STATUS <<\EOF])
721ec2 $4
a172c2 exit 0
bc89bd EOF
ea8f87 chmod +x $CONFIG_STATUS
b78316 rm -fr confdefs* $ac_clean_files
edcfdc test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
166644 dnl config.status should not do recursion.
9d5d44 ifdef([AC_LIST_SUBDIRS], [AC_OUTPUT_SUBDIRS(AC_LIST_SUBDIRS)])dnl
42d9ba ])dnl
69af5a
c236d9 dnl This is a subroutine of PGP_AC_OUTPUT. ·It is called inside an unquoted
49b99c dnl here document whose contents are going into config.status.
bfe230 dnl PGP_AC_OUTPUT_FILES(FILE..., PRE.IN, POST.IN)
4f4cdb define(PGP_AC_OUTPUT_FILES,
6b618d [# Protect against being on the right side of a sed subst in config.status.·
be7447 changequote(, )dnl
fc7172 sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g;·
8d8722 ·s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
83b0bc changequote([, ])dnl
3ecfce dnl These here document variables are unquoted when configure runs
adfdbe dnl but quoted when config.status runs, so variables are expanded once.
c0853e $ac_vpsub
b4683e dnl Shell code in configure.in might set extrasub.
7cfc66 $extrasub
38cd8a dnl Insert the sed substitutions of variables.
e49b67 undivert(AC_DIVERSION_SED)
7c5553 CEOF
6689bd EOF
78d5c9 cat >> $CONFIG_STATUS <<EOF
89af5a
b54424 CONFIG_FILES=\${CONFIG_FILES-"$1"}
d383cb CONFIG_PRE=\${CONFIG_PRE-"$2"}
076484 CONFIG_POST=\${CONFIG_POST-"$3"}
e589bd EOF
eabe10 cat >> $CONFIG_STATUS <<\EOF
3dd90f dnl Check for the existence of the pre and post files _FIRST_
25516f # test for pre and post files, to make sure they exist
55851d if test -r "$ac_given_srcdir/$CONFIG_PRE"; then
87fe7c ··ac_config_pre="$ac_given_srcdir/$CONFIG_PRE"
b78881 ··echo "Using $ac_config_pre for pre-makefile"
18523c else
737399 ··ac_config_pre=""
8c027f ··echo "No file $CONFIG_PRE"
e4ce83 fi
edaf5a
f6d550 if test -r "$ac_given_srcdir/$CONFIG_POST"; then
931fa9 ··ac_config_post="$ac_given_srcdir/$CONFIG_POST"
2ce53d ··echo "Using $ac_config_post for post-makefile"
78523c else
b06b40 ··ac_config_post=""
c2dfd5 ··echo "No file $CONFIG_POST"
--4ce5 0017ae11bc9401000bd Page 3 of aclocal.m4
18ce83 fi
43af5a
ea66fb for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
be8ef2 dnl Specifying an input file breaks the trap to clean up on interrupt,
5c6c2a dnl but that's not a huge problem.
bad001 ··# Support "outfile[:infile]", defaulting infile="outfile.in".
7ce80f ··case "$ac_file" in
f6394c ··*:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
20a691 ·······ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
b844cd ··*) ac_file_in="${ac_file}.in" ;;
4c0e75 ··esac
36af5a
bd1427 ··# Adjust relative srcdir, etc. for subdirectories.
c6af5a
4ac805 ··# Remove last slash and all that follows it. ·Not all systems have dirname.
027447 changequote(, )dnl
62d4a5 ··ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
9fb0bc changequote([, ])dnl
dbb1d2 ··if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
fb7cd1 ····# The file is in a subdirectory.
e76756 ····test ! -d "$ac_dir" && mkdir "$ac_dir"
dda752 ····ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
4a82a5 ····# A "../" for each directory in $ac_dir_suffix.
1e7447 changequote(, )dnl
becb2a ····ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
1ab0bc changequote([, ])dnl
bd1bd0 ··else
276402 ····ac_dir_suffix= ac_dots=
c09666 ··fi
31af5a
50148f ··case "$ac_given_srcdir" in
01a29a ··.) ·srcdir=.
382258 ······if test -z "$ac_dots"; then top_srcdir=.
5a2d19 ······else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
ffdf8e ··/*) srcdir="$ac_given_srcdir$ac_dir_suffix"
b3de94 ······top_srcdir="$ac_given_srcdir" ;;
95c254 ··*) # Relative path.
730457 ····srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
521e5c ····top_srcdir="$ac_dots$ac_given_srcdir" ;;
8c0e75 ··esac
cdaf5a
9e8cf1 ifdef([AC_PROVIDE_AC_PROG_INSTALL],
e946c0 [ ·case "$ac_given_INSTALL" in
bf7447 changequote(, )dnl
dbfc22 ··[/$]*) INSTALL="$ac_given_INSTALL" ;;
c8b0bc changequote([, ])dnl
7dcffa ··*) INSTALL="$ac_dots$ac_given_INSTALL" ;;
090e75 ··esac
3fd9ba ])dnl
67df95 ··echo creating "$ac_file"
987be8 ··rm -f "$ac_file"
5865a2 ··conf_in_file="`echo $ac_file_in|sed 's%.*/%%'`"
fea068 ··configure_input="Generated automatically from $conf_in_file by configure."
8fe80f ··case "$ac_file" in
315fec ··*Makefile*) ac_comsub="1i\\
8c68ff # $configure_input" ;;
a09e45 ··*) ac_comsub= ;;
0e0e75 ··esac
e71191 ··sed -e "$ac_comsub
a2f10f s%@configure_input@%$configure_input%g
9f0788 s%@srcdir@%$srcdir%g
540e12 s%@top_srcdir@%$top_srcdir%g
362048 s%@top_builddir@%$ac_dots.%g
a16ecb s%@dir_suffix@%$ac_dir_suffix%g
6bdbad ifdef([AC_PROVIDE_AC_PROG_INSTALL], [s%@INSTALL@%$INSTALL%g
fad9ba ])dnl
a8cc78 " -f conftest.subs $ac_config_pre $ac_given_srcdir/$ac_file_in \
52de7a ¤   ¤   $ac_config_post > $ac_file
c2e9b0 fi; done
d66ad6 rm -f conftest.subs
7a27ed ])
--7cd8 0006b1e993a401000be Page 1 of configure.in
df9df1 dnl
7e2249 dnl $Id: configure.in,v 1.10 1998/03/14 01:27:39 elowe Exp $
b69df1 dnl
69b740 dnl This file in input to autoconf. ·It consists of a series of m4
6d8941 dnl macros which expand to produce the shell script "configure".
662be6 dnl Anything which is not an m4 macro is copied directly to the output.
7d9df1 dnl
05924f dnl Start things up. ·If the specified file doesn't exist, configure
21b8be dnl will complain.
bfaf5a
557577 AC_INIT(common/pgpBase.h)
9caf5a
6afea0 dnl The following tests need to know that we intend to produce a config.h
08dd8b dnl file, even though this won't expand to any shell script code until
0552a6 dnl AC_OUTPUT time.
b3fb9a AC_CONFIG_HEADER(unix/pgpPFLConfig.h)
04af5a
c4f644 dnl The following directory is where we will find the ancillary scripts,
44e9c0 dnl like install-sh, config.sub, and config.guess.
648ea3 AC_CONFIG_AUX_DIR(unix/config)
adaf5a
69090f AC_CANONICAL_HOST
c3af5a
1b8ddb SHELL=/bin/sh
82af5a
568129 case "$host" in
542c56 *-*-solaris*)
75942e ····PGPARCH=PGP_UNIX_SOLARIS
1c4351 ····;;
1bedae *-*-linux)
b2961d ····PGPARCH=PGP_UNIX_LINUX
3e4351 ····;;
572b30 *)
55982e ····PGPARCH=PGP_UNIX_UNKNOWN
994351 ····;;
f14799 esac
59af5a
3da3de dnl Checks for programs.
9ac82f # Find a compiler to use.
3011d5 # Check 1) The $CC environment varaible, 2) gcc, 3) acc, and 4) cc.
f8ae5a dnl This used to be just AC-CHECK-PROGS(CC, gcc acc, cc), but...
e3d6b2 # This deals with brain-damaged Sun systems that place a bogus cc or
0e7fb7 # acc executable in the $PATH, which just prints an error and exit.
75bf5f # We deal with this by actually trying to compile a trivial test program.
2df53e if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
310de4 ··AC_MSG_CHECKING(For C compiler (cached))
0d0d5c ··CC="$ac_cv_prog_CC"
96cb02 ··AC_MSG_RESULT($CC)
688d37 elif test -n "$CC"; then
3c3913 ··ac_cv_prog_CC="$CC" # Let the user override the test.
97eac2 ··AC_MSG_CHECKING(For C compiler)
ffcb02 ··AC_MSG_RESULT($CC)
c9523c else
939ee0 ··IFS="${IFS=¤  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
f15536 ··echo 'main(){return 0;}' > conftest.$ac_ext
171263 ··for ac_prog in gcc acc cc; do
bc801e # Extract the first word of "$ac_prog", so it can be a program name with args.
602283 ····set dummy $ac_prog; ac_word=$2
cd6b14 ····AC_MSG_CHECKING(for $ac_word)
b82cf4 ····for ac_dir in $PATH; do
2fcf86 ······test -z "$ac_dir" && ac_dir=.
a14cf9 ······if test -r "$ac_dir/$ac_word"; then
5a5f41 ········CC="$ac_prog"
76552c ········if eval $ac_compile; then
5fc7ef ··········ac_cv_prog_CC="$ac_prog"
abf9a0 ········fi
101dec ········break
014076 ······fi
75d04f ····done
16f080 ····CC="$ac_cv_prog_CC"
1a049f ····if test -n "$CC"; then
6b034f ······AC_MSG_RESULT($ac_dir/$CC)
--52a1 0003cd9f0e8401000be Page 2 of configure.in
2088e1 ······break;
19df8a ····fi
ecc319 ····AC_MSG_RESULT(no)
7f4fb3 ··done
6dc13d ··if test ! -n "$CC"; then
30aec6 ····AC_MSG_ERROR(no C compiler found)
1a9666 ··fi
726b79 ··IFS="$ac_save_ifs"
3bdd24 ··rm -f conftest*
f4ce83 fi
f6d58b AC_SUBST(CC)
e9af5a
828965 AC_CACHE_CHECK(whether we are using GNU CC, ac_cv_prog_gcc,
2e5a6e [dnl The semicolon is to pacify NeXT's syntax-checking cpp.
3c5396 cat > conftest.c <<EOF
a8d1d1 #ifdef __GNUC__
2e6824 ··yes;
087454 #endif
0489bd EOF
6a0a98 if ${CC-cc} -E conftest.c 2>&AC_FD_CC | egrep yes >/dev/null 2>&1; then
113022 ··ac_cv_prog_gcc=yes
86523c else
a9b38d ··ac_cv_prog_gcc=no
aedd41 fi])
44af5a
256e28 if test $ac_cv_prog_gcc = yes; then
aad9b2 ··if test "${CFLAGS+set}" != set; then
4c2a14 AC_CACHE_CHECK(whether ${CC-cc} accepts -g, ac_cv_prog_gcc_g,
5fcf88 [echo 'void f(){}' > conftest.c
ec6b51 if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
0b00bc ··ac_cv_prog_gcc_g=yes
31523c else
f6a6ac ··ac_cv_prog_gcc_g=no
eace83 fi
0b963a rm -f conftest*
2627ed ])
219666 ··fi
d7ce83 fi
08af5a
6f9b15 # Now, figure out what CFLAGS we want. ·If the user didn't ask specifically,
c711fa # we're going to use some ideas of our own.
7472b3 if test "${CFLAGS+set}" != set; then
5baf5a
38c0f8 # Prefer optimizing, with debugging a second
bcdbf8 if test $ac_cv_prog_gcc$ac_cv_prog_gcc_g = yesyes; then
dcd4a4 ··CFLAGS="-O -g"
8e523c else
4cf54f ··CFLAGS=-O
f2ce83 fi
feaf5a
ce98f0 dnl This ugly hack is to get warnings enabled where possible.
6d329c AC_MSG_CHECKING(for useful warning options (\$WARN))
23999a if test "${WARN+set}" != set; then
fe1566 ··if test $ac_cv_prog_gcc = yes; then
261d67 ····WARN="-Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \
4f1e0d -Wwrite-strings"
8e8744 ··elif $CC -flags 2>&1 | grep SunSoft >/dev/null 2>&1 ||
851970 ¤   $CC -flags 2>&1 | grep SunPro >/dev/null 2>&1; then
55d676 ····if $CC -flags 2>&1 | grep 'checking' | grep '^-vc' > /dev/null 2>&1; then
014f8a ······WARN=-vc
c69f89 ····elif $CC -flags 2>&1 | grep 'checking' | grep '^-v ' > /dev/null 2>&1; then
671850 ······WARN=-v
fedf8a ····fi
ef2d3f ····if $CC -flags 2>&1 | grep '^-xstrconst' > /dev/null 2>&1; then
e72369 ······WARN="${WARN}${WARN+ }-xstrconst"
c2df8a ····fi
419666 ··fi
dac4c9 ··# Any other compiler's warning flags?
63ce83 fi
8a149a AC_MSG_RESULT(${WARN-none})
da09e6 AC_SUBST(WARN)
3caf5a
--fb23 000b990df32401000be Page 3 of configure.in
18ce83 fi
9cccc0 # ^^ end of CFLAGS inference section
28af5a
c1143a AC_REQUIRE_CPP
a71bb1 # Finally, figure out the command to generate dependencies.
5253cd AC_CACHE_CHECK(how to make dependencies, ac_cv_prog_DEPEND,
a1f9a9 [if test -n "$DEPEND"; then
db6e05 ··ac_cv_prog_DEPEND="$DEPEND"
a7523c else
539ee0 ··IFS="${IFS=¤  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
cb0807 ··echo '#include "confdefs.h"' > conftest.c
857991 ··for ac_prog in "$CPP -M" "$CC -xM" "$CC -M"; do
522c44 ····echo $ac_prog $CPPFLAGS conftest.c 1>&AC_FD_CC;
51d448 ····if $ac_prog $CPPFLAGS conftest.c 2>&AC_FD_CC \
bd204f ····················| egrep "conftest\.o" >/dev/null 2>&1; then
dbcffc ······ac_cv_prog_DEPEND="$ac_prog $CPPFLAGS"
75a94c ······break
91df8a ····fi
3d4fb3 ··done
5bc62d ··if test ! -n "$ac_cv_prog_DEPEND"; then
43978e ····ac_cv_prog_DEPEND=:
989666 ··fi
7c6b79 ··IFS="$ac_save_ifs"
50dd24 ··rm -f conftest*
87dd41 fi])
e093ba DEPEND="$ac_cv_prog_DEPEND"
9f5235 AC_SUBST(DEPEND)
79af5a
8b7658 # Find a BSD-compatibile install program, with install-sh as a fallback.
2c96e6 AC_PROG_INSTALL
b1af5a
296fc7 # Find "ranlib". ·Sone systems don't have or need ranlib. ·If so,
5eb825 # ":" (do nothing) is used instead.
6114d7 AC_PROG_RANLIB
b4af5a
406aee # Use symlinks (ln -s) if possible. ·If not, use hard links (ln).
ce2fe9 AC_PROG_LN_S
a1af5a
726a92 # Figure out how to test for symlinks... ·Check 'test -L' and then 'test -h'
8122cc AC_CACHE_CHECK(how to test for symlinks, ac_cv_prog_TEST_L,
3a7fd5 [rm -f conftest
b19ec9 $ac_cv_prog_LN_S foo conftest
04feb9 IFS="${IFS=¤}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
530e8c if ( test -L conftest ); then
698bc9 ··ac_cv_prog_TEST_L="test -L"
bb188d elif ( test -h conftest ); then
d3eb93 ··ac_cv_prog_TEST_L="test -h"
d4523c else
1a6dd0 ··ac_cv_prog_TEST_L="test ! -f"
f9ce83 fi
f85c39 IFS="$ac_save_ifs"
72eefa rm -f conftest*])
f05638 TEST_L="$ac_cv_prog_TEST_L"
35a3ec AC_SUBST(TEST_L)
d9af5a
43c3e7 dnl Checks for libraries.
8d9cdb AC_CHECK_LIB(thread, thr_create)
1cdbe8 AC_CHECK_LIB(pthread, pthread_create)
3caf5a
fb2a59 dnl Checks for library functions.
f9ba80 AC_CHECK_FUNCS(gethrtime clock_gettime clock_getres gettimeofday \
5c5cb7 ¤   getitimer setitimer ftime mktemp mkstemp thr_create \
e7a4ac ¤   pthread_create pthread_attr_create sem_init semget)
50af5a
729113 dnl Checks for header files.
e1a199 # Check that this system has a set of properly working ANSI C header files.
876100 # In particular, check for the existence of <stdlib.h>, <stdarg.h>,
a3eb1b # <string.h> and <float.h>. ·Also check that <string.h> declares mem*,
e87fb9 # that <stdlib.h> declares free, and that the <ctype.h> macros work
6f1635 # with values >= 128.
f683ef AC_HEADER_STDC
b9af5a
--402e 00192831ae5401000be Page 4 of configure.in
b81969 # Check for which system headers are available
aa04be AC_CHECK_HEADERS(fcntl.h limits.h stdarg.h stdlib.h unistd.h paths.h \
f1129b ¤   dirent.h sys/ioctl.h sys/time.h sys/timeb.h sys/param.h sys/stat.h \
2cb61d ¤   sys/types.h)
8733d3 AC_HEADER_TIME
96af5a
9acacb dnl Checks for typedefs, structures, and compiler characteristics.
4c00ac # Verify that the compiler supports const, and that it works.
b11b37 # A lot of compilers sort of support const, but they have bugs
c19c18 # that will prevent valid programs from compiling.
dbdc8e AC_C_CONST
31af5a
349164 # See if we have off_t in <sys/types.h> or <stdlib.h>.
b27190 # If not, define it as "long".
4a74a7 AC_TYPE_OFF_T
6baf5a
abac92 # See if we have size_t similarly. ·If not, define it as unsigned.
07fb7f AC_TYPE_SIZE_T
18af5a
d110e2 # Check for our style of unsigned typedefs in sys/types.h
89a6ef AC_EGREP_HEADER([[^a-zA-Z0-9_]uchar[^a-zA-Z0-9_]], sys/types.h,
879e79 ¤   ¤   AC_DEFINE(HAVE_UCHAR))
bd4ae7 AC_EGREP_HEADER([[^a-zA-Z0-9_]ushort[^a-zA-Z0-9_]], sys/types.h,
71fbc9 ¤   ¤   AC_DEFINE(HAVE_USHORT))
713048 AC_EGREP_HEADER([[^a-zA-Z0-9_]uint[^a-zA-Z0-9_]], sys/types.h,
8da5b7 ¤   ¤   AC_DEFINE(HAVE_UINT))
8bde97 AC_EGREP_HEADER([[^a-zA-Z0-9_]ulong[^a-zA-Z0-9_]], sys/types.h,
b45c56 ¤   ¤   AC_DEFINE(HAVE_ULONG))
7baf5a
bb0c0e # The big bang! ·Produce the output files. ·This is config.cache, and
70219f # config.status, which builds the config.h file and a long list of
b6c1ed # Makefiles.
9cc2a6 dnl The value specified to AC_CONFIG_HEADER at the top if the file is
b69cc0 dnl used here.
20a140 PGP_AC_OUTPUT(
4716f2 ¤   Makefile
cd4ebb ¤   common/Makefile
307317 ¤   common/file/Makefile
605a31 ¤   common/prefs/Makefile
94926e ¤   common/lthread/Makefile
40e8c3 ····test/Makefile
fdee29 ¤   common/util/Makefile,
b451e5 ¤   unix/config/pre.in, unix/config/post.in)
52af5a
04f90a cat >> unix/pgpPFLConfig.h << END
335f65 #ifndef $PGPARCH
160e67 #define $PGPARCH 1
887454 #endif
92e0d1 END
--db7d 0013fd10c69401000bf Page 1 of Makefile.in
5ea601 #
8e9506 # common/
0ea601 #
506f26 # $Id: Makefile.in,v 1.12 1998/08/05 05:36:44 heller Exp $
7aa601 #
4baf5a
b7d84f SUBDIRS= file prefs util lthread
0eaf5a
324719 LOCALDEFINES=
e7af5a
23197f LIBDONE= DONE file/DONE prefs/DONE util/DONE lthread/DONE
c9af5a
e63db7 OBJS= pgpDebug.o pgpLeaks.o pgpMem.o pgpMemoryMgr.o \
6f4e6f ¤   ¤   pgpMemoryMgrStd.o pgpBinaryTree.o pgpRMWOLock.o
57af5a
64211d all:: LIBDONE
3faf5a
--29c4 001377ff402401000c0 Page 1 of pflTypes.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
c5d735 ¤   $Id: pflTypes.h,v 1.4.16.1 1998/11/12 03:17:48 heller Exp $
44f7f7 ____________________________________________________________________________*/
f8af31 #ifndef Included_pflTypes_h¤/* [ */
355362 #define Included_pflTypes_h
f9af5a
c6af5a
36af5a
950c0d /* opaque declarations */
632e8c typedef struct PFLFileSpec *¤   ¤   PFLFileSpecRef;
0b9973 typedef struct PFLFileSpec const *¤ PFLConstFileSpecRef;
42af5a
dbecf2 typedef struct PFLDirectoryIter *¤  ¤   PFLDirectoryIterRef;
85ca66 typedef struct PFLDirectoryIter const *¤PFLConstDirectoryIterRef;
68af5a
fea6d6 /* Validity checks */
48357a #define¤kInvalidPFLFileSpecRef¤ ¤   ¤   ((PFLFileSpecRef) NULL)
a895aa #define¤kInvalidPFLDirectoryIterRef¤¤   ((PFLDirectoryIterRef) NULL)
e1af5a
797bcf #define PFLFileSpecRefIsValid( ref )¤   ¤   ( (ref) != kInvalidPFLFileSpecRef )
4d7095 #define PFLDirectoryIterRefIsValid( ref )¤  \
31c1a2 ¤   ¤   ¤   ( (ref) != kInvalidPFLDirectoryIterRef )
7aaf5a
b07900 #endif /* ] Included_pflTypes_h */
bbaf5a
37af5a
d47e4d /*__Editor_settings____
a9af5a
944126 ¤   Local Variables:
367b17 ¤   tab-width: 4
b60e6c ¤   End:
d05f8c ¤   vi: ts=4 sw=4
b69e9b ¤   vim: si
37d062 _____________________*/
--5872 0007e4d14da401000c1 Page 1 of pgpBase.h
a70335 /*____________________________________________________________________________
9b685b ¤   pgpBase.h
da67c5 ¤
c0c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
7a4b0f ¤   All rights reserved.
cb67c5 ¤
ab7b64 ¤   This file deals with system dependencies to derive our very basic data
c836f0 ¤   types. ·It should not contain any higher level types.
ebaf5a
66aba9 ¤   $Id: pgpBase.h,v 1.24.26.1 1998/11/12 03:17:48 heller Exp $
8bf7f7 ____________________________________________________________________________*/
abb409 #ifndef Included_pgpBase_h¤ /* [ */
864caa #define Included_pgpBase_h
48af5a
fbe610 #include "pgpPFLConfig.h"
5baf5a
b331fd #if !( defined(PGP_MACINTOSH) || defined(PGP_UNIX) || defined(PGP_WIN32) )
61593c #error one of {PGP_MACINTOSH, PGP_UNIX, PGP_WIN32} must be defined
5a7454 #endif
f2af5a
000ccc #if PGP_MACINTOSH
9e7cab #include <stddef.h>
8d000e #if __MWERKS__ && ! defined( __dest_os )
bb33d2 ¤   #include <ansi_parms.h>
7f626f ¤   #define __dest_os __mac_os
db7454 #endif
a1db21 #else
eb13bf ¤   #include <sys/types.h>
c37454 #endif
2baf5a
2bafb9 #if PGP_WIN32
c2d95a #include <stddef.h>¤¤   /* For size_t */
9d7454 #endif
63af5a
f9c6a3 #if ! NO_LIMITS_H
92a7a0 #include <limits.h>
d07454 #endif
42af5a
5eaf5a
fb0335 /*____________________________________________________________________________
8c2f52 ¤   PGP basic types
e2f7f7 ____________________________________________________________________________*/
e9af5a
175338 typedef unsigned char¤  PGPBoolean;¤/* can be TRUE or FALSE */
3f64cc #ifndef TRUE
fd5faf #define TRUE¤   1
8b7454 #endif
56ec14 #ifndef FALSE
5fdefa #define FALSE¤  0
237454 #endif
0aaf5a
abaf5a
562625 /* PGPUInt8, PGPInt8 */
e3e4bc #if UCHAR_MAX == 0xff
60af5a
ce7558 typedef unsigned char¤  PGPUInt8;
364d0c typedef signed char¤¤   PGPInt8;
ce547d #define MAX_PGPUInt8¤   UCHAR_MAX
1b9a4d #define MAX_PGPInt8¤¤   SCHAR_MAX
d1af5a
73db21 #else
154373 #error This machine has no 8-bit type
557454 #endif
b2af5a
f2af5a
4bcb89 /* PGPUInt16, PGPInt16 */
12a106 #if UINT_MAX == 0xffff
47af5a
487265 typedef unsigned int¤   PGPUInt16;
f7c9fa typedef int¤¤   ¤   ¤   PGPInt16;
8a5d1c #define MAX_PGPUInt16¤  UINT_MAX
7ef728 #define MAX_PGPInt16¤   INT_MAX
--170a 0000b3948a0401000c1 Page 2 of pgpBase.h
e0af5a
d0e688 #elif USHRT_MAX == 0xffff
d7af5a
ca81ec typedef unsigned short¤ PGPUInt16;
713fc4 typedef short¤  ¤   ¤   PGPInt16;
62ca27 #define MAX_PGPUInt16¤  USHRT_MAX
b1bd2a #define MAX_PGPInt16¤   SHRT_MAX
e0af5a
58db21 #else
d074f9 #error This machine has no 16-bit type
9a7454 #endif
e1af5a
beaf5a
c4d247 /* PGPUInt32, PGPInt32 */
83e1b1 #if UINT_MAX == 0xfffffffful
63af5a
d62872 typedef unsigned int¤   PGPUInt32;
d193ed typedef int¤¤   ¤   ¤   PGPInt32;
7cb67c #define MAX_PGPUInt32¤  UINT_MAX
021c48 #define MAX_PGPInt32¤   INT_MAX
45af5a
296e15 #elif ULONG_MAX == 0xfffffffful
d0af5a
6cd796 typedef unsigned long¤  PGPUInt32;
b4bd95 typedef long¤   ¤   ¤   PGPInt32;
d416e6 #define MAX_PGPUInt32¤  ULONG_MAX
a061eb #define MAX_PGPInt32¤   LONG_MAX
25af5a
4e2c4f #elif USHRT_MAX == 0xfffffffful
40af5a
afdbfb typedef unsigned short¤ PGPUInt32;
0365d3 typedef short¤  ¤   ¤   PGPInt32;
eca9ca #define MAX_PGPUInt32¤  USHRT_MAX
aadec7 #define MAX_PGPInt32¤   SHRT_MAX
d8af5a
e5db21 #else
652817 #error This machine has no 32-bit type
c87454 #endif
87af5a
07af5a
240335 /*____________________________________________________________________________
507444 ¤   PGPUInt64, PGPInt64
7067c5 ¤
601b39 ¤   Find a 64-bit data type, if possible.
39d90c ¤   The conditions here are more complicated to avoid using numbers that
c8c7c6 ¤   will choke lesser preprocessors (like 0xffffffffffffffff) unless
457408 ¤   we're reasonably certain that they'll be acceptable.
5ad83c ·
704d60 ¤   Some *preprocessors* choke on constants that long even if the
26ce4d ¤   compiler can accept them, so it doesn't work reliably to test values.
e82851 ¤   So cross our fingers and hope that it's a 64-bit type.
3167c5 ¤
50468c ¤   GCC uses ULONG_LONG_MAX. ·Solaris uses ULLONG_MAX.
3d9ea8 ¤   IRIX uses ULONGLONG_MAX. ·Are there any other names for this?
2cf7f7 ____________________________________________________________________________*/
567e61 #if ULONG_MAX > 0xfffffffful
2f6f03 #if ULONG_MAX == 0xfffffffffffffffful
98af5a
af30d2 typedef ulong¤  ¤   PGPUInt64;
a8ecab typedef long¤   ¤   PGPInt64;
cee4c8 #define PGP_HAVE64¤ 1
e2af5a
ae7454 #endif
327454 #endif
43af5a
a3af5a
564b99 #ifndef PGP_HAVE64
7eaf5a
d27690 #if defined(ULONG_LONG_MAX) || defined (ULLONG_MAX) || defined(ULONGLONG_MAX)
ea7f86 typedef unsigned long long¤ PGPUInt64;
e52178 typedef long long¤  ¤   ¤   PGPInt64;
0b9893 #define PGP_HAVE64¤ ¤   ¤   1
--518c 00058ca46a7401000c1 Page 3 of pgpBase.h
e0af5a
317454 #endif
d77454 #endif
38af5a
18af5a
564b99 #ifndef PGP_HAVE64
5f976f #if defined(__MWERKS__)
a3338f #if __option( longlong )
dbaf5a
d37f86 typedef unsigned long long¤ PGPUInt64;
142178 typedef long long¤  ¤   ¤   PGPInt64;
fd9893 #define PGP_HAVE64¤ ¤   ¤   1
54af5a
307454 #endif
587454 #endif
ba7454 #endif
1eaf5a
41bab6 #if PGP_HAVE64
29e7d9 /* too painful to test all the variants above, so just do it this way */
753cbc #define MAX_PGPUInt64¤  ((PGPUInt64)0xfffffffffffffffful)
164cba #define MAX_PGPInt64¤   ((PGPInt64)0x7fffffffffffffff)
9d7454 #endif
34af5a
9caf5a
b09ca5 #if INT_MAX == 0x7FFFFFFFL
8a8540 #define PGPENUM_TYPEDEF( enumName, typeName )¤  typedef enum enumName typeName
00db21 #else
039473 #define PGPENUM_TYPEDEF( enumName, typeName )¤  typedef PGPInt32 typeName
ba7454 #endif
400c2c #define kPGPEnumMaxValue¤   ¤   INT_MAX
d6af5a
66c6cf #define PGP_ENUM_FORCE( enumName )¤ ¤   \
163c98 ¤   ¤   k ## enumName ## force = kPGPEnumMaxValue
c7af5a
cdaf5a
157bf4 typedef PGPUInt8¤   ¤   ¤   PGPByte;
5baf5a
a609a4 typedef PGPInt32¤   ¤   ¤   PGPError;
71af5a
1efe37 /* a simple value sufficient to hold any numeric or pointer type */
5fe50e typedef void *¤ ¤   ¤   ¤   PGPUserValue;
01af5a
aa6708 /* A PGPSize refers to in memory sizes. Use PGPFileOffset for file offsets */
38915b typedef size_t¤ ¤   ¤   ¤   PGPSize;
3fee84 #define MAX_PGPSize¤¤   ¤   ( ~(PGPSize)0 )
acaf5a
ff9d9c /* An offset or size of a file */
1b129a #if PGP_UNIX
7935e0 typedef off_t¤  ¤   ¤   ¤   PGPFileOffset;
2edb21 #else
4ebab6 #if PGP_HAVE64
5fd0c9 typedef PGPInt64¤   ¤   ¤   PGPFileOffset;
f5db21 #else
316169 typedef PGPInt32¤   ¤   ¤   PGPFileOffset;
f67454 #endif
d57454 #endif
30af5a
eb9c0b typedef PGPUInt32¤  ¤   ¤   PGPFlags;
b32480 typedef PGPUInt32¤  ¤   ¤   PGPTime;
002d54 typedef PGPUInt32¤  ¤   ¤   PGPTimeInterval;¤   /* In milliseconds */
4aaf5a
d45089 typedef struct PGPVersion
5ebb36 {
0357c6 ¤   PGPUInt16¤  majorVersion;
d37fd8 ¤   PGPUInt16¤  minorVersion;
5e67c5 ¤
0e6e2a } PGPVersion;
e7af5a
020335 /*____________________________________________________________________________
9bcf5a ¤   These macros should surround all C declarations in public
20b736 ¤   header files which define function or data symbols.
58f7f7 ____________________________________________________________________________*/
--efc7 0014c9873b1401000c1 Page 4 of pgpBase.h
e0af5a
d409eb #ifdef __cplusplus¤ /* [ */
50af5a
0d13da #define PGP_BEGIN_C_DECLARATIONS¤   extern "C" {
42e542 #define PGP_END_C_DECLARATIONS¤ ¤   }
f5af5a
7060bc #else¤  /* ] __cplusplus [ */
2daf5a
4b5de3 #define PGP_BEGIN_C_DECLARATIONS
8b33ec #define PGP_END_C_DECLARATIONS
30af5a
a479c3 #endif¤ /* ] __cplusplus */
9baf5a
5aaf5a
4baf5a
85af5a
b480a1 #ifndef pgpMin
34b623 #define pgpMin(x,y) (((x)<(y)) ? (x) : (y))
087454 #endif
09af5a
0d8722 #ifndef pgpMax
668695 #define pgpMax(x,y) (((x)>(y)) ? (x) : (y))
b57454 #endif
17af5a
4baf5a
0929aa #endif /* ] Included_pgpBase_h */
1faf5a
ec7e4d /*__Editor_settings____
52af5a
364126 ¤   Local Variables:
0a7b17 ¤   tab-width: 4
830e6c ¤   End:
2c5f8c ¤   vi: ts=4 sw=4
9d9e9b ¤   vim: si
4cd062 _____________________*/
--bc0a 0004e041562401000c2 Page 1 of pgpBinaryTree.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
14f950 ¤   $Id: pgpBinaryTree.c,v 1.6.14.1 1998/11/12 03:17:49 heller Exp $
f4f7f7 ____________________________________________________________________________*/
adaf5a
de2b62 #include "pgpPFLErrors.h"
4caf5a
e02b46 #include "pgpBinaryTree.h"
a3af5a
20af5a
f6af5a
8f790a typedef enum EBalance {
5b7046 ¤   balance_Left,
2aeed2 ¤   balance_Equal,
cc5dde ¤   balance_Right
c5c8ad } EBalance;
67af5a
aaaf5a
7eb059 typedef struct SPGPBinaryTreeNode {
783f74 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   key;
eb85a8 ¤   PGPUserValue¤   ¤   ¤   ¤   userValue;
8e05af ¤   struct SPGPBinaryTreeNode *¤left;
db4ca4 ¤   struct SPGPBinaryTreeNode *¤right;
ed0fba ¤   EBalance¤   ¤   ¤   ¤   ¤   balance;
d525c6 } SPGPBinaryTreeNode;
09af5a
54af5a
f374cc typedef struct SPGPBinaryTree {
7bb586 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr;
5a2dd7 ¤   SPGPBinaryTreeNode *¤   firstNode;
33a7e5 } SPGPBinaryTree;
a3af5a
abaf5a
adaf5a
2e9c50 #define RotateRight_(x)¤{¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f6200f ¤   SPGPBinaryTreeNode *¤   temp = (*(x))->left;¤   ¤   ¤   \
a6b59b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f61913 ¤   (*(x))->left = temp->right;¤¤   ¤   ¤   ¤   ¤   ¤   ¤   \
827bca ¤   temp->right = *(x);¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f45fbe ¤   *(x) = temp;¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
7cefe6 }
52af5a
8eaf5a
9eaf5a
e76e95 #define RotateLeft_(x)¤ {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
b87db2 ¤   SPGPBinaryTreeNode *¤   temp = (*(x))->right;¤  ¤   ¤   \
13b59b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
7838fe ¤   (*(x))->right = temp->left;¤¤   ¤   ¤   ¤   ¤   ¤   ¤   \
5899b3 ¤   temp->left = *(x);¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
685fbe ¤   *(x) = temp;¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
aeefe6 }
a5af5a
4daf5a
e0af5a
3d66dd ¤   static PGPError
cf67ee Insert(
026d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
7cf98d ¤   SPGPBinaryTreeNode **¤  root,
db8f4c ¤   PGPInt32¤   ¤   ¤   ¤   key,
58c515 ¤   PGPUserValue¤   ¤   ¤   data,
02c0be ¤   PGPBoolean *¤   ¤   ¤   taller)
84bb36 {
48e74b ¤   PGPError¤   ¤   ¤   ¤   result = kPGPError_NoErr;
23ec75 ¤   PGPBoolean¤ ¤   ¤   ¤   tallerSub;
7237f2 ¤   SPGPBinaryTreeNode *¤   left;
0dc5f6 ¤   SPGPBinaryTreeNode *¤   right;
eb67c5 ¤
4e9d68 ¤   if (*root == NULL) {
--6aa4 00048d45d92401000c2 Page 2 of pgpBinaryTree.c
14014e ¤   ¤   if ((*root = (SPGPBinaryTreeNode *) PGPNewData(memoryMgr,
88de72 ¤   ¤   sizeof(SPGPBinaryTreeNode), 0)) == NULL) {
f6a36e ¤   ¤   ¤   *taller = FALSE;
f7d666 ¤   ¤   ¤   result = kPGPError_OutOfMemory;
9545a6 ¤   ¤   } else {
16bee6 ¤   ¤   ¤   (*root)->left = NULL;
621cd2 ¤   ¤   ¤   (*root)->right = NULL;
aecb0e ¤   ¤   ¤   (*root)->balance = balance_Equal;
4c5a45 ¤   ¤   ¤   (*root)->key = key;
d1aa00 ¤   ¤   ¤   (*root)->userValue = data;
8394f6 ¤   ¤   ¤   *taller = TRUE;
b50fe4 ¤   ¤   }
3c91f3 ¤   } else if (key == (*root)->key) {
e29733 ¤   ¤   *taller = FALSE;
400b34 ¤   ¤   result = kPGPError_ItemAlreadyExists;
4d9afa ¤   } else if (key > (*root)->key) {
a70d1c ¤   ¤   result = Insert(memoryMgr, &((*root)->right), key, data, &tallerSub);
f1ac50 ¤   ¤   if (tallerSub) {
018afe ¤   ¤   ¤   switch ((*root)->balance) {
b82bf9 ¤   ¤   ¤   ¤   case balance_Left:
4772c3 ¤   ¤   ¤   ¤   {
502a31 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
8a2550 ¤   ¤   ¤   ¤   ¤   *taller = FALSE;
382613 ¤   ¤   ¤   ¤   }
a2f622 ¤   ¤   ¤   ¤   break;
242b85 ¤   ¤   ¤   ¤
1a2b85 ¤   ¤   ¤   ¤
1a31f8 ¤   ¤   ¤   ¤   case balance_Equal:
5572c3 ¤   ¤   ¤   ¤   {
8423f4 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Right;
1ab254 ¤   ¤   ¤   ¤   ¤   *taller = TRUE;
b12613 ¤   ¤   ¤   ¤   }
88f622 ¤   ¤   ¤   ¤   break;
152b85 ¤   ¤   ¤   ¤
922b85 ¤   ¤   ¤   ¤
6d383d ¤   ¤   ¤   ¤   case balance_Right:
5672c3 ¤   ¤   ¤   ¤   {
cd9329 ¤   ¤   ¤   ¤   ¤   right = (*root)->right;
025461 ¤   ¤   ¤   ¤   ¤   switch (right->balance) {
ed6446 ¤   ¤   ¤   ¤   ¤   ¤   case balance_Left:
c88fec ¤   ¤   ¤   ¤   ¤   ¤   {
2ebb75 ¤   ¤   ¤   ¤   ¤   ¤   ¤   left = right->left;
638654 ¤   ¤   ¤   ¤   ¤   ¤   ¤   switch (left->balance) {
ff2d6c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   case balance_Left:
9f31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
db627c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
303599 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Right;
bf6560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
e9cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
a3da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
bfda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
98f2da ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   case balance_Equal:
d231b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
84627c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
b23c5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
da6560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
72cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
27da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
e1da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
cffb1f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   case balance_Right:
1531b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
3f2ae9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Left;
883c5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
116560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
dacd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
755268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
2bb9c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
10f690 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RotateRight_(&right);
b33106 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->right = right;
44e16b ¤   ¤   ¤   ¤   ¤   ¤   ¤   RotateLeft_(root);
3d2605 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *taller = FALSE;
48db3c ¤   ¤   ¤   ¤   ¤   ¤   }
--5abd 00099364295401000c2 Page 3 of pgpBinaryTree.c
d300eb ¤   ¤   ¤   ¤   ¤   ¤   break;
0d94aa ¤   ¤   ¤   ¤   ¤   ¤
b294aa ¤   ¤   ¤   ¤   ¤   ¤
d2750e ¤   ¤   ¤   ¤   ¤   ¤   case balance_Right:
858fec ¤   ¤   ¤   ¤   ¤   ¤   {
73cb46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
46c52e ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
f7e16b ¤   ¤   ¤   ¤   ¤   ¤   ¤   RotateLeft_(root);
ea2605 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *taller = FALSE;
26db3c ¤   ¤   ¤   ¤   ¤   ¤   }
8c00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
9e94aa ¤   ¤   ¤   ¤   ¤   ¤
ba7ccb ¤   ¤   ¤   ¤   ¤   ¤   case balance_Equal:
d824ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* Needed to silence compiler */
4d8c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
8d1c89 ¤   ¤   ¤   ¤   ¤   }
f92613 ¤   ¤   ¤   ¤   }
61f622 ¤   ¤   ¤   ¤   break;
7da3a6 ¤   ¤   ¤   }
d545a6 ¤   ¤   } else {
41a36e ¤   ¤   ¤   *taller = FALSE;
f70fe4 ¤   ¤   }
29f037 ¤   } else {
67132f ¤   ¤   result = Insert(memoryMgr, &((*root)->left), key, data, &tallerSub);
15ac50 ¤   ¤   if (tallerSub) {
ce8afe ¤   ¤   ¤   switch ((*root)->balance) {
642bf9 ¤   ¤   ¤   ¤   case balance_Left:
ae72c3 ¤   ¤   ¤   ¤   {
f3a6a1 ¤   ¤   ¤   ¤   ¤   left = (*root)->left;
0587d2 ¤   ¤   ¤   ¤   ¤   switch (left->balance) {
1a6446 ¤   ¤   ¤   ¤   ¤   ¤   case balance_Left:
4a8fec ¤   ¤   ¤   ¤   ¤   ¤   {
97cb46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
c6b9c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
516fe3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RotateRight_(root);
962605 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *taller = FALSE;
05db3c ¤   ¤   ¤   ¤   ¤   ¤   }
fe00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
7f94aa ¤   ¤   ¤   ¤   ¤   ¤
8194aa ¤   ¤   ¤   ¤   ¤   ¤
14750e ¤   ¤   ¤   ¤   ¤   ¤   case balance_Right:
9d8fec ¤   ¤   ¤   ¤   ¤   ¤   {
1b0acd ¤   ¤   ¤   ¤   ¤   ¤   ¤   right = left->right;
e7b55e ¤   ¤   ¤   ¤   ¤   ¤   ¤   switch (right->balance) {
c82d6c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   case balance_Left:
d731b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
596bb9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Right;
0e34d9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
8b6560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
c7cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
10da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
8bda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
39f2da ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   case balance_Equal:
5b31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
7b627c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
2234d9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
166560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
64cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
52da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
07da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
9ffb1f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   case balance_Right:
5c31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
55627c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
1e2afd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Left;
1f6560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
1fcd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
ac5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
01c52e ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
a7b85f ¤   ¤   ¤   ¤   ¤   ¤   ¤   RotateLeft_(&left);
6d51f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->left = left;
b26fe3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RotateRight_(root);
992605 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *taller = FALSE;
--a41f 0002c39c5d1401000c2 Page 4 of pgpBinaryTree.c
0ddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
f000eb ¤   ¤   ¤   ¤   ¤   ¤   break;
62af5a
ae7ccb ¤   ¤   ¤   ¤   ¤   ¤   case balance_Equal:
7424ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* Needed to silence compiler */
128c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
b11c89 ¤   ¤   ¤   ¤   ¤   }
442613 ¤   ¤   ¤   ¤   }
e2f622 ¤   ¤   ¤   ¤   break;
902b85 ¤   ¤   ¤   ¤
7f2b85 ¤   ¤   ¤   ¤
e831f8 ¤   ¤   ¤   ¤   case balance_Equal:
5d72c3 ¤   ¤   ¤   ¤   {
6b3303 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Left;
efb254 ¤   ¤   ¤   ¤   ¤   *taller = TRUE;
2f2613 ¤   ¤   ¤   ¤   }
69f622 ¤   ¤   ¤   ¤   break;
ef2b85 ¤   ¤   ¤   ¤
d22b85 ¤   ¤   ¤   ¤
6a383d ¤   ¤   ¤   ¤   case balance_Right:
f372c3 ¤   ¤   ¤   ¤   {
a52a31 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
e82550 ¤   ¤   ¤   ¤   ¤   *taller = FALSE;
052613 ¤   ¤   ¤   ¤   }
6cf622 ¤   ¤   ¤   ¤   break;
c1a3a6 ¤   ¤   ¤   }
ab45a6 ¤   ¤   } else {
0ba36e ¤   ¤   ¤   *taller = FALSE;
1a0fe4 ¤   ¤   }
fa9371 ¤   }
5467c5 ¤
a35d73 ¤   return result;
5eefe6 }
69af5a
ecaf5a
6daf5a
dfc744 ¤   PGPError
066cad PGPAddNode(
c460d3 ¤   PGPBinaryTreeRef¤   inBinaryTree,
d3fa27 ¤   PGPInt32¤   ¤   ¤   inKey,
a4edc5 ¤   PGPUserValue¤   ¤   inUserValue)
5ebb36 {
b6f547 ¤   PGPBoolean¤ taller;
6567c5 ¤
7d997e ¤   return Insert(inBinaryTree->memoryMgr, &inBinaryTree->firstNode,
65b54a ¤   ¤   ¤   ¤   inKey, inUserValue, &taller);
7fefe6 }
caaf5a
93af5a
bbaf5a
b16c2c ¤   static PGPBoolean
dbdfec RightBalance(
5e8735 ¤   SPGPBinaryTreeNode **¤  root)
6ebb36 {
a07d7c ¤   PGPBoolean¤ ¤   ¤   ¤   result = FALSE;
e637f2 ¤   SPGPBinaryTreeNode *¤   left;
26c5f6 ¤   SPGPBinaryTreeNode *¤   right;
82af5a
43c457 ¤   switch ((*root)->balance) {
811e9f ¤   ¤   case balance_Right:
895b34 ¤   ¤   {
03cb0e ¤   ¤   ¤   (*root)->balance = balance_Equal;
e2046c ¤   ¤   ¤   result = TRUE;
1c0fe4 ¤   ¤   }
8f2f68 ¤   ¤   break;
b61b52 ¤   ¤
0a1b52 ¤   ¤
b5175a ¤   ¤   case balance_Equal:
975b34 ¤   ¤   {
443285 ¤   ¤   ¤   (*root)->balance = balance_Left;
34982d ¤   ¤   ¤   result = FALSE;
2c0fe4 ¤   ¤   }
--ba98 0008e2a6b05401000c2 Page 5 of pgpBinaryTree.c
4f2f68 ¤   ¤   break;
891b52 ¤   ¤
441b52 ¤   ¤
fbb3ae ¤   ¤   case balance_Left:
965b34 ¤   ¤   {
b1753c ¤   ¤   ¤   left = (*root)->left;
c78487 ¤   ¤   ¤   switch (left->balance) {
8f383d ¤   ¤   ¤   ¤   case balance_Right:
7272c3 ¤   ¤   ¤   ¤   {
c45ee8 ¤   ¤   ¤   ¤   ¤   right = left->right;
a95461 ¤   ¤   ¤   ¤   ¤   switch (right->balance) {
eb750e ¤   ¤   ¤   ¤   ¤   ¤   case balance_Right:
f18fec ¤   ¤   ¤   ¤   ¤   ¤   {
f1cb46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
cb74e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Left;
7fdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
c400eb ¤   ¤   ¤   ¤   ¤   ¤   break;
3394aa ¤   ¤   ¤   ¤   ¤   ¤
e494aa ¤   ¤   ¤   ¤   ¤   ¤
307ccb ¤   ¤   ¤   ¤   ¤   ¤   case balance_Equal:
228fec ¤   ¤   ¤   ¤   ¤   ¤   {
76cb46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
e6b9c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
3cdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
2600eb ¤   ¤   ¤   ¤   ¤   ¤   break;
7194aa ¤   ¤   ¤   ¤   ¤   ¤
4b94aa ¤   ¤   ¤   ¤   ¤   ¤
056446 ¤   ¤   ¤   ¤   ¤   ¤   case balance_Left:
ee8fec ¤   ¤   ¤   ¤   ¤   ¤   {
9ac283 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Right;
68b9c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
44db3c ¤   ¤   ¤   ¤   ¤   ¤   }
6700eb ¤   ¤   ¤   ¤   ¤   ¤   break;
5d1c89 ¤   ¤   ¤   ¤   ¤   }
351fd5 ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
042869 ¤   ¤   ¤   ¤   ¤   RotateLeft_(&left);
6e270d ¤   ¤   ¤   ¤   ¤   (*root)->left = left;
40ffd5 ¤   ¤   ¤   ¤   ¤   RotateRight_(root);
a69c3b ¤   ¤   ¤   ¤   ¤   result = TRUE;
392613 ¤   ¤   ¤   ¤   }
3cf622 ¤   ¤   ¤   ¤   break;
932b85 ¤   ¤   ¤   ¤
962b85 ¤   ¤   ¤   ¤
2331f8 ¤   ¤   ¤   ¤   case balance_Equal:
e572c3 ¤   ¤   ¤   ¤   {
6f3303 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Left;
27a61e ¤   ¤   ¤   ¤   ¤   left->balance = balance_Right;
17ffd5 ¤   ¤   ¤   ¤   ¤   RotateRight_(root);
e1be8f ¤   ¤   ¤   ¤   ¤   result = FALSE;
c82613 ¤   ¤   ¤   ¤   }
6ff622 ¤   ¤   ¤   ¤   break;
d92b85 ¤   ¤   ¤   ¤
c22b85 ¤   ¤   ¤   ¤
502bf9 ¤   ¤   ¤   ¤   case balance_Left:
af72c3 ¤   ¤   ¤   ¤   {
1b2a31 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
aeafdb ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
41ffd5 ¤   ¤   ¤   ¤   ¤   RotateRight_(root);
389c3b ¤   ¤   ¤   ¤   ¤   result = TRUE;
be2613 ¤   ¤   ¤   ¤   }
a4f622 ¤   ¤   ¤   ¤   break;
04a3a6 ¤   ¤   ¤   }
630fe4 ¤   ¤   }
3c2f68 ¤   ¤   break;
679371 ¤   }
f567c5 ¤
e35d73 ¤   return result;
07efe6 }
21af5a
10af5a
a7af5a
8e6c2c ¤   static PGPBoolean
--aed7 00032991f13401000c2 Page 6 of pgpBinaryTree.c
4f5a5f LeftBalance(
628735 ¤   SPGPBinaryTreeNode **¤  root)
91bb36 {
697d7c ¤   PGPBoolean¤ ¤   ¤   ¤   result = FALSE;
4c37f2 ¤   SPGPBinaryTreeNode *¤   left;
94c5f6 ¤   SPGPBinaryTreeNode *¤   right;
88af5a
d7c457 ¤   switch ((*root)->balance) {
abb3ae ¤   ¤   case balance_Left:
785b34 ¤   ¤   {
5acb0e ¤   ¤   ¤   (*root)->balance = balance_Equal;
16046c ¤   ¤   ¤   result = TRUE;
c40fe4 ¤   ¤   }
db2f68 ¤   ¤   break;
b11b52 ¤   ¤
981b52 ¤   ¤
88175a ¤   ¤   case balance_Equal:
2b5b34 ¤   ¤   {
c5c2cb ¤   ¤   ¤   (*root)->balance = balance_Right;
09982d ¤   ¤   ¤   result = FALSE;
ed0fe4 ¤   ¤   }
8a2f68 ¤   ¤   break;
051b52 ¤   ¤
ac1b52 ¤   ¤
581e9f ¤   ¤   case balance_Right:
a95b34 ¤   ¤   {
d8de1a ¤   ¤   ¤   right = (*root)->right;
41514a ¤   ¤   ¤   switch (right->balance) {
812bf9 ¤   ¤   ¤   ¤   case balance_Left:
8a72c3 ¤   ¤   ¤   ¤   {
f22b43 ¤   ¤   ¤   ¤   ¤   left = right->left;
0087d2 ¤   ¤   ¤   ¤   ¤   switch (left->balance) {
e86446 ¤   ¤   ¤   ¤   ¤   ¤   case balance_Left:
188fec ¤   ¤   ¤   ¤   ¤   ¤   {
86cb46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
96cceb ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Right;
f3db3c ¤   ¤   ¤   ¤   ¤   ¤   }
3e00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
a994aa ¤   ¤   ¤   ¤   ¤   ¤
c094aa ¤   ¤   ¤   ¤   ¤   ¤
ea7ccb ¤   ¤   ¤   ¤   ¤   ¤   case balance_Equal:
828fec ¤   ¤   ¤   ¤   ¤   ¤   {
54cb46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
f6c52e ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
9edb3c ¤   ¤   ¤   ¤   ¤   ¤   }
1000eb ¤   ¤   ¤   ¤   ¤   ¤   break;
d494aa ¤   ¤   ¤   ¤   ¤   ¤
be94aa ¤   ¤   ¤   ¤   ¤   ¤
a6750e ¤   ¤   ¤   ¤   ¤   ¤   case balance_Right:
eb8fec ¤   ¤   ¤   ¤   ¤   ¤   {
a57a85 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Left;
e9c52e ¤   ¤   ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
b3db3c ¤   ¤   ¤   ¤   ¤   ¤   }
1e00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
1c1c89 ¤   ¤   ¤   ¤   ¤   }
1eafdb ¤   ¤   ¤   ¤   ¤   left->balance = balance_Equal;
e0806b ¤   ¤   ¤   ¤   ¤   RotateRight_(&right);
42bf17 ¤   ¤   ¤   ¤   ¤   (*root)->right = right;
b87ebf ¤   ¤   ¤   ¤   ¤   RotateLeft_(root);
d79c3b ¤   ¤   ¤   ¤   ¤   result = TRUE;
de2613 ¤   ¤   ¤   ¤   }
65f622 ¤   ¤   ¤   ¤   break;
812b85 ¤   ¤   ¤   ¤
2f2b85 ¤   ¤   ¤   ¤
df31f8 ¤   ¤   ¤   ¤   case balance_Equal:
3672c3 ¤   ¤   ¤   ¤   {
6e23f4 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Right;
8e7477 ¤   ¤   ¤   ¤   ¤   right->balance = balance_Left;
af7ebf ¤   ¤   ¤   ¤   ¤   RotateLeft_(root);
8cbe8f ¤   ¤   ¤   ¤   ¤   result = FALSE;
642613 ¤   ¤   ¤   ¤   }
32f622 ¤   ¤   ¤   ¤   break;
--6bc3 000933a95fa401000c2 Page 7 of pgpBinaryTree.c
9f2b85 ¤   ¤   ¤   ¤
a32b85 ¤   ¤   ¤   ¤
2d383d ¤   ¤   ¤   ¤   case balance_Right:
9372c3 ¤   ¤   ¤   ¤   {
6c2a31 ¤   ¤   ¤   ¤   ¤   (*root)->balance = balance_Equal;
d21fd5 ¤   ¤   ¤   ¤   ¤   right->balance = balance_Equal;
217ebf ¤   ¤   ¤   ¤   ¤   RotateLeft_(root);
769c3b ¤   ¤   ¤   ¤   ¤   result = TRUE;
402613 ¤   ¤   ¤   ¤   }
2cf622 ¤   ¤   ¤   ¤   break;
90a3a6 ¤   ¤   ¤   }
c10fe4 ¤   ¤   }
512f68 ¤   ¤   break;
ab9371 ¤   }
2967c5 ¤
525d73 ¤   return result;
33efe6 }
c9af5a
4faf5a
41af5a
1913ad ¤   static PGPUserValue
dc405b Delete(
2df98d ¤   SPGPBinaryTreeNode **¤  root,
258f4c ¤   PGPInt32¤   ¤   ¤   ¤   key,
b0ed68 ¤   PGPBoolean *¤   ¤   ¤   shorter)
2dbb36 {
1dbdd6 ¤   PGPBoolean¤ ¤   ¤   ¤   shorterSubtree = FALSE;
f0ad92 ¤   PGPUserValue¤   ¤   ¤   result;
5c8446 ¤   PGPInt32¤   ¤   ¤   ¤   resultKey;
5e2aff ¤   SPGPBinaryTreeNode *¤   minNode;
ff0930 ¤   SPGPBinaryTreeNode *¤   saveNode;
2567c5 ¤
aa9d68 ¤   if (*root == NULL) {
54b21b ¤   ¤   *shorter = FALSE;
f21b33 ¤   ¤   result = NULL;
8891f3 ¤   } else if (key == (*root)->key) {
3843a5 ¤   ¤   saveNode = *root;
3f06d5 ¤   ¤   result = saveNode->userValue;
e3201c ¤   ¤   resultKey = saveNode->key;
5273ba ¤   ¤   if ((*root)->left == NULL) {
2f2e9c ¤   ¤   ¤   *root = (*root)->right;
d65caa ¤   ¤   ¤   *shorter = TRUE;
c575fc ¤   ¤   ¤   PGPFreeData(saveNode);
1898a5 ¤   ¤   } else if ((*root)->right == NULL) {
9333de ¤   ¤   ¤   *root = (*root)->left;
515caa ¤   ¤   ¤   *shorter = TRUE;
6b75fc ¤   ¤   ¤   PGPFreeData(saveNode);
4f45a6 ¤   ¤   } else {
f39752 ¤   ¤   ¤   minNode = (*root)->right;
2f2fa3 ¤   ¤   ¤   while (minNode->left != NULL) {
a293c8 ¤   ¤   ¤   ¤   minNode = minNode->left;
2ea3a6 ¤   ¤   ¤   }
1933b0 ¤   ¤   ¤   (*root)->key = minNode->key;
227c35 ¤   ¤   ¤   (*root)->userValue = minNode->userValue;
9c7931 ¤   ¤   ¤   minNode->userValue = result;
e02f2b ¤   ¤   ¤   minNode->key = resultKey;
b4fc7d ¤   ¤   ¤   result = Delete(&(*root)->right, key, &shorterSubtree);
305cea ¤   ¤   ¤   if (shorterSubtree) {
60e1be ¤   ¤   ¤   ¤   *shorter = RightBalance(root);
ee042d ¤   ¤   ¤   } else {
3b0c47 ¤   ¤   ¤   ¤   *shorter = FALSE;
e9a3a6 ¤   ¤   ¤   }
f60fe4 ¤   ¤   }
006325 ¤   } else if (key < (*root)->key) {
fd45d3 ¤   ¤   if ((result = Delete(&(*root)->left, key, &shorterSubtree)) ==
60bf2a ¤   ¤   NULL) {
ce3b4f ¤   ¤   ¤   *shorter = FALSE;
eff9d2 ¤   ¤   ¤   result = NULL;
3538ce ¤   ¤   } else if (shorterSubtree) {
0783fe ¤   ¤   ¤   *shorter = LeftBalance(root);
4d45a6 ¤   ¤   } else {
933b4f ¤   ¤   ¤   *shorter = FALSE;
--bec0 000ce5f2928401000c2 Page 8 of pgpBinaryTree.c
b50fe4 ¤   ¤   }
eff037 ¤   } else {
114d06 ¤   ¤   if ((result = Delete(&(*root)->right, key, &shorterSubtree)) ==
e0bf2a ¤   ¤   NULL) {
8b3b4f ¤   ¤   ¤   *shorter = FALSE;
70f9d2 ¤   ¤   ¤   result = NULL;
7a38ce ¤   ¤   } else if (shorterSubtree) {
f27026 ¤   ¤   ¤   *shorter = RightBalance(root);
5545a6 ¤   ¤   } else {
d13b4f ¤   ¤   ¤   *shorter = FALSE;
9f0fe4 ¤   ¤   }
119371 ¤   }
d367c5 ¤
b95d73 ¤   return result;
eaefe6 }
fcaf5a
e3af5a
96af5a
b3c744 ¤   PGPError
0c74be PGPDisposeNode(
f860d3 ¤   PGPBinaryTreeRef¤   inBinaryTree,
d7fa27 ¤   PGPInt32¤   ¤   ¤   inKey,
980ffc ¤   PGPUserValue *¤ ¤   outUserValue)
f7bb36 {
c744e1 ¤   PGPError¤   result = kPGPError_NoErr;
65111f ¤   PGPBoolean¤ shorter;
b467c5 ¤
4520ad ¤   *outUserValue = Delete(&inBinaryTree->firstNode, inKey, &shorter);
4af275 ¤   if (*outUserValue == NULL) {
d3d97a ¤   ¤   result = kPGPError_ItemNotFound;
a99371 ¤   }
0d67c5 ¤
595d73 ¤   return result;
a5efe6 }
97af5a
8faf5a
3aaf5a
a7c744 ¤   PGPError
f167ad PGPNewBinaryTree(
50d406 ¤   PGPMemoryMgrRef¤¤   inMemoryMgr,
9cfd82 ¤   PGPBinaryTreeRef *¤ outBinaryTree)
43bb36 {
f744e1 ¤   PGPError¤   result = kPGPError_NoErr;
0567c5 ¤
071b86 ¤   *outBinaryTree = PGPNewData(inMemoryMgr,sizeof(SPGPBinaryTree), 0);
a13266 ¤   if (*outBinaryTree == NULL) {
4a5e00 ¤   ¤   result = kPGPError_OutOfMemory;
0bf037 ¤   } else {
8084eb ¤   ¤   (*outBinaryTree)->memoryMgr = inMemoryMgr;
89587a ¤   ¤   (*outBinaryTree)->firstNode = NULL;
0d9371 ¤   }
b067c5 ¤
c65d73 ¤   return result;
1defe6 }
8daf5a
5aaf5a
a4af5a
b61964 ¤   static PGPUInt32
f70687 FreeTree(
2f5f0a ¤   SPGPBinaryTreeNode *¤   root)
10bb36 {
302675 ¤   PGPUInt32¤  numLeft = 0;
41a003 ¤   PGPUInt32¤  numRight = 0;
2ef2f8 ¤   PGPUInt32¤  result = 0;
1e67c5 ¤
bebd66 ¤   if (root != NULL) {
fbe5d7 ¤   ¤   if (root->left != NULL) {
fbc110 ¤   ¤   ¤   numLeft = FreeTree(root->left);
dc0fe4 ¤   ¤   }
c2fe1b ¤   ¤   if (root->right != NULL) {
b2f5f5 ¤   ¤   ¤   numRight = FreeTree(root->right);
ce0fe4 ¤   ¤   }
--cf47 00039ef2d06401000c2 Page 9 of pgpBinaryTree.c
a3c397 ¤   ¤   PGPFreeData(root);
4f4603 ¤   ¤   result = numLeft + numRight + 1;
1f9371 ¤   }
8e67c5 ¤
cc5d73 ¤   return result;
9befe6 }
9faf5a
b9af5a
e5ae30 ¤   ¤   ¤   ¤   ¤
ffc744 ¤   PGPError
5c4c78 PGPDisposeBinaryTree(
cf1e6b ¤   PGPBinaryTreeRef¤   inBinaryTree)
15bb36 {
9ded0f ¤   FreeTree(inBinaryTree->firstNode);
228046 ¤   PGPFreeData(inBinaryTree);
7faf5a
b7151e ¤   return kPGPError_NoErr;
feefe6 }
7caf5a
50af5a
02af5a
9c7579 ¤   static SPGPBinaryTreeNode *
d2f9df Find(
7d21b2 ¤   SPGPBinaryTreeNode *¤   root,
ec90e7 ¤   PGPInt32¤   ¤   ¤   ¤   inKey)
3bbb36 {
eb6d12 ¤   while ((root != NULL) && (inKey != root->key)) {
a27ef5 ¤   ¤   if (inKey < root->key) {
b4bab4 ¤   ¤   ¤   root = root->left;
6145a6 ¤   ¤   } else {
4de249 ¤   ¤   ¤   root = root->right;
2c0fe4 ¤   ¤   }
ab9371 ¤   }
7767c5 ¤
52bbf6 ¤   return root;
13efe6 }
bbaf5a
27af5a
72af5a
21c744 ¤   PGPError
8e876f PGPFindNode(
9860d3 ¤   PGPBinaryTreeRef¤   inBinaryTree,
c4fa27 ¤   PGPInt32¤   ¤   ¤   inKey,
5d0ffc ¤   PGPUserValue *¤ ¤   outUserValue)
b1bb36 {
90e74b ¤   PGPError¤   ¤   ¤   ¤   result = kPGPError_NoErr;
3b9533 ¤   SPGPBinaryTreeNode *¤   node;
3a67c5 ¤
05b72d ¤   node = Find(inBinaryTree->firstNode, inKey);
59c4d2 ¤   if (node == NULL) {
14d97a ¤   ¤   result = kPGPError_ItemNotFound;
44f037 ¤   } else {
ed9c65 ¤   ¤   *outUserValue = node->userValue;
419371 ¤   }
4c67c5 ¤
b65d73 ¤   return result;
c5efe6 }
4eaf5a
6faf5a
03af5a
d8c744 ¤   PGPError
7415b6 PGPChangeNode(
9a60d3 ¤   PGPBinaryTreeRef¤   inBinaryTree,
1efa27 ¤   PGPInt32¤   ¤   ¤   inKey,
d86b51 ¤   PGPUserValue¤   ¤   inNewUserValue,
aa1169 ¤   PGPUserValue *¤ ¤   outOldUserValue)
87bb36 {
75e74b ¤   PGPError¤   ¤   ¤   ¤   result = kPGPError_NoErr;
5b9533 ¤   SPGPBinaryTreeNode *¤   node;
5d67c5 ¤
c1b72d ¤   node = Find(inBinaryTree->firstNode, inKey);
39c4d2 ¤   if (node == NULL) {
--fa71 00189376723401000c2 Page 10 of pgpBinaryTree.c
7cd97a ¤   ¤   result = kPGPError_ItemNotFound;
d4f037 ¤   } else {
91bfd5 ¤   ¤   *outOldUserValue = node->userValue;
737a0f ¤   ¤   node->userValue = inNewUserValue;
d19371 ¤   }
1767c5 ¤
5f5d73 ¤   return result;
5defe6 }
ffaf5a
f2af5a
01af5a
3166dd ¤   static PGPError
a29629 InOrderTraversal(
1362f8 ¤   SPGPBinaryTreeNode *¤   ¤   root,
4fbef0 ¤   PGPBinaryTreeTraversalProc¤ userProc,
d32389 ¤   PGPUserValue¤   ¤   ¤   ¤   userValue)
8dbb36 {
6144e1 ¤   PGPError¤   result = kPGPError_NoErr;
b667c5 ¤
f9bd66 ¤   if (root != NULL) {
973bf3 ¤   ¤   result = InOrderTraversal(root->left, userProc, userValue);
5025fe ¤   ¤   if (result == kPGPError_NoErr) {
816895 ¤   ¤   ¤   result = (*userProc)(userValue, root->key, root->userValue);
7f0fe4 ¤   ¤   }
da25fe ¤   ¤   if (result == kPGPError_NoErr) {
c05c2c ¤   ¤   ¤   result = InOrderTraversal(root->right, userProc, userValue);
a90fe4 ¤   ¤   }
4c9371 ¤   }
5c67c5 ¤
a65d73 ¤   return result;
e5efe6 }
0aaf5a
c1af5a
bbc744 ¤   PGPError
3ca56d PGPInOrderTraversal(
d5ae81 ¤   PGPBinaryTreeRef¤   ¤   ¤   inBinaryTree,
e47fda ¤   PGPBinaryTreeTraversalProc¤ inUserProc,
756c00 ¤   PGPUserValue¤   ¤   ¤   ¤   inUserValue)
d1bb36 {
428293 ¤   return InOrderTraversal(inBinaryTree->firstNode, inUserProc, inUserValue);
89efe6 }
--51f3 000b9cf0546401000c3 Page 1 of pgpBinaryTree.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
a1e6aa ¤   $Id: pgpBinaryTree.h,v 1.3.16.1 1998/11/12 03:17:50 heller Exp $
f9f7f7 ____________________________________________________________________________*/
bbaf5a
7e0fdd #ifndef Included_pgpBinaryTree_h¤   /* [ */
c9c7af #define Included_pgpBinaryTree_h
15af5a
9d6773 #include "pgpMemoryMgr.h"
ceaf5a
d4fa23 #if PRAGMA_ALIGN_SUPPORTED
a1af46 #pragma options align=mac68k
717454 #endif
60af5a
ad99c6 PGP_BEGIN_C_DECLARATIONS
c6cbcf #if PRAGMA_IMPORT_SUPPORTED
92b981 #pragma import on
3f7454 #endif
c4af5a
08af5a
180cc6 typedef struct SPGPBinaryTree * PGPBinaryTreeRef;
ecaf5a
0e9ea5 #define¤kInvalidPGPBinaryTreeRef¤   ¤   ((PGPBinaryTreeRef) NULL)
b1a183 #define PGPBinaryTreeRefIsValid(ref)¤   ((ref) != kInvalidPGPBinaryTreeRef)
bbaf5a
aaaf5a
b8e99a /* Creating and disposing of binary trees */
d4b6e8 PGPError¤   PGPNewBinaryTree(PGPMemoryMgrRef inMemoryMgr,
c952aa ¤   ¤   ¤   ¤   PGPBinaryTreeRef * outBinaryTree);
e8ae30 ¤   ¤   ¤   ¤   ¤
4df4d2 PGPError¤   PGPDisposeBinaryTree(PGPBinaryTreeRef inBinaryTree);
5baf5a
0caf5a
d0af5a
17732b /* Creating, disposing, finding and changing nodes */
7d15e6 PGPError¤   PGPAddNode(PGPBinaryTreeRef inBinaryTree,
b45264 ¤   ¤   ¤   ¤   PGPInt32 inKey, PGPUserValue inUserValue);
b0af5a
1ed521 PGPError¤   PGPDisposeNode(PGPBinaryTreeRef inBinaryTree,
5e6829 ¤   ¤   ¤   ¤   PGPInt32 inKey, PGPUserValue * outUserValue);
04af5a
2139bf PGPError¤   PGPFindNode(PGPBinaryTreeRef inBinaryTree,
1f6829 ¤   ¤   ¤   ¤   PGPInt32 inKey, PGPUserValue * outUserValue);
d7af5a
7709ec PGPError¤   PGPChangeNode(PGPBinaryTreeRef inBinaryTree,
a05106 ¤   ¤   ¤   ¤   PGPInt32 inKey, PGPUserValue inNewUserValue,
9aef89 ¤   ¤   ¤   ¤   PGPUserValue * outOldUserValue);
b4ae30 ¤   ¤   ¤   ¤   ¤
12ceed /* Traversal of tree. Any return value other than kPGPError_NoErr will
862ace result in halting the traversal and that error will be returned. Note
76c5e9 that this has not been tested for node deletion safety .*/
b30968 typedef¤PGPError¤   (*PGPBinaryTreeTraversalProc)(PGPUserValue inUserValue,
8a4d78 ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inNodeKey, PGPUserValue inNodeUserValue);
84af5a
08a42a PGPError¤   PGPInOrderTraversal(PGPBinaryTreeRef inBinaryTree,
985e33 ¤   ¤   ¤   ¤   PGPBinaryTreeTraversalProc inUserProc,
1a8e65 ¤   ¤   ¤   ¤   PGPUserValue inUserValue);
22af5a
22cbcf #if PRAGMA_IMPORT_SUPPORTED
c02ced #pragma import reset
7e7454 #endif
771254 PGP_END_C_DECLARATIONS
9daf5a
29af5a
3eaf5a
26fa23 #if PRAGMA_ALIGN_SUPPORTED
467c46 #pragma options align=reset
b97454 #endif
--bb48 001d35fa5ff401000c3 Page 2 of pgpBinaryTree.h
e0af5a
1aaf5a
d39f15 #endif /* ] Included_pgpBinaryTree_h */
--2d9c 0004dac2fb8401000c4 Page 1 of pgpDebug.c
a70335 /*____________________________________________________________________________
134e4e ¤   pgpDebug.c
8367c5 ¤
0cf254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
f74b0f ¤   All rights reserved.
f667c5 ¤
69f4d6 ¤   Assertion support routines·
9caf5a
082d57 ¤   $Id: pgpDebug.c,v 1.14.14.1 1998/11/12 03:17:51 heller Exp $
56f7f7 ____________________________________________________________________________*/
80e610 #include "pgpPFLConfig.h"
42af5a
d9324c #include <string.h>
94d92d #include <stdarg.h>
78a7a0 #include <limits.h>
7c675a #include "pgpTypes.h"
45a146 #include "pgpDebug.h"
140d08 #include "pgpMem.h"
1faf5a
ceaf5a
03bf15 #if PGP_DEBUG && !PGP_DEBUG_STACK_BUFFERS
03e61c uchar¤  pgpaDebugBuf[PGP_DEBUG_BUF_SIZE * PGP_DEBUG_NUM_BUFS];
0dccbc uchar *¤pgpaDebugBufStack = pgpaDebugBuf + sizeof(pgpaDebugBuf);
347454 #endif
d0af5a
d4af5a
c533c8 ¤   static void
4f124b AppendChars(
a05fd6 ¤   uchar *¤¤   ¤   dest,
ec723f ¤   int *¤  ¤   ¤   offset,
b37636 ¤   int¤¤   ¤   ¤   max,
7d1338 ¤   PGPBoolean¤ ¤   ¤   canonicalizeNLs,
26edef ¤   char const *¤   src,
7b226a ¤   int¤¤   ¤   ¤   len)
8dbb36 {
9bf1a6 ¤   int¤¤   ¤   ¤   destIndex = *offset;
2cd750 ¤   int¤¤   ¤   ¤   srcIndex = 0;
6eaf5a
e15f09 ¤   pgpa(pgpaAddrValid(src, char));
ccaf5a
e56d0f ¤   if (canonicalizeNLs)
e0c7a1 ¤   {
d90a46 ¤   ¤   while (srcIndex < len && destIndex < max)
9bcd2e ¤   ¤   ¤   switch (src[srcIndex])
1ff776 ¤   ¤   ¤   {
88d688 ¤   ¤   ¤   ¤   case '\r':
f81b46 ¤   ¤   ¤   ¤   ¤   if (srcIndex + 1 < len && src[srcIndex + 1] == '\n')
120d9c ¤   ¤   ¤   ¤   ¤   ¤   srcIndex++;
ddaaf4 ¤   ¤   ¤   ¤   ¤   /* Fall through */
d2821d ¤   ¤   ¤   ¤   case '\n':
7a0ccc #if PGP_MACINTOSH
30a2a3 ¤   ¤   ¤   ¤   ¤   dest[destIndex++] = '\r';
64d77a #elif defined(PGP_WIN32)
3ea2a3 ¤   ¤   ¤   ¤   ¤   dest[destIndex++] = '\r';
9e4479 ¤   ¤   ¤   ¤   ¤   if (destIndex < max)
c2b908 ¤   ¤   ¤   ¤   ¤   ¤   dest[destIndex++] = '\n';
05db21 #else
8ef636 ¤   ¤   ¤   ¤   ¤   dest[destIndex++] = '\n';
cf7454 #endif
058660 ¤   ¤   ¤   ¤   ¤   srcIndex++;
2814c3 ¤   ¤   ¤   ¤   ¤   break;
3f6ab9 ¤   ¤   ¤   ¤   default:
35ecbf ¤   ¤   ¤   ¤   ¤   dest[destIndex++] = src[srcIndex++];
bf14c3 ¤   ¤   ¤   ¤   ¤   break;
4da3a6 ¤   ¤   ¤   }
d59371 ¤   }
460e24 ¤   else
bec7a1 ¤   {
7c0a46 ¤   ¤   while (srcIndex < len && destIndex < max)
46d097 ¤   ¤   ¤   dest[destIndex++] = src[srcIndex++];
1e9371 ¤   }
4daf5a
--a05a 0002bca36b5401000c4 Page 2 of pgpDebug.c
d648ef ¤   *offset = destIndex;
07efe6 }
19af5a
3733c8 ¤   static void
8d0f8e AppendUnsignedNumber(
495fd6 ¤   uchar *¤¤   ¤   dest,
a7723f ¤   int *¤  ¤   ¤   offset,
487636 ¤   int¤¤   ¤   ¤   max,
bef3c7 ¤   int¤¤   ¤   ¤   radix,
1a3add ¤   PGPUInt32¤  ¤   ¤   num)
7abb36 {
283c86 ¤   static char¤const digit[17] = "0123456789ABCDEF";
a05cae ¤   char¤   ¤   buf[36];
bf5d41 ¤   int¤¤   ¤   i = sizeof(buf);
a967c5 ¤
5ae397 ¤   pgpAssertMsg(radix >= 2 && radix <= 16, "Invalid radix");
a1cfa1 ¤   do
89c7a1 ¤   {
9f423a ¤   ¤   pgpAssert(i > 0);
2d625e ¤   ¤   buf[--i] = digit[num % radix];
2c73b9 ¤   ¤   num /= radix;
7cce5f ¤   } while (num > 0);
139bd7 ¤   AppendChars(dest, offset, max, FALSE, buf + i, sizeof(buf) - i);
e1efe6 }
a5af5a
a333c8 ¤   static void
18374c AppendSignedNumber(
d05fd6 ¤   uchar *¤¤   ¤   dest,
e7723f ¤   int *¤  ¤   ¤   offset,
c97636 ¤   int¤¤   ¤   ¤   max,
1cf3c7 ¤   int¤¤   ¤   ¤   radix,
448a13 ¤   long¤   ¤   ¤   num)
29bb36 {
b63cfe ¤   if (num < 0)
49c7a1 ¤   {
fbb102 ¤   ¤   AppendChars(dest, offset, max, FALSE, "-", 1);
995715 ¤   ¤   AppendUnsignedNumber(dest, offset, max, radix, -num);
899371 ¤   }
b20e24 ¤   else
3f804a ¤   ¤   AppendUnsignedNumber(dest, offset, max, radix, num);
45efe6 }
85af5a
7238e5 /*
0c5828 ·* Formats a string into the given <buffer>, similarly to sprintf.
253656 ·* If <putLengthPrefix> is true, a pascal-style length prefix is put at the
253dcc ·* beginning of the string. ·If <putNullTerminator> is true, a 0 byte is
9d8546 ·* added to the end. ·This allows creation of C strings, Pascal strings, or
a5b1e3 ·* hybrid strings which are both. ·<bufferSize> indicates the size of the
27bce6 ·* buffer, ie, the total number of bytes which can be modified, including
d1866c ·* length prefix size and null-terminator. ·In all cases, the length of the
7f678c ·* string in actual characters is returned.
c2775e ·*
ac2227 ·* Recognizes the following special sequences in the format string:
3a297d ·*¤ ¤   %%¤ Replaced with a single '%'
cafa86 ·*¤ ¤   %c¤ Replaced with the char argument
889552 ·*¤ ¤   %s¤ Replaced with the C string argument
40e8a6 ·*¤ ¤   %S¤ Replaced with the Pascal string argument
afa32e ·*¤ ¤   %B¤ Replaced with the memory buffer as a string
4f8ca6 ·*¤ ¤   ¤   ¤   (two args: length (int), buffer)
384042 ·*¤ ¤   %lB¤Replaced with the memory buffer as a string
a5085b ·*¤ ¤   ¤   ¤   (two args: length (long), buffer)
baaca3 ·*¤ ¤   %d¤ Replaced with the signed integer value (base 10)
13270d ·*¤ ¤   %ld¤Replaced with the signed long value (base 10)
e41441 ·*¤ ¤   %u¤ Replaced with the unsigned integer value (base 10)
a636f4 ·*¤ ¤   %lu¤Replaced with the unsigned long value (base 10)
c7445e ·*¤ ¤   %x¤ Replaced with the unsigned integer value (base 16)
b4b7e2 ·*¤ ¤   %lx¤Replaced with the unsigned long value (base 16)
ae9805 ·*¤ ¤   %o¤ Replaced with the unsigned integer value (base 8)
094649 ·*¤ ¤   %lo¤Replaced with the unsigned long value (base 8)
9a35dd ·*¤ ¤   %b¤ Replaced with the unsigned integer value (base 2)
c65736 ·*¤ ¤   %lb¤Replaced with the unsigned long value (base 2)
2ba803 ·*¤ ¤   %p¤ Replaced with the pointer value, printed in hex
--8809 0002022e47c401000c4 Page 3 of pgpDebug.c
47495d ·*/
c7a091 ¤   int
4ec4b9 pgpFormatVAStr(
e47119 ¤   uchar *¤¤   ¤   buffer,
a9c2bf ¤   int¤¤   ¤   ¤   bufferSize,
0e044b ¤   PGPBoolean¤ ¤   ¤   putLengthPrefix,
e46ea2 ¤   PGPBoolean¤ ¤   ¤   putNullTerminator,
9c1338 ¤   PGPBoolean¤ ¤   ¤   canonicalizeNLs,
22b46a ¤   char const *¤   formatStr,
c98f97 ¤   va_list¤¤   ¤   args)
e0bb36 {
6f62e5 ¤   int¤¤   ¤   ¤   bufferIndex = putLengthPrefix ? 1 : 0;
1f5a81 ¤   int¤¤   ¤   ¤   formatStrIndex;
6c0fa9 ¤   int¤¤   ¤   ¤   stringLength;
a767c5 ¤
515e68 ¤   pgpa((
3b0eeb ¤   ¤   pgpaAddrValid(buffer, uchar),
3d827d ¤   ¤   pgpaAssert(bufferSize >=
4723b4 ¤   ¤   ¤   ¤   ¤   ¤   putLengthPrefix + (putNullTerminator ? 1 : 0)),
7ad389 ¤   ¤   pgpaAddrValid(formatStr, char),
aa2fce ¤   ¤   pgpaMsg("Invalid parameters to pgpaFormatVAStr")));
8367c5 ¤
cc65c5 ¤   for (formatStrIndex = 0; formatStr[formatStrIndex] != '\0';
b6b278 ¤   ¤   ¤   formatStrIndex++)
ddc7a1 ¤   {
8019b4 ¤   ¤   if (formatStr[formatStrIndex] != '%')
72fbfe ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
5c5c7e ¤   ¤   ¤   ¤   ¤   ¤   canonicalizeNLs, &formatStr[formatStrIndex], 1);
6a1c03 ¤   ¤   else if (formatStr[formatStrIndex + 1] != '\0')
b45b34 ¤   ¤   {
695781 ¤   ¤   ¤   int¤¤   ¤   cmdStartIndex = formatStrIndex;
259341 ¤   ¤   ¤   PGPBoolean¤ ¤   longFlag = FALSE;
565391 ¤   ¤   ¤   int¤¤   ¤   radix;
deaf5a
901459 ¤   ¤   ¤   formatStrIndex++;
f9d944 ¤   ¤   ¤   if (formatStr[formatStrIndex] == 'l')
dcf776 ¤   ¤   ¤   {
3edcb6 ¤   ¤   ¤   ¤   longFlag = TRUE;
d92351 ¤   ¤   ¤   ¤   formatStrIndex++;
29a3a6 ¤   ¤   ¤   }
700756 ¤   ¤   ¤   switch (formatStr[formatStrIndex])
cff776 ¤   ¤   ¤   {
a01dbf ¤   ¤   ¤   ¤   case '%':¤  /* Literal '%' */
aba5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
cac486 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FALSE, &formatStr[formatStrIndex], 1);
cc14c3 ¤   ¤   ¤   ¤   ¤   break;
04ae30 ¤   ¤   ¤   ¤   ¤
eaed05 ¤   ¤   ¤   ¤   case 'c':¤  /* Single character */
c072c3 ¤   ¤   ¤   ¤   {
2ddf6c ¤   ¤   ¤   ¤   ¤   char¤   ¤   ¤   ch = va_arg(args, char);
acae30 ¤   ¤   ¤   ¤   ¤
e6a5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
5eec52 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   canonicalizeNLs, &ch, 1);
bb14c3 ¤   ¤   ¤   ¤   ¤   break;
cc2613 ¤   ¤   ¤   ¤   }
ef8d6c ¤   ¤   ¤   ¤   case 's':¤  /* C string argument */
5872c3 ¤   ¤   ¤   ¤   {
0d1a53 ¤   ¤   ¤   ¤   ¤   char const *¤   str = va_arg(args, char const *);
73ae30 ¤   ¤   ¤   ¤   ¤
01bf32 ¤   ¤   ¤   ¤   ¤   pgpa(pgpaAddrValid(str, char));
e4a5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
9e5044 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   canonicalizeNLs, str, strlen(str));
9614c3 ¤   ¤   ¤   ¤   ¤   break;
352613 ¤   ¤   ¤   ¤   }
cefc3b ¤   ¤   ¤   ¤   case 'S':¤  /* Pascal string argument */
4272c3 ¤   ¤   ¤   ¤   {
ed8204 ¤   ¤   ¤   ¤   ¤   uchar const *¤  pstr = va_arg(args, uchar const *);
79ae30 ¤   ¤   ¤   ¤   ¤
80aa65 ¤   ¤   ¤   ¤   ¤   pgpa(pgpaAddrValid(pstr, uchar));
e0a5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
62b394 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   canonicalizeNLs, (char *)(pstr + 1), pstr[0]);
2014c3 ¤   ¤   ¤   ¤   ¤   break;
--2599 0004dbaf35a401000c4 Page 4 of pgpDebug.c
862613 ¤   ¤   ¤   ¤   }
2c75df ¤   ¤   ¤   ¤   case 'B':¤  /* String buffer argument (length, buf) */
fe72c3 ¤   ¤   ¤   ¤   {
b6a845 ¤   ¤   ¤   ¤   ¤   long¤   ¤   ¤   length;
a25360 ¤   ¤   ¤   ¤   ¤   char const *¤   buf;
7faf5a
82b746 ¤   ¤   ¤   ¤   ¤   if (longFlag)
24ba39 ¤   ¤   ¤   ¤   ¤   ¤   length = va_arg(args, long);
244bd6 ¤   ¤   ¤   ¤   ¤   else
9b5acf ¤   ¤   ¤   ¤   ¤   ¤   length = va_arg(args, int);
eeaf5a
667fd4 ¤   ¤   ¤   ¤   ¤   buf = va_arg(args, char const *);
c8af5a
010479 ¤   ¤   ¤   ¤   ¤   pgpa((
6ae7df ¤   ¤   ¤   ¤   ¤   ¤   pgpaAssert(length >= 0),
f881bd ¤   ¤   ¤   ¤   ¤   ¤   pgpaAddrValid(buf, char)));
46b9e2 ¤   ¤   ¤   ¤   ¤   if (length > INT_MAX)
2c3312 ¤   ¤   ¤   ¤   ¤   ¤   length = INT_MAX;
43a5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
02e683 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   canonicalizeNLs, buf, length);
a214c3 ¤   ¤   ¤   ¤   ¤   break;
8d2613 ¤   ¤   ¤   ¤   }
1e30b0 ¤   ¤   ¤   ¤   case 'p':¤  /* pointer argument */
617eca ¤   ¤   ¤   ¤   ¤   pgpAssert(sizeof(PGPUInt32) == sizeof(void *));
e9a5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
0ec40d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FALSE, "0x", 2);
04e1de ¤   ¤   ¤   ¤   ¤   longFlag = TRUE;
cd7a28 ¤   ¤   ¤   ¤   ¤   radix = 16;
80c223 ¤   ¤   ¤   ¤   ¤   goto doUInt;
e5ae30 ¤   ¤   ¤   ¤   ¤
73f0f4 ¤   ¤   ¤   ¤   case 'x':¤  /* unsigned int argument, base 16 */
03d902 ¤   ¤   ¤   ¤   case 'X':
dd7a28 ¤   ¤   ¤   ¤   ¤   radix = 16;
0cc223 ¤   ¤   ¤   ¤   ¤   goto doUInt;
f3ae30 ¤   ¤   ¤   ¤   ¤
4ceea2 ¤   ¤   ¤   ¤   case 'o':¤  /* unsigned int argument, base 8 */
d4eb8f ¤   ¤   ¤   ¤   ¤   radix = 8;
9bc223 ¤   ¤   ¤   ¤   ¤   goto doUInt;
1eae30 ¤   ¤   ¤   ¤   ¤
00a701 ¤   ¤   ¤   ¤   case 'b':¤  /* unsigned int argument, base 2 */
0a98f5 ¤   ¤   ¤   ¤   ¤   radix = 2;
1bc223 ¤   ¤   ¤   ¤   ¤   goto doUInt;
10ae30 ¤   ¤   ¤   ¤   ¤
5475ba ¤   ¤   ¤   ¤   case 'u':¤  /* unsigned int argument, base 10 */
71acf1 ¤   ¤   ¤   ¤   ¤   radix = 10;
3742ae ¤   ¤   ¤   ¤   doUInt:
b24859 ¤   ¤   ¤   ¤   ¤   {
324b0a ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   num;
4aaf5a
a25835 ¤   ¤   ¤   ¤   ¤   ¤   if (longFlag)
1ee0f7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   num = va_arg(args, PGPUInt32);
fe7f8b ¤   ¤   ¤   ¤   ¤   ¤   else
54842f ¤   ¤   ¤   ¤   ¤   ¤   ¤   num = va_arg(args, unsigned int);
77af5a
1b1983 ¤   ¤   ¤   ¤   ¤   ¤   AppendUnsignedNumber(buffer, &bufferIndex, bufferSize,
9eaf13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   radix, num);
b91c89 ¤   ¤   ¤   ¤   ¤   }
c514c3 ¤   ¤   ¤   ¤   ¤   break;
4cae30 ¤   ¤   ¤   ¤   ¤
5ec8f0 ¤   ¤   ¤   ¤   case 'd':¤  /* signed integer argument, base 10 */
1072c3 ¤   ¤   ¤   ¤   {
df9bbc ¤   ¤   ¤   ¤   ¤   long¤   ¤   ¤   num;
b1ae30 ¤   ¤   ¤   ¤   ¤
fcb746 ¤   ¤   ¤   ¤   ¤   if (longFlag)
7a509d ¤   ¤   ¤   ¤   ¤   ¤   num = va_arg(args, long);
4a4bd6 ¤   ¤   ¤   ¤   ¤   else
c698f2 ¤   ¤   ¤   ¤   ¤   ¤   num = va_arg(args, int);
e0ae30 ¤   ¤   ¤   ¤   ¤
d1f047 ¤   ¤   ¤   ¤   ¤   AppendSignedNumber(buffer, &bufferIndex, bufferSize,
518634 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   10, num);
3914c3 ¤   ¤   ¤   ¤   ¤   break;
4d2613 ¤   ¤   ¤   ¤   }
--cf82 0005f1a700f401000c4 Page 5 of pgpDebug.c
976ab9 ¤   ¤   ¤   ¤   default:
eb72c3 ¤   ¤   ¤   ¤   {
dd0fce ¤   ¤   ¤   ¤   ¤   char¤   ¤   ¤   errorBuf[32];
baae30 ¤   ¤   ¤   ¤   ¤
044f84 ¤   ¤   ¤   ¤   ¤   pgpFormatStr(errorBuf, sizeof(errorBuf), FALSE,
351c31 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "[INVALID %B]",
d0f9a2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   formatStrIndex - cmdStartIndex + 1,
b7e09e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   formatStr + cmdStartIndex);
dfa5e7 ¤   ¤   ¤   ¤   ¤   AppendChars(buffer, &bufferIndex, bufferSize,
03cdd5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   canonicalizeNLs, errorBuf, strlen(errorBuf));
c514c3 ¤   ¤   ¤   ¤   ¤   break;
8a2613 ¤   ¤   ¤   ¤   }
f1a3a6 ¤   ¤   ¤   }
1c0fe4 ¤   ¤   }
dc9371 ¤   }
7067c5 ¤
361f1e ¤   if (putNullTerminator)
94c7a1 ¤   {
3242bd ¤   ¤   if (bufferIndex >= bufferSize)
93a9dc ¤   ¤   ¤   bufferIndex = bufferSize - 1;
b24ff5 ¤   ¤   buffer[bufferIndex] = '\0';
c09371 ¤   }
a967c5 ¤
398106 ¤   stringLength = bufferIndex - (putLengthPrefix ? 1 : 0);
9167c5 ¤
b97a7c ¤   if (putLengthPrefix)
6381f6 ¤   ¤   buffer[0] = (stringLength <= 255) ? stringLength : 255;
eb67c5 ¤
1816c3 ¤   return stringLength;
eeefe6 }
fbaf5a
2437fc ¤   uchar *
c25e0e pgpFormatHStr(
d57119 ¤   uchar *¤¤   ¤   buffer,
02c2bf ¤   int¤¤   ¤   ¤   bufferSize,
1b1338 ¤   PGPBoolean¤ ¤   ¤   canonicalizeNLs,
b2b46a ¤   char const *¤   formatStr,
1a3471 ¤   ...)
81bb36 {
c929b6 ¤   va_list¤¤   ¤   args;
9467c5 ¤
2014dc ¤   va_start(args, formatStr);
03943a ¤   pgpFormatVAStr(buffer, bufferSize, TRUE, TRUE, canonicalizeNLs,
f70f94 ¤   ¤   ¤   ¤   ¤   formatStr, args);
893557 ¤   va_end(args);
1e63c3 ¤   return buffer;
66efe6 }
9daf5a
a437fc ¤   uchar *
983de6 pgpFormatPStr(
9c7119 ¤   uchar *¤¤   ¤   buffer,
a5c2bf ¤   int¤¤   ¤   ¤   bufferSize,
df1338 ¤   PGPBoolean¤ ¤   ¤   canonicalizeNLs,
5fb46a ¤   char const *¤   formatStr,
df3471 ¤   ...)
05bb36 {
8729b6 ¤   va_list¤¤   ¤   args;
6367c5 ¤
b614dc ¤   va_start(args, formatStr);
eaa9a8 ¤   pgpFormatVAStr(buffer, bufferSize, TRUE, FALSE, canonicalizeNLs,
870f94 ¤   ¤   ¤   ¤   ¤   formatStr, args);
723557 ¤   va_end(args);
0963c3 ¤   return buffer;
feefe6 }
fdaf5a
c737fc ¤   uchar *
7622fb pgpFormatPStr255(
e47119 ¤   uchar *¤¤   ¤   buffer,
491338 ¤   PGPBoolean¤ ¤   ¤   canonicalizeNLs,
e5b46a ¤   char const *¤   formatStr,
223471 ¤   ...)
5fbb36 {
--6fb9 0005995bcea401000c4 Page 6 of pgpDebug.c
9129b6 ¤   va_list¤¤   ¤   args;
b567c5 ¤
3914dc ¤   va_start(args, formatStr);
cfe723 ¤   pgpFormatVAStr(buffer, 256, TRUE, FALSE, canonicalizeNLs, formatStr, args);
ee3557 ¤   va_end(args);
ab63c3 ¤   return buffer;
c6efe6 }
99af5a
ead25c ¤   char *
b43a06 pgpFormatStr(
6d9139 ¤   char *¤ ¤   ¤   buffer,
c1c2bf ¤   int¤¤   ¤   ¤   bufferSize,
2f1338 ¤   PGPBoolean¤ ¤   ¤   canonicalizeNLs,
29b46a ¤   char const *¤   formatStr,
1f3471 ¤   ...)
64bb36 {
0629b6 ¤   va_list¤¤   ¤   args;
3c67c5 ¤
a014dc ¤   va_start(args, formatStr);
36f925 ¤   pgpFormatVAStr((uchar *)buffer, bufferSize, FALSE, TRUE, canonicalizeNLs,
e10f94 ¤   ¤   ¤   ¤   ¤   formatStr, args);
b83557 ¤   va_end(args);
5563c3 ¤   return buffer;
93efe6 }
ecaf5a
67e85e #if PGP_DEBUG¤  /* [ */
7baf5a
a737fc ¤   uchar *
bbe483 pgpDebugFormatHStr(
407119 ¤   uchar *¤¤   ¤   buffer,
9cc2bf ¤   int¤¤   ¤   ¤   bufferSize,
30b46a ¤   char const *¤   formatStr,
723471 ¤   ...)
d7bb36 {
c729b6 ¤   va_list¤¤   ¤   args;
3967c5 ¤
2e14dc ¤   va_start(args, formatStr);
05f013 ¤   pgpFormatVAStr(buffer, bufferSize, TRUE, TRUE, TRUE, formatStr, args);
fc3557 ¤   va_end(args);
ca63c3 ¤   return buffer;
2defe6 }
50af5a
f137fc ¤   uchar *
5bdaa3 pgpDebugPrefixFormatHStr(
117119 ¤   uchar *¤¤   ¤   buffer,
6dc2bf ¤   int¤¤   ¤   ¤   bufferSize,
55b46a ¤   char const *¤   formatStr,
3d3471 ¤   ...)
58bb36 {
be29b6 ¤   va_list¤¤   ¤   args;
a0463a ¤   int¤¤   ¤   ¤   origSize;¤  /* Including null, but not length prefix */
b11f1c ¤   int¤¤   ¤   ¤   origOffset;
035fac ¤   int¤¤   ¤   ¤   prefixSize;¤/* Including length prefix, no null */
d956d8 ¤   int¤¤   ¤   ¤   totalLen;
cf67c5 ¤
d9d8af ¤   /*
37ff0e ¤   ·* Move the original string (except length prefix) to the end of the
804228 ¤   ·* buffer.
02a4e3 ¤   ·*/
2bb6c3 ¤   origSize = buffer[0] + 1;
4016d8 ¤   if (origSize == 256)
b3e066 ¤   ¤   origSize = strlen((char const *)buffer + 1) + 1;
a4f44a ¤   origOffset = bufferSize - origSize;
738a0b ¤   pgpCopyMemory(buffer + 1, buffer + origOffset, origSize);
59af5a
0755f1 ¤   /* Format the new prefix, without null-terminator */
c814dc ¤   va_start(args, formatStr);
ca6888 ¤   prefixSize = 1 + pgpFormatVAStr(buffer, origOffset, TRUE, FALSE, TRUE,
c2eb80 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   formatStr, args);
853557 ¤   va_end(args);
72af5a
590744 ¤   /* Add a separating string */
--171c 00062fcc2b6401000c4 Page 7 of pgpDebug.c
4db6a4 ¤   AppendChars(buffer, &prefixSize, origOffset, TRUE, ":\n ·", 4);
9daf5a
cffe47 ¤   /* Move the original part back so that it's adjacent to the prefix */
671399 ¤   pgpCopyMemory(buffer + origOffset, buffer + prefixSize, origSize);
ccaf5a
4ffbe0 ¤   /* Set the length prefix */
fbe2ae ¤   totalLen = (origSize - 1) + (prefixSize - 1);
b81bfc ¤   buffer[0] = (totalLen <= 255) ? totalLen : 255;
caaf5a
4a63c3 ¤   return buffer;
7befe6 }
c7af5a
ae6d52 ¤   void
23f814 pgpDebugFillMemory(
cb2903 ¤   void *¤ ¤   ¤   buffer,
4d8155 ¤   size_t¤ ¤   ¤   length)
87bb36 {
649bff ¤   pgpFillMemory(buffer, length, 0xDD);
cdefe6 }
a5af5a
53f17e ¤   static char
499dea pgpMemAccessTest(
5320dd ¤   void const *¤   addr)
86bb36 {
dac04c ¤   return *(volatile char const *)addr;
eaefe6 }
97af5a
5516ea ¤   PGPBoolean
ba4d17 pgpaInternalAddrValid(
4a3c2c ¤   pgpaCallPrefixDef,
425e65 ¤   void const *¤   addr,
d47e32 ¤   int¤¤   ¤   ¤   alignSize,
ef6553 ¤   char const *¤   varName)
7abb36 {
e90ccc #if PGP_MACINTOSH
3a9cf6 ¤   /* XXX alignof() doesn't match up with reality...bummer */
15c605 ¤   if (alignSize > 2)
e3995e ¤   ¤   alignSize = 2;
3e7454 #endif
2867c5 ¤
0deb2b ¤   pgpaAssert(addr != NULL);
ff6502 ¤   pgpaAssert(alignSize > 0);
db9b33 ¤   pgpaAssert(alignSize == 1 || (PGPUInt32)addr % alignSize == 0);
6c0ccc #if PGP_MACINTOSH
c5de39 ¤   pgpaAssert((PGPUInt32)addr >= 256);
e87454 #endif
72bd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
9e9efd ¤   ¤   ¤   "pgpaAddrValidAligned failed on %s (%p) (align %d)",
927016 ¤   ¤   ¤   varName, addr, alignSize));
a7af5a
e2dd07 ¤   if (!pgpaFailed)
7d7ab8 ¤   ¤   pgpMemAccessTest(addr);
08af5a
f6750f ¤   return pgpaFailed;
3fefe6 }
efaf5a
4616ea ¤   PGPBoolean
29088a pgpaInternalStrLenValid(
313c2c ¤   pgpaCallPrefixDef,
c6793c ¤   char const *¤   str,
582539 ¤   PGPUInt32¤  ¤   ¤   minLen,
d9a19f ¤   PGPUInt32¤  ¤   ¤   maxLen,
756553 ¤   char const *¤   varName)
38bb36 {
c2f685 ¤   PGPUInt32¤  ¤   ¤   i;
ee67c5 ¤
a19e36 ¤   pgpaAddrValid(str, char);
a4af5a
18770f ¤   for (i = 0; !pgpaFailed && str[i] != '\0'; i++)
7cc7a1 ¤   {
11f055 ¤   ¤   pgpaFailIf(i >= maxLen, (pgpaFmtPrefix,
625486 ¤   ¤   ¤   ¤   "longer than %lu chars", maxLen));
--2008 001ee910374401000c4 Page 8 of pgpDebug.c
f14dd6 ¤   ¤   pgpaFailIf((uchar)(str[i]) < '\b', (pgpaFmtPrefix,
e55c15 ¤   ¤   ¤   ¤   "suspicious char 0x%x at index %lu", str[i], i));
009371 ¤   }
edaf5a
f765c4 ¤   pgpaFailIf(i < minLen, (pgpaFmtPrefix, "shorter than %lu chars", minLen));
00dbad ¤   pgpaFmtMsg((pgpaFmtPrefix, "pgpaStrLenValid failed on %s (%p)",
438c67 ¤   ¤   ¤   ¤   varName, str));
8967c5 ¤
45750f ¤   return pgpaFailed;
88efe6 }
36af5a
3f16ea ¤   PGPBoolean
bfcd40 pgpaInternalPStrLenValid(
5f3c2c ¤   pgpaCallPrefixDef,
3b2e64 ¤   uchar const *¤  str,
a9caf4 ¤   int¤¤   ¤   ¤   minLen,
dc4e52 ¤   int¤¤   ¤   ¤   maxLen,
176553 ¤   char const *¤   varName)
f0bb36 {
1c844b ¤   int¤¤   ¤   ¤   len;
6ed312 ¤   int¤¤   ¤   ¤   i;
1e67c5 ¤
c98fe6 ¤   pgpaAssert(minLen >= 0),
61ebf6 ¤   pgpaAssert(maxLen <= 255),
0fcd91 ¤   pgpaAddrValid(str, uchar);
c5af5a
f8dd07 ¤   if (!pgpaFailed)
18c7a1 ¤   {
d8218e ¤   ¤   len = str[0];
25af5a
ed76c2 ¤   ¤   pgpaFailIf(len > maxLen, (pgpaFmtPrefix,
2ded53 ¤   ¤   ¤   ¤   ¤   "longer than %d chars", maxLen));
0ba0f8 ¤   ¤   pgpaFailIf(len < minLen, (pgpaFmtPrefix,
839eb9 ¤   ¤   ¤   ¤   ¤   "shorter than %d chars", minLen));
07af5a
a025fc ¤   ¤   for (i = 1; !pgpaFailed && i <= len; i++)
4376d5 ¤   ¤   ¤   pgpaFailIf(str[i] < '\b', (pgpaFmtPrefix,
14e491 ¤   ¤   ¤   ¤   ¤   "suspicious char 0x%x at index %d", str[i], i));
08af5a
2a6ac9 ¤   ¤   pgpaFailIf(i < minLen, (pgpaFmtPrefix,
8e538b ¤   ¤   ¤   ¤   "shorter than %lu chars", minLen));
259371 ¤   }
e5af5a
63bd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
e2ff63 ¤   ¤   ¤   "pgpaPStrLenValid failed on %s (%p)", varName, str));
68af5a
89750f ¤   return pgpaFailed;
58efe6 }
20af5a
446d52 ¤   void
b6cd51 pgpDebugHook(void)
4abb36 {
05efe6 }
e5af5a
16ab79 #endif¤ /* ] PGP_DEBUG */
2baf5a
3faf5a
db7e4d /*__Editor_settings____
d2af5a
284126 ¤   Local Variables:
7d7b17 ¤   tab-width: 4
050e6c ¤   End:
df5f8c ¤   vi: ts=4 sw=4
609e9b ¤   vim: si
eed062 _____________________*/
--35ef 0000926cc6c401000c5 Page 1 of pgpDebug.h
a70335 /*____________________________________________________________________________
f0aae6 ¤   pgpDebug.h
5467c5 ¤
2cf254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
404b0f ¤   All rights reserved.
8667c5 ¤
6c0d51 ¤   Assertion macro header
ddaf5a
04ca93 ¤   $Id: pgpDebug.h,v 1.25.16.1 1998/11/12 03:17:51 heller Exp $
bbf7f7 ____________________________________________________________________________*/
3e84a9 #ifndef Included_pgpDebug_h¤/* [ */
2ad03e #define Included_pgpDebug_h
1caf5a
b8bea3 #include <stdlib.h>
4fd92d #include <stdarg.h>
55af5a
7dafb9 #if PGP_WIN32
e6460b #include <crtdbg.h>
6c7caf #elif ! PGP_MACINTOSH
8ffeb2 #include <stdio.h>
847454 #endif
93af5a
5b675a #include "pgpTypes.h"
41af5a
1caf5a
4538e5 /*
517f35 ·* pgpFixBeforeShip is a macro which forces a compile error unless
02d1b0 ·* the UNFINISHED_CODE_ALLOWED macro is non-zero.
2c3b12 ·* Example: ·pgpFixBeforeShip("Does this really work?")
e5495d ·*/
143849 #ifndef pgpFixBeforeShip
e9e83c #if UNFINISHED_CODE_ALLOWED
da9018 #define pgpFixBeforeShip(msg)
8adb21 #else
7649c6 #define pgpFixBeforeShip(msg)¤  @@@@@@ #msg @@@@@@
427454 #endif
377454 #endif
a6af5a
e538e5 /*
865b20 ·* DEBUG_STRUCT_CONSTRUCTOR defines a null constructor for a struct
e21e88 ·* which initializes the structure which all 0xDDs if PGP_DEBUG is non-zero,
8650eb ·* or does nothing otherwise. ·It requires C++. ·It shouldn't be used
d9b032 ·* for anything with virtual methods, because it will overwrite the
a56c3e ·* virtual dispatch table pointer.
aa9392 ·* Example: ·foo { int a; DEBUG_STRUCT_CONSTRUCTOR(foo) }
d2495d ·*/
536b9f #if defined(__cplusplus) && PGP_DEBUG
7e4b2e #define DEBUG_STRUCT_CONSTRUCTOR(type)¤ ¤   ¤   ¤   ¤   ¤   \
ca3f15 ¤   ¤   type(void)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
ff8b49 ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
4a43c0 ¤   ¤   ¤   pgpDebugFillMemory(this, sizeof(*this));¤   ¤   \
f10fe4 ¤   ¤   }
3edb21 #else
3fde78 #define DEBUG_STRUCT_CONSTRUCTOR(type)
237454 #endif
90af5a
9699c6 PGP_BEGIN_C_DECLARATIONS
8baf5a
6138e5 /*
f97b81 ·* All the FmtMsg macros accept the following special sequences:
60297d ·*¤ ¤   %%¤ Replaced with a single '%'
bafa86 ·*¤ ¤   %c¤ Replaced with the char argument
7b9552 ·*¤ ¤   %s¤ Replaced with the C string argument
3ce8a6 ·*¤ ¤   %S¤ Replaced with the Pascal string argument
d9a32e ·*¤ ¤   %B¤ Replaced with the memory buffer as a string
e08ca6 ·*¤ ¤   ¤   ¤   (two args: length (int), buffer)
3e4042 ·*¤ ¤   %lB¤Replaced with the memory buffer as a string
fb085b ·*¤ ¤   ¤   ¤   (two args: length (long), buffer)
afaca3 ·*¤ ¤   %d¤ Replaced with the signed integer value (base 10)
74270d ·*¤ ¤   %ld¤Replaced with the signed long value (base 10)
b11441 ·*¤ ¤   %u¤ Replaced with the unsigned integer value (base 10)
0936f4 ·*¤ ¤   %lu¤Replaced with the unsigned long value (base 10)
--6b46 000c6f2b3a1401000c5 Page 2 of pgpDebug.h
74445e ·*¤ ¤   %x¤ Replaced with the unsigned integer value (base 16)
8bb7e2 ·*¤ ¤   %lx¤Replaced with the unsigned long value (base 16)
b49805 ·*¤ ¤   %o¤ Replaced with the unsigned integer value (base 8)
934649 ·*¤ ¤   %lo¤Replaced with the unsigned long value (base 8)
5935dd ·*¤ ¤   %b¤ Replaced with the unsigned integer value (base 2)
445736 ·*¤ ¤   %lb¤Replaced with the unsigned long value (base 2)
fea803 ·*¤ ¤   %p¤ Replaced with the pointer value, printed in hex
a1495d ·*/
64af5a
2d0c9b #if PGP_DEBUG¤  ¤   ¤   ¤   /* [ */
5caf5a
da1c65 #define PGP_DEBUG_BUF_SIZE¤ ¤   256
7faf5a
fffca8 #if PGP_DEBUG_STACK_BUFFERS¤¤   /* [ */
94af5a
efa2e8 #define PGP_DEBUG_ALLOC_BUF¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
49c550 ¤   ¤   uchar¤  pgpaBuf[PGP_DEBUG_BUF_SIZE];¤   ¤   ¤   ¤   ¤   ¤   \
a3346d ¤   ¤   int¤¤   pgpaBufSize = sizeof(pgpaBuf);
f8388b #define PGP_DEBUG_DEALLOC_BUF
b7af5a
b7db21 #else
89af5a
935062 #define PGP_DEBUG_NUM_BUFS¤ ¤   2
bfaf5a
14a2e8 #define PGP_DEBUG_ALLOC_BUF¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
ca8f5a ¤   ¤   int¤¤   pgpaBufSize = PGP_DEBUG_BUF_SIZE;¤  ¤   ¤   ¤   ¤   \
f091ec ¤   ¤   uchar¤  *pgpaBuf = (pgpaDebugBufStack -= PGP_DEBUG_BUF_SIZE);
323c55 #define PGP_DEBUG_DEALLOC_BUF¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
4cdb8d ¤   ¤   pgpaDebugBufStack += PGP_DEBUG_BUF_SIZE;
b756c1 extern ·uchar¤  pgpaDebugBuf[PGP_DEBUG_BUF_SIZE
920ea7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   * PGP_DEBUG_NUM_BUFS];
39f212 extern ·uchar *¤pgpaDebugBufStack;
4faf5a
25c511 #endif¤ /* ] PGP_DEBUG_STACK_BUFFERS */
f8af5a
8eaf5a
715ef2 #if PGP_MACINTOSH¤  ¤   ¤   /* [ */
abaf5a
a18bef #define pgpDebugPStr(pStr)¤ ¤   ¤   DebugStr(pStr)
f4e1f0 #define pgpDebugHybridStr(hStr)¤¤   pgpDebugPStr( hStr )·
171b52 ¤   ¤
b6604e #define pgpDebugMsg(message)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
0f49a6 ¤   ¤   do¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
33b2ce ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
a9ec6c ¤   ¤   ¤   uchar¤  PGP__msg_buf[256];¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c91ca1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
53109f ¤   ¤   ¤   pgpFormatPStr(PGP__msg_buf, sizeof(PGP__msg_buf),¤  ¤   \
7920b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   TRUE, "%s", (message));¤¤   ¤   ¤   ¤   \
087266 ¤   ¤   ¤   pgpDebugPStr(PGP__msg_buf);¤¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c42799 ¤   ¤   } while (0)
ffaf5a
19c54b #elif defined(PGP_WIN32)¤   /* ] [ */
cbaf5a
02af5a
14604e #define pgpDebugMsg(message)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f049a6 ¤   ¤   do¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
26b2ce ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
6b74a1 ¤   ¤   ¤   if (_CrtDbgReport(_CRT_ASSERT, NULL, 0, NULL, "\r\n%s",¤\
e482ea ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (message))==1)¤ ¤   ¤   \
59f02d ¤   ¤   ¤   ¤   _CrtDbgBreak();¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c742aa ····} while (0)
36af5a
881b52 ¤   ¤
efe65c #define pgpDebugHybridStr(hStr)¤pgpDebugMsg((char *)(hStr) + 1)
d1af5a
82f754 #else¤  /* ] [ */
40af5a
fc604e #define pgpDebugMsg(message)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2249a6 ¤   ¤   do¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f8b2ce ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
85e6a5 ¤   ¤   ¤   fprintf(stderr, "%s\n", (char *)(message));¤¤   ¤   ¤   \
c6b1ee ¤   ¤   ¤   pgpDebugHook();¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
--fa90 000338c3c18401000c5 Page 3 of pgpDebug.h
332799 ¤   ¤   } while (0)
69e65c #define pgpDebugHybridStr(hStr)¤pgpDebugMsg((char *)(hStr) + 1)
ccaf5a
133167 #endif¤ /* ] */
30af5a
9e9399 #define pgpDebugFmtMsg(params)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c049a6 ¤   ¤   do¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
63b2ce ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
0b1260 ¤   ¤   ¤   uchar¤  pgpaBuf[256];¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
a68a45 ¤   ¤   ¤   int¤¤   pgpaBufSize = sizeof(pgpaBuf);¤ ¤   ¤   ¤   ¤   \
351ca1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f23c61 ¤   ¤   ¤   pgpDebugHybridStr(pgpDebugFormatHStr params);¤  ¤   ¤   \
cd2799 ¤   ¤   } while (0)
d3af5a
8d7ecd #define pgpDebugMsgIf(condition, message)¤  ¤   ¤   ¤   ¤   ¤   ¤   \
1149a6 ¤   ¤   do¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
afb2ce ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
137b04 ¤   ¤   ¤   if (condition)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
b1f01b ¤   ¤   ¤   ¤   pgpDebugMsg(message);¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
d72799 ¤   ¤   } while (0)
7faf5a
9b38e5 /*
983f4c ·* The first couple parameters which must always be
f29373 ·* passed as the beginning of a format list.
b4495d ·*/
2c43a3 #define pgpaFmtPrefix¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2d0ecc ¤   ¤   pgpaBuf, pgpaBufSize
7daf5a
7a38e5 /*
5e0ca7 ·* The general pgpa command to check a condition and
b0dd7f ·* print out a formatted message if it's not true.
80495d ·*/
49d294 #if !PGP_MACINTOSH¤ /* [ */
21af5a
8a94af #define pgpaFailIf(condition, params)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
acd310 ¤   ¤   ((void)(pgpaFailed || !(condition) ||¤  ¤   ¤   ¤   ¤   ¤   \
93bd0b ¤   ¤   ¤   ((pgpaFailed = TRUE), (pgpDebugFormatHStr params))))
18af5a
509098 #else¤  /* ] !PGP_MACINTOSH [ */
87af5a
7382c9 /* XXX: This is a workaround for a CW11 68k codegen bug */
cb94af #define pgpaFailIf(condition, params)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
aa096c ¤   ¤   ((void)(pgpaFailed || !((condition) ? 1 : 0) ||¤¤   ¤   ¤   \
8bbd0b ¤   ¤   ¤   ((pgpaFailed = TRUE), (pgpDebugFormatHStr params))))
b4af5a
a9087d #endif¤ /* ] !PGP_MACINTOSH */
d0af5a
8138e5 /*
25b664 ·* A simple pgpa command to assert a given condition.
92495d ·*/
0397bb #define pgpaAssert(condition)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
9931ae ¤   ¤   pgpaFailIf(!(condition),¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
ec58ca ¤   ¤   ¤   (pgpaFmtPrefix, "(%s) not true", #condition))
dcaf5a
ae38e5 /*
690f4e ·* Used to add more formatted information to an assertion failure
ac495d ·*/
091667 #define pgpaFmtMsg(params)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c5f1a1 ¤   ¤   ((void)(pgpaFailed && (pgpDebugPrefixFormatHStr params)))
0cda6e #define pgpaMsg(message)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
0d3d4e ¤   ¤   pgpaFmtMsg((pgpaFmtPrefix, "%s", message))
65af5a
d238e5 /*
9c3f4c ·* The first couple parameters which must always be
dfb5ba ·* passed as the beginning of a pgpaCall parameter list.
39495d ·*/
ff8781 #define pgpaCallPrefix¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c39451 ¤   ¤   pgpaBuf, pgpaBufSize, pgpaFailed
80c5b3 #define pgpaCallPrefixDef¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
68f566 ¤   ¤   uchar *pgpaBuf, int pgpaBufSize, PGPBoolean pgpaFailed
67af5a
3338e5 /*
--2dd5 0007dfb6e55401000c5 Page 4 of pgpDebug.h
5154d1 ·* The general pgpa command to call a pgpa-style function.
48495d ·*/
b25bbe #define pgpaCall(function, params)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
b05bba ¤   ¤   ((void)(pgpaFailed || ((pgpaFailed = (function params)) != FALSE)))
afaf5a
a938e5 /*
64f588 ·* The main pgpa macro from which all the pgpa
664aa1 ·* macros must be used as parameters.
2b495d ·*/
524236 #define pgpa(assertions)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c749a6 ¤   ¤   do¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
61b2ce ¤   ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
41a673 ¤   ¤   ¤   PGPBoolean¤ ¤   pgpaFailed = FALSE;¤¤   ¤   ¤   ¤   ¤   ¤   \
7f91cf ¤   ¤   ¤   PGP_DEBUG_ALLOC_BUF¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
121ca1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2da93c ¤   ¤   ¤   (assertions);¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2116cc ¤   ¤   ¤   pgpaFmtMsg((pgpaFmtPrefix,¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
e58108 ¤   ¤   ¤   ¤   ¤   ¤   "ASSERTION FAILED at %s line %ld",¤ ¤   ¤   \
e4cef2 ¤   ¤   ¤   ¤   ¤   ¤   __FILE__, (long)__LINE__));¤¤   ¤   ¤   ¤   \
cbfd54 ¤   ¤   ¤   if (pgpaFailed)¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
4f804b ¤   ¤   ¤   ¤   pgpDebugHybridStr(pgpaBuf);¤¤   ¤   ¤   ¤   ¤   ¤   \
7e6699 ¤   ¤   ¤   PGP_DEBUG_DEALLOC_BUF¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
dd2799 ¤   ¤   } while (0)
60af5a
9ab111 #define pgpaAddrValid(addr, pointedAtType)¤ ¤   ¤   ¤   ¤   ¤   ¤   \
37ad02 ¤   ¤   pgpaCall(pgpaInternalAddrValid,¤¤   ¤   ¤   ¤   ¤   ¤   ¤   \
fea99e ¤   ¤   ¤   ¤   (pgpaCallPrefix, addr, alignof(pointedAtType), #addr))
d1af5a
47fe57 #define pgpaStrLenValid(str, minLen, maxLen)¤   ¤   ¤   ¤   ¤   ¤   \
258bee ¤   ¤   pgpaCall(pgpaInternalStrLenValid,¤  ¤   ¤   ¤   ¤   ¤   ¤   \
7d6c76 ¤   ¤   ¤   ¤   (pgpaCallPrefix, str, minLen, maxLen, #str))
c39d53 #define pgpaPStrLenValid(pstr, minLen, maxLen)¤ ¤   ¤   ¤   ¤   ¤   \
83d1f1 ¤   ¤   pgpaCall(pgpaInternalPStrLenValid,¤ ¤   ¤   ¤   ¤   ¤   ¤   \
b32f7b ¤   ¤   ¤   ¤   (pgpaCallPrefix, pstr, minLen, maxLen, #pstr))
73af5a
da68a6 /* pgpaStrValid currently assumes an arbitrary reasonable length */
2a2fe2 #define pgpaStrValid(str)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
6034d4 ¤   ¤   pgpaStrLenValid(str, 0, 32767)
5f00cf #define pgpaPStrValid(pstr)¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
d70be3 ¤   ¤   pgpaPStrLenValid(pstr, 0, 255)
28af5a
346f22 #else /* ] PGP_DEBUG [ */
d9af5a
35ea38 #define pgpa(assertions)
34d44f #define pgpDebugMsgIf(cond, msg)
b3458a #define pgpDebugPStr(pStr)
68f941 #define pgpDebugFmtMsg(params)
9025e0 #define pgpDebugMsg(msg)
c4af5a
249e9f #endif /* ] PGP_DEBUG */
36af5a
e538e5 /*
bd9c03 ·* Convenient short-hands follow
5e495d ·*/
f0af5a
542c30 #define pgpAssert(condition)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
b961a0 ¤   ¤   pgpa(pgpaAssert(condition))
c84f26 #define pgpAssertMsg(condition, message)¤   ¤   ¤   ¤   ¤   ¤   ¤   \
9d08a4 ¤   ¤   pgpa((¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2c3501 ¤   ¤   ¤   pgpaAssert(condition),¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
bca5ee ¤   ¤   ¤   pgpaMsg(message)))
9aaf5a
17fa6f #define pgpAssertAddrValid(ptr, type)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
3a165c ¤   ¤   pgpa(pgpaAddrValid(ptr, type))
db8612 #define pgpAssertAddrValidMsg(ptr, type, message)¤  ¤   ¤   ¤   ¤   \
d908a4 ¤   ¤   pgpa((¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2ea420 ¤   ¤   ¤   pgpaAddrValid(ptr, type),¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f6a5ee ¤   ¤   ¤   pgpaMsg(message)))
e5af5a
a46149 #define pgpAssertStrLenValid(str, minLen, maxLen)¤  ¤   ¤   ¤   ¤   \
9cdf2e ¤   ¤   pgpa(pgpaStrLenValid(str, minLen, maxLen))
7d07ee #define pgpAssertStrLenValidMsg(str, minLen, maxLen, message)¤  ¤   \
--9cb3 0003d674fea401000c5 Page 5 of pgpDebug.h
d808a4 ¤   ¤   pgpa((¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
bc0511 ¤   ¤   ¤   pgpaStrLenValid(str, minLen, maxLen),¤  ¤   ¤   ¤   ¤   \
97a5ee ¤   ¤   ¤   pgpaMsg(message)))
49af5a
c33105 #define pgpAssertPStrLenValid(pstr, minLen, maxLen)¤¤   ¤   ¤   ¤   \
06ccf6 ¤   ¤   pgpa(pgpaPStrLenValid(pstr, minLen, maxLen))
35dfab #define pgpAssertPStrLenValidMsg(pstr, minLen, maxLen, message)¤¤   \
6308a4 ¤   ¤   pgpa((¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
2ae43e ¤   ¤   ¤   pgpaPStrLenValid(pstr, minLen, maxLen),¤¤   ¤   ¤   ¤   \
63a5ee ¤   ¤   ¤   pgpaMsg(message)))
47af5a
5aad7b #define pgpAssertStrValid(str)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
c77b26 ¤   ¤   pgpa(pgpaStrValid(str))
fe324c #define pgpAssertStrValidMsg(str, msg)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
4908a4 ¤   ¤   pgpa((¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
041af0 ¤   ¤   ¤   pgpaStrValid(str, minLen, maxLen),¤ ¤   ¤   ¤   ¤   ¤   \
9aa5ee ¤   ¤   ¤   pgpaMsg(message)))
43af5a
0c41db #define pgpAssertPStrValid(pstr)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
e6e16a ¤   ¤   pgpa(pgpaPStrValid(pstr))
3ad921 #define pgpAssertPStrValidMsg(pstr, message)¤   ¤   ¤   ¤   ¤   ¤   \
1908a4 ¤   ¤   pgpa((¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
52ffd1 ¤   ¤   ¤   pgpaPStrValid(pstr, minLen, maxLen),¤   ¤   ¤   ¤   ¤   \
9da5ee ¤   ¤   ¤   pgpaMsg(message)))
81af5a
b7af5a
6d15d7 #define pgpAssertNoErr( err ) ¤ pgpAssert( IsntPGPError( err ) || ¤ \
73f726 ¤   ¤   err == kPGPError_UserAbort )
8d70cc #define pgpAssertErrWithPtr(err, ptr) \
78dfac ¤   ¤   pgpAssert( ( IsntPGPError( err ) && (ptr) != NULL ) || \
9b8b5d ¤   ¤   ( IsPGPError( err ) && (ptr) == NULL ) )
ba1b52 ¤   ¤
e81b52 ¤   ¤
d497eb int¤¤   ¤   pgpFormatVAStr(uchar *buffer, int bufferSize,
7557c1 ¤   ¤   ¤   ¤   PGPBoolean putLengthPrefix, PGPBoolean putNullTerminator,
0605f0 ¤   ¤   ¤   ¤   PGPBoolean canonicalizeNLs, char const *formatStr,
708434 ¤   ¤   ¤   ¤   va_list args);
2f50e5 uchar *¤¤   pgpFormatHStr(uchar *buffer, int bufferSize,
c35da6 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean canonicalizeNLs, char const *formatStr, ...);
ec8e92 uchar *¤¤   pgpFormatPStr(uchar *buffer, int bufferSize,
f45da6 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean canonicalizeNLs, char const *formatStr, ...);
fc7443 uchar *¤¤   pgpFormatPStr255(uchar *buffer, PGPBoolean canonicalizeNLs,
b48c65 ¤   ¤   ¤   ¤   ¤   ¤   char const *formatStr, ...);
b4f75d char *¤ ¤   pgpFormatStr(char *buffer, int bufferSize,
4a598a ¤   ¤   ¤   ¤   ¤   PGPBoolean canonicalizeNLs,
c7df7e ¤   ¤   ¤   ¤   ¤   char const *formatStr, ...);
1daf5a
89af5a
e5e85e #if PGP_DEBUG¤  /* [ */
201b5b #define pgpDebugWhackMemory( buffer, length )¤  \
e8d5df ¤   pgpFillMemory( buffer, length, 0xDD )
61db21 #else
37f26a #define pgpDebugWhackMemory( buffer, length )¤  /* nothing */
b77454 #endif
ebaf5a
20e85e #if PGP_DEBUG¤  /* [ */
0aaf5a
9dfc80 uchar ·*¤   pgpDebugFormatHStr(uchar *buffer, int bufferSize,
c6c5e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *formatStr, ...);
e729df uchar ·*¤   pgpDebugPrefixFormatHStr(uchar *buffer,
36ba62 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   int bufferSize, char const *formatStr, ...);
ecaf5a
5438e5 /*
05a5eb ·* These are internal routines which should only be called by the above macros
ef495d ·*/
3e5df0 void ¤  ¤   pgpDebugFillMemory(void *buffer, size_t length);
be289e PGPBoolean¤ ¤   pgpaInternalAddrValid(pgpaCallPrefixDef,
ccd22c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   void const *addr, int alignSize,
208a48 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *varName);
b6b7e5 PGPBoolean¤ ¤   pgpaInternalStrLenValid(pgpaCallPrefixDef,
3af165 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *str, PGPUInt32 minLen,
3dd826 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 maxLen, char const *varName);
--b1d4 001b9135e28401000c5 Page 6 of pgpDebug.h
992be0 PGPBoolean¤ ¤   pgpaInternalPStrLenValid(pgpaCallPrefixDef,
1b9566 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   uchar const *str, int minLen,
bd4ce1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   int maxLen, char const *varName);
2eaf5a
a838e5 /*
bd8eb8 ·* Except on the Mac, when debugger messages are printed or assertions
15b25e ·* fail, this routine will always be called. ·Its only purpose is to be
3f51de ·* used as a breakpoint location, to catch failed assertions from the
f239c8 ·* debugger.
b6495d ·*/
431578 void¤   ¤   pgpDebugHook(void);
85af5a
169e9f #endif /* ] PGP_DEBUG */
39af5a
7a1254 PGP_END_C_DECLARATIONS
4aaf5a
69af5a
c9f9e4 #endif /* ] Included_pgpDebug_h */
f4af5a
9faf5a
bd7e4d /*__Editor_settings____
0baf5a
414126 ¤   Local Variables:
657b17 ¤   tab-width: 4
e20e6c ¤   End:
af5f8c ¤   vi: ts=4 sw=4
649e9b ¤   vim: si
b9d062 _____________________*/
--01b0 001e9c06dd1401000c6 Page 1 of pgpException.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
ce24f3 ¤   $Id: pgpException.h,v 1.2.16.1 1998/11/12 03:17:52 heller Exp $
52f7f7 ____________________________________________________________________________*/
23af5a
d293e7 #ifndef Included_pgpException_h
aa5684 #define Included_pgpException_h
d9af5a
c82b62 #include "pgpPFLErrors.h"
33af5a
f2f53a #define ThrowPGPError_(x)¤  throw(((PGPError) (x)))
b96a50 #define ThrowIfPGPError_(x)¤if (IsPGPError((x))) ThrowPGPError_(x)
0aaf5a
e92841 #endif¶
--e442 0007c7a2d9e401000c7 Page 1 of pgpLeaks.c
a70335 /*____________________________________________________________________________
460b3a ¤   pgpLeaks.c
b167c5 ¤
a9f254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
744b0f ¤   All rights reserved.
0b67c5 ¤
b052af ¤   Leak tracking module for memory allocation routines
68af5a
9c2e97 ¤   $Id: pgpLeaks.c,v 1.24.14.1 1998/11/12 03:17:53 heller Exp $
11f7f7 ____________________________________________________________________________*/
74e610 #include "pgpPFLConfig.h"
04af5a
1bbea3 #include <stdlib.h>
29a7a0 #include <limits.h>
e1324c #include <string.h>
9f0d08 #include "pgpMem.h"
e994a0 #include "pgpLeaks.h"
02675a #include "pgpTypes.h"
990ccc #if PGP_MACINTOSH
8a090b #include "MacEvents.h"
ed7454 #endif
60af5a
1e3f02 #if USE_PGP_LEAKS¤  /* [ */
44af5a
dbec08 #ifdef _WIN32
711d42 #define inline
d67454 #endif
86af5a
0a1ebd typedef struct LeaksSession
2abb36 {
4951c9 ¤   struct LeaksSession *¤  prevSession;
fde80d ¤   char const *¤   ¤   ¤   name;
66c585 ¤   PGPUInt32¤  ¤   ¤   ¤   allocationNumber;
a2a884 ¤   LeakItem¤   ¤   ¤   ¤   dummyItem;
8f5a5d } LeaksSession;
50af5a
bdaf5a
c53e0d static DECLARE_LEAKDEALLOCSTRUCT(kSessionDummyDeallocType,
1e29b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "Session dummy dealloc");
327942 static DECLARE_LEAKALLOCTYPE(kSessionDummyAllocType, "Session dummy alloc",
a3846c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kSessionDummyDeallocType);
abaf5a
dd38e5 /*
6c086a ·* In order to avoid allocating memory until we have the first session
17cdb5 ·* initialized, we use this static variable for the first session.
6d495d ·*/
0baf3c static LeaksSession¤¤   sInitialSession =·
1abb36 {
ed8e59 ¤   NULL,¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* prevSession¤ ¤   */
ff4070 ¤   "init",¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* name¤¤   ¤   ¤   */
76432d ¤   0,
fa18ba ¤   {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* dummyItem¤   ¤   */
16ddee ¤   kLeakItemMagic,¤¤   ¤   ¤   ¤   ¤   ¤   ¤   /* ··magic¤ ¤   ¤   */
5c0255 ¤   &LeakStructName(kSessionDummyAllocType),¤   /* ··allocType¤ ¤   */
5926cf ¤   0,¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* ··size¤  ¤   ¤   */
832b60 ¤   FALSE,¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* ··ignore¤¤   ¤   */
de537d ¤   FALSE,¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ·inSessionList¤ */
abd5d7 ¤   FALSE,¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ·pad[1]¤¤   ¤   */
7256e9 ¤   FALSE,¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ·pad[2]¤¤   ¤   */
9f87cb ¤   &sInitialSession.dummyItem,¤¤   ¤   ¤   ¤   /* ··prev¤  ¤   ¤   */
e733dd ¤   &sInitialSession.dummyItem,¤¤   ¤   ¤   ¤   /* ··next¤  ¤   ¤   */
bbd1e4 ¤   __FILE__,¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* ··fileName¤  ¤   */
c59985 ¤   __LINE__,¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* ··lineNumber¤¤   */
849349 ¤   &sInitialSession¤   ¤   ¤   ¤   ¤   ¤   ¤   /* ··memory¤¤   ¤   */
fc9371 ¤   }
a582f7 };
f2af5a
014827 static LeaksSession *¤  sCurrentSession = &sInitialSession;
6681cd static int¤ ¤   ¤   ¤   sNumUnallocatedSessions = 0;
7e54c0 static int¤ ¤   ¤   ¤   sSuspendCount = 0;
a6af5a
7caf5a
--62b4 000ac073cbd401000c7 Page 2 of pgpLeaks.c
3b6d52 ¤   void
f66be4 pgpLeaksSuspend(void)
c2cebb {¤
64553a ¤   ++sSuspendCount;
60efe6 }
2eaf5a
256d52 ¤   void
dd4d93 pgpLeaksResume(void)
44bb36 {
c07620 ¤   pgpAssertMsg(sSuspendCount >= 1,
6cdd38 ¤   ¤   "pgpLeaksResume: not currently suspended");
b3094b ¤   --sSuspendCount;
99efe6 }
2aaf5a
65c9b7 ¤   static inline PGPBoolean
d088d1 pgpLeaksSuspended(void)
cdbb36 {
14d8ac ¤   return sSuspendCount != 0;
beefe6 }
68af5a
fa33c8 ¤   static void
622ea3 pgpLeaksLinkItem(
702b7c ¤   LeakItem *¤ ¤   existingItem,
944e15 ¤   LeakItem *¤ ¤   newItem)
79bb36 {
ff5e68 ¤   pgpa((
5a3ce7 ¤   ¤   pgpaLeakItemValid(existingItem),
c2d38d ¤   ¤   pgpaMsg("Invalid existing item")));
abc6e3 ¤   newItem->prev¤  ¤   ¤   = existingItem;
56f258 ¤   newItem->next¤  ¤   ¤   = existingItem->next;
9fbf0f ¤   newItem->prev->next¤¤   = newItem;
2bf409 ¤   newItem->next->prev¤¤   = newItem;
35d763 ¤   newItem->inSessionList¤ = TRUE;
d667c5 ¤
662b25 ¤   pgpa(pgpaLeakItemValid(newItem));
3defe6 }
27af5a
0733c8 ¤   static void
f33572 pgpLeaksUnlinkItem(
5e334a ¤   LeakItem *¤ ¤   item)
b9bb36 {
fecc74 ¤   pgpa((pgpaLeakItemValid(item),
f120bb ¤   ¤   pgpaMsg("Invalid item")));
d91b52 ¤   ¤
ac4317 ¤   if( item->inSessionList )
62c7a1 ¤   {
753fd2 ¤   ¤   pgpa((
772101 ¤   ¤   ¤   pgpaLeakItemValid(item->prev),
7fbdca ¤   ¤   ¤   pgpaLeakItemValid(item->next),
34d584 ¤   ¤   ¤   pgpaMsg("Invalid item links")));
98f4de ¤   ¤   item->prev->next = item->next;
0cbc1f ¤   ¤   item->next->prev = item->prev;
a19371 ¤   }
deefe6 }
bbaf5a
34a9ca #define pgpaLeaksSessionValid(session)¤ ¤   ¤   ¤   ¤   ¤   \
e19015 ¤   ¤   pgpaCall(pgpaInternalLeaksSessionValid, (pgpaCallPrefix, session))
f2af5a
58e85e #if PGP_DEBUG¤  /* [ */
e8af5a
696c2c ¤   static PGPBoolean
6f0ce0 pgpaInternalLeaksSessionValid(
4a3c2c ¤   pgpaCallPrefixDef,
0d3ab0 ¤   const LeaksSession *¤   session)
6dbb36 {
4dd8af ¤   /*
62136a ¤   ·* pgpLeaksNotifyItemMoved assumes this routine
116afb ¤   ·* won't check the prev and next links
24a4e3 ¤   ·*/
b6b6f5 ¤   pgpaAddrValid(session, LeaksSession);
572975 ¤   pgpaLeakItemValid(&session->dummyItem);
acc5f2 ¤   pgpaAssert(session->dummyItem.allocType == kSessionDummyAllocType);
--ec33 000971ea681401000c7 Page 3 of pgpLeaks.c
73a16e ¤   pgpaMsg("pgpaLeaksSessionValid failed");
4aaf5a
ab750f ¤   return pgpaFailed;
f4efe6 }
82af5a
6fab79 #endif¤ /* ] PGP_DEBUG */
bbaf5a
c133c8 ¤   static void
ebc7f4 pgpLeaksInitLinkItem(
edc6d5 ¤   LeakItem *¤ ¤   ¤   item,
f3d958 ¤   LeakAllocType *¤¤   allocType,
7f74f7 ¤   void const *¤   ¤   memory,
84ab78 ¤   PGPUInt32¤  ¤   ¤   ¤   size,
1ca355 ¤   char const *¤   ¤   fileName,
b230e0 ¤   long¤   ¤   ¤   ¤   lineNumber)
3abb36 {
2f5e68 ¤   pgpa((
237c3e ¤   ¤   pgpaAddrValid(item, LeakItem),
afc556 ¤   ¤   pgpaLeakAllocTypeValid(allocType),
0b2ca4 ¤   ¤   pgpaAddrValid(memory, VoidAlign),
e2660a ¤   ¤   pgpaStrValid(fileName),
61be79 ¤   ¤   pgpaMsg("Invalid parameters")));
4267c5 ¤
a1cdd1 ¤   item->magic¤¤   ¤   = kLeakItemMagic;
01c3d7 ¤   item->allocType¤¤   = allocType;
e298e1 ¤   item->size¤ ¤   ¤   = size;
a82976 ¤   item->ignore¤   ¤   = FALSE;
d7f53d ¤   item->inSessionList¤= FALSE;
f46119 ¤   item->prev¤ ¤   ¤   = item;
2a0001 ¤   item->next¤ ¤   ¤   = item;
bac6c4 ¤   item->fileName¤ ¤   = fileName;
928317 ¤   item->lineNumber¤   = lineNumber;
2f9711 ¤   item->memory¤   ¤   = memory;
d62abd ¤   /* monotonically increasing number, to identify a leak */
63af5a
b88c69 ¤   item->allocationNumber¤ = sCurrentSession->allocationNumber++;
f6efe6 }
46af5a
7f6d52 ¤   void
1b8233 pgpLeaksBeginSession(
0914fc ¤   char const *¤   ¤   sessionName)
d7bb36 {
d96846 ¤   LeaksSession *¤ ¤   newSession ¤¤   = NULL;
7167c5 ¤
7f5e68 ¤   pgpa((
af6f63 ¤   ¤   pgpaStrValid(sessionName),
3bbe79 ¤   ¤   pgpaMsg("Invalid parameters")));
3967c5 ¤
65d8af ¤   /*
231872 ¤   ·* If we can't allocate a new session, we just increment the
846733 ¤   ·* sNumUnallocatedSessions counter, so we keep using the parent session
e98607 ¤   ·* instead. ·In addition, if we're already in a session which couldn't
d63a76 ¤   ·* be allocated (sNumUnallocatedSessions > 0), we won't even try to
759f20 ¤   ·* allocate this one, because it would be more complicated to keep track
e5c5c5 ¤   ·* of than it's worth.
3aa4e3 ¤   ·*/
55ea4c ¤   if (sNumUnallocatedSessions <= 0)
557774 ¤   ¤   newSession = (LeaksSession *)pgpAlloc(sizeof(LeaksSession));
f267c5 ¤
9e1957 ¤   if (newSession == NULL)
0ec7a1 ¤   {
d9a317 ¤   ¤   sNumUnallocatedSessions++;
c40729 ¤   ¤   pgpDebugMsg("Unable to allocate new leaks session");
ec9371 ¤   }
c90e24 ¤   else
17c7a1 ¤   {
99d10e ¤   ¤   pgpClearMemory( newSession, sizeof( *newSession ) );
0a1b52 ¤   ¤
5e7792 ¤   ¤   newSession->prevSession¤¤   ¤   = sCurrentSession;
63c6f1 ¤   ¤   newSession->name¤   ¤   ¤   ¤   = sessionName;
ebfbd9 ¤   ¤   newSession->allocationNumber¤   = 0;
9765e3 ¤   ¤   pgpLeaksInitLinkItem(&newSession->dummyItem, kSessionDummyAllocType,
--92a7 000699726c1401000c7 Page 4 of pgpLeaks.c
3faad8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *)newSession, 0, __FILE__, __LINE__);
71c5ce ¤   ¤   sCurrentSession = newSession;
659371 ¤   }
22efe6 }
0baf5a
cf1964 ¤   static PGPUInt32
48c834 pgpLeaksCountLeaks(
e00703 ¤   const LeaksSession *¤   ¤   session)
a3bb36 {
dec706 ¤   PGPUInt32¤  ¤   ¤   ¤   numLeaks = 0;
ebfc3c ¤   LeakItem const *¤   item;
bd67c5 ¤
0d5e68 ¤   pgpa((
be7539 ¤   ¤   pgpaLeaksSessionValid(session),
70294e ¤   ¤   pgpaMsg("Invalid LeaksSession")));
9f67c5 ¤
2609eb ¤   for (item = session->dummyItem.next; item != &session->dummyItem;
ac826f ¤   ¤   ¤   item = item->next)
99c7a1 ¤   {
33a41b ¤   ¤   pgpa(pgpaLeakItemValid(item));
deb41e ¤   ¤   if (!item->ignore)
bcfc69 ¤   ¤   ¤   ++numLeaks;
849371 ¤   }
3cd85e ¤   return numLeaks;
84efe6 }
c7af5a
de33c8 ¤   static void
7dd33c pgpLeaksShowSessionLeaks(
c80703 ¤   const LeaksSession *¤   ¤   session)
3ebb36 {
ebeebb ¤   PGPUInt32¤  ¤   ¤   ¤   numLeaks;
13fc3c ¤   LeakItem const *¤   item;
801b52 ¤   ¤
845e68 ¤   pgpa((
067539 ¤   ¤   pgpaLeaksSessionValid(session),
b1294e ¤   ¤   pgpaMsg("Invalid LeaksSession")));
c367c5 ¤
7ca35f ¤   numLeaks = pgpLeaksCountLeaks(session);
ca585b ¤   if (numLeaks != 0)
21c7a1 ¤   {
85d009 ¤   ¤   pgpDebugFmtMsg((pgpaFmtPrefix,
36c2e2 ¤   ¤   ¤   ¤   ¤   ¤   "Ending session %s with %lu leaks:",
5a27fa ¤   ¤   ¤   ¤   ¤   ¤   session->name, numLeaks));
ce67c5 ¤
ab1f5d ¤   ¤   for (item = session->dummyItem.next; item != &session->dummyItem;
8f0e10 ¤   ¤   ¤   ¤   item = item->next)
3c5b34 ¤   ¤   {
eecb99 ¤   ¤   ¤   PGPBoolean¤ shouldShowLeak;
3287c7 ¤   ¤   ¤
07aa57 ¤   ¤   ¤   pgpa(pgpaLeakItemValid(item));
fb87c7 ¤   ¤   ¤
b0e39d ¤   ¤   ¤   shouldShowLeak¤ = ! item->ignore;
b1f1e3 ¤   ¤   #if PGP_MACINTOSH
38e356 ¤   ¤   ¤   shouldShowLeak¤ = shouldShowLeak &&
ac6a9a ¤   ¤   ¤   ¤   ¤   (( GetAllModifiers() & alphaLock ) == 0 );
88d656 ¤   ¤   #endif
81a699 ¤   ¤   ¤   if ( shouldShowLeak )
00f776 ¤   ¤   ¤   {
ec4fdd ¤   ¤   ¤   ¤   pgpDebugFmtMsg((pgpaFmtPrefix,
b477d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "LEAK ID=%ld at %p of %lu bytes from %s "
d95b82 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "line %ld (%s), session %s ",
57e9ce ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (long)item->allocationNumber,
b3ecdc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->memory, item->size,
69edf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->fileName, item->lineNumber,
312469 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->allocType->name, session->name ));
30a3a6 ¤   ¤   ¤   }
620fe4 ¤   ¤   }
e19371 ¤   }
70efe6 }
45af5a
996d52 ¤   void
698a3e pgpLeaksEndSession(void)
--9bdc 000870508a6401000c7 Page 5 of pgpLeaks.c
2cbb36 {
32a014 ¤   if (sNumUnallocatedSessions > 0)
d93e54 ¤   ¤   sNumUnallocatedSessions--;
ff0e24 ¤   else
76c7a1 ¤   {
f91fd6 ¤   ¤   LeaksSession *¤ oldSession;
951b52 ¤   ¤
7988f8 ¤   ¤   pgpa(pgpaLeaksSessionValid(sCurrentSession));
e51b6e ¤   ¤   oldSession = sCurrentSession;
cc61d4 ¤   ¤   sCurrentSession = oldSession->prevSession;
09309e ¤   ¤   pgpLeaksShowSessionLeaks(oldSession);
79eb2a ¤   ¤   if (oldSession != &sInitialSession)
88b40f ¤   ¤   ¤   pgpFree(oldSession);
4d9371 ¤   }
c6efe6 }
b5af5a
be6d52 ¤   void
f50580 pgpLeaksRememberItem(
ebc6d5 ¤   LeakItem *¤ ¤   ¤   item,
779831 ¤   LeakAllocType *¤¤   type,
4674f7 ¤   void const *¤   ¤   memory,
24ab78 ¤   PGPUInt32¤  ¤   ¤   ¤   size,
daa355 ¤   char const *¤   ¤   fileName,
bf30e0 ¤   long¤   ¤   ¤   ¤   lineNumber)
72bb36 {
b326f9 ¤   pgpa(pgpaLeaksSessionValid(sCurrentSession));
0767c5 ¤
ba5e68 ¤   pgpa((
9a7c3e ¤   ¤   pgpaAddrValid(item, LeakItem),
d8c9c9 ¤   ¤   pgpaLeakAllocTypeValid(type),
4c2ca4 ¤   ¤   pgpaAddrValid(memory, VoidAlign),
7a660a ¤   ¤   pgpaStrValid(fileName),
36be79 ¤   ¤   pgpaMsg("Invalid parameters")));
4326f9 ¤   pgpa(pgpaLeaksSessionValid(sCurrentSession));
4767c5 ¤
2f64d9 ¤   pgpLeaksInitLinkItem(item, type, memory, size, fileName, lineNumber);
0967c5 ¤
343adf ¤   if( pgpLeaksSuspended() )
7dc7a1 ¤   {
4c9b7e ¤   ¤   pgpLeaksIgnoreItem(item);
0f9371 ¤   }
0e0e24 ¤   else
d2c7a1 ¤   {
b16496 ¤   ¤   pgpLeaksLinkItem(&sCurrentSession->dummyItem, item);
1e9371 ¤   }
9fefe6 }
b0af5a
736d52 ¤   void
05dc61 pgpLeaksIgnoreItem(
83334a ¤   LeakItem *¤ ¤   item)
6fbb36 {
ee5e68 ¤   pgpa((
2704dc ¤   ¤   pgpaLeakItemValid(item),
32be79 ¤   ¤   pgpaMsg("Invalid parameters")));
0b67c5 ¤
36f25c ¤   item->ignore = TRUE;
e7efe6 }
24af5a
206d52 ¤   void
434fd3 pgpLeaksIgnoreMemory(
a1d536 ¤   const void *¤   memory)
b3bb36 {
509847 ¤   pgpAssertAddrValid(memory, VoidAlign);
b148bd ¤   pgpLeaksIgnoreItem(pgpLeaksFindItem(memory));
08efe6 }
56af5a
8daf5a
77314a void
5a71f8 pgpLeaksForgetItem(
04c6d5 ¤   LeakItem *¤ ¤   ¤   item,
c6620b ¤   LeakDeallocType *¤  deallocType)
87bb36 {
--9828 001226b7401401000c7 Page 6 of pgpLeaks.c
7d5e68 ¤   pgpa((
1104dc ¤   ¤   pgpaLeakItemValid(item),
711f5d ¤   ¤   pgpaLeakDeallocTypeValid(deallocType),
ffbe79 ¤   ¤   pgpaMsg("Invalid parameters")));
a75e68 ¤   pgpa((
98e27f ¤   ¤   pgpaAssert(item->allocType->deallocType == deallocType),
d23124 ¤   ¤   pgpaFmtMsg((pgpaFmtPrefix,
ecaacf ¤   ¤   ¤   "Block deallocated incorrectly with %s instead of %s\n"
19564d ¤   ¤   ¤   " ·from %s in %s line %ld",
038580 ¤   ¤   ¤   deallocType->name, item->allocType->deallocType->name,
7d4950 ¤   ¤   ¤   item->allocType->name, item->fileName, item->lineNumber))));
c99839 ¤   pgpLeaksUnlinkItem(item);
f4efe6 }
a6af5a
c2b3c3 ¤   LeakItem *
ed0630 pgpLeaksFindItem(
bda67f ¤   void const *¤   memory)
d7bb36 {
bd3195 ¤   LeaksSession const *¤   session;
f8ca50 ¤   LeakItem ·*¤¤   ¤   ¤   item;
dfaf5a
f85e68 ¤   pgpa((
512ca4 ¤   ¤   pgpaAddrValid(memory, VoidAlign),
f4be79 ¤   ¤   pgpaMsg("Invalid parameters")));
7e10c6 ¤   for (session = sCurrentSession; session != NULL;
a9438a ¤   ¤   ¤   session = session->prevSession)
e9c7a1 ¤   {
5498c8 ¤   ¤   pgpa(pgpaLeaksSessionValid(session));
c91f5d ¤   ¤   for (item = session->dummyItem.next; item != &session->dummyItem;
780e10 ¤   ¤   ¤   ¤   item = item->next)
8f5b34 ¤   ¤   {
faaa57 ¤   ¤   ¤   pgpa(pgpaLeakItemValid(item));
8fb430 ¤   ¤   ¤   if (item->memory == memory)
6b26ed ¤   ¤   ¤   ¤   return item;
000fe4 ¤   ¤   }
e29371 ¤   }
173f59 ¤   return NULL;
7aefe6 }
e5af5a
f56d52 ¤   void
a0e496 pgpLeaksNotifyItemMoved(
60715f ¤   LeakItem const *¤   oldItem,
bda94f ¤   LeakItem *¤ ¤   ¤   newItem)
2bbb36 {
e89f03 ¤   /* Assumes that the assertion won't check the links */
d75e68 ¤   pgpa((
dcf663 ¤   ¤   pgpaLeakItemValid(newItem),
b7be79 ¤   ¤   pgpaMsg("Invalid parameters")));
1b67c5 ¤
2d2143 ¤   if (newItem->prev == oldItem)
7ac7a1 ¤   {
c17c94 ¤   ¤   /* This is the only item in the list */
f7eb32 ¤   ¤   newItem->prev = newItem->next = newItem;
219371 ¤   }
8a0e24 ¤   else
72c7a1 ¤   {
56e027 ¤   ¤   newItem->prev->next = newItem;
a6a1be ¤   ¤   newItem->next->prev = newItem;
809371 ¤   }
77efe6 }
f9af5a
300727 #endif /* ] USE_PGP_LEAKS */
6aaf5a
f67e4d /*__Editor_settings____
9baf5a
154126 ¤   Local Variables:
9e7b17 ¤   tab-width: 4
5b0e6c ¤   End:
b75f8c ¤   vi: ts=4 sw=4
f69e9b ¤   vim: si
22d062 _____________________*/
--2274 000ad03fbc1401000c8 Page 1 of pgpLeaks.h
a70335 /*____________________________________________________________________________
a5ef92 ¤   pgpLeaks.h
6667c5 ¤
89f254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
c34b0f ¤   All rights reserved.
7b67c5 ¤
3952af ¤   Leak tracking module for memory allocation routines
55af5a
565775 ¤   $Id: pgpLeaks.h,v 1.16.14.1 1998/11/12 03:17:54 heller Exp $
8ff7f7 ____________________________________________________________________________*/
3c2dab #ifndef Included_pgpLeaks_h¤/* [ */
86954a #define Included_pgpLeaks_h
57af5a
15675a #include "pgpTypes.h"
eba146 #include "pgpDebug.h"
5eaf5a
21e021 #ifndef USE_PGP_LEAKS
becb50 #define USE_PGP_LEAKS¤  ¤   PGP_DEBUG
a57454 #endif
23af5a
fe99c6 PGP_BEGIN_C_DECLARATIONS
1aaf5a
f63f02 #if USE_PGP_LEAKS¤  /* [ */
6aaf5a
a638e5 /*
e166a9 ·* WARNING: The leaks library is currently not thread-safe
de495d ·*/
22af5a
8f3e33 #define kLeakDeallocTypeMagic¤  0xD073A915
10ddd0 #define kLeakAllocTypeMagic¤¤   0xE19C834B
9ae782 #ifndef kLeakItemMagic
ff6b07 #define kLeakItemMagic¤ ¤   ¤   0xB74D951F
e37454 #endif
51af5a
6234d6 typedef struct LeakDeallocType_ const¤  LeakDeallocType;
7df9db struct LeakDeallocType_
c8bb36 {
49b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
12a9a2 ¤   char const *¤   ¤   name;
5882f7 };
f6af5a
5e6dfb typedef struct LeakAllocType_ const¤LeakAllocType;
121a88 struct LeakAllocType_
bebb36 {
5db5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
96a9a2 ¤   char const *¤   ¤   name;
16c42a ¤   LeakDeallocType *¤  deallocType;
3882f7 };
e1af5a
cb20a3 #define LeakStructName(name)¤   name ## __struct
90af5a
1b9083 #define DECLARE_LEAKDEALLOCSTRUCT(varName, nameStr)¤¤   ¤   ¤   \
6e3091 ¤   ¤   LeakDeallocType LeakStructName(varName) = {¤¤   ¤   ¤   \
b21d8a ¤   ¤   ¤   ¤   ¤   ¤   ¤   kLeakDeallocTypeMagic,¤ ¤   ¤   ¤   \
72638e ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameStr }
a8af5a
28dfaa #define DECLARE_LEAKDEALLOCTYPE(varName, nameStr)¤  ¤   ¤   ¤   \
2b1084 ¤   ¤   DECLARE_LEAKDEALLOCSTRUCT(¤ varName, nameStr),¤ ¤   ¤   \
dfd850 ¤   ¤   ¤   ¤   ¤   ¤   *varName = &LeakStructName(varName)
6eaf5a
ba2b60 #define DECLARE_LEAKALLOCTYPE(varName, nameStr, deallocType)¤   \
60f505 ¤   ¤   LeakAllocType LeakStructName(varName) = {¤  ¤   ¤   ¤   \
bbf2ba ¤   ¤   ¤   ¤   ¤   ¤   ¤   kLeakAllocTypeMagic,¤   ¤   ¤   ¤   \
948610 ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameStr,¤   ¤   ¤   ¤   ¤   ¤   ¤   \
e10e7c ¤   ¤   ¤   ¤   ¤   ¤   ¤   &LeakStructName(deallocType) },¤¤   \
8cd850 ¤   ¤   ¤   ¤   ¤   ¤   *varName = &LeakStructName(varName)
6daf5a
0738e5 /*
b159e1 ·* The LeakItems form a circularly-linked list.
ab8f11 ·* Each session has its own list, each with its own dummy element.
d9495d ·*/
ad84dd typedef struct LeakItem_¤   ¤   LeakItem;
--e216 0003edc988e401000c8 Page 2 of pgpLeaks.h
5cd7b2 struct LeakItem_
4ebb36 {
8a9d0d ¤   PGPUInt32¤  ¤   magic;
b92a3d ¤   LeakAllocType *¤allocType;
9e3d81 ¤   PGPUInt32¤  ¤   size;
25a1eb ¤   PGPBoolean¤ ¤   ignore;
01b167 ¤   PGPBoolean¤ ¤   inSessionList;
93c30e ¤   PGPBoolean¤ ¤   pad1;
332c6a ¤   PGPBoolean¤ ¤   pad2;
1f6503 ¤   LeakItem *¤ ¤   prev;
e7671b ¤   LeakItem *¤ ¤   next;
a73a63 ¤   char const *¤   fileName;
2bda39 ¤   long¤   ¤   ¤   lineNumber;
a7005e ¤   void const *¤   memory;
fd3d8d ¤   PGPUInt32¤  ¤   allocationNumber;
d082f7 };
85af5a
d5c4ad #define pgpaLeakDeallocTypeValid(type)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
5bf6b6 ¤   ¤   pgpaFailIf((type) == NULL || (type)->magic != kLeakDeallocTypeMagic,\
32f2e2 ¤   ¤   ¤   ¤   ¤   (pgpaFmtPrefix, "Invalid LeakDeallocType magic"))
eac962 #define pgpaLeakAllocTypeValid(type)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f3cefb ¤   ¤   pgpaFailIf((type) == NULL || (type)->magic != kLeakAllocTypeMagic,¤ \
27c6a0 ¤   ¤   ¤   ¤   ¤   (pgpaFmtPrefix, "Invalid LeakAllocType magic"))
ffe89f #define pgpaLeakItemValid(item)¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
713291 ¤   ¤   pgpaFailIf((item) == NULL || (item)->magic != kLeakItemMagic,¤  ¤   \
7be9d4 ¤   ¤   ¤   ¤   ¤   (pgpaFmtPrefix, "Invalid LeakInfo magic"))
a3af5a
cbaf5a
06697f void ¤  pgpLeaksBeginSession(char const *sessionName);
ef06b0 void ¤  pgpLeaksEndSession(void);
eaaf5a
16a312 void ¤  pgpLeaksRememberItem(LeakItem *item, LeakAllocType *type,
9f1ecd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   void const *memory, PGPUInt32 size,
f208e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *fileName,
432321 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   long lineNumber);
2c36d7 void ¤  pgpLeaksIgnoreItem(LeakItem *item);
6e775a void ¤  pgpLeaksIgnoreMemory( const void * memory);
6adee2 void ¤  pgpLeaksForgetItem(LeakItem *item, LeakDeallocType *type);
95af5a
20c9de LeakItem ·*¤pgpLeaksFindItem(void const *memory);
c9af5a
ed38e5 /*
fe155a ·* Call this whenever a LeakItem moves in memory. ·<oldItem> will not be
ab3ac8 ·* referenced and need not contain any valid data. ·It need only indicate
932ea3 ·* where the item used to be in memory.
80495d ·*/
e9c65f void ¤  pgpLeaksNotifyItemMoved(LeakItem const *oldItem,
210f1b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   LeakItem *newItem);
08af5a
ff2a43 void ¤  pgpLeaksSuspend(void);
32f400 void ¤  pgpLeaksResume(void);
58af5a
34e38a #else /* ] USE_PGP_LEAKS [ */
83af5a
0348a6 #define pgpLeaksBeginSession(name)
1d720a #define pgpLeaksEndSession()
3415cb #define pgpLeaksRememberItem(item, type, memory, fileName, lineNumber)
ede441 #define pgpLeaksIgnoreItem(item)
9fad97 #define pgpLeaksIgnoreMemory(memory)
3240f3 #define pgpLeaksForgetItem(item, type)
9ca908 #define pgpLeaksSuspend()
6253c5 #define pgpLeaksResume()
4daf5a
7b0727 #endif /* ] USE_PGP_LEAKS */
ddaf5a
7a1254 PGP_END_C_DECLARATIONS
24af5a
02af5a
ac2283 #endif /* ] Included_pgpLeaks_h */
5eaf5a
b27e4d /*__Editor_settings____
3eaf5a
--971b 00150c9616f401000c8 Page 3 of pgpLeaks.h
734126 ¤   Local Variables:
567b17 ¤   tab-width: 4
430e6c ¤   End:
895f8c ¤   vi: ts=4 sw=4
ab9e9b ¤   vim: si
50d062 _____________________*/
--7367 000c0aca543401000c9 Page 1 of pgpMem.c
a70335 /*____________________________________________________________________________
7de171 ¤   pgpMem.c
8667c5 ¤
3af254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
594b0f ¤   All rights reserved.
5567c5 ¤
cc360b ¤   pgpMemAlloc and friends with debugging support
34af5a
345675 ¤   $Id: pgpMem.c,v 1.26.28.1 1998/11/12 03:17:55 heller Exp $
7cf7f7 ____________________________________________________________________________*/
ede610 #include "pgpPFLConfig.h"
4caf5a
68bea3 #include <stdlib.h>
00a7a0 #include <limits.h>
55324c #include <string.h>
9eaf5a
65675a #include "pgpTypes.h"
f30d08 #include "pgpMem.h"
f32b62 #include "pgpPFLErrors.h"
41a146 #include "pgpDebug.h"
0994a0 #include "pgpLeaks.h"
6baf5a
3eaf5a
f817d1 #ifdef DEBUG_FIND_LEAKS
fe3143 #error use PGP_DEBUG_FIND_LEAKS instead of DEBUG_FIND_LEAKS
287454 #endif
80af5a
ec0f91 #ifndef PGP_DEBUG_FIND_LEAKS
b73637 #error you must #define PGP_DEBUG_FIND_LEAKS as 0 or 1
e07454 #endif
92af5a
c3af5a
07af5a
fc340c /* Fills allocated/deallocated memory with 0xDD's */
7829f8 #ifndef DEBUG_FILL_MEM
582e6d #define DEBUG_FILL_MEM¤ ¤   ¤   PGP_DEBUG
9d7454 #endif
baaf5a
e9e878 /* Puts a ulong-sized magic number before the start of each block */
dd9e81 #ifndef DEBUG_MEM_HEAD_MAGIC
9f0f72 #define DEBUG_MEM_HEAD_MAGIC¤   PGP_DEBUG
c87454 #endif
47af5a
2c3993 /* Puts magic bytes after the end of each block */
44efd1 #ifndef DEBUG_MEM_TAIL_MAGIC
265c98 #if PGP_DEBUG
82079d #define DEBUG_MEM_TAIL_MAGIC¤   4
17db21 #else
cd60fd #define DEBUG_MEM_TAIL_MAGIC¤   0
e37454 #endif
8a7454 #endif
4faf5a
8dc7c6 /* Makes pgpMemRealloc always move a growing block */
610af8 #ifndef DEBUG_ALWAYS_MOVE
4611c7 #define DEBUG_ALWAYS_MOVE¤  ¤   PGP_DEBUG
657454 #endif
bbaf5a
a5c2ba #if DEBUG_FILL_MEM
6029b4 #define MaybeFillMem(p, size)¤  pgpFillMemory((void *)(p), (size), 0xDD)
8ddb21 #else
45761d #define MaybeFillMem(p, size)
217454 #endif
c1af5a
82693e /* This is a useful macro to find the minimum of two values */
49007d #ifndef min
c6f8ab #define min(x,y) (((x)<(y)) ? (x) : (y))
7c7454 #endif
10af5a
b27e0a #define kMemHeaderMagic¤¤   0xD837C51E
6eaf5a
a5aba2 typedef struct MemHeader
c0bb36 {
--6f4c 00057afe420401000c9 Page 2 of pgpMem.c
fa691c #if PGP_DEBUG_FIND_LEAKS
7ab050 ¤   LeakItem¤   leakItem;¤  /* Information for the leaks package */
c37454 #endif
451626 ¤   size_t¤ ¤   size;¤  ¤   /* Size of the user area of the block */
23f80c #if DEBUG_MEM_HEAD_MAGIC
94355e ¤   PGPUInt32¤  magic;¤ ¤   /* Trailing magic number */
e87454 #endif
95b2a7 } MemHeader;
17af5a
b538bd #define UserPtrToMemHeader(userPtr)¤¤   \
025d29 ¤   ¤   ((MemHeader *)((char *)(userPtr) - sizeof(MemHeader)))
258874 #define MemHeaderToUserPtr(hdrPtr)¤ ¤   \
2bce42 ¤   ¤   ((void *)((char *)(hdrPtr) + sizeof(MemHeader)))
3b7c22 #define FullBlockSize(userSize)¤¤   ¤   \
1b265e ¤   ¤   (sizeof(MemHeader) + (userSize) + DEBUG_MEM_TAIL_MAGIC)
8eaf5a
9438e5 /*
ab431d ·* Defines the sequence of tail magic bytes. ·We want every byte to be
06e58a ·* odd to catch memory references, but also each should be distinct.
17495d ·*/
72e50b #define TailMagicByte(i)¤   ¤   ¤   ¤   \
785ab4 ¤   ¤   ((char)(34 * (i) + 0x3D))
d1af5a
cf691c #if PGP_DEBUG_FIND_LEAKS
fcf989 static DECLARE_LEAKDEALLOCTYPE(kPGPFree, "pgpFree");
4c05a6 static DECLARE_LEAKALLOCTYPE(kPGPAlloc, "pgpAlloc", kPGPFree);
a87454 #endif
2baf5a
eb6438 /*_____________________________________________________________________________
64405f ··Platform specific routines
7d7cb9 _____________________________________________________________________________*/
8aaf5a
0838e5 /*
0c3fa1 ·* These platform-specific routines can be very simple. ·They needn't
a6a1a1 ·* deal with NULL pointers or perform any assertion checking. ·They will
4713f8 ·* never be passed a zero size, because a MemHeader will always be included.
22bddc ·* pgpPlatformRealloc should never move the block itself; instead it should
f1c392 ·* just return kPGPError_OutOfMemory, causing the platform-independent routine
fe26ff ·* to allocate a new block and move the memory itself.
d3495d ·*/
1a53b9 static void *pgpPlatformAlloc(size_t size);
26757d static PGPError pgpPlatformRealloc(void **ptrRef, size_t oldSize,
21aa01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   size_t newSize);
7573d7 static void pgpPlatformFree(void *ptr);
58af5a
369a50 #if PGP_MACINTOSH¤  ¤   /* [ */
0caf5a
136b82 #include <Memory.h>
25af5a
6138e5 /*
304cac ·* Macintosh specific routines
dd495d ·*/
9ad83c ·
5a6d52 ¤   void
01b1a6 pgpCopyMemory(
8b2bb3 ¤   void const *¤   src,
46e18f ¤   void *¤ ¤   ¤   dest,
a14758 ¤   size_t¤ ¤   ¤   size)
48bb36 {
a95e68 ¤   pgpa((
90c826 ¤   ¤   pgpaAddrValid(src, VoidAlign),
8d745e ¤   ¤   pgpaAddrValid(dest, VoidAlign),
e498ec ¤   ¤   pgpaAssert(size >= 0)));
8467c5 ¤
3fce14 ¤   BlockMoveData(src, dest, (Size)size);
c6efe6 }
3baf5a
cc062a ¤   static void *
28be9b pgpPlatformAlloc(
47708b ¤   size_t¤ ¤   size)
d4bb36 {
575e68 ¤   pgpa((
--d7c2 000ae3ecdb9401000c9 Page 3 of pgpMem.c
bb0fc0 ¤   ¤   pgpaAssert((Size)size >= 0),
c91d31 ¤   ¤   pgpaMsg((pgpaFmtPrefix,
e5d746 ¤   ¤   ¤   ¤   "pgpPlatformAlloc: size negative or too large"))));
0e67c5 ¤
6add3e #undef NewPtr¤  /* We don't want DebugTraps_NewPtr tracking this */
959c4b ¤   return (void *)NewPtr((Size)size);
f0efe6 }
f0af5a
5166dd ¤   static PGPError
4cf632 pgpPlatformRealloc(
191c47 ¤   void **¤¤   ptrRef,
0d93c8 ¤   size_t¤ ¤   oldSize,
901129 ¤   size_t¤ ¤   newSize)
13bb36 {
d3a633 ¤   Ptr¤¤   ¤   ptr = (Ptr)*ptrRef;
e70c75 ¤   size_t¤ ¤   actualSize;
b967c5 ¤
e4d8af ¤   /*
b1db53 ¤   ·* We need to perform this additional assertion, because the Mac uses a
757af0 ¤   ·* signed long instead of an unsigned long (size_t) for memory allocation
43a4e3 ¤   ·*/
1c5e68 ¤   pgpa((
f92b00 ¤   ¤   pgpaAssert((Size)newSize >= 0),
171d31 ¤   ¤   pgpaMsg((pgpaFmtPrefix,
d9a8af ¤   ¤   ¤   ¤   "pgpPlatformRealloc: size negative or too large"))));
9d67c5 ¤
f1f2e1 ¤   (void)oldSize;¤ ¤   /* Avoid warning */
1c7748 ¤   SetPtrSize(ptr, (Size)newSize);
ae6db2 ¤   actualSize = GetPtrSize(ptr);
2de286 ¤   if (actualSize != newSize)
f44030 ¤   ¤   return kPGPError_OutOfMemory;
420e24 ¤   else
9eb840 ¤   ¤   return kPGPError_NoErr;
54efe6 }
03af5a
6033c8 ¤   static void
efabef pgpPlatformFree(
63e5b5 ¤   void *¤ ¤   ptr)
d1bb36 {
dad511 #undef DisposePtr¤  /* We don't want DebugTraps_DisposePtr tracking this */
c772e6 ¤   DisposePtr((char *)ptr);
08efe6 }
0eaf5a
0cc69d #else¤  /* ] PGP_MACINTOSH [ */
aaaf5a
1738e5 /*
06b147 ·* ANSI-specific routines (for non-Macs)
a7495d ·*/
6baf5a
076d52 ¤   void
74b1a6 pgpCopyMemory(
d92bb3 ¤   void const *¤   src,
a1e18f ¤   void *¤ ¤   ¤   dest,
3e4758 ¤   size_t¤ ¤   ¤   size)
5dbb36 {
e75e68 ¤   pgpa((
e3c826 ¤   ¤   pgpaAddrValid(src, VoidAlign),
99031c ¤   ¤   pgpaAddrValid(dest, VoidAlign)));
a267c5 ¤
364e3b ¤   memmove(dest, src, size);
71efe6 }
d7af5a
9e062a ¤   static void *
dfbe9b pgpPlatformAlloc(
f1708b ¤   size_t¤ ¤   size)
79bb36 {
f7c6eb ¤   return (void *)malloc(size);
6eefe6 }
95af5a
3d66dd ¤   static PGPError
a3f632 pgpPlatformRealloc(
ae4ae8 ¤   void **¤¤   pp,
--06d7 000b45f68aa401000c9 Page 4 of pgpMem.c
e293c8 ¤   size_t¤ ¤   oldSize,
ec1129 ¤   size_t¤ ¤   newSize)
44bb36 {
f866e8 ¤   void *¤ ¤   oldP = *pp;
755464 ¤   void *¤ ¤   newP;
6167c5 ¤
571f36 ¤   if (newSize > oldSize)
b54030 ¤   ¤   return kPGPError_OutOfMemory;
0da8b5 ¤   newP = realloc(oldP, newSize);
030664 ¤   if (newP == NULL)
e74030 ¤   ¤   return kPGPError_OutOfMemory;
f667c5 ¤
10c1cd ¤   *pp = newP;
0a151e ¤   return kPGPError_NoErr;
0fefe6 }
dcaf5a
f733c8 ¤   static void
2babef pgpPlatformFree(
a92e27 ¤   void *¤ ¤   p)
a2bb36 {
eff3fb ¤   free(p);
47efe6 }
11af5a
ff3167 #endif¤ /* ] */
0aaf5a
156438 /*_____________________________________________________________________________
238b37 ··Platform independent routines
037cb9 _____________________________________________________________________________*/
aeaf5a
95e85e #if PGP_DEBUG¤  /* [ */
51af5a
6916ea ¤   PGPBoolean
a0fc84 pgpaInternalMemBlockValid(
6f3c2c ¤   pgpaCallPrefixDef,
3d131a ¤   const void *¤   ¤   ¤   userPtr)
6fbb36 {
9b48ab ¤   MemHeader *¤¤   header = UserPtrToMemHeader(userPtr);
1b67c5 ¤
c21603 ¤   pgpaAssert(userPtr != NULL);
a22ddb ¤   pgpaAddrValid(header, MemHeader);
79af5a
a8691c #if PGP_DEBUG_FIND_LEAKS
5ca68d ¤   pgpaLeakItemValid(&header->leakItem);
6a7454 #endif
59af5a
81f80c #if DEBUG_MEM_HEAD_MAGIC
b20d7d ¤   pgpaAssert(header->magic == kMemHeaderMagic);
837454 #endif
c0af5a
d5895c #if DEBUG_MEM_TAIL_MAGIC
ccc7a1 ¤   {
669066 ¤   ¤   char *¤ ¤   tailMagic = (char *)userPtr + header->size;
064cc5 ¤   ¤   int¤¤   ¤   i;
0f1b52 ¤   ¤
8ea55e ¤   ¤   for (i = 0; !pgpaFailed && i < DEBUG_MEM_TAIL_MAGIC; i++)
2fce74 ¤   ¤   ¤   pgpaAssert(tailMagic[i] == TailMagicByte(i));
879371 ¤   }
327454 #endif
43af5a
e9750f ¤   return pgpaFailed;
14efe6 }
76af5a
7a33c8 ¤   static void
c3e209 pgpMemSetTailMagic(
52cb0b ¤   MemHeader *¤header)
adbb36 {
7c895c #if DEBUG_MEM_TAIL_MAGIC
42bb45 ¤   char *¤ ¤   tailMagic = (char *)header + sizeof(MemHeader) + header->size;
c2772c ¤   int¤¤   ¤   i;
ea67c5 ¤
6e35e2 ¤   for (i = 0; i < DEBUG_MEM_TAIL_MAGIC; i++)
b42c72 ¤   ¤   tailMagic[i] = TailMagicByte(i);
--a3c0 0004a191012401000c9 Page 5 of pgpMem.c
a07454 #endif
96efe6 }
18af5a
33ab79 #endif¤ /* ] PGP_DEBUG */
9aaf5a
c759fc ¤   void *
f96271 PGP_INTERNAL_ALLOC(
636786 ¤   size_t¤ ¤   ¤   size
e5c7d7 ¤   PGPALLOC_CONTEXT_PARAMS_DEF)¤   /* fileName and lineNumber */
c6bb36 {
b76305 ¤   MemHeader *¤¤   header;
4be9c0 ¤   void *¤ ¤   ¤   userPtr;
3b67c5 ¤
91af5a
6981b8 ¤   header = (MemHeader *)pgpPlatformAlloc(FullBlockSize(size));
afdbfb ¤   if (header == NULL)
4a7ed2 ¤   ¤   return NULL;
ca67c5 ¤
215091 ¤   MaybeFillMem(header, FullBlockSize(size));
59bf28 ¤   userPtr = MemHeaderToUserPtr(header);
9e67c5 ¤
1a691c #if PGP_DEBUG_FIND_LEAKS
fc384a ¤   pgpLeaksRememberItem(&header->leakItem, kPGPAlloc,
450861 ¤   ¤   ¤   ¤   ¤   ¤   userPtr, size, fileName, lineNumber);
237454 #endif
67af5a
ddcccc ¤   header->size = size;
5167c5 ¤
b1f80c #if DEBUG_MEM_HEAD_MAGIC
4031f5 ¤   header->magic = kMemHeaderMagic;
b77454 #endif
74af5a
30895c #if DEBUG_MEM_TAIL_MAGIC
cff052 ¤   pgpMemSetTailMagic(header);
187454 #endif
0f2616 ¤   return userPtr;
27efe6 }
1faf5a
c4c744 ¤   PGPError
50d79b pgpRealloc(
893d61 ¤   void **¤¤   ¤   userPtrRef,
f88ae8 ¤   size_t¤ ¤   ¤   newSize)
9cbb36 {
45d090 ¤   size_t¤ ¤   ¤   oldSize;
09d90b ¤   void *¤ ¤   ¤   oldUserPtr = *userPtrRef;
6fe0d2 ¤   MemHeader *¤¤   oldHeader = UserPtrToMemHeader(oldUserPtr);
627060 ¤   void *¤ ¤   ¤   newUserPtr;
d7e790 ¤   MemHeader *¤¤   newHeader;
d25caa ¤   PGPError¤   ¤   result;
8667c5 ¤
ef9a1a ¤   pgpa(pgpaMemBlockValid(oldUserPtr));
34e0a7 ¤   oldSize = oldHeader->size;
9a30ff ¤   if (newSize == oldSize)
d3b840 ¤   ¤   return kPGPError_NoErr;
bb67c5 ¤
22c2ba #if DEBUG_FILL_MEM
401c1b ¤   /* If we're shrinking the block, wipe the tail end before resizing */
0cb414 ¤   if (newSize < oldSize)
d1b7eb ¤   ¤   MaybeFillMem((char *)oldUserPtr + newSize, oldSize - newSize);
9e7454 #endif
c467c5 ¤
a17564 ¤   newHeader = oldHeader;
7a38f9 ¤   /* Always move growing blocks if DEBUG_ALWAYS_MOVE is set */
679c87 ¤   if (DEBUG_ALWAYS_MOVE && newSize > oldSize)
255e00 ¤   ¤   result = kPGPError_OutOfMemory;
d00e24 ¤   else
9d9fae ¤   ¤   result = pgpPlatformRealloc((void **)&newHeader,
5f90b4 ¤   ¤   ¤   ¤   ¤   ¤   FullBlockSize(oldSize), FullBlockSize(newSize));
b667c5 ¤
6b7b7c ¤   if (result == kPGPError_OutOfMemory)
87c7a1 ¤   {
4a0d04 ¤   ¤   /* pgpPlatformRealloc failed, try allocating a new block and moving */
--dbca 00086915ba9401000c9 Page 6 of pgpMem.c
573fd2 ¤   ¤   pgpa((
261401 ¤   ¤   ¤   pgpaAssert(newSize > oldSize),
6dcdd2 ¤   ¤   ¤   pgpaMsg("pgpPlatformRealloc failed to shrink block")));
e1a10e ¤   ¤   newHeader = (MemHeader *)pgpPlatformAlloc(FullBlockSize(newSize));
5387ae ¤   ¤   if (newHeader == NULL)
957cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
ad879d ¤   ¤   pgpCopyMemory((void *)oldHeader, (void *)newHeader,
7ab3b9 ¤   ¤   ¤   ¤   ¤   sizeof(MemHeader) + oldSize);
3ed2d3 ¤   ¤   MaybeFillMem(oldHeader, FullBlockSize(oldSize));
781f8d ¤   ¤   pgpPlatformFree(oldHeader);
ac9371 ¤   }
90b5c4 ¤   else if (result != kPGPError_NoErr)
7f669a ¤   ¤   return result;
6967c5 ¤
479b2b ¤   newUserPtr = MemHeaderToUserPtr(newHeader);
6067c5 ¤
dec2ba #if DEBUG_FILL_MEM
8dfa01 ¤   /* If we're growing the block, wipe the newly-allocated portion */
821f36 ¤   if (newSize > oldSize)
cbef2a ¤   ¤   MaybeFillMem((char *)newUserPtr + oldSize, newSize - oldSize);
617454 #endif
6167c5 ¤
706b14 ¤   if (newHeader != oldHeader)
ffc7a1 ¤   {
63691c #if PGP_DEBUG_FIND_LEAKS
019348 ¤   ¤   pgpLeaksNotifyItemMoved(&oldHeader->leakItem, &newHeader->leakItem);
fb7454 #endif
f9d77e ¤   ¤   *userPtrRef = newUserPtr;
c19371 ¤   }
3514ee ¤   newHeader->size = newSize;
6d67c5 ¤
17895c #if DEBUG_MEM_TAIL_MAGIC
c42393 ¤   pgpMemSetTailMagic(newHeader);
8e7454 #endif
0f151e ¤   return kPGPError_NoErr;
ceefe6 }
a4af5a
a56d52 ¤   void
df2037 pgpFree(
884fe1 ¤   void *¤ ¤   ¤   userPtr)
bcbb36 {
0848ab ¤   MemHeader *¤¤   header = UserPtrToMemHeader(userPtr);
de67c5 ¤
9df49a ¤   pgpa(pgpaMemBlockValid(userPtr));
68691c #if PGP_DEBUG_FIND_LEAKS
fb2bcf ¤   pgpLeaksForgetItem(&header->leakItem, kPGPFree);
027454 #endif
befdb8 ¤   MaybeFillMem(header, FullBlockSize(header->size));
f2ea3c ¤   pgpPlatformFree(header);
12efe6 }
ebaf5a
ea6438 /*_____________________________________________________________________________
1089c0 ··Backward-compatible wrapper routines,
8b8a76 ··which treat NULL like a 0-sized block.
287cb9 _____________________________________________________________________________*/
f7af5a
6959fc ¤   void *
8f028c PGP_INTERNAL_MEMALLOC(
8d6786 ¤   size_t¤ ¤   ¤   size
fac7d7 ¤   PGPALLOC_CONTEXT_PARAMS_DEF)¤   /* fileName and lineNumber */
7abb36 {
f26c53 ¤   if (size == 0)
487ed2 ¤   ¤   return NULL;
a30e24 ¤   else
9a1e2e ¤   ¤   return PGP_INTERNAL_ALLOC(size ·PGPALLOC_CONTEXT_PASS_PARAMS);
9aefe6 }
faaf5a
6259fc ¤   void *
18dd24 PGP_INTERNAL_MEMREALLOC(
843159 ¤   void *¤ ¤   ¤   userPtr,
0e83fd ¤   size_t¤ ¤   ¤   newSize
86c7d7 ¤   PGPALLOC_CONTEXT_PARAMS_DEF)¤   /* fileName and lineNumber */
--7e70 000efd33904401000c9 Page 7 of pgpMem.c
2cbb36 {
e1e4b2 ¤   if (userPtr == NULL)
dbea17 ¤   ¤   return PGP_INTERNAL_MEMALLOC(newSize ·PGPALLOC_CONTEXT_PASS_PARAMS);
7a41af ¤   else if (newSize == 0)
0fc7a1 ¤   {
1770b1 ¤   ¤   if ( IsntNull( userPtr ) )
54821e ¤   ¤   ¤   pgpFree(userPtr);
4a7ed2 ¤   ¤   return NULL;
b29371 ¤   }
d6623a ¤   else if (pgpRealloc(&userPtr, newSize) != kPGPError_NoErr)
647ed2 ¤   ¤   return NULL;
450e24 ¤   else
155ce2 ¤   ¤   return userPtr;
1cefe6 }
3baf5a
09b177 #if 0
dc6d52 ¤   void
917c5c pgpMemFree(
f34fe1 ¤   void *¤ ¤   ¤   userPtr)
eebb36 {
25237a ¤   if (userPtr)
cf0b4a ¤   ¤   pgpFree(userPtr);
cbefe6 }
e37454 #endif
69af5a
1b6d52 ¤   void
51948f pgpCopyPattern(
e43dde ¤   const void *¤   pattern,
3e4032 ¤   size_t¤ ¤   ¤   patternLength,
f32903 ¤   void *¤ ¤   ¤   buffer,
0db2bf ¤   size_t¤ ¤   ¤   bufferLength)
dbbb36 {
8c4627 ¤   size_t¤ count;
6887d3 ¤   size_t¤ remaining¤  = bufferLength;
dcad89 ¤   size_t¤ doneSoFar¤  = 0;
4e67c5 ¤
b35e68 ¤   pgpa((
23d896 ¤   ¤   pgpaAddrValid(pattern, VoidAlign),
d0f5eb ¤   ¤   pgpaAssert(patternLength > 0),
5d204e ¤   ¤   pgpaAddrValid(buffer, VoidAlign)));
d367c5 ¤
882abf ¤   /* copy the pattern once first */
b10e32 ¤   count = min(patternLength, bufferLength);
ec239a ¤   pgpCopyMemory(pattern, buffer, count);
df575a ¤   remaining¤  -= count;
7b2ae3 ¤   doneSoFar¤  += count;
7d67c5 ¤
1a0589 ¤   while ( remaining != 0 )
fec7a1 ¤   {
c81b17 ¤   ¤   /*
164074 ¤   ¤   ** replicate the pattern we have produced so far
2756af ¤   ¤   ** because the original pattern might be small (say 1 PGPByte)
8f5c12 ¤   ¤   */
7a1b52 ¤   ¤
54ad52 ¤   ¤   count = min(doneSoFar, remaining);
66c230 ¤   ¤   pgpCopyMemory(buffer, ((uchar *)buffer) + doneSoFar, count);
bf1b52 ¤   ¤
f0de0e ¤   ¤   remaining¤  -= count;
9ca3b7 ¤   ¤   doneSoFar¤  += count;
1b9371 ¤   }
deefe6 }
fbaf5a
bac21c #if PGP_MACINTOSH¤  /* [ */
93af5a
5f0335 /*____________________________________________________________________________
a65860 ¤   Fill memory with a PGPByte pattern.
7a9079 ¤   Obviously, this routine can be optimized.
f46c11 ··____________________________________________________________________________*/
f667c5 ¤
df28dd ¤   static inline void
f9cb2e FillBytes(
ef5bc6 ¤   void *¤ buffer,
--3f13 0000f9bb701401000c9 Page 8 of pgpMem.c
9d87d1 ¤   size_t¤ length,
544daf ¤   uchar¤  fillChar)
6abb36 {
3cce0e ¤   char *¤ cur = (char *)buffer;
d37d75 ¤   UInt32¤ remaining = length;
dd67c5 ¤
5fbd98 ¤   while (remaining-- > 0)
980c64 ¤   ¤   *cur++ = fillChar;
6fefe6 }
bcaf5a
660335 /*____________________________________________________________________________
843571 ¤   Fast fill routine. ·Highly efficient for fills of as little as 16 bytes.
5c67c5 ¤
ee26d6 ¤   Testing on PPC 604 shows that filling more than 4 bytes (one long) per loop
2fce5c ¤   iteration does not produce any measurable speed improvement. ·That fact,
0dc03f ¤   coupled with the fact that using PGPByte fills, even on small chunks, is
4632e8 ¤   slow, means that unrolling it substantially is not a win.
3b6c11 ··____________________________________________________________________________*/
466d52 ¤   void
d14299 pgpFillMemory(
e12903 ¤   void *¤ ¤   ¤   buffer,
af5eb2 ¤   const size_t¤   length,
f45673 ¤   const uchar¤¤   fillChar)
5ebb36 {
f1a65b ¤   const UInt32¤   kAlignSize¤ ¤   ¤   = sizeof(UInt32);
63bfc8 ¤   const UInt32¤   kUnrollBytesPerIter¤= 8;¤   /* must be power of 2 */
2aa679 ¤   uchar *¤¤   ¤   cur¤¤   ¤   ¤   ¤   = (uchar *)buffer;
f2f1b8 ¤   UInt32¤ ¤   ¤   remaining¤  ¤   ¤   = length;
6b67c5 ¤
2d5e68 ¤   pgpa((
6d623c ¤   ¤   pgpaAddrValid(buffer, VoidAlign),
a58b7f ¤   ¤   pgpaAssert(length >= 0),
ca9d88 ¤   ¤   pgpaAssert( length < 128 *1024UL * 1024UL )));
f067c5 ¤
76b361 ¤   if ( length >= kUnrollBytesPerIter )
22c7a1 ¤   {
2df66f ¤   ¤   UInt32¤ ¤   ¤   fillPattern;
6b1a09 ¤   ¤   UInt32¤ ¤   ¤   oddballCount;
6846ad ¤   ¤   UInt32 *¤   ¤   curLong;
f754cc ¤   ¤   UInt32¤ ¤   ¤   numChunks;
501b52 ¤   ¤
26d0ab ¤   ¤   pgpAssert( length >= kAlignSize );
3b1b52 ¤   ¤
45290d ¤   ¤   /* create the fill pattern */
3e9213 ¤   ¤   pgpAssert( sizeof(fillPattern) == 4 * sizeof(fillChar) );
418f7d ¤   ¤   fillPattern = fillChar;
428eae ¤   ¤   fillPattern |= (fillPattern << 8);
445ccb ¤   ¤   fillPattern |= (fillPattern << 16);
a71b52 ¤   ¤
ff6047 ¤   ¤   /* align address to kAlignSize PGPByte boundary */
cd0134 ¤   ¤   oddballCount¤   = kAlignSize - ( ((UInt32)cur) % kAlignSize );
e9357d ¤   ¤   pgpAssert( oddballCount <= remaining );
9a551e ¤   ¤   FillBytes( cur, oddballCount, fillChar );
8d0883 ¤   ¤   remaining¤  -= oddballCount;
ca35c0 ¤   ¤   cur¤¤   ¤   += oddballCount;
20ddcc ¤   ¤   pgpAssert( remaining == 0 || (((UInt32)cur) % kAlignSize) == 0 );
151b52 ¤   ¤
a6b841 ¤   ¤   /* fill all the chunks */
d8a9bc ¤   ¤   curLong¤¤   = (UInt32 *)cur;
9ec734 ¤   ¤   numChunks¤  = remaining / kUnrollBytesPerIter;
ea188a ¤   ¤   while ( numChunks-- != 0 )
3d5b34 ¤   ¤   {
b2cd22 ¤   ¤   ¤   /* CAUTION:
fa93ea ¤   ¤   ¤   ¤   this loop must move a total of 'kUnrollBytesPerIter' bytes */
8dfeec ¤   ¤   ¤   *curLong++¤ = fillPattern;
e1feec ¤   ¤   ¤   *curLong++¤ = fillPattern;
0d0fe4 ¤   ¤   }
e11b52 ¤   ¤
006029 ¤   ¤   /* any remaining bytes get filled below... */
e3616a ¤   ¤   cur¤¤   ¤   = (Byte *)curLong;
7f0bc6 ¤   ¤   remaining¤  &= ( kUnrollBytesPerIter - 1 );
0f9371 ¤   }
--bb27 00106461bb2401000c9 Page 9 of pgpMem.c
f11b52 ¤   ¤
b3b1db ¤   FillBytes( cur, remaining, fillChar );
7667c5 ¤
ae8127 ¤   /* verify that at least first and last bytes have been set properly */
d581c3 ¤   pgpAssert( length == 0 ||
6c8d05 ¤   ¤   ( ((Byte *)buffer)[ 0 ] == fillChar &&
189208 ¤   ¤   ((Byte *)buffer)[ length - 1 ] == fillChar) );
b2efe6 }
63af5a
030335 /*____________________________________________________________________________
59cf30 ¤   Return true if memory blocks are equal, false otherwise.
8167c5 ¤
d85b1d ¤   Note: not yet optimized; this version is slow.
35f7f7 ____________________________________________________________________________*/
ed16ea ¤   PGPBoolean
ecf07e pgpMemoryEqual(
f481d4 ¤   const void *¤   b1,
e56eb0 ¤   const void *¤   b2,
468155 ¤   size_t¤ ¤   ¤   length)
cbbb36 {
d04812 ¤   size_t¤ ¤   ¤   remaining¤  = length;
06b141 ¤   const uchar *¤  cur1¤   = (uchar *)b1;
a137ce ¤   const uchar *¤  cur2¤   = (uchar *)b2;
9567c5 ¤
485e68 ¤   pgpa((
c770e8 ¤   ¤   pgpaAddrValid(b1, VoidAlign),
7da896 ¤   ¤   pgpaAddrValid(b2, VoidAlign),
38368f ¤   ¤   pgpaAssert(length >= 0)));
be67c5 ¤
56bd98 ¤   while (remaining-- > 0)
09d84a ¤   ¤   if (*cur1++ != *cur2++)
545f1f ¤   ¤   ¤   return FALSE;
9bc2e7 ¤   return TRUE;
83efe6 }
63af5a
b0ddc8 #endif¤ /* ] PGP_MACINTOSH */
26af5a
d07e4d /*__Editor_settings____
88af5a
3c4126 ¤   Local Variables:
e97b17 ¤   tab-width: 4
a40e6c ¤   End:
ac5f8c ¤   vi: ts=4 sw=4
0c9e9b ¤   vim: si
06d062 _____________________*/
--b5ea 0005d576147401000ca Page 1 of pgpMem.h
a70335 /*____________________________________________________________________________
9e05d9 ¤   pgpMem.h
5167c5 ¤
1af254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
ee4b0f ¤   All rights reserved.
2567c5 ¤
4f7feb ¤   Memory allocation routines with debugging support
23af5a
005e9e ¤   $Id: pgpMem.h,v 1.23.28.1 1998/11/12 03:17:55 heller Exp $
50f7f7 ____________________________________________________________________________*/
1893d7 #ifndef Included_pgpMem_h¤  /* [ */
d6edb4 #define Included_pgpMem_h
85af5a
9bbea3 #include <stdlib.h>
9529db #if ! PGP_MACINTOSH
3809c9 #include <string.h>¤¤   /* for memset and memcmp */
e37454 #endif
d4af5a
0e675a #include "pgpTypes.h"
7b2b62 #include "pgpPFLErrors.h"
36a146 #include "pgpDebug.h"
3f94a0 #include "pgpLeaks.h"
5caf5a
a75380 #ifndef IsNull
538cb5 #define IsntNull( p )¤  ( (PGPBoolean) ( (p) != NULL ) )
9e1d63 #define IsNull( p )¤¤   ( (PGPBoolean) ( (p) == NULL ) )
4c7454 #endif
b5af5a
37af5a
b599c6 PGP_BEGIN_C_DECLARATIONS
850335 /*____________________________________________________________________________
9bc2ea ·* There are five macros which control the debugging features of pgpmem.
10ff91 ·* Unless explicitly set, they default to the value of the PGP_DEBUG macro.
6e775e ·*
ace283 ·* NOTE: There's no need to set these explicitly for most purposes.
a5775e ·*
09bd0a ·* DEBUG_FILL_MEM¤  ¤   If set, all allocated memory will be set to 0xDD
9b5666 ·*¤ ¤   ¤   ¤   ¤   ¤   before use, and all deallocated memory will be set
025796 ·*¤ ¤   ¤   ¤   ¤   ¤   to 0xDD before being freed. ·This is also done when
cef274 ·*¤ ¤   ¤   ¤   ¤   ¤   resizing blocks.
2273a3 ·* DEBUG_MEM_HEAD_MAGIC¤If set, a ulong-byte magic number is placed immediately
85bf80 ·*¤ ¤   ¤   ¤   ¤   ¤   before each block, to detect buffer overruns.
6746b4 ·* DEBUG_MEM_TAIL_MAGIC¤If set, magic numbers are placed after the end of each
c88ca7 ·*¤ ¤   ¤   ¤   ¤   ¤   block to detect buffer overruns. ·The value of the
1cd770 ·*¤ ¤   ¤   ¤   ¤   ¤   macro determines the number of bytes added.
945d4a ·* PGP_DEBUG_FIND_LEAKS¤¤   If set, a list is kept of all allocated blocks·
839021 ·*¤ ¤   ¤   ¤   ¤   ¤   which is used to detect memory leaks on program exit.
03683c ·* DEBUG_ALWAYS_MOVE¤   If set, memory blocks are always moved when increasing
17e633 ·*¤ ¤   ¤   ¤   ¤   ¤   the size of a block.
56f7f7 ____________________________________________________________________________*/
33af5a
1b0f91 #ifndef PGP_DEBUG_FIND_LEAKS
94b4b1 #define PGP_DEBUG_FIND_LEAKS¤   USE_PGP_LEAKS¤  /* Find memory leaks */
d77454 #endif
4eaf5a
e1691c #if PGP_DEBUG_FIND_LEAKS
daaf5a
6c1a8e #define PGPALLOC_CONTEXT_PARAMS¤¤   ¤   , __FILE__, __LINE__
ce6fe8 #define PGPALLOC_CONTEXT_PARAMS_DEF¤¤   , char const *fileName, long lineNumber
902d26 #define PGPALLOC_CONTEXT_PASS_PARAMS¤   , fileName, lineNumber
bb4893 #define PGP_INTERNAL_ALLOC¤ ¤   ¤   ¤   pgpInternalContextAlloc
1aea4d #define PGP_INTERNAL_MEMALLOC¤  ¤   ¤   pgpInternalContextMemAlloc
d0317d #define PGP_INTERNAL_MEMREALLOC¤¤   ¤   pgpInternalContextMemRealloc
d9af5a
26db21 #else
d3af5a
f72f3c #define PGPALLOC_CONTEXT_PARAMS
e02770 #define PGPALLOC_CONTEXT_PARAMS_DEF
62c7a5 #define PGPALLOC_CONTEXT_PASS_PARAMS
d29289 #define PGP_INTERNAL_ALLOC¤ ¤   ¤   ¤   pgpInternalAlloc
d00aea #define PGP_INTERNAL_MEMALLOC¤  ¤   ¤   pgpInternalMemAlloc
5dc4f0 #define PGP_INTERNAL_MEMREALLOC¤¤   ¤   pgpInternalMemRealloc
--9d18 0003d67b8f3401000ca Page 2 of pgpMem.h
e0af5a
317454 #endif
75af5a
5b38e5 /*
172e0a ·* These functions won't return NULL for 0-sized blocks,
f93c96 ·* and will fail assertions if NULL is passed in.
ec2896 ·* pgpRealloc also has a different, cleaner calling convention.
c2495d ·*/
9902c4 #define ¤   ¤   ¤   pgpAlloc(size)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
faf8b3 ¤   ¤   ¤   ¤   ¤   PGP_INTERNAL_ALLOC(size ·PGPALLOC_CONTEXT_PARAMS)
ec88cf #define ¤   ¤   ¤   pgpNew(type)¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
cc96f1 ¤   ¤   ¤   ¤   ¤   ((type *)pgpAlloc(sizeof(type)))
cebf3a PGPError ¤  pgpRealloc(void **userPtrRef, size_t newSize);
a15da2 void ¤  ¤   pgpFree(void *userPtr);
a5af5a
3538e5 /*
927d85 ·* These functions WILL return NULL for 0-sized blocks, and
31254e ·* deal with NULL passed in as if it was a 0-sized block,
da397e ·* for backward compatibility. ·They have the same semantics
3512ca ·* as malloc/realloc/free.
90495d ·*/
366dd6 #define ¤   ¤   ¤   pgpMemAlloc(size) ¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
80617b ¤   ¤   ¤   ¤   ¤   PGP_INTERNAL_MEMALLOC(size ·PGPALLOC_CONTEXT_PARAMS)
7a43d5 #define ¤   ¤   ¤   pgpMemNew(type)¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
99223c ¤   ¤   ¤   ¤   ¤   ((type *)pgpMemAlloc(sizeof(type)))
897874 #define ¤   ¤   ¤   pgpMemRealloc(userPtr, newSize) ¤   ¤   ¤   ¤   ¤   ¤   \
f887eb ¤   ¤   ¤   ¤   ¤   PGP_INTERNAL_MEMREALLOC(userPtr, newSize¤   ¤   ¤   ¤   \
0830be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPALLOC_CONTEXT_PARAMS)
66d64d void ¤  ¤   ¤   ¤   pgpMemFree(void *userPtr);
22af5a
ba383f #define¤¤   ¤   ¤   pgpaMemBlockValid(userPtr)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
a47a54 ¤   ¤   ¤   ¤   ¤   pgpaCall(pgpaInternalMemBlockValid,¤¤   ¤   ¤   ¤   ¤   \
13bcc7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (pgpaCallPrefix, userPtr))
ee606a #define ¤   ¤   ¤   pgpAssertMemBlockValid( ptr ) ¤ \
529629 ¤   ¤   ¤   ¤   ¤   ¤   pgpa( pgpaMemBlockValid( ptr ) )
8eaf5a
e9af5a
4b9379 /* Memory copy routine optimized for large blocks, overlapping okay */
04fff8 void ¤  pgpCopyMemory(void const *src, void *dest, size_t size);
93af5a
77c21c #if PGP_MACINTOSH¤  /* [ */
ecaf5a
e5bb9e PGPBoolean ¤pgpMemoryEqual(const void *b1, const void *b2,
e18992 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   size_t length);
1d3a62 void ¤  ¤   pgpFillMemory(void *buffer, size_t length,
490899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   uchar fillChar);
51af5a
fec69d #else¤  /* ] PGP_MACINTOSH [ */
dfaf5a
377df5 #define¤¤   ¤   ¤   pgpMemoryEqual(b1, b2, length)¤ ¤   ¤   ¤   ¤   ¤   ¤   \
6871f5 ¤   ¤   ¤   ¤   ¤   (memcmp((void *)(b1), (void *)(b2), (length)) == 0)
369780 #define¤¤   ¤   ¤   pgpFillMemory(buffer, length, fillChar)¤¤   ¤   ¤   ¤   \
bd14d2 ¤   ¤   ¤   ¤   ¤   ((void)memset((void *)(buffer), (fillChar), (length)))
44af5a
6dddc8 #endif¤ /* ] PGP_MACINTOSH */
04af5a
31c88c #define ¤   ¤   ¤   pgpClearMemory(buffer, byteCount)¤  ¤   ¤   ¤   ¤   ¤   \
a79861 ¤   ¤   ¤   ¤   ¤   pgpFillMemory((buffer), (byteCount), '\0')
06af5a
56f11d void ¤  pgpCopyPattern(const void *pattern, size_t patternLength,
40c6c8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   void *buffer, size_t bufferLength);
98af5a
8caf5a
f2ec00 /* Lookie here! ·An ANSI-compliant alignment finder! */
5cda6c #ifndef ¤   ¤   ¤   alignof
2124e1 #define ¤   ¤   ¤   alignof(type) (sizeof(struct{type _x; char _y;})¤   ¤   \
bfc052 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   - sizeof(type))
127454 #endif
edaf5a
4c38e5 /*
82adc4 ·* WARNING: These should only be used by the above macros
3d495d ·*/
--af2a 001daa9207a401000ca Page 3 of pgpMem.h
7306b6 void ·*¤PGP_INTERNAL_ALLOC(size_t size
2acfa4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPALLOC_CONTEXT_PARAMS_DEF);
b261df void ·*¤PGP_INTERNAL_MEMALLOC(size_t size
53d912 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPALLOC_CONTEXT_PARAMS_DEF);
a137f4 void ·*¤PGP_INTERNAL_MEMREALLOC(void *userPtr, size_t newSize
eed912 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPALLOC_CONTEXT_PARAMS_DEF);
90af5a
5a5c98 #if PGP_DEBUG
c0f45a PGPBoolean ¤pgpaInternalMemBlockValid(pgpaCallPrefixDef,
9467eb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const void *userPtr);
7c7454 #endif
d3af5a
791254 PGP_END_C_DECLARATIONS
9aaf5a
4cd96d #endif /* ] Included_pgpMem_h */
baaf5a
dc7e4d /*__Editor_settings____
2caf5a
f64126 ¤   Local Variables:
177b17 ¤   tab-width: 4
e30e6c ¤   End:
b05f8c ¤   vi: ts=4 sw=4
389e9b ¤   vim: si
dad062 _____________________*/
--cce7 0005b7d3153401000cb Page 1 of pgpMemoryMgr.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
1760c2 ¤   $Id: pgpMemoryMgr.c,v 1.38.12.1 1998/11/12 03:17:56 heller Exp $
48f7f7 ____________________________________________________________________________*/
9e2b62 #include "pgpPFLErrors.h"
e60d08 #include "pgpMem.h"
9a51b9 #include "pgpRMWOLock.h"
a5af5a
39025a #include "pgpMemoryMgrPriv.h"
25af5a
b9af5a
ca80fd /* if defined as 1, causes leaks to be tracked */
930ebf #define MEMORY_MGR_TRACK_LEAKS¤ ¤   ¤   PGP_DEBUG
43af5a
ffaf5a
9f1cb9 #define TESTING¤¤   PGP_DEBUG
a9af5a
a7dede #if TESTING
aea221 static void¤¤   sTestMemoryMgr( PGPMemoryMgrRef mgr );
ecdb21 #else
9e624f #define sTestMemoryMgr( mgr )¤  /* nothing */
327454 #endif
5faf5a
e00335 /*____________________________________________________________________________
b257f4 ¤   This structure is prepended to every allocated block.
6667c5 ¤
86e222 ¤   It is dynamically padded to keep it aligned to the alignment
e6762d ¤   requirement. ·See kRealHeaderSize.
acf7f7 ____________________________________________________________________________*/
2ef705 typedef struct DataHeader
72bb36 {
f323ac #define kHeaderMagic¤   ((PGPUInt16)0xABCD)
59bfd9 ¤   PGPMemoryMgrRef¤mgr;
1167c5 ¤
32d3e6 ¤   PGPUInt32¤  ¤   secureAlloc¤¤   : 1;
ec6359 ¤   PGPUInt32¤  ¤   nonPageable¤¤   : 1;
f64171 ¤   PGPUInt32¤  ¤   requestSize¤: 30;
7e67c5 ¤
1bb1a7 #if MEMORY_MGR_TRACK_LEAKS
0d24af ¤   struct DataHeader *¤next;
4526b7 ¤   struct DataHeader *¤prev;
5f7454 #endif
9d67c5 ¤
ff9d0d ¤   PGPUInt32¤  ¤   magic;
db269b ¤   #define kDataHeaderMagic¤   ¤   0x42554746 ·/*'BUGF'*/
6b20e9 } DataHeader;
0faf5a
cfca36 #define kHeaderAlign¤   ¤   16
57cfd0 #define kOddHeaderBytes¤¤   ( sizeof( DataHeader ) % kHeaderAlign )
389d8e #define kNeededHeaderBytes¤ ( (kHeaderAlign - kOddHeaderBytes) % kHeaderAlign)
b5372a #define kRealHeaderSize¤¤   ( sizeof( DataHeader ) + kNeededHeaderBytes )
8baf5a
1cd57c #define HeaderToUserBlock( hdr )¤   \
3d36df ¤   ( (void *)( ((char *)(hdr)) + kRealHeaderSize) )
e2dc55 #define UserBlockToHeader( user )¤  \
af3975 ¤   ( (DataHeader *)(((char *)user) - kRealHeaderSize) )
efaf5a
97af5a
666c2c ¤   static PGPBoolean
d97aea sDataHeaderIsValid( const DataHeader *header )
83bb36 {
a50d51 ¤   return( IsntNull( header ) &&
ef22d5 ¤   ¤   ¤   PGPMemoryMgrIsValid( header->mgr ) &&
f5df28 ¤   ¤   ¤   header->magic == kDataHeaderMagic );
59efe6 }
bcaf5a
5c5c98 #if PGP_DEBUG
077f31 #define AssertBlockValid( block) \
91f127 ¤   pgpAssert( IsntNull( block ) && \
5b3f09 ¤   sDataHeaderIsValid( (const DataHeader *)\
--61c9 0004c7c657f401000cb Page 2 of pgpMemoryMgr.c
508f7f ¤   ¤   UserBlockToHeader( block ) ) )
27db21 #else
57fb2d #define AssertBlockValid( block ) /* nothing */
c77454 #endif
4faf5a
e7af5a
f1af5a
2ace0d struct PGPMemoryMgr
eabb36 {
dd6521 #define kPGPMemoryMgrMagic¤ 0x4D4D6772¤ /* 'MMgr' */
ca7800 ¤   PGPUInt32¤  ¤   magic;¤ ¤   ¤   ¤   /* Always kPGPMemoryMgrMagic */
a4786e ¤   PGPUserValue¤   customValue;¤   ¤   /* for custom memory mgrs */
f5672a ¤   PGPBoolean¤ ¤   isDefault;
8e67c5 ¤
e8961c ¤   PGPMemoryMgrAllocationProc¤ ¤   allocProc;
227cbd ¤   PGPMemoryMgrReallocationProc¤   reallocProc;
7894ac ¤   PGPMemoryMgrDeallocationProc¤   deallocProc;
a867c5 ¤
f662f3 ¤   PGPMemoryMgrSecureAllocationProc¤   secureAllocProc;¤   /* may be NULL */
12f601 ¤   PGPMemoryMgrSecureDeallocationProc¤ secureDeallocProc;¤ /* may be NULL */
ffaf5a
22b1a7 #if MEMORY_MGR_TRACK_LEAKS
3b52ac ¤   PGPRMWOLock¤¤   ¤   leaksRMWOLock;
ce2675 ¤   DataHeader *¤   ¤   leaksList;
d17f37 ¤   DataHeader¤ ¤   ¤   dummyItem;
d1b194 ¤   PGPSize¤¤   ¤   ¤   numAllocations;
b67454 #endif
b72fa1 } ;
d1af5a
d8af5a
d8af5a
e716ea ¤   PGPBoolean
a507f6 PGPMemoryMgrIsValid( PGPMemoryMgrRef mgr )
c9bb36 {
7ec8e4 ¤   return( IsntNull( mgr ) &&
a523e2 ¤   ¤   ¤   mgr->magic == kPGPMemoryMgrMagic );
26efe6 }
22af5a
2aaf5a
cfaf5a
78cf93 #if MEMORY_MGR_TRACK_LEAKS¤ /* [ */
3baf5a
f0af5a
2933c8 ¤   static void
afdca1 sCheckListIntegrity( DataHeader const * list )
34bb36 {
23b4a3 ¤   DataHeader *¤   ¤   cur¤¤   = list->next;
eb735f ¤   const DataHeader *¤ prev¤   = list;
b067c5 ¤
77b44f ¤   /* verify that item isn't already in list */
0d5d6e ¤   while ( cur != list )
f8c7a1 ¤   {
8d6c7f ¤   ¤   pgpAssert( cur->magic == kDataHeaderMagic );
00f16b ¤   ¤   pgpAssert( cur->prev->magic == kDataHeaderMagic );
5f7f56 ¤   ¤   pgpAssert( cur->next->magic == kDataHeaderMagic );
77bb9f ¤   ¤   pgpAssert( cur->next->prev == cur && cur->prev->next == cur);
d8b14f ¤   ¤   prev = cur;
6835af ¤   ¤   cur¤= cur->next;
df9371 ¤   }
5aefe6 }
fcaf5a
3c33c8 ¤   static void
9de083 sAddToLeaksList(
8e6740 ¤   PGPMemoryMgrRef¤mgr,
06ae1e ¤   DataHeader *¤   item )
3cbb36 {
4b63b2 ¤   DataHeader *¤   list;
0967c5 ¤
0eac94 ¤   PGPRMWOLockStartWriting(&mgr->leaksRMWOLock);
cfaf5a
15322b ¤   list = mgr->leaksList;
4caf5a
--5203 0004c97343b401000cb Page 3 of pgpMemoryMgr.c
bb1db3 ¤   sCheckListIntegrity( list );
cf67c5 ¤
9a217d ¤   pgpAssert( IsntNull( list->next ) && IsntNull( list->prev ) );
0c67c5 ¤
415c98 #if PGP_DEBUG
52c7a1 ¤   {
865c96 ¤   ¤   DataHeader *¤   cur¤= list->next;
651b52 ¤   ¤
b1e754 ¤   ¤   /* verify that item isn't already in list */
8ed43a ¤   ¤   while ( cur != list )
4e5b34 ¤   ¤   {
aa3220 ¤   ¤   ¤   pgpAssert( cur != item );
1801f2 ¤   ¤   ¤   cur¤= cur->next;
270fe4 ¤   ¤   }
bb9371 ¤   }
307454 #endif
67af5a
266150 ¤   /* insert new item into circular linked list */
d74d02 ¤   item->next¤ ¤   ¤   = list;
321972 ¤   item->prev¤ ¤   ¤   = list->prev;
2543ae ¤   list->prev->next¤   = item;
24789f ¤   list->prev¤ ¤   ¤   = item;
df67c5 ¤
3311e8 ¤   mgr->numAllocations¤+= 1;
5667c5 ¤
cf1db3 ¤   sCheckListIntegrity( list );
c667c5 ¤
134403 ¤   pgpAssert( IsntNull( item->next ) && IsntNull( item->prev ) );
fbaf5a
bfaf7c ¤   PGPRMWOLockStopWriting(&mgr->leaksRMWOLock);
dbaf5a
12efe6 }
87af5a
1c33c8 ¤   static void
3eabc8 sRemoveFromLeaksList(
bc4d00 ¤   PGPMemoryMgrRef¤¤   mgr,
2c9052 ¤   DataHeader *¤   ¤   item )
59bb36 {
81dcc1 ¤   DataHeader *¤   next;
c3ded9 ¤   DataHeader *¤   prev;
4367c5 ¤
b4ac94 ¤   PGPRMWOLockStartWriting(&mgr->leaksRMWOLock);
31af5a
890952 ¤   next¤   = item->next;
8f6a52 ¤   prev¤   = item->prev;
7daf5a
06f6d2 ¤   sCheckListIntegrity( mgr->leaksList );
f667c5 ¤
0ebea4 ¤   pgpAssert( prev->next == item && next->prev == item );
a767c5 ¤
7110f5 ¤   next->prev¤ = prev;
57617c ¤   prev->next¤ = next;
8167c5 ¤
460d8f ¤   item->next¤ = NULL;
144cf0 ¤   item->prev¤ = NULL;
5167c5 ¤
390912 ¤   mgr->numAllocations¤-= 1;
df67c5 ¤
38f6d2 ¤   sCheckListIntegrity( mgr->leaksList );
46af5a
5eaf7c ¤   PGPRMWOLockStopWriting(&mgr->leaksRMWOLock);
63efe6 }
f4af5a
d6db21 #else
db430b #define sAddToLeaksList( mgr, item )¤   ¤   /* nothing */
201462 #define sRemoveFromLeaksList( mgr, item )¤  /* nothing */
76af5a
1d3167 #endif¤ /* ] */
e6af5a
e36d52 ¤   void
f0e5fd PGPCheckMemoryMgrIntegrity( PGPMemoryMgrRef mgr )
4cbb36 {
--c768 00051c27d69401000cb Page 4 of pgpMemoryMgr.c
b2b076 ¤   (void)mgr;
85b1a7 #if MEMORY_MGR_TRACK_LEAKS
2257b2 ¤   PGPRMWOLockStartReading(&mgr->leaksRMWOLock);
c0af5a
a2f6d2 ¤   sCheckListIntegrity( mgr->leaksList );
6aaf5a
1a545a ¤   PGPRMWOLockStopReading(&mgr->leaksRMWOLock);
117454 #endif
70efe6 }
00af5a
7aaf5a
f633c8 ¤   static void
cee8df sInitDataHeader(
386740 ¤   PGPMemoryMgrRef¤mgr,
f4d43c ¤   PGPSize¤¤   ¤   requestSize,
43478f ¤   DataHeader *¤   header )
95bb36 {
75ac1f ¤   pgpClearMemory( header, sizeof(*header) );
8816ad ¤   header->mgr¤¤   ¤   ¤   = mgr;
b75023 ¤   header->secureAlloc¤¤   = FALSE;
c00904 ¤   header->nonPageable¤¤   = FALSE;
d84ed1 ¤   header->requestSize¤= requestSize;
b467c5 ¤
76afbb ¤   header->magic¤  = kDataHeaderMagic;
fa67c5 ¤
57b1a7 #if MEMORY_MGR_TRACK_LEAKS
25a72c ¤   header->next¤   ¤   ¤   = NULL;
8a8ef2 ¤   header->prev¤   ¤   ¤   = NULL;
7e67c5 ¤
217454 #endif
9eefe6 }
abaf5a
7aaf5a
deaf5a
66af5a
cd0335 /*____________________________________________________________________________
96265c ¤   Reallocate a secure block.
7267c5 ¤
84042d ¤   To preserve the semantics of the block not changing if it shrinks,
73bd2a ¤   we take no action if the block is shrinking. ·If it's growing, we
e10b40 ¤   always discard it and create a new one.
89f7f7 ____________________________________________________________________________*/
0e66dd ¤   static PGPError
28bfb0 sSecureMemoryReallocProc(
404d00 ¤   PGPMemoryMgrRef¤¤   mgr,
7e40a7 ¤   void **¤¤   ¤   ¤   allocation,
a48553 ¤   PGPSize ¤   ¤   ¤   newAllocationSize,
326569 ¤   PGPMemoryMgrFlags¤  flags,
b30f8e ¤   PGPSize¤¤   ¤   ¤   existingSize )
24bb36 {
f77637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
c567c5 ¤
8a047a ¤   pgpAssert( IsntNull( *allocation ) );
6667c5 ¤
c1b177 #if 0
7d56e3 ¤   if ( newAllocationSize <= existingSize )
93c7a1 ¤   {
e8acdf ¤   ¤   PGPUInt32¤  excessByteCount;
e24931 ¤   ¤   char *¤ ¤   dataToClear¤= NULL;
2d1b52 ¤   ¤
ebf2f4 ¤   ¤   /* leave existing size intact, but clear excess bytes now
1ac68f ¤   ¤   to avoid leaving sensitive data in memory unnecessarily */
9e99a3 ¤   ¤   excessByteCount¤= existingSize - newAllocationSize;
9cc0ac ¤   ¤   dataToClear¤= ((char *)*allocation) + newAllocationSize;
4f572b ¤   ¤   pgpClearMemory( dataToClear, excessByteCount );
301b52 ¤   ¤
94d87c ¤   ¤   err¤= kPGPError_NoErr;
c19371 ¤   }
9c0e24 ¤   else
c27454 #endif
ed6119 ¤   {¤  /* block is increasing in size */
515459 ¤   ¤   PGPBoolean¤ isNonPageable;
--08f6 000750f117f401000cb Page 5 of pgpMemoryMgr.c
91ced2 ¤   ¤   void *¤ ¤   newBlock¤   = NULL;
d81b52 ¤   ¤
b1d08f ¤   ¤   newBlock¤   = (mgr->secureAllocProc)( mgr, mgr->customValue,
f02466 ¤   ¤   ¤   newAllocationSize, flags, &isNonPageable);
9748ce ¤   ¤   if ( IsntNull( newBlock ) )
a15b34 ¤   ¤   {
758be1 ¤   ¤   ¤   DataHeader *¤   oldHeader¤  = (DataHeader *)*allocation;
1baf5a
ee09f6 ¤   ¤   ¤   pgpCopyMemory( *allocation, newBlock,
62b741 ¤   ¤   ¤   ¤   pgpMin( existingSize, newAllocationSize ) );
ec87c7 ¤   ¤   ¤
33df39 ¤   ¤   ¤   (mgr->secureDeallocProc)( mgr, mgr->customValue,
5e6f91 ¤   ¤   ¤   ¤   *allocation, existingSize,
8fa486 ¤   ¤   ¤   ¤   (PGPBoolean)oldHeader->nonPageable );
31b5f1 ¤   ¤   ¤   *allocation¤= newBlock;
d00fe4 ¤   ¤   }
ab0e1d ¤   ¤   else
175b34 ¤   ¤   {
b3124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
010fe4 ¤   ¤   }
0b9371 ¤   }
5667c5 ¤
eedeb7 ¤   return( err );
26efe6 }
f9af5a
eeaf5a
6faf5a
6daf5a
730335 /*____________________________________________________________________________
a8bed5 ¤   Allocate a new Memory Mgr using custom memory allocators.
5bf7f7 ____________________________________________________________________________*/
5ac744 ¤   PGPError
fd95c1 PGPNewMemoryMgrCustom(
d1ddb2 ¤   PGPNewMemoryMgrStruct const *¤  custom,
c3ff97 ¤   PGPMemoryMgrRef *¤  ¤   ¤   ¤   newMgr )
0bbb36 {
117d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
5b2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
94cf12 ¤   PGPUInt32¤  ¤   ¤   idx;
e167c5 ¤
0d582e ¤   PGPValidatePtr( newMgr );
02f218 ¤   *newMgr¤= NULL;
ad2c61 ¤   PGPValidatePtr( custom );
fe5521 ¤   PGPValidatePtr( custom->allocProc );
e9c61e ¤   PGPValidatePtr( custom->reallocProc );
9ddc17 ¤   PGPValidatePtr( custom->deallocProc );
0752ff ¤   PGPValidatePtr( custom->secureAllocProc );
2f6d83 ¤   PGPValidatePtr( custom->secureDeallocProc );
d381b1 ¤   PGPValidateParam( custom->sizeofStruct >= sizeof( *custom ) );
4d87a4 ¤   PGPValidateParam( custom->reserved == NULL );
e767c5 ¤
32827a ¤   #define kNumPads¤   sizeof( custom->pad ) / sizeof( custom->pad[ 0 ] )
2d13fc ¤   for( idx = 0; idx < kNumPads; ++idx )
2bc7a1 ¤   {
b8c28c ¤   ¤   PGPValidateParam( custom->pad[ idx ] == NULL );
9e9371 ¤   }
4767c5 ¤
32e344 ¤   /* NOTE: do not depend on kPGPMemoryMgrFlags_Clear here;
9c2b37 ¤   ·allocator is not required to support it */
b553f1 ¤   mgr = (PGPMemoryMgr *) (*(custom->allocProc))( NULL, custom->customValue,
ad523f ¤   ¤   ¤   ¤   sizeof( *mgr ), 0 );
62451f ¤   if( IsntNull( mgr ) )
c4c7a1 ¤   {
5f9244 ¤   ¤   pgpClearMemory( mgr, sizeof( *mgr ) );
4eb948 ¤   ¤   mgr->magic¤ ¤   ¤   ¤   = kPGPMemoryMgrMagic;
5082e8 ¤   ¤   mgr->allocProc¤ ¤   ¤   = custom->allocProc;
21f0eb ¤   ¤   mgr->reallocProc¤   ¤   = custom->reallocProc;
7b1a64 ¤   ¤   mgr->deallocProc¤   ¤   = custom->deallocProc;
f62ea5 ¤   ¤   mgr->secureAllocProc¤   = custom->secureAllocProc;
9a1b8e ¤   ¤   mgr->secureDeallocProc¤ = custom->secureDeallocProc;
98af5a
753e9e ¤   ¤   mgr->customValue¤   ¤   = custom->customValue;
--d363 000e26c3eb6401000cb Page 6 of pgpMemoryMgr.c
79b3d3 ¤   ¤   mgr->isDefault¤ ¤   ¤   = FALSE;
d81b52 ¤   ¤
39b1a7 #if MEMORY_MGR_TRACK_LEAKS
fc856d ¤   ¤   /* Create read many/write once mutex. */
f2ac3e ¤   ¤   InitializePGPRMWOLock(&mgr->leaksRMWOLock);
16af5a
169aeb ¤   ¤   /* set up doubly-linked leaks list */
7f5216 ¤   ¤   mgr->leaksList¤ ¤   ¤   = &mgr->dummyItem;
61e49f ¤   ¤   mgr->dummyItem.next¤¤   = &mgr->dummyItem;
a22d80 ¤   ¤   mgr->dummyItem.prev¤¤   = &mgr->dummyItem;
188566 ¤   ¤   mgr->dummyItem.magic¤   = kDataHeaderMagic;
d39818 ¤   ¤   mgr->numAllocations¤¤   = 0;
c47454 #endif
a99371 ¤   }
f50e24 ¤   else
50c7a1 ¤   {
d3bce1 ¤   ¤   err = kPGPError_OutOfMemory;
499371 ¤   }
4a67c5 ¤
e4bc05 ¤   *newMgr¤= mgr;
ee67c5 ¤
aadede #if TESTING
06f1e7 ¤   if ( IsntPGPError( err ) )
d7c7a1 ¤   {
2794fb ¤   ¤   sTestMemoryMgr( mgr );
e69371 ¤   }
c37454 #endif
8167c5 ¤
d5deb7 ¤   return( err );
d4efe6 }
aaaf5a
cbaf5a
0f0335 /*____________________________________________________________________________
3cf7f7 ____________________________________________________________________________*/
aaaf5a
48c744 ¤   PGPError
511d91 PGPNewMemoryMgr(
3b595f ¤   PGPFlags¤   ¤   ¤   reserved,
819913 ¤   PGPMemoryMgrRef *¤  newMgr )
e3bb36 {
8826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5867c5 ¤
b1582e ¤   PGPValidatePtr( newMgr );
4ef218 ¤   *newMgr¤= NULL;
78c4be ¤   PGPValidateParam( reserved == 0 );
1767c5 ¤
52d23c ¤   err¤= pgpCreateStandardMemoryMgr( newMgr );
e3f1e7 ¤   if ( IsntPGPError( err ) )
86c7a1 ¤   {
fedbdd ¤   ¤   (*newMgr)->isDefault¤   = TRUE;
a09371 ¤   }
9667c5 ¤
dedeb7 ¤   return( err );
9defe6 }
88af5a
60af5a
08af5a
b40335 /*____________________________________________________________________________
07a422 ¤   Delete an existing PFLContext and all resources associated with it.
d6f7f7 ____________________________________________________________________________*/
99c744 ¤   PGPError
e9fd44 PGPFreeMemoryMgr(PGPMemoryMgrRef¤   mgr)
e6bb36 {
008e12 ¤   PGPError¤   err = kPGPError_NoErr;
0867c5 ¤
cf6382 ¤   PGPValidateParam( PGPMemoryMgrIsValid( mgr ) );
f5af5a
b5f42d ¤   if( PGPMemoryMgrIsValid( mgr ) )
83c7a1 ¤   {
7e04d0 ¤   ¤   PGPUserValue¤   customValue¤= mgr->customValue;
0b44c8 ¤   ¤   PGPBoolean¤ ¤   isDefault¤  = mgr->isDefault;
e21b52 ¤   ¤
--b484 00049a1fadd401000cb Page 7 of pgpMemoryMgr.c
d8b1a7 #if MEMORY_MGR_TRACK_LEAKS
362e2c ¤   ¤   DeletePGPRMWOLock(&mgr->leaksRMWOLock);
55af5a
3dc74f ¤   ¤   pgpAssertMsg( mgr->numAllocations == 0,
fdceaf ¤   ¤   "PGPFreeData(): mgr being freed with outstanding allocations" );
7c7454 #endif
621b52 ¤   ¤
20208d ¤   ¤   (*mgr->deallocProc)( NULL, customValue, mgr, sizeof( *mgr ));
ec1b52 ¤   ¤
7d522d ¤   ¤   if ( isDefault )
405b34 ¤   ¤   {
39af82 ¤   ¤   ¤   pgpDisposeStandardMemoryMgrUserValue( customValue );
070fe4 ¤   ¤   }
bf1b52 ¤   ¤
af9371 ¤   }
d50e24 ¤   else
ccc7a1 ¤   {
4519d3 ¤   ¤   err = kPGPError_BadParams;
5c9371 ¤   }
2267c5 ¤
3edeb7 ¤   return( err );
e5efe6 }
f1af5a
29af5a
50c744 ¤   PGPError
15d473 PGPGetMemoryMgrCustomValue(
855f6a ¤   PGPMemoryMgrRef ¤   mgr,
bce5d2 ¤   PGPUserValue *¤ ¤   customValue)
54bb36 {
d98e12 ¤   PGPError¤   err = kPGPError_NoErr;
e367c5 ¤
f69792 ¤   PGPValidatePtr( customValue );
f3a689 ¤   *customValue¤   = NULL;
46ab8f ¤   PGPValidateMemoryMgr( mgr );
9f392a ¤   /* illegal to change user value of default allocator */
e9a488 ¤   PGPValidateParam( ! mgr->isDefault );
4167c5 ¤
4a951d ¤   if( PGPMemoryMgrIsValid( mgr ) &&
3ccf24 ¤   ¤   IsntNull( customValue ) )
15c7a1 ¤   {
4d545e ¤   ¤   *customValue = mgr->customValue;
d09371 ¤   }
790e24 ¤   else
07c7a1 ¤   {
9219d3 ¤   ¤   err = kPGPError_BadParams;
ac9371 ¤   }
cb67c5 ¤
f4deb7 ¤   return( err );
20efe6 }
8aaf5a
22c744 ¤   PGPError
5b822f PGPSetMemoryMgrCustomValue(
3d5f6a ¤   PGPMemoryMgrRef ¤   mgr,
e29403 ¤   PGPUserValue ¤  ¤   customValue)
17bb36 {
a38e12 ¤   PGPError¤   err = kPGPError_NoErr;
3767c5 ¤
a8ab8f ¤   PGPValidateMemoryMgr( mgr );
bb392a ¤   /* illegal to change user value of default allocator */
d2a488 ¤   PGPValidateParam( ! mgr->isDefault );
e467c5 ¤
d0f42d ¤   if( PGPMemoryMgrIsValid( mgr ) )
ddc7a1 ¤   {
8a15d1 ¤   ¤   mgr->customValue = customValue;
df9371 ¤   }
e30e24 ¤   else
15c7a1 ¤   {
3019d3 ¤   ¤   err = kPGPError_BadParams;
0a9371 ¤   }
ea67c5 ¤
6adeb7 ¤   return( err );
49efe6 }
--6be9 0006d1b727f401000cb Page 8 of pgpMemoryMgr.c
e0af5a
1aaf5a
17af5a
78af5a
32af5a
ff0335 /*____________________________________________________________________________
21c6b3 ¤   Allocate a block of memory using the allocator stored in a PFLContext.
32f7f7 ____________________________________________________________________________*/
88af5a
6b59fc ¤   void *
a48eeb PGPNewData(
125f6a ¤   PGPMemoryMgrRef ¤   mgr,
0dcb76 ¤   PGPSize ¤   ¤   ¤   requestSize,
ee1bd1 ¤   PGPMemoryMgrFlags¤  flags)
a4bb36 {
49c53a ¤   void¤   *allocation¤¤   = NULL;
7ee84d ¤   PGPSize¤allocationSize¤ = requestSize;
5c67c5 ¤
860c20 ¤   allocationSize¤ += kRealHeaderSize;
ed67c5 ¤
17e05f ¤   pgpAssert( PGPMemoryMgrIsValid( mgr ) );
e267c5 ¤
8df42d ¤   if( PGPMemoryMgrIsValid( mgr ) )
a7c7a1 ¤   {
518d65 ¤   ¤   allocation = (*mgr->allocProc)( mgr, mgr->customValue,
201049 ¤   ¤   ¤   ¤   ¤   ¤   allocationSize, flags );
f69371 ¤   }
cd67c5 ¤
50f2e5 ¤   if ( IsntNull( allocation ) )
60c7a1 ¤   {
ddc1a7 ¤   ¤   DataHeader *¤   header¤ = NULL;
d567c5 ¤
f9971d ¤   ¤   if ( (flags & kPGPMemoryMgrFlags_Clear ) != 0 )
1f5b34 ¤   ¤   {
3ed38f ¤   ¤   ¤   pgpClearMemory( allocation, allocationSize );
460fe4 ¤   ¤   }
eb0e1d ¤   ¤   else
345b34 ¤   ¤   {
42e137 ¤   ¤   ¤   pgpDebugWhackMemory( allocation, allocationSize );
bd0fe4 ¤   ¤   }
4d1b52 ¤   ¤
dfd9a8 ¤   ¤   header¤ = (DataHeader *)allocation;
4e43e1 ¤   ¤   sInitDataHeader( mgr, requestSize, header );
1a1b52 ¤   ¤
b0cb82 ¤   ¤   allocation¤ ¤   = HeaderToUserBlock( allocation );
c25b75 ¤   ¤   AssertBlockValid( allocation );
721b52 ¤   ¤
9ae5dd ¤   ¤   sAddToLeaksList( mgr, header );
239371 ¤   }
6daf5a
30ec77 ¤   return( allocation );
42efe6 }
aaaf5a
23af5a
a7af5a
71af5a
590335 /*____________________________________________________________________________
f5f242 ¤   Allocate a block of memory (secure or non-secure).
e2f7f7 ____________________________________________________________________________*/
37c744 ¤   PGPError
5feb3c PGPReallocData(
4b5f6a ¤   PGPMemoryMgrRef ¤   mgr,
06fd41 ¤   void **¤¤   ¤   ¤   userPtr,
39cb76 ¤   PGPSize ¤   ¤   ¤   requestSize,
bf1bd1 ¤   PGPMemoryMgrFlags¤  flags)
61bb36 {
983ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
b267c5 ¤
c66382 ¤   PGPValidateParam( PGPMemoryMgrIsValid( mgr ) );
1b5a80 ¤   PGPValidatePtr( userPtr );
48af5a
6db385 ¤   /* allow a NULL input ·*/
--81b1 0002c8d7bd4401000cb Page 9 of pgpMemoryMgr.c
c2f873 ¤   if ( IsntNull( *userPtr ) )
74c7a1 ¤   {
c3a1e8 ¤   ¤   DataHeader *¤   header¤ = UserBlockToHeader( *userPtr );
24bd68 ¤   ¤   PGPSize¤¤   ¤   oldRequestSize¤ = header->requestSize;
3d1b52 ¤   ¤
e795ad ¤   ¤   sRemoveFromLeaksList( mgr, header );
9087c7 ¤   ¤   ¤
6723a1 ¤   ¤   if ( header->secureAlloc )
4f5b34 ¤   ¤   {
5ce973 ¤   ¤   ¤   AssertBlockValid( *userPtr );
077d13 ¤   ¤   ¤   err = sSecureMemoryReallocProc( mgr,
7d0347 ¤   ¤   ¤   ¤   ¤   ¤   (void **) &header,
13c969 ¤   ¤   ¤   ¤   ¤   ¤   kRealHeaderSize + requestSize,
b6e9cb ¤   ¤   ¤   ¤   ¤   ¤   flags,
17c804 ¤   ¤   ¤   ¤   ¤   ¤   kRealHeaderSize + header->requestSize );
0587c7 ¤   ¤   ¤
aa0fe4 ¤   ¤   }
970e1d ¤   ¤   else
a85b34 ¤   ¤   {
d4e973 ¤   ¤   ¤   AssertBlockValid( *userPtr );
7dad29 ¤   ¤   ¤   err = (*(mgr->reallocProc))( mgr, mgr->customValue,
4b0347 ¤   ¤   ¤   ¤   ¤   ¤   (void **) &header,
bdc969 ¤   ¤   ¤   ¤   ¤   ¤   kRealHeaderSize + requestSize,
f5e9cb ¤   ¤   ¤   ¤   ¤   ¤   flags,
cfc804 ¤   ¤   ¤   ¤   ¤   ¤   kRealHeaderSize + header->requestSize );
150fe4 ¤   ¤   }
0c1b52 ¤   ¤
9fe5dd ¤   ¤   sAddToLeaksList( mgr, header );
861b52 ¤   ¤
607d98 ¤   ¤   if ( IsntPGPError( err ) )
555b34 ¤   ¤   {
a64360 ¤   ¤   ¤   *userPtr¤   = HeaderToUserBlock( header );
e8d105 ¤   ¤   ¤   header->requestSize¤= requestSize;
45e973 ¤   ¤   ¤   AssertBlockValid( *userPtr );
d00fe4 ¤   ¤   }
d01b52 ¤   ¤
c11b52 ¤   ¤
f8e12e ¤   ¤   if ( IsntPGPError( err ) && requestSize > oldRequestSize )
c05b34 ¤   ¤   {
d7184a ¤   ¤   ¤   if ( (flags & kPGPMemoryMgrFlags_Clear ) != 0 )
cef776 ¤   ¤   ¤   {
b219ba ¤   ¤   ¤   ¤   pgpClearMemory( ((char *)(*userPtr)) + oldRequestSize,
11248c ¤   ¤   ¤   ¤   ¤   requestSize - oldRequestSize );
5fa3a6 ¤   ¤   ¤   }
d6bb8c ¤   ¤   ¤   else
4ff776 ¤   ¤   ¤   {
7dd92d ¤   #if PGP_DEBUG
2d3f5b ¤   ¤   ¤   ¤   /* clear all newly allocated data to garbage */
ed4468 ¤   ¤   ¤   ¤   pgpDebugWhackMemory( ((char *)(*userPtr)) + oldRequestSize,
80248c ¤   ¤   ¤   ¤   ¤   requestSize - oldRequestSize );
6bb7ec ¤   #endif
69a3a6 ¤   ¤   ¤   }
a40fe4 ¤   ¤   }
899371 ¤   }
dd0e24 ¤   else
bbc7a1 ¤   {
0f99ec ¤   ¤   /* allocate a brand-new block */
2df1db ¤   ¤   *userPtr¤   = PGPNewData( mgr, requestSize, flags );
3df744 ¤   ¤   if ( IsNull( *userPtr ) )
7f5b34 ¤   ¤   {
02124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
f20fe4 ¤   ¤   }
799371 ¤   }
8867c5 ¤
d6deb7 ¤   return( err );
e6efe6 }
e2af5a
baaf5a
4f0335 /*____________________________________________________________________________
2e7cd2 ¤   Free a block of memory, whether secure or not.
88f7f7 ____________________________________________________________________________*/
2cc744 ¤   PGPError
--b53f 000bc317fe0401000cb Page 10 of pgpMemoryMgr.c
732244 PGPFreeData( void * allocation )
3cbb36 {
ba9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
a8423d ¤   PGPMemoryMgrRef¤mgr¤= NULL;
1dc1bf ¤   DataHeader *¤   header;
85a422 ¤   PGPSize¤¤   ¤   allocationSize;
5d67c5 ¤
534575 ¤   PGPValidatePtr( allocation );
f74bda ¤   header¤ = UserBlockToHeader( allocation );
f28048 ¤   PGPValidateParam( sDataHeaderIsValid( header ) );
ad67c5 ¤
87d73f ¤   mgr¤¤   ¤   ¤   = header->mgr;
727e65 ¤   allocationSize¤ = kRealHeaderSize + header->requestSize;
ec67c5 ¤
5c9315 ¤   sRemoveFromLeaksList( mgr, header );
b767c5 ¤
34afde ¤   if ( header->secureAlloc )
63c7a1 ¤   {
413fc7 ¤   ¤   pgpClearMemory( allocation, header->requestSize );
291b52 ¤   ¤
bb48d4 ¤   ¤   err¤= (*(mgr->secureDeallocProc))(
ae53b0 ¤   ¤   ¤   ¤   ¤   mgr, mgr->customValue,
e47aea ¤   ¤   ¤   ¤   ¤   header,
6c8660 ¤   ¤   ¤   ¤   ¤   allocationSize,
2b861a ¤   ¤   ¤   ¤   ¤   (PGPBoolean)header->nonPageable );
3d9371 ¤   }
ef0e24 ¤   else
f6c7a1 ¤   {
aa0eb8 ¤   ¤   pgpDebugWhackMemory( header, allocationSize );
bb1b52 ¤   ¤
f91e7c ¤   ¤   err¤= (*(mgr->deallocProc))(
3953b0 ¤   ¤   ¤   ¤   ¤   mgr, mgr->customValue,
207aea ¤   ¤   ¤   ¤   ¤   header,
dd0250 ¤   ¤   ¤   ¤   ¤   allocationSize );
0a9371 ¤   }
2e67c5 ¤
75deb7 ¤   return( err );
d9efe6 }
59af5a
d0af5a
11af5a
cd59fc ¤   void *
c27328 PGPNewSecureData(
125f6a ¤   PGPMemoryMgrRef ¤   mgr,
5dcb76 ¤   PGPSize ¤   ¤   ¤   requestSize,
0ffd00 ¤   PGPMemoryMgrFlags¤  flags )
04bb36 {
b8a37d ¤   void *¤ ¤   allocation¤ ¤   = NULL;
afc267 ¤   PGPSize¤¤   allocationSize¤ = requestSize;
6ed826 ¤   PGPBoolean¤ isNonPageable;
2c67c5 ¤
4f0c20 ¤   allocationSize¤ += kRealHeaderSize;
8567c5 ¤
60f42d ¤   if( PGPMemoryMgrIsValid( mgr ) )
7ac7a1 ¤   {
8c66dc ¤   ¤   allocation = (*mgr->secureAllocProc)( mgr, mgr->customValue,
0c100a ¤   ¤   ¤   ¤   ¤   ¤   allocationSize, flags, &isNonPageable );
d39371 ¤   }
f367c5 ¤
69f2e5 ¤   if ( IsntNull( allocation ) )
2ec7a1 ¤   {
06c1a7 ¤   ¤   DataHeader *¤   header¤ = NULL;
e667c5 ¤
184828 ¤   ¤   if ( (flags & kPGPMemoryMgrFlags_Clear ) != 0)
9d5b34 ¤   ¤   {
0ed38f ¤   ¤   ¤   pgpClearMemory( allocation, allocationSize );
3f0fe4 ¤   ¤   }
690e1d ¤   ¤   else
695b34 ¤   ¤   {
f1e137 ¤   ¤   ¤   pgpDebugWhackMemory( allocation, allocationSize );
300fe4 ¤   ¤   }
bc1b52 ¤   ¤
--b581 000eb4187fa401000cb Page 11 of pgpMemoryMgr.c
e3d9a8 ¤   ¤   header¤ = (DataHeader *)allocation;
1043e1 ¤   ¤   sInitDataHeader( mgr, requestSize, header );
ea088b ¤   ¤   header->secureAlloc¤= TRUE;
6b619d ¤   ¤   header->nonPageable¤= isNonPageable;
5e1b52 ¤   ¤
f1cb82 ¤   ¤   allocation¤ ¤   = HeaderToUserBlock( allocation );
6d5b75 ¤   ¤   AssertBlockValid( allocation );
e71b52 ¤   ¤
c0e5dd ¤   ¤   sAddToLeaksList( mgr, header );
fb9371 ¤   }
dcaf5a
8eec77 ¤   return( allocation );
d7efe6 }
f6af5a
e0af5a
3e27b7 ¤   PGPFlags
d8e560 PGPGetMemoryMgrDataInfo( void *allocation )
80bb36 {
334c09 ¤   PGPFlags¤   ¤   flags¤  = 0;
0bc1bf ¤   DataHeader *¤   header;
6667c5 ¤
737a44 ¤   if ( IsNull( allocation ) )
91abea ¤   ¤   return( 0 );
221b52 ¤   ¤
594bda ¤   header¤ = UserBlockToHeader( allocation );
a697d8 ¤   if ( sDataHeaderIsValid( header ) )
90c7a1 ¤   {
e00adf ¤   ¤   flags¤  |= kPGPMemoryMgrBlockInfo_Valid;
d71b52 ¤   ¤
f923a1 ¤   ¤   if ( header->secureAlloc )
359d7c ¤   ¤   ¤   flags¤  |= kPGPMemoryMgrBlockInfo_Secure;
1f87c7 ¤   ¤   ¤
880ea1 ¤   ¤   if ( header->nonPageable )
46e8d8 ¤   ¤   ¤   flags¤  |= kPGPMemoryMgrBlockInfo_NonPageable;
d29371 ¤   }
e7dd31 ¤   return( flags );
9eefe6 }
09af5a
7d35fc typedef struct MemoryMgrInfo
b9bb36 {
0ce61e ¤   struct MemoryMgrInfo¤   *next;
0cf36f ¤   PGPMemoryMgrRef¤¤   ¤   mgr;
5caf5a
24e627 } MemoryMgrInfo;
9faf5a
ba18c4 static PGPMemoryMgrRef¤ sDefaultMemoryMgr ¤ ¤   = kInvalidPGPMemoryMgrRef;
c7d764 static MemoryMgrInfo¤   *sMemoryMgrList¤¤   ¤   = NULL;
2387a7 static PGPRMWOLock¤ ¤   sMemoryMgrListLock;
beaf5a
ad5947 ¤   PGPMemoryMgrRef
20a944 PGPGetDefaultMemoryMgr(void)
0bbb36 {
b1bfd9 ¤   PGPMemoryMgrRef¤mgr;
6467c5 ¤
074a75 ¤   if( IsntNull( sMemoryMgrList ) )
dfc7a1 ¤   {
d51b17 ¤   ¤   /*
fb02ad ¤   ¤   ** If the list is non-null, then we have a mgr. We need to use a RMWO
a65a59 ¤   ¤   ** lock because this is a global list
b15c12 ¤   ¤   */
c11b52 ¤   ¤
cb57ad ¤   ¤   PGPRMWOLockStartReading( &sMemoryMgrListLock );
8a40e6 ¤   ¤   ¤   mgr = sDefaultMemoryMgr;
a206e4 ¤   ¤   PGPRMWOLockStopReading( &sMemoryMgrListLock );
a89371 ¤   }
480e24 ¤   else
62c7a1 ¤   {
97d93d ¤   ¤   mgr = kInvalidPGPMemoryMgrRef;
4e9371 ¤   }
a967c5 ¤
6e566c ¤   return( mgr );
ebefe6 }
--4a52 000c082a28c401000cb Page 12 of pgpMemoryMgr.c
e0af5a
01c744 ¤   PGPError
c69f4c PGPSetDefaultMemoryMgr(PGPMemoryMgrRef memoryMgr)
abbb36 {
c6a49b ¤   PGPError¤   err ¤   ¤   ¤   = kPGPError_NoErr;
063a8d ¤   PGPBoolean¤ foundMemoryMgr¤ = FALSE;
f167c5 ¤
f3a127 ¤   PGPValidateParam( PGPMemoryMgrRefIsValid( memoryMgr ) );
cfaf5a
1cdcf6 ¤   if( IsNull( sMemoryMgrList ) )
95c7a1 ¤   {
8c1b17 ¤   ¤   /*
0d7a31 ¤   ¤   ** If there is no list, initialize the RMWO lock. This presents
d03594 ¤   ¤   ** a small window where the lock could get initialized twice,
2cdeb9 ¤   ¤   ** however this is not a call likely to introduce race conditions.
4d5c12 ¤   ¤   */
cb67c5 ¤
146e31 ¤   ¤   InitializePGPRMWOLock( &sMemoryMgrListLock );
b49371 ¤   }
3baf5a
1d3cbe ¤   PGPRMWOLockStartWriting( &sMemoryMgrListLock );
0baf5a
6d4a75 ¤   if( IsntNull( sMemoryMgrList ) )
52c7a1 ¤   {
574a55 ¤   ¤   MemoryMgrInfo¤  *cur;
c01b52 ¤   ¤
a31b17 ¤   ¤   /*
1133bd ¤   ¤   ** Check to see if this memory mgr is already in our list and use
087fd7 ¤   ¤   ** it if it is
8e5c12 ¤   ¤   */
be1b52 ¤   ¤
fe2429 ¤   ¤   cur = sMemoryMgrList;
eb9cf9 ¤   ¤   while( IsntNull( cur ) )
d45b34 ¤   ¤   {
c0bfcc ¤   ¤   ¤   if( cur->mgr == memoryMgr )
19f776 ¤   ¤   ¤   {
bd5a3e ¤   ¤   ¤   ¤   foundMemoryMgr = TRUE;
ecf622 ¤   ¤   ¤   ¤   break;
13a3a6 ¤   ¤   ¤   }
2087c7 ¤   ¤   ¤
4c7495 ¤   ¤   ¤   cur = cur->next;
db0fe4 ¤   ¤   }
539371 ¤   }
cdaf5a
41e8eb ¤   if( ! foundMemoryMgr )
a9c7a1 ¤   {
888e2f ¤   ¤   MemoryMgrInfo¤  *info;
711b52 ¤   ¤
a0589b ¤   ¤   info = (MemoryMgrInfo *) PGPNewData( memoryMgr, sizeof( *info ), 0 );
e21802 ¤   ¤   if( IsntNull( info ) )
d75b34 ¤   ¤   {
0aa738 ¤   ¤   ¤   info->mgr = memoryMgr;
3c87c7 ¤   ¤   ¤
55d919 ¤   ¤   ¤   info->next¤ ¤   = sMemoryMgrList;
00b2f0 ¤   ¤   ¤   sMemoryMgrList¤ = info;
e50fe4 ¤   ¤   }
ba0e1d ¤   ¤   else
485b34 ¤   ¤   {
32b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
d20fe4 ¤   ¤   }
cf9371 ¤   }
ffaf5a
6db1f0 ¤   if( IsntPGPError( err ) )
ee7545 ¤   ¤   sDefaultMemoryMgr = memoryMgr;
321b52 ¤   ¤
0a297c ¤   PGPRMWOLockStopWriting( &sMemoryMgrListLock );
4d67c5 ¤
82deb7 ¤   return( err );
e5efe6 }
94af5a
676d52 ¤   void
c0b345 pgpFreeDefaultMemoryMgrList(void)
--3b8b 0006b436e64401000cb Page 13 of pgpMemoryMgr.c
2cbb36 {
604a75 ¤   if( IsntNull( sMemoryMgrList ) )
47c7a1 ¤   {
974a55 ¤   ¤   MemoryMgrInfo¤  *cur;
c2af5a
476912 ¤   ¤   PGPRMWOLockStartWriting( &sMemoryMgrListLock );
12af5a
912429 ¤   ¤   cur = sMemoryMgrList;
269cf9 ¤   ¤   while( IsntNull( cur ) )
fe5b34 ¤   ¤   {
5698bd ¤   ¤   ¤   MemoryMgrInfo¤  *next;
ea30d2 ¤   ¤   ¤   PGPMemoryMgrRef¤mgr;
2987c7 ¤   ¤   ¤
27c4f0 ¤   ¤   ¤   next ¤  = cur->next;
a168a2 ¤   ¤   ¤   mgr¤¤   = cur->mgr;
2887c7 ¤   ¤   ¤
83509f ¤   ¤   ¤   PGPFreeData( cur );
559fed ¤   ¤   ¤   PGPFreeMemoryMgr( mgr );
2987c7 ¤   ¤   ¤
7475ba ¤   ¤   ¤   cur = next;
cc0fe4 ¤   ¤   }
eb1b52 ¤   ¤
e001a8 ¤   ¤   sMemoryMgrList = NULL;
631b52 ¤   ¤
c2385b ¤   ¤   PGPRMWOLockStopWriting( &sMemoryMgrListLock );
f66f0a ¤   ¤   DeletePGPRMWOLock( &sMemoryMgrListLock );
a19371 ¤   }
3fefe6 }
89dede #if TESTING
23af5a
822eea /* test reallocation, then dispose of the ptr */
ca33c8 ¤   static void
092afe sTestUsingPtr(
536740 ¤   PGPMemoryMgrRef¤mgr,
3cf23a ¤   void *¤ ¤   ¤   data )
33bb36 {
229372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
76af5a
c3b076 ¤   (void)mgr;
9fd67f ¤   err¤= PGPReallocData( mgr, &data, 20000, 0 );
5c8c1a ¤   pgpAssertNoErr( err );
4247d3 ¤   err¤= PGPReallocData( mgr, &data, 500, 0 );
8a8c1a ¤   pgpAssertNoErr( err );
b8b99a ¤   err¤= PGPReallocData( mgr, &data, 0, 0 );
ac8c1a ¤   pgpAssertNoErr( err );
6557c0 ¤   err¤= PGPReallocData( mgr, &data, 20001, 0 );
6f8c1a ¤   pgpAssertNoErr( err );
4267c5 ¤
d2be66 ¤   PGPFreeData( data );
93efe6 }
56af5a
3f33c8 ¤   static void
36a5da sTestMultiAllocations( PGPMemoryMgrRef¤ mgr)
dcbb36 {
4e1c75 #define kNumTestPtrs¤   50
809bf8 ¤   void *¤ ¤   plain[ kNumTestPtrs ];
723836 ¤   void *¤ ¤   secure[ kNumTestPtrs ];
07e18b ¤   PGPUInt32¤  idx;
9c23ee ¤   void *¤ ¤   temp;
4226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a267c5 ¤
955f15 ¤   for( idx = 0; idx < kNumTestPtrs; ++idx )
55c7a1 ¤   {
0ea3f1 ¤   ¤   PGPSize¤¤   ¤   ptrSize;
28e30d ¤   ¤   PGPFlags¤   ¤   flags;
8c1b52 ¤   ¤
34838f ¤   ¤   ptrSize¤= idx * 17;
81d909 ¤   ¤   plain[ idx ]¤   = PGPNewData( mgr, ptrSize, 0);
2b5a49 ¤   ¤   if ( IsntNull( plain[ idx ] ) )
965b34 ¤   ¤   {
e54e54 ¤   ¤   ¤   flags¤  = PGPGetMemoryMgrDataInfo( plain[ idx ] );
6b3220 ¤   ¤   ¤   pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Valid ) != 0 );
--41b3 000851ffd98401000cb Page 14 of pgpMemoryMgr.c
d3e774 ¤   ¤   ¤   pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Secure ) == 0 );
0b0bef ¤   ¤   ¤   pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_NonPageable ) == 0 );
5c0fe4 ¤   ¤   }
d11b52 ¤   ¤
36cdbb ¤   ¤   secure[ idx ]¤  = PGPNewSecureData( mgr, ptrSize, 0 );
9d50d8 ¤   ¤   if ( IsntNull( secure[ idx ] ) )
115b34 ¤   ¤   {
3c6b4c ¤   ¤   ¤   flags¤  = PGPGetMemoryMgrDataInfo( secure[ idx ] );
903220 ¤   ¤   ¤   pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Valid ) != 0 );
bd876e ¤   ¤   ¤   pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Secure ) != 0 );
ad0fe4 ¤   ¤   }
639371 ¤   }
4367c5 ¤
f9862f ¤   /* free even numbered items */
43ba1b ¤   for( idx = 0; idx < kNumTestPtrs; idx += 2 )
5ec7a1 ¤   {
142780 ¤   ¤   PGPFreeData( plain[ idx ] );
adfb8c ¤   ¤   PGPFreeData( secure[ idx ] );
1b9371 ¤   }
b967c5 ¤
de47e7 ¤   /* free odd numbered items */
5bebc6 ¤   for( idx = 1; idx < kNumTestPtrs; idx += 2 )
04c7a1 ¤   {
fb2780 ¤   ¤   PGPFreeData( plain[ idx ] );
a4fb8c ¤   ¤   PGPFreeData( secure[ idx ] );
ad9371 ¤   }
7eaf5a
5500bc ¤   /* test realloc case with NULL ptr */
3ac736 ¤   temp¤   = NULL;
f36718 ¤   err¤= PGPReallocData( mgr, &temp, 1000, 0 );
d28c1a ¤   pgpAssertNoErr( err );
037c23 ¤   pgpAssert( IsntNull( temp ) );
95af5a
d052af ¤   PGPFreeData( temp );
36efe6 }
beaf5a
aeaf5a
d433c8 ¤   static void
339972 sTestMemoryMgr( PGPMemoryMgrRef mgr )
85bb36 {
769e88 ¤   void *¤ ¤   ¤   temp¤   = NULL;
d367c5 ¤
0b22c7 ¤   /* test normal allocation */
312b38 ¤   temp¤   = PGPNewData( mgr, 1000,
bf4ae1 ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
a1ac52 ¤   if ( IsntNull( temp ) )
1ac7a1 ¤   {
cb296b ¤   ¤   sTestUsingPtr( mgr, temp );
fc9371 ¤   }
5ea222 ¤   sTestMultiAllocations( mgr );
71af5a
1f6956 ¤   /* test secure allocation */
281493 ¤   temp¤   = PGPNewSecureData( mgr, 1000,
374ae1 ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
1fac52 ¤   if ( IsntNull( temp ) )
71c7a1 ¤   {
e6296b ¤   ¤   sTestUsingPtr( mgr, temp );
ca9371 ¤   }
69af5a
48a222 ¤   sTestMultiAllocations( mgr );
0b67c5 ¤
2cb1a7 #if MEMORY_MGR_TRACK_LEAKS
1a65bd ¤   pgpAssert( mgr->numAllocations == 0 );
b77454 #endif
31af5a
6fefe6 }
9aaf5a
737454 #endif
e3af5a
d0af5a
7a7e4d /*__Editor_settings____
85af5a
--ab3d 00150c9616f401000cb Page 15 of pgpMemoryMgr.c
734126 ¤   Local Variables:
567b17 ¤   tab-width: 4
430e6c ¤   End:
895f8c ¤   vi: ts=4 sw=4
ab9e9b ¤   vim: si
50d062 _____________________*/
--13aa 0009a7e4879401000cc Page 1 of pgpMemoryMgr.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3a69aa ¤   Contains the definition of the PGPMemoryMgr object.
9aaf5a
9b2d54 ¤   $Id: pgpMemoryMgr.h,v 1.19.12.1 1998/11/12 03:17:57 heller Exp $
1af7f7 ____________________________________________________________________________*/
68af5a
63e69e #ifndef Included_pgpMemoryMgr_h¤/* [ */
7941d1 #define Included_pgpMemoryMgr_h
1daf5a
c0af5a
bfc5d5 #include "pgpBase.h"
48af5a
940335 /*____________________________________________________________________________
7ea3ea ¤   Mini-tutorial:
2a67c5 ¤
2b816d ¤   A PGPMemoryMgr is an object which implements memory management, including
4b3fde ¤   allocation, reallocation, deallocation, and secure versions of the same.
9567c5 ¤
a7e409 ¤   *** Using it ***
a51f14 ¤   A typical sequence of calls is as follows:
b49750 ¤   ¤   PGPNewMemoryMgr
cff0f6 ¤   ¤   ...
79051f ¤   ¤   PGPNewData or PGPNewSecureData
2c7ec8 ¤   ¤   PGPFreeData
16f0f6 ¤   ¤   ...
173671 ¤   ¤   PGPFreeMemoryMgr
2167c5 ¤
ccc254 ¤   Typically, a program will create one PGPMemoryMgr per thread at
d18599 ¤   thread creation time and use that memory mgr until the thread dies.
cad95d ¤   Generally, an individual PGPMemoryMgr instance is not thread-safe;
7fa18d ¤   you must either synchronize or use one PGPMemoryMgr per thread.
d467c5 ¤
a167c5 ¤
3a3b93 ¤   *** Custom Allocators ***
8667c5 ¤
32b93f ¤   Default allocators are supplied, but the client can create a custom
fa1b6e ¤   PGPMemoryMgr using PGPNewMemoryMgrCustom() which uses client-supplied
b8d17f ¤   routines.
d140e2 ¤   Custom routines need only concern themselves with the actual
89a8f2 ¤   allocation and deallocation.
d5ac52 ¤   The following should be kept in mind for user supplied routines:
fc2852 ¤   ¤   - they can ignore the allocation flags passed
4b3cb9 ¤   ¤   - leaks, memory clearing, etc is done by the PGPMemoryMgr
844a02 ¤   ¤   - secure allocator must set 'isNonPageable' to TRUE only if the
50b8b1 ¤   ¤   memory really can't be paged.
0c4210 ¤   ¤   - the user value is not interpreted by the PGPMemoryMgr. Typically,
8a9856 ¤   ¤   it would be a pointer to some data the allocation routines use
afd05c ¤   ¤   to store state.
3967c5 ¤
eb67c5 ¤
935aa1 ¤   *** Secure memory allocation ***
9167c5 ¤
92e027 ¤   Blocks can be allocated as "Secure" blocks. ·Secure blocks are guaranteed
32c48b ¤   to be wiped when they are deallocated. ·Additionally, if the operating
4765b5 ¤   system and the current conditions allow, the block will be allocated
7d4477 ¤   in non-pageable memory. ·You can determine the attributes of a block using
a159a3 ¤   PGPGetMemoryMgrDataInfo().
a867c5 ¤
1f67c5 ¤
9ee7f4 ¤   *** Leaks tracking ***
1c67c5 ¤
870ddd ¤   Leaks tracking is implemented when debugging is on,
eb86ec ¤   but currently reporting is limited to reporting the number of leaks
1b929e ¤   outstanding when the PGPMemoryMgr is disposed.
9b67c5 ¤
0e67c5 ¤
1741a6 ¤   *** Debugging ***
0367c5 ¤
9a2e08 ¤   For debugging purposes, blocks may be larger in debug mode to accomodate
--bdb6 000f4eb0089401000cc Page 2 of pgpMemoryMgr.h
50b098 ¤   various schemes to detect stray pointers, etc.
b3f7f7 ____________________________________________________________________________*/
33af5a
52af5a
16fa23 #if PRAGMA_ALIGN_SUPPORTED
aaaf46 #pragma options align=mac68k
467454 #endif
e4af5a
2a4521 enum·
5cbb36 {
fe0594 ¤   kPGPMemoryMgrFlags_None¤¤   =¤  0,
6eaea9 ¤   kPGPMemoryMgrFlags_Clear¤   =¤  1
4982f7 };
eaaf5a
a8f9ff typedef PGPFlags¤   PGPMemoryMgrFlags;
a9af5a
b12891 typedef struct PGPMemoryMgr¤PGPMemoryMgr;
164122 typedef PGPMemoryMgr¤   *¤  PGPMemoryMgrRef;
aeaf5a
ff4cd3 #define¤kInvalidPGPMemoryMgrRef¤¤   ¤   ((PGPMemoryMgrRef) NULL)
e44e32 #define PGPMemoryMgrRefIsValid(ref)¤¤   ((ref) != kInvalidPGPMemoryMgrRef)
82af5a
1f049f typedef¤void¤   *(*PGPMemoryMgrAllocationProc)( PGPMemoryMgrRef mgr,
ab543f ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
81bd23 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize requestSize, PGPMemoryMgrFlags flags );
acaf5a
9c7db7 /* realloc not be implemented using PGPNewData() */
0d8cbf typedef¤PGPError (*PGPMemoryMgrReallocationProc)( PGPMemoryMgrRef mgr,
d5543f ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
07e149 ¤   ¤   ¤   ¤   ¤   ¤   void **allocation, PGPSize newAllocationSize,
1d5324 ¤   ¤   ¤   ¤   ¤   ¤   PGPMemoryMgrFlags flags, PGPSize existingSize );
0caf5a
894b83 typedef¤PGPError (*PGPMemoryMgrDeallocationProc)( PGPMemoryMgrRef mgr,
02543f ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
365838 ¤   ¤   ¤   ¤   ¤   ¤   void *allocation, PGPSize allocationSize );
5caf5a
a1af5a
07af5a
2fc115 typedef¤void¤   *(*PGPMemoryMgrSecureAllocationProc)( PGPMemoryMgrRef mgr,
6b543f ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
3cfe1d ¤   ¤   ¤   ¤   ¤   ¤   PGPSize requestSize, PGPMemoryMgrFlags flags,
01a3cb ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *isNonPageable );
4c94aa ¤   ¤   ¤   ¤   ¤   ¤
ddaf5a
821c91 /* deallocation proc need not clear the memory upon deallocation since
586c41 ¤   PGPFreeData() does it automatically */
9116bf typedef¤PGPError (*PGPMemoryMgrSecureDeallocationProc)( PGPMemoryMgrRef mgr,
a8543f ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
261448 ¤   ¤   ¤   ¤   ¤   ¤   void *allocation, PGPSize allocationSize,
a467ba ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ wasLocked );
afaf5a
f2af5a
0f8873 typedef struct PGPNewMemoryMgrStruct
efbb36 {
fd092a ¤   /* sizeofStruct must be inited to sizeof( PGPNewMemoryMgrStruct ) */
a946cb ¤   PGPUInt32¤  ¤   sizeofStruct;
c455b8 ¤   PGPFlags¤   ¤   reservedFlags;
3967c5 ¤
32961c ¤   PGPMemoryMgrAllocationProc¤ ¤   allocProc;
2d7cbd ¤   PGPMemoryMgrReallocationProc¤   reallocProc;
4694ac ¤   PGPMemoryMgrDeallocationProc¤   deallocProc;
6f67c5 ¤
5a9b78 ¤   PGPMemoryMgrSecureAllocationProc¤   ¤   secureAllocProc;
88995d ¤   void *¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   reserved;¤  /* MUST be zeroed */
aab2da ¤   PGPMemoryMgrSecureDeallocationProc¤ ¤   secureDeallocProc;
bc67c5 ¤
e64600 ¤   PGPUserValue¤   ¤   ¤   ¤   ¤   customValue;
353578 ¤   void *¤ ¤   ¤   ¤   ¤   ¤   ¤   pad[ 8 ];¤  /* MUST be zeroed */
60b730 } PGPNewMemoryMgrStruct;
f7af5a
f599c6 PGP_BEGIN_C_DECLARATIONS
f4cbcf #if PRAGMA_IMPORT_SUPPORTED
--dade 0003910c712401000cc Page 3 of pgpMemoryMgr.h
06b981 #pragma import on
ee7454 #endif
ebaf5a
76af5a
980335 /*____________________________________________________________________________
d64ce0 ¤   Memory Mgr routines
dbf7f7 ____________________________________________________________________________*/
be2dde PGPBoolean¤ PGPMemoryMgrIsValid( PGPMemoryMgrRef mgr );
ceaf6f #define PGPValidateMemoryMgr( mgr )¤\
88b547 ¤   ¤   PGPValidateParam( PGPMemoryMgrIsValid( mgr ) )
5caf5a
3ec54e PGPError¤   PGPNewMemoryMgr( PGPFlags reserved,
0c5af2 ¤   ¤   ¤   ¤   PGPMemoryMgrRef *newMemoryMgr );
25af5a
d9ddab PGPError¤   PGPNewMemoryMgrCustom( PGPNewMemoryMgrStruct const * custom,
8a5af2 ¤   ¤   ¤   ¤   PGPMemoryMgrRef *newMemoryMgr );
c2af5a
02145a PGPError¤   PGPFreeMemoryMgr( PGPMemoryMgrRef mgr );
33af5a
5a2ed6 PGPError¤   PGPGetMemoryMgrCustomValue( PGPMemoryMgrRef mgr,
06c001 ¤   ¤   ¤   ¤   ¤   PGPUserValue *customValue );
6eb584 PGPError¤   PGPSetMemoryMgrCustomValue( PGPMemoryMgrRef mgr,
09c437 ¤   ¤   ¤   ¤   PGPUserValue customValue );
c2af5a
177000 /* allocate a block of the specified size */
a2dfd6 void * ·¤   PGPNewData( PGPMemoryMgrRef mgr,
bace3a ¤   ¤   ¤   ¤   PGPSize requestSize, PGPMemoryMgrFlags flags );
1a2b85 ¤   ¤   ¤   ¤
54bad4 /* allocate a block of the specified size in non-pageable memory */
31c8ed /* *isSecure is TRUE if the block definitely can't be paged */
3cd7cd void * ·¤   PGPNewSecureData( PGPMemoryMgrRef mgr,
f0ce3a ¤   ¤   ¤   ¤   PGPSize requestSize, PGPMemoryMgrFlags flags );
f7af5a
ecc026 /* properly reallocs secure or non-secure blocks */
7bcfda /* WARNING: the block may move, even if its size is being reduced */
6ef1e8 PGPError ·¤ PGPReallocData( PGPMemoryMgrRef mgr,
17f46a ¤   ¤   ¤   ¤   ¤   void **allocation, PGPSize newAllocationSize,
ba18d7 ¤   ¤   ¤   ¤   ¤   PGPMemoryMgrFlags flags );
3eae30 ¤   ¤   ¤   ¤   ¤
328206 /* properly frees secure or non-secure blocks */
e883c5 PGPError ¤  PGPFreeData( void *allocation );
14af5a
2daf5a
ed0335 /*____________________________________________________________________________
339c6f ¤   Block Info:
cbaf61 ¤   ¤   kPGPMemoryMgrBlockInfo_Valid¤   ¤   it's a valid block
832235 ¤   ¤   kPGPMemoryMgrBlockInfo_Secure¤  ¤   block is a secure allocation
c823a9 ¤   ¤   kPGPMemoryMgrBlockInfo_NonPageable¤ block cannot be paged by VM
6c1b52 ¤   ¤
305b37 ¤   Secure blocks are always wiped before being disposed,
1215bf ¤   but may or may not be pageable, depending on the OS facilities. ·Some
c42a0c ¤   OSs may not provide the ability to make blocks non-pageable.
0f67c5 ¤
f645d5 ¤   You should check these flags if the information matters to you.
7ef7f7 ____________________________________________________________________________*/
288e70 #define kPGPMemoryMgrBlockInfo_Valid¤   ¤   ( ((PGPFlags)1) << 0 )
722546 #define kPGPMemoryMgrBlockInfo_Secure¤  ¤   ( ((PGPFlags)1) << 1 )
43d630 #define kPGPMemoryMgrBlockInfo_NonPageable¤ ( ((PGPFlags)1) << 2 )
46b3f8 PGPFlags¤   ¤   PGPGetMemoryMgrDataInfo( void *allocation );
d5af5a
24af5a
460335 /*____________________________________________________________________________
dbb1db ¤   Default memory manager routines:
b3f7f7 ____________________________________________________________________________*/
64af5a
93e59d PGPMemoryMgrRef¤PGPGetDefaultMemoryMgr(void);
b23e59 PGPError¤   ¤   PGPSetDefaultMemoryMgr(PGPMemoryMgrRef memoryMgr);
cbaf5a
ff0335 /*____________________________________________________________________________
0b2559 ¤   Debug-only routines:
3af7f7 ____________________________________________________________________________*/
39e50a /* validates data structures (debug only) */
--f47a 00114a71341401000cc Page 4 of pgpMemoryMgr.h
76f6d0 void¤   ¤   PGPCheckMemoryMgrIntegrity( PGPMemoryMgrRef mgr );
baaf5a
01af5a
29cbcf #if PRAGMA_IMPORT_SUPPORTED
942ced #pragma import reset
ee7454 #endif
0d1254 PGP_END_C_DECLARATIONS
6aaf5a
bbaf5a
a2af5a
ccfa23 #if PRAGMA_ALIGN_SUPPORTED
3f7c46 #pragma options align=reset
597454 #endif
14af5a
7eaf5a
6f8b22 #endif /* ] Included_pgpMemoryMgr_h */
98af5a
6d7e4d /*__Editor_settings____
f0af5a
8c4126 ¤   Local Variables:
6c7b17 ¤   tab-width: 4
940e6c ¤   End:
cc5f8c ¤   vi: ts=4 sw=4
0f9e9b ¤   vim: si
14d062 _____________________*/
--6d39 0008af17918401000cd Page 1 of pgpMemoryMgrMac.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
0d1948 ¤   Mac-specific functions to plug into the PGPMemoryMgr:
699046 ¤   ¤   pgpCreateStandardMemoryMgr
e7b3fc ¤   ¤   pgpDisposeStandardMemoryMgrUserValue
ae67c5 ¤
e900e5 ¤   $Id: pgpMemoryMgrMac.c,v 1.4.12.1 1998/11/12 03:17:58 heller Exp $
92f7f7 ____________________________________________________________________________*/
332b62 #include "pgpPFLErrors.h"
640d08 #include "pgpMem.h"
6aaf5a
b1025a #include "pgpMemoryMgrPriv.h"
7aaf5a
dd8bd8 #include "MacEnvirons.h"
3caf5a
1faf5a
75af5a
0caf5a
7b33c8 ¤   static void
f017a8 sLockMemory(
5e2c65 ¤   void *¤ ¤   ¤   mem,
468dce ¤   PGPSize¤¤   ¤   numBytes )
a2bb36 {
bd7d70 ¤   if ( VirtualMemoryIsOn() ·)
43c7a1 ¤   {
7b72dd ¤   ¤   HoldMemory( mem, numBytes );
d49371 ¤   }
9cefe6 }
89af5a
0e33c8 ¤   static void
89eca3 sUnlockMemory(
f2c601 ¤   void *¤ mem,
e22b70 ¤   PGPSize¤numBytes )
adbb36 {
2a7d70 ¤   if ( VirtualMemoryIsOn() ·)
9dc7a1 ¤   {
f35d04 ¤   ¤   UnholdMemory( mem, numBytes );
469371 ¤   }
61efe6 }
99af5a
adaf5a
80af5a
4caf5a
7d0335 /*____________________________________________________________________________
557d85 ¤   The default memory allocator. Note that memory mgr will be
76ddda ¤   NULL when allocating the memory mgr itself.
e7f7f7 ____________________________________________________________________________*/
7b062a ¤   static void *
14361d sMacMemoryAllocationProc(
e84d00 ¤   PGPMemoryMgrRef¤¤   mgr,
6296f3 ¤   PGPUserValue¤   ¤   userValue,
ca1fee ¤   PGPSize ¤   ¤   ¤   allocationSize,
aefd00 ¤   PGPMemoryMgrFlags¤  flags )
e1bb36 {
205a19 ¤   (void) mgr;
32eec9 ¤   (void) flags;
274d52 ¤   (void) userValue;
68af5a
ddedad ¤   return( NewPtr( allocationSize ) );
efefe6 }
fdaf5a
4daf5a
64af5a
510335 /*____________________________________________________________________________
254e96 ¤   This is the default PFL memory deallocator. Note that mgr will
5cbc08 ¤   be NULL when deallocating the PFLContext structure itself.
e8f7f7 ____________________________________________________________________________*/
7766dd ¤   static PGPError
d8e98b sMacMemoryDeallocationProc(
8a4d00 ¤   PGPMemoryMgrRef¤¤   mgr,
--7203 0006687fc62401000cd Page 2 of pgpMemoryMgrMac.c
7196f3 ¤   PGPUserValue¤   ¤   userValue,
271ff8 ¤   void *¤ ¤   ¤   ¤   allocation,
307691 ¤   PGPSize¤¤   ¤   ¤   allocationSize )
8cbb36 {
065a19 ¤   (void) mgr;
984dfb ¤   (void) allocationSize;
254d52 ¤   (void) userValue;
a8af5a
285ff7 ¤   DisposePtr( (Ptr)allocation );
2967c5 ¤
6a2d68 ¤   return( kPGPError_NoErr );
c3efe6 }
4faf5a
18af5a
3eaf5a
360335 /*____________________________________________________________________________
b6fd28 ¤   This is the default PFL memory reallocator.·
00f7f7 ____________________________________________________________________________*/
c966dd ¤   static PGPError
f71d74 sMacMemoryReallocationProc(
0a4d00 ¤   PGPMemoryMgrRef¤¤   mgr,
6496f3 ¤   PGPUserValue¤   ¤   userValue,
e940a7 ¤   void **¤¤   ¤   ¤   allocation,
668553 ¤   PGPSize ¤   ¤   ¤   newAllocationSize,
c16569 ¤   PGPMemoryMgrFlags¤  flags,
5f0f8e ¤   PGPSize¤¤   ¤   ¤   existingSize )
9abb36 {
ee26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
72930b ¤   Ptr¤¤   ¤   ptr¤= (Ptr)*allocation;
de67c5 ¤
2f1006 ¤   /* we aren't required to support NULL ptr semantics */
a9047a ¤   pgpAssert( IsntNull( *allocation ) );
7167c5 ¤
525a19 ¤   (void) mgr;
faeec9 ¤   (void) flags;
ac4a0f ¤   (void) existingSize;
b64d52 ¤   (void) userValue;
34af5a
76c18c ¤   SetPtrSize( ptr, newAllocationSize );
23c6dd ¤   if ( GetPtrSize( ptr ) != newAllocationSize )
cdc7a1 ¤   {
7f01c8 ¤   ¤   void *¤ newPtr;
8b1b52 ¤   ¤
2cb5c6 ¤   ¤   /* get a new pointer and copy old to it */
ded131 ¤   ¤   newPtr¤ = NewPtr( newAllocationSize );
87287d ¤   ¤   if ( IsntNull( newPtr ) )
f95b34 ¤   ¤   {
679bf8 ¤   ¤   ¤   pgpCopyMemory( ptr, newPtr,
b9b741 ¤   ¤   ¤   ¤   pgpMin( existingSize, newAllocationSize ) );
c3c607 ¤   ¤   ¤   pgpDebugWhackMemory( ptr, existingSize );
641ec3 ¤   ¤   ¤   DisposePtr( ptr );
7f2eb0 ¤   ¤   ¤   ptr¤= (Ptr)newPtr;
3e0fe4 ¤   ¤   }
c50e1d ¤   ¤   else
645b34 ¤   ¤   {
14124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
130fe4 ¤   ¤   }
689371 ¤   }
7267c5 ¤
c2cdcc ¤   *allocation¤= ptr;
dc67c5 ¤
81deb7 ¤   return( err );
68efe6 }
16af5a
9baf5a
6daf5a
6f062a ¤   static void *
5eae21 sMacSecureMemoryAllocationProc(
9e4d00 ¤   PGPMemoryMgrRef¤¤   mgr,
5a96f3 ¤   PGPUserValue¤   ¤   userValue,
aa1fee ¤   PGPSize ¤   ¤   ¤   allocationSize,
666569 ¤   PGPMemoryMgrFlags¤  flags,
--a05d 000e0ba29ec401000cd Page 3 of pgpMemoryMgrMac.c
21b166 ¤   PGPBoolean *¤   ¤   isNonPageable )
f2bb36 {
435a23 ¤   void *¤ ¤   ptr¤= NULL;
8a67c5 ¤
1b9917 ¤   pgpAssert( IsntNull( isNonPageable ) );
4a5a19 ¤   (void) mgr;
9feec9 ¤   (void) flags;
e04d52 ¤   (void) userValue;
cbaf5a
753f7c ¤   *isNonPageable¤ = TRUE;
3e67c5 ¤
64f924 ¤   ptr¤= NewPtrSys( allocationSize );
9b8756 ¤   if ( IsntNull( ptr ) )
46c7a1 ¤   {
92d32f ¤   ¤   sLockMemory( ptr, allocationSize );
9d9371 ¤   }
d467c5 ¤
2f8327 ¤   return( ptr );
3fefe6 }
5caf5a
cdaf5a
81af5a
08af5a
060335 /*____________________________________________________________________________
bd8d86 ¤   The default secure memory deallocator.
8cf7f7 ____________________________________________________________________________*/
de66dd ¤   static PGPError
1dee48 sMacSecureMemoryDeallocationProc(
7e6740 ¤   PGPMemoryMgrRef¤mgr,
5c3298 ¤   PGPUserValue¤   userValue,
1960fa ¤   void *¤ ¤   ¤   allocation,
1b7cbb ¤   PGPSize¤¤   ¤   allocationSize,
2d4be0 ¤   PGPBoolean¤ ¤   wasLocked )
40bb36 {
ca5a19 ¤   (void) mgr;
1e4dfb ¤   (void) allocationSize;
064d52 ¤   (void) userValue;
54af5a
0b81b2 ¤   pgpAssert( wasLocked );
732c11 ¤   if ( wasLocked )
9ec7a1 ¤   {
36c1a8 ¤   ¤   sUnlockMemory( allocation, allocationSize );
de9371 ¤   }
1567c5 ¤
865ff7 ¤   DisposePtr( (Ptr)allocation );
5e67c5 ¤
c42d68 ¤   return( kPGPError_NoErr );
67efe6 }
4daf5a
1faf5a
35af5a
a1c744 ¤   PGPError
38882b pgpCreateStandardMemoryMgr( PGPMemoryMgrRef *newMemoryMgr )
08bb36 {
6a9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
128d13 ¤   PGPNewMemoryMgrStruct¤  custom;
9967c5 ¤
0bab12 ¤   PGPValidatePtr( newMemoryMgr );
428179 ¤   *newMemoryMgr¤  = NULL;
3d67c5 ¤
552528 ¤   pgpClearMemory( &custom, sizeof( custom ) );
1cfc46 ¤   custom.customValue¤ = NULL;
ba67c5 ¤
e692fd ¤   custom.sizeofStruct¤¤   = sizeof( custom );
0c4b85 ¤   custom.allocProc¤   ¤   = sMacMemoryAllocationProc;
89cf2f ¤   custom.reallocProc¤ ¤   = sMacMemoryReallocationProc;
bc47a2 ¤   custom.deallocProc¤ ¤   = sMacMemoryDeallocationProc;
2567c5 ¤
1b3ee8 ¤   custom.secureAllocProc¤ ¤   = sMacSecureMemoryAllocationProc;
aeda2d ¤   custom.secureDeallocProc¤   = sMacSecureMemoryDeallocationProc;
d967c5 ¤
e0cd62 ¤   err¤= PGPNewMemoryMgrCustom( &custom, newMemoryMgr );
--fa2e 00198ec8210401000cd Page 4 of pgpMemoryMgrMac.c
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
40af5a
c6af5a
23af5a
63c744 ¤   PGPError
0060e2 pgpDisposeStandardMemoryMgrUserValue( PGPUserValue userValue )
e5bb36 {
f7d629 ¤   /* we don't maintain any state */
8d9024 ¤   (void)userValue;
a02d68 ¤   return( kPGPError_NoErr );
53efe6 }
1faf5a
bfaf5a
c5af5a
62af5a
c37e4d /*__Editor_settings____
a0af5a
134126 ¤   Local Variables:
007b17 ¤   tab-width: 4
780e6c ¤   End:
dc5f8c ¤   vi: ts=4 sw=4
b99e9b ¤   vim: si
98d062 _____________________*/
--429c 001b1faafad401000ce Page 1 of pgpMemoryMgrPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
bc23b6 ¤   $Id: pgpMemoryMgrPriv.h,v 1.2.12.1 1998/11/12 03:17:58 heller Exp $
40f7f7 ____________________________________________________________________________*/
247f60 #ifndef Included_pgpMemoryMgrPriv_h¤/* [ */
33aa68 #define Included_pgpMemoryMgrPriv_h
3eaf5a
cb6773 #include "pgpMemoryMgr.h"
6baf5a
c699c6 PGP_BEGIN_C_DECLARATIONS
c3af5a
a1af5a
7ce0d0 PGPError¤   pgpCreateStandardMemoryMgr( PGPMemoryMgrRef *newMemoryMgr );
b72499 PGPError¤   pgpDisposeStandardMemoryMgrUserValue( PGPUserValue userValue );
1e0a26 void¤   ¤   pgpFreeDefaultMemoryMgrList(void);
91af5a
1d1254 PGP_END_C_DECLARATIONS
45af5a
aaad39 #endif /* ] Included_pgpMemoryMgrPriv_h */
79af5a
07af5a
017e4d /*__Editor_settings____
5baf5a
954126 ¤   Local Variables:
2b7b17 ¤   tab-width: 4
c20e6c ¤   End:
8f5f8c ¤   vi: ts=4 sw=4
7b9e9b ¤   vim: si
b1d062 _____________________*/
--3f3d 0009c9467c1401000cf Page 1 of pgpMemoryMgrStd.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
e81977 ¤   Generic/Unix functions to plug into the PGPMemoryMgr:
0a9046 ¤   ¤   pgpCreateStandardMemoryMgr
99b3fc ¤   ¤   pgpDisposeStandardMemoryMgrUserValue
aa1b52 ¤   ¤
5b471a ¤   $Id: pgpMemoryMgrStd.c,v 1.6.12.1 1998/11/12 03:17:59 heller Exp $
54f7f7 ____________________________________________________________________________*/
072b62 #include "pgpPFLErrors.h"
350d08 #include "pgpMem.h"
1baf5a
606773 #include "pgpMemoryMgr.h"
9d025a #include "pgpMemoryMgrPriv.h"
78af5a
bf0ccc #if PGP_MACINTOSH
d08bd8 #include "MacEnvirons.h"
2e7454 #endif
88af5a
f7b177 #if 0
97fbc3 #if PGP_MACINTOSH || PGP_WIN32
59d4c9 #error use platform-specific variants
3d7454 #endif
157454 #endif
4eaf5a
7baf5a
260335 /*____________________________________________________________________________
8257cb ¤   IMPORANT NOTE:
0f67c5 ¤
7fb9cb ¤   Even though we provide sLockMemory() and sUnlockMemory() for mac and win32
a4af11 ¤   it is expected that the generic implementation will not be used since·
d902c6 ¤   there are specific implementations for those platforms.
2c67c5 ¤
4df7f7 ____________________________________________________________________________*/
0ac21c #if PGP_MACINTOSH¤  /* [ */
8daf5a
aa33c8 ¤   static void
8117a8 sLockMemory(
c12c65 ¤   void *¤ ¤   ¤   mem,
d4342a ¤   PGPSize¤¤   ¤   numBytes,
9a3c4d ¤   PGPBoolean *¤   isNonPageable )
25bb36 {
213f7c ¤   *isNonPageable¤ = TRUE;
2a67c5 ¤
d47d70 ¤   if ( VirtualMemoryIsOn() ·)
dfc7a1 ¤   {
6e72dd ¤   ¤   HoldMemory( mem, numBytes );
379371 ¤   }
04efe6 }
e5af5a
af33c8 ¤   static void
12eca3 sUnlockMemory(
3e4371 ¤   void *¤ ¤   mem,
14d1ca ¤   PGPSize¤¤   numBytes,
263791 ¤   PGPBoolean¤ nonPageable )
17bb36 {
0a1974 ¤   if ( nonPageable && VirtualMemoryIsOn() ·)
95c7a1 ¤   {
7e5d04 ¤   ¤   UnholdMemory( mem, numBytes );
bf9371 ¤   }
9eefe6 }
baaf5a
ffa12d #elif PGP_WIN32 ¤   /* ] [ */
78af5a
ce2a68 #define WIN32_LEAN_AND_MEAN
2d5655 #include <windows.h>
2daf5a
6d33c8 ¤   static void
de17a8 sLockMemory(
c02c65 ¤   void *¤ ¤   ¤   mem,
9c342a ¤   PGPSize¤¤   ¤   numBytes,
--22ce 000ec8207a1401000cf Page 2 of pgpMemoryMgrStd.c
843c4d ¤   PGPBoolean *¤   isNonPageable )
e7bb36 {
f28897 ¤   *isNonPageable¤ = FALSE;
1ea863 ¤   /* this doesn't actually prevent paging in all cases */
141c5e ¤   VirtualLock ( mem, numBytes );
c9efe6 }
6caf5a
a533c8 ¤   static void
f1eca3 sUnlockMemory(
cc4371 ¤   void *¤ ¤   mem,
5ee27a ¤   PGPSize¤¤   numBytes.
f93791 ¤   PGPBoolean¤ nonPageable )
39bb36 {
e3b5ba ¤   /* we always call VirtualLock() so always call VirtualUnlock() */
390190 ¤   (void)wasLocked;
7267c5 ¤
6fb583 ¤   VirtualUnlock ( mem, numBytes );
2fefe6 }
18af5a
ca5e53 #elif PGP_UNIX ¤/* ] [ */
90af5a
49af5a
6c3c94 /* Code borrowed from Peter Gutmann's cryptlib for secure memory locking */
cbaf5a
5f3278 #if defined( __osf__ )
0f4e45 ··#include <sys/mman.h>
1d5c75 #elif defined( sun )
95ed42 ··#include <sys/types.h>
d84e45 ··#include <sys/mman.h>
9adb21 #else
2d7372 ··int mlock( void *address, size_t length );
32f771 ··int munlock( void *address, size_t length );
1d3e23 #endif /* Unix-variant-specific includes */
18af5a
c10335 /*____________________________________________________________________________
2be254 ¤   Unix version
e9f7f7 ____________________________________________________________________________*/
25af5a
6033c8 ¤   static void
d717a8 sLockMemory(
662c65 ¤   void *¤ ¤   ¤   mem,
01342a ¤   PGPSize¤¤   ¤   numBytes,
963c4d ¤   PGPBoolean *¤   isNonPageable )
7bbb36 {
d69917 ¤   pgpAssert( IsntNull( isNonPageable ) );
d3af5a
a74652 ¤   (void)mem;
e3718f ¤   (void)numBytes;
1cbaa4 ¤   /* mlock call taken from Peter Gutmann's cryptlib */
80dd17 ¤   /* Under many Unix variants the SYSV/POSIX mlock() call can be
f74d90 ¤   ···used, but only by the superuser. ·OSF/1 has mlock(), but
572ca6 ¤   ···this is defined to the nonexistant memlk() so we need to
6e3fe2 ¤   ···special-case it out. ·Aches and PHUX don't even pretend to
0783be ¤   ···have mlock(). ·Many systems also have plock(), but this is
0fae28 ¤   ···pretty crude since it locks all data, and also has various
6a8d44 ¤   ···other shortcomings. ·Finally, PHUX has datalock(), which is
f51250 ¤   ···just a plock() variant */
6f60a1 #if !( defined( __osf__ ) || defined( _AIX ) || defined( __hpux ) || \
fa16da defined( _M_XENIX ) )
380ade ¤   *isNonPageable = (mlock( mem, numBytes ) == 0);
94db21 #else
c70ae8 ¤   *isNonPageable = FALSE;
469e2e #endif /* !( __osf__ || _AIX || __hpux || _M_XENIX ) */
d8af5a
07efe6 }
d4af5a
32af5a
a50335 /*____________________________________________________________________________
71e254 ¤   Unix version
7af7f7 ____________________________________________________________________________*/
d733c8 ¤   static void
ececa3 sUnlockMemory(
--cc73 0008f8f8d22401000cf Page 3 of pgpMemoryMgrStd.c
304371 ¤   void *¤ ¤   mem,
acd1ca ¤   PGPSize¤¤   numBytes,
7d3791 ¤   PGPBoolean¤ nonPageable )
79bb36 {
314652 ¤   (void)mem;
74718f ¤   (void)numBytes;
0d67c5 ¤
b1f96c ¤   if ( nonPageable )
89c7a1 ¤   {
3d8a37 ¤   ¤   (void)munlock( mem, ·numBytes );
d09371 ¤   }
48efe6 }
b7af5a
52af5a
7faf5a
f8db21 #else
aaaf5a
9ab699 #error unknown platform
05af5a
ca3167 #endif¤ /* ] */
14af5a
d4af5a
f3af5a
b2af5a
ea0335 /*____________________________________________________________________________
667d85 ¤   The default memory allocator. Note that memory mgr will be
2addda ¤   NULL when allocating the memory mgr itself.
2ff7f7 ____________________________________________________________________________*/
d0062a ¤   static void *
c8c99a sGenericMemoryAllocationProc(
834d00 ¤   PGPMemoryMgrRef¤¤   mgr,
20f067 ¤   PGPUserValue¤   ¤   customValue,
4f1fee ¤   PGPSize ¤   ¤   ¤   allocationSize,
e0fd00 ¤   PGPMemoryMgrFlags¤  flags )
3dbb36 {
8a5a19 ¤   (void) mgr;
83eec9 ¤   (void) flags;
076207 ¤   (void) customValue;
c1af5a
2158c3 ¤   return( malloc( allocationSize ) );
4befe6 }
28af5a
bbaf5a
e1af5a
a10335 /*____________________________________________________________________________
6e4e96 ¤   This is the default PFL memory deallocator. Note that mgr will
d5bc08 ¤   be NULL when deallocating the PFLContext structure itself.
1ff7f7 ____________________________________________________________________________*/
8b66dd ¤   static PGPError
ec2737 sGenericMemoryDeallocationProc(
f74d00 ¤   PGPMemoryMgrRef¤¤   mgr,
46f067 ¤   PGPUserValue¤   ¤   customValue,
2d1ff8 ¤   void *¤ ¤   ¤   ¤   allocation,
dc7691 ¤   PGPSize¤¤   ¤   ¤   allocationSize )
47bb36 {
8e5a19 ¤   (void) mgr;
e54dfb ¤   (void) allocationSize;
dc6207 ¤   (void) customValue;
c8af5a
a2b283 ¤   free( allocation );
5c67c5 ¤
aa2d68 ¤   return( kPGPError_NoErr );
d3efe6 }
aeaf5a
c0af5a
2c0335 /*____________________________________________________________________________
12e558 ¤   Generic memory reallocator.·
6bf7f7 ____________________________________________________________________________*/
a066dd ¤   static PGPError
f6d3c8 sGenericMemoryReallocationProc(
5a4d00 ¤   PGPMemoryMgrRef¤¤   mgr,
8ff067 ¤   PGPUserValue¤   ¤   customValue,
--7767 000c5671d00401000cf Page 4 of pgpMemoryMgrStd.c
ea40a7 ¤   void **¤¤   ¤   ¤   allocation,
328553 ¤   PGPSize ¤   ¤   ¤   newAllocationSize,
c46569 ¤   PGPMemoryMgrFlags¤  flags,
770f8e ¤   PGPSize¤¤   ¤   ¤   existingSize )
30bb36 {
bb61e0 ¤   PGPError¤   err;
089c47 ¤   void *¤ ¤   newPtr¤ = NULL;
a832d3 ¤   void *¤ ¤   oldPtr¤ = *allocation;
5267c5 ¤
3f5a19 ¤   (void) mgr;
92eec9 ¤   (void) flags;
894a0f ¤   (void) existingSize;
5f6207 ¤   (void) customValue;
ebaf5a
d2ff47 ¤   newPtr = realloc( oldPtr, newAllocationSize );
ba21b6 ¤   if ( IsNull( newPtr ) )
13c7a1 ¤   {
9017a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
af9371 ¤   }
ac0e24 ¤   else
65c7a1 ¤   {
44d87c ¤   ¤   err¤= kPGPError_NoErr;
17d339 ¤   ¤   *allocation¤= newPtr;
a99371 ¤   }
3467c5 ¤
a0deb7 ¤   return( err );
74efe6 }
24af5a
aaaf5a
35af5a
59af5a
6a062a ¤   static void *
a34208 sGenericSecureMemoryAllocationProc(
e54d00 ¤   PGPMemoryMgrRef¤¤   mgr,
84f067 ¤   PGPUserValue¤   ¤   customValue,
1c1fee ¤   PGPSize ¤   ¤   ¤   allocationSize,
3e6569 ¤   PGPMemoryMgrFlags¤  flags,
d6409e ¤   PGPBoolean *¤   ¤   isSecure )
c6bb36 {
8d5a23 ¤   void *¤ ¤   ptr¤= NULL;
8d67c5 ¤
405a19 ¤   (void) mgr;
66eec9 ¤   (void) flags;
886207 ¤   (void) customValue;
adaf5a
dc5c5a ¤   *isSecure¤  = FALSE;
b767c5 ¤
e9da4a ¤   ptr¤= sGenericMemoryAllocationProc( mgr,
3c763f ¤   ¤   ¤   ¤   customValue, allocationSize, flags );
918756 ¤   if ( IsntNull( ptr ) )
8fc7a1 ¤   {
3a4209 ¤   ¤   sLockMemory( ptr, allocationSize, isSecure );
779371 ¤   }
7d67c5 ¤
e88327 ¤   return( ptr );
2fefe6 }
13af5a
8aaf5a
6eaf5a
d3af5a
7b0335 /*____________________________________________________________________________
a7dd63 ¤   Generic secure memory deallocator.
bdf7f7 ____________________________________________________________________________*/
0b66dd ¤   static PGPError
7c3701 sGenericSecureMemoryDeallocationProc(
146740 ¤   PGPMemoryMgrRef¤mgr,
1892b4 ¤   PGPUserValue¤   customValue,
5860fa ¤   void *¤ ¤   ¤   allocation,
c67cbb ¤   PGPSize¤¤   ¤   allocationSize,
494be0 ¤   PGPBoolean¤ ¤   wasLocked )
eebb36 {
c526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
--4561 00102ff8d6b401000cf Page 5 of pgpMemoryMgrStd.c
2a67c5 ¤
3e5a19 ¤   (void) mgr;
c64dfb ¤   (void) allocationSize;
3f6207 ¤   (void) customValue;
3aaf5a
252c11 ¤   if ( wasLocked )
8cc7a1 ¤   {
ec842c ¤   ¤   sUnlockMemory( allocation, allocationSize, wasLocked );
059371 ¤   }
b667c5 ¤
96ac67 ¤   err¤= sGenericMemoryDeallocationProc( mgr, customValue,
131119 ¤   ¤   ¤   ¤   allocation, allocationSize);
1767c5 ¤
6bdeb7 ¤   return( err );
54efe6 }
d4af5a
bcaf5a
b7af5a
abc744 ¤   PGPError
48882b pgpCreateStandardMemoryMgr( PGPMemoryMgrRef *newMemoryMgr )
46bb36 {
739479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
118d13 ¤   PGPNewMemoryMgrStruct¤  custom;
c567c5 ¤
f5ab12 ¤   PGPValidatePtr( newMemoryMgr );
be8179 ¤   *newMemoryMgr¤  = NULL;
f667c5 ¤
352528 ¤   pgpClearMemory( &custom, sizeof( custom ) );
e3fc46 ¤   custom.customValue¤ = NULL;
6b67c5 ¤
9992fd ¤   custom.sizeofStruct¤¤   = sizeof( custom );
e34c1e ¤   custom.allocProc¤   ¤   = sGenericMemoryAllocationProc;
270d48 ¤   custom.reallocProc¤ ¤   = sGenericMemoryReallocationProc;
10bfff ¤   custom.deallocProc¤ ¤   = sGenericMemoryDeallocationProc;
f367c5 ¤
91f8ff ¤   custom.secureAllocProc¤ ¤   = sGenericSecureMemoryAllocationProc;
46d449 ¤   custom.secureDeallocProc¤   = sGenericSecureMemoryDeallocationProc;
6167c5 ¤
a9cd62 ¤   err¤= PGPNewMemoryMgrCustom( &custom, newMemoryMgr );
cb67c5 ¤
21deb7 ¤   return( err );
65efe6 }
0faf5a
84af5a
44c744 ¤   PGPError
e52dcd pgpDisposeStandardMemoryMgrUserValue( PGPUserValue customValue )
0bbb36 {
76d629 ¤   /* we don't maintain any state */
87cb7b ¤   (void)customValue;
cc2d68 ¤   return( kPGPError_NoErr );
bbefe6 }
3daf5a
d9af5a
2d7e4d /*__Editor_settings____
dfaf5a
504126 ¤   Local Variables:
757b17 ¤   tab-width: 4
0c0e6c ¤   End:
d65f8c ¤   vi: ts=4 sw=4
b09e9b ¤   vim: si
02d062 _____________________*/
--664c 0006c79dc4d401000d0 Page 1 of pgpMemoryMgrWin32.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
a592a5 ¤   Win32-specific functions to plug into the PGPMemoryMgr:
6a9046 ¤   ¤   pgpCreateStandardMemoryMgr
76b3fc ¤   ¤   pgpDisposeStandardMemoryMgrUserValue
5067c5 ¤
924322 ¤   $Id: pgpMemoryMgrWin32.c,v 1.12.12.1 1998/11/12 03:18:00 heller Exp $
9af7f7 ____________________________________________________________________________*/
372b62 #include "pgpPFLErrors.h"
d40d08 #include "pgpMem.h"
2caf5a
93025a #include "pgpMemoryMgrPriv.h"
10af5a
69af5a
ebaf5a
be64ae #define INTEGRITY_CHECKS¤   ¤   PGP_DEBUG
6eaf5a
67afb9 #if PGP_WIN32
78af5a
242a68 #define WIN32_LEAN_AND_MEAN
f35655 #include <windows.h>
89af5a
107a5e /* header containing device driver definitions */
0e2a59 #include "pgpMemLockWin32.h"
77af5a
9baf5a
dfaf5a
7a468b /* names of device drivers used for memory locking */
f9dead static const char¤  kPGPMemLockDriver95Name[] = "\\\\.\\PGPMemLock.vxd";
41866c static const char¤  kPGPMemLockDriverNTName[] = "\\\\.\\PGPMEMLOCK";
cdaf5a
22db21 #else
4eaf5a
edddd0 typedef void *¤ HANDLE;
43af5a
8f7454 #endif
75af5a
e9af5a
4e0335 /*____________________________________________________________________________
40a73e ¤   [Secure memory only]
f267c5 ¤
200dce ¤   kPageSize¤  ¤   page size suitable for VM allocation and locking
8966d0 ¤   kMinHeapSize¤   minimum size of heap we'll create
a7c5b7 ¤   kChunkSize¤ ¤   granularity of allocation and alignment value
e9729f ¤   ¤   ¤   ¤   ¤   nothing smaller can be allocated and therefore,
ce0c43 ¤   ¤   ¤   ¤   ¤   every allocation is aligned to this value.
51b72a ¤   kMinLeftoverBytes¤  dont create a free block with fewer bytes than this
72f7f7 ____________________________________________________________________________*/
0caf5a
f0c0e9 #define kPageSize¤  ¤   ¤   ( (PGPSize)4096 )
6be57d #define kMinHeapSizeBytes¤  ( kPageSize * 2 )
93fc89 #define kChunkSize¤ ¤   ¤   ( 32 )
3db5fc #define kMinLeftoverBytes¤  pgpMax( kChunkSize, sizeof( ChunkHeader ) )
1faf5a
b3af5a
e60335 /*____________________________________________________________________________
6fa73e ¤   [Secure memory only]
9467c5 ¤
01984e ¤   Free space is linked together in a list in each heap.
160257 ¤   'numChunks' contains the total size of the block, in chunks, which
333628 ¤   includes the ChunkHeader itself.
08f7f7 ____________________________________________________________________________*/
a04597 typedef struct ChunkHeader
06bb36 {
0d3c66 ¤   struct ChunkHeader *¤   next;
493e7e ¤   struct ChunkHeader *¤   prev;
1106ee ¤   PGPUInt32¤  ¤   ¤   ¤   numChunks;
234636 } ChunkHeader;
7faf5a
6caf5a
--00c3 000c508b778401000d0 Page 2 of pgpMemoryMgrWin32.c
e0af5a
7e0335 /*____________________________________________________________________________
aea73e ¤   [Secure memory only]
ed67c5 ¤
7e9ba6 ¤   A PageHeap keeps a memory heap on a contiguous range of pages.
a06dab ¤   Free space is maintained in a free list; there is no overhead to
084dcf ¤   allocated items other than our chunk size requirement.
0cf7f7 ____________________________________________________________________________*/
532666 typedef struct PageHeap
bfbb36 {
051dd7 ¤   struct PageHeap *¤  next;
4c1fcf ¤   struct PageHeap *¤  prev;
6867c5 ¤
5a2c6c ¤   HANDLE¤ ¤   ¤   hDriver;
4767c5 ¤
763943 ¤   void *¤ ¤   ¤   pages;
3ae017 ¤   PGPUInt32¤  ¤   numPages;
970a37 ¤   PGPBoolean¤ ¤   isNonPageable;
9567c5 ¤
7c310c ¤   PGPUInt32¤  ¤   numFreeChunks;
f867c5 ¤
50f3df ¤   ChunkHeader *¤  freeList;
949953 } PageHeap;
ecaf5a
0a0335 /*____________________________________________________________________________
f0a73e ¤   [Secure memory only]
c867c5 ¤
7964d1 ¤   A pointer to this struct is stored as the customValue of the MemoryMgr.
bef7f7 ____________________________________________________________________________*/
a0c6a9 typedef struct MyData
40bb36 {
1bd55e ¤   /* handle of loaded driver; NULL=>no driver loaded */
62a4a0 ¤   HANDLE¤ ¤   hDriver;
cb67c5 ¤
dafbda ¤   PageHeap *¤ heapList;
ae74e6 ¤   PageHeap *¤ lastHeapUsed;
71908c } MyData;
ceaf5a
61af5a
54af5a
92af5a
7a128e static PageHeap *¤  sCreateHeap( HANDLE hDriver, PGPSize heapSize );
f6392b static void¤¤   ¤   sDisposeHeap( HANDLE hDriver, PageHeap *heap );
70af5a
b5b189 static PageHeap *¤  sCreateAndAddHeap( MyData * myData, PGPSize heapSize );
7980f0 static void¤¤   ¤   sRemoveAndDisposeHeap( MyData *myData, PageHeap *heap );
96ade0 static PGPBoolean¤  sHeapOwnsAllocation( PageHeap const *heap,
19b2b5 ¤   ¤   ¤   ¤   ¤   ¤   void const *allocation );
3c25b7 static PGPBoolean¤  sHeapIsEmpty( PageHeap const *heap );
82af5a
25de4c static void *¤  sAllocateBytes( MyData *myData,
2b0fa9 ¤   ¤   ¤   ¤   ¤   PGPSize requestSize, PGPBoolean *isNonPageable );
93e5c3 static void ¤   sFreeBytes( MyData *myData,
056556 ¤   ¤   ¤   ¤   ¤   void *allocation, PGPSize allocationSize );
edaf5a
9784a7 static void *¤  sHeapAllocateChunks( PageHeap *heap,
3e04df ¤   ¤   ¤   ¤   ¤   PGPUInt32 allocChunks, PGPBoolean *isNonPageable );
a22603 static void¤¤   sHeapFreeChunks( PageHeap *heap,
41b69f ¤   ¤   ¤   ¤   ¤   void *ptr, PGPUInt32 numChunks );
82af5a
25f404 #if INTEGRITY_CHECKS¤   /* [ */
2bd8a9 static void¤¤   sHeapValidate( PageHeap const *heap );
a7db21 #else
61eb89 #define sHeapValidate( heap )¤  ¤   /* nothing */
4a7454 #endif
c0af5a
7f6297 static PGPError¤sInitMyData( MyData *myData );
ec406f static PGPError¤sCleanupMyData( MyData *myData );
f4af5a
c6fd6a static void¤¤   sLockMemory( HANDLE hDriver, void *mem, PGPSize numBytes,
29f0d0 ¤   ¤   ¤   ¤   ¤   PGPBoolean *isNonPageable );
c5781a static void¤¤   sUnlockMemory( HANDLE hDriver, void *mem, PGPSize numBytes );
--2a16 000f246ff93401000d0 Page 3 of pgpMemoryMgrWin32.c
e0af5a
1aaf5a
17af5a
e3062a ¤   static void *
67507a sInternalAlloc( PGPSize numBytes )
dbbb36 {
e2deb3 ¤   void *¤ result¤ = malloc( numBytes );
7167c5 ¤
62e164 ¤   if ( IsntNull( result ) )
19c7a1 ¤   {
450fd4 ¤   ¤   pgpClearMemory( result, numBytes );
859371 ¤   }
8367c5 ¤
594c6e ¤   return( result );
42efe6 }
5caf5a
ce33c8 ¤   static void
c4263e sInternalFree( void *ptr )
f6bb36 {
bb8756 ¤   if ( IsntNull( ptr ) )
c20537 ¤   ¤   free( ptr );
76efe6 }
b5af5a
77af5a
d30335 /*____________________________________________________________________________
fce31e ¤   For non-secure memory allocation, we just use standard malloc/realloc/free
15f7f7 ____________________________________________________________________________*/
86062a ¤   static void *
cff2ae sWin32MemoryAllocationProc(
354d00 ¤   PGPMemoryMgrRef¤¤   mgr,
5af067 ¤   PGPUserValue¤   ¤   customValue,
611fee ¤   PGPSize ¤   ¤   ¤   allocationSize,
5dfd00 ¤   PGPMemoryMgrFlags¤  flags )
15bb36 {
5a5a19 ¤   (void) mgr;
d5eec9 ¤   (void) flags;
6d6207 ¤   (void) customValue;
d458c3 ¤   return( malloc( allocationSize ) );
62efe6 }
78af5a
90af5a
3866dd ¤   static PGPError
a579a5 sWin32MemoryDeallocationProc(
864d00 ¤   PGPMemoryMgrRef¤¤   mgr,
85f067 ¤   PGPUserValue¤   ¤   customValue,
821ff8 ¤   void *¤ ¤   ¤   ¤   allocation,
167691 ¤   PGPSize¤¤   ¤   ¤   allocationSize )
cebb36 {
175a19 ¤   (void) mgr;
104dfb ¤   (void) allocationSize;
3c6207 ¤   (void) customValue;
02b283 ¤   free( allocation );
ce2d68 ¤   return( kPGPError_NoErr );
69efe6 }
a9af5a
26af5a
6466dd ¤   static PGPError
cd8d5a sWin32MemoryReallocationProc(
2c4d00 ¤   PGPMemoryMgrRef¤¤   mgr,
88f067 ¤   PGPUserValue¤   ¤   customValue,
5440a7 ¤   void **¤¤   ¤   ¤   allocation,
eb8553 ¤   PGPSize ¤   ¤   ¤   newAllocationSize,
446569 ¤   PGPMemoryMgrFlags¤  flags,
120f8e ¤   PGPSize¤¤   ¤   ¤   existingSize )
a6bb36 {
7861e0 ¤   PGPError¤   err;
8f32d3 ¤   void *¤ ¤   oldPtr¤ = *allocation;
569c47 ¤   void *¤ ¤   newPtr¤ = NULL;
cd67c5 ¤
3a5a19 ¤   (void) mgr;
61eec9 ¤   (void) flags;
f24a0f ¤   (void) existingSize;
--020e 000a612661d401000d0 Page 4 of pgpMemoryMgrWin32.c
366207 ¤   (void) customValue;
17af5a
01ff47 ¤   newPtr = realloc( oldPtr, newAllocationSize );
4021b6 ¤   if ( IsNull( newPtr ) )
22c7a1 ¤   {
cd17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
5b9371 ¤   }
320e24 ¤   else
b3c7a1 ¤   {
e6d87c ¤   ¤   err¤= kPGPError_NoErr;
f9d339 ¤   ¤   *allocation¤= newPtr;
4d9371 ¤   }
0767c5 ¤
c1deb7 ¤   return( err );
4cefe6 }
dbaf5a
bbaf5a
e1af5a
38af5a
b50335 /*____________________________________________________________________________
212837 ¤   Win32 version
f4af5a
3ca852 ¤   Under Win32 we can lock individual pages or ranges of pages by using
27e3fd ¤   APIs which are available only to device drivers. ·In order to avoid any·
bf20d2 ¤   potential problems derived from locking pages in the process heaps,·
a04fa0 ¤   we restrict ourselves to locking pages which are directly assigned to
c07f7a ¤   us from the OS using the Win32 API function VirtualAlloc. ·Using·
a1f859 ¤   VirtualAlloc we can obtain virtual pages of memory from our process's·
c28430 ¤   private address space and which are outside the process heaps. ·Also,
76c6f4 ¤   VirtualAlloc gives us committed and page-aligned memory, two other·
a7af9c ¤   requirements for pagelocking.
44af5a
e1896a ¤   Memory is allocated with a granularity of 4K bytes (the page size
29e0ef ¤   in Win32).
9ff7f7 ____________________________________________________________________________*/
d9062a ¤   static void *
9a0649 sWin32SecureMemoryAllocationProc(
084d00 ¤   PGPMemoryMgrRef¤¤   mgr,
57eabb ¤   PGPUserValue ¤  ¤   customValue,
631fee ¤   PGPSize ¤   ¤   ¤   allocationSize,
c46569 ¤   PGPMemoryMgrFlags¤  flags,
afb166 ¤   PGPBoolean *¤   ¤   isNonPageable )
0dbb36 {
84cf43 ¤   void *¤ ¤   result;
d515af ¤   MyData *¤   myData¤ = (MyData *)customValue;
8667c5 ¤
985a19 ¤   (void) mgr;
87eec9 ¤   (void) flags;
69af5a
cf8897 ¤   *isNonPageable¤ = FALSE;
fd67c5 ¤
193fed ¤   result¤ = sAllocateBytes( myData, allocationSize, isNonPageable );
bb67c5 ¤
364c6e ¤   return( result );
c8efe6 }
daaf5a
25af5a
df0335 /*____________________________________________________________________________
849630 ¤   Win32 secure memory deallocator.
0bf7f7 ____________________________________________________________________________*/
ca66dd ¤   static PGPError
f56c9f sWin32SecureMemoryDeallocationProc(
e46740 ¤   PGPMemoryMgrRef¤mgr,
6799f7 ¤   PGPUserValue ¤  customValue,
c760fa ¤   void *¤ ¤   ¤   allocation,
2a7cbb ¤   PGPSize¤¤   ¤   allocationSize,
4bb1f4 ¤   PGPBoolean¤ ¤   nonPageable)
90bb36 {
cd15af ¤   MyData *¤   myData¤ = (MyData *)customValue;
cbaf5a
0d5a19 ¤   (void) mgr;
a64dfb ¤   (void) allocationSize;
--6fd9 0006f5bd6e8401000d0 Page 5 of pgpMemoryMgrWin32.c
e643a3 ¤   (void) nonPageable;
5daf5a
1eacfd ¤   sFreeBytes( myData, allocation, allocationSize );
7c67c5 ¤
fc2d68 ¤   return( kPGPError_NoErr );
f2efe6 }
abaf5a
ebaf5a
8daf5a
40af5a
9caf5a
e1af5a
e473ee ¤   static HANDLE
4ab56d sGetMyDriver( void )
5fbb36 {
f8af5a
18a9a6 ¤   HANDLE¤ ¤   ¤   hDriver¤= NULL;
75afb9 #if PGP_WIN32
eb3731 ¤   OSVERSIONINFO¤  osid;
71af5a
6ba9b0 ¤   osid.dwOSVersionInfoSize = sizeof ( osid );
bcdb4c ¤   GetVersionEx ( &osid );
91af5a
d79c9f ¤   /*¤ load correct memory-locking driver on basis of which·
0cf011 ¤   ¤   OS we're running under¤ */
f1c813 ¤   switch ( osid.dwPlatformId ) {
49af5a
1d9e41 ¤   ¤   /* Windows 95 */
cc7ab5 ¤   ¤   case VER_PLATFORM_WIN32_WINDOWS :
a23776 ¤   ¤   ¤   hDriver =·
d6138a ¤   ¤   ¤   ¤   CreateFile (¤   kPGPMemLockDriver95Name,·
0b4bfe ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   GENERIC_READ | GENERIC_WRITE,·
57c118 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,·
631cf9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL,·
1b9ba8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   OPEN_EXISTING,·
351a6f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FILE_FLAG_DELETE_ON_CLOSE,·
6e6424 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL );
121539 //¤ ¤   ¤   pgpFixBeforeShip ("Need to do something if driver load fails");
263e37 ///¤¤   ¤   ¤   pgpAssertMsg ( hDriver != INVALID_HANDLE_VALUE,
76d5a3 ///¤¤   ¤   ¤   ¤   ¤   ¤   ··"Could not load page-locking driver" );·
4d37fc ¤   ¤   ¤   if ( hDriver == INVALID_HANDLE_VALUE )·
58f776 ¤   ¤   ¤   {
74f267 ¤   ¤   ¤   ¤   hDriver = NULL;
b9a3a6 ¤   ¤   ¤   }
5dcdcb ¤   ¤   ¤   break;
73af5a
4bed66 ¤   ¤   /* Windows NT */
d85331 ¤   ¤   case VER_PLATFORM_WIN32_NT :
c23776 ¤   ¤   ¤   hDriver =·
a85260 ¤   ¤   ¤   ¤   CreateFile (¤   kPGPMemLockDriverNTName,
dbdcbd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   GENERIC_READ | GENERIC_WRITE,
5a42d3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
7776b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL,
d1370b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   OPEN_EXISTING,
8ffdba ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FILE_ATTRIBUTE_NORMAL,
4e6424 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL );
2b1539 //¤ ¤   ¤   pgpFixBeforeShip ("Need to do something if driver load fails");
653e37 ///¤¤   ¤   ¤   pgpAssertMsg ( hDriver != INVALID_HANDLE_VALUE,
e1d5a3 ///¤¤   ¤   ¤   ¤   ¤   ¤   ··"Could not load page-locking driver" );·
d837fc ¤   ¤   ¤   if ( hDriver == INVALID_HANDLE_VALUE )·
c1f776 ¤   ¤   ¤   {
b0f267 ¤   ¤   ¤   ¤   hDriver = NULL;
6aa3a6 ¤   ¤   ¤   }
c0cdcb ¤   ¤   ¤   break;
35af5a
0949f1 ¤   ¤   /* all other OSes */
3b3a18 ¤   ¤   default :
4cb773 ¤   ¤   ¤   pgpDebugMsg( "unknown platform" );
95e2a7 ¤   ¤   ¤   break;¤
ca9371 ¤   }
eb7454 #endif
6faf5a
--140d 0007f6831f3401000d0 Page 6 of pgpMemoryMgrWin32.c
daf10d ¤   return( hDriver );
d2efe6 }
77af5a
dfaf5a
3b0335 /*____________________________________________________________________________
c8d47b ¤   Initialize MyData data structure. ·It has already been allocated.
3df7f7 ____________________________________________________________________________*/
7766dd ¤   static PGPError
ddcbc2 sInitMyData( MyData *myData )
8ebb36 {
b17637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
10af5a
50c1fc ¤   PGPValidatePtr( myData );
aa67c5 ¤
7b0fad ¤   myData->hDriver¤= sGetMyDriver();
3ad369 ¤   myData->heapList¤   ¤   = NULL;
f6827d ¤   myData->lastHeapUsed¤   = NULL;
3caf5a
7b5ea8 ¤   return err;
daefe6 }
caaf5a
42af5a
800335 /*____________________________________________________________________________
9ebbd0 ¤   Dispose MyData data structure contents and free it.
47f7f7 ____________________________________________________________________________*/
db66dd ¤   static PGPError
aefd30 sCleanupMyData( MyData *myData )
e6bb36 {
71b931 ¤   PageHeap *¤ heap¤   = NULL;
3d67c5 ¤
92da88 ¤   pgpAssertMsg( IsNull( myData->heapList ),
e365eb ¤   ¤   "sCleanupMyData(): WARNING: secure memory is being leaked" );
9baf5a
1bc514 ¤   while ( IsntNull( myData->heapList ) )
4fc7a1 ¤   {
b0f937 ¤   ¤   sRemoveAndDisposeHeap( myData, myData->heapList );
559371 ¤   }
4067c5 ¤
9fafb9 #if PGP_WIN32
f61866 ¤   if ( myData->hDriver != NULL )·
89c7a1 ¤   {
9a11dc ¤   ¤   CloseHandle ( myData->hDriver );
9767eb ¤   ¤   myData->hDriver = NULL;
9c9371 ¤   }
837454 #endif
35af5a
c24188 ¤   sInternalFree( myData );
adaf5a
6b151e ¤   return kPGPError_NoErr;
73efe6 }
93af5a
93af5a
84af5a
1caf5a
66c744 ¤   PGPError
d4882b pgpCreateStandardMemoryMgr( PGPMemoryMgrRef *newMemoryMgr )
a4bb36 {
ed9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
93590f ¤   MyData *¤   ¤   ¤   ¤   pmyData¤= NULL;
d367c5 ¤
55ab12 ¤   PGPValidatePtr( newMemoryMgr );
cd8179 ¤   *newMemoryMgr¤  = NULL;
3367c5 ¤
bae001 ¤   /* allocate private data which we will store as the customValue */
43793f ¤   pmyData¤= (MyData *)sInternalAlloc( sizeof( MyData ) );
b1c1da ¤   if ( IsntNull( pmyData ) )
ffc7a1 ¤   {
cd4846 ¤   ¤   PGPNewMemoryMgrStruct¤  custom;
7d1b52 ¤   ¤
beb12b ¤   ¤   pgpClearMemory( pmyData, sizeof( MyData ) );
46302e ¤   ¤   err¤= sInitMyData( pmyData );
7f7d98 ¤   ¤   if ( IsntPGPError( err ) )
--9f68 000c755a3bd401000d0 Page 7 of pgpMemoryMgrWin32.c
e35b34 ¤   ¤   {
341900 ¤   ¤   ¤   pgpClearMemory( &custom, sizeof( custom ) );
7e1b52 ¤   ¤
e84f3b ¤   ¤   ¤   custom.customValue¤ = (PGPUserValue)pmyData;
5d87c7 ¤   ¤   ¤
785110 ¤   ¤   ¤   custom.sizeofStruct¤¤   = sizeof( custom );
a28add ¤   ¤   ¤   custom.allocProc¤   ¤   = sWin32MemoryAllocationProc;
f2ef7d ¤   ¤   ¤   custom.reallocProc¤ ¤   = sWin32MemoryReallocationProc;
66611d ¤   ¤   ¤   custom.deallocProc¤ ¤   = sWin32MemoryDeallocationProc;
f487c7 ¤   ¤   ¤
828399 ¤   ¤   ¤   custom.secureAllocProc¤ ¤   = sWin32SecureMemoryAllocationProc;
0f36bc ¤   ¤   ¤   custom.secureDeallocProc¤   = sWin32SecureMemoryDeallocationProc;
7587c7 ¤   ¤   ¤
2c937b ¤   ¤   ¤   err¤= PGPNewMemoryMgrCustom( &custom, newMemoryMgr );
4b8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
39f776 ¤   ¤   ¤   {
286656 ¤   ¤   ¤   ¤   sCleanupMyData( pmyData );
1fa3a6 ¤   ¤   ¤   }
d40fe4 ¤   ¤   }
aa1b52 ¤   ¤
13be18 ¤   ¤   if ( IsPGPError( err ) )
265b34 ¤   ¤   {
417ceb ¤   ¤   ¤   /* creation failed...dispose our private data */
1c4024 ¤   ¤   ¤   sInternalFree( pmyData );
290fe4 ¤   ¤   }
5d9371 ¤   }
7f0e24 ¤   else
b1c7a1 ¤   {
0e17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
299371 ¤   }
ed67c5 ¤
13deb7 ¤   return( err );
eeefe6 }
f6af5a
5daf5a
e9af5a
3ac744 ¤   PGPError
7c2dcd pgpDisposeStandardMemoryMgrUserValue( PGPUserValue customValue )
f5bb36 {
3687dc ¤   MyData *¤   pmyData¤= (MyData *)customValue;
fc67c5 ¤
85a596 ¤   sCleanupMyData( pmyData );
2867c5 ¤
b52d68 ¤   return( kPGPError_NoErr );
9fefe6 }
fdaf5a
80af5a
3faf5a
3a0335 /*____________________________________________________________________________
b17c06 ¤   Allocate a page of memory from the VM system and make it non-pageable
d0f0f7 ¤   if possible.
17f7f7 ____________________________________________________________________________*/
ee062a ¤   static void *
56f9b3 sAllocatePages(
ffbd97 ¤   HANDLE¤ ¤   ¤   hDriver,¤   /* may be NULL */
86388e ¤   PGPUInt32¤  ¤   numPages,
853c4d ¤   PGPBoolean *¤   isNonPageable )
27bb36 {
689aad ¤   void *¤ result¤ = NULL;
b667c5 ¤
129917 ¤   pgpAssert( IsntNull( isNonPageable ) );
a167c5 ¤
c78897 ¤   *isNonPageable¤ = FALSE;
6967c5 ¤
26afb9 #if PGP_WIN32
0a59c3 ¤   /* since the first parameter to VirtualAlloc is NULL, it automatically·
390b4b ¤   ···rounds allocation size up to next page boundary */
021d3c ¤   result = VirtualAlloc ( NULL,
fee2df ¤   ¤   ¤   ¤   numPages * kPageSize, MEM_COMMIT, PAGE_READWRITE );
0d67c5 ¤
48e164 ¤   if ( IsntNull( result ) )
c7c7a1 ¤   {
--9a5b 0008a4067b2401000d0 Page 8 of pgpMemoryMgrWin32.c
7edf68 ¤   ¤   sLockMemory( hDriver, result, numPages * kPageSize, isNonPageable );
499371 ¤   }
18db21 #else
7dc0d2 ¤   (void)hDriver;
fbc1fe ¤   result¤ = sInternalAlloc( numPages * kPageSize );
427454 #endif
c667c5 ¤
854c6e ¤   return( result );
ebefe6 }
2caf5a
b1af5a
830335 /*____________________________________________________________________________
ebc103 ¤   Free pages allocated with sAllocatePages()
19f7f7 ____________________________________________________________________________*/
5b33c8 ¤   static void
563cf8 sFreePages(
3a085a ¤   HANDLE¤ ¤   hDriver,¤   /* may be NULL */
7c88da ¤   void *¤ ¤   pages,
cd8b37 ¤   PGPUInt32¤  numPages,
c23791 ¤   PGPBoolean¤ nonPageable )
a3bb36 {
b7afb9 #if PGP_WIN32
598783 ¤   /* we can assume it has already been safely cleared ·*/
03f96c ¤   if ( nonPageable )
b1c7a1 ¤   {
12de27 ¤   ¤   sUnlockMemory( hDriver, pages, numPages * kPageSize );
f89371 ¤   }
d967c5 ¤
57273e ¤   VirtualFree( pages, 0, MEM_RELEASE );
13db21 #else
58c0d2 ¤   (void)hDriver;
c23999 ¤   (void)numPages;
25eadf ¤   (void)nonPageable;
24c712 ¤   sInternalFree( (Ptr)pages );
c97454 #endif
73efe6 }
8daf5a
32af5a
570335 /*____________________________________________________________________________
800425 ¤   Create a heap of the specified size.
cdf7f7 ____________________________________________________________________________*/
59c241 ¤   static PageHeap *
04b3a3 sCreateHeap(
a17c39 ¤   HANDLE¤ ¤   hDriver,
9824e9 ¤   PGPSize¤¤   heapSize)
8fbb36 {
9c26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
83b931 ¤   PageHeap *¤ heap¤   = NULL;
7053ae ¤   PGPUInt32¤  numPages;
993751 ¤   PGPUInt32¤  numChunks;
a567c5 ¤
0e13ce ¤   numPages¤   = heapSize / kPageSize;
e75103 ¤   if ( ( heapSize % kPageSize ) != 0 )
c46761 ¤   ¤   numPages¤   += 1;
6e67c5 ¤
27fecf ¤   numChunks¤  = ( numPages * kPageSize ) / kChunkSize;
bb67c5 ¤
06e3bc ¤   heap¤   = (PageHeap *)sInternalAlloc( sizeof( *heap ) );
63a273 ¤   if ( IsntNull( heap ) )
b0c7a1 ¤   {
296a63 ¤   ¤   heap->hDriver¤  ¤   = hDriver;
b32c6a ¤   ¤   heap->numPages¤ ¤   = numPages;
639e7b ¤   ¤   heap->numFreeChunks¤= numChunks;
481b52 ¤   ¤
f31b47 ¤   ¤   heap->pages¤= sAllocatePages( hDriver,
7f812b ¤   ¤   ¤   ¤   ¤   ¤   numPages, &heap->isNonPageable );
be8bc4 ¤   ¤   if ( IsntNull( heap->pages ) )
9d5b34 ¤   ¤   {
7f36b4 ¤   ¤   ¤   ChunkHeader *¤  chunkHeader¤= (ChunkHeader *)heap->pages;
3987c7 ¤   ¤   ¤
c0cce8 ¤   ¤   ¤   chunkHeader->next¤  ¤   = NULL;
8ab9eb ¤   ¤   ¤   chunkHeader->prev¤  ¤   = NULL;
--0aa1 000278c83a9401000d0 Page 9 of pgpMemoryMgrWin32.c
62dc1f ¤   ¤   ¤   chunkHeader->numChunks¤ = numChunks;
676bee ¤   ¤   ¤   heap->freeList¤ = chunkHeader;
a00fe4 ¤   ¤   }
bd0e1d ¤   ¤   else
c75b34 ¤   ¤   {
56d0c3 ¤   ¤   ¤   sInternalFree( heap );
b18e53 ¤   ¤   ¤   heap¤   = NULL;
79124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
3d0fe4 ¤   ¤   }
a89371 ¤   }
bc67c5 ¤
3ffb27 ¤   return( heap );
4fefe6 }
c4af5a
75af5a
db0335 /*____________________________________________________________________________
1ff103 ¤   Dispose the heap, releasing all the memory it references.
eef7f7 ____________________________________________________________________________*/
5433c8 ¤   static void
9288ed sDisposeHeap(
dc7c39 ¤   HANDLE¤ ¤   hDriver,
45c63b ¤   PageHeap *¤ heap )
f5bb36 {
491313 ¤   /* free chunks better be all of them... */
3a2388 ¤   pgpAssert( IsntNull( heap ) &&
c4066b ¤   ¤   ( heap->numPages * kPageSize ) / kChunkSize );
ce67c5 ¤
62c863 ¤   sFreePages( hDriver, heap->pages, heap->numPages, heap->isNonPageable );
f967c5 ¤
3a4894 ¤   sInternalFree( heap );
0aefe6 }
f0af5a
bbaf5a
5dc241 ¤   static PageHeap *
1444cb sCreateAndAddHeap(
33341c ¤   MyData *¤   myData,
4f40f4 ¤   PGPSize¤¤   heapSize )
76bb36 {
7126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
44b931 ¤   PageHeap *¤ heap¤   = NULL;
be67c5 ¤
a21a27 ¤   pgpAssert( ( heapSize % kPageSize ) == 0 );
ec1b52 ¤   ¤
9957ba ¤   heap¤   = sCreateHeap( myData->hDriver, heapSize);
fea273 ¤   if ( IsntNull( heap ) )
a4c7a1 ¤   {
d9a986 ¤   ¤   heap->prev¤ = NULL;
71e8f9 ¤   ¤   heap->next¤ = NULL;
0e87c7 ¤   ¤   ¤
160810 ¤   ¤   if ( IsNull( myData->heapList ) )
425b34 ¤   ¤   {
3c0d8f ¤   ¤   ¤   myData->heapList¤   = heap;
350fe4 ¤   ¤   }
d30e1d ¤   ¤   else
3f5b34 ¤   ¤   {
8a9c28 ¤   ¤   ¤   heap->next¤ = myData->heapList;
00c1b1 ¤   ¤   ¤   myData->heapList->prev¤ = heap;
77f0c0 ¤   ¤   ¤   myData->heapList¤   ¤   = heap;
f10fe4 ¤   ¤   }
366ef3 ¤   ¤   sHeapValidate( heap );
8a9371 ¤   }
d267c5 ¤
c6fb27 ¤   return( heap );
87efe6 }
abaf5a
56af5a
1533c8 ¤   static void
5347ad sRemoveAndDisposeHeap(
3a341c ¤   MyData *¤   myData,
e1c63b ¤   PageHeap *¤ heap )
a0bb36 {
271433 ¤   PageHeap *¤ next;
--fc32 000e281e2bd401000d0 Page 10 of pgpMemoryMgrWin32.c
2a67c5 ¤
e56f87 ¤   if ( heap == myData->lastHeapUsed )
534728 ¤   ¤   myData->lastHeapUsed¤   = NULL;
5d1b52 ¤   ¤
8c7adb ¤   sHeapValidate( heap );
0b67c5 ¤
6bea09 ¤   next¤   = heap->next;
8367c5 ¤
7f46ac ¤   if ( heap == myData->heapList )
7bc7a1 ¤   {
ac8983 ¤   ¤   myData->heapList¤   = next;
169371 ¤   }
d1af5a
643a8a ¤   if ( IsntNull( heap->prev ) )
4cc7a1 ¤   {
c724fc ¤   ¤   heap->prev->next¤   = heap->next;
999371 ¤   }
314a6d ¤   if ( IsntNull( heap->next ) )
14c7a1 ¤   {
1b8ee3 ¤   ¤   heap->next->prev¤   = heap->prev;
c59371 ¤   }
a467c5 ¤
1ac76e ¤   sDisposeHeap( myData->hDriver, heap );
d1efe6 }
46af5a
adaf5a
9f062a ¤   static void *
8bfaea sAllocateChunksFromExistingHeaps(
4efaed ¤   MyData *¤   ¤   myData,
904668 ¤   PGPSize¤¤   ¤   allocChunks,
aa3c4d ¤   PGPBoolean *¤   isNonPageable )
27bb36 {
04594f ¤   void *¤ ¤   alloc¤  = NULL;
9fb931 ¤   PageHeap *¤ heap¤   = NULL;
6167c5 ¤
8ca3f7 ¤   heap¤   = myData->lastHeapUsed;
a4a273 ¤   if ( IsntNull( heap ) )
9ac7a1 ¤   {
b7e5ac ¤   ¤   alloc¤  = sHeapAllocateChunks( heap, allocChunks, isNonPageable);
169371 ¤   }
0567c5 ¤
69841c ¤   if ( IsNull( alloc ) )
b8c7a1 ¤   {
6686c4 ¤   ¤   heap¤   = myData->heapList;
43b1e3 ¤   ¤   while ( IsntNull( heap ) )
325b34 ¤   ¤   {
222f14 ¤   ¤   ¤   if ( heap->numFreeChunks >= allocChunks )
cdf776 ¤   ¤   ¤   {
3c03ec ¤   ¤   ¤   ¤   alloc¤  = sHeapAllocateChunks( heap,
bdf7db ¤   ¤   ¤   ¤   ¤   ¤   ¤   allocChunks,isNonPageable );
533f00 ¤   ¤   ¤   ¤   if ( IsntNull( alloc ) )
4072c3 ¤   ¤   ¤   ¤   {
9214c3 ¤   ¤   ¤   ¤   ¤   break;
512613 ¤   ¤   ¤   ¤   }
71a3a6 ¤   ¤   ¤   }
e46e93 ¤   ¤   ¤   heap¤   = heap->next;
240fe4 ¤   ¤   }
2a9371 ¤   }
1467c5 ¤
d7ece7 ¤   myData->lastHeapUsed¤   = heap;
3667c5 ¤
ad8f84 ¤   return( alloc );
41efe6 }
8aaf5a
3dbb2e ¤   static PGPSize
db7513 sSizeToChunks( PGPSize allocationSize )
ebbb36 {
6afeb3 ¤   PGPSize¤allocChunks;
2767c5 ¤
15ecf0 ¤   allocChunks¤= allocationSize / kChunkSize;
d3f690 ¤   if ( (allocationSize % kChunkSize) != 0 )
e2618c ¤   ¤   ++allocChunks;
--120b 000eb619f4f401000d0 Page 11 of pgpMemoryMgrWin32.c
f3061c ¤   return( allocChunks );
52efe6 }
4faf5a
e2062a ¤   static void *
f4b1a5 sAllocateBytes(
b1faed ¤   MyData *¤   ¤   myData,
b0d43c ¤   PGPSize¤¤   ¤   requestSize,
b93c4d ¤   PGPBoolean *¤   isNonPageable )
5cbb36 {
7a594f ¤   void *¤ ¤   alloc¤  = NULL;
318657 ¤   PGPUInt32¤  allocChunks;
a367c5 ¤
629917 ¤   pgpAssert( IsntNull( isNonPageable ) );
9d67c5 ¤
f88897 ¤   *isNonPageable¤ = FALSE;
8467c5 ¤
f458da ¤   allocChunks¤= sSizeToChunks( requestSize );
0867c5 ¤
d05a11 ¤   alloc = sAllocateChunksFromExistingHeaps( myData, allocChunks,
6aa97f ¤   ¤   ¤   ¤   isNonPageable );
bb841c ¤   if ( IsNull( alloc ) )
abc7a1 ¤   {
e10b9c ¤   ¤   PGPSize¤¤   heapSize;
ad32cd ¤   ¤   PageHeap *¤ heap¤   = NULL;
381b52 ¤   ¤
7e61da ¤   ¤   /* make heap size meet minimum & be multiple of page size */
c5d6fd ¤   ¤   heapSize¤   = allocChunks * kChunkSize;
e9af98 ¤   ¤   if ( heapSize < kMinHeapSizeBytes )
68edd2 ¤   ¤   ¤   heapSize¤   = kMinHeapSizeBytes;
7a57bb ¤   ¤   if ( ( heapSize % kPageSize ) != 0 )
ec69b0 ¤   ¤   ¤   heapSize¤   += kPageSize - (heapSize % kPageSize);
e7af5a
64bc80 ¤   ¤   heap¤   = sCreateAndAddHeap( myData, heapSize );
d50f2d ¤   ¤   if ( IsntNull( heap ) )
ee5b34 ¤   ¤   {
059ce6 ¤   ¤   ¤   alloc¤  = sHeapAllocateChunks( heap, allocChunks, isNonPageable);
1f0fe4 ¤   ¤   }
2a9371 ¤   }
dc67c5 ¤
658f84 ¤   return( alloc );
e7efe6 }
85ae30 ¤   ¤   ¤   ¤   ¤
c067c5 ¤
eb6c2c ¤   static PGPBoolean
6c2cc4 sHeapOwnsAllocation(
4d48da ¤   PageHeap const *¤   heap,
2121c6 ¤   void const *¤   ¤   allocation )
60bb36 {
2762d2 ¤   PGPBoolean¤ ownsIt¤ = FALSE;
3067c5 ¤
976e5f ¤   if ( allocation >= heap->pages )
d3c7a1 ¤   {
10074d ¤   ¤   void *last;
b767c5 ¤
adf424 ¤   ¤   last¤   = (char *)heap->pages + ( (heap->numPages * kPageSize) -1 );
baf785 ¤   ¤   if ( allocation <= last )
f4caad ¤   ¤   ¤   ownsIt¤ = TRUE;
9a9371 ¤   }
7967c5 ¤
1a274f ¤   return( ownsIt );
c6efe6 }
00af5a
8d67c5 ¤
d06c2c ¤   static PGPBoolean
baaa46 sHeapIsEmpty( PageHeap const *¤ heap)
f0bb36 {
bfa264 ¤   PGPSize¤numChunks¤  = (heap->numPages * kPageSize ) / kChunkSize;
bc67c5 ¤
73c9a2 ¤   return( heap->numFreeChunks == numChunks );
19efe6 }
6faf5a
ebaf5a
--38c6 0008c5e6eec401000d0 Page 12 of pgpMemoryMgrWin32.c
2633c8 ¤   static void
5774ee sFreeBytes(
9dfaed ¤   MyData *¤   ¤   myData,
df60fa ¤   void *¤ ¤   ¤   allocation,
c80886 ¤   PGPSize¤¤   ¤   allocationSize )
cbbb36 {
e4556a ¤   PageHeap *¤ heap;
2c0071 ¤   PGPSize¤¤   allocChunks;
7c67c5 ¤
795e35 ¤   allocChunks¤= sSizeToChunks( allocationSize );
0867c5 ¤
440d38 ¤   heap¤   = myData->heapList;
863d9c ¤   while ( IsntNull( heap ) )
41c7a1 ¤   {
036ef3 ¤   ¤   sHeapValidate( heap );
321b52 ¤   ¤
9280e8 ¤   ¤   if ( sHeapOwnsAllocation( heap, allocation ) )
545b34 ¤   ¤   {
67f190 ¤   ¤   ¤   sHeapFreeChunks( heap, allocation, allocChunks );
1187c7 ¤   ¤   ¤
24f482 ¤   ¤   ¤   if ( sHeapIsEmpty( heap ) )
56f776 ¤   ¤   ¤   {
7f7557 ¤   ¤   ¤   ¤   sRemoveAndDisposeHeap( myData, heap );
0ea3a6 ¤   ¤   ¤   }
e3cdcb ¤   ¤   ¤   break;
cc0fe4 ¤   ¤   }
a5599b ¤   ¤   heap¤   = heap->next;
259371 ¤   }
80efe6 }
a0af5a
4eaf5a
60062a ¤   static void *
10fd75 sHeapAllocateChunks(
8770cb ¤   PageHeap *¤ ¤   heap,
a9552e ¤   PGPUInt32 ¤ ¤   allocChunks,
d93c4d ¤   PGPBoolean *¤   isNonPageable )
17bb36 {
d68528 ¤   void *¤ ¤   ¤   result¤ = NULL;
877af4 ¤   ChunkHeader *¤  chunk¤  = NULL;
9267c5 ¤
cc9917 ¤   pgpAssert( IsntNull( isNonPageable ) );
d58897 ¤   *isNonPageable¤ = FALSE;
6467c5 ¤
f57adb ¤   sHeapValidate( heap );
fc67c5 ¤
0e62a1 ¤   chunk¤  = heap->freeList;
748de8 ¤   while ( IsntNull( chunk ) )
b2c7a1 ¤   {
626c58 ¤   ¤   if ( chunk->numChunks >= allocChunks )
fd5b34 ¤   ¤   {
fefd99 ¤   ¤   ¤   ChunkHeader *¤  remainder;
04c94b ¤   ¤   ¤   PGPUInt32¤  ¤   leftoverChunks;
a8b079 ¤   ¤   ¤   PGPUInt32¤  ¤   actualChunksUsed¤   = 0;
1687c7 ¤   ¤   ¤
d7c434 ¤   ¤   ¤   result¤ = (void *)chunk;
2687c7 ¤   ¤   ¤
b9f032 ¤   ¤   ¤   remainder¤  = (ChunkHeader *)
961a1c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ((char *)chunk + (allocChunks * kChunkSize ));
f7c1eb ¤   ¤   ¤   leftoverChunks¤ = chunk->numChunks - allocChunks;
4987c7 ¤   ¤   ¤
cadb4c ¤   ¤   ¤   if ( leftoverChunks != 0 &&
6ffc2b ¤   ¤   ¤   ¤   ¤   (leftoverChunks * kChunkSize >= kMinLeftoverBytes) )
04f776 ¤   ¤   ¤   {
4f8617 ¤   ¤   ¤   ¤   actualChunksUsed¤   = allocChunks;
962b85 ¤   ¤   ¤   ¤
0ad016 ¤   ¤   ¤   ¤   remainder->numChunks¤   = leftoverChunks;
d6431c ¤   ¤   ¤   ¤   remainder->next¤¤   ¤   = chunk->next;
99881b ¤   ¤   ¤   ¤   remainder->prev¤¤   ¤   = chunk->prev;
222b85 ¤   ¤   ¤   ¤
efab7b ¤   ¤   ¤   ¤   /* need to make a new chunk out of leftover */
a5f369 ¤   ¤   ¤   ¤   if ( chunk == heap->freeList )
8c72c3 ¤   ¤   ¤   ¤   {
--d30d 000ca34de3f401000d0 Page 13 of pgpMemoryMgrWin32.c
110224 ¤   ¤   ¤   ¤   ¤   heap->freeList¤ = remainder;
3c2613 ¤   ¤   ¤   ¤   }
18fa07 ¤   ¤   ¤   ¤   else
4472c3 ¤   ¤   ¤   ¤   {
fb6a31 ¤   ¤   ¤   ¤   ¤   chunk->prev->next¤  = chunk->next;
3d2613 ¤   ¤   ¤   ¤   }
0a9427 ¤   ¤   ¤   ¤   if ( IsntNull( remainder->next ) )
58b62d ¤   ¤   ¤   ¤   ¤   remainder->next->prev¤  = remainder;
4ee4c0 ¤   ¤   ¤   ¤   if ( IsntNull( remainder->prev ) )
6afd2b ¤   ¤   ¤   ¤   ¤   remainder->prev->next¤  = remainder;
25a3a6 ¤   ¤   ¤   }
bdbb8c ¤   ¤   ¤   else
d0f776 ¤   ¤   ¤   {
f5729a ¤   ¤   ¤   ¤   actualChunksUsed¤   = allocChunks + leftoverChunks;
362b85 ¤   ¤   ¤   ¤
036744 ¤   ¤   ¤   ¤   /* remove the chunk from the list */
8bf369 ¤   ¤   ¤   ¤   if ( chunk == heap->freeList )
8472c3 ¤   ¤   ¤   ¤   {
b0cad3 ¤   ¤   ¤   ¤   ¤   heap->freeList¤ = chunk->next;
592613 ¤   ¤   ¤   ¤   }
46fa07 ¤   ¤   ¤   ¤   else
b472c3 ¤   ¤   ¤   ¤   {
516a31 ¤   ¤   ¤   ¤   ¤   chunk->prev->next¤  = chunk->next;
7e2613 ¤   ¤   ¤   ¤   }
6db5e7 ¤   ¤   ¤   ¤   if ( IsntNull( chunk->next ) )
43c02e ¤   ¤   ¤   ¤   ¤   chunk->next->prev¤  = chunk->prev;
7da3a6 ¤   ¤   ¤   }
d387c7 ¤   ¤   ¤
4c6205 ¤   ¤   ¤   heap->numFreeChunks¤-= actualChunksUsed;
1d87c7 ¤   ¤   ¤
a536c0 ¤   ¤   ¤   *isNonPageable¤ = heap->isNonPageable;
a3cdcb ¤   ¤   ¤   break;
330fe4 ¤   ¤   }
b5b865 ¤   ¤   chunk¤  = chunk->next;
979371 ¤   }
d867c5 ¤
b37adb ¤   sHeapValidate( heap );
8d67c5 ¤
6d4c6e ¤   return( result );
6eefe6 }
29af5a
53af5a
8f6c2c ¤   static PGPBoolean
94280a sChunksAreAdjacent( ChunkHeader const * chunkHeader )
65bb36 {
e1a7a5 ¤   ChunkHeader const *¤next¤   = NULL;
5b231d ¤   PGPSize¤¤   chunkBytes;
5967c5 ¤
18a0dd ¤   pgpAssert( IsntNull( chunkHeader ) );
f9f475 ¤   next¤   = chunkHeader->next;
f7e699 ¤   if ( IsNull( next ) )
dee20d ¤   ¤   return( FALSE );
a567c5 ¤
80e35f ¤   chunkBytes¤ = chunkHeader->numChunks * kChunkSize;
e267c5 ¤
fd2388 ¤   return( (char *)chunkHeader + chunkBytes == (char *)next );
bcefe6 }
cdaf5a
0233c8 ¤   static void
11de1d sMergeChunks( ChunkHeader *chunkHeader )
0ebb36 {
c7845a ¤   ChunkHeader *¤  next¤   = chunkHeader->next;
a367c5 ¤
d55cc6 ¤   pgpAssert( sChunksAreAdjacent( chunkHeader ) );
e467c5 ¤
be4722 ¤   chunkHeader->numChunks¤ += next->numChunks;
7e85e3 ¤   if ( IsntNull( next->next ) )
f125a3 ¤   ¤   next->next->prev¤   = chunkHeader;
4cf13c ¤   chunkHeader->next¤  = next->next;
80efe6 }
b7af5a
ca33c8 ¤   static void
--fc7e 000fcccf4cd401000d0 Page 14 of pgpMemoryMgrWin32.c
22b5b4 sMergeFree( ChunkHeader *chunkHeader )
57bb36 {
013e6a ¤   ChunkHeader *¤  prev¤   = NULL;
8f67c5 ¤
72a0dd ¤   pgpAssert( IsntNull( chunkHeader ) );
b567c5 ¤
e89812 ¤   if ( sChunksAreAdjacent( chunkHeader ) )
22c7a1 ¤   {
556b2a ¤   ¤   sMergeChunks( chunkHeader );
479371 ¤   }
9f1ed2 ¤   prev¤   = chunkHeader->prev;
fd9de3 ¤   if ( IsntNull( prev ) && sChunksAreAdjacent( prev ) )
c9c7a1 ¤   {
7b520e ¤   ¤   sMergeChunks( prev );
90ca6f ¤   ¤   chunkHeader¤= NULL;
0e9371 ¤   }
a7efe6 }
4daf5a
bb0335 /*____________________________________________________________________________
52eb54 ¤   Free an allocation within a heap of specified size.
5ff7f7 ____________________________________________________________________________*/
3d33c8 ¤   static void
4839c0 sHeapFreeChunks(
008df3 ¤   PageHeap *¤ heap,
c7007d ¤   void *¤ ¤   allocation,
ca27cd ¤   PGPUInt32 ¤ allocChunks )
4ebb36 {
0c9f2f ¤   ChunkHeader *¤  chunkHeader;
4f7d36 ¤   ChunkHeader *¤  cur;
53e0b2 ¤   ChunkHeader *¤  preceeding¤ = NULL;
7967c5 ¤
8642c9 ¤   pgpAssert( sHeapOwnsAllocation( heap, allocation ) );
ac67c5 ¤
5f7adb ¤   sHeapValidate( heap );
db67c5 ¤
615e5f ¤   heap->numFreeChunks¤+= allocChunks;
3d67c5 ¤
0c481a ¤   chunkHeader¤= (ChunkHeader *)allocation;
4e4ad6 ¤   chunkHeader->numChunks¤ = allocChunks;
0267c5 ¤
599af1 ¤   /* find the first chunk which precedes this one */
230a4a ¤   cur¤= heap->freeList;
24f700 ¤   while ( IsntNull( cur ) )
dac7a1 ¤   {
e23760 ¤   ¤   if ( chunkHeader < cur )
105b34 ¤   ¤   {
f1739f ¤   ¤   ¤   preceeding¤ = cur->prev;
29cdcb ¤   ¤   ¤   break;
460fe4 ¤   ¤   }
cd35af ¤   ¤   cur¤= cur->next;
539371 ¤   }
fe67c5 ¤
cb80d5 ¤   if ( IsNull( preceeding ) )
6ac7a1 ¤   {
dde97a ¤   ¤   chunkHeader->next¤  = heap->freeList;
f656ba ¤   ¤   chunkHeader->prev¤  = NULL;
afbbe0 ¤   ¤   if ( IsntNull( chunkHeader->next ) )
13a41d ¤   ¤   ¤   chunkHeader->next->prev¤= chunkHeader;
df130c ¤   ¤   heap->freeList¤ ¤   = chunkHeader;
679371 ¤   }
d70e24 ¤   else
38c7a1 ¤   {
81cb88 ¤   ¤   chunkHeader->prev¤  = preceeding;
9f242b ¤   ¤   chunkHeader->next¤  = preceeding->next;
e478b6 ¤   ¤   if ( IsntNull( preceeding->next ) )
6d237f ¤   ¤   ¤   preceeding->next->prev¤ = chunkHeader;
0e69a2 ¤   ¤   preceeding->next¤   = chunkHeader;
fd9371 ¤   }
b967c5 ¤
83d4ad ¤   sMergeFree( chunkHeader );
d267c5 ¤
fc7adb ¤   sHeapValidate( heap );
--5fbe 000ef45d4f5401000d0 Page 15 of pgpMemoryMgrWin32.c
7aefe6 }
46af5a
8eaf5a
9af404 #if INTEGRITY_CHECKS¤   /* [ */
8433c8 ¤   static void
1ed11b sHeapValidate( PageHeap const *¤heap )
dfbb36 {
d17d36 ¤   ChunkHeader *¤  cur;
b21627 ¤   PGPSize¤¤   ¤   freeChunks¤ = 0;
9567c5 ¤
096e11 ¤   /* verify that free chunks match count in heap */
220a4a ¤   cur¤= heap->freeList;
0bf700 ¤   while ( IsntNull( cur ) )
7cc7a1 ¤   {
2f30f8 ¤   ¤   pgpAssert( cur->numChunks != 0 );
28b2de ¤   ¤   freeChunks¤ += cur->numChunks;
911b52 ¤   ¤
203e68 ¤   ¤   /* verify next item points back at cur */
1df063 ¤   ¤   if ( IsntNull( cur->next ) )
985b34 ¤   ¤   {
e90a87 ¤   ¤   ¤   pgpAssert( cur->next->prev == cur );
c60fe4 ¤   ¤   }
3935af ¤   ¤   cur¤= cur->next;
dd9371 ¤   }
81f39b ¤   pgpAssert( heap->numFreeChunks == freeChunks );
62efe6 }
1d3167 #endif¤ /* ] */
ffaf5a
a5af5a
1694d2 #if PGP_WIN32¤  /* [ */
8fae30 ¤   ¤   ¤   ¤   ¤
850335 /*____________________________________________________________________________
96709a ¤   Win32 version of sLockMemory()
a1af5a
826f4d ¤   Win32 supports locking of pages into memory only by using
633bd0 ¤   special purpose drivers (VxD under Win95, kernel mode driver
372071 ¤   under WinNT). ·Note, the current driver implementations take
2c8ee2 ¤   the virtual (linear) address to lock and the number of bytes.
469120 ¤   This memory must have been allocated on a page-boundary and·
b47fa8 ¤   committed using the Win32 API function VirtualAlloc (see routine
adbf6f ¤   sNewSecureDataHeader).
f2af5a
708d89 ¤   Here we attempt to use such drivers if they have been successfully
9c9faf ¤   loaded (if the handle is non-NULL). ·In this case, the return
f7e761 ¤   codes from the DeviceIoControl call and the driver are used to·
583d64 ¤   ascertain if the lock was successful.
dfaf5a
83d93e ¤   If the driver has not been loaded, we revert back to the "old"·
c3323c ¤   method of calling the Win32 APIs "VirtualLock" and "VirtualUnlock".
0dfbe8 ¤   Under Windows95 these functions do absolutely nothing. ·
9917ec ¤   Under WindowsNT they prevent the specified memory range from being·
1442d0 ¤   paged to disk *while this process is executing*. ·When all threads·
31acb4 ¤   of this process become pre-empted, the OS is free to page whatever·
048296 ¤   it wants (including "VirtualLock-ed" memory) to disk.
70af5a
cde7fa ¤   Assign a value of "TRUE" to 'isNonPageable' only if we have
6e9623 ¤   a valid driver loaded and the driver successfully locks the page
7d2065 ¤   in memory.·
12f7f7 ____________________________________________________________________________*/
39af5a
6733c8 ¤   static void
9217a8 sLockMemory(
11f4f5 ¤   HANDLE¤ ¤   ¤   hDriver,
902c65 ¤   void *¤ ¤   ¤   mem,
b5342a ¤   PGPSize¤¤   ¤   numBytes,
693c4d ¤   PGPBoolean *¤   isNonPageable )
24bb36 {
dcf88e ¤   PGPMEMLOCKSTRUCT¤   mls;
5106b1 ¤   DWORD¤  ¤   ¤   ¤   dw;
66d1ea ¤   BOOL¤   ¤   ¤   ¤   bDIOreturn;
03af5a
ef9917 ¤   pgpAssert( IsntNull( isNonPageable ) );
--bd24 0003030bd64401000d0 Page 16 of pgpMemoryMgrWin32.c
578897 ¤   *isNonPageable¤ = FALSE;
e6d83c ·
5045c3 ¤   if ( IsntNull( hDriver ) )·
38c7a1 ¤   {
dbd790 ¤   ¤   mls.pMem = mem;
6abb84 ¤   ¤   mls.ulNumBytes = numBytes;
63546b ¤   ¤   bDIOreturn = DeviceIoControl(¤  hDriver,·
7f9231 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   IOCTL_PGPMEMLOCK_LOCK_MEMORY,·
c28156 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mls,·
02a44c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( mls ),·
c98156 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mls,·
7fa44c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( mls ),·
d17eb0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &dw,·
bcf412 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL );
f0f49f ¤   ¤   pgpAssertMsg ( bDIOreturn, "DIOC error from page-locking driver" );
cfd8ad ¤   ¤   if ( bDIOreturn )
7f5b34 ¤   ¤   {
c07673 ¤   ¤   ¤   pgpAssertMsg ( mls.ulError == 0,·
a37e0a ¤   ¤   ¤   ¤   ¤   ¤   ··"Internal error in page-locking driver" );
adaf5a
cf3350 ¤   ¤   ¤   if ( mls.ulError == 0 )·
2bf776 ¤   ¤   ¤   {
34dc8b ¤   ¤   ¤   ¤   *isNonPageable¤ = TRUE;
fe69c5 ¤   ¤   ¤   }¤  ¤
bf0fe4 ¤   ¤   }
0a9371 ¤   }
674264 ¤   else·
30c7a1 ¤   {
c56bda ¤   ·¤  VirtualLock ( mem, numBytes );¤ /* call for good measure*/
ed9371 ¤   }
31efe6 }
c4af5a
b5af5a
1a33c8 ¤   static void
8beca3 sUnlockMemory(
ab7c39 ¤   HANDLE¤ ¤   hDriver,
654371 ¤   void *¤ ¤   mem,
cb6a25 ¤   PGPSize¤¤   numBytes )
adbb36 {
abf88e ¤   PGPMEMLOCKSTRUCT¤   mls;
8406b1 ¤   DWORD¤  ¤   ¤   ¤   dw;
60d1ea ¤   BOOL¤   ¤   ¤   ¤   bDIOreturn;
85af5a
269153 ¤   if ( IsntNull( hDriver ) )
9ec7a1 ¤   {
bfd790 ¤   ¤   mls.pMem = mem;
f3bb84 ¤   ¤   mls.ulNumBytes = numBytes;
cd546b ¤   ¤   bDIOreturn = DeviceIoControl(¤  hDriver,·
43193e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   IOCTL_PGPMEMLOCK_UNLOCK_MEMORY,·
b38156 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mls,·
d8a44c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( mls ),·
ee8156 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mls,·
d8a44c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( mls ),·
ec7eb0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &dw,·
9cf412 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL );
94f49f ¤   ¤   pgpAssertMsg ( bDIOreturn, "DIOC error from page-locking driver" );
6ad8ad ¤   ¤   if ( bDIOreturn )
e55b34 ¤   ¤   {
187673 ¤   ¤   ¤   pgpAssertMsg ( mls.ulError == 0,·
337e0a ¤   ¤   ¤   ¤   ¤   ¤   ··"Internal error in page-locking driver" );
d80fe4 ¤   ¤   }
519371 ¤   }
0b4264 ¤   else·
e8c7a1 ¤   {
823ac3 ¤   ·¤  VirtualUnlock ( mem, numBytes );¤   /* call for good measure*/
be9371 ¤   }
33efe6 }
c7af5a
d4a4fe #endif¤ /* ] PGP_WIN32 */
73af5a
857e4d /*__Editor_settings____
30af5a
--55f5 00150c9616f401000d0 Page 17 of pgpMemoryMgrWin32.c
734126 ¤   Local Variables:
567b17 ¤   tab-width: 4
430e6c ¤   End:
895f8c ¤   vi: ts=4 sw=4
ab9e9b ¤   vim: si
50d062 _____________________*/
--f248 0006cb8624c401000d1 Page 1 of pgpPFLErrors.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
697c52 ¤   Error codes.
c8af5a
91f24b ¤   $Id: pgpPFLErrors.h,v 1.19.16.1 1998/11/12 03:18:01 heller Exp $
68f7f7 ____________________________________________________________________________*/
33ffa7 #ifndef Included_pgpPFLErrors_h¤/* [ */
e5247f #define Included_pgpPFLErrors_h
43af5a
65a146 #include "pgpDebug.h"
78af5a
e4af5a
34af5a
e530af #define kPGPPFLErrorBase¤   -12000
40f3c8 #define kPGPPFLErrorRange¤  500
02af5a
237353 enum
f3bb36 {
ddd8af ¤   /*
6112bf ¤   NOTE: error numbers must not be changed as compile clients depend on them.
ab9faa ¤   */
2f67c5 ¤
2d76eb ¤   kPGPError_NoErr¤¤   ¤   ¤   = 0,
1b67c5 ¤
4f1a31 ¤   kPGPError_BadParams¤¤   ¤   = -12000,
89e92b ¤   kPGPError_OutOfMemory¤  ¤   = -11999,
63063c ¤   kPGPError_BufferTooSmall¤   = -11998,
f267c5 ¤
0e7dea ¤   kPGPError_FileNotFound¤ ¤   = -11997,
ac80ef ¤   kPGPError_CantOpenFile¤ ¤   = -11996,
012325 ¤   kPGPError_FilePermissions¤  = -11995,
9597e3 ¤   kPGPError_FileLocked¤   ¤   = -11994,
9b8caa ¤   kPGPError_DiskFull¤ ¤   ¤   = -11993,
8adc84 ¤   kPGPError_IllegalFileOp¤¤   = -11992,
c7db14 ¤   kPGPError_FileOpFailed¤ ¤   = -11991,
ffaa19 ¤   kPGPError_ReadFailed¤   ¤   = -11990,
c6ed85 ¤   kPGPError_WriteFailed¤  ¤   = -11989,
133045 ¤   kPGPError_EOF¤  ¤   ¤   ¤   = -11988,
7b67c5 ¤
470347 ¤   kPGPError_UserAbort¤¤   ¤   = -11987,
971451 ¤   kPGPError_UnknownRequest¤   = -11986,
0a0257 ¤   kPGPError_LazyProgrammer¤   = -11985,
399d7b ¤   kPGPError_ItemNotFound¤ ¤   = -11984,
97fdde ¤   kPGPError_ItemAlreadyExists¤= -11983,
918a43 ¤   kPGPError_AssertFailed¤ ¤   = -11982,
6c7479 ¤   kPGPError_BadMemAddress¤¤   = -11981,
3f3c68 ¤   kPGPError_UnknownError¤ ¤   = -11980,
ce67c5 ¤
3115ad ¤   kPGPError_PrefNotFound¤ ¤   = -11979,
868e00 ¤   kPGPError_EndOfIteration¤   = -11978,
dfef2d ¤   kPGPError_ImproperInitialization¤   = -11977,
19eca1 ¤   kPGPError_CorruptData¤  ¤   ¤   ¤   = -11976,
265c8d ¤   kPGPError_FeatureNotAvailable¤  ¤   = -11975,
7167c5 ¤
518914 ¤   kPGPError_LastPFLError = kPGPPFLErrorBase + kPGPPFLErrorRange
8682f7 };
60af5a
05ed4a #define IsPGPError( err )¤  ¤   ( (err) != kPGPError_NoErr )
6f17d3 #define IsntPGPError( err )¤¤   ( (err) == kPGPError_NoErr )
3aaf5a
15af5a
feaf5a
11e0c8 #define PGPValidateParam( expr )¤   \
769e64 ¤   if ( ! (expr ) )¤   \
c59c39 ¤   {\
fb080e ¤   ¤   pgpAssert( expr );\
b23ba4 ¤   ¤   return( kPGPError_BadParams );\
459371 ¤   }
e6af5a
6c10e5 #define PGPValidatePtr( ptr )¤  \
--6c38 0015aee2ae9401000d1 Page 2 of pgpPFLErrors.h
f34c46 ¤   ¤   ¤   PGPValidateParam( (ptr) != NULL )
e0af5a
ecaf5a
34c5d5 #include "pgpBase.h"
6e87c7 ¤   ¤   ¤
3099c6 PGP_BEGIN_C_DECLARATIONS
42af5a
3aaf5a
acd5ba PGPError ¤  PFLGetErrorString( PGPError theError,
71290d ¤   ¤   ¤   ¤   PGPSize bufferSize, char * theString );
3caf5a
83af5a
731254 PGP_END_C_DECLARATIONS
30af5a
74af5a
df8f03 #endif /* ] Included_pgpPFLErrors_h */
baaf5a
38af5a
ed7e4d /*__Editor_settings____
afaf5a
fa4126 ¤   Local Variables:
7c7b17 ¤   tab-width: 4
cc0e6c ¤   End:
d95f8c ¤   vi: ts=4 sw=4
a99e9b ¤   vim: si
5ad062 _____________________*/
--5138 000a9ddf7e8401000d2 Page 1 of pgpRMWOLock.c
a70335 /*____________________________________________________________________________
f7f413 Copyright (C) 1997 Network Associates, Inc. and its affiliates.
1cfade All rights reserved.
d667c5 ¤
d567c5 ¤
6a67c5 ¤
966ba3 $Id: pgpRMWOLock.c,v 1.9.12.1 1998/11/12 03:18:01 heller Exp $
79f7f7 ____________________________________________________________________________*/
0baf5a
7bc5d5 #include "pgpBase.h"
24af5a
b551b9 #include "pgpRMWOLock.h"
c4af5a
8fecf1 #if PGP_UNIX_SOLARIS
c838e5 /*
3beb0c ·* Use the Solaris system read/write locks. This is slightly different
d8f3d6 ·* from the default implementation: In determining who can proceed
10ba48 ·* from blocking, Solaris is random with a bias toward writers. The
13e4a7 ·* default implementation has readers and writers proceeding in
c8a24e ·* alternating phases.
20495d ·*/
56314a void
dd34c3 InitializePGPRMWOLock(PGPRMWOLock * inLock)
90bb36 {
c64e52 ¤   (void) rwlock_init(inLock, USYNC_THREAD, NULL);
c3efe6 }
8caf5a
d4314a void
76a8f6 DeletePGPRMWOLock(PGPRMWOLock * inLock)
67bb36 {
ebb776 ¤   (void) rwlock_destroy(inLock);
bfefe6 }
6caf5a
e3314a void
230e60 PGPRMWOLockStartReading(PGPRMWOLock * inLock)
44bb36 {
6cffda ¤   (void) rw_rdlock(inLock);
6eefe6 }
6aaf5a
68314a void
f9102b PGPRMWOLockStopReading(PGPRMWOLock * inLock)
5fbb36 {
5c8cbf ¤   (void) rw_unlock(inLock);
63efe6 }
61af5a
ac314a void
a0f546 PGPRMWOLockStartWriting(PGPRMWOLock * inLock)
81bb36 {
1343a1 ¤   (void) rw_wrlock(inLock);
97efe6 }
a8af5a
85314a void
53eb0d PGPRMWOLockStopWriting(PGPRMWOLock * inLock)
47bb36 {
ac8cbf ¤   (void) rw_unlock(inLock);
12efe6 }
f5af5a
1fd54c #else /* everything else */
81af5a
62314a void
d7cff1 InitializePGPRMWOLock(PGPRMWOLock *¤inLock)
30bb36 {
6aaa15 ¤   (void) PGPMutexCreate(&(inLock->mutex), PGPMutexAttr_default);
86a1fe ¤   (void) PGPSemCreate(&(inLock->blockedReaders), PGPSemAttr_default);
e0e531 ¤   (void) PGPSemCreate(&(inLock->blockedWriters), PGPSemAttr_default);
ab67c5 ¤
0aec75 ¤   inLock->activeReaders = 0;
f46d97 ¤   inLock->waitingReader = 0;
3806d4 ¤   inLock->activeWriters = 0;
9caaaa ¤   inLock->waitingWriter = 0;
61efe6 }
a9af5a
--46c3 0002e1560da401000d2 Page 2 of pgpRMWOLock.c
b3314a void
ee53c4 DeletePGPRMWOLock(PGPRMWOLock *¤inLock)
cfcebb {¤
c73bd7 ¤   (void) PGPMutexDestroy(&(inLock->mutex));
674986 ¤   (void) PGPSemDestroy(&(inLock->blockedReaders));
aa7057 ¤   (void) PGPSemDestroy(&(inLock->blockedWriters));
3fefe6 }
8baf5a
60314a void
648ce2 PGPRMWOLockStartReading(PGPRMWOLock *¤  inLock)
9abb36 {
740c98 ¤   PGPMutexLock(&(inLock->mutex));
9567c5 ¤
39da66 ¤   if ((inLock->activeWriters > 0) || (inLock->waitingWriter > 0)) {
f47d52 ¤   ¤   inLock->waitingReader++;
e52761 ¤   ¤   PGPMutexUnlock(&(inLock->mutex));
b81b17 ¤   ¤   /*
fb25b9 ¤   ¤   ·* we need to wait for any active people to finish before
60620c ¤   ¤   ·* we can read, so we wait for blockedReaders to fire
c29de3 ¤   ¤   ·*/
12ac11 ¤   ¤   PGPSemWait(&(inLock->blockedReaders));
55f037 ¤   } else {
1484d6 ¤   ¤   inLock->activeReaders++;
d22761 ¤   ¤   PGPMutexUnlock(&(inLock->mutex));
299371 ¤   }
d8efe6 }
41af5a
04314a void
9df699 PGPRMWOLockStopReading(PGPRMWOLock *¤   inLock)
6dbb36 {
120c98 ¤   PGPMutexLock(&(inLock->mutex));
0ea2c3 ¤   inLock->activeReaders--;
3967c5 ¤
a8fcd4 ¤   if ((inLock->activeReaders == 0) && (inLock->waitingWriter > 0)) {
eed077 ¤   ¤   inLock->activeWriters = 1;
7cf2a9 ¤   ¤   inLock->waitingWriter--;
701b17 ¤   ¤   /*
7962ee ¤   ¤   ·* I've stopped reading, there aren't anymore readers, but there
160f90 ¤   ¤   ·* are some writers, so I need to fire blockedWriters to let
99c425 ¤   ¤   ·* those writers do their thing.
ce9de3 ¤   ¤   ·*/
326cb5 ¤   ¤   PGPSemPost(&(inLock->blockedWriters));
eb9371 ¤   }
091b8f ¤   PGPMutexUnlock(&(inLock->mutex));
21efe6 }
bfaf5a
e3314a void
74b25d PGPRMWOLockStartWriting(PGPRMWOLock *¤  inLock)
72bb36 {
ee0c98 ¤   PGPMutexLock(&(inLock->mutex));
fa67c5 ¤
143eee ¤   if ((inLock->activeReaders == 0) && (inLock->activeWriters == 0)) {
fdd077 ¤   ¤   inLock->activeWriters = 1;
022761 ¤   ¤   PGPMutexUnlock(&(inLock->mutex));
15f037 ¤   } else {
6b6fea ¤   ¤   inLock->waitingWriter++;
452761 ¤   ¤   PGPMutexUnlock(&(inLock->mutex));
e41b17 ¤   ¤   /*
b525b9 ¤   ¤   ·* we need to wait for any active people to finish before
fb9f4a ¤   ¤   ·* we can write, so we wait for blockedWriters to fire
329de3 ¤   ¤   ·*/
bd95c0 ¤   ¤   PGPSemWait(&(inLock->blockedWriters));
289371 ¤   }
c9efe6 }
03af5a
5a314a void
6ebbdb PGPRMWOLockStopWriting(PGPRMWOLock *¤   inLock)
90bb36 {
930c98 ¤   PGPMutexLock(&(inLock->mutex));
ff06d4 ¤   inLock->activeWriters = 0;
83af5a
2e0b35 ¤   /* waiting readers go before waiting writers */
--9a6a 0010cc64322401000d2 Page 3 of pgpRMWOLock.c
b2b52c ¤   if (inLock->waitingReader > 0) {
f65fc7 ¤   ¤   while (inLock->waitingReader > 0) {
ccdd79 ¤   ¤   ¤   inLock->waitingReader--;
adb9be ¤   ¤   ¤   inLock->activeReaders++;
d47822 ¤   ¤   ¤   /* there are some readers, so let 'em go */
c38dd6 ¤   ¤   ¤   PGPSemPost(&(inLock->blockedReaders));
0a0fe4 ¤   ¤   }
01ebcd ¤   } else if (inLock->waitingWriter > 0) {
19f2a9 ¤   ¤   inLock->waitingWriter--;
59d077 ¤   ¤   inLock->activeWriters = 1;
844fa2 ¤   ¤   /* there are some writers, let 'em go */
5d6cb5 ¤   ¤   PGPSemPost(&(inLock->blockedWriters));
ea9371 ¤   }
9e1b8f ¤   PGPMutexUnlock(&(inLock->mutex));
4aefe6 }
e4af5a
0c3199 #endif·
--ccc3 001bd00a9e7401000d3 Page 1 of pgpRMWOLock.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
bf7725 ¤   $Id: pgpRMWOLock.h,v 1.8.14.1 1998/11/12 03:18:02 heller Exp $
5bf7f7 ____________________________________________________________________________*/
50af5a
935b9f #ifndef Included_pgpRMWOLock_h¤ /* [ */
64e447 #define Included_pgpRMWOLock_h
b3af5a
99afb9 #if PGP_WIN32
b57ef2 # include <windows.h>
fd7454 #endif
99af5a
aa675a #include "pgpTypes.h"
b09ea8 #include "pgpThreads.h"
c8af5a
df99c6 PGP_BEGIN_C_DECLARATIONS
c9af5a
8fc76c /* These files implement a Read Many/Write Once lock. To use, simply
600ca6 initialize a lock for the resource and surround your reading and writing of it
00d37b with the appropriate calls. */
1faf5a
f1971d #if PGP_UNIX_SOLARIS¤   /* solaris has a system impl. of this */
5e7bf6 ·typedef rwlock_t PGPRMWOLock;
c75ff3 #elif PGP_MACINTOSH
af29d2 ¤   typedef char PGPRMWOLock;
cedb21 #else
9b627e ·typedef struct PGPRMWOLock {
391793 ¤   PGPMutex_t¤ mutex;
ea1012 ¤   PGPSem_t¤   blockedReaders;
853920 ¤   PGPSem_t¤   blockedWriters;
36570f ¤   PGPUInt16¤  activeReaders;
038ef7 ¤   PGPUInt16¤  waitingReader;
487e3d ¤   PGPUInt16¤  activeWriters;
46fe5f ¤   PGPUInt16¤  waitingWriter;
69156c ·} PGPRMWOLock;
ff7454 #endif
a3af5a
f20ccc #if PGP_MACINTOSH
39af5a
8ea455 # define InitializePGPRMWOLock(x)
580b0f # define DeletePGPRMWOLock(x)
1cd249 # define PGPRMWOLockStartReading(x)
314e29 # define PGPRMWOLockStopReading(x)
c4eb98 # define PGPRMWOLockStartWriting(x)
7f77f8 # define PGPRMWOLockStopWriting(x)
33af5a
52db21 #else
0baf5a
425fc3 void¤   InitializePGPRMWOLock(PGPRMWOLock * inLock);
8e439b void¤   DeletePGPRMWOLock(PGPRMWOLock * inLock);
843e97 void¤   PGPRMWOLockStartReading(PGPRMWOLock * inLock);
75dd4e void¤   PGPRMWOLockStopReading(PGPRMWOLock * inLock);
a37a58 void¤   PGPRMWOLockStartWriting(PGPRMWOLock * inLock);
f29981 void¤   PGPRMWOLockStopWriting(PGPRMWOLock * inLock);
41af5a
a9bb8e #endif /* PGP_MACINTOSH */
18af5a
751254 PGP_END_C_DECLARATIONS
d5af5a
bd187b #endif /* ] Included_pgpRMWOLock_h */
--d5e0 00162203156401000d4 Page 1 of pgpTemplate.c
a70335 /*____________________________________________________________________________
a99e23 ¤   Copyright (C) 1998 Network Associates, Inc.
e74b0f ¤   All rights reserved.
3d67c5 ¤
8767c5 ¤
90af5a
2c7368 ¤   $Id$
44f7f7 ____________________________________________________________________________*/
312194 #include "pgpPFLConfig.h"¤  /* or pgpConfig.h in the CDK */
a2af5a
44af5a
abaf5a
35af5a
daaf5a
3eaf5a
ceaf5a
55af5a
20af5a
9baf5a
baaf5a
23af5a
05af5a
56af5a
63af5a
21af5a
3daf5a
29af5a
86af5a
47af5a
efaf5a
6daf5a
ebaf5a
efaf5a
3caf5a
d8af5a
e0af5a
1faf5a
c2af5a
a2af5a
b5af5a
f27e4d /*__Editor_settings____
55af5a
2a4126 ¤   Local Variables:
9e7b17 ¤   tab-width: 4
260e6c ¤   End:
725f8c ¤   vi: ts=4 sw=4
b79e9b ¤   vim: si
62d062 _____________________*/
--842b 001a05fc506401000d5 Page 1 of pgpTemplate.h
a70335 /*____________________________________________________________________________
a99e23 ¤   Copyright (C) 1998 Network Associates, Inc.
e74b0f ¤   All rights reserved.
3d67c5 ¤
8767c5 ¤
90af5a
2c7368 ¤   $Id$
44f7f7 ____________________________________________________________________________*/
e0fbee #ifndef Included_CHANGE_THIS_FILENAME_TO_BE_CORRECT_h¤  /* [ */
2dcfb5 #define Included_CHANGE_THIS_FILENAME_TO_BE_CORRECT_h
5eaf5a
17af5a
e1af5a
fbaf5a
87c0c1 #endif /* ] Included_CHANGE_THIS_FILENAME_TO_BE_CORRECT_h */
e0af5a
e7af5a
fd7e4d /*__Editor_settings____
77af5a
054126 ¤   Local Variables:
d47b17 ¤   tab-width: 4
b60e6c ¤   End:
d05f8c ¤   vi: ts=4 sw=4
8f9e9b ¤   vim: si
a0d062 _____________________*/
--0cb4 00194a73783401000d6 Page 1 of pgpTypes.h
a70335 /*____________________________________________________________________________
ddba26 ¤   pgpTypes.h
f867c5 ¤
3df254 ¤   Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
4e4b0f ¤   All rights reserved.
b567c5 ¤
558772 ¤   Basic type definitions
dfaf5a
c80293 ¤   $Id: pgpTypes.h,v 1.6.16.1 1998/11/12 03:18:03 heller Exp $
caf7f7 ____________________________________________________________________________*/
0d9f73 #ifndef Included_pgpTypes_h¤/* [ */
90c0fe #define Included_pgpTypes_h
97af5a
bf0ccc #if PGP_MACINTOSH
c085b6 #include <types.h>
19db21 #else
38f15e #include <sys/types.h>
187454 #endif
e2af5a
cdc5d5 #include "pgpBase.h"
32af5a
8432e0 #if ! HAVE_UCHAR
34f8d5 typedef unsigned char¤  uchar;
917454 #endif
c0af5a
1aed73 #if ! HAVE_USHORT
beb76b typedef unsigned short¤ ushort;
157454 #endif
c8af5a
df449a #if ! HAVE_UINT
9f412a typedef unsigned int¤   uint;
927454 #endif
f7af5a
d2aed3 #if ! HAVE_ULONG
3f8e03 typedef unsigned long¤  ulong;
587454 #endif
74af5a
3f3f5f typedef char¤   ¤   ¤   VoidAlign;
09af5a
db29db #if ! PGP_MACINTOSH
32bff3 typedef PGPBoolean¤ ¤   Boolean;
307454 #endif
37af5a
78af5a
c8ec00 /* Lookie here! ·An ANSI-compliant alignment finder! */
3831f5 #ifndef ¤   alignof
95320e #define ¤   alignof(type) (sizeof(struct{type _x; char _y;}) - sizeof(type))
96afb9 #if PGP_WIN32
edda3c /* Causes "unnamed type definition in parentheses" warning" */
320b77 #ifndef __MWERKS__
c4e95e #pragma warning ( disable : 4116 )
847454 #endif
e67454 #endif
467454 #endif
0caf5a
fcaf5a
be66ef #endif /* ] Included_pgpTypes_h */
94af5a
e27e4d /*__Editor_settings____
a9af5a
d84126 ¤   Local Variables:
7d7b17 ¤   tab-width: 4
f70e6c ¤   End:
905f8c ¤   vi: ts=4 sw=4
259e9b ¤   vim: si
94d062 _____________________*/
--8ddf 000a0b0ff77401000d7 Page 1 of CComboError.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
9cdb50 ¤   Class intended to solve the problem of distinguishing a PGPError from
a62692 ¤   an os-specific error or other errors.
a6af5a
7ab84f ¤   $Id: CComboError.h,v 1.5.32.1 1998/11/12 03:18:05 heller Exp $
40f7f7 ____________________________________________________________________________*/
628aec #ifndef Included_ComboError_h¤  /* [ */
39b9b6 #define Included_ComboError_h
d8af5a
fb2b62 #include "pgpPFLErrors.h"
acaf5a
1b0ccc #if PGP_MACINTOSH
0776b7 #include "MacErrors.h"
627454 #endif
f7af5a
93af5a
150335 /*____________________________________________________________________________
b18393 ¤   The field "PGPError" contains a PGPError value as defined in PFL and CDK.
6467c5 ¤
f45b81 ¤   The field "err" contains an operating system-dependent error code. ·Both
43769f ¤   can exist with different values at the same time. Simply assign to the
c10aab ¤   appropriate field and then use the supplied function to test for errors.
8867c5 ¤
fdee29 ¤   Sample Usage:
3d865f ¤   CComboError¤¤   err;
6c67c5 ¤
c229d6 ¤   err.pgpErr¤ = PGPNewContext( .. );
ceed80 ¤   if ( err.IsntError() )
ea7e54 ¤   ¤   err.err¤¤   = FSWrite( ... );
ea67c5 ¤
07defc ¤   if ( err.IsError() )
29e55e ¤   ¤   return( err );
581b52 ¤   ¤
a54c4a Routine overview:
2b9d6e ¤   CComboError¤¤   (no args) initializes both error values to no error
20064f ¤   CComboError¤¤   creates a new with specified error
ba67c5 ¤
6d0fd8 ¤   IsError¤¤   ¤   returns TRUE if either error value contains an error
4d9e61 ¤   IsntError¤  ¤   returns TRUE if neither error value contains an error
c567c5 ¤
817655 ¤   IsCancelError¤  returns TRUE if either error value contains a cancel error
9467c5 ¤
92a746 ¤   HavePGPError¤   returns TRUE if pgpErr is not kPGPError_NoErr
5c9762 ¤   HaveNonPGPError¤returns TRUE if err is not zero (kNoErr)
1df6a3 ¤   ¤   ¤   ¤   ¤   both HavePGPError and HaveNonPGPError can be TRUE
ae67c5 ¤
c1f7f7 ____________________________________________________________________________*/
19af5a
8baf5a
64b246 class CComboError
1abb36 {
1b5ed4 public:
1af7ef ¤   PGPError¤   pgpErr;
a43cb9 ¤   PGPError¤   err;¤   /* platform specific error */
c867c5 ¤
bcb216 ¤   enum¤   ComboErrorType{ kPlatformError, kPGPError };
a8a5fa ¤   enum ¤  { kNoErr¤   = 0 };
74ae30 ¤   ¤   ¤   ¤   ¤
937602 ¤   ¤   ¤   ¤   CComboError( void )
2072c3 ¤   ¤   ¤   ¤   {
bec8ab ¤   ¤   ¤   ¤   ¤   pgpErr¤ = kPGPError_NoErr;
c1b357 ¤   ¤   ¤   ¤   ¤   err¤¤   = kNoErr;
412613 ¤   ¤   ¤   ¤   }
4faf5a
db489c ¤   ¤   ¤   ¤   /* no type difference between a PGPError, OSStatus, int
f02e6f ¤   ¤   ¤   ¤   so we need an enum type to distinguis in the constructor */
6283ab ¤   ¤   ¤   ¤   CComboError( ComboErrorType type, SInt32 errCode )
5a72c3 ¤   ¤   ¤   ¤   {
a0a2bc ¤   ¤   ¤   ¤   ¤   if ( type == kPlatformError )
--344e 000f9164ca1401000d7 Page 2 of CComboError.h
e04859 ¤   ¤   ¤   ¤   ¤   {
627551 ¤   ¤   ¤   ¤   ¤   ¤   err¤¤   = errCode;
101019 ¤   ¤   ¤   ¤   ¤   ¤   pgpErr¤ = kPGPError_NoErr;
151c89 ¤   ¤   ¤   ¤   ¤   }
e34bd6 ¤   ¤   ¤   ¤   ¤   else
cf4859 ¤   ¤   ¤   ¤   ¤   {
b5637c ¤   ¤   ¤   ¤   ¤   ¤   pgpErr¤ = errCode;
558fb9 ¤   ¤   ¤   ¤   ¤   ¤   err¤¤   = kNoErr;
b91c89 ¤   ¤   ¤   ¤   ¤   }
df2613 ¤   ¤   ¤   ¤   }
ae67c5 ¤
8c67c5 ¤
b9dd3a ¤   virtual PGPBoolean¤ IsError( void )
f872c3 ¤   ¤   ¤   ¤   {
0ed328 ¤   ¤   ¤   ¤   ¤   return( IsPGPError( pgpErr ) || err != kNoErr );
8a2613 ¤   ¤   ¤   ¤   }
942b85 ¤   ¤   ¤   ¤
211f4e ¤   virtual PGPBoolean¤ IsntError( void )
9372c3 ¤   ¤   ¤   ¤   {
d5b90f ¤   ¤   ¤   ¤   ¤   return( ! IsError() );
ae2613 ¤   ¤   ¤   ¤   }
2e2b85 ¤   ¤   ¤   ¤
d34a06 ¤   virtual PGPBoolean¤ IsCancelError( void )
7872c3 ¤   ¤   ¤   ¤   {
acff1d ¤   ¤   ¤   ¤   ¤   if ( pgpErr == kPGPError_UserAbort && err == kNoErr )
a87600 ¤   ¤   ¤   ¤   ¤   ¤   return( TRUE );
c54fbf ¤   ¤   ¤   ¤   #if PGP_MACINTOSH
a0854d ¤   ¤   ¤   ¤   ¤   if( err == userCanceledErr && pgpErr == kPGPError_NoErr )
077600 ¤   ¤   ¤   ¤   ¤   ¤   return( TRUE );
440f1c ¤   ¤   ¤   ¤   #endif
99506e ¤   ¤   ¤   ¤   ¤   return( FALSE );
c02613 ¤   ¤   ¤   ¤   }
0c67c5 ¤
040c9b ¤   /* unusual, but both HavePGPError() and HaveNonPGPError() can be TRUE */
ebaef2 ¤   PGPBoolean¤ HavePGPError( void )
7072c3 ¤   ¤   ¤   ¤   {
599b79 ¤   ¤   ¤   ¤   ¤   return( pgpErr != kPGPError_NoErr );
2f2613 ¤   ¤   ¤   ¤   }
6a67c5 ¤
e7f945 ¤   virtual PGPBoolean¤ HaveNonPGPError( void )
8d72c3 ¤   ¤   ¤   ¤   {
cdcd18 ¤   ¤   ¤   ¤   ¤   return( err != 0 );
912613 ¤   ¤   ¤   ¤   }
ad67c5 ¤
530ccc #if PGP_MACINTOSH
694e68 ¤   ¤   virtual PGPError
e7a292 ¤   ConvertToPGPError( void )
79c7a1 ¤   {
141b2e ¤   ¤   if ( HavePGPError() )
94dd2b ¤   ¤   ¤   return( pgpErr );
d381c9 ¤   ¤   else if ( IsError() )
8c124c ¤   ¤   ¤   return( MacErrorToPGPError( err ) );
d90e1d ¤   ¤   else
8be0e4 ¤   ¤   ¤   return( kPGPError_NoErr );
899371 ¤   }
8a1fa7 #endif¤ ¤
6782f7 };
a4af5a
36af5a
cfaf5a
ddaf5a
caaf5a
b5fad1 #endif /* ] Included_ComboError_h */
b3af5a
acaf5a
3b7e4d /*__Editor_settings____
f2af5a
1f4126 ¤   Local Variables:
0c7b17 ¤   tab-width: 4
a50e6c ¤   End:
af5f8c ¤   vi: ts=4 sw=4
f99e9b ¤   vim: si
--28ca 001177e2b6c401000d7 Page 3 of CComboError.h
17d062 _____________________*/
--c26c 001c385b8af401000d8 Page 1 of Makefile.in
5ea601 #
73c013 # common/file/
57a601 #
bc6918 # $Id: Makefile.in,v 1.4 1997/08/21 04:58:45 lloyd Exp $
0aa601 #
feaf5a
525399 OBJS= pgpFileIO.o pgpFileSpec.o pgpFileSpecStd.o pgpFileSpecVTBL.o \
8f8c56 ¤   pgpFileUtilities.o pgpIO.o pgpMemoryIO.o pgpProxyIO.o pgpStdFileIO.o \
3e44ce ¤   pgpIOUtilities.o pgpLineEndIO.o
7faf5a
89b7a3 all:: DONE
c3af5a
--dc1d 0004ddd1875401000d9 Page 1 of pgpFileIO.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
301f74 ¤   Abstract base class for all PGPFileIO objects.
fdaf5a
d90b03 ¤   $Id: pgpFileIO.c,v 1.3.34.1 1998/11/12 03:18:06 heller Exp $
fcf7f7 ____________________________________________________________________________*/
8ee610 #include "pgpPFLConfig.h"
0baf5a
f52b62 #include "pgpPFLErrors.h"
fdc5a2 #include "pgpFileIOPriv.h"
770d08 #include "pgpMem.h"
9faf5a
9faf5a
df75cd #define GetParentVTBL()¤¤   pgpIOGetClassVTBL()
33af5a
fcc258 #define GetSelfVTBL( ref ) \
a3a710 ¤   (PGPFileIOVtbl const *)pgpioGetObjectVTBL( ref )
0faf5a
8baf5a
8c16ea ¤   PGPBoolean
71c8c9 PGPFileIOIsValid( PGPFileIORef ref )
7cbb36 {
9908f8 ¤   if ( ! PGPIOIsValid( (PGPIORef)ref ) )
ace20d ¤   ¤   return( FALSE );
e367c5 ¤
d2f046 ¤   return( ref->fileIOMagic == kPGPFileIOMagic );
54efe6 }
3aaf5a
bdaf5a
deaf5a
8faf5a
a9af5a
b466dd ¤   static PGPError
ac46e3 sFileIOInitProc(
e7f273 ¤   PGPIORef¤   inRef,
ae9b3a ¤   void *¤ ¤   data )
b3bb36 {
647637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
7c0926 ¤   PGPFileIORef¤   self¤   = (PGPFileIORef)inRef;
4e67c5 ¤
fb3d77 ¤   PGPValidateIO( inRef );
ef67c5 ¤
41ee01 ¤   err¤= pgpioInheritInit( inRef, GetParentVTBL(), data );
5567c5 ¤
182a7a ¤   self->fileIOMagic¤  = kPGPFileIOMagic;
a738d1 ¤   self->autoClose¤¤   = TRUE;
4367c5 ¤
eadeb7 ¤   return( err );
8befe6 }
fdaf5a
5daf5a
beaf5a
eb66dd ¤   static PGPError
a88130 sFileIODestroyProc( PGPIORef¤   inRef )
b3bb36 {
b49372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1b0926 ¤   PGPFileIORef¤   self¤   = (PGPFileIORef)inRef;
3baf5a
971e75 ¤   PGPValidateFileIO( self );
bf67c5 ¤
3f5b91 ¤   self->fileIOMagic¤  = 0;
9967c5 ¤
3d2343 ¤   err¤= pgpioInheritDestroy( inRef, GetParentVTBL() );
6667c5 ¤
8ddeb7 ¤   return( err );
47efe6 }
89af5a
ecaf5a
1ca855 ¤   PGPFileIOVtbl const *
4d61c3 pgpFileIOGetClassVTBL()
--4c9e 001df9d4c28401000d9 Page 2 of pgpFileIO.c
2cbb36 {
29eb25 ¤   static PGPFileIOVtbl¤   sVTBL¤  = { {NULL,} };
092c67 ¤   PGPFileIOVtbl *¤¤   ¤   vtbl¤   = &sVTBL;
4f67c5 ¤
3381d0 ¤   if ( IsNull( vtbl->parentVTBL.initProc ) )
41c7a1 ¤   {
3a901f ¤   ¤   PGPIOVtbl *¤parent¤ = &vtbl->parentVTBL;
b81b52 ¤   ¤
acfaa1 ¤   ¤   /* get default routines */
4b918b ¤   ¤   *parent¤= *pgpIOGetClassVTBL();
7b1f6b ¤   ¤   parent->initProc¤   = sFileIOInitProc;
8ddbb0 ¤   ¤   parent->destroyProc¤= sFileIODestroyProc;
4e9371 ¤   }
cb67c5 ¤
e97543 ¤   return( vtbl );
2aefe6 }
1daf5a
0caf5a
d0af5a
c7af5a
99af5a
57af5a
29af5a
d9af5a
47af5a
a1af5a
71af5a
c7af5a
a8af5a
3eaf5a
d8af5a
9eaf5a
71af5a
4baf5a
57af5a
81af5a
9eaf5a
f9af5a
64af5a
bdaf5a
89af5a
0daf5a
087e4d /*__Editor_settings____
9faf5a
0c4126 ¤   Local Variables:
497b17 ¤   tab-width: 4
430e6c ¤   End:
8e5f8c ¤   vi: ts=4 sw=4
7a9e9b ¤   vim: si
dfd062 _____________________*/
--6ec6 00192dbaae1401000da Page 1 of pgpFileIO.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
948a6e ¤   $Id: pgpFileIO.h,v 1.4.16.1 1998/11/12 03:18:07 heller Exp $
18f7f7 ____________________________________________________________________________*/
cbf9ef #ifndef Included_pgpFileIO_h¤   /* [ */
d38db8 #define Included_pgpFileIO_h
77af5a
9f6773 #include "pgpMemoryMgr.h"
75894b #include "pgpFileSpec.h"
10af5a
182864 /* base class */
ada9cb #include "pgpIO.h"
c0af5a
7caf5a
f399c6 PGP_BEGIN_C_DECLARATIONS
4bcbcf #if PRAGMA_IMPORT_SUPPORTED
c1b981 #pragma import on
627454 #endif
7baf5a
ebaf5a
6af886 typedef struct PGPFileIO¤   PGPFileIO;
fd99c7 typedef PGPFileIO *¤¤   ¤   PGPFileIORef;
f0af5a
4caf5a
d2af5a
6daf5a
24fdbf PGPBoolean¤ PGPFileIOIsValid( PGPFileIORef ref );
4a9267 #define PGPValidateFileIO( ref )¤   PGPValidateParam( PGPFileIOIsValid( ref ) )
3baf5a
4aaf5a
03af5a
73af5a
85cbcf #if PRAGMA_IMPORT_SUPPORTED
352ced #pragma import reset
1d7454 #endif
0b1254 PGP_END_C_DECLARATIONS
ecaf5a
9e5b0d #endif /* ] Included_pgpFileIO_h */
37af5a
3e7e4d /*__Editor_settings____
e4af5a
ac4126 ¤   Local Variables:
c37b17 ¤   tab-width: 4
440e6c ¤   End:
dc5f8c ¤   vi: ts=4 sw=4
029e9b ¤   vim: si
92d062 _____________________*/
--0dc0 001b3f60bc1401000db Page 1 of pgpFileIOPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
b63bd1 ¤   abstract base class for file IO.
51af5a
cffea8 ¤   $Id: pgpFileIOPriv.h,v 1.3.34.1 1998/11/12 03:18:07 heller Exp $
f7f7f7 ____________________________________________________________________________*/
f3af5a
e4c68b #include "pgpFileIO.h"
8e9c9f #include "pgpIOPriv.h"
00894b #include "pgpFileSpec.h"
a2af5a
ef99c6 PGP_BEGIN_C_DECLARATIONS
6faf5a
23af5a
b06f01 /* the virtual function table for a PGPFileIO */
29c632 typedef struct PGPFileIOVtbl
2ebb36 {
00654e ¤   PGPIOVtbl¤  ¤   ¤   parentVTBL;
22c9a6 } PGPFileIOVtbl;
dbaf5a
7daf5a
4d54e3 PGPFileIOVtbl const *¤  pgpFileIOGetClassVTBL( void );
28af5a
feaf5a
a80fa6 struct PGPFileIO
3abb36 {
dfc23c ¤   PGPIO¤  ¤   ¤   parent;
c167c5 ¤
f62dda ¤   PGPUInt32¤  ¤   fileIOMagic;
11ed2a ¤   PGPBoolean¤ ¤   autoClose;
9682f7 };
f1ab00 #define kPGPFileIOMagic¤¤   0x464c494f
2eaf5a
1baf5a
c7af5a
e71254 PGP_END_C_DECLARATIONS
9eaf5a
077e4d /*__Editor_settings____
d6af5a
9d4126 ¤   Local Variables:
077b17 ¤   tab-width: 4
440e6c ¤   End:
2f5f8c ¤   vi: ts=4 sw=4
379e9b ¤   vim: si
b3d062 _____________________*/
--3a80 000e11c1df9401000dc Page 1 of pgpFileSpec.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
993f81 ¤   $Id: pgpFileSpec.c,v 1.31.16.1 1998/11/12 03:18:08 heller Exp $
70f7f7 ____________________________________________________________________________*/
68af5a
a4e610 #include "pgpPFLConfig.h"
7eaf5a
89324c #include <string.h>
afaf5a
56a146 #include "pgpDebug.h"
512b62 #include "pgpPFLErrors.h"
f50d08 #include "pgpMem.h"
52af5a
a26773 #include "pgpMemoryMgr.h"
451b42 #include "pgpStrings.h"
29af5a
58af5a
901c21 #define PGP_USE_FILE_SPEC_PRIV
16b2ca #include "pgpFileSpecPriv.h"
80af5a
5ea409 #include "pgpFileSpecVTBL.h"
a0af5a
76af5a
16ffae #if !defined(_PATH_TMP) && PGP_UNIX && HAVE_MKSTEMP
853323 #define _PATH_TMP¤  "/tmp/"
fb7454 #endif
38af5a
19af5a
8caf5a
4ca748 #define PFLFileSpecData(fileRef, type)¤ ((type *)( fileRef->data ) )
c9af5a
5216ea ¤   PGPBoolean
35dbce pflFileSpecIsValid( PFLConstFileSpecRef¤ref )
a2bb36 {
2079da ¤   return( IsntNull( ref ) && ref->magic == kPFLFileSpecMagic );
eeefe6 }
a1af5a
26af5a
3aaf5a
a55947 ¤   PGPMemoryMgrRef
37db58 PFLGetFileSpecMemoryMgr(
9f7779 ¤   PFLConstFileSpecRef fileRef)
4ebb36 {
078a1a ¤   if ( ! pflFileSpecIsValid( fileRef ) )
79ef86 ¤   ¤   return( NULL );
3967c5 ¤
c7a966 ¤   return( fileRef->memoryMgr );
f3efe6 }
20af5a
61af5a
00c744 ¤   PGPError
111b75 pgpNewFileSpec(
9c2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
f2b9cc ¤   PFLFileSpecType¤¤   type,
2c068f ¤   PGPUInt32¤  ¤   ¤   dataSize,
2d9620 ¤   PFLFileSpecRef *¤   outRef )
2bbb36 {
5c98f3 ¤   PFLFileSpecRef¤ newFileRef¤ = NULL;
189372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
8167c5 ¤
353c76 ¤   PGPValidatePtr( outRef );
993652 ¤   *outRef¤= NULL;
6bad91 ¤   PGPValidateMemoryMgr( memoryMgr );
2067c5 ¤
d7d8af ¤   /*
980812 ¤   ·* XXX In the future if PFLFileSpecs contain pointers,
4febdf ¤   ·* ····this will need to be changed.
31a4e3 ¤   ·*/
e1c585 ¤   newFileRef = (PFLFileSpecRef) PGPNewData( memoryMgr,
--b052 0005d0cf7d9401000dc Page 2 of pgpFileSpec.c
debbf5 ¤   ¤   sizeof( *newFileRef ), kPGPMemoryMgrFlags_Clear );
ea67c5 ¤
a2cd07 ¤   if ( IsntNull( newFileRef ) )
c9c7a1 ¤   {
e267d5 ¤   ¤   newFileRef->magic¤  ¤   = kPFLFileSpecMagic;
5cf255 ¤   ¤   newFileRef->type¤   ¤   = type;
816a8d ¤   ¤   newFileRef->memoryMgr¤  = memoryMgr;
e82ba8 ¤   ¤   newFileRef->dataSize¤   = dataSize;
a7afe2 ¤   ¤   newFileRef->data¤   ¤   = NULL;
382bdc ¤   ¤   newFileRef->vtbl¤   ¤   = pgpGetFileSpecVTBLForType( type );
1e1b52 ¤   ¤
3ed348 ¤   ¤   if ( dataSize != 0 )
9e5b34 ¤   ¤   {
0ccd6a ¤   ¤   ¤   PGPByte *¤  newData¤= NULL;
6887c7 ¤   ¤   ¤
95fe74 ¤   ¤   ¤   newData = (PGPByte *) PGPNewData( memoryMgr,
3b573a ¤   ¤   ¤   ¤   dataSize, kPGPMemoryMgrFlags_Clear );
9329fe ¤   ¤   ¤   if ( IsntNull( newData ) )
bff776 ¤   ¤   ¤   {
15a3dc ¤   ¤   ¤   ¤   newFileRef->data¤   = newData;
d2a3a6 ¤   ¤   ¤   }
6abb8c ¤   ¤   ¤   else
e3f776 ¤   ¤   ¤   {
5264a4 ¤   ¤   ¤   ¤   PGPFreeData( newFileRef );
0c590f ¤   ¤   ¤   ¤   newFileRef¤ = NULL;
2b14f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
eba3a6 ¤   ¤   ¤   }
790fe4 ¤   ¤   }
c59371 ¤   }
290e24 ¤   else
ffc7a1 ¤   {
3917a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
d49371 ¤   }
4d67c5 ¤
417893 ¤   *outRef¤= newFileRef;
9d67c5 ¤
1c5ea8 ¤   return err;
afefe6 }
4daf5a
c8af5a
9faf5a
39af5a
fac744 ¤   PGPError
7cbe62 PFLCopyFileSpec(
ef1bab ¤   PFLConstFileSpecRef¤fileRef,
349620 ¤   PFLFileSpecRef *¤   outRef )
01bb36 {
d298f3 ¤   PFLFileSpecRef¤ newFileRef¤ = NULL;
fb9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
2967c5 ¤
073c76 ¤   PGPValidatePtr( outRef );
bb3652 ¤   *outRef¤= NULL;
b465f3 ¤   PFLValidateFileSpec( fileRef );
4767c5 ¤
5e04bc ¤   err¤= pgpNewFileSpec( fileRef->memoryMgr, fileRef->type,
8134e1 ¤   ¤   ¤   fileRef->dataSize, &newFileRef );
5cf1e7 ¤   if ( IsntPGPError( err ) )
21c7a1 ¤   {
c92997 ¤   ¤   PGPByte *¤  dataPtr;
2d1b52 ¤   ¤
cc8db3 ¤   ¤   /* copy entire struct, being careful to preserve embedded pointer */
21556c ¤   ¤   dataPtr¤¤   ¤   ¤   = PFLFileSpecData( newFileRef, PGPByte );
34aa72 ¤   ¤   *newFileRef¤¤   ¤   = *fileRef;
2f420b ¤   ¤   newFileRef->data¤   = dataPtr;
6c1b52 ¤   ¤
45b899 ¤   ¤   /* copy data itself */
45edbd ¤   ¤   if ( IsntNull( dataPtr ) )
365b34 ¤   ¤   {
615272 ¤   ¤   ¤   pgpCopyMemory( fileRef->data,
e3561b ¤   ¤   ¤   ¤   newFileRef->data, fileRef->dataSize );
b60fe4 ¤   ¤   }
5d9371 ¤   }
--c6da 000adf71c40401000dc Page 3 of pgpFileSpec.c
2a67c5 ¤
c87893 ¤   *outRef¤= newFileRef;
c567c5 ¤
234c5f ¤   pgpAssertErrWithPtr( err, *outRef );
c067c5 ¤
865ea8 ¤   return err;
efefe6 }
d8af5a
2aaf5a
c3c744 ¤   PGPError
b2515b PFLFreeFileSpec( PFLFileSpecRef¤fileRef)
f1bb36 {
d465f3 ¤   PFLValidateFileSpec( fileRef );
c267c5 ¤
37dd99 ¤   if ( IsntNull( fileRef->data ) )
cec7a1 ¤   {
023fc0 ¤   ¤   PGPFreeData( fileRef->data );
6c9371 ¤   }
b567c5 ¤
150a2d ¤   PGPFreeData( fileRef );
9567c5 ¤
0d2d68 ¤   return( kPGPError_NoErr );
7aefe6 }
21af5a
490335 /*____________________________________________________________________________
9fff6e ¤   Caller must free 'outName' with PGPFreeData
7cf7f7 ____________________________________________________________________________*/
24c744 ¤   PGPError
6a8a5e PFLGetFileSpecName(
541bab ¤   PFLConstFileSpecRef¤fileRef,
66f2ca ¤   char **¤¤   ¤   ¤   outName )
d7bb36 {
8cc2ad ¤   char¤   ¤   ¤   tempName[ 256 ];
719372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b8e238 ¤   char *¤ ¤   ¤   allocName¤  = NULL;
c967c5 ¤
6e1adc ¤   PGPValidatePtr( outName );
4c5806 ¤   *outName¤   = NULL;
7465f3 ¤   PFLValidateFileSpec( fileRef );
2367c5 ¤
2e3ec2 ¤   err¤= PFLGetFileSpecNameBuffer( fileRef, sizeof( tempName ), tempName );
a3f1e7 ¤   if ( IsntPGPError( err ) )
cac7a1 ¤   {
ec87c6 ¤   ¤   PGPUInt32¤  ¤   nameLength;
8867c5 ¤
c41107 ¤   ¤   nameLength¤ = strlen( tempName );
241b52 ¤   ¤
22b86e ¤   ¤   allocName = (char *)PGPNewData( fileRef->memoryMgr,
afdea9 ¤   ¤   ¤   nameLength + 1, 0);
f795d1 ¤   ¤   if ( IsntNull( allocName ) )
3e5b34 ¤   ¤   {
ec7221 ¤   ¤   ¤   strcpy( allocName, tempName );
f10fe4 ¤   ¤   }
110e1d ¤   ¤   else
015b34 ¤   ¤   {
2f124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
d10fe4 ¤   ¤   }
e79371 ¤   }
5767c5 ¤
0cc202 ¤   *outName¤   = allocName;
e95ea8 ¤   return err;
32efe6 }
48af5a
afc744 ¤   PGPError
ccc74e PFLGetFileSpecNameBuffer(
291bab ¤   PFLConstFileSpecRef¤fileRef,
3489b6 ¤   PGPSize¤¤   ¤   ¤   maxSize,
57cc0d ¤   char *¤ ¤   ¤   ¤   outName )
abbb36 {
10c2ad ¤   char¤   ¤   ¤   tempName[ 256 ];
2b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
ad67c5 ¤
--706e 000c01c8bb8401000dc Page 4 of pgpFileSpec.c
cc1adc ¤   PGPValidatePtr( outName );
c58eb4 ¤   PGPValidateParam( maxSize >= 1 );
fc65f3 ¤   PFLValidateFileSpec( fileRef );
bf67c5 ¤
1e6faa ¤   err¤= CallGetNameProc( fileRef, tempName );
5cf1e7 ¤   if ( IsntPGPError( err ) )
5cc7a1 ¤   {
64e94a ¤   ¤   if ( strlen( tempName ) + 1 <= maxSize )
9d5b34 ¤   ¤   {
18849a ¤   ¤   ¤   strcpy( outName, tempName );
cd0fe4 ¤   ¤   }
520e1d ¤   ¤   else
735b34 ¤   ¤   {
654aea ¤   ¤   ¤   err¤= kPGPError_BufferTooSmall;
e70fe4 ¤   ¤   }
929371 ¤   }
9967c5 ¤
a75ea8 ¤   return err;
2befe6 }
a7af5a
caaf5a
2baf5a
a2c744 ¤   PGPError
58c283 PFLSetFileSpecName(
c71e85 ¤   PFLFileSpecRef¤ ¤   fileRef,
13b003 ¤   char const *¤   ¤   newName)
7ebb36 {
6e9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
cb67c5 ¤
454b18 ¤   PGPValidatePtr( newName );
1965f3 ¤   PFLValidateFileSpec( fileRef );
e367c5 ¤
0a30d5 ¤   err¤= CallSetNameProc( fileRef, newName );
9767c5 ¤
e55ea8 ¤   return err;
18efe6 }
ebaf5a
b6c744 ¤   PGPError
8c4482 PFLComposeFileSpec(
73603e ¤   PFLConstFileSpecRef¤parentDir,
09a355 ¤   char const *¤   ¤   fileName,
679620 ¤   PFLFileSpecRef *¤   outRef )
d9bb36 {
799372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
8e67c5 ¤
d05cef ¤   PGPValidatePtr( fileName );
343c76 ¤   PGPValidatePtr( outRef );
ffd66b ¤   PFLValidateFileSpec( parentDir );
f6af5a
68cd60 ¤   *outRef = NULL;
5167c5 ¤
eb5779 ¤   err = CallComposeProc( parentDir, fileName, outRef );
bb67c5 ¤
7f5ea8 ¤   return err;
d5efe6 }
c8af5a
11af5a
570335 /*____________________________________________________________________________
d60451 ¤   Get the maximum length namre legal for this file spec. ·The maximum
cf6bcc ¤   length may depend not only on the OS, but also on the volume format.
dbf7f7 ____________________________________________________________________________*/
90c744 ¤   PGPError
f9c177 PFLGetMaxFileSpecNameLength(
90b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
e04ab4 ¤   PGPSize *¤  ¤   ¤   ¤   maxLength)
48bb36 {
be9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0367c5 ¤
96e29b ¤   PGPValidatePtr( maxLength );
cb1dbe ¤   *maxLength¤ = 0;
5b65f3 ¤   PFLValidateFileSpec( fileRef );
c067c5 ¤
--2121 00018907b5e401000dc Page 5 of pgpFileSpec.c
6a80d1 ¤   err¤= CallGetMaxNameLength( fileRef, maxLength );
8e67c5 ¤
a15ea8 ¤   return err;
caefe6 }
4aaf5a
f0af5a
610335 /*____________________________________________________________________________
934439 ¤   Extend the file name to include the extension, truncating the base name
377b56 ¤   if necessary to meet the constraints of maximum name length
88f7f7 ____________________________________________________________________________*/
41c744 ¤   PGPError
f5de2f PFLExtendFileSpecName(
88db0b ¤   PFLFileSpecRef¤ fileRef,
8715bb ¤   char const *¤   extension)
f4bb36 {
8e9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
49e4e3 ¤   PGPSize¤¤   ¤   maxLength;
3567c5 ¤
3dc492 ¤   PGPValidatePtr( extension );
af65f3 ¤   PFLValidateFileSpec( fileRef );
1e67c5 ¤
0c747e ¤   err¤= PFLGetMaxFileSpecNameLength( fileRef, &maxLength );
c1f1e7 ¤   if ( IsntPGPError( err ) )
1fc7a1 ¤   {
96a38d ¤   ¤   PGPUInt32¤  extensionLength;
5c1b52 ¤   ¤
a64f55 ¤   ¤   extensionLength¤= strlen( extension );
17f60e ¤   ¤   if ( strlen( extension ) > maxLength )
265b34 ¤   ¤   {
e3fdcd ¤   ¤   ¤   err¤= kPGPError_BadParams;
080fe4 ¤   ¤   }
030e1d ¤   ¤   else
545b34 ¤   ¤   {
181770 ¤   ¤   ¤   char¤   tempName[ 512 ];
1187c7 ¤   ¤   ¤
5f0cc1 ¤   ¤   ¤   err¤= PFLGetFileSpecNameBuffer( fileRef,
7b046b ¤   ¤   ¤   ¤   ¤   sizeof( tempName ), tempName );
e23c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
5ef776 ¤   ¤   ¤   {
1585ab ¤   ¤   ¤   ¤   PGPUInt32¤  nameLength;
182b85 ¤   ¤   ¤   ¤
0e67fc ¤   ¤   ¤   ¤   nameLength¤ = strlen( tempName );
331966 ¤   ¤   ¤   ¤   if ( nameLength + extensionLength > maxLength )
4b72c3 ¤   ¤   ¤   ¤   {
519a4c ¤   ¤   ¤   ¤   ¤   /* truncate base name */
3d30cb ¤   ¤   ¤   ¤   ¤   tempName[ maxLength - extensionLength ]¤= '\0';
cb2613 ¤   ¤   ¤   ¤   }
4e700a ¤   ¤   ¤   ¤   strcat( tempName, extension );
79d63e ¤   ¤   ¤   ¤   err¤= PFLSetFileSpecName( fileRef, tempName );
69a3a6 ¤   ¤   ¤   }
e90fe4 ¤   ¤   }
6f9371 ¤   }
8067c5 ¤
0f5ea8 ¤   return err;
21efe6 }
2caf5a
330335 /*____________________________________________________________________________
940584 ¤   Get a unique file spec. ·If the input spec does not exist, then it will
ea9721 ¤   be returned.
7ef7f7 ____________________________________________________________________________*/
20c744 ¤   PGPError
68f887 PFLFileSpecGetUniqueSpec(
635a35 ¤   PFLConstFileSpecRef¤spec,
af81aa ¤   PFLFileSpecRef *¤   uniqueOut )
e3bb36 {
6d9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
c3ec15 ¤   PFLFileSpecRef¤ out¤= NULL;
8bf1c3 ¤   PGPBoolean¤ ¤   exists;
4c67c5 ¤
cd903a ¤   PGPValidatePtr( uniqueOut );
9e0722 ¤   *uniqueOut¤ = NULL;
180282 ¤   PFLValidateFileSpec( spec );
--091b 00050c676d5401000dc Page 6 of pgpFileSpec.c
2a67c5 ¤
980996 ¤   /* important to copy it to preserve meta-data */
2aec7c ¤   err¤= PFLCopyFileSpec( spec, &out );
2ef1e7 ¤   if ( IsntPGPError( err ) )
4a29d9 ¤   ¤   err¤= PFLFileSpecExists( out, &exists );
1a67c5 ¤
e42dfb ¤   if ( IsntPGPError( err ) && exists )
17c7a1 ¤   {
b1df6c ¤   ¤   PGPUInt32¤  number = 1;
2fcdca ¤   ¤   char¤   ¤   origName[ 256 ];
a94492 ¤   ¤   PGPSize¤¤   maxNameLength;
9f1b52 ¤   ¤
0b4060 ¤   ¤   err¤= PFLGetMaxFileSpecNameLength( spec, &maxNameLength );
3b7d98 ¤   ¤   if ( IsntPGPError( err ) )
2d5b34 ¤   ¤   {
64f3b1 ¤   ¤   ¤   err¤= PFLGetFileSpecNameBuffer( spec,
dde097 ¤   ¤   ¤   ¤   sizeof( origName ), origName );
8b0fe4 ¤   ¤   }
c01b52 ¤   ¤
c47311 ¤   ¤   if ( IsntPGPError( err ) ) do
0c5b34 ¤   ¤   {
28edd4 ¤   ¤   ¤   char¤   tempName[ 256 ];
529b1a ¤   ¤   ¤   PGPSize¤maxSize;
5687c7 ¤   ¤   ¤
1e49d7 ¤   ¤   ¤   /* name can't exceed buffer size and must be <= platform limits */
664bcd ¤   ¤   ¤   maxSize¤= pgpMin( maxNameLength + 1, sizeof(tempName ) );
4687c7 ¤   ¤   ¤
791570 ¤   ¤   ¤   err¤= PGPNewNumberFileName( origName, "", number,
2e706e ¤   ¤   ¤   ¤   ¤   maxSize, tempName );
ea8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
75f622 ¤   ¤   ¤   ¤   break;
0d87c7 ¤   ¤   ¤
35bb1d ¤   ¤   ¤   err¤= PFLSetFileSpecName( out, tempName );
ae8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
69f622 ¤   ¤   ¤   ¤   break;
5287c7 ¤   ¤   ¤
627ac2 ¤   ¤   ¤   err¤= PFLFileSpecExists( out, &exists );
7949fc ¤   ¤   ¤   if ( IsPGPError( err ) || ! exists )
62f622 ¤   ¤   ¤   ¤   break;
dec459 ¤   ¤   ¤   ++number;
c387c7 ¤   ¤   ¤
ac0d89 ¤   ¤   } while ( TRUE );
1b9371 ¤   }
5767c5 ¤
c9ea2a ¤   if ( IsPGPError( err ) && IsntNull( out ) )
60c7a1 ¤   {
5a5d67 ¤   ¤   PFLFreeFileSpec( out );
1b3cf7 ¤   ¤   out¤= NULL;
fa9371 ¤   }
b067c5 ¤
b52351 ¤   *uniqueOut¤ = out;
f7deb7 ¤   return( err );
e3efe6 }
efaf5a
34af5a
bec744 ¤   PGPError
162aa2 PFLExportFileSpec(
96b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
da94ec ¤   PGPByte **¤ ¤   ¤   ¤   outData,
c05d75 ¤   PGPSize *¤  ¤   ¤   ¤   outDataSize )
36bb36 {
f926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
bfada4 ¤   PGPByte *¤  data¤   ¤   = NULL;
b597cc ¤   PGPSize¤¤   dataSize¤   = 0;
9f67c5 ¤
fae13f ¤   /* make sure we set these to known values first */
14640b ¤   if ( IsntNull( outData ) )
53bb7c ¤   ¤   *outData¤   = NULL;
da51ff ¤   if ( IsntNull( outDataSize ) )
1b96f6 ¤   ¤   *outDataSize¤   = 0;
ca1b52 ¤   ¤
5076dc ¤   PGPValidatePtr( outData );
--897e 0000a548133401000dc Page 7 of pgpFileSpec.c
57dc71 ¤   PGPValidatePtr( outDataSize );
1165f3 ¤   PFLValidateFileSpec( fileRef );
6a67c5 ¤
5187ce ¤   err¤= CallExportProc( fileRef, &data, &dataSize );
4bf1e7 ¤   if ( IsntPGPError( err ) )
dcc7a1 ¤   {
3b0315 ¤   ¤   PGPMemoryMgrRef¤memoryMgr¤  = fileRef->memoryMgr;
36fc70 ¤   ¤   void *¤ ¤   ¤   temp;
011b52 ¤   ¤
32a2be ¤   ¤   /* prepend the object type byte to the data */
e656c3 ¤   ¤   dataSize¤   += 1;
29bd03 ¤   ¤   temp¤   = data;
cf07be ¤   ¤   err¤= PGPReallocData( memoryMgr, &temp, dataSize, 0);
dfbfad ¤   ¤   data¤   = (PGPByte *)temp;
eb7d98 ¤   ¤   if ( IsntPGPError( err ) )
8f5b34 ¤   ¤   {
c6177e ¤   ¤   ¤   /* shift data up and insert the type byte */
733dfd ¤   ¤   ¤   pgpCopyMemory( data, data + 1, dataSize - 1 );
36fc5e ¤   ¤   ¤   data[ 0 ]¤  = (PGPByte)fileRef->type;
6d0d8f ¤   ¤   ¤   pgpAssert( (PFLFileSpecType)data[ 0 ] == fileRef->type );
140fe4 ¤   ¤   }
550e1d ¤   ¤   else
085b34 ¤   ¤   {
05316d ¤   ¤   ¤   PGPFreeData( data );
932a3b ¤   ¤   ¤   data¤   ¤   = NULL;
28cd5a ¤   ¤   ¤   dataSize¤   = 0;
910fe4 ¤   ¤   }
7d9371 ¤   }
7867c5 ¤
fe1a8f ¤   *outData¤   ¤   = data;
a2ad5e ¤   *outDataSize¤   = dataSize;
c85ea8 ¤   return err;
3defe6 }
83af5a
45af5a
48c744 ¤   PGPError
6d9073 PFLImportFileSpec(
e1d8a8 ¤   PGPMemoryMgrRef¤¤   context,
106f48 ¤   PGPByte const *¤¤   buffer,
0b1213 ¤   PGPSize¤¤   ¤   ¤   size,
f39620 ¤   PFLFileSpecRef *¤   outRef )
ddbb36 {
469479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
b1d103 ¤   PFLFileSpecRef¤ ¤   ¤   newRef¤ = NULL;
464b61 ¤   PFLFileSpecType¤¤   ¤   type;
b4bc9d ¤   PGPByte const *¤¤   ¤   typeData;
0667c5 ¤
b43c76 ¤   PGPValidatePtr( outRef );
093652 ¤   *outRef¤= NULL;
aab99f ¤   PGPValidatePtr( buffer );
c67243 ¤   PGPValidateParam( PGPMemoryMgrIsValid( context ) );
06028f ¤   PGPValidateParam( size != 0);
09af5a
76079d ¤   /* first byte is the type of file spec */
d2d6ff ¤   type¤   ¤   = (PFLFileSpecType)buffer[ 0 ];
60fd62 ¤   typeData¤   = buffer + 1;
184f31 ¤   PGPValidateParam( type == kPFLFileSpecFullPathType ||
15b284 ¤   ¤   type == kPFLFileSpecMacType );
2067c5 ¤
f58edd ¤   err¤= pgpNewFileSpec( context, type, 0, &newRef );
90f1e7 ¤   if ( IsntPGPError( err ) )
53c7a1 ¤   {
11e4e9 ¤   ¤   err¤= CallImportProc( newRef, typeData, size-1 );
b8be18 ¤   ¤   if ( IsPGPError( err ) )
015b34 ¤   ¤   {
9cdf1b ¤   ¤   ¤   PFLFreeFileSpec( newRef );
7282ad ¤   ¤   ¤   newRef¤ = NULL;
ec0fe4 ¤   ¤   }
389371 ¤   }
b167c5 ¤
f1cdaf ¤   *outRef¤= newRef;
0a67c5 ¤
--2284 00025302cbe401000dc Page 8 of pgpFileSpec.c
ec5ea8 ¤   return err;
2aefe6 }
e0af5a
bbaf5a
2faf5a
eac744 ¤   PGPError
b2b464 PFLSetFileSpecMetaInfo(
f51e85 ¤   PFLFileSpecRef¤ ¤   fileRef,
a1acee ¤   const void *¤   ¤   info )
77bb36 {
d89372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
e467c5 ¤
2e65f3 ¤   PFLValidateFileSpec( fileRef );
a767c5 ¤
2dabe2 ¤   err¤= CallSetMetaInfoProc( fileRef, info);
c167c5 ¤
bedeb7 ¤   return( err );
56efe6 }
dcaf5a
1faf5a
1dc744 ¤   PGPError
d852c6 PFLFileSpecExists(
68db0b ¤   PFLFileSpecRef¤ fileRef,
a9fb2f ¤   PGPBoolean *¤   exists )
a0bb36 {
5c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b867c5 ¤
1bc9bf ¤   PGPValidatePtr( exists );
478718 ¤   *exists¤= FALSE;
7465f3 ¤   PFLValidateFileSpec( fileRef );
3067c5 ¤
99db8a ¤   err¤= CallExistsProc( fileRef, exists );
e067c5 ¤
d1deb7 ¤   return( err );
0fefe6 }
44ae30 ¤   ¤   ¤   ¤   ¤
23af5a
cec744 ¤   PGPError
a7ca64 PFLFileSpecCreate( PFLFileSpecRef¤  fileRef)
6ebb36 {
729372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
fd67c5 ¤
a265f3 ¤   PFLValidateFileSpec( fileRef );
ff67c5 ¤
1b16c8 ¤   err¤= CallCreateProc( fileRef );
ab67c5 ¤
c9deb7 ¤   return( err );
6fefe6 }
49af5a
5daf5a
d0c744 ¤   PGPError
3ab1ce PFLFileSpecDelete( PFLConstFileSpecRef¤ fileRef)
37bb36 {
4b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
ae67c5 ¤
b565f3 ¤   PFLValidateFileSpec( fileRef );
d867c5 ¤
933374 ¤   err¤= CallDeleteProc( fileRef, info);
c367c5 ¤
63deb7 ¤   return( err );
dcefe6 }
e5af5a
18af5a
cac744 ¤   PGPError
37d9a1 PFLFileSpecRename(
dbdb0b ¤   PFLFileSpecRef¤ fileRef,
cebb28 ¤   const char *¤   newName )
74bb36 {
6c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
3a67c5 ¤
b765f3 ¤   PFLValidateFileSpec( fileRef );
254b18 ¤   PGPValidatePtr( newName );
--827e 0007560daf2401000dc Page 9 of pgpFileSpec.c
2a67c5 ¤
63d944 ¤   err¤= CallRenameProc( fileRef, newName );
c267c5 ¤
92deb7 ¤   return( err );
ffefe6 }
b5af5a
d7c744 ¤   PGPError
a44dd9 PFLGetParentDirectory(
fdb4fd ¤   PFLConstFileSpecRef¤¤   childSpec,
41e58f ¤   PFLFileSpecRef *¤   ¤   outParent )
9fbb36 {
0726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
f167c5 ¤
2b82a5 ¤   PFLValidateFileSpec( childSpec );
ffd0fd ¤   PGPValidatePtr( outParent );
6bdda2 ¤   *outParent¤ = NULL;
04af5a
35fa15 ¤   err¤= CallGetParentDirProc( childSpec, outParent );
0d67c5 ¤
47deb7 ¤   return( err );
4aefe6 }
d1af5a
63af5a
93c744 ¤   PGPError
09e9bb PFLGetTempFileSpec(
d1378d ¤   PGPMemoryMgrRef¤¤   ¤   context,
d1e2af ¤   PFLConstFileSpecRef¤¤   optionalRef,¤   /* may be NULL */
ee514f ¤   PFLFileSpecRef *¤   ¤   outRef)
f3bb36 {
cb26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
ca67c5 ¤
553c76 ¤   PGPValidatePtr( outRef );
463652 ¤   *outRef¤= NULL;
be661e ¤   PGPValidateParam( IsNull( optionalRef ) ||
429cb0 ¤   ¤   pflFileSpecIsValid( optionalRef ) );
6d67c5 ¤
3fcf60 ¤   err¤= pgpPlatformGetTempFileSpec( context, optionalRef, outRef );
7167c5 ¤
7fdeb7 ¤   return( err );
0eefe6 }
feaf5a
b3c744 ¤   PGPError
98d26b PFLGetFileInfo(
d25a35 ¤   PFLConstFileSpecRef¤spec,
bf56c1 ¤   PFLFileInfo *¤  ¤   outInfo )
81bb36 {
0ffeab ¤   PGPValidatePtr( outInfo );
9c0282 ¤   PFLValidateFileSpec( spec );
ca89b7 ¤   pgpClearMemory( outInfo, sizeof( *outInfo ) );
96af5a
2ec363 ¤   return pgpPlatformGetFileInfo( spec, outInfo );
2cefe6 }
e7af5a
51c744 ¤   PGPError
adde50 PFLNewDirectoryIter(
904505 ¤   PFLConstFileSpecRef¤¤   parentDir,
c1a05a ¤   PFLDirectoryIterRef *¤  outIter )
2ebb36 {
83d66b ¤   PFLValidateFileSpec( parentDir );
7e667c ¤   PGPValidatePtr( outIter );
5f18d6 ¤   *outIter = NULL;
96af5a
7d29b2 ¤   return pgpPlatformNewDirectoryIter( parentDir, outIter );
95efe6 }
b0af5a
e3c744 ¤   PGPError
e25965 PFLNextFileInDirectory(
789676 ¤   PFLDirectoryIterRef¤¤   iter,
1880bd ¤   PFLFileSpecRef *¤   ¤   outRef )
4dbb36 {
d9d4ad ¤   PGPValidatePtr( iter );
753c76 ¤   PGPValidatePtr( outRef );
--9fae 001b5fe4d96401000dc Page 10 of pgpFileSpec.c
44cd60 ¤   *outRef = NULL;
85af5a
710820 ¤   return pgpPlatformNextFileInDirectory( iter, outRef );
b9efe6 }
15af5a
1ac744 ¤   PGPError
468157 PFLFreeDirectoryIter(
ed1585 ¤   PFLDirectoryIterRef¤¤   iter )
ddbb36 {
82d4ad ¤   PGPValidatePtr( iter );
81af5a
bec615 ¤   return pgpPlatformFreeDirectoryIter( iter );
a9efe6 }
53af5a
4338e5 /*
b0e6c5 ·* Local Variables:
a69b19 ·* tab-width: 4
16e7a4 ·* End:
a4b612 ·* vi: ts=4 sw=4
c06c42 ·* vim: si
b5495d ·*/
--e651 000e824e021401000dd Page 1 of pgpFileSpec.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a3a348 ¤   Platform-independent file-specification. ·Specifies the *location* of a
6e49d1 ¤   file in the file system. ·Also included are utility routines for
e76bcb ¤   manipulating files.
d767c5 ¤
a39f1e ¤   Note that a PGPFileSpec is not an object; it does not have subclasses
b42597 ¤   or inheritence.
fbaf5a
41d97f ¤   $Id: pgpFileSpec.h,v 1.20.16.1 1998/11/12 03:18:09 heller Exp $
12f7f7 ____________________________________________________________________________*/
563955 #ifndef Included_pgpFileSpec_h¤ /* [ */
7aeb79 #define Included_pgpFileSpec_h
efaf5a
e872c6 #include <time.h>¤  /* Temporary, for time_t below */
a6af5a
5e6773 #include "pgpMemoryMgr.h"
d4af5a
02392c #include "pflTypes.h"
09af5a
b6af5a
2799c6 PGP_BEGIN_C_DECLARATIONS
82cbcf #if PRAGMA_IMPORT_SUPPORTED
70b981 #pragma import on
fe7454 #endif
b5af5a
ebdd51 enum PFLFileInfoFlags_
a2bb36 {
b9f8d8 ¤   kPGPFileInfo_IsDirectory¤   = ( 1L << 0 ),
685f52 ¤   kPGPFileInfo_IsPlainFile¤   = ( 1L << 1 )
ea82f7 };
f1547a typedef PGPUInt32¤  PFLFileInfoFlags;
f2d83c ·
24a3db typedef struct PFLFileInfo_
85bb36 {
a5b889 ¤   PFLFileInfoFlags¤   flags;
c611b8 ¤   PGPFileOffset¤  ¤   dataLength;
54e37c ¤   time_t¤ ¤   ¤   ¤   modificationTime;
06078b } PFLFileInfo;
2faf5a
41eba2 PGPError ¤  PFLCopyFileSpec( PFLConstFileSpecRef spec,
5f4710 ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef * outRef );
0b67c5 ¤
54ef7b PGPError ¤  PFLFreeFileSpec( PFLFileSpecRef ref);
4aaf5a
39af80 PGPMemoryMgrRef¤PFLGetFileSpecMemoryMgr( PFLConstFileSpecRef spec );
79af5a
1ce0a1 /* *outData must be freed with PGPFreeData */
973a8b PGPError ¤  PFLExportFileSpec( PFLConstFileSpecRef spec,
e023bd ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **outData, PGPSize *outSize );
c394aa ¤   ¤   ¤   ¤   ¤   ¤
c5a307 PGPError ·¤ PFLImportFileSpec( PGPMemoryMgrRef context,
5878c8 ¤   ¤   ¤   ¤   ¤   PGPByte const *buffer, PGPSize size,
07e038 ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outRef );
6eaf5a
282e88 /* *outName must be freed with PGPFreeData */
15af1b PGPError ¤  PFLGetFileSpecName( PFLConstFileSpecRef spec,
b27dc8 ¤   ¤   ¤   ¤   ¤   char **outName );
88af5a
5c650f /* put C-String name into client-supplied buffer */
3e6812 PGPError ¤  PFLGetFileSpecNameBuffer( PFLConstFileSpecRef spec,
0c5d8b ¤   ¤   ¤   ¤   PGPSize maxSize, char *outName );
42af5a
8d83cc /* does not rename the file itself */
4f3ba9 PGPError ¤  ¤   PFLSetFileSpecName( PFLFileSpecRef spec,
597bff ¤   ¤   ¤   ¤   ¤   ¤   char const *newName);
5294aa ¤   ¤   ¤   ¤   ¤   ¤
1690db /* create a new filespec from a directory spec and a filename */
e7ba74 PGPError ¤  ¤   PFLComposeFileSpec( PFLConstFileSpecRef parentDir,
e8eaa1 ¤   ¤   ¤   ¤   ¤   ¤   char const *fileName,
--94ce 00002b6889b401000dd Page 2 of pgpFileSpec.h
53af06 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outRef );
e894aa ¤   ¤   ¤   ¤   ¤   ¤
bd837c /* extend the file name with the extension.
f9ae2c ···Takes into account max name length */
be9d6d PGPError ¤  ¤   PFLExtendFileSpecName( PFLFileSpecRef spec,
13b07a ¤   ¤   ¤   ¤   ¤   ¤   char const *extension);
4894aa ¤   ¤   ¤   ¤   ¤   ¤
a483aa /* get the maximum name length a file spec can handle */
ad3795 PGPError ¤  ¤   PFLGetMaxFileSpecNameLength( PFLConstFileSpecRef spec,
7897fd ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  maxLength);
4faf5a
e96fcf /* remember meta information for file. ·Used when create file */
7e403e PGPError¤   ¤   PFLSetFileSpecMetaInfo( PFLFileSpecRef spec,
8c53dd ¤   ¤   ¤   ¤   ¤   const void *info);
31af5a
e59c98 /* generate a unique FileSpec based on 'spec'. ·If spec doesn't exist,
4d3beb then output will be the same (but a copy) */
6d0679 PGPError ¤  ¤   PFLFileSpecGetUniqueSpec( PFLConstFileSpecRef spec,
8423d7 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *uniqueOut );
56af5a
c17b47 PGPError¤   ¤   PFLFileSpecExists( PFLFileSpecRef spec,
9c2d5d ¤   ¤   ¤   ¤   ¤   PGPBoolean *exists );
d192f3 PGPError¤   ¤   PFLFileSpecCreate( PFLFileSpecRef spec );
68c9ac PGPError¤   ¤   PFLFileSpecDelete( PFLConstFileSpecRef spec );
afaf5a
a18fd6 /* Renames the file AND changes the name in the file spec itself.
c4ad3a ¤   If an error occurs, the spec is not changed. The name is *not*
bb5690 ¤   the full path, but just the filename itself.
f17fe0 */
e8ffe9 PGPError¤   ¤   PFLFileSpecRename( PFLFileSpecRef spec,
8623b1 ¤   ¤   ¤   ¤   ¤   const char *newName );
44af5a
278749 PGPError¤   ¤   PFLGetParentDirectory( PFLConstFileSpecRef fileInDir,
c2300b ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outParent );
e2ae30 ¤   ¤   ¤   ¤   ¤
4ca1b3 PGPError¤   ¤   PFLGetTempFileSpec( PGPMemoryMgrRef context,·
abbccd ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef optionalRef, PFLFileSpecRef * outRef );
ddaf5a
bfa62e /* Get file information */
e3b1f1 PGPError¤   ¤   PFLGetFileInfo( PFLConstFileSpecRef spec,
eafcb5 ¤   ¤   ¤   ¤   ¤   PFLFileInfo *outInfo );
64af5a
e30d4b /* Directory iteration functions */
7350ab PGPError¤   ¤   PFLNewDirectoryIter( PFLConstFileSpecRef parentDir,
69a0fb ¤   ¤   ¤   ¤   ¤   PFLDirectoryIterRef * outIter );
cc412c PGPError¤   ¤   PFLNextFileInDirectory( PFLDirectoryIterRef iter,
3a4710 ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef * outRef );
96eb65 PGPError¤   ¤   PFLFreeDirectoryIter( PFLDirectoryIterRef iter );
d6af5a
55af5a
fbcfc6 PGPBoolean¤ ¤   pflFileSpecIsValid( PFLConstFileSpecRef¤ref );
113c14 #define PFLValidateFileSpec( ref )¤ ¤   \
380f6e ¤   PGPValidateParam( pflFileSpecIsValid( ref ) )
d4af5a
33af5a
33cbcf #if PRAGMA_IMPORT_SUPPORTED
b02ced #pragma import reset
0f7454 #endif
111254 PGP_END_C_DECLARATIONS
0aaf5a
56af5a
f038e5 /*
c584bc ·* Flag indicating whether attempting to delete an open file will
b14277 ·* disrupt the process which has the file open. ·Depends on the platform.
80fb7a ·* If deletion fails in this case, or succeeds but keeps the file
d4725c ·* accessable until the last close, then deletes are considered safe
ccd2c5 ·* and this flag can be set to 0 safely.
81495d ·*/
64ee4b #define PFL_PLATFORM_UNSAFE_DELETE¤ 0
62af5a
b1af5a
021c36 #define _pgpFileSpecIncludeRightStuff_
--8d61 00152c18b65401000dd Page 3 of pgpFileSpec.h
e0af5a
530ccc #if PGP_MACINTOSH
841613 #include "pgpFileSpecMac.h"
55db21 #else
a14310 #include "pgpFileSpecStd.h"
0b7454 #endif
92af5a
3c39f6 #undef _pgpFileSpecIncludeRightStuff_
c6af5a
32bef0 #endif¤ /* ] Included_pgpFileSpec_h */
ceaf5a
7738e5 /*
9ee6c5 ·* Local Variables:
9a9b19 ·* tab-width: 4
8ee7a4 ·* End:
e4b612 ·* vi: ts=4 sw=4
796c42 ·* vim: si
52495d ·*/
--c1a8 0004d18284d401000de Page 1 of pgpFileSpecMac.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
646f57 ¤   $Id: pgpFileSpecMac.c,v 1.24.14.1 1998/11/12 03:18:10 heller Exp $
eef7f7 ____________________________________________________________________________*/
0faf5a
ecc21c #if PGP_MACINTOSH¤  /* [ */
a6af5a
8cb2bf #include <Errors.h>
771ef3 #include <Folders.h>
425a11 #include <Script.h>
30af5a
8ee610 #include "pgpPFLConfig.h"
c0af5a
14324c #include <string.h>
47feb2 #include <stdio.h>
1a156c #include <FSp_fopen.h>
9aaf5a
c3a146 #include "pgpDebug.h"
e52b62 #include "pgpPFLErrors.h"
bbbbf4 #include "MacFiles.h"
b085c2 #include "MacStrings.h"
f70d08 #include "pgpMem.h"
0faf5a
656773 #include "pgpMemoryMgr.h"
69af5a
871c21 #define PGP_USE_FILE_SPEC_PRIV
2ebe15 #include "PGPFileSpecPriv.h"
562dd2 #include "PGPFileSpecMacPriv.h"
74af5a
2aaf5a
b2c6a9 typedef struct MyData
6bbb36 {
7e1faf ¤   /* in memory state can refer to a real volume or one
da034a ¤   that is not mounted. ·If the volume is not available
6de2dc ¤   then the spec contains the parID and name, but vRefNum
97b2c9 ¤   is set to kInvalidVRefNum. ·The 'nm' struct contains
63f576 ¤   info needed to get the vRefNum later.
a69faa ¤   */
b9c480 ¤   PGPBoolean¤ ¤   vRefNumIsValid;¤
984a89 ¤   struct
e858c8 ¤   {¤  ¤
6a7f38 ¤   ¤   long¤   ¤   ¤   volumeCreationDate;
237fdb ¤   ¤   unsigned char¤  volumeName[ 32 ];
773d7e ¤   } volumeInfo;
1667c5 ¤
d9496c ¤   FSSpec¤ ¤   spec;
ff2420 ¤   PFLFileSpecMacMetaInfo¤ metaInfo;
f9908c } MyData;
19d457 #define kInvalidVRefNum¤¤   1¤  /* boot volume */
e5af5a
e5af5a
2c66ae struct PFLDirectoryIter
4fbb36 {
8dd91c ¤   PGPMemoryMgrRef¤memoryMgr;
adb692 ¤   short¤  ¤   ¤   vRefNum;
9f593a ¤   long¤   ¤   ¤   parID;
bacf98 ¤   long¤   ¤   ¤   dirIndex;
5282f7 };
b1af5a
55af5a
f9bc93 static PGPError¤ResolveVolume( MyData *myData );
8aaf5a
57af5a
bfa770 #define GetMyData( ref )¤   ( (MyData *)(ref)->data )
9faf5a
1c5b9f static PGPError¤sExportProc( PFLConstFileSpecRef ref,
44f543 ¤   ¤   ¤   ¤   ¤   PGPByte **data, PGPSize *dataSize );
62e333 static PGPError¤sImportProc( PFLFileSpecRef ref,
4d54c2 ¤   ¤   ¤   ¤   ¤   PGPByte const *data, PGPSize dataSize );
--1071 000d9b13000401000de Page 2 of pgpFileSpecMac.c
3bb442 static PGPError¤sGetNameProc( PFLConstFileSpecRef ref, char name[ 256 ] );
eff35a static PGPError¤sSetNameProc( PFLFileSpecRef ref, char const *name );
622249 static PGPError¤sSetMetaInfoProc( PFLFileSpecRef ref, void const *info );
e85a33 static PGPError¤sExistsProc( PFLFileSpecRef ref, PGPBoolean *exists);
d9a566 static PGPError¤sCreateProc( PFLFileSpecRef ref );
3e8737 static PGPError¤sDeleteProc( PFLConstFileSpecRef ref );
8d63a1 static PGPError¤sRenameProc( PFLFileSpecRef ref, const char *newName);
d40b6d static PGPError¤sGetMaxNameLengthProc( PFLConstFileSpecRef ref,
40cf6c ¤   ¤   ¤   ¤   ¤   PGPSize * maxNameLength);
779436 static PGPError¤sParentDirProc( PFLConstFileSpecRef fileFromDir,
7b300b ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outParent );
6530c0 static PGPError¤sComposeProc( PFLConstFileSpecRef parent, char const *name,
23e038 ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outRef );
35af5a
81af5a
06b3cc static const PGPFileSpecVTBL¤   sVTBL =
6dbb36 {
68f041 ¤   sExportProc,
88855a ¤   sImportProc,
94a7c8 ¤   sGetNameProc,
11ebac ¤   sSetNameProc,
b267c5 ¤
d52e15 ¤   sSetMetaInfoProc,
a2020f ¤   sExistsProc,
d94295 ¤   sCreateProc,
c36b45 ¤   sDeleteProc,
b5e980 ¤   sRenameProc,
8861b1 ¤   sGetMaxNameLengthProc,
a775fb ¤   sParentDirProc,
55c383 ¤   sComposeProc
2982f7 };
c567c5 ¤
7c67c5 ¤
f34aca ¤   PGPFileSpecVTBL const *
a3d5b9 GetFileSpecVTBLMac()
2ebb36 {
72cba4 ¤   return( &sVTBL );
91efe6 }
08af5a
85af5a
73fa23 #if PRAGMA_ALIGN_SUPPORTED
34af46 #pragma options align=mac68k
377454 #endif
7b6de9 /* note: since this is mac-specific,
7a15e5 we can get away with writing it out as a whole struct */
bb1741 typedef struct
7ebb36 {
606f85 ¤   FSSpec¤ ¤   ¤   spec;
a9f75e ¤   long¤   ¤   ¤   volumeCreationDate;
0f6c2a ¤   unsigned char¤  volumeName[ 64 ];
a475ff } ExportedFileSpec;
e3fa23 #if PRAGMA_ALIGN_SUPPORTED
217c46 #pragma options align=reset
967454 #endif
faaf5a
a1c744 ¤   PGPError
6bf192 pgpPlatformGetFileInfo(
bb389e ¤   PFLConstFileSpecRef¤ref,
1c56c1 ¤   PFLFileInfo *¤  ¤   outInfo )
20bb36 {
b97637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
cb2274 ¤   MyData *¤   ¤   myData;
666f85 ¤   FSSpec¤ ¤   ¤   spec;
57c106 ¤   HFileInfo¤  ¤   pb;
beaf5a
a6e5c8 ¤   PGPValidateParam( ref->type == kPFLFileSpecMacType );
fcaf5a
d917c2 ¤   myData¤ = GetMyData( ref );
7c1a1c ¤   spec¤   = myData->spec;
6512a6 ¤   (void)ResolveVolume( myData );
f367c5 ¤
d98ec1 ¤   pb.ioNamePtr = spec.name;
--bddd 0008b800ce5401000de Page 3 of pgpFileSpecMac.c
b7d8ba ¤   pb.ioVRefNum = spec.vRefNum;
a0735b ¤   pb.ioDirID = spec.parID;
ee3bc7 ¤   pb.ioFDirIndex = 0;
dc67c5 ¤
bcb011 ¤   if ( PBGetCatInfoSync( (CInfoPBPtr)&pb ) != noErr )
67c7a1 ¤   {
b1a589 ¤   ¤   if ( pb.ioResult == fnfErr )
58fc3e ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
400e1d ¤   ¤   else
22c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
ec9371 ¤   }
ae0e24 ¤   else
e0c7a1 ¤   {
9ff41d ¤   ¤   /* Check directory bit: XXX couldn't find a #define for these masks */
67657b ¤   ¤   if ( pb.ioFlAttrib & 0x10 )
4a5b34 ¤   ¤   {
90cedc ¤   ¤   ¤   outInfo->flags = kPGPFileInfo_IsDirectory;
42fea6 ¤   ¤   ¤   outInfo->dataLength = 0;
f00fe4 ¤   ¤   }
6f0e1d ¤   ¤   else
e75b34 ¤   ¤   {
06f802 ¤   ¤   ¤   outInfo->flags = kPGPFileInfo_IsPlainFile;
188d78 ¤   ¤   ¤   outInfo->dataLength = pb.ioFlLgLen;
d10fe4 ¤   ¤   }
5c5b34 ¤   ¤   {
76906d ¤   ¤   ¤   time_t¤ ¤   ¤   nowStdTime = time( NULL );
fe23af ¤   ¤   ¤   unsigned long¤  nowMacTime;
af87c7 ¤   ¤   ¤
da6ddc ¤   ¤   ¤   GetDateTime( &nowMacTime );
f3d36d ¤   ¤   ¤   outInfo->modificationTime = (time_t)(pb.ioFlMdDat
d2dbcf ¤   ¤   ¤   ¤   ¤   ¤   ¤   + ((unsigned long)nowStdTime - nowMacTime));
dc0fe4 ¤   ¤   }
a99371 ¤   }
6567c5 ¤
e35ea8 ¤   return err;
6fefe6 }
3eaf5a
4bc744 ¤   PGPError
0be6af pgpPlatformLockFILE(
6af51c ¤   FILE *¤ ¤   ¤   ¤   file,
1f61bb ¤   PFLFileOpenFlags¤   flags )
30bb36 {
68f644 ¤   /* Nothing to do, normal file locking should be enough */
2aaf5a
9ee437 ¤   (void)file;¤¤   /* Avoid warnings */
a34000 ¤   (void)flags;
b2af5a
10151e ¤   return kPGPError_NoErr;
fbefe6 }
a2af5a
90c744 ¤   PGPError
60ba0c pgpPlatformNewDirectoryIter(
274505 ¤   PFLConstFileSpecRef¤¤   parentDir,
8ca05a ¤   PFLDirectoryIterRef *¤  outIter )
1dbb36 {
d008cc ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr¤  = parentDir->memoryMgr;
6c3a27 ¤   PGPError¤   ¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
51567b ¤   MyData *¤   ¤   ¤   ¤   myData;
0c7820 ¤   FSSpec¤ ¤   ¤   ¤   ¤   spec;
3964a8 ¤   PFLDirectoryIterRef¤¤   newIter¤= NULL;
43af5a
a218d6 ¤   *outIter = NULL;
719f08 ¤   PGPValidateParam( parentDir->type == kPFLFileSpecMacType );
19ad91 ¤   PGPValidateMemoryMgr( memoryMgr );
b7af5a
33b13f ¤   myData¤ = GetMyData( parentDir );
551a1c ¤   spec¤   = myData->spec;
4e12a6 ¤   (void)ResolveVolume( myData );
7faf5a
1f3d6c ¤   newIter = (PFLDirectoryIterRef)PGPNewData( memoryMgr,
68ab03 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *newIter ), 0 );
8b4168 ¤   if ( IsntNull( newIter ) )
--1d96 000a19b7bc7401000de Page 4 of pgpFileSpecMac.c
f7c7a1 ¤   {
d33763 ¤   ¤   HFileInfo¤  ¤   pb;
3d1b52 ¤   ¤
f7b9c9 ¤   ¤   pb.ioNamePtr = spec.name;
41e5d2 ¤   ¤   pb.ioVRefNum = spec.vRefNum;
c3c80d ¤   ¤   pb.ioDirID = spec.parID;
e0cda2 ¤   ¤   pb.ioFDirIndex = 0;
873f46 ¤   ¤   if ( PBGetCatInfoSync( (CInfoPBPtr)&pb ) != noErr )
835b34 ¤   ¤   {
d1a064 ¤   ¤   ¤   if ( pb.ioResult == fnfErr )
4cc5fb ¤   ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
7abb8c ¤   ¤   ¤   else
dbffd7 ¤   ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
450fe4 ¤   ¤   }
e60e1d ¤   ¤   else
075b34 ¤   ¤   {
69709b ¤   ¤   ¤   newIter->memoryMgr¤ = memoryMgr;
3a172e ¤   ¤   ¤   newIter->vRefNum¤   = spec.vRefNum;
13d8c9 ¤   ¤   ¤   newIter->parID¤ ¤   = pb.ioDirID;
635f95 ¤   ¤   ¤   newIter->dirIndex¤  = 1;
730fe4 ¤   ¤   }
be9371 ¤   }
5f0e24 ¤   else
55c7a1 ¤   {
e7bce1 ¤   ¤   err = kPGPError_OutOfMemory;
139371 ¤   }
6f67c5 ¤
70f1e7 ¤   if ( IsntPGPError( err ) )
8712ef ¤   ¤   *outIter = newIter;
53360d ¤   else if ( IsntNull( newIter ) )
30bbb9 ¤   ¤   PGPFreeData( newIter );
ccaf5a
fa5ea8 ¤   return err;
66efe6 }
bcaf5a
e8c744 ¤   PGPError
ed7d10 pgpPlatformNextFileInDirectory(
969676 ¤   PFLDirectoryIterRef¤¤   iter,
4e80bd ¤   PFLFileSpecRef *¤   ¤   outRef )
e3bb36 {
623bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
fb6f85 ¤   FSSpec¤ ¤   ¤   spec;
f2c106 ¤   HFileInfo¤  ¤   pb;
c9af5a
99cd60 ¤   *outRef = NULL;
e967c5 ¤
438ec1 ¤   pb.ioNamePtr = spec.name;
6a894c ¤   pb.ioVRefNum = iter->vRefNum;
345e63 ¤   pb.ioDirID = iter->parID;
044dfe ¤   pb.ioFDirIndex = iter->dirIndex;
11b011 ¤   if ( PBGetCatInfoSync( (CInfoPBPtr)&pb ) != noErr )
63c7a1 ¤   {
5ca589 ¤   ¤   if ( pb.ioResult == fnfErr )
7c008f ¤   ¤   ¤   err¤= kPGPError_EndOfIteration;
310e1d ¤   ¤   else
d6c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
fd9371 ¤   }
0a0e24 ¤   else
7bc7a1 ¤   {
7cbb51 ¤   ¤   spec.vRefNum = iter->vRefNum;
894b0e ¤   ¤   spec.parID = iter->parID;
f8f540 ¤   ¤   err = PFLNewFileSpecFromFSSpec( iter->memoryMgr, &spec, outRef );
079371 ¤   }
a467c5 ¤
0df1e7 ¤   if ( IsntPGPError( err ) )
0050ca ¤   ¤   iter->dirIndex++;
acaf5a
b15ea8 ¤   return err;
ffefe6 }
58af5a
85c744 ¤   PGPError
a119da pgpPlatformFreeDirectoryIter(
--94d3 000bc4034f6401000de Page 5 of pgpFileSpecMac.c
fa1585 ¤   PFLDirectoryIterRef¤¤   iter )
21bb36 {
67d4ad ¤   PGPValidatePtr( iter );
03af5a
32aec6 ¤   PGPFreeData( iter );
4c151e ¤   return kPGPError_NoErr;
a4efe6 }
39af5a
fa66dd ¤   static PGPError
2b22b0 sExportProc(
bec6c5 ¤   PFLConstFileSpecRef¤¤   ¤   ref,
d8fb67 ¤   PGPByte **¤ ¤   ¤   ¤   ¤   dataOut,
7a20c2 ¤   PGPSize *¤  ¤   ¤   ¤   ¤   dataSizeOut )
84bb36 {
825365 ¤   MyData *¤   ¤   ¤   myData;
f32db8 ¤   FSSpec const *¤ ¤   spec;
156189 ¤   ExportedFileSpec¤   exported;
a020c8 ¤   PGPByte *¤  ¤   ¤   data¤   = NULL;
5e9891 ¤   PGPUInt32¤  ¤   ¤   dataSize¤   = sizeof( exported );
ebd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
7fe4fe ¤   PGPBoolean¤ ¤   ¤   haveVolume¤ = FALSE;
c4af5a
3317c2 ¤   myData¤ = GetMyData( ref );
65ad82 ¤   spec¤   = &myData->spec;
ea67c5 ¤
6f12a6 ¤   (void)ResolveVolume( myData );
c967c5 ¤
5adbcb ¤   exported.spec¤  = *spec;
6e67c5 ¤
81ad74 ¤   haveVolume¤ = myData->vRefNumIsValid;
031b6b ¤   if ( haveVolume )
d2c7a1 ¤   {
f83be3 ¤   ¤   err¤= GetVolumeName( spec->vRefNum, exported.volumeName);
4d7d98 ¤   ¤   if ( IsntPGPError( err ) )
355b34 ¤   ¤   {
2b3458 ¤   ¤   ¤   err¤= GetVolumeDates( spec->vRefNum,
a4f5e5 ¤   ¤   ¤   ¤   &exported.volumeCreationDate, NULL );
180fe4 ¤   ¤   }
f29371 ¤   }
bc0e24 ¤   else
34c7a1 ¤   {
17adde ¤   ¤   pgpAssert( myData->volumeInfo.volumeCreationDate != 0 );
1c914f ¤   ¤   pgpAssert( StrLength( myData->volumeInfo.volumeName ) != 0 );
370d80 ¤   ¤   pgpAssert( StrLength( myData->volumeInfo.volumeName ) <= 27 );
101b52 ¤   ¤
3c2573 ¤   ¤   CopyPString( myData->volumeInfo.volumeName, exported.volumeName);
34727e ¤   ¤   exported.volumeCreationDate¤= myData->volumeInfo.volumeCreationDate;
229371 ¤   }
5567c5 ¤
56f1e7 ¤   if ( IsntPGPError( err ) )
45c7a1 ¤   {
9942c0 ¤   ¤   data = (PGPByte *)
3fe09e ¤   ¤   ¤   PGPNewData( ref->memoryMgr, dataSize, 0);
3e87c7 ¤   ¤   ¤
c95a2d ¤   ¤   if ( IsntNull( data ) )
a45b34 ¤   ¤   {
5f436c ¤   ¤   ¤   pgpCopyMemory( &exported, data, dataSize);
e7a26d ¤   ¤   ¤   *dataSizeOut¤   = dataSize;
e20fe4 ¤   ¤   }
cd0e1d ¤   ¤   else
b15b34 ¤   ¤   {
fe124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
700fe4 ¤   ¤   }
439371 ¤   }
9c0e24 ¤   else
4fc7a1 ¤   {
78bc3e ¤   ¤   err¤= kPGPError_BadParams;
3b9371 ¤   }
c967c5 ¤
cd8e1d ¤   *dataOut¤   ¤   = data;
f2ecc4 ¤   *dataSizeOut¤   = dataSize;
bc6067 ¤   return( err);
--7043 0004ad6cc4a401000de Page 6 of pgpFileSpecMac.c
7aefe6 }
46af5a
8eaf5a
79af5a
0866dd ¤   static PGPError
c3c9a6 FindVRefNum(
9d2fc7 ¤   long¤   ¤   ¤   volumeCreationDate,
232fa6 ¤   const uchar *¤  volumeName,
bf2fe1 ¤   short *¤¤   ¤   vRefNumOut )
63bb36 {
233c64 ¤   PGPUInt32¤  ¤   volIndex;
d91dc6 ¤   short¤  ¤   ¤   vRefNums[ 100 ];
79be3d ¤   unsigned short¤ numVRefNums;
0aec6d ¤   PGPBoolean¤ ¤   foundIt¤= false;
2ad1c5 ¤   OSStatus¤   ¤   macErr;
bd9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
2a67c5 ¤
3035a3 ¤   numVRefNums¤= sizeof( vRefNums ) / sizeof( vRefNums[ 0 ] );
a5108a ¤   GetAllVRefNums( vRefNums, numVRefNums, &numVRefNums );
005818 ¤   for( volIndex = 0; volIndex < numVRefNums; ++volIndex )
88c7a1 ¤   {
8caf18 ¤   ¤   long¤   creationDate;
734bd2 ¤   ¤   short¤  vRefNum¤= vRefNums[ volIndex ];
9a8b16 ¤   ¤   Str255¤ vName;
7a1b52 ¤   ¤
7dc9cc ¤   ¤   macErr¤ = GetVolumeName( vRefNum, vName );
5a7965 ¤   ¤   if ( macErr == noErr )
aa5b34 ¤   ¤   {
3efee7 ¤   ¤   ¤   macErr¤ = GetVolumeDates( vRefNum, &creationDate, NULL );
680fe4 ¤   ¤   }
1c1b52 ¤   ¤
835bdc ¤   ¤   if ( macErr == noErr &&
07f94d ¤   ¤   ¤   creationDate == volumeCreationDate )
f35b34 ¤   ¤   {
2666f7 ¤   ¤   ¤   foundIt¤= TRUE;
c47900 ¤   ¤   ¤   *vRefNumOut¤= vRefNum;
e52b85 ¤   ¤   ¤   ¤
0682c0 ¤   ¤   ¤   if ( PStringsAreEqual( volumeName, vName) )
76f776 ¤   ¤   ¤   {
98db2a ¤   ¤   ¤   ¤   /* both match, that's as good as we get */
be5ce7 ¤   ¤   ¤   ¤   /* otherwise, continue search for matching name */
d2f622 ¤   ¤   ¤   ¤   break;
45a3a6 ¤   ¤   ¤   }
9d0fe4 ¤   ¤   }
7a9371 ¤   }
4b67c5 ¤
56d219 ¤   if ( ! foundIt ·)
12c7a1 ¤   {
03c0d0 ¤   ¤   err¤= kPGPError_FileNotFound;
969371 ¤   }
43deb7 ¤   return( err );
7eefe6 }
e1af5a
9faf5a
9166dd ¤   static PGPError
20f5aa ResolveVolume( MyData *myData)
6cbb36 {
8726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9967c5 ¤
ba9d13 ¤   if ( ! myData->vRefNumIsValid )
8fc7a1 ¤   {
aebe3a ¤   ¤   short¤  vRefNum;
7e1b52 ¤   ¤
e5fbfd ¤   ¤   err¤= FindVRefNum( myData->volumeInfo.volumeCreationDate,
b66981 ¤   ¤   ¤   ¤   ¤   ¤   myData->volumeInfo.volumeName, &vRefNum);
c27d98 ¤   ¤   if ( IsntPGPError( err ) )
385b34 ¤   ¤   {
5c5247 ¤   ¤   ¤   myData->vRefNumIsValid¤ = TRUE;
72e242 ¤   ¤   ¤   myData->spec.vRefNum¤   = vRefNum;
990fe4 ¤   ¤   }
df9371 ¤   }
4a67c5 ¤
--f84c 00076c6fb4d401000de Page 7 of pgpFileSpecMac.c
afdeb7 ¤   return( err );
b7efe6 }
35af5a
adaf5a
a266dd ¤   static PGPError
f357ab sImportProc(
86abec ¤   PFLFileSpecRef¤ ¤   ref,
1c453a ¤   PGPByte const *¤¤   data,
bf530c ¤   PGPSize¤¤   ¤   ¤   dataSize )
35bb36 {
6d41ce ¤   const ExportedFileSpec *¤   exported;
333751 ¤   MyData *¤   ¤   ¤   ¤   ¤   newData¤= NULL;
3d9981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
4eaf5a
c48901 ¤   PGPValidateParam( dataSize == sizeof( ExportedFileSpec ) );
1167c5 ¤
26679a ¤   exported¤   = (const ExportedFileSpec *)data;
bbbfa0 ¤   newData¤¤   = GetMyData( ref );
2767c5 ¤
494474 ¤   err¤= PGPReallocData( ref->memoryMgr,
d5b41e ¤   ¤   ¤   &newData, sizeof( *newData ), 0 );
06f1e7 ¤   if ( IsntPGPError( err ) )
efc7a1 ¤   {
bd143e ¤   ¤   MyData *¤   ¤   myData¤ = (MyData *)newData;
711b52 ¤   ¤
c41837 ¤   ¤   ref->data¤  ¤   ¤   ¤   = (PGPByte *)newData;
54e724 ¤   ¤   ref->dataSize¤  ¤   ¤   = sizeof( *newData );
431b52 ¤   ¤
edc496 ¤   ¤   myData->spec¤   ¤   ¤   ¤   = exported->spec;
8db62d ¤   ¤   myData->spec.vRefNum¤   ¤   = kInvalidVRefNum;
561b52 ¤   ¤
c2b234 ¤   ¤   /* stroe info for use by ResolveSpec */
6d0112 ¤   ¤   myData->vRefNumIsValid¤ = FALSE;
33e556 ¤   ¤   myData->volumeInfo.volumeCreationDate¤  = exported->volumeCreationDate;
1781a5 ¤   ¤   CopyPString( exported->volumeName, myData->volumeInfo.volumeName );
841b52 ¤   ¤
f25355 ¤   ¤   (void)ResolveVolume( myData );
3b9371 ¤   }
dc67c5 ¤
6b6067 ¤   return( err);
67efe6 }
4daf5a
46af5a
ca66dd ¤   static PGPError
37451d sGetNameProc(
4d389e ¤   PFLConstFileSpecRef¤ref,
47437a ¤   char¤   ¤   ¤   ¤   name[ 256 ] )
f7bb36 {
985a58 ¤   const MyData *¤ myData¤ = GetMyData( ref );
7a232f ¤   const FSSpec *¤ spec;
d167c5 ¤
04c1fc ¤   PGPValidatePtr( myData );
03ad82 ¤   spec¤   = &myData->spec;
696287 ¤   PGPValidateParam( StrLength( spec->name ) <= 31 );
bc67c5 ¤
f6c318 ¤   pgpCopyMemory( &spec->name[ 1 ], name, StrLength( spec->name ) );
8327f3 ¤   name[ StrLength( spec->name ) ]¤= '\0';
6c67c5 ¤
fd2d68 ¤   return( kPGPError_NoErr );
58efe6 }
d2af5a
cdaf5a
8e66dd ¤   static PGPError
6e0979 sSetNameProc(
33abec ¤   PFLFileSpecRef¤ ¤   ref,
fe8c83 ¤   char const *¤   ¤   name )
dfbb36 {
2730d4 ¤   PGPError¤   err¤¤   = kPGPError_NoErr;
951076 ¤   MyData *¤   myData¤ = GetMyData( ref );
d3665c ¤   PGPUInt32¤  nameLength;
1c67c5 ¤
76c1fc ¤   PGPValidatePtr( myData );
--f265 0007e7626c0401000de Page 8 of pgpFileSpecMac.c
1d2546 ¤   nameLength¤ = strlen( name );
a9fb3b ¤   PGPValidateParam( nameLength <= sizeof( myData->spec.name ) - 1 );
df67c5 ¤
274da3 ¤   if ( nameLength > sizeof( myData->spec.name ) - 1 )
5fc7a1 ¤   {
7e5974 ¤   ¤   err = kPGPError_BufferTooSmall;
cf9371 ¤   }
2b0e24 ¤   else
75c7a1 ¤   {
daad34 ¤   ¤   pgpCopyMemory( name, &myData->spec.name[ 1 ], nameLength );
748da3 ¤   ¤   myData->spec.name[ 0 ]¤ = nameLength;
679371 ¤   }
9d67c5 ¤
42deb7 ¤   return( err );
55af5a
d9efe6 }
07af5a
3faf5a
6566dd ¤   static PGPError
3ae430 sGetMaxNameLengthProc(
b5389e ¤   PFLConstFileSpecRef¤ref,
35bb39 ¤   PGPSize *¤  ¤   maxNameLength )
99bb36 {
445a58 ¤   const MyData *¤ myData¤ = GetMyData( ref );
c567c5 ¤
6dc1fc ¤   PGPValidatePtr( myData );
1867c5 ¤
714dcf ¤   /* at some point, this will need to be done programmatically by
d82c4d ¤   examining the file system in use which the file is ·on */
64151f ¤   *maxNameLength¤ = kMaxHFSFileNameLength;
f167c5 ¤
4f2d68 ¤   return( kPGPError_NoErr );
27efe6 }
e6af5a
d3af5a
85af5a
b666dd ¤   static PGPError
ac73ef sSetMetaInfoProc(
727b33 ¤   PFLFileSpecRef¤ ref,
a4587f ¤   void const *¤   infoIn )
2fbb36 {
5226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9d1076 ¤   MyData *¤   myData¤ = GetMyData( ref );
563818 ¤   PFLFileSpecMacMetaInfo const *¤ info;
2a67c5 ¤
8e803f ¤   info¤   = (PFLFileSpecMacMetaInfo const *)infoIn;
9267c5 ¤
0e4b24 ¤   myData->metaInfo¤   = *info;
7f67c5 ¤
fadeb7 ¤   return( err );
e1efe6 }
8caf5a
c3af5a
c866dd ¤   static PGPError
1fd0fe sExistsProc(
c77b33 ¤   PFLFileSpecRef¤ ref,
e704b7 ¤   PGPBoolean *¤   exists)
f1bb36 {
d026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
ea1076 ¤   MyData *¤   myData¤ = GetMyData( ref );
d8c759 ¤   FInfo¤  ¤   fInfo;
5067c5 ¤
9812a6 ¤   (void)ResolveVolume( myData );
5dbc1b ¤   if ( myData->vRefNumIsValid )
18c7a1 ¤   {
3918f8 ¤   ¤   err¤¤   = FSpGetFInfo( &myData->spec, &fInfo );
ebba97 ¤   ¤   *exists¤= ( err == noErr );
3f9371 ¤   }
bb0e24 ¤   else
bac7a1 ¤   {
ef36c9 ¤   ¤   *exists¤= FALSE;
7e9371 ¤   }
--1cac 00035678600401000de Page 9 of pgpFileSpecMac.c
2a67c5 ¤
fe2d68 ¤   return( kPGPError_NoErr );
b2efe6 }
78af5a
c466dd ¤   static PGPError
6f3d91 sCreateProc( PFLFileSpecRef ref )
edbb36 {
379372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
6021de ¤   OSStatus¤   ¤   macErr¤ = noErr;
de034b ¤   MyData *¤   ¤   myData¤ = GetMyData( ref );
888f4b ¤   OSType¤ ¤   ¤   fileCreator;
e8c072 ¤   OSType¤ ¤   ¤   fileType;
ddaf5a
2712a6 ¤   (void)ResolveVolume( myData );
9f67c5 ¤
91aa69 ¤   fileCreator¤= myData->metaInfo.fInfo.fdCreator;
0444ea ¤   fileType¤   = myData->metaInfo.fInfo.fdType;
b567c5 ¤
7a7d35 ¤   macErr¤ = FSpCreate( &myData->spec, fileCreator, fileType, smSystemScript );
a6fef7 ¤   if ( macErr != noErr )
acc7a1 ¤   {
6efafc ¤   ¤   err¤= kPGPError_FileOpFailed;
c09371 ¤   }
ba67c5 ¤
7cdeb7 ¤   return( err );
ebefe6 }
c5af5a
80af5a
f366dd ¤   static PGPError
9b9ed8 sDeleteProc( PFLConstFileSpecRef ref )
20bb36 {
a59372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
63034b ¤   MyData *¤   ¤   myData¤ = GetMyData( ref );
7e67c5 ¤
d812a6 ¤   (void)ResolveVolume( myData );
d9bc1b ¤   if ( myData->vRefNumIsValid )
29c7a1 ¤   {
8b2cd2 ¤   ¤   err¤= FSpDelete( &myData->spec );
6d456e ¤   ¤   if ( err == fnfErr )
f1fc3e ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
a9f2b9 ¤   ¤   else if ( IsPGPError( err ) )
a5c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
519371 ¤   }
260e24 ¤   else
f5c7a1 ¤   {
69c0d0 ¤   ¤   err¤= kPGPError_FileNotFound;
be9371 ¤   }
7c67c5 ¤
01deb7 ¤   return( err );
84efe6 }
10af5a
f3af5a
3966dd ¤   static PGPError
a73b71 sRenameProc(
f97b33 ¤   PFLFileSpecRef¤ ref,
0117d5 ¤   const char *¤   newName)
58bb36 {
4d9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
26034b ¤   MyData *¤   ¤   myData¤ = GetMyData( ref );
d40c3a ¤   PGPUInt32¤  ¤   nameLength;
a2f0e4 ¤   Str255¤ ¤   ¤   pascalName;
eb67c5 ¤
b412a6 ¤   (void)ResolveVolume( myData );
ebbc1b ¤   if ( myData->vRefNumIsValid )
b4c7a1 ¤   {
451b52 ¤   ¤
865d91 ¤   ¤   nameLength¤ = strlen( newName );
3030bc ¤   ¤   PGPValidateParam( nameLength <= 31 );
f71b52 ¤   ¤
a128e2 ¤   ¤   pgpCopyMemory( newName, &pascalName[ 1 ], nameLength );
9d5c68 ¤   ¤   pascalName[ 0 ]¤= nameLength;
351b52 ¤   ¤
--13aa 000f8a4178a401000de Page 10 of pgpFileSpecMac.c
a204d1 ¤   ¤   err¤= FSpRename( &myData->spec, pascalName );
727d98 ¤   ¤   if ( IsntPGPError( err ) )
7b5b34 ¤   ¤   {
4cc739 ¤   ¤   ¤   err¤= sSetNameProc( ref, newName );
9a0fe4 ¤   ¤   }
9d544f ¤   ¤   else if ( err == fnfErr )
43fc3e ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
c10e1d ¤   ¤   else
f6c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
689371 ¤   }
fb0e24 ¤   else
b7c7a1 ¤   {
f0c0d0 ¤   ¤   err¤= kPGPError_FileNotFound;
dc9371 ¤   }
9267c5 ¤
d0deb7 ¤   return( err );
7defe6 }
06af5a
bd66dd ¤   static PGPError
8385e8 sParentDirProc(
aa389e ¤   PFLConstFileSpecRef¤ref,
3452c8 ¤   PFLFileSpecRef *¤   outParent )
3ebb36 {
d97637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
da2274 ¤   MyData *¤   ¤   myData;
c36f85 ¤   FSSpec¤ ¤   ¤   spec;
b7c106 ¤   HFileInfo¤  ¤   pb;
42af5a
e2e5c8 ¤   PGPValidateParam( ref->type == kPFLFileSpecMacType );
8eaf5a
9817c2 ¤   myData¤ = GetMyData( ref );
aa1a1c ¤   spec¤   = myData->spec;
ed12a6 ¤   (void)ResolveVolume( myData );
b767c5 ¤
4b8ec1 ¤   pb.ioNamePtr = spec.name;
30d8ba ¤   pb.ioVRefNum = spec.vRefNum;
aa735b ¤   pb.ioDirID = spec.parID;
7589fc ¤   pb.ioFDirIndex = -1;
e367c5 ¤
62b011 ¤   if ( PBGetCatInfoSync( (CInfoPBPtr)&pb ) != noErr )
3ac7a1 ¤   {
e0a589 ¤   ¤   if ( pb.ioResult == fnfErr )
09fc3e ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
600e1d ¤   ¤   else
1dc612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
e19371 ¤   }
d40e24 ¤   else
77c7a1 ¤   {
41cb82 ¤   ¤   spec.vRefNum = pb.ioVRefNum;
632d9f ¤   ¤   spec.parID = pb.ioFlParID;
a88793 ¤   ¤   err = PFLNewFileSpecFromFSSpec( ref->memoryMgr, &spec, outParent );
729371 ¤   }
5367c5 ¤
c8deb7 ¤   return( err );
75efe6 }
a7af5a
a166dd ¤   static PGPError
7c8c3c sComposeProc(
746a3b ¤   PFLConstFileSpecRef¤parent,
74de88 ¤   const char *¤   ¤   fileName,
3a9620 ¤   PFLFileSpecRef *¤   outRef )
84bb36 {
c87637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
342274 ¤   MyData *¤   ¤   myData;
676f85 ¤   FSSpec¤ ¤   ¤   spec;
fac106 ¤   HFileInfo¤  ¤   pb;
1b01c4 ¤   PGPSize¤¤   ¤   nameLength;
acaf5a
96aea5 ¤   PGPValidateParam( parent->type == kPFLFileSpecMacType );
70af5a
f5fe45 ¤   myData¤ = GetMyData( parent );
f81a1c ¤   spec¤   = myData->spec;
--0f26 000874d7dd8401000de Page 11 of pgpFileSpecMac.c
d112a6 ¤   (void)ResolveVolume( myData );
0d67c5 ¤
1c8ec1 ¤   pb.ioNamePtr = spec.name;
0cd8ba ¤   pb.ioVRefNum = spec.vRefNum;
5e735b ¤   pb.ioDirID = spec.parID;
253bc7 ¤   pb.ioFDirIndex = 0;
d267c5 ¤
4ab011 ¤   if ( PBGetCatInfoSync( (CInfoPBPtr)&pb ) != noErr )
fac7a1 ¤   {
1ca589 ¤   ¤   if ( pb.ioResult == fnfErr )
aefc3e ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
260e1d ¤   ¤   else
4fc612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
f79371 ¤   }
e80e24 ¤   else
90c7a1 ¤   {
2b48bd ¤   ¤   nameLength = strlen( fileName );
472843 ¤   ¤   if ( nameLength > sizeof( spec.name ) - 1 )
9c5b34 ¤   ¤   {
23d112 ¤   ¤   ¤   err = kPGPError_BufferTooSmall;
f20fe4 ¤   ¤   }
410e1d ¤   ¤   else
5a5b34 ¤   ¤   {
ef876e ¤   ¤   ¤   pgpCopyMemory( fileName, spec.name + 1, nameLength );
e2c39f ¤   ¤   ¤   spec.name[0] = nameLength;
dace6f ¤   ¤   ¤   spec.vRefNum = pb.ioVRefNum;
8903de ¤   ¤   ¤   spec.parID = pb.ioDirID;
be2db8 ¤   ¤   ¤   err = PFLNewFileSpecFromFSSpec( parent->memoryMgr, &spec,
9392cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outRef );
610fe4 ¤   ¤   }
a89371 ¤   }
1567c5 ¤
f2deb7 ¤   return( err );
99efe6 }
33af5a
c3af5a
a321ab ¤   PGPError·
1675f7 PFLNewFileSpecFromFSSpec(
bf2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
e6f521 ¤   FSSpec const *¤ ¤   spec,
ae9620 ¤   PFLFileSpecRef *¤   outRef )
e1bb36 {
8a98f3 ¤   PFLFileSpecRef¤ newFileRef¤ = NULL;
359372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0467c5 ¤
443c76 ¤   PGPValidatePtr( outRef );
b43652 ¤   *outRef¤= NULL;
1fad91 ¤   PGPValidateMemoryMgr( memoryMgr );
747974 ¤   PGPValidatePtr( spec );
87515e ¤   PGPValidateParam( spec->vRefNum < 0 && spec->parID != 0 &&
990e40 ¤   ¤   spec->name[ 0 ] != 0 && spec->name[ 0 ] <= 31 );
6267c5 ¤
543f8a ¤   err¤= pgpNewFileSpec( memoryMgr, kPFLFileSpecMacType,
989d1d ¤   ¤   sizeof( MyData ), &newFileRef );
4cf1e7 ¤   if ( IsntPGPError( err ) )
4ac7a1 ¤   {
bbf8fc ¤   ¤   MyData *¤   myData¤ = GetMyData( newFileRef );
831b52 ¤   ¤
322efe ¤   ¤   pgpClearMemory( myData, sizeof( *myData ) );
70c111 ¤   ¤   myData->spec¤   ¤   ¤   = *spec;
541b52 ¤   ¤
58da8e ¤   ¤   /* volume info not used if vRefNumIsValid */
67da21 ¤   ¤   myData->vRefNumIsValid¤ = TRUE;
dec48b ¤   ¤   pgpClearMemory( &myData->volumeInfo, sizeof( myData->volumeInfo ) );
1f1b52 ¤   ¤
d28d47 ¤   ¤   (void)FSpGetFInfo( spec, &myData->metaInfo.fInfo );
9b9371 ¤   }
9b67c5 ¤
a17893 ¤   *outRef¤= newFileRef;
8d5ea8 ¤   return err;
45efe6 }
87af5a
--f096 00004ef7163401000de Page 12 of pgpFileSpecMac.c
d3c744 ¤   PGPError
0a41de PFLGetFSSpecFromFileSpec(
e76b4c ¤   PFLConstFileSpecRef¤¤   ref,
db0e63 ¤   FSSpec *¤   ¤   ¤   ¤   spec)
8ebb36 {
7dec85 ¤   MyData *¤   myData;
ef26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
dd1b52 ¤   ¤
127974 ¤   PGPValidatePtr( spec );
d866a2 ¤   pgpClearMemory( spec, sizeof( *spec ) );
c56f49 ¤   PFLValidateFileSpec( ref );
96af5a
bb17c2 ¤   myData¤ = GetMyData( ref );
ba12a6 ¤   (void)ResolveVolume( myData );
10024d ¤   pgpAssert( ref->type == kPFLFileSpecMacType );
bb67c5 ¤
d3d5e6 ¤   /* name, parID may be useful even if vRefNum wrong */
ec8ded ¤   *spec¤  = myData->spec;
6567c5 ¤
cb9d13 ¤   if ( ! myData->vRefNumIsValid )
80c7a1 ¤   {
dbcdd2 ¤   ¤   err¤¤   = kPGPError_FileNotFound;
d6f8d1 ¤   ¤   pgpAssert( spec->vRefNum == kInvalidVRefNum );
3f9371 ¤   }
a567c5 ¤
675ea8 ¤   return err;
bfefe6 }
49af5a
e8af5a
33c744 ¤   PGPError
038bac pgpPlatformGetTempFileSpec(
7e6d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
7b0536 ¤   PFLConstFileSpecRef¤¤   optionalRef,
8380bd ¤   PFLFileSpecRef *¤   ¤   outRef )
1ebb36 {
d69479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
304b7d ¤   OSStatus¤   ¤   ¤   ¤   macErr¤ = noErr;
cfaf53 ¤   FSSpec¤ ¤   ¤   ¤   ¤   tempSpec;
2ee54a ¤   const unsigned char¤*¤  kTempFileBase¤  = "\pPGPTemp";
ca67c5 ¤
dfa570 ¤   if ( IsntNull( optionalRef ) )
2bc7a1 ¤   {
187972 ¤   ¤   err¤= PFLGetFSSpecFromFileSpec( optionalRef, &tempSpec );
e89371 ¤   }
0e0e24 ¤   else
34c7a1 ¤   {
6b52d7 ¤   ¤   macErr¤ = FindFolder( kOnSystemDisk, kTemporaryFolderType,
f8469e ¤   ¤   ¤   ¤   ¤   kCreateFolder, &tempSpec.vRefNum, &tempSpec.parID);
17eadf ¤   ¤   if ( macErr != noErr )
6fc612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
d89371 ¤   }
d767c5 ¤
b9f1e7 ¤   if ( IsntPGPError( err ) )
80c7a1 ¤   {
ae2c5d ¤   ¤   CopyPString( kTempFileBase, tempSpec.name );
b01428 ¤   ¤   macErr¤ = FSpGetUniqueSpec( &tempSpec, &tempSpec );
e77965 ¤   ¤   if ( macErr == noErr )
fb80e7 ¤   ¤   ¤   err¤= PFLNewFileSpecFromFSSpec( memoryMgr, &tempSpec, outRef );
6a0e1d ¤   ¤   else
f0c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
579371 ¤   }
6d67c5 ¤
afdeb7 ¤   return( err );
41efe6 }
1baf5a
afaf5a
56af5a
e7c744 ¤   PGPError
70b22a pgpPlatformOpenFileSpecAsFILE(
422499 ¤   PFLFileSpecRef¤ spec,
b7d6c3 ¤   const char *¤   openMode,
049605 ¤   FILE **¤¤   ¤   fileOut )
--f3d3 001d9002b3d401000de Page 13 of pgpFileSpecMac.c
2cbb36 {
4f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b4afc5 ¤   FILE *¤ ¤   ¤   stdioFILE¤  = NULL;
3f6403 ¤   FSSpec¤ ¤   ¤   fsSpec;
e8877b ¤   MyData *¤   ¤   myData¤ = NULL;
d567c5 ¤
8f508c ¤   PGPValidatePtr( fileOut );
d148de ¤   *fileOut¤   = NULL;
aa0282 ¤   PFLValidateFileSpec( spec );
c78e69 ¤   PGPValidatePtr( openMode );
1e85d6 ¤   PGPValidateParam( spec->type == kPFLFileSpecMacType );
1367c5 ¤
1f3821 ¤   myData¤ = GetMyData( spec );
8367c5 ¤
a4bc1b ¤   if ( myData->vRefNumIsValid )
c3c7a1 ¤   {
3ca2e9 ¤   ¤   err¤= PFLGetFSSpecFromFileSpec( spec, &fsSpec );
777d98 ¤   ¤   if ( IsntPGPError( err ) )
a85b34 ¤   ¤   {
e7bec4 ¤   ¤   ¤   stdioFILE¤  = FSp_fopen( &fsSpec, openMode );
a84b5c ¤   ¤   ¤   if ( IsNull( stdioFILE ) )
eec5fb ¤   ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
560fe4 ¤   ¤   }
dd9371 ¤   }
2b0e24 ¤   else
64c7a1 ¤   {
c5c5e2 ¤   ¤   stdioFILE¤  = NULL;
a6c0d0 ¤   ¤   err¤= kPGPError_FileNotFound;
389371 ¤   }
871b52 ¤   ¤
5f9d73 ¤   *fileOut¤   = stdioFILE;
f767c5 ¤
e1deb7 ¤   return( err );
e6efe6 }
fbaf5a
ffaf5a
22ddc8 #endif¤ /* ] PGP_MACINTOSH */
a6af5a
c7af5a
1738e5 /*
54e6c5 ·* Local Variables:
629b19 ·* tab-width: 4
2de7a4 ·* End:
69b612 ·* vi: ts=4 sw=4
426c42 ·* vim: si
d9495d ·*/
--decb 0018a39e6b5401000df Page 1 of pgpFileSpecMac.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
f0cb45 ¤   Mac implementation of a file specification. ·Uses FSSpec as its
586082 ¤   location.
cbaf5a
2c0afa ¤   $Id: pgpFileSpecMac.h,v 1.7.16.1 1998/11/12 03:18:10 heller Exp $
aef7f7 ____________________________________________________________________________*/
5c4abf #ifndef Included_pgpFileSpecMac_h¤  /* [ */
39a719 #define Included_pgpFileSpecMac_h
9caf5a
c70304 /* this file is included by pgpFileSpec.h and
1cd274 ¤   shouldn't be included directly */
f30329 #ifndef _pgpFileSpecIncludeRightStuff_
90734e #error don't include this file directly. ·Use pgpFileSpec.h instead.
0d7454 #endif
8daf5a
baaf5a
3699c6 PGP_BEGIN_C_DECLARATIONS
2ccbcf #if PRAGMA_IMPORT_SUPPORTED
40b981 #pragma import on
1d7454 #endif
3baf5a
a8af5a
f2af5a
5e5302 typedef struct PFLFileSpecMacMetaInfo
7bbb36 {
0939e0 ¤   FInfo¤  fInfo;
6ee1bb } PFLFileSpecMacMetaInfo;
ccaf5a
8f1da2 PGPError ¤  PFLNewFileSpecFromFSSpec( PGPMemoryMgrRef context,
78dbcd ¤   ¤   ¤   ¤   ¤   const FSSpec * spec, PFLFileSpecRef * outRef );
f9ae30 ¤   ¤   ¤   ¤   ¤
4efdea PGPError ¤  PFLGetFSSpecFromFileSpec( PFLConstFileSpecRef ref,
661a26 ¤   ¤   ¤   ¤   ¤   FSSpec * spec );
05af5a
eeaf5a
e9af5a
87cbcf #if PRAGMA_IMPORT_SUPPORTED
d92ced #pragma import reset
ab7454 #endif
ca1254 PGP_END_C_DECLARATIONS
cfaf5a
c1af5a
4c872a #endif¤ /* ] Included_pgpFileSpecMac_h */
b1af5a
c438e5 /*
3fe6c5 ·* Local Variables:
899b19 ·* tab-width: 4
5de7a4 ·* End:
fdb612 ·* vi: ts=4 sw=4
a66c42 ·* vim: si
8a495d ·*/
--e484 001337168c8401000e0 Page 1 of pgpFileSpecMacPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
a5f3ac ¤   $Id: pgpFileSpecMacPriv.h,v 1.1.34.1 1998/11/12 03:18:11 heller Exp $
5ef7f7 ____________________________________________________________________________*/
964f2b #ifndef Included_pgpFileSpecMacPriv_h¤  /* [ */
46ab11 #define Included_pgpFileSpecMacPriv_h
dbaf5a
3fb2ca #include "pgpFileSpecPriv.h"
29af5a
2caf5a
1599c6 PGP_BEGIN_C_DECLARATIONS
3aaf5a
c5af5a
a2598c PGPFileSpecVTBL const *¤GetFileSpecVTBLMac( void );
eaaf5a
a71254 PGP_END_C_DECLARATIONS
d5af5a
89af5a
6bed42 #endif¤ /* ] Included_pgpFileSpecMacPriv_h */
73af5a
f638e5 /*
3ce6c5 ·* Local Variables:
639b19 ·* tab-width: 4
87e7a4 ·* End:
82b612 ·* vi: ts=4 sw=4
f06c42 ·* vim: si
72495d ·*/
33af5a
--4324 0001f514df9401000e1 Page 1 of pgpFileSpecPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
e1da01 ¤   $Id: pgpFileSpecPriv.h,v 1.12.16.1 1998/11/12 03:18:12 heller Exp $
65f7f7 ____________________________________________________________________________*/
a5fbb2 #ifndef Included_pgpFileSpecPriv_h¤ /* [ */
d59120 #define Included_pgpFileSpecPriv_h
d9af5a
f76bd2 #ifndef PGP_USE_FILE_SPEC_PRIV
401d4a #error you should not be including this file
ef7454 #endif
54af5a
96feb2 #include <stdio.h>
edaf5a
c1894b #include "pgpFileSpec.h"
c13427 #include "pgpFileUtilities.h"
c7af5a
c9211a #define kPFLFileSpecMagic¤  ¤   ¤   0x251DEA9B
1baf5a
78af5a
8411e6 typedef enum PFLFileSpecType
45bb36 {
f9b307 ¤   kPFLFileSpecInvalidType¤= 13,
edbd7a ¤   kPFLFileSpecFullPathType,
b4ec48 ¤   kPFLFileSpecMacType
eeb4a2 } PFLFileSpecType;
cfaf5a
92af5a
8baf5a
49349d typedef PGPError¤   (*PGPFileSpecExportProc)( PFLConstFileSpecRef ref,
50d3f6 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **data, PGPSize *dataSize );
1b94aa ¤   ¤   ¤   ¤   ¤   ¤
158068 typedef PGPError¤   (*PGPFileSpecImportProc)( PFLFileSpecRef ref,
d4761c ¤   ¤   ¤   ¤   ¤   ¤   PGPByte const *data,
0a540f ¤   ¤   ¤   ¤   ¤   ¤   PGPSize dataSize );
6c94aa ¤   ¤   ¤   ¤   ¤   ¤
0a7b3e typedef PGPError¤   (*PGPFileSpecGetNameProc)(
5f79e4 ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef ref, char name[ 256 ] );
f194aa ¤   ¤   ¤   ¤   ¤   ¤
f25e50 typedef PGPError¤   (*PGPFileSpecSetNameProc)(
951db9 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef ref, char const *name );
08af5a
f25fde typedef PGPError¤   (*PGPFileSpecSetMetaInfoProc)(
807ec8 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef ref, const void *info );
9794aa ¤   ¤   ¤   ¤   ¤   ¤
f98ade typedef PGPError¤   (*PGPFileSpecCreateProc)( PFLFileSpecRef ref );
bd94aa ¤   ¤   ¤   ¤   ¤   ¤
d86635 typedef PGPError¤   (*PGPFileSpecDeleteProc)( PFLConstFileSpecRef ref );
7894aa ¤   ¤   ¤   ¤   ¤   ¤
981544 typedef PGPError¤   (*PGPFileSpecRenameProc)( PFLFileSpecRef ref,
f980f8 ¤   ¤   ¤   ¤   ¤   ¤   const char *newName);
8694aa ¤   ¤   ¤   ¤   ¤   ¤
a776b6 typedef PGPError¤   (*PGPFileSpecExistsProc)( PFLFileSpecRef ref,
701498 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *exists );
1c94aa ¤   ¤   ¤   ¤   ¤   ¤
3ae994 typedef PGPError¤   (*PGPFileGetMaxNameLengthProc)( PFLConstFileSpecRef ref,
40e593 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  maxLength );
25af5a
d55650 typedef PGPError¤   (*PGPFileGetParentDirProc)(
5346ec ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileFromDir,
876310 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outParent );
dcaf5a
6c4b7c typedef PGPError¤   (*PGPFileSpecComposeProc)(
62b752 ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef parent, char const *name,
e9af06 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outRef );
aeaf5a
829264 typedef struct PGPFileSpecVTBL¤ PGPFileSpecVTBL;
33af5a
7099b5 struct PGPFileSpecVTBL
1fbb36 {
--c919 000c42a231d401000e1 Page 2 of pgpFileSpecPriv.h
0ff6b6 ¤   PGPFileSpecExportProc¤  ¤   exportProc;
e0e1dc ¤   PGPFileSpecImportProc¤  ¤   importProc;
8ea413 ¤   PGPFileSpecGetNameProc¤ ¤   getNameProc;
9074a9 ¤   PGPFileSpecSetNameProc¤ ¤   setNameProc;
3867c5 ¤
fe79da ¤   PGPFileSpecSetMetaInfoProc¤ setMetaInfoProc;
518b89 ¤   PGPFileSpecExistsProc¤  ¤   existsProc;
dab29e ¤   PGPFileSpecCreateProc¤  ¤   createProc;
7362f6 ¤   PGPFileSpecDeleteProc¤  ¤   deleteProc;
d1e4a8 ¤   PGPFileSpecRenameProc¤  ¤   renameProc;
1f8b7d ¤   PGPFileGetMaxNameLengthProc¤maxNameLengthProc;
3c4cb3 ¤   PGPFileGetParentDirProc¤¤   getParentDirProc;
30003c ¤   PGPFileSpecComposeProc¤ ¤   composeProc;
2b2fa1 } ;
38af5a
0a59ea #define CallExportProc( ref, data, dataSize ) \
0384bc ¤   (*((ref)->vtbl->exportProc))( ref, data, dataSize )
1b67c5 ¤
a85894 #define CallImportProc( ref, data, dataSize ) \
1585c2 ¤   (*((ref)->vtbl->importProc))( ref, data, dataSize )
8967c5 ¤
e01404 #define CallGetNameProc( ref, name ) \
5ae37e ¤   (*((ref)->vtbl->getNameProc))( ref, name )
8e67c5 ¤
1059e0 #define CallSetNameProc( ref, name ) \
49ae9a ¤   (*((ref)->vtbl->setNameProc))( ref, name )
4967c5 ¤
d186d3 #define CallSetMetaInfoProc( ref, info ) \
73798f ¤   (*((ref)->vtbl->setMetaInfoProc))( ref, info )
7967c5 ¤
0a4fd2 #define CallExistsProc( ref, exists ) \
7f0b00 ¤   (*((ref)->vtbl->existsProc))( ref, exists )
7b67c5 ¤
00895e #define CallCreateProc( ref ) \
95d56e ¤   (*((ref)->vtbl->createProc))( ref )
4467c5 ¤
6fd1df #define CallDeleteProc( ref, name ) \
de02bf ¤   (*((ref)->vtbl->deleteProc))( ref )
2a67c5 ¤
1054c5 #define CallRenameProc( ref, name ) \
f1ba12 ¤   (*((ref)->vtbl->renameProc))( ref, name )
6767c5 ¤
bef4ce #define CallGetMaxNameLength( ref, length ) \
27c70e ¤   (*((ref)->vtbl->maxNameLengthProc))( ref, length )
f5af5a
be4f3b #define CallGetParentDirProc( childSpec, outParent ) \
b2d12c ¤   (*((childSpec)->vtbl->getParentDirProc))( childSpec, outParent )
23af5a
6433bb #define CallComposeProc( parent, name, outRef ) \
00ae5c ¤   (*((parent)->vtbl->composeProc))( parent, name, outRef )
3767c5 ¤
e8af5a
e7f4a0 struct PFLFileSpec
16bb36 {
a4fe45 ¤   PGPUInt32¤  ¤   ¤   ¤   magic;
08b586 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr;
d94b61 ¤   PFLFileSpecType¤¤   ¤   type;
8aac46 ¤   PGPUInt32¤  ¤   ¤   ¤   dataSize;
f2d87c ¤   PGPFileSpecVTBL const *¤vtbl;
b0ef80 ¤   void *¤ ¤   ¤   ¤   ¤   data;
912fa1 } ;
5eaf5a
0eaf5a
8d8bb1 PGPError¤   pgpNewFileSpec( PGPMemoryMgrRef context,
c30fdf ¤   ¤   ¤   ¤   PFLFileSpecType type,·
86dc60 ¤   ¤   ¤   ¤   PGPUInt32 dataSize, PFLFileSpecRef * outRef );
7caf5a
24af5a
4b7db5 PGPError¤   pgpPlatformGetTempFileSpec( PGPMemoryMgrRef context,
3fe99d ¤   ¤   ¤   ¤   PFLConstFileSpecRef optionalRef, PFLFileSpecRef * outRef );
2e2b85 ¤   ¤   ¤   ¤
c43a63 PGPError¤   pgpPlatformOpenFileSpecAsFILE( PFLFileSpecRef spec,
--9398 00152d07714401000e1 Page 3 of pgpFileSpecPriv.h
5ecdd5 ¤   ¤   ¤   ¤   const char * openMode, FILE ** fileOut );
abaf5a
6c9fc3 PGPError¤   pgpPlatformGetFileInfo( PFLConstFileSpecRef spec,
5f74d3 ¤   ¤   ¤   ¤   PFLFileInfo *outInfo );
665aee PGPError¤   pgpPlatformNewDirectoryIter( PFLConstFileSpecRef parentDir,
e1f3e0 ¤   ¤   ¤   ¤   PFLDirectoryIterRef * outIter );
c44269 PGPError¤   pgpPlatformNextFileInDirectory( PFLDirectoryIterRef iter,
30d688 ¤   ¤   ¤   ¤   PFLFileSpecRef * outRef );
47e820 PGPError¤   pgpPlatformFreeDirectoryIter( PFLDirectoryIterRef iter );
71af5a
f3a9ec PGPError¤   pgpPlatformLockFILE( FILE * file, PFLFileOpenFlags flags );
0baf5a
63d324 #endif¤ /* ] Included_pgpFileSpecPriv_h */
76af5a
7838e5 /*
86e6c5 ·* Local Variables:
349b19 ·* tab-width: 4
a9e7a4 ·* End:
52b612 ·* vi: ts=4 sw=4
6b6c42 ·* vim: si
52495d ·*/
--6752 0007bc6d5f8401000e2 Page 1 of pgpFileSpecStd.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
18cac7 ¤   $Id: pgpFileSpecStd.c,v 1.47.12.1 1998/11/12 03:18:13 heller Exp $
15f7f7 ____________________________________________________________________________*/
4daf5a
dfaf5a
ebe610 #include "pgpPFLConfig.h"
acaf5a
9efeb2 #include <stdio.h>
91324c #include <string.h>
d8495d #include <errno.h>
d4cd8f #if HAVE_PATHS_H
11963e #include <paths.h>
1f7454 #endif
afabff #if HAVE_UNISTD_H
d717c2 #include <unistd.h>
477454 #endif
04e006 #if HAVE_SYS_TYPES_H
eef15e #include <sys/types.h>
8a7454 #endif
e9be68 #if HAVE_SYS_STAT_H
01d4f4 #include <sys/stat.h>
1d7454 #endif
1843d6 #if HAVE_DIRENT_H && !PGP_WIN32
03cebb #include <dirent.h>
dc454f #define USE_DIRENT¤ 1
9c7454 #endif
cd656b #if HAVE_FCNTL_H
8d37bc #include <fcntl.h>
a47454 #endif
37af5a
0fa146 #include "pgpDebug.h"
ef2b62 #include "pgpPFLErrors.h"
7f0d08 #include "pgpMem.h"
48af5a
426773 #include "pgpMemoryMgr.h"
49af5a
aadd39 #define PGP_USE_FILE_SPEC_PRIV¤ ¤   1
e7de29 #include "pgpFileSpecStdPriv.h"
baaf5a
79af5a
4ec6a9 typedef struct MyData
1ebb36 {
5d113b ¤   char¤   ¤   path[ 1 ];
a7908c } MyData;
4ff735 #define GetMyData( ref )¤   ¤   ¤   ( (MyData *)((ref)->data) )
8d4f87 #define SetMyData( ref, newData )¤  ( ((ref)->data)¤= (MyData *)newData )
41ed3c #define MyDataSize( ref )¤  ¤   ¤   ( strlen( GetMyData(ref)->path ) + 1)
2eaf5a
45c0ad #if USE_DIRENT
fd66ae struct PFLDirectoryIter
6abb36 {
dcd91c ¤   PGPMemoryMgrRef¤memoryMgr;
aaa1d3 ¤   DIR *¤  ¤   ¤   dirRef;
0ad154 ¤   PFLFileSpecRef¤ parentDir;
f782f7 };
767454 #endif
f4af5a
1eaf5a
6e5b9f static PGPError¤sExportProc( PFLConstFileSpecRef ref,
63f543 ¤   ¤   ¤   ¤   ¤   PGPByte **data, PGPSize *dataSize );
21e333 static PGPError¤sImportProc( PFLFileSpecRef ref,
9254c2 ¤   ¤   ¤   ¤   ¤   PGPByte const *data, PGPSize dataSize );
91b442 static PGPError¤sGetNameProc( PFLConstFileSpecRef ref, char name[ 256 ] );
69f35a static PGPError¤sSetNameProc( PFLFileSpecRef ref, char const *name );
c42249 static PGPError¤sSetMetaInfoProc( PFLFileSpecRef ref, void const *info );
f15a33 static PGPError¤sExistsProc( PFLFileSpecRef ref, PGPBoolean *exists);
35a566 static PGPError¤sCreateProc( PFLFileSpecRef ref );
7b8737 static PGPError¤sDeleteProc( PFLConstFileSpecRef ref );
--f691 00020165552401000e2 Page 2 of pgpFileSpecStd.c
7663a1 static PGPError¤sRenameProc( PFLFileSpecRef ref, const char *newName);
010b6d static PGPError¤sGetMaxNameLengthProc( PFLConstFileSpecRef ref,
abcf6c ¤   ¤   ¤   ¤   ¤   PGPSize * maxNameLength);
209436 static PGPError¤sParentDirProc( PFLConstFileSpecRef fileFromDir,
8b9a1e ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outParent);
9030c0 static PGPError¤sComposeProc( PFLConstFileSpecRef parent, char const *name,
24e038 ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *outRef );
3aaf5a
f3af5a
f27b18 static const PGPFileSpecVTBL¤   sVTBLStd =
6dbb36 {
63f041 ¤   sExportProc,
c7855a ¤   sImportProc,
aba7c8 ¤   sGetNameProc,
1aebac ¤   sSetNameProc,
5467c5 ¤
442e15 ¤   sSetMetaInfoProc,
f4020f ¤   sExistsProc,
e24295 ¤   sCreateProc,
466b45 ¤   sDeleteProc,
b2e980 ¤   sRenameProc,
9c61b1 ¤   sGetMaxNameLengthProc,
5c75fb ¤   sParentDirProc,
cac383 ¤   sComposeProc
6a82f7 };
8367c5 ¤
f267c5 ¤
474aca ¤   PGPFileSpecVTBL const *
006b9e GetFileSpecVTBLStd()
5bbb36 {
5ba03e ¤   return( &sVTBLStd );
d7efe6 }
31af5a
3aaf5a
3038e5 /*
d00c26 ·* kDirectorySeparators is a string of possible directory-separation characters
c52a42 ·* The first one is the preferred one, which goes in between
b5e44d ·* PGPPATH and the file name if PGPPATH is not terminated with a
21ad06 ·* directory separator.
c0775e ·*
ea0e66 ·* PATHSEP is a the directory separator within a PATH of directories.
cb4c43 ·* Only one character per platform, please
6c495d ·*/
ccaf5a
16dd29 #if defined(PGP_MSDOS) || defined(PGP_ATARI) || defined(PGP_WIN32)
02a19e static char const kDirectorySeparators[] = "\\/";
6af6aa #define PATHSEP ';'
d90395 #define SINGLE_EXT 1
c8af5a
2fde2b #elif defined(PGP_UNIX)
19dd6a static char const kDirectorySeparators[] = "/";
d8ac76 #define PATHSEP ':'
4faf5a
8b5d1b #elif defined(PGP_AMIGA)
74f353 static char const kDirectorySeparators[] = "/:";
4cf6aa #define PATHSEP ';'
57af5a
a8d239 #elif defined(PGP_VMS)
fffd6d static char const kDirectorySeparators[] = "]:";¤   /* Any more? */
bdf6aa #define PATHSEP ';'
360395 #define SINGLE_EXT 1
aaaf5a
67f51d #elif defined(PGP_MACINTOSH)
b0709c static char const kDirectorySeparators[] = ":";
47f6aa #define PATHSEP ';'
42af5a
acdb21 #else
29ccd9 #error Unknown operating system - need one of\
5f4f25 ·UNIX, MSDOS, AMIGA, ATARI, VMS, or MACINTOSH.
0c7454 #endif
79af5a
20af5a
--bac5 0001dd565ca401000e2 Page 3 of pgpFileSpecStd.c
d3abfe ¤   static char const *
57ceaf pgpFileNameTail( char const *path )
b2bb36 {
0fe39e ¤   char const *¤   lastTail = path;
469fe4 ¤   char const *¤   separator;
7667c5 ¤
9a9295 ¤   for (separator = kDirectorySeparators; *separator != '\0'; ++separator)
5bc7a1 ¤   {
f7f9e5 ¤   ¤   char const *¤   tail;
0567c5 ¤
bb2ac3 ¤   ¤   tail = strrchr(lastTail, *separator);
6a0be0 ¤   ¤   if ( IsntNull( tail ) )
161427 ¤   ¤   ¤   lastTail = tail + 1;
da9371 ¤   }
1d2b4d ¤   return( lastTail );
07efe6 }
47af5a
36af5a
b8af5a
5daf5a
d9af5a
7fa97f #if ! PGP_MACINTOSH /* [ */
e7af5a
55c744 ¤   PGPError
0fb22a pgpPlatformOpenFileSpecAsFILE(
6c2499 ¤   PFLFileSpecRef¤ spec,
04d6c3 ¤   const char *¤   openMode,
1b9605 ¤   FILE **¤¤   ¤   fileOut )
c5bb36 {
0c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
aaafc5 ¤   FILE *¤ ¤   ¤   stdioFILE¤  = NULL;
939c12 ¤   char *¤ ¤   ¤   fullPath;
1c67c5 ¤
53508c ¤   PGPValidatePtr( fileOut );
1c48de ¤   *fileOut¤   = NULL;
9f0282 ¤   PFLValidateFileSpec( spec );
758e69 ¤   PGPValidatePtr( openMode );
243904 ¤   PGPValidateParam( spec->type == kPFLFileSpecFullPathType );
6967c5 ¤
5667c5 ¤
a34fcc ¤   err¤= PFLGetFullPathFromFileSpec( spec, &fullPath );
7df1e7 ¤   if ( IsntPGPError( err ) )
fdc7a1 ¤   {
9ef8bb ¤   ¤   stdioFILE¤  = fopen( fullPath, openMode );
dc9ca5 ¤   ¤   PGPFreeData( fullPath );
38af5a
630aaf ¤   ¤   if ( IsNull( stdioFILE ) )
985b34 ¤   ¤   {
a84bfa ¤   ¤   ¤   if (errno == EACCES
4c467d #ifdef EROFS
c35318 ¤   ¤   ¤   ¤   || errno == EROFS
667454 #endif
e99284 ¤   ¤   ¤   ¤   )
98f776 ¤   ¤   ¤   {
4b0162 ¤   ¤   ¤   ¤   err¤= kPGPError_FilePermissions;
41a3a6 ¤   ¤   ¤   }
14e413 ¤   ¤   ¤   else if (errno == ENOENT)
b7f776 ¤   ¤   ¤   {
b7c5fb ¤   ¤   ¤   ¤   err¤= kPGPError_FileNotFound;
17a3a6 ¤   ¤   ¤   }
69bb8c ¤   ¤   ¤   else
54f776 ¤   ¤   ¤   {
3bffd7 ¤   ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
0ba3a6 ¤   ¤   ¤   }
130fe4 ¤   ¤   }
539371 ¤   }
d567c5 ¤
c39d73 ¤   *fileOut¤   = stdioFILE;
2967c5 ¤
d4deb7 ¤   return( err );
62efe6 }
1daf5a
--c13b 0004166c876401000e2 Page 4 of pgpFileSpecStd.c
e0af5a
1aaf5a
1321ab ¤   PGPError·
df6bc4 PFLNewFileSpecFromFullPath(
6d2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
f3cf94 ¤   char const *¤   ¤   path,
e79620 ¤   PFLFileSpecRef *¤   outRef )
fbbb36 {
5b98f3 ¤   PFLFileSpecRef¤ newFileRef¤ = NULL;
739372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
6867c5 ¤
aa3c76 ¤   PGPValidatePtr( outRef );
cd3652 ¤   *outRef¤= NULL;
cbad91 ¤   PGPValidateMemoryMgr( memoryMgr );
5667c5 ¤
0fe893 ¤   err¤= pgpNewFileSpec( memoryMgr, kPFLFileSpecFullPathType,
9b07ef ¤   ¤   ¤   strlen(path) + 1, &newFileRef );
65f1e7 ¤   if ( IsntPGPError( err ) )
0dc7a1 ¤   {
98f8fc ¤   ¤   MyData *¤   myData¤ = GetMyData( newFileRef );
d31b52 ¤   ¤
3c56a3 ¤   ¤   strcpy( myData->path, path );
c29371 ¤   }
b867c5 ¤
9e7893 ¤   *outRef¤= newFileRef;
245ea8 ¤   return err;
17efe6 }
dcaf5a
0aaf5a
c521ab ¤   PGPError·
2ef35f PFLGetFullPathFromFileSpec(
7db622 ¤   PFLConstFileSpecRef¤¤   fileRef,
fb168a ¤   char **¤¤   ¤   ¤   ¤   fullPathPtr)
5bbb36 {
ea3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
e9f471 ¤   char const *¤   srcPath;
b31723 ¤   char *¤ ¤   ¤   newPath¤= NULL;
bdfc6b ¤   MyData *¤   ¤   myData¤ = GetMyData( fileRef );
82af5a
cef65f ¤   PGPValidatePtr( fullPathPtr );
868917 ¤   *fullPathPtr¤   = NULL;
bb65f3 ¤   PFLValidateFileSpec( fileRef );
961daa ¤   PGPValidateParam( fileRef->type == kPFLFileSpecFullPathType );
6c67c5 ¤
9eb30f ¤   srcPath¤= myData->path;
82af5a
4d5ca8 ¤   newPath = (char *)PGPNewData( fileRef->memoryMgr,
3e35ed ¤   ¤   ¤   ¤   strlen( myData->path ) + 1, 0);
2867c5 ¤
8d0170 ¤   if ( IsntNull( newPath ) )
efbf54 ¤   ¤   strcpy( newPath, myData->path );
8e0e24 ¤   else
4e17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
3e67c5 ¤
7e686b ¤   *fullPathPtr¤   = newPath;
8967c5 ¤
1c5ea8 ¤   return err;
8fefe6 }
aaaf5a
33af5a
10c744 ¤   PGPError
9d8bac pgpPlatformGetTempFileSpec(
1a6d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
2c0536 ¤   PFLConstFileSpecRef¤¤   optionalRef,
e880bd ¤   PFLFileSpecRef *¤   ¤   outRef )
97bb36 {
284138 ¤   char¤   ¤   ¤   fileName[ L_tmpnam ];
1e3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
7b005c ¤   PFLFileSpecRef¤ tempRef = NULL;
e9af5a
6fc053 ¤   (void)optionalRef;
4167c5 ¤
--c922 0007a9e69b6401000e2 Page 5 of pgpFileSpecStd.c
6c4bbf #if defined(_PATH_TMP) && HAVE_MKTEMP¤  /* [ */
c6c7a1 ¤   {
7d4a55 ¤   ¤   strncpy(fileName, _PATH_TMP "ptmpXXXXXX", sizeof(fileName));
ffa9d8 ¤   ¤   fileName[ sizeof(fileName) - 1 ] = '\0';
fbae30 ¤   ¤   if ( IsNull( mktemp(fileName) ) )
dd5b34 ¤   ¤   {
b9c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
b70fe4 ¤   ¤   }
c687c7 ¤   ¤   ¤
287d98 ¤   ¤   if ( IsntPGPError( err ) )
515b34 ¤   ¤   {
4fec2f ¤   ¤   ¤   err¤= PFLNewFileSpecFromFullPath( memoryMgr, fileName, &tempRef);
270fe4 ¤   ¤   }
b49371 ¤   }
dfaf5a
fce623 #else¤  /* ] defined(_PATH_TMP) && HAVE_MKTEMP [ */
b667c5 ¤
fe64c1 ¤   if ( tmpnam(fileName) != fileName)
3dc7a1 ¤   {
b0fafc ¤   ¤   err¤= kPGPError_FileOpFailed;
639371 ¤   }
9e67c5 ¤
a9ffe1 ¤   err = PFLNewFileSpecFromFullPath( memoryMgr, fileName, &tempRef);
8167c5 ¤
db5fee #endif¤ /* ] defined(_PATH_TMP) && HAVE_MKTEMP */
7467c5 ¤
242a40 ¤   *outRef¤= tempRef;
6e67c5 ¤
3d5ea8 ¤   return err;
b7efe6 }
aeaf5a
43015a #define PGP_ISDIR(m)¤   ( ( ( m ) & S_IFDIR ) != 0 )
2870f3 #define PGP_ISREG(m)¤   ( ( ( m ) & S_IFREG ) != 0 )
08af5a
99c744 ¤   PGPError
27f192 pgpPlatformGetFileInfo(
205a35 ¤   PFLConstFileSpecRef¤spec,
e356c1 ¤   PFLFileInfo *¤  ¤   outInfo )
fdbb36 {
087637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
d37d32 ¤   const char *¤   path¤   = GetMyData( spec )->path;
2410c5 ¤   struct stat¤¤   statInfo;
07af5a
d43904 ¤   PGPValidateParam( spec->type == kPFLFileSpecFullPathType );
8594ec ¤   if ( stat( path, &statInfo ) != 0 )
f2c7a1 ¤   {
9ddd65 ¤   ¤   err = kPGPError_FileOpFailed;
d49371 ¤   }
0d0e24 ¤   else
3ec7a1 ¤   {
84a717 ¤   ¤   outInfo->flags = 0;
2bfaec ¤   ¤   if ( PGP_ISDIR( statInfo.st_mode ) )
a72541 ¤   ¤   ¤   outInfo->flags |= kPGPFileInfo_IsDirectory;
506086 ¤   ¤   if ( PGP_ISREG( statInfo.st_mode ) )
e45b34 ¤   ¤   {
36139f ¤   ¤   ¤   outInfo->flags |= kPGPFileInfo_IsPlainFile;
212414 ¤   ¤   ¤   outInfo->dataLength = statInfo.st_size;
bb0fe4 ¤   ¤   }
da0e1d ¤   ¤   else
ae5b34 ¤   ¤   {
f9fea6 ¤   ¤   ¤   outInfo->dataLength = 0;
7a0fe4 ¤   ¤   }
764d5d ¤   ¤   outInfo->modificationTime = statInfo.st_mtime;
169371 ¤   }
6b67c5 ¤
dd5ea8 ¤   return err;
66efe6 }
3daf5a
2bc744 ¤   PGPError
a6e6af pgpPlatformLockFILE(
9ef51c ¤   FILE *¤ ¤   ¤   ¤   file,
7a61bb ¤   PFLFileOpenFlags¤   flags )
--d422 000295a2220401000e2 Page 6 of pgpFileSpecStd.c
2cbb36 {
a77637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
7fa474 #if HAVE_FCNTL_H && defined(F_SETLK)
dadefe ¤   int¤¤   ¤   ¤   fileDesc = fileno( file );
b8d325 ¤   struct flock¤   lockInfo;
a7af5a
89ab05 ¤   if ( flags & kPFLFileOpenFlags_ReadWrite )
c01d8b ¤   ¤   lockInfo.l_type = F_WRLCK;
d40e24 ¤   else
8bb762 ¤   ¤   lockInfo.l_type = F_RDLCK;
cd851f ¤   lockInfo.l_start¤   = 0;
c607c9 ¤   lockInfo.l_whence¤  = SEEK_SET;
39f3bc ¤   lockInfo.l_len¤ ¤   = 0;
e9af5a
e26c78 ¤   if ( fcntl( fileDesc, F_SETLK, &lockInfo ) == -1 )
e6c7a1 ¤   {
83c577 ¤   ¤   if ( errno == EACCES || errno == EAGAIN )
706e40 ¤   ¤   ¤   err = kPGPError_FileLocked;
e78186 ¤   ¤   else if ( errno == ENOENT )
f4dba7 ¤   ¤   ¤   err = kPGPError_FileNotFound;
d10e1d ¤   ¤   else
eee18b ¤   ¤   ¤   err = kPGPError_FileOpFailed;
1f9371 ¤   }
1fe4ce #elif PGP_MACINTOSH || PGP_WIN32
ba478d ¤   /* Locking on MacOS and Win32 is done during open */
82a4a7 ¤   (void)file;
264000 ¤   (void)flags;
3adb21 #else
4ea6a6 #error File locking needs to be implemented for this platform!
457454 #endif
b1af5a
2f5ea8 ¤   return err;
a3efe6 }
86af5a
5dddc8 #endif¤ /* ] PGP_MACINTOSH */
ddaf5a
162265 #if USE_DIRENT¤ /* [ */
49af5a
17c744 ¤   PGPError
9bba0c pgpPlatformNewDirectoryIter(
444505 ¤   PFLConstFileSpecRef¤¤   parentDir,
55a05a ¤   PFLDirectoryIterRef *¤  outIter )
06bb36 {
b59450 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr¤  ¤   = parentDir->memoryMgr;
315291 ¤   const char *¤   ¤   ¤   path¤   ¤   = GetMyData( parentDir )->path;
c7f84c ¤   PFLDirectoryIterRef¤¤   newIter¤¤   = NULL;
645ebf ¤   PGPError¤   ¤   ¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
5caf5a
6318d6 ¤   *outIter = NULL;
25b884 ¤   PGPValidateParam( parentDir->type == kPFLFileSpecFullPathType );
cc7989 ¤   PGPValidateParam( PGPMemoryMgrIsValid( memoryMgr ) );
56af5a
b53d6c ¤   newIter = (PFLDirectoryIterRef)PGPNewData( memoryMgr,
3bab03 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *newIter ), 0 );
8a4168 ¤   if ( IsntNull( newIter ) )
d2c7a1 ¤   {
3574da ¤   ¤   newIter->memoryMgr = memoryMgr;
6354d5 ¤   ¤   newIter->dirRef = opendir( path );
c5c0cb ¤   ¤   if ( IsNull( newIter->dirRef ) )
756da7 ¤   ¤   ¤   err = kPGPError_FileOpFailed;¤  /* XXX Better error code? */
890e1d ¤   ¤   else
c0a517 ¤   ¤   ¤   err = PFLCopyFileSpec( parentDir, &newIter->parentDir );
3d9371 ¤   }
150e24 ¤   else
3ac7a1 ¤   {
aebce1 ¤   ¤   err = kPGPError_OutOfMemory;
9d9371 ¤   }
c267c5 ¤
1cf1e7 ¤   if ( IsntPGPError( err ) )
ca12ef ¤   ¤   *outIter = newIter;
1f360d ¤   else if ( IsntNull( newIter ) )
29bbb9 ¤   ¤   PGPFreeData( newIter );
--517f 0006e93432c401000e2 Page 7 of pgpFileSpecStd.c
e0af5a
de5ea8 ¤   return err;
57efe6 }
b7af5a
f3c744 ¤   PGPError
937d10 pgpPlatformNextFileInDirectory(
0f9676 ¤   PFLDirectoryIterRef¤¤   iter,
cd80bd ¤   PFLFileSpecRef *¤   ¤   outRef )
51bb36 {
3d7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
a62f0a ¤   struct dirent *¤¤   entry;
f2af5a
68cd60 ¤   *outRef = NULL;
0eccf6 ¤   PGPValidatePtr( iter->dirRef );
b3af5a
b2858e ¤   entry = readdir( iter->dirRef );
3c1149 ¤   if ( IsntNull( entry ) )
42abc2 ¤   ¤   err = PFLComposeFileSpec( iter->parentDir, entry->d_name, outRef );
3f0e24 ¤   else
6c1311 ¤   ¤   err = kPGPError_EndOfIteration;
2faf5a
785ea8 ¤   return err;
6cefe6 }
09af5a
ffc744 ¤   PGPError
4e19da pgpPlatformFreeDirectoryIter(
f01585 ¤   PFLDirectoryIterRef¤¤   iter )
89bb36 {
7c8e12 ¤   PGPError¤   err = kPGPError_NoErr;
35af5a
d1d4ad ¤   PGPValidatePtr( iter );
d2af5a
cdcd6a ¤   if ( closedir( iter->dirRef ) != 0 )
9e6ad1 ¤   ¤   err = kPGPError_FileOpFailed;¤  /* XXX Better error code? */
e11f11 ¤   PFLFreeFileSpec( iter->parentDir );
acaec6 ¤   PGPFreeData( iter );
295ea8 ¤   return err;
07efe6 }
62af5a
591eed #endif¤ /* ] USE_DIRENT */
84af5a
c7af5a
1b0335 /*____________________________________________________________________________
b4ea44 ¤   Export a C string which is the entire path.
6af7f7 ____________________________________________________________________________*/
bd66dd ¤   static PGPError
e622b0 sExportProc(
5e389e ¤   PFLConstFileSpecRef¤ref,
63cdc7 ¤   PGPByte **¤ ¤   ¤   dataOut,
e130dd ¤   PGPSize *¤  ¤   ¤   dataSizeOut )
6cbb36 {
67de16 ¤   PGPUInt32¤  ¤   ¤   dataSize;
acd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
8c99a7 ¤   char *¤ ¤   ¤   ¤   exported¤   = NULL;
e6f9ad ¤   char const *¤   ¤   srcName;
e667c5 ¤
ba8595 ¤   srcName¤¤   = GetMyData( ref )->path;
19ce78 ¤   dataSize¤   = strlen( srcName ) + 1;¤   /* yes, include the NULL char */
4367c5 ¤
11d252 ¤   exported¤   = (char *)PGPNewData( ref->memoryMgr, dataSize, 0);
ab3b6a ¤   if ( IsntNull( exported ) )
73c7a1 ¤   {
5a2946 ¤   ¤   strcpy( exported, srcName );
9f9371 ¤   }
8f0e24 ¤   else
31c7a1 ¤   {
3a17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
c89371 ¤   }
9267c5 ¤
e8e8f0 ¤   pgpAssert( dataSize == strlen( srcName ) + 1 );
e030c4 ¤   *dataOut¤   ¤   = (PGPByte *)exported;
6eecc4 ¤   *dataSizeOut¤   = dataSize;
--d1de 00016d5d646401000e2 Page 8 of pgpFileSpecStd.c
2a67c5 ¤
c96067 ¤   return( err);
60efe6 }
6daf5a
e2af5a
3d0335 /*____________________________________________________________________________
ed96ee ¤   The imported data should be a NULL-terminated C string
eaf7f7 ____________________________________________________________________________*/
1266dd ¤   static PGPError
2357ab sImportProc(
acabec ¤   PFLFileSpecRef¤ ¤   ref,
f57943 ¤   PGPByte const *¤¤   importData,
cd745d ¤   PGPSize¤¤   ¤   ¤   importDataSize )
b3bb36 {
c27637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
c70f6d ¤   char const *¤   importedPath;
e9877b ¤   MyData *¤   ¤   myData¤ = NULL;
26af5a
49da46 ¤   importedPath¤   = (char const *)importData;
2c1649 ¤   /* data should be a C string (NULL-terminated) ·*/
063bd1 ¤   PGPValidateParam( importedPath[ importDataSize - 1 ] == '\0' );
11025c ¤   pgpAssert( strlen( importedPath ) == importDataSize - 1 );
5567c5 ¤
cdd49c ¤   err¤= PGPReallocData( ref->memoryMgr, &ref->data, importDataSize, 0 );
fc67c5 ¤
d0f1e7 ¤   if ( IsntPGPError( err ) )
48c7a1 ¤   {
e79c3e ¤   ¤   myData¤ = GetMyData( ref );
8e7896 ¤   ¤   ref->dataSize¤  = importDataSize;
721b52 ¤   ¤
170013 ¤   ¤   pgpAssert( ref->dataSize == strlen( importedPath ) + 1 );
fb751c ¤   ¤   strcpy( myData->path, importedPath );
cf9371 ¤   }
5f67c5 ¤
c96067 ¤   return( err);
32efe6 }
02af5a
41af5a
7766dd ¤   static PGPError
83451d sGetNameProc(
61389e ¤   PFLConstFileSpecRef¤ref,
f1437a ¤   char¤   ¤   ¤   ¤   name[ 256 ] )
06bb36 {
1f008f ¤   char const *¤   tail¤   = NULL;
8f7637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
5467c5 ¤
666f49 ¤   PFLValidateFileSpec( ref );
fcfe27 ¤   PGPValidatePtr( ref->data );
e867c5 ¤
ba49aa ¤   tail¤   = pgpFileNameTail( (const char *)ref->data );
803bca ¤   if ( IsntNull( tail) && strlen( tail ) <= 256 )
d5c7a1 ¤   {
5c7c47 ¤   ¤   strcpy( name, tail );
e39371 ¤   }
a50e24 ¤   else
11c7a1 ¤   {
07bc3e ¤   ¤   err¤= kPGPError_BadParams;
169371 ¤   }
a867c5 ¤
43deb7 ¤   return( err );
12efe6 }
62af5a
d6af5a
7266dd ¤   static PGPError
ce0979 sSetNameProc(
677b33 ¤   PFLFileSpecRef¤ ref,
7b499b ¤   char const *¤   newName )
5dbb36 {
9d665c ¤   PGPUInt32¤  nameLength;
b50d6b ¤   char *¤ ¤   path¤   = NULL;
ba03c6 ¤   PGPUInt32¤  nameOffset;
169272 ¤   PGPUInt32¤  newSize;
--4e3d 0004f74103f401000e2 Page 9 of pgpFileSpecStd.c
a326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
1623ee ¤   void *¤ ¤   temp;
7167c5 ¤
c03593 ¤   PFLValidateFileSpec( ref);
5afe27 ¤   PGPValidatePtr( ref->data );
cf4b18 ¤   PGPValidatePtr( newName );
ba587c ¤   nameLength¤ = strlen( newName );
d608d5 ¤   PGPValidateParam( nameLength != 0 );
eb67c5 ¤
3baab0 ¤   path¤   ¤   = (char *)ref->data;
a5377e ¤   nameOffset¤ = pgpFileNameTail( path ) - path;
01af5a
35eb86 ¤   newSize¤= nameOffset + nameLength + 1;
0e09f5 ¤   temp¤   = path;
ff9bb2 ¤   err = PGPReallocData(ref->memoryMgr, &temp, newSize, 0);
871e68 ¤   path¤   = (char *)temp;
74af5a
75f1e7 ¤   if ( IsntPGPError( err ) )
4cc7a1 ¤   {
749b18 ¤   ¤   ref->data¤  ¤   = (PGPByte *)path;
bdb4f1 ¤   ¤   strcpy( path + nameOffset, newName);
ba15e1 ¤   ¤   ref->dataSize¤  = newSize;
919371 ¤   }
6f67c5 ¤
50deb7 ¤   return( err );
fcaf5a
ddefe6 }
60af5a
1baf5a
8e66dd ¤   static PGPError
38e430 sGetMaxNameLengthProc(
df389e ¤   PFLConstFileSpecRef¤ref,
9bbb39 ¤   PGPSize *¤  ¤   maxNameLength )
a0bb36 {
935a58 ¤   const MyData *¤ myData¤ = GetMyData( ref );
a567c5 ¤
68c1fc ¤   PGPValidatePtr( myData );
3767c5 ¤
da4dcf ¤   /* at some point, this will need to be done programmatically by
e62c4d ¤   examining the file system in use which the file is ·on */
479606 ¤   /* obviously, 8.3 file systems have a max of 8 + 1 + 3 */
d89afd ¤   *maxNameLength¤ = 255;
8f67c5 ¤
0e2d68 ¤   return( kPGPError_NoErr );
a5efe6 }
f5af5a
93af5a
1b66dd ¤   static PGPError
4c73ef sSetMetaInfoProc(
ab7b33 ¤   PFLFileSpecRef¤ ref,
c3587f ¤   void const *¤   infoIn )
39bb36 {
f326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a967c5 ¤
87b148 ¤   (void)ref;
6fea9a ¤   (void)infoIn;
f367c5 ¤
d2deb7 ¤   return( err );
f1efe6 }
7aaf5a
2d66dd ¤   static PGPError
6985e8 sParentDirProc(
577ace ¤   PFLConstFileSpecRef¤¤   fileFromDir,
26e58f ¤   PFLFileSpecRef *¤   ¤   outParent )
5bbb36 {
6a3093 ¤   PGPMemoryMgrRef¤memoryMgr¤  ¤   = fileFromDir->memoryMgr;
f998f3 ¤   PFLFileSpecRef¤ newFileRef¤ = NULL;
913ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
0242c3 ¤   char *¤ ¤   ¤   path¤   ¤   = NULL;
6c69a0 ¤   PGPUInt32¤  ¤   nameOffset;
1367c5 ¤
4fd0fd ¤   PGPValidatePtr( outParent );
--b2ec 00012bca877401000e2 Page 10 of pgpFileSpecStd.c
7edda2 ¤   *outParent¤ = NULL;
0b7989 ¤   PGPValidateParam( PGPMemoryMgrIsValid( memoryMgr ) );
85af5a
1376a5 ¤   path¤   ¤   = (char *)fileFromDir->data;
e2377e ¤   nameOffset¤ = pgpFileNameTail( path ) - path;
05af5a
e12181 ¤   if (nameOffset <= 1)¤   /* There is no parent directory */
869dd3 ¤   ¤   return kPGPError_FileNotFound;¤ /* XXX Reasonable error code? */
4667c5 ¤
c5e893 ¤   err¤= pgpNewFileSpec( memoryMgr, kPFLFileSpecFullPathType,
5c1b35 ¤   ¤   ¤   ¤   nameOffset, &newFileRef );
33f1e7 ¤   if ( IsntPGPError( err ) )
d6c7a1 ¤   {
5ef8fc ¤   ¤   MyData *¤   myData¤ = GetMyData( newFileRef );
551b52 ¤   ¤
f1b39a ¤   ¤   pgpCopyMemory( path, myData->path, nameOffset - 1 );
ad920d ¤   ¤   myData->path[nameOffset - 1] = '\0';
de9371 ¤   }
1167c5 ¤
e5d43a ¤   *outParent¤ = newFileRef;
355ea8 ¤   return err;
26efe6 }
03af5a
d866dd ¤   static PGPError
408c3c sComposeProc(
606a3b ¤   PFLConstFileSpecRef¤parent,
ecde88 ¤   const char *¤   ¤   fileName,
f69620 ¤   PFLFileSpecRef *¤   outRef )
64bb36 {
4a4356 ¤   PGPMemoryMgrRef¤memoryMgr¤  ¤   = parent->memoryMgr;
1498f3 ¤   PFLFileSpecRef¤ newFileRef¤ = NULL;
893ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
1042c3 ¤   char *¤ ¤   ¤   path¤   ¤   = NULL;
8083b3 ¤   PGPSize¤¤   ¤   pathLength;
8e67c5 ¤
923c76 ¤   PGPValidatePtr( outRef );
433652 ¤   *outRef¤= NULL;
e17989 ¤   PGPValidateParam( PGPMemoryMgrIsValid( memoryMgr ) );
13af5a
880e38 ¤   path¤   = (char *)parent->data;
fb198a ¤   pathLength¤ = strlen( path );
19ea99 ¤   if ( pathLength > 0 && IsntNull( strchr( kDirectorySeparators,
2434de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·path[ pathLength - 1 ] ) ) )
84c7a1 ¤   {
74e3c4 ¤   ¤   pathLength--;
2a9371 ¤   }
6baf5a
9ee893 ¤   err¤= pgpNewFileSpec( memoryMgr, kPFLFileSpecFullPathType,
e66fde ¤   ¤   ¤   ¤   pathLength + strlen( fileName ) + 2, &newFileRef );
97f1e7 ¤   if ( IsntPGPError( err ) )
54c7a1 ¤   {
5bf8fc ¤   ¤   MyData *¤   myData¤ = GetMyData( newFileRef );
a51b52 ¤   ¤
a9aba8 ¤   ¤   pgpCopyMemory( path, myData->path, pathLength );
a10760 ¤   ¤   myData->path[ pathLength ] = kDirectorySeparators[0];
f6f46a ¤   ¤   strcpy( myData->path + pathLength + 1, fileName );
b59371 ¤   }
e267c5 ¤
327893 ¤   *outRef¤= newFileRef;
cd5ea8 ¤   return err;
79efe6 }
87af5a
1daf5a
a666dd ¤   static PGPError
13d0fe sExistsProc(
337b33 ¤   PFLFileSpecRef¤ ref,
3704b7 ¤   PGPBoolean *¤   exists)
6abb36 {
419372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
445832 ¤   MyData const *¤ myData = GetMyData( ref );
0b1eb8 ¤   FILE *¤ ¤   ¤   stdIOFile;
12af5a
--04aa 000305d6cf4401000e2 Page 11 of pgpFileSpecStd.c
bfb7c9 ¤   /* Open the file read-only. If file doesn't exit, fopen fails */
e6af5a
043bac ¤   stdIOFile = fopen( myData->path, "rb" );
7151b0 ¤   if ( IsntNull( stdIOFile ) )
b1c7a1 ¤   {
7dc3de ¤   ¤   fclose(stdIOFile);
fc4945 ¤   ¤   *exists = TRUE;
f09371 ¤   }
400777 #ifdef EACCES
f20265 ¤   else if ( errno == EACCES )
5fc7a1 ¤   {
26afb9 #if PGP_WIN32
3743e7 ¤   ¤   err = kPGPError_CantOpenFile;
d37454 #endif
384945 ¤   ¤   *exists = TRUE;
869371 ¤   }
4b7454 #endif
1262fa #ifdef ENOENT
cd0a7a ¤   else if ( errno == ENOENT )
ed24a3 ¤   ¤   *exists = FALSE;
0a7454 #endif
74935b #ifdef EAGAIN
1e5a5b ¤   else if ( errno == EAGAIN )
8324a3 ¤   ¤   *exists = FALSE;
eb7454 #endif
810e24 ¤   else
d2c7a1 ¤   {
c25478 ¤   ¤   pgpDebugMsg( "pgpFileSpecStd.c:sExistsProc(): unknown errno" );
9e43e7 ¤   ¤   err = kPGPError_CantOpenFile;
e89371 ¤   }
3daf5a
00deb7 ¤   return( err );
eeefe6 }
e4af5a
61af5a
6a66dd ¤   static PGPError
2f3d91 sCreateProc( PFLFileSpecRef ref )
89bb36 {
129372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
76294e ¤   char const *¤   path¤   = GetMyData( ref )->path;
6767c5 ¤
078556 #if PGP_UNIX¤   /* [ */
cfd466 ¤   int¤¤   ¤   fileDes;
4c67c5 ¤
97d8af ¤   /*
11d5dc ¤   ·* XXX Beware that calling this routine could be a security flaw,
31b110 ¤   ·* ····because there is a window between creating and opening
101ca3 ¤   ·* ····the file, in between which the file might have been moved
8d55ba ¤   ·* ····out of the way, thus possibly having you open a new file
2cfe7d ¤   ·* ····with the wrong permissions.
b0a4e3 ¤   ·*/
dc2b2b ¤   fileDes = open( path, O_WRONLY | O_CREAT | O_EXCL, 0600 );
72d7dd ¤   if (fileDes > 0)
15cbe9 ¤   ¤   close( fileDes );
970e24 ¤   else
b0dd65 ¤   ¤   err = kPGPError_FileOpFailed;
c45532 #else¤  /* ] PGP_UNIX [ */
8b6571 ¤   FILE *¤ ¤   stdIOFile;
d767c5 ¤
658a5e ¤   stdIOFile = fopen( path, "ab+");
6051b0 ¤   if ( IsntNull( stdIOFile ) )
4dc3de ¤   ¤   fclose(stdIOFile);
db0e24 ¤   else
58dd65 ¤   ¤   err = kPGPError_FileOpFailed;
534bf8 #endif¤ /* ] PGP_UNIX */
62af5a
75deb7 ¤   return( err );
d3efe6 }
bbaf5a
6baf5a
3e66dd ¤   static PGPError
309ed8 sDeleteProc( PFLConstFileSpecRef ref )
--0ded 00173b1c91b401000e2 Page 12 of pgpFileSpecStd.c
2cbb36 {
4f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
f4670f ¤   const char *¤   path¤   = GetMyData( ref )->path;
9967c5 ¤
b785c9 ¤   if ( remove( path ) != 0 )
d7dd65 ¤   ¤   err = kPGPError_FileOpFailed;
2267c5 ¤
c6deb7 ¤   return( err );
5cefe6 }
60af5a
fdaf5a
3a0335 /*____________________________________________________________________________
0a0f3e ¤   Rename the file AND change the name in the file spec itself.
cc67c5 ¤
d61e7e ¤   If the file cannot be renamed, the file spec is not changed.
a6f7f7 ____________________________________________________________________________*/
4aaf5a
c466dd ¤   static PGPError
ec3b71 sRenameProc(
ec7b33 ¤   PFLFileSpecRef¤ ref,
1a17d5 ¤   const char *¤   newName)
c1bb36 {
e19372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
a5c3a7 ¤   MyData *¤   ¤   oldDataCopy¤= NULL;
6c2fb0 ¤   PGPMemoryMgrRef¤memoryMgr¤  = ref->memoryMgr;
a367c5 ¤
2c5aa1 ¤   /* save the old data in case the rename fails */
fe00f5 ¤   /* also needed for rename (see below) */
85d67e ¤   oldDataCopy¤= (MyData *)PGPNewData( memoryMgr,
342c95 ¤   ¤   ¤   ¤   ¤   MyDataSize( ref ), 0);
7344a2 ¤   if ( IsntNull( oldDataCopy ) )
e5c7a1 ¤   {
a50dd5 ¤   ¤   pgpCopyMemory( GetMyData( ref ),
c8af0f ¤   ¤   ¤   oldDataCopy, MyDataSize( ref ) );
36af5a
1aeb8c ¤   ¤   /* this changes the current data */
fadf69 ¤   ¤   err¤= sSetNameProc( ref, newName );
f61b52 ¤   ¤
ff73ef ¤   ¤   if ( rename( oldDataCopy->path, GetMyData( ref )->path ) != 0)
0a5b34 ¤   ¤   {
ab0903 ¤   ¤   ¤   err = kPGPError_FileOpFailed;¤  ¤   /* XXX Improve error */
ef90b8 ¤   ¤   ¤   /* put old path back in place of new one */
004c82 ¤   ¤   ¤   PGPFreeData( GetMyData( ref ) );
f98e61 ¤   ¤   ¤   SetMyData( ref, oldDataCopy );
100fe4 ¤   ¤   }
0d0e1d ¤   ¤   else
3b5b34 ¤   ¤   {
c75895 ¤   ¤   ¤   PGPFreeData( oldDataCopy );
b70fe4 ¤   ¤   }
bc9371 ¤   }
c00e24 ¤   else
70c7a1 ¤   {
8c17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
f69371 ¤   }
9167c5 ¤
3bdeb7 ¤   return( err );
8defe6 }
d0af5a
f4af5a
d5af5a
22af5a
54af5a
a1af5a
baaf5a
1138e5 /*
b5e6c5 ·* Local Variables:
109b19 ·* tab-width: 4
03e7a4 ·* End:
dcb612 ·* vi: ts=4 sw=4
f46c42 ·* vim: si
73495d ·*/
--e5b5 001886b6336401000e3 Page 1 of pgpFileSpecStd.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ba2a01 ¤   Standard implementation of a file specification. ·Assumes system uses
056a04 ¤   full paths of the form /a/b/c or \a\b\c.
58af5a
8d6a94 ¤   $Id: pgpFileSpecStd.h,v 1.8.16.1 1998/11/12 03:18:14 heller Exp $
9bf7f7 ____________________________________________________________________________*/
733550 #ifndef Included_pgpFileSpecStd_h¤  /* [ */
54193e #define Included_pgpFileSpecStd_h
d9af5a
26af5a
9c6e4c /* this file is included by pgpFileSpec.h and shouldn't be included directly */
e70329 #ifndef _pgpFileSpecIncludeRightStuff_
b2ce44 #error "don't include this file directly. ·Use pgpFileSpec.h instead."
d57454 #endif
50af5a
3daf5a
7a99c6 PGP_BEGIN_C_DECLARATIONS
5fcbcf #if PRAGMA_IMPORT_SUPPORTED
fbb981 #pragma import on
f77454 #endif
1baf5a
92af5a
6ba97f #if ! PGP_MACINTOSH /* [ */
48af5a
1401d9 PGPError ¤  PFLNewFileSpecFromFullPath( PGPMemoryMgrRef memoryMgr,
fc7951 ¤   ¤   ¤   ¤   ¤   char const * path, PFLFileSpecRef * outRef );
e2af5a
74af5a
dae10b PGPError ·¤ PFLGetFullPathFromFileSpec(PFLConstFileSpecRef fileRef,
6d0acf ¤   ¤   ¤   ¤   ¤   ¤   char **fullPathPtr);
5994aa ¤   ¤   ¤   ¤   ¤   ¤
be3167 #endif¤ /* ] */
fcaf5a
76af5a
32af5a
35cbcf #if PRAGMA_IMPORT_SUPPORTED
892ced #pragma import reset
1a7454 #endif
461254 PGP_END_C_DECLARATIONS
7caf5a
1baf5a
b0a86a #endif¤ /* ] Included_pgpFileSpecStd_h */
a8af5a
f138e5 /*
ece6c5 ·* Local Variables:
229b19 ·* tab-width: 4
4fe7a4 ·* End:
b4b612 ·* vi: ts=4 sw=4
bb6c42 ·* vim: si
88495d ·*/
--491e 00106e245cf401000e4 Page 1 of pgpFileSpecStdPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
b65506 ¤   $Id: pgpFileSpecStdPriv.h,v 1.2.34.1 1998/11/12 03:18:14 heller Exp $
74f7f7 ____________________________________________________________________________*/
e28347 #ifndef Included_pgpFileSpecStdPriv_h¤  /* [ */
74e93a #define Included_pgpFileSpecStdPriv_h
38af5a
5caf5a
18b2ca #include "pgpFileSpecPriv.h"
73af5a
1599c6 PGP_BEGIN_C_DECLARATIONS
97af5a
8aaf5a
092cc5 const PGPFileSpecVTBL *¤GetFileSpecVTBLStd( void );
90af5a
381254 PGP_END_C_DECLARATIONS
8faf5a
77af5a
fba86a #endif¤ /* ] Included_pgpFileSpecStd_h */
28af5a
0d38e5 /*
c8e6c5 ·* Local Variables:
539b19 ·* tab-width: 4
59e7a4 ·* End:
34b612 ·* vi: ts=4 sw=4
686c42 ·* vim: si
06495d ·*/
--9c81 00089370de8401000e5 Page 1 of pgpFileSpecVTBL.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
88cd45 ¤   $Id: pgpFileSpecVTBL.c,v 1.2.34.1 1998/11/12 03:18:15 heller Exp $
9af7f7 ____________________________________________________________________________*/
59e610 #include "pgpPFLConfig.h"
b2af5a
920d08 #include "pgpMem.h"
cfaf5a
bd6ab2 #define PGP_USE_FILE_SPEC_PRIV¤ 1
1941ba #include "pgpFileSpecMacPriv.h"
c3de29 #include "pgpFileSpecStdPriv.h"
2ba409 #include "pgpFileSpecVTBL.h"
ecaf5a
d20335 /*____________________________________________________________________________
132026 ¤   This routine is needed in order to reconstruct a FileSpec that has been
847e39 ¤   exported and now needs to be imported and formed into a valid object.
5f67c5 ¤
f1dd37 ¤   Since the object doesn't exist, we don't have its vtbl and since we
101e9c ¤   don't have its vtbl, we can't tell it to create itself. ·So this forms
a139ac ¤   the glue that allows this to happen.
aef7f7 ____________________________________________________________________________*/
ff4aee ¤   const PGPFileSpecVTBL *
03c0eb pgpGetFileSpecVTBLForType( PFLFileSpecType type )
d7bb36 {
94f177 ¤   const PGPFileSpecVTBL *vtbl¤= NULL;
f667c5 ¤
89c302 ¤   switch( type )
05c7a1 ¤   {
c23d00 ¤   ¤   default:¤   vtbl¤   = NULL;¤break;
5b1b52 ¤   ¤
129a50 #if PGP_MACINTOSH¤  ¤   /* [ */
1180e8 ¤   ¤   case kPFLFileSpecMacType:¤  ¤   vtbl¤   = GetFileSpecVTBLMac();¤break;
4fac70 #else¤  ¤   ¤   ¤   ¤   /* ] PGP_MACINTOSH [ */
6dda2e ¤   ¤   case kPFLFileSpecFullPathType:¤ vtbl¤   = GetFileSpecVTBLStd();¤break;
fe5948 #endif¤ ¤   ¤   ¤   ¤   /* ] */
ff9371 ¤   }
4b67c5 ¤
1323e5 ¤   pgpAssert( IsntNull( vtbl ) );
6c7543 ¤   return( vtbl );
0befe6 }
a4af5a
daaf5a
1baf5a
84af5a
bbaf5a
69af5a
f4af5a
f4af5a
f2af5a
7faf5a
87af5a
efaf5a
8aaf5a
9aaf5a
a5af5a
65af5a
7faf5a
b3af5a
2faf5a
b3af5a
01af5a
36af5a
9caf5a
9aaf5a
c5af5a
28af5a
e4af5a
89af5a
--b824 0010f542cf2401000e5 Page 2 of pgpFileSpecVTBL.c
e0af5a
1aaf5a
17af5a
c27e4d /*__Editor_settings____
98af5a
804126 ¤   Local Variables:
287b17 ¤   tab-width: 4
550e6c ¤   End:
b75f8c ¤   vi: ts=4 sw=4
ae9e9b ¤   vim: si
0fd062 _____________________*/
--0324 001992f6aec401000e6 Page 1 of pgpFileSpecVTBL.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
3f2eaa ¤   $Id: pgpFileSpecVTBL.h,v 1.2.30.1 1998/11/12 03:18:16 heller Exp $
b0f7f7 ____________________________________________________________________________*/
1a3275 #ifndef Included_pgpFileSpecVTBL_h¤ /* [ */
26e356 #define Included_pgpFileSpecVTBL_h
5baf5a
bdb2ca #include "pgpFileSpecPriv.h"
74af5a
1899c6 PGP_BEGIN_C_DECLARATIONS
9fcbcf #if PRAGMA_IMPORT_SUPPORTED
44b981 #pragma import on
ab7454 #endif
caaf5a
3baf5a
b2af5a
84af5a
1366ad const PGPFileSpecVTBL *¤pgpGetFileSpecVTBLForType( PFLFileSpecType type );
26af5a
22af5a
bfaf5a
05cbcf #if PRAGMA_IMPORT_SUPPORTED
b82ced #pragma import reset
fc7454 #endif
2f1254 PGP_END_C_DECLARATIONS
afaf5a
3f1fc6 #endif /* ] Included_pgpFileSpecVTBL_h */
8faf5a
23af5a
037e4d /*__Editor_settings____
a0af5a
a74126 ¤   Local Variables:
ab7b17 ¤   tab-width: 4
f60e6c ¤   End:
a25f8c ¤   vi: ts=4 sw=4
f39e9b ¤   vim: si
99d062 _____________________*/
--6a68 0000e734848401000e7 Page 1 of pgpFileSpecWin32.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
f2182d ¤   $Id: pgpFileSpecWin32.c,v 1.6.16.1 1998/11/12 03:18:16 heller Exp $
3ff7f7 ____________________________________________________________________________*/
e8af5a
aaaf5a
bde610 #include "pgpPFLConfig.h"
bbaf5a
cb5655 #include <windows.h>
fffeb2 #include <stdio.h>
c5af5a
81a146 #include "pgpDebug.h"
6a0d08 #include "pgpMem.h"
562b62 #include "pgpPFLErrors.h"
7c1c21 #define PGP_USE_FILE_SPEC_PRIV
39b2ca #include "pgpFileSpecPriv.h"
ba6773 #include "pgpMemoryMgr.h"
dcaf5a
3866ae struct PFLDirectoryIter
e1bb36 {
a5f7f4 ¤   PGPMemoryMgrRef¤¤   memoryMgr;
a65629 ¤   PFLFileSpecRef¤ ¤   parentDir;
d21407 ¤   HANDLE¤ ¤   ¤   ¤   fileSearch;
20f82a ¤   WIN32_FIND_DATA¤¤   findData;
7c82f7 };
b1af5a
6caf5a
f6af5a
67c744 ¤   PGPError
49ba0c pgpPlatformNewDirectoryIter(
894505 ¤   PFLConstFileSpecRef¤¤   parentDir,
e0a05a ¤   PFLDirectoryIterRef *¤  outIter )
b2bb36 {
90b002 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr¤  = PFLGetFileSpecMemoryMgr( parentDir );
4fcbf8 ¤   char *¤ ¤   ¤   ¤   ¤   path;
4154f1 ¤   char *¤ ¤   ¤   ¤   ¤   pattern;
9b64a8 ¤   PFLDirectoryIterRef¤¤   newIter¤= NULL;
633a27 ¤   PGPError¤   ¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
04af5a
6a18d6 ¤   *outIter = NULL;
bead91 ¤   PGPValidateMemoryMgr( memoryMgr );
b1af5a
a4b098 ¤   err = PFLGetFullPathFromFileSpec( parentDir, &path );
b2f1e7 ¤   if ( IsntPGPError( err ) )
68c7a1 ¤   {
b002a9 ¤   ¤   pattern = (char *)PGPNewData( memoryMgr,
5c8621 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·strlen( path ) + 5, ·0 );
3e21ff ¤   ¤   if ( IsntNull( pattern ) )
9d5b34 ¤   ¤   {
681cf3 ¤   ¤   ¤   strcpy( pattern, path );
736c79 ¤   ¤   ¤   strcat( pattern, "\\*.*" );
bd6375 ¤   ¤   ¤   newIter = (PFLDirectoryIterRef)PGPNewData( memoryMgr,
4a2630 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *newIter ), 0 );
2f8ce4 ¤   ¤   ¤   if ( IsntNull( newIter ) )
eaf776 ¤   ¤   ¤   {
f4e4ec ¤   ¤   ¤   ¤   newIter->memoryMgr = memoryMgr;
2ce4c8 ¤   ¤   ¤   ¤   newIter->fileSearch = FindFirstFile( pattern,
494042 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&newIter->findData );
bdaf5a
465a91 ¤   ¤   ¤   ¤   if ( newIter->fileSearch == INVALID_HANDLE_VALUE &&
351316 ¤   ¤   ¤   ¤   ¤   ¤   GetLastError() != 0 )
c772c3 ¤   ¤   ¤   ¤   {
1aa2ad ¤   ¤   ¤   ¤   ¤   err = kPGPError_FileOpFailed;¤  /* XXX Better error code? */
4e2613 ¤   ¤   ¤   ¤   }
0dfa07 ¤   ¤   ¤   ¤   else
fd72c3 ¤   ¤   ¤   ¤   {
fc3fbb ¤   ¤   ¤   ¤   ¤   err = PFLCopyFileSpec( parentDir, &newIter->parentDir );
d92613 ¤   ¤   ¤   ¤   }
0ea3a6 ¤   ¤   ¤   }
--b93b 001dfdababa401000e7 Page 2 of pgpFileSpecWin32.c
b1bb8c ¤   ¤   ¤   else
89f776 ¤   ¤   ¤   {
a9bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
eba3a6 ¤   ¤   ¤   }
908e1e ¤   ¤   ¤   PGPFreeData( pattern );
450fe4 ¤   ¤   }
6f0e1d ¤   ¤   else
d25b34 ¤   ¤   {
ceb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
f60fe4 ¤   ¤   }
c596f9 ¤   ¤   PGPFreeData( path );
8c9371 ¤   }
52af5a
4ff1e7 ¤   if ( IsntPGPError( err ) )
1112ef ¤   ¤   *outIter = newIter;
24360d ¤   else if ( IsntNull( newIter ) )
1abbb9 ¤   ¤   PGPFreeData( newIter );
27af5a
935ea8 ¤   return err;
aaefe6 }
27af5a
b7c744 ¤   PGPError
fc7d10 pgpPlatformNextFileInDirectory(
e89676 ¤   PFLDirectoryIterRef¤¤   iter,
4680bd ¤   PFLFileSpecRef *¤   ¤   outRef )
98bb36 {
c17d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
e3af5a
c5cd60 ¤   *outRef = NULL;
b9af5a
9f7bd9 ¤   if ( iter->fileSearch != INVALID_HANDLE_VALUE )
bec7a1 ¤   {
2e0f58 ¤   ¤   err = PFLComposeFileSpec( iter->parentDir,
08dbd6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··iter->findData.cFileName, outRef );
290e10 ¤   ¤   if ( !FindNextFile( iter->fileSearch, &iter->findData ) )
895595 ¤   ¤   ¤   iter->fileSearch = INVALID_HANDLE_VALUE;
c79371 ¤   }
500e24 ¤   else
95c7a1 ¤   {
231311 ¤   ¤   err = kPGPError_EndOfIteration;
ae9371 ¤   }
61af5a
5f5ea8 ¤   return err;
2defe6 }
cfaf5a
35c744 ¤   PGPError
d619da pgpPlatformFreeDirectoryIter(
311585 ¤   PFLDirectoryIterRef¤¤   iter )
6abb36 {
1e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
a2af5a
78d4ad ¤   PGPValidatePtr( iter );
d9af5a
3e1f11 ¤   PFLFreeFileSpec( iter->parentDir );
d3fda2 ¤   FindClose( iter->fileSearch );·
24aec6 ¤   PGPFreeData( iter );
b75ea8 ¤   return err;
f4efe6 }
1daf5a
c2af5a
8faf5a
5838e5 /*
eee6c5 ·* Local Variables:
e79b19 ·* tab-width: 4
4de7a4 ·* End:
a8b612 ·* vi: ts=4 sw=4
fc6c42 ·* vim: si
df495d ·*/
--da2a 00094076822401000e8 Page 1 of pgpFileUtilities.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
9489ff ¤   $Id: pgpFileUtilities.c,v 1.16.16.1 1998/11/12 03:18:17 heller Exp $
20f7f7 ____________________________________________________________________________*/
bcaf5a
38e610 #include "pgpPFLConfig.h"
daaf5a
15324c #include <string.h>
aafeb2 #include <stdio.h>
25af5a
16abff #if HAVE_UNISTD_H
2dd912 #include <unistd.h>¤¤   ¤   /* Declares truncate() */
747454 #endif
1faf5a
01a146 #include "pgpDebug.h"
802b62 #include "pgpPFLErrors.h"
8c0d08 #include "pgpMem.h"
44af5a
303427 #include "pgpFileUtilities.h"
ffae60 #include "pgpStdFileIO.h"
3aaf5a
651c21 #define PGP_USE_FILE_SPEC_PRIV
34b2ca #include "pgpFileSpecPriv.h"
9caf5a
c0eb0f #ifdef PGP_WIN32
301044 #include <io.h>
d137bc #include <fcntl.h>
adaf5a
25c5c0 #endif¤ /* PGP_WIN32 */
b9af5a
8caf5a
cb66dd ¤   static PGPError
1fab12 pgpOpenFileSpecAsFILE(
fc2499 ¤   PFLFileSpecRef¤ spec,
d7d6c3 ¤   const char *¤   openMode,
779605 ¤   FILE **¤¤   ¤   fileOut )
26bb36 {
bc26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5867c5 ¤
4a508c ¤   PGPValidatePtr( fileOut );
eb48de ¤   *fileOut¤   = NULL;
870282 ¤   PFLValidateFileSpec( spec );
a48e69 ¤   PGPValidatePtr( openMode );
8f67c5 ¤
f40785 ¤   err¤= pgpPlatformOpenFileSpecAsFILE( spec, openMode, fileOut);
4c67c5 ¤
14deb7 ¤   return( err );
27efe6 }
6eaf5a
cec744 ¤   PGPError
adb430 PFLLockFILE(
64f51c ¤   FILE *¤ ¤   ¤   ¤   file,
4f61bb ¤   PFLFileOpenFlags¤   flags )
b4bb36 {
8e5f76 ¤   PGPValidatePtr( file );
65af5a
90c9cd ¤   return pgpPlatformLockFILE( file, flags );
65efe6 }
aeaf5a
b1c744 ¤   PGPError
66dc24 PGPOpenFileSpec(
580a33 ¤   PFLFileSpecRef¤ ¤   spec,
e11771 ¤   PFLFileOpenFlags¤   flags,
204f20 ¤   PGPFileIORef *¤ ¤   outRef )
07bb36 {
ce9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
2e24f9 ¤   const char *¤   modeString¤ = NULL;
55afc5 ¤   FILE *¤ ¤   ¤   stdioFILE¤  = NULL;
9467c5 ¤
--904b 000ea8e0235401000e8 Page 2 of pgpFileUtilities.c
e23c76 ¤   PGPValidatePtr( outRef );
313652 ¤   *outRef¤= NULL;
4d0282 ¤   PFLValidateFileSpec( spec );
2c3c93 ¤   PGPValidateParam( ( flags & ~( kPFLFileOpenFlags_ReadWrite·
0532ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·| kPFLFileOpenFlags_LockFile ) ) == 0 );
7367c5 ¤
1dab05 ¤   if ( flags & kPFLFileOpenFlags_ReadWrite )
edf815 ¤   ¤   modeString¤ = "r+b";
fc0e24 ¤   else
986924 ¤   ¤   modeString¤ = "rb";
3167c5 ¤
b4cbf0 ¤   err¤= pgpOpenFileSpecAsFILE( spec, modeString, &stdioFILE );
09f1e7 ¤   if ( IsntPGPError( err ) )
98c7a1 ¤   {
9f5440 ¤   ¤   if ( flags & kPFLFileOpenFlags_LockFile )
fc8dab ¤   ¤   ¤   err = pgpPlatformLockFILE( stdioFILE, flags );
0f7d98 ¤   ¤   if ( IsntPGPError( err ) )
d85b34 ¤   ¤   {
9c391a ¤   ¤   ¤   PGPStdFileIORef¤¤   ref;
1bb84b ¤   ¤   ¤   PGPMemoryMgrRef¤¤   memoryMgr;
9787c7 ¤   ¤   ¤
fe08fd ¤   ¤   ¤   memoryMgr¤  = PFLGetFileSpecMemoryMgr( spec );
2493ae ¤   ¤   ¤   err¤= PGPNewStdFileIO( memoryMgr, stdioFILE, TRUE, &ref );
a587c7 ¤   ¤   ¤
ca83ab ¤   ¤   ¤   *outRef¤= (PGPFileIORef)ref;
9a0fe4 ¤   ¤   }
6c9371 ¤   }
1d67c5 ¤
28deb7 ¤   return( err );
b8efe6 }
32af5a
09af5a
a8af5a
2bc21c #if PGP_MACINTOSH¤  /* [ */
b7af5a
eb76b7 #include "MacErrors.h"
6166dd ¤   static PGPError
bf6a13 sPGPSetFileSize(
923c38 ¤   PFLConstFileSpecRef¤fileSpec,
d8cb0e ¤   PGPFileOffset¤  ¤   newSize )
9ebb36 {
4726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
11eaa1 ¤   FSSpec¤ ¤   macSpec;
4167c5 ¤
15689c ¤   /* caller has already validated other things */
f5fe5d ¤   /* Macs with current file system & API only support < 2GB files */
0e67f9 ¤   PGPValidateParam( newSize < ( 2UL * 1024UL * 1024UL * 1024UL) - 512 );
a567c5 ¤
ab28e1 ¤   err¤= PFLGetFSSpecFromFileSpec( fileSpec, &macSpec );
2af1e7 ¤   if ( IsntPGPError( err ) )
f4c7a1 ¤   {
c8126d ¤   ¤   short¤  ¤   fileRef;
18c656 ¤   ¤   OSStatus¤   macErr;
d967c5 ¤
ac5c6c ¤   ¤   macErr¤ = FSpOpenDF( &macSpec, fsRdWrPerm, &fileRef );
657965 ¤   ¤   if ( macErr == noErr )
bf5b34 ¤   ¤   {
787bed ¤   ¤   ¤   macErr¤ = SetEOF( fileRef, (long)newSize );
3601e0 ¤   ¤   ¤   FSClose( fileRef );
550fe4 ¤   ¤   }
ef1b52 ¤   ¤
90a5a0 ¤   ¤   err¤= MacErrorToPGPError( macErr );
819371 ¤   }
9c67c5 ¤
1767c5 ¤
81deb7 ¤   return( err );
20efe6 }
aeaf5a
343167 #endif¤ /* ] */
d1af5a
5b94d2 #if PGP_WIN32¤  /* [ */
eaaf5a
--9f88 000090c1796401000e8 Page 3 of pgpFileUtilities.c
b9d3c9 #if defined( __MWERKS__ )
4a99c6 PGP_BEGIN_C_DECLARATIONS
7c3e3d /* metrowerks doesn't seem to have this prototype */
d10510 int¤¤   _chsize( int fileHandle, long newSize );
0b1254 PGP_END_C_DECLARATIONS
437454 #endif
1daf5a
1166dd ¤   static PGPError
e16a13 sPGPSetFileSize(
db3c38 ¤   PFLConstFileSpecRef¤fileSpec,
a0cb0e ¤   PGPFileOffset¤  ¤   newSize )
75bb36 {
9c8e12 ¤   PGPError¤   err = kPGPError_NoErr;
ffcca2 ¤   char *¤ ¤   fullFilePath¤   = NULL;
18af5a
9f689c ¤   /* caller has already validated other things */
5fbb74 ¤   PGPValidateParam(newSize <= LONG_MAX);
57af5a
63ee3b ¤   err = PFLGetFullPathFromFileSpec(fileSpec, &fullFilePath);
b3bb4c ¤   if ( IsntPGPError(err) )
64c7a1 ¤   {
95c783 ¤   ¤   int¤¤   ¤   result¤ ¤   = -1;
9e4587 ¤   ¤   int¤¤   ¤   fileHandle¤ = -1;
6567c5 ¤
fcef44 ¤   ¤   fileHandle = _open(fullFilePath, _O_BINARY | O_WRONLY);
ecaf5a
8455f3 ¤   ¤   if (fileHandle == -1)
4ae18b ¤   ¤   ¤   err = kPGPError_FileOpFailed;
700e1d ¤   ¤   else
455b34 ¤   ¤   {
13a3e0 ¤   ¤   ¤   result = _chsize(fileHandle, (long) newSize);
5ef3fa ¤   ¤   ¤   _close(fileHandle);
a4af5a
2e482a ¤   ¤   ¤   if (result == -1)
dbd84e ¤   ¤   ¤   ¤   err = kPGPError_FileOpFailed;
b60fe4 ¤   ¤   }
181b52 ¤   ¤
ed0af3 ¤   ¤   PGPFreeData( fullFilePath);
229371 ¤   }
a7af5a
305ea8 ¤   return err;
d3efe6 }
a1af5a
a4a4fe #endif¤ /* ] PGP_WIN32 */
6caf5a
e4af5a
6baf5a
908556 #if PGP_UNIX¤   /* [ */
80af5a
c066dd ¤   static PGPError
d16a13 sPGPSetFileSize(
783c38 ¤   PFLConstFileSpecRef¤fileSpec,
2dcb0e ¤   PGPFileOffset¤  ¤   newSize )
04bb36 {
628e12 ¤   PGPError¤   err = kPGPError_NoErr;
edcca2 ¤   char *¤ ¤   fullFilePath¤   = NULL;
b3af5a
b6f8ef ¤   /* caller has already validated params */
53af5a
45ee3b ¤   err = PFLGetFullPathFromFileSpec(fileSpec, &fullFilePath);
04bb4c ¤   if ( IsntPGPError(err) )
99c7a1 ¤   {
ecc783 ¤   ¤   int¤¤   ¤   result¤ ¤   = -1;
cc67c5 ¤
41e09a ¤   ¤   result = truncate( fullFilePath, (size_t)newSize );
63af5a
20709b ¤   ¤   if( result == -1 )
a9e18b ¤   ¤   ¤   err = kPGPError_FileOpFailed;
391b52 ¤   ¤
787461 ¤   ¤   PGPFreeData(fullFilePath);
ba9371 ¤   }
09af5a
--8945 001be6acddf401000e8 Page 4 of pgpFileUtilities.c
ec5ea8 ¤   return err;
2aefe6 }
e0af5a
ba4bf8 #endif¤ /* ] PGP_UNIX */
ccaf5a
09af5a
ffaf5a
4cc744 ¤   PGPError
3b60a5 PGPSetFileSize(
ee3c38 ¤   PFLConstFileSpecRef¤fileSpec,
ffcb0e ¤   PGPFileOffset¤  ¤   newSize )
7dbb36 {
c926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
e467c5 ¤
421859 ¤   PFLValidateFileSpec( fileSpec );
eda88c ¤   PGPValidateParam( newSize >= 0 );
ffaf5a
36fc95 ¤   /* call platform specific version */
b74487 ¤   err¤= sPGPSetFileSize( fileSpec, newSize );¤
d067c5 ¤
35deb7 ¤   return( err );
78efe6 }
b2af5a
18af5a
3eaf5a
f2af5a
cfaf5a
d0af5a
21af5a
d7af5a
5baf5a
a1af5a
54af5a
b2af5a
2daf5a
24af5a
36af5a
30af5a
a838e5 /*
b1e6c5 ·* Local Variables:
729b19 ·* tab-width: 4
8be7a4 ·* End:
aab612 ·* vi: ts=4 sw=4
356c42 ·* vim: si
be495d ·*/
--2ffc 0018e777811401000e9 Page 1 of pgpFileUtilities.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a3a348 ¤   Platform-independent file-specification. ·Specifies the *location* of a
6e49d1 ¤   file in the file system. ·Also included are utility routines for
e76bcb ¤   manipulating files.
d767c5 ¤
a39f1e ¤   Note that a PGPFileSpec is not an object; it does not have subclasses
b42597 ¤   or inheritence.
fbaf5a
ef0995 ¤   $Id: pgpFileUtilities.h,v 1.8.16.1 1998/11/12 03:18:18 heller Exp $
58f7f7 ____________________________________________________________________________*/
709f49 #ifndef Included_pgpFileUtilities_h¤/* [ */
2f6c2f #define Included_pgpFileUtilities_h
1daf5a
2dfeb2 #include <stdio.h>
1d6773 #include "pgpMemoryMgr.h"
d6894b #include "pgpFileSpec.h"
1cc68b #include "pgpFileIO.h"
14af5a
cc99c6 PGP_BEGIN_C_DECLARATIONS
0bcbcf #if PRAGMA_IMPORT_SUPPORTED
7ab981 #pragma import on
427454 #endif
62af5a
ceaf5a
ef2c37 enum PFLFileOpenFlags_
25bb36 {
3fdf98 ¤   kPFLFileOpenFlags_ReadOnly¤ ¤   = 0,
be97cd ¤   kPFLFileOpenFlags_ReadWrite¤¤   = (1L << 0),
2548f0 ¤   kPFLFileOpenFlags_LockFile¤ ¤   = (1L << 1)
a282f7 };
2ca51c typedef PGPUInt32¤  PFLFileOpenFlags;
abaf5a
2503e2 PGPError¤   PGPOpenFileSpec( PFLFileSpecRef spec, PFLFileOpenFlags flags,
9b8cd4 ¤   ¤   ¤   ¤   PGPFileIORef *outRef );
95af5a
2d38e5 /*
317512 ·* Perform any optional locking which isn't done by fopen().
62a469 ·* Normally you shouldn't use this directly. ·Instead just pass the
2cca11 ·* kPFLFileOpenFlags_LockFile flag to PGPOpenFileSpec(). ·This routine
96df39 ·* is solely to support similar functionality in pgpFileRefStdIOOpen()
597a3b ·* of the PGPsdk library.
0d495d ·*/
dba3a9 PGPError¤   ¤   PFLLockFILE( FILE * file, PFLFileOpenFlags flags );
30af5a
a5af5a
f2ec7b /* set the file size of a *closed* file; it remains closed afterwards */
be3d88 PGPError¤   PGPSetFileSize( PFLConstFileSpecRef spec, PGPFileOffset size);
03af5a
c1af5a
82af5a
dfcbcf #if PRAGMA_IMPORT_SUPPORTED
85b981 #pragma import on
eb7454 #endif
631254 PGP_END_C_DECLARATIONS
05af5a
ab595f #endif¤ /* ] Included_pgpFileUtilities_h */
c4af5a
af38e5 /*
5ce6c5 ·* Local Variables:
a89b19 ·* tab-width: 4
8de7a4 ·* End:
c9b612 ·* vi: ts=4 sw=4
6f6c42 ·* vim: si
8e495d ·*/
--a052 0006e04be93401000ea Page 1 of pgpIO.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
2ff800 ¤   Abstract superclass for all PGPIO objects. ·PGPIO objects form a class
f294bc ¤   hierarchy which implements C++ style inheritance and virtual functions.
d4f5b7 ¤   Subclasses can override parent methods and can inherit as part of their
1de020 ¤   own implementation.
2767c5 ¤
4d2f8b ¤   Each PGPIO object type consists of three files:
be8b93 ¤   ¤   pgpXXXIO.c¤ ¤   ¤   code for the class
0fd1d0 ¤   ¤   pgpXXXIO.h¤ ¤   ¤   public API for the class
afb26c ¤   ¤   pgpXXXIOPriv.h¤ ¤   private class implementation details
cd67c5 ¤
b9e0fc ¤   Note that the pgpXXXIOPriv.h file contents should *only* be used
c79c19 ¤   by subclasses. ·It is off-limits to clients.
09af5a
266ca5 ¤   $Id: pgpIO.c,v 1.17.16.1 1998/11/12 03:18:18 heller Exp $
b7f7f7 ____________________________________________________________________________*/
9fe610 #include "pgpPFLConfig.h"
8baf5a
602b62 #include "pgpPFLErrors.h"
3c9c9f #include "pgpIOPriv.h"
920d08 #include "pgpMem.h"
7eaf5a
e43172 /* note: convention used here is that static functions begin with "s" */
32af5a
05af5a
f7af5a
d45947 ¤   PGPMemoryMgrRef
b1a9e4 PGPIOGetMemoryMgr( PGPIORef ref )
89bb36 {
e47d44 ¤   return( ref->context );
34efe6 }
3caf5a
8baf5a
02af5a
f56b90 #define CallInit( ref, vtbl, data ) \
627aa1 ¤   ¤   ((vtbl)->initProc)( ref, data )
bd1b52 ¤   ¤
cb7f9d #define CallDestroy( ref, vtbl ) \
ce94a6 ¤   ¤   ((vtbl)->destroyProc)( ref )
831b52 ¤   ¤
d459b4 #define CallRead( ref, vtbl, reqCount, buffer, bytesRead ) \
acdf22 ¤   ¤   ((vtbl)->readProc)( ref, reqCount, buffer, bytesRead )
5f1b52 ¤   ¤
492159 #define CallWrite( ref, vtbl, reqCount, buffer ) \
9cb26e ¤   ¤   ((vtbl)->writeProc)( ref, reqCount, buffer )
361b52 ¤   ¤
93f01a #define CallGetPos( ref, vtbl, pos ) \
2d2c10 ¤   ¤   ((vtbl)->getPosProc)( ref, pos )
451b52 ¤   ¤
5dbdfe #define CallSetPos( ref, vtbl, pos ) \
21d504 ¤   ¤   ((vtbl)->setPosProc)( ref, pos )
e61b52 ¤   ¤
cab9ff #define CallGetEOF( ref, vtbl, pos ) \
58d100 ¤   ¤   ((vtbl)->getEOFProc)( ref, pos )
f11b52 ¤   ¤
dfdc47 #if PGPIO_EOF
35f41b #define CallSetEOF( ref, vtbl, pos ) \
292814 ¤   ¤   ((vtbl)->setEOFProc)( ref, pos )
b67454 #endif
ab1b52 ¤   ¤
d09ee0 #define CallFlush( ref, vtbl ) \
4b25a5 ¤   ¤   ((vtbl)->flushProc)( ref )
bcaf5a
adaf5a
84c744 ¤   PGPError
8ac36f pgpioInheritInit(
4b36b4 ¤   PGPIORef¤   ¤   ¤   ref,
f2caa5 ¤   PGPIOVtbl const *¤  vtbl,
6e6b69 ¤   void *¤ ¤   ¤   ¤   data )
--5d82 0001306553d401000ea Page 2 of pgpIO.c
2cbb36 {
133253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
cc2652 ¤   return( CallInit( ref, vtbl, data ) );
efefe6 }
ceaf5a
c6c744 ¤   PGPError
89c97e pgpioInheritDestroy(
a136b4 ¤   PGPIORef¤   ¤   ¤   ref,
adf1cf ¤   PGPIOVtbl const *¤  vtbl )
06bb36 {
893253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
ed61c0 ¤   return( CallDestroy( ref, vtbl ) );
edefe6 }
85af5a
68af5a
cbc744 ¤   PGPError
a38b5b pgpioInheritRead(
8b36b4 ¤   PGPIORef¤   ¤   ¤   ref,
2bcaa5 ¤   PGPIOVtbl const *¤  vtbl,
1baba1 ¤   PGPSize¤¤   ¤   ¤   requestCount,
204984 ¤   void *¤ ¤   ¤   ¤   buffer,
3d2724 ¤   PGPSize *¤  ¤   ¤   bytesRead )
ddbb36 {
2d3253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
e16f15 ¤   return( CallRead( ref, vtbl, requestCount, buffer, bytesRead ) );
6befe6 }
f7af5a
03af5a
b1c744 ¤   PGPError
479d4e pgpioInheritWrite(
8636b4 ¤   PGPIORef¤   ¤   ¤   ref,
fecaa5 ¤   PGPIOVtbl const *¤  vtbl,
4faba1 ¤   PGPSize¤¤   ¤   ¤   requestCount,
12b500 ¤   const void *¤   ¤   buffer )
d9bb36 {
5b3253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
6e35cd ¤   return( CallWrite( ref, vtbl, requestCount, buffer ) );
75efe6 }
cfaf5a
85af5a
85c744 ¤   PGPError
b13c34 pgpioInheritSetPos(
8836b4 ¤   PGPIORef¤   ¤   ¤   ref,
2dcaa5 ¤   PGPIOVtbl const *¤  vtbl,
825fdb ¤   PGPFileOffset¤  ¤   newPos )
88bb36 {
413253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
380bc2 ¤   return( CallSetPos( ref, vtbl, newPos ) );
2eefe6 }
31af5a
ddaf5a
dec744 ¤   PGPError
4ad3c6 pgpioInheritGetEOF(
5936b4 ¤   PGPIORef¤   ¤   ¤   ref,
67caa5 ¤   PGPIOVtbl const *¤  vtbl,
4d537d ¤   PGPFileOffset *¤¤   eof )
32bb36 {
a93253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
e9de4b ¤   return( CallGetEOF( ref, vtbl, eof ) );
47efe6 }
0caf5a
7baf5a
50dc47 #if PGPIO_EOF
1bc744 ¤   PGPError
ce9e60 pgpioInheritSetEOF(
5636b4 ¤   PGPIORef¤   ¤   ¤   ref,
40caa5 ¤   PGPIOVtbl const *¤  vtbl,
1d3cd2 ¤   PGPFileOffset ¤ ¤   eof )
33bb36 {
2b3253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
7d7f2c ¤   return( CallSetEOF( ref, vtbl, eof ) );
13efe6 }
--07a1 000b0bad9a2401000ea Page 3 of pgpIO.c
a07454 #endif
e0af5a
f6af5a
b2c744 ¤   PGPError
42a76e pgpioInheritFlush(
9f36b4 ¤   PGPIORef¤   ¤   ¤   ref,
c9b41d ¤   PGPIOVtbl const *¤  vtbl)
d6bb36 {
8a3253 ¤   pgpAssert( PGPIOIsValid( ref ) && IsntNull( vtbl ) );
07c5a2 ¤   return( CallFlush( ref, vtbl ) );
5aefe6 }
7aaf5a
482b85 ¤   ¤   ¤   ¤
4c2b85 ¤   ¤   ¤   ¤
952b85 ¤   ¤   ¤   ¤
9716ea ¤   PGPBoolean
4f5697 PGPIOIsValid( PGPIORef ref )
fabb36 {
3b7088 ¤   return( IsntNull( ref ) &&
c2f905 ¤   ¤   ref->magic == kPGPIOMagic &&
c39806 ¤   ¤   IsntNull( ref->vtbl ) );
a8efe6 }
a8af5a
f7af5a
360335 /*____________________________________________________________________________
633966 ¤   Create a new PGPIO object. ·The vtbl and object size are specified so
a40432 ¤   that subclasses can use this routine.
55f7f7 ____________________________________________________________________________*/
cec744 ¤   PGPError
188183 pgpNewIOFromVTBL(
39d8a8 ¤   PGPMemoryMgrRef¤¤   context,
58caa5 ¤   PGPIOVtbl const *¤  vtbl,
461213 ¤   PGPSize¤¤   ¤   ¤   size,
6595db ¤   void *¤ ¤   ¤   ¤   data,
15be9e ¤   PGPIORef *¤ ¤   ¤   outRef )
90bb36 {
0d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
478e69 ¤   PGPIORef¤   newRef;
0567c5 ¤
1a3c76 ¤   PGPValidatePtr( outRef );
673652 ¤   *outRef¤= NULL;
bbefa3 ¤   PGPValidateMemoryMgr( context );
fe67c5 ¤
2dedd9 ¤   newRef¤ = (PGPIORef)PGPNewData( context,
51db89 ¤   ¤   ¤   ¤   size, kPGPMemoryMgrFlags_Clear );
856c1a ¤   if ( IsntNull( newRef ) )
dfc7a1 ¤   {
046bb2 ¤   ¤   /* use cast so we can assign to this const * const field */
4c7bb9 ¤   ¤   *(PGPIOVtbl const **)(&newRef->vtbl)¤   ¤   = vtbl;
9c1b52 ¤   ¤
e423bb ¤   ¤   newRef->context¤¤   = context;
151eb9 ¤   ¤   newRef->magic¤  ¤   = kPGPIOMagic;
28e4a9 ¤   ¤   /* initialize remaining fields in sInitProc */
981b52 ¤   ¤
98d91b ¤   ¤   err¤= CallInit( newRef, newRef->vtbl, data );
ffbe18 ¤   ¤   if ( IsPGPError( err ) )
205b34 ¤   ¤   {
c816bf ¤   ¤   ¤   CallDestroy( newRef, newRef->vtbl);
19a062 ¤   ¤   ¤   PGPFreeData( newRef );
ff82ad ¤   ¤   ¤   newRef¤ = NULL;
b20fe4 ¤   ¤   }
809371 ¤   }
9e0e24 ¤   else
5bc7a1 ¤   {
e117a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
029371 ¤   }
1e67c5 ¤
40cdaf ¤   *outRef¤= newRef;
d1deb7 ¤   return( err );
f1efe6 }
6aaf5a
b0af5a
--42ea 00092a2fdc0401000ea Page 4 of pgpIO.c
d3c744 ¤   PGPError
119972 PGPFreeIO( PGPIORef ref )
bfbb36 {
4830d4 ¤   PGPError¤   err¤¤   = kPGPError_NoErr;
d567c5 ¤
4d3ef5 ¤   PGPValidateIO( ref );
e767c5 ¤
c01d2c ¤   err¤= CallDestroy( ref, ref->vtbl);
3b67c5 ¤
2dfa58 ¤   PGPFreeData( ref );
8b67c5 ¤
d6deb7 ¤   return( err );
4eefe6 }
10af5a
c5af5a
8ec744 ¤   PGPError
bd4933 PGPIORead(
3adcbc ¤   PGPIORef¤   ref,
01e5ef ¤   PGPSize¤¤   requestCount,
6e296a ¤   void *¤ ¤   buffer,
55fca5 ¤   PGPSize *¤  bytesReadOut )
9bbb36 {
5226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
51d1cc ¤   PGPSize¤¤   bytesRead¤  = 0;
2c67c5 ¤
9f79bd ¤   if ( IsntNull( bytesReadOut ) )
d1c7a1 ¤   {
c0974e ¤   ¤   *bytesReadOut¤  = 0;
e99371 ¤   }
013ef5 ¤   PGPValidateIO( ref );
7bb99f ¤   PGPValidatePtr( buffer );
4c67c5 ¤
281413 ¤   if( requestCount > 0 )
d7c7a1 ¤   {
b4cf9e ¤   ¤   err¤= CallRead( ref, ref->vtbl, requestCount, buffer, &bytesRead );
9d7d98 ¤   ¤   if ( IsntPGPError( err ) )
8d4759 ¤   ¤   ¤   ref->offset¤+= bytesRead;
359371 ¤   }
c667c5 ¤
f279bd ¤   if ( IsntNull( bytesReadOut ) )
2b14d3 ¤   ¤   *bytesReadOut = bytesRead;
ac67c5 ¤
3ddeb7 ¤   return( err );
1aefe6 }
1794aa ¤   ¤   ¤   ¤   ¤   ¤
29c744 ¤   PGPError
2172c2 PGPIOWrite(
ccb7a9 ¤   PGPIORef¤   ¤   ref,
756179 ¤   PGPSize¤¤   ¤   requestCount,
2fb457 ¤   const void *¤   buffer )
ffbb36 {
1126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d167c5 ¤
2a3ef5 ¤   PGPValidateIO( ref );
93b99f ¤   PGPValidatePtr( buffer );
ba67c5 ¤
ef1413 ¤   if( requestCount > 0 )
79c7a1 ¤   {
3fba38 ¤   ¤   err¤= CallWrite( ref, ref->vtbl, requestCount, buffer );
977d98 ¤   ¤   if ( IsntPGPError( err ) )
9824cb ¤   ¤   ¤   ref->offset¤+= requestCount;
559371 ¤   }
0667c5 ¤
56deb7 ¤   return( err );
6b1623 }¤  ¤   ¤   ¤   ¤
ddaf5a
aeaf5a
d80335 /*____________________________________________________________________________
ffae3b ¤   The real position is *always stored* in this object. ·The position
6c5cb3 ¤   in the underlying implementation should be kept in sync, but not
1992f0 ¤   relied upon.
9267c5 ¤
--eb55 00097c2bf04401000ea Page 5 of pgpIO.c
1b90c0 ¤   Read & Write update the position accordingly.
44f7f7 ____________________________________________________________________________*/
bdc744 ¤   PGPError
5b72bf PGPIOSetPos(
23b7a9 ¤   PGPIORef¤   ¤   ref,
3416ce ¤   PGPFileOffset¤  newPos )
35bb36 {
c73ef5 ¤   PGPValidateIO( ref );
4b943b ¤   PGPValidateParam( newPos >= 0 );
a367c5 ¤
b410b3 ¤   ref->offset¤= newPos;
7167c5 ¤
4d29d7 ¤   return( CallSetPos( ref, ref->vtbl, newPos ) );
5befe6 }
23af5a
d0af5a
b00335 /*____________________________________________________________________________
e2ae3b ¤   The real position is *always stored* in this object. ·The position
4b9ea0 ¤   in the underlying implementation is irrelevant.
ed67c5 ¤
1bc631 ¤   Subclasses may override in unusual circumstances.
df1972 ____________________________________________________________________________*/¤
88c744 ¤   PGPError
7a3f19 PGPIOGetPos(
3ab7a9 ¤   PGPIORef¤   ¤   ref,
5e1e93 ¤   PGPFileOffset *¤curPos )
f6bb36 {
0326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3767c5 ¤
ae74d3 ¤   PGPValidatePtr( curPos );
eaf1e1 ¤   *curPos¤= 0;
e03ef5 ¤   PGPValidateIO( ref );
4c67c5 ¤
697511 ¤   err¤= CallGetPos( ref, ref->vtbl, curPos );
9267c5 ¤
a0deb7 ¤   return( err );
59797c }¤  ¤   ¤   ¤
5094aa ¤   ¤   ¤   ¤   ¤   ¤
10c744 ¤   PGPError
569d4d PGPIOGetEOF(
34b7a9 ¤   PGPIORef¤   ¤   ref,
2e927a ¤   PGPFileOffset *¤eof )
dbbb36 {
8c056e ¤   PGPValidatePtr( eof );
abfc3f ¤   *eof¤   = 0;
dc3ef5 ¤   PGPValidateIO( ref );
d267c5 ¤
285f15 ¤   return( CallGetEOF( ref, ref->vtbl, eof ) );
9aefe6 }
58af5a
1caf5a
ccdc47 #if PGPIO_EOF
12c744 ¤   PGPError
c3d0eb PGPIOSetEOF(
35b7a9 ¤   PGPIORef¤   ¤   ref,
4a6535 ¤   PGPFileOffset ¤ newEOF )
20bb36 {
c89372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
45064f ¤   PGPFileOffset¤  curPos;
4567c5 ¤
ff3ef5 ¤   PGPValidateIO( ref );
f0af5a
6567c5 ¤
ba166c ¤   /* it's illegal to make the eof less than the current pos */
a7f7fc ¤   err¤= PGPIOGetPos( ref, &curPos );
caa2de ¤   if ( IsPGPError( err ))
44e55e ¤   ¤   return( err );
a43a3d ¤   if ( curPos > newEOF )
5d9e46 ¤   ¤   return( kPGPError_IllegalFileOp );
8667c5 ¤
6d5586 ¤   /* not implemented properly pgpStdFileIO yet */
97ef04 ¤   pgpDebugMsg( "not yet implemented fully" );
--efca 000118810fc401000ea Page 6 of pgpIO.c
e3900a ¤   return( kPGPError_IllegalFileOp );
f867c5 ¤
ec5a25 ¤   return( CallSetEOF( ref, ref->vtbl, newEOF ) );
ecefe6 }
977454 #endif
f9af5a
ffaf5a
c6af5a
b4af5a
7ec744 ¤   PGPError
31358f PGPIOFlush( PGPIORef ref )
6cbb36 {
983ef5 ¤   PGPValidateIO( ref );
d367c5 ¤
22da4f ¤   return( CallFlush( ref, ref->vtbl ) );
d4efe6 }
96af5a
acaf5a
4566dd ¤   static PGPError
abbf3c sInitProc(
76dcbc ¤   PGPIORef¤   ref,
dc9b3a ¤   void *¤ ¤   data )
9bbb36 {
7b26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6d67c5 ¤
8eb148 ¤   (void)ref;
18b3c9 ¤   (void)data;
623ef5 ¤   PGPValidateIO( ref );
7167c5 ¤
6ada58 ¤   ref->offset¤¤   = 0;
e267c5 ¤
18deb7 ¤   return( err );
99efe6 }
41af5a
53af5a
4eaf5a
dd66dd ¤   static PGPError
d799fb sDestroyProc( PGPIORef¤ ref )
3bbb36 {
0926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
44af5a
d43ef5 ¤   PGPValidateIO( ref );
6767c5 ¤
af0500 ¤   /* nothing to destroy; caller release ref itself */
fe67c5 ¤
dedeb7 ¤   return( err );
75efe6 }
26af5a
3daf5a
cf16ea ¤   PGPBoolean
b1e0ce PGPIOIsAtEOF( PGPIORef ref )
27bb36 {
c0157c ¤   PGPFileOffset¤  eofPos;
71064f ¤   PGPFileOffset¤  curPos;
6167c5 ¤
7afbb8 ¤   PGPIOGetEOF(ref, &eofPos);
33e6ea ¤   PGPIOGetPos(ref, &curPos);
a267c5 ¤
6a826e ¤   return( curPos >= eofPos );
d2efe6 }
baaf5a
aeaf5a
c4af5a
a066dd ¤   static PGPError
184196 sReadProc(
a9b7a9 ¤   PGPIORef¤   ¤   ref,
f36179 ¤   PGPSize¤¤   ¤   requestCount,
342903 ¤   void *¤ ¤   ¤   buffer,
4e69c6 ¤   PGPSize *¤  ¤   bytesRead )
05bb36 {
c8288a ¤   PGPError¤   err¤= kPGPError_IllegalFileOp;
1167c5 ¤
--4d4a 00005719c82401000ea Page 7 of pgpIO.c
e1b148 ¤   (void)ref;
871420 ¤   (void)requestCount;
e2e788 ¤   (void)buffer;
09e787 ¤   (void)bytesRead;
4b67c5 ¤
b4deb7 ¤   return( err );
0defe6 }
32af5a
9daf5a
6994aa ¤   ¤   ¤   ¤   ¤   ¤
5c66dd ¤   static PGPError
d1acf9 sWriteProc(
6ab7a9 ¤   PGPIORef¤   ¤   ref,
526179 ¤   PGPSize¤¤   ¤   requestCount,
a7b457 ¤   const void *¤   buffer )
1ebb36 {
32288a ¤   PGPError¤   err¤= kPGPError_IllegalFileOp;
8b67c5 ¤
04b148 ¤   (void)ref;
e91420 ¤   (void)requestCount;
37e788 ¤   (void)buffer;
2c67c5 ¤
18deb7 ¤   return( err );
f4efe6 }
9faf5a
bcaf5a
8f94aa ¤   ¤   ¤   ¤   ¤   ¤
b566dd ¤   static PGPError
13fe2a sSetPosProc(
2ab7a9 ¤   PGPIORef¤   ¤   ref,
9c16ce ¤   PGPFileOffset¤  newPos )
79bb36 {
8526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7067c5 ¤
49467c ¤   /* already set by PGPIOSetPos() */
5e4683 ¤   (void)newPos;
c53ef5 ¤   PGPValidateIO( ref );
8a67c5 ¤
77deb7 ¤   return( err );
dcefe6 }
78af5a
6faf5a
ba94aa ¤   ¤   ¤   ¤   ¤   ¤
4a66dd ¤   static PGPError
58ee84 sGetPosProc(
2bb7a9 ¤   PGPIORef¤   ¤   ref,
191e93 ¤   PGPFileOffset *¤curPos )
02bb36 {
1326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
1e67c5 ¤
499493 ¤   *curPos¤= ref->offset;
6a67c5 ¤
43deb7 ¤   return( err );
cfefe6 }
36af5a
dbaf5a
2294aa ¤   ¤   ¤   ¤   ¤   ¤
db66dd ¤   static PGPError
c4f311 sGetEOFProc(
15b7a9 ¤   PGPIORef¤   ¤   ref,
60927a ¤   PGPFileOffset *¤eof )
73bb36 {
aa288a ¤   PGPError¤   err¤= kPGPError_IllegalFileOp;
3467c5 ¤
c8b148 ¤   (void)ref;
56e97a ¤   (void)eof;
4367c5 ¤
51deb7 ¤   return( err );
49efe6 }
0baf5a
54ae30 ¤   ¤   ¤   ¤   ¤
05acd2 #if PGPIO_EOF¤
--b3d6 000268ded76401000ea Page 8 of pgpIO.c
9966dd ¤   static PGPError
4ce3bf sSetEOFProc(
52b7a9 ¤   PGPIORef¤   ¤   ref,
d980fe ¤   PGPFileOffset ¤ eof )
77bb36 {
84288a ¤   PGPError¤   err¤= kPGPError_IllegalFileOp;
bb67c5 ¤
2cb148 ¤   (void)ref;
15e97a ¤   (void)eof;
d367c5 ¤
c3deb7 ¤   return( err );
daefe6 }
5d7454 #endif
57af5a
eb66dd ¤   static PGPError
03f521 sFlushProc( PGPIORef¤   ref)
28bb36 {
0db148 ¤   (void)ref;
3dbbdf ¤   /* default does nothing */
432d68 ¤   return( kPGPError_NoErr );
33efe6 }
6daf5a
cbaf5a
87af5a
9daf5a
3523a1 ¤   PGPIOVtbl const *
369bb4 pgpIOGetClassVTBL( ·)
0cbb36 {
39852f ¤   static const PGPIOVtbl¤ sVTBL =
aac7a1 ¤   {
215b45 ¤   ¤   sInitProc,
325a6c ¤   ¤   sDestroyProc,
82a5ef ¤   ¤   sReadProc,
f6465a ¤   ¤   sWriteProc,
7f7dfe ¤   ¤   sGetPosProc,
466d50 ¤   ¤   sSetPosProc,
66606b ¤   ¤   sGetEOFProc,
abdc47 #if PGPIO_EOF
e870c5 ¤   ¤   sSetEOFProc,
2f7454 #endif
7d72d3 ¤   ¤   sFlushProc
bc62bd ¤   };
a167c5 ¤
6fcba4 ¤   return( &sVTBL );
a7efe6 }
abaf5a
d1af5a
3baf5a
1faf5a
6caf5a
11af5a
d5af5a
b4af5a
6aaf5a
b8af5a
2aaf5a
b6af5a
0caf5a
95af5a
16af5a
70af5a
c4af5a
5baf5a
4caf5a
37af5a
bdaf5a
8daf5a
89af5a
33af5a
27af5a
39af5a
267e4d /*__Editor_settings____
--1dba 00151798a1b401000ea Page 9 of pgpIO.c
e0af5a
e44126 ¤   Local Variables:
d27b17 ¤   tab-width: 4
0e0e6c ¤   End:
385f8c ¤   vi: ts=4 sw=4
0b9e9b ¤   vim: si
51d062 _____________________*/
--7bb2 000bfba5675401000eb Page 1 of pgpIO.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
c47289 ¤   Interface for all PGPIO objects. ·Note that PGPIO doesn't include the
b4e4cd ¤   notion of files, nor are there creation routines. ·Only subclasses
ab81fe ¤   can be instantiated. ·See appropriate subclass header files for creation
724955 ¤   routines. ·See PGPIO.h for more info.
da67c5 ¤
1e7cc3 ¤   Notes:
4e76a2 ¤   ¤   Unlike C++, one needs to cast PGPIO subclass types to PGPIORef to keep
0bf887 ¤   the compiler happy when calling the routines in this file.
2aaf5a
a0225e ¤   $Id: pgpIO.h,v 1.13.16.1 1998/11/12 03:18:19 heller Exp $
11f7f7 ____________________________________________________________________________*/
4474b1 #ifndef Included_pgpIO_h¤   /* [ */
fb1c05 #define Included_pgpIO_h
dcaf5a
00e610 #include "pgpPFLConfig.h"
2e6773 #include "pgpMemoryMgr.h"
0eaf5a
2caf5a
6799c6 PGP_BEGIN_C_DECLARATIONS
6dcbcf #if PRAGMA_IMPORT_SUPPORTED
e5b981 #pragma import on
297454 #endif
83af5a
fa2272 typedef struct PGPIO¤   PGPIO;
47280e typedef struct PGPIO *¤ PGPIORef;
5baf5a
ba2a4e #define¤kInvalidPGPIORef¤   ¤   ¤   ((PGPIORef) NULL)
3f8c80 #define PGPIORefIsValid( ref )¤ ¤   ( (ref) != kInvalidPGPIORef )
f3af5a
3f3698 /* frees any and all subclasses of PGPIO */
3b0146 PGPError¤   PGPFreeIO( PGPIORef ref );
9eaf5a
7baf5a
b7131e /* after reading, file position advances by number of bytes read */
8c24c2 PGPError¤   PGPIORead( PGPIORef ref, PGPSize requestCount,
2edae0 ¤   ¤   ¤   ¤   ¤   ¤   void *buffer, PGPSize *bytesRead );
ff94aa ¤   ¤   ¤   ¤   ¤   ¤
ce6623 /* after writing, file position advances by number of bytes read */
1e5482 PGPError¤   PGPIOWrite( PGPIORef ref, PGPSize requestCount,
4a28e1 ¤   ¤   ¤   ¤   ¤   ¤   const void *buffer );
0994aa ¤   ¤   ¤   ¤   ¤   ¤
ce7dac /* set file position to this position */
0a77d7 PGPError¤   PGPIOSetPos( PGPIORef ref, PGPFileOffset newPos );
df94aa ¤   ¤   ¤   ¤   ¤   ¤
1a457b /* get current file position */
879394 PGPError¤   PGPIOGetPos( PGPIORef ref, PGPFileOffset *curPos );
9e94aa ¤   ¤   ¤   ¤   ¤   ¤
07242d /* get the logical end of file (the file size) */
d150ec PGPError¤   PGPIOGetEOF( PGPIORef ref, PGPFileOffset *eof );
8caf5a
5ddc47 #if PGPIO_EOF
005521 /* set the logical end of file (the file size) */
e9da3e /* excess data is removed or the file is grown if needed */
ef7519 /* it is illegal to set the EOF less than the current file pos */
97e3df PGPError¤   PGPIOSetEOF( PGPIORef ref, PGPFileOffset eof );
307454 #endif
9caf5a
a9280c /* flush to backing store */
b8b0e7 PGPError¤   PGPIOFlush( PGPIORef ref );
04af5a
3caf5a
5f2c4c /* returns TRUE if currently at EOF */
a76cfb PGPBoolean¤ PGPIOIsAtEOF( PGPIORef ref );
0caf5a
dbf053 PGPMemoryMgrRef¤PGPIOGetMemoryMgr( PGPIORef ref );
f9af5a
bfa309 PGPBoolean¤ PGPIOIsValid( PGPIORef ref );
--388b 001a5ea0ffc401000eb Page 2 of pgpIO.h
ada0ff #define PGPValidateIO( ref )¤   PGPValidateParam( PGPIOIsValid( ref ) )
56af5a
e6af5a
02cbcf #if PRAGMA_IMPORT_SUPPORTED
d3b981 #pragma import on
057454 #endif
ae1254 PGP_END_C_DECLARATIONS
30af5a
eabd7d #endif /* ] Included_pgpIO_h¤   */
96af5a
16af5a
b87e4d /*__Editor_settings____
62af5a
3f4126 ¤   Local Variables:
f77b17 ¤   tab-width: 4
360e6c ¤   End:
9d5f8c ¤   vi: ts=4 sw=4
989e9b ¤   vim: si
a5d062 _____________________*/
--f81b 0004e8a94df401000ec Page 1 of pgpIOPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
e43be8 ¤   Private declarations for PGPIO. ·CLIENTS SHOULD NOT INCLUDE THIS FILE.
5667c5 ¤
e8af5a
7be264 ¤   $Id: pgpIOPriv.h,v 1.6.16.1 1998/11/12 03:18:20 heller Exp $
b5f7f7 ____________________________________________________________________________*/
02e610 #include "pgpPFLConfig.h"
82af5a
d7a9cb #include "pgpIO.h"
ae894b #include "pgpFileSpec.h"
c8af5a
ecaf5a
1e99c6 PGP_BEGIN_C_DECLARATIONS
10af5a
c77d34 typedef PGPError¤   (*PGPIOInitProc)( PGPIORef ref, void *data);
ba7fa9 typedef PGPError¤   (*PGPIODestroyProc)( PGPIORef ref );
e1af5a
d23597 typedef PGPError¤   (*PGPIOReadProc)( PGPIORef ref, PGPSize requestCount,
0edae0 ¤   ¤   ¤   ¤   ¤   ¤   void *buffer, PGPSize *bytesRead );
af94aa ¤   ¤   ¤   ¤   ¤   ¤
a0fd9f typedef PGPError¤   (*PGPIOWriteProc)( PGPIORef ref, PGPSize requestCount,
6428e1 ¤   ¤   ¤   ¤   ¤   ¤   const void *buffer );
1e94aa ¤   ¤   ¤   ¤   ¤   ¤
b2df4c typedef PGPError¤   (*PGPIOSetPosProc)( PGPIORef ref, PGPFileOffset newPos );
c794aa ¤   ¤   ¤   ¤   ¤   ¤
a0f9a4 typedef PGPError¤   (*PGPIOGetPosProc)( PGPIORef ref, PGPFileOffset *curPos );
2d94aa ¤   ¤   ¤   ¤   ¤   ¤
819e72 typedef PGPError¤   (*PGPIOGetEOFProc)( PGPIORef ref, PGPFileOffset *eof );
30af5a
3fdc47 #if PGPIO_EOF
7180ad typedef PGPError¤   (*PGPIOSetEOFProc)( PGPIORef ref, PGPFileOffset eof );
637454 #endif
6baf5a
74cc5d typedef PGPError¤   (*PGPIOFlushProc)( PGPIORef ref );
5baf5a
d8af5a
1c73bc /* the virtual function table for a PGPIO */
132067 typedef struct PGPIOVtbl
07bb36 {
9752f6 ¤   PGPIOInitProc¤  ¤   initProc;
a4dd28 ¤   PGPIODestroyProc¤   destroyProc;
ab67c5 ¤
834801 ¤   PGPIOReadProc¤  ¤   readProc;
c36473 ¤   PGPIOWriteProc¤ ¤   writeProc;
d2f105 ¤   PGPIOGetPosProc¤¤   getPosProc;
8dac4f ¤   PGPIOSetPosProc¤¤   setPosProc;
37a575 ¤   PGPIOGetEOFProc¤¤   getEOFProc;
46dc47 #if PGPIO_EOF
38f83f ¤   PGPIOSetEOFProc¤¤   setEOFProc;
dc7454 #endif
13f3f6 ¤   PGPIOFlushProc¤ ¤   flushProc;
ca238d } PGPIOVtbl;
26af5a
dfaf5a
8a10c8 PGPIOVtbl const *¤  pgpIOGetClassVTBL( void );
72af5a
21af5a
a34980 PGPError¤   pgpioInheritInit( PGPIORef ref, PGPIOVtbl const * vtbl,
d97d82 ¤   ¤   ¤   ¤   void *data );
99e4b1 PGPError¤   pgpioInheritDestroy( PGPIORef ref, PGPIOVtbl const * vtbl );
34af5a
4ce95f PGPError¤   pgpioInheritRead( PGPIORef ref, PGPIOVtbl const * vtbl,
4cc711 ¤   ¤   ¤   ¤   PGPSize requestCount, void *buffer, PGPSize *bytesRead );
6e94aa ¤   ¤   ¤   ¤   ¤   ¤
0eed3b PGPError¤   pgpioInheritWrite( PGPIORef ref, PGPIOVtbl const * vtbl,
df3d28 ¤   ¤   ¤   ¤   PGPSize requestCount, const void *buffer );
fb94aa ¤   ¤   ¤   ¤   ¤   ¤
ba68c0 PGPError¤   pgpioInheritSetPos( PGPIORef ref, PGPIOVtbl const * vtbl,
4eed6e ¤   ¤   ¤   ¤   PGPFileOffset newPos );
--3d53 001d4f8a408401000ec Page 2 of pgpIOPriv.h
e694aa ¤   ¤   ¤   ¤   ¤   ¤
bd0026 PGPError¤   pgpioInheritGetEOF( PGPIORef ref, PGPIOVtbl const * vtbl,
5202e3 ¤   ¤   ¤   ¤   PGPFileOffset *eof );
302b85 ¤   ¤   ¤   ¤
27dc47 #if PGPIO_EOF
049b74 PGPError¤   pgpioInheritSetEOF( PGPIORef ref, PGPIOVtbl const * vtbl,
d012a8 ¤   ¤   ¤   ¤   PGPFileOffset eof );
437454 #endif
6a94aa ¤   ¤   ¤   ¤   ¤   ¤
ff6ef8 PGPError¤   pgpioInheritFlush( PGPIORef ref, PGPIOVtbl const * vtbl );
20af5a
1baf5a
5f060b struct PGPIO
97bb36 {
b2acb2 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   magic;
0fb6e8 ¤   PGPIOVtbl const * const¤¤   vtbl;
3f4d76 ¤   PGPMemoryMgrRef¤¤   ¤   ¤   context;
6e5905 ¤   PGPFileOffset¤  ¤   ¤   ¤   offset;
dd2fa1 } ;
7449b3 #define kPGPIOMagic¤¤   0x5047494f¤ /* 'PGIO' */
cfaf5a
f485a5 #define¤¤   pgpioGetObjectVTBL( ref ) \
6bb6d9 ¤   ¤   ¤   ¤   ( (PGPIORef)(ref))->vtbl
2eaf5a
b43ffc PGPError¤   pgpNewIOFromVTBL( PGPMemoryMgrRef context,·
513589 ¤   ¤   ¤   ¤   PGPIOVtbl const * vtbl, PGPSize size, void *data,
dcdc9f ¤   ¤   ¤   ¤   PGPIORef * outRef );
9aaf5a
a11254 PGP_END_C_DECLARATIONS
1caf5a
4aaf5a
65af5a
d1af5a
d7af5a
29af5a
17af5a
62af5a
3daf5a
8caf5a
3faf5a
6aaf5a
1daf5a
ceaf5a
e0af5a
45af5a
40af5a
acaf5a
b7af5a
85af5a
beaf5a
b1af5a
217e4d /*__Editor_settings____
07af5a
614126 ¤   Local Variables:
d07b17 ¤   tab-width: 4
a20e6c ¤   End:
565f8c ¤   vi: ts=4 sw=4
269e9b ¤   vim: si
d4d062 _____________________*/
--4027 000dcd90383401000ed Page 1 of pgpIOSample.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
87d0ba ¤   Sample code for using PGPIO.
ff67c5 ¤
b2ef54 ¤   $Id: pgpIOSample.c,v 1.2.16.1 1998/11/12 03:18:21 heller Exp $
f5f7f7 ____________________________________________________________________________*/
f3e610 #include "pgpPFLConfig.h"
fbaf5a
ce324c #include <string.h>
57af5a
e93427 #include "pgpFileUtilities.h"
b82b62 #include "pgpPFLErrors.h"
04fbe2 #include "pgpMemoryIO.h"
35ebac #include "pgpIOUtilities.h"
34af5a
69ae30 ¤   ¤   ¤   ¤   ¤
950335 /*____________________________________________________________________________
6dce8c ¤   Create a PGPMemoryIO from specified data and position at beginning of IO.
c9f7f7 ____________________________________________________________________________*/
3766dd ¤   static PGPError
d35b63 sCreateIOFromData(
42231a ¤   PGPMemoryMgrRef ¤   memoryMgr,
01225b ¤   const PGPByte *¤¤   data,
9bb0bc ¤   PGPSize¤¤   ¤   ¤   numBytes,
d45e9f ¤   PGPIORef *¤ outRef )
13bb36 {
9665d7 ¤   PGPIORef¤   ¤   ioRef¤  = NULL;
7b7637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
65af5a
11fc67 ¤   err¤= PGPNewMemoryIO( memoryMgr, (PGPMemoryIORef *)&ioRef );
18f1e7 ¤   if ( IsntPGPError( err ) )
34c7a1 ¤   {
73cc82 ¤   ¤   /* write our string into our memory I/O */
171af5 ¤   ¤   err¤= PGPIOWrite( ioRef, numBytes, data );
457d98 ¤   ¤   if ( IsntPGPError( err ) )
f95b34 ¤   ¤   {
1e9251 ¤   ¤   ¤   /* reposition at beginning */
c284a7 ¤   ¤   ¤   err¤= PGPIOSetPos( ioRef, 0 );
200fe4 ¤   ¤   }
a81b52 ¤   ¤
530d8e ¤   ¤   /* clean up if we got an error */
1dbe18 ¤   ¤   if ( IsPGPError( err ) )
815b34 ¤   ¤   {
f0863e ¤   ¤   ¤   PGPFreeIO( ioRef );
7c4faf ¤   ¤   ¤   ioRef¤  = NULL;
930fe4 ¤   ¤   }
f39371 ¤   }
a067c5 ¤
68e490 ¤   *outRef¤= ioRef;
c9deb7 ¤   return( err );
d8efe6 }
b7af5a
18af5a
de0335 /*____________________________________________________________________________
71c8c4 ¤   Create and open a test IO which uses the specified file.
51f7f7 ____________________________________________________________________________*/
ea66dd ¤   static PGPError
63d0eb sOpenTestFile(
4a231a ¤   PGPMemoryMgrRef ¤   memoryMgr,
debe9e ¤   PGPIORef *¤ ¤   ¤   outRef )
dcbb36 {
ac9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
ea5567 ¤   PFLFileSpecRef¤ fileSpec¤   = NULL;
6e4a2c ¤   PGPIORef¤   ¤   ioRef¤  ¤   = NULL;
ee67c5 ¤
4c0ccc #if PGP_MACINTOSH
39ec33 ¤   FSSpec¤ fsSpec;
5d67c5 ¤
bfbf27 ¤   (void)FSMakeFSSpec( -1, fsRtDirID, "\pPGPIOTestFile", &fsSpec );
dc71a9 ¤   err¤= PFLNewFileSpecFromFSSpec( memoryMgr, &fsSpec, &fileSpec );
--86ae 000e8cac4ae401000ed Page 2 of pgpIOSample.c
0fdb21 #else
a01c36 ¤   /* create a file spec from a path string */
b09b67 ¤   const char¤ kPath[]¤= "C:\\PGPIOTestFile.bin";
63b242 ¤   err¤= PFLNewFileSpecFromFullPath( memoryMgr, kPath, &fileSpec );
da7454 #endif
6aaf5a
f7f1e7 ¤   if ( IsntPGPError( err ) )
0bc7a1 ¤   {
655aed ¤   ¤   /* delete it in case it's already there */
2d1bd4 ¤   ¤   (void)PFLFileSpecDelete( fileSpec );
fb1b52 ¤   ¤
b9f467 ¤   ¤   /* create a new file */
7570ce ¤   ¤   err¤= PFLFileSpecCreate( fileSpec );
1f7d98 ¤   ¤   if ( IsntPGPError( err ) )
235b34 ¤   ¤   {
03a7d2 ¤   ¤   ¤   err¤= PGPOpenFileSpec( fileSpec,
ec5266 ¤   ¤   ¤   ¤   ¤   kPFLFileOpenFlags_ReadWrite, (PGPFileIORef *)&ioRef );
7c0fe4 ¤   ¤   }
511b52 ¤   ¤
c408ba ¤   ¤   PFLFreeFileSpec( fileSpec );
719371 ¤   }
8d67c5 ¤
ade490 ¤   *outRef¤= ioRef;
9edeb7 ¤   return( err );
d9efe6 }
58af5a
5caf5a
830335 /*____________________________________________________________________________
76ceb7 ¤   Write a string into a PGPMemoryIO, then copy that into a file.
56f7f7 ____________________________________________________________________________*/
ef66dd ¤   static PGPError
e77cf6 SampleCode( PGPMemoryMgrRef ¤   memoryMgr )
bcbb36 {
da2494 ¤   const char¤ ¤   kTestString[]¤  = "hello world";
376d3d ¤   const char¤ ¤   kPath[]¤¤   ¤   = "C:\\pgpIOTest.bin";
c567c5 ¤
d19372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
bf2dfd ¤   PGPIORef¤   ¤   inRef¤  = NULL;
a3071f ¤   PGPIORef¤   ¤   outRef¤ = NULL;
3867c5 ¤
bd30ca ¤   /* create a memory IO which has some stuff in it */
783635 ¤   err¤= sCreateIOFromData( memoryMgr,
76b4d7 ¤   ¤   ¤   (PGPByte const *)kTestString, strlen( kTestString ), &inRef );
99f1e7 ¤   if ( IsntPGPError( err ) )
6cc7a1 ¤   {
15f2a9 ¤   ¤   /* open a test file to write into */
1ef847 ¤   ¤   err¤= sOpenTestFile( memoryMgr, &outRef );
bc9371 ¤   }
e767c5 ¤
d7f1e7 ¤   if ( IsntPGPError( err ) )
2fc7a1 ¤   {
1b97a4 ¤   ¤   PGPFileOffset¤  length;
3a1b52 ¤   ¤
24c289 ¤   ¤   /* see how big input is */
1f120a ¤   ¤   err¤= PGPIOGetEOF( inRef, &length );
8b7d98 ¤   ¤   if ( IsntPGPError( err ) )
655b34 ¤   ¤   {
79c18d ¤   ¤   ¤   /* copy entire input to output */
04859c ¤   ¤   ¤   err¤= PGPCopyIO( inRef, length, outRef );
3c0fe4 ¤   ¤   }
259371 ¤   }
bf67c5 ¤
44f38a ¤   if ( outRef != NULL )
2315e1 ¤   ¤   PGPFreeIO( outRef );
7a6f3b ¤   if ( inRef != NULL )
18aadf ¤   ¤   PGPFreeIO( inRef );
cc67c5 ¤
53deb7 ¤   return( err );
9befe6 }
b5af5a
3faf5a
e87e4d /*__Editor_settings____
--cb7c 00151798a1b401000ed Page 3 of pgpIOSample.c
e0af5a
e44126 ¤   Local Variables:
d27b17 ¤   tab-width: 4
0e0e6c ¤   End:
385f8c ¤   vi: ts=4 sw=4
0b9e9b ¤   vim: si
51d062 _____________________*/
--2da5 000dc994e51401000ee Page 1 of pgpIOUtilities.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
30609a ¤   Sample code for using PGPIO
b067c5 ¤
64efca ¤   $Id: pgpIOUtilities.c,v 1.3.16.1 1998/11/12 03:18:21 heller Exp $
e9f7f7 ____________________________________________________________________________*/
e8e610 #include "pgpPFLConfig.h"
87af5a
0a2b62 #include "pgpPFLErrors.h"
9c0d08 #include "pgpMem.h"
44ebac #include "pgpIOUtilities.h"
ecaf5a
c2af5a
bf0335 /*____________________________________________________________________________
ffc7fb ¤   Copy bytes from one I/O to another using supplied buffer.·
acf7f7 ____________________________________________________________________________*/
3bc744 ¤   PGPError
d12981 PGPCopyIOUsingBuffer(
88531a ¤   PGPIORef¤   fromIO,
fed1ca ¤   PGPSize¤¤   numBytes,
022453 ¤   PGPIORef¤   toIO,
fe296a ¤   void *¤ ¤   buffer,
512071 ¤   PGPSize¤¤   bufferSize )
93bb36 {
71dad6 ¤   PGPSize¤¤   remaining;
9526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
bc67c5 ¤
a48edb ¤   remaining¤  = numBytes;
600589 ¤   while ( remaining != 0 )
d22ef1 ¤   {¤
2953d9 ¤   ¤   PGPSize¤count;
8f1b52 ¤   ¤
11226d ¤   ¤   count¤  = pgpMin( remaining, bufferSize );
fe51f1 ¤   ¤   err¤= PGPIORead( fromIO, count, buffer, NULL);
fbbe18 ¤   ¤   if ( IsPGPError( err ) )
16cdcb ¤   ¤   ¤   break;
1b1b52 ¤   ¤
deed18 ¤   ¤   err¤= PGPIOWrite( toIO, count, buffer );
15be18 ¤   ¤   if ( IsPGPError( err ) )
fbcdcb ¤   ¤   ¤   break;
b81b52 ¤   ¤
19de0e ¤   ¤   remaining¤  -= count;
3e9371 ¤   }
9a67c5 ¤
b1deb7 ¤   return( err );
46efe6 }
faaf5a
590335 /*____________________________________________________________________________
0bffd7 ¤   Copy bytes from one I/O to another.·
725f70 ¤   Caller will want to call PGPIOSetPos to set file mark first.
25f7f7 ____________________________________________________________________________*/
e9c744 ¤   PGPError
9d0233 PGPCopyIO(
b4531a ¤   PGPIORef¤   fromIO,
aad1ca ¤   PGPSize¤¤   numBytes,
a86398 ¤   PGPIORef¤   toIO )
bdbb36 {
a4f329 ¤   void *¤ ¤   ¤   buffer¤ = NULL;
9740a1 ¤   PGPSize¤¤   ¤   bufferSize;
a39372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
d467c5 ¤
a6a330 ¤   /* a reasonable cross-platform size */
6862ab ¤   #define kBufferSize¤¤   ( 32UL * 1024UL )
7067c5 ¤
cf9ded ¤   bufferSize¤ = pgpMin( numBytes, kBufferSize );
615637 ¤   buffer¤ ¤   = PGPNewData( PGPIOGetMemoryMgr( fromIO ), bufferSize, 0);
494794 ¤   if ( IsntNull( buffer ) )
48c7a1 ¤   {
f154ce ¤   ¤   err¤= PGPCopyIOUsingBuffer( fromIO, numBytes, toIO,
dcfaee ¤   ¤   ¤   ¤   buffer, bufferSize );
--cd72 001423b8db7401000ee Page 2 of pgpIOUtilities.c
e587c7 ¤   ¤   ¤
18f097 ¤   ¤   PGPFreeData( buffer );
c19371 ¤   }
f00e24 ¤   else
bac7a1 ¤   {
d217a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
349371 ¤   }
7fdeb7 ¤   return( err );
78efe6 }
63af5a
25af5a
847e4d /*__Editor_settings____
8baf5a
054126 ¤   Local Variables:
2c7b17 ¤   tab-width: 4
e90e6c ¤   End:
405f8c ¤   vi: ts=4 sw=4
799e9b ¤   vim: si
42d062 _____________________*/
--e179 0016a74a2ed401000ef Page 1 of pgpIOUtilities.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
9b7d6e ¤   $Id: pgpIOUtilities.h,v 1.3.28.1 1998/11/12 03:18:22 heller Exp $
1ef7f7 ____________________________________________________________________________*/
c5e9ab #ifndef Included_pgpIOUtilities_h¤  /* [ */
23c743 #define Included_pgpIOUtilities_h
dbaf5a
9ca9cb #include "pgpIO.h"
77af5a
8199c6 PGP_BEGIN_C_DECLARATIONS
eccbcf #if PRAGMA_IMPORT_SUPPORTED
45b981 #pragma import on
387454 #endif
44af5a
a2af5a
b70335 /*____________________________________________________________________________
67ffd7 ¤   Copy bytes from one I/O to another.·
105f70 ¤   Caller will want to call PGPIOSetPos to set file mark first.
fcf7f7 ____________________________________________________________________________*/
239a5a PGPError¤   PGPCopyIO( PGPIORef fromIO, PGPSize numBytes, PGPIORef toIO );
c3af5a
a5b3cf /* same as PGPCopyIO(), but use user-supplied buffer */
ed818c PGPError¤   PGPCopyIOUsingBuffer( PGPIORef fromIO,
4e34f7 ¤   ¤   ¤   ¤   PGPSize numBytes, PGPIORef toIO,
9bb046 ¤   ¤   ¤   ¤   void *buffer, PGPSize bufferSize );
7e2b85 ¤   ¤   ¤   ¤
f0af5a
f3af5a
e8cbcf #if PRAGMA_IMPORT_SUPPORTED
312ced #pragma import reset
c97454 #endif
461254 PGP_END_C_DECLARATIONS
64af5a
f9580d #endif /* ] Included_pgpIOUtilities_h */
a6af5a
b5af5a
917e4d /*__Editor_settings____
aeaf5a
ed4126 ¤   Local Variables:
807b17 ¤   tab-width: 4
b50e6c ¤   End:
b35f8c ¤   vi: ts=4 sw=4
7e9e9b ¤   vim: si
6ad062 _____________________*/
--f3b4 0004d451a17401000f0 Page 1 of pgpLineEndIO.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
9eb336 ¤   Abstract base class for all PGPLineEndIO objects.
f1af5a
4cd78a ¤   $Id: pgpLineEndIO.c,v 1.2.32.1 1998/11/12 03:18:23 heller Exp $
d4f7f7 ____________________________________________________________________________*/
c8e610 #include "pgpPFLConfig.h"
55af5a
972b62 #include "pgpPFLErrors.h"
20af5a
6ae3c9 #include "pgpLineEndIOPriv.h"
2d0d08 #include "pgpMem.h"
95af5a
73af5a
8872b0 #define GetParentVTBL()¤¤   pgpProxyIOGetClassVTBL()
a4af5a
1bc258 #define GetSelfVTBL( ref ) \
779cd4 ¤   (PGPIOVtbl const *)pgpLineEndIOGetObjectVTBL( ref )
70af5a
0e0038 static PGPError¤¤   sLineEndIOFlushProc( PGPIORef ref );
beaf5a
dc16ea ¤   PGPBoolean
82b999 PGPLineEndIOIsValid( PGPLineEndIORef ref )
d4bb36 {
1e08f8 ¤   if ( ! PGPIOIsValid( (PGPIORef)ref ) )
abe20d ¤   ¤   return( FALSE );
c067c5 ¤
3932f4 ¤   return( ref->lineEndConvertMagic == kPGPLineEndIOMagic );
6fefe6 }
5caf5a
e6af5a
dcaf5a
06af5a
a5af5a
3f66dd ¤   static PGPError
2b1d7e sLineEndIOInitProc(
57f273 ¤   PGPIORef¤   inRef,
f39b3a ¤   void *¤ ¤   data )
e2bb36 {
b937df ¤   PGPError¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
f821d1 ¤   PGPLineEndIORef¤¤   self¤   = (PGPLineEndIORef)inRef;
aca2a5 ¤   PGPLineEndIOData *¤ myData¤ = (PGPLineEndIOData *)data;
ab67c5 ¤
853d77 ¤   PGPValidateIO( inRef );
a667c5 ¤
0272f8 ¤   err¤= pgpioInheritInit( inRef,
f649fb ¤   ¤   ¤   (PGPIOVtbl const *)GetParentVTBL(), data );
0567c5 ¤
d5df5a ¤   self->lineEndConvertMagic¤  = kPGPLineEndIOMagic;
a92379 ¤   self->toType¤   ¤   = myData->toType;
efb5a6 ¤   self->lastCharWasCR¤= FALSE;
0467c5 ¤
9716d1 ¤   self->buffer¤   ¤   = self->bufferSpace;
b469f8 ¤   self->bufferSize¤   = sizeof( self->bufferSpace );
d7358b ¤   self->bytesInBuffer¤= 0;
ee67c5 ¤
c7deb7 ¤   return( err );
feefe6 }
4daf5a
8baf5a
d1af5a
d666dd ¤   static PGPError
43db1a sLineEndIODestroyProc( PGPIORef¤inRef )
e8bb36 {
897637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
59f947 ¤   PGPError¤   ¤   err2¤   = kPGPError_NoErr;
87f574 ¤   PGPLineEndIORef¤self¤   = (PGPLineEndIORef)inRef;
7daf5a
19adee ¤   PGPValidateLineEndIO( self );
4d67c5 ¤
--40ca 0006b4a5be9401000f0 Page 2 of pgpLineEndIO.c
65167b ¤   /* don't use virtual method */
0bf88b ¤   err¤= sLineEndIOFlushProc( inRef );
d967c5 ¤
78183f ¤   self->lineEndConvertMagic¤  = ~self->lineEndConvertMagic;
4767c5 ¤
7f11cd ¤   err2¤   = pgpioInheritDestroy( inRef,
11578b ¤   ¤   ¤   (PGPIOVtbl const *)GetParentVTBL() );
58f1e7 ¤   if ( IsntPGPError( err ) )
13f6ef ¤   ¤   err¤= err2;
e11b52 ¤   ¤
5667c5 ¤
b8deb7 ¤   return( err );
34efe6 }
f2af5a
9faf5a
9b66dd ¤   static PGPError
31e3d4 sLineEndIOReadProc(
10b7a9 ¤   PGPIORef¤   ¤   ref,
bb6179 ¤   PGPSize¤¤   ¤   requestCount,
242903 ¤   void *¤ ¤   ¤   buffer,
730988 ¤   PGPSize *¤  ¤   actualCount )
24bb36 {
b2b148 ¤   (void)ref;
cb1420 ¤   (void)requestCount;
6fe788 ¤   (void)buffer;
5967c5 ¤
79c028 ¤   pgpClearMemory( buffer, requestCount );
79097d ¤   *actualCount¤   = 0;
5567c5 ¤
b2adc8 ¤   /* we don't support reading yet (not implemented) */
ca900a ¤   return( kPGPError_IllegalFileOp );
78efe6 }
08af5a
8eaf5a
ff66dd ¤   static PGPError
8bd02c AddToBuffer(
a5c64c ¤   PGPLineEndIORef¤¤   self,
f4e697 ¤   char¤   ¤   ¤   ¤   theChar )
3cbb36 {
0e61e0 ¤   PGPError¤   err;
b367c5 ¤
ef368b ¤   self->buffer[ self->bytesInBuffer ]¤= theChar;
f8186b ¤   self->bytesInBuffer¤+= 1;
150537 ¤   if ( self->bytesInBuffer == self->bufferSize )
b3c7a1 ¤   {
756c67 ¤   ¤   err¤= PGPIOWrite( self->parent.baseIO, self->bufferSize, self->buffer );
108edd ¤   ¤   self->bytesInBuffer¤= 0;
2f9371 ¤   }
1e0e24 ¤   else
62c7a1 ¤   {
bad87c ¤   ¤   err¤= kPGPError_NoErr;
349371 ¤   }
1867c5 ¤
ffdeb7 ¤   return( err );
08efe6 }
8aaf5a
e667c5 ¤
73c1e9 #define IsLineEndChar( c )¤ ((c) == '\r' || (c) == '\n' )
b866dd ¤   static PGPError
0acd4d sLineEndIOWriteProc(
7fb7a9 ¤   PGPIORef¤   ¤   ref,
bc6179 ¤   PGPSize¤¤   ¤   requestCount,
feb457 ¤   const void *¤   buffer )
ffbb36 {
77cc06 ¤   PGPSize¤¤   ¤   ¤   remaining;
0bb745 ¤   const char *¤   ¤   cur;
59b945 ¤   PGPLineEndIORef¤¤   self¤   = (PGPLineEndIORef)ref;
3ad591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
d07069 ¤   PGPInt32¤   ¤   ¤   delta¤  = 0;
c067c5 ¤
2ecac2 ¤   if ( requestCount == 0 )
6ba117 ¤   ¤   return( kPGPError_NoErr );
--20b8 00033a1ab7c401000f0 Page 3 of pgpLineEndIO.c
2a67c5 ¤
227529 ¤   remaining¤  = requestCount;
94c721 ¤   cur¤¤   ¤   = (const char *)buffer;
3b67c5 ¤
c0c0fd ¤   if ( self->lastCharWasCR &&
1d015d ¤   ¤   *(char const *)buffer == '\n' )
14c7a1 ¤   {
cf78a6 ¤   ¤   /* eat line feed; it followed CR */
545f1b ¤   ¤   ++cur;
feecd9 ¤   ¤   --remaining;
3a4740 ¤   ¤   --delta;
f69371 ¤   }
91af5a
c90589 ¤   while ( remaining != 0 )
dfc7a1 ¤   {
7a6a83 ¤   ¤   char¤   curChar;
461b52 ¤   ¤
a1af9f ¤   ¤   curChar¤= *cur++;
f3ecd9 ¤   ¤   --remaining;
f41b52 ¤   ¤
1295fb ¤   ¤   if ( IsLineEndChar( curChar ) )
4d5b34 ¤   ¤   {
4dfbb1 ¤   ¤   ¤   /* eat newline if it follows carriage return */
e98b98 ¤   ¤   ¤   if ( remaining != 0 ·&&
822553 ¤   ¤   ¤   ¤   curChar == '\r' &&
327d54 ¤   ¤   ¤   ¤   *cur == '\n' )
fcf776 ¤   ¤   ¤   {
608651 ¤   ¤   ¤   ¤   ++cur;
ff6955 ¤   ¤   ¤   ¤   --remaining;
4fb71a ¤   ¤   ¤   ¤   --delta;
4fa3a6 ¤   ¤   ¤   }
a187c7 ¤   ¤   ¤
a34170 ¤   ¤   ¤   /* output correct line end */
c3dd7b ¤   ¤   ¤   if ( self->toType == kCRLFLineEndType )
eef776 ¤   ¤   ¤   {
e46497 ¤   ¤   ¤   ¤   err¤= AddToBuffer( self, '\r' );
4d3227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
3a44c8 ¤   ¤   ¤   ¤   ¤   err¤= AddToBuffer( self, '\n' );
a60eb4 ¤   ¤   ¤   ¤   ++delta;
7fa3a6 ¤   ¤   ¤   }
3a201b ¤   ¤   ¤   else if ( self->toType == kCRLineEndType)
0ff776 ¤   ¤   ¤   {
986497 ¤   ¤   ¤   ¤   err¤= AddToBuffer( self, '\r' );
9aa3a6 ¤   ¤   ¤   }
13bb8c ¤   ¤   ¤   else
42f776 ¤   ¤   ¤   {
a217d3 ¤   ¤   ¤   ¤   err¤= AddToBuffer( self, '\n' );
19a3a6 ¤   ¤   ¤   }
ed0fe4 ¤   ¤   }
480e1d ¤   ¤   else
075b34 ¤   ¤   {
90b591 ¤   ¤   ¤   err¤= AddToBuffer( self, curChar );
e00fe4 ¤   ¤   }
7c9371 ¤   }
0067c5 ¤
8b410d ¤   /* must remember this for next write which starts with '\n' */
c8c31e ¤   self->lastCharWasCR¤=
8f72b1 ¤   ¤   ((const char *)buffer)[ requestCount - 1 ] == '\r';
9367c5 ¤
00bc31 ¤   /* PGPIOWrite function will add the request count in;
d31423 ¤   ¤   we add in the delta bytes to account for more, fewer we output */
34f1e7 ¤   if ( IsntPGPError( err ) )
604196 ¤   ¤   ref->offset¤+= delta;
111b52 ¤   ¤
acdeb7 ¤   return( err );
33efe6 }
04af5a
322b85 ¤   ¤   ¤   ¤
fa66dd ¤   static PGPError
d7bc04 sLineEndIOFlushProc( PGPIORef¤  ¤   ref)
44bb36 {
337637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
--a952 00091d4d333401000f0 Page 4 of pgpLineEndIO.c
3580ec ¤   PGPLineEndIORef¤self¤   = (PGPLineEndIORef)ref;
7167c5 ¤
2024b6 ¤   if ( self->bytesInBuffer != 0 )
ffc7a1 ¤   {
0886bc ¤   ¤   err¤= PGPIOWrite( self->parent.baseIO,
4ce6c9 ¤   ¤   ¤   ¤   self->bytesInBuffer, self->buffer );
678edd ¤   ¤   self->bytesInBuffer¤= 0;
3d9371 ¤   }
ecf1e7 ¤   if ( IsntPGPError( err ) )
26c7a1 ¤   {
023b63 ¤   ¤   err¤= PGPIOFlush( self->parent.baseIO );
de9371 ¤   }
f467c5 ¤
0adeb7 ¤   return( err );
fdefe6 }
91af5a
3aaf5a
9d0335 /*____________________________________________________________________________
b2d206 ¤   We need to override this because we may output a different number of bytes
2e1185 ¤   than we read.
29f7f7 ____________________________________________________________________________*/
e366dd ¤   static PGPError
4c1d4a sLineEndIOGetPosProc(
c4b7a9 ¤   PGPIORef¤   ¤   ref,
17a675 ¤   PGPFileOffset *¤curPos)
8cbb36 {
2ab945 ¤   PGPLineEndIORef¤¤   self¤   = (PGPLineEndIORef)ref;
d667c5 ¤
3145f2 ¤   return( PGPIOGetPos( self->parent.baseIO, curPos ) );
c9efe6 }
5daf5a
a1af5a
2066dd ¤   static PGPError
9a0de4 sLineEndIOSetPosProc(
e6b7a9 ¤   PGPIORef¤   ¤   ref,
6416ce ¤   PGPFileOffset¤  newPos )
6fbb36 {
d9b945 ¤   PGPLineEndIORef¤¤   self¤   = (PGPLineEndIORef)ref;
29d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
0367c5 ¤
663ef5 ¤   PGPValidateIO( ref );
ea943b ¤   PGPValidateParam( newPos >= 0 );
0967c5 ¤
fbb5a6 ¤   self->lastCharWasCR¤= FALSE;
4267c5 ¤
4ff514 ¤   err¤= PGPIOSetPos( self->parent.baseIO, newPos );
21f1e7 ¤   if ( IsntPGPError( err ) )
e5c7a1 ¤   {
4699e7 ¤   ¤   ref->offset¤= newPos;
549371 ¤   }
2867c5 ¤
a3deb7 ¤   return( err );
36efe6 }
30af5a
ddaf5a
bbaf5a
54af5a
ce24ad ¤   PGPLineEndIOVtbl const *
ad889e pgpLineEndIOGetClassVTBL()
d7bb36 {
8135a2 ¤   static PGPLineEndIOVtbl¤sVTBL¤  = { {{NULL,},} };
c4bce4 ¤   PGPLineEndIOVtbl *¤ ¤   ¤   vtbl¤   = &sVTBL;
6867c5 ¤
9eed72 ¤   if ( IsNull( vtbl->parentVTBL.parentVTBL.initProc ) )
17c7a1 ¤   {
6d9bee ¤   ¤   PGPProxyIOVtbl *¤   parent¤ = &vtbl->parentVTBL;
931b52 ¤   ¤
51faa1 ¤   ¤   /* get default routines */
faeb8e ¤   ¤   *parent¤= *pgpProxyIOGetClassVTBL();
bd6b73 ¤   ¤   parent->parentVTBL.initProc¤¤   = sLineEndIOInitProc;
a5fdf0 ¤   ¤   parent->parentVTBL.destroyProc¤ = sLineEndIODestroyProc;
91090a ¤   ¤   parent->parentVTBL.readProc¤¤   = sLineEndIOReadProc;
--e18c 001a5416901401000f0 Page 5 of pgpLineEndIO.c
860e8d ¤   ¤   parent->parentVTBL.writeProc¤   = sLineEndIOWriteProc;
cb30c6 ¤   ¤   parent->parentVTBL.getPosProc¤  = sLineEndIOGetPosProc;
6f247d ¤   ¤   parent->parentVTBL.setPosProc¤  = sLineEndIOSetPosProc;
fcf41b ¤   ¤   parent->parentVTBL.flushProc¤   = sLineEndIOFlushProc;
b59371 ¤   }
4367c5 ¤
b07543 ¤   return( vtbl );
8defe6 }
56af5a
bdaf5a
e1af5a
f7c744 ¤   PGPError
9e4767 PGPNewLineEndIO(
89a32c ¤   PGPIORef¤   ¤   ¤   baseIO,
0265df ¤   PGPBoolean¤ ¤   ¤   ownsBase,
870a5b ¤   ConvertLineEndType¤ toType,
f48b1c ¤   PGPLineEndIORef *¤  outRef )
a3bb36 {
50d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
285c42 ¤   PGPIORef¤   ¤   ¤   newRef;
524a6f ¤   PGPLineEndIOData¤   data;
6867c5 ¤
70cc67 ¤   data.parentData.ownsBaseIO¤ = ownsBase;
91821a ¤   data.parentData.baseIO¤ ¤   = baseIO;
f467c5 ¤
b5f9f2 ¤   data.toType¤= toType;
8067c5 ¤
0f9b7b ¤   err¤= pgpNewIOFromVTBL( baseIO->context,
e018c2 ¤   ¤   ¤   (PGPIOVtbl const *)pgpLineEndIOGetClassVTBL(),
ac2beb ¤   ¤   ¤   sizeof( PGPLineEndIO ), &data, &newRef );
dd67c5 ¤
6f665a ¤   *outRef¤= (PGPLineEndIORef)newRef;
18deb7 ¤   return( err );
0eefe6 }
75af5a
4daf5a
69af5a
caaf5a
9daf5a
32af5a
08af5a
f2af5a
2faf5a
68af5a
a7af5a
06af5a
ecaf5a
19af5a
feaf5a
abaf5a
95af5a
5eaf5a
3aaf5a
42af5a
59af5a
aaaf5a
a0af5a
0baf5a
10af5a
abaf5a
cf7e4d /*__Editor_settings____
faaf5a
244126 ¤   Local Variables:
1c7b17 ¤   tab-width: 4
bd0e6c ¤   End:
375f8c ¤   vi: ts=4 sw=4
2d9e9b ¤   vim: si
a5d062 _____________________*/
--bf10 001ac0bb9d9401000f1 Page 1 of pgpLineEndIO.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a00c5e ¤   A PGPIO subclass which converts TEXT file line endings.
b339c0 ¤   A subclass of PGPProxyIO.
41af5a
93bfa0 ¤   $Id: pgpLineEndIO.h,v 1.3.16.1 1998/11/12 03:18:23 heller Exp $
caf7f7 ____________________________________________________________________________*/
7e70c2 #ifndef Included_pgpLineEndIO_h¤/* [ */
c6d332 #define Included_pgpLineEndIO_h
3daf5a
8eaf5a
bc2864 /* base class */
b54850 #include "pgpProxyIO.h"
4daf5a
39af5a
abaf5a
026fe5 typedef struct PGPLineEndIO¤PGPLineEndIO;
d55da7 typedef PGPLineEndIO *¤ ¤   PGPLineEndIORef;
a9af5a
2f4792 enum ConvertLineEndType_
c8bb36 {
2fec54 ¤   kCRLineEndType,
93688f ¤   kLFLineEndType,
794ea4 ¤   kCRLFLineEndType
a882f7 };
30b434 PGPENUM_TYPEDEF( ConvertLineEndType_, ConvertLineEndType );
8daf5a
28af5a
7099c6 PGP_BEGIN_C_DECLARATIONS
a5cbcf #if PRAGMA_IMPORT_SUPPORTED
4db981 #pragma import on
637454 #endif
3aaf5a
48af5a
c0af5a
e3b691 PGPBoolean¤ PGPLineEndIOIsValid( PGPLineEndIORef ref );
7ee5b0 #define PGPValidateLineEndIO( ref )¤\
6a5f15 ¤   PGPValidateParam( PGPLineEndIOIsValid( ref ) )
5867c5 ¤
3daf5a
9c6e69 /* creates a new PGPLineEndIO type which converts to the specified type
e57586 ¤   of line ending */
1e0f96 PGPError¤   PGPNewLineEndIO( PGPIORef baseIO, PGPBoolean ownsBase,
5ce60b ¤   ¤   ¤   ¤   ConvertLineEndType toType, PGPLineEndIORef *outRef );
fcaf5a
00af5a
baaf5a
40af5a
3faf5a
cccbcf #if PRAGMA_IMPORT_SUPPORTED
62b981 #pragma import on
f57454 #endif
2c1254 PGP_END_C_DECLARATIONS
aaaf5a
81470a #endif /* ] Included_pgpLineEndIO_h */
d1af5a
fa7e4d /*__Editor_settings____
2aaf5a
854126 ¤   Local Variables:
bf7b17 ¤   tab-width: 4
200e6c ¤   End:
855f8c ¤   vi: ts=4 sw=4
a39e9b ¤   vim: si
acd062 _____________________*/
--8c76 001df119e56401000f2 Page 1 of pgpLineEndIOPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
b63bd1 ¤   abstract base class for file IO.
51af5a
5c7646 ¤   $Id: pgpLineEndIOPriv.h,v 1.1.34.1 1998/11/12 03:18:24 heller Exp $
6df7f7 ____________________________________________________________________________*/
6daf5a
e9b274 #include "pgpLineEndIO.h"
76e138 #include "pgpProxyIOPriv.h"
4d894b #include "pgpFileSpec.h"
b8af5a
3099c6 PGP_BEGIN_C_DECLARATIONS
67af5a
8aaf5a
cde823 /* the virtual function table for a PGPLineEndIO */
91cf68 typedef struct PGPLineEndIOVtbl
29bb36 {
6778be ¤   PGPProxyIOVtbl¤ ¤   ¤   parentVTBL;
5b81e1 } PGPLineEndIOVtbl;
1aaf5a
3daf5a
b80654 PGPLineEndIOVtbl const *¤   pgpLineEndIOGetClassVTBL( void );
36af5a
d9af5a
b50d29 /* used to initialize */
6d2362 typedef struct PGPLineEndIOData
e5bb36 {
67548d ¤   PGPProxyIOData¤ ¤   parentData;
28d2c2 ¤   ConvertLineEndType¤ toType;
282e57 } PGPLineEndIOData;
e7af5a
78af5a
f4fdd5 struct PGPLineEndIO
febb36 {
7afb84 ¤   PGPProxyIO¤ ¤   ¤   parent;
cc8f3b ¤   PGPUInt32¤  ¤   ¤   lineEndConvertMagic;
07d2c2 ¤   ConvertLineEndType¤ toType;
2a67c5 ¤
a9b5ab ¤   PGPByte¤¤   ¤   ¤   bufferSpace[ 4096 ];
4d3675 ¤   PGPByte *¤  ¤   ¤   buffer;
0ecf00 ¤   PGPSize¤¤   ¤   ¤   bufferSize;
698f18 ¤   PGPSize¤¤   ¤   ¤   bytesInBuffer;
f20a16 ¤   PGPBoolean¤ ¤   ¤   lastCharWasCR;
0a82f7 };
7e530c #define kPGPLineEndIOMagic¤ ¤   0x464c494f
e1af5a
c1af5a
4eaf5a
411254 PGP_END_C_DECLARATIONS
51af5a
7c7e4d /*__Editor_settings____
90af5a
c14126 ¤   Local Variables:
ed7b17 ¤   tab-width: 4
330e6c ¤   End:
285f8c ¤   vi: ts=4 sw=4
fe9e9b ¤   vim: si
dfd062 _____________________*/
--e020 000fb254cd0401000f3 Page 1 of pgpMemoryIO.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
c60bdc ¤   $Id: pgpMemoryIO.c,v 1.7.16.1 1998/11/12 03:18:25 heller Exp $
0df7f7 ____________________________________________________________________________*/
dae610 #include "pgpPFLConfig.h"
ceaf5a
d1feb2 #include <stdio.h>
fdaf5a
8ebe68 #if HAVE_SYS_STAT_H
02d4f4 #include <sys/stat.h>
647454 #endif
9daf5a
252b62 #include "pgpPFLErrors.h"
940d08 #include "pgpMem.h"
6aaf5a
7bdcf4 #include "pgpMemoryIOPriv.h"
bbaf5a
cbaf5a
5975cd #define GetParentVTBL()¤¤   pgpIOGetClassVTBL()
02af5a
14c258 #define GetSelfVTBL( ref ) \
6c1149 ¤   (PGPMemoryIOVtbl const *)pgpioGetObjectVTBL( ref )
07af5a
0dab2d #define CallReallocate( ref, vtbl, ptr, size) \
eaebf6 ¤   ¤   ((vtbl)->reallocateProc)( ref, ptr, size)
2e1b52 ¤   ¤
47af5a
eb16ea ¤   PGPBoolean
d50802 PGPMemoryIOIsValid( PGPMemoryIORef self )
d0bb36 {
245756 ¤   if ( ! PGPIOIsValid( (PGPIORef)self ) )
b0e20d ¤   ¤   return( FALSE );
2e67c5 ¤
92f7d3 ¤   return( self->memoryIOMagic == kPGPMemoryIOMagic );
20efe6 }
4aaf5a
28af5a
9baf5a
c3af5a
58c744 ¤   PGPError
5fe345 PGPNewMemoryIO(
31d8a8 ¤   PGPMemoryMgrRef¤¤   context,
79a22b ¤   PGPMemoryIORef *¤   outRef )
f5bb36 {
7b26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
b3b3bc ¤   PGPIORef¤   ¤   newRef;
159b82 ¤   PGPMemoryIOData¤data;
5767c5 ¤
ff3c76 ¤   PGPValidatePtr( outRef );
e83652 ¤   *outRef¤= NULL;
6367c5 ¤
90cf62 ¤   data.useFixedBuffer¤= FALSE;
1a67c5 ¤
b95299 ¤   err¤= pgpNewIOFromVTBL( context,
a2813c ¤   ¤   (PGPIOVtbl const *)pgpMemoryIOGetClassVTBL(),
1a3cff ¤   ¤   ¤   sizeof( PGPMemoryIO ), (void *)&data, &newRef );
2967c5 ¤
a1a1c5 ¤   *outRef¤= (PGPMemoryIORef)newRef;
9edeb7 ¤   return( err );
02efe6 }
17af5a
06af5a
1dc744 ¤   PGPError
f75718 PGPNewMemoryIOFixedBuffer(
9ad8a8 ¤   PGPMemoryMgrRef¤¤   context,
354984 ¤   void *¤ ¤   ¤   ¤   buffer,
341799 ¤   PGPSize¤¤   ¤   ¤   bufferSize,
d4a22b ¤   PGPMemoryIORef *¤   outRef )
fbbb36 {
--a48e 0006d02ff26401000f3 Page 2 of pgpMemoryIO.c
a326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
82b3bc ¤   PGPIORef¤   ¤   newRef;
369b82 ¤   PGPMemoryIOData¤data;
fc67c5 ¤
403c76 ¤   PGPValidatePtr( outRef );
e63652 ¤   *outRef¤= NULL;
17b99f ¤   PGPValidatePtr( buffer );
d567c5 ¤
bfe669 ¤   data.useFixedBuffer¤= TRUE;
2620fc ¤   data.buffer¤¤   ¤   = buffer;
95deb3 ¤   data.bufferSize¤¤   = bufferSize;
b667c5 ¤
a45299 ¤   err¤= pgpNewIOFromVTBL( context,
a7813c ¤   ¤   (PGPIOVtbl const *)pgpMemoryIOGetClassVTBL(),
e03cff ¤   ¤   ¤   sizeof( PGPMemoryIO ), (void *)&data, &newRef );
4f67c5 ¤
c6a1c5 ¤   *outRef¤= (PGPMemoryIORef)newRef;
91deb7 ¤   return( err );
ddefe6 }
f1af5a
20af5a
9466dd ¤   static PGPError
62be10 sMemoryIOInitProc(
5cf273 ¤   PGPIORef¤   inRef,
419b3a ¤   void *¤ ¤   data )
c7bb36 {
e53a27 ¤   PGPError¤   ¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
a9d761 ¤   PGPMemoryIORef¤ ¤   ¤   self¤   = (PGPMemoryIORef)inRef;
ca7291 ¤   const PGPMemoryIOData *¤myData= (PGPMemoryIOData *)data;
30b7d7 #define kDefaultBufferSize¤ ¤   512UL
1a67c5 ¤
583d77 ¤   PGPValidateIO( inRef );
1967c5 ¤
4a0bb2 ¤   err¤= pgpioInheritInit( inRef, (PGPIOVtbl const *)GetParentVTBL(), NULL );
b067c5 ¤
d0d657 ¤   self->memoryIOMagic¤= kPGPMemoryIOMagic;
0dbce8 ¤   self->buffer¤   ¤   = NULL;
d7ce69 ¤   self->bufferSize¤   = kDefaultBufferSize;
703f83 ¤   self->ownsBuffer¤   = TRUE;
cf4b12 ¤   self->eof¤  ¤   ¤   = 0;
351c70 ¤   self->canResize¤¤   = ! myData->useFixedBuffer;
8967c5 ¤
774668 ¤   if ( myData->useFixedBuffer )
3cc7a1 ¤   {
d739be ¤   ¤   self->buffer¤   ¤   = myData->buffer;
4a11ed ¤   ¤   self->bufferSize¤   = myData->bufferSize;
abbb93 ¤   ¤   self->eof¤  ¤   ¤   = myData->bufferSize;
90ba87 ¤   ¤   self->ownsBuffer¤   = FALSE;
ca9371 ¤   }
f20e24 ¤   else
5ec7a1 ¤   {
13eaae ¤   ¤   /* allocate a small buffer for starters */
21ac34 ¤   ¤   err¤¤   = CallReallocate( self, GetSelfVTBL( self ),
583fb9 ¤   ¤   ¤   &self->buffer, kDefaultBufferSize );
bd9371 ¤   }
d91b52 ¤   ¤
b967c5 ¤
3cdeb7 ¤   return( err );
b1efe6 }
8caf5a
c4af5a
abaf5a
1c66dd ¤   static PGPError
23c87b sMemoryIODestroyProc( PGPIORef¤ inRef )
f1bb36 {
b79372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
9ea7a6 ¤   PGPMemoryIORef¤ self¤   = (PGPMemoryIORef)inRef;
ffaf5a
fae39d ¤   PGPValidateMemoryIO( self );
6c67c5 ¤
04e6f1 ¤   if ( IsntNull( self->buffer ) && self->ownsBuffer )
6dc7a1 ¤   {
--f7b0 0001605241a401000f3 Page 3 of pgpMemoryIO.c
38f660 ¤   ¤   pgpClearMemory( self->buffer, self->bufferSize );
109515 ¤   ¤   PGPFreeData( self->buffer );
929371 ¤   }
bfbce8 ¤   self->buffer¤   ¤   = NULL;
9067c5 ¤
a0a81f ¤   self->memoryIOMagic¤= ~self->memoryIOMagic;
2b67c5 ¤
bbfcc8 ¤   err¤= pgpioInheritDestroy( inRef, (PGPIOVtbl const *)GetParentVTBL() );
2467c5 ¤
e6deb7 ¤   return( err );
54efe6 }
f8af5a
09af5a
70af5a
2daf5a
0866dd ¤   static PGPError
2140ba sMemoryIOReadProc(
ffb7a9 ¤   PGPIORef¤   ¤   ref,
a16179 ¤   PGPSize¤¤   ¤   requestCount,
0f2903 ¤   void *¤ ¤   ¤   buffer,
0c69c6 ¤   PGPSize *¤  ¤   bytesRead )
e4bb36 {
ca7de9 ¤   PGPMemoryIORef¤ self¤   = (PGPMemoryIORef)ref;
397637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
d2dce6 ¤   PGPFileOffset¤  offset¤ = ref->offset;
389f8b ¤   PGPSize¤¤   ¤   bytesAvailable¤ = 0;
aacba6 ¤   PGPSize¤¤   ¤   actualCount;
cc67c5 ¤
0fe39d ¤   PGPValidateMemoryIO( self );
5167c5 ¤
2bc555 ¤   pgpAssert( IsntNull( self->buffer ) );
d9f6f0 ¤   if ( offset <= (PGPFileOffset)self->eof )
3ac7a1 ¤   {
92d379 ¤   ¤   bytesAvailable¤ = (PGPSize)(self->eof - offset);
b29371 ¤   }
e867c5 ¤
58aa84 ¤   if ( bytesAvailable < requestCount )
5d34cf ¤   ¤   actualCount¤= ·bytesAvailable;
610e24 ¤   else
529f89 ¤   ¤   actualCount¤= requestCount;
fd1b52 ¤   ¤
6cc57b ¤   pgpCopyMemory( (char *)self->buffer + offset, buffer, actualCount );
a167c5 ¤
760750 ¤   if ( actualCount!= requestCount )
275d84 ¤   ¤   err¤= kPGPError_EOF;
6f472b ¤   *bytesRead¤ = actualCount;
c867c5 ¤
1cdeb7 ¤   return( err );
eaefe6 }
a1af5a
9267c5 ¤
9566dd ¤   static PGPError
e170f6 sSetBufferSize(
521acf ¤   PGPMemoryIORef¤ self,
d1ad3e ¤   PGPSize¤¤   ¤   newSize )
34bb36 {
1c26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
c967c5 ¤
21cad2 ¤   pgpAssert( self->canResize );
5c1b52 ¤   ¤
d4375b ¤   if ( self->canResize)
32c7a1 ¤   {
247eb0 ¤   ¤   err¤= CallReallocate( self, GetSelfVTBL( self ),
ae4372 ¤   ¤   ¤   ¤   &self->buffer, newSize);
817d98 ¤   ¤   if ( IsntPGPError( err ) )
0d5b34 ¤   ¤   {
553410 ¤   ¤   ¤   self->bufferSize¤   = newSize;
be0fe4 ¤   ¤   }
a39371 ¤   }
b20e24 ¤   else
c9c7a1 ¤   {
16e8eb ¤   ¤   err¤= kPGPError_IllegalFileOp;
--30bc 000f64b5856401000f3 Page 4 of pgpMemoryIO.c
a19371 ¤   }
9967c5 ¤
c7deb7 ¤   return( err );
6aefe6 }
baaf5a
aeaf5a
3466dd ¤   static PGPError
50ff93 sGrowBuffer(
421acf ¤   PGPMemoryIORef¤ self,
a0be2d ¤   PGPSize¤¤   ¤   minimumSize )
60bb36 {
397273 ¤   PGPSize¤¤   allocSize;
b926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5167c5 ¤
2f2799 ¤   if ( ! self->canResize )
f6025b ¤   ¤   return( kPGPError_DiskFull );
501b52 ¤   ¤
778978 ¤   /* grow existing size proportionally, or to minimum */
023df6 ¤   allocSize¤  = self->bufferSize;
66a533 ¤   allocSize¤  += allocSize / 2;
7adfdf ¤   if ( allocSize < minimumSize )
686f0c ¤   ¤   allocSize¤  = minimumSize;
9467c5 ¤
54087a ¤   /* grow the buffer to the size needed plus 1/8 more */
caf9c9 ¤   err¤= sSetBufferSize( self, allocSize);
a2054e ¤   if ( IsPGPError( err ) )
5bc7a1 ¤   {
112870 ¤   ¤   /* try again with minimum size */
346f0c ¤   ¤   allocSize¤  = minimumSize;
a1c0c7 ¤   ¤   err¤= sSetBufferSize( self, allocSize );
ce9371 ¤   }
7cf1e7 ¤   if ( IsntPGPError( err ) )
46c7a1 ¤   {
a1bbdd ¤   ¤   self->bufferSize¤   = allocSize;
059371 ¤   }
a0deb7 ¤   return( err );
c5efe6 }
21af5a
d5af5a
94ae30 ¤   ¤   ¤   ¤   ¤
7f66dd ¤   static PGPError
764796 sMemoryIOWriteProc(
d5b7a9 ¤   PGPIORef¤   ¤   ref,
726179 ¤   PGPSize¤¤   ¤   requestCount,
28b457 ¤   const void *¤   buffer )
e7bb36 {
1f7de9 ¤   PGPMemoryIORef¤ self¤   = (PGPMemoryIORef)ref;
3a9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
29dce6 ¤   PGPFileOffset¤  offset¤ = ref->offset;
c094f8 ¤   PGPSize¤¤   ¤   bufferSizeNeeded;
0567c5 ¤
a2e39d ¤   PGPValidateMemoryIO( self );
ad67c5 ¤
54ec22 ¤   bufferSizeNeeded¤   = (PGPSize)(offset + requestCount);
078f41 ¤   if ( bufferSizeNeeded > self->bufferSize )
0fc7a1 ¤   {
9c217f ¤   ¤   err¤= sGrowBuffer( self, bufferSizeNeeded );
e39371 ¤   }
ed67c5 ¤
d7f1e7 ¤   if ( IsntPGPError( err ) )
c5c7a1 ¤   {
a23bd2 ¤   ¤   pgpCopyMemory( buffer, (char *)self->buffer + offset, requestCount );
f11b52 ¤   ¤
f9dd67 ¤   ¤   if ( offset + requestCount > self->eof )
9c5e2d ¤   ¤   ¤   self->eof¤  = (PGPSize)(offset + requestCount);
f89371 ¤   }
4f67c5 ¤
7967c5 ¤
cbdeb7 ¤   return( err );
52efe6 }
aeaf5a
f694aa ¤   ¤   ¤   ¤   ¤   ¤
--0002 000ced32bea401000f3 Page 5 of pgpMemoryIO.c
9966dd ¤   static PGPError
e0680b sMemoryIOGetEOFProc(
0cb7a9 ¤   PGPIORef¤   ¤   ref,
26927a ¤   PGPFileOffset *¤eof )
bbbb36 {
8d7de9 ¤   PGPMemoryIORef¤ self¤   = (PGPMemoryIORef)ref;
8367c5 ¤
dae39d ¤   PGPValidateMemoryIO( self );
6267c5 ¤
4d01e0 ¤   *eof¤   = self->eof;
ae2d68 ¤   return( kPGPError_NoErr );
d5efe6 }
baaf5a
a9af5a
04dc47 #if PGPIO_EOF
4666dd ¤   static PGPError
2b78a5 sMemoryIOSetEOFProc(
88b7a9 ¤   PGPIORef¤   ¤   ref,
816535 ¤   PGPFileOffset ¤ newEOF )
31bb36 {
887de9 ¤   PGPMemoryIORef¤ self¤   = (PGPMemoryIORef)ref;
939372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
5b67c5 ¤
9fe39d ¤   PGPValidateMemoryIO( self );
7367c5 ¤
83d67e ¤   if ( self->canResize )
aec7a1 ¤   {
3e803f ¤   ¤   err¤= sSetBufferSize( self, newEOF );
a79371 ¤   }
bd0e24 ¤   else
bfc7a1 ¤   {
21766b ¤   ¤   /* buffer cannot be changed */
461803 ¤   ¤   if ( self->eof > self->bufferSize )
0d5b34 ¤   ¤   {
0ae6a7 ¤   ¤   ¤   err¤= kPGPError_IllegalFileOp;
2f0fe4 ¤   ¤   }
db9371 ¤   }
c467c5 ¤
46f1e7 ¤   if ( IsntPGPError( err ) )
e6c7a1 ¤   {
8f2e88 ¤   ¤   self->eof¤  = newEOF;
409371 ¤   }
c467c5 ¤
d52d68 ¤   return( kPGPError_NoErr );
deefe6 }
dc7454 #endif
18af5a
0baf5a
2a66dd ¤   static PGPError
17cabd sMemoryIOReallocateProc(
dc81ec ¤   PGPMemoryIORef¤ ¤   self,
954c8c ¤   void **¤¤   ¤   ¤   ptr,
4429a8 ¤   PGPSize¤¤   ¤   ¤   newSize )
48bb36 {
149372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
7667c5 ¤
52e39d ¤   PGPValidateMemoryIO( self );
4967c5 ¤
eee246 ¤   /* *ptr may be NULL, which is OK */
addfc0 ¤   err¤= PGPReallocData( self->parent.context, ptr, newSize, 0);
7067c5 ¤
7bdeb7 ¤   return( err );
7cefe6 }
5faf5a
d2af5a
92af5a
e4ad8a ¤   PGPMemoryIOVtbl const *
774b81 pgpMemoryIOGetClassVTBL()
cdbb36 {
7c4467 ¤   static PGPMemoryIOVtbl¤ sVTBL¤  = { {NULL,}, NULL, };
7283c5 ¤   PGPIOVtbl *¤¤   ¤   ¤   parent¤ = &sVTBL.parentVTBL;
ce67c5 ¤
--09fa 0015ce0c26d401000f3 Page 6 of pgpMemoryIO.c
a96a83 ¤   if ( IsNull( parent->initProc ) )
73c7a1 ¤   {
9ffaa1 ¤   ¤   /* get default routines */
ce918b ¤   ¤   *parent¤= *pgpIOGetClassVTBL();
bc1b52 ¤   ¤
906acd ¤   ¤   parent->initProc¤   = sMemoryIOInitProc;
0f8304 ¤   ¤   parent->destroyProc¤= sMemoryIODestroyProc;
6d1b52 ¤   ¤
445ddd ¤   ¤   parent->readProc¤   = sMemoryIOReadProc;
dfa093 ¤   ¤   parent->writeProc¤  = sMemoryIOWriteProc;
4a1b52 ¤   ¤
3a8f11 ¤   ¤   parent->getEOFProc¤ = sMemoryIOGetEOFProc;
49dc47 #if PGPIO_EOF
7e78cb ¤   ¤   parent->setEOFProc¤ = sMemoryIOSetEOFProc;
877454 #endif
d41b52 ¤   ¤
4b69fc ¤   ¤   sVTBL.reallocateProc¤   = sMemoryIOReallocateProc;
3c9371 ¤   }
e367c5 ¤
56cba4 ¤   return( &sVTBL );
94efe6 }
66af5a
c9af5a
03af5a
ccaf5a
83af5a
ebaf5a
5baf5a
c1af5a
03af5a
dcaf5a
63af5a
afaf5a
2daf5a
9faf5a
42af5a
abaf5a
12af5a
96af5a
5aaf5a
a6af5a
afaf5a
03af5a
2aaf5a
86af5a
a9af5a
3eaf5a
a67e4d /*__Editor_settings____
3daf5a
ab4126 ¤   Local Variables:
707b17 ¤   tab-width: 4
ba0e6c ¤   End:
905f8c ¤   vi: ts=4 sw=4
439e9b ¤   vim: si
5cd062 _____________________*/
--3ad9 001d3d91fa0401000f4 Page 1 of pgpMemoryIO.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
de5fc5 ¤   Superclass for all memory IO objects.
2967c5 ¤
4a2efb ¤   A pgpMemoryIO uses memory as a backing store, dynamically resizing
ef9831 ¤   as needed.
5267c5 ¤
c81f57 ¤   $Id: pgpMemoryIO.h,v 1.6.16.1 1998/11/12 03:18:26 heller Exp $
cef7f7 ____________________________________________________________________________*/
b7af5a
dd2864 /* base class */
b4a9cb #include "pgpIO.h"
966773 #include "pgpMemoryMgr.h"
f9af5a
68af5a
6999c6 PGP_BEGIN_C_DECLARATIONS
98cbcf #if PRAGMA_IMPORT_SUPPORTED
73b981 #pragma import on
957454 #endif
bfaf5a
bdaf5a
bcaf5a
4fc125 typedef struct PGPMemoryIO¤ ¤   PGPMemoryIO;
a7f4ee typedef PGPMemoryIO *¤  ¤   ¤   PGPMemoryIORef;
56af5a
0fec3d PGPError¤   PGPNewMemoryIO( PGPMemoryMgrRef context, PGPMemoryIORef *outRef );
78af5a
3d4759 /* buffer can't change and caller is responsible for destroying the buffer */
1036c9 PGPError¤   PGPNewMemoryIOFixedBuffer( PGPMemoryMgrRef context,
e62ad2 ¤   ¤   ¤   ¤   void *buffer, PGPSize bufferSize, PGPMemoryIORef *outRef );
4baf5a
58af5a
a55702 PGPBoolean¤ PGPMemoryIOIsValid( PGPMemoryIORef ref );
b7ba3d #define PGPValidateMemoryIO( ref )¤ \
93df61 ¤   PGPValidateParam( PGPMemoryIOIsValid( ref ) )
68af5a
66af5a
f9af5a
d1cbcf #if PRAGMA_IMPORT_SUPPORTED
8fb981 #pragma import on
f27454 #endif
641254 PGP_END_C_DECLARATIONS
f6af5a
d2af5a
587e4d /*__Editor_settings____
6eaf5a
454126 ¤   Local Variables:
937b17 ¤   tab-width: 4
d70e6c ¤   End:
7e5f8c ¤   vi: ts=4 sw=4
a29e9b ¤   vim: si
d3d062 _____________________*/
--7125 00112750913401000f5 Page 1 of pgpMemoryIOPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a66bcd ¤   File IO that uses a FILE * for its implementation
d6af5a
c896f9 ¤   $Id: pgpMemoryIOPriv.h,v 1.1.34.1 1998/11/12 03:18:26 heller Exp $
0df7f7 ____________________________________________________________________________*/
55af5a
38fbe2 #include "pgpMemoryIO.h"
9b9c9f #include "pgpIOPriv.h"
cfaf5a
1c99c6 PGP_BEGIN_C_DECLARATIONS
2baf5a
3daf5a
a95816 typedef PGPError¤   (*PGPMemoryIOReallocateProc)( PGPMemoryIORef ref,
b199dc ¤   ¤   ¤   ¤   ¤   ¤   void **ptr, PGPSize size );
cbaf5a
3e6f01 /* the virtual function table for a PGPFileIO */
9c06d2 typedef struct PGPMemoryIOVtbl
0cbb36 {
a4d2bb ¤   PGPIOVtbl¤  ¤   ¤   ¤   ¤   parentVTBL;
7f67c5 ¤
4e6d03 ¤   PGPMemoryIOReallocateProc¤  reallocateProc;
79db04 } PGPMemoryIOVtbl;
05af5a
faaf5a
800514 PGPMemoryIOVtbl const *¤pgpMemoryIOGetClassVTBL( void );
fbaf5a
3baf5a
ca0d29 /* used to initialize */
bfead8 typedef struct PGPMemoryIOData
41bb36 {
4744b1 ¤   PGPBoolean¤ ¤   useFixedBuffer;
50f19a ¤   void *¤ ¤   ¤   buffer;
7e40a1 ¤   PGPSize¤¤   ¤   bufferSize;
a174b2 } PGPMemoryIOData;
89af5a
66301f struct PGPMemoryIO
3cbb36 {
09c23c ¤   PGPIO¤  ¤   ¤   parent;
9767c5 ¤
9b3084 ¤   PGPUInt32¤  ¤   memoryIOMagic;
4af19a ¤   void *¤ ¤   ¤   buffer;
d52c58 ¤   PGPBoolean¤ ¤   ownsBuffer;
7eeebb ¤   PGPBoolean¤ ¤   canResize;
a34d5f ¤   PGPUInt32¤  ¤   bufferSize;
82ef6f ¤   PGPUInt32¤  ¤   eof;
1082f7 };
f4cc87 #define kPGPMemoryIOMagic¤  ¤   0x50524f58¤ /* PROX */
2baf5a
5faf5a
c2af5a
4e1254 PGP_END_C_DECLARATIONS
67af5a
847e4d /*__Editor_settings____
62af5a
524126 ¤   Local Variables:
357b17 ¤   tab-width: 4
820e6c ¤   End:
225f8c ¤   vi: ts=4 sw=4
179e9b ¤   vim: si
12d062 _____________________*/
--f182 0001f5f1d37401000f6 Page 1 of pgpProxyIO.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
175aa5 ¤   $Id: pgpProxyIO.c,v 1.7.34.1 1998/11/12 03:18:27 heller Exp $
9ff7f7 ____________________________________________________________________________*/
28e610 #include "pgpPFLConfig.h"
02af5a
c22b62 #include "pgpPFLErrors.h"
660d08 #include "pgpMem.h"
a9af5a
cbe138 #include "pgpProxyIOPriv.h"
a0af5a
b6af5a
9875cd #define GetParentVTBL()¤¤   pgpIOGetClassVTBL()
4baf5a
cac258 #define GetSelfVTBL( ref ) \
b8e6ce ¤   (PGPProxyIOVtbl const *)pgpioGetObjectVTBL( ref )
62af5a
45af5a
7b16ea ¤   PGPBoolean
dfc1f2 PGPProxyIOIsValid( PGPProxyIORef self )
4bbb36 {
8d5756 ¤   if ( ! PGPIOIsValid( (PGPIORef)self ) )
5de20d ¤   ¤   return( FALSE );
3267c5 ¤
8a743c ¤   return( self->proxyIOMagic == kPGPProxyIOMagic );
6befe6 }
88af5a
04af5a
6baf5a
afc744 ¤   PGPError
67c0ce PGPNewProxyIO(
ec4cd2 ¤   PGPIORef¤   ¤   baseIO,
690433 ¤   PGPBoolean¤ ¤   ownsBaseIO,
b511a2 ¤   PGPProxyIORef *¤outRef )
69bb36 {
ca26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7bb3bc ¤   PGPIORef¤   ¤   newRef;
3f3cbf ¤   PGPProxyIOData¤ data;
a067c5 ¤
9601ea ¤   PGPValidateIO( baseIO );
a867c5 ¤
ba6667 ¤   data.ownsBaseIO¤= ownsBaseIO;
00bb68 ¤   data.baseIO¤¤   = baseIO;
9f67c5 ¤
a69b7b ¤   err¤= pgpNewIOFromVTBL( baseIO->context,
b6f22e ¤   ¤   (PGPIOVtbl const *)pgpProxyIOGetClassVTBL(),
3082e3 ¤   ¤   ¤   sizeof( PGPProxyIO ), (void *)&data, &newRef );
e867c5 ¤
2da393 ¤   *outRef¤= (PGPProxyIORef)newRef;
69deb7 ¤   return( err );
47efe6 }
b8af5a
2eaf5a
d666dd ¤   static PGPError
4389e3 sProxyIOInitProc(
6ff273 ¤   PGPIORef¤   inRef,
649b3a ¤   void *¤ ¤   data )
c7bb36 {
1c7637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
9a2fad ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)inRef;
62936f ¤   const PGPProxyIOData *¤ myData= (PGPProxyIOData *)data;
6c67c5 ¤
fd3d77 ¤   PGPValidateIO( inRef );
70daa0 ¤   PGPValidateIO( myData->baseIO );
5d67c5 ¤
160bb2 ¤   err¤= pgpioInheritInit( inRef, (PGPIOVtbl const *)GetParentVTBL(), NULL );
d467c5 ¤
c0aa9b ¤   self->proxyIOMagic¤ = kPGPProxyIOMagic;
1f9e79 ¤   self->baseIO¤   ¤   = myData->baseIO;
--cf13 000d6b0b591401000f6 Page 2 of pgpProxyIO.c
2892d0 ¤   self->ownsBaseIO¤   = myData->ownsBaseIO;
c467c5 ¤
77deb7 ¤   return( err );
b0efe6 }
f4af5a
4daf5a
72af5a
1b66dd ¤   static PGPError
5fd6fc sProxyIODestroyProc( PGPIORef¤  inRef )
13bb36 {
1e9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
422fad ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)inRef;
4baf5a
849724 ¤   PGPValidateProxyIO( self );
5b67c5 ¤
b658bc ¤   if ( self->ownsBaseIO )
dec7a1 ¤   {
75f60a ¤   ¤   PGPFreeIO( self->baseIO );
669371 ¤   }
6cbd66 ¤   self->baseIO¤   ¤   = NULL;
a067c5 ¤
39be20 ¤   self->proxyIOMagic¤ = 0;
f167c5 ¤
32fcc8 ¤   err¤= pgpioInheritDestroy( inRef, (PGPIOVtbl const *)GetParentVTBL() );
6a67c5 ¤
e8deb7 ¤   return( err );
a9efe6 }
73af5a
e5af5a
edaf5a
d7af5a
b566dd ¤   static PGPError
8ce3ca sProxySetPosProc(
23b7a9 ¤   PGPIORef¤   ¤   ref,
0916ce ¤   PGPFileOffset¤  newPos )
c8bb36 {
713789 ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)ref;
1e67c5 ¤
48b7b0 ¤   return( PGPIOSetPos( self->baseIO, newPos ) );
75efe6 }
eeaf5a
afaf5a
8faf5a
80af5a
0766dd ¤   static PGPError
617749 sProxyIOReadProc(
87b7a9 ¤   PGPIORef¤   ¤   ref,
646179 ¤   PGPSize¤¤   ¤   requestCount,
dc2903 ¤   void *¤ ¤   ¤   buffer,
1d69c6 ¤   PGPSize *¤  ¤   bytesRead )
4abb36 {
133789 ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)ref;
029372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
fa67c5 ¤
70e0a1 ¤   err¤= PGPIORead( self->baseIO, requestCount, buffer, bytesRead );
4b67c5 ¤
5edeb7 ¤   return( err );
e2efe6 }
deaf5a
8694aa ¤   ¤   ¤   ¤   ¤   ¤
1266dd ¤   static PGPError
9382b5 sProxyIOWriteProc(
7cb7a9 ¤   PGPIORef¤   ¤   ref,
7c6179 ¤   PGPSize¤¤   ¤   requestCount,
b5b457 ¤   const void *¤   buffer )
b5bb36 {
f83789 ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)ref;
cc9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
d867c5 ¤
61dbe4 ¤   err¤= PGPIOWrite( self->baseIO, requestCount, buffer );
c667c5 ¤
d6deb7 ¤   return( err );
--8eb5 000214f9d86401000f6 Page 3 of pgpProxyIO.c
7aefe6 }
46af5a
2194aa ¤   ¤   ¤   ¤   ¤   ¤
3966dd ¤   static PGPError
7d7b57 sProxyIOGetEOFProc(
9eb7a9 ¤   PGPIORef¤   ¤   ref,
6f927a ¤   PGPFileOffset *¤eof )
29bb36 {
dd3789 ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)ref;
3f67c5 ¤
9c7cfa ¤   return( PGPIOGetEOF( self->baseIO, eof ) );
27efe6 }
9caf5a
5eaf5a
c1ae30 ¤   ¤   ¤   ¤   ¤
f066dd ¤   static PGPError
f6ffed sProxyIOFlushProc( PGPIORef¤¤   ref)
91bb36 {
1d7637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
5c3789 ¤   PGPProxyIORef¤  self¤   = (PGPProxyIORef)ref;
2867c5 ¤
d8dd71 ¤   err¤= PGPIOFlush( self->baseIO );
a267c5 ¤
bddeb7 ¤   return( err );
feefe6 }
26af5a
d3af5a
c5af5a
a51af9 ¤   PGPProxyIOVtbl const *
9e3eb8 pgpProxyIOGetClassVTBL()
61bb36 {
53b7aa ¤   static PGPProxyIOVtbl¤  sVTBL¤  = { {NULL,} };
df83c5 ¤   PGPIOVtbl *¤¤   ¤   ¤   parent¤ = &sVTBL.parentVTBL;
5f67c5 ¤
a06a83 ¤   if ( IsNull( parent->initProc ) )
2dc7a1 ¤   {
21faa1 ¤   ¤   /* get default routines */
22918b ¤   ¤   *parent¤= *pgpIOGetClassVTBL();
d81b52 ¤   ¤
7a54f2 ¤   ¤   parent->initProc¤   = sProxyIOInitProc;
5f8c71 ¤   ¤   parent->destroyProc¤= sProxyIODestroyProc;
bc1b52 ¤   ¤
c56467 ¤   ¤   parent->readProc¤   = sProxyIOReadProc;
9214b6 ¤   ¤   parent->writeProc¤  = sProxyIOWriteProc;
c21b52 ¤   ¤
677ee8 ¤   ¤   parent->setPosProc¤ = sProxySetPosProc;
ec1b52 ¤   ¤
93f254 ¤   ¤   parent->getEOFProc¤ = sProxyIOGetEOFProc;
381b52 ¤   ¤
fbee46 ¤   ¤   parent->flushProc¤  = sProxyIOFlushProc;
2e9371 ¤   }
8267c5 ¤
edcba4 ¤   return( &sVTBL );
a9efe6 }
f7af5a
64af5a
54af5a
76af5a
1caf5a
69af5a
63af5a
97af5a
baaf5a
b2af5a
a6af5a
4caf5a
07af5a
7eaf5a
c2af5a
bdaf5a
fbaf5a
21af5a
--154c 001ee726838401000f6 Page 4 of pgpProxyIO.c
e0af5a
1aaf5a
17af5a
78af5a
32af5a
93af5a
37af5a
a6af5a
557e4d /*__Editor_settings____
00af5a
994126 ¤   Local Variables:
7e7b17 ¤   tab-width: 4
060e6c ¤   End:
4f5f8c ¤   vi: ts=4 sw=4
bc9e9b ¤   vim: si
eed062 _____________________*/
--c070 001d2aff840401000f7 Page 1 of pgpProxyIO.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
7ea90b ¤   Abstract superclass for all proxy objects.
4167c5 ¤
1de63c ¤   A pgpProxyIO uses another object to do the real IO, but performs
009f52 ¤   additional processing on top of that. ·Proxy objects could be·
494ce5 ¤   chained. ·Examples of possible proxy objects include:
b45eeb ¤   ¤   memory buffer and/or readahead for faster file I/O
043a3a ¤   ¤   checksum computations
e79818 ¤   ¤   merging two fork files into one virtual fork
2e20d3 ¤   ¤   etc
bc67c5 ¤
ea6f0e ¤   $Id: pgpProxyIO.h,v 1.6.30.1 1998/11/12 03:18:27 heller Exp $
4cf7f7 ____________________________________________________________________________*/
2f5c2d #ifndef Included_pgpProxyIO_h¤  /* [ */
72883c #define Included_pgpProxyIO_h
29af5a
852864 /* base class */
56a9cb #include "pgpIO.h"
5eaf5a
33af5a
8cc488 typedef struct PGPProxyIO¤  ¤   PGPProxyIO;
a7b4d7 typedef PGPProxyIO *¤   ¤   ¤   PGPProxyIORef;
63af5a
daaf5a
6899c6 PGP_BEGIN_C_DECLARATIONS
c3cbcf #if PRAGMA_IMPORT_SUPPORTED
d5b981 #pragma import on
7f7454 #endif
43af5a
67af5a
d6af5a
1ebca3 /* note: one would normally always create a subclass;
4bc53c this is just here for debug testing */
36b709 PGPError¤   PGPNewProxyIO( PGPIORef io,
333c3b ¤   ¤   ¤   ¤   PGPBoolean ownsProxy, PGPProxyIORef *outRef );
ceaf5a
73af5a
a6518c PGPBoolean¤ PGPProxyIOIsValid( PGPProxyIORef ref );
ea04f6 #define PGPValidateProxyIO( ref )¤  PGPValidateParam( PGPProxyIOIsValid( ref ) )
15af5a
91af5a
83af5a
28cbcf #if PRAGMA_IMPORT_SUPPORTED
34b981 #pragma import on
037454 #endif
671254 PGP_END_C_DECLARATIONS
34af5a
452a3d #endif /* ] Included_pgpProxyIO_h */
f2af5a
4d7e4d /*__Editor_settings____
c1af5a
e74126 ¤   Local Variables:
6d7b17 ¤   tab-width: 4
c60e6c ¤   End:
035f8c ¤   vi: ts=4 sw=4
469e9b ¤   vim: si
d2d062 _____________________*/
--837a 001eb5d9a2a401000f8 Page 1 of pgpProxyIOPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a66bcd ¤   File IO that uses a FILE * for its implementation
d6af5a
be4144 ¤   $Id: pgpProxyIOPriv.h,v 1.2.34.1 1998/11/12 03:18:28 heller Exp $
bbf7f7 ____________________________________________________________________________*/
98af5a
ea4850 #include "pgpProxyIO.h"
ee9c9f #include "pgpIOPriv.h"
92af5a
2099c6 PGP_BEGIN_C_DECLARATIONS
85af5a
14af5a
566f01 /* the virtual function table for a PGPFileIO */
8f1751 typedef struct PGPProxyIOVtbl
06bb36 {
1d538b ¤   PGPIOVtbl¤  parentVTBL;
be84e4 } PGPProxyIOVtbl;
7caf5a
3daf5a
5a695e PGPProxyIOVtbl const *¤ pgpProxyIOGetClassVTBL( void );
6faf5a
63af5a
1b0d29 /* used to initialize */
7afb5b typedef struct PGPProxyIOData
aabb36 {
7858af ¤   PGPBoolean¤ ownsBaseIO;
21a99e ¤   PGPIORef¤   baseIO;
132b52 } PGPProxyIOData;
d9af5a
3d8c57 struct PGPProxyIO
d9bb36 {
d1c23c ¤   PGPIO¤  ¤   ¤   parent;
df67c5 ¤
847aa9 ¤   PGPUInt32¤  ¤   proxyIOMagic;
ebdcaa ¤   PGPBoolean¤ ¤   ownsBaseIO;
b3e69a ¤   /* this object does all the work */
5145a3 ¤   PGPIO *¤¤   ¤   baseIO;
7582f7 };
b8af55 #define kPGPProxyIOMagic¤   ¤   0x50524f58¤ /* PROX */
29af5a
eeaf5a
b8af5a
581254 PGP_END_C_DECLARATIONS
88af5a
207e4d /*__Editor_settings____
06af5a
a44126 ¤   Local Variables:
ed7b17 ¤   tab-width: 4
8a0e6c ¤   End:
585f8c ¤   vi: ts=4 sw=4
759e9b ¤   vim: si
ebd062 _____________________*/
--9501 00060dc921f401000f9 Page 1 of pgpStdFileIO.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
913398 ¤   Implementation of FileIO based on a FILE *. ·This is a concrete subclass
ad27e1 ¤   that can be instantiated using a FILE *.
f0af5a
3b4f3f ¤   $Id: pgpStdFileIO.c,v 1.14.16.1 1998/11/12 03:18:29 heller Exp $
a3f7f7 ____________________________________________________________________________*/
67e610 #include "pgpPFLConfig.h"
2aaf5a
e0feb2 #include <stdio.h>
3daf5a
a9be68 #if HAVE_SYS_STAT_H
4ad4f4 #include <sys/stat.h>
7e7454 #endif
f7af5a
752b62 #include "pgpPFLErrors.h"
430d08 #include "pgpMem.h"
84af5a
2f72b2 #include "pgpStdFileIOPriv.h"
99af5a
d81c21 #define PGP_USE_FILE_SPEC_PRIV
7fb2ca #include "pgpFileSpecPriv.h"
06af5a
4faf5a
6b1d6d #define GetParentVTBL()¤¤   pgpFileIOGetClassVTBL()
2caf5a
d7c258 #define GetSelfVTBL( ref ) \
f70b5c ¤   (PGPStdFileIOVtbl const *)pgpioGetObjectVTBL( ref )
beaf5a
3caf5a
cb16ea ¤   PGPBoolean
ff7aa4 PGPStdFileIOIsValid( PGPStdFileIORef self )
23bb36 {
7c4f2b ¤   if ( ! PGPFileIOIsValid( (PGPFileIORef)self ) )
cde20d ¤   ¤   return( FALSE );
5967c5 ¤
14ba29 ¤   return( self->stdFileIOMagic == kPGPStdFileIOMagic );
90efe6 }
c8af5a
aeaf5a
9baf5a
d7c744 ¤   PGPError
7104b5 PGPNewStdFileIO(
1ad8a8 ¤   PGPMemoryMgrRef¤¤   context,
9e946f ¤   FILE *¤ ¤   ¤   ¤   stdioFILE,
65a76d ¤   Boolean¤¤   ¤   ¤   autoClose,
9cdd3a ¤   PGPStdFileIORef *¤  outRef )
65bb36 {
bcd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
c75c42 ¤   PGPIORef¤   ¤   ¤   newRef;
23971a ¤   PGPStdFileIOData¤   data;
fd67c5 ¤
b23b58 ¤   data.autoClose¤ = autoClose;
c59776 ¤   data.stdioFILE¤ = stdioFILE;
ea67c5 ¤
ec5299 ¤   err¤= pgpNewIOFromVTBL( context,
6f9bd6 ¤   ¤   ¤   (PGPIOVtbl const *)pgpStdFileIOGetClassVTBL(),
73ee6e ¤   ¤   ¤   sizeof( PGPStdFileIO ), &data, &newRef );
0067c5 ¤
4f2faf ¤   *outRef¤= (PGPStdFileIORef)newRef;
b4deb7 ¤   return( err );
08efe6 }
c0af5a
98af5a
6c66dd ¤   static PGPError
4b8c12 sStdFileIOInitProc(
f3f273 ¤   PGPIORef¤   inRef,
899b3a ¤   void *¤ ¤   data )
42bb36 {
6057ab ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
--5a9a 000d3cebf55401000f9 Page 2 of pgpStdFileIO.c
8b580d ¤   PGPStdFileIORef¤¤   ¤   ¤   self¤   = (PGPStdFileIORef)inRef;
feb177 ¤   const PGPStdFileIOData *¤   myData¤ = (PGPStdFileIOData *)data;
7167c5 ¤
f83d77 ¤   PGPValidateIO( inRef );
3867c5 ¤
90d8c0 ¤   err¤= pgpioInheritInit( inRef, (PGPIOVtbl const *)GetParentVTBL(), data );
1567c5 ¤
391624 ¤   self->stdFileIOMagic¤   = kPGPStdFileIOMagic;
436d65 ¤   self->stdioFILE¤¤   ¤   = myData->stdioFILE;
89270d ¤   self->autoClose¤¤   ¤   = myData->autoClose;
2167c5 ¤
19deb7 ¤   return( err );
dbefe6 }
f4af5a
8caf5a
63af5a
c466dd ¤   static PGPError
013621 sStdFileIODestroyProc( PGPIORef¤inRef )
96bb36 {
2c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
8f1abc ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)inRef;
6bf0f7 ¤   int¤¤   ¤   ¤   closeResult;
a6af5a
8a3c82 ¤   PGPValidateStdFileIO( self );
8b9d0c ¤   PGPValidatePtr( self->stdioFILE );
3267c5 ¤
9d5f90 ¤   closeResult¤= fclose( self->stdioFILE );
8a1850 ¤   self->stdioFILE¤= NULL;
5d67c5 ¤
80039c ¤   self->stdFileIOMagic¤   = 0;
4e67c5 ¤
3efcc8 ¤   err¤= pgpioInheritDestroy( inRef, (PGPIOVtbl const *)GetParentVTBL() );
9467c5 ¤
b93f70 ¤   if ( closeResult != 0 )
e3fafc ¤   ¤   err¤= kPGPError_FileOpFailed;
a267c5 ¤
9bdeb7 ¤   return( err );
5cefe6 }
cdaf5a
99af5a
aaaf5a
7daf5a
da66dd ¤   static PGPError
fce63b sStdFileSetPosProc(
76b7a9 ¤   PGPIORef¤   ¤   ref,
8c16ce ¤   PGPFileOffset¤  newPos )
bfbb36 {
9b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
27f04e ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)ref;
4cd1d3 ¤   int¤¤   ¤   result;
11488b ¤   fpos_t¤ ¤   tempPos;
4967c5 ¤
e19d0c ¤   PGPValidatePtr( self->stdioFILE );
9667c5 ¤
874590 ¤   tempPos¤= newPos;
c78d5d ¤   result¤ = fsetpos( self->stdioFILE, &tempPos );
cefa26 ¤   if ( result != 0 )
d3c7a1 ¤   {
32fafc ¤   ¤   err¤= kPGPError_FileOpFailed;
7f9371 ¤   }
4667c5 ¤
cddeb7 ¤   return( err );
81efe6 }
aaaf5a
0daf5a
e3af5a
c4af5a
e866dd ¤   static PGPError
f372b8 sStdFileIOReadProc(
85b7a9 ¤   PGPIORef¤   ¤   ref,
a86179 ¤   PGPSize¤¤   ¤   requestCount,
d32903 ¤   void *¤ ¤   ¤   buffer,
--c764 000ec2094e8401000f9 Page 3 of pgpStdFileIO.c
3969c6 ¤   PGPSize *¤  ¤   bytesRead )
5abb36 {
6e7637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
adf04e ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)ref;
149fe9 ¤   size_t¤ ¤   ¤   result;
be67c5 ¤
f69d0c ¤   PGPValidatePtr( self->stdioFILE );
c767c5 ¤
35c120 ¤   result¤ = fread( buffer, 1, requestCount, self->stdioFILE );
050614 ¤   if ( result != requestCount )
4ac7a1 ¤   {
415d84 ¤   ¤   err¤= kPGPError_EOF;
ec9371 ¤   }
6c41dd ¤   *bytesRead¤ = result;
0067c5 ¤
c2deb7 ¤   return( err );
52efe6 }
cfaf5a
f494aa ¤   ¤   ¤   ¤   ¤   ¤
c766dd ¤   static PGPError
3c64b6 sStdFileIOWriteProc(
4eb7a9 ¤   PGPIORef¤   ¤   ref,
f66179 ¤   PGPSize¤¤   ¤   requestCount,
5eb457 ¤   const void *¤   buffer )
1bbb36 {
617637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
faf04e ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)ref;
c99fe9 ¤   size_t¤ ¤   ¤   result;
e067c5 ¤
309d0c ¤   PGPValidatePtr( self->stdioFILE );
e767c5 ¤
c51067 ¤   result¤ = fwrite( buffer, 1, requestCount, self->stdioFILE );
1f0614 ¤   if ( result != requestCount )
59c7a1 ¤   {
a1ba1c ¤   ¤   err¤= kPGPError_WriteFailed;
2a9371 ¤   }
2c67c5 ¤
43deb7 ¤   return( err );
80efe6 }
56af5a
1394aa ¤   ¤   ¤   ¤   ¤   ¤
1566dd ¤   static PGPError
16492a sStdFileIOGetEOFProc(
c5b7a9 ¤   PGPIORef¤   ¤   ref,
7c927a ¤   PGPFileOffset *¤eof )
7abb36 {
dd9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
62f04e ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)ref;
414895 ¤   FILE *¤ ¤   ¤   stdioFILE¤  = self->stdioFILE;
6c548a ¤   fpos_t¤ ¤   ¤   startPos;
329595 ¤   fpos_t¤ ¤   ¤   eofPos;
5216a4 ¤   int¤¤   ¤   ¤   fResult;
1967c5 ¤
f0fc3f ¤   *eof¤   = 0;
9b9d0c ¤   PGPValidatePtr( self->stdioFILE );
3267c5 ¤
d856f4 ¤   /* save current file position */
dc9a20 ¤   fResult¤= fgetpos( stdioFILE, &startPos );
6933b6 ¤   if ( fResult == 0 )
bac7a1 ¤   {
d283b3 ¤   ¤   /* seek to the end of the file so we can get its length */
e915c0 ¤   ¤   fResult¤= fseek( stdioFILE, 0, SEEK_END );
84c5d3 ¤   ¤   if ( fResult == 0 )
3cd83f ¤   ¤   ¤   fResult¤= fgetpos( stdioFILE, &eofPos);
761b52 ¤   ¤
abc180 ¤   ¤   if ( fResult != 0 )
95c612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
be87c7 ¤   ¤   ¤
1dfc68 ¤   ¤   /* restore previous file position */
2fd95c ¤   ¤   fResult¤= fsetpos( stdioFILE, &startPos );
bdc180 ¤   ¤   if ( fResult != 0 )
ecc612 ¤   ¤   ¤   err¤= kPGPError_FileOpFailed;
--cc16 0003ce4bee8401000f9 Page 4 of pgpStdFileIO.c
a19371 ¤   }
0e0e24 ¤   else
96c7a1 ¤   {
38fafc ¤   ¤   err¤= kPGPError_FileOpFailed;
079371 ¤   }
f767c5 ¤
4767c5 ¤
3590b5 ¤   *eof¤   = eofPos;
94deb7 ¤   return( err );
e2efe6 }
42af5a
fcaf5a
86af5a
e9af5a
71dc47 #if PGPIO_EOF
3e66dd ¤   static PGPError
dc473a sChangeFileSize(
45fbe4 ¤   FILE *¤ ¤   ¤   file,
6519a9 ¤   PGPFileOffset¤  newEOF)
99bb36 {
e726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
fd67c5 ¤
16a4a7 ¤   (void)file;
9ae4d7 ¤   (void)newEOF;
317938 #if defined( PGP_UNIX )
8eaf5a
25c821 #elif defined( PGP_WIN32 )
e1af5a
fbdcb0 #elif defined( PGP_MACINTOSH )
79af5a
9d7454 #endif
76deb7 ¤   return( err );
5defe6 }
10af5a
40af5a
b2af5a
5b66dd ¤   static PGPError
8b5984 sStdFileIOSetEOFProc(
ddb7a9 ¤   PGPIORef¤   ¤   ref,
1b6535 ¤   PGPFileOffset ¤ newEOF )
51bb36 {
456962 ¤   PGPError¤   ¤   err¤= kPGPError_IllegalFileOp;
f3f04e ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)ref;
564895 ¤   FILE *¤ ¤   ¤   stdioFILE¤  = self->stdioFILE;
ff67c5 ¤
83de31 ¤   PGPValidatePtr( stdioFILE );
8367c5 ¤
08139b ¤   err¤= sChangeFileSize( stdioFILE, newEOF);
24f1e7 ¤   if ( IsntPGPError( err ) )
9cc7a1 ¤   {
7f04e7 ¤   ¤   /* stdio buffers may now be whacked */
e9b4ad ¤   ¤   /* how to flush them? */
d6b4ba ¤   ¤   pgpDebugMsg( "flush buffers" );
b79371 ¤   }
b3af5a
aadeb7 ¤   return( err );
faefe6 }
94af5a
9c7454 #endif
03ae30 ¤   ¤   ¤   ¤   ¤
1466dd ¤   static PGPError
d833b9 sStdFileIOFlushProc( PGPIORef¤  ¤   ref)
39bb36 {
0d7637 ¤   PGPError¤   ¤   err¤¤   = kPGPError_NoErr;
0ef04e ¤   PGPStdFileIORef¤self¤   = (PGPStdFileIORef)ref;
4c67c5 ¤
899d0c ¤   PGPValidatePtr( self->stdioFILE );
07f721 ¤   if ( fflush( self->stdioFILE ) != 0 )
66c7a1 ¤   {
3bfafc ¤   ¤   err¤= kPGPError_FileOpFailed;
e29371 ¤   }
3c67c5 ¤
--217b 0012a7f1808401000f9 Page 5 of pgpStdFileIO.c
afdeb7 ¤   return( err );
b7efe6 }
35af5a
adaf5a
8daf5a
20af5a
3a84c6 ¤   PGPStdFileIOVtbl const *
2bac69 pgpStdFileIOGetClassVTBL()
c2bb36 {
7d82da ¤   static PGPStdFileIOVtbl¤sVTBL¤  = { {{NULL,}} };
bb2957 ¤   PGPFileIOVtbl *¤parent¤ = &sVTBL.parentVTBL;
0e67c5 ¤
28edf9 ¤   if ( IsNull( parent->parentVTBL.initProc ) )
90c7a1 ¤   {
19faa1 ¤   ¤   /* get default routines */
e70a42 ¤   ¤   *parent¤= *pgpFileIOGetClassVTBL();
7b1b52 ¤   ¤
a6fa1f ¤   ¤   parent->parentVTBL.initProc¤¤   = sStdFileIOInitProc;
835d9b ¤   ¤   parent->parentVTBL.destroyProc¤ = sStdFileIODestroyProc;
491b52 ¤   ¤
549866 ¤   ¤   parent->parentVTBL.readProc¤¤   = sStdFileIOReadProc;
79a776 ¤   ¤   parent->parentVTBL.writeProc¤   = sStdFileIOWriteProc;
6f1b52 ¤   ¤
0414dc ¤   ¤   parent->parentVTBL.setPosProc¤  = sStdFileSetPosProc;
a21b52 ¤   ¤
697371 ¤   ¤   parent->parentVTBL.getEOFProc¤  = sStdFileIOGetEOFProc;
851b52 ¤   ¤
bcdc47 #if PGPIO_EOF
af67ca ¤   ¤   parent->parentVTBL.setEOFProc¤  = sStdFileIOSetEOFProc;
f67454 #endif
2a1b52 ¤   ¤
bb5de0 ¤   ¤   parent->parentVTBL.flushProc¤   = sStdFileIOFlushProc;
8e9371 ¤   }
6a67c5 ¤
49cba4 ¤   return( &sVTBL );
07efe6 }
c7af5a
d9af5a
99af5a
c6af5a
b3af5a
45af5a
f0af5a
25af5a
1baf5a
d9af5a
a9af5a
a5af5a
eeaf5a
54af5a
d7af5a
13af5a
2caf5a
76af5a
5baf5a
f9af5a
b1af5a
12af5a
1caf5a
c9af5a
37af5a
d1af5a
6d7e4d /*__Editor_settings____
1caf5a
9f4126 ¤   Local Variables:
c77b17 ¤   tab-width: 4
f80e6c ¤   End:
c15f8c ¤   vi: ts=4 sw=4
339e9b ¤   vim: si
2ad062 _____________________*/
--2434 0016c4ea353401000fa Page 1 of pgpStdFileIO.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
0877cc ¤   $Id: pgpStdFileIO.h,v 1.7.16.1 1998/11/12 03:18:30 heller Exp $
5cf7f7 ____________________________________________________________________________*/
daaf5a
a12864 /* base class */
d6c68b #include "pgpFileIO.h"
85feb2 #include <stdio.h>
3baf5a
de0796 typedef struct PGPStdFileIO¤¤   PGPStdFileIO;
a2bd21 typedef PGPStdFileIO *¤ ¤   ¤   PGPStdFileIORef;
afaf5a
e8af5a
5c99c6 PGP_BEGIN_C_DECLARATIONS
b9cbcf #if PRAGMA_IMPORT_SUPPORTED
95b981 #pragma import on
887454 #endif
64af5a
26af5a
580335 /*____________________________________________________________________________
4d9a0f ¤   Caller loses ownership of the FILE * after calling PGPNewStdFileIO().
5167c5 ¤
ad0aa8 ¤   If autoClose is TRUE, then the FILE * is automatically closed via fclose()
4b2204 ¤   when the PGPFileIO is destroyed.
ce67c5 ¤
762aae ¤   if autoClose is FALSE, then the caller *may not* use the FILE * until
8f9ff5 ¤   the PGPFileIO is destroyed, at which point ownership of the the FILE *
7e0f3a ¤   reverts back to the caller. ·The caller can't assume any particular
08d47f ¤   state of the FILE * at that point however (e.g file position, eof, etc).
98f7f7 ____________________________________________________________________________*/
665a4c PGPError¤   PGPNewStdFileIO( PGPMemoryMgrRef context,
004b3b ¤   ¤   ¤   ¤   FILE *file, Boolean autoClose, PGPStdFileIORef *outRef );
98af5a
3daf5a
86718b PGPBoolean¤ PGPStdFileIOIsValid( PGPStdFileIORef ref );
1074dc #define PGPValidateStdFileIO( ref )¤\
801814 ¤   ¤   PGPValidateParam( PGPStdFileIOIsValid( ref ) )
d1af5a
1baf5a
4eaf5a
3dcbcf #if PRAGMA_IMPORT_SUPPORTED
c82ced #pragma import reset
687454 #endif
4b1254 PGP_END_C_DECLARATIONS
2caf5a
a57e4d /*__Editor_settings____
f1af5a
0f4126 ¤   Local Variables:
ee7b17 ¤   tab-width: 4
270e6c ¤   End:
865f8c ¤   vi: ts=4 sw=4
a99e9b ¤   vim: si
6cd062 _____________________*/
--395b 00180270578401000fb Page 1 of pgpStdFileIOPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a66bcd ¤   File IO that uses a FILE * for its implementation
d6af5a
b6738b ¤   $Id: pgpStdFileIOPriv.h,v 1.2.34.1 1998/11/12 03:18:30 heller Exp $
37f7f7 ____________________________________________________________________________*/
fbaf5a
a9ae60 #include "pgpStdFileIO.h"
1dc5a2 #include "pgpFileIOPriv.h"
e6feb2 #include <stdio.h>
4baf5a
f199c6 PGP_BEGIN_C_DECLARATIONS
0baf5a
0aaf5a
a26f01 /* the virtual function table for a PGPFileIO */
2a99d1 typedef struct PGPStdFileIOVtbl
73bb36 {
754e3d ¤   PGPFileIOVtbl¤  parentVTBL;
e2a9fd } PGPStdFileIOVtbl;
acaf5a
deaf5a
714225 PGPStdFileIOVtbl const *¤   pgpStdFileIOGetClassVTBL( void );
caaf5a
c4af5a
f40d29 /* used to initialize */
5075db typedef struct PGPStdFileIOData
88bb36 {
6eed2a ¤   PGPBoolean¤ ¤   autoClose;
d32732 ¤   FILE *¤ ¤   ¤   stdioFILE;
b0064b } PGPStdFileIOData;
83af5a
152384 struct PGPStdFileIO
9cbb36 {
55e8ff ¤   PGPFileIO¤  ¤   parent;
a467c5 ¤
e0e3fe ¤   PGPUInt32¤  ¤   stdFileIOMagic;
9c2732 ¤   FILE *¤ ¤   ¤   stdioFILE;
fded2a ¤   PGPBoolean¤ ¤   autoClose;
d982f7 };
b98f70 #define kPGPStdFileIOMagic¤ ¤   0x5354494f
18af5a
adaf5a
3aaf5a
021254 PGP_END_C_DECLARATIONS
0aaf5a
867e4d /*__Editor_settings____
bdaf5a
6b4126 ¤   Local Variables:
707b17 ¤   tab-width: 4
730e6c ¤   End:
945f8c ¤   vi: ts=4 sw=4
349e9b ¤   vim: si
80d062 _____________________*/
--8b47 001e746b202401000fc Page 1 of Makefile.in
5ea601 #
56b4a3 # common/util/
fea601 #
b60207 # $Id: Makefile.in,v 1.4 1998/04/08 00:58:05 marcd Exp $
0da601 #
5daf5a
934719 LOCALDEFINES=
bbaf5a
cc6f28 OBJS= pgpThreads.o pgpCond.o pgpMutex.o pgpSemaphore.o
7aaf5a
feb7a3 all:: DONE
e7af5a
--3d8b 000db7c0175401000fd Page 1 of pgpCond.c
bc38e5 /*
eaa2b5 ·* pgpCond.c
fd775e ·*
5ec8d5 ·* $Id: pgpCond.c,v 1.3 1998/07/31 18:14:34 marcd Exp $
30775e ·*
31c554 ·* Implements conditional variable stuff
bd775e ·*
38df97 ·* copyright (C) 1998 Network Associates Inc.
15495d ·*/
4aaf5a
17feb2 #include <stdio.h>
759ea8 #include "pgpThreads.h"
90af5a
1becf1 #if PGP_UNIX_SOLARIS
9638e5 /*
fe0c65 ·* Oh goodie, we have solaris, which is chalk full of useful routines.
645da1 ·* Simply call various system functions.
53495d ·*/
494d2f int
199f1d PGPCondCreate( PGPCond_t *cv, PGPCondAttr_t *attr )
86bb36 {
47d29c ¤   return( cond_init( cv, attr ? *attr : USYNC_THREAD, NULL ) );
bfefe6 }
c9af5a
f54d2f int
a93edc PGPCondDestroy( PGPCond_t *cv )
87bb36 {
927a1b ¤   return( cond_destroy( cv ) );
b4efe6 }
dbaf5a
f14d2f int
6bba93 PGPCondWait( PGPCond_t *cv, PGPMutex_t *mp )
6bbb36 {
3b1fca ¤   return( cond_wait( cv, mp ) );
22efe6 }
e4af5a
1c4d2f int
8818a1 PGPCondSignal( PGPCond_t *cv )
7cbb36 {
f81bcc ¤   return( cond_signal( cv ) );
20efe6 }
a1af5a
dc4d2f int
17e23a PGPCondBroadcast( PGPCond_t *cv )
adbb36 {
e72690 ¤   return( cond_broadcast( cv ) );
f6efe6 }
e5c933 #endif /* PGP_UNIX_SOLARIS */
f0af5a
9d093d #if HAVE_PTHREAD_CREATE
3938e5 /*
411811 ·* We have pthreads support, so call the pthreads functions
03495d ·*/
01af5a
f34d2f int
169f1d PGPCondCreate( PGPCond_t *cv, PGPCondAttr_t *attr )
7bbb36 {
2fcdc4 ¤   return( pthread_cond_init( cv, attr ) );
c5efe6 }
66af5a
d04d2f int
fd3edc PGPCondDestroy( PGPCond_t *cv )
66bb36 {
8a13c0 ¤   return( pthread_cond_destroy( cv ) );
e9efe6 }
76af5a
614d2f int
46ba93 PGPCondWait( PGPCond_t *cv, PGPMutex_t *mp )
3fbb36 {
d177fd ¤   return( pthread_cond_wait( cv, mp ) );
c7efe6 }
dbaf5a
--23ae 000c488b0cc401000fd Page 2 of pgpCond.c
af4d2f int
9a18a1 PGPCondSignal( PGPCond_t *cv )
1cbb36 {
4f9606 ¤   return( pthread_cond_signal( cv ) );
d8efe6 }
d9af5a
c74d2f int
39e23a PGPCondBroadcast( PGPCond_t *cv )
dfbb36 {
6f63c4 ¤   return( pthread_cond_broadcast( cv ) );
c4efe6 }
2caf5a
57460a #endif /* HAVE_PTREAD_CREATE */
efaf5a
68afb9 #if PGP_WIN32
6238e5 /*
38e7bf ·* Windows 32 stuff. Conditionals are called Events. See comment below
8b36e4 ·* about broadcast problems.
1c495d ·*/
3511a9 #include <process.h>
fe5655 #include <windows.h>
69af5a
754d2f int
779f1d PGPCondCreate( PGPCond_t *cv, PGPCondAttr_t *attr )
febb36 {
85af5a
7df423 ¤   *cv = CreateEvent(NULL, 0, 0, NULL);
70af5a
26efb6 ¤   return(*cv == NULL);
80efe6 }
a2af5a
b52a6b /* init2 creates an event object that is manually reset (which means that */
ce2e56 /* ··broadcast signals can be done). */
764d2f int
10ce56 PGPCondCreate2( PGPCond_t *cv, PGPCondAttr_t *attr )
28bb36 {
bdaf5a
80f18e ¤   *cv = CreateEvent(NULL, 1, 0, NULL);
bcaf5a
49efb6 ¤   return(*cv == NULL);
cfefe6 }
8baf5a
014d2f int
0c3edc PGPCondDestroy( PGPCond_t *cv )
12bb36 {
dd00ad ¤   int¤lRC;
44af5a
353db9 ¤   lRC = CloseHandle(*cv);
7aee2d ¤   return(lRC == 0);
b8efe6 }
b8af5a
3e4d2f int
0cba93 PGPCondWait( PGPCond_t *cv, PGPMutex_t *mp )
c6bb36 {
df00ad ¤   int¤lRC;
6be2d1 ¤   int¤lRC2;
9caf5a
dfbed8 ¤   lRC = ReleaseMutex(*mp);
f36e91 ¤   if (lRC == 0)
c8e102 ¤   ¤   return 1;
6faf5a
05d378 ¤   lRC2 = WaitForSingleObject(*cv, INFINITE);
7faf5a
fd1e25 ¤   lRC = WaitForSingleObject(*mp, INFINITE);
c9af5a
ace415 ¤   return(lRC == WAIT_FAILED || lRC2 == WAIT_FAILED);
c0efe6 }
89af5a
eb4d2f int
4f18a1 PGPCondSignal( PGPCond_t *cv )
66bb36 {
c400ad ¤   int¤lRC;
--ed62 001ab4650ef401000fd Page 3 of pgpCond.c
e0af5a
ef592d ¤   lRC = SetEvent(*cv);
13ee2d ¤   return(lRC == 0);
37efe6 }
11af5a
2a4d2f int
fde23a PGPCondBroadcast( PGPCond_t *cv )
a8bb36 {
b200ad ¤   int¤lRC;
dfaf5a
6f638c ¤   /* In order for broadcast to work under Win32, you need to call
296fa1 ¤   ·* cond_init2 when creating the cond variable. ·Note that
e970f5 ¤   ·* regular signaling won't work if this is done. WARNING!!!!
1d0ec5 ¤   ·* This does not do a broadcast. ·A single event semaphore does
a88784 ¤   ·* not seem to be able to do both a broadcast and a
3a53c2 ¤   ·* PGPCondSignal. ·May need to create 2 events: one manual reset
15a62b ¤   ·* one auto reset and have the cond_wait wait on both then pulse
761d07 ¤   ·* the manual reset event for a broadcast.
99a4e3 ¤   ·*/
f2825c ¤   lRC = PulseEvent(*cv);
7aee2d ¤   return(lRC == 0);
28efe6 }
ca8df7 #endif /* PGP_WIN32 */
3faf5a
d51808 #ifndef _PGP_THREAD
fa38e5 /*
cbe3d5 ·* Hummm, no thread support. This probably isn't a good thing
95495d ·*/
73af5a
8a0873 /* ARGSUSED */
234d2f int
a99f1d PGPCondCreate( PGPCond_t *cv, PGPCondAttr_t *attr )
7abb36 {
48ea61 ¤   return( 0 );
d2efe6 }
f5af5a
d20873 /* ARGSUSED */
cc4d2f int
6f3edc PGPCondDestroy( PGPCond_t *cv )
b2bb36 {
cbea61 ¤   return( 0 );
fcefe6 }
05af5a
ae0873 /* ARGSUSED */
3d4d2f int
0bba93 PGPCondWait( PGPCond_t *cv, PGPMutex_t *mp )
b0bb36 {
e9ea61 ¤   return( 0 );
dbefe6 }
6aaf5a
f30873 /* ARGSUSED */
5d4d2f int
b718a1 PGPCondSignal( PGPCond_t *cv )
3abb36 {
2bea61 ¤   return( 0 );
43efe6 }
43af5a
ce0873 /* ARGSUSED */
574d2f int
dbe23a PGPCondBroadcast( PGPCond_t *cv )
8ebb36 {
3dea61 ¤   return( 0 );
5cefe6 }
62af5a
ab368e #endif /* no threads package */
--3916 000e2513359401000fe Page 1 of pgpMutex.c
bc38e5 /*
72947f ·* pgpMutex.c
7e775e ·*
4a5b21 ·* $Id: pgpMutex.c,v 1.2 1998/03/18 05:08:16 elowe Exp $
95495d ·*/
95af5a
e3feb2 #include <stdio.h>
769ea8 #include "pgpThreads.h"
c7af5a
a1ecf1 #if PGP_UNIX_SOLARIS
3faf5a
6e0873 /* ARGSUSED */
844d2f int
e367b2 PGPMutexCreate( PGPMutex_t *mp, PGPMutexAttr_t *attr )
5fbb36 {
20329c ¤   return( mutex_init( mp, attr ? *attr : USYNC_THREAD, NULL ) );
42efe6 }
75af5a
6c4d2f int
4ac7db PGPMutexDestroy( PGPMutex_t *mp )
b3bb36 {
140e1c ¤   return( mutex_destroy( mp ) );
52efe6 }
3faf5a
524d2f int
c07dba PGPMutexLock( PGPMutex_t *mp )
eebb36 {
bb4214 ¤   return( mutex_lock( mp ) );
f8efe6 }
71af5a
834d2f int
f062ca PGPMutexUnlock( PGPMutex_t *mp )
30bb36 {
3852e9 ¤   return( mutex_unlock( mp ) );
70efe6 }
cfaf5a
a54d2f int
a2a874 PGPMutexTryLock( PGPMutex_t *mp )
e7bb36 {
aa5cf8 ¤   return( mutex_trylock( mp ) );
d3efe6 }
21c933 #endif /* PGP_UNIX_SOLARIS */
17af5a
2b093d #if HAVE_PTHREAD_CREATE
c7af5a
300873 /* ARGSUSED */
874d2f int
c567b2 PGPMutexCreate( PGPMutex_t *mp, PGPMutexAttr_t *attr )
47bb36 {
1ad51b ¤   return( pthread_mutex_init(mp, attr) );
62efe6 }
47af5a
644d2f int
35c7db PGPMutexDestroy( PGPMutex_t *mp )
e9bb36 {
8c662b ¤   return( pthread_mutex_destroy( mp ) );
1cefe6 }
a1af5a
e54d2f int
7a7dba PGPMutexLock( PGPMutex_t *mp )
2fbb36 {
a8c80d ¤   return( pthread_mutex_lock( mp ) );
d3efe6 }
66af5a
b14d2f int
ff62ca PGPMutexUnlock( PGPMutex_t *mp )
22bb36 {
623b32 ¤   return( pthread_mutex_unlock( mp ) );
17efe6 }
efaf5a
d04d2f int
e2a874 PGPMutexTryLock( PGPMutex_t *mp )
--e263 00058da631a401000fe Page 2 of pgpMutex.c
2cbb36 {
2934cf ¤   return( pthread_mutex_trylock( mp ) );
0defe6 }
70af5a
4f460a #endif /* HAVE_PTREAD_CREATE */
2baf5a
c1afb9 #if PGP_WIN32
13af5a
4f11a9 #include <process.h>
6a5655 #include <windows.h>
71af5a
220873 /* ARGSUSED */
194d2f int
bd67b2 PGPMutexCreate( PGPMutex_t *mp, PGPMutexAttr_t *attr )
71bb36 {
8aaf5a
ac2b7e ¤   *mp = CreateMutex(NULL, FALSE, NULL);
af67c5 ¤
a3dbb3 ¤   return( *mp == NULL );
41efe6 }
fcaf5a
994d2f int
95c7db PGPMutexDestroy( PGPMutex_t *mp )
4bbb36 {
f61ec4 ¤   int¤lRC = CloseHandle(*mp);
d1ee2d ¤   return(lRC == 0);
75efe6 }
91af5a
cd4d2f int
137dba PGPMutexLock( PGPMutex_t *mp )
27bb36 {
92bf0a ¤   int¤lRC = WaitForSingleObject(*mp, INFINITE);
5d67c5 ¤
f1781a ¤   return(lRC == WAIT_FAILED);
f3efe6 }
a9af5a
304d2f int
fd62ca PGPMutexUnlock( PGPMutex_t *mp )
a5bb36 {
ba14a3 ¤   int¤lRC = ReleaseMutex(*mp);
5cee2d ¤   return(lRC == 0);
80efe6 }
3aaf5a
b24d2f int
c4a874 PGPMutexTryLock( PGPMutex_t *mp )
a4bb36 {
d4182f ¤   int¤lRC = WaitForSingleObject(*mp, 0);
b267c5 ¤
ff781a ¤   return(lRC == WAIT_FAILED);
76efe6 }
36af5a
7d8df7 #endif /* PGP_WIN32 */
6daf5a
501808 #ifndef _PGP_THREAD
52af5a
7c0873 /* ARGSUSED */
324d2f int
ea67b2 PGPMutexCreate( PGPMutex_t *mp, PGPMutexAttr_t *attr )
eabb36 {
40ea61 ¤   return( 0 );
72efe6 }
f1af5a
da0873 /* ARGSUSED */
434d2f int
a3c7db PGPMutexDestroy( PGPMutex_t *mp )
e7bb36 {
c2ea61 ¤   return( 0 );
63efe6 }
44af5a
740873 /* ARGSUSED */
2f4d2f int
587dba PGPMutexLock( PGPMutex_t *mp )
--5479 0012d3360fd401000fe Page 3 of pgpMutex.c
2cbb36 {
4bea61 ¤   return( 0 );
eaefe6 }
3caf5a
700873 /* ARGSUSED */
7c4d2f int
8662ca PGPMutexUnlock( PGPMutex_t *mp )
efbb36 {
49ea61 ¤   return( 0 );
01efe6 }
05af5a
660873 /* ARGSUSED */
aa4d2f int
b7a874 PGPMutexTryLock( PGPMutex_t *mp )
4cbb36 {
59ea61 ¤   return( 0 );
2befe6 }
a6af5a
2de0c0 #endif /* no thread package */
--2b88 0002ad15c18401000ff Page 1 of pgpSemaphore.c
bc38e5 /*
720b05 ·* pgpSemaphore.c
ea775e ·*
a61c97 ·* $Id: pgpSemaphore.c,v 1.3 1998/03/18 05:08:17 elowe Exp $
1b495d ·*/
caaf5a
0dfeb2 #include <stdio.h>
bf9ea8 #include "pgpThreads.h"
2caf5a
faecf1 #if PGP_UNIX_SOLARIS
5faf5a
9ab760 PGPSemAttr_t PGPSemAttr_def = {0,USYNC_THREAD,0};
3baf5a
b84d2f int
381a00 PGPSemCreate(PGPSem_t *sem, PGPSemAttr_t *attr)
9ebb36 {
619be1 ¤   return sema_init(sem, attr->count, attr->type, attr->arg);
e1efe6 }
f0af5a
ef4d2f int
9a78f8 PGPSemWait(PGPSem_t *sem)
b1bb36 {
6084ef ¤   return sema_wait(sem);
5fefe6 }
7baf5a
b57ba7 int PGPSemTryWait(PGPSem_t *sem)
91bb36 {
41a70e ¤   return sema_trywait(sem);
07efe6 }
d0af5a
c919d5 int PGPSemPost(PGPSem_t *sem)
16bb36 {
10be56 ¤   return sema_post(sem);
ccefe6 }
beaf5a
f2b0b4 int PGPSemDestroy(PGPSem_t *sem)
b0bb36 {
7a7d57 ¤   return sema_destroy(sem);
15efe6 }
f5af5a
39622d #endif /* end PGP_UNIX_SOLARIS */
daaf5a
b4d27e /* Linux has sem_init function but no headers ?? */
f77722 #if HAVE_SEM_INIT && !PGP_UNIX_LINUX
3eaf5a
36fbcb PGPSemAttr_t PGPSemAttr_def = {0, 0};
6eaf5a
6d4d2f int
601a00 PGPSemCreate(PGPSem_t *sem, PGPSemAttr_t *attr)
2abb36 {
6f9fd5 ¤   return sem_init(sem, attr->shared, attr->value);
69efe6 }
2daf5a
064d2f int
7878f8 PGPSemWait(PGPSem_t *sem)
8dbb36 {
100921 ¤   return sem_wait(sem);
55efe6 }
73af5a
cc7ba7 int PGPSemTryWait(PGPSem_t *sem)
56bb36 {
e4813b ¤   return sem_trywait(sem);
91efe6 }
6daf5a
9119d5 int PGPSemPost(PGPSem_t *sem)
46bb36 {
513398 ¤   return sem_post(sem);
5cefe6 }
ecaf5a
b8b0b4 int PGPSemDestroy(PGPSem_t *sem)
0cbb36 {
2a5b62 ¤   return sem_destroy(sem);
--8c57 000a9bbeae9401000ff Page 2 of pgpSemaphore.c
7aefe6 }
46af5a
c3141c #endif /* HAVE_SEM_INIT */
23af5a
6fe29c #if HAVE_SEMGET
d0af5a
5e641e PGPSemAttr_t PGPSemAttr_def = {1, 0};
e8af5a
e84d2f int
371a00 PGPSemCreate(PGPSem_t *sem, PGPSemAttr_t *attr)
00bb36 {
101dfd ¤   *sem = semget(IPC_PRIVATE, attr->nsems, attr->type);
82dc9a ¤   return *sem;
96efe6 }
adaf5a
e74d2f int
0178f8 PGPSemWait(PGPSem_t *sem)
e4bb36 {
60be63 ¤   struct sembuf sops;
f4af5a
d8f2f1 ¤   sops.sem_num = 0;
07af2c ¤   sops.sem_op = -1;
389317 ¤   sops.sem_flg = 0;
8867c5 ¤
fec792 ¤   return semop(*sem, &sops, 1);
54efe6 }
baaf5a
8f7ba7 int PGPSemTryWait(PGPSem_t *sem)
1bbb36 {
eabe63 ¤   struct sembuf sops;
ecaf5a
00f2f1 ¤   sops.sem_num = 0;
d8af2c ¤   sops.sem_op = -1;
c6f36f ¤   sops.sem_flg = IPC_NOWAIT;
ef67c5 ¤
55c792 ¤   return semop(*sem, &sops, 1);
a5efe6 }
14af5a
e619d5 int PGPSemPost(PGPSem_t *sem)
c3bb36 {
15be63 ¤   struct sembuf sops;
ceaf5a
f9f2f1 ¤   sops.sem_num = 0;
9e8b4c ¤   sops.sem_op = 1;
ba9317 ¤   sops.sem_flg = 0;
f767c5 ¤
88c792 ¤   return semop(*sem, &sops, 1);
f7efe6 }
fdaf5a
2cb0b4 int PGPSemDestroy(PGPSem_t *sem)
26bb36 {
937eaa ¤   return semctl(*sem, 0, IPC_RMID, 0);
a0efe6 }
07af5a
0465a0 #endif /* HAVE_SEMGET */
82af5a
7dafb9 #if PGP_WIN32
0911a9 #include <process.h>
985655 #include <windows.h>
eeaf5a
d8b621 PGPSemAttr_t PGPSemAttr_def = {0, 32, 0};
3baf5a
924d2f int
aa1a00 PGPSemCreate(PGPSem_t *sem, PGPSemAttr_t *attr)
debb36 {
83e4fe ¤   *sem = CreateSemaphore(NULL, attr->icount, attr->max, attr->name);
30dccd ¤   return (int) *sem;
8fefe6 }
95af5a
da4d2f int
2978f8 PGPSemWait(PGPSem_t *sem)
a9bb36 {
--fac0 00121d48ace401000ff Page 3 of pgpSemaphore.c
068126 ¤   int lRC = WaitForSingleObject(*sem, INFINITE);
b567c5 ¤
167bfa ¤   return (lRC == WAIT_FAILED);
7cefe6 }
d8af5a
477ba7 int PGPSemTryWait(PGPSem_t *sem)
8cbb36 {
b2cd6c ¤   int lRC = WaitForSingleObject(*sem, 0);
8667c5 ¤
dc7bfa ¤   return (lRC == WAIT_FAILED);
92efe6 }
c0af5a
6619d5 int PGPSemPost(PGPSem_t *sem)
21bb36 {
a3b455 ¤   return ReleaseSemaphore(*sem, 1, NULL);
cfefe6 }
24af5a
8ab0b4 int PGPSemDestroy(PGPSem_t *sem)
d5bb36 {
023bcf ¤   return CloseHandle(*sem);
a2efe6 }
5caf5a
668df7 #endif /* PGP_WIN32 */
32af5a
3e399c #ifndef _PGP_SEMAPHORE
46af5a
c54d2f int
381a00 PGPSemCreate(PGPSem_t *sem, PGPSemAttr_t *attr)
95bb36 {
a33e6b ¤   return 0;
daefe6 }
82af5a
cd4d2f int
0278f8 PGPSemWait(PGPSem_t *sem)
91bb36 {
be3e6b ¤   return 0;
dbefe6 }
47af5a
867ba7 int PGPSemTryWait(PGPSem_t *sem)
f1bb36 {
6d3e6b ¤   return 0;
8cefe6 }
f8af5a
2619d5 int PGPSemPost(PGPSem_t *sem)
08bb36 {
bf3e6b ¤   return 0;
52efe6 }
b0af5a
29b0b4 int PGPSemDestroy(PGPSem_t *sem)
57bb36 {
543e6b ¤   return 0;
59efe6 }
63af5a
2159d5 #endif /* no semaphore package */
--f777 00097db2ffa40100100 Page 1 of pgpThreads.c
bc38e5 /*
5870df ·* pgpThreads.c
4a775e ·*
652690 ·* $Id: pgpThreads.c,v 1.3 1998/03/18 05:08:17 elowe Exp $
8e495d ·*/
39af5a
e1feb2 #include <stdio.h>
889ea8 #include "pgpThreads.h"
9eaf5a
bcecf1 #if PGP_UNIX_SOLARIS
c4af5a
9f4d2f int
aa6845 PGPThreadAttrCreate( PGPThreadAttr_t *attr )
c0bb36 {
edf542 ¤   *attr = 0;
c7ea61 ¤   return( 0 );
13efe6 }
35af5a
774d2f int
4cf470 PGPThreadAttrDestroy( PGPThreadAttr_t *attr )
dfbb36 {
2cf542 ¤   *attr = 0;
fdea61 ¤   return( 0 );
41efe6 }
03af5a
2d4d2f int
c40d72 PGPThreadAttrGetDetachState( PGPThreadAttr_t *attr, int *detachstate )
33bb36 {
fd6a3a ¤   *detachstate = *attr;
bfea61 ¤   return( 0 );
8fefe6 }
e0af5a
ef4d2f int
c9076d PGPThreadAttrSetDetachState( PGPThreadAttr_t *attr, int detachstate )
a5bb36 {
d3e1f7 ¤   *attr = detachstate;
c3ea61 ¤   return( 0 );
49efe6 }
48af5a
f40873 /* ARGSUSED */
bf4d2f int
96bda3 PGPThreadCreate(
764d59 ¤   PGPThread_t¤¤   *tid,
1ca009 ¤   PGPThreadAttr_t¤*attr,
fc462e ¤   VFP¤¤   ¤   func,
fab9f0 ¤   void¤   ¤   *arg
3d27e6 ¤   )
eebb36 {
9dda1c ¤   return( thr_create( NULL, 0, func, arg, *attr, tid ) );
aaefe6 }
79af5a
23314a void
7e5c47 PGPThreadYield()
d5bb36 {
c547e0 ¤   thr_yield();
15efe6 }
31af5a
52314a void
bd1ab9 PGPThreadExit(PGPThread_t tid)
27bb36 {
3e4233 ¤   (void) tid;
08e6c5 ¤   thr_exit( NULL );
c6efe6 }
d2af5a
87314a void
c84478 PGPThreadJoin( PGPThread_t tid, int *status )
08bb36 {
556a21 ¤   thr_join( tid, NULL, (void **) status );
e1efe6 }
4caf5a
0c314a void
9763ef PGPThreadKill( PGPThread_t tid, int sig )
--b211 00030c8a21f40100100 Page 2 of pgpThreads.c
2cbb36 {
054a44 ¤   thr_kill( tid, sig );
13efe6 }
c4af5a
284d2f int
0bc19a PGPThreadKeyCreate(PGPThreadKey_t *key, void (*destructor)(void* value))
dabb36 {
782d00 ¤   return thr_keycreate(key, destructor);
c7efe6 }
44af5a
f04d2f int
ba2afe PGPThreadGetSpecific(PGPThreadKey_t key, void **value)
75bb36 {
d8ac00 ¤   return thr_getspecific(key, value);
27efe6 }
bcaf5a
514d2f int
f8a5b6 PGPThreadSetSpecific(PGPThreadKey_t key, void *value)
febb36 {
69fa5c ¤   return thr_setspecific(key, value);
13efe6 }
aeaf5a
a74d2f int
1b6b8c PGPThreadKeyDelete(PGPThreadKey_t key)
9abb36 {
377151 ¤   (void) key;
f93e6b ¤   return 0;
10efe6 }
d7af5a
c7622d #endif /* end PGP_UNIX_SOLARIS */
71af5a
73093d #if HAVE_PTHREAD_CREATE
b2af5a
734d2f int
b66845 PGPThreadAttrCreate( PGPThreadAttr_t *attr )
98bb36 {
a47351 ¤   return pthread_attr_init(attr);
dbefe6 }
0faf5a
6d4d2f int
4af470 PGPThreadAttrDestroy( PGPThreadAttr_t *attr )
f3bb36 {
851ee8 ¤   return pthread_attr_destroy(attr);
c0efe6 }
aaaf5a
9a4d2f int
b00d72 PGPThreadAttrGetDetachState( PGPThreadAttr_t *attr, int *detachstate )
a4bb36 {
62bd00 ¤   return pthread_attr_getdetachstate(attr, detachstate);
f5efe6 }
cfaf5a
d64d2f int
15076d PGPThreadAttrSetDetachState( PGPThreadAttr_t *attr, int detachstate )
88bb36 {
ca5a74 ¤   return pthread_attr_setdetachstate(attr, detachstate);
dbefe6 }
62af5a
ab0873 /* ARGSUSED */
404d2f int
10bda3 PGPThreadCreate(
fd4d59 ¤   PGPThread_t¤¤   *tid,
dea009 ¤   PGPThreadAttr_t¤*attr,
c1462e ¤   VFP¤¤   ¤   func,
4eb9f0 ¤   void¤   ¤   *arg
5127e6 ¤   )
3bbb36 {
e8e0d2 ¤   return( pthread_create( tid, attr, func, arg) );
a9efe6 }
0eaf5a
ac314a void
5a5c47 PGPThreadYield()
30bb36 {
--2222 000a3a49a2540100100 Page 3 of pgpThreads.c
f9830f ¤   return;
38efe6 }
44af5a
59314a void
031ab9 PGPThreadExit(PGPThread_t tid)
cbbb36 {
2942d4 ¤   pthread_exit( NULL );
aeefe6 }
4baf5a
ee314a void
f94478 PGPThreadJoin( PGPThread_t tid, int *status )
d5bb36 {
4578ab ¤   pthread_join( tid, (void **) status );
c7efe6 }
ecaf5a
96314a void
c963ef PGPThreadKill( PGPThread_t tid, int sig )
dabb36 {
a4f9e8 ¤   pthread_kill( tid, sig );
42efe6 }
1daf5a
d74d2f int
43c19a PGPThreadKeyCreate(PGPThreadKey_t *key, void (*destructor)(void* value))
d9bb36 {
42d42f ¤   return pthread_key_create(key, destructor);
64efe6 }
9faf5a
314d2f int
5a2afe PGPThreadGetSpecific(PGPThreadKey_t key, void **value)
e5bb36 {
b628f9 ¤   *value = pthread_getspecific(key);
375690 ¤   return (int)*value;
37efe6 }
02af5a
054d2f int
a1a5b6 PGPThreadSetSpecific(PGPThreadKey_t key, void *value)
c4bb36 {
33c001 ¤   return pthread_setspecific(key, value);
c8efe6 }
5faf5a
e14d2f int
c06b8c PGPThreadKeyDelete(PGPThreadKey_t key)
4dbb36 {
76e218 ¤   return pthread_key_delete(key);
4defe6 }
0d460a #endif /* HAVE_PTREAD_CREATE */
3faf5a
48350c #if HAVE_THREAD_ATTR_CREATE
92af5a
1933d4 /***********************************************************************
0c43ad ·*¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·*
4f7e9a ·* pthreads package with DCE - no mapping to do (except to create a¤*
58ce78 ·* pthread_kill() routine)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·*
0a43ad ·*¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·*
78475c ·***********************************************************************/
87af5a
fe0873 /* ARGSUSED */
10314a void
6f9a25 PGPThreadKill( pthread_t tid, int sig )
91bb36 {
d8dc8d ¤   kill( getpid(), sig );
88efe6 }
d7af5a
0a394e #endif /* HAVE_THREAD_ATTR_CREATE (DCE THREADS) */
5faf5a
92afb9 #if PGP_WIN32
0baf5a
b811a9 #include <process.h>
eb5655 #include <windows.h>
2aaf5a
894d2f int
a36845 PGPThreadAttrCreate( PGPThreadAttr_t *attr )
--04eb 000ca5b29a740100100 Page 4 of pgpThreads.c
2cbb36 {
adf542 ¤   *attr = 0;
15ea61 ¤   return( 0 );
ecefe6 }
f2af5a
234d2f int
1cf470 PGPThreadAttrDestroy( PGPThreadAttr_t *attr )
22bb36 {
4cea61 ¤   return( 0 );
4eefe6 }
2baf5a
9b4d2f int
090d72 PGPThreadAttrGetDetachState( PGPThreadAttr_t *attr, int *detachstate )
11bb36 {
9c6a3a ¤   *detachstate = *attr;
c2ea61 ¤   return( 0 );
c8efe6 }
0faf5a
414d2f int
34076d PGPThreadAttrSetDetachState( PGPThreadAttr_t *attr, int detachstate )
86bb36 {
67e1f7 ¤   *attr = detachstate;
47ea61 ¤   return( 0 );
2aefe6 }
e4af5a
530873 /* ARGSUSED */
3c4d2f int
2cbda3 PGPThreadCreate(
764d59 ¤   PGPThread_t¤¤   *tid,
fca009 ¤   PGPThreadAttr_t¤*attr,
2c462e ¤   VFP¤¤   ¤   func,
d2b9f0 ¤   void¤   ¤   *arg
6e27e6 ¤   )
e9bb36 {
78d710 ¤   unsigned hack;
afaf5a
27a4c0 ¤   *tid = (HANDLE) _beginthreadex(NULL, 0, func, arg, 0, &hack);
b77290 /*¤ tid = CreateThread(NULL, 0, func, arg, 0, &threadID); */
df67c5 ¤
98b3b8 ¤   return !(*tid);
d0efe6 }
b7af5a
63314a void
315c47 PGPThreadYield()
08bb36 {
23830f ¤   return;
f8efe6 }
d4af5a
73314a void
ab1ab9 PGPThreadExit(PGPThread_t tid)
3fbb36 {
388e52 ¤   _endthreadex(0);
976b98 ¤   CloseHandle(tid);
5defe6 }
0daf5a
bb314a void
054478 PGPThreadJoin( PGPThread_t tid, int *status )
5ebb36 {
70a5d0 ¤   int rc;
0367c5 ¤
e4081d ¤   rc = WaitForSingleObject((HANDLE) tid, INFINITE);
da67c5 ¤
cc830f ¤   return;
5cefe6 }
b5af5a
240873 /* ARGSUSED */
9d314a void
a9fade PGPTKill( PGPThread_t tid, int sig )
fdbb36 {
6a88ca ¤   /* !!! Don't know how to kill a thread created with beginthread. */
a1d76d ¤   /* Seems to only be done when the server is coming down due to error. */
ca830f ¤   return;
--d27c 0003888a1fb40100100 Page 5 of pgpThreads.c
7aefe6 }
46af5a
c94d2f int
b0c19a PGPThreadKeyCreate(PGPThreadKey_t *key, void (*destructor)(void* value))
e1bb36 {
082e18 ¤   *key = TlsAlloc();
932e83 ¤   if (*key == 0xFFFFFFFF)
24043c ¤   ¤   return -1;
720e24 ¤   else
e5bbde ¤   ¤   return 0;
00efe6 }
0eaf5a
fa4d2f int
a42afe PGPThreadGetSpecific(PGPThreadKey_t key, void **value)
86bb36 {
0ee635 ¤   *value = TlsGetValue(key);
9dc84f ¤   if (*value)
f1bbde ¤   ¤   return 0;
c70e24 ¤   else
0e043c ¤   ¤   return -1;
7eefe6 }
a3af5a
6c4d2f int
efa5b6 PGPThreadSetSpecific(PGPThreadKey_t key, void *value)
01bb36 {
dd1ce4 ¤   return !(TlsSetValue(key, value));
4defe6 }
43af5a
814d2f int
df6b8c PGPThreadKeyDelete(PGPThreadKey_t key)
6dbb36 {
23f3f4 ¤   return !(TlsFree(key));
09efe6 }
e7af5a
158df7 #endif /* PGP_WIN32 */
52af5a
b51808 #ifndef _PGP_THREAD
c0af5a
e60873 /* ARGSUSED */
064d2f int
f46845 PGPThreadAttrCreate( PGPThreadAttr_t *attr )
79bb36 {
0cea61 ¤   return( 0 );
15efe6 }
68af5a
f40873 /* ARGSUSED */
d24d2f int
52f470 PGPThreadAttrDestroy( PGPThreadAttr_t *attr )
4ebb36 {
f6ea61 ¤   return( 0 );
e4efe6 }
caaf5a
b80873 /* ARGSUSED */
de4d2f int
5f0d72 PGPThreadAttrGetDetachState( PGPThreadAttr_t *attr, int *detachstate )
7abb36 {
5cea61 ¤   return( 0 );
f1efe6 }
ebaf5a
1a0873 /* ARGSUSED */
f24d2f int
d0076d PGPThreadAttrSetDetachState( PGPThreadAttr_t *attr, int detachstate )
33bb36 {
c7ea61 ¤   return( 0 );
e3efe6 }
53af5a
280873 /* ARGSUSED */
7d4d2f int
79bda3 PGPThreadCreate(
324d59 ¤   PGPThread_t¤¤   *tid,
07a009 ¤   PGPThreadAttr_t¤*attr,
38462e ¤   VFP¤¤   ¤   func,
--983e 0016868bd7d40100100 Page 6 of pgpThreads.c
1cb9f0 ¤   void¤   ¤   *arg
d127e6 ¤   )
6abb36 {
ab8af7 ¤   (*func)( arg );
0667c5 ¤
f9ea61 ¤   return( 0 );
b5efe6 }
bdaf5a
f8314a void
645c47 PGPThreadYield()
97bb36 {
14830f ¤   return;
08efe6 }
59af5a
39314a void
bd1ab9 PGPThreadExit(PGPThread_t tid)
bebb36 {
df830f ¤   return;
46efe6 }
75af5a
020873 /* ARGSUSED */
88314a void
d763ef PGPThreadKill( PGPThread_t tid, int sig )
54bb36 {
7b830f ¤   return;
d5efe6 }
13af5a
a1314a void
564478 PGPThreadJoin( PGPThread_t tid, int *status )
c8bb36 {
49830f ¤   return;
c5efe6 }
7e4d2f int
48c19a PGPThreadKeyCreate(PGPThreadKey_t *key, void (*destructor)(void* value))
dcbb36 {
e73e6b ¤   return 0;
c3efe6 }
31af5a
c44d2f int
ac2afe PGPThreadGetSpecific(PGPThreadKey_t key, void **value)
bcbb36 {
313e6b ¤   return 0;
b3efe6 }
f7af5a
ef4d2f int
fda5b6 PGPThreadSetSpecific(PGPThreadKey_t key, void *value)
b5bb36 {
8b3e6b ¤   return 0;
19efe6 }
aeaf5a
c24d2f int
6c6b8c PGPThreadKeyDelete(PGPThreadKey_t key)
93bb36 {
253e6b ¤   return 0;
8eefe6 }
a6af5a
68368e #endif /* no threads package */
--407e 0005a8cd3f040100101 Page 1 of pgpThreads.h
bc38e5 /*
bb9477 ·* pgpThreads.h
3d775e ·*
c6c7ea ·* NAI generic thread code.
a1775e ·*
db495d ·*/
bbaf5a
7ba9d8 #ifndef Included_pgpThreads_h
01fdec #define Included_pgpThreads_h
0caf5a
506e75 #ifndef PGP_MACINTOSH /* This threads lib is not supported by the Mac yet */
70af5a
8fe610 #include "pgpPFLConfig.h"
cfc5d5 #include "pgpBase.h"
3baf5a
42ab92 #ifdef _PGP_THREAD
b23ecf # undef _PGP_THREAD
317454 #endif
b3af5a
c4d399 #ifdef _PGP_SEMAPHORE
35c8e0 # undef _PGP_SEMAPHORE
907454 #endif
59af5a
6e38e5 /*
113d1c ·* On all platforms but Win32, cond variables can do broadcasts.
eab536 ·* cond_init2 needs to be special for Win32 to support broadcasts.
70797a ·* Use cond_init if you never need broadcast. ·Use cond_init2 if you
927f8b ·* ONLY do broadcasts.
3a495d ·*/
0a7158 #ifndef WIN32
e8ea05 # define PGPCondCreate2¤PGPCondCreate
8f7454 #endif
20af5a
b9ecf1 #if PGP_UNIX_SOLARIS
79af5a
36d8dd #include <thread.h>
b4b4ea #include <synch.h>
50af5a
ff118f #define _PGP_THREAD
8b6e6d #define _PGP_SEMAPHORE
9b05f9 #undef HAVE_PTHREAD_CREATE
646e2f #define HAVE_PTHREAD_CREATE 0¤  /* we also have this, but don't want it */
44fa15 #undef HAVE_SEMGET
bde7bb #define HAVE_SEMGET 0¤  ¤   /* don't want this either */
dbaf5a
563e1c typedef void¤   *(*VFP)();
82af5a
a93d6c /* solaris threads are preemptive */
3c3764 #define PGPTHREAD_PREEMPTIVE¤   1
7faf5a
73d7d9 /* default attr states */
d34893 #define PGPMutexAttr_default¤   NULL
e9d082 #define PGPCondAttr_default¤NULL
e1af5a
aea942 /* thread state - joinable or not */
1f2f46 #define PGPTHREAD_CREATE_JOINABLE 0
4d1369 #define PGPTHREAD_CREATE_DETACHED THR_DETACHED
69af5a
9f8c79 /* thread scope - who is in scheduling pool */
afe44f #define PGPTHREAD_SCOPE_PROCESS ··0
4c63bf #define PGPTHREAD_SCOPE_SYSTEM¤ THR_BOUND
1caf5a
8d38de /* mutex and condition variable scope - process or system */
8d4f01 #define PGPTHREAD_SHARE_PRIVATE ··USYNC_THREAD
fbdd32 #define PGPTHREAD_SHARE_PROCESS ··USYNC_PROCESS
07af5a
5bf9ea typedef int¤¤   PGPThreadAttr_t;
d4239d typedef thread_t¤   PGPThread_t;
ce37c7 typedef int¤¤   PGPMutexAttr_t;
e7cfb9 typedef mutex_t¤¤   PGPMutex_t;
abf4ba typedef int¤ ¤  PGPCondAttr_t;
5a5624 typedef cond_t¤ ¤   PGPCond_t;
--4985 000f60fdffd40100101 Page 2 of pgpThreads.h
b79272 typedef thread_key_t¤   PGPThreadKey_t;
b6e707 typedef sema_t ¤¤   PGPSem_t;
d395c9 typedef struct¤ ¤   PGPSemAttr_t {
1c1242 ¤   unsigned int count;
fb29f6 ¤   int type;
940e96 ¤   void *arg;
3f615c } PGPSemAttr_t;
24af5a
128fcf extern PGPSemAttr_t PGPSemAttr_def;
d4d7e7 #define PGPSemAttr_default &PGPSemAttr_def
7faf5a
5a622d #endif /* end PGP_UNIX_SOLARIS */
1baf5a
80093d #if HAVE_PTHREAD_CREATE
7baf5a
c00424 #include <pthread.h>
13af5a
22118f #define _PGP_THREAD
99af5a
0e4893 #define PGPMutexAttr_default¤   NULL
55d082 #define PGPCondAttr_default¤NULL
bdaf5a
873e1c typedef void¤   *(*VFP)();
f0af5a
f646fc #if PGP_UNIX_LINUX¤ /* I think Linux pthreads are preemptive */
4b8d8d # define PGPTHREAD_PREEMPTIVE¤  1
6bdb21 #else
889455 # define PGPTHREAD_PREEMPTIVE¤  0
987454 #endif
2caf5a
88d7d9 /* default attr states */
2a4893 #define PGPMutexAttr_default¤   NULL
dcd082 #define PGPCondAttr_default¤NULL
d7af5a
fba942 /* thread state - joinable or not */
b83f1c #define PGPTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
85c10c #define PGPTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
30af5a
af8c79 /* thread scope - who is in scheduling pool */
1905a1 #define PGPTHREAD_SCOPE_PROCESS ··PTHREAD_SCOPE_PROCESS
8ff445 #define PGPTHREAD_SCOPE_SYSTEM¤ PTHREAD_SCOPE_SYSTEM
4daf5a
2b38de /* mutex and condition variable scope - process or system */
e74637 #define PGPTHREAD_SHARE_PRIVATE ··0
f2a8e5 #define PGPTHREAD_SHARE_PROCESS ··0
e2af5a
53f00f typedef pthread_attr_t¤ ¤   PGPThreadAttr_t;
d39ac0 typedef pthread_t¤  ¤   PGPThread_t;
52a8a5 typedef pthread_mutex_t¤¤   PGPMutex_t;
59f056 typedef pthread_mutexattr_t¤PGPMutexAttr_t;
363312 typedef pthread_condattr_t¤ ·¤  PGPCondAttr_t;
906c00 typedef pthread_cond_t¤ ¤   PGPCond_t;
dcf4e4 typedef pthread_key_t¤  ¤   PGPThreadKey_t;
53af5a
0e1a03 #endif /* end PTHREAD_CREATE */
7caf5a
767508 #if HAVE_PTHREAD_ATTR_CREATE
8aaf5a
bd118f #define _PGP_THREAD
ceaf5a
7b0424 #include <pthread.h>
cfaf5a
079e18 /* dce threads are preemptive */
cc3764 #define PGPTHREAD_PREEMPTIVE¤   1
43af5a
fad7c1 #endif /* end HAVE_PTHREAD_ATTR_CREATE */
36af5a
9123be /* My version of Linux has sem_init in pthreads.so, but *zero* headers ?? */
fc7722 #if HAVE_SEM_INIT && !PGP_UNIX_LINUX
94af5a
264e7d #undef HAVE_SEMGET¤ /* prefer POSIX sem_init over semget */
f66d71 #define HAVE_SEMGET 0
--e179 00041a9f7f340100101 Page 3 of pgpThreads.h
e0af5a
266e6d #define _PGP_SEMAPHORE
6baf5a
32f20e typedef struct sem_t PGPSem_t;
99e007 typedef struct¤ ¤   ¤   PGPSemAttr_t {
02735c ¤   int shared;
8d55ca ¤   int value;
7c615c } PGPSemAttr_t;
e5af5a
8e8fcf extern PGPSemAttr_t PGPSemAttr_def;
13d7e7 #define PGPSemAttr_default &PGPSemAttr_def
3eaf5a
e47454 #endif
e4af5a
d9e29c #if HAVE_SEMGET
9caf5a
75f15e #include <sys/types.h>
b71ad5 #include <sys/ipc.h>
0c71c4 #include <sys/sem.h>
c2af5a
2e6e6d #define _PGP_SEMAPHORE
ceaf5a
2eba3a typedef int ·¤  ¤   ¤   PGPSem_t;
abe007 typedef struct¤ ¤   ¤   PGPSemAttr_t {
4c5058 ¤   int nsems;
5c29f6 ¤   int type;
39615c } PGPSemAttr_t;
f9af5a
d98fcf extern PGPSemAttr_t PGPSemAttr_def;
86d7e7 #define PGPSemAttr_default &PGPSemAttr_def
3caf5a
7d65a0 #endif /* HAVE_SEMGET */
feaf5a
2cafb9 #if PGP_WIN32
414a15 /***********************************
dd5d6d ·*¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·*
266813 ·* thread definitions for winnt¤*
635d6d ·*¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·*
16eeaf ·***********************************/
765655 #include <windows.h>
6aaf5a
81118f #define _PGP_THREAD
7f6e6d #define _PGP_SEMAPHORE
f6af5a
4eca50 typedef unsigned (__stdcall *VFP)(void *);
1108dc /* typedef DWORD WINAPI (*VFP)(LPVOID); */
daaf5a
e16e52 /* winnt threads are preemptive */
ed3764 #define PGPTHREAD_PREEMPTIVE¤   1
a2af5a
98d7d9 /* default attr states */
eb4893 #define PGPMutexAttr_default¤   NULL
27d082 #define PGPCondAttr_default¤NULL
78af5a
f7a942 /* thread state - joinable or not */
7dc61e #define PGPTHREAD_CREATE_JOINABLE¤  0
4574db #define PGPTHREAD_CREATE_DETACHED¤  1
77af5a
0d8c79 /* thread scope - who is in scheduling pool */
fbc4fc #define PGPTHREAD_SCOPE_PROCESS¤0
1c8834 #define PGPTHREAD_SCOPE_SYSTEM¤ 1
82af5a
3f38de /* mutex and condition variable scope - process or system */
ce5734 #define PGPTHREAD_SHARE_PRIVATE¤0
16be7c #define PGPTHREAD_SHARE_PROCESS¤1
33af5a
88a70f typedef int¤PGPThreadAttr_t;
abadca typedef HANDLE¤ PGPThread_t;
45ba67 typedef int¤PGPCondAttr_t;
763973 typedef void¤   *PGPCond_t;
d9375b typedef int¤PGPMutexAttr_t;
41a345 typedef HANDLE ·PGPMutex_t;
--849d 000e0363bb740100101 Page 4 of pgpThreads.h
25757a typedef DWORD¤  PGPThreadKey_t;
0dfac6 typedef HANDLE¤ PGPSem_t;
6fa92c typedef struct PGPSemAttr_t {
b6348b ¤   int icount;
94d8d0 ¤   int max;
f52d7d ¤   char *name;
0b615c } PGPSemAttr_t;
25af5a
dd8fcf extern PGPSemAttr_t PGPSemAttr_def;
13d7e7 #define PGPSemAttr_default &PGPSemAttr_def
d3af5a
ccf277 #endif /* winnt threads */
1eaf5a
5d1808 #ifndef _PGP_THREAD
0daf5a
4f3e1c typedef void¤   *(*VFP)();
48af5a
c2d7d9 /* default attr states */
2d4893 #define PGPMutexAttr_default¤   NULL
3ed082 #define PGPCondAttr_default¤NULL
50af5a
29a942 /* thread state - joinable or not */
40df62 #define PTHREAD_CREATE_JOINABLE 0
ddb746 #define PTHREAD_CREATE_DETACHED 0
018c79 /* thread scope - who is in scheduling pool */
c3146b #define PTHREAD_SCOPE_PROCESS ··0
359f05 #define PTHREAD_SCOPE_SYSTEM¤   0
70af5a
8438de /* mutex and condition variable scope - process or system */
d6b613 #define PTHREAD_SHARE_PRIVATE ··0
7458c1 #define PTHREAD_SHARE_PROCESS ··0
66af5a
36375b typedef int¤PGPMutexAttr_t;
be5770 typedef int¤PGPMutex_t;
fca70f typedef int¤PGPThreadAttr_t;
85fc52 typedef int¤PGPThread_t;
bab610 typedef int PGPCondAttr_t;
f1c62d typedef int¤PGPCond_t;
c50ae1 typedef int PGPThreadKey_t;
e5af5a
d31066 #endif /* no threads support */
66af5a
7e399c #ifndef _PGP_SEMAPHORE
baaf5a
0d2f51 typedef int PGPSem_t;
e6e2a9 typedef int PGPSemAttr_t;
13af5a
1f33e0 #define PGPSemAttr_default 0
00af5a
d2f7ab #endif /* no semaphores */
59af5a
5338e5 /*
fa35d1 ·* PGPthreads
a7495d ·*/
1daf5a
1e99c6 PGP_BEGIN_C_DECLARATIONS
c8af5a
50c130 int PGPThreadAttrCreate( PGPThreadAttr_t *attr );
73b483 int PGPThreadAttrDestroy( PGPThreadAttr_t *attr );
91042c int PGPThreadAttrGetDetachState( PGPThreadAttr_t *attr, int *detachstate );
4899f2 int PGPThreadAttrSetDetachState( PGPThreadAttr_t *attr, int detachstate );
62af5a
b4cbca int PGPThreadCreate(PGPThread_t *t, PGPThreadAttr_t *attr, VFP func, void *arg);
794661 void PGPThreadYield(void);
e81a6e void PGPThreadExit(PGPThread_t tid);
d73a6c void PGPThreadJoin( PGPThread_t tid, int *status );
75018b void PGPThreadKill( PGPThread_t tid, int sig );
f4af5a
de79e3 int PGPMutexCreate( PGPMutex_t *mp, PGPMutexAttr_t *attr );
0ee18e int PGPMutexDestroy( PGPMutex_t *mp );
2ca80b int PGPMutexLock( PGPMutex_t *mp );
e03e49 int PGPMutexUnlock( PGPMutex_t *mp );
--88ce 001ddef903a40100101 Page 5 of pgpThreads.h
cbbc1c int PGPMutexTryLock( PGPMutex_t *mp );
56af5a
636461 int PGPSemCreate(PGPSem_t *ms, PGPSemAttr_t *attr);
7db236 int PGPSemWait(PGPSem_t *ms);
bae552 int PGPSemTryWait(PGPSem_t *ms);
198720 int PGPSemPost(PGPSem_t *ms);
f72e41 int PGPSemDestroy(PGPSem_t *ms);
84af5a
3ff5b3 int PGPCondCreate( PGPCond_t *cv, PGPCondAttr_t *attr );
f7afb9 #if PGP_WIN32
f6c408 ·int PGPCondCreate2( PGPCond_t *cv, PGPCondAttr_t *attr );
7d7454 #endif
18ecfa int PGPCondDestroy( PGPCond_t *cv );
287259 int PGPCondWait( PGPCond_t *cv, PGPMutex_t *mp );
f3063c int PGPCondSignal( PGPCond_t *cv );
b7172c int PGPCondBroadcast( PGPCond_t *cv );
75af5a
9fb393 int PGPThreadKeyCreate(PGPThreadKey_t *key, void (*destructor)(void*value));
11f1c6 int PGPThreadGetSpecific(PGPThreadKey_t key, void **value);
bfa350 int PGPThreadSetSpecific(PGPThreadKey_t key, void *value);
787e2f int PGPThreadKeyDelete(PGPThreadKey_t key);
faaf5a
261254 PGP_END_C_DECLARATIONS
d1af5a
2abb8e #endif /* PGP_MACINTOSH */
dde290 #endif /* Included_pgpThreads_h */
--0378 0019b7ad9d640100102 Page 1 of Makefile.in
5ea601 #
120073 # common/prefs/
cfa601 #
d2d218 # $Id: Makefile.in,v 1.2 1997/07/28 23:46:34 mhw Exp $
c6a601 #
7baf5a
ad4bc5 OBJS= pflPrefTypes.o pflPrefs.o
19af5a
1eb7a3 all:: DONE
9baf5a
--7c60 00040bc9d6740100103 Page 1 of pflPrefTypes.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
d4b2b7 ¤   $Id: pflPrefTypes.c,v 1.18.16.1 1998/11/12 03:18:33 heller Exp $
92f7f7 ____________________________________________________________________________*/
66324c #include <string.h>
10af5a
d94720 #include "pflPrefTypes.h"
432b62 #include "pgpPFLErrors.h"
7aa146 #include "pgpDebug.h"
cc0d08 #include "pgpMem.h"
853d4b #include "pgpEndianConversion.h"
25af5a
dc4131 #define kPGPPrefsEndian¤¤   kPGPBigEndian
9aaf5a
6aaf5a
77c62f PGPError PGPGetPrefBoolean(PGPPrefRef prefRef,
728891 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex,
f90b40 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPBoolean *data)
f4bb36 {
6ad065 ¤   void *¤ ¤   ¤   tempData;
44a12a ¤   PGPSize¤¤   ¤   dataLength;
7efb19 ¤   PGPError¤   ¤   err;
b6af5a
41943e ¤   if (IsntNull(data))
dd87b9 ¤   ¤   *data = FALSE;
f51b52 ¤   ¤
20403b ¤   PGPValidatePtr(data);
4daf5a
08deb8 ¤   err = PGPGetPrefData(prefRef, prefIndex, &dataLength, &tempData);
d682f0 ¤   if (IsPGPError(err))
92c9db ¤   ¤   return err;
d2af5a
08542d ¤   pgpAssert(dataLength == sizeof(PGPBoolean));
b975f3 ¤   if (dataLength != sizeof(PGPBoolean))
26c7a1 ¤   {
f53217 ¤   ¤   PGPDisposePrefData(prefRef, tempData);
5762b5 ¤   ¤   return kPGPError_BadParams;
a79371 ¤   }
0daf5a
84bb6a ¤   *data = *(PGPBoolean *)tempData;
daa38f ¤   PGPDisposePrefData(prefRef, tempData);
45af5a
e95ea8 ¤   return err;
84efe6 }
ccaf5a
3eaf5a
e1215b PGPError PGPSetPrefBoolean(PGPPrefRef prefRef,
ee8891 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex,
bd8f77 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPBoolean data)
dfbb36 {
600040 ¤   PGPError err;
d3af5a
623609 ¤   err = PGPSetPrefData(prefRef, prefIndex, sizeof(PGPBoolean), &data);
f7af5a
c25ea8 ¤   return err;
b0efe6 }
aaaf5a
00af5a
8e3a2e PGPError PGPGetPrefNumber(PGPPrefRef prefRef,
5ac957 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPPrefIndex prefIndex,
615769 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPUInt32 *data)
92bb36 {
766228 ¤   void *¤ ¤   tempData;
dbf810 ¤   PGPSize¤¤   dataLength;
ef61e0 ¤   PGPError¤   err;
cdaf5a
57943e ¤   if (IsntNull(data))
401b71 ¤   ¤   *data = 0;
--8ec3 0005484c3e040100103 Page 2 of pflPrefTypes.c
e0af5a
fe403b ¤   PGPValidatePtr(data);
71af5a
7cdeb8 ¤   err = PGPGetPrefData(prefRef, prefIndex, &dataLength, &tempData);
9282f0 ¤   if (IsPGPError(err))
35c9db ¤   ¤   return err;
63af5a
19c0af ¤   pgpAssert(dataLength == sizeof(PGPUInt32));
8122dd ¤   if (dataLength != sizeof(PGPUInt32))
7cc7a1 ¤   {
e63217 ¤   ¤   PGPDisposePrefData(prefRef, tempData);
e162b5 ¤   ¤   return kPGPError_BadParams;
b29371 ¤   }
30af5a
66c8b4 ¤   *data = PGPEndianToUInt32(kPGPPrefsEndian, (PGPByte *)tempData);
dca38f ¤   PGPDisposePrefData(prefRef, tempData);
62af5a
555ea8 ¤   return err;
9aefe6 }
a9af5a
f1af5a
7940ce PGPError PGPSetPrefNumber(PGPPrefRef prefRef,
80c957 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPPrefIndex prefIndex,
2853c9 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPUInt32 data)
3ebb36 {
7961e0 ¤   PGPError¤   err;
22bacf ¤   PGPByte ¤   tempData[sizeof(PGPUInt32)];
97af5a
60e831 ¤   PGPUInt32ToEndian(data, kPGPPrefsEndian, tempData);
7dc4ff ¤   err = PGPSetPrefData(prefRef, prefIndex, sizeof(PGPUInt32), tempData);
875ea8 ¤   return err;
61efe6 }
82af5a
adaf5a
dfe6bb PGPError PGPGetPrefStringAlloc(PGPPrefRef prefRef,
9499b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex,
42e97e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···char **string)
b2bb36 {
9b61e0 ¤   PGPError¤   err;
3425c7 ¤   void *¤ ¤   data¤   ¤   ¤   = NULL;
fc55f5 ¤   PGPSize¤¤   stringLength¤   = 0;
69af5a
b2a3c0 ¤   if (IsntNull(string))
ddd2eb ¤   ¤   *string = NULL;
a8af5a
141127 ¤   PGPValidatePtr(string);
54af5a
47dabd ¤   err = PGPGetPrefData(prefRef, prefIndex, &stringLength, &data);
62f69b ¤   if (IsntPGPError(err))
6ac7a1 ¤   {
e618b4 ¤   ¤   *string¤= (char *)data;
7c9371 ¤   }
bb67c5 ¤
485ea8 ¤   return err;
6eefe6 }
45af5a
40af5a
9cf9d2 PGPError PGPGetPrefStringBuffer(PGPPrefRef prefRef,
0f4ed5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,
8d861f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize maxSize,
18a5b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char *string)
1abb36 {
d561e0 ¤   PGPError¤   err;
0bd102 ¤   void *¤ ¤   tempString;
6896a8 ¤   PGPSize¤¤   tempLength;
a7af5a
728a6a ¤   if (IsntNull(string) && (maxSize > 0))
a275b8 ¤   ¤   string[0] = '\0';
bcaf5a
bf1127 ¤   PGPValidatePtr(string);
5a9e52 ¤   PGPValidateParam(maxSize > 0);
54af5a
--27e0 0013f4205fe40100103 Page 3 of pflPrefTypes.c
9036d6 ¤   err = PGPGetPrefData(prefRef, prefIndex, &tempLength, &tempString);
f882f0 ¤   if (IsPGPError(err))
7ac9db ¤   ¤   return err;
0aaf5a
257cec ¤   if (tempLength > maxSize)
54c7a1 ¤   {
b7be5b ¤   ¤   tempLength = maxSize;
ca4718 ¤   ¤   string[tempLength-1] = 0;
db9371 ¤   }
e3af5a
391df7 ¤   pgpCopyMemory(tempString, string, tempLength);
4299bc ¤   PGPDisposePrefData(prefRef, tempString);
f467c5 ¤
645ea8 ¤   return err;
e8efe6 }
6aaf5a
a5af5a
fb6ba0 PGPError PGPSetPrefString(PGPPrefRef prefRef,
0ec957 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPPrefIndex prefIndex,
07f7a0 ¤   ¤   ¤   ¤   ¤   ¤   ··const char *string)
29bb36 {
db61e0 ¤   PGPError¤   err;
dfb724 ¤   PGPSize¤¤   stringLength;
edaf5a
121127 ¤   PGPValidatePtr(string);
2267c5 ¤
89d4f8 ¤   stringLength = strlen(string)+1;¤   /* Include null terminator */
43af5a
b2e4ad ¤   err = PGPSetPrefData(prefRef, prefIndex, stringLength, string);
865ea8 ¤   return err;
9aefe6 }
c5af5a
03af5a
2d7e4d /*__Editor_settings____
6eaf5a
ae4126 ¤   Local Variables:
e47b17 ¤   tab-width: 4
ab0e6c ¤   End:
f15f8c ¤   vi: ts=4 sw=4
159e9b ¤   vim: si
61d062 _____________________*/
f7af5a
3faf5a
--dcc3 0018fbdd0e740100104 Page 1 of pflPrefTypes.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
3dbb75 ¤   $Id: pflPrefTypes.h,v 1.9.30.1 1998/11/12 03:18:34 heller Exp $
e4f7f7 ____________________________________________________________________________*/
1db95f #ifndef Included_pflPrefTypes_h¤/* [ */
3518e0 #define Included_pflPrefTypes_h
07af5a
92c5d5 #include "pgpBase.h"
de2b62 #include "pgpPFLErrors.h"
3fe8b2 #include "pflPrefs.h"
43af5a
b099c6 PGP_BEGIN_C_DECLARATIONS
14cbcf #if PRAGMA_IMPORT_SUPPORTED
f3b981 #pragma import on
d87454 #endif
84af5a
6daf5a
52af5a
c8c62f PGPError PGPGetPrefBoolean(PGPPrefRef prefRef,
9f4ed5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,
f5bb9d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *data);
91af5a
7b215b PGPError PGPSetPrefBoolean(PGPPrefRef prefRef,
1a4ed5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,
b94a89 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean data);
02af5a
423a2e PGPError PGPGetPrefNumber(PGPPrefRef prefRef,
0c99b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex,
0a1370 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPUInt32 *data);
05af5a
4e40ce PGPError PGPSetPrefNumber(PGPPrefRef prefRef,
ca99b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex,
06c5f4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPUInt32 data);
08af5a
2ee6bb PGPError PGPGetPrefStringAlloc(PGPPrefRef prefRef,
adc182 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,
e22c98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char **string);
faaf5a
b2f9d2 PGPError PGPGetPrefStringBuffer(PGPPrefRef prefRef,
89c182 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,
e9d504 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize maxSize,
412b98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char *string);
0caf5a
366ba0 PGPError PGPSetPrefString(PGPPrefRef prefRef,
c199b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex,
80f6a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···const char *string);
60af5a
d3af5a
b4af5a
9dcbcf #if PRAGMA_IMPORT_SUPPORTED
d02ced #pragma import reset
7e7454 #endif
901254 PGP_END_C_DECLARATIONS
53af5a
9353bf #endif /* ] Included_pflPrefTypes_h */
fbaf5a
23af5a
687e4d /*__Editor_settings____
bfaf5a
9b4126 ¤   Local Variables:
707b17 ¤   tab-width: 4
7e0e6c ¤   End:
9a5f8c ¤   vi: ts=4 sw=4
9f9e9b ¤   vim: si
8fd062 _____________________*/
--a93e 0007173183f40100105 Page 1 of pflPrefs.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
0baa3e ¤   $Id: pflPrefs.c,v 1.19.14.1 1998/11/12 03:18:35 heller Exp $
39f7f7 ____________________________________________________________________________*/
ecaf5a
f3feb2 #include <stdio.h>
63324c #include <string.h>
8eaf5a
736773 #include "pgpMemoryMgr.h"
64e8b2 #include "pflPrefs.h"
d90d08 #include "pgpMem.h"
17a146 #include "pgpDebug.h"
132b62 #include "pgpPFLErrors.h"
903427 #include "pgpFileUtilities.h"
2c3d4b #include "pgpEndianConversion.h"
d5af5a
05ccf6 typedef struct PGPPrefData¤ PGPPrefData;
c057bc typedef struct PGPPref¤ ¤   PGPPref;
58af5a
ad4131 #define kPGPPrefsEndian¤¤   kPGPBigEndian
88d90c #define kPGPPrefsMagic¤ ¤   0x155A1326
53af5a
32f772 struct PGPPrefData
1cbb36 {
7857ef ¤   PGPPrefIndex¤   prefIndex;
73a12a ¤   PGPSize¤¤   ¤   dataLength;
cbdef2 ¤   void *¤ ¤   ¤   dataBuffer;
70af5a
4dc2cf ¤   PGPPrefData *¤  nextPrefData;
7fa4ad ¤   PGPPrefData *¤  lastPrefData;
cf82f7 };
0aaf5a
7b92a5 struct PGPPref·
93bb36 {
b8d91c ¤   PGPMemoryMgrRef¤memoryMgr;
71bd58 ¤   PFLFileSpecRef¤ prefFileSpec;
83af5a
55ef63 ¤   PGPPrefData *¤  prefList;
6e8447 ¤   PGPPrefData *¤  prefListEnd;
3782f7 };
2daf5a
41af5a
22847e #define PGPValidatePref(prefRef)¤   ¤   PGPValidateParam(prefRef != NULL)
9baf5a
d278d2 static PGPError pgpFindPrefData(PGPPrefRef prefRef,·
b7a422 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,·
6f5cc3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefData **prefData);
a3af5a
fda6b3 static PGPError pgpCalcPrefFileSize(PGPPrefRef prefRef, PGPUInt32 *size);
29af5a
4fb4c1 static PGPError pgpFreePref(PGPPrefRef prefRef);
96af5a
aab291 static PGPError pgpAddPrefData(PGPPrefRef prefRef,·
9a3255 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefData *prefData);
36af5a
04bbe8 static PGPError pgpRemovePrefData(PGPPrefRef prefRef,·
2ccfc2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPPrefData *prefData);
adaf5a
5455b4 static PGPError pgpGetNextPrefData(const PGPPrefData *currentPrefData,·
b6a60f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefData **nextPrefData);
0faf5a
9a9dc4 static PGPError sIORead(PGPIORef fileIO, PGPSize dataSize,·
91cfaf ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, void *data);
4aaf5a
41b882 static PGPError sIOWrite(PGPIORef fileIO, PGPSize dataSize,·
4ade04 ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, const void *data);
c2af5a
71af5a
--03de 0009e944f9940100105 Page 2 of pflPrefs.c
369b45 PGPError PGPOpenPrefFile(PFLFileSpecRef prefFileSpec,·
2e199d ¤   ¤   ¤   ¤   ¤   ¤   ·const PGPPrefDefault *defaults,
a15c68 ¤   ¤   ¤   ¤   ¤   ¤   ·PGPUInt32 numDefaults,
27927a ¤   ¤   ¤   ¤   ¤   ¤   ·PGPPrefRef *prefRef)
8ebb36 {
4cf0bf ¤   PGPMemoryMgrRef¤memoryMgr¤  = NULL;
3e9e7d ¤   PGPIORef¤   ¤   prefIO;
b4d2fc ¤   PGPPrefIndex¤   newIndex;
49e939 ¤   PGPUInt32¤  ¤   index;
3b9d0d ¤   PGPUInt32¤  ¤   magic;
75a12a ¤   PGPSize¤¤   ¤   dataLength;
a5289e ¤   void *¤ ¤   ¤   newData¤¤   = NULL;
5f17b7 ¤   PGPPrefData *¤  newPrefData = NULL;
991613 ¤   PGPPrefData *¤  oldPrefData = NULL;
611cf5 ¤   PGPSize¤¤   ¤   bytesRead;
2efb19 ¤   PGPError¤   ¤   err;
5faf5a
292ab8 ¤   if (IsntNull(prefRef))
d97cca ¤   ¤   *prefRef = NULL;
e1af5a
2a2fb7 ¤   PGPValidatePtr(prefRef);
2f5a6f ¤   PFLValidateFileSpec(prefFileSpec);
c6af5a
2228d6 ¤   memoryMgr = PFLGetFileSpecMemoryMgr( prefFileSpec );
c967c5 ¤
1cae4e ¤   pgpAssert(PGPMemoryMgrIsValid(memoryMgr));
23dbbb ¤   if (!PGPMemoryMgrIsValid(memoryMgr))
c362b5 ¤   ¤   return kPGPError_BadParams;
eaaf5a
076df4 ¤   *prefRef = (PGPPrefRef) PGPNewData(memoryMgr,·
10a0ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPPref),·
b4e0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
beaf5a
b50a0b ¤   pgpAssert(IsntNull(*prefRef));
c0f6d6 ¤   if (IsNull(*prefRef))
d64030 ¤   ¤   return kPGPError_OutOfMemory;
f8af5a
117a9a ¤   (*prefRef)->memoryMgr¤  ¤   = memoryMgr;
d137a0 ¤   (*prefRef)->prefFileSpec¤   = NULL;
43d063 ¤   (*prefRef)->prefList¤   ¤   = NULL;
3eb588 ¤   (*prefRef)->prefListEnd¤¤   = NULL;
15af5a
4e364f ¤   err = PFLCopyFileSpec(prefFileSpec, &((*prefRef)->prefFileSpec));
6e82f0 ¤   if (IsPGPError(err))
06c7a1 ¤   {
16a0ad ¤   ¤   pgpFreePref(*prefRef);
9a7cca ¤   ¤   *prefRef = NULL;
c4c9db ¤   ¤   return err;
569371 ¤   }
0faf5a
362d8f ¤   err = PGPOpenFileSpec(¤ (*prefRef)->prefFileSpec,·
de241d ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPFLFileOpenFlags_ReadOnly,·
07b278 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPFileIORef *) &prefIO);
9f67c5 ¤
6b512b ¤   if ((err != kPGPError_FileNotFound) && (err != kPGPError_FileOpFailed))
dcc7a1 ¤   {
59b6ad ¤   ¤   if (IsPGPError(err))
985b34 ¤   ¤   {
102cd2 ¤   ¤   ¤   pgpFreePref(*prefRef);
f34897 ¤   ¤   ¤   *prefRef = NULL;
9bb32f ¤   ¤   ¤   return err;
de0fe4 ¤   ¤   }
ef1b52 ¤   ¤
a9d6a3 ¤   ¤   pgpAssert(PGPIOIsValid(prefIO));
a297ec ¤   ¤   if (!PGPIOIsValid(prefIO))
435b34 ¤   ¤   {
a62cd2 ¤   ¤   ¤   pgpFreePref(*prefRef);
304897 ¤   ¤   ¤   *prefRef = NULL;
bd7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
da0fe4 ¤   ¤   }
151b52 ¤   ¤
9e66fb ¤   ¤   if (!PGPIOIsAtEOF(prefIO))
--7a21 0004315a77440100105 Page 3 of pflPrefs.c
e35b34 ¤   ¤   {
2f4252 ¤   ¤   ¤   err = sIORead(prefIO, sizeof(PGPUInt32), TRUE, &magic);
7c0abb ¤   ¤   ¤   if (magic != kPGPPrefsMagic)
d47300 ¤   ¤   ¤   ¤   err = PGPIOSetPos(prefIO, 0);
ff0fe4 ¤   ¤   }
d01b52 ¤   ¤
2bc4b1 ¤   ¤   while (!PGPIOIsAtEOF(prefIO) && IsntPGPError(err))
ec5b34 ¤   ¤   {
7375b4 ¤   ¤   ¤   newData = NULL;
49bc22 ¤   ¤   ¤   newPrefData = NULL;
5f87c7 ¤   ¤   ¤
2991b8 ¤   ¤   ¤   if (magic == kPGPPrefsMagic)
c486ab ¤   ¤   ¤   ¤   err = sIORead(prefIO, sizeof(PGPPrefIndex), TRUE, &newIndex);
43bb8c ¤   ¤   ¤   else
e7ccea ¤   ¤   ¤   ¤   err = PGPIORead(prefIO, sizeof(PGPPrefIndex), &newIndex,·
641b61 ¤   ¤   ¤   ¤   &bytesRead);
be87c7 ¤   ¤   ¤
230dfb ¤   ¤   ¤   if (IsPGPError(err))
c1f622 ¤   ¤   ¤   ¤   break;
d387c7 ¤   ¤   ¤
3f91b8 ¤   ¤   ¤   if (magic == kPGPPrefsMagic)
dd1603 ¤   ¤   ¤   ¤   err = sIORead(prefIO, sizeof(PGPSize), TRUE, &dataLength);
1bbb8c ¤   ¤   ¤   else
e420e5 ¤   ¤   ¤   ¤   err = PGPIORead(prefIO, sizeof(PGPSize), &dataLength,·
729d5f ¤   ¤   ¤   ¤   ¤   ¤   &bytesRead);
0b87c7 ¤   ¤   ¤
a60dfb ¤   ¤   ¤   if (IsPGPError(err))
69f622 ¤   ¤   ¤   ¤   break;
3287c7 ¤   ¤   ¤
924a9c ¤   ¤   ¤   newData = PGPNewData(memoryMgr,·
35f8b3 ¤   ¤   ¤   ¤   dataLength,·
2dbff7 ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
4087c7 ¤   ¤   ¤
cbb3a0 ¤   ¤   ¤   if (IsNull(newData))
45f776 ¤   ¤   ¤   {
5dbfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
01f622 ¤   ¤   ¤   ¤   break;
92a3a6 ¤   ¤   ¤   }
6b87c7 ¤   ¤   ¤
2d91b8 ¤   ¤   ¤   if (magic == kPGPPrefsMagic)
03e336 ¤   ¤   ¤   ¤   err = sIORead(prefIO, dataLength, FALSE, newData);
e9bb8c ¤   ¤   ¤   else
49f157 ¤   ¤   ¤   ¤   err = PGPIORead(prefIO, dataLength, newData, &bytesRead);
df87c7 ¤   ¤   ¤
3f0dfb ¤   ¤   ¤   if (IsPGPError(err))
f6f622 ¤   ¤   ¤   ¤   break;
4f87c7 ¤   ¤   ¤
472c4e ¤   ¤   ¤   newPrefData = (PGPPrefData *) PGPNewData(memoryMgr,
ed9e46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPPrefData),
927e53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
99fc54 ¤   ¤   ¤   if (IsNull(newPrefData))
27f776 ¤   ¤   ¤   {
06bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
2ef622 ¤   ¤   ¤   ¤   break;
76a3a6 ¤   ¤   ¤   }
0087c7 ¤   ¤   ¤
09402e ¤   ¤   ¤   newPrefData->prefIndex¤ = newIndex;
6a7337 ¤   ¤   ¤   newPrefData->dataLength = dataLength;
a2b059 ¤   ¤   ¤   newPrefData->dataBuffer = newData;
e287c7 ¤   ¤   ¤
3ebabe ¤   ¤   ¤   pgpAddPrefData(*prefRef, newPrefData);
ae0fe4 ¤   ¤   }
2c1b52 ¤   ¤
5633b0 ¤   ¤   if (err == kPGPError_EOF)
3d5b34 ¤   ¤   {
d5d097 ¤   ¤   ¤   if (IsntNull(newData))
6eb4fd ¤   ¤   ¤   ¤   PGPFreeData( newData);
4087c7 ¤   ¤   ¤
9cfcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
f10fe4 ¤   ¤   }
ffa78c ¤   ¤   else if (IsPGPError(err))
435b34 ¤   ¤   {
--45e7 0001bd83ab840100105 Page 4 of pflPrefs.c
b9524f ¤   ¤   ¤   pgpAssertNoErr(err);
f22cd2 ¤   ¤   ¤   pgpFreePref(*prefRef);
f34897 ¤   ¤   ¤   *prefRef = NULL;
2e0fe4 ¤   ¤   }
111b52 ¤   ¤
5992ec ¤   ¤   PGPFreeIO(prefIO);
449371 ¤   }
380e24 ¤   else
8e70bb ¤   ¤   err = kPGPError_NoErr;
96af5a
7c3eea ¤   if ((numDefaults > 0) && IsntNull(defaults) && IsntPGPError(err))
57c7a1 ¤   {
83ef60 ¤   ¤   for (index=0; index<numDefaults; index++)
a35b34 ¤   ¤   {
03a478 ¤   ¤   ¤   err = pgpFindPrefData(*prefRef, defaults[index].index,·
962934 ¤   ¤   ¤   ¤   ¤   &oldPrefData);
15af5a
36524f ¤   ¤   ¤   pgpAssertNoErr(err);
c90dfb ¤   ¤   ¤   if (IsPGPError(err))
a6f622 ¤   ¤   ¤   ¤   break;
d3af5a
80384d ¤   ¤   ¤   if (IsNull(oldPrefData))
4cf776 ¤   ¤   ¤   {
061120 ¤   ¤   ¤   ¤   newPrefData = (PGPPrefData *) PGPNewData(memoryMgr,
3a1403 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPPrefData),
03aef8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
b12b85 ¤   ¤   ¤   ¤
75f9b9 ¤   ¤   ¤   ¤   if (IsNull(newPrefData))
f672c3 ¤   ¤   ¤   ¤   {
baed29 ¤   ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
a014c3 ¤   ¤   ¤   ¤   ¤   break;
bf2613 ¤   ¤   ¤   ¤   }
2d2b85 ¤   ¤   ¤   ¤
df64ad ¤   ¤   ¤   ¤   newPrefData->prefIndex = defaults[index].index;
1b2b85 ¤   ¤   ¤   ¤
da8cb9 ¤   ¤   ¤   ¤   switch (defaults[index].type)
9672c3 ¤   ¤   ¤   ¤   {
d93e74 ¤   ¤   ¤   ¤   case kPGPPrefType_Boolean:
714859 ¤   ¤   ¤   ¤   ¤   {
88142a ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ temp;
e9ae30 ¤   ¤   ¤   ¤   ¤
72376d ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength = sizeof(PGPBoolean);
8b75bf ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer = PGPNewData(memoryMgr,
b41ae3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength,
ecaef8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
b9af5a
311c87 ¤   ¤   ¤   ¤   ¤   temp = (PGPBoolean) (size_t) defaults[index].data;
c29f23 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory( &temp,
50d149 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer,
711ce8 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength);
a614c3 ¤   ¤   ¤   ¤   ¤   break;
821c89 ¤   ¤   ¤   ¤   ¤   }
c56e32 ¤   ¤   ¤   ¤   case kPGPPrefType_Number:
474859 ¤   ¤   ¤   ¤   ¤   {
06aaf1 ¤   ¤   ¤   ¤   ¤   PGPByte data32[sizeof(PGPUInt32)];
12af5a
9d2d2f ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength = sizeof(PGPUInt32);
1575bf ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer = PGPNewData(memoryMgr,
211ae3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength,
9faef8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
76af5a
d650e2 ¤   ¤   ¤   ¤   ¤   PGPUInt32ToEndian((PGPUInt32) defaults[index].data,·
a3479b ¤   ¤   ¤   ¤   ¤   ¤   kPGPPrefsEndian, data32);
80af5a
190998 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory(data32,
72d149 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer,
0e1ce8 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength);
1b14c3 ¤   ¤   ¤   ¤   ¤   break;
ae1c89 ¤   ¤   ¤   ¤   ¤   }
13ae30 ¤   ¤   ¤   ¤   ¤
6354aa ¤   ¤   ¤   ¤   case kPGPPrefType_String:
1bb91e ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength =·
--0425 0001fd627de40100105 Page 5 of pflPrefs.c
8077d7 ¤   ¤   ¤   ¤   ¤   ¤   strlen((char *) defaults[index].data) + 1;
6775bf ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer = PGPNewData(memoryMgr,
8f1ae3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength,
59aef8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
d0af5a
1799a0 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory(defaults[index].data,
36fa58 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer,·
d31ce8 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength);
6214c3 ¤   ¤   ¤   ¤   ¤   break;
07ae30 ¤   ¤   ¤   ¤   ¤
961d77 ¤   ¤   ¤   ¤   case kPGPPrefType_Byte:
a0123e ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength = defaults[index].size;
ca75bf ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer = PGPNewData(memoryMgr,
421ae3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength,
dfaef8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
2baf5a
f899a0 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory(defaults[index].data,
cfd149 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataBuffer,
101ce8 ¤   ¤   ¤   ¤   ¤   ¤   newPrefData->dataLength);
6e14c3 ¤   ¤   ¤   ¤   ¤   break;
f72613 ¤   ¤   ¤   ¤   }
f62b85 ¤   ¤   ¤   ¤
c2ab99 ¤   ¤   ¤   ¤   pgpAddPrefData(*prefRef, newPrefData);
0ea3a6 ¤   ¤   ¤   }
1b0fe4 ¤   ¤   }
cb9371 ¤   }
f5af5a
f16355 ¤   if ((magic != kPGPPrefsMagic) && IsntPGPError(err))
b7ee12 ¤   ¤   PGPSavePrefFile(*prefRef);
31af5a
fe5ea8 ¤   return err;
ecefe6 }
7caf5a
1faf5a
93035c PGPError PGPSavePrefFile(PGPPrefRef prefRef)
91bb36 {
bc95f0 ¤   PGPPrefData *¤  currentPrefData;
319e7d ¤   PGPIORef¤   ¤   prefIO;
4f71a0 ¤   PGPUInt32¤  ¤   prefFileSize;
1d9d0d ¤   PGPUInt32¤  ¤   magic;
04fb19 ¤   PGPError¤   ¤   err;
b000a6 ¤   PGPBoolean¤ ¤   fileExists;
a167c5 ¤
e8f814 ¤   PGPValidatePref(prefRef);
68af5a
41d0c5 ¤   pgpCalcPrefFileSize(prefRef, &prefFileSize);
8caf5a
c0da70 ¤   /* Create the file if it does not exist */
39f291 ¤   err = PFLFileSpecExists( prefRef->prefFileSpec, &fileExists );
f069c3 ¤   if( IsntPGPError( err ) && ! fileExists )
55c7a1 ¤   {
ac9212 ¤   ¤   err = PFLFileSpecCreate(prefRef->prefFileSpec);
039371 ¤   }
4f67c5 ¤
75dd44 ¤   pgpAssertNoErr(err);
2882f0 ¤   if (IsPGPError(err))
e0c9db ¤   ¤   return err;
4daf5a
4aea70 ¤   err = PGPSetFileSize(prefRef->prefFileSpec, prefFileSize);
78dd44 ¤   pgpAssertNoErr(err);
cc82f0 ¤   if (IsPGPError(err))
fcc9db ¤   ¤   return err;
59af5a
ecf195 ¤   err = PGPOpenFileSpec(¤ prefRef->prefFileSpec,·
06bb63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPFLFileOpenFlags_ReadWrite,·
c0b278 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPFileIORef *) &prefIO);
62dd44 ¤   pgpAssertNoErr(err);
b282f0 ¤   if (IsPGPError(err))
04c9db ¤   ¤   return err;
f9af5a
40d33f ¤   magic = kPGPPrefsMagic;
1fe9eb ¤   err = sIOWrite(prefIO, sizeof(PGPUInt32), TRUE, &magic);
--b7ae 000acdbcadb40100105 Page 6 of pflPrefs.c
e0af5a
87dd44 ¤   pgpAssertNoErr(err);
d282f0 ¤   if (IsPGPError(err))
0ac7a1 ¤   {
0392ec ¤   ¤   PGPFreeIO(prefIO);
acc9db ¤   ¤   return err;
fa9371 ¤   }
a8af5a
55146f ¤   currentPrefData = prefRef->prefList;
87af5a
80dbb2 ¤   while (IsntNull(currentPrefData))
82c7a1 ¤   {
fb1c23 ¤   ¤   err = sIOWrite(prefIO, sizeof(PGPPrefIndex), TRUE,
699cb5 ¤   ¤   ¤   ¤   &(currentPrefData->prefIndex));
62af5a
65e919 ¤   ¤   pgpAssertNoErr(err);
11b6ad ¤   ¤   if (IsPGPError(err))
21cdcb ¤   ¤   ¤   break;
39af5a
cc1954 ¤   ¤   err = sIOWrite(prefIO, sizeof(PGPSize), TRUE,
454c19 ¤   ¤   ¤   ¤   &(currentPrefData->dataLength));
efaf5a
bfe919 ¤   ¤   pgpAssertNoErr(err);
7fb6ad ¤   ¤   if (IsPGPError(err))
fccdcb ¤   ¤   ¤   break;
e5af5a
9da8c1 ¤   ¤   err = sIOWrite(prefIO, currentPrefData->dataLength, FALSE,
56cb0c ¤   ¤   ¤   ¤   currentPrefData->dataBuffer);
b4af5a
dce919 ¤   ¤   pgpAssertNoErr(err);
b7b6ad ¤   ¤   if (IsPGPError(err))
cdcdcb ¤   ¤   ¤   break;
fdaf5a
23b0bf ¤   ¤   pgpGetNextPrefData(currentPrefData, &currentPrefData);
ee9371 ¤   }
21af5a
58700d ¤   PGPFreeIO(prefIO);
425ea8 ¤   return err;
03efe6 }
64af5a
ffaf5a
4505be PGPError PGPClosePrefFile(PGPPrefRef prefRef)
7bbb36 {
71f814 ¤   PGPValidatePref(prefRef);
d6af5a
1e9c21 ¤   pgpFreePref(prefRef);
8c151e ¤   return kPGPError_NoErr;
79efe6 }
3caf5a
37af5a
95c615 PGPError PGPGetPrefFileSpec(PGPPrefRef prefRef,
5e3c38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *prefFileSpec)
92bb36 {
d0c55b ¤   PGPError err = kPGPError_NoErr;
59af5a
7af0d1 ¤   if (IsntNull(prefFileSpec))
9f6213 ¤   ¤   *prefFileSpec = NULL;
6daf5a
37f814 ¤   PGPValidatePref(prefRef);
d6d029 ¤   PGPValidatePtr(prefFileSpec);
39af5a
ccd7f7 ¤   err = PFLCopyFileSpec(prefRef->prefFileSpec, prefFileSpec);
1782f0 ¤   if (IsPGPError(err))
446213 ¤   ¤   *prefFileSpec = NULL;
bcaf5a
a45ea8 ¤   return err;
f2efe6 }
45af5a
0eaf5a
ba62c9 PGPError PGPGetPrefData(PGPPrefRef prefRef,·
e5980a ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,·
ac1cb8 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *dataLength,·
--867e 0000c11957c40100105 Page 7 of pflPrefs.c
adfa36 ¤   ¤   ¤   ¤   ¤   ¤   void **inBuffer)
febb36 {
a195f0 ¤   PGPPrefData *¤  currentPrefData;
87fb19 ¤   PGPError¤   ¤   err;
6baf5a
ac00be ¤   if (IsntNull(dataLength))
5bffa6 ¤   ¤   *dataLength = 0;
227e8c ¤   if (IsntNull(inBuffer))
f12c90 ¤   ¤   *inBuffer = NULL;
91af5a
9d1072 ¤   PGPValidatePtr(inBuffer);
cc3028 ¤   PGPValidatePtr(dataLength);
96f814 ¤   PGPValidatePref(prefRef);
28af5a
ed3145 ¤   err = pgpFindPrefData(prefRef, prefIndex, &currentPrefData);
6fdd44 ¤   pgpAssertNoErr(err);
5482f0 ¤   if (IsPGPError(err))
4fc9db ¤   ¤   return err;
bbaf5a
599012 ¤   if (IsNull(currentPrefData))
fcc7a1 ¤   {
9ef04e ¤   ¤   return kPGPError_PrefNotFound;
0d9371 ¤   }
79af5a
bb3fdb ¤   *inBuffer¤  = PGPNewData(prefRef->memoryMgr,
51e215 ¤   ¤   ¤   ¤   ¤   currentPrefData->dataLength,
c82e6f ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
1aaf5a
6ef428 ¤   if (IsNull(*inBuffer))
36c7a1 ¤   {
264030 ¤   ¤   return kPGPError_OutOfMemory;
399371 ¤   }
daaf5a
9c96bd ¤   *dataLength¤= currentPrefData->dataLength;
b48ea9 ¤   pgpCopyMemory(currentPrefData->dataBuffer,·
fd8f57 ¤   ¤   *inBuffer,·
4e3446 ¤   ¤   currentPrefData->dataLength);
19af5a
e6151e ¤   return kPGPError_NoErr;
b4efe6 }
62af5a
94af5a
744d20 PGPError PGPSetPrefData(PGPPrefRef prefRef,·
14980a ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,·
e50636 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize dataLength,·
042504 ¤   ¤   ¤   ¤   ¤   ¤   const void *outBuffer)
f7bb36 {
1395f0 ¤   PGPPrefData *¤  currentPrefData;
18fb19 ¤   PGPError¤   ¤   err;
2c67c5 ¤
ddf814 ¤   PGPValidatePref(prefRef);
e06f29 ¤   PGPValidatePtr(outBuffer);
4aaf5a
c83145 ¤   err = pgpFindPrefData(prefRef, prefIndex, &currentPrefData);
4fdd44 ¤   pgpAssertNoErr(err);
9082f0 ¤   if (IsPGPError(err))
6ac9db ¤   ¤   return err;
c8af5a
c29012 ¤   if (IsNull(currentPrefData))
cac7a1 ¤   {
ae9569 ¤   ¤   currentPrefData =·
3c0e7a ¤   ¤   ¤   (PGPPrefData *) PGPNewData(prefRef->memoryMgr,
0d0de9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPPrefData),
d8e0c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
a3af5a
3ead7a ¤   ¤   if (IsNull(currentPrefData))
577cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
7eaf5a
3644af ¤   ¤   currentPrefData->prefIndex¤ = prefIndex;
c6a16f ¤   ¤   currentPrefData->dataBuffer = NULL;
69af5a
0c894b ¤   ¤   pgpAddPrefData(prefRef, currentPrefData);
--2dcb 000802f9b6040100105 Page 8 of pflPrefs.c
a19371 ¤   }
93af5a
8aa50e ¤   currentPrefData->dataLength = dataLength;
2c67c5 ¤
4f42fa ¤   if (IsntNull(currentPrefData->dataBuffer))
7ad074 ¤   ¤   PGPFreeData( currentPrefData->dataBuffer);
0caf5a
ef81bb ¤   currentPrefData->dataBuffer = PGPNewData(prefRef->memoryMgr,
a359aa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataLength,
76e023 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
ebaf5a
729552 ¤   if (IsNull(currentPrefData->dataBuffer))
96c7a1 ¤   {
723c93 ¤   ¤   pgpRemovePrefData(prefRef, currentPrefData);
a64030 ¤   ¤   return kPGPError_OutOfMemory;
489371 ¤   }
24af5a
9f4b2e ¤   pgpCopyMemory(outBuffer, currentPrefData->dataBuffer, dataLength);
beaf5a
6c151e ¤   return kPGPError_NoErr;
2fefe6 }
baaf5a
0caf5a
34d6c4 PGPError PGPRemovePref(PGPPrefRef prefRef,·
aa2e9b ¤   ¤   ¤   ¤   ¤   ···PGPPrefIndex prefIndex)
3abb36 {
c495f0 ¤   PGPPrefData *¤  currentPrefData;
74fb19 ¤   PGPError¤   ¤   err;
ec67c5 ¤
e9f814 ¤   PGPValidatePref(prefRef);
0aaf5a
193145 ¤   err = pgpFindPrefData(prefRef, prefIndex, &currentPrefData);
d9dd44 ¤   pgpAssertNoErr(err);
d782f0 ¤   if (IsPGPError(err))
a0c9db ¤   ¤   return err;
25af5a
d3286a ¤   pgpAssert(IsntNull(currentPrefData));
eb9012 ¤   if (IsNull(currentPrefData))
f562b5 ¤   ¤   return kPGPError_BadParams;
5aaf5a
bb6f88 ¤   pgpRemovePrefData(prefRef, currentPrefData);
9f151e ¤   return kPGPError_NoErr;
6befe6 }
bdaf5a
f8af5a
97ad4a PGPError PGPDisposePrefData(PGPPrefRef prefRef,·
63a043 ¤   ¤   ¤   ¤   ¤   ¤   ¤   void *dataBuffer)
36bb36 {
dcf814 ¤   PGPValidatePref(prefRef);
11ca49 ¤   PGPValidatePtr(dataBuffer);
92af5a
c9b6da ¤   PGPFreeData( dataBuffer);
20151e ¤   return kPGPError_NoErr;
41efe6 }
eeaf5a
fdaf5a
f078d2 static PGPError pgpFindPrefData(PGPPrefRef prefRef,·
eca422 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex,·
f516be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefData **prefData)
98bb36 {
a55820 ¤   PGPPrefData *searchPrefData;
d8af5a
5933e7 ¤   if (IsntNull(prefData))
1d3b52 ¤   ¤   *prefData = NULL;
01af5a
635d19 ¤   PGPValidatePtr(prefData);
eaf814 ¤   PGPValidatePref(prefRef);
1aaf5a
b203ce ¤   searchPrefData = prefRef->prefList;
c16345 ¤   while (IsntNull(searchPrefData))
a3c7a1 ¤   {
8023f7 ¤   ¤   if (searchPrefData->prefIndex == prefIndex)
--382f 000b11baab540100105 Page 9 of pflPrefs.c
7ecdcb ¤   ¤   ¤   break;
f8af5a
8a1c0b ¤   ¤   pgpGetNextPrefData(searchPrefData, &searchPrefData);
b79371 ¤   }
a1af5a
8eaaae ¤   *prefData = searchPrefData;
3e151e ¤   return kPGPError_NoErr;
c9efe6 }
3daf5a
fdaf5a
268193 static PGPError pgpCalcPrefFileSize(PGPPrefRef prefRef, PGPUInt32 *size)
5cbb36 {
d3368c ¤   PGPPrefData *currentPrefData;
fcaf5a
41d4e3 ¤   if (IsntNull(size))
32445d ¤   ¤   *size = ·0;
26af5a
c200e6 ¤   PGPValidatePtr(size);
93f814 ¤   PGPValidatePref(prefRef);
bcaf5a
7e7650 ¤   *size = sizeof(PGPUInt32);
59af5a
0b146f ¤   currentPrefData = prefRef->prefList;
99dbb2 ¤   while (IsntNull(currentPrefData))
81c7a1 ¤   {
9fb596 ¤   ¤   *size += sizeof(PGPPrefIndex) + sizeof(PGPSize) +
913a8c ¤   ¤   ¤   ¤   ¤   currentPrefData->dataLength;
9bb0bf ¤   ¤   pgpGetNextPrefData(currentPrefData, &currentPrefData);
9f9371 ¤   }
98af5a
28151e ¤   return kPGPError_NoErr;
7eefe6 }
efaf5a
8daf5a
5e62a1 static PGPError pgpFreePref(PGPPrefRef prefRef)
5dbb36 {
01368c ¤   PGPPrefData *currentPrefData;
7cefb4 ¤   PGPPrefData *tempPrefData;
3372aa ¤   PGPMemoryMgrRef memoryMgr;
46af5a
a4f814 ¤   PGPValidatePref(prefRef);
e0af5a
50146f ¤   currentPrefData = prefRef->prefList;
9bdbb2 ¤   while (IsntNull(currentPrefData))
36c7a1 ¤   {
e1aae7 ¤   ¤   pgpGetNextPrefData(currentPrefData, &tempPrefData);
103c93 ¤   ¤   pgpRemovePrefData(prefRef, currentPrefData);
ac68ba ¤   ¤   currentPrefData = tempPrefData;
2c9371 ¤   }
74af5a
678e06 ¤   if (pflFileSpecIsValid(prefRef->prefFileSpec))
58c8ff ¤   ¤   PFLFreeFileSpec(prefRef->prefFileSpec);
7aaf5a
783664 ¤   memoryMgr = prefRef->memoryMgr;
ae0f21 ¤   PGPFreeData( prefRef);
aa151e ¤   return kPGPError_NoErr;
25efe6 }
52af5a
d2af5a
57b291 static PGPError pgpAddPrefData(PGPPrefRef prefRef,·
98ee03 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefData *prefData)
d0bb36 {
6bf814 ¤   PGPValidatePref(prefRef);
de5d19 ¤   PGPValidatePtr(prefData);
59af5a
fdb59e ¤   if (IsNull(prefRef->prefList))
55af62 ¤   ¤   prefRef->prefList = prefData;
1aaf5a
31f0ed ¤   if (IsntNull(prefRef->prefListEnd))
8578b8 ¤   ¤   prefRef->prefListEnd->nextPrefData = prefData;
baaf5a
b18f13 ¤   prefData->lastPrefData¤ = prefRef->prefListEnd;
--5a7a 000db0d81ce40100105 Page 10 of pflPrefs.c
ded97f ¤   prefData->nextPrefData¤ = NULL;
24f3fe ¤   prefRef->prefListEnd¤   = prefData;
f2151e ¤   return kPGPError_NoErr;
eeefe6 }
90af5a
81af5a
09bbe8 static PGPError pgpRemovePrefData(PGPPrefRef prefRef,·
11a659 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPPrefData *prefData)
3fbb36 {
8ff814 ¤   PGPValidatePref(prefRef);
625d19 ¤   PGPValidatePtr(prefData);
7faf5a
935c9b ¤   if (IsntNull(prefData->dataBuffer))
615f48 ¤   ¤   PGPFreeData( prefData->dataBuffer);
56af5a
04cefd ¤   if (IsntNull(prefData->nextPrefData))
24acaa ¤   ¤   prefData->nextPrefData->lastPrefData = prefData->lastPrefData;
36af5a
1e8e8f ¤   if (IsntNull(prefData->lastPrefData))
e88c21 ¤   ¤   prefData->lastPrefData->nextPrefData = prefData->nextPrefData;
c8af5a
3038c9 ¤   if (prefRef->prefList == prefData)
e4dae8 ¤   ¤   prefRef->prefList = prefData->nextPrefData;
4e67c5 ¤
edbd5f ¤   if (prefRef->prefListEnd == prefData)
9feb6e ¤   ¤   prefRef->prefListEnd = prefData->lastPrefData;
32af5a
4bac86 ¤   PGPFreeData( prefData);
4d151e ¤   return kPGPError_NoErr;
31efe6 }
fdaf5a
aaaf5a
f755b4 static PGPError pgpGetNextPrefData(const PGPPrefData *currentPrefData,·
f43d93 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPPrefData **nextPrefData)
40bb36 {
512fc7 ¤   if (IsntNull(nextPrefData))
9ead92 ¤   ¤   *nextPrefData = NULL;
e4af5a
f60f3f ¤   PGPValidatePtr(nextPrefData);
16f769 ¤   PGPValidatePtr(currentPrefData);
35af5a
e50f2e ¤   *nextPrefData = currentPrefData->nextPrefData;
37151e ¤   return kPGPError_NoErr;
99efe6 }
efaf5a
01af5a
3b9dc4 static PGPError sIORead(PGPIORef fileIO, PGPSize dataSize,·
d1cb59 ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, void *data)
6dbb36 {
b053ac ¤   PGPByte¤¤   tempData16[sizeof(PGPUInt16)];
22d83f ¤   PGPByte¤¤   tempData32[sizeof(PGPUInt32)];
69ec9c ¤   PGPUInt32¤  data32;
a3b8a7 ¤   PGPUInt16¤  data16;
4cfb1e ¤   PGPSize¤¤   bytesRead;
c88e12 ¤   PGPError¤   err = kPGPError_NoErr;
2baf5a
eb4194 ¤   PGPValidateIO(fileIO);
7e207b ¤   PGPValidateParam(dataSize > 0);
15403b ¤   PGPValidatePtr(data);
ddaf5a
a13bd3 ¤   if (crossPlatform)
c9c7a1 ¤   {
8e4b71 ¤   ¤   if (dataSize == sizeof(PGPUInt16))
165695 ¤   ¤   ¤   err = PGPIORead(fileIO, dataSize, tempData16, &bytesRead);
350e1d ¤   ¤   else
295ee9 ¤   ¤   ¤   err = PGPIORead(fileIO, dataSize, tempData32, &bytesRead);
3caf5a
72e2b3 ¤   ¤   if (IsntPGPError(err))
955b34 ¤   ¤   {
c1dae9 ¤   ¤   ¤   if (dataSize == sizeof(PGPUInt16))
9ff776 ¤   ¤   ¤   {
db8026 ¤   ¤   ¤   ¤   data16 = PGPEndianToUInt16(kPGPPrefsEndian, tempData16);
--2beb 001c7b85d2440100105 Page 11 of pflPrefs.c
d1016e ¤   ¤   ¤   ¤   pgpCopyMemory(&data16, data, sizeof(PGPUInt16));
6fa3a6 ¤   ¤   ¤   }
afbb8c ¤   ¤   ¤   else
c3f776 ¤   ¤   ¤   {
3ec653 ¤   ¤   ¤   ¤   data32 = PGPEndianToUInt32(kPGPPrefsEndian, tempData32);
a29939 ¤   ¤   ¤   ¤   pgpCopyMemory(&data32, data, sizeof(PGPUInt32));
f4a3a6 ¤   ¤   ¤   }
ab0fe4 ¤   ¤   }
989371 ¤   }
6c0e24 ¤   else
5d409e ¤   ¤   err = PGPIORead(fileIO, dataSize, data, &bytesRead);
01af5a
d15ea8 ¤   return err;
59efe6 }
b4af5a
97af5a
d7b882 static PGPError sIOWrite(PGPIORef fileIO, PGPSize dataSize,·
44e958 ¤   ¤   ¤   ¤   ¤   PGPBoolean crossPlatform, const void *data)
e1bb36 {
1353ac ¤   PGPByte¤¤   tempData16[sizeof(PGPUInt16)];
31d83f ¤   PGPByte¤¤   tempData32[sizeof(PGPUInt32)];
94ec9c ¤   PGPUInt32¤  data32;
cbb8a7 ¤   PGPUInt16¤  data16;
e58e12 ¤   PGPError¤   err = kPGPError_NoErr;
83af5a
6e4194 ¤   PGPValidateIO(fileIO);
eb207b ¤   PGPValidateParam(dataSize > 0);
dd403b ¤   PGPValidatePtr(data);
9caf5a
8b3bd3 ¤   if (crossPlatform)
b0c7a1 ¤   {
2a4b71 ¤   ¤   if (dataSize == sizeof(PGPUInt16))
bf5b34 ¤   ¤   {
790f17 ¤   ¤   ¤   pgpCopyMemory(data, &data16, sizeof(PGPUInt16));
9df148 ¤   ¤   ¤   PGPUInt16ToEndian(data16, kPGPPrefsEndian, tempData16);
498e58 ¤   ¤   ¤   err = PGPIOWrite(fileIO, dataSize, tempData16);
800fe4 ¤   ¤   }
ae0e1d ¤   ¤   else
c65b34 ¤   ¤   {
dfabdf ¤   ¤   ¤   pgpCopyMemory(data, &data32, sizeof(PGPUInt32));
d7b3c3 ¤   ¤   ¤   PGPUInt32ToEndian(data32, kPGPPrefsEndian, tempData32);
9fea3c ¤   ¤   ¤   err = PGPIOWrite(fileIO, dataSize, tempData32);
9e0fe4 ¤   ¤   }
bd9371 ¤   }
b00e24 ¤   else
50ae87 ¤   ¤   err = PGPIOWrite(fileIO, dataSize, data);
c1af5a
155ea8 ¤   return err;
eaefe6 }
62af5a
21af5a
937e4d /*__Editor_settings____
70af5a
9e4126 ¤   Local Variables:
d37b17 ¤   tab-width: 4
f60e6c ¤   End:
0d5f8c ¤   vi: ts=4 sw=4
729e9b ¤   vim: si
38d062 _____________________*/
45af5a
6faf5a
c7af5a
--9071 0009def66fe40100106 Page 1 of pflPrefs.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
92b858 ¤   $Id: pflPrefs.h,v 1.11.12.1 1998/11/12 03:18:36 heller Exp $
66f7f7 ____________________________________________________________________________*/
3a5b2c #ifndef Included_pflPrefs_h¤/* [ */
bb78c5 #define Included_pflPrefs_h
39af5a
e0e610 #include "pgpPFLConfig.h"
14c5d5 #include "pgpBase.h"
24392c #include "pflTypes.h"
38af5a
8593d6 typedef struct PGPPref *¤   PGPPrefRef;
16f4e7 typedef PGPInt32¤   ¤   ¤   PGPPrefIndex;
10af5a
920b72 typedef enum PGPPrefType
8fbb36 {
d823a4 ¤   kPGPPrefType_Boolean = 0,
5b5d46 ¤   kPGPPrefType_Number = 1,
f14ce1 ¤   kPGPPrefType_String = 2,
2f53b1 ¤   kPGPPrefType_Byte = 3
367162 } PGPPrefType;
3caf5a
27fa23 #if PRAGMA_ALIGN_SUPPORTED
0caf46 #pragma options align=mac68k
8e7454 #endif
c1af5a
d494d4 typedef struct PGPPrefDefault
84bb36 {
e5831f ¤   PGPPrefIndex¤   index;
e694d2 ¤   PGPPrefType¤¤   type;
17ff0f ¤   void *¤ ¤   ¤   data;
052f6a ¤   PGPSize¤¤   ¤   size;
e057c2 } PGPPrefDefault;
3caf5a
aefa23 #if PRAGMA_ALIGN_SUPPORTED
8a7c46 #pragma options align=reset
ef7454 #endif
b1af5a
9f2fd1 #define¤kInvalidPGPPrefRef¤ ¤   ¤   ((PGPPrefRef) NULL)
8b29f7 #define PGPPrefRefIsValid( ref )¤   ( (ref) != kInvalidPGPPrefRef )
74af5a
2f99c6 PGP_BEGIN_C_DECLARATIONS
53cbcf #if PRAGMA_IMPORT_SUPPORTED
ddb981 #pragma import on
017454 #endif
7daf5a
1aaf5a
979b45 PGPError PGPOpenPrefFile(PFLFileSpecRef prefFileSpec,·
084325 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const PGPPrefDefault *defaults,
aa41e0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 numDefaults,
bdbda2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefRef *prefRef);
98af5a
8698ca PGPError PGPSavePrefFile(PGPPrefRef prefRef);
31af5a
005cd0 PGPError PGPClosePrefFile(PGPPrefRef prefRef);
3eaf5a
eec615 PGPError PGPGetPrefFileSpec(PGPPrefRef prefRef,
6fbdd7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *prefFileSpec);
53af5a
95af5a
b8a915 PGPError PGPGetPrefData(PGPPrefRef prefRef,
01ec78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPPrefIndex prefIndex,·
dbeaf9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPSize *dataLength,·
fdc755 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·void **inBuffer);
60af5a
474d20 PGPError PGPSetPrefData(PGPPrefRef prefRef,·
7aec78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPPrefIndex prefIndex,·
9dc0d7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPSize dataLength,·
--c5e4 001eb495b5d40100106 Page 2 of pflPrefs.h
808b26 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·const void *outBuffer);
23af5a
e8d6c4 PGPError PGPRemovePref(PGPPrefRef prefRef,·
7fd7c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefIndex prefIndex);
c0af5a
d3ad4a PGPError PGPDisposePrefData(PGPPrefRef prefRef,·
03e98c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·void *dataBuffer);
8daf5a
afaf5a
baaf5a
8bcbcf #if PRAGMA_IMPORT_SUPPORTED
1c2ced #pragma import reset
6e7454 #endif
961254 PGP_END_C_DECLARATIONS
01af5a
733d49 #endif /* ] Included_pflPrefs_h */
85af5a
48af5a
9b7e4d /*__Editor_settings____
7baf5a
b14126 ¤   Local Variables:
507b17 ¤   tab-width: 4
500e6c ¤   End:
a05f8c ¤   vi: ts=4 sw=4
fb9e9b ¤   vim: si
ebd062 _____________________*/
--cfcb 00043037ee940100107 Page 1 of pgpHeapSort.h
a70335 /*____________________________________________________________________________
e95902 ¤   Copyright 1991 Lloyd Chambers
f61258 ¤   Rights granted to PGP to use this source code freely and
8b2240 ¤   without restriction.
7aaf5a
37624b ¤   This file should be #included, and the following symbols defined:
b067c5 ¤
646780 ¤   HeapSortName
f6f2a8 ¤   HeapSortItem
2d67c5 ¤
f5ea35 ¤   For example:
8e4528 ¤   #define HeapSortName¤   MySortName
427985 ¤   #define HeapSortItem¤   MyStructName
5d5c16 ¤   #include "pgpHeapSort.h"
875809 ¤   #undef HeapSortName
b1cd21 ¤   #undef HeapSortItem
7d67c5 ¤
b7abe9 ¤   $Id: pgpHeapSort.h,v 1.2 1997/09/17 00:45:42 mhw Exp $
e1f7f7 ____________________________________________________________________________*/
20af5a
9eaf5a
050335 /*____________________________________________________________________________
190b56 ¤   This function is declared static on purpose. Place it in a C file and
a28d52 ¤   write a wrapper if you want to make it visible.
07f7f7 ____________________________________________________________________________*/
df33c8 ¤   static void
18be03 HeapSortName(
6258a9 ¤   HeapSortItem *¤ ¤   start,
efbfaf ¤   size_t¤ ¤   ¤   ¤   numItems,
140bbf ¤   int ¤   ¤   ¤   ¤   (*compareFunc)( HeapSortItem *item1,
4f88a2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   HeapSortItem *item2, void *userValue ),
47dc80 ¤   void *¤ ¤   ¤   ¤   userValue
4027e6 ¤   )
f7bb36 {
9d0f14 ¤   HeapSortItem¤   *i;
4ae070 ¤   HeapSortItem¤   *j;
f5cfe4 ¤   HeapSortItem¤   *right;
fb7558 ¤   HeapSortItem¤   *left;
34b816 ¤   HeapSortItem¤   key;
c4254e ¤   HeapSortItem *¤ stop;
5daf5a
88f483 ¤   if ( numItems == 0 )
1e99bf ¤   ¤   return;
1c8f9f ¤   stop¤   = start + (numItems - 1);
83b4b8 ¤   if ( stop - start ·< 1)
e699bf ¤   ¤   return;
481b52 ¤   ¤
2bcb95 H1:
3a20da ¤   right = stop;
8d2188 ¤   left = ·start + (stop-start)/2 + 1;
33af5a
3424f1 H2:
8973a3 ¤   if ( left > start )
7dc7a1 ¤   {
bf9f64 ¤   ¤   --left;
3022ad ¤   ¤   key = *left;
ae9371 ¤   }
550e24 ¤   else
50c7a1 ¤   {
7a6f91 ¤   ¤   key = *right;
878715 ¤   ¤   *right¤ = *start;
7434e1 ¤   ¤   --right;
de103e ¤   ¤   if ( right == start )
c35b34 ¤   ¤   {
403a71 ¤   ¤   ¤   *start¤ = key;
a0871b ¤   ¤   ¤   return;¤/* all done */
6d0fe4 ¤   ¤   }
5a9371 ¤   }
91af5a
bb7e2d H3:
005e31 ¤   j = left;
43f228 H4:
--2fdf 0017a1aa2e640100107 Page 2 of pgpHeapSort.h
0c0ff5 ¤   i = j;
b5f5ad ¤   j += j - start + 1;¤/* j = 2*j */
0867c5 ¤
570093 ¤   if ( j < right )
7d3a1c ¤   ¤   goto H5;
bb4f67 ¤   if ( j == right )
38d578 ¤   ¤   goto H6;
1e58dd ¤   if ( j > right )
2ec563 ¤   ¤   goto H8;
5d67c5 ¤
229154 H5:¤if ( compareFunc( j, j + 1, userValue) < 0 )
afbf7d ¤   ¤   ++j;
b74790 H6:
8794d0 ¤   if ( compareFunc( &key, j, userValue) >= 0)
cec563 ¤   ¤   goto H8;
ae67c5 ¤
391d4c H7:
a050b6 ¤   *i¤ = *j;
4bd551 ¤   goto H4;
6caf5a
1c578b H8:
1c1b9c ¤   *i¤ = key;
4f0388 ¤   goto H2;
68efe6 }
92af5a
70af5a
7aaf5a
--c69c 00057d6f87d40100108 Page 1 of pgpInsertionSort.h
a70335 /*____________________________________________________________________________
e95902 ¤   Copyright 1991 Lloyd Chambers
f61258 ¤   Rights granted to PGP to use this source code freely and
8b2240 ¤   without restriction.
7aaf5a
37624b ¤   This file should be #included, and the following symbols defined:
b067c5 ¤
36a3f3 ¤   InsertionSortName
7836db ¤   InsertionSortItem
a667c5 ¤
54ea35 ¤   For example:
1f4a86 ¤   #define InsertionSortName¤  MySortName
4793ab ¤   #define InsertionSortItem¤  MyStructName
d36e8e ¤   #include "pgpInsertionSort.h"
2086c9 ¤   #undef InsertionSortName
a313e1 ¤   #undef InsertionSortItem
6e67c5 ¤
16de14 ¤   $Id: pgpInsertionSort.h,v 1.2 1997/09/17 00:45:42 mhw Exp $
c9f7f7 ____________________________________________________________________________*/
caaf5a
f8af5a
440335 /*____________________________________________________________________________
590b56 ¤   This function is declared static on purpose. Place it in a C file and
208d52 ¤   write a wrapper if you want to make it visible.
fef7f7 ____________________________________________________________________________*/
0433c8 ¤   static void
f44187 InsertionSortName(
6acc91 ¤   InsertionSortItem¤  ¤   *start,
f7e710 ¤   size_t¤ ¤   ¤   ¤   ¤   numItems,
4d9661 ¤   int ¤   ¤   ¤   ¤   ¤   (*compareProc)( InsertionSortItem *item1,
0d49c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   InsertionSortItem *item2, void *userValue ),
6f4874 ¤   void *¤ ¤   ¤   ¤   ¤   userValue )
3fbb36 {
015700 ¤   InsertionSortItem¤  ¤   *stop;
2bfdda ¤   InsertionSortItem¤  ¤   *cur;
5ae215 ¤   InsertionSortItem¤  ¤   *least;
32a66b ¤   InsertionSortItem¤  ¤   data;
f82c40 ¤   InsertionSortItem¤  ¤   temp;
f667c5 ¤
da77ed ¤   if ( numItems <= 1 )
8799bf ¤   ¤   return;
d98f9f ¤   stop¤   = start + (numItems - 1);
0967c5 ¤
41d8af ¤   /*
367e8b ¤   ** find least element and place it at start so
f6c2da ¤   ** we can guarantee halt to insertion
a39faa ¤   */
9337d6 ¤   least = cur = start;
8fcfa1 ¤   do
afc7a1 ¤   {
225f1b ¤   ¤   ++cur;
c99d13 ¤   ¤   if ( compareProc( cur,least, userValue ) < 0 )
e92f1d ¤   ¤   ¤   least = cur;
697689 ¤   } while ( cur < stop );
ad47b0 ¤   /* swap */
c62067 ¤   temp¤   = *least;
b2d2da ¤   *least¤ = *start;
010f21 ¤   *start¤ = temp;
c567c5 ¤
696f89 ¤   while ( start < stop )
a7c7a1 ¤   {
6f0f36 ¤   ¤   ++start;¤   /* ·next item to insert */
4e9447 ¤   ¤   cur = start;
c41b52 ¤   ¤
5069f5 ¤   ¤   data = *start;
441b52 ¤   ¤
3e9d78 ¤   ¤   while ( compareProc( &data, cur - 1, userValue ) < 0 )
ed5b34 ¤   ¤   {
9b9f79 ¤   ¤   ¤   *cur¤   = *(cur - 1);
3cfd8f ¤   ¤   ¤   --cur;
a40fe4 ¤   ¤   }
576c1d ¤   ¤   *cur¤   = data;
--0a4d 0012008f83a40100108 Page 2 of pgpInsertionSort.h
a19371 ¤   }
c9efe6 }
a0af5a
67af5a
20af5a
--3469 001480cbd1c40100109 Page 1 of Makefile.in
5ea601 #
56b4a3 # common/util/
fea601 #
2c4c7f # $Id: Makefile.in,v 1.4 1998/05/28 22:56:33 elowe Exp $
59a601 #
c6af5a
968ebe OBJS= pgpEndianConversion.o pgpStrings.o pgpHex.o pgpPassphraseUtils.o
2baf5a
beb7a3 all:: DONE
48af5a
--75ef 000e8f4f0044010010a Page 1 of pgpBitUtils.c
a70335 /*____________________________________________________________________________
ecedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
bb4b0f ¤   All rights reserved.
b567c5 ¤
33bf62 ¤   $Id: pgpBitUtils.c,v 1.1.14.1 1998/11/12 03:18:37 heller Exp $
c1f7f7 ____________________________________________________________________________*/
85af5a
9770d6 #include "pgpBitUtils.h"
67af5a
ce37b0 #define BitIndexToByteMask(index)¤  ¤   (((PGPByte) 1) << (7-((index) & 0x07)))
030f60 #define¤BitIndexToByte(bitmap,index)¤   ((PGPByte *) bitmap)[(index) >> 3]
24af5a
08a89a static PGPBitCount¤ sSetBitsInNibble[16] =
a15d37 ¤   ¤   ¤   ¤   ¤   ¤   ¤   { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
61af5a
f33fd3 #define¤SetBitsInByte(byte)¤¤   ¤   ¤   ( sSetBitsInNibble[(byte) & 0x0f] + \
64325e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··sSetBitsInNibble[(byte) >> 4] )
476d52 ¤   void
84aad0 pgpSetBit(
6352fd ¤   PGPByte ¤   *bitmap,
99e3bd ¤   PGPBitIndex¤bitIndex)
2dbb36 {
d3c25e ¤   pgpAssertAddrValid( bitmap, PGPByte );
4a67c5 ¤
89da08 ¤   BitIndexToByte( bitmap, bitIndex ) |= BitIndexToByteMask( bitIndex );
63efe6 }
65af5a
dc6d52 ¤   void
e8a3bc pgpSetBitRange(
eb52fd ¤   PGPByte ¤   *bitmap,
4e6581 ¤   PGPBitIndex¤startBitIndex,
d99c85 ¤   PGPBitCount¤numBits)
72bb36 {
bbf0f3 ¤   PGPByte¤¤   *curByte;
883217 ¤   PGPBitCount¤remainingBits;
2e67c5 ¤
837b15 ¤   if( numBits == 0 )
4299bf ¤   ¤   return;
8867c5 ¤
2fc690 ¤   curByte ¤   ¤   = &BitIndexToByte( bitmap, startBitIndex );
b6b508 ¤   remainingBits¤  = numBits;
3267c5 ¤
089ced ¤   if( ( startBitIndex & 0x07 ) != 0 )
80c7a1 ¤   {
c73cc8 ¤   ¤   PGPUInt32¤  i;
f61019 ¤   ¤   PGPUInt32¤  partalByteBits;
2baf5a
b8c99f ¤   ¤   partalByteBits = 8 - ( startBitIndex & 0x07 );
b1f18e ¤   ¤   if( partalByteBits > remainingBits )
1401a0 ¤   ¤   ¤   partalByteBits = remainingBits;
101b52 ¤   ¤
913de2 ¤   ¤   for( i = 0; i < partalByteBits; i++ )
dcc05f ¤   ¤   ¤   pgpSetBit( bitmap, startBitIndex + i );
a287c7 ¤   ¤   ¤
b23ad6 ¤   ¤   remainingBits -= partalByteBits;
adcbd4 ¤   ¤   ++curByte;
6c9371 ¤   }
3067c5 ¤
73c40f ¤   while( remainingBits >= 8 )
0cc7a1 ¤   {
79d887 ¤   ¤   *curByte++ ¤¤   = 0xFF;
94211a ¤   ¤   remainingBits ¤ -= 8;
019371 ¤   }
c667c5 ¤
4b928c ¤   if( remainingBits != 0 )
4fc7a1 ¤   {
f73cc8 ¤   ¤   PGPUInt32¤  i;
d21b52 ¤   ¤
99b636 ¤   ¤   /* curByte becomes our new bitmap base for remaining bits */
ed2a10 ¤   ¤   for( i = 0; i < remainingBits; i++ )
cd3ad9 ¤   ¤   ¤   pgpSetBit( curByte, i );
e89371 ¤   }
--5823 0005ef291b94010010a Page 2 of pgpBitUtils.c
7aefe6 }
46af5a
746d52 ¤   void
d5fc9e pgpClearBit(
b852fd ¤   PGPByte ¤   *bitmap,
16e3bd ¤   PGPBitIndex¤bitIndex)
e3bb36 {
cbc25e ¤   pgpAssertAddrValid( bitmap, PGPByte );
1a67c5 ¤
716b47 ¤   BitIndexToByte( bitmap, bitIndex ) &=
cd7c19 ¤   ¤   ¤   ¤   ~BitIndexToByteMask( bitIndex );
3befe6 }
66af5a
966d52 ¤   void
cf9daa pgpClearBitRange(
3d52fd ¤   PGPByte ¤   *bitmap,
4a6581 ¤   PGPBitIndex¤startBitIndex,
039c85 ¤   PGPBitCount¤numBits)
c4bb36 {
8bf0f3 ¤   PGPByte¤¤   *curByte;
b83217 ¤   PGPBitCount¤remainingBits;
1067c5 ¤
ae7b15 ¤   if( numBits == 0 )
3399bf ¤   ¤   return;
e567c5 ¤
aac690 ¤   curByte ¤   ¤   = &BitIndexToByte( bitmap, startBitIndex );
e0b508 ¤   remainingBits¤  = numBits;
9067c5 ¤
eb9ced ¤   if( ( startBitIndex & 0x07 ) != 0 )
1dc7a1 ¤   {
d33cc8 ¤   ¤   PGPUInt32¤  i;
081019 ¤   ¤   PGPUInt32¤  partalByteBits;
1aaf5a
65c99f ¤   ¤   partalByteBits = 8 - ( startBitIndex & 0x07 );
54f18e ¤   ¤   if( partalByteBits > remainingBits )
6d01a0 ¤   ¤   ¤   partalByteBits = remainingBits;
111b52 ¤   ¤
893de2 ¤   ¤   for( i = 0; i < partalByteBits; i++ )
9f7ffe ¤   ¤   ¤   pgpClearBit( bitmap, startBitIndex + i );
2987c7 ¤   ¤   ¤
8f3ad6 ¤   ¤   remainingBits -= partalByteBits;
42cbd4 ¤   ¤   ++curByte;
7e9371 ¤   }
ab67c5 ¤
5cc40f ¤   while( remainingBits >= 8 )
8ec7a1 ¤   {
39d91c ¤   ¤   *curByte++ ¤¤   = 0;
cf211a ¤   ¤   remainingBits ¤ -= 8;
689371 ¤   }
2267c5 ¤
e9928c ¤   if( remainingBits != 0 )
e8c7a1 ¤   {
113cc8 ¤   ¤   PGPUInt32¤  i;
e01b52 ¤   ¤
feb636 ¤   ¤   /* curByte becomes our new bitmap base for remaining bits */
c52a10 ¤   ¤   for( i = 0; i < remainingBits; i++ )
3bd710 ¤   ¤   ¤   pgpClearBit( curByte, i );
1c9371 ¤   }
d4efe6 }
86af5a
8316ea ¤   PGPBoolean
edd13d pgpTestBit(
0852fd ¤   PGPByte ¤   *bitmap,
42e3bd ¤   PGPBitIndex¤bitIndex)
62bb36 {
02c25e ¤   pgpAssertAddrValid( bitmap, PGPByte );
2caf5a
d9daae ¤   return( ( BitIndexToByte( bitmap, bitIndex ) &
8a0100 ¤   ¤   ¤   ¤   ¤   BitIndexToByteMask( bitIndex ) ) != 0 );
5aefe6 }
53af5a
5e16ea ¤   PGPBoolean
--1dd4 000d447c3274010010a Page 3 of pgpBitUtils.c
a8925a pgpTestAndSetBit(
4752fd ¤   PGPByte ¤   *bitmap,
f9e3bd ¤   PGPBitIndex¤bitIndex)
3abb36 {
c6a2cc ¤   PGPByte¤¤   mask;
a8c4fd ¤   PGPByte¤¤   *byteAddr;
7bdabb ¤   PGPByte¤¤   byteValue;
db67c5 ¤
9cc25e ¤   pgpAssertAddrValid( bitmap, PGPByte );
2daf5a
040af3 ¤   mask ¤  ¤   = BitIndexToByteMask( bitIndex );
20b1bb ¤   byteAddr ¤  = &BitIndexToByte( bitmap, bitIndex );
a567c5 ¤
d44aee ¤   byteValue ¤ = *byteAddr;
ddb04f ¤   *byteAddr¤  = byteValue | mask;
7a67c5 ¤
46aa49 ¤   return( ( byteValue & mask ) != 0 );
2cefe6 }
a8af5a
8e163a ¤   PGPBitCount
036b76 pgpCountAndSetBitRange(
5652fd ¤   PGPByte ¤   *bitmap,
ac6581 ¤   PGPBitIndex¤startBitIndex,
5b9c85 ¤   PGPBitCount¤numBits)
bbbb36 {
e2f0f3 ¤   PGPByte¤¤   *curByte;
063217 ¤   PGPBitCount¤remainingBits;
5c6895 ¤   PGPBitCount¤numSetBits;
1467c5 ¤
ad7b15 ¤   if( numBits == 0 )
34abea ¤   ¤   return( 0 );
2567c5 ¤
b0c690 ¤   curByte ¤   ¤   = &BitIndexToByte( bitmap, startBitIndex );
39b508 ¤   remainingBits¤  = numBits;
3c5023 ¤   numSetBits¤ ¤   = 0;
4967c5 ¤
329ced ¤   if( ( startBitIndex & 0x07 ) != 0 )
7bc7a1 ¤   {
363cc8 ¤   ¤   PGPUInt32¤  i;
191019 ¤   ¤   PGPUInt32¤  partalByteBits;
6caf5a
e8c99f ¤   ¤   partalByteBits = 8 - ( startBitIndex & 0x07 );
e3f18e ¤   ¤   if( partalByteBits > remainingBits )
3b01a0 ¤   ¤   ¤   partalByteBits = remainingBits;
be1b52 ¤   ¤
c43de2 ¤   ¤   for( i = 0; i < partalByteBits; i++ )
acf7b8 ¤   ¤   ¤   numSetBits += pgpTestAndSetBit( bitmap, startBitIndex + i );
3187c7 ¤   ¤   ¤
0d3ad6 ¤   ¤   remainingBits -= partalByteBits;
8bcbd4 ¤   ¤   ++curByte;
ef9371 ¤   }
0067c5 ¤
b0c40f ¤   while( remainingBits >= 8 )
8bc7a1 ¤   {
c9b52e ¤   ¤   numSetBits¤ ¤   += SetBitsInByte( *curByte );
5ed887 ¤   ¤   *curByte++ ¤¤   = 0xFF;
68211a ¤   ¤   remainingBits ¤ -= 8;
179371 ¤   }
5567c5 ¤
a7928c ¤   if( remainingBits != 0 )
c0c7a1 ¤   {
c83cc8 ¤   ¤   PGPUInt32¤  i;
251b52 ¤   ¤
c5b636 ¤   ¤   /* curByte becomes our new bitmap base for remaining bits */
ca2a10 ¤   ¤   for( i = 0; i < remainingBits; i++ )
58849f ¤   ¤   ¤   numSetBits += pgpTestAndSetBit( curByte, i );
089371 ¤   }
5c67c5 ¤
53c725 ¤   return( numSetBits );
adefe6 }
d5af5a
d416ea ¤   PGPBoolean
--1f0a 000a84221d24010010a Page 4 of pgpBitUtils.c
4e30e9 pgpTestAndClearBit(
4752fd ¤   PGPByte ¤   *bitmap,
79e3bd ¤   PGPBitIndex¤bitIndex)
69bb36 {
7fa2cc ¤   PGPByte¤¤   mask;
29c4fd ¤   PGPByte¤¤   *byteAddr;
e6dabb ¤   PGPByte¤¤   byteValue;
c367c5 ¤
21c25e ¤   pgpAssertAddrValid( bitmap, PGPByte );
03af5a
ab0af3 ¤   mask ¤  ¤   = BitIndexToByteMask( bitIndex );
1bb1bb ¤   byteAddr ¤  = &BitIndexToByte( bitmap, bitIndex );
9267c5 ¤
594aee ¤   byteValue ¤ = *byteAddr;
046ca5 ¤   *byteAddr¤  = byteValue & ~mask;
e067c5 ¤
58aa49 ¤   return( ( byteValue & mask ) != 0 );
e7efe6 }
7aaf5a
88163a ¤   PGPBitCount
45e034 pgpCountAndClearBitRange(
4452fd ¤   PGPByte ¤   *bitmap,
ad6581 ¤   PGPBitIndex¤startBitIndex,
5f9c85 ¤   PGPBitCount¤numBits)
53bb36 {
01f0f3 ¤   PGPByte¤¤   *curByte;
593217 ¤   PGPBitCount¤remainingBits;
396895 ¤   PGPBitCount¤numSetBits;
1867c5 ¤
ad7b15 ¤   if( numBits == 0 )
38abea ¤   ¤   return( 0 );
8c67c5 ¤
f9c690 ¤   curByte ¤   ¤   = &BitIndexToByte( bitmap, startBitIndex );
79b508 ¤   remainingBits¤  = numBits;
985023 ¤   numSetBits¤ ¤   = 0;
0a67c5 ¤
869ced ¤   if( ( startBitIndex & 0x07 ) != 0 )
53c7a1 ¤   {
e33cc8 ¤   ¤   PGPUInt32¤  i;
641019 ¤   ¤   PGPUInt32¤  partalByteBits;
e9af5a
c8c99f ¤   ¤   partalByteBits = 8 - ( startBitIndex & 0x07 );
0df18e ¤   ¤   if( partalByteBits > remainingBits )
2001a0 ¤   ¤   ¤   partalByteBits = remainingBits;
2e1b52 ¤   ¤
983de2 ¤   ¤   for( i = 0; i < partalByteBits; i++ )
6c9e53 ¤   ¤   ¤   numSetBits += pgpTestAndClearBit( bitmap, startBitIndex + i );
de87c7 ¤   ¤   ¤
633ad6 ¤   ¤   remainingBits -= partalByteBits;
36cbd4 ¤   ¤   ++curByte;
cb9371 ¤   }
2367c5 ¤
1ac40f ¤   while( remainingBits >= 8 )
fec7a1 ¤   {
8fb52e ¤   ¤   numSetBits¤ ¤   += SetBitsInByte( *curByte );
12d91c ¤   ¤   *curByte++ ¤¤   = 0;
f6211a ¤   ¤   remainingBits ¤ -= 8;
df9371 ¤   }
9e67c5 ¤
9f928c ¤   if( remainingBits != 0 )
37c7a1 ¤   {
7b3cc8 ¤   ¤   PGPUInt32¤  i;
3d1b52 ¤   ¤
a3b636 ¤   ¤   /* curByte becomes our new bitmap base for remaining bits */
1c2a10 ¤   ¤   for( i = 0; i < remainingBits; i++ )
219953 ¤   ¤   ¤   numSetBits += pgpTestAndClearBit( curByte, i );
109371 ¤   }
8567c5 ¤
c3c725 ¤   return( numSetBits );
b5efe6 }
f9af5a
a8163a ¤   PGPBitCount
--9338 00165a07b1e4010010a Page 5 of pgpBitUtils.c
a509a1 pgpCountSetBitsInRange(
4f52fd ¤   PGPByte ¤   *bitmap,
e16581 ¤   PGPBitIndex¤startBitIndex,
479c85 ¤   PGPBitCount¤numBits)
c6bb36 {
90f0f3 ¤   PGPByte¤¤   *curByte;
ef3217 ¤   PGPBitCount¤remainingBits;
b56895 ¤   PGPBitCount¤numSetBits;
5a67c5 ¤
1f7b15 ¤   if( numBits == 0 )
66abea ¤   ¤   return( 0 );
2267c5 ¤
4ac690 ¤   curByte ¤   ¤   = &BitIndexToByte( bitmap, startBitIndex );
7eb508 ¤   remainingBits¤  = numBits;
dd5023 ¤   numSetBits¤ ¤   = 0;
5567c5 ¤
e19ced ¤   if( ( startBitIndex & 0x07 ) != 0 )
efc7a1 ¤   {
3c3cc8 ¤   ¤   PGPUInt32¤  i;
371019 ¤   ¤   PGPUInt32¤  partalByteBits;
e9af5a
6fc99f ¤   ¤   partalByteBits = 8 - ( startBitIndex & 0x07 );
c3f18e ¤   ¤   if( partalByteBits > remainingBits )
b101a0 ¤   ¤   ¤   partalByteBits = remainingBits;
241b52 ¤   ¤
023de2 ¤   ¤   for( i = 0; i < partalByteBits; i++ )
6cc71e ¤   ¤   ¤   numSetBits += ( pgpTestBit( bitmap, startBitIndex + i ) != 0 );
9087c7 ¤   ¤   ¤
993ad6 ¤   ¤   remainingBits -= partalByteBits;
37cbd4 ¤   ¤   ++curByte;
3b9371 ¤   }
0567c5 ¤
ecc40f ¤   while( remainingBits >= 8 )
d3c7a1 ¤   {
78a348 ¤   ¤   /* Do not increment curByte in SetBitsInByte() because it is a macro */
42b52e ¤   ¤   numSetBits¤ ¤   += SetBitsInByte( *curByte );
c2211a ¤   ¤   remainingBits ¤ -= 8;
09843c ¤   ¤   ++curByte;¤ ¤   ¤
0f9371 ¤   }
d767c5 ¤
91928c ¤   if( remainingBits != 0 )
2ac7a1 ¤   {
603cc8 ¤   ¤   PGPUInt32¤  i;
8f1b52 ¤   ¤
3fb636 ¤   ¤   /* curByte becomes our new bitmap base for remaining bits */
1d2a10 ¤   ¤   for( i = 0; i < remainingBits; i++ )
19ce5b ¤   ¤   ¤   numSetBits += ( pgpTestBit( curByte, i ) != 0 );
b19371 ¤   }
1167c5 ¤
36c725 ¤   return( numSetBits );
73efe6 }
9eaf5a
fc163a ¤   PGPBitCount
61d79b pgpCountClearBitsInRange(
2f52fd ¤   PGPByte ¤   *bitmap,
046581 ¤   PGPBitIndex¤startBitIndex,
e09c85 ¤   PGPBitCount¤numBits)
98bb36 {
a57e54 ¤   return( numBits - pgpCountSetBitsInRange(bitmap, startBitIndex, numBits) );
65be43 }¶
--c30e 0013b5a87ab4010010b Page 1 of pgpBitUtils.h
a70335 /*____________________________________________________________________________
ecedb8 ¤   Copyright (C) 1998 Network Associates, Inc. and its affiliates.
bb4b0f ¤   All rights reserved.
b567c5 ¤
afdc18 ¤   $Id: pgpBitUtils.h,v 1.1.14.1 1998/11/12 03:18:38 heller Exp $
31f7f7 ____________________________________________________________________________*/
fcaf5a
93c57a #ifndef Included_pgpBitUtils_h¤ /* [ */
078967 #define Included_pgpBitUtils_h
abaf5a
d5c5d5 #include "pgpBase.h"
10af5a
4e6577 typedef PGPUInt32¤  PGPBitIndex;
8f52b9 typedef PGPUInt32¤  PGPBitCount;
37af5a
1199c6 PGP_BEGIN_C_DECLARATIONS
4daf5a
32cbcf #if PRAGMA_IMPORT_SUPPORTED
0db981 #pragma import on
e87454 #endif
bdaf5a
e70fdb void¤   ¤   ¤   pgpSetBit(PGPByte *bitmap, PGPBitIndex bitIndex);
4c62fd void¤   ¤   ¤   pgpSetBitRange(PGPByte *bitmap, PGPBitIndex startBitIndex,
f54b53 ¤   ¤   ¤   ¤   ¤   ¤   PGPBitCount numBits);
79af5a
c0ee5c void¤   ¤   ¤   pgpClearBit(PGPByte *bitmap, PGPBitIndex bitIndex);
c8d694 void¤   ¤   ¤   pgpClearBitRange(PGPByte *bitmap, PGPBitIndex startBitIndex,
5f4b53 ¤   ¤   ¤   ¤   ¤   ¤   PGPBitCount numBits);
e8af5a
dc4d53 PGPBoolean¤ ¤   pgpTestBit(PGPByte *bitmap, PGPBitIndex bitIndex);
de3bd6 PGPBoolean¤ ¤   pgpTestAndClearBit(PGPByte *bitmap, PGPBitIndex bitIndex);
101534 PGPBoolean¤ ¤   pgpTestAndSetBit(PGPByte *bitmap, PGPBitIndex bitIndex);
c3af5a
ee7db4 PGPBitCount¤¤   pgpCountAndClearBitRange(PGPByte *bitmap,
c457f9 ¤   ¤   ¤   ¤   ¤   ¤   PGPBitIndex startBitIndex, PGPBitCount numBits);
a30b80 PGPBitCount¤¤   pgpCountAndSetBitRange(PGPByte *bitmap,
b457f9 ¤   ¤   ¤   ¤   ¤   ¤   PGPBitIndex startBitIndex, PGPBitCount numBits);
b8efdd PGPBitCount¤¤   pgpCountClearBitsInRange(PGPByte *bitmap,
0057f9 ¤   ¤   ¤   ¤   ¤   ¤   PGPBitIndex startBitIndex, PGPBitCount numBits);
beec63 PGPBitCount¤¤   pgpCountSetBitsInRange(PGPByte *bitmap,
fa57f9 ¤   ¤   ¤   ¤   ¤   ¤   PGPBitIndex startBitIndex, PGPBitCount numBits);
2faf5a
23cbcf #if PRAGMA_IMPORT_SUPPORTED
ed2ced #pragma import reset
e17454 #endif
f8af5a
c31254 PGP_END_C_DECLARATIONS
04af5a
3bce6d #endif /* ] Included_pgpBitUtils_h */
--fb7a 0001db001ea4010010c Page 1 of pgpEndianConversion.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
6ac027 ¤   $Id: pgpEndianConversion.c,v 1.2.16.1 1998/11/12 03:18:38 heller Exp $
e4f7f7 ____________________________________________________________________________*/
6a2194 #include "pgpPFLConfig.h"¤  /* or pgpConfig.h in the CDK */
15af5a
413d4b #include "pgpEndianConversion.h"
d6af5a
75c255 ¤   PGPUInt16
0eb3b8 PGPEndianToUInt16(
153ad4 ¤   PGPEndianType¤  type,
84ade3 ¤   const PGPByte *¤raw )
19bb36 {
9af9ce ¤   PGPUInt16¤  result;
5667c5 ¤
1f3233 ¤   if ( type == kPGPBigEndian )
6ec7a1 ¤   {
e828c0 ¤   ¤   result¤ = raw[ 0 ];
66de5a ¤   ¤   result¤ <<= 8;
16c08b ¤   ¤   result¤ |= raw[ 1 ];
399371 ¤   }
170e24 ¤   else
0ac7a1 ¤   {
752384 ¤   ¤   result¤ = raw[ 1 ];
04de5a ¤   ¤   result¤ <<= 8;
70cbcf ¤   ¤   result¤ |= raw[ 0 ];
d89371 ¤   }
3b67c5 ¤
4f4c6e ¤   return( result );
b8efe6 }
dcaf5a
6eaf5a
b4108d ¤   PGPUInt32
96e9af PGPEndianToUInt32(
103ad4 ¤   PGPEndianType¤  type,
afade3 ¤   const PGPByte *¤raw )
5cbb36 {
60f7e2 ¤   PGPUInt32¤  result;
2467c5 ¤
e33233 ¤   if ( type == kPGPBigEndian )
5cc7a1 ¤   {
f5187a ¤   ¤   result¤ = raw[ 0 ];¤¤   result¤ <<= 8;
e167c8 ¤   ¤   result¤ |= raw[ 1 ];¤   result¤ <<= 8;
01f582 ¤   ¤   result¤ |= raw[ 2 ];¤   result¤ <<= 8;
e3d603 ¤   ¤   result¤ |= raw[ 3 ];
679371 ¤   }
7f0e24 ¤   else
83c7a1 ¤   {
edf5b6 ¤   ¤   result¤ = raw[ 3 ];¤¤   result¤ <<= 8;
27f582 ¤   ¤   result¤ |= raw[ 2 ];¤   result¤ <<= 8;
7f67c8 ¤   ¤   result¤ |= raw[ 1 ];¤   result¤ <<= 8;
0ccbcf ¤   ¤   result¤ |= raw[ 0 ];
399371 ¤   }
0b67c5 ¤
e84c6e ¤   return( result );
8eefe6 }
4faf5a
4e6d52 ¤   void
5f1584 PGPUInt16ToEndian(
8cadd3 ¤   PGPUInt16¤  ¤   num,
16355b ¤   PGPEndianType¤  toType,
79b50f ¤   PGPByte¤¤   ¤   out[ sizeof( PGPUInt16 ) ] )
5dbb36 {
99b2bd ¤   if ( toType == kPGPBigEndian )
66c7a1 ¤   {
0ebe2c ¤   ¤   out[0] = num >> 8;
b8c9fe ¤   ¤   out[1] = num & 0xFF;¤   ¤
1d9371 ¤   }
--3e56 00138c6ce7b4010010c Page 2 of pgpEndianConversion.c
060e24 ¤   else
c2c7a1 ¤   {
c82051 ¤   ¤   out[ 0 ]¤   = num & 0xFF;
b0f1cb ¤   ¤   num¤¤   ¤   >>= 8;
af173d ¤   ¤   out[ 1 ]¤   = num & 0xFF;
8a9371 ¤   }
67efe6 }
cfaf5a
6baf5a
886d52 ¤   void
5a496a PGPUInt32ToEndian(
8046b3 ¤   PGPUInt32¤  ¤   num,
56355b ¤   PGPEndianType¤  toType,
44382b ¤   PGPByte¤¤   ¤   out[ sizeof( PGPUInt32 ) ] )
22bb36 {
c1b2bd ¤   if ( toType == kPGPBigEndian )
f4c7a1 ¤   {
0e7d99 ¤   ¤   out[0] = num >> 24;
17b3cf ¤   ¤   out[1] = (num >> 16) & 0xFF;¤   ¤
7a2532 ¤   ¤   out[2] = (num >> 8) & 0xFF;¤¤
349355 ¤   ¤   out[3] = num & 0xFF;¤   ¤
ac9371 ¤   }
e50e24 ¤   else
fdc7a1 ¤   {
032051 ¤   ¤   out[ 0 ]¤   = num & 0xFF;
dbf1cb ¤   ¤   num¤¤   ¤   >>= 8;
63173d ¤   ¤   out[ 1 ]¤   = num & 0xFF;
3af1cb ¤   ¤   num¤¤   ¤   >>= 8;
e64e89 ¤   ¤   out[ 2 ]¤   = num & 0xFF;
ebf1cb ¤   ¤   num¤¤   ¤   >>= 8;
5379e5 ¤   ¤   out[ 3 ]¤   = num & 0xFF;
7d9371 ¤   }
f1efe6 }
7eaf5a
666d52 ¤   void
f442bd PGPUInt16ToStorage(
f00d57 ¤   PGPUInt16¤  num,
35dd62 ¤   PGPByte¤¤   out[ sizeof( PGPUInt16 ) ] )
3fbb36 {
0a1b48 ¤   PGPUInt16ToEndian( num, kPGPLittleEndian, out );
12efe6 }
ecaf5a
f96d52 ¤   void
3a4c91 PGPUInt32ToStorage(
3e6afc ¤   PGPUInt32¤  num,
585046 ¤   PGPByte¤¤   out[ sizeof( PGPUInt32 ) ] )
17bb36 {
563d7f ¤   PGPUInt32ToEndian( num, kPGPLittleEndian, out );
cbefe6 }
56af5a
a0c255 ¤   PGPUInt16
2aeabd PGPStorageToUInt16( const PGPByte *¤in )
5bbb36 {
0bbcd5 ¤   return( PGPEndianToUInt16( kPGPLittleEndian, in ) );
c2efe6 }
bcaf5a
32108d ¤   PGPUInt32
ba874a PGPStorageToUInt32( const PGPByte *¤in )
edbb36 {
ec01c4 ¤   return( PGPEndianToUInt32( kPGPLittleEndian, in ) );
e0efe6 }
bdaf5a
c7af5a
c47e4d /*__Editor_settings____
90af5a
1e4126 ¤   Local Variables:
007b17 ¤   tab-width: 4
b30e6c ¤   End:
515f8c ¤   vi: ts=4 sw=4
8f9e9b ¤   vim: si
38d062 _____________________*/
--82bb 0010dc558db4010010d Page 1 of pgpEndianConversion.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
52618f ¤   Convert data to/from big endian/little endian formats.
8aaf5a
106064 ¤   $Id: pgpEndianConversion.h,v 1.5.16.1 1998/11/12 03:18:39 heller Exp $
9af7f7 ____________________________________________________________________________*/
c188cc #ifndef Included_pgpEndianConversion_h¤ /* [ */
dd9bf6 #define Included_pgpEndianConversion_h
4daf5a
14e610 #include "pgpPFLConfig.h"
15af5a
f4c5d5 #include "pgpBase.h"
76af5a
d84c64 enum PGPEndianType_
11bb36 {
6e35b7 ¤   kPGPBigEndian,
165df8 ¤   kPGPLittleEndian,
4d67c5 ¤
e34c8d ¤   PGP_ENUM_FORCE( PGPEndianType_ )
0882f7 };
4b063e PGPENUM_TYPEDEF( PGPEndianType_, PGPEndianType );
2baf5a
e03e74 /* use this if you need to make the endianness explicit */
e99fbc PGPUInt16¤  PGPEndianToUInt16( PGPEndianType fromType, const PGPByte *¤ raw );
6d6c2c PGPUInt32¤  PGPEndianToUInt32( PGPEndianType fromType, const PGPByte *¤ raw );
5daf5a
ab573b void¤   ¤   PGPUInt16ToEndian( PGPUInt16 num, PGPEndianType toType,
40466b ¤   ¤   ¤   ¤   PGPByte out[ sizeof( PGPUInt16 ) ] );
d266e2 void¤   ¤   PGPUInt32ToEndian( PGPUInt32 num, PGPEndianType toType,
9821c0 ¤   ¤   ¤   ¤   PGPByte out[ sizeof( PGPUInt32 ) ] );
6aaf5a
6d6172 /* convert types to our standard storage format */
56e378 /* Do NOT assume what the format is */
117b4c void¤   ¤   PGPUInt16ToStorage( PGPUInt16 num,
ff466b ¤   ¤   ¤   ¤   PGPByte out[ sizeof( PGPUInt16 ) ] );
8fca49 void¤   ¤   PGPUInt32ToStorage( PGPUInt32 num,
ce21c0 ¤   ¤   ¤   ¤   PGPByte out[ sizeof( PGPUInt32 ) ] );
03af5a
bb2c2a /* convert from our standard storage format */
c8e378 /* Do NOT assume what the format is */
57fc06 PGPUInt16¤  PGPStorageToUInt16( PGPByte const in[ sizeof( PGPUInt16 ) ] );
2f89c4 PGPUInt32¤  PGPStorageToUInt32( PGPByte const in[ sizeof( PGPUInt32 ) ] );
51af5a
c8af5a
faaf5a
787ece #endif /* ] Included_pgpEndianConversion_h */
a1af5a
b1af5a
df7e4d /*__Editor_settings____
d9af5a
9d4126 ¤   Local Variables:
497b17 ¤   tab-width: 4
0e0e6c ¤   End:
535f8c ¤   vi: ts=4 sw=4
e19e9b ¤   vim: si
0dd062 _____________________*/
--6154 000c3abd1944010010e Page 1 of pgpHex.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
5df180 ¤   $Id: pgpHex.c,v 1.2.26.1 1998/11/12 03:18:40 heller Exp $
d3f7f7 ____________________________________________________________________________*/
ffe610 #include "pgpPFLConfig.h"
f8af5a
98324c #include <string.h>
02af5a
296fbf #include "pgpHex.h"
beaf5a
bcaf5a
02af5a
a1af5a
1916ea ¤   PGPBoolean
800dbf pgpIsValidHexChar( char¤theChar )
4bbb36 {
d10efd ¤   return( (theChar >= '0' && theChar <= '9') ||
f7719c ¤   ¤   ( theChar >= 'a' && theChar <= 'f' ) ||
9b15d5 ¤   ¤   ( theChar >= 'A' && theChar <= 'F' ) );
7defe6 }
20af5a
8faf5a
48af5a
cc6474 ¤   PGPByte
aa1e3e pgpHexCharToNibble( char theChar )
95bb36 {
b2bfd8 ¤   if ( theChar >= '0' && theChar <= '9' )
109fe4 ¤   ¤   return( theChar - '0' );
8c9dc4 ¤   if ( theChar >= 'a' && theChar <= 'f' )
bc1f28 ¤   ¤   return( ( theChar - 'a' ) + 10 );
e81b52 ¤   ¤
2c9666 ¤   return( ( theChar - 'A' ) + 10 );
85efe6 }
e2af5a
d3af5a
3aaf5a
7eaf5a
c26d52 ¤   void
3bbdbb pgpBytesToHex(
c484e8 ¤   PGPByte const *¤keyBytes,
20342a ¤   PGPSize¤¤   ¤   numBytes,
41fa36 ¤   PGPBoolean¤ ¤   add0x,
4ccaef ¤   char *¤ ¤   ¤   outString )
3cbb36 {
12d83c ¤   static const char ¤ sHexDigits[] = "0123456789ABCDEF";
b87d11 ¤   char *¤ ¤   ¤   ¤   curString¤  = outString;
e9f5f9 ¤   static const char¤  sPrefixStr[] = "0x";
9402af ¤   PGPSize¤¤   ¤   ¤   keyByteIndex;
1e67c5 ¤
37ddc1 ¤   if ( add0x )
48c7a1 ¤   {
72f4c3 ¤   ¤   strcpy( curString, sPrefixStr );
0ae983 ¤   ¤   curString¤  += sizeof( sPrefixStr ) - 1;
bc9371 ¤   }
8b67c5 ¤
319061 ¤   for( keyByteIndex = 0; keyByteIndex < numBytes; ++keyByteIndex )
dfc7a1 ¤   {
ab4a8d ¤   ¤   PGPByte¤keyByte¤= keyBytes[ keyByteIndex ];
091b52 ¤   ¤
2ce16d ¤   ¤   // output high nibble, then low nibble
e002d2 ¤   ¤   *curString++¤   = sHexDigits[ ( keyByte >> 4 ) & 0x0F ];
a6f14b ¤   ¤   *curString++¤   = sHexDigits[ keyByte & 0x0F ];
389371 ¤   }
7967c5 ¤
359136 ¤   *curString++¤   = '\0';
38efe6 }
a7af5a
c3af5a
--c087 0002b30ffb54010010e Page 2 of pgpHex.c
a70335 /*____________________________________________________________________________
109f51 ¤   Convert a stream of hex data into binary data. Since it's just a stream,
9cd66b ¤   byte order is irrelevant.
88f7f7 ____________________________________________________________________________*/
136d52 ¤   void
40e7a0 pgpHexToBytes(
07cecc ¤   const char *¤   hex,
582898 ¤   PGPUInt32¤  ¤   numBinaryBytes,
de38cd ¤   PGPByte *¤  ¤   buffer )
42bb36 {
34ceed ¤   PGPUInt32¤  ¤   counter;
44e162 ¤   const char *¤   cur;
c1115c ¤   PGPByte *¤  ¤   outCur;
f767c5 ¤
836236 ¤   /* skip leading "0x", if present */
40d976 ¤   if ( hex[ 0 ] == '0' &&·
0b8670 ¤   ¤   (( hex[ 1 ] == 'x' ) || ( hex[ 1 ] == 'X' )) )
dac7a1 ¤   {
b3b08a ¤   ¤   hex¤+= 2;
349371 ¤   }
ba1b52 ¤   ¤
b30a2e ¤   counter¤= numBinaryBytes;
f35f28 ¤   cur¤¤   = hex;
21427e ¤   outCur¤ = buffer;
3ac85e ¤   while ( counter-- != 0 )
c4c7a1 ¤   {
eec991 ¤   ¤   PGPByte¤¤   theByte;
551b52 ¤   ¤
02ad46 ¤   ¤   if ( ! pgpIsValidHexChar( *cur ) )
60cdcb ¤   ¤   ¤   break;
3b6ac7 ¤   ¤   theByte¤= pgpHexCharToNibble( *cur ) << 4;
8a5f1b ¤   ¤   ++cur;
e71b52 ¤   ¤
6ead46 ¤   ¤   if ( ! pgpIsValidHexChar( *cur ) )
16cdcb ¤   ¤   ¤   break;
4a24ae ¤   ¤   theByte¤|= pgpHexCharToNibble( *cur );
465f1b ¤   ¤   ++cur;
f91b52 ¤   ¤
fa0dfe ¤   ¤   *outCur++¤  = theByte;
f99371 ¤   }
adefe6 }
e2af5a
e2108d ¤   PGPUInt32
073b92 pgpHexToPGPUInt32( const char *hex )
14bb36 {
3ac317 ¤   PGPByte¤¤   buffer[ 4 ];
3bf7e2 ¤   PGPUInt32¤  result;
2367c5 ¤
a873ef ¤   pgpHexToBytes( hex, 4, buffer );
2a67c5 ¤
6deeb6 ¤   result¤ = buffer[ 0 ];
16c88e ¤   result¤ = ( result << 8 ) | buffer[ 1 ];
44d542 ¤   result¤ = ( result << 8 ) | buffer[ 2 ];
a4de06 ¤   result¤ = ( result << 8 ) | buffer[ 3 ];
2667c5 ¤
8e4c6e ¤   return( result );
97efe6 }
f9af5a
edaf5a
adaf5a
d7af5a
45af5a
a5af5a
8eaf5a
91af5a
58af5a
44af5a
16af5a
67af5a
1baf5a
84af5a
2baf5a
--7316 00111ef05014010010e Page 3 of pgpHex.c
e0af5a
1aaf5a
17af5a
78af5a
32af5a
93af5a
37af5a
a6af5a
33af5a
547e4d /*__Editor_settings____
b6af5a
164126 ¤   Local Variables:
897b17 ¤   tab-width: 4
050e6c ¤   End:
b85f8c ¤   vi: ts=4 sw=4
249e9b ¤   vim: si
11d062 _____________________*/
--3d52 001b4b623464010010f Page 1 of pgpHex.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
bf2101 ¤   $Id: pgpHex.h,v 1.1.26.1 1998/11/12 03:18:40 heller Exp $
ecf7f7 ____________________________________________________________________________*/
2c6e21 #ifndef Included_pgpHex_h¤  /* [ */
8c54c5 #define Included_pgpHex_h
7aaf5a
a0c5d5 #include "pgpBase.h"
9eaf5a
fb99c6 PGP_BEGIN_C_DECLARATIONS
82af5a
43af5a
1cee6d PGPBoolean¤ pgpIsValidHexChar( char¤theChar );
6baf5a
782c5c PGPByte¤¤   pgpHexCharToNibble( char nibble );
c0af5a
4fd518 void¤   ¤   pgpBytesToHex( PGPByte const * keyBytes,
d24f74 ¤   ¤   ¤   ¤   PGPSize¤numBytes, PGPBoolean add0x, char *outString );
25af5a
e9641d void¤   ¤   pgpHexToBytes( const char * hex,
3b6025 ¤   ¤   ¤   ¤   PGPUInt32 numBinaryBytes, PGPByte * buffer );
a6af5a
b9e3bb PGPUInt32¤  pgpHexToPGPUInt32( const char *hex );
a767c5 ¤
dd1254 PGP_END_C_DECLARATIONS
72af5a
ecee1f #endif /* ] Included_pgpHex_h */
50af5a
d3af5a
487e4d /*__Editor_settings____
e0af5a
694126 ¤   Local Variables:
4a7b17 ¤   tab-width: 4
4d0e6c ¤   End:
415f8c ¤   vi: ts=4 sw=4
109e9b ¤   vim: si
b4d062 _____________________*/
--7583 0000c14ce6f40100110 Page 1 of pgpPassphraseUtils.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
83c8c7 ¤   $Id: pgpPassphraseUtils.c,v 1.5.16.1 1998/11/12 03:18:41 heller Exp $
29f7f7 ____________________________________________________________________________*/
02af5a
8538ab #include <math.h>
6e324c #include <string.h>
25af5a
290d08 #include "pgpMem.h"
bcaf5a
c1afa7 #include "pgpPassphraseUtils.h"
aeaf5a
f50f9a typedef struct ScoreStruct
51bb36 {
693741 ¤   uchar¤  firstChar;
0324cc ¤   uchar¤  lastChar;
ee5c6c } Range;
fb67c5 ¤
8d7915 static const Range¤ sRanges[] =
9ebb36 {
7c5568 ¤   { 0,¤   ¤   ' ' - 1},
ba3efc ¤   { ' ',¤ ¤   'A' - 1},
e4a940 ¤   { 'A',¤ ¤   'Z'},
356a82 ¤   { 'Z' + 1,¤ 'a' - 1},
5d8408 ¤   { 'a',¤ ¤   'z'},
ea299a ¤   { '0',¤ ¤   '9'},
42c16d ¤   { 'z' + 1,¤ 127},
83b6f6 ¤   { 128,¤ ¤   255},
ea82f7 };
01af5a
0902b9 #define¤kNumRanges¤ ( sizeof( sRanges ) / sizeof( sRanges[ 0 ] ) )
2baf5a
0c108d ¤   PGPUInt32
cb1c34 pgpEstimatePassphraseQuality(
6abedd ¤   const char *passphrase)
8ebb36 {
79d2ff ¤   PGPUInt16¤  quality;
997e10 ¤   PGPUInt16¤  passphraseLength;
f74a91 ¤   PGPUInt16 ¤ charIndex;
8476f3 ¤   PGPUInt16 ¤ rangeIndex;
c2a050 ¤   PGPUInt16¤  span = 0;
89fbc9 ¤   Boolean¤¤   haveRange[ kNumRanges ];
cd67c5 ¤
fdacf2 ¤   pgpAssertAddrValid( passphrase, char );
685afc ¤   pgpClearMemory( haveRange, sizeof( haveRange ) );
e867c5 ¤
6ef13f ¤   passphraseLength = strlen( passphrase );
2ef6fd ¤   for( charIndex = 0; charIndex < passphraseLength; ++charIndex )
0ac7a1 ¤   {
218e93 ¤   ¤   for( rangeIndex = 0; rangeIndex < kNumRanges; ++rangeIndex )
a95b34 ¤   ¤   {
0eca80 ¤   ¤   ¤   uchar¤  ¤   ¤   theChar;
8127ff ¤   ¤   ¤   const Range *¤  theRange;
c787c7 ¤   ¤   ¤
168485 ¤   ¤   ¤   theChar¤¤   = passphrase[ charIndex ];
bc6896 ¤   ¤   ¤   theRange¤   = &sRanges[ rangeIndex ];
4887c7 ¤   ¤   ¤
dae311 ¤   ¤   ¤   if ( theChar >= theRange->firstChar &&·
4fdf3b ¤   ¤   ¤   ¤   theChar <= theRange->lastChar )
9ef776 ¤   ¤   ¤   {
77b316 ¤   ¤   ¤   ¤   haveRange[ rangeIndex ] ¤   = TRUE;
c1f622 ¤   ¤   ¤   ¤   break;
2aa3a6 ¤   ¤   ¤   }
350fe4 ¤   ¤   }
e69371 ¤   }
5767c5 ¤
5ea07c ¤   // determine the total span
ba04d6 ¤   for( rangeIndex = 0; rangeIndex < kNumRanges; ++rangeIndex )
4cc7a1 ¤   {
0cb0b2 ¤   ¤   if ( haveRange[ rangeIndex ] )
--cfa0 00116fc507840100110 Page 2 of pgpPassphraseUtils.c
e35b34 ¤   ¤   {
d7eb39 ¤   ¤   ¤   span¤   += 1 + ( sRanges[ rangeIndex ].lastChar -
2c778a ¤   ¤   ¤   ¤   sRanges[ rangeIndex ].firstChar );
3f0fe4 ¤   ¤   }
b69371 ¤   }
4364ac ¤   pgpAssert( span <= 256 );
6167c5 ¤
b2d785 ¤   if ( span != 0 )
d2c7a1 ¤   {
e456f9 ¤   ¤   double¤ ¤   bitsPerChar¤= log( span ) / log( 2.0 );
5765e6 ¤   ¤   PGPUInt32¤  totalBits¤  = (PGPUInt32) bitsPerChar * passphraseLength;
491b52 ¤   ¤
1026da ¤   ¤   // assume a maximum quality of 128 bits
c3c297 ¤   ¤   quality = ( totalBits * 100 ) / 128;
39f4d5 ¤   ¤   if( quality > 100 )
39bc0d ¤   ¤   ¤   quality = 100;
e59371 ¤   }
6c0e24 ¤   else
03c7a1 ¤   {
08eb01 ¤   ¤   quality¤= 0;
129371 ¤   }
1e1b52 ¤   ¤
4f280b ¤   return( quality );
90efe6 }
16af5a
--8b1e 001f37f6b1e40100111 Page 1 of pgpPassphraseUtils.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
aabc97 ¤   $Id: pgpPassphraseUtils.h,v 1.6.14.1 1998/11/12 03:18:42 heller Exp $
b9f7f7 ____________________________________________________________________________*/
52af5a
8a9583 #ifndef Included_pgpPassphraseUtils_h¤  /* [ */
96f068 #define Included_pgpPassphraseUtils_h
2caf5a
aec5d5 #include "pgpBase.h"
84af5a
af99c6 PGP_BEGIN_C_DECLARATIONS
7aaf5a
0bcbcf #if PRAGMA_IMPORT_SUPPORTED
02b981 #pragma import on
027454 #endif
64af5a
064651 PGPUInt32¤  pgpEstimatePassphraseQuality(const char *passphrase );
32af5a
e0cbcf #if PRAGMA_IMPORT_SUPPORTED
4d2ced #pragma import reset
837454 #endif
0daf5a
401254 PGP_END_C_DECLARATIONS
0baf5a
f0af5a
f3c748 #endif /* ] Included_pgpPassphraseUtils_h */
--f18f 000a6d0984340100112 Page 1 of pgpStrings.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
49aad1 ¤   $Id: pgpStrings.c,v 1.8.12.1 1998/11/12 03:18:43 heller Exp $
f1f7f7 ____________________________________________________________________________*/
9daf5a
80e610 #include "pgpPFLConfig.h"
19af5a
a0324c #include <string.h>
e1feb2 #include <stdio.h>
e3b1cb #include <ctype.h>
75af5a
070d08 #include "pgpMem.h"
761b42 #include "pgpStrings.h"
0baf5a
b80ccc #if PGP_MACINTOSH
63eef1 #include <NumberFormatting.h>
9baf5a
5785c2 #include "MacStrings.h"
357454 #endif
39af5a
62af5a
a70335 /*____________________________________________________________________________
5cd901 ¤   Return a pointer to the file name extension in the name. ·The pointer
4efd5b ¤   does NOT include the period.
d967c5 ¤
d95f57 ¤   File name extensions must be 3 chars or less and not be the whole name.
3667c5 ¤
ffc1f0 ¤   Return NULL if extension not found
86f7f7 ____________________________________________________________________________*/
3c3efe #define kMaxExtensionLength¤¤   3¤  /* not including period */
84d2ab ¤   const char *
ed5d35 PGPGetFileNameExtension( const char *¤  name )
97bb36 {
f56df0 ¤   const char *extension;
9d67c5 ¤
43cdd8 ¤   extension¤  = strrchr( name, '.' );
22d817 ¤   if ( IsntNull( extension ) )
f3c7a1 ¤   {
cd50b0 ¤   ¤   /* must not be whole name, or be longer than ".xxx" */
b1afd2 ¤   ¤   if ( extension == name )
474ef2 ¤   ¤   ¤   extension¤  = NULL;
d149aa ¤   ¤   else if ( strlen( extension ) > (kMaxExtensionLength + 1) ·)
d14ef2 ¤   ¤   ¤   extension¤  = NULL;
4e0e1d ¤   ¤   else
e3ec29 ¤   ¤   ¤   ++extension;¤   /* skip over period */
179371 ¤   }
dc67c5 ¤
b5acfe ¤   return( extension );
11efe6 }
15af5a
0ed2ab ¤   const char *
d49727 PGPGetEndOfBaseFileName(
1a52e9 ¤   const char *¤   name )
f3bb36 {
99479c ¤   const char *¤   result;
3daf5a
b8b70e ¤   result = PGPGetFileNameExtension( name );
9ddfa7 ¤   if ( IsNull( result ) )
f489a6 ¤   ¤   result = name + strlen( name );
210e24 ¤   else
4c554f ¤   ¤   result--;
4167c5 ¤
455d73 ¤   return result;
27efe6 }
b8af5a
b60335 /*____________________________________________________________________________
c926a1 ¤   Form a new file name based on the base name, a number.
a667c5 ¤
--21c0 000dccda38c40100112 Page 2 of pgpStrings.c
ad9ded ¤   Example (with number = 99, separator = "-", maxSize = 13):
08fdcd ¤   Foo.tmp¤¤   ¤   => Foo-99.tmp
bad02f ¤   Foo¤¤   ¤   ¤   => Foo-99
60a5bb ¤   TooLongName.tmp => TooLo-99.tmp
1a67c5 ¤
91bb11 ¤   'maxSize' includes trailing null. ·If necessary, first the base name
b1cb81 ¤   will be truncated, then the separator, and then the extension, in
7c2a41 ¤   order to fit in maxSize.
7a67c5 ¤
4a67bc ¤   returns an error if new name won't fit in buffer
bbf7f7 ____________________________________________________________________________*/
d6c744 ¤   PGPError
3b3e83 PGPNewNumberFileName(
91a3c4 ¤   const char *¤   origName,
59c09f ¤   const char *¤   separator,
dbecbe ¤   PGPUInt32¤  ¤   number,
6b5f87 ¤   PGPSize¤¤   ¤   maxSize,¤   /* including NULL */
04f6a4 ¤   char *¤ ¤   ¤   outName )
1cbb36 {
5f254d ¤   char¤   ¤   ¤   numString[ 32 ];
f01e4e ¤   const char *¤   extension¤  ¤   = NULL;
6a257f ¤   PGPSize¤¤   ¤   baseLength¤ ¤   = 0;
053b73 ¤   PGPSize¤¤   ¤   separatorLength¤= 0;
a32202 ¤   PGPSize¤¤   ¤   extensionLength¤= 0;
5cb8d6 ¤   PGPSize¤¤   ¤   numLength¤  ¤   = 0;
eaaf5a
090236 ¤   PGPValidateParam( origName != outName );
3c641f ¤   /* require minimum of 8.3 */
d7f148 ¤   PGPValidateParam( maxSize >= ( 8 + 1 + 3 + 1 ) );
71af5a
070ccc #if PGP_MACINTOSH
88390a ¤   /* avoid linking in sprintf */
34d29a ¤   NumToString( number, (unsigned char *)numString );
ebf5e7 ¤   PToCString( (unsigned char *)numString, numString );
60db21 #else
825e8e ¤   sprintf( numString, "%ld", (long)number );
e27454 #endif
4767c5 ¤
b9fb1c ¤   extension¤  = PGPGetFileNameExtension( origName );
bbd817 ¤   if ( IsntNull( extension ) )
c1c7a1 ¤   {
264f55 ¤   ¤   extensionLength¤= strlen( extension );
dcc8ba ¤   ¤   pgpAssert( strlen( extension ) <= maxSize - 1 );
d09371 ¤   }
dd0e24 ¤   else
6fc7a1 ¤   {
e1b28f ¤   ¤   extensionLength¤= 0;
4a9371 ¤   }
bd67c5 ¤
dcb006 ¤   baseLength¤ = strlen( origName ) - extensionLength;
e69369 ¤   if ( extensionLength != 0 )
dfc7a1 ¤   {
1a80e5 ¤   ¤   if ( baseLength != 0 )
bded21 ¤   ¤   ¤   --baseLength;¤  /* account for "." */
e69371 ¤   }
f2af5a
e8ee89 ¤   separatorLength¤= strlen( separator );
1a67c5 ¤
e87d20 ¤   numLength¤  = strlen( numString );
c172c9 ¤   while ( TRUE )
47c7a1 ¤   {
47a292 ¤   ¤   PGPSize¤totalLength;
8967c5 ¤
cc1cac ¤   ¤   totalLength¤= baseLength + separatorLength + numLength;
ab1895 ¤   ¤   if ( extensionLength != 0 )
8e5b34 ¤   ¤   {
d8b209 ¤   ¤   ¤   ++totalLength; /* for "." */
8bdfb0 ¤   ¤   ¤   totalLength¤+= extensionLength;
920fe4 ¤   ¤   }
1bce81 ¤   ¤   ++totalLength;¤ /* for trailing NULL */
7bf55d ¤   ¤   if ( totalLength <= maxSize )
dccdcb ¤   ¤   ¤   break;
--d38f 000c996021740100112 Page 3 of pgpStrings.c
e587c7 ¤   ¤   ¤
ae4cac ¤   ¤   /* reduce the size of various name parts */
b2a057 ¤   ¤   /* truncate the base name first */
cf80e5 ¤   ¤   if ( baseLength != 0 )
523bb9 ¤   ¤   ¤   --baseLength;
2cc604 ¤   ¤   else if ( separatorLength != 0 )
aeadf3 ¤   ¤   ¤   --separatorLength;
a3a258 ¤   ¤   else if ( extensionLength != 0 )
7346f1 ¤   ¤   ¤   --extensionLength;
250e1d ¤   ¤   else
c15b34 ¤   ¤   {
c56040 ¤   ¤   ¤   pgpDebugMsg( "impossible" );
800fe4 ¤   ¤   }
3a9371 ¤   }
4a67c5 ¤
725da7 ¤   /* now form the complete name */
b6c7a1 ¤   {
3d33a3 ¤   ¤   char *cur¤  = outName;
4c1b52 ¤   ¤
fcf083 ¤   ¤   pgpCopyMemory( origName, cur, baseLength );
5184bd ¤   ¤   cur¤+= baseLength;
1ecae3 ¤   ¤   pgpCopyMemory( separator, cur, separatorLength );
ba5386 ¤   ¤   cur¤+= separatorLength;
63d80e ¤   ¤   pgpCopyMemory( numString, cur, numLength );
db4a3d ¤   ¤   cur¤+= numLength;
051895 ¤   ¤   if ( extensionLength != 0 )
905b34 ¤   ¤   {
def3fb ¤   ¤   ¤   *cur++¤ = '.';
8c7e76 ¤   ¤   ¤   pgpCopyMemory( extension, cur, extensionLength );
3a3378 ¤   ¤   ¤   cur¤+= extensionLength;
210fe4 ¤   ¤   }
7d7ee0 ¤   ¤   *cur¤   = '\0';
2e9371 ¤   }
f967c5 ¤
7b1265 ¤   pgpAssert( strlen( outName ) + 1 <= maxSize );
2667c5 ¤
c32d68 ¤   return( kPGPError_NoErr );
bcefe6 }
ccaf5a
c80335 /*____________________________________________________________________________
e4c969 ¤   Checks to see if PGPNewNumberFileName() could have generated <fileName>
b14c4e ¤   from <origName> for some number, and returns the number.
61af5a
79c65a ¤   maxSize must be <= the maxSize which was passed to PGPNewNumberFileName()
e264d0 ¤   and is used to make sure the origName wasn't truncated more than
c96371 ¤   necessary. ·Passing 0 is fine, but then any filename of the form
c8036d ¤   <number>.xxx (with matching extension) will succeed.
eaaf5a
96d756 ¤   WARNING: This may not work properly if the separator contains a digit,
28c97c ¤   ¤   ¤   ·or if the separator is empty and the basename contains a digit.
22f7f7 ____________________________________________________________________________*/
e5c744 ¤   PGPError
1613bb PGPVerifyNumberFileName(
eaa3c4 ¤   const char *¤   origName,
72c09f ¤   const char *¤   separator,
2d1049 ¤   const char *¤   fileName,
a61736 ¤   PGPSize¤¤   ¤   maxSize,
02d1d1 ¤   PGPBoolean *¤   outValid,
4b5e1a ¤   PGPUInt32 *¤¤   outNumber )
a5bb36 {
5daee4 ¤   PGPSize¤¤   ¤   fileNameLength;
95510d ¤   const char *¤   fileNamePtr;
122663 ¤   const char *¤   fileNameSep;
9a571c ¤   const char *¤   fileNameNum;
496ccf ¤   const char *¤   origNameEnd;
248f5a ¤   const char *¤   fileNameEnd;
b3c12b ¤   PGPSize¤¤   ¤   origNameEndLength;
fca494 ¤   PGPSize¤¤   ¤   fileNameEndLength;
ce45c9 ¤   PGPBoolean¤ ¤   isMaxLength;
cc3427 ¤   PGPUInt32¤  ¤   number;
9a2e4f ¤   PGPUInt32¤  ¤   oldNumber;
c9af5a
--2001 0002c05092940100112 Page 4 of pgpStrings.c
c53f97 ¤   *outValid = FALSE;
faab23 ¤   *outNumber = -1;
12af5a
b02311 ¤   fileNameLength = strlen( fileName );
963dcc ¤   isMaxLength = (maxSize <= fileNameLength + 1 );
d3aecc ¤   origNameEnd = PGPGetEndOfBaseFileName( origName );
072ae8 ¤   fileNameEnd = PGPGetEndOfBaseFileName( fileName );
d2a337 ¤   origNameEndLength = strlen( origNameEnd );
ee59f7 ¤   fileNameEndLength = strlen( fileNameEnd );
81af5a
d2e631 ¤   /* Check to see if the extensions match */
f5f81a ¤   if ( fileNameEndLength != 1 &&
82f155 ¤   ¤   ·strncmp( origNameEnd, fileNameEnd, fileNameEndLength ) == 0 )
70c7a1 ¤   {
cd3eef ¤   ¤   /* Scan left from the extension to find the start of the number */
f058eb ¤   ¤   fileNamePtr = fileNameEnd;
d8d19f ¤   ¤   while ( fileNamePtr >= fileName &&
add875 ¤   ¤   ¤   ¤   fileNamePtr[-1] >= '0' && fileNamePtr[-1] <= '9' )
429fa2 ¤   ¤   ¤   fileNamePtr--;
89336f ¤   ¤   fileNameNum = fileNamePtr;
ebaf5a
03ca57 ¤   ¤   /* Parse the number */
1f903f ¤   ¤   number = 0;
bd1db9 ¤   ¤   if ( *fileNamePtr >= '0' && *fileNamePtr <= '9' )
d85b34 ¤   ¤   {
65bc23 ¤   ¤   ¤   while ( *fileNamePtr >= '0' && *fileNamePtr <= '9' )
57f776 ¤   ¤   ¤   {
0eef5b ¤   ¤   ¤   ¤   oldNumber = number;
a7f9fe ¤   ¤   ¤   ¤   number = ( number * 10 ) + ( *fileNamePtr - '0' );
f775d6 ¤   ¤   ¤   ¤   if ( oldNumber != ( number - ( *fileNamePtr - '0' ) ) / 10 )
2365dd ¤   ¤   ¤   ¤   ¤   break;¤ /* Overflow */
2616c9 ¤   ¤   ¤   ¤   fileNamePtr++;
eea3a6 ¤   ¤   ¤   }
6eaf5a
807aad ¤   ¤   ¤   /*
7e53c7 ¤   ¤   ¤   ·* Now we know exactly where the separator must start.
c5dda0 ¤   ¤   ¤   ·* The separator won't be truncated until the rest of the
63ba4a ¤   ¤   ¤   ·* Basename is completely gone.
498753 ¤   ¤   ¤   ·*/
d842fa ¤   ¤   ¤   fileNameSep = fileNameNum - strlen( separator );
64a626 ¤   ¤   ¤   if ( fileNameSep < fileName )
2a20bb ¤   ¤   ¤   ¤   fileNameSep = fileName;
66af5a
23262f ¤   ¤   ¤   /* Check the following conditions for a valid name: */
aba13d ¤   ¤   ¤   ¤   /* - short extension implies an empty baseName */
64bf3f ¤   ¤   ¤   if ( ( fileNameEndLength == origNameEndLength ||
6a733f ¤   ¤   ¤   ¤   ···fileNameNum == fileName ) &&
18af5a
f5dfdd ¤   ¤   ¤   ¤   /* - short baseName implies fileName is max length */
c9f20d ¤   ¤   ¤   ¤   ·( fileNameSep - fileName == origNameEnd - origName ||
ea8e31 ¤   ¤   ¤   ¤   ···fileNameLength + 1 >= maxSize ) &&
daaf5a
d5f921 ¤   ¤   ¤   ¤   /* - baseName before separator matches */
71c3a3 ¤   ¤   ¤   ¤   ·strncmp( origName, fileName, fileNameSep - fileName ) == 0 &&
cdaf5a
8b5539 ¤   ¤   ¤   ¤   /* - separator matches */
4ef052 ¤   ¤   ¤   ¤   ·strncmp( separator, fileNameSep, fileNameNum - fileNameSep )
c7f3a2 ¤   ¤   ¤   ¤   ¤   ¤   == 0 )
e3f776 ¤   ¤   ¤   {
10dd07 ¤   ¤   ¤   ¤   *outValid = TRUE;
f4e556 ¤   ¤   ¤   ¤   *outNumber = number;
11a3a6 ¤   ¤   ¤   }
9b0fe4 ¤   ¤   }
619371 ¤   }
a0151e ¤   return kPGPError_NoErr;
0defe6 }
0faf5a
0faf5a
8ca091 ¤   int
eb06cf pgpCompareStringsIgnoreCase(
4793d7 ¤   const char *¤   s1,
2c84ce ¤   const char *¤   s2 )
--cf7c 000be1fea6240100112 Page 5 of pgpStrings.c
2cbb36 {
5d1669 ¤   while ((*s1 != 0) && (*s2 != 0) && (tolower(*s1) == tolower(*s2))) {
39beb5 ¤   ¤   s1++;
18a379 ¤   ¤   s2++;
e69371 ¤   }
a01ac5 ¤   return (*s1 - *s2);
e7efe6 }
a6af5a
0aaf5a
24af5a
15a091 ¤   int
3352b0 pgpCompareStringsIgnoreCaseN(
5493d7 ¤   const char *¤   s1,
a27cb3 ¤   const char *¤   s2,
7ef936 ¤   int¤¤   ¤   ¤   n)
e5bb36 {
c9efb3 ¤   while ((n > 0) &&
a8b40e ¤   ¤   (*s1 != 0) && (*s2 != 0) &&
acc5db ¤   ¤   (tolower(*s1) == tolower(*s2)))
0ac7a1 ¤   {
7abeb5 ¤   ¤   s1++;
1da379 ¤   ¤   s2++;
5099e2 ¤   ¤   n--;
ad9371 ¤   }
5367c5 ¤
3abb38 ¤   return ((n == 0) ? 0 : *s1 - *s2);
7cefe6 }
61af5a
0eaf5a
8baf5a
b80fd0 /*¤ Case insensitive strstr */
e1d25c ¤   char *
763aa5 FindSubStringNoCase(
d0bf9f ¤   const char * inBuffer,
6cfeb0 ¤   const char * inSearchStr)
fabb36 {
cf3abd ¤   const char *¤   currBuffPointer = inBuffer;
ae67c5 ¤
1f7c13 ¤   while (*currBuffPointer != 0)
15c7a1 ¤   {
e4d40a ¤   ¤   const char * compareOne = currBuffPointer;
1f303b ¤   ¤   const char * compareTwo = inSearchStr;
201b52 ¤   ¤
05e7b7 ¤   ¤   while ( tolower(*compareOne) == tolower(*compareTwo) )
465b34 ¤   ¤   {
5bc94b ¤   ¤   ¤   compareOne++;
f9216b ¤   ¤   ¤   compareTwo++;
9639fb ¤   ¤   ¤   if (*compareTwo == 0)
22f776 ¤   ¤   ¤   {
19bb76 ¤   ¤   ¤   ¤   return (char *) currBuffPointer;
eda3a6 ¤   ¤   ¤   }
2c0fe4 ¤   ¤   }
e4985e ¤   ¤   currBuffPointer++;
349371 ¤   }
d23f59 ¤   return NULL;
72efe6 }
3aaf5a
c9af5a
b3af5a
02af5a
7faf5a
93af5a
71af5a
1aaf5a
eaaf5a
ebaf5a
ffaf5a
74af5a
faaf5a
fbaf5a
14af5a
beaf5a
--260d 001dffab6e240100112 Page 6 of pgpStrings.c
217e4d /*__Editor_settings____
c9af5a
864126 ¤   Local Variables:
f87b17 ¤   tab-width: 4
5c0e6c ¤   End:
b85f8c ¤   vi: ts=4 sw=4
a09e9b ¤   vim: si
dfd062 _____________________*/
--b4c7 0000370754c40100113 Page 1 of pgpStrings.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
ae3d52 ¤   $Id: pgpStrings.h,v 1.6.12.1 1998/11/12 03:18:43 heller Exp $
37f7f7 ____________________________________________________________________________*/
818c1a #ifndef Included_pgpStrings_h¤  /* [ */
b6177d #define Included_pgpStrings_h
bdaf5a
8bc5d5 #include "pgpBase.h"
aaaf5a
5699c6 PGP_BEGIN_C_DECLARATIONS
0ecbcf #if PRAGMA_IMPORT_SUPPORTED
3eb981 #pragma import on
4a7454 #endif
9daf5a
d8af5a
680335 /*____________________________________________________________________________
2ed901 ¤   Return a pointer to the file name extension in the name. ·The pointer
8bfd5b ¤   does NOT include the period.
3467c5 ¤
885f57 ¤   File name extensions must be 3 chars or less and not be the whole name.
f067c5 ¤
b0c1f0 ¤   Return NULL if extension not found
1df7f7 ____________________________________________________________________________*/
67eb5d const char *¤   PGPGetFileNameExtension( const char * name );
88af5a
8eac79 const char *¤   PGPGetEndOfBaseFileName( const char * name );
d0af5a
4c0335 /*____________________________________________________________________________
a226a1 ¤   Form a new file name based on the base name, a number.
4d67c5 ¤
6a9ded ¤   Example (with number = 99, separator = "-", maxSize = 13):
07fdcd ¤   Foo.tmp¤¤   ¤   => Foo-99.tmp
6ed02f ¤   Foo¤¤   ¤   ¤   => Foo-99
5ba5bb ¤   TooLongName.tmp => TooLo-99.tmp
8f67c5 ¤
92bb11 ¤   'maxSize' includes trailing null. ·If necessary, first the base name
84cb81 ¤   will be truncated, then the separator, and then the extension, in
f42a41 ¤   order to fit in maxSize.
7267c5 ¤
8967bc ¤   returns an error if new name won't fit in buffer
ccf7f7 ____________________________________________________________________________*/
06a93c PGPError¤   PGPNewNumberFileName( const char * baseName,
8a8de6 ¤   ¤   ¤   ¤   const char * separator, PGPUInt32 number,
4f5d8b ¤   ¤   ¤   ¤   PGPSize maxSize, char *outName );
bcaf5a
ea0335 /*____________________________________________________________________________
4ec969 ¤   Checks to see if PGPNewNumberFileName() could have generated <fileName>
9b4c4e ¤   from <origName> for some number, and returns the number.
b5af5a
84c65a ¤   maxSize must be <= the maxSize which was passed to PGPNewNumberFileName()
5864d0 ¤   and is used to make sure the origName wasn't truncated more than
1d6371 ¤   necessary. ·Passing 0 is fine, but then any filename of the form
7a036d ¤   <number>.xxx (with matching extension) will succeed.
ccaf5a
bad756 ¤   WARNING: This may not work properly if the separator contains a digit,
89c97c ¤   ¤   ¤   ·or if the separator is empty and the basename contains a digit.
ddf7f7 ____________________________________________________________________________*/
f44c1e PGPError¤   PGPVerifyNumberFileName( const char * origName,
0775db ¤   ¤   ¤   ¤   const char * separator, const char * fileName,
bd7781 ¤   ¤   ¤   ¤   PGPSize maxSize, PGPBoolean * outValid,
0fbc95 ¤   ¤   ¤   ¤   PGPUInt32 * outNumber );
edaf5a
6d0335 /*____________________________________________________________________________
985015 ¤   Case insensitive string compare
04f7f7 ____________________________________________________________________________*/
9e2a9d int¤¤   pgpCompareStringsIgnoreCase( const char *str1, const char *str2 );
ed0f84 int¤¤   pgpCompareStringsIgnoreCaseN( const char *str1, const char *str2,
03ec5f ¤   ¤   ¤   int length);
--cfa4 001a49f5f9940100113 Page 2 of pgpStrings.h
2a67c5 ¤
9b0b00 char *¤ FindSubStringNoCase( const char * mainString,
5f3c43 ¤   ¤   ¤   ¤   ¤   const char * subString);
e4af5a
acaf5a
89cbcf #if PRAGMA_IMPORT_SUPPORTED
b02ced #pragma import reset
6f7454 #endif
5b1254 PGP_END_C_DECLARATIONS
f0af5a
e1ec02 #endif /* ] Included_pgpStrings_h */
1daf5a
dbaf5a
fe7e4d /*__Editor_settings____
44af5a
6d4126 ¤   Local Variables:
597b17 ¤   tab-width: 4
600e6c ¤   End:
c95f8c ¤   vi: ts=4 sw=4
b79e9b ¤   vim: si
a4d062 _____________________*/
--ad98 0004f0bb75c40100114 Page 1 of pgpWordWrap.c
4b6438 /*_____________________________________________________________________________
cec97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
2d4b0f ¤   All rights reserved.
167cb9 _____________________________________________________________________________*/
8aaf5a
15324c #include <string.h>
ccaf5a
61c5d5 #include "pgpBase.h"
b00d08 #include "pgpMem.h"
05af5a
133427 #include "pgpFileUtilities.h"
32af5a
2b6aa0 #include "pgpWordWrap.h"
fdaf5a
eeaf5a
34cd1d #define MIN(a, b )¤ ¤   ( (a) <= (b) ? (a) : (b) )
c3af5a
6daf5a
26a132 #define IsWordBreakChar( c) \
216c52 ¤   ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' )
32af5a
301415 #define IsEOLChar( c )¤ ( (c) == '\r' || (c) == '\n' )
3baf5a
f0af5a
ba1964 ¤   static PGPUInt32
db61d4 FindBreakChar( const char *buffer, PGPUInt32 numChars )
e0bb36 {
9945dc ¤   PGPUInt32¤  breakIndex¤ = numChars;
dc9dad ¤   PGPInt32¤   index;
3f695d ¤   /* time to line break...find the last breaking character */
232c2e ¤   for ( index = numChars - 1; index >= 0; --index )
52c7a1 ¤   {
7197d6 ¤   ¤   if ( IsWordBreakChar( buffer[ index ] ) )
915b34 ¤   ¤   {
bbbd68 ¤   ¤   ¤   breakIndex¤ = index;
0ecdcb ¤   ¤   ¤   break;
5e0fe4 ¤   ¤   }
709371 ¤   }
f0d793 ¤   return( breakIndex );
d8efe6 }
5caf5a
88af5a
f2af5a
a0c744 ¤   PGPError
f537a2 pgpWordWrapIO(
5c6edc ¤   PGPIORef¤   ¤   in,¤¤   ¤   /* should be positioned at start */
81c7e4 ¤   PGPIORef¤   ¤   out,¤   ¤   /* should be positioned at start */
7c9ebe ¤   PGPUInt16¤  ¤   wrapLength,
b9ee60 ¤   const char *¤   lineEnd¤¤   /* "\r", "\r\n", "\n" */
8927e6 ¤   )
49bb36 {
5c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
e30a16 ¤   PGPUInt16¤  ¤   charsOnCurrentLine¤ = 0;
222481 ¤   #define¤kWordWrapBufferSize¤¤   512UL
e00a94 ¤   char¤   ¤   ¤   buffer[ kWordWrapBufferSize ];
82ab9e ¤   PGPUInt16¤  ¤   charsInBuffer¤  ¤   = 0;
a9e4ba ¤   PGPUInt16¤  ¤   lineEndLength¤  ¤   = strlen( lineEnd );
d94189 ¤   char¤   ¤   ¤   c;
e567c5 ¤
418e26 ¤   pgpAssert( wrapLength + 1 <= kWordWrapBufferSize );
8d8f89 ¤   if ( wrapLength + 1 > kWordWrapBufferSize )
c949fa ¤   ¤   return( -1 );
f067c5 ¤
62110e ¤   while( IsntPGPError( err = PGPIORead( in, 1, &c, NULL ) ) ·)
fcc7a1 ¤   {
5295d1 ¤   ¤   /* accumulate characters into our temp buffer */
71a326 ¤   ¤   pgpAssert( charsInBuffer < kWordWrapBufferSize );
fe3d4f ¤   ¤   buffer[ charsInBuffer ]¤= c;
b9a44d ¤   ¤   ++charsInBuffer;
721b52 ¤   ¤
72b3f6 ¤   ¤   if ( IsEOLChar( c ) )
4f5b34 ¤   ¤   {
--38a8 00044ba06ce40100114 Page 2 of pgpWordWrap.c
93420b ¤   ¤   ¤   charsOnCurrentLine¤ = 0;
0787c7 ¤   ¤   ¤
6ec048 ¤   ¤   ¤   /* if the buffer can't hold another lines worth, then write it */
5350dc ¤   ¤   ¤   /* out now */
948acd ¤   ¤   ¤   if ( charsInBuffer + wrapLength + 1 > kWordWrapBufferSize )
e2f776 ¤   ¤   ¤   {
a88577 ¤   ¤   ¤   ¤   err¤= PGPIOWrite( out, charsInBuffer, buffer );
4e869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
9e14c3 ¤   ¤   ¤   ¤   ¤   break;
4e28fc ¤   ¤   ¤   ¤   charsInBuffer¤  = 0;
51a3a6 ¤   ¤   ¤   }
860fe4 ¤   ¤   }
660e1d ¤   ¤   else
a45b34 ¤   ¤   {
a10803 ¤   ¤   ¤   ++charsOnCurrentLine;
64e4e5 ¤   ¤   ¤   if ( charsOnCurrentLine > wrapLength )
c5f776 ¤   ¤   ¤   {
924614 ¤   ¤   ¤   ¤   PGPUInt16¤  breakIndex¤ = charsInBuffer;
572b85 ¤   ¤   ¤   ¤
79f8a7 ¤   ¤   ¤   ¤   breakIndex¤ = FindBreakChar( buffer, charsInBuffer );
5a87c7 ¤   ¤   ¤
075772 ¤   ¤   ¤   ¤   err¤= PGPIOWrite( out, breakIndex, buffer );
38869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
0314c3 ¤   ¤   ¤   ¤   ¤   break;
2bae30 ¤   ¤   ¤   ¤   ¤
e600b9 ¤   ¤   ¤   ¤   err¤= PGPIOWrite( out, lineEndLength, lineEnd );
e4869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
5814c3 ¤   ¤   ¤   ¤   ¤   break;
792b85 ¤   ¤   ¤   ¤
d0f822 ¤   ¤   ¤   ¤   /* careful: we are skipping the breaking char */
d5aa21 ¤   ¤   ¤   ¤   pgpAssert( breakIndex <= charsInBuffer );
e5e3b8 ¤   ¤   ¤   ¤   if ( breakIndex < charsInBuffer - 1 )
af72c3 ¤   ¤   ¤   ¤   {
5cea0a ¤   ¤   ¤   ¤   ¤   /* characters remain in the buffer after the break */
9605c2 ¤   ¤   ¤   ¤   ¤   /* character */
f5293a ¤   ¤   ¤   ¤   ¤   charsInBuffer¤  -= breakIndex + 1;
1302de ¤   ¤   ¤   ¤   ¤   pgpCopyMemory( &buffer[ breakIndex + 1 ], &buffer[ 0 ],
9b8697 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   charsInBuffer);
d12613 ¤   ¤   ¤   ¤   }
a4fa07 ¤   ¤   ¤   ¤   else
1172c3 ¤   ¤   ¤   ¤   {
ec9b90 ¤   ¤   ¤   ¤   ¤   charsInBuffer¤  = 0;¤
8b2613 ¤   ¤   ¤   ¤   }
6d2b85 ¤   ¤   ¤   ¤
8e1a5c ¤   ¤   ¤   ¤   charsOnCurrentLine¤ = charsInBuffer;
03a3a6 ¤   ¤   ¤   }
b00fe4 ¤   ¤   }
31d35c ¤   ¤   pgpAssert( err != kPGPError_EOF );
fa9371 ¤   }
aac57b ¤   /* normal to reach EOF while reading */
a18e7c ¤   if ( err == kPGPError_EOF )
31d87c ¤   ¤   err¤= kPGPError_NoErr;
8567c5 ¤
fb11f5 ¤   /* flush any characters that remain in buffer */
df895d ¤   if ( charsInBuffer != 0 && IsntPGPError( err ) )
e1c7a1 ¤   {
53ce3c ¤   ¤   err¤= PGPIOWrite( out, charsInBuffer, buffer );
7c9371 ¤   }
e867c5 ¤
05deb7 ¤   return( err );
95efe6 }
b1af5a
3daf5a
33c744 ¤   PGPError
b0e341 pgpWordWrapFileSpecs(
8d887e ¤   PFLFileSpecRef¤ inputSpec,
d34d9f ¤   PFLFileSpecRef¤ outputSpec,·
029ebe ¤   PGPUInt16¤  ¤   wrapLength,
a6d588 ¤   const char *¤   lineEnd )
06bb36 {
b7fb19 ¤   PGPError¤   ¤   err;
44e71e ¤   PGPFileIORef¤   inRef¤  = NULL;
--f1a0 00168a33b0940100114 Page 3 of pgpWordWrap.c
2a67c5 ¤
e3690b ¤   (void)PFLFileSpecCreate( outputSpec );
af67c5 ¤
70ac69 ¤   err¤= PGPOpenFileSpec( inputSpec,
6ef691 ¤   ¤   ¤   kPFLFileOpenFlags_ReadOnly, &inRef );
0df1e7 ¤   if ( IsntPGPError( err ) )
bdc7a1 ¤   {
3b08a9 ¤   ¤   PGPFileIORef¤   outRef¤ = NULL;
4867c5 ¤
04e78d ¤   ¤   err¤= PGPOpenFileSpec( outputSpec,
470540 ¤   ¤   ¤   kPFLFileOpenFlags_ReadWrite, &outRef );
057d98 ¤   ¤   if ( IsntPGPError( err ) )
945b34 ¤   ¤   {
ce3c97 ¤   ¤   ¤   err¤= pgpWordWrapIO( (PGPIORef)inRef,
3b08bd ¤   ¤   ¤   ¤   (PGPIORef)outRef, wrapLength, lineEnd );
4a4b68 ¤   ¤   ¤   PGPFreeIO( (PGPIORef)outRef );
2d0fe4 ¤   ¤   }
42faad ¤   ¤   PGPFreeIO( (PGPIORef)inRef );
2c9371 ¤   }
fe67c5 ¤
dddeb7 ¤   return( err );
6aefe6 }
ebaf5a
2eaf5a
72c21c #if PGP_MACINTOSH¤  /* [ */
05af5a
13c744 ¤   PGPError
7c3a0e pgpWordWrapFileFSSpec(
210185 ¤   PGPMemoryMgrRef¤memoryMgr,
f93b0a ¤   const FSSpec *¤ inFSSpec,
aa0ed1 ¤   const FSSpec *¤ outFSSpec,
dd9ebe ¤   PGPUInt16¤  ¤   wrapLength,
f7273b ¤   char const *¤   lineEnd )
98bb36 {
d58f52 ¤   PGPError¤   ¤   ¤   err;
68bd84 ¤   PFLFileSpecRef¤ ¤   inSpec¤ = NULL;
b167c5 ¤
fe6de7 ¤   err¤= PFLNewFileSpecFromFSSpec( memoryMgr, inFSSpec, &inSpec );
0ff1e7 ¤   if ( IsntPGPError( err ) )
ffc7a1 ¤   {
65e0f0 ¤   ¤   PFLFileSpecRef¤ ¤   outSpec¤= NULL;
031b52 ¤   ¤
9ca646 ¤   ¤   err¤= PFLNewFileSpecFromFSSpec( memoryMgr, outFSSpec, &outSpec );
de7d98 ¤   ¤   if ( IsntPGPError( err ) )
a65b34 ¤   ¤   {
dca90a ¤   ¤   ¤   err¤= pgpWordWrapFileSpecs( inSpec,
39db76 ¤   ¤   ¤   ¤   outSpec, wrapLength, lineEnd );
a487c7 ¤   ¤   ¤
7c2261 ¤   ¤   ¤   PFLFreeFileSpec( outSpec );
6d0fe4 ¤   ¤   }
2f2192 ¤   ¤   PFLFreeFileSpec( inSpec );
d89371 ¤   }
0267c5 ¤
b267c5 ¤
fddeb7 ¤   return( err );
b2efe6 }
5caf5a
e8af5a
439dcb #endif /* ] PGP_MACINTOSH */
94af5a
bdaf5a
1faf5a
bcaf5a
2baf5a
59af5a
c1af5a
f7af5a
68af5a
8eaf5a
39af5a
7eaf5a
68af5a
--70f2 0016127ef6640100115 Page 1 of pgpWordWrap.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
fe292e ¤   $Id: pgpWordWrap.h,v 1.3.16.1 1998/11/12 03:18:45 heller Exp $
e7f7f7 ____________________________________________________________________________*/
d40c2c #ifndef Included_pgpWordWrap_h¤ /* [ */
6c2edd #define Included_pgpWordWrap_h
a1af5a
2baf5a
f6a9cb #include "pgpIO.h"
0faf5a
e6af5a
6d99c6 PGP_BEGIN_C_DECLARATIONS
1dcbcf #if PRAGMA_IMPORT_SUPPORTED
bbb981 #pragma import on
f67454 #endif
c8af5a
34af5a
a9af5a
5bc763 /* lineEnd should be one of "\r", "\n", "\r\n" ·*/
2b37f1 /* and is the type of line end that will be inserted */
5cfbd8 /* any one of { \r, \n, \r\n } are consider line breaks for input purposes */
0bf803 PGPError¤   pgpWordWrapIO( PGPIORef input, PGPIORef output,
696170 ¤   ¤   ¤   ¤   PGPUInt16 wrapLength, const char * lineEnd);
8e2b85 ¤   ¤   ¤   ¤
3e83ee /* same as above, but takes file specs */
5e17c7 PGPError¤   pgpWordWrapFileSpecs( PFLFileSpecRef input,
cfbe8d ¤   ¤   ¤   ¤   PFLFileSpecRef output,·
de6170 ¤   ¤   ¤   ¤   PGPUInt16 wrapLength, const char * lineEnd);
15af5a
d3af5a
da0ccc #if PGP_MACINTOSH
0faf5a
527dc3 /* same as above, but takes FSSpecs */
885997 /* you may have to create a temporary PGPMemoryMgrRef first */
0ed539 PGPError¤   pgpWordWrapFileFSSpec( PGPMemoryMgrRef memoryMgr,
6a7831 ¤   ¤   ¤   ¤   const FSSpec * inFSSpec, const FSSpec * outFSSpec,
c96170 ¤   ¤   ¤   ¤   PGPUInt16 wrapLength, const char * lineEnd);
767454 #endif
e0af5a
f7af5a
ceaf5a
3aaf5a
0dcbcf #if PRAGMA_IMPORT_SUPPORTED
762ced #pragma import reset
d67454 #endif
0e1254 PGP_END_C_DECLARATIONS
efaf5a
4eaf5a
ffaf5a
7ad5a2 #endif /* ] Included_pgpWordWrap_h */
62af5a
60af5a
1e7e4d /*__Editor_settings____
70af5a
464126 ¤   Local Variables:
227b17 ¤   tab-width: 4
660e6c ¤   End:
c35f8c ¤   vi: ts=4 sw=4
1f9e9b ¤   vim: si
61d062 _____________________*/
--cba6 001158e075440100116 Page 1 of Makefile.in
5ea601 #
f91455 # Top level makefile
8ba601 #
ca66ce # $Id: Makefile.in,v 1.7 1997/09/18 23:05:06 mhw Exp $
08a601 #
64af5a
bcfd38 SUBDIRS= priv pub
1f9709 POSTSUBDIRS= pub/test
54af5a
89b982 LIBDONE= priv/LIBDONE ../pfl/LIBDONE
18af5a
b19a74 LIBTARGET= unix/libPGPsdk.a
8741e7 LIBTDEPS= LIBDONE
4daf5a
239f6e INSTALLLIBS= $(LIBTARGET)
5aaf5a
c5b34c all:: LIBDONE $(LIBTARGET)
cbaf5a
b84886 world::
246b63 ¤   $(MAKE) $(MFLAGS) headers
c13166 ¤   $(MAKE) $(MFLAGS) depend
07d992 ¤   $(MAKE) $(MFLAGS) all
baaf5a
3253f5 clean::
151b0f ¤   rm -f $(LIBTARGET)
--ec21 000490fa58240100117 Page 1 of SDKChangeHistory
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
153774 ¤   $Id: SDKChangeHistory,v 1.14.22.1 1998/11/12 03:20:19 heller Exp $
a5f7f7 ____________________________________________________________________________*/
bbaf5a
179431 - added checking to pgpBase.h to verify that one of {PGP_UNIX, PGP_MACINTOSH,
4c05fd ··PGP_WIN32} is defined.
feaf5a
52c3f7 - added support for Diffie-Helman only version. ·This includes changing key
c2703c ··properties to indicate that RSA keys can't sign and can't encrypt.
a6af5a
c5fed4 - added include file "pgpSDKBuildFlags.h" which contains all our build flags.
a6af5a
258f1f - Mac libaries and PEF names are changed.
52af5a
b02082 - illegal options are now errors. ·A kPGPError_BadParams will be returned if
235dcb ··you pass an illegal option. ·In the debug version, the option number will be
7b46eb ··displayed in a debug message.
5daf5a
15a894 - Put self-signatures onto secret keyring in addition to public keyring.
f2af5a
c9ab94 - Rename PGPOKeyGenPreferredAlgorithms to PGPOPreferredAlgorithms.
3aa911 ··Add support for it on encryption.
13af5a
172aa4 - all CipherFeedback functions and data types have been renamed to use the
af0e2a ··term "CFB".
29af5a
668cf0 - PGPNewSymmetricCipher, PGPNewCipherFeedback, PGPNewHash were renamed to
3f9f52 ··PGPNewSymmetricCipherContext, PGPNewCipherFeedbackContext, PGPNewHashContext.·
afde7b ··
b76a88 ·- PGPGetNumMessageRecoveryKeys has been renamed to PGPCountMessageRecoveryKeys
c2af5a
d10899 - Remove keyset parameter from PGPGetIndexedMessageRecoveryKeyID and
d51a52 ··PGPCountMessageRecoveryKeys
fbaf5a
fb2992 - Add pgpPublicKey.h and pgpCBC.h, along with the new data types for these,
f2db95 ··and the source modules to support them.
8baf5a
0f2a54 - Add support for PKCS1 formatting of bignums as used in SSL in addition to
2a0aeb ··standard PGP formating.
08af5a
6124bf - kPGPError_ItemIsReadOnly is now returned upon any attempt to modify a key
2313bf ··or keyDB which is not mutable. ·Previously, the behavior was somewhat
0d5b78 ··inconsistent, sometimes returning kPGPError_FileLocked, sometimes failing
1a4b6b ··silently, and sometimes making the change anyway even though it cannot be
a558cf ··committed.
5caf5a
b4a5a4 - MacBinary code now uses external file to perform Mac creator/type to
a74446 ··DOS file name extension mapping (and vice versa). ·The file is created
927b5c ··if it does not exist, but once it exists, it is the only information
a6083e ··used to perform these mappings.
deaf5a
6232aa - Fix two bugs: (1) secret keys which aren't axiomatic weren't having their
8b9652 ··non-exportable signatures trusted; (2) expired keys were returned as having
e10417 ··no validity, but only once the first maintenance pass was run after the
94315b ··time of expiring.
7baf5a
d981fe - Changed definitions of following functions to standardize on void */PGPSize
c8a05a ··as descriptors of a buffer in memory. These functions were previously using
929b1a ··PGPByte * and/or PGPUInt32:
56de7b ··
7d81b7 ¤   ¤   PGPInitCBC
855a59 ¤   ¤   PGPCBCEncrypt
b8ad64 ¤   ¤   PGPCBCDecrypt
7cfb0e ¤   ¤   PGPInitCFB
8ca738 ¤   ¤   PGPCFBEncrypt
135005 ¤   ¤   PGPCFBDecrypt
49cf97 ¤   ¤   PGPCFBGetRandom
--70ef 0010fb6bf5540100117 Page 2 of SDKChangeHistory
94a9ec ¤   ¤   PGPCFBRandomCycle
e8404b ¤   ¤   PGPCFBRandomWash
868306 ¤   ¤   PGPContinueHash
cd2ed9 ¤   ¤   PGPFinalizeHash
e762ab ¤   ¤   PGPNewKeyFingerPrintFilter
ef46ea ¤   ¤   PGPGetKeyPropertyBuffer
2cf75d ¤   ¤   PGPGetSubKeyPropertyBuffer
c2e08e ¤   ¤   PGPImportKeyID
7a6233 ¤   ¤   PGPPublicKeyEncrypt
702f2c ¤   ¤   PGPPublicKeyVerifySignature
c72f36 ¤   ¤   PGPPrivateKeyDecrypt
e4e813 ¤   ¤   PGPPrivateKeySign
a49db9 ¤   ¤   PGPInitSymmetricCipher
857b7e ¤   ¤   PGPWashSymmetricCipher
5bee8d ¤   ¤   PGPSymmetricCipherEncrypt
ac19b0 ¤   ¤   PGPSymmetricCipherDecrypt
38b720 ¤   ¤   PGPContextGetRandomBytes
561f26 ¤   ¤   PGPGetHashSize
7caf5a
90d980 - Add support for revocationkey subpacket, to allow keys to be revoked by
7fb213 ··other keys, as well as for the nonrevokable attribute so that keys can't
6e5f86 ··revoke their revocationkey subpacket.
56af5a
b6e821 - Change name of additional decryption packet to reflect its true nature.
0faf5a
--7dad 000f62c35fc40100118 Page 1 of aclocal.m4
df9df1 dnl
fb2692 dnl Local autoconf configuration macros for PGP 3
c79df1 dnl
71bae4 dnl $Id: aclocal.m4,v 1.1 1997/05/04 10:29:59 mhw Exp $
179df1 dnl
d6af5a
359df1 dnl
8834e3 dnl The big finish.
36c5f4 dnl Produce config.status, config.h, and links, and configure subdirs.
ff15cf dnl PGP_AC_OUTPUT([FILE...] [, PRE.IN] [, POST.IN] [, EXTRA-CMDS]·
86818e dnl ¤   [, INIT-CMDS])
337429 define(PGP_AC_OUTPUT,
1ecef8 [trap '' 1 2 15
bc467d AC_CACHE_SAVE
91bbd5 trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' \
b2f97f ¤   1 2 15
b3af5a
846c40 test "x$prefix" = xNONE && prefix=$ac_default_prefix
5cbd2e # Let make expand exec_prefix.
c11d0d test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
10af5a
364b0d # Any assignment to VPATH causes Sun make to only execute
8e798f # the first set of double-colon rules, so remove it if not needed.
751003 # If there is a colon in the path, we need to keep it.
6bc767 if test "x$srcdir" = x.; then
9d7447 changequote(, )dnl
2bd9ad ··ac_vpsub='/^[ ¤   ]*VPATH[ ¤  ]*=[^:]*$/d'
79b0bc changequote([, ])dnl
84ce83 fi
8caf5a
9c1b66 trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
60af5a
98109c ifdef([AC_LIST_HEADER], [DEFS=-DHAVE_CONFIG_H], [AC_OUTPUT_MAKE_DEFS()])
ceaf5a
a53f7c # Without the "./", some shells look in PATH for config.status.
f78a5f : ${CONFIG_STATUS=./config.status}
27af5a
36b3f7 echo creating $CONFIG_STATUS
48bde5 rm -f $CONFIG_STATUS
09a54d cat > $CONFIG_STATUS <<EOF
95cbfe #! /bin/sh
f3c6e6 # Generated automatically by configure.
84f233 # Run this file to recreate the current configuration.
95730d # This directory was configured as follows,
b9b7e7 dnl hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
5d5512 dnl so uname gets run too.
dcd1ef # on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
80a601 #
bd73a8 [#] [$]0 [$]ac_configure_args
4fa601 #
7ff973 # Compiler output produced by configure, useful for debugging
1af544 # configure, is in ./config.log if it exists.
41af5a
0f7447 changequote(, )dnl
504af9 ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
ffb0bc changequote([, ])dnl
b92450 for ac_option
372feb do
89af84 ··case "[\$]ac_option" in
82f722 ··-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
79069b ····echo "running [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args" \
94bbe9 ¤   ¤   "--no-create --no-recursion"
23c724 ····exec [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create \
eb08e1 ¤   ¤   --no-recursion ;;
4db252 ··-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
2cd947 ····echo "$CONFIG_STATUS generated by autoconf version AC_ACVERSION"
b67a51 ····exit 0 ;;
2a5939 ··-help | --help | --hel | --he | --h)
eb509c ····echo "[\$]ac_cs_usage"; exit 0 ;;
470eb9 ··*) echo "[\$]ac_cs_usage"; exit 1 ;;
870e75 ··esac
f6065f done
--80c3 000c2ce00b440100118 Page 2 of aclocal.m4
e0af5a
d029b7 ac_given_srcdir=$srcdir
5af2de ifdef([AC_PROVIDE_AC_PROG_INSTALL], [ac_given_INSTALL="$INSTALL"
26d9ba ])dnl
25af5a
2c03ee changequote(<<, >>)dnl
435465 ifdef(<<AC_LIST_HEADER>>,
42753f <<trap 'rm -fr `echo "$1 AC_LIST_HEADER" | sed "s/:[^ ]*//g"` conftest*; \
e3bf03 ¤   exit 1' 1 2 15>>,
66ae70 <<trap 'rm -fr `echo "$1" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15>>)
34b0bc changequote([, ])dnl
bfaf5a
d080ca PGP_AC_OUTPUT_FILES($1, $2, $3)
b21b1b ifdef([AC_LIST_HEADER], [AC_OUTPUT_HEADER(AC_LIST_HEADER)])dnl
93d588 ifdef([AC_LIST_LINKS], [AC_OUTPUT_LINKS(AC_LIST_FILES, AC_LIST_LINKS)])dnl
3c5c2e ifelse([$5], , ,·
a0bb33 [EOF
d5d5c9 cat >> $CONFIG_STATUS <<EOF
f7071a $5
2689bd EOF
259df3 cat >> $CONFIG_STATUS <<\EOF])
721ec2 $4
a172c2 exit 0
bc89bd EOF
ea8f87 chmod +x $CONFIG_STATUS
b78316 rm -fr confdefs* $ac_clean_files
edcfdc test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
166644 dnl config.status should not do recursion.
9d5d44 ifdef([AC_LIST_SUBDIRS], [AC_OUTPUT_SUBDIRS(AC_LIST_SUBDIRS)])dnl
42d9ba ])dnl
69af5a
c236d9 dnl This is a subroutine of PGP_AC_OUTPUT. ·It is called inside an unquoted
49b99c dnl here document whose contents are going into config.status.
bfe230 dnl PGP_AC_OUTPUT_FILES(FILE..., PRE.IN, POST.IN)
4f4cdb define(PGP_AC_OUTPUT_FILES,
6b618d [# Protect against being on the right side of a sed subst in config.status.·
be7447 changequote(, )dnl
fc7172 sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g;·
8d8722 ·s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
83b0bc changequote([, ])dnl
3ecfce dnl These here document variables are unquoted when configure runs
adfdbe dnl but quoted when config.status runs, so variables are expanded once.
c0853e $ac_vpsub
b4683e dnl Shell code in configure.in might set extrasub.
7cfc66 $extrasub
38cd8a dnl Insert the sed substitutions of variables.
e49b67 undivert(AC_DIVERSION_SED)
7c5553 CEOF
6689bd EOF
78d5c9 cat >> $CONFIG_STATUS <<EOF
89af5a
b54424 CONFIG_FILES=\${CONFIG_FILES-"$1"}
d383cb CONFIG_PRE=\${CONFIG_PRE-"$2"}
076484 CONFIG_POST=\${CONFIG_POST-"$3"}
e589bd EOF
eabe10 cat >> $CONFIG_STATUS <<\EOF
3dd90f dnl Check for the existence of the pre and post files _FIRST_
25516f # test for pre and post files, to make sure they exist
55851d if test -r "$ac_given_srcdir/$CONFIG_PRE"; then
87fe7c ··ac_config_pre="$ac_given_srcdir/$CONFIG_PRE"
b78881 ··echo "Using $ac_config_pre for pre-makefile"
18523c else
737399 ··ac_config_pre=""
8c027f ··echo "No file $CONFIG_PRE"
e4ce83 fi
edaf5a
f6d550 if test -r "$ac_given_srcdir/$CONFIG_POST"; then
931fa9 ··ac_config_post="$ac_given_srcdir/$CONFIG_POST"
2ce53d ··echo "Using $ac_config_post for post-makefile"
78523c else
b06b40 ··ac_config_post=""
c2dfd5 ··echo "No file $CONFIG_POST"
--b470 0017ae11bc940100118 Page 3 of aclocal.m4
18ce83 fi
43af5a
ea66fb for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
be8ef2 dnl Specifying an input file breaks the trap to clean up on interrupt,
5c6c2a dnl but that's not a huge problem.
bad001 ··# Support "outfile[:infile]", defaulting infile="outfile.in".
7ce80f ··case "$ac_file" in
f6394c ··*:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
20a691 ·······ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
b844cd ··*) ac_file_in="${ac_file}.in" ;;
4c0e75 ··esac
36af5a
bd1427 ··# Adjust relative srcdir, etc. for subdirectories.
c6af5a
4ac805 ··# Remove last slash and all that follows it. ·Not all systems have dirname.
027447 changequote(, )dnl
62d4a5 ··ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
9fb0bc changequote([, ])dnl
dbb1d2 ··if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
fb7cd1 ····# The file is in a subdirectory.
e76756 ····test ! -d "$ac_dir" && mkdir "$ac_dir"
dda752 ····ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
4a82a5 ····# A "../" for each directory in $ac_dir_suffix.
1e7447 changequote(, )dnl
becb2a ····ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
1ab0bc changequote([, ])dnl
bd1bd0 ··else
276402 ····ac_dir_suffix= ac_dots=
c09666 ··fi
31af5a
50148f ··case "$ac_given_srcdir" in
01a29a ··.) ·srcdir=.
382258 ······if test -z "$ac_dots"; then top_srcdir=.
5a2d19 ······else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
ffdf8e ··/*) srcdir="$ac_given_srcdir$ac_dir_suffix"
b3de94 ······top_srcdir="$ac_given_srcdir" ;;
95c254 ··*) # Relative path.
730457 ····srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
521e5c ····top_srcdir="$ac_dots$ac_given_srcdir" ;;
8c0e75 ··esac
cdaf5a
9e8cf1 ifdef([AC_PROVIDE_AC_PROG_INSTALL],
e946c0 [ ·case "$ac_given_INSTALL" in
bf7447 changequote(, )dnl
dbfc22 ··[/$]*) INSTALL="$ac_given_INSTALL" ;;
c8b0bc changequote([, ])dnl
7dcffa ··*) INSTALL="$ac_dots$ac_given_INSTALL" ;;
090e75 ··esac
3fd9ba ])dnl
67df95 ··echo creating "$ac_file"
987be8 ··rm -f "$ac_file"
5865a2 ··conf_in_file="`echo $ac_file_in|sed 's%.*/%%'`"
fea068 ··configure_input="Generated automatically from $conf_in_file by configure."
8fe80f ··case "$ac_file" in
315fec ··*Makefile*) ac_comsub="1i\\
8c68ff # $configure_input" ;;
a09e45 ··*) ac_comsub= ;;
0e0e75 ··esac
e71191 ··sed -e "$ac_comsub
a2f10f s%@configure_input@%$configure_input%g
9f0788 s%@srcdir@%$srcdir%g
540e12 s%@top_srcdir@%$top_srcdir%g
362048 s%@top_builddir@%$ac_dots.%g
a16ecb s%@dir_suffix@%$ac_dir_suffix%g
6bdbad ifdef([AC_PROVIDE_AC_PROG_INSTALL], [s%@INSTALL@%$INSTALL%g
fad9ba ])dnl
a8cc78 " -f conftest.subs $ac_config_pre $ac_given_srcdir/$ac_file_in \
52de7a ¤   ¤   $ac_config_post > $ac_file
c2e9b0 fi; done
d66ad6 rm -f conftest.subs
7a27ed ])
--f9b0 000886c0c1b40100119 Page 1 of configure.in
df9df1 dnl
b2f407 dnl $Id: configure.in,v 1.16 1998/07/31 22:05:53 hal Exp $
e99df1 dnl
08b740 dnl This file in input to autoconf. ·It consists of a series of m4
118941 dnl macros which expand to produce the shell script "configure".
902be6 dnl Anything which is not an m4 macro is copied directly to the output.
0b9df1 dnl
bc924f dnl Start things up. ·If the specified file doesn't exist, configure
7ab8be dnl will complain.
3eaf5a
aa01bd AC_INIT(pub/test/pgpTest.h)
e4af5a
5afea0 dnl The following tests need to know that we intend to produce a config.h
64dd8b dnl file, even though this won't expand to any shell script code until
7a52a6 dnl AC_OUTPUT time.
cf094a AC_CONFIG_HEADER(unix/pgpConfig.h)
1aaf5a
7df644 dnl The following directory is where we will find the ancillary scripts,
38e9c0 dnl like install-sh, config.sub, and config.guess.
ae8ea3 AC_CONFIG_AUX_DIR(unix/config)
ffaf5a
d41402 dnl Platform configuration
9d090f AC_CANONICAL_HOST
70d5ed # Export the host CPU to Makefiles for assembly-language use
1078b7 HOST_CPU=$host_cpu
d763f0 AC_SUBST(HOST_CPU)
89af5a
f6a3de dnl Checks for programs.
81c82f # Find a compiler to use.
d811d5 # Check 1) The $CC environment varaible, 2) gcc, 3) acc, and 4) cc.
55ae5a dnl This used to be just AC-CHECK-PROGS(CC, gcc acc, cc), but...
48d6b2 # This deals with brain-damaged Sun systems that place a bogus cc or
ba7fb7 # acc executable in the $PATH, which just prints an error and exit.
06bf5f # We deal with this by actually trying to compile a trivial test program.
40f53e if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
080de4 ··AC_MSG_CHECKING(For C compiler (cached))
9a0d5c ··CC="$ac_cv_prog_CC"
cccb02 ··AC_MSG_RESULT($CC)
048d37 elif test -n "$CC"; then
f53913 ··ac_cv_prog_CC="$CC" # Let the user override the test.
bfeac2 ··AC_MSG_CHECKING(For C compiler)
37cb02 ··AC_MSG_RESULT($CC)
53523c else
b79ee0 ··IFS="${IFS=¤  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
e45536 ··echo 'main(){return 0;}' > conftest.$ac_ext
4c1263 ··for ac_prog in gcc acc cc; do
4d801e # Extract the first word of "$ac_prog", so it can be a program name with args.
ad2283 ····set dummy $ac_prog; ac_word=$2
0c6b14 ····AC_MSG_CHECKING(for $ac_word)
fb2cf4 ····for ac_dir in $PATH; do
74cf86 ······test -z "$ac_dir" && ac_dir=.
cd4cf9 ······if test -r "$ac_dir/$ac_word"; then
825f41 ········CC="$ac_prog"
ad552c ········if eval $ac_compile; then
94c7ef ··········ac_cv_prog_CC="$ac_prog"
cbf9a0 ········fi
5d1dec ········break
a94076 ······fi
3ad04f ····done
99f080 ····CC="$ac_cv_prog_CC"
4c049f ····if test -n "$CC"; then
87034f ······AC_MSG_RESULT($ac_dir/$CC)
b388e1 ······break;
38df8a ····fi
acc319 ····AC_MSG_RESULT(no)
a24fb3 ··done
4ec13d ··if test ! -n "$CC"; then
adaec6 ····AC_MSG_ERROR(no C compiler found)
bc9666 ··fi
b56b79 ··IFS="$ac_save_ifs"
8ddd24 ··rm -f conftest*
88ce83 fi
--04d9 0009c00a5c940100119 Page 2 of configure.in
e6d58b AC_SUBST(CC)
80af5a
f88965 AC_CACHE_CHECK(whether we are using GNU CC, ac_cv_prog_gcc,
d05a6e [dnl The semicolon is to pacify NeXT's syntax-checking cpp.
8e5396 cat > conftest.c <<EOF
2cd1d1 #ifdef __GNUC__
3e6824 ··yes;
387454 #endif
ff89bd EOF
6d0a98 if ${CC-cc} -E conftest.c 2>&AC_FD_CC | egrep yes >/dev/null 2>&1; then
a03022 ··ac_cv_prog_gcc=yes
59523c else
3bb38d ··ac_cv_prog_gcc=no
e6dd41 fi])
9daf5a
cf6e28 if test $ac_cv_prog_gcc = yes; then
36d9b2 ··if test "${CFLAGS+set}" != set; then
a42a14 AC_CACHE_CHECK(whether ${CC-cc} accepts -g, ac_cv_prog_gcc_g,
55cf88 [echo 'void f(){}' > conftest.c
cd6b51 if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
f900bc ··ac_cv_prog_gcc_g=yes
d4523c else
52a6ac ··ac_cv_prog_gcc_g=no
3dce83 fi
85963a rm -f conftest*
2027ed ])
1f9666 ··fi
bece83 fi
dcaf5a
f89b15 # Now, figure out what CFLAGS we want. ·If the user didn't ask specifically,
f811fa # we're going to use some ideas of our own.
9972b3 if test "${CFLAGS+set}" != set; then
e5af5a
cec0f8 # Prefer optimizing, with debugging a second
91dbf8 if test $ac_cv_prog_gcc$ac_cv_prog_gcc_g = yesyes; then
ddd4a4 ··CFLAGS="-O -g"
cc523c else
b7f54f ··CFLAGS=-O
fbce83 fi
13af5a
4398f0 dnl This ugly hack is to get warnings enabled where possible.
57329c AC_MSG_CHECKING(for useful warning options (\$WARN))
27c324 # This currently only deals with gcc and SunPro CC.
08999a if test "${WARN+set}" != set; then
a01566 ··if test $ac_cv_prog_gcc = yes; then
a51d67 ····WARN="-Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes \
0b1e0d -Wwrite-strings"
668744 ··elif $CC -flags 2>&1 | grep SunSoft >/dev/null 2>&1 ||
331970 ¤   $CC -flags 2>&1 | grep SunPro >/dev/null 2>&1; then
3dd676 ····if $CC -flags 2>&1 | grep 'checking' | grep '^-vc' > /dev/null 2>&1; then
574f8a ······WARN=-vc
899f89 ····elif $CC -flags 2>&1 | grep 'checking' | grep '^-v ' > /dev/null 2>&1; then
211850 ······WARN=-v
cfdf8a ····fi
792d3f ····if $CC -flags 2>&1 | grep '^-xstrconst' > /dev/null 2>&1; then
8b2369 ······WARN="${WARN}${WARN+ }-xstrconst"
7edf8a ····fi
1f9666 ··fi
14c4c9 ··# Any other compiler's warning flags?
19ce83 fi
d7149a AC_MSG_RESULT(${WARN-none})
2e09e6 AC_SUBST(WARN)
22af5a
db50e3 dnl currently, this only attempts to handle 386 linux/bsd difficulties
55af5a
20a17a case "$host_os" in
573494 ········*aout* | *BSD* | *bsd*)
f015e1 ················case "$host_cpu" in
702b55 ························i[[3456]]86) host_obj_type=_aout;;
ede69e ················esac;;
094799 esac
9caf5a
--aa64 00062d6695140100119 Page 3 of configure.in
b76a49 host_obj_type=$host_obj_type
f623e5 AC_SUBST(host_obj_type)
efaf5a
3e8a0f AC_MSG_CHECKING(for useful tuning options (\$TUNE))
26671c if test "${TUNE+set}" != set; then
a91566 ··if test $ac_cv_prog_gcc = yes; then
1a34c2 ····TUNE="-O6 -fomit-frame-pointer"
177419 ····case "$host_cpu" in
b3e978 ····i486)
f4525f ······TUNE="$TUNE -m486"
acdcad ······;;
a2c64e ····i586 | i686)
848ce9 ······TUNE="$TUNE -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2"
67dcad ······;;
912295 ····sparc)
3038df ······# Try to use the architecture-detecting tool with SunPro CC.
4348b6 ······if bn_tune=`(fpversion -foption) 2>/dev/null`; then
abc64c ¤   if test "$bn_tune" = xcg92 || test "$bn_tune" = cg92; then
006f3b ¤   ··TUNE="$TUNE -mv8"
147cd7 ¤   elif test "$bn_tune" != xcg89 && test "$bn_tune" != cg89; then
2b6f3b ¤   ··TUNE="$TUNE -mv8"
69d8d0 ¤   ··bn_tune_guess=yes
372ec9 ¤   fi
e03dfa ······else
dbdc03 ¤   TUNE="$TUNE -mv8"
ca6be8 ¤   bn_tune_guess=yes
4b4076 ······fi
57dcad ······;;
9f9189 ····esac
4d8050 ··elif $CC -flags 2>&1 | grep SunSoft >/dev/null 2>&1; then
82b454 ····# SunPro C compiler - now grok version and platform
be567e ····if $CC -flags 2>&1 | grep '^-xO.*5' >/dev/null 2>&1; then
561b77 ······TUNE=-xO5
32842c ····else
5302af ······TUNE=-xO4
c6df8a ····fi
a5fa2c ····# Architecture: -native if avail., else as fpversion says, else guess -mv8
24f985 ····if $CC -flags 2>&1 | grep '^-native' >/dev/null 2>&1; then
cf5206 ······TUNE="$TUNE -native"
0913db ····elif bn_tune=`(fpversion -foption) 2>/dev/null`; then
4fadb6 ······TUNE="$TUNE -$bn_tune"
137b5a ····elif $CC -flags 2>&1 | grep '^-xcg92' >/dev/null 2>&1; then
8fd9a1 ······TUNE="$TUNE -xcg92"
d31dcb ······bn_tune_guess=yes
a2df8a ····fi
109666 ··fi
15ce83 fi
cd187c bn_tune_set=${TUNE+set}
9ac55c # If nothing better is available, turn on -O
43bb54 : ${TUNE=-O}
bb1e4e AC_MSG_RESULT(${TUNE-none})
e016c8 if test "$bn_tune_set" != set; then
f8adc3 ··AC_MSG_WARN(not optimizing heavily - try setting \$CFLAGS)
6dc2e3 elif test "$bn_tune_guess" = yes; then
f03408 ··AC_MSG_WARN([architecture guessed. ·If incorrect, use explicit \$TUNE.])
28ce83 fi
2be1f8 AC_SUBST(TUNE)
9aaf5a
66ce83 fi
51ccc0 # ^^ end of CFLAGS inference section
eaaf5a
32143a AC_REQUIRE_CPP
a01bb1 # Finally, figure out the command to generate dependencies.
ae53cd AC_CACHE_CHECK(how to make dependencies, ac_cv_prog_DEPEND,
87f9a9 [if test -n "$DEPEND"; then
b96e05 ··ac_cv_prog_DEPEND="$DEPEND"
20523c else
109ee0 ··IFS="${IFS=¤  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
940807 ··echo '#include "confdefs.h"' > conftest.c
a77991 ··for ac_prog in "$CPP -M" "$CC -xM" "$CC -M"; do
ec2c44 ····echo $ac_prog $CPPFLAGS conftest.c 1>&AC_FD_CC;
62d448 ····if $ac_prog $CPPFLAGS conftest.c 2>&AC_FD_CC \
--7348 000c9936d7e40100119 Page 4 of configure.in
30204f ····················| egrep "conftest\.o" >/dev/null 2>&1; then
f6cffc ······ac_cv_prog_DEPEND="$ac_prog $CPPFLAGS"
f9a94c ······break
c4df8a ····fi
f64fb3 ··done
d5c62d ··if test ! -n "$ac_cv_prog_DEPEND"; then
13978e ····ac_cv_prog_DEPEND=:
689666 ··fi
686b79 ··IFS="$ac_save_ifs"
53dd24 ··rm -f conftest*
92dd41 fi])
9f93ba DEPEND="$ac_cv_prog_DEPEND"
d55235 AC_SUBST(DEPEND)
0eaf5a
297658 # Find a BSD-compatibile install program, with install-sh as a fallback.
3196e6 AC_PROG_INSTALL
c5af5a
396fc7 # Find "ranlib". ·Sone systems don't have or need ranlib. ·If so,
fdb825 # ":" (do nothing) is used instead.
1c14d7 AC_PROG_RANLIB
67af5a
ab6aee # Use symlinks (ln -s) if possible. ·If not, use hard links (ln).
392fe9 AC_PROG_LN_S
acaf5a
d36a92 # Figure out how to test for symlinks... ·Check 'test -L' and then 'test -h'
3422cc AC_CACHE_CHECK(how to test for symlinks, ac_cv_prog_TEST_L,
457fd5 [rm -f conftest
069ec9 $ac_cv_prog_LN_S foo conftest
9ffeb9 IFS="${IFS=¤}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
0d0e8c if ( test -L conftest ); then
b58bc9 ··ac_cv_prog_TEST_L="test -L"
66188d elif ( test -h conftest ); then
c4eb93 ··ac_cv_prog_TEST_L="test -h"
31523c else
fd6dd0 ··ac_cv_prog_TEST_L="test ! -f"
eace83 fi
595c39 IFS="$ac_save_ifs"
c5eefa rm -f conftest*])
065638 TEST_L="$ac_cv_prog_TEST_L"
a5a3ec AC_SUBST(TEST_L)
21af5a
33c3e7 dnl Checks for libraries.
8cd3f3 AC_CHECK_LIB(thread, main,·
c24fb3 ··THREADLIB="-lthread",·
5db6af ··AC_CHECK_LIB(pthread, main, THREADLIB="-lpthread"))
8605af AC_SUBST(THREADLIB)
26af5a
be2a59 dnl Checks for library functions.
748a0f dnl (we don't have any)
6caf5a
560c0e # The big bang! ·Produce the output files. ·This is config.cache, and
c3219f # config.status, which builds the config.h file and a long list of
a2c1ed # Makefiles.
11c2a6 dnl The value specified to AC_CONFIG_HEADER at the top if the file is
d59cc0 dnl used here.
5aa140 PGP_AC_OUTPUT(
bf16f2 ¤   Makefile
b17dbf ¤   priv/Makefile
ed11db ¤   priv/clientlib/Makefile
2a12e7 ¤   priv/crypto/Makefile
e8d2fc ¤   priv/crypto/bignum/Makefile
599f83 ¤   priv/crypto/cipher/Makefile
e94bdf ¤   priv/crypto/compress/Makefile
01d5c3 ¤   priv/crypto/hash/Makefile
b3f19f ¤   priv/crypto/pipe/Makefile
0552e0 ¤   priv/crypto/pipe/crypt/Makefile
11edf3 ¤   priv/crypto/pipe/file/Makefile
5a300d ¤   priv/crypto/pipe/parser/Makefile
0acb2a ¤   priv/crypto/pipe/sig/Makefile
dac956 ¤   priv/crypto/pipe/text/Makefile
71a6f0 ¤   priv/crypto/pipe/utils/Makefile
c98832 ¤   priv/crypto/random/Makefile
--ee35 001460bce0a40100119 Page 5 of configure.in
137a6c ¤   priv/crypto/secshare/Makefile
6f0ae8 ¤   priv/debug/Makefile
ef8656 ¤   priv/encrypt/Makefile
e573df ¤   priv/regexp/Makefile
477e6d ¤   priv/include/Makefile
7d7f1d ¤   priv/keys/Makefile
11d747 ¤   priv/keys/keydb/Makefile
bbba27 ¤   priv/keys/keys/Makefile
26d480 ¤   priv/keys/pubkey/Makefile
2c5a79 ¤   priv/ui/Makefile
178d01 ¤   priv/ui/common/Makefile
0801d3 ¤   priv/utilities/Makefile
1a66e9 ¤   priv/utilities/helper/Makefile
965706 ¤   priv/utilities/prefs/Makefile
080a73 ¤   priv/utilities/utils/Makefile
1e588f ¤   priv/utilities/errors/Makefile
4cdef7 ¤   priv/networklib/Makefile
e961a2 ¤   priv/networklib/keyserver/Makefile
5bbd17 ¤   priv/networklib/pgpsockets/Makefile
1b3167 ¤   priv/networklib/pgpsockets/common/Makefile
fe9788 ¤   priv/networklib/pgpsockets/unix/test/Makefile
7d499a ¤   priv/networklib/tls/Makefile
3f4394 ¤   pub/Makefile
f97356 ¤   pub/clientlib/Makefile
725b52 ¤   pub/test/Makefile
52326a ¤   unix/ui/Makefile
466ae8 ¤   pub/include/Makefile, unix/config/pre.in, unix/config/post.in)
--6b27 0012542bb414010011a Page 1 of Makefile.in
5ea601 #
e5a0fe # priv/
8ea601 #
3a90f7 # $Id: Makefile.in,v 1.7 1998/05/28 22:47:52 elowe Exp $
b1a601 #
c8af5a
c89e8e SUBDIRS=clientlib crypto debug encrypt include keys regexp \
e33d1c ¤   utilities networklib
75714b LIBDONE=clientlib/DONE crypto/LIBDONE debug/DONE encrypt/DONE \
a739c6 ¤   keys/LIBDONE regexp/DONE utilities/LIBDONE
fcaf5a
2d211d all:: LIBDONE
25af5a
--5a3d 001e7ca70694010011b Page 1 of Makefile.in
5ea601 #
840880 # prib/clientlib/
1aa601 #
5e7317 # $Id: Makefile.in,v 1.7 1997/09/03 21:24:51 markm Exp $
40a601 #
aeaf5a
f44e67 OBJS= pgpClientEncode.o pgpClientKeyDB.o
bfa900 PRIVHDRS=·
beaf5a
72b7a3 all:: DONE
e7af5a
--5544 00068036ded4010011c Page 1 of pgpClientEncode.c
a70335 /*____________________________________________________________________________
d0de55 ¤   pgpClientEncode.c
1e67c5 ¤
8cc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
b54b0f ¤   All rights reserved.
ec67c5 ¤
7067c5 ¤
77af5a
ad6740 ¤   $Id: pgpClientEncode.c,v 1.93.10.1 1998/11/12 03:21:13 heller Exp $
1ff7f7 ____________________________________________________________________________*/
bcaf5a
64324c #include <string.h>
06af5a
083051 #include "pgpSDKBuildFlags.h"
b7af5a
382f8d #include "pgpErrors.h"
59894b #include "pgpFileSpec.h"
410d08 #include "pgpMem.h"
e5af5a
fac26c #include "pgpContext.h"
109f63 #include "pgpEncode.h"
c88b0d #include "pgpEncodePriv.h"
f3a076 #include "pgpKeys.h"
5efb31 #include "pgpOptionList.h"
a1adb8 #include "pgpOpaqueStructs.h"
49979a #include "pgpKDBInt.h"
215417 #include "pgpHashPriv.h"
da0e2f #include "pgpSymmetricCipherPriv.h"
26af5a
7d0ccc #if PGP_MACINTOSH
73bbf4 #include "MacFiles.h"
147454 #endif
96af5a
0766dd ¤   static PGPError
588cd9 pgpEncode(
dfa1bc ¤   PGPContextRef¤  ¤   context,
224ae2 ¤   PGPOptionListRef ¤  firstOption,
c6a7f2 ¤   va_list¤¤   ¤   ¤   args)
d7bb36 {
348f52 ¤   PGPError¤   ¤   ¤   err;
b03ddd ¤   PGPOptionListRef¤   optionList;
4d67c5 ¤
e68679 ¤   pgpAssert( pgpContextIsValid( context ) );
1b67c5 ¤
b55014 ¤   optionList = pgpBuildOptionListArgs( context, FALSE, firstOption, args );
0867c5 ¤
3fbd44 ¤   err = pgpGetOptionListError( optionList );
c4b1f0 ¤   if( IsntPGPError( err ) )
68c7a1 ¤   {
85c953 ¤   ¤   err = pgpEncodeInternal( context, optionList );
489371 ¤   }
a667c5 ¤
cc10d0 ¤   PGPFreeOptionList( optionList );
deaf5a
5bdeb7 ¤   return( err );
23efe6 }
17af5a
b1c744 ¤   PGPError
1b35df PGPEncode(
aaa1bc ¤   PGPContextRef¤  ¤   context,
ab4ae2 ¤   PGPOptionListRef ¤  firstOption,
9b3471 ¤   ...)
6abb36 {
cb61e0 ¤   PGPError¤   err;
8b46e9 ¤   va_list¤¤   args;
1767c5 ¤
6e8679 ¤   pgpAssert( pgpContextIsValid( context ) );
a667c5 ¤
f4e8d2 ¤   if( pgpContextIsValid( context ) )
b8c7a1 ¤   {
dd02ff ¤   ¤   va_start( args, firstOption );
68e6f9 ¤   ¤   ¤   err = pgpEncode( context, firstOption, args );
--2f65 0000e8f76ff4010011c Page 2 of pgpClientEncode.c
c0c414 ¤   ¤   va_end( args );
019371 ¤   }
e10e24 ¤   else
98c7a1 ¤   {
3602ff ¤   ¤   va_start( args, firstOption );
8bed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
41c414 ¤   ¤   va_end( args );
441b52 ¤   ¤
9119d3 ¤   ¤   err = kPGPError_BadParams;
f19371 ¤   }
9767c5 ¤
a0deb7 ¤   return( err );
13efe6 }
c9af5a
2866dd ¤   static PGPError
c87be4 pgpDecode(
cba1bc ¤   PGPContextRef¤  ¤   context,
8141a1 ¤   PGPOptionListRef¤   firstOption,
27a7f2 ¤   va_list¤¤   ¤   ¤   args)
f9bb36 {
4f8f52 ¤   PGPError¤   ¤   ¤   err;
533ddd ¤   PGPOptionListRef¤   optionList;
2e67c5 ¤
708679 ¤   pgpAssert( pgpContextIsValid( context ) );
6467c5 ¤
f95014 ¤   optionList = pgpBuildOptionListArgs( context, FALSE, firstOption, args );
a167c5 ¤
31bd44 ¤   err = pgpGetOptionListError( optionList );
6bb1f0 ¤   if( IsntPGPError( err ) )
afc7a1 ¤   {
940ae1 ¤   ¤   err = pgpDecodeInternal( context, optionList );
0b1b52 ¤   ¤
959371 ¤   }
d367c5 ¤
f510d0 ¤   PGPFreeOptionList( optionList );
eb67c5 ¤
c6deb7 ¤   return( err );
48efe6 }
4faf5a
a6c744 ¤   PGPError
12c2e2 PGPDecode(
08ba07 ¤   PGPContextRef ¤ ¤   context,
b241a1 ¤   PGPOptionListRef¤   firstOption,
8f3471 ¤   ...)
8abb36 {
3961e0 ¤   PGPError¤   err;
5146e9 ¤   va_list¤¤   args;
6467c5 ¤
5d8679 ¤   pgpAssert( pgpContextIsValid( context ) );
c067c5 ¤
1be8d2 ¤   if( pgpContextIsValid( context ) )
60c7a1 ¤   {
0b02ff ¤   ¤   va_start( args, firstOption );
6e706c ¤   ¤   ¤   err = pgpDecode( context, firstOption, args );
0bc414 ¤   ¤   va_end( args );
dc9371 ¤   }
ae0e24 ¤   else
8bc7a1 ¤   {
0a02ff ¤   ¤   va_start( args, firstOption );
b7ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
31c414 ¤   ¤   va_end( args );
f41b52 ¤   ¤
f019d3 ¤   ¤   err = kPGPError_BadParams;
7f9371 ¤   }
7a67c5 ¤
15deb7 ¤   return( err );
32efe6 }
47af5a
18c744 ¤   PGPError
30bda1 PGPNewOptionList(
29a1bc ¤   PGPContextRef¤  ¤   context,
0e43dd ¤   PGPOptionListRef *¤ outList )
--20b9 000a616ea4c4010011c Page 3 of pgpClientEncode.c
2cbb36 {
b23ddd ¤   PGPOptionListRef¤   optionList;
87d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
cf67c5 ¤
b10b49 ¤   PGPValidatePtr( outList );
06df00 ¤   *outList¤   = kInvalidPGPOptionListRef;
3ef3ca ¤   PGPValidateContext( context );
cf67c5 ¤
8c43f6 ¤   /* Option lists built with PGPNewOptionList are always persistent */
bc5d6f ¤   optionList = pgpNewOptionList( context, TRUE );
67cc92 ¤   if ( pgpOptionListIsReal( optionList ) )
48c7a1 ¤   {
8716e4 ¤   ¤   *outList¤   = optionList;
e79371 ¤   }
fe0e24 ¤   else
1dc7a1 ¤   {
77c2d2 ¤   ¤   err¤= pgpOptionListToError( optionList );
a09371 ¤   }
3b67c5 ¤
e3deb7 ¤   return( err );
67efe6 }
56af5a
eec744 ¤   PGPError
256a55 PGPAddJobOptions(
f1cad7 ¤   PGPJobRef¤  ¤   ¤   job,
5541a1 ¤   PGPOptionListRef¤   firstOption,
d83471 ¤   ...)
30bb36 {
aa26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
bf46e9 ¤   va_list¤¤   args;
b91b52 ¤   ¤
05318a ¤   PGPValidatePtr( job );
6b67c5 ¤
98430c ¤   va_start( args, firstOption );
707bf9 ¤   ¤   err = pgpAddJobOptionsArgs( job, firstOption, args );
79bee0 ¤   va_end( args );
1b67c5 ¤
cedeb7 ¤   return( err );
8befe6 }
08af5a
a4c744 ¤   PGPError
305e2d PGPAppendOptionList(
56e544 ¤   PGPOptionListRef¤   optionList,
d941a1 ¤   PGPOptionListRef¤   firstOption,
4e4776 ¤   ...)·
05bb36 {
ae8e12 ¤   PGPError¤   err = kPGPError_NoErr;
0d67c5 ¤
20c43b ¤   /* don't validate 'optionList' here */
14c7a1 ¤   {
5d1d2b ¤   ¤   va_list¤args;
2a1b52 ¤   ¤
6b02ff ¤   ¤   va_start( args, firstOption );
9e744e ¤   ¤   ¤   err = pgpAppendOptionListArgs( optionList, firstOption, args );
26c414 ¤   ¤   va_end( args );
3e9371 ¤   }
6e67c5 ¤
b3deb7 ¤   return( err );
b0efe6 }
0faf5a
eec744 ¤   PGPError
989bc3 PGPBuildOptionList(
4ba1bc ¤   PGPContextRef¤  ¤   context,
eb6b62 ¤   PGPOptionListRef *¤ outList,
b2f095 ¤   PGPOptionListRef firstOption,
1a4776 ¤   ...)·
8bbb36 {
8c3ddd ¤   PGPOptionListRef¤   optionList;
61d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
1daf5a
510b49 ¤   PGPValidatePtr( outList );
a675e1 ¤   *outList¤   = NULL;
--a521 000cde812074010011c Page 4 of pgpClientEncode.c
9ef3ca ¤   PGPValidateContext( context );
6c67c5 ¤
76a425 ¤   /* don't validate 'firstOption' here */
47c7a1 ¤   {
d91d2b ¤   ¤   va_list¤args;
b91b52 ¤   ¤
8861eb ¤   ¤   /* Option lists built with pgpBuildOptionListInternal are
475f71 ¤   ¤   ···always persistent */
1602ff ¤   ¤   va_start( args, firstOption );
7f689b ¤   ¤   ¤   optionList = pgpBuildOptionListArgs( context,
ec7aac ¤   ¤   ¤   ¤   TRUE, firstOption, args );
8cc414 ¤   ¤   va_end( args );
279371 ¤   }
e867c5 ¤
44cc92 ¤   if ( pgpOptionListIsReal( optionList ) )
30c7a1 ¤   {
a416e4 ¤   ¤   *outList¤   = optionList;
459371 ¤   }
5f0e24 ¤   else
9ac7a1 ¤   {
a2c2d2 ¤   ¤   err¤= pgpOptionListToError( optionList );
9d9371 ¤   }
c267c5 ¤
0cdeb7 ¤   return( err );
b8efe6 }
36af5a
3ec744 ¤   PGPError
8b1811 PGPCopyOptionList(
9fe544 ¤   PGPOptionListRef¤   optionList,
199f4a ¤   PGPOptionListRef *¤ ¤   outList
30a753 ¤   )·
e6bb36 {
9cf209 ¤   PGPOptionListRef¤   newOptionList;
5dd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
c867c5 ¤
cf0b49 ¤   PGPValidatePtr( outList );
d075e1 ¤   *outList¤   = NULL;
191189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
f267c5 ¤
41f79e ¤   newOptionList = pgpCopyOptionList( optionList );
f567c5 ¤
a20a6e ¤   if ( pgpOptionListIsReal( newOptionList ) )
1dc7a1 ¤   {
e52f22 ¤   ¤   *outList¤   = newOptionList;
da9371 ¤   }
120e24 ¤   else
34c7a1 ¤   {
349368 ¤   ¤   err¤= pgpOptionListToError( newOptionList );
eb9371 ¤   }
6c67c5 ¤
9adeb7 ¤   return( err );
0fefe6 }
dcaf5a
93c744 ¤   PGPError
7fcce1 PGPFreeOptionList(PGPOptionListRef optionList)
55bb36 {
1f8e12 ¤   PGPError¤   err = kPGPError_NoErr;
5067c5 ¤
4b1189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
d167c5 ¤
dfa78e ¤   pgpFreeOptionList( optionList );
9267c5 ¤
0edeb7 ¤   return( err );
f6efe6 }
18af5a
aeaf5a
e9af5a
8638e5 /*
ab72dd **¤ This is the handler proc for standard allocated options.
df4396 **¤ The free procedure calls pgpContextMemFree() to release
f69dc3 **¤ the allocation and the copy procedure calls pgpContextMemAlloc()
cd320c **¤ to create a copy.
--60f5 000139ee4fc4010011c Page 5 of pgpClientEncode.c
c77fe0 */
e6af5a
4e66dd ¤   static PGPError
b7f5d1 AllocatedOptionHandlerProc(
44883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
cd0315 ¤   PGPOptionHandlerOperation ¤ operation,
9f1a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
bdd276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
73a79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
2348db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
5c4ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
82bb36 {
908e12 ¤   PGPError¤   err = kPGPError_NoErr;
1067c5 ¤
c8b643 ¤   switch( operation )
37c7a1 ¤   {
f84885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
bd5b34 ¤   ¤   {
2415b6 ¤   ¤   ¤   if( type == kPGPOptionType_AdditionalRecipientRequestKeySet ||
939e60 ¤   ¤   ¤   ¤   type == kPGPOptionType_RevocationKeySet ) {
d011cc ¤   ¤   ¤   ¤   PGPOAdditionalRecipientRequestKeySetDesc¤   *descriptor;
c3baae ¤   ¤   ¤   ¤   descriptor = (PGPOAdditionalRecipientRequestKeySetDesc *)
8b6ea7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inputValue.asPtr;
6840f9 ¤   ¤   ¤   ¤   PGPFreeKeySet( descriptor->arKeySetRef );
99a3a6 ¤   ¤   ¤   }
862b85 ¤   ¤   ¤   ¤
dc4b83 ¤   ¤   ¤   pgpContextMemFree( context, inputValue.asPtr );
fecdcb ¤   ¤   ¤   break;
ec0fe4 ¤   ¤   }
8787c7 ¤   ¤   ¤
930dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
085b34 ¤   ¤   {
76bd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
46cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
ebaf5a
ba0e31 ¤   ¤   ¤   outputValue->asPtr = pgpContextMemAlloc( context, inputValueSize,
991955 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·0 );
01a24a ¤   ¤   ¤   if( IsntNull( outputValue->asPtr ) )
1c8cf3 ¤   ¤   ¤   {¤
d4bf8d ¤   ¤   ¤   ¤   pgpCopyMemory( inputValue.asPtr, outputValue->asPtr,
f7b7df ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···inputValueSize );
922b85 ¤   ¤   ¤   ¤
a256f4 ¤   ¤   ¤   ¤   if( type == kPGPOptionType_AdditionalRecipientRequestKeySet||
c95a7c ¤   ¤   ¤   ¤   ¤   type == kPGPOptionType_RevocationKeySet ) {
368c16 ¤   ¤   ¤   ¤   ¤   PGPOAdditionalRecipientRequestKeySetDesc¤   *descriptor;
3dc3e4 ¤   ¤   ¤   ¤   ¤   descriptor = (PGPOAdditionalRecipientRequestKeySetDesc *)
ffb275 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outputValue->asPtr;
8419fb ¤   ¤   ¤   ¤   ¤   PGPIncKeySetRefCount( descriptor->arKeySetRef );
cf2613 ¤   ¤   ¤   ¤   }
32af5a
d32c0a ¤   ¤   ¤   ¤   *outputValueSize = inputValueSize;
e3a3a6 ¤   ¤   ¤   }
f1bb8c ¤   ¤   ¤   else
edf776 ¤   ¤   ¤   {
3bbfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
30a3a6 ¤   ¤   ¤   }
a087c7 ¤   ¤   ¤
61cdcb ¤   ¤   ¤   break;
ec0fe4 ¤   ¤   }
da1b52 ¤   ¤
1d9ae3 ¤   ¤   default:
e15b34 ¤   ¤   {
9fe119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
f8cdcb ¤   ¤   ¤   break;
c70fe4 ¤   ¤   }
f59371 ¤   }
03af5a
2edeb7 ¤   return( err );
3defe6 }
54af5a
3a38e5 /*
137d2b **¤ This is the handler proc for options which don't need any
--b9a9 000a4080b0d4010011c Page 6 of pgpClientEncode.c
1d4fd0 **¤ routine copying, but for which certain ones may need special
cdba95 **¤ treatment.
6d7fe0 */
c4af5a
ca66dd ¤   static PGPError
1f2568 SpecialOptionHandlerProc(
5e883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
270315 ¤   PGPOptionHandlerOperation ¤ operation,
b71a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
f9d276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
9fa79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
0848db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
614ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
b8bb36 {
7f8e12 ¤   PGPError¤   err = kPGPError_NoErr;
3967c5 ¤
4e6d02 ¤   (void) context;
1ea835 ¤   (void) inputValueSize;
d89fb0 ¤   (void) outputValueSize;
90af5a
deb643 ¤   switch( operation )
b3c7a1 ¤   {
0f4885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
b85b34 ¤   ¤   {
7689dc ¤   ¤   ¤   switch( type ) {
65af1e ¤   ¤   ¤   case kPGPOptionType_EncryptToKey:
abe88c ¤   ¤   ¤   case kPGPOptionType_SignWithKey:
e6ece2 ¤   ¤   ¤   case kPGPOptionType_KeyGenMasterKey:
36badc ¤   ¤   ¤   ¤   pgpFreeKey( inputValue.asKeyRef );
bbf622 ¤   ¤   ¤   ¤   break;
1a6542 ¤   ¤   ¤   case kPGPOptionType_EncryptToKeySet:
443e26 ¤   ¤   ¤   case kPGPOptionType_KeySetRef:
950990 ¤   ¤   ¤   case kPGPOptionType_ImportKeysTo:
66086a ¤   ¤   ¤   ¤   PGPFreeKeySet( inputValue.asKeySetRef );
e1f622 ¤   ¤   ¤   ¤   break;
a5656b ¤   ¤   ¤   case kPGPOptionType_EncryptToUserID:
98546b ¤   ¤   ¤   ¤   pgpFreeUserID( inputValue.asUserIDRef );
0ff622 ¤   ¤   ¤   ¤   break;
a4db68 ¤   ¤   ¤   default:
2ef622 ¤   ¤   ¤   ¤   break;
c7a3a6 ¤   ¤   ¤   }
83cdcb ¤   ¤   ¤   break;
460fe4 ¤   ¤   }
f387c7 ¤   ¤   ¤
170dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
bd5b34 ¤   ¤   {
3a89dc ¤   ¤   ¤   switch( type ) {
03af1e ¤   ¤   ¤   case kPGPOptionType_EncryptToKey:
6ee88c ¤   ¤   ¤   case kPGPOptionType_SignWithKey:
d4ece2 ¤   ¤   ¤   case kPGPOptionType_KeyGenMasterKey:
9e7c52 ¤   ¤   ¤   ¤   pgpIncKeyRefCount( outputValue->asKeyRef );
2bf622 ¤   ¤   ¤   ¤   break;
a36542 ¤   ¤   ¤   case kPGPOptionType_EncryptToKeySet:
133e26 ¤   ¤   ¤   case kPGPOptionType_KeySetRef:
500990 ¤   ¤   ¤   case kPGPOptionType_ImportKeysTo:
456a13 ¤   ¤   ¤   ¤   PGPIncKeySetRefCount( outputValue->asKeySetRef );
5ef622 ¤   ¤   ¤   ¤   break;
92656b ¤   ¤   ¤   case kPGPOptionType_EncryptToUserID:
ab2ac1 ¤   ¤   ¤   ¤   pgpIncUserIDRefCount( outputValue->asUserIDRef );
c0f622 ¤   ¤   ¤   ¤   break;
bddb68 ¤   ¤   ¤   default:
b9f622 ¤   ¤   ¤   ¤   break;
80a3a6 ¤   ¤   ¤   }
7bcdcb ¤   ¤   ¤   break;
060fe4 ¤   ¤   }
ad1b52 ¤   ¤
979ae3 ¤   ¤   default:
bb5b34 ¤   ¤   {
6ee119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
4dcdcb ¤   ¤   ¤   break;
590fe4 ¤   ¤   }
a49371 ¤   }
--2048 00060deb8984010011c Page 7 of pgpClientEncode.c
e0af5a
f8deb7 ¤   return( err );
20efe6 }
d8af5a
a6af5a
5067c5 ¤
a613fb ¤   PGPOptionListRef
501e5d PGPOLastOption( PGPContextRef context )
55bb36 {
4a1aa1 ¤   pgpValidateOptionContext( context );
01af5a
b0bd3b ¤   return( kPGPEndOfArgsOptionListRef );
68efe6 }
09af5a
0213fb ¤   PGPOptionListRef
e88aa5 PGPONullOption( PGPContextRef context )
76bb36 {
721aa1 ¤   pgpValidateOptionContext( context );
2baf5a
c28e42 ¤   return( kPGPNullOptionListRef );
adefe6 }
c0af5a
2f13fb ¤   PGPOptionListRef
37a1b9 PGPOInputFile(
2a35f6 ¤   PGPContextRef ¤ context,
d0d00b ¤   PGPFileSpecRef fileRef)
07bb36 {
f71aa1 ¤   pgpValidateOptionContext( context );
cde449 ¤   pgpValidateOptionParam( pflFileSpecIsValid( (PFLFileSpecRef)fileRef ) );
a767c5 ¤
bf182b ¤   return( pgpCreateFileRefOptionList( context,
81dc4b ¤   ¤   ¤   ¤   kPGPOptionType_InputFileRef, fileRef ) );
03efe6 }
0eaf5a
38c21c #if PGP_MACINTOSH¤  /* [ */
c3af5a
2e13fb ¤   PGPOptionListRef
57d0a7 PGPOInputFileFSSpec(
7d35f6 ¤   PGPContextRef ¤ context,
bb291c ¤   const FSSpec¤   *fileSpec)
37bb36 {
663ddd ¤   PGPOptionListRef¤   optionList;
7bc784 ¤   PGPFileSpecRef¤ ¤   fileRef;
4e67c5 ¤
8b1aa1 ¤   pgpValidateOptionContext( context );
f635db ¤   pgpValidateOptionParam( FSSpecIsValid( fileSpec ) );
3067c5 ¤
08df9f ¤   if( IsntPGPError( PGPNewFileSpecFromFSSpec( context,
9d9091 ¤   ¤   ¤   fileSpec, &fileRef ) ) )
fec7a1 ¤   {
bcc79e ¤   ¤   optionList = pgpCreateFileRefOptionList( context,
24de85 ¤   ¤   ¤   kPGPOptionType_InputFileRef, fileRef );
b287c7 ¤   ¤   ¤
bd97f2 ¤   ¤   PGPFreeFileSpec( fileRef );
c79371 ¤   }
1b0e24 ¤   else
e1c7a1 ¤   {
7a1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
ec9371 ¤   }
dd67c5 ¤
6a8233 ¤   return( optionList );
2eefe6 }
31af5a
3e3167 #endif¤ /* ] */
5eaf5a
4213fb ¤   PGPOptionListRef
cde631 PGPOInputBuffer(
e2520e ¤   PGPContextRef¤  context,
241ddb ¤   void const *¤   buffer,
32e680 ¤   PGPSize¤¤   ¤   bufferSize)
19bb36 {
603ddd ¤   PGPOptionListRef¤   optionList;
--a37a 00047d75db34010011c Page 8 of pgpClientEncode.c
8c0cfd ¤   PGPOptionValue¤ ¤   value;
8b67c5 ¤
1e1aa1 ¤   pgpValidateOptionContext( context );
30acec ¤   pgpValidateOptionParam( IsntNull( buffer ) );
9cfb6e ¤   /* buffer size may be 0 */
8d67c5 ¤
af566b ¤   value.asConstPtr¤   = buffer;
ce3c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
469d44 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_InputBuffer,
df6fe2 ¤   ¤   ¤   ¤   ¤   ¤   &value, bufferSize, NULL );
49af5a
348233 ¤   return( optionList );
c5efe6 }
93af5a
eb13fb ¤   PGPOptionListRef
569fbe PGPOOutputFile(
54520e ¤   PGPContextRef¤  context,
2dd00b ¤   PGPFileSpecRef fileRef)
17bb36 {
ce1aa1 ¤   pgpValidateOptionContext( context );
b7e449 ¤   pgpValidateOptionParam( pflFileSpecIsValid( (PFLFileSpecRef)fileRef ) );
3567c5 ¤
69182b ¤   return( pgpCreateFileRefOptionList( context,
07895f ¤   ¤   ¤   ¤   kPGPOptionType_OutputFileRef, fileRef ) );
7aefe6 }
2eaf5a
5013fb ¤   PGPOptionListRef
0073c4 PGPOOutputBuffer(
6f520e ¤   PGPContextRef¤  context,
a3d8ca ¤   void¤   ¤   ¤   *buffer,
7a9838 ¤   PGPSize¤¤   ¤   bufferSize,
5f7a3a ¤   PGPSize¤¤   ¤   *outputDataLength)
49bb36 {
1d710b ¤   PGPOptionListRef¤   ¤   optionList;
b463fc ¤   PGPOOutputBufferDesc¤   *descriptor;
be67c5 ¤
e3cfe1 ¤   pgpValidateOptionParam( IsntNull( outputDataLength ) );
5001c8 ¤   *outputDataLength¤  = 0;
1f1aa1 ¤   pgpValidateOptionContext( context );
627ced ¤   pgpValidateOptionParam( IsntNull( buffer ) && bufferSize > 0 );
99af5a
3359ad ¤   pgpDebugWhackMemory( buffer, bufferSize );
0267c5 ¤
dcf00a ¤   descriptor = (PGPOOutputBufferDesc *)
b2f321 ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor),
c1f048 ¤   ¤   kPGPMemoryMgrFlags_Clear);
b9cc91 ¤   if( IsntNull( descriptor ) )
c4c7a1 ¤   {
bfdc71 ¤   ¤   PGPOptionValue¤ value;
b01b52 ¤   ¤
df47f4 ¤   ¤   descriptor->buffer ¤¤   ¤   ¤   = buffer;
282663 ¤   ¤   descriptor->bufferSize ¤¤   ¤   = bufferSize;
d286c0 ¤   ¤   descriptor->outputDataLength¤   = outputDataLength;
001b52 ¤   ¤
8ebb8d ¤   ¤   value.asPtr = descriptor;
3e1b52 ¤   ¤
00e6a3 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context,·
253ca7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_OutputBuffer,
d3f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
3d2d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
699371 ¤   }
3d0e24 ¤   else
87c7a1 ¤   {
ce1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
839371 ¤   }
7f67c5 ¤
f88233 ¤   return( optionList );
8cefe6 }
cdaf5a
64c21c #if PGP_MACINTOSH¤  /* [ */
bfaf5a
4713fb ¤   PGPOptionListRef
--6c69 000138ad3f34010011c Page 9 of pgpClientEncode.c
bc791f PGPOOutputFileFSSpec(
d035f6 ¤   PGPContextRef ¤ context,
b4291c ¤   const FSSpec¤   *fileSpec)
77bb36 {
923ddd ¤   PGPOptionListRef¤   optionList;
f3c784 ¤   PGPFileSpecRef¤ ¤   fileRef;
0467c5 ¤
e21aa1 ¤   pgpValidateOptionContext( context );
e535db ¤   pgpValidateOptionParam( FSSpecIsValid( fileSpec ) );
1f67c5 ¤
28df9f ¤   if( IsntPGPError( PGPNewFileSpecFromFSSpec( context,
a59091 ¤   ¤   ¤   fileSpec, &fileRef ) ) )
41c7a1 ¤   {
7ac79e ¤   ¤   optionList = pgpCreateFileRefOptionList( context,
5ca976 ¤   ¤   ¤   kPGPOptionType_OutputFileRef, fileRef );
8b87c7 ¤   ¤   ¤
f497f2 ¤   ¤   PGPFreeFileSpec( fileRef );
159371 ¤   }
670e24 ¤   else
50c7a1 ¤   {
1b1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
739371 ¤   }
e167c5 ¤
bc8233 ¤   return( optionList );
2defe6 }
8faf5a
773167 #endif¤ /* ] */
37af5a
ca13fb ¤   PGPOptionListRef
aa57d5 PGPOAllocatedOutputBuffer(
fe520e ¤   PGPContextRef¤  context,
52e8fb ¤   void¤   ¤   ¤   **buffer,
f866aa ¤   PGPSize¤¤   ¤   maximumBufferSize,
c83c08 ¤   PGPSize¤¤   ¤   *actualBufferSize)
cfbb36 {
02ff7a ¤   PGPOptionListRef¤   ¤   ¤   ¤   optionList;
1245b7 ¤   PGPOAllocatedOutputBufferDesc¤  *descriptor;
cd67c5 ¤
7f4794 ¤   if ( IsntNull( buffer ) )
94751d ¤   ¤   *buffer¤= NULL;
2e4fab ¤   if ( IsntNull( actualBufferSize ) )
0d8fa2 ¤   ¤   *actualBufferSize¤  = 0;
bfacec ¤   pgpValidateOptionParam( IsntNull( buffer ) );
646aca ¤   pgpValidateOptionParam( IsntNull( actualBufferSize ) );
f6d459 ¤   pgpValidateOptionParam( maximumBufferSize > 0 );
7f1aa1 ¤   pgpValidateOptionContext( context );
e167c5 ¤
f1a06c ¤   descriptor = (PGPOAllocatedOutputBufferDesc *)
54cb55 ¤   ¤   ¤   pgpContextMemAlloc( context,
3abdd6 ¤   ¤   ¤   ¤   sizeof(*descriptor), kPGPMemoryMgrFlags_Clear);
1bcc91 ¤   if( IsntNull( descriptor ) )
4fc7a1 ¤   {
22dc71 ¤   ¤   PGPOptionValue¤ value;
a51b52 ¤   ¤
7747f4 ¤   ¤   descriptor->buffer ¤¤   ¤   ¤   = buffer;
f992d9 ¤   ¤   descriptor->maximumBufferSize ¤ = maximumBufferSize;
03dd73 ¤   ¤   descriptor->actualBufferSize¤   = actualBufferSize;
d41b52 ¤   ¤
c1bb8d ¤   ¤   value.asPtr = descriptor;
e31b52 ¤   ¤
2eb747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
8f8f90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_OutputAllocatedBuffer,
99f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
0c2d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
e49371 ¤   }
1c0e24 ¤   else
4bc7a1 ¤   {
3a1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
a39371 ¤   }
0b67c5 ¤
288233 ¤   return( optionList );
13efe6 }
--3946 000cca215864010011c Page 10 of pgpClientEncode.c
e0af5a
ec764c /* Not yet supported */
1c13fb ¤   PGPOptionListRef
1ba439 PGPOAppendOutput(
a9520e ¤   PGPContextRef¤  context,
673ad0 ¤   PGPBoolean¤ ¤   appendOutput
ad27e6 ¤   )
a0bb36 {
a43ddd ¤   PGPOptionListRef¤   optionList;
d90cfd ¤   PGPOptionValue¤ ¤   value;
0e67c5 ¤
aa1aa1 ¤   pgpValidateOptionContext( context );
85af5a
5c33d2 ¤   value.asUInt = (PGPUInt32)appendOutput;
4167c5 ¤
6b0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
4deb5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_AppendOutput,
065974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
54af5a
cb8233 ¤   return( optionList );
11efe6 }
dbaf5a
9f13fb ¤   PGPOptionListRef
ea1d7d PGPODiscardOutput(
57520e ¤   PGPContextRef¤  context,
715b80 ¤   PGPBoolean¤ ¤   discardOutput
1327e6 ¤   )
4bbb36 {
443ddd ¤   PGPOptionListRef¤   optionList;
a80cfd ¤   PGPOptionValue¤ ¤   value;
f967c5 ¤
aa1aa1 ¤   pgpValidateOptionContext( context );
d5af5a
52913f ¤   value.asUInt = (PGPUInt32)discardOutput;
bc67c5 ¤
110b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
a148ae ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DiscardOutput,
d35974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
a7af5a
738233 ¤   return( optionList );
e1efe6 }
5baf5a
f7af5a
81b177 #if 0
4daf5a
e713fb ¤   PGPOptionListRef
b3b85d PGPOAskUserForOutput(
60520e ¤   PGPContextRef¤  context,
1ec943 ¤   PGPBoolean¤ ¤   askUserForOutput
e627e6 ¤   )
76bb36 {
053ddd ¤   PGPOptionListRef¤   optionList;
370cfd ¤   PGPOptionValue¤ ¤   value;
6667c5 ¤
c21aa1 ¤   pgpValidateOptionContext( context );
b8af5a
75388a ¤   value.asUInt = (PGPUInt32)askUserForOutput;
0867c5 ¤
d70b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
5d3f09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_AskUserForOutput,
235974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
a6af5a
828233 ¤   return( optionList );
82efe6 }
b97454 #endif
a0af5a
15af5a
a0af5a
db13fb ¤   PGPOptionListRef
bbde51 PGPOEncryptToKey(
fc520e ¤   PGPContextRef¤  context,
ccc54e ¤   PGPKeyRef¤  ¤   keyRef
--edfb 000d635cad34010011c Page 11 of pgpClientEncode.c
7f27e6 ¤   )
dbbb36 {
ee3ddd ¤   PGPOptionListRef¤   optionList;
cf0cfd ¤   PGPOptionValue¤ ¤   value;
b567c5 ¤
ee1aa1 ¤   pgpValidateOptionContext( context );
327cae ¤   pgpValidateOptionParam( pgpKeyIsValid( keyRef ) );
9467c5 ¤
a8759d ¤   value.asKeyRef = keyRef;
68af5a
be7175 ¤   pgpIncKeyRefCount( keyRef );
d5af5a
e50b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
969132 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EncryptToKey,
52c1eb ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( keyRef ),
3399c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
ff67c5 ¤
f54641 #if PGP_ENCRYPT_DISABLE
30d537 ¤   pgpSetOptionListError( optionList, kPGPError_FeatureNotAvailable );
6c7454 #endif
0eaf5a
318233 ¤   return( optionList );
9fefe6 }
b1af5a
c313fb ¤   PGPOptionListRef
8ec406 PGPOEncryptToKeySet(
90520e ¤   PGPContextRef¤  context,
05d327 ¤   PGPKeySetRef¤   keySetRef
6c27e6 ¤   )
50bb36 {
f93ddd ¤   PGPOptionListRef¤   optionList;
6a0cfd ¤   PGPOptionValue¤ ¤   value;
d867c5 ¤
601aa1 ¤   pgpValidateOptionContext( context );
65bbbb ¤   pgpValidateOptionParam( pgpKeySetIsValid( keySetRef ) );
1e67c5 ¤
f406aa ¤   value.asKeySetRef = keySetRef;
72af5a
cfef8a ¤   PGPIncKeySetRefCount( keySetRef );
1aaf5a
100b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
8ea1f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EncryptToKeySet,
17fe0c ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( keySetRef ),
4c99c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
4e67c5 ¤
794641 #if PGP_ENCRYPT_DISABLE
0bd537 ¤   pgpSetOptionListError( optionList, kPGPError_FeatureNotAvailable );
377454 #endif
dbaf5a
048233 ¤   return( optionList );
c1efe6 }
61af5a
be13fb ¤   PGPOptionListRef
b6c42f PGPOEncryptToUserID(
ac520e ¤   PGPContextRef¤  context,
34738d ¤   PGPUserIDRef¤   userIDRef
3227e6 ¤   )
5abb36 {
b33ddd ¤   PGPOptionListRef¤   optionList;
460cfd ¤   PGPOptionValue¤ ¤   value;
d567c5 ¤
fb1aa1 ¤   pgpValidateOptionContext( context );
988de7 ¤   pgpValidateOptionParam( PGPUserIDRefIsValid( userIDRef ) );
1d67c5 ¤
61cd0e ¤   value.asUserIDRef = userIDRef;
c6af5a
ae0f57 ¤   pgpIncUserIDRefCount( userIDRef );
11af5a
753c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
4da1d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EncryptToUserID,
90cff9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( userIDRef ),
d699c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
--a4d8 000690238154010011c Page 12 of pgpClientEncode.c
2a67c5 ¤
494641 #if PGP_ENCRYPT_DISABLE
5dd537 ¤   pgpSetOptionListError( optionList, kPGPError_FeatureNotAvailable );
a37454 #endif
31af5a
a48233 ¤   return( optionList );
41efe6 }
06af5a
5813fb ¤   PGPOptionListRef
fea56c PGPOSignWithKey(
5ba1bc ¤   PGPContextRef¤  ¤   context,
26c209 ¤   PGPKeyRef¤  ¤   ¤   keyRef,
a641a1 ¤   PGPOptionListRef¤   firstOption,
7b3471 ¤   ...)
9bbb36 {
c93ddd ¤   PGPOptionListRef¤   optionList;
cc67c5 ¤
3c8679 ¤   pgpAssert( pgpContextIsValid( context ) );
86eed9 ¤   pgpAssert( pgpKeyIsValid( keyRef ) );
0867c5 ¤
e1be5f ¤   if( pgpKeyIsValid( keyRef ) && pgpContextIsValid( context ) )
53c7a1 ¤   {
6958a8 ¤   ¤   PGPOptionListRef¤   subOptions;
ab8082 ¤   ¤   PGPOptionValue¤ ¤   value;
4e36db ¤   ¤   va_list¤¤   ¤   ¤   args;
7c1b52 ¤   ¤
d702ff ¤   ¤   va_start( args, firstOption );
1d74c8 ¤   ¤   ¤   subOptions = pgpBuildOptionListArgs( context,
2f307f ¤   ¤   ¤   ¤   FALSE, firstOption, args );
4fc414 ¤   ¤   va_end( args );
1aaf5a
0acecb ¤   ¤   value.asKeyRef = keyRef;
6d67c5 ¤
d34c1d ¤   ¤   pgpIncKeyRefCount( keyRef );
d0af5a
d0c11b ¤   ¤   optionList = pgpCreateCustomValueOptionList(
4f5e91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   context,
9204e2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_SignWithKey,
d95fdd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Default, &value,
f6b190 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( keyRef ), subOptions,
6a1696 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
3b9371 ¤   }
d10e24 ¤   else
3ac7a1 ¤   {
0536db ¤   ¤   va_list¤¤   ¤   ¤   args;
2b1b52 ¤   ¤
2102ff ¤   ¤   va_start( args, firstOption );
baed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
4ac414 ¤   ¤   va_end( args );
891b52 ¤   ¤
4eb46d ¤   ¤   optionList = kPGPBadParamsOptionListRef;
de9371 ¤   }
6167c5 ¤
ccdb05 #if PGP_SIGN_DISABLE
5bd537 ¤   pgpSetOptionListError( optionList, kPGPError_FeatureNotAvailable );
237454 #endif
deaf5a
f98233 ¤   return( optionList );
ccefe6 }
94af5a
d413fb ¤   PGPOptionListRef
da7a4d PGPOConventionalEncrypt(
2d520e ¤   PGPContextRef¤  context,
0cf095 ¤   PGPOptionListRef firstOption,
443471 ¤   ...)
aebb36 {
cd3ddd ¤   PGPOptionListRef¤   optionList;
6c9dfd ¤   PGPOptionListRef¤   subOptions;
6701d3 ¤   va_list¤¤   ¤   ¤   args;
aa67c5 ¤
048679 ¤   pgpAssert( pgpContextIsValid( context ) );
69af5a
--2562 000322bcebb4010011c Page 13 of pgpClientEncode.c
189b55 ¤   if ( pgpContextIsValid( context ) )
dfc7a1 ¤   {
2a02ff ¤   ¤   va_start( args, firstOption );
9a74c8 ¤   ¤   ¤   subOptions = pgpBuildOptionListArgs( context,
1abe6e ¤   ¤   ¤   ¤   ¤   ¤   FALSE, firstOption, args );
0dc414 ¤   ¤   va_end( args );
1eaf5a
17c11b ¤   ¤   optionList = pgpCreateCustomValueOptionList(
b85cbc ¤   ¤   ¤   ¤   ¤   ¤   context, ·
95d567 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ConventionalEncrypt,
b4ae37 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Default, NULL,
d9e059 ¤   ¤   ¤   ¤   ¤   ¤   0, subOptions, NULL);
4e9371 ¤   }
2c0e24 ¤   else
e4c7a1 ¤   {
0502ff ¤   ¤   va_start( args, firstOption );
bfed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
20c414 ¤   ¤   va_end( args );
931b52 ¤   ¤
a8b46d ¤   ¤   optionList = kPGPBadParamsOptionListRef;
f49371 ¤   }
2e67c5 ¤
024641 #if PGP_ENCRYPT_DISABLE
ffd537 ¤   pgpSetOptionListError( optionList, kPGPError_FeatureNotAvailable );
097454 #endif
16af5a
ec8233 ¤   return( optionList );
64efe6 }
53af5a
9613fb ¤   PGPOptionListRef
d7129b PGPOPassphraseBuffer(
57520e ¤   PGPContextRef¤  context,
bb5053 ¤   const void *¤   passphrase,
c381c1 ¤   PGPSize¤¤   ¤   passphraseLength)
0fbb36 {
e61aa1 ¤   pgpValidateOptionContext( context );
9f28b0 ¤   pgpValidateOptionParam( IsntNull( passphrase ) );
2a67c5 ¤
621b80 ¤   return( pgpCreateSensitiveOptionList( context,
2ca28e ¤   ¤   ¤   ¤   kPGPOptionType_Passphrase, passphrase, passphraseLength ) );
9eefe6 }
81af5a
2d13fb ¤   PGPOptionListRef
cf50c6 PGPOPassphrase(
a7520e ¤   PGPContextRef¤  context,
33b6c4 ¤   const char *¤   passphrase)
21bb36 {
a727e0 ¤   PGPSize¤¤   ¤   passphraseLength;
95af5a
d31aa1 ¤   pgpValidateOptionContext( context );
5428b0 ¤   pgpValidateOptionParam( IsntNull( passphrase ) );
b9af5a
14bc8f ¤   /* Don't include trailing null, it is not used in the hash operations */
c8f13f ¤   passphraseLength = strlen( passphrase );
ae67c5 ¤
871b80 ¤   return( pgpCreateSensitiveOptionList( context,
22a28e ¤   ¤   ¤   ¤   kPGPOptionType_Passphrase, passphrase, passphraseLength ) );
edefe6 }
f2af5a
8baf5a
cf13fb ¤   PGPOptionListRef
2df469 PGPOPasskeyBuffer(
dd520e ¤   PGPContextRef¤  context,
d71abf ¤   const void *¤   passkey,
3f5ad0 ¤   PGPSize¤¤   ¤   passkeyLength)
a1bb36 {
1d1aa1 ¤   pgpValidateOptionContext( context );
3bcaae ¤   pgpValidateOptionParam( IsntNull( passkey ) );
e067c5 ¤
531b80 ¤   return( pgpCreateSensitiveOptionList( context,
1bdb7a ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, passkey, passkeyLength ) );
32efe6 }
--2ce9 0006bde3b134010011c Page 14 of pgpClientEncode.c
e0af5a
1aaf5a
b313fb ¤   PGPOptionListRef
e68b8a PGPODetachedSig(
92520e ¤   PGPContextRef¤  context,
4af095 ¤   PGPOptionListRef firstOption,
f13471 ¤   ...)
c2bb36 {
223ddd ¤   PGPOptionListRef¤   optionList;
129dfd ¤   PGPOptionListRef¤   subOptions;
3501d3 ¤   va_list¤¤   ¤   ¤   args;
e867c5 ¤
a28679 ¤   pgpAssert( pgpContextIsValid( context ) );
35af5a
423ad0 ¤   if ( pgpContextIsValid( context ) ·)
f3c7a1 ¤   {
7802ff ¤   ¤   va_start( args, firstOption );
6e74c8 ¤   ¤   ¤   subOptions = pgpBuildOptionListArgs( context,
a2307f ¤   ¤   ¤   ¤   FALSE, firstOption, args );
d0c414 ¤   ¤   va_end( args );
7aaf5a
324c52 ¤   ¤   optionList = pgpCreateCustomValueOptionList( context,·
491c0c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DetachedSignature,
3c4f40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Default, NULL,
6b0166 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, subOptions, NULL);
8d9371 ¤   }
4d0e24 ¤   else
49c7a1 ¤   {
a802ff ¤   ¤   va_start( args, firstOption );
6fed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
27c414 ¤   ¤   va_end( args );
aa1b52 ¤   ¤
c8b46d ¤   ¤   optionList = kPGPBadParamsOptionListRef;
a29371 ¤   }
b767c5 ¤
558233 ¤   return( optionList );
d9efe6 }
72af5a
d7b177 #if 0
c7f6af /* Not supported */
9713fb ¤   PGPOptionListRef
4b14d6 PGPOMailHeaders(
5b520e ¤   PGPContextRef¤  context,
e9f095 ¤   PGPOptionListRef firstOption,
a23471 ¤   ...)
1cbb36 {
aa3ddd ¤   PGPOptionListRef¤   optionList;
f69dfd ¤   PGPOptionListRef¤   subOptions;
1601d3 ¤   va_list¤¤   ¤   ¤   args;
7e67c5 ¤
c88679 ¤   pgpAssert( pgpContextIsValid( context ) );
caaf5a
6e430c ¤   va_start( args, firstOption );
4877bf ¤   ¤   subOptions = pgpBuildOptionListArgs( context,
82b819 ¤   ¤   ¤   FALSE, firstOption, args );
88bee0 ¤   va_end( args );
5baf5a
a04cb0 ¤   optionList = pgpCreateCustomValueOptionList( context,·
643a0f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_MailHeaders,
20ad40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Default, NULL,
cbaf67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, subOptions, NULL);
2d67c5 ¤
778233 ¤   return( optionList );
bfefe6 }
2d7454 #endif
71af5a
c113fb ¤   PGPOptionListRef
ac6923 PGPOCipherAlgorithm(
34520e ¤   PGPContextRef¤  context,
81e93d ¤   PGPCipherAlgorithm¤ algorithm
ba27e6 ¤   )
6bbb36 {
--3448 00057e3d5ce4010011c Page 15 of pgpClientEncode.c
f03ddd ¤   PGPOptionListRef¤   optionList;
920cfd ¤   PGPOptionValue¤ ¤   value;
3c67c5 ¤
3f1aa1 ¤   pgpValidateOptionContext( context );
55c34f ¤   pgpValidateOptionParam( algorithm == kPGPCipherAlgorithm_IDEA ||
9027ab ¤   ¤   algorithm == kPGPCipherAlgorithm_3DES ||
59f9cc ¤   ¤   algorithm == kPGPCipherAlgorithm_CAST5 );
c3af5a
dda1dd ¤   value.asCipherAlgorithm = algorithm;
8c67c5 ¤
650b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
230cd4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_CipherAlgorithm,
37870b ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( algorithm ), NULL);
4267c5 ¤
5b8233 ¤   return( optionList );
a5efe6 }
d6af5a
2313fb ¤   PGPOptionListRef
091bc1 PGPOHashAlgorithm(
80a1bc ¤   PGPContextRef¤  ¤   context,
fbc9d1 ¤   PGPHashAlgorithm¤   algorithm
d727e6 ¤   )
8cbb36 {
b53ddd ¤   PGPOptionListRef¤   optionList;
ed0cfd ¤   PGPOptionValue¤ ¤   value;
d01b52 ¤   ¤
091aa1 ¤   pgpValidateOptionContext( context );
932aff ¤   pgpValidateOptionParam( algorithm == kPGPHashAlgorithm_MD5 ||
89f57d ¤   ¤   algorithm == kPGPHashAlgorithm_SHA ||
e04f04 ¤   ¤   algorithm == kPGPHashAlgorithm_RIPEMD160 );
2aaf5a
5f8ef7 ¤   value.asHashAlgorithm = algorithm;
5467c5 ¤
763c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
f34d65 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_HashAlgorithm,
88ad13 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( algorithm ), NULL );
1a67c5 ¤
4f8233 ¤   return( optionList );
24efe6 }
eaaf5a
0813fb ¤   PGPOptionListRef
997d12 PGPOFailBelowValidity(
b8520e ¤   PGPContextRef¤  context,
5366ee ¤   PGPValidity¤¤   minValidity)
6abb36 {
f23ddd ¤   PGPOptionListRef¤   optionList;
180cfd ¤   PGPOptionValue¤ ¤   value;
2a67c5 ¤
eb1aa1 ¤   pgpValidateOptionContext( context );
a2af5a
0dcea0 ¤   value.asValidity = minValidity;
0367c5 ¤
1b0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
f68f35 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_FailBelowValidity,
6fad93 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( minValidity ), NULL );
6767c5 ¤
558233 ¤   return( optionList );
20efe6 }
97af5a
d113fb ¤   PGPOptionListRef
533eeb PGPOWarnBelowValidity(
4e520e ¤   PGPContextRef¤  context,
ce66ee ¤   PGPValidity¤¤   minValidity)
73bb36 {
943ddd ¤   PGPOptionListRef¤   optionList;
080cfd ¤   PGPOptionValue¤ ¤   value;
cf67c5 ¤
2b1aa1 ¤   pgpValidateOptionContext( context );
3baf5a
6fcea0 ¤   value.asValidity = minValidity;
dc67c5 ¤
573c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
--57b6 000385a8dfa4010011c Page 16 of pgpClientEncode.c
73cccc ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_WarnBelowValidity,
24ad93 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( minValidity ), NULL );
2667c5 ¤
0c8233 ¤   return( optionList );
f0efe6 }
abaf5a
4613fb ¤   PGPOptionListRef
db18a1 PGPOEventHandler(
6e520e ¤   PGPContextRef¤  context,
66bbc4 ¤   PGPEventHandlerProcPtr¤ handler,
72dd0c ¤   PGPUserValue¤   ¤   ¤   userValue)
61bb36 {
c4710b ¤   PGPOptionListRef¤   ¤   optionList;
9674e3 ¤   PGPOEventHandlerDesc¤   *descriptor;
8067c5 ¤
771aa1 ¤   pgpValidateOptionContext( context );
52f2fa ¤   pgpValidateOptionParam( IsntNull( handler ) );
7067c5 ¤
638563 ¤   descriptor = (PGPOEventHandlerDesc *)
2434c0 ¤   ¤   ¤   ¤   ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor), 0);
63cc91 ¤   if( IsntNull( descriptor ) )
8dc7a1 ¤   {
42dc71 ¤   ¤   PGPOptionValue¤ value;
b41b52 ¤   ¤
da59b7 ¤   ¤   descriptor->handlerProc = handler;
3b668d ¤   ¤   descriptor->userValue ¤ = userValue;
561b52 ¤   ¤
01bb8d ¤   ¤   value.asPtr = descriptor;
391b52 ¤   ¤
3eb747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
b057c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EventHandler,
91f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
ea2d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
099371 ¤   }
080e24 ¤   else
c5c7a1 ¤   {
af1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
fa9371 ¤   }
adaf5a
478233 ¤   return( optionList );
efefe6 }
ffaf5a
6a13fb ¤   PGPOptionListRef
2b4fda PGPOSendNullEvents(
cb520e ¤   PGPContextRef¤  context,
65de7f ¤   PGPTimeInterval approxInterval)
1ebb36 {
8e3ddd ¤   PGPOptionListRef¤   optionList;
e00cfd ¤   PGPOptionValue¤ ¤   value;
091b52 ¤   ¤
b81aa1 ¤   pgpValidateOptionContext( context );
82af5a
44559f ¤   value.asInterval = approxInterval;
ec67c5 ¤
643c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
41a8a3 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_SendNullEvents,
a3bab8 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( approxInterval ), NULL );
2567c5 ¤
b88233 ¤   return( optionList );
08efe6 }
d3af5a
0b13fb ¤   PGPOptionListRef
993a81 PGPOArmorOutput(
7b520e ¤   PGPContextRef¤  context,
a63ba2 ¤   PGPBoolean¤ ¤   armorOutput
2727e6 ¤   )
b1bb36 {
2b3ddd ¤   PGPOptionListRef¤   optionList;
bc0cfd ¤   PGPOptionValue¤ ¤   value;
ed67c5 ¤
821aa1 ¤   pgpValidateOptionContext( context );
38af5a
--257e 0003ea4af334010011c Page 17 of pgpClientEncode.c
94ddc1 ¤   value.asUInt = (PGPUInt32)armorOutput;
aa67c5 ¤
310b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
bd1458 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ArmorOutput,
ae5974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
72af5a
3f8233 ¤   return( optionList );
0aefe6 }
83af5a
df13fb ¤   PGPOptionListRef
779e26 PGPODataIsASCII(
8b520e ¤   PGPContextRef¤  context,
099e13 ¤   PGPBoolean¤ ¤   dataIsASCII
3a27e6 ¤   )
d3bb36 {
023ddd ¤   PGPOptionListRef¤   optionList;
bf0cfd ¤   PGPOptionValue¤ ¤   value;
1a67c5 ¤
fa1aa1 ¤   pgpValidateOptionContext( context );
9aaf5a
167966 ¤   value.asUInt = (PGPUInt32)dataIsASCII;
8b67c5 ¤
690b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
beb0ff ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DataIsASCII,
545974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
aaaf5a
938233 ¤   return( optionList );
eeefe6 }
82af5a
2c13fb ¤   PGPOptionListRef
b5c91c PGPOClearSign(
eb520e ¤   PGPContextRef¤  context,
2fa951 ¤   PGPBoolean¤ ¤   clearSign
c327e6 ¤   )
3dbb36 {
fa3ddd ¤   PGPOptionListRef¤   optionList;
030cfd ¤   PGPOptionValue¤ ¤   value;
7267c5 ¤
c71aa1 ¤   pgpValidateOptionContext( context );
05af5a
bff27a ¤   value.asUInt = (PGPUInt32)clearSign;
9867c5 ¤
c70b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
c34bbe ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ClearSign,
e45974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
47af5a
cb8233 ¤   return( optionList );
0cefe6 }
e4af5a
b513fb ¤   PGPOptionListRef
71d4d5 PGPOForYourEyesOnly(
aa520e ¤   PGPContextRef¤  context,
dfc9fe ¤   PGPBoolean¤ ¤   forYourEyesOnly
4527e6 ¤   )
81bb36 {
133ddd ¤   PGPOptionListRef¤   optionList;
730cfd ¤   PGPOptionValue¤ ¤   value;
5567c5 ¤
161aa1 ¤   pgpValidateOptionContext( context );
a7af5a
74b6f2 ¤   value.asUInt = (PGPUInt32)forYourEyesOnly;
4a67c5 ¤
f70b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
0fb122 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ForYourEyesOnly,
465974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
37af5a
2a8233 ¤   return( optionList );
31efe6 }
95af5a
cc13fb ¤   PGPOptionListRef
c44ec5 PGPOSendEventIfKeyFound(
3e520e ¤   PGPContextRef¤  context,
--714f 000f012593a4010011c Page 18 of pgpClientEncode.c
cdc825 ¤   PGPBoolean¤ ¤   sendEventIfKeyFound
da27e6 ¤   )
0fbb36 {
f33ddd ¤   PGPOptionListRef¤   optionList;
5a0cfd ¤   PGPOptionValue¤ ¤   value;
3b67c5 ¤
f81aa1 ¤   pgpValidateOptionContext( context );
bbaf5a
a8d776 ¤   value.asUInt = (PGPUInt32)sendEventIfKeyFound;
f367c5 ¤
300b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
6425f3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_SendEventIfKeyFound,
935974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
15af5a
9f8233 ¤   return( optionList );
eeefe6 }
1faf5a
ba13fb ¤   PGPOptionListRef
d9267b PGPOPassThroughIfUnrecognized(
3c520e ¤   PGPContextRef¤  context,
556b1d ¤   PGPBoolean¤ ¤   passThroughIfUnrecognized
fe27e6 ¤   )
3fbb36 {
983ddd ¤   PGPOptionListRef¤   optionList;
b70cfd ¤   PGPOptionValue¤ ¤   value;
7867c5 ¤
c51aa1 ¤   pgpValidateOptionContext( context );
f0af5a
7de954 ¤   value.asUInt = (PGPUInt32)passThroughIfUnrecognized;
1467c5 ¤
c40b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
836eb0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PassThroughIfUnrecognized,
9c5974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
0aaf5a
b68233 ¤   return( optionList );
a2efe6 }
b8af5a
6a13fb ¤   PGPOptionListRef
7a7aef PGPOPassThroughClearSigned(
9f520e ¤   PGPContextRef¤  context,
a1c628 ¤   PGPBoolean¤ ¤   passThroughClearSigned
c527e6 ¤   )
42bb36 {
f53ddd ¤   PGPOptionListRef¤   optionList;
950cfd ¤   PGPOptionValue¤ ¤   value;
5267c5 ¤
e51aa1 ¤   pgpValidateOptionContext( context );
84af5a
0ec7f9 ¤   value.asUInt = (PGPUInt32)passThroughClearSigned;
9067c5 ¤
c90b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
5be115 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PassThroughClearSigned,
c05974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
38af5a
648233 ¤   return( optionList );
9defe6 }
5aaf5a
f613fb ¤   PGPOptionListRef
c1e04e PGPOPassThroughKeys(
72520e ¤   PGPContextRef¤  context,
72f99b ¤   PGPBoolean¤ ¤   passThroughKeys
6627e6 ¤   )
e7bb36 {
7d3ddd ¤   PGPOptionListRef¤   optionList;
770cfd ¤   PGPOptionValue¤ ¤   value;
b867c5 ¤
3e1aa1 ¤   pgpValidateOptionContext( context );
bbaf5a
df8269 ¤   value.asUInt = (PGPUInt32)passThroughKeys;
e067c5 ¤
f70b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
f085b9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PassThroughKeys,
--5d2d 00053c0cb894010011c Page 19 of pgpClientEncode.c
185974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
b4af5a
158233 ¤   return( optionList );
d9efe6 }
b1af5a
8a13fb ¤   PGPOptionListRef
cf3dc6 PGPORecursivelyDecode(
3c520e ¤   PGPContextRef¤  context,
39bdd8 ¤   PGPBoolean¤ ¤   recurse
c327e6 ¤   )
80bb36 {
a43ddd ¤   PGPOptionListRef¤   optionList;
770cfd ¤   PGPOptionValue¤ ¤   value;
9f67c5 ¤
3b1aa1 ¤   pgpValidateOptionContext( context );
d0af5a
cb1b6e ¤   value.asUInt = (PGPUInt32)recurse;
1c67c5 ¤
070b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
682de1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RecursivelyDecode,
275974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
98af5a
878233 ¤   return( optionList );
64efe6 }
b1af5a
d113fb ¤   PGPOptionListRef
8b7548 PGPOAskUserForEntropy(
46520e ¤   PGPContextRef¤  context,
e48ade ¤   PGPBoolean¤ ¤   askUserForEntropy
8127e6 ¤   )
a7bb36 {
453ddd ¤   PGPOptionListRef¤   optionList;
770cfd ¤   PGPOptionValue¤ ¤   value;
e867c5 ¤
8c1aa1 ¤   pgpValidateOptionContext( context );
07af5a
3d02f2 ¤   value.asUInt = (PGPUInt32)askUserForEntropy;
6967c5 ¤
910b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
db656f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_AskUserForEntropy,
015974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
12af5a
fe67c5 ¤
898233 ¤   return( optionList );
9befe6 }
8caf5a
a813fb ¤   PGPOptionListRef
d4d577 PGPORawPGPInput(
d6520e ¤   PGPContextRef¤  context,
2c83ca ¤   PGPBoolean¤ ¤   rawPGPInput
6a27e6 ¤   )
fabb36 {
2f3ddd ¤   PGPOptionListRef¤   optionList;
cd0cfd ¤   PGPOptionValue¤ ¤   value;
fe67c5 ¤
5d1aa1 ¤   pgpValidateOptionContext( context );
56af5a
9a3237 ¤   value.asUInt = (PGPUInt32)rawPGPInput;
5567c5 ¤
3a0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
cbfbae ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RawPGPInput,
055974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
3daf5a
e08233 ¤   return( optionList );
1cefe6 }
87af5a
fc13fb ¤   PGPOptionListRef
fc09b9 PGPOCompression(
5f520e ¤   PGPContextRef¤  context,
cf90b0 ¤   PGPBoolean¤ ¤   compression
8427e6 ¤   )
53bb36 {
--3100 00021d5a1084010011c Page 20 of pgpClientEncode.c
f03ddd ¤   PGPOptionListRef¤   optionList;
920cfd ¤   PGPOptionValue¤ ¤   value;
3c67c5 ¤
3f1aa1 ¤   pgpValidateOptionContext( context );
b6af5a
ffeef9 ¤   value.asUInt = (PGPUInt32)compression;
3e67c5 ¤
4f0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
292760 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Compression,
fc5974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
f7af5a
548233 ¤   return( optionList );
67efe6 }
b3af5a
a313fb ¤   PGPOptionListRef
a9ee0d PGPOKeySetRef(
7e520e ¤   PGPContextRef¤  context,
cd91c4 ¤   PGPKeySetRef ¤  keySetRef)
e6bb36 {
993ddd ¤   PGPOptionListRef¤   optionList;
dd0cfd ¤   PGPOptionValue¤ ¤   value;
b967c5 ¤
991aa1 ¤   pgpValidateOptionContext( context );
93bbbb ¤   pgpValidateOptionParam( pgpKeySetIsValid( keySetRef ) );
5167c5 ¤
0706aa ¤   value.asKeySetRef = keySetRef;
9667c5 ¤
e7ef8a ¤   PGPIncKeySetRefCount( keySetRef );
16af5a
180b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
9cc2ae ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeySetRef,
93913f ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( keySetRef ),
becc6d ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
2767c5 ¤
da8233 ¤   return( optionList );
94efe6 }
9aaf5a
74af5a
a713fb ¤   PGPOptionListRef
91fdd1 PGPOKeyGenParams(
559a06 ¤   PGPContextRef¤  ¤   ¤   context,
a79062 ¤   PGPPublicKeyAlgorithm¤  pubKeyAlg,
6a6e55 ¤   PGPUInt32¤  ¤   ¤   ¤   bits)
64bb36 {
e1710b ¤   PGPOptionListRef¤   ¤   optionList;
e4a08a ¤   PGPOKeyGenParamsDesc¤   *descriptor;
46af5a
ca1aa1 ¤   pgpValidateOptionContext( context );
237e48 ¤   pgpValidateOptionParam( pubKeyAlg >= kPGPPublicKeyAlgorithm_First &&
44c0da ¤   ¤   pubKeyAlg <= kPGPPublicKeyAlgorithm_Last );
b7cadd ¤   pgpValidateOptionParam( bits >= 512 );
7eaf5a
424dd0 ¤   descriptor = (PGPOKeyGenParamsDesc *)
bd34c0 ¤   ¤   ¤   ¤   ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor), 0);
02cc91 ¤   if( IsntNull( descriptor ) )
a2c7a1 ¤   {
d9dc71 ¤   ¤   PGPOptionValue¤ value;
98af5a
0f61eb ¤   ¤   descriptor->pkalg¤  = pubKeyAlg;
96e161 ¤   ¤   descriptor->bits ¤  = bits;
30af5a
e8bb8d ¤   ¤   value.asPtr = descriptor;
41af5a
72b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
07b2b2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenParams,
02f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
802d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
c39371 ¤   }
560e24 ¤   else
0bc7a1 ¤   {
c01b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
219371 ¤   }
--c778 0001c75442e4010011c Page 21 of pgpClientEncode.c
2a67c5 ¤
c28233 ¤   return( optionList );
08efe6 }
faaf5a
d913fb ¤   PGPOptionListRef
149f75 PGPOKeyGenName(
e3520e ¤   PGPContextRef¤  context,
0ced02 ¤   const void¤ *¤  name,
88a7e5 ¤   PGPSize¤¤   ¤   nameLength)
50bb36 {
761aa1 ¤   pgpValidateOptionContext( context );
d3319e ¤   pgpValidateOptionParam( IsntNull( name ) );
7f394d ¤   pgpValidateOptionParam( nameLength >= 1 );
6a37ef ¤   pgpValidateOptionParam( nameLength < 256 );
3c67c5 ¤
c4a51a ¤   return( pgpCreateBufferOptionList( context,
369077 ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenName, name, nameLength ) );
60efe6 }
39af5a
9113fb ¤   PGPOptionListRef
414731 PGPOExpiration(
01520e ¤   PGPContextRef¤  context,
ddb384 ¤   PGPUInt32¤  ¤   expirationDays)
aabb36 {
6f3ddd ¤   PGPOptionListRef¤   optionList;
8d0cfd ¤   PGPOptionValue¤ ¤   value;
0faf5a
d71aa1 ¤   pgpValidateOptionContext( context );
ecaf5a
cf10c9 ¤   value.asUInt = expirationDays;
9faf5a
ad3c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
02c5aa ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Expiration,
4788bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( expirationDays ), NULL);
5467c5 ¤
f08233 ¤   return( optionList );
41efe6 }
b6af5a
a113fb ¤   PGPOptionListRef
dcb963 PGPOCreationDate(
f3520e ¤   PGPContextRef¤  context,
d982b3 ¤   PGPTime¤¤   ¤   creationDate)
46bb36 {
1f3ddd ¤   PGPOptionListRef¤   optionList;
860cfd ¤   PGPOptionValue¤ ¤   value;
eeaf5a
a71aa1 ¤   pgpValidateOptionContext( context );
7faf5a
4622d4 ¤   value.asTime = creationDate;
46af5a
f73c8a ¤   optionList = pgpCreateStandardValueOptionList( context,·
d6f600 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_CreationDate,
e259e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( creationDate ), NULL);
cb67c5 ¤
198233 ¤   return( optionList );
72efe6 }
d5af5a
0513fb ¤   PGPOptionListRef
48f1a2 PGPOAdditionalRecipientRequestKeySet(
85520e ¤   PGPContextRef¤  context,
1503ca ¤   PGPKeySetRef¤   arKeySetRef,
a96181 ¤   PGPByte¤¤   ¤   arkclass
5b27e6 ¤   )
dcbb36 {
6a3ddd ¤   PGPOptionListRef¤   optionList;
0946d6 ¤   PGPOAdditionalRecipientRequestKeySetDesc¤   *descriptor;
faaf5a
cc1aa1 ¤   pgpValidateOptionContext( context );
6568b6 ¤   pgpValidateOptionParam( pgpKeySetIsValid( arKeySetRef ) );
75af5a
cd0522 ¤   descriptor = (PGPOAdditionalRecipientRequestKeySetDesc *)
1c34c0 ¤   ¤   ¤   ¤   ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor), 0);
--2375 000c4d493834010011c Page 22 of pgpClientEncode.c
59cc91 ¤   if( IsntNull( descriptor ) )
adc7a1 ¤   {
56dc71 ¤   ¤   PGPOptionValue¤ value;
86af5a
ccbfe3 ¤   ¤   descriptor->arKeySetRef¤= arKeySetRef;
cc01be ¤   ¤   descriptor->arkclass ¤  = arkclass;
a5af5a
12bb8d ¤   ¤   value.asPtr = descriptor;
59af5a
5f0479 ¤   ¤   PGPIncKeySetRefCount( arKeySetRef );
0baf5a
9bb747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
a0bd37 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_AdditionalRecipientRequestKeySet,
a7f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
072d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
599371 ¤   }
970e24 ¤   else
abc7a1 ¤   {
461b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
199371 ¤   }
9267c5 ¤
528233 ¤   return( optionList );
5defe6 }
daaf5a
e613fb ¤   PGPOptionListRef
89f0eb PGPORevocationKeySet(
c3520e ¤   PGPContextRef¤  context,
f48bcd ¤   PGPKeySetRef¤   raKeySetRef
7c27e6 ¤   )
e0bb36 {
ca3ddd ¤   PGPOptionListRef¤   optionList;
0746d6 ¤   PGPOAdditionalRecipientRequestKeySetDesc¤   *descriptor;
99af5a
dc1aa1 ¤   pgpValidateOptionContext( context );
9a6bef ¤   pgpValidateOptionParam( pgpKeySetIsValid( raKeySetRef ) );
00af5a
01b083 ¤   /* Use ADK descriptor as we have similar data structure */
af0522 ¤   descriptor = (PGPOAdditionalRecipientRequestKeySetDesc *)
2f34c0 ¤   ¤   ¤   ¤   ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor), 0);
1ccc91 ¤   if( IsntNull( descriptor ) )
2dc7a1 ¤   {
42dc71 ¤   ¤   PGPOptionValue¤ value;
f0af5a
c079f2 ¤   ¤   descriptor->arKeySetRef¤= raKeySetRef;
55f6a3 ¤   ¤   descriptor->arkclass ¤  = 0x80;¤/* hard code value for revocation */
94af5a
6abb8d ¤   ¤   value.asPtr = descriptor;
fdaf5a
df2b0a ¤   ¤   PGPIncKeySetRefCount( raKeySetRef );
deaf5a
31b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
5077bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RevocationKeySet,
7ff145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
642d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
a29371 ¤   }
9c0e24 ¤   else
f7c7a1 ¤   {
0b1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
4f9371 ¤   }
2067c5 ¤
708233 ¤   return( optionList );
cfefe6 }
6aaf5a
f913fb ¤   PGPOptionListRef
394da6 PGPOKeyGenMasterKey(
ca520e ¤   PGPContextRef¤  context,
0d91bc ¤   PGPKeyRef¤  ¤   masterKeyRef
5c27e6 ¤   )
05bb36 {
323ddd ¤   PGPOptionListRef¤   optionList;
090cfd ¤   PGPOptionValue¤ ¤   value;
c467c5 ¤
--5c5a 000ee139f774010011c Page 23 of pgpClientEncode.c
051aa1 ¤   pgpValidateOptionContext( context );
84796e ¤   pgpValidateOptionParam( pgpKeyIsValid( masterKeyRef ) );
9067c5 ¤
6fe98f ¤   value.asKeyRef = masterKeyRef;
a7af5a
752e76 ¤   pgpIncKeyRefCount( masterKeyRef );
75af5a
6d0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
e62851 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenMasterKey,
4811ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( masterKeyRef ),
fd99c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
3a67c5 ¤
cc8233 ¤   return( optionList );
d9efe6 }
79af5a
8013fb ¤   PGPOptionListRef
f9ffe8 PGPOPreferredAlgorithms(
83883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
73fd16 ¤   PGPCipherAlgorithm const *¤ prefAlg,
34df1f ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numAlgs)
ddbb36 {
021aa1 ¤   pgpValidateOptionContext( context );
141ea1 ¤   pgpValidateOptionParam( IsntNull( prefAlg ) );
641baa ¤   pgpValidateOptionParam( numAlgs != 0 );
b7feb6 ¤   pgpAssert( numAlgs <= kPGPNumPossibleCipherAlgorithms );
bb67c5 ¤
cea51a ¤   return( pgpCreateBufferOptionList( context,
e2df95 ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PreferredAlgorithms,
caa4cb ¤   ¤   ¤   ¤   ¤   prefAlg, numAlgs * sizeof( prefAlg[ 0 ] ) ·) );
02efe6 }
29af5a
2c13fb ¤   PGPOptionListRef
480c87 PGPOKeyGenFast(
4a520e ¤   PGPContextRef¤  context,
0543bd ¤   PGPBoolean¤ ¤   fastGen
4427e6 ¤   )
57bb36 {
ba3ddd ¤   PGPOptionListRef¤   optionList;
3b0cfd ¤   PGPOptionValue¤ ¤   value;
b067c5 ¤
4a1aa1 ¤   pgpValidateOptionContext( context );
14af5a
af2f3b ¤   value.asUInt = (PGPUInt32)fastGen;
a567c5 ¤
6b0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
0a8e1c ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenFast,
cc5974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
40af5a
468233 ¤   return( optionList );
d3efe6 }
2faf5a
1e13fb ¤   PGPOptionListRef
f1bbf4 PGPOExportable(
e1520e ¤   PGPContextRef¤  context,
803824 ¤   PGPBoolean¤ ¤   exportable
6327e6 ¤   )
8fbb36 {
e53ddd ¤   PGPOptionListRef¤   optionList;
da0cfd ¤   PGPOptionValue¤ ¤   value;
dc67c5 ¤
211aa1 ¤   pgpValidateOptionContext( context );
a2af5a
e768f7 ¤   value.asUInt = (PGPUInt32)exportable;
6167c5 ¤
1b0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
2d396f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Exportable,
fc5974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
e2af5a
878233 ¤   return( optionList );
1defe6 }
13af5a
ee13fb ¤   PGPOptionListRef
--c20c 000218c81c04010011c Page 24 of pgpClientEncode.c
1c5bac PGPOExportPrivateKeys(
95520e ¤   PGPContextRef¤  context,
5b3e55 ¤   PGPBoolean¤ ¤   exportKeys
f027e6 ¤   )
66bb36 {
c23ddd ¤   PGPOptionListRef¤   optionList;
7b0cfd ¤   PGPOptionValue¤ ¤   value;
5067c5 ¤
b71aa1 ¤   pgpValidateOptionContext( context );
7caf5a
390aff ¤   value.asUInt = (PGPUInt32)exportKeys;
f267c5 ¤
130b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
fd4b8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ExportPrivateKeys,
e15974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
06af5a
d78233 ¤   return( optionList );
bcefe6 }
0aaf5a
5c13fb ¤   PGPOptionListRef
5d0965 PGPOExportPrivateSubkeys(
97520e ¤   PGPContextRef¤  context,
439639 ¤   PGPBoolean¤ ¤   exportSubkeys
a527e6 ¤   )
9ebb36 {
fa3ddd ¤   PGPOptionListRef¤   optionList;
050cfd ¤   PGPOptionValue¤ ¤   value;
5367c5 ¤
651aa1 ¤   pgpValidateOptionContext( context );
43af5a
feb9b8 ¤   value.asUInt = (PGPUInt32)exportSubkeys;
bd67c5 ¤
a10b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
3859ba ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ExportPrivateSubkeys,
705974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
00af5a
ed8233 ¤   return( optionList );
98efe6 }
34af5a
ce13fb ¤   PGPOptionListRef
5aa81e PGPOOmitMIMEVersion(
01520e ¤   PGPContextRef¤  context,
211f74 ¤   PGPBoolean¤ ¤   omitVersion
7327e6 ¤   )
a5bb36 {
8b3ddd ¤   PGPOptionListRef¤   optionList;
820cfd ¤   PGPOptionValue¤ ¤   value;
7d67c5 ¤
031aa1 ¤   pgpValidateOptionContext( context );
a6af5a
166e5e ¤   value.asUInt = (PGPUInt32)omitVersion;
ce67c5 ¤
a00b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
29cde9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_OmitMIMEVersion,
b35974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
4aaf5a
b88233 ¤   return( optionList );
85efe6 }
eeaf5a
9313fb ¤   PGPOptionListRef
88d0e8 PGPOX509Encoding(
d3520e ¤   PGPContextRef¤  context,
2454d7 ¤   PGPBoolean¤ ¤   x509Encoding
4a27e6 ¤   )
46bb36 {
bd3ddd ¤   PGPOptionListRef¤   optionList;
c80cfd ¤   PGPOptionValue¤ ¤   value;
0867c5 ¤
c21aa1 ¤   pgpValidateOptionContext( context );
1baf5a
ad4703 ¤   value.asUInt = (PGPUInt32)x509Encoding;
2167c5 ¤
--cad8 000a18c1db44010011c Page 25 of pgpClientEncode.c
890b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
d89f8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_X509Encoding,
4a5974 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL);
6aaf5a
078233 ¤   return( optionList );
77efe6 }
edaf5a
5c13fb ¤   PGPOptionListRef
dadba8 PGPOSigTrust(
47520e ¤   PGPContextRef¤  context,
696afe ¤   PGPUInt32¤  ¤   trustLevel,
40ff23 ¤   PGPUInt32¤  ¤   trustValue)
a4bb36 {
42613c ¤   PGPOptionListRef¤   ¤   ¤   optionList;
83ec4f ¤   PGPOCertificateTrustDesc¤   *descriptor;
58af5a
1d1aa1 ¤   pgpValidateOptionContext( context );
24b1d0 ¤   pgpValidateOptionParam( trustValue >= kPGPKeyTrust_Unknown &&
6fbc06 ¤   ¤   trustValue <= kPGPKeyTrust_Ultimate );
faaf5a
925220 ¤   descriptor = (PGPOCertificateTrustDesc *)
5934c0 ¤   ¤   ¤   ¤   ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor), 0);
9ccc91 ¤   if( IsntNull( descriptor ) )
55c7a1 ¤   {
a4dc71 ¤   ¤   PGPOptionValue¤ value;
b6af5a
ea1cb2 ¤   ¤   descriptor->trustLevel¤ = trustLevel;
55b423 ¤   ¤   descriptor->trustValue ¤= trustValue;
aaaf5a
3bbb8d ¤   ¤   value.asPtr = descriptor;
98af5a
a9b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
de531c ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_CertificateTrust,
c8f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
bc2d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
0c9371 ¤   }
c30e24 ¤   else
b1c7a1 ¤   {
591b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
eb9371 ¤   }
6a67c5 ¤
278233 ¤   return( optionList );
f7efe6 }
65af5a
a413fb ¤   PGPOptionListRef
f845d2 PGPOCommentString(
5a520e ¤   PGPContextRef¤  context,
8df8c5 ¤   char const¤ ¤   *comment
4427e6 ¤   )
29bb36 {
936810 ¤   PGPSize¤¤   ¤   ·commentLength;
09af5a
0c1aa1 ¤   pgpValidateOptionContext( context );
c1aa6f ¤   pgpValidateOptionParam( IsntNull( comment ) );
6367c5 ¤
237fcb ¤   commentLength = strlen( comment ) + 1;
52af5a
bfa51a ¤   return( pgpCreateBufferOptionList( context,
a7f201 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_CommentString,
866694 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   comment, commentLength ) );
98efe6 }
98af5a
7f13fb ¤   PGPOptionListRef
0d376c PGPOVersionString(
d1520e ¤   PGPContextRef¤  context,
e7d243 ¤   char const¤ ¤   *version
4c27e6 ¤   )
aabb36 {
261aae ¤   PGPSize¤¤   ¤   ·versionLength;
26af5a
ae1aa1 ¤   pgpValidateOptionContext( context );
a1485f ¤   pgpValidateOptionParam( IsntNull( version ) );
--0745 000585622774010011c Page 26 of pgpClientEncode.c
2a67c5 ¤
da67d5 ¤   versionLength = strlen( version ) + 1;
7eaf5a
1ba51a ¤   return( pgpCreateBufferOptionList( context,
c180bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_VersionString,
8deecd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   version, versionLength ) );
d3efe6 }
b1af5a
9f13fb ¤   PGPOptionListRef
ee1ea6 PGPOFileNameString(
05520e ¤   PGPContextRef¤  context,
fe85b5 ¤   char const¤ ¤   *fileName
2627e6 ¤   )
e5bb36 {
3e6de4 ¤   PGPSize¤¤   ¤   ·fileNameLength;
e0af5a
701aa1 ¤   pgpValidateOptionContext( context );
706863 ¤   pgpValidateOptionParam( IsntNull( fileName ) );
b967c5 ¤
9b9974 ¤   fileNameLength = strlen( fileName ) + 1;
dcaf5a
d1a51a ¤   return( pgpCreateBufferOptionList( context,
796f01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_InputFileName,
8501f3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   fileName, fileNameLength ) );
72efe6 }
e0af5a
c213fb ¤   PGPOptionListRef
95df56 PGPOSigRegularExpression(
eb520e ¤   PGPContextRef¤  context,
cc77f5 ¤   char const¤ ¤   *regexp
4d27e6 ¤   )
06bb36 {
a2f6a2 ¤   PGPSize¤¤   ¤   ·regexpLength;
39af5a
331aa1 ¤   pgpValidateOptionContext( context );
66e44f ¤   pgpValidateOptionParam( IsntNull( regexp ) );
c067c5 ¤
6a0d40 ¤   regexpLength = strlen( regexp ) + 1;
c6af5a
3ca51a ¤   return( pgpCreateBufferOptionList( context,
b96d3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_CertificateRegularExpression,
40cedd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   regexp, regexpLength ) );
efefe6 }
8baf5a
ad13fb ¤   PGPOptionListRef
30ec98 PGPOLocalEncoding(
85883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
bfde55 ¤   PGPLocalEncodingFlags¤  ¤   localEncode
9727e6 ¤   )
2abb36 {
a63ddd ¤   PGPOptionListRef¤   optionList;
ed0cfd ¤   PGPOptionValue¤ ¤   value;
ed67c5 ¤
701aa1 ¤   pgpValidateOptionContext( context );
6faf5a
1352c9 ¤   /* Ensure incompatible options not selected */
178267 ¤   if( (localEncode & kPGPLocalEncoding_Force) &&
df9e71 ¤   ¤   (localEncode & kPGPLocalEncoding_Auto) )
a6b0b7 ¤   ¤   return kPGPBadParamsOptionListRef;
4faf5a
baf788 ¤   value.asUInt = localEncode;
d467c5 ¤
e00b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
00143d ¤   ¤   ¤   ¤   ¤   kPGPOptionType_LocalEncoding,
b608c2 ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPLocalEncodingFlags ), NULL);
f5af5a
bd8233 ¤   return( optionList );
66efe6 }
ecaf5a
b013fb ¤   PGPOptionListRef
5c031f PGPOOutputLineEndType(
58a1bc ¤   PGPContextRef¤  ¤   context,
--db85 0008b8860c84010011c Page 27 of pgpClientEncode.c
256d38 ¤   PGPLineEndType¤ ¤   lineEnd
db27e6 ¤   )
84bb36 {
6d3ddd ¤   PGPOptionListRef¤   optionList;
c30cfd ¤   PGPOptionValue¤ ¤   value;
9a67c5 ¤
291aa1 ¤   pgpValidateOptionContext( context );
edeaa4 ¤   pgpValidateOptionParam( lineEnd == kPGPLineEnd_LF ||
bdb556 ¤   ¤   lineEnd == kPGPLineEnd_CR || lineEnd == kPGPLineEnd_CRLF );
43af5a
913e92 ¤   value.asUInt = (PGPUInt32) lineEnd;
1367c5 ¤
780f89 ¤   optionList = pgpCreateStandardValueOptionList( context,
97f24f ¤   ¤   ¤   ¤   ¤   kPGPOptionType_OutputLineEndType,
5508c2 ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPLocalEncodingFlags ), NULL);
a5af5a
4e8233 ¤   return( optionList );
02efe6 }
09af5a
fd13fb ¤   PGPOptionListRef
8e080d PGPOExportFormat(
c1a1bc ¤   PGPContextRef¤  ¤   context,
e8782e ¤   PGPExportFormat¤¤   exportFormat
a827e6 ¤   )
37bb36 {
6b3ddd ¤   PGPOptionListRef¤   optionList;
340cfd ¤   PGPOptionValue¤ ¤   value;
3867c5 ¤
741aa1 ¤   pgpValidateOptionContext( context );
5daf5a
14a810 ¤   value.asUInt = (PGPUInt32) exportFormat;
2167c5 ¤
ad0f89 ¤   optionList = pgpCreateStandardValueOptionList( context,
997b46 ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ExportFormat,
af08c2 ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPLocalEncodingFlags ), NULL);
b0af5a
588233 ¤   return( optionList );
3aefe6 }
64af5a
1f13fb ¤   PGPOptionListRef
0978df PGPOImportKeysTo(
86520e ¤   PGPContextRef¤  context,
87d327 ¤   PGPKeySetRef¤   keySetRef
cd27e6 ¤   )
40bb36 {
3d3ddd ¤   PGPOptionListRef¤   optionList;
e20cfd ¤   PGPOptionValue¤ ¤   value;
7167c5 ¤
431aa1 ¤   pgpValidateOptionContext( context );
a4bbbb ¤   pgpValidateOptionParam( pgpKeySetIsValid( keySetRef ) );
0d1b52 ¤   ¤
a106aa ¤   value.asKeySetRef = keySetRef;
faaf5a
06ef8a ¤   PGPIncKeySetRefCount( keySetRef );
5baf5a
8d0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
7037bc ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ImportKeysTo,
4bfe0c ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( keySetRef ),
dd99c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SpecialOptionHandlerProc );
2a67c5 ¤
fc8233 ¤   return( optionList );
1befe6 }
c5af5a
6b13fb ¤   PGPOptionListRef
20cb26 PGPOPGPMIMEEncoding(
37520e ¤   PGPContextRef¤  context,
b1b5ce ¤   PGPBoolean¤ ¤   mimeEncoding,
621993 ¤   PGPSize *¤  ¤   mimeBodyOffset,
8f61a9 ¤   char *¤ ¤   ¤   mimeSeparator
3b27e6 ¤   )
ddbb36 {
8b613c ¤   PGPOptionListRef¤   ¤   ¤   optionList;
--aba4 00182e807d64010011c Page 28 of pgpClientEncode.c
3af19c ¤   PGPOPGPMIMEEncodingDesc¤¤   *descriptor;
1daf5a
181aa1 ¤   pgpValidateOptionContext( context );
82d2d0 ¤   if ( mimeEncoding )
06c7a1 ¤   {
9a552f ¤   ¤   if ( IsntNull( mimeBodyOffset ) )
f811b6 ¤   ¤   ¤   *mimeBodyOffset¤= 0;
19505f ¤   ¤   if ( IsntNull( mimeSeparator ) )
514372 ¤   ¤   ¤   *mimeSeparator¤ = '\0';
4f87c7 ¤   ¤   ¤
3409e0 ¤   ¤   pgpValidateOptionParam( IsntNull( mimeBodyOffset ) );
1877b4 ¤   ¤   pgpValidateOptionParam( IsntNull( mimeSeparator ) );
945128 ¤   ¤   pgpDebugWhackMemory( mimeSeparator, kPGPMimeSeparatorSize );
0f9371 ¤   }
f40e24 ¤   else
d6c7a1 ¤   {
9e3af7 ¤   ¤   /* mime off--ignore other params */
a39371 ¤   }
05af5a
95db35 ¤   descriptor = (PGPOPGPMIMEEncodingDesc *)
8a0f56 ¤   ¤   ¤   ¤   ¤   ¤   pgpContextMemAlloc( context, sizeof(*descriptor), 0 );
2acc91 ¤   if( IsntNull( descriptor ) )
f5c7a1 ¤   {
e9dc71 ¤   ¤   PGPOptionValue¤ value;
d3af5a
68cc21 ¤   ¤   descriptor->mimeEncoding¤   = (PGPUInt32) mimeEncoding;
d2200d ¤   ¤   descriptor->mimeBodyOffset ¤= mimeEncoding ? mimeBodyOffset : NULL;
93e410 ¤   ¤   descriptor->mimeSeparator ¤ = mimeEncoding ? mimeSeparator : NULL;
8baf5a
77bb8d ¤   ¤   value.asPtr = descriptor;
ebaf5a
09cb95 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context,
50aed1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PGPMIMEEncoding,
71f145 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *descriptor ),
a22d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   AllocatedOptionHandlerProc );
4b9371 ¤   }
b00e24 ¤   else
34c7a1 ¤   {
231b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
399371 ¤   }
c067c5 ¤
b98233 ¤   return( optionList );
2befe6 }
d0af5a
31af5a
d5af5a
517e4d /*__Editor_settings____
2daf5a
a84126 ¤   Local Variables:
647b17 ¤   tab-width: 4
170e6c ¤   End:
685f8c ¤   vi: ts=4 sw=4
f99e9b ¤   vim: si
82d062 _____________________*/
--dc1c 00084a7f7eb4010011d Page 1 of pgpClientKeyDB.c
a70335 /*____________________________________________________________________________
ab71de ¤   pgpClientKeyDB.c
db67c5 ¤
e8c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
6a4b0f ¤   All rights reserved.
2267c5 ¤
e6791f ¤   Wrapper functions for KeyDB library
0e67c5 ¤
deaf5a
eb3ddd ¤   $Id: pgpClientKeyDB.c,v 1.37.12.1 1998/11/12 03:21:14 heller Exp $
44f7f7 ____________________________________________________________________________*/
2f324c #include <string.h>
e0af5a
be0d08 #include "pgpMem.h"
dac26c #include "pgpContext.h"
900141 #include "pgpOptionListPriv.h"
f3a076 #include "pgpKeys.h"
76711b #include "pgpKeyDB.h"
21adb8 #include "pgpOpaqueStructs.h"
a02f8d #include "pgpErrors.h"
65979a #include "pgpKDBInt.h"
b8af5a
41af5a
ce0335 /*____________________________________________________________________________
2d2494 ¤   Generate a key
f9f7f7 ____________________________________________________________________________*/
93af5a
fdc744 ¤   PGPError
74ac15 PGPGenerateKey(
e4a1bc ¤   PGPContextRef¤  ¤   context,
9d8d16 ¤   PGPKeyRef¤  ¤   ¤   *key,
1b41a1 ¤   PGPOptionListRef¤   firstOption,
b0c9f6 ¤   ...
c227e6 ¤   )
7ebb36 {
d15108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
b467c5 ¤
2a8679 ¤   pgpAssert( pgpContextIsValid( context ) );
7db8d3 ¤   pgpAssert( IsntNull(key ) );
c467c5 ¤
8332ea ¤   if (IsntNull( key ) )
7bce51 ¤   ¤   *key¤   = kInvalidPGPKeyRef;
5067c5 ¤
739a79 ¤   if( pgpContextIsValid( context ) &&
2d38c2 ¤   ¤   ¤   IsntNull(key ) )
2fc7a1 ¤   {
c636db ¤   ¤   va_list¤¤   ¤   ¤   args;
51f888 ¤   ¤   PGPOptionListRef¤   optionList;
8aaf5a
8c02ff ¤   ¤   va_start( args, firstOption );
c36bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
65b819 ¤   ¤   ¤   FALSE, firstOption, args );
5caf5a
4eb8fa ¤   ¤   error = pgpGetOptionListError( optionList );
77cb70 ¤   ¤   if( IsntPGPError( error ) )
575b34 ¤   ¤   {
5aa1e6 ¤   ¤   ¤   error = pgpGenerateKeyInternal( context, key, optionList );
680fe4 ¤   ¤   }
a0c414 ¤   ¤   va_end( args );
63af5a
fe153d ¤   ¤   PGPFreeOptionList( optionList );
3b9371 ¤   }
370e24 ¤   else
51c7a1 ¤   {
7136db ¤   ¤   va_list¤¤   ¤   ¤   args;
771b52 ¤   ¤
7b02ff ¤   ¤   va_start( args, firstOption );
17ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
b8c414 ¤   ¤   va_end( args );
ce1b52 ¤   ¤
8fd5d3 ¤   ¤   error = kPGPError_BadParams;
849371 ¤   }
--c362 00061315df04010011d Page 2 of pgpClientKeyDB.c
2a67c5 ¤
5e08be ¤   pgpAssertErrWithPtr( error, *key );
5867c5 ¤
07da11 ¤   if ( IsntPGPError( error ) )
d5c7a1 ¤   {
520f14 ¤   ¤   pgpAssert( (*key)->refCount == 1 );
a69256 ¤   ¤   pgpIncKeyRefCount( *key );
ac9371 ¤   }
f967c5 ¤
f857f8 ¤   return( error );
ebefe6 }
53af5a
45af5a
aa0335 /*____________________________________________________________________________
bf455b ¤   Generate a subkey
3af7f7 ____________________________________________________________________________*/
b0af5a
acc744 ¤   PGPError
acdfe2 PGPGenerateSubKey(
2ba1bc ¤   PGPContextRef¤  ¤   context,
eb71e9 ¤   PGPSubKeyRef¤   ¤   *subkey,
6641a1 ¤   PGPOptionListRef¤   firstOption,
f5c9f6 ¤   ...
2c27e6 ¤   )
8dbb36 {
695108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
3d67c5 ¤
858679 ¤   pgpAssert( pgpContextIsValid( context ) );
24fa17 ¤   pgpAssertAddrValid( subkey, PGPSubKeyRef );
a367c5 ¤
4dc48e ¤   if (IsntNull( subkey ) )
6b6f74 ¤   ¤   *subkey¤= kInvalidPGPSubKeyRef;
211b52 ¤   ¤
659a79 ¤   if( pgpContextIsValid( context ) &&
cd18f0 ¤   ¤   IsntNull( subkey ) )
39c7a1 ¤   {
6f36db ¤   ¤   va_list¤¤   ¤   ¤   args;
63f888 ¤   ¤   PGPOptionListRef¤   optionList;
e81b52 ¤   ¤
0be5da ¤   ¤   *subkey = NULL;
e4af5a
ea02ff ¤   ¤   va_start( args, firstOption );
a06bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
9bb819 ¤   ¤   ¤   FALSE, firstOption, args );
bdaf5a
12b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
15cb70 ¤   ¤   if( IsntPGPError( error ) )
595b34 ¤   ¤   {
dd543f ¤   ¤   ¤   error = pgpGenerateSubKeyInternal( context, subkey, optionList );
9c0fe4 ¤   ¤   }
b3c414 ¤   ¤   va_end( args );
c7af5a
9f153d ¤   ¤   PGPFreeOptionList( optionList );
309371 ¤   }
800e24 ¤   else
d2c7a1 ¤   {
bc36db ¤   ¤   va_list¤¤   ¤   ¤   args;
ba1b52 ¤   ¤
b902ff ¤   ¤   va_start( args, firstOption );
3ded0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
dbc414 ¤   ¤   va_end( args );
811b52 ¤   ¤
02d5d3 ¤   ¤   error = kPGPError_BadParams;
329371 ¤   }
df67c5 ¤
ec57f8 ¤   return( error );
3cefe6 }
b7af5a
a0af5a
6e0335 /*____________________________________________________________________________
720860 ¤   Certify a userid, possibly with trust information
61f7f7 ____________________________________________________________________________*/
--bb85 00028e43ed54010011d Page 3 of pgpClientKeyDB.c
e0af5a
01c744 ¤   PGPError
3e8b84 PGPSignUserID(
7203f8 ¤   PGPUserIDRef¤   ¤   userid,
1b31fb ¤   PGPKeyRef¤  ¤   ¤   certifyingKey,
8341a1 ¤   PGPOptionListRef¤   firstOption,
e4c9f6 ¤   ...
8e27e6 ¤   )
21bb36 {
c787a6 ¤   PGPError¤   error;
6067c5 ¤
968562 ¤   pgpAssertAddrValid( userid, PGPUserID );
399d61 ¤   pgpAssert( pgpKeyIsValid( certifyingKey ) );
cc67c5 ¤
873b51 ¤   if( IsntNull( userid ) && pgpKeyIsValid( certifyingKey ) )
a3c7a1 ¤   {
da36db ¤   ¤   va_list¤¤   ¤   ¤   args;
54f888 ¤   ¤   PGPOptionListRef¤   optionList;
84444d ¤   ¤   PGPContextRef¤  ¤   context;
0c1b52 ¤   ¤
4402ff ¤   ¤   va_start( args, firstOption );
d92823 ¤   ¤   context¤= PGPGetKeyContext( certifyingKey );
4967c5 ¤
ef6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
2bb819 ¤   ¤   ¤   FALSE, firstOption, args );
81af5a
4cb8fa ¤   ¤   error = pgpGetOptionListError( optionList );
c6cb70 ¤   ¤   if( IsntPGPError( error ) )
415b34 ¤   ¤   {
c85346 ¤   ¤   ¤   error = pgpCertifyUserIDInternal( userid, certifyingKey,
a21a1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··optionList );
9c0fe4 ¤   ¤   }
c5c414 ¤   ¤   va_end( args );
5eaf5a
12153d ¤   ¤   PGPFreeOptionList( optionList );
439371 ¤   }
bf0e24 ¤   else
64c7a1 ¤   {
6f36db ¤   ¤   va_list¤¤   ¤   ¤   args;
471b52 ¤   ¤
7402ff ¤   ¤   va_start( args, firstOption );
8ded0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
7cc414 ¤   ¤   va_end( args );
b81b52 ¤   ¤
07d5d3 ¤   ¤   error = kPGPError_BadParams;
019371 ¤   }
ca67c5 ¤
5057f8 ¤   return( error );
d2efe6 }
11af5a
94af5a
780335 /*____________________________________________________________________________
9f6fe3 ¤   Revoke a certificate
57f7f7 ____________________________________________________________________________*/
1faf5a
19c744 ¤   PGPError
30709e PGPRevokeSig(
395a1b ¤   PGPSigRef¤  ¤   ¤   sig,
08bba1 ¤   PGPKeySetRef¤   ¤   allkeys,
eb41a1 ¤   PGPOptionListRef¤   firstOption,
e8c9f6 ¤   ...
2f27e6 ¤   )
5bbb36 {
f35bd0 ¤   PGPError¤   ¤   error = kPGPError_NoErr;
e567c5 ¤
102c9b ¤   pgpAssert( pgpKeySetIsValid( allkeys ) );
91ff9a ¤   pgpAssert( pgpSigIsValid( sig ) );
0e67c5 ¤
fe5c7c ¤   if( pgpSigIsValid( sig ) &&
b48a66 ¤   ¤   pgpKeySetIsValid( allkeys ) )
06c7a1 ¤   {
2836db ¤   ¤   va_list¤¤   ¤   ¤   args;
--457b 0008f44a6e14010011d Page 4 of pgpClientKeyDB.c
cbf888 ¤   ¤   PGPOptionListRef¤   optionList;
32444d ¤   ¤   PGPContextRef¤  ¤   context;
6cc27b ¤   ¤   PGPKeyRef¤  ¤   ¤   sigParentKey;
0267c5 ¤
483418 ¤   ¤   error = pgpGetCertKey( sig, TRUE, &sigParentKey );
a56442 ¤   ¤   if( IsPGPError( error ) )
075b34 ¤   ¤   {
ef8f0c ¤   ¤   ¤   goto cleanup;
7b0fe4 ¤   ¤   }
291b52 ¤   ¤
a402ff ¤   ¤   va_start( args, firstOption );
f9ddd7 ¤   ¤   context¤¤   = PGPGetKeyContext( sigParentKey );
106c4f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE,
ed77f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·firstOption, args );
dfaf5a
75b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
b2cb70 ¤   ¤   if( IsntPGPError( error ) )
d15b34 ¤   ¤   {
c33a2d ¤   ¤   ¤   error = pgpRevokeCertInternal( sig, allkeys, optionList );
de0fe4 ¤   ¤   }
7cc414 ¤   ¤   va_end( args );
baaf5a
cf153d ¤   ¤   PGPFreeOptionList( optionList );
159371 ¤   }
400e24 ¤   else
49c7a1 ¤   {
ce36db ¤   ¤   va_list¤¤   ¤   ¤   args;
76af5a
1168cb cleanup:
a3af5a
f902ff ¤   ¤   va_start( args, firstOption );
9fed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
64c414 ¤   ¤   va_end( args );
b51b52 ¤   ¤
cbcb70 ¤   ¤   if( IsntPGPError( error ) )
2a5b34 ¤   ¤   {
dfd03e ¤   ¤   ¤   error = kPGPError_BadParams;
570fe4 ¤   ¤   }
889371 ¤   }
f267c5 ¤
ab57f8 ¤   return( error );
4defe6 }
1eaf5a
13af5a
730335 /*____________________________________________________________________________
9511ee ¤   Revoke a key
69f7f7 ____________________________________________________________________________*/
a2af5a
52c744 ¤   PGPError
7f9c44 PGPRevokeKey(
37fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
8e41a1 ¤   PGPOptionListRef¤   firstOption,
62c9f6 ¤   ...
4427e6 ¤   )
84bb36 {
8c1765 ¤   PGPError¤   ¤   error;
9967c5 ¤
06b0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
5967c5 ¤
c8e68f ¤   if( pgpKeyIsValid( key ) )
59c7a1 ¤   {
5d36db ¤   ¤   va_list¤¤   ¤   ¤   args;
90f888 ¤   ¤   PGPOptionListRef¤   optionList;
a6444d ¤   ¤   PGPContextRef¤  ¤   context;
5f1b52 ¤   ¤
5502ff ¤   ¤   va_start( args, firstOption );
4a3a3e ¤   ¤   context¤¤   = PGPGetKeyContext( key );
9d6c4f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE,
7877f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·firstOption, args );
cdaf5a
9db8fa ¤   ¤   error = pgpGetOptionListError( optionList );
8fcb70 ¤   ¤   if( IsntPGPError( error ) )
--500a 000d16ba72a4010011d Page 5 of pgpClientKeyDB.c
e35b34 ¤   ¤   {
f38ef6 ¤   ¤   ¤   error = pgpRevokeKeyInternal( key, optionList );
d70fe4 ¤   ¤   }
33c414 ¤   ¤   va_end( args );
84af5a
fa153d ¤   ¤   PGPFreeOptionList( optionList );
1f9371 ¤   }
5e0e24 ¤   else
bbc7a1 ¤   {
e236db ¤   ¤   va_list¤¤   ¤   ¤   args;
341b52 ¤   ¤
4602ff ¤   ¤   va_start( args, firstOption );
4eed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
d0c414 ¤   ¤   va_end( args );
c01b52 ¤   ¤
1cd5d3 ¤   ¤   error = kPGPError_BadParams;
509371 ¤   }
d267c5 ¤
8457f8 ¤   return( error );
69efe6 }
d6af5a
1daf5a
d80335 /*____________________________________________________________________________
cb7ee3 ¤   Revoke a subkey
8bf7f7 ____________________________________________________________________________*/
e5af5a
0ec744 ¤   PGPError
96b07f PGPRevokeSubKey(
14dc15 ¤   PGPSubKeyRef¤   ¤   subkey,
1d41a1 ¤   PGPOptionListRef¤   firstOption,
fac9f6 ¤   ...
8927e6 ¤   )
d4bb36 {
d91765 ¤   PGPError¤   ¤   error;
2d67c5 ¤
0b7a00 ¤   pgpAssert( pgpSubKeyIsValid( subkey ) );
2667c5 ¤
4e5253 ¤   if( pgpSubKeyIsValid( subkey ) )
56c7a1 ¤   {
1e36db ¤   ¤   va_list¤¤   ¤   ¤   args;
b9f888 ¤   ¤   PGPOptionListRef¤   optionList;
62444d ¤   ¤   PGPContextRef¤  ¤   context;
bf1b52 ¤   ¤
5402ff ¤   ¤   va_start( args, firstOption );
0869e5 ¤   ¤   context¤¤   = PGPGetKeyContext( subkey->key );
036c4f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE,
4277f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·firstOption, args );
c1af5a
d6b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
1ecb70 ¤   ¤   if( IsntPGPError( error ) )
535b34 ¤   ¤   {
931f27 ¤   ¤   ¤   error = pgpRevokeSubKeyInternal( subkey, optionList );
e10fe4 ¤   ¤   }
5bc414 ¤   ¤   va_end( args );
eeaf5a
42153d ¤   ¤   PGPFreeOptionList( optionList );
889371 ¤   }
e90e24 ¤   else
a6c7a1 ¤   {
7d36db ¤   ¤   va_list¤¤   ¤   ¤   args;
061b52 ¤   ¤
7c02ff ¤   ¤   va_start( args, firstOption );
a2ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
a5c414 ¤   ¤   va_end( args );
bb1b52 ¤   ¤
9cd5d3 ¤   ¤   error = kPGPError_BadParams;
8f9371 ¤   }
db67c5 ¤
6c57f8 ¤   return( error );
a0efe6 }
d0af5a
d1af5a
--ca67 00085749b554010011d Page 6 of pgpClientKeyDB.c
a70335 /*____________________________________________________________________________
02a7cd ¤   Add a new userid to a key
44f7f7 ____________________________________________________________________________*/
42af5a
13c744 ¤   PGPError
f71f86 PGPAddUserID(
1afb7a ¤   PGPKeyRef¤  ¤   ¤   key,
f32fb1 ¤   char const *¤   ¤   userID,
6a41a1 ¤   PGPOptionListRef¤   firstOption,
81c9f6 ¤   ...
2327e6 ¤   )
b1bb36 {
4a87a6 ¤   PGPError¤   error;
fa67c5 ¤
13b0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
a19462 ¤   pgpAssertAddrValid( userID, char );
5767c5 ¤
e4da25 ¤   if( pgpKeyIsValid( key ) ·&& IsntNull( userID )
48917a ¤   ¤   && strlen( userID ) < 256 )
4dc7a1 ¤   {
9f36db ¤   ¤   va_list¤¤   ¤   ¤   args;
b7f888 ¤   ¤   PGPOptionListRef¤   optionList;
c1444d ¤   ¤   PGPContextRef¤  ¤   context;
d51b52 ¤   ¤
1002ff ¤   ¤   va_start( args, firstOption );
781b52 ¤   ¤
cb3a3e ¤   ¤   context¤¤   = PGPGetKeyContext( key );
e86c4f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE,
4a77f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·firstOption, args );
a9af5a
1db8fa ¤   ¤   error = pgpGetOptionListError( optionList );
80cb70 ¤   ¤   if( IsntPGPError( error ) )
635b34 ¤   ¤   {
1e908f ¤   ¤   ¤   error = pgpAddUserIDInternal( key, userID, optionList );
250fe4 ¤   ¤   }
33c414 ¤   ¤   va_end( args );
3faf5a
4c153d ¤   ¤   PGPFreeOptionList( optionList );
9d9371 ¤   }
860e24 ¤   else
7ec7a1 ¤   {
6936db ¤   ¤   va_list¤¤   ¤   ¤   args;
471b52 ¤   ¤
bb02ff ¤   ¤   va_start( args, firstOption );
31ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
3fc414 ¤   ¤   va_end( args );
cf1b52 ¤   ¤
2dd5d3 ¤   ¤   error = kPGPError_BadParams;
2d9371 ¤   }
d167c5 ¤
ce57f8 ¤   return( error );
dbefe6 }
9daf5a
84af5a
720335 /*____________________________________________________________________________
d368dc ¤   Add a generalized attribute to a key
96f7f7 ____________________________________________________________________________*/
ddaf5a
15c744 ¤   PGPError
f08d69 PGPAddAttributeUserID(
13fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
97e896 ¤   PGPAttributeType¤   attributeType,
344be0 ¤   PGPByte¤¤   ¤   ···*attributeData,
3e71fa ¤   PGPSize¤¤   ¤   ¤   attributeLength,
0541a1 ¤   PGPOptionListRef¤   firstOption,
afc9f6 ¤   ...
4b27e6 ¤   )
89bb36 {
8887a6 ¤   PGPError¤   error;
6167c5 ¤
2cb0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
854378 ¤   pgpAssertAddrValid( attributeData, PGPByte );
--bf20 000a24efa0c4010011d Page 7 of pgpClientKeyDB.c
2a67c5 ¤
f0a829 ¤   if( pgpKeyIsValid( key ) ·&& IsntNull( attributeData ) )
f5c7a1 ¤   {
6f36db ¤   ¤   va_list¤¤   ¤   ¤   args;
f0f888 ¤   ¤   PGPOptionListRef¤   optionList;
87444d ¤   ¤   PGPContextRef¤  ¤   context;
411b52 ¤   ¤
a902ff ¤   ¤   va_start( args, firstOption );
ec1b52 ¤   ¤
283a3e ¤   ¤   context¤¤   = PGPGetKeyContext( key );
b06c4f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE,
5f77f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·firstOption, args );
b9af5a
71b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
16cb70 ¤   ¤   if( IsntPGPError( error ) )
6e5b34 ¤   ¤   {
01252c ¤   ¤   ¤   error = pgpAddAttributeInternal( key, attributeType,
fdb506 ¤   ¤   ¤   ¤   ¤   ¤   ¤   attributeData, attributeLength, optionList );
2b0fe4 ¤   ¤   }
50c414 ¤   ¤   va_end( args );
47af5a
34153d ¤   ¤   PGPFreeOptionList( optionList );
4b9371 ¤   }
760e24 ¤   else
dfc7a1 ¤   {
5f36db ¤   ¤   va_list¤¤   ¤   ¤   args;
5d1b52 ¤   ¤
f702ff ¤   ¤   va_start( args, firstOption );
69ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
3fc414 ¤   ¤   va_end( args );
ce1b52 ¤   ¤
61d5d3 ¤   ¤   error = kPGPError_BadParams;
159371 ¤   }
3267c5 ¤
1057f8 ¤   return( error );
87efe6 }
b2af5a
6eaf5a
2e0335 /*____________________________________________________________________________
66035e ¤   Find out how much entropy is needed
a0f7f7 ____________________________________________________________________________*/
02af5a
ad108d ¤   PGPUInt32
84fcf8 PGPGetKeyEntropyNeeded(
92a1bc ¤   PGPContextRef¤  ¤   context,
d841a1 ¤   PGPOptionListRef¤   firstOption,
fac9f6 ¤   ...
0c27e6 ¤   )
f9bb36 {
945108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
caa9d2 ¤   PGPUInt32¤  result = ~(PGPUInt32)0;
ac67c5 ¤
a78679 ¤   pgpAssert( pgpContextIsValid( context ) );
9c67c5 ¤
67e8d2 ¤   if( pgpContextIsValid( context ) )
5fc7a1 ¤   {
5b36db ¤   ¤   va_list¤¤   ¤   ¤   args;
06f888 ¤   ¤   PGPOptionListRef¤   optionList;
f51b52 ¤   ¤
ac02ff ¤   ¤   va_start( args, firstOption );
4f6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
c7b819 ¤   ¤   ¤   FALSE, firstOption, args );
69af5a
31b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
3acb70 ¤   ¤   if( IsntPGPError( error ) )
bb5b34 ¤   ¤   {
88a54e ¤   ¤   ¤   result = pgpKeyEntropyNeededInternal( context, optionList );
980fe4 ¤   ¤   }
06c414 ¤   ¤   va_end( args );
0daf5a
f6153d ¤   ¤   PGPFreeOptionList( optionList );
a29371 ¤   }
--988a 0000aa82b914010011d Page 8 of pgpClientKeyDB.c
060e24 ¤   else
c2c7a1 ¤   {
5036db ¤   ¤   va_list¤¤   ¤   ¤   args;
931b52 ¤   ¤
2c02ff ¤   ¤   va_start( args, firstOption );
9fed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
72c414 ¤   ¤   va_end( args );
8a9371 ¤   }
6367c5 ¤
c41534 ¤   /* No mechanism to return an error at this time */
ce4c6e ¤   return( result );
b6efe6 }
ffaf5a
e1af5a
8c0335 /*____________________________________________________________________________
3e4e8e ¤   Export a keyset to a buffer or file
29f7f7 ____________________________________________________________________________*/
41af5a
e1c744 ¤   PGPError
d8edf1 PGPExportKeySet(
20131f ¤   PGPKeySetRef¤   ¤   keys,
bf41a1 ¤   PGPOptionListRef¤   firstOption,
10c9f6 ¤   ...
e227e6 ¤   )
bfbb36 {
3817eb ¤   PGPError¤   ¤   error¤  = kPGPError_NoErr;
9967c5 ¤
637a27 ¤   pgpAssert( pgpKeySetIsValid( keys ) );
5567c5 ¤
8067bb ¤   if( pgpKeySetIsValid( keys ) )
a5c7a1 ¤   {
7936db ¤   ¤   va_list¤¤   ¤   ¤   args;
89f888 ¤   ¤   PGPOptionListRef¤   optionList;
38444d ¤   ¤   PGPContextRef¤  ¤   context;
1f67c5 ¤
ea02ff ¤   ¤   va_start( args, firstOption );
541b52 ¤   ¤
17d575 ¤   ¤   context¤= PGPGetKeySetContext( keys );
356bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
d5b819 ¤   ¤   ¤   FALSE, firstOption, args );
2baf5a
4cb8fa ¤   ¤   error = pgpGetOptionListError( optionList );
28cb70 ¤   ¤   if( IsntPGPError( error ) )
c15b34 ¤   ¤   {
bb60c0 ¤   ¤   ¤   error = pgpExportKeySetInternal( keys, optionList );
050fe4 ¤   ¤   }
07c414 ¤   ¤   va_end( args );
e5af5a
a3ca21 ¤   ¤   /* optionList is freed in internal function */
f19371 ¤   }
940e24 ¤   else
21c7a1 ¤   {
5536db ¤   ¤   va_list¤¤   ¤   ¤   args;
bc1b52 ¤   ¤
de02ff ¤   ¤   va_start( args, firstOption );
04ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
c8c414 ¤   ¤   va_end( args );
fb1b52 ¤   ¤
87d5d3 ¤   ¤   error = kPGPError_BadParams;
ec9371 ¤   }
9a67c5 ¤
7757f8 ¤   return( error );
2cefe6 }
06af5a
5e0335 /*____________________________________________________________________________
771df3 ¤   Import a keyset from a buffer or file
46f7f7 ____________________________________________________________________________*/
70af5a
17c744 ¤   PGPError
51b8e2 PGPImportKeySet(
7ba1bc ¤   PGPContextRef¤  ¤   context,
0a8757 ¤   PGPKeySetRef¤   ¤   *keys,
--4fd3 0001bffbb734010011d Page 9 of pgpClientKeyDB.c
3b41a1 ¤   PGPOptionListRef¤   firstOption,
15c9f6 ¤   ...
3027e6 ¤   )
c7bb36 {
165108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
2367c5 ¤
88efc5 ¤   if( IsntNull( keys ) )
4756a9 ¤   ¤   *keys¤  = kInvalidPGPKeySetRef;
911b52 ¤   ¤
6a69d7 ¤   if( pgpContextIsValid( context ) && IsntNull( keys ) )
f9c7a1 ¤   {
5736db ¤   ¤   va_list¤¤   ¤   ¤   args;
caf888 ¤   ¤   PGPOptionListRef¤   optionList;
451b52 ¤   ¤
1556a9 ¤   ¤   *keys¤  = kInvalidPGPKeySetRef;
3367c5 ¤
8b02ff ¤   ¤   va_start( args, firstOption );
ef6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
e2b819 ¤   ¤   ¤   FALSE, firstOption, args );
f0af5a
8db8fa ¤   ¤   error = pgpGetOptionListError( optionList );
25cb70 ¤   ¤   if( IsntPGPError( error ) )
d65b34 ¤   ¤   {
e1804a ¤   ¤   ¤   error = pgpImportKeySetInternal( context, keys, optionList );
370fe4 ¤   ¤   }
85c414 ¤   ¤   va_end( args );
a8af5a
1fca21 ¤   ¤   /* optionList is freed in internal function */
949371 ¤   }
df0e24 ¤   else
f3c7a1 ¤   {
ff36db ¤   ¤   va_list¤¤   ¤   ¤   args;
541b52 ¤   ¤
8602ff ¤   ¤   va_start( args, firstOption );
3ded0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
5dc414 ¤   ¤   va_end( args );
d31b52 ¤   ¤
94d5d3 ¤   ¤   error = kPGPError_BadParams;
b19371 ¤   }
6667c5 ¤
8e57f8 ¤   return( error );
daefe6 }
06af5a
9c0335 /*____________________________________________________________________________
3856b1 ¤   Change (top level) key passphrase
cdf7f7 ____________________________________________________________________________*/
78af5a
12c744 ¤   PGPError
72b2ee PGPChangePassphrase(
13fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
0141a1 ¤   PGPOptionListRef¤   firstOption,
57c9f6 ¤   ...
7b27e6 ¤   )
27bb36 {
c55108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
eb67c5 ¤
ccb0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
0b67c5 ¤
a3e68f ¤   if( pgpKeyIsValid( key ) )
42c7a1 ¤   {
bb36db ¤   ¤   va_list¤¤   ¤   ¤   args;
9b444d ¤   ¤   PGPContextRef¤  ¤   context;
bcf888 ¤   ¤   PGPOptionListRef¤   optionList;
6eaf5a
dd494b ¤   ¤   context = PGPGetKeyContext( key );
97af5a
5602ff ¤   ¤   va_start( args, firstOption );
c56bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
16b819 ¤   ¤   ¤   FALSE, firstOption, args );
66af5a
fbb8fa ¤   ¤   error = pgpGetOptionListError( optionList );
1bcb70 ¤   ¤   if( IsntPGPError( error ) )
--b31a 0005d35e9234010011d Page 10 of pgpClientKeyDB.c
e35b34 ¤   ¤   {
0b6559 ¤   ¤   ¤   error = pgpChangePassphraseInternal( key, optionList );
f10fe4 ¤   ¤   }
3dc414 ¤   ¤   va_end( args );
c7af5a
86153d ¤   ¤   PGPFreeOptionList( optionList );
c99371 ¤   }
2e0e24 ¤   else
b8c7a1 ¤   {
aa36db ¤   ¤   va_list¤¤   ¤   ¤   args;
8d1b52 ¤   ¤
0602ff ¤   ¤   va_start( args, firstOption );
34ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
a4c414 ¤   ¤   va_end( args );
e61b52 ¤   ¤
07d5d3 ¤   ¤   error = kPGPError_BadParams;
a69371 ¤   }
fe67c5 ¤
0657f8 ¤   return( error );
92efe6 }
55af5a
ab0335 /*____________________________________________________________________________
b58d4e ¤   Change subkey passphrase
40f7f7 ____________________________________________________________________________*/
36af5a
65c744 ¤   PGPError
6ebb8c PGPChangeSubKeyPassphrase(
cddc15 ¤   PGPSubKeyRef¤   ¤   subkey,
4441a1 ¤   PGPOptionListRef¤   firstOption,
b9c9f6 ¤   ...
5527e6 ¤   )
69bb36 {
125108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
c767c5 ¤
717a00 ¤   pgpAssert( pgpSubKeyIsValid( subkey ) );
2467c5 ¤
385253 ¤   if( pgpSubKeyIsValid( subkey ) )
cbc7a1 ¤   {
a636db ¤   ¤   va_list¤¤   ¤   ¤   args;
11444d ¤   ¤   PGPContextRef¤  ¤   context;
d5f888 ¤   ¤   PGPOptionListRef¤   optionList;
93af5a
d6495e ¤   ¤   context = PGPGetSubKeyContext( subkey );
60af5a
ca02ff ¤   ¤   va_start( args, firstOption );
4b6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
31b819 ¤   ¤   ¤   FALSE, firstOption, args );
bdaf5a
a6b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
e9cb70 ¤   ¤   if( IsntPGPError( error ) )
765b34 ¤   ¤   {
cb2f01 ¤   ¤   ¤   error = pgpChangeSubKeyPassphraseInternal( subkey, optionList );
d80fe4 ¤   ¤   }
a3c414 ¤   ¤   va_end( args );
a9af5a
37153d ¤   ¤   PGPFreeOptionList( optionList );
7e9371 ¤   }
760e24 ¤   else
20c7a1 ¤   {
ca36db ¤   ¤   va_list¤¤   ¤   ¤   args;
da1b52 ¤   ¤
c402ff ¤   ¤   va_start( args, firstOption );
54ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
fac414 ¤   ¤   va_end( args );
d91b52 ¤   ¤
d8d5d3 ¤   ¤   error = kPGPError_BadParams;
0f9371 ¤   }
fb67c5 ¤
1957f8 ¤   return( error );
d4efe6 }
b9af5a
5d0335 /*____________________________________________________________________________
--e012 000af7b9c734010011d Page 11 of pgpClientKeyDB.c
3366ae ¤   Check passphrase validity
46f7f7 ____________________________________________________________________________*/
7aaf5a
3c16ea ¤   PGPBoolean
e79cfe PGPPassphraseIsValid(
4cfb7a ¤   PGPKeyRef¤  ¤   ¤   key,
a041a1 ¤   PGPOptionListRef¤   firstOption,
d3c9f6 ¤   ...
b427e6 ¤   )
2fbb36 {
ebd76b ¤   PGPBoolean¤ rslt¤   = FALSE;
a75108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
aa67c5 ¤
70b0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
4467c5 ¤
ede68f ¤   if( pgpKeyIsValid( key ) )
09c7a1 ¤   {
5336db ¤   ¤   va_list¤¤   ¤   ¤   args;
26444d ¤   ¤   PGPContextRef¤  ¤   context;
63f888 ¤   ¤   PGPOptionListRef¤   optionList;
3eaf5a
f5494b ¤   ¤   context = PGPGetKeyContext( key );
02af5a
b302ff ¤   ¤   va_start( args, firstOption );
636bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
9cb819 ¤   ¤   ¤   FALSE, firstOption, args );
d2af5a
2cb8fa ¤   ¤   error = pgpGetOptionListError( optionList );
dacb70 ¤   ¤   if( IsntPGPError( error ) )
c25b34 ¤   ¤   {
92fa71 ¤   ¤   ¤   rslt = pgpPassphraseIsValidInternal( key, optionList );
0b0fe4 ¤   ¤   }
2bc414 ¤   ¤   va_end( args );
68af5a
90153d ¤   ¤   PGPFreeOptionList( optionList );
acaf5a
af1cc0 ¤   ¤   return rslt;
1d9371 ¤   }
4a0e24 ¤   else
61c7a1 ¤   {
cc36db ¤   ¤   va_list¤¤   ¤   ¤   args;
351b52 ¤   ¤
e902ff ¤   ¤   va_start( args, firstOption );
a6ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
03c414 ¤   ¤   va_end( args );
8a1b52 ¤   ¤
d098aa ¤   ¤   return FALSE;
7b9371 ¤   }
cbefe6 }
4aaf5a
2d0335 /*____________________________________________________________________________
e5d6eb ¤   Set key axiomatic, possibly testing passphrase
e7f7f7 ____________________________________________________________________________*/
d2af5a
bec744 ¤   PGPError
9b8101 PGPSetKeyAxiomatic(
a9fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
f741a1 ¤   PGPOptionListRef¤   firstOption,
d0c9f6 ¤   ...
3e27e6 ¤   )
99bb36 {
c75108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
4567c5 ¤
bfb0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
4a67c5 ¤
b2e68f ¤   if( pgpKeyIsValid( key ) )
51c7a1 ¤   {
9e36db ¤   ¤   va_list¤¤   ¤   ¤   args;
30444d ¤   ¤   PGPContextRef¤  ¤   context;
16f888 ¤   ¤   PGPOptionListRef¤   optionList;
07af5a
af494b ¤   ¤   context = PGPGetKeyContext( key );
--85df 0006de4464a4010011d Page 12 of pgpClientKeyDB.c
e0af5a
4002ff ¤   ¤   va_start( args, firstOption );
db6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
12b819 ¤   ¤   ¤   FALSE, firstOption, args );
9baf5a
07b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
eacb70 ¤   ¤   if( IsntPGPError( error ) )
145b34 ¤   ¤   {
8d1082 ¤   ¤   ¤   error = pgpSetKeyAxiomaticInternal( key, optionList );
340fe4 ¤   ¤   }
a9c414 ¤   ¤   va_end( args );
81af5a
41153d ¤   ¤   PGPFreeOptionList( optionList );
cc9371 ¤   }
7c0e24 ¤   else
6fc7a1 ¤   {
dd36db ¤   ¤   va_list¤¤   ¤   ¤   args;
cb1b52 ¤   ¤
bb02ff ¤   ¤   va_start( args, firstOption );
91ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
1bc414 ¤   ¤   va_end( args );
d91b52 ¤   ¤
6ed5d3 ¤   ¤   error = kPGPError_BadParams;
709371 ¤   }
ba67c5 ¤
af57f8 ¤   return( error );
39efe6 }
42af5a
83af5a
cf0335 /*____________________________________________________________________________
069d8b ¤   Get the passkeybuffer to unlock a key, given its passphrase
6df7f7 ____________________________________________________________________________*/
88af5a
3fc744 ¤   PGPError
69ebd3 PGPGetKeyPasskeyBuffer(
24fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
5c0d88 ¤   void¤   ¤   ¤   ···*passkeyBuffer,
3741a1 ¤   PGPOptionListRef¤   firstOption,
dec9f6 ¤   ...
9327e6 ¤   )
63bb36 {
425108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
1d67c5 ¤
7ab0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
3fc549 ¤   pgpAssert( IsntNull( passkeyBuffer ) );
6767c5 ¤
0ae25f ¤   if( pgpKeyIsValid( key ) && IsntNull( passkeyBuffer ) )
9bc7a1 ¤   {
1c36db ¤   ¤   va_list¤¤   ¤   ¤   args;
54444d ¤   ¤   PGPContextRef¤  ¤   context;
98f888 ¤   ¤   PGPOptionListRef¤   optionList;
7aaf5a
4d494b ¤   ¤   context = PGPGetKeyContext( key );
1faf5a
1202ff ¤   ¤   va_start( args, firstOption );
b86bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
d2b819 ¤   ¤   ¤   FALSE, firstOption, args );
90af5a
36b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
4acb70 ¤   ¤   if( IsntPGPError( error ) )
d95b34 ¤   ¤   {
8b0198 ¤   ¤   ¤   error = pgpGetKeyPasskeyBufferInternal( key, passkeyBuffer,
00f21b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   optionList );
2f0fe4 ¤   ¤   }
aec414 ¤   ¤   va_end( args );
e6af5a
ad153d ¤   ¤   PGPFreeOptionList( optionList );
489371 ¤   }
a50e24 ¤   else
8bc7a1 ¤   {
b836db ¤   ¤   va_list¤¤   ¤   ¤   args;
6d1b52 ¤   ¤
--04fe 0002e68defb4010011d Page 13 of pgpClientKeyDB.c
bf02ff ¤   ¤   va_start( args, firstOption );
29ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
cdc414 ¤   ¤   va_end( args );
dd1b52 ¤   ¤
66d5d3 ¤   ¤   error = kPGPError_BadParams;
409371 ¤   }
0467c5 ¤
0657f8 ¤   return( error );
12efe6 }
b7af5a
fa0335 /*____________________________________________________________________________
9c48c9 ¤   Get the passkeybuffer to unlock a subkey, given its passphrase
23f7f7 ____________________________________________________________________________*/
e5af5a
f1c744 ¤   PGPError
c29908 PGPGetSubKeyPasskeyBuffer(
71dc15 ¤   PGPSubKeyRef¤   ¤   subkey,
040d88 ¤   void¤   ¤   ¤   ···*passkeyBuffer,
4841a1 ¤   PGPOptionListRef¤   firstOption,
6cc9f6 ¤   ...
1027e6 ¤   )
7fbb36 {
505108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
0367c5 ¤
5c7a00 ¤   pgpAssert( pgpSubKeyIsValid( subkey ) );
ddc549 ¤   pgpAssert( IsntNull( passkeyBuffer ) );
4167c5 ¤
655632 ¤   if( pgpSubKeyIsValid( subkey ) && IsntNull( passkeyBuffer ) )
39c7a1 ¤   {
6136db ¤   ¤   va_list¤¤   ¤   ¤   args;
96444d ¤   ¤   PGPContextRef¤  ¤   context;
d9f888 ¤   ¤   PGPOptionListRef¤   optionList;
aeaf5a
60495e ¤   ¤   context = PGPGetSubKeyContext( subkey );
0caf5a
2702ff ¤   ¤   va_start( args, firstOption );
af6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
96b819 ¤   ¤   ¤   FALSE, firstOption, args );
99af5a
68b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
fbcb70 ¤   ¤   if( IsntPGPError( error ) )
175b34 ¤   ¤   {
825ba9 ¤   ¤   ¤   error = pgpGetSubKeyPasskeyBufferInternal( subkey, passkeyBuffer,
8e4982 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···optionList );
e20fe4 ¤   ¤   }
7ec414 ¤   ¤   va_end( args );
8faf5a
c0153d ¤   ¤   PGPFreeOptionList( optionList );
219371 ¤   }
ec0e24 ¤   else
ddc7a1 ¤   {
4e36db ¤   ¤   va_list¤¤   ¤   ¤   args;
e71b52 ¤   ¤
fd02ff ¤   ¤   va_start( args, firstOption );
90ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
6ac414 ¤   ¤   va_end( args );
f91b52 ¤   ¤
11d5d3 ¤   ¤   error = kPGPError_BadParams;
a39371 ¤   }
be67c5 ¤
3b57f8 ¤   return( error );
80efe6 }
5caf5a
b6af5a
0c0335 /*____________________________________________________________________________
1b20b0 ¤   Add, Remove, or Replace key self-sig options
81f7f7 ____________________________________________________________________________*/
18af5a
c2c744 ¤   PGPError
27379a PGPAddKeyOptions(
77fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
2e41a1 ¤   PGPOptionListRef¤   firstOption,
--04eb 000d5862b274010011d Page 14 of pgpClientKeyDB.c
bec9f6 ¤   ...
5627e6 ¤   )
53bb36 {
e75108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
5167c5 ¤
36b0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
4e67c5 ¤
7ce68f ¤   if( pgpKeyIsValid( key ) )
76c7a1 ¤   {
6a36db ¤   ¤   va_list¤¤   ¤   ¤   args;
a3444d ¤   ¤   PGPContextRef¤  ¤   context;
f8f888 ¤   ¤   PGPOptionListRef¤   optionList;
17af5a
2c494b ¤   ¤   context = PGPGetKeyContext( key );
51af5a
9d02ff ¤   ¤   va_start( args, firstOption );
706bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
2cb819 ¤   ¤   ¤   FALSE, firstOption, args );
59af5a
1bb8fa ¤   ¤   error = pgpGetOptionListError( optionList );
17cb70 ¤   ¤   if( IsntPGPError( error ) )
da5b34 ¤   ¤   {
d8e0b1 ¤   ¤   ¤   error = pgpAddKeyOptionsInternal( key, optionList );
fa0fe4 ¤   ¤   }
49c414 ¤   ¤   va_end( args );
f5af5a
4d153d ¤   ¤   PGPFreeOptionList( optionList );
6d9371 ¤   }
ff0e24 ¤   else
0bc7a1 ¤   {
0936db ¤   ¤   va_list¤¤   ¤   ¤   args;
3b1b52 ¤   ¤
9502ff ¤   ¤   va_start( args, firstOption );
34ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
17c414 ¤   ¤   va_end( args );
a11b52 ¤   ¤
55d5d3 ¤   ¤   error = kPGPError_BadParams;
b19371 ¤   }
6167c5 ¤
1257f8 ¤   return( error );
1befe6 }
68af5a
aac744 ¤   PGPError
ea5a0a PGPRemoveKeyOptions(
f9fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
0f41a1 ¤   PGPOptionListRef¤   firstOption,
35c9f6 ¤   ...
8227e6 ¤   )
77bb36 {
cc5108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
ee67c5 ¤
1db0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
e667c5 ¤
6ce68f ¤   if( pgpKeyIsValid( key ) )
94c7a1 ¤   {
4236db ¤   ¤   va_list¤¤   ¤   ¤   args;
84444d ¤   ¤   PGPContextRef¤  ¤   context;
9df888 ¤   ¤   PGPOptionListRef¤   optionList;
2baf5a
3b494b ¤   ¤   context = PGPGetKeyContext( key );
c9af5a
4802ff ¤   ¤   va_start( args, firstOption );
7c6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
9ab819 ¤   ¤   ¤   FALSE, firstOption, args );
d1af5a
58b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
98cb70 ¤   ¤   if( IsntPGPError( error ) )
225b34 ¤   ¤   {
851076 ¤   ¤   ¤   error = pgpRemoveKeyOptionsInternal( key, optionList );
650fe4 ¤   ¤   }
e6c414 ¤   ¤   va_end( args );
d5af5a
--3214 0017ac197884010011d Page 15 of pgpClientKeyDB.c
bb153d ¤   ¤   PGPFreeOptionList( optionList );
659371 ¤   }
4a0e24 ¤   else
8bc7a1 ¤   {
1f36db ¤   ¤   va_list¤¤   ¤   ¤   args;
141b52 ¤   ¤
ce02ff ¤   ¤   va_start( args, firstOption );
31ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
6cc414 ¤   ¤   va_end( args );
771b52 ¤   ¤
a5d5d3 ¤   ¤   error = kPGPError_BadParams;
1a9371 ¤   }
6667c5 ¤
b057f8 ¤   return( error );
57efe6 }
57af5a
1fc744 ¤   PGPError
3932d0 PGPUpdateKeyOptions(
39fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
4641a1 ¤   PGPOptionListRef¤   firstOption,
d5c9f6 ¤   ...
f127e6 ¤   )
d4bb36 {
a45108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
bf67c5 ¤
eeb0f1 ¤   pgpAssert( pgpKeyIsValid( key ) );
7967c5 ¤
1ae68f ¤   if( pgpKeyIsValid( key ) )
1ac7a1 ¤   {
ed36db ¤   ¤   va_list¤¤   ¤   ¤   args;
d4444d ¤   ¤   PGPContextRef¤  ¤   context;
a1f888 ¤   ¤   PGPOptionListRef¤   optionList;
40af5a
7f494b ¤   ¤   context = PGPGetKeyContext( key );
5faf5a
e802ff ¤   ¤   va_start( args, firstOption );
6b6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
7db819 ¤   ¤   ¤   FALSE, firstOption, args );
c6af5a
08b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
6dcb70 ¤   ¤   if( IsntPGPError( error ) )
985b34 ¤   ¤   {
5c91d0 ¤   ¤   ¤   error = pgpUpdateKeyOptionsInternal( key, optionList );
520fe4 ¤   ¤   }
b0c414 ¤   ¤   va_end( args );
f9af5a
57153d ¤   ¤   PGPFreeOptionList( optionList );
859371 ¤   }
1d0e24 ¤   else
0bc7a1 ¤   {
a236db ¤   ¤   va_list¤¤   ¤   ¤   args;
c81b52 ¤   ¤
8702ff ¤   ¤   va_start( args, firstOption );
88ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
26c414 ¤   ¤   va_end( args );
6c1b52 ¤   ¤
bfd5d3 ¤   ¤   error = kPGPError_BadParams;
ce9371 ¤   }
6c67c5 ¤
b157f8 ¤   return( error );
e5efe6 }
b4af5a
03af5a
9eaf5a
807e4d /*__Editor_settings____
69af5a
cd4126 ¤   Local Variables:
a37b17 ¤   tab-width: 4
d70e6c ¤   End:
eb5f8c ¤   vi: ts=4 sw=4
c39e9b ¤   vim: si
7ad062 _____________________*/
--9f76 0011b20fc5b4010011e Page 1 of Makefile.in
5ea601 #
875544 # priv/crypto/
3ca601 #
e131a8 # $Id: Makefile.in,v 1.2 1997/12/15 23:49:25 hal Exp $
3da601 #
5daf5a
60055f SUBDIRS=bignum cipher compress hash pipe random secshare
fca183 LIBDONE=bignum/DONE cipher/DONE compress/DONE hash/DONE pipe/LIBDONE \
3fc74b ¤   random/DONE secshare/DONE
81af5a
21211d all:: LIBDONE
1baf5a
--d4c3 0010e5cceaf4010011f Page 1 of Makefile.in
5ea601 #
d295c8 # priv/crypto/cipher/
a2a601 #
57c986 # $Id: Makefile.in,v 1.5 1997/10/07 17:34:31 hal Exp $
30a601 #
e5af5a
21e2fd OBJS=¤  pgpCFB.o pgpSymmetricCipher.o pgpIDEA.o pgpDES3.o \
ea4aa6 ¤   pgpCAST5.o pgpCBC.o
b013a0 PRIVHDRS= pgpCFBPriv.h pgpSymmetricCipherPriv.h pgpDES3.h \
f79367 ¤   pgpCAST5.h pgpIDEA.h pgpCBCPriv.h
1daf5a
0eb7a3 all:: DONE
--21c0 000a74c3fde40100120 Page 1 of pgpCAST5.c
bc38e5 /*
7c4981 ·* pgpCAST5.c - C source code for CAST block cipher, version 5
a533b0 ·*¤ ¤   ¤   ¤   AKA CAST5-128 and CAST-128.
63775e ·*
eb7ccd ·* RFC2144 describes this version of the CAST cipher.
e7775e ·*
7b9ec0 ·*·
7a2d8b ·* Subject to the terms and conditions set forth below, Northern Telecom
38d14a ·* Limited, to the extent of its legal right to do so, hereby grants a
6c8416 ·* non-exclusive, royalty free license to make, have made, use, sell and
4f1b63 ·* have sold products incorporating or embodying the CAST algorithm as
b3e9e2 ·* described herein.
dc9ec0 ·*·
8fea87 ·* DISCLAIMER OF ALL WARRANTIES
ba9ec0 ·*·
9deddf ·* IN NO EVENT SHALL NORTHERN TELECOM LIMITED OR ANY OF ITS·
dac635 ·* SUBSIDIARIES BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,·
688a34 ·* INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE GRANT OF·
95d47f ·* RIGHTS UNDER THIS LICENSE, EVEN IF NORTHERN TELECOM OR ANY OF ITS·
62f2bf ·* SUBSIDIARIES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ·
5d77bf ·* USE OF ANY OF THE RIGHTS GRANTED HEREUNDER SHALL BE AT LICENSEE'S·
21a51b ·* SOLE RISK.
0b9ec0 ·*·
6be743 ·* NORTHERN TELECOM LIMITED AND ITS SUBSIDIARIES SPECIFICALLY·
56d32b ·* DISCLAIM ANY REPRESENTATIONS, CONDITIONS, OR WARRANTIES,·
392299 ·* INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF NON-
51f54f ·* INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR·
dd74b5 ·* PURPOSE. ·WITHOUT LIMITING THE GENERALITY OF THE FOREGOING,·
9b723f ·* NOTHING IN THIS LICENSE SHALL BE CONSTRUED AS:
0e9ec0 ·*·
db5d71 ·* (A)¤ A WARRANTY OR REPRESENTATION AS TO THE VALIDITY OR SCOPE OF·
0457f4 ·* ANY PATENT OR ANY RIGHTS UNDER ANY OTHER FORM OF INTELLECTUAL·
d99290 ·* PROPERTY PROTECTION (WHETHER STATUTORY OR OTHERWISE);
049ec0 ·*·
9bab4f ·* (B)¤ A WARRANTY OR REPRESENTATION THAT ANY MANUFACTURE, SALE,·
f43da0 ·* LEASE, USE OR IMPORTATION WILL BE FREE FROM INFRINGEMENT OF ANY·
4865b8 ·* INTELLECTUAL PROPERTY RIGHTS OTHER THAN THOSE UNDER WHICH AND·
6c9a65 ·* TO THE EXTENT TO WHICH LICENSES ARE IN FORCE HEREUNDER;
f99ec0 ·*·
061e7f ·* (C)¤ AN OBLIGATION TO MAINTAIN ANY INTELLECTUAL PROPERTY RIGHTS·
2533a8 ·* OR TO CONTINUE TO PROSECUTE ANY APPLICATION IN RESPECT OF ANY·
3e4777 ·* INTELLECTUAL PROPERTY RIGHTS IN ANY COUNTRY;
579ec0 ·*·
c81cdb ·* (D)¤ AN OBLIGATION TO FURNISH ANY MANUFACTURING, TECHNICAL OR·
9c89ae ·* CONFIDENTIAL INFORMATION OR TO PROVIDE ANY ASSISTANCE,·
115abb ·* MAINTENANCE, OR SUPPORT OF ANY KIND;
5d9ec0 ·*·
5eeb50 ·* (E)¤ CONFERRING ANY RIGHT TO USE, IN ADVERTISING, PUBLICITY OR·
87044e ·* OTHERWISE, ANY NAME, TRADE NAME OR TRADEMARK (STATUTORY OR·
40597c ·* OTHERWISE), OR ANY CONTRACTION, ABBREVIATION OR SIMULATION·
107136 ·* THEREOF (EXCEPT AS SET OUT BELOW);
d99ec0 ·*·
25478f ·* (F)¤ CONFERRING BY IMPLICATION, ESTOPPEL OR OTHERWISE ANY·
9fbc02 ·* LICENSE OR OTHER RIGHT UNDER ANY INTELLECTUAL PROPERTY RIGHT,·
508dc3 ·* EXCEPT THE LICENSES AND RIGHTS EXPRESSLY GRANTED HEREUNDER;
d99ec0 ·*·
4e328f ·* (G)¤ AN OBLIGATION TO MAKE ANY DETERMINATION AS TO THE·
719122 ·* APPLICABILITY OF ANY INTELLECTUAL PROPERTY RIGHT TO ANY PRODUCT;
f29ec0 ·*·
368343 ·* (H)¤ CREATING ANY AGENCY, PARTNERSHIP, JOINT VENTURE OR SIMILAR·
fa6bb4 ·* RELATIONSHIP.
199ec0 ·*·
01176c ·* THIS LICENSE IS EXPRESSLY SUBJECT TO ANY LAWS, REGULATIONS, ORDERS·
4a1ae0 ·* OR OTHER RESTRICTIONS ON THE EXPORT FROM CANADA, THE UNITED·
ae6470 ·* STATES OR ANY OTHER COUNTRY OF CRYPTOGRAPHIC TECHNOLOGY. ·THIS·
9d5a65 ·* LICENSE SHALL NOT EXTEND TO ANY SUBJECT MATTER COVERED·
ec28ec ·* HEREUNDER WHICH IS EXPORTED WITHOUT A PROPER EXPORT LICENSE OR·
3421a8 ·* APPROVAL.
1e9ec0 ·*·
2f4d13 ·* License to use CAST as described herein is subject to it being
55edb3 ·* referred to in any inplementation thereof (including all product and
a7c9fb ·* markteting materials) as the "Northern Telecom Ltd., CAST Encryption
--c9cd 0003c69bd9440100120 Page 2 of pgpCAST5.c
4a2ef8 ·* Algorithm". ·The name of Northern Telecom Limited (including its
53b0db ·* subsidiaries) shall not be used to endorse or promote products without
0e0345 ·* the specific prior written consent of Northern Telecom Limited.
e09ec0 ·*·
a99ec0 ·*·
fee874 ·* $Id: pgpCAST5.c,v 1.17 1997/10/14 01:48:14 heller Exp $
d1775e ·*
75495d ·*/
a3d83c ·
573051 #include "pgpSDKBuildFlags.h"
48af5a
7dbb7d #ifndef PGP_CAST5
71bc9d #error you must define PGP_CAST5 one way or the other
4d7454 #endif
79af5a
47b487 #if PGP_CAST5¤  /* [ */
b8af5a
c1af5a
3936e5 #include "string.h"
63e2ff #include "pgpConfig.h"
a6af5a
650e2f #include "pgpSymmetricCipherPriv.h"
7143b4 #include "pgpCAST5.h"
e38e4c #include "pgpCASTBox5.h"
b30d08 #include "pgpMem.h"
02af5a
47e869 /* The size of a scheduled CAST5 key */
49a069 #define CAST5_KEYWORDS 32
9004fb #define CAST5_KEYBYTES (sizeof(PGPUInt32)*CAST5_KEYWORDS)
dfaf5a
8c6f00 /* CAST is uniformly big-endian - byte access macros */
124b22 #define B0(x) ((x) >> 24 & 255)
b12d78 #define B1(x) ((x) >> 16 & 255)
2d0798 #define B2(x) ((x) >> 8 & 255)
f34e6f #define B3(x) ((x) & 255)
49af5a
641566 /* Some macros used in the key scheduling code */
3928db #define x0 B0(x0123)
e3e073 #define x1 B1(x0123)
83b19a #define x2 B2(x0123)
077932 #define x3 B3(x0123)
8a019c #define x4 B0(x4567)
afc934 #define x5 B1(x4567)
c998dd #define x6 B2(x4567)
655075 #define x7 B3(x4567)
30fcc3 #define x8 B0(x89AB)
35346b #define x9 B1(x89AB)
ce8188 #define xA B2(x89AB)
634b9b #define xB B3(x89AB)
9588e7 #define xC B0(xCDEF)
424782 #define xD B1(xCDEF)
2914d0 #define xE B2(xCDEF)
60dec3 #define xF B3(xCDEF)
54143a #define z0 B0(z0123)
b9dc92 #define z1 B1(z0123)
b38d7b #define z2 B2(z0123)
f345d3 #define z3 B3(z0123)
083d7d #define z4 B0(z4567)
f5f5d5 #define z5 B1(z4567)
dba43c #define z6 B2(z4567)
fc6c94 #define z7 B3(z4567)
a6c022 #define z8 B0(z89AB)
a7088a #define z9 B1(z89AB)
babd69 #define zA B2(z89AB)
54777a #define zB B3(z89AB)
4db406 #define zC B0(zCDEF)
5a7b63 #define zD B1(zCDEF)
da2831 #define zE B2(zCDEF)
4ce222 #define zF B3(zCDEF)
4caf5a
6c38e5 /*
3cd23a ·* This expands a 128-bit key to a 32-word scheduled key, where each round
--9766 000cf4af84940100120 Page 3 of pgpCAST5.c
71b913 ·* uses two words: a 32-bit XOR mask and a 5-bit rotate amount. ·Shorter keys
df02ee ·* are just padded with zeros, and if they are 80 bits or less, the cipher
10730f ·* is reduced to 12 rounds (not implemented here).
8c775e ·*
d13127 ·* The feed-forward used with x0123 through yCDEF prevent any weak keys,
8f0686 ·* and the substitution to set up the xkey tables ensure that the subround
33d42b ·* keys are not easily derivable from each other, so linear cryptanalysis
0e3505 ·* won't do very well against CAST.
9b495d ·*/
cd2978 static void
7efd4b CAST5schedule(PGPUInt32 xkey[32], PGPByte const *k)
d5bb36 {
fa146b ¤   PGPUInt32 x0123, x4567, x89AB, xCDEF;
4324f1 ¤   PGPUInt32 z0123, z4567, z89AB, zCDEF;
704ba4 ¤   int i;
6baf5a
99f6c3 ¤   /* Initialize x0123456789ABCDEF with input key */
b78ec4 ¤   x0123=(PGPUInt32)
0b79e6 ¤   ¤   k[ 0]<<24 | (PGPUInt32)k[ 1]<<16 | (PGPUInt32)k[ 2]<<8 | k[ 3];
901b52 ¤   ¤
b63d9a ¤   x4567=(PGPUInt32)
6b4e50 ¤   ¤   k[ 4]<<24 | (PGPUInt32)k[ 5]<<16 | (PGPUInt32)k[ 6]<<8 | k[ 7];
2b1b52 ¤   ¤
dbbc64 ¤   x89AB=(PGPUInt32)
0e9b9e ¤   ¤   k[ 8]<<24 | (PGPUInt32)k[ 9]<<16 | (PGPUInt32)k[10]<<8 | k[11];
731b52 ¤   ¤
1a6797 ¤   xCDEF=(PGPUInt32)
21d259 ¤   ¤   k[12]<<24 | (PGPUInt32)k[13]<<16 | (PGPUInt32)k[14]<<8 | k[15];
66af5a
f1ac80 ¤   /* Now set up the key table */
1baf5a
d8cbf3 ¤   for (i = 0; i < 4; i++) {
9c3718 ¤   ¤   z0123 = x0123 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8];
be3b20 ¤   ¤   z4567 = x89AB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA];
1c7fad ¤   ¤   z89AB = xCDEF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9];
6c0950 ¤   ¤   zCDEF = x4567 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB];
ecaf5a
a7707b ¤   ¤   x0123 = z89AB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0];
8983c9 ¤   ¤   x4567 = z0123 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2];
52d457 ¤   ¤   x89AB = z4567 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1];
fc018c ¤   ¤   xCDEF = zCDEF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3];
2faf5a
430459 ¤   ¤   switch (i) {
14d5e4 ¤   ¤   ··case 0:
31e7ae ¤   ¤   ¤   /* Masking keys, rounds 0..7 */
df262e ¤   ¤   ¤   xkey[ 0] = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2];
c01deb ¤   ¤   ¤   xkey[ 2] = S5[zA] ^ S6[zB] ^ S7[z5] ^ S8[z4] ^ S6[z6];
a48b78 ¤   ¤   ¤   xkey[ 4] = S5[zC] ^ S6[zD] ^ S7[z3] ^ S8[z2] ^ S7[z9];
095242 ¤   ¤   ¤   xkey[ 6] = S5[zE] ^ S6[zF] ^ S7[z1] ^ S8[z0] ^ S8[zC];
dc87c7 ¤   ¤   ¤
bd40be ¤   ¤   ¤   xkey[ 8] = S5[x3] ^ S6[x2] ^ S7[xC] ^ S8[xD] ^ S5[x8];
b81271 ¤   ¤   ¤   xkey[10] = S5[x1] ^ S6[x0] ^ S7[xE] ^ S8[xF] ^ S6[xD];
42160f ¤   ¤   ¤   xkey[12] = S5[x7] ^ S6[x6] ^ S7[x8] ^ S8[x9] ^ S7[x3];
751642 ¤   ¤   ¤   xkey[14] = S5[x5] ^ S6[x4] ^ S7[xA] ^ S8[xB] ^ S8[x7];
bbcdcb ¤   ¤   ¤   break;
2a8f38 ¤   ¤   ··case 1:
a4ae75 ¤   ¤   ¤   /* Masking keys, rounds 8..15 */
a6e199 ¤   ¤   ¤   xkey[16] = S5[z3] ^ S6[z2] ^ S7[zC] ^ S8[zD] ^ S5[z9];
52ba12 ¤   ¤   ¤   xkey[18] = S5[z1] ^ S6[z0] ^ S7[zE] ^ S8[zF] ^ S6[zC];
fb24cf ¤   ¤   ¤   xkey[20] = S5[z7] ^ S6[z6] ^ S7[z8] ^ S8[z9] ^ S7[z2];
c74ef1 ¤   ¤   ¤   xkey[22] = S5[z5] ^ S6[z4] ^ S7[zA] ^ S8[zB] ^ S8[z6];
c287c7 ¤   ¤   ¤
655630 ¤   ¤   ¤   xkey[24] = S5[x8] ^ S6[x9] ^ S7[x7] ^ S8[x6] ^ S5[x3];
466df5 ¤   ¤   ¤   xkey[26] = S5[xA] ^ S6[xB] ^ S7[x5] ^ S8[x4] ^ S6[x7];
292f80 ¤   ¤   ¤   xkey[28] = S5[xC] ^ S6[xD] ^ S7[x3] ^ S8[x2] ^ S7[x8];
5d4ca2 ¤   ¤   ¤   xkey[30] = S5[xE] ^ S6[xF] ^ S7[x1] ^ S8[x0] ^ S8[xD];
d9cdcb ¤   ¤   ¤   break;
4e605c ¤   ¤   ··case 2:
406fd3 ¤   ¤   ¤   /* Rotation keys, rounds 0..7 */
7e6a01 ¤   ¤   ¤   xkey[ 1] = (S5[z8]^S6[z9]^S7[z7]^S8[z6]^S5[z2]) & 31;
2b2c0e ¤   ¤   ¤   xkey[ 3] = (S5[zA]^S6[zB]^S7[z5]^S8[z4]^S6[z6]) & 31;
cf43c2 ¤   ¤   ¤   xkey[ 5] = (S5[zC]^S6[zD]^S7[z3]^S8[z2]^S7[z9]) & 31;
--9c30 000ee141a9340100120 Page 4 of pgpCAST5.c
62008a ¤   ¤   ¤   xkey[ 7] = (S5[zE]^S6[zF]^S7[z1]^S8[z0]^S8[zC]) & 31;
c787c7 ¤   ¤   ¤
3a65b0 ¤   ¤   ¤   xkey[ 9] = (S5[x3]^S6[x2]^S7[xC]^S8[xD]^S5[x8]) & 31;
43b7be ¤   ¤   ¤   xkey[11] = (S5[x1]^S6[x0]^S7[xE]^S8[xF]^S6[xD]) & 31;
42597a ¤   ¤   ¤   xkey[13] = (S5[x7]^S6[x6]^S7[x8]^S8[x9]^S7[x3]) & 31;
6873e8 ¤   ¤   ¤   xkey[15] = (S5[x5]^S6[x4]^S7[xA]^S8[xB]^S8[x7]) & 31;
13cdcb ¤   ¤   ¤   break;
563a80 ¤   ¤   ··case 3:
d3069f ¤   ¤   ¤   /* Rotation keys, rounds 8..15 */
61c936 ¤   ¤   ¤   xkey[17] = (S5[z3]^S6[z2]^S7[zC]^S8[zD]^S5[z9]) & 31;
fc29aa ¤   ¤   ¤   xkey[19] = (S5[z1]^S6[z0]^S7[zE]^S8[zF]^S6[zC]) & 31;
29a31b ¤   ¤   ¤   xkey[21] = (S5[z7]^S6[z6]^S7[z8]^S8[z9]^S7[z2]) & 31;
7bb470 ¤   ¤   ¤   xkey[23] = (S5[z5]^S6[z4]^S7[zA]^S8[zB]^S8[z6]) & 31;
581b52 ¤   ¤
ec4a20 ¤   ¤   ¤   xkey[25] = (S5[x8]^S6[x9]^S7[x7]^S8[x6]^S5[x3]) & 31;
260c2f ¤   ¤   ¤   xkey[27] = (S5[xA]^S6[xB]^S7[x5]^S8[x4]^S6[x7]) & 31;
351811 ¤   ¤   ¤   xkey[29] = (S5[xC]^S6[xD]^S7[x3]^S8[x2]^S7[x8]) & 31;
208e1d ¤   ¤   ¤   xkey[31] = (S5[xE]^S6[xF]^S7[x1]^S8[x0]^S8[xD]) & 31;
4ecdcb ¤   ¤   ¤   break;
920fe4 ¤   ¤   }
f99371 ¤   }
c38751 ¤   x0123 = x4567 = x89AB = xCDEF = 0;
58bc12 ¤   z0123 = z4567 = z89AB = zCDEF = 0;
64efe6 }
64af5a
67b559 #undef x0
efac81 #undef x1
5986e9 #undef x2
229f31 #undef x3
96d239 #undef x4
7fcbe1 #undef x5
14e189 #undef x6
8ff851 #undef x7
c17b99 #undef x8
aa6241 #undef x9
945c45 #undef xA
31762d #undef xB
3e6ff5 #undef xC
6b22fd #undef xD
e33b25 #undef xE
98114d #undef xF
7a00e1 #undef z0
be1939 #undef z1
6f3351 #undef z2
062a89 #undef z3
d66781 #undef z4
fc7e59 #undef z5
3d5431 #undef z6
444de9 #undef z7
a8ce21 #undef z8
10d7f9 #undef z9
6ce9fd #undef zA
61c395 #undef zB
e5da4d #undef zC
559745 #undef zD
2b8e9d #undef zE
dca4f5 #undef zF
05af5a
c0ba65 /* Some macros used in the encryption/decryption code */
c144d8 #define ROL(x,r) ((x)<<(r) | (x)>>(32-(r)))
01af5a
f5d1d1 #ifdef __GNUC__
23af5e #if __i386__
78cf87 /* Redefine using GCC inline assembler */
4cebff #undef ROL
105bff #define ROL(x,r)¤   \
417da7 ¤   ({unsigned _y;¤ \
7aacec ¤   __asm__("rol %%cl,%0" : "=g" (_y) : "0" (x), "c" (r)); _y;})
7be3bd #endif /* __i386__ */
55a5dc #endif /* __GNUC__ */
52af5a
eec62a #define F1(x,xkey,i) (ROL((xkey)[2*(i)] + (x), (xkey)[2*(i)+1]))
--db24 0004a2cfe4140100120 Page 5 of pgpCAST5.c
e0c599 #define F2(x,xkey,i) (ROL((xkey)[2*(i)] ^ (x), (xkey)[2*(i)+1]))
4550f6 #define F3(x,xkey,i) (ROL((xkey)[2*(i)] - (x), (xkey)[2*(i)+1]))
e9af5a
bd08e5 #define G1(x) (((S1[B0(x)] ^ S2[B1(x)]) - S3[B2(x)]) + S4[B3(x)])
2e3005 #define G2(x) (((S1[B0(x)] - S2[B1(x)]) + S3[B2(x)]) ^ S4[B3(x)])
ca2000 #define G3(x) (((S1[B0(x)] + S2[B1(x)]) ^ S3[B2(x)]) - S4[B3(x)])
d2af5a
af38e5 /*
4cf7b4 ·* Encrypt the 8 bytes at *in into the 8 bytes at *out using the expanded
401e46 ·* key schedule from *xkey.
05495d ·*/
8a2978 static void
79dfa3 CAST5encrypt(PGPByte const *in, PGPByte *out, PGPUInt32 const *xkey)
0abb36 {
7efb87 ¤   PGPUInt32 l, r, t;
8baf5a
fd62ed ¤   l = (PGPUInt32)
060e2f ¤   ¤   in[0]<<24 | (PGPUInt32)in[1]<<16 | (PGPUInt32)in[2]<<8 | in[3];
54aff2 ¤   r = (PGPUInt32)
c03999 ¤   ¤   in[4]<<24 | (PGPUInt32)in[5]<<16 | (PGPUInt32)in[6]<<8 | in[7];
aaaf5a
07fe6a ¤   t = F1(r, xkey, ·0); l ^= G1(t);
126e25 ¤   t = F2(l, xkey, ·1); r ^= G2(t);
517620 ¤   t = F3(r, xkey, ·2); l ^= G3(t);
3e2c5a ¤   t = F1(l, xkey, ·3); r ^= G1(t);
bc8046 ¤   t = F2(r, xkey, ·4); l ^= G2(t);
8c8c72 ¤   t = F3(l, xkey, ·5); r ^= G3(t);
edc239 ¤   t = F1(r, xkey, ·6); l ^= G1(t);
8e5276 ¤   t = F2(l, xkey, ·7); r ^= G2(t);
9232d5 ¤   t = F3(r, xkey, ·8); l ^= G3(t);
4268af ¤   t = F1(l, xkey, ·9); r ^= G1(t);
d68f0e ¤   t = F2(r, xkey, 10); l ^= G2(t);
be833a ¤   t = F3(l, xkey, 11); r ^= G3(t);
50bb5b ¤   /* Stop here if only doing 12 rounds */
6bcd71 ¤   t = F1(r, xkey, 12); l ^= G1(t);
615d3e ¤   t = F2(l, xkey, 13); r ^= G2(t);
a36d59 ¤   t = F3(r, xkey, 14); l ^= G3(t);
163723 ¤   t = F1(l, xkey, 15); r ^= G1(t);
6aaf5a
f943ad ¤   out[0] = B0(r);
75c2d3 ¤   out[1] = B1(r);
584940 ¤   out[2] = B2(r);
a9c83e ¤   out[3] = B3(r);
c12b38 ¤   out[4] = B0(l);
a6aa46 ¤   out[5] = B1(l);
f021d5 ¤   out[6] = B2(l);
25a0ab ¤   out[7] = B3(l);
10efe6 }
59af5a
0038e5 /*
02b41f ·* Decrypt the 8 bytes at *in into the 8 bytes at *out using the expanded
f01e46 ·* key schedule from *xkey.
2c495d ·*/
c32978 static void
477f71 CAST5decrypt(PGPByte const *in, PGPByte *out, PGPUInt32 const *xkey)
e4bb36 {
8dfb87 ¤   PGPUInt32 l, r, t;
ccaf5a
05aff2 ¤   r = (PGPUInt32)
770e2f ¤   ¤   in[0]<<24 | (PGPUInt32)in[1]<<16 | (PGPUInt32)in[2]<<8 | in[3];
c662ed ¤   l = (PGPUInt32)
013999 ¤   ¤   in[4]<<24 | (PGPUInt32)in[5]<<16 | (PGPUInt32)in[6]<<8 | in[7];
60af5a
283723 ¤   t = F1(l, xkey, 15); r ^= G1(t);
f06d59 ¤   t = F3(r, xkey, 14); l ^= G3(t);
5f5d3e ¤   t = F2(l, xkey, 13); r ^= G2(t);
20cd71 ¤   t = F1(r, xkey, 12); l ^= G1(t);
ce0f8f ¤   /* Start here if only doing 12 rounds */
d1833a ¤   t = F3(l, xkey, 11); r ^= G3(t);
df8f0e ¤   t = F2(r, xkey, 10); l ^= G2(t);
1868af ¤   t = F1(l, xkey, ·9); r ^= G1(t);
4a32d5 ¤   t = F3(r, xkey, ·8); l ^= G3(t);
--4bfc 0001c05357240100120 Page 6 of pgpCAST5.c
685276 ¤   t = F2(l, xkey, ·7); r ^= G2(t);
a5c239 ¤   t = F1(r, xkey, ·6); l ^= G1(t);
1c8c72 ¤   t = F3(l, xkey, ·5); r ^= G3(t);
208046 ¤   t = F2(r, xkey, ·4); l ^= G2(t);
ed2c5a ¤   t = F1(l, xkey, ·3); r ^= G1(t);
2f7620 ¤   t = F3(r, xkey, ·2); l ^= G3(t);
216e25 ¤   t = F2(l, xkey, ·1); r ^= G2(t);
8cfe6a ¤   t = F1(r, xkey, ·0); l ^= G1(t);
87af5a
122e4e ¤   out[0] = B0(l);
94af30 ¤   out[1] = B1(l);
d524a3 ¤   out[2] = B2(l);
85a5dd ¤   out[3] = B3(l);
8146db ¤   out[4] = B0(r);
12c7a5 ¤   out[5] = B1(r);
824c36 ¤   out[6] = B2(r);
7dcd48 ¤   out[7] = B3(r);
22efe6 }
37af5a
01af5a
2138e5 /*
85457f ·* Exported functions
79495d ·*/
4aaf5a
4b7d22 /* Expand 16 byte key into expanded key *priv */
2c2978 static void
16a0f2 cast5Key(void *priv, void const *key)
adbb36 {
62d929 ¤   CAST5schedule((PGPUInt32 *)priv, (const PGPByte *) key);
40efe6 }
96af5a
5aa6ff /* Encrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
842978 static void
6ae3c7 cast5Encrypt(void *priv, void const *in, void *out)
1ebb36 {
a1ad67 ¤   CAST5encrypt((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 *)priv);
dfefe6 }
9caf5a
45ec80 /* Decrypt 8 bytes at *in into 8 bytes at *out using key sched from *priv */
df2978 static void
4227b7 cast5Decrypt(void *priv, void const *in, void *out)
ebbb36 {
4aa96b ¤   CAST5decrypt( (const PGPByte *) in, (PGPByte *) out, (PGPUInt32 *)priv);
84efe6 }
0daf5a
e3af5a
81af5a
7d38e5 /*
79fea0 ·* Do one 64-bit step of a Tandem Davies-Meyer hash computation.
fff1a8 ·* The hash buffer is 32 bytes long and contains H (0..7), then G (8..15),
34f12f ·* then 16 bytes of scratch space. ·The buf is 8 bytes long.
f1f18f ·* xkey is a temporary key schedule buffer.
133a09 ·* This and the extra data in the hash buffer are allocated by the
6c2186 ·* caller to reduce the amount of buffer-wiping we have to do.
7728d7 ·* (It's only called from ideaWash, so the interface can be a bit
aa5ff5 ·* specialized.)
b1495d ·*/
002978 static void
52fce6 CAST5StepTandemDM(PGPByte *hash, PGPByte const *buf, PGPUInt32 *xkey)
37bb36 {
db4ba4 ¤   int i;
d6af5a
69faea ¤   /* key1 = G << 64 + M, remembering that CAST is big-endian */
f745c1 ¤   memcpy(hash+16, buf, 8);
49aba5 ¤   CAST5schedule(xkey, hash+8);
45ca23 ¤   /* W = E_key1(H), key2 = M << 64 + W */
7f2e31 ¤   CAST5encrypt(hash, hash+24, xkey);
81e23d ¤   CAST5schedule(xkey, hash+16);
0e932e ¤   /* V = E_key2(G) */
186cc1 ¤   CAST5encrypt(hash+8, hash+16, xkey);
b8a8d1 ¤   /* H ^= W, G ^= V */
1c1246 ¤   for (i = 0; i < 8; i++) {
--517e 0001aa353e540100120 Page 7 of pgpCAST5.c
58575f ¤   ¤   hash[i] ^= hash[i+24];
d65171 ¤   ¤   hash[i+8] ^= hash[i+16];
699371 ¤   }
3aefe6 }
39af5a
6438e5 /*
2ddc2f ·* Munge the key of the CipherContext based on the supplied bytes.
346a26 ·* This is for random-number generation, so the exact technique is
b7572d ·* unimportant, but it happens to use the current key as the
b2d7f2 ·* IV for computing a tandem Davies-Meyer hash of the bytes,
9b2d54 ·* and uses the output as the new key.
6f495d ·*/
4a2978 static void
12f3ef cast5Wash(void *priv, void const *bufIn, PGPSize len)
38bb36 {
cf80de ¤   PGPSize i;
a6a42c ¤   PGPByte hash[32];
1328fd ¤   PGPUInt32 ¤ *xkey = (PGPUInt32 *)priv;
16cd75 ¤   PGPByte¤¤   *buf = (PGPByte *) bufIn;
b567c5 ¤
8a4c69 ¤   /* Read out the key in canonical byte order for the IV */
961246 ¤   for (i = 0; i < 8; i++) {
6f4239 ¤   ¤   hash[2*i] = (PGPByte)(xkey[i]>>8);
e90859 ¤   ¤   hash[2*i+1] = (PGPByte)xkey[i];
9d9371 ¤   }
dcaf5a
114c63 ¤   /* Do the initial blocks of the hash */
6721f7 ¤   i = len;
c2ac52 ¤   while (i >= 8) {
384d5c ¤   ¤   CAST5StepTandemDM(hash, buf, xkey);
918f1d ¤   ¤   buf += 8;
221544 ¤   ¤   i -= 8;
349371 ¤   }
2bd8af ¤   /*
1c22a9 ¤   ·* At the end, we do Damgard-Merkle strengthening, just like
46deb8 ¤   ·* MD5 or SHA. ·Pad with 0x80 then 0 bytes to 6 mod 8, then
409725 ¤   ·* add the length. ·We use a 16-bit length in bytes instead
d1ed88 ¤   ·* of a 64-bit length in bits, but that is cryptographically
66dbba ¤   ·* irrelevant.
b4a4e3 ¤   ·*/
608210 ¤   /* Do the first partial block - i <= 7 */
748020 ¤   memcpy(hash+24, buf, i);
b4b9ac ¤   hash[24 + i++] = 0x80;
a1764c ¤   if (i > 6) {
959246 ¤   ¤   pgpClearMemory(hash+24+i, 8-i);
a3c321 ¤   ¤   CAST5StepTandemDM(hash, hash+24, xkey);
399ed6 ¤   ¤   i = 0;
f29371 ¤   }
c06eb1 ¤   pgpClearMemory(hash+24+i, 6-i);
a9d966 ¤   hash[30] = (PGPByte)(len >> 8);
25fd34 ¤   hash[31] = (PGPByte)len;
e5db71 ¤   CAST5StepTandemDM(hash, hash+24, xkey);
6baf5a
9509a6 ¤   /* Re-schedule the key */
2e0d3b ¤   CAST5schedule(xkey, hash);
75af5a
46bf06 ¤   pgpClearMemory( hash, ·sizeof(hash));
e9efe6 }
90af5a
f338e5 /*
a719dd ·* Define a Cipher for the generic cipher. ·This is the only
49c178 ·* real exported thing -- everything else can be static, since everything
5db83b ·* is referenced through function pointers!
6c495d ·*/
3e1ba8 PGPCipherVTBL const cipherCAST5 =
87bb36 {
0f7e89 ¤   "CAST5",
8e8e4e ¤   kPGPCipherAlgorithm_CAST5,
bbf346 ¤   8,¤ ¤   ¤   /* Blocksize */
47f8ba ¤   16,¤¤   ¤   /* Keysize */
142924 ¤   CAST5_KEYBYTES,¤¤   ¤   ¤   /* Priv array size */
1a3cdd ¤   alignof(PGPUInt32),
--77a7 0000c6ac64240100120 Page 8 of pgpCAST5.c
c49ef4 ¤   cast5Key,
77514b ¤   cast5Encrypt,
a8bbda ¤   cast5Decrypt,
7c7d14 ¤   cast5Wash
8282f7 };
82af5a
b9af5a
d6af5a
c2af5a
40af5a
94814a #if UNITTEST
91af5a
f8af5a
a838e5 /*
a9dccd ·* From RFC2144:
50775e ·*
a9b227 ·* Appendix B. Test Vectors
719ec0 ·*·
12740f ·* ···This appendix provides test vectors for the CAST-128 cipher described
e7fa45 ·* ···this document.
b49ec0 ·*·
3f8b58 ·* B.1. Single Plaintext-Key-Ciphertext Sets
d29ec0 ·*·
73d1a3 ·* ···In order to ensure that the algorithm is implemented correctly, the
60ada2 ·* ···following test vectors can be used for verification (values given in
8e9479 ·* ···hexadecimal notation).
0b9ec0 ·*·
a880e7 ·* ···128-bit key ········= 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
81dc0c ·* ···········plaintext ··= 01 23 45 67 89 AB CD EF
9aeaea ·* ···········ciphertext ·= 23 8B 4F E5 84 7E 44 B2
e69ec0 ·*·
b8d46a ·* ···80-bit ·key ········= 01 23 45 67 12 34 56 78 23 45
2abb4d ·* ·······················= 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
15dc0c ·* ···········plaintext ··= 01 23 45 67 89 AB CD EF
610fb4 ·* ···········ciphertext ·= EB 6A 71 1A 2C 02 27 1B
d59ec0 ·*·
7760a5 ·* ···40-bit ·key ········= 01 23 45 67 12
6ea58a ·* ·······················= 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
e6dc0c ·* ···········plaintext ··= 01 23 45 67 89 AB CD EF
645a28 ·* ···········ciphertext ·= 7A C8 16 D1 6E 9B 30 2E
a09ec0 ·*·
a55ecc ·* B.2. Full Maintenance Test
549ec0 ·*·
1a7556 ·* ···A maintenance test for CAST-128 has been defined to verify the
39c4e2 ·* ···correctness of implementations. ·It is defined in pseudo-code as
327dc8 ·* ···follows, where a and b are 128-bit vectors, aL and aR are the
55094f ·* ···leftmost and rightmost halves of a, bL and bR are the leftmost and
e0cf4b ·* ···rightmost halves of b, and encrypt(d,k) is the encryption in ECB mode
880690 ·* ···of block d under key k.
489ec0 ·*·
42f80b ·* ···Initial a = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
87efc4 ·* ···Initial b = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A (hex)
ab9ec0 ·*·
e433a9 ·* ···do 1,000,000 times
475044 ·* ···{
36965e ·* ·······aL = encrypt(aL,b)
a04816 ·* ·······aR = encrypt(aR,b)
2dc88d ·* ·······bL = encrypt(bL,a)
9716c5 ·* ·······bR = encrypt(bR,a)
1b0494 ·* ···}
799ec0 ·*·
b5b94e ·* Verify a == EE A9 D0 A2 49 FD 3B A6 B3 43 6F B8 9D 6D CA 92 (hex)
6b7f34 ·* Verify b == B2 C9 5E B0 0C 31 AD 71 80 AC 05 B8 E8 3D 69 6E (hex)
9f9ec0 ·*·
fe495d ·*/
d8af5a
8baf5a
0ae01b /* Test vectors */
b38526 PGPByte K1[] = {
187515 ¤   0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
ac5ad5 ¤   0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
0c82f7 };
--11c2 0005fde8f2240100120 Page 9 of pgpCAST5.c
bed37f PGPByte P1[] = {
908dca ¤   0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
1982f7 };
49faec PGPByte C1[] = {
e4153b ¤   0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2
a482f7 };
34af5a
a7b177 #if 0
3938e5 /*
787519 ·* We do not support 80-bit and lower keys, which require 12 rather
a28fb0 ·* than 16 rounds of encryption.
95495d ·*/
8b0ff6 PGPByte K2[] = {
e57515 ¤   0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
226918 ¤   0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6f82f7 };
3659af PGPByte P2[] = {
468dca ¤   0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
7882f7 };
0c703c PGPByte C2[] = {
d4811b ¤   0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B
7e82f7 };
01af5a
9a8e49 PGPByte K3[] = {
866eca ¤   0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00,
e5bfd5 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
f382f7 };
acd810 PGPByte P3[] = {
f28dca ¤   0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
d882f7 };
22f183 PGPByte C3[] = {
f352cb ¤   0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E
1a82f7 };
3f7454 #endif
dbaf5a
b1af5a
67a02c /* Maintenance test */
275b72 PGPByte A[] = {
827515 ¤   0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
d05ad5 ¤   0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
7182f7 };
b4d1a2 PGPByte B[] = {
f37515 ¤   0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
bd5ad5 ¤   0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
c182f7 };
ccff19 PGPByte VA[] = {
2a5082 ¤   0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6,
cba068 ¤   0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92
1b82f7 };
7175c9 PGPByte VB[] = {
bc655c ¤   0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71,
52ff1d ¤   0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E
2e82f7 };
c2af5a
5eaf5a
3f4d2f int
f37f68 main(void)
6aaa6d {¤  /* Test driver for CAST cipher */
cb4ba4 ¤   int i;
b060d1 ¤   PGPByte priv[CAST5_KEYBYTES];
91aabb ¤   PGPByte X[8], Y[8];
b1af5a
923959 ¤   /* First test */
e2b3a8 ¤   cast5Key(priv, K1);
de2114 ¤   cast5Encrypt(priv, P1, X);
38dce9 ¤   if (memcmp(C1, X, sizeof(X)) == 0)
9e41ec ¤   ¤   printf ("Encryption test 1 passed\n");
680e24 ¤   else
340c05 ¤   ¤   printf ("ERROR ON ENCRYPTION TEST 1\n");
c2af9f ¤   cast5Decrypt(priv, C1, Y);
a35e41 ¤   if (memcmp(P1, Y, sizeof(Y)) == 0)
5f93a2 ¤   ¤   printf ("Decryption test 1 passed\n");
--939f 00121cdb58540100120 Page 10 of pgpCAST5.c
060e24 ¤   else
e61487 ¤   ¤   printf ("ERROR ON DECRYPTION TEST 1\n");
d0af5a
e642cd ¤   /* Maintenance test */
6820d6 ¤   printf ("Performing maintenance test...\n");
cd0756 ¤   for (i=0; i<1000000; ++i) {
4acd22 ¤   ¤   cast5Key(priv, B);
2dd211 ¤   ¤   cast5Encrypt(priv, A, A);
4dc566 ¤   ¤   cast5Encrypt(priv, A+8, A+8);
4be8ef ¤   ¤   cast5Key(priv, A);
175fb2 ¤   ¤   cast5Encrypt(priv, B, B);
9137a8 ¤   ¤   cast5Encrypt(priv, B+8, B+8);
719371 ¤   }
8e1d90 ¤   if (memcmp(A, VA, sizeof(A)) == 0)
f04f25 ¤   ¤   printf ("Maintenance test A passed\n");
6b0e24 ¤   else
985b46 ¤   ¤   printf ("ERROR ON MAINTENANCE TEST A\n");
93edde ¤   if (memcmp(B, VB, sizeof(B)) == 0)
b9cc1b ¤   ¤   printf ("Maintenance test B passed\n");
be0e24 ¤   else
0ef328 ¤   ¤   printf ("ERROR ON MAINTENANCE TEST B\n");
1faf5a
7ba7e7 ¤   return 0;¤  /* normal exit */
c4cd3b } /* main */
52af5a
96bc6a #endif /* UNITTEST */
5eaf5a
e6af5a
0faf5a
714cef #endif /* ] PGP_CAST5 */
79af5a
527e4d /*__Editor_settings____
e6af5a
2e4126 ¤   Local Variables:
987b17 ¤   tab-width: 4
730e6c ¤   End:
925f8c ¤   vi: ts=4 sw=4
1c9e9b ¤   vim: si
21d062 _____________________*/
--38da 00114ae383a40100121 Page 1 of pgpCAST5.h
bc38e5 /*
a22a0f ·* pgpCAST5.h - header file for pgpCAST5.c
db775e ·*
c9e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
a42979 ·* You should not be using these functions in an application.
85775e ·*
0d506f ·* $Id: pgpCAST5.h,v 1.6 1997/06/13 01:52:54 lloyd Exp $
87495d ·*/
5d125e #ifndef Included_pgpCAST5_h
2e048b #define Included_pgpCAST5_h
62af5a
0f137e #include "pgpSymmetricCipherPriv.h"¤¤   /* for Cipher */
60af5a
1699c6 PGP_BEGIN_C_DECLARATIONS
faaf5a
3e38e5 /*
0b612d ·* This is the definition of the CAST5 cipher, for use with the
34dad0 ·* PGP Generic Cipher code.
b6495d ·*/
dfafca extern PGPCipherVTBL const cipherCAST5;
63af5a
d61254 PGP_END_C_DECLARATIONS
88af5a
14b009 #endif /* !Included_pgpCAST5_h */
--8a91 000977882b940100122 Page 1 of pgpCASTBox5.h
bc38e5 /*
00010f ·* pgpCASTBOX5.h - S-boxes for CAST5 cipher
9b775e ·*
f3e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
552979 ·* You should not be using these functions in an application.
61775e ·*
76ac51 ·* $Id: pgpCASTBox5.h,v 1.5 1997/06/04 16:17:40 lloyd Exp $
d5495d ·*/
41a3fd #ifndef Included_pgpCASTBox5_h
90d40e #define Included_pgpCASTBox5_h
7daf5a
ad99c6 PGP_BEGIN_C_DECLARATIONS
1caf5a
0538e5 /*
59e02f ·* The new CAST5 S-boxes, each mapping 8 input bits to 32 output bits.
d15ae6 ·* These boxes are at the heart of CAST's security. ·Random boxes
a3a12c ·* would not do nearly as well!
d1495d ·*/
2daf5a
cc7600 static PGPUInt32 const S1[256] = {
11b948 ¤   0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3,
4d7ff0 ¤   0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675,
180ab9 ¤   0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059,
6cee18 ¤   0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
99332d ¤   0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b,
271642 ¤   0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de,
085626 ¤   0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159,
aa4ca1 ¤   0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
55515b ¤   0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f,
6e9a21 ¤   0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165,
7920b9 ¤   0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38,
8cac40 ¤   0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
cbcec4 ¤   0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493,
095661 ¤   0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a,
a216d0 ¤   0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb,
304468 ¤   0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
f0080d ¤   0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14,
0c3cd7 ¤   0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6,
3a9cd7 ¤   0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8,
55d886 ¤   0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
ef576b ¤   0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495,
030054 ¤   0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e,
3cd435 ¤   0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426,
831fc4 ¤   0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
37bf73 ¤   0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98,
37b500 ¤   0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f,
c5418f ¤   0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad,
603694 ¤   0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
bc5d2b ¤   0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464,
717a9e ¤   0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a,
2778cf ¤   0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153,
e7bfda ¤   0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
0627cc ¤   0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274,
eae131 ¤   0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755,
0ca13d ¤   0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1,
862f6f ¤   0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
1dc87c ¤   0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1,
2941e0 ¤   0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79,
74714c ¤   0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c,
b54230 ¤   0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
77ad7b ¤   0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff,
43cdc5 ¤   0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d,
bf8280 ¤   0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf };
8eaf5a
aa88b3 static PGPUInt32 const S2[256] = {
967c67 ¤   0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a,
b76e56 ¤   0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba,
295544 ¤   0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605,
a1c2ec ¤   0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
a7401b ¤   0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b,
0d382b ¤   0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4,
973748 ¤   0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083,
--ef45 00061d89ee440100122 Page 2 of pgpCASTBox5.h
3746ce ¤   0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
f5d1ce ¤   0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f,
eff855 ¤   0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d,
6f359b ¤   0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e,
a58e5c ¤   0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
b7270f ¤   0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366,
a7e413 ¤   0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4,
4b8372 ¤   0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064,
0c43f0 ¤   0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
76db95 ¤   0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6,
58637d ¤   0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709,
421cdd ¤   0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364,
c1a1b1 ¤   0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
e50729 ¤   0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b,
b7da80 ¤   0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9,
f36f3f ¤   0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c,
d56715 ¤   0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
89ad2d ¤   0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741,
710219 ¤   0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab,
d2788d ¤   0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b,
e1e52a ¤   0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
03ea29 ¤   0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa,
751cc8 ¤   0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8,
e9a873 ¤   0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028,
7a5857 ¤   0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
2ebe7e ¤   0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6,
6a31e1 ¤   0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b,
fe2e6d ¤   0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1,
b6525b ¤   0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
215bdf ¤   0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb,
0f53c0 ¤   0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea,
359754 ¤   0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d,
a58440 ¤   0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
d95ef9 ¤   0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e,
02bf12 ¤   0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef,
31d004 ¤   0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 };
c1af5a
1fdd22 static PGPUInt32 const S3[256] = {
65ea5b ¤   0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b,
70a650 ¤   0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae,
323f35 ¤   0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9,
4ce748 ¤   0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
c469f6 ¤   0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd,
197f5b ¤   0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e,
3f2404 ¤   0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264,
165628 ¤   0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
0b54ce ¤   0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e,
b0e9ec ¤   0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f,
3d79cb ¤   0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e,
ab4d5c ¤   0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
7c1643 ¤   0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790,
ba6a71 ¤   0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504,
59000b ¤   0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e,
ebf5d8 ¤   0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
e43b89 ¤   0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8,
616491 ¤   0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d,
f2c2a2 ¤   0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240,
d623e6 ¤   0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
10b251 ¤   0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c,
856d45 ¤   0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15,
f1de09 ¤   0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788,
e3e698 ¤   0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
93af4a ¤   0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa,
3c4955 ¤   0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392,
8d4c67 ¤   0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f,
60c4ad ¤   0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
7d710a ¤   0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae,
2d55ec ¤   0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67,
884990 ¤   0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9,
17530e ¤   0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
a517d1 ¤   0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888,
61d4c6 ¤   0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d,
--dbe4 000f05446c140100122 Page 3 of pgpCASTBox5.h
c03174 ¤   0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2,
f6681c ¤   0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
34c1c1 ¤   0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2,
767711 ¤   0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce,
ae0aaf ¤   0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d,
733cb6 ¤   0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
4930c6 ¤   0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00,
4615d9 ¤   0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5,
c7725d ¤   0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 };
7aaf5a
ce7dc4 static PGPUInt32 const S4[256] = {
e87851 ¤   0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57,
c9847f ¤   0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120,
e08355 ¤   0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd,
9e1ee7 ¤   0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
ac4cfb ¤   0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe,
0a1ad7 ¤   0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701,
9d602d ¤   0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801,
64ea2a ¤   0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
f098ce ¤   0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1,
83964a ¤   0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746,
6c2361 ¤   0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3,
2ef21b ¤   0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
8a4ccb ¤   0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c,
51e947 ¤   0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c,
ca84a0 ¤   0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16,
02d494 ¤   0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
a6baa3 ¤   0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7,
040a1b ¤   0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327,
286854 ¤   0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002,
65243e ¤   0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
92fd3e ¤   0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7,
0ea991 ¤   0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031,
023778 ¤   0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff,
48053c ¤   0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
8df504 ¤   0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035,
8a2fb9 ¤   0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69,
1e43f4 ¤   0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec,
e75f3b ¤   0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
dcadeb ¤   0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e,
e6c2a2 ¤   0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3,
0b0b03 ¤   0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6,
d30a1f ¤   0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
60ba2c ¤   0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f,
a53dd5 ¤   0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091,
c01fd0 ¤   0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6,
6c76fd ¤   0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
d00127 ¤   0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2,
cdcf57 ¤   0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367,
3e8dc0 ¤   0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda,
e2ef9f ¤   0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
fa16c7 ¤   0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6,
781560 ¤   0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e,
3120df ¤   0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 };
22af5a
5d2855 static PGPUInt32 const S5[256] = {
eebe7a ¤   0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5,
1c25a4 ¤   0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00,
0b520b ¤   0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd,
8c93da ¤   0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
811c6a ¤   0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb,
613f6c ¤   0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725,
64671e ¤   0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040,
5953ed ¤   0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
242ebc ¤   0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2,
e5e4a9 ¤   0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec,
ac05ba ¤   0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399,
073039 ¤   0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
b77dfd ¤   0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966,
21089b ¤   0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468,
358ae6 ¤   0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9,
f0bddb ¤   0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
--0c13 000c69670a240100122 Page 4 of pgpCASTBox5.h
c8ff3d ¤   0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616,
b7eec9 ¤   0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4,
c560a0 ¤   0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419,
fe4a4b ¤   0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
3b3ec3 ¤   0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9,
c1e0b7 ¤   0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6,
e9a11a ¤   0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c,
1a3080 ¤   0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
c4b558 ¤   0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715,
47242b ¤   0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6,
7199f0 ¤   0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d,
cc490c ¤   0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
207ee9 ¤   0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba,
ecf6e8 ¤   0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487,
af3ef4 ¤   0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4,
1846ef ¤   0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
cd4a55 ¤   0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c,
36288d ¤   0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78,
773915 ¤   0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87,
f17efe ¤   0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
8b6cf5 ¤   0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110,
eb3103 ¤   0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58,
186be6 ¤   0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3,
394ce6 ¤   0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
2f518f ¤   0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d,
9eb1b8 ¤   0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55,
dd2738 ¤   0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 };
16af5a
e0d6e6 static PGPUInt32 const S6[256] = {
de43df ¤   0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4,
fd9ff7 ¤   0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9,
3abab3 ¤   0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd,
606c26 ¤   0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
5c494b ¤   0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f,
f8d958 ¤   0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c,
888b9d ¤   0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0,
b92633 ¤   0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
629a8b ¤   0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941,
6a2aba ¤   0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d,
c1ee62 ¤   0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223,
c48ae0 ¤   0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
9ee1f2 ¤   0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6,
4bf1b2 ¤   0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a,
8af8dc ¤   0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7,
9c0e51 ¤   0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
89bae6 ¤   0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89,
c8f9f3 ¤   0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be,
72b0b1 ¤   0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0,
f318e8 ¤   0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
38896c ¤   0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4,
6bb185 ¤   0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853,
51844d ¤   0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87,
84e85c ¤   0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
14c506 ¤   0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585,
d08ca8 ¤   0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751,
0757d0 ¤   0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75,
fc7273 ¤   0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
1fae39 ¤   0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283,
71b360 ¤   0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459,
a0a6ec ¤   0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef,
5a9879 ¤   0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
e4c4bf ¤   0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0,
e621d0 ¤   0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb,
6f31d8 ¤   0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200,
60ca87 ¤   0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
d0d2ae ¤   0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf,
7d6821 ¤   0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b,
1e5fd1 ¤   0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869,
382f9d ¤   0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
70109f ¤   0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb,
de9fbb ¤   0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454,
c6f24e ¤   0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f };
--a8f2 000ddee89f540100122 Page 5 of pgpCASTBox5.h
e0af5a
328377 static PGPUInt32 const S7[256] = {
688806 ¤   0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912,
80653e ¤   0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82,
df27fe ¤   0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9,
ccda17 ¤   0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
c21260 ¤   0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4,
687566 ¤   0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9,
2b4b1c ¤   0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce,
c0f80f ¤   0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
cfe288 ¤   0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7,
85c67e ¤   0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e,
b766f0 ¤   0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e,
680cad ¤   0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
39bac2 ¤   0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9,
71ddad ¤   0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b,
ba0198 ¤   0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3,
e1b8bb ¤   0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
795c22 ¤   0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c,
ffecdb ¤   0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802,
675359 ¤   0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778,
1aa3c3 ¤   0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
d0a723 ¤   0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be,
045a96 ¤   0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858,
6e9ed6 ¤   0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310,
990c09 ¤   0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
ae02cc ¤   0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476,
d5439b ¤   0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df,
9fd400 ¤   0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70,
180aa5 ¤   0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
f30ed8 ¤   0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a,
f8e7de ¤   0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07,
ee7664 ¤   0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c,
2da14f ¤   0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
dec40c ¤   0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e,
cc59e9 ¤   0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378,
bc7254 ¤   0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e,
6304c4 ¤   0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
d15d9a ¤   0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301,
25ceaa ¤   0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2,
a7bddf ¤   0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4,
aaebc7 ¤   0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
10b38b ¤   0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021,
968685 ¤   0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada,
61c059 ¤   0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 };
67af5a
749f3b static PGPUInt32 const S8[256] = {
73ce51 ¤   0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b,
b523a5 ¤   0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174,
1f5ce8 ¤   0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c,
7db7c0 ¤   0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
3ad74d ¤   0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7,
c630ba ¤   0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164,
87bea3 ¤   0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d,
70692d ¤   0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
7b87cd ¤   0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8,
6fefeb ¤   0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6,
1c3822 ¤   0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04,
de4010 ¤   0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
911e7f ¤   0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38,
16be70 ¤   0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8,
4b64a7 ¤   0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354,
936482 ¤   0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
a2180c ¤   0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160,
56060a ¤   0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab,
f14b9d ¤   0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2,
d744ac ¤   0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
10b20a ¤   0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98,
5f36ae ¤   0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441,
57dd09 ¤   0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4,
d882cc ¤   0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
dd39ba ¤   0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5,
--16bd 0010ceb7bcf40100122 Page 6 of pgpCASTBox5.h
a49702 ¤   0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c,
ef6bc6 ¤   0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5,
3a4212 ¤   0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
7c8107 ¤   0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b,
1d321c ¤   0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4,
a7a5cb ¤   0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084,
719c70 ¤   0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
1ca23b ¤   0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a,
84a7bb ¤   0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf,
ce2608 ¤   0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77,
3e756f ¤   0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
74f3b6 ¤   0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f,
d51e8b ¤   0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819,
38bc82 ¤   0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3,
0c16f6 ¤   0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
b3c113 ¤   0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1,
bd49ee ¤   0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d,
37be53 ¤   0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e };
6caf5a
891254 PGP_END_C_DECLARATIONS
39af5a
0c57c3 #endif /* !Included_pgpCASTBox5_h */
--c7ef 0009927e00e40100123 Page 1 of pgpCBC.c
a70335 /*____________________________________________________________________________
74a98f ¤   pgpCBC.c
a467c5 ¤
bec97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
c44b0f ¤   All rights reserved.
e667c5 ¤
d467c5 ¤
ebaf5a
93b6e4 ¤   $Id: pgpCBC.c,v 1.9.12.1 1998/11/12 03:21:17 heller Exp $
d0f7f7 ____________________________________________________________________________*/
d5e2ff #include "pgpConfig.h"
7d324c #include <string.h>
97af5a
240d08 #include "pgpMem.h"
d62f8d #include "pgpErrors.h"
780e2f #include "pgpSymmetricCipherPriv.h"
d3e34c #include "pgpCBCPriv.h"
3e5430 #include "pgpUtilitiesPriv.h"
7caf5a
1caf5a
4aaf5a
7f37ac #define PGPValidateCBC( CBC )¤  \
757d00 ¤   PGPValidateParam( pgpCBCIsValid( CBC ) );
c767c5 ¤
360335 /*____________________________________________________________________________
0b48d4 ¤   In CBC, iv[] is the previous block's ciphertext, or the Initial
863868 ¤   Vector before the first block is processed. ·As we read plaintext
c31b6e ¤   bytes during encryption, they are xored into iv[] until it is
84e82b ¤   full, then the symmetric cipher is run. ·For decryption, iv[] is
d2cb01 ¤   loaded with the previous ciphertext after we finish decrypting the
fcea00 ¤   current block.
8ff7f7 ____________________________________________________________________________*/
5a67c5 ¤
2167c5 ¤
e4af5a
fc9418 struct PGPCBCContext
29bb36 {
cc3c19 #define kCBCMagic¤  ¤   0xBAAB0957
0bbae3 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   magic;
ef16d0 ¤   PGPMemoryMgrRef¤¤   ¤   ¤   ¤   memoryMgr;
151778 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   CBCInited;
95d336 ¤   PGPSymmetricCipherContextRef¤   symmetricRef;
e631f9 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   ¤   iv1[ PGP_CBC_MAXBLOCKSIZE ];
8cc721 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   ¤   iv2[ PGP_CBC_MAXBLOCKSIZE ];
28e447 ¤   PGPByte *¤  ¤   ¤   ¤   ¤   ¤   iv;
3282f7 };
19af5a
376c2c ¤   static PGPBoolean
4eabbd pgpCBCIsValid( const PGPCBCContext * ref)
27bb36 {
e0984c ¤   PGPBoolean¤ valid¤  = FALSE;
d767c5 ¤
f995d3 ¤   valid¤  = IsntNull( ref ) && ref->magic¤ == kCBCMagic
9fe5dd ¤   ¤   ¤   ¤   && (ref->iv == ref->iv1 ·|| ·ref->iv == ref->iv2);
e767c5 ¤
260b09 ¤   return( valid );
b1efe6 }
46af5a
e7af5a
bdaf5a
2a0335 /*____________________________________________________________________________
8ae793 ¤   Internal forward references
39f7f7 ____________________________________________________________________________*/
5baf5a
da7f62 static void¤¤   pgpCBCInit( PGPCBCContext *¤ref,
df7c9c ¤   ¤   ¤   ¤   ¤   void const * key, void const * iv);
80ae30 ¤   ¤   ¤   ¤   ¤
07c8bf static PGPError¤pgpCBCEncrypt( PGPCBCContext *ref,
c77cfd ¤   ¤   ¤   ¤   ¤   void const * src, PGPSize len, void * dest );
bdae30 ¤   ¤   ¤   ¤   ¤
c72b2b static PGPError¤pgpCBCDecrypt( PGPCBCContext *ref,
997cfd ¤   ¤   ¤   ¤   ¤   void const * src, PGPSize len, void * dest );
--bffe 000a9d8edd140100123 Page 2 of pgpCBC.c
e0af5a
1aaf5a
17af5a
c90335 /*____________________________________________________________________________
8f913f ¤   Exported routines
f4f7f7 ____________________________________________________________________________*/
a1af5a
9c21ab ¤   PGPError·
267260 PGPNewCBCContext(
f00baf ¤   PGPSymmetricCipherContextRef¤   symmetricRef,
fc8699 ¤   PGPCBCContextRef *¤ ¤   ¤   ¤   outRef )
48bb36 {
cc1284 ¤   PGPCBCContextRef¤   ¤   ¤   ¤   newRef¤ = NULL;
9ef40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
d78d85 ¤   PGPMemoryMgrRef¤¤   ¤   ¤   ¤   memoryMgr¤  = NULL;
0267c5 ¤
233c76 ¤   PGPValidatePtr( outRef );
b63652 ¤   *outRef¤= NULL;
c4ffb4 ¤   PGPValidatePtr( symmetricRef );
0367c5 ¤
87e54c ¤   memoryMgr¤  = pgpGetSymmetricCipherMemoryMgr( symmetricRef );
6028f5 ¤   newRef¤ = (PGPCBCContextRef)
10a7c1 ¤   ¤   ¤   PGPNewData( memoryMgr,
c31f96 ¤   ¤   ¤   ¤   sizeof( *newRef ), 0 | kPGPMemoryMgrFlags_Clear);
b787c7 ¤   ¤   ¤
606c1a ¤   if ( IsntNull( newRef ) )
38c7a1 ¤   {
a35c98 #if PGP_DEBUG
283b63 ¤   ¤   /* make original invalid to enforce semantics */
16bd54 ¤   ¤   PGPSymmetricCipherContextRef¤   tempRef;
4a12f4 ¤   ¤   err¤= PGPCopySymmetricCipherContext( symmetricRef, &tempRef );
277d98 ¤   ¤   if ( IsntPGPError( err ) )
585b34 ¤   ¤   {
494127 ¤   ¤   ¤   PGPFreeSymmetricCipherContext( symmetricRef );
9a49e4 ¤   ¤   ¤   symmetricRef¤   = tempRef;
250fe4 ¤   ¤   }
60d87c ¤   ¤   err¤= kPGPError_NoErr;
287454 #endif
9faf5a
869fe0 ¤   ¤   newRef->magic¤  ¤   ¤   = kCBCMagic;
625fd9 ¤   ¤   newRef->CBCInited¤  ¤   = FALSE;
604e24 ¤   ¤   newRef->symmetricRef¤   = symmetricRef;
73c88a ¤   ¤   newRef->iv¤ ¤   ¤   ¤   = newRef->iv1;
4deb8f ¤   ¤   newRef->memoryMgr¤  ¤   = memoryMgr;
e21b52 ¤   ¤
b273d4 ¤   ¤   /* make sure we clean up */
3fbe18 ¤   ¤   if ( IsPGPError( err ) )
285b34 ¤   ¤   {
dc7f1d ¤   ¤   ¤   PGPFreeCBCContext( newRef );
be82ad ¤   ¤   ¤   newRef¤ = NULL;
da0fe4 ¤   ¤   }
1d9371 ¤   }
8a0e24 ¤   else
00c7a1 ¤   {
e1a810 ¤   ¤   /* we own it, so dispose it */
2f461c ¤   ¤   PGPFreeSymmetricCipherContext( symmetricRef );
af17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
439371 ¤   }
e167c5 ¤
8ecdaf ¤   *outRef¤= newRef;
4ddeb7 ¤   return( err );
e0efe6 }
0baf5a
b8af5a
aeaf5a
160335 /*____________________________________________________________________________
cbf7f7 ____________________________________________________________________________*/
f321ab ¤   PGPError·
2e1d82 PGPFreeCBCContext( PGPCBCContextRef ref )
ecbb36 {
289372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
a967c5 ¤
--44a7 000db38de1b40100123 Page 3 of pgpCBC.c
66f8ff ¤   PGPValidateCBC( ref );
ee67c5 ¤
cef7c6 ¤   PGPFreeSymmetricCipherContext( ref->symmetricRef );
2e67c5 ¤
cb4500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
78fa58 ¤   PGPFreeData( ref );
7c67c5 ¤
badeb7 ¤   return( err );
15efe6 }
c5af5a
5aaf5a
1eaf5a
900335 /*____________________________________________________________________________
33f7f7 ____________________________________________________________________________*/
f321ab ¤   PGPError·
e4d7d0 PGPCopyCBCContext(
ec6b85 ¤   PGPCBCContextRef¤   inRef,
a37f0f ¤   PGPCBCContextRef *¤ outRef )
c5bb36 {
51d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
cd8045 ¤   PGPCBCContextRef¤   newRef¤ = NULL;
4967c5 ¤
3b3c76 ¤   PGPValidatePtr( outRef );
6e3652 ¤   *outRef¤= NULL;
3f633d ¤   PGPValidateCBC( inRef );
2667c5 ¤
3728f5 ¤   newRef¤ = (PGPCBCContextRef)
20530e ¤   ¤   PGPNewData( inRef->memoryMgr,
91bb39 ¤   ¤   sizeof( *newRef ), 0);
deaf5a
566c1a ¤   if ( IsntNull( newRef ) )
b4c7a1 ¤   {
b85c22 ¤   ¤   *newRef¤¤   = *inRef;
8b1b52 ¤   ¤
39739c ¤   ¤   /* clear symmetric cipher in case later allocation fails */
356e86 ¤   ¤   newRef->symmetricRef = NULL;
d31b52 ¤   ¤
7d6df8 ¤   ¤   /* copy symmetric cipher */
52f6ca ¤   ¤   err¤= PGPCopySymmetricCipherContext(
632651 ¤   ¤   ¤   ¤   inRef->symmetricRef, &newRef->symmetricRef );
bd1b52 ¤   ¤
5dbe18 ¤   ¤   if ( IsPGPError( err ) )
e75b34 ¤   ¤   {
b07f1d ¤   ¤   ¤   PGPFreeCBCContext( newRef );
2a82ad ¤   ¤   ¤   newRef¤ = NULL;
930fe4 ¤   ¤   }
b79371 ¤   }
f00e24 ¤   else
58c7a1 ¤   {
ca17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
219371 ¤   }
e967c5 ¤
b0cdaf ¤   *outRef¤= newRef;
95deb7 ¤   return( err );
e0efe6 }
a3af5a
c2af5a
b4af5a
cf0335 /*____________________________________________________________________________
eef7f7 ____________________________________________________________________________*/
5321ab ¤   PGPError·
ccf3af PGPInitCBC(
b228db ¤   PGPCBCContextRef¤   ref,
f98a89 ¤   const void *¤   ¤   key,
cef1f1 ¤   const void *¤   ¤   initializationVector )
52bb36 {
43d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
e267c5 ¤
f8f8ff ¤   PGPValidateCBC( ref );
65057c ¤   /* at least one param must be non-nil */
4fdb79 ¤   PGPValidateParam( IsntNull( key ) || IsntNull( initializationVector ) );
db1b52 ¤   ¤
--ba28 0009ff5f86940100123 Page 4 of pgpCBC.c
d6e2ad ¤   pgpCBCInit( ref, key, initializationVector);
6c67c5 ¤
0bdeb7 ¤   return( err );
3eefe6 }
deaf5a
5baf5a
dcaf5a
47af5a
5eaf5a
620335 /*____________________________________________________________________________
0df7f7 ____________________________________________________________________________*/
2d66dd ¤   static PGPError
c8405b PGPCBCEncryptDecrypt(
f7c54b ¤   PGPBoolean¤ ¤   ¤   encrypt,
a428db ¤   PGPCBCContextRef¤   ref,
df08cf ¤   const void *¤   ¤   in,
72bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
7f03bc ¤   void *¤ ¤   ¤   ¤   out )
05bb36 {
2a9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
3067c5 ¤
62254f ¤   PGPValidatePtr( out );
43f8ff ¤   PGPValidateCBC( ref );
783bf7 ¤   PGPValidatePtr( in );
7cfddc ¤   PGPValidateParam( bytesIn != 0 );
28af5a
ff7d22 ¤   if ( ref->CBCInited )
2ac7a1 ¤   {
a3d90c ¤   ¤   if ( encrypt )
5f5dbf ¤   ¤   ¤   err = pgpCBCEncrypt( ref, in, bytesIn, out);
690e1d ¤   ¤   else
002759 ¤   ¤   ¤   err = pgpCBCDecrypt( ref, in, bytesIn, out);
8f9371 ¤   }
b50e24 ¤   else
82c7a1 ¤   {
233cb2 ¤   ¤   err¤= kPGPError_ImproperInitialization;
979371 ¤   }
b467c5 ¤
d9deb7 ¤   return( err );
10efe6 }
8caf5a
3eaf5a
d20335 /*____________________________________________________________________________
4cf7f7 ____________________________________________________________________________*/
cd21ab ¤   PGPError·
96a98d PGPCBCEncrypt(
ec28db ¤   PGPCBCContextRef¤   ref,
cc08cf ¤   const void *¤   ¤   in,
b0bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
9103bc ¤   void *¤ ¤   ¤   ¤   out )
7cbb36 {
984b4a ¤   return( PGPCBCEncryptDecrypt( TRUE, ref, in, bytesIn, out ) );
6eefe6 }
6caf5a
7dae30 ¤   ¤   ¤   ¤   ¤
650335 /*____________________________________________________________________________
19f7f7 ____________________________________________________________________________*/
6621ab ¤   PGPError·
53431c PGPCBCDecrypt(
1228db ¤   PGPCBCContextRef¤   ref,
6d08cf ¤   const void *¤   ¤   in,
12bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
0803bc ¤   void *¤ ¤   ¤   ¤   out )
73bb36 {
ca9029 ¤   return( PGPCBCEncryptDecrypt( FALSE, ref, in, bytesIn, out ) );
0defe6 }
bfaf5a
aaaf5a
0caf5a
370335 /*____________________________________________________________________________
b8f7f7 ____________________________________________________________________________*/
9f21ab ¤   PGPError·
--69f1 000ae6592c540100123 Page 5 of pgpCBC.c
a001c4 PGPCBCGetSymmetricCipher(
d34466 ¤   PGPCBCContextRef¤   ¤   ¤   ¤   ref,
5c386f ¤   PGPSymmetricCipherContextRef *¤ outRef )
b0bb36 {
5df40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
fd8365 ¤   PGPSymmetricCipherContextRef¤   symmetricRef¤   = NULL;
e567c5 ¤
583c76 ¤   PGPValidatePtr( outRef );
393652 ¤   *outRef¤= NULL;
48f8ff ¤   PGPValidateCBC( ref );
45af5a
d7585d ¤   symmetricRef¤   = ref->symmetricRef;
9a67c5 ¤
f45d89 ¤   *outRef¤= symmetricRef;
9ddeb7 ¤   return( err );
71efe6 }
3eaf5a
05af5a
b1af5a
a4af5a
cbaf5a
9bf66a #if PRAGMA_MARK_SUPPORTED
cb65af #pragma mark --- Internal Routines ---
ca7454 #endif
eeaf5a
99af5a
a0af5a
3eaf5a
81af5a
a2af5a
d6af5a
84af5a
8d0335 /*____________________________________________________________________________
784a35 ¤   Initialize contexts.
a5f390 ¤   If key is NULL, the current key is not changed.
e5b2ba ¤   if iv is NULL, the IV is set to all zero.
ddf7f7 ____________________________________________________________________________*/
f333c8 ¤   static void
d6de51 pgpCBCInit(
8b39e2 ¤   PGPCBCContext *¤¤   ref,
d3553f ¤   void const *¤   ¤   key,
724669 ¤   void const *¤   ¤   iv)
3fbb36 {
d958a2 ¤   PGPSize¤¤   ¤   blockSize;
2cab1f ¤   void const *¤   curIV¤  = iv;
b867c5 ¤
0c36b1 ¤   PGPGetSymmetricCipherSizes( ref->symmetricRef, NULL, &blockSize );
2167c5 ¤
357c7b ¤   if ( IsntNull( key ) )
b0c7a1 ¤   {
cd4583 ¤   ¤   PGPInitSymmetricCipher( ref->symmetricRef, key );
079371 ¤   }
2caf5a
42278d ¤   pgpClearMemory( ref->iv1, sizeof( ref->iv1 ) ·);
55f2bc ¤   pgpClearMemory( ref->iv2, sizeof( ref->iv2 ) ·);
9b13a6 ¤   ref->iv = ref->iv1;
c6af5a
4f7809 ¤   if ( IsntNull( iv ) )
b3c7a1 ¤   {
41fb6c ¤   ¤   pgpCopyMemory( curIV, ref->iv, blockSize );
d29371 ¤   }
60af5a
ee3706 ¤   /* rely on the symmetric cipher to know whether it has been inited */
29cb86 ¤   /* also, iv of NULL is OK, since semantics say that means zeroes */
3d88eb ¤   ref->CBCInited¤ ¤   = TRUE;
eaefe6 }
cbaf5a
a5af5a
e9af5a
ee0335 /*____________________________________________________________________________
95f7f7 ____________________________________________________________________________*/
ae08ca ¤   PGPSize
--c1f2 000bc41c93e40100123 Page 6 of pgpCBC.c
bb29bc pgpCBCGetKeySize( PGPCBCContextRef ref )
a8bb36 {
6c3382 ¤   PGPSize¤keySize;
bb67c5 ¤
894d61 ¤   pgpAssert( pgpCBCIsValid( ref ) );
cf67c5 ¤
f1a328 ¤   PGPGetSymmetricCipherSizes( ref->symmetricRef, &keySize, NULL );
a2ba22 ¤   return( keySize );
d9efe6 }
4baf5a
ffaf5a
cb0335 /*____________________________________________________________________________
a6f7f7 ____________________________________________________________________________*/
2808ca ¤   PGPSize
bf472e pgpCBCGetBlockSize( PGPCBCContextRef ref )
febb36 {
c0fe1c ¤   PGPSize¤blockSize;
fc67c5 ¤
714d61 ¤   pgpAssert( pgpCBCIsValid( ref ) );
0e67c5 ¤
f036b1 ¤   PGPGetSymmetricCipherSizes( ref->symmetricRef, NULL, &blockSize );
73aaae ¤   return( blockSize );
e3efe6 }
a4af5a
1daf5a
2faf5a
46af5a
200335 /*____________________________________________________________________________
cb9d4c ¤   Encrypt a buffer of data blocks, using a block cipher in CBC mode.
77f7f7 ____________________________________________________________________________*/
1c66dd ¤   static PGPError
63f44b pgpCBCEncrypt(
a639e2 ¤   PGPCBCContext *¤¤   ref,
4c8657 ¤   void const *¤   ¤   srcParam,
99f80e ¤   PGPSize¤¤   ¤   ¤   len,
c92b16 ¤   void *¤ ¤   ¤   ¤   destParam )
d7bb36 {
6458a2 ¤   PGPSize¤¤   ¤   blockSize;
21014a ¤   PGPSize¤¤   ¤   bufcnt;
2b34c1 ¤   PGPByte *¤  ¤   bufptr;
bff90a ¤   const PGPByte *¤src = (const PGPByte *) srcParam;
eb3e1a ¤   PGPByte *¤  ¤   dest = (PGPByte *) destParam;
9e67c5 ¤
8a36b1 ¤   PGPGetSymmetricCipherSizes( ref->symmetricRef, NULL, &blockSize );
6b67c5 ¤
0c5acc ¤   /* Length must be a multiple of blocksize */
531708 ¤   if( len % blockSize != 0 )
00c7a1 ¤   {
0e62b5 ¤   ¤   return kPGPError_BadParams;
679371 ¤   }
4eaf5a
f07d3a ¤   while( len != 0 )
3cc7a1 ¤   {
ebc819 ¤   ¤   bufptr¤ ¤   = ref->iv;
710795 ¤   ¤   bufcnt¤ ¤   = blockSize;
52af5a
0bf082 ¤   ¤   /* XOR new data into iv buffer */
b87ce1 ¤   ¤   while( bufcnt-- )
785b34 ¤   ¤   {
2dfd0f ¤   ¤   ¤   *bufptr++ ^= *src++;
ae0fe4 ¤   ¤   }
5eaf5a
47641c ¤   ¤   /* Encrypt IV buffer to itself to form ciphertext */
c038c6 ¤   ¤   bufptr = ref->iv;
1cde1d ¤   ¤   PGPSymmetricCipherEncrypt(ref->symmetricRef, bufptr, bufptr);
9caf5a
e2cfcf ¤   ¤   /* Copy ciphertext to destination buffer */
381f89 ¤   ¤   bufcnt = blockSize;
a77ce1 ¤   ¤   while( bufcnt-- )
085b34 ¤   ¤   {
472dcd ¤   ¤   ¤   *dest++ = *bufptr++;
bc0fe4 ¤   ¤   }
--5de3 000014aecb040100123 Page 7 of pgpCBC.c
e0af5a
c1ded2 ¤   ¤   /* Loop until we have exhausted the data */
a62a3b ¤   ¤   len -= blockSize;
149371 ¤   }
27af5a
9f151e ¤   return kPGPError_NoErr;
87efe6 }
89af5a
eeaf5a
6b0335 /*____________________________________________________________________________
fe0804 ¤   Decrypt a buffer of data blocks, using a block cipher in CBC mode.
74f7f7 ____________________________________________________________________________*/
a666dd ¤   static PGPError
751eda pgpCBCDecrypt(
91e3e0 ¤   PGPCBCContext *¤ref,
6b5f93 ¤   void const *¤   srcParam,
0306cc ¤   PGPSize¤¤   ¤   len,
8a5414 ¤   void *¤ ¤   ¤   destParam )
e4bb36 {
f658a2 ¤   PGPSize¤¤   ¤   blockSize;
fa014a ¤   PGPSize¤¤   ¤   bufcnt;
4934c1 ¤   PGPByte *¤  ¤   bufptr;
8ef90a ¤   const PGPByte *¤src = (const PGPByte *) srcParam;
453e1a ¤   PGPByte *¤  ¤   dest = (PGPByte *) destParam;
e767c5 ¤
8736b1 ¤   PGPGetSymmetricCipherSizes( ref->symmetricRef, NULL, &blockSize );
7c67c5 ¤
165acc ¤   /* Length must be a multiple of blocksize */
c11708 ¤   if( len % blockSize != 0 )
e0c7a1 ¤   {
d462b5 ¤   ¤   return kPGPError_BadParams;
cf9371 ¤   }
21af5a
097d3a ¤   while( len != 0 )
62c7a1 ¤   {
a8f8ff ¤   ¤   PGPByte *¤  altiv;
8baf5a
a67644 ¤   ¤   /* Copy input ciphertext into alternate iv buffer */
c10611 ¤   ¤   altiv¤  ¤   = (ref->iv == ref->iv1) ? ref->iv2 : ref->iv1;
130795 ¤   ¤   bufcnt¤ ¤   = blockSize;
287562 ¤   ¤   bufptr¤ ¤   = altiv;
147ce1 ¤   ¤   while( bufcnt-- )
135b34 ¤   ¤   {
fe434f ¤   ¤   ¤   *bufptr++ = *src++;
7e0fe4 ¤   ¤   }
f2af5a
783244 ¤   ¤   /* Decrypt ciphertext into destination */
c3b142 ¤   ¤   PGPSymmetricCipherDecrypt(ref->symmetricRef, altiv, dest);
5eaf5a
8ef298 ¤   ¤   /* XOR iv into output data to form plaintext */
f70795 ¤   ¤   bufcnt¤ ¤   = blockSize;
03c819 ¤   ¤   bufptr¤ ¤   = ref->iv;
e27ce1 ¤   ¤   while( bufcnt-- )
275b34 ¤   ¤   {
78cab1 ¤   ¤   ¤   *dest++ ^= *bufptr++;
7f0fe4 ¤   ¤   }
62af5a
e5efb1 ¤   ¤   /* Toggle the IV buffers each iteration */
69dea3 ¤   ¤   ref->iv = altiv;
8f1b52 ¤   ¤
cfded2 ¤   ¤   /* Loop until we have exhausted the data */
5b2a3b ¤   ¤   len -= blockSize;
4d9371 ¤   }
73af5a
c9151e ¤   return kPGPError_NoErr;
edefe6 }
16af5a
55af5a
6daf5a
9faf5a
917e4d /*__Editor_settings____
01af5a
--a936 00150c9616f40100123 Page 8 of pgpCBC.c
734126 ¤   Local Variables:
567b17 ¤   tab-width: 4
430e6c ¤   End:
895f8c ¤   vi: ts=4 sw=4
ab9e9b ¤   vim: si
50d062 _____________________*/
--93d1 001447408c840100124 Page 1 of pgpCBCPriv.h
a70335 /*____________________________________________________________________________
a967e7 ¤   pgpCBCPriv.h
af67c5 ¤
f1c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
f64b0f ¤   All rights reserved.
fc67c5 ¤
bbaf5a
05f024 ¤   $Id: pgpCBCPriv.h,v 1.2.22.1 1998/11/12 03:21:18 heller Exp $
c4f7f7 ____________________________________________________________________________*/
a9af5a
4c39e8 #ifndef Included_pgpCBCPriv_h¤  /* [ */
d4ee72 #define Included_pgpCBCPriv_h
7faf5a
e6adb8 #include "pgpOpaqueStructs.h"
a3e603 #include "pgpSymmetricCipher.h"
b513b1 #include "pgpCBC.h"
c1af5a
75af5a
8f99c6 PGP_BEGIN_C_DECLARATIONS
f9af5a
9aaf5a
a7b0d9 #define PGP_CBC_MAXBLOCKSIZE 20
1caf5a
7eaf5a
bbaf5a
b10335 /*____________________________________________________________________________
0099d9 ¤   internal glue routine follow; use is discouraged
e1f7f7 ____________________________________________________________________________*/
a3af5a
425782 PGPSize¤¤   pgpCBCGetKeySize( PGPCBCContextRef ref );
aea9a4 PGPSize¤¤   pgpCBCGetBlockSize( PGPCBCContextRef ref );
18af5a
0daf5a
19af5a
7d1254 PGP_END_C_DECLARATIONS
12af5a
af0dd5 #endif /* ] Included_pgpCBCPriv_h */
81af5a
e2af5a
5b7e4d /*__Editor_settings____
a3af5a
3c4126 ¤   Local Variables:
a77b17 ¤   tab-width: 4
bf0e6c ¤   End:
725f8c ¤   vi: ts=4 sw=4
049e9b ¤   vim: si
44d062 _____________________*/
--7e6d 000e3c28f4f40100125 Page 1 of pgpCFB.c
a70335 /*____________________________________________________________________________
80b942 ¤   pgpCipherFeedback.c
a667c5 ¤
68c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
d04b0f ¤   All rights reserved.
1567c5 ¤
1867c5 ¤
69af5a
9b3eb8 ¤   $Id: pgpCFB.c,v 1.19.12.1 1998/11/12 03:21:19 heller Exp $
0ff7f7 ____________________________________________________________________________*/
1be2ff #include "pgpConfig.h"
5f324c #include <string.h>
d9af5a
b40d08 #include "pgpMem.h"
7f2f8d #include "pgpErrors.h"
49c26c #include "pgpContext.h"
050e2f #include "pgpSymmetricCipherPriv.h"
a71e2d #include "pgpCFBPriv.h"
b25430 #include "pgpUtilitiesPriv.h"
e8af5a
93af5a
05af5a
a4929e #define PGPValidateCFB( cfb )¤  \
6a2063 ¤   PGPValidateParam( pgpCFBIsValid( cfb ) );
e467c5 ¤
a00335 /*____________________________________________________________________________
c22c5d ¤   Some stuff does double duty for CFB encryption/decryption,
651f22 ¤   and for X9.17 random number generation.
1067c5 ¤
08cb27 ¤   For random number generate, it is illegal to attempt to use
779d6b ¤   an interleaved CFB.
84af5a
632a17 ¤   When used for CFB, iv[] is used as a circular buffer. ·bufLeft is
b57702 ¤   the number of bytes at the end which have to be filled in before we
0d83ae ¤   crank the block cipher again. ·We do the block cipher operation
b7fb50 ¤   lazily: bufLeft may be 0. ·When we need one more byte, we
8056ff ¤   crank the block cipher and set bufLeft to 7.
dfaf5a
8e7fd3 ¤   prev[] holds the previous 8 bytes of ciphertext, for use
00522d ¤   by ideaCFBSync() and Phil's, ahem, unique (not insecure, just
b6c0f7 ¤   unusual) way of doing CFB encryption.
6eaf5a
1b59fc ¤   When used for X9.17 random number generation, iv[] holds the V initial
9cd123 ¤   vector, and prev[] holds the R random output. ·bufLeft indicates how
f88138 ¤   much of R is still available before the generator has to be cranked again.
f3f7f7 ____________________________________________________________________________*/
00af5a
70af5a
dc0335 /*____________________________________________________________________________
f872ae ¤   Each interleaved CFB has its own data.
52f7f7 ____________________________________________________________________________*/
b21741 typedef struct
0bbb36 {
63d336 ¤   PGPSymmetricCipherContextRef¤   symmetricRef;
d40a0e ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   ¤   prev[ PGP_CFB_MAXBLOCKSIZE ];
575378 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   ¤   iv[ PGP_CFB_MAXBLOCKSIZE ];
b77069 ¤   /* note bufLeft could actually be in the main structure,
4181a5 ¤   but it's more convenient here */
14f4c4 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   ¤   bufLeft;
fbbe75 } CFBInterleaveStruct;
d1b307 #define kCFBSize¤   ¤   sizeof( CFBInterleaveStruct )
16af5a
76af5a
576979 struct PGPCFBContext
b0bb36 {
7da792 #define kCFBMagic¤  ¤   0xBAABBAAB
34bae3 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   magic;
6916d0 ¤   PGPMemoryMgrRef¤¤   ¤   ¤   ¤   memoryMgr;
310627 ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   interleave;
8c4f9c ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   curCFBIndex;
37e721 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   ¤   bytesInCur;
e3531f ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   cfbInited;
--2a40 000b101cd0c40100125 Page 2 of pgpCFB.c
7f1c9d ¤   CFBInterleaveStruct¤¤   ¤   ¤   cfbData[ 1 ];¤  /* variable */
d982f7 };
b335b6 #define IndCFB( ref, x )¤   (ref)->cfbData[ x ]
bdaf5a
1cbb2e ¤   static PGPSize
568d3d CalcContextSize( PGPUInt16¤ numInterleaves )
f4bb36 {
024c7e ¤   /* one CFBInterleaveStruct is already declared in main struct */
abe70b ¤   return( sizeof( PGPCFBContext ) +
42208f ¤   ¤   numInterleaves * ( kCFBSize - 1 ) );
b7efe6 }
2daf5a
4baf5a
e86c2c ¤   static PGPBoolean
4164cc pgpCFBIsValid( const PGPCFBContext * ref)
60bb36 {
18984c ¤   PGPBoolean¤ valid¤  = FALSE;
8267c5 ¤
935af9 ¤   valid¤  = IsntNull( ref ) && ref->magic¤ == kCFBMagic;
f767c5 ¤
050b09 ¤   return( valid );
46efe6 }
3faf5a
c5af5a
dbaf5a
58283d static void¤¤   pgpCFBSync(CFBInterleaveStruct *cfb);
36af5a
916476 static void¤¤   pgpCFBRandCycle(PGPCFBContext *ref,
653e17 ¤   ¤   ¤   ¤   ¤   void const *salt);
a3ae30 ¤   ¤   ¤   ¤   ¤
4c5434 static void¤¤   pgpCFBRandWash(PGPCFBContext *ref,
3e5708 ¤   ¤   ¤   ¤   ¤   void const *buf, PGPSize len);
7cae30 ¤   ¤   ¤   ¤   ¤
3183a7 static void¤¤   pgpCFBInit( PGPCFBContext *¤ref,
647c9c ¤   ¤   ¤   ¤   ¤   void const * key, void const * iv);
98ae30 ¤   ¤   ¤   ¤   ¤
91beaf static void¤¤   pgpCFBEncrypt( CFBInterleaveStruct *ref,
1d7cfd ¤   ¤   ¤   ¤   ¤   void const * src, PGPSize len, void * dest );
9dae30 ¤   ¤   ¤   ¤   ¤
cbdf3b static void¤¤   pgpCFBDecrypt( CFBInterleaveStruct *ref,
797cfd ¤   ¤   ¤   ¤   ¤   void const * src, PGPSize len, void * dest );
74af5a
b7af5a
526fb2 /* Returns as many bytes as are available before more salt is needed */
a3f8ab static PGPSize ¤pgpCFBRandBytes(PGPCFBContext *ref,
4dac9c ¤   ¤   ¤   ¤   ¤   ¤   PGPSize len, void *dest );
6daf5a
a8af5a
190335 /*____________________________________________________________________________
acf7f7 ____________________________________________________________________________*/
4d21ab ¤   PGPError·
190012 PGPNewCFBContext(
580baf ¤   PGPSymmetricCipherContextRef¤   symmetricRef,
4cdebe ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   interleave,
6635a7 ¤   PGPCFBContextRef *¤ outRef )
4bbb36 {
54673e ¤   PGPCFBContextRef¤   ¤   newRef¤ = NULL;
cff40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
5567c5 ¤
133c76 ¤   PGPValidatePtr( outRef );
a43652 ¤   *outRef¤= NULL;
9affb4 ¤   PGPValidatePtr( symmetricRef );
7f989e ¤   PGPValidateParam( interleave != 0 );
2a67c5 ¤
3fdee1 ¤   newRef¤ = (PGPCFBContextRef)
8d1bac ¤   ¤   ¤   PGPNewData( pgpGetSymmetricCipherMemoryMgr( symmetricRef ),
3effd4 ¤   ¤   ¤   ¤   CalcContextSize( interleave ),
9ad419 ¤   ¤   ¤   ¤   0 | kPGPMemoryMgrFlags_Clear);
6187c7 ¤   ¤   ¤
d76c1a ¤   if ( IsntNull( newRef ) )
20c7a1 ¤   {
b14a5a ¤   ¤   PGPUInt32¤  cfbIndex;
--a210 0008879a7fe40100125 Page 3 of pgpCFB.c
f11b52 ¤   ¤
685c98 #if PGP_DEBUG
eb3b63 ¤   ¤   /* make original invalid to enforce semantics */
48bd54 ¤   ¤   PGPSymmetricCipherContextRef¤   tempRef;
dd12f4 ¤   ¤   err¤= PGPCopySymmetricCipherContext( symmetricRef, &tempRef );
977d98 ¤   ¤   if ( IsntPGPError( err ) )
335b34 ¤   ¤   {
be4127 ¤   ¤   ¤   PGPFreeSymmetricCipherContext( symmetricRef );
df49e4 ¤   ¤   ¤   symmetricRef¤   = tempRef;
9e0fe4 ¤   ¤   }
5fd87c ¤   ¤   err¤= kPGPError_NoErr;
b57454 #endif
65af5a
4199e6 ¤   ¤   newRef->magic¤  ¤   ¤   ¤   ¤   ¤   = kCFBMagic;
089730 ¤   ¤   newRef->interleave¤ ¤   ¤   ¤   ¤   = interleave;¤
58acf0 ¤   ¤   newRef->cfbInited¤  ¤   ¤   ¤   ¤   = FALSE;
925bfc ¤   ¤   IndCFB( newRef, 0 ).symmetricRef¤   = symmetricRef;
1c1b52 ¤   ¤
8ff17b ¤   ¤   newRef->memoryMgr = pgpGetSymmetricCipherMemoryMgr( symmetricRef );
331b52 ¤   ¤
800786 ¤   ¤   /* create a separate symmetric cipher for each cfb */
2244a9 ¤   ¤   for ( cfbIndex = 1; cfbIndex < interleave; ++ cfbIndex )
995b34 ¤   ¤   {
524a69 ¤   ¤   ¤   err¤= PGPCopySymmetricCipherContext( symmetricRef,
5c9a52 ¤   ¤   ¤   ¤   ¤   ¤   &IndCFB( newRef, cfbIndex ).symmetricRef );
078370 ¤   ¤   ¤   if ( IsPGPError( err ) )
d5f776 ¤   ¤   ¤   {
a1f622 ¤   ¤   ¤   ¤   break;
e0a3a6 ¤   ¤   ¤   }
2e0fe4 ¤   ¤   }
f01b52 ¤   ¤
3873d4 ¤   ¤   /* make sure we clean up */
0cbe18 ¤   ¤   if ( IsPGPError( err ) )
a65b34 ¤   ¤   {
117dfb ¤   ¤   ¤   PGPFreeCFBContext( newRef );
0782ad ¤   ¤   ¤   newRef¤ = NULL;
2d0fe4 ¤   ¤   }
4b9371 ¤   }
830e24 ¤   else
67c7a1 ¤   {
e8a810 ¤   ¤   /* we own it, so dispose it */
e7461c ¤   ¤   PGPFreeSymmetricCipherContext( symmetricRef );
7317a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
0c9371 ¤   }
c167c5 ¤
adcdaf ¤   *outRef¤= newRef;
e8deb7 ¤   return( err );
59efe6 }
2caf5a
65af5a
35af5a
6e0335 /*____________________________________________________________________________
a3f7f7 ____________________________________________________________________________*/
4221ab ¤   PGPError·
e6b765 PGPFreeCFBContext( PGPCFBContextRef ref )
9abb36 {
4d9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1f70b7 ¤   PGPUInt32¤  ¤   cfbIndex;
a167c5 ¤
fd8a8d ¤   PGPValidateCFB( ref );
8767c5 ¤
266688 ¤   for( cfbIndex = 0; cfbIndex < ref->interleave; ++cfbIndex )
9bc7a1 ¤   {
1b05ee ¤   ¤   if ( IsntNull( IndCFB( ref, cfbIndex ).symmetricRef ) )
945b34 ¤   ¤   {
10800c ¤   ¤   ¤   PGPFreeSymmetricCipherContext(
a9511f ¤   ¤   ¤   ¤   IndCFB( ref, cfbIndex ).symmetricRef );
37decf ¤   ¤   ¤   IndCFB( ref, cfbIndex ).symmetricRef¤   = NULL;
b30fe4 ¤   ¤   }
289371 ¤   }
3767c5 ¤
884500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
--cd68 0008943185540100125 Page 4 of pgpCFB.c
5afa58 ¤   PGPFreeData( ref );
c667c5 ¤
62deb7 ¤   return( err );
47efe6 }
a0af5a
5baf5a
feaf5a
970335 /*____________________________________________________________________________
10f7f7 ____________________________________________________________________________*/
4a21ab ¤   PGPError·
14a5a2 PGPCopyCFBContext(
71f5de ¤   PGPCFBContextRef¤   inRef,
0935a7 ¤   PGPCFBContextRef *¤ outRef )
ccbb36 {
229981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
7a90e8 ¤   PGPCFBContextRef¤   newRef¤ = NULL;
d567c5 ¤
c33c76 ¤   PGPValidatePtr( outRef );
153652 ¤   *outRef¤= NULL;
92f0dc ¤   PGPValidateCFB( inRef );
5767c5 ¤
5ddee1 ¤   newRef¤ = (PGPCFBContextRef)
df530e ¤   ¤   PGPNewData( inRef->memoryMgr,
3695f6 ¤   ¤   CalcContextSize( inRef->interleave ), 0);
076c1a ¤   if ( IsntNull( newRef ) )
d8c7a1 ¤   {
0c4a5a ¤   ¤   PGPUInt32¤  cfbIndex;
c61b52 ¤   ¤
c15c22 ¤   ¤   *newRef¤¤   = *inRef;
6b1b52 ¤   ¤
104a49 ¤   ¤   /* clear each symmetric cipher in case later allocation fails */
3b3422 ¤   ¤   for ( cfbIndex = 0; cfbIndex < inRef->interleave; ++cfbIndex )
125b34 ¤   ¤   {
ca2bcd ¤   ¤   ¤   IndCFB( newRef, cfbIndex ).symmetricRef¤= NULL;
f40fe4 ¤   ¤   }
7f1b52 ¤   ¤
ce52fa ¤   ¤   /* copy each symmetric cipher */
713422 ¤   ¤   for ( cfbIndex = 0; cfbIndex < inRef->interleave; ++cfbIndex )
ad5b34 ¤   ¤   {
41a457 ¤   ¤   ¤   err¤= PGPCopySymmetricCipherContext(
bfe6d9 ¤   ¤   ¤   ¤   ¤   IndCFB( inRef, cfbIndex ).symmetricRef,
cfa73c ¤   ¤   ¤   ¤   ¤   &IndCFB( newRef, cfbIndex ).symmetricRef );
b28370 ¤   ¤   ¤   if ( IsPGPError( err ) )
00f776 ¤   ¤   ¤   {
9df622 ¤   ¤   ¤   ¤   break;
c6a3a6 ¤   ¤   ¤   }
490fe4 ¤   ¤   }
061b52 ¤   ¤
8dbe18 ¤   ¤   if ( IsPGPError( err ) )
d95b34 ¤   ¤   {
137dfb ¤   ¤   ¤   PGPFreeCFBContext( newRef );
7382ad ¤   ¤   ¤   newRef¤ = NULL;
ab0fe4 ¤   ¤   }
a69371 ¤   }
ba0e24 ¤   else
cbc7a1 ¤   {
e017a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
6d9371 ¤   }
1267c5 ¤
ddcdaf ¤   *outRef¤= newRef;
e4deb7 ¤   return( err );
4defe6 }
7faf5a
f5af5a
07af5a
aa0335 /*____________________________________________________________________________
faf7f7 ____________________________________________________________________________*/
6621ab ¤   PGPError·
b5db9f PGPInitCFB(
6c2a3d ¤   PGPCFBContextRef¤   ref,
998a89 ¤   const void *¤   ¤   key,
89f1f1 ¤   const void *¤   ¤   initializationVector )
--6f5f 000c4672af240100125 Page 5 of pgpCFB.c
2cbb36 {
cd26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
e867c5 ¤
308a8d ¤   PGPValidateCFB( ref );
90057c ¤   /* at least one param must be non-nil */
82db79 ¤   PGPValidateParam( IsntNull( key ) || IsntNull( initializationVector ) );
5b1b52 ¤   ¤
d287e9 ¤   pgpCFBInit( ref, key, initializationVector);
bf67c5 ¤
d9deb7 ¤   return( err );
7cefe6 }
39af5a
b4af5a
c0af5a
a4af5a
3533c8 ¤   static void
98a792 pgpEncryptDecryptInterleaved(
dfc54b ¤   PGPBoolean¤ ¤   ¤   encrypt,
d82a3d ¤   PGPCFBContextRef¤   ref,
0408cf ¤   const void *¤   ¤   in,
61bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
d703bc ¤   void *¤ ¤   ¤   ¤   out )
dbbb36 {
e5caa8 ¤   PGPSize¤¤   ¤   blockSize¤  = pgpCFBGetBlockSize( ref );
d3a59b ¤   PGPUInt16¤  ¤   cfbIndex;
843d3d ¤   PGPSize¤¤   ¤   remaining;
9e6b6c ¤   const PGPByte *¤curIn¤  = (const PGPByte *) in;
670d4a ¤   PGPByte *¤  ¤   curOut¤ = (PGPByte *) out;
2267c5 ¤
2430f6 ¤   cfbIndex¤   = ref->curCFBIndex;
869ff3 ¤   remaining¤  = bytesIn;
b70589 ¤   while ( remaining != 0 )
a6c7a1 ¤   {
8b8660 ¤   ¤   CFBInterleaveStruct *¤  cfb¤= NULL;
05d5ae ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   bytesAvail;
e91b52 ¤   ¤
6190ad ¤   ¤   bytesAvail¤ = blockSize - ref->bytesInCur;
57aa79 ¤   ¤   if ( bytesAvail > remaining )
82de31 ¤   ¤   ¤   bytesAvail¤ = remaining;
861b52 ¤   ¤
c1ae23 ¤   ¤   cfb¤= &IndCFB( ref, cfbIndex );
8fd90c ¤   ¤   if ( encrypt )
eb59e8 ¤   ¤   ¤   pgpCFBEncrypt( cfb, curIn, bytesAvail, curOut);
e00e1d ¤   ¤   else
5586d0 ¤   ¤   ¤   pgpCFBDecrypt( cfb, curIn, bytesAvail, curOut);
211b52 ¤   ¤
dac11e ¤   ¤   ref->bytesInCur¤+= bytesAvail;
d49837 ¤   ¤   curIn¤  ¤   ¤   += bytesAvail;
369c9b ¤   ¤   curOut¤ ¤   ¤   += bytesAvail;
039443 ¤   ¤   remaining¤  ¤   -= bytesAvail;
201b52 ¤   ¤
da2e52 ¤   ¤   /* do we need to go onto the next CFB? */
b0bffa ¤   ¤   pgpAssert( ref->bytesInCur <= blockSize );
10549f ¤   ¤   if ( ref->bytesInCur == blockSize )
eb5b34 ¤   ¤   {
4aedec ¤   ¤   ¤   ++cfbIndex;
71ba5e ¤   ¤   ¤   /* wrap around to first CFB if necessary */
23c19e ¤   ¤   ¤   if ( cfbIndex == ref->interleave )
e5f776 ¤   ¤   ¤   {
83f5b0 ¤   ¤   ¤   ¤   cfbIndex¤   = 0;
aaa3a6 ¤   ¤   ¤   }
5efd2a ¤   ¤   ¤   ref->bytesInCur¤= 0;
210fe4 ¤   ¤   }
119371 ¤   }
8767c5 ¤
83bf43 ¤   ref->curCFBIndex¤   = cfbIndex;
2d67c5 ¤
650979 ¤   (void)encrypt;
a9b148 ¤   (void)ref;
af8a69 ¤   (void)in;
2f048b ¤   (void)bytesIn;
c48af0 ¤   (void)out;
--e897 0000e34ad8040100125 Page 6 of pgpCFB.c
7aefe6 }
46af5a
8eaf5a
bf66dd ¤   static PGPError
d2dccb PGPCFBEncryptDecrupt(
54c54b ¤   PGPBoolean¤ ¤   ¤   encrypt,
092a3d ¤   PGPCFBContextRef¤   ref,
3d08cf ¤   const void *¤   ¤   in,
74bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
ab03bc ¤   void *¤ ¤   ¤   ¤   out )
47bb36 {
f726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5567c5 ¤
39254f ¤   PGPValidatePtr( out );
f28a8d ¤   PGPValidateCFB( ref );
103bf7 ¤   PGPValidatePtr( in );
8ffddc ¤   PGPValidateParam( bytesIn != 0 );
d5af5a
086adf ¤   if ( ref->cfbInited )
4bc7a1 ¤   {
d41feb ¤   ¤   if ( ref->interleave == 1 )
9c5b34 ¤   ¤   {
b0e59d ¤   ¤   ¤   /* keep it most efficient for common case */
eaddab ¤   ¤   ¤   CFBInterleaveStruct *cfb¤   = &IndCFB( ref, 0);
b387c7 ¤   ¤   ¤
313bed ¤   ¤   ¤   if ( encrypt )
539437 ¤   ¤   ¤   ¤   pgpCFBEncrypt( cfb, in, bytesIn, out);
8cbb8c ¤   ¤   ¤   else
87eed1 ¤   ¤   ¤   ¤   pgpCFBDecrypt( cfb, in, bytesIn, out);
cb0fe4 ¤   ¤   }
310e1d ¤   ¤   else
6b5b34 ¤   ¤   {
b41e28 ¤   ¤   ¤   pgpEncryptDecryptInterleaved( encrypt, ref, in, bytesIn, out );
de0fe4 ¤   ¤   }
639371 ¤   }
df0e24 ¤   else
c9c7a1 ¤   {
de3cb2 ¤   ¤   err¤= kPGPError_ImproperInitialization;
599371 ¤   }
fe67c5 ¤
fddeb7 ¤   return( err );
5fefe6 }
ddaf5a
43af5a
0e21ab ¤   PGPError·
c1dbff PGPCFBEncrypt(
1b2a3d ¤   PGPCFBContextRef¤   ref,
8c08cf ¤   const void *¤   ¤   in,
e4bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
ec03bc ¤   void *¤ ¤   ¤   ¤   out )
0abb36 {
cb0cf8 ¤   return( PGPCFBEncryptDecrupt( TRUE, ref, in, bytesIn, out ) );
88efe6 }
51af5a
0eae30 ¤   ¤   ¤   ¤   ¤
7d21ab ¤   PGPError·
78316e PGPCFBDecrypt(
ad2a3d ¤   PGPCFBContextRef¤   ref,
1e08cf ¤   const void *¤   ¤   in,
b1bf9b ¤   PGPSize¤¤   ¤   ¤   bytesIn,
7503bc ¤   void *¤ ¤   ¤   ¤   out )
abbb36 {
2b06f7 ¤   return( PGPCFBEncryptDecrupt( FALSE, ref, in, bytesIn, out ) );
99efe6 }
b1af5a
62af5a
c5af5a
4821ab ¤   PGPError·
a383fe PGPCFBGetSymmetricCipher(
82dc91 ¤   PGPCFBContextRef¤   ¤   ref,
f0386f ¤   PGPSymmetricCipherContextRef *¤ outRef )
0ebb36 {
--e677 0005fd8908340100125 Page 7 of pgpCFB.c
68f40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
198365 ¤   PGPSymmetricCipherContextRef¤   symmetricRef¤   = NULL;
6167c5 ¤
ae3c76 ¤   PGPValidatePtr( outRef );
403652 ¤   *outRef¤= NULL;
b88a8d ¤   PGPValidateCFB( ref );
a7af5a
3c52d6 ¤   symmetricRef¤   = IndCFB( ref, 0).symmetricRef;
1467c5 ¤
995d89 ¤   *outRef¤= symmetricRef;
6fdeb7 ¤   return( err );
43efe6 }
7daf5a
1baf5a
11af5a
55af5a
cf0335 /*____________________________________________________________________________
2ef7f7 ____________________________________________________________________________*/
3721ab ¤   PGPError·
b7de3e PGPCFBSync( PGPCFBContextRef ref )
29bb36 {
e6d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
d867c5 ¤
da8a8d ¤   PGPValidateCFB( ref );
7b67c5 ¤
11d77f ¤   pgpCFBSync( &IndCFB( ref, ref->curCFBIndex ) );
4e67c5 ¤
fedeb7 ¤   return( err );
ddefe6 }
68af5a
dfaf5a
e7af5a
370335 /*____________________________________________________________________________
a0f7f7 ____________________________________________________________________________*/
cd21ab ¤   PGPError·
5daf7a PGPCFBGetRandom(
702a3d ¤   PGPCFBContextRef¤   ref,
27aba1 ¤   PGPSize¤¤   ¤   ¤   requestCount,
e6031e ¤   void *¤ ¤   ¤   ¤   outBytes,
ff05b8 ¤   PGPSize *¤  ¤   ¤   outCount )
a6bb36 {
b926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
dd67c5 ¤
70f638 ¤   PGPValidatePtr( outCount );
60a83c ¤   *outCount¤  = 0;
ab8a8d ¤   PGPValidateCFB( ref );
8e7f20 ¤   PGPValidatePtr( outBytes );
93fe30 ¤   PGPValidateParam( ref->interleave == 1 );
711b52 ¤   ¤
75eb44 ¤   *outCount¤  = pgpCFBRandBytes( ref, requestCount, outBytes);
0267c5 ¤
e1deb7 ¤   return( err );
40efe6 }
60af5a
d2ae30 ¤   ¤   ¤   ¤   ¤
7eae30 ¤   ¤   ¤   ¤   ¤
3b0335 /*____________________________________________________________________________
3ff7f7 ____________________________________________________________________________*/
f121ab ¤   PGPError·
934b1a PGPCFBRandomCycle(
8c2a3d ¤   PGPCFBContextRef¤   ref,
05196d ¤   const void *¤   ¤   salt)
32bb36 {
f526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5067c5 ¤
858a8d ¤   PGPValidateCFB( ref );
05f287 ¤   PGPValidatePtr( salt );
c0fe30 ¤   PGPValidateParam( ref->interleave == 1 );
5e67c5 ¤
1a6ca3 ¤   pgpCFBRandCycle( ref, salt);
0f67c5 ¤
5fdeb7 ¤   return( err );
--ed34 000efa1c22840100125 Page 8 of pgpCFB.c
7aefe6 }
46af5a
7cae30 ¤   ¤   ¤   ¤   ¤
0cae30 ¤   ¤   ¤   ¤   ¤
230335 /*____________________________________________________________________________
90f7f7 ____________________________________________________________________________*/
5b21ab ¤   PGPError·
56be61 PGPCFBRandomWash(
8a2a3d ¤   PGPCFBContextRef¤   ref,
7508cf ¤   const void *¤   ¤   in,
db2947 ¤   PGPSize¤¤   ¤   ¤   bytesIn )
73bb36 {
da26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
f767c5 ¤
3d8a8d ¤   PGPValidateCFB( ref );
0e3bf7 ¤   PGPValidatePtr( in );
2bfe30 ¤   PGPValidateParam( ref->interleave == 1 );
3f67c5 ¤
0cd29b ¤   pgpCFBRandWash( ref, in, bytesIn );
0367c5 ¤
fbdeb7 ¤   return( err );
39efe6 }
3caf5a
91af5a
83af5a
67af5a
8aaf5a
47af5a
4eaf5a
60f66a #if PRAGMA_MARK_SUPPORTED
5d65af #pragma mark --- Internal Routines ---
327454 #endif
37af5a
e9af5a
50af5a
29af5a
55af5a
00af5a
a6af5a
01af5a
e7af5a
2b6d93 ¤   PGPCFBContextRef
3dc6dc pgpCFBCreate(
d16d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
567d09 ¤   PGPCipherVTBL const *¤  vtbl)
b7bb36 {
737075 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤¤   ¤   ¤   = kPGPError_NoErr;
1337b5 ¤   PGPCFBContextRef¤   ¤   newRef¤ ¤   ¤   = NULL;
1c8365 ¤   PGPSymmetricCipherContextRef¤   symmetricRef¤   = NULL;
0e67c5 ¤
1da7af ¤   pgpAssert( vtbl->blocksize <= PGP_CFB_MAXBLOCKSIZE );
499e0c ¤   pgpAssert( PGPMemoryMgrIsValid( memoryMgr ) );
d31b52 ¤   ¤
279e5f ¤   err¤= PGPNewSymmetricCipherContext( memoryMgr,
4e359e ¤   ¤   vtbl->algorithm, vtbl->keysize, &symmetricRef );
88f1e7 ¤   if ( IsntPGPError( err ) )
74c7a1 ¤   {
d2f2b9 ¤   ¤   err¤= PGPNewCFBContext( symmetricRef, 1, &newRef );
28be18 ¤   ¤   if ( IsPGPError( err ) )
945b34 ¤   ¤   {
be4127 ¤   ¤   ¤   PGPFreeSymmetricCipherContext( symmetricRef );
0e6402 ¤   ¤   ¤   symmetricRef¤   = NULL;
ba09b9 ¤   ¤   ¤   pgpAssert( IsNull( newRef ) );
a10fe4 ¤   ¤   }
449371 ¤   }
6d67c5 ¤
81b4c6 ¤   return newRef;
17efe6 }
aeaf5a
afaf5a
b10335 /*____________________________________________________________________________
ef4a35 ¤   Initialize contexts.
--53e7 000da749e6740100125 Page 9 of pgpCFB.c
4bf390 ¤   If key is NULL, the current key is not changed.
e9b2ba ¤   if iv is NULL, the IV is set to all zero.
b7f7f7 ____________________________________________________________________________*/
d533c8 ¤   static void
ba575a pgpCFBInit(
652dcc ¤   PGPCFBContext *¤ref,
fca7bc ¤   void const *¤   key,
f762cc ¤   void const *¤   iv)
c1bb36 {
2158a2 ¤   PGPSize¤¤   ¤   blockSize;
a170b7 ¤   PGPUInt32¤  ¤   cfbIndex;
862f94 ¤   PGPByte const *¤curIV¤  = (const PGPByte *) iv;
2267c5 ¤
7b68a6 ¤   PGPGetSymmetricCipherSizes( IndCFB( ref, 0 ).symmetricRef,
fd328e ¤   ¤   NULL, &blockSize );
7d67c5 ¤
3dc1f0 ¤   for ( cfbIndex = 0; cfbIndex < ref->interleave; ++cfbIndex )
34c7a1 ¤   {
3aad61 ¤   ¤   CFBInterleaveStruct *¤  cfb;
111b52 ¤   ¤
cf6b24 ¤   ¤   cfb¤= &IndCFB( ref, cfbIndex);
cf1b52 ¤   ¤
396853 ¤   ¤   if ( IsntNull( key ) )
b75b34 ¤   ¤   {
55b693 ¤   ¤   ¤   PGPInitSymmetricCipher( cfb->symmetricRef, key );
de0fe4 ¤   ¤   }
ec1b52 ¤   ¤
577871 ¤   ¤   pgpClearMemory( cfb->prev, sizeof( cfb->prev ) ·);
df254f ¤   ¤   pgpClearMemory( cfb->iv, sizeof( cfb->iv ) ·);
4ef15d ¤   ¤   if ( IsntNull( iv ) )
db5b34 ¤   ¤   {
ea85f9 ¤   ¤   ¤   pgpCopyMemory( curIV, &cfb->iv, blockSize );
110287 ¤   ¤   ¤   curIV¤  += blockSize;
ca0fe4 ¤   ¤   }
771b52 ¤   ¤
152eb8 ¤   ¤   cfb->bufLeft¤   = 0;
089371 ¤   }
d467c5 ¤
650c96 ¤   ref->curCFBIndex¤   = 0;
326500 ¤   ref->bytesInCur¤¤   = 0;
a63706 ¤   /* rely on the symmetric cipher to know whether it has been inited */
23cb86 ¤   /* also, iv of NULL is OK, since semantics say that means zeroes */
d1e5f3 ¤   ref->cfbInited¤ ¤   = TRUE;
7fefe6 }
fbaf5a
61af5a
53af5a
d208ca ¤   PGPSize
71d94c pgpCFBGetKeySize( PGPCFBContextRef ref )
b9bb36 {
1f3382 ¤   PGPSize¤keySize;
d167c5 ¤
92bb43 ¤   pgpAssert( pgpCFBIsValid( ref ) );
c467c5 ¤
38d4b1 ¤   PGPGetSymmetricCipherSizes( IndCFB( ref, 0).symmetricRef, &keySize, NULL );
81ba22 ¤   return( keySize );
99efe6 }
29af5a
e008ca ¤   PGPSize
116bae pgpCFBGetBlockSize( PGPCFBContextRef ref )
8cbb36 {
1dfe1c ¤   PGPSize¤blockSize;
4067c5 ¤
c5bb43 ¤   pgpAssert( pgpCFBIsValid( ref ) );
7667c5 ¤
d1ef62 ¤   PGPGetSymmetricCipherSizes( IndCFB( ref, 0).symmetricRef,
f4328e ¤   ¤   NULL, &blockSize );
afaaae ¤   return( blockSize );
e9efe6 }
27af5a
14af5a
daaf5a
--b2c4 0001a79323d40100125 Page 10 of pgpCFB.c
3b6d52 ¤   void
ad2ffd pgpCFBWipe( PGPCFBContextRef¤   ref)
fdbb36 {
38c30e ¤   PGPUInt32¤  cfbIndex;
cc67c5 ¤
252518 ¤   ref->cfbInited¤ ¤   ¤   = FALSE;
c31b52 ¤   ¤
10bb43 ¤   pgpAssert( pgpCFBIsValid( ref ) );
fd67c5 ¤
c3c1f0 ¤   for ( cfbIndex = 0; cfbIndex < ref->interleave; ++cfbIndex )
7ac7a1 ¤   {
d8ad61 ¤   ¤   CFBInterleaveStruct *¤  cfb;
401b52 ¤   ¤
e46b24 ¤   ¤   cfb¤= &IndCFB( ref, cfbIndex);
9f1b52 ¤   ¤
462688 ¤   ¤   PGPWipeSymmetricCipher( cfb->symmetricRef );
ed1b52 ¤   ¤
237871 ¤   ¤   pgpClearMemory( cfb->prev, sizeof( cfb->prev ) ·);
05254f ¤   ¤   pgpClearMemory( cfb->iv, sizeof( cfb->iv ) ·);
f21b52 ¤   ¤
d9c209 ¤   ¤   cfb->bufLeft = 0;
cb9371 ¤   }
8367c5 ¤
840c96 ¤   ref->curCFBIndex¤   = 0;
abefe6 }
9aaf5a
adaf5a
97af5a
630335 /*____________________________________________________________________________
d66b9e ¤   Encrypt a buffer of data, using a block cipher in CFB mode.
c48cff ¤   here are more compact ways of writing this, but this is
9fb6fd ¤   written for speed.
edf7f7 ____________________________________________________________________________*/
7933c8 ¤   static void
c18639 pgpCFBEncrypt(
fd4890 ¤   CFBInterleaveStruct *¤  cfb,
c6dc73 ¤   void const *¤   ¤   ¤   srcParam,
d3668e ¤   PGPSize¤¤   ¤   ¤   ¤   len,
3ed87f ¤   void *¤ ¤   ¤   ¤   ¤   destParam )
ecbb36 {
e058a2 ¤   PGPSize¤¤   ¤   blockSize;
7feeb8 ¤   PGPSize¤¤   ¤   bufLeft¤¤   = cfb->bufLeft;
3134c1 ¤   PGPByte *¤  ¤   bufptr;
c4c05e ¤   const PGPByte *¤src;
47798e ¤   PGPByte *¤  ¤   dest;
c767c5 ¤
0afcec ¤   PGPGetSymmetricCipherSizes( cfb->symmetricRef, NULL, &blockSize );
6d67c5 ¤
d83afe ¤   bufptr¤ = cfb->iv + blockSize - bufLeft;
9060f4 ¤   src¤¤   = (const PGPByte *) srcParam;
2546e4 ¤   dest¤   = (PGPByte *) destParam;
a067c5 ¤
8dd8af ¤   /*
aaad24 ¤   ·* If there are no more bytes to encrypt that there are bytes
3c539b ¤   ·* in the buffer, XOR them in and return.
06a4e3 ¤   ·*/
ba929f ¤   if (len <= bufLeft)
29c7a1 ¤   {
d19227 ¤   ¤   cfb->bufLeft = bufLeft - len;
69d2e4 ¤   ¤   while (len--)
9d5b34 ¤   ¤   {
6d3ad5 ¤   ¤   ¤   *dest++ = *bufptr++ ^= *src++;
b50fe4 ¤   ¤   }
4199bf ¤   ¤   return;
f09371 ¤   }
340e9e ¤   len -= bufLeft;
92edfa ¤   /* Encrypt the first bufLeft (0 to 7) bytes of the input by XOR
60e843 ¤   ·* with the last bufLeft bytes in the iv buffer.
00a4e3 ¤   ·*/
537c8f ¤   while (bufLeft--)
0ec7a1 ¤   {
1a0335 ¤   ¤   *dest++ = (*bufptr++ ^= *src++);
--77df 00002d854d840100125 Page 11 of pgpCFB.c
a19371 ¤   }
330718 ¤   /* Encrypt middle blocks of the input by cranking the cipher,
36c78f ¤   ·* XORing blockSize-byte blocks, and repeating until the len
6a981e ¤   ·* is blockSize or less.
45a4e3 ¤   ·*/
4d5bd5 ¤   while (len > blockSize)
aec7a1 ¤   {
eb6f09 ¤   ¤   bufptr = cfb->iv;
8b494d ¤   ¤   pgpCopyMemory( bufptr, cfb->prev, blockSize);
eabe26 ¤   ¤   PGPSymmetricCipherEncrypt(cfb->symmetricRef, bufptr, bufptr);
b595f0 ¤   ¤   bufLeft = blockSize;
932a3b ¤   ¤   len -= blockSize;
f30c19 ¤   ¤   do
505b34 ¤   ¤   {
57058d ¤   ¤   ¤   *dest++ = (*bufptr++ ^= *src++);
f31114 ¤   ¤   } while (--bufLeft);
009371 ¤   }
967a26 ¤   /* Do the last 1 to blockSize bytes */
a4a8bc ¤   bufptr = cfb->iv;
eee74c ¤   pgpCopyMemory( bufptr, cfb->prev, blockSize);
ffab05 ¤   PGPSymmetricCipherEncrypt(cfb->symmetricRef, bufptr, bufptr);
29dca3 ¤   cfb->bufLeft = blockSize-len;
d79100 ¤   do·
ddc7a1 ¤   {
550335 ¤   ¤   *dest++ = (*bufptr++ ^= *src++);
dbc57e ¤   } while (--len);
ddefe6 }
dcaf5a
ddaf5a
190335 /*____________________________________________________________________________
a0b74c ¤   Decrypt a buffer of data, using a cipher in CFB mode.
02886f ¤   There are more compact ways of writing this, but this is
65b6fd ¤   written for speed.
94f7f7 ____________________________________________________________________________*/
8b33c8 ¤   static void
ba6ca8 pgpCFBDecrypt(
454890 ¤   CFBInterleaveStruct *¤  cfb,
4edc73 ¤   void const *¤   ¤   ¤   srcParam,
b3668e ¤   PGPSize¤¤   ¤   ¤   ¤   len,
b6d87f ¤   void *¤ ¤   ¤   ¤   ¤   destParam )
d5bb36 {
6d58a2 ¤   PGPSize¤¤   ¤   blockSize;
65cdab ¤   PGPSize¤¤   ¤   bufLeft = cfb->bufLeft;
8edb74 ¤   PGPByte *¤  ¤   bufptr¤ = NULL;
daf887 ¤   PGPByte¤¤   ¤   t;
14f90a ¤   const PGPByte *¤src = (const PGPByte *) srcParam;
743e1a ¤   PGPByte *¤  ¤   dest = (PGPByte *) destParam;
7167c5 ¤
ddfcec ¤   PGPGetSymmetricCipherSizes( cfb->symmetricRef, NULL, &blockSize );
79af5a
268035 ¤   bufptr = cfb->iv + (blockSize-bufLeft);
ce929f ¤   if (len <= bufLeft)
31c7a1 ¤   {
729227 ¤   ¤   cfb->bufLeft = bufLeft - len;
67d2e4 ¤   ¤   while (len--)
d25b34 ¤   ¤   {
923c53 ¤   ¤   ¤   t = *bufptr;
1e3cfa ¤   ¤   ¤   *dest++ = t ^ (*bufptr++ = *src++);
580fe4 ¤   ¤   }
e999bf ¤   ¤   return;
a09371 ¤   }
ea0e9e ¤   len -= bufLeft;
177c8f ¤   while (bufLeft--)
21c7a1 ¤   {
5b8d82 ¤   ¤   t = *bufptr;
1d24aa ¤   ¤   *dest++ = t ^ (*bufptr++ = *src++);
e59371 ¤   }
555bd5 ¤   while (len > blockSize)
9dc7a1 ¤   {
b16f09 ¤   ¤   bufptr = cfb->iv;
38eb83 ¤   ¤   pgpCopyMemory( bufptr, cfb->prev, 8);
02be26 ¤   ¤   PGPSymmetricCipherEncrypt(cfb->symmetricRef, bufptr, bufptr);
--4b71 000a00ebd2740100125 Page 12 of pgpCFB.c
2395f0 ¤   ¤   bufLeft = blockSize;
222a3b ¤   ¤   len -= blockSize;
da0c19 ¤   ¤   do
855b34 ¤   ¤   {
9d3c53 ¤   ¤   ¤   t = *bufptr;
023cfa ¤   ¤   ¤   *dest++ = t ^ (*bufptr++ = *src++);
b91114 ¤   ¤   } while (--bufLeft);
379371 ¤   }
74a8bc ¤   bufptr = cfb->iv;
20e74c ¤   pgpCopyMemory( bufptr, cfb->prev, blockSize);
abab05 ¤   PGPSymmetricCipherEncrypt(cfb->symmetricRef, bufptr, bufptr);
65dca3 ¤   cfb->bufLeft = blockSize-len;
59cfa1 ¤   do
ecc7a1 ¤   {
af8d82 ¤   ¤   t = *bufptr;
e224aa ¤   ¤   *dest++ = t ^ (*bufptr++ = *src++);
a8c57e ¤   } while (--len);
f6efe6 }
0daf5a
7d0335 /*____________________________________________________________________________
e7ac25 ¤   Okay, explanation time:
087a94 ¤   Phil invented a unique way of doing CFB that's sensitive to semantic
ad7fab ¤   boundaries within the data being encrypted. ·One way to phrase
5eca40 ¤   CFB en/decryption on an 8-byte block cipher is to say that you XOR
8a22ea ¤   the current 8 bytes with CRYPT(previous 8 bytes of ciphertext).
9713f5 ¤   Normally, you repeat this at 8-byte intervals, but Phil decided to
3a5b10 ¤   resync things on the boundaries between elements in the stream being
ab57fe ¤   encrypted.
4caf5a
8f9dd1 ¤   That is, the last 4 bytes of a 12-byte field are en/decrypted using
2250e4 ¤   the first 4 bytes of CRYPT(previous 8 bytes of ciphertext), but then
ee286a ¤   the last 4 bytes of that CRYPT computation are thrown away, and the
f0ece0 ¤   first 8 bytes of the next field are en/decrypted using
5f775e ¤   CRYPT(last 8 bytes of ciphertext). ·This is equivalent to using a
417aa4 ¤   shorter feedback length (if you're familiar with the general CFB
0b5319 ¤   technique) briefly, and doesn't weaken the cipher any (using shorter
416173 ¤   CFB lengths makes it stronger, actually), it just makes it a bit unusual.
bfaf5a
2c9c69 ¤   Anyway, to accomodate this behaviour, every time we do an
fecf73 ¤   encryption of 8 bytes of ciphertext to get 8 bytes of XOR mask,
82c124 ¤   we remember the ciphertext. ·Then if we have to resync things
b74433 ¤   after having processed, say, 2 bytes, we refill the iv buffer
1ce2de ¤   with the last 6 bytes of the old ciphertext followed by the
0ab351 ¤   2 bytes of new ciphertext stored in the front of the iv buffer.
eaf7f7 ____________________________________________________________________________*/
9533c8 ¤   static void
ac80e6 pgpCFBSync(CFBInterleaveStruct *cfb)
36bb36 {
e0fe1c ¤   PGPSize¤blockSize;
6e038e ¤   PGPSize¤bufLeft¤¤   = cfb->bufLeft;
41af5a
45b86a ¤   (void)PGPGetSymmetricCipherSizes( cfb->symmetricRef, NULL, &blockSize );
e667c5 ¤
3ea02a ¤   if (bufLeft)
a4c7a1 ¤   {
c9f5f9 ¤   ¤   pgpCopyMemory( cfb->iv, cfb->iv + bufLeft, blockSize - bufLeft);
086c67 ¤   ¤   pgpCopyMemory( cfb->prev + blockSize - bufLeft, cfb->iv, bufLeft);
ed2eb8 ¤   ¤   cfb->bufLeft¤   = 0;
2b9371 ¤   }
b9efe6 }
70af5a
750335 /*____________________________________________________________________________
7800c6 ¤   Cryptographically strong pseudo-random-number generator.
7ca7a1 ¤   The design is from Appendix C of ANSI X9.17, "Financial
bab27b ¤   Institution Key Management (Wholesale)", with IDEA
11575b ¤   substituted for triple-DES.
c8d83c ·
1883cb ¤   This generates one block (64 bits) of random number R, based on a
473cc2 ¤   key K, an initial vector V, and a time-dependent salt I. ·I need not
d619d1 ¤   be truly random, but should differ for each block of output R, and
0e16c5 ¤   contain as much entropy as possible. ·In X9.17, I is encrypt(K,time()),
a01b0b ¤   where time() is the most accurate time available. ·This has I supplied
--204b 0005ce46b8940100125 Page 13 of pgpCFB.c
da5cfa ¤   (from the true random number pool, which is based on similar information)
9fb8f8 ¤   to the ideaRandCycle function.
dbaf5a
e1386a ¤   The operation of ideaRandCycle is straight from X9.17::
c959be ¤   R = encrypt(K, V^I)
c811c5 ¤   V = encrypt(K, R^I)
cbaf5a
b850f4 ¤   One thing worth noting is that, given fixed values of K and V,
140483 ¤   there is an isomorphism between values of I and values of R.
c3a976 ¤   Thus, R always contains at least as much entropy as is in I;
63b6d5 ¤   if I is truly completely random, it does not matter if K and/or V
32b4fb ¤   are known. ·Thus, if the supplied I (from the true random number pool)
eb8b90 ¤   are good, the output of this is good.
f4af5a
eaaf5a
eebc22 ¤   Fills in the supplied buffer with up to "count" pseudo-random bytes.
eca30b ¤   Returns the number of bytes filled in. ·If less than "count",
9eda6a ¤   pgpCFBRandCycle will need to be called with a new random salt value
ecd183 ¤   before more bytes are available. ·pgpCFBRandBytes will return 0 until
1deb07 ¤   that is done.
e7f7f7 ____________________________________________________________________________*/
fbaf5a
7abb2e ¤   static PGPSize
e9f10c pgpCFBRandBytes(
492a3d ¤   PGPCFBContextRef¤   ref,
d1b84a ¤   PGPSize¤¤   ¤   ¤   count,
b1e6ef ¤   void *¤ ¤   ¤   ¤   dest )
c0bb36 {
1b8e90 ¤   PGPSize¤¤   ¤   ¤   ¤   bufLeft;
0d9009 ¤   CFBInterleaveStruct *¤  cfb;
84af5a
6832df ¤   pgpAssert( ref->interleave == 1 );
8567c5 ¤
596c72 ¤   cfb¤= &IndCFB( ref, 0 );
da67c5 ¤
d58a3b ¤   bufLeft = cfb->bufLeft;
2267c5 ¤
2961d9 ¤   if (count > bufLeft)
eff6df ¤   ¤   count = bufLeft;
8c1b52 ¤   ¤
880971 ¤   cfb->bufLeft = bufLeft - count;
06bb76 ¤   pgpCopyMemory( cfb->prev + pgpCFBGetBlockSize( ref ) - bufLeft,
dbbc1f ¤   ¤   dest, count);
1c1b52 ¤   ¤
711368 ¤   return count;
3befe6 }
ddaf5a
78af5a
2c0335 /*____________________________________________________________________________
af3d9f ¤   Make more random bytes available from ideaRandBytes using the X9.17
de9bcb ¤   algorithm and the supplied random salt. ·Expects "ref->cipher->blockSize"
8add62 ¤   bytes of salt.
46f7f7 ____________________________________________________________________________*/
6633c8 ¤   static void
62406a pgpCFBRandCycle(
fa2dcc ¤   PGPCFBContext *¤ref,
c7f531 ¤   void const *¤   saltParam)
eabb36 {
f948a1 ¤   PGPSize¤¤   ¤   ¤   ¤   i;
693100 ¤   PGPSize¤¤   ¤   ¤   ¤   blockSize = pgpCFBGetBlockSize( ref );
839009 ¤   CFBInterleaveStruct *¤  cfb;
05e5ef ¤   const PGPByte *¤¤   ¤   salt = (const PGPByte *) saltParam;
9767c5 ¤
5732df ¤   pgpAssert( ref->interleave == 1 );
cc67c5 ¤
2b6c72 ¤   cfb¤= &IndCFB( ref, 0 );
e9af5a
4232df ¤   pgpAssert( ref->interleave == 1 );
6567c5 ¤
e688ff ¤   for (i = 0; i < blockSize; i++)
50c7a1 ¤   {
5c6617 ¤   ¤   cfb->iv[i] ^= salt[i];
--e20f 000f5ec8a5740100125 Page 14 of pgpCFB.c
a19371 ¤   }
9967c5 ¤
8b852b ¤   PGPSymmetricCipherEncrypt( cfb->symmetricRef, cfb->iv, cfb->prev);
df67c5 ¤
ea88ff ¤   for (i = 0; i < blockSize; i++)
c3c7a1 ¤   {
4861d3 ¤   ¤   cfb->iv[i] = cfb->prev[i] ^ salt[i];
079371 ¤   }
9367c5 ¤
90182b ¤   PGPSymmetricCipherEncrypt( cfb->symmetricRef, cfb->iv, cfb->iv);
08ae01 ¤   cfb->bufLeft = blockSize;
14efe6 }
c1af5a
c3af5a
970335 /*____________________________________________________________________________
766bd9 ¤   "Wash" the random number state using an irreversible transformation
7e214f ¤   based on the input buffer and the previous state.
23f7f7 ____________________________________________________________________________*/
d633c8 ¤   static void
a796da pgpCFBRandWash(
5b2a3d ¤   PGPCFBContextRef¤   ref,
a206a1 ¤   void const *¤   ¤   bufParam,
f186b6 ¤   PGPSize¤¤   ¤   ¤   len)
61bb36 {
5059b5 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   ¤   blockSize = pgpCFBGetBlockSize( ref );
63b7a1 ¤   PGPSize ¤   ¤   ¤   ¤   ¤   ¤   i, j;
7cb3de ¤   CFBInterleaveStruct *¤  ¤   ¤   cfb¤= NULL;
f3d336 ¤   PGPSymmetricCipherContextRef¤   symmetricRef;
71e1c5 ¤   const PGPByte *¤¤   ¤   ¤   ¤   buf = (const PGPByte *) bufParam;
6867c5 ¤
c332df ¤   pgpAssert( ref->interleave == 1 );
a167c5 ¤
726c72 ¤   cfb¤= &IndCFB( ref, 0 );
48f619 ¤   symmetricRef¤   = cfb->symmetricRef;
edaf5a
23a62f ¤   /* Wash the key (if supported) */
f24b4f ¤   PGPWashSymmetricCipher( symmetricRef, buf, len);
f6af5a
b6d8af ¤   /*
0c6005 ¤   ·* Wash the IV - a bit ad-hoc, but it works. ··It's
31aa68 ¤   ·* basically a CBC-MAC.
31a4e3 ¤   ·*/
9df534 ¤   for (i = j = 0; i < len; i++)
77c7a1 ¤   {
8018de ¤   ¤   cfb->iv[j] ^= buf[i];
06d2df ¤   ¤   if (++j == blockSize)
0c5b34 ¤   ¤   {
388151 ¤   ¤   ¤   PGPSymmetricCipherEncrypt(symmetricRef, cfb->iv, cfb->iv);
8cd41b ¤   ¤   ¤   j = 0;
e90fe4 ¤   ¤   }
059371 ¤   }
66a73b ¤   /* Pad with typical CBC padding indicating the length */
4d2379 ¤   while (j < blockSize)
94c7a1 ¤   {
adbe57 ¤   ¤   cfb->iv[j++] ^= (PGPByte)len;
b99371 ¤   }
9c67c5 ¤
dedf9b ¤   PGPSymmetricCipherEncrypt( symmetricRef, cfb->iv, cfb->iv);
98af5a
bc8f78 ¤   /* Set to empty */
f805bc ¤   cfb->bufLeft = 0;
58efe6 }
dbaf5a
90af5a
8eaf5a
7eaf5a
2faf5a
16af5a
09af5a
2daf5a
e3af5a
f5af5a
--310d 001a9b2632d40100125 Page 15 of pgpCFB.c
e0af5a
1aaf5a
17af5a
78af5a
32af5a
93af5a
e47e4d /*__Editor_settings____
daaf5a
2a4126 ¤   Local Variables:
627b17 ¤   tab-width: 4
7a0e6c ¤   End:
8a5f8c ¤   vi: ts=4 sw=4
7e9e9b ¤   vim: si
a9d062 _____________________*/
--291e 00198144d3140100126 Page 1 of pgpCFBPriv.h
a70335 /*____________________________________________________________________________
38d9bd ¤   pgpCFBPriv.h
f067c5 ¤
f8c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
cc4b0f ¤   All rights reserved.
3b67c5 ¤
08af5a
2f3720 ¤   $Id: pgpCFBPriv.h,v 1.3.12.1 1998/11/12 03:21:19 heller Exp $
eef7f7 ____________________________________________________________________________*/
e5af5a
839c09 #ifndef Included_pgpCFBPriv_h¤  /* [ */
c25028 #define Included_pgpCFBPriv_h
31af5a
5cadb8 #include "pgpOpaqueStructs.h"
f2e603 #include "pgpSymmetricCipher.h"
a90859 #include "pgpCFB.h"
a7af5a
f1af5a
7399c6 PGP_BEGIN_C_DECLARATIONS
5baf5a
f7af5a
361538 #define PGP_CFB_MAXBLOCKSIZE 20
66af5a
1faf5a
feaf5a
8db257 /* Clear a PGPCFBContext of its sensitive data */
e3674b void ¤  ¤   ¤   ¤   ¤   ¤   ¤   pgpCFBWipe( PGPCFBContextRef ref );
27af5a
5daf5a
19af5a
830335 /*____________________________________________________________________________
8999d9 ¤   internal glue routine follow; use is discouraged
60f7f7 ____________________________________________________________________________*/
b8af5a
88a0fd PGPSize¤¤   pgpCFBGetKeySize( PGPCFBContextRef ref );
512d80 PGPSize¤¤   pgpCFBGetBlockSize( PGPCFBContextRef ref );
10af5a
938657 /* Allocate a new PGPCFBContext structure */
544176 PGPCFBContextRef¤   ¤   pgpCFBCreate( PGPMemoryMgrRef memoryMgr,
062f53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPCipherVTBL const *c );
b4af5a
23af5a
60af5a
e01254 PGP_END_C_DECLARATIONS
f5af5a
105d32 #endif /* ] Included_pgpCFBPriv_h */
32af5a
84af5a
c47e4d /*__Editor_settings____
a9af5a
974126 ¤   Local Variables:
547b17 ¤   tab-width: 4
660e6c ¤   End:
1b5f8c ¤   vi: ts=4 sw=4
3e9e9b ¤   vim: si
98d062 _____________________*/
--a96a 0006ec6543840100127 Page 1 of pgpDES3.c
bc38e5 /*
9e3a01 ·* pgpDES3.c - TripleDES EDE Encryptor
44775e ·*
66ad14 ·* pgpDES3.c 95/09/11 23:29:03 EDT by Richard Outerbridge
e5775e ·*
818592 ·* $Id: pgpDES3.c,v 1.15 1997/10/14 01:48:17 heller Exp $
a3495d ·*/
4bd83c ·
97de7b ··
4b3051 #include "pgpSDKBuildFlags.h"
14af5a
ef254d #ifndef PGP_DES3
74aa68 #error you must define PGP_DES3 one way or the other
b87454 #endif
75af5a
a112cc #if PGP_DES3¤   /* [ */
29af5a
17af5a
9d324c #include <string.h>
62e2ff #include "pgpConfig.h"
5daf5a
f70e2f #include "pgpSymmetricCipherPriv.h"
ff1f0b #include "pgpDES3.h"
930d08 #include "pgpMem.h"
31af5a
2994c0 /* The size of a scheduled DES key */
bc9235 #define DES_KEYWORDS 32
bb355a #define DES_KEYBYTES (sizeof(PGPUInt32)*DES_KEYWORDS)
bcae74 #define DES3_KEYWORDS (3*DES_KEYWORDS)
e8afc0 #define DES3_KEYBYTES (sizeof(PGPUInt32)*DES3_KEYWORDS)
b5af5a
7c898b #define DES3_USERKEYBYTES 24
6baf5a
dc38e5 /*
0de8ab ·* Flags in priv array to record whether key schedule is in encrypt
6f01d2 ·* or decrypt mode
20495d ·*/
c9dfd8 #define DES3_MODE_OFFSET¤   ¤   (DES3_KEYBYTES + DES3_USERKEYBYTES)
d5e44e #define DES3_UNDEFINED_MODE¤¤   0x00
a0020a #define DES3_ENCRYPTION_MODE¤   0x11
ee6004 #define DES3_DECRYPTION_MODE¤   0x22
84af5a
15af5a
1cc741 static PGPUInt32 const bigbyte[24] = {
277cd9 ¤   0x800000L,¤ 0x400000L,¤ 0x200000L, ¤0x100000L,
31c299 ¤   0x80000L,¤  0x40000L,¤  0x20000L,¤  0x10000L,
76366a ¤   0x8000L,¤   0x4000L,¤   0x2000L,¤   0x1000L,
847f78 ¤   0x800L,¤¤   0x400L,¤¤   0x200L,¤¤   0x100L,
861c52 ¤   0x80L,¤ ¤   0x40L,¤ ¤   0x20L,¤ ¤   0x10L,
f21701 ¤   0x8L,¤  ¤   0x4L,¤  ¤   0x2L,¤  ¤   0x1L¤   };
c9af5a
718ccd /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
5baf5a
387c9a static PGPByte const pc1[56] = {
21b1b3 ¤   56, 48, 40, 32, 24, 16, ·8,¤ 0, 57, 49, 41, 33, 25, 17,
af67f5 ¤   ·9, ·1, 58, 50, 42, 34, 26,¤18, 10, ·2, 59, 51, 43, 35,
35451c ¤   62, 54, 46, 38, 30, 22, 14,¤ 6, 61, 53, 45, 37, 29, 21,
d770f5 ¤   13, ·5, 60, 52, 44, 36, 28,¤20, 12, ·4, 27, 19, 11, ·3 };
b1af5a
23886c static PGPByte const totrot[16] = {
907f78 ¤   ·1, ·2, ·4, ·6, ·8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
00af5a
b50f6d static PGPByte const pc2[48] = {
fe118a ¤   13, 16, 10, 23, ·0, ·4,¤ 2, 27, 14, ·5, 20, ·9,
63488f ¤   22, 18, 11, ·3, 25, ·7,¤15, ·6, 26, 19, 12, ·1,
552f2e ¤   40, 51, 30, 36, 46, 54,¤29, 39, 50, 44, 32, 47,
fae56e ¤   43, 48, 38, 55, 33, 52,¤45, 41, 49, 35, 28, 31 };
f9af5a
cf38e5 /*
b1a0aa ·* This is a less-that-brilliant key scheduling routine.
e2669c ·* It could stand optimization some time.
6e775e ·*
--6758 000c1b6816c40100127 Page 2 of pgpDES3.c
e7c70e ·* cookey "cooks" the key into the desired form, from the basic one that
9f99cd ·* has the keys for S-boxes 1 through 8 in adjacent words of the
041cb9 ·* "raw" array. ·I.e. the bits start out like this:
a4e8dd ·* xxxxxxxx111111222222333333444444
8c0b15 ·* xxxxxxxx555555666666777777888888
974905 ·* We actually want the keys to look like this:
e24ef5 ·* 111111xx333333xx555555xx777777xx
d33590 ·* 222222xx444444xx666666xx888888xx
9bdd7b ·* Where the "xx" patterns are set to 01020300 for use by the s-box
81a31c ·* lookup code in the main encrypt loop.
0e495d ·*/
e32978 static void
1978f2 cookey (PGPUInt32 *raw, PGPUInt32 *cooked)
05bb36 {
d44ba4 ¤   int i;
31af5a
43b5fd ¤   for (i = 0; i < 16; i++, raw += 2, cooked += 2) {
76e30f ¤   ¤   cooked[0] ·= (raw[0] & 0x00fc0000L) << 8;
fce77f ¤   ¤   cooked[0] |= (raw[0] & 0x00000fc0L) << 12;
3bcfc7 ¤   ¤   cooked[0] |= (raw[1] & 0x00fc0000L) >> 8;
98fadf ¤   ¤   cooked[0] |= (raw[1] & 0x00000fc0L) >> 4;
d1ea2d ¤   ¤   cooked[0] |= 0x01020300;
394e85 ¤   ¤   cooked[1] ·= (raw[0] & 0x0003f000L) << 14;
e417aa ¤   ¤   cooked[1] |= (raw[0] & 0x0000003fL) << 18;
5481e8 ¤   ¤   cooked[1] |= (raw[1] & 0x0003f000L) >> 2;
d4ad2f ¤   ¤   cooked[1] |= (raw[1] & 0x0000003fL) << 2;
8712ca ¤   ¤   cooked[1] |= 0x01020300;
e09371 ¤   }
16830f ¤   return;
62efe6 }
5b67c5 ¤
bd2978 static void
ae72a7 deskey (PGPByte const *key, int decryptf, PGPUInt32 *outbuf)
36bb36 {
b29f61 ¤   int i, j, l, m, n;
639acd ¤   PGPByte pc1m[56], pcr[56];
80d127 ¤   PGPUInt32 kn[32];
ff67c5 ¤
e98ac4 ¤   for (j = 0; j < 56; j++) {
6ed12e ¤   ¤   l = pc1[j];
9d28f8 ¤   ¤   m = l & 07;
cae95c ¤   ¤   pc1m[j] = ( key[l >> 3] >> (~l & 7) ) & 1;
2b9371 ¤   }
70436b ¤   for (i = 0; i < 16; i++ ) {
aa2096 ¤   ¤   m = (decryptf ? 15-i : i) << 1;
957cd7 ¤   ¤   n = m + 1;
521700 ¤   ¤   kn[m] = kn[n] = 0L;
af27a6 ¤   ¤   for (j = 0; j < 28; j++) {
a5fbbf ¤   ¤   ¤   l = j + totrot[i];
17ac1d ¤   ¤   ¤   if (l >= 28)
43b59d ¤   ¤   ¤   ¤   l -= 28;
8bde0c ¤   ¤   ¤   pcr[j] = pc1m[l];
a90fe4 ¤   ¤   }
b16f95 ¤   ¤   for (j = 28; j < 56; j++) {
3ffbbf ¤   ¤   ¤   l = j + totrot[i];
f1eb27 ¤   ¤   ¤   if (l >= 56)
f9b59d ¤   ¤   ¤   ¤   l -= 28;
1ede0c ¤   ¤   ¤   pcr[j] = pc1m[l];
420fe4 ¤   ¤   }
76fe13 ¤   ¤   for (j = 0; j < 24; j++) {
f13338 ¤   ¤   ¤   if (pcr[pc2[j]])
92bea5 ¤   ¤   ¤   ¤   kn[m] |= bigbyte[j];
a442f1 ¤   ¤   ¤   if (pcr[pc2[j+24]])
46bf9d ¤   ¤   ¤   ¤   kn[n] |= bigbyte[j];
bd0fe4 ¤   ¤   }
d19371 ¤   }
bd228c ¤   cookey(kn, outbuf);
98830f ¤   return;
9defe6 }
e9af5a
ec4810 /* S-boxes 1, 3, 5, 7, plus P permutation, rotated */
c1911d static PGPUInt32 const SP0[512] = {
--caa4 0004555497240100127 Page 3 of pgpDES3.c
11e4cb ¤   0x00404100, 0x00000000, 0x00004000, 0x00404101,
d6ec84 ¤   0x00404001, 0x00004101, 0x00000001, 0x00004000,
fca1e3 ¤   0x00000100, 0x00404100, 0x00404101, 0x00000100,
39a358 ¤   0x00400101, 0x00404001, 0x00400000, 0x00000001,
4ccbe8 ¤   0x00000101, 0x00400100, 0x00400100, 0x00004100,
4ed667 ¤   0x00004100, 0x00404000, 0x00404000, 0x00400101,
6e6d69 ¤   0x00004001, 0x00400001, 0x00400001, 0x00004001,
dd43d8 ¤   0x00000000, 0x00000101, 0x00004101, 0x00400000,
7b7413 ¤   0x00004000, 0x00404101, 0x00000001, 0x00404000,
7bf338 ¤   0x00404100, 0x00400000, 0x00400000, 0x00000100,
7cb8d9 ¤   0x00404001, 0x00004000, 0x00004100, 0x00400001,
3aed10 ¤   0x00000100, 0x00000001, 0x00400101, 0x00004101,
8f0a66 ¤   0x00404101, 0x00004001, 0x00404000, 0x00400101,
8803e0 ¤   0x00400001, 0x00000101, 0x00004101, 0x00404100,
4cd000 ¤   0x00000101, 0x00400100, 0x00400100, 0x00000000,
4aabda ¤   0x00004001, 0x00004100, 0x00000000, 0x00404001,
eeaf5a
ca793a ¤   0x00000082, 0x02008080, 0x00000000, 0x02008002,
4201ae ¤   0x02000080, 0x00000000, 0x00008082, 0x02000080,
ce0e9e ¤   0x00008002, 0x02000002, 0x02000002, 0x00008000,
9c8254 ¤   0x02008082, 0x00008002, 0x02008000, 0x00000082,
33b198 ¤   0x02000000, 0x00000002, 0x02008080, 0x00000080,
52eea4 ¤   0x00008080, 0x02008000, 0x02008002, 0x00008082,
cdae45 ¤   0x02000082, 0x00008080, 0x00008000, 0x02000082,
15685e ¤   0x00000002, 0x02008082, 0x00000080, 0x02000000,
83c2db ¤   0x02008080, 0x02000000, 0x00008002, 0x00000082,
429105 ¤   0x00008000, 0x02008080, 0x02000080, 0x00000000,
61a819 ¤   0x00000080, 0x00008002, 0x02008082, 0x02000080,
6bebd3 ¤   0x02000002, 0x00000080, 0x00000000, 0x02008002,
a15e1c ¤   0x02000082, 0x00008000, 0x02000000, 0x02008082,
77a26f ¤   0x00000002, 0x00008082, 0x00008080, 0x02000002,
d61244 ¤   0x02008000, 0x02000082, 0x00000082, 0x02008000,
7de51f ¤   0x00008082, 0x00000002, 0x02008002, 0x00008080,
6faf5a
6ef32e ¤   0x00000040, 0x00820040, 0x00820000, 0x10800040,
5a116c ¤   0x00020000, 0x00000040, 0x10000000, 0x00820000,
2d3c4e ¤   0x10020040, 0x00020000, 0x00800040, 0x10020040,
aa9246 ¤   0x10800040, 0x10820000, 0x00020040, 0x10000000,
932bf3 ¤   0x00800000, 0x10020000, 0x10020000, 0x00000000,
69808d ¤   0x10000040, 0x10820040, 0x10820040, 0x00800040,
b85f6a ¤   0x10820000, 0x10000040, 0x00000000, 0x10800000,
d31d16 ¤   0x00820040, 0x00800000, 0x10800000, 0x00020040,
005516 ¤   0x00020000, 0x10800040, 0x00000040, 0x00800000,
66d150 ¤   0x10000000, 0x00820000, 0x10800040, 0x10020040,
48335f ¤   0x00800040, 0x10000000, 0x10820000, 0x00820040,
e3e94e ¤   0x10020040, 0x00000040, 0x00800000, 0x10820000,
7192fa ¤   0x10820040, 0x00020040, 0x10800000, 0x10820040,
142644 ¤   0x00820000, 0x00000000, 0x10020000, 0x10800000,
ed8f79 ¤   0x00020040, 0x00800040, 0x10000040, 0x00020000,
ad1cad ¤   0x00000000, 0x10020000, 0x00820040, 0x10000040,
eaaf5a
8a8946 ¤   0x00080000, 0x81080000, 0x81000200, 0x00000000,
ed31a6 ¤   0x00000200, 0x81000200, 0x80080200, 0x01080200,
735e04 ¤   0x81080200, 0x00080000, 0x00000000, 0x81000000,
7bd69e ¤   0x80000000, 0x01000000, 0x81080000, 0x80000200,
54a0ca ¤   0x01000200, 0x80080200, 0x80080000, 0x01000200,
6273a4 ¤   0x81000000, 0x01080000, 0x01080200, 0x80080000,
3259bd ¤   0x01080000, 0x00000200, 0x80000200, 0x81080200,
366f9b ¤   0x00080200, 0x80000000, 0x01000000, 0x00080200,
24002b ¤   0x01000000, 0x00080200, 0x00080000, 0x81000200,
d2449e ¤   0x81000200, 0x81080000, 0x81080000, 0x80000000,
52e96f ¤   0x80080000, 0x01000000, 0x01000200, 0x00080000,
5021ed ¤   0x01080200, 0x80000200, 0x80080200, 0x01080200,
57b145 ¤   0x80000200, 0x81000000, 0x81080200, 0x01080000,
288054 ¤   0x00080200, 0x00000000, 0x80000000, 0x81080200,
46bb62 ¤   0x00000000, 0x80080200, 0x01080000, 0x00000200,
8d44c1 ¤   0x81000000, 0x01000200, 0x00000200, 0x80080000 };
20af5a
0f37c2 /* S-boxes 2, 4, 6, 8, plus P permutation, rotated */
13c48c static PGPUInt32 const SP1[512] = {
884c53 ¤   0x20042008, 0x20002000, 0x00002000, 0x00042008,
45a893 ¤   0x00040000, 0x00000008, 0x20040008, 0x20002008,
--d34f 0000b8d831740100127 Page 4 of pgpDES3.c
78c69b ¤   0x20000008, 0x20042008, 0x20042000, 0x20000000,
71aa0a ¤   0x20002000, 0x00040000, 0x00000008, 0x20040008,
6ddb3a ¤   0x00042000, 0x00040008, 0x20002008, 0x00000000,
00c85d ¤   0x20000000, 0x00002000, 0x00042008, 0x20040000,
8feb5e ¤   0x00040008, 0x20000008, 0x00000000, 0x00042000,
2f7068 ¤   0x00002008, 0x20042000, 0x20040000, 0x00002008,
cbab3b ¤   0x00000000, 0x00042008, 0x20040008, 0x00040000,
88184e ¤   0x20002008, 0x20040000, 0x20042000, 0x00002000,
0db6ab ¤   0x20040000, 0x20002000, 0x00000008, 0x20042008,
90c31c ¤   0x00042008, 0x00000008, 0x00002000, 0x20000000,
927adb ¤   0x00002008, 0x20042000, 0x00040000, 0x20000008,
c26ff5 ¤   0x00040008, 0x20002008, 0x20000008, 0x00040008,
42ca5d ¤   0x00042000, 0x00000000, 0x20002000, 0x00002008,
acae33 ¤   0x20000000, 0x20040008, 0x20042008, 0x00042000,
2aaf5a
b59cf2 ¤   0x40200800, 0x40000820, 0x40000820, 0x00000020,
dd4339 ¤   0x00200820, 0x40200020, 0x40200000, 0x40000800,
a5acae ¤   0x00000000, 0x00200800, 0x00200800, 0x40200820,
c17544 ¤   0x40000020, 0x00000000, 0x00200020, 0x40200000,
16d6de ¤   0x40000000, 0x00000800, 0x00200000, 0x40200800,
79f93d ¤   0x00000020, 0x00200000, 0x40000800, 0x00000820,
b08d91 ¤   0x40200020, 0x40000000, 0x00000820, 0x00200020,
381e57 ¤   0x00000800, 0x00200820, 0x40200820, 0x40000020,
3a06df ¤   0x00200020, 0x40200000, 0x00200800, 0x40200820,
853d74 ¤   0x40000020, 0x00000000, 0x00000000, 0x00200800,
c14ad2 ¤   0x00000820, 0x00200020, 0x40200020, 0x40000000,
6b9cf2 ¤   0x40200800, 0x40000820, 0x40000820, 0x00000020,
938666 ¤   0x40200820, 0x40000020, 0x40000000, 0x00000800,
54663b ¤   0x40200000, 0x40000800, 0x00200820, 0x40200020,
0f940f ¤   0x40000800, 0x00000820, 0x00200000, 0x40200800,
0e4704 ¤   0x00000020, 0x00200000, 0x00000800, 0x00200820,
dfaf5a
d1c215 ¤   0x08000004, 0x08100000, 0x00001000, 0x08101004,
41188c ¤   0x08100000, 0x00000004, 0x08101004, 0x00100000,
1093cd ¤   0x08001000, 0x00101004, 0x00100000, 0x08000004,
9c19e9 ¤   0x00100004, 0x08001000, 0x08000000, 0x00001004,
000ca2 ¤   0x00000000, 0x00100004, 0x08001004, 0x00001000,
a0b84b ¤   0x00101000, 0x08001004, 0x00000004, 0x08100004,
a5b284 ¤   0x08100004, 0x00000000, 0x00101004, 0x08101000,
43606b ¤   0x00001004, 0x00101000, 0x08101000, 0x08000000,
f8c6ab ¤   0x08001000, 0x00000004, 0x08100004, 0x00101000,
555ee9 ¤   0x08101004, 0x00100000, 0x00001004, 0x08000004,
f13a40 ¤   0x00100000, 0x08001000, 0x08000000, 0x00001004,
4b1bcb ¤   0x08000004, 0x08101004, 0x00101000, 0x08100000,
348508 ¤   0x00101004, 0x08101000, 0x00000000, 0x08100004,
a5d47d ¤   0x00000004, 0x00001000, 0x08100000, 0x00101004,
b8aa25 ¤   0x00001000, 0x00100004, 0x08001004, 0x00000000,
553a82 ¤   0x08101000, 0x08000000, 0x00100004, 0x08001004,
38af5a
881e78 ¤   0x04000410, 0x00000400, 0x00010000, 0x04010410,
4c0f98 ¤   0x04000000, 0x04000410, 0x00000010, 0x04000000,
78c2b2 ¤   0x00010010, 0x04010000, 0x04010410, 0x00010400,
fa2af9 ¤   0x04010400, 0x00010410, 0x00000400, 0x00000010,
638179 ¤   0x04010000, 0x04000010, 0x04000400, 0x00000410,
871fac ¤   0x00010400, 0x00010010, 0x04010010, 0x04010400,
89843a ¤   0x00000410, 0x00000000, 0x00000000, 0x04010010,
55bcf9 ¤   0x04000010, 0x04000400, 0x00010410, 0x00010000,
73b194 ¤   0x00010410, 0x00010000, 0x04010400, 0x00000400,
afbf3a ¤   0x00000010, 0x04010010, 0x00000400, 0x00010410,
4dd3e9 ¤   0x04000400, 0x00000010, 0x04000010, 0x04010000,
ba707d ¤   0x04010010, 0x04000000, 0x00010000, 0x04000410,
539db2 ¤   0x00000000, 0x04010410, 0x00010010, 0x04000010,
db0c2b ¤   0x04010000, 0x04000400, 0x04000410, 0x00000000,
a75484 ¤   0x04010410, 0x00010400, 0x00010400, 0x00000410,
17d38c ¤   0x00000410, 0x00010010, 0x04000000, 0x04010400 };
fdaf5a
3e38e5 /*
c0e18d ·* This encryption function is fairly clever in the way it does its
e04dce ·* s-box lookup. ·The S-boxes are indexed by bytes, rather than
825efe ·* words, because that's faster on many machines, and shifting
cd9ee1 ·* everything two bits to do the multiply by 4 is trivial.
0b5d29 ·* Then, the indexing into the various S boxes is done by
--062d 0001d6121ec40100127 Page 5 of pgpDES3.c
09795b ·* adding the appropriate offset bits into the key array, so the
f142e3 ·* addition is done by the XOR with the key rather than having to
b52d43 ·* be done explicitly here.
36495d ·*/
9f2978 static void
673038 des3DES (PGPByte const inblock[8], PGPByte outblock[8], PGPUInt32 const *keys)
10bb36 {
157436 ¤   PGPUInt32 s, t, right, leftt;
a43ee1 ¤   int round, iterate;
3b67c5 ¤
cb8883 ¤   leftt¤  = ((PGPUInt32)inblock[0] << 24)
16ed82 ················| ((PGPUInt32)inblock[1] << 16)
539399 ················| ((PGPUInt32)inblock[2] << 8)
1845b9 ················| ·(PGPUInt32)inblock[3];
f5be78 ¤   right¤  = ((PGPUInt32)inblock[4] << 24)
b55d1e ················| ((PGPUInt32)inblock[5] << 16)
8fac7c ················| ((PGPUInt32)inblock[6] << 8)
2b3755 ················| ·(PGPUInt32)inblock[7];
16af5a
4e4cff ¤   /* Initial permutation IP */
72eccb ¤   t = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
f75de4 ¤   right ^= t;
2257eb ¤   leftt ^= (t << 4);
d94543 ¤   t = ((leftt >> 16) ^ right) & 0x0000ffffL;
d05de4 ¤   right ^= t;
843e8b ¤   leftt ^= (t << 16);
6bb0cb ¤   t = ((right >> 2) ^ leftt) & 0x33333333L;
f6347e ¤   leftt ^= t;
186430 ¤   right ^= (t << 2);
349280 ¤   t = ((right >> 8) ^ leftt) & 0x00ff00ffL;
b0347e ¤   leftt ^= t;
f4b89e ¤   right ^= (t << 8);
1970b6 ¤   leftt = ((leftt >> 1) | (leftt << 31));
3e4a26 ¤   t = (leftt ^ right) & 0x55555555L;
cb347e ¤   leftt ^= t;
4e5de4 ¤   right ^= t;
4c60be ¤   right = ((right >> 1) | (right << 31));
0baf5a
45d42f ¤   /* The main encryption loop */
1bd468 ¤   iterate = 3;
b8ff36 ¤   goto Des0;
7e43ab ¤   do {
3aeb33 ¤   ¤   t = right;
f1c7a1 ¤   ¤   right = leftt;
29c6bb ¤   ¤   leftt = t;
15ed9a Des0:¤
7072c6 ¤   ¤   for (round = 0; round < 8; round++) {
7a8e5d ¤   ¤   ¤   s ·= (right & 0xfcfcfcfc) ^ keys[0];
d80584 ¤   ¤   ¤   t ·= (((right >> 28) | (right << 4)) & 0xfcfcfcfc)
7785cc ¤   ¤   ¤   ¤   ^ keys[1];
536817 ¤   ¤   ¤   leftt ^= *(PGPUInt32 *)((char *)SP0+( s ·······& 0x3fc))
f1dfbe ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP0+((s >> 8 ) & 0x3fc))
630909 ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP0+((s >> 16) & 0x3fc))
988d10 ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP0+((s >> 24) & 0x0fc))
86540f ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+( t ·······& 0x3fc))
46b6bb ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+((t >> 8 ) & 0x3fc))
ec600c ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+((t >> 16) & 0x3fc))
d647e8 ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+((t >> 24) & 0x0fc));
82af5a
23877e ¤   ¤   ¤   s ·= (leftt & 0xfcfcfcfc) ^ keys[2];
8a7f3e ¤   ¤   ¤   t ·= (((leftt >> 28) | (leftt << 4)) & 0xfcfcfcfc)
5ebcba ¤   ¤   ¤   ¤   ^ keys[3];
4d323a ¤   ¤   ¤   right ^= *(PGPUInt32 *)((char *)SP0+( s ·······& 0x3fc))
9fdfbe ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP0+((s >> 8 ) & 0x3fc))
760909 ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP0+((s >> 16) & 0x3fc))
e18d10 ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP0+((s >> 24) & 0x0fc))
69540f ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+( t ·······& 0x3fc))
ccb6bb ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+((t >> 8 ) & 0x3fc))
40600c ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+((t >> 16) & 0x3fc))
0447e8 ¤   ¤   ¤   ·······^ *(PGPUInt32 *)((char *)SP1+((t >> 24) & 0x0fc));
979eec ¤   ¤   ¤   keys += 4;
1d0fe4 ¤   ¤   }
--c234 000f8eab82540100127 Page 6 of pgpDES3.c
93c231 ¤   } while (--iterate);
e8af5a
2c56a5 ¤   /* Inverse IP */
864d28 ¤   leftt = ((leftt << 1) | (leftt >> 31));
6c4a26 ¤   t = (leftt ^ right) & 0x55555555L;
15347e ¤   leftt ^= t;
795de4 ¤   right ^= t;
dd5d20 ¤   right = ((right << 1) | (right >> 31));
b9efea ¤   t = ((leftt >> 8) ^ right) & 0x00ff00ffL;
495de4 ¤   right ^= t;
80c0df ¤   leftt ^= (t << 8);
c3cda1 ¤   t = ((leftt >> 2) ^ right) & 0x33333333L;
ff5de4 ¤   right ^= t;
c81c71 ¤   leftt ^= (t << 2);
cba7da ¤   t = ((right >> 16) ^ leftt) & 0x0000ffffL;
c0347e ¤   leftt ^= t;
3b6d7e ¤   right ^= (t << 16);
4691a1 ¤   t = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
d0347e ¤   leftt ^= t;
6d2faa ¤   right ^= (t << 4);
a9af5a
f86498 ¤   outblock[0] = (PGPByte)(right >> 24);
03b913 ¤   outblock[1] = (PGPByte)(right >> 16);
9ba5de ¤   outblock[2] = (PGPByte)(right >> ·8);
cc387e ¤   outblock[3] = (PGPByte)(right ·····);
628285 ¤   outblock[4] = (PGPByte)(leftt >> 24);
805f0e ¤   outblock[5] = (PGPByte)(leftt >> 16);
b943c3 ¤   outblock[6] = (PGPByte)(leftt >> ·8);
6ede63 ¤   outblock[7] = (PGPByte)(leftt ·····);
5d830f ¤   return;
5eefe6 }
ffaf5a
07a91d /*** Externally called functions ***/
62af5a
872978 static void
9a559f des3Key (void *priv, void const *key)
a0bb36 {
22b63d ¤   /* Do key schedule at encrypt/decrypt time; just store key for now */
d3941d ¤   *((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_UNDEFINED_MODE;
29e3b9 ¤   /* Keep a copy of the unscheduled key for Washing purposes */
cae96a ¤   memcpy ((PGPByte *)priv + DES3_KEYBYTES, key, DES3_USERKEYBYTES);
48efe6 }
a0af5a
712978 static void
f177e6 scheduleKey (void *priv, PGPUInt32 mode)
11bb36 {
a8c7a4 ¤   if (mode == DES3_ENCRYPTION_MODE) {
d92b45 ¤   ¤   if (*((PGPByte *)priv + DES3_MODE_OFFSET) != DES3_ENCRYPTION_MODE) {
c13844 ¤   ¤   ¤   /* EDE triple-DES */
d95957 ¤   ¤   ¤   PGPByte *key = (PGPByte *)priv + DES3_KEYBYTES;
a3d6ba ¤   ¤   ¤   deskey (key ··, 0, (PGPUInt32 *)priv);
b00689 ¤   ¤   ¤   deskey (key+ 8, 1, (PGPUInt32 *)priv + DES_KEYWORDS);
d13d44 ¤   ¤   ¤   deskey (key+16, 0, (PGPUInt32 *)priv + 2*DES_KEYWORDS);
deee6b ¤   ¤   ¤   *((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_ENCRYPTION_MODE;
140fe4 ¤   ¤   }
d0f037 ¤   } else {
0f7e89 #if !UNITTEST
b81d2c ¤   ¤   pgpAssert (mode == DES3_DECRYPTION_MODE);
c37454 #endif
62467b ¤   ¤   if (*((PGPByte *)priv + DES3_MODE_OFFSET) != DES3_DECRYPTION_MODE) {
213844 ¤   ¤   ¤   /* EDE triple-DES */
deb30b ¤   ¤   ¤   /* To decrypt, do DED with the keys in the opposite order */
115957 ¤   ¤   ¤   PGPByte *key = (PGPByte *)priv + DES3_KEYBYTES;
e68dba ¤   ¤   ¤   deskey (key+16, 1, (PGPUInt32 *)priv);
1bac41 ¤   ¤   ¤   deskey (key+ 8, 0, (PGPUInt32 *)priv + DES_KEYWORDS);
d6c02b ¤   ¤   ¤   deskey (key ··, 1, (PGPUInt32 *)priv + 2*DES_KEYWORDS);
aa3481 ¤   ¤   ¤   *((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_DECRYPTION_MODE;
7a0fe4 ¤   ¤   }
fb9371 ¤   }
61efe6 }
64af5a
f82978 static void
--b5ac 00009ac0c1840100127 Page 7 of pgpDES3.c
50e8ab des3Encrypt (void *priv, void const *in, void *out)
93bb36 {
060d0a ¤   /* Make sure key schedule is in the right mode */
7eb207 ¤   scheduleKey (priv, DES3_ENCRYPTION_MODE);
1ba283 ¤   des3DES ((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 const *)priv);
a2efe6 }
e9af5a
a22978 static void
e19be8 des3Decrypt (void *priv, void const *in, void *out)
ccbb36 {
e70d0a ¤   /* Make sure key schedule is in the right mode */
0cfa89 ¤   scheduleKey (priv, DES3_DECRYPTION_MODE);
56a283 ¤   des3DES ((const PGPByte *) in, (PGPByte *) out, (PGPUInt32 const *)priv);
99efe6 }
9daf5a
0f38e5 /*
ee9dd9 ·* Do one 64-bit step of a Triple Tandem Davies-Meyer hash computation.
0af1a8 ·* The hash buffer is 32 bytes long and contains H (0..7), then G (8..15),
8049c7 ·* then F (16..23), then 8 bytes of scratch space. ·The buf is 8 bytes long.
0a432c ·* xkey is a temporary key schedule buffer, with room for *4* DES
aa7625 ·* keys, i.e. 4*DESKEYWORDS words.
7b3a09 ·* This and the extra data in the hash buffer are allocated by the
f02186 ·* caller to reduce the amount of buffer-wiping we have to do.
bd5369 ·* (It's only called from des3Wash, so the interface can be a bit
ce5ff5 ·* specialized.)
97775e ·*
09a31a ·* What is triple Tandem Davies-Meyer? ·Well, it's a simple
e81e68 ·* extension of (double) Tandem Davies-Meyer, which goes
865581 ·* like this, to hash (H,G) with message block M:
bc6131 ·* H' = E_{G,M}(H)
aed447 ·* G' = E_{M,H'}(G)
15bff7 ·* H ^= H'
654482 ·* G ^= G'
91775e ·*
e54371 ·* The extension, to a triple-width hash (H,G,F) is just:
a4afac ·* H' = E_{F,G,M}(H)
753170 ·* G' = E_{F,M,H'}(G)
960e5f ·* F' = E_(M,G',H'}(F)
1cbff7 ·* H ^= H'
094482 ·* G ^= G'
0f9fe1 ·* F ^= F'
c7775e ·*
ff5d0f ·* This schedules individual DES keys to avoid having to copy the
fb234e ·* bits to contiguous buffers and to re-use the already-scheduled
d11b40 ·* leys. ·F and H' are used twice in the same spot, and M is scheduled
cb07b6 ·* twice for encryption.
54495d ·*/
fd2978 static void
f16c09 des3StepTripleDM(PGPByte *hash, PGPByte const *buf, PGPUInt32 *xkey)
a0bb36 {
104ba4 ¤   int i;
0faf5a
6f56b4 ¤   /* Set up triple-DES with F, G, M */
0a2432 ¤   deskey(hash+16, 0, xkey);
2f68c8 ¤   deskey(hash+ 8, 1, xkey + DES_KEYWORDS);
295748 ¤   deskey(buf, ····0, xkey + 2*DES_KEYWORDS);
40af5a
ff022f ¤   /* Compute H' and new H */
b0edb5 ¤   des3DES(hash, hash+24, xkey);
1e33e2 ¤   for (i = 0; i < 8; i++)
60575f ¤   ¤   hash[i] ^= hash[i+24];
b0d50e ¤   /* Copy encryption schedule for M out of harm's way */
aabf8f ¤   memcpy(xkey +3*DES_KEYWORDS, xkey+2*DES_KEYWORDS, DES_KEYBYTES);
42af5a
4d2450 ¤   /* Set up triple-DES with F, M, H' */
560581 ¤   deskey(buf, ····1, xkey + DES_KEYWORDS);
344365 ¤   deskey(hash+24, 0, xkey + 2*DES_KEYWORDS);
20af5a
128a54 ¤   /* Compute G' and new G */
2ad507 ¤   des3DES(hash+8, hash+24, xkey);
6e33e2 ¤   for (i = 0; i < 8; i++)
0975cb ¤   ¤   hash[i+8] ^= hash[i+24];
--f0f0 00049b4ac0340100127 Page 8 of pgpDES3.c
e0af5a
ce35b9 ¤   /* Set up triple-DES with M, G', H' */
f8f030 ¤   memcpy(xkey, xkey+3*DES_KEYWORDS, DES_KEYBYTES);
0e1989 ¤   deskey(hash+24, 1, xkey + DES_KEYWORDS);
e4af5a
830f00 ¤   /* Compute F' and new F */
479021 ¤   des3DES(hash+16, hash+24, xkey);
df33e2 ¤   for (i = 0; i < 8; i++)
5c3bf7 ¤   ¤   hash[i+16] ^= hash[i+24];
51efe6 }
6caf5a
e738e5 /*
89dc2f ·* Munge the key of the CipherContext based on the supplied bytes.
f86a26 ·* This is for random-number generation, so the exact technique is
32572d ·* unimportant, but it happens to use the current key as the
7714b6 ·* IV for computing a triple-Tandem Davies-Meyer hash of the bytes,
7f2d54 ·* and uses the output as the new key.
49495d ·*/
b62978 static void
eaf6b5 des3Wash(void *priv, void const *bufIn, PGPSize len)
b2bb36 {
ce9d7e ¤   PGPSize ¤   i;
0894ea ¤   PGPByte ¤   temp[8];
c8a30c ¤   PGPUInt32 ¤ xkey[4*DES_KEYWORDS];
e9cd75 ¤   PGPByte¤¤   *buf = (PGPByte *) bufIn;
1b67c5 ¤
d5d93d ¤   /* The key is used as the IV for the hash */
fbaf5a
db4c63 ¤   /* Do the initial blocks of the hash */
8c21f7 ¤   i = len;
25ac52 ¤   while (i >= 8) {
461485 ¤   ¤   des3StepTripleDM((PGPByte *)priv+DES3_KEYBYTES, buf, xkey);
218f1d ¤   ¤   buf += 8;
8e1544 ¤   ¤   i -= 8;
cc9371 ¤   }
d1d8af ¤   /*
8b22a9 ¤   ·* At the end, we do Damgard-Merkle strengthening, just like
c5deb8 ¤   ·* MD5 or SHA. ·Pad with 0x80 then 0 bytes to 6 mod 8, then
0c9725 ¤   ·* add the length. ·We use a 16-bit length in bytes instead
b2ed88 ¤   ·* of a 64-bit length in bits, but that is cryptographically
56a235 ¤   ·* irrelevant, as long as the length is there.
eca4e3 ¤   ·*/
0d8210 ¤   /* Do the first partial block - i <= 7 */
d1ef01 ¤   memcpy(temp, buf, i);
1cc386 ¤   temp[i++] = 0x80;
8a764c ¤   if (i > 6) {
ae86a7 ¤   ¤   pgpClearMemory(temp+i, 8-i);
a4c8a6 ¤   ¤   des3StepTripleDM((PGPByte *)priv+DES3_KEYBYTES, temp, xkey);
cd9ed6 ¤   ¤   i = 0;
589371 ¤   }
28826d ¤   pgpClearMemory(temp+i, 6-i);
00f532 ¤   temp[6] = (PGPByte)(len >> 8);
b3106e ¤   temp[7] = (PGPByte)len;
6c42e3 ¤   des3StepTripleDM((PGPByte *)priv+DES3_KEYBYTES, temp, xkey);
38af5a
a409a6 ¤   /* Re-schedule the key */
9c941d ¤   *((PGPByte *)priv + DES3_MODE_OFFSET) = DES3_UNDEFINED_MODE;
5cb207 ¤   scheduleKey (priv, DES3_ENCRYPTION_MODE);
65af5a
85a881 ¤   pgpClearMemory( temp, ·sizeof(temp));
5d519f ¤   pgpClearMemory( xkey, ·sizeof(xkey));
9defe6 }
46af5a
6f38e5 /*
e3dd19 ·* Define a Cipher for the generic cipher. ·This is the only real
3ec09c ·* exported symbol -- everything else can be static, since everything
62b83b ·* is referenced through function pointers!
15495d ·*/
3647b5 PGPCipherVTBL const cipher3DES = {
546c21 ¤   "3DES",
c0f7f6 ¤   kPGPCipherAlgorithm_3DES,
49f346 ¤   8,¤ ¤   ¤   /* Blocksize */
--0621 000d1451a4b40100127 Page 9 of pgpDES3.c
f83b1c ¤   DES3_USERKEYBYTES,¤ /* Keysize */
99808f ¤   DES3_KEYBYTES + DES3_USERKEYBYTES + 1,
d73cdd ¤   alignof(PGPUInt32),
46501b ¤   des3Key,
574db9 ¤   des3Encrypt,
aba728 ¤   des3Decrypt,
8ab3fb ¤   des3Wash
c182f7 };
93af5a
66814a #if UNITTEST
004336 /* Validation set:
df775e ·*
8d0e17 ·* Double-length key, single-length plaintext -
4ba8e9 ·* Key ···: 0123 4567 89ab cdef fedc ba98 7654 3210
348da6 ·* Plain ·: 0123 4567 89ab cde7
ffdf12 ·* Cipher : 7f1d 0a77 826b 8aff
a5775e ·*
1ed68a ·***************************************************/
eeaf5a
45feb2 #include <stdio.h>
ea0a8b #include <time.h>
aeaf5a
672978 static void
048ce9 printhex(unsigned char const *buf, unsigned len)
19bb36 {
0fcae5 ¤   while (len--) {
a9f57e ¤   ¤   printf("%02X", *buf++);
1f167e ¤   ¤   putchar(len ? ' ' : '\n');
f29371 ¤   }
59efe6 }
b3af5a
624d2f int
107f68 main(void)
0ebb36 {
e7743f ¤   unsigned i;
a14578 ¤   clock_t c;
1caf5a
5d6bb1 ¤   static unsigned char const key[24] = {
3035f2 ¤   ¤   0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
4f343c ¤   ¤   0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
8e154a ¤   ¤   0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
d062bd ¤   };
804a53 ¤   static unsigned char const plain[8] = {
59df65 ¤   ¤   0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7
9c62bd ¤   };
a5aac6 ¤   static unsigned char const cipher[8] = {
c58509 ¤   ¤   0x7f, 0x1d, 0x0a, 0x77, 0x82, 0x6b, 0x8a, 0xff
8c62bd ¤   };
414090 ¤   unsigned char out[8];
46af5a
4ad5e6 ¤   PGPByte priv[DES3_KEYBYTES + DES3_USERKEYBYTES + 1];
58af5a
c7c256 ¤   des3Key(priv, key);
51675e ¤   des3Encrypt(priv, plain, out);
db1a40 ¤   printf(" ··key=");
8ebf66 ¤   printhex(key, 24);
cd90fd ¤   printf(" plain=");
ad4e61 ¤   printhex(plain, 8);
2e8c88 ¤   printf(" ··out=");
d3d7ad ¤   printhex(out, 8);
a7e571 ¤   printf("cipher=");
443bba ¤   printhex(cipher, 8);
336e28 ¤   if (memcmp(cipher, out, 8) == 0)
4ce282 ¤   ¤   printf("Encryption successful\n");
710e24 ¤   else
36b7fd ¤   ¤   printf("### ENCRYPTION ERROR\n");
d8af5a
02b648 ¤   des3Decrypt(priv, cipher, out);
cde571 ¤   printf("cipher=");
643bba ¤   printhex(cipher, 8);
608c88 ¤   printf(" ··out=");
d1d7ad ¤   printhex(out, 8);
--3fbf 0014cdfe5b240100127 Page 10 of pgpDES3.c
1490fd ¤   printf(" plain=");
e14e61 ¤   printhex(plain, 8);
8d42d2 ¤   if (memcmp(plain, out, 8) == 0)
3ab5cd ¤   ¤   printf("Decryption successful\n");
d00e24 ¤   else
28f465 ¤   ¤   printf("### DECRYPTION ERROR\n");
c2af5a
5a28f2 ¤   printf("Doing test encryptions\n");
c63911 ¤   c = clock();
4b0cd8 ¤   for (i = 0; i < 100000; i++)
34a6af ¤   ¤   des3Encrypt(priv, out, out);
c86258 ¤   c = clock() - c;
f43d44 ¤   printf("%u encryptions required %lu ticks\n",
2dd538 ¤   ¤   i, (unsigned long)c);
eb3e6b ¤   return 0;
efefe6 }
4faf5a
327454 #endif
5eaf5a
8d2f28 #endif /* ] PGP_DES3 */
b7af5a
85af5a
efaf5a
497e4d /*__Editor_settings____
a2af5a
a24126 ¤   Local Variables:
257b17 ¤   tab-width: 4
d40e6c ¤   End:
9d5f8c ¤   vi: ts=4 sw=4
1b9e9b ¤   vim: si
4cd062 _____________________*/
--40c3 001e875660740100128 Page 1 of pgpDES3.h
fa802e /* pgpDES3.h - headers for TripleDES
15775e ·*
89a9d3 ·*¤ By Richard Outerbridge
58775e ·*
9be39d ·* This is a PRIVATE header file, for use only within the PGP Library.
7d2979 ·* You should not be using these functions in an application.
34775e ·*
1b7ab4 ·* $Id: pgpDES3.h,v 1.6 1997/06/13 01:52:57 lloyd Exp $
6a495d ·*/
57af5a
151bc0 #ifndef Included_pgpDES3_h
727fb6 #define Included_pgpDES3_h
dbaf5a
b50e2f #include "pgpSymmetricCipherPriv.h"
f3af5a
be99c6 PGP_BEGIN_C_DECLARATIONS
2baf5a
f829b6 /* This is the definition of the 3DES cipher, for use with the PGP
6a7208 ·* Generic Cipher code.
be495d ·*/
5bcd71 extern PGPCipherVTBL const cipher3DES;
38af5a
5b1254 PGP_END_C_DECLARATIONS
b7af5a
e8b6e9 #endif /* Included_pgpDES3_h */
--d195 000f50733f240100129 Page 1 of pgpDES3_68K.c
bc38e5 /*
4f486d ·* $Id: pgpDES3_68K.c,v 1.2 1997/05/09 20:19:43 lloyd Exp $
a3495d ·*/
cdaf5a
74bea3 #include <stdlib.h>
c6af5a
bcae9a #include "PGPFoneUtils.h"
411f0b #include "pgpDES3.h"
d0af5a
b8e5a1 static void deskey(uchar *, short, ulong *);
a6af5a
877204 static asm void deskey(uchar *key, short edf, ulong *buf)
5fbb36 {
f68af2 ····fralloc +
66714b ····movem.l d3-d5/a2-a3,-(a7) ···//save registers
c10ddd ····lea ····@kpp,a2 ·············//table of permutation adjusts
9c9b72 ····lea ····@kp0,a0 ·············//tables of PGPByte/bit offsets
34a236 ····movea.l key,a1 ··············//load address of nominal key
9b3d30 ····moveq ··#0,d4 ···············//clear this register
d2033a ····moveq ··#15,d0 ··············//do all 16 rounds
0eb8a9 ····movea.l buf,a3 ··············//load address of key register
3775fb ····cmpi.w ·#EN0,edf ············//are we encrypting
3aeba4 ····beq ····@cks1 ···············//yes - start now
e32568 ····lea ····120(a3),a3 ··········//no - adjust backfill
b48493 ····bra ····@cks1 ···············//now start
c8da9b @kpp:
346d90 ····dc.w ···0,0,0,112,112,112,112,112,224,0,112,112,112,112,112,224
41dced @kp0:
61ac11 ····dc.b ···6,6,1,6,6,5,4,6,7,4,6,7,2,7,1,5,0,5,4,5,3,6,3,7,5,4,7,6
fd406e ····dc.b ···0,1,2,2,3,4,4,1,6,2,4,3,0,4,0,2,7,3,2,3,4,2,7,1,1,1,2,4
1f7cab ····dc.b ···5,5,4,7,7,7,0,6,1,7,2,5,5,6,6,4,7,5,0,7,4,4,3,5,2,6,5,7
83c082 ····dc.b ···5,2,5,1,3,2,0,3,6,3,2,1,3,3,1,4,5,3,1,2,1,3,7,2,6,1,3,1
e8869e ····
24844b ····dc.b ···4,0,4,3,4,6,1,3,5,6,5,0,4,2,1,5,0,2,5,2,5,1,0,0,5,3,0,6
00711c ····dc.b ···7,2,7,4,3,0,7,0,6,6,6,0,3,2,3,5,6,2,7,3,6,4,7,1,2,6,7,6
be8c6e ····dc.b ···1,4,1,2,0,1,5,5,5,4,1,6,0,3,1,1,0,4,1,0,4,4,4,1,0,5,4,5
6dd897 ····dc.b ···3,3,2,3,2,5,2,4,7,5,3,1,3,4,2,0,2,1,3,6,6,3,2,2,6,5,6,1
2e869e ····
076d77 ····dc.b ···0,3,5,5,1,4,5,1,1,1,4,5,5,4,0,2,5,6,4,1,0,5,4,2,4,4,4,0
aa83eb ····dc.b ···2,2,3,6,7,6,6,1,3,3,3,4,7,1,6,2,7,5,6,3,2,5,6,5,7,2,2,0
b27d58 ····dc.b ···5,2,0,0,5,0,0,4,1,0,1,5,1,3,5,3,4,6,0,6,0,1,1,6,4,3,1,2
1b58b8 ····dc.b ···6,4,7,0,7,4,3,0,2,1,2,6,7,3,3,2,6,0,3,5,2,4,6,6,2,3,3,1
44ede7 @cks1:
ab5f5b ····suba.w ·(a2)+,a0 ············//correct permutation
c861a7 ····moveq ··#7,d1 ···············//do 8 bytes worth
6179e4 @cks2: ···
36cd4a ····moveq ··#6,d2 ···············//do 7 bits per PGPByte
d21f2f ····moveq ··#0,d3 ···············//clear a PGPByte to fill
04585f @cks3:
12f145 ····move.b ·(a0)+,d4 ············//get a PGPByte number
0a4140 ····move.b ·(a0)+,d5 ············//get a bit number
38ddc3 ····btst ···d5,0(a1,d4.w) ·······//test bit in key PGPByte
cb78df ····beq.s ··@cks4 ···············//if no bit to set
bcdbe5 ····bset ···d2,d3 ···············//else set a bit
58d45a @cks4:
f56480 ····dbf ····d2,@cks3 ············//loop until all bits done
f2b623 ····move.b ·d3,(a3)+ ············//set PGPByte
c44982 ····dbf ····d1,@cks2 ············//loop through all bytes
1f28c1 ····lea ····-8(a3),a1 ···········//reset a1 to last subkey
f95881 ····cmpi.w ·#EN0,edf ············//check mode
f73af8 ····beq.s ··@cks5 ···············//encryption
586203 ····lea ····-16(a3),a3 ··········//adjust filling
328e86 @cks5:
951b3d ····dbf ····d0,@cks1 ············//for all rounds
678c8d ····move.l ·#0x3f3f3f3f,d1 ······//load bit mask
f62efb ····movea.l buf,a0 ··············//reload key register
50a1fe ····moveq ··#15,d2 ··············//load loop index
1761e2 @cks6:
6008f2 ····move.l ·(a0),d0 ·············//next raw target
afe682 ····and.l ··d1,d0 ···············//clear bits
4c28d2 ····rol.l ··#4,d0 ···············//preallign
f52dda ····move.l ·d0,(a0)+ ············//set cooked key - even
--1642 000ff137bf940100129 Page 2 of pgpDES3_68K.c
1a5940 ····and.l ··d1,(a0)+ ············//set cooked key - odd
837751 ····dbf ····d2,@cks6 ············//all 32 longs
c5452f ····movem.l (a7)+,d3-d5/a2-a3 ···//restore registers
f6666a ····frfree
0368ac ····rts
6defe6 }
0eaf5a
8635f2 void des3key(uchar *hexkey, short mode, void **ksa)
febb36 {
2c7568 ¤   ulong *ks;
8c2e9a ¤   uchar *first, *third;
d3c30d ¤   short revmod;
3baf5a
c2693c ¤   *ksa = ks = (ulong *)pgp_malloc(96 * sizeof(ulong));
7daf5a
69e320 ¤   if(mode == EN0)
9bc7a1 ¤   {
4641f8 ¤   ¤   revmod = DE1;
5dc0e1 ¤   ¤   first = hexkey;
74a0ce ¤   ¤   third = &hexkey[16];
789371 ¤   }
670e24 ¤   else
ffc7a1 ¤   {
62d075 ¤   ¤   revmod = EN0;
28f47a ¤   ¤   first = &hexkey[16];
e8978d ¤   ¤   third = hexkey;
b49371 ¤   }
b6cc89 ····deskey(first, mode, ks);
9c8baf ····deskey(&hexkey[8], revmod, &ks[32]);
7b9512 ····deskey(third, mode, &ks[64]);
5befe6 }
0d869e ····
766275 void DESDKeyDone(void *ksa)
dabb36 {
cf891c ¤   pgp_free((ulong *)ksa);
73efe6 }
ee67c5 ¤
9833cb asm void D3des(uchar *in, uchar *out, void *ksa)
b3bb36 {
678af2 ····fralloc +
ed2844 ····movem.l d3-d7/a2,-(a7)
9070d8 ····movea.l in,a0
62bb88 ····move.l ·(a0)+,d3 ·······/* D3 = L */
321e1f ····move.l ·(a0),d5 ········/* D5 = R */ ··
6989ae ····move.l ·d3,d2 ··········/* EXSHMSK(R,0x0f0f0f0f,L,4,tmp) */
da75c0 ····lsr.l ··#4,d2
5b9001 ····eor.l ··d5,d2
9c5559 ····andi.l ·#0x0f0f0f0f,d2
53edd5 ····eor.l ··d2,d5
d06d39 ····lsl.l ··#4,d2
e1b905 ····eor.l ··d2,d3
027221 ····swap ···d3 ·············/* EXSHMSK(R,0x0000ffff,L,16,tmp) */
2e3b24 ····move.w ·d3,d2
1f1964 ····move.w ·d5,d3
7f7d68 ····move.w ·d2,d5
58a9a8 ····swap ···d3
2beae3 ····move.l ·d5,d2 ··········/* EXSHMSK(L,0x33333333,R,2,tmp) */
284e58 ····lsr.l ··#2,d2
4dab99 ····eor.l ··d3,d2
302d42 ····andi.l ·#0x33333333,d2
19b905 ····eor.l ··d2,d3
a556a1 ····lsl.l ··#2,d2
1bedd5 ····eor.l ··d2,d5
737d7e ····move.l ·d5,d2 ··········/* EXSHMSK(L,0x00ff00ff,R,8,tmp) */
0602f0 ····lsr.l ··#8,d2
70ab99 ····eor.l ··d3,d2
f1050c ····andi.l ·#0x00ff00ff,d2
83b905 ····eor.l ··d2,d3
b61a09 ····lsl.l ··#8,d2
d0edd5 ····eor.l ··d2,d5
b06b97 ····rol.l ··#1,d5 ··········/* EXSHMSK(R,0x55555555,L,1,tmp) */
ff6d7d ····move.l ·d3,d2
--501f 00073d77d4e40100129 Page 3 of pgpDES3_68K.c
c99001 ····eor.l ··d5,d2
ac7806 ····andi.l ·#0xaaaaaaaa,d2
a4edd5 ····eor.l ··d2,d5
48b905 ····eor.l ··d2,d3
a90460 ····rol.l ··#1,d3
587d1f ····lea ····@SP0,a0
0f6f83 ····lea ····@SP1,a1
9b3408 ····movea.l ksa,a2
58ff02 ····move.l ·#0x03f003f0,d2
6482ac ····moveq ··#2,d7
e08fec ····bra ····@des0
75808a ····DC.W ···0x0123 ···/* alignment slop */
70e1a0 /* On a 68030 it helps _a_lot_ if SP0 (& SP1) are long alligned! */
59dd4f @SP0:
2459fd ····DC.L ···0x01010400,0x00000208,0x00000100,0x00200000
2eaea9 ····DC.L ···0x00000000,0x08020200,0x02080100,0x04200002
0a771b ····DC.L ···0x00010000,0x00000000,0x02080000,0x04000802
46185f ····DC.L ···0x01010404,0x08020008,0x42000100,0x00000000
ce4bfd ····DC.L ···0x01010004,0x08000200,0x00080000,0x00000800
a85c70 ····DC.L ···0x00010404,0x00000000,0x00000100,0x04000802
b12f7a ····DC.L ···0x00000004,0x00020208,0x40000000,0x00200802
daee28 ····DC.L ···0x00010000,0x08000200,0x02080000,0x04200800
88aefd ····DC.L ···0x00000400,0x00020008,0x40080100,0x04200802
080c97 ····DC.L ···0x01010400,0x08000008,0x00080000,0x00200000
c5e919 ····DC.L ···0x01010404,0x08000008,0x02000100,0x00000000
67b69c ····DC.L ···0x00000400,0x00020000,0x40080100,0x04000002
5af3b0 ····DC.L ···0x01000404,0x08020208,0x42000100,0x00000002
d23004 ····DC.L ···0x01010004,0x00020008,0x42080000,0x04000000
338c4c ····DC.L ···0x01000000,0x08020000,0x00080100,0x04200002
558cec ····DC.L ···0x00000004,0x00000208,0x40000000,0x00000802
274c0e ····DC.L ···0x00000404,0x08000000,0x02000000,0x04000800
bbfaf3 ····DC.L ···0x01000400,0x00000008,0x40080000,0x00200802
b2dc3c ····DC.L ···0x01000400,0x08020200,0x40080000,0x00200002
cc81bf ····DC.L ···0x00010400,0x00000200,0x00000000,0x04000800
48eebb ····DC.L ···0x00010400,0x00020200,0x40000100,0x04000002
ebbefa ····DC.L ···0x01010000,0x08020000,0x42080100,0x04200000
d09120 ····DC.L ···0x01010000,0x08020008,0x42080100,0x04200800
81aee9 ····DC.L ···0x01000404,0x00020208,0x02000100,0x00200002
9b907d ····DC.L ···0x00010004,0x08000208,0x42080000,0x04200000
af378e ····DC.L ···0x01000004,0x00020200,0x40000100,0x00000800
dcbbce ····DC.L ···0x01000004,0x00020000,0x00000000,0x00000802
9fc66d ····DC.L ···0x00010004,0x08000208,0x42000000,0x04200802
6dad08 ····DC.L ···0x00000000,0x00000008,0x02080100,0x00200800
3f4026 ····DC.L ···0x00000404,0x08020208,0x02000000,0x00000002
551b6b ····DC.L ···0x00010404,0x00000200,0x42000000,0x04000000
d3d8d7 ····DC.L ···0x01000000,0x08000000,0x00080100,0x00200800
3d86e5 ····DC.L ···0x00010000,0x08020200,0x00080000,0x04000000
979413 ····DC.L ···0x01010404,0x08000000,0x42000100,0x00200800
a846e2 ····DC.L ···0x00000004,0x00020008,0x00000100,0x00200000
4e3107 ····DC.L ···0x01010000,0x00000208,0x02000000,0x04000802
c34f2f ····DC.L ···0x01010400,0x00020000,0x40000000,0x04000802
da7854 ····DC.L ···0x01000000,0x08020200,0x02080000,0x04200002
914140 ····DC.L ···0x01000000,0x08000200,0x42000100,0x04200002
63346f ····DC.L ···0x00000400,0x00000000,0x40080100,0x00000002
d94376 ····DC.L ···0x01010004,0x00000200,0x02000100,0x00200002
9f34cc ····DC.L ···0x00010000,0x00020008,0x40000000,0x04000000
c91b89 ····DC.L ···0x00010400,0x08020208,0x42080000,0x04000800
e7b5d9 ····DC.L ···0x01000004,0x08000200,0x02080100,0x00200000
4406e9 ····DC.L ···0x00000400,0x08000008,0x40080100,0x04200800
966baf ····DC.L ···0x00000004,0x00000200,0x00000100,0x00000802
9bcf85 ····DC.L ···0x01000404,0x00000000,0x02000000,0x00200802
fb8a67 ····DC.L ···0x00010404,0x08020008,0x42080000,0x04200800
7148d3 ····DC.L ···0x01010404,0x08000208,0x42080100,0x00000802
7954a3 ····DC.L ···0x00010004,0x00020000,0x00080100,0x04000002
1634ed ····DC.L ···0x01010000,0x08000000,0x42000000,0x04200802
d0611d ····DC.L ···0x01000404,0x08020208,0x42080100,0x04200000
e04f11 ····DC.L ···0x01000004,0x00000008,0x02080000,0x00200800
2b529c ····DC.L ···0x00000404,0x00020208,0x00000000,0x00000000
a304d3 ····DC.L ···0x00010404,0x00020200,0x40080000,0x00000002
d407b1 ····DC.L ···0x01010400,0x08000008,0x42000000,0x04200802
bbcdf4 ····DC.L ···0x00000404,0x08020000,0x00080100,0x00000000
73e471 ····DC.L ···0x01000400,0x08000208,0x02000100,0x00200802
--c920 000b8f3aa0a40100129 Page 4 of pgpDES3_68K.c
9560a6 ····DC.L ···0x01000400,0x00000208,0x40000100,0x04200000
2dadbc ····DC.L ···0x00000000,0x08020000,0x00080000,0x00000800
a0c442 ····DC.L ···0x00010004,0x00020208,0x00000000,0x04000002
4e3c1f ····DC.L ···0x00010400,0x00000008,0x40080000,0x04000800
3e0117 ····DC.L ···0x00000000,0x08020008,0x02080100,0x00000800
009cb3 ····DC.L ···0x01010004,0x00020200,0x40000100,0x00200002
348793 @SP1:
cbad89 ····DC.L ···0x80108020,0x00802001,0x20000010,0x10001040
ee8ac2 ····DC.L ···0x80008000,0x00002081,0x20400000,0x00001000
2ec96f ····DC.L ···0x00008000,0x00002081,0x00004000,0x00040000
697e2e ····DC.L ···0x00108020,0x00000080,0x20404010,0x10041040
9f2bda ····DC.L ···0x00100000,0x00802080,0x20400000,0x10000000
81d166 ····DC.L ···0x00000020,0x00800081,0x00000010,0x10001040
d6e278 ····DC.L ···0x80100020,0x00800001,0x20404010,0x00000040
130991 ····DC.L ···0x80008020,0x00002001,0x00400000,0x10000000
35d310 ····DC.L ···0x80000020,0x00000000,0x20004000,0x00040040
b4eb34 ····DC.L ···0x80108020,0x00802000,0x00404010,0x10040000
df8516 ····DC.L ···0x80108000,0x00802000,0x00400000,0x10041040
6790c1 ····DC.L ···0x80000000,0x00802081,0x20000010,0x00041000
50bb54 ····DC.L ···0x80008000,0x00000081,0x00400010,0x10041000
9bbbd4 ····DC.L ···0x00100000,0x00000000,0x20004000,0x00041040
f86ce9 ····DC.L ···0x00000020,0x00800080,0x20000000,0x00001000
dfaf6a ····DC.L ···0x80100020,0x00800001,0x00004010,0x00000040
7b2582 ····DC.L ···0x00108000,0x00000001,0x00000000,0x10040000
910244 ····DC.L ···0x00100020,0x00002000,0x00400010,0x10000040
e01764 ····DC.L ···0x80008020,0x00800000,0x20004010,0x10001000
b71dd4 ····DC.L ···0x00000000,0x00802001,0x00004000,0x00001040
428570 ····DC.L ···0x80000000,0x00000080,0x00404000,0x00041000
574faa ····DC.L ···0x00008000,0x00800000,0x20004010,0x00040040
8bcc16 ····DC.L ···0x00108020,0x00002001,0x00000010,0x10040040
238212 ····DC.L ···0x80100000,0x00002080,0x20400010,0x10041000
c7dfb3 ····DC.L ···0x00100020,0x00800081,0x20400010,0x00001040
bd6546 ····DC.L ···0x80000020,0x00000001,0x00000000,0x00000000
d879d7 ····DC.L ···0x00000000,0x00002080,0x00404010,0x00000000
c5aaf0 ····DC.L ···0x00108000,0x00800080,0x20404000,0x10040040
3ea1a6 ····DC.L ···0x00008020,0x00002000,0x00004010,0x10000040
8dfd61 ····DC.L ···0x80108000,0x00802080,0x00404000,0x10001000
ae50bd ····DC.L ···0x80100000,0x00802081,0x20404000,0x00041040
77a3af ····DC.L ···0x00008020,0x00000081,0x20000000,0x00040000
3467c9 ····DC.L ···0x00000000,0x00800080,0x20004000,0x00041040
85b7e5 ····DC.L ···0x00108020,0x00800001,0x00000010,0x00040000
fb00ba ····DC.L ···0x80100020,0x00802000,0x20400010,0x10041000
eea8f8 ····DC.L ···0x00100000,0x00802081,0x00404000,0x00001000
8a4070 ····DC.L ···0x80008020,0x00000081,0x20404010,0x00000040
dfa528 ····DC.L ···0x80100000,0x00000000,0x00400000,0x10040040
ef436e ····DC.L ···0x80108000,0x00000000,0x00004010,0x00001000
dfc81c ····DC.L ···0x00008000,0x00802000,0x20000010,0x00041040
105ae9 ····DC.L ···0x80100000,0x00002080,0x00400000,0x10001000
e73f01 ····DC.L ···0x80008000,0x00800080,0x20004000,0x00000040
b21275 ····DC.L ···0x00000020,0x00800081,0x20000000,0x10000040
331eb0 ····DC.L ···0x80108020,0x00000001,0x00004010,0x10040000
298b54 ····DC.L ···0x00108020,0x00802001,0x20000010,0x10040040
da895c ····DC.L ···0x00000020,0x00002081,0x20404010,0x10000000
5332c0 ····DC.L ···0x00008000,0x00002081,0x00404000,0x00040000
bb259f ····DC.L ···0x80000000,0x00000080,0x20400000,0x10001040
20fdf6 ····DC.L ···0x00008020,0x00802081,0x00404010,0x00000000
5c363a ····DC.L ···0x80108000,0x00000081,0x20404000,0x10041040
a8750b ····DC.L ···0x00100000,0x00000001,0x00000000,0x00040040
7687f6 ····DC.L ···0x80000020,0x00002000,0x20400010,0x10000040
f0840d ····DC.L ···0x00100020,0x00800001,0x00000010,0x10040000
4ad118 ····DC.L ···0x80008020,0x00002001,0x00004000,0x10001000
ca207f ····DC.L ···0x80000020,0x00802080,0x20400000,0x10001040
5e2949 ····DC.L ···0x00100020,0x00800081,0x00404010,0x00000000
eac155 ····DC.L ···0x00108000,0x00002001,0x00004000,0x10041040
384a5d ····DC.L ···0x00000000,0x00002080,0x00400010,0x00041000
6c1aba ····DC.L ···0x80008000,0x00800000,0x20004010,0x00041000
6f1b2c ····DC.L ···0x00008020,0x00802001,0x00000000,0x00001040
3c4000 ····DC.L ···0x80000000,0x00000080,0x20404000,0x00001040
e804b7 ····DC.L ···0x80100020,0x00800000,0x20000000,0x00040040
ec2205 ····DC.L ···0x80108020,0x00002000,0x00400010,0x10000000
43e300 ····DC.L ···0x00108000,0x00802080,0x20004010,0x10041000
b8bb9c @desIter:
--3bbd 000291087ad40100129 Page 5 of pgpDES3_68K.c
d6f952 ····exg ····d5,d3
34517f @des0: ···
cdf028 ····moveq ··#7,d1
6535a1 @desLoop:
2863ff ····move.l ·(a2)+,d0
9da3b1 ····eor.l ··d5,d0
6717d1 ····move.l ·d0,d6
9a776c ····and.l ··d2,d0
3fd077 ····move.l ·12(a0,d0.w),d4 ···/* S6 */
6f83c0 ····swap ···d0
d1c7b8 ····or.l ···4(a0,d0.w),d4 ····/* S2 */
e83345 ····ror.l ··#8,d6
e523bc ····and.l ··d2,d6
d88c1b ····or.l ···8(a0,d6.w),d4 ····/* S4 */
ffd710 ····swap ···d6
b22369 ····or.l ···0(a0,d6.w),d4 ····/* S0 */
c363ff ····move.l ·(a2)+,d0
d5a3b1 ····eor.l ··d5,d0
0717d1 ····move.l ·d0,d6
575e89 ····lsl.l ··#4,d0
fc776c ····and.l ··d2,d0
6294ff ····or.l ···12(a1,d0.w),d4 ···/* S7 */
7a83c0 ····swap ···d0
f497b8 ····or.l ···4(a1,d0.w),d4 ····/* S3 */
6812a0 ····lsr.l ··#4,d6
fe23bc ····and.l ··d2,d6
4cdc1b ····or.l ···8(a1,d6.w),d4 ····/* S5 */
5ad710 ····swap ···d6
637369 ····or.l ···0(a1,d6.w),d4 ····/* S1 */
73829d ····eor.l ··d4,d3
a563ff ····move.l ·(a2)+,d0
289829 ····eor.l ··d3,d0
f717d1 ····move.l ·d0,d6
eb776c ····and.l ··d2,d0
44d077 ····move.l ·12(a0,d0.w),d4 ···/* S6 */
5c83c0 ····swap ···d0
3ac7b8 ····or.l ···4(a0,d0.w),d4 ····/* S2 */
5d3345 ····ror.l ··#8,d6
b623bc ····and.l ··d2,d6
148c1b ····or.l ···8(a0,d6.w),d4 ····/* S4 */
63d710 ····swap ···d6
802369 ····or.l ···0(a0,d6.w),d4 ····/* S0 */
0163ff ····move.l ·(a2)+,d0
299829 ····eor.l ··d3,d0
1017d1 ····move.l ·d0,d6
225e89 ····lsl.l ··#4,d0
99776c ····and.l ··d2,d0
1994ff ····or.l ···12(a1,d0.w),d4 ···/* S7 */
e583c0 ····swap ···d0
2b97b8 ····or.l ···4(a1,d0.w),d4 ····/* S3 */
4212a0 ····lsr.l ··#4,d6
c523bc ····and.l ··d2,d6
abdc1b ····or.l ···8(a1,d6.w),d4 ····/* S5 */
14d710 ····swap ···d6
827369 ····or.l ···0(a1,d6.w),d4 ····/* S1 */
f0d64d ····eor.l ··d4,d5
09fa17 ····dbf ····d1,@desLoop ······/* 53 */
e81487 ····dbf ····d7,@desIter
108fae ····ror.l ··#1,d5 ············/* EXSHMSK(R,0x55555555,L,1,tmp) */
0956e5 ····move.l ·d5,d2
86ab99 ····eor.l ··d3,d2
bf7806 ····andi.l ·#0xaaaaaaaa,d2
74b905 ····eor.l ··d2,d3
14edd5 ····eor.l ··d2,d5
121c99 ····ror.l ··#1,d3
53140c ····move.l ·d3,d2 ············/* EXSHMSK(L,0x00ff00ff,R,8,tmp) */
ac02f0 ····lsr.l ··#8,d2
ca9001 ····eor.l ··d5,d2
61050c ····andi.l ·#0x00ff00ff,d2
98edd5 ····eor.l ··d2,d5
c21a09 ····lsl.l ··#8,d2
29b905 ····eor.l ··d2,d3
--5c89 0017b0692ff40100129 Page 6 of pgpDES3_68K.c
4f8391 ····move.l ·d3,d2 ············/* EXSHMSK(L,0x33333333,R,2,tmp) */
5d4e58 ····lsr.l ··#2,d2
509001 ····eor.l ··d5,d2
d12d42 ····andi.l ·#0x33333333,d2
f5edd5 ····eor.l ··d2,d5
6d56a1 ····lsl.l ··#2,d2
3cb905 ····eor.l ··d2,d3
f77d9a ····swap ···d5 ···············/* EXSHMSK(R,0x0000ffff,L,16,tmp) */
0e00bc ····move.w ·d5,d2
c3762c ····move.w ·d3,d5
3229b8 ····move.w ·d2,d3
cafd78 ····swap ···d5
f3743c ····move.l ·d5,d2 ············/* EXSHMSK(R,0x0f0f0f0f,L,4,tmp) */
3b75c0 ····lsr.l ··#4,d2
b7ab99 ····eor.l ··d3,d2
365559 ····andi.l ·#0x0f0f0f0f,d2
c4b905 ····eor.l ··d2,d3
2e6d39 ····lsl.l ··#4,d2
2cedd5 ····eor.l ··d2,d5
48e220 ····movea.l out,a0
138b08 ····move.l ·d5,(a0)+
b51033 ····move.l ·d3,(a0)
927a2a ····movem.l (a7)+,a2/d3-d7
c2666a ····frfree
8b68ac ····rts
3aefe6 }
58af5a
e0994a /* Validation triples -
f6775e ·*
c60e17 ·* Double-length key, single-length plaintext -
5ea8e9 ·* Key ···: 0123 4567 89ab cdef fedc ba98 7654 3210
408da6 ·* Plain ·: 0123 4567 89ab cde7
b4df12 ·* Cipher : 7f1d 0a77 826b 8aff
a5775e ·*
91a87e ·* Triple-length key, single-length plaintext -
5fc6af ·* Key ···: 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
1d8da6 ·* Plain ·: 0123 4567 89ab cde7
06e789 ·* Cipher : de0b 7c06 ae5e 0ed5
19775e ·*
b7495d ·*/
7baf5a
--2ed4 00033e933684010012a Page 1 of pgpIDEA.c
bc38e5 /*
737720 ·* pgpIDEA.c - C source code for IDEA block cipher.
62811b ·* Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
e7775e ·*
d584ce ·* $Id: pgpIDEA.c,v 1.16 1997/10/14 01:48:18 heller Exp $
73775e ·*
d6fdbb ·* There are two adjustments that can be made to this code to speed it
937938 ·* up. ·Defaults may be used for PCs. ·Only the -DIDEA32 pays off
7a9f70 ·* significantly if selectively set or not set. ·Experiment to see what
c2c24f ·* works best for your machine.
49775e ·*
e8820e ·* Multiplication: default is inline, -DAVOID_JUMPS uses a different
947878 ·* ¤version that does not do any conditional jumps (a few percent
12175a ·* ¤worse on a SPARC, better on other machines), while
50564d ·* ¤-DSMALL_CACHE takes it out of line to stay within a small
bc5ec0 ·* ¤on-chip code cache. ·(Not really applicable with current L1
fd3669 ·* ¤cache sizes.)
034910 ·* Variables: normally, 16-bit variables are used, but some machines do
832a8e ·* ¤not have 16-bit registers, so they do a great deal of masking.
b5ffd9 ·* ¤-DUSE_IDEA32 uses "int" register variables and masks explicitly
d416be ·* ¤only where necessary. ·On a SPARC, for example, this boosts
49aeec ·* ¤performance by 30%.
8a775e ·*
2c7a94 ·* The IDEA(tm) block cipher is covered by a patent held by ETH and a
6edec5 ·* Swiss company called Ascom-Tech AG. ·The Swiss patent number is
f973d9 ·* PCT/CH91/00117. ·International patents are pending. IDEA(tm) is a
79ca67 ·* trademark of Ascom-Tech AG. ·There is no license fee required for
faee18 ·* noncommercial use. ·Commercial users may obtain licensing details from
3a49dd ·* Dieter Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502
ad652e ·* Solothurn, Switzerland, Tel +41 65 242885, Fax +41 65 235761.
4b775e ·*
1ef6ae ·* The IDEA block cipher uses a 64-bit block size, and a 128-bit key·
4024b2 ·* size. ·It breaks the 64-bit cipher block into four 16-bit words
dd4889 ·* because all of the primitive inner operations are done with 16-bit·
e4a7cf ·* arithmetic. ·It likewise breaks the 128-bit cipher key into eight·
dd9424 ·* 16-bit words.
67775e ·*
8fdf57 ·* For further information on the IDEA cipher, see these papers:
d89204 ·* 1) Xuejia Lai, "Detailed Description and a Software Implementation of·
7b604f ·* ···the IPES Cipher", Institute for Signal and Information
8fd8dc ·* ···Processing, ETH-Zentrum, Zurich, Switzerland, 1991
7af6fb ·* 2) Xuejia Lai, James L. Massey, Sean Murphy, "Markov Ciphers and·
5dc7e5 ·* ···Differential Cryptanalysis", Advances in Cryptology - EUROCRYPT'91
a2775e ·*
773555 ·* This code runs on arrays of bytes by taking pairs in big-endian order
02b5fe ·* to make the 16-bit words that IDEA uses internally. ·This produces the
4c1681 ·* same result regardless of the byte order of the native CPU.
dd495d ·*/
84d83c ·
813051 #include "pgpSDKBuildFlags.h"
c1af5a
08d5ba #ifndef PGP_IDEA
f044a3 #error you must define PGP_IDEA one way or the other
257454 #endif
96af5a
e9f391 #if PGP_IDEA¤   /* [ */
dcaf5a
92324c #include <string.h>
73e2ff #include "pgpConfig.h"
99af5a
4b0e2f #include "pgpSymmetricCipherPriv.h"
c56332 #include "pgpIDEA.h"
bb0d08 #include "pgpMem.h"
14d11f #include "pgpUsuals.h"
fdaf5a
7df38b /* If IDEA32 isn't predefined as 1 or 0, make a guess. */
3f9240 #ifndef USE_IDEA32
c4f19e #if UINT_MAX > 0xffff
327122 #define USE_IDEA32 1
5d7454 #endif
ea7454 #endif
33af5a
--e7f1 00069e8a45b4010012a Page 2 of pgpIDEA.c
5f15c4 #if USE_IDEA32¤ /* Use >16-bit temporaries */
3c90c0 #define low16(x) ((x) & 0xFFFF)
f1fb7b typedef unsigned int uint16;¤   /* at LEAST 16 bits, maybe more */
00db21 #else
c0b96e #define low16(x) (uint16)(x)
15d874 typedef PGPUInt16 uint16;
a77454 #endif
5faf5a
644788 /* A few handy definitions */
4e7b3c #define IDEA_ROUNDS 8
c47237 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4)
c20c3b #define IDEA_KEYBYTES (sizeof(PGPUInt16) * IDEA_KEYLEN)
50af5a
b3af5a
d138e5 /*
c0e8ab ·* Flags in priv array to record whether key schedule is in encrypt
9801d2 ·* or decrypt mode
b7495d ·*/
4b52bf #define IDEA_ENCRYPTION_MODE¤   0x11
7130b1 #define IDEA_DECRYPTION_MODE¤   0x22
caaf5a
409150 /* Private functions */
63af5a
e075b4 /* Expand a 128-bit user key to a working encryption key EK */
f9af5a
d72978 static void
b3856c ideaExpandKey(PGPByte const *userkey, PGPUInt16 *EK)
44bb36 {
a6927e ¤   int i, j;
c0af5a
a0a05e ¤   for (j=0; j<8; j++) {
b2fa17 ¤   ¤   EK[j] = (userkey[0]<<8) + userkey[1];
840c76 ¤   ¤   userkey += 2;
519371 ¤   }
455ed2 ¤   for (i=0; j < IDEA_KEYLEN; j++) {
82347d ¤   ¤   i++;
6981b4 ¤   ¤   EK[i+7] = EK[i & 7] << 9 | EK[(i+1) & 7] >> 7;
52b77a ¤   ¤   EK += i & 8;
ff72a6 ¤   ¤   i &= 7;
f69371 ¤   }
f4e960 } /* ideaExpandKey */
4faf5a
9e38e5 /*
015b75 ·* Compute the multiplicative inverse of x, modulo 65537, using Euclid's
a9c73b ·* algorithm. It is unrolled twice to avoid swapping the registers each
740ce3 ·* iteration, and some subtracts of t have been changed to adds.
33495d ·*/
85230e static uint16
70610c mulInv(uint16 x) ····
a1bb36 {
1339de ¤   uint16 t0, t1;
584e36 ¤   uint16 q, y;
96af5a
5387f0 ¤   if (x <= 1)
d48744 ¤   ¤   return x;¤  /* 0 and 1 are self-inverse */
2f1419 ¤   t1 = 0x10001L / x;¤ /* Since x >= 2, this fits into 16 bits */
99cd17 ¤   y = 0x10001L % x;
930264 ¤   if (y == 1)
fbff65 ¤   ¤   return low16(1-t1);
eff259 ¤   t0 = 1;
dd43ab ¤   do {
45b910 ¤   ¤   q = x / y;
8e1c83 ¤   ¤   x = x % y;
36cbbf ¤   ¤   t0 += q * t1;
1714a8 ¤   ¤   if (x == 1)
09497c ¤   ¤   ¤   return t0;
8c7c19 ¤   ¤   q = y / x;
c78c1b ¤   ¤   y = y % x;
ff94ce ¤   ¤   t1 += q * t0;
7f386d ¤   } while (y != 1);
f10900 ¤   return low16(1-t1);
693b2a } /* mulInv */
--1455 000408bb2ac4010012a Page 3 of pgpIDEA.c
e0af5a
d338e5 /*
45465e ·* Compute IDEA decryption key DK from an expanded IDEA encryption key EK
feff74 ·* Note that the input and output may be the same. ·Thus, the key is
a7d3f0 ·* inverted into an internal buffer, and then copied to the output.
61495d ·*/
6d2978 static void
321eb6 ideaInvertKey(PGPUInt16 const EK[IDEA_KEYLEN], PGPUInt16 DK[IDEA_KEYLEN])
debb36 {
644ba4 ¤   int i;
1f7f1e ¤   uint16 t1, t2, t3;
543c93 ¤   PGPUInt16 temp[IDEA_KEYLEN];
b2f52f ¤   PGPUInt16 *p = temp + IDEA_KEYLEN;
05af5a
3d6352 ¤   t1 = mulInv(*EK++);
f403fb ¤   t2 = -*EK++;
1a86ae ¤   t3 = -*EK++;
f0653c ¤   *--p = mulInv(*EK++);
3cf223 ¤   *--p = t3;
e1a8ff ¤   *--p = t2;
07479b ¤   *--p = t1;
4aaf5a
875afb ¤   for (i = 0; i < IDEA_ROUNDS-1; i++) {
c5ba1e ¤   ¤   t1 = *EK++;
10e1be ¤   ¤   *--p = *EK++;
e9a538 ¤   ¤   *--p = t1;
3eaf5a
a49537 ¤   ¤   t1 = mulInv(*EK++);
cf4270 ¤   ¤   t2 = -*EK++;
91c725 ¤   ¤   t3 = -*EK++;
17ec68 ¤   ¤   *--p = mulInv(*EK++);
b54a5c ¤   ¤   *--p = t2;
9a1080 ¤   ¤   *--p = t3;
4ba538 ¤   ¤   *--p = t1;
6e9371 ¤   }
d02d6d ¤   t1 = *EK++;
dfdb24 ¤   *--p = *EK++;
85479b ¤   *--p = t1;
70af5a
3d6352 ¤   t1 = mulInv(*EK++);
7003fb ¤   t2 = -*EK++;
2886ae ¤   t3 = -*EK++;
72653c ¤   *--p = mulInv(*EK++);
26f223 ¤   *--p = t3;
eea8ff ¤   *--p = t2;
f8479b ¤   *--p = t1;
bc0133 /* Copy and destroy temp copy */
c5ee9b ¤   memcpy(DK, temp, sizeof(temp));
52a881 ¤   pgpClearMemory( temp, ·sizeof(temp));
386181 } /* ideaInvertKey */
feaf5a
4baf5a
1d38e5 /*
9239c2 ·* MUL(x,y) computes x *= y, modulo 0x10001. ·Requires two temps,·
6e35a3 ·* t16 and t32. ·x is modified, and must be a side-effect-free lvalue.
804cd7 ·* y may be anything, and is guaranteed to be evaluated exactly once,
9d535a ·* but unlike x, must be strictly 16 bits even if low16() is #defined.
82ad92 ·* All of these are equivalent - see which is faster on your machine.
c7495d ·*/
82b20b #if SMALL_CACHE
b6af5a
0ab499 #define MUL(x,y) (x = mul(low16(x),y))
cd230e static uint16
73b8ef mul(register uint16 a, register uint16 b)
acbb36 {
f64e3d ¤   register PGPUInt32 p;
c6af5a
8cabce ¤   p = (PGPUInt32)a * b;
65f191 ¤   if (p) {
7764ec ¤   ¤   b = low16(p);
c84104 ¤   ¤   a = p>>16;
40f2e3 ¤   ¤   return (b - a) + (b < a);
--c2b2 000189cc01b4010012a Page 4 of pgpIDEA.c
faf037 ¤   } else {
1a9f67 ¤   ¤   return 1-a-b;
8e9371 ¤   }
4ed8a1 } /* mul */
6caf5a
6e2adb #elif AVOID_JUMPS
56af5a
501715 #define MUL(x,y) ( x = low16(x-1), t16 = low16((y)-1), \
4d08a6 ¤   ¤   ···t32 = (PGPUInt32)x*t16 + x + t16, \
dfd259 ¤   ¤   ···x = low16(t32), t16 = t32>>16, \
756116 ¤   ¤   ···x = (x-t16) + (x<t16) + 1 )
83af5a
2161c1 #else /* default */
6caf5a
816ce1 #define MUL(x,y) (x = \
75a22e ¤   ¤   ··( ( t32 = (PGPUInt32)(x=low16(x))*(t16=(y)) ) != 0 ) ? \
ade0e6 ¤   ¤   ¤   x = low16(t32), \
be30d9 ¤   ¤   ¤   t16 = (uint16)(t32>>16), \
3cbe1f ¤   ¤   ¤   (x-t16)+(x<t16) \
0ac3dc ¤   ¤   ···: \
315abb ¤   ¤   ¤   (uint16)(1-x-t16) \
117ec4 ¤   ¤   ·)
f4af5a
327454 #endif
6caf5a
ff38e5 /*
62ca38 ·* IDEA encryption/decryption algorithm. ·In and out may be the same buffer.
537bbe ·* key is a pointer to IDEAKEYLEN words. ·(Borland C 3.1 gives an error if
e83532 ·* you declare it as a "PGPUInt16 const key[IDEAKEYLEN]" array.)
24495d ·*/
2b2978 static void
9eec72 ideaCipher(PGPByte const inbuf[8], PGPByte outbuf[8], PGPUInt16 const *key)
b8bb36 {
174310 ¤   register uint16 x1, x2, x3, x4, s2, s3;
9aa835 #if !SMALL_CACHE
1ee73a ¤   register uint16 t16;¤   /* Temporaries needed by MUL macro */
ced854 ¤   register PGPUInt32 t32;
c47454 #endif
e93e92 ¤   int r = IDEA_ROUNDS;
69af5a
05a15b ¤   x1 = (uint16)inbuf[0] << 8 | inbuf[1];
e8d9d9 ¤   x2 = (uint16)inbuf[2] << 8 | inbuf[3];
22eb5d ¤   x3 = (uint16)inbuf[4] << 8 | inbuf[5];
a928dd ¤   x4 = (uint16)inbuf[6] << 8 | inbuf[7];
6daf5a
9143ab ¤   do {
801a4f ¤   ¤   MUL(x1,*key++);
5a7e00 ¤   ¤   x2 += *key++;
af7bad ¤   ¤   x3 += *key++;
88d521 ¤   ¤   MUL(x4, *key++);
2caf5a
ce3023 ¤   ¤   s3 = x3;
baffd7 ¤   ¤   x3 ^= x1;
6857b9 ¤   ¤   MUL(x3, *key++);
55eb40 ¤   ¤   s2 = x2;
1a8b97 ¤   ¤   x2 ^= x4;
4ee67d ¤   ¤   x2 += x3;
d1d2ec ¤   ¤   MUL(x2, *key++);
99f15c ¤   ¤   x3 += x2;
96af5a
df9327 ¤   ¤   x1 ^= x2; ·x4 ^= x3;
08af5a
7d7e01 ¤   ¤   x2 ^= s3; ·x3 ^= s2;
17c722 ¤   } while (--r);
f4e4d3 ¤   MUL(x1, *key++);
f54137 ¤   x3 += *key++;
9d449a ¤   x2 += *key++;
8762c3 ¤   MUL(x4, *key);
85af5a
13d714 ¤   outbuf[0] = (PGPByte)(x1>>8);
de6700 ¤   outbuf[1] = (PGPByte)x1;
18fb2c ¤   outbuf[2] = (PGPByte)(x3>>8);
--4e40 0005036fab14010012a Page 5 of pgpIDEA.c
7c2b67 ¤   outbuf[3] = (PGPByte)x3;
f9487c ¤   outbuf[4] = (PGPByte)(x2>>8);
cc73cb ¤   outbuf[5] = (PGPByte)x2;
050b32 ¤   outbuf[6] = (PGPByte)(x4>>8);
975ccd ¤   outbuf[7] = (PGPByte)x4;
55ebb8 } /* ideaCipher */
bdaf5a
0b38e5 /*
37457f ·* Exported functions
5a495d ·*/
a4af5a
bd2978 static void
910e11 ideaKey(void *priv, void const *key)
53bb36 {
077748 ¤   /* Do key schedule for encryption, can be converted later */
f340e3 ¤   ideaExpandKey((const PGPByte *) key, (PGPUInt16 *)priv);
9c7517 ¤   *((PGPByte *)priv + IDEA_KEYBYTES) = IDEA_ENCRYPTION_MODE;
82efe6 }
5aaf5a
832978 static void
0b4373 ideaEncrypt(void *priv, void const *in, void *out)
03bb36 {
a70d0a ¤   /* Make sure key schedule is in the right mode */
542ba8 ¤   if (*((PGPByte *)priv + IDEA_KEYBYTES) != IDEA_ENCRYPTION_MODE) {
4d6980 ¤   ¤   ideaInvertKey ((PGPUInt16 *)priv, (PGPUInt16 *)priv);
31f8eb ¤   ¤   *((PGPByte *)priv + IDEA_KEYBYTES) = IDEA_ENCRYPTION_MODE;
ab9371 ¤   }
8fd2ac ¤   /* Do the operation */
a8ebd4 ¤   ideaCipher((const PGPByte *) in, (PGPByte *) out, (PGPUInt16 *)priv);
beefe6 }
4aaf5a
6a2978 static void
bc8703 ideaDecrypt(void *priv, void const *in, void *out)
11bb36 {
da0d0a ¤   /* Make sure key schedule is in the right mode */
9e4696 ¤   if (*((PGPByte *)priv + IDEA_KEYBYTES) != IDEA_DECRYPTION_MODE) {
326980 ¤   ¤   ideaInvertKey ((PGPUInt16 *)priv, (PGPUInt16 *)priv);
9b2201 ¤   ¤   *((PGPByte *)priv + IDEA_KEYBYTES) = IDEA_DECRYPTION_MODE;
229371 ¤   }
5ed2ac ¤   /* Do the operation */
13ebd4 ¤   ideaCipher((const PGPByte *) in, (PGPByte *) out, (PGPUInt16 *)priv);
a3efe6 }
eeaf5a
a038e5 /*
11fea0 ·* Do one 64-bit step of a Tandem Davies-Meyer hash computation.
47f1a8 ·* The hash buffer is 32 bytes long and contains H (0..7), then G (8..15),
61f12f ·* then 16 bytes of scratch space. ·The buf is 8 bytes long.
c9f18f ·* xkey is a temporary key schedule buffer.
ec3a09 ·* This and the extra data in the hash buffer are allocated by the
102186 ·* caller to reduce the amount of buffer-wiping we have to do.
3c28d7 ·* (It's only called from ideaWash, so the interface can be a bit
7d5ff5 ·* specialized.)
3a495d ·*/
8d2978 static void
94a980 ideaStepTandemDM(PGPByte *hash, PGPByte const *buf, PGPUInt16 *xkey)
88bb36 {
9c4ba4 ¤   int i;
b7af5a
66d40d ¤   /* key1 = G << 64 + M, remembering that IDEA is big-endian */
6345c1 ¤   memcpy(hash+16, buf, 8);
7fd8b9 ¤   ideaExpandKey(hash+8, xkey);
74ca23 ¤   /* W = E_key1(H), key2 = M << 64 + W */
e5635d ¤   ideaCipher(hash, hash+24, xkey);
f773e8 ¤   ideaExpandKey(hash+16, xkey);
fa932e ¤   /* V = E_key2(G) */
f239d5 ¤   ideaCipher(hash+8, hash+16, xkey);
2aa8d1 ¤   /* H ^= W, G ^= V */
de1246 ¤   for (i = 0; i < 8; i++) {
24575f ¤   ¤   hash[i] ^= hash[i+24];
225171 ¤   ¤   hash[i+8] ^= hash[i+16];
889371 ¤   }
50efe6 }
--4655 0003312c9894010012a Page 6 of pgpIDEA.c
e0af5a
d338e5 /*
02dc2f ·* Munge the key of the CipherContext based on the supplied bytes.
b36a26 ·* This is for random-number generation, so the exact technique is
c9572d ·* unimportant, but it happens to use the current key as the
76d7f2 ·* IV for computing a tandem Davies-Meyer hash of the bytes,
0b2d54 ·* and uses the output as the new key.
1c495d ·*/
e92978 static void
a40beb ideaWash(void *priv, void const *bufIn, PGPSize len)
4abb36 {
aa743f ¤   unsigned i;
2fa42c ¤   PGPByte hash[32];
f83eb2 ¤   PGPUInt16 ¤ *xkey ¤ = (PGPUInt16 *)priv;
d59133 ¤   PGPByte¤¤   *buf¤   = (PGPByte *) bufIn;
4aaf5a
994c69 ¤   /* Read out the key in canonical byte order for the IV */
f01246 ¤   for (i = 0; i < 8; i++) {
8d4239 ¤   ¤   hash[2*i] = (PGPByte)(xkey[i]>>8);
ad0859 ¤   ¤   hash[2*i+1] = (PGPByte)xkey[i];
849371 ¤   }
2daf5a
ac4c63 ¤   /* Do the initial blocks of the hash */
4c21f7 ¤   i = len;
bdac52 ¤   while (i >= 8) {
8f5752 ¤   ¤   ideaStepTandemDM(hash, buf, xkey);
398f1d ¤   ¤   buf += 8;
e21544 ¤   ¤   i -= 8;
769371 ¤   }
93d8af ¤   /*
d622a9 ¤   ·* At the end, we do Damgard-Merkle strengthening, just like
dddeb8 ¤   ·* MD5 or SHA. ·Pad with 0x80 then 0 bytes to 6 mod 8, then
599725 ¤   ·* add the length. ·We use a 16-bit length in bytes instead
41ed88 ¤   ·* of a 64-bit length in bits, but that is cryptographically
21dbba ¤   ·* irrelevant.
5fa4e3 ¤   ·*/
078210 ¤   /* Do the first partial block - i <= 7 */
fb8020 ¤   memcpy(hash+24, buf, i);
37b9ac ¤   hash[24 + i++] = 0x80;
74764c ¤   if (i > 6) {
c69246 ¤   ¤   pgpClearMemory(hash+24+i, 8-i);
079b8c ¤   ¤   ideaStepTandemDM(hash, hash+24, xkey);
319ed6 ¤   ¤   i = 0;
729371 ¤   }
0c6eb1 ¤   pgpClearMemory(hash+24+i, 6-i);
28d966 ¤   hash[30] = (PGPByte)(len >> 8);
94fd34 ¤   hash[31] = (PGPByte)len;
a00a14 ¤   ideaStepTandemDM(hash, hash+24, xkey);
93af5a
4609a6 ¤   /* Re-schedule the key */
3c5a0f ¤   ideaExpandKey(hash, xkey);
b8af5a
6fbf06 ¤   pgpClearMemory( hash, ·sizeof(hash));
88efe6 }
f5af5a
0538e5 /*
1a19dd ·* Define a Cipher for the generic cipher. ·This is the only
11c178 ·* real exported thing -- everything else can be static, since everything
aeb83b ·* is referenced through function pointers!
92495d ·*/
3607ad PGPCipherVTBL const cipherIDEA = {
b06eed ¤   "IDEA",
062bd4 ¤   kPGPCipherAlgorithm_IDEA,
94f346 ¤   8,¤ ¤   ¤   /* Blocksize */
33f8ba ¤   16,¤¤   ¤   /* Keysize */
1e80e6 ¤   IDEA_KEYBYTES + 1,¤ ¤   ¤   /* Last one remembers encrypt vs decrypt */
0a58b9 ¤   alignof(PGPUInt16),
b27945 ¤   ideaKey,
f0a9c8 ¤   ideaEncrypt,
ad4359 ¤   ideaDecrypt,
079aa5 ¤   ideaWash
3382f7 };
--a260 0005a7e7c6d4010012a Page 7 of pgpIDEA.c
e0af5a
ac91f0 #if UNITTEST¤   /* Currently unused; left in in case of future need */
07af5a
661800 /* Test driver proper starts here */
cefeb2 #include <stdio.h>
190a8b #include <time.h>
e138e5 /*
6410de ·* This is the number of Kbytes of test data to encrypt.
b26038 ·* It defaults to 1 MByte.
44495d ·*/
806923 #ifndef BLOCKS
7c1afb #ifndef KBYTES
45bc45 #define KBYTES 1024
bc7454 #endif
3f47ce #define BLOCKS (64*KBYTES)
3f7454 #endif
9eaf5a
b54d2f int
307f68 main(void)
3e34dd {¤  /* Test driver for IDEA cipher */
8bbcf4 ¤   int i, j, k;
35ee8b ¤   PGPByte userkey[16];
052984 ¤   PGPByte priv[IDEA_KEYBYTES+1];
df88b2 ¤   PGPByte XX[8], YY[8], ZZ[8];
07d05c ¤   clock_t start, end;
769183 ¤   long l;
a8af5a
4a77d2 ¤   /* Make a sample user key for testing... */
2369f4 ¤   for(i=0; i<16; i++)
ff14ba ¤   ¤   userkey[i] = i+1;
a8af5a
57b799 ¤   /* Compute encryption subkeys from user key... */
29e359 ¤   ideaKey(priv, userkey);
67b177 #if 0
a1cc64 ¤   ideaExpandKey(userkey, EK);
fe343c ¤   printf("\nEncryption key subblocks: ");
e40fea ¤   for (j=0; j<IDEA_ROUNDS+1; j++) {
088e97 ¤   ¤   printf("\nround %d: ··", j+1);
8c80fe ¤   ¤   if (j < IDEA_ROUNDS)
3f1673 ¤   ¤   ¤   for(i=0; i<6; i++)
fc187c ¤   ¤   ¤   ¤   printf(" %6u", EK[j*6+i]);
370e1d ¤   ¤   else
991d1c ¤   ¤   ¤   for(i=0; i<4; i++)
2b187c ¤   ¤   ¤   ¤   printf(" %6u", EK[j*6+i]);
649371 ¤   }
1aaf5a
02fb91 ¤   /* Compute decryption subkeys from encryption subkeys... */
4473c6 ¤   ideaInvertKey(EK, DK);
e3e672 ¤   printf("\nDecryption key subblocks: ");
300fea ¤   for (j=0; j<IDEA_ROUNDS+1; j++) {
708e97 ¤   ¤   printf("\nround %d: ··", j+1);
4680fe ¤   ¤   if (j < IDEA_ROUNDS)
961673 ¤   ¤   ¤   for(i=0; i<6; i++)
df9d29 ¤   ¤   ¤   ¤   printf(" %6u", DK[j*6+i]);
e90e1d ¤   ¤   else
4c1d1c ¤   ¤   ¤   for(i=0; i<4; i++)
f29d29 ¤   ¤   ¤   ¤   printf(" %6u", DK[j*6+i]);
859371 ¤   }
cd7454 #endif
14af5a
f5df08 ¤   /* Make a sample plaintext pattern for testing... */
dde1e5 ¤   for (k=0; k<8; k++)
d68209 ¤   ¤   XX[k] = k;
e2af5a
68d3f3 ¤   printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS*16, BLOCKS);
036b16 ¤   fflush(stdout);
968255 ¤   start = clock();
d7392c ¤   memcpy(YY, XX, 8);
8aa71f ¤   for (l = 0; l < BLOCKS; l++)
df7128 ¤   ¤   ideaEncrypt(priv, YY, YY);¤ /* repeated encryption */
5e5e1b ¤   memcpy(ZZ, YY, 8);
5aa71f ¤   for (l = 0; l < BLOCKS; l++)
--0f92 0017b5a17b24010012a Page 8 of pgpIDEA.c
b7342f ¤   ¤   ideaDecrypt(priv, ZZ, ZZ);¤ /* repeated decryption */
ac22d8 ¤   end = clock() - start;
015672 ¤   l = end * 1000 / CLOCKS_PER_SEC + 1;
5dc52d ¤   i = l/1000;
33ab94 ¤   j = l%1000;
034009 ¤   l = BLOCKS * 16 * CLOCKS_PER_SEC / end;
5763e5 ¤   printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
60af5a
9a5d1e ¤   printf("\nX %3u ·%3u ·%3u ·%3u ·%3u ·%3u ·%3u \n", ···
e13687 ¤   ··XX[0], XX[1], ·XX[2], XX[3], XX[4], XX[5], ·XX[6], XX[7]);
e66b25 ¤   printf("\nY %3u ·%3u ·%3u ·%3u ·%3u ·%3u ·%3u \n", ···
757c57 ¤   ··YY[0], YY[1], ·YY[2], YY[3], YY[4], YY[5], ·YY[6], YY[7]);
3b3168 ¤   printf("\nZ %3u ·%3u ·%3u ·%3u ·%3u ·%3u ·%3u \n", ···
d3a327 ¤   ··ZZ[0], ZZ[1], ·ZZ[2], ZZ[3], ZZ[4], ZZ[5], ·ZZ[6], ZZ[7]);
8baf5a
c97a9c ¤   /* Now decrypted ZZ should be same as original XX */
7be1e5 ¤   for (k=0; k<8; k++)
778c75 ¤   ¤   if (XX[k] != ZZ[k]) {
8d1b68 ¤   ¤   ¤   printf("\n\07Error! ·Noninvertable encryption.\n");
86cda0 ¤   ¤   ¤   exit(-1);¤  /* error exit */·
7e0fe4 ¤   ¤   }
03c010 ¤   printf("\nNormal exit.\n");
0aa7e7 ¤   return 0;¤  /* normal exit */
00cd3b } /* main */
5baf5a
ac69f0 #endif /* 0 */
3caf5a
c2af5a
005311 #endif /* ] PGP_IDEA */
a2af5a
94af5a
327e4d /*__Editor_settings____
bdaf5a
d34126 ¤   Local Variables:
a47b17 ¤   tab-width: 4
be0e6c ¤   End:
6b5f8c ¤   vi: ts=4 sw=4
aa9e9b ¤   vim: si
7bd062 _____________________*/
--c225 001a7a9eba94010012b Page 1 of pgpIDEA.h
bc38e5 /*
88ddf2 ·* pgpIDEA.h - header file for pgpIDEA.c
df775e ·*
bee39d ·* This is a PRIVATE header file, for use only within the PGP Library.
0c2979 ·* You should not be using these functions in an application.
bc775e ·*
e15fd3 ·* $Id: pgpIDEA.h,v 1.7 1997/10/10 18:08:13 lloyd Exp $
15495d ·*/
7cdd4f #ifndef Included_pgpIDEA_h
b8b939 #define Included_pgpIDEA_h
60af5a
f5af5a
643051 #include "pgpSDKBuildFlags.h"
f2af5a
97d5ba #ifndef PGP_IDEA
fb44a3 #error you must define PGP_IDEA one way or the other
c97454 #endif
dfaf5a
fcaf5a
64f391 #if PGP_IDEA¤   /* [ */
f4af5a
fdaf5a
39137e #include "pgpSymmetricCipherPriv.h"¤¤   /* for Cipher */
64af5a
2799c6 PGP_BEGIN_C_DECLARATIONS
b9af5a
a438e5 /*
4132b8 ·* This is the definition of the IDEA cipher, for use with the
dfdad0 ·* PGP Generic Cipher code.
9b495d ·*/
031153 extern PGPCipherVTBL const cipherIDEA;
e9af5a
411254 PGP_END_C_DECLARATIONS
46af5a
c12883 #endif /* !Included_pgpIDEA_h */
cfaf5a
caaf5a
f7af5a
a73dcf #endif /* ] PGP_IDEA */¶
--44a8 000bbd3c14e4010012c Page 1 of pgpSymmetricCipher.c
a70335 /*____________________________________________________________________________
2afdbb ¤   pgpSymmetricCipher.c
6067c5 ¤
1cc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
b04b0f ¤   All rights reserved.
4867c5 ¤
6a67c5 ¤
27af5a
4bdece ¤   $Id: pgpSymmetricCipher.c,v 1.39.10.1 1998/11/12 03:21:20 heller Exp $
17f7f7 ____________________________________________________________________________*/
8ee2ff #include "pgpConfig.h"
84af5a
b00e2f #include "pgpSymmetricCipherPriv.h"
dd0d08 #include "pgpMem.h"
c72f8d #include "pgpErrors.h"
2e5430 #include "pgpUtilitiesPriv.h"
b8af5a
90adb8 #include "pgpOpaqueStructs.h"
9a3051 #include "pgpSDKBuildFlags.h"
6a43b4 #include "pgpCAST5.h"
5a1f0b #include "pgpDES3.h"
7e0d6d #include "pgpEnv.h"
f1af5a
a0d5ba #ifndef PGP_IDEA
1244a3 #error you must define PGP_IDEA one way or the other
a17454 #endif
f6af5a
7eea6e #if PGP_IDEA
b46332 #include "pgpIDEA.h"
e77454 #endif
bdaf5a
2ee603 #include "pgpSymmetricCipher.h"
a30e2f #include "pgpSymmetricCipherPriv.h"
d5af5a
4caf5a
fcaf5a
7360e9 struct PGPSymmetricCipherContext
06bb36 {
3fab51 #define kSymmetricContextMagic¤ ¤   0xABBADABA
f9fe45 ¤   PGPUInt32¤  ¤   ¤   ¤   magic;
29b586 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr;
f1db28 ¤   PGPCipherVTBL const *¤  vtbl;
380be7 ¤   void *¤ ¤   ¤   ¤   ¤   cipherData;
7bc1df ¤   PGPBoolean¤ ¤   ¤   ¤   keyInited;
af2fa1 } ;
5daf5a
e7af5a
2daf5a
c57920 /* Macros to access the member functions */
0993fc #define CallInitKey(cc, k) ((cc)->vtbl->initKey((cc)->cipherData, k))
8bdc07 #define CallEncrypt(cc, in, out) \
eb4ff4 ¤   ¤   ¤   ((cc)->vtbl->encrypt((cc)->cipherData, in, out))
23c485 #define CallDecrypt(cc, in, out) \
5b9d38 ¤   ¤   ¤   ((cc)->vtbl->decrypt((cc)->cipherData, in, out))
b8cb44 #define CallWash(cc, buf, len) \
6fd1a4 ¤   ¤   ¤   ((cc)->vtbl->wash((cc)->cipherData, buf, len))
e9af5a
28af5a
4716ea ¤   PGPBoolean
68bfbd pgpSymmetricCipherIsValid( const PGPSymmetricCipherContext * ref)
d3bb36 {
97984c ¤   PGPBoolean¤ valid¤  = FALSE;
2167c5 ¤
bdd2e5 ¤   valid¤  = IsntNull( ref ) && ref->magic¤ == kSymmetricContextMagic;
b667c5 ¤
000b09 ¤   return( valid );
b0efe6 }
dbbcc5 #define pgpValidateSymmetricCipher( s )¤¤   \
6a0d58 ¤   PGPValidateParam( pgpSymmetricCipherIsValid( s ) )
70af5a
b75c98 #if PGP_DEBUG
bb8c16 #define AssertSymmetricContextValid( ref )¤ \
--49a4 000cc3c77244010012c Page 2 of pgpSymmetricCipher.c
2cef40 ¤   pgpAssert( pgpSymmetricCipherIsValid( ref ) )
d4db21 #else
9082b4 #define AssertSymmetricContextValid( ref )
8d7454 #endif
11af5a
9daf5a
696c2c ¤   static PGPBoolean
d8e693 IsValidKeySizeAndAlgorithm(
673236 ¤   PGPCipherAlgorithm¤ algorithm,
d7851e ¤   PGPSize¤¤   ¤   ¤   keySize )
6cbb36 {
c5f611 ¤   PGPBoolean¤ ¤   ¤   ¤   valid¤  = FALSE;
20af06 ¤   PGPCipherVTBL const *¤  vtbl¤   = NULL;
6f67c5 ¤
751929 ¤   vtbl¤   = pgpCipherGetVTBL( algorithm );
cc87df ¤   if ( IsntNull( vtbl ) )
02c7a1 ¤   {
30616a ¤   ¤   valid¤  = keySize == vtbl->keysize;
a69371 ¤   }
8b67c5 ¤
7e0b09 ¤   return( valid );
2defe6 }
e3af5a
c6af5a
4eaf5a
ee66dd ¤   static PGPError
30112c sSymmetricCipherCreate(
4ece49 ¤   PGPMemoryMgrRef¤¤   ¤   ¤   ¤   memoryMgr,
4feff9 ¤   PGPCipherAlgorithm¤ ¤   ¤   ¤   algorithm,
1b386f ¤   PGPSymmetricCipherContextRef *¤ outRef )
2fbb36 {
b13610 ¤   PGPSymmetricCipherContextRef¤   ref¤= NULL;
5bc12c ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
ea67c5 ¤
c9f896 ¤   ref¤= (PGPSymmetricCipherContextRef)
a88f34 ¤   ¤   PGPNewData( memoryMgr, sizeof( *ref ),
f344fa ¤   ¤   ¤   ¤   0 | kPGPMemoryMgrFlags_Clear );
7167c5 ¤
85f439 ¤   if ( IsntNull( ref ) )
37c7a1 ¤   {
331611 ¤   ¤   PGPCipherVTBL const *¤  vtbl¤   = pgpCipherGetVTBL( algorithm );
278381 ¤   ¤   void *¤ ¤   ¤   ¤   ¤   cipherData;
db1b52 ¤   ¤
6aa634 ¤   ¤   ref->vtbl¤  = vtbl;
c587c7 ¤   ¤   ¤
0784b8 ¤   ¤   cipherData¤ = PGPNewData( memoryMgr,
181ef8 ¤   ¤   ¤   ¤   ¤   ¤   vtbl->context_size,
861d8c ¤   ¤   ¤   ¤   ¤   ¤   0 | kPGPMemoryMgrFlags_Clear);
a187c7 ¤   ¤   ¤
7d6b9a ¤   ¤   if ( IsntNull( cipherData ) )
395b34 ¤   ¤   {
4ebbf5 ¤   ¤   ¤   ref->cipherData¤= cipherData;¤
7668db ¤   ¤   ¤   ref->magic¤ ¤   = kSymmetricContextMagic;
c2446c ¤   ¤   ¤   ref->memoryMgr¤ = memoryMgr;
4ac1c2 ¤   ¤   ¤   ref->keyInited¤ = FALSE;
8e5403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
a30fe4 ¤   ¤   }
ca0e1d ¤   ¤   else
415b34 ¤   ¤   {
2aa163 ¤   ¤   ¤   PGPFreeData( ref );
63224d ¤   ¤   ¤   ref¤= NULL;
a6124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
180fe4 ¤   ¤   }
c89371 ¤   }
d20e24 ¤   else
31c7a1 ¤   {
ea17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
339371 ¤   }
9d67c5 ¤
23ebd9 ¤   *outRef¤= ref;
b5deb7 ¤   return( err );
ccefe6 }
--eba4 000a5c54ea84010012c Page 3 of pgpSymmetricCipher.c
e0af5a
1aaf5a
17af5a
2121ab ¤   PGPError·
97fbc1 PGPNewSymmetricCipherContext(
81ce49 ¤   PGPMemoryMgrRef¤¤   ¤   ¤   ¤   memoryMgr,
e6eff9 ¤   PGPCipherAlgorithm¤ ¤   ¤   ¤   algorithm,
c26afa ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   ¤   keySize,
33386f ¤   PGPSymmetricCipherContextRef *¤ outRef )
e4bb36 {
859372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
f767c5 ¤
303c76 ¤   PGPValidatePtr( outRef );
d73652 ¤   *outRef¤= NULL;
05ad91 ¤   PGPValidateMemoryMgr( memoryMgr );
03ae05 ¤   PGPValidateParam( IsValidKeySizeAndAlgorithm( algorithm, keySize ) );
0767c5 ¤
fdde5f ¤   err¤= sSymmetricCipherCreate( memoryMgr, algorithm, outRef );
0b67c5 ¤
494c5f ¤   pgpAssertErrWithPtr( err, *outRef );
dcdeb7 ¤   return( err );
82efe6 }
9caf5a
8caf5a
13af5a
41af5a
8c21ab ¤   PGPError·
c64932 PGPFreeSymmetricCipherContext( PGPSymmetricCipherContextRef ref )
2cbb36 {
d19372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
bed91c ¤   PGPMemoryMgrRef¤memoryMgr;
e067c5 ¤
25be82 ¤   pgpValidateSymmetricCipher( ref );
9767c5 ¤
ae91be ¤   memoryMgr = ref->memoryMgr;
a267c5 ¤
626d7a ¤   PGPWipeSymmetricCipher( ref );
bba12a ¤   PGPFreeData( ref->cipherData );
6467c5 ¤
9b4500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
54fa58 ¤   PGPFreeData( ref );
cf67c5 ¤
48deb7 ¤   return( err );
e2efe6 }
28af5a
63af5a
0eaf5a
f021ab ¤   PGPError·
4a103c PGPCopySymmetricCipherContext(
3289b6 ¤   PGPSymmetricCipherContextRef¤   ref,
db386f ¤   PGPSymmetricCipherContextRef *¤ outRef )
7abb36 {
81f40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
563ac0 ¤   PGPSymmetricCipherContextRef¤   newRef¤ = NULL;
7867c5 ¤
773c76 ¤   PGPValidatePtr( outRef );
9f3652 ¤   *outRef¤= NULL;
22be82 ¤   pgpValidateSymmetricCipher( ref );
4167c5 ¤
d7e9f1 ¤   newRef¤ = (PGPSymmetricCipherContextRef)
f8935b ¤   ¤   ¤   ¤   PGPNewData( ref->memoryMgr,
612b3e ¤   ¤   ¤   ¤   sizeof( *newRef ), 0 );
186c1a ¤   if ( IsntNull( newRef ) )
93c7a1 ¤   {
acdbf6 ¤   ¤   void *¤ ¤   newData;
0bbf9b ¤   ¤   PGPUInt32¤  dataSize¤   = ref->vtbl->context_size;
de1b52 ¤   ¤
ea1d8d ¤   ¤   *newRef¤= *ref;
e61b52 ¤   ¤
638a9a ¤   ¤   newData¤= PGPNewData( ref->memoryMgr,
5b3dd4 ¤   ¤   ¤   ¤   ¤   ¤   dataSize, 0 );
a5680d ¤   ¤   if ( IsntNull( newData ) )
--eab5 00089fc6a8a4010012c Page 4 of pgpSymmetricCipher.c
e35b34 ¤   ¤   {
41e45f ¤   ¤   ¤   pgpCopyMemory( ref->cipherData, newData, dataSize );
9760ab ¤   ¤   ¤   newRef->cipherData¤ = newData;
2a0fe4 ¤   ¤   }
c90e1d ¤   ¤   else
3e5b34 ¤   ¤   {
38a062 ¤   ¤   ¤   PGPFreeData( newRef );
53124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
fb0fe4 ¤   ¤   }
9a9371 ¤   }
590e24 ¤   else
d8c7a1 ¤   {
5017a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
ff9371 ¤   }
8767c5 ¤
74cdaf ¤   *outRef¤= newRef;
6d4c5f ¤   pgpAssertErrWithPtr( err, *outRef );
c8deb7 ¤   return( err );
53efe6 }
6daf5a
68af5a
0421ab ¤   PGPError·
98cc35 PGPInitSymmetricCipher(
f689b6 ¤   PGPSymmetricCipherContextRef¤   ref,
ae1475 ¤   const void *¤   ¤   ¤   ¤   ¤   key )
dcbb36 {
2126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7267c5 ¤
41be82 ¤   pgpValidateSymmetricCipher( ref );
8c74fd ¤   PGPValidatePtr( key );
b167c5 ¤
7c4d2f ¤   CallInitKey( ref, key );
741025 ¤   ref->keyInited¤ = TRUE;
7f67c5 ¤
3edeb7 ¤   return( err );
0befe6 }
70af5a
52af5a
61af5a
6c21ab ¤   PGPError·
79acb3 PGPWipeSymmetricCipher( PGPSymmetricCipherContextRef ref )
31bb36 {
e826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7f67c5 ¤
d2be82 ¤   pgpValidateSymmetricCipher( ref );
5067c5 ¤
bdfa53 ¤   pgpClearMemory( ref->cipherData, ref->vtbl->context_size);
d847fc ¤   ref->keyInited¤ = FALSE;
6e67c5 ¤
6cdeb7 ¤   return( err );
91efe6 }
2aaf5a
01af5a
e9af5a
2b21ab ¤   PGPError·
097e60 PGPWashSymmetricCipher(
6d89b6 ¤   PGPSymmetricCipherContextRef¤   ref,
a09682 ¤   void const *¤   ¤   ¤   ¤   ¤   buf,
2bd22d ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   ¤   len)
8cbb36 {
4b26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
1367c5 ¤
8fbe82 ¤   pgpValidateSymmetricCipher( ref );
8ba9c8 ¤   PGPValidatePtr( buf );
8a67c5 ¤
2c2dd6 ¤   CallWash( ref, buf, len );
1c5354 ¤   ref->keyInited = TRUE;
c967c5 ¤
7edeb7 ¤   return( err );
2eefe6 }
2faf5a
89af5a
--4531 000fa06f85d4010012c Page 5 of pgpSymmetricCipher.c
e0af5a
e721ab ¤   PGPError·
e4788d PGPSymmetricCipherEncrypt(
6089b6 ¤   PGPSymmetricCipherContextRef¤   ref,
95f01c ¤   const void *¤   ¤   ¤   ¤   ¤   in,
f26ee7 ¤   void *¤ ¤   ¤   ¤   ¤   ¤   ¤   out )
adbb36 {
bd26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a867c5 ¤
98be82 ¤   pgpValidateSymmetricCipher( ref );
543bf7 ¤   PGPValidatePtr( in );
4e254f ¤   PGPValidatePtr( out );
7faf5a
b35192 ¤   if ( ref->keyInited )
29c7a1 ¤   {
9e3fdb ¤   ¤   CallEncrypt( ref, in, out );
d39371 ¤   }
110e24 ¤   else
6ac7a1 ¤   {
553cb2 ¤   ¤   err¤= kPGPError_ImproperInitialization;
b29371 ¤   }
b967c5 ¤
5c67c5 ¤
c12d68 ¤   return( kPGPError_NoErr );
bbefe6 }
4aaf5a
0fae30 ¤   ¤   ¤   ¤   ¤
8521ab ¤   PGPError·
9f921c PGPSymmetricCipherDecrypt(
7189b6 ¤   PGPSymmetricCipherContextRef¤   ref,
e2f01c ¤   const void *¤   ¤   ¤   ¤   ¤   in,
fe6ee7 ¤   void *¤ ¤   ¤   ¤   ¤   ¤   ¤   out )
d9bb36 {
5a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
4a67c5 ¤
b2be82 ¤   pgpValidateSymmetricCipher( ref );
ee3bf7 ¤   PGPValidatePtr( in );
52254f ¤   PGPValidatePtr( out );
42af5a
4d5192 ¤   if ( ref->keyInited )
6fc7a1 ¤   {
081c6e ¤   ¤   CallDecrypt( ref, in, out );
999371 ¤   }
c90e24 ¤   else
05c7a1 ¤   {
c83cb2 ¤   ¤   err¤= kPGPError_ImproperInitialization;
cf9371 ¤   }
ef67c5 ¤
c167c5 ¤
e12d68 ¤   return( kPGPError_NoErr );
f7efe6 }
ccaf5a
a8ae30 ¤   ¤   ¤   ¤   ¤
c921ab ¤   PGPError·
a50825 PGPGetSymmetricCipherSizes(
3d89b6 ¤   PGPSymmetricCipherContextRef¤   ref,
336b5d ¤   PGPSize *¤  ¤   ¤   ¤   ¤   ¤   keySizePtr,
e7f1cc ¤   PGPSize *¤  ¤   ¤   ¤   ¤   ¤   blockSizePtr )
00bb36 {
9726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
55614e ¤   PGPSize¤¤   blockSize¤  = 0;
2f1971 ¤   PGPSize¤¤   keySize¤¤   = 0;
1667c5 ¤
064106 ¤   if ( IsntNull( keySizePtr ) )
71c087 ¤   ¤   *keySizePtr¤= 0;
afa4da ¤   if ( IsntNull( blockSizePtr ) )
c3f145 ¤   ¤   *blockSizePtr¤  = 0;
7c1b52 ¤   ¤
78be82 ¤   pgpValidateSymmetricCipher( ref );
7e5c22 ¤   PGPValidateParam( IsntNull( blockSizePtr ) || IsntNull( keySizePtr ) );
adaf5a
fa7170 ¤   blockSize¤  = ref->vtbl->blocksize;
--0a0a 00082dea3a34010012c Page 6 of pgpSymmetricCipher.c
b52c65 ¤   keySize¤¤   = ref->vtbl->keysize;
491b52 ¤   ¤
6aa4da ¤   if ( IsntNull( blockSizePtr ) )
4dc7a1 ¤   {
f46049 ¤   ¤   pgpAssertAddrValid( blockSizePtr, PGPUInt32 );
19b9be ¤   ¤   *blockSizePtr¤  = blockSize;
999371 ¤   }
5067c5 ¤
ee4106 ¤   if ( IsntNull( keySizePtr ) )
fac7a1 ¤   {
ebe5f9 ¤   ¤   pgpAssertAddrValid( keySizePtr, PGPUInt32 );
d3ae18 ¤   ¤   *keySizePtr¤= keySize;
319371 ¤   }
f467c5 ¤
dedeb7 ¤   return( err );
dcefe6 }
14af5a
a2af5a
95af5a
6b5947 ¤   PGPMemoryMgrRef
fce4bf pgpGetSymmetricCipherMemoryMgr( PGPSymmetricCipherContextRef¤   ref)
9bbb36 {
2a9c07 ¤   AssertSymmetricContextValid( ref );
9067c5 ¤
f1be9b ¤   return( ref->memoryMgr );
5cefe6 }
6caf5a
1aaf5a
16d60f static PGPCipherVTBL const * const sCipherList[] =
44bb36 {
0cea6e #if PGP_IDEA
9bc9dd ¤   &cipherIDEA,
1e7454 #endif
b615ff ¤   &cipher3DES,
1db01d ¤   &cipherCAST5
ac82f7 };
a9dd20 #define kNumCiphers¤ ( sizeof( sCipherList ) / sizeof( sCipherList[ 0 ] ) )
b0af5a
6faf5a
b1108d ¤   PGPUInt32
f78782 pgpCountSymmetricCiphers( void )
eabb36 {
26e01d ¤   return( kNumCiphers );
c0efe6 }
58af5a
40af5a
a518cc ¤   PGPCipherVTBL const *
297233 pgpCipherGetVTBL (PGPCipherAlgorithm¤   algorithm)
6abb36 {
81447d ¤   const PGPCipherVTBL *¤  vtbl¤   = NULL;
d5d421 ¤   PGPUInt32¤  ¤   ¤   ¤   algIndex;
6667c5 ¤
70520b ¤   for( algIndex = 0; algIndex < kNumCiphers; ++algIndex )
88c7a1 ¤   {
49c852 ¤   ¤   if ( sCipherList[ algIndex ]->algorithm == algorithm )
c25b34 ¤   ¤   {
749b45 ¤   ¤   ¤   vtbl¤   = sCipherList[ algIndex ];
92cdcb ¤   ¤   ¤   break;
7b0fe4 ¤   ¤   }
529371 ¤   }
9067c5 ¤
dd902e ¤   return vtbl;
07efe6 }
edaf5a
8caf5a
fdaf5a
b538e5 /*
bd4ae5 ·* Choose cipher for key encryption. ·Not used for V2-V3 compatible keys.
4df971 ·* Override pgpenv defaults with our own default.
ec495d ·*/
a8df79 PGPCipherVTBL const *
82c470 pgpCipherDefaultKey(PGPEnv const *env)
--db51 001817a94c44010012c Page 7 of pgpSymmetricCipher.c
2cbb36 {
642dbf ¤   PGPInt32¤   ¤   ¤   ciphernum;
56cc07 ¤   PGPInt32¤   ¤   ¤   cipherpri;
411eae ¤   const PGPCipherVTBL *vtbl;
a667c5 ¤
8646ac ¤   ciphernum = pgpenvGetInt (env, PGPENV_CIPHER, &cipherpri, NULL);
dcaf77 ¤   if (cipherpri < PGPENV_PRI_CONFIG)
515005 ¤   ¤   ciphernum = kPGPCipherAlgorithm_CAST5;
7f67c5 ¤
086e93 ¤   vtbl = pgpCipherGetVTBL ( (PGPCipherAlgorithm)ciphernum);
f833b9 ¤   if( IsNull( vtbl ) )
fdc7a1 ¤   {
5fa670 ¤   ¤   pgpDebugMsg( "pgpCipherDefaultKey(): Cipher algorithm not found" );
09c591 ¤   ¤   vtbl = pgpCipherGetVTBL ( kPGPCipherAlgorithm_CAST5 );
959371 ¤   }
6267c5 ¤
ba7543 ¤   return( vtbl );
08efe6 }
15af5a
9326a8 /* Use this for old pre-PGP5 key encryption; default to backwards compat */
a6df79 PGPCipherVTBL const *
ea94ad pgpCipherDefaultKeyV3(PGPEnv const *env)
79bb36 {
502dbf ¤   PGPInt32¤   ¤   ¤   ciphernum;
4ecc07 ¤   PGPInt32¤   ¤   ¤   cipherpri;
6e1eae ¤   const PGPCipherVTBL *vtbl;
c9af5a
b246ac ¤   ciphernum = pgpenvGetInt (env, PGPENV_CIPHER, &cipherpri, NULL);
fbaf77 ¤   if (cipherpri < PGPENV_PRI_CONFIG)
30112b ¤   ¤   ciphernum = kPGPCipherAlgorithm_IDEA;
f71b52 ¤   ¤
e4fbdc ¤   vtbl = pgpCipherGetVTBL ( (PGPCipherAlgorithm) ciphernum);
df33b9 ¤   if( IsNull( vtbl ) )
24c7a1 ¤   {
7dcb2d ¤   ¤   pgpDebugMsg( "pgpCipherDefaultKeyV3(): Cipher algorithm not found" );
422c14 ¤   ¤   vtbl = pgpCipherGetVTBL ( kPGPCipherAlgorithm_IDEA );
e39371 ¤   }
b867c5 ¤
e27543 ¤   return( vtbl );
13efe6 }
b3af5a
15af5a
d4af5a
cbaf5a
16af5a
85af5a
d8af5a
e8af5a
3aaf5a
feaf5a
08af5a
3aaf5a
83af5a
90af5a
4faf5a
dfaf5a
9eaf5a
79af5a
1aaf5a
57af5a
b2af5a
21af5a
677e4d /*__Editor_settings____
67af5a
fd4126 ¤   Local Variables:
dc7b17 ¤   tab-width: 4
190e6c ¤   End:
de5f8c ¤   vi: ts=4 sw=4
b19e9b ¤   vim: si
81d062 _____________________*/
--aaec 0002c85ba124010012d Page 1 of pgpSymmetricCipherPriv.h
a70335 /*____________________________________________________________________________
afb97b ¤   pgpSymmetricCipherPriv.h
1967c5 ¤
cfc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
484b0f ¤   All rights reserved.
d667c5 ¤
5c67c5 ¤
8daf5a
a8fc69 ¤   $Id: pgpSymmetricCipherPriv.h,v 1.9.10.1 1998/11/12 03:21:21 heller Exp $
57f7f7 ____________________________________________________________________________*/
cfec4a #ifndef Included_pgpSymmetricCipherPriv_h¤  /* [ */
ca1fc1 #define Included_pgpSymmetricCipherPriv_h
e5af5a
d5c5d5 #include "pgpBase.h"
a6adb8 #include "pgpOpaqueStructs.h"
9ce603 #include "pgpSymmetricCipher.h"
64af5a
41af5a
6299c6 PGP_BEGIN_C_DECLARATIONS
0faf5a
1ead1f #define¤kPGPNumPossibleCipherAlgorithms¤¤   3
07af5a
430335 /*____________________________________________________________________________
21dda6 ¤   a "virtual function table" for a cipher class.
7767c5 ¤
b5ff65 ¤   Use of this structure is discouraged. Use formal API where possible.
f0f7f7 ____________________________________________________________________________*/
c7af5a
e5db2e struct PGPCipherVTBL
6cbb36 {
35a9a2 ¤   char const *¤   ¤   name;
cfeaaf ¤   PGPCipherAlgorithm¤ algorithm;
112cf9 ¤   PGPSize¤¤   ¤   ¤   blocksize;
8bf95b ¤   PGPSize¤¤   ¤   ¤   keysize;
9d46a4 ¤   PGPSize¤¤   ¤   ¤   context_size;
615f19 ¤   PGPSize¤¤   ¤   ¤   context_align;
c0af5a
1e0d42 ¤   void¤   ¤   ¤   (*initKey)(void *priv, void const *key);
680fd8 ¤   void¤   ¤   ¤   (*encrypt)(void *priv, void const *in, void *out);
937f34 ¤   void¤   ¤   ¤   (*decrypt)(void *priv, void const *in, void *out);
a7d7fd ¤   void¤   ¤   ¤   (*wash)(void *priv, void const *buf, PGPSize len);
f282f7 };
9faf5a
c67e96 PGPBoolean¤ pgpSymmetricCipherIsValid( const PGPSymmetricCipherContext * ref);
cdaf5a
1caf5a
51d925 PGPCipherVTBL const ·*¤ pgpCipherGetVTBL (PGPCipherAlgorithm alg);
53af5a
7a2e9b PGPUInt32¤  pgpCountSymmetricCiphers( void );
44af5a
dc87f4 PGPMemoryMgrRef¤pgpGetSymmetricCipherMemoryMgr(
dedaab ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSymmetricCipherContextRef ref);
4faf5a
f03c0f /* Get the default ciphers for operations */
4c0698 PGPCipherVTBL const ··*¤pgpCipherDefaultKey( PGPEnv const *env);
0cc702 PGPCipherVTBL const ·*¤ pgpCipherDefaultKeyV3( PGPEnv const *env);
f3af5a
6de481 /* Static buffer size for keys */
771c5e #define PGP_CIPHER_MAXKEYSIZE¤  32¤ /* 256 bits */
dfaf5a
dfaf5a
811254 PGP_END_C_DECLARATIONS
02af5a
454b8e #endif /* ] Included_pgpSymmetricCipherPriv_h */
caaf5a
2caf5a
d47e4d /*__Editor_settings____
24af5a
b34126 ¤   Local Variables:
727b17 ¤   tab-width: 4
350e6c ¤   End:
2c5f8c ¤   vi: ts=4 sw=4
--6e8c 00133d4bd534010012d Page 2 of pgpSymmetricCipherPriv.h
b99e9b ¤   vim: si
33d062 _____________________*/
--bbe1 001db2c07804010012e Page 1 of Makefile.in
5ea601 #
d86269 # priv/crypto/compress/
05a601 #
fb6d04 # $Id: Makefile.in,v 1.2 1997/05/04 10:30:05 mhw Exp $
60a601 #
ebaf5a
70072c OBJS=¤  pgpZInflate.o
a44f38 PRIVHDRS= pgpCompress.h pgpZInflate.h
efaf5a
97b7a3 all:: DONE
dbaf5a
--d5c2 0014bb3d2c64010012f Page 1 of pgpCompress.h
bc38e5 /*
d735c3 ·* pgpCompress.h -- this defines the compression and decompression
07931f ·* functions for PGP.. It provides a generalized interface to the
b4a59a ·* compression modules, and keeps applications from requiring
5535e1 ·* knowledge of all the different types of compression that may be
6e87d9 ·* supported.
2c775e ·*
ba8190 ·* This is a Public API Function Header.
8c775e ·*
683337 ·* $Id: pgpCompress.h,v 1.2 1997/05/13 01:18:57 mhw Exp $
d7495d ·*/
a3af5a
8c1860 #ifndef Included_pgpCompress_h
dc6f93 #define Included_pgpCompress_h
2baf5a
85fa74 /* Defintions for known compression algorithms */
78af5a
74d0ba #define PGP_COMPRESSALG_ZIP 1
9daf5a
4ba34b #endif /* Included_pgpCompress_h */
--237d 000b2243bcf40100130 Page 1 of pgpZInflate.c
bc38e5 /*
ca662c ·* inflate.c -- Not copyrighted 1992,1993 by Mark Adler
d668c8 ·* Latest hacking on this version by Colin Plumb
e3ee1d ·* version p3, 19 Oct 1995
a6775e ·*
3ef8da ·* $Id: pgpZInflate.c,v 1.22 1998/06/01 21:03:04 hal Exp $
d6495d ·*/
1eaf5a
2faf5a
6138e5 /*
7b87cd ·* You can do whatever you like with this source file, though I would
69222a ·* prefer that if you modify it and redistribute it that you include
ec4459 ·* comments to that effect with your name and the date. ·Thank you.
39775e ·*
3e9191 ·* History:
f45605 ·* vers ···date ·········who ··········what
8da94a ·* ---- ·--------- ·-------------- ·------------------------------------
f2fd1c ·* ·a ···~~ Feb 92 ·M. Adler ·······used full (large, one-step) lookup table
b7606f ·* ·b1 ··21 Mar 92 ·M. Adler ·······first version with partial lookup tables
8a4e8a ·* ·b2 ··21 Mar 92 ·M. Adler ·······fixed bug in fixed-code blocks
02cf9a ·* ·b3 ··22 Mar 92 ·M. Adler ·······sped up match copies, cleaned up some
68673c ·* ·b4 ··25 Mar 92 ·M. Adler ·······added prototypes; removed window[] (now
63c502 ·* ·································is the responsibility of unzip.h--also
eea5f3 ·* ·································changed name to slide[]), so needs diffs
dbe3de ·* ·································for unzip.c and unzip.h (this allows
158abe ·* ·································compiling in the small model on MSDOS);
24205d ·* ·································fixed cast of q in huft_build();
25e9e1 ·* ·b5 ··26 Mar 92 ·M. Adler ·······got rid of unintended macro recursion.
240a05 ·* ·b6 ··27 Mar 92 ·M. Adler ·······got rid of nextbyte() routine. ·fixed
fcf4d9 ·* ·································bug in inflate_fixed().
e8eeda ·* ·c1 ··30 Mar 92 ·M. Adler ·······removed lbits, dbits environment variables.
ef9ce5 ·* ·································changed BMAX to 16 for explode. ·Removed
efc851 ·* ·································OUTB usage, and replaced it with flush()--
d889e6 ·* ·································this was a 20% speed improvement! ·Added
970882 ·* ·································an explode.c (to replace unimplode.c) that
8fae9c ·* ·································uses the huft routines here. ·Removed
cfda8f ·* ·································register union.
2b6b9e ·* ·c2 ···4 Apr 92 ·M. Adler ·······fixed bug for file sizes a multiple of 32k.
880c9d ·* ·c3 ··10 Apr 92 ·M. Adler ·······reduced memory of code tables made by
0a57dd ·* ·································huft_build significantly (factor of two to
492513 ·* ·································three).
a81ab4 ·* ·c4 ··15 Apr 92 ·M. Adler ·······added NOMEMCPY do kill use of memcpy().
0fd30c ·* ·································worked around a Turbo C optimization bug.
874556 ·* ·c5 ··21 Apr 92 ·M. Adler ·······added the WSIZE #define to allow reducing
ed5bea ·* ·································the 32K window size for specialized
027092 ·* ·································applications.
bce785 ·* ·c6 ··31 May 92 ·M. Adler ·······added some typecasts to eliminate warnings
c4b21c ·* ·c7 ··27 Jun 92 ·G. Roelofs ·····added some more typecasts (444: ·MSC bug).
84754e ·* ·c8 ···5 Oct 92 ·J-l. Gailly ····added ifdef'd code to deal with PKZIP bug.
e9dedc ·* ·c9 ···9 Oct 92 ·M. Adler ·······removed a memory error message (~line 416).
5ccce2 ·* ·c10 ·17 Oct 92 ·G. Roelofs ·····changed ULONG/UWORD/byte to ulg/ush/uch,
883910 ·* ·································removed old inflate, renamed inflate_entry
d9e120 ·* ·································to inflate, added Mark's fix to a comment.
df91ec ·* ·c11 ··2 Jan 93 ·M. Adler ·······fixed bug in detection of incomplete
a2af14 ·* ·································tables, and removed assumption that EOB is
72be81 ·* ·································the longest code (bad assumption).
490a52 ·* ·c12 ··3 Jan 93 ·M. Adler ·······make tables for fixed blocks only once.
5b5ca2 ·* ·c13 ··5 Jan 93 ·M. Adler ·······allow all zero length codes (pkzip 2.04c
e96f27 ·* ·································outputs one zero length code for an empty
993d26 ·* ·································distance tree).
be8dfd ·* ·c14 ·12 Mar 93 ·M. Adler ·······made inflate.c standalone with the
bea561 ·* ·································introduction of inflate.h.
6ae16a ·* ·d0 ··25 Apr 93 ·M. Adler ·······several speedups in inflate_codes of
f8fa13 ·* ·································almost 20% (suggested by Urban Mueller)--
ba35df ·* ·································now requires the use of backfill.[ch]
7bb4fb ·* ·d1 ···4 May 93 ·M. Adler ·······deleted extraneous statement in cheap loop,
6e3353 ·* ·································optimized common copy a little more.
01fe5f ·* ·d2 ···5 May 93 ·M. Adler ·······calculate number of cheap loops, a few
a6983b ·* ·································other small optimizations.
5e3559 ·* ·p1 ·····Nov 93 ·C. Plumb ·······Adpated to be able to suspend itself.
91d78b ·* ·································Pretty massive reorganization.
b294cf ·* ·································Many comments added.
--2e94 0002ab4454440100130 Page 2 of pgpZInflate.c
23c573 ·* ·p2 ··18 Oct 95 ·C. Plumb ·······Improved interface some more. ·Now
910d13 ·* ·································nicely re-entrant. ·Still more comments.
341aae ·* ·p3 ··19 Oct 95 ·C. Plumb ·······Changed infInflate core function so that
914dee ·* ·································it sucks the input completely dry before
c17580 ·* ·································returning. ·This gets rid of the old ad-hoc
27138c ·* ·································technique for flushing out the last little
44a53c ·* ·································bit of a compressed file by padding it
202c4d ·* ·································with some dummy data, which was ugly.
11495d ·*/
85af5a
caaf5a
ad38e5 /*
a55c41 ·* Inflate deflated (PKZIP's method 8 compressed) data. ·The compression
5e100f ·* method searches for as much of the current string of bytes (up to a
3ad30a ·* length of 258) in the previous 32K bytes. ·If it doesn't find any
fe4e9c ·* matches (of at least length 3), it codes the next byte. ·Otherwise, it
da3696 ·* codes the length of the matched string and its distance backwards from
14b234 ·* the current position. ·There is a single Huffman code that codes both
aa4072 ·* single bytes (called "literals") and match lengths. ·A second Huffman
ce8b77 ·* code codes the distance information, which follows a length code. ·Each
d12ff1 ·* length or distance code actually represents a base value and a number
7784b3 ·* of "extra" (sometimes zero) bits to get to add to the base value. ·At
532006 ·* the end of each deflated block is a special end-of-block (EOB) literal/
2de641 ·* length code. ·The decoding process is basically: get a literal/length
3df58b ·* code; if EOB then done; if a literal, emit the decoded byte; if a
e6d58b ·* length then get the distance and emit the referred-to bytes from the
fc325c ·* sliding window of previously emitted data.
78775e ·*
bbf3a4 ·* There are (currently) three kinds of inflate blocks: stored, fixed, and
615cc0 ·* dynamic. ·The compressor outputs a chunk of data at a time and decides
2a31a6 ·* which method to use on a chunk-by-chunk basis. ·A chunk might typically
80f12a ·* be 32K to 64K, uncompressed. ·If the chunk is uncompressible, then the
aff8cf ·* "stored" method is used. ·In this case, the bytes are simply stored as
10a37f ·* is, eight bits per byte, with none of the above coding. ·The bytes are
253a48 ·* preceded by a (16-bit) count, since there is no longer an EOB code.
45775e ·*
cf372b ·* If the data is compressible, then either the fixed or dynamic methods
46f2f8 ·* are used. ·In the dynamic method, the compressed data is preceded by
3dfb38 ·* an encoding of the literal/length and distance Huffman codes that are
e061a4 ·* to be used to decode this block. ·The representation is itself Huffman
4e66ef ·* coded, and so is preceded by a description of that code. ·These code
2bc9d3 ·* descriptions take up a little space, and so for small blocks, there is
cd692b ·* a predefined set of codes, called the fixed codes. ·The fixed method is
662e9b ·* used if the block ends up smaller that way (usually for quite small
72b565 ·* chunks); otherwise the dynamic method is used. ·In the latter case, the
20f0c2 ·* codes are customized to the probabilities in the current block and so
ffba87 ·* can code it much better than the pre-determined fixed codes can.
e9775e ·*
199c4d ·* The Huffman codes themselves are decoded using a mutli-level table
9f215d ·* lookup, in order to maximize the speed of decoding plus the speed of
50a2f7 ·* building the decoding tables. ·See the comments below that precede the
6dc340 ·* LBITS and DBITS tuning parameters.
73495d ·*/
d0af5a
18af5a
c938e5 /*
4a2d17 ·* ·Notes beyond the 1.93a appnote.txt:
65775e ·*
e19efa ·* ·1. Distance pointers never point before the beginning of the output
60f36e ·* ····stream.
c3e60c ·* ·2. Distance pointers can point back across blocks, up to 32k away.
5b4490 ·* ·3. There is an implied maximum of 7 bits for the bit length table and
588151 ·* ····15 bits for the actual data.
770725 ·* ·4. If only one code exists, then it is encoded using one bit. ·(Zero
a45dca ·* ····would be more efficient, but perhaps a little confusing.) ·If two
28bd7c ·* ····codes exist, they are coded using one bit each (0 and 1).
88b82e ·* ·5. There is no way of sending zero distance codes--a dummy must be
f1482c ·* ····sent if there are none. ·(History: a pre 2.0 version of PKZIP would
20cff8 ·* ····store blocks with no distance codes, but this was discovered to be
06af81 ·* ····too harsh a criterion.) ·Valid only for 1.93a. ·2.04c does allow
e4c403 ·* ····zero distance codes, which is sent as one code of zero bits in
2ac23f ·* ····length.
--b292 0004e3d02de40100130 Page 3 of pgpZInflate.c
cf297b ·* ·6. There are up to 286 literal/length codes. ·Code 256 represents the
15c760 ·* ····end-of-block. ·Note however that the static length tree defines
de1a2f ·* ····288 codes just to fill out the Huffman codes. ·Codes 286 and 287
d8a939 ·* ····cannot be used though, since there is no length base or extra bits
c8ef27 ·* ····defined for them. ·Similarily, there are up to 30 distance codes.
715113 ·* ····However, static trees define 32 codes (all 5 bits) to fill out the
f4c029 ·* ····Huffman codes, but the last two had better not show up in the data.
736331 ·* ·7. Unzip can check dynamic Huffman blocks for complete code sets.
d20ac0 ·* ····The exception is that a single code would not be complete (see #4).
cafc51 ·* ·8. The five bits following the block type is really the number of
0d6f2c ·* ····literal codes sent minus 257.
6f9ce1 ·* ·9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
e31345 ·* ····(1+6+6). ·Therefore, to output three times the length, you output
36804e ·* ····three codes (1+1+1), whereas to output four times the same length,
2467f1 ·* ····you only need two codes (1+3). ·Hmm.
3f530f ·* 10. In the tree reconstruction algorithm, Code = Code + Increment
b844f2 ·* ····only if BitLength(i) is not zero. ·(Pretty obvious.)
27ed30 ·* 11. Correction: 4 Bits: # of Bit Length codes - 4 ····(4 - 19)
ff1c90 ·* 12. Note: length code 284 can represent 227-258, but length code 285
1cfeec ·* ····really is 258. ·The last length deserves its own, short code
2949a4 ·* ····since it gets used a lot in very redundant files. ·The length
b58d4d ·* ····258 is special since 258 - 3 (the min match length) is 255.
0477ee ·* 13. The literal/length and distance code bit lengths are read as a
30c4ce ·* ····single stream of lengths. ·It is possible (and advantageous) for
22638f ·* ····a repeat code (16, 17, or 18) to go across the boundary between
bd8300 ·* ····the two sets of lengths.
70495d ·*/
c3af5a
1ee2ff #include "pgpConfig.h"
c3af5a
e6324c #include <string.h>
20af5a
bfa146 #include "pgpDebug.h"
460d08 #include "pgpMem.h"
cdd11f #include "pgpUsuals.h"
52f4ef #include "pgpZInflate.h"
46af5a
3f4890 /* Increasing these only wastes space, so they can be changed if necessary */
b65028 typedef PGPUInt16 ush;
dc0fae typedef PGPUInt32 ulg;
6eaf5a
c7af5a
c17505 typedef struct huft¤huft;
5c8b84 /* Private context structure for use by all functions. */
f36ee7 struct InflateContext {
2c8a97 ¤   PGPContextRef¤  context;
a90f10 ¤   /* Major state information */
0b9391 ¤   int state;
10aa53 ¤   int substate;
36a23a ¤   int lastblock;
c9af5a
85e446 ¤   /* static trees*/
a7af21 ¤   huft *¤ ¤   fixed_tl;
5e69e3 ¤   huft *¤ ¤   fixed_td;
d86dc9 ¤   PGPUInt32¤  fixed_bl;
94ab0b ¤   PGPUInt32¤  fixed_bd;
b9af5a
e0f4d8 ¤   /* Output-related information */
eedfc6 ¤   unsigned char *slide;¤  /* Circular output buffer */
e7c6c6 ¤   unsigned char *slideend;
a88186 ¤   unsigned slidelen; ·····/* slideend-slide - MUST BE POWER OF 2 */
edb9fc ¤   unsigned slidemask;¤/* slidelen-1 */
3817b7 ¤   unsigned char *outptr;¤ /* Pointer into slide */
984f77 ¤   unsigned char const *readptr;¤  /* Pointer into slide for reading */
35af5a
1d2e61 ¤   /* Input-related information */
e76e82 ¤   unsigned char const *inptr;¤/* Input pointer */
142327 ¤   int inlen;¤ ¤   /* Input length */
5a0793 ¤   ulg bitbuffer;
2eeee1 ¤   unsigned bufbits;
faaf5a
4e7023 ¤   /* The literal/length tree - also used for the bit-length tree */
--47c6 00006046cbe40100130 Page 4 of pgpZInflate.c
0a67da ¤   huft *tree1;
6609e6 ¤   unsigned bits1;
beaf5a
acd045 ¤   /* The distance tree */
3c88be ¤   huft *tree2;
7de682 ¤   unsigned bits2;
09af5a
b32f6c ¤   /* Encoded huffman tree */
1f4041 ¤   unsigned char bitlen[286+30];
bbaf5a
7b9b0c ¤   /* For dynamic trees */
ce4ec7 ¤   unsigned bitlengths;
9ee3fe ¤   unsigned litcodes;
b95378 ¤   unsigned distcodes;
57af5a
b447b3 ¤   /* Used in various places */
1a31d6 ¤   huft const *t;
90df82 ¤   unsigned copylen;
8d13fb ¤   int distbase;
ccf43a ¤   int numbits;¤   /* # of bits in dyn. tree repeat and after dist. code*/
349a24 ¤   unsigned index;¤/* Position in dynamic tree bit lengths we've read to*/
be7457 ¤   DEBUG_STRUCT_CONSTRUCTOR( InflateContext )
0a82f7 };
7baf5a
842b10 /* Options for behaviour */
ec418d #ifndef SECURE
c1e72b #define SECURE 1¤   /* Wipe memory before freeing it? */
9c7454 #endif
6daf5a
cbfa0e #ifndef WSIZE
4ed112 #define WSIZE 32768¤/* Window size - 32768 for PKZIP compatibility */
6c7454 #endif
a1af5a
8fbf87 #ifndef STRICT
0d3068 #define STRICT 1¤   /* Require unused bits to be zero? */
c87454 #endif
abaf5a
c038e5 /*
8a2c2a ·* Huffman code lookup table entry--this entry is four bytes for machines
929d98 ·* that have 16-bit pointers (e.g. PC's in the small or medium model).
6a1fcc ·* Valid extra bits are 0..13. ·e == 32 is EOB (end of block), e == 16
57d186 ·* means that v is a literal, e < 0 means that v is a pointer to the next
f5ea10 ·* table, which codes -e bits, and lastly e == -128 indicates an unused
965a43 ·* code. ·If a code with e == -128 is looked up, this implies an error in
137a24 ·* the data.
02495d ·*/
aa580d struct huft {
87e29a ¤   union {
dec86c ¤   ¤   struct {
6a2ee9 ¤   ¤   ¤   signed char exop; /* # of extra bits or operation */
f392aa ¤   ¤   ¤   char bits;¤ /* # of bits in this code/subcode */
0dcb62 ¤   ¤   } what;
4b9ea3 ¤   ¤   char *pad;¤ /* pad structure to a power of 2 (4 bytes for*/
8d17c0 ¤   } word;¤¤   ¤   /* ·16-bit, 8 bytes for 32-bit machines) */
dce29a ¤   union {
ee0c48 ¤   ¤   ush base;¤  /* literal, length base, or distance base */
8fe450 ¤   ¤   huft *next; /* pointer to next level of table */
e7b395 ¤   } more;
ad82f7 };
7baf5a
c18fbf #define base more.base
2116ec #define next more.next
26057e #define exop word.what.exop
f7b7ca #define bits word.what.bits
adaf5a
bdaf5a
ae3c49 /* Function prototypes */
d84e50 #ifndef OF
25e445 # ·if defined(__STDC__) || defined(__cplusplus)
3e2bf1 # ···define OF(a) a
1dd33c # ·else
06da44 # ···define OF(a) ()
--39ff 00053202fa540100130 Page 5 of pgpZInflate.c
f9bf38 # ·endif
fa7454 #endif
26af5a
a62d81 static int huft_build OF(( PGPContextRef context,
649e65 ¤   ¤   ¤   ¤   unsigned char const *, unsigned, unsigned,
e9664b ·················ush const *, ush const *, huft **,
0fcfb9 ··················unsigned *));
01fbaa static int huft_free OF(( PGPContextRef context, huft *));
30af5a
d238e5 /*
8bf735 ·* The inflate algorithm uses a sliding 32K byte window on the uncompressed
387bbd ·* stream to find repeated byte strings. ·This is implemented here as a
a67169 ·* circular buffer. ·The index is updated simply by incrementing and then
f5f580 ·* and'ing with 0x7fff (32K-1).
26495d ·*/
61af5a
422b06 /* Tables for deflate from PKZIP's appnote.txt. */
5d8582 static unsigned const border[] = { /* Order of the bit length code lengths */
f32351 ¤   16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
a3af5a
0d790d static ush const cplens[] = { /* Copy lengths for literal codes 257..285 */
0d6719 ¤   1, 2, 3, 4, 5, 6, 7, ·8, ·9, 11, 13, 15, 17, 21, 25, 29,
441a9d ¤   33, 41, 49, 57, 65, 81, 97, 113, 129, 161, 193, 225, 256, 0, 0};
3ac905 ¤   /* actually lengths - 2; also see note #13 above about 258 */
baaf5a
631480 static ush const cplext[] = { /* Extra bits for literal codes 257..285 */
87e9a3 ¤   0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
ee1a71 ¤   3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 128, 128}; /* 128==invalid */
44af5a
8259bb static ush const cpdist[] = { /* Copy offsets for distance codes 0..29 */
9438d6 ¤   1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
28e849 ¤   257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
f9f477 ¤   8193, 12289, 16385, 24577};
53af5a
1a9f41 static ush const cpdext[] = { /* Extra bits for distance codes */
6a43c5 ¤   0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
e026ac ¤   7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
6d1c50 ¤   12, 12, 13, 13};
c5af5a
109846 /* And'ing with mask[n] masks the lower n bits */
62e910 static unsigned const mask[17] = {
d750c2 ····0x0000,
b21395 ····0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
ab98b0 ····0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
3782f7 };
c8af5a
b8af5a
1856fc /* Macros for inflate() bit peeking and grabbing.
794d13 ·* The usage is:
23775e ·*
e28a91 ·*¤ NEEDBITS(j)
a3c3bc ·*¤ x = b & mask[j];
785adb ·*¤ DUMPBITS(j)
8c775e ·*
022f1a ·* where NEEDBITS makes sure that b has at least j bits in it, and
b1d1b2 ·* DUMPBITS removes the bits from b. ·The macros use the variable k
bffb7b ·* for the number of bits in b. ·Normally, b and k are register
332a4f ·* variables for speed, and are initialized at the beginning of a
5d6892 ·* routine that uses these macros from a global bit buffer and count.
95775e ·*
918aad ·* It is allowed for more bits to be requested than actually used.
fe9a5a ·* The remainder stay in the bit buffer. ·NOTE that a few more
973c08 ·* bytes than necessary may be grabbed at the end of input.
a042ba ·* This should not be fatal as long as the grabbed bits stay
cd10f3 ·* in the bit buffer. ·The wrapup functions should check for this.
4aaf5a
1d415c ·* There is also the macro GRABBITS which is like NEEDBITS, but uses
2c24f9 ·* *g++ to get the byte without checking availability. ·This requires
5031d0 ·* using AVAILBYTES first to assure that the needed bytes are there
522a9f ·* already. ·g is set to inptr and then inptr is restored to g around
7a8dad ·* this usage.
53495d ·*/
--d2dd 000437aee2b40100130 Page 6 of pgpZInflate.c
e0af5a
d338e5 /*
fbd0b6 ·* Variable usage:
964718 ·* b = bit buffer, k least-significant bits valid
bf96c9 ·* k = # of bits in bit buffer
503370 ·* g = grab bits pointer (pointer to next byte to add: b |= *g++ << k)
36abb0 ·* s = # of bytes available
bc7e2e ·* ctx = InflateContext
c0495d ·*/
ffaf5a
444a91 /* Functions to save the state of the bit buffer before returning */
fedaec #define LOADBITBUF \
f7ec26 ¤   (b=ctx->bitbuffer, k=ctx->bufbits, g=ctx->inptr, s=ctx->inlen)
b145b2 #define SAVEBITBUF \
a98221 ¤   (ctx->bitbuffer=b, ctx->bufbits=k, ctx->inptr=g, ctx->inlen=s)
bf95ce #define SAVEBITBUFEMPTY \
a16b33 ¤   (ctx->bitbuffer=b, ctx->bufbits=k, ctx->inptr=g, ctx->inlen=0)
adaf5a
e038e5 /*
dd3cf8 ·* A simple macro to ensure that at least "x" bits are in the bit buffer.
b5d6b7 ·* Does NOT check for input underflow (s < 0).
9c495d ·*/
5b4bfd #define GRABBITS(x) \
fa8ca1 ¤   while (k < x) { \
fe0d9f ¤   ¤   --s; \
013b41 ¤   ¤   b |= (ulg)*g++ << k; \
0b8699 ¤   ¤   k += 8; \
c69371 ¤   }
76af5a
3b38e5 /*
145206 ·* Get "x" bits in the input buffer or execute the "whatif" code.
dc0b18 ·* NOTE NOTE NOTE that if the "whatif" code is executed, s is set to -1!
5770be ·* (This is faster on a lot of machines.) ·You will usually have to
abcedd ·* reset it to 0 manually.
c0495d ·*/
23e989 #define GETBITSOR(x, whatif) \
edede7 ¤   while (k < (unsigned)(x)) { \
0c3680 ¤   ¤   if (--s < 0) { \
4dd828 ¤   ¤   ¤   whatif; \
3cd342 ¤   ¤   } \
7c3b41 ¤   ¤   b |= (ulg)*g++ << k; \
6f8699 ¤   ¤   k += 8; \
f29371 ¤   }
09af5a
4e38e5 /*
5bd18b ·* A macro to ensure that there are at least "x" bits available in the
e5d2c1 ·* bit buffer. ·If there are not, the bit buffer is saved back into the
1b9d2a ·* context, and any code in "savestate" is run to save any additional
ad9f39 ·* context that might be needed. ·Then, "return 1" means that more input is
54e480 ·* needed.
14495d ·*/
7c6874 #define NEEDBITS(x, savestate) \
4c3318 ¤   GETBITSOR(x, savestate; SAVEBITBUFEMPTY; return 1)
d9af5a
f538e5 /*
75fde7 ·* NEEDBITS2 uses two figures for the number of bits required. ·The first,
506c36 ·* x, is cheap to compute and is used unless we run out of input data.
c86fad ·* If that happens, the more expensive value, x2, is used.
cf495d ·*/
33df03 #define NEEDBITS2(x, x2, savestate) \
c9c6b2 ¤   NEEDBITS(x, if (k >= (unsigned)(x2)) {s=0; break;} savestate)
faaf5a
d8aa51 #define DUMPBITS(x) (b >>= x, k -= x)
a1af5a
3038e5 /*
e6038f ·* Huffman code decoding is performed using a multi-level table lookup.
d2e126 ·* The fastest way to decode is to simply build a lookup table whose
c93e5e ·* size is determined by the longest code. ·However, the time it takes
497d1c ·* to build this table can also be a factor if the data being decoded
96fb40 ·* is not very long. ·The most common codes are necessarily the
b8b977 ·* shortest codes, so those codes dominate the decoding time, and hence
4375ef ·* the speed. ·The idea is you can have a shorter table that decodes the
--5bb8 0003f4a3a5c40100130 Page 7 of pgpZInflate.c
820ca3 ·* shorter, more probable codes, and then point to subsidiary tables for
ac75b0 ·* the longer codes. ·The time it costs to decode the longer codes is
3fba0a ·* then traded against the time it takes to make longer tables.
aa775e ·*
e08a4a ·* This results of this trade are in the values LBITS and DBITS
20c842 ·* below. ·LBITS is the number of bits the first level table for literal/
249d4a ·* length codes can decode in one step, and DBITS is the same thing for
45ddb7 ·* the distance codes. ·Subsequent tables are also less than or equal to
09c869 ·* those sizes. ·These values may be adjusted either when all of the
c757ca ·* codes are shorter than that, in which case the longest code length in
1e6fd2 ·* bits is used, or when the shortest code is *longer* than the requested
e71bb7 ·* table size, in which case the length of the shortest code in bits is
a18867 ·* used.
de775e ·*
bceee4 ·* There are two different values for the two tables, since they code a
c915d4 ·* different number of possibilities each. ·The literal/length table
68f479 ·* codes 286 possible values, or in a flat code, a little over eight
9684bf ·* bits. ·The distance table codes 30 possible values, or a little less
a1e4ec ·* than five bits, flat. ·The optimum values for speed end up being
65248f ·* about one bit more than those, so LBITS is 8+1 and DBITS is 5+1.
82306b ·* The optimum values may differ though from machine to machine, and
7a165c ·* possibly even between compilers. ·Your mileage may vary.
55495d ·*/
27af5a
dcef3e #define LBITS 9 ··/* bits in base literal/length lookup table */
337eaa #define DBITS 6 ··/* bits in base distance lookup table */
b5af5a
ef7e11 /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
b0a10c #define BMAX 15 ········/* maximum bit length of any code (16 for explode) */
4f6208 #define N_MAX 288 ······/* maximum number of codes in any set */
aeaf5a
2007b5 #if defined(__STDC__) || defined(__cplusplus)
b7beb7 static int
43749f huft_build( PGPContextRef context,
f446d1 ¤   ¤   unsigned char const *b, unsigned n, unsigned s, ush const *d,
8fc637 ¤   ···ush const *e, huft **t, unsigned *m)
13db21 #else
7fbeb7 static int
4e877d huft_build(context, b, n, s, d, e, t, m)
c1ff2b PGPContextRef context;¤ /* context for memory allocation */
85dff0 unsigned char *b; ······/* code lengths in bits (all assumed <= BMAX) */
f32b1d unsigned n; ············/* number of codes (assumed <= N_MAX) */
669d23 unsigned s; ············/* number of simple-valued codes (0..s-1) */
e57139 ush const *d; ··········/* list of base values for non-simple codes */
22a405 ush const *e; ··········/* list of extra bits for non-simple codes */
b8afb9 huft **t; ·······/* result: starting table */
4ca265 unsigned *m; ···········/* suggested lookup bits, returns actual */
cb7454 #endif
ee38e5 /*
806630 ·* Given a list of code lengths and a maximum table size, make a set of
304924 ·* tables to decode that set of codes. ·Return values:
76bb85 ·* 0 = success
bd6979 ·* 1 = the given code set is incomplete
64ade4 ·* ····(the tables are still built in this case)
1632fb ·* 2 = the input is invalid
17f6da ·* ····(all zero length codes or an oversubscribed set of lengths)
c7b309 ·* 3 = not enough memory.
3a495d ·*/
27bb36 {
e1a69e ··unsigned a; ··················/* counter for codes of length k */
36284b ··unsigned c[BMAX+1]; ··········/* bit length count table */
d8ef93 ··unsigned f; ··················/* i repeats in table every f entries */
d0cb0b ··int g; ·······················/* maximum code length */
8f794e ··int h; ·······················/* table level */
2cd992 ··register unsigned i; ·········/* counter, current code */
b43a4d ··register unsigned j; ·········/* counter */
e622c8 ··register int k; ··············/* number of bits in current code */
789462 ··int l; ·······················/* bits per table (returned in m) */
d9d229 ··register unsigned char const *bp;¤/* pointer into b[] */
38b1e4 ··register unsigned *p; ········/* pointer into c[] or v[] */
eb6250 ··register huft *q; ·····/* points to current table */
3f85cf ··huft r; ···············/* table entry for structure assignment */
--9a26 00049d3227040100130 Page 8 of pgpZInflate.c
a62668 ··huft *u[BMAX]; ········/* table stack */
c93388 ··unsigned v[N_MAX]; ···········/* values in order of bit length */
fdbf73 ··register int w; ··············/* bits before this table == (l * h) */
7a07a5 ··unsigned x[BMAX+1]; ··········/* bit offsets, then code stack */
f0b436 ··unsigned *xp; ················/* pointer into x */
03e6f7 ··int y; ·······················/* number of dummy codes added */
b7fd2a ··unsigned z; ··················/* number of entries in current table */
2daf5a
a4af5a
d62329 ··/* Generate counts for each bit length */
72958f ··pgpClearMemory( c, ·sizeof(c));
b3acd6 ··bp = b; ·i = n;
d4565f ··do {
1c25e1 ····c[*bp++]++; ················/* assume all entries <= BMAX */
d774ec ··} while (--i);
2698df ··if (c[0] == n) ···············/* null input--all zero length codes */
4c8bcc ··{
8addf6 ····*t = (huft *)NULL;
374dff ····*m = 0;
28958b ····return 0;
49df1c ··}
04af5a
a5af5a
4891d0 ··/* Find minimum and maximum length, bound *m by those */
aa709d ··l = *m;
73046e ··for (j = 1; j <= BMAX; j++)
e3da5d ····if (c[j])
7f88e1 ······break;
0704d4 ··k = j; ·······················/* minimum code length */
30e857 ··if ((unsigned)l < j)
791ac4 ····l = j;
19906f ··for (i = BMAX; i; i--)
17ff90 ····if (c[i])
5d88e1 ······break;
440373 ··g = i; ·······················/* maximum code length */
c811bb ··if ((unsigned)l > i)
b6f5a0 ····l = i;
20d8bd ··*m = l;
27af5a
a9af5a
66e085 ··/* Adjust last length count to fill out codes, if needed */
98b7ed ··for (y = 1 << j; j < i; j++, y <<= 1)
8aba87 ····if ((y -= c[j]) < 0)
e64563 ······return 2; ················/* bad input: more codes than bits */
a3709c ··if ((y -= c[i]) < 0)
752033 ····return 2;
09c66b ··c[i] += y;
44af5a
58af5a
51c82b ··/* Generate starting offsets into the value table for each length */
10a2b9 ··x[1] = j = 0;
071483 ··p = c + 1; ·xp = x + 2;
84e85e ··while (--i) { ················/* note that i == g from above */
d0a264 ····*xp++ = (j += *p++);
90df1c ··}
51af5a
63af5a
1c71ad ··/* Make a table of values in order of bit lengths */
fc3f2e ··bp = b; ·i = 0;
49565f ··do {
3e29f7 ····if ((j = *bp++) != 0)
2a5c98 ······v[x[j]++] = i;
efa8c8 ··} while (++i < n);
a0af5a
a2af5a
58a706 ··/* Generate the Huffman codes and for each, make the table entries */
274e59 ··x[0] = i = 0; ················/* first Huffman code is zero */
90bb32 ··p = v; ·······················/* grab values in bit order */
dea9d5 ··h = -1; ······················/* no tables yet--level -1 */
24aff0 ··w = -l; ······················/* bits decoded == (l * h) */
f64462 ··u[0] = (huft *)NULL; ··/* just to keep compilers happy */
490626 ··q = (huft *)NULL; ·····/* ditto */
--ed25 000f788f86c40100130 Page 9 of pgpZInflate.c
eb8a9a ··z = 0; ·······················/* ditto */
efaf5a
b07f19 ··/* go through the bit lengths (k already is bits in shortest code) */
697f05 ··for (; k <= g; k++) {
c674db ····a = c[k];
17c679 ····while (a--) {
39298e ······/* here i is the Huffman code of length k bits for value *p */
bcab1c ······/* make tables up to required level */
af2411 ······while (k > w + l) {
973f00 ¤   h++;
96393b ¤   w += l; ················/* previous table always l bits */
e3af5a
64b4d3 ¤   /* compute minimum size table less than or equal to l bits */
49d8d4 ¤   z = (z = g - w) > (unsigned)l ? l : z; ·/* upper limit on table size */
2410ce ¤   if ((f = 1 << (j = k - w)) > a + 1) ····/* try a k-w bit table */
ba71e9 ¤   { ······················/* too few codes for k-w bit table */
9685b8 ¤   ··f -= a + 1; ··········/* deduct codes from patterns left */
8fe31f ¤   ··xp = c + k;
cef880 ¤   ··while (++j < z) { ····/* try smaller tables up to z bits */
1a3446 ¤   ····if ((f <<= 1) <= *++xp)
ced8d3 ¤   ······break; ···········/* enough codes to use up j bits */
b053cf ¤   ····f -= *xp; ··········/* else deduct codes from patterns */
4132a2 ¤   ··}
a09371 ¤   }
80905f ¤   z = 1 << j; ············/* table entries for j-bit table */
fcaf5a
4c0bda ¤   /* allocate and link in new table */
7089d7 ¤   if ((q = (huft *)pgpContextMemAlloc( context, (z + 1)*sizeof(huft),
fbf5f0 ¤   ¤   0)) == (huft *)NULL)
cec7a1 ¤   {
5677d6 ¤   ··if (h)
972a14 ¤   ····huft_free( context, u[0]);
34e1b0 ¤   ··return 3; ············/* not enough memory */
e59371 ¤   }
e1adcb #if SECURE
047cbc ¤   q->bits = (char)j;¤ /* Track size for free */
557454 #endif
75f41d ¤   *t = q + 1; ············/* link to list for huft_free() */
f29b76 ¤   *(t = &(q->next)) = (huft *)NULL;
bfd71d ¤   u[h] = ++q; ············/* table starts after link */
acaf5a
126b59 ¤   /* connect to last table, if there is one */
1c1ff1 ¤   if (h) {
59c274 ¤   ··x[h] = i; ············/* save pattern for backing up */
68f928 ¤   ··r.bits = (char)l; ····/* bits to dump before this table */
b11467 ¤   ··r.exop = -(char)j; ···/* bits in this table */
189cf8 ¤   ··r.next = q; ··········/* pointer to this table */
4e88dc ¤   ··j = i >> (w - l); ····/* (get around Turbo C bug) */
4e9c49 ¤   ··u[h-1][j] = r; ·······/* connect to last table */
739371 ¤   }
ea42cc ······}
c2af5a
e2fdb8 ······/* set up table entry in r */
63aa19 ······r.bits = (char)(k - w);
233553 ······if (p >= v + n) {
d09289 ¤   r.exop = -128; ·········/* out of values--invalid code */
596a8a ······} else if (*p < s) {
71399d ¤   r.exop = (char)(*p < 256 ? 16 : 32); ···/* 256 is end-of-block code */
59aa4d ¤   r.base = *p++; ·········/* simple code is just the value */
b0cfc7 ······} else {
0d27e4 ¤   r.exop = (char)e[*p - s]; ······/* non-simple--look up in lists */
6e2f8b ¤   r.base = d[*p++ - s];
5e42cc ······}
38af5a
e01d26 ······/* fill code-like entries with r */
175d9a ······f = 1 << (k - w);
aaf019 ······for (j = i >> w; j < z; j += f)
b8dc37 ¤   q[j] = r;
a5af5a
eb4054 ······/* backwards increment the k-bit code i */
08b0fd ······for (j = 1 << (k - 1); i & j; j >>= 1)
f7f0d3 ¤   i ^= j;
--9cbb 0006f3bdc7840100130 Page 10 of pgpZInflate.c
f7f30d ······i ^= j;
f1af5a
f800a7 ······/* back up over finished tables */
324e78 ······while ((i & ((1 << w) - 1)) != x[h]) {
da5105 ¤   h--; ···················/* don't need to update q */
3a8403 ¤   w -= l;
9d42cc ······}
f46fe7 ····}
e0df1c ··}
cdaf5a
5aaf5a
2d9379 ··/* Return true (1) if we were given an incomplete table */
8e5358 ··return y != 0 && g != 1;
38efe6 }
efaf5a
daaf5a
2e07b5 #if defined(__STDC__) || defined(__cplusplus)
6dbeb7 static int
0c0f1d huft_free(PGPContextRef context, huft *t)
17db21 #else
6fbeb7 static int
75587d huft_free( context, t)
32ff2b PGPContextRef context;¤ /* context for memory allocation */
a2b605 huft *t;¤   ¤   ¤   ¤   /* table to free */
4e7454 #endif
cb38e5 /*
3bd1cd ·* Free the malloc'ed tables built by huft_build(), which makes a linked
136073 ·* list of the tables it made, with the links in a dummy -1st entry of
779bcf ·* each table.
48495d ·*/
f8bb36 {
660802 ··register huft *p, *q;
13af5a
26e2cf ··/* Go through linked list, freeing from the malloced (t[-1]) address. */
e732cf ··p = t;
87b2e8 ··while (p != (huft *)NULL)
8f8bcc ··{
5a9639 ····q = (--p)->next;
3eadcb #if SECURE
15d35c ····pgpClearMemory( p, ·(1+(1<<p->bits)) * sizeof(*p));
d97454 #endif
0b1315 ····pgpContextMemFree( context, p);
d3b2a4 ····p = q;
6edf1c ··}
0e212b ··return 0;
22efe6 }
9daf5a
25af5a
7638e5 /*
c7cbca ·* Colin's new code.
25495d ·*/
19af5a
86cf6e #define STATE_START¤0
fa206a #define¤STATE_STOREDLEN¤1
91d3f8 #define STATE_STORED¤   2
f5ab47 #define¤STATE_DYN_HDR¤  3
d706d1 #define¤STATE_DYN_BITS¤ 4
31f6b5 #define STATE_DYN_TREE¤ 5
e22cff #define STATE_INFLATE¤  6
8c27e8 #define STATE_DONE¤ 7
2b3622 #define STATE_STOP¤ 8
b1af5a
8138e5 /*
7abaa6 ·* All these functions return
4cd5e4 ·* 2 if the output buffer is full
352de6 ·* 1 if the input buffer is empty
5a5816 ·* ·0 if things should continue with the new ctx->state, and
14e3b2 ·* <0 on error.
7d495d ·*/
98af5a
80beb7 static int
6fb358 infStoredLen(InflateContext *ctx)
--caf1 000efdec99240100130 Page 11 of pgpZInflate.c
2cbb36 {
1fc78b ¤   ulg b;
1fc187 ¤   unsigned k;
8ebd4b ¤   int s;
63db56 ¤   unsigned char const *g;
900ed5 ¤   unsigned t;
a3af5a
4ecea1 ¤   LOADBITBUF;
ce0ad9 ¤   t = k & 7;
c253c1 #if STRICT
d6816b ¤   if (b & mask[t])¤   /* Require unused bits are zero */
b0c9a4 ¤   ¤   return INFERR_BADINPUT;
087454 #endif
316e0e ¤   DUMPBITS(t);
8daf5a
bb18ee ¤   NEEDBITS(32, (void)0);
9baf5a
31ca4e ¤   /* At this point, k is exactly 32 */
efaf5a
273646 ¤   ctx->copylen = (unsigned)b & 0xffff;
e8fb66 ¤   t = ~(unsigned)(b>>16) & 0xffff;
a089ee ¤   b = 0;
cbc8d7 ¤   k = 0;
1faf5a
37418a ¤   SAVEBITBUF;
1f0062 ¤   if (t != ctx->copylen)
d5f476 ¤   ¤   return INFERR_BADINPUT;¤/* Two lengths not identical */
d1af5a
711623 ¤   ctx->state = STATE_STORED;
d88fb3 ¤   ctx->substate = 0;
9caf5a
5a3e6b ¤   return 0;
57efe6 }
deaf5a
a838e5 /*
9f6718 ·* Process the data in a stored block. ·Copy the input data to
8e2830 ·* the circular buffer, flushing it as necessary.
45495d ·*/
b5beb7 static int
18967e infStored(InflateContext *ctx)
39bb36 {
cb88f3 ¤   int len;¤   /* # of bytes to copy */
4bb9db ¤   int retval = 1;¤/* Out of memory */
fcaf5a
e6d691 ¤   pgpAssert(ctx->bufbits == 0);
90af5a
bd2b59 ¤   len = ctx->inlen;
dbebbc ¤   if ((unsigned)len >= ctx->copylen) {
e4f82c ¤   ¤   len = ctx->copylen;¤/* Copy done! */
2b4883 ¤   ¤   ctx->state = STATE_START;
dc8923 ¤   ¤   retval = 0;
ea9371 ¤   }
5c07db ¤   if (len > ctx->slideend-ctx->outptr) {
69fa12 ¤   ¤   len = (int)(ctx->slideend-ctx->outptr);
86aa92 ¤   ¤   retval = 2;¤/* Output buffer full */
429a5c ¤   ¤   ctx->state = STATE_STORED;
6a9371 ¤   }
3caf5a
de6c3b ¤   memcpy(ctx->outptr, ctx->inptr, len);
de7073 ¤   ctx->inptr += len;
c558b3 ¤   ctx->inlen -= len;
711271 ¤   ctx->outptr += len;
6ce26f ¤   ctx->copylen -= (unsigned)len;
f1af5a
ad2521 ¤   /* Return 2 if output full, 1 if input empty, 0 otherwise (copy done)*/
b594b6 ¤   return retval;
ddefe6 }
00af5a
d1beb7 static int
877946 infDynHdr(InflateContext *ctx)
a9bb36 {
efc78b ¤   ulg b;
--24c1 0007dd6969740100130 Page 12 of pgpZInflate.c
37c187 ¤   unsigned k;
99bd4b ¤   int s;
b0db56 ¤   unsigned char const *g;
30af5a
02cea1 ¤   LOADBITBUF;
3ff8d4 ¤   NEEDBITS(14, (void)0);
a8af5a
4114e2 ¤   ctx->litcodes = 257 + ((unsigned)b & 0x1f);
456402 ¤   DUMPBITS(5);
e3eeb6 ¤   ctx->distcodes = 1 + ((unsigned)b & 0x1f);
c56402 ¤   DUMPBITS(5);
008d38 ¤   ctx->bitlengths = 4 + ((unsigned)b & 0xf);
b578b9 ¤   DUMPBITS(4);
63af5a
fe418a ¤   SAVEBITBUF;
74af5a
4bfbc8 #ifndef PKZIP_BUG_WORKAROUND
4d6c87 ¤   if (ctx->litcodes > 286 || ctx->distcodes > 30)
d0c435 ¤   ¤   return INFERR_BADINPUT;¤/* Bad lengths */
b47454 #endif
3c617c ¤   ctx->state = STATE_DYN_BITS;
253e6b ¤   return 0;
88efe6 }
d6af5a
641db3 /* Load up the ctx->bitlen array with the bit lengths for the encoded
1a93de ·* trees. ·Unpermute them according to the border[] array.
70495d ·*/
f8beb7 static int
c0753e infDynBits(InflateContext *ctx)
6abb36 {
d8c78b ¤   ulg b;
47c187 ¤   unsigned k;
76bd4b ¤   int s;
96db56 ¤   unsigned char const *g;
4575d1 ¤   huft *t;
7a7eaf ¤   int i, lim;
2baf5a
2acea1 ¤   LOADBITBUF;
20525e ¤   i = ctx->substate;
f900ea ¤   lim = ctx->bitlengths;
9faf5a
c7c0e0 ¤   while (i < lim) {
8b4d88 ¤   ¤   NEEDBITS(3, ctx->substate=i)
338d20 ¤   ¤   ctx->bitlen[border[i++]] = (unsigned)b & 7;
996e13 ¤   ¤   DUMPBITS(3);
b79371 ¤   }
48418a ¤   SAVEBITBUF;
5aaf5a
647997 ¤   while (i < 19)
061151 ¤   ¤   ctx->bitlen[border[i++]] = 0;
dbaf5a
e6dcbe ¤   k = 7;¤ /* Bits in tree table */
99af5a
a1afec ¤   i = huft_build( ctx->context, ctx->bitlen, 19, 19, NULL, NULL, &t, &k);
3214b5 ¤   if (i) {
53ce6f ¤   ¤   if (i == 1)
64d44f ¤   ¤   ¤   huft_free( ctx->context,t);¤/* Incomplete code set */
c64cd5 ¤   ¤   return i == 3 ? INFERR_NOMEM : INFERR_BADINPUT;
bf9371 ¤   }
c24e14 ¤   ctx->tree1 = t;
773ec6 ¤   ctx->bits1 = k;
b9af5a
9644cc ¤   ctx->state = STATE_DYN_TREE;
408fb3 ¤   ctx->substate = 0;
e7af5a
923e6b ¤   return 0;
26efe6 }
80af5a
2dbeb7 static int
f78b06 infFixedTree( InflateContext *¤ ctx )
b4bb36 {
7d4ba4 ¤   int i;
--3005 0005182850f40100130 Page 13 of pgpZInflate.c
8389b6 ¤   unsigned char l[288];
dc1183 ¤   PGPContextRef¤  context¤= ctx->context;
37af5a
67f86f ¤   if ( IsntNull( ctx->fixed_tl ) )
7ae37b ¤   ¤   return 0;¤  /* All okay */
d8af5a
610eba ¤   /* literal table */
edc3aa ¤   for (i = 0; i < 144; i++)
59819e ¤   ¤   l[i] = 8;
21e2b5 ¤   for (; i < 256; i++)
30db42 ¤   ¤   l[i] = 9;
63f2d6 ¤   for (; i < 280; i++)
1ccb59 ¤   ¤   l[i] = 7;
677201 ¤   for (; i < 288; i++) ·····/* make a complete, but wrong code set */
73819e ¤   ¤   l[i] = 8;
02a659 ¤   ctx->fixed_bl = 7;
11bb29 ¤   i = huft_build( context, l,
085648 ¤   ¤   288, 257, cplens, cplext, &ctx->fixed_tl, &ctx->fixed_bl);
01535c ¤   if (i != 0) {
b2ca65 ¤   ¤   ctx->fixed_tl = NULL;
8c6f9b ¤   ¤   return INFERR_NOMEM;
ff9371 ¤   }
ecaf5a
09f465 ¤   /* distance table */
001f92 ¤   for (i = 0; i < 30; i++) ·····/* make an incomplete code set */
157ee1 ¤   ¤   l[i] = 5;
89cd0d ¤   ctx->fixed_bd = 5;
76dfaf ¤   i = huft_build( context, l, 30, 0,
fa134f ¤   ¤   ¤   cpdist, cpdext, &ctx->fixed_td, &ctx->fixed_bd);
fa4690 ¤   if (i > 1) {
f28c01 ¤   ¤   huft_free( context, ctx->fixed_tl);
9aca65 ¤   ¤   ctx->fixed_tl = NULL;
496f9b ¤   ¤   return INFERR_NOMEM;
3f9371 ¤   }
aaaf5a
4b3e6b ¤   return 0;
9eefe6 }
09af5a
e0beb7 static int
012019 infDynTree(InflateContext *ctx)
0fbb36 {
b5c78b ¤   ulg b;
aec187 ¤   unsigned k;
94bd4b ¤   int s;
2bdb56 ¤   unsigned char const *g;
1af10a ¤   huft *tl, *td;
b742da ¤   unsigned bl, bd;
63780c ¤   unsigned i, j, l, m, lim;
90af5a
45cea1 ¤   LOADBITBUF;
a37c0a ¤   i = ctx->index;
b46efa ¤   l = ctx->numbits;¤  /* Previous # of bits for repeat code use */
7a1bcd ¤   lim = ctx->litcodes + ctx->distcodes;
4a0ff5 ¤   tl = ctx->tree1;
fbd298 ¤   bl = ctx->bits1;
5a33ee ¤   m = mask[bl];
74af5a
d50757 ¤   switch(ctx->substate) {
785051 ¤   ··case 0:
da9ed6 ¤   ¤   i = 0;
656e75 ¤   ¤   l = 0;
d1fc9f ¤   ¤   /*FALLTHROUGH*/
690a8d ¤   ··case 1:
7b0755 ¤   ¤   while (i < lim) {
ec7dda ¤   ¤   ¤   NEEDBITS2(bl, tl[(unsigned)b & m].bits,
b56e7a ¤   ¤   ¤   ¤   ctx->index=i; ctx->numbits=l; ctx->substate=1)
a3eb87 ¤   ¤   ¤   td = tl + ((unsigned)b & m);
6747fc ¤   ¤   ¤   j = td->bits;
b2f3b7 ¤   ¤   ¤   DUMPBITS(j);
3f19b1 ¤   ¤   ¤   j = td->base;
3fdd3a ¤   ¤   ¤   if (j < 16) {
51bbb2 ¤   ¤   ¤   ¤   ctx->bitlen[i++] = l = j;
--a8cc 0007dfabd9840100130 Page 14 of pgpZInflate.c
738ae5 ¤   ¤   ¤   } else if (j == 16) {¤  /* 3 to 6 repeats */
61a7a4 ¤   ¤   ¤   ¤   /*FALLTHROUGH*/
29e5e9 ¤   ··case 2:
02a308 ¤   ¤   ¤   ¤   NEEDBITS(2, ctx->index=i; ctx->numbits=l;
175450 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ctx->substate=2)
900819 ¤   ¤   ¤   ¤   j = 3 + ((unsigned)b & 3);
89f724 ¤   ¤   ¤   ¤   DUMPBITS(2);
f66341 ¤   ¤   ¤   ¤   if (i + j > lim)
700f6b ¤   ¤   ¤   ¤   ¤   return INFERR_BADINPUT;
93b788 ¤   ¤   ¤   ¤   do {
c9e4d3 ¤   ¤   ¤   ¤   ¤   ctx->bitlen[i++] = (unsigned char)l;
542c7b ¤   ¤   ¤   ¤   } while (--j);
59b22a ¤   ¤   ¤   } else if (j == 17) {¤  /* 3 to 10 zeros */
89a7a4 ¤   ¤   ¤   ¤   /*FALLTHROUGH*/
71bf35 ¤   ··case 3:
8a63a6 ¤   ¤   ¤   ¤   NEEDBITS(3, ctx->index=i; ctx->substate=3)
a07af5 ¤   ¤   ¤   ¤   j = 3 + ((unsigned)b & 7);
a5eb9f ¤   ¤   ¤   ¤   DUMPBITS(3);
656341 ¤   ¤   ¤   ¤   if (i + j > lim)
220f6b ¤   ¤   ¤   ¤   ¤   return INFERR_BADINPUT;
93b788 ¤   ¤   ¤   ¤   do {
b1e44f ¤   ¤   ¤   ¤   ¤   ctx->bitlen[i++] = 0;
112c7b ¤   ¤   ¤   ¤   } while (--j);
67b73f ¤   ¤   ¤   ¤   l = 0;
ab1997 ¤   ¤   ¤   } else {¤   /* j == 18 -- 11 to 138 zeros */
bcf14b ¤   ¤   ¤   ¤   pgpAssert(j == 18);
6da7a4 ¤   ¤   ¤   ¤   /*FALLTHROUGH*/
d13330 ¤   ··case 4:
36a0c6 ¤   ¤   ¤   ¤   NEEDBITS(7, ctx->index=i; ctx->substate=4)
d09970 ¤   ¤   ¤   ¤   j = 11 + ((unsigned)b & 127);
309973 ¤   ¤   ¤   ¤   DUMPBITS(7);
e66341 ¤   ¤   ¤   ¤   if (i + j > lim)
650f6b ¤   ¤   ¤   ¤   ¤   return INFERR_BADINPUT;
6eb788 ¤   ¤   ¤   ¤   do {
0ce44f ¤   ¤   ¤   ¤   ¤   ctx->bitlen[i++] = 0;
cb2c7b ¤   ¤   ¤   ¤   } while (--j);
b1b73f ¤   ¤   ¤   ¤   l = 0;
e0a3a6 ¤   ¤   ¤   }
1d0fe4 ¤   ¤   }
969371 ¤   }
d1af5a
589075 ¤   /* Input finished */
13418a ¤   SAVEBITBUF;
3b3532 ¤   huft_free( ctx->context, tl);
7d2b03 ¤   ctx->tree1 = 0;
2faf5a
b1ec37 ¤   /* Now build the trees - literal/length, then distance */
94af5a
986ce1 ¤   bl = LBITS;
689e16 ¤   i = huft_build( ctx->context, ctx->bitlen, ctx->litcodes, 257,
60480d ¤   ¤   ·······cplens, cplext, &tl, &bl);
7e535c ¤   if (i != 0) {
59ce6f ¤   ¤   if (i == 1)
8b899b ¤   ¤   ¤   huft_free(ctx->context, tl);
194cd5 ¤   ¤   return i == 3 ? INFERR_NOMEM : INFERR_BADINPUT;
2a9371 ¤   }
b60ea7 ¤   bd = DBITS;
fa1f11 ¤   i = huft_build( ctx->context, ctx->bitlen+ctx->litcodes, ctx->distcodes, 0,
4894c7 ¤   ¤   ·······cpdist, cpdext, &td, &bd);
3a8801 #ifdef PKZIP_BUG_WORKAROUND
764690 ¤   if (i > 1) {
3adb21 #else
d8535c ¤   if (i != 0) {
43ce6f ¤   ¤   if (i == 1)
bd6c43 ¤   ¤   ¤   huft_free(ctx->context, td);
d47454 #endif
d4da41 ¤   ¤   huft_free( ctx->context, tl);
f24cd5 ¤   ¤   return i == 3 ? INFERR_NOMEM : INFERR_BADINPUT;
e69371 ¤   }
83592d ¤   ctx->tree1 = tl;
b555a1 ¤   ctx->bits1 = bl;
7d153f ¤   ctx->tree2 = td;
--a4f6 000f33b996c40100130 Page 15 of pgpZInflate.c
1919b3 ¤   ctx->bits2 = bd;
48af5a
e031f9 ¤   ctx->state = STATE_INFLATE;
c88fb3 ¤   ctx->substate = 0;
cfaf5a
d53e6b ¤   return 0;
f1efe6 }
b7af5a
9a38e5 /*
c3da10 ·* This is the heart of ZIP inflation. ·The code is heavily optimized
56f047 ·* for speed, including for many brain-damaged compilers that can only
bc5bfe ·* optimize one statement at a time. ·To generate better code from
d87413 ·* such idiot compilers (which are distressingly common on platforms
e92c29 ·* such as MS-DOS), expressions are made big and complex, and intermediate
08d645 ·* results are ssigned to variables in the expression where possible
fc4cfb ·* so the compiler won't try to use a disjoint temporary and have to
200f4c ·* spill. ·This makes the code a little hard to follow at times.
91b773 ·* Sorry.
7e775e ·*
8438ae ·* Also, due to the deep nesting (it's all in one function, again, for
b41829 ·* speed even on systems that can't inline), the indent amount is only
b3f7db ·* two spaces and variable names are very short.
17775e ·*
e00f11 ·* This does NOT currently detect a reference to before the beginning of
34208c ·* the file. ·It just blindly uses the circular buffer.
c8495d ·*/
17beb7 static int
19add9 infInflate(InflateContext *ctx)
76bb36 {
223bd0 ··ulg b;¤   ¤   /* Bit buffer info - bit buffer itself */
b650e3 ··unsigned k;¤  ¤   /* Number of low0order bits of b that are valid */
e10ac4 ··int s;¤   ¤   /* Bytes of valid input remaining */
45821c ··unsigned char const *g;¤  /* Input buffer pointer */
24af5a
af383d ··unsigned char *w;¤/* Window output write pointer */
aeee8d ··unsigned r;¤  ¤   /* Space available after w (always >0) */
5caf5a
3e1778 ··huft *tl, *td;¤   /* Tree info (const except for EOB processing) */
92fae5 ··unsigned bl, bd;
57f9ae ··unsigned ml, md;
4cab53 ··huft const *t;¤   /* Temporary tree pointer */
a8af5a
92a62e ··unsigned char const *p;¤  /* Copy source pointer */
1e17e0 ··int i;
2db243 ··int e;
d7474a ··unsigned n;¤  ¤   /* Copy length */
04efa4 ··unsigned d;¤  ¤   /* Copy distance */
b7af5a
928aed ··LOADBITBUF;¤  ¤   /* Load b, k, s, g */
8aaf5a
a8fc80 ··w = ctx->outptr;
544202 ··r = ctx->slideend-w;
b1bc88 ··pgpAssert(r);
03af5a
c7328d ··tl = ctx->tree1;¤ /* Literal/length tree */
0a02e6 ··bl = ctx->bits1;¤ /* Number of bits in top-level table */
1bdd9b ··ml = mask[bl];¤   /* Mask of that many bits */
49af5a
a57ad1 ··td = ctx->tree2;¤ /* Distance tree */
7f14c8 ··bd = ctx->bits2;¤ /* Number of bits in top-level table */
23ccc2 ··md = mask[bd];¤   /* Mask of that many bits */
81af5a
626000 ··/*
8815a5 ···* We don't always need all of these, but it's easier to always
a62183 ···* load them than to do it conditionally.
36f9a6 ···*/
1d6516 ··t = ctx->t;
e5c2cc ··n = ctx->copylen;
a2931c ··d = ctx->distbase;
a93b75 ··e = ctx->numbits;
8daf5a
f38ecd ··switch (ctx->substate) {
--a262 0008750f05e40100130 Page 16 of pgpZInflate.c
aefc13 ··case 0:
4fe262 ····for (;;) { ····················/* do until end of block */
0db610 ······/*
9e8962 ·······* This cheap loop does no input or output checking.
49a52b ·······* At most 258 bytes of output are produced per iteration,
721c08 ·······* so we must do no more than r/258 iterations.
dda006 ·······* Also, at most 15+5+15+13 = 48 bits = 6 bytes are consumed
f816aa ·······* every iteration, so we can do no more than s/6 iterations.
d7b6af ·······* Also, to allow for starting with an empty bit buffer and
8032f7 ·······* ending with a full one, subtract 4 bytes, so it's (s-4)/6.
6cf9ab ·······*
e7015f ·······* These are approximated by r/256-1 and (s-2)/8, respectively.
4d5dd3 ·······* Note: for a file that compresses to 258 bytes per symbol (e.g. all
86d736 ·······* the same character), that approximation would break down if
acf9ab ·······*
acedb7 ·······*¤   r/256-1 > r/258
1ec761 ·······* thus,¤ 258 * r - 256 * 258 > 256*r
693361 ·······* thus,¤ 2 * r > 256 * 258
f22860 ·······* thus,¤ r > 128 * 258 ·= 33024 > 32768
daf9ab ·······*
fd7878 ·······* Of course, the window is <= 32768, so it's not a concern.
f0f9ab ·······*
92528a ·······* For the input approximation to break down, you'd have to have
76f9ab ·······*
25eb62 ·······*¤   (s-2)/8 > (s-4)/6
e62138 ·······* thus,¤ 6*s - 12 > 8*s - 32
18874d ·······* thus, ·20 > 2*s
5a920e ·······* thus, ·10 > s
a2f9ab ·······*
bb3cfe ·······* But for s<10, both approximations (since this is integer math)
ad35ad ·······* return 0, so it's not a problem. ·The r/258 limit is usually
1a7bfc ·······* hit first, so the crudeness of this approximation is acceptable.
4be9f1 ·······*/
d7e61f ······while (r >= 512 && s >= 10) {
fe6493 ·········/* Compute number of iterations we can do, worst-case */
12e474 ¤   if ((e = (s - 2) >> 3) < (i = (r >> 8) - 1))
39194f ¤   ··i = e;
390fc6 ········/*
55aed2 ·········* This is the cheap loop, which is performed i times before
d42af3 ·········* the available buffer space is re-evaluated. ·If you want to
746bf0 ·········* understand how the inflation process works, this is the best
d193e6 ·········* part of the code to read, since it isn't cluttered up with
72551a ·········* error checking. ·First comes a literal/length code, which
0c0dec ·········* can be either a literal (0-255), an end of block code (256),
125af3 ·········*/
2c43ab ¤   do {
52e99e ¤   ··GRABBITS(20) ···········/* max bits for literal/length code */
c05532 ¤   ··t = tl + ((unsigned)b & ml);
94935d ¤   ··if ((e = t->exop) < 0) {
4bc99a ¤   ····do {
52266a ¤   ······if (e == -128)
30c9a4 ¤   ¤   return INFERR_BADINPUT;
a18b2a ¤   ······DUMPBITS(t->bits);
78cf6a ¤   ······e = -e;
48728e ¤   ······t = t->next + ((unsigned)b & mask[e]);
9d4517 ¤   ····} while ((e = t->exop) < 0);
d732a2 ¤   ··}
0a11e0 ¤   ··DUMPBITS(t->bits);
d523a4 ¤   ··if (e & 16) { ············/* then it's a literal */
ebc37c ¤   ····*w++ = (unsigned char)t->base;
21868f ¤   ····continue;
8532a2 ¤   ··}
a10cab ¤   ··if (e & 32) ¤ /* EOB */
a8dc91 ¤   ····goto EOB;¤  /* At end of function */
d5af5a
8d4d84 ¤   ··/* Else length code */
0eaf5a
32b93f ¤   ··/* get length of block to copy */
66ef53 ¤   ··n = t->base + ((unsigned)b & mask[e]);
b94398 ¤   ··DUMPBITS(e);
deaf5a
879943 ¤   ··/* decode distance of block to copy */
--e7e0 0004d7d34bf40100130 Page 17 of pgpZInflate.c
3b6ae8 ¤   ··GRABBITS(15);
1a7ae8 ¤   ··t = td + ((unsigned)b & md);
b5935d ¤   ··if ((e = t->exop) < 0) {
50c99a ¤   ····do {
3b266a ¤   ······if (e == -128)
b5c9a4 ¤   ¤   return INFERR_BADINPUT;
6b8b2a ¤   ······DUMPBITS(t->bits);
eccf6a ¤   ······e = -e;
fd728e ¤   ······t = t->next + ((unsigned)b & mask[e]);
4f4517 ¤   ····} while ((e = t->exop) < 0);
4c32a2 ¤   ··}
cb11e0 ¤   ··DUMPBITS(t->bits);
ee3e29 ¤   ··GRABBITS((unsigned)e) ··········/* get up to 13 extra bits */
7b3ddd ¤   ··d = t->base + ((unsigned)b & mask[e]);
21bbfd ¤   ··DUMPBITS((unsigned)e);
95af5a
bf512f #if WSIZE < 32768
d70ce7 ¤   ··if (d > ctx->slidelen)
ebf937 ¤   ····return INFERR_BADINPUT;
957454 #endif
90af5a
905d04 ¤   ··/* do the copy */
cc1449 ¤   ··if ((unsigned)(w - ctx->slide) >= d) {
1e7eb2 ¤   ····p = w - d;
d13d71 ¤   ····*w++ = *p++;
a03d71 ¤   ····*w++ = *p++;
52c99a ¤   ····do {
d6bea7 ¤   ······*w++ = *p++;
39e190 ¤   ····} while (--n);
022862 ¤   ··} else {
8e55b4 ¤   ····n += 2;
91f677 ¤   ····p = w - d + ctx->slidelen;
55c99a ¤   ····do {
88fe54 ¤   ······n -= (e = (unsigned)(e = ctx->slideend - (p>w?p:w)) > n ? n : e);
0f11cf ¤   ······do {
f07f87 ¤   ¤   *w++ = *p++;
b79cfd ¤   ······} while (--e);
e955bd ¤   ······if (p == ctx->slideend)
0b374f ¤   ¤   p = ctx->slide;
8930ed ¤   ····} while (n);
cf32a2 ¤   ··}
cec496 ¤   } while (--i);
03af5a
6d210d ¤   r = ctx->slideend - w;
28e6ad ······} /* while (we can use the cheap loop) */
77af5a
68b610 ······/*
2d376e ·······* Okay, we've fallen through from the cheap loop to the
ff8272 ·······* expensive loop. ·This one checks each time it gets bits
b3fddc ·······* from the input or writes bytes to the output that there
f60420 ·······* is enough room. ·However, there are two versions of
288de7 ·······* much of *this*, too! ·The first uses worst-case figures
4f53fb ·······* for the amount of input data needed, and obtains one batch of
8eaaea ·······* input bits for several uses.
0fdbdc ·······* The second carefully avoids asking for any more bits than it really
e7ffbf ·······* needs. ·When it gives up and returns, it is really not possible
f86021 ·······* to extract any more symbols from the input data.
4ce9f1 ·······*/
2a6742 ······/* Pessimistic estimate of bits for literal/length: 15+5 */
9bfa51 ······GETBITSOR(20, goto getlitlength2)
500958 ······t = tl + ((unsigned)b & ml);
9543e2 ······if ((e = t->exop) < 0) {
f043ab ¤   do {
0a18c4 ¤   ··if (e == -128)
88f937 ¤   ····return INFERR_BADINPUT;
5511e0 ¤   ··DUMPBITS(t->bits);
09e13f ¤   ··e = -e;
87b562 ¤   ··t = t->next + ((unsigned)b & mask[e]);
a81754 ¤   } while ((e = t->exop) < 0);
8142cc ······}
4dbf77 ······DUMPBITS(t->bits);
4df3c6 ······if (e & 16) { ········/* then it's a literal */
--8ea5 0000613b6bf40100130 Page 18 of pgpZInflate.c
a6dee5 ¤   *w++ = (unsigned char)t->base;
cf83f9 ¤   if (--r == 0) {
0049b1 ··········SAVEBITBUF;
05677b ··········ctx->outptr = w;
8a78fa ··········ctx->substate = 0;¤   /* Restart at top of loop */
608956 ··········return 2;¤/* Output buffer full */
179371 ¤   }
f5a8da ¤   continue;
5e42cc ······}
06af5a
de7589 ······if (e & 32)
b68667 ¤   break;¤ /* Leave infinite loop */
eeaf5a
6e622e ······goto gotlength;
cbaf5a
afc2d4 getlitlength2:
c6c115 ······/* Method 2: We don't even have 20 bits available - do it bit-by-bit. */
f80958 ······t = tl + ((unsigned)b & ml);
5fb610 ······/*
7ec6af ·······* See if higher-order bits we're missing actually matter.
9f87d4 ·······* We don't have to try to fill the bit buffer, because we only get
cf89c2 ·······* here if s (number of following input bytes) is supposed to be zero.
0de9f1 ·······*/
cce79a ······if (k < (unsigned)t->bits) {
ad81a7 ········ctx->outptr = w;
907a80 ········ctx->substate = 0;
18e590 ········SAVEBITBUFEMPTY;
73d819 ········return 1;
fd42cc ······}
922f99 ······/* Actually, s is set (see GETBITSOR comment) to -1, so reset it */
5965c1 ······s = 0;
2a43e2 ······if ((e = t->exop) < 0) {
3043ab ¤   do {
1818c4 ¤   ··if (e == -128)
23f937 ¤   ····return INFERR_BADINPUT;
6211e0 ¤   ··DUMPBITS(t->bits);
60e13f ¤   ··e = -e;
701615 ··········t = t->next;
3da6cf ··case 1:
88a48e ··········NEEDBITS2(e, t[(unsigned)b & mask[e]].bits,
11a6de ····················ctx->t=t; ctx->outptr=w; ctx->numbits=e; ctx->substate=1)
e82a24 ¤   ··t += (unsigned)b & mask[e];
b11754 ¤   } while ((e = t->exop) < 0);
1b42cc ······}
7dbf77 ······DUMPBITS(t->bits);
f0f3c6 ······if (e & 16) { ········/* then it's a literal */
d2dee5 ¤   *w++ = (unsigned char)t->base;
f083f9 ¤   if (--r == 0) {
5a487f ··········/* We just filled the output buffer - return */
5e49b1 ··········SAVEBITBUF;
4e677b ··········ctx->outptr = w;
0778fa ··········ctx->substate = 0;¤   /* Restart at top of loop */
378956 ··········return 2;¤/* Output buffer full */
969371 ¤   }
9ea8da ¤   continue;
6142cc ······}
56af5a
3375bd ······if (e & 32)¤  /* EOB */
f68667 ¤   break;¤ /* Leave infinite loop */
eaaf5a
c3eb63 ······/*FALLTHROUGH*/
9f49ab ··case 2:
5536d7 ······NEEDBITS(e, ctx->t = t; ctx->outptr=w; ctx->numbits=e; ctx->substate=2)
bfaf5a
2e92c7 gotlength:
8baf5a
0e228a ······/* All data is available - compute total length of block to copy */
cc7a22 ······n = t->base + ((unsigned)b & mask[e]);
631ddf ······DUMPBITS((unsigned)e);
15af5a
33eb63 ······/*FALLTHROUGH*/
061377 ··case 3:
--ec9d 000a6f5d43840100130 Page 19 of pgpZInflate.c
0e43aa ······/* Get distance code - 15 is maximum code size */
d614af ······GETBITSOR(15, goto getdistance2)
f72682 ······t = td + ((unsigned)b & md);
da4960 ······/* Negative t->exop means there's a subtable of 2^-e entries */
3043e2 ······if ((e = t->exop) < 0) {
2943ab ¤   do {
f318c4 ¤   ··if (e == -128)
916c13 ¤   ····return INFERR_BADINPUT;¤/* Invalid code (static table case) */
5c11e0 ¤   ··DUMPBITS(t->bits);
c8e13f ¤   ··e = -e;
23b562 ¤   ··t = t->next + ((unsigned)b & mask[e]);
361754 ¤   } while ((e = t->exop) < 0);
7842cc ······}
4fc388 ······goto gotdistance;
84af5a
7049a4 getdistance2:
e49f8f ······/* We don't even have 15 bits available - do it bit-by-bit. */
b42682 ······t = td + ((unsigned)b & md);
45b610 ······/*
09c6af ·······* See if higher-order bits we're missing actually matter.
4d87d4 ·······* We don't have to try to fill the bit buffer, because we only get
c489c2 ·······* here if s (number of following input bytes) is supposed to be zero.
76e9f1 ·······*/
46e79a ······if (k < (unsigned)t->bits) {
9c81a7 ········ctx->outptr = w;
ff6d21 ········ctx->copylen = n;
f795e4 ········ctx->substate = 3;
3ee590 ········SAVEBITBUFEMPTY;
f1d819 ········return 1;
7442cc ······}
88f5f3 ······/* Actually (see GETBITSOR comment) s is set to -1, so reset it */
c765c1 ······s = 0;
e04960 ······/* Negative t->exop means there's a subtable of 2^-e entries */
0243e2 ······if ((e = t->exop) < 0) {
5c43ab ¤   do {
eb18c4 ¤   ··if (e == -128)
a66c13 ¤   ····return INFERR_BADINPUT;¤/* Invalid code (static table case) */
a911e0 ¤   ··DUMPBITS(t->bits);
a6e13f ¤   ··e = -e;
f46bc1 ¤   ··t = t->next;
969f72 ··case 4:
a711ea ··········NEEDBITS2(e, t[(unsigned)b & mask[e]].bits, ctx->t=t; ctx->outptr=w;
1fad08 ·······················ctx->copylen = n; ctx->numbits=e; ctx->substate=4)
582a24 ¤   ··t += (unsigned)b & mask[e];
b81754 ¤   } while ((e = t->exop) < 0);
5842cc ······}
90af5a
9d0fe5 gotdistance:
4731b9 ······/* All data is available - compute the base distance */
97bf77 ······DUMPBITS(t->bits);
f47b67 ······d = t->base;
86eb63 ······/*FALLTHROUGH*/
80c5ae ··case 5:
ebba37 ······/* e is number of bits extra following distance code (0..13) */
e52093 ······NEEDBITS(e, ctx->outptr=w; ctx->copylen=n; ctx->distbase=d;
ad046a ··················ctx->numbits=e; ctx->substate=5)
5be596 ······d += ((unsigned)b & mask[e]);
ee1ddf ······DUMPBITS((unsigned)e);
b7af5a
9e512f #if WSIZE < 32768
fcaac5 ······if (d > ctx->slidelen)
3064fa ¤   return INFERR_BADINPUT;
f27454 #endif
0faf5a
80921b ······/* do the copy, with handling for wrapping around end of buffer */
e6f1f8 ······if ((unsigned)(w - ctx->slide) >= d && w + n < ctx->slideend - 2) {
fb78d3 ········/* Simple case - neither source nor dest cross end of buffer */
747bb4 ¤   p = w - d;
b6b88d ¤   r -= n + 2;
a43e0c ¤   *w++ = *p++;
6b3e0c ¤   *w++ = *p++;
a643ab ¤   do {
--8037 000a24a942340100130 Page 20 of pgpZInflate.c
3dcc80 ¤   ··*w++ = *p++;
7f93b7 ¤   } while (--n);
00cfc7 ······} else {
a8cb1e ¤   n += 2;¤/* # of bytes to copy */
418f34 ¤   p = ctx->slide + ((w - ctx->slide - d) & ctx->slidemask); ·/* src */
9243ab ¤   do {
4d9680 ··········/* Set e to number of bytes we can copy at once */
4b42e4 ¤   ··n -= (e = (unsigned)(e = ctx->slideend - (p>w?p:w)) > n ? n : e);
012742 ¤   ··r -= e;
1d95e7 ¤   ··do {
e23d71 ¤   ····*w++ = *p++;
45a253 ¤   ··} while (--e);
e95273 ¤   ··if (r == 0) {¤/* Did we just write everything we could? */
d6b46d ············SAVEBITBUF;
a513d8 ············ctx->outptr = w;
62e6c3 ············ctx->copylen = n;
18a268 ············ctx->distbase = d;¤ /* Save copy distance to recompute p */
fd68ce ············ctx->substate = 6;
d001f6 ············return 2;¤  /* Need more output space */
932aca ··case 6:
dc8a0d ¤   ····p = ctx->slide + ((w - ctx->slide - d) & ctx->slidemask);
7d32a2 ¤   ··}
ea6003 ¤   ··if (p == ctx->slideend)
911874 ¤   ····p = ctx->slide;
253390 ¤   } while (n);
fe42cc ······}
94123c ····} /* for(;;) */
1d4bbe ··} /* switch(ctx->subcase) */
ecaf5a
f0147e EOB:
c2ffc0 ··/* End of Block */
0fa9a1 ··ctx->outptr = w;
57ef9a ··SAVEBITBUF;
edead8 ··ctx->state = STATE_START;
80831a ··ctx->substate = 0;
40af5a
d40901 ··if (tl && tl != ctx->fixed_tl)
21de35 ····huft_free(ctx->context, tl);
a85ff3 ··if (td && td != ctx->fixed_td)
8c4f54 ····huft_free( ctx->context, td);
54f76e ··ctx->tree1 = 0;
425f00 ··ctx->tree2 = 0;
68af5a
00212b ··return 0;
30efe6 }
c1af5a
b1af5a
ef38e5 /*
5a3d8a ·* Start state - read 3 bits, which are last block flag (set to 1 on
454ad7 ·* last block), and 2 bits of block type.
8f495d ·*/
a5beb7 static int
2808c7 infStart(InflateContext *ctx)
7fbb36 {
9bc78b ¤   ulg b;
08c187 ¤   unsigned k;
b8bd4b ¤   int s;
2adb56 ¤   unsigned char const *g;
35d9ae ¤   int retval = 0;
4faf5a
98e632 ¤   if (ctx->lastblock) {
f907d3 ¤   ¤   ctx->state = STATE_DONE;
57bbde ¤   ¤   return 0;
319371 ¤   }
d8af5a
dccea1 ¤   LOADBITBUF;
45fcc2 ¤   NEEDBITS(3, (void)0);
b5af5a
62f6dc ¤   ctx->lastblock = (int)(b & 1);
a716ee ¤   DUMPBITS(1);
b4af5a
a23084 ¤   switch(b & 3) {
--2629 000113b559640100130 Page 21 of pgpZInflate.c
05207e ¤   case 0:¤/* Stored */
37a831 ¤   ¤   ctx->state = STATE_STOREDLEN;
ab2f68 ¤   ¤   break;
b54ec7 ¤   case 1: /* Static - build fixed trees and start decoding */
806598 ¤   ¤   retval = infFixedTree( ctx );
ae5732 ¤   ¤   ctx->tree1 = ctx->fixed_tl;
b76c51 ¤   ¤   ctx->bits1 = ctx->fixed_bl;
562c3a ¤   ¤   ctx->tree2 = ctx->fixed_td;
f51759 ¤   ¤   ctx->bits2 = ctx->fixed_bd;
ceba05 ¤   ¤   ctx->state = STATE_INFLATE;
5d2f68 ¤   ¤   break;
513570 ¤   case 2: /* Dynamic */
ab7bd5 ¤   ¤   ctx->state = STATE_DYN_HDR;
562f68 ¤   ¤   break;
2af32f ¤   case 3: /* Illegal */
0ff967 ¤   ¤   retval = INFERR_BADINPUT;
292f68 ¤   ¤   break;
709371 ¤   }
01af5a
3d3323 ¤   DUMPBITS(2);
4b418a ¤   SAVEBITBUF;
daaf5a
3d8fb3 ¤   ctx->substate = 0;
0094b6 ¤   return retval;
12efe6 }
d9af5a
8b38e5 /*
bce74c ·* Get a pointer to available data in the output buffer
2b495d ·*/
83c3bb unsigned char const *
97f1b5 infGetBytes(InflateContext *ctx, unsigned *len)
8ebb36 {
0aefc9 ¤   *len = ctx->outptr - ctx->readptr;
21842d ¤   return *len ? ctx->readptr : 0;
eaefe6 }
cbaf5a
5238e5 /*
0f19ec ·* Mark data in the output buffer as already read. ·We don't start
7cab87 ·* accepting new data until the entire output buffer has been read,
242bc8 ·* at which point the outptr is set back to the beginning of the
622392 ·* buffer.
35495d ·*/
2d314a void
41f7cf infSkipBytes(InflateContext *ctx, unsigned len)
1bbb36 {
40420c ¤   pgpAssert(len <= (unsigned)(ctx->outptr - ctx->readptr));
55af5a
8fc7e8 ¤   ctx->readptr += len;
3eaf5a
79bc62 ¤   /* If at end of buffer, recirculate */
b47997 ¤   if (ctx->readptr == ctx->slideend) {
90f4d4 ¤   ¤   pgpAssert(ctx->outptr == ctx->slideend);
558898 ¤   ¤   ctx->readptr = ctx->outptr = ctx->slide;
e19371 ¤   }
7eefe6 }
9aaf5a
35af5a
e138e5 /*
91e435 ·* Returns number of bytes written.
d4bbd8 ·* *error < 0 on error, == 0 if no error (done with input or output full)
87495d ·*/
ab44d2 size_t
030b8a infWrite(InflateContext *ctx, unsigned char const *buf, size_t len,
2e1bdb ·········PGPError *error)
acbb36 {
3e6434 ¤   int i¤  = 0;
0caf5a
0fefe1 ¤   if (ctx->outptr == ctx->slideend) {
7df7d9 ¤   ¤   *error = (ctx->state == STATE_STOP) ?
4fae3e ¤   ¤   ¤   kPGPError_NoErr : (PGPError)ctx->substate;
7f9b79 ¤   ¤   return 0;¤  /* Out of output space! */
119371 ¤   }
--29b6 000ead5873d40100130 Page 22 of pgpZInflate.c
e0af5a
f0f96b ¤   ctx->inptr = buf;
54c2a9 ¤   /* Decompression code can't handle more than INT_MAX bytes at a time */
a245bc ¤   ctx->inlen = len > INT_MAX ? INT_MAX : (int)len;
ceaf5a
ba43ab ¤   do {
a0bf27 ¤   ¤   switch(ctx->state) {
fbe6e2 ¤   ¤   ··case STATE_START:
bcaccd ¤   ¤   ¤   i = infStart(ctx);
23cdcb ¤   ¤   ¤   break;
c12f51 ¤   ¤   ··case STATE_STOREDLEN:
e6e6dd ¤   ¤   ¤   i = infStoredLen(ctx);
1dcdcb ¤   ¤   ¤   break;
52ab79 ¤   ¤   ··case STATE_STORED:
2cd917 ¤   ¤   ¤   i = infStored(ctx);
8fcdcb ¤   ¤   ¤   break;
544e4f ¤   ¤   ··case STATE_DYN_HDR:
2d006e ¤   ¤   ¤   i = infDynHdr(ctx);
5bcdcb ¤   ¤   ¤   break;
5724f6 ¤   ¤   ··case STATE_DYN_BITS:
8134ed ¤   ¤   ¤   i = infDynBits(ctx);
21cdcb ¤   ¤   ¤   break;
f00146 ¤   ¤   ··case STATE_DYN_TREE:
948b6d ¤   ¤   ¤   i = infDynTree(ctx);
0bcdcb ¤   ¤   ¤   break;
d58f9f ¤   ¤   ··case STATE_INFLATE:
e59a15 ¤   ¤   ¤   i = infInflate(ctx);
07cdcb ¤   ¤   ¤   break;
893c99 ¤   ¤   ··case STATE_DONE:
103d08 ¤   ¤   ¤   if (ctx->inlen || ctx->bufbits > 7)
128298 ¤   ¤   ¤   ¤   i = INFERR_LONG;
2353c1 #if STRICT
026a47 ¤   ¤   ¤   else if (ctx->bitbuffer & mask[ctx->bufbits])
bc9a23 ¤   ¤   ¤   ¤   i = INFERR_BADINPUT;¤   /* Unused bits != 0 */
9c7454 #endif
b6bb8c ¤   ¤   ¤   else
53d723 ¤   ¤   ¤   ¤   i = 2;¤ /* Read output, please */
4dcdcb ¤   ¤   ¤   break;
8131c7 ¤   ¤   ··case STATE_STOP:
37a497 ¤   ¤   ¤   i = ctx->substate;
66cdcb ¤   ¤   ¤   break;
631584 ¤   ¤   ··default:
0ea780 ¤   ¤   ··¤ i¤  = 0;
d27fba ¤   ¤   ··¤ pgpDebugMsg( "impossible state" );
200d5e ¤   ¤   ··¤ break;
0b0fe4 ¤   ¤   }
fcdf11 ¤   } while (i == 0);
86af5a
b27a6f ¤   if (i < 0) {
3c0a8d ¤   ¤   ctx->state = STATE_STOP;
ee72af ¤   ¤   ctx->substate = i;
25fab6 ¤   ¤   *error = (PGPError)i;
e9f037 ¤   } else {
10a79e ¤   ¤   *error = kPGPError_NoErr;
5e9371 ¤   }
dcaf5a
e5c74c ¤   pgpAssert((size_t)(ctx->inptr - buf) == len - ctx->inlen);
2f336f ¤   return (size_t)(ctx->inptr - buf);¤ /* Bytes read */
b3efe6 }
a8af5a
f638e5 /*
8e93ac ·* Signal EOF, detecting truncated messages.
c3b33d ·* If another error has been reported, this just repeats it.
40495d ·*/
f18cad /* New version, hopefully useful. */
314d2f int
50d242 infEOF(InflateContext *ctx)
c2bb36 {
94f87f ¤   /* If processing is halted, just return the last error (if any) */
a3aeb6 ¤   if (ctx->state == STATE_STOP)
00531d ¤   ¤   return ctx->substate;
eaaf5a
--abe1 0004088e01740100130 Page 23 of pgpZInflate.c
024f89 ¤   /* If expecting still more input, we're short */
d278c7 ¤   if (ctx->state != STATE_DONE)
82734f ¤   ¤   return INFERR_SHORT;
29af5a
9aef59 ¤   /* Otherwise, all is well. */
cabbde ¤   ¤   return 0;
8befe6 }
e6af5a
03b4ba InflateContext *
e8f3f2 infAlloc( PGPContextRef¤context )
28bb36 {
1886f4 ¤   InflateContext *ctx;
d94932 ¤   unsigned char *slide;
6caf5a
00d195 ¤   slide = (unsigned char *)pgpContextMemAlloc( context,
492723 ¤   ¤   ¤   WSIZE, kPGPMemoryMgrFlags_Clear);
3f5311 ¤   if (!slide)
f6bbde ¤   ¤   return 0;
5bb41e ¤   ctx = (InflateContext *)pgpContextMemAlloc( context,
985a5c ¤   ¤   ¤   sizeof(*ctx), kPGPMemoryMgrFlags_Clear);
ec7880 ¤   if (!ctx) {
3640d7 ¤   ¤   pgpContextMemFree( context, slide);
85bbde ¤   ¤   return 0;
329371 ¤   }
4dfc88 ¤   ctx->context¤   = context;
2e31dd ¤   ctx->slide = slide;
e8a483 ¤   ctx->slideend = slide+WSIZE;
eb944b ¤   ctx->slidelen = WSIZE;
fd1cf3 ¤   ctx->slidemask = WSIZE-1;
86af5a
7c3ad5 ¤   ctx->outptr = slide;
093348 ¤   ctx->readptr = slide;
57af5a
9a7f8b ¤   ctx->state = STATE_START;
678fb3 ¤   ctx->substate = 0;
ebbfc3 ¤   ctx->inlen = 0;
0e95ed ¤   ctx->bitbuffer = 0;
2d3250 ¤   ctx->bufbits = 0;
3ca2f5 ¤   ctx->lastblock = 0;
e7af5a
c12b03 ¤   ctx->tree1 = 0;
ad836d ¤   ctx->tree2 = 0;
2eaf5a
135dd0 ¤   return ctx;
c3efe6 }
2daf5a
bc314a void
069234 infFree(InflateContext *ctx)
59bb36 {
5d1819 ¤   PGPContextRef context = ctx->context;
39af5a
f5c3a8 ¤   if (ctx->tree1 && ctx->tree1 != ctx->fixed_tl)
3d62d4 ¤   ¤   huft_free(context, ctx->tree1);
8c9ee6 ¤   if (ctx->tree2 && ctx->tree2 != ctx->fixed_td)
f74719 ¤   ¤   huft_free(context, ctx->tree2);
0567c5 ¤
ecf86f ¤   if ( IsntNull( ctx->fixed_tl ) )
33c7a1 ¤   {
3019fa ¤   ¤   huft_free(context, ctx->fixed_tl);
a2b79a ¤   ¤   ctx->fixed_tl¤  = NULL;
3f9371 ¤   }
cdd937 ¤   if ( IsntNull( ctx->fixed_td ) )
3fc7a1 ¤   {
47fc22 ¤   ¤   huft_free(context, ctx->fixed_td);
01b79a ¤   ¤   ctx->fixed_tl¤  = NULL;
1c9371 ¤   }
20af5a
85c24a ¤   if (ctx->slide) {
ddadcb #if SECURE
bfa6e4 ¤   ¤   pgpClearMemory(ctx->slide, ctx->slidelen);
287454 #endif
402307 ¤   ¤   pgpContextMemFree( context, ctx->slide);
--0113 001d72ecaa740100130 Page 24 of pgpZInflate.c
a19371 ¤   }
eaadcb #if SECURE
30d71d ¤   pgpClearMemory( ctx, ·sizeof(*ctx));
9d7454 #endif
c1a0fd ¤   pgpContextMemFree( context, ctx);
d7efe6 }
--42e1 00161cb449440100131 Page 1 of pgpZInflate.h
bc38e5 /*
480305 ·* pgpZInflate.h - inflate a zip-compressed stream of bytes.
73775e ·*
c3e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
182979 ·* You should not be using these functions in an application.
83775e ·*
43c22f ·* $Id: pgpZInflate.h,v 1.5 1997/06/28 00:21:32 lloyd Exp $
4c495d ·*/
d0af5a
64c546 #include <stddef.h>¤/* For size_t */
d6af5a
d6c26c #include "pgpContext.h"
c5af5a
abaf5a
1299c6 PGP_BEGIN_C_DECLARATIONS
a9af5a
0f3829 /* Private context structure */
a69a80 struct InflateContext;
ccbbd9 #ifndef TYPE_InflateContext
d4a72e #define TYPE_InflateContext 1
b058a3 typedef struct InflateContext InflateContext;
757454 #endif
e1af5a
23337d InflateContext *infAlloc(PGPContextRef¤ context);
827484 void infFree(InflateContext *ctx);
72af5a
c88a1d /* Write bytes. ·Returns bytes written. ·error < 0 if trouble */
475200 size_t infWrite(InflateContext *ctx, unsigned char const *buf,·
629ee2 ¤   size_t len, PGPError *error);
9e67d0 /* Get pointer & len of available output bytes */
525795 unsigned char const *infGetBytes(InflateContext *ctx, unsigned *len);
be14c9 /* Tell InflateContext that you've read "len" of available bytes */
90282f void infSkipBytes(InflateContext *ctx, unsigned len);
544bda /* Returns 0 for okay, or <0 for error */
747a7b int infEOF(InflateContext *ctx);
4eaf5a
6c1254 PGP_END_C_DECLARATIONS
50af5a
8c0f88 /* Error codes returned. */
8c88e1 #define INFERR_NONE¤0
a61150 #define INFERR_NOMEM¤   -1¤ /* Unable to allocate as needed */
1a2144 #define INFERR_BADINPUT¤-2¤ /* Corrupt input */
d0fe9a #define INFERR_SHORT¤   -3¤ /* Unexpected EOF */
61d8fb #define INFERR_LONG¤-4¤ /* Padding after expected EOF */
--5429 001657537f840100132 Page 1 of Makefile.in
5ea601 #
d9c1c5 # priv/crypto/hash/
38a601 #
85a88a # $Id: Makefile.in,v 1.10 1998/07/27 19:35:02 heller Exp $
46a601 #
19af5a
90f065 OBJS=¤  pgpHash.o pgpMD5.o pgpSHA.o pgpRIPEMD160.o pgpHMAC.o \
8c44eb ¤   pgpMD2.o
2d2e62 PRIVHDRS= pgpHashPriv.h pgpMD5.h pgpSHA.h pgpMD2.h
30af5a
c5b7a3 all:: DONE
65af5a
--42be 0009323c80e40100133 Page 1 of pgpHMAC.c
a70335 /*____________________________________________________________________________
f2d7a0 ¤   pgpHMAC.c
d867c5 ¤
40c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
954b0f ¤   All rights reserved.
19af5a
7bcd53 ¤   $Id: pgpHMAC.c,v 1.5.10.1 1998/11/12 03:21:22 heller Exp $
65f7f7 ____________________________________________________________________________*/
f7e2ff #include "pgpConfig.h"
862f8d #include "pgpErrors.h"
710d08 #include "pgpMem.h"
56af5a
2ba590 #include "pgpHMAC.h"
fe9f72 #include "pgpHash.h"
0d5430 #include "pgpUtilitiesPriv.h"
7faf5a
d0081a #define kPGPHMAC_ipad¤  ¤   ¤   0x36
1a8369 #define kPGPHMAC_opad¤  ¤   ¤   0x5C
68af0d #define kPGPHMAC_MaxHashBlock¤  64
c3af5a
dfaf5a
39bba3 struct PGPHMACContext
49bb36 {
987193 #define kHMACContextMagic¤  ¤   0xEBBADBBA
29b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
5ff7f4 ¤   PGPMemoryMgrRef¤¤   memoryMgr;
3f1dcc ¤   PGPHashContextRef¤  hash;
010275 ¤   PGPByte *¤  ¤   ¤   secret;
365300 ¤   PGPSize¤¤   ¤   ¤   secretLen;
7c82f7 };
3aaf5a
136c2c ¤   static PGPBoolean
84bb3b pgpHMACContextIsValid( PGPHMACContextRef ref)
1ebb36 {
447088 ¤   return( IsntNull( ref ) &&
17a1d4 ¤   ¤   ¤   IsntNull( ref->hash ) &&
ceb3db ¤   ¤   ¤   ref->magic == kHMACContextMagic ·);
acefe6 }
49af5a
0baf5a
b8eb95 #define pgpValidateHMAC( ref )¤ ¤   \
48e0f2 ¤   PGPValidateParam( pgpHMACContextIsValid( ref ) )
3267c5 ¤
9921ab ¤   PGPError·
4a8988 PGPNewHMACContext(
632f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
911f74 ¤   PGPHashAlgorithm¤   algorithm,
24daec ¤   PGPByte *¤  ¤   ¤   secret,
4a8b99 ¤   PGPSize¤¤   ¤   ¤   secretLen,
b500d3 ¤   PGPHMACContextRef *¤outRef )
38bb36 {
30d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
c1f7fa ¤   PGPHMACContextRef¤  ref = NULL;
2167c5 ¤
203c76 ¤   PGPValidatePtr( outRef );
953652 ¤   *outRef¤= NULL;
21ad91 ¤   PGPValidateMemoryMgr( memoryMgr );
b367c5 ¤
bc1f9a ¤   ref¤= (PGPHMACContextRef) PGPNewData( memoryMgr, sizeof( *ref ),
d5a90e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
7af439 ¤   if ( IsntNull( ref ) )
1fc7a1 ¤   {
055339 ¤   ¤   ref->magic = kHMACContextMagic;
974181 ¤   ¤   ref->memoryMgr¤ = memoryMgr;
1090a3 ¤   ¤   err = PGPNewHashContext( memoryMgr, algorithm, &ref->hash );
3abe18 ¤   ¤   if ( IsPGPError( err ) )
d01dc4 ¤   ¤   ¤   goto done;
3d1b52 ¤   ¤
12890b ¤   ¤   if( secretLen > kPGPHMAC_MaxHashBlock )
2b5b34 ¤   ¤   {
32184b ¤   ¤   ¤   /* revert it down to the hash size */
93f3c2 ¤   ¤   ¤   err = PGPGetHashSize( ref->hash, &ref->secretLen );
--7b0d 0004d8d837140100133 Page 2 of pgpHMAC.c
dd59df ¤   ¤   ¤   if( IsPGPError( err ) )
8cff25 ¤   ¤   ¤   ¤   goto done;
761090 ¤   ¤   ¤   ref->secret¤= (PGPByte *) PGPNewSecureData( memoryMgr,
33251b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ref->secretLen, 0 );
823935 ¤   ¤   ¤   if ( IsNull( ref->secret ) )
2bf776 ¤   ¤   ¤   {
ec14f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
93ff25 ¤   ¤   ¤   ¤   goto done;
31a3a6 ¤   ¤   ¤   }
ddca19 ¤   ¤   ¤   err = PGPContinueHash( ref->hash, secret, secretLen );
f259df ¤   ¤   ¤   if( IsPGPError( err ) )
efff25 ¤   ¤   ¤   ¤   goto done;
b1114a ¤   ¤   ¤   err = PGPFinalizeHash( ref->hash, ref->secret );
1859df ¤   ¤   ¤   if( IsPGPError( err ) )
50ff25 ¤   ¤   ¤   ¤   goto done;
400fe4 ¤   ¤   }
6b0e1d ¤   ¤   else
d95b34 ¤   ¤   {
a33b36 ¤   ¤   ¤   ref->secretLen = secretLen;
8a4c42 ¤   ¤   ¤   ref->secret¤= ·(PGPByte *) PGPNewSecureData( memoryMgr,
bda030 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   secretLen, 0 );
9a3935 ¤   ¤   ¤   if ( IsNull( ref->secret ) )
01f776 ¤   ¤   ¤   {
7d14f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
75ff25 ¤   ¤   ¤   ¤   goto done;
8ba3a6 ¤   ¤   ¤   }
d39cc3 ¤   ¤   ¤   pgpCopyMemory( secret, ref->secret, secretLen );
470fe4 ¤   ¤   }
7027b8 ¤   ¤   err = PGPResetHMAC( ref );
4a9371 ¤   }
a90e24 ¤   else
ff17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
c3b38c done:
667f7d ¤   if( IsPGPError( err ) )
22c7a1 ¤   {
0f3c44 ¤   ¤   if( PGPHMACContextRefIsValid( ref ) )
305b34 ¤   ¤   {
018688 ¤   ¤   ¤   if( PGPHashContextRefIsValid( ref->hash ) )
c7423e ¤   ¤   ¤   ¤   PGPFreeHashContext( ref->hash );
5ff4d0 ¤   ¤   ¤   if( IsntNull( ref->secret ) )
847665 ¤   ¤   ¤   ¤   PGPFreeData( ref->secret );
c5a163 ¤   ¤   ¤   PGPFreeData( ref );
88d97f ¤   ¤   ¤   ref = NULL;
f30fe4 ¤   ¤   }
dc9371 ¤   }
00ebd9 ¤   *outRef¤= ref;
00deb7 ¤   return( err );
6defe6 }
c3af5a
4d21ab ¤   PGPError·
7cd9ab PGPFreeHMACContext( PGPHMACContextRef ref )
89bb36 {
7e9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
db67c5 ¤
48ea6c ¤   pgpValidateHMAC( ref );
3067c5 ¤
57b0aa ¤   PGPFreeData( ref->secret );
ec13f6 ¤   PGPFreeHashContext( ref->hash );
cd4500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
d6fa58 ¤   PGPFreeData( ref );
0867c5 ¤
a1deb7 ¤   return( err );
74efe6 }
feaf5a
5321ab ¤   PGPError·
b9f8b4 PGPResetHMAC( PGPHMACContextRef ref )
39bb36 {
6926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d767c5 ¤
56ea6c ¤   pgpValidateHMAC( ref );
2a67c5 ¤
4db5cf ¤   err = PGPResetHash( ref->hash );
--3e19 0001b72f86040100133 Page 3 of pgpHMAC.c
54b1f0 ¤   if( IsntPGPError( err ) )
f1c7a1 ¤   {
26b6ce ¤   ¤   PGPByte¤¤   bstr[kPGPHMAC_MaxHashBlock];
237fce ¤   ¤   PGPUInt32¤  bindex;
231b52 ¤   ¤
4969c5 ¤   ¤   pgpCopyMemory( ref->secret, bstr, ref->secretLen );
92e26c ¤   ¤   for( bindex = ref->secretLen; bindex < kPGPHMAC_MaxHashBlock; bindex++ )
ccc284 ¤   ¤   ¤   bstr[bindex] = '\0';
9bf18a ¤   ¤   for( bindex = 0; bindex < kPGPHMAC_MaxHashBlock; bindex++ )
7d7da4 ¤   ¤   ¤   bstr[bindex] ^= kPGPHMAC_ipad;
f37128 ¤   ¤   err = PGPContinueHash( ref->hash, bstr, kPGPHMAC_MaxHashBlock );
299371 ¤   }
0b67c5 ¤
e6deb7 ¤   return( err );
cbefe6 }
73af5a
f021ab ¤   PGPError·
2b628e PGPContinueHMAC(
37467f ¤   PGPHMACContextRef¤  ref,
8a08cf ¤   const void *¤   ¤   in,
7a7cf5 ¤   PGPSize¤¤   ¤   ¤   numBytes )
5abb36 {
7126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d267c5 ¤
e5ea6c ¤   pgpValidateHMAC( ref );
b63bf7 ¤   PGPValidatePtr( in );
3eaf5a
40147d ¤   if ( numBytes != 0 )
5ee4e3 ¤   ¤   err = PGPContinueHash( ref->hash, in, numBytes );
d867c5 ¤
fedeb7 ¤   return( err );
85efe6 }
74af5a
2621ab ¤   PGPError·
a64c59 PGPFinalizeHMAC(
5c467f ¤   PGPHMACContextRef¤  ref,
f56eb1 ¤   void *¤ ¤   ¤   ¤   hmacOut )
e8bb36 {
23d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
b9e769 ¤   PGPSize¤¤   ¤   ¤   hashSize;
9f5dda ¤   PGPByte¤¤   ¤   ¤   bstr[kPGPHMAC_MaxHashBlock];
7425ef ¤   PGPUInt32¤  ¤   ¤   bindex;
5767c5 ¤
4eea6c ¤   pgpValidateHMAC( ref );
b8b9ae ¤   PGPValidatePtr( hmacOut );
b367c5 ¤
649793 ¤   (void)PGPGetHashSize( ref->hash, &hashSize);
f7d6ce ¤   err = PGPFinalizeHash( ref->hash, hmacOut );
1d7f7d ¤   if( IsPGPError( err ) )
bc262d ¤   ¤   goto done;
48b5cf ¤   err = PGPResetHash( ref->hash );
2d7f7d ¤   if( IsPGPError( err ) )
94262d ¤   ¤   goto done;
85e692 ¤   pgpCopyMemory( ref->secret, bstr, ref->secretLen );
0bb0bc ¤   for( bindex = ref->secretLen; bindex < kPGPHMAC_MaxHashBlock; bindex++ )
cc79d2 ¤   ¤   bstr[bindex] = '\0';
ffcce4 ¤   for( bindex = 0; bindex < kPGPHMAC_MaxHashBlock; bindex++ )
3a6b12 ¤   ¤   bstr[bindex] ^= kPGPHMAC_opad;
92765e ¤   err = PGPContinueHash( ref->hash, bstr, kPGPHMAC_MaxHashBlock );
db7f7d ¤   if( IsPGPError( err ) )
66262d ¤   ¤   goto done;
03d423 ¤   err = PGPContinueHash( ref->hash, hmacOut, hashSize );
cd7f7d ¤   if( IsPGPError( err ) )
ae262d ¤   ¤   goto done;
c7d6ce ¤   err = PGPFinalizeHash( ref->hash, hmacOut );
557f7d ¤   if( IsPGPError( err ) )
d1262d ¤   ¤   goto done;
20b38c done:
acdeb7 ¤   return( err );
81efe6 }
73af5a
1baf5a
--6585 001dffab6e240100133 Page 4 of pgpHMAC.c
217e4d /*__Editor_settings____
c9af5a
864126 ¤   Local Variables:
f87b17 ¤   tab-width: 4
5c0e6c ¤   End:
b85f8c ¤   vi: ts=4 sw=4
a09e9b ¤   vim: si
dfd062 _____________________*/
--a441 00048d77bec40100134 Page 1 of pgpHash.c
a70335 /*____________________________________________________________________________
2eee2b ¤   pgpHash.c
2467c5 ¤
e3c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
ae4b0f ¤   All rights reserved.
c067c5 ¤
7967c5 ¤
53af5a
eb4efa ¤   $Id: pgpHash.c,v 1.39.10.1 1998/11/12 03:21:23 heller Exp $
f7f7f7 ____________________________________________________________________________*/
a2e2ff #include "pgpConfig.h"
d52f8d #include "pgpErrors.h"
d80d08 #include "pgpMem.h"
67af5a
26a301 #include "pgpMD5.h"
9893dd #include "pgpMD2.h"
d199fe #include "pgpSHA.h"
946f37 #include "pgpRIPEMD160.h"
c6af5a
cc9f72 #include "pgpHash.h"
ae5417 #include "pgpHashPriv.h"
2a5430 #include "pgpUtilitiesPriv.h"
f6af5a
2baf5a
5daf5a
b2c38b struct PGPHashContext
3fbb36 {
d5385a #define kHashContextMagic¤  ¤   0xABBADABA
5fb5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
014f79 ¤   PGPHashVTBL const *¤vtbl;
b7f7f4 ¤   PGPMemoryMgrRef¤¤   memoryMgr;
bc46f5 ¤   void *¤ ¤   ¤   ¤   hashData;
4d82f7 };
4faf5a
cfaaf6 struct PGPHashList
1ebb36 {
5474dd ¤   PGPUInt32¤  ¤   numHashes;
dad91c ¤   PGPMemoryMgrRef¤memoryMgr;
232f2c ¤   PGPHashContext¤ hashes[ 1 ];¤   /* open ended */
e982f7 };
38af5a
06ad07 static void¤sDisposeHashData( PGPHashContextRef¤ref );
60af5a
5aaf5a
ce9fab #define CallInit(hc)¤   (hc)->vtbl->init((hc)->hashData)
47bc0e #define CallUpdate(hc, buf, len) (hc)->vtbl->update((hc)->hashData, buf, len)
54eb78 #define CallFinal(hc) (hc)->vtbl->final((hc)->hashData)
6baf5a
0caf5a
9e6c2c ¤   static PGPBoolean
88a2d4 pgpHashContextIsValid( const PGPHashContext * ref)
73bb36 {
a27088 ¤   return( IsntNull( ref ) &&
b7c482 ¤   ¤   ¤   IsntNull( ref->hashData ) &&
fd9eed ¤   ¤   ¤   ref->magic == kHashContextMagic ·);
0eefe6 }
71af5a
d5af5a
41b2a3 #define pgpValidateHash( ref )¤ ¤   \
83deca ¤   PGPValidateParam( pgpHashContextIsValid( ref ) )
4367c5 ¤
9c4353 #define IsValidAlgorithm( alg )¤¤   \
c29497 ¤   IsntNull( pgpHashByNumber( alg ) )
05af5a
cdaf5a
2566dd ¤   static PGPError
4d9a72 sHashInit(
65b82b ¤   PGPHashContextRef¤  ¤   ref,
156d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
0a9c60 ¤   PGPHashAlgorithm¤   ¤   algorithm )
c5bb36 {
489479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
--b410 00006bdba4d40100134 Page 2 of pgpHash.c
2a67c5 ¤
a44500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
578318 ¤   ref->magic¤ ¤   = kHashContextMagic;
227ce9 ¤   ref->memoryMgr¤ = memoryMgr;
305009 ¤   ref->vtbl¤  ¤   = pgpHashByNumber( algorithm );
08d4a1 ¤   pgpAssert( IsntNull( ref->vtbl ) );
ee67c5 ¤
4d9595 ¤   ref->hashData¤  = PGPNewData( memoryMgr,
136b0a ¤   ¤   ref->vtbl->context_size, 0);
cab174 ¤   if ( IsntNull( ref->hashData ) )
40c7a1 ¤   {
847a68 ¤   ¤   CallInit( ref );
a49371 ¤   }
490e24 ¤   else
dfc7a1 ¤   {
9f17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
8c9371 ¤   }
4367c5 ¤
acdeb7 ¤   return( err );
9befe6 }
8baf5a
49af5a
2c66dd ¤   static PGPError
9436c6 sHashCreate(
626d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
5c132b ¤   PGPHashAlgorithm¤   ¤   algorithm,
e52d64 ¤   PGPHashContextRef *¤¤   outRef )
85bb36 {
83e870 ¤   PGPHashContextRef¤  ¤   ref¤= NULL;
289479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
4a67c5 ¤
703652 ¤   *outRef¤= NULL;
8f67c5 ¤
e0c4c7 ¤   ref¤= (PGPHashContextRef)
268f34 ¤   ¤   PGPNewData( memoryMgr, sizeof( *ref ),
ed5caa ¤   ¤   ¤   0 | kPGPMemoryMgrFlags_Clear );
5267c5 ¤
4af439 ¤   if ( IsntNull( ref ) )
92c7a1 ¤   {
b47abb ¤   ¤   err¤= sHashInit( ref, memoryMgr, algorithm );
e41b52 ¤   ¤
a9be18 ¤   ¤   if ( IsPGPError( err ) )
a45b34 ¤   ¤   {
6ca163 ¤   ¤   ¤   PGPFreeData( ref );
cf224d ¤   ¤   ¤   ref¤= NULL;
370fe4 ¤   ¤   }
159371 ¤   }
020e24 ¤   else
15c7a1 ¤   {
0e17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
8d9371 ¤   }
ec67c5 ¤
c7ebd9 ¤   *outRef¤= ref;
b3deb7 ¤   return( err );
e0efe6 }
28af5a
7baf5a
73af5a
76af5a
a221ab ¤   PGPError·
c724ba PGPNewHashContext(
9b2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
001f74 ¤   PGPHashAlgorithm¤   algorithm,
d0eb46 ¤   PGPHashContextRef *¤outRef )
e1bb36 {
2a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6e67c5 ¤
723c76 ¤   PGPValidatePtr( outRef );
e83652 ¤   *outRef¤= NULL;
daad91 ¤   PGPValidateMemoryMgr( memoryMgr );
d42ffd ¤   PGPValidateParam( IsValidAlgorithm( algorithm ) );
0667c5 ¤
--27ba 00095d1c7f940100134 Page 3 of pgpHash.c
677ef7 ¤   err¤= sHashCreate( memoryMgr, algorithm, outRef );
9d67c5 ¤
14deb7 ¤   return( err );
a6efe6 }
64af5a
37af5a
64af5a
7e21ab ¤   PGPError·
8e5e7f PGPFreeHashContext( PGPHashContextRef ref )
e0bb36 {
3b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
9d67c5 ¤
79475e ¤   pgpValidateHash( ref );
6767c5 ¤
0c8858 ¤   sDisposeHashData(ref);
b04500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
88fa58 ¤   PGPFreeData( ref );
ae67c5 ¤
2cdeb7 ¤   return( err );
a9efe6 }
42af5a
edaf5a
6921ab ¤   PGPError·
b19194 PGPCopyHashContext(
eb12e7 ¤   PGPHashContextRef¤  ref,
5eeca7 ¤   PGPHashContextRef *¤outRef)
81bb36 {
4cd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
c2bef5 ¤   PGPHashContextRef¤  newRef¤ = NULL;
f367c5 ¤
a83c76 ¤   PGPValidatePtr( outRef );
7c3652 ¤   *outRef¤= NULL;
c6475e ¤   pgpValidateHash( ref );
e867c5 ¤
1fb201 ¤   err¤= sHashCreate( ref->memoryMgr, ref->vtbl->algorithm, &newRef );
4ff1e7 ¤   if ( IsntPGPError( err ) )
c1c7a1 ¤   {
3ef343 ¤   ¤   pgpCopyMemory( ref->hashData,
2f953e ¤   ¤   ¤   newRef->hashData, ref->vtbl->context_size );
fe1b52 ¤   ¤
c79371 ¤   }
f667c5 ¤
e3cdaf ¤   *outRef¤= newRef;
0edeb7 ¤   return( err );
d1efe6 }
d2af5a
45af5a
83af5a
3321ab ¤   PGPError·
11751d PGPResetHash( PGPHashContextRef ref )
86bb36 {
8f26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
dd67c5 ¤
30475e ¤   pgpValidateHash( ref );
e267c5 ¤
98cbb9 ¤   CallInit( ref );
bb67c5 ¤
46deb7 ¤   return( err );
31efe6 }
00af5a
6daf5a
cd21ab ¤   PGPError·
802a36 PGPContinueHash(
2212e7 ¤   PGPHashContextRef¤  ref,
d108cf ¤   const void *¤   ¤   in,
da8dce ¤   PGPSize¤¤   ¤   numBytes )
12bb36 {
4c26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9567c5 ¤
03475e ¤   pgpValidateHash( ref );
6e3bf7 ¤   PGPValidatePtr( in );
95af5a
--7f8d 00083ec33cb40100134 Page 4 of pgpHash.c
e4147d ¤   if ( numBytes != 0 )
75c7a1 ¤   {
26bf81 ¤   ¤   CallUpdate( ref, in, numBytes );
569371 ¤   }
cb67c5 ¤
3cdeb7 ¤   return( err );
b2efe6 }
31af5a
e7af5a
c621ab ¤   PGPError·
2904e1 PGPFinalizeHash(
0a12e7 ¤   PGPHashContextRef¤  ref,
87080b ¤   void *¤ ¤   ¤   ¤   hashOut )
34bb36 {
e09372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b788bb ¤   const void *¤   result;
0363ff ¤   PGPSize¤¤   ¤   hashSize;
ac67c5 ¤
b1475e ¤   pgpValidateHash( ref );
41a319 ¤   PGPValidatePtr( hashOut );
e467c5 ¤
0261fd ¤   (void)PGPGetHashSize( ref, &hashSize);
7e67c5 ¤
bb8adb ¤   result¤ = CallFinal( ref );
62827a ¤   pgpCopyMemory( result, hashOut, hashSize );
eb67c5 ¤
9ddeb7 ¤   return( err );
e1efe6 }
bdaf5a
0baf5a
2e21ab ¤   PGPError·
8a1675 PGPGetHashSize(
2912e7 ¤   PGPHashContextRef¤  ref,
716d30 ¤   PGPSize *¤  ¤   ¤   hashSize )
cfbb36 {
3026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d767c5 ¤
adfe10 ¤   PGPValidatePtr( hashSize );
930475 ¤   *hashSize¤  = 0;
83475e ¤   pgpValidateHash( ref );
9f67c5 ¤
2af503 ¤   *hashSize¤  = ref->vtbl->hashsize;
fd67c5 ¤
d6deb7 ¤   return( err );
81efe6 }
89af5a
efaf5a
b4af5a
c0af5a
06af5a
d43d76 ¤   PGPHashContextRef
10dae9 pgpHashCreate(
a42f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
23e958 ¤   PGPHashVTBL const *¤vtbl)
88bb36 {
b3d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
a37496 ¤   PGPHashContextRef¤  newRef;
6b67c5 ¤
d49e0c ¤   pgpAssert( PGPMemoryMgrIsValid( memoryMgr ) );
b967c5 ¤
c3b06d ¤   err¤= PGPNewHashContext( memoryMgr, vtbl->algorithm, &newRef );
99af5a
83df4a ¤   pgpAssert( ( IsntPGPError( err ) && IsntNull( newRef ) ) ||
a35635 ¤   ¤   ( IsPGPError( err ) && IsNull( newRef ) ) );
f167c5 ¤
577277 ¤   return( newRef );
bdefe6 }
d6af5a
91af5a
1daf5a
34af5a
8333c8 ¤   static void
--0cce 0009c17dcad40100134 Page 5 of pgpHash.c
26a16d sDisposeHashData (PGPHashContextRef¤ref)
3cbb36 {
cc09d6 ¤   if ( pgpHashContextIsValid( ref ) )
9bc7a1 ¤   {
7ae2b4 ¤   ¤   pgpClearMemory (ref->hashData, ref->vtbl->context_size);
37ac5f ¤   ¤   PGPFreeData( ref->hashData );
304849 ¤   ¤   ref->hashData¤  = NULL;
6e9371 ¤   }
49efe6 }
b0af5a
f8af5a
cea422 ¤   void const *
f52bad pgpHashFinal( PGPHashContextRef ref )
45bb36 {
053078 ¤   pgpAssert( pgpHashContextIsValid( ref ) );
4e67c5 ¤
cc5c05 ¤   return( CallFinal( ref ) );
bdefe6 }
1aaf5a
e1af5a
b53d76 ¤   PGPHashContextRef
862a2a pgpHashCopy(const PGPHashContext *ref)
7bbb36 {
7d7496 ¤   PGPHashContextRef¤  newRef;
67af5a
5e3078 ¤   pgpAssert( pgpHashContextIsValid( ref ) );
d267c5 ¤
661ac0 ¤   (void)PGPCopyHashContext( (PGPHashContextRef)ref, &newRef );
3f67c5 ¤
39b4c6 ¤   return newRef;
feefe6 }
0aaf5a
bc6d52 ¤   void
d4d48c pgpHashCopyData(
279eab ¤   PGPHashContext ·*¤  src,
794dd5 ¤   PGPHashContext *¤   dest )
31bb36 {
4c4a50 ¤   pgpAssert( pgpHashContextIsValid( src ) );
8b2d3f ¤   pgpAssert(dest->vtbl == src->vtbl);
a867c5 ¤
ed71a0 ¤   pgpCopyMemory( src->hashData, dest->hashData, src->vtbl->context_size);
c1efe6 }
89af5a
5eaf5a
7f5124 /* Access to all known hashes */
a15f8b /* The order of the entries in this table is not significant */
ed086f static PGPHashVTBL const * const sHashList[] ·=
39bb36 {
ce7f2e ¤   &HashMD5,
eade5b ¤   &HashSHA,
ba2eef ¤   &HashRIPEMD160,
e0c08a ¤   &HashMD2
4482f7 };
c1d8e5 #define kNumHashes¤ ·( sizeof( sHashList ) / sizeof( sHashList[ 0 ] ) )
05af5a
9c8a3d ¤   PGPHashVTBL const *
89604c pgpHashByNumber (PGPHashAlgorithm¤  algorithm)
9abb36 {
a9c416 ¤   const PGPHashVTBL *¤vtbl¤   = NULL;
8ba671 ¤   PGPUInt32¤  ¤   ¤   algIndex;
8667c5 ¤
4b8136 ¤   for( algIndex = 0; algIndex < kNumHashes; ++algIndex )
eec7a1 ¤   {
0ceaa1 ¤   ¤   if ( sHashList[ algIndex ]->algorithm == algorithm )
fa5b34 ¤   ¤   {
79674f ¤   ¤   ¤   vtbl¤   = sHashList[ algIndex ];
d8cdcb ¤   ¤   ¤   break;
d50fe4 ¤   ¤   }
589371 ¤   }
8a67c5 ¤
db902e ¤   return vtbl;
9cefe6 }
--277b 000a206717240100134 Page 6 of pgpHash.c
e0af5a
d338e5 /*
60fe9a ·* Given a hash name, return the corresponding hash.
0b495d ·*/
738a3d ¤   PGPHashVTBL const *
0d60b7 pgpHashByName (char const *name, size_t namelen)
0dbb36 {
08e811 ¤   PGPUInt32¤  algIndex;
c3af5a
a98136 ¤   for( algIndex = 0; algIndex < kNumHashes; ++algIndex )
2fc7a1 ¤   {
8fd309 ¤   ¤   PGPHashVTBL const *vtbl;
7367c5 ¤
57fcc8 ¤   ¤   vtbl = sHashList[ algIndex ];
0b1b52 ¤   ¤
6829fe ¤   ¤   if ( pgpMemoryEqual (name, vtbl->name, namelen) &&·
852600 ¤   ¤   ····vtbl->name[ namelen ] == '\0')
375b34 ¤   ¤   {
f76074 ¤   ¤   ¤   return vtbl;
c20fe4 ¤   ¤   }
8a9371 ¤   }
ce2fbc ¤   return NULL;¤   /* Not found */
fbefe6 }
b2af5a
e5af5a
f6af5a
581083 ¤   PGPHashVTBL const ·*
3bcb0f pgpHashGetVTBL( const PGPHashContext *ref )
babb36 {
aa3078 ¤   pgpAssert( pgpHashContextIsValid( ref ) );
9267c5 ¤
e2a508 ¤   return( ref->vtbl );
14efe6 }
d0af5a
810335 /*____________________________________________________________________________
617f58 ¤   Given a list of hash identifiers, create a list of hash contexts.
bf7e8d ¤   Ignores unknown algorithms. ·Returns the number of PgpHashContexts
838e56 ¤   created and stored in the "hashes" buffer, or an Error (and none created)
6e1221 ¤   on error.
aa67c5 ¤
054657 ¤   Note that the formal data type returned is an opaque 'PGPHashListRef',
0f61d6 ¤   although the actual format of the list is just an array of PGPHashContext.
dc4221 ¤   The formal data type is used to preserve opacity of the PGPHashContext.
ecf7f7 ____________________________________________________________________________*/
4ac744 ¤   PGPError
36d258 pgpHashListCreate (
8e2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
4306a1 ¤   void const *¤   ¤   bufParam,
3c613c ¤   PGPHashListRef *¤   hashListPtr,
1ca367 ¤   PGPUInt32¤  ¤   ¤   numHashes )
b3bb36 {
523393 ¤   PGPInt32¤   ¤   ¤   ¤   numHashesCreated;
2849d2 ¤   PGPHashListRef¤ ¤   ¤   hashList;
f69479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
8063c1 ¤   PGPUInt32¤  ¤   ¤   ¤   listSize;
9c019d ¤   const PGPByte *¤¤   ¤   buf;
3f67c5 ¤
102348 ¤   PGPValidatePtr( hashListPtr );
aa9670 ¤   *hashListPtr = NULL;
9ff0c0 ¤   PGPValidatePtr( bufParam );
4d4f32 ¤   PGPValidateParam( numHashes != 0 );
86ad91 ¤   PGPValidateMemoryMgr( memoryMgr );
feaf5a
f98981 ¤   buf ¤   ¤   = (const PGPByte *) bufParam;
05e7ec ¤   listSize¤   = sizeof( *hashList ) +
97f403 ¤   ¤   ( numHashes -1 ) ·* sizeof( hashList->hashes[ 0 ] );
7a1b52 ¤   ¤
27644d ¤   hashList¤   = (PGPHashListRef)
59ae80 ¤   ¤   PGPNewData( memoryMgr, listSize,
70d4cc ¤   ¤   0 | kPGPMemoryMgrFlags_Clear );
bf67c5 ¤
a2006a ¤   if ( IsNull( hashList ) )
--7afe 000b8617ea640100134 Page 7 of pgpHash.c
2bff29 ¤   ¤   return( kPGPError_OutOfMemory );
bb1b52 ¤   ¤
90c95b ¤   pgpClearMemory( hashList, listSize );
72861f ¤   hashList->numHashes¤= 0;
b168a9 ¤   hashList->memoryMgr¤= memoryMgr;
1faf5a
226180 ¤   numHashesCreated = 0;
4319e9 ¤   while (numHashes--)
2ec7a1 ¤   {
4cc5fe ¤   ¤   PGPHashAlgorithm¤   ¤   algorithm;
2af90c ¤   ¤   PGPHashVTBL const *¤¤   vtbl;
de1b52 ¤   ¤
50089b ¤   ¤   algorithm¤  = (PGPHashAlgorithm) ( *buf++ );
d51b52 ¤   ¤
f96bf0 ¤   ¤   vtbl¤   = pgpHashByNumber ( algorithm );
4d2a81 ¤   ¤   if ( IsntNull( vtbl ) )
b45b34 ¤   ¤   {
e6d5f7 ¤   ¤   ¤   PGPHashContext *¤   curHash;
9f87c7 ¤   ¤   ¤
20a833 ¤   ¤   ¤   curHash¤= &hashList->hashes[ numHashesCreated ];
0187c7 ¤   ¤   ¤
e068d3 ¤   ¤   ¤   err¤= sHashInit( curHash, memoryMgr, vtbl->algorithm );
e78370 ¤   ¤   ¤   if ( IsPGPError( err ) )
7bf776 ¤   ¤   ¤   {
de94fc ¤   ¤   ¤   ¤   while ( numHashesCreated-- )
7672c3 ¤   ¤   ¤   ¤   {
4a71fe ¤   ¤   ¤   ¤   ¤   sDisposeHashData( curHash );
f12613 ¤   ¤   ¤   ¤   }
ab2b85 ¤   ¤   ¤   ¤
91a72d ¤   ¤   ¤   ¤   PGPFreeData( hashList );
ab7611 ¤   ¤   ¤   ¤   hashList¤   = NULL;
4f14f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
28f622 ¤   ¤   ¤   ¤   break;
57a3a6 ¤   ¤   ¤   }
cff60b ¤   ¤   ¤   numHashesCreated++;
380fe4 ¤   ¤   }
969371 ¤   }
32af5a
1e078f ¤   hashList->numHashes¤= numHashesCreated;
cd67c5 ¤
1222cb ¤   *hashListPtr = hashList;
5c67c5 ¤
865ea8 ¤   return err;
2fefe6 }
a2af5a
aeaf5a
7e6d52 ¤   void
4ef937 pgpHashListDestroy ( PGPHashListRef¤hashList )
afbb36 {
5ce543 ¤   PGPUInt32¤  ¤   hashIndex;
9967c5 ¤
6bd33b ¤   pgpAssertAddrValid( hashList, PGPHashList );
3367c5 ¤
8d80ff ¤   hashIndex¤  = hashList->numHashes;
cdf963 ¤   if ( hashIndex != 0 )
ddc7a1 ¤   {
d6b1ec ¤   ¤   while ( hashIndex--)
485b34 ¤   ¤   {
62cd4b ¤   ¤   ¤   sDisposeHashData( &hashList->hashes[ hashIndex ] );
7e0fe4 ¤   ¤   }
841b52 ¤   ¤
ec9fa8 ¤   ¤   PGPFreeData( hashList );
4b9371 ¤   }
37efe6 }
baaf5a
7baf5a
0b108d ¤   PGPUInt32
33629f pgpHashListGetSize( PGPHashListRef¤ list ·)
4dbb36 {
3a6ac1 ¤   pgpAssertAddrValid( list, PGPHashList );
0d2593 ¤   return( list->numHashes );
b8efe6 }
--7c5d 00187338e8940100134 Page 8 of pgpHash.c
e0af5a
7e0335 /*____________________________________________________________________________
9875f3 ¤   pgpHashListGetIndHash() is made necessary by incestuous code that wants
15edd2 ¤   to be able to index over a struct. ·Since we want to keep the structure
aeb5de ¤   of a PGPHashContext opaque, we need to provide this accessor.
c0f7f7 ____________________________________________________________________________*/
2baf5a
adcc52 ¤   PGPHashContext *
5a7d28 pgpHashListGetIndHash(
df96f6 ¤   PGPHashListRef¤ list,
87232b ¤   PGPUInt32¤  ¤   algIndex )
0dbb36 {
a96ac1 ¤   pgpAssertAddrValid( list, PGPHashList );
f3281f ¤   pgpAssert( algIndex < list->numHashes );
0067c5 ¤
61b803 ¤   if ( algIndex < list->numHashes )
856f46 ¤   ¤   return( &list->hashes[ algIndex ] );
061b52 ¤   ¤
0e9572 ¤   return( NULL );
9defe6 }
95af5a
1eaf5a
a5cc52 ¤   PGPHashContext *
162fb3 pgpHashListFind (
ef288c ¤   PGPHashListRef¤ ¤   hashList,
75e958 ¤   PGPHashVTBL const *¤vtbl)
f2bb36 {
493d12 ¤   PGPHashContext *¤   cur;
abe051 ¤   PGPUInt32¤  ¤   ¤   remaining;
4967c5 ¤
67d33b ¤   pgpAssertAddrValid( hashList, PGPHashList );
b567c5 ¤
e77235 ¤   cur¤= &hashList->hashes[ 0 ];
f1b73e ¤   remaining¤  = hashList->numHashes;
583149 ¤   while (remaining--)
97c7a1 ¤   {
16d872 ¤   ¤   if ( cur->vtbl == vtbl )
50df96 ¤   ¤   ¤   return cur;
55e49f ¤   ¤   cur++;
e89371 ¤   }
4c3f59 ¤   return NULL;
b7efe6 }
8eaf5a
0aaf5a
2eaf5a
32af5a
adaf5a
17af5a
b8af5a
47af5a
7baf5a
ecaf5a
7eaf5a
52af5a
65af5a
c9af5a
efaf5a
4eaf5a
a5af5a
5aaf5a
e6af5a
f0af5a
25af5a
00af5a
957e4d /*__Editor_settings____
70af5a
0d4126 ¤   Local Variables:
797b17 ¤   tab-width: 4
ed0e6c ¤   End:
bc5f8c ¤   vi: ts=4 sw=4
e69e9b ¤   vim: si
87d062 _____________________*/
--3d32 0001ead739040100135 Page 1 of pgpHashPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
8e0128 ¤   $Id: pgpHashPriv.h,v 1.11.10.1 1998/11/12 03:21:24 heller Exp $
bcf7f7 ____________________________________________________________________________*/
1530da #ifndef Included_pgpHashingPriv_h¤  /* [ */
c752b8 #define Included_pgpHashingPriv_h
16af5a
19c5d5 #include "pgpBase.h"
e6adb8 #include "pgpOpaqueStructs.h"
029f72 #include "pgpHash.h"
6aaf5a
3caf5a
9199c6 PGP_BEGIN_C_DECLARATIONS
37af5a
77a85a enum PGPPrivHashAlgorithm_
c7bb36 {
02103b ¤   kPGPHashAlgorithm_MD2¤  ¤   = 5,
2f9cdb //¤ kPGPHashAlgorithm_SHADouble¤= 100,
b3af5a
39b9a1 ¤   PGP_ENUM_FORCE( PGPPrivHashAlgorithm_ )
c082f7 };
71eff9 PGPENUM_TYPEDEF( PGPPrivHashAlgorithm_, PGPPrivHashAlgorithm );
22af5a
72af5a
eb0335 /*____________________________________________________________________________
4aa612 ¤   A static description of a hash; analagous to a C++ virtual function tbl.
33f7f7 ____________________________________________________________________________*/
f13173 struct PGPHashVTBL
95bb36 {
98a9a2 ¤   char const *¤   ¤   name;
70c7ed ¤   PGPHashAlgorithm¤   algorithm;
4eea54 ¤   void const *¤   ¤   DERprefix;¤ ¤   /* DER-encoded prefix */
9b1807 ¤   PGPSize¤¤   ¤   ¤   DERprefixsize;¤ /* DER-encoded prefix length */
5d2656 ¤   PGPSize¤¤   ¤   ¤   hashsize;¤  ¤   /* Bytes of output */
c946a4 ¤   PGPSize¤¤   ¤   ¤   context_size;
9f5f19 ¤   PGPSize¤¤   ¤   ¤   context_align;
6567c5 ¤
1effcb ¤   void¤   ¤   ¤   (*init)( void *priv );
598062 ¤   void¤   ¤   ¤   (*update)( void *priv, void const *buf, PGPSize len );
09e67d ¤   void const *¤   (*final)( void *priv );
e982f7 };
47af5a
16af5a
35af5a
fa4872 PGPHashVTBL const ·*¤   pgpHashGetVTBL( const PGPHashContext * );
c0af5a
9daf5a
da2bd1 /* Create and Destroy a big bunch of hashes at once. */
d46840 PGPError ¤  ¤   ¤   pgpHashListCreate( PGPMemoryMgrRef memoryMgr,
b8e510 ¤   ¤   ¤   ¤   ¤   ¤   void const *buf,
ba2e37 ¤   ¤   ¤   ¤   ¤   ¤   PGPHashListRef *outList, PGPUInt32 numHashes );
fd6122 PGPHashContextRef¤  pgpHashListGetIndHash( PGPHashListRef list,
18527a ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 algIndex );
dd1e5a void ¤  ¤   ¤   ¤   pgpHashListDestroy( PGPHashListRef hashes );
64c1a3 PGPUInt32 ¤ ¤   ¤   pgpHashListGetSize( PGPHashListRef hashes );
92af5a
283d1d /* Find the context of a given type in the list */
507a33 PGPHashContextRef¤  pgpHashListFind( ·PGPHashListRef hashList,
aaa678 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPHashVTBL const *vtbl);
d7af5a
afaf5a
6d0335 /*____________________________________________________________________________
8206e1 ¤   The following are glue routines for compatibility with existing source.
1f13a7 ¤   Use is discouraged in favor of official routines.
69f7f7 ____________________________________________________________________________*/
c2af5a
ac4189 void const *¤   ¤   pgpHashFinal( PGPHashContextRef ref );
1eaf5a
--d779 001db942db940100135 Page 2 of pgpHashPriv.h
a11d58 /* Allocate, deallocate, and copy a hash context */
517616 PGPHashContextRef¤  pgpHashCreate( PGPMemoryMgrRef memoryMgr,
b00879 ¤   ¤   ¤   ¤   ¤   ¤   PGPHashVTBL const *vtbl);
09b7bb PGPHashContextRef¤  pgpHashCopy( const PGPHashContext *hc);
0bb063 void ¤  ¤   ¤   ¤   pgpHashCopyData( PGPHashContextRef src,
76aba1 ¤   ¤   ¤   ¤   ¤   ¤   PGPHashContext *dest );
f6af5a
bfc229 /* Return a hash struction of the appropriate number */
67438f PGPHashVTBL const ·*¤   pgpHashByNumber( PGPHashAlgorithm type);
bf61e0 PGPHashVTBL const ·*¤   pgpHashByName( char const *name, PGPSize namelen);
bbaf5a
5caf5a
0daf5a
121254 PGP_END_C_DECLARATIONS
fdaf5a
909a7a #endif /* ] Included_pgpHashingPriv_h */
faaf5a
02af5a
b17e4d /*__Editor_settings____
c1af5a
334126 ¤   Local Variables:
907b17 ¤   tab-width: 4
5f0e6c ¤   End:
c75f8c ¤   vi: ts=4 sw=4
a39e9b ¤   vim: si
dbd062 _____________________*/
--59cd 0007c99f1b540100136 Page 1 of pgpMD2.c
bc38e5 /*
31233f ·* This code implements the MD2 message-digest algorithm.
dc3f16 ·* The algorithm is due to Ron Rivest, documented in RFC1319.
f6bca6 ·* This code is in the public domain; do with it what you wish.
89775e ·*
0f83ac ·* Equivalent code is available from RSA Data Security, Inc.
cd775e ·*
a756bc ·* To compute the message digest of a chunk of bytes, declare an
d72c5b ·* MD2Context structure, pass it to MD2Init, call MD2Update as
7e933e ·* needed on buffers full of bytes, and then call MD2Final, which
982fb7 ·* will fill a supplied 16-byte array with the digest.
ff775e ·*
bd3c12 ·* $Id: pgpMD2.c,v 1.4 1998/08/05 05:36:54 heller Exp $
03495d ·*/
70af5a
ebe2ff #include "pgpConfig.h"
8caf5a
a39f72 #include "pgpHash.h"
3793dd #include "pgpMD2.h"
37d11f #include "pgpUsuals.h"
a90d08 #include "pgpMem.h"
aca146 #include "pgpDebug.h"
164704 #include "pgpMSRSAGlue.h"
18af5a
c5af5a
1c1aa4 /* MD2 size parameters */
91af5a
9e4fa6 #define MD2_BLOCKBYTES¤ 16
b4d863 #define MD2_BLOCKWORDS¤ 4
f98bbb #define MD2_ITERATIONS¤ 18
7567b1 #define MD2_HASHBYTES¤  16
2aaf5a
bcaf5a
568d10 #if PGP_USECAPIFORMD2¤  /* [ */
68af5a
8e38e5 /*
5fdbb4 ·* Due to bugs in CAPI, we can't set the hash value for MD2 hash.
a4ec8d ·* Therefore we will go with a very limited implementation which can
185655 ·* only verify MD2 signatures, and even then only in simple cases.
da775e ·*
1bcc46 ·* We will not return a true MD2 hash when asked, but rather we will
c1f439 ·* return a pointer to the hProv and hHash handles. ·This will be used
b884a9 ·* by the CAPI verification code to do the actual verification. ·That
20087e ·* code will be responsible for disposing of the handles.
f8495d ·*/
2aaf5a
8acdc2 #include "pgpPubKey.h"
04af5a
312eac /* Shorthand for accessing CAPI externs */
78a10e #define e pgp_CAPI_externs
57af5a
42e567 extern CAPIEntries pgp_CAPI_externs;
79af5a
cf0278 typedef struct MD2Context {
73bd1a ¤   HCRYPTPROV¤ ¤   ¤   hProv;¤ ¤   ¤   /* Handle to CAPI provider */
819868 ¤   HCRYPTHASH¤ ¤   ¤   hHash;¤ ¤   ¤   /* Handle to CAPI hash object */
bf6477 ¤   DEBUG_STRUCT_CONSTRUCTOR( MD2Context )
340c8c } MD2Context;
f9af5a
872978 static void
3b93a3 MD2Init(void *priv)
1dbb36 {
d5a91c ¤   MD2Context *ctx = (MD2Context *)priv;
d3af5a
914c25 ¤   pgpClearMemory (ctx, sizeof(*ctx));
03af5a
f65f5f ¤   /* Verify CAPI loadability */
a1280f ¤   if (!(pgpCAPIuse() & PGP_PKUSE_SIGN))
869397 ¤   ¤   return;¤¤   ¤   /* Unusable */
e7af5a
e1aeed ¤   /* Acquire context */
7cfcbd ¤   if (!e.CryptAcquireContext(&ctx->hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
--4d99 000e72aae5f40100136 Page 2 of pgpMD2.c
ca441b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_VERIFYCONTEXT)) {
c5c443 ¤   ¤   pgpClearMemory (ctx, sizeof(*ctx));
ec99bf ¤   ¤   return;
ea9371 ¤   }
6faf5a
cc03f8 ¤   /* Create hash */
030a73 ¤   if (!e.CryptCreateHash (ctx->hProv, CALG_MD2, 0, 0, &ctx->hHash)) {
8c2483 ¤   ¤   e.CryptReleaseContext(ctx->hProv, 0);
d8c443 ¤   ¤   pgpClearMemory (ctx, sizeof(*ctx));
2199bf ¤   ¤   return;
529371 ¤   }
90efe6 }
34af5a
562978 static void
8b3c98 MD2Update(void *priv, void const *bufIn, PGPSize len)
b7bb36 {
1b9c41 ¤   MD2Context ¤*ctx = (MD2Context *)priv;
f4af5a
162921 ¤   e.CryptHashData (ctx->hHash, bufIn, len, 0);
bdefe6 }
b4af5a
b8862c /* Instead of returning hash, return pointer to hProv/hHash */
ae9c71 static void const *
2b30dc MD2Final(void *priv)
0cbb36 {
e385b6 ¤   return priv;
a5efe6 }
6daf5a
7956f3 #else¤  ¤   ¤   ¤   ¤   /* ] PGP_USECAPIFORMD2 [ */
6eaf5a
7eaf5a
102d34 #define DATA(ctx) ((ctx)->X+MD2_BLOCKBYTES)
39af5a
620278 typedef struct MD2Context {
7a320e ¤   PGPByte csum[MD2_BLOCKBYTES];¤  /* Accumulated checksum */
26bf36 ¤   PGPByte X[3*MD2_BLOCKBYTES];¤   /* X array which gets crunched */
819d4d ¤   PGPByte data[MD2_BLOCKBYTES];¤  /* accumulate data up to 1 block */
61771f ¤   PGPUInt32 bytesLo;
fd6477 ¤   DEBUG_STRUCT_CONSTRUCTOR( MD2Context )
610c8c } MD2Context;
c8af5a
266872 /* Substitution table, a permutation of 0..255 based on PI */
997d3b static PGPByte S[256] = {
f46c14 ··41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
f649c1 ··19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
f1ea3c ··76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
cdf9f7 ··138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
ea246f ··245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
724a9a ··148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
471a3e ··39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
0bc757 ··181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
e00d1d ··150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
046399 ··112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
328191 ··96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
33451a ··85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
d3888a ··234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
51e60d ··129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
a75639 ··8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
b8f020 ··203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
c8bce1 ··166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
414d2c ··31, 26, 219, 153, 141, 51, 159, 17, 131, 20
5c82f7 };
25af5a
11af5a
9b38e5 /*
824de8 ·* Start MD2 accumulation. ·Set bit count to 0 and buffer to mysterious
c438a0 ·* initialization constants.
6c495d ·*/
df2978 static void
dc93a3 MD2Init(void *priv)
e3bb36 {
e7a91c ¤   MD2Context *ctx = (MD2Context *)priv;
--a058 000f056e6d840100136 Page 3 of pgpMD2.c
e0af5a
714c25 ¤   pgpClearMemory (ctx, sizeof(*ctx));
17efe6 }
9aaf5a
2a38e5 /*
3e683a ·* The core of the MD2 algorithm, this alters an existing MD2 hash to
25db19 ·* reflect the addition of 16 bytes of new data.
8abaaf ·* The incoming data is already in place in X+MD2_BLOCKBYTES.
6a495d ·*/
af2978 static void
44f686 MD2Transform(PGPByte *X, PGPByte *csum)
fcbb36 {
f1ac98 ¤   PGPByte t;
7ce91f ¤   PGPUInt32 j, k;
9469bd ¤   PGPUInt32 *XW = (PGPUInt32 *)X;
77af5a
7c35e8 ¤   if (csum) {
8f1c33 ¤   ¤   /* Update checksum */
0ac95c ¤   ¤   t = csum[MD2_BLOCKBYTES-1];
ec0e7c ¤   ¤   for (j=0; j<MD2_BLOCKBYTES; ++j) {
7784d5 ¤   ¤   ¤   /* Note that RFC1319 says "=" not "^=", but that is wrong */
a53cdf ¤   ¤   ¤   t = csum[j] ^= S[ X[MD2_BLOCKBYTES + j] ^ t ];
130fe4 ¤   ¤   }
4d9371 ¤   }
6faf5a
dfebdc ¤   /* XOR to produce third part of X; shortcut doing 32 bits at once */
68bbe4 ¤   for (j=0; j<MD2_BLOCKWORDS; ++j)
50db86 ¤   ¤   XW[2*MD2_BLOCKWORDS + j] = XW[j] ^ XW[MD2_BLOCKWORDS + j];
deaf5a
b464ea ¤   t = 0;
821847 ¤   for (j=0; j<MD2_ITERATIONS; ++j) {
e704df ¤   ¤   for (k=0; k<3*MD2_BLOCKBYTES; ++k) {
bd09f0 ¤   ¤   ¤   t = X[k] ^= S[t];
a80fe4 ¤   ¤   }
8ae290 ¤   ¤   t = (t + j) & 0xff;
389371 ¤   }
42efe6 }
ddaf5a
eb38e5 /*
3c049f ·* Update context to reflect the concatenation of another buffer full
cd6682 ·* of bytes.
b4495d ·*/
092978 static void
f83c98 MD2Update(void *priv, void const *bufIn, PGPSize len)
8dbb36 {
d19c41 ¤   MD2Context ¤*ctx = (MD2Context *)priv;
c2cd75 ¤   PGPByte¤¤   *buf = (PGPByte *) bufIn;
bdad33 ¤   unsigned ¤  i;
6baf5a
be30a7 ¤   PGPUInt32 t = ctx->bytesLo;
2e1733 ¤   ctx->bytesLo = t + len;
383489 ¤   i = (unsigned)t % MD2_BLOCKBYTES;¤  /* Bytes already in ctx->key */
c7af5a
56cdff ¤   if (MD2_BLOCKBYTES-i > len) {
4c1fa2 ¤   ¤   /* Insufficient data to fill out a block */
fe97ae ¤   ¤   pgpCopyMemory (buf, DATA(ctx)+i, len);
b799bf ¤   ¤   return;
499371 ¤   }
f2af5a
55c265 ¤   if (i) {¤   /* First chunk is an odd size */
ed5097 ¤   ¤   pgpCopyMemory (buf, DATA(ctx) + i, MD2_BLOCKBYTES - i);
109def ¤   ¤   MD2Transform(ctx->X, ctx->csum);
3e1a86 ¤   ¤   buf += MD2_BLOCKBYTES-i;
576135 ¤   ¤   len -= MD2_BLOCKBYTES-i;
899371 ¤   }
a5af5a
b9d2bd ¤   /* Process data in 16-byte chunks */
5c3b17 ¤   while (len >= MD2_BLOCKBYTES) {
5af64c ¤   ¤   pgpCopyMemory (buf, DATA(ctx), MD2_BLOCKBYTES);
8a9def ¤   ¤   MD2Transform(ctx->X, ctx->csum);
158de2 ¤   ¤   buf += MD2_BLOCKBYTES;
f0cae5 ¤   ¤   len -= MD2_BLOCKBYTES;
--137a 00074b9026940100136 Page 4 of pgpMD2.c
a19371 ¤   }
93af5a
0094e0 ¤   /* Handle any remaining bytes of data. */
704548 ¤   if (len)
328106 ¤   ¤   pgpCopyMemory (buf, DATA(ctx), len);
9eefe6 }
84af5a
5538e5 /*
6e9e9a ·* Final wrapup - pad and add checksum.
b0495d ·*/
fb9c71 static void const *
9830dc MD2Final(void *priv)
b7bb36 {
7da91c ¤   MD2Context *ctx = (MD2Context *)priv;
71ced6 ¤   unsigned i = (unsigned)ctx->bytesLo % MD2_BLOCKBYTES;
c0d514 ¤   unsigned j = i;
24af5a
722257 ¤   /* Fill the second to last block with padding */
4cee71 ¤   for ( ; i<MD2_BLOCKBYTES; ++i) {
63fc16 ¤   ¤   DATA(ctx)[i] = 16 - j;
e39371 ¤   }
df9802 ¤   MD2Transform(ctx->X, ctx->csum);
d4af5a
42d370 ¤   /* Finally transform the checksum as the last block */
28ae2e ¤   pgpCopyMemory (ctx->csum, DATA(ctx), MD2_BLOCKBYTES);
c3a022 ¤   MD2Transform(ctx->X, NULL);
bdaf5a
fe57b6 ¤   /* In case it's sensitive */
2673ec /* XXX¤ memset(DATA(ctx), 0, 2*MD2_BLOCKBYTES); */
d23cce ¤   return (PGPByte const *)ctx->X;
d9efe6 }
04af5a
1eaf5a
f84ccc #endif /* ] PGP_USECAPIFORMD2 */
2baf5a
f5af5a
4138e5 /*
d9dbd6 ·* The Basic Encoding Rules (of which the Distinguished Encoding Rules
94cee6 ·* are a simple minimal-sized subset) are supposed to be compact. ·Humph.
13495d ·*/
0128b5 static PGPByte const MD2DERprefix[] = {
0ceef2 ¤   0x30, /* Universal, Constructed, Sequence */
66de2a ¤   0x20, /* Length 32 (bytes following) */
8bbde9 ¤   ¤   0x30, /* Universal, Constructed, Sequence */
b39f04 ¤   ¤   0x0c, /* Length 12 */
796507 ¤   ¤   ¤   0x06, /* Universal, Primitive, object-identifier */
1a745e ¤   ¤   ¤   0x08, /* Length 8 */
295b93 ¤   ¤   ¤   ¤   0x2a, /* 42 = ISO(1)*40 + Member bodies(2) */
12adb4 ¤   ¤   ¤   ¤   0x86, 0x48, /* 840 = US (ANSI) */
54bc6f ¤   ¤   ¤   ¤   0x86, 0xF7, 0x0D, /* 113549 = RSADSI */
fe2e94 ¤   ¤   ¤   ¤   0x02, /* 2 = Hash functions */
96fa74 ¤   ¤   ¤   ¤   0x02, /* 2 = MD2 */
a3c238 ¤   ¤   ¤   0x05, /* Universal, Primitive, NULL */
fbd131 ¤   ¤   ¤   0x00, /* Length 0 */
c66fe2 ¤   ¤   0x04, /* Universal, Primitive, Octet string */
bfca9a ¤   ¤   0x10 /* Length 16 */
407bb3 ¤   ¤   ¤   /* 16 MD2 digest bytes go here */
b282f7 };
6daf5a
111d39 PGPHashVTBL const HashMD2 = {
613936 ¤   "MD2", (PGPHashAlgorithm) kPGPHashAlgorithm_MD2,
3c7a83 ¤   MD2DERprefix, sizeof(MD2DERprefix),
f2a1fd ¤   MD2_HASHBYTES,
631ae4 ¤   sizeof(MD2Context),
937d3f ¤   sizeof(struct{char _a; MD2Context _b;}) -
78ec81 ¤   ¤   sizeof(MD2Context),
549e47 ¤   MD2Init, MD2Update, MD2Final
3782f7 };
5eaf5a
d46828 #if TESTMAIN¤   /* [ */
82af5a
74feb2 #include <stdio.h>
--e2de 001d823f31f40100136 Page 5 of pgpMD2.c
37324c #include <string.h>
1baf5a
36af5a
589785 static char const * const md2TestResults[] = {
d114b8 ¤   "8350e5a3e24c153df2275c9f80692773",
b4d10f ¤   "32ec01ec4a6dac72c0ab96fb34c0b5d1",
cf4808 ¤   "da853b0d3f88d99b30283a69e6ded6bb",
c78718 ¤   "ab4f496bfb2a530b219ff33031fe06b0",
400db2 ¤   "4e8ddff3650292ab5a4108c3aa47940b",
17a743 ¤   "da33def2a42df13975352846c30338cd",
36f712 ¤   "d5976f79d83d3a0dc9806c3c66f3efd8"
b782f7 };
32af5a
746fdc static char const * const md2TestValues[] = {
1dc8d1 ¤   "",
413c14 ¤   "a",
278c42 ¤   "abc",
a617de ¤   "message digest",
2cdd0e ¤   "abcdefghijklmnopqrstuvwxyz",
95d10c ¤   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
6c0698 ¤   "1234567890123456789012345678901234567890" /* No comma here */
c77b8b ¤   "1234567890123456789012345678901234567890"
5882f7 };
3faf5a
75beb7 static int
68fc45 compareMD2results(PGPByte const *hash, int level)
27bb36 {
929e40 ¤   char buf[33];
55743f ¤   unsigned i;
91af5a
897d63 ¤   for (i = 0; i < MD2_HASHBYTES; i++)
84e1a7 ¤   ¤   sprintf(buf+2*i, "%02x", hash[i]);
0712d6 ¤   if (strcmp(buf, md2TestResults[level]) == 0) {
61721c ¤   ¤   printf("Test %d passed, result = %s\n", level+1, buf);
0ebbde ¤   ¤   return 0;
75f037 ¤   } else {
7a0672 ¤   ¤   printf("Error in MD2 implementation; test %d failed\n", level+1);
9b945d ¤   ¤   printf(" ·Result = %s\nExpected = %s\n", buf,
467976 ¤   ¤   ¤   md2TestResults[level]);
51043c ¤   ¤   return -1;
a89371 ¤   }
aaefe6 }
e2af5a
e04d2f int
6e7f68 main(void)
90bb36 {
966f74 ¤   MD2Context md2;
46e578 ¤   PGPByte const *hash;
9f743f ¤   unsigned i;
29af5a
2f697a ¤   for (i=0; i<sizeof(md2TestValues)/sizeof(md2TestValues[0]); ++i) {
da79bb ¤   ¤   MD2Init(&md2);
cf383c ¤   ¤   MD2Update(&md2, md2TestValues[i], strlen(md2TestValues[i]));
4819b1 ¤   ¤   hash = MD2Final(&md2);
b3e70f ¤   ¤   if (compareMD2results(hash, i) < 0)
d51baa ¤   ¤   ¤   return -1;¤
fcefe6 }
df3e6b ¤   return 0;
98efe6 }
e0af5a
d89d94 #endif /* ] TESTMAIN */
--ee22 001a9e85b0540100137 Page 1 of pgpMD2.h
bc38e5 /*
186a1b ·* pgpMD2.h -- The MD-5 Message Digest.
d4775e ·*
9ee39d ·* This is a PRIVATE header file, for use only within the PGP Library.
8e2979 ·* You should not be using these functions in an application.
d0775e ·*
d053b5 ·* $Id: pgpMD2.h,v 1.1 1998/03/14 00:23:24 hal Exp $
25495d ·*/
c0af5a
27a999 #ifndef Included_pgpMD2_h
bce18e #define Included_pgpMD2_h
13af5a
245417 #include "pgpHashPriv.h"
aeaf5a
1a99c6 PGP_BEGIN_C_DECLARATIONS
7daf5a
36aa24 extern PGPHashVTBL const HashMD2;
67af5a
671254 PGP_END_C_DECLARATIONS
68af5a
a9371f #endif /* !Included_pgpMD2_h */
--a0e5 00002acd04a40100138 Page 1 of pgpMD5.c
bc38e5 /*
355947 ·* This code implements the MD5 message-digest algorithm.
004aaf ·* The algorithm is due to Ron Rivest. ·This code was
aee95a ·* written by Colin Plumb in 1993, no copyright is claimed.
b1bca6 ·* This code is in the public domain; do with it what you wish.
82775e ·*
5283ac ·* Equivalent code is available from RSA Data Security, Inc.
4ced7a ·* This code has been tested against that, and is equivalent,
9a6d71 ·* except that you don't need to include two pages of legalese
f15b9f ·* with every copy.
d8775e ·*
b056bc ·* To compute the message digest of a chunk of bytes, declare an
f84b08 ·* MD5Context structure, pass it to MD5Init, call MD5Update as
a5e3b9 ·* needed on buffers full of bytes, and then call MD5Final, which
ae2fb7 ·* will fill a supplied 16-byte array with the digest.
07775e ·*
c50fa2 ·* $Id: pgpMD5.c,v 1.13 1997/10/14 01:48:21 heller Exp $
ae495d ·*/
4caf5a
83e2ff #include "pgpConfig.h"
97af5a
6ee08d #include <string.h>¤¤   /* for memcpy() */
deaf5a
d79f72 #include "pgpHash.h"
eea301 #include "pgpMD5.h"
5fd11f #include "pgpUsuals.h"
eb0d08 #include "pgpMem.h"
6fa146 #include "pgpDebug.h"
a8af5a
64803e #define MD5_BLOCKBYTES¤ 64
41a88d #define MD5_BLOCKWORDS¤ 16
0aaf5a
0f179c #define MD5_HASHBYTES¤  16
77373c #define MD5_HASHWORDS¤  4
9daf5a
b2a29e typedef struct MD5Context {
170f94 ¤   PGPUInt32 key[MD5_BLOCKWORDS];
fb779e ¤   PGPUInt32 iv[MD5_HASHWORDS];
70a0a9 #if HAVE64
6905fb ¤   word64 bytes;
d1db21 #else
7eed3f ¤   PGPUInt32 bytesLo, bytesHi;
d97454 #endif
e6c491 ¤   DEBUG_STRUCT_CONSTRUCTOR( MD5Context )
40c879 } MD5Context;
77af5a
5838e5 /*
5ebbe0 ·* Shuffle the bytes into little-endian order within words, as per the
c64395 ·* MD5 spec.
96495d ·*/
322978 static void
499398 MD5ByteSwap(PGPUInt32 *dest, PGPByte const *src, unsigned words)
ecbb36 {
0a43ab ¤   do {
cc5137 ¤   ¤   *dest++ = (PGPUInt32)((unsigned)src[3] << 8 | src[2]) << 16 |
273e19 ¤   ¤   ··················((unsigned)src[1] << 8 | src[0]);
9aaa48 ¤   ¤   src += 4;
53c244 ¤   } while (--words);
31efe6 }
abaf5a
ae38e5 /*
c103cd ·* Start MD5 accumulation. ·Set bit count to 0 and buffer to mysterious
d038a0 ·* initialization constants.
eb495d ·*/
562978 static void
646934 MD5Init(void *priv)
1cbb36 {
6b84ef ¤   MD5Context *ctx = (MD5Context *)priv;
4caf5a
ab84d8 ¤   ctx->iv[0] = 0x67452301;
1b6920 ¤   ctx->iv[1] = 0xefcdab89;
02f244 ¤   ctx->iv[2] = 0x98badcfe;
--c00f 000c9f587ce40100138 Page 2 of pgpMD5.c
6135e1 ¤   ctx->iv[3] = 0x10325476;
c2af5a
a1a0a9 #if HAVE64
11f0a5 ¤   ctx->bytes = 0;
73db21 #else
d45e5b ¤   ctx->bytesHi = ctx->bytesLo = 0;
c37454 #endif
57efe6 }
5faf5a
7dc60f /* The four core functions - F1 is optimized somewhat */
31af5a
f70028 /* #define F1(x, y, z) (x & y | ~x & z) */
e23895 #define F1(x, y, z) (z ^ (x & (y ^ z)))
233e81 #define F2(x, y, z) F1(z, x, y)
5dc6c0 #define F3(x, y, z) (x ^ y ^ z)
db984a #define F4(x, y, z) (y ^ (x | ~z))
deaf5a
5303cd /* This is the central step in the MD5 algorithm. */
1e747e #define MD5STEP(f,w,x,y,z,in,s) \
62d0be ¤   ·(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
32af5a
0138e5 /*
3fab1d ·* The core of the MD5 algorithm, this alters an existing MD5 hash to
a40028 ·* reflect the addition of 16 longwords of new data. ·MD5Update blocks
4e5b14 ·* the data and converts bytes into longwords for this routine.
ba775e ·*
366af4 ·* NOTE This is not declared as static because pgpRndPool.c references it.
021d09 ·* (Sorry for that modularity violation.)
ef495d ·*/
7a3a6c void pgpMD5Transform(PGPUInt32 *block, PGPUInt32 const *key);
6a314a void
9965af pgpMD5Transform(PGPUInt32 *block, PGPUInt32 const *key)
52bb36 {
0c608c ¤   register PGPUInt32 a, b, c, d;
9aaf5a
c2318b ¤   a = block[0];
6eae0e ¤   b = block[1];
c8f529 ¤   c = block[2];
029915 ¤   d = block[3];
2faf5a
af6540 ¤   MD5STEP(F1, a, b, c, d, key[0] + 0xd76aa478, 7);
b1f445 ¤   MD5STEP(F1, d, a, b, c, key[1] + 0xe8c7b756, 12);
111836 ¤   MD5STEP(F1, c, d, a, b, key[2] + 0x242070db, 17);
ed443a ¤   MD5STEP(F1, b, c, d, a, key[3] + 0xc1bdceee, 22);
999adc ¤   MD5STEP(F1, a, b, c, d, key[4] + 0xf57c0faf, 7);
588746 ¤   MD5STEP(F1, d, a, b, c, key[5] + 0x4787c62a, 12);
6b9787 ¤   MD5STEP(F1, c, d, a, b, key[6] + 0xa8304613, 17);
268621 ¤   MD5STEP(F1, b, c, d, a, key[7] + 0xfd469501, 22);
67745d ¤   MD5STEP(F1, a, b, c, d, key[8] + 0x698098d8, 7);
5af9a2 ¤   MD5STEP(F1, d, a, b, c, key[9] + 0x8b44f7af, 12);
c0f230 ¤   MD5STEP(F1, c, d, a, b, key[10] + 0xffff5bb1, 17);
04a4f9 ¤   MD5STEP(F1, b, c, d, a, key[11] + 0x895cd7be, 22);
04d363 ¤   MD5STEP(F1, a, b, c, d, key[12] + 0x6b901122, 7);
1227dd ¤   MD5STEP(F1, d, a, b, c, key[13] + 0xfd987193, 12);
79fbf6 ¤   MD5STEP(F1, c, d, a, b, key[14] + 0xa679438e, 17);
06f7ef ¤   MD5STEP(F1, b, c, d, a, key[15] + 0x49b40821, 22);
b5af5a
218ff5 ¤   MD5STEP(F2, a, b, c, d, key[1] + 0xf61e2562, 5);
472e17 ¤   MD5STEP(F2, d, a, b, c, key[6] + 0xc040b340, 9);
1321f6 ¤   MD5STEP(F2, c, d, a, b, key[11] + 0x265e5a51, 14);
6dc003 ¤   MD5STEP(F2, b, c, d, a, key[0] + 0xe9b6c7aa, 20);
9f706f ¤   MD5STEP(F2, a, b, c, d, key[5] + 0xd62f105d, 5);
f3a472 ¤   MD5STEP(F2, d, a, b, c, key[10] + 0x02441453, 9);
736aa0 ¤   MD5STEP(F2, c, d, a, b, key[15] + 0xd8a1e681, 14);
4a14b0 ¤   MD5STEP(F2, b, c, d, a, key[4] + 0xe7d3fbc8, 20);
88c736 ¤   MD5STEP(F2, a, b, c, d, key[9] + 0x21e1cde6, 5);
7ca377 ¤   MD5STEP(F2, d, a, b, c, key[14] + 0xc33707d6, 9);
cae90e ¤   MD5STEP(F2, c, d, a, b, key[3] + 0xf4d50d87, 14);
16e575 ¤   MD5STEP(F2, b, c, d, a, key[8] + 0x455a14ed, 20);
2cbaa9 ¤   MD5STEP(F2, a, b, c, d, key[13] + 0xa9e3e905, 5);
c0583b ¤   MD5STEP(F2, d, a, b, c, key[2] + 0xfcefa3f8, 9);
c91393 ¤   MD5STEP(F2, c, d, a, b, key[7] + 0x676f02d9, 14);
--ef84 0005613428340100138 Page 3 of pgpMD5.c
bb0800 ¤   MD5STEP(F2, b, c, d, a, key[12] + 0x8d2a4c8a, 20);
dcaf5a
a28057 ¤   MD5STEP(F3, a, b, c, d, key[5] + 0xfffa3942, 4);
0573d2 ¤   MD5STEP(F3, d, a, b, c, key[8] + 0x8771f681, 11);
fa5ad8 ¤   MD5STEP(F3, c, d, a, b, key[11] + 0x6d9d6122, 16);
3e9c73 ¤   MD5STEP(F3, b, c, d, a, key[14] + 0xfde5380c, 23);
611193 ¤   MD5STEP(F3, a, b, c, d, key[1] + 0xa4beea44, 4);
ce3b30 ¤   MD5STEP(F3, d, a, b, c, key[4] + 0x4bdecfa9, 11);
2e2abf ¤   MD5STEP(F3, c, d, a, b, key[7] + 0xf6bb4b60, 16);
ab8860 ¤   MD5STEP(F3, b, c, d, a, key[10] + 0xbebfbc70, 23);
211195 ¤   MD5STEP(F3, a, b, c, d, key[13] + 0x289b7ec6, 4);
fa94fb ¤   MD5STEP(F3, d, a, b, c, key[0] + 0xeaa127fa, 11);
77d869 ¤   MD5STEP(F3, c, d, a, b, key[3] + 0xd4ef3085, 16);
2921fc ¤   MD5STEP(F3, b, c, d, a, key[6] + 0x04881d05, 23);
d235b0 ¤   MD5STEP(F3, a, b, c, d, key[9] + 0xd9d4d039, 4);
b97f94 ¤   MD5STEP(F3, d, a, b, c, key[12] + 0xe6db99e5, 11);
283d36 ¤   MD5STEP(F3, c, d, a, b, key[15] + 0x1fa27cf8, 16);
9c8a51 ¤   MD5STEP(F3, b, c, d, a, key[2] + 0xc4ac5665, 23);
dfaf5a
1ad183 ¤   MD5STEP(F4, a, b, c, d, key[0] + 0xf4292244, 6);
cd83d4 ¤   MD5STEP(F4, d, a, b, c, key[7] + 0x432aff97, 10);
4bcda7 ¤   MD5STEP(F4, c, d, a, b, key[14] + 0xab9423a7, 15);
98a5d1 ¤   MD5STEP(F4, b, c, d, a, key[5] + 0xfc93a039, 21);
62ecfe ¤   MD5STEP(F4, a, b, c, d, key[12] + 0x655b59c3, 6);
9f5e5d ¤   MD5STEP(F4, d, a, b, c, key[3] + 0x8f0ccc92, 10);
431680 ¤   MD5STEP(F4, c, d, a, b, key[10] + 0xffeff47d, 15);
bdd0a7 ¤   MD5STEP(F4, b, c, d, a, key[1] + 0x85845dd1, 21);
9b7c8c ¤   MD5STEP(F4, a, b, c, d, key[8] + 0x6fa87e4f, 6);
b45b38 ¤   MD5STEP(F4, d, a, b, c, key[15] + 0xfe2ce6e0, 10);
ccbc12 ¤   MD5STEP(F4, c, d, a, b, key[6] + 0xa3014314, 15);
046ead ¤   MD5STEP(F4, b, c, d, a, key[13] + 0x4e0811a1, 21);
4198d5 ¤   MD5STEP(F4, a, b, c, d, key[4] + 0xf7537e82, 6);
efdb8d ¤   MD5STEP(F4, d, a, b, c, key[11] + 0xbd3af235, 10);
39d457 ¤   MD5STEP(F4, c, d, a, b, key[2] + 0x2ad7d2bb, 15);
e8e701 ¤   MD5STEP(F4, b, c, d, a, key[9] + 0xeb86d391, 21);
ffaf5a
ca7785 ¤   block[0] += a;
d6d51c ¤   block[1] += b;
f359c7 ¤   block[2] += c;
44983f ¤   block[3] += d;
3cefe6 }
68af5a
3b38e5 /*
d6049f ·* Update context to reflect the concatenation of another buffer full
396682 ·* of bytes.
50495d ·*/
f82978 static void
954b27 MD5Update(void *priv, void const *bufIn, PGPSize len)
f9bb36 {
add3c2 ¤   MD5Context ¤*ctx = (MD5Context *)priv;
a5cd75 ¤   PGPByte¤¤   *buf = (PGPByte *) bufIn;
21ad33 ¤   unsigned ¤  i;
5aaf5a
91a0a9 #if HAVE64
9e834d ¤   i = (unsigned)ctx->bytes % MD5_BLOCKBYTES;
935338 ¤   ctx->bytes += len;
c6db21 #else
4b30a7 ¤   PGPUInt32 t = ctx->bytesLo;
864e69 ¤   if ((ctx->bytesLo = t + len) < t)
dbc448 ¤   ¤   ctx->bytesHi++; ¤   /* Carry from low to high */
b4defe ¤   i = (unsigned)t % MD5_BLOCKBYTES;¤  /* Bytes already in ctx->key */
8b7454 #endif
554532 ¤   if (MD5_BLOCKBYTES-i > len) {
ef67e3 ¤   ¤   memcpy((PGPByte *)ctx->key + i, buf, len);
6c99bf ¤   ¤   return;
439371 ¤   }
7aaf5a
e9c265 ¤   if (i) {¤   /* First chunk is an odd size */
49e9f4 ¤   ¤   memcpy((PGPByte *)ctx->key + i, buf, MD5_BLOCKBYTES - i);
d233f2 ¤   ¤   MD5ByteSwap(ctx->key, (PGPByte *)ctx->key, MD5_BLOCKWORDS);
03474a ¤   ¤   pgpMD5Transform(ctx->iv, ctx->key);
56a8c5 ¤   ¤   buf += MD5_BLOCKBYTES-i;
--5be3 000e6e7d9ee40100138 Page 4 of pgpMD5.c
fbd376 ¤   ¤   len -= MD5_BLOCKBYTES-i;
0c9371 ¤   }
88af5a
390834 ¤   /* Process data in 64-byte chunks */
2d8954 ¤   while (len >= MD5_BLOCKBYTES) {
d89cfa ¤   ¤   MD5ByteSwap(ctx->key, buf, MD5_BLOCKWORDS);
f5474a ¤   ¤   pgpMD5Transform(ctx->iv, ctx->key);
7afd65 ¤   ¤   buf += MD5_BLOCKBYTES;
b7ba62 ¤   ¤   len -= MD5_BLOCKBYTES;
ad9371 ¤   }
dfaf5a
7894e0 ¤   /* Handle any remaining bytes of data. */
ec4548 ¤   if (len)
f7fab4 ¤   ¤   memcpy(ctx->key, buf, len);
1defe6 }
d7af5a
3d38e5 /*
4e65d5 ·* Final wrapup - pad to 64-byte boundary with the bit pattern·
17473d ·* 1 0* (64-bit count of bits processed, LSB-first)
11495d ·*/
289c71 static void const *
50d010 MD5Final(void *priv)
2dbb36 {
3484ef ¤   MD5Context *ctx = (MD5Context *)priv;
7bc7aa ¤   PGPByte *digest;
c9a0a9 #if HAVE64
c9f9b8 ¤   unsigned i = (unsigned)ctx->bytes % MD5_BLOCKBYTES;
6bdb21 #else
25be51 ¤   unsigned i = (unsigned)ctx->bytesLo % MD5_BLOCKBYTES;
567454 #endif
b2d219 ¤   PGPByte *p = (PGPByte *)ctx->key + i;¤  /* First unused byte */
482b16 ¤   PGPUInt32 t;
85af5a
bfb051 ¤   /* Set the first char of padding to 0x80. ·There is always room. */
b3c755 ¤   *p++ = 0x80;
98af5a
8aaeaf ¤   /* Bytes of padding needed to make 64 bytes (0..63) */
7794ab ¤   i = MD5_BLOCKBYTES - 1 - i;
afaf5a
175a02 ¤   if (i < 8) {¤   /* Padding forces an extra block */
fa577d ¤   ¤   pgpClearMemory( p, ·i);
2a6c56 ¤   ¤   MD5ByteSwap(ctx->key, (PGPByte *)ctx->key, 16);
da474a ¤   ¤   pgpMD5Transform(ctx->iv, ctx->key);
c053a0 ¤   ¤   p = (PGPByte *)ctx->key;
7fb258 ¤   ¤   i = 64;
929371 ¤   }
a5485c ¤   pgpClearMemory( p, ·i-8);
cf008c ¤   MD5ByteSwap(ctx->key, (PGPByte *)ctx->key, 14);
e4af5a
df52ad ¤   /* Append length in bits and transform */
48a0a9 #if HAVE64
22c6cb ¤   ctx->key[14] = (PGPUInt32)ctx->bytes << 3;
d3b87e ¤   ctx->key[15] = (PGPUInt32)(ctx->bytes >> 29);
72db21 #else
4d4316 ¤   ctx->key[14] = ctx->bytesLo << 3;
b389f3 ¤   ctx->key[15] = ctx->bytesHi << 3 | ctx->bytesLo >> 29;
747454 #endif
f9cf2c ¤   pgpMD5Transform(ctx->iv, ctx->key);
b9af5a
5f53be ¤   /* Convert digest to the correct byte order */
f4a1bb ¤   digest = (PGPByte *)ctx->iv;
166e4e ¤   for (i = 0; i < MD5_HASHWORDS; i++) {
1621b7 ¤   ¤   t = ctx->iv[i];
fb72ae ¤   ¤   digest[0] = (PGPByte)t;
844a8f ¤   ¤   digest[1] = (PGPByte)(t >> 8);
0e6009 ¤   ¤   digest[2] = (PGPByte)(t >> 16);
7040c8 ¤   ¤   digest[3] = (PGPByte)(t >> 24);
337beb ¤   ¤   digest += 4;
c59371 ¤   }
9e57b6 ¤   /* In case it's sensitive */
5bc2db /* XXX¤ memset(ctx->key, 0, sizeof(ctx->key)); */
e6862e ¤   return (PGPByte const *)ctx->iv;
--5cdf 000fa139a4640100138 Page 5 of pgpMD5.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
c8dbd6 ·* The Basic Encoding Rules (of which the Distinguished Encoding Rules
b1cee6 ·* are a simple minimal-sized subset) are supposed to be compact. ·Humph.
3b495d ·*/
cb5898 static PGPByte const MD5DERprefix[] = {
a3eef2 ¤   0x30, /* Universal, Constructed, Sequence */
b7de2a ¤   0x20, /* Length 32 (bytes following) */
9cbde9 ¤   ¤   0x30, /* Universal, Constructed, Sequence */
309f04 ¤   ¤   0x0c, /* Length 12 */
a76507 ¤   ¤   ¤   0x06, /* Universal, Primitive, object-identifier */
83745e ¤   ¤   ¤   0x08, /* Length 8 */
d85b93 ¤   ¤   ¤   ¤   0x2a, /* 42 = ISO(1)*40 + Member bodies(2) */
e5adb4 ¤   ¤   ¤   ¤   0x86, 0x48, /* 840 = US (ANSI) */
37bc6f ¤   ¤   ¤   ¤   0x86, 0xF7, 0x0D, /* 113549 = RSADSI */
332e94 ¤   ¤   ¤   ¤   0x02, /* 2 = Hash functions */
621a63 ¤   ¤   ¤   ¤   0x05, /* 5 = MD5 */
50c238 ¤   ¤   ¤   0x05, /* Universal, Primitive, NULL */
e5d131 ¤   ¤   ¤   0x00, /* Length 0 */
036fe2 ¤   ¤   0x04, /* Universal, Primitive, Octet string */
10ca9a ¤   ¤   0x10 /* Length 16 */
b80921 ¤   ¤   ¤   /* 16 MD5 digest bytes go here */
e582f7 };
0daf5a
3701e8 PGPHashVTBL const HashMD5 = {
17bab3 ¤   "MD5", kPGPHashAlgorithm_MD5,
39dfc2 ¤   MD5DERprefix, sizeof(MD5DERprefix),
1fb9be ¤   MD5_HASHBYTES,
99ba02 ¤   sizeof(MD5Context),
da0d12 ¤   sizeof(struct{char _a; MD5Context _b;}) -
824c67 ¤   ¤   sizeof(MD5Context),
371421 ¤   MD5Init, MD5Update, MD5Final
5482f7 };
f5af5a
ca3e83 #if TESTMAIN
bfaf5a
26feb2 #include <stdio.h>
40324c #include <string.h>
5a0a8b #include <time.h>
20af5a
b76ec3 #define TEST_BYTES 10000000
75af5a
bb7749 static char const * const md5TestResults[] = {
d385d5 ¤   "0cc175b9c0f1b6a831c399e269772661",
a78698 ¤   "900150983cd24fb0d6963f7d28e17f72",
5d1416 ¤   "7707d6ae4e027c70eea2a935c2296f21",
151416 ¤   "7707d6ae4e027c70eea2a935c2296f21",
61f36a ¤   "7707d6ae4e027c70eea2a935c2296f21"
3f82f7 };
a4af5a
9abeb7 static int
883c53 compareMD5results(PGPByte const *hash, int level)
d9bb36 {
bc9e40 ¤   char buf[33];
5e743f ¤   unsigned i;
17af5a
1143b8 ¤   for (i = 0; i < MD5_HASHSIZE; i++)
5ae1a7 ¤   ¤   sprintf(buf+2*i, "%02x", hash[i]);
a5e021 ¤   if (strcmp(buf, md5TestResults[level-1]) == 0) {
352031 ¤   ¤   printf("Test %d passed, result = %s\n", level, buf);
0abbde ¤   ¤   return 0;
e9f037 ¤   } else {
12b18b ¤   ¤   printf("Error in MD5 implementation; test %d failed\n", level);
b0945d ¤   ¤   printf(" ·Result = %s\nExpected = %s\n", buf,
7b2a8f ¤   ¤   ¤   md5TestResults[level-1]);
3d043c ¤   ¤   return -1;
d29371 ¤   }
71efe6 }
aaaf5a
fa4d2f int
--1a2f 0012d958d7440100138 Page 6 of pgpMD5.c
077f68 main(void)
8fbb36 {
07817a ¤   clock_t ticks;
d593f6 ¤   MD5Context md5;
61f96d ¤   PGPByte hash[MD5_HASHSIZE];
75cd18 ¤   PGPByte data[1999];
5b743f ¤   unsigned i;
ddaf5a
240d30 ¤   MD5Init(&md5);
fac86e ¤   MD5Update(&md5, "a", 1);
f72281 ¤   MD5Final(&md5, hash);
a5d910 ¤   if (compareMD5results(hash, 1) < 0)
ee043c ¤   ¤   return -1;
87af5a
950d30 ¤   MD5Init(&md5);
126246 ¤   MD5Update(&md5, "abc", 3);
752281 ¤   MD5Final(&md5, hash);
8853c0 ¤   if (compareMD5results(hash, 2) < 0)
44043c ¤   ¤   return -1;
03af5a
04d5be ¤   /* 1,000,000 bytes of ASCII 'a', by 64s */
d10d30 ¤   MD5Init(&md5);
f043cb ¤   for (i = 0; i < 15625; i++) {
b37ebc ¤   ¤   MD5Update(&md5, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
77246a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64);
3d9371 ¤   }
0e2281 ¤   MD5Final(&md5, hash);
10d27f ¤   if (compareMD5results(hash, 3) < 0)
93043c ¤   ¤   return -1;
89af5a
3ebee3 ¤   /* 1,000,000 bytes of ASCII 'a', by 25s */
a90d30 ¤   MD5Init(&md5);
72be5c ¤   for (i = 0; i < 40000; i++)
c6031e ¤   ¤   MD5Update(&md5, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa", 25);
202281 ¤   MD5Final(&md5, hash);
044e71 ¤   if (compareMD5results(hash, 4) < 0)
f8043c ¤   ¤   return -1;
0faf5a
f4fda4 ¤   /* 1,000,000 bytes of ASCII 'a', by 125s */
5d0d30 ¤   MD5Init(&md5);
4eeb47 ¤   for (i = 0; i < 8000; i++)
777ebc ¤   ¤   MD5Update(&md5, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
0fc1b0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
198064 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 125);
802281 ¤   MD5Final(&md5, hash);
6ccfce ¤   if (compareMD5results(hash, 5) < 0)
2b043c ¤   ¤   return -1;
e2af5a
8a3bff ¤   pgpClearMemory( data, ·sizeof(data));
a5af5a
ae6a0f ¤   ticks = clock();
cb0d30 ¤   MD5Init(&md5);
8e316a ¤   for (i = 0; i < TEST_BYTES/sizeof(data); i++)
976957 ¤   ¤   MD5Update(&md5, data, sizeof(data));
9fdf2c ¤   MD5Update(&md5, data,TEST_BYTES % sizeof(data));
ee67c5 ¤
e82281 ¤   MD5Final(&md5, hash);
31af5a
3930c3 ¤   ticks = clock() - ticks;
74af5a
5d5587 ¤   printf("Elapsed time for %lu characters: %lu ticks\n",
299b87 ¤   ¤   (unsigned long)TEST_BYTES, (unsigned long)ticks);
ca3e6b ¤   return 0;
2aefe6 }
3baf5a
2d9348 #endif /* TESTMAIN */
--f345 001bb731d4340100139 Page 1 of pgpMD5.h
bc38e5 /*
a02624 ·* pgpMD5.h -- The MD-5 Message Digest.
d7775e ·*
16e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
d62979 ·* You should not be using these functions in an application.
8f775e ·*
44e878 ·* $Id: pgpMD5.h,v 1.7 1997/08/30 03:05:59 hal Exp $
d9495d ·*/
e0af5a
f7feb8 #ifndef Included_pgpMD5_h
64b6af #define Included_pgpMD5_h
0aaf5a
275417 #include "pgpHashPriv.h"
03af5a
ab99c6 PGP_BEGIN_C_DECLARATIONS
91af5a
092621 extern PGPHashVTBL const HashMD5;
beaf5a
94af5a
733850 void¤   pgpMD5Transform(PGPUInt32 *block, PGPUInt32 const *key);
3faf5a
021254 PGP_END_C_DECLARATIONS
d0af5a
bbf007 #endif /* !Included_pgpMD5_h */
--bab1 000e8eed62e4010013a Page 1 of pgpRIPEMD160.c
bc38e5 /*
421c6c ·* pgpRIPEMD160.c - European RIPE Message Digest, 160 bit (RIPEMD-160)
08775e ·*
b44841 ·* The algorithm is by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
f5775e ·*
b12d59 ·* The code below is based on the reference implementation by Bosselaers.
f236d9 ·* It is available at the time of writing from
2f6ba6 ·* http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
41775e ·*
5188ac ·* $Id: pgpRIPEMD160.c,v 1.5 1997/10/14 01:48:22 heller Exp $
f2495d ·*/
24af5a
b0e2ff #include "pgpConfig.h"
50af5a
d4324c #include <string.h>
ebaf5a
3f9f72 #include "pgpHash.h"
146f37 #include "pgpRIPEMD160.h"
a1d11f #include "pgpUsuals.h"
b60d08 #include "pgpMem.h"
91a146 #include "pgpDebug.h"
63af5a
66df57 #define RIPEMD160_BLOCKBYTES¤   64
43d404 #define RIPEMD160_BLOCKWORDS¤   16
dfaf5a
fe560f #define RIPEMD160_HASHBYTES¤20
eb4b6c #define RIPEMD160_HASHWORDS¤5
7caf5a
49754c typedef struct RIPEMD160Context {
b9616a ¤   PGPUInt32 key[RIPEMD160_BLOCKWORDS];
3ebe9e ¤   PGPUInt32 iv[RIPEMD160_HASHWORDS];
845873 ¤   PGPUInt32 bytesHi, bytesLo;
a9074f ¤   DEBUG_STRUCT_CONSTRUCTOR( RIPEMD160Context )
de866b } RIPEMD160Context;
2baf5a
ceaf5a
9caf5a
70e1aa /************************ File rmd160.h **********************/
94907c /* Extracted from rmd160.h in the reference implementation */
8caf5a
10b21f /* macro definitions */
9daf5a
eb075e /* ROL(x, n) cyclically rotates x over n bits to the left */
042252 /* x must be of an unsigned 32 bits type and 0 <= n < 32. */
8e2796 #define ROL(x, n) ·······(((x) << (n)) | ((x) >> (32-(n))))
b9af5a
ab6533 /* the three basic functions F(), G() and H() */
24ab50 #define F(x, y, z) ·······((x) ^ (y) ^ (z))·
1c85b9 #define G(x, y, z) ·······(((x) & (y)) | (~(x) & (z)))·
7247f2 #define H(x, y, z) ·······(((x) | ~(y)) ^ (z))
5bcb94 #define I(x, y, z) ·······(((x) & (z)) | ((y) & ~(z)))·
701529 #define J(x, y, z) ·······((x) ^ ((y) | ~(z)))
c0de7b ··
d067c0 /* the eight basic operations FF() through III() */
31b784 #define FF(a, b, c, d, e, x, s) ·······{\
d5e835 ······(a) += F((b), (c), (d)) + (x);\
e60163 ······(a) = ROL((a), (s)) + (e);\
cff6b5 ······(c) = ROL((c), 10);\
e9b144 ···}
04a63a #define GG(a, b, c, d, e, x, s) ·······{\
c602a2 ······(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
8c0163 ······(a) = ROL((a), (s)) + (e);\
77f6b5 ······(c) = ROL((c), 10);\
60b144 ···}
815ff0 #define HH(a, b, c, d, e, x, s) ·······{\
e98739 ······(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
140163 ······(a) = ROL((a), (s)) + (e);\
64f6b5 ······(c) = ROL((c), 10);\
fbb144 ···}
f74e4e #define II(a, b, c, d, e, x, s) ·······{\
aec74f ······(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
e80163 ······(a) = ROL((a), (s)) + (e);\
--1d3b 0006c15dae34010013a Page 2 of pgpRIPEMD160.c
85f6b5 ······(c) = ROL((c), 10);\
12b144 ···}
317c8c #define JJ(a, b, c, d, e, x, s) ·······{\
44360c ······(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
d00163 ······(a) = ROL((a), (s)) + (e);\
3cf6b5 ······(c) = ROL((c), 10);\
31b144 ···}
2fdfd2 #define FFF(a, b, c, d, e, x, s) ·······{\
e7e835 ······(a) += F((b), (c), (d)) + (x);\
8c0163 ······(a) = ROL((a), (s)) + (e);\
4ff6b5 ······(c) = ROL((c), 10);\
86b144 ···}
f7c355 #define GGG(a, b, c, d, e, x, s) ·······{\
375939 ······(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
660163 ······(a) = ROL((a), (s)) + (e);\
7ff6b5 ······(c) = ROL((c), 10);\
92b144 ···}
fb70f8 #define HHH(a, b, c, d, e, x, s) ·······{\
0eeb39 ······(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
550163 ······(a) = ROL((a), (s)) + (e);\
a9f6b5 ······(c) = ROL((c), 10);\
6eb144 ···}
926c7f #define III(a, b, c, d, e, x, s) ·······{\
f77d40 ······(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
7b0163 ······(a) = ROL((a), (s)) + (e);\
24f6b5 ······(c) = ROL((c), 10);\
45b144 ···}
6a49f6 #define JJJ(a, b, c, d, e, x, s) ·······{\
872627 ······(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
c50163 ······(a) = ROL((a), (s)) + (e);\
11f6b5 ······(c) = ROL((c), 10);\
d2b144 ···}
71af5a
b4af5a
8daf5a
86e4ad /************************ File rmd160.c **********************/
d3ac21 /* Extracted from rmd160.c in the reference implementation */
70af5a
dfaf5a
0038e5 /*
26184d ·* ·initializes MDbuffer to "magic constants"
b1495d ·*/
94ac88 static void RMDinit(PGPUInt32 *MDbuf)
00bb36 {
830e2e ···MDbuf[0] = 0x67452301UL;
90800d ···MDbuf[1] = 0xefcdab89UL;
d8a862 ···MDbuf[2] = 0x98badcfeUL;
f6cb96 ···MDbuf[3] = 0x10325476UL;
ac63ce ···MDbuf[4] = 0xc3d2e1f0UL;
46af5a
012641 ···return;
9cefe6 }
74af5a
d5af5a
6438e5 /*
166932 ·* ·the compression function.
15c78f ·* ·transforms MDbuf using message PGPBytes X[0] through X[15]
65495d ·*/
a78603 static void RMDcompress(PGPUInt32 *MDbuf, PGPUInt32 *X)
cabb36 {
e6ce9e ···PGPUInt32 aa = MDbuf[0], ·bb = MDbuf[1], ·cc = MDbuf[2],
81f479 ·········dd = MDbuf[3], ·ee = MDbuf[4];
6bb782 ···PGPUInt32 aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
c356d0 ·········ddd = MDbuf[3], eee = MDbuf[4];
b8af5a
e14bba ···/* round 1 */
ef4686 ···FF(aa, bb, cc, dd, ee, X[ 0], 11);
f5e846 ···FF(ee, aa, bb, cc, dd, X[ 1], 14);
1980cb ···FF(dd, ee, aa, bb, cc, X[ 2], 15);
3341cc ···FF(cc, dd, ee, aa, bb, X[ 3], 12);
cc99ba ···FF(bb, cc, dd, ee, aa, X[ 4], ·5);
6c7c30 ···FF(aa, bb, cc, dd, ee, X[ 5], ·8);
--03e2 000c82a018c4010013a Page 3 of pgpRIPEMD160.c
9e95a4 ···FF(ee, aa, bb, cc, dd, X[ 6], ·7);
f6d42a ···FF(dd, ee, aa, bb, cc, X[ 7], ·9);
f4cdcc ···FF(cc, dd, ee, aa, bb, X[ 8], 11);
776e3f ···FF(bb, cc, dd, ee, aa, X[ 9], 13);
72d6a4 ···FF(aa, bb, cc, dd, ee, X[10], 14);
100a88 ···FF(ee, aa, bb, cc, dd, X[11], 15);
9eeabe ···FF(dd, ee, aa, bb, cc, X[12], ·6);
086023 ···FF(cc, dd, ee, aa, bb, X[13], ·7);
b4f0fb ···FF(bb, cc, dd, ee, aa, X[14], ·9);
cb8245 ···FF(aa, bb, cc, dd, ee, X[15], ·8);
6a452c ·····························
b55676 ···/* round 2 */
fb84bd ···GG(ee, aa, bb, cc, dd, X[ 7], ·7);
beec30 ···GG(dd, ee, aa, bb, cc, X[ 4], ·6);
8d8e3e ···GG(cc, dd, ee, aa, bb, X[13], ·8);
314d11 ···GG(bb, cc, dd, ee, aa, X[ 1], 13);
d0e417 ···GG(aa, bb, cc, dd, ee, X[10], 11);
046702 ···GG(ee, aa, bb, cc, dd, X[ 6], ·9);
714303 ···GG(dd, ee, aa, bb, cc, X[15], ·7);
3b4a09 ···GG(cc, dd, ee, aa, bb, X[ 3], 15);
39a642 ···GG(bb, cc, dd, ee, aa, X[12], ·7);
713faf ···GG(aa, bb, cc, dd, ee, X[ 0], 12);
11d7d3 ···GG(ee, aa, bb, cc, dd, X[ 9], 15);
511334 ···GG(dd, ee, aa, bb, cc, X[ 5], ·9);
747518 ···GG(cc, dd, ee, aa, bb, X[ 2], 11);
44025d ···GG(bb, cc, dd, ee, aa, X[14], ·7);
61909c ···GG(aa, bb, cc, dd, ee, X[11], 13);
a7cd0f ···GG(ee, aa, bb, cc, dd, X[ 8], 12);
aeaf5a
365d32 ···/* round 3 */
268a91 ···HH(dd, ee, aa, bb, cc, X[ 3], 11);
9c404e ···HH(cc, dd, ee, aa, bb, X[10], 13);
8a7749 ···HH(bb, cc, dd, ee, aa, X[14], ·6);
55b67f ···HH(aa, bb, cc, dd, ee, X[ 4], ·7);
c4a2c7 ···HH(ee, aa, bb, cc, dd, X[ 9], 14);
f884ee ···HH(dd, ee, aa, bb, cc, X[15], ·9);
19c1f1 ···HH(cc, dd, ee, aa, bb, X[ 8], 13);
aa6f24 ···HH(bb, cc, dd, ee, aa, X[ 1], 15);
658660 ···HH(aa, bb, cc, dd, ee, X[ 2], 14);
955feb ···HH(ee, aa, bb, cc, dd, X[ 7], ·8);
bd65e0 ···HH(dd, ee, aa, bb, cc, X[ 0], 13);
e8c5be ···HH(cc, dd, ee, aa, bb, X[ 6], ·6);
86bb66 ···HH(bb, cc, dd, ee, aa, X[13], ·5);
5ae588 ···HH(aa, bb, cc, dd, ee, X[11], 12);
8176e8 ···HH(ee, aa, bb, cc, dd, X[ 5], ·7);
49fa38 ···HH(dd, ee, aa, bb, cc, X[12], ·5);
caaf5a
3b6dee ···/* round 4 */
c29654 ···II(cc, dd, ee, aa, bb, X[ 1], 11);
b31b2b ···II(bb, cc, dd, ee, aa, X[ 9], 12);
b4f2f6 ···II(aa, bb, cc, dd, ee, X[11], 14);
f62eda ···II(ee, aa, bb, cc, dd, X[10], 15);
f06e25 ···II(dd, ee, aa, bb, cc, X[ 0], 14);
e8d68f ···II(cc, dd, ee, aa, bb, X[ 8], 15);
1f3d4b ···II(bb, cc, dd, ee, aa, X[12], ·9);
f85862 ···II(aa, bb, cc, dd, ee, X[ 4], ·8);
62de24 ···II(ee, aa, bb, cc, dd, X[13], ·9);
80b822 ···II(dd, ee, aa, bb, cc, X[ 3], 14);
a2f16a ···II(cc, dd, ee, aa, bb, X[ 7], ·5);
db6650 ···II(bb, cc, dd, ee, aa, X[15], ·6);
3ca617 ···II(aa, bb, cc, dd, ee, X[14], ·8);
a636b7 ···II(ee, aa, bb, cc, dd, X[ 5], ·6);
f7674c ···II(dd, ee, aa, bb, cc, X[ 6], ·5);
7e659e ···II(cc, dd, ee, aa, bb, X[ 2], 12);
e6af5a
0266aa ···/* round 5 */
92820d ···JJ(bb, cc, dd, ee, aa, X[ 4], ·9);
ebb8e9 ···JJ(aa, bb, cc, dd, ee, X[ 0], 15);
ccf656 ···JJ(ee, aa, bb, cc, dd, X[ 5], ·5);
dcd769 ···JJ(dd, ee, aa, bb, cc, X[ 9], 11);
ae318b ···JJ(cc, dd, ee, aa, bb, X[ 7], ·6);
c8c4dc ···JJ(bb, cc, dd, ee, aa, X[12], ·8);
--375f 000e3fffda74010013a Page 4 of pgpRIPEMD160.c
006889 ···JJ(aa, bb, cc, dd, ee, X[ 2], 13);
639cd7 ···JJ(ee, aa, bb, cc, dd, X[10], 12);
f7e7ef ···JJ(dd, ee, aa, bb, cc, X[14], ·5);
4456b5 ···JJ(cc, dd, ee, aa, bb, X[ 1], 12);
15068c ···JJ(bb, cc, dd, ee, aa, X[ 3], 13);
2edb98 ···JJ(aa, bb, cc, dd, ee, X[ 8], 14);
51f4e7 ···JJ(ee, aa, bb, cc, dd, X[11], 11);
0509ef ···JJ(dd, ee, aa, bb, cc, X[ 6], ·8);
b171c9 ···JJ(cc, dd, ee, aa, bb, X[15], ·5);
c82763 ···JJ(bb, cc, dd, ee, aa, X[13], ·6);
00af5a
c66f73 ···/* parallel round 1 */
d1021e ···JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], ·8);
3ffd05 ···JJJ(eee, aaa, bbb, ccc, ddd, X[14], ·9);
f34292 ···JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], ·9);
2a442d ···JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
3a55ad ···JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
4fd1be ···JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
55a9e4 ···JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
2503a1 ···JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], ·5);
fc9608 ···JJJ(ccc, ddd, eee, aaa, bbb, X[13], ·7);
1900a4 ···JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], ·7);
d3fc6b ···JJJ(aaa, bbb, ccc, ddd, eee, X[15], ·8);
25174a ···JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
57dccf ···JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
ebd40f ···JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
78ad26 ···JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
b1bbcb ···JJJ(aaa, bbb, ccc, ddd, eee, X[12], ·6);
beaf5a
5572bf ···/* parallel round 2 */
c25845 ···III(eee, aaa, bbb, ccc, ddd, X[ 6], ·9);·
f1138f ···III(ddd, eee, aaa, bbb, ccc, X[11], 13);
3686d2 ···III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
f82b4d ···III(bbb, ccc, ddd, eee, aaa, X[ 7], ·7);
e67b71 ···III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
c76e48 ···III(eee, aaa, bbb, ccc, ddd, X[13], ·8);
b1bf7c ···III(ddd, eee, aaa, bbb, ccc, X[ 5], ·9);
84dc4c ···III(ccc, ddd, eee, aaa, bbb, X[10], 11);
07033f ···III(bbb, ccc, ddd, eee, aaa, X[14], ·7);
822886 ···III(aaa, bbb, ccc, ddd, eee, X[15], ·7);
6a5493 ···III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
4106a9 ···III(ddd, eee, aaa, bbb, ccc, X[12], ·7);
b6fb30 ···III(ccc, ddd, eee, aaa, bbb, X[ 4], ·6);
4e7823 ···III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
6c2a37 ···III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
4d956e ···III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
d4af5a
1979fb ···/* parallel round 3 */
599b0a ···HHH(ddd, eee, aaa, bbb, ccc, X[15], ·9);
9c7075 ···HHH(ccc, ddd, eee, aaa, bbb, X[ 5], ·7);
24ddea ···HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
8252b8 ···HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
ee75db ···HHH(eee, aaa, bbb, ccc, ddd, X[ 7], ·8);
e3640e ···HHH(ddd, eee, aaa, bbb, ccc, X[14], ·6);
febac9 ···HHH(ccc, ddd, eee, aaa, bbb, X[ 6], ·6);
abbe9b ···HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
4412fa ···HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
06922b ···HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
33e5dc ···HHH(ddd, eee, aaa, bbb, ccc, X[12], ·5);
e50d97 ···HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
9925f8 ···HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
85bdc9 ···HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
3c1125 ···HHH(eee, aaa, bbb, ccc, ddd, X[ 4], ·7);
84a821 ···HHH(ddd, eee, aaa, bbb, ccc, X[13], ·5);
03af5a
ab93c6 ···/* parallel round 4 */ ··
640349 ···GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
727390 ···GGG(bbb, ccc, ddd, eee, aaa, X[ 6], ·5);
a805a1 ···GGG(aaa, bbb, ccc, ddd, eee, X[ 4], ·8);
a96f3f ···GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
800d77 ···GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
e3d3b0 ···GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
--6ede 00022c95fbb4010013a Page 5 of pgpRIPEMD160.c
a97e2f ···GGG(bbb, ccc, ddd, eee, aaa, X[15], ·6);
c01cbd ···GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
55b636 ···GGG(eee, aaa, bbb, ccc, ddd, X[ 5], ·6);
b284bd ···GGG(ddd, eee, aaa, bbb, ccc, X[12], ·9);
2cb058 ···GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
1d68c9 ···GGG(bbb, ccc, ddd, eee, aaa, X[13], ·9);
396510 ···GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
9f0801 ···GGG(eee, aaa, bbb, ccc, ddd, X[ 7], ·5);
f939be ···GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
158751 ···GGG(ccc, ddd, eee, aaa, bbb, X[14], ·8);
c4af5a
da4263 ···/* parallel round 5 */
479002 ···FFF(bbb, ccc, ddd, eee, aaa, X[12] , ·8);
77db3e ···FFF(aaa, bbb, ccc, ddd, eee, X[15] , ·5);
d80c73 ···FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
2259d7 ···FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , ·9);
fc7a43 ···FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
a5fbac ···FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , ·5);
4ba70e ···FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
c82f73 ···FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , ·6);
681d22 ···FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , ·8);
001291 ···FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
cc1267 ···FFF(bbb, ccc, ddd, eee, aaa, X[13] , ·6);
68f719 ···FFF(aaa, bbb, ccc, ddd, eee, X[14] , ·5);
d97f86 ···FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
fdf041 ···FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
5e36a7 ···FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
7cacc5 ···FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
4caf5a
6989de ···/* combine results */
e6c120 ···ddd += cc + MDbuf[1]; ··············/* final result for MDbuf[0] */
5eff21 ···MDbuf[1] = MDbuf[2] + dd + eee;
3bb5ad ···MDbuf[2] = MDbuf[3] + ee + aaa;
45d026 ···MDbuf[3] = MDbuf[4] + aa + bbb;
486540 ···MDbuf[4] = MDbuf[0] + bb + ccc;
a658f5 ···MDbuf[0] = ddd;
53af5a
e02641 ···return;
88efe6 }
07af5a
e2af5a
1438e5 /*
9448bd ·* ·puts bytes from strptr into X and pad out; appends length·
f4079e ·* ·and finally, compresses the last block(s)
9ccf72 ·* ·note: length in bits == 8 * (lswlen + 2^32 mswlen).
03763e ·* ·note: there are (lswlen mod 64) bytes left in strptr.
df495d ·*/
e40302 static void RMDfinish(PGPUInt32 *MDbuf, PGPByte *strptr, PGPUInt32 lswlen,
3bb1c6 ¤   PGPUInt32 mswlen)
cfbb36 {
3dc80b ···PGPUInt32 ·······i; ·························/* counter ······*/
070a41 ···PGPUInt32 ·······X[16]; ·····················/* message words */
f0af5a
256637 ···pgpClearMemory( X, ·16*sizeof(PGPUInt32));
e9af5a
0c9db1 ···/* put bytes from strptr into X */
71025b ···for (i=0; i<(lswlen&63); i++) {
6dc6d0 ······/* byte i goes into word X[i div 4] at pos. ·8*(i mod 4) ·*/
29b450 ······X[i>>2] ^= (PGPUInt32) *strptr++ << (8 * (i&3));
49b144 ···}
8eaf5a
36cc3d ···/* append the bit m_n == 1 */
945ea5 ···X[(lswlen>>2)&15] ^= (PGPUInt32)1 << (8*(lswlen&3) + 7);
fcaf5a
e088be ···if ((lswlen & 63) > 55) {
377ae5 ······/* length goes to next block */
ff0189 ······RMDcompress(MDbuf, X);
0ecc97 ¤   ··pgpClearMemory( X, ·16*sizeof(PGPUInt32));
bdb144 ···}
6faf5a
62912b ···/* append length in bits*/
229130 ···X[14] = lswlen << 3;
--486f 0007b837cfd4010013a Page 6 of pgpRIPEMD160.c
320d5a ···X[15] = (lswlen >> 29) | (mswlen << 3);
b0b114 ···RMDcompress(MDbuf, X);
8eaf5a
b22641 ···return;
96efe6 }
6eaf5a
e73fe8 /************************ end of file rmd160.c **********************/
4cf8eb /* Remainder provides common interface used by PGP library */
a4af5a
93af5a
3d38e5 /*
fffcdf ·* Shuffle the bytes into little-endian order within 32-bit words,
bca4cd ·* as per the RIPEMD-160 spec (which follows MD4 conventions).
0f495d ·*/
f62978 static void
218fe5 rmd160ByteSwap(PGPUInt32 *dest, PGPByte const *src, unsigned words)
8ebb36 {
6043ab ¤   do {
905137 ¤   ¤   *dest++ = (PGPUInt32)((unsigned)src[3] << 8 | src[2]) << 16 |
6b3e19 ¤   ¤   ··················((unsigned)src[1] << 8 | src[0]);
d3aa48 ¤   ¤   src += 4;
00c244 ¤   } while (--words);
7eefe6 }
e0af5a
79af5a
456be6 /* Initialize the RIPEMD-160 values */
7eaf5a
c22978 static void
7d0286 rmd160Init(void *priv)
2cbb36 {
81e6ed ¤   struct RIPEMD160Context *ctx = (struct RIPEMD160Context *)priv;
fdaf5a
a4f4a8 ¤   /* Set the h-vars to their initial values */
73a513 ¤   RMDinit (ctx->iv);
8faf5a
3bf91f ¤   /* Initialise bit count */
23b288 ¤   ctx->bytesHi = 0;
5bfc9b ¤   ctx->bytesLo = 0;
faefe6 }
8eaf5a
6e78e0 /* Update the RIPEMD-160 hash state for a block of data. */
53af5a
aa2978 static void
bc148c rmd160Update(void *priv, void const *bufIn, PGPSize len)
27bb36 {
46e6ed ¤   struct RIPEMD160Context *ctx = (struct RIPEMD160Context *)priv;
35743f ¤   unsigned i;
1ce130 ¤   PGPByte *buf = (PGPByte *) bufIn;
2f67c5 ¤
d17f74 ¤   /* Update bitcount */
f5af5a
f330a7 ¤   PGPUInt32 t = ctx->bytesLo;
536738 ¤   if ( ( ctx->bytesLo = t + len ) < t )
b7f8d4 ¤   ¤   ctx->bytesHi++;¤/* Carry from low to high */
edaf5a
9f098e ¤   i = (unsigned)t % RIPEMD160_BLOCKBYTES; /* bytes already in ctx->key */
55af5a
d70138 ¤   /* i is always less than RIPEMD160_BLOCKBYTES. */
8e55f6 ¤   if (RIPEMD160_BLOCKBYTES-i > len) {
2e67e3 ¤   ¤   memcpy((PGPByte *)ctx->key + i, buf, len);
2099bf ¤   ¤   return;
7d9371 ¤   }
73af5a
44c265 ¤   if (i) {¤   /* First chunk is an odd size */
c77b65 ¤   ¤   memcpy((PGPByte *)ctx->key + i, buf, RIPEMD160_BLOCKBYTES - i);
cb5e15 ¤   ¤   rmd160ByteSwap(ctx->key, (PGPByte *)ctx->key, RIPEMD160_BLOCKWORDS);
2e6d4f ¤   ¤   RMDcompress(ctx->iv, ctx->key);
cc5f1c ¤   ¤   buf += RIPEMD160_BLOCKBYTES-i;
e9c30c ¤   ¤   len -= RIPEMD160_BLOCKBYTES-i;
419371 ¤   }
beaf5a
7b0834 ¤   /* Process data in 64-byte chunks */
--8f5b 00045feae184010013a Page 7 of pgpRIPEMD160.c
53d82b ¤   while (len >= RIPEMD160_BLOCKBYTES) {
a3287f ¤   ¤   rmd160ByteSwap(ctx->key, buf, RIPEMD160_BLOCKWORDS);
c06d4f ¤   ¤   RMDcompress(ctx->iv, ctx->key);
cda871 ¤   ¤   buf += RIPEMD160_BLOCKBYTES;
9d455e ¤   ¤   len -= RIPEMD160_BLOCKBYTES;
329371 ¤   }
aaaf5a
fa94e0 ¤   /* Handle any remaining bytes of data. */
624548 ¤   if (len)
cdfab4 ¤   ¤   memcpy(ctx->key, buf, len);
e6efe6 }
a2af5a
82af5a
caae74 /* Final wrapup - MD4 style padding on last block. */
05af5a
559c71 static void const *
b246e2 rmd160Final(void *priv)
ebbb36 {
c8e6ed ¤   struct RIPEMD160Context *ctx = (struct RIPEMD160Context *)priv;
86c7aa ¤   PGPByte *digest;
964ba4 ¤   int i;
7b2b16 ¤   PGPUInt32 t;
11af5a
a7634d ¤   RMDfinish(ctx->iv, (PGPByte *)ctx->key, ctx->bytesLo, ctx->bytesHi);
adaf5a
e7a1bb ¤   digest = (PGPByte *)ctx->iv;
4624b5 ¤   for (i = 0; i < RIPEMD160_HASHWORDS; i++) {
5d21b7 ¤   ¤   t = ctx->iv[i];
6d72ae ¤   ¤   digest[0] = (PGPByte)t;
e64a8f ¤   ¤   digest[1] = (PGPByte)(t >> 8);
e86009 ¤   ¤   digest[2] = (PGPByte)(t >> 16);
b940c8 ¤   ¤   digest[3] = (PGPByte)(t >> 24);
277beb ¤   ¤   digest += 4;
df9371 ¤   }
8d57b6 ¤   /* In case it's sensitive */
ea1339 /* XXX ··pgpClearMemory( ctx, sizeof(ctx)); */
89af5a
6c862e ¤   return (PGPByte const *)ctx->iv;
94efe6 }
0caf5a
2baf5a
d8af5a
ee38e5 /*
05ec9e ·* RIPEM OID is 1.3.36.3.2.1, from URL above.
1f7bbe ·* The rest of the format is stolen from MD5. ·Do we need the NULL
e2ae84 ·* in there?
02495d ·*/
1cb78e static PGPByte const RIPEMD160DERprefix[] = {
f5eef2 ¤   0x30, /* Universal, Constructed, Sequence */
76edbc ¤   0x21, /* Length 33 (bytes following) */
99bde9 ¤   ¤   0x30, /* Universal, Constructed, Sequence */
db3cab ¤   ¤   0x09, /* Length 9 */
556507 ¤   ¤   ¤   0x06, /* Universal, Primitive, object-identifier */
0f8859 ¤   ¤   ¤   0x05, /* Length 8 */
d05a3b ¤   ¤   ¤   ¤   43, /* 43 = ISO(1)*40 + 3 */
4345fc ¤   ¤   ¤   ¤   36,
4eece8 ¤   ¤   ¤   ¤   3,
adb634 ¤   ¤   ¤   ¤   2,
9d5950 ¤   ¤   ¤   ¤   1,
a2c238 ¤   ¤   ¤   0x05, /* Universal, Primitive, NULL */
99d131 ¤   ¤   ¤   0x00, /* Length 0 */
af6fe2 ¤   ¤   0x04, /* Universal, Primitive, Octet string */
2d06d0 ¤   ¤   0x14 /* Length 20 */
5e232f ¤   ¤   ¤   /* 20 RIPEMD-160 digest bytes go here */
fd82f7 };
abaf5a
a75e37 struct PGPHashVTBL const HashRIPEMD160 = {
22062e ¤   "RIPEMD160", kPGPHashAlgorithm_RIPEMD160,
deee33 ¤   RIPEMD160DERprefix, sizeof(RIPEMD160DERprefix),
c5f136 ¤   RIPEMD160_HASHBYTES,
3a4c28 ¤   sizeof(struct RIPEMD160Context),
45f9f5 ¤   sizeof(struct{char _a; struct RIPEMD160Context _b;}) -
--86d6 0003be2e7514010013a Page 8 of pgpRIPEMD160.c
9c49c5 ¤   ¤   sizeof(struct RIPEMD160Context),
f906dc ¤   rmd160Init, rmd160Update, rmd160Final
d082f7 };
c3af5a
63af5a
ec3e83 #if TESTMAIN
34af5a
0ed48f /* --------------------------- RMD160 Test code --------------------------- */
30feb2 #include <stdio.h>
314083 #include <stdlib.h>¤/* For exit() */
fa0a8b #include <time.h>
11af5a
7449fa /* Size of buffer for RMD160 speed test data */
e6af5a
de5275 #define TEST_BLOCK_SIZE¤( RIPEMD160_HASHBYTES * 100 )
99af5a
f1d673 /* Number of bytes of test data to process */
52af5a
847cb7 #define TEST_BYTES¤ 10000000L
7bca48 #define TEST_BLOCKS¤( TEST_BYTES / TEST_BLOCK_SIZE )
40af5a
6ede65 static char const *rmd160TestResults[] = {
c3cb4b ¤   "9C1185A5C5E9FC54612808977EE8F548B2258D31",¤¤   /* "" */
20a288 ¤   "0BDC9D2D256B3EE9DAAE347BE6F4DC835A467FFE",¤¤   /* "a" */
96aff2 ¤   "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC",¤¤   /* "abc" */
f3a6fe ¤   "5D0689EF49D2FAE572B881B123A85FFA21595F36",¤¤   /* "message digest" */
6d972a ¤   "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC",¤¤   /* "a..z" */
c67aef ¤   "12A053384A9C0C88E405A06C27DCF49ADA62EB2B",¤¤   /* "abcdbcde...nopq" */
c58be0 ¤   "B0E20B6E3116640286ED3A87A5713079B21F5189",¤¤   /* "A..Za..z0..9" */
0c7772 ¤   "9B752E45573D4B39F4DBD3323CAB82BF63326BFB",¤¤   /* 8 * "1234567890" */
6b9433 ¤   "52783243C1697BDBE16D37F97F68F08325DC1528",¤¤   /* 1,000,000 "a" */
9a9433 ¤   "52783243C1697BDBE16D37F97F68F08325DC1528",¤¤   /* 1,000,000 "a" */
6b4150 ¤   "52783243C1697BDBE16D37F97F68F08325DC1528" };¤  /* 1,000,000 "a" */
01af5a
94beb7 static int
9d7422 compareRMD160results(PGPByte const *hash, int level)
10bb36 {
ba97ea ¤   char buf[41];
474ba4 ¤   int i;
4eaf5a
9e94ee ¤   for (i = 0; i < RIPEMD160_HASHBYTES; i++)
ad4418 ¤   ¤   sprintf(buf+2*i, "%02X", hash[i]);
68af5a
f0a492 ¤   if (strcmp(buf, rmd160TestResults[level-1]) == 0) {
992031 ¤   ¤   printf("Test %d passed, result = %s\n", level, buf);
e6bbde ¤   ¤   return 0;
e9f037 ¤   } else {
040941 ¤   ¤   printf("Error in RMD160 implementation: Test %d failed\n", level);
c6282d ¤   ¤   printf(" ·Result = %s\n", buf);
2ff197 ¤   ¤   printf("Expected = %s\n", rmd160TestResults[level-1]);
7d043c ¤   ¤   return -1;
389371 ¤   }
8befe6 }
ceaf5a
fdaf5a
0e4d2f int
397f68 main(void)
7ebb36 {
7feb8d ¤   struct RIPEMD160Context rmd160;
6f6b91 ¤   PGPByte data[TEST_BLOCK_SIZE];
c3e578 ¤   PGPByte const *hash;
6c817a ¤   clock_t ticks;
86a83e ¤   long i;
d5af5a
02d8af ¤   /*
08285b ¤   ·* Test output data, based on URL above.
71a4e3 ¤   ·*/
95074e ¤   rmd160Init(&rmd160);
080e9b ¤   rmd160Update(&rmd160, (PGPByte *)"", 0);
dbbe67 ¤   hash = rmd160Final(&rmd160);
f2f639 ¤   if (compareRMD160results(hash, 1) < 0)
3bb54f ¤   ¤   exit (-1);
--36f4 000d494b5724010013a Page 9 of pgpRIPEMD160.c
e0af5a
cd074e ¤   rmd160Init(&rmd160);
79d094 ¤   rmd160Update(&rmd160, (PGPByte *)"a", 1);
37be67 ¤   hash = rmd160Final(&rmd160);
5f7ce9 ¤   if (compareRMD160results(hash, 2) < 0)
e3b54f ¤   ¤   exit (-1);
d6af5a
c1074e ¤   rmd160Init(&rmd160);
f27ff7 ¤   rmd160Update(&rmd160, (PGPByte *)"abc", 3);
9cbe67 ¤   hash = rmd160Final(&rmd160);
7efd56 ¤   if (compareRMD160results(hash, 3) < 0)
66b54f ¤   ¤   exit (-1);
f6af5a
e2074e ¤   rmd160Init(&rmd160);
bb4a4e ¤   rmd160Update(&rmd160, (PGPByte *)"message digest", 14);
c8be67 ¤   hash = rmd160Final(&rmd160);
dd6158 ¤   if (compareRMD160results(hash, 4) < 0)
deb54f ¤   ¤   exit (-1);
09af5a
55074e ¤   rmd160Init(&rmd160);
99438b ¤   rmd160Update(&rmd160, (PGPByte *)"abcdefghijklmnopqrstuvwxyz", 26);
a5be67 ¤   hash = rmd160Final(&rmd160);
45e0e7 ¤   if (compareRMD160results(hash, 5) < 0)
88b54f ¤   ¤   exit (-1);
05af5a
f0074e ¤   rmd160Init(&rmd160);
1f580c ¤   rmd160Update(&rmd160, (PGPByte *)"abcdbcdecdefdefgefghfghighijhijkijkl\
e2457a jklmklmnlmnomnopnopq", 56);
d4be67 ¤   hash = rmd160Final(&rmd160);
b76a37 ¤   if (compareRMD160results(hash, 6) < 0)
76b54f ¤   ¤   exit (-1);
a5af5a
30074e ¤   rmd160Init(&rmd160);
ae581a ¤   rmd160Update(&rmd160, (PGPByte *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
3e42ee abcdefghijklmnopqrstuvwxyz0123456789", 62);
88be67 ¤   hash = rmd160Final(&rmd160);
84eb88 ¤   if (compareRMD160results(hash, 7) < 0)
38b54f ¤   ¤   exit (-1);
33af5a
8e074e ¤   rmd160Init(&rmd160);
365d66 ¤   rmd160Update(&rmd160, (PGPByte *)"123456789012345678901234567890\
b8a35f 12345678901234567890123456789012345678901234567890", 80);
38be67 ¤   hash = rmd160Final(&rmd160);
565a3a ¤   if (compareRMD160results(hash, 8) < 0)
bfb54f ¤   ¤   exit (-1);
2caf5a
ef2ec3 ¤   /* 1,000,000 bytes of ASCII 'a' (0x61), by 64's */
b7074e ¤   rmd160Init(&rmd160);
bed1f2 ¤   for (i = 0; i < 15625; i++)
bdecaa ¤   ¤   rmd160Update(&rmd160, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
81246a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64);
f6be67 ¤   hash = rmd160Final(&rmd160);
2ddb85 ¤   if (compareRMD160results(hash, 9) < 0)
d9b54f ¤   ¤   exit (-1);
0baf5a
c7a7c8 ¤   /* 1,000,000 bytes of ASCII 'a' (0x61), by 25's */
c2074e ¤   rmd160Init(&rmd160);
24be5c ¤   for (i = 0; i < 40000; i++)
7e71c9 ¤   ¤   rmd160Update(&rmd160, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa", 25);
d0be67 ¤   hash = rmd160Final(&rmd160);
e8d6e9 ¤   if (compareRMD160results(hash, 10) < 0)
4cb54f ¤   ¤   exit (-1);
7caf5a
2dad39 ¤   /* 1,000,000 bytes of ASCII 'a' (0x61), by 125's */
f8074e ¤   rmd160Init(&rmd160);
36eb47 ¤   for (i = 0; i < 8000; i++)
52ecaa ¤   ¤   rmd160Update(&rmd160, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
8ac1b0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
168064 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 125);
5ebe67 ¤   hash = rmd160Final(&rmd160);
fd5756 ¤   if (compareRMD160results(hash, 11) < 0)
d4b54f ¤   ¤   exit (-1);
--a12d 001fa65d16d4010013a Page 10 of pgpRIPEMD160.c
e0af5a
16fb6d ¤   /* Now perform time trial, generating MD for 10MB of data. ·First,
b1376b ¤   ···initialize the test data */
7ec5f1 ¤   pgpClearMemory( data, ·TEST_BLOCK_SIZE);
85af5a
825c54 ¤   /* Get start time */
6a8ccc ¤   printf("RMD160 time trial. ·Processing %ld characters...\n", TEST_BYTES);
cf6a0f ¤   ticks = clock();
43af5a
6031af ¤   /* Calculate RMD160 message digest in TEST_BLOCK_SIZE byte blocks */
a0074e ¤   rmd160Init(&rmd160);
3046e0 ¤   for (i = TEST_BLOCKS; i > 0; i--)
73493c ¤   ¤   rmd160Update(&rmd160, data, TEST_BLOCK_SIZE);
09be67 ¤   hash = rmd160Final(&rmd160);
ecaf5a
0a0c81 ¤   /* Get finish time and print difference */
4d30c3 ¤   ticks = clock() - ticks;
63320e ¤   printf("Ticks to process test input: %lu\n", (unsigned long)ticks);
adaf5a
b53e6b ¤   return 0;
4defe6 }
fadb0e #endif /* Test driver */
--f7e3 00105e086c84010013b Page 1 of pgpRIPEMD160.h
bc38e5 /*
214ee7 ·* pgpRIPEMD160.h -- RIPEMD-160 message digest
72775e ·*
81e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
5e2979 ·* You should not be using these functions in an application.
02775e ·*
a754c5 ·* $Id: pgpRIPEMD160.h,v 1.2 1997/06/13 01:53:00 lloyd Exp $
74495d ·*/
67af5a
f6803a #ifndef Included_pgpRIPEMD160_h
c64559 #define Included_pgpRIPEMD160_h
e9af5a
0a5417 #include "pgpHashPriv.h"
57af5a
5299c6 PGP_BEGIN_C_DECLARATIONS
4aaf5a
ee288f extern PGPHashVTBL const HashRIPEMD160;
6baf5a
db1254 PGP_END_C_DECLARATIONS
99af5a
05769a #endif /* !Included_pgpRIPEMD160_h */
--9458 00089982af14010013c Page 1 of pgpSHA.c
bc38e5 /*
e562c9 ·* pgpSHA.c - NIST Secure Hash Algorithm, FIPS PUB 180 and 180.1.
47e2ff ·* The algorithm is by spook(s) unknown at the U.S. National Security Agency.
fe775e ·*
651f5f ·* Written 2 September 1992, Peter C. Gutmann.
4b7912 ·* This implementation placed in the public domain.
2e775e ·*
eecf7e ·* Modified 1 June 1993, Colin Plumb.
c63d9d ·* Modified for the new SHS based on Peter Gutmann's work,
e2e2dc ·* 18 July 1994, Colin Plumb.
fb775e ·*
53a659 ·* Renamed to SHA and comments updated a bit 1 November 1995, Colin Plumb.
d67534 ·* These modifications placed in the public domain.
898feb ·* Hacked on some more for PGP 3, December 1995, Colin Plumb.
565e19 ·* You probably don't *want* these modifications.
b9775e ·*
011f9a ·* Comments to pgut1@cs.aukuni.ac.nz
7a775e ·*
ecc179 ·* $Id: pgpSHA.c,v 1.15 1997/10/14 01:48:23 heller Exp $
f5495d ·*/
72af5a
a4e2ff #include "pgpConfig.h"
9eaf5a
29324c #include <string.h>
94af5a
8c9f72 #include "pgpHash.h"
7999fe #include "pgpSHA.h"
5fd11f #include "pgpUsuals.h"
7f0d08 #include "pgpMem.h"
d3a146 #include "pgpDebug.h"
4aaf5a
5638e5 /*
581e42 ·* Define to 1 for FIPS 180.1 version (with extra rotate in prescheduling),
3a4a84 ·* 0 for FIPS 180 version (with the mysterious "weakness" that the NSA
a001bf ·* isn't talking about).
cb495d ·*/
429775 #define SHA_VERSION 1
0caf5a
d1af5a
3138e5 /*
dd99c2 ·* Shuffle the bytes into big-endian order within words, as per the
7fceb4 ·* SHA spec.
7e495d ·*/
2f2978 static void
4f7b74 shaByteSwap(PGPUInt32 *dest, PGPByte const *src, unsigned words)
d6bb36 {
6343ab ¤   do {
3f8938 ¤   ¤   *dest++ = (PGPUInt32)((unsigned)src[0] << 8 | src[1]) << 16 |
a89e1f ¤   ¤   ··················((unsigned)src[2] << 8 | src[3]);
17aa48 ¤   ¤   src += 4;
35c244 ¤   } while (--words);
81efe6 }
c8af5a
67a78c /* Initialize the SHA values */
30af5a
202978 static void
3b0ed5 shaInit(void *priv)
dcbb36 {
067cf0 ¤   SHAContext *ctx = (SHAContext *)priv;
82af5a
7bf4a8 ¤   /* Set the h-vars to their initial values */
4184d8 ¤   ctx->iv[0] = 0x67452301;
d8022e ¤   ctx->iv[1] = 0xEFCDAB89;
824eae ¤   ctx->iv[2] = 0x98BADCFE;
cf35e1 ¤   ctx->iv[3] = 0x10325476;
df831c ¤   ctx->iv[4] = 0xC3D2E1F0;
93af5a
b4f91f ¤   /* Initialise bit count */
1bb757 #ifdef HAVE64
62f0a5 ¤   ctx->bytes = 0;
c9db21 #else
89b288 ¤   ctx->bytesHi = 0;
--43ec 000709428254010013c Page 2 of pgpSHA.c
f0fc9b ¤   ctx->bytesLo = 0;
057454 #endif
dfefe6 }
57af5a
7238e5 /*
59c9c4 ·* The SHA f()-functions. ·The f1 and f3 functions can be optimized to
9a4ec5 ·* save one boolean operation each - thanks to Rich Schroeppel,
0249eb ·* rcs@cs.arizona.edu for discovering this.
16ebcb ·* The f3 function can be modified to use an addition to combine the
81143c ·* two halves rather than OR, allowing more opportunity for using
54b86a ·* associativity in optimization. ·(Colin Plumb)
2a775e ·*
dcefce ·* Note that it may be necessary to add parentheses to these macros
22a878 ·* if they are to be called with expressions as arguments.
3a495d ·*/
c709f2 /* f1 is a bit-select function. ·If (x) then y else z */
b2d008 /*#define f1(x,y,z)¤( (x & y) | (~x & z) )¤ ¤   // Rounds ·0-19 */
d44980 #define f1(x,y,z)¤  ( z ^ (x & (y ^ z) ) )¤ ¤   /* Rounds ·0-19 */
7f089e #define f2(x,y,z)¤  ( x ^ y ^ z )¤  ¤   ¤   /* Rounds 20-39 */
1c2b56 /* f3 is a majority function */
0e0c08 /*#define f3(x,y,z)¤( (x & y) | (y & z) | (z & x) )¤// Rounds 40-59 */
ff8d9d /*#define f3(x,y,z)¤( (x & y) | (z & (x | y) ) )¤   // Rounds 40-59 */
8d681a #define f3(x,y,z)¤  ( (x & y) + (z & (x ^ y) ) )¤   /* Rounds 40-59 */
fcc810 #define f4(x,y,z)¤  ( x ^ y ^ z )¤  ¤   ¤   /* Rounds 60-79 */
40af5a
4adf87 /* The SHA Mysterious Constants. */
e7e7c0 #define K2¤ 0x5A827999L¤/* Rounds ·0-19 - floor(sqrt(2) * 2^30) */
7da819 #define K3¤ 0x6ED9EBA1L¤/* Rounds 20-39 - floor(sqrt(3) * 2^30) */
d50f56 #define K5¤ 0x8F1BBCDCL¤/* Rounds 40-59 - floor(sqrt(5) * 2^30) */
aa8ef5 #define K10¤0xCA62C1D6L¤/* Rounds 60-79 - floor(sqrt(10) * 2^30) */
77695e /* I wonder why not use K7=0xA953FD4E, K11=0xD443949F or K13=0xE6C15A23 */
e7af5a
999ff0 /* 32-bit rotate left - kludged with shifts */
1faf5a
7165a8 #define ROTL(n,X) ·( (X << n) | (X >> (32-n)) )
c4af5a
6b38e5 /*
c41242 ·* The initial expanding function
87775e ·*
7dc2ae ·* The hash function is defined over an 80-word expanded input array W,
04edf9 ·* where the first 16 are copies of the input data, and the remaining 64
4161e3 ·* are defined by W[i] = W[i-16] ^ W[i-14] ^ W[i-8] ^ W[i-3]. ·This
ffc422 ·* implementation generates these values on the fly in a circular buffer.
6e775e ·*
525984 ·* The new "corrected" FIPS 180.1 added a 1-bit left rotate to this
cb4f23 ·* computation of W[i].
1c775e ·*
7fdbab ·* The expandx() version doesn't write the result back, which can be
c1223c ·* used for the last three rounds since those outputs are never used.
e5495d ·*/
84af5a
26a375 #if SHA_VERSION¤/* FIPS 180.1 */
7a39f5 #define expandx(W,i) (t = W[i&15] ^ W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15], \
63f86a ······················ROTL(1, t))
a3da29 #define expand(W,i) (W[i&15] = expandx(W,i))
89ab42 #else¤  /* Old FIPS 180 */
62a303 #define expandx(W,i) (W[i&15] ^ W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15])
c35564 #define expand(W,i) (W[i&15] ^= W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15])
d27454 #endif
36af5a
d838e5 /*
3c8fcd ·* The prototype SHA sub-round
13775e ·*
c112b6 ·* The fundamental sub-round is
4a7cfa ·* a' = e + ROTL(5,a) + f(b, c, d) + k + data;
6fb77b ·* b' = a;
aa0711 ·* c' = ROTL(30,b);
aa1f72 ·* d' = c;
c412c8 ·* e' = d;
0bec6b ·* ... but this is implemented by unrolling the loop 5 times and renaming
9289f6 ·* the variables (e,a,b,c,d) = (a',b',c',d',e') each iteration.
70495d ·*/
--96ec 000438838624010013c Page 3 of pgpSHA.c
8f0d73 #define subRound(a, b, c, d, e, f, k, data) \
6a3801 ¤   ( e += ROTL(5,a) + f(b, c, d) + k + data, b = ROTL(30, b) )
b638e5 /*
daf21c ·* The above code is replicated 20 times for each of the 4 functions,
5e880e ·* using the next 20 values from the W[] array for "data" each time.
3b495d ·*/
30af5a
7a38e5 /*
657e9a ·* Perform the SHA transformation. ·Note that this code, like MD5, seems to
7797be ·* break some optimizing compilers due to the complexity of the expressions
4ce0bd ·* and the size of the basic block. ·It may be necessary to split it into
d9efbb ·* sections, e.g. based on the four subrounds
3a775e ·*
2372f0 ·* Note that this corrupts the sha->key area.
806af4 ·* NOTE This is not declared as static because pgpRndPool.c references it.
8d1d09 ·* (Sorry for that modularity violation.)
e8495d ·*/
11d7d3 void pgpSHATransform(PGPUInt32 *block, PGPUInt32 *key);
95314a void
e3444c pgpSHATransform(PGPUInt32 *block, PGPUInt32 *key)
44bb36 {
77cdd0 ¤   register PGPUInt32 A, B, C, D, E;
3be139 #if SHA_VERSION
0b2d5c ¤   register PGPUInt32 t;
4a7454 #endif
6daf5a
c4fb15 ¤   /* Set up first buffer */
9a9434 ¤   A = block[0];
780bb1 ¤   B = block[1];
a65096 ¤   C = block[2];
c63caa ¤   D = block[3];
f11561 ¤   E = block[4];
7faf5a
2e9ae2 ¤   /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
1dcc8d ¤   subRound( A, B, C, D, E, f1, K2, key[ 0] );
adbaac ¤   subRound( E, A, B, C, D, f1, K2, key[ 1] );
b2f307 ¤   subRound( D, E, A, B, C, f1, K2, key[ 2] );
3a0a81 ¤   subRound( C, D, E, A, B, f1, K2, key[ 3] );
4f2027 ¤   subRound( B, C, D, E, A, f1, K2, key[ 4] );
53d80a ¤   subRound( A, B, C, D, E, f1, K2, key[ 5] );
8ea67d ¤   subRound( E, A, B, C, D, f1, K2, key[ 6] );
21e780 ¤   subRound( D, E, A, B, C, f1, K2, key[ 7] );
d727a4 ¤   subRound( C, D, E, A, B, f1, K2, key[ 8] );
cb15f8 ¤   subRound( B, C, D, E, A, f1, K2, key[ 9] );
fbe691 ¤   subRound( A, B, C, D, E, f1, K2, key[10] );
cf90b0 ¤   subRound( E, A, B, C, D, f1, K2, key[11] );
a0d91b ¤   subRound( D, E, A, B, C, f1, K2, key[12] );
a1209d ¤   subRound( C, D, E, A, B, f1, K2, key[13] );
190a3b ¤   subRound( B, C, D, E, A, f1, K2, key[14] );
57f216 ¤   subRound( A, B, C, D, E, f1, K2, key[15] );
cda499 ¤   subRound( E, A, B, C, D, f1, K2, expand(key, 16) );
ab7fcd ¤   subRound( D, E, A, B, C, f1, K2, expand(key, 17) );
fe3c95 ¤   subRound( C, D, E, A, B, f1, K2, expand(key, 18) );
11a24e ¤   subRound( B, C, D, E, A, f1, K2, expand(key, 19) );
63af5a
c5e295 ¤   subRound( A, B, C, D, E, f2, K3, expand(key, 20) );
30e69a ¤   subRound( E, A, B, C, D, f2, K3, expand(key, 21) );
f23598 ¤   subRound( D, E, A, B, C, f2, K3, expand(key, 22) );
1d4f62 ¤   subRound( C, D, E, A, B, f2, K3, expand(key, 23) );
bdc943 ¤   subRound( B, C, D, E, A, f2, K3, expand(key, 24) );
e8f612 ¤   subRound( A, B, C, D, E, f2, K3, expand(key, 25) );
a9fa4b ¤   subRound( E, A, B, C, D, f2, K3, expand(key, 26) );
4b211f ¤   subRound( D, E, A, B, C, f2, K3, expand(key, 27) );
556247 ¤   subRound( C, D, E, A, B, f2, K3, expand(key, 28) );
e0fc9c ¤   subRound( B, C, D, E, A, f2, K3, expand(key, 29) );
f27d40 ¤   subRound( A, B, C, D, E, f2, K3, expand(key, 30) );
9e794f ¤   subRound( E, A, B, C, D, f2, K3, expand(key, 31) );
b2aa4d ¤   subRound( D, E, A, B, C, f2, K3, expand(key, 32) );
7ad0b7 ¤   subRound( C, D, E, A, B, f2, K3, expand(key, 33) );
965696 ¤   subRound( B, C, D, E, A, f2, K3, expand(key, 34) );
e769c7 ¤   subRound( A, B, C, D, E, f2, K3, expand(key, 35) );
43659e ¤   subRound( E, A, B, C, D, f2, K3, expand(key, 36) );
--4adf 0009d0f328f4010013c Page 4 of pgpSHA.c
89beca ¤   subRound( D, E, A, B, C, f2, K3, expand(key, 37) );
80fd92 ¤   subRound( C, D, E, A, B, f2, K3, expand(key, 38) );
6d6349 ¤   subRound( B, C, D, E, A, f2, K3, expand(key, 39) );
14af5a
7098f5 ¤   subRound( A, B, C, D, E, f3, K5, expand(key, 40) );
fe9cfa ¤   subRound( E, A, B, C, D, f3, K5, expand(key, 41) );
bf4ff8 ¤   subRound( D, E, A, B, C, f3, K5, expand(key, 42) );
ea3502 ¤   subRound( C, D, E, A, B, f3, K5, expand(key, 43) );
ddb323 ¤   subRound( B, C, D, E, A, f3, K5, expand(key, 44) );
d58c72 ¤   subRound( A, B, C, D, E, f3, K5, expand(key, 45) );
d8802b ¤   subRound( E, A, B, C, D, f3, K5, expand(key, 46) );
f55b7f ¤   subRound( D, E, A, B, C, f3, K5, expand(key, 47) );
f21827 ¤   subRound( C, D, E, A, B, f3, K5, expand(key, 48) );
9b86fc ¤   subRound( B, C, D, E, A, f3, K5, expand(key, 49) );
f20720 ¤   subRound( A, B, C, D, E, f3, K5, expand(key, 50) );
d4032f ¤   subRound( E, A, B, C, D, f3, K5, expand(key, 51) );
cad02d ¤   subRound( D, E, A, B, C, f3, K5, expand(key, 52) );
1faad7 ¤   subRound( C, D, E, A, B, f3, K5, expand(key, 53) );
eb2cf6 ¤   subRound( B, C, D, E, A, f3, K5, expand(key, 54) );
1e13a7 ¤   subRound( A, B, C, D, E, f3, K5, expand(key, 55) );
661ffe ¤   subRound( E, A, B, C, D, f3, K5, expand(key, 56) );
c3c4aa ¤   subRound( D, E, A, B, C, f3, K5, expand(key, 57) );
fc87f2 ¤   subRound( C, D, E, A, B, f3, K5, expand(key, 58) );
ca1929 ¤   subRound( B, C, D, E, A, f3, K5, expand(key, 59) );
e7af5a
255533 ¤   subRound( A, B, C, D, E, f4, K10, expand(key, 60) );
c4363e ¤   subRound( E, A, B, C, D, f4, K10, expand(key, 61) );
29b1ec ¤   subRound( D, E, A, B, C, f4, K10, expand(key, 62) );
0472bd ¤   subRound( C, D, E, A, B, f4, K10, expand(key, 63) );
3c9979 ¤   subRound( B, C, D, E, A, f4, K10, expand(key, 64) );
7e41b4 ¤   subRound( A, B, C, D, E, f4, K10, expand(key, 65) );
c42aef ¤   subRound( E, A, B, C, D, f4, K10, expand(key, 66) );
32a56b ¤   subRound( D, E, A, B, C, f4, K10, expand(key, 67) );
d45f98 ¤   subRound( C, D, E, A, B, f4, K10, expand(key, 68) );
33aca6 ¤   subRound( B, C, D, E, A, f4, K10, expand(key, 69) );
afcae6 ¤   subRound( A, B, C, D, E, f4, K10, expand(key, 70) );
83a9eb ¤   subRound( E, A, B, C, D, f4, K10, expand(key, 71) );
b02e39 ¤   subRound( D, E, A, B, C, f4, K10, expand(key, 72) );
89ed68 ¤   subRound( C, D, E, A, B, f4, K10, expand(key, 73) );
b606ac ¤   subRound( B, C, D, E, A, f4, K10, expand(key, 74) );
00de61 ¤   subRound( A, B, C, D, E, f4, K10, expand(key, 75) );
1eb53a ¤   subRound( E, A, B, C, D, f4, K10, expand(key, 76) );
6f4199 ¤   subRound( D, E, A, B, C, f4, K10, expandx(key, 77) );
6aa00a ¤   subRound( C, D, E, A, B, f4, K10, expandx(key, 78) );
efe3fa ¤   subRound( B, C, D, E, A, f4, K10, expandx(key, 79) );
2aaf5a
9933ee ¤   /* Build message digest */
f374be ¤   block[0] += A;
49d627 ¤   block[1] += B;
d45afc ¤   block[2] += C;
a69b04 ¤   block[3] += D;
f9283a ¤   block[4] += E;
f3efe6 }
13af5a
5a084d /* Update SHA for a block of data. */
eaaf5a
ce2978 static void
a81fdd shaUpdate(void *priv, void const *bufIn, PGPSize len)
64bb36 {
b47cf0 ¤   SHAContext *ctx = (SHAContext *)priv;
91e130 ¤   PGPByte *buf = (PGPByte *) bufIn;
8d743f ¤   unsigned i;
9aaf5a
2b7f74 ¤   /* Update bitcount */
cdaf5a
ecb757 #ifdef HAVE64
8df427 ¤   i = (unsigned)ctx->bytes % SHA_BLOCKBYTES;
fd5338 ¤   ctx->bytes += len;
11db21 #else
0c30a7 ¤   PGPUInt32 t = ctx->bytesLo;
676738 ¤   if ( ( ctx->bytesLo = t + len ) < t )
9df8d4 ¤   ¤   ctx->bytesHi++;¤/* Carry from low to high */
--5f67 000b0e6c4544010013c Page 5 of pgpSHA.c
e0af5a
3bc1b2 ¤   i = (unsigned)t % SHA_BLOCKBYTES; /* Bytes already in ctx->key */
527454 #endif
c8af5a
59a5aa ¤   /* i is always less than SHA_BLOCKBYTES. */
688eb7 ¤   if (SHA_BLOCKBYTES-i > len) {
8d67e3 ¤   ¤   memcpy((PGPByte *)ctx->key + i, buf, len);
4799bf ¤   ¤   return;
7d9371 ¤   }
26af5a
7ac265 ¤   if (i) {¤   /* First chunk is an odd size */
e7098b ¤   ¤   memcpy((PGPByte *)ctx->key + i, buf, SHA_BLOCKBYTES - i);
d94e06 ¤   ¤   shaByteSwap(ctx->key, (PGPByte *)ctx->key, SHA_BLOCKWORDS);
ef1ba2 ¤   ¤   pgpSHATransform(ctx->iv, ctx->key);
0837d8 ¤   ¤   buf += SHA_BLOCKBYTES-i;
8e4c6b ¤   ¤   len -= SHA_BLOCKBYTES-i;
b79371 ¤   }
7baf5a
ec0834 ¤   /* Process data in 64-byte chunks */
0a1649 ¤   while (len >= SHA_BLOCKBYTES) {
7ce60a ¤   ¤   shaByteSwap(ctx->key, buf, SHA_BLOCKWORDS);
161ba2 ¤   ¤   pgpSHATransform(ctx->iv, ctx->key);
9f8a0f ¤   ¤   buf += SHA_BLOCKBYTES;
9bcd08 ¤   ¤   len -= SHA_BLOCKBYTES;
af9371 ¤   }
54af5a
7994e0 ¤   /* Handle any remaining bytes of data. */
9b4548 ¤   if (len)
fffab4 ¤   ¤   memcpy(ctx->key, buf, len);
54efe6 }
61af5a
1438e5 /*
ec65d5 ·* Final wrapup - pad to 64-byte boundary with the bit pattern·
9e12ac ·* 1 0* (64-bit count of bits processed, MSB-first)
1a495d ·*/
489c71 static void const *
7926f0 shaFinal(void *priv)
e2bb36 {
bd7cf0 ¤   SHAContext *ctx = (SHAContext *)priv;
70c7aa ¤   PGPByte *digest;
a6a0a9 #if HAVE64
d38ed2 ¤   unsigned i = (unsigned)ctx->bytes % SHA_BLOCKBYTES;
6cdb21 #else
9bc93b ¤   unsigned i = (unsigned)ctx->bytesLo % SHA_BLOCKBYTES;
657454 #endif
89d219 ¤   PGPByte *p = (PGPByte *)ctx->key + i;¤  /* First unused byte */
eb2b16 ¤   PGPUInt32 t;
58af5a
e8b051 ¤   /* Set the first char of padding to 0x80. ·There is always room. */
bcc755 ¤   *p++ = 0x80;
1faf5a
80aeaf ¤   /* Bytes of padding needed to make 64 bytes (0..63) */
5eb72d ¤   i = SHA_BLOCKBYTES - 1 - i;
d6af5a
0b5a02 ¤   if (i < 8) {¤   /* Padding forces an extra block */
ff577d ¤   ¤   pgpClearMemory( p, ·i);
0308a0 ¤   ¤   shaByteSwap(ctx->key, (PGPByte *)ctx->key, 16);
b81ba2 ¤   ¤   pgpSHATransform(ctx->iv, ctx->key);
8c53a0 ¤   ¤   p = (PGPByte *)ctx->key;
74b258 ¤   ¤   i = 64;
fe9371 ¤   }
4f485c ¤   pgpClearMemory( p, ·i-8);
fc647a ¤   shaByteSwap(ctx->key, (PGPByte *)ctx->key, 14);
deaf5a
3252ad ¤   /* Append length in bits and transform */
34a0a9 #if HAVE64
f91431 ¤   ctx->key[14] = (PGPUInt32)(ctx->bytes >> 29);
7786a8 ¤   ctx->key[15] = (PGPUInt32)ctx->bytes << 3;
95db21 #else
43bfc8 ¤   ctx->key[14] = ctx->bytesHi << 3 | ctx->bytesLo >> 29;
6f1852 ¤   ctx->key[15] = ctx->bytesLo << 3;
b07454 #endif
--e9f9 000a7ab92874010013c Page 6 of pgpSHA.c
4a93c4 ¤   pgpSHATransform(ctx->iv, ctx->key);
ddaf5a
83a1bb ¤   digest = (PGPByte *)ctx->iv;
3ee5de ¤   for (i = 0; i < SHA_HASHWORDS; i++) {
fa21b7 ¤   ¤   t = ctx->iv[i];
c74c45 ¤   ¤   digest[0] = (PGPByte)(t >> 24);
656c84 ¤   ¤   digest[1] = (PGPByte)(t >> 16);
b8a743 ¤   ¤   digest[2] = (PGPByte)(t >> 8);
0242bf ¤   ¤   digest[3] = (PGPByte)t;
997beb ¤   ¤   digest += 4;
139371 ¤   }
4c57b6 ¤   /* In case it's sensitive */
0365bd /* XXX¤ pgpClearMemory( ctx, ·sizeof(ctx)); */
7b862e ¤   return (PGPByte const *)ctx->iv;
24efe6 }
eeaf5a
87b177 #if 0
4a38e5 /*
73c161 ·* Nobody knows an SHA format, so we make one up out of the
96b9eb ·* context-dependent tag space.
a9495d ·*/
f29363 static PGPByte const SHADERprefix[] = {
e10abd ¤   0x82,¤  /* context-specific [2], primitive */
72fb19 ¤   0x14¤   /* Length 20 */
083f28 ¤   ¤   /* 20 SHA digest bytes go here */
f682f7 };
aedb21 #else
af38e5 /*
3b3ac2 ·* Actually, there is one. ·SHA.1 has an OID of 1.3.14.3.2.26
70f0ac ·* (From the 1994 Open Systems Environment Implementor's Workshop (OIW))
6884a1 ·* The rest of the format is stolen from MD5. ·Do we need the @#$@$
6649fe ·* NULL in there?
7d495d ·*/
8d029c PGPByte const SHADERprefix[] = {
3deef2 ¤   0x30, /* Universal, Constructed, Sequence */
1fedbc ¤   0x21, /* Length 33 (bytes following) */
b3bde9 ¤   ¤   0x30, /* Universal, Constructed, Sequence */
f43cab ¤   ¤   0x09, /* Length 9 */
186507 ¤   ¤   ¤   0x06, /* Universal, Primitive, object-identifier */
368859 ¤   ¤   ¤   0x05, /* Length 8 */
df5a3b ¤   ¤   ¤   ¤   43, /* 43 = ISO(1)*40 + 3 */
f8c932 ¤   ¤   ¤   ¤   14,
d3ece8 ¤   ¤   ¤   ¤   3,
0fb634 ¤   ¤   ¤   ¤   2,
065947 ¤   ¤   ¤   ¤   26,
9fc238 ¤   ¤   ¤   0x05, /* Universal, Primitive, NULL */
f4d131 ¤   ¤   ¤   0x00, /* Length 0 */
786fe2 ¤   ¤   0x04, /* Universal, Primitive, Octet string */
9c06d0 ¤   ¤   0x14 /* Length 20 */
8ccae0 ¤   ¤   ¤   /* 20 SHA.1 digest bytes go here */
7f82f7 };
c07454 #endif
2eaf5a
b50eaa PGPHashVTBL const HashSHA = {
8a92ff ¤   "SHA1", kPGPHashAlgorithm_SHA,
44a7c2 ¤   SHADERprefix, sizeof(SHADERprefix),
7b748a ¤   SHA_HASHBYTES,
e9df51 ¤   sizeof(SHAContext),
dec6e9 ¤   sizeof(struct{char _a; SHAContext _b;}) -
8a2934 ¤   ¤   sizeof(SHAContext),
50e7ec ¤   shaInit, shaUpdate, shaFinal
0c82f7 };
6faf5a
bb3e83 #if TESTMAIN
e4af5a
883fd5 /* ----------------------------- SHA Test code --------------------------- */
ebfeb2 #include <stdio.h>
614083 #include <stdlib.h>¤/* For exit() */
a20a8b #include <time.h>
2baf5a
ccc2fc /* Size of buffer for SHA speed test data */
a7af5a
--ea92 000a72b56d64010013c Page 7 of pgpSHA.c
fc8abf #define TEST_BLOCK_SIZE¤( SHA_HASHBYTES * 100 )
34af5a
7ad673 /* Number of bytes of test data to process */
52af5a
1b7cb7 #define TEST_BYTES¤ 10000000L
9cca48 #define TEST_BLOCKS¤( TEST_BYTES / TEST_BLOCK_SIZE )
acaf5a
36e139 #if SHA_VERSION
8e83f4 static char const *shaTestResults[] = {
2971ec ¤   "A9993E364706816ABA3E25717850C26C9CD0D89D",
a26657 ¤   "84983E441C3BD26EBAAE4AA1F95129E5E54670F1",
cf15ac ¤   "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F",
1f15ac ¤   "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F",
ec27ca ¤   "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" };
72db21 #else
7183f4 static char const *shaTestResults[] = {
009f77 ¤   "0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880",
339b7e ¤   "D2516EE1ACFA5BAF33DFC1C471E438449EF134C8",
ba24b3 ¤   "3232AFFA48628A26653B5AAA44541FD90D690603",
6224b3 ¤   "3232AFFA48628A26653B5AAA44541FD90D690603",
791199 ¤   "3232AFFA48628A26653B5AAA44541FD90D690603" };
357454 #endif
f2af5a
0abeb7 static int
b1539a compareSHAresults(PGPByte const *hash, int level)
95bb36 {
ae97ea ¤   char buf[41];
9f4ba4 ¤   int i;
39af5a
a8ce63 ¤   for (i = 0; i < SHA_HASHBYTES; i++)
974418 ¤   ¤   sprintf(buf+2*i, "%02X", hash[i]);
c6af5a
ebdbd1 ¤   if (strcmp(buf, shaTestResults[level-1]) == 0) {
f12031 ¤   ¤   printf("Test %d passed, result = %s\n", level, buf);
72bbde ¤   ¤   return 0;
79f037 ¤   } else {
01dc20 ¤   ¤   printf("Error in SHA implementation: Test %d failed\n", level);
85282d ¤   ¤   printf(" ·Result = %s\n", buf);
5a81ff ¤   ¤   printf("Expected = %s\n", shaTestResults[level-1]);
f0043c ¤   ¤   return -1;
fc9371 ¤   }
70efe6 }
21af5a
c5af5a
4e4d2f int
207f68 main(void)
b5bb36 {
b746d2 ¤   SHAContext sha;
cb6b91 ¤   PGPByte data[TEST_BLOCK_SIZE];
49341c ¤   byte const *¤   hash;
e4817a ¤   clock_t ticks;
ffa83e ¤   long i;
c2af5a
5bd8af ¤   /*
a482b2 ¤   ·* Test output data (these are the only test data given in the
8d08ad ¤   ·* Secure Hash Standard document, but chances are if it works
cac526 ¤   ·* for this it'll work for anything)
c8a4e3 ¤   ·*/
8c361a ¤   shaInit(&sha);
f0bc7f ¤   shaUpdate(&sha, (PGPByte *)"abc", 3);
825e80 ¤   hash¤   = shaFinal(&sha);
5d380d ¤   if (compareSHAresults(hash, 1) < 0)
f6b54f ¤   ¤   exit (-1);
c6af5a
cb361a ¤   shaInit(&sha);
7588e8 ¤   shaUpdate(&sha, (PGPByte *)"abcdbcdecdefdefgefghfghighijhijki\
493e55 jkljklmklmnlmnomnopnopq", 56);
ba5e80 ¤   hash¤   = shaFinal(&sha);
7bb2dd ¤   if (compareSHAresults(hash, 2) < 0)
29b54f ¤   ¤   exit (-1);
56af5a
a72ec3 ¤   /* 1,000,000 bytes of ASCII 'a' (0x61), by 64's */
--7174 00191d681d24010013c Page 8 of pgpSHA.c
af361a ¤   shaInit(&sha);
f9d1f2 ¤   for (i = 0; i < 15625; i++)
21894b ¤   ¤   shaUpdate(&sha, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
8f246a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64);
0c5e80 ¤   hash¤   = shaFinal(&sha);
df3362 ¤   if (compareSHAresults(hash, 3) < 0)
66b54f ¤   ¤   exit (-1);
a5af5a
d3a7c8 ¤   /* 1,000,000 bytes of ASCII 'a' (0x61), by 25's */
db361a ¤   shaInit(&sha);
11be5c ¤   for (i = 0; i < 40000; i++)
097016 ¤   ¤   shaUpdate(&sha, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa", 25);
790cca ¤   shaFinal(&sha, hash);
35af6c ¤   if (compareSHAresults(hash, 4) < 0)
5db54f ¤   ¤   exit (-1);
c2af5a
d6ad39 ¤   /* 1,000,000 bytes of ASCII 'a' (0x61), by 125's */
8b361a ¤   shaInit(&sha);
8feb47 ¤   for (i = 0; i < 8000; i++)
37894b ¤   ¤   shaUpdate(&sha, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
c3c1b0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
028064 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 125);
a1c687 ¤   , hashshaFinal(&sha);
732ed3 ¤   if (compareSHAresults(hash, 5) < 0)
ccb54f ¤   ¤   exit (-1);
c2af5a
d9fb6d ¤   /* Now perform time trial, generating MD for 10MB of data. ·First,
f5376b ¤   ···initialize the test data */
15c5f1 ¤   pgpClearMemory( data, ·TEST_BLOCK_SIZE);
57af5a
145c54 ¤   /* Get start time */
4314c7 ¤   printf("SHA time trial. ·Processing %ld characters...\n", TEST_BYTES);
966a0f ¤   ticks = clock();
2caf5a
b9c038 ¤   /* Calculate SHA message digest in TEST_BLOCK_SIZE byte blocks */
2f361a ¤   shaInit(&sha);
4a46e0 ¤   for (i = TEST_BLOCKS; i > 0; i--)
2549f6 ¤   ¤   shaUpdate(&sha, data, TEST_BLOCK_SIZE);
3f5e80 ¤   hash¤   = shaFinal(&sha);
caaf5a
250c81 ¤   /* Get finish time and print difference */
b130c3 ¤   ticks = clock() - ticks;
b4320e ¤   printf("Ticks to process test input: %lu\n", (unsigned long)ticks);
72af5a
9a3e6b ¤   return 0;
5defe6 }
91db0e #endif /* Test driver */
--59fe 001a82308fd4010013d Page 1 of pgpSHA.h
bc38e5 /*
371b94 ·* pgpSHA.h -- NIST Secure Hhash Algorithm
55775e ·*
8be39d ·* This is a PRIVATE header file, for use only within the PGP Library.
6c2979 ·* You should not be using these functions in an application.
e9775e ·*
bb67b4 ·* $Id: pgpSHA.h,v 1.8 1997/08/30 03:06:31 hal Exp $
f3495d ·*/
40af5a
e9da33 #ifndef Included_pgpSHA_h
e39224 #define Included_pgpSHA_h
19af5a
4d5417 #include "pgpHashPriv.h"
eda146 #include "pgpDebug.h"
4eaf5a
354bc5 #define SHA_BLOCKBYTES¤ 64
e06376 #define SHA_BLOCKWORDS¤ 16
23af5a
9f67d3 #define SHA_HASHBYTES¤  20
dcb1f9 #define SHA_HASHWORDS¤  5
48af5a
59c7cd typedef struct SHAContext {
cac3bf ¤   PGPUInt32 key[SHA_BLOCKWORDS];
5d00f4 ¤   PGPUInt32 iv[SHA_HASHWORDS];
21a0a9 #if HAVE64
2405fb ¤   word64 bytes;
ecdb21 #else
6d5873 ¤   PGPUInt32 bytesHi, bytesLo;
f27454 #endif
79a1c2 ¤   DEBUG_STRUCT_CONSTRUCTOR( SHAContext )
f7ad7f } SHAContext;
93af5a
8daf5a
fcaf5a
f699c6 PGP_BEGIN_C_DECLARATIONS
ceaf5a
cf8754 extern PGPHashVTBL const HashSHA;
c6e91a extern PGPByte const SHADERprefix[15];
a4af5a
b027f5 void¤   pgpSHATransform(PGPUInt32 *block, PGPUInt32 *key);
6caf5a
b11254 PGP_END_C_DECLARATIONS
ffaf5a
a8911e #endif /* !Included_pgpSHA_h */
--9738 0000d3474314010013e Page 1 of Makefile.in
5ea601 #
c87d7d # priv/crypto/bignum/
b9a601 #
81e503 # $Id: Makefile.in,v 1.12 1998/07/31 22:03:35 hal Exp $
83a601 #
d1af5a
e0c013 # Ignore post-processed dependencies here
471617 DEPEND=:
e6af5a
64cd44 # Architecture-dependent asm code
13fda3 .SUFFIXES: .s
153eee .s.o:
f459d8 ¤   $(CC) -c $(CFLAGS) $<
13af5a
86f9ad DEFS_sparc=-DBNINCLUDE=bnisparc.h
7001e1 OBJS_sparc=bnisparc.o
15af5a
73f171 DEFS_alpha=-DBNINCLUDE=bnialpha.h
f70685 OBJS_alpha=bnialpha.o
c4af5a
78b9a1 DEFS_i386=-DBNINCLUDE=bni80386.h
fc0e48 DEFS_i486=-DBNINCLUDE=bni80386.h
585c00 DEFS_i586=-DBNINCLUDE=bni80386.h
e7aad8 DEFS_i686=-DBNINCLUDE=bni80386.h
a6ed0f OBJS_i386=bni80386.o
c61dc8 OBJS_i486=bni80386.o
cf55e2 OBJS_i586=bni80386.o
8f8d9c OBJS_i686=bni80386.o
cd9aee OBJS_i386_aout=bni80386_aout.o
41878f OBJS_i486_aout=bni80386_aout.o
bb83f4 OBJS_i586_aout=bni80386_aout.o
b38f79 OBJS_i686_aout=bni80386_aout.o
5faf5a
64c552 # These come out blank on unknown architectures
914dc6 LOCALDEFINES=$(DEFS_@host_cpu@)
c8244c LOCALOBJS=$(OBJS_@host_cpu@@host_obj_type@)
53af5a
5ab0d4 # We use more aggressive optimization options than normal
e1cf4c CCOPTS=@TUNE@
e6af5a
dcc6ef # The BigNum library in various word sizes
38a413 BN16OBJS = bn16.o bni16.o bninit16.o
742866 BN32OBJS = bn32.o bni32.o bninit32.o
a69cf5 BN64OBJS = bn64.o bni64.o bninit64.o
a5b0b9 # This one auto-detects
270f00 BN00OBJS = bn00.o bni00.o
a1af5a
45e1ad # If you don't know what size to use, use BN00OBJS.
d49624 BNOBJS = $(BN00OBJS)
a6af5a
3bd422 # Size-independent auxiliary files.
9eb293 BNAUXOBJS = bn.o bnimem.o bnsieve.o bnprime.o bngermain.o bnjacobi.o \
667193 ¤   bnprint.o bnlegal.o pgpBigNum.o
0faf5a
03f941 # Auto-generated aux sources
0077f5 BNSOURCES = bni32.c bni32.h bn32.c bn32.h bninit32.c \
27b492 ¤   bni64.c bni64.h bn64.c bn64.h bninit64.c pgpBigNum.c
08e3ee bnsources: $(BNSOURCES)
b3af5a
db6fc0 LOCALINCLUDES = -I.
afb162 OBJS = $(BNAUXOBJS) $(BNOBJS) $(LOCALOBJS)
a4af5a
d6e5d5 # The interfaces exported from this module
d4bbc1 PRIVHDRS = bn.h bnprime.h bngermain.h
79af5a
4134c4 INSTALLLIBS = $(BNLIB)
85a71c LIBTARGET = $(BNLIB)
fc27ce LIBTDEPS = DONE
7caf5a
6553f5 clean::
595a3d ¤   $(RM) $(OBJS) $(BN00OBJS) $(BN16OBJS) $(BN32OBJS) $(BN64OBJS)
0daf5a
--3466 001cdfd55fd4010013e Page 2 of Makefile.in
467c11 very-clean:: clean
6268b3 ¤   $(RM) $(BNSOURCES)
9daf5a
69f8d0 depend:: bnsources
25af5a
a4b7a3 all:: DONE
aeaf5a
2c9973 ### Some manual dependencies needed by the bignum library
f4a3fb # The 16-bit versions of the code are the master versions; all else is
fd466b # generated from them. ·(You didn't know that suffixes for suffix rules
fe24ca # didn't have to begin with a period, did you? ·It's portable.)
f4af5a
1efc05 .SUFFIXES: 16.c 16.h 32.c 32.h 64.c 64.h
645220 16.c32.c:
0877a1 ¤   sed -e s/32/64/g -e s/16/32/g $< > $@
77af5a
910d04 16.h32.h:
b177a1 ¤   sed -e s/32/64/g -e s/16/32/g $< > $@
5faf5a
857d3f 16.c64.c:
d48810 ¤   sed -e s/32/128/g -e s/16/64/g $< > $@
e0af5a
6d221b 16.h64.h:
6b8810 ¤   sed -e s/32/128/g -e s/16/64/g $< > $@
51af5a
2e04e2 ## Dependencies ##
1b65c1 ### Bignum library dependencies
20cd30 # The bignum library does a lot of preprocessor trickery with
c8f3e6 # <limits.h> and conditional #includes. ·Here are all the dependencies
db9a82 # that might happen, even though only some of them will be used on any
59b46e # given platform.
642e65 bni00.o: bni16.c bni32.c bni64.c bnlegal.h
b7d981 bn00.o: bn16.c bn16.h bni16.h bn32.c bn32.h bni32.h bn64.c bn64.h bni64.h \
ed14b7 ¤   bninit16.c bninit32.c bninit64.c
b36151 bni16.o: bni.h bni16.h bnimem.h bnlegal.h
cfce01 bni32.o: bni.h bni32.h bnimem.h bnlegal.h
9f5305 bni64.o: bni.h bni64.h bnimem.h bnlegal.h
1f2eae bninit16.o: bn.h bn16.h
0ff329 bninit32.o: bn.h bn32.h
d1fd8d bninit64.o: bn.h bn64.h
a0672b bn16.o: bni.h bnimem.h bn.h bni16.h bn16.h
4d52f6 bn32.o: bni.h bnimem.h bn.h bni32.h bn32.h
5a9b59 bn64.o: bni.h bnimem.h bn.h bni64.h bn64.h
c82002 bnsieve.o: bn.h bnsieve.h
cd6059 bnprime.o: bnprime.h bn.h bnsieve.h
--88e5 000f82fadd64010013f Page 1 of bn.c
bc38e5 /*
601ae7 ·* bn.c - the high-level bignum interface
aa775e ·*
8cfbf7 ·* Written by Colin Plumb
5f775e ·*
9ee662 ·* $Id: bn.c,v 1.4 1997/12/11 23:11:55 lloyd Exp $
2b495d ·*/
c5af5a
cf39fc #include "bn.h"
34af5a
c4ad60 /* Functions */
b6314a void
83ac30 bnBegin(
6bd259 ¤   BigNum *¤   ¤   bn,
e66740 ¤   PGPMemoryMgrRef¤mgr,
b9ce35 ¤   PGPBoolean¤ ¤   isSecure)
e4bb36 {
09bbe4 ¤   static PGPBoolean bninit = FALSE;
d3af5a
c1807f ¤   if (!bninit) {
ea3f71 ¤   ¤   bnInit();
acc7c8 ¤   ¤   bninit = TRUE;
839371 ¤   }
0aaf5a
11e09a ¤   bn->mgr¤¤   ¤   = mgr;
465b51 ¤   bn->isSecure¤   = isSecure;
f467c5 ¤
ed3cc5 ¤   bn->ptr = 0;
fc58d7 ¤   bn->size = 0;
237222 ¤   bn->allocated = 0;
63efe6 }
dbaf5a
35314a void
a6bae4 bnSwap(BigNum *a, BigNum *b)
81bb36 {
3a141e ¤   void *p;
2d0ed5 ¤   unsigned t;
ebaf5a
dbf914 ¤   p = a->ptr;
2d198a ¤   a->ptr = b->ptr;
b147a3 ¤   b->ptr = p;
0eaf5a
3ef2a1 ¤   t = a->size;
1f8d95 ¤   a->size = b->size;
942d3c ¤   b->size = t;
87af5a
4fc6c2 ¤   t = a->allocated;
eb1d56 ¤   a->allocated = b->allocated;
ba3c02 ¤   b->allocated = t;
85efe6 }
1faf5a
c87022 int (*bnYield)(void);
89af5a
2b5a40 void (*bnEnd)(BigNum *bn);
600e5c int (*bnPrealloc)(BigNum *bn, unsigned bits);
4e42d9 int (*bnCopy)(BigNum *dest, BigNum const *src);
d0b79e void (*bnNorm)(BigNum *bn);
8d84ff void (*bnExtractBigBytes)(BigNum const *bn, unsigned char *dest,
c43762 ¤   unsigned lsbyte, unsigned len);
bee76d int (*bnInsertBigBytes)(BigNum *bn, unsigned char const *src,
9a3762 ¤   unsigned lsbyte, unsigned len);
5280ad void (*bnExtractLittleBytes)(BigNum const *bn, unsigned char *dest,
b33762 ¤   unsigned lsbyte, unsigned len);
2375cc int (*bnInsertLittleBytes)(BigNum *bn, unsigned char const *src,
633762 ¤   unsigned lsbyte, unsigned len);
6dde9e unsigned (*bnLSWord)(BigNum const *src);
962b0e unsigned (*bnBits)(BigNum const *src);
34083d int (*bnAdd)(BigNum *dest, BigNum const *src);
0fc056 int (*bnSub)(BigNum *dest, BigNum const *src);
602fbe int (*bnCmpQ)(BigNum const *a, unsigned b);
a89093 int (*bnSetQ)(BigNum *dest, unsigned src);
f82ed8 int (*bnAddQ)(BigNum *dest, unsigned src);
--46ef 001758549bd4010013f Page 2 of bn.c
530a39 int (*bnSubQ)(BigNum *dest, unsigned src);
25a03d int (*bnCmp)(BigNum const *a, BigNum const *b);
526770 int (*bnSquare)(BigNum *dest, BigNum const *src);
403e62 int (*bnMul)(BigNum *dest, BigNum const *a,
219cfe ¤   BigNum const *b);
327dbb int (*bnMulQ)(BigNum *dest, BigNum const *a, unsigned b);
8f47bb int (*bnDivMod)(BigNum *q, BigNum *r, BigNum const *n,
5ed764 ¤   BigNum const *d);
83da7a int (*bnMod)(BigNum *dest, BigNum const *src,
1fd764 ¤   BigNum const *d);
5a003c unsigned (*bnModQ)(BigNum const *src, unsigned d);
56874d int (*bnExpMod)(BigNum *result, BigNum const *n,
527da1 ¤   BigNum const *exp, BigNum const *mod);
460025 int (*bnDoubleExpMod)(BigNum *dest,
4cb250 ¤   BigNum const *n1, BigNum const *e1,
5e0480 ¤   BigNum const *n2, BigNum const *e2,
3c092e ¤   BigNum const *mod);
076d1f int (*bnTwoExpMod)(BigNum *n, BigNum const *exp,
e1092e ¤   BigNum const *mod);
ac470c int (*bnGcd)(BigNum *dest, BigNum const *a,
ed9cfe ¤   BigNum const *b);
a31ff2 int (*bnInv)(BigNum *dest, BigNum const *src,
76092e ¤   BigNum const *mod);
f4b205 int (*bnLShift)(BigNum *dest, unsigned amt);
38f284 void (*bnRShift)(BigNum *dest, unsigned amt);
75f966 unsigned (*bnMakeOdd)(BigNum *n);
--1f0d 000ca476aa840100140 Page 1 of bn.h
bc38e5 /*
2d7b63 ·* bn.h - the interface to the bignum routines.
51af9e ·* All functions which return ints can potentially allocate memory
1c0926 ·* and return -1 if they are unable to. All "const" arguments
35cf54 ·* are unmodified.
89775e ·*
67cf6f ·* This is not particularly asymmetric, as some operations are of the
418c9d ·* form a = b @ c, while others do a @= b. ·In general, outputs may not
b594d3 ·* point to the same BigNums as inputs, except as specified
736314 ·* below. ·This relationship is referred to as "being the same as".
b12c47 ·* This is not numerical equivalence.
d3775e ·*
ce492d ·* The "Q" operations take "unsigned" inputs. ·Higher values of the
853fb6 ·* extra input may work on some implementations, but 65535 is the
1bc3e7 ·* highest portable value. ·Just because UNSIGNED_MAX is larger than
94b0d0 ·* that, or you know that the word size of the library is larger than that,
b8e593 ·* that, does *not* mean it's allowed.
7f775e ·*
d18a4f ·* $Id: bn.h,v 1.7 1997/12/11 23:11:57 lloyd Exp $
e3495d ·*/
a5e6e9 #ifndef Included_bn_h
bdbaec #define Included_bn_h
88af5a
bcc5d5 #include "pgpBase.h"
78af5a
396773 #include "pgpMemoryMgr.h"
6daf5a
5199c6 PGP_BEGIN_C_DECLARATIONS
f5af5a
6d419a struct BigNum
2abb36 {
d44620 ¤   void *ptr;
bd944c ¤   unsigned size;¤ /* Note: in (variable-sized) words */
3ed5dd ¤   unsigned allocated;
2767c5 ¤
5f9599 ¤   PGPMemoryMgrRef¤¤   mgr;
0dd480 ¤   PGPBoolean¤ ¤   ¤   isSecure;
9b2fa1 } ;
e2af5a
38bdbd #include "pgpBigNumOpaqueStructs.h"
3caf5a
a238e5 /*
26afb4 ·* User-supplied function: if non-NULL, this is called during long-running
c548d2 ·* computations. ·You may put Yield() calls in here to give CPU time to
82365a ·* other processes. ·You may also force the computation to be aborted,
637308 ·* by returning a value < 0, which will be the return value of the
14273f ·* bnXXX call. ·(You probably want the value to be someting other than
d95072 ·* -1, to distinguish it from an out-of-memory error.)
3d775e ·*
8f1dc5 ·* The functions that this is called from, and the intervals at which it
d4e3b4 ·* is called, are not well defined, just "reasonably often". ·(Currently,
231d2b ·* once per exponent bit in modular exponentiation, and once per two
1e3a36 ·* divisions in GCD and inverse computation.)
5f495d ·*/
2ace77 extern int (*bnYield)(void);
26af5a
51ad60 /* Functions */
8eaf5a
bd38e5 /*
022d20 ·* You usually never have to call this function explicitly, as
b16996 ·* bnBegin() takes care of it. ·If the program jumps to address 0,
28bfc7 ·* this function has not been called.
12495d ·*/
f80cb6 void bnInit(void);
c9af5a
4538e5 /*
555c8b ·* This initializes an empty BigNum to a zero value.
101596 ·* Do not use this on a BigNum which has had a value stored in it!
08495d ·*/
1ee26b void bnBegin(BigNum *bn, PGPMemoryMgrRef mgr, PGPBoolean isSecure );
7aaf5a
caf520 /* Swap two BigNums. ·Cheap. */
--287e 0001fb640be40100140 Page 2 of bn.h
eca221 void bnSwap(BigNum *a, BigNum *b);
a7af5a
7a9faf /* Reset an initialized bigNum to empty, pending deallocation. */
0ec6a8 extern void (*bnEnd)(BigNum *bn);
bdaf5a
0138e5 /*
c5a7bf ·* If you know you'll need space in the number soon, you can use this function
5d24ee ·* to ensure that there is room for at least "bits" bits. ·Optional.
874c09 ·* Returns <0 on out of memory, but the value is unaffected.
d0495d ·*/
11326c extern int (*bnPrealloc)(BigNum *bn, unsigned bits);
5faf5a
4129e8 /* Hopefully obvious. ·dest = src. ··dest may be the same as src. */
e10f94 extern int (*bnCopy)(BigNum *dest, BigNum const *src);
c2af5a
cd38e5 /*
c224ce ·* Mostly done automatically, but this removes leading zero words from
bf1dd4 ·* the internal representation of the BigNum. ·Use is unclear.
34495d ·*/
64dc44 extern void (*bnNorm)(BigNum *bn);
ecaf5a
ff38e5 /*
14b555 ·* Move bytes between the given buffer and the given BigNum encoded in
c15965 ·* base 256. ·I.e. after either of these, the buffer will be equal to
ecea08 ·* (bn / 256^lsbyte) % 256^len. ·The difference is which is altered to
733b60 ·* match the other!
29495d ·*/
54f4bb extern void (*bnExtractBigBytes)(BigNum const *bn,
7835b5 ¤   unsigned char *dest, unsigned lsbyte, unsigned len);
c36ed3 extern int (*bnInsertBigBytes)(BigNum *bn,
312c99 ¤   unsigned char const *src, unsigned lsbyte, unsigned len);
41af5a
35684c /* The same, but the buffer is little-endian. */
89a8b8 extern void (*bnExtractLittleBytes)(BigNum const *bn,
c935b5 ¤   unsigned char *dest, unsigned lsbyte, unsigned len);
680f81 extern int (*bnInsertLittleBytes)(BigNum *bn,
e02c99 ¤   unsigned char const *src, unsigned lsbyte, unsigned len);
a1af5a
230b69 /* Return the least-significant bits (at least 16) of the BigNum */
65f65d extern unsigned (*bnLSWord)(BigNum const *src);
11af5a
e238e5 /*
4b810c ·* Return the number of significant bits in the BigNum.
dad5d9 ·* 0 or 1+floor(log2(src))
79495d ·*/
a0f253 extern unsigned (*bnBits)(BigNum const *src);
e9ae55 #define bnBytes(bn) ((bnBits(bn)+7)/8)
78af5a
fb38e5 /*
6a3846 ·* dest += src. ·dest and src may be the same. ·Guaranteed not to
d33bcc ·* allocate memory unnecessarily, so if you're sure bnBits(dest)
64a7d7 ·* won't change, you don't need to check the return value.
cd495d ·*/
3c3982 extern int (*bnAdd)(BigNum *dest, BigNum const *src);
59af5a
6c38e5 /*
a78ca6 ·* dest -= src. ·dest and src may be the same, but bnSetQ(dest, 0) is faster.
4e9a2c ·* if dest < src, returns +1 and sets dest = src-dest.
08495d ·*/
2df1e9 extern int (*bnSub)(BigNum *dest, BigNum const *src);
70af5a
935a0c /* Return sign (-1, 0, +1) of a-b. ·a <=> b --> bnCmpQ(a, b) <=> 0 */
2e27b3 extern int (*bnCmpQ)(BigNum const *a, unsigned b);
05af5a
1c848c /* dest = src, where 0 <= src < 2^16. */
65dd1b extern int (*bnSetQ)(BigNum *dest, unsigned src);
b7af5a
f43019 /* dest += src, where 0 <= src < 2^16 */
e86350 extern int (*bnAddQ)(BigNum *dest, unsigned src);
79af5a
0bb942 /* dest -= src, where 0 <= src < 2^16 */
1f47b1 extern int (*bnSubQ)(BigNum *dest, unsigned src);
--6b4d 0012a0ec51540100140 Page 3 of bn.h
e0af5a
c28dd9 /* Return sign (-1, 0, +1) of a-b. ·a <=> b --> bnCmp(a, b) <=> 0 */
65ed70 extern int (*bnCmp)(BigNum const *a, BigNum const *b);
aeaf5a
ba0a05 /* dest = src^2. ·dest may be the same as src, but it costs time. */
64e4d7 extern int (*bnSquare)(BigNum *dest,
26ed29 ¤   BigNum const *src);
64af5a
832854 /* dest = a * b. ·dest may be the same as a or b, but it costs time. */
16366f extern int (*bnMul)(BigNum *dest, BigNum const *a,
699cfe ¤   BigNum const *b);
54af5a
44804c /* dest = a * b, where 0 <= b < 2^16. ·dest and a may be the same. */
ed573a extern int (*bnMulQ)(BigNum *dest, BigNum const *a,
773918 ¤   unsigned b);
a4af5a
2a38e5 /*
f87a36 ·* q = n/d, r = n%d. ·r may be the same as n, but not d,
32eb22 ·* and q may not be the same as n or d.
ddad6f ·* re-entrancy issue: this temporarily modifies d, but restores
22bf83 ·* it for return.
a4495d ·*/
580fe6 extern int (*bnDivMod)(BigNum *q, BigNum *r,
e22493 ¤   BigNum const *n, BigNum const *d);
0738e5 /*
cc4079 ·* dest = src % d. ·dest and src may be the same, but not dest and d.
e6ad6f ·* re-entrancy issue: this temporarily modifies d, but restores
7cbf83 ·* it for return.
13495d ·*/
10e64a extern int (*bnMod)(BigNum *dest, BigNum const *src,
efd764 ¤   BigNum const *d);
7aaf5a
a25662 /* return src % d, where 0 <= d < 2^16. ·*/
b30dcb extern unsigned int (*bnModQ)(BigNum const *src, unsigned d);
08af5a
60b223 /* n = n^exp, modulo "mod" ··"mod" *must* be odd */
681ee1 extern int (*bnExpMod)(BigNum *result, BigNum const *n,
b67da1 ¤   BigNum const *exp, BigNum const *mod);
a9af5a
5c38e5 /*
217329 ·* dest = n1^e1 * n2^e2, modulo "mod". ·"mod" *must* be odd.
eff0f0 ·* dest may be the same as n1 or n2.
5b495d ·*/
14019a extern int (*bnDoubleExpMod)(BigNum *dest,
4db250 ¤   BigNum const *n1, BigNum const *e1,
f00480 ¤   BigNum const *n2, BigNum const *e2,
88092e ¤   BigNum const *mod);
3aaf5a
d84e98 /* n = 2^exp, modulo "mod" ··"mod" *must* be odd */
c8f4b3 extern int (*bnTwoExpMod)(BigNum *n, BigNum const *exp,
66092e ¤   BigNum const *mod);
60af5a
475c5b /* dest = gcd(a, b). ·The inputs may overlap arbitrarily. */
d44f01 extern int (*bnGcd)(BigNum *dest, BigNum const *a,
8b9cfe ¤   BigNum const *b);
a7af5a
f21893 /* dest = src^-1, modulo "mod". ·dest may be the same as src. */
aa23c2 extern int (*bnInv)(BigNum *dest, BigNum const *src,
b8092e ¤   BigNum const *mod);
89af5a
f66138 /* Shift dest left "amt" places */
2a69e8 extern int (*bnLShift)(BigNum *dest, unsigned amt);
db70f6 /* Shift dest right "amt" places, discarding low-order bits */
15ceb4 extern void (*bnRShift)(BigNum *dest, unsigned amt);
e0af5a
03f952 /* For the largest 2^k that divides n, divide n by it and return k. */
1a73f4 extern unsigned (*bnMakeOdd)(BigNum *n);
1faf5a
ff1254 PGP_END_C_DECLARATIONS
99af5a
2a58ca #endif/* !Included_bn_h */
--6059 001f6be20df40100141 Page 1 of bn00.c
bc38e5 /*
c0d3a9 ·* bn00.c - auto-size-detecting bn??.c file.
51775e ·*
4b001b ·* Written in 1995 by Colin Plumb.
ff775e ·*
940c01 ·* $Id: bn00.c,v 1.1 1997/04/30 08:36:00 mhw Exp $
53495d ·*/
17af5a
e0afa6 #include "bnsize00.h"
fcaf5a
9284d0 #if BNSIZE64
dcaf5a
d3a754 /* Include all of the C source file by reference */
70a9ee #include "bn64.c"
494289 #include "bninit64.c"
32af5a
3e41e3 #elif BNSIZE32
ecaf5a
eba754 /* Include all of the C source file by reference */
3a86f1 #include "bn32.c"
a16d96 #include "bninit32.c"
fdaf5a
f99a11 #else /* BNSIZE16 */
00af5a
87a754 /* Include all of the C source file by reference */
b7a3b7 #include "bn16.c"
7048d0 #include "bninit16.c"
20af5a
f67454 #endif
--b7f6 00070a7255d40100142 Page 1 of bn16.c
bc38e5 /*
fa1756 ·* bn16.c - the high-level bignum interface
d1775e ·*
d7d51d ·* Like bni16.c, this reserves the string "16" for textual replacement.
b2dd9c ·* The string must not appear anywhere unless it is intended to be replaced
8e295d ·* to generate other bignum interface functions.
9d775e ·*
effbf7 ·* Written by Colin Plumb
42775e ·*
96b4a6 ·* $Id: bn16.c,v 1.6.4.1 1998/10/22 19:49:29 heller Exp $
6e495d ·*/
bbaf5a
10e2ff #include "pgpConfig.h"
44af5a
8738e5 /*
8f16cf ·* Some compilers complain about #if FOO if FOO isn't defined,
3f59aa ·* so do the ANSI-mandated thing explicitly...
e5495d ·*/
d3b552 #ifndef NO_STRING_H
5937dd #define NO_STRING_H 0
5f7454 #endif
df8537 #ifndef HAVE_STRINGS_H
3f025c #define HAVE_STRINGS_H 0
477454 #endif
5c101b #ifndef NEED_MEMORY_H
e3ee50 #define NEED_MEMORY_H 0
f27454 #endif
67af5a
797668 #if !NO_STRING_H
89f91c #include <string.h>¤/* for memmove() in bnMakeOdd */
80a752 #elif HAVE_STRINGS_H
adf7c3 #include <strings.h>
a37454 #endif
de3c37 #if NEED_MEMORY_H
7fc737 #include <memory.h>
4e7454 #endif
74af5a
2a38e5 /*
46be8a ·* This was useful during debugging, so it's left in here.
37954b ·* You can ignore it. ·DBMALLOC is generally undefined.
68495d ·*/
55e178 #ifndef DBMALLOC
0b15ee #define DBAMLLOC 0
507454 #endif
96deac #if DBMALLOC
d81594 #include "../dbmalloc/malloc.h"
934685 #define MALLOCDB malloc_chain_check(1)
8cdb21 #else
c6756d #define MALLOCDB (void)0
007454 #endif
deaf5a
aaa6ac #include "bni.h"
053598 #include "bni16.h"
6321db #include "bnimem.h"
148a11 #include "bn16.h"
4f39fc #include "bn.h"
70af5a
2665e3 /* Work-arounds for some particularly broken systems */
7f9ba2 #include "bnkludge.h"¤  /* For memmove() */
74af5a
55a146 #include "pgpDebug.h"
50af5a
bcad60 /* Functions */
c2314a void
e65c3c bnInit_16(void)
2ebb36 {
5905ef ¤   bnEnd = bnEnd_16;
826b6a ¤   bnPrealloc = bnPrealloc_16;
08a6ad ¤   bnCopy = bnCopy_16;
19acb3 ¤   bnNorm = bnNorm_16;
f7eaf5 ¤   bnExtractBigBytes = bnExtractBigBytes_16;
70dfb2 ¤   bnInsertBigBytes = bnInsertBigBytes_16;
--e4ec 000d980ab9c40100142 Page 2 of bn16.c
f95dd8 ¤   bnExtractLittleBytes = bnExtractLittleBytes_16;
f74eea ¤   bnInsertLittleBytes = bnInsertLittleBytes_16;
46a6e9 ¤   bnLSWord = bnLSWord_16;
67c118 ¤   bnBits = bnBits_16;
fa1322 ¤   bnAdd = bnAdd_16;
af20c9 ¤   bnSub = bnSub_16;
68354f ¤   bnCmpQ = bnCmpQ_16;
92d684 ¤   bnSetQ = bnSetQ_16;
65384b ¤   bnAddQ = bnAddQ_16;
cef5c2 ¤   bnSubQ = bnSubQ_16;
5b236f ¤   bnCmp = bnCmp_16;
7b69f7 ¤   bnSquare = bnSquare_16;
0a5e0f ¤   bnMul = bnMul_16;
3c3085 ¤   bnMulQ = bnMulQ_16;
99f53b ¤   bnDivMod = bnDivMod_16;
fbaf68 ¤   bnMod = bnMod_16;
ff6b81 ¤   bnModQ = bnModQ_16;
c2d9d4 ¤   bnExpMod = bnExpMod_16;
f3133f ¤   bnDoubleExpMod = bnDoubleExpMod_16;
7d97be ¤   bnTwoExpMod = bnTwoExpMod_16;
ab051f ¤   bnGcd = bnGcd_16;
0727ce ¤   bnInv = bnInv_16;
fda316 ¤   bnLShift = bnLShift_16;
80d3b4 ¤   bnRShift = bnRShift_16;
7e916c ¤   bnMakeOdd = bnMakeOdd_16;
aaefe6 }
10af5a
ff314a void
5f006a bnEnd_16(BigNum *bn)
37bb36 {
5b8780 ¤   if (bn->ptr) {
76cf60 ¤   ¤   BNIFREE((BNWORD16 *)bn->ptr, bn->allocated);
fd7d4e ¤   ¤   bn->ptr = 0;
c79371 ¤   }
3d58d7 ¤   bn->size = 0;
467222 ¤   bn->allocated = 0;
40af5a
bd4249 ¤   MALLOCDB;
fcefe6 }
62af5a
75a782 /* Internal function. ·It operates in words. */
43beb7 static int
9d0522 bnResize_16(BigNum *bn, unsigned len)
abbb36 {
f2141e ¤   void *p;
0caf5a
1c3834 ¤   /* Round size up: most mallocs impose 8-byte granularity anyway */
4de288 ¤   len = (len + (8/sizeof(BNWORD16) - 1)) & ~(8/sizeof(BNWORD16) - 1);
fbe6c0 ¤   p = BNIREALLOC( bn->mgr, bn->isSecure,
c195e4 ¤   ¤   ¤   (BNWORD16 *)bn->ptr, bn->allocated, len);
f94dda ¤   if (!p)
4a043c ¤   ¤   return -1;
183ab3 ¤   bn->ptr = p;
12a26c ¤   bn->allocated = len;
daaf5a
174249 ¤   MALLOCDB;
9baf5a
4a3e6b ¤   return 0;
9befe6 }
1daf5a
074e7d #define bnSizeCheck(bn, size) \
216569 ¤   if (bn->allocated < size && bnResize_16(bn, size) < 0) \
b03c44 ¤   ¤   return -1
cfaf5a
564d2f int
b88dbc bnPrealloc_16(BigNum *bn, unsigned bits)
42bb36 {
07ec8e ¤   bits = (bits + 16-1)/16;
c25fca ¤   bnSizeCheck(bn, bits);
264249 ¤   MALLOCDB;
423e6b ¤   return 0;
d9efe6 }
--2e01 000563d0cd240100142 Page 3 of bn16.c
e0af5a
e54d2f int
f589a5 bnCopy_16(BigNum *dest, BigNum const *src)
d7bb36 {
2c8a1f ¤   bnSizeCheck(dest, src->size);
6a5e12 ¤   dest->size = src->size;
c2fc10 ¤   bniCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, src->size);
004249 ¤   MALLOCDB;
c93e6b ¤   return 0;
62efe6 }
bfaf5a
88314a void
2286d0 bnNorm_16(BigNum *bn)
62bb36 {
ba3c03 ¤   bn->size = bniNorm_16((BNWORD16 *)bn->ptr, bn->size);
04efe6 }
d6af5a
cf38e5 /*
d8516a ·* Convert a bignum to big-endian bytes. ·Returns, in big-endian form, a
e5bbfe ·* substring of the bignum starting from lsbyte and "len" bytes long.
3f4f9d ·* Unused high-order (leading) bytes are filled with 0.
b9495d ·*/
71314a void
d76e6e bnExtractBigBytes_16(BigNum const *bn, unsigned char *dest,
37baaa ··················unsigned lsbyte, unsigned len)
50bb36 {
b5af48 ¤   unsigned s = bn->size * (16 / 8);
e9af5a
ac59b6 ¤   /* Fill unused leading bytes with 0 */
d50077 ¤   while (s < lsbyte+len && len) {
e16d4e ¤   ¤   *dest++ = 0;
90e1e8 ¤   ¤   len--;
3a9371 ¤   }
e1af5a
7b4548 ¤   if (len)
c6db5d ¤   ¤   bniExtractBigBytes_16((BNWORD16 *)bn->ptr, dest, lsbyte, len);
854249 ¤   MALLOCDB;
07efe6 }
9aaf5a
af4d2f int
b83595 bnInsertBigBytes_16(BigNum *bn, unsigned char const *src,
f671b3 ·················unsigned lsbyte, unsigned len)
a0bb36 {
0fbe7f ¤   unsigned s = bn->size;
693140 ¤   unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16);
c7af5a
a9756a ¤   /* Pad with zeros as required */
a1580e ¤   bnSizeCheck(bn, words);
d1af5a
7c637b ¤   if (s < words) {
61d69a ¤   ¤   bniZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s);
1f2aa9 ¤   ¤   s = words;
e39371 ¤   }
5faf5a
683433 ¤   bniInsertBigBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len);
30af5a
0ec4df ¤   bn->size = bniNorm_16((BNWORD16 *)bn->ptr, s);
adaf5a
d44249 ¤   MALLOCDB;
f23e6b ¤   return 0;
19efe6 }
c4af5a
8daf5a
8138e5 /*
133ccd ·* Convert a bignum to little-endian bytes. ·Returns, in little-endian form, a
95bbfe ·* substring of the bignum starting from lsbyte and "len" bytes long.
78b273 ·* Unused high-order (trailing) bytes are filled with 0.
b5495d ·*/
97314a void
d5e22b bnExtractLittleBytes_16(BigNum const *bn, unsigned char *dest,
76baaa ··················unsigned lsbyte, unsigned len)
56bb36 {
--509e 00095782ff240100142 Page 4 of bn16.c
83af48 ¤   unsigned s = bn->size * (16 / 8);
ffaf5a
c859b6 ¤   /* Fill unused leading bytes with 0 */
252317 ¤   while (s < lsbyte+len && len)
975946 ¤   ¤   dest[--len] = 0;
53af5a
054548 ¤   if (len)
46713f ¤   ¤   bniExtractLittleBytes_16((BNWORD16 *)bn->ptr, dest,
de2bf3 ¤   ¤   ·························lsbyte, len);
ae4249 ¤   MALLOCDB;
e7efe6 }
a8af5a
604d2f int
4b9311 bnInsertLittleBytes_16(BigNum *bn, unsigned char const *src,
1a3de8 ·······················unsigned lsbyte, unsigned len)
25bb36 {
67be7f ¤   unsigned s = bn->size;
b93140 ¤   unsigned words = (len+lsbyte+sizeof(BNWORD16)-1) / sizeof(BNWORD16);
baaf5a
88756a ¤   /* Pad with zeros as required */
6d580e ¤   bnSizeCheck(bn, words);
23af5a
4a637b ¤   if (s < words) {
c6d69a ¤   ¤   bniZero_16((BNWORD16 *)bn->ptr BIGLITTLE(-s,+s), words-s);
402aa9 ¤   ¤   s = words;
939371 ¤   }
beaf5a
fd583f ¤   bniInsertLittleBytes_16((BNWORD16 *)bn->ptr, src, lsbyte, len);
a8af5a
87c4df ¤   bn->size = bniNorm_16((BNWORD16 *)bn->ptr, s);
ffaf5a
384249 ¤   MALLOCDB;
613e6b ¤   return 0;
0defe6 }
f7af5a
5e03b4 /* Return the least-significant word of the input. */
9c536c unsigned
6c3202 bnLSWord_16(BigNum const *src)
2cbb36 {
a2d6eb ¤   return src->size ? (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)]
ab0715 ¤   ¤   ¤   ·: 0;
1aefe6 }
33af5a
ec536c unsigned
ee3622 bnBits_16(BigNum const *src)
c3bb36 {
d1657a ¤   return bniBits_16((BNWORD16 *)src->ptr, src->size);
87efe6 }
34af5a
364d2f int
f08d0f bnAdd_16(BigNum *dest, BigNum const *src)
e8bb36 {
e1d27a ¤   unsigned s = src->size, d = dest->size;
58dcba ¤   BNWORD16 t;
4faf5a
daa2be ¤   if (!s)
cabbde ¤   ¤   return 0;
56af5a
767ebc ¤   bnSizeCheck(dest, s);
2caf5a
5aab53 ¤   if (d < s) {
d759f9 ¤   ¤   bniZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d);
038fbc ¤   ¤   dest->size = d = s;
cbc7fc ¤   ¤   MALLOCDB;
869371 ¤   }
79b6ec ¤   t = bniAddN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
8c4249 ¤   MALLOCDB;
3edc81 ¤   if (t) {
9add63 ¤   ¤   if (d > s) {
c907f0 ¤   ¤   ¤   t = bniAdd1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s),
cd911f ¤   ¤   ¤   ···············d-s, t);
95fd66 ¤   ¤   ¤   MALLOCDB;
--1166 00004202a3940100142 Page 5 of bn16.c
b50fe4 ¤   ¤   }
636910 ¤   ¤   if (t) {
e8aadd ¤   ¤   ¤   bnSizeCheck(dest, d+1);
f9c14c ¤   ¤   ¤   ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
9d14fd ¤   ¤   ¤   dest->size = d+1;
760fe4 ¤   ¤   }
8d9371 ¤   }
b83e6b ¤   return 0;
c5efe6 }
81af5a
4a38e5 /*
6c477d ·* dest -= src.
8e260a ·* If dest goes negative, this produces the absolute value of
202d02 ·* the difference (the negative of the true value) and returns 1.
497407 ·* Otherwise, it returls 0.
ad495d ·*/
384d2f int
2f5012 bnSub_16(BigNum *dest, BigNum const *src)
32bb36 {
5ed27a ¤   unsigned s = src->size, d = dest->size;
d8dcba ¤   BNWORD16 t;
06af5a
9d2d91 ¤   if (d < s ·&& ·d < (s = bniNorm_16((BNWORD16 *)src->ptr, s))) {
05f7e8 ¤   ¤   bnSizeCheck(dest, s);
0659f9 ¤   ¤   bniZero_16((BNWORD16 *)dest->ptr BIGLITTLE(-d,+d), s-d);
e58fbc ¤   ¤   dest->size = d = s;
1ec7fc ¤   ¤   MALLOCDB;
e59371 ¤   }
c2a2be ¤   if (!s)
8cbbde ¤   ¤   return 0;
ff8b6f ¤   t = bniSubN_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
054249 ¤   MALLOCDB;
b9dc81 ¤   if (t) {
8edd63 ¤   ¤   if (d > s) {
ec3cc8 ¤   ¤   ¤   t = bniSub1_16((BNWORD16 *)dest->ptr BIGLITTLE(-s,+s),
50911f ¤   ¤   ¤   ···············d-s, t);
c8fd66 ¤   ¤   ¤   MALLOCDB;
480fe4 ¤   ¤   }
896910 ¤   ¤   if (t) {
642e4b ¤   ¤   ¤   bniNeg_16((BNWORD16 *)dest->ptr, d);
a058bf ¤   ¤   ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr,
54ff67 ¤   ¤   ¤   ························dest->size);
f7fd66 ¤   ¤   ¤   MALLOCDB;
aadb98 ¤   ¤   ¤   return 1;
580fe4 ¤   ¤   }
3d9371 ¤   }
d76360 ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, dest->size);
a53e6b ¤   return 0;
d3efe6 }
78af5a
5338e5 /*
c18fa6 ·* Compare the BigNum to the given value, which must be < 65536.
a8b0f5 ·* Returns -1. 0 or 1 if a<b, a == b or a>b.
fdb1d0 ·* a <=> b --> bnCmpQ(a,b) <=> 0
6a495d ·*/
6b4d2f int
16c675 bnCmpQ_16(BigNum const *a, unsigned b)
0dbb36 {
3d0ed5 ¤   unsigned t;
3b6902 ¤   BNWORD16 v;
ddaf5a
618dda ¤   t = bniNorm_16((BNWORD16 *)a->ptr, a->size);
a88c5d ¤   /* If a is more than one word long or zero, it's easy... */
fccbfd ¤   if (t != 1)
8f9178 ¤   ¤   return (t > 1) ? 1 : (b ? -1 : 0);
3a3d12 ¤   v = (unsigned)((BNWORD16 *)a->ptr)[BIGLITTLE(-1,0)];
5eb9fd ¤   return (v > b) ? 1 : ((v < b) ? -1 : 0);
57efe6 }
c1af5a
104d2f int
d8ba9e bnSetQ_16(BigNum *dest, unsigned src)
04bb36 {
--dfd9 0006ffabb1e40100142 Page 6 of bn16.c
f9d850 ¤   if (src) {
7fd829 ¤   ¤   bnSizeCheck(dest, 1);
c3af5a
e1e067 ¤   ¤   ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD16)src;
06fd7f ¤   ¤   dest->size = 1;
e8f037 ¤   } else {
1da7a3 ¤   ¤   dest->size = 0;
ea9371 ¤   }
153e6b ¤   return 0;
2aefe6 }
7eaf5a
424d2f int
8946f7 bnAddQ_16(BigNum *dest, unsigned src)
dabb36 {
aadcba ¤   BNWORD16 t;
feaf5a
a3e656 ¤   if (!dest->size)
d6798d ¤   ¤   return bnSetQ(dest, src);
fc67c5 ¤
631894 ¤   t = bniAdd1_16((BNWORD16 *)dest->ptr, dest->size, (BNWORD16)src);
064249 ¤   MALLOCDB;
bbdc81 ¤   if (t) {
d06cb7 ¤   ¤   src = dest->size;
d66dfe ¤   ¤   bnSizeCheck(dest, src+1);
f48da5 ¤   ¤   ((BNWORD16 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
fbd25b ¤   ¤   dest->size = src+1;
e39371 ¤   }
893e6b ¤   return 0;
d9efe6 }
f6af5a
7c38e5 /*
b47f39 ·* Return value as for bnSub: 1 if subtract underflowed, in which
a26059 ·* case the return is the negative of the computed value.
9a495d ·*/
304d2f int
28b054 bnSubQ_16(BigNum *dest, unsigned src)
d5bb36 {
85dcba ¤   BNWORD16 t;
92af5a
b2e656 ¤   if (!dest->size)
31d85e ¤   ¤   return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
15af5a
c3cea7 ¤   t = bniSub1_16((BNWORD16 *)dest->ptr, dest->size, src);
fe4249 ¤   MALLOCDB;
afdc81 ¤   if (t) {
8b8587 ¤   ¤   /* Underflow. <= 1 word, so do it simply. */
2ac797 ¤   ¤   bniNeg_16((BNWORD16 *)dest->ptr, 1);
40fd7f ¤   ¤   dest->size = 1;
9ae102 ¤   ¤   return 1;
f19371 ¤   }
9af754 /* Try to normalize? ·Needing this is going to be pretty damn rare. */
c85e6c /*¤ ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, dest->size); */
953e6b ¤   return 0;
0eefe6 }
9daf5a
6438e5 /*
f04f98 ·* Compare two BigNums. ·Returns -1. 0 or 1 if a<b, a == b or a>b.
1c6081 ·* a <=> b --> bnCmp(a,b) <=> 0
32495d ·*/
fd4d2f int
006dde bnCmp_16(BigNum const *a, BigNum const *b)
ffbb36 {
04f9fb ¤   unsigned s, t;
66af5a
0a0f7b ¤   s = bniNorm_16((BNWORD16 *)a->ptr, a->size);
14f88b ¤   t = bniNorm_16((BNWORD16 *)b->ptr, b->size);
0367c5 ¤
c16838 ¤   if (s != t)
5bce46 ¤   ¤   return s > t ? 1 : -1;
36f143 ¤   return bniCmp_16((BNWORD16 *)a->ptr, (BNWORD16 *)b->ptr, s);
4aefe6 }
6faf5a
--6f01 0000b37a46540100142 Page 7 of bn16.c
af4d2f int
d01dc5 bnSquare_16(BigNum *dest, BigNum const *src)
fabb36 {
7082d0 ¤   unsigned s;
fa0095 ¤   BNWORD16 *srcbuf;
9eaf5a
466832 ¤   s = bniNorm_16((BNWORD16 *)src->ptr, src->size);
59ed11 ¤   if (!s) {
bfa7a3 ¤   ¤   dest->size = 0;
bbbbde ¤   ¤   return 0;
9f9371 ¤   }
2df061 ¤   bnSizeCheck(dest, 2*s);
f8af5a
9c59de ¤   if (src == dest) {
380e43 ¤   ¤   BNIALLOC( src->mgr, src->isSecure, srcbuf, BNWORD16, s);
bb48bf ¤   ¤   if (!srcbuf)
643fd5 ¤   ¤   ¤   return -1;
713bae ¤   ¤   bniCopy_16(srcbuf, (BNWORD16 *)src->ptr, s);
5f1ee3 ¤   ¤   bniSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)srcbuf, s);
565788 ¤   ¤   BNIFREE(srcbuf, s);
07f037 ¤   } else {
0b645a ¤   ¤   bniSquare_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, s);
d69371 ¤   }
80af5a
b558b3 ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, 2*s);
334249 ¤   MALLOCDB;
1f3e6b ¤   return 0;
8cefe6 }
ebaf5a
044d2f int
f96041 bnMul_16(BigNum *dest, BigNum const *a, BigNum const *b)
76bb36 {
88f9fb ¤   unsigned s, t;
950095 ¤   BNWORD16 *srcbuf;
b3f93f ¤   PGPBoolean¤ secure¤ = dest->isSecure || a->isSecure || b->isSecure;
76af5a
7c0f7b ¤   s = bniNorm_16((BNWORD16 *)a->ptr, a->size);
20f88b ¤   t = bniNorm_16((BNWORD16 *)b->ptr, b->size);
33af5a
286c90 ¤   if (!s || !t) {
67a7a3 ¤   ¤   dest->size = 0;
09bbde ¤   ¤   return 0;
399371 ¤   }
36af5a
371827 ¤   if (a == b)
73b826 ¤   ¤   return bnSquare_16(dest, a);
c0af5a
c5aafe ¤   bnSizeCheck(dest, s+t);
46af5a
09bfe3 ¤   if (dest == a) {
14ce5c ¤   ¤   BNIALLOC( dest->mgr, secure, srcbuf, BNWORD16, s);
ab48bf ¤   ¤   if (!srcbuf)
123fd5 ¤   ¤   ¤   return -1;
c0a4d0 ¤   ¤   bniCopy_16(srcbuf, (BNWORD16 *)a->ptr, s);
55f32b ¤   ¤   bniMul_16((BNWORD16 *)dest->ptr, srcbuf, s,
c4d448 ¤   ¤   ·································(BNWORD16 *)b->ptr, t);
705788 ¤   ¤   BNIFREE(srcbuf, s);
a884bc ¤   } else if (dest == b) {
9a997d ¤   ¤   BNIALLOC( dest->mgr, secure, srcbuf, BNWORD16, t);
d148bf ¤   ¤   if (!srcbuf)
ff3fd5 ¤   ¤   ¤   return -1;
b3741f ¤   ¤   bniCopy_16(srcbuf, (BNWORD16 *)b->ptr, t);
25817f ¤   ¤   bniMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s,
bf322d ¤   ¤   ·································srcbuf, t);
6c00a9 ¤   ¤   BNIFREE(srcbuf, t);
0af037 ¤   } else {
7b817f ¤   ¤   bniMul_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s,
12d448 ¤   ¤   ·································(BNWORD16 *)b->ptr, t);
879371 ¤   }
92022c ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, s+t);
194249 ¤   MALLOCDB;
0b3e6b ¤   return 0;
--cfbf 000177a43cd40100142 Page 8 of bn16.c
7aefe6 }
46af5a
c94d2f int
a901a4 bnMulQ_16(BigNum *dest, BigNum const *a, unsigned b)
3abb36 {
4482d0 ¤   unsigned s;
0aaf5a
710f7b ¤   s = bniNorm_16((BNWORD16 *)a->ptr, a->size);
1de348 ¤   if (!s || !b) {
65a7a3 ¤   ¤   dest->size = 0;
54bbde ¤   ¤   return 0;
be9371 ¤   }
24fe70 ¤   if (b == 1)
9d7fab ¤   ¤   return bnCopy_16(dest, a);
dcd21e ¤   bnSizeCheck(dest, s+1);
d75ae7 ¤   bniMulN1_16((BNWORD16 *)dest->ptr, (BNWORD16 *)a->ptr, s, b);
a47acc ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, s+1);
754249 ¤   MALLOCDB;
383e6b ¤   return 0;
88efe6 }
28af5a
6d4d2f int
de1e23 bnDivMod_16(BigNum *q, BigNum *r, BigNum const *n,
46c387 ············BigNum const *d)
23bb36 {
0fb221 ¤   unsigned dsize, nsize;
cd6744 ¤   BNWORD16 qhigh;
1eaf5a
75fefd ¤   dsize = bniNorm_16((BNWORD16 *)d->ptr, d->size);
46acdd ¤   nsize = bniNorm_16((BNWORD16 *)n->ptr, n->size);
2eaf5a
71b959 ¤   if (nsize < dsize) {
4fa365 ¤   ¤   q->size = 0;¤   /* No quotient */
321a91 ¤   ¤   r->size = nsize;
c41ef3 ¤   ¤   return 0;¤  /* Success */
3f9371 ¤   }
a2af5a
d4f25e ¤   bnSizeCheck(q, nsize-dsize);
86af5a
6b0a29 ¤   if (r != n) {¤  /* You are allowed to reduce in place */
d1e5de ¤   ¤   bnSizeCheck(r, nsize);
c390e7 ¤   ¤   bniCopy_16((BNWORD16 *)r->ptr, (BNWORD16 *)n->ptr, nsize);
ad9371 ¤   }
6e1b52 ¤   ¤
80bbed ¤   qhigh = bniDiv_16((BNWORD16 *)q->ptr, (BNWORD16 *)r->ptr, nsize,
3ab30a ¤   ··················(BNWORD16 *)d->ptr, dsize);
75169e ¤   nsize -= dsize;
f30152 ¤   if (qhigh) {
d0a056 ¤   ¤   bnSizeCheck(q, nsize+1);
85cfba ¤   ¤   *((BNWORD16 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
57936d ¤   ¤   q->size = nsize+1;
04f037 ¤   } else {
3e9c4b ¤   ¤   q->size = bniNorm_16((BNWORD16 *)q->ptr, nsize);
b99371 ¤   }
b9222b ¤   r->size = bniNorm_16((BNWORD16 *)r->ptr, dsize);
4d4249 ¤   MALLOCDB;
fe3e6b ¤   return 0;
43efe6 }
96af5a
3d4d2f int
5bb9fe bnMod_16(BigNum *dest, BigNum const *src, BigNum const *d)
d6bb36 {
deb221 ¤   unsigned dsize, nsize;
ceaf5a
36dadf ¤   nsize = bniNorm_16((BNWORD16 *)src->ptr, src->size);
4dfefd ¤   dsize = bniNorm_16((BNWORD16 *)d->ptr, d->size);
07af5a
26af5a
6791a5 ¤   if (dest != src) {
d6e35c ¤   ¤   bnSizeCheck(dest, nsize);
e2b958 ¤   ¤   bniCopy_16((BNWORD16 *)dest->ptr, (BNWORD16 *)src->ptr, nsize);
179371 ¤   }
--bcdd 0008c3faa2140100142 Page 9 of bn16.c
e0af5a
6db959 ¤   if (nsize < dsize) {
27b0f4 ¤   ¤   dest->size = nsize;¤/* No quotient */
b0bbde ¤   ¤   return 0;
d59371 ¤   }
54af5a
828252 ¤   (void)bniDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-dsize,+dsize),
1a71d3 ¤   ················(BNWORD16 *)dest->ptr, nsize,
3bd656 ¤   ················(BNWORD16 *)d->ptr, dsize);
2bb74e ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, dsize);
ec4249 ¤   MALLOCDB;
fd3e6b ¤   return 0;
1cefe6 }
44af5a
9c536c unsigned
a6b688 bnModQ_16(BigNum const *src, unsigned d)
b2bb36 {
da82d0 ¤   unsigned s;
46af5a
db6832 ¤   s = bniNorm_16((BNWORD16 *)src->ptr, src->size);
e5a2be ¤   if (!s)
0abbde ¤   ¤   return 0;
1367c5 ¤
e96350 ¤   if (d & (d-1))¤ /* Not a power of 2 */
b27f72 ¤   ¤   d = bniModQ_16((BNWORD16 *)src->ptr, s, d);
580e24 ¤   else
acffae ¤   ¤   d = (unsigned)((BNWORD16 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1);
fcdee9 ¤   return d;
d5efe6 }
32af5a
ed4d2f int
845061 bnExpMod_16(BigNum *dest, BigNum const *n,
c5769e ¤   BigNum const *exp, BigNum const *mod)
f0bb36 {
48f5f9 ¤   unsigned nsize, esize, msize;
d726cc ¤   PGPBoolean¤ ¤   secure;
f667c5 ¤
d944fc ¤   secure¤ = dest->isSecure || n->isSecure ||
1b1228 ¤   ¤   exp->isSecure || mod->isSecure;
70af5a
61acdd ¤   nsize = bniNorm_16((BNWORD16 *)n->ptr, n->size);
1c2dcb ¤   esize = bniNorm_16((BNWORD16 *)exp->ptr, exp->size);
33f7a8 ¤   msize = bniNorm_16((BNWORD16 *)mod->ptr, mod->size);
3daf5a
a110cb ¤   if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
eca4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
41af5a
6d5e84 ¤   bnSizeCheck(dest, msize);
60af5a
66dbab ¤   /* Special-case base of 2 */
13abbd ¤   if (nsize == 1 && ((BNWORD16 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
57de38 ¤   ¤   if (bniTwoExpMod_16( dest->mgr, secure,
3c7d88 ¤   ¤   ¤   ¤   ¤   (BNWORD16 *)dest->ptr,
09e381 ¤   ¤   ¤   ¤   ····(BNWORD16 *)exp->ptr, esize,
49c786 ¤   ¤   ¤   ¤   ····(BNWORD16 *)mod->ptr, msize) < 0)
333fd5 ¤   ¤   ¤   return -1;
c1f037 ¤   } else {
4f8579 ¤   ¤   if (bniExpMod_16( dest->mgr, secure,
47ec10 ¤   ¤   ¤   ¤   ¤   ¤   (BNWORD16 *)dest->ptr,
ddd19c ¤   ¤   ·················(BNWORD16 *)n->ptr, nsize,
8bbd73 ¤   ¤   ¤   ¤   ·(BNWORD16 *)exp->ptr, esize,
ae35fc ¤   ¤   ¤   ¤   ·(BNWORD16 *)mod->ptr, msize) < 0)
c0043c ¤   ¤   return -1;
7b9371 ¤   }
a9af5a
d41b4d ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, msize);
ce4249 ¤   MALLOCDB;
113e6b ¤   return 0;
5fefe6 }
69af5a
df4d2f int
8cec01 bnDoubleExpMod_16(BigNum *dest,
--1804 0001f81255340100142 Page 10 of bn16.c
25b250 ¤   BigNum const *n1, BigNum const *e1,
e10480 ¤   BigNum const *n2, BigNum const *e2,
a74699 ¤   BigNum const *mod)
b7bb36 {
6e93dc ¤   unsigned n1size, e1size, n2size, e2size, msize;
d126cc ¤   PGPBoolean¤ ¤   secure;
d867c5 ¤
5bcf25 ¤   secure¤ = dest->isSecure || n1->isSecure || e1->isSecure ||
4d3105 ¤   ¤   ¤   ¤   n2->isSecure || e2->isSecure || mod->isSecure;
50af5a
b1013c ¤   n1size = bniNorm_16((BNWORD16 *)n1->ptr, n1->size);
8d871d ¤   e1size = bniNorm_16((BNWORD16 *)e1->ptr, e1->size);
2ec65b ¤   n2size = bniNorm_16((BNWORD16 *)n2->ptr, n2->size);
a5407a ¤   e2size = bniNorm_16((BNWORD16 *)e2->ptr, e2->size);
b5f7a8 ¤   msize = bniNorm_16((BNWORD16 *)mod->ptr, mod->size);
76af5a
2010cb ¤   if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
64a4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
9faf5a
7e5e84 ¤   bnSizeCheck(dest, msize);
bdaf5a
9ca1e4 ¤   if (bniDoubleExpMod_16(
63e597 ¤   ¤   dest->mgr, secure,
01be48 ¤   ¤   (BNWORD16 *)dest->ptr,
78b96f ¤   ¤   (BNWORD16 *)n1->ptr, n1size, (BNWORD16 *)e1->ptr, e1size,
292dad ¤   ¤   (BNWORD16 *)n2->ptr, n2size, (BNWORD16 *)e2->ptr, e2size,
89131c ¤   ¤   (BNWORD16 *)mod->ptr, msize) < 0)
58043c ¤   ¤   return -1;
feaf5a
5a1b4d ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, msize);
8c4249 ¤   MALLOCDB;
d53e6b ¤   return 0;
73efe6 }
12af5a
334d2f int
99001a bnTwoExpMod_16(BigNum *n, BigNum const *exp,
e04699 ¤   BigNum const *mod)
dbbb36 {
a164a5 ¤   unsigned esize, msize;
6a673e ¤   PGPBoolean¤ secure¤ = n->isSecure || exp->isSecure || mod->isSecure;
7aaf5a
942dcb ¤   esize = bniNorm_16((BNWORD16 *)exp->ptr, exp->size);
84f7a8 ¤   msize = bniNorm_16((BNWORD16 *)mod->ptr, mod->size);
b6af5a
6d10cb ¤   if (!msize || (((BNWORD16 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
bda4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
2faf5a
14e89c ¤   bnSizeCheck(n, msize);
a3af5a
def804 ¤   if (bniTwoExpMod_16( n->mgr, secure,
29b75d ¤   ¤   ¤   ¤   (BNWORD16 *)n->ptr, (BNWORD16 *)exp->ptr, esize,
56375b ¤   ············(BNWORD16 *)mod->ptr, msize) < 0)
e8043c ¤   ¤   return -1;
aeaf5a
03484e ¤   n->size = bniNorm_16((BNWORD16 *)n->ptr, msize);
454249 ¤   MALLOCDB;
cb3e6b ¤   return 0;
a9efe6 }
f6af5a
a14d2f int
d27fc8 bnGcd_16(BigNum *dest, BigNum const *a, BigNum const *b)
87bb36 {
d56ef3 ¤   BNWORD16 *tmp;
3d8ee8 ¤   unsigned asize, bsize;
e84ba4 ¤   int i;
90f93f ¤   PGPBoolean¤ secure¤ = dest->isSecure || a->isSecure || b->isSecure;
9eaf5a
320824 ¤   /* Kind of silly, but we might as well permit it... */
ff1827 ¤   if (a == b)
e71266 ¤   ¤   return dest == a ? 0 : bnCopy(dest, a);
acaf5a
1f097b ¤   /* Ensure a is not the same as "dest" */
--da97 00013870a9640100142 Page 11 of bn16.c
2a0bb5 ¤   if (a == dest) {
687661 ¤   ¤   a = b;
1b3e03 ¤   ¤   b = dest;
539371 ¤   }
11af5a
2cd7ed ¤   asize = bniNorm_16((BNWORD16 *)a->ptr, a->size);
28cf1d ¤   bsize = bniNorm_16((BNWORD16 *)b->ptr, b->size);
1daf5a
2926a2 ¤   bnSizeCheck(dest, bsize+1);
61af5a
6ad672 ¤   /* Copy a to tmp */
10e4a2 ¤   BNIALLOC( dest->mgr, secure, tmp, BNWORD16, asize+1);
97da32 ¤   if (!tmp)
22043c ¤   ¤   return -1;
67902a ¤   bniCopy_16(tmp, (BNWORD16 *)a->ptr, asize);
a6af5a
276562 ¤   /* Copy b to dest, if necessary */
2ec9aa ¤   if (dest != b)
ac3d3e ¤   ¤   bniCopy_16((BNWORD16 *)dest->ptr,
14850f ¤   ¤   ¤   ···(BNWORD16 *)b->ptr, bsize);
72d29e ¤   if (bsize > asize || (bsize == asize &&
7c0eb2 ¤   ········bniCmp_16((BNWORD16 *)b->ptr, (BNWORD16 *)a->ptr, asize) > 0))
e1c7a1 ¤   {
586f25 ¤   ¤   i = bniGcd_16((BNWORD16 *)dest->ptr, bsize, tmp, asize,
942094 ¤   ¤   ¤   &dest->size);
99c640 ¤   ¤   if (i > 0)¤ /* Result in tmp, not dest */
f95981 ¤   ¤   ¤   bniCopy_16((BNWORD16 *)dest->ptr, tmp, dest->size);
a5f037 ¤   } else {
59ccdf ¤   ¤   i = bniGcd_16(tmp, asize, (BNWORD16 *)dest->ptr, bsize,
542094 ¤   ¤   ¤   &dest->size);
b9027d ¤   ¤   if (i == 0)¤/* Result in tmp, not dest */
385981 ¤   ¤   ¤   bniCopy_16((BNWORD16 *)dest->ptr, tmp, dest->size);
c99371 ¤   }
55eaf9 ¤   BNIFREE(tmp, asize+1);
f34249 ¤   MALLOCDB;
5515a5 ¤   return (i < 0) ? i : 0;
b6efe6 }
77af5a
454d2f int
0bf142 bnInv_16(BigNum *dest, BigNum const *src,
1b6b93 ·········BigNum const *mod)
2fbb36 {
d4e070 ¤   unsigned s, m;
844ba4 ¤   int i;
8b4382 ¤   PGPBoolean¤ secure;
3867c5 ¤
5e4500 ¤   secure¤ = dest->isSecure || src->isSecure || mod->isSecure;
55af5a
7c6832 ¤   s = bniNorm_16((BNWORD16 *)src->ptr, src->size);
52af88 ¤   m = bniNorm_16((BNWORD16 *)mod->ptr, mod->size);
deaf5a
d882b5 ¤   /* bniInv_16 requires that the input be less than the modulus */
560b4f ¤   if (m < s ||
0a2ea2 ¤   ····(m==s && bniCmp_16((BNWORD16 *)src->ptr, (BNWORD16 *)mod->ptr, s)))
fec7a1 ¤   {
32e1a3 ¤   ¤   bnSizeCheck(dest, s + (m==s));
edd0b6 ¤   ¤   if (dest != src)
0b04fb ¤   ¤   ¤   bniCopy_16((BNWORD16 *)dest->ptr,
bd6844 ¤   ¤   ¤   ···········(BNWORD16 *)src->ptr, s);
d42bbe ¤   ¤   /* Pre-reduce modulo the modulus */
1b5afb ¤   ¤   (void)bniDiv_16((BNWORD16 *)dest->ptr BIGLITTLE(-m,+m),
8d0e12 ¤   ¤   ¤   ········(BNWORD16 *)dest->ptr, s,
b56ade ¤   ¤   ················(BNWORD16 *)mod->ptr, m);
3e4200 ¤   ¤   s = bniNorm_16((BNWORD16 *)dest->ptr, m);
fdc7fc ¤   ¤   MALLOCDB;
74f037 ¤   } else {
f20452 ¤   ¤   bnSizeCheck(dest, m+1);
0dd0b6 ¤   ¤   if (dest != src)
0904fb ¤   ¤   ¤   bniCopy_16((BNWORD16 *)dest->ptr,
f76844 ¤   ¤   ¤   ···········(BNWORD16 *)src->ptr, s);
eb9371 ¤   }
13af5a
--f591 0002753c41840100142 Page 12 of bn16.c
9b10cb ¤   i = bniInv_16( ·dest->mgr, secure,
b48b8e ¤   ¤   ¤   (BNWORD16 *)dest->ptr, s, (BNWORD16 *)mod->ptr, m);
5d03c0 ¤   if (i == 0)
40ca81 ¤   ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, m);
68af5a
704249 ¤   MALLOCDB;
db2196 ¤   return i;
b7efe6 }
c4af5a
5238e5 /*
4eda51 ·* Shift a bignum left the appropriate number of bits,
7d8141 ·* multiplying by 2^amt.
26495d ·*/
48fcf4 int·
27f960 bnLShift_16(BigNum *dest, unsigned amt)
0ebb36 {
483b6a ¤   unsigned s = dest->size;
a24156 ¤   BNWORD16 carry;
21af5a
5c6e95 ¤   if (amt % 16) {
2c5f0e ¤   ¤   carry = bniLshift_16((BNWORD16 *)dest->ptr, s, amt % 16);
b4a2cc ¤   ¤   if (carry) {
107904 ¤   ¤   ¤   s++;
efc0e0 ¤   ¤   ¤   bnSizeCheck(dest, s);
b78cd6 ¤   ¤   ¤   ((BNWORD16 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
f00fe4 ¤   ¤   }
4d9371 ¤   }
5aaf5a
7e61a4 ¤   amt /= 16;
b6a187 ¤   if (amt) {
c0d404 ¤   ¤   bnSizeCheck(dest, s+amt);
fd7d14 ¤   ¤   memmove((BNWORD16 *)dest->ptr BIGLITTLE(-s-amt, +amt),
49cac6 ¤   ¤   ········(BNWORD16 *)dest->ptr BIG(-s),
bb19f5 ¤   ¤   ¤   s * sizeof(BNWORD16));
3cacb1 ¤   ¤   bniZero_16((BNWORD16 *)dest->ptr, amt);
074fb7 ¤   ¤   s += amt;
829371 ¤   }
ec3445 ¤   dest->size = s;
554249 ¤   MALLOCDB;
a23e6b ¤   return 0;
f1efe6 }
4daf5a
8138e5 /*
935b10 ·* Shift a bignum right the appropriate number of bits,
4564af ·* dividing by 2^amt.
7f495d ·*/
541758 void bnRShift_16(BigNum *dest, unsigned amt)
38bb36 {
2f3b6a ¤   unsigned s = dest->size;
b4af5a
2b89a7 ¤   if (amt >= 16) {
eb712d ¤   ¤   memmove(
db6f99 ¤   ¤   ········(BNWORD16 *)dest->ptr BIG(-s+amt/16),
4c5c1d ¤   ¤   ¤   (BNWORD16 *)dest->ptr BIGLITTLE(-s, +amt/16),
ebaa3c ¤   ¤   ¤   (s-amt/16) * sizeof(BNWORD16));
f78e0e ¤   ¤   s -= amt/16;
c66a50 ¤   ¤   amt %= 16;
2c9371 ¤   }
d5af5a
c22a0b ¤   if (amt)
8e4885 ¤   ¤   (void)bniRshift_16((BNWORD16 *)dest->ptr, s, amt);
c5af5a
e1a059 ¤   dest->size = bniNorm_16((BNWORD16 *)dest->ptr, s);
8f4249 ¤   MALLOCDB;
fbefe6 }
f2af5a
b938e5 /*
603c6d ·* Shift a bignum right until it is odd, and return the number of
89dd34 ·* bits shifted. ·n = d * 2^s. ·Replaces n with d and returns s.
133e8b ·* Returns 0 when given 0. ·(Another valid answer is infinity.)
07495d ·*/
27536c unsigned
--e9d8 001c490400840100142 Page 13 of bn16.c
d635ea bnMakeOdd_16(BigNum *n)
89bb36 {
6bc87c ¤   unsigned size;
97d5a0 ¤   unsigned s;¤/* shift amount */
db4ea9 ¤   BNWORD16 *p;
9adcba ¤   BNWORD16 t;
b7af5a
378407 ¤   p = (BNWORD16 *)n->ptr;
dd4b00 ¤   size = bniNorm_16(p, n->size);
a9faf0 ¤   if (!size)
babbde ¤   ¤   return 0;
d0af5a
f3f624 ¤   t = BIGLITTLE(p[-1],p[0]);
f4a3f2 ¤   s = 0;
0eaf5a
986e2d ¤   /* See how many words we have to shift */
97ddcd ¤   if (!t) {
ac0d12 ¤   ¤   /* Shift by words */
c24392 ¤   ¤   do {
da87c7 ¤   ¤   ¤
af7904 ¤   ¤   ¤   s++;
d623b9 ¤   ¤   ¤   BIGLITTLE(--p,p++);
80d20d ¤   ¤   } while ((t = BIGLITTLE(p[-1],p[0])) == 0);
ecb318 ¤   ¤   size -= s;
acdeb5 ¤   ¤   s *= 16;
65abe3 ¤   ¤   memmove((BNWORD16 *)n->ptr BIG(-size), p BIG(-size),
b68287 ¤   ¤   ¤   size * sizeof(BNWORD16));
f22959 ¤   ¤   p = (BNWORD16 *)n->ptr;
6ec7fc ¤   ¤   MALLOCDB;
739371 ¤   }
fcaf5a
622ef7 ¤   pgpAssert(t);
98af5a
16928f ¤   /* Now count the bits */
ae8d0d ¤   while ((t & 1) == 0) {
097abe ¤   ¤   t >>= 1;
dbcc95 ¤   ¤   s++;
c29371 ¤   }
edaf5a
61097d ¤   /* Shift the bits */
3bd698 ¤   if (s & (16-1)) {
2726ce ¤   ¤   bniRshift_16(p, size, s & (16-1));
310098 ¤   ¤   /* Renormalize */
57066b ¤   ¤   if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
a58bc2 ¤   ¤   ¤   --size;
cc9371 ¤   }
072c3e ¤   n->size = size;
f0af5a
294249 ¤   MALLOCDB;
ded779 ¤   return s;
c4efe6 }
--cdae 001251b10fc40100143 Page 1 of bn16.h
bc38e5 /*
ee5725 ·* bn16.h - interface to 16-bit bignum routines.
e1775e ·*
f1b6a9 ·* $Id: bn16.h,v 1.4 1997/05/13 01:18:33 mhw Exp $
f6495d ·*/
d3af5a
ba99c6 PGP_BEGIN_C_DECLARATIONS
70af5a
75bdbd #include "pgpBigNumOpaqueStructs.h"
32af5a
ceff77 void bnInit_16(void);
5bb866 void bnEnd_16(BigNum *bn);
404ec9 int bnPrealloc_16(BigNum *bn, unsigned bits);
3874a0 int bnCopy_16(BigNum *dest, BigNum const *src);
e68fe7 int bnSwap_16(BigNum *a, BigNum *b);
da6984 void bnNorm_16(BigNum *bn);
b7aa5d void bnExtractBigBytes_16(BigNum const *bn, unsigned char *dest,
f68dcb ¤   unsigned lsbyte, unsigned dlen);
c62cb6 int bnInsertBigBytes_16(BigNum *bn, unsigned char const *src,
3d3762 ¤   unsigned lsbyte, unsigned len);
42262b void bnExtractLittleBytes_16(BigNum const *bn, unsigned char *dest,
3c8dcb ¤   unsigned lsbyte, unsigned dlen);
023dc7 int bnInsertLittleBytes_16(BigNum *bn, unsigned char const *src,
5a3762 ¤   unsigned lsbyte, unsigned len);
e79dbc unsigned bnLSWord_16(BigNum const *src);
f16faa unsigned bnBits_16(BigNum const *src);
e94ef8 int bnAdd_16(BigNum *dest, BigNum const *src);
108541 int bnSub_16(BigNum *dest, BigNum const *src);
eb14cc int bnCmpQ_16(BigNum const *a, unsigned b);
9ef64c int bnSetQ_16(BigNum *dest, unsigned src);
ed0877 int bnAddQ_16(BigNum *dest, unsigned src);
c09f10 int bnSubQ_16(BigNum *dest, unsigned src);
9cb910 int bnCmp_16(BigNum const *a, BigNum const *b);
51454d int bnSquare_16(BigNum *dest, BigNum const *src);
fc0097 int bnMul_16(BigNum *dest, BigNum const *a,
599cfe ¤   BigNum const *b);
0c0c7f int bnMulQ_16(BigNum *dest, BigNum const *a, unsigned b);
9660c4 int bnDivMod_16(BigNum *q, BigNum *r, BigNum const *n,
17d764 ¤   BigNum const *d);
eb136c int bnMod_16(BigNum *dest, BigNum const *src,
d1d764 ¤   BigNum const *d);
2f1add unsigned bnModQ_16(BigNum const *src, unsigned d);
9de6c3 int bnExpMod_16(BigNum *dest, BigNum const *n,
287da1 ¤   BigNum const *exp, BigNum const *mod);
fa5e86 int bnDoubleExpMod_16(BigNum *dest,
8ab250 ¤   BigNum const *n1, BigNum const *e1,
030480 ¤   BigNum const *n2, BigNum const *e2,
b4092e ¤   BigNum const *mod);
c64ce8 int bnTwoExpMod_16(BigNum *n, BigNum const *exp,
b3092e ¤   BigNum const *mod);
a81194 int bnGcd_16(BigNum *dest, BigNum const *a,
d69cfe ¤   BigNum const *b);
88c0c1 int bnInv_16(BigNum *dest, BigNum const *src,
17092e ¤   BigNum const *mod);
2663ef int bnLShift_16(BigNum *dest, unsigned amt);
56defa void bnRShift_16(BigNum *dest, unsigned amt);
7259b5 unsigned bnMakeOdd_16(BigNum *n);
f7af5a
251254 PGP_END_C_DECLARATIONS
--f495 0003b5c486a40100144 Page 1 of bn32.c
bc38e5 /*
3c3988 ·* bn32.c - the high-level bignum interface
5e775e ·*
398c8d ·* Like bni32.c, this reserves the string "32" for textual replacement.
bcdd9c ·* The string must not appear anywhere unless it is intended to be replaced
04295d ·* to generate other bignum interface functions.
aa775e ·*
24fbf7 ·* Written by Colin Plumb
e7775e ·*
8ed5f4 ·* $Id: bn32.c,v 1.9.2.1 1998/10/22 19:49:31 heller Exp $
1f495d ·*/
a5af5a
3fe2ff #include "pgpConfig.h"
4faf5a
d238e5 /*
6b16cf ·* Some compilers complain about #if FOO if FOO isn't defined,
1659aa ·* so do the ANSI-mandated thing explicitly...
49495d ·*/
6cb552 #ifndef NO_STRING_H
a737dd #define NO_STRING_H 0
f07454 #endif
098537 #ifndef HAVE_STRINGS_H
75025c #define HAVE_STRINGS_H 0
3e7454 #endif
3e101b #ifndef NEED_MEMORY_H
b6ee50 #define NEED_MEMORY_H 0
257454 #endif
94af5a
fe7668 #if !NO_STRING_H
dff91c #include <string.h>¤/* for memmove() in bnMakeOdd */
1fa752 #elif HAVE_STRINGS_H
37f7c3 #include <strings.h>
667454 #endif
c63c37 #if NEED_MEMORY_H
e8c737 #include <memory.h>
057454 #endif
7caf5a
9038e5 /*
4cbe8a ·* This was useful during debugging, so it's left in here.
41954b ·* You can ignore it. ·DBMALLOC is generally undefined.
9f495d ·*/
bde178 #ifndef DBMALLOC
6415ee #define DBAMLLOC 0
a97454 #endif
b6deac #if DBMALLOC
a91594 #include "../dbmalloc/malloc.h"
964685 #define MALLOCDB malloc_chain_check(1)
a7db21 #else
37756d #define MALLOCDB (void)0
5f7454 #endif
e9af5a
b4a6ac #include "bni.h"
8410de #include "bni32.h"
5021db #include "bnimem.h"
02af57 #include "bn32.h"
ee39fc #include "bn.h"
95af5a
8765e3 /* Work-arounds for some particularly broken systems */
499ba2 #include "bnkludge.h"¤  /* For memmove() */
a8af5a
76a146 #include "pgpDebug.h"
7eaf5a
32ad60 /* Functions */
dc314a void
aed118 bnInit_32(void)
77bb36 {
a75ff8 ¤   bnEnd = bnEnd_32;
e5317d ¤   bnPrealloc = bnPrealloc_32;
c2fcba ¤   bnCopy = bnCopy_32;
b6f6a4 ¤   bnNorm = bnNorm_32;
a2b0e2 ¤   bnExtractBigBytes = bnExtractBigBytes_32;
3b85a5 ¤   bnInsertBigBytes = bnInsertBigBytes_32;
--8d22 00085d21b2a40100144 Page 2 of bn32.c
5407cf ¤   bnExtractLittleBytes = bnExtractLittleBytes_32;
7914fd ¤   bnInsertLittleBytes = bnInsertLittleBytes_32;
cdfcfe ¤   bnLSWord = bnLSWord_32;
369b0f ¤   bnBits = bnBits_32;
894935 ¤   bnAdd = bnAdd_32;
237ade ¤   bnSub = bnSub_32;
166f58 ¤   bnCmpQ = bnCmpQ_32;
8a8c93 ¤   bnSetQ = bnSetQ_32;
10625c ¤   bnAddQ = bnAddQ_32;
71afd5 ¤   bnSubQ = bnSubQ_32;
947978 ¤   bnCmp = bnCmp_32;
6433e0 ¤   bnSquare = bnSquare_32;
8d0418 ¤   bnMul = bnMul_32;
586a92 ¤   bnMulQ = bnMulQ_32;
19af2c ¤   bnDivMod = bnDivMod_32;
a5f57f ¤   bnMod = bnMod_32;
183196 ¤   bnModQ = bnModQ_32;
f083c3 ¤   bnExpMod = bnExpMod_32;
ec4928 ¤   bnDoubleExpMod = bnDoubleExpMod_32;
c6cda9 ¤   bnTwoExpMod = bnTwoExpMod_32;
775f08 ¤   bnGcd = bnGcd_32;
ea7dd9 ¤   bnInv = bnInv_32;
b4f901 ¤   bnLShift = bnLShift_32;
0589a3 ¤   bnRShift = bnRShift_32;
02cb7b ¤   bnMakeOdd = bnMakeOdd_32;
f3efe6 }
50af5a
ca314a void
d86387 bnEnd_32(BigNum *bn)
c0bb36 {
198780 ¤   if (bn->ptr) {
9e7271 ¤   ¤   BNIFREE((BNWORD32 *)bn->ptr, bn->allocated);
177d4e ¤   ¤   bn->ptr = 0;
d29371 ¤   }
1358d7 ¤   bn->size = 0;
da7222 ¤   bn->allocated = 0;
19af5a
f84249 ¤   MALLOCDB;
65efe6 }
a7af5a
76a782 /* Internal function. ·It operates in words. */
70beb7 static int
a3df1a bnResize_32(BigNum *bn, unsigned len)
37bb36 {
93141e ¤   void *p;
0eaf5a
213834 ¤   /* Round size up: most mallocs impose 8-byte granularity anyway */
5cabfd ¤   len = (len + (8/sizeof(BNWORD32) - 1)) & ~(8/sizeof(BNWORD32) - 1);
bce6c0 ¤   p = BNIREALLOC( bn->mgr, bn->isSecure,
f6c0f3 ¤   ¤   ¤   (BNWORD32 *)bn->ptr, bn->allocated, len);
b84dda ¤   if (!p)
f2043c ¤   ¤   return -1;
e13ab3 ¤   bn->ptr = p;
e6a26c ¤   bn->allocated = len;
a0af5a
5e4249 ¤   MALLOCDB;
eaaf5a
e43e6b ¤   return 0;
13efe6 }
23af5a
e64e7d #define bnSizeCheck(bn, size) \
488ed2 ¤   if (bn->allocated < size && bnResize_32(bn, size) < 0) \
123c44 ¤   ¤   return -1
ffaf5a
d24d2f int
c430ad bnPrealloc_32(BigNum *bn, unsigned bits)
0cbb36 {
ccd132 ¤   bits = (bits + 32-1)/32;
245fca ¤   bnSizeCheck(bn, bits);
a04249 ¤   MALLOCDB;
963e6b ¤   return 0;
85efe6 }
--7460 000b8cc4a2440100144 Page 3 of bn32.c
e0af5a
e54d2f int
8cedce bnCopy_32(BigNum *dest, BigNum const *src)
79bb36 {
758a1f ¤   bnSizeCheck(dest, src->size);
e25e12 ¤   dest->size = src->size;
86a7cc ¤   bniCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, src->size);
7c4249 ¤   MALLOCDB;
563e6b ¤   return 0;
f7efe6 }
fbaf5a
c4314a void
67e53d bnNorm_32(BigNum *bn)
a9bb36 {
3304e3 ¤   bn->size = bniNorm_32((BNWORD32 *)bn->ptr, bn->size);
8defe6 }
b7af5a
4938e5 /*
6c516a ·* Convert a bignum to big-endian bytes. ·Returns, in big-endian form, a
fdbbfe ·* substring of the bignum starting from lsbyte and "len" bytes long.
1c4f9d ·* Unused high-order (leading) bytes are filled with 0.
4b495d ·*/
5b314a void
344859 bnExtractBigBytes_32(BigNum const *bn, unsigned char *dest,
30baaa ··················unsigned lsbyte, unsigned len)
68bb36 {
ae226c ¤   unsigned s = bn->size * (32 / 8);
2eaf5a
b259b6 ¤   /* Fill unused leading bytes with 0 */
4b0077 ¤   while (s < lsbyte+len && len) {
1c6d4e ¤   ¤   *dest++ = 0;
eae1e8 ¤   ¤   len--;
c99371 ¤   }
b9af5a
764548 ¤   if (len)
3acee4 ¤   ¤   bniExtractBigBytes_32((BNWORD32 *)bn->ptr, dest, lsbyte, len);
544249 ¤   MALLOCDB;
1befe6 }
f8af5a
5d4d2f int
2538c2 bnInsertBigBytes_32(BigNum *bn, unsigned char const *src,
ce71b3 ·················unsigned lsbyte, unsigned len)
64bb36 {
90be7f ¤   unsigned s = bn->size;
9edcc7 ¤   unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32);
5daf5a
7e756a ¤   /* Pad with zeros as required */
55580e ¤   bnSizeCheck(bn, words);
cfaf5a
2f637b ¤   if (s < words) {
ba91c3 ¤   ¤   bniZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s);
cc2aa9 ¤   ¤   s = words;
b99371 ¤   }
6aaf5a
1f2476 ¤   bniInsertBigBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len);
c7af5a
24a820 ¤   bn->size = bniNorm_32((BNWORD32 *)bn->ptr, s);
e9af5a
ee4249 ¤   MALLOCDB;
383e6b ¤   return 0;
e1efe6 }
6baf5a
1caf5a
0638e5 /*
273ccd ·* Convert a bignum to little-endian bytes. ·Returns, in little-endian form, a
17bbfe ·* substring of the bignum starting from lsbyte and "len" bytes long.
7eb273 ·* Unused high-order (trailing) bytes are filled with 0.
a0495d ·*/
cc314a void
e7c41c bnExtractLittleBytes_32(BigNum const *bn, unsigned char *dest,
5ebaaa ··················unsigned lsbyte, unsigned len)
b8bb36 {
--de60 0002c02b20140100144 Page 4 of bn32.c
29226c ¤   unsigned s = bn->size * (32 / 8);
a6af5a
4959b6 ¤   /* Fill unused leading bytes with 0 */
a22317 ¤   while (s < lsbyte+len && len)
c35946 ¤   ¤   dest[--len] = 0;
23af5a
ca4548 ¤   if (len)
cd2795 ¤   ¤   bniExtractLittleBytes_32((BNWORD32 *)bn->ptr, dest,
b82bf3 ¤   ¤   ·························lsbyte, len);
124249 ¤   MALLOCDB;
c7efe6 }
9eaf5a
094d2f int
f09e46 bnInsertLittleBytes_32(BigNum *bn, unsigned char const *src,
573de8 ·······················unsigned lsbyte, unsigned len)
37bb36 {
d5be7f ¤   unsigned s = bn->size;
8bdcc7 ¤   unsigned words = (len+lsbyte+sizeof(BNWORD32)-1) / sizeof(BNWORD32);
39af5a
6f756a ¤   /* Pad with zeros as required */
2d580e ¤   bnSizeCheck(bn, words);
0aaf5a
2f637b ¤   if (s < words) {
c591c3 ¤   ¤   bniZero_32((BNWORD32 *)bn->ptr BIGLITTLE(-s,+s), words-s);
be2aa9 ¤   ¤   s = words;
869371 ¤   }
50af5a
fa487a ¤   bniInsertLittleBytes_32((BNWORD32 *)bn->ptr, src, lsbyte, len);
38af5a
8ba820 ¤   bn->size = bniNorm_32((BNWORD32 *)bn->ptr, s);
55af5a
cc4249 ¤   MALLOCDB;
6f3e6b ¤   return 0;
ddefe6 }
5eaf5a
7a03b4 /* Return the least-significant word of the input. */
2c536c unsigned
0ab519 bnLSWord_32(BigNum const *src)
3cbb36 {
4e34cc ¤   return src->size ? (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)]
7f0715 ¤   ¤   ¤   ·: 0;
a2efe6 }
b4af5a
a6536c unsigned
72b139 bnBits_32(BigNum const *src)
dcbb36 {
0d3128 ¤   return bniBits_32((BNWORD32 *)src->ptr, src->size);
ddefe6 }
5faf5a
194d2f int
cde964 bnAdd_32(BigNum *dest, BigNum const *src)
6dbb36 {
f3d27a ¤   unsigned s = src->size, d = dest->size;
59f9fc ¤   BNWORD32 t;
64af5a
50a2be ¤   if (!s)
43bbde ¤   ¤   return 0;
72af5a
5b7ebc ¤   bnSizeCheck(dest, s);
43af5a
57ab53 ¤   if (d < s) {
94fbef ¤   ¤   bniZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d);
5e8fbc ¤   ¤   dest->size = d = s;
31c7fc ¤   ¤   MALLOCDB;
a89371 ¤   }
e2acc3 ¤   t = bniAddN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
8b4249 ¤   MALLOCDB;
98dc81 ¤   if (t) {
9cdd63 ¤   ¤   if (d > s) {
1d17b5 ¤   ¤   ¤   t = bniAdd1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s),
7f911f ¤   ¤   ¤   ···············d-s, t);
2cfd66 ¤   ¤   ¤   MALLOCDB;
--fa55 0002f70d92940100144 Page 5 of bn32.c
b50fe4 ¤   ¤   }
636910 ¤   ¤   if (t) {
e8aadd ¤   ¤   ¤   bnSizeCheck(dest, d+1);
9dfe91 ¤   ¤   ¤   ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
cd14fd ¤   ¤   ¤   dest->size = d+1;
ba0fe4 ¤   ¤   }
4d9371 ¤   }
303e6b ¤   return 0;
25efe6 }
26af5a
6738e5 /*
98477d ·* dest -= src.
a5260a ·* If dest goes negative, this produces the absolute value of
ef2d02 ·* the difference (the negative of the true value) and returns 1.
127407 ·* Otherwise, it returls 0.
c7495d ·*/
ea4d2f int
533479 bnSub_32(BigNum *dest, BigNum const *src)
08bb36 {
a4d27a ¤   unsigned s = src->size, d = dest->size;
42f9fc ¤   BNWORD32 t;
61af5a
e048ad ¤   if (d < s ·&& ·d < (s = bniNorm_32((BNWORD32 *)src->ptr, s))) {
0df7e8 ¤   ¤   bnSizeCheck(dest, s);
7ffbef ¤   ¤   bniZero_32((BNWORD32 *)dest->ptr BIGLITTLE(-d,+d), s-d);
018fbc ¤   ¤   dest->size = d = s;
78c7fc ¤   ¤   MALLOCDB;
439371 ¤   }
38a2be ¤   if (!s)
d7bbde ¤   ¤   return 0;
259140 ¤   t = bniSubN_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
e34249 ¤   MALLOCDB;
addc81 ¤   if (t) {
23dd63 ¤   ¤   if (d > s) {
ca2c8d ¤   ¤   ¤   t = bniSub1_32((BNWORD32 *)dest->ptr BIGLITTLE(-s,+s),
58911f ¤   ¤   ¤   ···············d-s, t);
76fd66 ¤   ¤   ¤   MALLOCDB;
230fe4 ¤   ¤   }
0b6910 ¤   ¤   if (t) {
5878e1 ¤   ¤   ¤   bniNeg_32((BNWORD32 *)dest->ptr, d);
c3e76a ¤   ¤   ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr,
9cff67 ¤   ¤   ¤   ························dest->size);
05fd66 ¤   ¤   ¤   MALLOCDB;
c6db98 ¤   ¤   ¤   return 1;
5a0fe4 ¤   ¤   }
619371 ¤   }
d69786 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, dest->size);
f53e6b ¤   return 0;
4eefe6 }
f0af5a
6638e5 /*
9b8fa6 ·* Compare the BigNum to the given value, which must be < 65536.
22b0f5 ·* Returns -1. 0 or 1 if a<b, a == b or a>b.
d2b1d0 ·* a <=> b --> bnCmpQ(a,b) <=> 0
0f495d ·*/
544d2f int
022452 bnCmpQ_32(BigNum const *a, unsigned b)
fcbb36 {
bc0ed5 ¤   unsigned t;
624c44 ¤   BNWORD32 v;
e8af5a
787650 ¤   t = bniNorm_32((BNWORD32 *)a->ptr, a->size);
e98c5d ¤   /* If a is more than one word long or zero, it's easy... */
02cbfd ¤   if (t != 1)
db9178 ¤   ¤   return (t > 1) ? 1 : (b ? -1 : 0);
893ca7 ¤   v = (unsigned)((BNWORD32 *)a->ptr)[BIGLITTLE(-1,0)];
07b9fd ¤   return (v > b) ? 1 : ((v < b) ? -1 : 0);
87efe6 }
41af5a
894d2f int
7fbb2b bnSetQ_32(BigNum *dest, unsigned src)
2fbb36 {
--67b6 0008cd6fc9f40100144 Page 6 of bn32.c
f9d850 ¤   if (src) {
7fd829 ¤   ¤   bnSizeCheck(dest, 1);
c3af5a
d4ceb6 ¤   ¤   ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD32)src;
79fd7f ¤   ¤   dest->size = 1;
5bf037 ¤   } else {
65a7a3 ¤   ¤   dest->size = 0;
629371 ¤   }
7a3e6b ¤   return 0;
5eefe6 }
b1af5a
d04d2f int
f04742 bnAddQ_32(BigNum *dest, unsigned src)
dbbb36 {
6ef9fc ¤   BNWORD32 t;
00af5a
a9e656 ¤   if (!dest->size)
69798d ¤   ¤   return bnSetQ(dest, src);
3f67c5 ¤
cc8123 ¤   t = bniAdd1_32((BNWORD32 *)dest->ptr, dest->size, (BNWORD32)src);
0d4249 ¤   MALLOCDB;
1cdc81 ¤   if (t) {
356cb7 ¤   ¤   src = dest->size;
566dfe ¤   ¤   bnSizeCheck(dest, src+1);
2a323b ¤   ¤   ((BNWORD32 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
d4d25b ¤   ¤   dest->size = src+1;
e49371 ¤   }
423e6b ¤   return 0;
e7efe6 }
00af5a
2038e5 /*
f27f39 ·* Return value as for bnSub: 1 if subtract underflowed, in which
516059 ·* case the return is the negative of the computed value.
9b495d ·*/
b04d2f int
25b1e1 bnSubQ_32(BigNum *dest, unsigned src)
7ebb36 {
a2f9fc ¤   BNWORD32 t;
48af5a
1fe656 ¤   if (!dest->size)
5fd85e ¤   ¤   return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
46af5a
31db1e ¤   t = bniSub1_32((BNWORD32 *)dest->ptr, dest->size, src);
114249 ¤   MALLOCDB;
b0dc81 ¤   if (t) {
7a8587 ¤   ¤   /* Underflow. <= 1 word, so do it simply. */
de913d ¤   ¤   bniNeg_32((BNWORD32 *)dest->ptr, 1);
55fd7f ¤   ¤   dest->size = 1;
1ce102 ¤   ¤   return 1;
ad9371 ¤   }
95f754 /* Try to normalize? ·Needing this is going to be pretty damn rare. */
1c9a7c /*¤ ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, dest->size); */
853e6b ¤   return 0;
c4efe6 }
63af5a
6838e5 /*
7d4f98 ·* Compare two BigNums. ·Returns -1. 0 or 1 if a<b, a == b or a>b.
f66081 ·* a <=> b --> bnCmp(a,b) <=> 0
b0495d ·*/
0f4d2f int
16b06f bnCmp_32(BigNum const *a, BigNum const *b)
a1bb36 {
2af9fb ¤   unsigned s, t;
68af5a
c5f4f1 ¤   s = bniNorm_32((BNWORD32 *)a->ptr, a->size);
c00301 ¤   t = bniNorm_32((BNWORD32 *)b->ptr, b->size);
2a67c5 ¤
676838 ¤   if (s != t)
44ce46 ¤   ¤   return s > t ? 1 : -1;
5e044a ¤   return bniCmp_32((BNWORD32 *)a->ptr, (BNWORD32 *)b->ptr, s);
05efe6 }
8caf5a
--e3fd 000530447ab40100144 Page 7 of bn32.c
af4d2f int
a979ae bnSquare_32(BigNum *dest, BigNum const *src)
54bb36 {
5382d0 ¤   unsigned s;
265c7b ¤   BNWORD32 *srcbuf;
f1af5a
4f3c60 ¤   s = bniNorm_32((BNWORD32 *)src->ptr, src->size);
52ed11 ¤   if (!s) {
34a7a3 ¤   ¤   dest->size = 0;
b4bbde ¤   ¤   return 0;
ca9371 ¤   }
44f061 ¤   bnSizeCheck(dest, 2*s);
6eaf5a
7259de ¤   if (src == dest) {
566a5a ¤   ¤   BNIALLOC( src->mgr, src->isSecure, srcbuf, BNWORD32, s);
9448bf ¤   ¤   if (!srcbuf)
913fd5 ¤   ¤   ¤   return -1;
3d3333 ¤   ¤   bniCopy_32(srcbuf, (BNWORD32 *)src->ptr, s);
b8638a ¤   ¤   bniSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)srcbuf, s);
1e5788 ¤   ¤   BNIFREE(srcbuf, s);
2af037 ¤   } else {
397e75 ¤   ¤   bniSquare_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, s);
1e9371 ¤   }
80af5a
833d8f ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, 2*s);
ff4249 ¤   MALLOCDB;
ee3e6b ¤   return 0;
ceefe6 }
cdaf5a
114d2f int
d92a4f bnMul_32(BigNum *dest, BigNum const *a, BigNum const *b)
ffbb36 {
3cf9fb ¤   unsigned s, t;
7c5c7b ¤   BNWORD32 *srcbuf;
9df93f ¤   PGPBoolean¤ secure¤ = dest->isSecure || a->isSecure || b->isSecure;
21af5a
9cf4f1 ¤   s = bniNorm_32((BNWORD32 *)a->ptr, a->size);
000301 ¤   t = bniNorm_32((BNWORD32 *)b->ptr, b->size);
9caf5a
e46c90 ¤   if (!s || !t) {
21a7a3 ¤   ¤   dest->size = 0;
5cbbde ¤   ¤   return 0;
3d9371 ¤   }
30af5a
fb1827 ¤   if (a == b)
ffb60a ¤   ¤   return bnSquare_32(dest, a);
56af5a
e5aafe ¤   bnSizeCheck(dest, s+t);
57af5a
debfe3 ¤   if (dest == a) {
1daa45 ¤   ¤   BNIALLOC( dest->mgr, secure, srcbuf, BNWORD32, s);
f948bf ¤   ¤   if (!srcbuf)
183fd5 ¤   ¤   ¤   return -1;
f5f9bb ¤   ¤   bniCopy_32(srcbuf, (BNWORD32 *)a->ptr, s);
86a779 ¤   ¤   bniMul_32((BNWORD32 *)dest->ptr, srcbuf, s,
31dc34 ¤   ¤   ·································(BNWORD32 *)b->ptr, t);
0d5788 ¤   ¤   BNIFREE(srcbuf, s);
2584bc ¤   } else if (dest == b) {
20fd64 ¤   ¤   BNIALLOC( dest->mgr, secure, srcbuf, BNWORD32, t);
7448bf ¤   ¤   if (!srcbuf)
513fd5 ¤   ¤   ¤   return -1;
1c2974 ¤   ¤   bniCopy_32(srcbuf, (BNWORD32 *)b->ptr, t);
9d1fe1 ¤   ¤   bniMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
40322d ¤   ¤   ·································srcbuf, t);
0a00a9 ¤   ¤   BNIFREE(srcbuf, t);
e8f037 ¤   } else {
121fe1 ¤   ¤   bniMul_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s,
36dc34 ¤   ¤   ·································(BNWORD32 *)b->ptr, t);
749371 ¤   }
d16710 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, s+t);
164249 ¤   MALLOCDB;
533e6b ¤   return 0;
--4073 000c827569c40100144 Page 8 of bn32.c
7aefe6 }
46af5a
c94d2f int
b5cf95 bnMulQ_32(BigNum *dest, BigNum const *a, unsigned b)
3fbb36 {
1882d0 ¤   unsigned s;
81af5a
94f4f1 ¤   s = bniNorm_32((BNWORD32 *)a->ptr, a->size);
a3e348 ¤   if (!s || !b) {
43a7a3 ¤   ¤   dest->size = 0;
babbde ¤   ¤   return 0;
c39371 ¤   }
7ffe70 ¤   if (b == 1)
bc7187 ¤   ¤   return bnCopy_32(dest, a);
15d21e ¤   bnSizeCheck(dest, s+1);
0c8308 ¤   bniMulN1_32((BNWORD32 *)dest->ptr, (BNWORD32 *)a->ptr, s, b);
571ff0 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, s+1);
814249 ¤   MALLOCDB;
aa3e6b ¤   return 0;
baefe6 }
b5af5a
764d2f int
d53814 bnDivMod_32(BigNum *q, BigNum *r, BigNum const *n,
73c387 ············BigNum const *d)
7ebb36 {
8cb221 ¤   unsigned dsize, nsize;
6800ef ¤   BNWORD32 qhigh;
dcaf5a
fe0577 ¤   dsize = bniNorm_32((BNWORD32 *)d->ptr, d->size);
f95757 ¤   nsize = bniNorm_32((BNWORD32 *)n->ptr, n->size);
b3af5a
d6b959 ¤   if (nsize < dsize) {
3da365 ¤   ¤   q->size = 0;¤   /* No quotient */
651a91 ¤   ¤   r->size = nsize;
2e1ef3 ¤   ¤   return 0;¤  /* Success */
319371 ¤   }
06af5a
50f25e ¤   bnSizeCheck(q, nsize-dsize);
0faf5a
c90a29 ¤   if (r != n) {¤  /* You are allowed to reduce in place */
3ce5de ¤   ¤   bnSizeCheck(r, nsize);
23dc0d ¤   ¤   bniCopy_32((BNWORD32 *)r->ptr, (BNWORD32 *)n->ptr, nsize);
5f9371 ¤   }
501b52 ¤   ¤
642543 ¤   qhigh = bniDiv_32((BNWORD32 *)q->ptr, (BNWORD32 *)r->ptr, nsize,
a6b8b9 ¤   ··················(BNWORD32 *)d->ptr, dsize);
c4169e ¤   nsize -= dsize;
a30152 ¤   if (qhigh) {
28a056 ¤   ¤   bnSizeCheck(q, nsize+1);
ec4372 ¤   ¤   *((BNWORD32 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
fa936d ¤   ¤   q->size = nsize+1;
68f037 ¤   } else {
f8964d ¤   ¤   q->size = bniNorm_32((BNWORD32 *)q->ptr, nsize);
0d9371 ¤   }
68282d ¤   r->size = bniNorm_32((BNWORD32 *)r->ptr, dsize);
954249 ¤   MALLOCDB;
d13e6b ¤   return 0;
73efe6 }
88af5a
f94d2f int
97ceb0 bnMod_32(BigNum *dest, BigNum const *src, BigNum const *d)
08bb36 {
b1b221 ¤   unsigned dsize, nsize;
b8af5a
968e8d ¤   nsize = bniNorm_32((BNWORD32 *)src->ptr, src->size);
8a0577 ¤   dsize = bniNorm_32((BNWORD32 *)d->ptr, d->size);
d3af5a
f2af5a
ef91a5 ¤   if (dest != src) {
23e35c ¤   ¤   bnSizeCheck(dest, nsize);
10721d ¤   ¤   bniCopy_32((BNWORD32 *)dest->ptr, (BNWORD32 *)src->ptr, nsize);
c89371 ¤   }
--4e33 0009013642b40100144 Page 9 of bn32.c
e0af5a
6db959 ¤   if (nsize < dsize) {
27b0f4 ¤   ¤   dest->size = nsize;¤/* No quotient */
b0bbde ¤   ¤   return 0;
d59371 ¤   }
54af5a
6bc50b ¤   (void)bniDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-dsize,+dsize),
01df06 ¤   ················(BNWORD32 *)dest->ptr, nsize,
4ddde5 ¤   ················(BNWORD32 *)d->ptr, dsize);
bc9ce7 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, dsize);
eb4249 ¤   MALLOCDB;
953e6b ¤   return 0;
b8efe6 }
fdaf5a
59536c unsigned
111caf bnModQ_32(BigNum const *src, unsigned d)
bcbb36 {
9682d0 ¤   unsigned s;
31af5a
683c60 ¤   s = bniNorm_32((BNWORD32 *)src->ptr, src->size);
a4a2be ¤   if (!s)
64bbde ¤   ¤   return 0;
5567c5 ¤
8b6350 ¤   if (d & (d-1))¤ /* Not a power of 2 */
281a4e ¤   ¤   d = bniModQ_32((BNWORD32 *)src->ptr, s, d);
4e0e24 ¤   else
7bf2f9 ¤   ¤   d = (unsigned)((BNWORD32 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1);
fadee9 ¤   return d;
28efe6 }
baaf5a
6b4d2f int
7afa46 bnExpMod_32(BigNum *dest, BigNum const *n,
b4769e ¤   BigNum const *exp, BigNum const *mod)
40bb36 {
1af5f9 ¤   unsigned nsize, esize, msize;
ee26cc ¤   PGPBoolean¤ ¤   secure;
f967c5 ¤
4044fc ¤   secure¤ = dest->isSecure || n->isSecure ||
451228 ¤   ¤   exp->isSecure || mod->isSecure;
6eaf5a
8f5757 ¤   nsize = bniNorm_32((BNWORD32 *)n->ptr, n->size);
347999 ¤   esize = bniNorm_32((BNWORD32 *)exp->ptr, exp->size);
0aa3fa ¤   msize = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
80af5a
f155d1 ¤   if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
73a4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
29af5a
3e5e84 ¤   bnSizeCheck(dest, msize);
daaf5a
75dbab ¤   /* Special-case base of 2 */
390f62 ¤   if (nsize == 1 && ((BNWORD32 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
3b70ed ¤   ¤   if (bniTwoExpMod_32( dest->mgr, secure,
ad4100 ¤   ¤   ¤   ¤   ¤   (BNWORD32 *)dest->ptr,
ba649a ¤   ¤   ¤   ¤   ····(BNWORD32 *)exp->ptr, esize,
844e65 ¤   ¤   ¤   ¤   ····(BNWORD32 *)mod->ptr, msize) < 0)
433fd5 ¤   ¤   ¤   return -1;
d5f037 ¤   } else {
372bac ¤   ¤   if (bniExpMod_32( dest->mgr, secure,
93d098 ¤   ¤   ¤   ¤   ¤   ¤   (BNWORD32 *)dest->ptr,
f23a27 ¤   ¤   ·················(BNWORD32 *)n->ptr, nsize,
cb3a68 ¤   ¤   ¤   ¤   ·(BNWORD32 *)exp->ptr, esize,
07bc1f ¤   ¤   ¤   ¤   ·(BNWORD32 *)mod->ptr, msize) < 0)
04043c ¤   ¤   return -1;
cd9371 ¤   }
adaf5a
c530e4 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, msize);
5b4249 ¤   MALLOCDB;
9a3e6b ¤   return 0;
69efe6 }
11af5a
f14d2f int
90e47d bnDoubleExpMod_32(BigNum *dest,
--2249 00021524a1c40100144 Page 10 of bn32.c
25b250 ¤   BigNum const *n1, BigNum const *e1,
e10480 ¤   BigNum const *n2, BigNum const *e2,
a74699 ¤   BigNum const *mod)
b7bb36 {
6e93dc ¤   unsigned n1size, e1size, n2size, e2size, msize;
d126cc ¤   PGPBoolean¤ ¤   secure;
d867c5 ¤
5bcf25 ¤   secure¤ = dest->isSecure || n1->isSecure || e1->isSecure ||
4d3105 ¤   ¤   ¤   ¤   n2->isSecure || e2->isSecure || mod->isSecure;
50af5a
9e39dc ¤   n1size = bniNorm_32((BNWORD32 *)n1->ptr, n1->size);
68bffd ¤   e1size = bniNorm_32((BNWORD32 *)e1->ptr, e1->size);
abfebb ¤   n2size = bniNorm_32((BNWORD32 *)n2->ptr, n2->size);
09789a ¤   e2size = bniNorm_32((BNWORD32 *)e2->ptr, e2->size);
51a3fa ¤   msize = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
2faf5a
1855d1 ¤   if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
3ba4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
e9af5a
185e84 ¤   bnSizeCheck(dest, msize);
37af5a
ebfbf3 ¤   if (bniDoubleExpMod_32(
30e597 ¤   ¤   dest->mgr, secure,
ed82c0 ¤   ¤   (BNWORD32 *)dest->ptr,
02747a ¤   ¤   (BNWORD32 *)n1->ptr, n1size, (BNWORD32 *)e1->ptr, e1size,
aee0b8 ¤   ¤   (BNWORD32 *)n2->ptr, n2size, (BNWORD32 *)e2->ptr, e2size,
749aff ¤   ¤   (BNWORD32 *)mod->ptr, msize) < 0)
75043c ¤   ¤   return -1;
17af5a
db30e4 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, msize);
864249 ¤   MALLOCDB;
633e6b ¤   return 0;
71efe6 }
7eaf5a
614d2f int
8e5545 bnTwoExpMod_32(BigNum *n, BigNum const *exp,
2a4699 ¤   BigNum const *mod)
d5bb36 {
7964a5 ¤   unsigned esize, msize;
ee673e ¤   PGPBoolean¤ secure¤ = n->isSecure || exp->isSecure || mod->isSecure;
67af5a
b97999 ¤   esize = bniNorm_32((BNWORD32 *)exp->ptr, exp->size);
bda3fa ¤   msize = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
a2af5a
1f55d1 ¤   if (!msize || (((BNWORD32 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
5fa4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
17af5a
85e89c ¤   bnSizeCheck(n, msize);
10af5a
ed13bf ¤   if (bniTwoExpMod_32( n->mgr, secure,
781671 ¤   ¤   ¤   ¤   (BNWORD32 *)n->ptr, (BNWORD32 *)exp->ptr, esize,
cebeb8 ¤   ············(BNWORD32 *)mod->ptr, msize) < 0)
34043c ¤   ¤   return -1;
68af5a
e14248 ¤   n->size = bniNorm_32((BNWORD32 *)n->ptr, msize);
b94249 ¤   MALLOCDB;
873e6b ¤   return 0;
8defe6 }
62af5a
624d2f int
0235c6 bnGcd_32(BigNum *dest, BigNum const *a, BigNum const *b)
d2bb36 {
44e3d7 ¤   BNWORD32 *tmp;
cf8ee8 ¤   unsigned asize, bsize;
d24ba4 ¤   int i;
48f93f ¤   PGPBoolean¤ secure¤ = dest->isSecure || a->isSecure || b->isSecure;
42af5a
670824 ¤   /* Kind of silly, but we might as well permit it... */
701827 ¤   if (a == b)
c21266 ¤   ¤   return dest == a ? 0 : bnCopy(dest, a);
21af5a
21097b ¤   /* Ensure a is not the same as "dest" */
--6119 0008d5692e440100144 Page 11 of bn32.c
2a0bb5 ¤   if (a == dest) {
687661 ¤   ¤   a = b;
1b3e03 ¤   ¤   b = dest;
539371 ¤   }
11af5a
812c67 ¤   asize = bniNorm_32((BNWORD32 *)a->ptr, a->size);
c53497 ¤   bsize = bniNorm_32((BNWORD32 *)b->ptr, b->size);
ddaf5a
8526a2 ¤   bnSizeCheck(dest, bsize+1);
85af5a
d6d672 ¤   /* Copy a to tmp */
0e0fc2 ¤   BNIALLOC( dest->mgr, secure, tmp, BNWORD32, asize+1);
9cda32 ¤   if (!tmp)
5d043c ¤   ¤   return -1;
55fff2 ¤   bniCopy_32(tmp, (BNWORD32 *)a->ptr, asize);
73af5a
a96562 ¤   /* Copy b to dest, if necessary */
66c9aa ¤   if (dest != b)
c882eb ¤   ¤   bniCopy_32((BNWORD32 *)dest->ptr,
4d8ebc ¤   ¤   ¤   ···(BNWORD32 *)b->ptr, bsize);
15d29e ¤   if (bsize > asize || (bsize == asize &&
8be87f ¤   ········bniCmp_32((BNWORD32 *)b->ptr, (BNWORD32 *)a->ptr, asize) > 0))
8ac7a1 ¤   {
27477a ¤   ¤   i = bniGcd_32((BNWORD32 *)dest->ptr, bsize, tmp, asize,
462094 ¤   ¤   ¤   &dest->size);
acc640 ¤   ¤   if (i > 0)¤ /* Result in tmp, not dest */
704c38 ¤   ¤   ¤   bniCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size);
53f037 ¤   } else {
811f42 ¤   ¤   i = bniGcd_32(tmp, asize, (BNWORD32 *)dest->ptr, bsize,
d42094 ¤   ¤   ¤   &dest->size);
6e027d ¤   ¤   if (i == 0)¤/* Result in tmp, not dest */
724c38 ¤   ¤   ¤   bniCopy_32((BNWORD32 *)dest->ptr, tmp, dest->size);
eb9371 ¤   }
00eaf9 ¤   BNIFREE(tmp, asize+1);
bc4249 ¤   MALLOCDB;
d915a5 ¤   return (i < 0) ? i : 0;
a4efe6 }
ebaf5a
294d2f int
759529 bnInv_32(BigNum *dest, BigNum const *src,
e06b93 ·········BigNum const *mod)
0dbb36 {
9de070 ¤   unsigned s, m;
104ba4 ¤   int i;
084382 ¤   PGPBoolean¤ secure;
db67c5 ¤
b94500 ¤   secure¤ = dest->isSecure || src->isSecure || mod->isSecure;
30af5a
703c60 ¤   s = bniNorm_32((BNWORD32 *)src->ptr, src->size);
2ffbda ¤   m = bniNorm_32((BNWORD32 *)mod->ptr, mod->size);
99af5a
1759fb ¤   /* bniInv_32 requires that the input be less than the modulus */
070b4f ¤   if (m < s ||
980a1a ¤   ····(m==s && bniCmp_32((BNWORD32 *)src->ptr, (BNWORD32 *)mod->ptr, s)))
cac7a1 ¤   {
5ae1a3 ¤   ¤   bnSizeCheck(dest, s + (m==s));
4ed0b6 ¤   ¤   if (dest != src)
a6bb2e ¤   ¤   ¤   bniCopy_32((BNWORD32 *)dest->ptr,
b0bd68 ¤   ¤   ¤   ···········(BNWORD32 *)src->ptr, s);
aa2bbe ¤   ¤   /* Pre-reduce modulo the modulus */
bc4abe ¤   ¤   (void)bniDiv_32((BNWORD32 *)dest->ptr BIGLITTLE(-m,+m),
19db3e ¤   ¤   ¤   ········(BNWORD32 *)dest->ptr, s,
8abff2 ¤   ¤   ················(BNWORD32 *)mod->ptr, m);
0e14aa ¤   ¤   s = bniNorm_32((BNWORD32 *)dest->ptr, m);
d1c7fc ¤   ¤   MALLOCDB;
aef037 ¤   } else {
3e0452 ¤   ¤   bnSizeCheck(dest, m+1);
80d0b6 ¤   ¤   if (dest != src)
a9bb2e ¤   ¤   ¤   bniCopy_32((BNWORD32 *)dest->ptr,
8dbd68 ¤   ¤   ¤   ···········(BNWORD32 *)src->ptr, s);
5e9371 ¤   }
8daf5a
--c301 000304a2d3b40100144 Page 12 of bn32.c
429145 ¤   i = bniInv_32( ·dest->mgr, secure,
8a23ea ¤   ¤   ¤   (BNWORD32 *)dest->ptr, s, (BNWORD32 *)mod->ptr, m);
d703c0 ¤   if (i == 0)
b29c2b ¤   ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, m);
e2af5a
044249 ¤   MALLOCDB;
0c2196 ¤   return i;
d6efe6 }
d2af5a
9d38e5 /*
6cda51 ·* Shift a bignum left the appropriate number of bits,
a48141 ·* multiplying by 2^amt.
27495d ·*/
f1fcf4 int·
9bf8d5 bnLShift_32(BigNum *dest, unsigned amt)
afbb36 {
503b6a ¤   unsigned s = dest->size;
4526fd ¤   BNWORD32 carry;
31af5a
974bd3 ¤   if (amt % 32) {
7bb9a6 ¤   ¤   carry = bniLshift_32((BNWORD32 *)dest->ptr, s, amt % 32);
23a2cc ¤   ¤   if (carry) {
0c7904 ¤   ¤   ¤   s++;
a6c0e0 ¤   ¤   ¤   bnSizeCheck(dest, s);
9d3348 ¤   ¤   ¤   ((BNWORD32 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
cb0fe4 ¤   ¤   }
d69371 ¤   }
8caf5a
733bb3 ¤   amt /= 32;
f2a187 ¤   if (amt) {
5fd404 ¤   ¤   bnSizeCheck(dest, s+amt);
7c42c9 ¤   ¤   memmove((BNWORD32 *)dest->ptr BIGLITTLE(-s-amt, +amt),
3d4b48 ¤   ¤   ········(BNWORD32 *)dest->ptr BIG(-s),
0b3cb3 ¤   ¤   ¤   s * sizeof(BNWORD32));
3fc98d ¤   ¤   bniZero_32((BNWORD32 *)dest->ptr, amt);
8f4fb7 ¤   ¤   s += amt;
779371 ¤   }
b13445 ¤   dest->size = s;
344249 ¤   MALLOCDB;
683e6b ¤   return 0;
efefe6 }
5daf5a
9938e5 /*
625b10 ·* Shift a bignum right the appropriate number of bits,
b764af ·* dividing by 2^amt.
49495d ·*/
2016ed void bnRShift_32(BigNum *dest, unsigned amt)
30bb36 {
3d3b6a ¤   unsigned s = dest->size;
22af5a
03ace1 ¤   if (amt >= 32) {
d3712d ¤   ¤   memmove(
ca0a48 ¤   ¤   ········(BNWORD32 *)dest->ptr BIG(-s+amt/32),
1716a7 ¤   ¤   ¤   (BNWORD32 *)dest->ptr BIGLITTLE(-s, +amt/32),
0fe28d ¤   ¤   ¤   (s-amt/32) * sizeof(BNWORD32));
89d419 ¤   ¤   s -= amt/32;
7d3047 ¤   ¤   amt %= 32;
959371 ¤   }
67af5a
d82a0b ¤   if (amt)
947065 ¤   ¤   (void)bniRshift_32((BNWORD32 *)dest->ptr, s, amt);
6baf5a
e0f6f3 ¤   dest->size = bniNorm_32((BNWORD32 *)dest->ptr, s);
bc4249 ¤   MALLOCDB;
92efe6 }
a0af5a
3938e5 /*
203c6d ·* Shift a bignum right until it is odd, and return the number of
e7dd34 ·* bits shifted. ·n = d * 2^s. ·Replaces n with d and returns s.
d33e8b ·* Returns 0 when given 0. ·(Another valid answer is infinity.)
b7495d ·*/
30536c unsigned
--40a4 001e9c7604540100144 Page 13 of bn32.c
f7de8a bnMakeOdd_32(BigNum *n)
84bb36 {
bdc87c ¤   unsigned size;
c7d5a0 ¤   unsigned s;¤/* shift amount */
5069be ¤   BNWORD32 *p;
34f9fc ¤   BNWORD32 t;
58af5a
658a2b ¤   p = (BNWORD32 *)n->ptr;
777788 ¤   size = bniNorm_32(p, n->size);
c2faf0 ¤   if (!size)
34bbde ¤   ¤   return 0;
f0af5a
66f624 ¤   t = BIGLITTLE(p[-1],p[0]);
3ba3f2 ¤   s = 0;
cbaf5a
646e2d ¤   /* See how many words we have to shift */
a7ddcd ¤   if (!t) {
310d12 ¤   ¤   /* Shift by words */
c54392 ¤   ¤   do {
1587c7 ¤   ¤   ¤
617904 ¤   ¤   ¤   s++;
f723b9 ¤   ¤   ¤   BIGLITTLE(--p,p++);
4dd20d ¤   ¤   } while ((t = BIGLITTLE(p[-1],p[0])) == 0);
f0b318 ¤   ¤   size -= s;
4c84a2 ¤   ¤   s *= 32;
8f0f3c ¤   ¤   memmove((BNWORD32 *)n->ptr BIG(-size), p BIG(-size),
dea7c1 ¤   ¤   ¤   size * sizeof(BNWORD32));
f52775 ¤   ¤   p = (BNWORD32 *)n->ptr;
aac7fc ¤   ¤   MALLOCDB;
cb9371 ¤   }
68af5a
642ef7 ¤   pgpAssert(t);
77af5a
c4928f ¤   /* Now count the bits */
768d0d ¤   while ((t & 1) == 0) {
e17abe ¤   ¤   t >>= 1;
eccc95 ¤   ¤   s++;
679371 ¤   }
45af5a
2a097d ¤   /* Shift the bits */
bb5bbc ¤   if (s & (32-1)) {
7e2f20 ¤   ¤   bniRshift_32(p, size, s & (32-1));
990098 ¤   ¤   /* Renormalize */
76066b ¤   ¤   if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
498bc2 ¤   ¤   ¤   --size;
a29371 ¤   }
942c3e ¤   n->size = size;
44af5a
ce4249 ¤   MALLOCDB;
14d779 ¤   return s;
e9efe6 }
--49c6 001a14f614340100145 Page 1 of bn32.h
bc38e5 /*
a46935 ·* bn32.h - interface to 32-bit bignum routines.
e0775e ·*
7c74c6 ·* $Id: bn32.h,v 1.7 1998/05/14 19:07:18 cbertsch Exp $
e1495d ·*/
a8af5a
fe99c6 PGP_BEGIN_C_DECLARATIONS
73af5a
62bdbd #include "pgpBigNumOpaqueStructs.h"
9eaf5a
4598dc void bnInit_32(void);
2484ee void bnEnd_32(BigNum *bn);
014f7c int bnPrealloc_32(BigNum *bn, unsigned bits);
bca911 int bnCopy_32(BigNum *dest, BigNum const *src);
b10cba int bnSwap_32(BigNum *a, BigNum *b);
35550c void bnNorm_32(BigNum *bn);
db8c6a void bnExtractBigBytes_32(BigNum const *bn, unsigned char *dest,
288dcb ¤   unsigned lsbyte, unsigned dlen);
b721e1 int bnInsertBigBytes_32(BigNum *bn, unsigned char const *src,
693762 ¤   unsigned lsbyte, unsigned len);
b6001c void bnExtractLittleBytes_32(BigNum const *bn, unsigned char *dest,
f78dcb ¤   unsigned lsbyte, unsigned dlen);
fe3090 int bnInsertLittleBytes_32(BigNum *bn, unsigned char const *src,
a33762 ¤   unsigned lsbyte, unsigned len);
5c3369 unsigned bnLSWord_32(BigNum const *src);
9ac17f unsigned bnBits_32(BigNum const *src);
1e9349 int bnAdd_32(BigNum *dest, BigNum const *src);
7c58f0 int bnSub_32(BigNum *dest, BigNum const *src);
234193 int bnCmpQ_32(BigNum const *a, unsigned b);
27146b int bnSetQ_32(BigNum *dest, unsigned src);
82ea50 int bnAddQ_32(BigNum *dest, unsigned src);
ff7d37 int bnSubQ_32(BigNum *dest, unsigned src);
871dcf int bnCmp_32(BigNum const *a, BigNum const *b);
7798fc int bnSquare_32(BigNum *dest, BigNum const *src);
95aab0 int bnMul_32(BigNum *dest, BigNum const *a,
769cfe ¤   BigNum const *b);
a82cbb int bnMulQ_32(BigNum *dest, BigNum const *a, unsigned b);
4146f3 int bnDivMod_32(BigNum *q, BigNum *r, BigNum const *n,
a5d764 ¤   BigNum const *d);
927707 int bnMod_32(BigNum *dest, BigNum const *src,
5cd764 ¤   BigNum const *d);
6d4fca unsigned bnModQ_32(BigNum const *src, unsigned d);
b44ce4 int bnExpMod_32(BigNum *dest, BigNum const *n,
d27da1 ¤   BigNum const *exp, BigNum const *mod);
5456fa int bnDoubleExpMod_32(BigNum *dest,
38b250 ¤   BigNum const *n1, BigNum const *e1,
b20480 ¤   BigNum const *n2, BigNum const *e2,
b4092e ¤   BigNum const *mod);
0719b7 int bnTwoExpMod_32(BigNum *n, BigNum const *exp,
88092e ¤   BigNum const *mod);
e3bbb3 int bnGcd_32(BigNum *dest, BigNum const *a,
829cfe ¤   BigNum const *b);
fca4aa int bnInv_32(BigNum *dest, BigNum const *src,
92092e ¤   BigNum const *mod);
9081c8 int bnLShift_32(BigNum *dest, unsigned amt);
de3cdd void bnRShift_32(BigNum *dest, unsigned amt);
2a3a58 unsigned bnMakeOdd_32(BigNum *n);
ebaf5a
a11254 PGP_END_C_DECLARATIONS
--2159 0008ad6638e40100146 Page 1 of bn64.c
bc38e5 /*
08b64c ·* bn64.c - the high-level bignum interface
0b775e ·*
d4c6c8 ·* Like bni64.c, this reserves the string "64" for textual replacement.
6add9c ·* The string must not appear anywhere unless it is intended to be replaced
8e295d ·* to generate other bignum interface functions.
f0775e ·*
bcfbf7 ·* Written by Colin Plumb
a2775e ·*
b1b34f ·* $Id: bn64.c,v 1.12.2.1 1998/10/22 19:49:32 heller Exp $
ed495d ·*/
cfaf5a
16e2ff #include "pgpConfig.h"
8faf5a
8338e5 /*
1b16cf ·* Some compilers complain about #if FOO if FOO isn't defined,
e759aa ·* so do the ANSI-mandated thing explicitly...
54495d ·*/
b2b552 #ifndef NO_STRING_H
f537dd #define NO_STRING_H 0
7a7454 #endif
0d8537 #ifndef HAVE_STRINGS_H
32025c #define HAVE_STRINGS_H 0
5d7454 #endif
5c101b #ifndef NEED_MEMORY_H
ccee50 #define NEED_MEMORY_H 0
db7454 #endif
2daf5a
277668 #if !NO_STRING_H
2ff91c #include <string.h>¤/* for memmove() in bnMakeOdd */
eca752 #elif HAVE_STRINGS_H
c6f7c3 #include <strings.h>
af7454 #endif
f83c37 #if NEED_MEMORY_H
c0c737 #include <memory.h>
627454 #endif
34af5a
a838e5 /*
8dbe8a ·* This was useful during debugging, so it's left in here.
35954b ·* You can ignore it. ·DBMALLOC is generally undefined.
28495d ·*/
7ce178 #ifndef DBMALLOC
9a15ee #define DBAMLLOC 0
e27454 #endif
b6deac #if DBMALLOC
cc1594 #include "../dbmalloc/malloc.h"
e14685 #define MALLOCDB malloc_chain_check(1)
66db21 #else
5a756d #define MALLOCDB (void)0
0c7454 #endif
a9af5a
94a6ac #include "bni.h"
f83fc1 #include "bni64.h"
3821db #include "bnimem.h"
d98048 #include "bn64.h"
0939fc #include "bn.h"
16af5a
9565e3 /* Work-arounds for some particularly broken systems */
3a9ba2 #include "bnkludge.h"¤  /* For memmove() */
70af5a
a0a146 #include "pgpDebug.h"
54af5a
94ad60 /* Functions */
6b314a void
abbeb1 bnInit_64(void)
b8bb36 {
9ce776 ¤   bnEnd = bnEnd_64;
1589f3 ¤   bnPrealloc = bnPrealloc_64;
524434 ¤   bnCopy = bnCopy_64;
b34e2a ¤   bnNorm = bnNorm_64;
af086c ¤   bnExtractBigBytes = bnExtractBigBytes_64;
8a3d2b ¤   bnInsertBigBytes = bnInsertBigBytes_64;
--b921 000b823bf5b40100146 Page 2 of bn64.c
67bf41 ¤   bnExtractLittleBytes = bnExtractLittleBytes_64;
90ac73 ¤   bnInsertLittleBytes = bnInsertLittleBytes_64;
b54470 ¤   bnLSWord = bnLSWord_64;
da2381 ¤   bnBits = bnBits_64;
bff1bb ¤   bnAdd = bnAdd_64;
20c250 ¤   bnSub = bnSub_64;
7bd7d6 ¤   bnCmpQ = bnCmpQ_64;
da341d ¤   bnSetQ = bnSetQ_64;
84dad2 ¤   bnAddQ = bnAddQ_64;
97175b ¤   bnSubQ = bnSubQ_64;
4cc1f6 ¤   bnCmp = bnCmp_64;
548b6e ¤   bnSquare = bnSquare_64;
54bc96 ¤   bnMul = bnMul_64;
97d21c ¤   bnMulQ = bnMulQ_64;
2417a2 ¤   bnDivMod = bnDivMod_64;
384df1 ¤   bnMod = bnMod_64;
198918 ¤   bnModQ = bnModQ_64;
6b3b4d ¤   bnExpMod = bnExpMod_64;
9bf1a6 ¤   bnDoubleExpMod = bnDoubleExpMod_64;
f87527 ¤   bnTwoExpMod = bnTwoExpMod_64;
71e786 ¤   bnGcd = bnGcd_64;
dbc557 ¤   bnInv = bnInv_64;
0c418f ¤   bnLShift = bnLShift_64;
3f312d ¤   bnRShift = bnRShift_64;
0b73f5 ¤   bnMakeOdd = bnMakeOdd_64;
7eefe6 }
36af5a
88314a void
4d0d79 bnEnd_64(BigNum *bn)
0ebb36 {
5c8780 ¤   if (bn->ptr) {
d3d7ca ¤   ¤   BNIFREE((BNWORD64 *)bn->ptr, bn->allocated);
2c7d4e ¤   ¤   bn->ptr = 0;
4b9371 ¤   }
2f58d7 ¤   bn->size = 0;
dc7222 ¤   bn->allocated = 0;
19af5a
af4249 ¤   MALLOCDB;
baefe6 }
80af5a
f2a782 /* Internal function. ·It operates in words. */
06beb7 static int
966eba bnResize_64(BigNum *bn, unsigned len)
eebb36 {
8a141e ¤   void *p;
77af5a
cc3834 ¤   /* Round size up: most mallocs impose 8-byte granularity anyway */
fc1c9d ¤   len = (len + (8/sizeof(BNWORD64) - 1)) & ~(8/sizeof(BNWORD64) - 1);
0be6c0 ¤   p = BNIREALLOC( bn->mgr, bn->isSecure,
2815f1 ¤   ¤   ¤   (BNWORD64 *)bn->ptr, bn->allocated, len);
854dda ¤   if (!p)
0a043c ¤   ¤   return -1;
ea3ab3 ¤   bn->ptr = p;
82a26c ¤   bn->allocated = len;
66af5a
014249 ¤   MALLOCDB;
b8af5a
263e6b ¤   return 0;
4fefe6 }
56af5a
8b4e7d #define bnSizeCheck(bn, size) \
db476a ¤   if (bn->allocated < size && bnResize_64(bn, size) < 0) \
8f3c44 ¤   ¤   return -1
b7af5a
a44d2f int
ae9516 bnPrealloc_64(BigNum *bn, unsigned bits)
81bb36 {
325118 ¤   bits = (bits + 64-1)/64;
025fca ¤   bnSizeCheck(bn, bits);
fb4249 ¤   MALLOCDB;
7e3e6b ¤   return 0;
b8efe6 }
--13c6 000548c613740100146 Page 3 of bn64.c
e0af5a
e54d2f int
edce09 bnCopy_64(BigNum *dest, BigNum const *src)
1bbb36 {
bf8a1f ¤   bnSizeCheck(dest, src->size);
c85e12 ¤   dest->size = src->size;
6f0f2a ¤   bniCopy_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, src->size);
1c4249 ¤   MALLOCDB;
653e6b ¤   return 0;
42efe6 }
85af5a
7b314a void
838bc3 bnNorm_64(BigNum *bn)
80bb36 {
7717ff ¤   bn->size = bniNorm_64((BNWORD64 *)bn->ptr, bn->size);
85efe6 }
f8af5a
6138e5 /*
11516a ·* Convert a bignum to big-endian bytes. ·Returns, in big-endian form, a
60bbfe ·* substring of the bignum starting from lsbyte and "len" bytes long.
634f9d ·* Unused high-order (leading) bytes are filled with 0.
92495d ·*/
c4314a void
602ea6 bnExtractBigBytes_64(BigNum const *bn, unsigned char *dest,
04baaa ··················unsigned lsbyte, unsigned len)
bcbb36 {
534dc5 ¤   unsigned s = bn->size * (64 / 8);
14af5a
e459b6 ¤   /* Fill unused leading bytes with 0 */
520077 ¤   while (s < lsbyte+len && len) {
ca6d4e ¤   ¤   *dest++ = 0;
42e1e8 ¤   ¤   len--;
219371 ¤   }
0caf5a
684548 ¤   if (len)
7ba0f7 ¤   ¤   bniExtractBigBytes_64((BNWORD64 *)bn->ptr, dest, lsbyte, len);
ff4249 ¤   MALLOCDB;
76efe6 }
f3af5a
894d2f int
82e9f7 bnInsertBigBytes_64(BigNum *bn, unsigned char const *src,
a071b3 ·················unsigned lsbyte, unsigned len)
ebbb36 {
7fbe7f ¤   unsigned s = bn->size;
b31db2 ¤   unsigned words = (len+lsbyte+sizeof(BNWORD64)-1) / sizeof(BNWORD64);
8aaf5a
54756a ¤   /* Pad with zeros as required */
c7580e ¤   bnSizeCheck(bn, words);
29af5a
a6637b ¤   if (s < words) {
d03277 ¤   ¤   bniZero_64((BNWORD64 *)bn->ptr BIGLITTLE(-s,+s), words-s);
342aa9 ¤   ¤   s = words;
c99371 ¤   }
f9af5a
0e59cb ¤   bniInsertBigBytes_64((BNWORD64 *)bn->ptr, src, lsbyte, len);
32af5a
96c0be ¤   bn->size = bniNorm_64((BNWORD64 *)bn->ptr, s);
6eaf5a
684249 ¤   MALLOCDB;
b53e6b ¤   return 0;
cfefe6 }
37af5a
d3af5a
8a38e5 /*
5d3ccd ·* Convert a bignum to little-endian bytes. ·Returns, in little-endian form, a
0fbbfe ·* substring of the bignum starting from lsbyte and "len" bytes long.
21b273 ·* Unused high-order (trailing) bytes are filled with 0.
b8495d ·*/
87314a void
0ca2e3 bnExtractLittleBytes_64(BigNum const *bn, unsigned char *dest,
5ebaaa ··················unsigned lsbyte, unsigned len)
54bb36 {
--0343 000a2e503df40100146 Page 4 of bn64.c
a54dc5 ¤   unsigned s = bn->size * (64 / 8);
33af5a
b859b6 ¤   /* Fill unused leading bytes with 0 */
3c2317 ¤   while (s < lsbyte+len && len)
f45946 ¤   ¤   dest[--len] = 0;
85af5a
b34548 ¤   if (len)
9b4b96 ¤   ¤   bniExtractLittleBytes_64((BNWORD64 *)bn->ptr, dest,
0c2bf3 ¤   ¤   ·························lsbyte, len);
c74249 ¤   MALLOCDB;
0defe6 }
c7af5a
574d2f int
224f73 bnInsertLittleBytes_64(BigNum *bn, unsigned char const *src,
c03de8 ·······················unsigned lsbyte, unsigned len)
23bb36 {
cfbe7f ¤   unsigned s = bn->size;
111db2 ¤   unsigned words = (len+lsbyte+sizeof(BNWORD64)-1) / sizeof(BNWORD64);
f0af5a
c1756a ¤   /* Pad with zeros as required */
68580e ¤   bnSizeCheck(bn, words);
07af5a
cf637b ¤   if (s < words) {
093277 ¤   ¤   bniZero_64((BNWORD64 *)bn->ptr BIGLITTLE(-s,+s), words-s);
ae2aa9 ¤   ¤   s = words;
359371 ¤   }
4faf5a
a435c7 ¤   bniInsertLittleBytes_64((BNWORD64 *)bn->ptr, src, lsbyte, len);
d2af5a
26c0be ¤   bn->size = bniNorm_64((BNWORD64 *)bn->ptr, s);
f7af5a
2e4249 ¤   MALLOCDB;
063e6b ¤   return 0;
abefe6 }
28af5a
eb03b4 /* Return the least-significant word of the input. */
8e536c unsigned
c01a7a bnLSWord_64(BigNum const *src)
56bb36 {
6d18ad ¤   return src->size ? (unsigned)((BNWORD64 *)src->ptr)[BIGLITTLE(-1,0)]
d60715 ¤   ¤   ¤   ·: 0;
beefe6 }
09af5a
54536c unsigned
751e5a bnBits_64(BigNum const *src)
e1bb36 {
682f03 ¤   return bniBits_64((BNWORD64 *)src->ptr, src->size);
5cefe6 }
67af5a
f04d2f int
72caa3 bnAdd_64(BigNum *dest, BigNum const *src)
0cbb36 {
bdd27a ¤   unsigned s = src->size, d = dest->size;
6dd6e3 ¤   BNWORD64 t;
a0af5a
aba2be ¤   if (!s)
84bbde ¤   ¤   return 0;
3daf5a
7d7ebc ¤   bnSizeCheck(dest, s);
7caf5a
c4ab53 ¤   if (d < s) {
d365c5 ¤   ¤   bniZero_64((BNWORD64 *)dest->ptr BIGLITTLE(-d,+d), s-d);
9c8fbc ¤   ¤   dest->size = d = s;
14c7fc ¤   ¤   MALLOCDB;
279371 ¤   }
0793f0 ¤   t = bniAddN_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, s);
ac4249 ¤   MALLOCDB;
b4dc81 ¤   if (t) {
efdd63 ¤   ¤   if (d > s) {
366a08 ¤   ¤   ¤   t = bniAdd1_64((BNWORD64 *)dest->ptr BIGLITTLE(-s,+s),
6a911f ¤   ¤   ¤   ···············d-s, t);
a2fd66 ¤   ¤   ¤   MALLOCDB;
--ffa2 000e87389b940100146 Page 5 of bn64.c
b50fe4 ¤   ¤   }
636910 ¤   ¤   if (t) {
e8aadd ¤   ¤   ¤   bnSizeCheck(dest, d+1);
9e7e36 ¤   ¤   ¤   ((BNWORD64 *)dest->ptr)[BIGLITTLE(-1-d,d)] = t;
b914fd ¤   ¤   ¤   dest->size = d+1;
b50fe4 ¤   ¤   }
e99371 ¤   }
1a3e6b ¤   return 0;
b5efe6 }
0daf5a
a438e5 /*
32477d ·* dest -= src.
27260a ·* If dest goes negative, this produces the absolute value of
5a2d02 ·* the difference (the negative of the true value) and returns 1.
0b7407 ·* Otherwise, it returls 0.
17495d ·*/
684d2f int
7c17be bnSub_64(BigNum *dest, BigNum const *src)
f2bb36 {
3ad27a ¤   unsigned s = src->size, d = dest->size;
a9d6e3 ¤   BNWORD64 t;
09af5a
69cbaf ¤   if (d < s ·&& ·d < (s = bniNorm_64((BNWORD64 *)src->ptr, s))) {
7cf7e8 ¤   ¤   bnSizeCheck(dest, s);
b965c5 ¤   ¤   bniZero_64((BNWORD64 *)dest->ptr BIGLITTLE(-d,+d), s-d);
b08fbc ¤   ¤   dest->size = d = s;
98c7fc ¤   ¤   MALLOCDB;
949371 ¤   }
22a2be ¤   if (!s)
a5bbde ¤   ¤   return 0;
50ae73 ¤   t = bniSubN_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, s);
7c4249 ¤   MALLOCDB;
13dc81 ¤   if (t) {
f8dd63 ¤   ¤   if (d > s) {
de5130 ¤   ¤   ¤   t = bniSub1_64((BNWORD64 *)dest->ptr BIGLITTLE(-s,+s),
87911f ¤   ¤   ¤   ···············d-s, t);
49fd66 ¤   ¤   ¤   MALLOCDB;
e30fe4 ¤   ¤   }
7c6910 ¤   ¤   if (t) {
7f14e2 ¤   ¤   ¤   bniNeg_64((BNWORD64 *)dest->ptr, d);
8400cc ¤   ¤   ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr,
aeff67 ¤   ¤   ¤   ························dest->size);
69fd66 ¤   ¤   ¤   MALLOCDB;
21db98 ¤   ¤   ¤   return 1;
1d0fe4 ¤   ¤   }
829371 ¤   }
3fa9e2 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, dest->size);
8f3e6b ¤   return 0;
2aefe6 }
caaf5a
4638e5 /*
828fa6 ·* Compare the BigNum to the given value, which must be < 65536.
1eb0f5 ·* Returns -1. 0 or 1 if a<b, a == b or a>b.
0bb1d0 ·* a <=> b --> bnCmpQ(a,b) <=> 0
ef495d ·*/
e64d2f int
f60833 bnCmpQ_64(BigNum const *a, unsigned b)
77bb36 {
ac0ed5 ¤   unsigned t;
34635b ¤   BNWORD64 v;
32af5a
c655c1 ¤   t = bniNorm_64((BNWORD64 *)a->ptr, a->size);
618c5d ¤   /* If a is more than one word long or zero, it's easy... */
75cbfd ¤   if (t != 1)
fa9178 ¤   ¤   return (t > 1) ? 1 : (b ? -1 : 0);
6d375a ¤   v = (unsigned)((BNWORD64 *)a->ptr)[BIGLITTLE(-1,0)];
54b9fd ¤   return (v > b) ? 1 : ((v < b) ? -1 : 0);
78efe6 }
55af5a
1b4d2f int
3cb0d6 bnSetQ_64(BigNum *dest, unsigned src)
e8bb36 {
--47b3 0002f13776040100146 Page 6 of bn64.c
f9d850 ¤   if (src) {
7fd829 ¤   ¤   bnSizeCheck(dest, 1);
c3af5a
930f7b ¤   ¤   ((BNWORD64 *)dest->ptr)[BIGLITTLE(-1,0)] = (BNWORD64)src;
4efd7f ¤   ¤   dest->size = 1;
79f037 ¤   } else {
73a7a3 ¤   ¤   dest->size = 0;
9a9371 ¤   }
d93e6b ¤   return 0;
b0efe6 }
e5af5a
884d2f int
084cbf bnAddQ_64(BigNum *dest, unsigned src)
f6bb36 {
4ed6e3 ¤   BNWORD64 t;
8eaf5a
29e656 ¤   if (!dest->size)
7a798d ¤   ¤   return bnSetQ(dest, src);
3467c5 ¤
72823e ¤   t = bniAdd1_64((BNWORD64 *)dest->ptr, dest->size, (BNWORD64)src);
eb4249 ¤   MALLOCDB;
c5dc81 ¤   if (t) {
226cb7 ¤   ¤   src = dest->size;
dc6dfe ¤   ¤   bnSizeCheck(dest, src+1);
8ecbcb ¤   ¤   ((BNWORD64 *)dest->ptr)[BIGLITTLE(-1-src,src)] = t;
45d25b ¤   ¤   dest->size = src+1;
b29371 ¤   }
c33e6b ¤   return 0;
3eefe6 }
66af5a
b238e5 /*
517f39 ·* Return value as for bnSub: 1 if subtract underflowed, in which
2e6059 ·* case the return is the negative of the computed value.
c0495d ·*/
bc4d2f int
b6ba1c bnSubQ_64(BigNum *dest, unsigned src)
c6bb36 {
e2d6e3 ¤   BNWORD64 t;
4eaf5a
1ae656 ¤   if (!dest->size)
71d85e ¤   ¤   return bnSetQ(dest, src) < 0 ? -1 : (src != 0);
cbaf5a
80b50d ¤   t = bniSub1_64((BNWORD64 *)dest->ptr, dest->size, src);
8d4249 ¤   MALLOCDB;
39dc81 ¤   if (t) {
4f8587 ¤   ¤   /* Underflow. <= 1 word, so do it simply. */
b2fd3e ¤   ¤   bniNeg_64((BNWORD64 *)dest->ptr, 1);
dafd7f ¤   ¤   dest->size = 1;
cce102 ¤   ¤   return 1;
0a9371 ¤   }
52f754 /* Try to normalize? ·Needing this is going to be pretty damn rare. */
3cd0e2 /*¤ ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, dest->size); */
aa3e6b ¤   return 0;
8defe6 }
c1af5a
f238e5 /*
9f4f98 ·* Compare two BigNums. ·Returns -1. 0 or 1 if a<b, a == b or a>b.
b46081 ·* a <=> b --> bnCmp(a,b) <=> 0
bb495d ·*/
1d4d2f int
6002ff bnCmp_64(BigNum const *a, BigNum const *b)
1cbb36 {
34f9fb ¤   unsigned s, t;
3daf5a
16d760 ¤   s = bniNorm_64((BNWORD64 *)a->ptr, a->size);
1c2090 ¤   t = bniNorm_64((BNWORD64 *)b->ptr, b->size);
7067c5 ¤
b86838 ¤   if (s != t)
8dce46 ¤   ¤   return s > t ? 1 : -1;
05fd9e ¤   return bniCmp_64((BNWORD64 *)a->ptr, (BNWORD64 *)b->ptr, s);
7cefe6 }
2faf5a
--41ff 000b99c0b9f40100146 Page 7 of bn64.c
af4d2f int
c85a69 bnSquare_64(BigNum *dest, BigNum const *src)
36bb36 {
8982d0 ¤   unsigned s;
e8292f ¤   BNWORD64 *srcbuf;
e0af5a
b0224b ¤   s = bniNorm_64((BNWORD64 *)src->ptr, src->size);
0fed11 ¤   if (!s) {
65a7a3 ¤   ¤   dest->size = 0;
cabbde ¤   ¤   return 0;
2d9371 ¤   }
f8f061 ¤   bnSizeCheck(dest, 2*s);
26af5a
1d59de ¤   if (src == dest) {
63a5f6 ¤   ¤   BNIALLOC( src->mgr, src->isSecure, srcbuf, BNWORD64, s);
5b48bf ¤   ¤   if (!srcbuf)
f03fd5 ¤   ¤   ¤   return -1;
694d9c ¤   ¤   bniCopy_64(srcbuf, (BNWORD64 *)src->ptr, s);
9e812c ¤   ¤   bniSquare_64((BNWORD64 *)dest->ptr, (BNWORD64 *)srcbuf, s);
415788 ¤   ¤   BNIFREE(srcbuf, s);
baf037 ¤   } else {
e54146 ¤   ¤   bniSquare_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, s);
b09371 ¤   }
69af5a
d8be8d ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, 2*s);
ff4249 ¤   MALLOCDB;
1c3e6b ¤   return 0;
46efe6 }
9faf5a
664d2f int
7158ce bnMul_64(BigNum *dest, BigNum const *a, BigNum const *b)
5ebb36 {
eff9fb ¤   unsigned s, t;
cf292f ¤   BNWORD64 *srcbuf;
ddf93f ¤   PGPBoolean¤ secure¤ = dest->isSecure || a->isSecure || b->isSecure;
bbaf5a
b5d760 ¤   s = bniNorm_64((BNWORD64 *)a->ptr, a->size);
6f2090 ¤   t = bniNorm_64((BNWORD64 *)b->ptr, b->size);
f0af5a
166c90 ¤   if (!s || !t) {
45a7a3 ¤   ¤   dest->size = 0;
a0bbde ¤   ¤   return 0;
9a9371 ¤   }
4aaf5a
121827 ¤   if (a == b)
85a2de ¤   ¤   return bnSquare_64(dest, a);
50af5a
e6aafe ¤   bnSizeCheck(dest, s+t);
1aaf5a
bfbfe3 ¤   if (dest == a) {
1f65e9 ¤   ¤   BNIALLOC( dest->mgr, secure, srcbuf, BNWORD64, s);
b148bf ¤   ¤   if (!srcbuf)
983fd5 ¤   ¤   ¤   return -1;
ae40d9 ¤   ¤   bniCopy_64(srcbuf, (BNWORD64 *)a->ptr, s);
5bb952 ¤   ¤   bniMul_64((BNWORD64 *)dest->ptr, srcbuf, s,
4db054 ¤   ¤   ·································(BNWORD64 *)b->ptr, t);
535788 ¤   ¤   BNIFREE(srcbuf, s);
d984bc ¤   } else if (dest == b) {
4332c8 ¤   ¤   BNIALLOC( dest->mgr, secure, srcbuf, BNWORD64, t);
9448bf ¤   ¤   if (!srcbuf)
e63fd5 ¤   ¤   ¤   return -1;
219016 ¤   ¤   bniCopy_64(srcbuf, (BNWORD64 *)b->ptr, t);
339f54 ¤   ¤   bniMul_64((BNWORD64 *)dest->ptr, (BNWORD64 *)a->ptr, s,
5a322d ¤   ¤   ·································srcbuf, t);
2c00a9 ¤   ¤   BNIFREE(srcbuf, t);
62f037 ¤   } else {
279f54 ¤   ¤   bniMul_64((BNWORD64 *)dest->ptr, (BNWORD64 *)a->ptr, s,
e7b054 ¤   ¤   ·································(BNWORD64 *)b->ptr, t);
319371 ¤   }
cbe412 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, s+t);
454249 ¤   MALLOCDB;
b93e6b ¤   return 0;
--f324 00042574e3540100146 Page 8 of bn64.c
7aefe6 }
46af5a
c94d2f int
91d9d3 bnMulQ_64(BigNum *dest, BigNum const *a, unsigned b)
58bb36 {
fe82d0 ¤   unsigned s;
fbaf5a
87d760 ¤   s = bniNorm_64((BNWORD64 *)a->ptr, a->size);
4ae348 ¤   if (!s || !b) {
19a7a3 ¤   ¤   dest->size = 0;
93bbde ¤   ¤   return 0;
b19371 ¤   }
84fe70 ¤   if (b == 1)
406553 ¤   ¤   return bnCopy_64(dest, a);
aed21e ¤   bnSizeCheck(dest, s+1);
3c802f ¤   bniMulN1_64((BNWORD64 *)dest->ptr, (BNWORD64 *)a->ptr, s, b);
bd9cf2 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, s+1);
f54249 ¤   MALLOCDB;
8c3e6b ¤   return 0;
7befe6 }
14af5a
a84d2f int
2b5eeb bnDivMod_64(BigNum *q, BigNum *r, BigNum const *n,
32c387 ············BigNum const *d)
4fbb36 {
dbb221 ¤   unsigned dsize, nsize;
bf384b ¤   BNWORD64 qhigh;
a3af5a
6b26e6 ¤   dsize = bniNorm_64((BNWORD64 *)d->ptr, d->size);
b574c6 ¤   nsize = bniNorm_64((BNWORD64 *)n->ptr, n->size);
73af5a
c6b959 ¤   if (nsize < dsize) {
5fa365 ¤   ¤   q->size = 0;¤   /* No quotient */
911a91 ¤   ¤   r->size = nsize;
481ef3 ¤   ¤   return 0;¤  /* Success */
e49371 ¤   }
48af5a
eff25e ¤   bnSizeCheck(q, nsize-dsize);
9daf5a
020a29 ¤   if (r != n) {¤  /* You are allowed to reduce in place */
afe5de ¤   ¤   bnSizeCheck(r, nsize);
a646b3 ¤   ¤   bniCopy_64((BNWORD64 *)r->ptr, (BNWORD64 *)n->ptr, nsize);
f29371 ¤   }
821b52 ¤   ¤
2b623d ¤   qhigh = bniDiv_64((BNWORD64 *)q->ptr, (BNWORD64 *)r->ptr, nsize,
6e81b3 ¤   ··················(BNWORD64 *)d->ptr, dsize);
38169e ¤   nsize -= dsize;
fd0152 ¤   if (qhigh) {
88a056 ¤   ¤   bnSizeCheck(q, nsize+1);
5a529c ¤   ¤   *((BNWORD64 *)q->ptr BIGLITTLE(-nsize-1,+nsize)) = qhigh;
30936d ¤   ¤   q->size = nsize+1;
79f037 ¤   } else {
56a4ba ¤   ¤   q->size = bniNorm_64((BNWORD64 *)q->ptr, nsize);
fd9371 ¤   }
051ada ¤   r->size = bniNorm_64((BNWORD64 *)r->ptr, dsize);
f54249 ¤   MALLOCDB;
b43e6b ¤   return 0;
c5efe6 }
5daf5a
e94d2f int
180b31 bnMod_64(BigNum *dest, BigNum const *src, BigNum const *d)
6fbb36 {
bdb221 ¤   unsigned dsize, nsize;
2baf5a
fb90a6 ¤   nsize = bniNorm_64((BNWORD64 *)src->ptr, src->size);
de26e6 ¤   dsize = bniNorm_64((BNWORD64 *)d->ptr, d->size);
1caf5a
e5af5a
f691a5 ¤   if (dest != src) {
2be35c ¤   ¤   bnSizeCheck(dest, nsize);
aad74b ¤   ¤   bniCopy_64((BNWORD64 *)dest->ptr, (BNWORD64 *)src->ptr, nsize);
429371 ¤   }
--04cb 0003a37e51540100146 Page 9 of bn64.c
e0af5a
6db959 ¤   if (nsize < dsize) {
27b0f4 ¤   ¤   dest->size = nsize;¤/* No quotient */
b0bbde ¤   ¤   return 0;
d59371 ¤   }
54af5a
3a66bf ¤   (void)bniDiv_64((BNWORD64 *)dest->ptr BIGLITTLE(-dsize,+dsize),
868e34 ¤   ················(BNWORD64 *)dest->ptr, nsize,
d5e4ef ¤   ················(BNWORD64 *)d->ptr, dsize);
ef19c4 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, dsize);
774249 ¤   MALLOCDB;
c83e6b ¤   return 0;
36efe6 }
15af5a
e4536c unsigned
148b4c bnModQ_64(BigNum const *src, unsigned d)
bebb36 {
c982d0 ¤   unsigned s;
8eaf5a
27224b ¤   s = bniNorm_64((BNWORD64 *)src->ptr, src->size);
eea2be ¤   if (!s)
bcbbde ¤   ¤   return 0;
8a67c5 ¤
696350 ¤   if (d & (d-1))¤ /* Not a power of 2 */
17994c ¤   ¤   d = bniModQ_64((BNWORD64 *)src->ptr, s, d);
6c0e24 ¤   else
4b23cc ¤   ¤   d = (unsigned)((BNWORD64 *)src->ptr)[BIGLITTLE(-1,0)] & (d-1);
13dee9 ¤   return d;
a9efe6 }
dcaf5a
b24d2f int
ca6da5 bnExpMod_64(BigNum *dest, BigNum const *n,
1c769e ¤   BigNum const *exp, BigNum const *mod)
c8bb36 {
a5f5f9 ¤   unsigned nsize, esize, msize;
1826cc ¤   PGPBoolean¤ ¤   secure;
d967c5 ¤
0444fc ¤   secure¤ = dest->isSecure || n->isSecure ||
811228 ¤   ¤   exp->isSecure || mod->isSecure;
ecaf5a
a374c6 ¤   nsize = bniNorm_64((BNWORD64 *)n->ptr, n->size);
db67b2 ¤   esize = bniNorm_64((BNWORD64 *)exp->ptr, exp->size);
edbdd1 ¤   msize = bniNorm_64((BNWORD64 *)mod->ptr, mod->size);
21af5a
bb5acf ¤   if (!msize || (((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
59a4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
0faf5a
875e84 ¤   bnSizeCheck(dest, msize);
99af5a
3ddbab ¤   /* Special-case base of 2 */
1a9b59 ¤   if (nsize == 1 && ((BNWORD64 *)n->ptr)[BIGLITTLE(-1,0)] == 2) {
e421df ¤   ¤   if (bniTwoExpMod_64( dest->mgr, secure,
715f9f ¤   ¤   ¤   ¤   ¤   (BNWORD64 *)dest->ptr,
e4cbf9 ¤   ¤   ¤   ¤   ····(BNWORD64 *)exp->ptr, esize,
75e2de ¤   ¤   ¤   ¤   ····(BNWORD64 *)mod->ptr, msize) < 0)
9b3fd5 ¤   ¤   ¤   return -1;
b1f037 ¤   } else {
e27a9e ¤   ¤   if (bniExpMod_64( dest->mgr, secure,
16ce07 ¤   ¤   ¤   ¤   ¤   ¤   (BNWORD64 *)dest->ptr,
3af39f ¤   ¤   ·················(BNWORD64 *)n->ptr, nsize,
3e950b ¤   ¤   ¤   ¤   ·(BNWORD64 *)exp->ptr, esize,
0310a4 ¤   ¤   ¤   ¤   ·(BNWORD64 *)mod->ptr, msize) < 0)
d7043c ¤   ¤   return -1;
5f9371 ¤   }
b4af5a
6eb5c7 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, msize);
fc4249 ¤   MALLOCDB;
e93e6b ¤   return 0;
19efe6 }
66af5a
024d2f int
3a881d bnDoubleExpMod_64(BigNum *dest,
--1966 000211bf96d40100146 Page 10 of bn64.c
25b250 ¤   BigNum const *n1, BigNum const *e1,
e10480 ¤   BigNum const *n2, BigNum const *e2,
a74699 ¤   BigNum const *mod)
b7bb36 {
6e93dc ¤   unsigned n1size, e1size, n2size, e2size, msize;
d126cc ¤   PGPBoolean¤ ¤   secure;
d867c5 ¤
5bcf25 ¤   secure¤ = dest->isSecure || n1->isSecure || e1->isSecure ||
4d3105 ¤   ¤   ¤   ¤   n2->isSecure || e2->isSecure || mod->isSecure;
50af5a
ec2ac0 ¤   n1size = bniNorm_64((BNWORD64 *)n1->ptr, n1->size);
03ace1 ¤   e1size = bniNorm_64((BNWORD64 *)e1->ptr, e1->size);
faeda7 ¤   n2size = bniNorm_64((BNWORD64 *)n2->ptr, n2->size);
466b86 ¤   e2size = bniNorm_64((BNWORD64 *)e2->ptr, e2->size);
a9bdd1 ¤   msize = bniNorm_64((BNWORD64 *)mod->ptr, mod->size);
6daf5a
915acf ¤   if (!msize || (((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
87a4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
91af5a
545e84 ¤   bnSizeCheck(dest, msize);
8faf5a
89437d ¤   if (bniDoubleExpMod_64(
9fe597 ¤   ¤   dest->mgr, secure,
b89c5f ¤   ¤   (BNWORD64 *)dest->ptr,
4aa998 ¤   ¤   (BNWORD64 *)n1->ptr, n1size, (BNWORD64 *)e1->ptr, e1size,
7e3d5a ¤   ¤   (BNWORD64 *)n2->ptr, n2size, (BNWORD64 *)e2->ptr, e2size,
a53644 ¤   ¤   (BNWORD64 *)mod->ptr, msize) < 0)
9f043c ¤   ¤   return -1;
feaf5a
f8b5c7 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, msize);
1c4249 ¤   MALLOCDB;
2a3e6b ¤   return 0;
ecefe6 }
9baf5a
0e4d2f int
8c27e6 bnTwoExpMod_64(BigNum *n, BigNum const *exp,
864699 ¤   BigNum const *mod)
0fbb36 {
f664a5 ¤   unsigned esize, msize;
46673e ¤   PGPBoolean¤ secure¤ = n->isSecure || exp->isSecure || mod->isSecure;
8faf5a
2067b2 ¤   esize = bniNorm_64((BNWORD64 *)exp->ptr, exp->size);
fcbdd1 ¤   msize = bniNorm_64((BNWORD64 *)mod->ptr, mod->size);
a5af5a
485acf ¤   if (!msize || (((BNWORD64 *)mod->ptr)[BIGLITTLE(-1,0)] & 1) == 0)
48a4ef ¤   ¤   return -1;¤ /* Illegal modulus! */
44af5a
e8e89c ¤   bnSizeCheck(n, msize);
47af5a
0dda07 ¤   if (bniTwoExpMod_64( n->mgr, secure,
65dfed ¤   ¤   ¤   ¤   (BNWORD64 *)n->ptr, (BNWORD64 *)exp->ptr, esize,
1d1203 ¤   ············(BNWORD64 *)mod->ptr, msize) < 0)
01043c ¤   ¤   return -1;
64af5a
ac70bf ¤   n->size = bniNorm_64((BNWORD64 *)n->ptr, msize);
e44249 ¤   MALLOCDB;
e13e6b ¤   return 0;
40efe6 }
1baf5a
ce4d2f int
a84747 bnGcd_64(BigNum *dest, BigNum const *a, BigNum const *b)
cbbb36 {
618c7e ¤   BNWORD64 *tmp;
638ee8 ¤   unsigned asize, bsize;
7c4ba4 ¤   int i;
5df93f ¤   PGPBoolean¤ secure¤ = dest->isSecure || a->isSecure || b->isSecure;
d6af5a
650824 ¤   /* Kind of silly, but we might as well permit it... */
871827 ¤   if (a == b)
5a1266 ¤   ¤   return dest == a ? 0 : bnCopy(dest, a);
23af5a
21097b ¤   /* Ensure a is not the same as "dest" */
--bf59 000c44db6fc40100146 Page 11 of bn64.c
2a0bb5 ¤   if (a == dest) {
687661 ¤   ¤   a = b;
1b3e03 ¤   ¤   b = dest;
539371 ¤   }
11af5a
cc0ff6 ¤   asize = bniNorm_64((BNWORD64 *)a->ptr, a->size);
921706 ¤   bsize = bniNorm_64((BNWORD64 *)b->ptr, b->size);
a5af5a
0b26a2 ¤   bnSizeCheck(dest, bsize+1);
e1af5a
24d672 ¤   /* Copy a to tmp */
2f9f7f ¤   BNIALLOC( dest->mgr, secure, tmp, BNWORD64, asize+1);
27da32 ¤   if (!tmp)
59043c ¤   ¤   return -1;
33e53f ¤   bniCopy_64(tmp, (BNWORD64 *)a->ptr, asize);
1eaf5a
3e6562 ¤   /* Copy b to dest, if necessary */
44c9aa ¤   if (dest != b)
c3654d ¤   ¤   bniCopy_64((BNWORD64 *)dest->ptr,
23b7b6 ¤   ¤   ¤   ···(BNWORD64 *)b->ptr, bsize);
ead29e ¤   if (bsize > asize || (bsize == asize &&
f8e522 ¤   ········bniCmp_64((BNWORD64 *)b->ptr, (BNWORD64 *)a->ptr, asize) > 0))
b3c7a1 ¤   {
2c650e ¤   ¤   i = bniGcd_64((BNWORD64 *)dest->ptr, bsize, tmp, asize,
dc2094 ¤   ¤   ¤   &dest->size);
43c640 ¤   ¤   if (i > 0)¤ /* Result in tmp, not dest */
f1222b ¤   ¤   ¤   bniCopy_64((BNWORD64 *)dest->ptr, tmp, dest->size);
2bf037 ¤   } else {
cdb906 ¤   ¤   i = bniGcd_64(tmp, asize, (BNWORD64 *)dest->ptr, bsize,
5a2094 ¤   ¤   ¤   &dest->size);
28027d ¤   ¤   if (i == 0)¤/* Result in tmp, not dest */
08222b ¤   ¤   ¤   bniCopy_64((BNWORD64 *)dest->ptr, tmp, dest->size);
ed9371 ¤   }
29eaf9 ¤   BNIFREE(tmp, asize+1);
684249 ¤   MALLOCDB;
0b15a5 ¤   return (i < 0) ? i : 0;
bcefe6 }
40af5a
954d2f int
a5b6ee bnInv_64(BigNum *dest, BigNum const *src,
426b93 ·········BigNum const *mod)
56bb36 {
3be070 ¤   unsigned s, m;
aa4ba4 ¤   int i;
544382 ¤   PGPBoolean¤ secure;
7f67c5 ¤
834500 ¤   secure¤ = dest->isSecure || src->isSecure || mod->isSecure;
a2af5a
25224b ¤   s = bniNorm_64((BNWORD64 *)src->ptr, src->size);
b2e5f1 ¤   m = bniNorm_64((BNWORD64 *)mod->ptr, mod->size);
52af5a
9c5d4e ¤   /* bniInv_64 requires that the input be less than the modulus */
450b4f ¤   if (m < s ||
7430ae ¤   ····(m==s && bniCmp_64((BNWORD64 *)src->ptr, (BNWORD64 *)mod->ptr, s)))
ccc7a1 ¤   {
fce1a3 ¤   ¤   bnSizeCheck(dest, s + (m==s));
2fd0b6 ¤   ¤   if (dest != src)
d05c88 ¤   ¤   ¤   bniCopy_64((BNWORD64 *)dest->ptr,
d37157 ¤   ¤   ¤   ···········(BNWORD64 *)src->ptr, s);
372bbe ¤   ¤   /* Pre-reduce modulo the modulus */
b93703 ¤   ¤   (void)bniDiv_64((BNWORD64 *)dest->ptr BIGLITTLE(-m,+m),
7e1701 ¤   ¤   ¤   ········(BNWORD64 *)dest->ptr, s,
7773cd ¤   ¤   ················(BNWORD64 *)mod->ptr, m);
8978a9 ¤   ¤   s = bniNorm_64((BNWORD64 *)dest->ptr, m);
e5c7fc ¤   ¤   MALLOCDB;
99f037 ¤   } else {
1f0452 ¤   ¤   bnSizeCheck(dest, m+1);
47d0b6 ¤   ¤   if (dest != src)
0e5c88 ¤   ¤   ¤   bniCopy_64((BNWORD64 *)dest->ptr,
d67157 ¤   ¤   ¤   ···········(BNWORD64 *)src->ptr, s);
2c9371 ¤   }
c4af5a
--946b 000e25e656340100146 Page 12 of bn64.c
478385 ¤   i = bniInv_64( ·dest->mgr, secure,
8f18a3 ¤   ¤   ¤   (BNWORD64 *)dest->ptr, s, (BNWORD64 *)mod->ptr, m);
c503c0 ¤   if (i == 0)
f0f028 ¤   ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, m);
ccaf5a
474249 ¤   MALLOCDB;
0f2196 ¤   return i;
2befe6 }
76af5a
fa38e5 /*
dada51 ·* Shift a bignum left the appropriate number of bits,
128141 ·* multiplying by 2^amt.
17495d ·*/
63fcf4 int·
90f328 bnLShift_64(BigNum *dest, unsigned amt)
e3bb36 {
103b6a ¤   unsigned s = dest->size;
451e59 ¤   BNWORD64 carry;
ebaf5a
5f64cc ¤   if (amt % 64) {
05f174 ¤   ¤   carry = bniLshift_64((BNWORD64 *)dest->ptr, s, amt % 64);
72a2cc ¤   ¤   if (carry) {
da7904 ¤   ¤   ¤   s++;
bcc0e0 ¤   ¤   ¤   bnSizeCheck(dest, s);
7acab8 ¤   ¤   ¤   ((BNWORD64 *)dest->ptr)[BIGLITTLE(-s,s-1)] = carry;
b60fe4 ¤   ¤   }
929371 ¤   }
6faf5a
bc833d ¤   amt /= 64;
63a187 ¤   if (amt) {
e2d404 ¤   ¤   bnSizeCheck(dest, s+amt);
d9c26e ¤   ¤   memmove((BNWORD64 *)dest->ptr BIGLITTLE(-s-amt, +amt),
7b5988 ¤   ¤   ········(BNWORD64 *)dest->ptr BIG(-s),
8613ac ¤   ¤   ¤   s * sizeof(BNWORD64));
3a4a8f ¤   ¤   bniZero_64((BNWORD64 *)dest->ptr, amt);
174fb7 ¤   ¤   s += amt;
d79371 ¤   }
163445 ¤   dest->size = s;
af4249 ¤   MALLOCDB;
2c3e6b ¤   return 0;
29efe6 }
00af5a
4838e5 /*
9b5b10 ·* Shift a bignum right the appropriate number of bits,
1f64af ·* dividing by 2^amt.
0a495d ·*/
0b1d10 void bnRShift_64(BigNum *dest, unsigned amt)
5fbb36 {
1c3b6a ¤   unsigned s = dest->size;
06af5a
be83fe ¤   if (amt >= 64) {
c1712d ¤   ¤   memmove(
ce6c7b ¤   ¤   ········(BNWORD64 *)dest->ptr BIG(-s+amt/64),
f2f4ad ¤   ¤   ¤   (BNWORD64 *)dest->ptr BIGLITTLE(-s, +amt/64),
cc0b8c ¤   ¤   ¤   (s-amt/64) * sizeof(BNWORD64));
676c97 ¤   ¤   s -= amt/64;
ed88c9 ¤   ¤   amt %= 64;
169371 ¤   }
4daf5a
c62a0b ¤   if (amt)
756379 ¤   ¤   (void)bniRshift_64((BNWORD64 *)dest->ptr, s, amt);
8caf5a
ff9af0 ¤   dest->size = bniNorm_64((BNWORD64 *)dest->ptr, s);
604249 ¤   MALLOCDB;
bfefe6 }
20af5a
7a38e5 /*
fb3c6d ·* Shift a bignum right until it is odd, and return the number of
0fdd34 ·* bits shifted. ·n = d * 2^s. ·Replaces n with d and returns s.
1c3e8b ·* Returns 0 when given 0. ·(Another valid answer is infinity.)
be495d ·*/
e2536c unsigned
--290d 001503f067540100146 Page 13 of bn64.c
d34e37 bnMakeOdd_64(BigNum *n)
dcbb36 {
21c87c ¤   unsigned size;
b3d5a0 ¤   unsigned s;¤/* shift amount */
4a81e7 ¤   BNWORD64 *p;
29d6e3 ¤   BNWORD64 t;
d5af5a
099eff ¤   p = (BNWORD64 *)n->ptr;
6f6917 ¤   size = bniNorm_64(p, n->size);
1bfaf0 ¤   if (!size)
59bbde ¤   ¤   return 0;
dfaf5a
ccf624 ¤   t = BIGLITTLE(p[-1],p[0]);
7ba3f2 ¤   s = 0;
f3af5a
726e2d ¤   /* See how many words we have to shift */
36ddcd ¤   if (!t) {
750d12 ¤   ¤   /* Shift by words */
674392 ¤   ¤   do {
6587c7 ¤   ¤   ¤
067904 ¤   ¤   ¤   s++;
0423b9 ¤   ¤   ¤   BIGLITTLE(--p,p++);
6bd20d ¤   ¤   } while ((t = BIGLITTLE(p[-1],p[0])) == 0);
0cb318 ¤   ¤   size -= s;
de3c2c ¤   ¤   s *= 64;
bb9b07 ¤   ¤   memmove((BNWORD64 *)n->ptr BIG(-size), p BIG(-size),
bb88de ¤   ¤   ¤   size * sizeof(BNWORD64));
ec33a1 ¤   ¤   p = (BNWORD64 *)n->ptr;
fcc7fc ¤   ¤   MALLOCDB;
139371 ¤   }
a8af5a
822ef7 ¤   pgpAssert(t);
18af5a
05928f ¤   /* Now count the bits */
048d0d ¤   while ((t & 1) == 0) {
ca7abe ¤   ¤   t >>= 1;
4bcc95 ¤   ¤   s++;
a19371 ¤   }
f9af5a
36097d ¤   /* Shift the bits */
fa3415 ¤   if (s & (64-1)) {
dd2692 ¤   ¤   bniRshift_64(p, size, s & (64-1));
be0098 ¤   ¤   /* Renormalize */
e9066b ¤   ¤   if (BIGLITTLE(*(p-size),*(p+(size-1))) == 0)
6b8bc2 ¤   ¤   ¤   --size;
879371 ¤   }
902c3e ¤   n->size = size;
caaf5a
2e4249 ¤   MALLOCDB;
c2d779 ¤   return s;
50efe6 }
--3195 0014381cbc040100147 Page 1 of bn64.h
bc38e5 /*
6a8205 ·* bn64.h - interface to 64-bit bignum routines.
1c775e ·*
54a0c1 ·* $Id: bn64.h,v 1.2 1998/05/14 19:07:20 cbertsch Exp $
8c495d ·*/
7aaf5a
3699c6 PGP_BEGIN_C_DECLARATIONS
70af5a
61bdbd #include "pgpBigNumOpaqueStructs.h"
e4af5a
fba078 void bnInit_64(void);
dd9a71 void bnEnd_64(BigNum *bn);
7c4481 int bnPrealloc_64(BigNum *bn, unsigned bits);
771b81 int bnCopy_64(BigNum *dest, BigNum const *src);
31f583 int bnSwap_64(BigNum *a, BigNum *b);
204b93 void bnNorm_64(BigNum *bn);
dbea95 void bnExtractBigBytes_64(BigNum const *bn, unsigned char *dest,
768dcb ¤   unsigned lsbyte, unsigned dlen);
01f0d4 int bnInsertBigBytes_64(BigNum *bn, unsigned char const *src,
d13762 ¤   unsigned lsbyte, unsigned len);
9a66e3 void bnExtractLittleBytes_64(BigNum const *bn, unsigned char *dest,
fa8dcb ¤   unsigned lsbyte, unsigned dlen);
e3e1a5 int bnInsertLittleBytes_64(BigNum *bn, unsigned char const *src,
1c3762 ¤   unsigned lsbyte, unsigned len);
b7625b unsigned bnLSWord_64(BigNum const *src);
15904d unsigned bnBits_64(BigNum const *src);
ba21d9 int bnAdd_64(BigNum *dest, BigNum const *src);
caea60 int bnSub_64(BigNum *dest, BigNum const *src);
db3330 int bnCmpQ_64(BigNum const *a, unsigned b);
0e380a int bnSetQ_64(BigNum *dest, unsigned src);
aec631 int bnAddQ_64(BigNum *dest, unsigned src);
705156 int bnSubQ_64(BigNum *dest, unsigned src);
cb89f4 int bnCmp_64(BigNum const *a, BigNum const *b);
a42a6c int bnSquare_64(BigNum *dest, BigNum const *src);
9d3d53 int bnMul_64(BigNum *dest, BigNum const *a,
aa9cfe ¤   BigNum const *b);
5d0b9f int bnMulQ_64(BigNum *dest, BigNum const *a, unsigned b);
db200c int bnDivMod_64(BigNum *q, BigNum *r, BigNum const *n,
72d764 ¤   BigNum const *d);
5254c0 int bnMod_64(BigNum *dest, BigNum const *src,
14d764 ¤   BigNum const *d);
9e9ac8 unsigned bnModQ_64(BigNum const *src, unsigned d);
9edb07 int bnExpMod_64(BigNum *dest, BigNum const *n,
f37da1 ¤   BigNum const *exp, BigNum const *mod);
6b3a9a int bnDoubleExpMod_64(BigNum *dest,
a4b250 ¤   BigNum const *n1, BigNum const *e1,
e50480 ¤   BigNum const *n2, BigNum const *e2,
66092e ¤   BigNum const *mod);
2f6b14 int bnTwoExpMod_64(BigNum *n, BigNum const *exp,
c7092e ¤   BigNum const *mod);
092c50 int bnGcd_64(BigNum *dest, BigNum const *a,
869cfe ¤   BigNum const *b);
90876d int bnInv_64(BigNum *dest, BigNum const *src,
f2092e ¤   BigNum const *mod);
d6ada9 int bnLShift_64(BigNum *dest, unsigned amt);
cb10bc void bnRShift_64(BigNum *dest, unsigned amt);
1354a6 unsigned bnMakeOdd_64(BigNum *n);
63af5a
431254 PGP_END_C_DECLARATIONS
--3161 0014913de6d40100148 Page 1 of bn68000.c
bc38e5 /*
8fa80b ·* bn68000.c - bnInit() for Motorola 680x0 family, 16 or 32-bit.
6e775e ·*
31001b ·* Written in 1995 by Colin Plumb.
38775e ·*
42d69b ·* $Id: bn68000.c,v 1.1 1997/04/30 08:36:06 mhw Exp $
d5495d ·*/
79af5a
6539fc #include "bn.h"
2ca6ac #include "bni.h"
6c8a11 #include "bn16.h"
edaf57 #include "bn32.h"
1baf5a
139c8e #ifndef BNINCLUDE
369248 #error You must define BNINCLUDE to bni68000.h to use assembly primitives.
a77454 #endif
ebaf5a
6f314a void
33bf9a bnInit(void)
59bb36 {
85c3d4 ¤   if (is68020())
17d7b0 ¤   ¤   bnInit_32();
130e24 ¤   else
f3f2f6 ¤   ¤   bnInit_16();
49efe6 }
--a22e 00117f463c340100149 Page 1 of bn8086.c
bc38e5 /*
b0c5bf ·* bn8086.c - bnInit() for Intel x86 family in 16-bit mode.
37775e ·*
fb001b ·* Written in 1995 by Colin Plumb.
f5775e ·*
16dfbd ·* $Id: bn8086.c,v 1.1 1997/04/30 08:36:06 mhw Exp $
13495d ·*/
8daf5a
7da6ac #include "bni.h"
468a11 #include "bn16.h"
6faf57 #include "bn32.h"
d4af5a
5e9c8e #ifndef BNINCLUDE
cc1e82 #error You must define BNINCLUDE to bni8086.h to use assembly primitives.
8b7454 #endif
39af5a
3a314a void
e1bf9a bnInit(void)
66bb36 {
30f0b9 ¤   if (not386())
c3f2f6 ¤   ¤   bnInit_16();
fe0e24 ¤   else
b4d7b0 ¤   ¤   bnInit_32();
17efe6 }
--cfbd 0004bfb79434010014a Page 1 of bndsaprime.c
bc38e5 /*
12c462 ·* Digital Signature Algorithm prime generation using the bignum
038e78 ·* library and sieving.
40775e ·*
c468c2 ·* Written by Colin Plumb.
f8775e ·*
c92dba ·* $Id: bndsaprime.c,v 1.2 1997/05/09 23:17:14 lloyd Exp $
a7495d ·*/
50d92d #include <stdarg.h>
24324c #include <string.h>
f963d6 #if BNDEBUG
04feb2 #include <stdio.h>
db7454 #endif
6a4724 #include "bnkludge.h"
50af5a
c239fc #include "bn.h"
e62602 #include "bnimem.h"¤/* For bniMemWipe */
7ca269 #include "bndsaprime.h"
a3e6d6 #include "bnsieve.h"
b5a146 #include "pgpDebug.h"
12af5a
90cb8e /* Size of the sieve area (can be up to 65536/8 = 8192) */
abb10e #define SIEVE 1024
daaf5a
9538e5 /*
421094 ·* Helper function that does the slow primality test.
2d1ec3 ·* bn is the input bignum; a and e are temporary buffers that are
5572c9 ·* allocated by the caller to save overhead.
1b775e ·*
8e1169 ·* Returns 0 if prime, >0 if not prime, and -1 on error (out of memory).
d8d46c ·* If not prime, the return value is the number of modular exponentiations
d2e9d8 ·* performed. ··Calls the progress function with progress indicators as
bd7455 ·* tests are passed.
f7775e ·*
efc21c ·* Currently, the testing performs Euler tests, to the bases 2, 3, 5, 7,
93ab6e ·* 11, 13 and 17. ·(An Euler test is a slightly strengthened Fermat test;
e4602e ·* Euler pseudoprimes are a subset of Fermat pseudoprimes.) ·Some people
6f8c6e ·* worry that this might not be enough. ·Number theorists may wish to
75ab98 ·* generate primality proofs, but for random inputs, this returns non-primes
143975 ·* with a probability which is quite negligible, which is good enough.
34426c ·* NOTE that for NON-random inputs, there are indeed numbers which are
2bd261 ·* strong pseudoprimes to a lot of bases. ·Up to 1/4 of all bases 0 < b < n.
93775e ·*
d8fede ·* It has been proved (see Carl Pomerance, "On the Distribution of
77e6a0 ·* Pseudoprimes", Math. Comp. v.37 (1981) pp. 587-593) that the number
8c60ec ·* of pseudoprimes (composite numbers that pass a Fermat test to the
377c42 ·* base 2) less than x is bounded by:
d542ce ·* exp(ln(x)^(5/14)) <= P_2(x)¤ ### CHECK THIS FORMULA - it looks wrong! ###
f99b29 ·* P_2(x) <= x * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))).
d16135 ·* Thus, the local density of Pseudoprimes near x is at most
51c53f ·* exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))), and at least
6aaf72 ·* exp(ln(x)^(5/14) - ln(x)). ·Here are some values of this function
29d900 ·* for various k-bit numbers x = 2^k:
28b1a2 ·* Bits¤Density <=¤ Bit equivalent¤ Density >=¤ Bit equivalent
66bca8 ·* ·128¤3.577869e-07¤   ·21.414396¤ 4.202213e-37¤   ·120.840190
fcd79f ·* ·192¤4.175629e-10¤   ·31.157288¤ 4.936250e-56¤   ·183.724558
73eef7 ·* ·256 5.804314e-13¤   ·40.647940¤ 4.977813e-75¤   ·246.829095
bfe5c7 ·* ·384 1.578039e-18¤   ·59.136573¤ 3.938861e-113¤  ·373.400096
0f4e78 ·* ·512 5.858255e-24¤   ·77.175803¤ 2.563353e-151¤  ·500.253110
512492 ·* ·768 1.489276e-34¤   112.370944¤ 7.872825e-228¤  ·754.422724
3730bc ·* 1024 6.633188e-45¤   146.757062¤ 1.882404e-304¤  1008.953565
5b775e ·*
acdc2a ·* As you can see, there's quite a bit of slop between these estimates.
5ad3d6 ·* In fact, the density of pseudoprimes is conjectured to be closer
7f7e84 ·* to the square of that upper bound. ·E.g. the density of pseudoprimes
c4240c ·* of size 256 is around 3 * 10^-27. ·The density of primes is very
908e80 ·* high, from 0.005636 at 256 bits to 0.001409 at 1024 bits, i.e.
4eb22e ·* more than 10^-3.
4a775e ·*
cd8e57 ·* For those people used to cryptographic levels of security where the
bff5ae ·* 56 bits of DES key space is too small because it's exhaustible with
4bb195 ·* custom hardware searching engines, note that you are not generating
--22d0 0007e8d01284010014a Page 2 of bndsaprime.c
9b49fa ·* 50,000,000 primes per second on each of 56,000 custom hardware chips
0238cc ·* for several hours. ·The chances that another Dinosaur Killer asteroid
58de2f ·* will land today is about 10^-11 or 2^-36, so it would be better to
680f04 ·* spend your time worrying about *that*. ·Well, okay, there should be
ee8afd ·* some derating for the chance that astronomers haven't seen it yet, but
f52c25 ·* I think you get the idea. ·For a good feel about the probability of
9b02bc ·* various events, I have heard that a good book is by E'mile Borel,
0d1a7c ·* "Les Probabilite's et la vie". ·(The 's are accents, not apostrophes.)
25775e ·*
aa8e80 ·* For more on the subject, try "Finding Four Million Large Random Primes",
e6eca1 ·* by Ronald Rivest, in Advancess in Cryptology: Proceedings of Crypto '90.
308cd0 ·* He used a small-divisor test, then a Fermat test to the base 2, and then
a47d20 ·* 8 iterations of a Miller-Rabin test. ·About 718 million random 256-bit
0af8e0 ·* integers were generated, 43,741,404 passed the small divisor test,
87bbaa ·* 4,058,000 passed the Fermat test, and all 4,058,000 passed all 8
893d08 ·* iterations of the Miller-Rabin test, proving their primality beyond most
0e52df ·* reasonable doubts.
ea775e ·*
a0fff3 ·* If the probability of getting a pseudoprime is some small p, then
c9fe8d ·* the probability of not getting it in t trials is (1-p)^t. ·Remember
3343fc ·* that, for small p, (1-p)^(1/p) ~ 1/e, the base of natural logarithms.
d01db8 ·* (This is more commonly expressed as e = lim_{x\to\infty} (1+1/x)^x.)
9bf18b ·* Thus, (1-p)^t ~ e^(-p*t) = exp(-p*t). ·So the odds of being able to
565045 ·* do this many tests without seeing a pseudoprime if you assume that
6f6e22 ·* p = 10^-6 (one in a million) is one in 57.86. ·If you assume that
7a8695 ·* p = 2*10^-6, it's one in 3347.6. ·So it's implausible that the
cf1790 ·* density of pseudoprimes is much more than one millionth the density
dfb308 ·* of primes.
9b775e ·*
1f5ea5 ·* He also gives a theoretical argument that the chance of finding a
fb1eba ·* 256-bit non-prime which satisfies one Fermat test to the base 2 is less
800e26 ·* than 10^-22. ·The small divisor test improves this number, and if the
61dac8 ·* numbers are 512 bits (as needed for a 1024-bit key) the odds of failure
3e616f ·* shrink to about 10^-44. ·Thus, he concludes, for practical purposes
5032cd ·* *one* Fermat test to the base 2 is sufficient.
e2495d ·*/
ddbeb7 static int
462884 primeTest(BigNum const *bn, BigNum *e, BigNum *a,
cf71b8 ¤   int (*f)(void *arg, int c), void *arg)
c0bb36 {
3017e6 ¤   int err;
e207cb ¤   unsigned i, j;
ced944 ¤   unsigned k, l;
f9cddd ¤   static unsigned const primes[] = {2, 3, 5, 7, 11, 13, 17};
47e4ff #define CONFIRMTESTS 7
1daf5a
ce24d7 #if BNDEBUG¤/* Debugging */
05d8af ¤   /*
e1dca9 ¤   ·* This is debugging code to test the sieving stage.
30a68c ¤   ·* If the sieving is wrong, it will let past numbers with
e2f84c ¤   ·* small divisors. ·The prime test here will still work, and
435dc7 ¤   ·* weed them out, but you'll be doing a lot more slow tests,
4a4eb6 ¤   ·* and presumably excluding from consideration some other numbers
3da4b5 ¤   ·* which might be prime. ·This check just verifies that none
1f8960 ¤   ·* of the candidates have any small divisors. ·If this
7aa1af ¤   ·* code is enabled and never triggers, you can feel quite
38b693 ¤   ·* confident that the sieving is doing its job.
7ba4e3 ¤   ·*/
f78e63 ¤   i = bnModQ(bn, 30030);¤ /* 30030 = 2 * 3 * 5 * 7 * 11 * 13 */
4ece3b ¤   if (!(i % 2)) printf("bn div by 2!");
1c040e ¤   if (!(i % 3)) printf("bn div by 3!");
c3a892 ¤   if (!(i % 5)) printf("bn div by 5!");
7234e9 ¤   if (!(i % 7)) printf("bn div by 7!");
dcff96 ¤   if (!(i % 11)) printf("bn div by 11!");
940db3 ¤   if (!(i % 13)) printf("bn div by 13!");
f75c79 ¤   i = bnModQ(bn, 7429);¤  /* 7429 = 17 * 19 * 23 */
3de1e8 ¤   if (!(i % 17)) printf("bn div by 17!");
312f31 ¤   if (!(i % 19)) printf("bn div by 19!");
cfc4c8 ¤   if (!(i % 23)) printf("bn div by 23!");
0b0f70 ¤   i = bnModQ(bn, 33263);¤ /* 33263 = 29 * 31 * 37 */
c0e64a ¤   if (!(i % 29)) printf("bn div by 29!");
7e89cb ¤   if (!(i % 31)) printf("bn div by 31!");
--bede 00015066e454010014a Page 3 of bndsaprime.c
4c97b5 ¤   if (!(i % 37)) printf("bn div by 37!");
9f7454 #endif
72af5a
18d8af ¤   /*
b74df5 ¤   ·* Now, check that bn is prime. ·If it passes to the base 2,
b0596a ¤   ·* it's prime beyond all reasonable doubt, and everything else
9c5206 ¤   ·* is just gravy, but it gives people warm fuzzies to do it.
bc9714 ¤   ·*
457c08 ¤   ·* This starts with verifying Euler's criterion for a base of 2.
9ba18c ¤   ·* This is the fastest pseudoprimality test that I know of,
2c64ce ¤   ·* saving a modular squaring over a Fermat test, as well as
342a96 ¤   ·* being stronger. ·7/8 of the time, it's as strong as a strong
9ecf16 ¤   ·* pseudoprimality test, too. ·(The exception being when bn ==
2e3952 ¤   ·* 1 mod 8 and 2 is a quartic residue, i.e. bn is of the form
0118e5 ¤   ·* a^2 + (8*b)^2.) ·The precise series of tricks used here is
499343 ¤   ·* not documented anywhere, so here's an explanation.
dae71b ¤   ·* Euler's criterion states that if p is prime then a^((p-1)/2)
d21293 ¤   ·* is congruent to Jacobi(a,p), modulo p. ·Jacobi(a,p) is
017fc0 ¤   ·* a function which is +1 if a is a square modulo p, and -1 if
5df691 ¤   ·* it is not. ·For a = 2, this is particularly simple. ·It's
e5caa4 ¤   ·* +1 if p == +/-1 (mod 8), and -1 if m == +/-3 (mod 8).
8108d2 ¤   ·* If p == 3 mod 4, then all a strong test does is compute
de1e1b ¤   ·* 2^((p-1)/2). and see if it's +1 or -1. ·(Euler's criterion
99d6a2 ¤   ·* says *which* it should be.) ·If p == 5 (mod 8), then
aa11a6 ¤   ·* 2^((p-1)/2) is -1, so the initial step in a strong test,
c163ca ¤   ·* looking at 2^((p-1)/4), is wasted - you're not going to
e22785 ¤   ·* find a +/-1 before then if it *is* prime, and it shouldn't
efc2ad ¤   ·* have either of those values if it isn't. ·So don't bother.
0a9714 ¤   ·*
1d7404 ¤   ·* The remaining case is p == 1 (mod 8). ·In this case, we
a9c3d2 ¤   ·* expect 2^((p-1)/2) == 1 (mod p), so we expect that the
8d8e58 ¤   ·* square root of this, 2^((p-1)/4), will be +/-1 (mod p).
cc8dcc ¤   ·* Evaluating this saves us a modular squaring 1/4 of the time.
08a3bb ¤   ·* If it's -1, a strong pseudoprimality test would call p
0694a2 ¤   ·* prime as well. ·Only if the result is +1, indicating that
189744 ¤   ·* 2 is not only a quadratic residue, but a quartic one as well,
c40994 ¤   ·* does a strong pseudoprimality test verify more things than
563bfe ¤   ·* this test does. ·Good enough.
0d9714 ¤   ·*
63aaef ¤   ·* We could back that down another step, looking at 2^((p-1)/8)
66ed62 ¤   ·* if there was a cheap way to determine if 2 were expected to
a464c1 ¤   ·* be a quartic residue or not. ·Dirichlet proved that 2 is
3b2dc3 ¤   ·* a quartic residue iff p is of the form a^2 + (8*b^2).
cd54a5 ¤   ·* All primes == 1 (mod 4) can be expressed as a^2 + (2*b)^2,
9aeb6f ¤   ·* but I see no cheap way to evaluate this condition.
3ea4e3 ¤   ·*/
5d63a5 ¤   if (bnCopy(e, bn) < 0)
1f043c ¤   ¤   return -1;
d71819 ¤   (void)bnSubQ(e, 1);
5f7b30 ¤   l = bnLSWord(e);
46af5a
f7dbfb ¤   j = 1;¤ /* Where to start in prime array for strong prime tests */
edaf5a
be6435 ¤   if (l & 7) {
ef19b7 ¤   ¤   bnRShift(e, 1);
0b252f ¤   ¤   if (bnTwoExpMod(a, e, bn) < 0)
f13fd5 ¤   ¤   ¤   return -1;
eb7f70 ¤   ¤   if ((l & 7) == 6) {
1c8aed ¤   ¤   ¤   /* bn == 7 mod 8, expect +1 */
43dd5e ¤   ¤   ¤   if (bnBits(a) != 1)
a22a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
c71112 ¤   ¤   ¤   k = 1;
8445a6 ¤   ¤   } else {
bb4ba2 ¤   ¤   ¤   /* bn == 3 or 5 mod 8, expect -1 == bn-1 */
b4b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
cedd34 ¤   ¤   ¤   ¤   return -1;
048b90 ¤   ¤   ¤   if (bnCmp(a, bn) != 0)
572a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
761112 ¤   ¤   ¤   k = 1;
ac89a3 ¤   ¤   ¤   if (l & 4) {
619986 ¤   ¤   ¤   ¤   /* bn == 5 mod 8, make odd for strong tests */
15428c ¤   ¤   ¤   ¤   bnRShift(e, 1);
--b978 00055eaae8a4010014a Page 4 of bndsaprime.c
eec59f ¤   ¤   ¤   ¤   k = 2;
baa3a6 ¤   ¤   ¤   }
700fe4 ¤   ¤   }
c9f037 ¤   } else {
27c2cf ¤   ¤   /* bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn */
823c7a ¤   ¤   bnRShift(e, 2);
a1252f ¤   ¤   if (bnTwoExpMod(a, e, bn) < 0)
e53fd5 ¤   ¤   ¤   return -1;
4fd8ea ¤   ¤   if (bnBits(a) == 1) {
202532 ¤   ¤   ¤   j = 0;¤ /* Re-do strong prime test to base 2 */
3b45a6 ¤   ¤   } else {
77b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
bcdd34 ¤   ¤   ¤   ¤   return -1;
1b8b90 ¤   ¤   ¤   if (bnCmp(a, bn) != 0)
0f2a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
930fe4 ¤   ¤   }
f36229 ¤   ¤   k = 2 + bnMakeOdd(e);
b79371 ¤   }
20e38b ¤   /* It's prime! ·Now go on to confirmation tests */
58af5a
1cd8af ¤   /*
c2426a ¤   ·* Now, e = (bn-1)/2^k is odd. ·k >= 1, and has a given value
9c057a ¤   ·* with probability 2^-k, so its expected value is 2.
86fabd ¤   ·* j = 1 in the usual case when the previous test was as good as
088f96 ¤   ·* a strong prime test, but 1/8 of the time, j = 0 because
cb5e72 ¤   ·* the strong prime test to the base 2 needs to be re-done.
3da4e3 ¤   ·*/
a4bd05 ¤   for (i = j; i < sizeof(primes)/sizeof(*primes); i++) {
d2ea64 ¤   ¤   if (f && (err = f(arg, '*')) < 0)
d6b32f ¤   ¤   ¤   return err;
68e463 ¤   ¤   (void)bnSetQ(a, primes[i]);
868380 ¤   ¤   if (bnExpMod(a, a, e, bn) < 0)
dd3fd5 ¤   ¤   ¤   return -1;
fa0344 ¤   ¤   if (bnBits(a) == 1)
4b8e3f ¤   ¤   ¤   continue;¤  /* Passed this test */
06af5a
6ec430 ¤   ¤   l = k;
bfc0ad ¤   ¤   for (;;) {
9db1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
a1dd34 ¤   ¤   ¤   ¤   return -1;
1576d7 ¤   ¤   ¤   if (bnCmp(a, bn) == 0)¤ /* Was result bn-1? */
fe4924 ¤   ¤   ¤   ¤   break;¤ /* Prime */
46e626 ¤   ¤   ¤   if (!--l)¤  /* Reached end, not -1? luck? */
4b29d7 ¤   ¤   ¤   ¤   return i+2-j;¤  /* Failed, not prime */
0e9599 ¤   ¤   ¤   /* This portion is executed, on average, once. */
56ae08 ¤   ¤   ¤   (void)bnSubQ(a, 1);¤/* Put a back where it was. */
6e5f02 ¤   ¤   ¤   if (bnSquare(a, a) < 0 || bnMod(a, a, bn) < 0)
11dd34 ¤   ¤   ¤   ¤   return -1;
e8ae1a ¤   ¤   ¤   if (bnBits(a) == 1)
d129d7 ¤   ¤   ¤   ¤   return i+2-j;¤  /* Failed, not prime */
760fe4 ¤   ¤   }
280321 ¤   ¤   /* It worked (to the base primes[i]) */
e79371 ¤   }
2f67c5 ¤
513627 ¤   /* Yes, we've decided that it's prime. */
f4d68a ¤   if (f && (err = f(arg, '*')) < 0)
f0c9db ¤   ¤   return err;
d5af5a
6e6c87 ¤   return 0;¤  /* Prime! */
7befe6 }
97af5a
af38e5 /*
42fec8 ·* Modifies the given bnq to return a prime slightly larger, and then
d7e1f3 ·* modifies the given bnp to be a prime which is == 1 (mod bnq).
b8d53e ·* This is done by decreasing bnp until it is == 1 (mod 2*bnq), and
d25594 ·* then searching forward in steps of 2*bnq.
9cde29 ·* Returns >=0 on success or -1 on failure (out of memory). ·On
09d771 ·* success, the return value is the number of modular exponentiations
1e4891 ·* performed (excluding the final confirmation).
20e134 ·* This never gives up searching.
84775e ·*
5596a2 ·* int (*f)(void *arg, int c), void *arg
--034f 00068059b404010014a Page 5 of bndsaprime.c
30e0be ·* The function f argument, if non-NULL, is called with progress indicator
80e614 ·* characters for printing. ·A dot (.) is written every time a primality test
43b1d5 ·* is failed, a star (*) every time one is passed, and a slash (/) in the
30de41 ·* case that the sieve was emptied without finding a prime and is being
2ec1a9 ·* refilled. ·f is also passed the void *arg argument for private
c9ad00 ·* context storage. ·If f returns < 0, the test aborts and returns
421150 ·* that value immediately.
18775e ·*
37d724 ·* Apologies to structured programmers for all the GOTOs.
8a495d ·*/
a04d2f int
8bbf1d dsaPrimeGen(BigNum *bnq, BigNum *bnp,
1371b8 ¤   int (*f)(void *arg, int c), void *arg)
5cbb36 {
3213a5 ¤   int retval;
f8d823 ¤   unsigned p, prev;
ae3d5b ¤   BigNum a, e;
bede1b ¤   int modexps = 0;
56306a #ifdef MSDOS
4cd052 ¤   unsigned char *sieve;
4bdb21 #else
7e0aa9 ¤   unsigned char sieve[SIEVE];
c47454 #endif
0eaf5a
49306a #ifdef MSDOS
fbaf13 ¤   sieve = bniMemAlloc(SIEVE);
ddca71 ¤   if (!sieve)
30043c ¤   ¤   return -1;
767454 #endif
9daf5a
f4a39c ¤   bnBegin(&a);
b3d170 ¤   bnBegin(&e);
42af5a
64dda5 ¤   /* Phase 1: Search forwards from bnq for a suitable prime. */
4caf5a
a1161e ¤   /* First, make sure that bnq is odd. */
f739db ¤   (void)bnAddQ(bnq, ~bnLSWord(bnq) & 1);
8daf5a
b8220e ¤   for (;;) {
ee7c51 ¤   ¤   if (sieveBuild(sieve, SIEVE, bnq, 2, 1) < 0)
1c3507 ¤   ¤   ¤   goto failed;
d5af5a
12e284 ¤   ¤   p = prev = 0;
3090d8 ¤   ¤   if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
def603 ¤   ¤   ¤   do {
68980e ¤   ¤   ¤   ¤   /*
e5cb9f ¤   ¤   ¤   ¤   ·* Adjust bn to have the right value,
8291ef ¤   ¤   ¤   ¤   ·* incrementing in steps of < 65536.
297ce6 ¤   ¤   ¤   ¤   ·* 32767 = 65535/2.
b11020 ¤   ¤   ¤   ¤   ·*/
5f6407 ¤   ¤   ¤   ¤   pgpAssert(p >= prev);
07aa87 ¤   ¤   ¤   ¤   prev = p-prev;¤ /* Delta - add 2*prev to bn */
0bf97a #if SIEVE*8*2 >= 65536
ce3e15 ¤   ¤   ¤   ¤   while (prev > 32767) {
5e652c ¤   ¤   ¤   ¤   ¤   if (bnAddQ(bnq, 2*32767) < 0)
2a8764 ¤   ¤   ¤   ¤   ¤   ¤   goto failed;
6b1c93 ¤   ¤   ¤   ¤   ¤   prev -= 32767;
f82613 ¤   ¤   ¤   ¤   }
497454 #endif
85985b ¤   ¤   ¤   ¤   if (bnAddQ(bnq, 2*prev) < 0)
b2ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
3e5c8f ¤   ¤   ¤   ¤   prev = p;
0daf5a
03f33c ¤   ¤   ¤   ¤   retval = primeTest(bnq, &e, &a, f, arg);
d55c26 ¤   ¤   ¤   ¤   if (retval <= 0)
918d0e ¤   ¤   ¤   ¤   ¤   goto phase2;¤   /* Success! */
fb8abc ¤   ¤   ¤   ¤   modexps += retval;
3c3edb ¤   ¤   ¤   ¤   if (f && (retval = f(arg, '.')) < 0)
ebeb0d ¤   ¤   ¤   ¤   ¤   goto done;
59af5a
545f0e ¤   ¤   ¤   ¤   /* And try again */
6857b0 ¤   ¤   ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
--dc9e 000949d64d34010014a Page 6 of bndsaprime.c
d9ae29 ¤   ¤   ¤   } while (p);
2e0fe4 ¤   ¤   }
c9af5a
914c40 ¤   ¤   /* Ran out of sieve space - increase bn and keep trying. */
7af97a #if SIEVE*8*2 >= 65536
8f26ed ¤   ¤   p = ((SIEVE-1)*8+7) - prev;¤/* Number of steps (of 2) */
cb570e ¤   ¤   while (p >= 32737) {
4313d7 ¤   ¤   ¤   if (bnAddQ(bnq, 2*32767) < 0)
ba015a ¤   ¤   ¤   ¤   goto failed;
bb3321 ¤   ¤   ¤   p -= 32767;
4b0fe4 ¤   ¤   }
8658b4 ¤   ¤   if (bnAddQ(bnq, 2*(p+1)) < 0)
2f3507 ¤   ¤   ¤   goto failed;
1adb21 #else
ee398c ¤   ¤   if (bnAddQ(bnq, SIEVE*8*2 - prev) < 0)
103507 ¤   ¤   ¤   goto failed;
397454 #endif
8c137a ¤   ¤   if (f && (retval = f(arg, '/')) < 0)
bc1dc4 ¤   ¤   ¤   goto done;
d3d6a0 ¤   } /* for (;;) */
caaf5a
a4d8af ¤   /*
6d6369 ¤   ·* Phase 2: find a suitable prime bnp == 1 (mod bnq).
1da4e3 ¤   ·*/
adaf5a
ffd8af ¤   /*
8b18bd ¤   ·* Since bnp will be, and bnq is, odd, bnp-1 must be a multiple
6dc572 ¤   ·* of 2*bnq. ·So start by subtracting the excess.
4da4e3 ¤   ·*/
90af5a
225998 phase2:
749167 ¤   /* Double bnq until end of bnp search. */
a9f573 ¤   if (bnAdd(bnq, bnq) < 0)
ed84d6 ¤   ¤   goto failed;
f3af5a
c4617c ¤   bnMod(&a, bnp, bnq);
68444d ¤   if (bnBits(&a)) {¤  /* Will always be true, but... */
6327e9 ¤   ¤   (void)bnSubQ(&a, 1);
4914c7 ¤   ¤   if (bnSub(bnp, &a)) ¤   /* Also error on underflow */
b93507 ¤   ¤   ¤   goto failed;
d59371 ¤   }
3aaf5a
6710f8 ¤   /* Okay, now we're ready. */
73af5a
c8220e ¤   for (;;) {
9761b0 ¤   ¤   if (sieveBuildBig(sieve, SIEVE, bnp, bnq, 0) < 0)
1d3507 ¤   ¤   ¤   goto failed;
bb137a ¤   ¤   if (f && (retval = f(arg, '/')) < 0)
ea1dc4 ¤   ¤   ¤   goto done;
f7af5a
07e284 ¤   ¤   p = prev = 0;
8390d8 ¤   ¤   if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
66f603 ¤   ¤   ¤   do {
ab980e ¤   ¤   ¤   ¤   /*
13cb9f ¤   ¤   ¤   ¤   ·* Adjust bn to have the right value,
e0affb ¤   ¤   ¤   ¤   ·* adding (p-prev) * 2*bnq.
881020 ¤   ¤   ¤   ¤   ·*/
8c6407 ¤   ¤   ¤   ¤   pgpAssert(p >= prev);
8f6094 ¤   ¤   ¤   ¤   /* Compute delta into a */
4c4863 ¤   ¤   ¤   ¤   if (bnMulQ(&a, bnq, p-prev) < 0)
20ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
97287e ¤   ¤   ¤   ¤   if (bnAdd(bnp, &a) < 0)
77ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
295c8f ¤   ¤   ¤   ¤   prev = p;
c9af5a
312c6a ¤   ¤   ¤   ¤   retval = primeTest(bnp, &e, &a, f, arg);
ab5c26 ¤   ¤   ¤   ¤   if (retval <= 0)
31f40b ¤   ¤   ¤   ¤   ¤   goto done;¤ /* Success! */
378abc ¤   ¤   ¤   ¤   modexps += retval;
4f3edb ¤   ¤   ¤   ¤   if (f && (retval = f(arg, '.')) < 0)
f9eb0d ¤   ¤   ¤   ¤   ¤   goto done;
94af5a
--c2e6 00119162b094010014a Page 7 of bndsaprime.c
c95f0e ¤   ¤   ¤   ¤   /* And try again */
8d57b0 ¤   ¤   ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
a5ae29 ¤   ¤   ¤   } while (p);
ab0fe4 ¤   ¤   }
72af5a
cb4c40 ¤   ¤   /* Ran out of sieve space - increase bn and keep trying. */
44abaa #if SIEVE*8 == 65536
ec5dfa ¤   ¤   if (prev) {
08f30b ¤   ¤   ¤   p = (unsigned)(SIEVE*8ul - prev);
1e45a6 ¤   ¤   } else {
d06b78 ¤   ¤   ¤   /* Corner case that will never actually happen */
6276e0 ¤   ¤   ¤   if (bnAdd(bnp, bnq) < 0)
4a015a ¤   ¤   ¤   ¤   goto failed;
947d29 ¤   ¤   ¤   p = 65535;
230fe4 ¤   ¤   }
58db21 #else
f8b054 ¤   ¤   p = SIEVE*8 - prev;
3f7454 #endif
360aa0 ¤   ¤   /* Add p * bnq to bnp */
a8ec45 ¤   ¤   if (bnMulQ(&a, bnq, p) < 0)
aa3507 ¤   ¤   ¤   goto failed;
d066d7 ¤   ¤   if (bnAdd(bnp, &a) < 0)
a93507 ¤   ¤   ¤   goto failed;
afd6a0 ¤   } /* for (;;) */
3caf5a
b6f4b6 failed:
5169ef ¤   retval = -1;
13af5a
adb38c done:
29f2b7 ¤   /* Shift bnq back down by the extra bit again. */
8d2b93 ¤   bnRShift(bnq, 1);¤  /* Harmless even if bnq is random */
0eaf5a
ac4f51 ¤   bnEnd(&e);
913dbd ¤   bnEnd(&a);
6b306a #ifdef MSDOS
2addc8 ¤   bniMemFree(sieve, SIEVE);
38db21 #else
09dd42 ¤   bniMemWipe(sieve, sizeof(sieve));
b87454 #endif
770aa3 ¤   return retval < 0 ? retval : modexps + 2*CONFIRMTESTS;
19efe6 }
--d52e 001e5df0e8c4010014b Page 1 of bndsaprime.h
bc38e5 /*
bb8ae6 ·* $Id: bndsaprime.h,v 1.4 1997/05/09 23:48:50 lloyd Exp $
51495d ·*/
e6af5a
6099c6 PGP_BEGIN_C_DECLARATIONS
f9af5a
6e434c #include "pgpBigNumOpaqueTypes.h"
03af5a
84af5a
d05043 /* Generate a pair of DSS primes */
eaee62 int dsaPrimeGen(BigNum *bnq, BigNum *bnp,
3a3992 ¤   int (*f)(void *arg, int c), void *arg);
e3af5a
e51254 PGP_END_C_DECLARATIONS
--87a4 00021c7489d4010014c Page 1 of bngermain.c
bc38e5 /*
32a955 ·* Sophie Germain prime generation using the bignum library and sieving.
2f775e ·*
7968c2 ·* Written by Colin Plumb.
5e775e ·*
dee943 ·* $Id: bngermain.c,v 1.6 1997/12/11 23:12:01 lloyd Exp $
df495d ·*/
85e2ff #include "pgpConfig.h"
d8af5a
1c4408 #ifndef BNDEBUG
207e00 #define BNDEBUG 0
077454 #endif
7563d6 #if BNDEBUG
7efeb2 #include <stdio.h>
c37454 #endif
25af5a
0d39fc #include "bn.h"
df47e2 #include "bngermain.h"
0e352d #include "bnjacobi.h"
d22602 #include "bnimem.h"¤/* For bniMemWipe */
c7e6d6 #include "bnsieve.h"
6caf5a
3c4724 #include "bnkludge.h"
eea146 #include "pgpDebug.h"
7eaf5a
f6cb8e /* Size of the sieve area (can be up to 65536/8 = 8192) */
4981a7 #define SIEVE 8192
5caf5a
0b0aa0 static unsigned const confirm[] = {2, 3, 5, 7, 11, 13, 17};
1e0565 #define CONFIRMTESTS (sizeof(confirm)/sizeof(*confirm))
51af5a
f363d6 #if BNDEBUG
0938e5 /*
182a92 ·* For sanity checking the sieve, we check for small divisors of the numbers
9e260d ·* we get back. ·This takes "remainder", a partially reduced form of the
a00ed3 ·* prime (the prime modulo some multiple of the divisor) a divisor to check
437925 ·* for, and "order", a parameter of the "order" of Sophie Germain primes
3a1313 ·* (0 = normal primes, 1 = Sophie Germain primes, 2 = 4*p+3 is also prime,
8b9a2b ·* etc.) and does the check. ·It just complains to stdout if the check fails.
e8495d ·*/
a32978 static void
a3fc01 germainSanity(unsigned remainder, unsigned divisor, unsigned order)
4cbb36 {
14a2e6 ¤   unsigned o;
54af5a
1a5eb0 ¤   remainder %= divisor;
75fdb5 ¤   if (!remainder)
dc421c ¤   ¤   printf("bn is divisible by %u!\n", divisor);
20f18f ¤   for (o = 1; o < order; o++) {
be9441 ¤   ¤   remainder += remainder+1;
614432 ¤   ¤   if (remainder >= divisor)
7dea00 ¤   ¤   ¤   remainder -= divisor;
c42502 ¤   ¤   mul += mul;
648741 ¤   ¤   if (!remainder)
a21b9f ¤   ¤   ¤   printf("%u*bn+%u is divisible by %u!\n",
1bbe75 ¤   ¤   ¤   ·······1u<<o, (1u<<o)-1, divisor);
ea9371 ¤   }
d1efe6 }
decab5 #endif /* BNDEBUG */
cdaf5a
e538e5 /*
db1094 ·* Helper function that does the slow primality test.
a23a67 ·* bn is the input bignum; a, e and bn2 are temporary buffers that are
dbac65 ·* allocated by the caller to save overhead. ·bn2 is filled with
204376 ·* a copy of 2^order*bn+2^order-1 if bn is found to be prime.
62775e ·*
51486b ·* Returns 0 if both bn and bn2 are prime, >0 if not prime, and -1 on
39921f ·* error (out of memory). ·If not prime, the return value is the number
d4b020 ·* of modular exponentiations performed. ··Prints a '+' or '-' on the
5b7b77 ·* given FILE (if any) for each test that is passed by bn, and a '*'
8eabcc ·* for each test that is passed by bn2.
21775e ·*
--a08b 000c1c993994010014c Page 2 of bngermain.c
770345 ·* The testing consists of strong pseudoprimality tests, to the bases given
ffbed5 ·* in the confirm[] array above. ·(Also called Miller-Rabin, although that's
fa7984 ·* not technically correct if we're using fixed bases.) ·Some people worry
7b0db3 ·* that this might not be enough. ·Number theorists may wish to generate
a935a3 ·* primality proofs, but for random inputs, this returns non-primes with
62b678 ·* a probability which is quite negligible, which is good enough.
21775e ·*
a8fede ·* It has been proved (see Carl Pomerance, "On the Distribution of
d63036 ·* Pseudoprimes", Math. Comp. v.37 (1981) pp. 587-593) that the number of
3be97e ·* pseudoprimes (composite numbers that pass a Fermat test to the base 2)
b7bd96 ·* less than x is bounded by:
8f42ce ·* exp(ln(x)^(5/14)) <= P_2(x)¤ ### CHECK THIS FORMULA - it looks wrong! ###
d89b29 ·* P_2(x) <= x * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))).
ee6135 ·* Thus, the local density of Pseudoprimes near x is at most
bec53f ·* exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))), and at least
d4af72 ·* exp(ln(x)^(5/14) - ln(x)). ·Here are some values of this function
5fd900 ·* for various k-bit numbers x = 2^k:
f9b1a2 ·* Bits¤Density <=¤ Bit equivalent¤ Density >=¤ Bit equivalent
2cbca8 ·* ·128¤3.577869e-07¤   ·21.414396¤ 4.202213e-37¤   ·120.840190
51d79f ·* ·192¤4.175629e-10¤   ·31.157288¤ 4.936250e-56¤   ·183.724558
b0eef7 ·* ·256 5.804314e-13¤   ·40.647940¤ 4.977813e-75¤   ·246.829095
8fe5c7 ·* ·384 1.578039e-18¤   ·59.136573¤ 3.938861e-113¤  ·373.400096
314e78 ·* ·512 5.858255e-24¤   ·77.175803¤ 2.563353e-151¤  ·500.253110
032492 ·* ·768 1.489276e-34¤   112.370944¤ 7.872825e-228¤  ·754.422724
2530bc ·* 1024 6.633188e-45¤   146.757062¤ 1.882404e-304¤  1008.953565
35775e ·*
5bdc2a ·* As you can see, there's quite a bit of slop between these estimates.
a58e80 ·* In fact, the density of pseudoprimes is conjectured to be closer to the
797bc2 ·* square of that upper bound. ·E.g. the density of pseudoprimes of size
dc897e ·* 256 is around 3 * 10^-27. ·The density of primes is very high, from
4445a3 ·* 0.005636 at 256 bits to 0.001409 at 1024 bits, i.e. ·more than 10^-3.
3d775e ·*
798e57 ·* For those people used to cryptographic levels of security where the
f3f5ae ·* 56 bits of DES key space is too small because it's exhaustible with
97b195 ·* custom hardware searching engines, note that you are not generating
a549fa ·* 50,000,000 primes per second on each of 56,000 custom hardware chips
6e38cc ·* for several hours. ·The chances that another Dinosaur Killer asteroid
ebde2f ·* will land today is about 10^-11 or 2^-36, so it would be better to
a70f04 ·* spend your time worrying about *that*. ·Well, okay, there should be
270937 ·* some derating for the chance that astronomers haven't seen it yet,
a11478 ·* but I think you get the idea. ·For a good feel about the probability
6b57d8 ·* of various events, I have heard that a good book is by E'mile Borel,
521a7c ·* "Les Probabilite's et la vie". ·(The 's are accents, not apostrophes.)
97775e ·*
2e8e80 ·* For more on the subject, try "Finding Four Million Large Random Primes",
8b2be9 ·* by Ronald Rivest, in Advancess in Cryptology: Proceedings of Crypto
72f702 ·* '90. ·He used a small-divisor test, then a Fermat test to the base 2,
aa1633 ·* and then 8 iterations of a Miller-Rabin test. ·About 718 million random
43f268 ·* 256-bit integers were generated, 43,741,404 passed the small divisor
1d2550 ·* test, 4,058,000 passed the Fermat test, and all 4,058,000 passed all
879d55 ·* 8 iterations of the Miller-Rabin test, proving their primality beyond
017b6b ·* most reasonable doubts.
97775e ·*
1be7bd ·* If the probability of getting a pseudoprime is some small p, then the
8c13d1 ·* probability of not getting it in t trials is (1-p)^t. ·Remember that,
b15ec0 ·* for small p, (1-p)^(1/p) ~ 1/e, the base of natural logarithms.
a11db8 ·* (This is more commonly expressed as e = lim_{x\to\infty} (1+1/x)^x.)
79f18b ·* Thus, (1-p)^t ~ e^(-p*t) = exp(-p*t). ·So the odds of being able to
915045 ·* do this many tests without seeing a pseudoprime if you assume that
296e22 ·* p = 10^-6 (one in a million) is one in 57.86. ·If you assume that
60e64f ·* p = 2*10^-6, it's one in 3347.6. ·So it's implausible that the density
9f5953 ·* of pseudoprimes is much more than one millionth the density of primes.
7b775e ·*
085ea5 ·* He also gives a theoretical argument that the chance of finding a
091474 ·* 256-bit non-prime which satisfies one Fermat test to the base 2 is
2c7b87 ·* less than 10^-22. ·The small divisor test improves this number, and
53b75e ·* if the numbers are 512 bits (as needed for a 1024-bit key) the odds
632a44 ·* of failure shrink to about 10^-44. ·Thus, he concludes, for practical
0ec0e1 ·* purposes *one* Fermat test to the base 2 is sufficient.
95495d ·*/
e7beb7 static int
c145a3 germainPrimeTest(BigNum const *bn, BigNum *bn2, BigNum *e,
--25d9 000a9e140194010014c Page 3 of bngermain.c
5a3285 ¤   BigNum *a, unsigned order, int (*f)(void *arg, int c),
daa8b7 ¤   void *arg)
62bb36 {
6417e6 ¤   int err;
14743f ¤   unsigned i;
0fa4c0 ¤   int j;
f6d253 ¤   unsigned k, l, n;
ccaf5a
3024d7 #if BNDEBUG¤/* Debugging */
bdd8af ¤   /*
53dca9 ¤   ·* This is debugging code to test the sieving stage.
28a68c ¤   ·* If the sieving is wrong, it will let past numbers with
d8f84c ¤   ·* small divisors. ·The prime test here will still work, and
105dc7 ¤   ·* weed them out, but you'll be doing a lot more slow tests,
1b4eb6 ¤   ·* and presumably excluding from consideration some other numbers
f0a4b5 ¤   ·* which might be prime. ·This check just verifies that none
d28960 ¤   ·* of the candidates have any small divisors. ·If this
e2a1af ¤   ·* code is enabled and never triggers, you can feel quite
53b693 ¤   ·* confident that the sieving is doing its job.
b5a4e3 ¤   ·*/
4773f7 ¤   i = bnLSWord(bn);
a4ce3b ¤   if (!(i % 2)) printf("bn div by 2!");
4ca0c0 ¤   i = bnModQ(bn, 51051);¤ /* 51051 = 3 * 7 * 11 * 13 * 17 */
71a192 ¤   germainSanity(i, 3, order);
07ffc7 ¤   germainSanity(i, 7, order);
48734c ¤   germainSanity(i, 11, order);
f4d86e ¤   germainSanity(i, 13, order);
17863b ¤   germainSanity(i, 17, order);
f1570d ¤   i = bnModQ(bn, 63365);¤ /* 63365 = 5 * 19 * 23 * 29 */
6754e5 ¤   germainSanity(i, 5, order);
24cfe6 ¤   germainSanity(i, 19, order);
fc5f80 ¤   germainSanity(i, 23, order);
204808 ¤   germainSanity(i, 29, order);
c154b6 ¤   i = bnModQ(bn, 47027);¤ /* 47027 = 31 * 37 * 41 */
b471f7 ¤   germainSanity(i, 31, order);
c68480 ¤   germainSanity(i, 37, order);
1cf36f ¤   germainSanity(i, 41, order);
f77454 #endif
37d8af ¤   /*
7d76a6 ¤   ·* First, check whether bn is prime. ·This uses a fast primality
319a39 ¤   ·* test which usually obviates the need to do one of the
32af30 ¤   ·* confirmation tests later. ·See bnprime.c for a full explanation.
25607c ¤   ·* We check bn first because it's one bit smaller, saving one
568900 ¤   ·* modular squaring, and because we might be able to save another
f4902a ¤   ·* when testing it. ·(1/4 of the time.) ·A small speed hack,
c3e49b ¤   ·* but finding big Sophie Germain primes is *slow*.
37a4e3 ¤   ·*/
4e63a5 ¤   if (bnCopy(e, bn) < 0)
b0043c ¤   ¤   return -1;
cd1819 ¤   (void)bnSubQ(e, 1);
307b30 ¤   l = bnLSWord(e);
baaf5a
67dbfb ¤   j = 1;¤ /* Where to start in prime array for strong prime tests */
71af5a
2f6435 ¤   if (l & 7) {
b019b7 ¤   ¤   bnRShift(e, 1);
9c252f ¤   ¤   if (bnTwoExpMod(a, e, bn) < 0)
af3fd5 ¤   ¤   ¤   return -1;
da7f70 ¤   ¤   if ((l & 7) == 6) {
708aed ¤   ¤   ¤   /* bn == 7 mod 8, expect +1 */
7bdd5e ¤   ¤   ¤   if (bnBits(a) != 1)
6f2a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
271112 ¤   ¤   ¤   k = 1;
b145a6 ¤   ¤   } else {
344ba2 ¤   ¤   ¤   /* bn == 3 or 5 mod 8, expect -1 == bn-1 */
75b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
ebdd34 ¤   ¤   ¤   ¤   return -1;
588b90 ¤   ¤   ¤   if (bnCmp(a, bn) != 0)
fa2a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
f51112 ¤   ¤   ¤   k = 1;
3489a3 ¤   ¤   ¤   if (l & 4) {
a99986 ¤   ¤   ¤   ¤   /* bn == 5 mod 8, make odd for strong tests */
--ed01 000376368994010014c Page 4 of bngermain.c
a3428c ¤   ¤   ¤   ¤   bnRShift(e, 1);
6ac59f ¤   ¤   ¤   ¤   k = 2;
bca3a6 ¤   ¤   ¤   }
030fe4 ¤   ¤   }
adf037 ¤   } else {
39c2cf ¤   ¤   /* bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn */
493c7a ¤   ¤   bnRShift(e, 2);
e8252f ¤   ¤   if (bnTwoExpMod(a, e, bn) < 0)
543fd5 ¤   ¤   ¤   return -1;
d6d8ea ¤   ¤   if (bnBits(a) == 1) {
db2532 ¤   ¤   ¤   j = 0;¤ /* Re-do strong prime test to base 2 */
be45a6 ¤   ¤   } else {
d6b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
d9dd34 ¤   ¤   ¤   ¤   return -1;
4c8b90 ¤   ¤   ¤   if (bnCmp(a, bn) != 0)
bd2a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
b70fe4 ¤   ¤   }
296229 ¤   ¤   k = 2 + bnMakeOdd(e);
299371 ¤   }
03af5a
68af5a
35d8af ¤   /*
2c856d ¤   ·* It's prime! ·Now check higher-order forms bn2 = 2*bn+1, 4*bn+3,
a9b9b9 ¤   ·* etc. ·Since bn2 == 3 mod 4, a strong pseudoprimality test boils
22004e ¤   ·* down to looking at a^((bn2-1)/2) mod bn and seeing if it's +/-1.
4646d4 ¤   ·* (+1 if bn2 is == 7 mod 8, -1 if it's == 3)
a2cd86 ¤   ·* Of course, that exponent is just the previous bn2 or bn...
1fa4e3 ¤   ·*/
40a4a3 ¤   if (bnCopy(bn2, bn) < 0)
723fd5 ¤   ¤   ¤   return -1;
77a5aa ¤   for (n = 0; n < order; n++) {
f31b17 ¤   ¤   /*
112313 ¤   ¤   ·* Print a success indicator: the sign of Jacobi(2,bn2),
6d1d33 ¤   ¤   ·* which is available to us in l. ·bn2 = 2*bn + 1. ·Since bn
3ecfec ¤   ¤   ·* is odd, bn2 must be == 3 mod 4, so the options modulo 8
caa847 ¤   ¤   ·* are 3 and 7. ·3 if l == 1 mod 4, 7 if l == 3 mod 4.
769430 ¤   ¤   ·* The sign of the Jacobi symbol is - and + for these cases,
6fa726 ¤   ¤   ·* respectively.
269de3 ¤   ¤   ·*/
3f1249 ¤   ¤   if (f && (err = f(arg, "-+"[(l >> 1) & 1])) < 0)
cfb32f ¤   ¤   ¤   return err;
5614c7 ¤   ¤   /* Exponent is previous bn2 */
5da14a ¤   ¤   if (bnCopy(e, bn2) < 0 || bnLShift(bn2, 1) < 0)
593fd5 ¤   ¤   ¤   return -1;
0d5e91 ¤   ¤   (void)bnAddQ(bn2, 1);¤  /* Can't overflow */
50a8e2 ¤   ¤   if (bnTwoExpMod(a, e, bn2) < 0)
753fd5 ¤   ¤   ¤   return -1;
ca21c3 ¤   ¤   if (n | l) {¤   /* Expect + */
9edd5e ¤   ¤   ¤   if (bnBits(a) != 1)
077545 ¤   ¤   ¤   ¤   return 2+n;¤/* Not prime */
e245a6 ¤   ¤   } else {
d9b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
dedd34 ¤   ¤   ¤   ¤   return -1;
2136d6 ¤   ¤   ¤   if (bnCmp(a, bn2) != 0)
207545 ¤   ¤   ¤   ¤   return 2+n;¤/* Not prime */
bb0fe4 ¤   ¤   }
6c9c54 ¤   ¤   l = bnLSWord(bn2);
aa9371 ¤   }
06af5a
2fd2f2 ¤   /* Final success indicator - it's in the bag. */
afd68a ¤   if (f && (err = f(arg, '*')) < 0)
65c9db ¤   ¤   return err;
9367c5 ¤
3ad8af ¤   /*
e0d831 ¤   ·* Success! ·We have found a prime! ·Now go on to confirmation
691c55 ¤   ·* tests... ·k is an amount by which we know it's safe to shift
10965d ¤   ·* down e. ·j = 1 unless the test to the base 2 could stand to be
c9c087 ¤   ·* re-done (it wasn't *quite* a strong test), in which case it's 0.
349714 ¤   ·*
39d8e6 ¤   ·* Here, we do the full strong pseudoprimality test. ·This proves
7558a2 ¤   ·* that a number is composite, or says that it's probably prime.
379714 ¤   ·*
--eac2 0009ae7266a4010014c Page 5 of bngermain.c
3f034a ¤   ·* For the given base a, find bn-1 = 2^k * e, then find
22260a ¤   ·* x == a^e (mod bn).
15476b ¤   ·* If x == +1 -> strong pseudoprime to base a
f657bf ¤   ·* Otherwise, repeat k times:
eb2dec ¤   ·* ··If x == -1, -> strong pseudoprime
d7a2fe ¤   ·* ··x = x^2 (mod bn)
c1290d ¤   ·* ··If x = +1 -> composite
fe204f ¤   ·* If we reach the end of the iteration and x is *not* +1, at the
fbe36c ¤   ·* end, it is composite. ·Which means that the squaring actually
b404fb ¤   ·* only has to proceed k-1 times. ·If x is not -1 by then,
e9303e ¤   ·* it's composite no matter what the result of the squaring is.
c19714 ¤   ·*
de19c6 ·¤  ·* For the multiples 2*bn+1, 4*bn+3, etc. then k = 1 (and e is
1cf80c ¤   ·* the previous multiple of bn) so there is no need to do any
1c921b ¤   ·* looping at all.
47a4e3 ¤   ·*/
eaa494 ¤   for (i = j; i < CONFIRMTESTS; i++) {
0b778d ¤   ¤   if (bnCopy(e, bn) < 0)
46dd34 ¤   ¤   ¤   ¤   return -1;
0d100f ¤   ¤   bnRShift(e, k);
78357f ¤   ¤   k += bnMakeOdd(e);
3c461b ¤   ¤   (void)bnSetQ(a, confirm[i]);
948380 ¤   ¤   if (bnExpMod(a, a, e, bn) < 0)
5a3fd5 ¤   ¤   ¤   return -1;
2caf5a
7bb8f0 ¤   ¤   if (bnBits(a) != 1) {
142693 ¤   ¤   ¤   l = k;
e0fb44 ¤   ¤   ¤   for (;;) {
2f5edf ¤   ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
07c91c ¤   ¤   ¤   ¤   ¤   return -1;
117635 ¤   ¤   ¤   ¤   if (bnCmp(a, bn) == 0)¤ /* Was result bn-1? */
ba8c71 ¤   ¤   ¤   ¤   ¤   break;¤ /* Prime */
94b02f ¤   ¤   ¤   ¤   if (!--l)
d69de3 ¤   ¤   ¤   ¤   ¤   return (1+order)*i+2;¤  /* Fail */
1d2528 ¤   ¤   ¤   ¤   /* This part is executed once, on average. */
87f5da ¤   ¤   ¤   ¤   (void)bnSubQ(a, 1);¤/* Restore a */
0b5fe0 ¤   ¤   ¤   ¤   if (bnSquare(a, a) < 0 || bnMod(a, a, bn) < 0)
02c91c ¤   ¤   ¤   ¤   ¤   return -1;
1b25e6 ¤   ¤   ¤   ¤   if (bnBits(a) == 1)
2b07c2 ¤   ¤   ¤   ¤   ¤   return (1+order)*i+1;¤  /* Fail */
5aa3a6 ¤   ¤   ¤   }
fb0fe4 ¤   ¤   }
fbaf5a
2a1ff5 ¤   ¤   if (bnCopy(bn2, bn) < 0)
4f3fd5 ¤   ¤   ¤   return -1;
d167c5 ¤
60b0c8 ¤   ¤   /* Only do the following if we're not re-doing base 2 */
8bad84 ¤   ¤   if (i) for (n = 0; n < order; n++) {
4a2e1d ¤   ¤   ¤   if (bnCopy(e, bn2) < 0 || bnLShift(bn2, 1) < 0)
3edd34 ¤   ¤   ¤   ¤   return -1;
07fd0b ¤   ¤   ¤   (void)bnAddQ(bn2, 1);
beaf5a
48a2ad ¤   ¤   ¤   /* Print success indicator for previous test */
0f684f ¤   ¤   ¤   j = bnJacobiQ(confirm[i], bn2);
89860c ¤   ¤   ¤   if (f && (err = f(arg, j < 0 ? '-' : '+')) < 0)
cc454a ¤   ¤   ¤   ¤   return err;
fdaf5a
2eadea ¤   ¤   ¤   /* Check that p^e == Jacobi(p,bn2) (mod bn2) */
1443f6 ¤   ¤   ¤   (void)bnSetQ(a, confirm[i]);
d37ddf ¤   ¤   ¤   if (bnExpMod(a, a, e, bn2) < 0)
93dd34 ¤   ¤   ¤   ¤   return -1;
657aad ¤   ¤   ¤   /*
632fd2 ¤   ¤   ¤   ·* FIXME: ·Actually, we don't need to compute the
d3ac63 ¤   ¤   ¤   ·* Jacobi symbol externally... it never happens that
16e0c7 ¤   ¤   ¤   ·* a = +/-1 but it's the wrong one. ·So we can just
8e1c20 ¤   ¤   ¤   ·* look at a and use its sign. ·Find a proof somewhere.
698753 ¤   ¤   ¤   ·*/
785c32 ¤   ¤   ¤   if (j < 0) {
47031e ¤   ¤   ¤   ¤   /* Not a Q.R., should have a = ·bn2-1 */
635edf ¤   ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
c5c91c ¤   ¤   ¤   ¤   ¤   return -1;
9a6bc6 ¤   ¤   ¤   ¤   if (bnCmp(a, bn2) != 0)¤/* Was result bn2-1? */
--c573 000b60a24324010014c Page 6 of bngermain.c
8dfcb6 ¤   ¤   ¤   ¤   ¤   return (1+order)*i+n+2;¤/* Fail */
b5042d ¤   ¤   ¤   } else {
de54d7 ¤   ¤   ¤   ¤   /* Quadratic residue, should have a = 1 */
6c56a2 ¤   ¤   ¤   ¤   if (bnBits(a) != 1)
04fcb6 ¤   ¤   ¤   ¤   ¤   return (1+order)*i+n+2;¤/* Fail */
eca3a6 ¤   ¤   ¤   }
7a0fe4 ¤   ¤   }
992e65 ¤   ¤   /* Final success indicator for the base confirm[i]. */
85ea64 ¤   ¤   if (f && (err = f(arg, '*')) < 0)
f7b32f ¤   ¤   ¤   return err;
e99371 ¤   }
99af5a
e76c87 ¤   return 0;¤  /* Prime! */
b3efe6 }
91af5a
8138e5 /*
5badb9 ·* Add x*y to bn, which is usually (but not always) < 65536.
cd3e74 ·* Do it in a simple linear manner.
b3495d ·*/
56beb7 static int
3094d4 bnAddMult(BigNum *bn, unsigned long x, unsigned y)
00bb36 {
913cfe ¤   unsigned long z = (unsigned long)x * y;
61af5a
c95a22 ¤   while (z > 65535) {
9e3292 ¤   ¤   if (bnAddQ(bn, 65535) < 0)
893fd5 ¤   ¤   ¤   return -1;
fe6097 ¤   ¤   z -= 65535;
879371 ¤   }
118ee8 ¤   return bnAddQ(bn, (unsigned)z);
67efe6 }
f1af5a
cc38e5 /*
5c9016 ·* Modifies the bignum to return the next Sophie Germain prime >= the
01834a ·* input value. ·Sohpie Germain primes are number such that p is
3a8587 ·* prime and 2*p+1 is also prime.
11775e ·*
e5f9de ·* This is actually parameterized: it generates primes p such that "order"
2622f4 ·* multiples-plus-two are also prime, 2*p+1, 2*(2*p+1)+1 = 4*p+3, etc.
73775e ·*
598f56 ·* Returns >=0 on success or -1 on failure (out of memory). ·On success,
9cd771 ·* the return value is the number of modular exponentiations performed
1d56ca ·* (excluding the final confirmations). ·This never gives up searching.
11775e ·*
ec813d ·* The FILE *f argument, if non-NULL, has progress indicators written
77d367 ·* to it. ·A dot (.) is written every time a primeality test is failed,
4f90c4 ·* a plus (+) or minus (-) when the smaller prime of the pair passes a
d21829 ·* test, and a star (*) when the larger one does. ·Finally, a slash (/)
b173e2 ·* is printed when the sieve was emptied without finding a prime and is
e8446b ·* being refilled.
4e775e ·*
6bd724 ·* Apologies to structured programmers for all the GOTOs.
87495d ·*/
f94d2f int
baa325 bnGermainPrimeGen(BigNum *bn, unsigned order,
1a71b8 ¤   int (*f)(void *arg, int c), void *arg)
c4bb36 {
8a13a5 ¤   int retval;
e0d823 ¤   unsigned p, prev;
06df8b ¤   unsigned inc;
0a6597 ¤   BigNum a, e, bn2;
f6de1b ¤   int modexps = 0;
c1306a #ifdef MSDOS
abd052 ¤   unsigned char *sieve;
47db21 #else
610aa9 ¤   unsigned char sieve[SIEVE];
437454 #endif
e11c7f ¤   PGPBoolean¤ ¤   isSecure¤   = bn->isSecure;
a19353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
b3af5a
07306a #ifdef MSDOS
b6af13 ¤   sieve = bniMemAlloc(SIEVE);
--d2e6 00049ae7fbf4010014c Page 7 of bngermain.c
20ca71 ¤   if (!sieve)
fb043c ¤   ¤   return -1;
237454 #endif
91af5a
218337 ¤   bnBegin(&a, mgr, isSecure);
e8de31 ¤   bnBegin(&e, mgr, isSecure);
7eae85 ¤   bnBegin(&bn2, mgr, isSecure);
d0af5a
6fd8af ¤   /*
ac96d7 ¤   ·* Obviously, the prime we find must be odd. ·Further, if 2*p+1
bbf35b ¤   ·* is also to be prime (order > 0) then p != 1 (mod 3), lest
85a001 ¤   ·* 2*p+1 == 3 (mod 3). ·Added to p != 3 (mod 3), p == 2 (mod 3)
18d9ec ¤   ·* and p == 5 (mod 6).
aa4a1c ¤   ·* If order > 2 and we care about 4*p+3 and 8*p+7, then similarly
1bcd4a ¤   ·* p == 4 (mod 5), so p == 29 (mod 30).
831485 ¤   ·* So pick the step size for searching based on the order
319664 ¤   ·* and increse bn until it's == -1 (mod inc).
d19714 ¤   ·*
f7730b ¤   ·* mod 7 doesn't have a unique value for p because 2 -> 5 -> 4 -> 2,
d44c33 ¤   ·* nor does mod 11, and I don't want to think about things past
c2fdfa ¤   ·* that. ·The required order would be impractically high, in any case.
3fa4e3 ¤   ·*/
c0fbf7 ¤   inc = order ? ((order > 2) ? 30 : 6) : 2;
c0a5a9 ¤   if (bnAddQ(bn, inc-1 - bnModQ(bn, inc)) < 0)
b284d6 ¤   ¤   goto failed;
9daf5a
c2220e ¤   for (;;) {
15c89e ¤   ¤   if (sieveBuild(sieve, SIEVE, bn, inc, order) < 0)
5d3507 ¤   ¤   ¤   goto failed;
b7af5a
3ce284 ¤   ¤   p = prev = 0;
8490d8 ¤   ¤   if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
21f603 ¤   ¤   ¤   do {
e1a321 ¤   ¤   ¤   ¤   /* Adjust bn to have the right value. */
d46407 ¤   ¤   ¤   ¤   pgpAssert(p >= prev);
1eb546 ¤   ¤   ¤   ¤   if (bnAddMult(bn, p-prev, inc) < 0)
47ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
d25c8f ¤   ¤   ¤   ¤   prev = p;
c5af5a
6fb69b ¤   ¤   ¤   ¤   /* Okay, do the strong tests. */
cf6b79 ¤   ¤   ¤   ¤   retval = germainPrimeTest(bn, &bn2, &e, &a,
267d9d ¤   ¤   ¤   ¤   ··························order, f, arg);
fc5c26 ¤   ¤   ¤   ¤   if (retval <= 0)
72eb0d ¤   ¤   ¤   ¤   ¤   goto done;
6c8abc ¤   ¤   ¤   ¤   modexps += retval;
353edb ¤   ¤   ¤   ¤   if (f && (retval = f(arg, '.')) < 0)
89eb0d ¤   ¤   ¤   ¤   ¤   goto done;
83af5a
405f0e ¤   ¤   ¤   ¤   /* And try again */
bd57b0 ¤   ¤   ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
19ae29 ¤   ¤   ¤   } while (p);
550fe4 ¤   ¤   }
79af5a
e54c40 ¤   ¤   /* Ran out of sieve space - increase bn and keep trying. */
f1edd2 ¤   ¤   if (bnAddMult(bn, (unsigned long)SIEVE*8-prev, inc) < 0)
ce3507 ¤   ¤   ¤   goto failed;
d4137a ¤   ¤   if (f && (retval = f(arg, '/')) < 0)
c11dc4 ¤   ¤   ¤   goto done;
30d6a0 ¤   } /* for (;;) */
60af5a
75f4b6 failed:
d469ef ¤   retval = -1;
56b38c done:
13759f ¤   bnEnd(&bn2);
a94f51 ¤   bnEnd(&e);
333dbd ¤   bnEnd(&a);
9e306a #ifdef MSDOS
ebddc8 ¤   bniMemFree(sieve, SIEVE);
1fdb21 #else
b2dd42 ¤   bniMemWipe(sieve, sizeof(sieve));
7a7454 #endif
49b557 ¤   return retval < 0 ? retval : modexps+(order+1)*CONFIRMTESTS;
--f8fa 0017a44eea54010014c Page 8 of bngermain.c
7aefe6 }
--a84c 00168e2c2dc4010014d Page 1 of bngermain.h
bc38e5 /*
403618 ·* $Id: bngermain.h,v 1.6 1997/05/13 01:18:37 mhw Exp $
ff495d ·*/
c1af5a
fc455b #ifndef Included_bngermain_h
38c46d #define Included_bngermain_h
83af5a
c6c5d5 #include "pgpBase.h"
87af5a
a899c6 PGP_BEGIN_C_DECLARATIONS
ffaf5a
b8bdbd #include "pgpBigNumOpaqueStructs.h"
8aaf5a
7a1b33 /* Generate a Sophie Germain prime */
ce9f53 int bnGermainPrimeGen(BigNum *bn, unsigned dbl,
573992 ¤   int (*f)(void *arg, int c), void *arg);
14af5a
661254 PGP_END_C_DECLARATIONS
2faf5a
68d6fe #endif /* Included_bngermain_h */
--96f5 0003a01b6264010014e Page 1 of bni.h
bc38e5 /*
4e010a ·* bni.h - Low-level bignum header.
c2ca1a ·* Defines various word sizes and useful macros.
fb775e ·*
f8fbf7 ·* Written by Colin Plumb
d7775e ·*
bef208 ·* $Id: bni.h,v 1.6 1997/05/13 01:18:38 mhw Exp $
d1495d ·*/
618e55 #ifndef Included_bni_h
79d9a4 #define Included_bni_h
feaf5a
45e2ff #include "pgpConfig.h"
84c5d5 #include "pgpBase.h"
02af5a
3b38e5 /*
8e16cf ·* Some compilers complain about #if FOO if FOO isn't defined,
0b59aa ·* so do the ANSI-mandated thing explicitly...
94495d ·*/
fad8d3 #ifndef NO_LIMITS_H
ec1a2a #define NO_LIMITS_H 0
887454 #endif
e5af5a
ccc619 /* Make sure we have 8-bit bytes */
961be9 #if !NO_LIMITS_H
e8a7a0 #include <limits.h>
245bc4 #if UCHAR_MAX != 0xff || CHAR_BIT != 8
87f240 #error The bignum library requires 8-bit unsigned characters.
9b7454 #endif
db635e #endif /* !NO_LIMITS_H */
36af5a
dd0c42 #ifdef BNINCLUDE¤   /* If this is defined as, say, foo.h */
a62094 #define STR(x) #x¤  /* STR(BNINCLUDE) -> "BNINCLUDE" */
167682 #define XSTR(x) STR(x)¤ /* XSTR(BNINCLUDE) -> STR(foo.h) -> "foo.h" */
d6b8d5 #include XSTR(BNINCLUDE)¤   /* #include "foo.h" */
a6e694 #undef XSTR
e654f6 #undef STR
9f7454 #endif
4aaf5a
d4aa52 /* Do we want bnYield()? */
992095 #ifndef BNYIELD
86f207 #define BNYIELD 0
8d7454 #endif
eeaf5a
72e176 /* Figure out the endianness */
cb6f28 /* Error if more than one is defined */
d7dcdb #if BN_BIG_ENDIAN && BN_LITTLE_ENDIAN
42a3d7 #error Only one of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN may be defined
307454 #endif
c7af5a
df38e5 /*
d2eddc ·* If no preference is stated, little-endian C code is slightly more
940f4f ·* efficient, so prefer that. ·(The endianness here does NOT have to
b5d6db ·* match the machine's native byte sex; the library's C code will work
1dc16f ·* either way. ·The flexibility is allowed for assembly routines
d546ad ·* that do care.
32495d ·*/
79a455 #if !defined(BN_BIG_ENDIAN) && !defined(BN_LITTLE_ENDIAN)
5d7be2 #define BN_LITTLE_ENDIAN 1
9212ae #endif /* !BN_BIG_ENDIAN && !BN_LITTLE_ENDIAN */
76af5a
969a03 /* Macros to choose between big and little endian */
c01f71 #if BN_BIG_ENDIAN
50a60e #define BIG(b) b
320ae2 #define LITTLE(l) /*nothing*/
435684 #define BIGLITTLE(b,l) b
e3041a #elif BN_LITTLE_ENDIAN
06e54a #define BIG(b) /*nothing*/
64f7c7 #define LITTLE(l) l
2fcc94 #define BIGLITTLE(b,l) l
eddb21 #else
1849f4 #error One of BN_BIG_ENDIAN or BN_LITTLE_ENDIAN must be defined as 1
3a7454 #endif
--3eda 0003f61ea114010014e Page 2 of bni.h
e0af5a
1aaf5a
9938e5 /*
6fc87a ·* Find a 16-bit unsigned type.
c3f306 ·* Unsigned short is preferred over unsigned int to make the type chosen
26cce1 ·* by this file more stable on platforms (such as many 68000 compilers)
b6e9cd ·* which support both 16- and 32-bit ints.
be495d ·*/
3635a6 #ifndef BNWORD16
e0f6b9 #ifndef USHRT_MAX¤  /* No <limits.h> available - guess */
8fe08e typedef unsigned short bnword16;
864434 #define BNWORD16 bnword16
29e688 #elif USHRT_MAX == 0xffff
d3e08e typedef unsigned short bnword16;
824434 #define BNWORD16 bnword16
8aeff0 #elif UINT_MAX == 0xffff
84a791 typedef unsigned bnword16;
1b4434 #define BNWORD16 bnword16
077454 #endif
399462 #endif /* BNWORD16 */
93af5a
c338e5 /*
8e4f61 ·* Find a 32-bit unsigned type.
ec3f66 ·* Unsigned long is preferred over unsigned int to make the type chosen
62cce1 ·* by this file more stable on platforms (such as many 68000 compilers)
a9e9cd ·* which support both 16- and 32-bit ints.
78495d ·*/
b5e77e #ifndef BNWORD32
f40580 #ifndef ULONG_MAX¤  /* No <limits.h> available - guess */
1769da typedef unsigned long bnword32;
58ca02 #define BNWORD32 bnword32
bb6e15 #elif ULONG_MAX == 0xfffffffful
7269da typedef unsigned long bnword32;
23ca02 #define BNWORD32 bnword32
087dfb #elif UINT_MAX == 0xffffffff
c7fd86 typedef unsigned bnword32;
edca02 #define BNWORD32 bnword32
105e78 #elif USHRT_MAX == 0xffffffff
72ba99 typedef unsigned short bnword32;
d7ca02 #define BNWORD32 bnword32
c37454 #endif
579462 #endif /* BNWORD16 */
72af5a
d938e5 /*
5fe002 ·* Find a 64-bit unsigned type.
a5bfb2 ·* The conditions here are more complicated to avoid using numbers that
8a360b ·* will choke lesser preprocessors (like 0xffffffffffffffff) unless
a74bcb ·* we're reasonably certain that they'll be acceptable.
ee495d ·*/
f6aacb #if !defined(BNWORD64) && ULONG_MAX > 0xfffffffful
9e1b1a #if ULONG_MAX == 0xffffffffffffffff
88d154 typedef unsigned long bnword64;
65d23b #define BNWORD64 bnword64
3b7454 #endif
4c7454 #endif
daaf5a
1238e5 /*
9e1041 ·* I would test the value of unsigned long long, but some *preprocessors*
a27c5d ·* can't parse constants that long even if the compiler can accept them, so it
2ba8c8 ·* doesn't work reliably. ·So cross our fingers and hope that it's a 64-bit
ce37ce ·* type.
70775e ·*
919fbf ·* GCC uses ULONG_LONG_MAX. ·Solaris uses ULLONG_MAX. ·IRIX and Metrowerks use
6b9b09 ·* ULONGLONG_MAX. ·Are there any other names for this?
d7495d ·*/
34af5a
708a13 #ifndef BNWORD64
c4a8d7 #if defined(ULONG_LONG_MAX)¤/* GCC uses this */
0d4f25 typedef unsigned long long bnword64;
e2d23b #define BNWORD64 bnword64
0e5248 #elif defined(ULLONG_MAX)¤  /* Solaris */
3f1302 /* Solaris defines ULLONG_MAX with ..ll, which its preprocessor chokes on.
--91c9 0013cfb88f04010014e Page 3 of bni.h
009414 ·* So we can't test the value. ·Just assume that it's 64 bits... */
934f25 typedef unsigned long long bnword64;
acd23b #define BNWORD64 bnword64
a0cf9b #elif defined(ULONGLONG_MAX) /* IRIX and Metrowerks */
8038e5 /*
ba58b9 ·* Metrowerks always defines ULONGLONG_MAX, but it may be
ade437 ·* equal to ULONG_MAX in some cases, so we have to test its value.
0c7a09 ·* Unformtunately, its preprocessor silently truncates to 32 bits!
f4495d ·*/
f6256f #if ULONGLONG_MAX > ULONG_MAX
c3be76 /* Case 1: preprocessor works */
444f25 typedef unsigned long long bnword64;
cad23b #define BNWORD64 bnword64
c55c28 #elif LONGLONG_MAX == LONGLONG_MIN
55c298 /* Case 2: Preprocessor silently truncates to 32 bits */
654f25 typedef unsigned long long bnword64;
e2d23b #define BNWORD64 bnword64
b37454 #endif
865c85 #endif /* ULONGLONG_MAX */
9a6feb #endif /* !BNWORD64 */
89af5a
7b2efd /* We don't even try to find a 128-bit type at the moment */
e1af5a
3c408a #endif /* !Included_bni_h */
--7976 001466dbfd94010014f Page 1 of bni00.c
bc38e5 /*
6f665b ·* bni00.c - auto-size-detecting bni??.c file.
bc775e ·*
f6001b ·* Written in 1995 by Colin Plumb.
6d775e ·*
670645 ·* $Id: bni00.c,v 1.1 1997/04/30 08:36:09 mhw Exp $
b9495d ·*/
9faf5a
10afa6 #include "bnsize00.h"
c0af5a
0e84d0 #if BNSIZE64
94af5a
e9a754 /* Include all of the C source file by reference */
901667 #include "bni64.c"
93af5a
0241e3 #elif BNSIZE32
40af5a
1fa754 /* Include all of the C source file by reference */
963978 #include "bni32.c"
ecaf5a
189a11 #else /* BNSIZE16 */
e2af5a
52a754 /* Include all of the C source file by reference */
f01c3e #include "bni16.c"
aeaf5a
467454 #endif
--1184 0008d57027540100150 Page 1 of bni16.c
bc38e5 /*
c4001f ·* bni16.c - Low-level bignum routines, 16-bit version.
6b775e ·*
6a68c2 ·* Written by Colin Plumb.
5d775e ·*
855fb8 ·* $Id: bni16.c,v 1.6 1998/02/22 06:38:18 heller Exp $
2e775e ·*
713a1e ·* NOTE: the magic constants "16" and "32" appear in many places in this
0add4e ·* file, including inside identifiers. ·Because it is not possible to
e29667 ·* ask "#ifdef" of a macro expansion, it is not possible to use the
c6b031 ·* preprocessor to conditionalize these properly. ·Thus, this file is
8acef9 ·* intended to be edited with textual search and replace to produce
3bd844 ·* alternate word size versions. ·Any reference to the number of bits
aeeb72 ·* in a word must be the string "16", and that string must not appear
d8d008 ·* otherwise. ·Any reference to twice this number must appear as "32",
96d7d6 ·* which likewise must not appear otherwise. ·Is that clear?
75775e ·*
9329af ·* Remember, when doubling the bit size replace the larger number (32)
71c563 ·* first, then the smaller (16). ·When halving the bit size, do the
0a0005 ·* opposite. ·Otherwise, things will get wierd. ·Also, be sure to replace
6fdfda ·* every instance that appears. ·(:%s/foo/bar/g in vi)
f8775e ·*
90496a ·* These routines work with a pointer to the least-significant end of
8c5bff ·* an array of WORD16s. ·The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros
4e3864 ·* defined in bni.h (which expand to x on a big-edian machine and y on a
d34cbc ·* little-endian machine) are used to conditionalize the code to work
56fc72 ·* either way. ·If you have no assembly primitives, it doesn't matter.
c483f3 ·* Note that on a big-endian machine, the least-significant-end pointer
92144c ·* is ONE PAST THE END. ·The bytes are ptr[-1] through ptr[-len].
c78d7a ·* On little-endian, they are ptr[0] through ptr[len-1]. ·This makes
61fd96 ·* perfect sense if you consider pointers to point *between* bytes rather
b9f32b ·* than at them.
0f775e ·*
f9f6ef ·* Because the array index values are unsigned integers, ptr[-i]
0d53f2 ·* may not work properly, since the index -i is evaluated as an unsigned,
1d0a10 ·* and if pointers are wider, zero-extension will produce a positive
dcda4d ·* number rahter than the needed negative. ·The expression used in this
54eb52 ·* code, *(ptr-i) will, however, work. ·(The array syntax is equivalent
0bfbc0 ·* to *(ptr+-i), which is a pretty subtle difference.)
3e775e ·*
a3bcef ·* Many of these routines will get very unhappy if fed zero-length inputs.
9909f7 ·* They use pgpAssert() to enforce this. ·An higher layer of code must make
62aed6 ·* sure that these aren't called with zero-length inputs.
ec775e ·*
c28e44 ·* Any of these routines can be replaced with more efficient versions
ce26b0 ·* elsewhere, by just #defining their names. ·If one of the names
a6f8b6 ·* is #defined, the C code is not compiled in and no declaration is
a0cdae ·* made. ·Use the BNINCLUDE file to do that. ·Typically, you compile
47a2ad ·* asm subroutines with the same name and just, e.g.
cab758 ·* #define bniMulAdd1_16 bniMulAdd1_16
63775e ·*
08b9f1 ·* If you want to write asm routines, start with bniMulAdd1_16().
7f0a7e ·* This is the workhorse of modular exponentiation. ·bniMulN1_16() is
1a364f ·* also used a fair bit, although not as much and it's defined in terms
e8b0dc ·* of bniMulAdd1_16 if that has a custom version. ·bniMulSub1_16 and
c68dc0 ·* bniDiv21_16 are used in the usual division and remainder finding.
738548 ·* (Not the Montgomery reduction used in modular exponentiation, though.)
ace3b1 ·* Once you have bniMulAdd1_16 defined, writing the other two should
6d0aae ·* be pretty easy. ·(Just make sure you get the sign of the subtraction
f5a2a8 ·* in bniMulSub1_16 right - it's dest = dest - source * k.)
cd775e ·*
b0d815 ·* The only definitions that absolutely need a double-word (BNWORD32)
488ff6 ·* type are bniMulAdd1_16 and bniMulSub1_16; if those are provided,
d1fece ·* the rest follows. ·bniDiv21_16, however, is a lot slower unless you
7e92b0 ·* have them, and bniModQ_16 takes after it. ·That one is used quite a
2770b6 ·* bit for prime sieving.
27495d ·*/
3aaf5a
dce2ff #include "pgpConfig.h"
5baf5a
3238e5 /*
8d16cf ·* Some compilers complain about #if FOO if FOO isn't defined,
--ee82 000b8442dae40100150 Page 2 of bni16.c
e259aa ·* so do the ANSI-mandated thing explicitly...
42495d ·*/
44c60f #ifndef NO_ASSERT_H
22154e #define NO_ASSERT_H 0
ab7454 #endif
72b552 #ifndef NO_STRING_H
3537dd #define NO_STRING_H 0
0f7454 #endif
268537 #ifndef HAVE_STRINGS_H
58025c #define HAVE_STRINGS_H 0
187454 #endif
1b101b #ifndef NEED_MEMORY_H
11ee50 #define NEED_MEMORY_H 0
3a7454 #endif
8faf5a
767668 #if !NO_STRING_H
d77210 #include <string.h>¤/* For memcpy */
15a752 #elif HAVE_STRINGS_H
a3f7c3 #include <strings.h>
3d7454 #endif
983c37 #if NEED_MEMORY_H
66c737 #include <memory.h>
207454 #endif
6faf5a
79a6ac #include "bni.h"
463598 #include "bni16.h"
6e21db #include "bnimem.h"
248cb6 #include "bnlegal.h"
64af5a
bc4724 #include "bnkludge.h"
69a146 #include "pgpDebug.h"
a2af5a
bd35a6 #ifndef BNWORD16
3386c9 #error 16-bit bignum library requires a 16-bit data type
767454 #endif
5caf5a
f9bfe9 /* Make sure the copyright notice gets included */
b0e326 volatile const char * volatile const bniCopyright_16 = bnCopyright;
bfaf5a
dee387 /* If this is defined, include bnYield() calls */
35074b #if BNYIELD
2a976d extern int (*bnYield)(void);¤   /* From bn.c */
7d7454 #endif
a9af5a
2a38e5 /*
f8d5df ·* Most of the multiply (and Montgomery reduce) routines use an outer
179462 ·* loop that iterates over one of the operands - a so-called operand
e6398d ·* scanning approach. ·One big advantage of this is that the assembly
961aea ·* support routines are simpler. ·The loops can be rearranged to have
91b971 ·* an outer loop that iterates over the product, a so-called product
186c0d ·* scanning approach. ·This has the advantage of writing less data
fec3ee ·* and doing fewer adds to memory, so is supposedly faster. ·Some
ab80d7 ·* code has been written using a product-scanning approach, but
263d3c ·* it appears to be slower, so it is turned off by default. ·Some
d55e9d ·* experimentation would be appreciated.
d6775e ·*
5a6dd6 ·* (The code is also annoying to get right and not very well commented,
5f6688 ·* one of my pet peeves about math libraries. ·I'm sorry.)
22495d ·*/
827621 #ifndef PRODUCT_SCAN
f01212 #define PRODUCT_SCAN 0
9c7454 #endif
2eaf5a
7c38e5 /*
cd2e0a ·* Copy an array of words. ·<Marvin mode on> ·Thrilling, isn't it? </Marvin>
0d01c1 ·* This is a good example of how the byte offsets and BIGLITTLE() macros work.
a7b38e ·* Another alternative would have been
7116fa ·* memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD16)), but I find that
2984f4 ·* putting operators into conditional macros is confusing.
38495d ·*/
db0df8 #ifndef bniCopy_16
b8314a void
--a5b7 000b43df2bb40100150 Page 3 of bni16.c
f713e8 bniCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len)
83bb36 {
5d0967 ¤   memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src),
6eda8b ¤   ·······len * sizeof(*src));
5aefe6 }
9ad698 #endif /* !bniCopy_16 */
a6af5a
c238e5 /*
e13e9e ·* Fill n words with zero. ·This does it manually rather than calling
216f32 ·* memset because it can assume alignment to make things faster while
29c78d ·* memset can't. ·Note how big-endian numbers are naturally addressed
392867 ·* using predecrement, while little-endian is postincrement.
e4495d ·*/
ba945a #ifndef bniZero_16
ad314a void
da1366 bniZero_16(BNWORD16 *num, unsigned len)
79bb36 {
83e87e ¤   while (len--)
8184f4 ¤   ¤   BIGLITTLE(*--num,*num++) = 0;
56efe6 }
eda2b2 #endif /* !bniZero_16 */
47af5a
f038e5 /*
9f5fe5 ·* Negate an array of words.
943551 ·* Negation is subtraction from zero. ·Negating low-order words
67af4a ·* entails doing nothing until a non-zero word is hit. ·Once that
24a81f ·* is negated, a borrow is generated and never dies until the end
86c1bd ·* of the number is hit. ·Negation with borrow, -x-1, is the same as ~x.
ae24aa ·* Repeat that until the end of the number.
f2775e ·*
10bb91 ·* Doesn't return borrow out because that's pretty useless - it's
16e078 ·* always set unless the input is 0, which is easy to notice in
d20df0 ·* normalized form.
b6495d ·*/
0c7472 #ifndef bniNeg_16
d8314a void
0a4fc1 bniNeg_16(BNWORD16 *num, unsigned len)
e6bb36 {
d486c8 ¤   pgpAssert(len);
1caf5a
7d043a ¤   /* Skip low-order zero words */
1ecadc ¤   while (BIGLITTLE(*--num,*num) == 0) {
6e253f ¤   ¤   if (!--len)
f40ecc ¤   ¤   ¤   return;
29c728 ¤   ¤   LITTLE(num++;)
7c9371 ¤   }
2887c2 ¤   /* Negate the lowest-order non-zero word */
4ea8e3 ¤   *num = -*num;
54e4e5 ¤   /* Complement all the higher-order words */
4be1ea ¤   while (--len) {
8810b0 ¤   ¤   BIGLITTLE(--num,++num);
ca48d8 ¤   ¤   *num = ~*num;
869371 ¤   }
cdefe6 }
7f85d9 #endif /* !bniNeg_16 */
99af5a
f4af5a
c838e5 /*
b24b6f ·* bniAdd1_16: add the single-word "carry" to the given number.
0e976d ·* Used for minor increments and propagating the carry after
3d674c ·* adding in a shorter bignum.
e1775e ·*
f9ce8e ·* Technique: If we have a double-width word, presumably the compiler
b2afd8 ·* can add using its carry in inline code, so we just use a larger
40f5de ·* accumulator to compute the carry from the first addition.
a2f394 ·* If not, it's more complex. ·After adding the first carry, which may
e5696d ·* be > 1, compare the sum and the carry. ·If the sum wraps (causing a
24c7d9 ·* carry out from the addition), the result will be less than each of the
876830 ·* inputs, since the wrap subtracts a number (2^16) which is larger than
239c68 ·* the other input can possibly be. ·If the sum is >= the carry input,
75739c ·* return success immediately.
b4a2cb ·* In either case, if there is a carry, enter a loop incrementing words
--0113 0000e88484f40100150 Page 4 of bni16.c
d66969 ·* until one does not wrap. ·Since we are adding 1 each time, the wrap
00b4b5 ·* will be to 0 and we can test for equality.
95495d ·*/
b9de43 #ifndef bniAdd1_16¤ /* If defined, it's provided as an asm subroutine */
a55a8c #ifdef BNWORD32
e03401 BNWORD16
b1c872 bniAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
47bb36 {
3af9fc ¤   BNWORD32 t;
de9c94 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return carry */
52af5a
7bbe24 ¤   t = (BNWORD32)BIGLITTLE(*--num,*num) + carry;
5db40c ¤   BIGLITTLE(*num,*num++) = (BNWORD16)t;
535e83 ¤   if ((t >> 16) == 0)
efbbde ¤   ¤   return 0;
f4e1ea ¤   while (--len) {
172439 ¤   ¤   if (++BIGLITTLE(*--num,*num++) != 0)
658144 ¤   ¤   ¤   return 0;
d59371 ¤   }
e464b7 ¤   return 1;
8fefe6 }
99c626 #else /* no BNWORD32 */
373401 BNWORD16
3bc872 bniAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
85bb36 {
169c94 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return carry */
54af5a
4c9c40 ¤   if ((BIGLITTLE(*--num,*num++) += carry) >= carry)
4abbde ¤   ¤   return 0;
f5e1ea ¤   while (--len) {
4a2439 ¤   ¤   if (++BIGLITTLE(*--num,*num++) != 0)
1f8144 ¤   ¤   ¤   return 0;
7e9371 ¤   }
8964b7 ¤   return 1;
49efe6 }
c77454 #endif
be08cf #endif/* !bniAdd1_16 */
6baf5a
8238e5 /*
258e58 ·* bniSub1_16: subtract the single-word "borrow" from the given number.
988db0 ·* Used for minor decrements and propagating the borrow after
81455f ·* subtracting a shorter bignum.
47775e ·*
6736de ·* Technique: Similar to the add, above. ·If there is a double-length type,
b2c57d ·* use that to generate the first borrow.
c425ae ·* If not, after subtracting the first borrow, which may be > 1, compare
227f2c ·* the difference and the *negative* of the carry. ·If the subtract wraps
e08a8c ·* (causing a borrow out from the subtraction), the result will be at least
519bc7 ·* as large as -borrow. ·If the result < -borrow, then no borrow out has
189e3c ·* appeared and we may return immediately, except when borrow == 0. ·To
5ae027 ·* deal with that case, use the identity that -x = ~x+1, and instead of
2557ce ·* comparing < -borrow, compare for <= ~borrow.
f2464d ·* Either way, if there is a borrow out, enter a loop decrementing words
d6fe08 ·* until a non-zero word is reached.
1c775e ·*
a3de67 ·* Note the cast of ~borrow to (BNWORD16). ·If the size of an int is larger
e8c6cb ·* than BNWORD16, C rules say the number is expanded for the arithmetic, so
0547f5 ·* the inversion will be done on an int and the value won't be quite what
02bf20 ·* is expected.
80495d ·*/
cb8ea7 #ifndef bniSub1_16¤ /* If defined, it's provided as an asm subroutine */
2a5a8c #ifdef BNWORD32
343401 BNWORD16
6a9fb4 bniSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
02bb36 {
c8f9fc ¤   BNWORD32 t;
542df5 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return borrow */
49af5a
cda31a ¤   t = (BNWORD32)BIGLITTLE(*--num,*num) - borrow;
8eb40c ¤   BIGLITTLE(*num,*num++) = (BNWORD16)t;
7b5e83 ¤   if ((t >> 16) == 0)
0ebbde ¤   ¤   return 0;
--6e03 000e1bff7aa40100150 Page 5 of bni16.c
f3e1ea ¤   while (--len) {
3adc4e ¤   ¤   if ((BIGLITTLE(*--num,*num++))-- != 0)
ed8144 ¤   ¤   ¤   return 0;
459371 ¤   }
9c64b7 ¤   return 1;
afefe6 }
41c626 #else /* no BNWORD32 */
7f3401 BNWORD16
259fb4 bniSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
8fbb36 {
3a2df5 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return borrow */
deaf5a
0afd5a ¤   if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD16)~borrow)
9abbde ¤   ¤   return 0;
3be1ea ¤   while (--len) {
a5dc4e ¤   ¤   if ((BIGLITTLE(*--num,*num++))-- != 0)
038144 ¤   ¤   ¤   return 0;
3f9371 ¤   }
8164b7 ¤   return 1;
f5efe6 }
9f7454 #endif
d368cb #endif /* !bniSub1_16 */
06af5a
b838e5 /*
2c903b ·* bniAddN_16: add two bignums of the same length,
f8bdf0 ·* returning the carry (0 or 1).
7b91db ·* One of the building blocks, along with bniAdd1, of adding two bignums of
b9a1e9 ·* differing lengths.
29775e ·*
0f2251 ·* Technique: Maintain a word of carry. ·If there is no double-width type,
f97ff1 ·* use the same technique as in bniAdd1, above, to maintain the carry by
663cda ·* comparing the inputs. ·Adding the carry sources is used as an OR operator;
dc7836 ·* at most one of the two comparisons can possibly be true. ·The first can
34d0d2 ·* only be true if carry == 1 and x, the result, is 0. ·In that case the
8220dc ·* second can't possibly be true.
de495d ·*/
ffc604 #ifndef bniAddN_16
6f5a8c #ifdef BNWORD32
623401 BNWORD16
936803 bniAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
82bb36 {
6df9fc ¤   BNWORD32 t;
b7af5a
b45334 ¤   pgpAssert(len > 0);
c4af5a
c25427 ¤   t = (BNWORD32)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++);
e30ce8 ¤   BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
8de1ea ¤   while (--len) {
a24068 ¤   ¤   t = (BNWORD32)BIGLITTLE(*--num1,*num1) +
969515 ¤   ¤   ····(BNWORD32)BIGLITTLE(*--num2,*num2++) + (t >> 16);
b114b8 ¤   ¤   BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
339371 ¤   }
9eaf5a
abf662 ¤   return (BNWORD16)(t>>16);
47efe6 }
e2c626 #else /* no BNWORD32 */
043401 BNWORD16
a36803 bniAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
85bb36 {
03ec72 ¤   BNWORD16 x, carry = 0;
99af5a
835327 ¤   pgpAssert(len > 0);¤/* Alternative: change loop to test at start */
9eaf5a
e843ab ¤   do {
f44bce ¤   ¤   x = BIGLITTLE(*--num2,*num2++);
424163 ¤   ¤   carry = (x += carry) < carry;
d15b74 ¤   ¤   carry += (BIGLITTLE(*--num1,*num1++) += x) < x;
0fc57e ¤   } while (--len);
63af5a
f7b1fc ¤   return carry;
25efe6 }
e17454 #endif
--9181 0009bcee7eb40100150 Page 6 of bni16.c
09d10d #endif /* !bniAddN_16 */
9daf5a
2638e5 /*
242bf8 ·* bniSubN_16: add two bignums of the same length,
01bdf0 ·* returning the carry (0 or 1).
9e6e07 ·* One of the building blocks, along with subn1, of subtracting two bignums of
e3a1e9 ·* differing lengths.
79775e ·*
1d4d44 ·* Technique: If no double-width type is availble, maintain a word of borrow.
087b0e ·* First, add the borrow to the subtrahend (did you have to learn all those
4e33b3 ·* awful words in elementary school, too?), and if it overflows, set the
1d182f ·* borrow again. ·Then subtract the modified subtrahend from the next word
95d9f4 ·* of input, using the same technique as in subn1, above.
4fc4fa ·* Adding the borrows is used as an OR operator; at most one of the two
3ee246 ·* comparisons can possibly be true. ·The first can only be true if
dff032 ·* borrow == 1 and x, the result, is 0. ·In that case the second can't
eb119d ·* possibly be true.
33775e ·*
35e180 ·* In the double-word case, (BNWORD16)-(t>>16) is subtracted, rather than
4faaf8 ·* adding t>>16, because the shift would need to sign-extend and that's
ad17f3 ·* not guaranteed to happen in ANSI C, even with signed types.
68495d ·*/
72a4f5 #ifndef bniSubN_16
9e5a8c #ifdef BNWORD32
8c3401 BNWORD16
cf8d51 bniSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
3cbb36 {
e9f9fc ¤   BNWORD32 t;
7baf5a
e75334 ¤   pgpAssert(len > 0);
2aaf5a
57960d ¤   t = (BNWORD32)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++);
650ce8 ¤   BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
51af5a
3be1ea ¤   while (--len) {
1714b8 ¤   ¤   t = (BNWORD32)BIGLITTLE(*--num1,*num1) -
7d7074 ¤   ¤   ····(BNWORD32)BIGLITTLE(*--num2,*num2++) -
f9afd1 ¤   ¤   ····(BNWORD16)-(t >> 16);
0614b8 ¤   ¤   BIGLITTLE(*num1,*num1++) = (BNWORD16)t;
df9371 ¤   }
0aaf5a
f74286 ¤   return -(BNWORD16)(t>>16);
98efe6 }
f1db21 #else
4a3401 BNWORD16
088d51 bniSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len)
37bb36 {
863a93 ¤   BNWORD16 x, borrow = 0;
e7af5a
0e5327 ¤   pgpAssert(len > 0);¤/* Alternative: change loop to test at start */
e7af5a
d043ab ¤   do {
f74bce ¤   ¤   x = BIGLITTLE(*--num2,*num2++);
f44b08 ¤   ¤   borrow = (x += borrow) < borrow;
48250d ¤   ¤   borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD16)~x;
f0c57e ¤   } while (--len);
31af5a
0e1102 ¤   return borrow;
45efe6 }
777454 #endif
105100 #endif /* !bniSubN_16 */
6daf5a
e8fff9 #ifndef bniCmp_16
6c38e5 /*
f37993 ·* bniCmp_16: compare two bignums of equal length, returning the sign of
aa8209 ·* num1 - num2. (-1, 0 or +1).
7f9ec0 ·*·
c9e837 ·* Technique: Change the little-endian pointers to big-endian pointers
e57660 ·* and compare from the most-significant end until a difference if found.
4ebd66 ·* When it is, figure out the sign of the difference and return it.
ee495d ·*/
9b4d2f int
--0efa 0002698de7340100150 Page 7 of bni16.c
cef474 bniCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len)
76bb36 {
c0cce6 ¤   BIGLITTLE(num1 -= len, num1 += len);
b0df99 ¤   BIGLITTLE(num2 -= len, num2 += len);
0daf5a
4ecae5 ¤   while (len--) {
24c2de ¤   ¤   if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) {
dadcf7 ¤   ¤   ¤   if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2))
40dd34 ¤   ¤   ¤   ¤   return -1;
7fbb8c ¤   ¤   ¤   else
b31c2d ¤   ¤   ¤   ¤   return 1;
0b0fe4 ¤   ¤   }
ef9371 ¤   }
303e6b ¤   return 0;
63efe6 }
65c8f7 #endif /* !bniCmp_16 */
d2af5a
4638e5 /*
f75ffa ·* mul16_ppmmaa(ph,pl,x,y,a,b) is an optional routine that
691741 ·* computes (ph,pl) = x * y + a + b. ·mul16_ppmma and mul16_ppmm
6b8dbd ·* are simpler versions. ·If you want to be lazy, all of these
7f1154 ·* can be defined in terms of the others, so here we create any
85a26b ·* that have not been defined in terms of the ones that have been.
ab495d ·*/
1caf5a
6cfaaa /* Define ones with fewer a's in terms of ones with more a's */
f2c75c #if !defined(mul16_ppmma) && defined(mul16_ppmmaa)
8f78d6 #define mul16_ppmma(ph,pl,x,y,a) mul16_ppmmaa(ph,pl,x,y,a,0)
fc7454 #endif
67af5a
367944 #if !defined(mul16_ppmm) && defined(mul16_ppmma)
efe19d #define mul16_ppmm(ph,pl,x,y) mul16_ppmma(ph,pl,x,y,0)
8a7454 #endif
45af5a
7f38e5 /*
f6d52f ·* Use this definition to test the mul16_ppmm-based operations on machines
7f4a5b ·* that do not provide mul16_ppmm. ·Change the final "0" to a "1" to
13925b ·* enable it.
d0495d ·*/
04cbed #if !defined(mul16_ppmm) && defined(BNWORD32) && 0¤ /* Debugging */
66a360 #define mul16_ppmm(ph,pl,x,y) \
969b3a ¤   ({BNWORD32 _ = (BNWORD32)(x)*(y); (pl) = _; (ph) = _>>16;})
567454 #endif
9eaf5a
008aeb #if defined(mul16_ppmm) && !defined(mul16_ppmma)
0be944 #define mul16_ppmma(ph,pl,x,y,a) \
9a7e3f ¤   (mul16_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a))
d57454 #endif
9baf5a
a420d4 #if defined(mul16_ppmma) && !defined(mul16_ppmmaa)
c57144 #define mul16_ppmmaa(ph,pl,x,y,a,b) \
b2603e ¤   (mul16_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b))
6f7454 #endif
c0af5a
ac38e5 /*
5d2327 ·* bniMulN1_16: Multiply an n-word input by a 1-word input and store the
baf2fb ·* n+1-word product. ·This uses either the mul16_ppmm and mul16_ppmma
1f8ba6 ·* macros, or C multiplication with the BNWORD32 type. ·This uses mul16_ppmma
6974b1 ·* if available, assuming you won't bother defining it unless you can do
d601e4 ·* better than the normal multiplication.
3b495d ·*/
e7c916 #ifndef bniMulN1_16
79f104 #ifdef bniMulAdd1_16¤   /* If we have this asm primitive, use it. */
b5314a void
703c2f bniMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
0fbb36 {
27b0f5 ¤   bniZero_16(out, len);
fd1851 ¤   BIGLITTLE(*(out-len),*(out+len)) = bniMulAdd1_16(out, in, len, k);
65efe6 }
170442 #elif defined(mul16_ppmm)
d6314a void
263c2f bniMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
--8e7a 0002c1ced5a40100150 Page 8 of bni16.c
2cbb36 {
33ff75 ¤   BNWORD16 prod, carry, carryin;
42af5a
895334 ¤   pgpAssert(len > 0);
62af5a
b5947d ¤   BIG(--out;--in;);
b27f0e ¤   mul16_ppmm(carry, *out, *in, k);
2ff1a6 ¤   LITTLE(out++;in++;)
faaf5a
25e1ea ¤   while (--len) {
056541 ¤   ¤   BIG(--out;--in;)
dfa85c ¤   ¤   carryin = carry;
bb25ec ¤   ¤   mul16_ppmma(carry, *out, *in, k, carryin);
6c07c3 ¤   ¤   LITTLE(out++;in++;)
789371 ¤   }
9cddd0 ¤   BIGLITTLE(*--out,*out) = carry;
38efe6 }
a0ef62 #elif defined(BNWORD32)
c7314a void
ac3c2f bniMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
f5bb36 {
659a9d ¤   BNWORD32 p;
6daf5a
3c5334 ¤   pgpAssert(len > 0);
23af5a
89c661 ¤   p = (BNWORD32)BIGLITTLE(*--in,*in++) * k;
a742fd ¤   BIGLITTLE(*--out,*out++) = (BNWORD16)p;
32af5a
26e1ea ¤   while (--len) {
2c6a7c ¤   ¤   p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + (BNWORD16)(p >> 16);
5e5aad ¤   ¤   BIGLITTLE(*--out,*out++) = (BNWORD16)p;
5f9371 ¤   }
a43397 ¤   BIGLITTLE(*--out,*out) = (BNWORD16)(p >> 16);
03efe6 }
e7db21 #else
60819c #error No 16x16 -> 32 multiply available for 16-bit bignum package
4b7454 #endif
4036ef #endif /* bniMulN1_16 */
bcaf5a
0b38e5 /*
4d55a1 ·* bniMulAdd1_16: Multiply an n-word input by a 1-word input and add the
9c72e0 ·* low n words of the product to the destination. ·*Returns the n+1st word
020f32 ·* of the product.* ·(That turns out to be more convenient than adding
e85a71 ·* it into the destination and dealing with a possible unit carry out
da5110 ·* of *that*.) ·This uses either the mul16_ppmma and mul16_ppmmaa macros,
edbcf8 ·* or C multiplication with the BNWORD32 type.
fb775e ·*
3c8e70 ·* If you're going to write assembly primitives, this is the one to
fd0dda ·* start with. ·It is by far the most commonly called function.
74495d ·*/
e8c100 #ifndef bniMulAdd1_16
f096b5 #if defined(mul16_ppmm)
283401 BNWORD16
af347d bniMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
a0bb36 {
e1ff75 ¤   BNWORD16 prod, carry, carryin;
c9af5a
d05334 ¤   pgpAssert(len > 0);
00af5a
43947d ¤   BIG(--out;--in;);
cbd6bd ¤   carryin = *out;
71fd5e ¤   mul16_ppmma(carry, *out, *in, k, carryin);
4bf1a6 ¤   LITTLE(out++;in++;)
74af5a
2ae1ea ¤   while (--len) {
8a53c8 ¤   ¤   BIG(--out;--in;);
1aa85c ¤   ¤   carryin = carry;
02257e ¤   ¤   mul16_ppmmaa(carry, prod, *in, k, carryin, *out);
46ecd6 ¤   ¤   *out = prod;
5a07c3 ¤   ¤   LITTLE(out++;in++;)
c59371 ¤   }
2caf5a
--520d 000767b713b40100150 Page 9 of bni16.c
dab1fc ¤   return carry;
72efe6 }
fbef62 #elif defined(BNWORD32)
f93401 BNWORD16
f1347d bniMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
c6bb36 {
f09a9d ¤   BNWORD32 p;
e9af5a
fe5334 ¤   pgpAssert(len > 0);
09af5a
69da34 ¤   p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out);
8ec456 ¤   BIGLITTLE(*out,*out++) = (BNWORD16)p;
d5af5a
9ce1ea ¤   while (--len) {
dd9379 ¤   ¤   p = (BNWORD32)BIGLITTLE(*--in,*in++) * k +
324e42 ¤   ¤   ····(BNWORD16)(p >> 16) + BIGLITTLE(*--out,*out);
20fd93 ¤   ¤   BIGLITTLE(*out,*out++) = (BNWORD16)p;
749371 ¤   }
bdaf5a
2967df ¤   return (BNWORD16)(p >> 16);
84efe6 }
86db21 #else
a8819c #error No 16x16 -> 32 multiply available for 16-bit bignum package
ac7454 #endif
f4426e #endif /* bniMulAdd1_16 */
0eaf5a
ff38e5 /*
fbc3f9 ·* bniMulSub1_16: Multiply an n-word input by a 1-word input and subtract the
aa843f ·* n-word product from the destination. ·Returns the n+1st word of the product.
3f560f ·* This uses either the mul16_ppmm and mul16_ppmma macros, or
9e4101 ·* C multiplication with the BNWORD32 type.
29775e ·*
fdceaf ·* This is rather uglier than adding, but fortunately it's only used in
357917 ·* division which is not used too heavily.
c9495d ·*/
0da3f1 #ifndef bniMulSub1_16
7696b5 #if defined(mul16_ppmm)
623401 BNWORD16
af39f2 bniMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
3abb36 {
c4ff75 ¤   BNWORD16 prod, carry, carryin;
bcaf5a
455334 ¤   pgpAssert(len > 0);
c6af5a
d6495e ¤   BIG(--in;)
8c5aa3 ¤   mul16_ppmm(carry, prod, *in, k);
dc745b ¤   LITTLE(in++;)
74bb1f ¤   carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod;
a6af5a
d5e1ea ¤   while (--len) {
7e2ce1 ¤   ¤   BIG(--in;);
2ca85c ¤   ¤   carryin = carry;
993a41 ¤   ¤   mul16_ppmma(carry, prod, *in, k, carryin);
dc4ec1 ¤   ¤   LITTLE(in++;)
14a893 ¤   ¤   carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD16)~prod;
ac9371 ¤   }
d1af5a
edb1fc ¤   return carry;
30efe6 }
c7ef62 #elif defined(BNWORD32)
323401 BNWORD16
2f39f2 bniMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
70bb36 {
df9a9d ¤   BNWORD32 p;
70c30c ¤   BNWORD16 carry, t;
c4af5a
485334 ¤   pgpAssert(len > 0);
20af5a
65c661 ¤   p = (BNWORD32)BIGLITTLE(*--in,*in++) * k;
5f8593 ¤   t = BIGLITTLE(*--out,*out);
04a4ce ¤   carry = (BNWORD16)(p>>16) +
764685 ¤   ¤   ¤   ((BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t);
--2d49 00040b94b4240100150 Page 10 of bni16.c
e0af5a
32e1ea ¤   while (--len) {
4c8596 ¤   ¤   p = (BNWORD32)BIGLITTLE(*--in,*in++) * k + carry;
990e6f ¤   ¤   t = BIGLITTLE(*--out,*out);
782f32 ¤   ¤   carry = (BNWORD16)(p>>16) +
84314a ¤   ¤   ¤   ( (BIGLITTLE(*out,*out++)=t-(BNWORD16)p) > t );
fc9371 ¤   }
1baf5a
6fb1fc ¤   return carry;
96efe6 }
4fdb21 #else
2d819c #error No 16x16 -> 32 multiply available for 16-bit bignum package
3f7454 #endif
2856c4 #endif /* !bniMulSub1_16 */
99af5a
6438e5 /*
114316 ·* Shift n words left "shift" bits. ·0 < shift < 16. ·Returns the
b72e41 ·* carry, any bits shifted off the left-hand side (0 <= carry < 2^shift).
20495d ·*/
bc3f35 #ifndef bniLshift_16
b33401 BNWORD16
e572df bniLshift_16(BNWORD16 *num, unsigned len, unsigned shift)
72bb36 {
939c78 ¤   BNWORD16 x, carry;
5daf5a
3be769 ¤   pgpAssert(shift > 0);
df838a ¤   pgpAssert(shift < 16);
7daf5a
331e50 ¤   carry = 0;
d0cae5 ¤   while (len--) {
d3cb1c ¤   ¤   BIG(--num;)
ebf3b8 ¤   ¤   x = *num;
452c6b ¤   ¤   *num = (x<<shift) | carry;
fbc728 ¤   ¤   LITTLE(num++;)
05ed42 ¤   ¤   carry = x >> (16-shift);
519371 ¤   }
acb1fc ¤   return carry;
15efe6 }
b242cc #endif /* !bniLshift_16 */
6aaf5a
5438e5 /*
d39f06 ·* An optimized version of the above, for shifts of 1.
87db8f ·* Some machines can use add-with-carry tricks for this.
39495d ·*/
cee88a #ifndef bniDouble_16
3d3401 BNWORD16
808614 bniDouble_16(BNWORD16 *num, unsigned len)
9ebb36 {
1a9c78 ¤   BNWORD16 x, carry;
08af5a
491e50 ¤   carry = 0;
d5cae5 ¤   while (len--) {
f9cb1c ¤   ¤   BIG(--num;)
54f3b8 ¤   ¤   x = *num;
ae77ad ¤   ¤   *num = (x<<1) | carry;
eec728 ¤   ¤   LITTLE(num++;)
25a349 ¤   ¤   carry = x >> (16-1);
589371 ¤   }
6fb1fc ¤   return carry;
f9efe6 }
f1907a #endif /* !bniDouble_16 */
dbaf5a
b238e5 /*
7b705e ·* Shift n words right "shift" bits. ·0 < shift < 16. ·Returns the
2df892 ·* carry, any bits shifted off the right-hand side (0 <= carry < 2^shift).
cb495d ·*/
396c9c #ifndef bniRshift_16
e33401 BNWORD16
8719d1 bniRshift_16(BNWORD16 *num, unsigned len, unsigned shift)
dfbb36 {
66ec72 ¤   BNWORD16 x, carry = 0;
40af5a
--3b9a 00046eb8bd340100150 Page 11 of bni16.c
54e769 ¤   pgpAssert(shift > 0);
e0838a ¤   pgpAssert(shift < 16);
5caf5a
831189 ¤   BIGLITTLE(num -= len, num += len);
b3af5a
e1cae5 ¤   while (len--) {
62c1a0 ¤   ¤   LITTLE(--num;)
fff3b8 ¤   ¤   x = *num;
aff5aa ¤   ¤   *num = (x>>shift) | carry;
cdcd94 ¤   ¤   BIG(num++;)
f280c2 ¤   ¤   carry = x << (16-shift);
619371 ¤   }
af8c7a ¤   return carry >> (16-shift);
a2efe6 }
f9289a #endif /* !bniRshift_16 */
01af5a
0d95d7 /*·
6c5d82 ·* Multiply two numbers of the given lengths. ·prod and num2 may overlap,
fe2dfd ·* provided that the low len1 bits of prod are free. ·(This corresponds
e6fdf8 ·* nicely to the place the result is returned from bniMontReduce_16.)
51775e ·*
4de9b9 ·* TODO: Use Karatsuba multiply. ·The overlap constraints may have
fe0cb9 ·* to get rewhacked.
62495d ·*/
60d940 #ifndef bniMul_16
4e314a void
57e1c7 bniMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1,
5e8550 ··························BNWORD16 const *num2, unsigned len2)
f1bb36 {
9e157a ¤   /* Special case of zero */
e2fee4 ¤   if (!len1 || !len2) {
3f24ea ¤   ¤   bniZero_16(prod, len1+len2);
8899bf ¤   ¤   return;
ba9371 ¤   }
e9af5a
ab5dc0 ¤   /* Multiply first word */
003231 ¤   bniMulN1_16(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
50af5a
95d8af ¤   /*
93ad33 ¤   ·* Add in subsequent words, storing the most significant word,
732a88 ¤   ·* which is new each time.
10a4e3 ¤   ·*/
b7ae79 ¤   while (--len2) {
54df7f ¤   ¤   BIGLITTLE(--prod,prod++);
64ef4a ¤   ¤   BIGLITTLE(*(prod-len1-1),*(prod+len1)) =
0576b3 ¤   ¤   ¤   bniMulAdd1_16(prod, num1, len1,
a064a3 ¤   ¤   ¤   ¤   BIGLITTLE(*--num2,*num2++));
439371 ¤   }
b6efe6 }
2ba948 #endif /* !bniMul_16 */
31af5a
ac38e5 /*
38eaee ·* bniMulX_16 is a square multiply - both inputs are the same length.
d973d5 ·* It's normally just a macro wrapper around the general multiply,
989a0a ·* but might be implementable in assembly more efficiently (such as
a6ee4d ·* when product scanning).
de495d ·*/
3679fa #ifndef bniMulX_16
359f73 #if defined(BNWORD32) && PRODUCT_SCAN
ec38e5 /*
c23384 ·* Test code to see whether product scanning is any faster. ·It seems
199f49 ·* to make the C code slower, so PRODUCT_SCAN is not defined.
d4495d ·*/
882978 static void
734616 bniMulX_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2,
d76094 ¤   unsigned len)
33bb36 {
d08584 ¤   BNWORD32 x, y;
ca0705 ¤   BNWORD16 const *p1, *p2;
4550fc ¤   unsigned carry;
8207cb ¤   unsigned i, j;
46af5a
--a797 000a986415e40100150 Page 12 of bni16.c
6d157a ¤   /* Special case of zero */
1a4404 ¤   if (!len)
0499bf ¤   ¤   return;
1baf5a
2e235a ¤   x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
83b2ba ¤   BIGLITTLE(*--prod, *prod++) = (BNWORD16)x;
06ffd0 ¤   x >>= 16;
7daf5a
8c6dce ¤   for (i = 1; i < len; i++) {
39fcf3 ¤   ¤   carry = 0;
d0f201 ¤   ¤   p1 = num1;
6f515c ¤   ¤   p2 = BIGLITTLE(num2-i-1,num2+i+1);
7bcdd8 ¤   ¤   for (j = 0; j <= i; j++) {
6a9a85 ¤   ¤   ¤   BIG(y = (BNWORD32)*--p1 * *p2++;)
be4968 ¤   ¤   ¤   LITTLE(y = (BNWORD32)*p1++ * *--p2;)
e11ca0 ¤   ¤   ¤   x += y;
12dfb0 ¤   ¤   ¤   carry += (x < y);
6f0fe4 ¤   ¤   }
93eb22 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
a69f5b ¤   ¤   x = (x >> 16) | (BNWORD32)carry << 16;
c79371 ¤   }
506dce ¤   for (i = 1; i < len; i++) {
93fcf3 ¤   ¤   carry = 0;
247f2d ¤   ¤   p1 = BIGLITTLE(num1-i,num1+i);
82429b ¤   ¤   p2 = BIGLITTLE(num2-len,num2+len);
b37807 ¤   ¤   for (j = i; j < len; j++) {
6b9a85 ¤   ¤   ¤   BIG(y = (BNWORD32)*--p1 * *p2++;)
9d4968 ¤   ¤   ¤   LITTLE(y = (BNWORD32)*p1++ * *--p2;)
0a1ca0 ¤   ¤   ¤   x += y;
61dfb0 ¤   ¤   ¤   carry += (x < y);
120fe4 ¤   ¤   }
baeb22 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
c19f5b ¤   ¤   x = (x >> 16) | (BNWORD32)carry << 16;
a99371 ¤   }
7967c5 ¤
446bd9 ¤   BIGLITTLE(*--prod,*prod) = (BNWORD16)x;
b4efe6 }
1d32fb #else /* !defined(BNWORD32) || !PRODUCT_SCAN */
a07015 /* Default trivial macro definition */
55960b #define bniMulX_16(prod, num1, num2, len) bniMul_16(prod, num1, len, num2, len)
1d37f6 #endif /* !defined(BNWORD32) || !PRODUCT_SCAN */
1c2b20 #endif /* !lbmMulX_16 */
c5af5a
61423c #if !defined(bniMontMul_16) && defined(BNWORD32) && PRODUCT_SCAN
c638e5 /*
6ab707 ·* Test code for product-scanning multiply. ·This seems to slow the C
d3f14b ·* code down rather than speed it up.
dfe2e9 ·* This does a multiply and Montgomery reduction together, using the
31053f ·* same loops. ·The outer loop scans across the product, twice.
1d093d ·* The first pass computes the low half of the product and the
0c8f6c ·* Montgomery multipliers. ·These are stored in the product array,
1c9620 ·* which contains no data as of yet. ·x and carry add up the columns
5517c7 ·* and propagate carries forward.
f9775e ·*
f7bdb8 ·* The second half multiplies the upper half, adding in the modulus
5e2380 ·* times the Montgomery multipliers. ·The results of this multiply
35fa30 ·* are stored.
21495d ·*/
ad2978 static void
e19559 bniMontMul_16(BNWORD16 *prod, BNWORD16 const *num1, BNWORD16 const *num2,
af2731 ¤   BNWORD16 const *mod, unsigned len, BNWORD16 inv)
3bbb36 {
bd8584 ¤   BNWORD32 x, y;
d7ded4 ¤   BNWORD16 const *p1, *p2, *pm;
851775 ¤   BNWORD16 *pp;
0adcba ¤   BNWORD16 t;
0050fc ¤   unsigned carry;
cc07cb ¤   unsigned i, j;
a0af5a
92157a ¤   /* Special case of zero */
024404 ¤   if (!len)
a999bf ¤   ¤   return;
--a979 0002a5400b640100150 Page 13 of bni16.c
e0af5a
f8d8af ¤   /*
c44576 ¤   ·* This computes directly into the high half of prod, so just
159d34 ¤   ·* shift the pointer and consider prod only "len" elements long
2aebc4 ¤   ·* for the rest of the code.
6ea4e3 ¤   ·*/
1c8517 ¤   BIGLITTLE(prod -= len, prod += len);
efaf5a
84a702 ¤   /* Pass 1 - compute Montgomery multipliers */
4d1ffe ¤   /* First iteration can have certain simplifications. */
12235a ¤   x = (BNWORD32)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
96fd2c ¤   BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD16)x;
48b30f ¤   y = (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]);
019163 ¤   x += y;
0712f8 ¤   /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */
9a27d4 ¤   carry = (x < y);
2e9e3d ¤   pgpAssert((BNWORD16)x == 0);
aac3cc ¤   x = x >> 16 | (BNWORD32)carry << 16;
cfaf5a
be6dce ¤   for (i = 1; i < len; i++) {
cffcf3 ¤   ¤   carry = 0;
e2f201 ¤   ¤   p1 = num1;
06515c ¤   ¤   p2 = BIGLITTLE(num2-i-1,num2+i+1);
9d47bb ¤   ¤   pp = prod;
10d39c ¤   ¤   pm = BIGLITTLE(mod-i-1,mod+i+1);
4ff8a4 ¤   ¤   for (j = 0; j < i; j++) {
aa3982 ¤   ¤   ¤   y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
881ca0 ¤   ¤   ¤   x += y;
09dfb0 ¤   ¤   ¤   carry += (x < y);
1de8af ¤   ¤   ¤   y = (BNWORD32)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm);
641ca0 ¤   ¤   ¤   x += y;
85dfb0 ¤   ¤   ¤   carry += (x < y);
4e0fe4 ¤   ¤   }
fa7136 ¤   ¤   y = (BNWORD32)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]);
c78bd3 ¤   ¤   x += y;
7756e4 ¤   ¤   carry += (x < y);
9c1cca ¤   ¤   pgpAssert(BIGLITTLE(pp == prod-i, pp == prod+i));
dd793b ¤   ¤   BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD16)x;
4a35b5 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-1, pm == mod+1));
f302e4 ¤   ¤   y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]);
c48bd3 ¤   ¤   x += y;
b356e4 ¤   ¤   carry += (x < y);
65a355 ¤   ¤   pgpAssert((BNWORD16)x == 0);
d4c574 ¤   ¤   x = x >> 16 | (BNWORD32)carry << 16;
439371 ¤   }
dcaf5a
e8d239 ¤   /* Pass 2 - compute reduced product and store */
b86dce ¤   for (i = 1; i < len; i++) {
86fcf3 ¤   ¤   carry = 0;
d97f2d ¤   ¤   p1 = BIGLITTLE(num1-i,num1+i);
88429b ¤   ¤   p2 = BIGLITTLE(num2-len,num2+len);
860805 ¤   ¤   pm = BIGLITTLE(mod-i,mod+i);
32a573 ¤   ¤   pp = BIGLITTLE(prod-len,prod+len);
d47807 ¤   ¤   for (j = i; j < len; j++) {
4c3982 ¤   ¤   ¤   y = (BNWORD32)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
de1ca0 ¤   ¤   ¤   x += y;
4ddfb0 ¤   ¤   ¤   carry += (x < y);
9abef6 ¤   ¤   ¤   y = (BNWORD32)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp);
641ca0 ¤   ¤   ¤   x += y;
40dfb0 ¤   ¤   ¤   carry += (x < y);
2f0fe4 ¤   ¤   }
b570a3 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-len, pm == mod+len));
f41cca ¤   ¤   pgpAssert(BIGLITTLE(pp == prod-i, pp == prod+i));
7812b3 ¤   ¤   BIGLITTLE(pp[0],pp[-1]) = (BNWORD16)x;
4a9f5b ¤   ¤   x = (x >> 16) | (BNWORD32)carry << 16;
eb9371 ¤   }
13af5a
74f753 ¤   /* Last round of second half, simplified. */
47fcc8 ¤   BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD16)x;
304493 ¤   carry = (x >> 16);
40af5a
2aa53b ¤   while (carry)
--7e7f 0000f8c039640100150 Page 14 of bni16.c
a742d3 ¤   ¤   carry -= bniSubN_16(prod, mod, len);
31ec4e ¤   while (bniCmp_16(prod, mod, len) >= 0)
25eafc ¤   ¤   (void)bniSubN_16(prod, mod, len);
b6efe6 }
4f25f5 /* Suppress later definition */
0e80fa #define bniMontMul_16 bniMontMul_16
e87454 #endif
c8af5a
78721b #if !defined(bniSquare_16) && defined(BNWORD32) && PRODUCT_SCAN
9538e5 /*
1b064e ·* Trial code for product-scanning squaring. ·This seems to slow the C
30f14b ·* code down rather than speed it up.
2d495d ·*/
4c314a void
2b89d3 bniSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len)
38bb36 {
fc446a ¤   BNWORD32 x, y, z;
cc0705 ¤   BNWORD16 const *p1, *p2;
6350fc ¤   unsigned carry;
9d07cb ¤   unsigned i, j;
1faf5a
d4157a ¤   /* Special case of zero */
014404 ¤   if (!len)
0a99bf ¤   ¤   return;
59af5a
5a61d6 ¤   /* Word 0 of product */
711f7b ¤   x = (BNWORD32)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]);
e0b2ba ¤   BIGLITTLE(*--prod, *prod++) = (BNWORD16)x;
3effd0 ¤   x >>= 16;
6baf5a
45be1a ¤   /* Words 1 through len-1 */
366dce ¤   for (i = 1; i < len; i++) {
ebfcf3 ¤   ¤   carry = 0;
d22b1f ¤   ¤   y = 0;
bd7bd5 ¤   ¤   p1 = num;
ecf73f ¤   ¤   p2 = BIGLITTLE(num-i-1,num+i+1);
c42b7b ¤   ¤   for (j = 0; j < (i+1)/2; j++) {
d9fb90 ¤   ¤   ¤   BIG(z = (BNWORD32)*--p1 * *p2++;)
7e287d ¤   ¤   ¤   LITTLE(z = (BNWORD32)*p1++ * *--p2;)
50727b ¤   ¤   ¤   y += z;
9d7bc2 ¤   ¤   ¤   carry += (y < z);
d10fe4 ¤   ¤   }
323099 ¤   ¤   y += z = y;
622289 ¤   ¤   carry += carry + (y < z);
a0d10c ¤   ¤   if ((i & 1) == 0) {
dcd553 ¤   ¤   ¤   pgpAssert(BIGLITTLE(p1-1 == p2, p1 == p2-1));
493a20 ¤   ¤   ¤   BIG(z = (BNWORD32)*p2 * *p2;)
cd6adb ¤   ¤   ¤   LITTLE(z = (BNWORD32)*p1 * *p1;)
bc727b ¤   ¤   ¤   y += z;
e87bc2 ¤   ¤   ¤   carry += (y < z);
460fe4 ¤   ¤   }
848bd3 ¤   ¤   x += y;
6256e4 ¤   ¤   carry += (x < y);
49eb22 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
d49f5b ¤   ¤   x = (x >> 16) | (BNWORD32)carry << 16;
7a9371 ¤   }
c0852e ¤   /* Words len through 2*len-2 */
ec6dce ¤   for (i = 1; i < len; i++) {
07fcf3 ¤   ¤   carry = 0;
9f2b1f ¤   ¤   y = 0;
bd7e3e ¤   ¤   p1 = BIGLITTLE(num-i,num+i);
7b2d6b ¤   ¤   p2 = BIGLITTLE(num-len,num+len);
62ca30 ¤   ¤   for (j = 0; j < (len-i)/2; j++) {
c3fb90 ¤   ¤   ¤   BIG(z = (BNWORD32)*--p1 * *p2++;)
95287d ¤   ¤   ¤   LITTLE(z = (BNWORD32)*p1++ * *--p2;)
53727b ¤   ¤   ¤   y += z;
ae7bc2 ¤   ¤   ¤   carry += (y < z);
340fe4 ¤   ¤   }
cf3099 ¤   ¤   y += z = y;
802289 ¤   ¤   carry += carry + (y < z);
aabcf9 ¤   ¤   if ((len-i) & 1) {
0fd553 ¤   ¤   ¤   pgpAssert(BIGLITTLE(p1-1 == p2, p1 == p2-1));
--64da 000904e902840100150 Page 15 of bni16.c
f23a20 ¤   ¤   ¤   BIG(z = (BNWORD32)*p2 * *p2;)
d36adb ¤   ¤   ¤   LITTLE(z = (BNWORD32)*p1 * *p1;)
f6727b ¤   ¤   ¤   y += z;
6f7bc2 ¤   ¤   ¤   carry += (y < z);
770fe4 ¤   ¤   }
3f8bd3 ¤   ¤   x += y;
9956e4 ¤   ¤   carry += (x < y);
13eb22 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD16)x;
969f5b ¤   ¤   x = (x >> 16) | (BNWORD32)carry << 16;
d79371 ¤   }
5d67c5 ¤
75b240 ¤   /* Word 2*len-1 */
3b6bd9 ¤   BIGLITTLE(*--prod,*prod) = (BNWORD16)x;
c0efe6 }
5d25f5 /* Suppress later definition */
b51a2d #define bniSquare_16 bniSquare_16
657454 #endif
8caf5a
0338e5 /*
82a533 ·* Square a number, using optimized squaring to reduce the number of
731f0f ·* primitive multiples that are executed. ·There may not be any
296dd9 ·* overlap of the input and output.
45775e ·*
f302ad ·* Technique: Consider the partial products in the multiplication
d172e6 ·* of "abcde" by itself:
6c775e ·*
d9de15 ·* ··············a ·b ·c ·d ·e
957669 ·* ···········* ·a ·b ·c ·d ·e
9e1afb ·* ·········==================
9ed8e6 ·* ·············ae be ce de ee
7bbd78 ·* ··········ad bd cd dd de
fae467 ·* ·······ac bc cc cd ce
00dcf1 ·* ····ab bb bc bd be
417dd1 ·* ·aa ab ac ad ae
1e775e ·*
834e38 ·* Note that everything above the main diagonal:
7f729a ·* ·············ae be ce de = (abcd) * e
5d06bf ·* ··········ad bd cd ······= (abc) * d
00eff2 ·* ·······ac bc ············= (ab) * c
e88267 ·* ····ab ··················= (a) * b
8c775e ·*
34cef0 ·* is a copy of everything below the main diagonal:
496424 ·* ······················de
d963ff ·* ················cd ce
3485ae ·* ··········bc bd be
e15a25 ·* ····ab ac ad ae
b4775e ·*
8c9c36 ·* Thus, the sum is 2 * (off the diagonal) + diagonal.
9c775e ·*
a31615 ·* This is accumulated beginning with the diagonal (which
0fd5d8 ·* consist of the squares of the digits of the input), which is then
ed9c50 ·* divided by two, the off-diagonal added, and multiplied by two
55874a ·* again. ·The low bit is simply a copy of the low bit of the
c87b99 ·* input, so it doesn't need special care.
c1775e ·*
e396ea ·* TODO: Merge the shift by 1 with the squaring loop.
4c35e2 ·* TODO: Use Karatsuba. ·(a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W.
eb495d ·*/
200910 #ifndef bniSquare_16
97314a void
5c89d3 bniSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len)
5cbb36 {
a4dcba ¤   BNWORD16 t;
a37f48 ¤   BNWORD16 *prodx = prod;¤¤   /* Working copy of the argument */
1d0837 ¤   BNWORD16 const *numx = num;¤/* Working copy of the argument */
72a2af ¤   unsigned lenx = len;¤   ¤   /* Working copy of the argument */
03af5a
c04404 ¤   if (!len)
4999bf ¤   ¤   return;
39af5a
880677 ¤   /* First, store all the squares */
900a75 ¤   while (lenx--) {
--7356 000bf0b2aab40100150 Page 16 of bni16.c
15f8b0 #ifdef mul16_ppmm
81fa3e ¤   ¤   BNWORD16 ph, pl;
87499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
ae714c ¤   ¤   mul16_ppmm(ph,pl,t,t);
8beac4 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = pl;
bb89a5 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = ph;
01b592 #elif defined(BNWORD32) /* use BNWORD32 */
b00dee ¤   ¤   BNWORD32 p;
05499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
0b6739 ¤   ¤   p = (BNWORD32)t * t;
0af87b ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)p;
7874c4 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = (BNWORD16)(p>>16);
603816 #else¤  /* Use bniMulN1_16 */
d55403 ¤   ¤   t = BIGLITTLE(numx[-1],*numx);
e38624 ¤   ¤   bniMulN1_16(prodx, numx, 1, t);
f09d54 ¤   ¤   BIGLITTLE(--numx,numx++);
680cad ¤   ¤   BIGLITTLE(prodx -= 2, prodx += 2);
f97454 #endif
b99371 ¤   }
226220 ¤   /* Then, shift right 1 bit */
834ea8 ¤   (void)bniRshift_16(prod, 2*len, 1);
75af5a
55ba8b ¤   /* Then, add in the off-diagonal sums */
8da223 ¤   lenx = len;
879ff9 ¤   numx = num;
4244f6 ¤   prodx = prod;
5623f3 ¤   while (--lenx) {
9d499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
e71fab ¤   ¤   BIGLITTLE(--prodx,prodx++);
081e0a ¤   ¤   t = bniMulAdd1_16(prodx, numx, lenx, t);
af9be4 ¤   ¤   bniAdd1_16(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t);
391fab ¤   ¤   BIGLITTLE(--prodx,prodx++);
a79371 ¤   }
c3af5a
a9ca8f ¤   /* Shift it back up */
525b16 ¤   bniDouble_16(prod, 2*len);
ccaf5a
7245fb ¤   /* And set the low bit appropriately */
b87f4b ¤   BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1;
eeefe6 }
a09a38 #endif /* !bniSquare_16 */
14af5a
5938e5 /*
cd4a41 ·* bniNorm_16 - given a number, return a modified length such that the
b1c010 ·* most significant digit is non-zero. ·Zero-length input is okay.
07495d ·*/
262623 #ifndef bniNorm_16
37536c unsigned
795ba3 bniNorm_16(BNWORD16 const *num, unsigned len)
f8bb36 {
d0788e ¤   BIGLITTLE(num -= len,num += len);
5dbd5b ¤   while (len && BIGLITTLE(*num++,*--num) == 0)
719647 ¤   ¤   --len;
0abb7a ¤   return len;
0cefe6 }
120e97 #endif /* bniNorm_16 */
21af5a
5238e5 /*
45a6e3 ·* bniBits_16 - return the number of significant bits in the array.
439a79 ·* It starts by normalizing the array. ·Zero-length input is okay.
0ccb59 ·* Then assuming there's anything to it, it fetches the high word,
06e5d5 ·* generates a bit length by multiplying the word length by 16, and
28d3c0 ·* subtracts off 16/2, 16/4, 16/8, ... bits if the high bits are clear.
2e495d ·*/
f7888e #ifndef bniBits_16
07536c unsigned
0db547 bniBits_16(BNWORD16 const *num, unsigned len)
0dbb36 {
99dcba ¤   BNWORD16 t;
be743f ¤   unsigned i;
88af5a
bf1094 ¤   len = bniNorm_16(num, len);
--03d5 0003ee10f1140100150 Page 17 of bni16.c
8e5678 ¤   if (len) {
49027d ¤   ¤   t = BIGLITTLE(*(num-len),*(num+(len-1)));
40146d ¤   ¤   pgpAssert(t);
8eb647 ¤   ¤   len *= 16;
5e8d86 ¤   ¤   i = 16/2;
114392 ¤   ¤   do {
af01ae ¤   ¤   ¤   if (t >> i)
b4cfc5 ¤   ¤   ¤   ¤   t >>= i;
fdbb8c ¤   ¤   ¤   else
03e024 ¤   ¤   ¤   ¤   len -= i;
5903d7 ¤   ¤   } while ((i /= 2) != 0);
929371 ¤   }
b7bb7a ¤   return len;
50efe6 }
79cbd0 #endif /* bniBits_16 */
aaaf5a
8c38e5 /*
a21bed ·* If defined, use hand-rolled divide rather than compiler's native.
266018 ·* If the machine doesn't do it in line, the manual code is probably
aaaab8 ·* faster, since it can assume normalization and the fact that the
9fc8ba ·* quotient will fit into 16 bits, which a general 32-bit divide
79b8b7 ·* in a compiler's run-time library can't do.
ed495d ·*/
60bfa9 #ifndef BN_SLOW_DIVIDE_32
808fe1 /* Assume that divisors of more than thirty-two bits are slow */
f161c2 #define BN_SLOW_DIVIDE_32 (32 > 0x20)
fc7454 #endif
eaaf5a
c938e5 /*
73e85f ·* Return (nh<<16|nl) % d, and place the quotient digit into *q.
477bdc ·* It is guaranteed that nh < d, and that d is normalized (with its high
875ded ·* bit set). ·If we have a double-width type, it's easy. ·If not, ooh,
b27c0f ·* yuk!
71495d ·*/
b43350 #ifndef bniDiv21_16
a13abf #if defined(BNWORD32) && !BN_SLOW_DIVIDE_32
4f3401 BNWORD16
9eb9a1 bniDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
bfbb36 {
53c584 ¤   BNWORD32 n = (BNWORD32)nh << 16 | nl;
c4af5a
c2d586 ¤   /* Divisor must be normalized */
72eef5 ¤   pgpAssert(d >> (16-1) == 1);
28af5a
1e94b0 ¤   *q = n / d;
c34a7d ¤   return n % d;
0fefe6 }
abdb21 #else
1738e5 /*
7019ca ·* This is where it gets ugly.
7f775e ·*
2de007 ·* Do the division in two halves, using Algorithm D from section 4.3.1
2bb8a8 ·* of Knuth. ·Note Theorem B from that section, that the quotient estimate
82a6e2 ·* is never more than the true quotient, and is never more than two
192734 ·* too low.
6d775e ·*
3ef95e ·* The mapping onto conventional long division is (everything a half word):
89e4ba ·* ·······_____________qh___ql_
d45d43 ·* dh dl ) nh.h nh.l nl.h nl.l
9db6a5 ·* ············- (qh * d)
6ec3aa ·* ···········-----------
5d2238 ·* ·············rrrr rrrr nl.l
ce6972 ·* ·················- (ql * d)
166a88 ·* ···············-----------
d5bc8e ·* ·················rrrr rrrr
3a775e ·*
3815e9 ·* The implicit 3/2-digit d*qh and d*ql subtractors are computed this way:
ab8d7d ·* ··First, estimate a q digit so that nh/dh works. ·Subtracting qh*dh from
1d7db1 ·* ··the (nh.h nh.l) list leaves a 1/2-word remainder r. ·Then compute the
4c9d8c ·* ··low part of the subtractor, qh * dl. ··This also needs to be subtracted
38f9d1 ·* ··from (nh.h nh.l nl.h) to get the final remainder. ·So we take the
3e91f1 ·* ··remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and
--b988 0002b4bafd440100150 Page 18 of bni16.c
af6618 ·* ··try to subtract qh * dl from that. ·Since the remainder is 1/2-word
16c6dd ·* ··long, shifting and adding nl.h results in a single word r.
1188e0 ·* ··It is possible that the remainder we're working with, r, is less than
c32698 ·* ··the product qh * dl, if we estimated qh too high. ·The estimation
e01818 ·* ··technique can produce a qh that is too large (never too small), leading
ccbbcb ·* ··to r which is too small. ·In that case, decrement the digit qh, add
0ae8c0 ·* ··shifted dh to r (to correct for that error), and subtract dl from the
461da5 ·* ··product we're comparing r with. ·That's the "correct" way to do it, but
f0d269 ·* ··just adding dl to r instead of subtracting it from the product is
9e3c97 ·* ··equivalent and a lot simpler. ·You just have to watch out for overflow.
1c775e ·*
7b6b5a ·* ··The process is repeated with (rrrr rrrr nl.l) for the low digit of the
ebf69b ·* ··quotient ql.
0b775e ·*
79f6f4 ·* The various uses of 16/2 for shifts are because of the note about
e31e9c ·* automatic editing of this file at the very top of the file.
fe495d ·*/
c70db5 #define highhalf(x) ( (x) >> 16/2 )
b6e90f #define lowhalf(x) ( (x) & (((BNWORD16)1 << 16/2)-1) )
7f3401 BNWORD16
1bb9a1 bniDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
7cbb36 {
22befa ¤   BNWORD16 dh = highhalf(d), dl = lowhalf(d);
50cf9d ¤   BNWORD16 qh, ql, prod, r;
f3af5a
38d586 ¤   /* Divisor must be normalized */
01e82a ¤   pgpAssert((d >> (16-1)) == 1);
9faf5a
39182e ¤   /* Do first half-word of division */
93c97b ¤   qh = nh / dh;
10e25e ¤   r = nh % dh;
6551b2 ¤   prod = qh * dl;
a3af5a
b3d8af ¤   /*
a3389a ¤   ·* Add next half-word of numerator to remainder and correct.
ac5820 ¤   ·* qh may be up to two too large.
35a4e3 ¤   ·*/
52e6a5 ¤   r = (r << (16/2)) | highhalf(nl);
f6482f ¤   if (r < prod) {
89eccd ¤   ¤   --qh; r += d;
cfd103 ¤   ¤   if (r >= d && r < prod) {
85daa8 ¤   ¤   ¤   --qh; r += d;·
490fe4 ¤   ¤   }
dc9371 ¤   }
0980c1 ¤   r -= prod;
b2af5a
21e034 ¤   /* Do second half-word of division */
0e3cab ¤   ql = r / dh;
842bf1 ¤   r = r % dh;
80476c ¤   prod = ql * dl;
5baf5a
c0e325 ¤   r = (r << (16/2)) | lowhalf(nl);
26482f ¤   if (r < prod) {
28b298 ¤   ¤   --ql; r += d;
edd103 ¤   ¤   if (r >= d && r < prod) {
ba752d ¤   ¤   ¤   --ql; r += d;
550fe4 ¤   ¤   }
929371 ¤   }
9980c1 ¤   r -= prod;
2aaf5a
66a431 ¤   *q = (qh << (16/2)) | ql;
a8af5a
538da5 ¤   return r;
b8efe6 }
677454 #endif
d86738 #endif /* bniDiv21_16 */
23af5a
71af5a
ac38e5 /*
c43149 ·* In the division functions, the dividend and divisor are referred to
23cc61 ·* as "n" and "d", which stand for "numerator" and "denominator".
2b775e ·*
--4e91 000fea1799740100150 Page 19 of bni16.c
0882a1 ·* The quotient is (nlen-dlen+1) digits long. ·It may be overlapped with
3a3b4e ·* the high (nlen-dlen) words of the dividend, but one extra word is needed
b4df50 ·* on top to hold the top word.
55495d ·*/
f7af5a
1438e5 /*
9923cd ·* Divide an n-word number by a 1-word number, storing the remainder
7ad04d ·* and n-1 words of the n-word quotient. ·The high word is returned.
9abd9b ·* It IS legal for rem to point to the same address as n, and for
42eab3 ·* q to point one word higher.
02775e ·*
946174 ·* TODO: If BN_SLOW_DIVIDE_32, add a divnhalf_16 which uses 16-bit
4d11b4 ·* ······dividends if the divisor is half that long.
66ac82 ·* TODO: Shift the dividend on the fly to avoid the last division and
672014 ·* ······instead have a remainder that needs shifting.
4ff820 ·* TODO: Use reciprocals rather than dividing.
84495d ·*/
7c4ac3 #ifndef bniDiv1_16
3a3401 BNWORD16
d685fc bniDiv1_16(BNWORD16 *q, BNWORD16 *rem, BNWORD16 const *n, unsigned len,
d4ff0e ¤   BNWORD16 d)
babb36 {
517dd8 ¤   unsigned shift;
259bf3 ¤   unsigned xlen;
610a63 ¤   BNWORD16 r;
f56744 ¤   BNWORD16 qhigh;
37af5a
4d5334 ¤   pgpAssert(len > 0);
3aed56 ¤   pgpAssert(d);
ceaf5a
e820c0 ¤   if (len == 1) {
e4ea40 ¤   ¤   r = *n;
6b94a7 ¤   ¤   *rem = r%d;
7e4092 ¤   ¤   return r/d;
659371 ¤   }
f0af5a
c71fab ¤   shift = 0;
ebdca5 ¤   r = d;
35235d ¤   xlen = 16/2;
8743ab ¤   do {
82d555 ¤   ¤   if (r >> xlen)
874bd3 ¤   ¤   ¤   r >>= xlen;
820e1d ¤   ¤   else
30f0a7 ¤   ¤   ¤   shift += xlen;
3e1729 ¤   } while ((xlen /= 2) != 0);
8155b3 ¤   pgpAssert((d >> (16-1-shift)) == 1);
1b1802 ¤   d <<= shift;
72af5a
dc2980 ¤   BIGLITTLE(q -= len-1,q += len-1);
51015b ¤   BIGLITTLE(n -= len,n += len);
fbaf5a
ab29a3 ¤   r = BIGLITTLE(*n++,*--n);
5d7444 ¤   if (r < d) {
6ed3c6 ¤   ¤   qhigh = 0;
f7f037 ¤   } else {
2df48d ¤   ¤   qhigh = r/d;
d9ee48 ¤   ¤   r %= d;
1f9371 ¤   }
71af5a
0d1d7d ¤   xlen = len;
4b2884 ¤   while (--xlen)
cc03bf ¤   ¤   r = bniDiv21_16(BIGLITTLE(q++,--q), r,
cf4662 ¤   ¤   ¤   ¤   BIGLITTLE(*n++,*--n), d);
12af5a
ded8af ¤   /*
db5d19 ¤   ·* Final correction for shift - shift the quotient up "shift"
da86e9 ¤   ·* bits, and merge in the extra bits of quotient. ·Then reduce
5f533a ¤   ·* the final remainder mod the real d.
ffa4e3 ¤   ·*/
d65df3 ¤   if (shift) {
d8aae5 ¤   ¤   d >>= shift;
fe6ab6 ¤   ¤   qhigh = (qhigh << shift) | bniLshift_16(q, len-1, shift);
--818d 0005ce2968140100150 Page 20 of bni16.c
ed14b8 ¤   ¤   BIGLITTLE(q[-1],*q) |= r/d;
64ee48 ¤   ¤   r %= d;
619371 ¤   }
7fe0a8 ¤   *rem = r;
8caf5a
d097ee ¤   return qhigh;
e2efe6 }
407454 #endif
34af5a
de38e5 /*
156e68 ·* This function performs a "quick" modulus of a number with a divisor
1280bd ·* d which is guaranteed to be at most sixteen bits, i.e. less than 65536.
622b4d ·* This applies regardless of the word size the library is compiled with.
a8775e ·*
04e96b ·* This function is important to prime generation, for sieving.
1c495d ·*/
185558 #ifndef bniModQ_16
27cd33 /* If there's a custom bniMod21_16, no normalization needed */
912d3e #ifdef bniMod21_16
8d536c unsigned
8c298a bniModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
c1bb36 {
f8bfcd ¤   unsigned i, shift;
4b0a63 ¤   BNWORD16 r;
b9af5a
545334 ¤   pgpAssert(len > 0);
ddaf5a
e8015b ¤   BIGLITTLE(n -= len,n += len);
19af5a
6210e0 ¤   /* Try using a compare to avoid the first divide */
8e29a3 ¤   r = BIGLITTLE(*n++,*--n);
8b132b ¤   if (r >= d)
3eee48 ¤   ¤   r %= d;
389fd1 ¤   while (--len)
f3a992 ¤   ¤   r = bniMod21_16(r, BIGLITTLE(*n++,*--n), d);
f5af5a
eb8da5 ¤   return r;
d4efe6 }
fd9962 #elif defined(BNWORD32) && !BN_SLOW_DIVIDE_32
25536c unsigned
b8298a bniModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
24bb36 {
680a63 ¤   BNWORD16 r;
9caf5a
36b24c ¤   if (!--len)
dd6024 ¤   ¤   return BIGLITTLE(n[-1],n[0]) % d;
c5af5a
24015b ¤   BIGLITTLE(n -= len,n += len);
544a3b ¤   r = BIGLITTLE(n[-1],n[0]);
b4af5a
3d43ab ¤   do {
e08a40 ¤   ¤   r = (BNWORD16)((((BNWORD32)r<<16) | BIGLITTLE(*n++,*--n)) % d);
88c57e ¤   } while (--len);
c0af5a
8a8da5 ¤   return r;
95efe6 }
ad24e4 #elif 16 >= 0x20
7638e5 /*
da0ce5 ·* If the single word size can hold 65535*65536, then this function
c9461a ·* is avilable.
6d495d ·*/
6d95bc #ifndef highhalf
b90db5 #define highhalf(x) ( (x) >> 16/2 )
d0715f #define lowhalf(x) ( (x) & ((1 << 16/2)-1) )
3c7454 #endif
15536c unsigned
93298a bniModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
22bb36 {
0a7b72 ¤   BNWORD16 r, x;
b7af5a
51015b ¤   BIGLITTLE(n -= len,n += len);
5caf5a
--b2ba 0008d8b611440100150 Page 21 of bni16.c
a729a3 ¤   r = BIGLITTLE(*n++,*--n);
85e1ea ¤   while (--len) {
e5d6fc ¤   ¤   x = BIGLITTLE(*n++,*--n);
d361ac ¤   ¤   r = (r%d << 16/2) | highhalf(x);
3c19c1 ¤   ¤   r = (r%d << 16/2) | lowhalf(x);
299371 ¤   }
faaf5a
350b4f ¤   return r%d;
d3efe6 }
bddb21 #else
859b25 /* Default case - use bniDiv21_16 */
cd536c unsigned
2e298a bniModQ_16(BNWORD16 const *n, unsigned len, unsigned d)
c8bb36 {
90bfcd ¤   unsigned i, shift;
4a0a63 ¤   BNWORD16 r;
a7e507 ¤   BNWORD16 q;
7eaf5a
2c5334 ¤   pgpAssert(len > 0);
41af5a
471fab ¤   shift = 0;
26dca5 ¤   r = d;
a44a71 ¤   i = 16;
de3a3d ¤   while (i /= 2) {
7966eb ¤   ¤   if (r >> i)
f5da0b ¤   ¤   ¤   r >>= i;
060e1d ¤   ¤   else
0c91e5 ¤   ¤   ¤   shift += i;
e29371 ¤   }
857545 ¤   pgpAssert(d >> (16-1-shift) == 1);
491802 ¤   d <<= shift;
ceaf5a
ac015b ¤   BIGLITTLE(n -= len,n += len);
38af5a
7229a3 ¤   r = BIGLITTLE(*n++,*--n);
60132b ¤   if (r >= d)
75ee48 ¤   ¤   r %= d;
21af5a
cd9fd1 ¤   while (--len)
64152a ¤   ¤   r = bniDiv21_16(&q, r, BIGLITTLE(*n++,*--n), d);
6aaf5a
d0d8af ¤   /*
985d19 ¤   ·* Final correction for shift - shift the quotient up "shift"
6c86e9 ¤   ·* bits, and merge in the extra bits of quotient. ·Then reduce
b0533a ¤   ·* the final remainder mod the real d.
2ba4e3 ¤   ·*/
1d5bcd ¤   if (shift)
e90a63 ¤   ¤   r %= d >> shift;
a0af5a
ec8da5 ¤   return r;
89efe6 }
d37454 #endif
3f7d45 #endif /* bniModQ_16 */
6baf5a
b838e5 /*
9f8f9d ·* Reduce n mod d and return the quotient. ·That is, find:
0e90f4 ·* q = n / d;
b9b155 ·* n = n % d;
7e3baf ·* d is altered during the execution of this subroutine by normalizing it.
9832be ·* It must already have its most significant word non-zero; it is shifted
8c8f79 ·* so its most significant bit is non-zero.
ed775e ·*
6eafe6 ·* The quotient q is nlen-dlen+1 words long. ·To make it possible to
346507 ·* overlap the quptient with the input (you can store it in the high dlen
b1ce0a ·* words), the high word of the quotient is *not* stored, but is returned.
82496b ·* (If all you want is the remainder, you don't care about it, anyway.)
a2775e ·*
0bdabd ·* This uses algorithm D from Knuth (4.3.1), except that we do binary
ffd5f9 ·* (shift) normalization of the divisor. ·WARNING: This is hairy!
95775e ·*
645ddb ·* This function is used for some modular reduction, but it is not used in
8dd0fc ·* the modular exponentiation loops; they use Montgomery form and the
--be27 0003116230240100150 Page 22 of bni16.c
dbaee4 ·* corresponding, more efficient, Montgomery reduction. ·This code
4510d2 ·* is needed for the conversion to Montgomery form, however, so it
21f6e7 ·* has to be here and it might as well be reasonably efficient.
70775e ·*
e3d437 ·* The overall operation is as follows ("top" and "up" refer to the
2dfeed ·* most significant end of the number; "bottom" and "down", the least):
3b775e ·*
dc9afe ·* - Shift the divisor up until the most significant bit is set.
ffa9b3 ·* - Shift the dividend up the same amount. ·This will produce the
f85a26 ·* ··correct quotient, and the remainder can be recovered by shifting
b17f2e ·* ··it back down the same number of bits. ·This may produce an overflow
a7697f ·* ··word, but the word is always strictly less than the most significant
484c66 ·* ··divisor word.
0bd315 ·* - Estimate the first quotient digit qhat:
f69aed ·* ··- First take the top two words (one of which is the overflow) of the
fb1d7a ·* ····dividend and divide by the top word of the divisor:
f94384 ·* ····qhat = (nh,nm)/dh. ·This qhat is >= the correct quotient digit
124e72 ·* ····and, since dh is normalized, it is at most two over.
3eb00c ·* ··- Second, correct by comparing the top three words. ·If
07e3f2 ·* ····(dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again.
396520 ·* ····The second iteration can be simpler because there can't be a third.
1e0134 ·* ····The computation can be simplified by subtracting dh*qhat from
e2e263 ·* ····both sides, suitably shifted. ·This reduces the left side to
4932b9 ·* ····dl*qhat. ·On the right, (nh,nm)-dh*qhat is simply the
1a468d ·* ····remainder r from (nh,nm)%dh, so the right is (r,nl).
c4208a ·* ····This produces qhat that is almost always correct and at
ff6fac ·* ····most (prob ~ 2/2^16) one too high.
f6666b ·* - Subtract qhat times the divisor (suitably shifted) from the dividend.
411eae ·* ··If there is a borrow, qhat was wrong, so decrement it
14e18e ·* ··and add the divisor back in (once).
a72ab7 ·* - Store the final quotient digit qhat in the quotient array q.
48775e ·*
eaabaf ·* Repeat the quotient digit computation for successive digits of the
6e2a22 ·* quotient until the whole quotient has been computed. ·Then shift the
ca2dab ·* divisor and the remainder down to correct for the normalization.
77775e ·*
8ad917 ·* TODO: Special case 2-word divisors.
7bf820 ·* TODO: Use reciprocals rather than dividing.
b9495d ·*/
1d6437 #ifndef divn_16
233401 BNWORD16
8f58a9 bniDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen)
37bb36 {
429b03 ¤   BNWORD16 nh,nm,nl;¤ /* Top three words of the dividend */
52dd05 ¤   BNWORD16 dh,dl;¤/* Top two words of the divisor */
2d6f51 ¤   BNWORD16 qhat;¤ /* Extimate of quotient word */
50df45 ¤   BNWORD16 r;¤/* Remainder from quotient estimate division */
41f3d8 ¤   BNWORD16 qhigh;¤/* High word of quotient */
0c27a0 ¤   unsigned i;¤/* Temp */
06500c ¤   unsigned shift;¤/* Bits shifted by normalization */
cf74f3 ¤   unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */
cbf8b0 #ifdef mul16_ppmm
c7d90c ¤   BNWORD16 t16;
38ef62 #elif defined(BNWORD32)
82e702 ¤   BNWORD32 t32;
489d9c #else /* use bniMulN1_16 */
b23883 ¤   BNWORD16 t2[2];
1dcd0c #define t2high BIGLITTLE(t2[0],t2[1])
da64b5 #define t2low BIGLITTLE(t2[1],t2[0])
8b7454 #endif
56af5a
f5872a ¤   pgpAssert(dlen);
bd9dbd ¤   pgpAssert(nlen >= dlen);
93af5a
c7d8af ¤   /*
7f480b ¤   ·* Special cases for short divisors. ·The general case uses the
00fd33 ¤   ·* top top 2 digits of the divisor (d) to estimate a quotient digit,
eec774 ¤   ·* so it breaks if there are fewer digits available. ·Thus, we need
658f21 ¤   ·* special cases for a divisor of length 1. ·A divisor of length
32ee27 ¤   ·* 2 can have a *lot* of administrivia overhead removed removed,
b26e28 ¤   ·* so it's probably worth special-casing that case, too.
31a4e3 ¤   ·*/
--7ff1 000f38ee92a40100150 Page 23 of bni16.c
2bb547 ¤   if (dlen == 1)
e5a1a8 ¤   ¤   return bniDiv1_16(q, BIGLITTLE(n-1,n), n, nlen,
0bbb59 ¤   ¤   ··················BIGLITTLE(d[-1],d[0]));
75af5a
bdb177 #if 0
a0d8af ¤   /*
559c22 ¤   ·* @@@ This is not yet written... ·The general loop will do,
c07741 ¤   ·* albeit less efficiently
b7a4e3 ¤   ·*/
543ff3 ¤   if (dlen == 2) {
9b1b17 ¤   ¤   /*
290fc2 ¤   ¤   ·* divisor two digits long:
611388 ¤   ¤   ·* use the 3/2 technique from Knuth, but we know
9ebd83 ¤   ¤   ·* it's exact.
259de3 ¤   ¤   ·*/
45a363 ¤   ¤   dh = BIGLITTLE(d[-1],d[0]);
139d7f ¤   ¤   dl = BIGLITTLE(d[-2],d[1]);
b0fd08 ¤   ¤   shift = 0;
9dc9f0 ¤   ¤   if ((sh & ((BNWORD16)1 << 16-1-shift)) == 0) {
1ef603 ¤   ¤   ¤   do {
3d5919 ¤   ¤   ¤   ¤   shift++;
d3358f ¤   ¤   ¤   } while (dh & (BNWORD16)1<<16-1-shift) == 0);
0525fb ¤   ¤   ¤   dh = dh << shift | dl >> (16-shift);
17ed08 ¤   ¤   ¤   dl <<= shift;
f0af5a
3baf5a
ad0fe4 ¤   ¤   }
26af5a
d3af5a
cb52a4 ¤   ¤   for (shift = 0; (dh & (BNWORD16)1 << 16-1-shift)) == 0;
c248b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   shift++)
97b110 ¤   ¤   ¤   ;
2d1c78 ¤   ¤   if (shift) {
f40fe4 ¤   ¤   }
f87766 ¤   ¤   dh = dh << shift | dl >> (16-shift);
26fd08 ¤   ¤   shift = 0;
243ddc ¤   ¤   while (dh
fb9371 ¤   }
d37454 #endif
beaf5a
6c53dc ¤   dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
b50d5f ¤   pgpAssert(dh);
23af5a
93d240 ¤   /* Normalize the divisor */
3f1fab ¤   shift = 0;
ea9edc ¤   r = dh;
760833 ¤   i = 16/2;
8543ab ¤   do {
3466eb ¤   ¤   if (r >> i)
28da0b ¤   ¤   ¤   r >>= i;
fa0e1d ¤   ¤   else
1391e5 ¤   ¤   ¤   shift += i;
93b881 ¤   } while ((i /= 2) != 0);
ddaf5a
10790d ¤   nh = 0;
705df3 ¤   if (shift) {
dd8a87 ¤   ¤   bniLshift_16(d, dlen, shift);
d10141 ¤   ¤   dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
d2ca8b ¤   ¤   nh = bniLshift_16(n, nlen, shift);
dc9371 ¤   }
13af5a
c42e18 ¤   /* Assert that dh is now normalized */
c1fbc2 ¤   pgpAssert(dh >> (16-1));
40af5a
b0ff88 ¤   /* Also get the second-most significant word of the divisor */
e7472b ¤   dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2)));
49af5a
68d8af ¤   /*
e2007a ¤   ·* Adjust pointers: n to point to least significant end of first
6ad7b5 ¤   ·* first subtract, and q to one the most-significant end of the
1ae66e ¤   ·* quotient array.
f3a4e3 ¤   ·*/
--809f 0005c3b949440100150 Page 24 of bni16.c
f63fac ¤   BIGLITTLE(n -= qlen,n += qlen);
7b4367 ¤   BIGLITTLE(q -= qlen,q += qlen);
36af5a
40eeb5 ¤   /* Fetch the most significant stored word of the dividend */
60e870 ¤   nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
5baf5a
28d8af ¤   /*
fc6d56 ¤   ·* Compute the first digit of the quotient, based on the
d70e82 ¤   ·* first two words of the dividend (the most significant of which
fe3605 ¤   ·* is the overflow word h).
fca4e3 ¤   ·*/
7921e5 ¤   if (nh) {
ba068c ¤   ¤   pgpAssert(nh < dh);
d8a2ec ¤   ¤   r = bniDiv21_16(&qhat, nh, nm, dh);
c66eba ¤   } else if (nm >= dh) {
3fa30b ¤   ¤   qhat = nm/dh;
9334b4 ¤   ¤   r = nm % dh;
762487 ¤   } else {¤   /* Quotient is zero */
a0d3c6 ¤   ¤   qhigh = 0;
f40a09 ¤   ¤   goto divloop;
ba9371 ¤   }
40af5a
8a10e1 ¤   /* Now get the third most significant word of the dividend */
365498 ¤   nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
c7af5a
56d8af ¤   /*
fb728b ¤   ·* Correct qhat, the estimate of quotient digit.
4efac8 ¤   ·* qhat can only be high, and at most two words high,
ee7c55 ¤   ·* so the loop can be unrolled and abbreviated.
36a4e3 ¤   ·*/
88f8b0 #ifdef mul16_ppmm
710db7 ¤   mul16_ppmm(nm, t16, qhat, dl);
c15a30 ¤   if (nm > r || (nm == r && t16 > nl)) {
df7f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
e9eeae ¤   ¤   qhat--;
d3588d ¤   ¤   if ((r += dh) >= dh) {
59b47f ¤   ¤   ¤   nm -= (t16 < dl);
159909 ¤   ¤   ¤   t16 -= dl;
d297d4 ¤   ¤   ¤   if (nm > r || (nm == r && t16 > nl))
b70329 ¤   ¤   ¤   ¤   qhat--;
7f0fe4 ¤   ¤   }
c49371 ¤   }
eeef62 #elif defined(BNWORD32)
b5c2a1 ¤   t32 = (BNWORD32)qhat * dl;
2b8ff6 ¤   if (t32 > ((BNWORD32)r << 16) + nl) {
377f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
e5eeae ¤   ¤   qhat--;
946578 ¤   ¤   if ((r += dh) > dh) {
dbfea2 ¤   ¤   ¤   t32 -= dl;
f23d86 ¤   ¤   ¤   if (t32 > ((BNWORD32)r << 16) + nl)
5a0329 ¤   ¤   ¤   ¤   qhat--;
e50fe4 ¤   ¤   }
829371 ¤   }
74658e #else /* Use bniMulN1_16 */
235240 ¤   bniMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
e0b1be ¤   if (t2high > r || (t2high == r && t2low > nl)) {
b37f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
e3eeae ¤   ¤   qhat--;
ba588d ¤   ¤   if ((r += dh) >= dh) {
875d65 ¤   ¤   ¤   t2high -= (t2low < dl);
90a6d7 ¤   ¤   ¤   t2low -= dl;
00cf7a ¤   ¤   ¤   if (t2high > r || (t2high == r && t2low > nl))
9c0329 ¤   ¤   ¤   ¤   qhat--;
400fe4 ¤   ¤   }
699371 ¤   }
037454 #endif
68af5a
e43d4c ¤   /* Do the multiply and subtract */
588828 ¤   r = bniMulSub1_16(n, d, dlen, qhat);
67e204 ¤   /* If there was a borrow, add back once. */
31fa13 ¤   if (r > nh) {¤  /* Borrow? */
5c1ce5 ¤   ¤   (void)bniAddN_16(n, d, dlen);
--15e3 0000adf177540100150 Page 25 of bni16.c
f0eeae ¤   ¤   qhat--;
b39371 ¤   }
90af5a
2ca3ca ¤   /* Remember the first quotient digit. */
75bac6 ¤   qhigh = qhat;
d3af5a
1e7f0b ¤   /* Now, the main division loop: */
3c2a7b divloop:
a655ea ¤   while (qlen--) {
5eaf5a
b17aef ¤   ¤   /* Advance n */
708c3f ¤   ¤   nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
109f99 ¤   ¤   BIGLITTLE(++n,--n);
d0baed ¤   ¤   nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
9aaf5a
2460da ¤   ¤   if (nh == dh) {
1d7cc0 ¤   ¤   ¤   qhat = ~(BNWORD16)0;
4a8a33 ¤   ¤   ¤   /* Optimized computation of r = (nh,nm) - qhat * dh */
62ceb5 ¤   ¤   ¤   r = nh + nm;
202398 ¤   ¤   ¤   if (r < nh)
1358b7 ¤   ¤   ¤   ¤   goto subtract;
0445a6 ¤   ¤   } else {
8aabd2 ¤   ¤   ¤   pgpAssert(nh < dh);
4cbabc ¤   ¤   ¤   r = bniDiv21_16(&qhat, nh, nm, dh);
eb0fe4 ¤   ¤   }
c4af5a
c70783 ¤   ¤   nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
eff8b0 #ifdef mul16_ppmm
fa4c44 ¤   ¤   mul16_ppmm(nm, t16, qhat, dl);
4dcba8 ¤   ¤   if (nm > r || (nm == r && t16 > nl)) {
8dc34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
7179dd ¤   ¤   ¤   qhat--;
7ad4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
598377 ¤   ¤   ¤   ¤   nm -= (t16 < dl);
637be8 ¤   ¤   ¤   ¤   t16 -= dl;
97c4cf ¤   ¤   ¤   ¤   if (nm > r || (nm == r && t16 > nl))
79f54c ¤   ¤   ¤   ¤   ¤   qhat--;
5ca3a6 ¤   ¤   ¤   }
ca0fe4 ¤   ¤   }
8cef62 #elif defined(BNWORD32)
c14ede ¤   ¤   t32 = (BNWORD32)qhat * dl;
03a8f9 ¤   ¤   if (t32 > ((BNWORD32)r<<16) + nl) {
15c34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
a279dd ¤   ¤   ¤   qhat--;
99d4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
7c1c43 ¤   ¤   ¤   ¤   t32 -= dl;
99abc7 ¤   ¤   ¤   ¤   if (t32 > ((BNWORD32)r << 16) + nl)
7ef54c ¤   ¤   ¤   ¤   ¤   qhat--;
00a3a6 ¤   ¤   ¤   }
3c0fe4 ¤   ¤   }
2d658e #else /* Use bniMulN1_16 */
194367 ¤   ¤   bniMulN1_16(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
6fde8d ¤   ¤   if (t2high > r || (t2high == r && t2low > nl)) {
fec34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
da79dd ¤   ¤   ¤   qhat--;
e3d4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
5c9830 ¤   ¤   ¤   ¤   t2high -= (t2low < dl);
4d928a ¤   ¤   ¤   ¤   t2low -= dl;
c6cf98 ¤   ¤   ¤   ¤   if (t2high > r || (t2high == r && t2low > nl))
e6f54c ¤   ¤   ¤   ¤   ¤   qhat--;
c4a3a6 ¤   ¤   ¤   }
920fe4 ¤   ¤   }
287454 #endif
99af5a
861b17 ¤   ¤   /*
f5a70b ¤   ¤   ·* As a point of interest, note that it is not worth checking
21b062 ¤   ¤   ·* for qhat of 0 or 1 and installing special-case code. ·These
474065 ¤   ¤   ·* occur with probability 2^-16, so spending 1 cycle to check
0f1cbe ¤   ¤   ·* for them is only worth it if we save more than 2^15 cycles,
0a265f ¤   ¤   ·* and a multiply-and-subtract for numbers in the 1024-bit
2f5841 ¤   ¤   ·* range just doesn't take that long.
0a9de3 ¤   ¤   ·*/
--74b1 000046dcd1740100150 Page 26 of bni16.c
70bdcf subtract:
261b17 ¤   ¤   /*
9aa55f ¤   ¤   ·* n points to the least significant end of the substring
386576 ¤   ¤   ·* of n to be subtracted from. ·qhat is either exact or
ecdb63 ¤   ¤   ·* one too large. ·If the subtract gets a borrow, it was
1b897d ¤   ¤   ·* one too large and the divisor is added back in. ·It's
cf6fbb ¤   ¤   ·* a dlen+1 word add which is guaranteed to produce a
5125ad ¤   ¤   ·* carry out, so it can be done very simply.
df9de3 ¤   ¤   ·*/
5c8e90 ¤   ¤   r = bniMulSub1_16(n, d, dlen, qhat);
f81560 ¤   ¤   if (r > nh) {¤  /* Borrow? */
e3200b ¤   ¤   ¤   (void)bniAddN_16(n, d, dlen);
a679dd ¤   ¤   ¤   qhat--;
a20fe4 ¤   ¤   }
e55982 ¤   ¤   /* Store the quotient digit */
08783d ¤   ¤   BIGLITTLE(*q++,*--q) = qhat;
fe9371 ¤   }
f59169 ¤   /* Tah dah! */
bbaf5a
535df3 ¤   if (shift) {
b6e191 ¤   ¤   bniRshift_16(d, dlen, shift);
3441f7 ¤   ¤   bniRshift_16(n, dlen, shift);
ef9371 ¤   }
a4af5a
8197ee ¤   return qhigh;
c8efe6 }
9c7454 #endif
12af5a
1238e5 /*
04a747 ·* Find the negative multiplicative inverse of x (x must be odd!) modulo 2^16.
10775e ·*
0ee4a4 ·* This just performs Newton's iteration until it gets the
7a2d8c ·* inverse. ·The initial estimate is always correct to 3 bits, and
fdd773 ·* sometimes 4. ·The number of valid bits doubles each iteration.
9c32ba ·* (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable
ba60ca ·* for the error mod 2^2n. ·x * y == 1 + k*2^n (mod 2^2n) and follow
c05d3e ·* the iteration through.)
6c495d ·*/
3e747d #ifndef bniMontInv1_16
be3401 BNWORD16
89bfc5 bniMontInv1_16(BNWORD16 const x)
dbbb36 {
fbfb93 ········BNWORD16 y = x, z;
deaf5a
d5201b ¤   pgpAssert(x & 1);
0ad83c ·
27d2ee ········while ((z = x*y) != 1)
c7fa12 ················y *= 2 - z;
4d6ae3 ········return -y;
c1efe6 }
80040b #endif /* !bniMontInv1_16 */
62af5a
e39f73 #if defined(BNWORD32) && PRODUCT_SCAN
4538e5 /*
7e3de0 ·* Test code for product-scanning Montgomery reduction.
dc5767 ·* This seems to slow the C code down rather than speed it up.
66775e ·*
443e2e ·* The first loop computes the Montgomery multipliers, storing them over
109652 ·* the low half of the number n.
d8775e ·*
76bdb8 ·* The second half multiplies the upper half, adding in the modulus
8f2380 ·* times the Montgomery multipliers. ·The results of this multiply
e6fa30 ·* are stored.
95495d ·*/
fa314a void
a3350a bniMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned mlen, BNWORD16 inv)
61bb36 {
828584 ¤   BNWORD32 x, y;
9e01b5 ¤   BNWORD16 const *pm;
aa82fb ¤   BNWORD16 *pn;
d9dcba ¤   BNWORD16 t;
0450fc ¤   unsigned carry;
--5aa8 0008bde824d40100150 Page 27 of bni16.c
d807cb ¤   unsigned i, j;
27af5a
94157a ¤   /* Special case of zero */
9bff48 ¤   if (!mlen)
db99bf ¤   ¤   return;
1aaf5a
e2a702 ¤   /* Pass 1 - compute Montgomery multipliers */
6b1ffe ¤   /* First iteration can have certain simplifications. */
e9af9a ¤   t = BIGLITTLE(n[-1],n[0]);
c4b067 ¤   x = t;
ab451d ¤   t *= inv;
9ef049 ¤   BIGLITTLE(n[-1], n[0]) = t;
4cf4e6 ¤   x += (BNWORD32)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */
ee9e3d ¤   pgpAssert((BNWORD16)x == 0);
92a36e ¤   x = x >> 16;
75af5a
23947e ¤   for (i = 1; i < mlen; i++) {
2ffcf3 ¤   ¤   carry = 0;
9dc3fd ¤   ¤   pn = n;
2ad39c ¤   ¤   pm = BIGLITTLE(mod-i-1,mod+i+1);
47f8a4 ¤   ¤   for (j = 0; j < i; j++) {
edb460 ¤   ¤   ¤   y = (BNWORD32)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm);
301ca0 ¤   ¤   ¤   x += y;
bcdfb0 ¤   ¤   ¤   carry += (x < y);
8d0fe4 ¤   ¤   }
d8ae1e ¤   ¤   pgpAssert(BIGLITTLE(pn == n-i, pn == n+i));
f4d720 ¤   ¤   y = t = BIGLITTLE(pn[-1], pn[0]);
448bd3 ¤   ¤   x += y;
d956e4 ¤   ¤   carry += (x < y);
ffa268 ¤   ¤   BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD16)x;
5d35b5 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-1, pm == mod+1));
1102e4 ¤   ¤   y = (BNWORD32)t * BIGLITTLE(pm[0],pm[-1]);
6e8bd3 ¤   ¤   x += y;
e556e4 ¤   ¤   carry += (x < y);
80a355 ¤   ¤   pgpAssert((BNWORD16)x == 0);
01c574 ¤   ¤   x = x >> 16 | (BNWORD32)carry << 16;
099371 ¤   }
fcaf5a
302d98 ¤   BIGLITTLE(n -= mlen, n += mlen);
aaaf5a
d77cfe ¤   /* Pass 2 - compute upper words and add to n */
bb947e ¤   for (i = 1; i < mlen; i++) {
b3fcf3 ¤   ¤   carry = 0;
ed0805 ¤   ¤   pm = BIGLITTLE(mod-i,mod+i);
2fc3fd ¤   ¤   pn = n;
23ed18 ¤   ¤   for (j = i; j < mlen; j++) {
5bbdff ¤   ¤   ¤   y = (BNWORD32)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn);
791ca0 ¤   ¤   ¤   x += y;
17dfb0 ¤   ¤   ¤   carry += (x < y);
8d0fe4 ¤   ¤   }
5dea60 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen));
bc3793 ¤   ¤   pgpAssert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i));
22dabc ¤   ¤   y = t = BIGLITTLE(*(n-i),*(n+i-1));
aa8bd3 ¤   ¤   x += y;
5c56e4 ¤   ¤   carry += (x < y);
97a45c ¤   ¤   BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD16)x;
439f5b ¤   ¤   x = (x >> 16) | (BNWORD32)carry << 16;
e89371 ¤   }
52af5a
4bf753 ¤   /* Last round of second half, simplified. */
e6d2d2 ¤   t = BIGLITTLE(*(n-mlen),*(n+mlen-1));
1a6e1c ¤   x += t;
e703ad ¤   BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD16)x;
675319 ¤   carry = (unsigned)(x >> 16);
2faf5a
81a53b ¤   while (carry)
460493 ¤   ¤   carry -= bniSubN_16(n, mod, mlen);
b49cf4 ¤   while (bniCmp_16(n, mod, mlen) >= 0)
84052c ¤   ¤   (void)bniSubN_16(n, mod, mlen);
2defe6 }
c1c818 #define bniMontReduce_16 bniMontReduce_16
8b7454 #endif
--cea8 0005c8255e640100150 Page 28 of bni16.c
e0af5a
d338e5 /*
9bee5a ·* Montgomery reduce n, modulo mod. ·This reduces modulo mod and divides by
3190a9 ·* 2^(16*mlen). ·Returns the result in the *top* mlen words of the argument n.
b74e35 ·* This is ready for another multiplication using bniMul_16.
d2775e ·*
c42def ·* Montgomery representation is a very useful way to encode numbers when
9ba0f9 ·* you're doing lots of modular reduction. ·What you do is pick a multiplier
497f63 ·* R which is relatively prime to the modulus and very easy to divide by.
13bca7 ·* Since the modulus is odd, R is closen as a power of 2, so the division
8cdc5c ·* is a shift. ·In fact, it's a shift of an integral number of words,
5afb89 ·* so the shift can be implicit - just drop the low-order words.
25775e ·*
b24556 ·* Now, choose R *larger* than the modulus m, 2^(16*mlen). ·Then convert
92bdb2 ·* all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the
488961 ·* relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. ·Note that:
c8a547 ·* - The Montgomery form of a number depends on the modulus m.
f7bd40 ·* ··A fixed modulus m is assumed throughout this discussion.
3f9d87 ·* - Since R is relaitvely prime to m, multiplication by R is invertible;
9870cf ·* ··no information about the numbers is lost, they're just scrambled.
94e310 ·* - Adding (and subtracting) numbers in this form works just as usual.
222937 ·* ··M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m
4c1edf ·* - Multiplying numbers in this form produces a*b*R*R. ·The problem
7b322e ·* ··is to divide out the excess factor of R, modulo m as well as to
9a7321 ·* ··reduce to the given length mlen. ·It turns out that this can be
e2ab47 ·* ··done *faster* than a normal divide, which is where the speedup
a8c3b7 ·* ··in Montgomery division comes from.
72775e ·*
a2e4aa ·* Normal reduction chooses a most-significant quotient digit q and then
09ffcc ·* subtracts q*m from the number to be reduced. ·Choosing q is tricky
7ed796 ·* and involved (just look at bniDiv_16 to see!) and is usually
a67816 ·* imperfect, requiring a check for correction after the subtraction.
ed775e ·*
b8b6cd ·* Montgomery reduction *adds* a multiple of m to the *low-order* part
2f1d3e ·* of the number to be reduced. ·This multiple is chosen to make the
4cdcbd ·* low-order part of the number come out to zero. ·This can be done
eb452c ·* with no trickery or error using a precomputed inverse of the modulus.
d5a07a ·* In this code, the "part" is one word, but any width can be used.
0d775e ·*
7ccd30 ·* Repeating this step sufficiently often results in a value which
6aafde ·* is a multiple of R (a power of two, remember) but is still (since
dbdfee ·* the additions were to the low-order part and thus did not increase
515a94 ·* the value of the number being reduced very much) still not much
afa69e ·* larger than m*R. ·Then implicitly divide by R and subtract off
bcb0fb ·* m until the result is in the correct range.
42775e ·*
8997b6 ·* Since the low-order part being cancelled is less than R, the
1f19df ·* multiple of m added must have a multiplier which is at most R-1.
fab2c3 ·* Assuming that the input is at most m*R-1, the final number is
38b3ee ·* at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from
cf88f4 ·* the high-order part, equivalent to subtracting m*R from the
8f3b57 ·* while number, produces a result which is at most m*R - m - 1,
b66ff3 ·* which divided by R is at most m-1.
f6775e ·*
d0e28b ·* To convert *to* Montgomery form, you need a regular remainder
2a0506 ·* routine, although you can just compute R*R (mod m) and do the
e19da9 ·* conversion using Montgomery multiplication. ·To convert *from*
1ae178 ·* Montgomery form, just Montgomery reduce the number to
53d688 ·* remove the extra factor of R.
669ec0 ·*·
e28bba ·* TODO: Change to a full inverse and use Karatsuba's multiplication
b7e6d5 ·* rather than this word-at-a-time.
1a495d ·*/
b4c756 #ifndef bniMontReduce_16
77314a void
d6e3a4 bniMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen,
4459d1 ················BNWORD16 inv)
f0bb36 {
cbdcba ¤   BNWORD16 t;
3e9a7a ¤   BNWORD16 c = 0;
318079 ¤   unsigned len = mlen;
5caf5a
--e17e 000678d9fce40100150 Page 29 of bni16.c
f59eac ¤   /* inv must be the negative inverse of mod's least significant word */
3fe5b6 ¤   pgpAssert((BNWORD16)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD16)-1);
86af5a
1086c8 ¤   pgpAssert(len);
74af5a
6743ab ¤   do {
00d5b5 ¤   ¤   t = bniMulAdd1_16(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0]));
6a2bf4 ¤   ¤   c += bniAdd1_16(BIGLITTLE(n-mlen,n+mlen), len, t);
20f036 ¤   ¤   BIGLITTLE(--n,++n);
c5c57e ¤   } while (--len);
86af5a
8ad8af ¤   /*
5df214 ¤   ·* All that adding can cause an overflow past the modulus size,
548b38 ¤   ·* but it's unusual, and never by much, so a subtraction loop
47a65a ¤   ·* is the right way to deal with it.
752a16 ¤   ·* This subtraction happens infrequently - I've only ever seen it
895758 ¤   ·* invoked once per reduction, and then just under 22.5% of the time.
6ba4e3 ¤   ·*/
b36bd2 ¤   while (c)
af52a3 ¤   ¤   c -= bniSubN_16(n, mod, mlen);
179cf4 ¤   while (bniCmp_16(n, mod, mlen) >= 0)
ea052c ¤   ¤   (void)bniSubN_16(n, mod, mlen);
8fefe6 }
07d3a0 #endif /* !bniMontReduce_16 */
9baf5a
1738e5 /*
2d00f3 ·* A couple of helpers that you might want to implement atomically
a94a88 ·* in asm sometime.
77495d ·*/
c0ae11 #ifndef bniMontMul_16
a138e5 /*
7b187a ·* Multiply "num1" by "num2", modulo "mod", all of length "len", and
d38535 ·* place the result in the high half of "prod". ·"inv" is the inverse
ca9541 ·* of the least-significant word of the modulus, modulo 2^16.
2dcfb2 ·* This uses numbers in Montgomery form. ·Reduce using "len" and "inv".
d8775e ·*
2e97ba ·* This is implemented as a macro to win on compilers that don't do
0799a7 ·* inlining, since it's so trivial.
62495d ·*/
40addc #define bniMontMul_16(prod, n1, n2, mod, len, inv) \
42fb0a ¤   (bniMulX_16(prod, n1, n2, len), bniMontReduce_16(prod, mod, len, inv))
0bef1d #endif /* !bniMontMul_16 */
3daf5a
0f6de3 #ifndef bniMontSquare_16
6a38e5 /*
e52c86 ·* Square "num", modulo "mod", both of length "len", and place the result
e62dbd ·* in the high half of "prod". ·"inv" is the inverse of the least-significant
a401bb ·* word of the modulus, modulo 2^16.
bacfb2 ·* This uses numbers in Montgomery form. ·Reduce using "len" and "inv".
29775e ·*
7997ba ·* This is implemented as a macro to win on compilers that don't do
ff99a7 ·* inlining, since it's so trivial.
f1495d ·*/
564bb4 #define bniMontSquare_16(prod, n, mod, len, inv) \
c06897 ¤   (bniSquare_16(prod, n, len), bniMontReduce_16(prod, mod, len, inv))
1d67c5 ¤
3932d0 #endif /* !bniMontSquare_16 */
5faf5a
4e38e5 /*
67a390 ·* Convert a number to Montgomery form - requires mlen + nlen words
8e15f8 ·* of memory in "n".
b7495d ·*/
84314a void
db2d01 bniToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen)
6bbb36 {
9a9cf5 ¤   /* Move n up "mlen" words */
33f826 ¤   bniCopy_16(BIGLITTLE(n-mlen,n+mlen), n, nlen);
668f80 ¤   bniZero_16(n, mlen);
f2a154 ¤   /* Do the division - dump the quotient in the high-order words */
138388 ¤   (void)bniDiv_16(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen);
50efe6 }
67af5a
--f5e3 000a2c654d840100150 Page 30 of bni16.c
bc38e5 /*
00d6c1 ·* Convert from Montgomery form. ·Montgomery reduction is all that is
e9e480 ·* needed.
b6495d ·*/
f0314a void
4fd57a bniFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len)
8cbb36 {
3e3595 ¤   /* Zero the high words of n */
f9e3d7 ¤   bniZero_16(BIGLITTLE(n-len,n+len), len);
4ec286 ¤   bniMontReduce_16(n, mod, len, bniMontInv1_16(mod[BIGLITTLE(-1,0)]));
ad9c58 ¤   /* Move n down len words */
4c931c ¤   bniCopy_16(n, BIGLITTLE(n-len,n+len), len);
a4efe6 }
2eaf5a
7238e5 /*
6cd039 ·* The windowed exponentiation algorithm, precomputes a table of odd
2c0d97 ·* powers of n up to 2^k. ·See the comment in bnExpMod_16 below for
e3c2ff ·* an explanation of how it actually works works.
1b775e ·*
0ea488 ·* It takes 2^(k-1)-1 multiplies to compute the table, and (e-1)/(k+1)
13e229 ·* multiplies (on average) to perform the exponentiation. ·To minimize
81e12a ·* the sum, k must vary with e. ·The optimal window sizes vary with the
6a06bb ·* exponent length. ·Here are some selected values and the boundary cases.
6b44f4 ·* (An underscore _ has been inserted into some of the numbers to ensure
3a40fc ·* that magic strings like 16 do not appear in this table. ·It should be
a60710 ·* ignored.)
e7775e ·*
1705dd ·* At e = ···1 bits, k=1 ··(0.000000) is best
1b630a ·* At e = ···2 bits, k=1 ··(0.500000) is best
a912b6 ·* At e = ···4 bits, k=1 ··(1.500000) is best
54a6b8 ·* At e = ···8 bits, k=2 ··(3.333333) < k=1 ··(3.500000)
3a5942 ·* At e = ·1_6 bits, k=2 ··(6.000000) is best
e20761 ·* At e = ··26 bits, k=3 ··(9.250000) < k=2 ··(9.333333)
52d0cf ·* At e = ·3_2 bits, k=3 ·(10.750000) is best
8f9f06 ·* At e = ·6_4 bits, k=3 ·(18.750000) is best
5d1f23 ·* At e = ··82 bits, k=4 ·(23.200000) < k=3 ·(23.250000)
6b030f ·* At e = ·128 bits, k=4 (3_2.400000) is best
8dfff6 ·* At e = ·242 bits, k=5 ·(55.1_66667) < k=4 (55.200000)
08abb3 ·* At e = ·256 bits, k=5 ·(57.500000) is best
3fcd12 ·* At e = ·512 bits, k=5 (100.1_66667) is best
0b03f9 ·* At e = ·674 bits, k=6 (127.142857) < k=5 (127.1_66667)
910d7b ·* At e = 1024 bits, k=6 (177.142857) is best
a8730e ·* At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857)
4b356a ·* At e = 2048 bits, k=7 (318.875000) is best
cf7a5b ·* At e = 4096 bits, k=7 (574.875000) is best
55775e ·*
ac0ef9 ·* The numbers in parentheses are the expected number of multiplications
d2471f ·* needed to do the computation. ·The normal russian-peasant modular
3447b0 ·* exponentiation technique always uses (e-1)/2. ·For exponents as
66d6ec ·* small as 192 bits (below the range of current factoring algorithms),
ca7212 ·* half of the multiplies are eliminated, 45.2 as opposed to the naive
8226b5 ·* 95.5. ·Counting the 191 squarings as 3/4 a multiply each (squaring
956545 ·* proper is just over half of multiplying, but the Montgomery
9fde2c ·* reduction in each case is also a multiply), that's 143.25
6b992d ·* multiplies, for totals of 188.45 vs. 238.75 - a 21% savings.
66e86b ·* For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a
588afb ·* 24.3% savings. ·It asymptotically approaches 25%.
69775e ·*
5cf291 ·* Um, actually there's a slightly more accurate way to count, which
8ce881 ·* really is the average number of multiplies required, averaged
310fb0 ·* uniformly over all 2^(e-1) e-bit numbers, from 2^(e-1) to (2^e)-1.
52bbff ·* It's based on the recurrence that for the last b bits, b <= k, at
084553 ·* most one multiply is needed (and none at all 1/2^b of the time),
72acfb ·* while when b > k, the odds are 1/2 each way that the bit will be
215519 ·* 0 (meaning no multiplies to reduce it to the b-1-bit case) and
b6dff6 ·* 1/2 that the bit will be 1, starting a k-bit window and requiring
e918fe ·* 1 multiply beyond the b-k-bit case. ·Since the most significant
ad41f6 ·* bit is always 1, a k-bit window always starts there, and that
cb0a4c ·* multiply is by 1, so it isn't a multiply at all. ·Thus, the
c1c456 ·* number of multiplies is simply that needed for the last e-k bits.
ed52be ·* This recurrence produces:
a2775e ·*
--caef 000ed186bd840100150 Page 31 of bni16.c
1605dd ·* At e = ···1 bits, k=1 ··(0.000000) is best
54630a ·* At e = ···2 bits, k=1 ··(0.500000) is best
e212b6 ·* At e = ···4 bits, k=1 ··(1.500000) is best
b55c43 ·* At e = ···6 bits, k=2 ··(2.437500) < k=1 ··(2.500000)
065dc4 ·* At e = ···8 bits, k=2 ··(3.109375) is best
2ba533 ·* At e = ·1_6 bits, k=2 ··(5.777771) is best
5a323f ·* At e = ··24 bits, k=3 ··(8.437629) < k=2 ··(8.444444)
c4b0ab ·* At e = ·3_2 bits, k=3 ·(10.437492) is best
46de54 ·* At e = ·6_4 bits, k=3 ·(18.437500) is best
0a9d65 ·* At e = ··81 bits, k=4 ·(22.6_40000) < k=3 ·(22.687500)
fb03d4 ·* At e = ·128 bits, k=4 (3_2.040000) is best
0323e8 ·* At e = ·241 bits, k=5 ·(54.611111) < k=4 ·(54.6_40000)
2d6078 ·* At e = ·256 bits, k=5 ·(57.111111) is best
5666d1 ·* At e = ·512 bits, k=5 ·(99.777778) is best
8423ae ·* At e = ·673 bits, k=6 (126.591837) < k=5 (126.611111)
45f6ca ·* At e = 1024 bits, k=6 (176.734694) is best
de8b19 ·* At e = 1793 bits, k=7 (286.578125) < k=6 (286.591837)
fadf27 ·* At e = 2048 bits, k=7 (318.453125) is best
7c9016 ·* At e = 4096 bits, k=7 (574.453125) is best
4c775e ·*
8071f5 ·* This has the rollover points at 6, 24, 81, 241, 673 and 1793 instead
0471d9 ·* of 8, 26, 82, 242, 674, and 1794. ·Not a very big difference.
17480f ·* (The numbers past that are k=8 at 4609 and k=9 at 11521,
08e3af ·* vs. one more in each case for the approximation.)
e4775e ·*
f2cd4d ·* Given that exponents for which k>7 are useful are uncommon,
c0986b ·* a fixed size table for k <= 7 is used for simplicity.
c3775e ·*
e63a91 ·* The basic number of squarings needed is e-1, although a k-bit
778550 ·* window (for k > 1) can save, on average, k-2 of those, too.
22a714 ·* That savings currently isn't counted here. ·It would drive the
94b9c9 ·* crossover points slightly lower.
a42fb9 ·* (Actually, this win is also reduced in the DoubleExpMod case,
1d73fc ·* meaning we'd have to split the tables. ·Except for that, the
b12115 ·* multiplies by powers of the two bases are independent, so
d57584 ·* the same logic applies to each as the single case.)
9d775e ·*
5bda92 ·* Table entry i is the largest number of bits in an exponent to
073c5d ·* process with a window size of i+1. ·Entry 6 is the largest
b13c90 ·* possible unsigned number, so the window will never be more
ac9487 ·* than 7 bits, requiring 2^6 = 0x40 slots.
2d495d ·*/
5c6cca #define BNEXPMOD_MAX_WINDOW¤7
f54fb9 static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = {
3d193c ¤   5, 23, 80, 240, 672, 1792, (unsigned)-1
c06504 /*¤ 7, 25, 81, 241, 673, 1793, (unsigned)-1¤ ### The old approximations */
1a82f7 };
02af5a
8938e5 /*
a51b1f ·* Perform modular exponentiation, as fast as possible! ·This uses
913ed2 ·* Montgomery reduction, optimized squaring, and windowed exponentiation.
c9aef1 ·* The modulus "mod" MUST be odd!
42775e ·*
c9669b ·* This returns 0 on success, -1 on out of memory.
18775e ·*
49a91b ·* The window algorithm:
0e34dc ·* The idea is to keep a running product of b1 = n^(high-order bits of exp),
514327 ·* and then keep appending exponent bits to it. ·The following patterns
cc1e2d ·* apply to a 3-bit window (k = 3):
8e57f4 ·* To append ··0: square
df17eb ·* To append ··1: square, multiply by n^1
591993 ·* To append ·10: square, multiply by n^1, square
f660d5 ·* To append ·11: square, square, multiply by n^3
8cb4bd ·* To append 100: square, multiply by n^1, square, square
1be469 ·* To append 101: square, square, square, multiply by n^5
10730b ·* To append 110: square, square, multiply by n^3, square
a6579e ·* To append 111: square, square, square, multiply by n^7
2f775e ·*
c49b90 ·* Since each pattern involves only one multiply, the longer the pattern
5c325f ·* the better, except that a 0 (no multiplies) can be appended directly.
b2f945 ·* We precompute a table of odd powers of n, up to 2^k, and can then
ede7a3 ·* multiply k bits of exponent at a time. ·Actually, assuming random
--c7d7 0005b615cce40100150 Page 32 of bni16.c
c5ab25 ·* exponents, there is on average one zero bit between needs to
9ec44d ·* multiply (1/2 of the time there's none, 1/4 of the time there's 1,
243076 ·* 1/8 of the time, there's 2, 1/16 of the time, there's 3, etc.), so
f85e90 ·* you have to do one multiply per k+1 bits of exponent.
90775e ·*
f26a37 ·* The loop walks down the exponent, squaring the result buffer as
c5bb92 ·* it goes. ·There is a wbits+1 bit lookahead buffer, buf, that is
b56a38 ·* filled with the upcoming exponent bits. ·(What is read after the
4aa4bc ·* end of the exponent is unimportant, but it is filled with zero here.)
c58f68 ·* When the most-significant bit of this buffer becomes set, i.e.
5f089f ·* (buf & tblmask) != 0, we have to decide what pattern to multiply
dc5ee7 ·* by, and when to do it. ·We decide, remember to do it in future
5d1e5d ·* after a suitable number of squarings have passed (e.g. a pattern
137b40 ·* of "100" in the buffer requires that we multiply by n^1 immediately;
7f7f6e ·* a pattern of "110" calls for multiplying by n^3 after one more
6e221f ·* squaring), clear the buffer, and continue.
71775e ·*
d7fbc2 ·* When we start, there is one more optimization: the result buffer
854fad ·* is implcitly one, so squaring it or multiplying by it can be
738e8b ·* optimized away. ·Further, if we start with a pattern like "100"
d2d51f ·* in the lookahead window, rather than placing n into the buffer
cfda03 ·* and then starting to square it, we have already computed n^2
4d58ee ·* to compute the odd-powers table, so we can place that into
7432c1 ·* the buffer and save a squaring.
72775e ·*
a2eb27 ·* This means that if you have a k-bit window, to compute n^z,
3fde80 ·* where z is the high k bits of the exponent, 1/2 of the time
1d4c51 ·* it requires no squarings. ·1/4 of the time, it requires 1
00b370 ·* squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
bda8af ·* And the remaining 1/2^(k-1) of the time, the top k bits are a
378321 ·* 1 followed by k-1 0 bits, so it again only requires k-2
0d3eec ·* squarings, not k-1. ·The average of these is 1. ·Add that
2f5ba0 ·* to the one squaring we have to do to compute the table,
e54f92 ·* and you'll see that a k-bit window saves k-2 squarings
5f8b94 ·* as well as reducing the multiplies. ·(It actually doesn't
4585e2 ·* hurt in the case k = 1, either.)
45775e ·*
eaa837 ·* n must have mlen words allocated. ·Although fewer may be in use
c3d9fa ·* when n is passed in, all are in use on exit.
c5495d ·*/
834d2f int
6ac8e9 bniExpMod_16(
546740 ¤   PGPMemoryMgrRef¤mgr,
bdfe55 ¤   PGPBoolean¤ ¤   secure,
579e1c ¤   BNWORD16 *result, BNWORD16 const *n, unsigned nlen,
e7b0a6 ¤   BNWORD16 const *e, unsigned elen, BNWORD16 *mod, unsigned mlen)
a7bb36 {
a80ce1 ¤   BNWORD16 *table[1 << (BNEXPMOD_MAX_WINDOW-1)];
a0ab6c ¤   ¤   ¤   ¤   /* Table of odd powers of n */
c6bbb1 ¤   unsigned ebits;¤¤   /* Exponent bits */
5b8abd ¤   unsigned wbits;¤¤   /* Window size */
ea4710 ¤   unsigned tblmask;¤  /* Mask of exponentiation window */
577ca8 ¤   BNWORD16 bitpos;¤   /* Mask of current look-ahead bit */
e2a550 ¤   unsigned buf;¤  ¤   /* Buffer of exponent bits */
94a4db ¤   unsigned multpos;¤  /* Where to do pending multiply */
75b648 ¤   BNWORD16 const *mult;¤  /* What to multiply by */
617dbe ¤   unsigned i;¤¤   /* Loop counter */
392054 ¤   int isone;¤ ¤   /* Flag: accum. is implicitly one */
ad5f15 ¤   BNWORD16 *a, *b;¤   /* Working buffers/accumulators */
a8e59d ¤   BNWORD16 *t;¤   ¤   /* Pointer into the working buffers */
8db042 ¤   BNWORD16 inv;¤  ¤   /* mod^-1 modulo 2^16 */
79de2a ¤   int y;¤ ¤   ¤   /* bnYield() result */
6daf5a
15c613 ¤   pgpAssert(mlen);
9384ca ¤   pgpAssert(nlen <= mlen);
30af5a
697d28 ¤   /* First, a couple of trivial cases. */
969d7d ¤   elen = bniNorm_16(e, elen);
ae6115 ¤   if (!elen) {
3b18ff ¤   ¤   /* x ^ 0 == 1 */
734bd3 ¤   ¤   bniZero_16(result, mlen);
5b0eac ¤   ¤   BIGLITTLE(result[-1],result[0]) = 1;
--0a86 000060ba13940100150 Page 33 of bni16.c
79bbde ¤   ¤   return 0;
a69371 ¤   }
1e957b ¤   ebits = bniBits_16(e, elen);
30cd76 ¤   if (ebits == 1) {
b1a49e ¤   ¤   /* x ^ 1 == x */
ee295d ¤   ¤   if (n != result)
1a6362 ¤   ¤   ¤   bniCopy_16(result, n, nlen);
f6efb1 ¤   ¤   if (mlen > nlen)
e26989 ¤   ¤   ¤   bniZero_16(BIGLITTLE(result-nlen,result+nlen),
9cab83 ¤   ¤   ¤   ···········mlen-nlen);
83bbde ¤   ¤   return 0;
e19371 ¤   }
1daf5a
af0565 ¤   /* Okay, now move the exponent pointer to the most-significant word */
f5eb85 ¤   e = BIGLITTLE(e-elen, e+elen-1);
99af5a
465f70 ¤   /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
a2e796 ¤   wbits = 0;
c23dd6 ¤   while (ebits > bnExpModThreshTable[wbits])
b6ca4f ¤   ¤   wbits++;
7baf5a
40b29c ¤   /* Allocate working storage: two product buffers and the tables. */
12fc9a ¤   BNIALLOC(mgr, secure, a, BNWORD16, 2*mlen);
7e9293 ¤   if (!a)
08043c ¤   ¤   return -1;
000f6c ¤   BNIALLOC(mgr, secure, b, BNWORD16, 2*mlen);
ed5215 ¤   if (!b) {
49dda3 ¤   ¤   BNIFREE(a, 2*mlen);
17043c ¤   ¤   return -1;
f59371 ¤   }
15af5a
abeb94 ¤   /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
027b5d ¤   tblmask = 1u << wbits;
44af5a
f4a19d ¤   /* We have the result buffer available, so use it. */
96b9d5 ¤   table[0] = result;
2daf5a
eed8af ¤   /*
eda077 ¤   ·* Okay, we now have a minimal-sized table - expand it.
d2951f ¤   ·* This is allowed to fail! ·If so, scale back the table size
7ee64a ¤   ·* and proceed.
cda4e3 ¤   ·*/
ea623b ¤   for (i = 1; i < tblmask; i++) {
fa5a7f ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD16, mlen);
93f4e7 ¤   ¤   if (!t)¤/* Out of memory! ·Quit the loop. */
3ccdcb ¤   ¤   ¤   break;
a55264 ¤   ¤   table[i] = t;
ba9371 ¤   }
82af5a
79e399 ¤   /* If we stopped, with i < tblmask, shrink the tables appropriately */
ba0729 ¤   while (tblmask > i) {
4e570c ¤   ¤   wbits--;
7f020b ¤   ¤   tblmask >>= 1;
0c9371 ¤   }
6490d4 ¤   /* Free up our overallocations */
f58b01 ¤   while (--i > tblmask)
1b06fb ¤   ¤   BNIFREE(table[i], mlen);
4caf5a
32523f ¤   /* Okay, fill in the table */
24af5a
1d6326 ¤   /* Compute the necessary modular inverse */
e67b32 ¤   inv = bniMontInv1_16(mod[BIGLITTLE(-1,0)]);¤/* LSW of modulus */
39af5a
04d2c8 ¤   /* Convert n to Montgomery form */
2aaf5a
0845b9 ¤   /* Move n up "mlen" words into a */
c4c360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
78d898 ¤   bniCopy_16(t, n, nlen);
41225c ¤   bniZero_16(a, mlen);
1fa0ad ¤   /* Do the division - lose the quotient into the high-order words */
9c5078 ¤   (void)bniDiv_16(t, a, mlen+nlen, mod, mlen);
06aa1a ¤   /* Copy into first table entry */
--52e8 0005a3b277240100150 Page 34 of bni16.c
b63998 ¤   bniCopy_16(table[0], a, mlen);
59af5a
afc9f6 ¤   /* Square a into b */
7e866b ¤   bniMontSquare_16(b, a, mod, mlen, inv);
98af5a
c70127 ¤   /* Use high half of b to initialize the table */
312576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
08623b ¤   for (i = 1; i < tblmask; i++) {
bd0ee4 ¤   ¤   bniMontMul_16(a, t, table[i-1], mod, mlen, inv);
66f0b2 ¤   ¤   bniCopy_16(table[i], BIGLITTLE(a-mlen, a+mlen), mlen);
db074b #if BNYIELD
969bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
7e74c2 ¤   ¤   ¤   goto yield;
5d7454 #endif
8f9371 ¤   }
a5af5a
dae133 ¤   /* We might use b = n^2 later... */
2faf5a
fcb3c9 ¤   /* Initialze the fetch pointer */
d1c740 ¤   bitpos = (BNWORD16)1 << ((ebits-1) & (16-1));¤  /* Initialize mask */
c2af5a
de41cc ¤   /* This should point to the msbit of e */
b1fda7 ¤   pgpAssert((*e & bitpos) != 0);
b2af5a
60d8af ¤   /*
72f61f ¤   ·* Pre-load the window. ·Becuase the window size is
189e1e ¤   ·* never larger than the exponent size, there is no need to
6754af ¤   ·* detect running off the end of e in here.
d59714 ¤   ·*
048d24 ¤   ·* The read-ahead is controlled by elen and the bitpos mask.
d6c658 ¤   ·* Note that this is *ahead* of ebits, which tracks the
4fe8fd ¤   ·* most significant end of the window. ·The purpose of this
47cbf3 ¤   ·* initialization is to get the two wbits+1 bits apart,
1cd4d6 ¤   ·* like they should be.
0e9714 ¤   ·*
9c9955 ¤   ·* Note that bitpos and e1len together keep track of the
327e30 ¤   ·* lookahead read pointer in the exponent that is used here.
c6a4e3 ¤   ·*/
51b0a1 ¤   buf = 0;
b35760 ¤   for (i = 0; i <= wbits; i++) {
866d2d ¤   ¤   buf = (buf << 1) | ((*e & bitpos) != 0);
971e4d ¤   ¤   bitpos >>= 1;
3ea81f ¤   ¤   if (!bitpos) {
340024 ¤   ¤   ¤   BIGLITTLE(e++,e--);
8ef1cd ¤   ¤   ¤   bitpos = (BNWORD16)1 << (16-1);
beb349 ¤   ¤   ¤   elen--;
0d0fe4 ¤   ¤   }
749371 ¤   }
fc5e84 ¤   pgpAssert(buf & tblmask);
15af5a
a5d8af ¤   /*
f0e4af ¤   ·* Set the pending multiply positions to a location that will
043edd ¤   ·* never be encountered, thus ensuring that nothing will happen
6d5986 ¤   ·* until the need for a multiply appears and one is scheduled.
94a4e3 ¤   ·*/
09bd01 ¤   multpos = ebits;¤   /* A NULL value */
00077f ¤   mult = 0;¤  /* Force a crash if we use these */
53af5a
11d8af ¤   /*
d011db ¤   ·* Okay, now begins the real work. ·The first step is
90c478 ¤   ·* slightly magic, so it's done outside the main loop,
0a3e1f ¤   ·* but it's very similar to what's inside.
7fa4e3 ¤   ·*/
dd806b ¤   ebits--;¤   /* Start processing the first bit... */
6a4f17 ¤   isone = 1;
82af5a
5ed8af ¤   /*
a29907 ¤   ·* This is just like the multiply in the loop, except that
5e1487 ¤   ·* - We know the msbit of buf is set, and
c856cd ¤   ·* - We have the extra value n^2 floating around.
3f63fa ¤   ·* So, do the usual computation, and if the result is that
5a6045 ¤   ·* the buffer should be multiplied by n^1 immediately
--572e 0002470bcfb40100150 Page 35 of bni16.c
83cce3 ¤   ·* (which we'd normally then square), we multiply it
289fa4 ¤   ·* (which reduces to a copy, which reduces to setting a flag)
a0c34f ¤   ·* by n^2 and skip the squaring. ·Thus, we do the
475501 ¤   ·* multiply and the squaring in one step.
83a4e3 ¤   ·*/
2b5e84 ¤   pgpAssert(buf & tblmask);
634e35 ¤   multpos = ebits - wbits;
308da4 ¤   while ((buf & 1) == 0) {
031feb ¤   ¤   buf >>= 1;
c45ccd ¤   ¤   multpos++;
ab9371 ¤   }
e1f0a6 ¤   /* Intermediates can wrap, but final must NOT */
3d28d7 ¤   pgpAssert(multpos <= ebits);
0e43c6 ¤   mult = table[buf>>1];
23b0a1 ¤   buf = 0;
33af5a
3fb24e ¤   /* Special case: use already-computed value sitting in buffer */
26b774 ¤   if (multpos == ebits)
2bf768 ¤   ¤   isone = 0;
e4af5a
85d8af ¤   /*
2bfe43 ¤   ·* At this point, the buffer (which is the high half of b) holds
3d61cd ¤   ·* either 1 (implicitly, as the "isone" flag is set), or n^2.
a6a4e3 ¤   ·*/
83af5a
19d8af ¤   /*
ea9409 ¤   ·* The main loop. ·The procedure is:
f0ab45 ¤   ·* - Advance the window
e3448c ¤   ·* - If the most-significant bit of the window is set,
9c0c66 ¤   ·* ··schedule a multiply for the appropriate time in the
56375c ¤   ·* ··future (may be immediately)
9e383a ¤   ·* - Perform any pending multiples
a06d15 ¤   ·* - Check for termination
43446f ¤   ·* - Square the buffer
da9714 ¤   ·*
247202 ¤   ·* At any given time, the acumulated product is held in
2d0d21 ¤   ·* the high half of b.
f9a4e3 ¤   ·*/
5f220e ¤   for (;;) {
653362 ¤   ¤   ebits--;
62af5a
711a36 ¤   ¤   /* Advance the window */
ea7403 ¤   ¤   pgpAssert(buf < tblmask);
5b2006 ¤   ¤   buf <<= 1;
bc1b17 ¤   ¤   /*
eee0cb ¤   ¤   ·* This reads ahead of the current exponent position
cc43d1 ¤   ¤   ·* (controlled by ebits), so we have to be able to read
54969f ¤   ¤   ·* past the lsb of the exponents without error.
a99de3 ¤   ¤   ·*/
524c6b ¤   ¤   if (elen) {
2a81dc ¤   ¤   ¤   buf |= ((*e & bitpos) != 0);
fbd9f8 ¤   ¤   ¤   bitpos >>= 1;
0d4afe ¤   ¤   ¤   if (!bitpos) {
ea8bd8 ¤   ¤   ¤   ¤   BIGLITTLE(e++,e--);
70e99d ¤   ¤   ¤   ¤   bitpos = (BNWORD16)1 << (16-1);
1fc9bd ¤   ¤   ¤   ¤   elen--;
8ca3a6 ¤   ¤   ¤   }
a00fe4 ¤   ¤   }
8eaf5a
d7be07 ¤   ¤   /* Examine the window for pending multiplies */
1acc0d ¤   ¤   if (buf & tblmask) {
f9c80b ¤   ¤   ¤   multpos = ebits - wbits;
b50b9a ¤   ¤   ¤   while ((buf & 1) == 0) {
b4c6e3 ¤   ¤   ¤   ¤   buf >>= 1;
8485c5 ¤   ¤   ¤   ¤   multpos++;
a6a3a6 ¤   ¤   ¤   }
08b920 ¤   ¤   ¤   /* Intermediates can wrap, but final must NOT */
421052 ¤   ¤   ¤   pgpAssert(multpos <= ebits);
a5fd9a ¤   ¤   ¤   mult = table[buf>>1];
5a44bb ¤   ¤   ¤   buf = 0;
c40fe4 ¤   ¤   }
24af5a
--7ea9 0004c05f7f640100150 Page 36 of bni16.c
0357bb ¤   ¤   /* If we have a pending multiply, do it */
d2d05a ¤   ¤   if (ebits == multpos) {
41a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
296ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
578c88 ¤   ¤   ¤   if (isone) {
f26b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
d325d5 ¤   ¤   ¤   ¤   bniCopy_16(t, mult, mlen);
bd2e60 ¤   ¤   ¤   ¤   isone = 0;
fc042d ¤   ¤   ¤   } else {
2acde0 ¤   ¤   ¤   ¤   bniMontMul_16(a, t, mult, mod, mlen, inv);
636783 ¤   ¤   ¤   ¤   /* Swap a and b */
ff51ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
46a3a6 ¤   ¤   ¤   }
b90fe4 ¤   ¤   }
bfaf5a
727b03 ¤   ¤   /* Are we done? */
068029 ¤   ¤   if (!ebits)
fccdcb ¤   ¤   ¤   break;
aaaf5a
88b085 ¤   ¤   /* Square the input */
4b9d17 ¤   ¤   if (!isone) {
9b6ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
7bbdb0 ¤   ¤   ¤   bniMontSquare_16(a, t, mod, mlen, inv);
0cebfc ¤   ¤   ¤   /* Swap a and b */
516c84 ¤   ¤   ¤   t = a; a = b; b = t;
ee0fe4 ¤   ¤   }
93074b #if BNYIELD
ee9bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
3074c2 ¤   ¤   ¤   goto yield;
8c7454 #endif
efd6a0 ¤   } /* for (;;) */
21af5a
d35f64 ¤   pgpAssert(!isone);
4dd8b5 ¤   pgpAssert(!buf);
e7af5a
7f2111 ¤   /* DONE! */
c0af5a
028619 ¤   /* Convert result out of Montgomery form */
7d2576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
eed4fd ¤   bniCopy_16(b, t, mlen);
0d6cb5 ¤   bniZero_16(t, mlen);
de2cdf ¤   bniMontReduce_16(b, mod, mlen, inv);
4f10bc ¤   bniCopy_16(result, t, mlen);
5bd8af ¤   /*
4c8c1b ¤   ·* Clean up - free intermediate storage.
e249dc ¤   ·* Do NOT free table[0], which is the result
654228 ¤   ·* buffer.
78a4e3 ¤   ·*/
ce4aa5 ¤   y = 0;
a6074b #if BNYIELD
27f924 yield:
a77454 #endif
f4f0a6 ¤   while (--tblmask)
56d094 ¤   ¤   BNIFREE(table[tblmask], mlen);
18ac28 ¤   BNIFREE(b, 2*mlen);
432bc6 ¤   BNIFREE(a, 2*mlen);
92af5a
a3f88b ¤   return y;¤  /* Success */
ceefe6 }
b0af5a
a438e5 /*
495706 ·* Compute and return n1^e1 * n2^e2 mod "mod".
f6c894 ·* result may be either input buffer, or something separate.
f48848 ·* It must be "mlen" words long.
bb775e ·*
629ebb ·* There is a current position in the exponents, which is kept in e1bits.
c510c7 ·* (The exponents are swapped if necessary so e1 is the longer of the two.)
71916c ·* At any given time, the value in the accumulator is
2cda55 ·* n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod".
45a31f ·* As e1bits is counted down, this is updated, by squaring it and doing
5eb1ee ·* any necessary multiplies.
4c093b ·* To decide on the necessary multiplies, two windows, each w1bits+1 bits
--0826 0008662f42d40100150 Page 37 of bni16.c
da411e ·* wide, are maintained in buf1 and buf2, which read *ahead* of the
fe3a68 ·* e1bits position (with appropriate handling of the case when e1bits
10074b ·* drops below w1bits+1). ·When the most-significant bit of either window
febb09 ·* becomes set, indicating that something needs to be multiplied by
7600a5 ·* the accumulator or it will get out of sync, the window is examined
f8ab86 ·* to see which power of n1 or n2 to multiply by, and when (possibly
ab89e9 ·* later, if the power is greater than 1) the multiply should take
426e2e ·* place. ·Then the multiply and its location are remembered and the
18b3de ·* window is cleared.
98775e ·*
4d5ec4 ·* If we had every power of n1 in the table, the multiply would always
26f328 ·* be w1bits steps in the future. ·But we only keep the odd powers,
9552f8 ·* so instead of waiting w1bits squarings and then multiplying
e72d0c ·* by n1^k, we wait w1bits-k squarings and multiply by n1.
68775e ·*
cd6296 ·* Actually, w2bits can be less than w1bits, but the window is the same
f913ee ·* size, to make it easier to keep track of where we're reading. ·The
d80c46 ·* appropriate number of low-order bits of the window are just ignored.
6d495d ·*/
e44d2f int
7c8e0f bniDoubleExpMod_16(
c76740 ¤   PGPMemoryMgrRef¤mgr,
d1fe55 ¤   PGPBoolean¤ ¤   secure,
c9e7a1 ¤   BNWORD16 *result,
63cf3a ···BNWORD16 const *n1, unsigned n1len,
341a85 ···BNWORD16 const *e1, unsigned e1len,
d57e8d ···BNWORD16 const *n2, unsigned n2len,
f6ab32 ···BNWORD16 const *e2, unsigned e2len,
7c19b0 ···BNWORD16 *mod, unsigned mlen)
3cbb36 {
cfb1e3 ¤   BNWORD16 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)];
a29746 ¤   ¤   ¤   ¤   ¤   /* Table of odd powers of n1 */
9e7146 ¤   BNWORD16 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)];
6b8a8a ¤   ¤   ¤   ¤   ¤   /* Table of odd powers of n2 */
b8aaa4 ¤   unsigned e1bits, e2bits;¤   /* Exponent bits */
7e2c22 ¤   unsigned w1bits, w2bits;¤   /* Window sizes */
75de31 ¤   unsigned tblmask;¤  ¤   /* Mask of exponentiation window */
fb2094 ¤   BNWORD16 bitpos;¤   ¤   /* Mask of current look-ahead bit */
78f0f4 ¤   unsigned buf1, buf2;¤   ¤   /* Buffer of exponent bits */
9ab874 ¤   unsigned mult1pos, mult2pos;¤   /* Where to do pending multiply */
1c2372 ¤   BNWORD16 const *mult1, *mult2;¤ /* What to multiply by */
9ae525 ¤   unsigned i;¤¤   ¤   /* Loop counter */
af395c ¤   int isone;¤ ¤   ¤   /* Flag: accum. is implicitly one */
ae0508 ¤   BNWORD16 *a, *b;¤   ¤   /* Working buffers/accumulators */
3d7ee4 ¤   BNWORD16 *t;¤   ¤   ¤   /* Pointer into the working buffers */
7b0482 ¤   BNWORD16 inv;¤  ¤   ¤   /* mod^-1 modulo 2^16 */
fc916f ¤   int y;¤ ¤   ¤   ¤   /* bnYield() result */
0daf5a
f8c613 ¤   pgpAssert(mlen);
e69714 ¤   pgpAssert(n1len <= mlen);
ce4f6a ¤   pgpAssert(n2len <= mlen);
57af5a
2d7d28 ¤   /* First, a couple of trivial cases. */
081a9b ¤   e1len = bniNorm_16(e1, e1len);
7a2d53 ¤   e2len = bniNorm_16(e2, e2len);
65af5a
b1c726 ¤   /* Ensure that the first exponent is the longer */
d700d9 ¤   e1bits = bniBits_16(e1, e1len);
f81149 ¤   e2bits = bniBits_16(e2, e2len);
daf8c6 ¤   if (e1bits < e2bits) {
71bd4e ¤   ¤   i = e1len; e1len = e2len; e2len = i;
ccd4ee ¤   ¤   i = e1bits; e1bits = e2bits; e2bits = i;
050be8 ¤   ¤   t = (BNWORD16 *)n1; n1 = n2; n2 = t;·
51ee86 ¤   ¤   t = (BNWORD16 *)e1; e1 = e2; e2 = t;·
809371 ¤   }
a29589 ¤   pgpAssert(e1bits >= e2bits);
b5af5a
7556ce ¤   /* Handle a trivial case */
fad49f ¤   if (!e2len)
b51204 ¤   ¤   return bniExpMod_16( mgr, secure, result, n1, n1len, e1, e1len,
108576 ¤   ¤   ¤   ¤   ¤   ¤   ¤   mod, mlen);
865d32 ¤   pgpAssert(e2bits);
--5e23 00023a0b94140100150 Page 38 of bni16.c
e0af5a
fcfc05 ¤   /* The code below fucks up if the exponents aren't at least 2 bits */
f13f8f ¤   if (e1bits == 1) {
744cfc ¤   ¤   pgpAssert(e2bits == 1);
49af5a
091d50 ¤   ¤   BNIALLOC(mgr, secure, a, BNWORD16, n1len+n2len);
a08823 ¤   ¤   if (!a)
8e3fd5 ¤   ¤   ¤   return -1;
ffaf5a
674c33 ¤   ¤   bniMul_16(a, n1, n1len, n2, n2len);
0046cf ¤   ¤   /* Do a direct modular reduction */
09016d ¤   ¤   if (n1len + n2len >= mlen)
6da376 ¤   ¤   ¤   (void)bniDiv_16(a+mlen, a, n1len+n2len, mod, mlen);
eb633d ¤   ¤   bniCopy_16(result, a, mlen);
18643e ¤   ¤   BNIFREE(a, n1len+n2len);
94bbde ¤   ¤   return 0;
be9371 ¤   }
3caf5a
f2aa9d ¤   /* Okay, now move the exponent pointers to the most-significant word */
b210a1 ¤   e1 = BIGLITTLE(e1-e1len, e1+e1len-1);
a6c984 ¤   e2 = BIGLITTLE(e2-e2len, e2+e2len-1);
caaf5a
965f70 ¤   /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
ec4f7e ¤   w1bits = 0;
51997d ¤   while (e1bits > bnExpModThreshTable[w1bits])
a4ff05 ¤   ¤   w1bits++;
d0b1cd ¤   w2bits = 0;
a9d55d ¤   while (e2bits > bnExpModThreshTable[w2bits])
6e2902 ¤   ¤   w2bits++;
78af5a
cca36d ¤   pgpAssert(w1bits >= w2bits);
64af5a
99b29c ¤   /* Allocate working storage: two product buffers and the tables. */
a6fc9a ¤   BNIALLOC(mgr, secure, a, BNWORD16, 2*mlen);
649293 ¤   if (!a)
48043c ¤   ¤   return -1;
0a0f6c ¤   BNIALLOC(mgr, secure, b, BNWORD16, 2*mlen);
275215 ¤   if (!b) {
e6dda3 ¤   ¤   BNIFREE(a, 2*mlen);
c7043c ¤   ¤   return -1;
b49371 ¤   }
40af5a
c8eb94 ¤   /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
ba211e ¤   tblmask = 1u << w1bits;
4ff1a9 ¤   /* Use buf2 for its size, temporarily */
43b274 ¤   buf2 = 1u << w2bits;
b1af5a
f61541 ¤   BNIALLOC(mgr, secure, t, BNWORD16, mlen);
bbddcd ¤   if (!t) {
9c5a4d ¤   ¤   BNIFREE(b, 2*mlen);
39dda3 ¤   ¤   BNIFREE(a, 2*mlen);
7b043c ¤   ¤   return -1;
809371 ¤   }
e24388 ¤   table1[0] = t;
dc11c2 ¤   table2[0] = result;
c5af5a
b0d8af ¤   /*
676773 ¤   ·* Okay, we now have some minimal-sized tables - expand them.
676065 ¤   ·* This is allowed to fail! ·If so, scale back the table sizes
325a99 ¤   ·* and proceed. ·We allocate both tables at the same time
b54729 ¤   ·* so if it fails partway through, they'll both be a reasonable
71e17e ¤   ·* size rather than one huge and one tiny.
859f45 ¤   ·* When i passes buf2 (the number of entries in the e2 window,
0b278f ¤   ·* which may be less than the number of entries in the e1 window),
282758 ¤   ·* stop allocating e2 space.
78a4e3 ¤   ·*/
dd623b ¤   for (i = 1; i < tblmask; i++) {
a05a7f ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD16, mlen);
bdf4e7 ¤   ¤   if (!t)¤/* Out of memory! ·Quit the loop. */
f9cdcb ¤   ¤   ¤   break;
71eaeb ¤   ¤   table1[i] = t;
235687 ¤   ¤   if (i < buf2) {
--7adb 000c29ed70940100150 Page 39 of bni16.c
8bf47e ¤   ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD16, mlen);
1062e2 ¤   ¤   ¤   if (!t) {
5b8b24 ¤   ¤   ¤   ¤   BNIFREE(table1[i], mlen);
33f622 ¤   ¤   ¤   ¤   break;
a9a3a6 ¤   ¤   ¤   }
8f7c63 ¤   ¤   ¤   table2[i] = t;
4f0fe4 ¤   ¤   }
449371 ¤   }
beaf5a
dde399 ¤   /* If we stopped, with i < tblmask, shrink the tables appropriately */
280729 ¤   while (tblmask > i) {
386246 ¤   ¤   w1bits--;
48020b ¤   ¤   tblmask >>= 1;
349371 ¤   }
3a90d4 ¤   /* Free up our overallocations */
3ee874 ¤   while (--i > tblmask) {
128a30 ¤   ¤   if (i < buf2)
05b93d ¤   ¤   ¤   BNIFREE(table2[i], mlen);
3958b9 ¤   ¤   BNIFREE(table1[i], mlen);
0f9371 ¤   }
f218ae ¤   /* And shrink the second window too, if needed */
57f5d4 ¤   if (w2bits > w1bits) {
1d0726 ¤   ¤   w2bits = w1bits;
62356a ¤   ¤   buf2 = tblmask;
fa9371 ¤   }
8caf5a
01d8af ¤   /*
d78b7f ¤   ·* From now on, use the w2bits variable for the difference
a5f9d1 ¤   ·* between w1bits and w2bits.
2da4e3 ¤   ·*/
f2c76a ¤   w2bits = w1bits-w2bits;
0caf5a
2bb64a ¤   /* Okay, fill in the tables */
8daf5a
966326 ¤   /* Compute the necessary modular inverse */
9f7b32 ¤   inv = bniMontInv1_16(mod[BIGLITTLE(-1,0)]);¤/* LSW of modulus */
15af5a
ec74f9 ¤   /* Convert n1 to Montgomery form */
9eaf5a
75e328 ¤   /* Move n1 up "mlen" words into a */
b8c360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
e5adac ¤   bniCopy_16(t, n1, n1len);
c9225c ¤   bniZero_16(a, mlen);
77a0ad ¤   /* Do the division - lose the quotient into the high-order words */
5e4cb4 ¤   (void)bniDiv_16(t, a, mlen+n1len, mod, mlen);
6eaa1a ¤   /* Copy into first table entry */
bdf330 ¤   bniCopy_16(table1[0], a, mlen);
b4af5a
6fc9f6 ¤   /* Square a into b */
03866b ¤   bniMontSquare_16(b, a, mod, mlen, inv);
2faf5a
928028 ¤   /* Use high half of b to initialize the first table */
f52576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
20623b ¤   for (i = 1; i < tblmask; i++) {
92ff0f ¤   ¤   bniMontMul_16(a, t, table1[i-1], mod, mlen, inv);
59c3e3 ¤   ¤   bniCopy_16(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen);
b4074b #if BNYIELD
139bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
8774c2 ¤   ¤   ¤   goto yield;
bc7454 #endif
5a9371 ¤   }
94af5a
109935 ¤   /* Convert n2 to Montgomery form */
8daf5a
ccc360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
0fb91b ¤   /* Move n2 up "mlen" words into a */
98fb71 ¤   bniCopy_16(t, n2, n2len);
ad225c ¤   bniZero_16(a, mlen);
13a0ad ¤   /* Do the division - lose the quotient into the high-order words */
6e4d8c ¤   (void)bniDiv_16(t, a, mlen+n2len, mod, mlen);
87aa1a ¤   /* Copy into first table entry */
c26911 ¤   bniCopy_16(table2[0], a, mlen);
--47a6 00063c3b1d540100150 Page 40 of bni16.c
e0af5a
98f67c ¤   /* Square it into a */
b4ff3f ¤   bniMontSquare_16(a, table2[0], mod, mlen, inv);
bb8e9d ¤   /* Copy to b, low half */
41d4fd ¤   bniCopy_16(b, t, mlen);
92af5a
77d1ec ¤   /* Use b to initialize the second table */
289f1b ¤   for (i = 1; i < buf2; i++) {
025cad ¤   ¤   bniMontMul_16(a, b, table2[i-1], mod, mlen, inv);
dfe69c ¤   ¤   bniCopy_16(table2[i], t, mlen);
a8074b #if BNYIELD
af9bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
2974c2 ¤   ¤   ¤   goto yield;
0f7454 #endif
ee9371 ¤   }
79af5a
8fd8af ¤   /*
f9a7c8 ¤   ·* Okay, a recap: at this point, the low part of b holds
3a4f8a ¤   ·* n2^2, the high part holds n1^2, and the tables are
45b069 ¤   ·* initialized with the odd powers of n1 and n2 from 1
af4e6c ¤   ·* through 2*tblmask-1 and 2*buf2-1.
079714 ¤   ·*
8deaa9 ¤   ·* We might use those squares in b later, or we might not.
1da4e3 ¤   ·*/
42af5a
7cb3c9 ¤   /* Initialze the fetch pointer */
b6e0e0 ¤   bitpos = (BNWORD16)1 << ((e1bits-1) & (16-1));¤ /* Initialize mask */
c7af5a
88a4e7 ¤   /* This should point to the msbit of e1 */
063755 ¤   pgpAssert((*e1 & bitpos) != 0);
d5af5a
54d8af ¤   /*
5292f4 ¤   ·* Pre-load the windows. ·Becuase the window size is
519e1e ¤   ·* never larger than the exponent size, there is no need to
8929e6 ¤   ·* detect running off the end of e1 in here.
d19714 ¤   ·*
6a6575 ¤   ·* The read-ahead is controlled by e1len and the bitpos mask.
47b24e ¤   ·* Note that this is *ahead* of e1bits, which tracks the
8de8fd ¤   ·* most significant end of the window. ·The purpose of this
0459ed ¤   ·* initialization is to get the two w1bits+1 bits apart,
6ad4d6 ¤   ·* like they should be.
959714 ¤   ·*
a49955 ¤   ·* Note that bitpos and e1len together keep track of the
837e30 ¤   ·* lookahead read pointer in the exponent that is used here.
2e0acb ¤   ·* e2len is not decremented, it is only ever compared with
479c64 ¤   ·* e1len as *that* is decremented.
eda4e3 ¤   ·*/
6ac6dc ¤   buf1 = buf2 = 0;
983d15 ¤   for (i = 0; i <= w1bits; i++) {
c9c5f3 ¤   ¤   buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0);
f15b2e ¤   ¤   if (e1len <= e2len)
9b4658 ¤   ¤   ¤   buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0);
871e4d ¤   ¤   bitpos >>= 1;
64a81f ¤   ¤   if (!bitpos) {
ecdc04 ¤   ¤   ¤   BIGLITTLE(e1++,e1--);
b1f670 ¤   ¤   ¤   if (e1len <= e2len)
37c1b9 ¤   ¤   ¤   ¤   BIGLITTLE(e2++,e2--);
5ef1cd ¤   ¤   ¤   bitpos = (BNWORD16)1 << (16-1);
28b8bc ¤   ¤   ¤   e1len--;
430fe4 ¤   ¤   }
839371 ¤   }
60f843 ¤   pgpAssert(buf1 & tblmask);
26af5a
3ed8af ¤   /*
03e4af ¤   ·* Set the pending multiply positions to a location that will
033edd ¤   ·* never be encountered, thus ensuring that nothing will happen
905986 ¤   ·* until the need for a multiply appears and one is scheduled.
92a4e3 ¤   ·*/
179c90 ¤   mult1pos = mult2pos = e1bits;¤  /* A NULL value */
890cc3 ¤   mult1 = mult2 = 0;¤ /* Force a crash if we use these */
31af5a
63d8af ¤   /*
--afd7 0001e43c75240100150 Page 41 of bni16.c
5211db ¤   ·* Okay, now begins the real work. ·The first step is
ecc478 ¤   ·* slightly magic, so it's done outside the main loop,
bd3e1f ¤   ·* but it's very similar to what's inside.
67a4e3 ¤   ·*/
08f44f ¤   isone = 1;¤ /* Buffer is implicitly 1, so replace * by copy */
8ca246 ¤   e1bits--;¤  /* Start processing the first bit... */
c8af5a
58d8af ¤   /*
e09907 ¤   ·* This is just like the multiply in the loop, except that
cbfc57 ¤   ·* - We know the msbit of buf1 is set, and
2a05dd ¤   ·* - We have the extra value n1^2 floating around.
4663fa ¤   ·* So, do the usual computation, and if the result is that
fd2227 ¤   ·* the buffer should be multiplied by n1^1 immediately
81cce3 ¤   ·* (which we'd normally then square), we multiply it
d69fa4 ¤   ·* (which reduces to a copy, which reduces to setting a flag)
48b99d ¤   ·* by n1^2 and skip the squaring. ·Thus, we do the
4e5501 ¤   ·* multiply and the squaring in one step.
40a4e3 ¤   ·*/
46f843 ¤   pgpAssert(buf1 & tblmask);
fe8464 ¤   mult1pos = e1bits - w1bits;
8bd9b6 ¤   while ((buf1 & 1) == 0) {
46e8d7 ¤   ¤   buf1 >>= 1;
fa8c75 ¤   ¤   mult1pos++;
519371 ¤   }
60f0a6 ¤   /* Intermediates can wrap, but final must NOT */
837afd ¤   pgpAssert(mult1pos <= e1bits);
988447 ¤   mult1 = table1[buf1>>1];
64cb53 ¤   buf1 = 0;
12af5a
adb24e ¤   /* Special case: use already-computed value sitting in buffer */
1317a5 ¤   if (mult1pos == e1bits)
f5f768 ¤   ¤   isone = 0;
5aaf5a
9ad8af ¤   /*
d273de ¤   ·* The first multiply by a power of n2. ·Similar, but
26d0bc ¤   ·* we might not even want to schedule a multiply if e2 is
58719d ¤   ·* shorter than e1, and the window might be shorter so
c0207e ¤   ·* we have to leave the low w2bits bits alone.
aea4e3 ¤   ·*/
f46486 ¤   if (buf2 & tblmask) {
c58236 ¤   ¤   /* Remember low-order bits for later */
2ca24c ¤   ¤   i = buf2 & ((1u << w2bits) - 1);
d4c885 ¤   ¤   buf2 >>= w2bits;
8d419a ¤   ¤   mult2pos = e1bits - w1bits + w2bits;
7a36c0 ¤   ¤   while ((buf2 & 1) == 0) {
454424 ¤   ¤   ¤   buf2 >>= 1;
ab7c51 ¤   ¤   ¤   mult2pos++;
740fe4 ¤   ¤   }
590b1f ¤   ¤   pgpAssert(mult2pos <= e1bits);
1f4925 ¤   ¤   mult2 = table2[buf2>>1];
4cf975 ¤   ¤   buf2 = i;
b8af5a
50483e ¤   ¤   if (mult2pos == e1bits) {
f16ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
b38c88 ¤   ¤   ¤   if (isone) {
ff6b4b ¤   ¤   ¤   ¤   bniCopy_16(t, b, mlen);¤/* Copy low to high */
1c2e60 ¤   ¤   ¤   ¤   isone = 0;
6e042d ¤   ¤   ¤   } else {
b79007 ¤   ¤   ¤   ¤   bniMontMul_16(a, t, b, mod, mlen, inv);
9c51ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
81a3a6 ¤   ¤   ¤   }
680fe4 ¤   ¤   }
d79371 ¤   }
43af5a
f6d8af ¤   /*
ec80e3 ¤   ·* At this point, the buffer (which is the high half of b)
e81e26 ¤   ·* holds either 1 (implicitly, as the "isone" flag is set),
348889 ¤   ·* n1^2, n2^2 or n1^2 * n2^2.
bba4e3 ¤   ·*/
7daf5a
6bd8af ¤   /*
1e9409 ¤   ·* The main loop. ·The procedure is:
--96c0 000db3102ba40100150 Page 42 of bni16.c
a09d84 ¤   ·* - Advance the windows
5fa32c ¤   ·* - If the most-significant bit of a window is set,
380c66 ¤   ·* ··schedule a multiply for the appropriate time in the
ca375c ¤   ·* ··future (may be immediately)
4a383a ¤   ·* - Perform any pending multiples
e36d15 ¤   ·* - Check for termination
a91333 ¤   ·* - Square the buffers
b19714 ¤   ·*
6f7202 ¤   ·* At any given time, the acumulated product is held in
df0d21 ¤   ·* the high half of b.
13a4e3 ¤   ·*/
01220e ¤   for (;;) {
65e85a ¤   ¤   e1bits--;
edaf5a
9f2bc3 ¤   ¤   /* Advance the windows */
e269b3 ¤   ¤   pgpAssert(buf1 < tblmask);
d6d73a ¤   ¤   buf1 <<= 1;
31ea8d ¤   ¤   pgpAssert(buf2 < tblmask);
8c013d ¤   ¤   buf2 <<= 1;
2d1b17 ¤   ¤   /*
72e0cb ¤   ¤   ·* This reads ahead of the current exponent position
92ead0 ¤   ¤   ·* (controlled by e1bits), so we have to be able to read
6b969f ¤   ¤   ·* past the lsb of the exponents without error.
8e9de3 ¤   ¤   ·*/
e7d14f ¤   ¤   if (e1len) {
030cd9 ¤   ¤   ¤   buf1 |= ((*e1 & bitpos) != 0);
f0f670 ¤   ¤   ¤   if (e1len <= e2len)
647ab8 ¤   ¤   ¤   ¤   buf2 |= ((*e2 & bitpos) != 0);
23d9f8 ¤   ¤   ¤   bitpos >>= 1;
4b4afe ¤   ¤   ¤   if (!bitpos) {
d03377 ¤   ¤   ¤   ¤   BIGLITTLE(e1++,e1--);
ff7d8c ¤   ¤   ¤   ¤   if (e1len <= e2len)
effd57 ¤   ¤   ¤   ¤   ¤   BIGLITTLE(e2++,e2--);
60e99d ¤   ¤   ¤   ¤   bitpos = (BNWORD16)1 << (16-1);
cd096d ¤   ¤   ¤   ¤   e1len--;
2da3a6 ¤   ¤   ¤   }
ad0fe4 ¤   ¤   }
1faf5a
3a56b0 ¤   ¤   /* Examine the first window for pending multiplies */
c535ac ¤   ¤   if (buf1 & tblmask) {
2acacd ¤   ¤   ¤   mult1pos = e1bits - w1bits;
bf01cd ¤   ¤   ¤   while ((buf1 & 1) == 0) {
276446 ¤   ¤   ¤   ¤   buf1 >>= 1;
c500e4 ¤   ¤   ¤   ¤   mult1pos++;
89a3a6 ¤   ¤   ¤   }
0eb920 ¤   ¤   ¤   /* Intermediates can wrap, but final must NOT */
6e3542 ¤   ¤   ¤   pgpAssert(mult1pos <= e1bits);
760279 ¤   ¤   ¤   mult1 = table1[buf1>>1];
95747c ¤   ¤   ¤   buf1 = 0;
710fe4 ¤   ¤   }
f0af5a
401b17 ¤   ¤   /*
f77036 ¤   ¤   ·* Examine the second window for pending multiplies.
42f9d2 ¤   ¤   ·* Window 2 can be smaller than window 1, but we
ba3db6 ¤   ¤   ·* keep the same number of bits in buf2, so we need
2c6701 ¤   ¤   ·* to ignore any low-order bits in the buffer when
214911 ¤   ¤   ·* computing what to multiply by, and recompute them
1dee26 ¤   ¤   ·* later.
a69de3 ¤   ¤   ·*/
deedd2 ¤   ¤   if (buf2 & tblmask) {
5f1477 ¤   ¤   ¤   /* Remember low-order bits for later */
0aa4f4 ¤   ¤   ¤   i = buf2 & ((1u << w2bits) - 1);
9efcd8 ¤   ¤   ¤   buf2 >>= w2bits;
fd1307 ¤   ¤   ¤   mult2pos = e1bits - w1bits + w2bits;
29d9b3 ¤   ¤   ¤   while ((buf2 & 1) == 0) {
cbb241 ¤   ¤   ¤   ¤   buf2 >>= 1;
e58a34 ¤   ¤   ¤   ¤   mult2pos++;
b9a3a6 ¤   ¤   ¤   }
470553 ¤   ¤   ¤   pgpAssert(mult2pos <= e1bits);
40744d ¤   ¤   ¤   mult2 = table2[buf2>>1];
e2c3ef ¤   ¤   ¤   buf2 = i;
db0fe4 ¤   ¤   }
--75d2 00022f24df240100150 Page 43 of bni16.c
e0af5a
1aaf5a
30591b ¤   ¤   /* If we have a pending multiply for e1, do it */
1d7851 ¤   ¤   if (e1bits == mult1pos) {
b2a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
d56ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
5f8c88 ¤   ¤   ¤   if (isone) {
d16b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
e7b517 ¤   ¤   ¤   ¤   bniCopy_16(t, mult1, mlen);
992e60 ¤   ¤   ¤   ¤   isone = 0;
b4042d ¤   ¤   ¤   } else {
94a6ef ¤   ¤   ¤   ¤   bniMontMul_16(a, t, mult1, mod, mlen, inv);
696783 ¤   ¤   ¤   ¤   /* Swap a and b */
3951ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
25a3a6 ¤   ¤   ¤   }
420fe4 ¤   ¤   }
9daf5a
9cdef5 ¤   ¤   /* If we have a pending multiply for e2, do it */
07f281 ¤   ¤   if (e1bits == mult2pos) {
8da6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
ff6ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
ca8c88 ¤   ¤   ¤   if (isone) {
bd6b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
59c17e ¤   ¤   ¤   ¤   bniCopy_16(t, mult2, mlen);
232e60 ¤   ¤   ¤   ¤   isone = 0;
fe042d ¤   ¤   ¤   } else {
1fcf04 ¤   ¤   ¤   ¤   bniMontMul_16(a, t, mult2, mod, mlen, inv);
d96783 ¤   ¤   ¤   ¤   /* Swap a and b */
9551ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
b1a3a6 ¤   ¤   ¤   }
040fe4 ¤   ¤   }
6eaf5a
a17b03 ¤   ¤   /* Are we done? */
c7824a ¤   ¤   if (!e1bits)
65cdcb ¤   ¤   ¤   break;
42af5a
68f1d1 ¤   ¤   /* Square the buffer */
369d17 ¤   ¤   if (!isone) {
676ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
54bdb0 ¤   ¤   ¤   bniMontSquare_16(a, t, mod, mlen, inv);
acebfc ¤   ¤   ¤   /* Swap a and b */
e96c84 ¤   ¤   ¤   t = a; a = b; b = t;
ba0fe4 ¤   ¤   }
40074b #if BNYIELD
869bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
f974c2 ¤   ¤   ¤   goto yield;
0f7454 #endif
d5d6a0 ¤   } /* for (;;) */
cfaf5a
d35f64 ¤   pgpAssert(!isone);
84f48a ¤   pgpAssert(!buf1);
4bd147 ¤   pgpAssert(!buf2);
f5af5a
882111 ¤   /* DONE! */
4baf5a
c48619 ¤   /* Convert result out of Montgomery form */
cc2576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
46d4fd ¤   bniCopy_16(b, t, mlen);
696cb5 ¤   bniZero_16(t, mlen);
022cdf ¤   bniMontReduce_16(b, mod, mlen, inv);
e210bc ¤   bniCopy_16(result, t, mlen);
d1af5a
be66e6 ¤   /* Clean up - free intermediate storage */
254aa5 ¤   y = 0;
de074b #if BNYIELD
80f924 yield:
da7454 #endif
1dec82 ¤   buf2 = tblmask >> w2bits;
24c7d7 ¤   while (--tblmask) {
a7369c ¤   ¤   if (tblmask < buf2)
90fb65 ¤   ¤   ¤   BNIFREE(table2[tblmask], mlen);
22cec9 ¤   ¤   BNIFREE(table1[tblmask], mlen);
--e353 0003d6e938740100150 Page 44 of bni16.c
a19371 ¤   }
f93a43 ¤   t = table1[0];
474807 ¤   BNIFREE(t, mlen);
47ac28 ¤   BNIFREE(b, 2*mlen);
762bc6 ¤   BNIFREE(a, 2*mlen);
77af5a
f9f88b ¤   return y;¤  /* Success */
adefe6 }
02af5a
2838e5 /*
0b75fe ·* 2^exp (mod mod). ·This is an optimized version for use in Fermat
75e1e7 ·* tests. ·The input value of n is ignored; it is returned with
b25d48 ·* "mlen" words valid.
b3495d ·*/
9d4d2f int
aeaccb bniTwoExpMod_16(
4a0598 ¤   PGPMemoryMgrRef¤mgr, PGPBoolean secure,
054e71 ¤   BNWORD16 *n, BNWORD16 const *exp, unsigned elen,
0dc1ba ¤   BNWORD16 *mod, unsigned mlen)
f7bb36 {
f79586 ¤   unsigned e;¤/* Copy of high words of the exponent */
588a45 ¤   unsigned bits;¤ /* Assorted counter of bits */
c5ecec ¤   BNWORD16 const *bitptr;
478ae1 ¤   BNWORD16 bitword, bitpos;
489c83 ¤   BNWORD16 *a, *b, *a1;
0270a1 ¤   BNWORD16 inv;
88d4d6 ¤   int y;¤ ¤   /* Result of bnYield() */
8faf5a
8ac613 ¤   pgpAssert(mlen);
26af5a
ce68b8 ¤   bitptr = BIGLITTLE(exp-elen, exp+elen-1);
8a5646 ¤   bitword = *bitptr;
badac6 ¤   pgpAssert(bitword);
36af5a
056c02 ¤   /* Clear n for future use. */
d18f80 ¤   bniZero_16(n, mlen);
01af5a
80f331 ¤   bits = bniBits_16(exp, elen);
1d67c5 ¤
617d28 ¤   /* First, a couple of trivial cases. */
853d59 ¤   if (bits <= 1) {
7004f3 ¤   ¤   /* 2 ^ 0 == 1, ·2 ^ 1 == 2 */
390394 ¤   ¤   BIGLITTLE(n[-1],n[0]) = (BNWORD16)1<<elen;
adbbde ¤   ¤   return 0;
1b9371 ¤   }
9eaf5a
a558f7 ¤   /* Set bitpos to the most significant bit */
6b94d5 ¤   bitpos = (BNWORD16)1 << ((bits-1) & (16-1));
16af5a
bbc6b9 ¤   /* Now, count the bits in the modulus. */
ed945c ¤   bits = bniBits_16(mod, mlen);
d81a06 ¤   pgpAssert(bits > 1);¤   /* a 1-bit modulus is just stupid... */
12af5a
3dd8af ¤   /*
e9a0aa ¤   ·* We start with 1<<e, where "e" is as many high bits of the
9c2f39 ¤   ·* exponent as we can manage without going over the modulus.
100fed ¤   ·* This first loop finds "e".
7da4e3 ¤   ·*/
30142a ¤   e = 1;
472e54 ¤   while (elen) {
de6961 ¤   ¤   /* Consume the first bit */
c41e4d ¤   ¤   bitpos >>= 1;
4aa81f ¤   ¤   if (!bitpos) {
5be0f0 ¤   ¤   ¤   if (!--elen)
acf622 ¤   ¤   ¤   ¤   break;
c22e5d ¤   ¤   ¤   bitword = BIGLITTLE(*++bitptr,*--bitptr);
671dcc ¤   ¤   ¤   bitpos = (BNWORD16)1<<(16-1);
780fe4 ¤   ¤   }
1a81e8 ¤   ¤   e = (e << 1) | ((bitpos & bitword) != 0);
a99a93 ¤   ¤   if (e >= bits) {¤   /* Overflow! ·Back out. */
39895c ¤   ¤   ¤   e >>= 1;
3dcdcb ¤   ¤   ¤   break;
--c9c1 000b086a20340100150 Page 45 of bni16.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
eed8af ¤   /*
36ce46 ¤   ·* The bit in "bitpos" being examined by the bit buffer has NOT
9a276b ¤   ·* been consumed yet. ·This may be past the end of the exponent,
94f3bd ¤   ·* in which case elen == 1.
d3a4e3 ¤   ·*/
cdaf5a
adf10e ¤   /* Okay, now, set bit "e" in n. ·n is already zero. */
ebbaa9 ¤   inv = (BNWORD16)1 << (e & (16-1));
74c00c ¤   e /= 16;
7539b7 ¤   BIGLITTLE(n[-e-1],n[e]) = inv;
d2d8af ¤   /*
42be4e ¤   ·* The effective length of n in words is now "e+1".
f1b121 ¤   ·* This is used a little bit later.
13a4e3 ¤   ·*/
c8af5a
c1de10 ¤   if (!elen)
bf2875 ¤   ¤   return 0;¤  /* That was easy! */
59af5a
fad8af ¤   /*
fbc0f9 ¤   ·* We have now processed the first few bits. ·The next step
44ef9b ¤   ·* is to convert this to Montgomery form for further squaring.
eda4e3 ¤   ·*/
22af5a
a1cc1d ¤   /* Allocate working storage: two product buffers */
55fc9a ¤   BNIALLOC(mgr, secure, a, BNWORD16, 2*mlen);
8e9293 ¤   if (!a)
98043c ¤   ¤   return -1;
6a0f6c ¤   BNIALLOC(mgr, secure, b, BNWORD16, 2*mlen);
c25215 ¤   if (!b) {
1bdda3 ¤   ¤   BNIFREE(a, 2*mlen);
73043c ¤   ¤   return -1;
499371 ¤   }
4daf5a
83d2c8 ¤   /* Convert n to Montgomery form */
75fe5c ¤   inv = BIGLITTLE(mod[-1],mod[0]);¤   /* LSW of modulus */
79a263 ¤   pgpAssert(inv & 1);¤/* Modulus must be odd */
b6b963 ¤   inv = bniMontInv1_16(inv);
a57b0c ¤   /* Move n (length e+1, remember?) up "mlen" words into b */
961ca2 ¤   /* Note that we lie about a1 for a bit - it's pointing to b */
6feed0 ¤   a1 = BIGLITTLE(b-mlen,b+mlen);
51d9e3 ¤   bniCopy_16(a1, n, e+1);
dc5635 ¤   bniZero_16(b, mlen);
91cd45 ¤   /* Do the division - dump the quotient into the high-order words */
5be86e ¤   (void)bniDiv_16(a1, b, mlen+e+1, mod, mlen);
acd8af ¤   /*
aa7cbb ¤   ·* Now do the first squaring and modular reduction to put
eebad9 ¤   ·* the number up in a1 where it belongs.
daa4e3 ¤   ·*/
207dca ¤   bniMontSquare_16(a, b, mod, mlen, inv);
728266 ¤   /* Fix up a1 to point to where it should go. */
18a2f6 ¤   a1 = BIGLITTLE(a-mlen,a+mlen);
68af5a
bed8af ¤   /*
5ea8c4 ¤   ·* Okay, now, a1 holds the number being accumulated, and
14e460 ¤   ·* b is a scratch register. ·Start working:
6da4e3 ¤   ·*/
7c220e ¤   for (;;) {
961b17 ¤   ¤   /*
61fe25 ¤   ¤   ·* Is the bit set? ·If so, double a1 as well.
a005df ¤   ¤   ·* A modular doubling like this is very cheap.
b39de3 ¤   ¤   ·*/
c326ed ¤   ¤   if (bitpos & bitword) {
b87aad ¤   ¤   ¤   /*
cc50e7 ¤   ¤   ¤   ·* Double the number. ·If there was a carry out OR
3466f7 ¤   ¤   ¤   ·* the result is greater than the modulus, subract
1cd530 ¤   ¤   ¤   ·* the modulus.
d48753 ¤   ¤   ¤   ·*/
a409aa ¤   ¤   ¤   if (bniDouble_16(a1, mlen) ||
7e2bc7 ¤   ¤   ¤   ····bniCmp_16(a1, mod, mlen) > 0)
b0e414 ¤   ¤   ¤   ¤   (void)bniSubN_16(a1, mod, mlen);
--d658 00016c2946340100150 Page 46 of bni16.c
b50fe4 ¤   ¤   }
e6af5a
8a10bb ¤   ¤   /* Advance to the next exponent bit */
111e4d ¤   ¤   bitpos >>= 1;
57a81f ¤   ¤   if (!bitpos) {
1ce0f0 ¤   ¤   ¤   if (!--elen)
276282 ¤   ¤   ¤   ¤   break;¤ /* Done! */
ff2e5d ¤   ¤   ¤   bitword = BIGLITTLE(*++bitptr,*--bitptr);
441dcc ¤   ¤   ¤   bitpos = (BNWORD16)1<<(16-1);
560fe4 ¤   ¤   }
7baf5a
be1b17 ¤   ¤   /*
9582e5 ¤   ¤   ·* The elen/bitword/bitpos bit buffer is known to be
3a511a ¤   ¤   ·* non-empty, i.e. there is at least one more unconsumed bit.
b521d7 ¤   ¤   ·* Thus, it's safe to square the number.
639de3 ¤   ¤   ·*/
0ecee2 ¤   ¤   bniMontSquare_16(b, a1, mod, mlen, inv);
785dee ¤   ¤   /* Rename result (in b) back to a (a1, really). */
a57e82 ¤   ¤   a1 = b; b = a; a = a1;
95e305 ¤   ¤   a1 = BIGLITTLE(a-mlen,a+mlen);
59074b #if BNYIELD
b09bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
2674c2 ¤   ¤   ¤   goto yield;
7c7454 #endif
5f9371 ¤   }
75af5a
402009 ¤   /* DONE! ·Just a little bit of cleanup... */
2baf5a
f7d8af ¤   /*
ba4b9e ¤   ·* Convert result out of Montgomery form... this is
7a5cb3 ¤   ·* just a Montgomery reduction.
e8a4e3 ¤   ·*/
e8e113 ¤   bniCopy_16(a, a1, mlen);
ceacd9 ¤   bniZero_16(a1, mlen);
424534 ¤   bniMontReduce_16(a, mod, mlen, inv);
547ef7 ¤   bniCopy_16(n, a1, mlen);
6aaf5a
e366e6 ¤   /* Clean up - free intermediate storage */
b74aa5 ¤   y = 0;
02074b #if BNYIELD
ddf924 yield:
067454 #endif
47ac28 ¤   BNIFREE(b, 2*mlen);
7e2bc6 ¤   BNIFREE(a, 2*mlen);
4baf5a
08f88b ¤   return y;¤  /* Success */
65efe6 }
96af5a
6caf5a
2c38e5 /*
4db33d ·* Returns a substring of the big-endian array of bytes representation
edb3f8 ·* of the bignum array based on two parameters, the least significant
1f05a1 ·* byte number (0 to start with the least significant byte) and the
ab831e ·* length. ·I.e. the number returned is a representation of
6dca57 ·* (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
28775e ·*
af66af ·* It is an error if the bignum is not at least buflen + lsbyte bytes
2003a5 ·* long.
86775e ·*
ef08c9 ·* This code assumes that the compiler has the minimal intelligence·
87be7b ·* neded to optimize divides and modulo operations on an unsigned data
935fd8 ·* type with a power of two.
7d495d ·*/
f3314a void
bfd411 bniExtractBigBytes_16(BNWORD16 const *n, unsigned char *buf,
cc163a ¤   unsigned lsbyte, unsigned buflen)
46bb36 {
def077 ¤   BNWORD16 t = 0;¤/* Needed to shut up uninitialized var warnings */
bf7dd8 ¤   unsigned shift;
13af5a
ae29ec ¤   lsbyte += buflen;
16af5a
--f2c2 00053eac5ac40100150 Page 47 of bni16.c
c8aa78 ¤   shift = (8 * lsbyte) % 16;
ea4fb4 ¤   lsbyte /= (16/8);¤  /* Convert to word offset */
9f378b ¤   BIGLITTLE(n -= lsbyte, n += lsbyte);
d4af5a
7f5bcd ¤   if (shift)
6c23e5 ¤   ¤   t = BIGLITTLE(n[-1],n[0]);
b8af5a
0598f0 ¤   while (buflen--) {
cabc36 ¤   ¤   if (!shift) {
ef4e1a ¤   ¤   ¤   t = BIGLITTLE(*n++,*--n);
1615a5 ¤   ¤   ¤   shift = 16;
750fe4 ¤   ¤   }
092ad4 ¤   ¤   shift -= 8;
d25443 ¤   ¤   *buf++ = (unsigned char)(t>>shift);
0c9371 ¤   }
95efe6 }
8faf5a
be38e5 /*
4a987d ·* Merge a big-endian array of bytes into a bignum array.
de225f ·* The array had better be big enough. ·This is
d59651 ·* equivalent to extracting the entire bignum into a
97e36b ·* large byte array, copying the input buffer into the
9c4fc8 ·* middle of it, and converting back to a bignum.
6a775e ·*
ebbf48 ·* The buf is "len" bytes long, and its *last* byte is at
87714c ·* position "lsbyte" from the end of the bignum.
41775e ·*
0e2e7d ·* Note that this is a pain to get right. ·Fortunately, it's hardly
437bdc ·* critical for efficiency.
8e495d ·*/
0c314a void
60c765 bniInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf,
35a951 ··················unsigned lsbyte, ·unsigned buflen)
e7bb36 {
99bee3 ¤   BNWORD16 t = 0;¤/* Shut up uninitialized varibale warnings */
b9af5a
1d29ec ¤   lsbyte += buflen;
8eaf5a
38620a ¤   BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8));
09af5a
b46297 ¤   /* Load up leading odd bytes */
d5c69d ¤   if (lsbyte % (16/8)) {
cea3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
05f492 ¤   ¤   t >>= (lsbyte * 8) % 16;
079371 ¤   }
cfaf5a
e00bd3 ¤   /* The main loop - merge into t, storing at each word boundary. */
2c98f0 ¤   while (buflen--) {
2313b9 ¤   ¤   t = (t << 8) | *buf++;
d59b41 ¤   ¤   if ((--lsbyte % (16/8)) == 0)
a09b8b ¤   ¤   ¤   BIGLITTLE(*n++,*--n) = t;
a29371 ¤   }
c1af5a
a845dc ¤   /* Merge odd bytes in t into last word */
14e102 ¤   lsbyte = (lsbyte * 8) % 16;
1e44bd ¤   if (lsbyte) {
158687 ¤   ¤   t <<= lsbyte;
869f2e ¤   ¤   t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
54bca8 ¤   ¤   BIGLITTLE(n[0],n[-1]) = t;
fe9371 ¤   }
46af5a
aa830f ¤   return;
caefe6 }
56af5a
3638e5 /*
6f0e40 ·* Returns a substring of the little-endian array of bytes representation
1bb3f8 ·* of the bignum array based on two parameters, the least significant
5005a1 ·* byte number (0 to start with the least significant byte) and the
8b831e ·* length. ·I.e. the number returned is a representation of
a5ca57 ·* (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
1e775e ·*
5366af ·* It is an error if the bignum is not at least buflen + lsbyte bytes
--aed1 0006398255440100150 Page 48 of bni16.c
9203a5 ·* long.
08775e ·*
de08c9 ·* This code assumes that the compiler has the minimal intelligence·
09be7b ·* neded to optimize divides and modulo operations on an unsigned data
a15fd8 ·* type with a power of two.
f9495d ·*/
c9314a void
0cf88f bniExtractLittleBytes_16(BNWORD16 const *n, unsigned char *buf,
eb163a ¤   unsigned lsbyte, unsigned buflen)
59bb36 {
5df077 ¤   BNWORD16 t = 0;¤/* Needed to shut up uninitialized var warnings */
a6af5a
a3620a ¤   BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8));
1aaf5a
4ac69d ¤   if (lsbyte % (16/8)) {
97a3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
77cb3b ¤   ¤   t >>= (lsbyte % (16/8)) * 8 ;
bc9371 ¤   }
09af5a
f498f0 ¤   while (buflen--) {
0418cb ¤   ¤   if ((lsbyte++ % (16/8)) == 0)
184cd1 ¤   ¤   ¤   t = BIGLITTLE(*--n,*n++);
2e8d7c ¤   ¤   *buf++ = (unsigned char)t;
bbe6a0 ¤   ¤   t >>= 8;
be9371 ¤   }
12efe6 }
d2af5a
a738e5 /*
d6f64f ·* Merge a little-endian array of bytes into a bignum array.
43225f ·* The array had better be big enough. ·This is
cc9651 ·* equivalent to extracting the entire bignum into a
e2e36b ·* large byte array, copying the input buffer into the
814fc8 ·* middle of it, and converting back to a bignum.
2f775e ·*
a3ef01 ·* The buf is "len" bytes long, and its first byte is at
34714c ·* position "lsbyte" from the end of the bignum.
7b775e ·*
8d2e7d ·* Note that this is a pain to get right. ·Fortunately, it's hardly
8c7bdc ·* critical for efficiency.
be495d ·*/
7d314a void
a8fc1a bniInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf,
a6a951 ··················unsigned lsbyte, ·unsigned buflen)
4ebb36 {
32bee3 ¤   BNWORD16 t = 0;¤/* Shut up uninitialized varibale warnings */
36af5a
84be7c ¤   /* Move to most-significant end */
6c29ec ¤   lsbyte += buflen;
c24a44 ¤   buf += buflen;
c0af5a
cf620a ¤   BIGLITTLE(n -= lsbyte/(16/8), n += lsbyte/(16/8));
0eaf5a
bb6297 ¤   /* Load up leading odd bytes */
0dc69d ¤   if (lsbyte % (16/8)) {
6da3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
baf492 ¤   ¤   t >>= (lsbyte * 8) % 16;
869371 ¤   }
33af5a
640bd3 ¤   /* The main loop - merge into t, storing at each word boundary. */
6e98f0 ¤   while (buflen--) {
69033f ¤   ¤   t = (t << 8) | *--buf;
df9b41 ¤   ¤   if ((--lsbyte % (16/8)) == 0)
8c9b8b ¤   ¤   ¤   BIGLITTLE(*n++,*--n) = t;
cd9371 ¤   }
e5af5a
b545dc ¤   /* Merge odd bytes in t into last word */
f7e102 ¤   lsbyte = (lsbyte * 8) % 16;
e344bd ¤   if (lsbyte) {
b48687 ¤   ¤   t <<= lsbyte;
649f2e ¤   ¤   t |= (((BNWORD16)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
66bca8 ¤   ¤   BIGLITTLE(n[0],n[-1]) = t;
639371 ¤   }
--a8c6 000c9e0195140100150 Page 49 of bni16.c
e0af5a
c3830f ¤   return;
5fefe6 }
b0af5a
4cf6c3 #ifdef DEADCODE¤/* This was a precursor to the more flexible bniExtractBytes */
b538e5 /*
98b36e ·* Convert a big-endian array of bytes to a bignum.
caabb4 ·* Returns the number of words in the bignum.
1cb05d ·* Note the expression "16/8" for the number of bytes per word.
5ecd11 ·* This is so the word-size adjustment will work.
57495d ·*/
87536c unsigned
a29a5e bniFromBytes_16(BNWORD16 *a, unsigned char const *b, unsigned blen)
bfbb36 {
08dcba ¤   BNWORD16 t;
a04887 ¤   unsigned alen = (blen + (16/8-1))/(16/8);
02dbd6 ¤   BIGLITTLE(a -= alen, a += alen);
9eaf5a
a9b25a ¤   while (blen) {
fb0550 ¤   ¤   t = 0;
854392 ¤   ¤   do {
7fc682 ¤   ¤   ¤   t = t << 8 | *b++;
500adc ¤   ¤   } while (--blen & (16/8-1));
8e64ff ¤   ¤   BIGLITTLE(*a++,*--a) = t;
b59371 ¤   }
64c2b6 ¤   return alen;
faefe6 }
467454 #endif
eeaf5a
0538e5 /*
49af62 ·* Computes the GCD of a and b. ·Modifies both arguments; when it returns,
4de261 ·* one of them is the GCD and the other is trash. ·The return value
e6d234 ·* indicates which: 0 for a, and 1 for b. ·The length of the retult is
de3d14 ·* returned in rlen. ·Both inputs must have one extra word of precision.
58bfe3 ·* alen must be >= blen.
db775e ·*
85537b ·* TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B).
9e6ece ·* This is based on taking out common powers of 2, then repeatedly:
09604a ·* gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted.
fa2ace ·* gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced.
498a0c ·* It gets less reduction per step, but the steps are much faster than
6179ed ·* the division case.
08495d ·*/
dc4d2f int
94650d bniGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen,
9c76c7 ¤   unsigned *rlen)
c9bb36 {
ca074b #if BNYIELD
0dce31 ¤   int y;
c87454 #endif
1d64c5 ¤   pgpAssert(alen >= blen);
7aaf5a
2efbe1 ¤   while (blen != 0) {
ee69a9 ¤   ¤   (void)bniDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
ee414e ¤   ¤   alen = bniNorm_16(a, blen);
548bb3 ¤   ¤   if (alen == 0) {
62e6e3 ¤   ¤   ¤   *rlen = blen;
6fdb98 ¤   ¤   ¤   return 1;
750fe4 ¤   ¤   }
c64079 ¤   ¤   (void)bniDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
f5c77a ¤   ¤   blen = bniNorm_16(b, alen);
25074b #if BNYIELD
6a9bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
d81b2c ¤   ¤   ¤   return y;
967454 #endif
ba9371 ¤   }
e517b1 ¤   *rlen = alen;
003e6b ¤   return 0;
c4efe6 }
3faf5a
2b38e5 /*
c93401 ·* Invert "a" modulo "mod" using the extended Euclidean algorithm.
--0724 000be009f4a40100150 Page 50 of bni16.c
0c81f2 ·* Note that this only computes one of the cosequences, and uses the
8cbe84 ·* theorem that the signs flip every step and the absolute value of
9eea0f ·* the cosequence values are always bounded by the modulus to avoid
bb1a6c ·* having to work with negative numbers.
2c7b80 ·* gcd(a,mod) had better equal 1. ·Returns 1 if the GCD is NOT 1.
cc9798 ·* a must be one word longer than "mod". ·It is overwritten with the
aa1d22 ·* result.
b06b11 ·* TODO: Use Richard Schroeppel's *much* faster algorithm.
3a495d ·*/
cb4d2f int
2db051 bniInv_16(
f66740 ¤   PGPMemoryMgrRef¤mgr,
b854d3 ¤   PGPBoolean secure,
430057 ¤   BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen)
49bb36 {
abb85b ¤   BNWORD16 *b;¤   /* Hold a copy of mod during GCD reduction */
3e2b63 ¤   BNWORD16 *p;¤   /* Temporary for products added to t0 and t1 */
397d0f ¤   BNWORD16 *t0, *t1;¤ /* Inverse accumulators */
423d63 ¤   BNWORD16 cy;
91fc25 ¤   unsigned blen, t0len, t1len, plen;
d4ce31 ¤   int y;
b7af5a
4962dc ¤   alen = bniNorm_16(a, alen);
c3cebc ¤   if (!alen)
b862ef ¤   ¤   return 1;¤  /* No inverse */
55af5a
0898c5 ¤   mlen = bniNorm_16(mod, mlen);
46af5a
af846b ¤   pgpAssert (alen <= mlen);
91af5a
04cfc2 ¤   /* Inverse of 1 is 1 */
7f5002 ¤   if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) {
7ffd7f ¤   ¤   bniZero_16(BIGLITTLE(a-alen,a+alen), mlen-alen);
4dbbde ¤   ¤   return 0;
a59371 ¤   }
69af5a
cc3e0b ¤   /* Allocate a pile of space */
11e93c ¤   BNIALLOC(mgr, secure, b, BNWORD16, mlen+1);
ea5359 ¤   if (b) {
701b17 ¤   ¤   /*
6733b9 ¤   ¤   ·* Although products are guaranteed to always be less than the
e46531 ¤   ¤   ·* modulus, it can involve multiplying two 3-word numbers to
69c163 ¤   ¤   ·* get a 5-word result, requiring a 6th word to store a 0
bea773 ¤   ¤   ·* temporarily. ·Thus, mlen + 1.
279de3 ¤   ¤   ·*/
b5e0ac ¤   ¤   BNIALLOC(mgr, secure, p, BNWORD16, mlen+1);
764400 ¤   ¤   if (p) {
7697a5 ¤   ¤   ¤   BNIALLOC(mgr, secure, t0, BNWORD16, mlen);
26da36 ¤   ¤   ¤   if (t0) {
934fc8 ¤   ¤   ¤   ¤   BNIALLOC(mgr, secure, t1, BNWORD16, mlen);
ab5d06 ¤   ¤   ¤   ¤   if (t1)
e85da1 ¤   ¤   ¤   ¤   ¤   ¤   goto allocated;
2a1674 ¤   ¤   ¤   ¤   BNIFREE(t0, mlen);
51a3a6 ¤   ¤   ¤   }
080620 ¤   ¤   ¤   BNIFREE(p, mlen+1);
4c0fe4 ¤   ¤   }
b1bc1d ¤   ¤   BNIFREE(b, mlen+1);
919371 ¤   }
87e69f ¤   return -1;
20af5a
7aaf26 allocated:
5eaf5a
d61bb7 ¤   /* Set t0 to 1 */
f4abc7 ¤   t0len = 1;
7d8f84 ¤   BIGLITTLE(t0[-1],t0[0]) = 1;
c767c5 ¤
60d0b9 ¤   /* b = mod */
912b02 ¤   bniCopy_16(b, mod, mlen);
433db3 ¤   /* blen = mlen (implicitly) */
d167c5 ¤
e7d980 ¤   /* t1 = b / a; b = b % a */
be4e89 ¤   cy = bniDiv_16(t1, b, mlen, a, alen);
--92c6 00011cfcf3f40100150 Page 51 of bni16.c
97107b ¤   *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy;
a1f68f ¤   t1len = bniNorm_16(t1, mlen-alen+1);
0b4c86 ¤   blen = bniNorm_16(b, alen);
85af5a
13aa55 ¤   /* while (b > 1) */
183ac4 ¤   while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD16)1) {
ad3f9a ¤   ¤   /* q = a / b; a = a % b; */
179509 ¤   ¤   if (alen < blen || (alen == blen && bniCmp_16(a, a, alen) < 0))
5fb783 ¤   ¤   ¤   pgpAssert(0);
91eedc ¤   ¤   cy = bniDiv_16(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
dd0118 ¤   ¤   *(BIGLITTLE(a-alen-1,a+alen)) = cy;
7d63ce ¤   ¤   plen = bniNorm_16(BIGLITTLE(a-blen,a+blen), alen-blen+1);
baec44 ¤   ¤   pgpAssert(plen);
57414e ¤   ¤   alen = bniNorm_16(a, blen);
b72c1f ¤   ¤   if (!alen)
bc6b71 ¤   ¤   ¤   goto failure;¤  /* GCD not 1 */
4eaf5a
9cc2fe ¤   ¤   /* t0 += q * t1; */
8d7df1 ¤   ¤   pgpAssert(plen+t1len <= mlen+1);
a39269 ¤   ¤   bniMul_16(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len);
f592cb ¤   ¤   plen = bniNorm_16(p, plen + t1len);
c674e7 ¤   ¤   pgpAssert(plen <= mlen);
837ccf ¤   ¤   if (plen > t0len) {
20d425 ¤   ¤   ¤   bniZero_16(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len);
90b0b8 ¤   ¤   ¤   t0len = plen;
c50fe4 ¤   ¤   }
6c2fba ¤   ¤   cy = bniAddN_16(t0, p, plen);
7e2e8b ¤   ¤   if (cy) {
8879eb ¤   ¤   ¤   if (t0len > plen) {
2bad79 ¤   ¤   ¤   ¤   cy = bniAdd1_16(BIGLITTLE(t0-plen,t0+plen),
9c8447 ¤   ¤   ¤   ¤   ¤   ¤   t0len-plen, cy);
bea3a6 ¤   ¤   ¤   }
491411 ¤   ¤   ¤   if (cy) {
2e8336 ¤   ¤   ¤   ¤   BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy;
b3a7f8 ¤   ¤   ¤   ¤   t0len++;
b5a3a6 ¤   ¤   ¤   }
e80fe4 ¤   ¤   }
56af5a
1a80a4 ¤   ¤   /* if (a <= 1) return a ? t0 : FAIL; */
c9b2ad ¤   ¤   if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD16)1) {
993d57 ¤   ¤   ¤   if (alen == 0)
497b91 ¤   ¤   ¤   ¤   goto failure;¤  /* FAIL */
f8e238 ¤   ¤   ¤   pgpAssert(t0len <= mlen);
e91dc0 ¤   ¤   ¤   bniCopy_16(a, t0, t0len);
ed273f ¤   ¤   ¤   bniZero_16(BIGLITTLE(a-t0len, a+t0len), mlen-t0len);
9e346a ¤   ¤   ¤   goto success;
240fe4 ¤   ¤   }
8caf5a
eead15 ¤   ¤   /* q = b / a; b = b % a; */
e789c1 ¤   ¤   if (blen < alen || (blen == alen && bniCmp_16(b, a, alen) < 0))
dcb783 ¤   ¤   ¤   pgpAssert(0);
4bc70c ¤   ¤   cy = bniDiv_16(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
38c9ab ¤   ¤   *(BIGLITTLE(b-blen-1,b+blen)) = cy;
f6c62f ¤   ¤   plen = bniNorm_16(BIGLITTLE(b-alen,b+alen), blen-alen+1);
faec44 ¤   ¤   pgpAssert(plen);
7dc77a ¤   ¤   blen = bniNorm_16(b, alen);
c62062 ¤   ¤   if (!blen)
886b71 ¤   ¤   ¤   goto failure;¤  /* GCD not 1 */
deaf5a
9f48c5 ¤   ¤   /* t1 += q * t0; */
de6dfe ¤   ¤   pgpAssert(plen+t0len <= mlen+1);
c0c9b9 ¤   ¤   bniMul_16(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len);
f20d1e ¤   ¤   plen = bniNorm_16(p, plen + t0len);
9774e7 ¤   ¤   pgpAssert(plen <= mlen);
59fd70 ¤   ¤   if (plen > t1len) {
1e933c ¤   ¤   ¤   bniZero_16(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len);
aab515 ¤   ¤   ¤   t1len = plen;
fd0fe4 ¤   ¤   }
5b2a17 ¤   ¤   cy = bniAddN_16(t1, p, plen);
432e8b ¤   ¤   if (cy) {
5631c1 ¤   ¤   ¤   if (t1len > plen) {
11bd76 ¤   ¤   ¤   ¤   cy = bniAdd1_16(BIGLITTLE(t1-plen,t0+plen),
--a801 0017dcac8ce40100150 Page 52 of bni16.c
f90a57 ¤   ¤   ¤   ¤   ¤   ¤   t1len-plen, cy);
dea3a6 ¤   ¤   ¤   }
be1411 ¤   ¤   ¤   if (cy) {
c4f5c1 ¤   ¤   ¤   ¤   BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy;
452647 ¤   ¤   ¤   ¤   t1len++;
49a3a6 ¤   ¤   ¤   }
c40fe4 ¤   ¤   }
9d074b #if BNYIELD
52b0d5 ¤   ¤   if (bnYield && (y = bnYield() < 0))
bc74c2 ¤   ¤   ¤   goto yield;
a27454 #endif
ba9371 ¤   }
7aaf5a
7ac2c1 ¤   if (!blen)
63fa45 ¤   ¤   goto failure;¤  /* gcd(a, mod) != 1 -- FAIL */
d7af5a
9a6f47 ¤   /* return mod-t1 */
8ef37c ¤   bniCopy_16(a, mod, mlen);
0f7269 ¤   pgpAssert(t1len <= mlen);
d2f67f ¤   cy = bniSubN_16(a, t1, t1len);
5cab3e ¤   if (cy) {
61a6e8 ¤   ¤   pgpAssert(mlen > t1len);
47a84d ¤   ¤   cy = bniSub1_16(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy);
e0642a ¤   ¤   pgpAssert(!cy);
b39371 ¤   }
dbaf5a
85d3ad success:
3a40e5 ¤   BNIFREE(t1, mlen);
cb6cc2 ¤   BNIFREE(t0, mlen);
455d1b ¤   BNIFREE(p, mlen+1);
e64a78 ¤   BNIFREE(b, mlen+1);
cc67c5 ¤
043e6b ¤   return 0;
44af5a
7e5cfe failure:¤   ¤   /* GCD is not 1 - no inverse exists! */
d21079 ¤   y = 1;
60074b #if BNYIELD
c2f924 yield:
e77454 #endif
5940e5 ¤   BNIFREE(t1, mlen);
c46cc2 ¤   BNIFREE(t0, mlen);
b45d1b ¤   BNIFREE(p, mlen+1);
484a78 ¤   BNIFREE(b, mlen+1);
4367c5 ¤
81a403 ¤   return y;
7defe6 }
--c668 0009e850d0640100151 Page 1 of bni16.h
bc38e5 /*
1d16e9 ·* $Id: bni16.h,v 1.4 1997/12/12 00:52:48 lloyd Exp $
d4495d ·*/
74af5a
19c5f7 #ifndef Included_bni16_h
d1861d #define Included_bni16_h
84af5a
35a6ac #include "bni.h"
246773 #include "pgpMemoryMgr.h"
09af5a
0135a6 #ifndef BNWORD16
4586c9 #error 16-bit bignum library requires a 16-bit data type
787454 #endif
c6af5a
e699c6 PGP_BEGIN_C_DECLARATIONS
d3af5a
af0df8 #ifndef bniCopy_16
44af75 void bniCopy_16(BNWORD16 *dest, BNWORD16 const *src, unsigned len);
8e7454 #endif
dc945a #ifndef bniZero_16
adc4a5 void bniZero_16(BNWORD16 *num, unsigned len);
1d7454 #endif
737472 #ifndef bniNeg_16
a55d6e void bniNeg_16(BNWORD16 *num, unsigned len);
757454 #endif
03af5a
37b90b #ifndef bniAdd1_16
be58b2 BNWORD16 bniAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry);
9a7454 #endif
fedbfa #ifndef bniSub1_16
f9cde3 BNWORD16 bniSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow);
e17454 #endif
daaf5a
aec604 #ifndef bniAddN_16
784b64 BNWORD16 bniAddN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len);
5c7454 #endif
03a4f5 #ifndef bniSubN_16
8d3a16 BNWORD16 bniSubN_16(BNWORD16 *num1, BNWORD16 const *num2, unsigned len);
887454 #endif
2eaf5a
48fff9 #ifndef bniCmp_16
3ebe12 int bniCmp_16(BNWORD16 const *num1, BNWORD16 const *num2, unsigned len);
4f7454 #endif
33af5a
01c916 #ifndef bniMulN1_16
bc9af8 void bniMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k);
887454 #endif
29c100 #ifndef bniMulAdd1_16
3c3401 BNWORD16
3ca876 bniMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k);
f97454 #endif
48a3f1 #ifndef bniMulSub1_16
81613d BNWORD16 bniMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len,
4fab02 ¤   ¤   ¤   BNWORD16 k);
8f7454 #endif
8daf5a
153f35 #ifndef bniLshift_16
bceb02 BNWORD16 bniLshift_16(BNWORD16 *num, unsigned len, unsigned shift);
697454 #endif
f9e88a #ifndef bniDouble_16
a98ef8 BNWORD16 bniDouble_16(BNWORD16 *num, unsigned len);
277454 #endif
d36c9c #ifndef bniRshift_16
f40217 BNWORD16 bniRshift_16(BNWORD16 *num, unsigned len, unsigned shift);
017454 #endif
3daf5a
d6d940 #ifndef bniMul_16
9e25c7 void bniMul_16(BNWORD16 *prod, BNWORD16 const *num1, unsigned len1,
bd6704 ¤   BNWORD16 const *num2, unsigned len2);
c67454 #endif
e40910 #ifndef bniSquare_16
9e6497 void bniSquare_16(BNWORD16 *prod, BNWORD16 const *num, unsigned len);
--cf4d 000eeedb0e840100151 Page 2 of bni16.h
a07454 #endif
e0af5a
e12623 #ifndef bniNorm_16
792ad1 unsigned bniNorm_16(BNWORD16 const *num, unsigned len);
dc7454 #endif
bc888e #ifndef bniBits_16
338b15 unsigned bniBits_16(BNWORD16 const *num, unsigned len);
cd7454 #endif
bbaf5a
c79e0e #ifndef bniExtractBigBytes_16
b895db void bniExtractBigBytes_16(BNWORD16 const *bn, unsigned char *buf,
8c9eef ¤   unsigned lsbyte, unsigned buflen);
337454 #endif
12c9e5 #ifndef bniInsertBigytes_16
250356 void bniInsertBigBytes_16(BNWORD16 *n, unsigned char const *buf,
907db1 ¤   unsigned lsbyte, ·unsigned buflen);
827454 #endif
4f2316 #ifndef bniExtractLittleBytes_16
ec74ca void bniExtractLittleBytes_16(BNWORD16 const *bn, unsigned char *buf,
199eef ¤   unsigned lsbyte, unsigned buflen);
7a7454 #endif
c6914b #ifndef bniInsertLittleBytes_16
5a381a void bniInsertLittleBytes_16(BNWORD16 *n, unsigned char const *buf,
507db1 ¤   unsigned lsbyte, ·unsigned buflen);
147454 #endif
4baf5a
de3350 #ifndef bniDiv21_16
d5cdad BNWORD16 bniDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d);
007454 #endif
1e4ac3 #ifndef bniDiv1_16
1bcec2 BNWORD16 bniDiv1_16(BNWORD16 *q, BNWORD16 *rem,
a3fcc9 ¤   BNWORD16 const *n, unsigned len, BNWORD16 d);
6f7454 #endif
cf5558 #ifndef bniModQ_16
bf8954 unsigned bniModQ_16(BNWORD16 const *n, unsigned len, unsigned d);
a67454 #endif
8c13d5 #ifndef bniDiv_16
8c3401 BNWORD16
7738b3 bniDiv_16(BNWORD16 *q, BNWORD16 *n, unsigned nlen, BNWORD16 *d, unsigned dlen);
bf7454 #endif
86af5a
2d747d #ifndef bniMontInv1_16
c67f69 BNWORD16 bniMontInv1_16(BNWORD16 const x);
d97454 #endif
82c756 #ifndef bniMontReduce_16
2b5b69 void bniMontReduce_16(BNWORD16 *n, BNWORD16 const *mod, unsigned const mlen,
49c77d ················BNWORD16 inv);
207454 #endif
6763f1 #ifndef bniToMont_16
c3a949 void bniToMont_16(BNWORD16 *n, unsigned nlen, BNWORD16 *mod, unsigned mlen);
057454 #endif
37d345 #ifndef bniFromMont_16
b34ce6 void bniFromMont_16(BNWORD16 *n, BNWORD16 *mod, unsigned len);
3a7454 #endif
baaf5a
f738f4 #ifndef bniExpMod_16
f1c5bb int bniExpMod_16( PGPMemoryMgrRef mgr, PGPBoolean secure,
039e1c ¤   BNWORD16 *result, BNWORD16 const *n, unsigned nlen,
4a22d0 ¤   BNWORD16 const *exp, unsigned elen, BNWORD16 *mod, unsigned mlen);
e47454 #endif
cdd27b #ifndef bniDoubleExpMod_16
42f70b int bniDoubleExpMod_16(
3239d6 ¤   PGPMemoryMgrRef mgr, PGPBoolean secure,
a0e7a1 ¤   BNWORD16 *result,
daba11 ¤   BNWORD16 const *n1, unsigned n1len, BNWORD16 const *e1, unsigned e1len,
47bd6d ¤   BNWORD16 const *n2, unsigned n2len, BNWORD16 const *e2, unsigned e2len,
e41a30 ¤   BNWORD16 *mod, unsigned mlen);
d47454 #endif
6dad8e #ifndef bniTwoExpMod_16
a50f25 int bniTwoExpMod_16( PGPMemoryMgrRef mgr, PGPBoolean secure,
e44e71 ¤   BNWORD16 *n, BNWORD16 const *exp, unsigned elen,
ee1a30 ¤   BNWORD16 *mod, unsigned mlen);
--a8c2 0011bc95a1440100151 Page 3 of bni16.h
a07454 #endif
db307d #ifndef bniGcd_16
faaddd int bniGcd_16(BNWORD16 *a, unsigned alen, BNWORD16 *b, unsigned blen,
4ab2e5 ¤   unsigned *rlen);
267454 #endif
f7214b #ifndef bniInv_16
74da67 int bniInv_16( PGPMemoryMgrRef mgr, PGPBoolean secure,
47216c ¤   ¤   BNWORD16 *a, unsigned alen, BNWORD16 const *mod, unsigned mlen);
bc7454 #endif
4daf5a
0d1254 PGP_END_C_DECLARATIONS
39af5a
1b48f4 #endif /* Included_bni16_h */
--0a1e 0001b71064240100152 Page 1 of bni32.c
bc38e5 /*
4a765f ·* bni32.c - Low-level bignum routines, 32-bit version.
95775e ·*
ba68c2 ·* Written by Colin Plumb.
f1775e ·*
28933d ·* $Id: bni32.c,v 1.7 1998/05/14 19:07:21 cbertsch Exp $
42775e ·*
75e8e7 ·* NOTE: the magic constants "32" and "64" appear in many places in this
f4dd4e ·* file, including inside identifiers. ·Because it is not possible to
139667 ·* ask "#ifdef" of a macro expansion, it is not possible to use the
a9b031 ·* preprocessor to conditionalize these properly. ·Thus, this file is
62cef9 ·* intended to be edited with textual search and replace to produce
8ad844 ·* alternate word size versions. ·Any reference to the number of bits
c236c3 ·* in a word must be the string "32", and that string must not appear
7cbdc6 ·* otherwise. ·Any reference to twice this number must appear as "64",
06d7d6 ·* which likewise must not appear otherwise. ·Is that clear?
f7775e ·*
c59121 ·* Remember, when doubling the bit size replace the larger number (64)
60fabe ·* first, then the smaller (32). ·When halving the bit size, do the
ff0005 ·* opposite. ·Otherwise, things will get wierd. ·Also, be sure to replace
5cdfda ·* every instance that appears. ·(:%s/foo/bar/g in vi)
08775e ·*
82496a ·* These routines work with a pointer to the least-significant end of
5f2cb1 ·* an array of WORD32s. ·The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros
753864 ·* defined in bni.h (which expand to x on a big-edian machine and y on a
d54cbc ·* little-endian machine) are used to conditionalize the code to work
fcfc72 ·* either way. ·If you have no assembly primitives, it doesn't matter.
db83f3 ·* Note that on a big-endian machine, the least-significant-end pointer
ce144c ·* is ONE PAST THE END. ·The bytes are ptr[-1] through ptr[-len].
4f8d7a ·* On little-endian, they are ptr[0] through ptr[len-1]. ·This makes
9bfd96 ·* perfect sense if you consider pointers to point *between* bytes rather
1df32b ·* than at them.
f5775e ·*
58f6ef ·* Because the array index values are unsigned integers, ptr[-i]
0353f2 ·* may not work properly, since the index -i is evaluated as an unsigned,
8a0a10 ·* and if pointers are wider, zero-extension will produce a positive
14da4d ·* number rahter than the needed negative. ·The expression used in this
1eeb52 ·* code, *(ptr-i) will, however, work. ·(The array syntax is equivalent
e3fbc0 ·* to *(ptr+-i), which is a pretty subtle difference.)
8f775e ·*
07bcef ·* Many of these routines will get very unhappy if fed zero-length inputs.
2409f7 ·* They use pgpAssert() to enforce this. ·An higher layer of code must make
33aed6 ·* sure that these aren't called with zero-length inputs.
c5775e ·*
498e44 ·* Any of these routines can be replaced with more efficient versions
db26b0 ·* elsewhere, by just #defining their names. ·If one of the names
3cf8b6 ·* is #defined, the C code is not compiled in and no declaration is
0fcdae ·* made. ·Use the BNINCLUDE file to do that. ·Typically, you compile
81a2ad ·* asm subroutines with the same name and just, e.g.
386dfc ·* #define bniMulAdd1_32 bniMulAdd1_32
74775e ·*
829cb7 ·* If you want to write asm routines, start with bniMulAdd1_32().
376e67 ·* This is the workhorse of modular exponentiation. ·bniMulN1_32() is
4f364f ·* also used a fair bit, although not as much and it's defined in terms
e07eff ·* of bniMulAdd1_32 if that has a custom version. ·bniMulSub1_32 and
a439e8 ·* bniDiv21_32 are used in the usual division and remainder finding.
a88548 ·* (Not the Montgomery reduction used in modular exponentiation, though.)
1aeee6 ·* Once you have bniMulAdd1_32 defined, writing the other two should
350aae ·* be pretty easy. ·(Just make sure you get the sign of the subtraction
88e7b2 ·* in bniMulSub1_32 right - it's dest = dest - source * k.)
f9775e ·*
fe609b ·* The only definitions that absolutely need a double-word (BNWORD64)
fd7b5d ·* type are bniMulAdd1_32 and bniMulSub1_32; if those are provided,
4fc113 ·* the rest follows. ·bniDiv21_32, however, is a lot slower unless you
f1eff8 ·* have them, and bniModQ_32 takes after it. ·That one is used quite a
5170b6 ·* bit for prime sieving.
fe495d ·*/
fbaf5a
34e2ff #include "pgpConfig.h"
dbaf5a
ed38e5 /*
1b16cf ·* Some compilers complain about #if FOO if FOO isn't defined,
--a554 0008366e0a840100152 Page 2 of bni32.c
e259aa ·* so do the ANSI-mandated thing explicitly...
42495d ·*/
44c60f #ifndef NO_ASSERT_H
22154e #define NO_ASSERT_H 0
ab7454 #endif
72b552 #ifndef NO_STRING_H
3537dd #define NO_STRING_H 0
0f7454 #endif
268537 #ifndef HAVE_STRINGS_H
58025c #define HAVE_STRINGS_H 0
187454 #endif
1b101b #ifndef NEED_MEMORY_H
11ee50 #define NEED_MEMORY_H 0
3a7454 #endif
8faf5a
767668 #if !NO_STRING_H
d77210 #include <string.h>¤/* For memcpy */
15a752 #elif HAVE_STRINGS_H
a3f7c3 #include <strings.h>
3d7454 #endif
983c37 #if NEED_MEMORY_H
66c737 #include <memory.h>
207454 #endif
6faf5a
79a6ac #include "bni.h"
fe10de #include "bni32.h"
8021db #include "bnimem.h"
d28cb6 #include "bnlegal.h"
61af5a
ec4724 #include "bnkludge.h"
fea146 #include "pgpDebug.h"
41af5a
cce77e #ifndef BNWORD32
f5c47d #error 32-bit bignum library requires a 32-bit data type
c07454 #endif
9daf5a
4ebfe9 /* Make sure the copyright notice gets included */
1c5ac5 volatile const char * volatile const bniCopyright_32 = bnCopyright;
f4af5a
ace387 /* If this is defined, include bnYield() calls */
7b074b #if BNYIELD
5a976d extern int (*bnYield)(void);¤   /* From bn.c */
447454 #endif
a7af5a
a038e5 /*
c9d5df ·* Most of the multiply (and Montgomery reduce) routines use an outer
459462 ·* loop that iterates over one of the operands - a so-called operand
c8398d ·* scanning approach. ·One big advantage of this is that the assembly
191aea ·* support routines are simpler. ·The loops can be rearranged to have
e3b971 ·* an outer loop that iterates over the product, a so-called product
5d6c0d ·* scanning approach. ·This has the advantage of writing less data
e8c3ee ·* and doing fewer adds to memory, so is supposedly faster. ·Some
1580d7 ·* code has been written using a product-scanning approach, but
b83d3c ·* it appears to be slower, so it is turned off by default. ·Some
4a5e9d ·* experimentation would be appreciated.
1c775e ·*
d06dd6 ·* (The code is also annoying to get right and not very well commented,
a46688 ·* one of my pet peeves about math libraries. ·I'm sorry.)
02495d ·*/
1d7621 #ifndef PRODUCT_SCAN
6f1212 #define PRODUCT_SCAN 0
137454 #endif
26af5a
7b38e5 /*
1f2e0a ·* Copy an array of words. ·<Marvin mode on> ·Thrilling, isn't it? </Marvin>
3b01c1 ·* This is a good example of how the byte offsets and BIGLITTLE() macros work.
3bb38e ·* Another alternative would have been
a691e1 ·* memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD32)), but I find that
ce84f4 ·* putting operators into conditional macros is confusing.
26495d ·*/
cfdf20 #ifndef bniCopy_32
83314a void
--20e3 0007c5a7e2740100152 Page 3 of bni32.c
201f95 bniCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len)
2abb36 {
de0967 ¤   memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src),
cada8b ¤   ·······len * sizeof(*src));
2aefe6 }
c1f3de #endif /* !bniCopy_32 */
f1af5a
3c38e5 /*
e93e9e ·* Fill n words with zero. ·This does it manually rather than calling
be6f32 ·* memset because it can assume alignment to make things faster while
01c78d ·* memset can't. ·Note how big-endian numbers are naturally addressed
fa2867 ·* using predecrement, while little-endian is postincrement.
b0495d ·*/
844682 #ifndef bniZero_32
67314a void
115f94 bniZero_32(BNWORD32 *num, unsigned len)
3ebb36 {
42e87e ¤   while (len--)
d284f4 ¤   ¤   BIGLITTLE(*--num,*num++) = 0;
b2efe6 }
6187f4 #endif /* !bniZero_32 */
60af5a
9e38e5 /*
c85fe5 ·* Negate an array of words.
2f3551 ·* Negation is subtraction from zero. ·Negating low-order words
2baf4a ·* entails doing nothing until a non-zero word is hit. ·Once that
eda81f ·* is negated, a borrow is generated and never dies until the end
6ec1bd ·* of the number is hit. ·Negation with borrow, -x-1, is the same as ~x.
cd24aa ·* Repeat that until the end of the number.
b9775e ·*
6bbb91 ·* Doesn't return borrow out because that's pretty useless - it's
3be078 ·* always set unless the input is 0, which is easy to notice in
2b0df0 ·* normalized form.
2c495d ·*/
99a6aa #ifndef bniNeg_32
7d314a void
ab0333 bniNeg_32(BNWORD32 *num, unsigned len)
76bb36 {
0986c8 ¤   pgpAssert(len);
2aaf5a
11043a ¤   /* Skip low-order zero words */
9dcadc ¤   while (BIGLITTLE(*--num,*num) == 0) {
dd253f ¤   ¤   if (!--len)
410ecc ¤   ¤   ¤   return;
54c728 ¤   ¤   LITTLE(num++;)
5a9371 ¤   }
0b87c2 ¤   /* Negate the lowest-order non-zero word */
4ca8e3 ¤   *num = -*num;
78e4e5 ¤   /* Complement all the higher-order words */
a7e1ea ¤   while (--len) {
fe10b0 ¤   ¤   BIGLITTLE(--num,++num);
6348d8 ¤   ¤   *num = ~*num;
aa9371 ¤   }
09efe6 }
e4a09f #endif /* !bniNeg_32 */
64af5a
28af5a
cc38e5 /*
713c21 ·* bniAdd1_32: add the single-word "carry" to the given number.
f0976d ·* Used for minor increments and propagating the carry after
ce674c ·* adding in a shorter bignum.
94775e ·*
25ce8e ·* Technique: If we have a double-width word, presumably the compiler
d7afd8 ·* can add using its carry in inline code, so we just use a larger
97f5de ·* accumulator to compute the carry from the first addition.
82f394 ·* If not, it's more complex. ·After adding the first carry, which may
94696d ·* be > 1, compare the sum and the carry. ·If the sum wraps (causing a
9cc7d9 ·* carry out from the addition), the result will be less than each of the
7205c7 ·* inputs, since the wrap subtracts a number (2^32) which is larger than
f79c68 ·* the other input can possibly be. ·If the sum is >= the carry input,
b7739c ·* return success immediately.
7ca2cb ·* In either case, if there is a carry, enter a loop incrementing words
--5f8f 000819a0e4840100152 Page 4 of bni32.c
d66969 ·* until one does not wrap. ·Since we are adding 1 each time, the wrap
00b4b5 ·* will be to 0 and we can test for equality.
95495d ·*/
fe6a6b #ifndef bniAdd1_32¤ /* If defined, it's provided as an asm subroutine */
1437e1 #ifdef BNWORD64
d2e6d9 BNWORD32
0f010f bniAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
9dbb36 {
b2d6e3 ¤   BNWORD64 t;
689c94 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return carry */
88af5a
2e6b26 ¤   t = (BNWORD64)BIGLITTLE(*--num,*num) + carry;
4f914a ¤   BIGLITTLE(*num,*num++) = (BNWORD32)t;
e03928 ¤   if ((t >> 32) == 0)
debbde ¤   ¤   return 0;
6ee1ea ¤   while (--len) {
4a2439 ¤   ¤   if (++BIGLITTLE(*--num,*num++) != 0)
678144 ¤   ¤   ¤   return 0;
f89371 ¤   }
6664b7 ¤   return 1;
45efe6 }
a6e939 #else /* no BNWORD64 */
8ee6d9 BNWORD32
90010f bniAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
6ebb36 {
0d9c94 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return carry */
7eaf5a
7b9c40 ¤   if ((BIGLITTLE(*--num,*num++) += carry) >= carry)
7dbbde ¤   ¤   return 0;
0be1ea ¤   while (--len) {
592439 ¤   ¤   if (++BIGLITTLE(*--num,*num++) != 0)
788144 ¤   ¤   ¤   return 0;
5d9371 ¤   }
2a64b7 ¤   return 1;
5cefe6 }
c47454 #endif
1a2d89 #endif/* !bniAdd1_32 */
91af5a
e438e5 /*
310df0 ·* bniSub1_32: subtract the single-word "borrow" from the given number.
be8db0 ·* Used for minor decrements and propagating the borrow after
8b455f ·* subtracting a shorter bignum.
d5775e ·*
e736de ·* Technique: Similar to the add, above. ·If there is a double-length type,
52c57d ·* use that to generate the first borrow.
3825ae ·* If not, after subtracting the first borrow, which may be > 1, compare
e27f2c ·* the difference and the *negative* of the carry. ·If the subtract wraps
738a8c ·* (causing a borrow out from the subtraction), the result will be at least
4a9bc7 ·* as large as -borrow. ·If the result < -borrow, then no borrow out has
2f9e3c ·* appeared and we may return immediately, except when borrow == 0. ·To
53e027 ·* deal with that case, use the identity that -x = ~x+1, and instead of
3e57ce ·* comparing < -borrow, compare for <= ~borrow.
df464d ·* Either way, if there is a borrow out, enter a loop decrementing words
d5fe08 ·* until a non-zero word is reached.
8a775e ·*
d67ab8 ·* Note the cast of ~borrow to (BNWORD32). ·If the size of an int is larger
87ef0a ·* than BNWORD32, C rules say the number is expanded for the arithmetic, so
ad47f5 ·* the inversion will be done on an int and the value won't be quite what
70bf20 ·* is expected.
a7495d ·*/
bb3a8f #ifndef bniSub1_32¤ /* If defined, it's provided as an asm subroutine */
fa37e1 #ifdef BNWORD64
eae6d9 BNWORD32
6d371f bniSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
bcbb36 {
0dd6e3 ¤   BNWORD64 t;
132df5 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return borrow */
0faf5a
8380dd ¤   t = (BNWORD64)BIGLITTLE(*--num,*num) - borrow;
4f914a ¤   BIGLITTLE(*num,*num++) = (BNWORD32)t;
993928 ¤   if ((t >> 32) == 0)
81bbde ¤   ¤   return 0;
--6ab6 0004eb7fd6040100152 Page 5 of bni32.c
f3e1ea ¤   while (--len) {
3adc4e ¤   ¤   if ((BIGLITTLE(*--num,*num++))-- != 0)
ed8144 ¤   ¤   ¤   return 0;
459371 ¤   }
9c64b7 ¤   return 1;
afefe6 }
9ee939 #else /* no BNWORD64 */
d3e6d9 BNWORD32
d9371f bniSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
5bbb36 {
d22df5 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return borrow */
22af5a
c0a1b4 ¤   if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD32)~borrow)
b5bbde ¤   ¤   return 0;
9be1ea ¤   while (--len) {
44dc4e ¤   ¤   if ((BIGLITTLE(*--num,*num++))-- != 0)
928144 ¤   ¤   ¤   return 0;
a29371 ¤   }
e464b7 ¤   return 1;
ecefe6 }
e97454 #endif
284d8d #endif /* !bniSub1_32 */
1baf5a
4b38e5 /*
2fafe6 ·* bniAddN_32: add two bignums of the same length,
c8bdf0 ·* returning the carry (0 or 1).
4391db ·* One of the building blocks, along with bniAdd1, of adding two bignums of
5ba1e9 ·* differing lengths.
ab775e ·*
8b2251 ·* Technique: Maintain a word of carry. ·If there is no double-width type,
817ff1 ·* use the same technique as in bniAdd1, above, to maintain the carry by
8e3cda ·* comparing the inputs. ·Adding the carry sources is used as an OR operator;
967836 ·* at most one of the two comparisons can possibly be true. ·The first can
4dd0d2 ·* only be true if carry == 1 and x, the result, is 0. ·In that case the
c420dc ·* second can't possibly be true.
b6495d ·*/
c514dc #ifndef bniAddN_32
a037e1 #ifdef BNWORD64
49e6d9 BNWORD32
52c06d bniAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
dbbb36 {
c5d6e3 ¤   BNWORD64 t;
24af5a
ad5334 ¤   pgpAssert(len > 0);
1daf5a
fe80b8 ¤   t = (BNWORD64)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++);
0829ae ¤   BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
c7e1ea ¤   while (--len) {
a3e5d3 ¤   ¤   t = (BNWORD64)BIGLITTLE(*--num1,*num1) +
d6fe6f ¤   ¤   ····(BNWORD64)BIGLITTLE(*--num2,*num2++) + (t >> 32);
1b31fe ¤   ¤   BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
679371 ¤   }
58af5a
11cee8 ¤   return (BNWORD32)(t>>32);
a5efe6 }
0be939 #else /* no BNWORD64 */
4ee6d9 BNWORD32
4bc06d bniAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
b7bb36 {
7ee40e ¤   BNWORD32 x, carry = 0;
19af5a
4e5327 ¤   pgpAssert(len > 0);¤/* Alternative: change loop to test at start */
2daf5a
6243ab ¤   do {
f44bce ¤   ¤   x = BIGLITTLE(*--num2,*num2++);
d64163 ¤   ¤   carry = (x += carry) < carry;
525b74 ¤   ¤   carry += (BIGLITTLE(*--num1,*num1++) += x) < x;
d9c57e ¤   } while (--len);
54af5a
2bb1fc ¤   return carry;
eaefe6 }
4e7454 #endif
--2cba 000c1162cc040100152 Page 6 of bni32.c
b1f44b #endif /* !bniAddN_32 */
91af5a
7f38e5 /*
261425 ·* bniSubN_32: add two bignums of the same length,
b4bdf0 ·* returning the carry (0 or 1).
7f6e07 ·* One of the building blocks, along with subn1, of subtracting two bignums of
08a1e9 ·* differing lengths.
af775e ·*
8f4d44 ·* Technique: If no double-width type is availble, maintain a word of borrow.
567b0e ·* First, add the borrow to the subtrahend (did you have to learn all those
7f33b3 ·* awful words in elementary school, too?), and if it overflows, set the
f8182f ·* borrow again. ·Then subtract the modified subtrahend from the next word
35d9f4 ·* of input, using the same technique as in subn1, above.
b2c4fa ·* Adding the borrows is used as an OR operator; at most one of the two
9ce246 ·* comparisons can possibly be true. ·The first can only be true if
dbf032 ·* borrow == 1 and x, the result, is 0. ·In that case the second can't
c4119d ·* possibly be true.
83775e ·*
edceeb ·* In the double-word case, (BNWORD32)-(t>>32) is subtracted, rather than
69b4a4 ·* adding t>>32, because the shift would need to sign-extend and that's
1c17f3 ·* not guaranteed to happen in ANSI C, even with signed types.
1d495d ·*/
5f762d #ifndef bniSubN_32
0737e1 #ifdef BNWORD64
28e6d9 BNWORD32
d5253f bniSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
a2bb36 {
5bd6e3 ¤   BNWORD64 t;
1aaf5a
ea5334 ¤   pgpAssert(len > 0);
aaaf5a
4d4292 ¤   t = (BNWORD64)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++);
5129ae ¤   BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
edaf5a
05e1ea ¤   while (--len) {
49b103 ¤   ¤   t = (BNWORD64)BIGLITTLE(*--num1,*num1) -
4c5c15 ¤   ¤   ····(BNWORD64)BIGLITTLE(*--num2,*num2++) -
a8a858 ¤   ¤   ····(BNWORD32)-(t >> 32);
fd31fe ¤   ¤   BIGLITTLE(*num1,*num1++) = (BNWORD32)t;
f19371 ¤   }
1caf5a
9e7a0c ¤   return -(BNWORD32)(t>>32);
a1efe6 }
34db21 #else
dae6d9 BNWORD32
ae253f bniSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len)
b0bb36 {
7b8370 ¤   BNWORD32 x, borrow = 0;
55af5a
155327 ¤   pgpAssert(len > 0);¤/* Alternative: change loop to test at start */
c5af5a
7543ab ¤   do {
084bce ¤   ¤   x = BIGLITTLE(*--num2,*num2++);
3a4b08 ¤   ¤   borrow = (x += borrow) < borrow;
5a021a ¤   ¤   borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD32)~x;
9ec57e ¤   } while (--len);
eeaf5a
3f1102 ¤   return borrow;
94efe6 }
eb7454 #endif
437446 #endif /* !bniSubN_32 */
6faf5a
972d21 #ifndef bniCmp_32
6638e5 /*
fcae3f ·* bniCmp_32: compare two bignums of equal length, returning the sign of
6f8209 ·* num1 - num2. (-1, 0 or +1).
8b9ec0 ·*·
a9e837 ·* Technique: Change the little-endian pointers to big-endian pointers
0c7660 ·* and compare from the most-significant end until a difference if found.
0ebd66 ·* When it is, figure out the sign of the difference and return it.
80495d ·*/
c14d2f int
--8cdf 00035d266a740100152 Page 7 of bni32.c
ca23f9 bniCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len)
42bb36 {
9ccce6 ¤   BIGLITTLE(num1 -= len, num1 += len);
cadf99 ¤   BIGLITTLE(num2 -= len, num2 += len);
93af5a
afcae5 ¤   while (len--) {
5dc2de ¤   ¤   if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) {
cedcf7 ¤   ¤   ¤   if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2))
bedd34 ¤   ¤   ¤   ¤   return -1;
a2bb8c ¤   ¤   ¤   else
951c2d ¤   ¤   ¤   ¤   return 1;
300fe4 ¤   ¤   }
cf9371 ¤   }
a03e6b ¤   return 0;
edefe6 }
38edb1 #endif /* !bniCmp_32 */
bbaf5a
cb38e5 /*
b528b4 ·* mul32_ppmmaa(ph,pl,x,y,a,b) is an optional routine that
31f2d6 ·* computes (ph,pl) = x * y + a + b. ·mul32_ppmma and mul32_ppmm
e98dbd ·* are simpler versions. ·If you want to be lazy, all of these
e91154 ·* can be defined in terms of the others, so here we create any
0fa26b ·* that have not been defined in terms of the ones that have been.
7a495d ·*/
42af5a
f9faaa /* Define ones with fewer a's in terms of ones with more a's */
4e89f5 #if !defined(mul32_ppmma) && defined(mul32_ppmmaa)
e85fe9 #define mul32_ppmma(ph,pl,x,y,a) mul32_ppmmaa(ph,pl,x,y,a,0)
7d7454 #endif
b7af5a
fa4bb0 #if !defined(mul32_ppmm) && defined(mul32_ppmma)
57d918 #define mul32_ppmm(ph,pl,x,y) mul32_ppmma(ph,pl,x,y,0)
187454 #endif
04af5a
ba38e5 /*
5e089e ·* Use this definition to test the mul32_ppmm-based operations on machines
1c0f41 ·* that do not provide mul32_ppmm. ·Change the final "0" to a "1" to
09925b ·* enable it.
4a495d ·*/
35dbe0 #if !defined(mul32_ppmm) && defined(BNWORD64) && 0¤ /* Debugging */
eda8d3 #define mul32_ppmm(ph,pl,x,y) \
fcbfb4 ¤   ({BNWORD64 _ = (BNWORD64)(x)*(y); (pl) = _; (ph) = _>>32;})
a37454 #endif
efaf5a
574767 #if defined(mul32_ppmm) && !defined(mul32_ppmma)
3268ca #define mul32_ppmma(ph,pl,x,y,a) \
fdf2f7 ¤   (mul32_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a))
8e7454 #endif
acaf5a
6d5f01 #if defined(mul32_ppmma) && !defined(mul32_ppmmaa)
cff8a7 #define mul32_ppmmaa(ph,pl,x,y,a,b) \
86890a ¤   (mul32_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b))
437454 #endif
4caf5a
ef38e5 /*
d8a08f ·* bniMulN1_32: Multiply an n-word input by a 1-word input and store the
61fe51 ·* n+1-word product. ·This uses either the mul32_ppmm and mul32_ppmma
a22ae3 ·* macros, or C multiplication with the BNWORD64 type. ·This uses mul32_ppmma
e274b1 ·* if available, assuming you won't bother defining it unless you can do
8f01e4 ·* better than the normal multiplication.
9f495d ·*/
a61bce #ifndef bniMulN1_32
c7bb0a #ifdef bniMulAdd1_32¤   /* If we have this asm primitive, use it. */
be314a void
6c924b bniMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
bebb36 {
de5b95 ¤   bniZero_32(out, len);
5813e2 ¤   BIGLITTLE(*(out-len),*(out+len)) = bniMulAdd1_32(out, in, len, k);
acefe6 }
008966 #elif defined(mul32_ppmm)
6a314a void
35924b bniMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
--c897 000e890935740100152 Page 8 of bni32.c
2cbb36 {
ca9282 ¤   BNWORD32 prod, carry, carryin;
acaf5a
0a5334 ¤   pgpAssert(len > 0);
50af5a
54947d ¤   BIG(--out;--in;);
8bc21f ¤   mul32_ppmm(carry, *out, *in, k);
54f1a6 ¤   LITTLE(out++;in++;)
d5af5a
0ee1ea ¤   while (--len) {
c06541 ¤   ¤   BIG(--out;--in;)
7fa85c ¤   ¤   carryin = carry;
c41a31 ¤   ¤   mul32_ppmma(carry, *out, *in, k, carryin);
e707c3 ¤   ¤   LITTLE(out++;in++;)
5d9371 ¤   }
2dddd0 ¤   BIGLITTLE(*--out,*out) = carry;
9eefe6 }
1f57ec #elif defined(BNWORD64)
3f314a void
b6924b bniMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
1bbb36 {
dbb582 ¤   BNWORD64 p;
7aaf5a
d95334 ¤   pgpAssert(len > 0);
5aaf5a
abcd9c ¤   p = (BNWORD64)BIGLITTLE(*--in,*in++) * k;
b567bb ¤   BIGLITTLE(*--out,*out++) = (BNWORD32)p;
79af5a
1ae1ea ¤   while (--len) {
a620f9 ¤   ¤   p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + (BNWORD32)(p >> 32);
517feb ¤   ¤   BIGLITTLE(*--out,*out++) = (BNWORD32)p;
669371 ¤   }
74bc93 ¤   BIGLITTLE(*--out,*out) = (BNWORD32)(p >> 32);
1fefe6 }
29db21 #else
f97ea3 #error No 32x32 -> 64 multiply available for 32-bit bignum package
7b7454 #endif
d613a9 #endif /* bniMulN1_32 */
41af5a
5c38e5 /*
a74bfd ·* bniMulAdd1_32: Multiply an n-word input by a 1-word input and add the
7072e0 ·* low n words of the product to the destination. ·*Returns the n+1st word
000f32 ·* of the product.* ·(That turns out to be more convenient than adding
045a71 ·* it into the destination and dealing with a possible unit carry out
b742d4 ·* of *that*.) ·This uses either the mul32_ppmma and mul32_ppmmaa macros,
b7d351 ·* or C multiplication with the BNWORD64 type.
ce775e ·*
a28e70 ·* If you're going to write assembly primitives, this is the one to
700dda ·* start with. ·It is by far the most commonly called function.
1f495d ·*/
f413d8 #ifndef bniMulAdd1_32
bf1b91 #if defined(mul32_ppmm)
79e6d9 BNWORD32
679a19 bniMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
ecbb36 {
6a9282 ¤   BNWORD32 prod, carry, carryin;
bcaf5a
dd5334 ¤   pgpAssert(len > 0);
7eaf5a
9b947d ¤   BIG(--out;--in;);
45d6bd ¤   carryin = *out;
50c283 ¤   mul32_ppmma(carry, *out, *in, k, carryin);
3df1a6 ¤   LITTLE(out++;in++;)
1eaf5a
39e1ea ¤   while (--len) {
fa53c8 ¤   ¤   BIG(--out;--in;);
11a85c ¤   ¤   carryin = carry;
3805ba ¤   ¤   mul32_ppmmaa(carry, prod, *in, k, carryin, *out);
a4ecd6 ¤   ¤   *out = prod;
8407c3 ¤   ¤   LITTLE(out++;in++;)
289371 ¤   }
e8af5a
--e0bc 0001e85d2dc40100152 Page 9 of bni32.c
dab1fc ¤   return carry;
72efe6 }
c857ec #elif defined(BNWORD64)
6ce6d9 BNWORD32
2b9a19 bniMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
d3bb36 {
21b582 ¤   BNWORD64 p;
09af5a
2f5334 ¤   pgpAssert(len > 0);
66af5a
8a3816 ¤   p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out);
94e110 ¤   BIGLITTLE(*out,*out++) = (BNWORD32)p;
11af5a
65e1ea ¤   while (--len) {
67bf18 ¤   ¤   p = (BNWORD64)BIGLITTLE(*--in,*in++) * k +
7ddd8d ¤   ¤   ····(BNWORD32)(p >> 32) + BIGLITTLE(*--out,*out);
52d8d5 ¤   ¤   BIGLITTLE(*out,*out++) = (BNWORD32)p;
f39371 ¤   }
a4af5a
11e8db ¤   return (BNWORD32)(p >> 32);
49efe6 }
f0db21 #else
867ea3 #error No 32x32 -> 64 multiply available for 32-bit bignum package
f17454 #endif
636728 #endif /* bniMulAdd1_32 */
f6af5a
a938e5 /*
fcac48 ·* bniMulSub1_32: Multiply an n-word input by a 1-word input and subtract the
d1843f ·* n-word product from the destination. ·Returns the n+1st word of the product.
5ae8a3 ·* This uses either the mul32_ppmm and mul32_ppmma macros, or
ee2ea8 ·* C multiplication with the BNWORD64 type.
84775e ·*
04ceaf ·* This is rather uglier than adding, but fortunately it's only used in
1d7917 ·* division which is not used too heavily.
52495d ·*/
ad7129 #ifndef bniMulSub1_32
371b91 #if defined(mul32_ppmm)
e7e6d9 BNWORD32
859796 bniMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
61bb36 {
679282 ¤   BNWORD32 prod, carry, carryin;
1faf5a
945334 ¤   pgpAssert(len > 0);
37af5a
81495e ¤   BIG(--in;)
8ae7b2 ¤   mul32_ppmm(carry, prod, *in, k);
4a745b ¤   LITTLE(in++;)
cadcb4 ¤   carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod;
80af5a
f0e1ea ¤   while (--len) {
482ce1 ¤   ¤   BIG(--in;);
4ba85c ¤   ¤   carryin = carry;
0e059c ¤   ¤   mul32_ppmma(carry, prod, *in, k, carryin);
c04ec1 ¤   ¤   LITTLE(in++;)
c1cf38 ¤   ¤   carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD32)~prod;
a29371 ¤   }
c4af5a
19b1fc ¤   return carry;
7eefe6 }
6b57ec #elif defined(BNWORD64)
92e6d9 BNWORD32
999796 bniMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
bdbb36 {
26b582 ¤   BNWORD64 p;
6fcd20 ¤   BNWORD32 carry, t;
fbaf5a
7a5334 ¤   pgpAssert(len > 0);
8aaf5a
d2cd9c ¤   p = (BNWORD64)BIGLITTLE(*--in,*in++) * k;
278593 ¤   t = BIGLITTLE(*--out,*out);
ae8fa4 ¤   carry = (BNWORD32)(p>>32) +
1e1a6b ¤   ¤   ¤   ((BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t);
--ff77 0000958d04140100152 Page 10 of bni32.c
e0af5a
32e1ea ¤   while (--len) {
780a52 ¤   ¤   p = (BNWORD64)BIGLITTLE(*--in,*in++) * k + carry;
1c0e6f ¤   ¤   t = BIGLITTLE(*--out,*out);
070458 ¤   ¤   carry = (BNWORD32)(p>>32) +
9c3f66 ¤   ¤   ¤   ( (BIGLITTLE(*out,*out++)=t-(BNWORD32)p) > t );
499371 ¤   }
0baf5a
a5b1fc ¤   return carry;
62efe6 }
d8db21 #else
387ea3 #error No 32x32 -> 64 multiply available for 32-bit bignum package
a67454 #endif
397382 #endif /* !bniMulSub1_32 */
caaf5a
7c38e5 /*
e94b6a ·* Shift n words left "shift" bits. ·0 < shift < 32. ·Returns the
762e41 ·* carry, any bits shifted off the left-hand side (0 <= carry < 2^shift).
e0495d ·*/
39eded #ifndef bniLshift_32
0de6d9 BNWORD32
09dc09 bniLshift_32(BNWORD32 *num, unsigned len, unsigned shift)
a1bb36 {
f99254 ¤   BNWORD32 x, carry;
d7af5a
dbe769 ¤   pgpAssert(shift > 0);
27e7ee ¤   pgpAssert(shift < 32);
ceaf5a
0a1e50 ¤   carry = 0;
71cae5 ¤   while (len--) {
1fcb1c ¤   ¤   BIG(--num;)
7df3b8 ¤   ¤   x = *num;
d82c6b ¤   ¤   *num = (x<<shift) | carry;
68c728 ¤   ¤   LITTLE(num++;)
01f6fc ¤   ¤   carry = x >> (32-shift);
ee9371 ¤   }
3ab1fc ¤   return carry;
96efe6 }
b3678a #endif /* !bniLshift_32 */
7daf5a
fb38e5 /*
d89f06 ·* An optimized version of the above, for shifts of 1.
53db8f ·* Some machines can use add-with-carry tricks for this.
b8495d ·*/
b03a52 #ifndef bniDouble_32
3fe6d9 BNWORD32
41cae6 bniDouble_32(BNWORD32 *num, unsigned len)
60bb36 {
d99254 ¤   BNWORD32 x, carry;
71af5a
9e1e50 ¤   carry = 0;
f4cae5 ¤   while (len--) {
12cb1c ¤   ¤   BIG(--num;)
37f3b8 ¤   ¤   x = *num;
2777ad ¤   ¤   *num = (x<<1) | carry;
b1c728 ¤   ¤   LITTLE(num++;)
c7845e ¤   ¤   carry = x >> (32-1);
879371 ¤   }
65b1fc ¤   return carry;
11efe6 }
15b53c #endif /* !bniDouble_32 */
52af5a
9238e5 /*
b37822 ·* Shift n words right "shift" bits. ·0 < shift < 32. ·Returns the
42f892 ·* carry, any bits shifted off the right-hand side (0 <= carry < 2^shift).
fd495d ·*/
e4be44 #ifndef bniRshift_32
24e6d9 BNWORD32
b2b707 bniRshift_32(BNWORD32 *num, unsigned len, unsigned shift)
1ebb36 {
eee40e ¤   BNWORD32 x, carry = 0;
09af5a
--f579 0005e77121b40100152 Page 11 of bni32.c
54e769 ¤   pgpAssert(shift > 0);
15e7ee ¤   pgpAssert(shift < 32);
e4af5a
b71189 ¤   BIGLITTLE(num -= len, num += len);
afaf5a
1ccae5 ¤   while (len--) {
2ec1a0 ¤   ¤   LITTLE(--num;)
6af3b8 ¤   ¤   x = *num;
4bf5aa ¤   ¤   *num = (x>>shift) | carry;
26cd94 ¤   ¤   BIG(num++;)
5d9b7c ¤   ¤   carry = x << (32-shift);
f69371 ¤   }
9a97c4 ¤   return carry >> (32-shift);
5aefe6 }
1b0ddc #endif /* !bniRshift_32 */
53af5a
9e95d7 /*·
0b5d82 ·* Multiply two numbers of the given lengths. ·prod and num2 may overlap,
9e2dfd ·* provided that the low len1 bits of prod are free. ·(This corresponds
4e999c ·* nicely to the place the result is returned from bniMontReduce_32.)
20775e ·*
84e9b9 ·* TODO: Use Karatsuba multiply. ·The overlap constraints may have
a20cb9 ·* to get rewhacked.
69495d ·*/
350b98 #ifndef bniMul_32
98314a void
046b17 bniMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1,
5c84e5 ··························BNWORD32 const *num2, unsigned len2)
e1bb36 {
03157a ¤   /* Special case of zero */
f4fee4 ¤   if (!len1 || !len2) {
dd2f59 ¤   ¤   bniZero_32(prod, len1+len2);
f199bf ¤   ¤   return;
bf9371 ¤   }
3caf5a
025dc0 ¤   /* Multiply first word */
0678f9 ¤   bniMulN1_32(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
33af5a
2ed8af ¤   /*
5fad33 ¤   ·* Add in subsequent words, storing the most significant word,
022a88 ¤   ·* which is new each time.
02a4e3 ¤   ·*/
e1ae79 ¤   while (--len2) {
71df7f ¤   ¤   BIGLITTLE(--prod,prod++);
56ef4a ¤   ¤   BIGLITTLE(*(prod-len1-1),*(prod+len1)) =
427d00 ¤   ¤   ¤   bniMulAdd1_32(prod, num1, len1,
cf64a3 ¤   ¤   ¤   ¤   BIGLITTLE(*--num2,*num2++));
329371 ¤   }
b4efe6 }
af8c0e #endif /* !bniMul_32 */
5baf5a
3638e5 /*
64f4b2 ·* bniMulX_32 is a square multiply - both inputs are the same length.
df73d5 ·* It's normally just a macro wrapper around the general multiply,
ba9a0a ·* but might be implementable in assembly more efficiently (such as
aaee4d ·* when product scanning).
53495d ·*/
39ab22 #ifndef bniMulX_32
1a56cb #if defined(BNWORD64) && PRODUCT_SCAN
bc38e5 /*
013384 ·* Test code to see whether product scanning is any faster. ·It seems
e49f49 ·* to make the C code slower, so PRODUCT_SCAN is not defined.
43495d ·*/
372978 static void
2ba2e0 bniMulX_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2,
636094 ¤   unsigned len)
87bb36 {
dfea2d ¤   BNWORD64 x, y;
8dd229 ¤   BNWORD32 const *p1, *p2;
9050fc ¤   unsigned carry;
a907cb ¤   unsigned i, j;
5eaf5a
--ecd2 0006cd085c640100152 Page 12 of bni32.c
6d157a ¤   /* Special case of zero */
1a4404 ¤   if (!len)
0499bf ¤   ¤   return;
1baf5a
f4b61e ¤   x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
0597fc ¤   BIGLITTLE(*--prod, *prod++) = (BNWORD32)x;
c3a5c7 ¤   x >>= 32;
74af5a
1e6dce ¤   for (i = 1; i < len; i++) {
1efcf3 ¤   ¤   carry = 0;
05f201 ¤   ¤   p1 = num1;
58515c ¤   ¤   p2 = BIGLITTLE(num2-i-1,num2+i+1);
7bcdd8 ¤   ¤   for (j = 0; j <= i; j++) {
de56ba ¤   ¤   ¤   BIG(y = (BNWORD64)*--p1 * *p2++;)
808557 ¤   ¤   ¤   LITTLE(y = (BNWORD64)*p1++ * *--p2;)
961ca0 ¤   ¤   ¤   x += y;
eedfb0 ¤   ¤   ¤   carry += (x < y);
ee0fe4 ¤   ¤   }
3ace64 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
8001eb ¤   ¤   x = (x >> 32) | (BNWORD64)carry << 32;
f19371 ¤   }
396dce ¤   for (i = 1; i < len; i++) {
bcfcf3 ¤   ¤   carry = 0;
b27f2d ¤   ¤   p1 = BIGLITTLE(num1-i,num1+i);
75429b ¤   ¤   p2 = BIGLITTLE(num2-len,num2+len);
f57807 ¤   ¤   for (j = i; j < len; j++) {
9456ba ¤   ¤   ¤   BIG(y = (BNWORD64)*--p1 * *p2++;)
758557 ¤   ¤   ¤   LITTLE(y = (BNWORD64)*p1++ * *--p2;)
3f1ca0 ¤   ¤   ¤   x += y;
c5dfb0 ¤   ¤   ¤   carry += (x < y);
b00fe4 ¤   ¤   }
bdce64 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
c101eb ¤   ¤   x = (x >> 32) | (BNWORD64)carry << 32;
ef9371 ¤   }
1767c5 ¤
b04e9f ¤   BIGLITTLE(*--prod,*prod) = (BNWORD32)x;
5cefe6 }
96203b #else /* !defined(BNWORD64) || !PRODUCT_SCAN */
ff7015 /* Default trivial macro definition */
4bf80f #define bniMulX_32(prod, num1, num2, len) bniMul_32(prod, num1, len, num2, len)
532536 #endif /* !defined(BNWORD64) || !PRODUCT_SCAN */
ec0e66 #endif /* !lbmMulX_32 */
3aaf5a
eb86d3 #if !defined(bniMontMul_32) && defined(BNWORD64) && PRODUCT_SCAN
9638e5 /*
10b707 ·* Test code for product-scanning multiply. ·This seems to slow the C
96f14b ·* code down rather than speed it up.
3ee2e9 ·* This does a multiply and Montgomery reduction together, using the
3a053f ·* same loops. ·The outer loop scans across the product, twice.
3a093d ·* The first pass computes the low half of the product and the
728f6c ·* Montgomery multipliers. ·These are stored in the product array,
e89620 ·* which contains no data as of yet. ·x and carry add up the columns
fe17c7 ·* and propagate carries forward.
06775e ·*
e0bdb8 ·* The second half multiplies the upper half, adding in the modulus
6e2380 ·* times the Montgomery multipliers. ·The results of this multiply
f7fa30 ·* are stored.
4e495d ·*/
802978 static void
3a71af bniMontMul_32(BNWORD32 *prod, BNWORD32 const *num1, BNWORD32 const *num2,
820632 ¤   BNWORD32 const *mod, unsigned len, BNWORD32 inv)
b9bb36 {
a4ea2d ¤   BNWORD64 x, y;
7d5f5a ¤   BNWORD32 const *p1, *p2, *pm;
97736c ¤   BNWORD32 *pp;
72f9fc ¤   BNWORD32 t;
9150fc ¤   unsigned carry;
8b07cb ¤   unsigned i, j;
5eaf5a
d4157a ¤   /* Special case of zero */
5c4404 ¤   if (!len)
6c99bf ¤   ¤   return;
--57fd 0003bba89a740100152 Page 13 of bni32.c
e0af5a
f8d8af ¤   /*
c44576 ¤   ·* This computes directly into the high half of prod, so just
159d34 ¤   ·* shift the pointer and consider prod only "len" elements long
2aebc4 ¤   ·* for the rest of the code.
6ea4e3 ¤   ·*/
1c8517 ¤   BIGLITTLE(prod -= len, prod += len);
efaf5a
84a702 ¤   /* Pass 1 - compute Montgomery multipliers */
4d1ffe ¤   /* First iteration can have certain simplifications. */
c8b61e ¤   x = (BNWORD64)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
19d86a ¤   BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD32)x;
6224ec ¤   y = (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]);
419163 ¤   x += y;
6a12f8 ¤   /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */
b227d4 ¤   carry = (x < y);
29c2d3 ¤   pgpAssert((BNWORD32)x == 0);
a95258 ¤   x = x >> 32 | (BNWORD64)carry << 32;
ddaf5a
e56dce ¤   for (i = 1; i < len; i++) {
4cfcf3 ¤   ¤   carry = 0;
07f201 ¤   ¤   p1 = num1;
3a515c ¤   ¤   p2 = BIGLITTLE(num2-i-1,num2+i+1);
3a47bb ¤   ¤   pp = prod;
dad39c ¤   ¤   pm = BIGLITTLE(mod-i-1,mod+i+1);
f5f8a4 ¤   ¤   for (j = 0; j < i; j++) {
79c072 ¤   ¤   ¤   y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
cc1ca0 ¤   ¤   ¤   x += y;
86dfb0 ¤   ¤   ¤   carry += (x < y);
c9115f ¤   ¤   ¤   y = (BNWORD64)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm);
bd1ca0 ¤   ¤   ¤   x += y;
68dfb0 ¤   ¤   ¤   carry += (x < y);
cf0fe4 ¤   ¤   }
fd6770 ¤   ¤   y = (BNWORD64)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]);
9e8bd3 ¤   ¤   x += y;
a456e4 ¤   ¤   carry += (x < y);
121cca ¤   ¤   pgpAssert(BIGLITTLE(pp == prod-i, pp == prod+i));
605c7d ¤   ¤   BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD32)x;
0e35b5 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-1, pm == mod+1));
c32e85 ¤   ¤   y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]);
ee8bd3 ¤   ¤   x += y;
4356e4 ¤   ¤   carry += (x < y);
32ffbb ¤   ¤   pgpAssert((BNWORD32)x == 0);
5954e0 ¤   ¤   x = x >> 32 | (BNWORD64)carry << 32;
989371 ¤   }
2daf5a
b4d239 ¤   /* Pass 2 - compute reduced product and store */
9b6dce ¤   for (i = 1; i < len; i++) {
95fcf3 ¤   ¤   carry = 0;
4f7f2d ¤   ¤   p1 = BIGLITTLE(num1-i,num1+i);
7b429b ¤   ¤   p2 = BIGLITTLE(num2-len,num2+len);
b00805 ¤   ¤   pm = BIGLITTLE(mod-i,mod+i);
10a573 ¤   ¤   pp = BIGLITTLE(prod-len,prod+len);
607807 ¤   ¤   for (j = i; j < len; j++) {
4ac072 ¤   ¤   ¤   y = (BNWORD64)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
9b1ca0 ¤   ¤   ¤   x += y;
b9dfb0 ¤   ¤   ¤   carry += (x < y);
e94706 ¤   ¤   ¤   y = (BNWORD64)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp);
0f1ca0 ¤   ¤   ¤   x += y;
99dfb0 ¤   ¤   ¤   carry += (x < y);
800fe4 ¤   ¤   }
9470a3 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-len, pm == mod+len));
dd1cca ¤   ¤   pgpAssert(BIGLITTLE(pp == prod-i, pp == prod+i));
1d37f5 ¤   ¤   BIGLITTLE(pp[0],pp[-1]) = (BNWORD32)x;
cf01eb ¤   ¤   x = (x >> 32) | (BNWORD64)carry << 32;
ae9371 ¤   }
92af5a
03f753 ¤   /* Last round of second half, simplified. */
82d98e ¤   BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD32)x;
8020f7 ¤   carry = (x >> 32);
e8af5a
3ba53b ¤   while (carry)
--66f6 00045218e4e40100152 Page 14 of bni32.c
84a968 ¤   ¤   carry -= bniSubN_32(prod, mod, len);
dc81b9 ¤   while (bniCmp_32(prod, mod, len) >= 0)
6f0147 ¤   ¤   (void)bniSubN_32(prod, mod, len);
21efe6 }
9b25f5 /* Suppress later definition */
255a5e #define bniMontMul_32 bniMontMul_32
b07454 #endif
5faf5a
a0b6f4 #if !defined(bniSquare_32) && defined(BNWORD64) && PRODUCT_SCAN
bd38e5 /*
37064e ·* Trial code for product-scanning squaring. ·This seems to slow the C
00f14b ·* code down rather than speed it up.
6b495d ·*/
9b314a void
3985ae bniSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len)
70bb36 {
96313e ¤   BNWORD64 x, y, z;
b3d229 ¤   BNWORD32 const *p1, *p2;
7550fc ¤   unsigned carry;
9407cb ¤   unsigned i, j;
f1af5a
14157a ¤   /* Special case of zero */
504404 ¤   if (!len)
eb99bf ¤   ¤   return;
a7af5a
7861d6 ¤   /* Word 0 of product */
05111a ¤   x = (BNWORD64)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]);
da97fc ¤   BIGLITTLE(*--prod, *prod++) = (BNWORD32)x;
77a5c7 ¤   x >>= 32;
feaf5a
febe1a ¤   /* Words 1 through len-1 */
fb6dce ¤   for (i = 1; i < len; i++) {
d7fcf3 ¤   ¤   carry = 0;
042b1f ¤   ¤   y = 0;
e77bd5 ¤   ¤   p1 = num;
49f73f ¤   ¤   p2 = BIGLITTLE(num-i-1,num+i+1);
632b7b ¤   ¤   for (j = 0; j < (i+1)/2; j++) {
9437af ¤   ¤   ¤   BIG(z = (BNWORD64)*--p1 * *p2++;)
a2e442 ¤   ¤   ¤   LITTLE(z = (BNWORD64)*p1++ * *--p2;)
97727b ¤   ¤   ¤   y += z;
2a7bc2 ¤   ¤   ¤   carry += (y < z);
160fe4 ¤   ¤   }
343099 ¤   ¤   y += z = y;
692289 ¤   ¤   carry += carry + (y < z);
ccd10c ¤   ¤   if ((i & 1) == 0) {
b5d553 ¤   ¤   ¤   pgpAssert(BIGLITTLE(p1-1 == p2, p1 == p2-1));
2054de ¤   ¤   ¤   BIG(z = (BNWORD64)*p2 * *p2;)
950425 ¤   ¤   ¤   LITTLE(z = (BNWORD64)*p1 * *p1;)
e1727b ¤   ¤   ¤   y += z;
fb7bc2 ¤   ¤   ¤   carry += (y < z);
b60fe4 ¤   ¤   }
af8bd3 ¤   ¤   x += y;
5756e4 ¤   ¤   carry += (x < y);
12ce64 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
7a01eb ¤   ¤   x = (x >> 32) | (BNWORD64)carry << 32;
399371 ¤   }
aa852e ¤   /* Words len through 2*len-2 */
056dce ¤   for (i = 1; i < len; i++) {
5afcf3 ¤   ¤   carry = 0;
c62b1f ¤   ¤   y = 0;
117e3e ¤   ¤   p1 = BIGLITTLE(num-i,num+i);
652d6b ¤   ¤   p2 = BIGLITTLE(num-len,num+len);
22ca30 ¤   ¤   for (j = 0; j < (len-i)/2; j++) {
0437af ¤   ¤   ¤   BIG(z = (BNWORD64)*--p1 * *p2++;)
aee442 ¤   ¤   ¤   LITTLE(z = (BNWORD64)*p1++ * *--p2;)
0a727b ¤   ¤   ¤   y += z;
6f7bc2 ¤   ¤   ¤   carry += (y < z);
7d0fe4 ¤   ¤   }
523099 ¤   ¤   y += z = y;
d22289 ¤   ¤   carry += carry + (y < z);
23bcf9 ¤   ¤   if ((len-i) & 1) {
45d553 ¤   ¤   ¤   pgpAssert(BIGLITTLE(p1-1 == p2, p1 == p2-1));
--631f 00000b1795540100152 Page 15 of bni32.c
3954de ¤   ¤   ¤   BIG(z = (BNWORD64)*p2 * *p2;)
e30425 ¤   ¤   ¤   LITTLE(z = (BNWORD64)*p1 * *p1;)
65727b ¤   ¤   ¤   y += z;
e07bc2 ¤   ¤   ¤   carry += (y < z);
ee0fe4 ¤   ¤   }
f88bd3 ¤   ¤   x += y;
7456e4 ¤   ¤   carry += (x < y);
27ce64 ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD32)x;
aa01eb ¤   ¤   x = (x >> 32) | (BNWORD64)carry << 32;
269371 ¤   }
df67c5 ¤
8ab240 ¤   /* Word 2*len-1 */
364e9f ¤   BIGLITTLE(*--prod,*prod) = (BNWORD32)x;
88efe6 }
da25f5 /* Suppress later definition */
29f47d #define bniSquare_32 bniSquare_32
5e7454 #endif
84af5a
7a38e5 /*
2ba533 ·* Square a number, using optimized squaring to reduce the number of
501f0f ·* primitive multiples that are executed. ·There may not be any
236dd9 ·* overlap of the input and output.
83775e ·*
6902ad ·* Technique: Consider the partial products in the multiplication
e972e6 ·* of "abcde" by itself:
ac775e ·*
f3de15 ·* ··············a ·b ·c ·d ·e
567669 ·* ···········* ·a ·b ·c ·d ·e
d41afb ·* ·········==================
bed8e6 ·* ·············ae be ce de ee
0abd78 ·* ··········ad bd cd dd de
f6e467 ·* ·······ac bc cc cd ce
3ddcf1 ·* ····ab bb bc bd be
c37dd1 ·* ·aa ab ac ad ae
e6775e ·*
a54e38 ·* Note that everything above the main diagonal:
77729a ·* ·············ae be ce de = (abcd) * e
5406bf ·* ··········ad bd cd ······= (abc) * d
e4eff2 ·* ·······ac bc ············= (ab) * c
828267 ·* ····ab ··················= (a) * b
58775e ·*
9ccef0 ·* is a copy of everything below the main diagonal:
196424 ·* ······················de
1363ff ·* ················cd ce
d285ae ·* ··········bc bd be
e05a25 ·* ····ab ac ad ae
9d775e ·*
ce9c36 ·* Thus, the sum is 2 * (off the diagonal) + diagonal.
56775e ·*
741615 ·* This is accumulated beginning with the diagonal (which
32d5d8 ·* consist of the squares of the digits of the input), which is then
119c50 ·* divided by two, the off-diagonal added, and multiplied by two
56874a ·* again. ·The low bit is simply a copy of the low bit of the
297b99 ·* input, so it doesn't need special care.
8a775e ·*
7496ea ·* TODO: Merge the shift by 1 with the squaring loop.
0a35e2 ·* TODO: Use Karatsuba. ·(a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W.
14495d ·*/
21dbc8 #ifndef bniSquare_32
61314a void
8a85ae bniSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len)
aabb36 {
a9f9fc ¤   BNWORD32 t;
57cb60 ¤   BNWORD32 *prodx = prod;¤¤   /* Working copy of the argument */
a7bc1f ¤   BNWORD32 const *numx = num;¤/* Working copy of the argument */
31a2af ¤   unsigned lenx = len;¤   ¤   /* Working copy of the argument */
3daf5a
5f4404 ¤   if (!len)
9499bf ¤   ¤   return;
f8af5a
2d0677 ¤   /* First, store all the squares */
000a75 ¤   while (lenx--) {
--0805 0003ec16fc940100152 Page 16 of bni32.c
a39ca9 #ifdef mul32_ppmm
cce180 ¤   ¤   BNWORD32 ph, pl;
54499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
929af7 ¤   ¤   mul32_ppmm(ph,pl,t,t);
68eac4 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = pl;
b989a5 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = ph;
1ecbbf #elif defined(BNWORD64) /* use BNWORD64 */
6c22f1 ¤   ¤   BNWORD64 p;
1a499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
2b5f9d ¤   ¤   p = (BNWORD64)t * t;
97dd3d ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)p;
814c4e ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = (BNWORD32)(p>>32);
761d50 #else¤  /* Use bniMulN1_32 */
145403 ¤   ¤   t = BIGLITTLE(numx[-1],*numx);
d128f1 ¤   ¤   bniMulN1_32(prodx, numx, 1, t);
f49d54 ¤   ¤   BIGLITTLE(--numx,numx++);
0e0cad ¤   ¤   BIGLITTLE(prodx -= 2, prodx += 2);
697454 #endif
739371 ¤   }
236220 ¤   /* Then, shift right 1 bit */
38a513 ¤   (void)bniRshift_32(prod, 2*len, 1);
53af5a
4fba8b ¤   /* Then, add in the off-diagonal sums */
0aa223 ¤   lenx = len;
2c9ff9 ¤   numx = num;
1444f6 ¤   prodx = prod;
6c23f3 ¤   while (--lenx) {
48499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
4b1fab ¤   ¤   BIGLITTLE(--prodx,prodx++);
fe9d57 ¤   ¤   t = bniMulAdd1_32(prodx, numx, lenx, t);
1a172c ¤   ¤   bniAdd1_32(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t);
931fab ¤   ¤   BIGLITTLE(--prodx,prodx++);
c89371 ¤   }
7eaf5a
b8ca8f ¤   /* Shift it back up */
b3536a ¤   bniDouble_32(prod, 2*len);
a4af5a
f745fb ¤   /* And set the low bit appropriately */
5a7f4b ¤   BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1;
7aefe6 }
bbbf7e #endif /* !bniSquare_32 */
4faf5a
5738e5 /*
5fd2b6 ·* bniNorm_32 - given a number, return a modified length such that the
22c010 ·* most significant digit is non-zero. ·Zero-length input is okay.
95495d ·*/
0bf4fb #ifndef bniNorm_32
81536c unsigned
802544 bniNorm_32(BNWORD32 const *num, unsigned len)
fabb36 {
f1788e ¤   BIGLITTLE(num -= len,num += len);
0cbd5b ¤   while (len && BIGLITTLE(*num++,*--num) == 0)
1c9647 ¤   ¤   --len;
9dbb7a ¤   return len;
a4efe6 }
d62bd1 #endif /* bniNorm_32 */
acaf5a
3138e5 /*
4812cb ·* bniBits_32 - return the number of significant bits in the array.
879a79 ·* It starts by normalizing the array. ·Zero-length input is okay.
a7cb59 ·* Then assuming there's anything to it, it fetches the high word,
1881cc ·* generates a bit length by multiplying the word length by 32, and
78c15c ·* subtracts off 32/2, 32/4, 32/8, ... bits if the high bits are clear.
e8495d ·*/
625a56 #ifndef bniBits_32
cd536c unsigned
c7cba0 bniBits_32(BNWORD32 const *num, unsigned len)
28bb36 {
eff9fc ¤   BNWORD32 t;
33743f ¤   unsigned i;
01af5a
3efbf4 ¤   len = bniNorm_32(num, len);
--5762 000faa9b44f40100152 Page 17 of bni32.c
8e5678 ¤   if (len) {
49027d ¤   ¤   t = BIGLITTLE(*(num-len),*(num+(len-1)));
40146d ¤   ¤   pgpAssert(t);
23ec50 ¤   ¤   len *= 32;
daa8c0 ¤   ¤   i = 32/2;
b84392 ¤   ¤   do {
ea01ae ¤   ¤   ¤   if (t >> i)
8bcfc5 ¤   ¤   ¤   ¤   t >>= i;
92bb8c ¤   ¤   ¤   else
f9e024 ¤   ¤   ¤   ¤   len -= i;
b603d7 ¤   ¤   } while ((i /= 2) != 0);
939371 ¤   }
7abb7a ¤   return len;
49efe6 }
04ee96 #endif /* bniBits_32 */
9aaf5a
6e38e5 /*
ce1bed ·* If defined, use hand-rolled divide rather than compiler's native.
4f6018 ·* If the machine doesn't do it in line, the manual code is probably
47aab8 ·* faster, since it can assume normalization and the fact that the
0776d9 ·* quotient will fit into 32 bits, which a general 64-bit divide
b6b8b7 ·* in a compiler's run-time library can't do.
2c495d ·*/
88d2c4 #ifndef BN_SLOW_DIVIDE_64
6a8fe1 /* Assume that divisors of more than thirty-two bits are slow */
d8ec2a #define BN_SLOW_DIVIDE_64 (64 > 0x20)
517454 #endif
5daf5a
8f38e5 /*
a9a297 ·* Return (nh<<32|nl) % d, and place the quotient digit into *q.
687bdc ·* It is guaranteed that nh < d, and that d is normalized (with its high
3f5ded ·* bit set). ·If we have a double-width type, it's easy. ·If not, ooh,
607c0f ·* yuk!
fb495d ·*/
fbe188 #ifndef bniDiv21_32
fdaeeb #if defined(BNWORD64) && !BN_SLOW_DIVIDE_64
23e6d9 BNWORD32
5b7da9 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
30bb36 {
7807ab ¤   BNWORD64 n = (BNWORD64)nh << 32 | nl;
e8af5a
36d586 ¤   /* Divisor must be normalized */
73e0d9 ¤   pgpAssert(d >> (32-1) == 1);
78af5a
1f94b0 ¤   *q = n / d;
a54a7d ¤   return n % d;
59efe6 }
76db21 #else
f638e5 /*
1119ca ·* This is where it gets ugly.
79775e ·*
74e007 ·* Do the division in two halves, using Algorithm D from section 4.3.1
4bb8a8 ·* of Knuth. ·Note Theorem B from that section, that the quotient estimate
a2a6e2 ·* is never more than the true quotient, and is never more than two
b02734 ·* too low.
11775e ·*
e3f95e ·* The mapping onto conventional long division is (everything a half word):
62e4ba ·* ·······_____________qh___ql_
375d43 ·* dh dl ) nh.h nh.l nl.h nl.l
87b6a5 ·* ············- (qh * d)
62c3aa ·* ···········-----------
1e2238 ·* ·············rrrr rrrr nl.l
5d6972 ·* ·················- (ql * d)
0b6a88 ·* ···············-----------
b2bc8e ·* ·················rrrr rrrr
f8775e ·*
be15e9 ·* The implicit 3/2-digit d*qh and d*ql subtractors are computed this way:
eb8d7d ·* ··First, estimate a q digit so that nh/dh works. ·Subtracting qh*dh from
e47db1 ·* ··the (nh.h nh.l) list leaves a 1/2-word remainder r. ·Then compute the
b49d8c ·* ··low part of the subtractor, qh * dl. ··This also needs to be subtracted
dbf9d1 ·* ··from (nh.h nh.l nl.h) to get the final remainder. ·So we take the
fa91f1 ·* ··remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and
--206a 0000da6571940100152 Page 18 of bni32.c
af6618 ·* ··try to subtract qh * dl from that. ·Since the remainder is 1/2-word
16c6dd ·* ··long, shifting and adding nl.h results in a single word r.
1188e0 ·* ··It is possible that the remainder we're working with, r, is less than
c32698 ·* ··the product qh * dl, if we estimated qh too high. ·The estimation
e01818 ·* ··technique can produce a qh that is too large (never too small), leading
ccbbcb ·* ··to r which is too small. ·In that case, decrement the digit qh, add
0ae8c0 ·* ··shifted dh to r (to correct for that error), and subtract dl from the
461da5 ·* ··product we're comparing r with. ·That's the "correct" way to do it, but
f0d269 ·* ··just adding dl to r instead of subtracting it from the product is
9e3c97 ·* ··equivalent and a lot simpler. ·You just have to watch out for overflow.
1c775e ·*
7b6b5a ·* ··The process is repeated with (rrrr rrrr nl.l) for the low digit of the
ebf69b ·* ··quotient ql.
0b775e ·*
6538c5 ·* The various uses of 32/2 for shifts are because of the note about
1d1e9c ·* automatic editing of this file at the very top of the file.
8e495d ·*/
fa2aa2 #define highhalf(x) ( (x) >> 32/2 )
2a279d #define lowhalf(x) ( (x) & (((BNWORD32)1 << 32/2)-1) )
6be6d9 BNWORD32
e47da9 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
21bb36 {
241a25 ¤   BNWORD32 dh = highhalf(d), dl = lowhalf(d);
782426 ¤   BNWORD32 qh, ql, prod, r;
33af5a
7fd586 ¤   /* Divisor must be normalized */
c0034a ¤   pgpAssert((d >> (32-1)) == 1);
41af5a
a6182e ¤   /* Do first half-word of division */
62c97b ¤   qh = nh / dh;
68e25e ¤   r = nh % dh;
c151b2 ¤   prod = qh * dl;
95af5a
26d8af ¤   /*
be389a ¤   ·* Add next half-word of numerator to remainder and correct.
e75820 ¤   ·* qh may be up to two too large.
7da4e3 ¤   ·*/
a94870 ¤   r = (r << (32/2)) | highhalf(nl);
0e482f ¤   if (r < prod) {
0feccd ¤   ¤   --qh; r += d;
34d103 ¤   ¤   if (r >= d && r < prod) {
26daa8 ¤   ¤   ¤   --qh; r += d;·
e60fe4 ¤   ¤   }
109371 ¤   }
1780c1 ¤   r -= prod;
8eaf5a
f2e034 ¤   /* Do second half-word of division */
ba3cab ¤   ql = r / dh;
b32bf1 ¤   r = r % dh;
22476c ¤   prod = ql * dl;
c1af5a
54643e ¤   r = (r << (32/2)) | lowhalf(nl);
9c482f ¤   if (r < prod) {
7cb298 ¤   ¤   --ql; r += d;
dcd103 ¤   ¤   if (r >= d && r < prod) {
c0752d ¤   ¤   ¤   --ql; r += d;
ec0fe4 ¤   ¤   }
d69371 ¤   }
9c80c1 ¤   r -= prod;
cfaf5a
afaa1d ¤   *q = (qh << (32/2)) | ql;
05af5a
2a8da5 ¤   return r;
53efe6 }
357454 #endif
b2427e #endif /* bniDiv21_32 */
72af5a
00af5a
2638e5 /*
113149 ·* In the division functions, the dividend and divisor are referred to
27cc61 ·* as "n" and "d", which stand for "numerator" and "denominator".
0d775e ·*
--aa7c 000ba7bb2f140100152 Page 19 of bni32.c
0882a1 ·* The quotient is (nlen-dlen+1) digits long. ·It may be overlapped with
3a3b4e ·* the high (nlen-dlen) words of the dividend, but one extra word is needed
b4df50 ·* on top to hold the top word.
55495d ·*/
f7af5a
1438e5 /*
9923cd ·* Divide an n-word number by a 1-word number, storing the remainder
7ad04d ·* and n-1 words of the n-word quotient. ·The high word is returned.
9abd9b ·* It IS legal for rem to point to the same address as n, and for
42eab3 ·* q to point one word higher.
02775e ·*
31cd77 ·* TODO: If BN_SLOW_DIVIDE_64, add a divnhalf_32 which uses 32-bit
ac11b4 ·* ······dividends if the divisor is half that long.
0dac82 ·* TODO: Shift the dividend on the fly to avoid the last division and
d62014 ·* ······instead have a remainder that needs shifting.
faf820 ·* TODO: Use reciprocals rather than dividing.
16495d ·*/
15981b #ifndef bniDiv1_32
c7e6d9 BNWORD32
f19ed7 bniDiv1_32(BNWORD32 *q, BNWORD32 *rem, BNWORD32 const *n, unsigned len,
8dda48 ¤   BNWORD32 d)
b2bb36 {
447dd8 ¤   unsigned shift;
069bf3 ¤   unsigned xlen;
cc2f25 ¤   BNWORD32 r;
6c00ef ¤   BNWORD32 qhigh;
eaaf5a
dc5334 ¤   pgpAssert(len > 0);
83ed56 ¤   pgpAssert(d);
d0af5a
9320c0 ¤   if (len == 1) {
e0ea40 ¤   ¤   r = *n;
6894a7 ¤   ¤   *rem = r%d;
b24092 ¤   ¤   return r/d;
ca9371 ¤   }
18af5a
191fab ¤   shift = 0;
afdca5 ¤   r = d;
c3061b ¤   xlen = 32/2;
2343ab ¤   do {
09d555 ¤   ¤   if (r >> xlen)
644bd3 ¤   ¤   ¤   r >>= xlen;
6f0e1d ¤   ¤   else
c6f0a7 ¤   ¤   ¤   shift += xlen;
411729 ¤   } while ((xlen /= 2) != 0);
d9be08 ¤   pgpAssert((d >> (32-1-shift)) == 1);
a01802 ¤   d <<= shift;
1daf5a
032980 ¤   BIGLITTLE(q -= len-1,q += len-1);
8b015b ¤   BIGLITTLE(n -= len,n += len);
bbaf5a
7429a3 ¤   r = BIGLITTLE(*n++,*--n);
097444 ¤   if (r < d) {
e3d3c6 ¤   ¤   qhigh = 0;
f5f037 ¤   } else {
aef48d ¤   ¤   qhigh = r/d;
33ee48 ¤   ¤   r %= d;
c89371 ¤   }
84af5a
091d7d ¤   xlen = len;
b42884 ¤   while (--xlen)
d980e2 ¤   ¤   r = bniDiv21_32(BIGLITTLE(q++,--q), r,
0b4662 ¤   ¤   ¤   ¤   BIGLITTLE(*n++,*--n), d);
9baf5a
71d8af ¤   /*
e45d19 ¤   ·* Final correction for shift - shift the quotient up "shift"
3686e9 ¤   ·* bits, and merge in the extra bits of quotient. ·Then reduce
38533a ¤   ·* the final remainder mod the real d.
69a4e3 ¤   ·*/
b75df3 ¤   if (shift) {
53aae5 ¤   ¤   d >>= shift;
ba6105 ¤   ¤   qhigh = (qhigh << shift) | bniLshift_32(q, len-1, shift);
--94de 0000e6135d840100152 Page 20 of bni32.c
ed14b8 ¤   ¤   BIGLITTLE(q[-1],*q) |= r/d;
64ee48 ¤   ¤   r %= d;
619371 ¤   }
7fe0a8 ¤   *rem = r;
8caf5a
d097ee ¤   return qhigh;
e2efe6 }
407454 #endif
34af5a
de38e5 /*
156e68 ·* This function performs a "quick" modulus of a number with a divisor
1280bd ·* d which is guaranteed to be at most sixteen bits, i.e. less than 65536.
622b4d ·* This applies regardless of the word size the library is compiled with.
a8775e ·*
04e96b ·* This function is important to prime generation, for sieving.
1c495d ·*/
7f8780 #ifndef bniModQ_32
36cc86 /* If there's a custom bniMod21_32, no normalization needed */
d1ffe6 #ifdef bniMod21_32
a7536c unsigned
63875c bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
b8bb36 {
37bfcd ¤   unsigned i, shift;
392f25 ¤   BNWORD32 r;
b2af5a
5c5334 ¤   pgpAssert(len > 0);
11af5a
1b015b ¤   BIGLITTLE(n -= len,n += len);
60af5a
1e10e0 ¤   /* Try using a compare to avoid the first divide */
7c29a3 ¤   r = BIGLITTLE(*n++,*--n);
42132b ¤   if (r >= d)
a3ee48 ¤   ¤   r %= d;
5f9fd1 ¤   while (--len)
5d4bb5 ¤   ¤   r = bniMod21_32(r, BIGLITTLE(*n++,*--n), d);
e3af5a
2a8da5 ¤   return r;
87efe6 }
c10d36 #elif defined(BNWORD64) && !BN_SLOW_DIVIDE_64
32536c unsigned
b4875c bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
10bb36 {
482f25 ¤   BNWORD32 r;
67af5a
1fb24c ¤   if (!--len)
f26024 ¤   ¤   return BIGLITTLE(n[-1],n[0]) % d;
6caf5a
32015b ¤   BIGLITTLE(n -= len,n += len);
1e4a3b ¤   r = BIGLITTLE(n[-1],n[0]);
36af5a
1443ab ¤   do {
70d78e ¤   ¤   r = (BNWORD32)((((BNWORD64)r<<32) | BIGLITTLE(*n++,*--n)) % d);
bbc57e ¤   } while (--len);
76af5a
678da5 ¤   return r;
63efe6 }
ac3f5a #elif 32 >= 0x20
1838e5 /*
b70ce5 ·* If the single word size can hold 65535*65536, then this function
a3461a ·* is avilable.
57495d ·*/
7795bc #ifndef highhalf
132aa2 #define highhalf(x) ( (x) >> 32/2 )
6d6ae1 #define lowhalf(x) ( (x) & ((1 << 32/2)-1) )
bc7454 #endif
fe536c unsigned
ce875c bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
79bb36 {
a2f656 ¤   BNWORD32 r, x;
47af5a
ba015b ¤   BIGLITTLE(n -= len,n += len);
0eaf5a
--db0c 0000e77abcb40100152 Page 21 of bni32.c
a729a3 ¤   r = BIGLITTLE(*n++,*--n);
85e1ea ¤   while (--len) {
e5d6fc ¤   ¤   x = BIGLITTLE(*n++,*--n);
796a1f ¤   ¤   r = (r%d << 32/2) | highhalf(x);
79f27a ¤   ¤   r = (r%d << 32/2) | lowhalf(x);
fa9371 ¤   }
9faf5a
ff0b4f ¤   return r%d;
27efe6 }
18db21 #else
23be63 /* Default case - use bniDiv21_32 */
e8536c unsigned
0d875c bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
36bb36 {
3abfcd ¤   unsigned i, shift;
312f25 ¤   BNWORD32 r;
a6c041 ¤   BNWORD32 q;
0baf5a
ad5334 ¤   pgpAssert(len > 0);
3caf5a
301fab ¤   shift = 0;
b1dca5 ¤   r = d;
ac1066 ¤   i = 32;
363a3d ¤   while (i /= 2) {
7166eb ¤   ¤   if (r >> i)
eeda0b ¤   ¤   ¤   r >>= i;
640e1d ¤   ¤   else
f391e5 ¤   ¤   ¤   shift += i;
549371 ¤   }
daa069 ¤   pgpAssert(d >> (32-1-shift) == 1);
5f1802 ¤   d <<= shift;
3faf5a
60015b ¤   BIGLITTLE(n -= len,n += len);
57af5a
8a29a3 ¤   r = BIGLITTLE(*n++,*--n);
cc132b ¤   if (r >= d)
f3ee48 ¤   ¤   r %= d;
9eaf5a
5a9fd1 ¤   while (--len)
647141 ¤   ¤   r = bniDiv21_32(&q, r, BIGLITTLE(*n++,*--n), d);
b7af5a
12d8af ¤   /*
f85d19 ¤   ·* Final correction for shift - shift the quotient up "shift"
7686e9 ¤   ·* bits, and merge in the extra bits of quotient. ·Then reduce
c9533a ¤   ·* the final remainder mod the real d.
78a4e3 ¤   ·*/
4c5bcd ¤   if (shift)
c90a63 ¤   ¤   r %= d >> shift;
97af5a
358da5 ¤   return r;
82efe6 }
907454 #endif
1a5803 #endif /* bniModQ_32 */
76af5a
5d38e5 /*
f48f9d ·* Reduce n mod d and return the quotient. ·That is, find:
7090f4 ·* q = n / d;
2eb155 ·* n = n % d;
743baf ·* d is altered during the execution of this subroutine by normalizing it.
4632be ·* It must already have its most significant word non-zero; it is shifted
df8f79 ·* so its most significant bit is non-zero.
e5775e ·*
e3afe6 ·* The quotient q is nlen-dlen+1 words long. ·To make it possible to
fd6507 ·* overlap the quptient with the input (you can store it in the high dlen
3cce0a ·* words), the high word of the quotient is *not* stored, but is returned.
92496b ·* (If all you want is the remainder, you don't care about it, anyway.)
d1775e ·*
a2dabd ·* This uses algorithm D from Knuth (4.3.1), except that we do binary
dcd5f9 ·* (shift) normalization of the divisor. ·WARNING: This is hairy!
0c775e ·*
a35ddb ·* This function is used for some modular reduction, but it is not used in
0ed0fc ·* the modular exponentiation loops; they use Montgomery form and the
--982c 000fbeb0e2f40100152 Page 22 of bni32.c
dbaee4 ·* corresponding, more efficient, Montgomery reduction. ·This code
4510d2 ·* is needed for the conversion to Montgomery form, however, so it
21f6e7 ·* has to be here and it might as well be reasonably efficient.
70775e ·*
e3d437 ·* The overall operation is as follows ("top" and "up" refer to the
2dfeed ·* most significant end of the number; "bottom" and "down", the least):
3b775e ·*
dc9afe ·* - Shift the divisor up until the most significant bit is set.
ffa9b3 ·* - Shift the dividend up the same amount. ·This will produce the
f85a26 ·* ··correct quotient, and the remainder can be recovered by shifting
b17f2e ·* ··it back down the same number of bits. ·This may produce an overflow
a7697f ·* ··word, but the word is always strictly less than the most significant
484c66 ·* ··divisor word.
0bd315 ·* - Estimate the first quotient digit qhat:
f69aed ·* ··- First take the top two words (one of which is the overflow) of the
fb1d7a ·* ····dividend and divide by the top word of the divisor:
f94384 ·* ····qhat = (nh,nm)/dh. ·This qhat is >= the correct quotient digit
124e72 ·* ····and, since dh is normalized, it is at most two over.
3eb00c ·* ··- Second, correct by comparing the top three words. ·If
07e3f2 ·* ····(dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again.
396520 ·* ····The second iteration can be simpler because there can't be a third.
1e0134 ·* ····The computation can be simplified by subtracting dh*qhat from
e2e263 ·* ····both sides, suitably shifted. ·This reduces the left side to
4932b9 ·* ····dl*qhat. ·On the right, (nh,nm)-dh*qhat is simply the
1a468d ·* ····remainder r from (nh,nm)%dh, so the right is (r,nl).
c4208a ·* ····This produces qhat that is almost always correct and at
89d64f ·* ····most (prob ~ 2/2^32) one too high.
15666b ·* - Subtract qhat times the divisor (suitably shifted) from the dividend.
b01eae ·* ··If there is a borrow, qhat was wrong, so decrement it
44e18e ·* ··and add the divisor back in (once).
b32ab7 ·* - Store the final quotient digit qhat in the quotient array q.
e7775e ·*
61abaf ·* Repeat the quotient digit computation for successive digits of the
802a22 ·* quotient until the whole quotient has been computed. ·Then shift the
4b2dab ·* divisor and the remainder down to correct for the normalization.
c4775e ·*
c4d917 ·* TODO: Special case 2-word divisors.
46f820 ·* TODO: Use reciprocals rather than dividing.
31495d ·*/
0db6ef #ifndef divn_32
e0e6d9 BNWORD32
c45872 bniDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen)
05bb36 {
3b7237 ¤   BNWORD32 nh,nm,nl;¤ /* Top three words of the dividend */
7ea04d ¤   BNWORD32 dh,dl;¤/* Top two words of the divisor */
d24966 ¤   BNWORD32 qhat;¤ /* Extimate of quotient word */
c57448 ¤   BNWORD32 r;¤/* Remainder from quotient estimate division */
ee5707 ¤   BNWORD32 qhigh;¤/* High word of quotient */
7a27a0 ¤   unsigned i;¤/* Temp */
0f500c ¤   unsigned shift;¤/* Bits shifted by normalization */
1d74f3 ¤   unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */
da9ca9 #ifdef mul32_ppmm
cce702 ¤   BNWORD32 t32;
cf57ec #elif defined(BNWORD64)
3e9020 ¤   BNWORD64 t64;
5bb8da #else /* use bniMulN1_32 */
f85f28 ¤   BNWORD32 t2[2];
afcd0c #define t2high BIGLITTLE(t2[0],t2[1])
af64b5 #define t2low BIGLITTLE(t2[1],t2[0])
887454 #endif
abaf5a
ce872a ¤   pgpAssert(dlen);
639dbd ¤   pgpAssert(nlen >= dlen);
48af5a
5cd8af ¤   /*
16480b ¤   ·* Special cases for short divisors. ·The general case uses the
e0fd33 ¤   ·* top top 2 digits of the divisor (d) to estimate a quotient digit,
edc774 ¤   ·* so it breaks if there are fewer digits available. ·Thus, we need
ae8f21 ¤   ·* special cases for a divisor of length 1. ·A divisor of length
02ee27 ¤   ·* 2 can have a *lot* of administrivia overhead removed removed,
cf6e28 ¤   ·* so it's probably worth special-casing that case, too.
fba4e3 ¤   ·*/
--e5f5 00081fccb1d40100152 Page 23 of bni32.c
2bb547 ¤   if (dlen == 1)
f9f4f7 ¤   ¤   return bniDiv1_32(q, BIGLITTLE(n-1,n), n, nlen,
94bb59 ¤   ¤   ··················BIGLITTLE(d[-1],d[0]));
d8af5a
ebb177 #if 0
81d8af ¤   /*
be9c22 ¤   ·* @@@ This is not yet written... ·The general loop will do,
907741 ¤   ·* albeit less efficiently
20a4e3 ¤   ·*/
5d3ff3 ¤   if (dlen == 2) {
cc1b17 ¤   ¤   /*
d50fc2 ¤   ¤   ·* divisor two digits long:
7f1388 ¤   ¤   ·* use the 3/2 technique from Knuth, but we know
2bbd83 ¤   ¤   ·* it's exact.
f19de3 ¤   ¤   ·*/
96a363 ¤   ¤   dh = BIGLITTLE(d[-1],d[0]);
dd9d7f ¤   ¤   dl = BIGLITTLE(d[-2],d[1]);
d8fd08 ¤   ¤   shift = 0;
8a187b ¤   ¤   if ((sh & ((BNWORD32)1 << 32-1-shift)) == 0) {
91f603 ¤   ¤   ¤   do {
a85919 ¤   ¤   ¤   ¤   shift++;
108d54 ¤   ¤   ¤   } while (dh & (BNWORD32)1<<32-1-shift) == 0);
6c3e45 ¤   ¤   ¤   dh = dh << shift | dl >> (32-shift);
eced08 ¤   ¤   ¤   dl <<= shift;
18af5a
0aaf5a
650fe4 ¤   ¤   }
fdaf5a
6eaf5a
800e6b ¤   ¤   for (shift = 0; (dh & (BNWORD32)1 << 32-1-shift)) == 0;
3c48b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   shift++)
41b110 ¤   ¤   ¤   ;
811c78 ¤   ¤   if (shift) {
520fe4 ¤   ¤   }
336cd8 ¤   ¤   dh = dh << shift | dl >> (32-shift);
9cfd08 ¤   ¤   shift = 0;
1a3ddc ¤   ¤   while (dh
409371 ¤   }
407454 #endif
c2af5a
e053dc ¤   dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
400d5f ¤   pgpAssert(dh);
3caf5a
27d240 ¤   /* Normalize the divisor */
451fab ¤   shift = 0;
1f9edc ¤   r = dh;
8e2d75 ¤   i = 32/2;
4f43ab ¤   do {
cd66eb ¤   ¤   if (r >> i)
a7da0b ¤   ¤   ¤   r >>= i;
d70e1d ¤   ¤   else
7b91e5 ¤   ¤   ¤   shift += i;
59b881 ¤   } while ((i /= 2) != 0);
76af5a
85790d ¤   nh = 0;
885df3 ¤   if (shift) {
d9613c ¤   ¤   bniLshift_32(d, dlen, shift);
890141 ¤   ¤   dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
192130 ¤   ¤   nh = bniLshift_32(n, nlen, shift);
1d9371 ¤   }
25af5a
6b2e18 ¤   /* Assert that dh is now normalized */
c59fdb ¤   pgpAssert(dh >> (32-1));
1faf5a
e2ff88 ¤   /* Also get the second-most significant word of the divisor */
c6472b ¤   dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2)));
73af5a
6dd8af ¤   /*
6e007a ¤   ·* Adjust pointers: n to point to least significant end of first
14d7b5 ¤   ·* first subtract, and q to one the most-significant end of the
eae66e ¤   ·* quotient array.
81a4e3 ¤   ·*/
--6502 0007a7a8aa140100152 Page 24 of bni32.c
f63fac ¤   BIGLITTLE(n -= qlen,n += qlen);
7b4367 ¤   BIGLITTLE(q -= qlen,q += qlen);
36af5a
40eeb5 ¤   /* Fetch the most significant stored word of the dividend */
60e870 ¤   nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
5baf5a
28d8af ¤   /*
fc6d56 ¤   ·* Compute the first digit of the quotient, based on the
d70e82 ¤   ·* first two words of the dividend (the most significant of which
fe3605 ¤   ·* is the overflow word h).
fca4e3 ¤   ·*/
7921e5 ¤   if (nh) {
ba068c ¤   ¤   pgpAssert(nh < dh);
690c39 ¤   ¤   r = bniDiv21_32(&qhat, nh, nm, dh);
456eba ¤   } else if (nm >= dh) {
66a30b ¤   ¤   qhat = nm/dh;
7034b4 ¤   ¤   r = nm % dh;
dc2487 ¤   } else {¤   /* Quotient is zero */
fbd3c6 ¤   ¤   qhigh = 0;
e40a09 ¤   ¤   goto divloop;
089371 ¤   }
0daf5a
3310e1 ¤   /* Now get the third most significant word of the dividend */
945498 ¤   nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
b8af5a
39d8af ¤   /*
3d728b ¤   ·* Correct qhat, the estimate of quotient digit.
cafac8 ¤   ·* qhat can only be high, and at most two words high,
737c55 ¤   ·* so the loop can be unrolled and abbreviated.
cea4e3 ¤   ·*/
669ca9 #ifdef mul32_ppmm
dcbb46 ¤   mul32_ppmm(nm, t32, qhat, dl);
5b06de ¤   if (nm > r || (nm == r && t32 > nl)) {
c67f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
22eeae ¤   ¤   qhat--;
bf588d ¤   ¤   if ((r += dh) >= dh) {
78d3d4 ¤   ¤   ¤   nm -= (t32 < dl);
47fea2 ¤   ¤   ¤   t32 -= dl;
dbf07f ¤   ¤   ¤   if (nm > r || (nm == r && t32 > nl))
e20329 ¤   ¤   ¤   ¤   qhat--;
270fe4 ¤   ¤   }
c99371 ¤   }
3957ec #elif defined(BNWORD64)
96ab25 ¤   t64 = (BNWORD64)qhat * dl;
096803 ¤   if (t64 > ((BNWORD64)r << 32) + nl) {
fd7f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
d7eeae ¤   ¤   qhat--;
556578 ¤   ¤   if ((r += dh) > dh) {
28c606 ¤   ¤   ¤   t64 -= dl;
3e32ba ¤   ¤   ¤   if (t64 > ((BNWORD64)r << 32) + nl)
bb0329 ¤   ¤   ¤   ¤   qhat--;
110fe4 ¤   ¤   }
c69371 ¤   }
be40c8 #else /* Use bniMulN1_32 */
31f69f ¤   bniMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
49b1be ¤   if (t2high > r || (t2high == r && t2low > nl)) {
b67f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
92eeae ¤   ¤   qhat--;
78588d ¤   ¤   if ((r += dh) >= dh) {
645d65 ¤   ¤   ¤   t2high -= (t2low < dl);
f5a6d7 ¤   ¤   ¤   t2low -= dl;
03cf7a ¤   ¤   ¤   if (t2high > r || (t2high == r && t2low > nl))
490329 ¤   ¤   ¤   ¤   qhat--;
4e0fe4 ¤   ¤   }
799371 ¤   }
e17454 #endif
57af5a
f33d4c ¤   /* Do the multiply and subtract */
730f33 ¤   r = bniMulSub1_32(n, d, dlen, qhat);
42e204 ¤   /* If there was a borrow, add back once. */
8cfa13 ¤   if (r > nh) {¤  /* Borrow? */
7a206d ¤   ¤   (void)bniAddN_32(n, d, dlen);
--883e 000f22c32f640100152 Page 25 of bni32.c
f0eeae ¤   ¤   qhat--;
b39371 ¤   }
90af5a
2ca3ca ¤   /* Remember the first quotient digit. */
75bac6 ¤   qhigh = qhat;
d3af5a
1e7f0b ¤   /* Now, the main division loop: */
3c2a7b divloop:
a655ea ¤   while (qlen--) {
5eaf5a
b17aef ¤   ¤   /* Advance n */
708c3f ¤   ¤   nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
109f99 ¤   ¤   BIGLITTLE(++n,--n);
d0baed ¤   ¤   nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
9aaf5a
2460da ¤   ¤   if (nh == dh) {
a55986 ¤   ¤   ¤   qhat = ~(BNWORD32)0;
ab8a33 ¤   ¤   ¤   /* Optimized computation of r = (nh,nm) - qhat * dh */
baceb5 ¤   ¤   ¤   r = nh + nm;
d42398 ¤   ¤   ¤   if (r < nh)
9c58b7 ¤   ¤   ¤   ¤   goto subtract;
0f45a6 ¤   ¤   } else {
c2abd2 ¤   ¤   ¤   pgpAssert(nh < dh);
321469 ¤   ¤   ¤   r = bniDiv21_32(&qhat, nh, nm, dh);
5e0fe4 ¤   ¤   }
02af5a
840783 ¤   ¤   nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
869ca9 #ifdef mul32_ppmm
8dfab5 ¤   ¤   mul32_ppmm(nm, t32, qhat, dl);
459746 ¤   ¤   if (nm > r || (nm == r && t32 > nl)) {
9fc34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
e079dd ¤   ¤   ¤   qhat--;
bcd4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
6fe4dc ¤   ¤   ¤   ¤   nm -= (t32 < dl);
021c43 ¤   ¤   ¤   ¤   t32 -= dl;
c7a364 ¤   ¤   ¤   ¤   if (nm > r || (nm == r && t32 > nl))
11f54c ¤   ¤   ¤   ¤   ¤   qhat--;
47a3a6 ¤   ¤   ¤   }
800fe4 ¤   ¤   }
f457ec #elif defined(BNWORD64)
51275a ¤   ¤   t64 = (BNWORD64)qhat * dl;
ee9c80 ¤   ¤   if (t64 > ((BNWORD64)r<<32) + nl) {
a2c34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
c679dd ¤   ¤   ¤   qhat--;
5ed4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
d924e7 ¤   ¤   ¤   ¤   t64 -= dl;
76a4fb ¤   ¤   ¤   ¤   if (t64 > ((BNWORD64)r << 32) + nl)
c9f54c ¤   ¤   ¤   ¤   ¤   qhat--;
42a3a6 ¤   ¤   ¤   }
370fe4 ¤   ¤   }
7140c8 #else /* Use bniMulN1_32 */
c2e7b8 ¤   ¤   bniMulN1_32(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
5dde8d ¤   ¤   if (t2high > r || (t2high == r && t2low > nl)) {
69c34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
6779dd ¤   ¤   ¤   qhat--;
56d4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
f89830 ¤   ¤   ¤   ¤   t2high -= (t2low < dl);
37928a ¤   ¤   ¤   ¤   t2low -= dl;
e8cf98 ¤   ¤   ¤   ¤   if (t2high > r || (t2high == r && t2low > nl))
2af54c ¤   ¤   ¤   ¤   ¤   qhat--;
b9a3a6 ¤   ¤   ¤   }
7f0fe4 ¤   ¤   }
947454 #endif
30af5a
f61b17 ¤   ¤   /*
aca70b ¤   ¤   ·* As a point of interest, note that it is not worth checking
2db062 ¤   ¤   ·* for qhat of 0 or 1 and installing special-case code. ·These
c9153a ¤   ¤   ·* occur with probability 2^-32, so spending 1 cycle to check
2e1cbe ¤   ¤   ·* for them is only worth it if we save more than 2^15 cycles,
1a265f ¤   ¤   ·* and a multiply-and-subtract for numbers in the 1024-bit
8f5841 ¤   ¤   ·* range just doesn't take that long.
f29de3 ¤   ¤   ·*/
--e4ab 000ef2018bd40100152 Page 26 of bni32.c
70bdcf subtract:
261b17 ¤   ¤   /*
9aa55f ¤   ¤   ·* n points to the least significant end of the substring
386576 ¤   ¤   ·* of n to be subtracted from. ·qhat is either exact or
ecdb63 ¤   ¤   ·* one too large. ·If the subtract gets a borrow, it was
1b897d ¤   ¤   ·* one too large and the divisor is added back in. ·It's
cf6fbb ¤   ¤   ·* a dlen+1 word add which is guaranteed to produce a
5125ad ¤   ¤   ·* carry out, so it can be done very simply.
df9de3 ¤   ¤   ·*/
60098b ¤   ¤   r = bniMulSub1_32(n, d, dlen, qhat);
c81560 ¤   ¤   if (r > nh) {¤  /* Borrow? */
0e1c83 ¤   ¤   ¤   (void)bniAddN_32(n, d, dlen);
2b79dd ¤   ¤   ¤   qhat--;
140fe4 ¤   ¤   }
885982 ¤   ¤   /* Store the quotient digit */
43783d ¤   ¤   BIGLITTLE(*q++,*--q) = qhat;
499371 ¤   }
859169 ¤   /* Tah dah! */
e7af5a
295df3 ¤   if (shift) {
e30a2a ¤   ¤   bniRshift_32(d, dlen, shift);
c6aa4c ¤   ¤   bniRshift_32(n, dlen, shift);
619371 ¤   }
fbaf5a
bc97ee ¤   return qhigh;
7cefe6 }
b97454 #endif
4baf5a
5138e5 /*
d9fd50 ·* Find the negative multiplicative inverse of x (x must be odd!) modulo 2^32.
9b775e ·*
f8e4a4 ·* This just performs Newton's iteration until it gets the
952d8c ·* inverse. ·The initial estimate is always correct to 3 bits, and
3fd773 ·* sometimes 4. ·The number of valid bits doubles each iteration.
c632ba ·* (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable
7e60ca ·* for the error mod 2^2n. ·x * y == 1 + k*2^n (mod 2^2n) and follow
015d3e ·* the iteration through.)
c0495d ·*/
eda6a5 #ifndef bniMontInv1_32
f5e6d9 BNWORD32
80e898 bniMontInv1_32(BNWORD32 const x)
17bb36 {
a2f5bf ········BNWORD32 y = x, z;
86af5a
28201b ¤   pgpAssert(x & 1);
17d83c ·
79d2ee ········while ((z = x*y) != 1)
60fa12 ················y *= 2 - z;
126ae3 ········return -y;
d6efe6 }
e4214d #endif /* !bniMontInv1_32 */
6baf5a
0456cb #if defined(BNWORD64) && PRODUCT_SCAN
f538e5 /*
e13de0 ·* Test code for product-scanning Montgomery reduction.
e85767 ·* This seems to slow the C code down rather than speed it up.
5a775e ·*
903e2e ·* The first loop computes the Montgomery multipliers, storing them over
7b9652 ·* the low half of the number n.
cc775e ·*
dabdb8 ·* The second half multiplies the upper half, adding in the modulus
fb2380 ·* times the Montgomery multipliers. ·The results of this multiply
c2fa30 ·* are stored.
83495d ·*/
dd314a void
abe2e2 bniMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv)
49bb36 {
94ea2d ¤   BNWORD64 x, y;
aaead5 ¤   BNWORD32 const *pm;
49e6e2 ¤   BNWORD32 *pn;
e1f9fc ¤   BNWORD32 t;
ef50fc ¤   unsigned carry;
--80e3 0000f3f0ac940100152 Page 27 of bni32.c
d807cb ¤   unsigned i, j;
27af5a
94157a ¤   /* Special case of zero */
9bff48 ¤   if (!mlen)
db99bf ¤   ¤   return;
1aaf5a
e2a702 ¤   /* Pass 1 - compute Montgomery multipliers */
6b1ffe ¤   /* First iteration can have certain simplifications. */
e9af9a ¤   t = BIGLITTLE(n[-1],n[0]);
c4b067 ¤   x = t;
ab451d ¤   t *= inv;
9ef049 ¤   BIGLITTLE(n[-1], n[0]) = t;
e3f053 ¤   x += (BNWORD64)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */
3bc2d3 ¤   pgpAssert((BNWORD32)x == 0);
c6f979 ¤   x = x >> 32;
6caf5a
a7947e ¤   for (i = 1; i < mlen; i++) {
4efcf3 ¤   ¤   carry = 0;
07c3fd ¤   ¤   pn = n;
b1d39c ¤   ¤   pm = BIGLITTLE(mod-i-1,mod+i+1);
f2f8a4 ¤   ¤   for (j = 0; j < i; j++) {
a54d90 ¤   ¤   ¤   y = (BNWORD64)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm);
d61ca0 ¤   ¤   ¤   x += y;
b6dfb0 ¤   ¤   ¤   carry += (x < y);
f20fe4 ¤   ¤   }
91ae1e ¤   ¤   pgpAssert(BIGLITTLE(pn == n-i, pn == n+i));
a3d720 ¤   ¤   y = t = BIGLITTLE(pn[-1], pn[0]);
dd8bd3 ¤   ¤   x += y;
e156e4 ¤   ¤   carry += (x < y);
6a872e ¤   ¤   BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD32)x;
7235b5 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-1, pm == mod+1));
2b2e85 ¤   ¤   y = (BNWORD64)t * BIGLITTLE(pm[0],pm[-1]);
4b8bd3 ¤   ¤   x += y;
d456e4 ¤   ¤   carry += (x < y);
67ffbb ¤   ¤   pgpAssert((BNWORD32)x == 0);
c854e0 ¤   ¤   x = x >> 32 | (BNWORD64)carry << 32;
959371 ¤   }
86af5a
092d98 ¤   BIGLITTLE(n -= mlen, n += mlen);
75af5a
677cfe ¤   /* Pass 2 - compute upper words and add to n */
a7947e ¤   for (i = 1; i < mlen; i++) {
b3fcf3 ¤   ¤   carry = 0;
ca0805 ¤   ¤   pm = BIGLITTLE(mod-i,mod+i);
d8c3fd ¤   ¤   pn = n;
40ed18 ¤   ¤   for (j = i; j < mlen; j++) {
48440f ¤   ¤   ¤   y = (BNWORD64)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn);
a71ca0 ¤   ¤   ¤   x += y;
34dfb0 ¤   ¤   ¤   carry += (x < y);
ca0fe4 ¤   ¤   }
f6ea60 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen));
3d3793 ¤   ¤   pgpAssert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i));
d1dabc ¤   ¤   y = t = BIGLITTLE(*(n-i),*(n+i-1));
cf8bd3 ¤   ¤   x += y;
7256e4 ¤   ¤   carry += (x < y);
40811a ¤   ¤   BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD32)x;
5101eb ¤   ¤   x = (x >> 32) | (BNWORD64)carry << 32;
909371 ¤   }
04af5a
e8f753 ¤   /* Last round of second half, simplified. */
dbd2d2 ¤   t = BIGLITTLE(*(n-mlen),*(n+mlen-1));
e86e1c ¤   x += t;
0a26eb ¤   BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD32)x;
e7377d ¤   carry = (unsigned)(x >> 32);
d1af5a
42a53b ¤   while (carry)
c1bd70 ¤   ¤   carry -= bniSubN_32(n, mod, mlen);
f23221 ¤   while (bniCmp_32(n, mod, mlen) >= 0)
c8bccf ¤   ¤   (void)bniSubN_32(n, mod, mlen);
b9efe6 }
a8f17b #define bniMontReduce_32 bniMontReduce_32
0f7454 #endif
--2681 0005a747eba40100152 Page 28 of bni32.c
e0af5a
d338e5 /*
9bee5a ·* Montgomery reduce n, modulo mod. ·This reduces modulo mod and divides by
d0739d ·* 2^(32*mlen). ·Returns the result in the *top* mlen words of the argument n.
421422 ·* This is ready for another multiplication using bniMul_32.
99775e ·*
e22def ·* Montgomery representation is a very useful way to encode numbers when
eca0f9 ·* you're doing lots of modular reduction. ·What you do is pick a multiplier
d47f63 ·* R which is relatively prime to the modulus and very easy to divide by.
47bca7 ·* Since the modulus is odd, R is closen as a power of 2, so the division
1edc5c ·* is a shift. ·In fact, it's a shift of an integral number of words,
90fb89 ·* so the shift can be implicit - just drop the low-order words.
a7775e ·*
eac4d8 ·* Now, choose R *larger* than the modulus m, 2^(32*mlen). ·Then convert
93bdb2 ·* all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the
0e8961 ·* relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. ·Note that:
8da547 ·* - The Montgomery form of a number depends on the modulus m.
b1bd40 ·* ··A fixed modulus m is assumed throughout this discussion.
069d87 ·* - Since R is relaitvely prime to m, multiplication by R is invertible;
5370cf ·* ··no information about the numbers is lost, they're just scrambled.
d3e310 ·* - Adding (and subtracting) numbers in this form works just as usual.
3e2937 ·* ··M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m
941edf ·* - Multiplying numbers in this form produces a*b*R*R. ·The problem
21322e ·* ··is to divide out the excess factor of R, modulo m as well as to
5e7321 ·* ··reduce to the given length mlen. ·It turns out that this can be
acab47 ·* ··done *faster* than a normal divide, which is where the speedup
08c3b7 ·* ··in Montgomery division comes from.
48775e ·*
3ce4aa ·* Normal reduction chooses a most-significant quotient digit q and then
16ffcc ·* subtracts q*m from the number to be reduced. ·Choosing q is tricky
605e75 ·* and involved (just look at bniDiv_32 to see!) and is usually
927816 ·* imperfect, requiring a check for correction after the subtraction.
31775e ·*
45b6cd ·* Montgomery reduction *adds* a multiple of m to the *low-order* part
dd1d3e ·* of the number to be reduced. ·This multiple is chosen to make the
03dcbd ·* low-order part of the number come out to zero. ·This can be done
e5452c ·* with no trickery or error using a precomputed inverse of the modulus.
35a07a ·* In this code, the "part" is one word, but any width can be used.
2e775e ·*
fdcd30 ·* Repeating this step sufficiently often results in a value which
18afde ·* is a multiple of R (a power of two, remember) but is still (since
b1dfee ·* the additions were to the low-order part and thus did not increase
745a94 ·* the value of the number being reduced very much) still not much
efa69e ·* larger than m*R. ·Then implicitly divide by R and subtract off
28b0fb ·* m until the result is in the correct range.
2f775e ·*
b297b6 ·* Since the low-order part being cancelled is less than R, the
d419df ·* multiple of m added must have a multiplier which is at most R-1.
8db2c3 ·* Assuming that the input is at most m*R-1, the final number is
06b3ee ·* at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from
c388f4 ·* the high-order part, equivalent to subtracting m*R from the
4b3b57 ·* while number, produces a result which is at most m*R - m - 1,
e86ff3 ·* which divided by R is at most m-1.
fa775e ·*
8ce28b ·* To convert *to* Montgomery form, you need a regular remainder
f80506 ·* routine, although you can just compute R*R (mod m) and do the
239da9 ·* conversion using Montgomery multiplication. ·To convert *from*
f9e178 ·* Montgomery form, just Montgomery reduce the number to
d6d688 ·* remove the extra factor of R.
e49ec0 ·*·
c68bba ·* TODO: Change to a full inverse and use Karatsuba's multiplication
c7e6d5 ·* rather than this word-at-a-time.
c2495d ·*/
db158e #ifndef bniMontReduce_32
4e314a void
fca6f9 bniMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen,
b93dc8 ················BNWORD32 inv)
9fbb36 {
27f9fc ¤   BNWORD32 t;
01fdd1 ¤   BNWORD32 c = 0;
718079 ¤   unsigned len = mlen;
5aaf5a
--be17 000be71ac4b40100152 Page 29 of bni32.c
f59eac ¤   /* inv must be the negative inverse of mod's least significant word */
cb5ae1 ¤   pgpAssert((BNWORD32)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD32)-1);
9faf5a
5086c8 ¤   pgpAssert(len);
57af5a
6143ab ¤   do {
2ff571 ¤   ¤   t = bniMulAdd1_32(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0]));
e48f2b ¤   ¤   c += bniAdd1_32(BIGLITTLE(n-mlen,n+mlen), len, t);
bef036 ¤   ¤   BIGLITTLE(--n,++n);
17c57e ¤   } while (--len);
19af5a
f6d8af ¤   /*
aff214 ¤   ·* All that adding can cause an overflow past the modulus size,
1b8b38 ¤   ·* but it's unusual, and never by much, so a subtraction loop
6ca65a ¤   ·* is the right way to deal with it.
372a16 ¤   ·* This subtraction happens infrequently - I've only ever seen it
fb5758 ¤   ·* invoked once per reduction, and then just under 22.5% of the time.
dda4e3 ¤   ·*/
c56bd2 ¤   while (c)
e1eb40 ¤   ¤   c -= bniSubN_32(n, mod, mlen);
ad3221 ¤   while (bniCmp_32(n, mod, mlen) >= 0)
3ebccf ¤   ¤   (void)bniSubN_32(n, mod, mlen);
1eefe6 }
baf6e6 #endif /* !bniMontReduce_32 */
daaf5a
f738e5 /*
b300f3 ·* A couple of helpers that you might want to implement atomically
224a88 ·* in asm sometime.
86495d ·*/
5f7cc9 #ifndef bniMontMul_32
5438e5 /*
9c187a ·* Multiply "num1" by "num2", modulo "mod", all of length "len", and
ce8535 ·* place the result in the high half of "prod". ·"inv" is the inverse
71cf56 ·* of the least-significant word of the modulus, modulo 2^32.
eccfb2 ·* This uses numbers in Montgomery form. ·Reduce using "len" and "inv".
a0775e ·*
fd97ba ·* This is implemented as a macro to win on compilers that don't do
ce99a7 ·* inlining, since it's so trivial.
e4495d ·*/
2707fb #define bniMontMul_32(prod, n1, n2, mod, len, inv) \
d9bf3c ¤   (bniMulX_32(prod, n1, n2, len), bniMontReduce_32(prod, mod, len, inv))
a6ca5b #endif /* !bniMontMul_32 */
5eaf5a
e0bf3b #ifndef bniMontSquare_32
b638e5 /*
772c86 ·* Square "num", modulo "mod", both of length "len", and place the result
2d2dbd ·* in the high half of "prod". ·"inv" is the inverse of the least-significant
9f5bac ·* word of the modulus, modulo 2^32.
18cfb2 ·* This uses numbers in Montgomery form. ·Reduce using "len" and "inv".
35775e ·*
ce97ba ·* This is implemented as a macro to win on compilers that don't do
0a99a7 ·* inlining, since it's so trivial.
3f495d ·*/
81918c #define bniMontSquare_32(prod, n, mod, len, inv) \
b9b148 ¤   (bniSquare_32(prod, n, len), bniMontReduce_32(prod, mod, len, inv))
3367c5 ¤
571796 #endif /* !bniMontSquare_32 */
81af5a
0a38e5 /*
37a390 ·* Convert a number to Montgomery form - requires mlen + nlen words
0b15f8 ·* of memory in "n".
a3495d ·*/
8c314a void
e4c613 bniToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen)
c8bb36 {
779cf5 ¤   /* Move n up "mlen" words */
7cd6f8 ¤   bniCopy_32(BIGLITTLE(n-mlen,n+mlen), n, nlen);
3181ac ¤   bniZero_32(n, mlen);
cba154 ¤   /* Do the division - dump the quotient in the high-order words */
d758c6 ¤   (void)bniDiv_32(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen);
7aefe6 }
beaf5a
--6497 00020d9aaa340100152 Page 30 of bni32.c
bc38e5 /*
00d6c1 ·* Convert from Montgomery form. ·Montgomery reduction is all that is
e9e480 ·* needed.
b6495d ·*/
f0314a void
b3628c bniFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len)
2dbb36 {
ca3595 ¤   /* Zero the high words of n */
bfb688 ¤   bniZero_32(BIGLITTLE(n-len,n+len), len);
79902b ¤   bniMontReduce_32(n, mod, len, bniMontInv1_32(mod[BIGLITTLE(-1,0)]));
829c58 ¤   /* Move n down len words */
a3f777 ¤   bniCopy_32(n, BIGLITTLE(n-len,n+len), len);
0defe6 }
ecaf5a
2b38e5 /*
4bd039 ·* The windowed exponentiation algorithm, precomputes a table of odd
8a03bb ·* powers of n up to 2^k. ·See the comment in bnExpMod_32 below for
6bc2ff ·* an explanation of how it actually works works.
ae775e ·*
dfa488 ·* It takes 2^(k-1)-1 multiplies to compute the table, and (e-1)/(k+1)
80e229 ·* multiplies (on average) to perform the exponentiation. ·To minimize
bfe12a ·* the sum, k must vary with e. ·The optimal window sizes vary with the
dc06bb ·* exponent length. ·Here are some selected values and the boundary cases.
2644f4 ·* (An underscore _ has been inserted into some of the numbers to ensure
938ecd ·* that magic strings like 32 do not appear in this table. ·It should be
7c0710 ·* ignored.)
32775e ·*
b505dd ·* At e = ···1 bits, k=1 ··(0.000000) is best
95630a ·* At e = ···2 bits, k=1 ··(0.500000) is best
4a12b6 ·* At e = ···4 bits, k=1 ··(1.500000) is best
0fa6b8 ·* At e = ···8 bits, k=2 ··(3.333333) < k=1 ··(3.500000)
1d5942 ·* At e = ·1_6 bits, k=2 ··(6.000000) is best
de0761 ·* At e = ··26 bits, k=3 ··(9.250000) < k=2 ··(9.333333)
dbd0cf ·* At e = ·3_2 bits, k=3 ·(10.750000) is best
a09f06 ·* At e = ·6_4 bits, k=3 ·(18.750000) is best
5e1f23 ·* At e = ··82 bits, k=4 ·(23.200000) < k=3 ·(23.250000)
e5030f ·* At e = ·128 bits, k=4 (3_2.400000) is best
b0fff6 ·* At e = ·242 bits, k=5 ·(55.1_66667) < k=4 (55.200000)
97abb3 ·* At e = ·256 bits, k=5 ·(57.500000) is best
68cd12 ·* At e = ·512 bits, k=5 (100.1_66667) is best
8203f9 ·* At e = ·674 bits, k=6 (127.142857) < k=5 (127.1_66667)
3c0d7b ·* At e = 1024 bits, k=6 (177.142857) is best
0b730e ·* At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857)
2a356a ·* At e = 2048 bits, k=7 (318.875000) is best
387a5b ·* At e = 4096 bits, k=7 (574.875000) is best
41775e ·*
920ef9 ·* The numbers in parentheses are the expected number of multiplications
76471f ·* needed to do the computation. ·The normal russian-peasant modular
3947b0 ·* exponentiation technique always uses (e-1)/2. ·For exponents as
d2d6ec ·* small as 192 bits (below the range of current factoring algorithms),
4a7212 ·* half of the multiplies are eliminated, 45.2 as opposed to the naive
fb26b5 ·* 95.5. ·Counting the 191 squarings as 3/4 a multiply each (squaring
d56545 ·* proper is just over half of multiplying, but the Montgomery
05de2c ·* reduction in each case is also a multiply), that's 143.25
e5992d ·* multiplies, for totals of 188.45 vs. 238.75 - a 21% savings.
c1e86b ·* For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a
628afb ·* 24.3% savings. ·It asymptotically approaches 25%.
4d775e ·*
8df291 ·* Um, actually there's a slightly more accurate way to count, which
cce881 ·* really is the average number of multiplies required, averaged
d70fb0 ·* uniformly over all 2^(e-1) e-bit numbers, from 2^(e-1) to (2^e)-1.
61bbff ·* It's based on the recurrence that for the last b bits, b <= k, at
054553 ·* most one multiply is needed (and none at all 1/2^b of the time),
cbacfb ·* while when b > k, the odds are 1/2 each way that the bit will be
1a5519 ·* 0 (meaning no multiplies to reduce it to the b-1-bit case) and
61dff6 ·* 1/2 that the bit will be 1, starting a k-bit window and requiring
2618fe ·* 1 multiply beyond the b-k-bit case. ·Since the most significant
0541f6 ·* bit is always 1, a k-bit window always starts there, and that
d60a4c ·* multiply is by 1, so it isn't a multiply at all. ·Thus, the
8dc456 ·* number of multiplies is simply that needed for the last e-k bits.
5452be ·* This recurrence produces:
20775e ·*
--c053 000ed186bd840100152 Page 31 of bni32.c
1605dd ·* At e = ···1 bits, k=1 ··(0.000000) is best
54630a ·* At e = ···2 bits, k=1 ··(0.500000) is best
e212b6 ·* At e = ···4 bits, k=1 ··(1.500000) is best
b55c43 ·* At e = ···6 bits, k=2 ··(2.437500) < k=1 ··(2.500000)
065dc4 ·* At e = ···8 bits, k=2 ··(3.109375) is best
2ba533 ·* At e = ·1_6 bits, k=2 ··(5.777771) is best
5a323f ·* At e = ··24 bits, k=3 ··(8.437629) < k=2 ··(8.444444)
c4b0ab ·* At e = ·3_2 bits, k=3 ·(10.437492) is best
46de54 ·* At e = ·6_4 bits, k=3 ·(18.437500) is best
0a9d65 ·* At e = ··81 bits, k=4 ·(22.6_40000) < k=3 ·(22.687500)
fb03d4 ·* At e = ·128 bits, k=4 (3_2.040000) is best
0323e8 ·* At e = ·241 bits, k=5 ·(54.611111) < k=4 ·(54.6_40000)
2d6078 ·* At e = ·256 bits, k=5 ·(57.111111) is best
5666d1 ·* At e = ·512 bits, k=5 ·(99.777778) is best
8423ae ·* At e = ·673 bits, k=6 (126.591837) < k=5 (126.611111)
45f6ca ·* At e = 1024 bits, k=6 (176.734694) is best
de8b19 ·* At e = 1793 bits, k=7 (286.578125) < k=6 (286.591837)
fadf27 ·* At e = 2048 bits, k=7 (318.453125) is best
7c9016 ·* At e = 4096 bits, k=7 (574.453125) is best
4c775e ·*
8071f5 ·* This has the rollover points at 6, 24, 81, 241, 673 and 1793 instead
0471d9 ·* of 8, 26, 82, 242, 674, and 1794. ·Not a very big difference.
17480f ·* (The numbers past that are k=8 at 4609 and k=9 at 11521,
08e3af ·* vs. one more in each case for the approximation.)
e4775e ·*
f2cd4d ·* Given that exponents for which k>7 are useful are uncommon,
c0986b ·* a fixed size table for k <= 7 is used for simplicity.
c3775e ·*
e63a91 ·* The basic number of squarings needed is e-1, although a k-bit
778550 ·* window (for k > 1) can save, on average, k-2 of those, too.
22a714 ·* That savings currently isn't counted here. ·It would drive the
94b9c9 ·* crossover points slightly lower.
a42fb9 ·* (Actually, this win is also reduced in the DoubleExpMod case,
1d73fc ·* meaning we'd have to split the tables. ·Except for that, the
b12115 ·* multiplies by powers of the two bases are independent, so
d57584 ·* the same logic applies to each as the single case.)
9d775e ·*
5bda92 ·* Table entry i is the largest number of bits in an exponent to
073c5d ·* process with a window size of i+1. ·Entry 6 is the largest
b13c90 ·* possible unsigned number, so the window will never be more
ac9487 ·* than 7 bits, requiring 2^6 = 0x40 slots.
2d495d ·*/
5c6cca #define BNEXPMOD_MAX_WINDOW¤7
f54fb9 static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = {
3d193c ¤   5, 23, 80, 240, 672, 1792, (unsigned)-1
c06504 /*¤ 7, 25, 81, 241, 673, 1793, (unsigned)-1¤ ### The old approximations */
1a82f7 };
02af5a
8938e5 /*
a51b1f ·* Perform modular exponentiation, as fast as possible! ·This uses
913ed2 ·* Montgomery reduction, optimized squaring, and windowed exponentiation.
c9aef1 ·* The modulus "mod" MUST be odd!
42775e ·*
c9669b ·* This returns 0 on success, -1 on out of memory.
18775e ·*
49a91b ·* The window algorithm:
0e34dc ·* The idea is to keep a running product of b1 = n^(high-order bits of exp),
514327 ·* and then keep appending exponent bits to it. ·The following patterns
cc1e2d ·* apply to a 3-bit window (k = 3):
8e57f4 ·* To append ··0: square
df17eb ·* To append ··1: square, multiply by n^1
591993 ·* To append ·10: square, multiply by n^1, square
f660d5 ·* To append ·11: square, square, multiply by n^3
8cb4bd ·* To append 100: square, multiply by n^1, square, square
1be469 ·* To append 101: square, square, square, multiply by n^5
10730b ·* To append 110: square, square, multiply by n^3, square
a6579e ·* To append 111: square, square, square, multiply by n^7
2f775e ·*
c49b90 ·* Since each pattern involves only one multiply, the longer the pattern
5c325f ·* the better, except that a 0 (no multiplies) can be appended directly.
b2f945 ·* We precompute a table of odd powers of n, up to 2^k, and can then
ede7a3 ·* multiply k bits of exponent at a time. ·Actually, assuming random
--7961 00093e9ab2d40100152 Page 32 of bni32.c
c5ab25 ·* exponents, there is on average one zero bit between needs to
9ec44d ·* multiply (1/2 of the time there's none, 1/4 of the time there's 1,
c6edc7 ·* 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so
ac5e90 ·* you have to do one multiply per k+1 bits of exponent.
b1775e ·*
926a37 ·* The loop walks down the exponent, squaring the result buffer as
8cbb92 ·* it goes. ·There is a wbits+1 bit lookahead buffer, buf, that is
9c6a38 ·* filled with the upcoming exponent bits. ·(What is read after the
6fa4bc ·* end of the exponent is unimportant, but it is filled with zero here.)
268f68 ·* When the most-significant bit of this buffer becomes set, i.e.
6d089f ·* (buf & tblmask) != 0, we have to decide what pattern to multiply
7d5ee7 ·* by, and when to do it. ·We decide, remember to do it in future
091e5d ·* after a suitable number of squarings have passed (e.g. a pattern
c27b40 ·* of "100" in the buffer requires that we multiply by n^1 immediately;
a77f6e ·* a pattern of "110" calls for multiplying by n^3 after one more
77221f ·* squaring), clear the buffer, and continue.
9c775e ·*
0cfbc2 ·* When we start, there is one more optimization: the result buffer
7e4fad ·* is implcitly one, so squaring it or multiplying by it can be
e38e8b ·* optimized away. ·Further, if we start with a pattern like "100"
e3d51f ·* in the lookahead window, rather than placing n into the buffer
fcda03 ·* and then starting to square it, we have already computed n^2
5358ee ·* to compute the odd-powers table, so we can place that into
a632c1 ·* the buffer and save a squaring.
f8775e ·*
97eb27 ·* This means that if you have a k-bit window, to compute n^z,
c2de80 ·* where z is the high k bits of the exponent, 1/2 of the time
f54c51 ·* it requires no squarings. ·1/4 of the time, it requires 1
46b370 ·* squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
3aa8af ·* And the remaining 1/2^(k-1) of the time, the top k bits are a
128321 ·* 1 followed by k-1 0 bits, so it again only requires k-2
343eec ·* squarings, not k-1. ·The average of these is 1. ·Add that
a85ba0 ·* to the one squaring we have to do to compute the table,
d74f92 ·* and you'll see that a k-bit window saves k-2 squarings
2f8b94 ·* as well as reducing the multiplies. ·(It actually doesn't
d285e2 ·* hurt in the case k = 1, either.)
ea775e ·*
35a837 ·* n must have mlen words allocated. ·Although fewer may be in use
94d9fa ·* when n is passed in, all are in use on exit.
c4495d ·*/
c54d2f int
9b92fe bniExpMod_32(
f96740 ¤   PGPMemoryMgrRef¤mgr,
60fe55 ¤   PGPBoolean¤ ¤   secure,
0f8531 ¤   BNWORD32 *result, BNWORD32 const *n, unsigned nlen,
749cd6 ¤   BNWORD32 const *e, unsigned elen, BNWORD32 *mod, unsigned mlen)
55bb36 {
9001b6 ¤   BNWORD32 *table[1 << (BNEXPMOD_MAX_WINDOW-1)];
54ab6c ¤   ¤   ¤   ¤   /* Table of odd powers of n */
65bbb1 ¤   unsigned ebits;¤¤   /* Exponent bits */
cc8abd ¤   unsigned wbits;¤¤   /* Window size */
f94710 ¤   unsigned tblmask;¤  /* Mask of exponentiation window */
8b36a6 ¤   BNWORD32 bitpos;¤   /* Mask of current look-ahead bit */
76a550 ¤   unsigned buf;¤  ¤   /* Buffer of exponent bits */
cda4db ¤   unsigned multpos;¤  /* Where to do pending multiply */
6b09d6 ¤   BNWORD32 const *mult;¤  /* What to multiply by */
d57dbe ¤   unsigned i;¤¤   /* Loop counter */
9b2054 ¤   int isone;¤ ¤   /* Flag: accum. is implicitly one */
cbd3dd ¤   BNWORD32 *a, *b;¤   /* Working buffers/accumulators */
9592d3 ¤   BNWORD32 *t;¤   ¤   /* Pointer into the working buffers */
86bbda ¤   BNWORD32 inv;¤  ¤   /* mod^-1 modulo 2^32 */
6bde2a ¤   int y;¤ ¤   ¤   /* bnYield() result */
5eaf5a
5ac613 ¤   pgpAssert(mlen);
f084ca ¤   pgpAssert(nlen <= mlen);
bbaf5a
c27d28 ¤   /* First, a couple of trivial cases. */
d09351 ¤   elen = bniNorm_32(e, elen);
736115 ¤   if (!elen) {
3918ff ¤   ¤   /* x ^ 0 == 1 */
eff230 ¤   ¤   bniZero_32(result, mlen);
930eac ¤   ¤   BIGLITTLE(result[-1],result[0]) = 1;
--133d 00058ba1f1e40100152 Page 33 of bni32.c
79bbde ¤   ¤   return 0;
a69371 ¤   }
7d9b57 ¤   ebits = bniBits_32(e, elen);
e6cd76 ¤   if (ebits == 1) {
81a49e ¤   ¤   /* x ^ 1 == x */
4a295d ¤   ¤   if (n != result)
7f68d1 ¤   ¤   ¤   bniCopy_32(result, n, nlen);
b1efb1 ¤   ¤   if (mlen > nlen)
9a4757 ¤   ¤   ¤   bniZero_32(BIGLITTLE(result-nlen,result+nlen),
edab83 ¤   ¤   ¤   ···········mlen-nlen);
51bbde ¤   ¤   return 0;
a59371 ¤   }
c8af5a
000565 ¤   /* Okay, now move the exponent pointer to the most-significant word */
18eb85 ¤   e = BIGLITTLE(e-elen, e+elen-1);
2aaf5a
905f70 ¤   /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
cbe796 ¤   wbits = 0;
a13dd6 ¤   while (ebits > bnExpModThreshTable[wbits])
bfca4f ¤   ¤   wbits++;
30af5a
88b29c ¤   /* Allocate working storage: two product buffers and the tables. */
b2f2b6 ¤   BNIALLOC(mgr, secure, a, BNWORD32, 2*mlen);
489293 ¤   if (!a)
fe043c ¤   ¤   return -1;
930140 ¤   BNIALLOC(mgr, secure, b, BNWORD32, 2*mlen);
9c5215 ¤   if (!b) {
6cdda3 ¤   ¤   BNIFREE(a, 2*mlen);
9c043c ¤   ¤   return -1;
639371 ¤   }
52af5a
adeb94 ¤   /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
cd7b5d ¤   tblmask = 1u << wbits;
04af5a
dca19d ¤   /* We have the result buffer available, so use it. */
0ab9d5 ¤   table[0] = result;
25af5a
d7d8af ¤   /*
cba077 ¤   ·* Okay, we now have a minimal-sized table - expand it.
ee951f ¤   ·* This is allowed to fail! ·If so, scale back the table size
55e64a ¤   ·* and proceed.
c9a4e3 ¤   ·*/
86623b ¤   for (i = 1; i < tblmask; i++) {
bd41c1 ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD32, mlen);
31f4e7 ¤   ¤   if (!t)¤/* Out of memory! ·Quit the loop. */
64cdcb ¤   ¤   ¤   break;
605264 ¤   ¤   table[i] = t;
629371 ¤   }
4caf5a
46e399 ¤   /* If we stopped, with i < tblmask, shrink the tables appropriately */
660729 ¤   while (tblmask > i) {
04570c ¤   ¤   wbits--;
31020b ¤   ¤   tblmask >>= 1;
209371 ¤   }
8e90d4 ¤   /* Free up our overallocations */
5e8b01 ¤   while (--i > tblmask)
7406fb ¤   ¤   BNIFREE(table[i], mlen);
1faf5a
9e523f ¤   /* Okay, fill in the table */
d0af5a
8e6326 ¤   /* Compute the necessary modular inverse */
b35bf6 ¤   inv = bniMontInv1_32(mod[BIGLITTLE(-1,0)]);¤/* LSW of modulus */
16af5a
2ad2c8 ¤   /* Convert n to Montgomery form */
5daf5a
b945b9 ¤   /* Move n up "mlen" words into a */
41c360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
0de410 ¤   bniCopy_32(t, n, nlen);
b22c70 ¤   bniZero_32(a, mlen);
6fa0ad ¤   /* Do the division - lose the quotient into the high-order words */
f1b25f ¤   (void)bniDiv_32(t, a, mlen+nlen, mod, mlen);
58aa1a ¤   /* Copy into first table entry */
--6dad 0008489f6de40100152 Page 34 of bni32.c
07974d ¤   bniCopy_32(table[0], a, mlen);
80af5a
2cc9f6 ¤   /* Square a into b */
c40536 ¤   bniMontSquare_32(b, a, mod, mlen, inv);
e8af5a
0c0127 ¤   /* Use high half of b to initialize the table */
592576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
66623b ¤   for (i = 1; i < tblmask; i++) {
dbaa3b ¤   ¤   bniMontMul_32(a, t, table[i-1], mod, mlen, inv);
4bd076 ¤   ¤   bniCopy_32(table[i], BIGLITTLE(a-mlen, a+mlen), mlen);
8b074b #if BNYIELD
c19bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
e474c2 ¤   ¤   ¤   goto yield;
447454 #endif
909371 ¤   }
7aaf5a
3ce133 ¤   /* We might use b = n^2 later... */
68af5a
a0b3c9 ¤   /* Initialze the fetch pointer */
168e6a ¤   bitpos = (BNWORD32)1 << ((ebits-1) & (32-1));¤  /* Initialize mask */
7aaf5a
c741cc ¤   /* This should point to the msbit of e */
20fda7 ¤   pgpAssert((*e & bitpos) != 0);
b7af5a
d4d8af ¤   /*
23f61f ¤   ·* Pre-load the window. ·Becuase the window size is
f89e1e ¤   ·* never larger than the exponent size, there is no need to
7254af ¤   ·* detect running off the end of e in here.
789714 ¤   ·*
478d24 ¤   ·* The read-ahead is controlled by elen and the bitpos mask.
77c658 ¤   ·* Note that this is *ahead* of ebits, which tracks the
f0e8fd ¤   ·* most significant end of the window. ·The purpose of this
1ecbf3 ¤   ·* initialization is to get the two wbits+1 bits apart,
e2d4d6 ¤   ·* like they should be.
0b9714 ¤   ·*
399955 ¤   ·* Note that bitpos and e1len together keep track of the
8a7e30 ¤   ·* lookahead read pointer in the exponent that is used here.
fca4e3 ¤   ·*/
d3b0a1 ¤   buf = 0;
d15760 ¤   for (i = 0; i <= wbits; i++) {
f86d2d ¤   ¤   buf = (buf << 1) | ((*e & bitpos) != 0);
b61e4d ¤   ¤   bitpos >>= 1;
9da81f ¤   ¤   if (!bitpos) {
c40024 ¤   ¤   ¤   BIGLITTLE(e++,e--);
70ea52 ¤   ¤   ¤   bitpos = (BNWORD32)1 << (32-1);
8fb349 ¤   ¤   ¤   elen--;
540fe4 ¤   ¤   }
419371 ¤   }
ba5e84 ¤   pgpAssert(buf & tblmask);
68af5a
63d8af ¤   /*
93e4af ¤   ·* Set the pending multiply positions to a location that will
ab3edd ¤   ·* never be encountered, thus ensuring that nothing will happen
735986 ¤   ·* until the need for a multiply appears and one is scheduled.
9da4e3 ¤   ·*/
1bbd01 ¤   multpos = ebits;¤   /* A NULL value */
14077f ¤   mult = 0;¤  /* Force a crash if we use these */
ceaf5a
69d8af ¤   /*
e311db ¤   ·* Okay, now begins the real work. ·The first step is
68c478 ¤   ·* slightly magic, so it's done outside the main loop,
7c3e1f ¤   ·* but it's very similar to what's inside.
16a4e3 ¤   ·*/
7b806b ¤   ebits--;¤   /* Start processing the first bit... */
c54f17 ¤   isone = 1;
00af5a
9fd8af ¤   /*
dd9907 ¤   ·* This is just like the multiply in the loop, except that
711487 ¤   ·* - We know the msbit of buf is set, and
5756cd ¤   ·* - We have the extra value n^2 floating around.
0a63fa ¤   ·* So, do the usual computation, and if the result is that
846045 ¤   ·* the buffer should be multiplied by n^1 immediately
--e880 0002af7615340100152 Page 35 of bni32.c
83cce3 ¤   ·* (which we'd normally then square), we multiply it
289fa4 ¤   ·* (which reduces to a copy, which reduces to setting a flag)
a0c34f ¤   ·* by n^2 and skip the squaring. ·Thus, we do the
475501 ¤   ·* multiply and the squaring in one step.
83a4e3 ¤   ·*/
2b5e84 ¤   pgpAssert(buf & tblmask);
634e35 ¤   multpos = ebits - wbits;
308da4 ¤   while ((buf & 1) == 0) {
031feb ¤   ¤   buf >>= 1;
c45ccd ¤   ¤   multpos++;
ab9371 ¤   }
e1f0a6 ¤   /* Intermediates can wrap, but final must NOT */
3d28d7 ¤   pgpAssert(multpos <= ebits);
0e43c6 ¤   mult = table[buf>>1];
23b0a1 ¤   buf = 0;
33af5a
3fb24e ¤   /* Special case: use already-computed value sitting in buffer */
26b774 ¤   if (multpos == ebits)
2bf768 ¤   ¤   isone = 0;
e4af5a
85d8af ¤   /*
2bfe43 ¤   ·* At this point, the buffer (which is the high half of b) holds
3d61cd ¤   ·* either 1 (implicitly, as the "isone" flag is set), or n^2.
a6a4e3 ¤   ·*/
83af5a
19d8af ¤   /*
ea9409 ¤   ·* The main loop. ·The procedure is:
f0ab45 ¤   ·* - Advance the window
e3448c ¤   ·* - If the most-significant bit of the window is set,
9c0c66 ¤   ·* ··schedule a multiply for the appropriate time in the
56375c ¤   ·* ··future (may be immediately)
9e383a ¤   ·* - Perform any pending multiples
a06d15 ¤   ·* - Check for termination
43446f ¤   ·* - Square the buffer
da9714 ¤   ·*
247202 ¤   ·* At any given time, the acumulated product is held in
2d0d21 ¤   ·* the high half of b.
f9a4e3 ¤   ·*/
5f220e ¤   for (;;) {
653362 ¤   ¤   ebits--;
62af5a
711a36 ¤   ¤   /* Advance the window */
ea7403 ¤   ¤   pgpAssert(buf < tblmask);
5b2006 ¤   ¤   buf <<= 1;
bc1b17 ¤   ¤   /*
eee0cb ¤   ¤   ·* This reads ahead of the current exponent position
cc43d1 ¤   ¤   ·* (controlled by ebits), so we have to be able to read
54969f ¤   ¤   ·* past the lsb of the exponents without error.
a99de3 ¤   ¤   ·*/
524c6b ¤   ¤   if (elen) {
2a81dc ¤   ¤   ¤   buf |= ((*e & bitpos) != 0);
fbd9f8 ¤   ¤   ¤   bitpos >>= 1;
0d4afe ¤   ¤   ¤   if (!bitpos) {
ea8bd8 ¤   ¤   ¤   ¤   BIGLITTLE(e++,e--);
71f202 ¤   ¤   ¤   ¤   bitpos = (BNWORD32)1 << (32-1);
97c9bd ¤   ¤   ¤   ¤   elen--;
9ba3a6 ¤   ¤   ¤   }
be0fe4 ¤   ¤   }
b6af5a
a8be07 ¤   ¤   /* Examine the window for pending multiplies */
48cc0d ¤   ¤   if (buf & tblmask) {
6ec80b ¤   ¤   ¤   multpos = ebits - wbits;
740b9a ¤   ¤   ¤   while ((buf & 1) == 0) {
bbc6e3 ¤   ¤   ¤   ¤   buf >>= 1;
2385c5 ¤   ¤   ¤   ¤   multpos++;
f1a3a6 ¤   ¤   ¤   }
66b920 ¤   ¤   ¤   /* Intermediates can wrap, but final must NOT */
351052 ¤   ¤   ¤   pgpAssert(multpos <= ebits);
93fd9a ¤   ¤   ¤   mult = table[buf>>1];
2244bb ¤   ¤   ¤   buf = 0;
980fe4 ¤   ¤   }
2aaf5a
--4552 0007e8f5fbe40100152 Page 36 of bni32.c
0357bb ¤   ¤   /* If we have a pending multiply, do it */
d2d05a ¤   ¤   if (ebits == multpos) {
41a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
296ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
578c88 ¤   ¤   ¤   if (isone) {
f26b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
acf0f9 ¤   ¤   ¤   ¤   bniCopy_32(t, mult, mlen);
a12e60 ¤   ¤   ¤   ¤   isone = 0;
c1042d ¤   ¤   ¤   } else {
e62fc7 ¤   ¤   ¤   ¤   bniMontMul_32(a, t, mult, mod, mlen, inv);
ff6783 ¤   ¤   ¤   ¤   /* Swap a and b */
8b51ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
2ba3a6 ¤   ¤   ¤   }
920fe4 ¤   ¤   }
d3af5a
9a7b03 ¤   ¤   /* Are we done? */
1b8029 ¤   ¤   if (!ebits)
0dcdcb ¤   ¤   ¤   break;
7daf5a
01b085 ¤   ¤   /* Square the input */
559d17 ¤   ¤   if (!isone) {
726ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
c93eed ¤   ¤   ¤   bniMontSquare_32(a, t, mod, mlen, inv);
e1ebfc ¤   ¤   ¤   /* Swap a and b */
1e6c84 ¤   ¤   ¤   t = a; a = b; b = t;
890fe4 ¤   ¤   }
e0074b #if BNYIELD
099bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
aa74c2 ¤   ¤   ¤   goto yield;
fa7454 #endif
d6d6a0 ¤   } /* for (;;) */
67af5a
df5f64 ¤   pgpAssert(!isone);
36d8b5 ¤   pgpAssert(!buf);
fcaf5a
812111 ¤   /* DONE! */
fcaf5a
a58619 ¤   /* Convert result out of Montgomery form */
b92576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
86e875 ¤   bniCopy_32(b, t, mlen);
1d6299 ¤   bniZero_32(t, mlen);
4f820a ¤   bniMontReduce_32(b, mod, mlen, inv);
0c1b0f ¤   bniCopy_32(result, t, mlen);
b3d8af ¤   /*
d78c1b ¤   ·* Clean up - free intermediate storage.
5049dc ¤   ·* Do NOT free table[0], which is the result
614228 ¤   ·* buffer.
03a4e3 ¤   ·*/
494aa5 ¤   y = 0;
95074b #if BNYIELD
96f924 yield:
077454 #endif
f5f0a6 ¤   while (--tblmask)
f8d094 ¤   ¤   BNIFREE(table[tblmask], mlen);
c4ac28 ¤   BNIFREE(b, 2*mlen);
092bc6 ¤   BNIFREE(a, 2*mlen);
89af5a
07f88b ¤   return y;¤  /* Success */
59efe6 }
63af5a
5d38e5 /*
bb5706 ·* Compute and return n1^e1 * n2^e2 mod "mod".
a2c894 ·* result may be either input buffer, or something separate.
4e8848 ·* It must be "mlen" words long.
ac775e ·*
559ebb ·* There is a current position in the exponents, which is kept in e1bits.
8610c7 ·* (The exponents are swapped if necessary so e1 is the longer of the two.)
48916c ·* At any given time, the value in the accumulator is
64da55 ·* n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod".
efa31f ·* As e1bits is counted down, this is updated, by squaring it and doing
27b1ee ·* any necessary multiplies.
7e093b ·* To decide on the necessary multiplies, two windows, each w1bits+1 bits
--2788 000de631dd640100152 Page 37 of bni32.c
da411e ·* wide, are maintained in buf1 and buf2, which read *ahead* of the
fe3a68 ·* e1bits position (with appropriate handling of the case when e1bits
10074b ·* drops below w1bits+1). ·When the most-significant bit of either window
febb09 ·* becomes set, indicating that something needs to be multiplied by
7600a5 ·* the accumulator or it will get out of sync, the window is examined
f8ab86 ·* to see which power of n1 or n2 to multiply by, and when (possibly
ab89e9 ·* later, if the power is greater than 1) the multiply should take
426e2e ·* place. ·Then the multiply and its location are remembered and the
18b3de ·* window is cleared.
98775e ·*
4d5ec4 ·* If we had every power of n1 in the table, the multiply would always
26f328 ·* be w1bits steps in the future. ·But we only keep the odd powers,
9552f8 ·* so instead of waiting w1bits squarings and then multiplying
e72d0c ·* by n1^k, we wait w1bits-k squarings and multiply by n1.
68775e ·*
cd6296 ·* Actually, w2bits can be less than w1bits, but the window is the same
f913ee ·* size, to make it easier to keep track of where we're reading. ·The
d80c46 ·* appropriate number of low-order bits of the window are just ignored.
6d495d ·*/
e44d2f int
d1d418 bniDoubleExpMod_32(
076740 ¤   PGPMemoryMgrRef¤mgr,
96fe55 ¤   PGPBoolean¤ ¤   secure,
42bb4f ¤   BNWORD32 *result,
cc722b ···BNWORD32 const *n1, unsigned n1len,
e5a794 ···BNWORD32 const *e1, unsigned e1len,
5fc39c ···BNWORD32 const *n2, unsigned n2len,
cf1623 ···BNWORD32 const *e2, unsigned e2len,
fb983e ···BNWORD32 *mod, unsigned mlen)
44bb36 {
e897d4 ¤   BNWORD32 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)];
2b9746 ¤   ¤   ¤   ¤   ¤   /* Table of odd powers of n1 */
205771 ¤   BNWORD32 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)];
738a8a ¤   ¤   ¤   ¤   ¤   /* Table of odd powers of n2 */
eeaaa4 ¤   unsigned e1bits, e2bits;¤   /* Exponent bits */
c92c22 ¤   unsigned w1bits, w2bits;¤   /* Window sizes */
99de31 ¤   unsigned tblmask;¤  ¤   /* Mask of exponentiation window */
b4fbda ¤   BNWORD32 bitpos;¤   ¤   /* Mask of current look-ahead bit */
02f0f4 ¤   unsigned buf1, buf2;¤   ¤   /* Buffer of exponent bits */
0fb874 ¤   unsigned mult1pos, mult2pos;¤   /* Where to do pending multiply */
6aca46 ¤   BNWORD32 const *mult1, *mult2;¤ /* What to multiply by */
9be525 ¤   unsigned i;¤¤   ¤   /* Loop counter */
a6395c ¤   int isone;¤ ¤   ¤   /* Flag: accum. is implicitly one */
4d7246 ¤   BNWORD32 *a, *b;¤   ¤   /* Working buffers/accumulators */
35cacc ¤   BNWORD32 *t;¤   ¤   ¤   /* Pointer into the working buffers */
6d64de ¤   BNWORD32 inv;¤  ¤   ¤   /* mod^-1 modulo 2^32 */
62916f ¤   int y;¤ ¤   ¤   ¤   /* bnYield() result */
37af5a
abc613 ¤   pgpAssert(mlen);
ce9714 ¤   pgpAssert(n1len <= mlen);
a84f6a ¤   pgpAssert(n2len <= mlen);
8aaf5a
c17d28 ¤   /* First, a couple of trivial cases. */
3e7976 ¤   e1len = bniNorm_32(e1, e1len);
ed4ebe ¤   e2len = bniNorm_32(e2, e2len);
abaf5a
6ec726 ¤   /* Ensure that the first exponent is the longer */
3e6334 ¤   e1bits = bniBits_32(e1, e1len);
8a72a4 ¤   e2bits = bniBits_32(e2, e2len);
8df8c6 ¤   if (e1bits < e2bits) {
adbd4e ¤   ¤   i = e1len; e1len = e2len; e2len = i;
4ad4ee ¤   ¤   i = e1bits; e1bits = e2bits; e2bits = i;
69820b ¤   ¤   t = (BNWORD32 *)n1; n1 = n2; n2 = t;·
306765 ¤   ¤   t = (BNWORD32 *)e1; e1 = e2; e2 = t;·
599371 ¤   }
a39589 ¤   pgpAssert(e1bits >= e2bits);
11af5a
1b56ce ¤   /* Handle a trivial case */
5ed49f ¤   if (!e2len)
fb32c0 ¤   ¤   return bniExpMod_32( mgr, secure, result, n1, n1len, e1, e1len,
148576 ¤   ¤   ¤   ¤   ¤   ¤   ¤   mod, mlen);
de5d32 ¤   pgpAssert(e2bits);
--faab 0007ef635ce40100152 Page 38 of bni32.c
e0af5a
fcfc05 ¤   /* The code below fucks up if the exponents aren't at least 2 bits */
f13f8f ¤   if (e1bits == 1) {
744cfc ¤   ¤   pgpAssert(e2bits == 1);
49af5a
7fa4b3 ¤   ¤   BNIALLOC(mgr, secure, a, BNWORD32, n1len+n2len);
328823 ¤   ¤   if (!a)
c93fd5 ¤   ¤   ¤   return -1;
08af5a
47960b ¤   ¤   bniMul_32(a, n1, n1len, n2, n2len);
9d46cf ¤   ¤   /* Do a direct modular reduction */
91016d ¤   ¤   if (n1len + n2len >= mlen)
6a8da8 ¤   ¤   ¤   (void)bniDiv_32(a+mlen, a, n1len+n2len, mod, mlen);
c7688e ¤   ¤   bniCopy_32(result, a, mlen);
de643e ¤   ¤   BNIFREE(a, n1len+n2len);
92bbde ¤   ¤   return 0;
6b9371 ¤   }
bdaf5a
e7aa9d ¤   /* Okay, now move the exponent pointers to the most-significant word */
3610a1 ¤   e1 = BIGLITTLE(e1-e1len, e1+e1len-1);
d3c984 ¤   e2 = BIGLITTLE(e2-e2len, e2+e2len-1);
a8af5a
eb5f70 ¤   /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
164f7e ¤   w1bits = 0;
77997d ¤   while (e1bits > bnExpModThreshTable[w1bits])
c3ff05 ¤   ¤   w1bits++;
7ab1cd ¤   w2bits = 0;
12d55d ¤   while (e2bits > bnExpModThreshTable[w2bits])
342902 ¤   ¤   w2bits++;
5eaf5a
eea36d ¤   pgpAssert(w1bits >= w2bits);
e9af5a
7db29c ¤   /* Allocate working storage: two product buffers and the tables. */
b6f2b6 ¤   BNIALLOC(mgr, secure, a, BNWORD32, 2*mlen);
579293 ¤   if (!a)
2e043c ¤   ¤   return -1;
960140 ¤   BNIALLOC(mgr, secure, b, BNWORD32, 2*mlen);
d55215 ¤   if (!b) {
bcdda3 ¤   ¤   BNIFREE(a, 2*mlen);
da043c ¤   ¤   return -1;
519371 ¤   }
2faf5a
8beb94 ¤   /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
57211e ¤   tblmask = 1u << w1bits;
cff1a9 ¤   /* Use buf2 for its size, temporarily */
1fb274 ¤   buf2 = 1u << w2bits;
12af5a
c40eff ¤   BNIALLOC(mgr, secure, t, BNWORD32, mlen);
58ddcd ¤   if (!t) {
275a4d ¤   ¤   BNIFREE(b, 2*mlen);
dadda3 ¤   ¤   BNIFREE(a, 2*mlen);
40043c ¤   ¤   return -1;
b89371 ¤   }
ab4388 ¤   table1[0] = t;
8311c2 ¤   table2[0] = result;
8caf5a
47d8af ¤   /*
ae6773 ¤   ·* Okay, we now have some minimal-sized tables - expand them.
546065 ¤   ·* This is allowed to fail! ·If so, scale back the table sizes
025a99 ¤   ·* and proceed. ·We allocate both tables at the same time
c54729 ¤   ·* so if it fails partway through, they'll both be a reasonable
fee17e ¤   ·* size rather than one huge and one tiny.
b29f45 ¤   ·* When i passes buf2 (the number of entries in the e2 window,
b3278f ¤   ·* which may be less than the number of entries in the e1 window),
092758 ¤   ·* stop allocating e2 space.
63a4e3 ¤   ·*/
04623b ¤   for (i = 1; i < tblmask; i++) {
0841c1 ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD32, mlen);
8ff4e7 ¤   ¤   if (!t)¤/* Out of memory! ·Quit the loop. */
33cdcb ¤   ¤   ¤   break;
7eeaeb ¤   ¤   table1[i] = t;
7e5687 ¤   ¤   if (i < buf2) {
--9073 000674316ca40100152 Page 39 of bni32.c
daefc0 ¤   ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD32, mlen);
0c62e2 ¤   ¤   ¤   if (!t) {
538b24 ¤   ¤   ¤   ¤   BNIFREE(table1[i], mlen);
ebf622 ¤   ¤   ¤   ¤   break;
fda3a6 ¤   ¤   ¤   }
b37c63 ¤   ¤   ¤   table2[i] = t;
7e0fe4 ¤   ¤   }
679371 ¤   }
99af5a
94e399 ¤   /* If we stopped, with i < tblmask, shrink the tables appropriately */
be0729 ¤   while (tblmask > i) {
7d6246 ¤   ¤   w1bits--;
e1020b ¤   ¤   tblmask >>= 1;
2a9371 ¤   }
0090d4 ¤   /* Free up our overallocations */
70e874 ¤   while (--i > tblmask) {
938a30 ¤   ¤   if (i < buf2)
1fb93d ¤   ¤   ¤   BNIFREE(table2[i], mlen);
fb58b9 ¤   ¤   BNIFREE(table1[i], mlen);
e99371 ¤   }
cf18ae ¤   /* And shrink the second window too, if needed */
0df5d4 ¤   if (w2bits > w1bits) {
910726 ¤   ¤   w2bits = w1bits;
dc356a ¤   ¤   buf2 = tblmask;
e89371 ¤   }
89af5a
ffd8af ¤   /*
8d8b7f ¤   ·* From now on, use the w2bits variable for the difference
75f9d1 ¤   ·* between w1bits and w2bits.
eda4e3 ¤   ·*/
a8c76a ¤   w2bits = w1bits-w2bits;
0faf5a
0ab64a ¤   /* Okay, fill in the tables */
65af5a
e36326 ¤   /* Compute the necessary modular inverse */
1b5bf6 ¤   inv = bniMontInv1_32(mod[BIGLITTLE(-1,0)]);¤/* LSW of modulus */
91af5a
5d74f9 ¤   /* Convert n1 to Montgomery form */
d0af5a
11e328 ¤   /* Move n1 up "mlen" words into a */
74c360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
27144f ¤   bniCopy_32(t, n1, n1len);
b52c70 ¤   bniZero_32(a, mlen);
d7a0ad ¤   /* Do the division - lose the quotient into the high-order words */
bb19eb ¤   (void)bniDiv_32(t, a, mlen+n1len, mod, mlen);
94aa1a ¤   /* Copy into first table entry */
9972be ¤   bniCopy_32(table1[0], a, mlen);
b6af5a
a5c9f6 ¤   /* Square a into b */
6f0536 ¤   bniMontSquare_32(b, a, mod, mlen, inv);
67af5a
da8028 ¤   /* Use high half of b to initialize the first table */
db2576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
59623b ¤   for (i = 1; i < tblmask; i++) {
eed1d1 ¤   ¤   bniMontMul_32(a, t, table1[i-1], mod, mlen, inv);
0343eb ¤   ¤   bniCopy_32(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen);
86074b #if BNYIELD
c59bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
5574c2 ¤   ¤   ¤   goto yield;
ff7454 #endif
6a9371 ¤   }
0daf5a
7c9935 ¤   /* Convert n2 to Montgomery form */
34af5a
98c360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
e6b91b ¤   /* Move n2 up "mlen" words into a */
854292 ¤   bniCopy_32(t, n2, n2len);
502c70 ¤   bniZero_32(a, mlen);
a1a0ad ¤   /* Do the division - lose the quotient into the high-order words */
2d18d3 ¤   (void)bniDiv_32(t, a, mlen+n2len, mod, mlen);
d3aa1a ¤   /* Copy into first table entry */
67e89f ¤   bniCopy_32(table2[0], a, mlen);
--8259 0005e712dd240100152 Page 40 of bni32.c
e0af5a
98f67c ¤   /* Square it into a */
265518 ¤   bniMontSquare_32(a, table2[0], mod, mlen, inv);
e78e9d ¤   /* Copy to b, low half */
dbe875 ¤   bniCopy_32(b, t, mlen);
71af5a
e7d1ec ¤   /* Use b to initialize the second table */
199f1b ¤   for (i = 1; i < buf2; i++) {
ae7273 ¤   ¤   bniMontMul_32(a, b, table2[i-1], mod, mlen, inv);
426712 ¤   ¤   bniCopy_32(table2[i], t, mlen);
c9074b #if BNYIELD
ea9bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
8974c2 ¤   ¤   ¤   goto yield;
577454 #endif
999371 ¤   }
72af5a
48d8af ¤   /*
bda7c8 ¤   ·* Okay, a recap: at this point, the low part of b holds
b54f8a ¤   ·* n2^2, the high part holds n1^2, and the tables are
7cb069 ¤   ·* initialized with the odd powers of n1 and n2 from 1
614e6c ¤   ·* through 2*tblmask-1 and 2*buf2-1.
b29714 ¤   ·*
a7eaa9 ¤   ·* We might use those squares in b later, or we might not.
f2a4e3 ¤   ·*/
0eaf5a
41b3c9 ¤   /* Initialze the fetch pointer */
694a58 ¤   bitpos = (BNWORD32)1 << ((e1bits-1) & (32-1));¤ /* Initialize mask */
50af5a
8ba4e7 ¤   /* This should point to the msbit of e1 */
c33755 ¤   pgpAssert((*e1 & bitpos) != 0);
53af5a
e4d8af ¤   /*
b792f4 ¤   ·* Pre-load the windows. ·Becuase the window size is
be9e1e ¤   ·* never larger than the exponent size, there is no need to
9729e6 ¤   ·* detect running off the end of e1 in here.
619714 ¤   ·*
8d6575 ¤   ·* The read-ahead is controlled by e1len and the bitpos mask.
08b24e ¤   ·* Note that this is *ahead* of e1bits, which tracks the
6de8fd ¤   ·* most significant end of the window. ·The purpose of this
4a59ed ¤   ·* initialization is to get the two w1bits+1 bits apart,
d5d4d6 ¤   ·* like they should be.
159714 ¤   ·*
979955 ¤   ·* Note that bitpos and e1len together keep track of the
a87e30 ¤   ·* lookahead read pointer in the exponent that is used here.
f30acb ¤   ·* e2len is not decremented, it is only ever compared with
0f9c64 ¤   ·* e1len as *that* is decremented.
f0a4e3 ¤   ·*/
25c6dc ¤   buf1 = buf2 = 0;
643d15 ¤   for (i = 0; i <= w1bits; i++) {
87c5f3 ¤   ¤   buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0);
8b5b2e ¤   ¤   if (e1len <= e2len)
a74658 ¤   ¤   ¤   buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0);
271e4d ¤   ¤   bitpos >>= 1;
44a81f ¤   ¤   if (!bitpos) {
81dc04 ¤   ¤   ¤   BIGLITTLE(e1++,e1--);
fcf670 ¤   ¤   ¤   if (e1len <= e2len)
f7c1b9 ¤   ¤   ¤   ¤   BIGLITTLE(e2++,e2--);
55ea52 ¤   ¤   ¤   bitpos = (BNWORD32)1 << (32-1);
5ab8bc ¤   ¤   ¤   e1len--;
640fe4 ¤   ¤   }
919371 ¤   }
6bf843 ¤   pgpAssert(buf1 & tblmask);
e4af5a
47d8af ¤   /*
06e4af ¤   ·* Set the pending multiply positions to a location that will
2d3edd ¤   ·* never be encountered, thus ensuring that nothing will happen
445986 ¤   ·* until the need for a multiply appears and one is scheduled.
01a4e3 ¤   ·*/
9d9c90 ¤   mult1pos = mult2pos = e1bits;¤  /* A NULL value */
ee0cc3 ¤   mult1 = mult2 = 0;¤ /* Force a crash if we use these */
f5af5a
5ed8af ¤   /*
--09ef 000c891160840100152 Page 41 of bni32.c
5211db ¤   ·* Okay, now begins the real work. ·The first step is
ecc478 ¤   ·* slightly magic, so it's done outside the main loop,
bd3e1f ¤   ·* but it's very similar to what's inside.
67a4e3 ¤   ·*/
08f44f ¤   isone = 1;¤ /* Buffer is implicitly 1, so replace * by copy */
8ca246 ¤   e1bits--;¤  /* Start processing the first bit... */
c8af5a
58d8af ¤   /*
e09907 ¤   ·* This is just like the multiply in the loop, except that
cbfc57 ¤   ·* - We know the msbit of buf1 is set, and
2a05dd ¤   ·* - We have the extra value n1^2 floating around.
4663fa ¤   ·* So, do the usual computation, and if the result is that
fd2227 ¤   ·* the buffer should be multiplied by n1^1 immediately
81cce3 ¤   ·* (which we'd normally then square), we multiply it
d69fa4 ¤   ·* (which reduces to a copy, which reduces to setting a flag)
48b99d ¤   ·* by n1^2 and skip the squaring. ·Thus, we do the
4e5501 ¤   ·* multiply and the squaring in one step.
40a4e3 ¤   ·*/
46f843 ¤   pgpAssert(buf1 & tblmask);
fe8464 ¤   mult1pos = e1bits - w1bits;
8bd9b6 ¤   while ((buf1 & 1) == 0) {
46e8d7 ¤   ¤   buf1 >>= 1;
fa8c75 ¤   ¤   mult1pos++;
519371 ¤   }
60f0a6 ¤   /* Intermediates can wrap, but final must NOT */
837afd ¤   pgpAssert(mult1pos <= e1bits);
988447 ¤   mult1 = table1[buf1>>1];
64cb53 ¤   buf1 = 0;
12af5a
adb24e ¤   /* Special case: use already-computed value sitting in buffer */
1317a5 ¤   if (mult1pos == e1bits)
f5f768 ¤   ¤   isone = 0;
5aaf5a
9ad8af ¤   /*
d273de ¤   ·* The first multiply by a power of n2. ·Similar, but
26d0bc ¤   ·* we might not even want to schedule a multiply if e2 is
58719d ¤   ·* shorter than e1, and the window might be shorter so
c0207e ¤   ·* we have to leave the low w2bits bits alone.
aea4e3 ¤   ·*/
f46486 ¤   if (buf2 & tblmask) {
c58236 ¤   ¤   /* Remember low-order bits for later */
2ca24c ¤   ¤   i = buf2 & ((1u << w2bits) - 1);
d4c885 ¤   ¤   buf2 >>= w2bits;
8d419a ¤   ¤   mult2pos = e1bits - w1bits + w2bits;
7a36c0 ¤   ¤   while ((buf2 & 1) == 0) {
454424 ¤   ¤   ¤   buf2 >>= 1;
ab7c51 ¤   ¤   ¤   mult2pos++;
740fe4 ¤   ¤   }
590b1f ¤   ¤   pgpAssert(mult2pos <= e1bits);
1f4925 ¤   ¤   mult2 = table2[buf2>>1];
4cf975 ¤   ¤   buf2 = i;
b8af5a
50483e ¤   ¤   if (mult2pos == e1bits) {
f16ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
b38c88 ¤   ¤   ¤   if (isone) {
394595 ¤   ¤   ¤   ¤   bniCopy_32(t, b, mlen);¤/* Copy low to high */
e12e60 ¤   ¤   ¤   ¤   isone = 0;
e9042d ¤   ¤   ¤   } else {
2e4a3f ¤   ¤   ¤   ¤   bniMontMul_32(a, t, b, mod, mlen, inv);
2c51ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
f3a3a6 ¤   ¤   ¤   }
170fe4 ¤   ¤   }
1a9371 ¤   }
2daf5a
83d8af ¤   /*
a080e3 ¤   ·* At this point, the buffer (which is the high half of b)
1f1e26 ¤   ·* holds either 1 (implicitly, as the "isone" flag is set),
6c8889 ¤   ·* n1^2, n2^2 or n1^2 * n2^2.
2da4e3 ¤   ·*/
7aaf5a
eed8af ¤   /*
c89409 ¤   ·* The main loop. ·The procedure is:
--9cd7 000dd3fc96a40100152 Page 42 of bni32.c
a09d84 ¤   ·* - Advance the windows
5fa32c ¤   ·* - If the most-significant bit of a window is set,
380c66 ¤   ·* ··schedule a multiply for the appropriate time in the
ca375c ¤   ·* ··future (may be immediately)
4a383a ¤   ·* - Perform any pending multiples
e36d15 ¤   ·* - Check for termination
a91333 ¤   ·* - Square the buffers
b19714 ¤   ·*
6f7202 ¤   ·* At any given time, the acumulated product is held in
df0d21 ¤   ·* the high half of b.
13a4e3 ¤   ·*/
01220e ¤   for (;;) {
65e85a ¤   ¤   e1bits--;
edaf5a
9f2bc3 ¤   ¤   /* Advance the windows */
e269b3 ¤   ¤   pgpAssert(buf1 < tblmask);
d6d73a ¤   ¤   buf1 <<= 1;
31ea8d ¤   ¤   pgpAssert(buf2 < tblmask);
8c013d ¤   ¤   buf2 <<= 1;
2d1b17 ¤   ¤   /*
72e0cb ¤   ¤   ·* This reads ahead of the current exponent position
92ead0 ¤   ¤   ·* (controlled by e1bits), so we have to be able to read
6b969f ¤   ¤   ·* past the lsb of the exponents without error.
8e9de3 ¤   ¤   ·*/
e7d14f ¤   ¤   if (e1len) {
030cd9 ¤   ¤   ¤   buf1 |= ((*e1 & bitpos) != 0);
f0f670 ¤   ¤   ¤   if (e1len <= e2len)
647ab8 ¤   ¤   ¤   ¤   buf2 |= ((*e2 & bitpos) != 0);
23d9f8 ¤   ¤   ¤   bitpos >>= 1;
4b4afe ¤   ¤   ¤   if (!bitpos) {
d03377 ¤   ¤   ¤   ¤   BIGLITTLE(e1++,e1--);
ff7d8c ¤   ¤   ¤   ¤   if (e1len <= e2len)
effd57 ¤   ¤   ¤   ¤   ¤   BIGLITTLE(e2++,e2--);
61f202 ¤   ¤   ¤   ¤   bitpos = (BNWORD32)1 << (32-1);
15096d ¤   ¤   ¤   ¤   e1len--;
73a3a6 ¤   ¤   ¤   }
950fe4 ¤   ¤   }
a5af5a
0456b0 ¤   ¤   /* Examine the first window for pending multiplies */
e335ac ¤   ¤   if (buf1 & tblmask) {
f4cacd ¤   ¤   ¤   mult1pos = e1bits - w1bits;
1a01cd ¤   ¤   ¤   while ((buf1 & 1) == 0) {
496446 ¤   ¤   ¤   ¤   buf1 >>= 1;
9200e4 ¤   ¤   ¤   ¤   mult1pos++;
3aa3a6 ¤   ¤   ¤   }
58b920 ¤   ¤   ¤   /* Intermediates can wrap, but final must NOT */
603542 ¤   ¤   ¤   pgpAssert(mult1pos <= e1bits);
0f0279 ¤   ¤   ¤   mult1 = table1[buf1>>1];
20747c ¤   ¤   ¤   buf1 = 0;
b70fe4 ¤   ¤   }
e1af5a
951b17 ¤   ¤   /*
d47036 ¤   ¤   ·* Examine the second window for pending multiplies.
7df9d2 ¤   ¤   ·* Window 2 can be smaller than window 1, but we
563db6 ¤   ¤   ·* keep the same number of bits in buf2, so we need
b16701 ¤   ¤   ·* to ignore any low-order bits in the buffer when
f34911 ¤   ¤   ·* computing what to multiply by, and recompute them
bbee26 ¤   ¤   ·* later.
949de3 ¤   ¤   ·*/
2aedd2 ¤   ¤   if (buf2 & tblmask) {
981477 ¤   ¤   ¤   /* Remember low-order bits for later */
aea4f4 ¤   ¤   ¤   i = buf2 & ((1u << w2bits) - 1);
3cfcd8 ¤   ¤   ¤   buf2 >>= w2bits;
a41307 ¤   ¤   ¤   mult2pos = e1bits - w1bits + w2bits;
8bd9b3 ¤   ¤   ¤   while ((buf2 & 1) == 0) {
59b241 ¤   ¤   ¤   ¤   buf2 >>= 1;
6d8a34 ¤   ¤   ¤   ¤   mult2pos++;
faa3a6 ¤   ¤   ¤   }
a20553 ¤   ¤   ¤   pgpAssert(mult2pos <= e1bits);
91744d ¤   ¤   ¤   mult2 = table2[buf2>>1];
93c3ef ¤   ¤   ¤   buf2 = i;
dd0fe4 ¤   ¤   }
--2bc1 0001136a58240100152 Page 43 of bni32.c
e0af5a
1aaf5a
30591b ¤   ¤   /* If we have a pending multiply for e1, do it */
1d7851 ¤   ¤   if (e1bits == mult1pos) {
b2a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
d56ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
5f8c88 ¤   ¤   ¤   if (isone) {
d16b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
c45eac ¤   ¤   ¤   ¤   bniCopy_32(t, mult1, mlen);
6f2e60 ¤   ¤   ¤   ¤   isone = 0;
26042d ¤   ¤   ¤   } else {
aaf3b0 ¤   ¤   ¤   ¤   bniMontMul_32(a, t, mult1, mod, mlen, inv);
d96783 ¤   ¤   ¤   ¤   /* Swap a and b */
5451ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
aca3a6 ¤   ¤   ¤   }
d70fe4 ¤   ¤   }
8baf5a
83def5 ¤   ¤   /* If we have a pending multiply for e2, do it */
7bf281 ¤   ¤   if (e1bits == mult2pos) {
c3a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
0d6ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
af8c88 ¤   ¤   ¤   if (isone) {
786b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
e32ac5 ¤   ¤   ¤   ¤   bniCopy_32(t, mult2, mlen);
a92e60 ¤   ¤   ¤   ¤   isone = 0;
10042d ¤   ¤   ¤   } else {
659a5b ¤   ¤   ¤   ¤   bniMontMul_32(a, t, mult2, mod, mlen, inv);
ea6783 ¤   ¤   ¤   ¤   /* Swap a and b */
3751ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
30a3a6 ¤   ¤   ¤   }
540fe4 ¤   ¤   }
d1af5a
797b03 ¤   ¤   /* Are we done? */
3f824a ¤   ¤   if (!e1bits)
fecdcb ¤   ¤   ¤   break;
77af5a
08f1d1 ¤   ¤   /* Square the buffer */
e09d17 ¤   ¤   if (!isone) {
1a6ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
f63eed ¤   ¤   ¤   bniMontSquare_32(a, t, mod, mlen, inv);
2aebfc ¤   ¤   ¤   /* Swap a and b */
c06c84 ¤   ¤   ¤   t = a; a = b; b = t;
d60fe4 ¤   ¤   }
98074b #if BNYIELD
599bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
a474c2 ¤   ¤   ¤   goto yield;
be7454 #endif
57d6a0 ¤   } /* for (;;) */
ecaf5a
cb5f64 ¤   pgpAssert(!isone);
f2f48a ¤   pgpAssert(!buf1);
8bd147 ¤   pgpAssert(!buf2);
0baf5a
262111 ¤   /* DONE! */
4baf5a
738619 ¤   /* Convert result out of Montgomery form */
232576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
1be875 ¤   bniCopy_32(b, t, mlen);
456299 ¤   bniZero_32(t, mlen);
3d820a ¤   bniMontReduce_32(b, mod, mlen, inv);
2f1b0f ¤   bniCopy_32(result, t, mlen);
46af5a
4566e6 ¤   /* Clean up - free intermediate storage */
fe4aa5 ¤   y = 0;
7b074b #if BNYIELD
70f924 yield:
c07454 #endif
7eec82 ¤   buf2 = tblmask >> w2bits;
10c7d7 ¤   while (--tblmask) {
52369c ¤   ¤   if (tblmask < buf2)
08fb65 ¤   ¤   ¤   BNIFREE(table2[tblmask], mlen);
11cec9 ¤   ¤   BNIFREE(table1[tblmask], mlen);
--5e33 0008c5b153a40100152 Page 44 of bni32.c
a19371 ¤   }
f93a43 ¤   t = table1[0];
474807 ¤   BNIFREE(t, mlen);
47ac28 ¤   BNIFREE(b, 2*mlen);
762bc6 ¤   BNIFREE(a, 2*mlen);
77af5a
f9f88b ¤   return y;¤  /* Success */
adefe6 }
02af5a
2838e5 /*
0b75fe ·* 2^exp (mod mod). ·This is an optimized version for use in Fermat
75e1e7 ·* tests. ·The input value of n is ignored; it is returned with
b25d48 ·* "mlen" words valid.
b3495d ·*/
9d4d2f int
03f6dc bniTwoExpMod_32(
4f0598 ¤   PGPMemoryMgrRef¤mgr, PGPBoolean secure,
86b67a ¤   BNWORD32 *n, BNWORD32 const *exp, unsigned elen,
e94034 ¤   BNWORD32 *mod, unsigned mlen)
74bb36 {
439586 ¤   unsigned e;¤/* Copy of high words of the exponent */
468a45 ¤   unsigned bits;¤ /* Assorted counter of bits */
eb550f ¤   BNWORD32 const *bitptr;
67615a ¤   BNWORD32 bitword, bitpos;
0da00b ¤   BNWORD32 *a, *b, *a1;
bb14b8 ¤   BNWORD32 inv;
4fd4d6 ¤   int y;¤ ¤   /* Result of bnYield() */
ebaf5a
99c613 ¤   pgpAssert(mlen);
78af5a
3c68b8 ¤   bitptr = BIGLITTLE(exp-elen, exp+elen-1);
055646 ¤   bitword = *bitptr;
94dac6 ¤   pgpAssert(bitword);
94af5a
b26c02 ¤   /* Clear n for future use. */
d381ac ¤   bniZero_32(n, mlen);
acaf5a
0f90dc ¤   bits = bniBits_32(exp, elen);
3567c5 ¤
eb7d28 ¤   /* First, a couple of trivial cases. */
4e3d59 ¤   if (bits <= 1) {
7204f3 ¤   ¤   /* 2 ^ 0 == 1, ·2 ^ 1 == 2 */
a65f7a ¤   ¤   BIGLITTLE(n[-1],n[0]) = (BNWORD32)1<<elen;
f6bbde ¤   ¤   return 0;
5e9371 ¤   }
6aaf5a
4558f7 ¤   /* Set bitpos to the most significant bit */
442af4 ¤   bitpos = (BNWORD32)1 << ((bits-1) & (32-1));
dbaf5a
2bc6b9 ¤   /* Now, count the bits in the modulus. */
89f7b1 ¤   bits = bniBits_32(mod, mlen);
691a06 ¤   pgpAssert(bits > 1);¤   /* a 1-bit modulus is just stupid... */
deaf5a
3ed8af ¤   /*
5aa0aa ¤   ·* We start with 1<<e, where "e" is as many high bits of the
5e2f39 ¤   ·* exponent as we can manage without going over the modulus.
f80fed ¤   ·* This first loop finds "e".
23a4e3 ¤   ·*/
bf142a ¤   e = 1;
d72e54 ¤   while (elen) {
8d6961 ¤   ¤   /* Consume the first bit */
861e4d ¤   ¤   bitpos >>= 1;
90a81f ¤   ¤   if (!bitpos) {
6de0f0 ¤   ¤   ¤   if (!--elen)
8af622 ¤   ¤   ¤   ¤   break;
f52e5d ¤   ¤   ¤   bitword = BIGLITTLE(*++bitptr,*--bitptr);
cdd1bb ¤   ¤   ¤   bitpos = (BNWORD32)1<<(32-1);
b20fe4 ¤   ¤   }
af81e8 ¤   ¤   e = (e << 1) | ((bitpos & bitword) != 0);
5f9a93 ¤   ¤   if (e >= bits) {¤   /* Overflow! ·Back out. */
51895c ¤   ¤   ¤   e >>= 1;
8ccdcb ¤   ¤   ¤   break;
--d952 00054ee43f040100152 Page 45 of bni32.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
eed8af ¤   /*
36ce46 ¤   ·* The bit in "bitpos" being examined by the bit buffer has NOT
9a276b ¤   ·* been consumed yet. ·This may be past the end of the exponent,
94f3bd ¤   ·* in which case elen == 1.
d3a4e3 ¤   ·*/
cdaf5a
adf10e ¤   /* Okay, now, set bit "e" in n. ·n is already zero. */
6159ab ¤   inv = (BNWORD32)1 << (e & (32-1));
a59a1b ¤   e /= 32;
5039b7 ¤   BIGLITTLE(n[-e-1],n[e]) = inv;
d6d8af ¤   /*
abbe4e ¤   ·* The effective length of n in words is now "e+1".
7eb121 ¤   ·* This is used a little bit later.
71a4e3 ¤   ·*/
76af5a
fbde10 ¤   if (!elen)
0f2875 ¤   ¤   return 0;¤  /* That was easy! */
94af5a
aed8af ¤   /*
51c0f9 ¤   ·* We have now processed the first few bits. ·The next step
1def9b ¤   ·* is to convert this to Montgomery form for further squaring.
b3a4e3 ¤   ·*/
99af5a
cecc1d ¤   /* Allocate working storage: two product buffers */
53f2b6 ¤   BNIALLOC(mgr, secure, a, BNWORD32, 2*mlen);
729293 ¤   if (!a)
b5043c ¤   ¤   return -1;
bd0140 ¤   BNIALLOC(mgr, secure, b, BNWORD32, 2*mlen);
d85215 ¤   if (!b) {
79dda3 ¤   ¤   BNIFREE(a, 2*mlen);
8c043c ¤   ¤   return -1;
c99371 ¤   }
b9af5a
6ad2c8 ¤   /* Convert n to Montgomery form */
20fe5c ¤   inv = BIGLITTLE(mod[-1],mod[0]);¤   /* LSW of modulus */
6fa263 ¤   pgpAssert(inv & 1);¤/* Modulus must be odd */
7e3447 ¤   inv = bniMontInv1_32(inv);
997b0c ¤   /* Move n (length e+1, remember?) up "mlen" words into b */
b31ca2 ¤   /* Note that we lie about a1 for a bit - it's pointing to b */
f1eed0 ¤   a1 = BIGLITTLE(b-mlen,b+mlen);
94e56b ¤   bniCopy_32(a1, n, e+1);
2a5819 ¤   bniZero_32(b, mlen);
6ecd45 ¤   /* Do the division - dump the quotient into the high-order words */
000a49 ¤   (void)bniDiv_32(a1, b, mlen+e+1, mod, mlen);
5fd8af ¤   /*
117cbb ¤   ·* Now do the first squaring and modular reduction to put
08bad9 ¤   ·* the number up in a1 where it belongs.
0fa4e3 ¤   ·*/
71fe97 ¤   bniMontSquare_32(a, b, mod, mlen, inv);
d48266 ¤   /* Fix up a1 to point to where it should go. */
bda2f6 ¤   a1 = BIGLITTLE(a-mlen,a+mlen);
bdaf5a
3fd8af ¤   /*
18a8c4 ¤   ·* Okay, now, a1 holds the number being accumulated, and
dbe460 ¤   ·* b is a scratch register. ·Start working:
68a4e3 ¤   ·*/
e5220e ¤   for (;;) {
cb1b17 ¤   ¤   /*
c2fe25 ¤   ¤   ·* Is the bit set? ·If so, double a1 as well.
b805df ¤   ¤   ·* A modular doubling like this is very cheap.
749de3 ¤   ¤   ·*/
9b26ed ¤   ¤   if (bitpos & bitword) {
1b7aad ¤   ¤   ¤   /*
4b50e7 ¤   ¤   ¤   ·* Double the number. ·If there was a carry out OR
b066f7 ¤   ¤   ¤   ·* the result is greater than the modulus, subract
d4d530 ¤   ¤   ¤   ·* the modulus.
e78753 ¤   ¤   ¤   ·*/
743522 ¤   ¤   ¤   if (bniDouble_32(a1, mlen) ||
cf8512 ¤   ¤   ¤   ····bniCmp_32(a1, mod, mlen) > 0)
543138 ¤   ¤   ¤   ¤   (void)bniSubN_32(a1, mod, mlen);
--4722 0005a27739f40100152 Page 46 of bni32.c
b50fe4 ¤   ¤   }
e6af5a
8a10bb ¤   ¤   /* Advance to the next exponent bit */
111e4d ¤   ¤   bitpos >>= 1;
57a81f ¤   ¤   if (!bitpos) {
1ce0f0 ¤   ¤   ¤   if (!--elen)
276282 ¤   ¤   ¤   ¤   break;¤ /* Done! */
ff2e5d ¤   ¤   ¤   bitword = BIGLITTLE(*++bitptr,*--bitptr);
69d1bb ¤   ¤   ¤   bitpos = (BNWORD32)1<<(32-1);
8f0fe4 ¤   ¤   }
f4af5a
071b17 ¤   ¤   /*
e282e5 ¤   ¤   ·* The elen/bitword/bitpos bit buffer is known to be
8e511a ¤   ¤   ·* non-empty, i.e. there is at least one more unconsumed bit.
7521d7 ¤   ¤   ·* Thus, it's safe to square the number.
6e9de3 ¤   ¤   ·*/
e54701 ¤   ¤   bniMontSquare_32(b, a1, mod, mlen, inv);
285dee ¤   ¤   /* Rename result (in b) back to a (a1, really). */
bb7e82 ¤   ¤   a1 = b; b = a; a = a1;
a2e305 ¤   ¤   a1 = BIGLITTLE(a-mlen,a+mlen);
a5074b #if BNYIELD
a69bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
0a74c2 ¤   ¤   ¤   goto yield;
627454 #endif
849371 ¤   }
daaf5a
422009 ¤   /* DONE! ·Just a little bit of cleanup... */
7eaf5a
9bd8af ¤   /*
e54b9e ¤   ·* Convert result out of Montgomery form... this is
7f5cb3 ¤   ·* just a Montgomery reduction.
8ca4e3 ¤   ·*/
97e96f ¤   bniCopy_32(a, a1, mlen);
cd47b9 ¤   bniZero_32(a1, mlen);
f7ebe1 ¤   bniMontReduce_32(a, mod, mlen, inv);
1c768b ¤   bniCopy_32(n, a1, mlen);
16af5a
dd66e6 ¤   /* Clean up - free intermediate storage */
da4aa5 ¤   y = 0;
8e074b #if BNYIELD
baf924 yield:
d47454 #endif
d0ac28 ¤   BNIFREE(b, 2*mlen);
1d2bc6 ¤   BNIFREE(a, 2*mlen);
aeaf5a
62f88b ¤   return y;¤  /* Success */
66efe6 }
aaaf5a
b5af5a
8938e5 /*
feb33d ·* Returns a substring of the big-endian array of bytes representation
6cb3f8 ·* of the bignum array based on two parameters, the least significant
0e05a1 ·* byte number (0 to start with the least significant byte) and the
9e831e ·* length. ·I.e. the number returned is a representation of
9fca57 ·* (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
41775e ·*
8966af ·* It is an error if the bignum is not at least buflen + lsbyte bytes
0303a5 ·* long.
82775e ·*
f208c9 ·* This code assumes that the compiler has the minimal intelligence·
16be7b ·* neded to optimize divides and modulo operations on an unsigned data
a45fd8 ·* type with a power of two.
cc495d ·*/
41314a void
04a779 bniExtractBigBytes_32(BNWORD32 const *n, unsigned char *buf,
9a163a ¤   unsigned lsbyte, unsigned buflen)
78bb36 {
5f73df ¤   BNWORD32 t = 0;¤/* Needed to shut up uninitialized var warnings */
ae7dd8 ¤   unsigned shift;
e3af5a
2229ec ¤   lsbyte += buflen;
5aaf5a
--f375 0009ead2fd340100152 Page 47 of bni32.c
65f06f ¤   shift = (8 * lsbyte) % 32;
03eb6b ¤   lsbyte /= (32/8);¤  /* Convert to word offset */
90378b ¤   BIGLITTLE(n -= lsbyte, n += lsbyte);
59af5a
b05bcd ¤   if (shift)
bc23e5 ¤   ¤   t = BIGLITTLE(n[-1],n[0]);
80af5a
9d98f0 ¤   while (buflen--) {
f9bc36 ¤   ¤   if (!shift) {
2d4e1a ¤   ¤   ¤   t = BIGLITTLE(*n++,*--n);
bc4fb2 ¤   ¤   ¤   shift = 32;
ca0fe4 ¤   ¤   }
432ad4 ¤   ¤   shift -= 8;
2e5443 ¤   ¤   *buf++ = (unsigned char)(t>>shift);
e09371 ¤   }
efefe6 }
abaf5a
f838e5 /*
6c987d ·* Merge a big-endian array of bytes into a bignum array.
32225f ·* The array had better be big enough. ·This is
219651 ·* equivalent to extracting the entire bignum into a
58e36b ·* large byte array, copying the input buffer into the
e04fc8 ·* middle of it, and converting back to a bignum.
08775e ·*
78bf48 ·* The buf is "len" bytes long, and its *last* byte is at
f0714c ·* position "lsbyte" from the end of the bignum.
bb775e ·*
2e2e7d ·* Note that this is a pain to get right. ·Fortunately, it's hardly
3c7bdc ·* critical for efficiency.
61495d ·*/
7d314a void
ceb40d bniInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf,
86a951 ··················unsigned lsbyte, ·unsigned buflen)
babb36 {
291542 ¤   BNWORD32 t = 0;¤/* Shut up uninitialized varibale warnings */
d9af5a
4429ec ¤   lsbyte += buflen;
cdaf5a
31d30f ¤   BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8));
d6af5a
a16297 ¤   /* Load up leading odd bytes */
204bb9 ¤   if (lsbyte % (32/8)) {
07a3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
cdae85 ¤   ¤   t >>= (lsbyte * 8) % 32;
6b9371 ¤   }
7caf5a
5e0bd3 ¤   /* The main loop - merge into t, storing at each word boundary. */
f398f0 ¤   while (buflen--) {
1613b9 ¤   ¤   t = (t << 8) | *buf++;
f6956d ¤   ¤   if ((--lsbyte % (32/8)) == 0)
9f9b8b ¤   ¤   ¤   BIGLITTLE(*n++,*--n) = t;
379371 ¤   }
1faf5a
9345dc ¤   /* Merge odd bytes in t into last word */
9cbb15 ¤   lsbyte = (lsbyte * 8) % 32;
4444bd ¤   if (lsbyte) {
5e8687 ¤   ¤   t <<= lsbyte;
80511f ¤   ¤   t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
0cbca8 ¤   ¤   BIGLITTLE(n[0],n[-1]) = t;
af9371 ¤   }
99af5a
e3830f ¤   return;
32efe6 }
4eaf5a
bf38e5 /*
e90e40 ·* Returns a substring of the little-endian array of bytes representation
b9b3f8 ·* of the bignum array based on two parameters, the least significant
ce05a1 ·* byte number (0 to start with the least significant byte) and the
f1831e ·* length. ·I.e. the number returned is a representation of
60ca57 ·* (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
23775e ·*
9e66af ·* It is an error if the bignum is not at least buflen + lsbyte bytes
--8fa9 000c9c7b71640100152 Page 48 of bni32.c
9203a5 ·* long.
08775e ·*
de08c9 ·* This code assumes that the compiler has the minimal intelligence·
09be7b ·* neded to optimize divides and modulo operations on an unsigned data
a15fd8 ·* type with a power of two.
f9495d ·*/
c9314a void
9f8be7 bniExtractLittleBytes_32(BNWORD32 const *n, unsigned char *buf,
f6163a ¤   unsigned lsbyte, unsigned buflen)
9dbb36 {
9a73df ¤   BNWORD32 t = 0;¤/* Needed to shut up uninitialized var warnings */
9faf5a
a2d30f ¤   BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8));
bfaf5a
874bb9 ¤   if (lsbyte % (32/8)) {
86a3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
c6c517 ¤   ¤   t >>= (lsbyte % (32/8)) * 8 ;
6a9371 ¤   }
75af5a
e898f0 ¤   while (buflen--) {
1516e7 ¤   ¤   if ((lsbyte++ % (32/8)) == 0)
484cd1 ¤   ¤   ¤   t = BIGLITTLE(*--n,*n++);
ad8d7c ¤   ¤   *buf++ = (unsigned char)t;
f3e6a0 ¤   ¤   t >>= 8;
0b9371 ¤   }
b2efe6 }
6caf5a
9738e5 /*
56f64f ·* Merge a little-endian array of bytes into a bignum array.
34225f ·* The array had better be big enough. ·This is
f89651 ·* equivalent to extracting the entire bignum into a
8be36b ·* large byte array, copying the input buffer into the
284fc8 ·* middle of it, and converting back to a bignum.
62775e ·*
62ef01 ·* The buf is "len" bytes long, and its first byte is at
22714c ·* position "lsbyte" from the end of the bignum.
6e775e ·*
152e7d ·* Note that this is a pain to get right. ·Fortunately, it's hardly
8a7bdc ·* critical for efficiency.
8c495d ·*/
0b314a void
7e8f72 bniInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf,
30a951 ··················unsigned lsbyte, ·unsigned buflen)
b1bb36 {
961542 ¤   BNWORD32 t = 0;¤/* Shut up uninitialized varibale warnings */
f6af5a
20be7c ¤   /* Move to most-significant end */
ed29ec ¤   lsbyte += buflen;
5c4a44 ¤   buf += buflen;
abaf5a
c1d30f ¤   BIGLITTLE(n -= lsbyte/(32/8), n += lsbyte/(32/8));
54af5a
d86297 ¤   /* Load up leading odd bytes */
c84bb9 ¤   if (lsbyte % (32/8)) {
3aa3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
94ae85 ¤   ¤   t >>= (lsbyte * 8) % 32;
a79371 ¤   }
ceaf5a
940bd3 ¤   /* The main loop - merge into t, storing at each word boundary. */
8598f0 ¤   while (buflen--) {
98033f ¤   ¤   t = (t << 8) | *--buf;
62956d ¤   ¤   if ((--lsbyte % (32/8)) == 0)
ec9b8b ¤   ¤   ¤   BIGLITTLE(*n++,*--n) = t;
0e9371 ¤   }
e4af5a
9d45dc ¤   /* Merge odd bytes in t into last word */
5dbb15 ¤   lsbyte = (lsbyte * 8) % 32;
4b44bd ¤   if (lsbyte) {
b58687 ¤   ¤   t <<= lsbyte;
1f511f ¤   ¤   t |= (((BNWORD32)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
0fbca8 ¤   ¤   BIGLITTLE(n[0],n[-1]) = t;
c99371 ¤   }
--0732 000705f645540100152 Page 49 of bni32.c
e0af5a
c3830f ¤   return;
5fefe6 }
b0af5a
4cf6c3 #ifdef DEADCODE¤/* This was a precursor to the more flexible bniExtractBytes */
b538e5 /*
98b36e ·* Convert a big-endian array of bytes to a bignum.
caabb4 ·* Returns the number of words in the bignum.
788f80 ·* Note the expression "32/8" for the number of bytes per word.
08cd11 ·* This is so the word-size adjustment will work.
03495d ·*/
20536c unsigned
358f21 bniFromBytes_32(BNWORD32 *a, unsigned char const *b, unsigned blen)
edbb36 {
9df9fc ¤   BNWORD32 t;
4267ec ¤   unsigned alen = (blen + (32/8-1))/(32/8);
d0dbd6 ¤   BIGLITTLE(a -= alen, a += alen);
ebaf5a
3eb25a ¤   while (blen) {
e40550 ¤   ¤   t = 0;
a54392 ¤   ¤   do {
0dc682 ¤   ¤   ¤   t = t << 8 | *b++;
0d6d77 ¤   ¤   } while (--blen & (32/8-1));
4e64ff ¤   ¤   BIGLITTLE(*a++,*--a) = t;
7a9371 ¤   }
95c2b6 ¤   return alen;
c8efe6 }
b57454 #endif
2eaf5a
fa38e5 /*
deaf62 ·* Computes the GCD of a and b. ·Modifies both arguments; when it returns,
4ae261 ·* one of them is the GCD and the other is trash. ·The return value
22d234 ·* indicates which: 0 for a, and 1 for b. ·The length of the retult is
213d14 ·* returned in rlen. ·Both inputs must have one extra word of precision.
5ebfe3 ·* alen must be >= blen.
da775e ·*
13537b ·* TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B).
8f6ece ·* This is based on taking out common powers of 2, then repeatedly:
62604a ·* gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted.
252ace ·* gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced.
948a0c ·* It gets less reduction per step, but the steps are much faster than
9479ed ·* the division case.
d1495d ·*/
c24d2f int
18b682 bniGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen,
1a76c7 ¤   unsigned *rlen)
93bb36 {
27074b #if BNYIELD
e5ce31 ¤   int y;
fb7454 #endif
0f64c5 ¤   pgpAssert(alen >= blen);
72af5a
ebfbe1 ¤   while (blen != 0) {
93e9a1 ¤   ¤   (void)bniDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
ab4f62 ¤   ¤   alen = bniNorm_32(a, blen);
1c8bb3 ¤   ¤   if (alen == 0) {
73e6e3 ¤   ¤   ¤   *rlen = blen;
bedb98 ¤   ¤   ¤   return 1;
5d0fe4 ¤   ¤   }
1dc071 ¤   ¤   (void)bniDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
60c956 ¤   ¤   blen = bniNorm_32(b, alen);
62074b #if BNYIELD
ff9bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
dc1b2c ¤   ¤   ¤   return y;
cd7454 #endif
7a9371 ¤   }
a717b1 ¤   *rlen = alen;
913e6b ¤   return 0;
4befe6 }
06af5a
3538e5 /*
703401 ·* Invert "a" modulo "mod" using the extended Euclidean algorithm.
--9967 00080f8004140100152 Page 50 of bni32.c
0c81f2 ·* Note that this only computes one of the cosequences, and uses the
8cbe84 ·* theorem that the signs flip every step and the absolute value of
9eea0f ·* the cosequence values are always bounded by the modulus to avoid
bb1a6c ·* having to work with negative numbers.
2c7b80 ·* gcd(a,mod) had better equal 1. ·Returns 1 if the GCD is NOT 1.
cc9798 ·* a must be one word longer than "mod". ·It is overwritten with the
aa1d22 ·* result.
b06b11 ·* TODO: Use Richard Schroeppel's *much* faster algorithm.
3a495d ·*/
cb4d2f int
80ea46 bniInv_32(
366740 ¤   PGPMemoryMgrRef¤mgr,
f554d3 ¤   PGPBoolean secure,
1310b8 ¤   BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen)
8ebb36 {
b613fa ¤   BNWORD32 *b;¤   /* Hold a copy of mod during GCD reduction */
e2869d ¤   BNWORD32 *p;¤   /* Temporary for products added to t0 and t1 */
e47058 ¤   BNWORD32 *t0, *t1;¤ /* Inverse accumulators */
aa1a74 ¤   BNWORD32 cy;
affc25 ¤   unsigned blen, t0len, t1len, plen;
9dce31 ¤   int y;
f5af5a
776cf0 ¤   alen = bniNorm_32(a, alen);
40cebc ¤   if (!alen)
b562ef ¤   ¤   return 1;¤  /* No inverse */
d8af5a
e1fb28 ¤   mlen = bniNorm_32(mod, mlen);
a9af5a
1f846b ¤   pgpAssert (alen <= mlen);
f6af5a
70cfc2 ¤   /* Inverse of 1 is 1 */
3f5002 ¤   if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) {
27f028 ¤   ¤   bniZero_32(BIGLITTLE(a-alen,a+alen), mlen-alen);
d9bbde ¤   ¤   return 0;
409371 ¤   }
54af5a
a53e0b ¤   /* Allocate a pile of space */
dae710 ¤   BNIALLOC(mgr, secure, b, BNWORD32, mlen+1);
f75359 ¤   if (b) {
651b17 ¤   ¤   /*
4733b9 ¤   ¤   ·* Although products are guaranteed to always be less than the
506531 ¤   ¤   ·* modulus, it can involve multiplying two 3-word numbers to
fcc163 ¤   ¤   ·* get a 5-word result, requiring a 6th word to store a 0
55a773 ¤   ¤   ·* temporarily. ·Thus, mlen + 1.
069de3 ¤   ¤   ·*/
f1ee80 ¤   ¤   BNIALLOC(mgr, secure, p, BNWORD32, mlen+1);
bb4400 ¤   ¤   if (p) {
6e8c1b ¤   ¤   ¤   BNIALLOC(mgr, secure, t0, BNWORD32, mlen);
41da36 ¤   ¤   ¤   if (t0) {
ac5476 ¤   ¤   ¤   ¤   BNIALLOC(mgr, secure, t1, BNWORD32, mlen);
ae5d06 ¤   ¤   ¤   ¤   if (t1)
2d5da1 ¤   ¤   ¤   ¤   ¤   ¤   goto allocated;
c91674 ¤   ¤   ¤   ¤   BNIFREE(t0, mlen);
9ea3a6 ¤   ¤   ¤   }
450620 ¤   ¤   ¤   BNIFREE(p, mlen+1);
3a0fe4 ¤   ¤   }
58bc1d ¤   ¤   BNIFREE(b, mlen+1);
f49371 ¤   }
36e69f ¤   return -1;
dbaf5a
99af26 allocated:
2aaf5a
9f1bb7 ¤   /* Set t0 to 1 */
e9abc7 ¤   t0len = 1;
a68f84 ¤   BIGLITTLE(t0[-1],t0[0]) = 1;
8f67c5 ¤
dcd0b9 ¤   /* b = mod */
2f92e1 ¤   bniCopy_32(b, mod, mlen);
133db3 ¤   /* blen = mlen (implicitly) */
e567c5 ¤
e5d980 ¤   /* t1 = b / a; b = b % a */
80cdd4 ¤   cy = bniDiv_32(t1, b, mlen, a, alen);
--4d95 000649fa2a940100152 Page 51 of bni32.c
97107b ¤   *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy;
0bfd3c ¤   t1len = bniNorm_32(t1, mlen-alen+1);
e942aa ¤   blen = bniNorm_32(b, alen);
87af5a
2caa55 ¤   /* while (b > 1) */
2c5edd ¤   while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD32)1) {
e13f9a ¤   ¤   /* q = a / b; a = a % b; */
599eba ¤   ¤   if (alen < blen || (alen == blen && bniCmp_32(a, a, alen) < 0))
a1b783 ¤   ¤   ¤   pgpAssert(0);
f66ed4 ¤   ¤   cy = bniDiv_32(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
610118 ¤   ¤   *(BIGLITTLE(a-alen-1,a+alen)) = cy;
4126d4 ¤   ¤   plen = bniNorm_32(BIGLITTLE(a-blen,a+blen), alen-blen+1);
f3ec44 ¤   ¤   pgpAssert(plen);
594f62 ¤   ¤   alen = bniNorm_32(a, blen);
682c1f ¤   ¤   if (!alen)
8a6b71 ¤   ¤   ¤   goto failure;¤  /* GCD not 1 */
a8af5a
a1c2fe ¤   ¤   /* t0 += q * t1; */
5d7df1 ¤   ¤   pgpAssert(plen+t1len <= mlen+1);
0bd8a1 ¤   ¤   bniMul_32(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len);
939978 ¤   ¤   plen = bniNorm_32(p, plen + t1len);
ae74e7 ¤   ¤   pgpAssert(plen <= mlen);
a37ccf ¤   ¤   if (plen > t0len) {
581a14 ¤   ¤   ¤   bniZero_32(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len);
16b0b8 ¤   ¤   ¤   t0len = plen;
ca0fe4 ¤   ¤   }
0f27c6 ¤   ¤   cy = bniAddN_32(t0, p, plen);
942e8b ¤   ¤   if (cy) {
a879eb ¤   ¤   ¤   if (t0len > plen) {
75accc ¤   ¤   ¤   ¤   cy = bniAdd1_32(BIGLITTLE(t0-plen,t0+plen),
d88447 ¤   ¤   ¤   ¤   ¤   ¤   t0len-plen, cy);
c3a3a6 ¤   ¤   ¤   }
c41411 ¤   ¤   ¤   if (cy) {
858336 ¤   ¤   ¤   ¤   BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy;
c5a7f8 ¤   ¤   ¤   ¤   t0len++;
eea3a6 ¤   ¤   ¤   }
fc0fe4 ¤   ¤   }
06af5a
d980a4 ¤   ¤   /* if (a <= 1) return a ? t0 : FAIL; */
cad6b4 ¤   ¤   if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD32)1) {
303d57 ¤   ¤   ¤   if (alen == 0)
467b91 ¤   ¤   ¤   ¤   goto failure;¤  /* FAIL */
5ae238 ¤   ¤   ¤   pgpAssert(t0len <= mlen);
cfa423 ¤   ¤   ¤   bniCopy_32(a, t0, t0len);
295a77 ¤   ¤   ¤   bniZero_32(BIGLITTLE(a-t0len, a+t0len), mlen-t0len);
e4346a ¤   ¤   ¤   goto success;
dc0fe4 ¤   ¤   }
59af5a
38ad15 ¤   ¤   /* q = b / a; b = b % a; */
088272 ¤   ¤   if (blen < alen || (blen == alen && bniCmp_32(b, a, alen) < 0))
2cb783 ¤   ¤   ¤   pgpAssert(0);
bf4704 ¤   ¤   cy = bniDiv_32(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
e5c9ab ¤   ¤   *(BIGLITTLE(b-blen-1,b+blen)) = cy;
fd8335 ¤   ¤   plen = bniNorm_32(BIGLITTLE(b-alen,b+alen), blen-alen+1);
86ec44 ¤   ¤   pgpAssert(plen);
81c956 ¤   ¤   blen = bniNorm_32(b, alen);
fa2062 ¤   ¤   if (!blen)
3a6b71 ¤   ¤   ¤   goto failure;¤  /* GCD not 1 */
afaf5a
1e48c5 ¤   ¤   /* t1 += q * t0; */
c76dfe ¤   ¤   pgpAssert(plen+t0len <= mlen+1);
028371 ¤   ¤   bniMul_32(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len);
d906ad ¤   ¤   plen = bniNorm_32(p, plen + t0len);
8074e7 ¤   ¤   pgpAssert(plen <= mlen);
98fd70 ¤   ¤   if (plen > t1len) {
6f5d0d ¤   ¤   ¤   bniZero_32(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len);
6bb515 ¤   ¤   ¤   t1len = plen;
f10fe4 ¤   ¤   }
4d226b ¤   ¤   cy = bniAddN_32(t1, p, plen);
e62e8b ¤   ¤   if (cy) {
be31c1 ¤   ¤   ¤   if (t1len > plen) {
64bcc3 ¤   ¤   ¤   ¤   cy = bniAdd1_32(BIGLITTLE(t1-plen,t0+plen),
--7c7b 001821a314e40100152 Page 52 of bni32.c
f90a57 ¤   ¤   ¤   ¤   ¤   ¤   t1len-plen, cy);
dea3a6 ¤   ¤   ¤   }
be1411 ¤   ¤   ¤   if (cy) {
c4f5c1 ¤   ¤   ¤   ¤   BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy;
452647 ¤   ¤   ¤   ¤   t1len++;
49a3a6 ¤   ¤   ¤   }
c40fe4 ¤   ¤   }
9d074b #if BNYIELD
52b0d5 ¤   ¤   if (bnYield && (y = bnYield() < 0))
bc74c2 ¤   ¤   ¤   goto yield;
a27454 #endif
ba9371 ¤   }
7aaf5a
7ac2c1 ¤   if (!blen)
63fa45 ¤   ¤   goto failure;¤  /* gcd(a, mod) != 1 -- FAIL */
d7af5a
9a6f47 ¤   /* return mod-t1 */
f84a9f ¤   bniCopy_32(a, mod, mlen);
0a7269 ¤   pgpAssert(t1len <= mlen);
3b4f9c ¤   cy = bniSubN_32(a, t1, t1len);
7eab3e ¤   if (cy) {
0ba6e8 ¤   ¤   pgpAssert(mlen > t1len);
202485 ¤   ¤   cy = bniSub1_32(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy);
84642a ¤   ¤   pgpAssert(!cy);
569371 ¤   }
44af5a
90d3ad success:
7240e5 ¤   BNIFREE(t1, mlen);
e46cc2 ¤   BNIFREE(t0, mlen);
1f5d1b ¤   BNIFREE(p, mlen+1);
034a78 ¤   BNIFREE(b, mlen+1);
9467c5 ¤
9e3e6b ¤   return 0;
0baf5a
325cfe failure:¤   ¤   /* GCD is not 1 - no inverse exists! */
6a1079 ¤   y = 1;
e9074b #if BNYIELD
92f924 yield:
c77454 #endif
4140e5 ¤   BNIFREE(t1, mlen);
696cc2 ¤   BNIFREE(t0, mlen);
8f5d1b ¤   BNIFREE(p, mlen+1);
f74a78 ¤   BNIFREE(b, mlen+1);
0c67c5 ¤
72a403 ¤   return y;
82efe6 }
--882a 000cc99a04440100153 Page 1 of bni32.h
bc38e5 /*
a7cf2c ·* $Id: bni32.h,v 1.6 1998/05/14 19:07:22 cbertsch Exp $
95495d ·*/
2faf5a
e9a193 #ifndef Included_bni32_h
76e279 #define Included_bni32_h
16af5a
d4a6ac #include "bni.h"
696773 #include "pgpMemoryMgr.h"
37af5a
e6e77e #ifndef BNWORD32
20c47d #error 32-bit bignum library requires a 32-bit data type
107454 #endif
4eaf5a
e399c6 PGP_BEGIN_C_DECLARATIONS
78af5a
21df20 #ifndef bniCopy_32
77071b void bniCopy_32(BNWORD32 *dest, BNWORD32 const *src, unsigned len);
aa7454 #endif
4b4682 #ifndef bniZero_32
201074 void bniZero_32(BNWORD32 *num, unsigned len);
db7454 #endif
73a6aa #ifndef bniNeg_32
3689bf void bniNeg_32(BNWORD32 *num, unsigned len);
ef7454 #endif
fcaf5a
066bd3 #ifndef bniAdd1_32
5868ee BNWORD32 bniAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry);
a47454 #endif
ea0922 #ifndef bniSub1_32
3b553a BNWORD32 bniSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow);
277454 #endif
f0af5a
6014dc #ifndef bniAddN_32
33f7b7 BNWORD32 bniAddN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len);
1e7454 #endif
5f762d #ifndef bniSubN_32
3286c5 BNWORD32 bniSubN_32(BNWORD32 *num1, BNWORD32 const *num2, unsigned len);
957454 #endif
75af5a
892d21 #ifndef bniCmp_32
c2e128 int bniCmp_32(BNWORD32 const *num1, BNWORD32 const *num2, unsigned len);
997454 #endif
d1af5a
ab1bce #ifndef bniMulN1_32
6fbf74 void bniMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k);
e27454 #endif
7713d8 #ifndef bniMulAdd1_32
2ee6d9 BNWORD32
f08dfa bniMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k);
807454 #endif
637129 #ifndef bniMulSub1_32
64a048 BNWORD32 bniMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len,
9b8c15 ¤   ¤   ¤   BNWORD32 k);
d47454 #endif
dcaf5a
e2eded #ifndef bniLshift_32
6a71d6 BNWORD32 bniLshift_32(BNWORD32 *num, unsigned len, unsigned shift);
317454 #endif
e63a52 #ifndef bniDouble_32
e29418 BNWORD32 bniDouble_32(BNWORD32 *num, unsigned len);
5a7454 #endif
a5be44 #ifndef bniRshift_32
7198c3 BNWORD32 bniRshift_32(BNWORD32 *num, unsigned len, unsigned shift);
897454 #endif
b8af5a
d20b98 #ifndef bniMul_32
f4af17 void bniMul_32(BNWORD32 *prod, BNWORD32 const *num1, unsigned len1,
ae8523 ¤   BNWORD32 const *num2, unsigned len2);
f47454 #endif
d4dbc8 #ifndef bniSquare_32
ccccf9 void bniSquare_32(BNWORD32 *prod, BNWORD32 const *num, unsigned len);
--fd4d 0001d47697f40100153 Page 2 of bni32.h
a07454 #endif
e0af5a
86f4fb #ifndef bniNorm_32
b2b91e unsigned bniNorm_32(BNWORD32 const *num, unsigned len);
df7454 #endif
475a56 #ifndef bniBits_32
ce18da unsigned bniBits_32(BNWORD32 const *num, unsigned len);
f77454 #endif
0caf5a
cd4cd6 #ifndef bniExtractBigBytes_32
af7ae6 void bniExtractBigBytes_32(BNWORD32 const *bn, unsigned char *buf,
fb9eef ¤   unsigned lsbyte, unsigned buflen);
117454 #endif
4f1b3d #ifndef bniInsertBigytes_32
1e703e void bniInsertBigBytes_32(BNWORD32 *n, unsigned char const *buf,
337db1 ¤   unsigned lsbyte, ·unsigned buflen);
447454 #endif
6df1ce #ifndef bniExtractLittleBytes_32
019bf7 void bniExtractLittleBytes_32(BNWORD32 const *bn, unsigned char *buf,
a19eef ¤   unsigned lsbyte, unsigned buflen);
b37454 #endif
2a4393 #ifndef bniInsertLittleBytes_32
964b72 void bniInsertLittleBytes_32(BNWORD32 *n, unsigned char const *buf,
fd7db1 ¤   unsigned lsbyte, ·unsigned buflen);
b07454 #endif
d4af5a
87e188 #ifndef bniDiv21_32
767722 BNWORD32 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d);
257454 #endif
1c981b #ifndef bniDiv1_32
48e37f BNWORD32 bniDiv1_32(BNWORD32 *q, BNWORD32 *rem,
38e403 ¤   BNWORD32 const *n, unsigned len, BNWORD32 d);
377454 #endif
fb8780 #ifndef bniModQ_32
f73a41 unsigned bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d);
e57454 #endif
dec10d #ifndef bniDiv_32
79e6d9 BNWORD32
c150ed bniDiv_32(BNWORD32 *q, BNWORD32 *n, unsigned nlen, BNWORD32 *d, unsigned dlen);
897454 #endif
12af5a
56a6a5 #ifndef bniMontInv1_32
532bef BNWORD32 bniMontInv1_32(BNWORD32 const x);
0b7454 #endif
2c158e #ifndef bniMontReduce_32
6e1e34 void bniMontReduce_32(BNWORD32 *n, BNWORD32 const *mod, unsigned const mlen,
124a59 ················BNWORD32 inv);
e67454 #endif
80b129 #ifndef bniToMont_32
e69a31 void bniToMont_32(BNWORD32 *n, unsigned nlen, BNWORD32 *mod, unsigned mlen);
6e7454 #endif
29019d #ifndef bniFromMont_32
0bdee8 void bniFromMont_32(BNWORD32 *n, BNWORD32 *mod, unsigned len);
b27454 #endif
a5af5a
84ea2c #ifndef bniExpMod_32
c87a25 int bniExpMod_32( PGPMemoryMgrRef mgr, PGPBoolean secure,
2e8531 ¤   BNWORD32 *result, BNWORD32 const *n, unsigned nlen,
72cc8f ¤   BNWORD32 const *exp, unsigned elen, BNWORD32 *mod, unsigned mlen);
d97454 #endif
0400a3 #ifndef bniDoubleExpMod_32
04ad1c int bniDoubleExpMod_32(
8139d6 ¤   PGPMemoryMgrRef mgr, PGPBoolean secure,
bbbb4f ¤   BNWORD32 *result,
debf47 ¤   BNWORD32 const *n1, unsigned n1len, BNWORD32 const *e1, unsigned e1len,
c0b83b ¤   BNWORD32 const *n2, unsigned n2len, BNWORD32 const *e2, unsigned e2len,
a877c7 ¤   BNWORD32 *mod, unsigned mlen);
277454 #endif
d37f56 #ifndef bniTwoExpMod_32
77b0bb int bniTwoExpMod_32( PGPMemoryMgrRef mgr, PGPBoolean secure,
35b67a ¤   BNWORD32 *n, BNWORD32 const *exp, unsigned elen,
1d77c7 ¤   BNWORD32 *mod, unsigned mlen);
--070c 0010511319940100153 Page 3 of bni32.h
a07454 #endif
bce2a5 #ifndef bniGcd_32
867e52 int bniGcd_32(BNWORD32 *a, unsigned alen, BNWORD32 *b, unsigned blen,
64b2e5 ¤   unsigned *rlen);
787454 #endif
6df393 #ifndef bniInv_32
1265f9 int bniInv_32( PGPMemoryMgrRef mgr, PGPBoolean secure,
913e85 ¤   ¤   BNWORD32 *a, unsigned alen, BNWORD32 const *mod, unsigned mlen);
f37454 #endif
b8af5a
541254 PGP_END_C_DECLARATIONS
a3af5a
052ced #endif /* Included_bni32_h */
--eb5c 000f35b675540100154 Page 1 of bni64.c
bc38e5 /*
7e66a1 ·* bni64.c - Low-level bignum routines, 64-bit version.
54775e ·*
9168c2 ·* Written by Colin Plumb.
66775e ·*
ee6066 ·* $Id: bni64.c,v 1.8 1998/05/14 19:07:23 cbertsch Exp $
e3775e ·*
352200 ·* NOTE: the magic constants "64" and "128" appear in many places in this
63dd4e ·* file, including inside identifiers. ·Because it is not possible to
fe9667 ·* ask "#ifdef" of a macro expansion, it is not possible to use the
52b031 ·* preprocessor to conditionalize these properly. ·Thus, this file is
54cef9 ·* intended to be edited with textual search and replace to produce
35d844 ·* alternate word size versions. ·Any reference to the number of bits
7f8453 ·* in a word must be the string "64", and that string must not appear
fe5363 ·* otherwise. ·Any reference to twice this number must appear as "128",
45d7d6 ·* which likewise must not appear otherwise. ·Is that clear?
73775e ·*
973214 ·* Remember, when doubling the bit size replace the larger number (128)
df7a19 ·* first, then the smaller (64). ·When halving the bit size, do the
9f0005 ·* opposite. ·Otherwise, things will get wierd. ·Also, be sure to replace
47dfda ·* every instance that appears. ·(:%s/foo/bar/g in vi)
e5775e ·*
f8496a ·* These routines work with a pointer to the least-significant end of
a2e930 ·* an array of WORD64s. ·The BIG(x), LITTLE(y) and BIGLTTLE(x,y) macros
5b3864 ·* defined in bni.h (which expand to x on a big-edian machine and y on a
204cbc ·* little-endian machine) are used to conditionalize the code to work
8cfc72 ·* either way. ·If you have no assembly primitives, it doesn't matter.
2e83f3 ·* Note that on a big-endian machine, the least-significant-end pointer
f8144c ·* is ONE PAST THE END. ·The bytes are ptr[-1] through ptr[-len].
658d7a ·* On little-endian, they are ptr[0] through ptr[len-1]. ·This makes
13fd96 ·* perfect sense if you consider pointers to point *between* bytes rather
4bf32b ·* than at them.
07775e ·*
81f6ef ·* Because the array index values are unsigned integers, ptr[-i]
b453f2 ·* may not work properly, since the index -i is evaluated as an unsigned,
cc0a10 ·* and if pointers are wider, zero-extension will produce a positive
f7da4d ·* number rahter than the needed negative. ·The expression used in this
97eb52 ·* code, *(ptr-i) will, however, work. ·(The array syntax is equivalent
77fbc0 ·* to *(ptr+-i), which is a pretty subtle difference.)
9a775e ·*
b9bcef ·* Many of these routines will get very unhappy if fed zero-length inputs.
4909f7 ·* They use pgpAssert() to enforce this. ·An higher layer of code must make
fdaed6 ·* sure that these aren't called with zero-length inputs.
ce775e ·*
328e44 ·* Any of these routines can be replaced with more efficient versions
f926b0 ·* elsewhere, by just #defining their names. ·If one of the names
1ef8b6 ·* is #defined, the C code is not compiled in and no declaration is
ffcdae ·* made. ·Use the BNINCLUDE file to do that. ·Typically, you compile
e1a2ad ·* asm subroutines with the same name and just, e.g.
f36cf1 ·* #define bniMulAdd1_64 bniMulAdd1_64
95775e ·*
62b3a8 ·* If you want to write asm routines, start with bniMulAdd1_64().
13a1cb ·* This is the workhorse of modular exponentiation. ·bniMulN1_64() is
0c364f ·* also used a fair bit, although not as much and it's defined in terms
c50355 ·* of bniMulAdd1_64 if that has a custom version. ·bniMulSub1_64 and
d53b1a ·* bniDiv21_64 are used in the usual division and remainder finding.
4a8548 ·* (Not the Montgomery reduction used in modular exponentiation, though.)
0b3fd3 ·* Once you have bniMulAdd1_64 defined, writing the other two should
b90aae ·* be pretty easy. ·(Just make sure you get the sign of the subtraction
5de8ac ·* in bniMulSub1_64 right - it's dest = dest - source * k.)
5c775e ·*
fd2834 ·* The only definitions that absolutely need a double-word (BNWORD128)
3b2090 ·* type are bniMulAdd1_64 and bniMulSub1_64; if those are provided,
2441b4 ·* the rest follows. ·bniDiv21_64, however, is a lot slower unless you
e9188e ·* have them, and bniModQ_64 takes after it. ·That one is used quite a
5c70b6 ·* bit for prime sieving.
7b495d ·*/
e1af5a
cee2ff #include "pgpConfig.h"
eeaf5a
a638e5 /*
f316cf ·* Some compilers complain about #if FOO if FOO isn't defined,
--994a 000789026f940100154 Page 2 of bni64.c
e259aa ·* so do the ANSI-mandated thing explicitly...
42495d ·*/
44c60f #ifndef NO_ASSERT_H
22154e #define NO_ASSERT_H 0
ab7454 #endif
72b552 #ifndef NO_STRING_H
3537dd #define NO_STRING_H 0
0f7454 #endif
268537 #ifndef HAVE_STRINGS_H
58025c #define HAVE_STRINGS_H 0
187454 #endif
1b101b #ifndef NEED_MEMORY_H
11ee50 #define NEED_MEMORY_H 0
3a7454 #endif
8faf5a
767668 #if !NO_STRING_H
d77210 #include <string.h>¤/* For memcpy */
15a752 #elif HAVE_STRINGS_H
a3f7c3 #include <strings.h>
3d7454 #endif
983c37 #if NEED_MEMORY_H
66c737 #include <memory.h>
207454 #endif
6faf5a
79a6ac #include "bni.h"
213fc1 #include "bni64.h"
2621db #include "bnimem.h"
1e8cb6 #include "bnlegal.h"
06af5a
984724 #include "bnkludge.h"
42a146 #include "pgpDebug.h"
ecaf5a
698a13 #ifndef BNWORD64
08a67c #error 64-bit bignum library requires a 64-bit data type
eb7454 #endif
f2af5a
dbbfe9 /* Make sure the copyright notice gets included */
6039af volatile const char * volatile const bniCopyright_64 = bnCopyright;
7caf5a
24e387 /* If this is defined, include bnYield() calls */
82074b #if BNYIELD
60976d extern int (*bnYield)(void);¤   /* From bn.c */
8e7454 #endif
55af5a
b038e5 /*
cfd5df ·* Most of the multiply (and Montgomery reduce) routines use an outer
fb9462 ·* loop that iterates over one of the operands - a so-called operand
09398d ·* scanning approach. ·One big advantage of this is that the assembly
dc1aea ·* support routines are simpler. ·The loops can be rearranged to have
b4b971 ·* an outer loop that iterates over the product, a so-called product
c76c0d ·* scanning approach. ·This has the advantage of writing less data
5ac3ee ·* and doing fewer adds to memory, so is supposedly faster. ·Some
c980d7 ·* code has been written using a product-scanning approach, but
fb3d3c ·* it appears to be slower, so it is turned off by default. ·Some
e35e9d ·* experimentation would be appreciated.
9e775e ·*
d26dd6 ·* (The code is also annoying to get right and not very well commented,
8a6688 ·* one of my pet peeves about math libraries. ·I'm sorry.)
79495d ·*/
d87621 #ifndef PRODUCT_SCAN
741212 #define PRODUCT_SCAN 0
d27454 #endif
20af5a
3238e5 /*
4b2e0a ·* Copy an array of words. ·<Marvin mode on> ·Thrilling, isn't it? </Marvin>
3001c1 ·* This is a good example of how the byte offsets and BIGLITTLE() macros work.
5fb38e ·* Another alternative would have been
e53e82 ·* memcpy(dest BIG(-len), src BIG(-len), len*sizeof(BNWORD64)), but I find that
aa84f4 ·* putting operators into conditional macros is confusing.
27495d ·*/
62b24d #ifndef bniCopy_64
78314a void
--0937 00045ba488040100154 Page 3 of bni64.c
77cc07 bniCopy_64(BNWORD64 *dest, BNWORD64 const *src, unsigned len)
fdbb36 {
390967 ¤   memcpy(BIGLITTLE(dest-len,dest), BIGLITTLE(src-len,src),
0bda8b ¤   ·······len * sizeof(*src));
96efe6 }
06dcc1 #endif /* !bniCopy_64 */
ccaf5a
2e38e5 /*
8d3e9e ·* Fill n words with zero. ·This does it manually rather than calling
916f32 ·* memset because it can assume alignment to make things faster while
47c78d ·* memset can't. ·Note how big-endian numbers are naturally addressed
cd2867 ·* using predecrement, while little-endian is postincrement.
a0495d ·*/
ed2bef #ifndef bniZero_64
66314a void
0822c7 bniZero_64(BNWORD64 *num, unsigned len)
73bb36 {
04e87e ¤   while (len--)
aa84f4 ¤   ¤   BIGLITTLE(*--num,*num++) = 0;
96efe6 }
98a8eb #endif /* !bniZero_64 */
b7af5a
8838e5 /*
d05fe5 ·* Negate an array of words.
ab3551 ·* Negation is subtraction from zero. ·Negating low-order words
d9af4a ·* entails doing nothing until a non-zero word is hit. ·Once that
7fa81f ·* is negated, a borrow is generated and never dies until the end
02c1bd ·* of the number is hit. ·Negation with borrow, -x-1, is the same as ~x.
8624aa ·* Repeat that until the end of the number.
00775e ·*
afbb91 ·* Doesn't return borrow out because that's pretty useless - it's
57e078 ·* always set unless the input is 0, which is easy to notice in
3f0df0 ·* normalized form.
dc495d ·*/
7acbc7 #ifndef bniNeg_64
5f314a void
7f7e60 bniNeg_64(BNWORD64 *num, unsigned len)
8dbb36 {
0c86c8 ¤   pgpAssert(len);
07af5a
7c043a ¤   /* Skip low-order zero words */
98cadc ¤   while (BIGLITTLE(*--num,*num) == 0) {
3a253f ¤   ¤   if (!--len)
d50ecc ¤   ¤   ¤   return;
73c728 ¤   ¤   LITTLE(num++;)
719371 ¤   }
8f87c2 ¤   /* Negate the lowest-order non-zero word */
e6a8e3 ¤   *num = -*num;
e0e4e5 ¤   /* Complement all the higher-order words */
32e1ea ¤   while (--len) {
9e10b0 ¤   ¤   BIGLITTLE(--num,++num);
ac48d8 ¤   ¤   *num = ~*num;
d09371 ¤   }
38efe6 }
058f80 #endif /* !bniNeg_64 */
54af5a
75af5a
1c38e5 /*
d4f9a0 ·* bniAdd1_64: add the single-word "carry" to the given number.
b9976d ·* Used for minor increments and propagating the carry after
8d674c ·* adding in a shorter bignum.
34775e ·*
5bce8e ·* Technique: If we have a double-width word, presumably the compiler
93afd8 ·* can add using its carry in inline code, so we just use a larger
7ff5de ·* accumulator to compute the carry from the first addition.
3cf394 ·* If not, it's more complex. ·After adding the first carry, which may
4c696d ·* be > 1, compare the sum and the carry. ·If the sum wraps (causing a
3bc7d9 ·* carry out from the addition), the result will be less than each of the
42c3d9 ·* inputs, since the wrap subtracts a number (2^64) which is larger than
d69c68 ·* the other input can possibly be. ·If the sum is >= the carry input,
1e739c ·* return success immediately.
45a2cb ·* In either case, if there is a carry, enter a loop incrementing words
--8309 000c243bd3840100154 Page 4 of bni64.c
d66969 ·* until one does not wrap. ·Since we are adding 1 each time, the wrap
00b4b5 ·* will be to 0 and we can test for equality.
95495d ·*/
c96899 #ifndef bniAdd1_64¤ /* If defined, it's provided as an asm subroutine */
0d5d00 #ifdef BNWORD128
b18bb4 BNWORD64
dbd16e bniAdd1_64(BNWORD64 *num, unsigned len, BNWORD64 carry)
abbb36 {
f60faa ¤   BNWORD128 t;
859c94 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return carry */
08af5a
ca6bfb ¤   t = (BNWORD128)BIGLITTLE(*--num,*num) + carry;
33be55 ¤   BIGLITTLE(*num,*num++) = (BNWORD64)t;
2f018c ¤   if ((t >> 64) == 0)
79bbde ¤   ¤   return 0;
ace1ea ¤   while (--len) {
b62439 ¤   ¤   if (++BIGLITTLE(*--num,*num++) != 0)
038144 ¤   ¤   ¤   return 0;
169371 ¤   }
d064b7 ¤   return 1;
e5efe6 }
638aeb #else /* no BNWORD128 */
078bb4 BNWORD64
6fd16e bniAdd1_64(BNWORD64 *num, unsigned len, BNWORD64 carry)
77bb36 {
5a9c94 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return carry */
ccaf5a
0e9c40 ¤   if ((BIGLITTLE(*--num,*num++) += carry) >= carry)
aabbde ¤   ¤   return 0;
25e1ea ¤   while (--len) {
d12439 ¤   ¤   if (++BIGLITTLE(*--num,*num++) != 0)
ac8144 ¤   ¤   ¤   return 0;
ea9371 ¤   }
8f64b7 ¤   return 1;
30efe6 }
dd7454 #endif
240296 #endif/* !bniAdd1_64 */
e4af5a
d238e5 /*
2ef615 ·* bniSub1_64: subtract the single-word "borrow" from the given number.
be8db0 ·* Used for minor decrements and propagating the borrow after
31455f ·* subtracting a shorter bignum.
c3775e ·*
3636de ·* Technique: Similar to the add, above. ·If there is a double-length type,
29c57d ·* use that to generate the first borrow.
ab25ae ·* If not, after subtracting the first borrow, which may be > 1, compare
0d7f2c ·* the difference and the *negative* of the carry. ·If the subtract wraps
c48a8c ·* (causing a borrow out from the subtraction), the result will be at least
d19bc7 ·* as large as -borrow. ·If the result < -borrow, then no borrow out has
749e3c ·* appeared and we may return immediately, except when borrow == 0. ·To
94e027 ·* deal with that case, use the identity that -x = ~x+1, and instead of
0757ce ·* comparing < -borrow, compare for <= ~borrow.
6c464d ·* Either way, if there is a borrow out, enter a loop decrementing words
4afe08 ·* until a non-zero word is reached.
e1775e ·*
ccee83 ·* Note the cast of ~borrow to (BNWORD64). ·If the size of an int is larger
ea5f52 ·* than BNWORD64, C rules say the number is expanded for the arithmetic, so
1d47f5 ·* the inversion will be done on an int and the value won't be quite what
2dbf20 ·* is expected.
36495d ·*/
c6387d #ifndef bniSub1_64¤ /* If defined, it's provided as an asm subroutine */
1c5d00 #ifdef BNWORD128
b38bb4 BNWORD64
994540 bniSub1_64(BNWORD64 *num, unsigned len, BNWORD64 borrow)
edbb36 {
3c0faa ¤   BNWORD128 t;
972df5 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return borrow */
64af5a
868db5 ¤   t = (BNWORD128)BIGLITTLE(*--num,*num) - borrow;
30be55 ¤   BIGLITTLE(*num,*num++) = (BNWORD64)t;
68018c ¤   if ((t >> 64) == 0)
c2bbde ¤   ¤   return 0;
--1b5a 00094edefea40100154 Page 5 of bni64.c
f3e1ea ¤   while (--len) {
3adc4e ¤   ¤   if ((BIGLITTLE(*--num,*num++))-- != 0)
ed8144 ¤   ¤   ¤   return 0;
459371 ¤   }
9c64b7 ¤   return 1;
afefe6 }
148aeb #else /* no BNWORD128 */
898bb4 BNWORD64
244540 bniSub1_64(BNWORD64 *num, unsigned len, BNWORD64 borrow)
a2bb36 {
502df5 ¤   pgpAssert(len > 0);¤/* Alternative: if (!len) return borrow */
9faf5a
bed4e0 ¤   if ((BIGLITTLE(*--num,*num++) -= borrow) <= (BNWORD64)~borrow)
e0bbde ¤   ¤   return 0;
b3e1ea ¤   while (--len) {
a5dc4e ¤   ¤   if ((BIGLITTLE(*--num,*num++))-- != 0)
898144 ¤   ¤   ¤   return 0;
fc9371 ¤   }
ca64b7 ¤   return 1;
f0efe6 }
2e7454 #endif
f76292 #endif /* !bniSub1_64 */
61af5a
d938e5 /*
db2f41 ·* bniAddN_64: add two bignums of the same length,
44bdf0 ·* returning the carry (0 or 1).
9091db ·* One of the building blocks, along with bniAdd1, of adding two bignums of
e6a1e9 ·* differing lengths.
a1775e ·*
122251 ·* Technique: Maintain a word of carry. ·If there is no double-width type,
047ff1 ·* use the same technique as in bniAdd1, above, to maintain the carry by
4a3cda ·* comparing the inputs. ·Adding the carry sources is used as an OR operator;
847836 ·* at most one of the two comparisons can possibly be true. ·The first can
4cd0d2 ·* only be true if carry == 1 and x, the result, is 0. ·In that case the
e320dc ·* second can't possibly be true.
01495d ·*/
0f79b1 #ifndef bniAddN_64
475d00 #ifdef BNWORD128
698bb4 BNWORD64
bc7725 bniAddN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len)
07bb36 {
980faa ¤   BNWORD128 t;
b1af5a
b85334 ¤   pgpAssert(len > 0);
a5af5a
6c3496 ¤   t = (BNWORD128)BIGLITTLE(*--num1,*num1) + BIGLITTLE(*--num2,*num2++);
4206b1 ¤   BIGLITTLE(*num1,*num1++) = (BNWORD64)t;
dae1ea ¤   while (--len) {
53bb05 ¤   ¤   t = (BNWORD128)BIGLITTLE(*--num1,*num1) +
79c60e ¤   ¤   ····(BNWORD128)BIGLITTLE(*--num2,*num2++) + (t >> 64);
691ee1 ¤   ¤   BIGLITTLE(*num1,*num1++) = (BNWORD64)t;
fb9371 ¤   }
6eaf5a
5bd672 ¤   return (BNWORD64)(t>>64);
48efe6 }
2e8aeb #else /* no BNWORD128 */
9e8bb4 BNWORD64
357725 bniAddN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len)
debb36 {
11886e ¤   BNWORD64 x, carry = 0;
44af5a
f05327 ¤   pgpAssert(len > 0);¤/* Alternative: change loop to test at start */
c0af5a
0f43ab ¤   do {
224bce ¤   ¤   x = BIGLITTLE(*--num2,*num2++);
634163 ¤   ¤   carry = (x += carry) < carry;
935b74 ¤   ¤   carry += (BIGLITTLE(*--num1,*num1++) += x) < x;
cfc57e ¤   } while (--len);
2faf5a
46b1fc ¤   return carry;
b2efe6 }
947454 #endif
--0ac4 000952ae7de40100154 Page 6 of bni64.c
6edb54 #endif /* !bniAddN_64 */
15af5a
ea38e5 /*
a79482 ·* bniSubN_64: add two bignums of the same length,
68bdf0 ·* returning the carry (0 or 1).
796e07 ·* One of the building blocks, along with subn1, of subtracting two bignums of
39a1e9 ·* differing lengths.
10775e ·*
074d44 ·* Technique: If no double-width type is availble, maintain a word of borrow.
af7b0e ·* First, add the borrow to the subtrahend (did you have to learn all those
2633b3 ·* awful words in elementary school, too?), and if it overflows, set the
67182f ·* borrow again. ·Then subtract the modified subtrahend from the next word
fad9f4 ·* of input, using the same technique as in subn1, above.
89c4fa ·* Adding the borrows is used as an OR operator; at most one of the two
d4e246 ·* comparisons can possibly be true. ·The first can only be true if
40f032 ·* borrow == 1 and x, the result, is 0. ·In that case the second can't
1e119d ·* possibly be true.
f5775e ·*
2a4ad2 ·* In the double-word case, (BNWORD64)-(t>>64) is subtracted, rather than
5ad80e ·* adding t>>64, because the shift would need to sign-extend and that's
7217f3 ·* not guaranteed to happen in ANSI C, even with signed types.
50495d ·*/
6d1b40 #ifndef bniSubN_64
305d00 #ifdef BNWORD128
8e8bb4 BNWORD64
d59277 bniSubN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len)
35bb36 {
af0faa ¤   BNWORD128 t;
cbaf5a
9c5334 ¤   pgpAssert(len > 0);
38af5a
08f6bc ¤   t = (BNWORD128)BIGLITTLE(*--num1,*num1) - BIGLITTLE(*--num2,*num2++);
bc06b1 ¤   BIGLITTLE(*num1,*num1++) = (BNWORD64)t;
52af5a
7ae1ea ¤   while (--len) {
6cefd5 ¤   ¤   t = (BNWORD128)BIGLITTLE(*--num1,*num1) -
0c0eee ¤   ¤   ····(BNWORD128)BIGLITTLE(*--num2,*num2++) -
eeab68 ¤   ¤   ····(BNWORD64)-(t >> 64);
de1ee1 ¤   ¤   BIGLITTLE(*num1,*num1++) = (BNWORD64)t;
2f9371 ¤   }
5daf5a
f66296 ¤   return -(BNWORD64)(t>>64);
43efe6 }
f2db21 #else
a58bb4 BNWORD64
c19277 bniSubN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len)
74bb36 {
cae01a ¤   BNWORD64 x, borrow = 0;
89af5a
295327 ¤   pgpAssert(len > 0);¤/* Alternative: change loop to test at start */
8eaf5a
3743ab ¤   do {
f84bce ¤   ¤   x = BIGLITTLE(*--num2,*num2++);
b44b08 ¤   ¤   borrow = (x += borrow) < borrow;
d8ea43 ¤   ¤   borrow += (BIGLITTLE(*--num1,*num1++) -= x) > (BNWORD64)~x;
08c57e ¤   } while (--len);
12af5a
771102 ¤   return borrow;
33efe6 }
a57454 #endif
1e5b59 #endif /* !bniSubN_64 */
95af5a
69404c #ifndef bniCmp_64
2a38e5 /*
0b7042 ·* bniCmp_64: compare two bignums of equal length, returning the sign of
638209 ·* num1 - num2. (-1, 0 or +1).
699ec0 ·*·
51e837 ·* Technique: Change the little-endian pointers to big-endian pointers
517660 ·* and compare from the most-significant end until a difference if found.
92bd66 ·* When it is, figure out the sign of the difference and return it.
78495d ·*/
954d2f int
--c7b1 000ebdf35be40100154 Page 7 of bni64.c
d0e854 bniCmp_64(BNWORD64 const *num1, BNWORD64 const *num2, unsigned len)
f5bb36 {
fbcce6 ¤   BIGLITTLE(num1 -= len, num1 += len);
36df99 ¤   BIGLITTLE(num2 -= len, num2 += len);
7aaf5a
9bcae5 ¤   while (len--) {
20c2de ¤   ¤   if (BIGLITTLE(*num1++ != *num2++, *--num1 != *--num2)) {
61dcf7 ¤   ¤   ¤   if (BIGLITTLE(num1[-1] < num2[-1], *num1 < *num2))
11dd34 ¤   ¤   ¤   ¤   return -1;
cabb8c ¤   ¤   ¤   else
301c2d ¤   ¤   ¤   ¤   return 1;
a70fe4 ¤   ¤   }
ae9371 ¤   }
4f3e6b ¤   return 0;
ccefe6 }
b9c2ae #endif /* !bniCmp_64 */
63af5a
8738e5 /*
a1ed35 ·* mul64_ppmmaa(ph,pl,x,y,a,b) is an optional routine that
d72fba ·* computes (ph,pl) = x * y + a + b. ·mul64_ppmma and mul64_ppmm
f18dbd ·* are simpler versions. ·If you want to be lazy, all of these
9f1154 ·* can be defined in terms of the others, so here we create any
e9a26b ·* that have not been defined in terms of the ones that have been.
38495d ·*/
fcaf5a
95faaa /* Define ones with fewer a's in terms of ones with more a's */
36bfe1 #if !defined(mul64_ppmma) && defined(mul64_ppmmaa)
8c9796 #define mul64_ppmma(ph,pl,x,y,a) mul64_ppmmaa(ph,pl,x,y,a,0)
617454 #endif
29af5a
e601b7 #if !defined(mul64_ppmm) && defined(mul64_ppmma)
2e8f8b #define mul64_ppmm(ph,pl,x,y) mul64_ppmma(ph,pl,x,y,0)
c07454 #endif
a1af5a
da38e5 /*
79ba0e ·* Use this definition to test the mul64_ppmm-based operations on machines
19005f ·* that do not provide mul64_ppmm. ·Change the final "0" to a "1" to
75925b ·* enable it.
ac495d ·*/
5bc336 #if !defined(mul64_ppmm) && defined(BNWORD128) && 0¤/* Debugging */
4891d9 #define mul64_ppmm(ph,pl,x,y) \
9fcd5a ¤   ({BNWORD128 _ = (BNWORD128)(x)*(y); (pl) = _; (ph) = _>>64;})
517454 #endif
a8af5a
4ce820 #if defined(mul64_ppmm) && !defined(mul64_ppmma)
1a7a0a #define mul64_ppmma(ph,pl,x,y,a) \
39e319 ¤   (mul64_ppmm(ph,pl,x,y), (ph) += ((pl) += (a)) < (a))
827454 #endif
7caf5a
d59fd0 #if defined(mul64_ppmma) && !defined(mul64_ppmmaa)
f9541c #define mul64_ppmmaa(ph,pl,x,y,a,b) \
801cf9 ¤   (mul64_ppmma(ph,pl,x,y,a), (ph) += ((pl) += (b)) < (b))
447454 #endif
c4af5a
8738e5 /*
a75b6a ·* bniMulN1_64: Multiply an n-word input by a 1-word input and store the
928338 ·* n+1-word product. ·This uses either the mul64_ppmm and mul64_ppmma
c201b0 ·* macros, or C multiplication with the BNWORD128 type. ·This uses mul64_ppmma
2974b1 ·* if available, assuming you won't bother defining it unless you can do
6901e4 ·* better than the normal multiplication.
81495d ·*/
6076a3 #ifndef bniMulN1_64
c4c98b #ifdef bniMulAdd1_64¤   /* If we have this asm primitive, use it. */
92314a void
1591fa bniMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
adbb36 {
59cb28 ¤   bniZero_64(out, len);
7d2ae8 ¤   BIGLITTLE(*(out-len),*(out+len)) = bniMulAdd1_64(out, in, len, k);
7aefe6 }
9fe6cf #elif defined(mul64_ppmm)
5f314a void
eb91fa bniMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
--cd98 000c5c3de9a40100154 Page 8 of bni64.c
2cbb36 {
24549c ¤   BNWORD64 prod, carry, carryin;
0aaf5a
665334 ¤   pgpAssert(len > 0);
aaaf5a
98947d ¤   BIG(--out;--in;);
2267a4 ¤   mul64_ppmm(carry, *out, *in, k);
66f1a6 ¤   LITTLE(out++;in++;)
99af5a
47e1ea ¤   while (--len) {
c66541 ¤   ¤   BIG(--out;--in;)
c6a85c ¤   ¤   carryin = carry;
1f9a96 ¤   ¤   mul64_ppmma(carry, *out, *in, k, carryin);
1707c3 ¤   ¤   LITTLE(out++;in++;)
139371 ¤   }
87ddd0 ¤   BIGLITTLE(*--out,*out) = carry;
9cefe6 }
9d2f3b #elif defined(BNWORD128)
68314a void
8e91fa bniMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
92bb36 {
106ccb ¤   BNWORD128 p;
c9af5a
355334 ¤   pgpAssert(len > 0);
e5af5a
4ec466 ¤   p = (BNWORD128)BIGLITTLE(*--in,*in++) * k;
2a48a4 ¤   BIGLITTLE(*--out,*out++) = (BNWORD64)p;
39af5a
1ae1ea ¤   while (--len) {
327972 ¤   ¤   p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + (BNWORD64)(p >> 64);
9e50f4 ¤   ¤   BIGLITTLE(*--out,*out++) = (BNWORD64)p;
eb9371 ¤   }
bf41e0 ¤   BIGLITTLE(*--out,*out) = (BNWORD64)(p >> 64);
f5efe6 }
c6db21 #else
cc6a5c #error No 64x64 -> 128 multiply available for 64-bit bignum package
557454 #endif
e13cb6 #endif /* bniMulN1_64 */
1eaf5a
6438e5 /*
2a2757 ·* bniMulAdd1_64: Multiply an n-word input by a 1-word input and add the
1972e0 ·* low n words of the product to the destination. ·*Returns the n+1st word
fd0f32 ·* of the product.* ·(That turns out to be more convenient than adding
7a5a71 ·* it into the destination and dealing with a possible unit carry out
9eb65d ·* of *that*.) ·This uses either the mul64_ppmma and mul64_ppmmaa macros,
2745dc ·* or C multiplication with the BNWORD128 type.
07775e ·*
5d8e70 ·* If you're going to write assembly primitives, this is the one to
0c0dda ·* start with. ·It is by far the most commonly called function.
b5495d ·*/
9a7eb5 #ifndef bniMulAdd1_64
307438 #if defined(mul64_ppmm)
2d8bb4 BNWORD64
ad99a8 bniMulAdd1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
f1bb36 {
cb549c ¤   BNWORD64 prod, carry, carryin;
35af5a
7e5334 ¤   pgpAssert(len > 0);
07af5a
2a947d ¤   BIG(--out;--in;);
96d6bd ¤   carryin = *out;
be4224 ¤   mul64_ppmma(carry, *out, *in, k, carryin);
b9f1a6 ¤   LITTLE(out++;in++;)
aeaf5a
e9e1ea ¤   while (--len) {
7053c8 ¤   ¤   BIG(--out;--in;);
84a85c ¤   ¤   carryin = carry;
78229e ¤   ¤   mul64_ppmmaa(carry, prod, *in, k, carryin, *out);
cbecd6 ¤   ¤   *out = prod;
a407c3 ¤   ¤   LITTLE(out++;in++;)
799371 ¤   }
c5af5a
--940f 000b3d2389f40100154 Page 9 of bni64.c
dab1fc ¤   return carry;
72efe6 }
092f3b #elif defined(BNWORD128)
ff8bb4 BNWORD64
4599a8 bniMulAdd1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
4ebb36 {
866ccb ¤   BNWORD128 p;
2aaf5a
3e5334 ¤   pgpAssert(len > 0);
28af5a
7d71dd ¤   p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + BIGLITTLE(*--out,*out);
cdce0f ¤   BIGLITTLE(*out,*out++) = (BNWORD64)p;
87af5a
83e1ea ¤   while (--len) {
64a937 ¤   ¤   p = (BNWORD128)BIGLITTLE(*--in,*in++) * k +
b0f7f2 ¤   ¤   ····(BNWORD64)(p >> 64) + BIGLITTLE(*--out,*out);
16f7ca ¤   ¤   BIGLITTLE(*out,*out++) = (BNWORD64)p;
0f9371 ¤   }
2aaf5a
3815a8 ¤   return (BNWORD64)(p >> 64);
aeefe6 }
24db21 #else
2e6a5c #error No 64x64 -> 128 multiply available for 64-bit bignum package
ec7454 #endif
a94837 #endif /* bniMulAdd1_64 */
56af5a
3c38e5 /*
2004f4 ·* bniMulSub1_64: Multiply an n-word input by a 1-word input and subtract the
99843f ·* n-word product from the destination. ·Returns the n+1st word of the product.
16f419 ·* This uses either the mul64_ppmm and mul64_ppmma macros, or
bf2f6f ·* C multiplication with the BNWORD128 type.
9e775e ·*
28ceaf ·* This is rather uglier than adding, but fortunately it's only used in
7b7917 ·* division which is not used too heavily.
03495d ·*/
d81c44 #ifndef bniMulSub1_64
a87438 #if defined(mul64_ppmm)
aa8bb4 BNWORD64
c19427 bniMulSub1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
d4bb36 {
3c549c ¤   BNWORD64 prod, carry, carryin;
fbaf5a
745334 ¤   pgpAssert(len > 0);
f8af5a
61495e ¤   BIG(--in;)
6c4209 ¤   mul64_ppmm(carry, prod, *in, k);
f7745b ¤   LITTLE(in++;)
20e410 ¤   carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD64)~prod;
5caf5a
3ee1ea ¤   while (--len) {
e52ce1 ¤   ¤   BIG(--in;);
b8a85c ¤   ¤   carryin = carry;
84853b ¤   ¤   mul64_ppmma(carry, prod, *in, k, carryin);
934ec1 ¤   ¤   LITTLE(in++;)
06f79c ¤   ¤   carry += (BIGLITTLE(*--out,*out++) -= prod) > (BNWORD64)~prod;
5c9371 ¤   }
ddaf5a
e3b1fc ¤   return carry;
6cefe6 }
3d2f3b #elif defined(BNWORD128)
608bb4 BNWORD64
bd9427 bniMulSub1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k)
13bb36 {
d26ccb ¤   BNWORD128 p;
39d9f4 ¤   BNWORD64 carry, t;
3faf5a
7c5334 ¤   pgpAssert(len > 0);
68af5a
d8c466 ¤   p = (BNWORD128)BIGLITTLE(*--in,*in++) * k;
8d8593 ¤   t = BIGLITTLE(*--out,*out);
8bb46f ¤   carry = (BNWORD64)(p>>64) +
b36f3f ¤   ¤   ¤   ((BIGLITTLE(*out,*out++)=t-(BNWORD64)p) > t);
--c43e 000120ded9c40100154 Page 10 of bni64.c
e0af5a
32e1ea ¤   while (--len) {
532a6f ¤   ¤   p = (BNWORD128)BIGLITTLE(*--in,*in++) * k + carry;
e00e6f ¤   ¤   t = BIGLITTLE(*--out,*out);
193f93 ¤   ¤   carry = (BNWORD64)(p>>64) +
8c2bb2 ¤   ¤   ¤   ( (BIGLITTLE(*out,*out++)=t-(BNWORD64)p) > t );
f89371 ¤   }
90af5a
88b1fc ¤   return carry;
f7efe6 }
09db21 #else
356a5c #error No 64x64 -> 128 multiply available for 64-bit bignum package
037454 #endif
465c9d #endif /* !bniMulSub1_64 */
faaf5a
0338e5 /*
b6270a ·* Shift n words left "shift" bits. ·0 < shift < 64. ·Returns the
7a2e41 ·* carry, any bits shifted off the left-hand side (0 <= carry < 2^shift).
4e495d ·*/
808080 #ifndef bniLshift_64
da8bb4 BNWORD64
2234cc bniLshift_64(BNWORD64 *num, unsigned len, unsigned shift)
f6bb36 {
208680 ¤   BNWORD64 x, carry;
22af5a
fae769 ¤   pgpAssert(shift > 0);
9f8a20 ¤   pgpAssert(shift < 64);
70af5a
411e50 ¤   carry = 0;
12cae5 ¤   while (len--) {
b1cb1c ¤   ¤   BIG(--num;)
18f3b8 ¤   ¤   x = *num;
4e2c6b ¤   ¤   *num = (x<<shift) | carry;
d7c728 ¤   ¤   LITTLE(num++;)
4e15ea ¤   ¤   carry = x >> (64-shift);
f29371 ¤   }
c5b1fc ¤   return carry;
a6efe6 }
494895 #endif /* !bniLshift_64 */
f1af5a
aa38e5 /*
919f06 ·* An optimized version of the above, for shifts of 1.
72db8f ·* Some machines can use add-with-carry tricks for this.
5c495d ·*/
4f573f #ifndef bniDouble_64
908bb4 BNWORD64
7bb7b5 bniDouble_64(BNWORD64 *num, unsigned len)
8bbb36 {
c68680 ¤   BNWORD64 x, carry;
37af5a
b81e50 ¤   carry = 0;
44cae5 ¤   while (len--) {
7bcb1c ¤   ¤   BIG(--num;)
c8f3b8 ¤   ¤   x = *num;
d977ad ¤   ¤   *num = (x<<1) | carry;
fcc728 ¤   ¤   LITTLE(num++;)
9b6c07 ¤   ¤   carry = x >> (64-1);
d99371 ¤   }
93b1fc ¤   return carry;
f2efe6 }
cb9a23 #endif /* !bniDouble_64 */
f8af5a
7f38e5 /*
461442 ·* Shift n words right "shift" bits. ·0 < shift < 64. ·Returns the
01f892 ·* carry, any bits shifted off the right-hand side (0 <= carry < 2^shift).
78495d ·*/
11d329 #ifndef bniRshift_64
b38bb4 BNWORD64
175fc2 bniRshift_64(BNWORD64 *num, unsigned len, unsigned shift)
fbbb36 {
ba886e ¤   BNWORD64 x, carry = 0;
12af5a
--27cc 000f74ec7f940100154 Page 11 of bni64.c
54e769 ¤   pgpAssert(shift > 0);
f88a20 ¤   pgpAssert(shift < 64);
3baf5a
0b1189 ¤   BIGLITTLE(num -= len, num += len);
8baf5a
1dcae5 ¤   while (len--) {
2ac1a0 ¤   ¤   LITTLE(--num;)
17f3b8 ¤   ¤   x = *num;
f7f5aa ¤   ¤   *num = (x>>shift) | carry;
b6cd94 ¤   ¤   BIG(num++;)
b3786a ¤   ¤   carry = x << (64-shift);
ca9371 ¤   }
5974d2 ¤   return carry >> (64-shift);
48efe6 }
7f22c3 #endif /* !bniRshift_64 */
06af5a
0f95d7 /*·
205d82 ·* Multiply two numbers of the given lengths. ·prod and num2 may overlap,
c02dfd ·* provided that the low len1 bits of prod are free. ·(This corresponds
81f452 ·* nicely to the place the result is returned from bniMontReduce_64.)
ff775e ·*
6be9b9 ·* TODO: Use Karatsuba multiply. ·The overlap constraints may have
ab0cb9 ·* to get rewhacked.
73495d ·*/
4066f5 #ifndef bniMul_64
d3314a void
e7a5ec bniMul_64(BNWORD64 *prod, BNWORD64 const *num1, unsigned len1,
ba8f18 ··························BNWORD64 const *num2, unsigned len2)
25bb36 {
8d157a ¤   /* Special case of zero */
01fee4 ¤   if (!len1 || !len2) {
ca1653 ¤   ¤   bniZero_64(prod, len1+len2);
0499bf ¤   ¤   return;
959371 ¤   }
90af5a
1f5dc0 ¤   /* Multiply first word */
b97698 ¤   bniMulN1_64(prod, num1, len1, BIGLITTLE(*--num2,*num2++));
6aaf5a
36d8af ¤   /*
4fad33 ¤   ·* Add in subsequent words, storing the most significant word,
e22a88 ¤   ·* which is new each time.
76a4e3 ¤   ·*/
5eae79 ¤   while (--len2) {
60df7f ¤   ¤   BIGLITTLE(--prod,prod++);
a6ef4a ¤   ¤   BIGLITTLE(*(prod-len1-1),*(prod+len1)) =
73440a ¤   ¤   ¤   bniMulAdd1_64(prod, num1, len1,
9064a3 ¤   ¤   ¤   ¤   BIGLITTLE(*--num2,*num2++));
e49371 ¤   }
4eefe6 }
3ba311 #endif /* !bniMul_64 */
f2af5a
df38e5 /*
fc9818 ·* bniMulX_64 is a square multiply - both inputs are the same length.
4d73d5 ·* It's normally just a macro wrapper around the general multiply,
d49a0a ·* but might be implementable in assembly more efficiently (such as
7bee4d ·* when product scanning).
da495d ·*/
b5c64f #ifndef bniMulX_64
e1957c #if defined(BNWORD128) && PRODUCT_SCAN
3f38e5 /*
183384 ·* Test code to see whether product scanning is any faster. ·It seems
239f49 ·* to make the C code slower, so PRODUCT_SCAN is not defined.
2c495d ·*/
722978 static void
b3637d bniMulX_64(BNWORD64 *prod, BNWORD64 const *num1, BNWORD64 const *num2,
076094 ¤   unsigned len)
50bb36 {
c4f866 ¤   BNWORD128 x, y;
c91e16 ¤   BNWORD64 const *p1, *p2;
c950fc ¤   unsigned carry;
2c07cb ¤   unsigned i, j;
f7af5a
--ce53 000b6152a3e40100154 Page 12 of bni64.c
6d157a ¤   /* Special case of zero */
1a4404 ¤   if (!len)
0499bf ¤   ¤   return;
1baf5a
a219f3 ¤   x = (BNWORD128)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
0ab8e3 ¤   BIGLITTLE(*--prod, *prod++) = (BNWORD64)x;
3d1d49 ¤   x >>= 64;
e7af5a
2b6dce ¤   for (i = 1; i < len; i++) {
3dfcf3 ¤   ¤   carry = 0;
3bf201 ¤   ¤   p1 = num1;
98515c ¤   ¤   p2 = BIGLITTLE(num2-i-1,num2+i+1);
78cdd8 ¤   ¤   for (j = 0; j <= i; j++) {
e0f037 ¤   ¤   ¤   BIG(y = (BNWORD128)*--p1 * *p2++;)
521dcc ¤   ¤   ¤   LITTLE(y = (BNWORD128)*p1++ * *--p2;)
8d1ca0 ¤   ¤   ¤   x += y;
44dfb0 ¤   ¤   ¤   carry += (x < y);
300fe4 ¤   ¤   }
82e17b ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD64)x;
68263a ¤   ¤   x = (x >> 64) | (BNWORD128)carry << 64;
4f9371 ¤   }
556dce ¤   for (i = 1; i < len; i++) {
bbfcf3 ¤   ¤   carry = 0;
e07f2d ¤   ¤   p1 = BIGLITTLE(num1-i,num1+i);
42429b ¤   ¤   p2 = BIGLITTLE(num2-len,num2+len);
ca7807 ¤   ¤   for (j = i; j < len; j++) {
c5f037 ¤   ¤   ¤   BIG(y = (BNWORD128)*--p1 * *p2++;)
c31dcc ¤   ¤   ¤   LITTLE(y = (BNWORD128)*p1++ * *--p2;)
3d1ca0 ¤   ¤   ¤   x += y;
5adfb0 ¤   ¤   ¤   carry += (x < y);
2a0fe4 ¤   ¤   }
73e17b ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD64)x;
ae263a ¤   ¤   x = (x >> 64) | (BNWORD128)carry << 64;
8b9371 ¤   }
7967c5 ¤
ba6180 ¤   BIGLITTLE(*--prod,*prod) = (BNWORD64)x;
33efe6 }
f67171 #else /* !defined(BNWORD128) || !PRODUCT_SCAN */
837015 /* Default trivial macro definition */
745b4e #define bniMulX_64(prod, num1, num2, len) bniMul_64(prod, num1, len, num2, len)
f0aa91 #endif /* !defined(BNWORD128) || !PRODUCT_SCAN */
cc2179 #endif /* !lbmMulX_64 */
59af5a
006f9a #if !defined(bniMontMul_64) && defined(BNWORD128) && PRODUCT_SCAN
a738e5 /*
d5b707 ·* Test code for product-scanning multiply. ·This seems to slow the C
f9f14b ·* code down rather than speed it up.
1ce2e9 ·* This does a multiply and Montgomery reduction together, using the
0e053f ·* same loops. ·The outer loop scans across the product, twice.
fd093d ·* The first pass computes the low half of the product and the
e18f6c ·* Montgomery multipliers. ·These are stored in the product array,
f29620 ·* which contains no data as of yet. ·x and carry add up the columns
be17c7 ·* and propagate carries forward.
05775e ·*
19bdb8 ·* The second half multiplies the upper half, adding in the modulus
9c2380 ·* times the Montgomery multipliers. ·The results of this multiply
b7fa30 ·* are stored.
25495d ·*/
ef2978 static void
90b032 bniMontMul_64(BNWORD64 *prod, BNWORD64 const *num1, BNWORD64 const *num2,
55c680 ¤   BNWORD64 const *mod, unsigned len, BNWORD64 inv)
ddbb36 {
7df866 ¤   BNWORD128 x, y;
ab4d9a ¤   BNWORD64 const *p1, *p2, *pm;
0bbcc0 ¤   BNWORD64 *pp;
dad6e3 ¤   BNWORD64 t;
6550fc ¤   unsigned carry;
8507cb ¤   unsigned i, j;
b0af5a
f8157a ¤   /* Special case of zero */
034404 ¤   if (!len)
b699bf ¤   ¤   return;
--e5be 000bf068ffa40100154 Page 13 of bni64.c
e0af5a
f8d8af ¤   /*
c44576 ¤   ·* This computes directly into the high half of prod, so just
159d34 ¤   ·* shift the pointer and consider prod only "len" elements long
2aebc4 ¤   ·* for the rest of the code.
6ea4e3 ¤   ·*/
1c8517 ¤   BIGLITTLE(prod -= len, prod += len);
efaf5a
84a702 ¤   /* Pass 1 - compute Montgomery multipliers */
4d1ffe ¤   /* First iteration can have certain simplifications. */
5619f3 ¤   x = (BNWORD128)BIGLITTLE(num1[-1] * num2[-1], num1[0] * num2[0]);
90f775 ¤   BIGLITTLE(prod[-1], prod[0]) = t = inv * (BNWORD64)x;
c8575a ¤   y = (BNWORD128)t * BIGLITTLE(mod[-1],mod[0]);
aa9163 ¤   x += y;
a412f8 ¤   /* Note: GCC 2.6.3 has a bug if you try to eliminate "carry" */
1b27d4 ¤   carry = (x < y);
d8b787 ¤   pgpAssert((BNWORD64)x == 0);
79b562 ¤   x = x >> 64 | (BNWORD128)carry << 64;
74af5a
e56dce ¤   for (i = 1; i < len; i++) {
7cfcf3 ¤   ¤   carry = 0;
58f201 ¤   ¤   p1 = num1;
6a515c ¤   ¤   p2 = BIGLITTLE(num2-i-1,num2+i+1);
ce47bb ¤   ¤   pp = prod;
a3d39c ¤   ¤   pm = BIGLITTLE(mod-i-1,mod+i+1);
25f8a4 ¤   ¤   for (j = 0; j < i; j++) {
b4b814 ¤   ¤   ¤   y = (BNWORD128)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
991ca0 ¤   ¤   ¤   x += y;
59dfb0 ¤   ¤   ¤   carry += (x < y);
996939 ¤   ¤   ¤   y = (BNWORD128)BIGLITTLE(*--pp * *pm++, *pp++ * *--pm);
2b1ca0 ¤   ¤   ¤   x += y;
1bdfb0 ¤   ¤   ¤   carry += (x < y);
5d0fe4 ¤   ¤   }
d2365c ¤   ¤   y = (BNWORD128)BIGLITTLE(p1[-1] * p2[0], p1[0] * p2[-1]);
5f8bd3 ¤   ¤   x += y;
5c56e4 ¤   ¤   carry += (x < y);
a51cca ¤   ¤   pgpAssert(BIGLITTLE(pp == prod-i, pp == prod+i));
6e7362 ¤   ¤   BIGLITTLE(pp[-1], pp[0]) = t = inv * (BNWORD64)x;
6835b5 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-1, pm == mod+1));
299346 ¤   ¤   y = (BNWORD128)t * BIGLITTLE(pm[0],pm[-1]);
a98bd3 ¤   ¤   x += y;
e356e4 ¤   ¤   carry += (x < y);
8f8aef ¤   ¤   pgpAssert((BNWORD64)x == 0);
5e8ca7 ¤   ¤   x = x >> 64 | (BNWORD128)carry << 64;
df9371 ¤   }
eaaf5a
fcd239 ¤   /* Pass 2 - compute reduced product and store */
316dce ¤   for (i = 1; i < len; i++) {
45fcf3 ¤   ¤   carry = 0;
637f2d ¤   ¤   p1 = BIGLITTLE(num1-i,num1+i);
ab429b ¤   ¤   p2 = BIGLITTLE(num2-len,num2+len);
7a0805 ¤   ¤   pm = BIGLITTLE(mod-i,mod+i);
5ca573 ¤   ¤   pp = BIGLITTLE(prod-len,prod+len);
647807 ¤   ¤   for (j = i; j < len; j++) {
f3b814 ¤   ¤   ¤   y = (BNWORD128)BIGLITTLE(*--p1 * *p2++, *p1++ * *--p2);
b91ca0 ¤   ¤   ¤   x += y;
89dfb0 ¤   ¤   ¤   carry += (x < y);
da3f60 ¤   ¤   ¤   y = (BNWORD128)BIGLITTLE(*--pm * *pp++, *pm++ * *--pp);
081ca0 ¤   ¤   ¤   x += y;
08dfb0 ¤   ¤   ¤   carry += (x < y);
7a0fe4 ¤   ¤   }
2170a3 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-len, pm == mod+len));
f11cca ¤   ¤   pgpAssert(BIGLITTLE(pp == prod-i, pp == prod+i));
a418ea ¤   ¤   BIGLITTLE(pp[0],pp[-1]) = (BNWORD64)x;
a3263a ¤   ¤   x = (x >> 64) | (BNWORD128)carry << 64;
bc9371 ¤   }
0baf5a
36f753 ¤   /* Last round of second half, simplified. */
ddf691 ¤   BIGLITTLE(*(prod-len),*(prod+len-1)) = (BNWORD64)x;
da4d39 ¤   carry = (x >> 64);
c9af5a
bfa53b ¤   while (carry)
--da0d 000fadab3bc40100154 Page 14 of bni64.c
3260d0 ¤   ¤   carry -= bniSubN_64(prod, mod, len);
f947a7 ¤   while (bniCmp_64(prod, mod, len) >= 0)
5ac8ff ¤   ¤   (void)bniSubN_64(prod, mod, len);
53efe6 }
4125f5 /* Suppress later definition */
ce5b53 #define bniMontMul_64 bniMontMul_64
e87454 #endif
b9af5a
df3a17 #if !defined(bniSquare_64) && defined(BNWORD128) && PRODUCT_SCAN
5838e5 /*
af064e ·* Trial code for product-scanning squaring. ·This seems to slow the C
f9f14b ·* code down rather than speed it up.
88495d ·*/
ad314a void
88563c bniSquare_64(BNWORD64 *prod, BNWORD64 const *num, unsigned len)
acbb36 {
e1b8cf ¤   BNWORD128 x, y, z;
921e16 ¤   BNWORD64 const *p1, *p2;
ba50fc ¤   unsigned carry;
ee07cb ¤   unsigned i, j;
94af5a
6a157a ¤   /* Special case of zero */
894404 ¤   if (!len)
c299bf ¤   ¤   return;
75af5a
9761d6 ¤   /* Word 0 of product */
214708 ¤   x = (BNWORD128)BIGLITTLE(num[-1] * num[-1], num[0] * num[0]);
0fb8e3 ¤   BIGLITTLE(*--prod, *prod++) = (BNWORD64)x;
081d49 ¤   x >>= 64;
7daf5a
6cbe1a ¤   /* Words 1 through len-1 */
246dce ¤   for (i = 1; i < len; i++) {
defcf3 ¤   ¤   carry = 0;
b52b1f ¤   ¤   y = 0;
737bd5 ¤   ¤   p1 = num;
eaf73f ¤   ¤   p2 = BIGLITTLE(num-i-1,num+i+1);
882b7b ¤   ¤   for (j = 0; j < (i+1)/2; j++) {
dbb77a ¤   ¤   ¤   BIG(z = (BNWORD128)*--p1 * *p2++;)
d05a81 ¤   ¤   ¤   LITTLE(z = (BNWORD128)*p1++ * *--p2;)
5d727b ¤   ¤   ¤   y += z;
b77bc2 ¤   ¤   ¤   carry += (y < z);
cc0fe4 ¤   ¤   }
bd3099 ¤   ¤   y += z = y;
b82289 ¤   ¤   carry += carry + (y < z);
a5d10c ¤   ¤   if ((i & 1) == 0) {
55d553 ¤   ¤   ¤   pgpAssert(BIGLITTLE(p1-1 == p2, p1 == p2-1));
64cf29 ¤   ¤   ¤   BIG(z = (BNWORD128)*p2 * *p2;)
6534fe ¤   ¤   ¤   LITTLE(z = (BNWORD128)*p1 * *p1;)
d0727b ¤   ¤   ¤   y += z;
787bc2 ¤   ¤   ¤   carry += (y < z);
680fe4 ¤   ¤   }
828bd3 ¤   ¤   x += y;
2256e4 ¤   ¤   carry += (x < y);
0ce17b ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD64)x;
65263a ¤   ¤   x = (x >> 64) | (BNWORD128)carry << 64;
a09371 ¤   }
7f852e ¤   /* Words len through 2*len-2 */
fe6dce ¤   for (i = 1; i < len; i++) {
c2fcf3 ¤   ¤   carry = 0;
0c2b1f ¤   ¤   y = 0;
6c7e3e ¤   ¤   p1 = BIGLITTLE(num-i,num+i);
ad2d6b ¤   ¤   p2 = BIGLITTLE(num-len,num+len);
52ca30 ¤   ¤   for (j = 0; j < (len-i)/2; j++) {
9eb77a ¤   ¤   ¤   BIG(z = (BNWORD128)*--p1 * *p2++;)
d15a81 ¤   ¤   ¤   LITTLE(z = (BNWORD128)*p1++ * *--p2;)
6c727b ¤   ¤   ¤   y += z;
c37bc2 ¤   ¤   ¤   carry += (y < z);
ea0fe4 ¤   ¤   }
443099 ¤   ¤   y += z = y;
312289 ¤   ¤   carry += carry + (y < z);
0cbcf9 ¤   ¤   if ((len-i) & 1) {
fad553 ¤   ¤   ¤   pgpAssert(BIGLITTLE(p1-1 == p2, p1 == p2-1));
--f7ab 000436867a640100154 Page 15 of bni64.c
12cf29 ¤   ¤   ¤   BIG(z = (BNWORD128)*p2 * *p2;)
2434fe ¤   ¤   ¤   LITTLE(z = (BNWORD128)*p1 * *p1;)
e5727b ¤   ¤   ¤   y += z;
927bc2 ¤   ¤   ¤   carry += (y < z);
310fe4 ¤   ¤   }
7d8bd3 ¤   ¤   x += y;
c056e4 ¤   ¤   carry += (x < y);
5be17b ¤   ¤   BIGLITTLE(*--prod,*prod++) = (BNWORD64)x;
12263a ¤   ¤   x = (x >> 64) | (BNWORD128)carry << 64;
d19371 ¤   }
6a67c5 ¤
6ab240 ¤   /* Word 2*len-1 */
1b6180 ¤   BIGLITTLE(*--prod,*prod) = (BNWORD64)x;
1befe6 }
5725f5 /* Suppress later definition */
ed878f #define bniSquare_64 bniSquare_64
787454 #endif
42af5a
0738e5 /*
a7a533 ·* Square a number, using optimized squaring to reduce the number of
9f1f0f ·* primitive multiples that are executed. ·There may not be any
d66dd9 ·* overlap of the input and output.
12775e ·*
d102ad ·* Technique: Consider the partial products in the multiplication
3972e6 ·* of "abcde" by itself:
45775e ·*
20de15 ·* ··············a ·b ·c ·d ·e
797669 ·* ···········* ·a ·b ·c ·d ·e
bc1afb ·* ·········==================
98d8e6 ·* ·············ae be ce de ee
9abd78 ·* ··········ad bd cd dd de
3ce467 ·* ·······ac bc cc cd ce
f5dcf1 ·* ····ab bb bc bd be
1e7dd1 ·* ·aa ab ac ad ae
97775e ·*
234e38 ·* Note that everything above the main diagonal:
2e729a ·* ·············ae be ce de = (abcd) * e
1006bf ·* ··········ad bd cd ······= (abc) * d
90eff2 ·* ·······ac bc ············= (ab) * c
0b8267 ·* ····ab ··················= (a) * b
fb775e ·*
f1cef0 ·* is a copy of everything below the main diagonal:
7e6424 ·* ······················de
fc63ff ·* ················cd ce
4b85ae ·* ··········bc bd be
fe5a25 ·* ····ab ac ad ae
6e775e ·*
f29c36 ·* Thus, the sum is 2 * (off the diagonal) + diagonal.
1d775e ·*
071615 ·* This is accumulated beginning with the diagonal (which
08d5d8 ·* consist of the squares of the digits of the input), which is then
189c50 ·* divided by two, the off-diagonal added, and multiplied by two
81874a ·* again. ·The low bit is simply a copy of the low bit of the
387b99 ·* input, so it doesn't need special care.
04775e ·*
1c96ea ·* TODO: Merge the shift by 1 with the squaring loop.
ce35e2 ·* TODO: Use Karatsuba. ·(a*W+b)^2 = a^2 * (W^2+W) + b^2 * (W+1) - (a-b)^2 * W.
f1495d ·*/
88b6a5 #ifndef bniSquare_64
a9314a void
23563c bniSquare_64(BNWORD64 *prod, BNWORD64 const *num, unsigned len)
a2bb36 {
85d6e3 ¤   BNWORD64 t;
99c992 ¤   BNWORD64 *prodx = prod;¤¤   /* Working copy of the argument */
51beed ¤   BNWORD64 const *numx = num;¤/* Working copy of the argument */
b3a2af ¤   unsigned lenx = len;¤   ¤   /* Working copy of the argument */
ceaf5a
1a4404 ¤   if (!len)
6299bf ¤   ¤   return;
bbaf5a
000677 ¤   /* First, store all the squares */
430a75 ¤   while (lenx--) {
--47e8 0006b19346140100154 Page 16 of bni64.c
885305 #ifdef mul64_ppmm
140296 ¤   ¤   BNWORD64 ph, pl;
62499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
c5534f ¤   ¤   mul64_ppmm(ph,pl,t,t);
0aeac4 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = pl;
aa89a5 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = ph;
da9792 #elif defined(BNWORD128) /* use BNWORD128 */
342d40 ¤   ¤   BNWORD128 p;
99499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
33a24e ¤   ¤   p = (BNWORD128)t * t;
1bf222 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = (BNWORD64)p;
5454d4 ¤   ¤   BIGLITTLE(*--prodx,*prodx++) = (BNWORD64)(p>>64);
5d324f #else¤  /* Use bniMulN1_64 */
545403 ¤   ¤   t = BIGLITTLE(numx[-1],*numx);
3b79c3 ¤   ¤   bniMulN1_64(prodx, numx, 1, t);
799d54 ¤   ¤   BIGLITTLE(--numx,numx++);
470cad ¤   ¤   BIGLITTLE(prodx -= 2, prodx += 2);
c07454 #endif
129371 ¤   }
4b6220 ¤   /* Then, shift right 1 bit */
e66cab ¤   (void)bniRshift_64(prod, 2*len, 1);
43af5a
1aba8b ¤   /* Then, add in the off-diagonal sums */
b2a223 ¤   lenx = len;
9e9ff9 ¤   numx = num;
6944f6 ¤   prodx = prod;
fa23f3 ¤   while (--lenx) {
2a499c ¤   ¤   t = BIGLITTLE(*--numx,*numx++);
091fab ¤   ¤   BIGLITTLE(--prodx,prodx++);
89646e ¤   ¤   t = bniMulAdd1_64(prodx, numx, lenx, t);
4006c2 ¤   ¤   bniAdd1_64(BIGLITTLE(prodx-lenx,prodx+lenx), lenx+1, t);
041fab ¤   ¤   BIGLITTLE(--prodx,prodx++);
849371 ¤   }
4faf5a
70ca8f ¤   /* Shift it back up */
7d3f0a ¤   bniDouble_64(prod, 2*len);
33af5a
8945fb ¤   /* And set the low bit appropriately */
e37f4b ¤   BIGLITTLE(prod[-1],prod[0]) |= BIGLITTLE(num[-1],num[0]) & 1;
2eefe6 }
139061 #endif /* !bniSquare_64 */
b9af5a
4f38e5 /*
4ed88a ·* bniNorm_64 - given a number, return a modified length such that the
aec010 ·* most significant digit is non-zero. ·Zero-length input is okay.
66495d ·*/
569996 #ifndef bniNorm_64
a2536c unsigned
e300df bniNorm_64(BNWORD64 const *num, unsigned len)
e7bb36 {
9b788e ¤   BIGLITTLE(num -= len,num += len);
e7bd5b ¤   while (len && BIGLITTLE(*num++,*--num) == 0)
bd9647 ¤   ¤   --len;
2ebb7a ¤   return len;
5aefe6 }
b004ce #endif /* bniNorm_64 */
bfaf5a
9e38e5 /*
0e1039 ·* bniBits_64 - return the number of significant bits in the array.
7a9a79 ·* It starts by normalizing the array. ·Zero-length input is okay.
33cb59 ·* Then assuming there's anything to it, it fetches the high word,
be4e60 ·* generates a bit length by multiplying the word length by 64, and
87db19 ·* subtracts off 64/2, 64/4, 64/8, ... bits if the high bits are clear.
4f495d ·*/
6f373b #ifndef bniBits_64
1c536c unsigned
aeee3b bniBits_64(BNWORD64 const *num, unsigned len)
ffbb36 {
56d6e3 ¤   BNWORD64 t;
ca743f ¤   unsigned i;
51af5a
6b6b49 ¤   len = bniNorm_64(num, len);
--196b 0004ea86a1640100154 Page 17 of bni64.c
8e5678 ¤   if (len) {
49027d ¤   ¤   t = BIGLITTLE(*(num-len),*(num+(len-1)));
40146d ¤   ¤   pgpAssert(t);
1054de ¤   ¤   len *= 64;
b887df ¤   ¤   i = 64/2;
144392 ¤   ¤   do {
6801ae ¤   ¤   ¤   if (t >> i)
c4cfc5 ¤   ¤   ¤   ¤   t >>= i;
8ebb8c ¤   ¤   ¤   else
d8e024 ¤   ¤   ¤   ¤   len -= i;
df03d7 ¤   ¤   } while ((i /= 2) != 0);
769371 ¤   }
92bb7a ¤   return len;
69efe6 }
dbc189 #endif /* bniBits_64 */
edaf5a
6738e5 /*
691bed ·* If defined, use hand-rolled divide rather than compiler's native.
ad6018 ·* If the machine doesn't do it in line, the manual code is probably
56aab8 ·* faster, since it can assume normalization and the fact that the
be8450 ·* quotient will fit into 64 bits, which a general 128-bit divide
a0b8b7 ·* in a compiler's run-time library can't do.
2c495d ·*/
422b4a #ifndef BN_SLOW_DIVIDE_128
228fe1 /* Assume that divisors of more than thirty-two bits are slow */
0ed901 #define BN_SLOW_DIVIDE_128 (128 > 0x20)
4d7454 #endif
abaf5a
1f38e5 /*
95acf6 ·* Return (nh<<64|nl) % d, and place the quotient digit into *q.
507bdc ·* It is guaranteed that nh < d, and that d is normalized (with its high
b45ded ·* bit set). ·If we have a double-width type, it's easy. ·If not, ooh,
5e7c0f ·* yuk!
92495d ·*/
a88ce5 #ifndef bniDiv21_64
f06e82 #if defined(BNWORD128) && !BN_SLOW_DIVIDE_128
4c8bb4 BNWORD64
60d0da bniDiv21_64(BNWORD64 *q, BNWORD64 nh, BNWORD64 nl, BNWORD64 d)
46bb36 {
19532b ¤   BNWORD128 n = (BNWORD128)nh << 64 | nl;
a8af5a
19d586 ¤   /* Divisor must be normalized */
50f40d ¤   pgpAssert(d >> (64-1) == 1);
31af5a
c494b0 ¤   *q = n / d;
844a7d ¤   return n % d;
11efe6 }
e6db21 #else
6c38e5 /*
e519ca ·* This is where it gets ugly.
78775e ·*
cae007 ·* Do the division in two halves, using Algorithm D from section 4.3.1
beb8a8 ·* of Knuth. ·Note Theorem B from that section, that the quotient estimate
ada6e2 ·* is never more than the true quotient, and is never more than two
4b2734 ·* too low.
6d775e ·*
b1f95e ·* The mapping onto conventional long division is (everything a half word):
1ae4ba ·* ·······_____________qh___ql_
735d43 ·* dh dl ) nh.h nh.l nl.h nl.l
01b6a5 ·* ············- (qh * d)
07c3aa ·* ···········-----------
812238 ·* ·············rrrr rrrr nl.l
a86972 ·* ·················- (ql * d)
116a88 ·* ···············-----------
1ebc8e ·* ·················rrrr rrrr
96775e ·*
4915e9 ·* The implicit 3/2-digit d*qh and d*ql subtractors are computed this way:
8c8d7d ·* ··First, estimate a q digit so that nh/dh works. ·Subtracting qh*dh from
637db1 ·* ··the (nh.h nh.l) list leaves a 1/2-word remainder r. ·Then compute the
599d8c ·* ··low part of the subtractor, qh * dl. ··This also needs to be subtracted
12f9d1 ·* ··from (nh.h nh.l nl.h) to get the final remainder. ·So we take the
4e91f1 ·* ··remainder, which is (nh.h nh.l) - qh*dl, shift it and add in nl.h, and
--b137 0000e66739140100154 Page 18 of bni64.c
af6618 ·* ··try to subtract qh * dl from that. ·Since the remainder is 1/2-word
16c6dd ·* ··long, shifting and adding nl.h results in a single word r.
1188e0 ·* ··It is possible that the remainder we're working with, r, is less than
c32698 ·* ··the product qh * dl, if we estimated qh too high. ·The estimation
e01818 ·* ··technique can produce a qh that is too large (never too small), leading
ccbbcb ·* ··to r which is too small. ·In that case, decrement the digit qh, add
0ae8c0 ·* ··shifted dh to r (to correct for that error), and subtract dl from the
461da5 ·* ··product we're comparing r with. ·That's the "correct" way to do it, but
f0d269 ·* ··just adding dl to r instead of subtracting it from the product is
9e3c97 ·* ··equivalent and a lot simpler. ·You just have to watch out for overflow.
1c775e ·*
7b6b5a ·* ··The process is repeated with (rrrr rrrr nl.l) for the low digit of the
ebf69b ·* ··quotient ql.
0b775e ·*
412e83 ·* The various uses of 64/2 for shifts are because of the note about
831e9c ·* automatic editing of this file at the very top of the file.
28495d ·*/
d9c2fb #define highhalf(x) ( (x) >> 64/2 )
5508b4 #define lowhalf(x) ( (x) & (((BNWORD64)1 << 64/2)-1) )
6b8bb4 BNWORD64
9cd0da bniDiv21_64(BNWORD64 *q, BNWORD64 nh, BNWORD64 nl, BNWORD64 d)
dabb36 {
cb8e1e ¤   BNWORD64 dh = highhalf(d), dl = lowhalf(d);
afed9e ¤   BNWORD64 qh, ql, prod, r;
e9af5a
05d586 ¤   /* Divisor must be normalized */
da93f7 ¤   pgpAssert((d >> (64-1)) == 1);
09af5a
d0182e ¤   /* Do first half-word of division */
d5c97b ¤   qh = nh / dh;
99e25e ¤   r = nh % dh;
1551b2 ¤   prod = qh * dl;
a6af5a
79d8af ¤   /*
5f389a ¤   ·* Add next half-word of numerator to remainder and correct.
da5820 ¤   ·* qh may be up to two too large.
79a4e3 ¤   ·*/
3b1942 ¤   r = (r << (64/2)) | highhalf(nl);
0b482f ¤   if (r < prod) {
b3eccd ¤   ¤   --qh; r += d;
f9d103 ¤   ¤   if (r >= d && r < prod) {
b4daa8 ¤   ¤   ¤   --qh; r += d;·
530fe4 ¤   ¤   }
d19371 ¤   }
4a80c1 ¤   r -= prod;
71af5a
1ce034 ¤   /* Do second half-word of division */
593cab ¤   ql = r / dh;
bc2bf1 ¤   r = r % dh;
4c476c ¤   prod = ql * dl;
6eaf5a
5bcb5d ¤   r = (r << (64/2)) | lowhalf(nl);
9d482f ¤   if (r < prod) {
d0b298 ¤   ¤   --ql; r += d;
5bd103 ¤   ¤   if (r >= d && r < prod) {
03752d ¤   ¤   ¤   --ql; r += d;
3b0fe4 ¤   ¤   }
ef9371 ¤   }
0d80c1 ¤   r -= prod;
b6af5a
0ebec9 ¤   *q = (qh << (64/2)) | ql;
caaf5a
938da5 ¤   return r;
65efe6 }
237454 #endif
b46d61 #endif /* bniDiv21_64 */
4aaf5a
58af5a
4338e5 /*
703149 ·* In the division functions, the dividend and divisor are referred to
38cc61 ·* as "n" and "d", which stand for "numerator" and "denominator".
0e775e ·*
--f16f 000a1e1ef4a40100154 Page 19 of bni64.c
0882a1 ·* The quotient is (nlen-dlen+1) digits long. ·It may be overlapped with
3a3b4e ·* the high (nlen-dlen) words of the dividend, but one extra word is needed
b4df50 ·* on top to hold the top word.
55495d ·*/
f7af5a
1438e5 /*
9923cd ·* Divide an n-word number by a 1-word number, storing the remainder
7ad04d ·* and n-1 words of the n-word quotient. ·The high word is returned.
9abd9b ·* It IS legal for rem to point to the same address as n, and for
42eab3 ·* q to point one word higher.
02775e ·*
0ae486 ·* TODO: If BN_SLOW_DIVIDE_128, add a divnhalf_64 which uses 64-bit
f911b4 ·* ······dividends if the divisor is half that long.
ccac82 ·* TODO: Shift the dividend on the fly to avoid the last division and
612014 ·* ······instead have a remainder that needs shifting.
91f820 ·* TODO: Use reciprocals rather than dividing.
d5495d ·*/
09f576 #ifndef bniDiv1_64
398bb4 BNWORD64
64f89a bniDiv1_64(BNWORD64 *q, BNWORD64 *rem, BNWORD64 const *n, unsigned len,
d7f557 ¤   BNWORD64 d)
23bb36 {
d37dd8 ¤   unsigned shift;
cc9bf3 ¤   unsigned xlen;
fc003a ¤   BNWORD64 r;
c7384b ¤   BNWORD64 qhigh;
32af5a
445334 ¤   pgpAssert(len > 0);
f1ed56 ¤   pgpAssert(d);
7daf5a
9e20c0 ¤   if (len == 1) {
e9ea40 ¤   ¤   r = *n;
1b94a7 ¤   ¤   *rem = r%d;
5c4092 ¤   ¤   return r/d;
b69371 ¤   }
79af5a
221fab ¤   shift = 0;
cbdca5 ¤   r = d;
ba2904 ¤   xlen = 64/2;
9643ab ¤   do {
c4d555 ¤   ¤   if (r >> xlen)
004bd3 ¤   ¤   ¤   r >>= xlen;
870e1d ¤   ¤   else
e4f0a7 ¤   ¤   ¤   shift += xlen;
001729 ¤   } while ((xlen /= 2) != 0);
fe77b0 ¤   pgpAssert((d >> (64-1-shift)) == 1);
8e1802 ¤   d <<= shift;
43af5a
c82980 ¤   BIGLITTLE(q -= len-1,q += len-1);
c6015b ¤   BIGLITTLE(n -= len,n += len);
ecaf5a
3929a3 ¤   r = BIGLITTLE(*n++,*--n);
387444 ¤   if (r < d) {
30d3c6 ¤   ¤   qhigh = 0;
ecf037 ¤   } else {
91f48d ¤   ¤   qhigh = r/d;
60ee48 ¤   ¤   r %= d;
b59371 ¤   }
1faf5a
281d7d ¤   xlen = len;
ad2884 ¤   while (--xlen)
6a79db ¤   ¤   r = bniDiv21_64(BIGLITTLE(q++,--q), r,
bf4662 ¤   ¤   ¤   ¤   BIGLITTLE(*n++,*--n), d);
27af5a
f7d8af ¤   /*
375d19 ¤   ·* Final correction for shift - shift the quotient up "shift"
4f86e9 ¤   ·* bits, and merge in the extra bits of quotient. ·Then reduce
d4533a ¤   ·* the final remainder mod the real d.
77a4e3 ¤   ·*/
5d5df3 ¤   if (shift) {
50aae5 ¤   ¤   d >>= shift;
a1580f ¤   ¤   qhigh = (qhigh << shift) | bniLshift_64(q, len-1, shift);
--02a6 000f8ec4b4740100154 Page 20 of bni64.c
ed14b8 ¤   ¤   BIGLITTLE(q[-1],*q) |= r/d;
64ee48 ¤   ¤   r %= d;
619371 ¤   }
7fe0a8 ¤   *rem = r;
8caf5a
d097ee ¤   return qhigh;
e2efe6 }
407454 #endif
34af5a
de38e5 /*
156e68 ·* This function performs a "quick" modulus of a number with a divisor
1280bd ·* d which is guaranteed to be at most sixteen bits, i.e. less than 65536.
622b4d ·* This applies regardless of the word size the library is compiled with.
a8775e ·*
04e96b ·* This function is important to prime generation, for sieving.
1c495d ·*/
2feaed #ifndef bniModQ_64
8bc77b /* If there's a custom bniMod21_64, no normalization needed */
cf928b #ifdef bniMod21_64
b5536c unsigned
d96f99 bniModQ_64(BNWORD64 const *n, unsigned len, unsigned d)
29bb36 {
76bfcd ¤   unsigned i, shift;
93003a ¤   BNWORD64 r;
b8af5a
825334 ¤   pgpAssert(len > 0);
a6af5a
be015b ¤   BIGLITTLE(n -= len,n += len);
f0af5a
0410e0 ¤   /* Try using a compare to avoid the first divide */
2d29a3 ¤   r = BIGLITTLE(*n++,*--n);
97132b ¤   if (r >= d)
40ee48 ¤   ¤   r %= d;
c19fd1 ¤   while (--len)
5a67d4 ¤   ¤   r = bniMod21_64(r, BIGLITTLE(*n++,*--n), d);
0faf5a
338da5 ¤   return r;
7befe6 }
c61650 #elif defined(BNWORD128) && !BN_SLOW_DIVIDE_128
7d536c unsigned
586f99 bniModQ_64(BNWORD64 const *n, unsigned len, unsigned d)
36bb36 {
54003a ¤   BNWORD64 r;
d0af5a
3fb24c ¤   if (!--len)
c76024 ¤   ¤   return BIGLITTLE(n[-1],n[0]) % d;
57af5a
ed015b ¤   BIGLITTLE(n -= len,n += len);
1e4a3b ¤   r = BIGLITTLE(n[-1],n[0]);
8eaf5a
bb43ab ¤   do {
22c180 ¤   ¤   r = (BNWORD64)((((BNWORD128)r<<64) | BIGLITTLE(*n++,*--n)) % d);
95c57e ¤   } while (--len);
9caf5a
b78da5 ¤   return r;
c9efe6 }
25dc4c #elif 64 >= 0x20
f338e5 /*
110ce5 ·* If the single word size can hold 65535*65536, then this function
28461a ·* is avilable.
d0495d ·*/
9595bc #ifndef highhalf
00c2fb #define highhalf(x) ( (x) >> 64/2 )
1489f7 #define lowhalf(x) ( (x) & ((1 << 64/2)-1) )
327454 #endif
81536c unsigned
c06f99 bniModQ_64(BNWORD64 const *n, unsigned len, unsigned d)
3cbb36 {
dd99ff ¤   BNWORD64 r, x;
bdaf5a
8e015b ¤   BIGLITTLE(n -= len,n += len);
f8af5a
--1235 000c6c42c2640100154 Page 21 of bni64.c
a729a3 ¤   r = BIGLITTLE(*n++,*--n);
85e1ea ¤   while (--len) {
e5d6fc ¤   ¤   x = BIGLITTLE(*n++,*--n);
705315 ¤   ¤   r = (r%d << 64/2) | highhalf(x);
4d3bc2 ¤   ¤   r = (r%d << 64/2) | lowhalf(x);
e69371 ¤   }
1caf5a
f30b4f ¤   return r%d;
3fefe6 }
5edb21 #else
f0917c /* Default case - use bniDiv21_64 */
37536c unsigned
506f99 bniModQ_64(BNWORD64 const *n, unsigned len, unsigned d)
2cbb36 {
bdbfcd ¤   unsigned i, shift;
3a003a ¤   BNWORD64 r;
40ef5e ¤   BNWORD64 q;
cfaf5a
c85334 ¤   pgpAssert(len > 0);
87af5a
471fab ¤   shift = 0;
28dca5 ¤   r = d;
f6a8e8 ¤   i = 64;
c63a3d ¤   while (i /= 2) {
d366eb ¤   ¤   if (r >> i)
d3da0b ¤   ¤   ¤   r >>= i;
1b0e1d ¤   ¤   else
5491e5 ¤   ¤   ¤   shift += i;
8e9371 ¤   }
9a6c56 ¤   pgpAssert(d >> (64-1-shift) == 1);
df1802 ¤   d <<= shift;
9eaf5a
29015b ¤   BIGLITTLE(n -= len,n += len);
a2af5a
c929a3 ¤   r = BIGLITTLE(*n++,*--n);
f3132b ¤   if (r >= d)
30ee48 ¤   ¤   r %= d;
69af5a
fd9fd1 ¤   while (--len)
af5286 ¤   ¤   r = bniDiv21_64(&q, r, BIGLITTLE(*n++,*--n), d);
f5af5a
add8af ¤   /*
575d19 ¤   ·* Final correction for shift - shift the quotient up "shift"
bf86e9 ¤   ·* bits, and merge in the extra bits of quotient. ·Then reduce
06533a ¤   ·* the final remainder mod the real d.
efa4e3 ¤   ·*/
bc5bcd ¤   if (shift)
3c0a63 ¤   ¤   r %= d >> shift;
b2af5a
058da5 ¤   return r;
83efe6 }
8d7454 #endif
a4771c #endif /* bniModQ_64 */
8aaf5a
fb38e5 /*
af8f9d ·* Reduce n mod d and return the quotient. ·That is, find:
e690f4 ·* q = n / d;
f5b155 ·* n = n % d;
8a3baf ·* d is altered during the execution of this subroutine by normalizing it.
df32be ·* It must already have its most significant word non-zero; it is shifted
258f79 ·* so its most significant bit is non-zero.
8f775e ·*
1aafe6 ·* The quotient q is nlen-dlen+1 words long. ·To make it possible to
ed6507 ·* overlap the quptient with the input (you can store it in the high dlen
77ce0a ·* words), the high word of the quotient is *not* stored, but is returned.
b8496b ·* (If all you want is the remainder, you don't care about it, anyway.)
5b775e ·*
dedabd ·* This uses algorithm D from Knuth (4.3.1), except that we do binary
32d5f9 ·* (shift) normalization of the divisor. ·WARNING: This is hairy!
93775e ·*
555ddb ·* This function is used for some modular reduction, but it is not used in
c6d0fc ·* the modular exponentiation loops; they use Montgomery form and the
--66e2 0003264844e40100154 Page 22 of bni64.c
dbaee4 ·* corresponding, more efficient, Montgomery reduction. ·This code
4510d2 ·* is needed for the conversion to Montgomery form, however, so it
21f6e7 ·* has to be here and it might as well be reasonably efficient.
70775e ·*
e3d437 ·* The overall operation is as follows ("top" and "up" refer to the
2dfeed ·* most significant end of the number; "bottom" and "down", the least):
3b775e ·*
dc9afe ·* - Shift the divisor up until the most significant bit is set.
ffa9b3 ·* - Shift the dividend up the same amount. ·This will produce the
f85a26 ·* ··correct quotient, and the remainder can be recovered by shifting
b17f2e ·* ··it back down the same number of bits. ·This may produce an overflow
a7697f ·* ··word, but the word is always strictly less than the most significant
484c66 ·* ··divisor word.
0bd315 ·* - Estimate the first quotient digit qhat:
f69aed ·* ··- First take the top two words (one of which is the overflow) of the
fb1d7a ·* ····dividend and divide by the top word of the divisor:
f94384 ·* ····qhat = (nh,nm)/dh. ·This qhat is >= the correct quotient digit
124e72 ·* ····and, since dh is normalized, it is at most two over.
3eb00c ·* ··- Second, correct by comparing the top three words. ·If
07e3f2 ·* ····(dh,dl) * qhat > (nh,nm,ml), decrease qhat and try again.
396520 ·* ····The second iteration can be simpler because there can't be a third.
1e0134 ·* ····The computation can be simplified by subtracting dh*qhat from
e2e263 ·* ····both sides, suitably shifted. ·This reduces the left side to
4932b9 ·* ····dl*qhat. ·On the right, (nh,nm)-dh*qhat is simply the
1a468d ·* ····remainder r from (nh,nm)%dh, so the right is (r,nl).
c4208a ·* ····This produces qhat that is almost always correct and at
cab525 ·* ····most (prob ~ 2/2^64) one too high.
b8666b ·* - Subtract qhat times the divisor (suitably shifted) from the dividend.
ef1eae ·* ··If there is a borrow, qhat was wrong, so decrement it
d4e18e ·* ··and add the divisor back in (once).
d52ab7 ·* - Store the final quotient digit qhat in the quotient array q.
0b775e ·*
1eabaf ·* Repeat the quotient digit computation for successive digits of the
212a22 ·* quotient until the whole quotient has been computed. ·Then shift the
7a2dab ·* divisor and the remainder down to correct for the normalization.
35775e ·*
dfd917 ·* TODO: Special case 2-word divisors.
c3f820 ·* TODO: Use reciprocals rather than dividing.
4e495d ·*/
cbdb82 #ifndef divn_64
9c8bb4 BNWORD64
e70177 bniDiv_64(BNWORD64 *q, BNWORD64 *n, unsigned nlen, BNWORD64 *d, unsigned dlen)
1bbb36 {
3ee7c4 ¤   BNWORD64 nh,nm,nl;¤ /* Top three words of the dividend */
68573b ¤   BNWORD64 dh,dl;¤/* Top two words of the divisor */
432f99 ¤   BNWORD64 qhat;¤ /* Extimate of quotient word */
ebe10c ¤   BNWORD64 r;¤/* Remainder from quotient estimate division */
57c33c ¤   BNWORD64 qhigh;¤/* High word of quotient */
6b27a0 ¤   unsigned i;¤/* Temp */
e2500c ¤   unsigned shift;¤/* Bits shifted by normalization */
5274f3 ¤   unsigned qlen = nlen-dlen; /* Size of quotient (less 1) */
255305 #ifdef mul64_ppmm
829020 ¤   BNWORD64 t64;
542f3b #elif defined(BNWORD128)
0aa7db ¤   BNWORD128 t128;
0097c5 #else /* use bniMulN1_64 */
08678c ¤   BNWORD64 t2[2];
5ecd0c #define t2high BIGLITTLE(t2[0],t2[1])
a164b5 #define t2low BIGLITTLE(t2[1],t2[0])
d27454 #endif
cdaf5a
9f872a ¤   pgpAssert(dlen);
a59dbd ¤   pgpAssert(nlen >= dlen);
8daf5a
b0d8af ¤   /*
cc480b ¤   ·* Special cases for short divisors. ·The general case uses the
e9fd33 ¤   ·* top top 2 digits of the divisor (d) to estimate a quotient digit,
10c774 ¤   ·* so it breaks if there are fewer digits available. ·Thus, we need
8f8f21 ¤   ·* special cases for a divisor of length 1. ·A divisor of length
ccee27 ¤   ·* 2 can have a *lot* of administrivia overhead removed removed,
b46e28 ¤   ·* so it's probably worth special-casing that case, too.
32a4e3 ¤   ·*/
--8ffb 0001803084540100154 Page 23 of bni64.c
2bb547 ¤   if (dlen == 1)
5d8654 ¤   ¤   return bniDiv1_64(q, BIGLITTLE(n-1,n), n, nlen,
51bb59 ¤   ¤   ··················BIGLITTLE(d[-1],d[0]));
24af5a
b1b177 #if 0
56d8af ¤   /*
2e9c22 ¤   ·* @@@ This is not yet written... ·The general loop will do,
007741 ¤   ·* albeit less efficiently
bba4e3 ¤   ·*/
963ff3 ¤   if (dlen == 2) {
211b17 ¤   ¤   /*
600fc2 ¤   ¤   ·* divisor two digits long:
c81388 ¤   ¤   ·* use the 3/2 technique from Knuth, but we know
a9bd83 ¤   ¤   ·* it's exact.
ec9de3 ¤   ¤   ·*/
66a363 ¤   ¤   dh = BIGLITTLE(d[-1],d[0]);
0a9d7f ¤   ¤   dl = BIGLITTLE(d[-2],d[1]);
98fd08 ¤   ¤   shift = 0;
f290d1 ¤   ¤   if ((sh & ((BNWORD64)1 << 64-1-shift)) == 0) {
47f603 ¤   ¤   ¤   do {
f85919 ¤   ¤   ¤   ¤   shift++;
bf8775 ¤   ¤   ¤   } while (dh & (BNWORD64)1<<64-1-shift) == 0);
d2dd53 ¤   ¤   ¤   dh = dh << shift | dl >> (64-shift);
dced08 ¤   ¤   ¤   dl <<= shift;
d0af5a
d8af5a
560fe4 ¤   ¤   }
18af5a
daaf5a
ca6eef ¤   ¤   for (shift = 0; (dh & (BNWORD64)1 << 64-1-shift)) == 0;
0a48b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   shift++)
30b110 ¤   ¤   ¤   ;
031c78 ¤   ¤   if (shift) {
770fe4 ¤   ¤   }
ef8fce ¤   ¤   dh = dh << shift | dl >> (64-shift);
befd08 ¤   ¤   shift = 0;
f03ddc ¤   ¤   while (dh
699371 ¤   }
437454 #endif
80af5a
8e53dc ¤   dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
520d5f ¤   pgpAssert(dh);
edaf5a
17d240 ¤   /* Normalize the divisor */
e81fab ¤   shift = 0;
a49edc ¤   r = dh;
ea026a ¤   i = 64/2;
dd43ab ¤   do {
9366eb ¤   ¤   if (r >> i)
94da0b ¤   ¤   ¤   r >>= i;
f20e1d ¤   ¤   else
b491e5 ¤   ¤   ¤   shift += i;
4bb881 ¤   } while ((i /= 2) != 0);
0eaf5a
54790d ¤   nh = 0;
c25df3 ¤   if (shift) {
06a884 ¤   ¤   bniLshift_64(d, dlen, shift);
4b0141 ¤   ¤   dh = BIGLITTLE(*(d-dlen),*(d+(dlen-1)));
2fe888 ¤   ¤   nh = bniLshift_64(n, nlen, shift);
4e9371 ¤   }
80af5a
762e18 ¤   /* Assert that dh is now normalized */
cf5077 ¤   pgpAssert(dh >> (64-1));
97af5a
11ff88 ¤   /* Also get the second-most significant word of the divisor */
e9472b ¤   dl = BIGLITTLE(*(d-(dlen-1)),*(d+(dlen-2)));
26af5a
43d8af ¤   /*
44007a ¤   ·* Adjust pointers: n to point to least significant end of first
3dd7b5 ¤   ·* first subtract, and q to one the most-significant end of the
35e66e ¤   ·* quotient array.
18a4e3 ¤   ·*/
--02f2 000c58b6b5e40100154 Page 24 of bni64.c
f63fac ¤   BIGLITTLE(n -= qlen,n += qlen);
7b4367 ¤   BIGLITTLE(q -= qlen,q += qlen);
36af5a
40eeb5 ¤   /* Fetch the most significant stored word of the dividend */
60e870 ¤   nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
5baf5a
28d8af ¤   /*
fc6d56 ¤   ·* Compute the first digit of the quotient, based on the
d70e82 ¤   ·* first two words of the dividend (the most significant of which
fe3605 ¤   ·* is the overflow word h).
fca4e3 ¤   ·*/
7921e5 ¤   if (nh) {
ba068c ¤   ¤   pgpAssert(nh < dh);
805d0b ¤   ¤   r = bniDiv21_64(&qhat, nh, nm, dh);
296eba ¤   } else if (nm >= dh) {
aca30b ¤   ¤   qhat = nm/dh;
dd34b4 ¤   ¤   r = nm % dh;
1a2487 ¤   } else {¤   /* Quotient is zero */
82d3c6 ¤   ¤   qhigh = 0;
bd0a09 ¤   ¤   goto divloop;
dd9371 ¤   }
21af5a
db10e1 ¤   /* Now get the third most significant word of the dividend */
fd5498 ¤   nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
96af5a
cad8af ¤   /*
bb728b ¤   ·* Correct qhat, the estimate of quotient digit.
58fac8 ¤   ·* qhat can only be high, and at most two words high,
5a7c55 ¤   ·* so the loop can be unrolled and abbreviated.
dba4e3 ¤   ·*/
255305 #ifdef mul64_ppmm
8dde4c ¤   mul64_ppmm(nm, t64, qhat, dl);
e6738a ¤   if (nm > r || (nm == r && t64 > nl)) {
627f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
39eeae ¤   ¤   qhat--;
14588d ¤   ¤   if ((r += dh) >= dh) {
9aeb70 ¤   ¤   ¤   nm -= (t64 < dl);
89c606 ¤   ¤   ¤   t64 -= dl;
59c8db ¤   ¤   ¤   if (nm > r || (nm == r && t64 > nl))
ec0329 ¤   ¤   ¤   ¤   qhat--;
540fe4 ¤   ¤   }
f59371 ¤   }
402f3b #elif defined(BNWORD128)
bd846a ¤   t128 = (BNWORD128)qhat * dl;
ead46d ¤   if (t128 > ((BNWORD128)r << 64) + nl) {
ef7f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
24eeae ¤   ¤   qhat--;
0d6578 ¤   ¤   if ((r += dh) > dh) {
2ed3cd ¤   ¤   ¤   t128 -= dl;
e9b75f ¤   ¤   ¤   if (t128 > ((BNWORD128)r << 64) + nl)
210329 ¤   ¤   ¤   ¤   qhat--;
070fe4 ¤   ¤   }
8e9371 ¤   }
846fd7 #else /* Use bniMulN1_64 */
4d62a4 ¤   bniMulN1_64(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
d5b1be ¤   if (t2high > r || (t2high == r && t2low > nl)) {
b17f54 ¤   ¤   /* Decrement qhat and adjust comparison parameters */
66eeae ¤   ¤   qhat--;
f9588d ¤   ¤   if ((r += dh) >= dh) {
695d65 ¤   ¤   ¤   t2high -= (t2low < dl);
4ca6d7 ¤   ¤   ¤   t2low -= dl;
b7cf7a ¤   ¤   ¤   if (t2high > r || (t2high == r && t2low > nl))
220329 ¤   ¤   ¤   ¤   qhat--;
340fe4 ¤   ¤   }
c69371 ¤   }
4a7454 #endif
e3af5a
893d4c ¤   /* Do the multiply and subtract */
52a050 ¤   r = bniMulSub1_64(n, d, dlen, qhat);
a8e204 ¤   /* If there was a borrow, add back once. */
d7fa13 ¤   if (r > nh) {¤  /* Borrow? */
c53ef2 ¤   ¤   (void)bniAddN_64(n, d, dlen);
--1474 0004877d87840100154 Page 25 of bni64.c
f0eeae ¤   ¤   qhat--;
b39371 ¤   }
90af5a
2ca3ca ¤   /* Remember the first quotient digit. */
75bac6 ¤   qhigh = qhat;
d3af5a
1e7f0b ¤   /* Now, the main division loop: */
3c2a7b divloop:
a655ea ¤   while (qlen--) {
5eaf5a
b17aef ¤   ¤   /* Advance n */
708c3f ¤   ¤   nh = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
109f99 ¤   ¤   BIGLITTLE(++n,--n);
d0baed ¤   ¤   nm = BIGLITTLE(*(n-dlen),*(n+(dlen-1)));
9aaf5a
2460da ¤   ¤   if (nh == dh) {
7a7699 ¤   ¤   ¤   qhat = ~(BNWORD64)0;
678a33 ¤   ¤   ¤   /* Optimized computation of r = (nh,nm) - qhat * dh */
46ceb5 ¤   ¤   ¤   r = nh + nm;
7e2398 ¤   ¤   ¤   if (r < nh)
6858b7 ¤   ¤   ¤   ¤   goto subtract;
2445a6 ¤   ¤   } else {
15abd2 ¤   ¤   ¤   pgpAssert(nh < dh);
6e455b ¤   ¤   ¤   r = bniDiv21_64(&qhat, nh, nm, dh);
d60fe4 ¤   ¤   }
15af5a
640783 ¤   ¤   nl = BIGLITTLE(*(n-(dlen-1)),*(n+(dlen-2)));
eb5305 #ifdef mul64_ppmm
a99fbf ¤   ¤   mul64_ppmm(nm, t64, qhat, dl);
a0e212 ¤   ¤   if (nm > r || (nm == r && t64 > nl)) {
68c34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
3379dd ¤   ¤   ¤   qhat--;
2dd4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
f4dc78 ¤   ¤   ¤   ¤   nm -= (t64 < dl);
7f24e7 ¤   ¤   ¤   ¤   t64 -= dl;
3d9bc0 ¤   ¤   ¤   ¤   if (nm > r || (nm == r && t64 > nl))
61f54c ¤   ¤   ¤   ¤   ¤   qhat--;
2da3a6 ¤   ¤   ¤   }
390fe4 ¤   ¤   }
982f3b #elif defined(BNWORD128)
6bb902 ¤   ¤   t128 = (BNWORD128)qhat * dl;
0403fb ¤   ¤   if (t128 > ((BNWORD128)r<<64) + nl) {
ecc34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
7e79dd ¤   ¤   ¤   qhat--;
a5d4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
e125a8 ¤   ¤   ¤   ¤   t128 -= dl;
e8195e ¤   ¤   ¤   ¤   if (t128 > ((BNWORD128)r << 64) + nl)
03f54c ¤   ¤   ¤   ¤   ¤   qhat--;
efa3a6 ¤   ¤   ¤   }
250fe4 ¤   ¤   }
e26fd7 #else /* Use bniMulN1_64 */
4e7383 ¤   ¤   bniMulN1_64(BIGLITTLE(t2+2,t2), &dl, 1, qhat);
a6de8d ¤   ¤   if (t2high > r || (t2high == r && t2low > nl)) {
a5c34d ¤   ¤   ¤   /* Decrement qhat and adjust comparison parameters */
4679dd ¤   ¤   ¤   qhat--;
85d4f2 ¤   ¤   ¤   if ((r += dh) >= dh) {
109830 ¤   ¤   ¤   ¤   t2high -= (t2low < dl);
49928a ¤   ¤   ¤   ¤   t2low -= dl;
51cf98 ¤   ¤   ¤   ¤   if (t2high > r || (t2high == r && t2low > nl))
5ff54c ¤   ¤   ¤   ¤   ¤   qhat--;
3aa3a6 ¤   ¤   ¤   }
660fe4 ¤   ¤   }
4f7454 #endif
b9af5a
691b17 ¤   ¤   /*
73a70b ¤   ¤   ·* As a point of interest, note that it is not worth checking
95b062 ¤   ¤   ·* for qhat of 0 or 1 and installing special-case code. ·These
f36799 ¤   ¤   ·* occur with probability 2^-64, so spending 1 cycle to check
c81cbe ¤   ¤   ·* for them is only worth it if we save more than 2^15 cycles,
c4265f ¤   ¤   ·* and a multiply-and-subtract for numbers in the 1024-bit
685841 ¤   ¤   ·* range just doesn't take that long.
489de3 ¤   ¤   ·*/
--5b11 000a0dd442b40100154 Page 26 of bni64.c
70bdcf subtract:
261b17 ¤   ¤   /*
9aa55f ¤   ¤   ·* n points to the least significant end of the substring
386576 ¤   ¤   ·* of n to be subtracted from. ·qhat is either exact or
ecdb63 ¤   ¤   ·* one too large. ·If the subtract gets a borrow, it was
1b897d ¤   ¤   ·* one too large and the divisor is added back in. ·It's
cf6fbb ¤   ¤   ·* a dlen+1 word add which is guaranteed to produce a
5125ad ¤   ¤   ·* carry out, so it can be done very simply.
df9de3 ¤   ¤   ·*/
dda6e8 ¤   ¤   r = bniMulSub1_64(n, d, dlen, qhat);
331560 ¤   ¤   if (r > nh) {¤  /* Borrow? */
c6021c ¤   ¤   ¤   (void)bniAddN_64(n, d, dlen);
e079dd ¤   ¤   ¤   qhat--;
f60fe4 ¤   ¤   }
cd5982 ¤   ¤   /* Store the quotient digit */
a2783d ¤   ¤   BIGLITTLE(*q++,*--q) = qhat;
3c9371 ¤   }
cf9169 ¤   /* Tah dah! */
75af5a
715df3 ¤   if (shift) {
cac392 ¤   ¤   bniRshift_64(d, dlen, shift);
be63f4 ¤   ¤   bniRshift_64(n, dlen, shift);
089371 ¤   }
f1af5a
4997ee ¤   return qhigh;
a1efe6 }
da7454 #endif
7caf5a
2338e5 /*
5045de ·* Find the negative multiplicative inverse of x (x must be odd!) modulo 2^64.
72775e ·*
42e4a4 ·* This just performs Newton's iteration until it gets the
1d2d8c ·* inverse. ·The initial estimate is always correct to 3 bits, and
e3d773 ·* sometimes 4. ·The number of valid bits doubles each iteration.
7632ba ·* (To prove it, assume x * y == 1 (mod 2^n), and introduce a variable
5560ca ·* for the error mod 2^2n. ·x * y == 1 + k*2^n (mod 2^2n) and follow
435d3e ·* the iteration through.)
66495d ·*/
4ccbc8 #ifndef bniMontInv1_64
ee8bb4 BNWORD64
bda4c6 bniMontInv1_64(BNWORD64 const x)
7dbb36 {
3ee16b ········BNWORD64 y = x, z;
13af5a
41201b ¤   pgpAssert(x & 1);
c8d83c ·
4dd2ee ········while ((z = x*y) != 1)
b7fa12 ················y *= 2 - z;
c86ae3 ········return -y;
fdefe6 }
0f0e52 #endif /* !bniMontInv1_64 */
31af5a
43957c #if defined(BNWORD128) && PRODUCT_SCAN
7238e5 /*
2b3de0 ·* Test code for product-scanning Montgomery reduction.
0b5767 ·* This seems to slow the C code down rather than speed it up.
68775e ·*
363e2e ·* The first loop computes the Montgomery multipliers, storing them over
e39652 ·* the low half of the number n.
d5775e ·*
dcbdb8 ·* The second half multiplies the upper half, adding in the modulus
ea2380 ·* times the Montgomery multipliers. ·The results of this multiply
57fa30 ·* are stored.
57495d ·*/
61314a void
ca6cc0 bniMontReduce_64(BNWORD64 *n, BNWORD64 const *mod, unsigned mlen, BNWORD64 inv)
3dbb36 {
fdf866 ¤   BNWORD128 x, y;
477a68 ¤   BNWORD64 const *pm;
36294e ¤   BNWORD64 *pn;
92d6e3 ¤   BNWORD64 t;
a050fc ¤   unsigned carry;
--56ad 0004f3d272740100154 Page 27 of bni64.c
d807cb ¤   unsigned i, j;
27af5a
94157a ¤   /* Special case of zero */
9bff48 ¤   if (!mlen)
db99bf ¤   ¤   return;
1aaf5a
e2a702 ¤   /* Pass 1 - compute Montgomery multipliers */
6b1ffe ¤   /* First iteration can have certain simplifications. */
e9af9a ¤   t = BIGLITTLE(n[-1],n[0]);
c4b067 ¤   x = t;
ab451d ¤   t *= inv;
9ef049 ¤   BIGLITTLE(n[-1], n[0]) = t;
322f20 ¤   x += (BNWORD128)t * BIGLITTLE(mod[-1],mod[0]); /* Can't overflow */
51b787 ¤   pgpAssert((BNWORD64)x == 0);
f641f7 ¤   x = x >> 64;
46af5a
9c947e ¤   for (i = 1; i < mlen; i++) {
0ffcf3 ¤   ¤   carry = 0;
60c3fd ¤   ¤   pn = n;
9bd39c ¤   ¤   pm = BIGLITTLE(mod-i-1,mod+i+1);
11f8a4 ¤   ¤   for (j = 0; j < i; j++) {
5735f6 ¤   ¤   ¤   y = (BNWORD128)BIGLITTLE(*--pn * *pm++, *pn++ * *--pm);
301ca0 ¤   ¤   ¤   x += y;
84dfb0 ¤   ¤   ¤   carry += (x < y);
2a0fe4 ¤   ¤   }
52ae1e ¤   ¤   pgpAssert(BIGLITTLE(pn == n-i, pn == n+i));
05d720 ¤   ¤   y = t = BIGLITTLE(pn[-1], pn[0]);
6a8bd3 ¤   ¤   x += y;
3756e4 ¤   ¤   carry += (x < y);
dfa831 ¤   ¤   BIGLITTLE(pn[-1], pn[0]) = t = inv * (BNWORD64)x;
f235b5 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-1, pm == mod+1));
e19346 ¤   ¤   y = (BNWORD128)t * BIGLITTLE(pm[0],pm[-1]);
eb8bd3 ¤   ¤   x += y;
d856e4 ¤   ¤   carry += (x < y);
e58aef ¤   ¤   pgpAssert((BNWORD64)x == 0);
038ca7 ¤   ¤   x = x >> 64 | (BNWORD128)carry << 64;
cd9371 ¤   }
5faf5a
902d98 ¤   BIGLITTLE(n -= mlen, n += mlen);
06af5a
447cfe ¤   /* Pass 2 - compute upper words and add to n */
e5947e ¤   for (i = 1; i < mlen; i++) {
b2fcf3 ¤   ¤   carry = 0;
c60805 ¤   ¤   pm = BIGLITTLE(mod-i,mod+i);
71c3fd ¤   ¤   pn = n;
4ced18 ¤   ¤   for (j = i; j < mlen; j++) {
fa3c69 ¤   ¤   ¤   y = (BNWORD128)BIGLITTLE(*--pm * *pn++, *pm++ * *--pn);
3f1ca0 ¤   ¤   ¤   x += y;
cedfb0 ¤   ¤   ¤   carry += (x < y);
350fe4 ¤   ¤   }
26ea60 ¤   ¤   pgpAssert(BIGLITTLE(pm == mod-mlen, pm == mod+mlen));
b83793 ¤   ¤   pgpAssert(BIGLITTLE(pn == n+mlen-i, pn == n-mlen+i));
10dabc ¤   ¤   y = t = BIGLITTLE(*(n-i),*(n+i-1));
ed8bd3 ¤   ¤   x += y;
0f56e4 ¤   ¤   carry += (x < y);
1bae05 ¤   ¤   BIGLITTLE(*(n-i),*(n+i-1)) = (BNWORD64)x;
64263a ¤   ¤   x = (x >> 64) | (BNWORD128)carry << 64;
599371 ¤   }
a8af5a
e5f753 ¤   /* Last round of second half, simplified. */
b8d2d2 ¤   t = BIGLITTLE(*(n-mlen),*(n+mlen-1));
686e1c ¤   x += t;
9d09f4 ¤   BIGLITTLE(*(n-mlen),*(n+mlen-1)) = (BNWORD64)x;
925ab3 ¤   carry = (unsigned)(x >> 64);
6daf5a
5aa53b ¤   while (carry)
5ede1a ¤   ¤   carry -= bniSubN_64(n, mod, mlen);
666313 ¤   while (bniCmp_64(n, mod, mlen) >= 0)
26dfa5 ¤   ¤   (void)bniSubN_64(n, mod, mlen);
a4efe6 }
5e55ae #define bniMontReduce_64 bniMontReduce_64
4f7454 #endif
--79d4 0002aacc42840100154 Page 28 of bni64.c
e0af5a
d338e5 /*
9bee5a ·* Montgomery reduce n, modulo mod. ·This reduces modulo mod and divides by
1caf66 ·* 2^(64*mlen). ·Returns the result in the *top* mlen words of the argument n.
99acac ·* This is ready for another multiplication using bniMul_64.
80775e ·*
082def ·* Montgomery representation is a very useful way to encode numbers when
d4a0f9 ·* you're doing lots of modular reduction. ·What you do is pick a multiplier
3e7f63 ·* R which is relatively prime to the modulus and very easy to divide by.
30bca7 ·* Since the modulus is odd, R is closen as a power of 2, so the division
49dc5c ·* is a shift. ·In fact, it's a shift of an integral number of words,
45fb89 ·* so the shift can be implicit - just drop the low-order words.
0d775e ·*
94d618 ·* Now, choose R *larger* than the modulus m, 2^(64*mlen). ·Then convert
01bdb2 ·* all numbers a, b, etc. to Montgomery form M(a), M(b), etc using the
0a8961 ·* relationship M(a) = a*R mod m, M(b) = b*R mod m, etc. ·Note that:
97a547 ·* - The Montgomery form of a number depends on the modulus m.
2dbd40 ·* ··A fixed modulus m is assumed throughout this discussion.
069d87 ·* - Since R is relaitvely prime to m, multiplication by R is invertible;
c570cf ·* ··no information about the numbers is lost, they're just scrambled.
20e310 ·* - Adding (and subtracting) numbers in this form works just as usual.
ff2937 ·* ··M(a+b) = (a+b)*R mod m = (a*R + b*R) mod m = (M(a) + M(b)) mod m
331edf ·* - Multiplying numbers in this form produces a*b*R*R. ·The problem
54322e ·* ··is to divide out the excess factor of R, modulo m as well as to
7f7321 ·* ··reduce to the given length mlen. ·It turns out that this can be
90ab47 ·* ··done *faster* than a normal divide, which is where the speedup
4bc3b7 ·* ··in Montgomery division comes from.
ed775e ·*
9ae4aa ·* Normal reduction chooses a most-significant quotient digit q and then
47ffcc ·* subtracts q*m from the number to be reduced. ·Choosing q is tricky
e0f2ce ·* and involved (just look at bniDiv_64 to see!) and is usually
097816 ·* imperfect, requiring a check for correction after the subtraction.
52775e ·*
e6b6cd ·* Montgomery reduction *adds* a multiple of m to the *low-order* part
bb1d3e ·* of the number to be reduced. ·This multiple is chosen to make the
27dcbd ·* low-order part of the number come out to zero. ·This can be done
ce452c ·* with no trickery or error using a precomputed inverse of the modulus.
05a07a ·* In this code, the "part" is one word, but any width can be used.
79775e ·*
b1cd30 ·* Repeating this step sufficiently often results in a value which
1aafde ·* is a multiple of R (a power of two, remember) but is still (since
25dfee ·* the additions were to the low-order part and thus did not increase
465a94 ·* the value of the number being reduced very much) still not much
a9a69e ·* larger than m*R. ·Then implicitly divide by R and subtract off
65b0fb ·* m until the result is in the correct range.
be775e ·*
8a97b6 ·* Since the low-order part being cancelled is less than R, the
5f19df ·* multiple of m added must have a multiplier which is at most R-1.
2cb2c3 ·* Assuming that the input is at most m*R-1, the final number is
6ab3ee ·* at most m*(2*R-1)-1 = 2*m*R - m - 1, so subtracting m once from
1e88f4 ·* the high-order part, equivalent to subtracting m*R from the
063b57 ·* while number, produces a result which is at most m*R - m - 1,
6b6ff3 ·* which divided by R is at most m-1.
ce775e ·*
2be28b ·* To convert *to* Montgomery form, you need a regular remainder
4f0506 ·* routine, although you can just compute R*R (mod m) and do the
da9da9 ·* conversion using Montgomery multiplication. ·To convert *from*
26e178 ·* Montgomery form, just Montgomery reduce the number to
73d688 ·* remove the extra factor of R.
5a9ec0 ·*·
7c8bba ·* TODO: Change to a full inverse and use Karatsuba's multiplication
71e6d5 ·* rather than this word-at-a-time.
8e495d ·*/
c878e3 #ifndef bniMontReduce_64
bb314a void
8b404f bniMontReduce_64(BNWORD64 *n, BNWORD64 const *mod, unsigned const mlen,
adf264 ················BNWORD64 inv)
a3bb36 {
dad6e3 ¤   BNWORD64 t;
f7c575 ¤   BNWORD64 c = 0;
c38079 ¤   unsigned len = mlen;
2aaf5a
--d2c3 00055ac761240100154 Page 29 of bni64.c
f59eac ¤   /* inv must be the negative inverse of mod's least significant word */
4f91f8 ¤   pgpAssert((BNWORD64)(inv * BIGLITTLE(mod[-1],mod[0])) == (BNWORD64)-1);
b4af5a
df86c8 ¤   pgpAssert(len);
e8af5a
f143ab ¤   do {
06d255 ¤   ¤   t = bniMulAdd1_64(n, mod, mlen, inv * BIGLITTLE(n[-1],n[0]));
081b10 ¤   ¤   c += bniAdd1_64(BIGLITTLE(n-mlen,n+mlen), len, t);
96f036 ¤   ¤   BIGLITTLE(--n,++n);
cdc57e ¤   } while (--len);
9caf5a
c4d8af ¤   /*
e2f214 ¤   ·* All that adding can cause an overflow past the modulus size,
0c8b38 ¤   ·* but it's unusual, and never by much, so a subtraction loop
56a65a ¤   ·* is the right way to deal with it.
912a16 ¤   ·* This subtraction happens infrequently - I've only ever seen it
d25758 ¤   ·* invoked once per reduction, and then just under 22.5% of the time.
5da4e3 ¤   ·*/
986bd2 ¤   while (c)
25882a ¤   ¤   c -= bniSubN_64(n, mod, mlen);
e26313 ¤   while (bniCmp_64(n, mod, mlen) >= 0)
69dfa5 ¤   ¤   (void)bniSubN_64(n, mod, mlen);
52efe6 }
e0d9f9 #endif /* !bniMontReduce_64 */
d0af5a
3938e5 /*
e900f3 ·* A couple of helpers that you might want to implement atomically
1f4a88 ·* in asm sometime.
e5495d ·*/
7611a4 #ifndef bniMontMul_64
c538e5 /*
09187a ·* Multiply "num1" by "num2", modulo "mod", all of length "len", and
1b8535 ·* place the result in the high half of "prod". ·"inv" is the inverse
4177d8 ·* of the least-significant word of the modulus, modulo 2^64.
becfb2 ·* This uses numbers in Montgomery form. ·Reduce using "len" and "inv".
32775e ·*
fd97ba ·* This is implemented as a macro to win on compilers that don't do
e299a7 ·* inlining, since it's so trivial.
6d495d ·*/
1a9018 #define bniMontMul_64(prod, n1, n2, mod, len, inv) \
50c97a ¤   (bniMulX_64(prod, n1, n2, len), bniMontReduce_64(prod, mod, len, inv))
b8e544 #endif /* !bniMontMul_64 */
b8af5a
45d256 #ifndef bniMontSquare_64
f038e5 /*
a32c86 ·* Square "num", modulo "mod", both of length "len", and place the result
fd2dbd ·* in the high half of "prod". ·"inv" is the inverse of the least-significant
57e322 ·* word of the modulus, modulo 2^64.
72cfb2 ·* This uses numbers in Montgomery form. ·Reduce using "len" and "inv".
7a775e ·*
a697ba ·* This is implemented as a macro to win on compilers that don't do
2c99a7 ·* inlining, since it's so trivial.
a7495d ·*/
23202c #define bniMontSquare_64(prod, n, mod, len, inv) \
7475a4 ¤   (bniSquare_64(prod, n, len), bniMontReduce_64(prod, mod, len, inv))
f967c5 ¤
6a3889 #endif /* !bniMontSquare_64 */
acaf5a
1a38e5 /*
6fa390 ·* Convert a number to Montgomery form - requires mlen + nlen words
1215f8 ·* of memory in "n".
99495d ·*/
cd314a void
11bac5 bniToMont_64(BNWORD64 *n, unsigned nlen, BNWORD64 *mod, unsigned mlen)
bbbb36 {
7b9cf5 ¤   /* Move n up "mlen" words */
43593c ¤   bniCopy_64(BIGLITTLE(n-mlen,n+mlen), n, nlen);
d19578 ¤   bniZero_64(n, mlen);
dfa154 ¤   /* Do the division - dump the quotient in the high-order words */
f05c73 ¤   (void)bniDiv_64(BIGLITTLE(n-mlen,n+mlen), n, mlen+nlen, mod, mlen);
a9efe6 }
55af5a
--4d72 000deba4b8240100154 Page 30 of bni64.c
bc38e5 /*
00d6c1 ·* Convert from Montgomery form. ·Montgomery reduction is all that is
e9e480 ·* needed.
b6495d ·*/
f0314a void
87e70f bniFromMont_64(BNWORD64 *n, BNWORD64 *mod, unsigned len)
6dbb36 {
103595 ¤   /* Zero the high words of n */
0cc42b ¤   bniZero_64(BIGLITTLE(n-len,n+len), len);
e13825 ¤   bniMontReduce_64(n, mod, len, bniMontInv1_64(mod[BIGLITTLE(-1,0)]));
ea9c58 ¤   /* Move n down len words */
46d4b0 ¤   bniCopy_64(n, BIGLITTLE(n-len,n+len), len);
91efe6 }
fdaf5a
fa38e5 /*
1bd039 ·* The windowed exponentiation algorithm, precomputes a table of odd
58176f ·* powers of n up to 2^k. ·See the comment in bnExpMod_64 below for
bbc2ff ·* an explanation of how it actually works works.
e9775e ·*
63a488 ·* It takes 2^(k-1)-1 multiplies to compute the table, and (e-1)/(k+1)
99e229 ·* multiplies (on average) to perform the exponentiation. ·To minimize
ede12a ·* the sum, k must vary with e. ·The optimal window sizes vary with the
e406bb ·* exponent length. ·Here are some selected values and the boundary cases.
0544f4 ·* (An underscore _ has been inserted into some of the numbers to ensure
5b988b ·* that magic strings like 64 do not appear in this table. ·It should be
600710 ·* ignored.)
ab775e ·*
0d05dd ·* At e = ···1 bits, k=1 ··(0.000000) is best
45630a ·* At e = ···2 bits, k=1 ··(0.500000) is best
0512b6 ·* At e = ···4 bits, k=1 ··(1.500000) is best
63a6b8 ·* At e = ···8 bits, k=2 ··(3.333333) < k=1 ··(3.500000)
6e5942 ·* At e = ·1_6 bits, k=2 ··(6.000000) is best
d90761 ·* At e = ··26 bits, k=3 ··(9.250000) < k=2 ··(9.333333)
f6d0cf ·* At e = ·3_2 bits, k=3 ·(10.750000) is best
cf9f06 ·* At e = ·6_4 bits, k=3 ·(18.750000) is best
fa1f23 ·* At e = ··82 bits, k=4 ·(23.200000) < k=3 ·(23.250000)
b9030f ·* At e = ·128 bits, k=4 (3_2.400000) is best
26fff6 ·* At e = ·242 bits, k=5 ·(55.1_66667) < k=4 (55.200000)
fbabb3 ·* At e = ·256 bits, k=5 ·(57.500000) is best
0ecd12 ·* At e = ·512 bits, k=5 (100.1_66667) is best
2e03f9 ·* At e = ·674 bits, k=6 (127.142857) < k=5 (127.1_66667)
470d7b ·* At e = 1024 bits, k=6 (177.142857) is best
f6730e ·* At e = 1794 bits, k=7 (287.125000) < k=6 (287.142857)
c3356a ·* At e = 2048 bits, k=7 (318.875000) is best
9b7a5b ·* At e = 4096 bits, k=7 (574.875000) is best
08775e ·*
cf0ef9 ·* The numbers in parentheses are the expected number of multiplications
a5471f ·* needed to do the computation. ·The normal russian-peasant modular
5a47b0 ·* exponentiation technique always uses (e-1)/2. ·For exponents as
abd6ec ·* small as 192 bits (below the range of current factoring algorithms),
ef7212 ·* half of the multiplies are eliminated, 45.2 as opposed to the naive
dd26b5 ·* 95.5. ·Counting the 191 squarings as 3/4 a multiply each (squaring
546545 ·* proper is just over half of multiplying, but the Montgomery
72de2c ·* reduction in each case is also a multiply), that's 143.25
bd992d ·* multiplies, for totals of 188.45 vs. 238.75 - a 21% savings.
33e86b ·* For larger exponents (like 512 bits), it's 483.92 vs. 639.25, a
218afb ·* 24.3% savings. ·It asymptotically approaches 25%.
3d775e ·*
78f291 ·* Um, actually there's a slightly more accurate way to count, which
10e881 ·* really is the average number of multiplies required, averaged
9f0fb0 ·* uniformly over all 2^(e-1) e-bit numbers, from 2^(e-1) to (2^e)-1.
e1bbff ·* It's based on the recurrence that for the last b bits, b <= k, at
644553 ·* most one multiply is needed (and none at all 1/2^b of the time),
a4acfb ·* while when b > k, the odds are 1/2 each way that the bit will be
455519 ·* 0 (meaning no multiplies to reduce it to the b-1-bit case) and
43dff6 ·* 1/2 that the bit will be 1, starting a k-bit window and requiring
2818fe ·* 1 multiply beyond the b-k-bit case. ·Since the most significant
2741f6 ·* bit is always 1, a k-bit window always starts there, and that
490a4c ·* multiply is by 1, so it isn't a multiply at all. ·Thus, the
cac456 ·* number of multiplies is simply that needed for the last e-k bits.
ed52be ·* This recurrence produces:
de775e ·*
--1ef5 000ed186bd840100154 Page 31 of bni64.c
1605dd ·* At e = ···1 bits, k=1 ··(0.000000) is best
54630a ·* At e = ···2 bits, k=1 ··(0.500000) is best
e212b6 ·* At e = ···4 bits, k=1 ··(1.500000) is best
b55c43 ·* At e = ···6 bits, k=2 ··(2.437500) < k=1 ··(2.500000)
065dc4 ·* At e = ···8 bits, k=2 ··(3.109375) is best
2ba533 ·* At e = ·1_6 bits, k=2 ··(5.777771) is best
5a323f ·* At e = ··24 bits, k=3 ··(8.437629) < k=2 ··(8.444444)
c4b0ab ·* At e = ·3_2 bits, k=3 ·(10.437492) is best
46de54 ·* At e = ·6_4 bits, k=3 ·(18.437500) is best
0a9d65 ·* At e = ··81 bits, k=4 ·(22.6_40000) < k=3 ·(22.687500)
fb03d4 ·* At e = ·128 bits, k=4 (3_2.040000) is best
0323e8 ·* At e = ·241 bits, k=5 ·(54.611111) < k=4 ·(54.6_40000)
2d6078 ·* At e = ·256 bits, k=5 ·(57.111111) is best
5666d1 ·* At e = ·512 bits, k=5 ·(99.777778) is best
8423ae ·* At e = ·673 bits, k=6 (126.591837) < k=5 (126.611111)
45f6ca ·* At e = 1024 bits, k=6 (176.734694) is best
de8b19 ·* At e = 1793 bits, k=7 (286.578125) < k=6 (286.591837)
fadf27 ·* At e = 2048 bits, k=7 (318.453125) is best
7c9016 ·* At e = 4096 bits, k=7 (574.453125) is best
4c775e ·*
8071f5 ·* This has the rollover points at 6, 24, 81, 241, 673 and 1793 instead
0471d9 ·* of 8, 26, 82, 242, 674, and 1794. ·Not a very big difference.
17480f ·* (The numbers past that are k=8 at 4609 and k=9 at 11521,
08e3af ·* vs. one more in each case for the approximation.)
e4775e ·*
f2cd4d ·* Given that exponents for which k>7 are useful are uncommon,
c0986b ·* a fixed size table for k <= 7 is used for simplicity.
c3775e ·*
e63a91 ·* The basic number of squarings needed is e-1, although a k-bit
778550 ·* window (for k > 1) can save, on average, k-2 of those, too.
22a714 ·* That savings currently isn't counted here. ·It would drive the
94b9c9 ·* crossover points slightly lower.
a42fb9 ·* (Actually, this win is also reduced in the DoubleExpMod case,
1d73fc ·* meaning we'd have to split the tables. ·Except for that, the
b12115 ·* multiplies by powers of the two bases are independent, so
d57584 ·* the same logic applies to each as the single case.)
9d775e ·*
5bda92 ·* Table entry i is the largest number of bits in an exponent to
073c5d ·* process with a window size of i+1. ·Entry 6 is the largest
b13c90 ·* possible unsigned number, so the window will never be more
ac9487 ·* than 7 bits, requiring 2^6 = 0x40 slots.
2d495d ·*/
5c6cca #define BNEXPMOD_MAX_WINDOW¤7
f54fb9 static unsigned const bnExpModThreshTable[BNEXPMOD_MAX_WINDOW] = {
3d193c ¤   5, 23, 80, 240, 672, 1792, (unsigned)-1
c06504 /*¤ 7, 25, 81, 241, 673, 1793, (unsigned)-1¤ ### The old approximations */
1a82f7 };
02af5a
8938e5 /*
a51b1f ·* Perform modular exponentiation, as fast as possible! ·This uses
913ed2 ·* Montgomery reduction, optimized squaring, and windowed exponentiation.
c9aef1 ·* The modulus "mod" MUST be odd!
42775e ·*
c9669b ·* This returns 0 on success, -1 on out of memory.
18775e ·*
49a91b ·* The window algorithm:
0e34dc ·* The idea is to keep a running product of b1 = n^(high-order bits of exp),
514327 ·* and then keep appending exponent bits to it. ·The following patterns
cc1e2d ·* apply to a 3-bit window (k = 3):
8e57f4 ·* To append ··0: square
df17eb ·* To append ··1: square, multiply by n^1
591993 ·* To append ·10: square, multiply by n^1, square
f660d5 ·* To append ·11: square, square, multiply by n^3
8cb4bd ·* To append 100: square, multiply by n^1, square, square
1be469 ·* To append 101: square, square, square, multiply by n^5
10730b ·* To append 110: square, square, multiply by n^3, square
a6579e ·* To append 111: square, square, square, multiply by n^7
2f775e ·*
c49b90 ·* Since each pattern involves only one multiply, the longer the pattern
5c325f ·* the better, except that a 0 (no multiplies) can be appended directly.
b2f945 ·* We precompute a table of odd powers of n, up to 2^k, and can then
ede7a3 ·* multiply k bits of exponent at a time. ·Actually, assuming random
--64a6 0003afd8cb440100154 Page 32 of bni64.c
c5ab25 ·* exponents, there is on average one zero bit between needs to
9ec44d ·* multiply (1/2 of the time there's none, 1/4 of the time there's 1,
e15f57 ·* 1/8 of the time, there's 2, 1/64 of the time, there's 3, etc.), so
bc5e90 ·* you have to do one multiply per k+1 bits of exponent.
66775e ·*
976a37 ·* The loop walks down the exponent, squaring the result buffer as
7bbb92 ·* it goes. ·There is a wbits+1 bit lookahead buffer, buf, that is
596a38 ·* filled with the upcoming exponent bits. ·(What is read after the
b2a4bc ·* end of the exponent is unimportant, but it is filled with zero here.)
9d8f68 ·* When the most-significant bit of this buffer becomes set, i.e.
04089f ·* (buf & tblmask) != 0, we have to decide what pattern to multiply
ce5ee7 ·* by, and when to do it. ·We decide, remember to do it in future
ef1e5d ·* after a suitable number of squarings have passed (e.g. a pattern
fa7b40 ·* of "100" in the buffer requires that we multiply by n^1 immediately;
bc7f6e ·* a pattern of "110" calls for multiplying by n^3 after one more
60221f ·* squaring), clear the buffer, and continue.
12775e ·*
41fbc2 ·* When we start, there is one more optimization: the result buffer
7b4fad ·* is implcitly one, so squaring it or multiplying by it can be
c98e8b ·* optimized away. ·Further, if we start with a pattern like "100"
c9d51f ·* in the lookahead window, rather than placing n into the buffer
4fda03 ·* and then starting to square it, we have already computed n^2
9f58ee ·* to compute the odd-powers table, so we can place that into
e932c1 ·* the buffer and save a squaring.
33775e ·*
1beb27 ·* This means that if you have a k-bit window, to compute n^z,
3dde80 ·* where z is the high k bits of the exponent, 1/2 of the time
334c51 ·* it requires no squarings. ·1/4 of the time, it requires 1
7fb370 ·* squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
45a8af ·* And the remaining 1/2^(k-1) of the time, the top k bits are a
4c8321 ·* 1 followed by k-1 0 bits, so it again only requires k-2
3a3eec ·* squarings, not k-1. ·The average of these is 1. ·Add that
735ba0 ·* to the one squaring we have to do to compute the table,
b34f92 ·* and you'll see that a k-bit window saves k-2 squarings
d38b94 ·* as well as reducing the multiplies. ·(It actually doesn't
7f85e2 ·* hurt in the case k = 1, either.)
81775e ·*
aea837 ·* n must have mlen words allocated. ·Although fewer may be in use
8cd9fa ·* when n is passed in, all are in use on exit.
ab495d ·*/
0e4d2f int
5f2a70 bniExpMod_64(
816740 ¤   PGPMemoryMgrRef¤mgr,
fbfe55 ¤   PGPBoolean¤ ¤   secure,
e09883 ¤   BNWORD64 *result, BNWORD64 const *n, unsigned nlen,
a55a89 ¤   BNWORD64 const *e, unsigned elen, BNWORD64 *mod, unsigned mlen)
15bb36 {
e4d083 ¤   BNWORD64 *table[1 << (BNEXPMOD_MAX_WINDOW-1)];
9eab6c ¤   ¤   ¤   ¤   /* Table of odd powers of n */
fbbbb1 ¤   unsigned ebits;¤¤   /* Exponent bits */
a78abd ¤   unsigned wbits;¤¤   /* Window size */
4b4710 ¤   unsigned tblmask;¤  /* Mask of exponentiation window */
d84427 ¤   BNWORD64 bitpos;¤   /* Mask of current look-ahead bit */
c8a550 ¤   unsigned buf;¤  ¤   /* Buffer of exponent bits */
7ca4db ¤   unsigned multpos;¤  /* Where to do pending multiply */
f2f026 ¤   BNWORD64 const *mult;¤  /* What to multiply by */
317dbe ¤   unsigned i;¤¤   /* Loop counter */
392054 ¤   int isone;¤ ¤   /* Flag: accum. is implicitly one */
a7c233 ¤   BNWORD64 *a, *b;¤   /* Working buffers/accumulators */
595752 ¤   BNWORD64 *t;¤   ¤   /* Pointer into the working buffers */
071b01 ¤   BNWORD64 inv;¤  ¤   /* mod^-1 modulo 2^64 */
c4de2a ¤   int y;¤ ¤   ¤   /* bnYield() result */
93af5a
4ec613 ¤   pgpAssert(mlen);
a084ca ¤   pgpAssert(nlen <= mlen);
36af5a
487d28 ¤   /* First, a couple of trivial cases. */
328785 ¤   elen = bniNorm_64(e, elen);
246115 ¤   if (!elen) {
6d18ff ¤   ¤   /* x ^ 0 == 1 */
bc915a ¤   ¤   bniZero_64(result, mlen);
3a0eac ¤   ¤   BIGLITTLE(result[-1],result[0]) = 1;
--119e 0009807081540100154 Page 33 of bni64.c
79bbde ¤   ¤   return 0;
a69371 ¤   }
8f8f83 ¤   ebits = bniBits_64(e, elen);
7acd76 ¤   if (ebits == 1) {
7aa49e ¤   ¤   /* x ^ 1 == x */
68295d ¤   ¤   if (n != result)
0f51db ¤   ¤   ¤   bniCopy_64(result, n, nlen);
ecefb1 ¤   ¤   if (mlen > nlen)
72c893 ¤   ¤   ¤   bniZero_64(BIGLITTLE(result-nlen,result+nlen),
23ab83 ¤   ¤   ¤   ···········mlen-nlen);
4bbbde ¤   ¤   return 0;
e99371 ¤   }
6baf5a
cc0565 ¤   /* Okay, now move the exponent pointer to the most-significant word */
60eb85 ¤   e = BIGLITTLE(e-elen, e+elen-1);
3eaf5a
7b5f70 ¤   /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
3be796 ¤   wbits = 0;
e33dd6 ¤   while (ebits > bnExpModThreshTable[wbits])
16ca4f ¤   ¤   wbits++;
fcaf5a
75b29c ¤   /* Allocate working storage: two product buffers and the tables. */
c2e662 ¤   BNIALLOC(mgr, secure, a, BNWORD64, 2*mlen);
399293 ¤   if (!a)
40043c ¤   ¤   return -1;
201594 ¤   BNIALLOC(mgr, secure, b, BNWORD64, 2*mlen);
2f5215 ¤   if (!b) {
eadda3 ¤   ¤   BNIFREE(a, 2*mlen);
e6043c ¤   ¤   return -1;
a39371 ¤   }
c4af5a
bceb94 ¤   /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
677b5d ¤   tblmask = 1u << wbits;
4caf5a
aaa19d ¤   /* We have the result buffer available, so use it. */
eab9d5 ¤   table[0] = result;
b9af5a
66d8af ¤   /*
19a077 ¤   ·* Okay, we now have a minimal-sized table - expand it.
e3951f ¤   ·* This is allowed to fail! ·If so, scale back the table size
94e64a ¤   ·* and proceed.
fca4e3 ¤   ·*/
10623b ¤   for (i = 1; i < tblmask; i++) {
4ea2d7 ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD64, mlen);
76f4e7 ¤   ¤   if (!t)¤/* Out of memory! ·Quit the loop. */
cacdcb ¤   ¤   ¤   break;
a45264 ¤   ¤   table[i] = t;
119371 ¤   }
d4af5a
39e399 ¤   /* If we stopped, with i < tblmask, shrink the tables appropriately */
2f0729 ¤   while (tblmask > i) {
73570c ¤   ¤   wbits--;
c8020b ¤   ¤   tblmask >>= 1;
069371 ¤   }
5e90d4 ¤   /* Free up our overallocations */
e68b01 ¤   while (--i > tblmask)
8506fb ¤   ¤   BNIFREE(table[i], mlen);
f5af5a
22523f ¤   /* Okay, fill in the table */
14af5a
e16326 ¤   /* Compute the necessary modular inverse */
e97cd2 ¤   inv = bniMontInv1_64(mod[BIGLITTLE(-1,0)]);¤/* LSW of modulus */
14af5a
8bd2c8 ¤   /* Convert n to Montgomery form */
8faf5a
8c45b9 ¤   /* Move n up "mlen" words into a */
28c360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
58fa8f ¤   bniCopy_64(t, n, nlen);
5d38a4 ¤   bniZero_64(a, mlen);
fba0ad ¤   /* Do the division - lose the quotient into the high-order words */
b39e3e ¤   (void)bniDiv_64(t, a, mlen+nlen, mod, mlen);
98aa1a ¤   /* Copy into first table entry */
--7354 000677ff07740100154 Page 34 of bni64.c
eec67f ¤   bniCopy_64(table[0], a, mlen);
85af5a
40c9f6 ¤   /* Square a into b */
72fc0f ¤   bniMontSquare_64(b, a, mod, mlen, inv);
7faf5a
f20127 ¤   /* Use high half of b to initialize the table */
af2576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
37623b ¤   for (i = 1; i < tblmask; i++) {
d93e00 ¤   ¤   bniMontMul_64(a, t, table[i-1], mod, mlen, inv);
cff752 ¤   ¤   bniCopy_64(table[i], BIGLITTLE(a-mlen, a+mlen), mlen);
37074b #if BNYIELD
619bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
6b74c2 ¤   ¤   ¤   goto yield;
ba7454 #endif
1c9371 ¤   }
7faf5a
b6e133 ¤   /* We might use b = n^2 later... */
17af5a
d3b3c9 ¤   /* Initialze the fetch pointer */
08374f ¤   bitpos = (BNWORD64)1 << ((ebits-1) & (64-1));¤  /* Initialize mask */
cfaf5a
ce41cc ¤   /* This should point to the msbit of e */
bafda7 ¤   pgpAssert((*e & bitpos) != 0);
d4af5a
2ad8af ¤   /*
36f61f ¤   ·* Pre-load the window. ·Becuase the window size is
839e1e ¤   ·* never larger than the exponent size, there is no need to
7654af ¤   ·* detect running off the end of e in here.
df9714 ¤   ·*
8c8d24 ¤   ·* The read-ahead is controlled by elen and the bitpos mask.
2fc658 ¤   ·* Note that this is *ahead* of ebits, which tracks the
7fe8fd ¤   ·* most significant end of the window. ·The purpose of this
04cbf3 ¤   ·* initialization is to get the two wbits+1 bits apart,
a6d4d6 ¤   ·* like they should be.
979714 ¤   ·*
bf9955 ¤   ·* Note that bitpos and e1len together keep track of the
a37e30 ¤   ·* lookahead read pointer in the exponent that is used here.
84a4e3 ¤   ·*/
2ab0a1 ¤   buf = 0;
b25760 ¤   for (i = 0; i <= wbits; i++) {
486d2d ¤   ¤   buf = (buf << 1) | ((*e & bitpos) != 0);
211e4d ¤   ¤   bitpos >>= 1;
1ea81f ¤   ¤   if (!bitpos) {
260024 ¤   ¤   ¤   BIGLITTLE(e++,e--);
fc1c94 ¤   ¤   ¤   bitpos = (BNWORD64)1 << (64-1);
ebb349 ¤   ¤   ¤   elen--;
e50fe4 ¤   ¤   }
d99371 ¤   }
d05e84 ¤   pgpAssert(buf & tblmask);
5eaf5a
01d8af ¤   /*
2ae4af ¤   ·* Set the pending multiply positions to a location that will
6d3edd ¤   ·* never be encountered, thus ensuring that nothing will happen
9d5986 ¤   ·* until the need for a multiply appears and one is scheduled.
e3a4e3 ¤   ·*/
cdbd01 ¤   multpos = ebits;¤   /* A NULL value */
c5077f ¤   mult = 0;¤  /* Force a crash if we use these */
c9af5a
5fd8af ¤   /*
2011db ¤   ·* Okay, now begins the real work. ·The first step is
f3c478 ¤   ·* slightly magic, so it's done outside the main loop,
553e1f ¤   ·* but it's very similar to what's inside.
63a4e3 ¤   ·*/
d2806b ¤   ebits--;¤   /* Start processing the first bit... */
f94f17 ¤   isone = 1;
21af5a
5cd8af ¤   /*
d49907 ¤   ·* This is just like the multiply in the loop, except that
d01487 ¤   ·* - We know the msbit of buf is set, and
2c56cd ¤   ·* - We have the extra value n^2 floating around.
6963fa ¤   ·* So, do the usual computation, and if the result is that
676045 ¤   ·* the buffer should be multiplied by n^1 immediately
--c745 00048646c7740100154 Page 35 of bni64.c
83cce3 ¤   ·* (which we'd normally then square), we multiply it
289fa4 ¤   ·* (which reduces to a copy, which reduces to setting a flag)
a0c34f ¤   ·* by n^2 and skip the squaring. ·Thus, we do the
475501 ¤   ·* multiply and the squaring in one step.
83a4e3 ¤   ·*/
2b5e84 ¤   pgpAssert(buf & tblmask);
634e35 ¤   multpos = ebits - wbits;
308da4 ¤   while ((buf & 1) == 0) {
031feb ¤   ¤   buf >>= 1;
c45ccd ¤   ¤   multpos++;
ab9371 ¤   }
e1f0a6 ¤   /* Intermediates can wrap, but final must NOT */
3d28d7 ¤   pgpAssert(multpos <= ebits);
0e43c6 ¤   mult = table[buf>>1];
23b0a1 ¤   buf = 0;
33af5a
3fb24e ¤   /* Special case: use already-computed value sitting in buffer */
26b774 ¤   if (multpos == ebits)
2bf768 ¤   ¤   isone = 0;
e4af5a
85d8af ¤   /*
2bfe43 ¤   ·* At this point, the buffer (which is the high half of b) holds
3d61cd ¤   ·* either 1 (implicitly, as the "isone" flag is set), or n^2.
a6a4e3 ¤   ·*/
83af5a
19d8af ¤   /*
ea9409 ¤   ·* The main loop. ·The procedure is:
f0ab45 ¤   ·* - Advance the window
e3448c ¤   ·* - If the most-significant bit of the window is set,
9c0c66 ¤   ·* ··schedule a multiply for the appropriate time in the
56375c ¤   ·* ··future (may be immediately)
9e383a ¤   ·* - Perform any pending multiples
a06d15 ¤   ·* - Check for termination
43446f ¤   ·* - Square the buffer
da9714 ¤   ·*
247202 ¤   ·* At any given time, the acumulated product is held in
2d0d21 ¤   ·* the high half of b.
f9a4e3 ¤   ·*/
5f220e ¤   for (;;) {
653362 ¤   ¤   ebits--;
62af5a
711a36 ¤   ¤   /* Advance the window */
ea7403 ¤   ¤   pgpAssert(buf < tblmask);
5b2006 ¤   ¤   buf <<= 1;
bc1b17 ¤   ¤   /*
eee0cb ¤   ¤   ·* This reads ahead of the current exponent position
cc43d1 ¤   ¤   ·* (controlled by ebits), so we have to be able to read
54969f ¤   ¤   ·* past the lsb of the exponents without error.
a99de3 ¤   ¤   ·*/
524c6b ¤   ¤   if (elen) {
2a81dc ¤   ¤   ¤   buf |= ((*e & bitpos) != 0);
fbd9f8 ¤   ¤   ¤   bitpos >>= 1;
0d4afe ¤   ¤   ¤   if (!bitpos) {
ea8bd8 ¤   ¤   ¤   ¤   BIGLITTLE(e++,e--);
ad04c4 ¤   ¤   ¤   ¤   bitpos = (BNWORD64)1 << (64-1);
28c9bd ¤   ¤   ¤   ¤   elen--;
fda3a6 ¤   ¤   ¤   }
f70fe4 ¤   ¤   }
6baf5a
a6be07 ¤   ¤   /* Examine the window for pending multiplies */
5acc0d ¤   ¤   if (buf & tblmask) {
37c80b ¤   ¤   ¤   multpos = ebits - wbits;
7d0b9a ¤   ¤   ¤   while ((buf & 1) == 0) {
17c6e3 ¤   ¤   ¤   ¤   buf >>= 1;
8f85c5 ¤   ¤   ¤   ¤   multpos++;
40a3a6 ¤   ¤   ¤   }
e3b920 ¤   ¤   ¤   /* Intermediates can wrap, but final must NOT */
cb1052 ¤   ¤   ¤   pgpAssert(multpos <= ebits);
33fd9a ¤   ¤   ¤   mult = table[buf>>1];
9544bb ¤   ¤   ¤   buf = 0;
d60fe4 ¤   ¤   }
48af5a
--951b 000acae443240100154 Page 36 of bni64.c
0357bb ¤   ¤   /* If we have a pending multiply, do it */
d2d05a ¤   ¤   if (ebits == multpos) {
41a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
296ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
578c88 ¤   ¤   ¤   if (isone) {
f26b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
9c3cc6 ¤   ¤   ¤   ¤   bniCopy_64(t, mult, mlen);
852e60 ¤   ¤   ¤   ¤   isone = 0;
7b042d ¤   ¤   ¤   } else {
3903a6 ¤   ¤   ¤   ¤   bniMontMul_64(a, t, mult, mod, mlen, inv);
2d6783 ¤   ¤   ¤   ¤   /* Swap a and b */
7c51ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
c1a3a6 ¤   ¤   ¤   }
c20fe4 ¤   ¤   }
0daf5a
547b03 ¤   ¤   /* Are we done? */
278029 ¤   ¤   if (!ebits)
8ecdcb ¤   ¤   ¤   break;
9aaf5a
60b085 ¤   ¤   /* Square the input */
509d17 ¤   ¤   if (!isone) {
816ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
7cc7d4 ¤   ¤   ¤   bniMontSquare_64(a, t, mod, mlen, inv);
a6ebfc ¤   ¤   ¤   /* Swap a and b */
d76c84 ¤   ¤   ¤   t = a; a = b; b = t;
f80fe4 ¤   ¤   }
7f074b #if BNYIELD
869bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
3474c2 ¤   ¤   ¤   goto yield;
047454 #endif
1fd6a0 ¤   } /* for (;;) */
27af5a
f15f64 ¤   pgpAssert(!isone);
0bd8b5 ¤   pgpAssert(!buf);
30af5a
f42111 ¤   /* DONE! */
45af5a
c98619 ¤   /* Convert result out of Montgomery form */
5b2576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
68f6ea ¤   bniCopy_64(b, t, mlen);
35764d ¤   bniZero_64(t, mlen);
72d338 ¤   bniMontReduce_64(b, mod, mlen, inv);
6c2205 ¤   bniCopy_64(result, t, mlen);
10d8af ¤   /*
998c1b ¤   ·* Clean up - free intermediate storage.
1849dc ¤   ·* Do NOT free table[0], which is the result
7f4228 ¤   ·* buffer.
35a4e3 ¤   ·*/
b74aa5 ¤   y = 0;
eb074b #if BNYIELD
a6f924 yield:
d07454 #endif
5ff0a6 ¤   while (--tblmask)
7dd094 ¤   ¤   BNIFREE(table[tblmask], mlen);
ddac28 ¤   BNIFREE(b, 2*mlen);
482bc6 ¤   BNIFREE(a, 2*mlen);
efaf5a
43f88b ¤   return y;¤  /* Success */
acefe6 }
24af5a
4b38e5 /*
215706 ·* Compute and return n1^e1 * n2^e2 mod "mod".
d3c894 ·* result may be either input buffer, or something separate.
d48848 ·* It must be "mlen" words long.
a3775e ·*
dc9ebb ·* There is a current position in the exponents, which is kept in e1bits.
0e10c7 ·* (The exponents are swapped if necessary so e1 is the longer of the two.)
81916c ·* At any given time, the value in the accumulator is
50da55 ·* n1^(e1>>e1bits) * n2^(e2>>e1bits) mod "mod".
70a31f ·* As e1bits is counted down, this is updated, by squaring it and doing
c9b1ee ·* any necessary multiplies.
ac093b ·* To decide on the necessary multiplies, two windows, each w1bits+1 bits
--de4a 000402d05b440100154 Page 37 of bni64.c
da411e ·* wide, are maintained in buf1 and buf2, which read *ahead* of the
fe3a68 ·* e1bits position (with appropriate handling of the case when e1bits
10074b ·* drops below w1bits+1). ·When the most-significant bit of either window
febb09 ·* becomes set, indicating that something needs to be multiplied by
7600a5 ·* the accumulator or it will get out of sync, the window is examined
f8ab86 ·* to see which power of n1 or n2 to multiply by, and when (possibly
ab89e9 ·* later, if the power is greater than 1) the multiply should take
426e2e ·* place. ·Then the multiply and its location are remembered and the
18b3de ·* window is cleared.
98775e ·*
4d5ec4 ·* If we had every power of n1 in the table, the multiply would always
26f328 ·* be w1bits steps in the future. ·But we only keep the odd powers,
9552f8 ·* so instead of waiting w1bits squarings and then multiplying
e72d0c ·* by n1^k, we wait w1bits-k squarings and multiply by n1.
68775e ·*
cd6296 ·* Actually, w2bits can be less than w1bits, but the window is the same
f913ee ·* size, to make it easier to keep track of where we're reading. ·The
d80c46 ·* appropriate number of low-order bits of the window are just ignored.
6d495d ·*/
e44d2f int
e26c96 bniDoubleExpMod_64(
366740 ¤   PGPMemoryMgrRef¤mgr,
a1fe55 ¤   PGPBoolean¤ ¤   secure,
edce1b ¤   BNWORD64 *result,
c1d790 ···BNWORD64 const *n1, unsigned n1len,
72022f ···BNWORD64 const *e1, unsigned e1len,
cf6627 ···BNWORD64 const *n2, unsigned n2len,
18b398 ···BNWORD64 const *e2, unsigned e2len,
db8afe ···BNWORD64 *mod, unsigned mlen)
b1bb36 {
def12b ¤   BNWORD64 *table1[1 << (BNEXPMOD_MAX_WINDOW-1)];
869746 ¤   ¤   ¤   ¤   ¤   /* Table of odd powers of n1 */
b2318e ¤   BNWORD64 *table2[1 << (BNEXPMOD_MAX_WINDOW-1)];
9b8a8a ¤   ¤   ¤   ¤   ¤   /* Table of odd powers of n2 */
d1aaa4 ¤   unsigned e1bits, e2bits;¤   /* Exponent bits */
5b2c22 ¤   unsigned w1bits, w2bits;¤   /* Window sizes */
b7de31 ¤   unsigned tblmask;¤  ¤   /* Mask of exponentiation window */
adff6f ¤   BNWORD64 bitpos;¤   ¤   /* Mask of current look-ahead bit */
acf0f4 ¤   unsigned buf1, buf2;¤   ¤   /* Buffer of exponent bits */
28b874 ¤   unsigned mult1pos, mult2pos;¤   /* Where to do pending multiply */
445fb5 ¤   BNWORD64 const *mult1, *mult2;¤ /* What to multiply by */
a7e525 ¤   unsigned i;¤¤   ¤   /* Loop counter */
e1395c ¤   int isone;¤ ¤   ¤   /* Flag: accum. is implicitly one */
d0b7c7 ¤   BNWORD64 *a, *b;¤   ¤   /* Working buffers/accumulators */
3ec83e ¤   BNWORD64 *t;¤   ¤   ¤   /* Pointer into the working buffers */
b244df ¤   BNWORD64 inv;¤  ¤   ¤   /* mod^-1 modulo 2^64 */
d5916f ¤   int y;¤ ¤   ¤   ¤   /* bnYield() result */
7faf5a
74c613 ¤   pgpAssert(mlen);
4a9714 ¤   pgpAssert(n1len <= mlen);
2e4f6a ¤   pgpAssert(n2len <= mlen);
14af5a
e57d28 ¤   /* First, a couple of trivial cases. */
de1788 ¤   e1len = bniNorm_64(e1, e1len);
882040 ¤   e2len = bniNorm_64(e2, e2len);
23af5a
94c726 ¤   /* Ensure that the first exponent is the longer */
8e0dca ¤   e1bits = bniBits_64(e1, e1len);
8a1c5a ¤   e2bits = bniBits_64(e2, e2len);
46f8c6 ¤   if (e1bits < e2bits) {
91bd4e ¤   ¤   i = e1len; e1len = e2len; e2len = i;
f6d4ee ¤   ¤   i = e1bits; e1bits = e2bits; e2bits = i;
902eb0 ¤   ¤   t = (BNWORD64 *)n1; n1 = n2; n2 = t;·
e2cbde ¤   ¤   t = (BNWORD64 *)e1; e1 = e2; e2 = t;·
959371 ¤   }
ed9589 ¤   pgpAssert(e1bits >= e2bits);
a3af5a
8656ce ¤   /* Handle a trivial case */
b4d49f ¤   if (!e2len)
d715e4 ¤   ¤   return bniExpMod_64( mgr, secure, result, n1, n1len, e1, e1len,
518576 ¤   ¤   ¤   ¤   ¤   ¤   ¤   mod, mlen);
405d32 ¤   pgpAssert(e2bits);
--2254 000a3653b2640100154 Page 38 of bni64.c
e0af5a
fcfc05 ¤   /* The code below fucks up if the exponents aren't at least 2 bits */
f13f8f ¤   if (e1bits == 1) {
744cfc ¤   ¤   pgpAssert(e2bits == 1);
49af5a
3cc7d9 ¤   ¤   BNIALLOC(mgr, secure, a, BNWORD64, n1len+n2len);
328823 ¤   ¤   if (!a)
fe3fd5 ¤   ¤   ¤   return -1;
e1af5a
e627ab ¤   ¤   bniMul_64(a, n1, n1len, n2, n2len);
6e46cf ¤   ¤   /* Do a direct modular reduction */
ca016d ¤   ¤   if (n1len + n2len >= mlen)
52026c ¤   ¤   ¤   (void)bniDiv_64(a+mlen, a, n1len+n2len, mod, mlen);
c35184 ¤   ¤   bniCopy_64(result, a, mlen);
44643e ¤   ¤   BNIFREE(a, n1len+n2len);
14bbde ¤   ¤   return 0;
3f9371 ¤   }
29af5a
35aa9d ¤   /* Okay, now move the exponent pointers to the most-significant word */
ba10a1 ¤   e1 = BIGLITTLE(e1-e1len, e1+e1len-1);
a9c984 ¤   e2 = BIGLITTLE(e2-e2len, e2+e2len-1);
daaf5a
8f5f70 ¤   /* Look up appropriate k-1 for the exponent - tblmask = 1<<(k-1) */
114f7e ¤   w1bits = 0;
07997d ¤   while (e1bits > bnExpModThreshTable[w1bits])
baff05 ¤   ¤   w1bits++;
b3b1cd ¤   w2bits = 0;
9cd55d ¤   while (e2bits > bnExpModThreshTable[w2bits])
352902 ¤   ¤   w2bits++;
ecaf5a
27a36d ¤   pgpAssert(w1bits >= w2bits);
41af5a
1fb29c ¤   /* Allocate working storage: two product buffers and the tables. */
f5e662 ¤   BNIALLOC(mgr, secure, a, BNWORD64, 2*mlen);
e79293 ¤   if (!a)
f1043c ¤   ¤   return -1;
ed1594 ¤   BNIALLOC(mgr, secure, b, BNWORD64, 2*mlen);
f35215 ¤   if (!b) {
76dda3 ¤   ¤   BNIFREE(a, 2*mlen);
74043c ¤   ¤   return -1;
649371 ¤   }
b4af5a
1beb94 ¤   /* Convert to the appropriate table size: tblmask = 1<<(k-1) */
0a211e ¤   tblmask = 1u << w1bits;
68f1a9 ¤   /* Use buf2 for its size, temporarily */
54b274 ¤   buf2 = 1u << w2bits;
acaf5a
9bede9 ¤   BNIALLOC(mgr, secure, t, BNWORD64, mlen);
8dddcd ¤   if (!t) {
de5a4d ¤   ¤   BNIFREE(b, 2*mlen);
b4dda3 ¤   ¤   BNIFREE(a, 2*mlen);
3c043c ¤   ¤   return -1;
079371 ¤   }
ee4388 ¤   table1[0] = t;
5611c2 ¤   table2[0] = result;
abaf5a
b7d8af ¤   /*
e36773 ¤   ·* Okay, we now have some minimal-sized tables - expand them.
ee6065 ¤   ·* This is allowed to fail! ·If so, scale back the table sizes
db5a99 ¤   ·* and proceed. ·We allocate both tables at the same time
844729 ¤   ·* so if it fails partway through, they'll both be a reasonable
89e17e ¤   ·* size rather than one huge and one tiny.
249f45 ¤   ·* When i passes buf2 (the number of entries in the e2 window,
84278f ¤   ·* which may be less than the number of entries in the e1 window),
cf2758 ¤   ·* stop allocating e2 space.
7ba4e3 ¤   ·*/
01623b ¤   for (i = 1; i < tblmask; i++) {
a6a2d7 ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD64, mlen);
fdf4e7 ¤   ¤   if (!t)¤/* Out of memory! ·Quit the loop. */
b9cdcb ¤   ¤   ¤   break;
dfeaeb ¤   ¤   table1[i] = t;
a35687 ¤   ¤   if (i < buf2) {
--3bbc 0003728ea0440100154 Page 39 of bni64.c
a60cd6 ¤   ¤   ¤   BNIALLOC(mgr, secure, t, BNWORD64, mlen);
a862e2 ¤   ¤   ¤   if (!t) {
d68b24 ¤   ¤   ¤   ¤   BNIFREE(table1[i], mlen);
17f622 ¤   ¤   ¤   ¤   break;
caa3a6 ¤   ¤   ¤   }
8d7c63 ¤   ¤   ¤   table2[i] = t;
d90fe4 ¤   ¤   }
ab9371 ¤   }
e2af5a
63e399 ¤   /* If we stopped, with i < tblmask, shrink the tables appropriately */
4a0729 ¤   while (tblmask > i) {
656246 ¤   ¤   w1bits--;
c6020b ¤   ¤   tblmask >>= 1;
799371 ¤   }
bd90d4 ¤   /* Free up our overallocations */
37e874 ¤   while (--i > tblmask) {
fd8a30 ¤   ¤   if (i < buf2)
27b93d ¤   ¤   ¤   BNIFREE(table2[i], mlen);
4258b9 ¤   ¤   BNIFREE(table1[i], mlen);
9f9371 ¤   }
5f18ae ¤   /* And shrink the second window too, if needed */
61f5d4 ¤   if (w2bits > w1bits) {
b70726 ¤   ¤   w2bits = w1bits;
82356a ¤   ¤   buf2 = tblmask;
e79371 ¤   }
44af5a
9ed8af ¤   /*
d58b7f ¤   ·* From now on, use the w2bits variable for the difference
34f9d1 ¤   ·* between w1bits and w2bits.
00a4e3 ¤   ·*/
74c76a ¤   w2bits = w1bits-w2bits;
84af5a
d2b64a ¤   /* Okay, fill in the tables */
12af5a
776326 ¤   /* Compute the necessary modular inverse */
b47cd2 ¤   inv = bniMontInv1_64(mod[BIGLITTLE(-1,0)]);¤/* LSW of modulus */
d2af5a
e074f9 ¤   /* Convert n1 to Montgomery form */
2eaf5a
c4e328 ¤   /* Move n1 up "mlen" words into a */
5fc360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
537725 ¤   bniCopy_64(t, n1, n1len);
6438a4 ¤   bniZero_64(a, mlen);
02a0ad ¤   /* Do the division - lose the quotient into the high-order words */
976b48 ¤   (void)bniDiv_64(t, a, mlen+n1len, mod, mlen);
a3aa1a ¤   /* Copy into first table entry */
fa607e ¤   bniCopy_64(table1[0], a, mlen);
18af5a
92c9f6 ¤   /* Square a into b */
ecfc0f ¤   bniMontSquare_64(b, a, mod, mlen, inv);
56af5a
5b8028 ¤   /* Use high half of b to initialize the first table */
7b2576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
d1623b ¤   for (i = 1; i < tblmask; i++) {
ae5e15 ¤   ¤   bniMontMul_64(a, t, table1[i-1], mod, mlen, inv);
2f24ea ¤   ¤   bniCopy_64(table1[i], BIGLITTLE(a-mlen, a+mlen), mlen);
c9074b #if BNYIELD
2c9bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
ef74c2 ¤   ¤   ¤   goto yield;
9c7454 #endif
839371 ¤   }
1daf5a
a69935 ¤   /* Convert n2 to Montgomery form */
f6af5a
0fc360 ¤   t = BIGLITTLE(a-mlen, a+mlen);
e5b91b ¤   /* Move n2 up "mlen" words into a */
a321f8 ¤   bniCopy_64(t, n2, n2len);
d738a4 ¤   bniZero_64(a, mlen);
16a0ad ¤   /* Do the division - lose the quotient into the high-order words */
b86a70 ¤   (void)bniDiv_64(t, a, mlen+n2len, mod, mlen);
24aa1a ¤   /* Copy into first table entry */
37fa5f ¤   bniCopy_64(table2[0], a, mlen);
--6a54 00022657f8d40100154 Page 40 of bni64.c
e0af5a
98f67c ¤   /* Square it into a */
26c2fb ¤   bniMontSquare_64(a, table2[0], mod, mlen, inv);
018e9d ¤   /* Copy to b, low half */
3ff6ea ¤   bniCopy_64(b, t, mlen);
7baf5a
1cd1ec ¤   /* Use b to initialize the second table */
979f1b ¤   for (i = 1; i < buf2; i++) {
a1fdb7 ¤   ¤   bniMontMul_64(a, b, table2[i-1], mod, mlen, inv);
5a75d2 ¤   ¤   bniCopy_64(table2[i], t, mlen);
10074b #if BNYIELD
279bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
ec74c2 ¤   ¤   ¤   goto yield;
177454 #endif
fa9371 ¤   }
d2af5a
99d8af ¤   /*
62a7c8 ¤   ·* Okay, a recap: at this point, the low part of b holds
554f8a ¤   ·* n2^2, the high part holds n1^2, and the tables are
6db069 ¤   ·* initialized with the odd powers of n1 and n2 from 1
b14e6c ¤   ·* through 2*tblmask-1 and 2*buf2-1.
e79714 ¤   ·*
9eeaa9 ¤   ·* We might use those squares in b later, or we might not.
4ba4e3 ¤   ·*/
1eaf5a
deb3c9 ¤   /* Initialze the fetch pointer */
33d4e1 ¤   bitpos = (BNWORD64)1 << ((e1bits-1) & (64-1));¤ /* Initialize mask */
0daf5a
d7a4e7 ¤   /* This should point to the msbit of e1 */
a23755 ¤   pgpAssert((*e1 & bitpos) != 0);
90af5a
d0d8af ¤   /*
8092f4 ¤   ·* Pre-load the windows. ·Becuase the window size is
1d9e1e ¤   ·* never larger than the exponent size, there is no need to
8c29e6 ¤   ·* detect running off the end of e1 in here.
8d9714 ¤   ·*
706575 ¤   ·* The read-ahead is controlled by e1len and the bitpos mask.
29b24e ¤   ·* Note that this is *ahead* of e1bits, which tracks the
8de8fd ¤   ·* most significant end of the window. ·The purpose of this
ae59ed ¤   ·* initialization is to get the two w1bits+1 bits apart,
76d4d6 ¤   ·* like they should be.
5b9714 ¤   ·*
7b9955 ¤   ·* Note that bitpos and e1len together keep track of the
d87e30 ¤   ·* lookahead read pointer in the exponent that is used here.
740acb ¤   ·* e2len is not decremented, it is only ever compared with
379c64 ¤   ·* e1len as *that* is decremented.
26a4e3 ¤   ·*/
0fc6dc ¤   buf1 = buf2 = 0;
273d15 ¤   for (i = 0; i <= w1bits; i++) {
28c5f3 ¤   ¤   buf1 = (buf1 << 1) | ((*e1 & bitpos) != 0);
d75b2e ¤   ¤   if (e1len <= e2len)
8f4658 ¤   ¤   ¤   buf2 = (buf2 << 1) | ((*e2 & bitpos) != 0);
931e4d ¤   ¤   bitpos >>= 1;
a6a81f ¤   ¤   if (!bitpos) {
fcdc04 ¤   ¤   ¤   BIGLITTLE(e1++,e1--);
93f670 ¤   ¤   ¤   if (e1len <= e2len)
6bc1b9 ¤   ¤   ¤   ¤   BIGLITTLE(e2++,e2--);
011c94 ¤   ¤   ¤   bitpos = (BNWORD64)1 << (64-1);
d4b8bc ¤   ¤   ¤   e1len--;
ab0fe4 ¤   ¤   }
1d9371 ¤   }
bbf843 ¤   pgpAssert(buf1 & tblmask);
51af5a
8bd8af ¤   /*
f4e4af ¤   ·* Set the pending multiply positions to a location that will
fa3edd ¤   ·* never be encountered, thus ensuring that nothing will happen
575986 ¤   ·* until the need for a multiply appears and one is scheduled.
ffa4e3 ¤   ·*/
449c90 ¤   mult1pos = mult2pos = e1bits;¤  /* A NULL value */
2a0cc3 ¤   mult1 = mult2 = 0;¤ /* Force a crash if we use these */
3faf5a
22d8af ¤   /*
--f222 000b04f9d6140100154 Page 41 of bni64.c
5211db ¤   ·* Okay, now begins the real work. ·The first step is
ecc478 ¤   ·* slightly magic, so it's done outside the main loop,
bd3e1f ¤   ·* but it's very similar to what's inside.
67a4e3 ¤   ·*/
08f44f ¤   isone = 1;¤ /* Buffer is implicitly 1, so replace * by copy */
8ca246 ¤   e1bits--;¤  /* Start processing the first bit... */
c8af5a
58d8af ¤   /*
e09907 ¤   ·* This is just like the multiply in the loop, except that
cbfc57 ¤   ·* - We know the msbit of buf1 is set, and
2a05dd ¤   ·* - We have the extra value n1^2 floating around.
4663fa ¤   ·* So, do the usual computation, and if the result is that
fd2227 ¤   ·* the buffer should be multiplied by n1^1 immediately
81cce3 ¤   ·* (which we'd normally then square), we multiply it
d69fa4 ¤   ·* (which reduces to a copy, which reduces to setting a flag)
48b99d ¤   ·* by n1^2 and skip the squaring. ·Thus, we do the
4e5501 ¤   ·* multiply and the squaring in one step.
40a4e3 ¤   ·*/
46f843 ¤   pgpAssert(buf1 & tblmask);
fe8464 ¤   mult1pos = e1bits - w1bits;
8bd9b6 ¤   while ((buf1 & 1) == 0) {
46e8d7 ¤   ¤   buf1 >>= 1;
fa8c75 ¤   ¤   mult1pos++;
519371 ¤   }
60f0a6 ¤   /* Intermediates can wrap, but final must NOT */
837afd ¤   pgpAssert(mult1pos <= e1bits);
988447 ¤   mult1 = table1[buf1>>1];
64cb53 ¤   buf1 = 0;
12af5a
adb24e ¤   /* Special case: use already-computed value sitting in buffer */
1317a5 ¤   if (mult1pos == e1bits)
f5f768 ¤   ¤   isone = 0;
5aaf5a
9ad8af ¤   /*
d273de ¤   ·* The first multiply by a power of n2. ·Similar, but
26d0bc ¤   ·* we might not even want to schedule a multiply if e2 is
58719d ¤   ·* shorter than e1, and the window might be shorter so
c0207e ¤   ·* we have to leave the low w2bits bits alone.
aea4e3 ¤   ·*/
f46486 ¤   if (buf2 & tblmask) {
c58236 ¤   ¤   /* Remember low-order bits for later */
2ca24c ¤   ¤   i = buf2 & ((1u << w2bits) - 1);
d4c885 ¤   ¤   buf2 >>= w2bits;
8d419a ¤   ¤   mult2pos = e1bits - w1bits + w2bits;
7a36c0 ¤   ¤   while ((buf2 & 1) == 0) {
454424 ¤   ¤   ¤   buf2 >>= 1;
ab7c51 ¤   ¤   ¤   mult2pos++;
740fe4 ¤   ¤   }
590b1f ¤   ¤   pgpAssert(mult2pos <= e1bits);
1f4925 ¤   ¤   mult2 = table2[buf2>>1];
4cf975 ¤   ¤   buf2 = i;
b8af5a
50483e ¤   ¤   if (mult2pos == e1bits) {
f16ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
b38c88 ¤   ¤   ¤   if (isone) {
0dca51 ¤   ¤   ¤   ¤   bniCopy_64(t, b, mlen);¤/* Copy low to high */
e02e60 ¤   ¤   ¤   ¤   isone = 0;
77042d ¤   ¤   ¤   } else {
38fb9f ¤   ¤   ¤   ¤   bniMontMul_64(a, t, b, mod, mlen, inv);
0151ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
0ea3a6 ¤   ¤   ¤   }
aa0fe4 ¤   ¤   }
649371 ¤   }
b7af5a
26d8af ¤   /*
cb80e3 ¤   ·* At this point, the buffer (which is the high half of b)
6d1e26 ¤   ·* holds either 1 (implicitly, as the "isone" flag is set),
718889 ¤   ·* n1^2, n2^2 or n1^2 * n2^2.
f7a4e3 ¤   ·*/
78af5a
99d8af ¤   /*
b09409 ¤   ·* The main loop. ·The procedure is:
--7fdd 000090d2c2b40100154 Page 42 of bni64.c
a09d84 ¤   ·* - Advance the windows
5fa32c ¤   ·* - If the most-significant bit of a window is set,
380c66 ¤   ·* ··schedule a multiply for the appropriate time in the
ca375c ¤   ·* ··future (may be immediately)
4a383a ¤   ·* - Perform any pending multiples
e36d15 ¤   ·* - Check for termination
a91333 ¤   ·* - Square the buffers
b19714 ¤   ·*
6f7202 ¤   ·* At any given time, the acumulated product is held in
df0d21 ¤   ·* the high half of b.
13a4e3 ¤   ·*/
01220e ¤   for (;;) {
65e85a ¤   ¤   e1bits--;
edaf5a
9f2bc3 ¤   ¤   /* Advance the windows */
e269b3 ¤   ¤   pgpAssert(buf1 < tblmask);
d6d73a ¤   ¤   buf1 <<= 1;
31ea8d ¤   ¤   pgpAssert(buf2 < tblmask);
8c013d ¤   ¤   buf2 <<= 1;
2d1b17 ¤   ¤   /*
72e0cb ¤   ¤   ·* This reads ahead of the current exponent position
92ead0 ¤   ¤   ·* (controlled by e1bits), so we have to be able to read
6b969f ¤   ¤   ·* past the lsb of the exponents without error.
8e9de3 ¤   ¤   ·*/
e7d14f ¤   ¤   if (e1len) {
030cd9 ¤   ¤   ¤   buf1 |= ((*e1 & bitpos) != 0);
f0f670 ¤   ¤   ¤   if (e1len <= e2len)
647ab8 ¤   ¤   ¤   ¤   buf2 |= ((*e2 & bitpos) != 0);
23d9f8 ¤   ¤   ¤   bitpos >>= 1;
4b4afe ¤   ¤   ¤   if (!bitpos) {
d03377 ¤   ¤   ¤   ¤   BIGLITTLE(e1++,e1--);
ff7d8c ¤   ¤   ¤   ¤   if (e1len <= e2len)
effd57 ¤   ¤   ¤   ¤   ¤   BIGLITTLE(e2++,e2--);
bd04c4 ¤   ¤   ¤   ¤   bitpos = (BNWORD64)1 << (64-1);
18096d ¤   ¤   ¤   ¤   e1len--;
f8a3a6 ¤   ¤   ¤   }
480fe4 ¤   ¤   }
93af5a
2956b0 ¤   ¤   /* Examine the first window for pending multiplies */
4735ac ¤   ¤   if (buf1 & tblmask) {
82cacd ¤   ¤   ¤   mult1pos = e1bits - w1bits;
8301cd ¤   ¤   ¤   while ((buf1 & 1) == 0) {
046446 ¤   ¤   ¤   ¤   buf1 >>= 1;
2300e4 ¤   ¤   ¤   ¤   mult1pos++;
f3a3a6 ¤   ¤   ¤   }
10b920 ¤   ¤   ¤   /* Intermediates can wrap, but final must NOT */
9d3542 ¤   ¤   ¤   pgpAssert(mult1pos <= e1bits);
c70279 ¤   ¤   ¤   mult1 = table1[buf1>>1];
ff747c ¤   ¤   ¤   buf1 = 0;
cb0fe4 ¤   ¤   }
4faf5a
ca1b17 ¤   ¤   /*
847036 ¤   ¤   ·* Examine the second window for pending multiplies.
d6f9d2 ¤   ¤   ·* Window 2 can be smaller than window 1, but we
1d3db6 ¤   ¤   ·* keep the same number of bits in buf2, so we need
bd6701 ¤   ¤   ·* to ignore any low-order bits in the buffer when
564911 ¤   ¤   ·* computing what to multiply by, and recompute them
80ee26 ¤   ¤   ·* later.
f19de3 ¤   ¤   ·*/
a8edd2 ¤   ¤   if (buf2 & tblmask) {
781477 ¤   ¤   ¤   /* Remember low-order bits for later */
c8a4f4 ¤   ¤   ¤   i = buf2 & ((1u << w2bits) - 1);
53fcd8 ¤   ¤   ¤   buf2 >>= w2bits;
d71307 ¤   ¤   ¤   mult2pos = e1bits - w1bits + w2bits;
d2d9b3 ¤   ¤   ¤   while ((buf2 & 1) == 0) {
e7b241 ¤   ¤   ¤   ¤   buf2 >>= 1;
588a34 ¤   ¤   ¤   ¤   mult2pos++;
03a3a6 ¤   ¤   ¤   }
520553 ¤   ¤   ¤   pgpAssert(mult2pos <= e1bits);
c5744d ¤   ¤   ¤   mult2 = table2[buf2>>1];
abc3ef ¤   ¤   ¤   buf2 = i;
090fe4 ¤   ¤   }
--0116 0000e95750a40100154 Page 43 of bni64.c
e0af5a
1aaf5a
30591b ¤   ¤   /* If we have a pending multiply for e1, do it */
1d7851 ¤   ¤   if (e1bits == mult1pos) {
b2a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
d56ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
5f8c88 ¤   ¤   ¤   if (isone) {
d16b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
729714 ¤   ¤   ¤   ¤   bniCopy_64(t, mult1, mlen);
a32e60 ¤   ¤   ¤   ¤   isone = 0;
95042d ¤   ¤   ¤   } else {
958113 ¤   ¤   ¤   ¤   bniMontMul_64(a, t, mult1, mod, mlen, inv);
ce6783 ¤   ¤   ¤   ¤   /* Swap a and b */
2c51ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
f4a3a6 ¤   ¤   ¤   }
b40fe4 ¤   ¤   }
e2af5a
94def5 ¤   ¤   /* If we have a pending multiply for e2, do it */
72f281 ¤   ¤   if (e1bits == mult2pos) {
45a6d9 ¤   ¤   ¤   /* Multiply by the table entry remembered previously */
ba6ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
a98c88 ¤   ¤   ¤   if (isone) {
dd6b85 ¤   ¤   ¤   ¤   /* Multiply by 1 is a trivial case */
c2e37d ¤   ¤   ¤   ¤   bniCopy_64(t, mult2, mlen);
f02e60 ¤   ¤   ¤   ¤   isone = 0;
9a042d ¤   ¤   ¤   } else {
25e8f8 ¤   ¤   ¤   ¤   bniMontMul_64(a, t, mult2, mod, mlen, inv);
166783 ¤   ¤   ¤   ¤   /* Swap a and b */
f751ec ¤   ¤   ¤   ¤   t = a; a = b; b = t;
b0a3a6 ¤   ¤   ¤   }
6d0fe4 ¤   ¤   }
45af5a
e97b03 ¤   ¤   /* Are we done? */
7e824a ¤   ¤   if (!e1bits)
5bcdcb ¤   ¤   ¤   break;
0caf5a
b0f1d1 ¤   ¤   /* Square the buffer */
c09d17 ¤   ¤   if (!isone) {
136ac9 ¤   ¤   ¤   t = BIGLITTLE(b-mlen, b+mlen);
fdc7d4 ¤   ¤   ¤   bniMontSquare_64(a, t, mod, mlen, inv);
dbebfc ¤   ¤   ¤   /* Swap a and b */
986c84 ¤   ¤   ¤   t = a; a = b; b = t;
060fe4 ¤   ¤   }
08074b #if BNYIELD
949bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
eb74c2 ¤   ¤   ¤   goto yield;
357454 #endif
60d6a0 ¤   } /* for (;;) */
64af5a
e95f64 ¤   pgpAssert(!isone);
5cf48a ¤   pgpAssert(!buf1);
14d147 ¤   pgpAssert(!buf2);
2caf5a
952111 ¤   /* DONE! */
dfaf5a
a38619 ¤   /* Convert result out of Montgomery form */
412576 ¤   t = BIGLITTLE(b-mlen, b+mlen);
faf6ea ¤   bniCopy_64(b, t, mlen);
88764d ¤   bniZero_64(t, mlen);
44d338 ¤   bniMontReduce_64(b, mod, mlen, inv);
9a2205 ¤   bniCopy_64(result, t, mlen);
29af5a
d166e6 ¤   /* Clean up - free intermediate storage */
914aa5 ¤   y = 0;
39074b #if BNYIELD
74f924 yield:
907454 #endif
1dec82 ¤   buf2 = tblmask >> w2bits;
90c7d7 ¤   while (--tblmask) {
3e369c ¤   ¤   if (tblmask < buf2)
31fb65 ¤   ¤   ¤   BNIFREE(table2[tblmask], mlen);
0ecec9 ¤   ¤   BNIFREE(table1[tblmask], mlen);
--b9c1 00089935afd40100154 Page 44 of bni64.c
a19371 ¤   }
f93a43 ¤   t = table1[0];
474807 ¤   BNIFREE(t, mlen);
47ac28 ¤   BNIFREE(b, 2*mlen);
762bc6 ¤   BNIFREE(a, 2*mlen);
77af5a
f9f88b ¤   return y;¤  /* Success */
adefe6 }
02af5a
2838e5 /*
0b75fe ·* 2^exp (mod mod). ·This is an optimized version for use in Fermat
75e1e7 ·* tests. ·The input value of n is ignored; it is returned with
b25d48 ·* "mlen" words valid.
b3495d ·*/
9d4d2f int
304e52 bniTwoExpMod_64(
280598 ¤   PGPMemoryMgrRef¤mgr, PGPBoolean secure,
141cdf ¤   BNWORD64 *n, BNWORD64 const *exp, unsigned elen,
0a52f4 ¤   BNWORD64 *mod, unsigned mlen)
91bb36 {
2c9586 ¤   unsigned e;¤/* Copy of high words of the exponent */
088a45 ¤   unsigned bits;¤ /* Assorted counter of bits */
fb3665 ¤   BNWORD64 const *bitptr;
b5a8e2 ¤   BNWORD64 bitword, bitpos;
24be94 ¤   BNWORD64 *a, *b, *a1;
12db14 ¤   BNWORD64 inv;
25d4d6 ¤   int y;¤ ¤   /* Result of bnYield() */
baaf5a
36c613 ¤   pgpAssert(mlen);
5baf5a
de68b8 ¤   bitptr = BIGLITTLE(exp-elen, exp+elen-1);
7f5646 ¤   bitword = *bitptr;
82dac6 ¤   pgpAssert(bitword);
e8af5a
316c02 ¤   /* Clear n for future use. */
659578 ¤   bniZero_64(n, mlen);
27af5a
cefe22 ¤   bits = bniBits_64(exp, elen);
1c67c5 ¤
467d28 ¤   /* First, a couple of trivial cases. */
ce3d59 ¤   if (bits <= 1) {
dd04f3 ¤   ¤   /* 2 ^ 0 == 1, ·2 ^ 1 == 2 */
e82a2e ¤   ¤   BIGLITTLE(n[-1],n[0]) = (BNWORD64)1<<elen;
76bbde ¤   ¤   return 0;
ba9371 ¤   }
feaf5a
e158f7 ¤   /* Set bitpos to the most significant bit */
8754f8 ¤   bitpos = (BNWORD64)1 << ((bits-1) & (64-1));
d0af5a
42c6b9 ¤   /* Now, count the bits in the modulus. */
61994f ¤   bits = bniBits_64(mod, mlen);
0e1a06 ¤   pgpAssert(bits > 1);¤   /* a 1-bit modulus is just stupid... */
d0af5a
a7d8af ¤   /*
3ba0aa ¤   ·* We start with 1<<e, where "e" is as many high bits of the
d62f39 ¤   ·* exponent as we can manage without going over the modulus.
9f0fed ¤   ·* This first loop finds "e".
77a4e3 ¤   ·*/
3e142a ¤   e = 1;
812e54 ¤   while (elen) {
d16961 ¤   ¤   /* Consume the first bit */
1d1e4d ¤   ¤   bitpos >>= 1;
cba81f ¤   ¤   if (!bitpos) {
88e0f0 ¤   ¤   ¤   if (!--elen)
a1f622 ¤   ¤   ¤   ¤   break;
7b2e5d ¤   ¤   ¤   bitword = BIGLITTLE(*++bitptr,*--bitptr);
4ca95f ¤   ¤   ¤   bitpos = (BNWORD64)1<<(64-1);
450fe4 ¤   ¤   }
6881e8 ¤   ¤   e = (e << 1) | ((bitpos & bitword) != 0);
9e9a93 ¤   ¤   if (e >= bits) {¤   /* Overflow! ·Back out. */
66895c ¤   ¤   ¤   e >>= 1;
89cdcb ¤   ¤   ¤   break;
--a44b 0007237307a40100154 Page 45 of bni64.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
eed8af ¤   /*
36ce46 ¤   ·* The bit in "bitpos" being examined by the bit buffer has NOT
9a276b ¤   ·* been consumed yet. ·This may be past the end of the exponent,
94f3bd ¤   ·* in which case elen == 1.
d3a4e3 ¤   ·*/
cdaf5a
adf10e ¤   /* Okay, now, set bit "e" in n. ·n is already zero. */
f73964 ¤   inv = (BNWORD64)1 << (e & (64-1));
032295 ¤   e /= 64;
b739b7 ¤   BIGLITTLE(n[-e-1],n[e]) = inv;
dad8af ¤   /*
33be4e ¤   ·* The effective length of n in words is now "e+1".
6fb121 ¤   ·* This is used a little bit later.
d0a4e3 ¤   ·*/
b1af5a
09de10 ¤   if (!elen)
6a2875 ¤   ¤   return 0;¤  /* That was easy! */
73af5a
50d8af ¤   /*
1fc0f9 ¤   ·* We have now processed the first few bits. ·The next step
e8ef9b ¤   ·* is to convert this to Montgomery form for further squaring.
6da4e3 ¤   ·*/
ecaf5a
71cc1d ¤   /* Allocate working storage: two product buffers */
8de662 ¤   BNIALLOC(mgr, secure, a, BNWORD64, 2*mlen);
3a9293 ¤   if (!a)
64043c ¤   ¤   return -1;
771594 ¤   BNIALLOC(mgr, secure, b, BNWORD64, 2*mlen);
835215 ¤   if (!b) {
c8dda3 ¤   ¤   BNIFREE(a, 2*mlen);
2a043c ¤   ¤   return -1;
749371 ¤   }
e7af5a
b4d2c8 ¤   /* Convert n to Montgomery form */
2afe5c ¤   inv = BIGLITTLE(mod[-1],mod[0]);¤   /* LSW of modulus */
48a263 ¤   pgpAssert(inv & 1);¤/* Modulus must be odd */
da5bee ¤   inv = bniMontInv1_64(inv);
1a7b0c ¤   /* Move n (length e+1, remember?) up "mlen" words into b */
f01ca2 ¤   /* Note that we lie about a1 for a bit - it's pointing to b */
74eed0 ¤   a1 = BIGLITTLE(b-mlen,b+mlen);
fafbf4 ¤   bniCopy_64(a1, n, e+1);
a44ccd ¤   bniZero_64(b, mlen);
2ccd45 ¤   /* Do the division - dump the quotient into the high-order words */
302628 ¤   (void)bniDiv_64(a1, b, mlen+e+1, mod, mlen);
68d8af ¤   /*
6e7cbb ¤   ·* Now do the first squaring and modular reduction to put
0ebad9 ¤   ·* the number up in a1 where it belongs.
37a4e3 ¤   ·*/
4107ae ¤   bniMontSquare_64(a, b, mod, mlen, inv);
458266 ¤   /* Fix up a1 to point to where it should go. */
78a2f6 ¤   a1 = BIGLITTLE(a-mlen,a+mlen);
c2af5a
41d8af ¤   /*
28a8c4 ¤   ·* Okay, now, a1 holds the number being accumulated, and
34e460 ¤   ·* b is a scratch register. ·Start working:
11a4e3 ¤   ·*/
81220e ¤   for (;;) {
5f1b17 ¤   ¤   /*
cbfe25 ¤   ¤   ·* Is the bit set? ·If so, double a1 as well.
f505df ¤   ¤   ·* A modular doubling like this is very cheap.
6a9de3 ¤   ¤   ·*/
8826ed ¤   ¤   if (bitpos & bitword) {
0e7aad ¤   ¤   ¤   /*
8e50e7 ¤   ¤   ¤   ·* Double the number. ·If there was a carry out OR
1f66f7 ¤   ¤   ¤   ·* the result is greater than the modulus, subract
acd530 ¤   ¤   ¤   ·* the modulus.
298753 ¤   ¤   ¤   ·*/
0b2bbd ¤   ¤   ¤   if (bniDouble_64(a1, mlen) ||
22d420 ¤   ¤   ¤   ····bniCmp_64(a1, mod, mlen) > 0)
72fd07 ¤   ¤   ¤   ¤   (void)bniSubN_64(a1, mod, mlen);
--c762 0001dcea06740100154 Page 46 of bni64.c
b50fe4 ¤   ¤   }
e6af5a
8a10bb ¤   ¤   /* Advance to the next exponent bit */
111e4d ¤   ¤   bitpos >>= 1;
57a81f ¤   ¤   if (!bitpos) {
1ce0f0 ¤   ¤   ¤   if (!--elen)
276282 ¤   ¤   ¤   ¤   break;¤ /* Done! */
ff2e5d ¤   ¤   ¤   bitword = BIGLITTLE(*++bitptr,*--bitptr);
c9a95f ¤   ¤   ¤   bitpos = (BNWORD64)1<<(64-1);
2d0fe4 ¤   ¤   }
59af5a
571b17 ¤   ¤   /*
6f82e5 ¤   ¤   ·* The elen/bitword/bitpos bit buffer is known to be
29511a ¤   ¤   ·* non-empty, i.e. there is at least one more unconsumed bit.
8621d7 ¤   ¤   ·* Thus, it's safe to square the number.
9e9de3 ¤   ¤   ·*/
43ebba ¤   ¤   bniMontSquare_64(b, a1, mod, mlen, inv);
ab5dee ¤   ¤   /* Rename result (in b) back to a (a1, really). */
b97e82 ¤   ¤   a1 = b; b = a; a = a1;
b6e305 ¤   ¤   a1 = BIGLITTLE(a-mlen,a+mlen);
9e074b #if BNYIELD
c99bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
a074c2 ¤   ¤   ¤   goto yield;
a27454 #endif
ad9371 ¤   }
edaf5a
3c2009 ¤   /* DONE! ·Just a little bit of cleanup... */
04af5a
c2d8af ¤   /*
834b9e ¤   ·* Convert result out of Montgomery form... this is
d45cb3 ¤   ·* just a Montgomery reduction.
23a4e3 ¤   ·*/
ad850f ¤   bniCopy_64(a, a1, mlen);
5fd704 ¤   bniZero_64(a1, mlen);
79bad3 ¤   bniMontReduce_64(a, mod, mlen, inv);
9a1aeb ¤   bniCopy_64(n, a1, mlen);
32af5a
4a66e6 ¤   /* Clean up - free intermediate storage */
9d4aa5 ¤   y = 0;
ef074b #if BNYIELD
21f924 yield:
287454 #endif
86ac28 ¤   BNIFREE(b, 2*mlen);
cd2bc6 ¤   BNIFREE(a, 2*mlen);
feaf5a
02f88b ¤   return y;¤  /* Success */
1befe6 }
deaf5a
f1af5a
a738e5 /*
71b33d ·* Returns a substring of the big-endian array of bytes representation
59b3f8 ·* of the bignum array based on two parameters, the least significant
a505a1 ·* byte number (0 to start with the least significant byte) and the
a2831e ·* length. ·I.e. the number returned is a representation of
baca57 ·* (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
64775e ·*
3266af ·* It is an error if the bignum is not at least buflen + lsbyte bytes
2403a5 ·* long.
e2775e ·*
a608c9 ·* This code assumes that the compiler has the minimal intelligence·
f9be7b ·* neded to optimize divides and modulo operations on an unsigned data
705fd8 ·* type with a power of two.
cc495d ·*/
d9314a void
89b325 bniExtractBigBytes_64(BNWORD64 const *n, unsigned char *buf,
a2163a ¤   unsigned lsbyte, unsigned buflen)
54bb36 {
9d883a ¤   BNWORD64 t = 0;¤/* Needed to shut up uninitialized var warnings */
747dd8 ¤   unsigned shift;
fdaf5a
7929ec ¤   lsbyte += buflen;
1daf5a
--4873 0007c3449bf40100154 Page 47 of bni64.c
5648e1 ¤   shift = (8 * lsbyte) % 64;
567f50 ¤   lsbyte /= (64/8);¤  /* Convert to word offset */
b3378b ¤   BIGLITTLE(n -= lsbyte, n += lsbyte);
65af5a
495bcd ¤   if (shift)
f223e5 ¤   ¤   t = BIGLITTLE(n[-1],n[0]);
36af5a
de98f0 ¤   while (buflen--) {
c7bc36 ¤   ¤   if (!shift) {
2e4e1a ¤   ¤   ¤   t = BIGLITTLE(*n++,*--n);
fdf73c ¤   ¤   ¤   shift = 64;
010fe4 ¤   ¤   }
922ad4 ¤   ¤   shift -= 8;
915443 ¤   ¤   *buf++ = (unsigned char)(t>>shift);
979371 ¤   }
03efe6 }
91af5a
7038e5 /*
3f987d ·* Merge a big-endian array of bytes into a bignum array.
3d225f ·* The array had better be big enough. ·This is
aa9651 ·* equivalent to extracting the entire bignum into a
46e36b ·* large byte array, copying the input buffer into the
264fc8 ·* middle of it, and converting back to a bignum.
54775e ·*
ddbf48 ·* The buf is "len" bytes long, and its *last* byte is at
34714c ·* position "lsbyte" from the end of the bignum.
5e775e ·*
762e7d ·* Note that this is a pain to get right. ·Fortunately, it's hardly
517bdc ·* critical for efficiency.
bd495d ·*/
3e314a void
c5a051 bniInsertBigBytes_64(BNWORD64 *n, unsigned char const *buf,
e2a951 ··················unsigned lsbyte, ·unsigned buflen)
ebbb36 {
6df760 ¤   BNWORD64 t = 0;¤/* Shut up uninitialized varibale warnings */
abaf5a
2d29ec ¤   lsbyte += buflen;
52af5a
c71757 ¤   BIGLITTLE(n -= lsbyte/(64/8), n += lsbyte/(64/8));
1daf5a
b16297 ¤   /* Load up leading odd bytes */
f42410 ¤   if (lsbyte % (64/8)) {
09a3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
1b160b ¤   ¤   t >>= (lsbyte * 8) % 64;
1a9371 ¤   }
22af5a
290bd3 ¤   /* The main loop - merge into t, storing at each word boundary. */
fe98f0 ¤   while (buflen--) {
8e13b9 ¤   ¤   t = (t << 8) | *buf++;
3581b9 ¤   ¤   if ((--lsbyte % (64/8)) == 0)
0b9b8b ¤   ¤   ¤   BIGLITTLE(*n++,*--n) = t;
b19371 ¤   }
48af5a
cd45dc ¤   /* Merge odd bytes in t into last word */
86039b ¤   lsbyte = (lsbyte * 8) % 64;
fa44bd ¤   if (lsbyte) {
ce8687 ¤   ¤   t <<= lsbyte;
e94759 ¤   ¤   t |= (((BNWORD64)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
6ebca8 ¤   ¤   BIGLITTLE(n[0],n[-1]) = t;
699371 ¤   }
daaf5a
8c830f ¤   return;
26efe6 }
88af5a
7038e5 /*
dd0e40 ·* Returns a substring of the little-endian array of bytes representation
a2b3f8 ·* of the bignum array based on two parameters, the least significant
7e05a1 ·* byte number (0 to start with the least significant byte) and the
1b831e ·* length. ·I.e. the number returned is a representation of
27ca57 ·* (bn / 2^(8*lsbyte)) % 2 ^ (8*buflen).
11775e ·*
7c66af ·* It is an error if the bignum is not at least buflen + lsbyte bytes
--e2e9 000ca62c64440100154 Page 48 of bni64.c
9203a5 ·* long.
08775e ·*
de08c9 ·* This code assumes that the compiler has the minimal intelligence·
09be7b ·* neded to optimize divides and modulo operations on an unsigned data
a15fd8 ·* type with a power of two.
f9495d ·*/
c9314a void
6e9fbb bniExtractLittleBytes_64(BNWORD64 const *n, unsigned char *buf,
f1163a ¤   unsigned lsbyte, unsigned buflen)
bcbb36 {
ef883a ¤   BNWORD64 t = 0;¤/* Needed to shut up uninitialized var warnings */
64af5a
6d1757 ¤   BIGLITTLE(n -= lsbyte/(64/8), n += lsbyte/(64/8));
d7af5a
5f2410 ¤   if (lsbyte % (64/8)) {
31a3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
1fd1c3 ¤   ¤   t >>= (lsbyte % (64/8)) * 8 ;
dc9371 ¤   }
48af5a
0e98f0 ¤   while (buflen--) {
4f0233 ¤   ¤   if ((lsbyte++ % (64/8)) == 0)
cb4cd1 ¤   ¤   ¤   t = BIGLITTLE(*--n,*n++);
2c8d7c ¤   ¤   *buf++ = (unsigned char)t;
42e6a0 ¤   ¤   t >>= 8;
f49371 ¤   }
c0efe6 }
a7af5a
5a38e5 /*
46f64f ·* Merge a little-endian array of bytes into a bignum array.
a0225f ·* The array had better be big enough. ·This is
129651 ·* equivalent to extracting the entire bignum into a
3ae36b ·* large byte array, copying the input buffer into the
024fc8 ·* middle of it, and converting back to a bignum.
36775e ·*
86ef01 ·* The buf is "len" bytes long, and its first byte is at
33714c ·* position "lsbyte" from the end of the bignum.
0d775e ·*
2d2e7d ·* Note that this is a pain to get right. ·Fortunately, it's hardly
1a7bdc ·* critical for efficiency.
25495d ·*/
33314a void
8c9b2e bniInsertLittleBytes_64(BNWORD64 *n, unsigned char const *buf,
a9a951 ··················unsigned lsbyte, ·unsigned buflen)
d1bb36 {
adf760 ¤   BNWORD64 t = 0;¤/* Shut up uninitialized varibale warnings */
8caf5a
0ebe7c ¤   /* Move to most-significant end */
f929ec ¤   lsbyte += buflen;
cb4a44 ¤   buf += buflen;
29af5a
da1757 ¤   BIGLITTLE(n -= lsbyte/(64/8), n += lsbyte/(64/8));
04af5a
516297 ¤   /* Load up leading odd bytes */
272410 ¤   if (lsbyte % (64/8)) {
98a3a2 ¤   ¤   t = BIGLITTLE(*--n,*n++);
44160b ¤   ¤   t >>= (lsbyte * 8) % 64;
829371 ¤   }
b8af5a
f00bd3 ¤   /* The main loop - merge into t, storing at each word boundary. */
0f98f0 ¤   while (buflen--) {
10033f ¤   ¤   t = (t << 8) | *--buf;
7781b9 ¤   ¤   if ((--lsbyte % (64/8)) == 0)
819b8b ¤   ¤   ¤   BIGLITTLE(*n++,*--n) = t;
c99371 ¤   }
c1af5a
9e45dc ¤   /* Merge odd bytes in t into last word */
0b039b ¤   lsbyte = (lsbyte * 8) % 64;
2644bd ¤   if (lsbyte) {
8e8687 ¤   ¤   t <<= lsbyte;
364759 ¤   ¤   t |= (((BNWORD64)1 << lsbyte) - 1) & BIGLITTLE(n[0],n[-1]);
54bca8 ¤   ¤   BIGLITTLE(n[0],n[-1]) = t;
ca9371 ¤   }
--ac65 00031b4fe5240100154 Page 49 of bni64.c
e0af5a
c3830f ¤   return;
5fefe6 }
b0af5a
4cf6c3 #ifdef DEADCODE¤/* This was a precursor to the more flexible bniExtractBytes */
b538e5 /*
98b36e ·* Convert a big-endian array of bytes to a bignum.
caabb4 ·* Returns the number of words in the bignum.
7b0f27 ·* Note the expression "64/8" for the number of bytes per word.
52cd11 ·* This is so the word-size adjustment will work.
13495d ·*/
0b536c unsigned
d99dd2 bniFromBytes_64(BNWORD64 *a, unsigned char const *b, unsigned blen)
e4bb36 {
e5d6e3 ¤   BNWORD64 t;
fce3d5 ¤   unsigned alen = (blen + (64/8-1))/(64/8);
a8dbd6 ¤   BIGLITTLE(a -= alen, a += alen);
8baf5a
eab25a ¤   while (blen) {
370550 ¤   ¤   t = 0;
0f4392 ¤   ¤   do {
42c682 ¤   ¤   ¤   t = t << 8 | *b++;
1c55d3 ¤   ¤   } while (--blen & (64/8-1));
b864ff ¤   ¤   BIGLITTLE(*a++,*--a) = t;
579371 ¤   }
11c2b6 ¤   return alen;
9cefe6 }
f57454 #endif
5baf5a
2138e5 /*
3aaf62 ·* Computes the GCD of a and b. ·Modifies both arguments; when it returns,
70e261 ·* one of them is the GCD and the other is trash. ·The return value
f5d234 ·* indicates which: 0 for a, and 1 for b. ·The length of the retult is
e73d14 ·* returned in rlen. ·Both inputs must have one extra word of precision.
83bfe3 ·* alen must be >= blen.
79775e ·*
92537b ·* TODO: use the binary algorithm (Knuth section 4.5.2, algorithm B).
c26ece ·* This is based on taking out common powers of 2, then repeatedly:
24604a ·* gcd(2*u,v) = gcd(u,2*v) = gcd(u,v) - isolated powers of 2 can be deleted.
932ace ·* gcd(u,v) = gcd(u-v,v) - the numbers can be easily reduced.
2c8a0c ·* It gets less reduction per step, but the steps are much faster than
bd79ed ·* the division case.
7e495d ·*/
4e4d2f int
d67b2a bniGcd_64(BNWORD64 *a, unsigned alen, BNWORD64 *b, unsigned blen,
1676c7 ¤   unsigned *rlen)
58bb36 {
95074b #if BNYIELD
f8ce31 ¤   int y;
3e7454 #endif
b764c5 ¤   pgpAssert(alen >= blen);
16af5a
7bfbe1 ¤   while (blen != 0) {
ba8ea0 ¤   ¤   (void)bniDiv_64(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
eb5bb6 ¤   ¤   alen = bniNorm_64(a, blen);
108bb3 ¤   ¤   if (alen == 0) {
e2e6e3 ¤   ¤   ¤   *rlen = blen;
1cdb98 ¤   ¤   ¤   return 1;
230fe4 ¤   ¤   }
f5a770 ¤   ¤   (void)bniDiv_64(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
87dd82 ¤   ¤   blen = bniNorm_64(b, alen);
15074b #if BNYIELD
c89bf2 ¤   ¤   if (bnYield && (y = bnYield()) < 0)
bf1b2c ¤   ¤   ¤   return y;
267454 #endif
079371 ¤   }
d217b1 ¤   *rlen = alen;
bd3e6b ¤   return 0;
bdefe6 }
f8af5a
3938e5 /*
313401 ·* Invert "a" modulo "mod" using the extended Euclidean algorithm.
--752b 000c59fe98140100154 Page 50 of bni64.c
0c81f2 ·* Note that this only computes one of the cosequences, and uses the
8cbe84 ·* theorem that the signs flip every step and the absolute value of
9eea0f ·* the cosequence values are always bounded by the modulus to avoid
bb1a6c ·* having to work with negative numbers.
2c7b80 ·* gcd(a,mod) had better equal 1. ·Returns 1 if the GCD is NOT 1.
cc9798 ·* a must be one word longer than "mod". ·It is overwritten with the
aa1d22 ·* result.
b06b11 ·* TODO: Use Richard Schroeppel's *much* faster algorithm.
3a495d ·*/
cb4d2f int
b352c8 bniInv_64(
076740 ¤   PGPMemoryMgrRef¤mgr,
3154d3 ¤   PGPBoolean secure,
ba619c ¤   BNWORD64 *a, unsigned alen, BNWORD64 const *mod, unsigned mlen)
79bb36 {
6ef1d8 ¤   BNWORD64 *b;¤   /* Hold a copy of mod during GCD reduction */
025202 ¤   BNWORD64 *p;¤   /* Temporary for products added to t0 and t1 */
daa16d ¤   BNWORD64 *t0, *t1;¤ /* Inverse accumulators */
0ff22d ¤   BNWORD64 cy;
bbfc25 ¤   unsigned blen, t0len, t1len, plen;
05ce31 ¤   int y;
8daf5a
4a7824 ¤   alen = bniNorm_64(a, alen);
20cebc ¤   if (!alen)
4c62ef ¤   ¤   return 1;¤  /* No inverse */
61af5a
fe95d6 ¤   mlen = bniNorm_64(mod, mlen);
e8af5a
2f846b ¤   pgpAssert (alen <= mlen);
61af5a
81cfc2 ¤   /* Inverse of 1 is 1 */
7b5002 ¤   if (alen == 1 && BIGLITTLE(a[-1],a[0]) == 1) {
33211d ¤   ¤   bniZero_64(BIGLITTLE(a-alen,a+alen), mlen-alen);
9fbbde ¤   ¤   return 0;
a19371 ¤   }
dcaf5a
0c3e0b ¤   /* Allocate a pile of space */
f2f3c4 ¤   BNIALLOC(mgr, secure, b, BNWORD64, mlen+1);
475359 ¤   if (b) {
6c1b17 ¤   ¤   /*
5033b9 ¤   ¤   ·* Although products are guaranteed to always be less than the
ff6531 ¤   ¤   ·* modulus, it can involve multiplying two 3-word numbers to
39c163 ¤   ¤   ·* get a 5-word result, requiring a 6th word to store a 0
87a773 ¤   ¤   ·* temporarily. ·Thus, mlen + 1.
ce9de3 ¤   ¤   ·*/
bbfa54 ¤   ¤   BNIALLOC(mgr, secure, p, BNWORD64, mlen+1);
374400 ¤   ¤   if (p) {
bb6f0d ¤   ¤   ¤   BNIALLOC(mgr, secure, t0, BNWORD64, mlen);
64da36 ¤   ¤   ¤   if (t0) {
cab760 ¤   ¤   ¤   ¤   BNIALLOC(mgr, secure, t1, BNWORD64, mlen);
b55d06 ¤   ¤   ¤   ¤   if (t1)
625da1 ¤   ¤   ¤   ¤   ¤   ¤   goto allocated;
921674 ¤   ¤   ¤   ¤   BNIFREE(t0, mlen);
66a3a6 ¤   ¤   ¤   }
6e0620 ¤   ¤   ¤   BNIFREE(p, mlen+1);
de0fe4 ¤   ¤   }
f5bc1d ¤   ¤   BNIFREE(b, mlen+1);
899371 ¤   }
3ae69f ¤   return -1;
76af5a
32af26 allocated:
66af5a
cd1bb7 ¤   /* Set t0 to 1 */
d3abc7 ¤   t0len = 1;
708f84 ¤   BIGLITTLE(t0[-1],t0[0]) = 1;
fe67c5 ¤
05d0b9 ¤   /* b = mod */
28f18b ¤   bniCopy_64(b, mod, mlen);
3a3db3 ¤   /* blen = mlen (implicitly) */
b667c5 ¤
59d980 ¤   /* t1 = b / a; b = b % a */
c534ed ¤   cy = bniDiv_64(t1, b, mlen, a, alen);
--a856 0001180238c40100154 Page 51 of bni64.c
97107b ¤   *(BIGLITTLE(t1-(mlen-alen)-1,t1+(mlen-alen))) = cy;
02c436 ¤   t1len = bniNorm_64(t1, mlen-alen+1);
ea567e ¤   blen = bniNorm_64(b, alen);
79af5a
1aaa55 ¤   /* while (b > 1) */
3a9171 ¤   while (blen > 1 || BIGLITTLE(b[-1],b[0]) != (BNWORD64)1) {
f33f9a ¤   ¤   /* q = a / b; a = a % b; */
c7a7b0 ¤   ¤   if (alen < blen || (alen == blen && bniCmp_64(a, a, alen) < 0))
d3b783 ¤   ¤   ¤   pgpAssert(0);
6b09d5 ¤   ¤   cy = bniDiv_64(BIGLITTLE(a-blen,a+blen), a, alen, b, blen);
aa0118 ¤   ¤   *(BIGLITTLE(a-alen-1,a+alen)) = cy;
a129ca ¤   ¤   plen = bniNorm_64(BIGLITTLE(a-blen,a+blen), alen-blen+1);
70ec44 ¤   ¤   pgpAssert(plen);
f15bb6 ¤   ¤   alen = bniNorm_64(a, blen);
0f2c1f ¤   ¤   if (!alen)
f06b71 ¤   ¤   ¤   goto failure;¤  /* GCD not 1 */
63af5a
f6c2fe ¤   ¤   /* t0 += q * t1; */
5e7df1 ¤   ¤   pgpAssert(plen+t1len <= mlen+1);
fed6c0 ¤   ¤   bniMul_64(p, BIGLITTLE(a-blen,a+blen), plen, t1, t1len);
a2a072 ¤   ¤   plen = bniNorm_64(p, plen + t1len);
0274e7 ¤   ¤   pgpAssert(plen <= mlen);
af7ccf ¤   ¤   if (plen > t0len) {
8c0c52 ¤   ¤   ¤   bniZero_64(BIGLITTLE(t0-t0len,t0+t0len), plen-t0len);
1db0b8 ¤   ¤   ¤   t0len = plen;
db0fe4 ¤   ¤   }
354ba6 ¤   ¤   cy = bniAddN_64(t0, p, plen);
2e2e8b ¤   ¤   if (cy) {
b079eb ¤   ¤   ¤   if (t0len > plen) {
6ca731 ¤   ¤   ¤   ¤   cy = bniAdd1_64(BIGLITTLE(t0-plen,t0+plen),
8c8447 ¤   ¤   ¤   ¤   ¤   ¤   t0len-plen, cy);
dfa3a6 ¤   ¤   ¤   }
4b1411 ¤   ¤   ¤   if (cy) {
338336 ¤   ¤   ¤   ¤   BIGLITTLE(t0[-t0len-1],t0[t0len]) = cy;
75a7f8 ¤   ¤   ¤   ¤   t0len++;
09a3a6 ¤   ¤   ¤   }
c60fe4 ¤   ¤   }
2aaf5a
5a80a4 ¤   ¤   /* if (a <= 1) return a ? t0 : FAIL; */
341918 ¤   ¤   if (alen <= 1 && BIGLITTLE(a[-1],a[0]) == (BNWORD64)1) {
533d57 ¤   ¤   ¤   if (alen == 0)
847b91 ¤   ¤   ¤   ¤   goto failure;¤  /* FAIL */
cde238 ¤   ¤   ¤   pgpAssert(t0len <= mlen);
bac749 ¤   ¤   ¤   bniCopy_64(a, t0, t0len);
eaad01 ¤   ¤   ¤   bniZero_64(BIGLITTLE(a-t0len, a+t0len), mlen-t0len);
08346a ¤   ¤   ¤   goto success;
f70fe4 ¤   ¤   }
2baf5a
e1ad15 ¤   ¤   /* q = b / a; b = b % a; */
eebb78 ¤   ¤   if (blen < alen || (blen == alen && bniCmp_64(b, a, alen) < 0))
31b783 ¤   ¤   ¤   pgpAssert(0);
bd2005 ¤   ¤   cy = bniDiv_64(BIGLITTLE(b-alen,b+alen), b, blen, a, alen);
abc9ab ¤   ¤   *(BIGLITTLE(b-blen-1,b+blen)) = cy;
4c8c2b ¤   ¤   plen = bniNorm_64(BIGLITTLE(b-alen,b+alen), blen-alen+1);
d7ec44 ¤   ¤   pgpAssert(plen);
1add82 ¤   ¤   blen = bniNorm_64(b, alen);
ec2062 ¤   ¤   if (!blen)
3f6b71 ¤   ¤   ¤   goto failure;¤  /* GCD not 1 */
73af5a
2948c5 ¤   ¤   /* t1 += q * t0; */
ad6dfe ¤   ¤   pgpAssert(plen+t0len <= mlen+1);
aa8d10 ¤   ¤   bniMul_64(p, BIGLITTLE(b-alen,b+alen), plen, t0, t0len);
993fa7 ¤   ¤   plen = bniNorm_64(p, plen + t0len);
3f74e7 ¤   ¤   pgpAssert(plen <= mlen);
8afd70 ¤   ¤   if (plen > t1len) {
a14b4b ¤   ¤   ¤   bniZero_64(BIGLITTLE(t1-t1len,t1+t1len), plen-t1len);
56b515 ¤   ¤   ¤   t1len = plen;
c90fe4 ¤   ¤   }
d74e0b ¤   ¤   cy = bniAddN_64(t1, p, plen);
2a2e8b ¤   ¤   if (cy) {
9631c1 ¤   ¤   ¤   if (t1len > plen) {
11b73e ¤   ¤   ¤   ¤   cy = bniAdd1_64(BIGLITTLE(t1-plen,t0+plen),
--bbd7 001d529630d40100154 Page 52 of bni64.c
f90a57 ¤   ¤   ¤   ¤   ¤   ¤   t1len-plen, cy);
dea3a6 ¤   ¤   ¤   }
be1411 ¤   ¤   ¤   if (cy) {
c4f5c1 ¤   ¤   ¤   ¤   BIGLITTLE(t1[-t1len-1],t1[t1len]) = cy;
452647 ¤   ¤   ¤   ¤   t1len++;
49a3a6 ¤   ¤   ¤   }
c40fe4 ¤   ¤   }
9d074b #if BNYIELD
52b0d5 ¤   ¤   if (bnYield && (y = bnYield() < 0))
bc74c2 ¤   ¤   ¤   goto yield;
a27454 #endif
ba9371 ¤   }
7aaf5a
7ac2c1 ¤   if (!blen)
63fa45 ¤   ¤   goto failure;¤  /* gcd(a, mod) != 1 -- FAIL */
d7af5a
9a6f47 ¤   /* return mod-t1 */
bb29f5 ¤   bniCopy_64(a, mod, mlen);
6d7269 ¤   pgpAssert(t1len <= mlen);
bd2cf6 ¤   cy = bniSubN_64(a, t1, t1len);
0fab3e ¤   if (cy) {
98a6e8 ¤   ¤   pgpAssert(mlen > t1len);
d0356b ¤   ¤   cy = bniSub1_64(BIGLITTLE(a-t1len, a+t1len), mlen-t1len, cy);
5a642a ¤   ¤   pgpAssert(!cy);
099371 ¤   }
48af5a
a5d3ad success:
1b40e5 ¤   BNIFREE(t1, mlen);
de6cc2 ¤   BNIFREE(t0, mlen);
8a5d1b ¤   BNIFREE(p, mlen+1);
304a78 ¤   BNIFREE(b, mlen+1);
1167c5 ¤
363e6b ¤   return 0;
4daf5a
515cfe failure:¤   ¤   /* GCD is not 1 - no inverse exists! */
9c1079 ¤   y = 1;
d1074b #if BNYIELD
24f924 yield:
117454 #endif
5040e5 ¤   BNIFREE(t1, mlen);
f76cc2 ¤   BNIFREE(t0, mlen);
6f5d1b ¤   BNIFREE(p, mlen+1);
c04a78 ¤   BNIFREE(b, mlen+1);
e867c5 ¤
4ba403 ¤   return y;
d5efe6 }
--1a43 0005fcd72c740100155 Page 1 of bni64.h
bc38e5 /*
cafa49 ·* $Id: bni64.h,v 1.3 1998/05/14 19:07:24 cbertsch Exp $
f1495d ·*/
efaf5a
c3cc5d #ifndef Included_bni64_h
fb8fb7 #define Included_bni64_h
75af5a
cca6ac #include "bni.h"
586773 #include "pgpMemoryMgr.h"
afaf5a
438a13 #ifndef BNWORD64
85a67c #error 64-bit bignum library requires a 64-bit data type
857454 #endif
d1af5a
3f99c6 PGP_BEGIN_C_DECLARATIONS
65af5a
00b24d #ifndef bniCopy_64
f0b053 void bniCopy_64(BNWORD64 *dest, BNWORD64 const *src, unsigned len);
517454 #endif
ec2bef #ifndef bniZero_64
017017 void bniZero_64(BNWORD64 *num, unsigned len);
1f7454 #endif
3bcbc7 #ifndef bniNeg_64
2ee9dc void bniNeg_64(BNWORD64 *num, unsigned len);
727454 #endif
67af5a
c006be #ifndef bniAdd1_64
7a108d BNWORD64 bniAdd1_64(BNWORD64 *num, unsigned len, BNWORD64 carry);
097454 #endif
8d644f #ifndef bniSub1_64
4504df BNWORD64 bniSub1_64(BNWORD64 *num, unsigned len, BNWORD64 borrow);
f67454 #endif
9aaf5a
0e79b1 #ifndef bniAddN_64
7a7792 BNWORD64 bniAddN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len);
827454 #endif
5a1b40 #ifndef bniSubN_64
0f06e0 BNWORD64 bniSubN_64(BNWORD64 *num1, BNWORD64 const *num2, unsigned len);
a47454 #endif
39af5a
b8404c #ifndef bniCmp_64
9b9f0c int bniCmp_64(BNWORD64 const *num1, BNWORD64 const *num2, unsigned len);
537454 #endif
3baf5a
e076a3 #ifndef bniMulN1_64
ec1b75 void bniMulN1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k);
ea7454 #endif
1e7eb5 #ifndef bniMulAdd1_64
368bb4 BNWORD64
1f29fb bniMulAdd1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len, BNWORD64 k);
497454 #endif
bf1c44 #ifndef bniMulSub1_64
c78bdd BNWORD64 bniMulSub1_64(BNWORD64 *out, BNWORD64 const *in, unsigned len,
14644c ¤   ¤   ¤   BNWORD64 k);
ed7454 #endif
58af5a
d18080 #ifndef bniLshift_64
6d50c7 BNWORD64 bniLshift_64(BNWORD64 *num, unsigned len, unsigned shift);
217454 #endif
b8573f #ifndef bniDouble_64
43e23d BNWORD64 bniDouble_64(BNWORD64 *num, unsigned len);
7f7454 #endif
2dd329 #ifndef bniRshift_64
07b9d2 BNWORD64 bniRshift_64(BNWORD64 *num, unsigned len, unsigned shift);
0b7454 #endif
02af5a
e666f5 #ifndef bniMul_64
4e61ec void bniMul_64(BNWORD64 *prod, BNWORD64 const *num1, unsigned len1,
e5a942 ¤   BNWORD64 const *num2, unsigned len2);
d17454 #endif
4ab6a5 #ifndef bniSquare_64
5f7bb1 void bniSquare_64(BNWORD64 *prod, BNWORD64 const *num, unsigned len);
--a61a 000fbf48c1240100155 Page 2 of bni64.h
a07454 #endif
e0af5a
d69996 #ifndef bniNorm_64
a89361 unsigned bniNorm_64(BNWORD64 const *num, unsigned len);
dd7454 #endif
e8373b #ifndef bniBits_64
d932a5 unsigned bniBits_64(BNWORD64 const *num, unsigned len);
297454 #endif
26af5a
2a21bb #ifndef bniExtractBigBytes_64
43e21b void bniExtractBigBytes_64(BNWORD64 const *bn, unsigned char *buf,
4b9eef ¤   unsigned lsbyte, unsigned buflen);
ee7454 #endif
e47650 #ifndef bniInsertBigytes_64
796462 void bniInsertBigBytes_64(BNWORD64 *n, unsigned char const *buf,
9b7db1 ¤   unsigned lsbyte, ·unsigned buflen);
357454 #endif
209ca3 #ifndef bniExtractLittleBytes_64
7d030a void bniExtractLittleBytes_64(BNWORD64 const *bn, unsigned char *buf,
269eef ¤   unsigned lsbyte, unsigned buflen);
be7454 #endif
f42efe #ifndef bniInsertLittleBytes_64
8b5f2e void bniInsertLittleBytes_64(BNWORD64 *n, unsigned char const *buf,
c37db1 ¤   unsigned lsbyte, ·unsigned buflen);
dc7454 #endif
7daf5a
ab8ce5 #ifndef bniDiv21_64
dd784d BNWORD64 bniDiv21_64(BNWORD64 *q, BNWORD64 nh, BNWORD64 nl, BNWORD64 d);
7d7454 #endif
60f576 #ifndef bniDiv1_64
0d4eb7 BNWORD64 bniDiv1_64(BNWORD64 *q, BNWORD64 *rem,
bd8cfd ¤   BNWORD64 const *n, unsigned len, BNWORD64 d);
6f7454 #endif
3aeaed #ifndef bniModQ_64
76ab08 unsigned bniModQ_64(BNWORD64 const *n, unsigned len, unsigned d);
8e7454 #endif
37ac60 #ifndef bniDiv_64
f48bb4 BNWORD64
070719 bniDiv_64(BNWORD64 *q, BNWORD64 *n, unsigned nlen, BNWORD64 *d, unsigned dlen);
267454 #endif
74af5a
d5cbc8 #ifndef bniMontInv1_64
e722c8 BNWORD64 bniMontInv1_64(BNWORD64 const x);
947454 #endif
b478e3 #ifndef bniMontReduce_64
eff882 void bniMontReduce_64(BNWORD64 *n, BNWORD64 const *mod, unsigned const mlen,
7525f0 ················BNWORD64 inv);
927454 #endif
7fdc44 #ifndef bniToMont_64
c629f6 void bniToMont_64(BNWORD64 *n, unsigned nlen, BNWORD64 *mod, unsigned mlen);
817454 #endif
646cf0 #ifndef bniFromMont_64
e168fe void bniFromMont_64(BNWORD64 *n, BNWORD64 *mod, unsigned len);
667454 #endif
a5af5a
938741 #ifndef bniExpMod_64
1183d5 int bniExpMod_64( PGPMemoryMgrRef mgr, PGPBoolean secure,
6c9883 ¤   BNWORD64 *result, BNWORD64 const *n, unsigned nlen,
dbf174 ¤   BNWORD64 const *exp, unsigned elen, BNWORD64 *mod, unsigned mlen);
267454 #endif
476dce #ifndef bniDoubleExpMod_64
c01592 int bniDoubleExpMod_64(
1d39d6 ¤   PGPMemoryMgrRef mgr, PGPBoolean secure,
3ace1b ¤   BNWORD64 *result,
50a070 ¤   BNWORD64 const *n1, unsigned n1len, BNWORD64 const *e1, unsigned e1len,
e3a70c ¤   BNWORD64 const *n2, unsigned n2len, BNWORD64 const *e2, unsigned e2len,
4bb1d9 ¤   BNWORD64 *mod, unsigned mlen);
737454 #endif
8a123b #ifndef bniTwoExpMod_64
26494b int bniTwoExpMod_64( PGPMemoryMgrRef mgr, PGPBoolean secure,
b81cdf ¤   BNWORD64 *n, BNWORD64 const *exp, unsigned elen,
fbb1d9 ¤   BNWORD64 *mod, unsigned mlen);
--9baf 00102a5c8db40100155 Page 3 of bni64.h
a07454 #endif
ec8fc8 #ifndef bniGcd_64
e9b3fa int bniGcd_64(BNWORD64 *a, unsigned alen, BNWORD64 *b, unsigned blen,
83b2e5 ¤   unsigned *rlen);
e07454 #endif
9a9efe #ifndef bniInv_64
4f9c09 int bniInv_64( PGPMemoryMgrRef mgr, PGPBoolean secure,
9f59d2 ¤   ¤   BNWORD64 *a, unsigned alen, BNWORD64 const *mod, unsigned mlen);
907454 #endif
e5af5a
1d1254 PGP_END_C_DECLARATIONS
79af5a
02e341 #endif /* Included_bni64_h */
--55ac 000b88d8bbe40100156 Page 1 of bni68000.c
bc38e5 /*
9df325 ·* bni68000.c - 16-bit bignum primitives for the 68000 (or 68010) processors.
2d775e ·*
2d4a32 ·* This was written for Metrowerks C, and while it should be reasonably
e0f81b ·* portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2.
c63093 ·* Some 680x0 compilers make d2 callee-save, so instructions to save it
35a39f ·* will have to be added.
4d9ec0 ·*·
4989e5 ·* This code supports 16 or 32-bit ints, based on UINT_MAX.
5dbc04 ·* Regardless of UINT_MAX, only bignums up to 64K words (1 million bits)
986238 ·* are supported. ·(68k hackers will recognize this as a consequence of
355ae9 ·* using dbra.)
3b775e ·*
480acf ·* These primitives use little-endian word order.
bbce5b ·* (The order of bytes within words is irrelevant to this issue.)
0d775e ·*
94d091 ·* $Id: bni68000.c,v 1.1 1997/04/30 08:36:11 mhw Exp $
53495d ·*/
14af5a
3ea7a0 #include <limits.h>
35af5a
dbaba6 #include "bni.h" ·······/* Should include bni68000.h */
29af5a
2c38e5 /*
e72d22 ·* The Metrowerks C compiler (1.2.2) produces bad 68k code for the
2054aa ·* following input, which happens to be the inner loop of bniSub1,
b0922a ·* so a few less than critical routines have been recoded in assembly
761e6c ·* to avoid the bug. ·(Optimizer on or off does not matter.)
e99ec0 ·*·
b418eb ·* unsigned
912bbf ·* decrement(unsigned *num, unsigned len)
8b85a8 ·* {
a321bb ·* ·····do {
221247 ·* ·············if ((*num++)-- != 0)
d6102a ·* ·····················return 0;
3a540b ·* ·····} while (--len);
f97065 ·* ·····return 1;
1cd178 ·* }
b2495d ·*/
243def asm BNWORD16
f09fb4 bniSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
6abb36 {
0928e2 ········movea.l 4(sp),a0 ·······/* num */
b5a106 #if UINT_MAX == 0xffff
fd70af ········move.w ·10(sp),d0 ······/* borrow */
10db21 #else
cfe482 ········move.w ·12(sp),d0 ······/* borrow */
347454 #endif
4fa180 ········sub.w ··d0,(a0)+
f75431 ········bcc ············done
b1a106 #if UINT_MAX == 0xffff
4de1e0 ········move.w ·8(sp),d0 ·······/* len */
c8db21 #else
650e35 ········move.w ·10(sp),d0 ······/* len */
2a7454 #endif
ddd830 ········subq.w ·#2,d0
192838 ········bcs ············done
6a3247 loop:
06b73e ········subq.w ·#1,(a0)+
81f464 ········dbcc ···d0,loop
d2b38c done:
321557 ········moveq.l #0,d0
a54a30 ········addx.w ·d0,d0
b9e6d2 ········rts
11efe6 }
5caf5a
fb3def asm BNWORD16
3cc872 bniAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
6cbb36 {
7b28e2 ········movea.l 4(sp),a0 ·······/* num */
08a106 #if UINT_MAX == 0xffff
b83b3b ········move.w ·10(sp),d0 ······/* carry */
--80c7 0001d607fc940100156 Page 2 of bni68000.c
0fdb21 #else
3d9fab ········move.w ·12(sp),d0 ······/* carry */
e67454 #endif
1c1e0a ········add.w ··d0,(a0)+
a05431 ········bcc ············done
a0a106 #if UINT_MAX == 0xffff
eee1e0 ········move.w ·8(sp),d0 ·······/* len */
a6db21 #else
e50e35 ········move.w ·10(sp),d0 ······/* len */
ad7454 #endif
9ed830 ········subq.w ·#2,d0
d62838 ········bcs ············done
563247 loop:
4c08b4 ········addq.w ·#1,(a0)+
55f464 ········dbcc ···d0,loop
90b38c done:
fe1557 ········moveq.l #0,d0
714a30 ········addx.w ·d0,d0
e9e6d2 ········rts
33efe6 }
2daf5a
3c60ee asm void
253c2f bniMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
92bb36 {
c884ac ········move.w ·d3,-(sp) ·······/* 2 bytes of stack frame */
37f8d8 ········move.l ·2+4(sp),a1 ·····/* out */
ddcfde ········move.l ·2+8(sp),a0 ·····/* in */
31a106 #if UINT_MAX == 0xffff
5e5735 ········move.w ·2+12(sp),d3 ····/* len */
dba410 ········move.w ·2+14(sp),d2 ····/* k */
aadb21 #else
08c77f ········move.w ·2+14(sp),d3 ····/* len (low 16 bits) */
68cac8 ········move.w ·2+16(sp),d2 ····/* k */
3a7454 #endif
f9af5a
ae311a ········move.w ·(a0)+,d1 ·······/* First multiply */
c5bb45 ········mulu.w ·d2,d1
4906f1 ········move.w ·d1,(a1)+
854621 ········clr.w ··d1
433175 ········swap ···d1
dbaf5a
ac052a ········subq.w ·#1,d3 ··········/* Setup for loop unrolling */
03343b ········lsr.w ··#1,d3
66053f ········bcs.s ··m16_even
7a0bc6 ········beq.s ··m16_short
26508e ········
85eec8 ········subq.w ·#1,d3 ··········/* Set up software pipeline properly */
78f920 ········move.l ·d1,d0
ce508e ········
28e449 m16_loop:
abca00 ········move.w ·(a0)+,d1
07bb45 ········mulu.w ·d2,d1
3bef6b ········add.l ··d0,d1
4706f1 ········move.w ·d1,(a1)+
78e408 ········clr.w¤  d1
1734fa ········swap¤   d1
736d3e m16_even:
ecaf5a
84d3d8 ········move.w ·(a0)+,d0
c1a29d ········mulu.w ·d2,d0
f3fdf7 ········add.l ··d1,d0
0b874e ········move.w ·d0,(a1)+
e35ff9 ········clr.w ··d0
f128ad ········swap ···d0
e6af5a
82bddc ········dbra ···d3,m16_loop
a8508e ········
e16e32 ········move.w ·d0,(a1)
496ea1 ········move.w ·(sp)+,d3
4ee6d2 ········rts
57592e m16_short:
1df1e7 ········move.w ·d1,(a1)
--4fa9 000ce18b94d40100156 Page 3 of bni68000.c
f46ea1 ········move.w ·(sp)+,d3
01e6d2 ········rts
25efe6 }
28af5a
c3af5a
e73def asm BNWORD16
b6347d bniMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
e2bb36 {
802832 ········move.w ·d4,-(sp)·
c03899 ········clr.w ··d4
623b6e ········move.w ·d3,-(sp) ·······/* 4 bytes of stack frame */
c1471a ········move.l ·4+4(sp),a1 ·····/* out */
00d6c4 ········move.l ·4+8(sp),a0 ·····/* in */
d8a106 #if UINT_MAX == 0xffff
9ce8f7 ········move.w ·4+12(sp),d3 ····/* len */
f37799 ········move.w ·4+14(sp),d2 ····/* k */
02db21 #else
8fe3e3 ········move.w ·4+14(sp),d3 ····/* len (low 16 bits) */
9c1941 ········move.w ·4+16(sp),d2 ····/* k */
627454 #endif
12af5a
1d311a ········move.w ·(a0)+,d1 ·······/* First multiply */
16bb45 ········mulu.w ·d2,d1
eb830e ········add.w ··d1,(a1)+
564621 ········clr.w ··d1
703175 ········swap ···d1
dd7ef8 ········addx.w ·d4,d1
abaf5a
6d052a ········subq.w ·#1,d3 ··········/* Setup for loop unrolling */
80343b ········lsr.w ··#1,d3
568cc3 ········bcs.s ··ma16_even
4260d1 ········beq.s ··ma16_short
45508e ········
43eec8 ········subq.w ·#1,d3 ··········/* Set up software pipeline properly */
b9f920 ········move.l ·d1,d0
73508e ········
56a51d ma16_loop:
9bca00 ········move.w ·(a0)+,d1
c4bb45 ········mulu.w ·d2,d1
22ef6b ········add.l ··d0,d1
02830e ········add.w ··d1,(a1)+
364621 ········clr.w ··d1
973175 ········swap ···d1
527ef8 ········addx.w ·d4,d1
452c6a ma16_even:
5eaf5a
ead3d8 ········move.w ·(a0)+,d0
cca29d ········mulu.w ·d2,d0
b5fdf7 ········add.l ··d1,d0
df02b1 ········add.w ··d0,(a1)+
805ff9 ········clr.w ··d0
1b28ad ········swap ···d0
b66720 ········addx.w ·d4,d0
b6af5a
7dc7c4 ········dbra ···d3,ma16_loop
dd508e ········
846ea1 ········move.w ·(sp)+,d3
a823a9 ········move.w ·(sp)+,d4
dbe6d2 ········rts
844dce ma16_short:
206ea1 ········move.w ·(sp)+,d3
4825ad ········move.l ·d1,d0 ··
b923a9 ········move.w ·(sp)+,d4
b2e6d2 ········rts
d1efe6 }
4baf5a
06af5a
13af5a
f33def asm BNWORD16
9c39f2 bniMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
b6bb36 {
ce2832 ········move.w ·d4,-(sp)·
--a4c4 000b44ad5ec40100156 Page 4 of bni68000.c
8c3899 ········clr.w ··d4
583b6e ········move.w ·d3,-(sp) ·······/* 4 bytes of stack frame */
22471a ········move.l ·4+4(sp),a1 ·····/* out */
b0d6c4 ········move.l ·4+8(sp),a0 ·····/* in */
50a106 #if UINT_MAX == 0xffff
55e8f7 ········move.w ·4+12(sp),d3 ····/* len */
d07799 ········move.w ·4+14(sp),d2 ····/* k */
1ddb21 #else
49e3e3 ········move.w ·4+14(sp),d3 ····/* len (low 16 bits) */
1d1941 ········move.w ·4+16(sp),d2 ····/* k */
407454 #endif
faaf5a
54311a ········move.w ·(a0)+,d1 ·······/* First multiply */
10bb45 ········mulu.w ·d2,d1
d83c84 ········sub.w ··d1,(a1)+
a54621 ········clr.w ··d1
fd3175 ········swap ···d1
d27ef8 ········addx.w ·d4,d1
ddaf5a
d1052a ········subq.w ·#1,d3 ··········/* Setup for loop unrolling */
45343b ········lsr.w ··#1,d3
3ae8ad ········bcs.s ··ms16_even
75eacd ········beq.s ··ms16_short
ad508e ········
84eec8 ········subq.w ·#1,d3 ··········/* Set up software pipeline properly */
ebf920 ········move.l ·d1,d0
5f508e ········
112f01 ms16_loop:
9cca00 ········move.w ·(a0)+,d1
77bb45 ········mulu.w ·d2,d1
98ef6b ········add.l ··d0,d1
5d3c84 ········sub.w ··d1,(a1)+
504621 ········clr.w ··d1
a63175 ········swap ···d1
dc7ef8 ········addx.w ·d4,d1
5da676 ms16_even:
71af5a
4ad3d8 ········move.w ·(a0)+,d0
ada29d ········mulu.w ·d2,d0
fafdf7 ········add.l ··d1,d0
6cbd3b ········sub.w ··d0,(a1)+
fd5ff9 ········clr.w ··d0
df28ad ········swap ···d0
a66720 ········addx.w ·d4,d0
09af5a
86a3aa ········dbra ···d3,ms16_loop
ce508e ········
2d6ea1 ········move.w ·(sp)+,d3
1523a9 ········move.w ·(sp)+,d4
73e6d2 ········rts
5e97a9 ms16_short:
216ea1 ········move.w ·(sp)+,d3
ac25ad ········move.l ·d1,d0 ··
6c23a9 ········move.w ·(sp)+,d4
1fe6d2 ········rts
95efe6 }
b8af5a
036cec /* The generic long/short divide doesn't know that nh < d */
843def asm BNWORD16
58b9a1 bniDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
47bb36 {
52b41c ········move.l ·8(sp),d0¤   ¤   /* nh *and* nl */
187ef3 ········divu.w¤ 12(sp),d0
b2601b ········move.l¤ 4(sp),a0
69f425 ········move.w¤ d0,(a0)
3efdd0 ········clr.w¤  d0
982d22 ········swap¤   d0
11e6d2 ········rts
5defe6 }
66af5a
2c5a82 asm unsigned
b4fbe5 bniModQ_16(BNWORD16 const *n, unsigned len, BNWORD16 d)
--c0bb 000a78d165d40100156 Page 5 of bni68000.c
2cbb36 {
d03ce6 ········move.l ·4(sp),a0 ·······/* n */
7be5e4 ········moveq.l¤#0,d1
82a106 #if UINT_MAX == 0xffff
9d72a9 ········move.w ·8(sp),d1 ·······/* len */
5d2934 ········move.w ·10(sp),d2 ······/* d */
4adb21 #else
bc24a8 ········move.w ·10(sp),d1 ······/* len (low 16 bits) */
3d32b7 ········move.w ·12(sp),d2 ······/* d */
567454 #endif
34af5a
e8de24 ¤   ¤   add.l¤  d1,a0
3d1455 ¤   ¤   add.l¤  d1,a0¤  ¤   ¤   /* n += len */
79e538 ¤   ¤   moveq.l¤#0,d0
c2dc24 ········subq.w ·#1,d1
b3af5a
65774f mq16_loop:
d60476 ········move.w ·-(a0),d0¤   ¤   /* Assemble remainder and new word */
2dc42f ········divu.w ·d2,d0 ·······¤  /* Put remainder in high half of d0 */
1b45b4 ········dbra ···d1,mq16_loop ···
ffec2c ························
52f684 mq16_done:
3f5ff9 ········clr.w ··d0
ee28ad ········swap ···d0
5ce6d2 ········rts
0eefe6 }
50af5a
6338e5 /*
bebc6f ·* Detect if this is a 32-bit processor (68020+ *or* CPU32).
0dabac ·* Both the 68020+ and CPU32 processors (which have 32x32->64-bit
c63045 ·* multiply, what the 32-bit math library wants) support scaled indexed
8b7b00 ·* addressing. ·The 68000 and 68010 ignore the scale selection
2d7cdc ·* bits, treating it as *1 all the time. ·So a 32-bit processor
307dfa ·* will evaluate -2(a0,a0.w*2) as 1+1*2-2 = 1.
f06ff7 ·* A 16-bit processor will compute 1+1-2 = 0.
8e775e ·*
f465dd ·* Thus, the return value will indicate whether the chip this is
0290df ·* running on supports 32x32->64-bit multiply (mulu.l).
56495d ·*/
5a744c asm int
d71576 is68020(void)
a5bb36 {
5cfbe7 ········machine 68020
47a96d ········lea ····1,a0
1cb177 #if 0
c2ad0c ········lea ····-2(a0,a0.w*2),a0¤   /* Metrowerks won't asm this, arrgh */
e5db21 #else
60025b ········dc.w ···0x41f0, 0x82fe
067454 #endif
8fcf13 ········move.l¤ a0,d0
12e6d2 ········rts
deefe6 }
5f38e5 /*
f20d21 ·* Since I had to hand-assemble that fancy addressing mode, I had to study
502a43 ·* up on 680x0 addressing modes.
db33c0 ·* A summary of 680x0 addressing modes.
6a51a1 ·* A 68000 effective address specifies an operand on an instruction, which
996ccf ·* may be a register or in memory. ·It is made up of a 3-bit mode and a
0c62f9 ·* 3-bit register specifier. ·The meanings of the various modes are:
64775e ·*
9ba165 ·* 000 reg - Dn, n specified by "reg"
4ef491 ·* 001 reg - An, n specified by "reg"
57d521 ·* 010 reg - (An)
dedb05 ·* 011 reg - (An)+
ab03ec ·* 100 reg - -(An)
70d7df ·* 101 reg - d16(An), one 16-bit displacement word follows, sign-extended
992e1d ·* 110 reg - Fancy addressing mode off of An, see extension word below
5ae8cf ·* 111 000 - abs.W, one 16-bit signed absolute address follows
11ea3d ·* 111 001 - abs.L, one 32-bit absolute address follows
16320e ·* 111 010 - d16(PC), one 16-bit displacemnt word follows, sign-extended
f1bfe9 ·* 111 011 - Fancy addressing mode off of PC, see extension word below
a7071c ·* 111 100 - #immediate, followed by 16 or 32 bits of immediate value
--9d0f 000ef6f7a1540100156 Page 6 of bni68000.c
bccd34 ·* 111 101 - unused, reserved
a55305 ·* 111 110 - unused, reserved
cc6469 ·* 111 111 - unused, reserved
c2775e ·*
dfd129 ·* Memory references are to data space, except that PC-relative references
cd68aa ·* are to program space, and are read-only.
69775e ·*
e2ceb1 ·* Fancy addressing modes are followed by a 16-bit extension word, and come
2f69eb ·* in "brief" and "full" forms.
db23bf ·* The "brief" form looks like this. ·Bit 8 is 0 to indicate this form:
f6775e ·*
96a831 ·* 1 ··1 ··1 ··1 ··1 ··1 ··1 ·
861a9e ·* 6 ··5 ··4 ··3 ··2 ··1 ··0 ··9 ··8 ··7 ··6 ··5 ··4 ··3 ··2 ··1 ··0
6c2da3 ·* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2c3508 ·* |A/D| ·register |L/W| scale | 0 | ··8-bit signed displacement ··|
4a2da3 ·* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
36775e ·*
58e628 ·* The basic effective address specifies a 32-bit base register - A0 through
d5a11a ·* A7 or PC (the address of the following instruction).
7a65b2 ·* The A/D and register fields specify an index register. ·A/D is 1 for
544615 ·* address registers, and 0 for data registers. ·L/W specifies the length
5b952f ·* of the index register, 1 for 32 bits, and 0 for 16 bits (sign-extended).
d119ab ·* The scale field is a left shift amount (0 to 3 bits) to apply to the
a2b50e ·* sign-extended index register. ·The final address is d8(An,Rn.X*SCALE),
a07d7f ·* also written (d8,An,Rn.X*SCALE). ·X is "W" or "L", SCALE is 1, 2, 4 or 8.
b091ce ·* "*1" may be omitted, as may a d8 of 0.
0e775e ·*
fcf931 ·* The 68000 supports this form, but only with a scale field of 0.
86d6b4 ·* It does NOT (says the MC68030 User's Manual MC68030UM/AD, section 2.7)
aa3feb ·* decode the scale field and the following format bit. ·They are treated
1d4219 ·* as 0.
cd2172 ·* I recall (I don't have the data book handy) that the CPU32 processor
fd96f9 ·* core used in the 683xx series processors supports variable scales,
8298f6 ·* but only the brief extension word form. ·I suspect it decodes the
8447ab ·* format bit and traps if it is not zero, but I don't recall.
72775e ·*
29b649 ·* The "full" form (680x0, x >= 2 processors only) looks like this:·
59775e ·*
b3a831 ·* 1 ··1 ··1 ··1 ··1 ··1 ··1 ·
751a9e ·* 6 ··5 ··4 ··3 ··2 ··1 ··0 ··9 ··8 ··7 ··6 ··5 ··4 ··3 ··2 ··1 ··0
392da3 ·* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
ace359 ·* |A/D| ·register |L/W| scale | 1 | BS| IS|BD size| 0 | P |OD size|
fa2da3 ·* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
37775e ·*
e30be5 ·* The first 8 bits are interpreted the same way as in the brief form,
c3f892 ·* except that bit 8 is set to 1 to indicate the full form.
627a8e ·* BS, Base Suppress, if set, causes a value of 0 to be used in place of
39aa1c ·* the base register value. ·If this is set, the base register
d15984 ·* specified is irrelevant, except that if it is the PC, the fetch is
a34ba3 ·* still done from program space. ·The specifier "ZPC" can be used in
a02466 ·* place of "PC" in the effective address mnemonic to represent this
9fa202 ·* case.
287c3d ·* IS, Index Suppress, if set, causes a value of 0 to be used in place
531d71 ·* of the scaled index register. In this case, the first 7 bits of the
a4f4e7 ·* extension word are irrelevant.
5baddf ·* BD size specifies the base displacement size. ·A value of 00
51718c ·* in this field is illegal, while 01, 10 and 11 indicate that the
0673ca ·* extension word is followed by 0, 1 or 2 16-bit words of base displacement
02059e ·* (zero, sign-extended to 32 bits, and most-significant word first,
c575df ·* respectively) to add to the base register value.
85dc00 ·* Bit 3 is unused.
8b6832 ·* The P bit is the pre/post indexing bit, and only applies if an outer
fa54b1 ·* displacement is used. ·This is explained later.
caa062 ·* OD size specifies the size of an outer displacement. ·In the simple
482f3e ·* case, this field is set to 00 and the effective address is
3337e0 ·* (disp,An,Rn.X*SCALE) or (disp,PC,Rn.X*SCALE).
24d039 ·* In this case the P bit must be 0. ·Any of those compnents may be
10bca6 ·* suppressed, with a BD size of 01, the BS bit, or the IS bit.
2a5f23 ·* If the OD size is not 00, it encodes an outer displacement in the same
23c51f ·* manner as the BD size, and 0, 1 or 2 16-bit words of outer displacement
68e629 ·* follow the base displacement in the instruction stream. ·In this case,
efc046 ·* this is a double-indirect addressing mode. ·The base, base displacement,
--8003 0018f80fb5940100156 Page 7 of bni68000.c
7ebfb8 ·* and possibly the index, specify a 32-bit memory word which holds a value
6a04ae ·* which is fetched, and the outer displacement and possibly the index are
c22522 ·* added to produce the address of the operand.
d00086 ·* If the P bit is 0, this is pre-indexed, and the index value is added
815c3e ·* before the fetch of the indirect word, producing an effective address
6092d1 ·* of ([disp,An,Rn.X*SCALE],disp). ·If the P bit is 1, the post-indexed case,
7e5b1d ·* the memory word is fectched from base+base displacement, then the index
48243f ·* and outer displacement are added to compute the address of the operand.
bf5993 ·* This effective address is written ([disp,An],Rn.X*SCALE,disp).
56aa8a ·* (In both cases, "An" may also be "PC" or "ZPC".)
892bc8 ·* Any of the components may be omitted. ·If the index is omitted (using the
5b4221 ·* IS bit), the P bit is irrelevant, but must be written as 0.
0d3f0e ·* Thus, legal combinations of IS, P and OD size are:
1d580b ·* 0 0 00 - (disp,An,Rn.X*SCALE), also written disp(An,Rn.X*SCALE)
db8a12 ·* 0 0 01 - ([disp,An,Rn.X*SCALE])
efb8d4 ·* 0 0 10 - ([disp,An,Rn.X*SCALE],d16)
d627f7 ·* 0 0 11 - ([disp,An,Rn.X*SCALE],d32)
d94983 ·* 0 1 01 - ([disp,An],Rn.X*SCALE)
dbaf5e ·* 0 1 10 - ([disp,An],Rn.X*SCALE,d16)
57307d ·* 0 1 11 - ([disp,An],Rn.X*SCALE,d32)
00d1e9 ·* 1 0 00 - (disp,An), also written disp(An)
16fb68 ·* 1 0 01 - ([disp,An])
cfbe57 ·* 1 0 10 - ([disp,An],d16)
313b16 ·* 1 0 11 - ([disp,An],d32)
e5ac65 ·*/·
10af5a
8f7b8e /* 45678901234567890123456789012345678901234567890123456789012345678901234567*/
--2d5c 00166d9598640100157 Page 1 of bni68000.h
bc38e5 /*
65b0c4 ·* bni68000.h - 16-bit bignum primitives for the 68000 (or 68010) processors.
97775e ·*
890acf ·* These primitives use little-endian word order.
84cd0d ·* (The order of bytes within words is irrelevant.)
e8775e ·*
fa55c0 ·* $Id: bni68000.h,v 1.2 1997/05/05 19:49:10 lloyd Exp $
8f495d ·*/
097be2 #define BN_LITTLE_ENDIAN 1
7eaf5a
c4e08e typedef unsigned short bnword16;
8c4434 #define BNWORD16 bnword16
afaf5a
6a99c6 PGP_BEGIN_C_DECLARATIONS
aaaf5a
96dfb9 bnword16 bniSub1_16(bnword16 *num, unsigned len, bnword16 borrow);
b49380 bnword16 bniAdd1_16(bnword16 *num, unsigned len, bnword16 carry);
35bf8b void bniMulN1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k);
fd7ce9 bnword16
5b8d05 bniMulAdd1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k);
597ce9 bnword16
31f1f7 bniMulSub1_16(bnword16 *out, bnword16 const *in, unsigned len, bnword16 k);
c7d961 bnword16 bniDiv21_16(bnword16 *q, bnword16 nh, bnword16 nl, bnword16 d);
2cbfec unsigned bniModQ_16(bnword16 const *n, unsigned len, bnword16 d);
23af5a
a0d443 int is68020(void);
6baf5a
b81254 PGP_END_C_DECLARATIONS
49af5a
41cf46 /* #define the values to exclude the C versions */
60b891 #define bniSub1_16 bniSub1_16
08e6a0 #define bniAdd1_16 bniAdd1_16
e5a1dd #define bniMulN1_16 bniMulN1_16
68a40c #define bniMulAdd1_16 bniMulAdd1_16
aad365 #define bniMulSub1_16 bniMulSub1_16
36d06f #define bniDiv21_16 bniDiv21_16
47ce8d #define bniModQ_16 bniModQ_16
f4af5a
f4ef49 /* Also include the 68020 definitions for 16/32 bit switching versions. */
6627e8 #include "bni68020.h"
--941d 000d9e4aede40100158 Page 1 of bni68020.c
bc38e5 /*
b37957 ·* bni68020.c - 32-bit bignum primitives for the 68020+ (0r 683xx) processors.
96775e ·*
edfbf7 ·* Written by Colin Plumb
6b775e ·*
713836 ·* $Id: bni68020.c,v 1.3 1997/05/13 01:18:46 mhw Exp $
e8775e ·*
6e4a32 ·* This was written for Metrowerks C, and while it should be reasonably
f6f81b ·* portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2.
b73093 ·* Some 680x0 compilers make d2 callee-save, so instructions to save it
cfa39f ·* will have to be added.
c29ec0 ·*·
2789e5 ·* This code supports 16 or 32-bit ints, based on UINT_MAX.
3d2625 ·* Regardless of UINT_MAX, only bignums up to 64K words (2 million bits)
206238 ·* are supported. ·(68k hackers will recognize this as a consequence of
ee5ae9 ·* using dbra.)
bf775e ·*
b0c307 ·* Under the Code Fragment Manager, different calling conventions apply.
6f5d23 ·* The called function pops its own arguments (unless it's variadic),
deba2d ·* and all arguments are passed in 4-byte-aligned stack slots, even
7b2f54 ·* if they're smaller that 4 bytes. ·Fortunately, this only requires
8a86f1 ·* minor hacking.
f6775e ·*
d70acf ·* These primitives use little-endian word order.
31ce5b ·* (The order of bytes within words is irrelevant to this issue.)
4d775e ·*
08bd02 ·* TODO: Schedule this for the 68040's pipeline. ·(When I get a 68040 manual.)
26495d ·*/
5aaf5a
9ea7a0 #include <limits.h>
81af5a
13a0c9 #include "bni.h" ·······/* Should include bni68020.h */
cfaf5a
8c38e5 /*
a02d22 ·* The Metrowerks C compiler (1.2.2) produces bad 68k code for the
1254aa ·* following input, which happens to be the inner loop of bniSub1,
a6922a ·* so a few less than critical routines have been recoded in assembly
e71e6c ·* to avoid the bug. ·(Optimizer on or off does not matter.)
fe9ec0 ·*·
6a18eb ·* unsigned
512bbf ·* decrement(unsigned *num, unsigned len)
2585a8 ·* {
7721bb ·* ·····do {
9a1247 ·* ·············if ((*num++)-- != 0)
0b102a ·* ·····················return 0;
56540b ·* ·····} while (--len);
397065 ·* ·····return 1;
a8d178 ·* }
bc495d ·*/
efef37 asm BNWORD32
c2371f bniSub1_32(BNWORD32 *num, unsigned len, BNWORD32 borrow)
f2bb36 {
9f28e2 ········movea.l 4(sp),a0 ·······/* num */
cc8a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
16047d ········move.l ·10(sp),d0 ······/* borrow */
7ddb21 #else
a09050 ········move.l ·12(sp),d0 ······/* borrow */
ce7454 #endif
75d8cf ········sub.l ··d0,(a0)+
b55431 ········bcc ············done
978a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
36e1e0 ········move.w ·8(sp),d0 ·······/* len */
84db21 #else
1d0e35 ········move.w ·10(sp),d0 ······/* len */
127454 #endif
32d830 ········subq.w ·#2,d0
dd2838 ········bcs ············done
fb3247 loop:
7f2fe4 ········subq.l ·#1,(a0)+
0bf464 ········dbcc ···d0,loop
f6b38c done:
d91557 ········moveq.l #0,d0
--f0ee 000098c456240100158 Page 2 of bni68020.c
0e4a30 ········addx.w ·d0,d0
218f76 #if GENERATINGCFM || defined(__CFM68K__)
e616ac ¤   ¤   rtd¤¤   #12
d8db21 #else
bee6d2 ········rts
da7454 #endif
c0efe6 }
10af5a
01ef37 asm BNWORD32
9a010f bniAdd1_32(BNWORD32 *num, unsigned len, BNWORD32 carry)
25bb36 {
0628e2 ········movea.l 4(sp),a0 ·······/* num */
fe8a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
ad563c ········move.l ·10(sp),d0 ······/* carry */
46db21 #else
1bf2ac ········move.l ·12(sp),d0 ······/* carry */
5b7454 #endif
e66745 ········add.l ··d0,(a0)+
1d5431 ········bcc ············done
058a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
d5e1e0 ········move.w ·8(sp),d0 ·······/* len */
f7db21 #else
900e35 ········move.w ·10(sp),d0 ······/* len */
567454 #endif
27d830 ········subq.w ·#2,d0
ee2838 ········bcs ············done
df3247 loop:
48906e ········addq.l ·#1,(a0)+
45f464 ········dbcc ···d0,loop
fab38c done:
a51557 ········moveq.l #0,d0
4c4a30 ········addx.w ·d0,d0
b28f76 #if GENERATINGCFM || defined(__CFM68K__)
ce16ac ¤   ¤   rtd¤¤   #12
17db21 #else
abe6d2 ········rts
f67454 #endif
f1efe6 }
27af5a
3860ee asm void
95924b bniMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
5fbb36 {
74fbe7 ········machine 68020
77508e ········
bae43f ········movem.l d3-d5,-(sp) ····/* 12 bytes of extra data */
ec7237 ········moveq.l #0,d4
8f2ae3 ········move.l ·16(sp),a1 ······/* out */
91415b ········move.l ·20(sp),a0 ······/* in */
dd8a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
cd4370 ········move.w ·24(sp),d5 ······/* len */
f3faee ········move.l ·26(sp),d2 ······/* k */
cadb21 #else
6a4b86 ········move.w ·26(sp),d5 ······/* len */
cbb867 ········move.l ·28(sp),d2 ······/* k */
c87454 #endif
d5af5a
0ef0c2 ········move.l ·(a0)+,d3 ·······/* First multiply */
18305b ········mulu.l ·d2,d1:d3 ·······/* dc.w ···0x4c02, 0x3401 */
a39544 ········move.l ·d3,(a1)+
3caf5a
ba6da3 ········subq.w ·#1,d5 ··········/* Setup for loop unrolling */
0760eb ········lsr.w ··#1,d5
e86126 ········bcs.s ··m32_even
9586e2 ········beq.s ··m32_short
7c508e ········
6ae695 ········subq.w ·#1,d5 ··········/* Set up software pipeline properly */
d4f920 ········move.l ·d1,d0
dd508e ········
d1696d m32_loop:
fa616a ········move.l ·(a0)+,d3
98305b ········mulu.l ·d2,d1:d3 ·······/* dc.w ···0x4c02, 0x3401 */
09dcdb ········add.l ··d0,d3
--2b3f 00041b8fe8140100158 Page 3 of bni68020.c
cc28a1 ········addx.l ·d4,d1
799544 ········move.l ·d3,(a1)+
21e01a m32_even:
9daf5a
cb616a ········move.l ·(a0)+,d3
a1a5c8 ········mulu.l ·d2,d0:d3 ·······/* dc.w ···0x4c02, 0x3400 */
66d79f ········add.l ··d1,d3
963179 ········addx.l ·d4,d0
c79544 ········move.l ·d3,(a1)+
52af5a
d22cb2 ········dbra ···d5,m32_loop
af508e ········
505d6e ········move.l ·d0,(a1)
da84f9 ········movem.l (sp)+,d3-d5
058f76 #if GENERATINGCFM || defined(__CFM68K__)
9b71cc ¤   ¤   rtd¤¤   #16
a3db21 #else
5fe6d2 ········rts
6a7454 #endif
523e85 m32_short:
5ec2bb ········move.l ·d1,(a1)
e584f9 ········movem.l (sp)+,d3-d5
5f8f76 #if GENERATINGCFM || defined(__CFM68K__)
5771cc ¤   ¤   rtd¤¤   #16
5bdb21 #else
52e6d2 ········rts
3b7454 #endif
5cefe6 }
63af5a
cfaf5a
51ef37 asm BNWORD32
619a19 bniMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
7bbb36 {
5dfbe7 ········machine 68020
7ce43f ········movem.l d3-d5,-(sp) ····/* 12 bytes of extra data */
a27237 ········moveq.l #0,d4
032ae3 ········move.l ·16(sp),a1 ······/* out */
b1415b ········move.l ·20(sp),a0 ······/* in */
858a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
b64370 ········move.w ·24(sp),d5 ······/* len */
07faee ········move.l ·26(sp),d2 ······/* k */
67db21 #else
844b86 ········move.w ·26(sp),d5 ······/* len */
f1b867 ········move.l ·28(sp),d2 ······/* k */
f07454 #endif
9baf5a
b8f0c2 ········move.l ·(a0)+,d3 ·······/* First multiply */
e7305b ········mulu.l ·d2,d1:d3 ·······/* dc.w ···0x4c02, 0x3401 */
5af12e ········add.l ··d3,(a1)+
6428a1 ········addx.l ·d4,d1
58af5a
1b6da3 ········subq.w ·#1,d5 ··········/* Setup for loop unrolling */
ec60eb ········lsr.w ··#1,d5
0de8da ········bcs.s ··ma32_even
d2edf5 ········beq.s ··ma32_short
50508e ········
9ee695 ········subq.w ·#1,d5 ··········/* Set up software pipeline properly */
0cf920 ········move.l ·d1,d0
87508e ········
792839 ma32_loop:
6c616a ········move.l ·(a0)+,d3
5f305b ········mulu.l ·d2,d1:d3 ·······/* dc.w ···0x4c02, 0x3401 */
aedcdb ········add.l ··d0,d3
0d28a1 ········addx.l ·d4,d1
aff12e ········add.l ··d3,(a1)+
fc28a1 ········addx.l ·d4,d1
f7a14e ma32_even:
d3af5a
4b616a ········move.l ·(a0)+,d3
2ca5c8 ········mulu.l ·d2,d0:d3 ·······/* dc.w ···0x4c02, 0x3400 */
d5d79f ········add.l ··d1,d3
413179 ········addx.l ·d4,d0
--3d6d 0009841a1d440100158 Page 4 of bni68020.c
c8f12e ········add.l ··d3,(a1)+
3d3179 ········addx.l ·d4,d0
c6af5a
bca410 ········dbra ···d5,ma32_loop
5a508e ········
6084f9 ········movem.l (sp)+,d3-d5
4f8f76 #if GENERATINGCFM || defined(__CFM68K__)
6371cc ¤   ¤   rtd¤¤   #16
68db21 #else
21e6d2 ········rts
f17454 #endif
a22a65 ma32_short:
b025ad ········move.l ·d1,d0 ··
6e84f9 ········movem.l (sp)+,d3-d5
dd8f76 #if GENERATINGCFM || defined(__CFM68K__)
fe71cc ¤   ¤   rtd¤¤   #16
54db21 #else
6ce6d2 ········rts
ea7454 #endif
98efe6 }
f5af5a
d2af5a
5bef37 asm BNWORD32
ed9796 bniMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
66bb36 {
62fbe7 ········machine 68020
98e43f ········movem.l d3-d5,-(sp) ····/* 12 bytes of extra data */
897237 ········moveq.l #0,d4
cd2ae3 ········move.l ·16(sp),a1 ······/* out */
a6415b ········move.l ·20(sp),a0 ······/* in */
278a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
d44370 ········move.w ·24(sp),d5 ······/* len */
9afaee ········move.l ·26(sp),d2 ······/* k */
28db21 #else
e24b86 ········move.w ·26(sp),d5 ······/* len */
74b867 ········move.l ·28(sp),d2 ······/* k */
df7454 #endif
01af5a
44f0c2 ········move.l ·(a0)+,d3 ·······/* First multiply */
30305b ········mulu.l ·d2,d1:d3 ·······/* dc.w ···0x4c02, 0x3401 */
9b4ea4 ········sub.l ··d3,(a1)+
3e28a1 ········addx.l ·d4,d1
e6af5a
4a6da3 ········subq.w ·#1,d5 ··········/* Setup for loop unrolling */
6d60eb ········lsr.w ··#1,d5
708cb4 ········bcs.s ··ms32_even
d867e9 ········beq.s ··ms32_short
18508e ········
c8e695 ········subq.w ·#1,d5 ··········/* Set up software pipeline properly */
7af920 ········move.l ·d1,d0
70508e ········
77a225 ms32_loop:
92616a ········move.l ·(a0)+,d3
42305b ········mulu.l ·d2,d1:d3 ·······/* dc.w ···0x4c02, 0x3401 */
2cdcdb ········add.l ··d0,d3
d828a1 ········addx.l ·d4,d1
0b4ea4 ········sub.l ··d3,(a1)+
c728a1 ········addx.l ·d4,d1
0f2b52 ms32_even:
a8af5a
9b616a ········move.l ·(a0)+,d3
e3a5c8 ········mulu.l ·d2,d0:d3 ·······/* dc.w ···0x4c02, 0x3400 */
09d79f ········add.l ··d1,d3
aa3179 ········addx.l ·d4,d0
df4ea4 ········sub.l ··d3,(a1)+
273179 ········addx.l ·d4,d0
d7af5a
9ec07e ········dbra ···d5,ms32_loop
e3508e ········
c484f9 ········movem.l (sp)+,d3-d5
c88f76 #if GENERATINGCFM || defined(__CFM68K__)
9871cc ¤   ¤   rtd¤¤   #16
--4b49 00146d5ac2e40100158 Page 5 of bni68020.c
0fdb21 #else
57e6d2 ········rts
dc7454 #endif
92508e ········
14f002 ms32_short:
cef920 ········move.l ·d1,d0
7e84f9 ········movem.l (sp)+,d3-d5
328f76 #if GENERATINGCFM || defined(__CFM68K__)
d571cc ¤   ¤   rtd¤¤   #16
c7db21 #else
2ce6d2 ········rts
da7454 #endif
fcefe6 }
6daf5a
adaf5a
dcef37 asm BNWORD32
757da9 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
d6bb36 {
acfbe7 ········machine 68020
746196 ········move.l ·8(sp),d0
c43304 ········move.l ·12(sp),d1
4b1804 ········move.l ·4(sp),a0
640e4d ········divu.l ·16(sp),d0:d1 ···/* ·dc.w ···0x4c6f, 0x1400, 16 */
419867 ········move.l ·d1,(a0)
d88f76 #if GENERATINGCFM || defined(__CFM68K__)
fd71cc ¤   ¤   rtd¤¤   #16
b2db21 #else
93e6d2 ········rts
fe7454 #endif
9cefe6 }
2aaf5a
325a82 asm unsigned
c4875c bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
9dbb36 {
0bfbe7 ········machine 68020
663ce6 ········move.l ·4(sp),a0 ·······/* n */
43cfcd ········move.l ·d3,a1
928a30 #if UINT_MAX == 0xffff && !GENERATINGCFM && !defined(__CFM68K__)
0626e7 ········moveq.l #0,d2
4b72a9 ········move.w ·8(sp),d1 ·······/* len */
c02934 ········move.w ·10(sp),d2 ······/* d */
5bdb21 #else
b0f6d2 ········move.w ·10(sp),d1 ······/* len */
454ad8 ········move.l ·12(sp),d2 ······/* d */
f77454 #endif
74352c ········dc.w ···0x41f0, 0x1cfc ·/* lea ·-4(a0,d1.L*4),a0 */
e8af5a
c08378 ¤   /* First time, divide 32/32 - may be faster than 64/32 */
c0d960 ········move.l ·(a0),d3
78d80f ········divul.l d2,d0:d3 ·······/* dc.w ···0x4c02, 0x3000 */
9ec1e8 ········subq.w ·#2,d1
90de73 ········bmi¤mq32_done
d8af5a
1afa6b mq32_loop:
8e46d1 ········move.l ·-(a0),d3
40733b ········divu.l ·d2,d0:d3 ·······/* dc.w ···0x4c02,0x3400 */
de195a ········dbra ···d1,mq32_loop ···
58ec2c ························
f07ba0 mq32_done:
09c7cf ········move.l ·a1,d3
368f76 #if GENERATINGCFM || defined(__CFM68K__)
df16ac ¤   ¤   rtd¤¤   #12
9cdb21 #else
a2e6d2 ········rts
7e7454 #endif
0defe6 }
70af5a
467b8e /* 45678901234567890123456789012345678901234567890123456789012345678901234567*/
--984e 0015d6e830840100159 Page 1 of bni68020.h
bc38e5 /*
3f271a ·* bni68020.h - 32-bit bignum primitives for the 68020 (or 683xx) processors.
cc775e ·*
220acf ·* These primitives use little-endian word order.
9dcd0d ·* (The order of bytes within words is irrelevant.)
19775e ·*
a4f4a2 ·* $Id: bni68020.h,v 1.2 1997/05/05 19:49:11 lloyd Exp $
20495d ·*/
a27be2 #define BN_LITTLE_ENDIAN 1
dbaf5a
ba69da typedef unsigned long bnword32;
6aca02 #define BNWORD32 bnword32
67af5a
1c99c6 PGP_BEGIN_C_DECLARATIONS
b1af5a
094760 bnword32 bniSub1_32(bnword32 *num, unsigned len, bnword32 borrow);
f4a3dc bnword32 bniAdd1_32(bnword32 *num, unsigned len, bnword32 carry);
869a07 void bniMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
33ae31 bnword32
fba889 bniMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
83ae31 bnword32
79d47b bniMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
ba63ee bnword32 bniDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
b1063c unsigned bniModQ_32(bnword32 const *n, unsigned len, unsigned d);
9eaf5a
821254 PGP_END_C_DECLARATIONS
58af5a
c0cf46 /* #define the values to exclude the C versions */
c88129 #define bniSub1_32 bniSub1_32
aadf18 #define bniAdd1_32 bniAdd1_32
6c10e8 #define bniMulN1_32 bniMulN1_32
c57ea8 #define bniMulAdd1_32 bniMulAdd1_32
9b09c1 #define bniMulSub1_32 bniMulSub1_32
0a615a #define bniDiv21_32 bniDiv21_32
5df735 #define bniModQ_32 bniModQ_32
--3809 0009e148dde4010015a Page 1 of bni80386.asm
fbd0e8 ;;; Assembly primitives for bignum library, 80386 family, 32-bit code.
92debf ;;;
d3b940 ;;; $Id: bni80386.asm,v 1.3 1997/09/19 06:20:35 colin Exp $
34debf ;;;
223bdc ;;; Several primitives are included here. ·Only bniMulAdd1 is *really*
ea6e89 ;;; critical, but once that's written, bniMulN1 and bniMulSub1 are quite
a2a220 ;;; easy to write as well, so they are included here as well.
e6800f ;;; bniDiv21 and bniModQ are so easy to write that they're included, too.
fddebf ;;;
5b9250 ;;; All functions here are for 32-bit flat mode. ·I.e. near code and
429f22 ;;; near data, although the near offsets are 32 bits.
21debf ;;;
b8a9ba ;;; The usual 80x86 calling conventions have AX, BX, CX and DX
bd74c2 ;;; volatile, and SI, DI, SP and BP preserved across calls.
ac40fc ;;; This includes the "E"xtended forms of all of those registers
0e68ee ;;;·
8f6779 ;;; However, just to be confusing, recent 32-bit DOS compilers have
55f97f ;;; quietly changed that to require EBX preserved across calls, too.
6a6204 ;;; Joy.
0caf5a
aa6552 .386
e07ead ;_TEXT ··segment para public use32 'CODE' ; 16-PGPByte aligned because 486 cares
3acb8f ;_TEXT¤ ends
19af5a
024672 ifdef @Version
dde339 if @Version le 510
c89fc1 FLAT¤   group¤  _TEXT
fdbfb9 endif
14523c else
de9fc1 FLAT¤   group¤  _TEXT
66bfb9 endif
ef73ac ¤   assume¤ cs:FLAT, ds:FLAT, ss:FLAT
fe61c7 _TEXT ··segment para public use32 'CODE' ; 16-PGPByte aligned because 486 cares
66af5a
bd6ef5 ¤   public ·_bniMulN1_32
6c65f8 ¤   public ·_bniMulAdd1_32
f30709 ¤   public ·_bniMulSub1_32
7ca3f1 ¤   public¤ _bniDiv21_32
8efac0 ¤   public¤ _bniModQ_32
d0af5a
f95ad9 ;; Register usage:
8d3c63 ;; eax - low half of product
367558 ;; ebx - carry to next iteration
b4704d ;; ecx - multiplier (k)
140ef0 ;; edx - high half of product
feb31b ;; esi - source pointer
31455f ;; edi - dest pointer
827b4c ;; ebp - loop counter
2b5258 ;;
7014cf ;; Stack frame:
9969b7 ;; +--------+ esp+20 ·esp+24 ·esp+28 ·esp+32 ·esp+36
cdec98 ;; | ···k ··|
18b826 ;; +--------+ esp+16 ·esp+20 ·esp+24 ·esp+28 ·esp+32
f84e1e ;; | ··len ·|
143bef ;; +--------+ esp+12 ·esp+16 ·esp+20 ·esp+24 ·esp+28
ae8aec ;; | ··in ··|
5f9629 ;; +--------+ esp+8 ··esp+12 ·esp+16 ·esp+20 ·esp+24
245c28 ;; | ··out ·|
14c18f ;; +--------+ esp+4 ··esp+8 ··esp+12 ·esp+16 ·esp+20
ecb7da ;; | return |
a631db ;; +--------+ esp ····esp+4 ··esp+8 ··esp+12 ·esp+16
d165b1 ;; | ··esi ·|
566e17 ;; +--------+ ········esp ····esp+4 ··esp+8 ··esp+12
b4c60e ;; | ··ebp ·|
5d13e5 ;; +--------+ ················esp ····esp+4 ··esp+8
749c2e ;; | ··ebx ·|
3fb75c ;; +--------+ ························esp ····esp+4
273bd0 ;; | ··edi ·|
d5a63f ;; +--------+ ································esp
34af5a
5a9fef ¤   align¤  16
9eaf1e _bniMulN1_32¤   proc¤   near
--73cc 000ef50f6b04010015a Page 2 of bni80386.asm
e0af5a
71f09a ¤   push¤   esi¤¤   ; U
dc1476 ¤   mov¤esi,[esp+12]¤   ; ·V¤   load in
554312 ¤   push¤   ebp¤¤   ; U
12dc3f ¤   mov¤ebp,[esp+20]¤   ; ·V¤   load len
d42a3b ¤   push¤   ebx¤¤   ; U
f9e25f ¤   mov¤ecx,[esp+28]¤   ; ·V¤   load k
2a2139 ¤   push¤   edi¤¤   ; U
a3c0a5 ¤   mov¤edi,[esp+20]¤   ; ·V¤   load out
d1af5a
ef16b9 ;; First multiply step has no carry in.
8c8189 ¤   mov¤eax,[esi]¤  ; U
a49f42 ¤   lea¤ebx,[ebp*4-4]¤  ; ·V¤   loop unrolling
fa6f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
b3d243 ¤   mov¤[edi],eax¤  ; U
a87c73 ¤   and¤ebx,12¤ ¤   ; ·V¤   loop unrolling
b0af5a
e78bdf ¤   add¤esi,ebx¤¤   ; U¤loop unrolling
b77822 ¤   add¤edi,ebx¤¤   ; ·V¤   loop unrolling
8faf5a
3279f4 ¤   jmp¤DWORD PTR m32_jumptable[ebx]¤   ; NP¤   loop unrolling
c9af5a
f6bb76 ¤   align¤  4
52bad8 m32_jumptable:
191284 ¤   dd¤ m32_case0
590b5c ¤   dd¤ m32_case1
362134 ¤   dd¤ m32_case2
1c38ec ¤   dd¤ m32_case3
e3af5a
c1ca0c ¤   nop
2712d6 ¤   align¤  8
bdca0c ¤   nop
a2ca0c ¤   nop
1592f6 ¤   nop¤; Get loop nicely aligned
c5af5a
119cd8 m32_case0:
030c43 ¤   sub¤ebp,4¤  ¤   ; U
00e616 ¤   jbe¤SHORT m32_done¤ ; ·V
58af5a
e0696d m32_loop:
34700e ¤   mov¤eax,[esi+4]¤; U
6b9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
22bdd6 ¤   add¤esi,16¤ ¤   ; U
c1c9d9 ¤   add¤edi,16¤ ¤   ; ·V
4f4ed8 ¤   mul¤ecx¤¤   ; NP
4df7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
83621c ¤   adc¤edx,0¤  ¤   ; U
cc25b0 ¤   mov¤[edi-12],eax¤   ; ·V
d573bc m32_case3:
00dc25 ¤   mov¤eax,[esi-8]¤; U
6d9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
024ed8 ¤   mul¤ecx¤¤   ; NP
1af7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
8e621c ¤   adc¤edx,0¤  ¤   ; U
a67c43 ¤   mov¤[edi-8],eax¤; ·V
6a2960 m32_case2:
2e6dbf ¤   mov¤eax,[esi-4]¤; U
599f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
a84ed8 ¤   mul¤ecx¤¤   ; NP
38f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
e4621c ¤   adc¤edx,0¤  ¤   ; U
7473d9 ¤   mov¤[edi-4],eax¤; ·V
24c604 m32_case1:
c28189 ¤   mov¤eax,[esi]¤  ; U
609f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
364ed8 ¤   mul¤ecx¤¤   ; NP
7cf7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
38621c ¤   adc¤edx,0¤  ¤   ; U
fd1959 ¤   mov¤[edi],eax¤  ; ·V
91af5a
8d0c43 ¤   sub¤ebp,4¤  ¤   ; U
efa948 ¤   ja¤ SHORT m32_loop¤ ; ·V
--df20 0000de2eb1d4010015a Page 3 of bni80386.asm
e0af5a
1be8a6 m32_done:
f3ebd4 ¤   mov¤[edi+4],edx¤; U
964a96 ¤   pop¤edi¤¤   ; ·V
239b00 ¤   pop¤ebx¤¤   ; U
24d525 ¤   pop¤ebp¤¤   ; ·V
6d41a1 ¤   pop¤esi¤¤   ; U
7b8622 ¤   ret¤¤   ¤   ; NP
c57a85 _bniMulN1_32¤   endp
33af5a
6aaf5a
009fef ¤   align¤  16
98d92f _bniMulAdd1_32¤ proc¤   near
1daf5a
01f09a ¤   push¤   esi¤¤   ; U
361476 ¤   mov¤esi,[esp+12]¤   ; ·V¤   load in
bc2139 ¤   push¤   edi¤¤   ; U
d136ea ¤   mov¤edi,[esp+12]¤   ; ·V¤   load out
e54312 ¤   push¤   ebp¤¤   ; U
adeb39 ¤   mov¤ebp,[esp+24]¤   ; ·V¤   load len
212a3b ¤   push¤   ebx¤¤   ; U
5a96ab ¤   mov¤ecx,[esp+32]¤   ; ·V¤   load k
5aaf5a
cd16b9 ;; First multiply step has no carry in.
b88189 ¤   mov¤eax,[esi]¤  ; U
483bde ¤   mov¤ebx,[edi]¤  ; ·V
0f6f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
94a715 ¤   add¤ebx,eax¤¤   ; U
ea680b ¤   lea¤eax,[ebp*4-4]¤  ; ·V¤   loop unrolling
3c621c ¤   adc¤edx,0¤  ¤   ; U
658e14 ¤   and¤eax,12¤ ¤   ; ·V¤   loop unrolling
960444 ¤   mov¤[edi],ebx¤  ; U
08af5a
6b91b0 ¤   add¤esi,eax¤¤   ; ·V¤   loop unrolling
e229f5 ¤   add¤edi,eax¤¤   ; U¤loop unrolling
7aaf5a
12a180 ¤   jmp¤DWORD PTR ma32_jumptable[eax]¤  ; NP¤   loop unrolling
43af5a
b6bb76 ¤   align¤  4
f9e8a6 ma32_jumptable:
a426db ¤   dd¤ ma32_case0
003f03 ¤   dd¤ ma32_case1
6a156b ¤   dd¤ ma32_case2
4c0cb3 ¤   dd¤ ma32_case3
69af5a
fcca0c ¤   nop
5e12d6 ¤   align¤  8
d1ca0c ¤   nop
50ca0c ¤   nop
b321db ¤   nop¤¤   ¤   ; To align loop properly
69af5a
2daf5a
fb8838 ma32_case0:
450c43 ¤   sub¤ebp,4¤  ¤   ; U
7f900f ¤   jbe¤SHORT ma32_done¤; ·V
e6af5a
db2839 ma32_loop:
a8700e ¤   mov¤eax,[esi+4]¤; U
649f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
f4bdd6 ¤   add¤esi,16¤ ¤   ; U
dbc9d9 ¤   add¤edi,16¤ ¤   ; ·V
cd4ed8 ¤   mul¤ecx¤¤   ; NP
bcf7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
1ab4e1 ¤   mov¤ebx,[edi-12]¤   ; ·V
d2621c ¤   adc¤edx,0¤  ¤   ; U
a82e9f ¤   add¤ebx,eax¤¤   ; ·V
55621c ¤   adc¤edx,0¤  ¤   ; U
59db03 ¤   mov¤[edi-12],ebx¤   ; ·V
ff675c ma32_case3:
27dc25 ¤   mov¤eax,[esi-8]¤; U
e99f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
0d4ed8 ¤   mul¤ecx¤¤   ; NP
--dd56 000bfcc54c34010015a Page 4 of bni80386.asm
05f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
e754e5 ¤   mov¤ebx,[edi-8]¤; ·V
6a621c ¤   adc¤edx,0¤  ¤   ; U
3a2e9f ¤   add¤ebx,eax¤¤   ; ·V
d6621c ¤   adc¤edx,0¤  ¤   ; U
71f693 ¤   mov¤[edi-8],ebx¤; ·V
433d80 ma32_case2:
fc6dbf ¤   mov¤eax,[esi-4]¤; U
749f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
8d4ed8 ¤   mul¤ecx¤¤   ; NP
58f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
6b6f87 ¤   mov¤ebx,[edi-4]¤; ·V
80621c ¤   adc¤edx,0¤  ¤   ; U
022e9f ¤   add¤ebx,eax¤¤   ; ·V
a8621c ¤   adc¤edx,0¤  ¤   ; U
42f909 ¤   mov¤[edi-4],ebx¤; ·V
57d2e4 ma32_case1:
d18189 ¤   mov¤eax,[esi]¤  ; U
009f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
864ed8 ¤   mul¤ecx¤¤   ; NP
61f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
e13bde ¤   mov¤ebx,[edi]¤  ; ·V
c6621c ¤   adc¤edx,0¤  ¤   ; U
692e9f ¤   add¤ebx,eax¤¤   ; ·V
71621c ¤   adc¤edx,0¤  ¤   ; U
0a6d30 ¤   mov¤[edi],ebx¤  ; ·V
5caf5a
840c43 ¤   sub¤ebp,4¤  ¤   ; U
694fe3 ¤   ja¤ SHORT ma32_loop¤; ·V
f2af5a
06a9f2 ma32_done:
eb9b00 ¤   pop¤ebx¤¤   ; U
14d525 ¤   pop¤ebp¤¤   ; ·V
3ad384 ¤   mov¤eax,edx¤¤   ; U
654a96 ¤   pop¤edi¤¤   ; ·V
0641a1 ¤   pop¤esi¤¤   ; U
c98622 ¤   ret¤¤   ¤   ; NP
63b430 _bniMulAdd1_32¤ endp
5eaf5a
c4af5a
339fef ¤   align¤  16
0fccb7 _bniMulSub1_32¤ proc¤   near
def09a ¤   push¤   esi¤¤   ; U
101476 ¤   mov¤esi,[esp+12]¤   ; ·V¤   load in
9b2139 ¤   push¤   edi¤¤   ; U
3d36ea ¤   mov¤edi,[esp+12]¤   ; ·V¤   load out
764312 ¤   push¤   ebp¤¤   ; U
caeb39 ¤   mov¤ebp,[esp+24]¤   ; ·V¤   load len
de2a3b ¤   push¤   ebx¤¤   ; U
8396ab ¤   mov¤ecx,[esp+32]¤   ; ·V¤   load k
98af5a
2616b9 ;; First multiply step has no carry in.
4ef09a ¤   push¤   esi¤¤   ; U
ae1476 ¤   mov¤esi,[esp+12]¤   ; ·V¤   load in
052139 ¤   push¤   edi¤¤   ; U
4936ea ¤   mov¤edi,[esp+12]¤   ; ·V¤   load out
9d4312 ¤   push¤   ebp¤¤   ; U
4deb39 ¤   mov¤ebp,[esp+24]¤   ; ·V¤   load len
efa47d ¤   mov¤ecx,[esp+28]¤   ; U¤load k
b7af5a
6816b9 ;; First multiply step has no carry in.
3b705c ¤   mov¤eax,[esi]¤  ; ·V
5d4f50 ¤   mov¤ebx,[edi]¤  ; U
016f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
b76125 ¤   sub¤ebx,eax¤¤   ; U
c0680b ¤   lea¤eax,[ebp*4-4]¤  ; ·V¤   loop unrolling
eb621c ¤   adc¤edx,0¤  ¤   ; U
918e14 ¤   and¤eax,12¤ ¤   ; ·V¤   loop unrolling
950444 ¤   mov¤[edi],ebx¤  ; U
a1af5a
4691b0 ¤   add¤esi,eax¤¤   ; ·V¤   loop unrolling
bf29f5 ¤   add¤edi,eax¤¤   ; U¤loop unrolling
--cddf 000026fce724010015a Page 5 of bni80386.asm
e0af5a
53ede7 ¤   jmp¤DWORD PTR ms32_jumptable[eax]¤  ; NP¤   loop unrolling
abaf5a
9ebb76 ¤   align¤  4
2ada16 ms32_jumptable:
e2acc7 ¤   dd¤ ms32_case0
b7b51f ¤   dd¤ ms32_case1
2b9f77 ¤   dd¤ ms32_case2
f086af ¤   dd¤ ms32_case3
79af5a
2bca0c ¤   nop
dd12d6 ¤   align¤  8
7fca0c ¤   nop
d4ca0c ¤   nop
93ca0c ¤   nop
11af5a
97525f ms32_case0:
510c43 ¤   sub¤ebp,4¤  ¤   ; U
31bb0c ¤   jbe¤SHORT ms32_done¤; ·V
b2af5a
26a225 ms32_loop:
7e700e ¤   mov¤eax,[esi+4]¤; U
f69f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
89bdd6 ¤   add¤esi,16¤ ¤   ; U
2cc9d9 ¤   add¤edi,16¤ ¤   ; ·V
594ed8 ¤   mul¤ecx¤¤   ; NP
adf7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
5eb4e1 ¤   mov¤ebx,[edi-12]¤   ; ·V
b3621c ¤   adc¤edx,0¤  ¤   ; U
ba1fda ¤   sub¤ebx,eax¤¤   ; ·V
d0621c ¤   adc¤edx,0¤  ¤   ; U
a5db03 ¤   mov¤[edi-12],ebx¤   ; ·V
debd3b ms32_case3:
05dc25 ¤   mov¤eax,[esi-8]¤; U
639f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
cb4ed8 ¤   mul¤ecx¤¤   ; NP
09f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
7e54e5 ¤   mov¤ebx,[edi-8]¤; ·V
1c621c ¤   adc¤edx,0¤  ¤   ; U
491fda ¤   sub¤ebx,eax¤¤   ; ·V
4c621c ¤   adc¤edx,0¤  ¤   ; U
2bf693 ¤   mov¤[edi-8],ebx¤; ·V
41e7e7 ms32_case2:
606dbf ¤   mov¤eax,[esi-4]¤; U
fc9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
594ed8 ¤   mul¤ecx¤¤   ; NP
f4f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
526f87 ¤   mov¤ebx,[edi-4]¤; ·V
cc621c ¤   adc¤edx,0¤  ¤   ; U
971fda ¤   sub¤ebx,eax¤¤   ; ·V
f5621c ¤   adc¤edx,0¤  ¤   ; U
42f909 ¤   mov¤[edi-4],ebx¤; ·V
540883 ms32_case1:
428189 ¤   mov¤eax,[esi]¤  ; U
649f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
3f4ed8 ¤   mul¤ecx¤¤   ; NP
92f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
a63bde ¤   mov¤ebx,[edi]¤  ; ·V
8a621c ¤   adc¤edx,0¤  ¤   ; U
b11fda ¤   sub¤ebx,eax¤¤   ; ·V
d2621c ¤   adc¤edx,0¤  ¤   ; U
256d30 ¤   mov¤[edi],ebx¤  ; ·V
77af5a
e30c43 ¤   sub¤ebp,4¤  ¤   ; U
6964e0 ¤   ja¤ SHORT ms32_loop¤; ·V
3caf5a
a723ee ms32_done:
b29b00 ¤   pop¤ebx¤¤   ; U
84d525 ¤   pop¤ebp¤¤   ; ·V
e0d384 ¤   mov¤eax,edx¤¤   ; U
084a96 ¤   pop¤edi¤¤   ; ·V
0241a1 ¤   pop¤esi¤¤   ; U
--979b 000cae8b8f24010015a Page 6 of bni80386.asm
228622 ¤   ret¤¤   ¤   ; NP
49c783 _bniMulSub1_32¤ endp
34af5a
c7af5a
8caf5a
d80e07 ;; Two-word by one-word divide. ·Stores quotient, returns remainder.
737dc5 ;; BNWORD32 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
bf35e9 ;; ·····················4 ···········8 ···········12 ··········16
133e09 align 4
a68f93 _bniDiv21_32¤   proc¤   near
b334c2 ¤   mov¤edx,[esp+8]¤¤   ; U¤Load nh
a5f246 ¤   mov¤eax,[esp+12]¤   ¤   ; ·V¤   Load nl
954950 ¤   mov¤ecx,[esp+4]¤¤   ; U¤Load q
343386 ¤   div¤DWORD PTR [esp+16]¤ ; NP
5e1080 ¤   mov¤[ecx],eax¤  ¤   ; U¤Store quotient
e843fa ¤   mov¤eax,edx¤¤   ¤   ; ·V¤   Return remainder
f58a83 ¤   ret
427cc3 _bniDiv21_32¤   endp
e0af5a
fedee8 ;; Multi-word by one-word remainder.
4dba42 ;; This speeds up key generation. ·It's not worth unrolling and so on;
2d4852 ;; using 32-bit divides is enough of a speedup.
f75258 ;;
04e943 ;; The modulus (in ebp) is often 16 bits. ·Given that the dividend is 32
3b3a0a ;; bits, the chances of saving the first divide because the high word of the
92ceea ;; dividend is less than the modulus are low enough it's not worth taking
52cce4 ;; the cycles to test for it.
b55258 ;;
16d236 ;; unsigned bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
fdb6d4 ;; ····················4 ·················8 ············12
c43e09 align 4
8dbe25 _bniModQ_32¤proc¤   near
35cdb8 ¤   mov¤eax,[esp+4]¤¤   ; U¤Load n
f9430c ¤   push¤   ebp¤¤   ¤   ; ·V
55dff4 ¤   mov¤ebp,[esp+12]¤   ¤   ; U¤Load len
13d728 ¤   push¤   esi¤¤   ¤   ; ·V
af9ad9 ¤   lea¤esi,[ebp*4+eax-4]¤  ; U
64ee42 ¤   mov¤ecx,[esp+20]¤   ¤   ; ·V¤   Load d
8dedb1 ¤   xor¤edx,edx¤¤   ¤   ; U¤Clear edx for first iteration
e50f74 modq32_loop:
73212c ¤   mov¤eax,[esi]¤  ¤   ; U¤Load new low word for divide
3e8ec3 ¤   sub¤esi,4¤  ¤   ¤   ; ·V
48c0a1 ¤   div¤ecx¤¤   ¤   ; NP¤   edx = edx:eax % ecx
f3850c ¤   dec¤ebp¤¤   ¤   ; U
5b2df5 ¤   jnz¤SHORT modq32_loop¤  ; ·V
daaf5a
b6b372 ¤   pop¤esi¤¤   ¤   ; U
a4e2cb ¤   mov¤eax,edx¤¤   ¤   ; ·V¤   Return remainder in eax
251ee2 ¤   pop¤ebp¤¤   ¤   ; U
891cd8 ¤   ret¤¤   ¤   ¤   ; NP
003d14 _bniModQ_32¤endp
15af5a
eaca22 ¤   movl¤   4(%esp),%eax¤   ¤   # U¤Load n
ff7957 ¤   pushl¤  %ebp¤   ¤   ¤   # ·V
3b4bbc ¤   movl¤   12(%esp),%ebp¤  ¤   # U¤Load len
046730 ¤   pushl¤  %esi¤   ¤   ¤   # ·V
4faa44 ¤   leal¤   -4(%eax,%ebp,4),%esi¤   # U
332000 ¤   movl¤   20(%esp),%ecx¤  ¤   # ·V¤   Load d
66b203 ¤   xorl¤   %edx,%edx¤  ¤   # U¤Clear MSW for first divide
d60f74 modq32_loop:
585e1e ¤   movl¤   (%esi),%eax¤¤   # U
3c8f3d ¤   subl¤   $4,%esi¤¤   ¤   # ·V
49240e ¤   divl¤   %ecx¤   ¤   ¤   # NP
0246ba ¤   decl¤   %ebp¤   ¤   ¤   # U
e180f4 ¤   jnz¤modq32_loop¤¤   # ·V
afaf5a
80bdfc ¤   popl¤   %esi¤   ¤   ¤   # U
bdf47f ¤   movl¤   %edx,%eax¤  ¤   # ·V
f02b02 ¤   popl¤   %ebp¤   ¤   ¤   # U
47f2b8 ¤   ret¤¤   ¤   ¤   # NP
a3af5a
ca6f03 _TEXT¤  ends
--1c97 0011d0cd6e04010015a Page 7 of bni80386.asm
e0af5a
1da234 ¤   end
--3c6c 0000c857a924010015b Page 1 of bni80386.h
bc38e5 /*
dc5ef9 ·* bni80386.h - This file defines the interfaces to the 80386
0d2b7e ·* assembly primitives. ·It is intended to be included in "bni.h"
897924 ·* via the "#include BNINCLUDE" mechanism.
9f775e ·*
b7cbe0 ·* $Id: bni80386.h,v 1.2 1997/05/05 19:49:11 lloyd Exp $
6a495d ·*/
0ed83c ·
767be2 #define BN_LITTLE_ENDIAN 1
1daf5a
ed69da typedef unsigned long bnword32;
e2ca02 #define BNWORD32 bnword32
3aaf5a
d3a5c8 /* MS-DOS needs the calling convention described to it. */
856756 #ifndef MSDOS
ed53a6 #ifdef __MSDOS
4ec3f7 #define MSDOS 1
837454 #endif
f67454 #endif
b86756 #ifndef MSDOS
9cde0a #ifdef __MSDOS__
c7c3f7 #define MSDOS 1
da7454 #endif
0b7454 #endif
b3af5a
cfa502 /* By MS-DOS, we mean 16-bit brain-dead MS-DOS. ·Not 32-bit good things. */
b8b053 #ifdef __GO32
d99682 #undef MSDOS
aa7454 #endif
9c092f #ifdef __GO32__
0e9682 #undef MSDOS
eb7454 #endif
d2af5a
ec306a #ifdef MSDOS
6c294a #define CDECL __cdecl
b4db21 #else
ecb021 #define CDECL /*nothing*/
897454 #endif
c7af5a
ed3379 #ifdef __cplusplus
3d8078 /* These assembly-language primitives use C names */
1d6dad extern "C" {
067454 #endif
bfaf5a
6d849a /* Function prototypes for the asm routines */
724d6e void CDECL
66d916 bniMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
a510e8 #define bniMulN1_32 bniMulN1_32
43caf9 ············
4ff1a3 bnword32 CDECL
b1a889 bniMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
797ea8 #define bniMulAdd1_32 bniMulAdd1_32
c07516 ·······
cdf1a3 bnword32 CDECL
53d47b bniMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
fb09c1 #define bniMulSub1_32 bniMulSub1_32
d9af5a
b2f1a3 bnword32 CDECL
363aba bniDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
30615a #define bniDiv21_32 bniDiv21_32
7aaf5a
6c67cf unsigned CDECL
6389e1 bniModQ_32(bnword32 const *n, unsigned len, bnword32 d);
b7f735 #define bniModQ_32 bniModQ_32
d7af5a
f51254 PGP_END_C_DECLARATIONS
4daf5a
48af5a
e653f7 #if __GNUC__
ff38e5 /*
912378 ·* Use the (massively cool) GNU inline-assembler extension to define
0c131a ·* inline expansions for various operations.
--eea0 001866561ed4010015b Page 2 of bni80386.h
4f775e ·*
23cf8e ·* The massively cool part is that the assembler can have inputs
81f904 ·* and outputs, and you specify the operands and which effective
b575a3 ·* addresses are legal and they get substituted into the code.
7de987 ·* (For example, some of the code requires a zero. ·Rather than
46c604 ·* specify an immediate constant, the expansion specifies an operand
385402 ·* of zero which can be in various places. ·This lets GCC use an
50a0ce ·* immediate zero, or a register which contains zero if it's available.)
07775e ·*
730b46 ·* The syntax is asm("asm_code" : outputs : inputs : trashed)
820148 ·* %0, %1 and so on in the asm code are substituted by the operands
e6b8cd ·* in left-to-right order (outputs, then inputs).
b00057 ·* The operands contain constraint strings and values to use.
51f79b ·* Outputs must be lvalues, inputs may be rvalues. ·In the constraints:
eaa684 ·* "a" means that the operand must be in eax.
26f0ed ·* "d" means that the operand must be in edx.
e721c0 ·* "g" means that the operand may be any effective address.
13d967 ·* "=" means that the operand is assigned to.
f2ef4a ·* "%" means that this operand and the following one may be
81d6fe ·* ····interchanged if desirable.
9ced2e ·* "bcDSmn" means that the operand must be in ebx, ecx, esi, edi, memory,
19aad8 ·* ·········or an immediate constant. ·(This is almost the same as "g"
a2d7b5 ·* ·········but allowing it in eax wouldn't help because x is already
e30b34 ·* ·········assigned there, and it must not be in edx, since edx is
05bbe7 ·* ·········overwritten by the multiply before a and b are read.)
f3775e ·*
621b3f ·* Note that GCC uses AT&T assembler syntax, which is rather
53fbe4 ·* different from Intel syntax. ·The length (b, w or l) of the
af562b ·* operation is appended to the opcode, and the *second* operand
e34598 ·* is the destination, not the first. ·Finally, the register names
d119ef ·* are all preceded with "%". ·(Doubled here because % is a
c98d60 ·* magic character.)
c5495d ·*/
65af5a
3117b2 /* (ph<<32) + pl = x*y */
8f9369 #define mul32_ppmm(ph,pl,x,y)¤  \
4c7a53 ¤   __asm__("mull %3" : "=d"(ph), "=a"(pl) : "%a"(x), "g"(y))
43af5a
cde5ca /* (ph<<32) + pl = x*y + a */
1a2073 #define mul32_ppmma(ph,pl,x,y,a)¤   \
04ce72 ¤   __asm__("mull %3\n\t"¤  ¤   \
8cdeb2 ¤   ········"addl %4,%%eax\n\t"¤\
fe15a5 ¤   ········"adcl %5,%%edx"¤¤   \
86b601 ¤   ········: "=&d"(ph), "=a"(pl)¤  \
9ffbaf ¤   ········: "%a"(x), "g"(y), "bcDSmn"(a), "bcDSmn"(0))
58af5a
c97e17 /* (ph<<32) + pl = x*y + a + b */
91972a #define mul32_ppmmaa(ph,pl,x,y,a,b)¤\
36ce72 ¤   __asm__("mull %3\n\t"¤  ¤   \
76deb2 ¤   ········"addl %4,%%eax\n\t"¤\
a23291 ¤   ········"adcl %6,%%edx\n\t"¤\
549698 ¤   ········"addl %5,%%eax\n\t"¤\
76cddb ¤   ········"adcl %6,%%edx"¤¤   \
93b601 ¤   ········: "=&d"(ph), "=a"(pl)¤  \
364754 ¤   ········: "%a"(x), "g"(y), "%bcDSmn"(a), "bcDSmn"(b), "bcDSmn"(0))
f6af5a
dcf64a /* q = ((nh<<32) + nl) / d, return remainder. ·nh guaranteed < d. */
1f2005 #undef bniDiv21_32
4678ed #define bniDiv21_32(q,nh,nl,d)¤ \
987c4b ¤   ({unsigned _;¤  \
cce3f8 ¤   ··__asm__("divl %4" : "=d"(_), "=a"(*q)¤: "d"(nh), "a"(nl), "g"(d)); \
503dfb ¤   ··_;})
b9af5a
28cd85 /* No quotient, just return remainder ((nh<<32) + nl) % d */
3214ec #define bniMod21_32(nh,nl,d)¤   \
067c4b ¤   ({unsigned _;¤  \
6650ca ¤   ··__asm__("divl %3" : "=d"(_) : "d"(nh), "a"(nl), "g"(d) : "ax"); \
a33dfb ¤   ··_;})
c4af5a
86a5dc #endif /* __GNUC__ */
--3f93 00045a180b54010015c Page 1 of bni80386.s
e0af5a
b6784f ### Assembly primitives for bignum library, 80386 family, 32-bit code.
e4e0c0 ###
93b5a7 ### $Id: bni80386.s,v 1.2 1998/07/31 22:03:36 hal Exp $
73e0c0 ###
39937b ### Several primitives are included here. ·Only bniMulAdd1 is *really*
6102b0 ### critical, but once that's written, lnmMulN1 and bniMulSub1 are quite
590371 ### easy to write as well, so they are included here as well.
d262e2 ### bniDiv21 and bniModQ are so easy to write that they're included, too.
e0e0c0 ###
9bfba3 ### All functions here are for 32-bit flat mode. ·I.e. near code and
a52cfb ### near data, although the near offsets are 32 bits.
0967af ### Preserved registers are esp, ebp, esi, edi and ebx. ·That last
73e6fd ### is needed by ELF for PIC, and differs from the IBM PC calling
b64233 ### convention.
c8af5a
6c36a2 # Different assemblers have different conventions here
cb3a42 # These conventions are for ELF assembler
1264fc align4=4¤   # could be 2 or 4
be39b7 align8=8¤   # could be 3 or 8
9820da align16=16¤ # cound be 4 or 16
43af5a
ffaf5a
c10d76 .text
6faf5a
c588a3 # We declare each symbol with two names, to deal with ELF/a.out variances.
cad3a9 ¤   .globl¤ bniMulN1_32
1335df ¤   .globl¤ _bniMulN1_32
d571c1 ¤   .globl¤ bniMulAdd1_32
8157ed ¤   .globl¤ _bniMulAdd1_32
061330 ¤   .globl¤ bniMulSub1_32
3a351c ¤   .globl¤ _bniMulSub1_32
8d29ef ¤   .globl¤ bniDiv21_32
5fcf99 ¤   .globl¤ _bniDiv21_32
f29cae ¤   .globl¤ bniModQ_32
f0ec5f ¤   .globl¤ _bniModQ_32
02af5a
3f951c ## Register usage:
8bf1b2 ## %eax - low half of product
26647e ## %ebx - carry to next iteration
1099e2 ## %ecx - multiplier (k)
c9c939 ## %edx - high half of product
b15ab4 ## %esi - source pointer
b7fef8 ## %edi - dest pointer
bac0eb ## %ebp - loop counter
6a4a5e ##
781615 ## Stack frame:
790c23 ## +--------+ %esp+20 ·%esp+24 ·%esp+28 ·%esp+32 ·%esp+36
48a294 ## | ···k ··|
a09365 ## +--------+ %esp+16 ·%esp+20 ·%esp+24 ·%esp+28 ·%esp+32
ef0012 ## | ··len ·|
ca6fce ## +--------+ %esp+12 ·%esp+16 ·%esp+20 ·%esp+24 ·%esp+28
38c4e0 ## | ··in ··|
a65273 ## +--------+ %esp+8 ··%esp+12 ·%esp+16 ·%esp+20 ·%esp+24
ce1224 ## | ··out ·|
2baa8c ## +--------+ %esp+4 ··%esp+8 ··%esp+12 ·%esp+16 ·%esp+20
1ef9d6 ## | return |
888805 ## +--------+ %esp ····%esp+4 ··%esp+8 ··%esp+12 ·%esp+16
bfb048 ## | ·%esi ·|
78d912 ## +--------+ ·········%esp ····%esp+4 ··%esp+8 ··%esp+12
5d13f7 ## | ·%ebp ·|
16e11a ## +--------+ ··················%esp ····%esp+4 ··%esp+8
3949d7 ## | ·%ebx ·|
a4afc0 ## +--------+ ···························%esp ····%esp+4
b0ee29 ## | ·%edi ·|
31271a ## +--------+ ····································%esp
63af5a
012996 ¤   .align¤ align16
2a9951 bniMulN1_32:
e3930d _bniMulN1_32:
a1de4a ¤   pushl¤  %esi¤   ¤   # U
452cec ¤   movl¤   12(%esp),%esi¤  # ·V¤   load in
--e5cf 000065037624010015c Page 2 of bni80386.s
6c0462 ¤   pushl¤  %ebp¤   ¤   # U
096f78 ¤   movl¤   20(%esp),%ebp¤  # ·V¤   load len
34290a ¤   pushl¤  %ebx¤   ¤   # U
37ebba ¤   movl¤   28(%esp),%ecx¤  # ·V¤   load k
45781a ¤   pushl¤  %edi¤   ¤   # U
74a2d2 ¤   movl¤   20(%esp),%edi¤  # ·V¤   load out
3daf5a
034d3f ## First multiply step has no carry in.
9190b5 ¤   movl¤   (%esi),%eax¤¤   # ·V
15b783 ¤   leal¤   -4(,%ebp,4),%ebx¤   # U¤loop unrolling
741a00 ¤   mull¤   %ecx¤   ¤   ¤   # NP¤   first multiply
8d8175 ¤   movl¤   %eax,(%edi)¤¤   # U
37a1e5 ¤   andl¤   $12,%ebx¤   ¤   # ·V¤   loop unrolling
75af5a
1c114d ¤   addl¤   %ebx,%esi¤  ¤   # U¤loop unrolling
97df77 ¤   addl¤   %ebx,%edi¤  ¤   # ·V¤   loop unrolling
00af5a
877730 ¤   jmp¤*m32_jumptable(%ebx)¤   # NP¤   loop unrolling
28af5a
9f51f5 ¤   .align¤ align4
d8bad8 m32_jumptable:
d1ca92 ¤   .long¤  m32_case0
f0d34a ¤   .long¤  m32_case1
caf922 ¤   .long¤  m32_case2
36e0fa ¤   .long¤  m32_case3
1faf5a
97ca0c ¤   nop
50f855 ¤   .align¤ align8
77ca0c ¤   nop
eeca0c ¤   nop
ae7ddc ¤   nop¤# Get loop nicely aligned
b6af5a
9c9cd8 m32_case0:
e089b4 ¤   subl¤   $4,%ebp¤¤   # U
d0e9fe ¤   jbe¤m32_done¤   # ·V
6eaf5a
07696d m32_loop:
cf6aae ¤   movl¤   4(%esi),%eax¤   # U
d2d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
d039ba ¤   addl¤   $16,%esi¤   # U
0aa25f ¤   addl¤   $16,%edi¤   # ·V
f9de86 ¤   mull¤   %ecx¤   ¤   # NP
eb7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
76eb42 ¤   adcl¤   $0,%edx¤¤   # U
c632a1 ¤   movl¤   %eax,-12(%edi)¤ # ·V
e073bc m32_case3:
c7f797 ¤   movl¤   -8(%esi),%eax¤  # U
10d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
80de86 ¤   mull¤   %ecx¤   ¤   # NP
927d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
e5eb42 ¤   adcl¤   $0,%edx¤¤   # U
bf58bc ¤   movl¤   %eax,-8(%edi)¤  # ·V
642960 m32_case2:
c2109d ¤   movl¤   -4(%esi),%eax¤  # U
c9d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
37de86 ¤   mull¤   %ecx¤   ¤   # NP
497d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
9feb42 ¤   adcl¤   $0,%edx¤¤   # U
e62177 ¤   movl¤   %eax,-4(%edi)¤  # ·V
66c604 m32_case1:
535343 ¤   movl¤   (%esi),%eax¤# U
87d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
5bde86 ¤   mull¤   %ecx¤   ¤   # NP
ee7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
eeeb42 ¤   adcl¤   $0,%edx¤¤   # U
34db73 ¤   movl¤   %eax,(%edi)¤# ·V
01af5a
8f89b4 ¤   subl¤   $4,%ebp¤¤   # U
3652a2 ¤   ja¤ m32_loop¤   # ·V
6faf5a
fae8a6 m32_done:
06f236 ¤   movl¤   %edx,4(%edi)¤   # U
--9fca 0002733e8cb4010015c Page 3 of bni80386.s
65d6f4 ¤   popl¤   %edi¤   ¤   # ·V
a06a0a ¤   popl¤   %ebx¤   ¤   # U
572947 ¤   popl¤   %ebp¤   ¤   # ·V
f09d4a ¤   popl¤   %esi¤   ¤   # U
206842 ¤   ret¤¤   ¤   # NP
23af5a
65af5a
012996 ¤   .align¤ align16
4fd479 bniMulAdd1_32:
140174 _bniMulAdd1_32:
c6af5a
b1de4a ¤   pushl¤  %esi¤   ¤   # U
ff2cec ¤   movl¤   12(%esp),%esi¤  # ·V¤   load in
c4781a ¤   pushl¤  %edi¤   ¤   # U
b08cb3 ¤   movl¤   12(%esp),%edi¤  # ·V¤   load out
a50462 ¤   pushl¤  %ebp¤   ¤   # U
4fbae1 ¤   movl¤   24(%esp),%ebp¤  # ·V¤   load len
2b290a ¤   pushl¤  %ebx¤   ¤   # U
fb60e1 ¤   movl¤   32(%esp),%ecx¤  # ·V¤   load k
68af5a
d74d3f ## First multiply step has no carry in.
ce90b5 ¤   movl¤   (%esi),%eax¤¤   # ·V
4cd861 ¤   movl¤   (%edi),%ebx¤¤   # U
941a00 ¤   mull¤   %ecx¤   ¤   ¤   # NP¤   first multiply
f694ac ¤   addl¤   %eax,%ebx¤  ¤   # U
3c92c8 ¤   leal¤   -4(,%ebp,4),%eax¤   # ·V¤   loop unrolling
cc0e25 ¤   adcl¤   $0,%edx¤¤   ¤   # U
cf6140 ¤   andl¤   $12,%eax¤   ¤   # ·V¤   loop unrolling
5a804d ¤   movl¤   %ebx,(%edi)¤¤   # U
62af5a
981bef ¤   addl¤   %eax,%esi¤  ¤   # ·V¤   loop unrolling
ae2abc ¤   addl¤   %eax,%edi¤  ¤   # U¤loop unrolling
dbaf5a
dd4c6d ¤   jmp¤*ma32_jumptable(%eax)¤  # NP¤   loop unrolling
eaaf5a
c951f5 ¤   .align¤ align4
1be8a6 ma32_jumptable:
0153b4 ¤   .long¤  ma32_case0
8c4a6c ¤   .long¤  ma32_case1
676004 ¤   .long¤  ma32_case2
2379dc ¤   .long¤  ma32_case3
87af5a
93f855 ¤   .align¤ align8
46ca0c ¤   nop
a8ca0c ¤   nop
cb45b3 ¤   nop¤¤   ¤   # To align loop properly
6daf5a
e4af5a
b68838 ma32_case0:
ed89b4 ¤   subl¤   $4,%ebp¤¤   # U
c1bdc6 ¤   jbe¤ma32_done¤  # ·V
08af5a
5f2839 ma32_loop:
786aae ¤   movl¤   4(%esi),%eax¤   # U
a5d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
bb39ba ¤   addl¤   $16,%esi¤   # U
25a25f ¤   addl¤   $16,%edi¤   # ·V
9dde86 ¤   mull¤   %ecx¤   ¤   # NP
7d7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
6299fa ¤   movl¤   -12(%edi),%ebx¤ # ·V
e7eb42 ¤   adcl¤   $0,%edx¤¤   # U
fd756f ¤   addl¤   %eax,%ebx¤  # ·V
baeb42 ¤   adcl¤   $0,%edx¤¤   # U
b98f6b ¤   movl¤   %ebx,-12(%edi)¤ # ·V
d3675c ma32_case3:
3cf797 ¤   movl¤   -8(%esi),%eax¤  # U
e5d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
f4de86 ¤   mull¤   %ecx¤   ¤   # NP
c07d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
37ee77 ¤   movl¤   -8(%edi),%ebx¤  # ·V
a3eb42 ¤   adcl¤   $0,%edx¤¤   # U
27756f ¤   addl¤   %eax,%ebx¤  # ·V
--4a39 00085f596c84010015c Page 4 of bni80386.s
b2eb42 ¤   adcl¤   $0,%edx¤¤   # U
d6e576 ¤   movl¤   %ebx,-8(%edi)¤  # ·V
fc3d80 ma32_case2:
86109d ¤   movl¤   -4(%esi),%eax¤  # U
4ad5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
4cde86 ¤   mull¤   %ecx¤   ¤   # NP
217d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
9a41ca ¤   movl¤   -4(%edi),%ebx¤  # ·V
95eb42 ¤   adcl¤   $0,%edx¤¤   # U
92756f ¤   addl¤   %eax,%ebx¤  # ·V
a3eb42 ¤   adcl¤   $0,%edx¤¤   # U
219cbd ¤   movl¤   %ebx,-4(%edi)¤  # ·V
42d2e4 ma32_case1:
8b5343 ¤   movl¤   (%esi),%eax¤# U
e3d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
fade86 ¤   mull¤   %ecx¤   ¤   # NP
fb7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
3a3558 ¤   movl¤   (%edi),%ebx¤# ·V
65eb42 ¤   adcl¤   $0,%edx¤¤   # U
95756f ¤   addl¤   %eax,%ebx¤  # ·V
c7eb42 ¤   adcl¤   $0,%edx¤¤   # U
d3030d ¤   movl¤   %ebx,(%edi)¤# ·V
01af5a
8689b4 ¤   subl¤   $4,%ebp¤¤   # U
799bcd ¤   ja¤ ma32_loop¤  # ·V
42af5a
d5a9f2 ma32_done:
a06a0a ¤   popl¤   %ebx¤   ¤   # U
ae2947 ¤   popl¤   %ebp¤   ¤   # ·V
310d1c ¤   movl¤   %edx,%eax¤  # U
b3d6f4 ¤   popl¤   %edi¤   ¤   # ·V
ab9d4a ¤   popl¤   %esi¤   ¤   # U
ce6842 ¤   ret¤¤   ¤   # NP
c0af5a
81af5a
8e2996 ¤   .align¤ align16
d8321d bniMulSub1_32:
5be710 _bniMulSub1_32:
cfde4a ¤   pushl¤  %esi¤   ¤   # U
d62cec ¤   movl¤   12(%esp),%esi¤  # ·V¤   load in
37781a ¤   pushl¤  %edi¤   ¤   # U
898cb3 ¤   movl¤   12(%esp),%edi¤  # ·V¤   load out
850462 ¤   pushl¤  %ebp¤   ¤   # U
17bae1 ¤   movl¤   24(%esp),%ebp¤  # ·V¤   load len
e4290a ¤   pushl¤  %ebx¤   ¤   # U
6060e1 ¤   movl¤   32(%esp),%ecx¤  # ·V¤   load k
35af5a
8a58e1 /* First multiply step has no carry in. */
1490b5 ¤   movl¤   (%esi),%eax¤¤   # ·V
4ed861 ¤   movl¤   (%edi),%ebx¤¤   # U
e21a00 ¤   mull¤   %ecx¤   ¤   ¤   # NP¤   first multiply
0060f2 ¤   subl¤   %eax,%ebx¤  ¤   # U
0b92c8 ¤   leal¤   -4(,%ebp,4),%eax¤   # ·V¤   loop unrolling
f00e25 ¤   adcl¤   $0,%edx¤¤   ¤   # U
0c6140 ¤   andl¤   $12,%eax¤   ¤   # ·V¤   loop unrolling
05804d ¤   movl¤   %ebx,(%edi)¤¤   # U
73af5a
551bef ¤   addl¤   %eax,%esi¤  ¤   # ·V¤   loop unrolling
282abc ¤   addl¤   %eax,%edi¤  ¤   # U¤loop unrolling
97af5a
b55b98 ¤   jmp¤*ms32_jumptable(%eax)¤  # NP¤   loop unrolling
11af5a
f151f5 ¤   .align¤ align4
16da16 ms32_jumptable:
f4d9a8 ¤   .long¤  ms32_case0
23c070 ¤   .long¤  ms32_case1
aaea18 ¤   .long¤  ms32_case2
bcf3c0 ¤   .long¤  ms32_case3
55af5a
c5f855 ¤   .align¤ align8
4bca0c ¤   nop
85ca0c ¤   nop
--e397 00019e8e62b4010015c Page 5 of bni80386.s
70ca0c ¤   nop
83af5a
49525f ms32_case0:
6289b4 ¤   subl¤   $4,%ebp¤¤   # U
4d087f ¤   jbe¤ms32_done¤  # ·V
65af5a
63a225 ms32_loop:
7c6aae ¤   movl¤   4(%esi),%eax¤   # U
a9d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
fd39ba ¤   addl¤   $16,%esi¤   # U
3da25f ¤   addl¤   $16,%edi¤   # ·V
0ade86 ¤   mull¤   %ecx¤   ¤   # NP
4e7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
cf99fa ¤   movl¤   -12(%edi),%ebx¤ # ·V
cdeb42 ¤   adcl¤   $0,%edx¤¤   # U
4ed1fd ¤   subl¤   %eax,%ebx¤  # ·V
16eb42 ¤   adcl¤   $0,%edx¤¤   # U
3c8f6b ¤   movl¤   %ebx,-12(%edi)¤ # ·V
97bd3b ms32_case3:
caf797 ¤   movl¤   -8(%esi),%eax¤  # U
f1d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
7ede86 ¤   mull¤   %ecx¤   ¤   # NP
e57d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
39ee77 ¤   movl¤   -8(%edi),%ebx¤  # ·V
03eb42 ¤   adcl¤   $0,%edx¤¤   # U
c0d1fd ¤   subl¤   %eax,%ebx¤  # ·V
a7eb42 ¤   adcl¤   $0,%edx¤¤   # U
65e576 ¤   movl¤   %ebx,-8(%edi)¤  # ·V
2be7e7 ms32_case2:
55109d ¤   movl¤   -4(%esi),%eax¤  # U
07d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
abde86 ¤   mull¤   %ecx¤   ¤   # NP
ba7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
c941ca ¤   movl¤   -4(%edi),%ebx¤  # ·V
4eeb42 ¤   adcl¤   $0,%edx¤¤   # U
f9d1fd ¤   subl¤   %eax,%ebx¤  # ·V
90eb42 ¤   adcl¤   $0,%edx¤¤   # U
6d9cbd ¤   movl¤   %ebx,-4(%edi)¤  # ·V
120883 ms32_case1:
9c5343 ¤   movl¤   (%esi),%eax¤# U
3fd5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
22de86 ¤   mull¤   %ecx¤   ¤   # NP
357d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
023558 ¤   movl¤   (%edi),%ebx¤# ·V
4feb42 ¤   adcl¤   $0,%edx¤¤   # U
ecd1fd ¤   subl¤   %eax,%ebx¤  # ·V
12eb42 ¤   adcl¤   $0,%edx¤¤   # U
ca030d ¤   movl¤   %ebx,(%edi)¤# ·V
c4af5a
6f89b4 ¤   subl¤   $4,%ebp¤¤   # U
792e74 ¤   ja¤ ms32_loop¤  # ·V
e1af5a
1023ee ms32_done:
576a0a ¤   popl¤   %ebx¤   ¤   # U
8a2947 ¤   popl¤   %ebp¤   ¤   # ·V
0f0d1c ¤   movl¤   %edx,%eax¤  # U
31d6f4 ¤   popl¤   %edi¤   ¤   # ·V
2c9d4a ¤   popl¤   %esi¤   ¤   # U
a76842 ¤   ret¤¤   ¤   # NP
7aaf5a
71e097 ## Two-word by one-word divide. ·Stores quotient, returns remainder.
567089 ## BNWORD32 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
40722a ## ·····················4 ···········8 ···········12 ··········16
e2af5a
2f160e ¤   .align align16
aabe99 bniDiv21_32:
99b4c5 _bniDiv21_32:
93c2af ¤   movl¤   8(%esp),%edx¤   # U¤Load nh
cb6769 ¤   movl¤   12(%esp),%eax¤  # ·V¤   Load nl
a266bd ¤   movl¤   4(%esp),%ecx¤   # U¤Load q
c8ffa2 ¤   divl¤   16(%esp)¤   # NP
19a20d ¤   movl¤   %eax,(%ecx)¤# U¤Store quotient
--2050 001f52d39cc4010015c Page 6 of bni80386.s
392724 ¤   movl¤   %edx,%eax¤  # ·V¤   Return remainder
d88a83 ¤   ret
54af5a
9d0779 ## Multi-word by one-word remainder.
fead6f ## This speeds up key generation. ·It's not worth unrolling and so on;
d39a4c ## using 32-bit divides is enough of a speedup.
a94a5e ##
febf8d ## The modulus (in %ebp) is often 16 bits. ·Given that the dividend is 32
cb0e29 ## bits, the chances of saving the first divide because the high word of the
32ea37 ## dividend is less than the modulus are low enough it's not worth taking
5fc66f ## the cycles to test for it.
834a5e ##
04044f ## unsigned bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
5bf7dd ## ····················4 ·················8 ············12
df160e ¤   .align align16
5c077d bniModQ_32:
c10bd7 _bniModQ_32:
72ca22 ¤   movl¤   4(%esp),%eax¤   ¤   # U¤Load n
617957 ¤   pushl¤  %ebp¤   ¤   ¤   # ·V
c74bbc ¤   movl¤   12(%esp),%ebp¤  ¤   # U¤Load len
906730 ¤   pushl¤  %esi¤   ¤   ¤   # ·V
1faa44 ¤   leal¤   -4(%eax,%ebp,4),%esi¤   # U
342000 ¤   movl¤   20(%esp),%ecx¤  ¤   # ·V¤   Load d
0eb203 ¤   xorl¤   %edx,%edx¤  ¤   # U¤Clear MSW for first divide
c00f74 modq32_loop:
cf5e1e ¤   movl¤   (%esi),%eax¤¤   # U
db8f3d ¤   subl¤   $4,%esi¤¤   ¤   # ·V
b2240e ¤   divl¤   %ecx¤   ¤   ¤   # NP
f346ba ¤   decl¤   %ebp¤   ¤   ¤   # U
3d80f4 ¤   jnz¤modq32_loop¤¤   # ·V
0baf5a
f7bdfc ¤   popl¤   %esi¤   ¤   ¤   # U
4cf47f ¤   movl¤   %edx,%eax¤  ¤   # ·V
582b02 ¤   popl¤   %ebp¤   ¤   ¤   # U
f5f2b8 ¤   ret¤¤   ¤   ¤   # NP
--a1ff 000d667e0bc4010015d Page 1 of bni80386_aout.s
e0af5a
b6784f ### Assembly primitives for bignum library, 80386 family, 32-bit code.
e4e0c0 ###
1644e0 ### $Id: bni80386_aout.s,v 1.1 1998/07/31 22:03:37 hal Exp $
d3e0c0 ###
bd937b ### Several primitives are included here. ·Only bniMulAdd1 is *really*
6402b0 ### critical, but once that's written, lnmMulN1 and bniMulSub1 are quite
080371 ### easy to write as well, so they are included here as well.
c562e2 ### bniDiv21 and bniModQ are so easy to write that they're included, too.
b5e0c0 ###
a9fba3 ### All functions here are for 32-bit flat mode. ·I.e. near code and
0b2cfb ### near data, although the near offsets are 32 bits.
8e67af ### Preserved registers are esp, ebp, esi, edi and ebx. ·That last
59e6fd ### is needed by ELF for PIC, and differs from the IBM PC calling
e84233 ### convention.
7daf5a
9d36a2 # Different assemblers have different conventions here
af97bc # These conventions are for a.out format assembler
2f4879 align4=2¤   # could be 2 or 4
80c5f1 align8=3¤   # could be 3 or 8
0ba869 align16=4¤  # cound be 4 or 16
66af5a
f2af5a
7d0d76 .text
feaf5a
7c88a3 # We declare each symbol with two names, to deal with ELF/a.out variances.
26d3a9 ¤   .globl¤ bniMulN1_32
cd35df ¤   .globl¤ _bniMulN1_32
ed71c1 ¤   .globl¤ bniMulAdd1_32
9e57ed ¤   .globl¤ _bniMulAdd1_32
701330 ¤   .globl¤ bniMulSub1_32
4e351c ¤   .globl¤ _bniMulSub1_32
e729ef ¤   .globl¤ bniDiv21_32
24cf99 ¤   .globl¤ _bniDiv21_32
4c9cae ¤   .globl¤ bniModQ_32
27ec5f ¤   .globl¤ _bniModQ_32
14af5a
1f951c ## Register usage:
eff1b2 ## %eax - low half of product
62647e ## %ebx - carry to next iteration
9499e2 ## %ecx - multiplier (k)
2bc939 ## %edx - high half of product
405ab4 ## %esi - source pointer
1bfef8 ## %edi - dest pointer
e2c0eb ## %ebp - loop counter
804a5e ##
f91615 ## Stack frame:
140c23 ## +--------+ %esp+20 ·%esp+24 ·%esp+28 ·%esp+32 ·%esp+36
b5a294 ## | ···k ··|
289365 ## +--------+ %esp+16 ·%esp+20 ·%esp+24 ·%esp+28 ·%esp+32
410012 ## | ··len ·|
546fce ## +--------+ %esp+12 ·%esp+16 ·%esp+20 ·%esp+24 ·%esp+28
4ec4e0 ## | ··in ··|
e35273 ## +--------+ %esp+8 ··%esp+12 ·%esp+16 ·%esp+20 ·%esp+24
191224 ## | ··out ·|
14aa8c ## +--------+ %esp+4 ··%esp+8 ··%esp+12 ·%esp+16 ·%esp+20
56f9d6 ## | return |
e88805 ## +--------+ %esp ····%esp+4 ··%esp+8 ··%esp+12 ·%esp+16
38b048 ## | ·%esi ·|
a5d912 ## +--------+ ·········%esp ····%esp+4 ··%esp+8 ··%esp+12
4913f7 ## | ·%ebp ·|
32e11a ## +--------+ ··················%esp ····%esp+4 ··%esp+8
a049d7 ## | ·%ebx ·|
08afc0 ## +--------+ ···························%esp ····%esp+4
0bee29 ## | ·%edi ·|
22271a ## +--------+ ····································%esp
edaf5a
e02996 ¤   .align¤ align16
999951 bniMulN1_32:
3a930d _bniMulN1_32:
7ade4a ¤   pushl¤  %esi¤   ¤   # U
d62cec ¤   movl¤   12(%esp),%esi¤  # ·V¤   load in
--e474 000065037624010015d Page 2 of bni80386_aout.s
6c0462 ¤   pushl¤  %ebp¤   ¤   # U
096f78 ¤   movl¤   20(%esp),%ebp¤  # ·V¤   load len
34290a ¤   pushl¤  %ebx¤   ¤   # U
37ebba ¤   movl¤   28(%esp),%ecx¤  # ·V¤   load k
45781a ¤   pushl¤  %edi¤   ¤   # U
74a2d2 ¤   movl¤   20(%esp),%edi¤  # ·V¤   load out
3daf5a
034d3f ## First multiply step has no carry in.
9190b5 ¤   movl¤   (%esi),%eax¤¤   # ·V
15b783 ¤   leal¤   -4(,%ebp,4),%ebx¤   # U¤loop unrolling
741a00 ¤   mull¤   %ecx¤   ¤   ¤   # NP¤   first multiply
8d8175 ¤   movl¤   %eax,(%edi)¤¤   # U
37a1e5 ¤   andl¤   $12,%ebx¤   ¤   # ·V¤   loop unrolling
75af5a
1c114d ¤   addl¤   %ebx,%esi¤  ¤   # U¤loop unrolling
97df77 ¤   addl¤   %ebx,%edi¤  ¤   # ·V¤   loop unrolling
00af5a
877730 ¤   jmp¤*m32_jumptable(%ebx)¤   # NP¤   loop unrolling
28af5a
9f51f5 ¤   .align¤ align4
d8bad8 m32_jumptable:
d1ca92 ¤   .long¤  m32_case0
f0d34a ¤   .long¤  m32_case1
caf922 ¤   .long¤  m32_case2
36e0fa ¤   .long¤  m32_case3
1faf5a
97ca0c ¤   nop
50f855 ¤   .align¤ align8
77ca0c ¤   nop
eeca0c ¤   nop
ae7ddc ¤   nop¤# Get loop nicely aligned
b6af5a
9c9cd8 m32_case0:
e089b4 ¤   subl¤   $4,%ebp¤¤   # U
d0e9fe ¤   jbe¤m32_done¤   # ·V
6eaf5a
07696d m32_loop:
cf6aae ¤   movl¤   4(%esi),%eax¤   # U
d2d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
d039ba ¤   addl¤   $16,%esi¤   # U
0aa25f ¤   addl¤   $16,%edi¤   # ·V
f9de86 ¤   mull¤   %ecx¤   ¤   # NP
eb7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
76eb42 ¤   adcl¤   $0,%edx¤¤   # U
c632a1 ¤   movl¤   %eax,-12(%edi)¤ # ·V
e073bc m32_case3:
c7f797 ¤   movl¤   -8(%esi),%eax¤  # U
10d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
80de86 ¤   mull¤   %ecx¤   ¤   # NP
927d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
e5eb42 ¤   adcl¤   $0,%edx¤¤   # U
bf58bc ¤   movl¤   %eax,-8(%edi)¤  # ·V
642960 m32_case2:
c2109d ¤   movl¤   -4(%esi),%eax¤  # U
c9d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
37de86 ¤   mull¤   %ecx¤   ¤   # NP
497d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
9feb42 ¤   adcl¤   $0,%edx¤¤   # U
e62177 ¤   movl¤   %eax,-4(%edi)¤  # ·V
66c604 m32_case1:
535343 ¤   movl¤   (%esi),%eax¤# U
87d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
5bde86 ¤   mull¤   %ecx¤   ¤   # NP
ee7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
eeeb42 ¤   adcl¤   $0,%edx¤¤   # U
34db73 ¤   movl¤   %eax,(%edi)¤# ·V
01af5a
8f89b4 ¤   subl¤   $4,%ebp¤¤   # U
3652a2 ¤   ja¤ m32_loop¤   # ·V
6faf5a
fae8a6 m32_done:
06f236 ¤   movl¤   %edx,4(%edi)¤   # U
--44cb 0002733e8cb4010015d Page 3 of bni80386_aout.s
65d6f4 ¤   popl¤   %edi¤   ¤   # ·V
a06a0a ¤   popl¤   %ebx¤   ¤   # U
572947 ¤   popl¤   %ebp¤   ¤   # ·V
f09d4a ¤   popl¤   %esi¤   ¤   # U
206842 ¤   ret¤¤   ¤   # NP
23af5a
65af5a
012996 ¤   .align¤ align16
4fd479 bniMulAdd1_32:
140174 _bniMulAdd1_32:
c6af5a
b1de4a ¤   pushl¤  %esi¤   ¤   # U
ff2cec ¤   movl¤   12(%esp),%esi¤  # ·V¤   load in
c4781a ¤   pushl¤  %edi¤   ¤   # U
b08cb3 ¤   movl¤   12(%esp),%edi¤  # ·V¤   load out
a50462 ¤   pushl¤  %ebp¤   ¤   # U
4fbae1 ¤   movl¤   24(%esp),%ebp¤  # ·V¤   load len
2b290a ¤   pushl¤  %ebx¤   ¤   # U
fb60e1 ¤   movl¤   32(%esp),%ecx¤  # ·V¤   load k
68af5a
d74d3f ## First multiply step has no carry in.
ce90b5 ¤   movl¤   (%esi),%eax¤¤   # ·V
4cd861 ¤   movl¤   (%edi),%ebx¤¤   # U
941a00 ¤   mull¤   %ecx¤   ¤   ¤   # NP¤   first multiply
f694ac ¤   addl¤   %eax,%ebx¤  ¤   # U
3c92c8 ¤   leal¤   -4(,%ebp,4),%eax¤   # ·V¤   loop unrolling
cc0e25 ¤   adcl¤   $0,%edx¤¤   ¤   # U
cf6140 ¤   andl¤   $12,%eax¤   ¤   # ·V¤   loop unrolling
5a804d ¤   movl¤   %ebx,(%edi)¤¤   # U
62af5a
981bef ¤   addl¤   %eax,%esi¤  ¤   # ·V¤   loop unrolling
ae2abc ¤   addl¤   %eax,%edi¤  ¤   # U¤loop unrolling
dbaf5a
dd4c6d ¤   jmp¤*ma32_jumptable(%eax)¤  # NP¤   loop unrolling
eaaf5a
c951f5 ¤   .align¤ align4
1be8a6 ma32_jumptable:
0153b4 ¤   .long¤  ma32_case0
8c4a6c ¤   .long¤  ma32_case1
676004 ¤   .long¤  ma32_case2
2379dc ¤   .long¤  ma32_case3
87af5a
93f855 ¤   .align¤ align8
46ca0c ¤   nop
a8ca0c ¤   nop
cb45b3 ¤   nop¤¤   ¤   # To align loop properly
6daf5a
e4af5a
b68838 ma32_case0:
ed89b4 ¤   subl¤   $4,%ebp¤¤   # U
c1bdc6 ¤   jbe¤ma32_done¤  # ·V
08af5a
5f2839 ma32_loop:
786aae ¤   movl¤   4(%esi),%eax¤   # U
a5d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
bb39ba ¤   addl¤   $16,%esi¤   # U
25a25f ¤   addl¤   $16,%edi¤   # ·V
9dde86 ¤   mull¤   %ecx¤   ¤   # NP
7d7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
6299fa ¤   movl¤   -12(%edi),%ebx¤ # ·V
e7eb42 ¤   adcl¤   $0,%edx¤¤   # U
fd756f ¤   addl¤   %eax,%ebx¤  # ·V
baeb42 ¤   adcl¤   $0,%edx¤¤   # U
b98f6b ¤   movl¤   %ebx,-12(%edi)¤ # ·V
d3675c ma32_case3:
3cf797 ¤   movl¤   -8(%esi),%eax¤  # U
e5d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
f4de86 ¤   mull¤   %ecx¤   ¤   # NP
c07d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
37ee77 ¤   movl¤   -8(%edi),%ebx¤  # ·V
a3eb42 ¤   adcl¤   $0,%edx¤¤   # U
27756f ¤   addl¤   %eax,%ebx¤  # ·V
--508e 00085f596c84010015d Page 4 of bni80386_aout.s
b2eb42 ¤   adcl¤   $0,%edx¤¤   # U
d6e576 ¤   movl¤   %ebx,-8(%edi)¤  # ·V
fc3d80 ma32_case2:
86109d ¤   movl¤   -4(%esi),%eax¤  # U
4ad5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
4cde86 ¤   mull¤   %ecx¤   ¤   # NP
217d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
9a41ca ¤   movl¤   -4(%edi),%ebx¤  # ·V
95eb42 ¤   adcl¤   $0,%edx¤¤   # U
92756f ¤   addl¤   %eax,%ebx¤  # ·V
a3eb42 ¤   adcl¤   $0,%edx¤¤   # U
219cbd ¤   movl¤   %ebx,-4(%edi)¤  # ·V
42d2e4 ma32_case1:
8b5343 ¤   movl¤   (%esi),%eax¤# U
e3d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
fade86 ¤   mull¤   %ecx¤   ¤   # NP
fb7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
3a3558 ¤   movl¤   (%edi),%ebx¤# ·V
65eb42 ¤   adcl¤   $0,%edx¤¤   # U
95756f ¤   addl¤   %eax,%ebx¤  # ·V
c7eb42 ¤   adcl¤   $0,%edx¤¤   # U
d3030d ¤   movl¤   %ebx,(%edi)¤# ·V
01af5a
8689b4 ¤   subl¤   $4,%ebp¤¤   # U
799bcd ¤   ja¤ ma32_loop¤  # ·V
42af5a
d5a9f2 ma32_done:
a06a0a ¤   popl¤   %ebx¤   ¤   # U
ae2947 ¤   popl¤   %ebp¤   ¤   # ·V
310d1c ¤   movl¤   %edx,%eax¤  # U
b3d6f4 ¤   popl¤   %edi¤   ¤   # ·V
ab9d4a ¤   popl¤   %esi¤   ¤   # U
ce6842 ¤   ret¤¤   ¤   # NP
c0af5a
81af5a
8e2996 ¤   .align¤ align16
d8321d bniMulSub1_32:
5be710 _bniMulSub1_32:
cfde4a ¤   pushl¤  %esi¤   ¤   # U
d62cec ¤   movl¤   12(%esp),%esi¤  # ·V¤   load in
37781a ¤   pushl¤  %edi¤   ¤   # U
898cb3 ¤   movl¤   12(%esp),%edi¤  # ·V¤   load out
850462 ¤   pushl¤  %ebp¤   ¤   # U
17bae1 ¤   movl¤   24(%esp),%ebp¤  # ·V¤   load len
e4290a ¤   pushl¤  %ebx¤   ¤   # U
6060e1 ¤   movl¤   32(%esp),%ecx¤  # ·V¤   load k
35af5a
8a58e1 /* First multiply step has no carry in. */
1490b5 ¤   movl¤   (%esi),%eax¤¤   # ·V
4ed861 ¤   movl¤   (%edi),%ebx¤¤   # U
e21a00 ¤   mull¤   %ecx¤   ¤   ¤   # NP¤   first multiply
0060f2 ¤   subl¤   %eax,%ebx¤  ¤   # U
0b92c8 ¤   leal¤   -4(,%ebp,4),%eax¤   # ·V¤   loop unrolling
f00e25 ¤   adcl¤   $0,%edx¤¤   ¤   # U
0c6140 ¤   andl¤   $12,%eax¤   ¤   # ·V¤   loop unrolling
05804d ¤   movl¤   %ebx,(%edi)¤¤   # U
73af5a
551bef ¤   addl¤   %eax,%esi¤  ¤   # ·V¤   loop unrolling
282abc ¤   addl¤   %eax,%edi¤  ¤   # U¤loop unrolling
97af5a
b55b98 ¤   jmp¤*ms32_jumptable(%eax)¤  # NP¤   loop unrolling
11af5a
f151f5 ¤   .align¤ align4
16da16 ms32_jumptable:
f4d9a8 ¤   .long¤  ms32_case0
23c070 ¤   .long¤  ms32_case1
aaea18 ¤   .long¤  ms32_case2
bcf3c0 ¤   .long¤  ms32_case3
55af5a
c5f855 ¤   .align¤ align8
4bca0c ¤   nop
85ca0c ¤   nop
--80ac 00019e8e62b4010015d Page 5 of bni80386_aout.s
70ca0c ¤   nop
83af5a
49525f ms32_case0:
6289b4 ¤   subl¤   $4,%ebp¤¤   # U
4d087f ¤   jbe¤ms32_done¤  # ·V
65af5a
63a225 ms32_loop:
7c6aae ¤   movl¤   4(%esi),%eax¤   # U
a9d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
fd39ba ¤   addl¤   $16,%esi¤   # U
3da25f ¤   addl¤   $16,%edi¤   # ·V
0ade86 ¤   mull¤   %ecx¤   ¤   # NP
4e7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
cf99fa ¤   movl¤   -12(%edi),%ebx¤ # ·V
cdeb42 ¤   adcl¤   $0,%edx¤¤   # U
4ed1fd ¤   subl¤   %eax,%ebx¤  # ·V
16eb42 ¤   adcl¤   $0,%edx¤¤   # U
3c8f6b ¤   movl¤   %ebx,-12(%edi)¤ # ·V
97bd3b ms32_case3:
caf797 ¤   movl¤   -8(%esi),%eax¤  # U
f1d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
7ede86 ¤   mull¤   %ecx¤   ¤   # NP
e57d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
39ee77 ¤   movl¤   -8(%edi),%ebx¤  # ·V
03eb42 ¤   adcl¤   $0,%edx¤¤   # U
c0d1fd ¤   subl¤   %eax,%ebx¤  # ·V
a7eb42 ¤   adcl¤   $0,%edx¤¤   # U
65e576 ¤   movl¤   %ebx,-8(%edi)¤  # ·V
2be7e7 ms32_case2:
55109d ¤   movl¤   -4(%esi),%eax¤  # U
07d5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
abde86 ¤   mull¤   %ecx¤   ¤   # NP
ba7d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
c941ca ¤   movl¤   -4(%edi),%ebx¤  # ·V
4eeb42 ¤   adcl¤   $0,%edx¤¤   # U
f9d1fd ¤   subl¤   %eax,%ebx¤  # ·V
90eb42 ¤   adcl¤   $0,%edx¤¤   # U
6d9cbd ¤   movl¤   %ebx,-4(%edi)¤  # ·V
120883 ms32_case1:
9c5343 ¤   movl¤   (%esi),%eax¤# U
3fd5b6 ¤   movl¤   %edx,%ebx¤  # ·V¤   Remember carry for later
22de86 ¤   mull¤   %ecx¤   ¤   # NP
357d95 ¤   addl¤   %ebx,%eax¤  # U¤Add carry in from previous word
023558 ¤   movl¤   (%edi),%ebx¤# ·V
4feb42 ¤   adcl¤   $0,%edx¤¤   # U
ecd1fd ¤   subl¤   %eax,%ebx¤  # ·V
12eb42 ¤   adcl¤   $0,%edx¤¤   # U
ca030d ¤   movl¤   %ebx,(%edi)¤# ·V
c4af5a
6f89b4 ¤   subl¤   $4,%ebp¤¤   # U
792e74 ¤   ja¤ ms32_loop¤  # ·V
e1af5a
1023ee ms32_done:
576a0a ¤   popl¤   %ebx¤   ¤   # U
8a2947 ¤   popl¤   %ebp¤   ¤   # ·V
0f0d1c ¤   movl¤   %edx,%eax¤  # U
31d6f4 ¤   popl¤   %edi¤   ¤   # ·V
2c9d4a ¤   popl¤   %esi¤   ¤   # U
a76842 ¤   ret¤¤   ¤   # NP
7aaf5a
71e097 ## Two-word by one-word divide. ·Stores quotient, returns remainder.
567089 ## BNWORD32 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
40722a ## ·····················4 ···········8 ···········12 ··········16
e2af5a
2f160e ¤   .align align16
aabe99 bniDiv21_32:
99b4c5 _bniDiv21_32:
93c2af ¤   movl¤   8(%esp),%edx¤   # U¤Load nh
cb6769 ¤   movl¤   12(%esp),%eax¤  # ·V¤   Load nl
a266bd ¤   movl¤   4(%esp),%ecx¤   # U¤Load q
c8ffa2 ¤   divl¤   16(%esp)¤   # NP
19a20d ¤   movl¤   %eax,(%ecx)¤# U¤Store quotient
--e513 001f52d39cc4010015d Page 6 of bni80386_aout.s
392724 ¤   movl¤   %edx,%eax¤  # ·V¤   Return remainder
d88a83 ¤   ret
54af5a
9d0779 ## Multi-word by one-word remainder.
fead6f ## This speeds up key generation. ·It's not worth unrolling and so on;
d39a4c ## using 32-bit divides is enough of a speedup.
a94a5e ##
febf8d ## The modulus (in %ebp) is often 16 bits. ·Given that the dividend is 32
cb0e29 ## bits, the chances of saving the first divide because the high word of the
32ea37 ## dividend is less than the modulus are low enough it's not worth taking
5fc66f ## the cycles to test for it.
834a5e ##
04044f ## unsigned bniModQ_32(BNWORD32 const *n, unsigned len, unsigned d)
5bf7dd ## ····················4 ·················8 ············12
df160e ¤   .align align16
5c077d bniModQ_32:
c10bd7 _bniModQ_32:
72ca22 ¤   movl¤   4(%esp),%eax¤   ¤   # U¤Load n
617957 ¤   pushl¤  %ebp¤   ¤   ¤   # ·V
c74bbc ¤   movl¤   12(%esp),%ebp¤  ¤   # U¤Load len
906730 ¤   pushl¤  %esi¤   ¤   ¤   # ·V
1faa44 ¤   leal¤   -4(%eax,%ebp,4),%esi¤   # U
342000 ¤   movl¤   20(%esp),%ecx¤  ¤   # ·V¤   Load d
0eb203 ¤   xorl¤   %edx,%edx¤  ¤   # U¤Clear MSW for first divide
c00f74 modq32_loop:
cf5e1e ¤   movl¤   (%esi),%eax¤¤   # U
db8f3d ¤   subl¤   $4,%esi¤¤   ¤   # ·V
b2240e ¤   divl¤   %ecx¤   ¤   ¤   # NP
f346ba ¤   decl¤   %ebp¤   ¤   ¤   # U
3d80f4 ¤   jnz¤modq32_loop¤¤   # ·V
0baf5a
f7bdfc ¤   popl¤   %esi¤   ¤   ¤   # U
4cf47f ¤   movl¤   %edx,%eax¤  ¤   # ·V
582b02 ¤   popl¤   %ebp¤   ¤   ¤   # U
f5f2b8 ¤   ret¤¤   ¤   ¤   # NP
--669d 0001f7d418d4010015e Page 1 of bni80386c.c
bc38e5 /*
19027f ·* bni80386c.c - Low-level bignum routines, 32-bit version.
05775e ·*
4c50b0 ·* Assembly primitives for bignum library, 80386 family, 32-bit code.
eaf59d ·* Inline assembler for MSVC++ 4.X
d6775e ·*
1ec5e4 ·* $Id: bni80386c.c,v 1.5 1997/09/18 01:35:10 lloyd Exp $
f1775e ·*
a5bb84 ·* Several primitives are included here. ·Only bniMulAdd1 is *really*
94f7b6 ·* critical, but once that's written, bniMulN1 and bniMulSub1 are quite
a85366 ·* easy to write as well, so they are included here as well.
ae49e2 ·* bniDiv21 and bniModQ are so easy to write that they're included, too.
fa775e ·*
818e79 ·* The usual 80x86 calling conventions have AX, BX, CX and DX
0a1ddc ·* volatile, and SI, DI, SP and BP preserved across calls.
92f583 ·* This includes the "E"xtended forms of all of those registers
349ec0 ·*·
f5495d ·*/
54af5a
5be2ff #include "pgpConfig.h"
0eaf5a
2838e5 /*
0816cf ·* Some compilers complain about #if FOO if FOO isn't defined,
f959aa ·* so do the ANSI-mandated thing explicitly...
84495d ·*/
5cc60f #ifndef NO_ASSERT_H
dd154e #define NO_ASSERT_H 0
bb7454 #endif
52b552 #ifndef NO_STRING_H
db37dd #define NO_STRING_H 0
707454 #endif
1c8537 #ifndef HAVE_STRINGS_H
28025c #define HAVE_STRINGS_H 0
c87454 #endif
8c101b #ifndef NEED_MEMORY_H
16ee50 #define NEED_MEMORY_H 0
fb7454 #endif
12af5a
4b7668 #if !NO_STRING_H
5b7210 #include <string.h>¤/* For memcpy */
24a752 #elif HAVE_STRINGS_H
07f7c3 #include <strings.h>
eb7454 #endif
fd3c37 #if NEED_MEMORY_H
77c737 #include <memory.h>
127454 #endif
dbaf5a
62a6ac #include "bni.h"
7310de #include "bni32.h"
de21db #include "bnimem.h"
598cb6 #include "bnlegal.h"
d8af5a
da4724 #include "bnkludge.h"
8ca146 #include "pgpDebug.h"
78af5a
f7e77e #ifndef BNWORD32
afc47d #error 32-bit bignum library requires a 32-bit data type
267454 #endif
5eaf5a
4daf5a
c1c664 /* Disable warning for no return value, typical of asm functions */
52c010 #pragma warning( disable : 4035 )
baaf5a
5ee6d9 BNWORD32
637258 bniMulAdd1_32(
153ea2 BNWORD32 *outParam, BNWORD32 const *inParam, unsigned len, BNWORD32 k)
49bb36 {
93f2e2 __asm
d7bd71 ·{
2e87b3 ¤   mov esi, inParam¤   ; load inParam
1734e0 ¤   mov edi, outParam¤  ; load outParam
1f5fac ¤   mov ecx, k¤ ¤   ¤   ; load k
--d5d6 00001d5481a4010015e Page 2 of bni80386c.c
41379d ¤   push ebp¤   ¤   ¤   ; preserve ebp for return block
648591 ¤   mov ebp, len¤   ¤   ; load len (must be last)
3daf5a
f216b9 ;; First multiply step has no carry in.
318189 ¤   mov¤eax,[esi]¤  ; U
e43bde ¤   mov¤ebx,[edi]¤  ; ·V
7b6f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
50a715 ¤   add¤ebx,eax¤¤   ; U
84680b ¤   lea¤eax,[ebp*4-4]¤  ; ·V¤   loop unrolling
f1621c ¤   adc¤edx,0¤  ¤   ; U
648e14 ¤   and¤eax,12¤ ¤   ; ·V¤   loop unrolling
cb0444 ¤   mov¤[edi],ebx¤  ; U
70af5a
d891b0 ¤   add¤esi,eax¤¤   ; ·V¤   loop unrolling
0b29f5 ¤   add¤edi,eax¤¤   ; U¤loop unrolling
84af5a
43ada7 ; inline assembler won't do tables, so use simple compare code
bc253b ;¤  jmp¤DWORD PTR ma32_jumptable[eax]¤  ; NP¤   loop unrolling
d5fd50 ;
f1a48d ;¤  align¤  4
f441ec ;ma32_jumptable:
c78fc9 ;¤  dd¤ ma32_case0
859611 ;¤  dd¤ ma32_case1
60bc79 ;¤  dd¤ ma32_case2
66a5a1 ;¤  dd¤ ma32_case3
00fd50 ;
9d024f ;¤  nop
a2af5a
4ca713 ¤   cmp¤eax, 0
bab1ae ¤   je¤ ma32_case0
68c073 ¤   cmp¤eax, 4
36a876 ¤   je¤ ma32_case1
6c69d3 ¤   cmp¤eax, 8
ad821e ¤   je¤ ma32_case2
633684 ¤   jmp¤ma32_case3
93af5a
8b12d6 ¤   align¤  8
77ca0c ¤   nop
abca0c ¤   nop
3121db ¤   nop¤¤   ¤   ; To align loop properly
a2af5a
6aaf5a
2d8838 ma32_case0:
6b0c43 ¤   sub¤ebp,4¤  ¤   ; U
d5900f ¤   jbe¤SHORT ma32_done¤; ·V
27af5a
422839 ma32_loop:
51700e ¤   mov¤eax,[esi+4]¤; U
d99f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
8cbdd6 ¤   add¤esi,16¤ ¤   ; U
21c9d9 ¤   add¤edi,16¤ ¤   ; ·V
544ed8 ¤   mul¤ecx¤¤   ; NP
cef7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
36b4e1 ¤   mov¤ebx,[edi-12]¤   ; ·V
ab621c ¤   adc¤edx,0¤  ¤   ; U
702e9f ¤   add¤ebx,eax¤¤   ; ·V
0d621c ¤   adc¤edx,0¤  ¤   ; U
e0db03 ¤   mov¤[edi-12],ebx¤   ; ·V
b8675c ma32_case3:
67dc25 ¤   mov¤eax,[esi-8]¤; U
2a9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
544ed8 ¤   mul¤ecx¤¤   ; NP
d6f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
af54e5 ¤   mov¤ebx,[edi-8]¤; ·V
c8621c ¤   adc¤edx,0¤  ¤   ; U
a32e9f ¤   add¤ebx,eax¤¤   ; ·V
74621c ¤   adc¤edx,0¤  ¤   ; U
8af693 ¤   mov¤[edi-8],ebx¤; ·V
273d80 ma32_case2:
246dbf ¤   mov¤eax,[esi-4]¤; U
2a9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
014ed8 ¤   mul¤ecx¤¤   ; NP
--811b 000b82d8d3d4010015e Page 3 of bni80386c.c
05f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
b06f87 ¤   mov¤ebx,[edi-4]¤; ·V
f8621c ¤   adc¤edx,0¤  ¤   ; U
9d2e9f ¤   add¤ebx,eax¤¤   ; ·V
62621c ¤   adc¤edx,0¤  ¤   ; U
5ef909 ¤   mov¤[edi-4],ebx¤; ·V
7bd2e4 ma32_case1:
6b8189 ¤   mov¤eax,[esi]¤  ; U
169f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
954ed8 ¤   mul¤ecx¤¤   ; NP
6bf7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
a13bde ¤   mov¤ebx,[edi]¤  ; ·V
11621c ¤   adc¤edx,0¤  ¤   ; U
102e9f ¤   add¤ebx,eax¤¤   ; ·V
99621c ¤   adc¤edx,0¤  ¤   ; U
716d30 ¤   mov¤[edi],ebx¤  ; ·V
9aaf5a
760c43 ¤   sub¤ebp,4¤  ¤   ; U
294fe3 ¤   ja¤ SHORT ma32_loop¤; ·V
01af5a
75a9f2 ma32_done:
3fd384 ¤   mov¤eax,edx¤¤   ; U
8c1605 ¤   pop¤ebp
09e9a1 ·}
0cefe6 }
83af5a
4daf5a
56e6d9 BNWORD32
06943c bniMulSub1_32(
743ea2 BNWORD32 *outParam, BNWORD32 const *inParam, unsigned len, BNWORD32 k)
4fbb36 {
1ef2e2 __asm
10bd71 ·{
f887b3 ¤   mov esi, inParam¤   ; load inParam
dc34e0 ¤   mov edi, outParam¤  ; load outParam
a85fac ¤   mov ecx, k¤ ¤   ¤   ; load k
92379d ¤   push ebp¤   ¤   ¤   ; preserve ebp for return block
c18591 ¤   mov ebp, len¤   ¤   ; load len (must be last)
91af5a
b116b9 ;; First multiply step has no carry in.
c7705c ¤   mov¤eax,[esi]¤  ; ·V
1d4f50 ¤   mov¤ebx,[edi]¤  ; U
6f6f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
ab6125 ¤   sub¤ebx,eax¤¤   ; U
00680b ¤   lea¤eax,[ebp*4-4]¤  ; ·V¤   loop unrolling
60621c ¤   adc¤edx,0¤  ¤   ; U
7e8e14 ¤   and¤eax,12¤ ¤   ; ·V¤   loop unrolling
4d0444 ¤   mov¤[edi],ebx¤  ; U
50af5a
5191b0 ¤   add¤esi,eax¤¤   ; ·V¤   loop unrolling
2229f5 ¤   add¤edi,eax¤¤   ; U¤loop unrolling
fcaf5a
78ada7 ; inline assembler won't do tables, so use simple compare code
02695c ;¤  jmp¤DWORD PTR ms32_jumptable[eax]¤  ; NP¤   loop unrolling
3cfd50 ;
6fa48d ;¤  align¤  4
d2735c ;ms32_jumptable:
d405d5 ;¤  dd¤ ms32_case0
4e1c0d ;¤  dd¤ ms32_case1
ae3665 ;¤  dd¤ ms32_case2
ed2fbd ;¤  dd¤ ms32_case3
abfd50 ;
d4024f ;¤  nop
9aaf5a
72a713 ¤   cmp¤eax, 0
013bb2 ¤   je¤ ms32_case0
00c073 ¤   cmp¤eax, 4
bd226a ¤   je¤ ms32_case1
de69d3 ¤   cmp¤eax, 8
cf0802 ¤   je¤ ms32_case2
90bc98 ¤   jmp¤ms32_case3
b8af5a
--801f 00127db0b354010015e Page 4 of bni80386c.c
a712d6 ¤   align¤  8
77ca0c ¤   nop
dbca0c ¤   nop
b6ca0c ¤   nop
2faf5a
3d525f ms32_case0:
b70c43 ¤   sub¤ebp,4¤  ¤   ; U
f8bb0c ¤   jbe¤SHORT ms32_done¤; ·V
c3af5a
6ca225 ms32_loop:
ce700e ¤   mov¤eax,[esi+4]¤; U
599f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
6bbdd6 ¤   add¤esi,16¤ ¤   ; U
60c9d9 ¤   add¤edi,16¤ ¤   ; ·V
d74ed8 ¤   mul¤ecx¤¤   ; NP
2af7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
dfb4e1 ¤   mov¤ebx,[edi-12]¤   ; ·V
df621c ¤   adc¤edx,0¤  ¤   ; U
921fda ¤   sub¤ebx,eax¤¤   ; ·V
15621c ¤   adc¤edx,0¤  ¤   ; U
d3db03 ¤   mov¤[edi-12],ebx¤   ; ·V
67bd3b ms32_case3:
96dc25 ¤   mov¤eax,[esi-8]¤; U
c39f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
644ed8 ¤   mul¤ecx¤¤   ; NP
1af7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
1e54e5 ¤   mov¤ebx,[edi-8]¤; ·V
94621c ¤   adc¤edx,0¤  ¤   ; U
ac1fda ¤   sub¤ebx,eax¤¤   ; ·V
34621c ¤   adc¤edx,0¤  ¤   ; U
59f693 ¤   mov¤[edi-8],ebx¤; ·V
ece7e7 ms32_case2:
636dbf ¤   mov¤eax,[esi-4]¤; U
2a9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
284ed8 ¤   mul¤ecx¤¤   ; NP
3ff7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
606f87 ¤   mov¤ebx,[edi-4]¤; ·V
10621c ¤   adc¤edx,0¤  ¤   ; U
0d1fda ¤   sub¤ebx,eax¤¤   ; ·V
2c621c ¤   adc¤edx,0¤  ¤   ; U
57f909 ¤   mov¤[edi-4],ebx¤; ·V
680883 ms32_case1:
718189 ¤   mov¤eax,[esi]¤  ; U
4f9f52 ¤   mov¤ebx,edx¤¤   ; ·V¤   Remember carry for later
4d4ed8 ¤   mul¤ecx¤¤   ; NP
48f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
be3bde ¤   mov¤ebx,[edi]¤  ; ·V
5f621c ¤   adc¤edx,0¤  ¤   ; U
7f1fda ¤   sub¤ebx,eax¤¤   ; ·V
0d621c ¤   adc¤edx,0¤  ¤   ; U
3a6d30 ¤   mov¤[edi],ebx¤  ; ·V
5daf5a
a70c43 ¤   sub¤ebp,4¤  ¤   ; U
1464e0 ¤   ja¤ SHORT ms32_loop¤; ·V
c8af5a
4d23ee ms32_done:
9ed384 ¤   mov¤eax,edx¤¤   ; U
bb1605 ¤   pop¤ebp
81e9a1 ·}
f1efe6 }
cbaf5a
595258 /* Reenable missing return value warning */
271c86 #pragma warning( default : 4035 )
--1578 000b4ee89df4010015f Page 1 of bni80386c.h
bc38e5 /*
a293f2 ·* bni80386c.h - This file defines the interfaces to the 80386 inlined C
6b2b7e ·* assembly primitives. ·It is intended to be included in "bni.h"
cc7924 ·* via the "#include BNINCLUDE" mechanism.
ee775e ·*
3e5ee9 ·* $Id: bni80386c.h,v 1.2 1997/05/05 19:49:11 lloyd Exp $
b2495d ·*/
aed83c ·
d47be2 #define BN_LITTLE_ENDIAN 1
86af5a
4469da typedef unsigned long bnword32;
7cca02 #define BNWORD32 bnword32
c6af5a
a4a5c8 /* MS-DOS needs the calling convention described to it. */
9b6756 #ifndef MSDOS
0753a6 #ifdef __MSDOS
5dc3f7 #define MSDOS 1
847454 #endif
0c7454 #endif
796756 #ifndef MSDOS
86de0a #ifdef __MSDOS__
dbc3f7 #define MSDOS 1
857454 #endif
c77454 #endif
5daf5a
b6a502 /* By MS-DOS, we mean 16-bit brain-dead MS-DOS. ·Not 32-bit good things. */
dfb053 #ifdef __GO32
d19682 #undef MSDOS
597454 #endif
8d092f #ifdef __GO32__
a39682 #undef MSDOS
c97454 #endif
fdaf5a
07306a #ifdef MSDOS
06294a #define CDECL __cdecl
4cdb21 #else
88b021 #define CDECL /*nothing*/
fe7454 #endif
c4af5a
953379 #ifdef __cplusplus
f18078 /* These assembly-language primitives use C names */
966dad extern "C" {
037454 #endif
58af5a
b9f5e0 /* Function prototypes for the inline asm routines */
aaf1a3 bnword32 CDECL
f5a889 bniMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
ed7ea8 #define bniMulAdd1_32 bniMulAdd1_32
3aaf5a
c9f1a3 bnword32 CDECL
98d47b bniMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
0309c1 #define bniMulSub1_32 bniMulSub1_32
6daf5a
4cb177 #if 0
e74d6e void CDECL
fad916 bniMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
dec143 #define bniMulN1_32 bniMulN1_32 ···········
397516 ·······
44f1a3 bnword32 CDECL
b23aba bniDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
8b615a #define bniDiv21_32 bniDiv21_32
60af5a
dd67cf unsigned CDECL
f789e1 bniModQ_32(bnword32 const *n, unsigned len, bnword32 d);
86f735 #define bniModQ_32 bniModQ_32
ae7454 #endif
20af5a
5f1254 PGP_END_C_DECLARATIONS
77af5a
50af5a
ee53f7 #if __GNUC__
b438e5 /*
--afa5 001f2e1745f4010015f Page 2 of bni80386c.h
d32378 ·* Use the (massively cool) GNU inline-assembler extension to define
97131a ·* inline expansions for various operations.
3a775e ·*
32cf8e ·* The massively cool part is that the assembler can have inputs
0af904 ·* and outputs, and you specify the operands and which effective
9775a3 ·* addresses are legal and they get substituted into the code.
efe987 ·* (For example, some of the code requires a zero. ·Rather than
16c604 ·* specify an immediate constant, the expansion specifies an operand
c85402 ·* of zero which can be in various places. ·This lets GCC use an
56a0ce ·* immediate zero, or a register which contains zero if it's available.)
0a775e ·*
d90b46 ·* The syntax is asm("asm_code" : outputs : inputs : trashed)
7d0148 ·* %0, %1 and so on in the asm code are substituted by the operands
90b8cd ·* in left-to-right order (outputs, then inputs).
c30057 ·* The operands contain constraint strings and values to use.
88f79b ·* Outputs must be lvalues, inputs may be rvalues. ·In the constraints:
f7a684 ·* "a" means that the operand must be in eax.
3ff0ed ·* "d" means that the operand must be in edx.
6b21c0 ·* "g" means that the operand may be any effective address.
75d967 ·* "=" means that the operand is assigned to.
3cef4a ·* "%" means that this operand and the following one may be
cdd6fe ·* ····interchanged if desirable.
08ed2e ·* "bcDSmn" means that the operand must be in ebx, ecx, esi, edi, memory,
b6aad8 ·* ·········or an immediate constant. ·(This is almost the same as "g"
22d7b5 ·* ·········but allowing it in eax wouldn't help because x is already
1a0b34 ·* ·········assigned there, and it must not be in edx, since edx is
03bbe7 ·* ·········overwritten by the multiply before a and b are read.)
29775e ·*
e41b3f ·* Note that GCC uses AT&T assembler syntax, which is rather
b3fbe4 ·* different from Intel syntax. ·The length (b, w or l) of the
10562b ·* operation is appended to the opcode, and the *second* operand
ff4598 ·* is the destination, not the first. ·Finally, the register names
4319ef ·* are all preceded with "%". ·(Doubled here because % is a
268d60 ·* magic character.)
ad495d ·*/
36af5a
e917b2 /* (ph<<32) + pl = x*y */
de9369 #define mul32_ppmm(ph,pl,x,y)¤  \
c27a53 ¤   __asm__("mull %3" : "=d"(ph), "=a"(pl) : "%a"(x), "g"(y))
06af5a
a7e5ca /* (ph<<32) + pl = x*y + a */
c12073 #define mul32_ppmma(ph,pl,x,y,a)¤   \
89ce72 ¤   __asm__("mull %3\n\t"¤  ¤   \
4adeb2 ¤   ········"addl %4,%%eax\n\t"¤\
ca15a5 ¤   ········"adcl %5,%%edx"¤¤   \
7bb601 ¤   ········: "=&d"(ph), "=a"(pl)¤  \
e0fbaf ¤   ········: "%a"(x), "g"(y), "bcDSmn"(a), "bcDSmn"(0))
9caf5a
e77e17 /* (ph<<32) + pl = x*y + a + b */
19972a #define mul32_ppmmaa(ph,pl,x,y,a,b)¤\
70ce72 ¤   __asm__("mull %3\n\t"¤  ¤   \
5ddeb2 ¤   ········"addl %4,%%eax\n\t"¤\
193291 ¤   ········"adcl %6,%%edx\n\t"¤\
199698 ¤   ········"addl %5,%%eax\n\t"¤\
b1cddb ¤   ········"adcl %6,%%edx"¤¤   \
25b601 ¤   ········: "=&d"(ph), "=a"(pl)¤  \
9d4754 ¤   ········: "%a"(x), "g"(y), "%bcDSmn"(a), "bcDSmn"(b), "bcDSmn"(0))
ebaf5a
23f64a /* q = ((nh<<32) + nl) / d, return remainder. ·nh guaranteed < d. */
5c2005 #undef bniDiv21_32
fc78ed #define bniDiv21_32(q,nh,nl,d)¤ \
697c4b ¤   ({unsigned _;¤  \
16e3f8 ¤   ··__asm__("divl %4" : "=d"(_), "=a"(*q)¤: "d"(nh), "a"(nl), "g"(d)); \
943dfb ¤   ··_;})
94af5a
40cd85 /* No quotient, just return remainder ((nh<<32) + nl) % d */
3014ec #define bniMod21_32(nh,nl,d)¤   \
df7c4b ¤   ({unsigned _;¤  \
b950ca ¤   ··__asm__("divl %3" : "=d"(_) : "d"(nh), "a"(nl), "g"(d) : "ax"); \
013dfb ¤   ··_;})
a5af5a
f2a5dc #endif /* __GNUC__ */
--f3f6 0003fbdb57140100160 Page 1 of bni8086.asm
4cbe57 ;;; Assembly primitives for bignum library, 80x86 family.
e3debf ;;;
3e0945 ;;; $Id: bni8086.asm,v 1.2 1997/05/09 20:19:38 lloyd Exp $
4bdebf ;;;
833bdc ;;; Several primitives are included here. ·Only bniMulAdd1 is *really*
92ef35 ;;; critical, but once that's written, bniMul1 and bniSub1 are quite
1ca220 ;;; easy to write as well, so they are included here as well.
aa800f ;;; bniDiv21 and bniModQ are so easy to write that they're included, too.
e9debf ;;;
10e04e ;;; All functions here are for large code, large data.
45b54c ;;; All use standard "cdecl" calling convention: arguments pushed on the
3ccfaf ;;; stack (ss:sp) right to left (the leftmost agrument at the lowest address)
fa1f08 ;;; and popped by the caller, return values in ax or dx:ax, and register
e7c5ea ;;; usage as follows:
3adebf ;;;
3af1fa ;;; Callee-save (preserved by callee if needed):
2a868c ;;;¤ss, esp, cs, eip, ds, esi, edi, ebp, high PGPByte of FLAGS except DF,
342e86 ;;;¤all other registers (CRx, DRx, TRx, IDT, GDT, LDT, TR, etc.).
36f958 ;;; Caller-save (may be corrupted by callee):
715705 ;;;¤es, eax, ebx, ecx, edx, low PGPByte of flags (SF, ZF, AF, PF, CF)
66debf ;;;
3b3408 ;;; The direction flag (DF) is either preserved or cleared.
be1840 ;;; I'm not sure what the calling convention is for fs and gs. ·This
7ae222 ;;; code never alters them.
e3af5a
82a693 ;; Not all of this code has to be '386 code, but STUPID FUCKING MASM (5.0)
c05dbe ;; gives an error if you change in the middle of a segment. ·Rather than
94a81a ;; fight the thing, just enable '386 instructions everywhere. ·(And lose
2782f7 ;; the error checking.)
d16552 .386
14af5a
77b2bd _TEXT ··segment para public use16 'CODE' ; 16-PGPByte aligned because '486 cares
7a83af ¤   assume ·cs:_TEXT
58af5a
15bc2d ¤   public ·_bniMulN1_16
8fb720 ¤   public ·_bniMulAdd1_16
d5d5d1 ¤   public ·_bniMulSub1_16
6b7129 ¤   public¤ _bniDiv21_16
212818 ¤   public¤ _bniModQ_16
f8af5a
9d6ef5 ¤   public ·_bniMulN1_32
d165f8 ¤   public ·_bniMulAdd1_32
180709 ¤   public ·_bniMulSub1_32
14a3f1 ¤   public¤ _bniDiv21_32
d6fac0 ¤   public¤ _bniModQ_32
46af5a
d02941 ¤   public¤ _not386
e9af5a
59af5a
fb845b ;; Prototype:
2ffa08 ;; BNWORD16
a4aad1 ;; bniMulAdd_16(BNWORD16 *out, BNWORD16 *in, unsigned len, BNWORD16 k)
e65258 ;;
b2684b ;; Multiply len words of "in" by k and add to len words of "out";
420415 ;; return the len+1st word of carry. ·All pointers are to the least-
f2df1c ;; significant ends of the appropriate arrays. ·len is guaraneed > 0.
355258 ;;
949967 ;; This 16-bit code is optimized for an 8086/80286. ·It will not be run
2e60f9 ;; on 32-bit processors except for debugging during development.
285258 ;;
4af70a ;; NOTE that it may be possible to assume that the direction flag is clear
2e7845 ;; on entry; this would avoid the need for the cld instructions. ·Hoewever,
b33d39 ;; the Microsoft C libraries require that the direction flag be clear.
a67556 ;; Thus, bniModQ_16 clears it before returning.
ea5258 ;;
6614cf ;; Stack frame:
e9bc13 ;; +--------+ bp+18
ec88ed ;; | ··k ···|
882603 ;; +--------+ bp+16
2d6971 ;; | ·len ··|
ad15b3 ;; +--------+ bp+14
3f9666 ;; | ·······|
--0de3 0009bcfefd140100160 Page 2 of bni8086.asm
96d585 ;; +- ·in ·-+
8d9666 ;; | ·······|
5d72d3 ;; +--------+ bp+10
1b9666 ;; | ·······|
6162bf ;; +- out ·-+
5f9666 ;; | ·······|
738fba ;; +--------+ bp+6
d49666 ;; | ·······|
e83f6e ;; +-return-+
f99666 ;; | ·······|
1ce8da ;; +--------+ bp+2
fed113 ;; | old bp |
b46780 ;; +--------+ bp
975258 ;;
21e367 ;; Register usage for bniMul1_16:
18f9a1 ;; ds:[si]¤ in
a98586 ;; es:[di]¤ out
12d813 ;; bp¤  ¤   k
b45b5a ;; cx¤  ¤   loop counter (len/4)
4812ea ;; dx,ax¤   high,low parts of product
3de9e0 ;; bx¤  ¤   carry from previous multiply iteration
cc5258 ;;
5cb9c8 ;; Register usage for bniMulAdd1_16 and bniMulSub1_16:
44f9a1 ;; ds:[si]¤ in
971f97 ;; es:[bx+si]¤  out
e9d813 ;; bp¤  ¤   k
f85b5a ;; cx¤  ¤   loop counter (len/4)
f012ea ;; dx,ax¤   high,low parts of product
a623a2 ;; di¤  ¤   carry from previous multiply iteration
6e5258 ;;
3eb7f9 ;; The reson for the difference is that straight mul can use stosw, but
166176 ;; the multiply and add or multiply and subtract add the result in, so
b02388 ;; they have to reference es:[di] to add it in.
3b5258 ;;
6d7f93 ;; The options are either "add ax,es:[di]; stosw" or "add es:[di],ax;
6d73ec ;; add di,2"; both take 10 cycles on an 80286, 27 on an 8086 and 35 on
63010f ;; an 8088 although the former is preferred since it's one PGPByte smaller.
0c37c1 ;; However, using [bx+si] is even faster; "add es:[bx+si],ax" takes
a29a7a ;; 7 cycles on an 80286, 25 on an 8086 and 33 on an 8088, as well as
d05afa ;; being the smallest. ·(Of course, stosw, at 3 on an 80286, 11 on an
0ff1f7 ;; 8086 amd 15 on an 8088 wins easily in the straight multiply case over
e8d4c6 ;; mov es:[bx+si],ax, which takes 3/18/22 cycles and is larger to boot.)
365258 ;;
e39873 ;; Most of these register assignments are driven by the 8086's instruction
e299f2 ;; set. ·The only really practical variation would be to put the multiplier
2bd5f2 ;; k into bx or di and use bp for carry, but if someone can make a faster
74b081 ;; Duff's device using a lookup table, bx and di are useful because indexing
9b84fd ;; off them is more flexible than bp.
615258 ;;
9c9957 ;; Overview of code:
785258 ;;
f10cf8 ;; len is guaranteed to be at least 1, so do the first multiply (with no
a84310 ;; carry in) unconditionally. ·Then go to a min loop unrolled 4 times,
1375a5 ;; jumping into the middle using a variant of Duff's device.
b65258 ;;
2d4c74 ;; The loop is constructed using the loop instruction, which does
c7cbaf ;; "} while (--cnt)". ·This means that we have to divide the count
8de486 ;; by 4, and increment it so it doesn't start at 0. ·To gain a little
6949db ;; bit more efficiency, we actually increment the count by 2, so the
713690 ;; minimum possible value is 3, which will be shifted down to produce 0.
bd21aa ;; usually in Duff's device, if the number of iterations is a multiple
59b1f3 ;; of the unrolling factor, you branch to just before the loop conditional
422a4b ;; and let it handle the case of 0. ·Here, we have a special test for 0
22c44e ;; at the head of the loop and fall through into the top of the loop
4b0198 ;; if it passes.
bd5258 ;;
ea1fcb ;; Basically, with STEP being a multiply step, it's:
f35258 ;;
98ece2 ;; ¤STEP;
fe2ea1 ;;¤ count += 2;
944ce2 ;;¤ mod4 = count % 4;
9be8d4 ;;¤ count /= 4;
--48b7 000f38c846a40100160 Page 3 of bni8086.asm
ddf482 ;;¤ switch(mod4) {
dea221 ;;¤ ··case 3:
8bf739 ;;¤ ¤   if (count) {
3694f7 ;;¤ ··¤ ¤   do {
914be5 ;;¤ ¤   ¤   ¤   STEP;
2cf8fd ;;¤ ··case 2:
c94be5 ;;¤ ¤   ¤   ¤   STEP;
fb1799 ;;¤ ··case 1:
624be5 ;;¤ ¤   ¤   ¤   STEP;
c44d45 ;;¤ ··case 0:
bf4be5 ;;¤ ¤   ¤   ¤   STEP;
766190 ;;¤ ¤   ¤   } while (--count);
be59f9 ;;¤ ¤   }
6c45c4 ;;¤ }
d35258 ;;
c0eab3 ;; The switch() is actually done by two levels of branch instructions
bc9d2c ;; rather than a lookup table.
1eaf5a
993b6c _bniMulN1_16¤   proc¤   far
f3af5a
f74502 ¤   push¤   bp
118e1d ¤   mov¤bp,sp
f3b9b3 ¤   push¤   ds
64d8c2 ¤   push¤   si
edd152 ¤   push¤   di
fd5c16 ¤   cld
9caf5a
06c26e ¤   les¤di,[bp+6]¤  ; out
f00683 ¤   lds¤si,[bp+10]¤ ; in
31fb53 ¤   mov¤cx,[bp+14]¤ ; len
36b6b5 ¤   mov ····bp,[bp+16]¤ ; k
18af5a
366f5a ;; First multiply step has no carry in
3477bd ¤   lodsw
db71cd ¤   mul¤bp
ea3b3d ¤   stosw
7baf5a
b99b94 ;; The switch() for Duff's device starts here
5e505c ;; Note: this *is* faster than a jump table for an 8086 and '286.
e35530 ;; 8086: ·jump table: 44 cycles; this: 27/29/31/41
70cdeb ;; 80286: jump table: 25 cycles; this: 17/17/20/22
95d58e ¤   shr¤cx,1
19471e ¤   jc¤ SHORT m16_odd
3aaf5a
a08fce ¤   inc¤cx
e1d58e ¤   shr¤cx,1
c2dfd8 ¤   jc¤ SHORT m16_case2
2261f5 ¤   jmp¤SHORT m16_case0
6eaf5a
a4ac69 ¤   nop¤¤   ¤   ; To align loop
b82133 m16_odd:
a58fce ¤   inc¤cx
49d58e ¤   shr¤cx,1
8d3250 ¤   jnc¤SHORT m16_case1
9baa94 ¤   jz¤ SHORT m16_done¤ ; Avoid entire loop in this case
97af5a
5ae449 m16_loop:
2a77bd ¤   lodsw
882db0 ¤   mov¤bx,dx¤  ¤   ; Remember carry for later
a171cd ¤   mul¤bp
7ddbdd ¤   add¤ax,bx¤  ¤   ; Add carry in from previous word
11899a ¤   adc¤dx,0
6c3b3d ¤   stosw
544ecb m16_case2:
2077bd ¤   lodsw
832db0 ¤   mov¤bx,dx¤  ¤   ; Remember carry for later
6871cd ¤   mul¤bp
02dbdd ¤   add¤ax,bx¤  ¤   ; Add carry in from previous word
52899a ¤   adc¤dx,0
713b3d ¤   stosw
87a1af m16_case1:
f377bd ¤   lodsw
--fd20 00031d7dd2a40100160 Page 4 of bni8086.asm
3b2db0 ¤   mov¤bx,dx¤  ¤   ; Remember carry for later
ec71cd ¤   mul¤bp
fbdbdd ¤   add¤ax,bx¤  ¤   ; Add carry in from previous word
89899a ¤   adc¤dx,0
aa3b3d ¤   stosw
3afb73 m16_case0:
b877bd ¤   lodsw
2b2db0 ¤   mov¤bx,dx¤  ¤   ; Remember carry for later
9e71cd ¤   mul¤bp
77dbdd ¤   add¤ax,bx¤  ¤   ; Add carry in from previous word
f8899a ¤   adc¤dx,0
643b3d ¤   stosw
30af5a
01a5b7 ¤   loop¤   m16_loop
0baf5a
186582 m16_done:
371f10 ¤   mov¤ax,dx
501f98 ¤   stosw¤  ¤   ¤   ; Store last word
f1d6d5 ¤   pop¤di
5ddf45 ¤   pop¤si
a7be34 ¤   pop¤ds
154285 ¤   pop¤bp
468a83 ¤   ret
09af5a
ed613b _bniMulN1_16¤   endp
03af5a
22af5a
3eefa6 ¤   align¤  2
492022 _bniMulAdd1_16¤ proc¤   far
87af5a
f74502 ¤   push¤   bp
a18e1d ¤   mov¤bp,sp
b1b9b3 ¤   push¤   ds
bdd8c2 ¤   push¤   si
3bd152 ¤   push¤   di
615c16 ¤   cld
61af5a
e7d8f0 ¤   les¤bx,[bp+6]¤  ; out
2d0683 ¤   lds¤si,[bp+10]¤ ; in
a7fb53 ¤   mov¤cx,[bp+14]¤ ; len
c1b6b5 ¤   mov ····bp,[bp+16]¤ ; k
74af5a
b26f5a ;; First multiply step has no carry in
e277bd ¤   lodsw
1971cd ¤   mul¤bp
9bc975 ¤   add¤es:[bx],ax¤ ; This time, store in [bx] directly
36899a ¤   adc¤dx,0
956dfc ¤   sub¤bx,si¤  ¤   ; Prepare to use [bx+si].
96af5a
189b94 ;; The switch() for Duff's device starts here
d1505c ;; Note: this *is* faster than a jump table for an 8086 and '286.
6b5530 ;; 8086: ·jump table: 44 cycles; this: 27/29/31/41
00cdeb ;; 80286: jump table: 25 cycles; this: 17/17/20/22
91d58e ¤   shr¤cx,1
dee630 ¤   jc¤ SHORT ma16_odd
a0af5a
a58fce ¤   inc¤cx
83d58e ¤   shr¤cx,1
afd278 ¤   jc¤ SHORT ma16_case2
c2ae29 ¤   jmp¤SHORT ma16_case0
02af5a
4d6940 ma16_odd:
3e8fce ¤   inc¤cx
35d58e ¤   shr¤cx,1
d11fd9 ¤   jnc¤SHORT ma16_case1
fd4dda ¤   jz¤ SHORT ma16_done¤; Avoid entire loop in this case
37af5a
aca51d ma16_loop:
8c77bd ¤   lodsw
73cd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
a671cd ¤   mul¤bp
316b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
--320a 000c8ad261c40100160 Page 5 of bni8086.asm
e9899a ¤   adc¤dx,0
a2f806 ¤   add¤es:[bx+si],ax
f7899a ¤   adc¤dx,0
355a2b ma16_case2:
7877bd ¤   lodsw
f2cd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
0f71cd ¤   mul¤bp
c86b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
85899a ¤   adc¤dx,0
90f806 ¤   add¤es:[bx+si],ax
ef899a ¤   adc¤dx,0
37b54f ma16_case1:
f177bd ¤   lodsw
94cd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
0a71cd ¤   mul¤bp
0c6b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
b9899a ¤   adc¤dx,0
b8f806 ¤   add¤es:[bx+si],ax
f8899a ¤   adc¤dx,0
ebef93 ma16_case0:
e377bd ¤   lodsw
84cd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
4e71cd ¤   mul¤bp
596b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
2b899a ¤   adc¤dx,0
a3f806 ¤   add¤es:[bx+si],ax
15899a ¤   adc¤dx,0
36af5a
261a09 ¤   loop¤   ma16_loop
6baf5a
b924d6 ma16_done:
af1f10 ¤   mov¤ax,dx
6cd6d5 ¤   pop¤di
eddf45 ¤   pop¤si
bdbe34 ¤   pop¤ds
1e4285 ¤   pop¤bp
908a83 ¤   ret
5daf5a
0e3914 _bniMulAdd1_16¤ endp
9daf5a
1eefa6 ¤   align¤  2
b61167 _bniMulSub1_16¤ proc¤   far
56af5a
3e4502 ¤   push¤   bp
408e1d ¤   mov¤bp,sp
20b9b3 ¤   push¤   ds
b4d8c2 ¤   push¤   si
25d152 ¤   push¤   di
995c16 ¤   cld
7faf5a
f5d8f0 ¤   les¤bx,[bp+6]¤  ; out
420683 ¤   lds¤si,[bp+10]¤ ; in
d4fb53 ¤   mov¤cx,[bp+14]¤ ; len
88b6b5 ¤   mov ····bp,[bp+16]¤ ; k
aaaf5a
b16f5a ;; First multiply step has no carry in
fc77bd ¤   lodsw
d671cd ¤   mul¤bp
4ecf57 ¤   sub¤es:[bx],ax¤ ; This time, store in [bx] directly
4c899a ¤   adc¤dx,0
a26dfc ¤   sub¤bx,si¤  ¤   ; Prepare to use [bx+si].
3aaf5a
c09b94 ;; The switch() for Duff's device starts here
8e505c ;; Note: this *is* faster than a jump table for an 8086 and '286.
c25530 ;; 8086: ·jump table: 44 cycles; this: 27/29/31/41
2bcdeb ;; 80286: jump table: 25 cycles; this: 17/17/20/22
29d58e ¤   shr¤cx,1
60b627 ¤   jc¤ SHORT ms16_odd
59af5a
fc8fce ¤   inc¤cx
79d58e ¤   shr¤cx,1
c85864 ¤   jc¤ SHORT ms16_case2
--7ac1 0001758eb0040100160 Page 6 of bni8086.asm
ef2435 ¤   jmp¤SHORT ms16_case0
83af5a
7b0d2e ms16_odd:
d78fce ¤   inc¤cx
e0d58e ¤   shr¤cx,1
e695c5 ¤   jnc¤SHORT ms16_case1
047af9 ¤   jz¤ SHORT ms16_done¤; Avoid entire loop in this case
a6af5a
3b2f01 ms16_loop:
5777bd ¤   lodsw
bdcd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
8171cd ¤   mul¤bp
2a6b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
81899a ¤   adc¤dx,0
1cd3eb ¤   sub¤es:[bx+si],ax
0c899a ¤   adc¤dx,0
de804c ms16_case2:
1977bd ¤   lodsw
bbcd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
4871cd ¤   mul¤bp
2c6b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
b3899a ¤   adc¤dx,0
17d3eb ¤   sub¤es:[bx+si],ax
b8899a ¤   adc¤dx,0
416f28 ms16_case1:
7d77bd ¤   lodsw
cbcd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
5271cd ¤   mul¤bp
506b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
e4899a ¤   adc¤dx,0
86d3eb ¤   sub¤es:[bx+si],ax
12899a ¤   adc¤dx,0
d135f4 ms16_case0:
9277bd ¤   lodsw
56cd27 ¤   mov¤di,dx¤  ¤   ; Remember carry for later
7171cd ¤   mul¤bp
9a6b92 ¤   add¤ax,di¤  ¤   ; Add carry in from previous word
27899a ¤   adc¤dx,0
c8d3eb ¤   sub¤es:[bx+si],ax
2c899a ¤   adc¤dx,0
71af5a
c37e67 ¤   loop¤   ms16_loop
79af5a
b7aeca ms16_done:
371f10 ¤   mov¤ax,dx
4dd6d5 ¤   pop¤di
dcdf45 ¤   pop¤si
dbbe34 ¤   pop¤ds
594285 ¤   pop¤bp
338a83 ¤   ret
1aaf5a
594aa7 _bniMulSub1_16¤ endp
91af5a
990e07 ;; Two-word by one-word divide. ·Stores quotient, returns remainder.
e0018a ;; BNWORD16 bniDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
1ac2dd ;; ·····················4 ···········8 ···········10 ··········12
f2efa6 ¤   align¤  2
82bc5d _bniDiv21_16¤   proc¤   far
d39105 ¤   mov¤cx,bp¤  ¤   ; bp NOT pushed; note change in offsets
518e1d ¤   mov¤bp,sp
79aeec ¤   mov¤dx,[bp+8]
4314fc ¤   mov¤ax,[bp+10]
bf9704 ¤   div¤WORD PTR [bp+12]
633b66 ¤   les¤bx,[bp+4]
96cfcb ¤   mov¤es:[bx],ax
261f10 ¤   mov¤ax,dx
99c548 ¤   mov¤bp,cx
898a83 ¤   ret
14af5a
2aed9e ¤   nop¤¤   ; To align loop in bniModQ properly
92af5a
17677d _bniDiv21_16¤   endp
--37f2 000131b07c240100160 Page 7 of bni8086.asm
e0af5a
e5dee8 ;; Multi-word by one-word remainder.
ebce9b ;; BNWORD16 bniModQ_16(BNWORD16 *q, unsigned len, unsigned d)
c87591 ;; ····················6 ···········10 ···········12
9e5363 _bniModQ_16¤proc¤   far
d84502 ¤   push¤   bp
218e1d ¤   mov¤bp,sp
7ab9b3 ¤   push¤   ds
8296b4 ¤   mov¤bx,si
cc578f ¤   mov¤cx,10[bp]¤  ; load len
9f6a2d ¤   lds¤si,6[bp]¤   ; load q
a3caa0 ¤   std¤¤   ¤   ; loop MSW to LSW
914698 ¤   add¤si,cx
1d9de8 ¤   mov¤bp,12[bp]¤  ; load d
bd4698 ¤   add¤si,cx
3511b5 ¤   xor¤dx,dx¤  ¤   ; Set up for first divide
97827d ¤   sub¤si,2¤   ¤   ; Adjust pointer to point to MSW
4daf5a
b65275 ¤   lodsw¤  ¤   ¤   ; Load first word
06af5a
537d94 ¤   cmp¤ax,bp¤  ¤   ; See if we can skip first divide
20a1b9 ¤   jnc¤SHORT modq16_inner¤ ; No such luck
018bcd ¤   mov¤dx,ax¤  ¤   ; Yes! ·Modulus > input, so remainder = input
861023 ¤   dec¤cx¤ ¤   ; Do loop
b3e49a ¤   jz¤ SHORT modq16_done
62af5a
758250 modq16_loop:
b277bd ¤   lodsw
8ad971 modq16_inner:
14bb58 ¤   div¤bp
0081b3 ¤   loop¤   modq16_loop
71039b modq16_done:
35be34 ¤   pop¤ds
efb33f ¤   mov¤ax,dx¤  ; Return remainder
8e4285 ¤   pop¤bp
f33c2b ¤   mov¤si,bx
f889d7 ¤   cld¤¤   ; Microsoft C's libraries assume this
e38a83 ¤   ret
4caf5a
ba590d _bniModQ_16¤endp
28af5a
f1af5a
334079 ;; Similar, but using 32-bit operations.
485258 ;;
57208a ;; The differences are that the switch() in Duff's device is done using
ffa8a3 ;; a jump table, and lods is not used because it's slower than load and
e71175 ;; increment. ·The pointers are only updated once per loop; offset
211330 ;; addressing modes are used, since they're no slower. ·[di] is used
f8ec72 ;; instead of [bx+si] because the extra increment of di take only one
f3a7c1 ;; cycle per loop a '486, while [bx+si] takes one extra cycle per multiply.
5a5258 ;;
9c89b9 ;; The register assignments are also slightly different:
375258 ;;
1e7cf4 ;; es:[si]¤ in
ec802b ;; ds:[di]¤ out
629efd ;; ecx¤ ¤   k
348a56 ;; bp¤  ¤   loop counter (len/4)
631ddf ;; edx,eax¤ high,low parts of product
1d5d3a ;; ebx¤ ¤   carry word from previous multiply iteration
905258 ;;
240a50 ;; The use of bp for a loop counter lets all the 32-bit values go
9e4224 ;; in caller-save registers, so there's no need to do any 32-bit
7f1032 ;; saves and restores. ·Using ds:di for the destination saves one
40b20d ;; segment override in the bniMulN1_32 code, since there's one more
501b31 ;; store to [di] than load from es:[si].
a85258 ;;
d6e558 ;; Given the number of 32-bit references that this code uses, optimizing
e475a7 ;; it for the Pentium is interesting, because the Pentium has a very
f62fa8 ;; inefficient implementation of prefix bytes. ·Each prefix PGPByte, with
8c054b ;; the exception of 0x0f *>> on conditional branch instructions ONLY <<*
928e1f ;; is a 1-cycle non-pairiable instruction. ·Which has the effect of
13e9e4 ;; forcing the instruction it's on into the U pipe. ·But this code uses
--e167 0009cc10ba840100160 Page 8 of bni8086.asm
c2f7d2 ;; *lots* of prefix bytes, notably the 0x66 operand size override.
9a5258 ;;
9192a1 ;; For example "add [di],eax" is advised against in Intel's optimization
b0634a ;; papers, because it takes 3 cycles and 2 of them are not pairable.
d0b249 ;; But any longer sequence would have a prefix PGPByte on every instruction,
e47b6e ;; resulting in even more non-pairable cycles. ·Also, only two instructions
1eefca ;; in the multiply kernel can go in the V pipe (the increments of si and
85584c ;; di), and they're already there, so the pairable cycles would be wasted.
6f5258 ;;
3882eb ;; Things would be *quite* different in native 32-bit mode.
7d5258 ;;
66e752 ;; All instructions that could go in the V pipe that aren't there are
47bb2a ;; marked.
9d5258 ;;
0525db ;; The setup code is quite intricately interleaved to get the best possible
13bae4 ;; performance out of a Pentium. ·If you want to follow the code,
a0a997 ;; pretend that the sections actually come in the following order:
e4f5ad ;; 1) prologue (push registers)
50dc68 ;; 2) load (fetch arguments)
49e995 ;; 3) first multiply
3be5a1 ;; 4) loop unrolling
0d5258 ;;
02221e ;; The loop unrolling setup consists of taking the count, adjusting
65c781 ;; it to account for the first multiply, and splitting it into
f2a880 ;; two parts: the high bits are a loop count, while the low bits are
0ab5cf ;; used to find the right entry in the Duff's device jump table and
4ffe82 ;; to adjust the initial data pointers.
805258 ;;
f7d028 ;; Known slack: There is one instruction in the prologue and one in
32fc3f ;; the epilogue that could go in the V pipe if I could find a U-pipe
5bb666 ;; instruction to pair them with, but all the U-pipe instructions
2adb68 ;; are already paired, so it looks difficult.
135258 ;;
b4cd9a ;; There is a cycle of Address Generation Interlock in the bniMulN1_32
4b553d ;; code on the Pentium (not on a '486). ·I can't figure out how to
10e8fd ;; get rid of it without wasting time elsewhere. ·The problem is that
d6ad95 ;; the load of bx needs to be done as soon as possible to let it
a440f0 ;; be set up in time for the switch(). ·The other problem is the
c336a1 ;; epilogue code which can waste time if the order of the pushed
3620ef ;; registers is diddled with so that ds doesn't come between si and di.
f95258 ;;
bce753 ;; The increment of si after the last load is redundant, and the
8b9775 ;; copy of the high word of the product to the carry after the last
7051cb ;; multiply is likewise unnecessary.
025258 ;;
d8e96e ;; In these cases, the operations were done that way in order to remove
4f3684 ;; cycles from the loop on the '486 and/or Pentium, even though it costs
32b146 ;; a few overhead cycles on a '386.
4070c7 ;; The increment fo si has to be done early because a load based on si
873a57 ;; is the first thing in any given multiply step, and the address
e84add ;; generation interlock on the '486 and Pentium requires that a full
f32033 ;; cycle (i.e. possibly two instructions on a Pentium) pass between
8d777e ;; incrementing a register and using it in an address.
0b71d6 ;; This saves one cycle per multiply on a '486 and Pentium, and costs
fae7e0 ;; 2 cycles per call to the function on a '386 and 1 cycle on a '486.
f95258 ;;
1a142e ;; The carry word is copied where it is so that the decrement of the loop
6fabd7 ;; counter happens in the V pipe. ·The instruction between the decrement
7395ab ;; of the loop counter and the branch should be a U-pipe instruction that
e99e6b ;; doesn't affect the flags. ·Thus, the "mov" was rotated down from
6a8831 ;; the top of the loop to fill the slot.
79f409 ;; This is a bit more marginal: it saves one cycle per loop iteration on
1e0b26 ;; a Pentium, and costs 2 cycles per call on a '386, '486 or Pentium.
045258 ;;
f4d89d ;; The same logic applies to the copy of the carry and increment of si
9345d4 ;; before the test, in case 0, for skipping the loop entirely.
926e3b ;; It makes no difference in speed if the loop is executed, but
2dc2b3 ;; incrementing si before saves an address generation interlock cycle
af75b1 ;; On a '486 and Pentium in the case that the loop is executed.
7fda04 ;; And the loop is executed more often than not.
b55258 ;;
9c258c ;; Given that just one multiply on a '386 takes 12 to 41 cycles (with the
--9093 000444dba1b40100160 Page 9 of bni8086.asm
44f056 ;; average being very much at the high end of that) 4 cycles of additional
48d548 ;; overhead per call is not a big deal.
6d5258 ;;
31d7c3 ;; On a Pentium, it would actually be easier to *not* unroll the loop
527500 ;; at all, since the decrement and compare are completely hidden
badfa6 ;; in the V-pipe and it wouldn't cost anything to do them more often.
13dc65 ;; That would save the setup for the unrolling and Duff's device at the
a74c77 ;; beginning. ·But the overhead for that is pretty minor: ignoring what's
54e140 ;; hidden in the V pipe, it's two cycles plus the indirect jump.
a83a9d ;; Not too much, and special-casing the pentium is quite a hassle.
d0cb11 ;; (For starters, you have to detect it, and since you're probably in
324bb1 ;; V86 mode, without access to the EFLAGS register to test the CPUID bit.)
b6af5a
73af5a
769fef ¤   align¤  16
81828f _bniMulN1_32¤   proc¤   far
57af5a
8f9717 ¤   push¤   bp¤ ¤   ; U¤prologue¤   ** Could be V
a94832 ¤   mov¤bp,sp¤  ¤   ; V¤prologue
497c4c ¤   push¤   si¤ ¤   ; U¤prologue¤   ** Could be V
8dee5c ¤   mov¤bx,[bp+14]¤ ; U¤load len¤   ** Could be V (AGI!)r
4d7d4f ¤   push¤   ds¤ ¤   ; NP¤   prologue
c666e3 ¤   les¤si,[bp+10]¤ ; NP¤   load in
ad1f44 ¤   mov ····ecx,[bp+16]¤; U¤load k
91dc10 ¤   dec¤bx¤ ¤   ; V¤loop unrolling
0ce74c ¤   shl¤bx,2¤   ¤   ; U¤loop unrolling
8d5640 ¤   push¤   di¤ ¤   ; V¤prologue
7b508b ¤   lds¤di,[bp+6]¤  ; NP¤   load out
ddb824 ¤   mov¤bp,bx¤  ¤   ; U¤loop unrolling¤ ** Could be V
a49ff3 ¤   and¤bx,12¤  ¤   ; V¤loop unrolling
c6af5a
7316b9 ;; First multiply step has no carry in.
e5789d ¤   mov¤eax,es:[si]¤; U¤first multiply
73b1f1 ¤   add¤si,bx¤  ¤   ; V¤loop unrolling
1b6f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
37e7d6 ¤   mov¤[di],eax¤   ; U¤first multiply
efc9d3 ¤   add¤di,bx¤  ¤   ; V¤loop unrolling
c5af5a
22ef2f ;; The switch() for Duff's device. ·This jump table is (slightly!) faster
da20f8 ;; than a bunch of branches on a '386 and '486, and is probably better yet
a05fa2 ;; on higher processors.
0288e4 ¤   jmp¤WORD PTR cs:m32_jumptable[bx]¤  ; NP¤   loop unrolling
fb53d9 ¤   align 2
88bad8 m32_jumptable:
e6c96b ¤   dw¤ OFFSET m32_case0, 0
25c22f ¤   dw¤ OFFSET m32_case1, 0
35dfe3 ¤   dw¤ OFFSET m32_case2, 0
121598 ¤   dw¤ OFFSET m32_case3, 0, 0, 0, 0¤   ; Get loop aligned properly
fbaf5a
5f9cd8 m32_case0:
438e45 ¤   add¤si,16¤  ¤   ; U¤Fix up si¤  ** Could be V
074514 ¤   test¤   bp,bp¤  ¤   ; V
69f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
15b613 ¤   jbe¤SHORT m32_done¤ ; V¤Avoid entire loop if loop count is 0
eeaf5a
d2696d m32_loop:
375784 ¤   mov¤eax,es:[si-12]¤ ; U
cb8f8c ¤   add¤di, 16¤ ¤   ; V
074ed8 ¤   mul¤ecx¤¤   ; NP
f0f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
09621c ¤   adc¤edx,0¤  ¤   ; U
51ac70 ¤   mov¤[di-12],eax¤; U
d573bc m32_case3:
83f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
94c466 ¤   mov¤eax,es:[si-8]¤  ; U
b64ed8 ¤   mul¤ecx¤¤   ; NP
85f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
65621c ¤   adc¤edx,0¤  ¤   ; U
b5f6b9 ¤   mov¤[di-8],eax¤ ; U
202960 m32_case2:
2ef162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
448449 ¤   mov¤eax,es:[si-4]¤  ; U
--0dd2 0003dba5db140100160 Page 10 of bni8086.asm
344ed8 ¤   mul¤ecx¤¤   ; NP
c7f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
94621c ¤   adc¤edx,0¤  ¤   ; U
2ef923 ¤   mov¤[di-4],eax¤ ; U
30c604 m32_case1:
dbf162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
a40fe2 ¤   mov¤eax,es:[si]¤; U
c44ed8 ¤   mul¤ecx¤¤   ; NP
9af7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
ac621c ¤   adc¤edx,0¤  ¤   ; U
239899 ¤   add¤si,16 ·¤¤   ; V
a793a3 ¤   mov¤[di],eax¤   ; U
a3af5a
3749a0 ¤   sub¤bp,16¤  ¤   ; V
20f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
7a698b ¤   ja¤ m32_loop¤   ; V
31af5a
f9e8a6 m32_done:
8c73ac ¤   mov¤[di+4],edx¤ ; U
ea757c ¤   pop¤di¤ ¤   ; V
e4669b ¤   pop¤ds¤ ¤   ; NP
3a48cf ¤   pop¤si¤ ¤   ; U¤** Could be V
1beacf ¤   pop¤bp¤ ¤   ; V
ad8622 ¤   ret¤¤   ¤   ; NP
5daf5a
e27a85 _bniMulN1_32¤   endp
11af5a
20af5a
3a9fef ¤   align¤  16
251caa _bniMulAdd1_32¤ proc¤   far
d7af5a
519717 ¤   push¤   bp¤ ¤   ; U¤prologue¤   ** Could be V
124832 ¤   mov¤bp,sp¤  ¤   ; V¤prologue
997d4f ¤   push¤   ds¤ ¤   ; NP¤   prologue
52af5a
1f1f44 ¤   mov ····ecx,[bp+16]¤; U¤load k
c619c8 ¤   mov¤bx,[bp+14]¤ ; V¤load len
10cc2d ¤   push¤   di¤ ¤   ; U¤prologue¤   ** Could be V
36dc10 ¤   dec¤bx¤ ¤   ; V¤loop unrolling
40508b ¤   lds¤di,[bp+6]¤  ; NP¤   load out
6fe74c ¤   shl¤bx,2¤   ¤   ; U¤loop unrolling
2bbcb7 ¤   push¤   si¤ ¤   ; V¤prologue
5d66e3 ¤   les¤si,[bp+10]¤ ; NP¤   load in
77af5a
dcb824 ¤   mov¤bp,bx¤  ¤   ; U¤loop unrolling¤ ** Could be V
389ff3 ¤   and¤bx,12¤  ¤   ; V¤loop unrolling
3caf5a
2516b9 ;; First multiply step has no carry in.
c4789d ¤   mov¤eax,es:[si]¤; U¤first multiply
8fb1f1 ¤   add¤si,bx¤  ¤   ; V¤loop unrolling
266f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
2970e5 ¤   add¤[di],eax¤   ; U¤first multiply
e15e18 ¤   adc¤edx,0¤  ¤   ; U¤first multiply
44c9d3 ¤   add¤di,bx¤  ¤   ; V¤loop unrolling
e6af5a
72ef2f ;; The switch() for Duff's device. ·This jump table is (slightly!) faster
4620f8 ;; than a bunch of branches on a '386 and '486, and is probably better yet
a95fa2 ;; on higher processors.
fb1e12 ¤   jmp¤WORD PTR cs:ma32_jumptable[bx]¤ ; NP¤   loop unrolling
8453d9 ¤   align 2
38e8a6 ma32_jumptable:
551277 ¤   dw¤ OFFSET ma32_case0, 0
e61933 ¤   dw¤ OFFSET ma32_case1, 0
3f04ff ¤   dw¤ OFFSET ma32_case2, 0
9cc6c7 ¤   dw¤ OFFSET ma32_case3, 0, 0¤; To get loop aligned properly
96af5a
658838 ma32_case0:
448e45 ¤   add¤si,16¤  ¤   ; U¤Fix up si¤  ** Could be V
814514 ¤   test¤   bp,bp¤  ¤   ; V
40f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
62c06f ¤   jbe¤SHORT ma32_done¤; V¤Avoid entire loop if loop count is 0
3daf5a
--7ead 000b848895e40100160 Page 11 of bni8086.asm
362839 ma32_loop:
6f5784 ¤   mov¤eax,es:[si-12]¤ ; U
bf8f8c ¤   add¤di, 16¤ ¤   ; V
3b4ed8 ¤   mul¤ecx¤¤   ; NP
20f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
86621c ¤   adc¤edx,0¤  ¤   ; U
ba0b5b ¤   add¤[di-12],eax¤; U
7b621c ¤   adc¤edx,0¤  ¤   ; U
5d675c ma32_case3:
76f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
8fc466 ¤   mov¤eax,es:[si-8]¤  ; U
ff4ed8 ¤   mul¤ecx¤¤   ; NP
97f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
2b621c ¤   adc¤edx,0¤  ¤   ; U
385192 ¤   add¤[di-8],eax¤ ; U
47621c ¤   adc¤edx,0¤  ¤   ; U
053d80 ma32_case2:
86f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
418449 ¤   mov¤eax,es:[si-4]¤  ; U
334ed8 ¤   mul¤ecx¤¤   ; NP
01f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
4d621c ¤   adc¤edx,0¤  ¤   ; U
7d5e08 ¤   add¤[di-4],eax¤ ; U
91621c ¤   adc¤edx,0¤  ¤   ; U
8dd2e4 ma32_case1:
0af162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
0a0fe2 ¤   mov¤eax,es:[si]¤; U
214ed8 ¤   mul¤ecx¤¤   ; NP
8bf7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
fb621c ¤   adc¤edx,0¤  ¤   ; U
299899 ¤   add¤si,16 ·¤¤   ; V
2a3488 ¤   add¤[di],eax¤   ; U
a6621c ¤   adc¤edx,0¤  ¤   ; U
4eaf5a
da49a0 ¤   sub¤bp,16¤  ¤   ; V
a5f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
4d72b4 ¤   ja¤ ma32_loop¤  ; V
2caf5a
29a9f2 ma32_done:
c49e46 ¤   pop¤si¤ ; U¤** Could be V
0d14d1 ¤   pop¤di¤ ; V
c3a312 ¤   mov¤ax,dx¤  ; U¤return value low¤   ** Could be V
537831 ¤   pop¤ds¤ ; NP
8ad000 ¤   shr¤edx,16¤ ; U¤return value high
01fd90 ¤   pop¤bp¤ ; V
155aef ¤   ret¤¤   ; NP
42af5a
6fb430 _bniMulAdd1_32¤ endp
92af5a
faaf5a
2f9fef ¤   align¤  16
332def _bniMulSub1_32¤ proc¤   far
21af5a
999717 ¤   push¤   bp¤ ¤   ; U¤prologue¤   ** Could be V
ca4832 ¤   mov¤bp,sp¤  ¤   ; V¤prologue
187d4f ¤   push¤   ds¤ ¤   ; NP¤   prologue
7eaf5a
1b1f44 ¤   mov ····ecx,[bp+16]¤; U¤load k
6919c8 ¤   mov¤bx,[bp+14]¤ ; V¤load len
f0cc2d ¤   push¤   di¤ ¤   ; U¤prologue¤   ** Could be V
4adc10 ¤   dec¤bx¤ ¤   ; V¤loop unrolling
49508b ¤   lds¤di,[bp+6]¤  ; NP¤   load out
28e74c ¤   shl¤bx,2¤   ¤   ; U¤loop unrolling
9abcb7 ¤   push¤   si¤ ¤   ; V¤prologue
fa66e3 ¤   les¤si,[bp+10]¤ ; NP¤   load in
72af5a
d2b824 ¤   mov¤bp,bx¤  ¤   ; U¤loop unrolling¤ ** Could be V
509ff3 ¤   and¤bx,12¤  ¤   ; V¤loop unrolling
65af5a
fc16b9 ;; First multiply step has no carry in.
b9789d ¤   mov¤eax,es:[si]¤; U¤first multiply
b8b1f1 ¤   add¤si,bx¤  ¤   ; V¤loop unrolling
--643f 00089a6f9af40100160 Page 12 of bni8086.asm
1b6f82 ¤   mul¤ecx¤¤   ; NP¤   first multiply
615404 ¤   sub¤[di],eax¤   ; U¤first multiply
9c5e18 ¤   adc¤edx,0¤  ¤   ; U¤first multiply
17c9d3 ¤   add¤di,bx¤  ¤   ; V¤loop unrolling
17af5a
0bef2f ;; The switch() for Duff's device. ·This jump table is (slightly!) faster
3820f8 ;; than a bunch of branches on a '386 and '486, and is probably better yet
195fa2 ;; on higher processors.
0f2931 ¤   jmp¤WORD PTR cs:ms32_jumptable[bx]¤ ; NP¤   loop unrolling
d853d9 ¤   align 2
31da16 ms32_jumptable:
7243fd ¤   dw¤ OFFSET ms32_case0, 0
cb48b9 ¤   dw¤ OFFSET ms32_case1, 0
3d5575 ¤   dw¤ OFFSET ms32_case2, 0
64a049 ¤   dw¤ OFFSET ms32_case3, 0, 0¤; To get loop aligned properly
9aaf5a
13525f ms32_case0:
698e45 ¤   add¤si,16¤  ¤   ; U¤Fix up si¤  ** Could be V
f54514 ¤   test¤   bp,bp¤  ¤   ; V
30f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
86ed1d ¤   jbe¤SHORT ms32_done¤; V¤Avoid entire loop if loop count is 0
9eaf5a
59a225 ms32_loop:
7a5784 ¤   mov¤eax,es:[si-12]¤ ; U
2a8f8c ¤   add¤di, 16¤ ¤   ; V
f34ed8 ¤   mul¤ecx¤¤   ; NP
9df7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
b5621c ¤   adc¤edx,0¤  ¤   ; U
3ccd6b ¤   sub¤[di-12],eax¤; U
cc621c ¤   adc¤edx,0¤  ¤   ; U
81bd3b ms32_case3:
8ff162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
62c466 ¤   mov¤eax,es:[si-8]¤  ; U
c14ed8 ¤   mul¤ecx¤¤   ; NP
e4f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
ba621c ¤   adc¤edx,0¤  ¤   ; U
dc97a2 ¤   sub¤[di-8],eax¤ ; U
d1621c ¤   adc¤edx,0¤  ¤   ; U
27e7e7 ms32_case2:
a9f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
9c8449 ¤   mov¤eax,es:[si-4]¤  ; U
034ed8 ¤   mul¤ecx¤¤   ; NP
36f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
46621c ¤   adc¤edx,0¤  ¤   ; U
589838 ¤   sub¤[di-4],eax¤ ; U
a8621c ¤   adc¤edx,0¤  ¤   ; U
180883 ms32_case1:
33f162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
2b0fe2 ¤   mov¤eax,es:[si]¤; U
8e4ed8 ¤   mul¤ecx¤¤   ; NP
f3f7d8 ¤   add¤eax,ebx¤¤   ; U¤Add carry in from previous word
60621c ¤   adc¤edx,0¤  ¤   ; U
149899 ¤   add¤si,16 ·¤¤   ; V
76f2b8 ¤   sub¤[di],eax¤   ; U
d1621c ¤   adc¤edx,0¤  ¤   ; U
0baf5a
6849a0 ¤   sub¤bp,16¤  ¤   ; V
2ff162 ¤   mov¤ebx,edx¤¤   ; U¤Remember carry for later
b64004 ¤   ja¤ ms32_loop¤  ; V
9caf5a
5b23ee ms32_done:
989e46 ¤   pop¤si¤ ; U¤** Could be V
7714d1 ¤   pop¤di¤ ; V
90a312 ¤   mov¤ax,dx¤  ; U¤return value low¤   ** Could be V
247831 ¤   pop¤ds¤ ; NP
5ad000 ¤   shr¤edx,16¤ ; U¤return value high
4bfd90 ¤   pop¤bp¤ ; V
575aef ¤   ret¤¤   ; NP
12af5a
b8c783 _bniMulSub1_32¤ endp
75af5a
89af5a
--8837 000271ca2b340100160 Page 13 of bni8086.asm
e0af5a
e326d7 ;; Just for interest's sake, here's a completely Pentium-optimized version.
98296a ;; In addition to being smaller, it takes 8 + (8+mul_time)*n cycles, as
957c83 ;; compared to the 10 + jmp_time + (8+mul_time)*n cycles for the loop above.
d48dcc ;; (I don't know how long a 32x32->64 bit multiply or an indirect jump
a18f2f ;; take on a Pentium, so plug those numbers in.)
f1f05d ;¤  align¤  2
c6789e ;¤  nop¤; To align loop nicely
bba1e9 ;P_bniMulAdd1_32¤   proc¤   far
cdfd50 ;
63cf2c ;¤  push¤   bp¤ ¤   ; U¤prologue¤   ** Could be V
3738f6 ;¤  mov¤bp,sp¤  ¤   ; V¤prologue
14b4a2 ;¤  push¤   ds¤ ¤   ; NP¤   prologue
d5c109 ;¤  mov ····ecx,[bp+16]¤; U¤load k
fecc73 ;¤  push¤   si¤ ¤   ; V¤prologue
a83ae8 ;¤  lds¤si,[bp+10]¤ ; NP¤   load in
817050 ;¤  mov¤eax,[si]¤   ; U¤first multiply
602684 ;¤  push¤   di¤ ¤   ; V¤prologue
e46dae ;¤  mul¤ecx¤¤   ; NP¤   first multiply
18ee04 ;¤  les¤di,[bp+6]¤  ; NP¤   load out
8f5189 ;¤  add¤es:[di],eax¤; U¤first multiply
8aa30e ;¤  mov¤bp,[bp+14]¤ ; V¤load len
495c34 ;¤  adc¤edx,0¤  ¤   ; U¤first multiply
19818e ;¤  dec ····bp¤ ¤   ; V
331f98 ;¤  mov¤ebx,edx¤¤   ; U¤Remember carry for later
09f887 ;¤  je¤ Pma32_done¤ ; V
aea66e ;Pma32_loop:
92dee5 ;¤  mov¤eax,[si+4]¤ ; U
d0971d ;¤  add¤di,4¤   ¤   ; V
6dd032 ;¤  mul¤ecx¤¤   ; NP
84326f ;¤  add¤eax,ebx¤¤   ; U¤Add carry in from previous word
5c9b8a ;¤  adc¤edx,0¤  ¤   ; U
a084d6 ;¤  add¤si,4¤   ¤   ; V
819d7b ;¤  add¤es:[di],eax¤; U
439b8a ;¤  adc¤edx,0¤  ¤   ; U
28c4d0 ;¤  dec¤bp¤ ¤   ; V
f41f98 ;¤  mov¤ebx,edx¤¤   ; U¤Remember carry for later
fae36e ;¤  jne¤Pma32_loop¤ ; V
a327a5 ;Pma32_done:
de8cb6 ;¤  pop¤di¤ ; U¤** Could be V
37a371 ;¤  pop¤si¤ ; V
a7cbfa ;¤  pop¤ds¤ ; NP
506ad4 ;¤  mov¤ax,dx¤  ; U¤return value low¤   ** Could be V
b08d46 ;¤  pop¤bp¤ ; V
67ec22 ;¤  shr¤edx,16¤ ; U¤return value high
ffe924 ;¤  ret¤¤   ; NP
befd50 ;
b77e52 ;P_bniMulAdd1_32¤   endp
94af5a
f3af5a
c6af5a
c00e07 ;; Two-word by one-word divide. ·Stores quotient, returns remainder.
057dc5 ;; BNWORD32 bniDiv21_32(BNWORD32 *q, BNWORD32 nh, BNWORD32 nl, BNWORD32 d)
2535e9 ;; ·····················4 ···········8 ···········12 ··········16
499fef ¤   align¤  16
b505be _bniDiv21_32¤   proc¤   far
a1f6e5 ¤   mov¤cx,bp¤  ¤   ¤   ; U¤bp NOT pushed; offsets differ
4bbaf0 ¤   mov¤bp,sp¤  ¤   ¤   ; V
307c72 ¤   ¤   ¤   ¤   ¤   ; AGI
47cdad ¤   mov¤edx,[bp+8]¤ ¤   ; U
508cce ¤   mov¤eax,[bp+12]¤¤   ; U
ce9e10 ¤   div¤DWORD PTR [bp+16]¤  ; NP
d75587 ¤   les¤bx,[bp+4]¤  ¤   ; NP
2b127e ¤   mov¤es:[bx],eax¤¤   ; U
b9411f ¤   mov¤ax,dx¤  ¤   ¤   ; V
bd5c3c ¤   shr¤edx,16¤ ¤   ¤   ; U
49e2d5 ¤   mov¤bp,cx¤  ¤   ¤   ; V
f21cd8 ¤   ret¤¤   ¤   ¤   ; NP
eeaf5a
54ca0c ¤   nop
5fca0c ¤   nop
27ca0c ¤   nop
--8301 000a35c431240100160 Page 14 of bni8086.asm
d251f8 ¤   nop¤¤   ¤   ¤   ; Get bniModQ_32 aligned properly
0caf5a
d77cc3 _bniDiv21_32¤   endp
57af5a
cfdee8 ;; Multi-word by one-word remainder.
a9ba42 ;; This speeds up key generation. ·It's not worth unrolling and so on;
164852 ;; using 32-bit divides is enough of a speedup.
535258 ;;
be691c ;; bp is used as a counter so that all the 32-bit values can be in
efb32b ;; caller-save registers (eax, ecx, edx). ·bx is needed as a pointer.
865258 ;;
ccd2b2 ;; The modulus (in ebp) is 16 bits. ·Given that the dividend is 32 bits,
691564 ;; the chances of saving the first divide because the high word of the
2eceea ;; dividend is less than the modulus are low enough it's not worth taking
a6cce4 ;; the cycles to test for it.
4f5258 ;;
a248fa ;; unsigned bniModQ_32(BNWORD16 *q, unsigned len, unsigned d)
387591 ;; ····················6 ···········10 ···········12
49308e _bniModQ_32¤proc¤   far
15ace9 ¤   xor¤ecx,ecx¤¤   ; U¤Clear ecx (really, the high half)
f85bf4 ¤   push¤   bp¤ ¤   ; V
fd9fd4 ¤   mov¤edx,ecx¤¤   ; U¤Clear high word for first divide
42101d ¤   mov¤bp,sp¤  ¤   ; V
b7e97a ¤   push¤   ds¤ ¤   ; NP
8775a4 ¤   lds¤ax,[bp+6]¤  ; NP¤   Load dividend pointer
754c5b ¤   mov¤bx,[bp+10]¤ ; U¤Load count¤ ** Could be V
32eee6 ¤   sub¤ax,4¤   ¤   ; V¤Offset dividend pointer
9a418a ¤   mov¤cx,[bp+12]¤ ; U¤Load modulus¤   ** Could be V
c1a6df ¤   mov¤bp,bx¤  ¤   ; V¤Copy count
b54e49 ¤   shl¤bx,2¤   ¤   ; U¤Shift index
033c17 ¤   add¤bx,ax¤  ¤   ; U¤Add base¤   ** Could be V
6c7098 ;¤  lea¤bx,[eax+ebp*4-4]; U¤Move pointer to high word
41af5a
b40f74 modq32_loop:
da0d94 ¤   mov¤eax,[bx]¤   ; U
0c7e26 ¤   sub¤bx,4¤   ¤   ; V
7f6443 ¤   div¤ecx¤¤   ; NP
571c0d ¤   dec¤bp¤ ¤   ; U¤** Could be V
aa1fb6 ¤   jnz¤modq32_loop¤; V
5e8ebf modq32_done:
a4669b ¤   pop¤ds¤ ¤   ; NP
b6a373 ¤   mov¤ax,dx¤  ¤   ; U¤** Could be V
f7eacf ¤   pop¤bp¤ ¤   ; V
568622 ¤   ret¤¤   ¤   ; NP
fbaf5a
a43d14 _bniModQ_32¤endp
27af5a
5daf5a
c8d225 ;; int not386(void) returns 0 on a 32-bit (386 or better) processor;
ca0331 ;; non-zero if an 80286 or lower. ·The Z flag is set to reflect
16c3ed ;; ax on return. ·This is only called once, so it doesn't matter how
0a0122 ;; it's aligned.
69af5a
55ad42 _not386 proc¤   far
b35258 ;;
0567e7 ;; This first test detects 80x86 for x < 2. ·On the 8086 and '186,
bfe705 ;; "push sp" does "--sp; sp[0] = sp". ·On all later processors, it does
b85859 ;; "sp[-1] = sp; --sp".
285258 ;;
2a9a4b ¤   push¤   sp
886321 ¤   pop¤ax
dfddeb ¤   sub¤ax,sp
b72866 ¤   jne¤SHORT return
4caf5a
c47be0 ;; This test is the key one. ·It will probably detect 8086, V30 and 80186
cdbeb6 ;; as well as 80286, but I haven't had access to test it on any of those,
52fc42 ;; so it's protected by the well-known test above. ·It has been tested
71e367 ;; on the 80286, 80386, 80486, Pentium and AMD tested it on their K5.
6e46cf ;; I have not been able to confirm effectiveness on the P6 yet, although
08f39f ;; someone I spoke to at Intel said it should work.
bb5258 ;;
a38a1d ;; This test uses the fact that the '386 and above have a barrel shifter
--51a1 001a65cdce540100160 Page 15 of bni8086.asm
19d49c ;; to do shifts, while the '286 does left shifts by releated adds.
0cb6e1 ;; That means that on the '286, the auxilliary carry gets a copy of
916f1e ;; bit 4 of the shift output, while on the '386 and up, it's trashed
fbe9bc ;; (as it happens, set to 1) independent of the result. ·(It's documented
7e87ac ;; as undefined.)
c15258 ;;
1a177f ;; We do two shifts, which should produce different auxilliary carries
a46311 ;; on a '286 and XOR them to see if they are different. ·Even on a
da311a ;; future processor that does something different with the aux carry
d4b61b ;; flag, it probably does something data-independent, so this will still
cc2241 ;; work. ·Note that all flags except aux carry are defined for shl
2eb23e ;; output and will be the same for both cases.
f6af5a
d6dbca ¤   mov¤al,4
5a1148 ¤   shl¤al,1¤   ; Expected to produce ac = 0 on a '286
2f5294 ¤   lahf
f8941d ¤   shl¤al,1¤   ; Expected to produce ac = 1 on a '286
6e2a6c ¤   mov¤al,ah
0f5294 ¤   lahf
56d5e5 ¤   xor¤al,ah¤  ; Xor the flags together to detect the difference
ec7090 ¤   mov¤ah,al¤  ; Clear ah if al is clear, leave Z flag alone
bca3d7 return:
788a83 ¤   ret
27af5a
cc581c _not386¤endp
90af5a
446f03 _TEXT¤  ends
dcaf5a
a6a234 ¤   end
--2cf7 00061aa3bc040100161 Page 1 of bni8086.h
bc38e5 /*
b13940 ·* bni8086.h - This file defines the interfaces to the 8086
e660e8 ·* assembly primitives for 16-bit MS-DOS environments.
629387 ·* It is intended to be included in "bni.h"
7e7924 ·* via the "#include BNINCLUDE" mechanism.
e4775e ·*
f32b28 ·* $Id: bni8086.h,v 1.2 1997/05/05 19:49:12 lloyd Exp $
a3495d ·*/
d5d83c ·
cd7be2 #define BN_LITTLE_ENDIAN 1
a9af5a
aa3379 #ifdef __cplusplus
158078 /* These assembly-language primitives use C names */
996dad extern "C" {
8d7454 #endif
d2af5a
a1ad48 /* Set up the appropriate types */
d7e08e typedef unsigned short bnword16;
0d4434 #define BNWORD16 bnword16
0469da typedef unsigned long bnword32;
f1ca02 #define BNWORD32 bnword32
b3af5a
051597 void __cdecl __far
767285 bniMulN1_16(bnword16 __far *out, bnword16 const __far *in,
8d7cf1 ············unsigned len, bnword16 k);
97a1dd #define bniMulN1_16 bniMulN1_16
c9caf9 ············
dde8e8 bnword16 __cdecl __far
3cfd33 bniMulAdd1_16(bnword16 __far *out, bnword16 const __far *in,
dc7ef0 ··············unsigned len, bnword16 k);
dca40c #define bniMulAdd1_16 bniMulAdd1_16
7f7516 ·······
5be8e8 bnword16 __cdecl __far
711f60 bniMulSub1_16(bnword16 __far *out, bnword16 const __far *in,
637ef0 ··············unsigned len, bnword16 k);
93d365 #define bniMulSub1_16 bniMulSub1_16
4eaf5a
33e8e8 bnword16 __cdecl __far
30cc23 bniDiv21_16(bnword16 __far *q, bnword16 nh, bnword16 nl, bnword16 d);
fcd06f #define bniDiv21_16 bniDiv21_16
d1af5a
bde8e8 bnword16 __cdecl __far
e7ed73 bniModQ_16(bnword16 const __far *n, unsigned len, bnword16 d);
46ce8d #define bniModQ_16 bniModQ_16
1daf5a
53af5a
77af5a
1d1597 void __cdecl __far
c0dea1 bniMulN1_32(bnword32 __far *out, bnword32 const __far *in,
385be6 ············unsigned len, bnword32 k);
8610e8 #define bniMulN1_32 bniMulN1_32
14caf9 ············
1fe094 bnword32 __cdecl __far
b45117 bniMulAdd1_32(bnword32 __far *out, bnword32 const __far *in,
7859e7 ··············unsigned len, bnword32 k);
677ea8 #define bniMulAdd1_32 bniMulAdd1_32
727516 ·······
0ae094 bnword32 __cdecl __far
6cb344 bniMulSub1_32(bnword32 __far *out, bnword32 const __far *in,
2259e7 ··············unsigned len, bnword32 k);
9109c1 #define bniMulSub1_32 bniMulSub1_32
54af5a
4ee094 bnword32 __cdecl __far
933f4c bniDiv21_32(bnword32 __far *q, bnword32 nh, bnword32 nl, bnword32 d);
13615a #define bniDiv21_32 bniDiv21_32
03af5a
1ce8e8 bnword16 __cdecl __far
ebdf1b bniModQ_32(bnword32 const __far *n, unsigned len, bnword32 d);
67f735 #define bniModQ_32 bniModQ_32
11af5a
c1bf6b int __cdecl __far not386(void);
61af5a
--b279 00187cf675b40100161 Page 2 of bni8086.h
871254 PGP_END_C_DECLARATIONS
--69fb 00046e86cca40100162 Page 1 of bni960jx.s
dbd837 # Assembly-language bignum primitives for the i960 Jx series.
82a601 #
4d9f3c # $Id: bni960jx.s,v 1.1 1997/04/30 08:36:14 mhw Exp $
22a601 #
805745 # The Jx series is fairly straightforward single-instruction-issue·
9b6a03 # implementation, with a 1-cycle-issue 4-cycle-latency non-pipelined
fea9bf # multiplier that we can use. ·Note also that loads which hit in the
ea034a # cache have 2 cycles of latency and stores stall until all pending
b3b1de # loads are done.
54a601 #
32adbf # What is intensely annoying about the i960 is that it uses the same
9b10c2 # flags for all conditional branches (even compare-and-branch sets the
c1a567 # flags) AND for the carry bit. ·Further, it is hard to manipulate
4a34dc # that bit.
36a601 #
de32a2 # Calling conventions:
95ccf3 # The r registers are all local, if you set them up. ·There's an alternative
88e9d1 # calling convention that uses bal (branch and link) and doesn't set them up.
2cec17 # Currently, all of these functions are designed to work that way.
f6d055 # g0-g7 are argument registers and volatile across calls. ·return in g0-g3.
036104 # g8-g11 are extra argument registers, and volatile if used, but
d57c2c #¤  preserved if not. ·Here, they are not.
551395 # g12 is used for PIC, and is preserved.
23b527 # g13 is a pointer to a structure return value, if used, and is volatile.
90ab2c # g14 is magic, and is used as a return address in the branch-and-link
6a20ef #¤  convention, and as a pointer to an argument block if the arguments
052d93 #¤  won't fit in registers, but is usually hardwired 0 and must be
5e00ee #¤  returned set to zero (0).
a3abc4 # g15 is the frame pointer, and shouldn't be messed with.
6a39bf # The AC (condition codes) are all volatile.
520493 # The fp registers are all volatile, but irrelevant.
d1a601 #
04af5a
be5655 # BNWORD32
1f355e # bniMultAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
057bc5 # This adds "k" * "in" to "len" words of "out" and returns the word of
097248 # carry.
c0a601 #
07f095 # For doing multiply-add, the 960 is a bit annoying because it uses
773858 # the same status bits for the carry flag and for the loop indexing
c584d8 # computation, and doesn't have an "add with carry out but not carry in"
efe951 # instruction. ·Fortunately, we can arrange to have the loop indexing
aa2702 # leave the carry bit clear most of the time.
02a601 #
a7179d # The basic sequence of the loop is:
adfaa0 # 1. Multiply k * *in++ -> high, low
b135bb # 2. Addc carry word and carry bit to low
2d5675 # 3. Addc carry bit to high, producing carry word (note: cannot generate carry)
95692f # 4. Addc low to *out++
25a601 #
f8a523 # Note that the carry bit set in step 4 is used in step 2. ·The only place
b8dcba # in this loop that the carry flag isn't in use is between steps 3 and 4,
d7400c # so we have to rotate the loop to place the loop indexing operations here.
a0b27f # (Which consist of a compare-and-decrement and a conditional branch.)
749350 # The loop above ignores the details of when to do loads and stores, which
85112d # have some flexibility, but must be carefully scheduled to avoid stalls.
40a601 #
95ab27 # The first iteration has no carry word in, so it requires only steps 1 and 4,
8732e1 # and since we begin the loop with step 4, it boils down to just step 1
5ee698 # followed by the loop indexing (which clears the carry bit in preparation
bfb664 # for step 4).
c6a601 #
ff87eb # Arguments are passed as follows:
7ad1e6 # g0 - out pointer
fa5a72 # g1 - in pointer
6edabb # g2 - length
82762f # g3 - k
591972 # The other registers are used as follows.
fbfaab # g4 - low word of product
9f14b5 # g5 - high word of product
c49d0d # g6 - current word of "out"
46354e # g7 - carry word
--4b13 0002b3524d640100162 Page 2 of bni960jx.s
e5db4f # g13 - current word of "in"
dbaf5a
d4a88c ¤   .globl _bniMulAdd1_32
c00174 _bniMulAdd1_32:
e0a0dd ¤   ld¤ (g1),g13 ··¤# Fetch *in
b33ed8 ¤   addo¤   g1,4,g1 ··¤ # Increment in
6882f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
7c8164 ¤   ld¤ (g0),g6 ··¤ # Fetch *out
cf0304 ¤   chkbit¤ 0,g2¤   ¤   # Check if loop counter was odd
88c58d ¤   shro¤   1,g2,g2 ··¤ # Divide loop counter by 2
4fe475 ¤   mov¤g5,g7¤  ¤   # Move high word to carry
f3affc ¤   bno¤ma_loop1¤   # If even, jump to ma_loop1
e4a1ea ¤   cmpo¤   0,g2¤   ¤   # If odd, was it 1 (now 0)?
35485e ¤   be¤ ma_done ··¤ # If equal (carry set), jump to ending code
24af5a
01e9f1 # Entered with carry bit clear
03174a ma_loop:
fd2522 ¤   ld¤ (g1),g13 ·¤ # Fetch *in
92dd0c ¤   addc¤   g4,g6,g6¤   # Add low to *out (step 4), generate carry
4d82f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
d9003d ¤   st¤ g6,(g0) ·¤  # Write out *out
c135aa ¤   addo¤   g0,4,g0 ·¤  # Increment out
8cce5b ¤   addo¤   g1,4,g1 ·¤  # Increment in
beb72d ¤   ld¤ (g0),g6 ·¤  # Fetch next *out
814b59 ¤   addc¤   g7,g4,g4¤   # Add carries to low (step 2)
6f8ae5 ¤   addc¤   g5,0,g7 ·¤  # Add carry bit to high (step 3) & clear carry
98dd17 ma_loop1:
302522 ¤   ld¤ (g1),g13 ·¤ # Fetch *in
34dd0c ¤   addc¤   g4,g6,g6¤   # Add low to *out (step 4), generate carry
d782f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
3c003d ¤   st¤ g6,(g0) ·¤  # Write out *out
8335aa ¤   addo¤   g0,4,g0 ·¤  # Increment out
b3ce5b ¤   addo¤   g1,4,g1 ·¤  # Increment in
c9b72d ¤   ld¤ (g0),g6 ·¤  # Fetch next *out
584b59 ¤   addc¤   g7,g4,g4¤   # Add carries to low (step 2)
f28ae5 ¤   addc¤   g5,0,g7 ·¤  # Add carry bit to high (step 3) & clear carry
d3af5a
f6ea3f ¤   cmpdeco¤1,g2,g2
75ad19 ¤   bne¤ma_loop
0ee592 # When we come here, carry is *set*, and we stil have to do step 4
529681 ma_done:
5fe5ee ¤   cmpi¤   0,1¤¤   # Clear carry (equal flag)
9fdd0c ¤   addc¤   g4,g6,g6¤   # Add low to *out (step 4), generate carry
8b5116 ¤   st¤ g6,(g0) ··¤ # Write out *out
672c28 ¤   addc¤   g7,0,g0 ··¤ # Add carry bit and word to produce return val
0a8a83 ¤   ret
04af5a
69f721 # Now, multiply N by 1 is similarly annoying. ·We only have one add in the
fea9d9 # whole loop, which should just be able to leave its carry output in the
00fd36 # carry flag for the next iteration, but we need the condition codes to do
7f2c2f # loop testing. ·*Sigh*.
fba601 #
ab7fc7 # void
c57186 # bniMultN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
3f26f6 # This stores len+1 words of "k" * len words of "in" and stores the result
c2df9f # in "out".
25a601 #
f77bd8 # To avoid having to do a move after the first iteration, for the first
29ca5f # step, g4/g5 is the product. ·For second step, g6/g7 is used for product
6101d9 # storage and g5 is the carry in. ·It alternates from then on.
231fc4 ¤   .globl _bniMulN1_32
09930d _bniMulN1_32:
dd2adf ¤   ld¤ (g1),g13 ¤  # Fetch *in
ca7838 ¤   addo¤   g1,4,g1 ¤   # Increment in
1682f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
1d0304 ¤   chkbit¤ 0,g2¤   ¤   # Check if loop counter was odd
bc2072 ¤   shro¤   1,g2,g2 ·¤  # Divide loop counter by 2
b2cfba ¤   bno¤m_loop1 ·¤  # If even, jump to ma_loop1
4982ea ¤   mov¤g4,g6
cbb700 ¤   cmpo¤   0,g2¤   ¤   # If counter was odd, was it 1 (now 0)?
cb9076 ¤   mov¤g5,g7
2b4eb9 ¤   be¤ m_done¤ ¤   # If equal (carry set), jump to ending code
--7615 000a4121ae740100162 Page 3 of bni960jx.s
e0af5a
90e9f1 # Entered with carry bit clear
4330a0 m_loop:
fe16ea ¤   # Result in g6, carry word in g7
6a3164 ¤   ld¤ (g1),g13¤   # Fetch *in
8f7838 ¤   addo¤   g1,4,g1 ¤   # Increment in
1182f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
359fbd ¤   st¤ g6,(g0) ¤   # Write out *out
72d69a ¤   addo¤   g0,4,g0¤¤   # Increment out
fa4b59 ¤   addc¤   g7,g4,g4¤   # Add carries to low (step 2)
418d77 # No need to add carry bit here, because it'll get remembered until next addc.
ef92f3 #¤  addc¤   g5,0,g5 ¤   # Add carry bit to high (step 3)
3c9564 m_loop1:
370320 ¤   # Carry word in g5
f23164 ¤   ld¤ (g1),g13¤   # Fetch *in
5bd0ff ¤   addo¤   g1,4,g1¤¤   # Increment in
7c2661 ¤   emul¤   g13,g3,g6¤  # Do multiply (step 1)
20a570 ¤   st¤ g4,(g0)¤¤   # Write out *out
926481 ¤   addo¤   g0,4,g0 ¤   # Increment out
f03915 ¤   addc¤   g5,g6,g6¤   # Add carries to low (step 2)
7d654a ¤   addc¤   g7,0,g7 ¤   # Add carry bit to high (step 3)
58af5a
52ea3f ¤   cmpdeco¤1,g2,g2
ed8b04 ¤   bne¤m_loop
81af5a
a7cebe # When we come here, we have to store g6 and the carry word in g7.
44b16b m_done:
629fbd ¤   st¤ g6,(g0) ¤   # Write out *out
483f01 ¤   st¤ g7,4(g0)¤   # Write out *out
b08a83 ¤   ret
7daf5a
1d5655 # BNWORD32
c538d1 # bniMultSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
a0c7b3 # This subtracts "k" * "in" from "len" words of "out" and returns the word of
4cb56f # borrow.
0ba601 #
052360 # This is similar to multiply-add, but actually a bit more obnoxious,
6d9dc2 # because of the carry situation. ·The 960 uses a carry (rather than a borrow)
4d8652 # bit on subtracts, so the carry bit should be 1 for a subc to do the
fe853d # same thing as an ordinary subo. ·So we use two carry chains: one from
0bb01f # the add of the low-order words to the high-order carry word, and a second,
59bb6a # which uses an extra register, to connect the subtracts. ·This avoids
60feb4 # the need to fiddle with inverting the bit in the usual case.
79a601 #
9c87eb # Arguments are passed as follows:
afd1e6 # g0 - out pointer
e85a72 # g1 - in pointer
dedabb # g2 - length
5e762f # g3 - k
621972 # The other registers are used as follows.
d7faab # g4 - low word of product
3714b5 # g5 - high word of product
b29d0d # g6 - current word of "out"
6f354e # g7 - carry word
05db4f # g13 - current word of "in"
fb7597 # g14 - remembered carry bit
08af5a
c2ca7d ¤   .globl _bniMulSub1_32
28e710 _bniMulSub1_32:
403164 ¤   ld¤ (g1),g13¤   # Fetch *in
597838 ¤   addo¤   g1,4,g1 ¤   # Increment in
2582f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
449986 ¤   ld¤ (g0),g6 ¤   # Fetch *out
8e404c ¤   chkbit¤ 0,g2 ···¤   # Check if loop counter was odd
8c0ec5 ¤   mov¤1,g14 ··¤   # Set remembered carry for first iteration
8f2fef ¤   shro¤   1,g2,g2 ¤   # Divide loop counter by 2
4d5af8 ¤   mov¤g5,g7 ··¤   # Move high word to carry
31b484 ¤   bno¤ms_loop1¤   # If even, jump to ma_loop1
1526fa ¤   cmpo¤   0,g2 ···¤   # If odd, was it 1 (now 0)?
bce042 ¤   be¤ ms_done ¤   # If equal (carry set), jump to ending code
70af5a
a4e9f1 # Entered with carry bit clear
--9978 0017a2a73b440100162 Page 4 of bni960jx.s
cc475d ms_loop:
7a3164 ¤   ld¤ (g1),g13¤   # Fetch *in
ff0bd5 ¤   cmpi¤   g14,1 ··¤   # Set carry flag
fc3d28 ¤   subc¤   g4,g6,g6¤   # Subtract low from *out (step 4), gen. carry
7882f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
9d3175 ¤   addc¤   0,0,g14 ¤   # g14 = carry, then clear carry
be9fbd ¤   st¤ g6,(g0) ¤   # Write out *out
4f6481 ¤   addo¤   g0,4,g0 ¤   # Increment out
c27838 ¤   addo¤   g1,4,g1 ¤   # Increment in
a333ba ¤   ld¤ (g0),g6 ¤   # Fetch next *out
ca4b59 ¤   addc¤   g7,g4,g4¤   # Add carries to low (step 2)
b86dd5 ¤   addc¤   g5,0,g7 ¤   # Add carry bit to high (step 3)
efb979 ms_loop1:
d53164 ¤   ld¤ (g1),g13¤   # Fetch *in
0c7fb0 ¤   cmpi¤   g14,1 ··¤   # Set carry flag for subtrsct
443d28 ¤   subc¤   g4,g6,g6¤   # Subtract low from *out (step 4), gen. carry
4a82f1 ¤   emul¤   g13,g3,g4¤  # Do multiply (step 1)
563175 ¤   addc¤   0,0,g14 ¤   # g14 = carry, then clear carry
4a9fbd ¤   st¤ g6,(g0) ¤   # Write out *out
4d6481 ¤   addo¤   g0,4,g0 ¤   # Increment out
c37838 ¤   addo¤   g1,4,g1 ¤   # Increment in
2033ba ¤   ld¤ (g0),g6 ¤   # Fetch next *out
374b59 ¤   addc¤   g7,g4,g4¤   # Add carries to low (step 2)
246dd5 ¤   addc¤   g5,0,g7 ¤   # Add carry bit to high (step 3)
08af5a
39ea3f ¤   cmpdeco¤1,g2,g2
7c2f6b ¤   bne¤ms_loop
86e592 # When we come here, carry is *set*, and we stil have to do step 4
16c696 ms_done:
a6ae47 ¤   cmpi¤   g14,1 ··¤   # set carry (equal flag)
137c76 ¤   subc¤   g4,g6,g6¤   # Add low to *out (step 4), generate carry
919fbd ¤   st¤ g6,(g0) ¤   # Write out *out
fa002a ¤   subc¤   0,0,g14 ¤   # g14 = -1 if no carry (borrow), 0 if carry
83f9f5 ¤   subo¤   g14,g7,g0¤  # Add borrow bit to produce return value
07a941 ¤   mov¤0,g14 ··¤   # Restore g14 to 0 for return
7a8a83 ¤   ret
--2d03 001d878cf9040100163 Page 1 of bnialpha.h
bc38e5 /*
a7affe ·* bnialpha.h - header file that declares the Alpha assembly-language
60eb43 ·* subroutines. ·It is intended to be included via the BNINCLUDE
151b30 ·* mechanism.
25775e ·*
10841d ·* $Id: bnialpha.h,v 1.2 1997/05/05 19:49:12 lloyd Exp $
89495d ·*/
8caf5a
c17be2 #define BN_LITTLE_ENDIAN 1
0baf5a
94d154 typedef unsigned long bnword64;
50d23b #define BNWORD64 bnword64
65af5a
fa3379 #ifdef __cplusplus
3d8078 /* These assembly-language primitives use C names */
c86dad extern "C" {
7b7454 #endif
4caf5a
953e06 void bniMulN1_64(bnword64 *out, bnword64 const *in, unsigned len, bnword64 k);
b5137b #define bniMulN1_64 bniMulN1_64
35af5a
4ec35c bnword64
500c88 bniMulAdd1_64(bnword64 *out, bnword64 const *in, unsigned len, bnword64 k);
277fa5 #define bniMulAdd1_64 bniMulAdd1_64
a9af5a
e5c35c bnword64
06707a bniMulSub1_64(bnword64 *out, bnword64 const *in, unsigned len, bnword64 k);
4108cc #define bniMulSub1_64 bniMulSub1_64
8daf5a
d81254 PGP_END_C_DECLARATIONS
--4725 000917b1fc740100164 Page 1 of bnialpha.s
bc38e5 /*
180778 ·* DEC Alpha 64-bit math primitives. ·These use 64-bit words
b3a8b5 ·* unless otherwise noted.
c4775e ·*
c8d2ad ·* $Id: bnialpha.s,v 1.1 1997/04/30 08:36:15 mhw Exp $
67775e ·*
aa2e08 ·* The DEC assembler apparently does some instruction scheduling,
5b7171 ·* but I tried to do some of my own, and tries to spread things
d198e4 ·* out over the register file to give the assembler more room
908e1e ·* to schedule things.
ec775e ·*
e71ac8 ·* Alpha OSF/1 register usage conventions:
8b0c5b ·* r0 ······- v0 ·····- Temp, holds integer return value
273d96 ·* r1..r8 ··- t0..t7 ·- Temp, trashed by procedure call
d18795 ·* r9..r14 ·- s0..s5 ·- Saved across procedure calls
ff3ca7 ·* r15 ·····- s6/FP ··- Frame pointer, saved across procedure calls
6b3cf3 ·* r16..r21 - a0..a5 ·- Argument registers, all trashed by procedure call
b29655 ·* r22..r25 - t8..t11 - Temp, trashed by procedure call
7fe1d5 ·* r26 ·····- ra ·····- Return address
440419 ·* r27 ·····- t12/pv ·- Procedure value, trashed by procedure call
e6bf88 ·* r28 ·····- at ·····- Assembler temp, trashed by procedure call
a6f246 ·* r29 ·····- gp ·····- Global pointer
cedaf0 ·* r30 ·····- sp ·····- Stack pointer
56d627 ·* r31 ·····- zero ···- hardwired to zero
24495d ·*/
1191e3 ¤   .text
1c266d ¤   .align¤ 4
febec4 ¤   .globl¤ bniMulN1_64
b5ed8b /* I have no idea what the '2' at the end of the .ent line means. */
d7ab5b ¤   .ent¤   bniMulN1_64 2
8538e5 /*
35856e ·* Arguments: $16 = out, $17 = in, $18 = len<32>, $19 = k
29cc89 ·* Other registers: $0 = carry word, $1 = product low,
0d7cfa ·* $2 = product high, $3 = input word
c2495d ·*/
4b21df bniMulN1_64:
b45df0 ¤   ldq¤$3,0($17)¤  /* Load first word of input */
d12392 ¤   subl¤   $18,1,$18
881101 ¤   mulq¤   $3,$19,$1¤  /* Do low half of first multiply */
47dff7 ¤   umulh¤  $3,$19,$0¤  /* Do second half of first multiply */
c2ded7 ¤   stq¤$1,0($16)
8aa8a9 ¤   beq¤$18,m64_done
ba06c4 m64_loop:
80d2fe ¤   ldq¤$3,8($17)
fd8c73 ¤   addq¤   $17,8,$17
4548dc ¤   mulq¤   $3,$19,$1¤  /* Do bottom half of multiply */
a82392 ¤   subl¤   $18,1,$18
453ea6 ¤   umulh¤  $3,$19,$2¤  /* Do top half of multiply */
16052e ¤   addq¤   $0,$1,$1¤   /* Add carry word from previous multiply */
73003b ¤   stq¤$1,8($16)
f712ab ¤   cmpult¤ $1,$0,$0¤   /* Compute carry bit from add */
981414 ¤   addq¤   $16,8,$16
1972ad ¤   addq¤   $2,$0,$0¤   /* Add carry bit to carry word */
05d83c ·
9ca8a9 ¤   beq¤$18,m64_done
2aaf5a
1ad2fe ¤   ldq¤$3,8($17)
218c73 ¤   addq¤   $17,8,$17
bb48dc ¤   mulq¤   $3,$19,$1¤  /* Do bottom half of multiply */
682392 ¤   subl¤   $18,1,$18
043ea6 ¤   umulh¤  $3,$19,$2¤  /* Do top half of multiply */
85052e ¤   addq¤   $0,$1,$1¤   /* Add carry word from previous multiply */
04003b ¤   stq¤$1,8($16)
ba12ab ¤   cmpult¤ $1,$0,$0¤   /* Compute carry bit from add */
f01414 ¤   addq¤   $16,8,$16
be72ad ¤   addq¤   $2,$0,$0¤   /* Add carry bit to carry word */
5fd83c ·
a603c4 ¤   bne¤$18,m64_loop
74870f m64_done:
07cde0 ¤   stq¤$0,8($16)¤  /* Store last word of result */
bb2eab ¤   ret¤$31,($26),1
913b3d /* The '1' in the hint field means procedure return - software convention */
--02fe 00072823d2f40100164 Page 2 of bnialpha.s
5eb8f6 ¤   .end bniMulN1_64
a9d83c ·
2dd83c ·
ce91e3 ¤   .text
05266d ¤   .align¤ 4
611cac ¤   .globl¤ bniMulAdd1_64
d55396 ¤   .ent¤   bniMulAdd1_64 2
4338e5 /*
70856e ·* Arguments: $16 = out, $17 = in, $18 = len<32>, $19 = k
9dbb7e ·* Other registers: $0 = product high, $1 = product low,
177500 ·* $2 = product high temp, $3 = input word, $4 = output word
00beed ·* $5 = carry bit from add to out
ee495d ·*/
516cf7 bniMulAdd1_64:
2b5df0 ¤   ldq¤$3,0($17)¤  /* Load first word of input */
8c2392 ¤   subl¤   $18,1,$18
171101 ¤   mulq¤   $3,$19,$1¤  /* Do low half of first multiply */
e959ad ¤   ldq¤$4,0($16)¤  /* Load first word of output */
15007f ¤   umulh¤  $3,$19,$2¤  /* Do second half of first multiply */
8d8bca ¤   addq¤   $4,$1,$4
d45672 ¤   cmpult¤ $4,$1,$5¤   /* Compute borrow bit from subtract */
e1accf ¤   stq¤$4,0($16)
fb3b16 ¤   addq¤   $5,$2,$0¤   /* Add carry bit to high word */
2ec0dd ¤   beq¤$18,ma64_done
204790 ma64_loop:
c9b63d ¤   ldq¤$3,8($17)¤  /* Load next word of input */
9e8c73 ¤   addq¤   $17,8,$17
572085 ¤   ldq¤$4,8($16)¤  /* Load next word of output */
1248dc ¤   mulq¤   $3,$19,$1¤  /* Do bottom half of multiply */
ef2392 ¤   subl¤   $18,1,$18
20052e ¤   addq¤   $0,$1,$1¤   /* Add carry word from previous multiply */
0e3ea6 ¤   umulh¤  $3,$19,$2¤  /* Do top half of multiply */
6c12ab ¤   cmpult¤ $1,$0,$0¤   /* Compute carry bit from add */
9c282c ¤   addq¤   $4,$1,$4¤   /* Add product to loaded word */
470ccf ¤   cmpult¤ $4,$1,$5¤   /* Compute carry bit from add */
587223 ¤   stq¤$4,8($16)
380176 ¤   addq¤   $5,$0,$5¤   /* Add carry bits together */
661414 ¤   addq¤   $16,8,$16
81fd2c ¤   addq¤   $5,$2,$0¤   /* Add carry bits to carry word */
16d83c ·
54c0dd ¤   beq¤$18,ma64_done
51af5a
7ab63d ¤   ldq¤$3,8($17)¤  /* Load next word of input */
5f8c73 ¤   addq¤   $17,8,$17
e62085 ¤   ldq¤$4,8($16)¤  /* Load next word of output */
9348dc ¤   mulq¤   $3,$19,$1¤  /* Do bottom half of multiply */
282392 ¤   subl¤   $18,1,$18
9a052e ¤   addq¤   $0,$1,$1¤   /* Add carry word from previous multiply */
b43ea6 ¤   umulh¤  $3,$19,$2¤  /* Do top half of multiply */
1512ab ¤   cmpult¤ $1,$0,$0¤   /* Compute carry bit from add */
6a282c ¤   addq¤   $4,$1,$4¤   /* Add product to loaded word */
290ccf ¤   cmpult¤ $4,$1,$5¤   /* Compute carry bit from add */
427223 ¤   stq¤$4,8($16)
8a0176 ¤   addq¤   $5,$0,$5¤   /* Add carry bits together */
541414 ¤   addq¤   $16,8,$16
0afd2c ¤   addq¤   $5,$2,$0¤   /* Add carry bits to carry word */
30d83c ·
51128b ¤   bne¤$18,ma64_loop
e5c65b ma64_done:
a12eab ¤   ret¤$31,($26),1
b4fc88 ¤   .end bniMulAdd1_64
c9d83c ·
bed83c ·
d491e3 ¤   .text
bc266d ¤   .align¤ 4
287e5d ¤   .globl¤ bniMulSub1_64
7e7652 ¤   .ent¤   bniMulSub1_64 2
cb38e5 /*
b1856e ·* Arguments: $16 = out, $17 = in, $18 = len<32>, $19 = k
cecc89 ·* Other registers: $0 = carry word, $1 = product low,
537500 ·* $2 = product high temp, $3 = input word, $4 = output word
7259a8 ·* $5 = borrow bit from subtract
--83c2 001886f607240100164 Page 3 of bnialpha.s
47495d ·*/
8d8a93 bniMulSub1_64:
205df0 ¤   ldq¤$3,0($17)¤  /* Load first word of input */
712392 ¤   subl¤   $18,1,$18
551101 ¤   mulq¤   $3,$19,$1¤  /* Do low half of first multiply */
df59ad ¤   ldq¤$4,0($16)¤  /* Load first word of output */
57007f ¤   umulh¤  $3,$19,$2¤  /* Do second half of first multiply */
f95672 ¤   cmpult¤ $4,$1,$5¤   /* Compute borrow bit from subtract */
843440 ¤   subq¤   $4,$1,$4
e53b16 ¤   addq¤   $5,$2,$0¤   /* Add carry bit to high word */
85accf ¤   stq¤$4,0($16)
99a4b3 ¤   beq¤$18,ms64_done
68cd8c ms64_loop:
d4b63d ¤   ldq¤$3,8($17)¤  /* Load next word of input */
eb8c73 ¤   addq¤   $17,8,$17
4f2085 ¤   ldq¤$4,8($16)¤  /* Load next word of output */
5148dc ¤   mulq¤   $3,$19,$1¤  /* Do bottom half of multiply */
d42392 ¤   subl¤   $18,1,$18
17052e ¤   addq¤   $0,$1,$1¤   /* Add carry word from previous multiply */
2e3ea6 ¤   umulh¤  $3,$19,$2¤  /* Do top half of multiply */
0d12ab ¤   cmpult¤ $1,$0,$0¤   /* Compute carry bit from add */
bf5672 ¤   cmpult¤ $4,$1,$5¤   /* Compute borrow bit from subtract */
433440 ¤   subq¤   $4,$1,$4
730176 ¤   addq¤   $5,$0,$5¤   /* Add carry bits together */
d37223 ¤   stq¤$4,8($16)
5bfd2c ¤   addq¤   $5,$2,$0¤   /* Add carry bits to carry word */
901414 ¤   addq¤   $16,8,$16
12d83c ·
33a4b3 ¤   beq¤$18,ms64_done
75af5a
24b63d ¤   ldq¤$3,8($17)¤  /* Load next word of input */
fd8c73 ¤   addq¤   $17,8,$17
3d2085 ¤   ldq¤$4,8($16)¤  /* Load next word of output */
be48dc ¤   mulq¤   $3,$19,$1¤  /* Do bottom half of multiply */
a02392 ¤   subl¤   $18,1,$18
ae052e ¤   addq¤   $0,$1,$1¤   /* Add carry word from previous multiply */
f93ea6 ¤   umulh¤  $3,$19,$2¤  /* Do top half of multiply */
4612ab ¤   cmpult¤ $1,$0,$0¤   /* Compute carry bit from add */
855672 ¤   cmpult¤ $4,$1,$5¤   /* Compute borrow bit from subtract */
c13440 ¤   subq¤   $4,$1,$4
5d0176 ¤   addq¤   $5,$0,$5¤   /* Add carry bits together */
b27223 ¤   stq¤$4,8($16)
e5fd2c ¤   addq¤   $5,$2,$0¤   /* Add carry bits to carry word */
8e1414 ¤   addq¤   $16,8,$16
d2d83c ·
7376e5 ¤   bne¤$18,ms64_loop
8b4c47 ms64_done:
152eab ¤   ret¤$31,($26),1
889e79 ¤   .end bniMulSub1_64
--98cb 000a8a85ead40100165 Page 1 of bnimem.c
bc38e5 /*
ea1db8 ·* bnimem.c - low-level bignum memory handling.
cb775e ·*
e8fbf7 ·* Written by Colin Plumb
12775e ·*
6d1453 ·* $Id: bnimem.c,v 1.8 1997/12/19 19:09:20 lloyd Exp $
24775e ·*
3727cb ·* Note that in all cases, the pointers passed around
25a424 ·* are pointers to the *least* significant end of the word.
5a8a99 ·* On big-endian machines, these are pointers to the *end*
83e510 ·* of the allocated range.
46775e ·*
97f0c1 ·* BNSECURE is a simple level of security; for more security
12c592 ·* change these function to use locked unswappable memory.
5c495d ·*/
d0e2ff #include "pgpConfig.h"
cf0d08 #include "pgpMem.h"
a8af5a
5938e5 /*
d516cf ·* Some compilers complain about #if FOO if FOO isn't defined,
cb59aa ·* so do the ANSI-mandated thing explicitly...
3b495d ·*/
fd125a #ifndef NO_STDLIB_H
ad28a8 #define NO_STDLIB_H 0
a37454 #endif
81b552 #ifndef NO_STRING_H
5737dd #define NO_STRING_H 0
c27454 #endif
9a8537 #ifndef HAVE_STRINGS_H
b9025c #define HAVE_STRINGS_H 0
737454 #endif
b4101b #ifndef NEED_MEMORY_H
f3ee50 #define NEED_MEMORY_H 0
467454 #endif
c9af5a
2ad160 #if !NO_STDLIB_H
44ddae #include <stdlib.h>¤/* For malloc() & co. */
f8db21 #else
6ff996 void *malloc();
c412e3 void *realloc();
e4eddc void free();
257454 #endif
ddaf5a
737668 #if !NO_STRING_H
d4ed9a #include <string.h>¤/* For memset */
a7a752 #elif HAVE_STRINGS_H
daf7c3 #include <strings.h>
ef7454 #endif
333c37 #if NEED_MEMORY_H
93c737 #include <memory.h>
0a7454 #endif
2caf5a
d5e178 #ifndef DBMALLOC
f96ea3 #define DBMALLOC 0
5b7454 #endif
dfdeac #if DBMALLOC
7c2631 /* Development debugging */
aa1594 #include "../dbmalloc/malloc.h"
d97454 #endif
11af5a
95a6ac #include "bni.h"
d321db #include "bnimem.h"
cfaf5a
734724 #include "bnkludge.h"
49af5a
1e00b9 #ifndef bniMemWipe
70314a void
4c34c9 bniMemWipe(void *ptr, unsigned bytes)
e3bb36 {
95abe7 ¤   pgpClearMemory(ptr, bytes);
2befe6 }
a871da #define bniMemWipe(ptr, bytes) pgpClearMemory(ptr, bytes)
--f406 00069da05b640100165 Page 2 of bnimem.c
a07454 #endif
e0af5a
f16eac #ifndef bniMemAlloc
23af5a
8faf5a
7b59fc ¤   void *
347f11 bniMemAlloc(
916740 ¤   PGPMemoryMgrRef¤mgr,
d2fe55 ¤   PGPBoolean¤ ¤   secure,
24fa1d ¤   PGPUInt32¤  ¤   bytes)
81bb36 {
87ed90 ¤   if ( secure )
1a58a9 ¤   ¤   return( PGPNewSecureData( mgr, bytes, 0 ) );
e61b52 ¤   ¤
4a28d9 ¤   return PGPNewData( mgr, bytes, 0);
7defe6 }
f0af5a
ea7454 #endif
46af5a
8d0021 #ifndef bniMemFree
ff314a void
a6dcd6 bniMemFree(void *ptr, unsigned bytes)
75bb36 {
8d03ba ¤   bniMemWipe(ptr, bytes);
d01228 ¤   PGPFreeData( ptr );
e0efe6 }
b77454 #endif
a3af5a
28bd6f #ifndef bniRealloc
dd813e #if defined(bniMemRealloc) || !BNSECURE
21af5a
fda2a6 this version does not use PGPMemoryMgrRef
baaf5a
f59a44 void *
5a95de bniRealloc(void *ptr, unsigned oldbytes, unsigned newbytes)
46bb36 {
3fd7c0 ¤   if (ptr) {
b4103f ¤   ¤   BIG(ptr = (char *)ptr - oldbytes;)
d8f072 ¤   ¤   if (newbytes < oldbytes)
e4f1cb ¤   ¤   ¤   memmove(ptr, (char *)ptr + oldbytes-newbytes,
673ced ¤   ¤   ¤   ¤   ¤   ¤   oldbytes);
fa9371 ¤   }
cc39f6 #ifdef bniMemRealloc
6e0e4a ¤   ptr = bniMemRealloc(ptr, oldbytes, newbytes);
e0db21 #else
ee462a ¤   ptr = realloc(ptr, newbytes);
8b7454 #endif
a4d7c0 ¤   if (ptr) {
fff2c9 ¤   ¤   if (newbytes > oldbytes)
9d2296 ¤   ¤   ¤   memmove((char *)ptr + newbytes-oldbytes, ptr,
523ced ¤   ¤   ¤   ¤   ¤   ¤   oldbytes);
3034dd ¤   ¤   BIG(ptr = (char *)ptr + newbytes;)
8f9371 ¤   }
d3af5a
a68726 ¤   return ptr;
b2efe6 }
d4af5a
261b7f #else /* BNSECURE */
19af5a
95af5a
ca9a44 void *
96be9f bniRealloc(
796740 ¤   PGPMemoryMgrRef¤mgr,
31fe55 ¤   PGPBoolean¤ ¤   secure,
f13fba ¤   void *¤ ¤   ¤   oldptr,
d3cb4b ¤   unsigned¤   ¤   oldbytes,
d37a4b ¤   unsigned¤   ¤   newbytes)
86bb36 {
bc6bb7 ¤   void *newptr = bniMemAlloc( mgr, secure, newbytes);
3eaf5a
3f9746 ¤   if ( IsNull( newptr ) )
69c0d8 ¤   ¤   return newptr;
--a348 00111e1681b40100165 Page 3 of bnimem.c
0aae4a ¤   if ( IsNull( oldptr ) )
e4f0f4 ¤   ¤   return BIGLITTLE((char *)newptr+newbytes, newptr);
faaf5a
cdd8af ¤   /*
6f1be3 ¤   ·* The following copies are a bit non-obvious in the big-endian case
644811 ¤   ·* because one of the pointers points to the *end* of allocated memory.
56a4e3 ¤   ·*/
c2bd71 ¤   if (newbytes > oldbytes) {¤ /* Copy all of old into part of new */
77ae22 ¤   ¤   BIG(newptr = (char *)newptr + newbytes;)
4a1382 ¤   ¤   BIG(oldptr = (char *)oldptr - oldbytes;)
27e1b7 ¤   ¤   memcpy(BIGLITTLE((char *)newptr-oldbytes, newptr), oldptr,
0ab25a ¤   ¤   ·······oldbytes);
85e78a ¤   } else {¤   /* Copy part of old into all of new */
85ae1f ¤   ¤   memcpy(newptr, BIGLITTLE((char *)oldptr-newbytes, oldptr),
e28b56 ¤   ¤   ·······newbytes);
56ae22 ¤   ¤   BIG(newptr = (char *)newptr + newbytes;)
421382 ¤   ¤   BIG(oldptr = (char *)oldptr - oldbytes;)
759371 ¤   }
7caf5a
748dee ¤   bniMemFree(oldptr, oldbytes);
14fb31 ¤   return newptr;
6aefe6 }
4cb3e6 #endif /* BNSECURE */
11e98a #endif /* !bniRealloc */
--89d7 0000510db9240100166 Page 1 of bnimem.h
bc38e5 /*
20c8de ·* Operations on the usual buffers of bytes
80775e ·*
ea19e0 ·* $Id: bnimem.h,v 1.3 1997/12/11 23:12:09 lloyd Exp $
7a495d ·*/
0b2345 #ifndef BNSECURE
f094bf #define BNSECURE 1
707454 #endif
63af5a
8a6773 #include "pgpMemoryMgr.h"
fcaf5a
a199c6 PGP_BEGIN_C_DECLARATIONS
1eaf5a
e038e5 /*
aa6b88 ·* These operations act on buffers of memory, just like malloc & free.
4c8e7a ·* One exception: it is not legal to pass a NULL pointer to bniMemFree.
b8495d ·*/
73af5a
a76eac #ifndef bniMemAlloc
baaf5a
a35642 void *¤ bniMemAlloc( PGPMemoryMgrRef mgr,
b6c09f ¤   ¤   ¤   PGPBoolean secure, PGPUInt32 bytes);
007454 #endif
76af5a
6c0021 #ifndef bniMemFree
bbba9d void bniMemFree( void *ptr, PGPUInt32 bytes);
ea7454 #endif
d6af5a
d91b13 /* This wipes out a buffer of bytes if necessary needed. */
5aaf5a
8f00b9 #ifndef bniMemWipe
f71c91 #if BNSECURE
4fa7b7 void bniMemWipe(void *ptr, unsigned bytes);
23db21 #else
82d619 #define bniMemWipe(ptr, bytes) (void)(ptr,bytes)
a87454 #endif
703a4a #endif /* !bniMemWipe */
29af5a
8e38e5 /*
d853d8 ·* bniRealloc is NOT like realloc(); it's endian-sensitive!
54f9e2 ·* If bniMemRealloc is #defined, bniRealloc will be defined in terms of it.
a6eeb7 ·* It is legal to pass a NULL pointer to bniRealloc, although oldbytes
f4eeb0 ·* will always be sero.
ea495d ·*/
24bd6f #ifndef bniRealloc
0d43be void *bniRealloc(PGPMemoryMgrRef mgr, PGPBoolean secure,
fa2fa6 ¤   ¤   void *ptr, unsigned oldbytes, unsigned newbytes);
f87454 #endif
2daf5a
ca1254 PGP_END_C_DECLARATIONS
cfaf5a
b038e5 /*
d721d7 ·* These macros are the ones actually used most often in the math library.
9cf0d8 ·* They take and return pointers to the *end* of the given buffer, and
1d78f0 ·* take sizes in terms of words, not bytes.
08775e ·*
177628 ·* Note that BNIALLOC takes the pointer as an argument instead of returning
9d7eda ·* the value.
7e775e ·*
9c70d0 ·* Note also that these macros are only useable if you have included
b7487a ·* bni.h (for the BIG and BIGLITTLE macros), which this file does NOT include.
b4495d ·*/
2daf5a
7bb979 #define BNIALLOC( mgr, sc, p,type,words) BIGLITTLE( \
a0b161 ¤   if ( ((p) = (type *)bniMemAlloc( mgr, sc, (words)*sizeof*(p))) != 0) \
c77a91 ¤   ¤   (p) += (words), \
2d39aa ¤   (p) = (type *)bniMemAlloc( mgr, sc, (words) * sizeof*(p)) \
5927e6 ¤   )
3f387d #define BNIFREE(p,words) bniMemFree((p) BIG(-(words)), (words) * sizeof*(p))
cda823 #define BNIREALLOC( mgr, sc, p,old,newP) \
b4ff21 ¤   bniRealloc( mgr, sc, p, (old) * sizeof*(p), (newP) * sizeof*(p))
05a78b #define BNIWIPE(p,words) bniMemWipe((p) BIG(-(words)), (words) * sizeof*(p))
--9df4 001e0d5e91e40100166 Page 2 of bnimem.h
e0af5a
--c17e 0014520032940100167 Page 1 of bninit16.c
bc38e5 /*
80ace9 ·* bninit16.c - Provide an init function that sets things up for 16-bit
d8e93d ·* operation. ·This is a seaparate tiny file so you can compile two bn
76cb94 ·* packages into the library and write a custom init routine.
11775e ·*
87001b ·* Written in 1995 by Colin Plumb.
79775e ·*
ad6555 ·* $Id: bninit16.c,v 1.1 1997/04/30 08:36:16 mhw Exp $
a3495d ·*/
acaf5a
e939fc #include "bn.h"
6c8a11 #include "bn16.h"
b1af5a
bb314a void
3dbf9a bnInit(void)
68bb36 {
50b37d ¤   bnInit_16();
45efe6 }
--cc8e 001f6e57fea40100168 Page 1 of bninit32.c
bc38e5 /*
985c52 ·* bninit32.c - Provide an init function that sets things up for 32-bit
11e93d ·* operation. ·This is a seaparate tiny file so you can compile two bn
decb94 ·* packages into the library and write a custom init routine.
d0775e ·*
d9001b ·* Written in 1995 by Colin Plumb.
6f775e ·*
430177 ·* $Id: bninit32.c,v 1.3 1998/05/14 19:07:24 cbertsch Exp $
15495d ·*/
bbaf5a
6b39fc #include "bn.h"
ceaf57 #include "bn32.h"
aeaf5a
17314a void
afbf9a bnInit(void)
0bbb36 {
ea963b ¤   bnInit_32();
f6efe6 }
--4f4d 0019e37faff40100169 Page 1 of bninit64.c
bc38e5 /*
d76a76 ·* bninit64.c - Provide an init function that sets things up for 64-bit
ade93d ·* operation. ·This is a seaparate tiny file so you can compile two bn
1ecb94 ·* packages into the library and write a custom init routine.
42775e ·*
a4001b ·* Written in 1995 by Colin Plumb.
1e775e ·*
28bd61 ·* $Id: bninit64.c,v 1.2 1998/05/14 19:07:25 cbertsch Exp $
b6495d ·*/
4eaf5a
7e39fc #include "bn.h"
4c8048 #include "bn64.h"
feaf5a
77314a void
15bf9a bnInit(void)
5cbb36 {
dcb924 ¤   bnInit_64();
9eefe6 }
--1724 000c7ce644e4010016a Page 1 of bnippc.c
c38dd2 #include "bnippc.h"
55af5a
8b38e5 /*
c99311 ·* bnippc.c - Assembly primitives for the bignum library, PowerPC version.
6e775e ·*
4da25b ·* $Id: bnippc.c,v 1.1 1997/04/30 08:36:16 mhw Exp $
80775e ·*
d9473f ·* Register usage during function calls is:
476eb3 ·* r0 - volatile
607355 ·* r1 - stack pointer, preserved
c58b34 ·* r2 - TOC pointer, preserved
db6c55 ·* r3 - First argument and return value register
1a619e ·* r4-r10 - More argument registers, volatile
07fe8d ·* r11-r12 - Volatile
337b64 ·* r13-r31 - Preserved
7f59df ·* LR, CTR, XER and MQ are all volatile.
baed36 ·* LR holds return address on entry.
11775e ·*
82f5d7 ·* On the PPC 601, unrolling the loops more doesn't seem to speed things
72194d ·* up at all. ·I'd be curious if other chips differed.
b9495d ·*/
43752c #if __MWERKS__ < 0x800
d1af5a
f24ae4 #include "bnppcasm.h"¤  /* PowerPC assembler */
65d83c ·
2d38e5 /*
4285a4 ·* MulN1 expects (*out, *in, len, k), count >= 1
77b5dc ·* ···············r3 ···r4 ··r5 ··r6
c2495d ·*/
cbb9c3 static const unsigned mulN1[] = {
a8db60 ¤   PPC_LWZ(7,4,0), ¤   /* Load first word of in in r7 */
fcbf0c ¤   PPC_MULLW(8,7,6),¤  /* Low half of multiply in r8 */
216748 ¤   PPC_MTCTR(5),¤  ¤   /* Move len into CTR */
662afe ¤   PPC_ADDIC(0,0,0),¤  /* Clear carry bit for loop */
3a260b ¤   PPC_MULHWU(5,7,6),¤ /* High half of multiply in r5 */
a28507 ¤   PPC_STW(8,3,0),
935783 ¤   PPC_BC(18,31,7),¤   /* Branch to Label if --ctr == 0 */
a32e36 /* Loop: */
d92114 ¤   PPC_LWZU(7,4,4),¤   /* r7 = *++in */
91e8a0 ¤   PPC_MULLW(8,7,6),¤  /* r8 = low word of product */
b13b8a ¤   PPC_ADDE(8,8,5),¤   /* Add carry word r5 and bit CF to r8 */
5faf29 ¤   PPC_STWU(8,3,4),¤   /* *++out = r8 */
fcdf24 ¤   PPC_MULHWU(5,7,6),¤ /* r5 is high word of product, for carry word*/
c857e8 ¤   PPC_BC(16,31,-5),¤  /* Branch to Loop if --ctr != 0 */
a1c748 /* Label: */
dab2d7 ¤   PPC_ADDZE(5,5),¤¤   /* Add carry flag to r5 */
74633a ¤   PPC_STW(5,3,4),¤¤   /* out[1] = r5 */
b07cfb ¤   PPC_BLR()
9a82f7 };
77af5a
6538e5 /*
9c299e ·* MulAdd1 expects (*out, *in, len, k), count >= 1
af49ae ·* ·················r3 ···r4 ··r5 ··r6
13495d ·*/
b955cd static unsigned const mulAdd1[] = {
9bdb60 ¤   PPC_LWZ(7,4,0), ¤   /* Load first word of in in r7 */
a4589f ¤   PPC_LWZ(0,3,0),¤¤   /* Load first word of out into r0 */
6abf0c ¤   PPC_MULLW(8,7,6),¤  /* Low half of multiply in r8 */
3c6748 ¤   PPC_MTCTR(5),¤  ¤   /* Move len into CTR */
eb260b ¤   PPC_MULHWU(5,7,6),¤ /* High half of multiply in r5 */
78b3c0 ¤   PPC_ADDC(8,8,0),¤   /* r8 = r8 + r0 */
eaa43f ¤   PPC_STW(8,3,0),¤¤   /* Store result to memory */
8e0d3a ¤   PPC_BC(18,31,10),¤  /* Branch to Label if --ctr == 0 */
a22e36 /* Loop: */
f32114 ¤   PPC_LWZU(7,4,4),¤   /* r7 = *++in */
3316b7 ¤   PPC_LWZU(0,3,4),¤   /* r0 = *++out */
4ce8a0 ¤   PPC_MULLW(8,7,6),¤  /* r8 = low word of product */
98f5c8 ¤   PPC_ADDE(8,8,5), ¤  /* Add carry word r5 and carry bit CF to r8 */
72df24 ¤   PPC_MULHWU(5,7,6),¤ /* r5 is high word of product, for carry word*/
4395c3 ¤   PPC_ADDZE(5,5),¤¤   /* Add carry bit from low add to r5 */
26b3c0 ¤   PPC_ADDC(8,8,0),¤   /* r8 = r8 + r0 */
c7f08c ¤   PPC_STW(8,3,0), ¤   /* *out = r8 */
--c681 000c0318faf4010016a Page 2 of bnippc.c
3974bd ¤   PPC_BC(16,31,-8),¤  /* Branch to Loop if --ctr != 0 */
9cc748 /* Label: */
b7a086 ¤   PPC_ADDZE(3,5),¤¤   /* Add carry flag to r5 and move to r3 */
be7cfb ¤   PPC_BLR()
9082f7 };
2baf5a
a538e5 /*
e6925d ·* MulSub1 expects (*out, *in, len, k), count >= 1
4449ae ·* ·················r3 ···r4 ··r5 ··r6
c7775e ·*
f98104 ·* Multiply and subtract is rather a pain. ·If the subtract of the
37cf9a ·* low word of the product from out[i] generates a borrow, we want to
417b22 ·* increment the carry word (initially in the range 0..0xfffffffe).
1dc591 ·* However, the PPC's carry bit CF is *clear* after a subtract, so
7fcef7 ·* we want to add (1-CF) to the carry word. ·This is done using two
ad0a8c ·* instructions:
d3775e ·*
fdfa53 ·* SUBFME, subtract from minus one extended. ·This computes
e6a0d2 ·* ··rD = ~rS + 0xffffffff + CF. ·Since rS is from 0 to 0xfffffffe,
0923b9 ·* ··~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is
159201 ·* ··from 0 through 0xfffffffff, setting the carry flag unconditionally, and
7195cd ·* NOR, which is used as a bitwise invert NOT instruction.
6a775e ·*
53eebd ·* The SUBFME performs the computation rD = ~rS + 0xffffffff + CF,
ac3fc9 ·* = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF),
2381b6 ·* which is the bitwise complement of the value we want.
6ee591 ·* We want to add the complement of that result to the low word of the
aa82f0 ·* product, which is just what a subtract would do, if only we could get
935687 ·* the carry flag clear. ·But it's always set, except for SUBFE, and the
8486d7 ·* operation we just performed unconditionally *sets* the carry flag. ·Ugh.
8a5b04 ·* So find the complement in a separate instruction.
f7495d ·*/
95d5c0 static unsigned const mulSub1[] = {
36db60 ¤   PPC_LWZ(7,4,0), ¤   /* Load first word of in in r7 */
f1589f ¤   PPC_LWZ(0,3,0),¤¤   /* Load first word of out into r0 */
4d6748 ¤   PPC_MTCTR(5),¤  ¤   /* Move len into CTR */
08bf0c ¤   PPC_MULLW(8,7,6),¤  /* Low half of multiply in r8 */
90260b ¤   PPC_MULHWU(5,7,6),¤ /* High half of multiply in r5 */
4aa33e ¤   PPC_SUBFC(8,8,0),¤  /* r8 = r0 - r8, setting CF */
e4a43f ¤   PPC_STW(8,3,0),¤¤   /* Store result to memory */
a3654f ¤   PPC_SUBFME(5,5),¤   /* First of two insns to add (1-CF) to r5 */
eb4073 ¤   PPC_BC(18,31,12),¤  /* Branch to Label if --ctr == 0 */
da2e36 /* Loop: */
ab2114 ¤   PPC_LWZU(7,4,4),¤   /* r7 = *++in */
c616b7 ¤   PPC_LWZU(0,3,4),¤   /* r0 = *++out */
a540b7 ¤   PPC_NOR(5,5,5),¤¤   /* Second of two insns to add (1-CF) to r5 */
38e8a0 ¤   PPC_MULLW(8,7,6),¤  /* r8 = low word of product */
b12e3e ¤   PPC_ADDC(8,8,5), ¤  /* Add carry word r5 to r8 */
7fdf24 ¤   PPC_MULHWU(5,7,6),¤ /* r5 is high word of product, for carry word*/
3895c3 ¤   PPC_ADDZE(5,5),¤¤   /* Add carry bit from low add to r5 */
1ca33e ¤   PPC_SUBFC(8,8,0),¤  /* r8 = r0 - r8, setting CF */
62f08c ¤   PPC_STW(8,3,0), ¤   /* *out = r8 */
3e654f ¤   PPC_SUBFME(5,5),¤   /* First of two insns to add (1-CF) to r5 */
ec45d8 ¤   PPC_BC(16,31,-10),¤ /* Branch to Loop if --ctr != 0 */
9ec748 /* Label: */
f0312d ¤   PPC_NOR(3,5,5),¤¤   /* Finish adding (1-CF) to r5, store in r3 */
4f7cfb ¤   PPC_BLR()
3182f7 };
b1af5a
33b177 #if 0
a838e5 /*
5f2200 ·* Args: BNWORD32 *n, BNWORD32 const *mod, unsigned mlen, BNWORD32 inv)
9946d3 ·* ···············r3 ·················r4 ···········r5 ············r6
48bbd3 ·* r7, r8 and r9 are the triple-width accumulator.
3bd03a ·* r0 and r10 are temporary registers.
c61f53 ·* r11 and r12 are temporary pointers into n and mod, respectively.·
86a3e0 ·* r2 (!) is another temporary register.
fe495d ·*/
6c8297 static unsigned const montReduce[] = {
577331 ¤   PPC_MTCTR(5),¤  /* ??? */
207d56 ¤   PPC_LWZ(7,3,0),¤¤   /* Load low word of n into r7 */
c02fe6 ¤   PPC_LWZ(10,4,0),¤   /* Fetch low word of mod */
--8dd6 0002e3246f34010016a Page 3 of bnippc.c
999485 ¤   PPC_MULLW(0,7,6),¤  /* Invert r7 into r0 */
cbe26d ¤   PPC_STW(0,3,0),¤¤   /* Store back for future use */
353fe7 ¤   PPC_MULHWU(8,10,7),¤/* Get high word of whatnot */
099d96 ¤   PPC_MULLW(10,10,7),¤/* Get low word of it */
8c105a ¤   PPC_ADDC(7,7,10),¤  /* Add low word of product to r7 */
40bf97 ¤   PPC_ADDZE(8,8),¤¤   /* Add carry to high word */
d3ea1b ¤   PPC_
3167c5 ¤
ddaf5a
303f0b ¤   PPC_MULHW(8,7,6),
6f0c85 ¤   PPC_ADDC(7,7,0),¤   /* Add inverse back to r7 */
eea501 ¤   PPC_ADDZE(8,8),
e9ea1b ¤   PPC_
2367c5 ¤
4c3552 ¤   PPC_LWZU(
e22e36 /* Loop: */
ff6b37 ¤   PPC_LWZU(0,11,4),
050db5 ¤   PPC_LWZU(10,23,-4),
6f73a8 ¤   PPC_MULLW(2,0,10),
01bef8 ¤   PPC_ADDC(7,7,2),
2c490b ¤   PPC_MULHWU(0,0,10),
57e367 ¤   PPC_ADDE(8,8,0),
fbbd91 ¤   PPC_ADDZE(9,9),
ff6257 ¤   PPC_BC(16,31,-7),¤  /* Branch to Loop if --ctr != 0 */
9eaf5a
e3499c ¤   PPC_ADDIC_(count,-1),
bff86b ¤   PPC_LWZU(0,x,4),
931b80 ¤   PPC_ADDC(0,7,0),
89874f ¤   PPC_STW(0,x,0),
459888 ¤   PPC_ADDZE(7,8),
76b9ba ¤   PPC_ADDZE(8,9),
7e0226 ¤   PPC_LI(9,0),
f5a04a ¤   PPC_BC(xx,2,yy),
0667c5 ¤
8982f7 };
f57454 #endif
a3af5a
c838e5 /*
b051e5 ·* Three overlapped transition vectors for three functions.
14729d ·* A PowerPC transition vector for a (potentially) inter-module
dc2c0a ·* jump or call consists of two words, an instruction address
f7f511 ·* and a Table Of Contents (TOC) pointer, which is loaded into
ad5fc9 ·* r1. ·Since none of the routines here have global variables,
2308c6 ·* they don't need a TOC pointer, so the value is unimportant.
78529f ·* This array places an unintersting 32-bit value after each address.
d4495d ·*/
9903fa unsigned const * const bniPPC_tv[] = {
d90f39 ¤   mulN1,
9d8e5c ¤   mulAdd1,
1a3024 ¤   mulSub1,
fb656f ¤   0
5b82f7 };
2faf5a
96eb97 #else /* __MWERKS >= 0x800 */
59af5a
7138e5 /*
ec85a4 ·* MulN1 expects (*out, *in, len, k), count >= 1
b7b5dc ·* ···············r3 ···r4 ··r5 ··r6
2d495d ·*/
8b60ee asm void
bfc495 bniMulN1_32(register unsigned *out, register unsigned const *in,
0ba7dd ¤   register unsigned len, register unsigned k)
1abb36 {
521370 ¤   lwz ¤   r7,0(in) ¤  /* Load first word of in in r7 */
1a2d6b ¤   mtctr¤  len¤¤   ¤   /* Move len into CTR */
3353e5 ¤   mullw¤  r8,r7,k¤¤   /* Low half of multiply in r8 */
46da2d ¤   addic¤  r0,r0,0¤¤   /* Clear carry bit for loop */
062e60 ¤   mulhwu¤ len,r7,k¤   /* High half of multiply in len */
6af643 ¤   stw ¤   r8,0(out)¤  /* *out = r8 */
a6a783 ¤   mulhwu¤ len,r7,k¤   /* len is high word of product, for carry */
93d70f ¤   bdz-¤   label¤  ¤   /* Branch to Label if --ctr == 0 */
2e3247 loop:
--38d9 0000d6c73494010016a Page 4 of bnippc.c
2f2c28 ¤   lwzu¤   r7,4(in)¤   /* r7 = *++in */
3053e5 ¤   mullw¤  r8,r7,k¤¤   /* Low half of multiply in r8 */
1af082 ¤   adde¤   r8,r8,len¤  /* Add carry word len and bit CF to r8 */
f16ab8 ¤   stwu¤   r8,4(out)¤  /* *++out = r8 */
e4a783 ¤   mulhwu¤ len,r7,k¤   /* len is high word of product, for carry */
266275 ¤   bdnz+¤  loop¤   ¤   /* Branch to Loop if --ctr != 0 */
e1926b label:
020904 ¤   addze¤  len,len¤¤   /* Add carry flag to carry word */
9f0195 ¤   stw ¤   len,4(out)
2981ec ¤   blr
e2efe6 }
a7af5a
1338e5 /*
fa299e ·* MulAdd1 expects (*out, *in, len, k), count >= 1
7f49ae ·* ·················r3 ···r4 ··r5 ··r6
eb495d ·*/
d25a82 asm unsigned
d6feb4 bniMulAdd1_32(register unsigned *out, register unsigned const *in,
c6a7dd ¤   register unsigned len, register unsigned k)
38bb36 {
7e1370 ¤   lwz ¤   r7,0(in) ¤  /* Load first word of in in r7 */
7da122 ¤   lwz ¤   r0,0(out)¤  /* Load first word of out into r0 */
3231c0 ¤   mullw¤  r8,r7,k ¤   /* Low half of multiply in r8 */
561f47 ¤   mtctr¤  len ¤   ¤   /* Move len into CTR */
ed2e60 ¤   mulhwu¤ len,r7,k¤   /* High half of multiply in len */
4b550c ¤   addc¤   r8,r8,r0¤   /* r8 = r8 + r0 */
1cd876 ¤   stw ¤   r8,0(out)¤  /* Store result to memory */
d5d70f ¤   bdz-¤   label¤  ¤   /* Branch to Label if --ctr == 0 */
093247 loop:
d72c28 ¤   lwzu¤   r7,4(in)¤   /* r7 = *++in */
974bee ¤   lwzu¤   r0,4(out)¤  /* r0 = *++out */
3368ba ¤   mullw¤  r8,r7,k¤¤   /* r8 = low word of product */
ad2fe7 ¤   adde¤   r8,r8,len¤  /* Add carry word len and carry bit CF to r8 */
fea783 ¤   mulhwu¤ len,r7,k¤   /* len is high word of product, for carry */
d0d095 ¤   addze¤  len,len¤¤   /* Add carry bit from low add to r5 */
0b550c ¤   addc¤   r8,r8,r0¤   /* r8 = r8 + r0 */
fdf643 ¤   stw ¤   r8,0(out)¤  /* *out = r8 */
0d6275 ¤   bdnz+¤  loop¤   ¤   /* Branch to Loop if --ctr != 0 */
98926b label:
964c9d ¤   addze¤  r3,r5¤  ¤   /* Add carry flag to r5 and move to r3 */
b581ec ¤   blr
a1efe6 }
d6af5a
9138e5 /*
61925d ·* MulSub1 expects (*out, *in, len, k), count >= 1
af49ae ·* ·················r3 ···r4 ··r5 ··r6
a4775e ·*
8a8104 ·* Multiply and subtract is rather a pain. ·If the subtract of the
27cf9a ·* low word of the product from out[i] generates a borrow, we want to
207b22 ·* increment the carry word (initially in the range 0..0xfffffffe).
7cc591 ·* However, the PPC's carry bit CF is *clear* after a subtract, so
91cef7 ·* we want to add (1-CF) to the carry word. ·This is done using two
800a8c ·* instructions:
53775e ·*
3efa53 ·* SUBFME, subtract from minus one extended. ·This computes
aea0d2 ·* ··rD = ~rS + 0xffffffff + CF. ·Since rS is from 0 to 0xfffffffe,
9e23b9 ·* ··~rS is from 1 through 0xffffffff, and the sum with 0xffffffff+CF is
5f9201 ·* ··from 0 through 0xfffffffff, setting the carry flag unconditionally, and
b095cd ·* NOR, which is used as a bitwise invert NOT instruction.
6b775e ·*
35eebd ·* The SUBFME performs the computation rD = ~rS + 0xffffffff + CF,
c63fc9 ·* = (-rS - 1) + (CF - 1) = -(rS - CF + 1) - 1 = ~(rS + 1-CF),
2981b6 ·* which is the bitwise complement of the value we want.
d5e591 ·* We want to add the complement of that result to the low word of the
df82f0 ·* product, which is just what a subtract would do, if only we could get
9d5687 ·* the carry flag clear. ·But it's always set, except for SUBFE, and the
4486d7 ·* operation we just performed unconditionally *sets* the carry flag. ·Ugh.
495b04 ·* So find the complement in a separate instruction.
37495d ·*/
ff5a82 asm unsigned
4d8fc6 bniMulSub1_32(register unsigned *out, register unsigned const *in,
0da7dd ¤   register unsigned len, register unsigned k)
--4436 001c72805394010016a Page 5 of bnippc.c
2cbb36 {
d61370 ¤   lwz ¤   r7,0(in) ¤  /* Load first word of in in r7 */
37a122 ¤   lwz ¤   r0,0(out)¤  /* Load first word of out into r0 */
e41f47 ¤   mtctr¤  len ¤   ¤   /* Move len into CTR */
2031c0 ¤   mullw¤  r8,r7,k ¤   /* Low half of multiply in r8 */
9e2e60 ¤   mulhwu¤ len,r7,k¤   /* High half of multiply in len */
464da7 ¤   subfc¤  r8,r8,r0¤   /* r8 = r0 - r8, setting CF */
58d876 ¤   stw ¤   r8,0(out)¤  /* Store result to memory */
4d7fcd ¤   subfme¤ len,len¤¤   /* First of two insns to add (1-CF) to len */
06d70f ¤   bdz-¤   label¤  ¤   /* Branch to Label if --ctr == 0 */
793247 loop:
182c28 ¤   lwzu¤   r7,4(in)¤   /* r7 = *++in */
cd4bee ¤   lwzu¤   r0,4(out)¤  /* r0 = *++out */
045974 ¤   nor ¤   len,len,len¤/* Second of two insns to add (1-CF) to len */
e768ba ¤   mullw¤  r8,r7,k¤¤   /* r8 = low word of product */
cdb62b ¤   addc¤   r8,r8,len¤  /* Add carry word len to r8 */
97a783 ¤   mulhwu¤ len,r7,k¤   /* len is high word of product, for carry */
9d0725 ¤   addze¤  len,len¤¤   /* Add carry bit from low add to len */
268ce8 ¤   subfc¤  r8,r8,r0¤   /* r8 = r0 - r8 */
87f643 ¤   stw ¤   r8,0(out)¤  /* *out = r8 */
f87fcd ¤   subfme¤ len,len¤¤   /* First of two insns to add (1-CF) to len */
8d6275 ¤   bdnz+¤  loop¤   ¤   /* Branch to Loop if --ctr != 0 */
72926b label:
b321b7 ¤   nor ¤   r3,r5,r5¤   /* Finish adding (1-CF) to len, store in r3 */
d981ec ¤   blr
25efe6 }
f0af5a
ebb24d #endif /* __MWERKS >= 0x800 */
c77b8e /* 45678901234567890123456789012345678901234567890123456789012345678901234567*/
--5ca2 0010f7fbd834010016b Page 1 of bnippc.h
875767 #ifndef Included_bnippc_h
f41f70 #define Included_bnippc_h
34af5a
65c5d5 #include "pgpBase.h"
d1af5a
6538e5 /*
0c7232 ·* Assembly-language routines for the Power PC processor.
78c415 ·* Annoyingly, the Power PC does not have 64/32->32 bit divide,
b2613b ·* so the C code should be reasonably fast. ·But it does have
7f2cea ·* 32x32->64-bit multiplies, and these routines provide access
2fc53d ·* to that.
d7775e ·*
74aadd ·* In versions of CodeWarrior before 8.0, there was no PPC assembler,
c91c10 ·* so a kludged-up one in CPP is used. ·This requires casting an
1f9c5e ·* array of unsigneds to function pointer type, and a function pointer
644350 ·* is not a pointer to the code, but rather a pointer to a (code,TOC)
8e1fac ·* pointer pair which we fake up.
30775e ·*
d20ebe ·* CodeWarrior 8.0 supports PCC assembly, which is used directly.
6e775e ·*
74e0e7 ·* $Id: bnippc.h,v 1.4 1997/05/23 00:36:31 heller Exp $
2e495d ·*/
8caf5a
d838e5 /*
6c198a ·* Bignums are stored in arrays of 32-bit words, and the least
b5f185 ·* significant 32-bit word has the lowest address, thus "little-endian".
79424f ·* The C code is slightly more efficient this way, so unless the
14f620 ·* processor cares (the PowerPC, like most RISCs, doesn't), it is
d5d7e6 ·* best to use BN_LITTLE_ENDIAN.
a382ac ·* Note that this has NOTHING to do with the order of bytes within a 32-bit
6fdd0f ·* word; the math library is insensitive to that.
84495d ·*/
8c7be2 #define BN_LITTLE_ENDIAN 1
04af5a
e4fd86 typedef unsigned bnword32;
e9ca02 #define BNWORD32 bnword32
8caf5a
0d99c6 PGP_BEGIN_C_DECLARATIONS
4aaf5a
f9752c #if __MWERKS__ < 0x800
acaf5a
934cbc /* Shared transition vector array */
d90275 extern unsigned const * const bniPPC_tv[];
0aaf5a
987919 /* A function pointer on the PowerPC is a pointer to a transition vector */
0507a1 #define bniMulN1_32 \
8ad7be ((void (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(bniPPC_tv+0))
31f0fc #define bniMulAdd1_32 \
340f7c ((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(bniPPC_tv+1))
b1d538 #define bniMulSub1_32 \
e92ab1 ((bnword32 (*)(bnword32 *, bnword32 const *, unsigned, bnword32))(bniPPC_tv+2))
8eaf5a
2e8cee #else /* __MWERKS__ >= 0x800 */
b0af5a
e09f25 void bniMulN1_32(bnword32 *, bnword32 const *, unsigned, bnword32);
c910e8 #define bniMulN1_32 bniMulN1_32
c923f0 bnword32 bniMulAdd1_32(bnword32 *, bnword32 const *, unsigned, bnword32);
f07ea8 #define bniMulAdd1_32 bniMulAdd1_32
df6f32 bnword32 bniMulSub1_32(bnword32 *, bnword32 const *, unsigned, bnword32);
cc09c1 #define bniMulSub1_32 bniMulSub1_32
6caf5a
15e1e1 #endif /* __MWERKS__ >= 0x800 */
cbaf5a
3f1254 PGP_END_C_DECLARATIONS
70af5a
0f522c #endif /* Included_bnippc_h */
--3683 001fc58715d4010016c Page 1 of bnisparc.h
bc38e5 /*
ff3297 ·* bnisparc.h - 32-bit bignum primitives for the 68020 (or 683xx) processors.
32775e ·*
410acf ·* These primitives use little-endian word order.
83cd0d ·* (The order of bytes within words is irrelevant.)
76775e ·*
fcafbf ·* $Id: bnisparc.h,v 1.1 1997/08/12 08:30:38 colin Exp $
ba495d ·*/
a07be2 #define BN_LITTLE_ENDIAN 1
42af5a
de69da typedef unsigned long bnword32;
46ca02 #define BNWORD32 bnword32
87af5a
893379 #ifdef __cplusplus
696dad extern "C" {
3f7454 #endif
83af5a
b99a07 void bniMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
10ae31 bnword32
88a889 bniMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
d2ae31 bnword32
39d47b bniMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
dd38e5 /*
9663ee bnword32 bniDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
03063c unsigned bniModQ_32(bnword32 const *n, unsigned len, unsigned d);
fc7fe0 */
8aaf5a
f23379 #ifdef __cplusplus
2cefe6 }
707454 #endif
3baf5a
c6cf46 /* #define the values to exclude the C versions */
ed10e8 #define bniMulN1_32 bniMulN1_32
927ea8 #define bniMulAdd1_32 bniMulAdd1_32
7709c1 #define bniMulSub1_32 bniMulSub1_32
f838e5 /*
89615a #define bniDiv21_32 bniDiv21_32
dbf735 #define bniModQ_32 bniModQ_32
fc7fe0 */
--26e3 0001232e03e4010016d Page 1 of bnisparc.s
6c95b1 !
39b1a8 ! On the SPARC, %o0..%o5 are available. ·%o6 is the stack pointer and
fd0bce ! %o7 is the return address.
650f2b ! Some of the globals are also available. ·%g0 is hardwired 0 and
731218 ! %g1 is definitely available. ·%g2-%g4 appear to be, as well.
886dcf ! Arguments are in %o0 upwards. ·Return values are in %o0.
8295b1 !
fde105 ! The SPARC has delayed branches. ·Unless the ,a option is added to an
bfdeae ! instruction, the instruction after a branch is executed.
fd95b1 !
9aa027 ! SPARC multipllies are variable-time in the second input
800da1 ! (The one that can possibly be an immediate.)
c48ce5 ! That should correspond to the "k" argument, %o3
8995b1 !
5b1983 .section¤   ".text"
c0af5a
71fd77 ! BNWORD32
311fe0 ! bniMulAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
d15a99 ! ·······················%o0 ·················%o1 ··········%o2 ·········%o3
778d8f ! out += k * in, of length len, and returns the word of carry.
9d95b1 !
76a791 ! Len is guaranteed greater than 0.
435908 ! %g1 is the current input word
a31ced ! %g2 is the current output word
b57888 ! %o4 is the current product word
429f1a ! %o5 is the carry word
5b95b1 !
e410e0 ! For doing multiply-add, the (pre-v9) SPARC is a bit annoying because
091217 ! it only has one set of condition codes, which are needed both by the
ce89c8 ! add-with-carry and the loop indexing.
ff95b1 !
006b32 ! The basic sequence of the loop is:
86860f ! 1. Multiply k * *in++ -> high, low
3d3985 ! 2. Addxcc carry word and carry bit to low
7000b2 ! 3. Addx carry bit to high, producing carry word (can't overflow)
60d508 ! 4. Addcc low to *out++
3695b1 !
915f3f ! Note that the carry bit set in step 4 is used in step 2. ·The only place
812797 ! in this loop that the carry flag isn't in use is between steps 3 and 4,
289a1b ! so we have to rotate the loop to place the loop indexing operations here.
c52e3c ! The loop above ignores the details of when to do loads, stores and the
663e1d ! pointer increments, which have some flexibility, but should be scheduled
445983 ! to avoid stalls.
3695b1 !
2a00fc ! The first iteration has no carry word in, so it requires only steps 1 and 4,
1a2265 ! and since we begin the loop with step 4, it boils down to just step 1
de2545 ! followed by the loop indexing.
3b95b1 !
15e3f2 ! This loop is unrolled once to simplify·
71af5a
3daf5a
af12dc ¤   .align 4
294359 ¤   .global bniMulAdd1_32
09dc95 ¤   .type¤  bniMulAdd1_32,#function
7bd479 bniMulAdd1_32:
1a4307 ¤   ld¤ [%o1],%g1¤  ! Fetch *in
785de2 ¤   subcc¤  %o2,1,%o2
87170e ¤   umul¤   %g1,%o3,%o4
14cec6 ¤   rd¤ %y,%o5
75af5a
623de7 ¤   be¤ Lma_once
68cf97 ¤   ld¤ [%o0],%g2¤  ! Fetch *out
20231b ¤   andcc¤  %o2,1,%g0
20ae81 ¤   ld¤ [%o1+4],%g1¤! Fetch *in
10d1dd ¤   bne¤Lma_loop1
bc2db3 ¤   addcc¤  %g2,%o4,%o4¤! Add to *out, setting carry bit
85af5a
729e3a ¤   sub¤%o1,4,%o1
3e065d ¤   sub¤%o0,4,%o0
d5af5a
319f84 Lma_loop:
12d84b ¤   st¤ %o4,[%o0+4]¤! Store prev *out
--1a2f 000929d3a0e4010016d Page 2 of bnisparc.s
89dc7d ¤   add¤%o1,8,%o1
0fdd0b ¤   umul¤   %g1,%o3,%o4¤! Multiply, low half of product in %o4
436996 ¤   ld¤ [%o0+8],%g2¤! Fetch *out
15ae81 ¤   ld¤ [%o1+4],%g1¤! Fetch *in
04d07d ¤   addxcc¤ %o5,%o4,%o4¤! Add carry word and bit from last step
ca1671 ¤   rd¤ %y,%o5¤ ¤   ! High half of product is new carry word
bcea0e ¤   addx¤   %g0,%o5,%o5¤! Propagate carry bit
35af5a
79441a ¤   add¤%o0,8,%o0
4c2db3 ¤   addcc¤  %g2,%o4,%o4¤! Add to *out, setting carry bit
b0af5a
61f2ed Lma_loop1:
2a613c ¤   st¤ %o4,[%o0]¤  ! Store prev *out
bedd0b ¤   umul¤   %g1,%o3,%o4¤! Multiply, low half of product in %o4
c5c62b ¤   ld¤ [%o0+4],%g2¤! Fetch *out
b0e18a ¤   ld¤ [%o1+8],%g1¤! Fetch *in (may be redundant)
e8d07d ¤   addxcc¤ %o5,%o4,%o4¤! Add carry word and bit from last step
361671 ¤   rd¤ %y,%o5¤ ¤   ! High half of product is new carry word
9fea0e ¤   addx¤   %g0,%o5,%o5¤! Propagate carry bit
59af5a
ca3e76 ¤   subcc¤  %o2,2,%o2¤  ! Loop overhead
d31901 ¤   bgu¤Lma_loop
832db3 ¤   addcc¤  %g2,%o4,%o4¤! Add to *out, setting carry bit
20af5a
d7a954 !Lma_done:
0406df ¤   st¤ %o4,[%o0+4]¤! Store *out
9c28c6 ¤   retl
d267c4 ¤   addx¤   %g0,%o5,%o0¤! Compute carry word to return
65af5a
12b3a1 Lma_once:
df2db3 ¤   addcc¤  %g2,%o4,%o4¤! Add to *out, setting carry bit
7ce9ce ¤   st¤ %o4,[%o0]¤  ! Store *out
2f28c6 ¤   retl
1167c4 ¤   addx¤   %g0,%o5,%o0¤! Compute carry word to return
65af5a
689d5f ma32_end:
28baa0 ¤   .size¤  ·bniMulAdd1_32,ma32_end-bniMulAdd1_32
36af5a
cbaf5a
01fd77 ! BNWORD32
a7126f ! bniMulSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
e36141 ! out -= k * in, of length len, and returns the word of carry.
a6f0f0 ! This is similar, but we subtract. ·The SPARc uses a borrow bit,
a75389 ! so we can add the borrow from a subtract to the carry word.
0695b1 !
9b12dc ¤   .align 4
f121a8 ¤   .global bniMulSub1_32
9ef778 ¤   .type¤  bniMulSub1_32,#function
14af5a
28321d bniMulSub1_32:
b94307 ¤   ld¤ [%o1],%g1¤  ! Fetch *in
e6170e ¤   umul¤   %g1,%o3,%o4
c9cec6 ¤   rd¤ %y,%o5
9eaf5a
7e5de2 ¤   subcc¤  %o2,1,%o2
6ccf97 ¤   ld¤ [%o0],%g2¤  ! Fetch *out
77bf95 ¤   be¤ Lms_once
4f231b ¤   andcc¤  %o2,1,%g0
2781ca ¤   bne¤Lms_loop1
9e33f4 ¤   subcc¤  %g2,%o4,%o4¤! Subtact from *out, setting carry bit
90af5a
4bcf93 Lms_loop:
96ae81 ¤   ld¤ [%o1+4],%g1¤! Fetch *in
8e613c ¤   st¤ %o4,[%o0]¤  ! Store prev *out
c5ed89 ¤   add¤%o1,4,%o1
0fdd0b ¤   umul¤   %g1,%o3,%o4¤! Multiply, low half of product in %o4
2cd07d ¤   addxcc¤ %o5,%o4,%o4¤! Add carry word and bit from last step
ca1671 ¤   rd¤ %y,%o5¤ ¤   ! High half of product is new carry word
28ea0e ¤   addx¤   %g0,%o5,%o5¤! Propagate carry bit
c8af5a
75c62b ¤   ld¤ [%o0+4],%g2¤! Fetch *out
9275ee ¤   add¤%o0,4,%o0
--7dd7 000706f57bb4010016d Page 3 of bnisparc.s
4833f4 ¤   subcc¤  %g2,%o4,%o4¤! Subtact from *out, setting carry bit
f5af5a
379683 Lms_loop1:
1dae81 ¤   ld¤ [%o1+4],%g1¤! Fetch *in
32613c ¤   st¤ %o4,[%o0]¤  ! Store prev *out
96ed89 ¤   add¤%o1,4,%o1
6ddd0b ¤   umul¤   %g1,%o3,%o4¤! Multiply, low half of product in %o4
ebd07d ¤   addxcc¤ %o5,%o4,%o4¤! Add carry word and bit from last step
c11671 ¤   rd¤ %y,%o5¤ ¤   ! High half of product is new carry word
fcea0e ¤   addx¤   %g0,%o5,%o5¤! Propagate carry bit
caaf5a
193e76 ¤   subcc¤  %o2,2,%o2¤  ! Loop overhead
f3c62b ¤   ld¤ [%o0+4],%g2¤! Fetch *out
b575ee ¤   add¤%o0,4,%o0
cb9b73 ¤   bgu¤Lms_loop
b0dc14 ¤   subcc¤  %g2,%o4,%o4¤! Subtract from *out, setting carry bit
6baf5a
70f943 !Lms_done:
0ee9ce ¤   st¤ %o4,[%o0]¤  ! Store *out
7728c6 ¤   retl
3567c4 ¤   addx¤   %g0,%o5,%o0¤! Compute carry word to return
16af5a
c8e3b6 Lms_once:
162fa5 ¤   subcc¤  %g2,%o4,%o4¤! Add to *out, setting carry bit
f7e9ce ¤   st¤ %o4,[%o0]¤  ! Store *out
ee28c6 ¤   retl
4567c4 ¤   addx¤   %g0,%o5,%o0¤! Compute carry word to return
98af5a
a49ff3 ms_end:
0e33cf ¤   .size¤  ·bniMulSub1_32,ms_end-bniMulSub1_32
36af5a
82487c ! void
87fc55 ! bniMulN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
a6c312 ! ······················%o0 ·················%o1 ·········%o2 ··········%o3
b7504a ! out = k * in. ·The carry word is stored.
11bcdf ! This is similar to the previous cases, but simpler.
c0838c ! If we didn't have to use the carry flag to do the loop overhead,
d70be5 ! we could just re-use the carry around the loop.
5212dc ¤   .align 4
13c89a ¤   .global bniMulN1_32
0dbad1 ¤   .type¤  bniMulN1_32,#function
929951 bniMulN1_32:
874307 ¤   ld¤ [%o1],%g1¤  ! Fetch *in
16170e ¤   umul¤   %g1,%o3,%o4
fbcec6 ¤   rd¤ %y,%o5
f7af5a
35d3ba ¤   subcc¤  %o2,1,%o2¤  ! Loop overhead
50a698 ¤   be¤ Lm_done
e8e9ce ¤   st¤ %o4,[%o0]¤  ! Store *out
6daf5a
2596ec Lm_loop:
beae81 ¤   ld¤ [%o1+4],%g1¤! Fetch *in
0aed89 ¤   add¤%o1,4,%o1
dd75ee ¤   add¤%o0,4,%o0
51dd0b ¤   umul¤   %g1,%o3,%o4¤! Multiply, low half of product in %o4
063cf0 ¤   addcc¤  %o5,%o4,%o4¤! Add carry word from last step
d91671 ¤   rd¤ %y,%o5¤ ¤   ! High half of product is new carry word
cc95b1 !
432c82 !¤  st¤ %o4,[%o0]¤  ! Store *out
26aab1 !Lm_loop1:
64f672 !¤  ld¤ [%o1+4],%g1¤! Fetch *in
1a65fa !¤  add¤%o1,4,%o1
9afd9d !¤  add¤%o0,4,%o0
08f840 !¤  umul¤   %g1,%o3,%o4¤! Multiply, low half of product in %o4
8f3b10 !¤  addxcc¤ %o5,%o4,%o4¤! Add carry bit and word from last step
6024bb !¤  rd¤ %y,%o5¤ ¤   ! High half of product is new carry word
a0ea0e ¤   addx¤   %g0,%o5,%o5¤! Propagate carry bit
30af5a
a85b1e !¤  subcc¤  %o2,2,%o2¤  ! Loop overhead
bcd3ba ¤   subcc¤  %o2,1,%o2¤  ! Loop overhead
dc10a5 ¤   bgu¤Lm_loop
70e9ce ¤   st¤ %o4,[%o0]¤  ! Store *out
--7e15 001fdfb0c734010016d Page 4 of bnisparc.s
e0af5a
691727 Lm_done:
0a28c6 ¤   retl
45410a ¤   st¤ %o5,[%o0+4]¤! Store carry word
08c5c7 m_end:
fd60c7 ¤   .size¤  ·bniMulN1_32,m_end-bniMulN1_32
--b088 0015d39a8194010016e Page 1 of bnjacobi.c
bc38e5 /*
95387d ·* Compute the Jacobi symbol (small prime case only).
e6775e ·*
c968c2 ·* Written by Colin Plumb.
b1775e ·*
e3eb5f ·* $Id: bnjacobi.c,v 1.2 1997/05/09 23:17:22 lloyd Exp $
8e495d ·*/
2b39fc #include "bn.h"
2a352d #include "bnjacobi.h"
bdaf5a
e038e5 /*
188bdf ·* For a small (usually prime, but not necessarily) prime p,
6a9c1c ·* compute Jacobi(p,bn), which is -1, 0 or +1, using the following rules:
563168 ·* Jacobi(x, y) = Jacobi(x mod y, y)
300312 ·* Jacobi(0, y) = 0
2836ed ·* Jacobi(1, y) = 1
6e8121 ·* Jacobi(2, y) = 0 if y is even, +1 if y is +/-1 mod 8, -1 if y = +/-3 mod 8
e23d99 ·* Jacobi(x1*x2, y) = Jacobi(x1, y) * Jacobi(x2, y) (used with x1 = 2 & x1 = 4)
55b741 ·* If x and y are both odd, then
80b61f ·* Jacobi(x, y) = Jacobi(y, x) * (-1 if x = y = 3 mod 4, +1 otherwise)
b2495d ·*/
dd4d2f int
84e348 bnJacobiQ(unsigned p, BigNum const *bn)
16bb36 {
777286 ¤   int j = 1;
03fb23 ¤   unsigned u = bnLSWord(bn);
27af5a
e2518f ¤   if (!(u & 1))
eda13f ¤   ¤   return 0;¤  /* Don't *do* that */
15af5a
7e23b5 ¤   /* First, get rid of factors of 2 in p */
106cd2 ¤   while ((p & 3) == 0)
56aa3f ¤   ¤   p >>= 2;
3c9cd5 ¤   if ((p & 1) == 0) {
b9455b ¤   ¤   p >>= 1;
524dd0 ¤   ¤   if ((u ^ u>>1) & 2)
05b441 ¤   ¤   ¤   j = -j;¤¤   /* 3 (011) or 5 (101) mod 8 */
6c9371 ¤   }
78ae67 ¤   if (p == 1)
f04b47 ¤   ¤   return j;
ae4d0d ¤   /* Then, apply quadratic reciprocity */
5cb7ed ¤   if (p & u & 2)¤ /* p = u = 3 (mod 4? */
82a8c4 ¤   ¤   j = -j;
de77c9 ¤   /* And reduce u mod p */
a04653 ¤   u = bnModQ(bn, p);
05af5a
e39e40 ¤   /* Now compute Jacobi(u,p), u < p */
d7f5f1 ¤   while (u) {
424b96 ¤   ¤   while ((u & 3) == 0)
e399ac ¤   ¤   ¤   u >>= 2;
420a23 ¤   ¤   if ((u & 1) == 0) {
ac76c8 ¤   ¤   ¤   u >>= 1;
e98bd9 ¤   ¤   ¤   if ((p ^ p>>1) & 2)
239f5c ¤   ¤   ¤   ¤   j = -j;¤/* 3 (011) or 5 (101) mod 8 */
800fe4 ¤   ¤   }
b3ae75 ¤   ¤   if (u == 1)
a171dd ¤   ¤   ¤   return j;
eec49d ¤   ¤   /* Now both u and p are odd, so use quadratic reciprocity */
91457d ¤   ¤   if (u < p) {
59fb9f ¤   ¤   ¤   unsigned t = u; u = p; p = t;
b52cb9 ¤   ¤   ¤   if (u & p & 2)¤ /* u = p = 3 (mod 4? */
704543 ¤   ¤   ¤   ¤   j = -j;
ca0fe4 ¤   ¤   }
bbd9fe ¤   ¤   /* Now u >= p, so it can be reduced */
b494b2 ¤   ¤   u %= p;
949371 ¤   }
6d3e6b ¤   return 0;
5defe6 }
--b1fd 001556144124010016f Page 1 of bnjacobi.h
bc38e5 /*
868bdf ·* For a small (usually prime, but not necessarily) prime p,
d0846d ·* Return Jacobi(p,bn), which is -1, 0 or +1.
88ad59 ·* bn must be odd.
fa775e ·*
ddce92 ·* $Id: bnjacobi.h,v 1.6 1997/05/13 01:18:49 mhw Exp $
86495d ·*/
adaf5a
66247b #ifndef Included_bnjacobi_h
6032ae #define Included_bnjacobi_h
1caf5a
e6c5d5 #include "pgpBase.h"
4aaf5a
7d99c6 PGP_BEGIN_C_DECLARATIONS
beaf5a
3abdbd #include "pgpBigNumOpaqueStructs.h"
56af5a
0dcebf int bnJacobiQ(unsigned p, BigNum const *bn);
05af5a
dd1254 PGP_END_C_DECLARATIONS
34af5a
64e7eb #endif /* Included_bnjacobi_h */
55af5a
--af84 000ea18e8b840100170 Page 1 of bnkludge.h
b6a21a #ifndef Included_bnkludge_h
4eb4cf #define Included_bnkludge_h
f1af5a
f338e5 /*
01b7c8 ·* Kludges for not-quite-ANSI systems.
4dfc2c ·* This should always be the last file included, because it may
526d3d ·* mess up some system header files.
55775e ·*
d6a9ad ·* $Id: bnkludge.h,v 1.3 1997/05/13 01:18:50 mhw Exp $
6c495d ·*/
a7af5a
6738e5 /*
5116cf ·* Some compilers complain about #if FOO if FOO isn't defined,
3f59aa ·* so do the ANSI-mandated thing explicitly...
5c495d ·*/
02e62f #ifndef ASSERT_NEEDS_STDIO
62ca4c #define ASSERT_NEEDS_STDIO 0
d97454 #endif
f34661 #ifndef ASSERT_NEEDS_STDLIB
5d6632 #define ASSERT_NEEDS_STDLIB 0
997454 #endif
bb125a #ifndef NO_STDLIB_H
ce28a8 #define NO_STDLIB_H 0
ca7454 #endif
b9af5a
de2ac0 /* SunOS 4.1.x <assert.h> needs "stderr" defined, and "exit" declared... */
08b08c #ifdef assert
04e9e9 #if ASSERT_NEEDS_STDIO
f4feb2 #include <stdio.h>
907454 #endif
96e554 #if ASSERT_NEEDS_STDLIB
b9d160 #if !NO_STDLIB_H
5bbea3 #include <stdlib.h>
197454 #endif
2a7454 #endif
bb7454 #endif
ebaf5a
f500ff #ifndef NO_MEMMOVE
fd66c7 #define NO_MEMMOVE 0
147454 #endif
57822e #if NO_MEMMOVE¤ /* memove() not in libraries */
5e148b #define memmove(dest,src,len) bcopy(src,dest,len)
357454 #endif
00af5a
f6a721 #ifndef NO_MEMCPY
908b60 #define NO_MEMCPY 0
8d7454 #endif
22db5b #if NO_MEMCPY¤  /* memcpy() not in libraries */
4926c7 #define memcpy(dest,src,len) bcopy(src,dest,len)
a07454 #endif
7baf5a
7f4144 #ifndef MEM_PROTOS_BROKEN
5e0de7 #define MEM_PROTOS_BROKEN 0
8e7454 #endif
edffbb #if MEM_PROTOS_BROKEN
c06cd8 #define memcpy(d,s,l) memcpy((void *)(d), (void const *)(s), l)
b6cb7a #define memmove(d,s,l) memmove((void *)(d), (void const *)(s), l)
4a1285 #define memcmp(d,s,l) memcmp((void const *)(d), (void const *)(s), l)
494223 #define memset(d,v,l) memset((void *)(d), v, l)
547454 #endif
95af5a
0338e5 /*
59eae7 ·* If there are no prototypes for the stdio functions, use these to
82e079 ·* reduce compiler warnings. ·Uses EOF as a giveaway to indicate
f60065 ·* that <stdio.h> was #included.
43495d ·*/
9cc826 #ifndef NO_STDIO_PROTOS
c11c09 #define NO_STDIO_PROTOS 0
597454 #endif
298b65 #if NO_STDIO_PROTOS¤/* Missing prototypes for "simple" functions */
9ff622 #ifdef EOF
ea99c6 PGP_BEGIN_C_DECLARATIONS
--3ed1 0019255b29140100170 Page 2 of bnkludge.h
b8fde8 int (puts)(char const *);
7b816d int (fputs)(char const *, FILE *);
f9449f int (fflush)(FILE *);
7a1aae int (printf)(char const *, ...);
15c6eb int (fprintf)(FILE *, char const *, ...);
3b8735 /* If we have a sufficiently old-fashioned stdio, it probably uses these... */
62e67e int (_flsbuf)(int, FILE *);
ccd5de int (_filbuf)(FILE *);
d81254 PGP_END_C_DECLARATIONS
2ab1f8 #endif /* EOF */
268a23 #endif /* NO_STDIO_PROTOS */
ddaf5a
e038e5 /*
db969c ·* Borland C seems to think that it's a bad idea to decleare a
6cf3f3 ·* structure tag and not declare the contents. ·I happen to think
2bdcd7 ·* it's a *good* idea to use such "opaque" structures wherever
d9c5db ·* possible. ·So shut up.
0e495d ·*/
d99e71 #ifdef __BORLANDC__
237f5d #pragma warn -stu
0a6756 #ifndef MSDOS
74c3f7 #define MSDOS 1
677454 #endif
407454 #endif
2daf5a
027648 /* Turn off warning about negation of unsigned values */
86c96f #ifdef _MSC_VER
c2c30e #pragma warning(disable:4146)
667454 #endif
95af5a
b22aea /* Cope with people forgetting to define the OS, if possible... */
036756 #ifndef MSDOS
9153a6 #ifdef __MSDOS
21c3f7 #define MSDOS 1
1f7454 #endif
507454 #endif
196756 #ifndef MSDOS
05de0a #ifdef __MSDOS__
7ac3f7 #define MSDOS 1
bb7454 #endif
9c7454 #endif
6baf5a
63e814 /* By MS-DOS, we mean 16-bit brain-dead MS-DOS. ·Not GCC & GO32 */
1bb053 #ifdef __GO32
ca9682 #undef MSDOS
bf7454 #endif
8f092f #ifdef __GO32__
b39682 #undef MSDOS
d67454 #endif
6eaf5a
926066 #endif /* Included_bnkludge_h */
--f7ac 001a141e05c40100171 Page 1 of bnlegal.c
bc38e5 /*
661607 ·* BigNum multiprecision integer math library.
5b775e ·*
6fe1fb ·* $Id: bnlegal.c,v 1.3 1997/05/06 00:21:10 mhw Exp $
a6495d ·*/
e6af5a
806900 #include "pgpConfig.h"¤ /* For "const"! */
e2af5a
e9eac7 /* Force inclusion of this... */
e28cb6 #include "bnlegal.h"
fcbc29 volatile const char bnCopyright[] =
a191c0 ¤   "\0bnlib 1.1.2 Copyright (c) 1995,1996 Colin Plumb.";
--d270 0018da7531640100172 Page 1 of bnlegal.h
bc38e5 /*
d5f163 ·* ANSI C stadard, section 3.5.3: "An object that has volatile-qualified
dead0c ·* type may be modified in ways unknown to the implementation or have
edb4fd ·* other unknown side effects." ·Yes, we can't expect a compiler to
f48617 ·* understand law...
6d775e ·*
1c6bc9 ·* $Id: bnlegal.h,v 1.3 1997/05/06 00:23:45 mhw Exp $
f9495d ·*/
12af5a
bbc5d5 #include "pgpBase.h"
5daf5a
a699c6 PGP_BEGIN_C_DECLARATIONS
52af5a
ef6937 extern volatile const char bnCopyright[];
a7af5a
8d1254 PGP_END_C_DECLARATIONS
--d651 000d99927e640100173 Page 1 of bnppcasm.h
b71152 #ifndef Included_bnppcasm_h
d60787 #define Included_bnppcasm_h
9d38e5 /*
64c945 ·* A PowerPC assembler in the C preprocessor.
30098f ·* This assumes that ints are 32 bits, and uses them for the values.
4b775e ·*
1df827 ·* An assembly-language routine is simply an array of unsigned ints,
d824aa ·* initialized with the macros defined here.
4e775e ·*
45e093 ·* $Id: bnppcasm.h,v 1.3 1997/05/13 01:18:51 mhw Exp $
6a775e ·*
cfe800 ·* In the PowerPC, a generic function pointer does *not* point to the
b6d342 ·* first word of code, but to a two (or possibly more) word "transition
53634c ·* vector." ·The first word of the TV points to the function's code.
0a7752 ·* The second word is the function's TOC (Table Of Contents) pointer,
c596a0 ·* which is loaded into r2. ·The function's global variables are
58794a ·* accessed via the TOC pointed to by r2. ·TOC pointers are changed,
ee19cd ·* for example, when a dynamically linked library is called, so the
00907b ·* library can have private global variables.
26775e ·*
b33d2a ·* Saving r2 and reloading r2 each function call is a hassle that
dc3f3a ·* I'd really rather avoid, since a lot of useful assembly language routines
748ac3 ·* can be written without global variables at all, so they don't need a TOC
2c2679 ·* pointer. ·But I haven't figured out how to persuade CodeWarrior 7 to
d08d1a ·* generate an intra-TOC call to an array. ·(CodeWarrior 8 supports
23a4d3 ·* PowerPC asm, which obviates the need to do the cast-to-function-pointer
23fee0 ·* trick, which obviates the need for cross-TOC calls.)
19775e ·*
241960 ·* The basic PowerPC calling conventions for integers are:
3d1e9c ·* r0 ·- scratch. ·May be modified by function calls.
f7ffac ·* r1 ·- stack pointer. ·Must be preserved across function calls.
a11942 ·* ······See IMPORTANT notes on stack frame format below.
d5eb73 ·* ······This must *ALWAYS*, at every instruction boundary, be 16-byte
55d207 ·* ······aligned and point to a valid stack frame. ·If a procedure
a1c54b ·* ······needs to create a stack frame, the recommended way is to do:
c51300 ·* ······stwu r1,-frame_size(r1)
f762f1 ·* ······and on exit, recover with one of:
c94ba3 ·* ······addi r1,r1,frame_size, ··OR
bf167f ·* ······lwz r1,0(r1)
a453b2 ·* r2 ·- TOC pointer. ·Points to the current table of contents.
e31d93 ·* ······Must be preserved across function calls.
625c08 ·* r3 ·- First argument register and return value register.
f15cb3 ·* ······Arguments are passed in r3 through r10, and values returned in
5d0b1e ·* ······r3 through r6, as needed. ·(Usually only r3 for single word.)
801562 ·* r4-r10 - More argument registers
53a654 ·* r11 - Scratch, may be modified by function calls.
9ec607 ·* ······On entry to indirect function calls, this points to the
4519b0 ·* ······transition vector, and additional words may be loaded
bdebc5 ·* ······at offsets from it. ·Some conventions use r12 instead.
1171da ·* r12 - Scratch, may be modified by function calls.
c420d4 ·* r13-r31 - Callee-save registers, may not be modified by function
a37ef3 ·* ······calls.
74c2e5 ·* The LR, CTR and XER may be modified by function calls, as may the MQ
18562e ·* register, on those processors for which it is implemented.
41f467 ·* CR fields 0, 1, 5, 6 and 7 are scratch and may be modified by function
cf90a0 ·* calls. ·CR fields 2, 3 and 4 must be preserved across function calls.
7b775e ·*
999b61 ·* Stack frame format - READ
10775e ·*
b8b103 ·* r1 points to a stack frame, which must *ALWAYS*, meaning after each and
d8ebcb ·* every instruction, without excpetion, point to a valid 16-byte-aligned
1e8fad ·* stack frame, defined as follows:
364ce3 ·* - The 296 bytes below r1 (from -296(r1) to -1(r1)) are the so-called Red
f56777 ·* ··Zone reserved for leaf procedures, which may use it without allocating
65da34 ·* ··a stack frame and without decrementing r1. ·The size comes from the room
62a69d ·* ··needed to store all the callee-save registers: 19 64-bit integer registers
f0b37d ·* ··and 18 64-bit floating-point registers. (18+19)*8 = 296. ·So any
774be8 ·* ··procedure can save all the registers it needs to save before creating
0f789b ·* ··a stack frame and moving r1.
02ad82 ·* ··The bytes at -297(r1) and below may be used by interrupt and exception
1ba743 ·* ··handlers *at any time*. ·Anything placed there may disappear before
d99e29 ·* ··the next instruction.
--7580 0009577664e40100173 Page 2 of bnppcasm.h
1ef2d1 ·* ··The word at 0(r1) is the previous r1, and so on in a linked list.
925cdb ·* ··This is the minimum needed to be a valid stack frame, but some other
f0ddac ·* ··offsets from r1 are preallocated by the calling procedure for the called
555a83 ·* ··procedure's use. ·These are:
545d3a ·* ··Offset 0: ·Link to previous stack frame - saved r1, if the called
c31ad1 ·* ·············procedure alters it.
7d6716 ·* ··Offset 4: ·Saved CR, if the called procedure alters the callee-save
b54778 ·* ·············fields. ·There's no important reason to save it here,
9479dd ·* ·············but the space is reserved and you might as well use it
85d22e ·* ·············for its intended purpose unless you have good reason to
6cde30 ·* ·············do otherwise. ·(This may help some debuggers.)
94e4bc ·* ··Offset 8: ·Saved LR, if the called procedure needs to save it for
bd80a8 ·* ·············later function return. ·Saving the LR here helps a debugger
aa2f1b ·* ·············track the chain of return addresses on the stack.
b8f67f ·* ·············Note that a called procedure does not need to preserve the
d854c3 ·* ·············LR for it's caller's sake, but it uually wants to preserve
a55b96 ·* ·············the value for its own sake until it finishes and it's
329036 ·* ·············time to return. ·At that point, this is usually loaded
6ae62d ·* ·············back into the LR and the branch accomplished with BLR.
56cc85 ·* ·············However, if you want to be preverse, you could load it
f78aff ·* ·············into the CTR and use BCTR instead.
decc4f ·* ··Offset 12: Reserved to compiler. ·I can't find what this is for.
a88334 ·* ··Offset 16: Reserved to compiler. ·I can't find what this is for.
4fff5f ·* ··Offset 20: Saved TOC pointer. ·In a cross-TOC call, the old TOC (r2)
827a67 ·* ·············is saved here before r2 is loaded with the new TOC value.
c12ecf ·* ·············Again, it's not important to use this slot for this, but
e016c7 ·* ·············you might as well.
d8fd01 ·* Beginning at offset 24 is the argument area. ·This area is at least 8 words
ff664b ·* (32 bytes; I don't know what happens with 64 bits) long, and may be longer,
abd5bc ·* up to the length of the longest argument list in a function called by
c3fa21 ·* the function which allocated this stack frame. ·Generally, arguments
ae4e35 ·* to functions are passed in registers, but if those functions notice
e80b59 ·* the address of the arguments being taken, the registers are stored
a75036 ·* into the space reserved for them in this area and then used from memory.
c2c707 ·* Additional arguments that will not fit into registers are also stored
eb2f1e ·* here. ·Variadic functions (like printf) generally start by saving
c4931e ·* all the integer argument registers from the "..." onwards to this space.
7ba7a2 ·* For that reason, the space must be large enough to store all the argument
1e7da9 ·* registers, even if they're never used.
77f77d ·* (It could probably be safely shrunk if you're not calling any variadic
db37d0 ·* functions, but be careful!)
6e9ec0 ·*·
76ae47 ·* Offsets above that are private to the calling function and shouldn't
48fbb6 ·* be messed with. ·Generally, what appears there is locals, then saved
59dfaa ·* registers.
e1775e ·*
fb775e ·*
b438e0 ·* The floating-point instruction set isn't implemented yet (I'm too
021205 ·* lazy, as I don't need it yet), but for when it is, the register
4c0eb2 ·* usage convention is:
4a16fa ·* FPSCR - Scratch, except for floating point exception enable fields,
4db611 ·* which should only be modified by functions defined to do so.
5558a9 ·* fr0 ·- scratch
18a5a5 ·* fr1 ·- first floating point parameter and return value, scratch
043628 ·* fr2 ·- second floating point parameter and return value (if needed), scratch
9fb89a ·* fr3 ·- third floating point parameter and return value (if needed), scratch
42dcd8 ·* fr4 ·- fourth floating point parameter and return value (if needed), scratch
317dfb ·* fr5-fr13 - More floating point argument registers, scratch
b9a26e ·* fr14-fr31 - Callee-save registers, may not be modified across a func call
7a775e ·*
41d79c ·* Complex values store the real part in the lower-numberd register of a pair.
69a9cd ·* When mixing floating-point and integer arguments, reserve space (one reg
b00ef2 ·* for single-precision, two for double-precision values) in the integer
6cd205 ·* argument list for the floating-point values. ·Those integer registers
c7fa8a ·* generally have undefined values, UNLESS there is no prototype for the call,
7536a0 ·* in which case they should contain a copy of the floating-point value's
8f564c ·* bit pattern to cope with wierd software.
f68cf0 ·* If the floating point arguments go past the end of the integer registers,
e91f9f ·* they are stored in the argument area as well as being passed in here.
d3775e ·*
57c62f ·* After the argument area comes the calling function's private storage.
95c57d ·* Typically, there are locals, followed by saved GP rgisters, followed
--46c4 0007bad41ff40100173 Page 3 of bnppcasm.h
32af19 ·* by saved FP registers.
c4775e ·*
afb8e6 ·* Suggested instruction for allocating a stack frame:
a5b201 ·* ·······stwu r1,-frame_size(r1)
a1264e ·* Suggested instructions for deallocating a stack frame:
1f1718 ·* ·······addi r1,r1,frame_size
3d5e6d ·* or
2c2eee ·* ·······lwz r1,0(r1)
cfc796 ·* If frame_size is too big, you'll have to load the offset into a temp
6520d2 ·* register, but be sure that r1 is updated atomically.
a1775e ·*
c8775e ·*
1944e0 ·* Basic PowerPC instructions look like this:
9b775e ·*
033d95 ·* ·····················1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
658a06 ·* ·0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
c31ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7698f5 ·* | ··Opcode ·| | | | | | | | | | | | | | | | | | | | | | | | | | |
d31ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96775e ·*
eaf758 ·* Branch instructions look like this:
8a775e ·*
351ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
278244 ·* | ··Opcode ·| ············Branch offset ····················|A|L|
1f1ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52775e ·*
092f54 ·* The L, or LK, or Link bit indicates that the return address for the
9f2b20 ·* branch should be copied to the link register (LR).
413ac6 ·* The A, or AA, or absolute address bit, indicates that the address
8c9cb1 ·* of the current instruction (NOTE: not next instruction!) should NOT
447341 ·* be added to the branch offset; it is relative to address 0.
e7775e ·*
3f9a25 ·* Conditional branches looks like this:
e41ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
05cfa9 ·* | ··Opcode ·| ···BO ··| ··BI ···| ·····Branch offset ·······|A|L|
9a1ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6d775e ·*
9f1d9c ·* The BI field specifies the condition bit of interest (from the CR).
5a0a13 ·* The BO field specifies what's interesting. ·You can branch on a
608e14 ·* combination of a bit of the condition register and --ctr, the CTR
f0021d ·* register. ·Two bits encode the branch condition to use:
6b820d ·* ··BRANCH IF
b2db17 ·* 00--- = Bit BI is 0
a65186 ·* 01--- = Bit BI is 1
8773e1 ·* 1z--- = don't care about bit BI (always true)
37f4fe ·* ··AND
b12cad ·* --00- = --ctr != 0
d061cd ·* --01- = --ctr == 0
9c9dae ·* --1z- = don't decrement ctr (always true)
142824 ·* The last bit us used as a branch prediction bit. ·If set, it reverses
25e67d ·* the usual backward-branch-taken heuristic.
c1775e ·*
5da426 ·* y = branch prediction bit. ·z = unused, must be 0
4f5cb9 ·* 0000y - branch if --ctr != 0 && BI == 0
2dd8fe ·* ········don't branch if --ctr == 0 || BI != 0
393fc8 ·* 0001y - branch if --ctr == 0 && BI == 0
f401d0 ·* ········don't branch if --ctr != 0 || BI != 0
133505 ·* 001zy - branch if BI == 0
6a0598 ·* ········don't branch if BI != 0
ead527 ·* 0100y - branch if --ctr != 0 && BI != 0
0b1b8e ·* ········don't branch if --ctr == 0 || BI == 0
e0b656 ·* 0101y - branch if --ctr == 0 && BI != 0
40c2a0 ·* ········don't branch if --ctr != 0 || BI == 0
f1f20e ·* 011zy - branch if BI != 0
ccc6e8 ·* ········don't branch if BI == 0
367253 ·* 1z00y - branch if --ctr != 0
f97588 ·* ········don't branch if --ctr == 0
4f7c73 ·* 1z01y - branch if --ctr == 0
a9b6f8 ·* ········don't branch if --ctr != 0
048e88 ·* 1z1zz - branch always
e1a4f8 ·* If y is 1, the usual branch prediction (usually not taken, taken for
7bda5f ·* backwards branches with immediate offsets) is reversed.
--2e0e 0003a8a7e3340100173 Page 4 of bnppcasm.h
4f775e ·*
a8aa97 ·* Instructions with 2 operands and a 16-bit immediate field look like this:
311ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
eef6d3 ·* | ··Opcode ·| ····D ··| ···A ···| ···16-bit immediate value ····|
a01ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3c775e ·*
8364cd ·* Now, there are three variations of note. ·In some instructions, the 16-bit
ac32cf ·* value is sign-extended. ·In others, it's zero-extended. ·These are noted
619ff7 ·* below as "simm" (signed immediate) and "uimm", respectively. ·Also, which
99f2d3 ·* field is the destination and which is the source sometimes switches.
13612c ·* Sometimes it's d = a OP imm, and sometimes it's a = s OP imm. ·In the
58b3b4 ·* latter cases, the "d" field is referred to as "s" ("source" instead of
e851e1 ·* "destination". ·These are logical and shift instructions. ·(Store also
3d073b ·* refers to the s register, but that's the source of the value to be stored.)
2f48d3 ·* The assembly mnemonics, however, always lists the destination first,
f4e8e7 ·* swapping the order in the instruction if necessary.
ddf4a1 ·* Third, quite often, if r0 is specified for the source a, then the constant
9cb503 ·* value 0 is used instead. ·Thus, r0 is of limited use - it can be used for
0c9f70 ·* some things, but not all.
49775e ·*
f5d848 ·* Instructions with three register operands look like this:
091ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1ab96f ·* | ··Opcode ·| ····D ··| ···A ···| ···B ···| ····Subopcode ····|C|
381ab0 ·* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80775e ·*
005105 ·* For most of the instructions of interest the Opcode is 31 and the subopcode
728a16 ·* determines what the instruction does. ·For a few instructions (mostly loads
49e5e8 ·* and stores), if the A field is 0, the constant 0 is used. ·The "C"
ef3006 ·* bit (also known as the "RC" bit) controls whether or not the condition
fd032f ·* codes are updated. ·If it is set (indicated by a "." suffix on the official
7c7c5d ·* PowerPC opcodes, and a "_" suffix on these macros), condition code register
6974a3 ·* field 0 (for integer instructions; field 1 for floating point) is updated
986efa ·* to reflect the result of the operation.
8d6bce ·* Some arithmetic instructions use the most significant bit of the subopcode
2d5c96 ·* field as an overflow enable bit (o suffix).
5d775e ·*
b39cd7 ·* Then there are the rotate and mask instructions, which have 5 operands, and
eb120a ·* fill the subopcode field with 2 more 5-bit fields. ·See below for them.
9d775e ·*
d8e7ea ·* NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
55cc21 ·* These macros fully parenthesize their arguments, but are not themselves
014451 ·* fully parenthesized. ·They are intended to be used for initializer lists,
1438b6 ·* and if you want to do tricks with their numeric values, wrap them in
a68f98 ·* parentheses.
9f495d ·*/
18af5a
6e9fb5 #define PPC_MAJOR(x)¤   ((x)<<26)¤  /* Major opcode (0..63) */
c305c9 #define PPC_MINOR(x)¤   ((x)<<1)¤   /* Minor opcode (0..1023) */
bea1e4 #define PPC_RC¤ 1¤  ¤   /* Record carry (. suffix, represented as _) */
c9c6b6 #define PPC_OE¤ 1024¤   ¤   /* Overflow enable (o suffix) */
7d67d5 #define PPC_DEST(reg)¤  ((reg)<<21)¤/* Dest register field */
95cd05 #define PPC_SRCA(reg)¤  ((reg)<<16)¤/* First source register field */
4863f9 #define PPC_SRCB(reg)¤  ((reg)<<11)¤/* Second source register field */
d6b34d #define PPC_AA¤ 2¤  /* Branch is absolute, relative to address 0 */
89bded #define PPC_LK¤ 1¤  /* Branch with link (L suffix) */
65af5a
297122 /* Unconditional branch (dest is 26 bits, +/- 2^25 bytes) */
077f67 #define PPC_B(dest)¤PPC_MAJOR(18)|(((dest)<<2) & 0x03fffffc)
23c761 #define PPC_BA(dest)¤   PPC_B(dest)|PPC_AA
3469d8 #define PPC_BL(dest)¤   PPC_B(dest)|PPC_LK
dff714 #define PPC_BLA(dest)¤  PPC_B(dest)|PPC_AA|PPC_LK
f3af5a
8304ef /* Three-operand instructions */
4b1850 #define PPC_TYPE31(minor,d,a,b)¤\
351411 ¤   PPC_MAJOR(31)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor)
27b6e0 #define PPC_ADD(d,a,b) ·¤   PPC_TYPE31(266,d,a,b)
1a7827 #define PPC_ADD_(d,a,b) ¤   PPC_TYPE31(266,d,a,b)|PPC_RC
af2c77 #define PPC_ADDO(d,a,b) ¤   PPC_TYPE31(266,d,a,b)|PPC_OE
46eae6 #define PPC_ADDO_(d,a,b)¤   PPC_TYPE31(266,d,a,b)|PPC_OE|PPC_RC
afb294 #define PPC_ADDC(d,a,b) ¤   PPC_TYPE31(10,d,a,b)
8d9d85 #define PPC_ADDC_(d,a,b)¤   PPC_TYPE31(10,d,a,b)|PPC_RC
3a501f #define PPC_ADDCO(d,a,b)¤   PPC_TYPE31(10,d,a,b)|PPC_OE
--2a8c 000c25547c740100173 Page 5 of bnppcasm.h
808626 #define PPC_ADDCO_(d,a,b)¤  PPC_TYPE31(10,d,a,b)|PPC_OE|PPC_RC
efa24a #define PPC_ADDE(d,a,b) ¤   PPC_TYPE31(138,d,a,b)
a8929a #define PPC_ADDE_(d,a,b)¤   PPC_TYPE31(138,d,a,b)|PPC_RC
bf1949 #define PPC_ADDEO(d,a,b)¤   PPC_TYPE31(138,d,a,b)|PPC_OE
d43b84 #define PPC_ADDEO_(d,a,b)¤  PPC_TYPE31(138,d,a,b)|PPC_OE|PPC_RC
13b7c1 #define PPC_ADDME(d,a) ·¤   PPC_TYPE31(234,d,a,0)
32b6bd #define PPC_ADDME_(d,a) ¤   PPC_TYPE31(234,d,a,0)|PPC_RC
9f7b27 #define PPC_ADDMEO(d,a) ¤   PPC_TYPE31(234,d,a,0)|PPC_OE
f4b512 #define PPC_ADDMEO_(d,a)¤   PPC_TYPE31(234,d,a,0)|PPC_OE|PPC_RC
c09788 #define PPC_ADDZE(d,a) ·¤   PPC_TYPE31(202,d,a,0)
97b5e2 #define PPC_ADDZE_(d,a) ¤   PPC_TYPE31(202,d,a,0)|PPC_RC
8f7878 #define PPC_ADDZEO(d,a) ¤   PPC_TYPE31(202,d,a,0)|PPC_OE
ffd254 #define PPC_ADDZEO_(d,a)¤   PPC_TYPE31(202,d,a,0)|PPC_OE|PPC_RC
57f8b8 #define PPC_AND(a,s,b) ·¤   PPC_TYPE31(28,s,a,b)
28f038 #define PPC_AND_(a,s,b) ¤   PPC_TYPE31(28,s,a,b)|PPC_RC
24e21d #define PPC_ANDC(a,s,b) ¤   PPC_TYPE31(60,s,a,b)
f3277c #define PPC_ANDC_(a,s,b)¤   PPC_TYPE31(60,s,a,b)|PPC_RC
a80622 #define PPC_CMP(cr,a,b) ¤   PPC_TYPE31(0,(cr)<<2,a,b)
9228f2 #define PPC_CMPL(cr,a,b)¤   PPC_TYPE31(32,(cr)<<2,a,b)
74cb39 #define PPC_CNTLZW(a,s) ¤   PPC_TYPE31(26,s,a,0)
681515 #define PPC_CNTLZW_(a,s)¤   PPC_TYPE31(26,s,a,0)|PPC_RC
296a8f #define PPC_DCBF(a,b) ··¤   PPC_TYPE31(86,0,a,b)
c898a4 #define PPC_DCBI(a,b) ··¤   PPC_TYPE31(470,0,a,b)
2a9ad9 #define PPC_DCBST(a,b) ·¤   PPC_TYPE31(54,0,a,b)
12919c #define PPC_DCBT(a,b) ··¤   PPC_TYPE31(278,0,a,b)
bc040f #define PPC_DCBTST(a,b) ¤   PPC_TYPE31(246,0,a,b)
e3d8a5 #define PPC_DCBZ(a,b) ··¤   PPC_TYPE31(1014,0,a,b)
7e0f8f #define PPC_DIVW(d,a,b) ¤   PPC_TYPE31(491,d,a,b)
e5963f #define PPC_DIVW_(d,a,b)¤   PPC_TYPE31(491,d,a,b)|PPC_RC
0c1dec #define PPC_DIVWO(d,a,b)¤   PPC_TYPE31(491,d,a,b)|PPC_OE
813e15 #define PPC_DIVWO_(d,a,b)¤  PPC_TYPE31(491,d,a,b)|PPC_OE|PPC_RC
9ae036 #define PPC_DIVWU(d,a,b)¤   PPC_TYPE31(459,d,a,b)
9882b8 #define PPC_DIVWU_(d,a,b)¤  PPC_TYPE31(459,d,a,b)|PPC_RC
944f22 #define PPC_DIVWUO(d,a,b)¤  PPC_TYPE31(459,d,a,b)|PPC_OE
9e011a #define PPC_DIVWUO_(d,a,b)¤ PPC_TYPE31(459,d,a,b)|PPC_OE|PPC_RC
fa59ca #define PPC_EIEIO() ····¤   PPC_TYPE31(854,0,0,0)
71a186 #define PPC_EQV(a,s,b) ·¤   PPC_TYPE31(284,s,a,b)
b9a3a6 #define PPC_EQV_(a,s,b) ¤   PPC_TYPE31(284,s,a,b)|PPC_RC
16d564 #define PPC_EXTSB(a,s,b)¤   PPC_TYPE31(954,s,a,b)
312927 #define PPC_EXTSB_(a,s,b)¤  PPC_TYPE31(954,s,a,b)|PPC_RC
9988fe #define PPC_EXTSH(a,s,b)¤   PPC_TYPE31(922,s,a,b)
f2861a #define PPC_EXTSH_(a,s,b)¤  PPC_TYPE31(922,s,a,b)|PPC_RC
327633 #define PPC_ICBI(a,b) ··¤   PPC_TYPE31(982,0,a,b)
c3bc23 #define PPC_ISYNC() ····¤   PPC_TYPE31(150,0,0,0)
246815 #define PPC_LBZUX(d,a,b)¤   PPC_TYPE31(119,d,a,b)
429ba3 #define PPC_LBZX(d,a,b) ¤   PPC_TYPE31(87,d,a,b)
aecf7f #define PPC_LHAUX(d,a,b)¤   PPC_TYPE31(375,d,a,b)
db86a8 #define PPC_LHAX(d,a,b) ¤   PPC_TYPE31(343,d,a,b)
7fbda6 #define PPC_LHBRX(d,a,b)¤   PPC_TYPE31(790,d,a,b)
b93aff #define PPC_LHZUX(d,a,b)¤   PPC_TYPE31(311,d,a,b)
6361d7 #define PPC_LHZX(d,a,b) ¤   PPC_TYPE31(279,d,a,b)
6f4538 #define PPC_LSWI(d,a,nb)¤   PPC_TYPE31(597,d,a,nb)
1f13f7 #define PPC_LSWX(d,a,b) ¤   PPC_TYPE31(533,d,a,b)
d2b2cc #define PPC_LSARX(d,a,b) ¤  PPC_TYPE31(20,d,a,b)
bb4e18 #define PPC_LSBRX(d,a,b) ¤  PPC_TYPE31(534,d,a,b)
92ea7e #define PPC_MCRXR(crd) ·¤   PPC_TYPE31(512,(crd)<<2,0,0)
0c297e #define PPC_MFCR(d) ····¤   PPC_TYPE31(19,d,0,0)
a1419b #define PPC_MFSPR(d,spr) ····¤  PPC_TYPE31(339,d,(spr)&31,(spr)>>5)
a45e6e #define PPC_MFTB(d) ····¤   PPC_TYPE31(371,d,12,8)
48821b #define PPC_MFTBU(d) ····¤  PPC_TYPE31(371,d,13,8)
f889e1 #define PPC_MTCRF(mask,s) ····¤ PPC_TYPE31(144,s,0,(mask)&0xff)
7a3537 #define PPC_MTSPR(s,spr) ····¤  PPC_TYPE31(467,s,(spr)&31,(spr)>>5)
319543 #define PPC_MULHW(d,a,b) ¤  PPC_TYPE31(75,d,a,b)
b17bee #define PPC_MULHW_(d,a,b) ¤ PPC_TYPE31(75,d,a,b)|PPC_RC
ff0247 #define PPC_MULHWU(d,a,b) ¤ PPC_TYPE31(11,d,a,b)
a1c83b #define PPC_MULHWU_(d,a,b) ¤PPC_TYPE31(11,d,a,b)|PPC_RC
2f8080 #define PPC_MULLW(d,a,b) ¤  PPC_TYPE31(235,d,a,b)
e9a72d #define PPC_MULLW_(d,a,b) ¤ PPC_TYPE31(235,d,a,b)|PPC_RC
106ab7 #define PPC_MULLWO(d,a,b) ¤ PPC_TYPE31(235,d,a,b)|PPC_OE
6c0e36 #define PPC_MULLWO_(d,a,b) ¤PPC_TYPE31(235,d,a,b)|PPC_OE|PPC_RC
acf8ba #define PPC_NAND(a,s,b) ·¤  PPC_TYPE31(476,s,a,b)
c2c783 #define PPC_NAND_(a,s,b) ¤  PPC_TYPE31(476,s,a,b)|PPC_RC
--c25b 000c001302040100173 Page 6 of bnppcasm.h
601228 #define PPC_NEG(d,a) ···¤   PPC_TYPE31(104,d,a,b)
9311ef #define PPC_NEG_(d,a) ···¤  PPC_TYPE31(104,d,a,b)|PPC_RC
f445bf #define PPC_NEGO(d,a) ···¤  PPC_TYPE31(104,d,a,b)|PPC_OE
15e5c3 #define PPC_NEGO_(d,a) ···¤ PPC_TYPE31(104,d,a,b)|PPC_OE|PPC_RC
72c407 #define PPC_NOR(a,s,b) ·¤   PPC_TYPE31(124,s,a,b)
722958 #define PPC_NOR_(a,s,b) ¤   PPC_TYPE31(124,s,a,b)|PPC_RC
da266b #define PPC_OR(a,s,b) ··¤   PPC_TYPE31(444,s,a,b)
ed25d5 #define PPC_OR_(a,s,b) ·¤   PPC_TYPE31(444,s,a,b)|PPC_RC
011fec #define PPC_ORC(a,s,b) ··¤  PPC_TYPE31(412,s,a,b)
e315a4 #define PPC_ORC_(a,s,b) ·¤  PPC_TYPE31(412,s,a,b)|PPC_RC
7a43f7 #define PPC_SLW(a,s,b) ··¤  PPC_TYPE31(24,s,a,b)
e7c19d #define PPC_SLW_(a,s,b) ·¤  PPC_TYPE31(24,s,a,b)|PPC_RC
ee2da1 #define PPC_SRAW(a,s,b) ··¤ PPC_TYPE31(792,s,a,b)
6d558c #define PPC_SRAW_(a,s,b) ·¤ PPC_TYPE31(792,s,a,b)|PPC_RC
fff2c0 #define PPC_SRAWI(a,s,sh) ··¤   PPC_TYPE31(824,s,a,sh)
28310c #define PPC_SRAWI_(a,s,sh) ·¤   PPC_TYPE31(824,s,a,sh)|PPC_RC
1f21af #define PPC_SRW(a,s,b) ··¤  PPC_TYPE31(536,s,a,b)
f684be #define PPC_SRW_(a,s,b) ·¤  PPC_TYPE31(536,s,a,b)|PPC_RC
a72669 #define PPC_STBUX(s,a,b) ··¤PPC_TYPE31(247,s,a,b)
ae82bf #define PPC_STBX(s,a,b) ··¤ PPC_TYPE31(215,s,a,b)
56a423 #define PPC_STHBRX(s,a,b) ··¤   PPC_TYPE31(918,s,a,b)
47d69c #define PPC_STHUX(s,a,b) ··¤PPC_TYPE31(439,s,a,b)
b2dab7 #define PPC_STHX(s,a,b) ··¤ PPC_TYPE31(407,s,a,b)
17531b #define PPC_STSWI(s,a,nb) ··¤   PPC_TYPE31(725,s,a,nb)
2ea60a #define PPC_STSWX(s,a,b) ··¤PPC_TYPE31(661,s,a,b)
41207c #define PPC_STWBRX(s,a,b) ··¤   PPC_TYPE31(662,s,a,b)
c8d156 #define PPC_STWCX_(s,a,b) ··¤   PPC_TYPE31(150,s,a,b)|PPC_RC
47a781 #define PPC_STWUX(s,a,b) ··¤PPC_TYPE31(183,s,a,b)
e76a7e #define PPC_STWX(s,a,b) ··¤ PPC_TYPE31(151,s,a,b)
e5a7f0 #define PPC_SUBF(d,a,b) ¤   PPC_TYPE31(40,d,a,b)
172fd0 #define PPC_SUBF_(d,a,b) ¤  PPC_TYPE31(40,d,a,b)|PPC_RC
e3e24a #define PPC_SUBFO(d,a,b) ¤  PPC_TYPE31(40,d,a,b)|PPC_OE
a593d2 #define PPC_SUBFO_(d,a,b) ¤ PPC_TYPE31(40,d,a,b)|PPC_OE|PPC_RC
b369d9 #define PPC_SUB(d,b,a)¤ ¤   PPC_SUBF(d,a,b)
76b3e6 #define PPC_SUB_(d,b,a)¤¤   PPC_SUBF_(d,a,b)
065360 #define PPC_SUBO(d,b,a)¤¤   PPC_SUBFO(d,a,b)
1f3576 #define PPC_SUBO_(d,b,a)¤   PPC_SUBFO_(d,a,b)
df42b3 #define PPC_SUBFC(d,a,b) ¤  PPC_TYPE31(8,d,a,b)
8c32cd #define PPC_SUBFC_(d,a,b) ¤ PPC_TYPE31(8,d,a,b)|PPC_RC
ede0dd #define PPC_SUBFCO(d,a,b) ¤ PPC_TYPE31(8,d,a,b)|PPC_OE
acef86 #define PPC_SUBFCO_(d,a,b) ¤PPC_TYPE31(8,d,a,b)|PPC_OE|PPC_RC
8892b1 #define PPC_SUBFE(d,a,b) ¤  PPC_TYPE31(136,d,a,b)
d5a454 #define PPC_SUBFE_(d,a,b) ¤ PPC_TYPE31(136,d,a,b)|PPC_RC
e769ce #define PPC_SUBFEO(d,a,b) ¤ PPC_TYPE31(136,d,a,b)|PPC_OE
b5523e #define PPC_SUBFEO_(d,a,b) ¤PPC_TYPE31(136,d,a,b)|PPC_OE|PPC_RC
543ed6 #define PPC_SUBFME(d,a) ¤   PPC_TYPE31(232,d,a,0)
aebf5a #define PPC_SUBFME_(d,a) ¤  PPC_TYPE31(232,d,a,0)|PPC_RC
f11fc4 #define PPC_SUBFMEO(d,a) ¤  PPC_TYPE31(232,d,a,0)|PPC_OE
d7e8c4 #define PPC_SUBFMEO_(d,a) ¤ PPC_TYPE31(232,d,a,0)|PPC_OE|PPC_RC
c859c2 #define PPC_SUBFZE(d,a) ¤   PPC_TYPE31(200,d,a,0)
76fe85 #define PPC_SUBFZE_(d,a) ¤  PPC_TYPE31(200,d,a,0)|PPC_RC
da5e1b #define PPC_SUBFZEO(d,a) ¤  PPC_TYPE31(200,d,a,0)|PPC_OE
480318 #define PPC_SUBFZEO_(d,a) ¤ PPC_TYPE31(200,d,a,0)|PPC_OE|PPC_RC
dba7fb #define PPC_SYNC()¤ ¤   PPC_TYPE31(598,0,0,0)
00581b #define PPC_TW(to,a,b) ··¤  PPC_TYPE31(4,to,a,b)
552312 #define PPC_XOR(a,s,b) ··¤  PPC_TYPE31(316,s,a,b)¤
60af5a
556c55 /* Immediate-operand instructions. ·Take a 16-bit immediate operand */
554b83 #define PPC_IMM(major,d,a,imm) \
e8784f ¤   PPC_MAJOR(major)|PPC_DEST(d)|PPC_SRCA(a)|((imm)&0xffff)
ffc618 /* Trap word immediate */
c46da1 #define PPV_TWI(to,a,simm)¤ PPC_IMM(3,to,a,simm)
1aac5e /* Integer arithmetic */
dcb6cf #define PPC_MULLI(d,a,simm)¤PPC_IMM(7,d,a,simm)
48e841 #define PPC_SUBFIC(s,a,simm)¤   PPC_IMM(8,s,a,simm)
bf1265 #define PPC_CMPLI(cr,a,uimm)¤   PPC_IMM(10,(cr)<<2,a,uimm)
3bdbf1 #define PPC_CMPI(cr,a,simm)¤PPC_IMM(11,(cr)<<2,a,simm)
3e77d3 #define PPC_ADDIC(d,a,simm)¤PPC_IMM(12,d,a,simm)
942c47 #define PPC_ADDIC_(d,a,simm)¤   PPC_IMM(13,d,a,simm)
af7606 #define PPC_ADDI(d,a,simm)¤ PPC_IMM(14,d,a,simm)
bbd33f #define PPC_ADDIS(d,a,simm)¤PPC_IMM(15,d,a,simm)
c0af5a
--6373 000c9084d2040100173 Page 7 of bnppcasm.h
a48913 /* Conditional branch (dest is 16 bits, +/- 2^15 bytes) */
e8163e #define PPC_BC(bo,bi,dest)¤ PPC_IMM(16,bo,bi,((dest)<<2)&0xfffc)
b790d6 #define PPC_BCA(bo,bi,dest)¤PPC_BC(bo,bi,dest)|PPC_AA
29d5db #define PPC_BCL(bo,bi,dest)¤PPC_BC(bo,bi,dest)|PPC_LK
78e564 #define PPC_BCLA(bo,bi,dest)¤   PPC_BC(bo,bi,dest)|PPC_AA|PPC_LK
4eaf5a
7f2a45 /* Logical operations */
d2631e #define PPC_ORI(a,s,uimm)¤  PPC_IMM(24,s,a,uimm)
78f9e7 #define PPC_ORIS(a,s,uimm)¤ PPC_IMM(25,s,a,uimm)
3dca2c #define PPC_XORI(a,s,uimm)¤ PPC_IMM(26,s,a,uimm)
b21a96 #define PPC_XORIS(a,s,uimm)¤PPC_IMM(27,s,a,uimm)
3d64b5 #define PPC_ANDI_(a,s,uimm)¤PPC_IMM(28,s,a,uimm)
f3fb47 #define PPC_ANDIS(a,s,uimm)¤PPC_IMM(29,s,a,uimm)
88af5a
dd37ff /* Load/store */
289ed6 #define PPC_LWZ(d,a,simm)¤  PPC_IMM(32,d,a,simm)
d25e16 #define PPC_LWZU(d,a,simm)¤ PPC_IMM(33,d,a,simm)
160010 #define PPC_LBZ(d,a,simm)¤  PPC_IMM(34,d,a,simm)
14c0d0 #define PPC_LBZU(d,a,simm)¤ PPC_IMM(35,d,a,simm)
76f6d6 #define PPC_STW(s,a,simm)¤  PPC_IMM(36,s,a,simm)
ecdb32 #define PPC_STWU(s,a,simm)¤ PPC_IMM(37,s,a,simm)
5e11ba #define PPC_STB(s,a,simm)¤  PPC_IMM(38,s,a,simm)
283c5e #define PPC_STBU(s,a,simm)¤ PPC_IMM(39,s,a,simm)
4b0787 #define PPC_LHZ(d,a,simm)¤  PPC_IMM(40,d,a,simm)
a2c747 #define PPC_LHZU(d,a,simm)¤ PPC_IMM(41,d,a,simm)
caa82f #define PPC_LHA(d,a,simm)¤  PPC_IMM(42,d,a,simm)
4d75d9 #define PPC_STH(s,a,simm)¤  PPC_IMM(44,s,a,simm)
2d583d #define PPC_STHU(s,a,simm)¤ PPC_IMM(45,s,a,simm)
1a68ef #define PPC_LHAU(d,a,simm)¤ PPC_IMM(43,d,a,simm)
045d0e #define PPC_LMW(d,a,simm)¤  PPC_IMM(46,d,a,simm)
9fc0e1 #define PPC_STMW(s,a,simm)¤ PPC_IMM(47,s,a,simm)
81af5a
20d18a /* Major number = 19 - condition register operations. ·d, a and b are CR bits*/
4b0e7a #define PPC_TYPE19(minor,d,a,b) \
b2989e ¤   PPC_MAJOR(19)|PPC_DEST(d)|PPC_SRCA(a)|PPC_SRCB(b)|PPC_MINOR(minor)
c63e5a #define PPC_MCRF(d,s) ··¤   PPC_TYPE19(0,(d)<<2,(s)<<2,0)
e7d5d9 #define PPC_CRNOR(d,a,b)¤   PPC_TYPE19(33,d,a,b)
caca87 #define PPC_CRANDC(d,a,b)¤  PPC_TYPE19(129,d,a,b)
0f3770 #define PPC_CRXOR(d,a,b)¤   PPC_TYPE19(193,d,a,b)
94ddc7 #define PPC_CRNAND(d,a,b)¤  PPC_TYPE19(225,d,a,b)
3e89c8 #define PPC_CRAND(d,a,b)¤   PPC_TYPE19(257,d,a,b)
2c0959 #define PPC_CREQV(d,a,b)¤   PPC_TYPE19(289,d,a,b)
734421 #define PPC_CRORC(d,a,b)¤   PPC_TYPE19(417,d,a,b)
6893d3 #define PPC_CROR(d,a,b) ¤   PPC_TYPE19(449,d,a,b)
56af5a
efa7f6 /* Indirect conditional branch */
ca9ff0 #define PPC_BCLR(bo,bi) ¤   PPC_TYPE19(16,bo,bi,0)
c06fbf #define PPC_BCLRL(bo,bi)¤   PPC_TYPE19(16,bo,bi,0)|PPC_LK
18be92 #define PPC_BCCTR(bo,bi)¤   PPC_TYPE19(528,bo,bi,0)
750e94 #define PPC_BCCTRL(bo,bi)¤  PPC_TYPE19(528,bo,bi,0)|PPC_LK
8bb9a0 #define PPC_BLR() ··········¤   PPC_BCLR(20,31)
700b64 #define PPC_BCTR() ··········¤  PPC_BCCTR(20,31)
a6af5a
570e08 /* Other */
bdf0c2 #define ·PPC_RLWIMI(a,s,sh,mb,me) \
4bfedf ¤   PPC_MAJOR(20)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1·
05abc8 #define ·PPC_RLWIMI_(a,s,sh,mb,me)¤ PPC_RLWIMI(a,s,sh,mb,me)|PPC_RC
0eb6a7 #define ·PPC_RLWINM(a,s,sh,mb,me) \
a12b0d ¤   PPC_MAJOR(21)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(sh)|(mb)<<6|(me)<<1·
a63eb0 #define ·PPC_RLWINM_(a,s,sh,mb,me)¤ PPC_RLWINM(a,s,sh,mb,me)|PPC_RC
7cd57c #define ·PPC_RLWNM(a,s,b,mb,me) \
23fda4 ·¤  PPC_MAJOR(23)|PPC_DEST(s)|PPC_SRCA(A)|PPC_SRCB(b)|(mb)<<6|(me)<<1·
3da37b #define ·PPC_RLWNM_(a,s,b,mb,me)¤   PPC_RLWNM(a,s,b,mb,me)|PPC_RC
daaf5a
4468c1 #define PPC_SC()¤   ¤   ¤   PPC_MAJOR(17)|2
161ddc /* Major number = 63 Floating-point operations (not implemented for now) */
90af5a
8951bc /* Simplified Mnemonics */
7b8fe5 /* Fabricate immediate subtract out of add negative */
833e4b #define PPC_SUBI(d,a,simm)¤ PPC_ADDI(d,a,-(simm))
b81367 #define PPC_SUBIS(d,a,simm)¤PPC_ADDIS(d,a,-(simm))
c96213 #define PPC_SUBIC(d,a,simm)¤PPC_ADDIC(d,a,-(simm))
--c6fb 001ef2747fd40100173 Page 8 of bnppcasm.h
2d29e4 #define PPC_SUBIC_(d,a,simm)¤   PPC_ADDIC_(d,a,-(simm))
01257e /* Fabricate subtract out of subtract from */
fd9f0a #define PPC_SUBC(d,b,a)¤¤   PPC_SUBFC(d,a,b)
2ef9e6 #define PPC_SUBC_(d,b,a)¤   PPC_SUBFC_(d,a,b)
3f1960 #define PPC_SUBCO(d,b,a)¤   PPC_SUBFCO(d,a,b)
999bdc #define PPC_SUBCO_(d,b,a)¤  PPC_SUBFCO_(d,a,b)
aa48da /* Messy compare bits omitted */
1fcdda /* Shift and rotate omitted */
96205e /* Branch coding omitted */
90277d #define PPC_CRSET(d)¤   ¤   PPC_CREQV(d,d,d)
729768 #define PPC_CRCLR(d)¤   ¤   PPC_CRXOR(d,d,d)
16b6e7 #define PPC_CRMOVE(d,s)¤¤   PPC_CROR(d,s,s)
29deb1 #define PPC_CRNOT(d,s)¤ ¤   PPC_CRNOR(d,s,s)
46bfcb /* Trap menmonics omitted */
11f290 /* Menmonics for user-accessible SPRs */
b9b957 #define PPC_MFXER(d) ···¤   PPC_MFSPR(d,1)¤ ¤
fefd4e #define PPC_MFLR(d) ····¤   PPC_MFSPR(d,8)¤ ¤
a51a65 #define PPC_MFCTR(d) ···¤   PPC_MFSPR(d,9)¤ ¤
e6724d #define PPC_MTXER(s) ···¤   PPC_MTSPR(s,1)¤ ¤
1fd95a #define PPC_MTLR(s) ····¤   PPC_MTSPR(s,8)¤ ¤
fed17f #define PPC_MTCTR(s) ···¤   PPC_MTSPR(s,9)¤ ¤
8ea9e7 /* Recommended mnemonics */
ed2898 #define PPC_NOP()¤  ¤   PPC_ORI(0,0,0)
243732 #define PPC_LI(d,simm)¤ ¤   PPC_ADDI(d,0,simm)
a1558c #define PPC_LIS(d,simm)¤¤   PPC_ADDIS(d,0,simm)
d7a969 #define PPC_LA(d,a,simm)¤   PPC_ADDI(d,a,simm)
56d580 #define PPC_MR(d,s)¤¤   PPC_OR(d,s,s)
504442 #define PPC_NOT(d,s)¤   ¤   PPC_NOR(d,s,s)
e19ca1 #define PPC_MTCR(s)¤¤   PPC_MTCRF(0xff,s)
0baf5a
bcb0d4 #endif /* Included_bnppcasm_h */
5aaf5a
ef7b8e /* 45678901234567890123456789012345678901234567890123456789012345678901234567*/
--9a0a 0008215d00940100174 Page 1 of bnprime.c
bc38e5 /*
88c6a5 ·* Prime generation using the bignum library and sieving.
7b775e ·*
69fbf7 ·* Written by Colin Plumb
97775e ·*
fac88a ·* $Id: bnprime.c,v 1.8 1997/12/11 23:12:11 lloyd Exp $
61495d ·*/
20e2ff #include "pgpConfig.h"
feaf5a
e79812 #include <stdarg.h>¤/* We just can't live without this... */
efaf5a
8b4408 #ifndef BNDEBUG
b97e00 #define BNDEBUG 0
dc7454 #endif
2363d6 #if BNDEBUG
e7feb2 #include <stdio.h>
f37454 #endif
11af5a
9239fc #include "bn.h"
6421db #include "bnimem.h"
7612ca #include "bnprime.h"
6ae6d6 #include "bnsieve.h"
d5af5a
324724 #include "bnkludge.h"
aba146 #include "pgpDebug.h"
c2af5a
b32264 /* Size of the shuffle table */
f6227b #define SHUFFLE¤256
1b69cf /* Size of the sieve area */
582f20 #define SIEVE 32768u/16
1caf5a
012ae2 /* Confirmation tests. ·The first one *must* be 2 */
7d0aa0 static unsigned const confirm[] = {2, 3, 5, 7, 11, 13, 17};
be0565 #define CONFIRMTESTS (sizeof(confirm)/sizeof(*confirm))
c7af5a
8838e5 /*
0b1094 ·* Helper function that does the slow primality test.
481ec3 ·* bn is the input bignum; a and e are temporary buffers that are
5872c9 ·* allocated by the caller to save overhead.
df775e ·*
b91169 ·* Returns 0 if prime, >0 if not prime, and -1 on error (out of memory).
fab116 ·* If not prime, returns the number of modular exponentiations performed.
cf6538 ·* Calls the given progress function with a '*' for each primality test
2e0bea ·* that is passed.
16775e ·*
b20345 ·* The testing consists of strong pseudoprimality tests, to the bases given
b3bed5 ·* in the confirm[] array above. ·(Also called Miller-Rabin, although that's
597984 ·* not technically correct if we're using fixed bases.) ·Some people worry
1a0db3 ·* that this might not be enough. ·Number theorists may wish to generate
a435a3 ·* primality proofs, but for random inputs, this returns non-primes with
31b678 ·* a probability which is quite negligible, which is good enough.
e5775e ·*
86fede ·* It has been proved (see Carl Pomerance, "On the Distribution of
8d3036 ·* Pseudoprimes", Math. Comp. v.37 (1981) pp. 587-593) that the number of
32e97e ·* pseudoprimes (composite numbers that pass a Fermat test to the base 2)
72bd96 ·* less than x is bounded by:
2742ce ·* exp(ln(x)^(5/14)) <= P_2(x)¤ ### CHECK THIS FORMULA - it looks wrong! ###
1c9b29 ·* P_2(x) <= x * exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))).
3a6135 ·* Thus, the local density of Pseudoprimes near x is at most
e4c53f ·* exp(-1/2 * ln(x) * ln(ln(ln(x))) / ln(ln(x))), and at least
02af72 ·* exp(ln(x)^(5/14) - ln(x)). ·Here are some values of this function
1ed900 ·* for various k-bit numbers x = 2^k:
f7b1a2 ·* Bits¤Density <=¤ Bit equivalent¤ Density >=¤ Bit equivalent
d4bca8 ·* ·128¤3.577869e-07¤   ·21.414396¤ 4.202213e-37¤   ·120.840190
3ad79f ·* ·192¤4.175629e-10¤   ·31.157288¤ 4.936250e-56¤   ·183.724558
d7eef7 ·* ·256 5.804314e-13¤   ·40.647940¤ 4.977813e-75¤   ·246.829095
19e5c7 ·* ·384 1.578039e-18¤   ·59.136573¤ 3.938861e-113¤  ·373.400096
674e78 ·* ·512 5.858255e-24¤   ·77.175803¤ 2.563353e-151¤  ·500.253110
582492 ·* ·768 1.489276e-34¤   112.370944¤ 7.872825e-228¤  ·754.422724
2030bc ·* 1024 6.633188e-45¤   146.757062¤ 1.882404e-304¤  1008.953565
1a775e ·*
82dc2a ·* As you can see, there's quite a bit of slop between these estimates.
--9475 00051c70b3d40100174 Page 2 of bnprime.c
0b8e80 ·* In fact, the density of pseudoprimes is conjectured to be closer to the
707bc2 ·* square of that upper bound. ·E.g. the density of pseudoprimes of size
66897e ·* 256 is around 3 * 10^-27. ·The density of primes is very high, from
7745a3 ·* 0.005636 at 256 bits to 0.001409 at 1024 bits, i.e. ·more than 10^-3.
1d775e ·*
b78e57 ·* For those people used to cryptographic levels of security where the
d1f5ae ·* 56 bits of DES key space is too small because it's exhaustible with
48b195 ·* custom hardware searching engines, note that you are not generating
6949fa ·* 50,000,000 primes per second on each of 56,000 custom hardware chips
a738cc ·* for several hours. ·The chances that another Dinosaur Killer asteroid
abde2f ·* will land today is about 10^-11 or 2^-36, so it would be better to
b50f04 ·* spend your time worrying about *that*. ·Well, okay, there should be
f50937 ·* some derating for the chance that astronomers haven't seen it yet,
1d1478 ·* but I think you get the idea. ·For a good feel about the probability
8d57d8 ·* of various events, I have heard that a good book is by E'mile Borel,
e81a7c ·* "Les Probabilite's et la vie". ·(The 's are accents, not apostrophes.)
aa775e ·*
7d8e80 ·* For more on the subject, try "Finding Four Million Large Random Primes",
302be9 ·* by Ronald Rivest, in Advancess in Cryptology: Proceedings of Crypto
57f702 ·* '90. ·He used a small-divisor test, then a Fermat test to the base 2,
bc1633 ·* and then 8 iterations of a Miller-Rabin test. ·About 718 million random
91f268 ·* 256-bit integers were generated, 43,741,404 passed the small divisor
262550 ·* test, 4,058,000 passed the Fermat test, and all 4,058,000 passed all
e09d55 ·* 8 iterations of the Miller-Rabin test, proving their primality beyond
677b6b ·* most reasonable doubts.
de775e ·*
e5e7bd ·* If the probability of getting a pseudoprime is some small p, then the
6c13d1 ·* probability of not getting it in t trials is (1-p)^t. ·Remember that,
8d5ec0 ·* for small p, (1-p)^(1/p) ~ 1/e, the base of natural logarithms.
b91db8 ·* (This is more commonly expressed as e = lim_{x\to\infty} (1+1/x)^x.)
9df18b ·* Thus, (1-p)^t ~ e^(-p*t) = exp(-p*t). ·So the odds of being able to
f55045 ·* do this many tests without seeing a pseudoprime if you assume that
b56e22 ·* p = 10^-6 (one in a million) is one in 57.86. ·If you assume that
4fe64f ·* p = 2*10^-6, it's one in 3347.6. ·So it's implausible that the density
825953 ·* of pseudoprimes is much more than one millionth the density of primes.
28775e ·*
255ea5 ·* He also gives a theoretical argument that the chance of finding a
6d1474 ·* 256-bit non-prime which satisfies one Fermat test to the base 2 is
db7b87 ·* less than 10^-22. ·The small divisor test improves this number, and
e9b75e ·* if the numbers are 512 bits (as needed for a 1024-bit key) the odds
b32a44 ·* of failure shrink to about 10^-44. ·Thus, he concludes, for practical
45c0e1 ·* purposes *one* Fermat test to the base 2 is sufficient.
40495d ·*/
56beb7 static int
f42884 primeTest(BigNum const *bn, BigNum *e, BigNum *a,
8c71b8 ¤   int (*f)(void *arg, int c), void *arg)
1fbb36 {
a607cb ¤   unsigned i, j;
95d944 ¤   unsigned k, l;
2217e6 ¤   int err;
94af5a
1e24d7 #if BNDEBUG¤/* Debugging */
30d8af ¤   /*
94dca9 ¤   ·* This is debugging code to test the sieving stage.
d5a68c ¤   ·* If the sieving is wrong, it will let past numbers with
a1f84c ¤   ·* small divisors. ·The prime test here will still work, and
9b5dc7 ¤   ·* weed them out, but you'll be doing a lot more slow tests,
0e4eb6 ¤   ·* and presumably excluding from consideration some other numbers
b7a4b5 ¤   ·* which might be prime. ·This check just verifies that none
aa8960 ¤   ·* of the candidates have any small divisors. ·If this
7ea1af ¤   ·* code is enabled and never triggers, you can feel quite
46b693 ¤   ·* confident that the sieving is doing its job.
eca4e3 ¤   ·*/
df73f7 ¤   i = bnLSWord(bn);
10ce3b ¤   if (!(i % 2)) printf("bn div by 2!");
89a0c0 ¤   i = bnModQ(bn, 51051);¤ /* 51051 = 3 * 7 * 11 * 13 * 17 */
d6040e ¤   if (!(i % 3)) printf("bn div by 3!");
c834e9 ¤   if (!(i % 7)) printf("bn div by 7!");
b4ff96 ¤   if (!(i % 11)) printf("bn div by 11!");
7d0db3 ¤   if (!(i % 13)) printf("bn div by 13!");
43e1e8 ¤   if (!(i % 17)) printf("bn div by 17!");
51570d ¤   i = bnModQ(bn, 63365);¤ /* 63365 = 5 * 19 * 23 * 29 */
--88fd 000d4f6551440100174 Page 3 of bnprime.c
faa892 ¤   if (!(i % 5)) printf("bn div by 5!");
ed2f31 ¤   if (!(i % 19)) printf("bn div by 19!");
90c4c8 ¤   if (!(i % 23)) printf("bn div by 23!");
19e64a ¤   if (!(i % 29)) printf("bn div by 29!");
2854b6 ¤   i = bnModQ(bn, 47027);¤ /* 47027 = 31 * 37 * 41 */
1e89cb ¤   if (!(i % 31)) printf("bn div by 31!");
c397b5 ¤   if (!(i % 37)) printf("bn div by 37!");
02ac0a ¤   if (!(i % 41)) printf("bn div by 41!");
3d7454 #endif
caaf5a
b0d8af ¤   /*
534df5 ¤   ·* Now, check that bn is prime. ·If it passes to the base 2,
c4596a ¤   ·* it's prime beyond all reasonable doubt, and everything else
285206 ¤   ·* is just gravy, but it gives people warm fuzzies to do it.
8b9714 ¤   ·*
587c08 ¤   ·* This starts with verifying Euler's criterion for a base of 2.
38a18c ¤   ·* This is the fastest pseudoprimality test that I know of,
a364ce ¤   ·* saving a modular squaring over a Fermat test, as well as
7d2a96 ¤   ·* being stronger. ·7/8 of the time, it's as strong as a strong
63cf16 ¤   ·* pseudoprimality test, too. ·(The exception being when bn ==
273952 ¤   ·* 1 mod 8 and 2 is a quartic residue, i.e. bn is of the form
3618e5 ¤   ·* a^2 + (8*b)^2.) ·The precise series of tricks used here is
d09343 ¤   ·* not documented anywhere, so here's an explanation.
61e71b ¤   ·* Euler's criterion states that if p is prime then a^((p-1)/2)
141293 ¤   ·* is congruent to Jacobi(a,p), modulo p. ·Jacobi(a,p) is
567fc0 ¤   ·* a function which is +1 if a is a square modulo p, and -1 if
22f691 ¤   ·* it is not. ·For a = 2, this is particularly simple. ·It's
c4caa4 ¤   ·* +1 if p == +/-1 (mod 8), and -1 if m == +/-3 (mod 8).
8208d2 ¤   ·* If p == 3 mod 4, then all a strong test does is compute
e11e1b ¤   ·* 2^((p-1)/2). and see if it's +1 or -1. ·(Euler's criterion
eed6a2 ¤   ·* says *which* it should be.) ·If p == 5 (mod 8), then
8a11a6 ¤   ·* 2^((p-1)/2) is -1, so the initial step in a strong test,
2563ca ¤   ·* looking at 2^((p-1)/4), is wasted - you're not going to
572785 ¤   ·* find a +/-1 before then if it *is* prime, and it shouldn't
cac2ad ¤   ·* have either of those values if it isn't. ·So don't bother.
e59714 ¤   ·*
b37404 ¤   ·* The remaining case is p == 1 (mod 8). ·In this case, we
48c3d2 ¤   ·* expect 2^((p-1)/2) == 1 (mod p), so we expect that the
b08e58 ¤   ·* square root of this, 2^((p-1)/4), will be +/-1 (mod p).
9f8dcc ¤   ·* Evaluating this saves us a modular squaring 1/4 of the time.
eca3bb ¤   ·* If it's -1, a strong pseudoprimality test would call p
0794a2 ¤   ·* prime as well. ·Only if the result is +1, indicating that
6b9744 ¤   ·* 2 is not only a quadratic residue, but a quartic one as well,
990994 ¤   ·* does a strong pseudoprimality test verify more things than
da3bfe ¤   ·* this test does. ·Good enough.
6d9714 ¤   ·*
31aaef ¤   ·* We could back that down another step, looking at 2^((p-1)/8)
82ed62 ¤   ·* if there was a cheap way to determine if 2 were expected to
b764c1 ¤   ·* be a quartic residue or not. ·Dirichlet proved that 2 is
192dc3 ¤   ·* a quartic residue iff p is of the form a^2 + (8*b^2).
5654a5 ¤   ·* All primes == 1 (mod 4) can be expressed as a^2 + (2*b)^2,
eeeb6f ¤   ·* but I see no cheap way to evaluate this condition.
36a4e3 ¤   ·*/
3363a5 ¤   if (bnCopy(e, bn) < 0)
c3043c ¤   ¤   return -1;
541819 ¤   (void)bnSubQ(e, 1);
a77b30 ¤   l = bnLSWord(e);
1baf5a
c8dbfb ¤   j = 1;¤ /* Where to start in prime array for strong prime tests */
e7af5a
836435 ¤   if (l & 7) {
a619b7 ¤   ¤   bnRShift(e, 1);
f8252f ¤   ¤   if (bnTwoExpMod(a, e, bn) < 0)
533fd5 ¤   ¤   ¤   return -1;
e67f70 ¤   ¤   if ((l & 7) == 6) {
b98aed ¤   ¤   ¤   /* bn == 7 mod 8, expect +1 */
4cdd5e ¤   ¤   ¤   if (bnBits(a) != 1)
fb2a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
6a1112 ¤   ¤   ¤   k = 1;
b645a6 ¤   ¤   } else {
8e4ba2 ¤   ¤   ¤   /* bn == 3 or 5 mod 8, expect -1 == bn-1 */
d4b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
--abb3 0001608704340100174 Page 4 of bnprime.c
6edd34 ¤   ¤   ¤   ¤   return -1;
9f8b90 ¤   ¤   ¤   if (bnCmp(a, bn) != 0)
082a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
c41112 ¤   ¤   ¤   k = 1;
5d89a3 ¤   ¤   ¤   if (l & 4) {
6b9986 ¤   ¤   ¤   ¤   /* bn == 5 mod 8, make odd for strong tests */
62428c ¤   ¤   ¤   ¤   bnRShift(e, 1);
ebc59f ¤   ¤   ¤   ¤   k = 2;
2ca3a6 ¤   ¤   ¤   }
2b0fe4 ¤   ¤   }
dbf037 ¤   } else {
7ac2cf ¤   ¤   /* bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn */
273c7a ¤   ¤   bnRShift(e, 2);
20252f ¤   ¤   if (bnTwoExpMod(a, e, bn) < 0)
283fd5 ¤   ¤   ¤   return -1;
74d8ea ¤   ¤   if (bnBits(a) == 1) {
ab2532 ¤   ¤   ¤   j = 0;¤ /* Re-do strong prime test to base 2 */
7745a6 ¤   ¤   } else {
07b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
71dd34 ¤   ¤   ¤   ¤   return -1;
ff8b90 ¤   ¤   ¤   if (bnCmp(a, bn) != 0)
3f2a41 ¤   ¤   ¤   ¤   return 1;¤  /* Not prime */
f60fe4 ¤   ¤   }
8f6229 ¤   ¤   k = 2 + bnMakeOdd(e);
339371 ¤   }
04e38b ¤   /* It's prime! ·Now go on to confirmation tests */
e5af5a
f6d8af ¤   /*
e3426a ¤   ·* Now, e = (bn-1)/2^k is odd. ·k >= 1, and has a given value
15057a ¤   ·* with probability 2^-k, so its expected value is 2.
d8fabd ¤   ·* j = 1 in the usual case when the previous test was as good as
4b8f96 ¤   ·* a strong prime test, but 1/8 of the time, j = 0 because
335e72 ¤   ·* the strong prime test to the base 2 needs to be re-done.
44a4e3 ¤   ·*/
a6a494 ¤   for (i = j; i < CONFIRMTESTS; i++) {
1dea64 ¤   ¤   if (f && (err = f(arg, '*')) < 0)
4eb32f ¤   ¤   ¤   return err;
6d461b ¤   ¤   (void)bnSetQ(a, confirm[i]);
f18380 ¤   ¤   if (bnExpMod(a, a, e, bn) < 0)
033fd5 ¤   ¤   ¤   return -1;
550344 ¤   ¤   if (bnBits(a) == 1)
8a8e3f ¤   ¤   ¤   continue;¤  /* Passed this test */
aaaf5a
f8c430 ¤   ¤   l = k;
04c0ad ¤   ¤   for (;;) {
a6b1ac ¤   ¤   ¤   if (bnAddQ(a, 1) < 0)
51dd34 ¤   ¤   ¤   ¤   return -1;
c676d7 ¤   ¤   ¤   if (bnCmp(a, bn) == 0)¤ /* Was result bn-1? */
064924 ¤   ¤   ¤   ¤   break;¤ /* Prime */
c4e626 ¤   ¤   ¤   if (!--l)¤  /* Reached end, not -1? luck? */
f729d7 ¤   ¤   ¤   ¤   return i+2-j;¤  /* Failed, not prime */
6f9599 ¤   ¤   ¤   /* This portion is executed, on average, once. */
4fae08 ¤   ¤   ¤   (void)bnSubQ(a, 1);¤/* Put a back where it was. */
7e5f02 ¤   ¤   ¤   if (bnSquare(a, a) < 0 || bnMod(a, a, bn) < 0)
9fdd34 ¤   ¤   ¤   ¤   return -1;
dcae1a ¤   ¤   ¤   if (bnBits(a) == 1)
0b29d7 ¤   ¤   ¤   ¤   return i+2-j;¤  /* Failed, not prime */
f00fe4 ¤   ¤   }
3ec50e ¤   ¤   /* It worked (to the base confirm[i]) */
d19371 ¤   }
c467c5 ¤
d83627 ¤   /* Yes, we've decided that it's prime. */
30d68a ¤   if (f && (err = f(arg, '*')) < 0)
a4c9db ¤   ¤   return err;
e16c87 ¤   return 0;¤  /* Prime! */
8cefe6 }
e9af5a
2638e5 /*
58adb9 ·* Add x*y to bn, which is usually (but not always) < 65536.
873e74 ·* Do it in a simple linear manner.
5a495d ·*/
16beb7 static int
--e743 00020eb72ff40100174 Page 5 of bnprime.c
61484b bnAddMult(BigNum *bn, unsigned x, unsigned y)
ccbb36 {
e23cfe ¤   unsigned long z = (unsigned long)x * y;
fcaf5a
415a22 ¤   while (z > 65535) {
863292 ¤   ¤   if (bnAddQ(bn, 65535) < 0)
8e3fd5 ¤   ¤   ¤   return -1;
a56097 ¤   ¤   z -= 65535;
7a9371 ¤   }
b28ee8 ¤   return bnAddQ(bn, (unsigned)z);
c4efe6 }
28af5a
45beb7 static int
717015 bnSubMult(BigNum *bn, unsigned x, unsigned y)
80bb36 {
5d3cfe ¤   unsigned long z = (unsigned long)x * y;
33af5a
f55a22 ¤   while (z > 65535) {
ee03d7 ¤   ¤   if (bnSubQ(bn, 65535) < 0)
ef3fd5 ¤   ¤   ¤   return -1;
9b6097 ¤   ¤   z -= 65535;
839371 ¤   }
d1963c ¤   return bnSubQ(bn, (unsigned)z);
6cefe6 }
64af5a
5438e5 /*
66e8d2 ·* Modifies the bignum to return a nearby (slightly larger) number which
e327bc ·* is a probable prime. ·Returns >=0 on success or -1 on failure (out of
69ae3f ·* memory). ·The return value is the number of unsuccessful modular
857bb1 ·* exponentiations performed. ·This never gives up searching.
d2775e ·*
ab22cc ·* All other arguments are optional. ·They may be NULL. ·They are:
12775e ·*
a4c958 ·* unsigned (*randfunc)(unsigned limit)
fd78b3 ·* For better distributed numbers, supply a non-null pointer to a
6f81ab ·* function which returns a random x, 0 <= x < limit. ·(It may make it
41a1ed ·* simpler to know that 0 < limit <= SHUFFLE, so you need at most a byte.)
1e3cdd ·* The program generates a large window of sieve data and then does
f10168 ·* pseudoprimality tests on the data. ·If a randfunc function is supplied,
6a6b25 ·* the candidates which survive sieving are shuffled with a window of
356ee1 ·* size SHUFFLE before testing to increase the uniformity of the prime
5627e4 ·* selection. ·This isn't perfect, but it reduces the correlation between
cc0439 ·* the size of the prime-free gap before a prime and the probability
174559 ·* that that prime will be found by a sequential search.
f5775e ·*
a35fad ·* If randfunc is NULL, sequential search is used. ·If you want sequential
4592fb ·* search, note that the search begins with the given number; if you're
f30a6a ·* trying to generate consecutive primes, you must increment the previous
0db0fc ·* one by two before calling this again.
cb775e ·*
4496a2 ·* int (*f)(void *arg, int c), void *arg
a2e0be ·* The function f argument, if non-NULL, is called with progress indicator
f6e614 ·* characters for printing. ·A dot (.) is written every time a primality test
28b1d5 ·* is failed, a star (*) every time one is passed, and a slash (/) in the
7e9a53 ·* (very rare) case that the sieve was emptied without finding a prime
456296 ·* and is being refilled. ·f is also passed the void *arg argument for
54b152 ·* private context storage. ·If f returns < 0, the test aborts and returns
f9db95 ·* that value immediately. ·(bn is set to the last value tested, so you
6ae853 ·* can increment bn and continue.)
d2775e ·*
3d1d61 ·* The "exponent" argument, and following unsigned numbers, are exponents
c04407 ·* for which an inverse is desired, modulo p. ·For a d to exist such that
b5700a ·* (x^e)^d == x (mod p), then d*e == 1 (mod p-1), so gcd(e,p-1) must be 1.
134ba9 ·* The prime returned is constrained to not be congruent to 1 modulo
c79034 ·* any of the zero-terminated list of 16-bit numbers. ·Note that this list
978b1f ·* should contain all the small prime factors of e. ·(You'll have to test
286b16 ·* for large prime factors of e elsewhere, but the chances of needing to
c33819 ·* generate another prime are low.)
cb775e ·*
a5b448 ·* The list is terminated by a 0, and may be empty.
8d495d ·*/
204d2f int
--296a 00021d036ca40100174 Page 6 of bnprime.c
e6fe27 bnPrimeGen(BigNum *bn, unsigned (*randfunc)(unsigned),
15a0b2 ·········int (*f)(void *arg, int c), void *arg, unsigned exponent, ...)
d7bb36 {
ea13a5 ¤   int retval;
1ade1b ¤   int modexps = 0;
d396a2 ¤   unsigned short offsets[SHUFFLE];
b607cb ¤   unsigned i, j;
b60188 ¤   unsigned p, q, prev;
c03d5b ¤   BigNum a, e;
2b306a #ifdef MSDOS
a3d052 ¤   unsigned char *sieve;
a2db21 #else
f40aa9 ¤   unsigned char sieve[SIEVE];
f97454 #endif
a6af5a
4c306a #ifdef MSDOS
ecaf13 ¤   sieve = bniMemAlloc(SIEVE);
b1ca71 ¤   if (!sieve)
60043c ¤   ¤   return -1;
857454 #endif
b7ef97 ¤   PGPBoolean¤ ¤   isSecure¤   = TRUE;
8e9353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
88af5a
308337 ¤   bnBegin(&a, mgr, isSecure);
4fde31 ¤   bnBegin(&e, mgr, isSecure);
80af5a
59ddae #if 0¤  /* Self-test (not used for production) */
bfbb36 {
5f15c9 ¤   BigNum t;
ad2563 ¤   static unsigned char const prime1[] = {5};
53e2a6 ¤   static unsigned char const prime2[] = {7};
272f1f ¤   static unsigned char const prime3[] = {11};
79e193 ¤   static unsigned char const prime4[] = {1, 1}; /* 257 */
bc4639 ¤   static unsigned char const prime5[] = {0xFF, 0xF1}; /* 65521 */
0147e1 ¤   static unsigned char const prime6[] = {1, 0, 1}; /* 65537 */
80cb59 ¤   static unsigned char const prime7[] = {1, 0, 3}; /* 65539 */
91bbb1 ¤   /* A small prime: 1234567891 */
eed72a ¤   static unsigned char const prime8[] = {0x49, 0x96, 0x02, 0xD3};
9c7861 ¤   /* A slightly larger prime: 12345678901234567891 */
cf23d4 ¤   static unsigned char const prime9[] = {
4c3cb1 ¤   ¤   0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD3 };
bfd8af ¤   /*
faf021 ¤   ·* No, 123456789012345678901234567891 isn't prime; it's just a
397365 ¤   ·* lucky, easy-to-remember conicidence. ·(You have to go to
1d2724 ¤   ·* ...4567907 for a prime.)
d0a4e3 ¤   ·*/
36dc64 ¤   static struct {
07891e ¤   ¤   unsigned char const *prime;
b0f395 ¤   ¤   unsigned size;
c9abd0 ¤   } const primelist[] = {
11b803 ¤   ¤   { prime1, sizeof(prime1) },
d0edca ¤   ¤   { prime2, sizeof(prime2) },
3ade8d ¤   ¤   { prime3, sizeof(prime3) },
de4658 ¤   ¤   { prime4, sizeof(prime4) },
9d751f ¤   ¤   { prime5, sizeof(prime5) },
3f20d6 ¤   ¤   { prime6, sizeof(prime6) },
fa1391 ¤   ¤   { prime7, sizeof(prime7) },
dd196d ¤   ¤   { prime8, sizeof(prime8) },
9636a2 ¤   ¤   { prime9, sizeof(prime9) } };
c2af5a
0d0e6a ¤   bnBegin(&t);
6faf5a
c1576c ¤   for (i = 0; i < sizeof(primelist)/sizeof(primelist[0]); i++) {
397188 ¤   ¤   ¤   bnInsertBytes(&t, primelist[i].prime, 0,
781ecb ¤   ¤   ¤   ¤   ······primelist[i].size);
a28420 ¤   ¤   ¤   bnCopy(&e, &t);
f0f3c9 ¤   ¤   ¤   (void)bnSubQ(&e, 1);
2ca3e7 ¤   ¤   ¤   bnTwoExpMod(&a, &e, &t);
5683b7 ¤   ¤   ¤   p = bnBits(&a);
7f326b ¤   ¤   ¤   if (p != 1) {
33bbe4 ¤   ¤   ¤   ¤   printf(
2145a8 ¤   ¤   ¤   "Bug: Fermat(2) %u-bit output (1 expected)\n", p);
--146c 00071b5718540100174 Page 7 of bnprime.c
4ef189 ¤   ¤   ¤   ¤   fputs("Prime = 0x", stdout);
b96f8d ¤   ¤   ¤   ¤   for (j = 0; j < primelist[i].size; j++)
b2b70f ¤   ¤   ¤   ¤   ¤   printf("%02X", primelist[i].prime[j]);
ad8445 ¤   ¤   ¤   ¤   putchar('\n');
d7a3a6 ¤   ¤   ¤   }
dfd9f3 ¤   ¤   ¤   bnSetQ(&a, 3);
6e9b22 ¤   ¤   ¤   bnExpMod(&a, &a, &e, &t);
2783b7 ¤   ¤   ¤   p = bnBits(&a);
fe326b ¤   ¤   ¤   if (p != 1) {
24bbe4 ¤   ¤   ¤   ¤   printf(
5fef60 ¤   ¤   ¤   "Bug: Fermat(3) %u-bit output (1 expected)\n", p);
faf189 ¤   ¤   ¤   ¤   fputs("Prime = 0x", stdout);
686f8d ¤   ¤   ¤   ¤   for (j = 0; j < primelist[i].size; j++)
b5b70f ¤   ¤   ¤   ¤   ¤   printf("%02X", primelist[i].prime[j]);
fa8445 ¤   ¤   ¤   ¤   putchar('\n');
dda3a6 ¤   ¤   ¤   }
050fe4 ¤   ¤   }
cfaf5a
1f904b ¤   bnEnd(&t);
67efe6 }
597454 #endif
17af5a
6b9a0e ¤   /* First, make sure that bn is odd. */
7f4b15 ¤   if ((bnLSWord(bn) & 1) == 0)
9a7942 ¤   ¤   (void)bnAddQ(bn, 1);
baaf5a
1a165f retry:
a340f7 ¤   /* Then build a sieve starting at bn. */
fff7c7 ¤   sieveBuild(sieve, SIEVE, bn, 2, 0);
fbaf5a
84f5bc ¤   /* Do the extra exponent sieving */
968ecf ¤   if (exponent) {
556d53 ¤   ¤   va_list ap;
8542bb ¤   ¤   unsigned t = exponent;
7daf5a
1b09d6 ¤   ¤   va_start(ap, exponent);
09af5a
5d4392 ¤   ¤   do {
4cd07e ¤   ¤   ¤   /* The exponent had better be odd! */
c45598 ¤   ¤   ¤   pgpAssert(t & 1);
ffaf5a
985975 ¤   ¤   ¤   i = bnModQ(bn, t);
075e48 ¤   ¤   ¤   /* Find 1-i */
79ee47 ¤   ¤   ¤   if (i == 0)
091d40 ¤   ¤   ¤   ¤   i = 1;
836851 ¤   ¤   ¤   else if (--i)
f48f70 ¤   ¤   ¤   ¤   i = t - i;
cbaf5a
81ee6a ¤   ¤   ¤   /* Divide by 2, modulo the exponent */
a31c8a ¤   ¤   ¤   i = (i & 1) ? i/2 + t/2 + 1 : i/2;
9caf5a
4502dc ¤   ¤   ¤   /* Remove all following multiples from the sieve. */
45033e ¤   ¤   ¤   sieveSingle(sieve, SIEVE, i, t);
86af5a
9c1b05 ¤   ¤   ¤   /* Get the next exponent value */
389f0e ¤   ¤   ¤   t = va_arg(ap, unsigned);
cb6d14 ¤   ¤   } while (t);
f6af5a
a9caaf ¤   ¤   va_end(ap);
199371 ¤   }
78af5a
5bdde5 ¤   /* Fill up the offsets array with the first SHUFFLE candidates */
127010 ¤   i = p = 0;
11ce74 ¤   /* Get first prime */
6e8354 ¤   if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
ea55ad ¤   ¤   offsets[i++] = p;
6c214b ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
199371 ¤   }
13d8af ¤   /*
e3d081 ¤   ·* Okay, from this point onwards, p is always the next entry
2741f4 ¤   ·* from the sieve, that has not been added to the shuffle table,
71c8ff ¤   ·* and is 0 iff the sieve has been exhausted.
--6b4f 0003f9d4a2340100174 Page 8 of bnprime.c
9a9714 ¤   ·*
dacf92 ¤   ·* If we want to shuffle, then fill the shuffle table until the
5f9fa6 ¤   ·* sieve is exhausted or the table is full.
e9a4e3 ¤   ·*/
64a8a0 ¤   if (randfunc && p) {
5b4392 ¤   ¤   do {
bcdcf9 ¤   ¤   ¤   offsets[i++] = p;
57188e ¤   ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
a20d20 ¤   ¤   } while (p && i < SHUFFLE);
bf9371 ¤   }
b3af5a
b4cfa1 ¤   /* Choose a random candidate for experimentation */
552263 ¤   prev = 0;
f43681 ¤   while (i) {
634f67 ¤   ¤   /* Pick a random entry from the shuffle table */
64b752 ¤   ¤   j = randfunc ? randfunc(i) : 0;
863974 ¤   ¤   q = offsets[j];¤/* The entry to use */
e9af5a
250afc ¤   ¤   /* Replace the entry with some more data, if possible */
3c4400 ¤   ¤   if (p) {
854164 ¤   ¤   ¤   offsets[j] = p;
e5188e ¤   ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
9c45a6 ¤   ¤   } else {
606add ¤   ¤   ¤   offsets[j] = offsets[--i];
50cdc2 ¤   ¤   ¤   offsets[i] = 0;
960fe4 ¤   ¤   }
37af5a
5d0d0e ¤   ¤   /* Adjust bn to have the right value */
5b8251 ¤   ¤   if ((q > prev ? bnAddMult(bn, q-prev, 2)
465f47 ¤   ¤   ··············: bnSubMult(bn, prev-q, 2)) < 0)
0a3507 ¤   ¤   ¤   goto failed;
bffb7c ¤   ¤   prev = q;
54af5a
442840 ¤   ¤   /* Now do the Fermat tests */
2d1f37 ¤   ¤   retval = primeTest(bn, &e, &a, f, arg);
5ad32d ¤   ¤   if (retval <= 0)
168a32 ¤   ¤   ¤   goto done;¤ /* Success or error */
3412eb ¤   ¤   modexps += retval;
dd3f5d ¤   ¤   if (f && (retval = f(arg, '.')) < 0)
1b1dc4 ¤   ¤   ¤   goto done;
549371 ¤   }
94af5a
16712e ¤   /* Ran out of sieve space - increase bn and keep trying. */
fe2be1 ¤   if (bnAddMult(bn, SIEVE*8-prev, 2) < 0)
0d84d6 ¤   ¤   goto failed;
2315c2 ¤   if (f && (retval = f(arg, '/')) < 0)
ad262d ¤   ¤   goto done;
4c763e ¤   goto retry;
ddaf5a
13f4b6 failed:
d569ef ¤   retval = -1;
24b38c done:
6d4f51 ¤   bnEnd(&e);
163dbd ¤   bnEnd(&a);
5feaad ¤   bniMemWipe(offsets, sizeof(offsets));
89306a #ifdef MSDOS
29ddc8 ¤   bniMemFree(sieve, SIEVE);
1fdb21 #else
cadd42 ¤   bniMemWipe(sieve, sizeof(sieve));
4a7454 #endif
47af5a
e44aae ¤   return retval < 0 ? retval : modexps + CONFIRMTESTS;
d5efe6 }
46af5a
b038e5 /*
1d9726 ·* Similar, but searches forward from the given starting value in steps of
584937 ·* "step" rather than 1. ·The step size must be even, and bn must be odd.
7d5510 ·* Among other possibilities, this can be used to generate "strong"
2771b0 ·* primes, where p-1 has a large prime factor.
77495d ·*/
9f4d2f int
3f9bd3 bnPrimeGenStrong(BigNum *bn, BigNum const *step,
--e25b 00065bffea640100174 Page 9 of bnprime.c
5871b8 ¤   int (*f)(void *arg, int c), void *arg)
4abb36 {
4713a5 ¤   int retval;
e1d823 ¤   unsigned p, prev;
373d5b ¤   BigNum a, e;
e4de1b ¤   int modexps = 0;
0f306a #ifdef MSDOS
13d052 ¤   unsigned char *sieve;
4ddb21 #else
400aa9 ¤   unsigned char sieve[SIEVE];
917454 #endif
481c7f ¤   PGPBoolean¤ ¤   isSecure¤   = bn->isSecure;
fe9353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
a1af5a
40306a #ifdef MSDOS
2aaf13 ¤   sieve = bniMemAlloc(SIEVE);
65ca71 ¤   if (!sieve)
db043c ¤   ¤   return -1;
9d7454 #endif
afaf5a
6af5e2 ¤   /* Step must be even and bn must be odd */
9761a8 ¤   pgpAssert((bnLSWord(step) & 1) == 0);
795e82 ¤   pgpAssert((bnLSWord(bn) & 1) == 1);
e8af5a
9c8337 ¤   bnBegin(&a, mgr, isSecure);
e3de31 ¤   bnBegin(&e, mgr, isSecure);
34af5a
6e220e ¤   for (;;) {
65de7c ¤   ¤   if (sieveBuildBig(sieve, SIEVE, bn, step, 0) < 0)
e93507 ¤   ¤   ¤   goto failed;
ccaf5a
36e284 ¤   ¤   p = prev = 0;
b490d8 ¤   ¤   if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
dcf603 ¤   ¤   ¤   do {
94980e ¤   ¤   ¤   ¤   /*
c7cb9f ¤   ¤   ¤   ¤   ·* Adjust bn to have the right value,
163e3c ¤   ¤   ¤   ¤   ·* adding (p-prev) * 2*step.
8d1020 ¤   ¤   ¤   ¤   ·*/
fb6407 ¤   ¤   ¤   ¤   pgpAssert(p >= prev);
316094 ¤   ¤   ¤   ¤   /* Compute delta into a */
befc84 ¤   ¤   ¤   ¤   if (bnMulQ(&a, step, p-prev) < 0)
c7ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
7091a0 ¤   ¤   ¤   ¤   if (bnAdd(bn, &a) < 0)
8cba0c ¤   ¤   ¤   ¤   ¤   goto failed;
5c5c8f ¤   ¤   ¤   ¤   prev = p;
7baf5a
d1dcda ¤   ¤   ¤   ¤   retval = primeTest(bn, &e, &a, f, arg);
fb5c26 ¤   ¤   ¤   ¤   if (retval <= 0)
b0f40b ¤   ¤   ¤   ¤   ¤   goto done;¤ /* Success! */
de8abc ¤   ¤   ¤   ¤   modexps += retval;
213edb ¤   ¤   ¤   ¤   if (f && (retval = f(arg, '.')) < 0)
d0eb0d ¤   ¤   ¤   ¤   ¤   goto done;
21af5a
fd5f0e ¤   ¤   ¤   ¤   /* And try again */
c857b0 ¤   ¤   ¤   ¤   p = sieveSearch(sieve, SIEVE, p);
f4ae29 ¤   ¤   ¤   } while (p);
ff0fe4 ¤   ¤   }
a6af5a
284c40 ¤   ¤   /* Ran out of sieve space - increase bn and keep trying. */
2dabaa #if SIEVE*8 == 65536
718978 ¤   ¤   /* Corner case that will never actually happen */
0d310f ¤   ¤   if (!prev) {
622b26 ¤   ¤   ¤   if (bnAdd(bn, step) < 0)
5e015a ¤   ¤   ¤   ¤   goto failed;
867d29 ¤   ¤   ¤   p = 65535;
bc45a6 ¤   ¤   } else {
29ba9b ¤   ¤   ¤   p = (unsigned)(SIEVE*8 - prev);
240fe4 ¤   ¤   }
bbdb21 #else
3db054 ¤   ¤   p = SIEVE*8 - prev;
547454 #endif
65b158 ¤   ¤   if (bnMulQ(&a, step, p) < 0 || bnAdd(bn, &a) < 0)
--b71a 001e3441f2340100174 Page 10 of bnprime.c
e33507 ¤   ¤   ¤   goto failed;
03137a ¤   ¤   if (f && (retval = f(arg, '/')) < 0)
421dc4 ¤   ¤   ¤   goto done;
92d6a0 ¤   } /* for (;;) */
f9af5a
bdf4b6 failed:
1969ef ¤   retval = -1;
a4af5a
45b38c done:
a7af5a
d94f51 ¤   bnEnd(&e);
623dbd ¤   bnEnd(&a);
ab306a #ifdef MSDOS
59ddc8 ¤   bniMemFree(sieve, SIEVE);
16db21 #else
21dd42 ¤   bniMemWipe(sieve, sizeof(sieve));
c17454 #endif
164aae ¤   return retval < 0 ? retval : modexps + CONFIRMTESTS;
e3efe6 }
--df2a 00169b859bc40100175 Page 1 of bnprime.h
bc38e5 /*
d0f74e ·* $Id: bnprime.h,v 1.6 1997/05/13 01:18:53 mhw Exp $
85495d ·*/
c1af5a
b3b21d #ifndef Included_bnprime_h
72d66b #define Included_bnprime_h
e1af5a
ffc5d5 #include "pgpBase.h"
bbaf5a
b299c6 PGP_BEGIN_C_DECLARATIONS
89af5a
68bdbd #include "pgpBigNumOpaqueStructs.h"
2aaf5a
17e103 /* Generate a prime >= bn. leaving the result in bn. */
766c8e int bnPrimeGen(BigNum *bn, unsigned (*randnum)(unsigned),
61b3a9 ¤   ·······int (*f)(void *arg, int c), void *arg, unsigned exponent, ...);
4eaf5a
0838e5 /*
4943bf ·* Generate a prime of the form bn + k*step. ·Step must be even and
d6ad59 ·* bn must be odd.
10495d ·*/
a6765b int bnPrimeGenStrong(BigNum *bn, BigNum const *step,
ba029a ¤   ¤   ·····int (*f)(void *arg, int c), void *arg);
42af5a
ea1254 PGP_END_C_DECLARATIONS
b4af5a
69be7e #endif /* Included_bnprime_h */
--3f41 0002526509840100176 Page 1 of bnprint.c
bc38e5 /*
069141 ·* bnprint.c - Print a bignum, for debugging purposes.
22775e ·*
3568c2 ·* Written by Colin Plumb.
90775e ·*
4cfeae ·* $Id: bnprint.c,v 1.7 1998/04/30 00:31:55 heller Exp $
5a495d ·*/
9ce2ff #include "pgpConfig.h"
3d0d08 #include "pgpMem.h"
64af5a
3d38e5 /*
3116cf ·* Some compilers complain about #if FOO if FOO isn't defined,
2c59aa ·* so do the ANSI-mandated thing explicitly...
40495d ·*/
78b552 #ifndef NO_STRING_H
a137dd #define NO_STRING_H 0
1e7454 #endif
368537 #ifndef HAVE_STRINGS_H
92025c #define HAVE_STRINGS_H 0
117454 #endif
9aaf5a
fffeb2 #include <stdio.h>
e1af5a
b67668 #if !NO_STRING_H
23324c #include <string.h>
65a752 #elif HAVE_STRINGS_H
32f7c3 #include <strings.h>
7a7454 #endif
64af5a
3839fc #include "bn.h"
76a1b3 #include "bnprint.h"
0aaf5a
4d4724 #include "bnkludge.h"
05af5a
944d2f int
3da942 bnPrint(FILE *f, char const *prefix, BigNum const *bn,
71298f ¤   char const *suffix)
47bb36 {
43cc97 ¤   unsigned char temp[32];¤/* How much to print on one line */
1ac6b5 ¤   unsigned len;
d7800d ¤   size_t i;
bcaf5a
9e06b8 ¤   if (prefix && fputs(prefix, f) < 0)
f88bf8 ¤   ¤   return EOF;
76af5a
4e116f ¤   len = (bnBits(bn) + 7)/ 8;
3faf5a
eda837 ¤   if (!len) {
39c6fb ¤   ¤   if (putc('0', f) < 0)
b2f10c ¤   ¤   ¤   return EOF;
dcf037 ¤   } else {
6e782a ¤   ¤   while (len > sizeof(temp)) {
841397 ¤   ¤   ¤   len -= sizeof(temp);
ed2208 ¤   ¤   ¤   bnExtractBigBytes(bn, temp, len, sizeof(temp));
ed82ca ¤   ¤   ¤   for (i = 0; i < sizeof(temp); i++)
3b8a1c ¤   ¤   ¤   ¤   if (fprintf(f, "%02X", temp[i]) < 0)
0baa37 ¤   ¤   ¤   ¤   ¤   return EOF;
f62384 ¤   ¤   ¤   if (putc('\\', f) < 0 || putc('\n', f) < 0)
640769 ¤   ¤   ¤   ¤   return EOF;
0070e0 ¤   ¤   ¤   if (prefix) {
cda28c ¤   ¤   ¤   ¤   i = strlen(prefix);
1f40b7 ¤   ¤   ¤   ¤   while (i--)
9237b6 ¤   ¤   ¤   ¤   ¤   if (putc(' ', f) < 0)
1d21cb ¤   ¤   ¤   ¤   ¤   ¤   return EOF;
f1a3a6 ¤   ¤   ¤   }
520fe4 ¤   ¤   }
391dbd ¤   ¤   bnExtractBigBytes(bn, temp, 0, len);
fece49 ¤   ¤   for (i = 0; i < len; i++)
6bd907 ¤   ¤   ¤   if (fprintf(f, "%02X", temp[i]) < 0)
5f0769 ¤   ¤   ¤   ¤   return EOF;
109371 ¤   }
25334d ¤   return suffix ?¤fputs(suffix, f) : 0;
--1ce7 00116e494d440100176 Page 2 of bnprint.c
7aefe6 }
46af5a
8eaf5a
d74d2f int
c3b541 bnPrint10(FILE *f, char const *prefix, BigNum const *bn,
f2298f ¤   char const *suffix)
a0bb36 {
0c88c0 ¤   BigNum pbig, pbig1;
a8e3c2 ¤   BigNum ten, zero, rem;
42851a ¤   char buf[3000];¤¤   ¤   /* up to 9000 bits */
956639 ¤   int bufi = sizeof(buf)-1;
f0c7a1 ¤   int n;
3aaf5a
dbf665 ¤   buf[bufi] = '\0';
c26bfb ¤   bnBegin (&pbig, bn->mgr, bn->isSecure );
0df983 ¤   bnBegin (&pbig1, bn->mgr, bn->isSecure );
1aee35 ¤   bnBegin (&rem, bn->mgr, bn->isSecure );
c867c5 ¤
6e762c ¤   bnBegin (&ten, bn->mgr, bn->isSecure );
df263c ¤   bnAddQ (&ten, 10);
af4b59 ¤   bnBegin (&zero, bn->mgr, bn->isSecure );
5aaf5a
5a7391 ¤   bnCopy (&pbig, bn);
1c67c5 ¤
c46ea8 ¤   while (bnCmp (&pbig, &zero) != 0) {
b5398e ¤   ¤   bnDivMod (&pbig1, &rem, &pbig, &ten);
06942d ¤   ¤   bnCopy (&pbig, &pbig1);
e79ae8 ¤   ¤   n = bnLSWord (&rem);
3d84ce ¤   ¤   buf[--bufi] = n + '0';
f19371 ¤   }
7eaf5a
7f9eea ¤   bnEnd (&pbig);
495ebe ¤   bnEnd (&pbig1);
70e910 ¤   bnEnd (&rem);
21af5a
9a06b8 ¤   if (prefix && fputs(prefix, f) < 0)
068bf8 ¤   ¤   return EOF;
dcaf5a
fe4839 ¤   fputs (buf+bufi, f);
d67c5f ¤   pgpClearMemory (buf, sizeof(buf));
25af5a
53334d ¤   return suffix ?¤fputs(suffix, f) : 0;
16efe6 }
--6a81 0014ad9564940100177 Page 1 of bnprint.h
bc38e5 /*
1c3324 ·* $Id: bnprint.h,v 1.6 1997/05/13 01:18:54 mhw Exp $
a2495d ·*/
fbaf5a
4770cb #ifndef Included_bnprint_h
a214bd #define Included_bnprint_h
78af5a
0fc5d5 #include "pgpBase.h"
67af5a
c899c6 PGP_BEGIN_C_DECLARATIONS
84af5a
dbfeb2 #include <stdio.h>
52adb8 #include "pgpOpaqueStructs.h"
c9af5a
fd72c7 /* Print in base 16 */
66da2a int bnPrint(FILE *f, char const *prefix, BigNum const *bn,
6f7cf6 ¤   char const *suffix);
c9af5a
86495f /* Print in base 10 */
e05fc8 int bnPrint10(FILE *f, char const *prefix, BigNum const *bn,
827cf6 ¤   char const *suffix);
39af5a
661254 PGP_END_C_DECLARATIONS
52af5a
061eb2 #endif /* Included_bnprint_h */
4aaf5a
--ee32 000cf43c24f40100178 Page 1 of bnsieve.c
bc38e5 /*
26e421 ·* bnsieve.c - Trial division for prime finding.
32775e ·*
f4fbf7 ·* Written by Colin Plumb
21775e ·*
15ee98 ·* $Id: bnsieve.c,v 1.7 1997/05/13 00:23:11 lloyd Exp $
7d775e ·*
803a3d ·* Finding primes:
f988ae ·* - Sieve 1 to find the small primes for
7e3b1d ·* - Sieve 2 to find the candidate large primes, then
268dc3 ·* - Pseudo-primality test.
f0775e ·*
bfa64e ·* An important question is how much trial division by small primes
00b59d ·* should we do? ·The answer is a LOT. ·Even a heavily optimized
88c733 ·* Fermat test to the base 2 (the simplest pseudoprimality test)
6972ad ·* is much more expensive than a division.
f0775e ·*
40a007 ·* For an prime of n k-bit words, a Fermat test to the base 2 requires n*k
88d9a2 ·* modular squarings, each of which involves n*(n+1)/2 signle-word multiplies
3a6539 ·* in the squaring and n*(n+1) multiplies in the modular reduction, plus
fff846 ·* some overhead to get into and out of Montgomery form. ·This is a total
ea1f34 ·* of 3/2 * k * n^2 * (n+1). ·Equivalently, if n*k = b bits, it's
ece7a6 ·* 3/2 * (b/k+1) * b^2 / k.
ce775e ·*
757cde ·* A modulo operation requires n single-word divides. ·Let's assume that
996aed ·* a divide is 4 times the cost of a multiply. ·That's 4*n multiplies.
b53de3 ·* However, you only have to do the division once for your entire
5a55fe ·* search. ·It can be amortized over 10-15 primes. ·So it's
ccb35d ·* really more like n/3 multiplies. ·This is b/3k.
b1775e ·*
16bb2d ·* Now, let's suppose you have a candidate prime t. ·Your options
76189d ·* are to a) do trial division by a prime p, then do a Fermat test,
d0f5fa ·* or to do the Fermat test directly. ·Doing the trial division
a64176 ·* costs b/3k multiplies, but a certain fraction of the time (1/p), it
2039d9 ·* saves you 3/2 b^3 / k^2 multiplies. ·Thus, it's worth it doing the
3505b6 ·* division as long as b/3k < 3/2 * (b/k+1) * b^2 / k / p.
f3fb58 ·* I.e. p < 9/2 * (b/k + 1) * b = 9/2 * (b^2/k + b).
36c722 ·* E.g. for k=16 and b=256, p < 9/2 * 17 * 256 = 19584.
4cda2d ·* Solving for k=16 and k=32 at a few interesting value of b:
b7775e ·*
bf1511 ·* k=16, b=256: p < ·19584¤ k=32, b=256: p < ·10368
08834e ·* k=16, b=384: p < ·43200¤ k=32, b=384; p < ·22464
b35e49 ·* k=16, b=512: p < ·76032¤ k=32, b=512: p < ·39168
f300ed ·* k=16, b=640: p < 118080¤ k=32, b=640: p < ·60480
92775e ·*
2b1588 ·* H'm... before using the highly-optimized Fermat test, I got much larger
2f8fad ·* numbers (64K to 256K), and designed the sieve for that. ·Maybe it needs
5b0cd6 ·* to be reduced. ·It *is* true that the desirable sieve size increases
2bb078 ·* rapidly with increasing prime size, and it's the larger primes that are
145840 ·* worrisome in any case. ·I'll leave it as is (64K) for now while I
91c719 ·* think about it.
e5775e ·*
077796 ·* A bit of tweaking the division (we can compute a reciprocal and do
c5e28d ·* multiplies instead, turning 4*n into 4 + 2*n) would increase all the
84c9f9 ·* numbers by a factor of 2 or so.
0c775e ·*
33775e ·*
829f2b ·* Bit k in a sieve corresponds to the number a + k*b.
fddc34 ·* For a given a and b, the sieve's job is to find the values of
cb481f ·* k for which a + k*b == 0 (mod p). ·Multiplying by b^-1 and
bd243f ·* isolating k, you get k == -a*b^-1 (mod p). ·So the values of
e3b402 ·* k which should be worked on are k = (-a*b^-1 mod p) + i * p,
3eb4a8 ·* for i = 0, 1, 2,...
9b775e ·*
ce87d1 ·* Note how this is still easy to use with very large b, if you need it.
b6c30b ·* It just requires computing (b mod p) and then finding the multiplicative
94c7af ·* inverse of that.
59775e ·*
31775e ·*
27f4df ·* How large a space to search to ensure that one will hit a prime?
191eb5 ·* The average density is known, but the primes behave oddly, and sometimes
cf1122 ·* there are large gaps. ·It is conjectured by shanks that the first gap
--b315 000dc6051bb40100178 Page 2 of bnsieve.c
dff1c0 ·* of size "delta" will occur at approximately exp(sqrt(delta)), so a delta
032569 ·* of 65536 is conjectured to be to contain a prime up to e^256.
e0301c ·* Remembering the handy 2<->e conversion ratios:
715dd0 ·* ln(2) = 0.693147 ··log2(e) = 1.442695
191519 ·* This covers up to 369 bits. ·Damn, not enough! ·Still, it'll have to do.
c4775e ·*
4e6709 ·* Cramer's conjecture (he proved it for "most" cases) is that in the limit,
c94570 ·* as p goes to infinity, the largest gap after a prime p tends to (ln(p))^2.
6dacf0 ·* So, for a 1024-bit p, the interval to the next prime is expected to be
b4bcd8 ·* about 709.78^2, or 503791. ·We'd need to enlarge our space by a factor of
84274c ·* 8 to be sure. ·It isn't worth the hassle.
8f775e ·*
ee376d ·* Note that a span of this size is expected to contain 92 primes even
ba80c2 ·* in the vicinity of 2^1024 (it's 369 at 256 bits and 492 at 192 bits).
0f9953 ·* So the probability of failure is pretty low.
ac495d ·*/
fae2ff #include "pgpConfig.h"
e00d08 #include "pgpMem.h"
91af5a
d138e5 /*
b316cf ·* Some compilers complain about #if FOO if FOO isn't defined,
b059aa ·* so do the ANSI-mandated thing explicitly...
e4495d ·*/
9ec60f #ifndef NO_ASSERT_H
f2154e #define NO_ASSERT_H 0
267454 #endif
19d8d3 #ifndef NO_LIMITS_H
371a2a #define NO_LIMITS_H 0
a87454 #endif
9fb552 #ifndef NO_STRING_H
1937dd #define NO_STRING_H 0
b27454 #endif
bb8537 #ifndef HAVE_STRINGS_H
b3025c #define HAVE_STRINGS_H 0
4c7454 #endif
38101b #ifndef NEED_MEMORY_H
c2ee50 #define NEED_MEMORY_H 0
467454 #endif
97af5a
7b1be9 #if !NO_LIMITS_H
f42e04 #include <limits.h>¤/* For UINT_MAX */
3af4cb #endif¤ ¤   ¤   /* If not avail, default value of 0 is safe */
55af5a
ac7668 #if !NO_STRING_H
a11130 #include <string.h>¤/* for memset() */
d0a752 #elif HAVE_STRINGS_H
62f7c3 #include <strings.h>
8d7454 #endif
1a3c37 #if NEED_MEMORY_H
dcc737 #include <memory.h>
b57454 #endif
a4af5a
5039fc #include "bn.h"
3be6d6 #include "bnsieve.h"
dd306a #ifdef MSDOS
d621db #include "bnimem.h"
047454 #endif
5aaf5a
b54724 #include "bnkludge.h"
84a146 #include "pgpDebug.h"
3daf5a
2c38e5 /*
74b113 ·* Each array stores potential primes as 1 bits in little-endian bytes.
ba4915 ·* Bit k in an array represents a + k*b, for some parameters a and b
d33517 ·* of the sieve. ·Currently, b is hardcoded to 2.
31775e ·*
43b122 ·* Various factors of 16 arise because these are all *byte* sizes, and
ee9cf4 ·* skipping even numbers, 16 numbers fit into a byte's worth of bitmap.
5c495d ·*/
57af5a
0238e5 /*
dc7dcb ·* The first number in the small prime sieve. ·This could be raised to
--08a5 0002df576de40100178 Page 3 of bnsieve.c
3ffb8a ·* 3 if you want to squeeze bytes out aggressively for a smaller SMALL
174aca ·* table, and doing so would let one more prime into the end of the array,
c436bb ·* but there is no sense making it larger if you're generating small
0029a9 ·* primes up to the limit if 2^16, since it doesn't save any memory and
38a5cc ·* would require extra code to ignore 65537 in the last byte, which is
9c566a ·* over the 16-bit limit.
79495d ·*/
9b6ba0 #define SMALLSTART 1
0eaf5a
5a38e5 /*
b88303 ·* Size of sieve used to find large primes, in bytes. ·For compatibility
d32e47 ·* with 16-bit-int systems, the largest prime that can appear in it,
4624a2 ·* SMALL * 16 + SMALLSTART - 2, must be < 65536. ·Since 65537 is a prime,
363364 ·* this is the absolute maximum table size.
3c495d ·*/
db8196 #define SMALL (65536/16)
dcaf5a
8638e5 /*
5bf924 ·* Compute the multiplicative inverse of x, modulo mod, using the extended
b5aa85 ·* Euclidean algorithm. ·The classical EEA returns two results, traditionally
98190e ·* named s and t, but only one (t) is needed or computed here.
d0f2d2 ·* It is unrolled twice to avoid some variable-swapping, and because negating
181d11 ·* t every other round makes all the number positive and less than the
9a2915 ·* modulus, which makes fixed-length arithmetic easier.
d1775e ·*
89c818 ·* If gcd(x, mod) != 1, then this will return 0.
ba495d ·*/
3465bf static unsigned
b6cd11 sieveModInvert(unsigned x, unsigned mod)
81bb36 {
dbf1aa ¤   unsigned y;
80f523 ¤   unsigned t0, t1;
9f3768 ¤   unsigned q;
cfaf5a
1687f0 ¤   if (x <= 1)
f28744 ¤   ¤   return x;¤  /* 0 and 1 are self-inverse */
f9d8af ¤   /*
7baced ¤   ·* The first round is simplified based on the
f97636 ¤   ·* initial conditions t0 = 1 and t1 = 0.
59a4e3 ¤   ·*/
7f01ae ¤   t1 = mod / x;
7bf0a5 ¤   y = mod % x;
82064f ¤   if (y <= 1)
1b66de ¤   ¤   return y ? mod - t1 : 0;
f0f259 ¤   t0 = 1;
b3af5a
e443ab ¤   do {
6cb910 ¤   ¤   q = x / y;
751c83 ¤   ¤   x = x % y;
b0cbbf ¤   ¤   t0 += q * t1;
791083 ¤   ¤   if (x <= 1)
774937 ¤   ¤   ¤   return x ? t0 : 0;
7e7c19 ¤   ¤   q = y / x;
a68c1b ¤   ¤   y = y % x;
e194ce ¤   ¤   t1 += q * t0;
c60bc8 ¤   } while (y > 1);
7cdd88 ¤   return y ? mod - t1 : 0;
9defe6 }
c9af5a
a9af5a
5338e5 /*
a7eb7c ·* Perform a single sieving operation on an array. ·Clear bits "start",
9cddb7 ·* "start+step", "start+2*step", etc. from the array, up to the size
1982bf ·* limit (in BYTES) "size". ·All of the arguments must fit into 16 bits
f7dd70 ·* for portability.
96775e ·*
57cd56 ·* This is the core of the sieving operation. ·In addition to being
f21ba6 ·* called from the sieving functions, it is useful to call directly if,
fc69aa ·* say, you want to exclude primes congruent to 1 mod 3, or whatever.
fadf11 ·* (Although in that case, it would be better to change the sieving to
d0dc3a ·* use a step size of 6 and start == 5 (mod 6).)
2d775e ·*
--c14f 0001496192640100178 Page 4 of bnsieve.c
c355dc ·* Originally, this was inlined in the code below (with various checks
d07e8c ·* turned off where they could be inferred from the environment), but it
107f13 ·* turns out that all the sieving is so fast that it makes a negligible
c7323b ·* speed difference and smaller, cleaner code was preferred.
2c775e ·*
a21e76 ·* Rather than increment a bit index through the array and clear
71c145 ·* the corresponding bit, this code takes advantage of the fact that
9ab7b8 ·* every eighth increment must use the same bit position in a byte.
620b7f ·* I.e. start + k*step == start + (k+8)*step (mod 8). ·Thus, a bitmask
428908 ·* can be computed only eight times and used for all multiples. ·Thus, the
fa3410 ·* outer loop is over (k mod 8) while the inner loop is over (k div 8).
e7775e ·*
48f730 ·* The only further trickiness is that this code is designed to accept
354e25 ·* start, step, and size up to 65535 on 16-bit machines. ·On such a
37a019 ·* machine, the computation "start+step" can overflow, so we need to
e08f00 ·* insert an extra check for that situation.
f4495d ·*/
f2314a void
1b54c8 sieveSingle(unsigned char *array, unsigned size, unsigned start, unsigned step)
9ebb36 {
47c6d6 ¤   unsigned bit;
092c60 ¤   unsigned char mask;
c8743f ¤   unsigned i;
99af5a
3e1a57 #if UINT_MAX < 0x1ffff
964ec6 ¤   /* Unsigned is small; add checks for wrap */
53695a ¤   for (bit = 0; bit < 8; bit++) {
cd4196 ¤   ¤   i = start/8;
6e3f56 ¤   ¤   if (i >= size)
48cdcb ¤   ¤   ¤   break;
7d95df ¤   ¤   mask = ~(1 << (start & 7));
dc4392 ¤   ¤   do {
9a79e6 ¤   ¤   ¤   array[i] &= mask;
c9c377 ¤   ¤   ¤   i += step;
d8c895 ¤   ¤   } while (i >= step && i < size);
b1b346 ¤   ¤   start += step;
b73532 ¤   ¤   if (start < step)¤  /* Overflow test */
7bcdcb ¤   ¤   ¤   break;
439371 ¤   }
61db21 #else
7f07b8 ¤   /* Unsigned has the range - no overflow possible */
c8695a ¤   for (bit = 0; bit < 8; bit++) {
af4196 ¤   ¤   i = start/8;
033f56 ¤   ¤   if (i >= size)
f6cdcb ¤   ¤   ¤   break;
9d95df ¤   ¤   mask = ~(1 << (start & 7));
854392 ¤   ¤   do {
4179e6 ¤   ¤   ¤   array[i] &= mask;
51c377 ¤   ¤   ¤   i += step;
7e4548 ¤   ¤   } while (i < size);
7fb346 ¤   ¤   start += step;
4f9371 ¤   }
b57454 #endif
dcefe6 }
d5af5a
5438e5 /*
86ef5a ·* Returns the index of the next bit set in the given array. ·The search
3a6b33 ·* begins after the specified bit, so if you care about bit 0, you need
579044 ·* to check it explicitly yourself. ·This returns 0 if no bits are found.
f6775e ·*
8d62c8 ·* Note that the size is in bytes, and that it takes and returns BIT
9a0d35 ·* positions. ·If the array represents odd numbers only, as usual, the
9bdadd ·* returned values must be doubled to turn them into offsets from the
e13637 ·* initial number.
95495d ·*/
ea536c unsigned
380cc3 sieveSearch(unsigned char const *array, unsigned size, unsigned start)
e2bb36 {
c5176a ¤   unsigned i;¤/* Loop index */
8d8d6a ¤   unsigned char t;¤   /* Temp */
44af5a
149e1a ¤   if (!++start)
--c349 00074e51dc340100178 Page 5 of bnsieve.c
79bbde ¤   ¤   return 0;
41001d ¤   i = start/8;
c404bf ¤   if (i >= size)
8318bb ¤   ¤   return 0;¤  /* Done! */
faaf5a
6c2145 ¤   /* Deal with odd-bit beginnings => search the first byte */
e0154e ¤   if (start & 7) {
3ee153 ¤   ¤   t = array[i++] >> (start & 7);
d46910 ¤   ¤   if (t) {
ce3dce ¤   ¤   ¤   if (!(t & 15)) {
7db359 ¤   ¤   ¤   ¤   t >>= 4;
0221fe ¤   ¤   ¤   ¤   start += 4;
71a3a6 ¤   ¤   ¤   }
2e2f9f ¤   ¤   ¤   if (!(t & 3)) {
526580 ¤   ¤   ¤   ¤   t >>= 2;
37f727 ¤   ¤   ¤   ¤   start += 2;
5ba3a6 ¤   ¤   ¤   }
652d1f ¤   ¤   ¤   if (!(t & 1))
d81843 ¤   ¤   ¤   ¤   start += 1;
dff9de ¤   ¤   ¤   return start;
13418b ¤   ¤   } else if (i == size) {
f1913b ¤   ¤   ¤   return 0;¤  /* Done */
a90fe4 ¤   ¤   }
309371 ¤   }
82af5a
159c55 ¤   /* Now the main search loop */
93af5a
9143ab ¤   do {
80e843 ¤   ¤   if ((t = array[i]) != 0) {
ab051e ¤   ¤   ¤   start = 8*i;
263dce ¤   ¤   ¤   if (!(t & 15)) {
1eb359 ¤   ¤   ¤   ¤   t >>= 4;
3d21fe ¤   ¤   ¤   ¤   start += 4;
4ea3a6 ¤   ¤   ¤   }
de2f9f ¤   ¤   ¤   if (!(t & 3)) {
106580 ¤   ¤   ¤   ¤   t >>= 2;
35f727 ¤   ¤   ¤   ¤   start += 2;
6ca3a6 ¤   ¤   ¤   }
b62d1f ¤   ¤   ¤   if (!(t & 1))
f51843 ¤   ¤   ¤   ¤   start += 1;
5cf9de ¤   ¤   ¤   return start;
440fe4 ¤   ¤   }
5d8d57 ¤   } while (++i < size);
2daf5a
5d9442 ¤   /* Failed */
963e6b ¤   return 0;
edefe6 }
fcaf5a
5f38e5 /*
8a4fee ·* Build a table of small primes for sieving larger primes with. ·This
330984 ·* could be cached between calls to sieveBuild, but it's so fast that
9d7ded ·* it's really not worth it. ·This code takes a few milliseconds to run.
52495d ·*/
c12978 static void
37e913 sieveSmall(unsigned char *array, unsigned size)
97bb36 {
e34259 ¤   unsigned i;¤¤   /* Loop index */
76a5d7 ¤   unsigned p;¤¤   /* The current prime */
caaf5a
8b2bd1 ¤   /* Initialize to all 1s */
7b4bcd ¤   pgpFillMemory(array, size, 0xFF);
c5af5a
b6667e #if SMALLSTART == 1
f88768 ¤   /* Mark 1 as NOT prime */
87a181 ¤   array[0] = 0xfe;
8b065c ¤   i = 1;¤ /* Index of first prime */
09db21 #else
53c368 ¤   i = 0;¤ /* Index of first prime */
a17454 #endif
a4af5a
55d8af ¤   /*
742468 ¤   ·* Okay, now sieve via the primes up to 256, obtained from the
--2387 000f864ad9c40100178 Page 6 of bnsieve.c
439125 ¤   ·* table itself. ·We know the maximum possible table size is
97f867 ¤   ·* 65536, and sieveSingle() can cope with out-of-range inputs
a8ee6b ¤   ·* safely, and the time required is trivial, so it isn't adaptive
1f5fec ¤   ·* based on the array size.
699714 ¤   ·*
1b5403 ¤   ·* Convert each bit position into a prime, compute a starting
4e3eec ¤   ·* sieve position (the square of the prime), and remove multiples
0ac8d0 ¤   ·* from the table, using sieveSingle(). ·I used to have that
d4d73c ¤   ·* code in line here, but the speed difference was so small it
3f4ea4 ¤   ·* wasn't worth it. ·If a compiler really wants to waste memory,
b6c411 ¤   ·* it can inline it.
bca4e3 ¤   ·*/
ce43ab ¤   do {
eb68e3 ¤   ¤   p = 2 * i + SMALLSTART;
8b30ea ¤   ¤   if (p > 256)
e0cdcb ¤   ¤   ¤   break;
5858a2 ¤   ¤   /* Start at square of p */
60a463 ¤   ¤   sieveSingle(array, size, (p*p-SMALLSTART)/2, p);
5caf5a
cbb51f ¤   ¤   /* And find the next prime */
5a9e60 ¤   ¤   i = sieveSearch(array, 16, i);
ca64b1 ¤   } while (i);
0cefe6 }
86af5a
44af5a
2638e5 /*
57b808 ·* This is the primary sieving function. ·It fills in the array with
65025c ·* a sieve (multiples of small primes removed) beginning at bn and
6f7ace ·* proceeding in steps of "step".
12775e ·*
e36df9 ·* It generates a small array to get the primes to sieve by. ·It's
0e982a ·* generated on the fly - sieveSmall is fast enough to make that
6a2aa0 ·* perfectly acceptable.
cc775e ·*
b88240 ·* The caller should take the array, walk it with sieveSearch, and
ee723d ·* apply a stronger primality test to the numbers that are returned.
cb775e ·*
f62063 ·* If the "dbl" flag non-zero (at least 1), this also sieves 2*bn+1, in
fef657 ·* steps of 2*step. ·If dbl is 2 or more, this also sieve 4*bn+3,
12c0bc ·* in steps of 4*step, and so on for arbitrarily high values of "dbl".
44ab44 ·* This is convenient for finding primes such that (p-1)/2 is also prime.
3cd6c5 ·* This is particularly efficient because sieveSingle is controlled by the
0dc893 ·* parameter s = -n/step (mod p). ·(In fact, we find t = -1/step (mod p)
bcb2ea ·* and multiply that by n (mod p).) ·If you have -n/step (mod p), then
5aeba4 ·* finding -(2*n+1)/(2*step) (mod p), which is -n/step - 1/(2*step) (mod p),
beac2d ·* reduces to finding -1/(2*step) (mod p), or t/2 (mod p), and adding that
611ab6 ·* to s = -n/step (mod p). ·Dividing by 2 modulo an odd p is easy -
d10cc3 ·* if even, divide directly. ·Otherwise, add p (which produces an even
9345cb ·* sum), and divide by 2. ·Very simple. ·And this produces s' and t'
ac26f8 ·* for step' = 2*step. ·It can be repeated for step'' = 4*step and so on.
02775e ·*
397319 ·* Note that some of the math is complicated by the fact that 2*p might
d0b9bd ·* not fit into an unsigned, so rather than if (odd(x)) x = (x+p)/2,
e8df66 ·* we do if (odd(x)) x = x/2 + p/2 + 1;
ac775e ·*
8c29b3 ·* TODO: Do the double-sieving by sieving the larger number, and then
cbf690 ·* just subtract one from the remainder to get the other parameter.
0e6862 ·* (bn-1)/2 is divisible by an odd p iff bn-1 is divisible, which is
8a6a4e ·* true iff bn == 1 mod p. ·This requires using a step size of 4.
a0495d ·*/
7f4d2f int
b1ad83 sieveBuild(unsigned char *array, unsigned size, BigNum const *bn,
3fc525 ¤   unsigned step, unsigned dbl)
aebb36 {
44d27f ¤   unsigned i, j;¤ /* Loop index */
8d281e ¤   unsigned p;¤/* Current small prime */
38a0b3 ¤   unsigned s;¤/* Where to start operations in the big sieve */
6f78b6 ¤   unsigned t;¤/* Step modulo p, the current prime */
a6936c #ifdef MSDOS¤   /* Use dynamic allocation rather than on the stack */
806eff ¤   unsigned char *small;
8adb21 #else
f844f9 ¤   unsigned char small[SMALL];
--ee11 0007ec32abe40100178 Page 7 of bnsieve.c
a07454 #endif
e0af5a
5dfbd0 ¤   pgpAssert(array);
4baf5a
7d306a #ifdef MSDOS
68d741 ¤   small = bniMemAlloc(SMALL);¤/* Which allocator? ·Not secure. */
0a74dc ¤   if (!small)
0b6659 ¤   ¤   return -1;¤ /* Failed */
357454 #endif
abaf5a
c3d8af ¤   /*
87ff2d ¤   ·* An odd step is a special case, since we must sieve by 2,
61b3cc ¤   ·* which isn't in the small prime array and has a few other
07d8c1 ¤   ·* special properties. ·These are:
6ef128 ¤   ·* - Since the numbers are stored in binary, we don't need to
15f6e7 ¤   ·* ··use bnModQ to find the remainder.
57dc33 ¤   ·* - If step is odd, then t = step % 2 is 1, which allows
81e40d ¤   ·* ··the elimination of a lot of math. ·Inverting and negating
94ca59 ¤   ·* ··t don't change it, and multiplying s by 1 is a no-op,
b4a250 ¤   ·* ··so t isn't actually mentioned.
20138e ¤   ·* - Since this is the first sieving, instead of calling
9f98a3 ¤   ·* ··sieveSingle, we can just use memset to fill the array
a94d8c ¤   ·* ··with 0x55 or 0xAA. ·Since a 1 bit means possible prime
819d58 ¤   ·* ··(i.e. NOT divisible by 2), and the least significant bit
1ce2b6 ¤   ·* ··is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT
5d1070 ¤   ·* ··prime), while if bn % 2 == 1, use 0x55.
8e0a17 ¤   ·* ··(If step is even, bn must be odd, so fill the array with 0xFF.)
0e1260 ¤   ·* - Any doublings need not be considered, since 2*bn+1 is odd, and
c32ad2 ¤   ·* ··2*step is even, so none of these numbers are divisible by 2.
7ba4e3 ¤   ·*/
d4bfe1 ¤   if (step & 1) {
25edcb ¤   ¤   s = bnLSWord(bn) & 1;
dd3811 ¤   ¤   memset(array, 0xAA >> s, size);
c2f037 ¤   } else {
4a0131 ¤   ¤   /* Initialize the array to all 1's */
cfaa67 ¤   ¤   memset(array, 255, size);
0e9f34 ¤   ¤   pgpAssert(bnLSWord(bn) & 1);
c29371 ¤   }
41af5a
b0d8af ¤   /*
488822 ¤   ·* This could be cached between calls to sieveBuild, but
367f9a ¤   ·* it's really not worth it; sieveSmall is *very* fast.
599f92 ¤   ·* sieveSmall returns a sieve of odd primes.
cfa4e3 ¤   ·*/
ea9de7 ¤   sieveSmall(small, SMALL);
0faf5a
b5d8af ¤   /*
4b0bd3 ¤   ·* Okay, now sieve via the primes up to ssize*16+SMALLSTART-1,
b945a9 ¤   ·* obtained from the small table.
b3a4e3 ¤   ·*/
ed7ff2 ¤   i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0);
d843ab ¤   do {
e668e3 ¤   ¤   p = 2 * i + SMALLSTART;
00af5a
951b17 ¤   ¤   /*
d87ea4 ¤   ¤   ·* Modulo is usually very expensive, but step is usually
7922d5 ¤   ¤   ·* small, so this conditional is worth it.
ec9de3 ¤   ¤   ·*/
2fbacb ¤   ¤   t = (step < p) ? step : step % p;
9d5878 ¤   ¤   if (!t) {
c17aad ¤   ¤   ¤   /*
264b0f ¤   ¤   ¤   ·* Instead of pgpAssert failing, returning all zero
b4cddf ¤   ¤   ¤   ·* bits is the "correct" thing to do, but I think
17e598 ¤   ¤   ¤   ·* that the caller should take care of that
b5e8bd ¤   ¤   ¤   ·* themselves before starting.
6a8753 ¤   ¤   ¤   ·*/
ec0930 ¤   ¤   ¤   pgpAssert(bnModQ(bn, p) != 0);
9817f5 ¤   ¤   ¤   continue;
d10fe4 ¤   ¤   }
7c1b17 ¤   ¤   /*
4d1f46 ¤   ¤   ·* Get inverse of step mod p. ·0 < t < p, and p is prime,
7e4745 ¤   ¤   ·* so it has an inverse and sieveModInvert can't return 0.
--bc77 000f561ef8840100178 Page 8 of bnsieve.c
509de3 ¤   ¤   ·*/
f5919b ¤   ¤   t = sieveModInvert(t, p);
15146d ¤   ¤   pgpAssert(t);
1a6bc0 ¤   ¤   /* Negate t, so now t == -1/step (mod p) */
b985cf ¤   ¤   t = p - t;
2caf5a
649007 ¤   ¤   /* Now get the bignum modulo the prime. */
92d737 ¤   ¤   s = bnModQ(bn, p);
3eaf5a
cba151 ¤   ¤   /* Multiply by t, the negative inverse of step size */
ad9758 #if UINT_MAX/0xffff < 0xffff
e255be ¤   ¤   s = (unsigned)(((unsigned long)s * t) % p);
15db21 #else
19b9a2 ¤   ¤   s = (s * t) % p;
807454 #endif
c8af5a
2f4281 ¤   ¤   /* s is now the starting bit position, so sieve */
6ac41e ¤   ¤   sieveSingle(array, size, s, p);
beaf5a
dbccbf ¤   ¤   /* Now do the double sieves as desired. */
ac273a ¤   ¤   for (j = 0; j < dbl; j++) {
7e4115 ¤   ¤   ¤   /* Halve t modulo p */
1f1a57 #if UINT_MAX < 0x1ffff
230e71 ¤   ¤   ¤   t = (t & 1) ? p/2 + t/2 + 1 : t/2;
d88da8 ¤   ¤   ¤   /* Add t to s, modulo p with overflow checks. */
bf44b3 ¤   ¤   ¤   s += t;
c79eaa ¤   ¤   ¤   if (s >= p || s < t)
6f45dc ¤   ¤   ¤   ¤   s -= p;
77db21 #else
a8af2e ¤   ¤   ¤   if (t & 1)
3ec128 ¤   ¤   ¤   ¤   t += p;
7318be ¤   ¤   ¤   t /= 2;
2895e6 ¤   ¤   ¤   /* Add t to s, modulo p */
7744b3 ¤   ¤   ¤   s += t;
2c99e7 ¤   ¤   ¤   if (s >= p)
6545dc ¤   ¤   ¤   ¤   s -= p;
847454 #endif
004c78 ¤   ¤   ¤   sieveSingle(array, size, s, p);
bf0fe4 ¤   ¤   }
e6af5a
67b51f ¤   ¤   /* And find the next prime */
e8586d ¤   } while ((i = sieveSearch(small, SMALL, i)) != 0);
a3af5a
19306a #ifdef MSDOS
e2b220 ¤   bniMemFree(small, SMALL);
d77454 #endif
e129fb ¤   return 0;¤  /* Success */
83efe6 }
35af5a
ba38e5 /*
cb1b7b ·* Similar to the above, but use "step" (which must be even) as a step
9d9944 ·* size rather than a fixed value of 2. ·If "step" has any small divisors
163f67 ·* other than 2, this will blow up.
ff775e ·*
f358f1 ·* Returns -1 on out of memory (MSDOS only, actually), and -2
93a4a0 ·* if step is found to be non-prime.
d5495d ·*/
d84d2f int
9f1c47 sieveBuildBig(unsigned char *array, unsigned size, BigNum const *bn,
74125f ¤   BigNum const *step, unsigned dbl)
1fbb36 {
43d27f ¤   unsigned i, j;¤ /* Loop index */
37281e ¤   unsigned p;¤/* Current small prime */
3ca0b3 ¤   unsigned s;¤/* Where to start operations in the big sieve */
ec5813 ¤   unsigned t;¤/* step modulo p, the current prime */
2d936c #ifdef MSDOS¤   /* Use dynamic allocation rather than on the stack */
4a6eff ¤   unsigned char *small;
a1db21 #else
ab44f9 ¤   unsigned char small[SMALL];
617454 #endif
dbaf5a
f5fbd0 ¤   pgpAssert(array);
--9745 00077abf47b40100178 Page 9 of bnsieve.c
e0af5a
14306a #ifdef MSDOS
2ed741 ¤   small = bniMemAlloc(SMALL);¤/* Which allocator? ·Not secure. */
c374dc ¤   if (!small)
146659 ¤   ¤   return -1;¤ /* Failed */
697454 #endif
edd8af ¤   /*
33ff2d ¤   ·* An odd step is a special case, since we must sieve by 2,
89b3cc ¤   ·* which isn't in the small prime array and has a few other
4bd8c1 ¤   ·* special properties. ·These are:
86f128 ¤   ·* - Since the numbers are stored in binary, we don't need to
88f6e7 ¤   ·* ··use bnModQ to find the remainder.
9fdc33 ¤   ·* - If step is odd, then t = step % 2 is 1, which allows
41e40d ¤   ·* ··the elimination of a lot of math. ·Inverting and negating
21ca59 ¤   ·* ··t don't change it, and multiplying s by 1 is a no-op,
a9a250 ¤   ·* ··so t isn't actually mentioned.
a7138e ¤   ·* - Since this is the first sieving, instead of calling
4498a3 ¤   ·* ··sieveSingle, we can just use memset to fill the array
d04d8c ¤   ·* ··with 0x55 or 0xAA. ·Since a 1 bit means possible prime
1b9d58 ¤   ·* ··(i.e. NOT divisible by 2), and the least significant bit
9ae2b6 ¤   ·* ··is first, if bn % 2 == 0, we use 0xAA (bit 0 = bn is NOT
921070 ¤   ·* ··prime), while if bn % 2 == 1, use 0x55.
b10a17 ¤   ·* ··(If step is even, bn must be odd, so fill the array with 0xFF.)
f11260 ¤   ·* - Any doublings need not be considered, since 2*bn+1 is odd, and
b52ad2 ¤   ·* ··2*step is even, so none of these numbers are divisible by 2.
e2a4e3 ¤   ·*/
177659 ¤   if (bnLSWord(step) & 1) {
beedcb ¤   ¤   s = bnLSWord(bn) & 1;
e43811 ¤   ¤   memset(array, 0xAA >> s, size);
b2f037 ¤   } else {
c40131 ¤   ¤   /* Initialize the array to all 1's */
fdaa67 ¤   ¤   memset(array, 255, size);
439f34 ¤   ¤   pgpAssert(bnLSWord(bn) & 1);
be9371 ¤   }
b6af5a
ffd8af ¤   /*
cc8822 ¤   ·* This could be cached between calls to sieveBuild, but
ac7f9a ¤   ·* it's really not worth it; sieveSmall is *very* fast.
912d23 ¤   ·* sieveSmall returns a sieve of the odd primes.
93a4e3 ¤   ·*/
c09de7 ¤   sieveSmall(small, SMALL);
89af5a
e4d8af ¤   /*
0d0bd3 ¤   ·* Okay, now sieve via the primes up to ssize*16+SMALLSTART-1,
6445a9 ¤   ·* obtained from the small table.
a4a4e3 ¤   ·*/
0d7ff2 ¤   i = (small[0] & 1) ? 0 : sieveSearch(small, SMALL, 0);
c443ab ¤   do {
2368e3 ¤   ¤   p = 2 * i + SMALLSTART;
ebaf5a
ff642c ¤   ¤   t = bnModQ(step, p);
a05878 ¤   ¤   if (!t) {
010930 ¤   ¤   ¤   pgpAssert(bnModQ(bn, p) != 0);
c217f5 ¤   ¤   ¤   continue;
000fe4 ¤   ¤   }
02002f ¤   ¤   /* Get negative inverse of step */
8fd7a6 ¤   ¤   t = sieveModInvert(bnModQ(step, p), p);
32146d ¤   ¤   pgpAssert(t);
2ea0d0 ¤   ¤   t = p-t;
1caf5a
6bdd1a ¤   ¤   /* Okay, we have a prime - get the remainder */
54d737 ¤   ¤   s = bnModQ(bn, p);
44af5a
3ce26d ¤   ¤   /* Now multiply s by the negative inverse of step (mod p) */
efd44b #if UINT_MAX < 0xffff * 0xffff
9a55be ¤   ¤   s = (unsigned)(((unsigned long)s * t) % p);
37db21 #else
e5b9a2 ¤   ¤   s = (s * t) % p;
9b7454 #endif
43f5c8 ¤   ¤   /* We now have the starting bit pos */
acc41e ¤   ¤   sieveSingle(array, size, s, p);
77af5a
--ffe5 001eb852ce840100178 Page 10 of bnsieve.c
12ccbf ¤   ¤   /* Now do the double sieves as desired. */
3e273a ¤   ¤   for (j = 0; j < dbl; j++) {
904115 ¤   ¤   ¤   /* Halve t modulo p */
f01a57 #if UINT_MAX < 0x1ffff
290e71 ¤   ¤   ¤   t = (t & 1) ? p/2 + t/2 + 1 : t/2;
dc8da8 ¤   ¤   ¤   /* Add t to s, modulo p with overflow checks. */
eb44b3 ¤   ¤   ¤   s += t;
d79eaa ¤   ¤   ¤   if (s >= p || s < t)
c645dc ¤   ¤   ¤   ¤   s -= p;
66db21 #else
a3af2e ¤   ¤   ¤   if (t & 1)
dec128 ¤   ¤   ¤   ¤   t += p;
c818be ¤   ¤   ¤   t /= 2;
1295e6 ¤   ¤   ¤   /* Add t to s, modulo p */
cf44b3 ¤   ¤   ¤   s += t;
df99e7 ¤   ¤   ¤   if (s >= p)
e645dc ¤   ¤   ¤   ¤   s -= p;
ac7454 #endif
c54c78 ¤   ¤   ¤   sieveSingle(array, size, s, p);
4b0fe4 ¤   ¤   }
35af5a
4cb51f ¤   ¤   /* And find the next prime */
78586d ¤   } while ((i = sieveSearch(small, SMALL, i)) != 0);
78af5a
ec306a #ifdef MSDOS
e2b220 ¤   bniMemFree(small, SMALL);
5b7454 #endif
a429fb ¤   return 0;¤  /* Success */
ebefe6 }
--7f05 001463bba8840100179 Page 1 of bnsieve.h
bc38e5 /*
dc6d7d ·* bnsieve.h - Trial division for prime finding.
fc775e ·*
94ba1b ·* This is generally not intended for direct use by a user of the library;
55d986 ·* the bnprime.c and dhprime.c functions. are more likely to be used.
92b150 ·* However, a special application may need these.
45775e ·*
20010b ·* $Id: bnsieve.h,v 1.5 1997/05/13 01:18:54 mhw Exp $
0b495d ·*/
95af5a
3739de #ifndef Included_bnsieve_h
545da8 #define Included_bnsieve_h
2daf5a
a799c6 PGP_BEGIN_C_DECLARATIONS
0eaf5a
c4c5d5 #include "pgpBase.h"
31af5a
61adb8 #include "pgpOpaqueStructs.h"
75af5a
7c2fa5 /* Remove multiples of a single number from the sieve */
ab615e void sieveSingle(unsigned char *array, unsigned size, unsigned start,
b38d0b ¤   unsigned step);
3baf5a
7703e0 /* Build a sieve starting at the number and incrementing by "step". */
e634f2 int sieveBuild(unsigned char *array, unsigned size,
6106c0 ¤   BigNum const *bn, unsigned step, unsigned dbl);
c2af5a
18e591 /* Similar, but uses a >16-bit step size */
573f25 int sieveBuildBig(unsigned char *array, unsigned size,
9c36f8 ¤   BigNum const *bn, BigNum const *step, unsigned dbl);
82af5a
cde4e1 /* Return the next bit set in the sieve (or 0 on failure) */
9b2975 unsigned sieveSearch(unsigned char const *array, unsigned size,
dad6ee ¤   unsigned start);
58af5a
181254 PGP_END_C_DECLARATIONS
96af5a
4633e4 #endif /* Included_bnsieve_h */
--6a24 001d457c8aa4010017a Page 1 of bnsize00.h
bc38e5 /*
4c3087 ·* bnsize00.h - pick the correct machine word size to use.
f0775e ·*
0068c2 ·* Written by Colin Plumb.
f0775e ·*
bcc978 ·* $Id: bnsize00.h,v 1.1 1997/04/30 08:36:24 mhw Exp $
3d495d ·*/
663fe0 #include "bni.h"¤   /* Get basic information */
3aaf5a
8dbadd #if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD64)
f347d2 # if defined(BNWORD128) || (defined(bniMulAdd1_64) && defined(bniMulSub1_64))
1bbd8d # ·define BNSIZE64 1
38d464 # elif defined(mul64_ppmm) || defined(mul64_ppmma) || defined(mul64_ppmmaa)
65bd8d # ·define BNSIZE64 1
67e01a # endif
7b7454 #endif
b9af5a
f50253 #if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD32)
21b9b3 # if defined(BNWORD64) || (defined(bniMulAdd1_32) && defined(bniMulSub1_32))
c7d043 # ·define BNSIZE32 1
9136ef # elif defined(mul32_ppmm) || defined(mul32_ppmma) || defined(mul32_ppmmaa)
97d043 # ·define BNSIZE32 1
4ce01a # endif
897454 #endif
d1af5a
eb5844 #if !BNSIZE64 && !BNSIZE32 && !BNSIZE16 && defined(BNWORD16)
7008fd # if defined(BNWORD32) || (defined(bniMulAdd1_16) && defined(bniMulSub1_16))
47b427 # ·define BNSIZE16 1
30d5b8 # elif defined(mul16_ppmm) || defined(mul16_ppmma) || defined(mul16_ppmmaa)
00b427 # ·define BNSIZE16 1
03e01a # endif
827454 #endif
9caf5a
eec863 #if !BNSIZE64 && !BNSIZE32 && !BNSIZE16
dfc120 #error Unable to find a viable word size to compile bignum library.
d47454 #endif
--6d31 0016493a83f4010017b Page 1 of lbn00.c
bc38e5 /*
7fa1a9 ·* lbn00.c - auto-size-detecting lbn??.c file.
20775e ·*
35001b ·* Written in 1995 by Colin Plumb.
ba775e ·*
0e1868 ·* $Id: lbn00.c,v 1.1 1997/04/30 08:36:24 mhw Exp $
3e495d ·*/
5eaf5a
dbafa6 #include "bnsize00.h"
ecaf5a
7784d0 #if BNSIZE64
b0af5a
f1a754 /* Include all of the C source file by reference */
d931c8 #include "lbn64.c"
2baf5a
4641e3 #elif BNSIZE32
6daf5a
e4a754 /* Include all of the C source file by reference */
ea1ed7 #include "lbn32.c"
33af5a
169a11 #else /* BNSIZE16 */
82af5a
8ea754 /* Include all of the C source file by reference */
fc3b91 #include "lbn16.c"
94af5a
647454 #endif
--867f 000a3b604b84010017c Page 1 of pgpBigNum.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
9295fe ¤   $Id: pgpBigNum.c,v 1.10.10.1 1998/11/12 03:21:15 heller Exp $
caf7f7 ____________________________________________________________________________*/
50e2ff #include "pgpConfig.h"
ffaf5a
270d08 #include "pgpMem.h"
482f8d #include "pgpErrors.h"
b1c26c #include "pgpContext.h"
364447 #include "pgpBigNum.h"
5e39fc #include "bn.h"
47af5a
1daf5a
0eaf5a
9caf5a
fcc60e #define IsBNError( i )¤ ¤   ¤   ( (i) != 0 )
6f21d5 #define IsntBNError( i )¤   ¤   ( (i) == 0 )
7eaf5a
42af5a
005bf4 struct PGPBigNum
01bb36 {
535995 ¤   BigNum¤ ¤   ¤   bn;
8b82f7 };
97af5a
706c2c ¤   static PGPBoolean
44b97c pgpBigNumIsValid( PGPBigNumRef bn )
ebbb36 {
23b528 ¤   return( IsntNull( bn ) &&
2f6bd0 ¤   ¤   PGPMemoryMgrIsValid( bn->bn.mgr ) );
deefe6 }
c003d0 #define pgpValidateBigNum( bn )¤PGPValidateParam( pgpBigNumIsValid( bn ) )
0aaf5a
5b308a /* Creates a new bignum */
eac744 ¤   PGPError
2872c2 PGPNewBigNum(
346740 ¤   PGPMemoryMgrRef¤mgr,
13fe55 ¤   PGPBoolean¤ ¤   secure,
c7cb5f ¤   PGPBigNumRef *¤ newBN )
7cbb36 {
179372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
98a48d ¤   PGPBigNumRef¤   ref;
4e67c5 ¤
c701d9 ¤   PGPValidatePtr( newBN );
a78173 ¤   *newBN¤ = kPGPInvalidBigNumRef;
ee67c5 ¤
d5727a ¤   ref¤= (PGPBigNumRef) PGPNewData( mgr,
72f318 ¤   ¤   ¤   sizeof( **newBN ), kPGPMemoryMgrFlags_Clear);
f0f439 ¤   if ( IsntNull( ref ) )
a3c7a1 ¤   {
a04f0b ¤   ¤   bnBegin( &ref->bn, mgr, secure );
d0d726 ¤   ¤   *newBN¤ = ref;
c89371 ¤   }
5c0e24 ¤   else
97c7a1 ¤   {
6117a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
429371 ¤   }
3c67c5 ¤
14deb7 ¤   return( err );
4befe6 }
60af5a
3faf5a
94d49b /* destoys the bignum and all memory it uses */
5cc744 ¤   PGPError
8ddf61 PGPFreeBigNum( PGPBigNumRef¤bn )
ddbb36 {
d426d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2067c5 ¤
a3489d ¤   pgpValidateBigNum( bn );
--cde9 0009c2dd25b4010017c Page 2 of pgpBigNum.c
e219b2 ¤   bnEnd( &bn->bn );
dd67c5 ¤
fdee1e ¤   err¤= PGPFreeData( bn );
dd67c5 ¤
7fdeb7 ¤   return( err );
04efe6 }
2caf5a
2caf5a
beaf5a
b17026 /* Create a new big num with same value as src */
17c744 ¤   PGPError
1a1f46 PGPCopyBigNum(
7bda6d ¤   PGPBigNumRef¤   src,
430fe1 ¤   PGPBigNumRef * ¤dest )
d8bb36 {
729372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
5c39a8 ¤   PGPBigNumRef¤   temp¤   = NULL;
6867c5 ¤
4c25be ¤   PGPValidatePtr( dest );
dc15a3 ¤   *dest¤  = NULL;
5803fc ¤   pgpValidateBigNum( src );
6c67c5 ¤
775174 ¤   err¤= PGPNewBigNum( src->bn.mgr, src->bn.isSecure, &temp );
17f1e7 ¤   if ( IsntPGPError( err ) )
7cc7a1 ¤   {
ac8dce ¤   ¤   err¤= PGPAssignBigNum( src, temp );
c1be18 ¤   ¤   if ( IsPGPError( err ) )
295b34 ¤   ¤   {
bfb2ed ¤   ¤   ¤   PGPFreeBigNum( temp );
124ba7 ¤   ¤   ¤   temp¤   = NULL;
4a0fe4 ¤   ¤   }
679371 ¤   }
1d67c5 ¤
009f49 ¤   *dest¤  = temp;
b167c5 ¤
e9deb7 ¤   return( err );
85efe6 }
25af5a
b7af5a
94ac73 /* Make existing bignum dest have same value as source */
56c744 ¤   PGPError
026e96 PGPAssignBigNum(
79da6d ¤   PGPBigNumRef¤   src,
f82ff4 ¤   PGPBigNumRef¤   dest )
81bb36 {
e226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
dc67c5 ¤
4403fc ¤   pgpValidateBigNum( src );
335beb ¤   pgpValidateBigNum( dest );
e567c5 ¤
cf4432 ¤   if ( IsBNError( bnCopy( &dest->bn, &src->bn ) ) )
8fc7a1 ¤   {
b017a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
9c9371 ¤   }
eb67c5 ¤
6fdeb7 ¤   return( err );
13efe6 }
26af5a
7aaf5a
d7af5a
c318ce /* Swap two BigNums. ·Very fast. */
d3c744 ¤   PGPError
3dc8b7 PGPSwapBigNum( PGPBigNumRef¤a, PGPBigNumRef¤b)
c9bb36 {
b526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
c367c5 ¤
fa76ec ¤   pgpValidateBigNum( a );
c76b20 ¤   pgpValidateBigNum( b );
d267c5 ¤
9dfe3b ¤   bnSwap( &a->bn, &b->bn );
c467c5 ¤
9cdeb7 ¤   return( err );
--bd74 0003fa232d34010017c Page 3 of pgpBigNum.c
7aefe6 }
46af5a
8eaf5a
79af5a
85af5a
0c38e5 /*
74b555 ·* Move bytes between the given buffer and the given BigNum encoded in
025965 ·* base 256. ·I.e. after either of these, the buffer will be equal to
afea08 ·* (bn / 256^lsbyte) % 256^len. ·The difference is which is altered to
fd3b60 ·* match the other!
d3495d ·*/
83c744 ¤   PGPError
a35874 PGPBigNumExtractBigEndianBytes(
f4fea0 ¤   PGPBigNumRef¤   bn,
a65ea3 ¤   PGPByte *¤  ¤   ¤   dest,
83cdd5 ¤   PGPUInt32¤  ¤   ¤   lsbyte,
ccae96 ¤   PGPUInt32¤  ¤   ¤   len )
64bb36 {
9f26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
f967c5 ¤
00489d ¤   pgpValidateBigNum( bn );
0067c5 ¤
b284a1 ¤   bnExtractBigBytes( &bn->bn, dest, lsbyte, len );
0167c5 ¤
9cdeb7 ¤   return( err );
c0efe6 }
53af5a
d92b85 ¤   ¤   ¤   ¤
3bc744 ¤   PGPError
488e14 PGPBigNumInsertBigEndianBytes(
76fea0 ¤   PGPBigNumRef¤   bn,
f79cb3 ¤   PGPByte const *¤src,
4ea7b3 ¤   PGPUInt32¤  ¤   lsbyte,
331d2f ¤   PGPUInt32¤  ¤   len )
76bb36 {
0126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2567c5 ¤
11489d ¤   pgpValidateBigNum( bn );
3167c5 ¤
46c71a ¤   if ( IsBNError( bnInsertBigBytes( &bn->bn, src, lsbyte, len ) ) )
d3c7a1 ¤   {
4617a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
369371 ¤   }
f367c5 ¤
37deb7 ¤   return( err );
b5efe6 }
f2af5a
11af5a
eb684c /* The same, but the buffer is little-endian. */
52c744 ¤   PGPError
c9519f PGPBigNumExtractLittleEndianBytes(
ebfea0 ¤   PGPBigNumRef¤   bn,
9ba117 ¤   PGPByte *¤  ¤   dest,
24a7b3 ¤   PGPUInt32¤  ¤   lsbyte,
a81d2f ¤   PGPUInt32¤  ¤   len )
c2bb36 {
ff26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5a67c5 ¤
83489d ¤   pgpValidateBigNum( bn );
2c67c5 ¤
5d651c ¤   bnExtractLittleBytes( &bn->bn, dest, lsbyte, len );
d167c5 ¤
dedeb7 ¤   return( err );
57efe6 }
68af5a
a52b85 ¤   ¤   ¤   ¤
60c744 ¤   PGPError
f25f39 PGPBigNumInsertLittleEndianBytes(
cafea0 ¤   PGPBigNumRef¤   bn,
d89cb3 ¤   PGPByte const *¤src,
28a7b3 ¤   PGPUInt32¤  ¤   lsbyte,
3f1d2f ¤   PGPUInt32¤  ¤   len )
--6e28 000609d5b394010017c Page 4 of pgpBigNum.c
2cbb36 {
cd26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
e867c5 ¤
a2489d ¤   pgpValidateBigNum( bn );
c467c5 ¤
685559 ¤   if ( IsBNError( bnInsertLittleBytes( &bn->bn, src, lsbyte, len ) ) )
43c7a1 ¤   {
2217a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
379371 ¤   }
cb67c5 ¤
29deb7 ¤   return( err );
a7efe6 }
a3af5a
e2af5a
660b69 /* Return the least-significant bits (at least 16) of the BigNum */
dac255 ¤   PGPUInt16
86fe99 PGPBigNumGetLSWord( PGPBigNumRef¤   bn )
d5bb36 {
712651 ¤   PGPUInt16¤  lsWord¤ = 0;
9067c5 ¤
1728e3 ¤   if ( pgpBigNumIsValid( bn ) )
b0c7a1 ¤   {
dabaf2 ¤   ¤   lsWord¤ = bnLSWord( &bn->bn );
bf9371 ¤   }
a667c5 ¤
ee77ae ¤   return( lsWord );
8befe6 }
80af5a
caaf5a
e738e5 /*
8c810c ·* Return the number of significant bits in the BigNum.
c3d5d9 ·* 0 or 1+floor(log2(src))
81495d ·*/
1f108d ¤   PGPUInt32
a2e7e2 PGPBigNumGetSignificantBits( PGPBigNumRef¤  bn )
4dbb36 {
152e01 ¤   PGPUInt32¤  numBits;
b067c5 ¤
25489d ¤   pgpValidateBigNum( bn );
a967c5 ¤
b4e1eb ¤   numBits¤= bnBits( &bn->bn );
3967c5 ¤
6bcf78 ¤   return( numBits );
d9efe6 }
feaf5a
32af5a
bd38e5 /*
444362 ·* Adds two bignums into dest. ·Faster if dest is same as lhs or rhs.
ca495d ·*/
5ac744 ¤   PGPError
8b89db PGPBigNumAdd(
d99e4b ¤   PGPBigNumRef¤   lhs,
d84bb3 ¤   PGPBigNumRef¤   rhs,
842ff4 ¤   PGPBigNumRef¤   dest )
69bb36 {
6926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
68626d ¤   int¤¤   ¤   bnError;
1667c5 ¤
c9703f ¤   pgpValidateBigNum( lhs );
c543d7 ¤   pgpValidateBigNum( rhs );
0a5beb ¤   pgpValidateBigNum( dest );
a867c5 ¤
a36539 ¤   if ( lhs == dest )
c6c7a1 ¤   {
7580b6 ¤   ¤   bnError¤= bnAdd( &dest->bn, &rhs->bn );
7a9371 ¤   }
197e22 ¤   else if ( rhs == dest )
2ec7a1 ¤   {
b1b82e ¤   ¤   bnError¤= bnAdd( &dest->bn, &lhs->bn );
cf9371 ¤   }
9b0e24 ¤   else
60c7a1 ¤   {
--b4ec 00067d10a864010017c Page 5 of pgpBigNum.c
7ca48b ¤   ¤   bnError¤= bnCopy( &dest->bn, &lhs->bn );
9ec2bd ¤   ¤   if ( bnError == 0 )
fb5b34 ¤   ¤   {
dc16f7 ¤   ¤   ¤   bnError¤= bnAdd( &dest->bn, &rhs->bn );
b90fe4 ¤   ¤   }
029371 ¤   }
e867c5 ¤
09a409 ¤   if ( IsBNError( bnError ) )
81c7a1 ¤   {
4d17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
d19371 ¤   }
2567c5 ¤
16deb7 ¤   return( err );
16efe6 }
34af5a
c4af5a
c638e5 /*
8492ed ·* lhs-rhs. ·dest and src may be the same, but bnSetQ(dest, 0) is faster.
1c869a ·* if dest < src, returns error and dest is undefined.
90495d ·*/
94c744 ¤   PGPError
d5d9d0 PGPBigNumSubtract(
099e4b ¤   PGPBigNumRef¤   lhs,
be4bb3 ¤   PGPBigNumRef¤   rhs,
ae3cfd ¤   PGPBigNumRef¤   dest,
bf2ff3 ¤   PGPBoolean *¤   underflowPtr )
7fbb36 {
5826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
8a626d ¤   int¤¤   ¤   bnError;
82d7e4 ¤   PGPBoolean¤ underflow¤  = FALSE;
0167c5 ¤
94a25b ¤   if ( IsntNull( underflowPtr ) )
20c24e ¤   ¤   *underflowPtr¤  = FALSE;
341b52 ¤   ¤
3a703f ¤   pgpValidateBigNum( lhs );
5f43d7 ¤   pgpValidateBigNum( rhs );
515beb ¤   pgpValidateBigNum( dest );
c267c5 ¤
4b6539 ¤   if ( lhs == dest )
aec7a1 ¤   {
a274e8 ¤   ¤   bnError¤= bnSub( &dest->bn, &rhs->bn );
de7844 ¤   ¤   underflow¤  = (bnError == 1);
0d5d9c ¤   ¤   bnError¤¤   = 0;
959371 ¤   }
f77e22 ¤   else if ( rhs == dest )
52c7a1 ¤   {
ef1f79 ¤   ¤   BigNum¤ temp;
23b5e7 ¤   ¤   PGPBoolean¤ secure;
ad1b52 ¤   ¤
820727 ¤   ¤   secure¤ = lhs->bn.isSecure || rhs->bn.isSecure ||
bfb447 ¤   ¤   ¤   ¤   ¤   dest->bn.isSecure;
3a0d86 ¤   ¤   bnBegin( &temp, dest->bn.mgr, secure );
9d360c ¤   ¤   ¤   bnError¤= bnCopy( &temp, &lhs->bn );
d36fe3 ¤   ¤   ¤   if ( bnError == 0 )
33f776 ¤   ¤   ¤   {
1ec8db ¤   ¤   ¤   ¤   bnError¤= bnSub( &temp, &rhs->bn );
e87d6f ¤   ¤   ¤   ¤   underflow¤  = (bnError == 1);
cad297 ¤   ¤   ¤   ¤   bnError¤¤   = 0;
272b85 ¤   ¤   ¤   ¤
a329b0 ¤   ¤   ¤   ¤   bnError¤= bnCopy( &dest->bn, &temp );
68a3a6 ¤   ¤   ¤   }
696b25 ¤   ¤   bnEnd( &temp );
5a9371 ¤   }
6f0e24 ¤   else
05c7a1 ¤   {
cea48b ¤   ¤   bnError¤= bnCopy( &dest->bn, &lhs->bn );
80c2bd ¤   ¤   if ( bnError == 0 )
a55b34 ¤   ¤   {
0ce2a9 ¤   ¤   ¤   bnError¤= bnSub( &dest->bn, &rhs->bn );
c644aa ¤   ¤   ¤   underflow¤  = (bnError == 1);
4b69c1 ¤   ¤   ¤   bnError¤¤   = 0;
670fe4 ¤   ¤   }
--913e 000bf214d264010017c Page 6 of pgpBigNum.c
a19371 ¤   }
9967c5 ¤
47a25b ¤   if ( IsntNull( underflowPtr ) )
40375f ¤   ¤   *underflowPtr¤  = underflow;
201b52 ¤   ¤
af77c0 ¤   if ( bnError == -1 )
e517a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
0767c5 ¤
dbdeb7 ¤   return( err );
eeefe6 }
95af5a
47af5a
e8af5a
725a0c /* Return sign (-1, 0, +1) of a-b. ·a <=> b --> bnCmpQ(a, b) <=> 0 */
321e7c ¤   PGPInt32
a058bf PGPBigNumCompareQ(
fffea0 ¤   PGPBigNumRef¤   bn,
88c42f ¤   PGPUInt16¤  ¤   sm )
54bb36 {
27c722 ¤   PGPUInt32¤  result¤ = 0;
7567c5 ¤
f028e3 ¤   if ( pgpBigNumIsValid( bn ) )
70c7a1 ¤   {
9541be ¤   ¤   result¤ = bnCmpQ( &bn->bn, sm );
409371 ¤   }
c367c5 ¤
d74c6e ¤   return( result );
7defe6 }
1baf5a
12af5a
a8848c /* dest = src, where 0 <= src < 2^16. */
23c744 ¤   PGPError
b649cb PGPBigNumSetQ(
853cfd ¤   PGPBigNumRef¤   dest,
4af769 ¤   PGPUInt16¤  ¤   sm)
61bb36 {
c226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6967c5 ¤
7b5beb ¤   pgpValidateBigNum( dest );
b067c5 ¤
90b089 ¤   if ( IsBNError( bnSetQ( &dest->bn, sm ) ) )
e1c7a1 ¤   {
6717a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
bd9371 ¤   }
3467c5 ¤
46deb7 ¤   return( err );
3defe6 }
b1af5a
dbaf5a
a9f8c6 /* dest = bn + sm, where 0 <= sm < 2^16 */
24c744 ¤   PGPError
5dcbc8 PGPBigNumAddQ(
cffea0 ¤   PGPBigNumRef¤   bn,
f989d1 ¤   PGPUInt16¤  ¤   sm,
fd4245 ¤   PGPBigNumRef¤   dest)
60bb36 {
8c26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
ef67c5 ¤
f5489d ¤   pgpValidateBigNum( bn );
7e5beb ¤   pgpValidateBigNum( dest );
8467c5 ¤
a80f9a ¤   if ( IsBNError( bnAddQ( &dest->bn, sm ) ) )
47c7a1 ¤   {
2317a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
9a9371 ¤   }
9567c5 ¤
8fdeb7 ¤   return( err );
41efe6 }
75af5a
bcaf5a
cef8c6 /* dest = bn + sm, where 0 <= sm < 2^16 */
bfc744 ¤   PGPError
--54db 000c568f58c4010017c Page 7 of pgpBigNum.c
90754b PGPBigNumSubtractQ(
a3fea0 ¤   PGPBigNumRef¤   bn,
ef89d1 ¤   PGPUInt16¤  ¤   sm,
113cfd ¤   PGPBigNumRef¤   dest,
482ff3 ¤   PGPBoolean *¤   underflowPtr )
abbb36 {
2426d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
1bc8a5 ¤   int¤¤   ¤   bnError¤= 0;
89d7e4 ¤   PGPBoolean¤ underflow¤  = FALSE;
8a67c5 ¤
f4a25b ¤   if ( IsntNull( underflowPtr ) )
c2c24e ¤   ¤   *underflowPtr¤  = FALSE;
451b52 ¤   ¤
38489d ¤   pgpValidateBigNum( bn );
435beb ¤   pgpValidateBigNum( dest );
2baf5a
b3e797 ¤   if ( bn != dest )
4cc7a1 ¤   {
731b19 ¤   ¤   bnError¤= bnCopy( &dest->bn, &bn->bn );
362ff5 ¤   ¤   if ( IsBNError( bnError ) )
f5124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
ce9371 ¤   }
af67c5 ¤
7b2ca8 ¤   if ( IsntBNError( bnError ) )
49c7a1 ¤   {
2dfe2c ¤   ¤   bnError¤= bnSubQ( &dest->bn, sm );¤
632ff5 ¤   ¤   if ( IsBNError( bnError ) )
ef5b34 ¤   ¤   {
7edb99 ¤   ¤   ¤   underflow¤  = TRUE;
cf0fe4 ¤   ¤   }
359371 ¤   }
1f67c5 ¤
a4a25b ¤   if ( IsntNull( underflowPtr ) )
db375f ¤   ¤   *underflowPtr¤  = underflow;
de67c5 ¤
64deb7 ¤   return( err );
15efe6 }
4daf5a
d6af5a
c78dd9 /* Return sign (-1, 0, +1) of a-b. ·a <=> b --> bnCmp(a, b) <=> 0 */
6d1e7c ¤   PGPInt32
644f3c PGPBigNumCompare(
de9e4b ¤   PGPBigNumRef¤   lhs,
a584f9 ¤   PGPBigNumRef¤   rhs )
dcbb36 {
3b8d5a ¤   if ( pgpBigNumIsValid( lhs ) && pgpBigNumIsValid( rhs ) )
5fc7a1 ¤   {
d224d2 ¤   ¤   return( bnCmp( &lhs->bn, &rhs->bn ) );
d99371 ¤   }
0d67c5 ¤
1dea61 ¤   return( 0 );
4cefe6 }
edaf5a
19af5a
e8ec3b /* dest = src * src. ·dest may be the same as src, but it costs time. */
89c744 ¤   PGPError
8fff19 PGPBigNumSquare(
42da6d ¤   PGPBigNumRef¤   src,
ea4245 ¤   PGPBigNumRef¤   dest)
f6bb36 {
6926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3067c5 ¤
a103fc ¤   pgpValidateBigNum( src );
d65beb ¤   pgpValidateBigNum( dest );
8d67c5 ¤
daddd7 ¤   if ( IsBNError( bnSquare( &dest->bn, &src->bn ) ) )
08c7a1 ¤   {
8f17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
8e9371 ¤   }
ef67c5 ¤
c3deb7 ¤   return( err );
c5efe6 }
--2fcc 000816eed8e4010017c Page 8 of pgpBigNum.c
e0af5a
1aaf5a
9e2854 /* dest = a * b. ·dest may be the same as a or b, but it costs time. */
30c744 ¤   PGPError
cd2763 PGPBigNumMultiply(
0b9e4b ¤   PGPBigNumRef¤   lhs,
2e4bb3 ¤   PGPBigNumRef¤   rhs,
d74245 ¤   PGPBigNumRef¤   dest)
e1bb36 {
1c26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
0e67c5 ¤
ba703f ¤   pgpValidateBigNum( lhs );
8743d7 ¤   pgpValidateBigNum( rhs );
435beb ¤   pgpValidateBigNum( dest );
4467c5 ¤
c2788b ¤   if ( IsBNError( bnMul( &dest->bn, &lhs->bn, &rhs->bn ) ) )
12c7a1 ¤   {
ce17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
849371 ¤   }
ef67c5 ¤
a6deb7 ¤   return( err );
e5efe6 }
edaf5a
eaaf5a
b5804c /* dest = a * b, where 0 <= b < 2^16. ·dest and a may be the same. */
f6c744 ¤   PGPError
13f2a5 PGPBigNumMultiplyQ(
569e4b ¤   PGPBigNumRef¤   lhs,
f489d1 ¤   PGPUInt16¤  ¤   sm,
ab4245 ¤   PGPBigNumRef¤   dest)
7fbb36 {
a326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3d67c5 ¤
86703f ¤   pgpValidateBigNum( lhs );
b15beb ¤   pgpValidateBigNum( dest );
8867c5 ¤
1f53c8 ¤   if ( IsBNError( bnMulQ( &dest->bn, &lhs->bn, sm ) ) )
b4c7a1 ¤   {
fc17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
ca9371 ¤   }
8967c5 ¤
b8deb7 ¤   return( err );
79efe6 }
f8af5a
6faf5a
db38e5 /*
277a36 ·* q = n/d, r = n%d. ·r may be the same as n, but not d,
20eb22 ·* and q may not be the same as n or d.
04ad6f ·* re-entrancy issue: this temporarily modifies d, but restores
d6bf83 ·* it for return.
f5495d ·*/
08c744 ¤   PGPError
828d2c PGPBigNumDivide(
c35e65 ¤   PGPBigNumRef¤   numerator,
4c1625 ¤   PGPBigNumRef¤   denominator,
aa2201 ¤   PGPBigNumRef¤   quotient,
08e1c7 ¤   PGPBigNumRef¤   remainder)
24bb36 {
7e26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a067c5 ¤
0ae5d7 ¤   pgpValidateBigNum( numerator );
a6dbe8 ¤   pgpValidateBigNum( denominator );
7b4366 ¤   pgpValidateBigNum( quotient );
8e5ab3 ¤   pgpValidateBigNum( remainder );
0a67c5 ¤
7c493b ¤   if ( IsBNError( bnDivMod( &quotient->bn,
43c894 ¤   ¤   ¤   ¤   &remainder->bn, &numerator->bn, &denominator->bn) ) )
1fc7a1 ¤   {
7917a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
f39371 ¤   }
dc67c5 ¤
81deb7 ¤   return( err );
--b756 000766ef9674010017c Page 9 of pgpBigNum.c
7aefe6 }
46af5a
2e38e5 /*
0b65ee ·* dest = n % d. ·dest and src may be the same, but not dest and d.
edad6f ·* re-entrancy issue: this temporarily modifies d, but restores
bcbf83 ·* it for return.
54495d ·*/
24c744 ¤   PGPError
753efe PGPBigNumMod(
bb5e65 ¤   PGPBigNumRef¤   numerator,
cc1625 ¤   PGPBigNumRef¤   denominator,
b12ff4 ¤   PGPBigNumRef¤   dest )
90bb36 {
3526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a167c5 ¤
b0e5d7 ¤   pgpValidateBigNum( numerator );
1edbe8 ¤   pgpValidateBigNum( denominator );
715beb ¤   pgpValidateBigNum( dest );
1d67c5 ¤
b49186 ¤   if ( IsBNError( bnMod( &dest->bn, &numerator->bn, &denominator->bn) ) )
2dc7a1 ¤   {
4d17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
969371 ¤   }
dc67c5 ¤
b2deb7 ¤   return( err );
76efe6 }
5caf5a
5daf5a
fb5662 /* return src % d, where 0 <= d < 2^16. ·*/
b1c255 ¤   PGPUInt16
1abdd0 PGPBigNumModQ(
9b5e65 ¤   PGPBigNumRef¤   numerator,
b6d746 ¤   PGPUInt16¤  ¤   denominator )
ebbb36 {
cf7ec1 ¤   PGPUInt16¤  result¤ = 0;
7867c5 ¤
9d8355 ¤   if ( pgpBigNumIsValid( numerator ) && denominator != 0 )
f5c7a1 ¤   {
871c6b ¤   ¤   result¤ = bnModQ( &numerator->bn, denominator);
e79371 ¤   }
4767c5 ¤
b24c6e ¤   return( result );
4defe6 }
f0af5a
71af5a
0cb223 /* n = n^exp, modulo "mod" ··"mod" *must* be odd */
e7c744 ¤   PGPError
e2e93d PGPBigNumExpMod(
bbf322 ¤   PGPBigNumRef¤   n,
c2784d ¤   PGPBigNumRef¤   exponent,
67cbbe ¤   PGPBigNumRef¤   mod,
592ff4 ¤   PGPBigNumRef¤   dest )
2bbb36 {
3e26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6e67c5 ¤
a01c10 ¤   pgpValidateBigNum( n );
50517f ¤   pgpValidateBigNum( exponent );
0777a7 ¤   pgpValidateBigNum( mod );
155beb ¤   pgpValidateBigNum( dest );
893913 ¤   PGPValidateParam( dest != n && dest != exponent && dest != mod );
0967c5 ¤
28ec48 ¤   if ( IsBNError( bnExpMod( &dest->bn,
d50879 ¤   ¤   ¤   &n->bn, &exponent->bn, &mod->bn ) ) )
0ac7a1 ¤   {
d117a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
329371 ¤   }
f067c5 ¤
d8deb7 ¤   return( err );
dbefe6 }
8caf5a
fcaf5a
7638e5 /*
--5d12 000f9a293144010017c Page 10 of pgpBigNum.c
2d7329 ·* dest = n1^e1 * n2^e2, modulo "mod". ·"mod" *must* be odd.
aaf0f0 ·* dest may be the same as n1 or n2.
4b495d ·*/
e3c744 ¤   PGPError
d8cb61 PGPBigNumDoubleExpMod(
c0a0b0 ¤   PGPBigNumRef¤   n1,
033bca ¤   PGPBigNumRef¤   exponent1,
7c4fd4 ¤   PGPBigNumRef¤   n2,
6ed4ae ¤   PGPBigNumRef¤   exponent2,
8ecbbe ¤   PGPBigNumRef¤   mod,
de2ff4 ¤   PGPBigNumRef¤   dest )
1dbb36 {
2826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
b767c5 ¤
9266f7 ¤   pgpValidateBigNum( n1 );
f7fd4b ¤   pgpValidateBigNum( exponent1 );
e37b3b ¤   pgpValidateBigNum( n2 );
6ae087 ¤   pgpValidateBigNum( exponent2 );
6b77a7 ¤   pgpValidateBigNum( mod );
725beb ¤   pgpValidateBigNum( dest );
d6c095 ¤   PGPValidateParam( dest != n1 && dest != exponent1 &&
299f96 ¤   ¤   ¤   dest != n2 && dest != exponent2 && dest != mod );
0c67c5 ¤
7a67c5 ¤
3c7e89 ¤   if ( IsBNError( bnDoubleExpMod( &dest->bn,
7df4f3 ¤   ¤   ¤   &n1->bn, &exponent1->bn,
d1ced7 ¤   ¤   ¤   &n2->bn, &exponent2->bn,
fd9e2c ¤   ¤   ¤   &mod->bn ) ) )
ddc7a1 ¤   {
1017a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
089371 ¤   }
b367c5 ¤
52deb7 ¤   return( err );
08efe6 }
44af5a
c9af5a
7120ba /* dest = 2^exp, modulo "mod" ··"mod" *must* be odd */
19c744 ¤   PGPError
c62192 PGPBigNumTwoExpMod(·
44784d ¤   PGPBigNumRef¤   exponent,
20cbbe ¤   PGPBigNumRef¤   mod,
682ff4 ¤   PGPBigNumRef¤   dest )
31bb36 {
9626d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
4367c5 ¤
9b517f ¤   pgpValidateBigNum( exponent );
8c77a7 ¤   pgpValidateBigNum( mod );
2c5beb ¤   pgpValidateBigNum( dest );
c267c5 ¤
7c181e ¤   if ( IsBNError( bnTwoExpMod( &dest->bn, &exponent->bn, &mod->bn ) ) )
73c7a1 ¤   {
8e17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
449371 ¤   }
e467c5 ¤
4adeb7 ¤   return( err );
99efe6 }
cdaf5a
93af5a
0f5c5b /* dest = gcd(a, b). ·The inputs may overlap arbitrarily. */
46c744 ¤   PGPError
30690a PGPBigNumGCD(
7ab9e5 ¤   PGPBigNumRef¤   a,
6b5681 ¤   PGPBigNumRef¤   b,
b92ff4 ¤   PGPBigNumRef¤   dest )
48bb36 {
1826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
ef67c5 ¤
9376ec ¤   pgpValidateBigNum( a );
2f6b20 ¤   pgpValidateBigNum( b );
f35beb ¤   pgpValidateBigNum( dest );
2067c5 ¤
f917b2 ¤   if ( IsBNError( bnGcd( &dest->bn, &a->bn, &b->bn ) ) )
--4485 00015efe0c04010017c Page 11 of pgpBigNum.c
f7c7a1 ¤   {
0717a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
b49371 ¤   }
2167c5 ¤
eadeb7 ¤   return( err );
ddefe6 }
22af5a
19af5a
ad1893 /* dest = src^-1, modulo "mod". ·dest may be the same as src. */
ccc744 ¤   PGPError
673f78 PGPBigNumInv(
f29d75 ¤   PGPBigNumRef¤   src,·
eacbbe ¤   PGPBigNumRef¤   mod,
f62ff4 ¤   PGPBigNumRef¤   dest )
b4bb36 {
0d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
f6c8a5 ¤   int¤¤   ¤   bnError¤= 0;
7467c5 ¤
d303fc ¤   pgpValidateBigNum( src );
d077a7 ¤   pgpValidateBigNum( mod );
045beb ¤   pgpValidateBigNum( dest );
6467c5 ¤
bdc152 ¤   bnError¤= bnInv( &dest->bn, &src->bn, &mod->bn );
d9a409 ¤   if ( IsBNError( bnError ) )
d1c7a1 ¤   {
5fde06 ¤   ¤   if ( bnError == 1 )
aed61f ¤   ¤   ¤   err¤ = kPGPError_BigNumNoInverse;
580e1d ¤   ¤   else
67124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
c29371 ¤   }
eeaf5a
06deb7 ¤   return( err );
f9efe6 }
51af5a
30af5a
2faf5a
dc6138 /* Shift dest left "amt" places */
84c744 ¤   PGPError
98a029 PGPBigNumLeftShift(
193cfd ¤   PGPBigNumRef¤   dest,
f3a82c ¤   PGPUInt32¤  ¤   numBits )
8fbb36 {
1a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5867c5 ¤
f85beb ¤   pgpValidateBigNum( dest );
3b67c5 ¤
100ea9 ¤   if ( IsBNError( bnLShift( &dest->bn, numBits ) ) )
0fc7a1 ¤   {
9617a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
aa9371 ¤   }
aa67c5 ¤
b2deb7 ¤   return( err );
edefe6 }
d8af5a
aeaf5a
cf70f6 /* Shift dest right "amt" places, discarding low-order bits */
6fc744 ¤   PGPError
fd5256 PGPBigNumRightShift(
be3cfd ¤   PGPBigNumRef¤   dest,
9ca82c ¤   PGPUInt32¤  ¤   numBits )
70bb36 {
d726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7567c5 ¤
925beb ¤   pgpValidateBigNum( dest );
7567c5 ¤
1fba02 ¤   bnRShift( &dest->bn, numBits );
9b67c5 ¤
4bdeb7 ¤   return( err );
8defe6 }
b6af5a
20af5a
154dd1 /* right shift all low order 0-bits, return number of bits shifted */
--66ac 0018c08078a4010017c Page 12 of pgpBigNum.c
fbc255 ¤   PGPUInt16
07dc5c PGPBigNumMakeOdd( PGPBigNumRef¤ dest )
0cbb36 {
fedc43 ¤   PGPUInt16¤  numBits¤= 0;
c867c5 ¤
64e9e7 ¤   if ( pgpBigNumIsValid( dest ) )
e0c7a1 ¤   {
de5aca ¤   ¤   numBits¤= bnMakeOdd( &dest->bn );
549371 ¤   }
e467c5 ¤
63cf78 ¤   return( numBits );
ecefe6 }
b2af5a
81af5a
7eaf5a
bdaf5a
a4af5a
a6af5a
adaf5a
ceaf5a
70af5a
d6af5a
66af5a
05af5a
eaaf5a
ccaf5a
2caf5a
d2af5a
7daf5a
acaf5a
cdaf5a
bbaf5a
7caf5a
9aaf5a
80af5a
6daf5a
06af5a
e7af5a
d0af5a
97af5a
dbaf5a
03af5a
e5af5a
e2af5a
e5af5a
41af5a
db7e4d /*__Editor_settings____
07af5a
454126 ¤   Local Variables:
267b17 ¤   tab-width: 4
260e6c ¤   End:
1b5f8c ¤   vi: ts=4 sw=4
d79e9b ¤   vim: si
8cd062 _____________________*/
--cce2 001770fb5234010017d Page 1 of Makefile.in
5ea601 #
1c22bf # priv/crypto/pipe/
daa601 #
80eaea # $Id: Makefile.in,v 1.2 1997/05/04 10:30:06 mhw Exp $
15a601 #
4eaf5a
f6cf54 SUBDIRS=utils file sig crypt text parser
921879 LIBDONE=utils/DONE file/DONE sig/DONE crypt/DONE text/DONE parser/DONE
40af5a
08211d all:: LIBDONE
77af5a
--c6c9 0014d2d85bb4010017e Page 1 of Makefile.in
5ea601 #
ef53c3 # priv/crypto/pipe/crypt/
dba601 #
56eaea # $Id: Makefile.in,v 1.2 1997/05/04 10:30:06 mhw Exp $
b6a601 #
bcaf5a
8487db OBJS=¤  pgpCiphrMod.o pgpConvMod.o pgpMakePKE.o pgpPKEMod.o
02f85f PRIVHDRS= pgpCiphrMod.h pgpConvMod.h pgpPKEMod.h
82af5a
9fb7a3 all:: DONE
4daf5a
--8b42 000b8011ba64010017f Page 1 of pgpCiphrMod.c
bc38e5 /*
4f3c82 ·* pgpCiphrMod.c -- A module to perform Block Cipher encryption and Decryption
3f775e ·*
687ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
14775e ·*
d55d0b ·* $Id: pgpCiphrMod.c,v 1.29 1997/12/12 01:13:54 heller Exp $
da495d ·*/
1daf5a
85e2ff #include "pgpConfig.h"
11af5a
e6feb2 #include <stdio.h>
1a324c #include <string.h>
f1af5a
dba146 #include "pgpDebug.h"
6277c6 #include "pgpAddHdr.h"
33d9c5 #include "pgpCiphrMod.h"
5f9c38 #include "pgpPktByte.h"
dd0859 #include "pgpCFB.h"
b90d08 #include "pgpMem.h"
1a2ece #include "pgpPipeline.h"
d8d11f #include "pgpUsuals.h"
4ec26c #include "pgpContext.h"
c3af5a
0aec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
c9e233 #define kPGPCipherModBufSize¤   16384
d9db21 #else
3c5848 #define kPGPCipherModBufSize¤   BUFSIZ
127454 #endif
91af5a
ceb77f #define CIPHERMODMAGIC¤ 0x0c1fec0de
a1cd79 #define CIPHERMOD_DECRYPT 0
54514b #define CIPHERMOD_ENCRYPT 1
e9af5a
347b9b typedef PGPError¤   (*ProgressHook)( size_t len );
47af5a
17d2b7 typedef struct CiphrModContext {
218b60 ¤   PGPPipeline¤pipe;
c567c5 ¤
d34230 ¤   PGPByte buffer[kPGPCipherModBufSize];
b3c98f ¤   PGPByte *bufptr;
b0c822 ¤   size_t buflen;
8375b0 ¤   PGPPipeline *tail;
77cfbe ¤   PGPCFBContext *cfb;
7f7966 ¤   ProgressHook¤   progress;
c3c8ef ¤   PGPByte encrypt;
b6cf06 ¤   DEBUG_STRUCT_CONSTRUCTOR( CiphrModContext )
612714 } CiphrModContext;
a9af5a
49f1ae static PGPError
f8df18 DoFlush (CiphrModContext *context)
f6bb36 {
7c5b01 ¤   PGPError¤   error = kPGPError_NoErr;
9b6c75 ¤   size_t retlen;
36af5a
1e16d3 ¤   /* Try to flush anything that we have buffered */
8549b8 ¤   while (context->buflen) {
5e88b9 ¤   ¤   retlen = context->tail->write (context->tail,
c3d239 ¤   ¤   ¤   ¤   ¤   ·······context->bufptr,
b3ee65 ¤   ¤   ¤   ¤   ¤   ·······context->buflen,
5448b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
14e166 ¤   ¤   context->buflen -= retlen;
809c96 ¤   ¤   pgpClearMemory (context->bufptr, retlen);
0d060f ¤   ¤   context->bufptr += retlen;
58e3c2 ¤   ¤   if (error)
253b5b ¤   ¤   ¤   return error;
529371 ¤   }
11c674 ¤   return error;
1eefe6 }
57af5a
76f1ae static PGPError
d8d02e Flush (PGPPipeline *myself)
b8bb36 {
--98a3 000104996164010017f Page 2 of pgpCiphrMod.c
17a0d8 ¤   CiphrModContext *context;
8387a6 ¤   PGPError¤   error;
e6af5a
dc29be ¤   pgpAssert (myself);
7172e1 ¤   pgpAssert (myself->magic == CIPHERMODMAGIC);
b6af5a
c273c7 ¤   context = (CiphrModContext *)myself->priv;
d1d30a ¤   pgpAssert (context);
84ebf4 ¤   pgpAssert (context->tail);
1faf5a
3f63fd ¤   error = DoFlush (context);
200161 ¤   if (error)
60fcee ¤   ¤   return error;
93af5a
749819 ¤   return context->tail->flush (context->tail);
dcefe6 }
e2af5a
765d09 static size_t
18f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
e0bb36 {
9ba0d8 ¤   CiphrModContext *context;
c2a371 ¤   size_t written = 0;
25af5a
8e29be ¤   pgpAssert (myself);
3372e1 ¤   pgpAssert (myself->magic == CIPHERMODMAGIC);
ef4866 ¤   pgpAssert (error);
08af5a
9d73c7 ¤   context = (CiphrModContext *)myself->priv;
8fd30a ¤   pgpAssert (context);
1bebf4 ¤   pgpAssert (context->tail);
21af5a
db43ab ¤   do {
a28f85 ¤   ¤   *error = DoFlush (context);
8dcf31 ¤   ¤   if (*error)
97ab0f ¤   ¤   ¤   return written;
dbaf5a
9e1b17 ¤   ¤   /*
f24511 ¤   ¤   ·* Now that we dont have anything buffered, bring in more
c23604 ¤   ¤   ·* data from the passed-in buffer, process it, and buffer
344169 ¤   ¤   ·* that to write out.
119de3 ¤   ¤   ·*/
83fe69 ¤   ¤   context->bufptr = context->buffer;
8de6db ¤   ¤   context->buflen = pgpMin (size, sizeof (context->buffer));
f8af5a
a848f4 ¤   ¤   /* Tell user how many bytes we're doing, allow him to interrupt */
0785f6 ¤   ¤   if (context->progress && context->buflen)
055b34 ¤   ¤   {
c5a5c3 ¤   ¤   ¤   if (context->progress(context->buflen) < 0)
cbf776 ¤   ¤   ¤   {
9d97ea ¤   ¤   ¤   ¤   /* User requested interruption */
1de8fd ¤   ¤   ¤   ¤   *error = kPGPError_UserAbort;
bd0651 ¤   ¤   ¤   ¤   return written;
52a3a6 ¤   ¤   ¤   }
d60fe4 ¤   ¤   }
e2af5a
cdef4b ¤   ¤   if (context->buflen > 0) {
24733c ¤   ¤   ¤   if (context->encrypt)
a14dd5 ¤   ¤   ¤   ¤   PGPCFBEncrypt (context->cfb, (PGPByte *)buf,
c406be ¤   ¤   ¤   ¤   ¤   ¤   ···context->buflen, context->buffer );
67bb8c ¤   ¤   ¤   else
d98e67 ¤   ¤   ¤   ¤   PGPCFBDecrypt (context->cfb, (PGPByte *)buf,
f706be ¤   ¤   ¤   ¤   ¤   ¤   ···context->buflen, context->buffer );
770fe4 ¤   ¤   }
64bdd6 ¤   ¤   buf += context->buflen;
a577c4 ¤   ¤   size -= context->buflen;
acaa82 ¤   ¤   written += context->buflen;
11af5a
be64ca ¤   } while (context->buflen > 0);
80c130 ¤   /* Continue until we have nothing buffered */
9aaf5a
e5e765 ¤   return written;¤
10efe6 }
--cebe 00052ccdb164010017f Page 3 of pgpCiphrMod.c
e0af5a
c1f1ae static PGPError
6213c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
4ab0b1 ¤   ··PGPByte const *string, size_t size)
91bb36 {
a0a0d8 ¤   CiphrModContext *context;
a387a6 ¤   PGPError¤   error;
a1af5a
fb29be ¤   pgpAssert (myself);
fb72e1 ¤   pgpAssert (myself->magic == CIPHERMODMAGIC);
49af5a
a073c7 ¤   context = (CiphrModContext *)myself->priv;
29d30a ¤   pgpAssert (context);
6aebf4 ¤   pgpAssert (context->tail);
57af5a
9063fd ¤   error = DoFlush (context);
780161 ¤   if (error)
7bfcee ¤   ¤   return error;
89af5a
d70df2 ¤   return context->tail->annotate (context->tail, origin, type,
6f3153 ¤   ¤   ¤   ¤   ¤   string, size);
ffefe6 }
bcaf5a
b5f1ae static PGPError
584b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
85bb36 {
b2a0d8 ¤   CiphrModContext *context;
f287a6 ¤   PGPError¤   error;
bdaf5a
f529be ¤   pgpAssert (myself);
2c72e1 ¤   pgpAssert (myself->magic == CIPHERMODMAGIC);
a6af5a
6873c7 ¤   context = (CiphrModContext *)myself->priv;
4bd30a ¤   pgpAssert (context);
a7ebf4 ¤   pgpAssert (context->tail);
d0af5a
2263fd ¤   error = DoFlush (context);
910161 ¤   if (error)
86fcee ¤   ¤   return error;
b5af5a
b2e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
77efe6 }
9caf5a
fbf1ae static PGPError
55c7e1 Teardown (PGPPipeline *myself)
ecbb36 {
eea0d8 ¤   CiphrModContext *context;
ffe9fa ¤   PGPContextRef¤  cdkContext;
1867c5 ¤
d53982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
37696e ¤   cdkContext¤ = myself->cdkContext;
05af5a
6d29be ¤   pgpAssert (myself);
ac72e1 ¤   pgpAssert (myself->magic == CIPHERMODMAGIC);
a9af5a
4073c7 ¤   context = (CiphrModContext *)myself->priv;
92d30a ¤   pgpAssert (context);
19af5a
3bcb05 ¤   if (context->tail)
931e8a ¤   ¤   context->tail->teardown (context->tail);
e9af5a
e9c8e1 ¤   PGPFreeCFBContext (context->cfb);
0567c5 ¤
6d3736 ¤   pgpClearMemory( context, ·sizeof (*context));
5cfa6e ¤   pgpContextMemFree( cdkContext, context);
a667c5 ¤
06151e ¤   return kPGPError_NoErr;
abefe6 }
bbaf5a
cd41cd PGPPipeline **
0620fd pgpCipherModDecryptCreate (
523163 ¤   PGPContextRef¤  cdkContext,
--0576 0003c03453f4010017f Page 4 of pgpCiphrMod.c
148941 ¤   PGPPipeline **head,
821727 ¤   PGPCFBContext *cfb,
84481c ¤   PGPEnv const *env)
aabb36 {
320df0 ¤   PGPPipeline *mod;
25a0d8 ¤   CiphrModContext *context;
fbaf5a
306b7b ¤   pgpAssert (cfb);
37af5a
d8c6f5 ¤   if (!head) {
22f65d ¤   ¤   PGPFreeCFBContext (cfb);
117ed2 ¤   ¤   return NULL;
2e9371 ¤   }
d9af5a
bcb1a1 ¤   context = (CiphrModContext *)pgpContextMemAlloc( cdkContext,
ded680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
3afa17 ¤   if (!context) {
9bf65d ¤   ¤   PGPFreeCFBContext (cfb);
0c7ed2 ¤   ¤   return NULL;
b69371 ¤   }
2e9228 ¤   mod = &context->pipe;
f4af5a
9178bc ¤   mod->magic = CIPHERMODMAGIC;
571f83 ¤   mod->write = Write;
f3ac4e ¤   mod->flush = Flush;
120aaf ¤   mod->sizeAdvise = SizeAdvise;
73d3a2 ¤   mod->annotate = Annotate;
0396de ¤   mod->teardown = Teardown;
3f489a ¤   mod->name = "Cipher Decryption Module";
de01ea ¤   mod->priv = context;
0ba99e ¤   mod->cdkContext¤= cdkContext;
b4af5a
2ff025 ¤   context->bufptr = context->buffer;
813ffa ¤   context->cfb = cfb;
9b4787 ¤   context->encrypt = CIPHERMOD_DECRYPT;
8a4b53 ¤   context->progress¤  = (ProgressHook)
173294 ¤   ¤   ¤   pgpenvGetPointer (env, PGPENV_ENCRYPTIONCALLBACK, NULL);
aaaf5a
2b65ad ¤   context->tail = *head;
842d11 ¤   *head = mod;
af7fa2 ¤   return &context->tail;
5befe6 }
c7af5a
be41cd PGPPipeline **
c827e1 pgpCipherModEncryptCreate (
013163 ¤   PGPContextRef¤  cdkContext,
4c0f32 ¤   PGPPipeline **head, PgpVersion version,
35fc19 ¤   PGPFifoDesc const *fd,
a11727 ¤   PGPCFBContext *cfb,
0dd4b9 ¤   PGPByte const iv[IVLEN-2], PGPEnv const *env)
63bb36 {
bc30ee ¤   PGPPipeline *mod, **tail;
0aa0d8 ¤   CiphrModContext *context;
3d5a1d ¤   PGPByte enc_iv[IVLEN];
19af5a
436b7b ¤   pgpAssert (cfb);
73af5a
4cbb3d ¤   if (!head)
c37ed2 ¤   ¤   return NULL;
feaf5a
73b1a1 ¤   context = (CiphrModContext *)pgpContextMemAlloc( cdkContext,
afd680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
fa1ea4 ¤   if (!context)
e07ed2 ¤   ¤   return NULL;
f39228 ¤   mod = &context->pipe;
c3af5a
bc78bc ¤   mod->magic = CIPHERMODMAGIC;
2e1f83 ¤   mod->write = Write;
d3ac4e ¤   mod->flush = Flush;
8e0aaf ¤   mod->sizeAdvise = SizeAdvise;
6cd3a2 ¤   mod->annotate = Annotate;
3c96de ¤   mod->teardown = Teardown;
--97df 00137bb849a4010017f Page 5 of pgpCiphrMod.c
04900a ¤   mod->name = "Cipher Encryption Module";
da01ea ¤   mod->priv = context;
9ba99e ¤   mod->cdkContext¤= cdkContext;
c8af5a
00f025 ¤   context->bufptr = context->buffer;
a23ffa ¤   context->cfb = cfb;
c6ad16 ¤   context->encrypt = CIPHERMOD_ENCRYPT;
a44b53 ¤   context->progress¤  = (ProgressHook)
121bf1 ¤   ¤   ¤   pgpenvGetPointer (env, PGPENV_ENCRYPTIONCALLBACK, NULL );
d5af5a
38be9d ¤   /* Splice in the module */
4765ad ¤   context->tail = *head;
5bc615 ¤   tail = &context->tail;
24af5a
2cd4dd ¤   /* Created the encrypted IV */
0c159d ¤   memcpy (enc_iv, iv, IVLEN-2);
9239c0 ¤   memcpy (enc_iv+IVLEN-2, enc_iv+IVLEN-4, 2);
0f59d6 ¤   PGPCFBEncrypt (cfb, enc_iv, IVLEN, enc_iv);
f21dac ¤   PGPCFBSync (cfb);
b7af5a
37e8d6 ¤   tail = pgpAddHeaderCreate ( cdkContext, tail,
9ab35f ¤   ¤   version, fd, PKTBYTE_CONVENTIONAL, 0, enc_iv, IVLEN);
1a67c5 ¤
2c84e6 ¤   pgpClearMemory (enc_iv, IVLEN);
e9b2e1 ¤   if (!tail) {
1aa8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
927ed2 ¤   ¤   return NULL;
309371 ¤   }
1eaf5a
f22d11 ¤   *head = mod;
b9ca79 ¤   return tail;
37efe6 }
--4f4c 0014c510f3c40100180 Page 1 of pgpCiphrMod.h
bc38e5 /*
48acc9 ·* pgpCiphrMod.h -- secret-key cipher module
57775e ·*
597ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
45775e ·*
10e8de ·* $Id: pgpCiphrMod.h,v 1.13 1997/10/06 18:00:55 lloyd Exp $
a3495d ·*/
e0af5a
d687f8 #ifndef Included_pgpCiphrMod_h
ddf00b #define Included_pgpCiphrMod_h
38af5a
4ad11f #include "pgpUsuals.h"
0e0d6d #include "pgpEnv.h"
19af5a
9e99c6 PGP_BEGIN_C_DECLARATIONS
13af5a
8faf5a
9d38e5 /*
f002aa ·* Create a Cfb Decryption Module using the passed-in PGPCFBContext.
b4a28f ·* This module assumes control of the PGPCFBContext and
c3944f ·* will clear/free it upon teardown.
24495d ·*/
9ff481 PGPPipeline ·**
4349c4 pgpCipherModDecryptCreate ( PGPContextRef¤  cdkContext,
9c7f24 ¤   ¤   PGPPipeline **head,
8d3137 ¤   ·¤  PGPCFBContext *cfb, PGPEnv const *env);
efaf5a
3d38e5 /*
20a1cc ·* Create a Cfb Encryption Module using the passed-in PGPCFBContext.
303e05 ·* The user must pass in an 8-byte iv, which will be encrypted into the
5c39e1 ·* stream. ·The Cipher Module assumes control of the PGPCFBContext·
3fc8ab ·* and will clear/free it upon teardown.
8a495d ·*/
65f481 PGPPipeline ·**
af1fdc pgpCipherModEncryptCreate ( PGPContextRef¤  cdkContext,
bbd48f ¤   ¤   ¤   ¤   PGPPipeline **head, PgpVersion version,
637129 ¤   ¤   ¤   ···PGPFifoDesc const *fd,
b94c85 ¤   ¤   ¤   ···PGPCFBContext *cfb,
9bfaa8 ¤   ¤   ¤   ···PGPByte const iv[IVLEN-2],
548127 ¤   ¤   ¤   ···PGPEnv const *env);
faaf5a
011254 PGP_END_C_DECLARATIONS
aaaf5a
4c7665 #endif /* Included_pgpCiphrMod_h */
--ef87 00068dadd7e40100181 Page 1 of pgpConvMod.c
bc38e5 /*
dcdc8b ·* pgpConvMod.c -- Convetional Encryption Module
4b775e ·*
2cb4c8 ·* Uses the cipher module to encrypt a message; this will output the
251500 ·* appropriate PGP headers (ESK-type) packets associated with the
8f9a8f ·* requested encryption type and pass phrase string.
c8775e ·*
137ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
e8775e ·*
80fd7a ·* $Id: pgpConvMod.c,v 1.32 1998/06/11 18:27:48 hal Exp $
c8495d ·*/
4eaf5a
b0e2ff #include "pgpConfig.h"
8faf5a
77feb2 #include <stdio.h>
57324c #include <string.h>
1faf5a
cb9e4d #include "pgpConvMod.h"
5b9c38 #include "pgpPktByte.h"
731e2d #include "pgpCFBPriv.h"
010e2f #include "pgpSymmetricCipherPriv.h"
2727ba #include "pgpConvKey.h"
20421a #include "pgpJoin.h"
a00d08 #include "pgpMem.h"
742f8d #include "pgpErrors.h"
c42ece #include "pgpPipeline.h"
b35579 #include "pgpStr2Key.h"
05c26c #include "pgpContext.h"
5eaf5a
1438e5 /*
afdcb9 ·* A conventional ESK has the following format:
ca465f ·*¤ <packet header> (type, llen, length)
5bfeff ·*¤ version[1]
42b91c ·*¤ cipher[1]
8cf738 ·*¤ StringToKey Object[x]
5cd7aa ·*¤ ESK (optional)[y]
7b495d ·*/
78beb7 static int
8bd27a addConvESKs (PGPPipeline *join, PgpVersion version, PGPByte cipher,
9346d4 ¤   ·····PGPStringToKey const *s2k,
8c8273 ¤   ·····PGPConvKey const *convkeys,
670308 ¤   ·····PGPByte const *session)
43bb36 {
661991 ¤   PGPStringToKey const *sToK;
748016 ¤   PGPCipherVTBL const *¤  sc = NULL;
da338a ¤   PGPCipherVTBL const *¤  ¤   c =
fee950 ¤   ¤   ¤   pgpCipherGetVTBL ( (PGPCipherAlgorithm)cipher);
1a1f93 ¤   PGPCFBContext *cfb = NULL;
497ae3 ¤   size_t esklen, last = 0;
271672 ¤   PGPByte *buf = NULL, *ptr;
d90c0e ¤   PGPByte *key = NULL;
15d6e7 ¤   int err = kPGPError_NoErr;
6c18f8 ¤   PGPContextRef¤  ¤   cdkContext¤ = NULL;
27dc05 ¤   PGPMemoryMgrRef¤¤   memoryMgr¤  = NULL;
0caf5a
03b658 ¤   pgpAssertAddrValid( join, PGPPipeline );
129741 ¤   cdkContext¤ = join->cdkContext;
5a1c1f ¤   memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
58af5a
9e3b14 ¤   pgpAssert( pgpContextIsValid( cdkContext ) );
0f67c5 ¤
98272b ¤   if (!c)
1262b5 ¤   ¤   return kPGPError_BadParams;
09af5a
cdfb0f ¤   if (session) {
e3f3dc ¤   ¤   sc = pgpCipherGetVTBL ((PGPCipherAlgorithm)*session);
ce3acb ¤   ¤   if (!sc)
90a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
4f947b ¤   ¤   cfb = pgpCFBCreate ( memoryMgr, c);
872b23 ¤   ¤   if (!cfb)
0a7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
68c47b ¤   ¤   key = (PGPByte *)pgpContextMemAlloc( cdkContext,
--8905 000af21e82840100181 Page 2 of pgpConvMod.c
d59dd9 ¤   ¤   ¤   c->keysize, kPGPMemoryMgrFlags_Clear );
7f7cc0 ¤   ¤   if (!key) {
2bcb35 ¤   ¤   ¤   PGPFreeCFBContext (cfb);
6d7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
f60fe4 ¤   ¤   }
269371 ¤   }
aeaf5a
ce2d9b ¤   for (; convkeys; convkeys = convkeys->next) {
54a6b7 ¤   ¤   sToK = (convkeys->stringToKey ? convkeys->stringToKey : s2k);
a5fde7 ¤   ¤   esklen = 1 + 1 + sToK->encodelen;
f2d1fb ¤   ¤   if (sc)
6848c5 ¤   ¤   ¤   esklen += sc->keysize + 1;
21be6b ¤   ¤   if (esklen + 3 > last) {
6b8e78 ¤   ¤   ¤   if( IsNull( buf ) ) {
398840 ¤   ¤   ¤   ¤   buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
ed7957 ¤   ¤   ¤   ¤   ¤   ¤   ¤   esklen + 3, 0 );
432fee ¤   ¤   ¤   ¤   if( IsNull( buf ) )
2aed29 ¤   ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
59042d ¤   ¤   ¤   } else {
d2b75f ¤   ¤   ¤   ¤   err = pgpContextMemRealloc ( cdkContext,
1897c6 ¤   ¤   ¤   ¤   ¤   ¤   (void **)&buf, esklen + 3, 0 );
bca3a6 ¤   ¤   ¤   }
7a8d20 ¤   ¤   ¤   if ( IsPGPError( err ) ) {
71ce55 ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, buf );
46bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
d3f622 ¤   ¤   ¤   ¤   break;
95a3a6 ¤   ¤   ¤   }
0070f5 ¤   ¤   ¤   last = esklen + 3;
b20fe4 ¤   ¤   }
ce13fb ¤   ¤   if (esklen > 8192) {
a84a7e ¤   ¤   ¤   err = kPGPError_BadSessionKeySize;
fdcdcb ¤   ¤   ¤   break;
ed0fe4 ¤   ¤   }
abfdd8 ¤   ¤   ptr = buf+3;
ab9f4d ¤   ¤   *ptr++ = (PGPByte) version;
54bfa7 ¤   ¤   *ptr++ = cipher;
266a94 ¤   ¤   memcpy (ptr, sToK->encoding, sToK->encodelen);
1e754e ¤   ¤   ptr += sToK->encodelen;
681cae ¤   ¤   /* Add optional ESK */
7294d3 ¤   ¤   if (sc) {
6a28e6 ¤   ¤   ¤   pgpStringToKey (sToK, convkeys->pass,
d0c02e ¤   ¤   ¤   ¤   ¤   convkeys->passlen, key, c->keysize);
b214fc ¤   ¤   ¤   PGPInitCFB (cfb, key, NULL);
b15117 ¤   ¤   ¤   pgpClearMemory( key, ·c->keysize);
a101d8 ¤   ¤   ¤   PGPCFBEncrypt (cfb, session, sc->keysize+1, ptr );
406f04 ¤   ¤   ¤   pgpCFBWipe (cfb);
02f425 ¤   ¤   ¤   ptr += sc->keysize + 1;
d10fe4 ¤   ¤   }
d5af5a
ad8683 ¤   ¤   /* Create the ConvESK Packet */
4e47e4 ¤   ¤   if (PKTLEN_ONE_BYTE(esklen)) {
a8ec7c ¤   ¤   ¤   buf[1] = PKTBYTE_BUILD_NEW (PKTBYTE_CONVESK);
98b527 ¤   ¤   ¤   buf[2] = PKTLEN_1BYTE(esklen);
cbf9b1 ¤   ¤   ¤   ptr = buf+1;
9c8510 ¤   ¤   ¤   esklen += 2;
bb45a6 ¤   ¤   } else {
594ed0 ¤   ¤   ¤   buf[0] = PKTBYTE_BUILD_NEW (PKTBYTE_CONVESK);
a9ae76 ¤   ¤   ¤   buf[1] = PKTLEN_BYTE0(esklen);
380d3f ¤   ¤   ¤   buf[2] = PKTLEN_BYTE1(esklen);
9e6a76 ¤   ¤   ¤   ptr = buf;
d4dfcc ¤   ¤   ¤   esklen += 3;
9a0fe4 ¤   ¤   }
59af5a
225af5 ¤   ¤   if (pgpJoinBuffer (join, ptr, esklen) != esklen) {
01b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
5ccdcb ¤   ¤   ¤   break;
6d0fe4 ¤   ¤   }
709371 ¤   }
c415fc ¤   if (key) {
671221 ¤   ¤   pgpClearMemory( key, ·c->keysize+1);
dee29a ¤   ¤   pgpContextMemFree( cdkContext, key);
af9371 ¤   }
--ba76 001d21d819740100181 Page 3 of pgpConvMod.c
edc8c9 ¤   if (buf) {
e60bce ¤   ¤   pgpClearMemory( buf, ·last);
ac02f1 ¤   ¤   pgpContextMemFree( cdkContext, buf);
5c9371 ¤   }
39afda ¤   if (cfb)
31f65d ¤   ¤   PGPFreeCFBContext (cfb);
c0af5a
6d5ea8 ¤   return err;
8defe6 }
11af5a
b341cd PGPPipeline **
253fc0 pgpConvModCreate (
dffdf9 ¤   PGPContextRef cdkContext,
ba0f32 ¤   PGPPipeline **head, PgpVersion version,
0ffc19 ¤   PGPFifoDesc const *fd,
0ae1cb ¤   PGPStringToKey const *s2k,
8f6aa2 ¤   PGPConvKey const *convkeys,
b1f2d7 ¤   PGPByte cipher, PGPByte const *session)
e0bb36 {
d799c7 ¤   PGPPipeline *join = NULL, **tail = &join;
46af5a
683321 ¤   tail = pgpJoinCreate ( cdkContext, &join, fd);
38c673 ¤   if (!tail)
2d7ed2 ¤   ¤   return NULL;
e3af5a
8726a3 ¤   /* Add the conventional ESKs here */
a5dceb ¤   if (version > PGPVERSION_3) {
58858b ¤   ¤   if (addConvESKs (join, version, cipher, s2k, convkeys,
586a3e ¤   ¤   ¤   ¤   ·session)) {
5d6206 ¤   ¤   ¤   join->teardown (join);
5ccf03 ¤   ¤   ¤   return NULL;
000fe4 ¤   ¤   }
779371 ¤   }
afaf5a
bdcb30 ¤   /* Splice in the join module */
7cea64 ¤   *tail = *head;
292c05 ¤   *head = join;
deca79 ¤   return tail;
d2efe6 }
--b749 0010943430040100182 Page 1 of pgpConvMod.h
bc38e5 /*
8e71c8 ·* pgpConvMod.h -- Conventional Encryption Module
e5775e ·*
9b5a45 ·* Written By:¤ Derek Atkins <warlord@MIT.EDU>
cf775e ·*
a6b02c ·* $Id: pgpConvMod.h,v 1.9 1997/06/25 19:39:59 lloyd Exp $
3c495d ·*/
6aaf5a
204cd8 #ifndef Included_pgpConvMod_h
a618ec #define Included_pgpConvMod_h
26af5a
b0adb8 #include "pgpOpaqueStructs.h"
0de82c #include "pgpPubTypes.h"
edd11f #include "pgpUsuals.h"
1aaf5a
0c99c6 PGP_BEGIN_C_DECLARATIONS
b1af5a
51af5a
0ef481 PGPPipeline ·**
7efcbb pgpConvModCreate ( PGPContextRef cdkContext,
a71762 ¤   ¤   PGPPipeline **head, PgpVersion version,
ce8def ¤   ¤   ··PGPFifoDesc const *fd,
62077e ¤   ¤   ··PGPStringToKey const *s2k,
718862 ¤   ¤   ··PGPConvKey const *convkeys,
15d7b8 ¤   ¤   ··PGPByte cipher, PGPByte const *session);
15af5a
5e1254 PGP_END_C_DECLARATIONS
acaf5a
0975b1 #endif /* Included_pgpConvMod_h */
--80d8 0018f3603cc40100183 Page 1 of pgpMakePKE.c
bc38e5 /*
bec073 ·* $Id: pgpMakePKE.c,v 1.11 1998/06/11 18:27:49 hal Exp $
3e495d ·*/
23af5a
69e2ff #include "pgpConfig.h"
a1324c #include <string.h>
1aaf5a
f3a146 #include "pgpDebug.h"
a99044 #include "pgpMakePKE.h"
632f8d #include "pgpErrors.h"
f5cdc2 #include "pgpPubKey.h"
97d11f #include "pgpUsuals.h"
9aaf5a
bbbb78 /* The maximum size of the PKE */
a944d2 size_t
95fd3a makePkeMaxSize (PGPPubKey const *pub, PgpVersion version)
e9bb36 {
4af748 ¤   /* version + keyID + type +bit count + mpi */
d89a46 ¤   (void)version;
c55b35 ¤   return 10 + pgpPubKeyMaxesk(pub, kPGPPublicKeyMessageFormat_PGP);
e5efe6 }
2daf5a
4f38e5 /*
f207de ·* Given a buffer of at least "makePkeMaxSize" bytes, make a PKE
e8e001 ·* into it and return the size of the PKE, or <0.
b7775e ·*
96f9f7 ·* Format of PKE packets:
9c775e ·*
d1eb47 ·* ·····Offset¤ Length¤ Meaning
7ddb37 ·* ······0¤ 1¤  Version byte (=2).
ed7e98 ·* ······1¤ 8¤  KeyID
d46fd5 ·*¤ ·9¤ 1¤  PK algorithm (1 = RSA)
d861b8 ·* ·····10¤ 2+?¤MPI of PK-encrypted integer
fb495d ·*/
1b4d2f int
acbd41 makePke (PGPByte *buf, PGPPubKey const *pub,
51f1d7 ¤   ·PGPRandomContext const *rc,
abd639 ¤   ·PGPByte const *key, unsigned keylen, PgpVersion version)
6dbb36 {
f9393e ¤   size_t esklen;
b34ba4 ¤   int i;
ecaf5a
4bcb80 ¤   (void) version;
69af5a
f7f14b ¤   /* XXX Should "die" gracefully, here */
774849 ¤   pgpAssert (pub->encrypt);
38af5a
f0062d ¤   i = pgpPubKeyEncrypt (pub, key, keylen, buf+10, &esklen, rc,
600f68 ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPPublicKeyMessageFormat_PGP);
e24fd6 ¤   if (i < 0)
f3a423 ¤   ¤   return i;
1267c5 ¤
8d163c ¤   /* Okay, build the PKE packet - fixed version number. */
f0461c ¤   buf[0] = (PGPByte)PGPVERSION_3;
7d805b ¤   /* KeyID */
ff90ab ¤   memcpy(buf+1, pub->keyID, 8);
ea3fe0 ¤   /* Type */
016e8d ¤   buf[9] = pub->pkAlg;
78af5a
2e7c29 ¤   return (int)esklen+10;
8fefe6 }
--2276 001423e621240100184 Page 1 of pgpMakePKE.h
bc38e5 /*
278573 ·* pgpMakePKE.h -- Make a Public Key Encrypted packet from a pubkey and a
c42d7f ·* session key.
74775e ·*
1ce39d ·* This is a PRIVATE header file, for use only within the PGP Library.
752979 ·* You should not be using these functions in an application.
4b775e ·*
a43977 ·* $Id: pgpMakePKE.h,v 1.7 1997/06/25 19:39:59 lloyd Exp $
03495d ·*/
2caf5a
0a3536 #ifndef Included_pgpMakePKE_h
666102 #define Included_pgpMakePKE_h
c2af5a
6dc546 #include <stddef.h>¤/* For size_t */
b3af5a
821d2a #include "pgpUsuals.h"¤ /* For PGPByte and PgpVersion */
51af5a
a699c6 PGP_BEGIN_C_DECLARATIONS
f1af5a
0e986e /* The maximum size of the public-key-encrypted packet */
4dcda1 size_t makePkeMaxSize(PGPPubKey const *pub, PgpVersion version);
46af5a
fb38e5 /*
508d57 ·* Given a buffer of at least "makePkeMaxSize" bytes, make a PKE packet
7bfa99 ·* into it and return the size of the PKE, or 0.
e3495d ·*/
9c4947 int makePke(PGPByte *buf, PGPPubKey const *pub,
ee8d15 ¤   ····PGPRandomContext const *rc,
98e72d ¤   ····PGPByte const *key, unsigned keylen, PgpVersion version);
87af5a
101254 PGP_END_C_DECLARATIONS
a1af5a
424bd7 #endif /* Included_pgpMakePKE_h */
--9045 000b3a1ef4d40100185 Page 1 of pgpPKEMod.c
bc38e5 /*
9e3956 ·* $Id: pgpPKEMod.c,v 1.28 1998/06/11 18:27:49 hal Exp $
df495d ·*/
96af5a
d7e2ff #include "pgpConfig.h"
f0af5a
c5feb2 #include <stdio.h>
e5324c #include <string.h>
cfaf5a
35a146 #include "pgpDebug.h"
509044 #include "pgpMakePKE.h"
3d8db3 #include "pgpPKEMod.h"
199c38 #include "pgpPktByte.h"
b6910a #include "pgpFIFO.h"
5a421a #include "pgpJoin.h"
a80d08 #include "pgpMem.h"
4f2f8d #include "pgpErrors.h"
b12ece #include "pgpPipeline.h"
45c26c #include "pgpContext.h"
80af5a
83e2ca #define PKEMODMAGIC¤0x90b11c47
28af5a
34bbd4 typedef struct PKEModContext {
d1f8fb ¤   PGPPipeline¤¤   pipe;
9967c5 ¤
7b8fce ¤   PGPByte *key;
ceaed1 ¤   size_t keylen;
3bd259 ¤   PGPByte *buf;
11c822 ¤   size_t buflen;
a1c5ae ¤   PgpVersion version;
0775b0 ¤   PGPPipeline *tail;
b5433b ¤   DEBUG_STRUCT_CONSTRUCTOR( PKEModContext )
5ce7b2 } PKEModContext;
e8af5a
ccf1ae static PGPError
e4d02e Flush (PGPPipeline *myself)
c4bb36 {
a2ea67 ¤   PKEModContext *context;
43af5a
7e29be ¤   pgpAssert (myself);
ee93c1 ¤   pgpAssert (myself->magic == PKEMODMAGIC);
36af5a
0de6ba ¤   context = (PKEModContext *)myself->priv;
3bd30a ¤   pgpAssert (context);
64ebf4 ¤   pgpAssert (context->tail);
0daf5a
439819 ¤   return context->tail->flush (context->tail);
67efe6 }
a4af5a
855d09 static size_t
aef37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
0cbb36 {
b5ea67 ¤   PKEModContext *context;
efe9fa ¤   PGPContextRef¤  cdkContext;
6a67c5 ¤
3c3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
3c696e ¤   cdkContext¤ = myself->cdkContext;
faaf5a
5429be ¤   pgpAssert (myself);
4193c1 ¤   pgpAssert (myself->magic == PKEMODMAGIC);
ff4866 ¤   pgpAssert (error);
56af5a
66e6ba ¤   context = (PKEModContext *)myself->priv;
52d30a ¤   pgpAssert (context);
19ebf4 ¤   pgpAssert (context->tail);
88af5a
5b0725 ¤   /* Once data is written, clear out the key! */
2cfd0f ¤   if (context->key) {
f4c7bd ¤   ¤   pgpClearMemory (context->key, context->keylen);
48e6dc ¤   ¤   pgpContextMemFree( cdkContext, context->key);
1803b4 ¤   ¤   context->key = NULL;
b3d65f ¤   ¤   if (context->buf) {
--cdc8 00085a7e73e40100185 Page 2 of pgpPKEMod.c
caf6a1 ¤   ¤   ¤   pgpClearMemory (context->buf, context->buflen);
5205c0 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context->buf);
c03990 ¤   ¤   ¤   context->buf = NULL;
42a3e5 ¤   ¤   ¤   context->buflen = 0;
590fe4 ¤   ¤   }
7e9371 ¤   }
caaf5a
ebd39f ¤   return context->tail->write (context->tail, buf, size, error);
1befe6 }
09af5a
a7f1ae static PGPError
5413c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
6cb0b1 ¤   ··PGPByte const *string, size_t size)
c1bb36 {
c8ea67 ¤   PKEModContext *context;
0caf5a
2b29be ¤   pgpAssert (myself);
0593c1 ¤   pgpAssert (myself->magic == PKEMODMAGIC);
acaf5a
e2e6ba ¤   context = (PKEModContext *)myself->priv;
1bd30a ¤   pgpAssert (context);
4aebf4 ¤   pgpAssert (context->tail);
eeaf5a
6f0df2 ¤   return context->tail->annotate (context->tail, origin, type,
3e3153 ¤   ¤   ¤   ¤   ¤   string, size);
2defe6 }
f4af5a
3ff1ae static PGPError
b94b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
cabb36 {
3cea67 ¤   PKEModContext *context;
2daf5a
2229be ¤   pgpAssert (myself);
bf93c1 ¤   pgpAssert (myself->magic == PKEMODMAGIC);
f5af5a
74e6ba ¤   context = (PKEModContext *)myself->priv;
bdd30a ¤   pgpAssert (context);
d7ebf4 ¤   pgpAssert (context->tail);
0caf5a
3ee1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
49efe6 }
49af5a
d0f1ae static PGPError
e5c7e1 Teardown (PGPPipeline *myself)
a4bb36 {
9aea67 ¤   PKEModContext *context;
dee9fa ¤   PGPContextRef¤  cdkContext;
ef67c5 ¤
023982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
91696e ¤   cdkContext¤ = myself->cdkContext;
6aaf5a
cf29be ¤   pgpAssert (myself);
5e93c1 ¤   pgpAssert (myself->magic == PKEMODMAGIC);
edaf5a
dbe6ba ¤   context = (PKEModContext *)myself->priv;
a1d30a ¤   pgpAssert (context);
e2af5a
2acb05 ¤   if (context->tail)
641e8a ¤   ¤   context->tail->teardown (context->tail);
e0af5a
c8fd0f ¤   if (context->key) {
ebc7bd ¤   ¤   pgpClearMemory (context->key, context->keylen);
d4e6dc ¤   ¤   pgpContextMemFree( cdkContext, context->key);
6a03b4 ¤   ¤   context->key = NULL;
b69371 ¤   }
49203a ¤   if (context->buf) {
5779f6 ¤   ¤   pgpClearMemory (context->buf, context->buflen);
1706b7 ¤   ¤   pgpContextMemFree( cdkContext, context->buf);
c682c6 ¤   ¤   context->buf = NULL;
7d18b3 ¤   ¤   context->buflen = 0;
f09371 ¤   }
853736 ¤   pgpClearMemory( context, ·sizeof (*context));
--877f 000eccc846340100185 Page 3 of pgpPKEMod.c
cafa6e ¤   pgpContextMemFree( cdkContext, context);
7667c5 ¤
8d151e ¤   return kPGPError_NoErr;
f6efe6 }
a3af5a
1e38e5 /*
37a300 ·* This adds a new PKE packet to the head of the message. ·If
231f3d ·* context->key is NULL, return an error. ·Also, return an error if
59842d ·* what we buffer is not as much as we thought we'd written
c1495d ·*/
3a4d2f int
6a5e4e pgpPkeAddKey (PGPPipeline *myself, PGPPubKey const *pubkey,
9317bc ¤   PGPRandomContext const *rng)
cfbb36 {
ccea67 ¤   PKEModContext *context;
d9e002 ¤   size_t size;
fe4ba4 ¤   int i;
4726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
de93c2 ¤   PGPByte *¤  ¤   p¤  = NULL;
b7e9fa ¤   PGPContextRef¤  cdkContext;
8667c5 ¤
df3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
8f696e ¤   cdkContext¤ = myself->cdkContext;
27af5a
dd29be ¤   pgpAssert (myself);
1093c1 ¤   pgpAssert (myself->magic == PKEMODMAGIC);
1caf5a
8be6ba ¤   context = (PKEModContext *)myself->priv;
89d30a ¤   pgpAssert (context);
5bebf4 ¤   pgpAssert (context->tail);
2eaf5a
663cea ¤   size = makePkeMaxSize(pubkey, context->version)+3;
68749f ¤   if (context->buflen < size) {
70e080 ¤   ¤   if( IsNull( context->buf ) ) {
03172c ¤   ¤   ¤   context->buf = (PGPByte *)pgpContextMemAlloc( cdkContext, size,
e417ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···0 );
52854d ¤   ¤   ¤   if( IsNull( context->buf ) )
edbfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
0145a6 ¤   ¤   } else {
14740b ¤   ¤   ¤   err = pgpContextMemRealloc( cdkContext,
6e4acb ¤   ¤   ¤   ¤   ¤   (void **)&context->buf, size, 0 );
560fe4 ¤   ¤   }
8937b3 ¤   ¤   if( IsPGPError( err ) ) {
35b32f ¤   ¤   ¤   return err;
610fe4 ¤   ¤   }
fac8d4 ¤   ¤   context->buflen = size;
1d9371 ¤   }
43af5a
2343a3 ¤   i = makePke(context->buf+3, pubkey, rng,
e1af4d ¤   ············context->key, context->keylen, context->version);
8b4fd6 ¤   if (i < 0)
34a423 ¤   ¤   return i;
52af5a
50b134 ¤   if (context->version > PGPVERSION_3) {
4992db ¤   ¤   if (PKTLEN_ONE_BYTE(i)) {
d8e33c ¤   ¤   ¤   context->buf[1] = PKTBYTE_BUILD_NEW(PKTBYTE_ESK);
43f8b6 ¤   ¤   ¤   context->buf[2] = PKTLEN_1BYTE(i);
305225 ¤   ¤   ¤   p = context->buf+1;
09c033 ¤   ¤   ¤   size = (size_t)i + 2;
2545a6 ¤   ¤   } else {
9b5963 ¤   ¤   ¤   context->buf[0] = PKTBYTE_BUILD_NEW(PKTBYTE_ESK);
5547ab ¤   ¤   ¤   context->buf[1] = PKTLEN_BYTE0(i);
b1b076 ¤   ¤   ¤   context->buf[2] = PKTLEN_BYTE1(i);
c4620f ¤   ¤   ¤   p = context->buf;
379aef ¤   ¤   ¤   size = (size_t)i + 3;
670fe4 ¤   ¤   }
46f037 ¤   } else {
0cb177 #if 0
9cc77e /* PGP 2.X wants to see 2 byte length field */
aded99 ¤   ¤   if (i < 256) {
ff4015 ¤   ¤   ¤   context->buf[1] = PKTBYTE_BUILD (PKTBYTE_ESK, 0);
ec238e ¤   ¤   ¤   context->buf[2] = (PGPByte)i;
--5e29 000efdcb2d640100185 Page 4 of pgpPKEMod.c
745225 ¤   ¤   ¤   p = context->buf+1;
a6c033 ¤   ¤   ¤   size = (size_t)i + 2;
35d2ef ¤   ¤   } else {}
5e7454 #endif
6f04f1 ¤   ¤   context->buf[0] = PKTBYTE_BUILD (PKTBYTE_ESK, 1);
305cd5 ¤   ¤   context->buf[1] = (PGPByte)(i >> 8);
161f60 ¤   ¤   context->buf[2] = (PGPByte)i;
22eb5b ¤   ¤   p = context->buf;
c7ade7 ¤   ¤   size = (size_t)i + 3;
c09371 ¤   }
88af5a
3560b0 ¤   pgpAssert( IsntNull( p ) );
a7b773 ¤   if (pgpJoinBuffer (context->tail, p, size) != size)
514030 ¤   ¤   return kPGPError_OutOfMemory;
6aaf5a
6d3e6b ¤   return 0;
a8efe6 }
eeaf5a
6541cd PGPPipeline **
87caae pgpPkeCreate (
233163 ¤   PGPContextRef¤  cdkContext,
466733 ¤   PGPPipeline **¤ head,
7603e7 ¤   PgpVersion¤ ¤   version,
a210bc ¤   PGPByte const *¤key,
080d15 ¤   size_t¤ ¤   ¤   keylen)
98bb36 {
d44b50 ¤   PGPPipeline *mod, *joinhead = NULL, **tail;
1dea67 ¤   PKEModContext *context;
51d259 ¤   PGPByte *buf;
49af5a
1d545b ¤   pgpAssert (key);
dfaf5a
84bb3d ¤   if (!head)
d87ed2 ¤   ¤   return NULL;
adaf5a
0e83f3 ¤   context = (PKEModContext *)pgpContextMemAlloc( cdkContext,
9fd680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
ed1ea4 ¤   if (!context)
237ed2 ¤   ¤   return NULL;
c49228 ¤   mod = &context->pipe;
e867c5 ¤
d89adc ¤   tail = pgpJoinCreate ( cdkContext, &joinhead, &pgpByteFifoDesc);
01b2e1 ¤   if (!tail) {
21a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
297ed2 ¤   ¤   return NULL;
b99371 ¤   }
fb5f07 ¤   buf = (PGPByte *)
f1c48a ¤   ¤   pgpContextMemAlloc( cdkContext, keylen, kPGPMemoryMgrFlags_Clear);
623686 ¤   if (!buf) {
c6a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
cd85ee ¤   ¤   joinhead->teardown (joinhead);
287ed2 ¤   ¤   return NULL;
af9371 ¤   }
534501 ¤   memcpy (buf, key, keylen);
adaf5a
0c870c ¤   mod->magic = PKEMODMAGIC;
961f83 ¤   mod->write = Write;
ecac4e ¤   mod->flush = Flush;
100aaf ¤   mod->sizeAdvise = SizeAdvise;
d9d3a2 ¤   mod->annotate = Annotate;
ed96de ¤   mod->teardown = Teardown;
f373da ¤   mod->name = "PKE Module";
a201ea ¤   mod->priv = context;
2ba99e ¤   mod->cdkContext¤= cdkContext;
fcaf5a
742f29 ¤   context->key = buf;
fb0dd6 ¤   context->keylen = keylen;
7d46a2 ¤   context->version = version;
99af5a
cb96e9 ¤   context->tail = joinhead;
42ea64 ¤   *tail = *head;
ef2d11 ¤   *head = mod;
--824e 0019cad6dfa40100185 Page 5 of pgpPKEMod.c
baca79 ¤   return tail;
9cefe6 }
--a39b 001ff1f8c1540100186 Page 1 of pgpPKEMod.h
bc38e5 /*
9b7a04 ·* pgpPKEMod.h -- A Module to create Public Key Encrypted packets
c2775e ·*
c38190 ·* This is a Public API Function Header.
10775e ·*
9da9b1 ·* $Id: pgpPKEMod.h,v 1.10 1997/06/25 19:40:00 lloyd Exp $
8f495d ·*/
25af5a
937857 #ifndef Included_pgpPKEMod_h
60f961 #define Included_pgpPKEMod_h
2daf5a
11adb8 #include "pgpOpaqueStructs.h"
53e82c #include "pgpPubTypes.h"
8caf5a
4199c6 PGP_BEGIN_C_DECLARATIONS
efaf5a
d5af5a
3a38e5 /*
c29db0 ·* Create a module to output PKE packets. ·The key is a block of data
da2d88 ·* of size keylen which is the session key and cipher type which should
8c0a16 ·* be encrypted in the public keys of the recipients.
27495d ·*/
58f481 PGPPipeline ·**
7028fc pgpPkeCreate (PGPContextRef¤cdkContext,
ab438e ¤   PGPPipeline **head, PgpVersion version, PGPByte const *key,
f6f7a7 ¤   size_t keylen);
11af5a
1d38e5 /*
04c3ba ·* Encrypt the session key in the passed-in public key and add that
d73aad ·* to the PKE list. ·This will return 0 on success or an error code.
8b775e ·*
ce97a7 ·* Note: Once any data is written to this module, no more public
9b9170 ·* keys can be added. ·Calling this function after any data has been
351730 ·* written will always return an error.
c8495d ·*/
fcc8dc int ·pgpPkeAddKey (PGPPipeline *myself,
953703 ¤   PGPPubKey const *pubkey, PGPRandomContext const *rng);
70af5a
7b1254 PGP_END_C_DECLARATIONS
9aaf5a
ff7587 #endif /* Included_pgpPKEMod_h */

--cf15 00122e555c240100187 Page 1 of Makefile.in
5ea601 #
0cf94e # priv/crypto/pipe/file/
47a601 #
fde7cb # $Id: Makefile.in,v 1.2 1997/05/04 10:30:08 mhw Exp $
99a601 #
c8af5a
aa8e03 OBJS=¤  pgpArmor.o pgpArmrFil.o pgpFileMod.o pgpCRC.o pgpHeader.o \
34afad ¤   pgpPrsAsc.o pgpRadix64.o·
215b1f PRIVHDRS= pgpArmor.h pgpArmrFil.h pgpFileMod.h pgpHeader.h pgpPrsAsc.h
8aaf5a
e7b7a3 all:: DONE
22af5a
--b77f 00096fe8bf840100188 Page 1 of pgpArmor.c
bc38e5 /*
d05869 ·* pgpArmor.c -- a module to perform Ascii Armor
91775e ·*
357ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
8a775e ·*
6d412d ·* $Id: pgpArmor.c,v 1.45 1998/07/15 05:35:57 hal Exp $
3d495d ·*/
2eaf5a
8ae2ff #include "pgpConfig.h"
bdaf5a
7bfeb2 #include <stdio.h>
73b1cb #include <ctype.h>
9a324c #include <string.h>
8daf5a
07a146 #include "pgpDebug.h"
16f476 #include "pgpArmor.h"
af5101 #include "pgpCRC.h"
2e9c38 #include "pgpPktByte.h"
310301 #include "pgpRadix64.h"
736aaa #include "pgpAnnotate.h"
5d910a #include "pgpFIFO.h"
8c5417 #include "pgpHashPriv.h"
2d421a #include "pgpJoin.h"
9b0d6d #include "pgpEnv.h"
fb0d08 #include "pgpMem.h"
1d0d6d #include "pgpEnv.h"
302ece #include "pgpPipeline.h"
282c96 #include "pgpRandomX9_17.h"
ec27c0 #include "pgpSplit.h"
abd11f #include "pgpUsuals.h"
0204f5 #include "pgpFeatures.h"
13c26c #include "pgpContext.h"
7faf5a
1742dd #define ARMORMAGIC¤ 0xa4904f11
9b1b52 ¤   ¤
ed08aa /* Max length of a line in MIME content-printable encoding */
8443f9 #define MIMEMAX 76
fbaf5a
87e19d /* Number characters in our random MIME separator */
4a949b #define NSEPCHARS¤  48
6caf5a
e038e5 /*
035cdf ·* PGP-MIME headers. ·We chose "=-" as boundary since it can't occur in
f8a1eb ·* a quoted-printable encoding, nor in base64.
7c495d ·*/
dda709 #define MIMEENCSEP "=--"
1f4cbd #define MIMESIGHDR1a "Mime-Version: 1.0\n"
bc6a4c #define MIMESIGHDR1b \
65cbd9 ¤   "Content-Type: multipart/signed;\n boundary=\""
a78bad #define MIMESIGHDR2 "\";\n" \
fca744 ¤   " protocol=\"application/pgp-signature\"; "
eae211 #define MIMESIGHDRLINESa 1
2cedb4 #define MIMESIGHDRLINESb 2
92ef85 #define MIMEENCHDR1a "Mime-Version: 1.0\n"
80156e #define MIMEENCHDR1b \
1ee1d0 ¤   "Content-Type: multipart/encrypted; boundary=\"" MIMEENCSEP "\";\n" \
f4a28a ¤   " protocol=\"application/pgp-encrypted\"\n\n"
7b06be #define MIMEENCHDR2 "--" MIMEENCSEP "\n" \
1f1794 ¤   "Content-Type: application/pgp-encrypted\n\n" \
9a9c19 ¤   "Version: 1\n\n--" MIMEENCSEP "\n" \
411ed4 ¤   "Content-Type: application/octet-stream\n\n"
969542 #define MIMEENCHDRLINES1a¤  1
1faa8f #define MIMEENCHDRLINES1b¤  3
47fa55 #define MIMEMIC "micalg=pgp-"
2ec184 #define MIMEDFLTMIC "pgp-md5"
e13867 #define MIMEMIDBOUND "Content-Type: application/pgp-signature\n\n"
56af5a
2cabcb typedef struct ArmorContext
5bbb36 {
fcb1a2 ¤   /* by placing this here, we can just allocate everything at once */
418b60 ¤   PGPPipeline¤pipe;
9667c5 ¤
--912f 00084daeead40100188 Page 2 of pgpArmor.c
e475b0 ¤   PGPPipeline *tail;
b02480 ¤   PGPFifoDesc const *fd;
573566 ¤   PGPFifoContext *fifo;
7b4d1f ¤   PGPFifoContext *header;
4d2560 ¤   PGPContextRef cdkContext;
7192e4 ¤   unsigned long¤  crc;
7310b4 ¤   unsigned long¤  armorlines;
d04a03 ¤   unsigned long¤  lineno;
c774a7 ¤   unsigned¤   thispart;
cc8bed ¤   unsigned¤   maxparts;
dc0c4e ¤   int¤scope_depth;
196bb8 ¤   PGPByte¤input[48];¤ /* Maximum 48 bytes */
a1b177 #if 0
25a1bc ¤   char¤   output[65];¤/* Maximum 63 buyes + \r and/or \n */
09db21 #else
5e396a ¤   char¤   output[MIMEMAX+2]; /* MIME line plus \n plus null */
d57454 #endif
854955 ¤   char¤   mimesigsep[NSEPCHARS+1];
f17cc6 ¤   char *¤ outptr;
a20897 ¤   PGPBoolean needmessageid;
61bfb7 ¤   char *¤ messageid;
d73a96 ¤   char const *¤   blocktype;
cb8c47 ¤   char const *¤   comment;
c09127 ¤   char const *¤   charset;
d88635 ¤   char const *¤   versionString;
ef3d55 ¤   PGPSize¤¤   mimebodyoff;¤   ¤   /* Offset to start of body (1 char/nl) */
86e5a9 ¤   PGPUInt32¤  mimeheaderlines;¤   /* # lines in mime header */
ea6cd7 ¤   PgpVersion¤ version;
6a36a1 ¤   PGPByte¤inlen;
d522a8 ¤   PGPByte¤outlen;
e538b8 ¤   PGPByte¤clearsign;
88bab3 ¤   PGPByte¤pgpmime;
9409a4 #define PGPMIMESIG 1
513bb6 #define PGPMIMEENC 2
a1747d ¤   PGPByte pgpmimeversionline;
5cb818 ¤   PGPByte¤didheader;
9feca0 ¤   PGPByte¤didfooter;
8d74d8 ¤   PGPByte¤sizevalid;
b28b49 ¤   PGPByte¤state;
80a944 ¤   PGPByte¤linebuf;
937773 ¤   DEBUG_STRUCT_CONSTRUCTOR( ArmorContext )
da4c59 } ArmorContext;
f2af5a
baaf5a
226a43 /* Forward declarations */
89beb7 static int
c20294 armorLine (PGPByte const *in, unsigned inlen, char *out);
ccaf5a
deaf5a
eeaf5a
7b38e5 /*
3f47c3 ·* Armor 3 raw bytes into 4
2caad3 ·* If armoring n < 3 bytes, make the trailers zero, and
c2c29d ·* then overwrite the trailing 3-n bytes with '='
79495d ·*/
062978 static void
f3b2af armorMorsel(PGPByte const raw[3], char armor[4])
39bb36 {
932c32 ········armor[0] = armorTable[raw[0] >> 2 & 0x3f];
35d39f ········armor[1] = armorTable[(raw[0] << 4 & 0x30) + (raw[1] >> 4 & 0x0f)];
677c56 ········armor[2] = armorTable[(raw[1] << 2 & 0x3c) + (raw[2] >> 6 & 0x03)];
1b8bfc ········armor[3] = armorTable[raw[2] & 0x3f];
8eefe6 }
ddaf5a
1f2978 static void
e7aea8 armorWriteClassify (ArmorContext *context, PGPByte const *buf)
08bb36 {
a8ccd8 ¤   if (context->blocktype)
db99bf ¤   ¤   return;
29af5a
8a619f ¤   if (PKTBYTE_TYPE(*buf) == PKTBYTE_PUBKEY)
84131d ¤   ¤   context->blocktype = "PUBLIC KEY BLOCK";
--f55e 00055f4d11c40100188 Page 3 of pgpArmor.c
a1acd5 ¤   else if (PKTBYTE_TYPE(*buf) == PKTBYTE_SECKEY)
fa1573 ¤   ¤   context->blocktype = "PRIVATE KEY BLOCK";
b10e24 ¤   else
592af7 ¤   ¤   context->blocktype = "MESSAGE";
47efe6 }
e1af5a
6a6aed /* Message ID is derived by hashing the beginning of the message data */
2b2978 static void
34d86a armorDeriveMessageID (ArmorContext *context)
bdbb36 {
63602d ¤   PGPHashVTBL const *h;
b8e2ba ¤   PGPHashContext *hc;
4809a3 ····PGPMemoryMgrRef¤memoryMgr;
ab8b0f ¤   PGPByte const *p;
f550d8 ¤   PGPUInt32 len;
17ee55 ¤   PGPByte hashdata[24];¤  ¤   /* Produces 32 chars of messageid */
5daf5a
b9a8bf ¤   memoryMgr = PGPGetContextMemoryMgr( context->cdkContext );
238088 ¤   pgpAssert (IsntNull (memoryMgr) );
96a993 ¤   h = pgpHashByNumber (kPGPHashAlgorithm_SHA);
720e8d ¤   if (!h)
4f97ed ¤   ¤   goto error;
f30f5c ¤   hc = pgpHashCreate (memoryMgr, h);
478cee ¤   if (!hc)
a697ed ¤   ¤   goto error;
87898f ¤   PGPContinueHash (hc, context->input, context->inlen);
f38bfa ¤   p = (PGPByte *) pgpHashFinal (hc);
9954cc ¤   pgpClearMemory (hashdata, sizeof(hashdata));
5e8d6d ¤   pgpCopyMemory (p, hashdata, pgpMin (h->hashsize, sizeof(hashdata)));
3134ef ¤   PGPFreeHashContext (hc);
c0c38d ¤   context->messageid = (char *)PGPNewData (memoryMgr,
3b5fca ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(hashdata)*4/3 + 1, 0);
17e93e ¤   if (!context->messageid)
cf99bf ¤   ¤   return;
edaf5a
433c95 ¤   len = armorLine (hashdata, sizeof(hashdata), context->messageid);
c4fcdf ¤   context->messageid[len] = '\0';
baaf5a
19830f ¤   return;
40af5a
2460ff error:
c77a92 ¤   /* Create an empty messageid */
008256 ¤   context->messageid = (char *)PGPNewData ( memoryMgr, 1, 0 );
158cb9 ¤   context->messageid[0] = '\0';
74830f ¤   return;
27efe6 }
9eaf5a
54f1ae static PGPError
1250ff armorFlushHeader (ArmorContext *context)
10bb36 {
77a617 ¤   PGPByte const *ptr;
4d875f ¤   PGPSize len;
5c87a6 ¤   PGPError¤   error;
0a6c75 ¤   size_t retlen;
c0af5a
22cbfd ¤   ptr = pgpFifoPeek (context->fd, context->header, &len);
8285aa ¤   while (len) {
b2ec77 ¤   ¤   retlen = context->tail->write (context->tail, ptr, len,
2e48b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
c7dbc8 ¤   ¤   pgpFifoSeek (context->fd, context->header, retlen);
5be3c2 ¤   ¤   if (error)
af3b5b ¤   ¤   ¤   return error;
d81b52 ¤   ¤
e40fe1 ¤   ¤   ptr = pgpFifoPeek (context->fd, context->header, &len);
ff9371 ¤   }
a0151e ¤   return kPGPError_NoErr;
a7efe6 }
54af5a
482978 static void
f42e17 armorMakeHeader (ArmorContext *context)
19bb36 {
555991 ¤   char temp[20];
--016b 000ad5d6ae040100188 Page 4 of pgpArmor.c
e0af5a
2ab2fc ¤   if (context->pgpmime == PGPMIMEENC) {
7d44fb ¤   ¤   context->mimebodyoff = 0;
3dfa92 ¤   ¤   context->mimeheaderlines = 0;
0ab330 ¤   ¤   if( context->pgpmimeversionline ) {
a3e5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
66b190 ¤   ¤   ¤   ······(PGPByte const *)MIMEENCHDR1a, strlen(MIMEENCHDR1a));
5fb5c5 ¤   ¤   ¤   context->mimebodyoff += strlen(MIMEENCHDR1a);
407854 ¤   ¤   ¤   context->mimeheaderlines += MIMEENCHDRLINES1a;
0a0fe4 ¤   ¤   }
37b006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
15f3bd ¤   ¤   ¤   ······(PGPByte const *)MIMEENCHDR1b, strlen(MIMEENCHDR1b));
6c937f ¤   ¤   context->mimebodyoff += strlen(MIMEENCHDR1b);
9a900b ¤   ¤   context->mimeheaderlines += MIMEENCHDRLINES1b;
aeb006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
a6df73 ¤   ¤   ¤   ······(PGPByte const *)MIMEENCHDR2, strlen(MIMEENCHDR2));
839371 ¤   }
442647 ¤   pgpFifoWrite (context->fd, context->header,
61fa05 ¤   ¤   ······(PGPByte const *)"-----BEGIN PGP ", 15);
8b16bb ¤   pgpFifoWrite (context->fd, context->header, (PGPByte *)context->blocktype,
0b8d11 ¤   ¤   ······strlen (context->blocktype));
fcaf5a
ef57f1 ¤   if (context->maxparts) {
7eb006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
3df71e ¤   ¤   ¤   ······(PGPByte const *)", PART ", 7);
cea35d ¤   ¤   sprintf (temp, "%02u", context->thispart);
98c2ad ¤   ¤   pgpFifoWrite (context->fd, context->header, (PGPByte const *)temp,
fbde4e ¤   ¤   ¤   ······strlen (temp));
698df6 ¤   ¤   if (context->version <= PGPVERSION_3 ||
f0acbc ¤   ¤   ·······context->thispart == context->maxparts) {
e9e5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
ee863f ¤   ¤   ¤   ¤   ······(PGPByte const *)"/", 1);
175fdb ¤   ¤   ¤   sprintf (temp, "%02u", context->maxparts);
1be5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
2c5949 ¤   ¤   ¤   ¤   ······(PGPByte const *)temp, strlen (temp));
670fe4 ¤   ¤   }
c89371 ¤   }
02af5a
912647 ¤   pgpFifoWrite (context->fd, context->header,
b79826 ¤   ¤   ······(PGPByte const *)"-----\nVersion: ", 15);
8dd9fd ¤   if( IsntNull( context->versionString ) ) {
eeb006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
37b749 ¤   ¤   ······(PGPByte const *)context->versionString,
0e1443 ¤   ¤   ······strlen (context->versionString));
e6f037 ¤   } else {
cd406b ¤   ¤   char sVersionString[ 256 ];
3ee6a5 ¤   ¤   PGPGetSDKString( sVersionString );
13b006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
c8495a ¤   ¤   ······(PGPByte const *)sVersionString, strlen (sVersionString));
6c9371 ¤   }
87af5a
2839d2 ¤   if (context->needmessageid && context->maxparts) {
b41175 ¤   ¤   if (!context->messageid) {
2f2579 ¤   ¤   ¤   armorDeriveMessageID (context);
c70fe4 ¤   ¤   }
50c7d2 ¤   ¤   if (context->messageid) {
eee5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
a23c36 ¤   ¤   ¤   ¤   ¤   ··(PGPByte const *)"\nMessageID: ", 12);
dfe5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
a92114 ¤   ¤   ¤   ¤   ¤   ··(PGPByte const *)context->messageid,
e06936 ¤   ¤   ¤   ¤   ¤   ··strlen (context->messageid));
aa0fe4 ¤   ¤   }
df9371 ¤   }
b9af5a
8df080 ¤   /* Don't do comment if empty string. ·This is more convenient for
9048b2 ¤   ·* callers who want no comment, in some cases. */
cbafab ¤   if (context->comment && context->comment[0]) {
82b006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
3e5039 ¤   ¤   ¤   ······(PGPByte const *)"\nComment: ", 10);
59b006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
2254e4 ¤   ¤   ¤   ······(PGPByte const *)context->comment,
ad9661 ¤   ¤   ¤   ······strlen (context->comment));
--3ff5 000eaf4734240100188 Page 5 of pgpArmor.c
a19371 ¤   }
93af5a
7d8af4 ¤   if (context->charset) {
c5b006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
e318be ¤   ¤   ¤   ······(PGPByte const *)"\nCharset: ", 10);
2fb006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
d54984 ¤   ¤   ¤   ······(PGPByte const *)context->charset,
8c3850 ¤   ¤   ¤   ······strlen (context->charset));
6b9371 ¤   }
73af5a
0876de ¤   pgpFifoWrite (context->fd, context->header, (PGPByte *)"\n\n", 2);
48c609 ¤   context->didheader = 1;
2defe6 }
adaf5a
e92978 static void
a88173 armorMakeFooter (ArmorContext *context)
74bb36 {
e25991 ¤   char temp[20];
2e68ca ¤   PGPByte crc[3];
2aaf5a
2cd1bf ¤   /* Emit CRC, MSB-first */
29ca9f ¤   crc[0] = (PGPByte)(context->crc >> 16);
d04e25 ¤   crc[1] = (PGPByte)(context->crc >> 8);
d45bfc ¤   crc[2] = (PGPByte)context->crc;
c91733 ¤   armorMorsel (crc, temp);
bdaf5a
dce8e0 ¤   pgpFifoWrite (context->fd, context->header, (PGPByte const *)"=", 1);
0c0be5 ¤   pgpFifoWrite (context->fd, context->header, (PGPByte const *)temp, 4);
beaf5a
016c16 ¤   /* Now emit the end */
082647 ¤   pgpFifoWrite (context->fd, context->header,
81f397 ¤   ¤   ······(PGPByte const *)"\n-----END PGP ", 14);
312647 ¤   pgpFifoWrite (context->fd, context->header,
9bb8fa ¤   ¤   ······(PGPByte const *)context->blocktype,
908d11 ¤   ¤   ······strlen (context->blocktype));
74af5a
e357f1 ¤   if (context->maxparts) {
9ab006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
40f71e ¤   ¤   ¤   ······(PGPByte const *)", PART ", 7);
3ca35d ¤   ¤   sprintf (temp, "%02u", context->thispart);
3eb006 ¤   ¤   pgpFifoWrite (context->fd, context->header,
a47ffc ¤   ¤   ¤   ······(PGPByte const *)temp, strlen (temp));
e18df6 ¤   ¤   if (context->version <= PGPVERSION_3 ||
1b2d31 ¤   ¤   ····context->thispart == context->maxparts) {
2be5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
2c863f ¤   ¤   ¤   ¤   ······(PGPByte const *)"/", 1);
235fdb ¤   ¤   ¤   sprintf (temp, "%02u", context->maxparts);
81e5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
d45949 ¤   ¤   ¤   ¤   ······(PGPByte const *)temp, strlen (temp));
d70fe4 ¤   ¤   }
599371 ¤   }
d32647 ¤   pgpFifoWrite (context->fd, context->header,
5262c1 ¤   ¤   ······(PGPByte const *)"-----\n", 6);
67af5a
c032bf ¤   if (context->pgpmime) {
1af6dc ¤   ¤   pgpFifoWrite (context->fd, context->header, (PGPByte *)"\n--", 3);
d38b39 ¤   ¤   if (context->pgpmime == PGPMIMEENC) {
60e5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
0c4f87 ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPByte *)MIMEENCSEP, strlen(MIMEENCSEP));
3145a6 ¤   ¤   } else {
f2e5aa ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
71393e ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPByte *)context->mimesigsep, NSEPCHARS);
c50fe4 ¤   ¤   }
549487 ¤   ¤   pgpFifoWrite (context->fd, context->header, (PGPByte *)"--\n", 3);
e79371 ¤   }
d7af5a
0ca2cf ¤   context->didfooter = 1;
ebe2c3 ¤   context->crc = CRC_INIT;
a7efe6 }
4daf5a
08f1ae static PGPError
ea33f3 armorNewFile (PGPPipeline *myself)
--b39e 0005125280d40100188 Page 6 of pgpArmor.c
2cbb36 {
1798bc ¤   ArmorContext *context = (ArmorContext *)myself->priv;
5187a6 ¤   PGPError¤   error;
706dbe ¤   PGPSize thispart;
b6af5a
59d8af ¤   /*
67ba30 ¤   ·* First, if we're already in a part, then close off the last
735ab0 ¤   ·* one.
1ea4e3 ¤   ·*/
e8e39f ¤   if (context->thispart) {
a2648c ¤   ¤   if (!context->didfooter)
9d6fdf ¤   ¤   ¤   armorMakeFooter (context);
9aaf5a
371f78 ¤   ¤   error = armorFlushHeader (context);
70e3c2 ¤   ¤   if (error)
d53b5b ¤   ¤   ¤   return error;
5eaf5a
01a059 ¤   ¤   error = context->tail->sizeAdvise (context->tail, 0);
43e3c2 ¤   ¤   if (error)
7f3b5b ¤   ¤   ¤   return error;
4caf5a
dfda90 ¤   ¤   error = context->tail->annotate (context->tail, myself,
45112f ¤   ¤   ¤   ¤   ¤   ¤   ·PGPANN_MULTIARMOR_END, 0, 0);
fde3c2 ¤   ¤   if (error)
cc3b5b ¤   ¤   ¤   return error;
6b9371 ¤   }
bbaf5a
275f9e ¤   thispart = context->thispart+1;
3b1e8c ¤   error = context->tail->annotate (context->tail, myself,
43c38c ¤   ¤   ¤   ¤   ¤   ·PGPANN_MULTIARMOR_BEGIN,
d31875 ¤   ¤   ¤   ¤   ¤   ·(PGPByte const *)&thispart,
ab22f9 ¤   ¤   ¤   ¤   ¤   ·sizeof (thispart));
ee0161 ¤   if (error)
ecfcee ¤   ¤   return error;
59af5a
895d0a ¤   context->thispart++;
639cd5 ¤   context->didheader = 0;
c4f813 ¤   context->didfooter = 0;
7cd1d2 ¤   context->lineno = 0;
2baf5a
08aeb1 ¤   /* And give it an appropriate header */
ac3179 ¤   armorMakeHeader (context);
a0af5a
08151e ¤   return kPGPError_NoErr;
b7efe6 }
c8af5a
4438e5 /*
1127e2 ·* The method here to do the armoring is somewhat tricky.
802c3d ·* Most lines just have inlen = 48 which maps to 48*4/3 = 64
ec1752 ·* output characters. ·But the last line has a short inlen.
75651b ·* This leads to a truncated last group, which looks like one of:
59b9b8 ·* xx== (if the last group contains 1 byte - 4 bits of padding are zero)
9753ce ·* xxx= (if the last group contains 2 bytes - 2 bits of padding are zero)
eada1d ·* xxxx (if the last group contains 3 bytes)
38ffd6 ·* To do this, we make sure that we've added an extra 0 byte to the
a88bff ·* end of the input, then encode it in blocks of 3 bytes, then note by
c9aaef ·* how much the encoding overshot the input length, len - inlen.
09efa5 ·* This is 2, 1, or 0. ·Overwrite that many trailing characters with '='.
b39b2e ·* Then a newline can be appended for output.
31495d ·*/
40beb7 static int
47a422 armorLine (PGPByte const *in, unsigned inlen, char *out)
1ebb36 {
e9c6b5 ¤   unsigned len;
94314e ¤   int t;
1d5b3c ¤   char const *out0 = out;
f7af5a
4b0fb0 ¤   /* Fill the output buffer from the input buffer */
abc751 ¤   for (len = 0; len < inlen; len += 3) {
cdd53e ¤   ¤   armorMorsel (in, out);
090d63 ¤   ¤   in += 3;
518f3b ¤   ¤   out += 4;
--fa51 000d6e85c1540100188 Page 7 of pgpArmor.c
a19371 ¤   }
93af5a
3fe76f ¤   /* Now back up and erase any overrun */
323f0e ¤   t = (int)(inlen - len);¤¤   /* Zero or negative */
cb6242 ¤   while (t)
745849 ¤   ¤   out[t++] = '=';
d80cca ¤   ······
d1ffd5 ¤   return (out - out0);
b9efe6 }
13af5a
102978 static void
696f55 armorProcessLine (ArmorContext *context)
c0bb36 {
1b34f3 ¤   /* Update CRC */
09cf10 ¤   context->crc = crcUpdate (context->crc, context->input,
736c69 ¤   ¤   ¤   ¤   ··context->inlen);
85af5a
ced792 ¤   /* Apply padding so that we can overshoot */
8667bd ¤   if (context->inlen < sizeof (context->input))
b654c0 ¤   ¤   context->input[context->inlen] = 0;
2267c5 ¤
20ae5a ¤   /* Refill the output buffer from the input buffer */
fe1516 ¤   context->outlen = armorLine (context->input, context->inlen,
46cc1c ¤   ¤   ¤   ¤   ·····context->output);
70af5a
6cd9d7 ¤   context->output [context->outlen++] = '\n';
410ae6 ¤   context->outptr = context->output;
27cd13 ¤   context->inlen = 0;
19efe6 }
85af5a
1ef1ae static PGPError
9dd02e Flush (PGPPipeline *myself)
79bb36 {
32a45a ¤   ArmorContext *context;
5d87a6 ¤   PGPError¤   error;
4c6c75 ¤   size_t retlen;
b2af5a
7429be ¤   pgpAssert (myself);
f3eb3a ¤   pgpAssert (myself->magic == ARMORMAGIC);
8baf5a
a57b54 ¤   context = (ArmorContext *)myself->priv;
88d30a ¤   pgpAssert (context);
bcebf4 ¤   pgpAssert (context->tail);
a0af5a
d0927a ¤   /* Try to flush anything that we have buffered. */
edec3d ¤   while (context->outlen) {
7288b9 ¤   ¤   retlen = context->tail->write (context->tail,
d42f14 ¤   ¤   ¤   ¤   ¤   ·······(PGPByte *)context->outptr,
371e5e ¤   ¤   ¤   ¤   ¤   ·······context->outlen,
f948b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
98a8d8 ¤   ¤   context->outlen -= retlen;
114fb1 ¤   ¤   context->outptr += retlen;
faaf5a
2f6f42 ¤   ¤   if (!context->outlen)
fe016f ¤   ¤   ¤   context->lineno++;
62af5a
d0e3c2 ¤   ¤   if (error)
cf3b5b ¤   ¤   ¤   return error;
3d9371 ¤   }
9baf5a
47151e ¤   return kPGPError_NoErr;
e2efe6 }
0caf5a
b638e5 /*
091391 ·* First, try to flush out the output buffer. ·Once that is empty,
d72c74 ·* refill the output buffer from the input buffer, append a newline,
71ff81 ·* and set the input buffer to 0 input. ·Then try to write that out,
66ffdd ·* too.
5a495d ·*/
b3f1ae static PGPError
9149a0 DoFlush (PGPPipeline *myself)
d6bb36 {
--1fb2 00013ff0f5e40100188 Page 8 of pgpArmor.c
1c98bc ¤   ArmorContext *context = (ArmorContext *)myself->priv;
4d5b01 ¤   PGPError¤   error = kPGPError_NoErr;
e1af5a
03d8af ¤   /*
a94196 ¤   ·* Try to flush anything that we have buffered. ·I know that
2439c9 ¤   ·* the first time Flush is called, outlen WILL be zero!
88a4e3 ¤   ·*/
f5a9f8 ¤   error = Flush (myself);
250161 ¤   if (error)
bffcee ¤   ¤   return error;
ccaf5a
d4a834 ¤   /* Next, try to output anything in the header fifo */
7b971e ¤   error = armorFlushHeader (context);
130161 ¤   if (error)
ddfcee ¤   ¤   return error;
4caf5a
55af5a
68fef2 ¤   /* Finally, process the input buffer and flush it out again */
6f62f6 ¤   if (context->inlen) {
e3f164 ¤   ¤   armorProcessLine (context);
f14a53 ¤   ¤   error = DoFlush (myself);
7a9371 ¤   }
0baf5a
2dc674 ¤   return error;
0defe6 }
51af5a
4538e5 /*
7b96e6 ·* Write a single line.
42495d ·*/
845d09 static size_t
3bef63 armorWriteBytes (PGPPipeline *myself, PGPByte const *buf, size_t size,
7570bc ¤   ¤   ·PGPError *error)
08bb36 {
ed98bc ¤   ArmorContext *context = (ArmorContext *)myself->priv;
b06d88 ¤   size_t size0 = size;
160ed5 ¤   unsigned t;
f5af5a
3ad8af ¤   /*
864196 ¤   ·* Try to flush anything that we have buffered. ·I know that
9939c9 ¤   ·* the first time Flush is called, outlen WILL be zero!
daa4e3 ¤   ·*/
56cf8e ¤   *error = Flush (myself);
4f5842 ¤   if (*error)
c2bbde ¤   ¤   return 0;
70af5a
d72461 ¤   /* try to fill up the input buffer */
11d722 ¤   t = pgpMin ((sizeof (context->input) - context->inlen), size);
bd6d85 ¤   memcpy (context->input + context->inlen, buf, t);
9ca97d ¤   buf += t;
1eddbe ¤   size -= t;
473f99 ¤   context->inlen += t;
d9af5a
3aaf78 ¤   if( context->inlen ) {
236760 ¤   ¤   armorWriteClassify (context, context->input);
261b52 ¤   ¤
0a1b17 ¤   ¤   /*
459040 ¤   ¤   ·* check if we need a new file. ·This is called if we
b77e1a ¤   ¤   ·* exceed armorlines, or when we do have multiparts and we do
ee1a2e ¤   ¤   ·* not have a current part.
4c9de3 ¤   ¤   ·*/
c2a82a ¤   ¤   if (context->armorlines && (context->lineno >=
c4d947 ¤   ¤   ¤   ¤   ¤   ····context->armorlines ||
2a2861 ¤   ¤   ¤   ¤   ¤   ····!context->thispart)) {
9caf5a
a47aad ¤   ¤   ¤   /*
cd5543 ¤   ¤   ¤   ·* Set maxparts to -1 if this _is_ multipart armor
ed1495 ¤   ¤   ¤   ·* using one-pass processing.
008753 ¤   ¤   ¤   ·*/
9eb42b ¤   ¤   ¤   if (context->version > PGPVERSION_3 &&
c6fe22 ¤   ¤   ¤   ····!context->maxparts && !context->sizevalid)
939d6e ¤   ¤   ¤   ¤   context->maxparts = -1;
13af5a
--c969 000076669f040100188 Page 9 of pgpArmor.c
da2b37 ¤   ¤   ¤   *error = armorNewFile (myself);
84b5c5 ¤   ¤   ¤   if (*error)
1d4a32 ¤   ¤   ¤   ¤   return size0-size;
7a0fe4 ¤   ¤   }
939371 ¤   }
bdaf5a
a02e8d ¤   /* If we've filled a line, then flush it out */
d11cec ¤   if (context->inlen == sizeof (context->input)) {
0f3034 ¤   ¤   if (!context->didheader)
3efcf5 ¤   ¤   ¤   armorMakeHeader (context);
b45300 ¤   ¤   *error = DoFlush (myself);
5bcf31 ¤   ¤   if (*error)
9cc64d ¤   ¤   ¤   return size0-size;
0d9371 ¤   }
32af5a
533084 ¤   return size0-size;
faefe6 }
abaf5a
3a38e5 /*
674f59 ·* Minimally perform a DoFlush(), but try to flush the fifo, too!
25775e ·*
26ed19 ·* If context->version > PGPVERSION_3 then we only start writing
beffc1 ·* things out context->armorlines == 0 or when we have a full block
42ffca ·* worth of data (48 * (context->armorlines - context->lineno)). ·If
73df64 ·* context->sizevalid == 2, we have an EOF and should flush the rest
414bab ·* of the fifo regardless.
e3495d ·*/
12f1ae static PGPError
b2853b armorFlushFifo (PGPPipeline *myself)
34bb36 {
9c98bc ¤   ArmorContext *context = (ArmorContext *)myself->priv;
66a617 ¤   PGPByte const *ptr;
0c875f ¤   PGPSize len;
cc6c75 ¤   size_t retlen;
2487a6 ¤   PGPError¤   error;
5aaf5a
aab797 ¤   ptr = pgpFifoPeek (context->fd, context->fifo, &len);
0e85aa ¤   while (len) {
646c99 ¤   ¤   if (context->version > PGPVERSION_3 &&
ef6a57 ¤   ¤   ····context->sizevalid < 2 &&
30d97e ¤   ¤   ····context->armorlines &&
3dce4f ¤   ¤   ····pgpFifoSize (context->fd, context->fifo) < 48 *
576f16 ¤   ¤   ····(context->lineno == context->armorlines ?·
09be4f ¤   ¤   ·····context->armorlines :
b3b86d ¤   ¤   ·····(context->armorlines - context->lineno)))
0033bc ¤   ¤   ¤   return kPGPError_NoErr;
acaf5a
1c01a8 ¤   ¤   retlen = armorWriteBytes (myself, ptr, len, &error);
a22cf7 ¤   ¤   pgpFifoSeek (context->fd, context->fifo, retlen);
83e3c2 ¤   ¤   if (error)
f13b5b ¤   ¤   ¤   return error;
71af5a
f15597 ¤   ¤   ptr = pgpFifoPeek (context->fd, context->fifo, &len);
ab9371 ¤   }
a8151e ¤   return kPGPError_NoErr;
eeefe6 }
9daf5a
c038e5 /*
934d3e ·* This is the function that processes a clearsigned message. ·It uses
79991f ·* context->state to tell it what it is doing:
5b03eb ·*¤ 0) at the beginning -- check it
4370ae ·*¤ 1) middle of line, pass it through
3d8ae2 ·* 2) end of line with \r -- check next character for \n */
005d09 static size_t
0175d7 armorDoClearsign (PGPPipeline *myself, PGPByte const *buf, size_t size,
99c837 ¤   ¤   ··PGPError *error)
8ebb36 {
8798bc ¤   ArmorContext *context = (ArmorContext *)myself->priv;
70282d ¤   size_t written, size0 = size;
95a617 ¤   PGPByte const *ptr;
f0b2a3 ¤   static PGPByte const from[] = "From ";
070552 ¤   int i, t, flag;
--d4cb 000c9fa9a7040100188 Page 10 of pgpArmor.c
e0af5a
2767c5 ¤
99a0eb ¤   while (size) {
816f59 ¤   ¤   if (context->state == 2) {
7db247 ¤   ¤   ¤   context->state = 0;
45e3f0 ¤   ¤   ¤   if (*buf == '\n') {
efcdec ¤   ¤   ¤   ¤   ptr = buf+1;
1fbb66 ¤   ¤   ¤   ¤   goto do_write;
b8a3a6 ¤   ¤   ¤   }
430fe4 ¤   ¤   }
eb87c7 ¤   ¤   ¤
eb4169 ¤   ¤   /*·
249ee6 ¤   ¤   ·* Here, we check the beginning of the line. ·We use the
273e1b ¤   ¤   ·* flag to denote what we've found/buffered:
1cf4da ¤   ¤   ·*¤ 0) no match
0ff5f7 ¤   ¤   ·*¤ 1) full match
0a36fb ¤   ¤   ·*¤ 2) partial match (and we buffered data)
ea9de3 ¤   ¤   ·*/
fde231 ¤   ¤   if (!context->state) {
dbbf4f ¤   ¤   ¤   flag = 0;
3a3b08 ¤   ¤   ¤   if (!context->linebuf) {
2df492 ¤   ¤   ¤   ¤   /* nothing is buffered */
5ecb09 ¤   ¤   ¤   ¤   if (*buf == '-')
37ab72 ¤   ¤   ¤   ¤   ¤   flag = 1;
32a3a6 ¤   ¤   ¤   }
045a57 ¤   ¤   ¤   if (!flag) {
dfd339 ¤   ¤   ¤   ¤   t = pgpMin (5, size - context->linebuf);
708e86 ¤   ¤   ¤   ¤   for (i = 0; i < t; i++)
a2dd5c ¤   ¤   ¤   ¤   ¤   if (buf[i] != from[context->linebuf +
e19acb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···i]) {
465a4c ¤   ¤   ¤   ¤   ¤   ¤   pgpFifoWrite
75a687 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (context->fd,
c763de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·context->header,
c6d81e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·context->input,
80bd79 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·context->linebuf);
4a5679 ¤   ¤   ¤   ¤   ¤   ¤   context->linebuf = 0;
3200eb ¤   ¤   ¤   ¤   ¤   ¤   break;
701c89 ¤   ¤   ¤   ¤   ¤   }
12ab0f ¤   ¤   ¤   ¤   if (i == t) {
fa5a54 ¤   ¤   ¤   ¤   ¤   /* We matched the whole input buffer */
17143b ¤   ¤   ¤   ¤   ¤   if (i + context->linebuf == 5)
a39c7a ¤   ¤   ¤   ¤   ¤   ¤   flag = 1;
073c4b ¤   ¤   ¤   ¤   ¤   else {
226c38 ¤   ¤   ¤   ¤   ¤   ¤   memcpy (context->input +
82fb38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   context->linebuf, buf,
c3326e ¤   ¤   ¤   ¤   ¤   ¤   ¤   t);
c2f35e ¤   ¤   ¤   ¤   ¤   ¤   context->linebuf += t;
407e42 ¤   ¤   ¤   ¤   ¤   ¤   size -= t;
fb6fbb ¤   ¤   ¤   ¤   ¤   ¤   buf += t;
43731e ¤   ¤   ¤   ¤   ¤   ¤   flag = 2;
331c89 ¤   ¤   ¤   ¤   ¤   }
bd2613 ¤   ¤   ¤   ¤   }
54a3a6 ¤   ¤   ¤   }
cbb7b2 ¤   ¤   ¤   if (flag == 1) {
926afd ¤   ¤   ¤   ¤   pgpFifoWrite (context->fd, context->header,
513114 ¤   ¤   ¤   ¤   ¤   ······(PGPByte const *)"- ", 2);
79c252 ¤   ¤   ¤   ¤   if (context->linebuf) {
faa797 ¤   ¤   ¤   ¤   ¤   pgpFifoWrite (context->fd,
9ac6d2 ¤   ¤   ¤   ¤   ¤   ¤   ······context->header,
cadebe ¤   ¤   ¤   ¤   ¤   ¤   ······context->input,
56e67e ¤   ¤   ¤   ¤   ¤   ¤   ······context->linebuf);
ae6fbc ¤   ¤   ¤   ¤   ¤   context->linebuf = 0;
b32613 ¤   ¤   ¤   ¤   }
37a3a6 ¤   ¤   ¤   }
5eaf5a
bac8ab ¤   ¤   ¤   if (flag != 2)
ed6367 ¤   ¤   ¤   ¤   context->state = 1;
410fe4 ¤   ¤   }
35af5a
af259b ¤   ¤   *error = armorFlushHeader (context);
d4cf31 ¤   ¤   if (*error)
c93ad8 ¤   ¤   ¤   return size0 - size;
--f639 00022a8541240100188 Page 11 of pgpArmor.c
e0af5a
8cc910 ¤   ¤   for (ptr = buf; ptr < buf+size; ptr++) {
3c45df ¤   ¤   ¤   if (*ptr == '\r' || *ptr == '\n') {
39a788 ¤   ¤   ¤   ¤   context->state = (*ptr++ == '\r') ?
d191ec ¤   ¤   ¤   ¤   ¤   2 : 0;
b4f622 ¤   ¤   ¤   ¤   break;
b0a3a6 ¤   ¤   ¤   }
940fe4 ¤   ¤   }
d1af5a
655e1e do_write:
c6a91f ¤   ¤   written = context->tail->write (context->tail, buf,
530346 ¤   ¤   ¤   ¤   ¤   ¤   ptr-buf, error);
38d06f ¤   ¤   buf += written;
1d28a7 ¤   ¤   size -= written;
d2cf31 ¤   ¤   if (*error)
243ad8 ¤   ¤   ¤   return size0 - size;
3aaf5a
259371 ¤   }
cc67c5 ¤
cfb5d3 ¤   return size0 - size;
81efe6 }
dcaf5a
4338e5 /*
7229e2 ·* This function creates a pgp-mime multipart/signed (clearsigned) message.
796abc ·* We are now assuming that caller is responsible for giving us a good,
54a2f3 ·* MIME formatted body part. ·So we just pass it through.
17495d ·*/
0d5d09 static size_t
8c9684 armorDoMimesign (PGPPipeline *myself, PGPByte const *buf, size_t size,
0470bc ¤   ¤   ·PGPError *error)
41bb36 {
6b98bc ¤   ArmorContext *context = (ArmorContext *)myself->priv;
da282d ¤   size_t written, size0 = size;
52af5a
76a0eb ¤   while (size) {
9a71e2 ¤   ¤   written = context->tail->write (context->tail, buf, size, error);
11d06f ¤   ¤   buf += written;
0428a7 ¤   ¤   size -= written;
cecf31 ¤   ¤   if (*error)
3b3ad8 ¤   ¤   ¤   return size0 - size;
6e9371 ¤   }
a667c5 ¤
34b5d3 ¤   return size0 - size;
ddefe6 }
b1af5a
295d09 static size_t
f1f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
dabb36 {
43a45a ¤   ArmorContext *context;
3f65a9 ¤   size_t retval, written = 0;
d9af5a
d029be ¤   pgpAssert (myself);
efeb3a ¤   pgpAssert (myself->magic == ARMORMAGIC);
b44866 ¤   pgpAssert (error);
57af5a
e57b54 ¤   context = (ArmorContext *)myself->priv;
20d30a ¤   pgpAssert (context);
75ebf4 ¤   pgpAssert (context->tail);
a6af5a
51d216 ¤   if (context->outlen) {
ac5300 ¤   ¤   *error = DoFlush (myself);
b7cf31 ¤   ¤   if (*error)
db8144 ¤   ¤   ¤   return 0;
229371 ¤   }
c7af5a
3ce16e ¤   if (context->clearsign) {
0e2402 ¤   ¤   if (context->pgpmime)
6cbaa5 ¤   ¤   ¤   return armorDoMimesign (myself, buf, size, error);
e70e1d ¤   ¤   else
77b1d8 ¤   ¤   ¤   return armorDoClearsign (myself, buf, size, error);
aa9371 ¤   }
22af5a
--1443 000ad07c65840100188 Page 12 of pgpArmor.c
6e65a0 ¤   if (!context->sizevalid || context->version > PGPVERSION_3) {
f727a2 ¤   ¤   written = pgpFifoWrite (context->fd, context->fifo, buf, size);
e5af5a
7b4156 ¤   ¤   if (context->version <= PGPVERSION_3)
42ab0f ¤   ¤   ¤   return written;
ba9371 ¤   }
fdaf5a
5d1ee0 ¤   *error = armorFlushFifo (myself);
425878 ¤   if (*error || context->version > PGPVERSION_3)
285d6a ¤   ¤   return written;
ddaf5a
d13cbd ¤   /* Try to write all the data we were given */
dd43ab ¤   do {
1087d4 ¤   ¤   retval = armorWriteBytes (myself, buf, size, error);
5449d8 ¤   ¤   written += retval;
84ea46 ¤   ¤   buf += retval;
8fd549 ¤   ¤   size -= retval;
44cf31 ¤   ¤   if (*error)
59ab0f ¤   ¤   ¤   return written;
810fea ¤   } while (size);
c6af5a
0e279e ¤   return written;
16efe6 }
3aaf5a
f4f1ae static PGPError
ef13c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
05b0b1 ¤   ··PGPByte const *string, size_t size)
d1bb36 {
68a45a ¤   ArmorContext *context;
105b01 ¤   PGPError¤   error = kPGPError_NoErr;
5baf5a
e729be ¤   pgpAssert (myself);
f4eb3a ¤   pgpAssert (myself->magic == ARMORMAGIC);
04af5a
317b54 ¤   context = (ArmorContext *)myself->priv;
4bd30a ¤   pgpAssert (context);
edaf5a
300c50 ¤   switch( type ) {
81d495 ¤   case PGPANN_PGPMIME_HEADER_SIZE:
d04f06 ¤   ¤   pgpAssert( size == sizeof(PGPSize) );
3c906b ¤   ¤   *(PGPSize *)string = context->mimebodyoff;
3c2f68 ¤   ¤   break;
267636 ¤   case PGPANN_PGPMIME_HEADER_LINES:
f7a994 ¤   ¤   pgpAssert( size == sizeof(PGPUInt32) );
5c2333 ¤   ¤   *(PGPUInt32 *)string = context->mimeheaderlines;
0d2f68 ¤   ¤   break;
2bf216 ¤   case PGPANN_PGPMIME_SEPARATOR:
1c8b39 ¤   ¤   if (context->pgpmime == PGPMIMEENC) {
d25b19 ¤   ¤   ¤   strncpy((char *)string, MIMEENCSEP,
195311 ¤   ¤   ¤   ¤   ¤   pgpMin(size, strlen(MIMEENCSEP)+1));
a745a6 ¤   ¤   } else {
826f19 ¤   ¤   ¤   strncpy((char *)string, context->mimesigsep,
17ce9c ¤   ¤   ¤   ¤   ¤   pgpMin(size, NSEPCHARS+1));
060fe4 ¤   ¤   }
9d2f68 ¤   ¤   break;
202f72 ¤   default:
ad29e4 ¤   ¤   if (context->tail)
85313e ¤   ¤   ¤   error = context->tail->annotate (context->tail, origin, type,
491665 ¤   ¤   ¤   ¤   ¤   ¤   ·string, size);
342f68 ¤   ¤   break;
499371 ¤   }
0eff2e ¤   if (!error)
e86467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
8204c8 ¤   pgpAssert(context->scope_depth != -1);
d7c674 ¤   return error;
43efe6 }
d3af5a
8cf1ae static PGPError
814b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
bdbb36 {
ada45a ¤   ArmorContext *context;
ad5b01 ¤   PGPError¤   error = kPGPError_NoErr;
--44e8 0006752595040100188 Page 13 of pgpArmor.c
cb450e ¤   unsigned long total;
53af5a
4e29be ¤   pgpAssert (myself);
c1eb3a ¤   pgpAssert (myself->magic == ARMORMAGIC);
82af5a
747b54 ¤   context = (ArmorContext *)myself->priv;
92d30a ¤   pgpAssert (context);
93ebf4 ¤   pgpAssert (context->tail);
5daf5a
74f39d ¤   /* Only handle bytes until EOF */
5ecc58 ¤   if (context->scope_depth)
0cb840 ¤   ¤   return kPGPError_NoErr;
f5af5a
280020 ¤   /* Then compute maxparts */
796183 ¤   if (!context->sizevalid) {
d1fb5f ¤   ¤   if (context->armorlines) {
a26896 ¤   ¤   ¤   total = bytes + pgpFifoSize (context->fd,
b86696 ¤   ¤   ¤   ¤   ¤   ¤   ·····context->fifo);
baaf5a
a2ba29 ¤   ¤   ¤   if (context->version > PGPVERSION_3 &&·
a21748 ¤   ¤   ¤   ····context->thispart) {
1dab27 ¤   ¤   ¤   ¤   total += 48 * context->armorlines *
ce8858 ¤   ¤   ¤   ¤   ¤   (context->thispart - 1);
c912b1 ¤   ¤   ¤   ¤   total += 48 * context->lineno;
31a3a6 ¤   ¤   ¤   }
46af5a
695432 ¤   ¤   ¤   /* 48 bytes / line */
84cdcc ¤   ¤   ¤   context->maxparts = total / (context->armorlines * 48);
76ecca ¤   ¤   ¤   if (context->maxparts)
fc5b07 ¤   ¤   ¤   ¤   context->maxparts++;
5f0fe4 ¤   ¤   }
4a9371 ¤   }
b852e9 ¤   context->sizevalid = 1;
f056b6 ¤   if (bytes)
ecfcc9 ¤   ¤   return kPGPError_NoErr;¤/* dont handle any more non-zero sizeAdvises */
a1af5a
5c538e ¤   /* This is the end */
d4bd8d ¤   context->sizevalid = 2;
35af5a
f32241 ¤   /* Clear out the clearsign buffer, if we have it. */
75227d ¤   if (context->clearsign && context->linebuf) {
56eacb ¤   ¤   pgpFifoWrite (context->fd, context->header, context->input,
30b7b6 ¤   ¤   ¤   ······context->linebuf);
a18b29 ¤   ¤   context->linebuf = 0;
d89371 ¤   }
9caf5a
f9d8af ¤   /*
938ea6 ¤   ·* If clearsign input ended with '\r', will be hashed with '\r\n' but
e171ad ¤   ·* the output file will be missing the '\n'. ·Add it here.
bfa4e3 ¤   ·*/
36e21e ¤   if (context->clearsign && context->state==2) {
8990be ¤   ¤   pgpFifoWrite (context->fd,·
45143e ¤   ¤   ¤   ·context->header, ·(const unsigned char *) "\n",·
6481fd ¤   ¤   ¤   ······1);
b31f19 ¤   ¤   context->state = 0;
069371 ¤   }
7caf5a
db9a81 ¤   error = armorFlushFifo (myself);
e00161 ¤   if (error)
c4fcee ¤   ¤   return error;
c367c5 ¤
38bde6 ¤   if (!context->didheader && !context->clearsign)
0dbd06 ¤   ¤   armorMakeHeader (context);
7d7d5b ¤   error = DoFlush (myself);
fb0161 ¤   if (error)
fcfcee ¤   ¤   return error;
bdaf5a
298cbe ¤   if (!context->clearsign) {
bc2e2c ¤   ¤   armorMakeFooter (context);
24af5a
da3f2c ¤   ¤   /* Set clearsign so we don't emit another CRC */
67c586 ¤   ¤   context->clearsign = 1;
--d500 000c5b09f6b40100188 Page 14 of pgpArmor.c
e0af5a
2a4a53 ¤   ¤   error = DoFlush (myself);
b9e3c2 ¤   ¤   if (error)
d53b5b ¤   ¤   ¤   return error;
959371 ¤   }
31af5a
99cb05 ¤   if (context->tail)
888d61 ¤   ¤   error = context->tail->sizeAdvise (context->tail, bytes);
c8c674 ¤   return error;
b3efe6 }
59af5a
25f1ae static PGPError
1ac7e1 Teardown (PGPPipeline *myself)
d4bb36 {
1699ab ¤   ArmorContext *¤ context;
b2e9fa ¤   PGPContextRef¤  cdkContext;
f267c5 ¤
2f3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
4e696e ¤   cdkContext¤ = myself->cdkContext;
1caf5a
2d29be ¤   pgpAssert (myself);
49eb3a ¤   pgpAssert (myself->magic == ARMORMAGIC);
abaf5a
8c7b54 ¤   context = (ArmorContext *)myself->priv;
04d30a ¤   pgpAssert (context);
0faf5a
accb05 ¤   if (context->tail)
961e8a ¤   ¤   context->tail->teardown (context->tail);
3aaf5a
683cff ¤   pgpFifoDestroy (context->fd, context->fifo);
d3466c ¤   pgpFifoDestroy (context->fd, context->header);
4175ad ¤   if (context->messageid)
05c7a1 ¤   {
57d728 ¤   ¤   pgpContextMemFree( cdkContext, context->messageid);
dd9371 ¤   }
c81b52 ¤   ¤
911b52 ¤   ¤
7a10cc ¤   pgpClearMemory ( context, sizeof (*context) );
78fa6e ¤   pgpContextMemFree( cdkContext, context);
4267c5 ¤
412d68 ¤   return( kPGPError_NoErr );
ebefe6 }
2caf5a
261ce8 #define ATYPE_NORMAL¤   0
4a972c #define ATYPE_CLEARSIG¤ 10
ee76b1 #define ATYPE_SEPSIG¤   20
bf0b59 #define ATYPE_SEPSIGMSG¤21
31015b #define ATYPE_MIMESIG¤  30
9325ad #define ATYPE_MIMEENC¤  40
ed33b3 #define ATYPE_MIMESEPSIG 50
b4af5a
f5e73a static PGPPipeline **
86920f armorDoCreate (
0ef3cb ¤   PGPContextRef¤  ¤   ¤   cdkContext,
750692 ¤   PGPPipeline **¤ ¤   ¤   head,
3e3261 ¤   ArmorContext **¤¤   ¤   pcontext,
006124 ¤   PGPEnv const *¤ ¤   ¤   env,
0c18a0 ¤   PgpVersion¤ ¤   ¤   ¤   version,
fffe98 ¤   PGPFifoDesc const *¤¤   fd,
274b45 ¤   PGPRandomContext const *rc,
4c8e80 ¤   unsigned long¤  ¤   ¤   armorlines,
450b48 ¤   int¤¤   ¤   ¤   ¤   ¤   armortype,
565e33 ¤   PGPByte const *¤¤   ¤   hashlist,
09c609 ¤   unsigned¤   ¤   ¤   ¤   hashlen)
72bb36 {
140df0 ¤   PGPPipeline *mod;
03a45a ¤   ArmorContext *context;
8e3566 ¤   PGPFifoContext *fifo;
cf4d1f ¤   PGPFifoContext *header;
6aaf5a
c6bb3d ¤   if (!head)
c57ed2 ¤   ¤   return NULL;
--a5a6 0009a424d4040100188 Page 15 of pgpArmor.c
e0af5a
bf8b3b ¤   pgpAssert (fd);
49af5a
964a61 ¤   context = (ArmorContext *)pgpContextMemAlloc( cdkContext,
094db0 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear );
11e31e ¤   if ( IsNull( context ) )
387ed2 ¤   ¤   return NULL;
973755 ¤   mod¤= &context->pipe;
4268c7 ¤   if( IsntNull( pcontext ) )
2570da ¤   ¤   *pcontext = context;
f8af5a
3e29f7 ¤   fifo = pgpFifoCreate ( cdkContext, fd);
151c5f ¤   if (!fifo) {
c7a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
ca7ed2 ¤   ¤   return NULL;
eb9371 ¤   }
d5777e ¤   header = pgpFifoCreate (cdkContext, fd);
6fd652 ¤   if (!header) {
8355db ¤   ¤   pgpFifoDestroy (fd, fifo);
c0a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
257ed2 ¤   ¤   return NULL;
c39371 ¤   }
478f5f ¤   mod->magic = ARMORMAGIC;
f31f83 ¤   mod->write = Write;
e3ac4e ¤   mod->flush = Flush;
d90aaf ¤   mod->sizeAdvise = SizeAdvise;
6dd3a2 ¤   mod->annotate = Annotate;
2b96de ¤   mod->teardown = Teardown;
5f3c4e ¤   mod->name = "ASCII Armor Write Module";
0c01ea ¤   mod->priv = context;
e4a99e ¤   mod->cdkContext¤= cdkContext;
74af5a
289fa0 ¤   context->cdkContext = cdkContext;·
9f0ae6 ¤   context->outptr = context->output;
3bc762 ¤   context->armorlines = armorlines;
70e2c3 ¤   context->crc = CRC_INIT;
aaf7da ¤   context->fd = fd;
1ed5cd ¤   context->fifo = fifo;
21a85e ¤   context->header = header;
9a46a2 ¤   context->version = version;
c4e315 ¤   context->comment¤   = pgpenvGetCString (env, PGPENV_COMMENT, NULL );
1e53f3 ¤   context->versionString = pgpenvGetCString( env,
e07311 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPENV_VERSION_STRING, NULL );
11af5a
6872c0 ¤   /* Will need to create a message id; now done deterministically later */
84154d ¤   if (rc) {
0b94db ¤   ¤   context->needmessageid = TRUE;
649371 ¤   }
cfaf5a
5db8a5 ¤   if (armortype == ATYPE_CLEARSIG) {
027806 #define CLRSIGN "-----BEGIN PGP SIGNED MESSAGE-----"
882154 ¤   ¤   int dohash=0;
438674 ¤   ¤   PGPHashVTBL const *hash;
3faf5a
5b8a75 ¤   ¤   pgpFifoWrite (fd, header, (PGPByte const *)CLRSIGN,
f74aab ¤   ¤   ¤   ······strlen (CLRSIGN));
32c586 ¤   ¤   context->clearsign = 1;
7f0a60 ¤   ¤   context->armorlines = 0;
d2af5a
7c1b17 ¤   ¤   /*
47c45d ¤   ¤   ·* Now deal with multiple hash types. ·If we don't specify
22dce1 ¤   ¤   ·* the hash type, or the only hash used is MD5, then ignore
a6f7d1 ¤   ¤   ·* the Hash header. ·Otherwise, we should print the out
999de3 ¤   ¤   ·*/
dab341 ¤   ¤   if (!hashlen || (hashlen == 1 && *hashlist == kPGPHashAlgorithm_MD5))
550caa ¤   ¤   ¤   goto clearsig_end;
13b0db ¤   ¤   pgpFifoWrite (fd, header, (PGPByte const *)"\nHash: ", 7);
933fb0 ¤   ¤   while (hashlen--) {
a115cc ¤   ¤   ¤   hash = pgpHashByNumber ( (PGPHashAlgorithm) (*hashlist++) );
12c3df ¤   ¤   ¤   if (hash) {
9d9f43 ¤   ¤   ¤   ¤   if (dohash)
9ab8da ¤   ¤   ¤   ¤   ¤   pgpFifoWrite (fd, header,
--747a 000cac7a72640100188 Page 16 of pgpArmor.c
ad13da ¤   ¤   ¤   ¤   ¤   ¤   ······(PGPByte const *)", ", 2);
a6811f ¤   ¤   ¤   ¤   pgpFifoWrite (fd, header,
20fb2a ¤   ¤   ¤   ¤   ¤   ······(PGPByte const *)hash->name,
f9c0ac ¤   ¤   ¤   ¤   ¤   ······strlen (hash->name));
107803 ¤   ¤   ¤   ¤   dohash = 1;
8ca3a6 ¤   ¤   ¤   }
000fe4 ¤   ¤   }
7512a7 clearsig_end:
513c33 ¤   ¤   pgpFifoWrite (fd, header, (PGPByte const *)"\n\n", 2);
11b680 ¤   ¤   context->didheader = TRUE;¤ ¤   /* No need for header here */
679985 ¤   } else if (armortype == ATYPE_MIMESIG) {
e2cdb8 //¤ ¤   pgpFifoWrite (fd, header, (PGPByte const *)MIMETOPHDR,
fbceef //¤ ¤   ¤   ······strlen(MIMETOPHDR));
1dc586 ¤   ¤   context->clearsign = 1;
0b0a60 ¤   ¤   context->armorlines = 0;
1936d8 ¤   ¤   context->pgpmime = PGPMIMESIG;
ef8f8f ¤   } else if (armortype == ATYPE_SEPSIG) {
15539c ¤   ¤   context->blocktype = "SIGNATURE";
49fad2 ¤   } else if (armortype == ATYPE_SEPSIGMSG) {
442af7 ¤   ¤   context->blocktype = "MESSAGE";
4597e6 ¤   } else if (armortype == ATYPE_MIMESEPSIG) {
142af7 ¤   ¤   context->blocktype = "MESSAGE";
bd36d8 ¤   ¤   context->pgpmime = PGPMIMESIG;
8c0a60 ¤   ¤   context->armorlines = 0;
ba4540 ¤   } else if (armortype == ATYPE_MIMEENC) {
d78d40 ¤   ¤   context->pgpmime = PGPMIMEENC;
000a60 ¤   ¤   context->armorlines = 0;
31adb4 ¤   ¤   context->pgpmimeversionline =
e1a7be ¤   ¤   ¤   pgpenvGetInt( env, PGPENV_PGPMIMEVERSIONLINE, NULL, NULL );
c09371 ¤   }
06af5a
7965ad ¤   context->tail = *head;
c12d11 ¤   *head = mod;
f77fa2 ¤   return &context->tail;
4cefe6 }
abaf5a
f341cd PGPPipeline **
b008ce pgpArmorWriteCreate (
48fdf9 ¤   PGPContextRef cdkContext,
4f8941 ¤   PGPPipeline **head,
e736a4 ¤   PGPEnv const *env,
b5fc19 ¤   PGPFifoDesc const *fd,
a64b45 ¤   PGPRandomContext const *rc,
471d37 ¤   PgpVersion version,
c497d4 ¤   PGPByte armortype)
45bb36 {
4fdca1 ¤   int type = 0;
42f63b ¤   unsigned long armorlines;
4b87a6 ¤   PGPError¤   error;
fdaf5a
6bbb3d ¤   if (!head)
5e7ed2 ¤   ¤   return NULL;
37af5a
193391 ¤   if (armortype == PGP_ARMOR_NORMAL) {
35377a ¤   ¤   if (pgpenvGetInt (env, PGPENV_PGPMIME, NULL, &error)) {
9ffbec ¤   ¤   ¤   type = ATYPE_MIMEENC;
647093 ¤   ¤   ¤   rc = NULL; /* prevents messageid appearing */
bd45a6 ¤   ¤   } else {
0b2d68 ¤   ¤   ¤   type = ATYPE_NORMAL;
a90fe4 ¤   ¤   }
a51c3f ¤   } else if (armortype == PGP_ARMOR_SEPSIG) {
5a8f1c ¤   ¤   type = ATYPE_SEPSIG;
9a43a5 ¤   } else if (armortype == PGP_ARMOR_SEPSIGMSG) {
425a0f ¤   ¤   type = ATYPE_SEPSIGMSG;
f8f037 ¤   } else {
0a7ed2 ¤   ¤   return NULL;
dc9371 ¤   }
0aaf5a
dd954d ¤   armorlines = pgpenvGetInt (env, PGPENV_ARMORLINES, NULL, NULL);
8aaf5a
1baf5a
ca9c88 ¤   return (armorDoCreate ( cdkContext,
--1666 00073e3c5b640100188 Page 17 of pgpArmor.c
a81516 ¤   ¤   head, NULL, env, version, fd, rc, armorlines, type, NULL, 0));
ffefe6 }
4daf5a
1641cd PGPPipeline **
1d35ee pgpArmorWriteCreateClearsig (
05cc23 ¤   PGPPipeline **texthead,
dffead ¤   PGPPipeline **signhead,
3e36a4 ¤   PGPEnv const *env,
7ffc19 ¤   PGPFifoDesc const *fd,
46ce74 ¤   PgpVersion version, PGPByte *hashlist,
630e96 ¤   unsigned hashlen)
d1bb36 {
884b93 ¤   PGPPipeline *txthead = NULL, *sighead = NULL;
65ff88 ¤   PGPPipeline **joinhead, **sigtail, **tail;
2da45a ¤   ArmorContext *context;
e6ba82 ¤   PGPContextRef¤  cdkContext¤ = pgpenvGetContext( env );
8daf5a
f567b1 ¤   if (!texthead || !signhead)
c67ed2 ¤   ¤   return NULL;
dfaf5a
5ac5ee ¤   joinhead = armorDoCreate ( cdkContext,
acf848 ¤   ¤   ¤   &txthead, NULL, env, version, fd, NULL, 0,
d966ba ¤   ¤   ¤   ¤   ··ATYPE_CLEARSIG, hashlist, hashlen);
5369bb ¤   if (!joinhead)
6e7ed2 ¤   ¤   return NULL;
48af5a
531636 ¤   tail = pgpJoinCreate (cdkContext, joinhead, fd);
28b2e1 ¤   if (!tail) {
ea3597 ¤   ¤   txthead->teardown (txthead);
897ed2 ¤   ¤   return NULL;
f89371 ¤   }
80af5a
e7b4b6 ¤   sigtail = armorDoCreate ( cdkContext,
004923 ¤   ¤   ¤   &sighead, NULL, env, version, fd, NULL, 0, ATYPE_SEPSIG, NULL, 0);
bd963a ¤   if (!sigtail) {
4d3597 ¤   ¤   txthead->teardown (txthead);
077ed2 ¤   ¤   return NULL;
b49371 ¤   }
5aaf5a
5c0f45 ¤   /* Add the charset used when generating the clearsigned message */
bf5543 ¤   context = (ArmorContext *)sighead->priv;
b4d30a ¤   pgpAssert (context);
3c1d1f ¤   context->charset¤   = pgpenvGetCString (env, PGPENV_CHARSET, NULL);
268aaa ¤   /* noconv is default, don't put it in */
52f519 ¤   if( strcmp( context->charset, "noconv" ) == 0) {
dad44f ¤   ¤   context->charset = NULL;
749371 ¤   }
0aaf5a
e3bb30 ¤   *sigtail = pgpJoinAppend (*joinhead);
21698f ¤   if (!*sigtail) {
543597 ¤   ¤   txthead->teardown (txthead);
b5d829 ¤   ¤   sighead->teardown (sighead);
b57ed2 ¤   ¤   return NULL;
1c9371 ¤   }
a61b52 ¤   ¤
93281a ¤   pgpJoinBuffer (*sigtail, (PGPByte *)"\n", 1);
a4af5a
4d73db ¤   *texthead = txthead;
2bed03 ¤   *signhead = sighead;
1fca79 ¤   return tail;
f0efe6 }
39af5a
c741cd PGPPipeline **
531b49 pgpArmorWriteCreatePgpMimesig (
81b16d ¤   PGPPipeline **texttail,
1683e3 ¤   PGPPipeline **signtail,
ba36a4 ¤   PGPEnv const *env,
affc19 ¤   PGPFifoDesc const *fd,
6e4b45 ¤   PGPRandomContext const *rc,
43ce74 ¤   PgpVersion version, PGPByte *hashlist,
660e96 ¤   unsigned hashlen)
73bb36 {
--6eff 0001342ca8b40100188 Page 18 of pgpArmor.c
078c11 ¤   ArmorContext *context, *sigcontext;
c84b93 ¤   PGPPipeline *txthead = NULL, *sighead = NULL;
9dff88 ¤   PGPPipeline **joinhead, **sigtail, **tail;
5c43ea ¤   PGPPipeline **splithead, **splittail;
b3ba82 ¤   PGPContextRef¤  cdkContext¤ = pgpenvGetContext( env );
81f539 ¤   PGPByte¤¤   sepbits[(NSEPCHARS+7)/8];
09eb25 ¤   PGPSize¤¤   bodyoff = 0;
c0f744 ¤   PGPUInt32¤  headerlines = 0;
400721 ¤   PGPUInt32¤  i;
d4af5a
c6a957 ¤   if (!texttail || !signtail || !rc)
d07ed2 ¤   ¤   return NULL;
faaf5a
59ce53 ¤   splithead = armorDoCreate ( cdkContext,
e6bfed ¤   ¤   &txthead, &context, env, version, fd, NULL, 0,
4a412c ¤   ¤   ·ATYPE_MIMESIG, hashlist, hashlen);
222f14 ¤   if (!splithead)
587ed2 ¤   ¤   return NULL;
69af5a
c5eae6 ¤   /* Create split to take output from clearmime armor module */
e0d667 ¤   joinhead = pgpSplitCreate(cdkContext, splithead);
22af5a
466598 ¤   /* Set second split output to go to signing pipeline */
7bfb28 ¤   splittail = pgpSplitAdd (*splithead);
156c93 ¤   *splittail = *texttail;
c3af5a
3314de ¤   tail = pgpJoinCreate ( cdkContext, joinhead, fd);
1db2e1 ¤   if (!tail) {
633597 ¤   ¤   txthead->teardown (txthead);
597ed2 ¤   ¤   return NULL;
579371 ¤   }
0baf5a
9c149c ¤   sigtail = armorDoCreate ( cdkContext, &sighead, &sigcontext, env, version,
8d64a5 ¤   ¤   ¤   ¤   fd, NULL, 0, ATYPE_MIMESEPSIG, NULL, 0);
0c963a ¤   if (!sigtail) {
713597 ¤   ¤   txthead->teardown (txthead);
8a7ed2 ¤   ¤   return NULL;
6f9371 ¤   }
8daf5a
98bb30 ¤   *sigtail = pgpJoinAppend (*joinhead);
2d698f ¤   if (!*sigtail) {
923597 ¤   ¤   txthead->teardown (txthead);
12d829 ¤   ¤   sighead->teardown (sighead);
437ed2 ¤   ¤   return NULL;
379371 ¤   }
a7af5a
08f2ce ¤   /* Create a random message separator */
23700e ¤   pgpRandomGetBytes (rc, sepbits, (NSEPCHARS+7)/8);
aa5d24 ¤   for (i=0; i<NSEPCHARS; ++i) {
9219ec ¤   ¤   context->mimesigsep[i] = ((sepbits[i/8]>>(i&7))&1) ? '-' : '=';
ba9371 ¤   }
aa2b61 ¤   context->mimesigsep[NSEPCHARS] = '\0';
821fb5 ¤   pgpCopyMemory(context->mimesigsep, sigcontext->mimesigsep, NSEPCHARS+1);
deaf5a
70eb34 ¤   bodyoff = 0;
bf36a2 ¤   headerlines = 0;
614906 ¤   context->pgpmimeversionline = pgpenvGetInt( env,
2f4e1c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPENV_PGPMIMEVERSIONLINE, NULL, NULL );
8c3b56 ¤   if( context->pgpmimeversionline ) {
465062 ¤   ¤   pgpJoinBuffer (*joinhead, (PGPByte *)MIMESIGHDR1a,
970721 ¤   ¤   ¤   ¤   ¤   ···strlen(MIMESIGHDR1a));
63fbf8 ¤   ¤   bodyoff += strlen(MIMESIGHDR1a);
b4f23f ¤   ¤   headerlines += MIMESIGHDRLINESa;
649371 ¤   }
6ebec8 ¤   pgpJoinBuffer (*joinhead, (PGPByte *)MIMESIGHDR1b, strlen(MIMESIGHDR1b));
022fee ¤   pgpJoinBuffer (*joinhead, (PGPByte *)context->mimesigsep, NSEPCHARS);
049274 ¤   pgpJoinBuffer (*joinhead, (PGPByte *)MIMESIGHDR2, strlen(MIMESIGHDR2));
99b8d0 ¤   bodyoff += strlen(MIMESIGHDR1b) + NSEPCHARS + strlen(MIMESIGHDR2);
aa18b6 ¤   headerlines += MIMESIGHDRLINESb;
b36517 ¤   if (!hashlen) {
fcb0e1 ¤   ¤   pgpJoinBuffer (*joinhead, (PGPByte *)MIMEMIC, strlen(MIMEMIC));
1380e0 ¤   ¤   pgpJoinBuffer (*joinhead, (PGPByte *)MIMEDFLTMIC,
--0003 00136d2846140100188 Page 19 of pgpArmor.c
38d625 ¤   ¤   ¤   ¤   strlen(MIMEDFLTMIC));
c5c7bf ¤   ¤   bodyoff += strlen(MIMEMIC) + strlen(MIMEDFLTMIC);
e7f037 ¤   } else {
1c3fb0 ¤   ¤   while (hashlen--) {
a8181b ¤   ¤   ¤   PGPHashVTBL const *hash = NULL;
288e51 ¤   ¤   ¤   unsigned j, len;
dd0b3c ¤   ¤   ¤   char hashname[30]; /* lower case name */
41af5a
e915cc ¤   ¤   ¤   hash = pgpHashByNumber ( (PGPHashAlgorithm) (*hashlist++) );
4742a1 ¤   ¤   ¤   pgpAssert(hash);
bdbf34 ¤   ¤   ¤   len = strlen(hash->name);
a97fb2 ¤   ¤   ¤   pgpAssert (len < sizeof(hashname));
238d2f ¤   ¤   ¤   pgpJoinBuffer (*joinhead, (PGPByte *)MIMEMIC,
a9b3c5 ¤   ¤   ¤   ¤   ·······strlen(MIMEMIC));
08d66b ¤   ¤   ¤   for (j=0; j<len; ++j)
610e2c ¤   ¤   ¤   ¤   hashname[j] = tolower(hash->name[j]);
d821a0 ¤   ¤   ¤   pgpJoinBuffer (*joinhead, (PGPByte *)hashname,
088723 ¤   ¤   ¤   ¤   ·······len);
b42283 ¤   ¤   ¤   bodyoff += strlen(MIMEMIC) + len;
b31c72 ¤   ¤   ¤   if( hashlen ) {
22b80c ¤   ¤   ¤   ¤   pgpJoinBuffer (*joinhead, (PGPByte *)";", 1);
e421b2 ¤   ¤   ¤   ¤   bodyoff += 1;
a7a3a6 ¤   ¤   ¤   }
090fe4 ¤   ¤   }
fd9371 ¤   }
a74fe4 ¤   pgpJoinBuffer (*joinhead, (PGPByte *)"\n\n", 2);
dbbaad ¤   bodyoff += 2;
fd4bcf ¤   headerlines += 2;
af9b98 ¤   context->mimebodyoff = bodyoff;
d377fa ¤   context->mimeheaderlines = headerlines;
dd0d7b ¤   pgpJoinBuffer (*joinhead, (PGPByte *)"--", 2);
3d2fee ¤   pgpJoinBuffer (*joinhead, (PGPByte *)context->mimesigsep, NSEPCHARS);
4364a4 ¤   pgpJoinBuffer (*joinhead, (PGPByte *)"\n", 1);
aaaf5a
52375b ¤   pgpJoinBuffer (*sigtail, (PGPByte *)"\n--", 3);
7a0bc8 ¤   pgpJoinBuffer (*sigtail, (PGPByte *)context->mimesigsep, NSEPCHARS);
6b281a ¤   pgpJoinBuffer (*sigtail, (PGPByte *)"\n", 1);
c6a317 ¤   pgpJoinBuffer (*sigtail, (PGPByte *)MIMEMIDBOUND, strlen(MIMEMIDBOUND));
32af5a
d44047 ¤   *texttail = txthead;
dede9f ¤   *signtail = sighead;
75ca79 ¤   return tail;
36efe6 }
--6035 0007199ea1640100189 Page 1 of pgpArmor.h
bc38e5 /*
284c0b ·* pgpArmor.h -- Create an armor write module
ad775e ·*
647ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
7b775e ·*
4ed146 ·* $Id: pgpArmor.h,v 1.11 1997/07/25 00:52:32 hal Exp $
9b495d ·*/
c4af5a
4c4bcc #ifndef Included_pgpArmor_h
295d19 #define Included_pgpArmor_h
0caf5a
feadb8 #include "pgpOpaqueStructs.h"
6ae82c #include "pgpPubTypes.h"
2fd11f #include "pgpUsuals.h"
afaf5a
a999c6 PGP_BEGIN_C_DECLARATIONS
4caf5a
b638e5 /*
ad3b56 ·* This creates a module that will take its input and mask it in ASCII
c63999 ·* Armor. ·The armortype should be one of ARMOR_NORMAL, for a normal
439deb ·* armor, or ARMOR_SEPSIG, which is a separate signature.
70495d ·*/
5cf481 PGPPipeline ·**
2e08ce pgpArmorWriteCreate (
04fdf9 ¤   PGPContextRef cdkContext,
aba296 ¤   PGPPipeline **head, PGPEnv const *env,
2d1aa3 ¤   ¤   ·····PGPFifoDesc const *fd,
59c9e0 ¤   ¤   ·····PGPRandomContext const *rc, PgpVersion version,
89221d ¤   ¤   ·····PGPByte armortype);
2baf5a
5038e5 /*
a58716 ·* These are the valid armortypes that can be passed into pgpArmorWriteCreate
c2495d ·*/
01c851 #define PGP_ARMOR_NORMAL¤   ¤   0
4398e6 #define PGP_ARMOR_SEPSIG¤   ¤   1
1eaf5a
5038e5 /*
06af11 ·* XXX: PGP_ARMOR_SEPSIGMSG is identical to PGP_ARMOR_SEPSIG, except that
fd3b3d ·* it outputs "BEGIN PGP MESSAGE" instead of "BEGIN PGP SIGNATURE" for
0fe89b ·* use in a PGP/MIME clear-signed message. ·This is only temporary, and
ecee9e ·* should be deprecated when the library handles PGP/MIME internally.
ad495d ·*/
e73615 #define PGP_ARMOR_SEPSIGMSG¤¤   2
eaaf5a
4a38e5 /*
456565 ·* Create an armor pipeline for clear signatures. ·You should pass in the
e5cad5 ·* tail pointers for the end of the text stream and the end of the signature
c8c552 ·* stream. ·This will return a pointer to the stream that will contain the
8ce3e9 ·* clearsigned message. ·Pass in a list of hash-type-bytes so it can say
c47d06 ·* what is being used.
12495d ·*/
a6f481 PGPPipeline ·**
bf5705 pgpArmorWriteCreateClearsig (PGPPipeline **texthead,
32e177 ¤   ¤   ¤   ·····PGPPipeline **signhead,
cc0d9f ¤   ¤   ¤   ·····PGPEnv const *env,
a8dff6 ¤   ¤   ¤   ·····PGPFifoDesc const *fd,
6c925c ¤   ¤   ¤   ·····PgpVersion version,
3d86bf ¤   ¤   ¤   ·····PGPByte *hashlist, unsigned hashlen);
6caf5a
bd38e5 /*
d36e78 ·* Create an armor pipeline for clear signatures, based on the PGPMIME
5dd625 ·* spec. ·You should pass in the tail pointers for the end of the text
17a5da ·* stream and the end of the signature stream.
a40620 ·* This will return a pointer to the stream
fa68cd ·* that will contain the clearsigned message. ·Pass in a list of
8ba6af ·* hash-type-bytes so it can say what is being used.
f1495d ·*/
61f481 PGPPipeline ·**
3de025 pgpArmorWriteCreatePgpMimesig (PGPPipeline **texttail,
229c39 ¤   ¤   ¤   ·····PGPPipeline **signtail,
5e0d9f ¤   ¤   ¤   ·····PGPEnv const *env,
71dff6 ¤   ¤   ¤   ·····PGPFifoDesc const *fd,
--921c 001f01ac3d040100189 Page 2 of pgpArmor.h
98cfea ¤   ¤   ¤   ¤   ·PGPRandomContext const *rc,
1b925c ¤   ¤   ¤   ·····PgpVersion version,
f286bf ¤   ¤   ¤   ·····PGPByte *hashlist, unsigned hashlen);
b1af5a
bb1254 PGP_END_C_DECLARATIONS
14af5a
f00731 #endif /* Included_pgpArmor_h */
--232a 000484c1b5e4010018a Page 1 of pgpArmrFil.c
bc38e5 /*
c80800 ·* pgpArmrFil.c -- an Armor File Write module. ·It watches for MULTIARMOR
7172f1 ·*¤ annotation scopes and will open multiple files if it occurs.
4484c6 ·*¤ Otherwise, it will only a single file when data is first written.
c9775e ·*
4f7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
50775e ·*
c1d040 ·* $Id: pgpArmrFil.c,v 1.19 1997/12/12 01:13:58 heller Exp $
50495d ·*/
68e2ff #include "pgpConfig.h"
82af5a
6ffeb2 #include <stdio.h>
51af5a
cba146 #include "pgpDebug.h"
e1e62e #include "pgpArmrFil.h"
126aaa #include "pgpAnnotate.h"
113709 #include "pgpFileMod.h"
030d08 #include "pgpMem.h"
022f8d #include "pgpErrors.h"
0272de #include "pgpFile.h"
622ece #include "pgpPipeline.h"
37c26c #include "pgpContext.h"
afaf5a
4c7994 #define ARMORWRITEFILEMAGIC¤0xa434f11e
12af5a
5887e5 typedef struct ArmorFilContext
46bb36 {
44b1a2 ¤   /* by placing this here, we can just allocate everything at once */
01f8fb ¤   PGPPipeline¤¤   pipe;
c367c5 ¤
ff75b0 ¤   PGPPipeline *tail;
9889ee ¤   PGPFile * (*fileOpen) (void *arg,
a8446d ¤   ¤   ¤   ¤   ······void const *baseName, unsigned number);
12425e ········void *arg;
2fdb8f ¤   void const *baseName;
bb7929 ¤   int scope_depth;
a4b150 ¤   DEBUG_STRUCT_CONSTRUCTOR( ArmorFilContext )
ac9eb9 } ArmorFilContext;
acaf5a
baf1ae static PGPError
dcd02e Flush (PGPPipeline *myself)
1fbb36 {
d2148d ¤   ArmorFilContext *context;
d8af5a
9f29be ¤   pgpAssert (myself);
29f482 ¤   pgpAssert (myself->magic == ARMORWRITEFILEMAGIC);
6aaf5a
c254b5 ¤   context = (ArmorFilContext *)myself->priv;
b7d30a ¤   pgpAssert (context);
7c0e36 ¤   if (!context->tail)
83b840 ¤   ¤   return kPGPError_NoErr;
dcaf5a
ed9819 ¤   return context->tail->flush (context->tail);
aaefe6 }
15af5a
cef1ae static PGPError
178a73 openFile (ArmorFilContext *context, unsigned num)
acbb36 {
7772ce ¤   PGPPipeline *tail = NULL;
0bc586 ¤   PGPFile *fp;
3187a6 ¤   PGPError¤   error;
23af5a
66c2be ¤   pgpAssert (!context->tail);
94af5a
6c4847 ¤   fp = context->fileOpen (context->arg, context->baseName, num);
cb485d ¤   if (!fp)
58841f ¤   ¤   return kPGPError_CantOpenFile;
b267c5 ¤
7b9aea ¤   if (!pgpFileWriteCreate ( context->tail->cdkContext, &tail, fp, 1)) {
df37e7 ¤   ¤   error = pgpFileClose (fp);
a3e3c2 ¤   ¤   if (error)
483b5b ¤   ¤   ¤   return error;
--210b 000d5dbb77f4010018a Page 2 of pgpArmrFil.c
c34030 ¤   ¤   return kPGPError_OutOfMemory;
689371 ¤   }
1fabd5 ¤   context->tail = tail;
54151e ¤   return kPGPError_NoErr;
6eefe6 }
2daf5a
e55d09 static size_t
8bf37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
d2bb36 {
5a148d ¤   ArmorFilContext *context;
aaaf5a
7729be ¤   pgpAssert (myself);
5ff482 ¤   pgpAssert (myself->magic == ARMORWRITEFILEMAGIC);
dd4866 ¤   pgpAssert (error);
a5af5a
c454b5 ¤   context = (ArmorFilContext *)myself->priv;
50d30a ¤   pgpAssert (context);
6eaf5a
33c07b ¤   if (!context->tail) {
05b275 ¤   ¤   *error = openFile (context, 0);
85cf31 ¤   ¤   if (*error)
928144 ¤   ¤   ¤   return 0;
8d4032 ¤   }¤  ¤
40af5a
18d39f ¤   return context->tail->write (context->tail, buf, size, error);
f6efe6 }
f5af5a
b2f1ae static PGPError
5113c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
2db0b1 ¤   ··PGPByte const *string, size_t size)
21bb36 {
1d148d ¤   ArmorFilContext *context;
fe5b01 ¤   PGPError¤   error = kPGPError_NoErr;
c3fcf8 ¤   unsigned num;
43af5a
1bdf26 ¤   (void)origin;¤  /* Avoid warning */
497aab ¤   (void)size;
5a29be ¤   pgpAssert (myself);
6bf482 ¤   pgpAssert (myself->magic == ARMORWRITEFILEMAGIC);
f0af5a
a754b5 ¤   context = (ArmorFilContext *)myself->priv;
58d30a ¤   pgpAssert (context);
afaf5a
23f5cb ¤   /* See what we should do here */
eb1609 ¤   switch (type) {
bf6ee1 ¤   case PGPANN_MULTIARMOR_BEGIN:
044942 ¤   ¤   pgpAssert (!context->tail);
19a0d9 ¤   ¤   pgpAssert (size == sizeof (num));
e37e80 ¤   ¤   num = *((unsigned *)string);
305195 ¤   ¤   error = openFile (context, num);
e52f68 ¤   ¤   break;
632620 ¤   case PGPANN_MULTIARMOR_END:
53678b ¤   ¤   pgpAssert (context->tail);
9da059 ¤   ¤   error = context->tail->sizeAdvise (context->tail, 0);
bbe3c2 ¤   ¤   if (error)
5d3b5b ¤   ¤   ¤   return error;
851e8a ¤   ¤   context->tail->teardown (context->tail);
bad7a1 ¤   ¤   context->tail = NULL;
802f68 ¤   ¤   break;
942f72 ¤   default:
7d1d52 ¤   ¤   ;
f69371 ¤   }
c4af5a
5dff2e ¤   if (!error)
e86467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
a404c8 ¤   pgpAssert(context->scope_depth != -1);
5dc674 ¤   return error;
44efe6 }
9daf5a
89f1ae static PGPError
fd4b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
d5bb36 {
--f561 000f69592274010018a Page 3 of pgpArmrFil.c
a3148d ¤   ArmorFilContext *context;
64af5a
6c29be ¤   pgpAssert (myself);
d8f482 ¤   pgpAssert (myself->magic == ARMORWRITEFILEMAGIC);
55af5a
3354b5 ¤   context = (ArmorFilContext *)myself->priv;
a1d30a ¤   pgpAssert (context);
460e36 ¤   if (!context->tail)
fab840 ¤   ¤   return kPGPError_NoErr;
8caf5a
72e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
6eefe6 }
5baf5a
92f1ae static PGPError
89c7e1 Teardown (PGPPipeline *myself)
dabb36 {
be148d ¤   ArmorFilContext *context;
13e9fa ¤   PGPContextRef¤  cdkContext;
6767c5 ¤
673982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
6f696e ¤   cdkContext¤ = myself->cdkContext;
8faf5a
fb29be ¤   pgpAssert (myself);
abf482 ¤   pgpAssert (myself->magic == ARMORWRITEFILEMAGIC);
7caf5a
6654b5 ¤   context = (ArmorFilContext *)myself->priv;
22d30a ¤   pgpAssert (context);
58af5a
4ecb05 ¤   if (context->tail)
a61e8a ¤   ¤   context->tail->teardown (context->tail);
71af5a
49352a ¤   pgpClearMemory( myself, sizeof (*context));
d2fa6e ¤   pgpContextMemFree( cdkContext, context);
e167c5 ¤
c82d68 ¤   return( kPGPError_NoErr );
d5efe6 }
6eaf5a
ecf07b PGPPipeline *
1635a2 pgpArmorFileWriteCreate (
03fdf9 ¤   PGPContextRef cdkContext,
c08941 ¤   PGPPipeline **head,
2d87bc ¤   PGPFile * ¤ (*fileOpen) (void *arg,·
06b9f0 ¤   ¤   ¤   ¤   ¤   ·void const *baseName, unsigned number),
19d60f ¤   void *arg,
ca7dae ¤   void const *baseName)
b0bb36 {
080df0 ¤   PGPPipeline *mod;
e5148d ¤   ArmorFilContext *context;
7daf5a
95d9c4 ¤   if (!head || !fileOpen)
ae7ed2 ¤   ¤   return NULL;
4daf5a
f9c833 ¤   context = (ArmorFilContext *)pgpContextMemAlloc(
288a72 ¤   ¤   cdkContext, sizeof (*context), kPGPMemoryMgrFlags_Clear );
eae31e ¤   if ( IsNull( context ) )
fe7ed2 ¤   ¤   return NULL;
3c9228 ¤   mod = &context->pipe;
f3af5a
d810fc ¤   mod->magic¤ ¤   = ARMORWRITEFILEMAGIC;
d6b327 ¤   mod->write¤ ¤   = Write;
780a98 ¤   mod->flush¤ ¤   = Flush;
6a1d63 ¤   mod->sizeAdvise¤= SizeAdvise;
a3b5a2 ¤   mod->annotate¤  = Annotate;
d705ac ¤   mod->teardown¤  = Teardown;
822337 ¤   mod->name¤  ¤   = "Armor File Write Module";
0d7fc7 ¤   mod->priv¤  ¤   = context;
35a99e ¤   mod->cdkContext¤= cdkContext;
26af5a
f58cc2 ¤   context->fileOpen¤  = fileOpen;
ae1b40 ¤   context->arg¤   ¤   = arg;
2c058e ¤   context->baseName¤  = baseName;
f6af5a
--17c9 001c7b248f44010018a Page 4 of pgpArmrFil.c
aa2d11 ¤   *head = mod;
9c1fea ¤   return mod;
65efe6 }
c7af5a
--f371 0013b41299d4010018b Page 1 of pgpArmrFil.h
bc38e5 /*
04ef1d ·* pgpArmrFil.h -- Armor Write File module
0a775e ·*
055338 ·* Creates output files based upon a "name". ·If the data is within a
a639a5 ·* MULTIARMOR scope, multiple files will be opened for the output.
5c8645 ·* Otherwise, just a single file will be output when data is first
77456e ·* written into this module.
31775e ·*
e25a45 ·* Written By:¤ Derek Atkins <warlord@MIT.EDU>
3b775e ·*
5de12f ·* $Id: pgpArmrFil.h,v 1.8 1997/06/25 19:40:02 lloyd Exp $
95495d ·*/
41af5a
66f013 #ifndef Included_pgpArmrFil_h
8ba427 #define Included_pgpArmrFil_h
2caf5a
4199c6 PGP_BEGIN_C_DECLARATIONS
b0af5a
7dadb8 #include "pgpOpaqueStructs.h"
f0e82c #include "pgpPubTypes.h"
13af5a
9637cb PGPPipeline ·*
a435a2 pgpArmorFileWriteCreate (
71fdf9 ¤   PGPContextRef cdkContext,
7f8941 ¤   PGPPipeline **head,
21daca ¤   ¤   ·PGPFile * (*fileOpen) (void *arg,
289f45 ¤   ¤   ¤   ¤   ·void const *baseName, unsigned number),
f4d60f ¤   void *arg,
204c29 ¤   void const *baseName);
f3af5a
d01254 PGP_END_C_DECLARATIONS
ffaf5a
3bc543 #endif /* Included_pgpArmrFil_h */
--6fcd 0011b85bcd04010018c Page 1 of pgpCRC.c
bc38e5 /*
4e59cf ·* pgpCRC.c - CRC computation routines (wow, how thrilling!)
18775e ·*
c6fbf7 ·* Written by Colin Plumb
c8775e ·*
733a04 ·* $Id: pgpCRC.c,v 1.5 1997/06/04 16:17:45 lloyd Exp $
fd495d ·*/
09af5a
7de2ff #include "pgpConfig.h"
68af5a
745101 #include "pgpCRC.h"
d4d11f #include "pgpUsuals.h"
40af5a
8f8cbe /* PRZ's magic 24-bit polynomial - (x+1) * (irreducible of degree 23) */
0690a0 #define POLY24 0x1864cfbu
31af5a
0738e5 /*
bc10be ·* Build the CRC-24 table.
95775e ·*
a30c68 ·* A byte-at-a-time CRC table is simply a table of the CRCs
8ef26a ·* of the individual bytes.
18775e ·*
12ef4e ·* From basic CRC theory, crc(c^y) = crc(x) ^ crc(y).
842a87 ·* (^ is XOR, which is addition to CRCs.)
4e775e ·*
ede90e ·* Through this code, h holds the CRC of i. ·(i is a power of 2.)
d932b7 ·* The CRCs of the values from i to 2*i-1 are the CRCs of the
9e8b5a ·* values from 0 to i-1, XORed with h.
f2775e ·*
b18107 ·* Then when you get to 2*i, shift h up one bit, XOR in the polynomail
893f5a ·* if necessary to get the right high 8 bits, and continue for 2*i
6c26e0 ·* through 4*i-1.
d2775e ·*
332e45 ·* This drastically reduces the amount of bit-twiddling necessary
1d93d6 ·* to generate a CRC table.
62495d ·*/
b12978 static void
f5cbb9 crcInit(PGPUInt32 table[256])
92bb36 {
9707cb ¤   unsigned i, j;
796be6 ¤   PGPUInt32 h;¤   /* CRC of i, where i is a power of 2 */
62af5a
309f63 ¤   table[0] = 0;
955a1a ¤   table[1] = h = POLY24;
a4af5a
4e1dda ¤   for (i = 2; i < 256; i *= 2) {
91a15d ¤   ¤   if ((h <<= 1) & 0x1000000)¤ /* h <<= 1 (mod poly) */
e28670 ¤   ¤   ¤   h ^= POLY24;
e40662 ¤   ¤   for (j = 0; j < i; j++)
801b82 ¤   ¤   ¤   table[i+j] = table[j] ^ h;
1f9371 ¤   }
8cefe6 }
14af5a
d5af5a
b238e5 /*
d85af3 ·* Update a CRC to reflect the addition of some more bytes.
c64646 ·* It doesn't matter how the bytes are broken up; the CRC is the same.
65df75 ·* I.e. crcUpdate(0, "abcd", 3) == crcUpdate(crcUpdate(0, "ab", 2), "cd", );
0b495d ·*/
debccf PGPUInt32
2bb5c7 crcUpdate(PGPUInt32 crc, PGPByte const *buf, unsigned len)
08bb36 {
b9f8b6 ¤   static PGPUInt32 table[256];¤   /* Initialized to 0 */
caaf5a
403e00 ¤   if (!table[1])
a9a9e7 ¤   ¤   crcInit(table);
dcaf5a
46e87e ¤   while (len--)
b011b8 ¤   ¤   crc = crc<<8 ^ table[*buf++ ^ (PGPByte)(crc>>16)];
8daf5a
a7c1a9 ¤   return crc & 0xffffff;
1befe6 }
--9dec 0019ccb8cfc4010018d Page 1 of pgpCRC.h
bc38e5 /*
4ee814 ·* pgpCRC.h -- this is used for CRC Checksums.
a4775e ·*
e6e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
872979 ·* You should not be using these functions in an application.
b3775e ·*
2b8b79 ·* $Id: pgpCRC.h,v 1.4 1997/06/04 16:17:46 lloyd Exp $
01495d ·*/
57af5a
bdd11f #include "pgpUsuals.h"
3aaf5a
8599c6 PGP_BEGIN_C_DECLARATIONS
94af5a
379f92 PGPUInt32 crcUpdate(PGPUInt32 crc, PGPByte const *buf, unsigned len);
41af5a
d91254 PGP_END_C_DECLARATIONS
1faf5a
9cda6f #define CRC_INIT 0xb704ceu
--42f4 0000c611e494010018e Page 1 of pgpFileMod.c
bc38e5 /*
3a9213 ·* File I/O modules.
27775e ·*
0b7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
2e775e ·*
5f2e86 ·* $Id: pgpFileMod.c,v 1.31 1998/02/07 00:42:14 heller Exp $
83495d ·*/
c8af5a
8de2ff #include "pgpConfig.h"
9a324c #include <string.h>
80af5a
e5feb2 #include <stdio.h>
b0abff #if HAVE_UNISTD_H
e117c2 #include <unistd.h>
3c7454 #endif
e60ccc #if PGP_MACINTOSH
7194b4 #include <unix.h>
c583f3 #include <stat.h>
c8db21 #else
14c382 #include <sys/types.h>¤ ¤   /* required for Ultrix */
4bd4f4 #include <sys/stat.h>
127454 #endif
cfaf5a
63a146 #include "pgpDebug.h"
fe3709 #include "pgpFileMod.h"
646aaa #include "pgpAnnotate.h"
c80d08 #include "pgpMem.h"
232f8d #include "pgpErrors.h"
2472de #include "pgpFile.h"
1a2ece #include "pgpPipeline.h"
cbc26c #include "pgpContext.h"
67af5a
e9b954 #include "pgpKludge.h"
89af5a
f7006f #define FILEMODMAGIC¤   0xfeedf11e
a4af5a
ce66d5 typedef struct FileModContext
12bb36 {
288b60 ¤   PGPPipeline¤pipe;
5867c5 ¤
a29c74 ¤   PGPFile *file;
40823e ¤   int closeFlag;
2c9ed7 ¤   int in_newfile;
707929 ¤   int scope_depth;
f025d9 ¤   DEBUG_STRUCT_CONSTRUCTOR( FileModContext )
fa46b9 } FileModContext;
8baf5a
7f38e5 /*
742564 ·* If we have a file, flush it. ·Then, if we are allowed to close
8440c0 ·* it, then do so. ·If we successfully closed it, then set the file
aec8a6 ·* pointer to 0. ·Return from any error with the error number.
aa495d ·*/
49f1ae static PGPError
7b8529 fileModClose (FileModContext *context)
7abb36 {
005b01 ¤   PGPError¤   error = kPGPError_NoErr;
18af5a
280608 ¤   if (context->file) {
5dad62 ¤   ¤   error = pgpFileFlush (context->file);
d5e3c2 ¤   ¤   if (error)
f93b5b ¤   ¤   ¤   return error;
7baf5a
879e50 ¤   ¤   if (context->closeFlag) {
c89b8a ¤   ¤   ¤   error = pgpFileClose (context->file);
19d82b ¤   ¤   ¤   if (error)
16b20f ¤   ¤   ¤   ¤   return error;
fc0fd8 ¤   ¤   ¤   context->file = 0;
ee0fe4 ¤   ¤   }
8b9371 ¤   }
58af5a
08151e ¤   return kPGPError_NoErr;
0cefe6 }
--0f55 000316538414010018e Page 2 of pgpFileMod.c
e0af5a
c1f1ae static PGPError
34d02e Flush (PGPPipeline *myself)
4ebb36 {
da8d74 ¤   FileModContext *context;
b3af5a
ba29be ¤   pgpAssert (myself);
9cf555 ¤   pgpAssert (myself->magic == FILEMODMAGIC);
57af5a
8cf483 ¤   context = (FileModContext *)myself->priv;
52d30a ¤   pgpAssert (context);
e7af5a
90ecb9 ¤   if (!context->file)
eab840 ¤   ¤   return kPGPError_NoErr;
79af5a
22a4fb ¤   return pgpFileFlush (context->file);
4cefe6 }
9baf5a
5e5d09 static size_t
9041ad fileWrite (PGPPipeline *myself, PGPByte const *buffer, size_t size,
9b0431 ¤   ···PGPError *error)
3bbb36 {
848d74 ¤   FileModContext *context;
f353c9 ¤   size_t retval;
31af5a
1229be ¤   pgpAssert (myself);
d4f555 ¤   pgpAssert (myself->magic == FILEMODMAGIC);
78af5a
bef483 ¤   context = (FileModContext *)myself->priv;
cad30a ¤   pgpAssert (context);
3daf5a
d80b63 ¤   if (!context->file) {
4de3c2 ¤   ¤   if (error)
a6a2ca ¤   ¤   ¤   *error = kPGPError_CantOpenFile; /* No such file or directory*/
a2bbde ¤   ¤   return 0;
e99371 ¤   }
04af5a
1c348e ¤   retval = pgpFileWrite (buffer, size, context->file);
d314f1 ¤   if (retval) {
aee3c2 ¤   ¤   if (error)
d848ed ¤   ¤   ¤   *error = kPGPError_NoErr;
cbaf5f ¤   ¤   return retval;
fe9371 ¤   }
189e1b ¤   if (error && pgpFileError (context->file))
7d1757 ¤   ¤   *error = kPGPError_FileOpFailed;
814baf ¤   pgpFileClearError (context->file);
1e3e6b ¤   return 0;
27efe6 }
24af5a
f738e5 /*
66bbc7 ·* We accept certain annotations to tell us that we should change
f46825 ·* the file we are writing. ·If we have an open file, then it is an
0caf2e ·* assertion error if it doesn't have closeFlag true.
00775e ·*
2e495d ·*/
eef1ae static PGPError
449498 fileAnnotate (PGPPipeline *myself, PGPPipeline *origin, int type,
a8b533 ¤   ······PGPByte const *string, size_t size)
98bb36 {
e58d74 ¤   FileModContext *context;
e9ae26 ¤   FILE *fp;
9fb825 ¤   char filename[FILENAME_MAX];
dcf20c ¤   size_t len;
de87a6 ¤   PGPError¤   error;
18d91c ¤   PGPMemoryMgrRef¤memoryMgr;
6d67c5 ¤
4c3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
eeb417 ¤   memoryMgr¤  = PGPGetContextMemoryMgr( myself->cdkContext );
57af5a
0f64e4 ¤   (void)origin;¤  /* Not used */
b8af5a
3129be ¤   pgpAssert (myself);
--63ab 0008fc1d19c4010018e Page 3 of pgpFileMod.c
d3f555 ¤   pgpAssert (myself->magic == FILEMODMAGIC);
c5af5a
1af483 ¤   context = (FileModContext *)myself->priv;
81d30a ¤   pgpAssert (context);
52af5a
2e1609 ¤   switch (type) {
873942 ¤   case PGPANN_NEWFILE_START:
e9d4da ¤   ¤   pgpAssert(!context->file || context->closeFlag);
c3af5a
5f3255 ¤   ¤   if (context->file) {
616d49 ¤   ¤   ¤   error = fileModClose (context);
ced82b ¤   ¤   ¤   if (error)
a4b20f ¤   ¤   ¤   ¤   return error;
ee0fe4 ¤   ¤   }
64af5a
58355f ¤   ¤   pgpAssert (!context->file);
065b34 ¤   ¤   {
49c57f ¤   ¤   ¤   PGPFile *pgpf;
45af5a
d3133c ¤   ¤   ¤   len = pgpMin (size, sizeof (filename) - 1);
07dbcc ¤   ¤   ¤   memcpy (filename, string, len);
5e3c1d ¤   ¤   ¤   filename[len] = '\0';
0b87c7 ¤   ¤   ¤
6d218c ¤   ¤   ¤   /* I need to know if this should be binary or not */
16e483 ¤   ¤   ¤   fp = fopen (filename, "wb");
78bc47 ¤   ¤   ¤   if (!fp)
b81bcb ¤   ¤   ¤   ¤   return kPGPError_CantOpenFile;
50f2ca ¤   ¤   ¤   pgpf = pgpFileWriteOpen ( myself->cdkContext, fp, NULL);
2f27c3 ¤   ¤   ¤   if (!pgpf) {
d7c5dc ¤   ¤   ¤   ¤   fclose (fp);
bb451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
99a3a6 ¤   ¤   ¤   }
3562a9 ¤   ¤   ¤   context->file = pgpf;
f56244 ¤   ¤   ¤   context->closeFlag = 1;
380fe4 ¤   ¤   }
bef163 ¤   ¤   context->in_newfile = 1;
f32f68 ¤   ¤   break;
502f72 ¤   default:
cfd30b ¤   ¤   ;¤  ¤   /* do nothing */
da9371 ¤   }
411b52 ¤   ¤
67af5a
e7eb30 ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
7404c8 ¤   pgpAssert(context->scope_depth != -1);
a1af5a
40151e ¤   return kPGPError_NoErr;
b2efe6 }
ebaf5a
1af1ae static PGPError
a0198a fileSizeAdvise (PGPPipeline *myself, unsigned long bytes)
12bb36 {
dd8d74 ¤   FileModContext *context;
1baf5a
1d29be ¤   pgpAssert (myself);
b5f555 ¤   pgpAssert (myself->magic == FILEMODMAGIC);
57af5a
03f483 ¤   context = (FileModContext *)myself->priv;
75d30a ¤   pgpAssert (context);
4faf5a
50bcce ¤   if (bytes || context->scope_depth)
a0b840 ¤   ¤   return kPGPError_NoErr;
83acb5 ·¤  if (context->in_newfile && !context->closeFlag)
dcb840 ¤   ¤   return kPGPError_NoErr;
5daf5a
45002e ¤   return fileModClose (context);
f8efe6 }
80af5a
2ff1ae static PGPError
3aa2bb fileTeardown (PGPPipeline *myself)
13bb36 {
9e8d74 ¤   FileModContext *context;
8f67c5 ¤
--7ce4 000a9162c3c4010018e Page 4 of pgpFileMod.c
d93982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
d8af5a
a929be ¤   pgpAssert (myself);
58f555 ¤   pgpAssert (myself->magic == FILEMODMAGIC);
70af5a
89f483 ¤   context = (FileModContext *)myself->priv;
a7d30a ¤   pgpAssert (context);
b5af5a
8ec124 ¤   fileModClose (context);
d61b52 ¤   ¤
253736 ¤   pgpClearMemory( context, ·sizeof (*context));
4897a0 ¤   PGPFreeData( context);
0567c5 ¤
de2d68 ¤   return( kPGPError_NoErr );
9fefe6 }
93af5a
6ef07b PGPPipeline *
604e03 pgpFileWriteCreate (
e8fdf9 ¤   PGPContextRef cdkContext,
8e8941 ¤   PGPPipeline **head,
be44ed ¤   PGPFile *file,
1a241f ¤   int closeFlag)
e5bb36 {
e70df0 ¤   PGPPipeline *mod;
828d74 ¤   FileModContext *context;
a6c3f1 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
f5af5a
dcbb3d ¤   if (!head)
b17ed2 ¤   ¤   return NULL;
fdaf5a
0d2338 ¤   *head = 0;
52af5a
5d45f9 ¤   context = (FileModContext *)PGPNewData(
0f70ef ¤   ¤   memoryMgr, sizeof(*context), kPGPMemoryMgrFlags_Clear );
2ae31e ¤   if ( IsNull( context ) )
147ed2 ¤   ¤   return NULL;
4f9228 ¤   mod = &context->pipe;
2faf5a
5025d4 ¤   mod->magic = FILEMODMAGIC;
fbf547 ¤   mod->write = fileWrite;
4aac4e ¤   mod->flush = Flush;
e68203 ¤   mod->sizeAdvise = fileSizeAdvise;
78f3ee ¤   mod->annotate = fileAnnotate;
7620b6 ¤   mod->teardown = fileTeardown;
77f1c7 ¤   mod->name = "Write file";
f801ea ¤   mod->priv = context;
e9a99e ¤   mod->cdkContext¤= cdkContext;
b6af5a
c85cf6 ¤   context->file = file;
45f5be ¤   context->closeFlag = closeFlag;
32af5a
452d11 ¤   *head = mod;
921fea ¤   return mod;
74efe6 }
b2af5a
b6ec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
98a2ec #define kPGPReadBufSize¤¤   16384
cfdb21 #else
2a7672 #define kPGPReadBufSize¤¤   BUFSIZ
967454 #endif
9caf5a
f9b177 #if 0
91f252 /* Enable this for debugging - it stresses the hell out of the pipeline */
b930cb #undef kPGPReadBufSize
b857b9 #define kPGPReadBufSize 1
887454 #endif
91af5a
b1220d struct PGPFileRead
f3bb36 {
20f7f4 ¤   PGPMemoryMgrRef¤¤   memoryMgr;
9667c5 ¤
a97ac1 ¤   PGPPipeline¤¤   ¤   mod;
--d853 0003852479b4010018e Page 5 of pgpFileMod.c
2a67c5 ¤
7678b3 ¤   PGPFile *¤  ¤   ¤   file;
0490ef ¤   PGPByte¤¤   ¤   ¤   buffer[kPGPReadBufSize];
7e29b6 ¤   PGPByte *¤  ¤   ¤   ¤   p;
bbbeee ¤   off_t¤  ¤   ¤   ¤   filesize;
7b351b ¤   off_t¤  ¤   ¤   ¤   sizeleft;
d01adc ¤   size_t¤ ¤   ¤   ¤   len;
1a4012 ¤   PGPFileReadCallBack¤callBack;
cd342b ¤   void *¤ ¤   ¤   ¤   callBackArg;
be210f ¤   int¤¤   ¤   ¤   ¤   annsent;
4175b2 ¤   int¤¤   ¤   ¤   ¤   sizesent;
9a4950 ¤   int¤¤   ¤   ¤   ¤   closeFlag;
8e2fa1 } ;
92af5a
c0dc2a PGPFileRead *
f8fc67 pgpFileReadCreate(
693163 ¤   PGPContextRef¤  cdkContext,
5b1352 ¤   FILE *¤ ¤   ¤   stdioFile,
87f2fc ¤   int¤¤   ¤   ¤   closeFlag)
1dbb36 {
8ad8af ¤   /*
ff2fb0 ¤   ·* XXX Potential space leak if <closeFlag> is false, although it's
dfa65e ¤   ·* ····never called that way from anywhere except possibly on Un*x.
77246f ¤   ·* ····never called that way from anywhere in PGP 5.0
c7a4e3 ¤   ·*/
47482a ¤   /* pgpFixBeforeShip("Potential space leak if <closeFlag> is false"); */
a467c5 ¤
7b32cb ¤   return pgpPGPFileReadCreate( cdkContext,
7ff95a ¤   ¤   pgpFileReadOpen ( cdkContext, stdioFile, NULL, NULL), closeFlag);
8aefe6 }
88af5a
47dc2a PGPFileRead *
2a98c3 pgpPGPFileReadCreate(
203163 ¤   PGPContextRef¤  cdkContext,
5e6529 ¤   PGPFile *input, int closeFlag)
8fbb36 {
7c829a ¤   PGPFileRead *context;
6a795c ¤   long sizeAdvise;
9fc3f1 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
40af5a
14cc73 ¤   pgpAssert (input);
fbaf5a
5adfa0 ¤   context = (PGPFileRead *)PGPNewData( memoryMgr,
194db0 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear );
ba1ea4 ¤   if (!context)
a07ed2 ¤   ¤   return NULL;
1fde83 ¤   context->memoryMgr¤ = memoryMgr;
fe67c5 ¤
89fca3 ¤   sizeAdvise = pgpFileSizeAdvise (input);
faaf5a
f4db80 ¤   context->file = input;
ed8d8c ¤   context->p = context->buffer;
579651 ¤   if (sizeAdvise < 0)
90c7a1 ¤   {
a64113 ¤   ¤   /* Dont trust the size if its not a regular file */
83ef49 ¤   ¤   context->filesize = 0;
33a214 ¤   ¤   context->sizesent = -1;
169371 ¤   }
300e24 ¤   else
fec7a1 ¤   {
fb4a8e ¤   ¤   context->filesize = sizeAdvise;
f2814d ¤   ¤   context->sizesent = 0;
039371 ¤   }
6e7d33 ¤   context->sizeleft = context->filesize;
7b90fb ¤   context->callBack = NULL;
92f5be ¤   context->closeFlag = closeFlag;
d6ffa7 ¤   context->mod.name = "File Read Module";
eaaf5a
55c097 ¤   return context;
20efe6 }
e9af5a
38314a void
--3869 000b55a72874010018e Page 6 of pgpFileMod.c
40b534 pgpFileReadSetCallBack (PGPFileRead *context, PGPFileReadCallBack callBack,
7fb4ae ¤   ¤   ¤   ¤   ¤   ¤   void *callBackArg)
b7bb36 {
97eee4 ¤   context->callBack = callBack;
74000c ¤   context->callBackArg = callBackArg;
a1efe6 }
80af5a
e3d929 PGPByte const *
c67fe8 pgpFileReadPeek (PGPFileRead *context, PGPSize *len)
d9bb36 {
ecd30a ¤   pgpAssert (context);
9daf5a
30306b ¤   /* Compress data to beginning of buffer */
0f9367 ¤   if (context->p != context->buffer) {
df7f44 ¤   ¤   pgpCopyMemory (context->p, context->buffer, context->len);
9d62ff ¤   ¤   context->p = context->buffer;
439371 ¤   }
25af5a
70a0b6 ¤   /* Now try to fill the buffer */
f1ef9f ¤   if (!pgpFileEof (context->file))
85edc1 ¤   ¤   context->len += pgpFileRead (context->p + context->len,
4916e1 ¤   ¤   ¤   ¤   ·······sizeof(context->buffer) - context->len,
e5ce68 ¤   ¤   ¤   ¤   ·······context->file);
bfaf5a
a14548 ¤   if (len)
94c8b4 ¤   ¤   *len = context->len;
26af5a
7f0398 ¤   return context->p;
f1efe6 }
6caf5a
55314a void
d8c62e pgpFileReadDestroy (PGPFileRead *context)
6fbb36 {
73d30a ¤   pgpAssert (context);
fbaf5a
2b7320 ¤   if (context->closeFlag)
a1be3d ¤   ¤   (void) pgpFileClose (context->file);
80af5a
b76cf3 ¤   PGPFreeData( context );
a31862 }¤
2faf5a
13c77d PGPError
c36484 pgpFileReadClose (PGPFileRead *context, PGPPipeline *head)
8bbb36 {
595b01 ¤   PGPError¤   error = kPGPError_NoErr;
6aaf5a
c648bc ¤   if (context->annsent < 2) {
7abf26 ¤   ¤   error = head->annotate (head, &context->mod, PGPANN_FILE_END,
e2346e ¤   ¤   ¤   ¤   ¤   NULL, 0);
0ee3c2 ¤   ¤   if (error)
5e3b5b ¤   ¤   ¤   return error;
5c2f7c ¤   ¤   context->annsent = 2;
e29371 ¤   }
29c674 ¤   return error;
0befe6 }
e1af5a
75c77d PGPError
c58e03 pgpFileReadPump (PGPFileRead *context, PGPPipeline *head)
d7bb36 {
5c5b01 ¤   PGPError¤   error = kPGPError_NoErr;
7e6c75 ¤   size_t retlen;
5eaf5a
35d30a ¤   pgpAssert (context);
0e0739 ¤   pgpAssert (head);
b8af5a
fcd8af ¤   /*
7a9c03 ¤   ·* Size should be sent outside scope. ·Also send it inside for consistency
235433 ¤   ·* with past behavior; that is not necessary but should not hurt.
b8a4e3 ¤   ·*/
4ff94a ¤   if (!context->sizesent) {
249ca0 ¤   ¤   error = head->sizeAdvise (head, context->sizeleft);
b5e3c2 ¤   ¤   if (error)
--1d29 000b70310064010018e Page 7 of pgpFileMod.c
193b5b ¤   ¤   ¤   return error;
599371 ¤   }
3caf5a
638221 ¤   if (!context->annsent) {
567a03 ¤   ¤   error = head->annotate (head, &context->mod, PGPANN_FILE_BEGIN,
b8346e ¤   ¤   ¤   ¤   ¤   NULL, 0);
07e3c2 ¤   ¤   if (error)
f03b5b ¤   ¤   ¤   return error;
15af5a
a9c018 ¤   ¤   context->annsent = 1;
049371 ¤   }
59af5a
3ff94a ¤   if (!context->sizesent) {
629ca0 ¤   ¤   error = head->sizeAdvise (head, context->sizeleft);
6ce3c2 ¤   ¤   if (error)
8d3b5b ¤   ¤   ¤   return error;
14af5a
73db91 ¤   ¤   context->sizesent = 1;
159371 ¤   }
5aaf5a
a143ab ¤   do {
82ad9b ¤   ¤   /* Write out anything in my buffer */
4b93c2 ¤   ¤   while (context->len) {
a112d1 ¤   ¤   ¤   retlen = head->write (head, context->p,
1e8edd ¤   ¤   ¤   ¤   ¤   ······context->len, &error);
190e80 ¤   ¤   ¤   context->len -= retlen;
6ca53f ¤   ¤   ¤   context->p += retlen;
aede97 ¤   ¤   ¤   context->sizeleft -= retlen;
8cd82b ¤   ¤   ¤   if (error)
ddb20f ¤   ¤   ¤   ¤   return error;
0fa27f ¤   ¤   ¤   if (context->callBack != NULL)
6ef776 ¤   ¤   ¤   {
817608 ¤   ¤   ¤   ¤   error = (*context->callBack) (context->callBackArg,
d5d2a8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   context->filesize - context->sizeleft,
87bcbf ¤   ¤   ¤   ¤   ¤   ¤   ¤   context->filesize);
d39ee0 ¤   ¤   ¤   ¤   if (error != kPGPError_NoErr)
688507 ¤   ¤   ¤   ¤   ¤   return error;
35a3a6 ¤   ¤   ¤   }
310fe4 ¤   ¤   }
87af5a
fc62ff ¤   ¤   context->p = context->buffer;
2bb2ce ¤   ¤   if (pgpFileEof (context->file))
9fcdcb ¤   ¤   ¤   break;
91969b ¤   ¤   context->len = pgpFileRead (context->p, sizeof(context->buffer),
b80ebf ¤   ¤   ······················context->file);
8faf5a
4a5060 ¤   } while (context->len);
b3af5a
711312 ¤   /* If I get here, then I'm at the end of the file */
3faf5a
757b4a ¤   if (context->sizeleft && context->sizesent > 0)
467011 ¤   ¤   return kPGPError_SizeAdviseFailure;
cdaf5a
74af5a
b09022 ¤   error = head->sizeAdvise (head, 0);
ea0161 ¤   if (error)
19fcee ¤   ¤   return error;
a6af5a
38af5a
faca08 ¤   error = pgpFileReadClose (context, head);
520161 ¤   if (error)
84fcee ¤   ¤   return error;
4eaf5a
f5151e ¤   return kPGPError_NoErr;
dbefe6 }
a1af5a
e138e5 /*
83e6c5 ·* Local Variables:
6e9b19 ·* tab-width: 4
f8e7a4 ·* End:
32b612 ·* vi: ts=4 sw=4
b76c42 ·* vim: si
--587d 00147b664664010018e Page 8 of pgpFileMod.c
47495d ·*/
--eee2 0002c9523c74010018f Page 1 of pgpFileMod.h
bc38e5 /*
2bf8d7 ·* pgpFileMod.h -- Pipeline Module to (read and) write files.
03775e ·*
0f7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
72775e ·*
b48190 ·* This is a Public API Function Header.
c9775e ·*
7c3687 ·* $Id: pgpFileMod.h,v 1.15 1997/12/11 23:12:35 lloyd Exp $
c2495d ·*/
97af5a
f962b4 #ifndef Included_pgpFileMod_h
ff3680 #define Included_pgpFileMod_h
54af5a
74feb2 #include <stdio.h>
e0af5a
ded11f #include "pgpUsuals.h"
37675a #include "pgpTypes.h"
562f8d #include "pgpErrors.h"
3faf5a
3d99c6 PGP_BEGIN_C_DECLARATIONS
b5af5a
1eadb8 #include "pgpOpaqueStructs.h"
2c6773 #include "pgpMemoryMgr.h"
31af5a
2daf5a
9f40c7 typedef PGPError (*PGPFileReadCallBack)(void *arg, PGPFileOffset soFar,
123e99 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFileOffset total);
27af5a
8738e5 /*
5e6aff ·* Create a module to write into the appropriate file. ·Will perform a
edd357 ·* fileClose() is close is non-zero when a sizeAdvise(0) is received.
5e495d ·*/
a737cb PGPPipeline ·*
c800ba pgpFileWriteCreate ( PGPContextRef context,
d55675 ¤   PGPPipeline **head, PGPFile *file, int close_at_eof);
b4af5a
f238e5 /*
d04816 ·* Create a context that is used to pump a file through a pipeline.
079057 ·* It will close the file when it reaches the end if close is non-zero
8b495d ·*/
be5940 PGPFileRead ·*pgpFileReadCreate ( PGPContextRef context,
61d1ad ¤   ¤   ¤   ¤   FILE *stdioFile, int close_at_eof);
5920af PGPFileRead ·*pgpPGPFileReadCreate ( PGPContextRef context,
27575e ¤   ¤   ¤   ¤   PGPFile *input, int close_at_eof);
e7af5a
1b9106 void ·pgpFileReadSetCallBack (PGPFileRead *context,
7c63d2 ¤   PGPFileReadCallBack callBack, void *callBackArg);
66af5a
aa38e5 /*
aad2f3 ·* Forcibly close a FileRead Context. ·This is only necessary if you
45675b ·* need to cause the fileread module to close itself forcibly, rather
8d40d1 ·* than waiting for the end. ·Basically it just sends an end annotation
08495d ·*/
c8f237 PGPError ·pgpFileReadClose (PGPFileRead *context,
522ef4 ¤   PGPPipeline *head);
c0af5a
ca38e5 /*
7b31ab ·* Destroy a FileReadContext. ·Close the file if necessary
2e495d ·*/
b58b82 void ·pgpFileReadDestroy (PGPFileRead *context);
9caf5a
ab95d7 /*·
fea35a ·* pgpFileReadPump takes the context and pipes the file down the pipeline
2eefaf ·* until it hits an error. ·It then returns the error. ·It returns 0
99cb8a ·* when it reaches the end of the file and successfully sends its data.
cb495d ·*/
e533a1 PGPError ·pgpFileReadPump (PGPFileRead *context,
c72ef4 ¤   PGPPipeline *head);
02af5a
0d38e5 /*
5e3b0a ·* Peek at the input buffer of a PGPFileRead object. ·This is useful to
2c4588 ·* check if it is a text or binary file, or to use the file contents
--d8d0 0017a49a5fd4010018f Page 2 of pgpFileMod.h
3ac943 ·* to obtain some amount of entropy. ·This will return a pointer to
710d77 ·* the buffer, and will fill in len with the amount of data in the
ce2392 ·* buffer.
64495d ·*/
91bf84 PGPByte const ·*pgpFileReadPeek (PGPFileRead *context,
5cf792 ¤   PGPSize *len);
d7af5a
721254 PGP_END_C_DECLARATIONS
55af5a
7a6c7c #endif /* Included_pgpFileMod_h */
--7b01 000df50c50440100190 Page 1 of pgpHeader.c
bc38e5 /*
caa1a8 ·* pgpHeader.c -- write out a file header.
96775e ·*
64d0f5 ·* currently, the header is: 10101000b \003 P G P == "\250\003PGP". ·In
43f2ec ·* other words, this is an OLD literal-1 packet which PGP 2.6.2 supports
88f2f8 ·* for backwards compatibility with pre-release versions of PGP 2.0, but
6498ed ·* have never been generated by any released version of PGP. ·PGP 2.6.2
2a72aa ·* will see this as a literal packet of type 'P', which is an unknown type,
21ada2 ·* therefore complaining that it needs a newer version of PGP.
b4775e ·*
9f4bb4 ·* PGPlib, on the other hand, will know to just ignore this completely.
47775e ·*
802cb2 ·* This module will wait for input. ·It will then check the first byte
d62e47 ·* of the message. ·If it is an old-style PGP message (10xxxxxx) then it
f374a3 ·* does nothing. ·If it is a new-style PGP message (11xxxxxx) then it will
9c0e9a ·* emit the header.
f6775e ·*
047ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
21775e ·*
86c9d2 ·* $Id: pgpHeader.c,v 1.18 1997/12/12 01:13:59 heller Exp $
f4495d ·*/
acaf5a
76e2ff #include "pgpConfig.h"
fdaf5a
68feb2 #include <stdio.h>
e1324c #include <string.h>
04af5a
d6a146 #include "pgpDebug.h"
8f3e66 #include "pgpHeader.h"
9b9c38 #include "pgpPktByte.h"
7c0d08 #include "pgpMem.h"
432f8d #include "pgpErrors.h"
b82ece #include "pgpPipeline.h"
36c26c #include "pgpContext.h"
67af5a
bf8357 #define HEADERMAGIC¤0x4eade640
a9af5a
e59ceb static PGPByte const pgpheader[] = { 168, 3, 'P', 'G', 'P' };
07af5a
4ca9d8 typedef struct HeaderContext {
908b60 ¤   PGPPipeline¤pipe;
c567c5 ¤
fd36dc ¤   PGPByte header[sizeof(pgpheader)];
2996f1 ¤   size_t hdrlen;
02470b ¤   size_t offset;
6075b0 ¤   PGPPipeline *tail;
c5798e ¤   PGPByte done;
b35137 ¤   DEBUG_STRUCT_CONSTRUCTOR( HeaderContext )
967a80 } HeaderContext;
ddaf5a
2df1ae static PGPError
787b02 DoFlush (HeaderContext *context)
59bb36 {
5a5b01 ¤   PGPError¤   error = kPGPError_NoErr;
fe6c75 ¤   size_t retlen;
d9af5a
c916d3 ¤   /* Try to flush anything that we have buffered */
a08710 ¤   while (context->hdrlen) {
0688b9 ¤   ¤   retlen = context->tail->write (context->tail,
263a58 ¤   ¤   ¤   ¤   ¤   ·······context->header+context->offset,
18b0b6 ¤   ¤   ¤   ¤   ¤   ·······context->hdrlen,
ec48b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
be76f2 ¤   ¤   context->hdrlen -= retlen;
bcaf55 ¤   ¤   context->offset += retlen;
b7e3c2 ¤   ¤   if (error)
fb3b5b ¤   ¤   ¤   return error;
679371 ¤   }
6ec674 ¤   return error;
b1efe6 }
9aaf5a
91f1ae static PGPError
dfd02e Flush (PGPPipeline *myself)
--5489 000b3819c1440100190 Page 2 of pgpHeader.c
2cbb36 {
865377 ¤   HeaderContext *context;
0587a6 ¤   PGPError¤   error;
c4af5a
f329be ¤   pgpAssert (myself);
291c52 ¤   pgpAssert (myself->magic == HEADERMAGIC);
d2af5a
18abea ¤   context = (HeaderContext *)myself->priv;
1ad30a ¤   pgpAssert (context);
0febf4 ¤   pgpAssert (context->tail);
26af5a
1563fd ¤   error = DoFlush (context);
080161 ¤   if (error)
d6fcee ¤   ¤   return error;
09af5a
d29819 ¤   return context->tail->flush (context->tail);
f1efe6 }
adaf5a
0a5d09 static size_t
70f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
50bb36 {
9a5377 ¤   HeaderContext *context;
7eaf5a
ed29be ¤   pgpAssert (myself);
651c52 ¤   pgpAssert (myself->magic == HEADERMAGIC);
b44866 ¤   pgpAssert (error);
72af5a
05abea ¤   context = (HeaderContext *)myself->priv;
a7d30a ¤   pgpAssert (context);
27ebf4 ¤   pgpAssert (context->tail);
f7af5a
285097 ¤   if (!context->done) {
7b1853 ¤   ¤   if (!size)
8c8144 ¤   ¤   ¤   return 0;
b2af5a
9f8bb3 ¤   ¤   if (IS_NEW_PKTBYTE (*buf))
c97b32 ¤   ¤   ¤   switch (NEW_PKTBYTE_TYPE (*buf)) {
cf2070 ¤   ¤   ¤   ¤   /* XXX: These should match pgpFileType.c */
7c180b ¤   ¤   ¤   case PKTBYTE_ESK:
202d7f ¤   ¤   ¤   case PKTBYTE_SIG:
f091fc ¤   ¤   ¤   case PKTBYTE_CONVESK:
85676e ¤   ¤   ¤   case PKTBYTE_1PASSSIG:
45b9ee ¤   ¤   ¤   case PKTBYTE_SECKEY:
df82dc ¤   ¤   ¤   case PKTBYTE_PUBKEY:
ae19d8 ¤   ¤   ¤   case PKTBYTE_SECSUBKEY:
e578c4 ¤   ¤   ¤   case PKTBYTE_PUBSUBKEY:
2d65f8 ¤   ¤   ¤   case PKTBYTE_COMPRESSED:
4440d1 ¤   ¤   ¤   case PKTBYTE_CONVENTIONAL:
e1fa78 ¤   ¤   ¤   case PKTBYTE_LITERAL:
59f92c ¤   ¤   ¤   ¤   memcpy (context->header, pgpheader,
fa8f18 ¤   ¤   ¤   ¤   ¤   sizeof(pgpheader));
47c4ff ¤   ¤   ¤   ¤   context->hdrlen = sizeof (pgpheader);
15f622 ¤   ¤   ¤   ¤   break;
c0a3a6 ¤   ¤   ¤   }
abaf5a
00b612 ¤   ¤   context->done = 1;
a79371 ¤   }
2eaf5a
7b0479 ¤   *error = DoFlush (context);
6f5842 ¤   if (*error)
3abbde ¤   ¤   return 0;
edaf5a
44d39f ¤   return context->tail->write (context->tail, buf, size, error);
3befe6 }
a1af5a
2bf1ae static PGPError
3c13c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
cfb0b1 ¤   ··PGPByte const *string, size_t size)
20bb36 {
d25377 ¤   HeaderContext *context;
e787a6 ¤   PGPError¤   error;
b3af5a
--c0ab 000de588de740100190 Page 3 of pgpHeader.c
c629be ¤   pgpAssert (myself);
1e1c52 ¤   pgpAssert (myself->magic == HEADERMAGIC);
42af5a
94abea ¤   context = (HeaderContext *)myself->priv;
f4d30a ¤   pgpAssert (context);
46ebf4 ¤   pgpAssert (context->tail);
c7af5a
a263fd ¤   error = DoFlush (context);
cf0161 ¤   if (error)
8dfcee ¤   ¤   return error;
85af5a
450df2 ¤   return context->tail->annotate (context->tail, origin, type,
023153 ¤   ¤   ¤   ¤   ¤   string, size);
80efe6 }
16af5a
d4f1ae static PGPError
2f4b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
33bb36 {
565377 ¤   HeaderContext *context;
8287a6 ¤   PGPError¤   error;
49af5a
ee29be ¤   pgpAssert (myself);
b91c52 ¤   pgpAssert (myself->magic == HEADERMAGIC);
50af5a
24abea ¤   context = (HeaderContext *)myself->priv;
cad30a ¤   pgpAssert (context);
caebf4 ¤   pgpAssert (context->tail);
6baf5a
84819e ¤   /* Can't send the sizeAdvise until we've figured out who we are */
0c0578 ¤   ···
45e601 ¤   if (!context->done)
80b840 ¤   ¤   return kPGPError_NoErr;
f6af5a
f063fd ¤   error = DoFlush (context);
ad0161 ¤   if (error)
d1fcee ¤   ¤   return error;
3daf5a
e4e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
dfefe6 }
cdaf5a
44f1ae static PGPError
5ec7e1 Teardown (PGPPipeline *myself)
c0bb36 {
505377 ¤   HeaderContext *context;
ace9fa ¤   PGPContextRef¤  cdkContext;
f167c5 ¤
6f3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
78696e ¤   cdkContext¤ = myself->cdkContext;
27af5a
1729be ¤   pgpAssert (myself);
1a1c52 ¤   pgpAssert (myself->magic == HEADERMAGIC);
0eaf5a
c1abea ¤   context = (HeaderContext *)myself->priv;
64d30a ¤   pgpAssert (context);
32af5a
b9cb05 ¤   if (context->tail)
fe1e8a ¤   ¤   context->tail->teardown (context->tail);
beaf5a
133736 ¤   pgpClearMemory( context, ·sizeof (*context));
88fa6e ¤   pgpContextMemFree( cdkContext, context);
f767c5 ¤
f0151e ¤   return kPGPError_NoErr;
68efe6 }
7eaf5a
ab41cd PGPPipeline **
4f5d43 pgpHeaderCreate (
fffdf9 ¤   PGPContextRef cdkContext,
25f7f9 ¤   PGPPipeline **head)
6ebb36 {
a20df0 ¤   PGPPipeline *mod;
e35377 ¤   HeaderContext *context;
deaf5a
--244b 0017059440740100190 Page 4 of pgpHeader.c
c1bb3d ¤   if (!head)
5e7ed2 ¤   ¤   return NULL;
75af5a
ab44bc ¤   context = (HeaderContext *)pgpContextMemAlloc( cdkContext,
1d4db0 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear );
e81ea4 ¤   if (!context)
837ed2 ¤   ¤   return NULL;
6d9228 ¤   mod = &context->pipe;
fbaf5a
fd4437 ¤   mod->magic = HEADERMAGIC;
b51f83 ¤   mod->write = Write;
0cac4e ¤   mod->flush = Flush;
af0aaf ¤   mod->sizeAdvise = SizeAdvise;
d8d3a2 ¤   mod->annotate = Annotate;
f296de ¤   mod->teardown = Teardown;
f01752 ¤   mod->name = "File Header Module";
b201ea ¤   mod->priv = context;
18a99e ¤   mod->cdkContext¤= cdkContext;
03af5a
8b65ad ¤   context->tail = *head;
8f2d11 ¤   *head = mod;
b37fa2 ¤   return &context->tail;
70efe6 }
--5e4c 001b9db444040100191 Page 1 of pgpHeader.h
bc38e5 /*
de4715 ·* pgpHeader.h -- Create a PGP File Header. ·It looks like a broken
2fe7d9 ·* ESK to older PGP versions, but this new code will understand it.
a8775e ·*
ba7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
a5775e ·*
f4ee45 ·* $Id: pgpHeader.h,v 1.8 1997/06/25 19:40:04 lloyd Exp $
4f495d ·*/
1baf5a
451681 #ifndef Included_pgpHeader_h
f897b7 #define Included_pgpHeader_h
3baf5a
80adb8 #include "pgpOpaqueStructs.h"
d3e82c #include "pgpPubTypes.h"
fbaf5a
1a99c6 PGP_BEGIN_C_DECLARATIONS
23af5a
37af5a
c27319 PGPPipeline ·**pgpHeaderCreate (PGPContextRef cdkContext,
87d8fa ¤   ¤   ¤   ¤   PGPPipeline **head);
e0af5a
941254 PGP_END_C_DECLARATIONS
10af5a
b9d314 #endif /* Included_pgpHeader_h */
--2fef 0005e5a3f8940100192 Page 1 of pgpPrsAsc.c
bc38e5 /*
9b62af ·* pgpPrsAsc.c -- ascii dearmor parser. ·This is fairly complicated. ·Read
82d429 ·* ¤the comment a page down for a description of how this system works.
2112e6 ·*¤ The nice part is that you can input multipart armor in any order
22d422 ·*¤ and it will work. ·In fact, you can intersperse armor parts from
8fa9ab ·*¤ multiple messages and it will work. ·Moreover, you can input binary
ae8150 ·*¤ PGP messages and it will still work! ·My god, can this man think
6f7e89 ·*¤ of everything or what?
93775e ·*
0f7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
62775e ·*
78106b ·* $Id: pgpPrsAsc.c,v 1.48 1998/06/03 20:31:57 hal Exp $
29495d ·*/
96af5a
c6e2ff #include "pgpConfig.h"
b2af5a
6cb1cb #include <ctype.h>
24feb2 #include <stdio.h>
6b324c #include <string.h>
7eaf5a
76d4e4 #ifndef MIMEPARSE
419c71 #define MIMEPARSE¤  ¤   1
e57454 #endif
ceaf5a
21a146 #include "pgpDebug.h"
c564f4 #include "pgpCharMap.h"¤¤   /* for charMapIdentity */
430bbe #include "pgpCopyMod.h"
685101 #include "pgpCRC.h"
4db512 #include "pgpPrsAsc.h"
d20301 #include "pgpRadix64.h"
dc6aaa #include "pgpAnnotate.h"
75910a #include "pgpFIFO.h"
be39d3 #include "pgpFileType.h"
975417 #include "pgpHashPriv.h"
68421a #include "pgpJoin.h"
d90d08 #include "pgpMem.h"
290ab6 #include "pgpPrsBin.h"
2a0d6d #include "pgpEnv.h"
a62f8d #include "pgpErrors.h"
292ece #include "pgpPipeline.h"
fc27c0 #include "pgpSplit.h"
4d3576 #include "pgpTextFilt.h"
d6d11f #include "pgpUsuals.h"
c99bb3 #include "pgpVerifyRa.h"
b5c26c #include "pgpContext.h"
a2af5a
3038e5 /*
c22e2d ·* This is a complicated piece of code. ·Less politely, this code is a
00ea09 ·* bitch. ·It needs to be able to keep track of many different things
62dc8f ·* at the same time in order to combine pieces of armor into whole messages.
dc775e ·*
74b8f7 ·* There are three entities defined here. ·First is an armor part, which
395a37 ·* is defined as the range from BEGIN PGP MESSAGE to the END. ·Second is
15a9f8 ·* a message, which is PGP message made up of one or more parts.
4daffe ·* And third, there are files, which can contain parts.
db775e ·*
a2def7 ·* Parts must be fully contained within a file, however there can be
273645 ·* multiple parts in a single file. ·On the other hand, messages can
576947 ·* cross file boundaries.
c8775e ·*
ccbbcb ·* This code will output PGP messages in a stream of input "files"
1c8b0c ·* wherever the first part of the message came in the stream. ·In a
26c913 ·* multipart message, this will require the least amount of buffering
537277 ·* since buffering is only required when pieces come out of order.
45debc ·* This can also handle the degenerate cases of interleaved messages,
8eef08 ·* although that requires possibly large amounts of buffering.
946cef ·* That case happens rarely enough that the resource requirement is
005917 ·* not onsidered a problem.
00775e ·*
98404e ·* A picture best describes this behavior:
8a775e ·*
5ef4ef ·* ·W1 ·········W2 ··X1 ····X2 ·····X3 ··Y1 ·····Y2 ·····Y3 ··Z1 ···Z2
--a2a7 0003f601bb240100192 Page 2 of pgpPrsAsc.c
1a3d27 ·* | ·| ··A2 ··| ·| | ·| B | ·| A1 | ·| | ·| C2 | ·| C1 | ·| | ·|A3| ·|
7cb737 ·* | ·+--------+ ·| | ·+---+ ·+----+ ·| | ·+----+ ·+----+ ·| | ·+--+ ·|
96cb0a ·* +--------------+ +-----------------+ +------------------+ +--------+
a0b221 ·* ····File 1 ·············File 2 ·············File 3 ·········File 4
7c5bff ·* ································^ ···························^
b40257 ·* ································| ··Everything is buffered ··|
a1eff4 ·* ································+----------------------------+
f0775e ·*
bf184c ·* W,X,Y,Z are file header and footer text which is outside the PGP armor.
f51f17 ·* The numbers are used to associate where in the data stream they occur.
c2775e ·*
0f5ca0 ·* A,B,C are 3 PGP messages. ·The numbers are the actual multipart parts
69c87e ·* which may occur out of order.
97775e ·*
7b724b ·* If this input stream were given to this armor parser, the following
db8a7f ·* output would occur:
f3775e ·*
9bc896 ·* ·| W1 ~ W2 | X1 B X2 A X3 | Y1 ~ Y2 C Y3 | Z1 ~ Z2 |
b0775e ·*
3bf518 ·* Where:¤  | == A file separation annotation (or multiple annotations)
584a5b ·*¤ ¤   ¤   ~ == An armor annotation (an armor part occured here)
f795ae ·*¤ ¤   ¤   W,X,Y,Z == The exact unencrypted text that arrived in the
a210e5 ·*¤ ¤   ¤   ···········input.
e186a2 ·*¤ ¤   ¤   A,B,C == The full messages, wrapped in "PGP data" annotations,
a4657f ·*¤ ¤   ¤   ·········which will be sent to a binary parser for decryption.
74775e ·*
df3be8 ·* As you can see, the messages are output in the order B, A, C, each
d7e396 ·* message occurring in the place in the unenecrpted text stream where
d0229e ·* part 1 is located. ·Other parts are replaced with an annotation that just
3332f9 ·* notes the deletion.
3f775e ·*
264ca1 ·* While decrypting message A, all the data between A1 and A3 (including
dec7df ·* annotations) needs to be buffered. ·In the usual case where the text
40f99f ·* between parts is short (e-mail headers, mostly) and there aren't
27cf51 ·* multiple interleaved parts, not very much needs to be buffered.
dba928 ·* Not much can be done to improve the worst case.
5a495d ·*/
9eaf5a
6acd69 #define kPGPPrsAscCmdBufSize¤   4096
01af5a
c86682 #define DEARMORMAGIC¤   0xdea4304
40af5a
c4f431 /* List of commands */
a5b99d #define CMD_WRITE¤  1
a33183 #define CMD_ANNOTATE¤   2
72af5a
6f3004 #define LINE_LEN¤   256¤/* 256 bytes is MORE than Ascii armorsize! */
e9af5a
5d7dcc /* Some explanations of the various pipeline pointers (as usual, the
dc507a ·* "tail" pointers are PGPPipeline **, that is, pointers to the "next"
ea8c5f ·* pointer in the relevant object):
1f775e ·*
123189 ·* context->tail¤   Points at next stage set up by our caller, usually
b50fe8 ·*¤ ¤   ¤   ¤   ¤   an annotation reader. ·Downstream of msg->tail.
7b4d67 ·* context->myself¤ Points at this very pipeline module.
9a31c0 ·* msg->tail¤   ¤   Points at a copy module which precedes context->tail.
37e3e5 ·*¤ ¤   ¤   ¤   ¤   Part of downstream pipeline of part->mod.
1ae995 ·* part->mod¤   ¤   Points at the 1st-nth stage of a join input, which leads
e9a72d ·*¤ ¤   ¤   ¤   ¤   to a binary parser, 1 stage for each part. ·Now NULL for
c4d36a ·*¤ ¤   ¤   ¤   ¤   clearsigned messages.
ace452 ·* part->text¤  ¤   Used for clearsigned text, points at a split which
611ff1 ·*¤ ¤   ¤   ¤   ¤   feeds into both the sig verifier (via a textfilt) and
25bfdc ·*¤ ¤   ¤   ¤   ¤   into the main msg->tail output (anno reader). ·(Used to
b0d8de ·*¤ ¤   ¤   ¤   ¤   point to 2nd stage of join input, where part->mod pointed
878903 ·*¤ ¤   ¤   ¤   ¤   at first stage. ·This caused unnecessary buffering.)
6cdd34 ·*¤ ¤   ¤   ¤   ¤   and we pass the raw data to context->tail.
c103c4 ·* part->sig¤   ¤   Used for clearsigned signatures, points at a binary
665bd7 ·*¤ ¤   ¤   ¤   ¤   parser that feeds into a sig verifier.
71495d ·*/
5caf5a
d56a88 typedef struct Message¤ Message;
3faf5a
--5dc1 00034612a5140100192 Page 3 of pgpPrsAsc.c
80a096 typedef struct MsgPart¤ MsgPart;
97e087 struct MsgPart {
4ce9fa ¤   PGPContextRef¤  cdkContext;
ed67c5 ¤
5116e3 ¤   unsigned num;¤  ¤   /* Which part number is this? */
4daf73 ¤   PGPPipeline *mod; /* Pointer to the join module for this part */
e436cd ¤   PGPPipeline *text; /* clearsigned: the text goes here */
4d8ab2 ¤   PGPPipeline *sig; /* clearsigned: the sig goes here */
32ad99 ¤   Message *msg;¤  /* What message does this belong to? */
9e1383 ¤   MsgPart *next;¤ /* Pointer to the next part */
0b13a1 ¤   PGPByte first;¤ ¤   /* Is this the first section left to do? */
ed4c87 ¤   PGPByte done;¤  ¤   /* Is this part complete? */
e20e9c ¤   DEBUG_STRUCT_CONSTRUCTOR( MsgPart )
5382f7 };
72af5a
8a7049 struct Message {
96e9fa ¤   PGPContextRef¤  cdkContext;
d367c5 ¤
2e617b ¤   char *name;¤¤   /* The name of this message */
c0dce7 ¤   unsigned size;¤ ¤   /* How many parts does this have, if known */
0207e4 ¤   PGPPipeline **tail; /* Tail pointer for this message */
dc4f25 ¤   MsgPart *parts;¤/* The message parts */
cd5c0c ¤   Message *next;¤ /* The next message */
424e03 ¤   int msg_number;¤¤   /* What is this message number */
f913c9 ¤   PGPByte writing;¤   ¤   /* Are we writing? */
46c677 ¤   PGPByte foundpart1;¤/* Did we find part 1? */
9f9e52 ¤   DEBUG_STRUCT_CONSTRUCTOR( Message )
2a2fa1 } ;
2eaf5a
e1b1cc typedef struct PrsAscContext {
75f8fb ¤   PGPPipeline¤¤   pipe;
f667c5 ¤
3fe89f ¤   PGPFifoDesc const *fifod;¤  /* Fifo Descriptor */
78855a ¤   PGPFifoContext *ann; /* Fifo to hold the saved annotations */
eb61b2 ¤   PGPFifoContext *data; /* Fifo to hold saved non-PGP data */
f2569f ¤   Message *msgs;¤ /* List of current messages */
14145a ¤   MsgPart *part;¤ /* The current message part */
1ee307 ¤   PGPPipeline *myself; /* Pointer to this pipeline module */
77c055 ¤   PGPPipeline *tail; /* Tail pointer for rest of the pipeline */
8b470a ¤   PGPUICb const *ui;
deee3d ¤   PGPEnv const *env;
525f9a ¤   void *ui_arg;
930d17 ¤   unsigned long written;¤ /* Fifo delta from last command */
95815b ¤   unsigned long left;¤/* Bytes left in fifo until next command */
69f670 ¤   unsigned thispart;¤ /* This part, obtained from the PGP header */
921c96 ¤   unsigned maxparts;¤ /* Max parts, obtained from the PGP header */
6a837e ¤   int state;¤ ¤   /* FSM state */
24ae96 ¤   int annotation;¤¤   /* Annotation State */
0f1c28 ¤   int depth_at_ann;¤  /* Scope depth when we sent the annotation */
90771a ¤   int scope_depth;¤   /* Count of scopes we're inside */
41c3d8 ¤   char messageid[LINE_LEN]; /* Message ID, obtained from the PGP header*/
e7d978 ¤   PGPByte databuf[65];¤   /* Space to hold raw data 60+slush */
250b44 ¤   PGPByte *dataptr;¤  ¤   /* Pointer into the data buffer */
e4bda9 ¤   unsigned datalen;¤  /* length of data buffer */
74d8bc ¤   PGPByte armorline[LINE_LEN]; /* line of armor */
2ec067 ¤   PGPByte *armorptr;¤ ¤   /* pointer into armorline */
da2475 ¤   unsigned armorlen;¤ /* length of line */
f2a481 ¤   unsigned long crc;¤ /* CRC Checksum */
d4b447 ¤   PGPByte hashlist[255];¤ /* List of hashes */
002fae ¤   PGPByte hashlen;¤   ¤   /* Length of the list of hashes */
49584e ¤   PGPByte cmdarg[kPGPPrsAscCmdBufSize];¤  /* buffered command */
1c93a7 ¤   unsigned cmdlen;¤   /* length of buffered command */
73a3ea ¤   int msg_count;¤ ¤   /* A count of the number of messages */
3cc8a7 ¤   PGPByte command;¤   ¤   /* the command that is buffered */
fedbd3 ¤   PGPByte buffering;¤ ¤   /* A flag -- are we buffering everything? */
8bb90a ¤   PGPByte eol;¤   ¤   /* Our readLine EOL flag */
b278d5 ¤   PGPByte eob;¤   ¤   /* End of Buffer flag (from readLine) */
54f5f1 ¤   PGPByte expectcrc;¤ ¤   /* Are we expecting the CRC line next? */
d30b99 ¤   PGPByte noarmorblanks;¤ /* Armor data starts on next line after BEGIN */
64b822 ¤   PGPLineEndType crlf;¤   /* The type of crlf we have */
49d2fa ¤   PGPByte saved_crlf;¤/* Save it off... */
34bd0f ¤   PGPSize bytesread;¤ ¤   /* Number of bytes read, total */

--45e6 00094077e9440100192 Page 4 of pgpPrsAsc.c
642199 ¤   PGPSize prevlineoff;¤   /* bytesread value at start of last line */
cd0769 ¤   PGPSize sectoff;¤   ¤   /* bytesread value at start of last section */
268a9e ¤   size_t¤ skipPrefixLength; /* Number of chars preceding -----BEGIN PGP... */
0d399d ¤   PGPByte¤skipPrefix[LINE_LEN]; /* Chars preceding -----BEGIN PGP... */
162eb2 ¤   PGPByte crcendline;¤¤   /* CRC at end of last armor line */
da1dff ¤   PGPByte¤passthrough;¤   /* Passing armor or cleartext data unchanged */
be35dc ¤   PGPByte passthroughcleartext;¤  /* Request passthrough on cleartext */
04f6bc ¤   PGPByte passthroughkey;¤/* Request passthrough on key blocks */
734472 #if MIMEPARSE
0cd9e6 ¤   PGPByte mime_signed;¤   /* Dealing with a PGP/MIME clearsigned message */
35ab23 ¤   PGPByte no_mime_headers;¤   ¤   /* Don't have mime headers, look in body */
668198 ¤   PGPByte mime_boundary[256];¤/* MIME boundary with "--" */
0dc388 ¤   int mime_bound_len;¤/* strlen(mime_boundary) */
197454 #endif
904923 ¤   DEBUG_STRUCT_CONSTRUCTOR( PrsAscContext )
84af18 } PrsAscContext;
aaaf5a
d0af5a
a1f5d7 static char const *¤sDearmorTable = NULL;¤  /* enforce 'const' access */
2caf5a
2d2cdd /* forward references */
aa0e11 static PGPError writeMessage (PrsAscContext *ctx, Message *msg);
c94bc4 static PGPError sendAnnotate (PrsAscContext *ctx, PGPPipeline *origin,
04c39c ¤   ¤   ¤   ¤   ¤   ·int type, PGPByte const *string, size_t size);
0fffac static PGPError flushMessage (PrsAscContext *ctx, Message *msg);
28af5a
f8af5a
c53946 /* Case-insensitive compare routine */
f5beb7 static int
abbd0b strncmp_ignorecase (const char *str1, const char *str2, int len)
33bb36 {
2acae5 ¤   while (len--) {
2f44af ¤   ¤   char c1 = tolower(*str1++);
ccbb24 ¤   ¤   char c2 = tolower(*str2++);
8025ce ¤   ¤   if (c1 != c2) {
dcaec7 ¤   ¤   ¤   return (int)c1 - (int)c2;
1b0fe4 ¤   ¤   }
879371 ¤   }
a43e6b ¤   return 0;
30efe6 }
8caf5a
92af5a
aa38e5 /*
f98d7b ·* Close this part. ·This makes sure that this message is being written
e0a5fd ·* before it does this. ·It will call a sizeAdvise (0) on the join
e22c9d ·* module and then possibly a teardown, too.
79495d ·*/
1bf1ae static PGPError
d9a389 closePart (MsgPart *part)
d7bb36 {
1e87a6 ¤   PGPError¤   error;
45af5a
d463cf ¤   if (! part->msg->writing)
f6b840 ¤   ¤   return kPGPError_NoErr;
faaf5a
1d797f ¤   if (part->sig) {
ef25a2 ¤   ¤   error = part->sig->sizeAdvise (part->sig, 0);
c9e3c2 ¤   ¤   if (error)
7c3b5b ¤   ¤   ¤   return error;
b49371 ¤   }
56af5a
b94fa1 ¤   if (part->mod) {
e08d9a ¤   ¤   error = part->mod->sizeAdvise (part->mod, 0);
a7e3c2 ¤   ¤   if (error)
4e3b5b ¤   ¤   ¤   return error;
1b9371 ¤   }
74af5a
f0c5d2 ¤   if (part->text) {
33335c ¤   ¤   error = part->text->sizeAdvise (part->text, 0);
bce3c2 ¤   ¤   if (error)
773b5b ¤   ¤   ¤   return error;
949371 ¤   }
--a16c 000ebe26a6440100192 Page 5 of pgpPrsAsc.c
e0af5a
404848 ¤   part->done = 2;
87151e ¤   return kPGPError_NoErr;
03efe6 }
68af5a
d938e5 /*
f3f9b8 ·* Free a message part; this tears down the join module, which must be
7afcf2 ·* unhooked from the pipeline first.
93495d ·*/
0c2978 static void
c5eb12 freePart (MsgPart *part)
46bb36 {
4803c3 ¤   MsgPart **partp = &part->msg->parts;
e5e9fa ¤   PGPContextRef¤  cdkContext;
7667c5 ¤
6bdd39 ¤   pgpAssertAddrValid( *partp, MsgPart );
6ff5df ¤   cdkContext¤ = (*partp)->cdkContext;
9baf5a
0a4d58 ¤   if (part->mod)
3fbe6e ¤   ¤   part->mod->teardown (part->mod);
c57be3 ¤   if (part->text)
8f58d4 ¤   ¤   part->text->teardown (part->text);
683c5e ¤   if (part->sig)
4e0370 ¤   ¤   part->sig->teardown (part->sig);
aaaf5a
720ab1 ¤   while (*partp) {
647c8b ¤   ¤   if (*partp == part) {
18d3b3 ¤   ¤   ¤   *partp = part->next;
e58ed9 ¤   ¤   ¤   pgpClearMemory( part, ·sizeof (*part));
578e90 ¤   ¤   ¤   pgpContextMemFree( cdkContext, part);
1c0ecc ¤   ¤   ¤   return;
540fe4 ¤   ¤   }
0c9371 ¤   }
306aec ¤   /* no match found */
83830f ¤   return;
83efe6 }
c5af5a
1a38e5 /*
0b53b9 ·* We are done with the current part, so mark it as done. ·We should
43ec23 ·* also close this part if we are writing this message and either
07aad6 ·* there is a next part or this is the last part. ·Then try to flush
25a259 ·* the message, in case we have anything buffered. ·Finally, clear the
208968 ·* part from the context so we know we don't have a current part.
51495d ·*/
e6f1ae static PGPError
dee6fa donePart (PrsAscContext *ctx)
16bb36 {
084aae ¤   MsgPart *part = ctx->part;
6887a6 ¤   PGPError¤   error;
a3af5a
67169d ¤   pgpAssert (part);
86af5a
f1a72c ¤   part->done = 1;
cce171 ¤   if (part->msg->writing) {
c0b7eb ¤   ¤   if (part->next || part->num == part->msg->size) {
dc7080 ¤   ¤   ¤   error = closePart (part);
e9d82b ¤   ¤   ¤   if (error)
38b20f ¤   ¤   ¤   ¤   return error;
5e0fe4 ¤   ¤   }
1e6a9e ¤   ¤   error = flushMessage (ctx, part->msg);
f2e3c2 ¤   ¤   if (error)
8b3b5b ¤   ¤   ¤   return error;
9d9371 ¤   }
c4af5a
c7cfc8 ¤   ctx->part = NULL;
882d68 ¤   return( kPGPError_NoErr );
a0efe6 }
1daf5a
3538e5 /*
0d1dae ·* We're going to start a new part. ·Therefore we need to pass in the
26f5c1 ·* message that it is a part of, and then create the new part or
eb8d17 ·* return the pre-created part. ·If we ask for a part number in this
--5784 000a9b1342840100192 Page 6 of pgpPrsAsc.c
12f804 ·* message that is beyond the highest number in the list, then we
70d9c8 ·* create that many more parts up to the number passed in.
c8775e ·*
df12f3 ·* Should we close old parts if we can? ·I don't know, yet. ·If we've
461f42 ·* already written out part one and we just got part two, should I close
cdfe55 ·* part one here? ·I don't know, yet.
f5495d ·*/
2c9faa static MsgPart *
a690f8 getPart (PrsAscContext *ctx, Message *msg, unsigned num)
22bb36 {
3809f0 ¤   MsgPart *temp = NULL, **part = &msg->parts;
82d8c0 ¤   PGPPipeline *last = NULL;
268d01 ¤   unsigned highest = 0;
64e9fa ¤   PGPContextRef¤  cdkContext;
0daf5a
8df326 ¤   pgpAssert( IsntNull( ctx ) && IsntNull( ctx->myself ) );
e14f7c ¤   cdkContext¤ = ctx->myself->cdkContext;
4167c5 ¤
21bf6c ¤   /* Initialize the CRC counter! */
df7ec7 ¤   ctx->crc = CRC_INIT;
3aaf5a
38049a ¤   while (*part) {
2667e8 ¤   ¤   if (num == (*part)->num)
71da84 ¤   ¤   ¤   return *part;
6498e0 ¤   ¤   highest = (*part)->num;
700c37 ¤   ¤   last = (*part)->mod;
23d399 ¤   ¤   part = &(*part)->next;
809371 ¤   }
86af5a
a94643 ¤   /* We need to allocate a bunch of parts */
e2bc33 ¤   for (highest++; highest <= num; highest++) {
eaa2fc ¤   ¤   temp = (MsgPart *)pgpContextMemAlloc( cdkContext,
2c0929 ¤   ¤   ¤   sizeof (*temp), kPGPMemoryMgrFlags_Clear);
415b1a ¤   ¤   if (!temp)
5bcf03 ¤   ¤   ¤   return NULL;
9aaf5a
1aaeec ¤   ¤   temp->num = highest;
a7b8cb ¤   ¤   temp->msg = msg;
cf630c ¤   ¤   temp->cdkContext¤   = cdkContext;
16af5a
eb6c85 ¤   ¤   if (last) {
06a279 ¤   ¤   ¤   temp->mod = pgpJoinAppend (last);
4b45a6 ¤   ¤   } else {
76c639 ¤   ¤   ¤   msg->tail = pgpJoinCreate ( cdkContext, &(temp->mod), ctx->fifod);
0442d3 ¤   ¤   ¤   temp->first = 1;
4b02aa ¤   ¤   ¤   msg->tail = pgpParseBinCreate ( cdkContext, msg->tail, ctx->env,
442f1b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ctx->ui, ctx->ui_arg );
d77aad ¤   ¤   ¤   /*
65b460 ¤   ¤   ¤   ·* Binary parser may add modules after itself, and in some
959786 ¤   ¤   ¤   ·* error recovery situations they are still there when we try
c0a487 ¤   ¤   ¤   ·* to close things. ·Create a copy module to act as a stable
a8f8a6 ¤   ¤   ¤   ·* predecessor to context->tail.
268753 ¤   ¤   ¤   ·*/
834721 ¤   ¤   ¤   msg->tail = pgpCopyModCreate ( cdkContext, msg->tail);
1baf5a
9d2286 ¤   ¤   ¤   /* connect the join module to the rest of the pipe */
7e0b71 ¤   ¤   ¤   if (msg->tail)
299147 ¤   ¤   ¤   ¤   *(msg->tail) = ctx->tail;
410fe4 ¤   ¤   }
a7af5a
b08705 ¤   ¤   if (!temp->mod) {
cc5d1a ¤   ¤   ¤   pgpContextMemFree( cdkContext, temp);
6ecf03 ¤   ¤   ¤   return NULL;
bb0fe4 ¤   ¤   }
18af5a
f3e92d ¤   ¤   *part = temp;
0c3217 ¤   ¤   last = temp->mod;
217779 ¤   ¤   part = &temp->next;
1f9371 ¤   }
0087c7 ¤   ¤   ¤
f7b5b3 ¤   return temp;
a9efe6 }
--0f23 000b71c570840100192 Page 7 of pgpPrsAsc.c
e0af5a
d338e5 /*
30d7de ·* We have a part of a message "name" of size "size" -- lets try to
4d04cc ·* find the message that this is a part of, and either return that
7e2f5a ·* message pointer or create a new one and return that. ·If name is
3c0358 ·* non-NULL, then it will compare the name passed in with older names
46ba64 ·* (i.e., a messageID). ·If name is NULL, then it will compare sizes
6f3715 ·* for old-style multipart armor. ·Do not return messages that have
4b42d0 ·* only one part.
9a775e ·*
8f1862 ·* This means that you can only have one old-style multipart message
89bc7f ·* going of any particular size (number of parts). ·I don't consider
7ed604 ·* this a big problem, since interleaved messages are rarely a
e7193e ·* problem. ·Out-of-order messages, on the other hand.....
cc495d ·*/
0b0f64 static Message *
325ec2 getMessage (PrsAscContext *ctx, char const *name, unsigned size)
60bb36 {
80b760 ¤   Message **msg = &ctx->msgs;
76bd26 ¤   char *newname;
a95c95 ¤   PGPContextRef¤  ¤   cdkContext¤ = ctx->pipe.cdkContext;
70af5a
ace0dd ¤   /* Just remove name if it is a NULL string */
b60085 ¤   if (name && !*name)
c866d0 ¤   ¤   name = NULL;
10af5a
942cde ¤   if (!name && !size)
117ed2 ¤   ¤   return NULL;
bcaf5a
7a6eec ¤   while (*msg) {
c6309d ¤   ¤   if (name && (*msg)->name && !memcmp (name, (*msg)->name,
6d2865 ¤   ¤   ····strlen (name))) {
1704fd ¤   ¤   ¤   /* Update the message size if we know it */
487083 ¤   ¤   ¤   if (!(*msg)->size && size)
c15b91 ¤   ¤   ¤   ¤   (*msg)->size = size;
7c0279 ¤   ¤   ¤   return *msg;
740fe4 ¤   ¤   }
7db926 ¤   ¤   if (!name && !(*msg)->name && size == (*msg)->size &&
a64b4f ¤   ¤   ····size != 1)
490279 ¤   ¤   ¤   return *msg;
6cb908 ¤   ¤   msg = &((*msg)->next);
bf9371 ¤   }
b7af5a
129123 ¤   *msg = (Message *)pgpContextMemAlloc( cdkContext,
0934bb ¤   ¤   sizeof (**msg), kPGPMemoryMgrFlags_Clear);
ea9fb3 ¤   if (! *msg)
5c7ed2 ¤   ¤   return NULL;
fdaf5a
855e63 ¤   (*msg)->cdkContext¤ = cdkContext;
4f67c5 ¤
58348f ¤   if (name) {
3f1616 ¤   ¤   newname = (char *)pgpContextMemAlloc( cdkContext,
d9c1ce ¤   ¤   ¤   strlen (name) + 1, kPGPMemoryMgrFlags_Clear);
be30a7 ¤   ¤   if (!newname) {
f0c9d4 ¤   ¤   ¤   pgpContextMemFree( cdkContext, *msg);
4bcda8 ¤   ¤   ¤   *msg = NULL;
8ccf03 ¤   ¤   ¤   return NULL;
c60fe4 ¤   ¤   }
330f81 ¤   ¤   memcpy (newname, name, strlen (name) + 1);
0a2be7 ¤   } else
7a38a1 ¤   ¤   newname = NULL;
a5af5a
715bf0 ¤   (*msg)->name = newname;
47e9f2 ¤   (*msg)->size = size;
b21fd9 ¤   (*msg)->msg_number = ++(ctx->msg_count);
c9af5a
1af223 ¤   return *msg;
44efe6 }
b8af5a
ee38e5 /*
9c814b ·* We're done with this message so we can remove it from our queue
b73543 ·* of pending messages. ·Free any remaining message parts in the process.
--f7d4 00054c7ab7340100192 Page 8 of pgpPrsAsc.c
19c42f ·* We can also turn buffering off now.
c4495d ·*/
552978 static void
1afc54 freeMessage (PrsAscContext *ctx, Message *msg)
fbbb36 {
cc421f ¤   Message **msgp = &ctx->msgs;
47f214 ¤   MsgPart *part, *temp;
505c95 ¤   PGPContextRef¤  ¤   cdkContext¤ = ctx->pipe.cdkContext;
24af5a
d71c6a ¤   while (*msgp) {
cdf1d2 ¤   ¤   if (*msgp == msg) {
1acba7 ¤   ¤   ¤   *msgp = msg->next;
daaa43 ¤   ¤   ¤   part = msg->parts;
bc0b71 ¤   ¤   ¤   if (msg->tail)
a89526 ¤   ¤   ¤   ¤   /* Disconnect join module */
121401 ¤   ¤   ¤   ¤   *(msg->tail) = NULL;
34b383 ¤   ¤   ¤   while (part) {
e0714e ¤   ¤   ¤   ¤   temp = part;
5234ce ¤   ¤   ¤   ¤   part = part->next;
5d5696 ¤   ¤   ¤   ¤   freePart (temp);
bba3a6 ¤   ¤   ¤   }
f78e3d ¤   ¤   ¤   if (msg->name)
7a3dd4 ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, msg->name);
e43782 ¤   ¤   ¤   ctx->buffering = 0;
129d84 ¤   ¤   ¤   pgpClearMemory( msg, ·sizeof (*msg));
a64ac6 ¤   ¤   ¤   pgpContextMemFree( cdkContext, msg);
c22b85 ¤   ¤   ¤   ¤
270ecc ¤   ¤   ¤   return;
b50fe4 ¤   ¤   }
769371 ¤   }
166aec ¤   /* no match found */
3c830f ¤   return;
36efe6 }
afaf5a
9838e5 /*
056e26 ·* Buffer a command at the current spot in the data stream. ·This is only
29f4db ·* called when ctx->buffering is true. ·What it does is find the delta
cf72eb ·* of this command in the data fifo from the last command in order to replay
41290a ·* the commands at the proper place. ·It saves off context->written as
3b83bd ·* the offset and then resets the value to 0.
f3775e ·*
89e516 ·* The return value is 0 on success or an error code.
86775e ·*
2abc63 ·* Command Byte Syntax: <offset><cmd><arglen><arg>
09495d ·*/
3df1ae static PGPError
065fea bufferCommand (
1eda65 ¤   PrsAscContext *ctx, PGPByte cmd, const PGPByte *arg, unsigned arglen)
3ebb36 {
3a2947 ¤   /* Make sure the command argument fits the buffer size */
5542ab ¤   if (arglen > sizeof (ctx->cmdarg))
7c62b5 ¤   ¤   return kPGPError_BadParams;
77af5a
a8f09a ¤   if (pgpFifoWrite (ctx->fifod, ctx->ann, (PGPByte const *)&ctx->written,
04dbb3 ¤   ¤   ¤   ··sizeof (ctx->written)) != sizeof (ctx->written))
794030 ¤   ¤   return kPGPError_OutOfMemory;
b7af5a
53fbe8 ¤   if (pgpFifoWrite (ctx->fifod, ctx->ann, &cmd, sizeof (cmd))
7cb088 ¤   ····!= sizeof (cmd))
a24030 ¤   ¤   return kPGPError_OutOfMemory;
aeaf5a
b16824 ¤   if (pgpFifoWrite (ctx->fifod, ctx->ann, (PGPByte const *)&arglen,
ff47ef ¤   ¤   ¤   ··sizeof (arglen)) != sizeof (arglen))
9e4030 ¤   ¤   return kPGPError_OutOfMemory;
d6af5a
00939f ¤   if (pgpFifoWrite (ctx->fifod, ctx->ann, arg, arglen) != arglen)
c74030 ¤   ¤   return kPGPError_OutOfMemory;
c1af5a
faaf5a
536cca ¤   ctx->written = 0;
902d68 ¤   return( kPGPError_NoErr );
54efe6 }
--2c2d 000a6473e0740100192 Page 9 of pgpPrsAsc.c
e0af5a
5e3567 /* Buffer up a write command for a particular message */
4af1ae static PGPError
d683bf bufferWriteCommand (PrsAscContext *ctx, Message *msg)
66bb36 {
a8547a ¤   PGPByte arg[sizeof (msg)];
725a72 ¤   memcpy (arg, (PGPByte const *)&msg, sizeof (arg));
bdaf5a
1f10bf ¤   return bufferCommand (ctx, CMD_WRITE, arg, sizeof (arg));
b4efe6 }
77af5a
819b08 /* Process a buffered Write command for a particular message */
22f1ae static PGPError
044d0f parseWriteCommand (PrsAscContext *ctx)
2dbb36 {
ac5b16 ¤   Message *msg;
29af5a
39dbda ¤   pgpAssert (ctx->cmdlen == sizeof (msg));
ad2c2d ¤   memcpy ((PGPByte *)&msg, ctx->cmdarg, sizeof (msg));
dbc968 ¤   return writeMessage (ctx, msg);
10efe6 }
e9af5a
20f84e /* Buffer up an annotation */
b1f1ae static PGPError
fdb2d2 bufferAnnotation (PrsAscContext *ctx, PGPPipeline *origin, int type,
558974 ¤   ¤   ··PGPByte const *string, size_t size)
b0bb36 {
28c268 ¤   PGPByte *arg;
c2c07c ¤   PGPByte *argp;
db1232 ¤   PGPError retval;
705c95 ¤   PGPContextRef¤  ¤   cdkContext¤ = ctx->pipe.cdkContext;
52af5a
38da21 ¤   arg = argp = (PGPByte *)pgpContextMemAlloc( cdkContext,
5fc2c3 ¤   ¤   ¤   sizeof (origin) + sizeof (type) + size + sizeof (size),
d9c287 ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
ab30ee ¤   if (!arg)
af4030 ¤   ¤   return kPGPError_OutOfMemory;
30af5a
dfa9ca ¤   memcpy (argp, (PGPByte const *)&origin, sizeof (origin));
ed0bfc ¤   argp += sizeof (origin);
c0af5a
1b5e6b ¤   memcpy (argp, (PGPByte const *)&type, sizeof (type));
863916 ¤   argp += sizeof (type);
fcaf5a
480a9a ¤   memcpy (argp, (PGPByte const *)&size, sizeof (size));
40f016 ¤   argp += sizeof (size);
adaf5a
f05afe ¤   memcpy (argp, string, size);
868201 ¤   argp += size;
a7af5a
546d25 ¤   retval = bufferCommand (ctx, CMD_ANNOTATE, arg, argp-arg);
472453 ¤   pgpContextMemFree( cdkContext, arg);
9a94b6 ¤   return retval;
55efe6 }
dbaf5a
a5f1ae static PGPError
289166 parseAnnotation (PrsAscContext *ctx)
f9bb36 {
26cf07 ¤   PGPPipeline *origin;
5c29f6 ¤   int type;
29e002 ¤   size_t size;
9672d5 ¤   PGPByte *string, *argp = ctx->cmdarg;
dc1232 ¤   PGPError retval;
635c95 ¤   PGPContextRef¤  ¤   cdkContext¤ = ctx->pipe.cdkContext;
e5af5a
440a7f ¤   pgpAssert (ctx->cmdlen >= sizeof (origin) + sizeof (type) +
37b1e4 ¤   ¤   sizeof (size));
74af5a
7d189e ¤   memcpy ((PGPByte *)&origin, argp, sizeof (origin));
740bfc ¤   argp += sizeof (origin);
e1af5a
a63f73 ¤   memcpy ((PGPByte *)&type, argp, sizeof (type));
--4df9 0000d8fbfbc40100192 Page 10 of pgpPrsAsc.c
3c3916 ¤   argp += sizeof (type);
75af5a
bb8140 ¤   memcpy ((PGPByte *)&size, argp, sizeof (size));
95f016 ¤   argp += sizeof (size);
6aaf5a
040c72 ¤   /* make sure we have the right number of bytes remaining */
5dca5e ¤   pgpAssert ((ctx->cmdlen - size) == (unsigned)(argp - ctx->cmdarg));
21af5a
1ba6fc ¤   string = (PGPByte *)pgpContextMemAlloc( cdkContext,
4f2217 ¤   ¤   size, kPGPMemoryMgrFlags_Clear);
13c643 ¤   if (string == NULL)
084030 ¤   ¤   return kPGPError_OutOfMemory;
f1af5a
d3d0b8 ¤   pgpCopyMemory (argp, string, size);
6daf5a
38702e ¤   retval = sendAnnotate (ctx, origin, type, string, size);
28af5a
033598 ¤   pgpContextMemFree( cdkContext, string);
0094b6 ¤   return retval;
13efe6 }
d5af5a
ab38e5 /*
9ea1b8 ·* Given a buffered command, process it appropriately. ·The cmd, args,
b546fd ·* and arglen are currently held in the ctx. ·Set arglen to 0 and
ca4219 ·* return 0 on success, otherwise return an error.
aa495d ·*/
f4f1ae static PGPError
e59aab processCommand (PrsAscContext *ctx)
0abb36 {
855b01 ¤   PGPError¤   error = kPGPError_NoErr;
b0af5a
8852f6 ¤   switch (ctx->command) {
42c38c ¤   case CMD_WRITE:
a590b1 ¤   ¤   error = parseWriteCommand (ctx);
e12f68 ¤   ¤   break;
7c2760 ¤   case CMD_ANNOTATE:
d18b5d ¤   ¤   error = parseAnnotation (ctx);
982f68 ¤   ¤   break;
d72f72 ¤   default:
461353 ¤   ¤   /* unknown command type. ·This should NEVER happen */
cd9132 ¤   ¤   pgpAssert (0);
3c9371 ¤   }
63af5a
1fff2e ¤   if (!error)
145b34 ¤   ¤   ctx->cmdlen = 0;
f5c674 ¤   return error;
4fefe6 }
a4af5a
5038e5 /*
e9f0f3 ·* Write a buffer of data which is a message part. ·This will either
8089e8 ·* write or buffer depending on what the current state of the world
5f42f2 ·* is.
0c775e ·*
afd461 ·* This will either perform a write() or a pgpJoinBuffer() depending
0e8066 ·* on what it is and what the state is. ·We perform a write if this is
09189a ·* the writing message, otherwise we just buffer it.
8c495d ·*/
ea5d09 static size_t
2f33d2 writePartData (MsgPart *part, PGPByte const *buf, size_t size, PGPError *error)
11bb36 {
828b1c ¤   Message *msg = part->msg;
d0af5a
769ee6 ¤   /* Ignore parts that we've already finished */
912289 ¤   if (part->done)
18b771 ¤   ¤   return size;
dbaf5a
993c5e ¤   if (part->sig)
d9c122 ¤   ¤   return part->sig->write (part->sig, buf, size, error);
6faf5a
6eec19 ¤   if (msg->writing)
e247c4 ¤   ¤   return part->mod->write (part->mod, buf, size, error);
0daf5a
--0546 000fe5703b340100192 Page 11 of pgpPrsAsc.c
414a3a ¤   return pgpJoinBuffer (part->mod, buf, size);
a4efe6 }
bbaf5a
da38e5 /*
b24031 ·* This will write 'extra' data out. ·In general this is just
fa0d34 ·* non-Ascii armor data. ·However if we are within a "buffering
2f2b26 ·* everything" mode, then this will get buffered into the ctx->data
d6370a ·* fifo and ctx->written will be increased.
2f495d ·*/
1f5d09 static size_t
7cb138 writeExtraData (
e16c1c ¤   PrsAscContext *ctx, PGPByte const *buf, size_t size, PGPError *error)
93bb36 {
efac29 ¤   size_t written;
a0af5a
592758 ¤   /* Handle clearsign text */
f1aa45 ¤   if (ctx->part && ctx->part->text)
2761ec ¤   ¤   return ctx->part->text->write (ctx->part->text, buf, size,
98dc64 ¤   ¤   ¤   ¤   ¤   ·······error);
e6af5a
4b1728 ¤   pgpAssert (ctx->tail);
58af5a
b3ae32 ¤   if (ctx->buffering) {
e64e21 ¤   ¤   written = pgpFifoWrite (ctx->fifod, ctx->data, buf, size);
99b7fd ¤   ¤   ctx->written += written;
135d6a ¤   ¤   return written;
b59371 ¤   }
22af5a
7c074b ¤   return ctx->tail->write (ctx->tail, buf, size, error);
64efe6 }
2faf5a
6f38e5 /*
adcc9b ·* This will start with the first part that we have. ·For each part,
64d5f9 ·* it will see if it is done. ·If not, return 0. ·If it is done, then
00f43e ·* see if there is another part sitting after it. ·If so, close this
de0fd4 ·* part, return an error if one exists, or move on to the next part if
95b264 ·* there was no error closing the part. ·If there is not another part
f506c3 ·* after this one, then only close this one if this is the last part
a22831 ·* (msg->size && part->num == msg->size). ·Otherwise return 0.
cf775e ·*
88e626 ·* If we flushed the whole message, free it.
28495d ·*/
8ef1ae static PGPError
f58bb8 flushMessage (PrsAscContext *ctx, Message *msg)
55bb36 {
69d457 ¤   MsgPart *temp, *part = msg->parts;
185b01 ¤   PGPError¤   error = kPGPError_NoErr;
1eaf5a
d643ab ¤   do {
c4e1ef ¤   ¤   if (!part->done)
86cdcb ¤   ¤   ¤   break;
09af5a
597fcc ¤   ¤   if (part->next) {
477080 ¤   ¤   ¤   error = closePart (part);
68d82b ¤   ¤   ¤   if (error)
fcf622 ¤   ¤   ¤   ¤   break;
3dcece ¤   ¤   ¤   temp = part->next;
363e4a ¤   ¤   ¤   freePart (part);
53a4c1 ¤   ¤   ¤   part = temp;
87af5a
8085b0 ¤   ¤   } else if (part->num == msg->size) {
0e707a ¤   ¤   ¤   pgpAssert (!part->next);
00af5a
867080 ¤   ¤   ¤   error = closePart (part);
b2d82b ¤   ¤   ¤   if (error)
5cf622 ¤   ¤   ¤   ¤   break;
598b03 ¤   ¤   ¤   error = ctx->tail->annotate (ctx->tail, ctx->myself,
893c2c ¤   ¤   ¤   ¤   ¤   ¤   ·····PGPANN_ARMOR_END, NULL,
3e5c36 ¤   ¤   ¤   ¤   ¤   ¤   ·····0);
23d82b ¤   ¤   ¤   if (error)
25f622 ¤   ¤   ¤   ¤   break;
fef464 ¤   ¤   ¤   freeMessage (ctx, msg);
--e8af 00051c14d3b40100192 Page 12 of pgpPrsAsc.c
9f4ec0 ¤   ¤   ¤   /* freeMessage will free the last part */
1fcdcb ¤   ¤   ¤   break;
eb4a5d ¤   ¤   } else
04cdcb ¤   ¤   ¤   break;
2aaf5a
a903e6 ¤   } while (part);
88af5a
2cc674 ¤   return error;
5ca79b }·
5faf5a
e538e5 /*
998a96 ·* Set the state so that we are writing out this message. ·It means that
5c4afe ·* we are probably going to be buffering everything else until this message
6d55b7 ·* is done. ·If we are already "buffering" everything, then buffer up this
e81a71 ·* command for later execution.
61495d ·*/
9ef1ae static PGPError
54892e writeMessage (PrsAscContext *ctx, Message *msg)
13bb36 {
4487a6 ¤   PGPError¤   error;
e8af5a
043da6 ¤   msg->foundpart1 = 1;
5a8170 ¤   if (ctx->buffering)
0d2045 ¤   ¤   return bufferWriteCommand (ctx, msg);
2faf5a
6f14ca ¤   error = ctx->tail->annotate (ctx->tail,
51ce5b ¤   ¤   ctx->myself, PGPANN_ARMOR_BEGIN,
ac0f2e ¤   ¤   (PGPByte *)&ctx->sectoff, sizeof(ctx->sectoff));
c50161 ¤   if (error)
b1fcee ¤   ¤   return error;
a0af5a
fa3665 ¤   ctx->buffering = 1;
f6ec18 ¤   msg->writing = 1;
f4af5a
eb7ade ¤   /* Start flushing the message now */
c7af5a
6e9522 ¤   return flushMessage (ctx, msg);
abefe6 }
b0af5a
0738e5 /*
e4ccc1 ·* This is the main logic in flushing out the buffered data. ·This
d51226 ·* function will try to flush the data fifo and command fifo in order
804092 ·* to create the appropriate output stream.
71775e ·*
f3bb5e ·* There are two streams which need to be merged. ·Since the command
5adf24 ·* stream gives deltas into the datastream, we need to use the command
315b88 ·* stream as the control. ·No problem.
2e775e ·*
96706c ·* First, we flush out any data in the data stream until the next
20e581 ·* command, until ctx->left == 0. ·Next, if ctx->cmdlen != 0 we
001cef ·* process the command in the ctx command buffer. ·If that returns
2065c6 ·* without error we read in the next command/offset into ctx (->left
630805 ·* and ->cmdlen) and then repeat. ·It at any time an error occurs,
398dac ·* stop and return the error code.
b2495d ·*/
46f1ae static PGPError
02f3c7 flushBuffers (PrsAscContext *ctx)
06bb36 {
a3018b ¤   PGPSize datalen, cmdlen, len;
67a617 ¤   PGPByte const *ptr;
795b01 ¤   PGPError¤   error = kPGPError_NoErr;
4cac29 ¤   size_t written;
7faf5a
d9f746 ¤   pgpAssert (! ctx->buffering);
a9af5a
211faa ¤   datalen = pgpFifoSize (ctx->fifod, ctx->data);
96b824 ¤   cmdlen = pgpFifoSize (ctx->fifod, ctx->ann);
e9af5a
a4c296 ¤   /* If nothing is buffered, just return ok */
2dbf6a ¤   if (!datalen && !cmdlen)
1fa117 ¤   ¤   return( kPGPError_NoErr );
51af5a
--7574 000dd12721c40100192 Page 13 of pgpPrsAsc.c
6eb31d ¤   /* Now try to flush the buffers... */
c043ab ¤   do {
fa1b17 ¤   ¤   /*
88fc06 ¤   ¤   ·* If buffering gets turned on processing a command,
83f9fa ¤   ¤   ·* just exit this function so more data can be read in.
319de3 ¤   ¤   ·*/
577715 ¤   ¤   if (ctx->buffering)
f2e0e4 ¤   ¤   ¤   return( kPGPError_NoErr );
57af5a
cb583a ¤   ¤   /* First flush any data until the next command */
305573 ¤   ¤   while (ctx->left) {
05f69f ¤   ¤   ¤   ptr = pgpFifoPeek (ctx->fifod, ctx->data, &len);
6c5986 ¤   ¤   ¤   pgpAssert (len);
53c153 ¤   ¤   ¤   pgpAssert (ptr);
15af5a
488fd1 ¤   ¤   ¤   if (len > ctx->left)
c0e893 ¤   ¤   ¤   ¤   len = ctx->left;
e53003 ¤   ¤   ¤   written = writeExtraData (ctx, ptr, len, &error);
aa94b4 ¤   ¤   ¤   pgpFifoSeek (ctx->fifod, ctx->data, written);
12939c ¤   ¤   ¤   ctx->left -= written;
43912b ¤   ¤   ¤   datalen -= written;
52d82b ¤   ¤   ¤   if (error)
36b20f ¤   ¤   ¤   ¤   return error;
340fe4 ¤   ¤   }
97af5a
2307c1 ¤   ¤   /* Process the buffered command, if any */
62107d ¤   ¤   if (ctx->cmdlen) {
c527d6 ¤   ¤   ¤   error = processCommand (ctx);
ead82b ¤   ¤   ¤   if (error)
5ab20f ¤   ¤   ¤   ¤   return error;
a10fe4 ¤   ¤   }
efaf5a
8d1b17 ¤   ¤   /*
1099d8 ¤   ¤   ·* Now, read in the data for the next command. ·The
b9a0c4 ¤   ¤   ·* syntax is: <offset><cmd><arglen><arg>
d29de3 ¤   ¤   ·*/
8eae16 ¤   ¤   if (cmdlen) {
3706a6 ¤   ¤   ¤   if (pgpFifoRead (ctx->fifod, ctx->ann,
544fa5 ¤   ¤   ¤   ¤   ¤   ·(PGPByte *)&ctx->left,
70e29a ¤   ¤   ¤   ¤   ¤   ·sizeof (ctx->left)) !=
70543b ¤   ¤   ¤   ····sizeof (ctx->left))
78bc38 ¤   ¤   ¤   ¤   return kPGPError_FIFOReadError;
fd4247 ¤   ¤   ¤   cmdlen -= sizeof (ctx->left);
afaf5a
d44b75 ¤   ¤   ¤   if (pgpFifoRead (ctx->fifod, ctx->ann, &ctx->command,
021ba7 ¤   ¤   ¤   ¤   ¤   ·sizeof (ctx->command)) !=
97206a ¤   ¤   ¤   ····sizeof (ctx->command))
28bc38 ¤   ¤   ¤   ¤   return kPGPError_FIFOReadError;
64c0b9 ¤   ¤   ¤   cmdlen -= sizeof (ctx->command);
b9af5a
0006a6 ¤   ¤   ¤   if (pgpFifoRead (ctx->fifod, ctx->ann,
9f4eed ¤   ¤   ¤   ¤   ¤   ·(PGPByte *)&ctx->cmdlen,
402612 ¤   ¤   ¤   ¤   ¤   ·sizeof (ctx->cmdlen)) !=
8fe9c6 ¤   ¤   ¤   ····sizeof (ctx->cmdlen))
9ebc38 ¤   ¤   ¤   ¤   return kPGPError_FIFOReadError;
e899e3 ¤   ¤   ¤   cmdlen -= sizeof (ctx->cmdlen);
52af5a
b1232d ¤   ¤   ¤   if (pgpFifoRead (ctx->fifod, ctx->ann, ctx->cmdarg,
04e175 ¤   ¤   ¤   ¤   ¤   ·ctx->cmdlen) != ctx->cmdlen)
91bc38 ¤   ¤   ¤   ¤   return kPGPError_FIFOReadError;
751abb ¤   ¤   ¤   cmdlen -= ctx->cmdlen;
2e45a6 ¤   ¤   } else {
9a7aad ¤   ¤   ¤   /*
ccc6c6 ¤   ¤   ¤   ·* If this can happen then we need to do this
4e14cd ¤   ¤   ¤   ·* and keep track of the amount of data left in
918755 ¤   ¤   ¤   ·* the fifo.
7c8753 ¤   ¤   ¤   ·*/
41af5a
ea082b ¤   ¤   ¤   ctx->left = datalen;
503dd5 ¤   ¤   ¤   ctx->written = datalen;
1f0fe4 ¤   ¤   }
ddaf5a
--9d3b 0008263d9ff40100192 Page 14 of pgpPrsAsc.c
ae0408 ¤   } while (datalen || cmdlen || ctx->cmdlen);
67af5a
8074be ¤   /* If we get here then everything has been written out. */
2a6cca ¤   ctx->written = 0;
bcaf5a
b62d68 ¤   return( kPGPError_NoErr );
3eefe6 }
c9af5a
7738e5 /*
d11c1f ·* TBD for MIME support:
be0518 ·* Add a filter to remove some MIME transforms. ·To wit:
cd7e9c ·*¤ First read headers, looking for blank line. ·If see any header other
1af072 ·*¤ than Content-Type: text/plain... or Content-Transfer-Encoding
c698e5 ·*¤ other than quoted-printable (or whatever the plain one is), we can't
df142e ·*¤ handle it, and we should just pass the whole thing through. ·Otherwise
df29d1 ·*¤ we delete the header and trailing blank line. ·We then run through the
f70385 ·*¤ filter which undoes the content-transfer-encoding transformation if
8644be ·*¤ necessary, or else just passes data through.
a60bca ·* This filter should be added just before the copymod, below. ·It might
d7bc69 ·* even replace the copymod, but I don't remember what it is for. ·Something
92567e ·* to do with some error recovery state, where we needed to know we were
35d93a ·* pointing at the last thing in the pipeline before context->tail?
26495d ·*/
d6af5a
4838e5 /*
7864a5 ·* This is a clearsigned message. ·We need to setup the verification
5318dd ·* pipeline to get this to work. ·First we have a join module. ·It is a
03d62c ·* placeholder for the message. ·The clearsigned text goes into the
a0beae ·* second input of the join module. ·The output of the join module goes
2ab8fc ·* to a split. ·The first output of the split goes to the annotation
6e2622 ·* reader. ·The second output of the split goes into a textfilt module
3cae5a ·* to strip the spaces and then into a signature verification module.
15495d ·*/
09f1ae static PGPError
709473 createClearsig (
2afdf9 ¤   PGPContextRef cdkContext,
a3dc6a ¤   PrsAscContext *ctx,
94838f ¤   Message *msg,
4b230d ¤   MsgPart *part)
0fbb36 {
5bd8af ¤   /*
353e6b ¤   ·* We don't need a join module for clearsigning. ·That causes the
615a4d ¤   ·* entire clearsigned part to be buffered in the join module until
e9bc9a ¤   ·* we get to the cleanup phase! ·Redo that.
7da4e3 ¤   ·*/
2cb177 #if 0
16b87c ¤   PGPPipeline *join = NULL, *split = NULL, *text = NULL;
107dc2 ¤   PGPPipeline **tail, **temp;
88258c ¤   PGPPipeline *sighead = NULL, **sigtail;
2aaf5a
f5c0a9 ¤   /* First, build up a replacement "join/split" module */
d01576 ¤   tail = pgpJoinCreate (cdkContext, &join, ctx->fifod);
f2c673 ¤   if (!tail)
5e4030 ¤   ¤   return kPGPError_OutOfMemory;
14af5a
3fe506 ¤   temp = tail;
d9f1c9 ¤   tail = pgpSplitCreate (cdkContext, temp);
9fb2e1 ¤   if (!tail) {
864030 ¤   ¤   return kPGPError_OutOfMemory;
ec9371 ¤   }
a0c8c9 ¤   split = *temp;
80af5a
87f6ff ¤   /* Splice in the join/split in place of the old join/parser */
4ea662 ¤   *(msg->tail) = NULL;
bbbb83 ¤   part->mod->teardown (part->mod);
f4af5a
3c43b9 ¤   part->mod = join;
ba6a66 ¤   msg->tail = tail;
f9af5a
c7d8af ¤   /*
e72a10 ¤   ·* Binary parser may add modules after itself, and in some
829413 ¤   ·* error recovery situations they are still there when we try
--68f6 000b312ba6640100192 Page 15 of pgpPrsAsc.c
6829b4 ¤   ·* to close things. ·Create a copy module to act as a stable
fefbf3 ¤   ·* predecessor to context->tail.
52a4e3 ¤   ·*/
f2ca3f ¤   msg->tail = pgpCopyModCreate ( cdkContext, msg->tail);
56af5a
2b7f0a ¤   /* And connect the tail */
c5d279 ¤   if (msg->tail)
fc42da ¤   ¤   *(msg->tail) = ctx->tail;
c4af5a
b78445 ¤   /* Create the text input */
9c78af ¤   text = pgpJoinAppend (join);
c6e3ce ¤   if (! text) {
864030 ¤   ¤   return kPGPError_OutOfMemory;
2f9371 ¤   }
f2af5a
cc955c ¤   /* add a textfilt module */
a92a59 ¤   tail = pgpSplitAdd (split);
dcb2e1 ¤   if (!tail) {
204a5a ¤   ¤   text->teardown (text);
1f4030 ¤   ¤   return kPGPError_OutOfMemory;
ce9371 ¤   }
e2af5a
9c4472 #if MIMEPARSE
c6b1b6 ¤   tail = pgpTextFiltCreate (cdkContext, tail, charMapIdentity, 1,
1f7274 ¤   ¤   ¤   (ctx->mime_signed ? kPGPLineEnd_CRLF : kPGPLineEnd_Default));
26db21 #else
f6e516 ¤   tail = pgpTextFiltCreate ( cdkContext,
5d1020 ¤   ¤   tail, charMapIdentity, 1, kPGPLineEnd_Default);
397454 #endif
2cb2e1 ¤   if (!tail) {
fe4a5a ¤   ¤   text->teardown (text);
8b4030 ¤   ¤   return kPGPError_OutOfMemory;
a19371 ¤   }
40af5a
6240e9 ¤   /* Create the signature parser... */
9a6f4b ¤   sigtail = pgpParseBinCreate ( cdkContext, &sighead, ctx->env,
fc73ca ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··ctx->ui, ctx->ui_arg );
30963a ¤   if (!sigtail) {
c14a5a ¤   ¤   text->teardown (text);
fc4030 ¤   ¤   return kPGPError_OutOfMemory;
c69371 ¤   }
82af5a
ac36dc ¤   /* ...and the signature verifier */
ffb6fa ¤   if (!pgpVerifyReaderCreate ( cdkContext,
725c41 ¤   ¤   ¤   ¤   tail, sigtail, ctx->env, ctx->fifod,
a14b72 ¤   ¤   ¤   ¤   ····(ctx->hashlen ? ctx->hashlist : NULL),
811a63 ¤   ¤   ¤   ¤   ····ctx->hashlen, (ctx->hashlen ? 1 : 0),
0dab22 ¤   ¤   ¤   ¤   ····ctx->ui, ctx->ui_arg)) {
ab4a5a ¤   ¤   text->teardown (text);
23d829 ¤   ¤   sighead->teardown (sighead);
d74030 ¤   ¤   return kPGPError_OutOfMemory;
629371 ¤   }
3eaf5a
5eb5ef ¤   /* Now put it all together in this message */
f613f9 ¤   part->text = text;
44a92d ¤   part->sig = sighead;
97db21 #else
a1e817 ¤   PGPPipeline *text = NULL;
a72c96 ¤   PGPPipeline **tail;
b1258c ¤   PGPPipeline *sighead = NULL, **sigtail;
3daf5a
36512a ¤   tail = pgpSplitCreate (cdkContext, &text);
a7af5a
f66384 ¤   /* Splice in the split in place of the old join/parser */
29a662 ¤   *(msg->tail) = NULL;
f1bb83 ¤   part->mod->teardown (part->mod);
96af5a
b9ae9d ¤   part->mod = NULL;¤  ¤   /* No join module */
d86a66 ¤   msg->tail = tail;
51af5a
03d8af ¤   /*
b32a10 ¤   ·* Binary parser may add modules after itself, and in some
--749c 00067e6952040100192 Page 16 of pgpPrsAsc.c
3b9413 ¤   ·* error recovery situations they are still there when we try
9e29b4 ¤   ·* to close things. ·Create a copy module to act as a stable
dafbf3 ¤   ·* predecessor to context->tail.
7ca4e3 ¤   ·*/
f4ca3f ¤   msg->tail = pgpCopyModCreate ( cdkContext, msg->tail);
c1af5a
7a7f0a ¤   /* And connect the tail */
83d279 ¤   if (msg->tail)
fb42da ¤   ¤   *(msg->tail) = ctx->tail;
70af5a
bc955c ¤   /* add a textfilt module */
ffb977 ¤   tail = pgpSplitAdd (text);
1bb2e1 ¤   if (!tail) {
704030 ¤   ¤   return kPGPError_OutOfMemory;
659371 ¤   }
8daf5a
9ef66b ¤   /* Not clear about using Default on non-MIME here */
d2b1b6 ¤   tail = pgpTextFiltCreate (cdkContext, tail, charMapIdentity, 1,
607274 ¤   ¤   ¤   (ctx->mime_signed ? kPGPLineEnd_CRLF : kPGPLineEnd_Default));
95b2e1 ¤   if (!tail) {
a94030 ¤   ¤   return kPGPError_OutOfMemory;
3c9371 ¤   }
a6af5a
9c40e9 ¤   /* Create the signature parser... */
d06f4b ¤   sigtail = pgpParseBinCreate ( cdkContext, &sighead, ctx->env,
d1574f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··ctx->ui, ctx->ui_arg);
3b963a ¤   if (!sigtail) {
924030 ¤   ¤   return kPGPError_OutOfMemory;
189371 ¤   }
2caf5a
a836dc ¤   /* ...and the signature verifier */
14b6fa ¤   if (!pgpVerifyReaderCreate ( cdkContext,
e75c41 ¤   ¤   ¤   ¤   tail, sigtail, ctx->env, ctx->fifod,
f44b72 ¤   ¤   ¤   ¤   ····(ctx->hashlen ? ctx->hashlist : NULL),
c01a63 ¤   ¤   ¤   ¤   ····ctx->hashlen, (ctx->hashlen ? 1 : 0),
90ab22 ¤   ¤   ¤   ¤   ····ctx->ui, ctx->ui_arg)) {
e2d829 ¤   ¤   sighead->teardown (sighead);
c14030 ¤   ¤   return kPGPError_OutOfMemory;
bd9371 ¤   }
19af5a
69b5ef ¤   /* Now put it all together in this message */
3b13f9 ¤   part->text = text;
7ba92d ¤   part->sig = sighead;
f57454 #endif
afaf5a
092d68 ¤   return( kPGPError_NoErr );
16efe6 }
8faf5a
5038e5 /*
bbbab4 ·* Build up the Ascii Parser Table in order to dearmor data. ·For all
775b59 ·* values, set it to -1 if it is not a valid armor character and then
7f776b ·* set the valid characters out of the armorTable.
c3775e ·*
f865ce ·* To make it thread-safe, init using local table, then copy table
f4fe7c ·* to global.
2a495d ·*/
492978 static void
eb2dcf parseAscInit (void)
f0bb36 {
171d59 ¤   #define kDearmorTableSize¤  ¤   ( (PGPSize)256 )
d35d1c ¤   static char ¤   ¤   sDearmorTableStorage[ kDearmorTableSize ];
cbd90a ¤   static PGPBoolean¤  sInited = FALSE;
1167c5 ¤
7be595 ¤   int¤¤   i;
3eef35 ¤   char¤   tempTable[ kDearmorTableSize ];
fcaf5a
b2db42 ¤   if ( sInited )
9c99bf ¤   ¤   return;
3faf5a
756d61 ¤   for (i = 0; i < (int)kDearmorTableSize; i++)
3bac22 ¤   ¤   tempTable[i] = -1;
67af5a
--8467 0003e3004c740100192 Page 17 of pgpPrsAsc.c
3f5406 ¤   for (i = 0; i < (int)(sizeof(armorTable) - 1); i++)
599b34 ¤   ¤   tempTable[armorTable[i] & 0xff] = (char)i;
30af5a
cbc747 ¤   pgpCopyMemory( tempTable, sDearmorTableStorage, sizeof(tempTable) );
185af8 ¤   sDearmorTable¤  = &sDearmorTableStorage[ 0 ];
4667c5 ¤
c4ab8a ¤   /* set 'sInited' only after everything has been setup above */
b707e8 ¤   sInited¤¤   ¤   = 1;
6e830f ¤   return;
ddefe6 }
36af5a
4838e5 /*
db8c30 ·* Convert input bytes to output bytes. ·Returns the number of
51d4ec ·* input bytes successfully converted. ·The number of output
5e4a23 ·* bytes available is one less than this number.
ad495d ·*/
d8beb7 static int
3100b8 dearmorMorsel (PGPByte const in[4], PGPByte out[3])
fdbb36 {
ba4fb0 ¤   signed char c0, c1;
f3af5a
16e633 ¤   c0 = sDearmorTable[in[0] & 255];
45ecf1 ¤   if (c0 < 0)
d3bbde ¤   ¤   return 0;
67c4c0 ¤   c1 = sDearmorTable[in[1] & 255];
637324 ¤   if (c1 < 0)
55e102 ¤   ¤   return 1;
2eaf5a
0cd4d6 ¤   out[0] = (c0 & 63u) << 2 | (c1 & 63u) >> 4;
3eaf5a
aa4d11 ¤   c0 = sDearmorTable[in[2] & 255];
13ecf1 ¤   if (c0 < 0)
ce0e66 ¤   ¤   return 2;
1baf5a
6eb714 ¤   out[1] = (c1 & 63u) << 4 | (c0 & 63u) >> 2;
d9af5a
986fe2 ¤   c1 = sDearmorTable[in[3] & 255];
c67324 ¤   if (c1 < 0)
e254ba ¤   ¤   return 3;
0eaf5a
306647 ¤   out[2] = (c0 & 63u) << 6 | (c1 & 63u);
fdaf5a
985d0a ¤   return 4;
30efe6 }
9aaf5a
8c38e5 /*
1ddf4a ·* Given a line of a certain length, convert to binary and
d666f0 ·* return the number of binary bytes that result, or -1 on error.
f9775e ·*
6d2d73 ·* This is very fussy about trailing junk and whatnot.
1eab7b ·* There is some complexity due to accepting "=3D" in place
9afd62 ·* of a normal "=". ·This is to allow MIME-encapsulated messages
c6df52 ·* to be input directly, without having MIME unencapsulate them
b76aa4 ·* first.
1f775e ·*
498cc3 ·* This will ignore trailing white space and give an error if there
93d7a6 ·* is too much data on the line.
83495d ·*/
49beb7 static int
124b98 dearmorLine (PGPByte const *in, PGPByte *out, unsigned inlen)
58bb36 {
7d0d3d ¤   int outlen = 0;
8b314e ¤   int t;
6aaf5a
5a145e ¤   while ((t = dearmorMorsel (in, out)) == 4) {
f58166 ¤   ¤   in += 4;
a3033e ¤   ¤   out += 3;
bb5098 ¤   ¤   inlen -= 4;
ed22eb ¤   ¤   outlen += 3;
acf064 ¤   ¤   if (inlen < 4)
eca61a ¤   ¤   ¤   return inlen ? -1 : outlen;
3e9371 ¤   }
--ca6e 0001da36a3040100192 Page 18 of pgpPrsAsc.c
b18de6 ¤   switch (t) {
10e5e9 ¤   ··case 2:
7c88a6 ¤   ¤   if (inlen == 4) {
4321d6 ¤   ¤   ¤   if (in[2] == '=' && in[3] == '=')
edc40a ¤   ¤   ¤   ¤   return outlen + 1;
602541 ¤   ¤   } else if (inlen == 8) {
4580f1 ¤   ¤   ¤   if (in[2] == '=' && in[3] == '3' && in[4] == 'D' &&
8e0498 ¤   ¤   ¤   ····in[5] == '=' && in[6] == '3' && in[7] == 'D')
7bc40a ¤   ¤   ¤   ¤   return outlen + 1;
4e0fe4 ¤   ¤   }
f82f68 ¤   ¤   break;
f0bf35 ¤   ··case 3:
d488a6 ¤   ¤   if (inlen == 4) {
478a38 ¤   ¤   ¤   if (in[3] == '=')
3c2b6e ¤   ¤   ¤   ¤   return outlen + 2;
9e44f9 ¤   ¤   } else if (inlen == 6) {
778ac3 ¤   ¤   ¤   if (in[3] == '=' && in[4] == '3' && in[5] == 'D')
432b6e ¤   ¤   ¤   ¤   return outlen + 2;
c00fe4 ¤   ¤   }
6a2f68 ¤   ¤   break;
9b9371 ¤   }
fb4073 ¤   /* None of the above - we have an error */
4ce69f ¤   return -1;
53af5a
4aefe6 }
b3af5a
a338e5 /*
2742d1 ·* Return true if the line is a valid candidate as an armor line,
81fe21 ·* one with no bad characters. ·This will allow us to have ascii armor
65ff19 ·* with no headers and no blanks before the armor data.
dc0f97 ·* A better check would look for mults of 4 or trailing '=', but we don't
c69d64 ·* do that yet.
4e495d ·*/
54beb7 static int
057d63 validArmorLine (PGPByte const *in, unsigned inlen)
12bb36 {
c71fe3 ¤   while (inlen--) {
108060 ¤   ¤   /* Fail if bad character */
b8d7ac ¤   ¤   if( sDearmorTable[in[0] & 255] < 0 ·&& in[0] != '=')
b55f1f ¤   ¤   ¤   return FALSE;
3a376e ¤   ¤   ++in;
fe9371 ¤   }
ecc2e7 ¤   return TRUE;
70efe6 }
0aaf5a
c838e5 /*
6398fb ·* Given a line thought to contain a CRC, this returns the 24-bit
9eb3f5 ·* CRC, or -1 on error. ·Handles possible MIME expansion
d3cf10 ·* of "=" to "=3D".
df495d ·*/
1b77fd static long
9fd1c3 dearmorCrc (PGPByte const *in, unsigned inlen)
7dbb36 {
b43aea ¤   PGPByte buf[3];
1faf5a
224048 ¤   /* skip trailing white space */
f4a683 ¤   while (inlen && isspace (in[inlen - 1]))
b73623 ¤   ¤   inlen--;
f1af5a
2ca05f ¤   if (*in != '=')
4b043c ¤   ¤   return -1;
d4a443 ¤   if (inlen == 5)
4a3c56 ¤   ¤   if (dearmorMorsel (in + 1, buf) != 4)
b53fd5 ¤   ¤   ¤   return -1;
35898d ¤   ¤   else if (inlen == 7)
e4e2fc ¤   ¤   ¤   if (in[1] != '3' || in[2] != 'D' ||
8fdd99 ¤   ¤   ¤   ····dearmorMorsel (in + 3, buf) != 4)
acdd34 ¤   ¤   ¤   ¤   return -1;
1ebb8c ¤   ¤   ¤   else
5edd34 ¤   ¤   ¤   ¤   return -1;
35d8af ¤   /*
1d3f08 ¤   ·* Welcome to the famous ANSI C glitch. ·ANSI C
--3296 0005191cfc840100192 Page 19 of pgpPrsAsc.c
9950a3 ¤   ·* promotes to signed values where possible when preserving
bb234a ¤   ·* the value. ·Thus, buf[1]<<8 is promoted to signed, then
3606b2 ¤   ·* shifted, then promoted to long (on a 16-bit int machine,
d0668d ¤   ·* this causes sign-extension!), and merged with the other
fe381b ¤   ·* values. ·Not Good.
0fc0c8 ¤   ·* I'm beginning to see why people preferred the K&R unsigned-
ef8300 ¤   ·* preserving rules. ·Sigh.
b8a4e3 ¤   ·*/
072990 ¤   return (long)buf[0] << 16 | (unsigned)(buf[1] << 8 | buf[2]);
96efe6 }
50af5a
2038e5 /*
d68ba2 ·* try to fill up ctx->armorline up to LINE_LEN-1 bytes or a newline,
b05e07 ·* whichever comes first.
7f9ec0 ·*·
248fd4 ·* This will set ctx->eol when an EOL condition occurs. ·eol == 1
daa4a6 ·* means armorline is ready for processing. ·eol == 2 means that
7d59a5 ·* readLine needs to be called with more data (looking for \n).
15775e ·*
2b677d ·* The return value is the number of bytes used. ·If all the bytes are
d65496 ·* used and EOL is not set, then more data is required and readLine
716d1e ·* should be called with more data.
2a495d ·*/
205d09 static size_t
250d69 readLine (PrsAscContext *ctx, PGPByte const *buf, size_t size)
69bb36 {
ed6d88 ¤   size_t size0 = size;
bc2a2e ¤   unsigned t, retlen;
f6b104 ¤   PGPByte eol = ctx->eol;
809231 ¤   PGPByte *ptr = ctx->armorline + ctx->armorlen;
81af5a
fefaf0 ¤   if (!size)
adbbde ¤   ¤   return 0;
d1af5a
f25774 ¤   /* If start of new line, remember total byte offset */
00ebfb ¤   if (eol == 0) {
a29120 ¤   ¤   ctx->prevlineoff = ctx->bytesread;
109371 ¤   }
feaf5a
91d8af ¤   /*
1b85b7 ¤   ·* This test is needed in case the '\r' and \'n' come in
fb5e31 ¤   ·* different write calls.
9ba4e3 ¤   ·*/
d5fd73 ¤   if (eol == 2) {
7b9dea ¤   ¤   /* Must have hit a '\r' as last char in previous input buffer */
914eae ¤   ¤   if (*buf == '\n') {
8e0a70 ¤   ¤   ¤   *ptr = *buf;
bb71c1 ¤   ¤   ¤   ctx->armorlen++;
d0d9a7 ¤   ¤   ¤   ctx->eol = 1;
f75a34 ¤   ¤   ¤   ctx->crlf = kPGPLineEnd_CRLF;
73c872 ¤   ¤   ¤   ctx->bytesread++;
11db98 ¤   ¤   ¤   return 1;
5a0fe4 ¤   ¤   }
bb4169 ¤   ¤   /*·
aec269 ¤   ¤   ·* Bug fix here - wasn't doing this. ·This happens when we have CR
a847f1 ¤   ¤   ·* terminated lines and a CR right before end of buffer. ·Should just
4bbf7d ¤   ¤   ·* reset our state on start of next buffer.
b59de3 ¤   ¤   ·*/
201e12 ¤   ¤   ctx->eol = 1;
e5bbde ¤   ¤   return 0;
889371 ¤   }
adaf5a
2d426f ¤   /* try to fill the input buffer with a line */
2e7acc ¤   t = (unsigned)pgpMin (LINE_LEN-1 - ctx->armorlen, size);
aa311a ¤   for (eol = 0, retlen = 0; retlen < t && !eol; retlen++) {
cf479e ¤   ¤   *ptr++ = *buf;
b1cdeb ¤   ¤   if (*buf == '\r' || *buf == '\n')
9d11b1 ¤   ¤   ¤   eol = (*buf == '\r' ? 2 : 1);
f0e21a ¤   ¤   buf++;
fa9371 ¤   }
c79001 ¤   size -= retlen;
519a79 ¤   ctx->armorlen += retlen;
--1389 0002db2f77f40100192 Page 20 of pgpPrsAsc.c
e0af5a
a01d4e ¤   /* Set EOB if we hit the end of the armorline buffer */
b7ee99 ¤   if (ctx->armorlen >= LINE_LEN-1)
759833 ¤   ¤   ctx->eob = 1;
b2af5a
7dd8af ¤   /*
5af5ae ¤   ·* At this point we are either at EOL or not. ·If not, then we
384251 ¤   ·* either ran out of input data or ran out of buffer space. ·If
21d697 ¤   ·* we are at EOL and eol==2 and we have more data, check if its a
07c2c8 ¤   ·* \n or something else. ·If so, copy that in and set eol=1.
aea4e3 ¤   ·*/
0128c7 ¤   if (eol) {
904808 ¤   ¤   ctx->crlf = (eol == 2 ? kPGPLineEnd_CR : kPGPLineEnd_LF);
94af5a
294b55 ¤   ¤   if (eol == 2 && size) {
30e3f0 ¤   ¤   ¤   if (*buf == '\n') {
423e2d ¤   ¤   ¤   ¤   *ptr = *buf;
c2ca97 ¤   ¤   ¤   ¤   ctx->armorlen++;
f463f1 ¤   ¤   ¤   ¤   ctx->crlf = kPGPLineEnd_CRLF;
a84702 ¤   ¤   ¤   ¤   size--;
2ca3a6 ¤   ¤   ¤   }
e66379 ¤   ¤   ¤   eol = 1;
a80fe4 ¤   ¤   }
c29371 ¤   }
3caf5a
ff8174 ¤   /* Save off the EOL and return the number of bytes used */
2cf466 ¤   ctx->eol = eol;
a787cf ¤   ctx->bytesread += size0-size;
033084 ¤   return size0-size;
8fefe6 }
8daf5a
e9af5a
ec4b03 /* memCmpPrefix works like memcmp except it allows certain material to
04a8dd ·* prefix the 1st arg. ·The intention is to generalize the search for
1c9ebe ·* "-----BEGIN PGP MESSAGE-----" so that quoted versions can be matched.
b040b3 ·* The rule presently is that material in angle brackets is ignored, like
a132f4 ·* "<bigger>", because Eudora in richtext mode sometimes puts those in.
c7d886 ·* Likewise non-alphabetic characters will be allowed, because people may
c0ae18 ·* be quoting a PGP message or key with "> " and similar conventions.
4c3775 ·* Only the number of chars specified in testlen must match.
94c8fe ·* In addition to returning the error code, this function returns the
3a8a60 ·* number of skipped chars in *skiplen.
a1495d ·*/
44beb7 static int
464780 memCmpPrefix(const char *orig, size_t origlen, const char *test,
35f078 ¤   ¤   ¤   ·size_t testlen, size_t *skiplen)
2ebb36 {
88c541 ¤   char ctest, corig;
2bd18d ¤   size_t len = 0;
d4ae67 ¤   PGPBoolean inbracket = FALSE;
d6af5a
b62b80 ¤   pgpAssert (IsntNull(skiplen));
803e53 ¤   pgpAssert (testlen > 0);
4067c5 ¤
2b4648 ¤   *skiplen = 0;
275223 ¤   if (origlen == 0)
45bbde ¤   ¤   return 0;
2eaf5a
d52db1 ¤   ctest = test[0];
105870 ¤   for ( ; ; ) {
8e5239 ¤   ¤   if (origlen-len < testlen)
4533bb ¤   ¤   ¤   return 1;¤  ¤   ¤   /* Failure, no match */
468d07 ¤   ¤   corig = orig[len];
17cd3f ¤   ¤   if (!inbracket) {
3f54c4 ¤   ¤   ¤   if (corig == ctest && memcmp (orig+len, test, testlen) == 0) {
a26c21 ¤   ¤   ¤   ¤   *skiplen = len;
f23ce4 ¤   ¤   ¤   ¤   return 0;¤  ¤   ¤   /* Success */
b1a3a6 ¤   ¤   ¤   }
cdcb35 ¤   ¤   ¤   if (isalnum(corig))
fe4102 ¤   ¤   ¤   ¤   return 1;¤  ¤   /* Failure, not a legal prefix */
adc1d8 ¤   ¤   ¤   if (corig == '<')
2d1f99 ¤   ¤   ¤   ¤   inbracket = TRUE;
--84f2 000098de4dc40100192 Page 21 of pgpPrsAsc.c
4f45a6 ¤   ¤   } else {
7df8ae ¤   ¤   ¤   if (corig == '>')
4c3814 ¤   ¤   ¤   ¤   inbracket = FALSE;
2f0fe4 ¤   ¤   }
c6d670 ¤   ¤   ++len;
d49371 ¤   }
4defe6 }
b6af5a
a7af5a
8d38e5 /*
7db512 ·* Contained in buf (of length size) should be a Header-line. ·Parse
a6d089 ·* it appropriately, and store it as necessary.
af775e ·*
d3efa9 ·* A headerline must fit in the armorline buffer (I.e., it must be
5f343e ·* less that LINE_LEN-1 bytes long), it must start with an Alpha
dc825d ·* character and then have up to 64 AlphaNumeric characters or dashes,
8706b7 ·* followed by a colon and then a space. ·A header that does not
6f99c6 ·* conform to this is an error.
2c9ec0 ·*·
bf0585 ·* Returns 0 on success, or a HEADER_ error code.
c9495d ·*/
ff81a4 #define HEADER_TOOLONG¤ -1
19ba71 #define HEADER_INVALID¤ -2
ebbeb7 static int
feddd8 parseHeader (PrsAscContext *ctx, PGPByte const *buf, size_t size)
50bb36 {
7b4ba4 ¤   int i;
e9af06 ¤   char const *ptr = (char const *)buf;
95737a ¤   static char const messageid[] = "MessageID:";
bd0273 ¤   char c;
87af5a
276691 ¤   (void)size;¤¤   /* So, why do I have this arg? */
eaaf5a
0ea8c0 ¤   /* Make sure this is the WHOLE line -- if not, it is an error */
b1ff58 ¤   if (!ctx->eol)
92acdd ¤   ¤   return HEADER_TOOLONG;
e4af5a
46e8fe ¤   /* The first character must be an Alpha character */
75b547 ¤   if (!isalpha (*ptr++))
b6bb82 ¤   ¤   return HEADER_INVALID;
b4af5a
7fa5b0 ¤   i = 1;
c9220e ¤   for (;;) {
b82709 ¤   ¤   c = *ptr++;
695391 ¤   ¤   /* header ends in a colon */
103609 ¤   ¤   if (c == ':')
84cdcb ¤   ¤   ¤   break;
c05709 ¤   ¤   /* Arbitrary label length restriction */
67a24c ¤   ¤   if (++i > 64)
c1a63e ¤   ¤   ¤   return HEADER_TOOLONG;¤ /* Error */
8bde07 ¤   ¤   /* Following chars much be alphanumeric or '-' */
4446cf ¤   ¤   if (!isalnum(c) && c != '-')
c93dd4 ¤   ¤   ¤   return HEADER_INVALID;¤ /* Error */
ff9371 ¤   }
77af5a
6f0750 ¤   /* Must be a space after the ':' */
b1d706 ¤   if (*ptr++ != ' ')
fdbb82 ¤   ¤   return HEADER_INVALID;
3faf5a
c5d8af ¤   /*
b3cdc1 ¤   ·* Now process the header
959714 ¤   ·*
fa7644 ¤   ·* ptr points to the value; buf points to the key (of length
e56b6a ¤   ·* (ptr - buf - 2), plus a colon)
1da4e3 ¤   ·*/
86c953 ¤   i = ptr - (char const *)buf - 1;
1baf5a
06521a ¤   /* Process message ID header */
2d5f75 ¤   if (i == sizeof (messageid) - 1 && !memcmp (buf, messageid, i))
47e284 ¤   ¤   memcpy (ctx->messageid, ptr,
3b9d97 ¤   ¤   ¤   pgpMin ((strlen (ptr) + 1), sizeof (ctx->messageid)));
09af5a
--48ac 000e2a0de9f40100192 Page 22 of pgpPrsAsc.c
14238e ¤   /* XXX: signal an unknown header? */
b1af5a
d73e6b ¤   return 0;
d7efe6 }
4eaf5a
b1ebbe /* Write data to be dearmored.
68775e ·*
6f6d6f ·* The main FSM to control dearmoring. ·The actual FSM is kind of
770ec1 ·* complicated so I'll try to explain it by comments in the code.
c10004 ·* Suffice it to say that there are two main parts of the machine.
605583 ·* The first part deals with armor'ed data, and the second part deals
fb0412 ·* with out-of-armored text. ·There is a little glue between them, and
be1fe7 ·* there you have it...
19775e ·*
9ed021 ·* Here are the states, categorized into general phases of activity:
6d775e ·*
259a7c ·*¤ ·0¤ ¤   ¤   Start state, outside PGP data
3f775e ·*
c75f75 ·*¤ ·10 - ·50¤  ¤   Waiting for start of PGP data
b7775e ·*
9002ac ·*¤ ·90 - 100¤  ¤   Process -----BEGIN PGP line
8e775e ·*
a5fe64 ·*¤ 110 - 130¤  ¤   Process headers after -----BEGIN PGP
6b775e ·*
79b406 ·*¤ 140 - 160¤  ¤   Setup to begin processing armored data
a4775e ·*
de617a ·*¤ 170 - 200¤  ¤   Process PGP armored data
9d775e ·*
91a36d ·*¤ 210 - 230¤  ¤   Process CRC at end of armored data
c4775e ·*
533ebc ·*¤ 240 - 270¤  ¤   Process -----END PGP line, finish up, back to 0
82775e ·*
221f30 ·*¤ 300 - 330¤  ¤   Clearsigned message, process Hash: lines if any
1e775e ·*
b3a8f2 ·*¤ 340 - 360¤  ¤   Setup to begin processing clearsigned message
ca775e ·*
92fc32 ·*¤ 390 - 430¤  ¤   Process clearsigned message body, then to 90 for sig
e6775e ·*
f9b1b9 ·*¤ 500 - 530¤  ¤   Process binary message, to 260 to finish up when done
5b775e ·*
fabe8e ·*¤ 600 - 630¤  ¤   Scan MIME headers, get boundary string
7d775e ·*
0e8205 ·*¤ 650 - 680¤  ¤   Look for initial MIME boundary string, to 340 when found
46775e ·*
033ee8 ·*¤ 700 - 720¤  ¤   Check apparent initial MIME separator, to 340 if looks OK
67775e ·*
61e6f7 ·*¤ 750 - 770¤  ¤   Look for start of PGP sig in MIME clearsig sig part, to 90
71775e ·*
e13054 ·*¤ 800 - 830¤  ¤   Look for final MIME clearsign boundary after PGP sig
c3775e ·*
0e495d ·*/
b45d09 static size_t
9ef37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
bbbb36 {
fe04f3 ¤   PrsAscContext *ctx;
5f5b16 ¤   Message *msg;
dc852c ¤   MsgPart *part;
a9a82b ¤   PGPByte *ptr, *num;
d2d8a4 ¤   static char const prefix1[] = "-----BEGIN PGP ";
de3476 ¤   static char const prefix2[] = ", PART ";
6669ae ¤   static char const prefix3[] = "-----END PGP ";
ad7f93 ¤   static char const suffix[] = "-----";¤  /* With trailing nul */
e60eaf ¤   static char const signedmsg[] = "SIGNED MESSAGE";
815f75 ¤   static char const pubkey[] = "PUBLIC KEY";
d49f9b ¤   static char const privkey[] = "PRIVATE KEY";
4e8b09 ¤   static char const sigprefix[] = "-----BEGIN PGP SIGNATURE-----";
1943b1 ¤   static char const signedprefix[] = "-----BEGIN PGP SIGNED MESSAGE-----";
ed4472 #if MIMEPARSE
00a347 ¤   PGPByte *ptr2;
db53e2 ¤   static char prefix_mimesig2[] = "-----BEGIN PGP MESSAGE-----";
475144 ¤   static char prefix_mime1[] = "content-type: multipart/signed;";
e26b04 ¤   static char prefix_mime2[] = "protocol=\"application/pgp-signature\"";
--0bcf 000e749187f40100192 Page 23 of pgpPrsAsc.c
4cc7c8 ¤   static char prefix_mime3[] = "boundary=";
78b177 #if 0
dc4cd3 ¤   static char prefix_mime4[] = "micalg=";
50b7ee ¤   static char prefix_mime5[] = "pgp-";
8d69f0 #endif /* 0 */
dea3fa #endif /* MIMEPARSE */
4723f4 ¤   int i, thispart, maxparts, lineused;
5865a9 ¤   size_t retval, written = 0;
feccca ¤   unsigned inlen;
46c28f ¤   long crc;
7afcd4 ¤   char temp_c;
07e9fa ¤   PGPContextRef¤  cdkContext;
6867c5 ¤
bc3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
81696e ¤   cdkContext¤ = myself->cdkContext;
e1af5a
3c29be ¤   pgpAssert (myself);
5e8b61 ¤   pgpAssert (myself->magic == DEARMORMAGIC);
8a4866 ¤   pgpAssert (error);
afaf5a
343504 ¤   ctx = (PrsAscContext *)myself->priv;
50d6bc ¤   pgpAssert (ctx);
361728 ¤   pgpAssert (ctx->tail);
4caf5a
c16f5c ¤   switch (ctx->state) {
abf86f ¤   case 0:
f345b5 state_start:
3ae158 ¤   ¤   ctx->state = 0;
8d1b17 ¤   ¤   /*
6c0b5b ¤   ¤   ·* This is the "start" position. ·Check if we are
01c845 ¤   ¤   ·* buffering and flush buffers if we are not. ·Then go
87c821 ¤   ¤   ·* to the next state.
479de3 ¤   ¤   ·*/
55af5a
7c67c2 ¤   ¤   if (!ctx->buffering) {
b6133d ¤   ¤   ¤   *error = flushBuffers (ctx);
90b5c5 ¤   ¤   ¤   if (*error)
f4f622 ¤   ¤   ¤   ¤   break;
850fe4 ¤   ¤   }
a2af5a
cd8224 ¤   ¤   /* FALLTHROUGH */
7fed30 ¤   case 10:
0fbb7d state_wait_for_pgp:
12eb11 ¤   ¤   ctx->state = 10;
0b16f6 ¤   ¤   /* call readline until we have EOB or EOL */
51af5a
22e811 ¤   ¤   retval = readLine (ctx, buf, size);
8ad549 ¤   ¤   size -= retval;
3cea46 ¤   ¤   buf += retval;
1149d8 ¤   ¤   written += retval;
72af5a
644fc6 ¤   ¤   if (ctx->eol || ctx->eob)
a4b110 ¤   ¤   ¤   ;
9b0e1d ¤   ¤   else
cdcdcb ¤   ¤   ¤   break;
37af5a
eb8224 ¤   ¤   /* FALLTHROUGH */
2ac8fd ¤   case 20:
bccedc ¤   ¤   ctx->state = 20;
0b1b17 ¤   ¤   /*
059cda ¤   ¤   ·* check the line for BEGIN. ·If it is not a begin
a139ec ¤   ¤   ·* then we should output this line. ·If it is a begin,
4dd769 ¤   ¤   ·* then we need to parse it as an armor beginning.
62a673 ¤   ¤   ·* Use special compare routine which skips some prefixes of the
6bc7ad ¤   ¤   ·* test line so we can recognize "- -----BEGIN PGP" and such.
5c9de3 ¤   ¤   ·*/
f7af5a
1a0f77 ¤   ¤   if (ctx->armorlen > sizeof (prefix1) - 1 &&
303553 ¤   ¤   ····!memCmpPrefix ((char *)ctx->armorline, ctx->armorlen,
f62fef ¤   ¤   ¤   ¤   ¤   ¤   ···prefix1, sizeof (prefix1) - 1,
aa2c07 ¤   ¤   ¤   ¤   ¤   ¤   ···&ctx->skipPrefixLength)) {
e77aad ¤   ¤   ¤   /*
--0df4 000a619ea7d40100192 Page 24 of pgpPrsAsc.c
911514 ¤   ¤   ¤   ·* Don't allow a prefix on BEGIN PGP SIGNATURE or BEGIN PGP
61b5b5 ¤   ¤   ¤   ·* SIGNED MESSAGE. ·People often quote signed messages in replies
b74c5f ¤   ¤   ¤   ·* and we don't want to trigger on those. ·And the SIGNATURE
fc76e2 ¤   ¤   ¤   ·* is the last part of the signed message.
568753 ¤   ¤   ¤   ·*/
b358a8 ¤   ¤   ¤   if (ctx->skipPrefixLength == 0 ||
f7092b ¤   ¤   ¤   ¤   (memcmp(ctx->armorline+ctx->skipPrefixLength, sigprefix,
a3f17c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(sigprefix)-1)!=0 &&
1fef7a ¤   ¤   ¤   ¤   ·memcmp(ctx->armorline+ctx->skipPrefixLength, signedprefix,
7264b7 ¤   ¤   ¤   ¤   ¤   ¤   ··¤ ¤   ¤   ¤   sizeof(signedprefix)-1)!=0 )) {
d72557 ¤   ¤   ¤   ¤   if (ctx->skipPrefixLength > 0) {
13926f ¤   ¤   ¤   ¤   ¤   pgpAssert (ctx->skipPrefixLength <
48f333 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···¤¤   ¤   ¤   sizeof(ctx->skipPrefix));
6b5f30 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory (ctx->armorline, ctx->skipPrefix,
e57282 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->skipPrefixLength);
b88901 ¤   ¤   ¤   ¤   ¤   ctx->skipPrefix[ctx->skipPrefixLength] = '\0';
472613 ¤   ¤   ¤   ¤   }
2407af ¤   ¤   ¤   ¤   goto state_pgp_begin;
f4a3a6 ¤   ¤   ¤   }
ff0fe4 ¤   ¤   }
471b17 ¤   ¤   /*
3f9a26 ¤   ¤   ·* check the line to see if it is the beginning of a
69928c ¤   ¤   ·* PGP binary message. ·This check is only done the
e43312 ¤   ¤   ·* first time through this loop, using ctx->annotation
4bf6ef ¤   ¤   ·* as the loop detector. ·If this is a PGP message,
49e447 ¤   ¤   ·* then treat it as such and buffer the data for
fa485c ¤   ¤   ·* processing through a parser.
4c9de3 ¤   ¤   ·*/
58383e ¤   ¤   ·
3e9d8f ¤   ¤   if (! ctx->annotation) {
429dfa ¤   ¤   ¤   if (pgpFileTypePGP (ctx->armorline, ctx->armorlen))
59f776 ¤   ¤   ¤   {
47980e ¤   ¤   ¤   ¤   /*
527463 ¤   ¤   ¤   ¤   ·* ooh, a binary PGP message fed into the
6abfde ¤   ¤   ¤   ¤   ·* ascii armor parser!
231020 ¤   ¤   ¤   ¤   ·*/
da7448 ¤   ¤   ¤   ¤   goto state_pgp_binary;
b4a3a6 ¤   ¤   ¤   }
630fe4 ¤   ¤   }
69af5a
d54472 #if MIMEPARSE
f41b17 ¤   ¤   /*
ae391a ¤   ¤   ·* Look for either the MIME content-type message, or what looks
adb649 ¤   ¤   ·* like a MIME message boundary (in case we don't have headers).
899de3 ¤   ¤   ·*/
986a36 ¤   ¤   if (ctx->armorlen > sizeof (prefix_mime1) - 1 &&
d28acf ¤   ¤   ¤   !strncmp_ignorecase ((char *)ctx->armorline, prefix_mime1,
f75ef4 ¤   ¤   ¤   ¤   ¤   ¤   ··sizeof (prefix_mime1) - 1)) {
9d7043 ¤   ¤   ¤   /* MIME header */
517a0b ¤   ¤   ¤   goto state_pgpmime;
a00fe4 ¤   ¤   }
c5af5a
121b17 ¤   ¤   /*
c98385 ¤   ¤   ·* If no_mime_headers, we have only a body, so assume that a line
ff85b2 ¤   ¤   ·* starting with -- is a pgp/mime signed part. ·This is not a very
c72f98 ¤   ¤   ·* good assumption in general, so we will assume that we had some
9184b7 ¤   ¤   ·* reason to think so.
889de3 ¤   ¤   ·*/
368bba ¤   ¤   if (ctx->no_mime_headers && ctx->eol &&
8dec5e ¤   ¤   ¤   ctx->armorlen > 2 && !memcmp (ctx->armorline, "--", 2) &&
709bed ¤   ¤   ¤   ctx->eol) {
1fccbb ¤   ¤   ¤   /* Potential MIME initial body indicator */
859e5b ¤   ¤   ¤   goto state_pgpmime_body_noheaders;
960fe4 ¤   ¤   }
617454 #endif
0baf5a
398224 ¤   ¤   /* FALLTHROUGH */
afd446 ¤   case 30:
566114 state_nonpgp:
e2d267 ¤   ¤   ctx->state = 30;
3874d5 ¤   ¤   /* send annotation if we need to */
a66a4c ¤   ¤   /* Get here with armorlen==0 only on flush call, don't annotate then */
--99c8 000b05d63f240100192 Page 25 of pgpPrsAsc.c
204e00 ¤   ¤   ctx->sectoff = ctx->prevlineoff;
8581e6 ·¤  ¤   if (!ctx->annotation && ctx->armorlen!=0) {
5c3a20 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_NONPGP_BEGIN,
25b18b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPByte *)&ctx->sectoff, sizeof(ctx->sectoff));
2d23bc ·¤  ¤   ¤   if (*error)
a01690 ·¤  ¤   ¤   ¤   break;
664953 ·¤  ¤   ¤   ctx->annotation = PGPANN_NONPGP_END;
6f7c5e ¤   ¤   ¤   ctx->depth_at_ann = ctx->scope_depth;
c952ed ·¤  ¤   }
7c8224 ¤   ¤   /* FALLTHROUGH */
858367 ¤   case 40:
046c95 state_nonpgp_output:
148546 ¤   ¤   ctx->state = 40;
4a42af ¤   ¤   /* output armorline buffer */
950356 ¤   ¤   while (ctx->armorlen) {
41d57e ¤   ¤   ¤   retval = writeExtraData (ctx, ctx->armorptr,
94adb0 ¤   ¤   ¤   ¤   ¤   ¤   ·ctx->armorlen, error);
7e31e5 ¤   ¤   ¤   ctx->armorptr += retval;
59d68c ¤   ¤   ¤   ctx->armorlen -= retval;
51b5c5 ¤   ¤   ¤   if (*error)
430651 ¤   ¤   ¤   ¤   return written;
0c0fe4 ¤   ¤   }
c8c550 ¤   ¤   ctx->armorptr = ctx->armorline;
858224 ¤   ¤   /* FALLTHROUGH */
b99fdc ¤   case 50:
0999fd ¤   ¤   ctx->state = 50;
af1b17 ¤   ¤   /*
6fd452 ¤   ¤   ·* if EOL == 1, clear state and goto state wait_for_pgp, otherwise
642145 ¤   ¤   ·* read data and return to state nonpgp_output to output the line.
bd9de3 ¤   ¤   ·*/
cf4743 ¤   ¤   if (ctx->eol == 1) {
c5837b ¤   ¤   ¤   ctx->eol = 0;
4e055a ¤   ¤   ¤   ctx->eob = 0;
45c33d ¤   ¤   ¤   goto state_wait_for_pgp;
9f0fe4 ¤   ¤   }
ebaf5a
ca1853 ¤   ¤   if (!size)
89cdcb ¤   ¤   ¤   break;
5faf5a
c1e811 ¤   ¤   retval = readLine (ctx, buf, size);
47d549 ¤   ¤   size -= retval;
66ea46 ¤   ¤   buf += retval;
5349d8 ¤   ¤   written += retval;
50af5a
37829e ¤   ¤   goto state_nonpgp_output;
84af5a
de08e8 ¤   case 90:
d00abe state_pgp_begin:
f70ec9 ¤   ¤   ctx->state = 90;
474169 ¤   ¤   /*·
68ee27 ¤   ¤   ·* parse begin line. ·If this is not a valid begin
dca542 ¤   ¤   ·* line, assume that it is not and output it as
738745 ¤   ¤   ·* non-PGP text (in state nonpgp).
4be066 ¤   ¤   ·* skipPrefixLength holds extra chars to skip at beginning
c89de3 ¤   ¤   ·*/
8c4e00 ¤   ¤   ctx->sectoff = ctx->prevlineoff;
694878 ¤   ¤   ptr = ctx->armorline + sizeof (prefix1) - 1 + ctx->skipPrefixLength;
c9d40d ¤   ¤   lineused = ctx->armorlen - (sizeof (prefix1) - 1)
0173d0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   - ctx->skipPrefixLength;
28de84 ¤   ¤   thispart = maxparts = 0;
5eaf5a
c94392 ¤   ¤   do {
92ca45 ¤   ¤   ¤   if (lineused == 0) {
defa39 ¤   ¤   ¤   ¤   /* not a valid BEGIN line */
3af366 ¤   ¤   ¤   ¤   goto state_nonpgp;
56a3a6 ¤   ¤   ¤   }
35af5a
510aa6 ¤   ¤   } while (isspace (ptr[--lineused]));
a4af5a
2e9bf5 ¤   ¤   /* temporarily null-terminate this string */
de2e23 ¤   ¤   temp_c = ptr[++lineused];
b000a7 ¤   ¤   ptr[lineused] = '\0';
--6945 0008069ec6540100192 Page 26 of pgpPrsAsc.c
e0af5a
ddeb38 ¤   ¤   if (!memcmp (ptr, signedmsg, sizeof (signedmsg)-1)) {
4a8d73 ¤   ¤   ¤   /* This is a clearsigned message */
f5af5a
a8271e ¤   ¤   ¤   if (ctx->eol) {
bc980e ¤   ¤   ¤   ¤   /*
e83c17 ¤   ¤   ¤   ¤   ·* This looks like a clearsigned
934d02 ¤   ¤   ¤   ¤   ·* message. ·jump into the clearsigned
133377 ¤   ¤   ¤   ¤   ·* parser and parse it.
851020 ¤   ¤   ¤   ¤   ·*/
f98cbe ¤   ¤   ¤   ¤   ptr[lineused] = temp_c;¤¤   /* restore terminator */
9a093f ¤   ¤   ¤   ¤   goto state_cleartext;
c1a3a6 ¤   ¤   ¤   }
1d7aad ¤   ¤   ¤   /*
f545df ¤   ¤   ¤   ·* Someone is playing with us.. This is an
003946 ¤   ¤   ¤   ·* error. ·
5d8753 ¤   ¤   ¤   ·*/
379269 ¤   ¤   ¤   goto err_state_pgp_begin;
2e0fe4 ¤   ¤   }
c3af5a
e1ef44 ¤   ¤   if (ctx->passthroughkey &&
7e95e8 ¤   ¤   ¤   (memcmp (ptr, pubkey, sizeof(pubkey)-1) == 0 ||
5b27b1 ¤   ¤   ¤   ·memcmp (ptr, privkey, sizeof(privkey)-1) == 0)) {
e4bd0a ¤   ¤   ¤   /* Go into passthrough mode on key block */
52ac1e ¤   ¤   ¤   ctx->passthrough = TRUE;
06f52a ¤   ¤   ¤   ptr[lineused] = temp_c;
281648 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
9e4c01 ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
9123bc ·¤  ¤   ¤   if (*error)
6e1690 ·¤  ¤   ¤   ¤   break;
db37af ¤   ¤   ¤   ptr[lineused] = '\0';
2e0fe4 ¤   ¤   }
5eaf5a
516a51 ¤   ¤   /* skip the "whatever" in "-----BEGIN PGP whatever" */
7611cf ¤   ¤   while (isalnum (*ptr) || *ptr == ' ') {
ac1fb0 ¤   ¤   ¤   ptr++;
bae1d9 ¤   ¤   ¤   lineused--;
430fe4 ¤   ¤   }
88af5a
a6762c ¤   ¤   /* check for multipart */
2bc6cc ¤   ¤   if (*ptr == ',') {
5bc8f4 ¤   ¤   ¤   /* "-----BEGIN PGP whatever, PART x[/y]-----" */
5d9a63 ¤   ¤   ¤   if (memcmp (ptr, prefix2, sizeof (prefix2) - 1))
2fae87 ¤   ¤   ¤   ¤   goto err_state_pgp_begin;
5a5314 ¤   ¤   ¤   ptr += sizeof (prefix2) - 1;
ddc772 ¤   ¤   ¤   lineused -= sizeof (prefix2) - 1;
4baf5a
89684e ¤   ¤   ¤   thispart = strtoul ((char *)ptr, (char **)&num, 10);
a2ef75 ¤   ¤   ¤   if (num == NULL || thispart < 0 || thispart > 999)
e5ae87 ¤   ¤   ¤   ¤   goto err_state_pgp_begin;
8daf5a
898f55 ¤   ¤   ¤   lineused -= (num - ptr);
e734e0 ¤   ¤   ¤   ptr = num;
27af5a
8e5bd9 ¤   ¤   ¤   /*·
dbbe35 ¤   ¤   ¤   ·* now check for "/y", if it exists. ·It is
964109 ¤   ¤   ¤   ·* legal for it not to exist, but it must have
0fffa1 ¤   ¤   ¤   ·* either a 'y' here or a messageID.
9c8753 ¤   ¤   ¤   ·*/
29af5a
75de99 ¤   ¤   ¤   if (*ptr == '/') {
24fd0a ¤   ¤   ¤   ¤   maxparts = strtoul ((char *)ptr+1,
651944 ¤   ¤   ¤   ¤   ¤   ¤   ····(char **)&num, 10);
380f0e ¤   ¤   ¤   ¤   if (!num || maxparts < 2 || maxparts > 999)
d19742 ¤   ¤   ¤   ¤   ¤   goto err_state_pgp_begin;
eb8ab8 ¤   ¤   ¤   ¤   lineused -= (num - ptr);
b2d601 ¤   ¤   ¤   ¤   ptr = num;
2da3a6 ¤   ¤   ¤   }
1045a6 ¤   ¤   } else {
6bb930 ¤   ¤   ¤   thispart = maxparts = 1;
a70fe4 ¤   ¤   }
8008f6 ¤   ¤   if (memcmp (ptr, suffix, sizeof (suffix)))
--6529 000e5568a1440100192 Page 27 of pgpPrsAsc.c
a49269 ¤   ¤   ¤   goto err_state_pgp_begin;
2615aa ¤   ¤   ctx->thispart = thispart;
3010db ¤   ¤   ctx->maxparts = maxparts;
156e9f ¤   ¤   goto state_pgp_end_anno;
7a9311 err_state_pgp_begin:
ae7ed6 ¤   ¤   ptr[lineused] = temp_c;
a16b31 ¤   ¤   goto state_nonpgp;
64af5a
f9de13 ·¤  case 100:
552bb7 state_pgp_end_anno:
742865 ¤   ¤   ctx->state = 100;
7c54e8 ·¤  ¤   /* Send end-annotation (if we sent a begin annotation) */
af24b1 ·¤  ¤   if (ctx->annotation) {
590f72 ¤   ¤   ¤   pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
8d1cf2 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, ctx->annotation,
c6461e ·¤  ¤   ¤   ¤   ¤   ·······NULL, 0);
2023bc ·¤  ¤   ¤   if (*error)
691690 ·¤  ¤   ¤   ¤   break;
15682e ·¤  ¤   ¤   ctx->annotation = 0;
1252ed ·¤  ¤   }
a25447 ·¤  ¤   /* FALLTHROUGH */
4a4757 ¤   case 110:
700e7a state_pgp_armor_header:
f034de ¤   ¤   ctx->state = 110;
bc2f31 ¤   ¤   /* read until EOL to get to end of the last line */
70af5a
08c550 ¤   ¤   ctx->armorptr = ctx->armorline;
410c99 ¤   ¤   ctx->armorlen = 0;
7fccec ¤   ¤   while (ctx->eol != 1) {
ab18b1 ¤   ¤   ¤   ctx->armorlen = 0;
d0f041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
8f5df0 ¤   ¤   ¤   written += retval;
5208a7 ¤   ¤   ¤   buf += retval;
79232c ¤   ¤   ¤   size -= retval;
0eaf5a
cb23ba ¤   ¤   ¤   if (!size)
230651 ¤   ¤   ¤   ¤   return written;
0e0fe4 ¤   ¤   }
5b44ce ¤   ¤   ctx->eol = 0;
90c2ef ¤   ¤   ctx->eob = 0;
560c99 ¤   ¤   ctx->armorlen = 0;
758224 ¤   ¤   /* FALLTHROUGH */
da629a ¤   case 120:
f01113 ¤   ¤   ctx->state = 120;
4316f6 ¤   ¤   /* call readline until we have EOB or EOL */
b1af5a
d7e811 ¤   ¤   retval = readLine (ctx, buf, size);
f3d549 ¤   ¤   size -= retval;
9dea46 ¤   ¤   buf += retval;
b049d8 ¤   ¤   written += retval;
68af5a
074fc6 ¤   ¤   if (ctx->eol || ctx->eob)
c4b110 ¤   ¤   ¤   ;
550e1d ¤   ¤   else
8fcdcb ¤   ¤   ¤   break;
69af5a
478224 ¤   ¤   /* FALLTHROUGH */
e85b27 ¤   case 125:
6b28ae ¤   ¤   ctx->state = 125;
8cea32 ¤   ¤   /* Send annotation of raw data if in passthrough mode */
eff5a4 ·¤  ¤   if (ctx->passthrough) {
6a1648 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
064c01 ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
b023bc ·¤  ¤   ¤   if (*error)
491690 ·¤  ¤   ¤   ¤   break;
9c52ed ·¤  ¤   }
dcaf5a
028224 ¤   ¤   /* FALLTHROUGH */
4663fa ¤   case 130:¤  ¤
860da8 ¤   ¤   ctx->state = 130;
9d4169 ¤   ¤   /*·
e59af4 ¤   ¤   ·* Process header line, then back to state armor_header,
--f372 00087585ca440100192 Page 28 of pgpPrsAsc.c
383d0d ¤   ¤   ·* or detect end of headers, and go to state armor_nonheader.
cc9de3 ¤   ¤   ·*/
0eaf5a
f4384b ¤   ¤   ptr = ctx->armorline;
264551 ¤   ¤   lineused = ctx->armorlen;
1eaf5a
fb22e6 ¤   ¤   /* Skip past prefix from "-----BEGIN PGP" if it matches */
603d47 ¤   ¤   if (ctx->skipPrefixLength > 0 &&
3b0ac3 ¤   ¤   ¤   (PGPSize)lineused > ctx->skipPrefixLength &&
0464d2 ¤   ¤   ¤   0 == memcmp (ptr, ctx->skipPrefix, ctx->skipPrefixLength)) {
647f1b ¤   ¤   ¤   ptr += ctx->skipPrefixLength;
8e79bf ¤   ¤   ¤   lineused -= ctx->skipPrefixLength;
100fe4 ¤   ¤   }
32af5a
573ef0 ¤   ¤   /* Find trailing white space... */
88d4ad ¤   ¤   while (lineused && isspace (ptr[lineused - 1]))
a4e1d9 ¤   ¤   ¤   lineused--;
7caf5a
185371 ¤   ¤   ctx->noarmorblanks = FALSE;
6d60ba ¤   ¤   if (lineused) {
3be3fc ¤   ¤   ¤   int err;
08f4c6 ¤   ¤   ¤   /* temporarily null-terminate this string */
a1c8ca ¤   ¤   ¤   temp_c = ptr[lineused];
fa37af ¤   ¤   ¤   ptr[lineused] = '\0';
0daf5a
447aad ¤   ¤   ¤   /*
a14368 ¤   ¤   ¤   ·* Change states once we see a non-header line. ·This is
72ca72 ¤   ¤   ¤   ·* now the only way of changing to the state where we are
ba926d ¤   ¤   ¤   ·* parsing the ascii armor. ·It deals with the case where
2ed14a ¤   ¤   ¤   ·* there are no blanks between the headers and the armored
5b4a73 ¤   ¤   ¤   ·* portion, as well as the normal case where there is a blank
8f9646 ¤   ¤   ¤   ·* line, and also munging which inserts blank lines.
178753 ¤   ¤   ¤   ·*/
34fa48 ¤   ¤   ¤   ·if( validArmorLine( ptr, lineused ) ) {
23307f ¤   ¤   ¤   ¤   ptr[lineused] = temp_c;
0173ce ¤   ¤   ¤   ¤   ctx->noarmorblanks = TRUE;
26cf20 ¤   ¤   ¤   ¤   goto state_pgp_armor_nonheader;
a3a3a6 ¤   ¤   ¤   }
c5af5a
b6aeae ¤   ¤   ¤   err = parseHeader (ctx, ptr, lineused);
cb531a ¤   ¤   ¤   if (err) {
a270a0 ¤   ¤   ¤   ¤   *error = sendAnnotate (ctx, myself,
22e19b ¤   ¤   ¤   ¤   ¤   ¤   ·······PGPANN_ARMOR_BADHEADER,
4906dc ¤   ¤   ¤   ¤   ¤   ¤   ·······ctx->armorline,
85fc66 ¤   ¤   ¤   ¤   ¤   ¤   ·······lineused);
17307f ¤   ¤   ¤   ¤   ptr[lineused] = temp_c;
0e43a0 ¤   ¤   ¤   ¤   if (*error)
ac14c3 ¤   ¤   ¤   ¤   ¤   break;
ffaf5a
183892 ¤   ¤   ¤   ¤   /* XXX: Ignore bad headers? */
22a3a6 ¤   ¤   ¤   }
a6af5a
5f4324 ¤   ¤   ¤   goto state_pgp_armor_header;
950fe4 ¤   ¤   }
9faf5a
0b1b17 ¤   ¤   /*
1c519a ¤   ¤   ·* No longer change states on blank lines. ·Instead use
0a417a ¤   ¤   ·* the validArmorLine test above. ·This deals with the munging
ee2cf2 ¤   ¤   ·* done by Eudora which makes every other line a blank line.
519de3 ¤   ¤   ·*/
8646c9 ¤   ¤   goto state_pgp_armor_header;
67af5a
0659c5 ¤   ¤   /* Not reached */
fc8224 ¤   ¤   /* FALLTHROUGH */
e935bb ¤   case 150:
4ea00a state_pgp_armor_nonheader:
824632 ¤   ¤   ctx->state = 150;
5fb9fa ¤   ¤   /* get the message and part information */
abaf5a
0757fb ¤   ¤   if (!ctx->part) {
295bd9 ¤   ¤   ¤   /* This is true for all normal armor messages */
87c4bb ¤   ¤   ¤   msg = getMessage (ctx, ctx->messageid, ctx->maxparts);
--6924 000a954660640100192 Page 29 of pgpPrsAsc.c
0fd14b ¤   ¤   ¤   if (!msg) {
17179e ¤   ¤   ¤   ¤   /* This is an error */
5c72db ¤   ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
e4f622 ¤   ¤   ¤   ¤   break;
89a3a6 ¤   ¤   ¤   }
05107f ¤   ¤   ¤   part = getPart (ctx, msg, ctx->thispart);
a3d590 ¤   ¤   ¤   if (!part) {
a8c876 ¤   ¤   ¤   ¤   /* This is an error too */
7c72db ¤   ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
b2f622 ¤   ¤   ¤   ¤   break;
dda3a6 ¤   ¤   ¤   }
f12446 ¤   ¤   ¤   ctx->part = part;
290fe4 ¤   ¤   }
cd3e02 ¤   ¤   ctx->expectcrc = 0;
318224 ¤   ¤   /* FALLTHROUGH */
fd1076 ¤   case 160:
1063ff ¤   ¤   ctx->state = 160;
991b17 ¤   ¤   /*
01175a ¤   ¤   ·* Either try to make the message writable or send an
0f6e4d ¤   ¤   ·* annotation saying we have a message part.
db9de3 ¤   ¤   ·*/
e9af5a
32c4ce ¤   ¤   msg = ctx->part->msg;
7a7aff ¤   ¤   if (ctx->thispart == 1) {
e45ca3 ¤   ¤   ¤   *error = writeMessage (ctx, msg);
20b5c5 ¤   ¤   ¤   if (*error)
37f622 ¤   ¤   ¤   ¤   break;
0945a6 ¤   ¤   } else {
e49163 ¤   ¤   ¤   PGPByte *b;
3caf5a
085677 ¤   ¤   ¤   b = (PGPByte *)pgpContextMemAlloc( cdkContext,
957ae0 ¤   ¤   ¤   ¤   kPGPPrsAscCmdBufSize, kPGPMemoryMgrFlags_Clear);
26800a ¤   ¤   ¤   if (b == NULL)
48f776 ¤   ¤   ¤   {
a072db ¤   ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
d0f622 ¤   ¤   ¤   ¤   break;
dda3a6 ¤   ¤   ¤   }
7f87c7 ¤   ¤   ¤
787c75 ¤   ¤   ¤   i = 0;
42d06f ¤   ¤   ¤   memcpy (b, &ctx->thispart, sizeof (ctx->thispart));
889d96 ··¤ ¤   ¤   i += sizeof (ctx->thispart);
61af5a
90116b ¤   ¤   ¤   memcpy (b+i, &ctx->maxparts, sizeof (ctx->maxparts));
88e40a ¤   ¤   ¤   i += sizeof (ctx->maxparts);
87af5a
3e8e8e ¤   ¤   ¤   memcpy (b+i, ctx->messageid,
7e97b7 ¤   ¤   ¤   ¤   strlen (ctx->messageid));
3eb641 ¤   ¤   ¤   i += strlen (ctx->messageid);
81af5a
0c325b ¤   ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_ARMOR_PART,
2803b5 ¤   ¤   ¤   ¤   ¤   ·······b, i);
cfd173 ¤   ¤   ¤   pgpContextMemFree( cdkContext, b);
20b5c5 ¤   ¤   ¤   if (*error)
68f622 ¤   ¤   ¤   ¤   break;
5c0fe4 ¤   ¤   }
c162da ¤   ¤   /* If we had no blank lines, we already have an armor buffer */
3ae41f ¤   ¤   if( ctx->noarmorblanks ) {
309624 ¤   ¤   ¤   ctx->noarmorblanks = FALSE;
e62813 ¤   ¤   ¤   goto state_pgp_armor_line;
ff0fe4 ¤   ¤   }
418224 ¤   ¤   /* FALLTHROUGH */
8c0ccd ¤   case 170:
3d0fd2 state_pgp_armor_loop:
3f7f44 ¤   ¤   ctx->state = 170;
e92f31 ¤   ¤   /* read until EOL to get to end of the last line */
3eaf5a
bfc550 ¤   ¤   ctx->armorptr = ctx->armorline;
970c99 ¤   ¤   ctx->armorlen = 0;
60ccec ¤   ¤   while (ctx->eol != 1) {
9618b1 ¤   ¤   ¤   ctx->armorlen = 0;
1af041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
a95df0 ¤   ¤   ¤   written += retval;
--5fc6 000a66d667f40100192 Page 30 of pgpPrsAsc.c
f808a7 ¤   ¤   ¤   buf += retval;
41232c ¤   ¤   ¤   size -= retval;
b0af5a
3023ba ¤   ¤   ¤   if (!size)
dc0651 ¤   ¤   ¤   ¤   return written;
a00fe4 ¤   ¤   }
7144ce ¤   ¤   ctx->eol = 0;
77c2ef ¤   ¤   ctx->eob = 0;
8b0c99 ¤   ¤   ctx->armorlen = 0;
638224 ¤   ¤   /* FALLTHROUGH */
7dbe34 ¤   case 180:
a2cdbd ¤   ¤   ctx->state = 180;
8b16f6 ¤   ¤   /* call readline until we have EOB or EOL */
6caf5a
d1e811 ¤   ¤   retval = readLine (ctx, buf, size);
41d549 ¤   ¤   size -= retval;
80ea46 ¤   ¤   buf += retval;
e249d8 ¤   ¤   written += retval;
e1af5a
944fc6 ¤   ¤   if (ctx->eol || ctx->eob)
e1b110 ¤   ¤   ¤   ;
790e1d ¤   ¤   else
bfcdcb ¤   ¤   ¤   break;
2faf5a
e18224 ¤   ¤   /* FALLTHROUGH */
2b8789 ¤   case 185:
1cf400 ¤   ¤   ctx->state = 185;
a2ea32 ¤   ¤   /* Send annotation of raw data if in passthrough mode */
63f5a4 ·¤  ¤   if (ctx->passthrough) {
661648 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
244c01 ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
8f23bc ·¤  ¤   ¤   if (*error)
561690 ·¤  ¤   ¤   ¤   break;
d152ed ·¤  ¤   }
2caf5a
278224 ¤   ¤   /* FALLTHROUGH */
6ba28f ¤   case 190:
4394d9 state_pgp_armor_line:
acd106 ¤   ¤   ctx->state = 190;
944169 ¤   ¤   /*·
99f61b ¤   ¤   ·* make sure this is not a CRC line. ·If it is a CRC
a94923 ¤   ¤   ·* then goto state armor_crc. ·if it is not a CRC line, then
224b42 ¤   ¤   ·* it must be an armorline. ·So, process it as an
59bd5a ¤   ¤   ·* armor line and then fallthrough to next state to
b99a1e ¤   ¤   ·* output it.
9d9de3 ¤   ¤   ·*/
86af5a
26384b ¤   ¤   ptr = ctx->armorline;
0ee92c ¤   ¤   inlen = ctx->armorlen;
a4af5a
b622e6 ¤   ¤   /* Skip past prefix from "-----BEGIN PGP" if it matches */
26c9fd ¤   ¤   if (ctx->skipPrefixLength > 0 && inlen >= ctx->skipPrefixLength &&
a264d2 ¤   ¤   ¤   0 == memcmp (ptr, ctx->skipPrefix, ctx->skipPrefixLength)) {
cf7f1b ¤   ¤   ¤   ptr += ctx->skipPrefixLength;
4bc52d ¤   ¤   ¤   inlen -= ctx->skipPrefixLength;
370fe4 ¤   ¤   }
b3af5a
5e4d70 ¤   ¤   if (ptr[0] == '=') {
ed3984 ¤   ¤   ¤   /* This looks like a CRC */
69a669 ¤   ¤   ¤   goto state_pgp_armor_crc;
4a0fe4 ¤   ¤   }
2eaf5a
c32756 ¤   ¤   /* find the end of the armorline */
e807ca ¤   ¤   while (inlen && isspace (ptr[inlen - 1]))
d777a8 ¤   ¤   ¤   inlen--;
97af5a
759da9 ¤   ¤   /* check the length of the armorline */
49a9d3 ¤   ¤   if (inlen > 80) {·
b4e6e1 ¤   ¤   ¤   *error = sendAnnotate (ctx, myself,
40a58a ¤   ¤   ¤   ¤   ¤   ·······PGPANN_ARMOR_TOOLONG,
532f0b ¤   ¤   ¤   ¤   ¤   ·······ctx->armorline, ctx->armorlen);
a6b5c5 ¤   ¤   ¤   if (*error)
--b897 0000c55ad0240100192 Page 31 of pgpPrsAsc.c
72f622 ¤   ¤   ¤   ¤   break;
3faf5a
26bab7 ¤   ¤   ¤   goto state_pgp_finish;
ad0fe4 ¤   ¤   }
9baf5a
0ea5b6 ¤   ¤   if (inlen == 0) {
d8065f ¤   ¤   ¤   /* Blank lines are just skipped, some mailers put blanks in */
1fb318 ¤   ¤   ¤   goto state_pgp_armor_loop;
f90fe4 ¤   ¤   }
67af5a
d083dc ¤   ¤   /* Make sure we're not expecting a CRC */
684b1c ¤   ¤   if (ctx->expectcrc) {
428583 ¤   ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_ARMOR_NOCRC,
d42f0b ¤   ¤   ¤   ¤   ¤   ·······ctx->armorline, ctx->armorlen);
c6b5c5 ¤   ¤   ¤   if (*error)
5df622 ¤   ¤   ¤   ¤   break;
d0af5a
f05151 ¤   ¤   ¤   /* Well, maybe this is an end? */
7c4561 ¤   ¤   ¤   goto state_pgp_armor_end;
440fe4 ¤   ¤   }
d9af5a
fdf111 ¤   ¤   if (inlen >= 9 && ptr[inlen-5] == '=') {
be4247 ¤   ¤   ¤   /* Handle CRC at end of armor line */
651339 ¤   ¤   ¤   ctx->crcendline = TRUE;
960dc2 ¤   ¤   ¤   i = dearmorLine (ptr, ctx->databuf, inlen - 5);
ef45a6 ¤   ¤   } else {
d7348f ¤   ¤   ¤   i = dearmorLine (ptr, ctx->databuf, inlen);
9c0fe4 ¤   ¤   }
441b52 ¤   ¤
eed699 ¤   ¤   if (i < 1 || i > 60) {
d7bc8b ¤   ¤   ¤   /* error in deamorline */
b8e6e1 ¤   ¤   ¤   *error = sendAnnotate (ctx, myself,
d036ae ¤   ¤   ¤   ¤   ¤   ·······PGPANN_ARMOR_BADLINE,
332f0b ¤   ¤   ¤   ¤   ¤   ·······ctx->armorline, ctx->armorlen);
d2b5c5 ¤   ¤   ¤   if (*error)
f3f622 ¤   ¤   ¤   ¤   break;
d0bab7 ¤   ¤   ¤   goto state_pgp_finish;
c50fe4 ¤   ¤   }
24b0b2 ¤   ¤   ctx->expectcrc = (i < 48);
c657e7 ¤   ¤   ctx->crc = crcUpdate (ctx->crc, ctx->databuf, i);
847a0f ¤   ¤   ctx->datalen = i;
178452 ¤   ¤   ctx->dataptr = ctx->databuf;
dd8224 ¤   ¤   /* FALLTHROUGH */
d34620 ¤   case 200:
5435a9 ¤   ¤   ctx->state = 200;
c7d116 ¤   ¤   /* output the dearmored data, then goto state armor_loop */
c6ff85 ¤   ¤   /* But check for CRC on end of armor line and to armor_crc if so */
1aaf5a
a9f439 ¤   ¤   part = ctx->part;
b2c7c6 ¤   ¤   while (ctx->datalen) {
782789 ¤   ¤   ¤   retval = writePartData (part, ctx->dataptr,
132720 ¤   ¤   ¤   ¤   ¤   ¤   ctx->datalen, error);
6add32 ¤   ¤   ¤   ctx->dataptr += retval;
7d3a5b ¤   ¤   ¤   ctx->datalen -= retval;
bdb5c5 ¤   ¤   ¤   if (*error)
490651 ¤   ¤   ¤   ¤   return written;
af0fe4 ¤   ¤   }
b3af5a
115bbb ¤   ¤   /* If had CRC at end of last armor line, go process it now */
748e9d ¤   ¤   if (ctx->crcendline) {
5a9d12 ¤   ¤   ¤   ctx->crcendline = FALSE;
10a669 ¤   ¤   ¤   goto state_pgp_armor_crc;
9d0fe4 ¤   ¤   }
b6af5a
94f2eb ¤   ¤   goto state_pgp_armor_loop;
42af5a
1c5a9b ¤   case 210:
2fa711 state_pgp_armor_crc:
022912 ¤   ¤   ctx->state = 210;
26585a ¤   ¤   /* Deal with CRC */
ceaf5a
0c384b ¤   ¤   ptr = ctx->armorline;
--e5ab 00039ca10bd40100192 Page 32 of pgpPrsAsc.c
98e92c ¤   ¤   inlen = ctx->armorlen;
59af5a
3222e6 ¤   ¤   /* Skip past prefix from "-----BEGIN PGP" if it matches */
c9c9fd ¤   ¤   if (ctx->skipPrefixLength > 0 && inlen >= ctx->skipPrefixLength &&
5f64d2 ¤   ¤   ¤   0 == memcmp (ptr, ctx->skipPrefix, ctx->skipPrefixLength)) {
ae7f1b ¤   ¤   ¤   ptr += ctx->skipPrefixLength;
06c52d ¤   ¤   ¤   inlen -= ctx->skipPrefixLength;
890fe4 ¤   ¤   }
35af5a
222756 ¤   ¤   /* find the end of the armorline */
f407ca ¤   ¤   while (inlen && isspace (ptr[inlen - 1]))
7477a8 ¤   ¤   ¤   inlen--;
4daf5a
dd4697 ¤   ¤   if (ptr[0] != '=') {
71dd0c ¤   ¤   ¤   /* Must be CRC at end of line */
53d4f2 ¤   ¤   ¤   pgpAssert(inlen >= 9 && ptr[inlen-5] == '=');
3210fa ¤   ¤   ¤   ptr += inlen - 5;
98d515 ¤   ¤   ¤   inlen = 5;
770fe4 ¤   ¤   }
88af5a
5ddff6 ¤   ¤   crc = dearmorCrc (ptr, inlen);
294527 ¤   ¤   if (crc < 0) {
9b8217 ¤   ¤   ¤   /* error */
9ee6e1 ¤   ¤   ¤   *error = sendAnnotate (ctx, myself,
fcd503 ¤   ¤   ¤   ¤   ¤   ·······PGPANN_ARMOR_CRCCANT,
d82f0b ¤   ¤   ¤   ¤   ¤   ·······ctx->armorline, ctx->armorlen);
67b5c5 ¤   ¤   ¤   if (*error)
7cf622 ¤   ¤   ¤   ¤   break;
0dbab7 ¤   ¤   ¤   goto state_pgp_finish;
5c0fe4 ¤   ¤   }
42e12f ¤   ¤   if ((PGPUInt32)crc != ctx->crc) {
0b0ed1 ¤   ¤   ¤   /* mismatch */
31e6e1 ¤   ¤   ¤   *error = sendAnnotate (ctx, myself,
ce94e7 ¤   ¤   ¤   ¤   ¤   ·······PGPANN_ARMOR_CRCBAD,
7d2f0b ¤   ¤   ¤   ¤   ¤   ·······ctx->armorline, ctx->armorlen);
f8b5c5 ¤   ¤   ¤   if (*error)
80f622 ¤   ¤   ¤   ¤   break;
00bab7 ¤   ¤   ¤   goto state_pgp_finish;
c20fe4 ¤   ¤   }
638224 ¤   ¤   /* FALLTHROUGH */
f37f56 ¤   case 220:
aece10 state_pgp_armor_end_loop:
d30cdf ¤   ¤   ctx->state = 220;
732f31 ¤   ¤   /* read until EOL to get to end of the last line */
44af5a
f5c550 ¤   ¤   ctx->armorptr = ctx->armorline;
2f0c99 ¤   ¤   ctx->armorlen = 0;
6bccec ¤   ¤   while (ctx->eol != 1) {
4018b1 ¤   ¤   ¤   ctx->armorlen = 0;
f1f041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
025df0 ¤   ¤   ¤   written += retval;
5708a7 ¤   ¤   ¤   buf += retval;
f7232c ¤   ¤   ¤   size -= retval;
11af5a
d023ba ¤   ¤   ¤   if (!size)
9a0651 ¤   ¤   ¤   ¤   return written;
e20fe4 ¤   ¤   }
8244ce ¤   ¤   ctx->eol = 0;
03c2ef ¤   ¤   ctx->eob = 0;
fa0c99 ¤   ¤   ctx->armorlen = 0;
e68224 ¤   ¤   /* FALLTHROUGH */
0063ed ¤   case 230:
951064 ¤   ¤   ctx->state = 230;
a716f6 ¤   ¤   /* call readline until we have EOB or EOL */
d3af5a
b6e811 ¤   ¤   retval = readLine (ctx, buf, size);
5bd549 ¤   ¤   size -= retval;
d1ea46 ¤   ¤   buf += retval;
ae49d8 ¤   ¤   written += retval;
81af5a
4e4fc6 ¤   ¤   if (ctx->eol || ctx->eob)
39b110 ¤   ¤   ¤   ;
--ed70 0006c35442740100192 Page 33 of pgpPrsAsc.c
040e1d ¤   ¤   else
dacdcb ¤   ¤   ¤   break;
08af5a
ac8224 ¤   ¤   /* FALLTHROUGH */
d85a50 ¤   case 235:
a429d9 ¤   ¤   ctx->state = 235;
2fea32 ¤   ¤   /* Send annotation of raw data if in passthrough mode */
2bf5a4 ·¤  ¤   if (ctx->passthrough) {
e91648 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
194c01 ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
1923bc ·¤  ¤   ¤   if (*error)
151690 ·¤  ¤   ¤   ¤   break;
0252ed ·¤  ¤   }
fbaf5a
2d8224 ¤   ¤   /* FALLTHROUGH */
e534cc ¤   case 240:
ea4419 state_pgp_armor_end:
dc4745 ¤   ¤   ctx->state = 240;
b72b1f ¤   ¤   /* check for END */
8caf5a
78384b ¤   ¤   ptr = ctx->armorline;
fde92c ¤   ¤   inlen = ctx->armorlen;
bbaf5a
4122e6 ¤   ¤   /* Skip past prefix from "-----BEGIN PGP" if it matches */
45c9fd ¤   ¤   if (ctx->skipPrefixLength > 0 && inlen >= ctx->skipPrefixLength &&
8964d2 ¤   ¤   ¤   0 == memcmp (ptr, ctx->skipPrefix, ctx->skipPrefixLength)) {
6a7f1b ¤   ¤   ¤   ptr += ctx->skipPrefixLength;
93c52d ¤   ¤   ¤   inlen -= ctx->skipPrefixLength;
c60fe4 ¤   ¤   }
44af5a
02400a ¤   ¤   /* ignore blank line here */
1f018f ¤   ¤   while (inlen && isspace (ctx->armorline[inlen - 1]))
c677a8 ¤   ¤   ¤   inlen--;
79af5a
d79c49 ¤   ¤   if (inlen==0) {
7c1b75 ¤   ¤   ¤   goto state_pgp_armor_end_loop;
370fe4 ¤   ¤   }
b9af5a
0291f4 ¤   ¤   /* Look for END PGP line */
43770a ¤   ¤   if (inlen < sizeof (prefix3) - 1 ||
60471b ¤   ¤   ····memcmp (ptr, prefix3, sizeof (prefix3) - 1)) {
99a2bc ¤   ¤   ¤   /* missing end -- do what??? */
28b110 ¤   ¤   ¤   ;
700fe4 ¤   ¤   }
1aaf5a
524472 #if MIMEPARSE
3516ab ¤   ¤   if (ctx->mime_signed) {
135645 ¤   ¤   ¤   /* Special cleanup for MIME, wait for final boundary */
998496 ¤   ¤   ¤   goto state_pgpmime_sig_end;
b50fe4 ¤   ¤   }
537454 #endif
f4af5a
578224 ¤   ¤   /* FALLTHROUGH */
452877 ¤   case 250:
575bfe ¤   ¤   ctx->state = 250;
852f31 ¤   ¤   /* read until EOL to get to end of the last line */
7daf5a
2ec550 ¤   ¤   ctx->armorptr = ctx->armorline;
490c99 ¤   ¤   ctx->armorlen = 0;
a6ccec ¤   ¤   while (ctx->eol != 1) {
4518b1 ¤   ¤   ¤   ctx->armorlen = 0;
36f041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
5b5df0 ¤   ¤   ¤   written += retval;
5308a7 ¤   ¤   ¤   buf += retval;
60232c ¤   ¤   ¤   size -= retval;
0eaf5a
2c23ba ¤   ¤   ¤   if (!size)
bb0651 ¤   ¤   ¤   ¤   return written;
ec0fe4 ¤   ¤   }
24af5a
398224 ¤   ¤   /* FALLTHROUGH */
6c0dba ¤   case 260:
--7a30 000504a262440100192 Page 34 of pgpPrsAsc.c
5bb945 state_pgp_finish:
af7e33 ¤   ¤   ctx->state = 260;
6f1b17 ¤   ¤   /*
e8233c ¤   ¤   ·* finish this part, send an end annotation if we need
7542a2 ¤   ¤   ·* to, then clear the context and go to state start.
002e94 ¤   ¤   ·* Be aware that this state number is hard-coded in SizeAdvise,
8d73d8 ¤   ¤   ·* below.
489de3 ¤   ¤   ·*/
c1af5a
8324b1 ·¤  ¤   if (ctx->annotation) {
6f0f72 ¤   ¤   ¤   pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
f81cf2 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, ctx->annotation,
c4461e ·¤  ¤   ¤   ¤   ¤   ·······NULL, 0);
0823bc ·¤  ¤   ¤   if (*error)
181690 ·¤  ¤   ¤   ¤   break;
41682e ·¤  ¤   ¤   ctx->annotation = 0;
0352ed ·¤  ¤   }
77af5a
2a8224 ¤   ¤   /* FALLTHROUGH */
bfaf5a
5d1101 ¤   case 270:
526288 ¤   ¤   ctx->state = 270;
a6f439 ¤   ¤   part = ctx->part;
7fd061 ¤   ¤   *error = donePart (ctx);
23cf31 ¤   ¤   if (*error)
79cdcb ¤   ¤   ¤   break;
aeaf5a
be087d ¤   ¤   ctx->part = NULL;
827347 ¤   ¤   ctx->thispart = 0;
237fad ¤   ¤   ctx->maxparts = 0;
f4f38d ¤   ¤   pgpClearMemory (ctx->messageid, sizeof (ctx->messageid));
348452 ¤   ¤   ctx->dataptr = ctx->databuf;
2c65f2 ¤   ¤   ctx->datalen = 0;
7bc550 ¤   ¤   ctx->armorptr = ctx->armorline;
db0c99 ¤   ¤   ctx->armorlen = 0;
6c3e02 ¤   ¤   ctx->expectcrc = 0;
082afc ¤   ¤   ctx->crlf = kPGPLineEnd_Default;
555228 ¤   ¤   ctx->saved_crlf = 0;
40bbc6 ¤   ¤   ctx->hashlen = 0;
2444ce ¤   ¤   ctx->eol = 0;
fdc2ef ¤   ¤   ctx->eob = 0;
3d465b ¤   ¤   ctx->skipPrefixLength = 0;
afc09e ¤   ¤   ctx->passthrough = 0;
c6384e ¤   ¤   goto state_start;
4e1b52 ¤   ¤
0c606e ¤   ¤   /* BEGIN CLEARSIGNED MESSAGE BELOW HERE */
ca4d64 ¤   case 300:
03042e state_cleartext:
803eed ¤   ¤   ctx->state = 300;
90af5a
95efa4 ¤   ¤   /* See if going into passthrough mode, send BEGIN line if so */
1ea352 ¤   ¤   if (ctx->passthroughcleartext) {
03ac1e ¤   ¤   ¤   ctx->passthrough = TRUE;
5d6077 ¤   ¤   ¤   /* Send annotation of raw data if in passthrough mode */
f7313b ¤   ¤   ¤   if (ctx->passthrough) {
dc0fc0 ¤   ¤   ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
104ce3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
5443a0 ¤   ¤   ¤   ¤   if (*error)
9614c3 ¤   ¤   ¤   ¤   ¤   break;
87a3a6 ¤   ¤   ¤   }
770fe4 ¤   ¤   }
a8af5a
138224 ¤   ¤   /* FALLTHROUGH */
a674d9 ¤   case 305:
ec0750 ¤   ¤   ctx->state = 305;
6b54e8 ·¤  ¤   /* Send end-annotation (if we sent a begin annotation) */
3624b1 ·¤  ¤   if (ctx->annotation) {
190f72 ¤   ¤   ¤   pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
91f67f ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, ctx->annotation, NULL, 0);
3123bc ·¤  ¤   ¤   if (*error)
fa1690 ·¤  ¤   ¤   ¤   break;
50682e ·¤  ¤   ¤   ctx->annotation = 0;
--cf62 00025a5fe9640100192 Page 35 of pgpPrsAsc.c
4252ed ·¤  ¤   }
33e840 ¤   ¤   /* See if BEGIN line has a header line at the end */
97e937 ¤   ¤   ptr = ctx->armorline + sizeof (prefix1) - 1 + sizeof (signedmsg) - 1;
9cfdbd ¤   ¤   if (!memcmp (ptr, ", ", 2)) {
edd5aa ¤   ¤   ¤   /* Treat remainder of begin line as the first header line */
cb4cba ¤   ¤   ¤   ptr += 2;
06028b ¤   ¤   ¤   ctx->armorlen -= ptr - ctx->armorline;
6b42e8 ¤   ¤   ¤   memcpy (ctx->armorline, ptr, ctx->armorlen);
437e38 ¤   ¤   ¤   goto state_cleartext_header;
a70fe4 ¤   ¤   }
8d41ba ¤   ¤   /* Else skip rest of begin line */
13af5a
b18224 ¤   ¤   /* FALLTHROUGH */
9551df ¤   case 310:
d5bc7b state_cleartext_header_loop:
d22256 ¤   ¤   ctx->state = 310;
661e94 ¤   ¤   /* Read until EOL == 1 to get to the end of the begin line */
36e8ad ¤   ¤   pgpAssert (ctx->eol);
57af5a
20c550 ¤   ¤   ctx->armorptr = ctx->armorline;
330c99 ¤   ¤   ctx->armorlen = 0;
1eccec ¤   ¤   while (ctx->eol != 1) {
5f18b1 ¤   ¤   ¤   ctx->armorlen = 0;
8df041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
2f5df0 ¤   ¤   ¤   written += retval;
ff08a7 ¤   ¤   ¤   buf += retval;
4e232c ¤   ¤   ¤   size -= retval;
5baf5a
4623ba ¤   ¤   ¤   if (!size)
870651 ¤   ¤   ¤   ¤   return written;
ea0fe4 ¤   ¤   }
8d44ce ¤   ¤   ctx->eol = 0;
c2c2ef ¤   ¤   ctx->eob = 0;
d20c99 ¤   ¤   ctx->armorlen = 0;
fd8224 ¤   ¤   /* FALLTHROUGH */
8b7412 ¤   case 320:
68079b ¤   ¤   ctx->state = 320;
57ea54 ¤   ¤   /* read the line after the begin: call readline until
83cb9c ¤   ¤   ·* we have EOB or EOL */
1daf5a
79e811 ¤   ¤   retval = readLine (ctx, buf, size);
11d549 ¤   ¤   size -= retval;
89ea46 ¤   ¤   buf += retval;
4249d8 ¤   ¤   written += retval;
42af5a
c84fc6 ¤   ¤   if (ctx->eol || ctx->eob)
1eb110 ¤   ¤   ¤   ;
510e1d ¤   ¤   else
b2cdcb ¤   ¤   ¤   break;
eeaf5a
118224 ¤   ¤   /* FALLTHROUGH */
654daf ¤   case 325:
973e26 ¤   ¤   ctx->state = 325;
a4ea32 ¤   ¤   /* Send annotation of raw data if in passthrough mode */
96f5a4 ·¤  ¤   if (ctx->passthrough) {
fb1648 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
904c01 ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
4523bc ·¤  ¤   ¤   if (*error)
1a1690 ·¤  ¤   ¤   ¤   break;
e452ed ·¤  ¤   }
5daf5a
748224 ¤   ¤   /* FALLTHROUGH */
2568a9 ¤   case 330:
b03366 state_cleartext_header:
871b20 ¤   ¤   ctx->state = 330;
974936 ¤   ¤   /* Make sure first line after "BEGIN" is empty or "Hash:" */
c04551 ¤   ¤   lineused = ctx->armorlen;
47384b ¤   ¤   ptr = ctx->armorline;
0eaf5a
3c3ef0 ¤   ¤   /* Find trailing white space... */
b0d4ad ¤   ¤   while (lineused && isspace (ptr[lineused - 1]))
25e1d9 ¤   ¤   ¤   lineused--;
--92e1 000dc69700e40100192 Page 36 of pgpPrsAsc.c
e0af5a
e016e7 ¤   ¤   if (lineused && !ctx->hashlen) {
675df2 ¤   ¤   ¤   /* The line MUST be of the form:
6dce1f ¤   ¤   ¤   ·*¤ Hash: <ID>[, <ID>]*
c88753 ¤   ¤   ¤   ·*/
ff0717 ¤   ¤   ¤   /* Check for "Hash:" here, put hashes into
5dfb51 ¤   ¤   ¤   ·* ctx->hashlist and number of hashes into
a50707 ¤   ¤   ¤   ·* ctx->hashlen
928753 ¤   ¤   ¤   ·*/
f3ca15 ¤   ¤   ¤   if (memcmp (ctx->armorline, "Hash: ", 6)) {
6f1ba2 ¤   ¤   ¤   ¤   /* Not a Hash -- Error out */
0baf06 ¤   ¤   ¤   ¤   /* XXX: Should annotate here */
55f366 ¤   ¤   ¤   ¤   goto state_nonpgp;
13a3a6 ¤   ¤   ¤   }
55085d ¤   ¤   ¤   lineused -= 6;
df2fdb ¤   ¤   ¤   ptr += 6;
7eaf5a
88d88d ¤   ¤   ¤   while (lineused) {
0e3102 ¤   ¤   ¤   ¤   PGPHashVTBL const *h;
ca8868 ¤   ¤   ¤   ¤   PGPByte const *comma = (PGPByte const *)
0ca764 ¤   ¤   ¤   ¤   ¤   strchr ((char const *) ptr, ',');
eeb2ce ¤   ¤   ¤   ¤   unsigned len;
66af5a
44f6f9 ¤   ¤   ¤   ¤   if( comma - ptr > lineused )
478b49 ¤   ¤   ¤   ¤   ¤   comma = NULL;
61abb5 ¤   ¤   ¤   ¤   len = comma ? comma-ptr : lineused;
0c3b57 ¤   ¤   ¤   ¤   h = pgpHashByName ((char const *)ptr, len);
d26627 ¤   ¤   ¤   ¤   if (!h) {
e41309 ¤   ¤   ¤   ¤   ¤   /* unknown hash.. now what? */
85d9f6 ¤   ¤   ¤   ¤   ¤   /*XXX: annotate?*/;
ba9317 ¤   ¤   ¤   ¤   } else
4e330c ¤   ¤   ¤   ¤   ¤   ctx->hashlist[ctx->hashlen++] =
e69b78 ¤   ¤   ¤   ¤   ¤   ¤   h->algorithm;
994de1 ¤   ¤   ¤   ¤   ptr += len;
348d73 ¤   ¤   ¤   ¤   lineused -= len;
882a29 ¤   ¤   ¤   ¤   if (comma) {
e492b4 ¤   ¤   ¤   ¤   ¤   if (memcmp (comma, ", ", 2)) {
ef3e21 ¤   ¤   ¤   ¤   ¤   ¤   /* invalid format */
92d73b ¤   ¤   ¤   ¤   ¤   ¤   /* XXX: annotate here */;
881c89 ¤   ¤   ¤   ¤   ¤   }
26025b ¤   ¤   ¤   ¤   ¤   ptr += 2;
8bf36b ¤   ¤   ¤   ¤   ¤   lineused -= 2;
4d2613 ¤   ¤   ¤   ¤   }
74b842 ¤   ¤   ¤   } /* while */
dfaf5a
a75cb4 ¤   ¤   ¤   if (!ctx->eol) {
04bfdf ¤   ¤   ¤   ¤   /* Too long a line */
8e9988 ¤   ¤   ¤   ¤   /* XXX: annotate: bad clearsig */
cd059a ¤   ¤   ¤   ¤   ctx->hashlen = 0;
d5f366 ¤   ¤   ¤   ¤   goto state_nonpgp;
14a3a6 ¤   ¤   ¤   }
bbaf5a
50d986 ¤   ¤   ¤   /* Now we need to get an *extra* line, the separator */
12b394 ¤   ¤   ¤   goto state_cleartext_header_loop;
1c39ad ¤   ¤   } /* if (lineused && !ctx->hashlen) */
23af5a
b16ecb ¤   ¤   if (!ctx->eol || lineused) {
c97aad ¤   ¤   ¤   /*
513b6d ¤   ¤   ¤   ·* We either have a long line or non
7c5762 ¤   ¤   ¤   ·* white-space. ·I bet someone's trying to
7277e4 ¤   ¤   ¤   ·* trick us into believeing this is a real
0fdaaf ¤   ¤   ¤   ·* clearsigned message, but they've added some
404ed1 ¤   ¤   ¤   ·* text to it. ·I dont buy it. ·Output as
b4f565 ¤   ¤   ¤   ·* non-pgp text; goto state nonpgp.
aa8753 ¤   ¤   ¤   ·*/
0eaf5a
b2bd65 ¤   ¤   ¤   /* XXX: Should send an annotation: bad clearsig */
3c3292 ¤   ¤   ¤   ctx->hashlen = 0;
c07f19 ¤   ¤   ¤   goto state_nonpgp;
100fe4 ¤   ¤   }
87869c ¤   ¤   /* FALLTHOUGH */
dc3f88 ¤   case 340:
--3a47 0000e00b75e40100192 Page 37 of pgpPrsAsc.c
cf4472 #if MIMEPARSE
955903 state_cleartext_body:
a07454 #endif
624c01 ¤   ¤   ctx->state = 340;
d59a40 ¤   ¤   /* Read until EOL == 1 to get to the next line */
92e8ad ¤   ¤   pgpAssert (ctx->eol);
bbaf5a
5ac550 ¤   ¤   ctx->armorptr = ctx->armorline;
a30c99 ¤   ¤   ctx->armorlen = 0;
ddccec ¤   ¤   while (ctx->eol != 1) {
a218b1 ¤   ¤   ¤   ctx->armorlen = 0;
9ef041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
6b5df0 ¤   ¤   ¤   written += retval;
1d08a7 ¤   ¤   ¤   buf += retval;
a6232c ¤   ¤   ¤   size -= retval;
17af5a
6f23ba ¤   ¤   ¤   if (!size)
5f0651 ¤   ¤   ¤   ¤   return written;
240fe4 ¤   ¤   }
6844ce ¤   ¤   ctx->eol = 0;
0dc2ef ¤   ¤   ctx->eob = 0;
3d0c99 ¤   ¤   ctx->armorlen = 0;
5c5228 ¤   ¤   ctx->saved_crlf = 0;
912afc ¤   ¤   ctx->crlf = kPGPLineEnd_Default;
ff8224 ¤   ¤   /* FALLTHROUGH */
322333 ¤   case 350:
2750ba ¤   ¤   ctx->state = 350;
4aedb8 ¤   ¤   /* Ok, this is a clearsigned message. ·Send a new
f38ba4 ¤   ¤   ·* begin annotation
019de3 ¤   ¤   ·*/
c5f0b7 ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARSIG_BEGIN,
b771cd ·¤  ¤   ¤   ¤   ¤   ·······(PGPByte *)&ctx->sectoff, sizeof(ctx->sectoff));
7bcf31 ¤   ¤   if (*error)
1fcdcb ¤   ¤   ¤   break;
d43aaf ¤   ¤   ctx->annotation = PGPANN_CLEARSIG_END;
3a3360 ¤   ¤   ctx->depth_at_ann = ctx->scope_depth;
808224 ¤   ¤   /* FALLTHROUGH */
3506fe ¤   case 360:
977577 ¤   ¤   ctx->state = 360;
ea099b ¤   ¤   /* Get a new message part */
3b299b ¤   ¤   ctx->thispart = 1;
0f2571 ¤   ¤   ctx->maxparts = 1;
1c44cd ¤   ¤   msg = getMessage (ctx, NULL, 1);
6aabbf ¤   ¤   if (!msg) {
39566d ¤   ¤   ¤   /* This is an error */
386a8b ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
f3cdcb ¤   ¤   ¤   break;
7c0fe4 ¤   ¤   }
54be7e ¤   ¤   part = getPart (ctx, msg, ctx->thispart);
ca6441 ¤   ¤   if (!part) {
e5c63a ¤   ¤   ¤   /* This is an error too */
dd6a8b ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
45cdcb ¤   ¤   ¤   break;
cb0fe4 ¤   ¤   }
61af5a
74c244 ¤   ¤   /* And set it up as a clearsigned message */
f54a1a ¤   ¤   *error = createClearsig ( myself->cdkContext, ctx, msg, part);
18cf31 ¤   ¤   if (*error)
1bcdcb ¤   ¤   ¤   break;
10af5a
c9ad12 ¤   ¤   ctx->part = part;
ed8224 ¤   ¤   /* FALLTHROUGH */
c0af5a
c21b17 ¤   ¤   /*
87614d ¤   ¤   ·* Below starts the main processing loop for
62e084 ¤   ¤   ·* clearsigned messages. ·It reads in a line. ·If it
f7daf7 ¤   ¤   ·* is a BEGIN line it converts to the signature output
b35192 ¤   ¤   ·* and starts de-armoring the signature. ·Otherwise it
2bb65a ¤   ¤   ·* will output any saved CRLF chars, then output this
aeb6e4 ¤   ¤   ·* new line, saving (but not outputting) the CRLF
515575 ¤   ¤   ·* chars at the end of the line. ·Then the loop
0eb144 ¤   ¤   ·* continues.
--f07a 000eb2bebe140100192 Page 38 of pgpPrsAsc.c
509de3 ¤   ¤   ·*/
28b407 ¤   case 390:
4e7ed6 state_cleartext_body_loop:
5dc78e ¤   ¤   ctx->state = 390;
9516f6 ¤   ¤   /* call readline until we have EOB or EOL */
10af5a
d2e811 ¤   ¤   retval = readLine (ctx, buf, size);
f4d549 ¤   ¤   size -= retval;
77ea46 ¤   ¤   buf += retval;
b249d8 ¤   ¤   written += retval;
a3af5a
874fc6 ¤   ¤   if (ctx->eol || ctx->eob)
69b110 ¤   ¤   ¤   ;
0e0e1d ¤   ¤   else
02cdcb ¤   ¤   ¤   break;
72af5a
c28224 ¤   ¤   /* FALLTHROUGH */
4a8dba ¤   case 395:
adfe33 ¤   ¤   ctx->state = 395;
ceea32 ¤   ¤   /* Send annotation of raw data if in passthrough mode */
9ef5a4 ·¤  ¤   if (ctx->passthrough) {
b11648 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_CLEARDATA,
394c01 ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->armorline, ctx->armorlen);
d023bc ·¤  ¤   ¤   if (*error)
221690 ·¤  ¤   ¤   ¤   break;
1052ed ·¤  ¤   }
7faf5a
908224 ¤   ¤   /* FALLTHROUGH */
eb7db8 ¤   case 400:
e70e31 ¤   ¤   ctx->state = 400;
f84169 ¤   ¤   /*·
52338c ¤   ¤   ·* Check if this is a begin line. ·If so, start
8891b7 ¤   ¤   ·* parsing the signature by jumping to case 9.
e357da ¤   ¤   ·* Otherwise, if the line begins with '- ', move
855673 ¤   ¤   ·* beyond that and fallthrough
489de3 ¤   ¤   ·*/
1faf5a
cb4551 ¤   ¤   lineused = ctx->armorlen;
31384b ¤   ¤   ptr = ctx->armorline;
1f1b52 ¤   ¤
0fd4ad ¤   ¤   while (lineused && isspace (ptr[lineused - 1]))
56e1d9 ¤   ¤   ¤   lineused--;
d51b52 ¤   ¤
e94472 #if MIMEPARSE
6316ab ¤   ¤   if (ctx->mime_signed) {
ba81f9 ¤   ¤   ¤   if (lineused == ctx->mime_bound_len &&
88eeb1 ¤   ¤   ¤   ¤   !memcmp (ptr, ctx->mime_boundary, ctx->mime_bound_len)) {
754594 ¤   ¤   ¤   ¤   /* Done with MIME body part, go look for sig */
1a3777 ¤   ¤   ¤   ¤   goto state_pgpmime_clearsig;
c4a3a6 ¤   ¤   ¤   }
8f45a6 ¤   ¤   } else {
d17454 #endif
6af3f9 ¤   ¤   if (lineused == sizeof (sigprefix) - 1 &&
ec6bf7 ¤   ¤   ····!memcmp (ptr, sigprefix, sizeof (sigprefix) - 1)) {
8de8dc ¤   ¤   ¤   goto state_pgp_begin;
660fe4 ¤   ¤   }
6caf5a
faa561 ¤   ¤   if (!memcmp (ctx->armorline, "- ", 2)) {
fabb34 ¤   ¤   ¤   ctx->armorptr = ctx->armorline + 2;
647101 ¤   ¤   ¤   ctx->armorlen -= 2;
960fe4 ¤   ¤   }
944472 #if MIMEPARSE
ed0fe4 ¤   ¤   }
0f7454 #endif
888224 ¤   ¤   /* FALLTHROUGH */
b66103 ¤   case 410:
7b128a ¤   ¤   ctx->state = 410;
632a94 ¤   ¤   /* output CRLF if we need to */
8daf5a
1073f9 ¤   ¤   while (ctx->saved_crlf) {
65af5a
ebb92b ¤   ¤   ¤   if (ctx->saved_crlf & kPGPLineEnd_CR) {
--4c0b 000558a399740100192 Page 39 of pgpPrsAsc.c
64cb04 ¤   ¤   ¤   ¤   i = writeExtraData (ctx, (PGPByte const *)"\r",
1e45be ¤   ¤   ¤   ¤   ¤   ¤   ····1, error);
44c987 ¤   ¤   ¤   ¤   if (i)
6d5d5b ¤   ¤   ¤   ¤   ¤   ctx->saved_crlf &= ~kPGPLineEnd_CR;
ca43a0 ¤   ¤   ¤   ¤   if (*error)
c314c3 ¤   ¤   ¤   ¤   ¤   break;
eaa3a6 ¤   ¤   ¤   }
58af5a
3f1df2 ¤   ¤   ¤   if (ctx->saved_crlf & kPGPLineEnd_LF) {
3f9f91 ¤   ¤   ¤   ¤   i = writeExtraData (ctx, (PGPByte const *)"\n",
1d45be ¤   ¤   ¤   ¤   ¤   ¤   ····1, error);
52c987 ¤   ¤   ¤   ¤   if (i)
8a0956 ¤   ¤   ¤   ¤   ¤   ctx->saved_crlf &= ~kPGPLineEnd_LF;
d443a0 ¤   ¤   ¤   ¤   if (*error)
4a14c3 ¤   ¤   ¤   ¤   ¤   break;
eda3a6 ¤   ¤   ¤   }
730fe4 ¤   ¤   }
cfaf5a
9a8224 ¤   ¤   /* FALLTHROUGH */
6144ce ¤   case 420:
57f8cc state_cleartext_body_output:
543747 ¤   ¤   ctx->state = 420;
af1b17 ¤   ¤   /*
765233 ¤   ¤   ·* output armorline buffer; do not output crlf until
945427 ¤   ¤   ·* the next line has been shown to not be the
3378a5 ¤   ¤   ·* delimiter.
0b9de3 ¤   ¤   ·*/
4b80d6 ¤   ¤   ptr = ctx->armorptr + ctx->armorlen - 1;
0be107 ¤   ¤   while (*ptr == '\r' || *ptr == '\n') {
e682f3 ¤   ¤   ¤   ptr--;
29ec82 ¤   ¤   ¤   ctx->armorlen--;
f40fe4 ¤   ¤   }
43af5a
7f0356 ¤   ¤   while (ctx->armorlen) {
d8d57e ¤   ¤   ¤   retval = writeExtraData (ctx, ctx->armorptr,
aeadb0 ¤   ¤   ¤   ¤   ¤   ¤   ·ctx->armorlen, error);
9031e5 ¤   ¤   ¤   ctx->armorptr += retval;
b2d68c ¤   ¤   ¤   ctx->armorlen -= retval;
42b5c5 ¤   ¤   ¤   if (*error)
470651 ¤   ¤   ¤   ¤   return written;
fb0fe4 ¤   ¤   }
ccc550 ¤   ¤   ctx->armorptr = ctx->armorline;
b48224 ¤   ¤   /* FALLTHROUGH */
655875 ¤   case 430:
512bfc ¤   ¤   ctx->state = 430;
351b17 ¤   ¤   /*
73fed2 ¤   ¤   ·* if EOL == 1, clear state and goto state body_loop, otherwise
8e71ab ¤   ¤   ·* read data and return to state body_output to output the line.
449de3 ¤   ¤   ·*/
a74743 ¤   ¤   if (ctx->eol == 1) {
e5837b ¤   ¤   ¤   ctx->eol = 0;
b3055a ¤   ¤   ¤   ctx->eob = 0;
e0e450 ¤   ¤   ¤   ctx->saved_crlf = ctx->crlf;
652c44 ¤   ¤   ¤   ctx->crlf = kPGPLineEnd_Default;
4809ac ¤   ¤   ¤   goto state_cleartext_body_loop;
580fe4 ¤   ¤   }
56af5a
3f1853 ¤   ¤   if (!size)
cccdcb ¤   ¤   ¤   break;
90af5a
53e811 ¤   ¤   retval = readLine (ctx, buf, size);
a9d549 ¤   ¤   size -= retval;
00ea46 ¤   ¤   buf += retval;
cc49d8 ¤   ¤   written += retval;
10af5a
3fcee6 ¤   ¤   goto state_cleartext_body_output;
4faf5a
72a838 ¤   ¤   /* BEGIN BINARY MESSAGE HERE */
5d76fc ¤   case 500:
2c3649 state_pgp_binary:
c70575 ¤   ¤   ctx->state = 500;
558354 ¤   ¤   /* Send a new begin annotation */
--4632 000b932e4bf40100192 Page 40 of pgpPrsAsc.c
534789 ¤   ¤   *error = sendAnnotate (ctx, myself, PGPANN_INPUT_BEGIN,
676347 ¤   ¤   ¤   ¤   ·······NULL, 0);
22cf31 ¤   ¤   if (*error)
39cdcb ¤   ¤   ¤   break;
1e6dca ¤   ¤   ctx->annotation = PGPANN_INPUT_END;
ad3360 ¤   ¤   ctx->depth_at_ann = ctx->scope_depth;
a08224 ¤   ¤   /* FALLTHROUGH */
666a47 ¤   case 510:
bd19ce ¤   ¤   ctx->state = 510;
af099b ¤   ¤   /* Get a new message part */
54d8bc ¤   ¤   pgpAssert (!ctx->part);
2b299b ¤   ¤   ctx->thispart = 1;
5e2571 ¤   ¤   ctx->maxparts = 1;
bc44cd ¤   ¤   msg = getMessage (ctx, NULL, 1);
6eabbf ¤   ¤   if (!msg) {
4f566d ¤   ¤   ¤   /* This is an error */
d26a8b ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
7fcdcb ¤   ¤   ¤   break;
de0fe4 ¤   ¤   }
3fbe7e ¤   ¤   part = getPart (ctx, msg, ctx->thispart);
506441 ¤   ¤   if (!part) {
79c63a ¤   ¤   ¤   /* This is an error too */
976a8b ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
2dcdcb ¤   ¤   ¤   break;
4d0fe4 ¤   ¤   }
b0af5a
596566 ¤   ¤   *error = writeMessage (ctx, msg);
2bcf31 ¤   ¤   if (*error)
7bcdcb ¤   ¤   ¤   break;
5aad12 ¤   ¤   ctx->part = part;
568224 ¤   ¤   /* FALLTHROUGH */
d44f8a ¤   case 520:
763c03 ¤   ¤   ctx->state = 520;
34ac4e ¤   ¤   /* Write out data cached in ctx->armorline */
3bf439 ¤   ¤   part = ctx->part;
3b0356 ¤   ¤   while (ctx->armorlen) {
1bf801 ¤   ¤   ¤   retval = writePartData (part, ctx->armorptr,
f4688a ¤   ¤   ¤   ¤   ¤   ¤   ctx->armorlen, error);
a031e5 ¤   ¤   ¤   ctx->armorptr += retval;
35d68c ¤   ¤   ¤   ctx->armorlen -= retval;
bcb5c5 ¤   ¤   ¤   if (*error)
440651 ¤   ¤   ¤   ¤   return written;
1c0fe4 ¤   ¤   }
6dc550 ¤   ¤   ctx->armorptr = ctx->armorline;
0244ce ¤   ¤   ctx->eol = 0;
d8c2ef ¤   ¤   ctx->eob = 0;
320c99 ¤   ¤   ctx->armorlen = 0;
ca8224 ¤   ¤   /* FALLTHROUGH */
b05331 ¤   case 530:
ea20b8 ¤   ¤   ctx->state = 530;
3f1b17 ¤   ¤   /*
e3cdbf ¤   ¤   ·* Check if this scope has ended. ·If so, then close
901767 ¤   ¤   ·* this part by jumping to state pgp_finish
2e9de3 ¤   ¤   ·*/
10c842 ¤   ¤   if (!ctx->annotation) {
aabab7 ¤   ¤   ¤   goto state_pgp_finish;
e50fe4 ¤   ¤   }
32af5a
608216 ¤   ¤   /* Otherwise, write out data from this write call. */
d1f439 ¤   ¤   part = ctx->part;
fd9b02 ¤   ¤   while (size) {
dafc37 ¤   ¤   ¤   retval = writePartData (part, buf, size, error);
6408a7 ¤   ¤   ¤   buf += retval;
90232c ¤   ¤   ¤   size -= retval;
fb5df0 ¤   ¤   ¤   written += retval;
2eb5c5 ¤   ¤   ¤   if (*error)
910651 ¤   ¤   ¤   ¤   return written;
630fe4 ¤   ¤   }
20af5a
a44c5f ¤   ¤   /* Can we get here any way other than not having data? */
bc2f7c ¤   ¤   pgpAssert (!size);
b92f68 ¤   ¤   break;
--a45b 000a82ca20940100192 Page 41 of pgpPrsAsc.c
e0af5a
a84472 #if MIMEPARSE
d56b30 ¤   case 600:
2be2f4 state_pgpmime:
3d18b9 ¤   ¤   ctx->state = 600;
221b17 ¤   ¤   /*
1920aa ¤   ¤   ·* Here on a MIME multipart/signed message. ·Must check protocol
223238 ¤   ¤   ·* and boundary.
2b9de3 ¤   ¤   ·*/
edeb24 ¤   ¤   /* Case sensitive OK? */
783cd0 ¤   ¤   if ((ptr = (PGPByte *)
97bd20 ¤   ¤   ¤   strstr ((char *)ctx->armorline, prefix_mime2)) != NULL) {
4f97b6 ¤   ¤   ¤   /* Have protocol, we know it's ours */
0d0ed9 ¤   ¤   ¤   ctx->mime_signed = 1;
d40fe4 ¤   ¤   }
3faf5a
d3eb24 ¤   ¤   /* Case sensitive OK? */
32909e ¤   ¤   if ((ptr = (PGPByte *)strstr
aa1df4 ¤   ¤   ¤   ((char *)ctx->armorline, prefix_mime3)) != NULL) {
04caf4 ¤   ¤   ¤   /* Get boundary */
49b9cd ¤   ¤   ¤   int need_quote;
41254f ¤   ¤   ¤   ptr += strlen (prefix_mime3);
58b272 ¤   ¤   ¤   need_quote = (*ptr == '"');
7f05f7 ¤   ¤   ¤   if (need_quote)
4d3366 ¤   ¤   ¤   ¤   ++ptr;
066590 ¤   ¤   ¤   ptr2 = (PGPByte *)strchr ((char *)ptr, need_quote?'"':';');
0d6a40 ¤   ¤   ¤   if (!ptr2) {
ddb163 ¤   ¤   ¤   ¤   /* Header too complex for us to parse, rely on heuristic */
64bb76 ¤   ¤   ¤   ¤   ctx->mime_signed = 0;
23aead ¤   ¤   ¤   ¤   ctx->mime_bound_len = 0;
66f366 ¤   ¤   ¤   ¤   goto state_nonpgp;
36a3a6 ¤   ¤   ¤   }
756e53 ¤   ¤   ¤   if (ptr2-ptr+5 > (int)sizeof(ctx->mime_boundary)) {
ae9dd2 ¤   ¤   ¤   ¤   /* Too big boundary, can't handle it */
90f366 ¤   ¤   ¤   ¤   goto state_nonpgp;
68a3a6 ¤   ¤   ¤   }
1fa23a ¤   ¤   ¤   ctx->mime_boundary[0] = '-';
ac8e1d ¤   ¤   ¤   ctx->mime_boundary[1] = '-';
9390c8 ¤   ¤   ¤   strncpy ((char *)ctx->mime_boundary+2, (char *)ptr, ptr2-ptr);
309b1f ¤   ¤   ¤   ctx->mime_bound_len = ptr2 - ptr + 2;
5b80a5 ¤   ¤   ¤   ctx->mime_boundary[ctx->mime_bound_len] = '\0';
440fe4 ¤   ¤   }
a9af5a
d6b177 #if 0
201b17 ¤   ¤   /*
a5e579 ¤   ¤   ·* This micalg finding code may not get used if boundary and proto
4c0759 ¤   ¤   ·* are on a line before the micalg. ·Also won't work with comma
13a1c4 ¤   ¤   ·* separated micalgs.
e74dce ¤   ¤   ·* Need to improve this, however
e45d94 ¤   ¤   ·* it is just a speed optimization to have a micalg anyway.
f39de3 ¤   ¤   ·*/
11384b ¤   ¤   ptr = ctx->armorline;
bddf3b ¤   ¤   while ((ptr = strstr (ctx->armorline, prefix_mime4)) != NULL) {
b79194 ¤   ¤   ¤   /* Have mic_alg */
ffde71 ¤   ¤   ¤   PGPHashVTBL const *h;
f1ebb1 ¤   ¤   ¤   ptr += strlen(prefix_mime4);
a3e066 ¤   ¤   ¤   if (strncmp (ptr, prefix_mime5, strlen(prefix_mime5)) != 0)
0e1322 ¤   ¤   ¤   ¤   continue;¤  ¤   /* Not a PGP hash */
9af70a ¤   ¤   ¤   ptr += strlen(prefix_mime5);
aa5bc4 ¤   ¤   ¤   ptr2 = strchr (ptr, ';');
eb0dcd ¤   ¤   ¤   if (!ptr2)
f4fbc9 ¤   ¤   ¤   ¤   break;¤ ¤   ¤   /* No terminator, ignore it? */
6beffc ¤   ¤   ¤   for (i=0; i<ptr2-ptr; ++i) {
bdb184 ¤   ¤   ¤   ¤   ptr[i] = toupper(ptr[i]);
39a3a6 ¤   ¤   ¤   }
bb05be ¤   ¤   ¤   h = pgpHashByName ((char const *)ptr, ptr2-ptr);
ceebeb ¤   ¤   ¤   if (h) {
a8a419 ¤   ¤   ¤   ¤   ctx->hashlist[ctx->hashlen++] = h->type;
01a3a6 ¤   ¤   ¤   }
d37a0a ¤   ¤   ¤   ptr = ptr2;
f80fe4 ¤   ¤   }
a87454 #endif
--7132 00032073b4e40100192 Page 42 of pgpPrsAsc.c
e0af5a
4e3d38 ¤   ¤   if (ctx->mime_signed && ctx->mime_bound_len) {
88ae95 ¤   ¤   ¤   /* Got the info we need, now go look for first boundary */
4fa9b1 ¤   ¤   ¤   goto state_pgpmime_initial_boundary;
1e0fe4 ¤   ¤   }
4daf5a
fd8224 ¤   ¤   /* FALLTHROUGH */
dd778b ¤   case 610:
430402 ¤   ¤   ctx->state = 610;
ef366e ¤   ¤   /* Read until EOL == 1 to get to the end of the header line */
9ec550 ¤   ¤   ctx->armorptr = ctx->armorline;
220c99 ¤   ¤   ctx->armorlen = 0;
96ccec ¤   ¤   while (ctx->eol != 1) {
3718b1 ¤   ¤   ¤   ctx->armorlen = 0;
55f041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
b75df0 ¤   ¤   ¤   written += retval;
7a08a7 ¤   ¤   ¤   buf += retval;
dc232c ¤   ¤   ¤   size -= retval;
c5af5a
b823ba ¤   ¤   ¤   if (!size)
090651 ¤   ¤   ¤   ¤   return written;
900fe4 ¤   ¤   }
de44ce ¤   ¤   ctx->eol = 0;
afc2ef ¤   ¤   ctx->eob = 0;
f40c99 ¤   ¤   ctx->armorlen = 0;
458224 ¤   ¤   /* FALLTHROUGH */
e05246 ¤   case 620:
c421cf ¤   ¤   ctx->state = 620;
59ea54 ¤   ¤   /* read the line after the begin: call readline until
4acb9c ¤   ¤   ·* we have EOB or EOL */
2aaf5a
ffe811 ¤   ¤   retval = readLine (ctx, buf, size);
73d549 ¤   ¤   size -= retval;
a2ea46 ¤   ¤   buf += retval;
d449d8 ¤   ¤   written += retval;
b5af5a
5e4fc6 ¤   ¤   if (ctx->eol || ctx->eob)
10b110 ¤   ¤   ¤   ;
f60e1d ¤   ¤   else
07cdcb ¤   ¤   ¤   break;
b8af5a
4e8224 ¤   ¤   /* FALLTHROUGH */
574efd ¤   case 630:
7a3d74 ¤   ¤   ctx->state = 630;
931b17 ¤   ¤   /*
e7caef ¤   ¤   ·* See if a continuation of previous header line. ·Must start with
6c9175 ¤   ¤   ·* whitespace followed by non-whitespace.
b79de3 ¤   ¤   ·*/
6ab959 ¤   ¤   if (ctx->armorlen > 1 && isspace (ctx->armorline[0])) {
4fbe6c ¤   ¤   ¤   for (i=1; i< (int)ctx->armorlen; ++i) {
093520 ¤   ¤   ¤   ¤   if (!isspace (ctx->armorline[i])) {
2134a2 ¤   ¤   ¤   ¤   ¤   goto state_pgpmime;
872613 ¤   ¤   ¤   ¤   }
5da3a6 ¤   ¤   ¤   }
170fe4 ¤   ¤   }
021b17 ¤   ¤   /*
f6c2cb ¤   ¤   ·* Here we had a mime-signed header, but not our protocol or boundary.
9d3326 ¤   ¤   ·* Maybe another flavor of mime. ·We will go back to our initial
4907bf ¤   ¤   ·* state. ·This means that we will have eaten one or more header
666d4a ¤   ¤   ·* lines.
009de3 ¤   ¤   ·*/
11630d ¤   ¤   ctx->mime_signed = 0;
7f9628 ¤   ¤   ctx->mime_bound_len = 0;
356b31 ¤   ¤   goto state_nonpgp;
05af5a
ee0567 ¤   case 650:
1f7b83 state_pgpmime_initial_boundary:
d676ee ¤   ¤   ctx->state = 650;
e01b17 ¤   ¤   /*
50b290 ¤   ¤   ·* Here when we have a good PGP/MIME signed header, with boundary.
33fbe1 ¤   ¤   ·* Look for that boundary.
328820 ¤   ¤   ·* Read until EOL == 1 to get to the end of the header line.
--315e 00017fe144d40100192 Page 43 of pgpPrsAsc.c
509de3 ¤   ¤   ·*/
7ec550 ¤   ¤   ctx->armorptr = ctx->armorline;
560c99 ¤   ¤   ctx->armorlen = 0;
65ccec ¤   ¤   while (ctx->eol != 1) {
7b18b1 ¤   ¤   ¤   ctx->armorlen = 0;
f6f041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
ef5df0 ¤   ¤   ¤   written += retval;
3708a7 ¤   ¤   ¤   buf += retval;
62232c ¤   ¤   ¤   size -= retval;
0baf5a
ef23ba ¤   ¤   ¤   if (!size)
990651 ¤   ¤   ¤   ¤   return written;
d20fe4 ¤   ¤   }
7a44ce ¤   ¤   ctx->eol = 0;
26c2ef ¤   ¤   ctx->eob = 0;
b80c99 ¤   ¤   ctx->armorlen = 0;
c08224 ¤   ¤   /* FALLTHROUGH */
4620aa ¤   case 660:
e75323 ¤   ¤   ctx->state = 660;
73ea54 ¤   ¤   /* read the line after the begin: call readline until
67cb9c ¤   ¤   ·* we have EOB or EOL */
beaf5a
a0e811 ¤   ¤   retval = readLine (ctx, buf, size);
6cd549 ¤   ¤   size -= retval;
abea46 ¤   ¤   buf += retval;
a449d8 ¤   ¤   written += retval;
ccaf5a
a94fc6 ¤   ¤   if (ctx->eol || ctx->eob)
9cb110 ¤   ¤   ¤   ;
580e1d ¤   ¤   else
c1cdcb ¤   ¤   ¤   break;
f5af5a
d18224 ¤   ¤   /* FALLTHROUGH */
693c11 ¤   case 670:
124f98 ¤   ¤   ctx->state = 670;
e26376 ¤   ¤   if (ctx->armorlen < (unsigned)ctx->mime_bound_len ||
ad0b37 ¤   ¤   ¤   !ctx->eol ||
8b5fdc ¤   ¤   ···memcmp (ctx->armorline, ctx->mime_boundary, ctx->mime_bound_len)) {
3aea56 ¤   ¤   ¤   /* Not yet at boundary for first part */
77a9b1 ¤   ¤   ¤   goto state_pgpmime_initial_boundary;
f50fe4 ¤   ¤   }
368224 ¤   ¤   /* FALLTHROUGH */
108ee8 ¤   case 680:
81cad1 state_pgpmime_to_cleartext:
7afd61 ¤   ¤   ctx->state = 680;
8a54e8 ·¤  ¤   /* Send end-annotation (if we sent a begin annotation) */
e224b1 ·¤  ¤   if (ctx->annotation) {
480f72 ¤   ¤   ¤   pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
571cf2 ·¤  ¤   ¤   *error = sendAnnotate (ctx, myself, ctx->annotation,
63461e ·¤  ¤   ¤   ¤   ¤   ·······NULL, 0);
6f23bc ·¤  ¤   ¤   if (*error)
061690 ·¤  ¤   ¤   ¤   break;
b0682e ·¤  ¤   ¤   ctx->annotation = 0;
ec52ed ·¤  ¤   }
91fcfe ¤   ¤   /* Here at first boundary, fall into common clearsign code above */
9b9e5d ¤   ¤   goto state_cleartext_body;;
bcaf5a
a16074 ¤   case 700:
50c2a9 state_pgpmime_body_noheaders:
5c13fd ¤   ¤   ctx->state = 700;
c8c719 ¤   ¤   /* Here if we see a "--" line while parsing, may be mime boundary */
8ae8ad ¤   ¤   pgpAssert (ctx->eol);
d214a8 ¤   ¤   strcpy ((char *)ctx->mime_boundary, (char *)ctx->armorline);
bcff74 ¤   ¤   ctx->mime_bound_len = strlen ((char *)ctx->mime_boundary);
408224 ¤   ¤   /* FALLTHROUGH */
467ccf ¤   case 710:
e20f46 ¤   ¤   ctx->state = 710;
9e7653 ¤   ¤   /* read the line after the boundary: call readline until
c6cb9c ¤   ¤   ·* we have EOB or EOL */
caaf5a
71e811 ¤   ¤   retval = readLine (ctx, buf, size);
17d549 ¤   ¤   size -= retval;
--706c 000be3a93ee40100192 Page 44 of pgpPrsAsc.c
7aea46 ¤   ¤   buf += retval;
9149d8 ¤   ¤   written += retval;
eaaf5a
bc4fc6 ¤   ¤   if (ctx->eol || ctx->eob)
c1b110 ¤   ¤   ¤   ;
1d0e1d ¤   ¤   else
70cdcb ¤   ¤   ¤   break;
635902 ¤   case 720:
d62a8b ¤   ¤   ctx->state = 720;
d63670 ¤   ¤   /* MUST be a MIME header, or we are lost */
415a57 ¤   ¤   if (!ctx->eol || ctx->armorlen < 4 || isspace(ctx->armorline[0]) ||
46f022 ¤   ¤   ···!(ptr = (PGPByte *)
70be56 ¤   ¤   ···¤¤   strchr ((char *)ctx->armorline, ':')) || !isspace(ptr[1])) {
487aad ¤   ¤   ¤   /*
70ddba ¤   ¤   ¤   ·* If no good, we go back to our initial state. ·This means we
af903a ¤   ¤   ¤   ·* will have eaten the boundary line.
e48753 ¤   ¤   ¤   ·*/
d77f19 ¤   ¤   ¤   goto state_nonpgp;
b30fe4 ¤   ¤   }
dcaf5a
d3b986 ¤   ¤   /* Valid mime header, go on and begin processing message */
7239d1 ¤   ¤   ctx->mime_signed = 1;
81af5a
ae1b17 ¤   ¤   /*
b11701 ¤   ¤   ·* Fall into common clearsigned code above. ·Flags we have set will
38b0ab ¤   ¤   ·* change its state-leaving behavior.
309de3 ¤   ¤   ·*/
3b53c7 ¤   ¤   goto state_pgpmime_to_cleartext;
ecaf5a
980e23 ¤   case 750:
cb7c91 state_pgpmime_clearsig:
0f7daa ¤   ¤   ctx->state = 750;
5e1b17 ¤   ¤   /*
a4aff1 ¤   ¤   ·* Here when we have seen the boundary at the end of the clearsign.
c8e614 ¤   ¤   ·* Must wait for signed part.
bdb772 ¤   ¤   ·* Read until EOL == 1 to get to the end of the boundary line.
619de3 ¤   ¤   ·*/
f0c550 ¤   ¤   ctx->armorptr = ctx->armorline;
9e0c99 ¤   ¤   ctx->armorlen = 0;
dcccec ¤   ¤   while (ctx->eol != 1) {
6f18b1 ¤   ¤   ¤   ctx->armorlen = 0;
7ef041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
a95df0 ¤   ¤   ¤   written += retval;
e008a7 ¤   ¤   ¤   buf += retval;
30232c ¤   ¤   ¤   size -= retval;
68af5a
8123ba ¤   ¤   ¤   if (!size)
550651 ¤   ¤   ¤   ¤   return written;
620fe4 ¤   ¤   }
3244ce ¤   ¤   ctx->eol = 0;
30c2ef ¤   ¤   ctx->eob = 0;
260c99 ¤   ¤   ctx->armorlen = 0;
2b8224 ¤   ¤   /* FALLTHROUGH */
8b2bee ¤   case 760:
ee5867 ¤   ¤   ctx->state = 760;
db6633 ¤   ¤   /* read the next line: call readline until
8dcb9c ¤   ¤   ·* we have EOB or EOL */
b0af5a
b0e811 ¤   ¤   retval = readLine (ctx, buf, size);
aed549 ¤   ¤   size -= retval;
8dea46 ¤   ¤   buf += retval;
a649d8 ¤   ¤   written += retval;
ffaf5a
f94fc6 ¤   ¤   if (ctx->eol || ctx->eob)
15b110 ¤   ¤   ¤   ;
8c0e1d ¤   ¤   else
9ccdcb ¤   ¤   ¤   break;
ddaf5a
e48224 ¤   ¤   /* FALLTHROUGH */
4b3755 ¤   case 770:
fd44dc ¤   ¤   ctx->state = 770;
be06c8 ¤   ¤   /* See if have BEGIN PGP SIGNATURE line, if so go process it */
--98a3 0001fd0e9e440100192 Page 45 of pgpPrsAsc.c
17b57e ¤   ¤   if ((ctx->armorlen > sizeof (sigprefix) - 1 &&
75dd46 ¤   ¤   ····!memcmp (ctx->armorline, sigprefix, sizeof (sigprefix) - 1)) ||
d6ead7 ¤   ¤   ¤   (ctx->armorlen > sizeof (prefix_mimesig2) - 1 &&
dd8b2e ¤   ¤   ····!memcmp (ctx->armorline, prefix_mimesig2,
9e0835 ¤   ¤   ¤   ¤   ¤   ·sizeof (prefix_mimesig2) - 1))) {
17a063 ¤   ¤   ¤   /* Have BEGIN line for signature */
36e8dc ¤   ¤   ¤   goto state_pgp_begin;
360fe4 ¤   ¤   }
ecaf5a
449254 ¤   ¤   /* Else loop back */
ff3422 ¤   ¤   goto state_pgpmime_clearsig;
e2af5a
ca0a88 ¤   case 800:
b0ae78 state_pgpmime_sig_end:
027901 ¤   ¤   ctx->state = 800;
ac1b17 ¤   ¤   /*
c4d2db ¤   ¤   ·* Here after -----END PGP MESSAGE----- in a mime signed message.
fdfed5 ¤   ¤   ·* Look for terminal boundary line.
2e54ac ¤   ¤   ·*
458820 ¤   ¤   ·* Read until EOL == 1 to get to the end of the header line.
ddd081 ¤   ¤   ·* Append two '-' chars to boundary to look like final boundary
649de3 ¤   ¤   ·*/
452bee ¤   ¤   ctx->mime_boundary [ctx->mime_bound_len++] = '-';
532bee ¤   ¤   ctx->mime_boundary [ctx->mime_bound_len++] = '-';
1ef3be ¤   ¤   ctx->mime_boundary [ctx->mime_bound_len] = '\0';
288224 ¤   ¤   /* FALLTHROUGH */
cb1633 ¤   case 810:
2e0cc3 state_pgpmime_sig_end_loop:
fb65ba ¤   ¤   ctx->state = 810;
159dd2 ¤   ¤   /* Read till end of previous line */
7ec550 ¤   ¤   ctx->armorptr = ctx->armorline;
a90c99 ¤   ¤   ctx->armorlen = 0;
26ccec ¤   ¤   while (ctx->eol != 1) {
e618b1 ¤   ¤   ¤   ctx->armorlen = 0;
24f041 ¤   ¤   ¤   retval = readLine (ctx, buf, size);
cb5df0 ¤   ¤   ¤   written += retval;
3808a7 ¤   ¤   ¤   buf += retval;
f5232c ¤   ¤   ¤   size -= retval;
24af5a
b123ba ¤   ¤   ¤   if (!size)
730651 ¤   ¤   ¤   ¤   return written;
0f0fe4 ¤   ¤   }
2844ce ¤   ¤   ctx->eol = 0;
12c2ef ¤   ¤   ctx->eob = 0;
6e0c99 ¤   ¤   ctx->armorlen = 0;
be8224 ¤   ¤   /* FALLTHROUGH */
b033fe ¤   case 820:
d74077 ¤   ¤   ctx->state = 820;
ecea54 ¤   ¤   /* read the line after the begin: call readline until
57cb9c ¤   ¤   ·* we have EOB or EOL */
7daf5a
96e811 ¤   ¤   retval = readLine (ctx, buf, size);
dcd549 ¤   ¤   size -= retval;
1cea46 ¤   ¤   buf += retval;
3c49d8 ¤   ¤   written += retval;
1baf5a
0c4fc6 ¤   ¤   if (ctx->eol || ctx->eob)
1db110 ¤   ¤   ¤   ;
050e1d ¤   ¤   else
83cdcb ¤   ¤   ¤   break;
14af5a
3f8224 ¤   ¤   /* FALLTHROUGH */
f32f45 ¤   case 830:
a15ccc ¤   ¤   ctx->state = 830;
854c83 ¤   ¤   /* Check for final boundary */
4aff56 ¤   ¤   if (ctx->eol && ctx->armorlen >= (unsigned)ctx->mime_bound_len &&
c3b93c ¤   ¤   ··!memcmp (ctx->armorline, ctx->mime_boundary, ctx->mime_bound_len)) {
828050 ¤   ¤   ¤   /* Clean up mime flags, go to clean-up state */
b75405 ¤   ¤   ¤   ctx->mime_signed = 0;
2cab40 ¤   ¤   ¤   ctx->mime_bound_len = 0;
7abab7 ¤   ¤   ¤   goto state_pgp_finish;
1f0fe4 ¤   ¤   }
--0d15 000c90fc8a940100192 Page 46 of pgpPrsAsc.c
f11b52 ¤   ¤
56bda6 ¤   ¤   /* Keep looping until we see it */
0a95d5 ¤   ¤   goto state_pgpmime_sig_end_loop;
4aaf5a
e17454 #endif
8faf5a
9e2f72 ¤   default:
fe9383 ¤   ¤   /* Every state should be enumerated above */
c19132 ¤   ¤   pgpAssert (0);
7b9371 ¤   }
02af5a
01279e ¤   return written;
d0efe6 }
daaf5a
9cf1ae static PGPError
cdd02e Flush (PGPPipeline *myself)
0bbb36 {
2375f4 ¤   PrsAscContext *context;
f35b01 ¤   PGPError¤   error = kPGPError_NoErr;
a1af5a
7129be ¤   pgpAssert (myself);
998b61 ¤   pgpAssert (myself->magic == DEARMORMAGIC);
43af5a
24f93c ¤   context = (PrsAscContext *)myself->priv;
41d30a ¤   pgpAssert (context);
1bebf4 ¤   pgpAssert (context->tail);
42af5a
67a921 ¤   (void) Write (myself, NULL, 0, &error);
f40161 ¤   if (error)
a0fcee ¤   ¤   return error;
c0af5a
559819 ¤   return context->tail->flush (context->tail);
f4efe6 }
a0af5a
63f1ae static PGPError
cc4b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
7bbb36 {
de75f4 ¤   PrsAscContext *context;
d75b01 ¤   PGPError¤   error = kPGPError_NoErr;
70af5a
ce29be ¤   pgpAssert (myself);
868b61 ¤   pgpAssert (myself->magic == DEARMORMAGIC);
36af5a
18f93c ¤   context = (PrsAscContext *)myself->priv;
17d30a ¤   pgpAssert (context);
60ebf4 ¤   pgpAssert (context->tail);
55af5a
2e56b6 ¤   if (bytes)
63a117 ¤   ¤   return( kPGPError_NoErr );
9caf5a
c81acd ¤   /* There are no more bytes. ·Therefore this is the EOL. */
1ea805 ¤   context->eol = 1;
11af5a
36877b ¤   /* Call write to purge out anything we might have buffered. */
18a921 ¤   (void) Write (myself, NULL, 0, &error);
1c0161 ¤   if (error)
fffcee ¤   ¤   return error;
31af5a
875a3b ¤   if (context->part) {
3a1b17 ¤   ¤   /*
01b444 ¤   ¤   ·* If we have a part, end it, flush the current
6ea2bd ¤   ¤   ·* message, and reset the context state.
1c9de3 ¤   ¤   ·*/
1aaf5a
451b17 ¤   ¤   /*
316f65 ¤   ¤   ·* Check if this is a clearsigned message that is
c88613 ¤   ¤   ·* incomplete. ·If it is, kill it now!
119de3 ¤   ¤   ·*/
69016d ¤   ¤   if (context->part->sig && !context->part->msg->foundpart1)
ae77c6 ¤   ¤   ¤   (void)0;
691b52 ¤   ¤
c911f9 ¤   ¤   /* Set to finish state */
--b0dd 0002d1f030140100192 Page 47 of pgpPrsAsc.c
323f7c ¤   ¤   context->state = 260;
3ab171 ¤   ¤   (void) Write (myself, NULL, 0, &error);
31e3c2 ¤   ¤   if (error)
6d3b5b ¤   ¤   ¤   return error;
a39371 ¤   }
b3af5a
add8af ¤   /*
781d91 ¤   ·* If we have data buffered at this point, we return an error
cd2ebe ¤   ·* code to let the caller know that. ·If we miss a part of a
46a193 ¤   ·* multipart message, this will be the case. ·The user will
9757f7 ¤   ·* receive the error message and can then send annotations to
9a9806 ¤   ·* figure out what is missing and possible send it or at least
49d005 ¤   ·* inform the user.
199714 ¤   ·*
c3a648 ¤   ·* This keeps the data consisent and doesn't propagate a
6f3a24 ¤   ·* sizeAdvise() in the wrong scope.
a1a4e3 ¤   ·*/
abaf5a
decc58 ¤   if (context->scope_depth)
1ba117 ¤   ¤   return( kPGPError_NoErr );
2eaf5a
7a6f1e ¤   if (context->msgs)
c32164 ¤   ¤   return kPGPError_AsciiParseIncomplete;
8faf5a
355f12 ¤   /* Bytes is zero */
f4c78b ¤   return context->tail->sizeAdvise (context->tail, bytes);·
9aefe6 }
03af5a
df0f64 static Message *
c5a96b getMessageNumber (PrsAscContext *ctx, int num)
afbb36 {
f95b16 ¤   Message *msg;
c2af5a
ca5988 ¤   msg = ctx->msgs;
6d1151 ¤   while (msg) {
508282 ¤   ¤   if (msg->msg_number == num)
c3499c ¤   ¤   ¤   return msg;
f27235 ¤   ¤   msg = msg->next;
3e9371 ¤   }
e43f59 ¤   return NULL;
f5efe6 }
13af5a
21beb7 static int
1589f4 sendStatus (PGPPipeline *myself, int type, PGPByte const *string,
86455e ¤   ····size_t size)
79bb36 {
b14b85 ¤   PrsAscContext *ctx = (PrsAscContext *)myself->priv;
d05b16 ¤   Message *msg;
24852c ¤   MsgPart *part;
2110db ¤   int count;
bdaf5a
802308 ¤   (void)size;¤¤   /* Avoid warning */
221609 ¤   switch (type) {
c38e19 ¤   case PGPANN_PARSEASC_MSG_COUNT:
2e2844 ¤   ¤   return ctx->msg_count;
6dee44 ¤   case PGPANN_PARSEASC_MSG_LEFT:
33e859 ¤   ¤   msg = ctx->msgs;
addabf ¤   ¤   count = 0;
5e2bcb ¤   ¤   while (msg) {
82ae59 ¤   ¤   ¤   count++;
a44668 ¤   ¤   ¤   msg = msg->next;
200fe4 ¤   ¤   }
1729f2 ¤   ¤   return count;
a606d5 ¤   case PGPANN_PARSEASC_MSG_CURRENT:
120ebf ¤   ¤   /* Return the pointer to the currently writing message */
34e859 ¤   ¤   msg = ctx->msgs;
302bcb ¤   ¤   while (msg) {
1ea2f8 ¤   ¤   ¤   if (msg->writing)
9df622 ¤   ¤   ¤   ¤   break;
924668 ¤   ¤   ¤   msg = msg->next;
110fe4 ¤   ¤   }
2defb8 ¤   ¤   if (msg)
--a6b1 000d2271ed840100192 Page 48 of pgpPrsAsc.c
786975 ¤   ¤   ¤   return msg->msg_number;
e6bbde ¤   ¤   return 0;
3a09ca ¤   case PGPANN_PARSEASC_MSG_PARTS:
c599ea ¤   ¤   /* Return the number of parts in the message */
b9ed70 ¤   ¤   pgpAssert (size == sizeof (int));
2bcc59 ¤   ¤   msg = getMessageNumber (ctx, ((int *) string)[0]);
83ded0 ¤   ¤   if (!msg)
2f8144 ¤   ¤   ¤   return 0;
afeee1 ¤   ¤   return msg->size;
49d41f ¤   case PGPANN_PARSEASC_MSG_PARTINFO:
a95462 ¤   ¤   /* Return information about part M of message N */
2976f2 ¤   ¤   pgpAssert (size == (2 * sizeof (int)));
85cc59 ¤   ¤   msg = getMessageNumber (ctx, ((int *) string)[0]);
ceded0 ¤   ¤   if (!msg)
248144 ¤   ¤   ¤   return 0;
635de6 ¤   ¤   count = ((int *) string)[1];
93be6b ¤   ¤   part = msg->parts;
705162 ¤   ¤   while (part) {
ad4737 ¤   ¤   ¤   if (part->num == (unsigned)count)
b52dc6 ¤   ¤   ¤   ¤   return (part->done ? 1 : 2);
db077f ¤   ¤   ¤   if (part->num > (unsigned)count)
af1c2d ¤   ¤   ¤   ¤   return 1;
deb8b1 ¤   ¤   ¤   part = part->next;
f30fe4 ¤   ¤   }
0b2370 ¤   ¤   pgpAssert (!part);
b00e66 ¤   ¤   return 2;
079371 ¤   }
a63e6b ¤   return 0;
c5efe6 }
0caf5a
abd62d /* Send an annotation */
02f1ae static PGPError
3a22cf sendAnnotate (PrsAscContext *ctx, PGPPipeline *origin, int type,
d8b533 ¤   ······PGPByte const *string, size_t size)
afbb36 {
5f1728 ¤   pgpAssert (ctx->tail);
b6af5a
1ec60e ¤   /* Buffer annotation if buffering flag is true, except we will pass
121d29 ¤   ·* CLEARDATA through if we are writing this part.
99a4e3 ¤   ·*/
3e173a ¤   if (ctx->buffering && ((type != PGPANN_CLEARDATA) ||
6e41a7 ¤   ¤   ¤   ¤   ¤   ¤   ···(ctx->part == NULL) ||
2303c9 ¤   ¤   ¤   ¤   ¤   ¤   ···!ctx->part->msg->writing))
8a4a69 ¤   ¤   return bufferAnnotation (ctx, origin, type, string, size);
8caf5a
ea4e2e ¤   return ctx->tail->annotate (ctx->tail, origin, type, string, size);
2eefe6 }
8faf5a
89f1ae static PGPError
ba13c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
0db0b1 ¤   ··PGPByte const *string, size_t size)
24bb36 {
eb75f4 ¤   PrsAscContext *context;
b187a6 ¤   PGPError¤   error;
bcaf5a
0829be ¤   pgpAssert (myself);
598b61 ¤   pgpAssert (myself->magic == DEARMORMAGIC);
0eaf5a
7af93c ¤   context = (PrsAscContext *)myself->priv;
74d30a ¤   pgpAssert (context);
c4ebf4 ¤   pgpAssert (context->tail);
bfaf5a
d31609 ¤   switch (type) {
bb8e19 ¤   case PGPANN_PARSEASC_MSG_COUNT:
b7ee44 ¤   case PGPANN_PARSEASC_MSG_LEFT:
0d06d5 ¤   case PGPANN_PARSEASC_MSG_CURRENT:
1309ca ¤   case PGPANN_PARSEASC_MSG_PARTS:
0bd41f ¤   case PGPANN_PARSEASC_MSG_PARTINFO:
c1b87e ¤   ¤   return (PGPError)sendStatus (myself, type, string, size);
c1e4be ¤   /* Enable/disable passthrough modes */
2de500 ¤   case PGPANN_PASSTHROUGH_CLEARSIGN:
d29cbd ¤   ¤   context->passthroughcleartext = *(PGPBoolean *)string;
--3a4f 000a0effc3f40100192 Page 49 of pgpPrsAsc.c
4f2f68 ¤   ¤   break;
cb0c54 ¤   case PGPANN_PASSTHROUGH_KEYS:
6ec591 ¤   ¤   context->passthroughkey = *(PGPBoolean *)string;
a62f68 ¤   ¤   break;
469371 ¤   }
aaaf5a
3b68b9 ¤   if (PGP_IS_END_SCOPE (type) && context->annotation &&
c8302b ¤   ····context->scope_depth == context->depth_at_ann) {
773bdf ¤   ¤   error = sendAnnotate (context, myself, context->annotation,
7184ac ¤   ¤   ¤   ¤   ······NULL, 0);
bce3c2 ¤   ¤   if (error)
673b5b ¤   ¤   ¤   return error;
c991a5 ¤   ¤   context->annotation = 0;
d89371 ¤   }
1caf5a
5063d2 ¤   error = sendAnnotate (context, origin, type, string, size);
54ff2e ¤   if (!error)
c1c545 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE (context->scope_depth, type);
ea04c8 ¤   pgpAssert(context->scope_depth != -1);
98c674 ¤   return error;
1fefe6 }
1daf5a
13f1ae static PGPError
2ec7e1 Teardown (PGPPipeline *myself)
b0bb36 {
6075f4 ¤   PrsAscContext *context;
97b168 ¤   Message *msg, *temp;
cde9fa ¤   PGPContextRef¤  cdkContext;
2167c5 ¤
b43982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
52696e ¤   cdkContext¤ = myself->cdkContext;
e9af5a
d429be ¤   pgpAssert (myself);
258b61 ¤   pgpAssert (myself->magic == DEARMORMAGIC);
3faf5a
b1f93c ¤   context = (PrsAscContext *)myself->priv;
80d30a ¤   pgpAssert (context);
feaf5a
278436 ¤   for (msg = context->msgs; msg; msg = temp) {
6c4a24 ¤   ¤   temp = msg->next;
2f263a ¤   ¤   freeMessage (context, msg);
949371 ¤   }
c6af5a
55cb05 ¤   if (context->tail)
061e8a ¤   ¤   context->tail->teardown (context->tail);
2caf5a
8c63c1 ¤   pgpFifoDestroy (context->fifod, context->data);
84e081 ¤   pgpFifoDestroy (context->fifod, context->ann);
62af5a
5d3736 ¤   pgpClearMemory( context, ·sizeof (*context));
fbfa6e ¤   pgpContextMemFree( cdkContext, context);
7867c5 ¤
13151e ¤   return kPGPError_NoErr;
19efe6 }
37af5a
ada36e ¤   PGPPipeline **
72731d pgpParseAscCreate ·(
1258f9 ¤   PGPContextRef¤  ¤   cdkContext,
7a0d82 ¤   PGPPipeline **¤ ¤   head,
4214ad ¤   PGPEnv const *¤ ¤   env,
38f138 ¤   PGPFifoDesc const *¤fd,
4c0e11 ¤   PGPUICb const *¤¤   ui,
eb0ece ¤   void *¤ ¤   ¤   ¤   ui_arg)
8fbb36 {
3e0df0 ¤   PGPPipeline *mod;
4875f4 ¤   PrsAscContext *context;
51168d ¤   PGPFifoContext *data, *ann;
ebaf5a
d892bd ¤   if (!head || !env)
707ed2 ¤   ¤   return NULL;
f2af5a
a02ef8 ¤   parseAscInit ();
--911f 00134c34bca40100192 Page 50 of pgpPrsAsc.c
e0af5a
e7f538 ¤   context = (PrsAscContext *)pgpContextMemAlloc( cdkContext,
31d680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
f81ea4 ¤   if (!context)
047ed2 ¤   ¤   return NULL;
3067c5 ¤
8a9228 ¤   mod = &context->pipe;
7ea99e ¤   mod->cdkContext¤= cdkContext;
8467c5 ¤
ce5500 ¤   data = pgpFifoCreate (cdkContext, fd);
6be282 ¤   if (!data) {
24a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
a17ed2 ¤   ¤   return NULL;
e09371 ¤   }
a9175a ¤   ann = pgpFifoCreate (cdkContext, fd);
eeab5d ¤   if (!ann) {
424fb2 ¤   ¤   pgpFifoDestroy (fd, data);
bea8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
fc7ed2 ¤   ¤   return NULL;
939371 ¤   }
36af5a
8efe79 ¤   mod->magic = DEARMORMAGIC;
ad1f83 ¤   mod->write = Write;
4eac4e ¤   mod->flush = Flush;
920aaf ¤   mod->sizeAdvise = SizeAdvise;
2ad3a2 ¤   mod->annotate = Annotate;
f996de ¤   mod->teardown = Teardown;
7b9439 ¤   mod->name = "Ascii Armor Parser Module";
5e01ea ¤   mod->priv = context;
75a99e ¤   mod->cdkContext¤= cdkContext;
cfaf5a
6dae49 ¤   context->fifod = fd;
1a375d ¤   context->data = data;
06eb2d ¤   context->ann = ann;
7d12f7 ¤   context->dataptr = context->databuf;
d0d400 ¤   context->armorptr = context->armorline;
7e3c31 ¤   context->myself = mod;
a65b61 ¤   context->env = env;
7a7d87 ¤   context->ui = ui;
a2f47a ¤   context->ui_arg = ui_arg;
b84472 #if MIMEPARSE
560689 ¤   context->no_mime_headers = pgpenvGetInt (env, PGPENV_PGPMIMEPARSEBODY,
d33270 ¤   ¤   ¤   NULL, NULL);
2a7454 #endif
03af5a
d665ad ¤   context->tail = *head;
dd2d11 ¤   *head = mod;
f57fa2 ¤   return &context->tail;
34efe6 }
--b0b4 001c1f682f240100193 Page 1 of pgpPrsAsc.h
bc38e5 /*
51459b ·* pgpPrsAsc.h -- An Ascii Armor Parser for PGP.
ff775e ·*
4b7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
30775e ·*
593c65 ·* $Id: pgpPrsAsc.h,v 1.8 1997/06/25 19:40:06 lloyd Exp $
d6495d ·*/
eaaf5a
0612fe #ifndef Included_pgpPrsAsc_h
bf93c8 #define Included_pgpPrsAsc_h
92af5a
77d11f #include "pgpUsuals.h"
a7af5a
c999c6 PGP_BEGIN_C_DECLARATIONS
acaf5a
12adb8 #include "pgpOpaqueStructs.h"
1ee82c #include "pgpPubTypes.h"
61af5a
8eb389 PGPPipeline ·**pgpParseAscCreate ( PGPContextRef cdkContext,
b65986 ¤   ¤   ¤   ¤   PGPPipeline **head,
dd4c12 ¤   ¤   ¤   ¤   PGPEnv const *env,
b925bd ¤   ¤   ¤   ¤   PGPFifoDesc const *fd,
4de525 ¤   ¤   ¤   ¤   PGPUICb const *ui,
e6c6a1 ¤   ¤   ¤   ¤   void *ui_arg);
0daf5a
fe1254 PGP_END_C_DECLARATIONS
feaf5a
c17e6b #endif /* Included_pgpPrsAsc_h */
--389f 0018e5da00740100194 Page 1 of pgpRadix64.c
bc38e5 /*
6264c0 ·* radix.c -- Define the armor Table for 6-bit integer to character
46af30 ·* conversion.
aa775e ·*
336023 ·* $Id: pgpRadix64.c,v 1.2 1997/05/02 22:45:25 lloyd Exp $
f3495d ·*/
b4af5a
d1e2ff #include "pgpConfig.h"
24af5a
890301 #include "pgpRadix64.h"
f9af5a
000a92 /* This is are table of 6-bit value -> character */
538a35 char const armorTable[65] =
8e6cd3 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
--6e94 001a03449a140100195 Page 1 of pgpRadix64.h
bc38e5 /*
180746 ·* pgpRadix64.h -- The header for Radix64 encoding,
9ae3fb ·*¤ ¤   ···which is used by ASCII Armor.
0f775e ·*
c1e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
592979 ·* You should not be using these functions in an application.
58775e ·*
9ecd74 ·* $Id: pgpRadix64.h,v 1.4 1997/05/13 01:19:01 mhw Exp $
5a495d ·*/
13af5a
45c1d1 #ifndef Included_pgpRadix64_h
c695e5 #define Included_pgpRadix64_h
7aaf5a
68c5d5 #include "pgpBase.h"
74af5a
e999c6 PGP_BEGIN_C_DECLARATIONS
f7af5a
f0e589 extern char const armorTable[65];
99af5a
8a1254 PGP_END_C_DECLARATIONS
12af5a
a0d51b #endif /* Included_pgpRadix64_h */
--719b 001dca2f42640100196 Page 1 of Makefile.in
5ea601 #
1a5975 # priv/crypto/pipe/parser/
97a601 #
f9e88a # $Id: Makefile.in,v 1.2 1997/05/04 10:30:10 mhw Exp $
43a601 #
dcaf5a
e9ff5b OBJS=¤  pgpPrsBin.o pgpReadAnn.o pgpVerifyRa.o pgpVrfySig.o
22acf2 PRIVHDRS= pgpPrsBin.h pgpReadAnn.h pgpVerifyRa.h
e0af5a
74b7a3 all:: DONE
dcaf5a
--ad4e 00010ddac1f40100197 Page 1 of pgpPrsBin.c
bc38e5 /*
37ebc4 ·* pgpPrsBin.c -- Binary Parser
bb775e ·*
fd9f38 ·* Written by:¤ Colin Plumb and Derek Atkins <warlord@MIT.EDU>
c9775e ·*
ed8d5b ·* $Id: pgpPrsBin.c,v 1.56.2.1 1998/10/21 05:59:27 heller Exp $
2a495d ·*/
6be2ff #include "pgpConfig.h"
acaf5a
3cfeb2 #include <stdio.h>
90324c #include <string.h>
7aaf5a
11a146 #include "pgpDebug.h"
149c38 #include "pgpPktByte.h"
9bb512 #include "pgpPrsAsc.h"
990ab6 #include "pgpPrsBin.h"
0f6aaa #include "pgpAnnotate.h"
251e2d #include "pgpCFBPriv.h"
c80e2f #include "pgpSymmetricCipherPriv.h"
c5d9c5 #include "pgpCiphrMod.h"
5bc19b #include "pgpCompress.h"
6d55fb #include "pgpCompMod.h"
a68b0d #include "pgpEncodePriv.h"
51910a #include "pgpFIFO.h"
925417 #include "pgpHashPriv.h"
91c49c #include "pgpHashMod.h"
673e66 #include "pgpHeader.h"
9c0d08 #include "pgpMem.h"
280d6d #include "pgpEnv.h"
fc2f8d #include "pgpErrors.h"
d02ece #include "pgpPipeline.h"
9443bc #include "pgpSig.h"
a83576 #include "pgpTextFilt.h"
53d11f #include "pgpUsuals.h"
60c26c #include "pgpContext.h"
f1af5a
d24eb4 #define PARSERMAGIC¤0xfeedf00d
6eaf5a
25c2c4 /* Only accept this much data per call to parsePacket */
e7836b #define PARSER_SIZE_LIMIT¤  512
48af5a
9e38e5 /*
8b4e94 ·* There are two formats for PGP packets. ·Both are equivalent as far as
8ab3f4 ·* the rest of the code is concerned.
522616 ·* The original PGP packet format:
4aa29d ·* - Packet byte: 10ttttll, where tttt = packet type, and ll = length of length
9a764e ·* - Length field, 1/2/4/0 bytes, big-endian, based on ll bits
8467ac ·* - Body
e045ad ·* This format is simple and small, but requires knowing the size of the
2b9a07 ·* enclosed data before you can emit the length field.
08775e ·*
1d5f92 ·* The one-pass PGP 3 format:
29bc7a ·* - Packet byte 11tttttt, where tttttt = packet type
521527 ·* - Zero or more non-final subpackets, starting with a byte of the form
2c82e0 ·* ··111sssss, followed by 2^s bytes of data
392ede ·* - A final subpacket, which starts with either 0sssssss, 10sssssss,
874fcc ·* ··or 110sssss ssssssss, holding up to 2^7 + 2^6 + 2^13 - 1 bytes.
c2675c ·* ··(The formats encode lengths of 0-127, 128-191, and 192-8383 bytes.)
ac775e ·*
f2d472 ·* Generally, a PGP implementation will emit non-final subpackets in the
d78037 ·* 1K to 8K range, followed by one final subpacket. ·However, any size
38e929 ·* may be used, down to one byte. ·This flexibility allows data to be
1570e1 ·* flushed out and a stream to be brought up to date at any byte boundary
6d5f41 ·* by emitting a combination of non-final subpackets which sum to the
e1a0d4 ·* desired boundary.
b6775e ·*
063b10 ·* To keep track of both of these formats, there is a Header,
bc0501 ·* which describes the parsing state of the current subpacket header on
808079 ·* an arbitrary byte boundary. ·It has three members:
01459c ·* lenbytes - the count of the number of bytes remaining in the
e7c1bd ·* ···········current big-endian subpacket size. ·This may be as large
10d2de ·* ···········as 4. ·As additional bytes are read, lenbytes is decremented
--ab63 0007db0196a40100197 Page 2 of pgpPrsBin.c
8286db ·* ···········and "pktlen" is increased with the appropriately shifted
264a9b ·* ···········byte.
271a68 ·* more - a flag which is true if the current subpacket is non-terminal,
efe359 ·* ·······so another subpacket is expected.
400a7f ·* pktlen - the length of the current subpacket. ·If lenbytes is non-zero,
eb3f2b ·* ·········the value here is an underestimate. ·When this is 0, a new
81e563 ·* ·········packet or subpacket (depending on the more flag) is expected.
2e9ec0 ·*·
af3d62 ·* To keep track of the state of the input stream, a Header structure is
221364 ·* used, but data that has already been read from the Header structure
186ff5 ·* is kept around as well. ·There are two data structures for this:
4ce1c5 ·* - The FIFO contains a copy of the raw input data up to the point
0d72c4 ·* ··marked by "passptr".
16e1ee ·* - The buffer, which also holds a prefix of the input data, but a
aa9deb ·* ··parsed version. ·A portion of the two overlap, and what can be
a96fca ·* ··kept in the buffer, is. ·This always includes the tail of the last
063c97 ·* ··subpacket that has been read. ·If this is also the first subpacket,
53cf58 ·* ··nothing actually needs to get copied to the FIFO at all.
e4775e ·*
3a8ec2 ·* The buffer ends up looking like this:
31775e ·*
0ff97c ·* /------------------------ passptr - First byte not passed through to FIFO.
56c8a0 ·* |
4235d0 ·* v
6dd0ab ·* +------------------------------------+
68c302 ·* | ···································|
4fd0ab ·* +------------------------------------+
c8fc19 ·* ····^ ··········^
94b4f1 ·* ····| ··········|
b678bb ·* ····| ··········\--------- bufend - End of packet header/start of read-ahead
8b7d81 ·* ····\--------------------- bufptr - Beginning of intra-packet header
979ec0 ·*·
91e2fe ·* It works like this: The data from the FIFO, plus passptr through bufend,
ddc693 ·* is the raw data that's been processed. ·Passptr is usually before
f75ee2 ·* bufptr, with the gap filled by the packet's external header
86757a ·* (packet header byte plus length or first subpacket header), and
310196 ·* then bufptr through bufend is shared between the two.
a9775e ·*
af32c4 ·* If the amount of header data needed exceeds the size of the first
4fec78 ·* subpacket, then the data up to and including the second subpacket
3c5dbe ·* header is copied to the FIFO, and as much of the second subpacket as
cae196 ·* is needed is read into the buffer immediately following the first
b84d13 ·* subpacket, with no intervening subpacket header, and "passptr" is
fdb138 ·* set to point to the beginning of the second subpacket data.
86775e ·*
a39733 ·* The data between bufend and readptr is, however, raw input data
36dec3 ·* including subpacket headers that have not yet been parsed.
dc495d ·*/
51af5a
2eac1e /* Size of buffer - must hold a whole ESK or SIG packet */
591787 /* 4096 bit ElGamal ESK's will be a bit over 1024 bytes */
c1a6f6 /* Some X.509 sigs can be several times this */
e31810 /* However this is OK, they are only in keyring and get passed through */
0c33d7 #define MAXPKTSIZE¤ ¤   1100
b7af5a
5baf5a
f2fe60 static size_t nextScope (PGPPipeline *myself, PGPByte const *buf,
08fdce ¤   ¤   ¤   ·size_t size, PGPError *error);
bed7fe static size_t nextESK (PGPPipeline *myself, PGPByte const *buf,
d30298 ¤   ¤   ·······size_t size, PGPError *error);
14599f static size_t parsePacket (PGPPipeline *myself, PGPByte const *buf,
ab0ef8 ¤   ¤   ¤   ···size_t size, PGPError *error);
a4db75 static size_t parseKey (PGPPipeline *myself, PGPByte const *buf,
8f049d ¤   ¤   ¤   size_t size, PGPError *error);
d5af5a
db75de /* Used to recognize the beginning of a recursive literal packet */
acf963 static char const pgp_message_begin[] = "-----BEGIN PGP ";
1aaf5a
adaf5a
5a4f7e /* Information needed to parse a subpacket header */
7adc67 typedef struct Header {
7d077f ¤   PGPUInt32 pktlen;¤  ¤   /* Length of current subpacket */
--1365 0004b0a332540100197 Page 3 of pgpPrsBin.c
7695ba ¤   unsigned lenbytes;¤ /* Number of length bytes to come */
66d2b2 ¤   PGPByte more;¤  ¤   /* More subpackets to come */
2601e6 } Header;
3baf5a
6f96e2 /* Information needed to parse a data stream */
9c08c2 typedef struct Input {
daf929 ¤   PGPByte buffer[MAXPKTSIZE];¤/* Buffer of parsed data */
30dbf0 ¤   PGPFifoContext *fifo;¤  /* FIFO of raw data */
53ae9c ¤   PGPByte const *passptr;¤/* Pointer into buffer */
ce2f45 ¤   PGPByte const *bufptr;¤ /* Pointer into buffer */
970bce ¤   PGPByte *bufend;¤   ¤   /* Pointer into buffer */
5ac1a2 ¤   Header head;¤   /* Current subpacket status */
214aee ¤   PGPByte silent_trunc;¤  /* Complain if out of input? */
3852c8 } Input;
90af5a
0915da typedef struct PrsBinContext {
35f8fb ¤   PGPPipeline¤¤   pipe;
b867c5 ¤
4c6165 ¤   Input input;
3675b0 ¤   PGPPipeline *tail;
0d2655 ¤   PGPPipeline *nextparser;
f8b080 ¤   PGPPipeline **end;
2e8113 ¤   PGPHashListRef hashes;
4aee3d ¤   PGPEnv const *env;
60961f ¤   int state;¤ ¤   /* Used my bumerous parse functions */
b295d2 ¤   int end_scope;¤ ¤   /* Annotation at end of this scope, or 0 */
a41845 ¤   PGPByte subtype;¤   ¤   /* Type of literal packet (t vs. b) */
92cd30 ¤   int sig1pass;¤  ¤   /* Within 1-pass signature scope */
d49b1a ¤   int sig1nest;¤  ¤   /* Number of unpaired 1pass headers nested */
7c1260 ¤   /* Flags */
98a7e9 ¤   PGPByte sepsig;¤¤   /* 1-pass separate signature */
410609 ¤   PGPByte findpkt;¤   ¤   /* Searching for a new packet */
551ab3 ¤   PGPByte eof;¤   ¤   /* No more input available, ever */
25a0e5 ¤   PGPByte needcallback;
9e470a ¤   PGPUICb const *ui;
fc5f9a ¤   void *ui_arg;
f36eb1 ¤   PGPByte beginline[sizeof(pgp_message_begin)-1];¤/* for literal recursion */
043877 ¤   PGPSize beginlength;¤   ¤   ¤   ¤   /* chars in beginline */
53ed35 ¤   DEBUG_STRUCT_CONSTRUCTOR( PrsBinContext )
c0bba9 } PrsBinContext;
f7af5a
fafb26 /* Return true if the end of the current packet has been reached */
5bbeb7 static int
84e60a inputFinished(Header const *head)
53bb36 {
f7106e ¤   return !head->pktlen && !head->lenbytes && !head->more;
36efe6 }
f3af5a
3238e5 /*
0adc31 ·* Return a pointer to, and then length of, the subpacket header at the
d4a837 ·* current position in the input buffer, using the context of "head".
95495d ·*/
d25abf static PGPByte const *
7d65c3 inputHeadPeek(Header const *head, PGPByte const *buf, size_t size,
e32803 ··············size_t *len)
7ebb36 {
84ab12 ¤   pgpAssert(buf || !size);
6aaf5a
4b8e2f ¤   if (head->lenbytes) {
e29468 ¤   ¤   *len = (size < head->lenbytes) ? size : (size_t)head->lenbytes;
0c48d2 ¤   ¤   return buf;
b79371 ¤   }
21a440 ¤   if (head->pktlen) {
da5afc ¤   ¤   *len = 0;
c748d2 ¤   ¤   return buf;
c29371 ¤   }
08a674 ¤   if (!head->more) {
ce5afc ¤   ¤   *len = 0;
2c9c0e ¤   ¤   return (PGPByte const *)0;
5e9371 ¤   }
10efaa ¤   if (!size) {
4b5afc ¤   ¤   *len = 0;
--0277 000215e026640100197 Page 4 of pgpPrsBin.c
b248d2 ¤   ¤   return buf;
f39371 ¤   }
ffc462 ¤   if (buf[0] == 0xff && size >= 5)
fa6341 ¤   ¤   *len = 5;
f08da3 ¤   else if (buf[0] == 0xff)
c8f1b3 ¤   ¤   *len = size;
2b89d6 ¤   else if ((buf[0] & 0xe0) == 0xc0 && size > 1)
2aef44 ¤   ¤   *len = 2;
130e24 ¤   else
7e0020 ¤   ¤   *len = 1;
24dfa1 ¤   return buf;
dbefe6 }
f7af5a
4b38e5 /*
b70d75 ·* Skip the upcoming header, adjusting the state in "head" appropriately.
2f2e1c ·* Return the number of bytes consumed (<= size).
25495d ·*/
575d09 static size_t
b500ad inputHeadSeek(Header *head, PGPByte const *buf, size_t size)
c3bb36 {
fa743f ¤   unsigned i;
b801ef ¤   unsigned char b;
fbaf5a
1baaf9 ¤   /* No data, don't care */
b2faf0 ¤   if (!size)
62bbde ¤   ¤   return 0;
aaeef2 ¤   pgpAssert(buf);
52af5a
b27b94 ¤   /* If we're in the middle of a header, read the tail of it */
388e2f ¤   if (head->lenbytes) {
e1df3a ¤   ¤   if (size > head->lenbytes)
d80c7f ¤   ¤   ¤   size = (size_t)head->lenbytes;
1cbad8 ¤   ¤   i = (unsigned)size;
814392 ¤   ¤   do {
796c40 ¤   ¤   ¤   head->pktlen += (PGPUInt32)*buf++ << (8*--head->lenbytes);
46ff7f ¤   ¤   } while (--i);
2cb771 ¤   ¤   return size;
cf9371 ¤   }
fdaf5a
0ea427 ¤   /* Are we not at the end of a packet? */
8f473a ¤   if (head->pktlen || !head->more)
02bbde ¤   ¤   return 0;
9faf5a
c180d7 ¤   /* Otherwise, we're starting a new subpacket header */
46a367 ¤   b = buf[0];
abb8d7 ¤   if (b < 0xc0) {
7b05bb ¤   ¤   head->pktlen = (PGPUInt32)b;
7274dc ¤   ¤   head->more = 0;
b3097a ¤   } else if (b < 0xe0) {
529ebe ¤   ¤   head->pktlen = ((PGPUInt32)b << 8) - (0xc000 - 0xc0);
ea74dc ¤   ¤   head->more = 0;
562117 ¤   ¤   if (size == 1) {
9369b5 ¤   ¤   ¤   head->lenbytes = 1;
1d45a6 ¤   ¤   } else {
fe0f42 ¤   ¤   ¤   head->pktlen += (PGPUInt32)buf[1];
1b34fc ¤   ¤   ¤   return 2;
410fe4 ¤   ¤   }
f364ff ¤   } else if (b == 0xff) {
07afd5 ¤   ¤   if (size > 5)
5971ac ¤   ¤   ¤   size = 5;
4e5149 ¤   ¤   i = (unsigned)size-1;
a474dc ¤   ¤   head->more = 0;
bafd56 ¤   ¤   head->lenbytes = 4;
fe87ea ¤   ¤   head->pktlen = 0;
fd4392 ¤   ¤   do {
5def8d ¤   ¤   ¤   head->pktlen += (PGPUInt32)*++buf << (8*--head->lenbytes);
2fff7f ¤   ¤   } while (--i);
16b771 ¤   ¤   return size;
42d8cb ¤   } else if (b >= 0xe0) {
e8d0e9 ¤   ¤   head->pktlen = (PGPUInt32)1 << (b & 31);
2c9371 ¤   }
2164b7 ¤   return 1;
--64d8 0004ee6691c40100197 Page 5 of pgpPrsBin.c
7aefe6 }
813d9e ················
a62978 static void
6833bc inputReset(Input *input)
25bb36 {
af4865 ¤   input->passptr = input->bufptr = input->bufend = input->buffer;
db7046 ¤   input->head.pktlen = 0;
181b58 ¤   input->head.lenbytes = 0;
f396de ¤   input->head.more = 0;
45efe6 }
f9af5a
4338e5 /*
1fbe69 ·* Start parsing a packet with the given header byte.
b6c21c ·* Returns 0 if it's a normal, good header byte, and -1
9d5bbc ·* if it's a bogus header byte, in which case the rest of the
682557 ·* input is taken as the body.
66495d ·*/
63beb7 static int
a0f109 inputStart(Input *input, PGPByte b)
d5bb36 {
a498b5 ¤   /* Store first byte in buffer */
0855e6 ¤   input->passptr = input->buffer;
110c6e ¤   input->buffer[0] = b;
5e0212 ¤   input->bufend = input->buffer+1;
d47046 ¤   input->head.pktlen = 0;
efaf5a
ac5899 ¤   if (IS_NEW_PKTBYTE(b)) {
33a7f6 ¤   ¤   /* New style */
e02c50 ¤   ¤   input->head.lenbytes = 0;
f04556 ¤   ¤   input->head.more = 1;
d612d8 ¤   ¤   input->silent_trunc = 0;
8e2aa4 ¤   } else if (IS_OLD_PKTBYTE(b)) {
03a214 ¤   ¤   /* Old style */
01f601 ¤   ¤   input->head.lenbytes = LLEN_TO_BYTES(PKTBYTE_LLEN(b));
581f8a ¤   ¤   input->head.more = 0;
2b12d8 ¤   ¤   input->silent_trunc = 0;
2254e8 ¤   ¤   if (PKTBYTE_LLEN(b) == 3) {
33756c ¤   ¤   ¤   input->silent_trunc = 1;
d6aaa2 ¤   ¤   ¤   input->head.pktlen = (PGPUInt32)-1;
8a0fe4 ¤   ¤   }
14f037 ¤   } else {
eb8ce6 ¤   ¤   /* Erroneous! */
55095e ¤   ¤   input->bufptr = input->buffer;
beb2f2 ¤   ¤   input->head.pktlen = (PGPUInt32)-1;
892c50 ¤   ¤   input->head.lenbytes = 0;
fe1f8a ¤   ¤   input->head.more = 0;
be4804 ¤   ¤   input->silent_trunc = 1;
4b043c ¤   ¤   return -1;
a49371 ¤   }
9662af ¤   /* Usual case wrapup */
b0c638 ¤   input->bufptr = input->bufend;
8a3e6b ¤   return 0;
23efe6 }
aeaf5a
df38e5 /*
9cc889 ·* Return a pointer to, and the length of, the next available packet payload
cca2a3 ·* bytes. ·These bytes will come from either the read-ahead buffer or the
87ab79 ·* input buffer (buf, size), as appropriate. ·Returns a NULL pointer when
6239b5 ·* there is no more data available in the packet. ·If "size" is 0 and
be52cc ·* this is not the end of the packet, this returns the "buf" pointer,
c58a9e ·* which may or may not be NULL, at the caller's discretion.
8b775e ·*
836f6b ·* This may, in some situations (like when "size" is 1 and sitting
f54772 ·* on a subpacket header), return the "buf" pointer but a zero length
eb139e ·* even when size is non-zero.
fc7431 ·* In that case, the current packet is not finished, but no data is available
00c4ee ·* in the current input buffer. ··You need to call inputSeek(0) to give
7091f1 ·* it a chance to consume the current input buffer.
78495d ·*/
215abf static PGPByte const *
52fc6d inputPeek(Input const *input, PGPByte const *buf, size_t size, size_t *len)
4ebb36 {
--615b 00057c1fdbb40100197 Page 6 of pgpPrsBin.c
0abb26 ¤   /* If we have no buffer, then size must be 0 */
67ab12 ¤   pgpAssert(buf || !size);
07af5a
4dc4ac ¤   /* If we have data buffered, use that. */
5f5bff ¤   if (input->bufend != input->bufptr) {
f75409 ¤   ¤   *len = (size_t)(input->bufend - input->bufptr);
220029 ¤   ¤   return input->bufptr;
249371 ¤   }
eed8af ¤   /*
0a47ac ¤   ·* If we are in the middle of a subpacket header, no data available,
e5df0f ¤   ·* but more to come.
5aa4e3 ¤   ·*/
4960e7 ¤   if (input->head.lenbytes) {
f25afc ¤   ¤   *len = 0;
fe48d2 ¤   ¤   return buf;
9a9371 ¤   }
65d8af ¤   /*
617cb1 ¤   ·* If we're at the end of a subpacket, no data available, and
9bc5e3 ¤   ·* there may or may not be more to come.
41a4e3 ¤   ·*/
cee8ba ¤   if (!input->head.pktlen) {
845afc ¤   ¤   *len = 0;
f77b30 ¤   ¤   return input->head.more ? buf : 0;
1c9371 ¤   }
45af5a
f25e07 ¤   /* Return the appropriate data from the input buffer */
a94723 ¤   if (size > input->head.pktlen)
b46304 ¤   ¤   size = (size_t)input->head.pktlen;
47af5a
75b038 ¤   *len = size;
37dfa1 ¤   return buf;
68efe6 }
f5af5a
8638e5 /*
f69704 ·* Skip over "len" bytes (where len <= the amount returned from the latest
74bb19 ·* call to inputPeek!) of input from the input stream (either the context
2ec1b0 ·* buffer or the supplied external buffer).
86495d ·*/
ce5d09 static size_t
9aef2b inputSeek(Input *input, PGPByte const *buf, size_t size, size_t len)
1dbb36 {
f1ab12 ¤   pgpAssert(buf || !size);
59af5a
4ad78c ¤   /* If we have data in the input buffer, skip that */
f65bff ¤   if (input->bufend != input->bufptr) {
807e63 ¤   ¤   pgpAssert(len <= (size_t)(input->bufend - input->bufptr));
ee0f0c ¤   ¤   input->bufptr += len;
a3bbde ¤   ¤   return 0;
b79371 ¤   }
a5e2f3 ¤   /* Make sure the skip is legal */
f755f4 ¤   pgpAssert(!len || !input->head.lenbytes);
3e6cb3 ¤   pgpAssert(len <= input->head.pktlen);
2af073 ¤   pgpAssert(len <= size);
0caf5a
78582c ¤   /* Skip the data */
432480 ¤   input->head.pktlen -= len;
9baf5a
fe4677 ¤   /* Skip any additional header that follows */
821bd1 ¤   return len + inputHeadSeek(&input->head, buf+len, size-len);
80efe6 }
e4af5a
3838e5 /*
8f1032 ·* Copy the input buffer to the FIFO.
0a495d ·*/
f2f1ae static PGPError
d1629c inputToFifo(Input *input)
7cbb36 {
61d7d7 ¤   size_t len, written;
34af5a
6c39a0 ¤   len = (size_t)(input->bufend - input->passptr);
ba5678 ¤   if (len) {
576e62 ¤   ¤   written = pgpFifoWrite (&pgpByteFifoDesc, input->fifo,
--1d34 0005783fd7140100197 Page 7 of pgpPrsBin.c
172945 ¤   ¤   ¤   ¤   ¤   input->passptr, len);
ca1769 ¤   ¤   input->passptr += written;
c7ea60 ¤   ¤   if (written != len)
327cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
ff9371 ¤   }
702d68 ¤   return( kPGPError_NoErr );
ceefe6 }
e5af5a
d238e5 /*
6914e3 ·* Try to ensure that the next "desired" bytes of input are contiguous
6f362c ·* and thus inputPeek will return them in one call. ·This will copy
57ec31 ·* bytes from the external buffer to the input buffer. ·If it does,
add3a8 ·* the number of bytes copied is returned.
44775e ·*
0f916b ·* If this needs to squeeze subpacket header bytes out of the read-ahead
1a59a4 ·* buffer to make the buffer contiguous, it copies the bytes to the FIFO
68031d ·* so they'll be available for raw reading.
d3495d ·*/
645d09 static size_t
011789 inputMerge(Input *input, PGPByte const *buf, size_t size, unsigned desired,
9007dc ···········PGPError *error)
4cbb36 {
fb0a74 ¤   size_t size0;
3cd185 ¤   size_t s, t;
bf2f36 ¤   unsigned avail;
83af5a
92ab12 ¤   pgpAssert(buf || !size);
8daf5a
9fc00a ¤   *error = kPGPError_NoErr;¤  /* No error */
59af5a
9fbc91 ¤   s = (size_t)(input->bufend - input->bufptr);
cf1a92 ¤   if (s >= desired)
5dbbde ¤   ¤   return 0;
92b4a7 ¤   desired -= (unsigned)s;
ccaf5a
824e44 ¤   size0 = size;
9d67c5 ¤
125523 ¤   while (desired && size) {
0cc86a ¤   ¤   /* Suck in the following header, if any */
d15139 ¤   ¤   if (!inputHeadPeek(&input->head, buf, size, &s))
7618f0 ¤   ¤   ¤   break;¤ /* End of packet */
379bb1 ¤   ¤   /* If we have a header, deal with it. */
b959cc ¤   ¤   if (s) {
f77aad ¤   ¤   ¤   /*
26944f ¤   ¤   ¤   ·* Do something with the header - put it in the buffer
fcdf6c ¤   ¤   ¤   ·* before bufptr if possible, or in the FIFO if not.
778753 ¤   ¤   ¤   ·*/
ce9f48 ¤   ¤   ¤   if (input->bufptr == input->bufend) {
287449 ¤   ¤   ¤   ¤   memcpy(input->bufend, buf, s);
d30f30 ¤   ¤   ¤   ¤   (void)inputHeadSeek(&input->head, buf, s);
af0fdf ¤   ¤   ¤   ¤   input->bufptr = input->bufend += s;
f05de2 ¤   ¤   ¤   ¤   buf += s;
6e6a10 ¤   ¤   ¤   ¤   size -= s;
c8042d ¤   ¤   ¤   } else {
f1dfdd ¤   ¤   ¤   ¤   /* Write what's already in the buffer */
354964 ¤   ¤   ¤   ¤   *error = inputToFifo(input);
0543a0 ¤   ¤   ¤   ¤   if (*error)
8614c3 ¤   ¤   ¤   ¤   ¤   break;
793095 ¤   ¤   ¤   ¤   /* Write the current header to the FIFO */
29cf64 ¤   ¤   ¤   ¤   t = pgpFifoWrite (&pgpByteFifoDesc,
a66ffe ¤   ¤   ¤   ¤   ¤   ¤   ··input->fifo, buf, s);
6c5811 ¤   ¤   ¤   ¤   (void)inputHeadSeek(&input->head, buf, t);
a4d1e7 ¤   ¤   ¤   ¤   buf += t;
4be615 ¤   ¤   ¤   ¤   size -= t;
4adc09 ¤   ¤   ¤   ¤   if (t != s) {
76e49a ¤   ¤   ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
2514c3 ¤   ¤   ¤   ¤   ¤   break;
e72613 ¤   ¤   ¤   ¤   }
39a3a6 ¤   ¤   ¤   }
3d0fe4 ¤   ¤   }
15af5a
5793e2 ¤   ¤   /* Normal data to be copied */
--b860 00075b22cd840100197 Page 8 of pgpPrsBin.c
b22bd1 ¤   ¤   avail = desired;
c85b08 ¤   ¤   if (avail > size)
14b310 ¤   ¤   ¤   avail = (unsigned)size;
bee85c ¤   ¤   if (avail > input->head.pktlen)
07ff4b ¤   ¤   ¤   avail = (unsigned)input->head.pktlen;
cf3d15 ¤   ¤   s = input->buffer+sizeof(input->buffer)-input->bufend;
713ff5 ¤   ¤   if (avail > s) {
c32f7d ¤   ¤   ¤   if (!s)
6df622 ¤   ¤   ¤   ¤   break;
b7f436 ¤   ¤   ¤   avail = (unsigned)s;
820fe4 ¤   ¤   }
e9c7de ¤   ¤   memcpy(input->bufend, buf, avail);
14acfe ¤   ¤   input->bufend += avail;
0a1e58 ¤   ¤   input->head.pktlen -= avail;
4d2d45 ¤   ¤   size -= avail;
2f62b6 ¤   ¤   desired -= avail;
539371 ¤   }
31af5a
303084 ¤   return size0-size;
85efe6 }
faaf5a
96216e /* Return true if there's more packet in here than will fit */
fabeb7 static int
62cb6f inputOverfull(Input const *input)
a5bb36 {
b8b8c7 ¤   return input->bufend == input->buffer+sizeof(input->buffer) &&
ce4c3b ¤   ¤   !inputFinished(&input->head);
eaefe6 }
d1af5a
c81e02 /* How many merged bytes are available? */
afb8d0 static size_t·
c28c4c inputMerged(Input const *input)
3abb36 {
75db89 ¤   return (size_t)(input->bufend - input->bufptr);
3befe6 }
6caf5a
6a75ba /* Pointer to the merged bytes */
3f0bca static unsigned char const *
a35528 inputMergedPtr(Input const *input)
dcbb36 {
40897d ¤   return input->bufptr;
caefe6 }
06af5a
5e38e5 /*
79623a ·* Return a buffer and length corresponding to the next batch of
31e704 ·* raw (unparsed) characters in the current packet.
9ccdd8 ·* The bytes might come from one of three places:
c9909c ·* - The FIFO where they have been copied by inputMerge()
c3eaea ·* - The input buffer
0d3ed1 ·* - the passed-in external buffer
887664 ·* In the latter case, this parses ahead in the input buffer as many
61ae92 ·* subpackets as possible to give the largest block of data possible.
f7775e ·*
e40447 ·* Returns NULL with a length of 0 if there are no more bytes in the current
67b714 ·* packet. ·Returns "buf" with a length of 0 if size is 0.
a25759 ·* That may or may not be NULL, depending on the caller.
82495d ·*/
175abf static PGPByte const *
09e7d7 inputRawPeek(Input const *input, PGPByte const *buf, size_t size,
59ec3d ·············size_t *len)
01bb36 {
e08b0f ¤   PGPByte const *p;
5776e2 ¤   size_t s;
f20a74 ¤   size_t size0;
82e639 ¤   PGPSize ulen;
178ced ¤   Header head;
c7af5a
52ab12 ¤   pgpAssert(buf || !size);
9967c5 ¤
7bfb76 ¤   /* Try the byte FIFO */
bdaa47 ¤   p = pgpFifoPeek (&pgpByteFifoDesc, input->fifo, &ulen);
75f191 ¤   if (p) {
--12c9 0004469047a40100197 Page 9 of pgpPrsBin.c
891396 ¤   ¤   *len = (size_t)ulen;
36bda8 ¤   ¤   return p;
7b9371 ¤   }
6658aa ¤   /* Then the buffered data */
36a99b ¤   if (input->passptr != input->bufend) {
4260e3 ¤   ¤   *len = input->bufend - input->passptr;
f320de ¤   ¤   return input->passptr;
309371 ¤   }
b6018e ¤   /* Finally, the external buffer */
6caf5a
f34e44 ¤   size0 = size;
bb888f ¤   p = buf;
086660 ¤   head = input->head;
65af5a
200f40 ¤   while (size && !inputFinished(&head)) {
414fe1 ¤   ¤   s = inputHeadSeek(&head, p, size);
1bb318 ¤   ¤   size -= s;
761853 ¤   ¤   if (!size)
f8cdcb ¤   ¤   ¤   break;
3dd515 ¤   ¤   p += s;
afed03 ¤   ¤   if (size <= head.pktlen) {
854811 ¤   ¤   ¤   size = 0;
d4cdcb ¤   ¤   ¤   break;
cf0fe4 ¤   ¤   }
45dd1d ¤   ¤   size -= head.pktlen;
6c9dca ¤   ¤   p += head.pktlen;
c3425c ¤   ¤   head.pktlen = 0;
8d9371 ¤   }
6baf5a
588f64 ¤   *len = size0 - size;
08dfa1 ¤   return buf;
31efe6 }
94af5a
b238e5 /*
60d538 ·* Skip forward over a given number of bytes of raw input data.
48074b ·* The number of bytes must be <= the number returned from
efac25 ·* inputRawPeek().
db775e ·*
516d96 ·* The FIFO and buffered data are simple. ·If those are empty,
139a85 ·* parse forward in the external buffer until the desired number of
0dad30 ·* bytes have been skipped, then store the parsing state.
3f495d ·*/
4e5d09 static size_t
cb68b1 inputRawSeek(Input *input, PGPByte const *buf, size_t size, unsigned len)
27bb36 {
6f76e2 ¤   size_t s;
04af5a
7dab12 ¤   pgpAssert(buf || !size);
6767c5 ¤
a1bbb9 ¤   /* If there's data in the FIFO, skip that... */
690cc8 ¤   if (pgpFifoSize (&pgpByteFifoDesc, input->fifo)) {
f2357b ¤   ¤   pgpFifoSeek (&pgpByteFifoDesc, input->fifo, len);
94bbde ¤   ¤   return 0;
079371 ¤   }
a23383 ¤   /* Otherwise the buffered data */
51a99b ¤   if (input->passptr != input->bufend) {
949b19 ¤   ¤   pgpAssert(len <= (size_t)(input->bufend - input->passptr));
e6e73a ¤   ¤   input->passptr += len;
95fb7c ¤   ¤   if (input->bufptr < input->passptr)
9f4ac7 ¤   ¤   ¤   input->bufptr = input->passptr;
f0bbde ¤   ¤   return 0;
939371 ¤   }
82af5a
bf018e ¤   /* Finally, the external buffer */
c3f073 ¤   pgpAssert(len <= size);
30af5a
514df8 ¤   size = len;
cfa0eb ¤   while (size) {
83f0f0 ¤   ¤   s = inputHeadSeek(&input->head, buf, size);
ccb318 ¤   ¤   size -= s;
49c1b1 ¤   ¤   if (!len)
44cdcb ¤   ¤   ¤   break;
--e636 00022fb4aec40100197 Page 10 of pgpPrsBin.c
9ba0cd ¤   ¤   buf += s;
9c1122 ¤   ¤   if (size <= input->head.pktlen) {
7be019 ¤   ¤   ¤   input->head.pktlen -= size;
26cdcb ¤   ¤   ¤   break;
860fe4 ¤   ¤   }
ad2a92 ¤   ¤   size -= input->head.pktlen;
562d65 ¤   ¤   buf += input->head.pktlen;
3add18 ¤   ¤   input->head.pktlen = 0;
1d9371 ¤   }
2cbb7a ¤   return len;
62efe6 }
c2af5a
f9a12e /* Get rid of the header we've processed from the system. */
092978 static void
bd0e69 inputPurge(Input *input)
cebb36 {
f7991b ¤   pgpFifoFlush (&pgpByteFifoDesc, input->fifo);
4d4865 ¤   input->passptr = input->bufptr = input->bufend = input->buffer;
58efe6 }
16af5a
acaf5a
0bb177 #if 0
6238e5 /*
f542d7 ·* Write all the already-buffered bytes from the current packet.
b61668 ·* Return an error, if any is encountered.
6d495d ·*/
f9beb7 static int
7d41d3 DoRawFlush (PrsBinContext *ctx, PGPPipeline *tail)
17bb36 {
a85b01 ¤   PGPError¤   error = kPGPError_NoErr;
e8f20c ¤   size_t len;
ab8b0f ¤   PGPByte const *p;
4aaf5a
dc43ab ¤   do {
7864d8 ¤   ¤   p = inputRawPeek(&ctx->input, NULL, 0, &len);
25576a ¤   ¤   if (!p)
8bcdcb ¤   ¤   ¤   break;
c151ed ¤   ¤   len = tail->write (tail, p, len, &error);
a2126b ¤   ¤   (void)inputRawSeek(&ctx->input, NULL, 0, len);
25d19d ¤   } while (!error);
48af5a
1fc674 ¤   return error;
54efe6 }
aa7454 #endif
7faf5a
aaaf5a
7e5d09 static size_t
6764f6 DoSkip (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
04bb36 {
35e07e ¤   PrsBinContext *ctx;
896d88 ¤   size_t size0 = size;
cd8b0f ¤   PGPByte const *p;
28f20c ¤   size_t len;
01af5a
1729be ¤   pgpAssert (myself);
c270c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
e8af5a
918808 ¤   ctx = (PrsBinContext *)myself->priv;
49d6bc ¤   pgpAssert (ctx);
3c4866 ¤   pgpAssert (error);
622aee ¤   pgpAssert (!size || !ctx->eof);
6eaf5a
129096 ¤   *error = kPGPError_NoErr;
90af5a
19135a ¤   inputPurge (&ctx->input);
5faf5a
39220e ¤   for (;;) {
39aa10 ¤   ¤   p = inputPeek(&ctx->input, buf, size, &len);
e67568 ¤   ¤   if (!p) {
8add93 ¤   ¤   ¤   if (inputFinished(&ctx->input.head)) {
11f48f ¤   ¤   ¤   ¤   /* End of input */
222691 ¤   ¤   ¤   ¤   myself->write = nextScope;
--530b 000396207d840100197 Page 11 of pgpPrsBin.c
f3639b ¤   ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
80a3a6 ¤   ¤   ¤   }
a7cdcb ¤   ¤   ¤   break;
720fe4 ¤   ¤   }
adf351 ¤   ¤   if (!len && !size)
75cdcb ¤   ¤   ¤   break;
56f4a2 ¤   ¤   len = inputSeek(&ctx->input, buf, size, len);
d7e2d5 ¤   ¤   size -= len;
87e14c ¤   ¤   buf += len;
549371 ¤   }
05af5a
dc3084 ¤   return size0-size;
c9efe6 }
c0af5a
bf38e5 /*
da5d89 ·* Write out the as-yet-unread body of this packet to the tail of this module.
ccb5e8 ·* At the end of the packet (inputFinished), set the state back to
6bdf79 ·* nextScope.
3e495d ·*/
045d09 static size_t
20f104 DoWrite (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
abbb36 {
11e07e ¤   PrsBinContext *ctx;
36f20c ¤   size_t len;
d66d88 ¤   size_t size0 = size;
168b0f ¤   PGPByte const *p;
ddaf5a
5229be ¤   pgpAssert (myself);
8e70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
21af5a
828808 ¤   ctx = (PrsBinContext *)myself->priv;
62d6bc ¤   pgpAssert (ctx);
151728 ¤   pgpAssert (ctx->tail);
bc4866 ¤   pgpAssert (error);
112aee ¤   pgpAssert (!size || !ctx->eof);
05af5a
e59096 ¤   *error = kPGPError_NoErr;
2faf5a
ef43ab ¤   do {
54aa10 ¤   ¤   p = inputPeek(&ctx->input, buf, size, &len);
337568 ¤   ¤   if (!p) {
cadd93 ¤   ¤   ¤   if (inputFinished(&ctx->input.head)) {
c7f48f ¤   ¤   ¤   ¤   /* End of input */
022691 ¤   ¤   ¤   ¤   myself->write = nextScope;
e4639b ¤   ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
55a3a6 ¤   ¤   ¤   }
21cdcb ¤   ¤   ¤   break;
fd0fe4 ¤   ¤   }
85f351 ¤   ¤   if (!len && !size)
8acdcb ¤   ¤   ¤   break;
551c19 ¤   ¤   len = ctx->tail->write (ctx->tail, p, len, error);
49f4a2 ¤   ¤   len = inputSeek(&ctx->input, buf, size, len);
a7e2d5 ¤   ¤   size -= len;
1ae14c ¤   ¤   buf += len;
8a62d5 ¤   } while (!*error);
abaf5a
e73084 ¤   return size0-size;
5befe6 }
40af5a
4caf5a
7138e5 /*
55a6fb ·* Write out a series of packets to the tail of this module, keeping
1dac56 ·* track of packet boundaries, and counting pairs of signature headers
5a5d1a ·* and footers. ·When come to an unpaired footer, exit to process it.
e0495d ·*/
245d09 static size_t
a357f7 DoWriteSignedPackets(PGPPipeline *myself, PGPByte const *buf, size_t size,
9a374f ¤   ·······PGPError *error)
c3bb36 {
86e07e ¤   PrsBinContext *ctx;
6ef20c ¤   size_t len;
396d88 ¤   size_t size0 = size;
--4d59 000842204fc40100197 Page 12 of pgpPrsBin.c
cc8b0f ¤   PGPByte const *p;
f8ffd4 ¤   PGPByte b;
c1af5a
e429be ¤   pgpAssert (myself);
cf70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
0caf5a
648808 ¤   ctx = (PrsBinContext *)myself->priv;
46d6bc ¤   pgpAssert (ctx);
541728 ¤   pgpAssert (ctx->tail);
494866 ¤   pgpAssert (error);
022aee ¤   pgpAssert (!size || !ctx->eof);
5daf5a
8e9096 ¤   *error = kPGPError_NoErr;
c4af5a
056f5c ¤   switch (ctx->state) {
42f86f ¤   case 0:
c2e70f ¤   ¤   /* Here at the start of a packet */
21af5a
1a18f5 ¤   ¤   inputReset(&ctx->input);
eeaf5a
be1853 ¤   ¤   if (!size)
c8483d ¤   ¤   ¤   return 0;¤  /* I need a packet header! */
05af5a
8c1b17 ¤   ¤   /*
c48be8 ¤   ¤   ·* Track signature nesting.
a3b417 ¤   ¤   ·* sig1nest holds the excess 1pass sig hdrs we've seen
7f4539 ¤   ¤   ·* We distinguish old-style sig packets from new style by
6209a0 ¤   ¤   ·* whether the packet type byte is old or new style.
329de3 ¤   ¤   ·*/
eba7f2 ¤   ¤   if (IS_NEW_PKTBYTE(buf[0])) {
988972 ¤   ¤   ¤   PGPByte bt = PKTBYTE_TYPE(buf[0]);
f1095c ¤   ¤   ¤   if (bt==PKTBYTE_SIG && ctx->sig1nest==0) {
38d298 ¤   ¤   ¤   ¤   /* This footer is what we are looking for */
8b2691 ¤   ¤   ¤   ¤   myself->write = nextScope;
a2639b ¤   ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
c8f622 ¤   ¤   ¤   ¤   break;
8a86e4 ¤   ¤   ¤   } else if (bt==PKTBYTE_1PASSSIG) { /* sig header */
fd6e0c ¤   ¤   ¤   ¤   ++ctx->sig1nest;
ffa961 ¤   ¤   ¤   } else if (bt==PKTBYTE_SIG) { /* sig footer */
c9327d ¤   ¤   ¤   ¤   --ctx->sig1nest;
44a3a6 ¤   ¤   ¤   }
9c0fe4 ¤   ¤   }
27af5a
474808 ¤   ¤   /* Else read and pass on this packet */
16fe03 ¤   ¤   b = *(buf++);
bdaa85 ¤   ¤   size--;
78af5a
453d67 ¤   ¤   if (inputStart(&ctx->input, b) < 0) {
72c427 ¤   ¤   ¤   pgpAssert (0);¤ /* what to do here? */
780fe4 ¤   ¤   }
33af5a
81af5a
55deb7 ¤   ¤   ctx->state++;
4d8224 ¤   ¤   /* FALLTHROUGH */
5ea2b3 ¤   case 1:
f76282 ¤   ¤   while (!inputFinished(&ctx->input.head)) {
15b1a7 ¤   ¤   ¤   p = inputRawPeek(&ctx->input, buf, size, &len);
defb2b ¤   ¤   ¤   if (!len)
0b4a32 ¤   ¤   ¤   ¤   return size0-size;
3c484f ¤   ¤   ¤   len = ctx->tail->write(ctx->tail, p, len, error);
80026b ¤   ¤   ¤   len = inputRawSeek(&ctx->input, buf, size, len);
b35304 ¤   ¤   ¤   size -= len;
fe9bb8 ¤   ¤   ¤   buf += len;
69b5c5 ¤   ¤   ¤   if (*error)
de4a32 ¤   ¤   ¤   ¤   return size0-size;
8a0fe4 ¤   ¤   }
ed5f69 ¤   ¤   /* Here at end of packet */
5de158 ¤   ¤   ctx->state = 0;
ac2f68 ¤   ¤   break;
f39371 ¤   }
1f1b52 ¤   ¤
843084 ¤   return size0-size;
--a587 000857b26b740100197 Page 13 of pgpPrsBin.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
6ef445 ·* This function flushes the raw header bytes from the beginning of
2a9ff3 ·* the parser's buffer "over" the following module on to the following
aeff7c ·* parser, then falls through to writing the payload bytes to the following
954195 ·* module and the header bytes "over" it.
ca495d ·*/
965d09 static size_t
03b8da DoWriteNext (PGPPipeline *myself, PGPByte const *buf, size_t size,
6bfb43 ¤   ·····PGPError *error)
34bb36 {
ade07e ¤   PrsBinContext *ctx;
de8b0f ¤   PGPByte const *p;
486d88 ¤   size_t size0 = size;
f8f20c ¤   size_t len;
0515d0 ¤   PGPPipeline *tail, *next;
8daf5a
8829be ¤   pgpAssert (myself);
9470c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
9aaf5a
338808 ¤   ctx = (PrsBinContext *)myself->priv;
d8d6bc ¤   pgpAssert (ctx);
f81728 ¤   pgpAssert (ctx->tail);
ce7578 ¤   pgpAssert (ctx->nextparser);
864866 ¤   pgpAssert (error);
132aee ¤   pgpAssert (!size || !ctx->eof);
36af5a
3aea7f ¤   next = ctx->nextparser;
089096 ¤   *error = kPGPError_NoErr;
0eaf5a
d7220e ¤   for (;;) {
6264d8 ¤   ¤   p = inputRawPeek(&ctx->input, NULL, 0, &len);
e3c1b1 ¤   ¤   if (!len)
1ccdcb ¤   ¤   ¤   break;
ac81f3 ¤   ¤   len = next->write (next, p, len, error);
17126b ¤   ¤   (void)inputRawSeek(&ctx->input, NULL, 0, len);
98cf31 ¤   ¤   if (*error)
8a8144 ¤   ¤   ¤   return 0;
d49371 ¤   }
62af5a
0a0097 ¤   tail = ctx->tail;
0843ab ¤   do {
3a54b9 ¤   ¤   p = inputHeadPeek(&ctx->input.head, buf, size, &len);
d1b4db ¤   ¤   if (len) {
62b969 ¤   ¤   ¤   len = next->write(next, p, len, error);
59a237 ¤   ¤   ¤   (void)inputHeadSeek(&ctx->input.head, buf, len);
d39bb8 ¤   ¤   ¤   buf += len;
c95304 ¤   ¤   ¤   size -= len;
e645a6 ¤   ¤   } else {
59c523 ¤   ¤   ¤   p = inputPeek(&ctx->input, buf, size, &len);
dc8f32 ¤   ¤   ¤   if (len) {
335ae0 ¤   ¤   ¤   ¤   len = tail->write(tail, p, len, error);
34bab8 ¤   ¤   ¤   ¤   /* Note double "len" to prevent header skip */
0cdee6 ¤   ¤   ¤   ¤   len = inputSeek(&ctx->input, buf, len, len);
896ddd ¤   ¤   ¤   ¤   buf += len;
026759 ¤   ¤   ¤   ¤   size -= len;
98a8fe ¤   ¤   ¤   } else
61f622 ¤   ¤   ¤   ¤   break;
a40fe4 ¤   ¤   }
3ccf31 ¤   ¤   if (*error)
0cc64d ¤   ¤   ¤   return size0-size;
7a0fea ¤   } while (size);
4aaf5a
5c2107 ¤   /* If that's the end of this packet, continue with the next. */
4094b9 ¤   if (inputFinished(&ctx->input.head)) {
fa6cd8 ¤   ¤   /* End of input */
58692e ¤   ¤   myself->write = nextScope;
b682ec ¤   ¤   size -= nextScope (myself, buf, size, error);
1e9371 ¤   }
85af5a
--fe75 000f8a4c02b40100197 Page 14 of pgpPrsBin.c
c03084 ¤   return size0-size;
bbefe6 }
c0af5a
0938e5 /*
aa3d22 ·* This function is called when we are checking the signature on a literal
531ed8 ·* packet. ·The reason it is needed is that signatures are only on the BODY
f52663 ·* of the literal packet, not the headers. ·OOPS. ·So find the size of
0518d8 ·* the literal packet header and pass it (external header and internal
860ed1 ·* header) "over" the hash module to the ctx->nextparser using
99a08f ·* DoWriteNext.
b8775e ·*
363600 ·* This does NOT report errors on a short or truncated literal packet, since
0fd392 ·* we're pretending not to be parsing it - the downstream parser will
a1f4cf ·* notice it and do any necessary complaining. ·It DOES, however, try
ba9010 ·* to write out such packets to the downstream parser so it can do the
5b8ee9 ·* reporting.
f6495d ·*/
f55d09 static size_t
b9a2ed parseSignedLiteralMagic (PGPPipeline *myself,
8a5d55 ·························PGPByte const *buf, size_t size, PGPError *error)
a2bb36 {
93e07e ¤   PrsBinContext *ctx;
e6f20c ¤   size_t len;
3d8b0f ¤   PGPByte const *p;
1a6d88 ¤   size_t size0 = size;
58af5a
c529be ¤   pgpAssert (myself);
8770c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
7daf5a
6c8808 ¤   ctx = (PrsBinContext *)myself->priv;
3ad6bc ¤   pgpAssert (ctx);
141728 ¤   pgpAssert (ctx->tail);
e04866 ¤   pgpAssert (error);
282aee ¤   pgpAssert (!size || !ctx->eof);
72af5a
9cac19 ¤   /* Make sure nothing confusing can happen here! */
6b0ccc ¤   pgpAssert(!ctx->needcallback);
f4af5a
579d00 ¤   /* Do NOT complain on truncation. */
f0363b ¤   ctx->input.silent_trunc = 1;
b6af5a
fccd6a ¤   /* No error until told otherwise */
d69096 ¤   *error = kPGPError_NoErr;
0aaf5a
a96f5c ¤   switch (ctx->state) {
01a7f3 ¤   ··case 0:¤  /* Get packet header byte */
cc1853 ¤   ¤   if (!size)
788144 ¤   ¤   ¤   return 0;
bfaf5a
a942fd ¤   ¤   /* We know it's a literal packet, so no worries. */
589163 ¤   ¤   (void)inputStart(&ctx->input, *buf);
c5e21a ¤   ¤   buf++;
a1aa85 ¤   ¤   size--;
c6deb7 ¤   ¤   ctx->state++;
a08224 ¤   ¤   /* FALLTHROUGH */
afcfc4 ¤   ··case 1:¤  /* Get internal header */
f0dc25 ¤   ¤   len = inputMerge(&ctx->input, buf, size, 2, error);
dce14c ¤   ¤   buf += len;
8ce2d5 ¤   ¤   size -= len;
30cf31 ¤   ¤   if (*error)
f9cdcb ¤   ¤   ¤   break;
30a212 ¤   ¤   p = inputPeek(&ctx->input, NULL, 0, &len);
955496 ¤   ¤   if (len < 2) {
02cffe ¤   ¤   ¤   if (!inputFinished(&ctx->input.head))
b6f622 ¤   ¤   ¤   ¤   break;
6f45a6 ¤   ¤   } else {
e6cfa6 ¤   ¤   ¤   len = inputMerge(&ctx->input, buf, size, 6+p[1],
925d9b ¤   ¤   ¤   ¤   ¤   error);
3b9bb8 ¤   ¤   ¤   buf += len;
8b5304 ¤   ¤   ¤   size -= len;
e6b5c5 ¤   ¤   ¤   if (*error)
f8f622 ¤   ¤   ¤   ¤   break;
--f3e9 000e192d0d240100197 Page 15 of pgpPrsBin.c
3aba53 ¤   ¤   ¤   if (inputMerged(&ctx->input) < (size_t)6+p[1]) {
2f61ff ¤   ¤   ¤   ¤   if (!inputFinished(&ctx->input.head))
a214c3 ¤   ¤   ¤   ¤   ¤   break;
3aa3a6 ¤   ¤   ¤   }
2e0fe4 ¤   ¤   }
3c1284 ¤   ¤   /* We've got as much as we need */
16deb7 ¤   ¤   ctx->state++;
5fa812 ¤   ¤   myself->write = DoWriteNext;
d98824 ¤   ¤   size -= DoWriteNext (myself, buf, size, error);
a52f68 ¤   ¤   break;
6df727 ¤   ··default:
9c7036 ¤   ¤   pgpAssert(0);
0a9371 ¤   }
093084 ¤   return size0-size;
18efe6 }
b1af5a
c638e5 /*
b47f78 ·* This function just does a little bit of trivial initialization,
ac9c49 ·* including setting the state to 0, and then falls through to
d6eed6 ·* parseSignedLiteralMagic. ·The Do functions can be called from a
dadd9f ·* variety of states, due to the way they are set up from callbacks
6c922f ·* that may be called from a variety of states, so they can't depend on
210bc5 ·* the ctx->state. ·Thus, the need for this little wrapper function.
d6495d ·*/
215d09 static size_t
485144 DoSignedLiteralMagic (PGPPipeline *myself, PGPByte const *buf, size_t size,
2ad3ec ¤   ¤   ······PGPError *error)
59bb36 {
a6e07e ¤   PrsBinContext *ctx;
cfaf5a
d929be ¤   pgpAssert (myself);
f470c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
c8af5a
dc8808 ¤   ctx = (PrsBinContext *)myself->priv;
42d6bc ¤   pgpAssert (ctx);
771728 ¤   pgpAssert (ctx->tail);
e54866 ¤   pgpAssert (error);
3c2aee ¤   pgpAssert (!size || !ctx->eof);
0aaf5a
97ac19 ¤   /* Make sure nothing confusing can happen here! */
650ccc ¤   pgpAssert(!ctx->needcallback);
d7af5a
8a9d00 ¤   /* Do NOT complain on truncation. */
4d363b ¤   ctx->input.silent_trunc = 1;
aee8d9 ¤   /* Reset state for parseSignedLiteralMagic */
db9bac ¤   ctx->state = 0;
2b6012 ¤   myself->write = parseSignedLiteralMagic;
3dd6c4 ¤   return parseSignedLiteralMagic(myself, buf, size, error);
e5efe6 }
f6af5a
7d38e5 /*
9d1cd4 ·* Pass through the full ciphertext of the current packet, headers and
6d78b6 ·* all, to the tail module
ac495d ·*/
995d09 static size_t
194b64 DoPassthrough (PGPPipeline *myself, PGPByte const *buf, size_t size,
99374f ¤   ·······PGPError *error)
cfbb36 {
19e07e ¤   PrsBinContext *ctx;
a86d88 ¤   size_t size0 = size;
598b0f ¤   PGPByte const *p;
89f20c ¤   size_t len;
a375b0 ¤   PGPPipeline *tail;
51af5a
5329be ¤   pgpAssert (myself);
6170c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
7baf5a
178808 ¤   ctx = (PrsBinContext *)myself->priv;
9cd6bc ¤   pgpAssert (ctx);
180097 ¤   tail = ctx->tail;
1fac3e ¤   pgpAssert (tail);
e14866 ¤   pgpAssert (error);
--5537 00056c8525a40100197 Page 16 of pgpPrsBin.c
692aee ¤   pgpAssert (!size || !ctx->eof);
80af5a
1f9096 ¤   *error = kPGPError_NoErr;
6dae80 ¤   /* empty out the buffered data and then the packet */
db220e ¤   for (;;) {
fd3ef0 ¤   ¤   p = inputRawPeek(&ctx->input, buf, size, &len);
c5c1b1 ¤   ¤   if (!len)
60cdcb ¤   ¤   ¤   break;
9941ed ¤   ¤   len = tail->write (tail, p, len, error);
9dafd5 ¤   ¤   len = inputRawSeek (&ctx->input, buf, size, len);
71e14c ¤   ¤   buf += len;
b0e2d5 ¤   ¤   size -= len;
f3cf31 ¤   ¤   if (*error)
82c64d ¤   ¤   ¤   return size0-size;
919371 ¤   }
d1af5a
eb2107 ¤   /* If that's the end of this packet, continue with the next. */
d4e4a7 ¤   if (inputFinished (&ctx->input.head)) {
0a6cd8 ¤   ¤   /* End of input */
0b692e ¤   ¤   myself->write = nextScope;
8482ec ¤   ¤   size -= nextScope (myself, buf, size, error);
109371 ¤   }
2caf5a
bd3084 ¤   return size0-size;
bfefe6 }
06af5a
5138e5 /*
024923 ·* Tear down the pipeline connected to our tail for the processing of the
c15479 ·* current packet. ·This is the pipeline starting with ctx->tail and
ee852d ·* ending at *ctx->end. ·Note that myself may be zero length, i.e.
e3a780 ·* ctx->end == &ctx->tail!
b0495d ·*/
3b2978 static void
be57d8 parsePipelineTeardown (PrsBinContext *ctx)
87bb36 {
cc0a7a ¤   PGPPipeline *temp;
30af5a
148f65 ¤   pgpAssert (ctx->end);
a8af5a
517869 ¤   /*·
b92679 ¤   ·* End the pipeline I created, tear it down, and re-attach the
024e5e ¤   ·* original pipeline
1da4e3 ¤   ·*/
c023c5 ¤   temp = *(ctx->end);
38b18c ¤   *(ctx->end) = NULL;
10af5a
cad8af ¤   /*
74d36e ¤   ·* Make sure this isn't a zero-length pipeline, since ctx->end
7e8351 ¤   ·* can point to the address of ctx->tail!
0227a5 ¤   ·*/¤ ··
2336ed ¤   if (ctx->tail)
b5f61c ¤   ¤   ctx->tail->teardown (ctx->tail);
26dbb1 ¤   ctx->tail = temp;
4389ee ¤   ctx->end = NULL;
44efe6 }
4faf5a
7d38e5 /*
f7765f ·* Given a candidate encryption key, verify it against the IV that we have
3be900 ·* stored in the buffer. ·If it checks, return the PGPCFBContext
4f1a93 ·* set up to decrypt the rest of the packet. ·Otherwise, return NULL.
e8495d ·*/
aba8c5 static PGPCFBContext *
d00562 CheckKey (
aa3163 ¤   PGPContextRef¤  cdkContext,
d701db ¤   PrsBinContext¤  *ctx,
8240ea ¤   PGPByte const¤  *string,
0d39e0 ¤   size_t¤ ¤   ¤   size,
b8344c ¤   PGPError¤   ¤   *error
7527e6 ¤   )
f3bb36 {
5d0eef ¤   PGPByte buf[IVLEN];
56cfbe ¤   PGPCFBContext *cfb;
--2daa 000e43b751740100197 Page 17 of pgpPrsBin.c
7808c6 ¤   PGPCipherVTBL const *cipher;
6ed2c6 ¤   unsigned char const *p;
99f20c ¤   size_t len;
29af5a
a6efaa ¤   if (!size) {
189e6a ¤   ¤   *error = kPGPError_BadKeyLength;¤   /* Um, I guess? */
842014 ¤   ¤   return (PGPCFBContext *)0;
ea9371 ¤   }
6298b8 ¤   cipher = pgpCipherGetVTBL ( (PGPCipherAlgorithm)string[0]);
c8e060 ¤   if (!cipher) {
f332f5 ¤   ¤   *error = kPGPError_BadCipherNumber;
4a2014 ¤   ¤   return (PGPCFBContext *)0;
a89371 ¤   }
71470a ¤   if (size != cipher->keysize+1) {
a1aff9 ¤   ¤   *error = kPGPError_BadKeyLength;
4b2014 ¤   ¤   return (PGPCFBContext *)0;
419371 ¤   }
3faf5a
892aa0 ¤   cfb = pgpCFBCreate ( PGPGetContextMemoryMgr( cdkContext ), cipher);
3aca8e ¤   if (!cfb) {
d3e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
7b2014 ¤   ¤   return (PGPCFBContext *)0;
469371 ¤   }
2daf5a
d27aa0 ¤   p = inputPeek(&ctx->input, NULL, 0, &len);
a5af58 ¤   pgpAssert(len >= IVLEN);
97f2bc ¤   PGPInitCFB (cfb, string+1, NULL);
12ddc9 ¤   PGPCFBDecrypt (cfb, p, IVLEN, buf);
0caf5a
1ddbbd ¤   if (buf[IVLEN-2] != buf[IVLEN-4] || buf[IVLEN-1] != buf[IVLEN-3]) {
6af65d ¤   ¤   PGPFreeCFBContext (cfb);
2d555f ¤   ¤   *error = kPGPError_CantDecrypt;
102014 ¤   ¤   return (PGPCFBContext *)0;
449371 ¤   }
15af5a
531dac ¤   PGPCFBSync (cfb);
299096 ¤   *error = kPGPError_NoErr;
4651e8 ¤   return cfb;
a1efe6 }
acaf5a
8338e5 /*
e17504 ·* Process one of the incoming annotations that's expected in response to
afaf76 ·* one of our own annotations. ·These can happen either during the
bd1a41 ·* ctx->tail->annotate() call, or after that call has returned an error
03b45a ·* to the top level, which makes the call in turn. ·Either way, we have
bf5d1b ·* to change state appropraitely.
3b775e ·*
2932ac ·* Currently, there are 4 things that can be done with any given packet:
765315 ·* - Eat it silently. ·No data will be emitted before the end scope
e914a4 ·* ··annotation.
6572ee ·* - Pass it through as ciphertext.
8c1a25 ·* - Decode it, and pass the body through as plaintext. The body is *not*
855edb ·* ··parsed further.
7882ab ·* - Decode it and parse it recursively.
5a775e ·*
fd9a67 ·* The latter two options depend on the type of packet we're inside, as
2690b8 ·* recorded in the ctx->end_scope variable. ·They do some special
e0a457 ·* processing setting up a pipeline to do the decoding, then everyone
ef9074 ·* appends another parser to the chain and sets things up to write the
f2cc28 ·* packet body to the decoding pipe.
20495d ·*/
3bf1ae static PGPError
922be4 ProcessCallback (PGPPipeline *myself, int type,
c01298 ·················PGPByte const *string, size_t size)
48bb36 {
2fa471 ¤   PrsBinContext *ctx = (PrsBinContext *)myself->priv;
57000e ¤   PGPPipeline *oldhead;
e3cfbe ¤   PGPCFBContext *cfb;
c35b01 ¤   PGPError¤   error = kPGPError_NoErr;
02e9fa ¤   PGPContextRef¤  cdkContext;
0f5f86 ····PGPMemoryMgrRef¤memoryMgr¤  = NULL;
e467c5 ¤
--634d 00026c1777640100197 Page 18 of pgpPrsBin.c
d93982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
30696e ¤   cdkContext¤ = myself->cdkContext;
851c1f ¤   memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
2daf5a
929f7a ¤   pgpAssert(ctx->needcallback);¤  /* Maybe a less nasty failure? */
93af5a
4156f9 ¤   pgpAssert(!ctx->end);¤  /* This will change in future, but for now */
d8af5a
192521 ¤   if (!ctx->end)
cdf93c ¤   ¤   ctx->end = &ctx->tail;
b89783 ¤   oldhead = *ctx->end;
fb1160 ¤   *ctx->end = NULL;
c0af5a
e60262 ¤   /* The other option is to make this illegal... */
a73c3a ¤   if (ctx->end_scope == PGPANN_NONPACKET_END &&
ccfcfd ············(type == PGPANN_PARSER_PROCESS || type == PGPANN_PARSER_RECURSE))
24d323 ¤   ¤   type = PGPANN_PARSER_PASSTHROUGH;
f2af5a
10841a ¤   /* Type will ONLY be one of these! */
611609 ¤   switch (type) {
2d319d ¤   case PGPANN_PARSER_EATIT:
8494e0 ¤   ¤   myself->write = DoSkip;
402f68 ¤   ¤   break;
6081b3 ¤   case PGPANN_PARSER_PASSTHROUGH:
fc33e8 ¤   ¤   if (ctx->end_scope == PGPANN_PGPKEY_END) {
06a16f ¤   ¤   ¤   /* Passthrough is unreasonable on keys */
56dbd0 ¤   ¤   ¤   type = PGPANN_PARSER_PROCESS;
67cdcb ¤   ¤   ¤   break;
930fe4 ¤   ¤   }
c5540b ¤   ¤   ctx->end = pgpHeaderCreate ( myself->cdkContext, ctx->end);
4036e2 ¤   ¤   if (!ctx->end) {
16becd ¤   ¤   ¤   error = kPGPError_OutOfMemory;
e8cdcb ¤   ¤   ¤   break;
370fe4 ¤   ¤   }
fd9675 ¤   ¤   myself->write = DoPassthrough;
af2f68 ¤   ¤   break;
bd1bb8 ¤   case PGPANN_PARSER_PROCESS:
777b34 ¤   case PGPANN_PARSER_RECURSE:
b0342c ¤   ¤   switch (ctx->end_scope) {
3db31a ¤   ¤   case PGPANN_LITERAL_END:
1a4e62 ¤   ¤   ¤   if (type == PGPANN_PARSER_PROCESS &&
fbf9ea ¤   ¤   ¤   ¤   ctx->subtype == PGP_LITERAL_RECURSE) {
936cfb ¤   ¤   ¤   ¤   /* Decided not to recurse, fixup subtype and type */
f48299 ¤   ¤   ¤   ¤   type = PGPANN_PARSER_RECURSE;
3427fa ¤   ¤   ¤   ¤   ctx->subtype = PGP_LITERAL_TEXT;
88a304 ¤   ¤   ¤   ¤   error = oldhead->annotate (oldhead, myself,
7ab6bf ¤   ¤   ······························PGPANN_LITERAL_TYPE, &ctx->subtype, 1);
53a3a6 ¤   ¤   ¤   }
3e0808 ¤   ¤   ¤   if (type == PGPANN_PARSER_RECURSE &&
cde986 ¤   ¤   ¤   ····ctx->subtype == PGP_LITERAL_TEXT) {
36b44d ¤   ¤   ¤   ¤   PGPByte const *charmap;
fd7399 ¤   ¤   ¤   ¤   PGPLineEndType lineEnd = pgpGetDefaultLineEndType();
c67cbe ¤   ¤   ¤   ¤   charmap = (PGPByte const *)
03c49b ¤   ¤   ¤   ¤   ¤   pgpenvGetPointer
3a020d ¤   ¤   ¤   ¤   ¤   (ctx->env, PGPENV_CHARMAPTOLOCAL, NULL);
3cc96c ¤   ¤   ¤   ¤   /* Recurse means filter the text */
ff41a3 ¤   ¤   ¤   ¤   ctx->end = pgpTextFiltCreate ( myself->cdkContext,
68dd34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ctx->end, ·charmap, ·0, lineEnd );
45b9e9 ¤   ¤   ¤   ¤   if (!ctx->end) {
76f7e7 ¤   ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
8b14c3 ¤   ¤   ¤   ¤   ¤   break;
242613 ¤   ¤   ¤   ¤   }
372dad ¤   ¤   ¤   } else if (type == PGPANN_PARSER_RECURSE &&
6ea48d ¤   ¤   ¤   ¤   ¤   ···ctx->subtype == PGP_LITERAL_RECURSE) {
cea59d ¤   ¤   ¤   ¤   /* Want to recurse inside literal packet */
0f3527 ¤   ¤   ¤   ¤   PGPPipeline **temp = ctx->end;
ab727f ¤   ¤   ¤   ¤   PGPBoolean trueflag = TRUE;
7eaf5a
97f8b4 ¤   ¤   ¤   ¤   ctx->end = pgpParseAscCreate ( myself->cdkContext,
39cf9c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ctx->end, ctx->env, &pgpByteFifoDesc,
000c92 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ctx->ui, ctx->ui_arg );
2674cf ¤   ¤   ¤   ¤   ctx->nextparser = *temp;
--c672 000d4d4fcec40100197 Page 19 of pgpPrsBin.c
03b9e9 ¤   ¤   ¤   ¤   if (!ctx->end) {
6cf7e7 ¤   ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
9e14c3 ¤   ¤   ¤   ¤   ¤   break;
9e2613 ¤   ¤   ¤   ¤   }
00fbb8 ¤   ¤   ¤   ¤   /* Chain end of pipeline so can do annotation */
4956e6 ¤   ¤   ¤   ¤   *(ctx->end) = oldhead;
f36ce4 ¤   ¤   ¤   ¤   ctx->needcallback--;
818407 ¤   ¤   ¤   ¤   /* Set ascii armor to passthroughclearsign mode */
4412d3 ¤   ¤   ¤   ¤   ctx->nextparser->annotate( ctx->nextparser, NULL,
86f2b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPANN_PASSTHROUGH_CLEARSIGN,
9e8bf9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&trueflag, 1 );
0f1da5 ¤   ¤   ¤   ¤   inputPurge(&ctx->input);
e8369e ¤   ¤   ¤   ¤   myself->write = DoWrite;
fbb20f ¤   ¤   ¤   ¤   return error;
52a3a6 ¤   ¤   ¤   }
cbdbd0 ¤   ¤   ¤   type = PGPANN_PARSER_PROCESS;
eacdcb ¤   ¤   ¤   break;
bb102a ¤   ¤   case PGPANN_CIPHER_END:
df5a8a ¤   ¤   ¤   cfb = CheckKey (myself->cdkContext, ctx, string, size, &error);
b411b9 ¤   ¤   ¤   if (!cfb)
47f622 ¤   ¤   ¤   ¤   break;
fe67da ¤   ¤   ¤   ctx->end = pgpCipherModDecryptCreate ( myself->cdkContext,
a0a4e2 ¤   ¤   ¤   ¤   ctx->end, cfb, ctx->env);
b3fc29 ¤   ¤   ¤   if (!ctx->end)
c92f55 ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
6acdcb ¤   ¤   ¤   break;
e2cfe9 ¤   ¤   case PGPANN_COMPRESSED_END:
7f5fd2 ¤   ¤   ¤   ctx->end = pgpDecompressModCreate ( cdkContext, ctx->end,
e92a12 ¤   ¤   ¤   ¤   ¤   ·········*inputMergedPtr(&ctx->input), &error);
64cdcb ¤   ¤   ¤   break;
51bc4a ¤   ¤   case PGPANN_COMMENT_END:
a0b0ea ¤   ¤   case PGPANN_UNKNOWN_END:
4ddbd0 ¤   ¤   ¤   type = PGPANN_PARSER_PROCESS;
f6cdcb ¤   ¤   ¤   break;
595a4e ¤   ¤   case PGPANN_SIGNED_END:
105b34 ¤   ¤   {
281b56 ¤   ¤   ¤   PGPUInt32¤  numHashes¤  =0;
1f87c7 ¤   ¤   ¤
66f638 ¤   ¤   ¤   if (ctx->nextparser)
68e215 ¤   ¤   ¤   ¤   type = PGPANN_PARSER_PROCESS;
3f095d ¤   ¤   ¤   /* Set up all requested hashes */
1ce194 ¤   ¤   ¤   pgpAssert(!ctx->hashes);
fc23ba ¤   ¤   ¤   if (!size)
2af6e9 ¤   ¤   ¤   ¤   return kPGPError_NoErr;
353200 ¤   ¤   ¤   /* Get all the PgpHashContexts */
5b3708 ¤   ¤   ¤   error = (PGPError)pgpHashListCreate ( memoryMgr,
df43da ¤   ¤   ¤   ¤   string, &ctx->hashes, size);
0aded1 ¤   ¤   ¤   if ( IsPGPError( error ) )
39f622 ¤   ¤   ¤   ¤   break;
1ab9e4 ¤   ¤   ¤   numHashes¤  = pgpHashListGetSize( ctx->hashes );
b0e54c ¤   ¤   ¤   /* Make a pipeline out of them */
a1bb84 ¤   ¤   ¤   ctx->end = pgpHashModListCreate ( cdkContext,
e1f08d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ctx->end, ·ctx->hashes, numHashes);
5a02bf ¤   ¤   ¤   if (!ctx->end) {
91a52b ¤   ¤   ¤   ¤   pgpHashListDestroy (ctx->hashes );
393ec1 ¤   ¤   ¤   ¤   ctx->hashes = NULL;
5f2f55 ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
7ef622 ¤   ¤   ¤   ¤   break;
14a3a6 ¤   ¤   ¤   }
63a897 ¤   ¤   ¤   pgpAssert(inputFinished(&ctx->input.head));
2b1fab ¤   ¤   ¤   ctx->input.head.pktlen = (PGPUInt32)-1l; /* Write through rest */
e00ebe ¤   ¤   ¤   ctx->input.silent_trunc = 1;
12007f ¤   ¤   ¤   error = kPGPError_NoErr;
b6cdcb ¤   ¤   ¤   break;
de0fe4 ¤   ¤   }
70af5a
a06b44 ¤   ¤   case PGPANN_PGPKEY_END:
61dbd0 ¤   ¤   ¤   type = PGPANN_PARSER_PROCESS;
24cdcb ¤   ¤   ¤   break;
569ae3 ¤   ¤   default:
55d03e ¤   ¤   ¤   error = kPGPError_BadParams;
d40fe4 ¤   ¤   }
--b873 000f023b18b40100197 Page 20 of pgpPrsBin.c
e0af5a
f61b17 ¤   ¤   /*
fcc65e ¤   ¤   ·* Processing for all packet types... set up parser if
8f15b8 ¤   ¤   ·* desired, then skip any header prifix in the buffer,
fea188 ¤   ¤   ·* then arrange to write out what we have.
259de3 ¤   ¤   ·*/
62b010 ¤   ¤   /* If we want to create a parser, do that */
fa17fb ¤   ¤   if (!error && type == PGPANN_PARSER_RECURSE) {
fca4bf ¤   ¤   ¤   PGPPipeline **temp = ctx->end;
4daf5a
18e86b ¤   ¤   ¤   ctx->end = pgpParseBinCreate ( myself->cdkContext,
6bb16a ¤   ¤   ¤   ¤   ¤   ¤   ctx->end, ctx->env, ctx->ui, ctx->ui_arg);
56fc29 ¤   ¤   ¤   if (!ctx->end)
b82f55 ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
4a7122 ¤   ¤   ¤   ctx->nextparser = *temp;
970fe4 ¤   ¤   }
7e5191 ¤   ¤   if (!error && type == PGPANN_PARSER_PROCESS) {
2aec66 ¤   ¤   ¤   /* Add a header if appropriate */
d8db5f ¤   ¤   ¤   switch (ctx->end_scope) {
da9bd6 ¤   ¤   ¤   case PGPANN_CIPHER_END:
ed0abc ¤   ¤   ¤   case PGPANN_COMPRESSED_END:
edd1b2 ¤   ¤   ¤   case PGPANN_SIGNED_END:
430175 ¤   ¤   ¤   ¤   ctx->end = pgpHeaderCreate ( myself->cdkContext, ctx->end);
fae801 ¤   ¤   ¤   ¤   if (!ctx->end)
fdf7e7 ¤   ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
47a3a6 ¤   ¤   ¤   }
770fe4 ¤   ¤   }
3d60b2 ¤   ¤   /* Success! ·Flush data and write through the rest */
8647b6 ¤   ¤   if (!error) {
03ffb5 ¤   ¤   ¤   if (ctx->end_scope == PGPANN_SIGNED_END) {
0271b7 ¤   ¤   ¤   ¤   if (ctx->state >= 10)
9ff18e ¤   ¤   ¤   ¤   ¤   myself->write = DoSignedLiteralMagic;
c2bffd ¤   ¤   ¤   ¤   else if (ctx->sig1pass)
d5721f ¤   ¤   ¤   ¤   ¤   myself->write = DoWriteSignedPackets;
f7deaa ¤   ¤   ¤   ¤   else {
161b1d ¤   ¤   ¤   ¤   ¤   inputPurge(&ctx->input);
c13026 ¤   ¤   ¤   ¤   ¤   myself->write = DoWrite;
232613 ¤   ¤   ¤   ¤   }
b9042d ¤   ¤   ¤   } else {
246df3 ¤   ¤   ¤   ¤   if (ctx->end_scope == PGPANN_PGPKEY_END)
f9d3d9 ¤   ¤   ¤   ¤   ¤   myself->write = parseKey;
0ddeaa ¤   ¤   ¤   ¤   else {
e71b1d ¤   ¤   ¤   ¤   ¤   inputPurge(&ctx->input);
af3026 ¤   ¤   ¤   ¤   ¤   myself->write = DoWrite;
de2613 ¤   ¤   ¤   ¤   }
6ca3a6 ¤   ¤   ¤   }
f5cdcb ¤   ¤   ¤   break;
0b0fe4 ¤   ¤   }
472f68 ¤   ¤   break;
642f72 ¤   default:
63d5d3 ¤   ¤   error = kPGPError_BadParams;
529371 ¤   }
09af5a
80a673 ¤   if (error) {
cc5921 ¤   ¤   /* Get rid of partial pipelines (if any) */
c39834 ¤   ¤   if (IsNull(ctx->end) ·|| ·IsNull(*(ctx->end)))
83efa4 ¤   ¤   ¤   ctx->end = &oldhead;
a84baa ¤   ¤   parsePipelineTeardown (ctx);
55f037 ¤   } else {
40356d ¤   ¤   /* Splice the new into the old */
6e9b6a ¤   ¤   *(ctx->end) = oldhead;
71eada ¤   ¤   ctx->needcallback--;
479371 ¤   }
e3af5a
23c674 ¤   return error;
93efe6 }
97af5a
435d09 static size_t
85e37d parseLiteral (PGPPipeline *myself, PGPByte const *buf, size_t size,
8f18d1 ¤   ¤   PGPError *error)
99bb36 {
f0e07e ¤   PrsBinContext *ctx;
--2e0d 000a05593e140100197 Page 21 of pgpPrsBin.c
bbf20c ¤   size_t len;
f26d88 ¤   size_t size0 = size;
f58b0f ¤   PGPByte const *p;
2daf5a
c129be ¤   pgpAssert (myself);
7570c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
4d4866 ¤   pgpAssert (error);
20af5a
c28808 ¤   ctx = (PrsBinContext *)myself->priv;
63d6bc ¤   pgpAssert (ctx);
771728 ¤   pgpAssert (ctx->tail);
442aee ¤   pgpAssert (!size || !ctx->eof);
d7af5a
db9096 ¤   *error = kPGPError_NoErr;
e0af5a
3e6f5c ¤   switch (ctx->state) {
97f86f ¤   case 0:
8779c5 ¤   case 10:¤   /* flags oldliteral, where length doesn't include prefix */
cc419b ¤   ¤   ¤   ¤   /* may also be pgpHeader.c packet, type 'P' */
ab1db7 ¤   ¤   /* Parse header; needed before callbacks are allowed */
70bfe8 ¤   ¤   ctx->beginlength = 0;
e8dc25 ¤   ¤   len = inputMerge(&ctx->input, buf, size, 2, error);
6be14c ¤   ¤   buf += len;
07e2d5 ¤   ¤   size -= len;
bb4802 ¤   ¤   if (*error || !size)
becdcb ¤   ¤   ¤   break;
383814 ¤   ¤   /* Size is non-zero but we haven't got desired? ·EOP */
c409b5 ¤   ¤   if (inputMerged(&ctx->input) < 2) {
85a897 ¤   ¤   ¤   pgpAssert(inputFinished(&ctx->input.head));
f3db9d ¤   ¤   ¤   *error = ctx->tail->annotate(ctx->tail, myself,
dd2395 ¤   ¤   ¤   ·····························PGPANN_PACKET_SHORT,
b23f22 ¤   ¤   ¤   ¤   ¤   ¤   ·····0, 0);
c8b5c5 ¤   ¤   ¤   if (*error)
2bf622 ¤   ¤   ¤   ¤   break;
b528dd ¤   ¤   ¤   myself->write = nextScope;
4f819b ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
5fcdcb ¤   ¤   ¤   break;
560fe4 ¤   ¤   }
d3696f ¤   ¤   p = inputMergedPtr(&ctx->input);
5e3889 ¤   ¤   /* Deal with "oldliteral" packets specially */
7846b1 ¤   ¤   if (ctx->state == 10) {
6bc1a2 ¤   ¤   ¤   if (p[0] == 'P') {
63a684 ¤   ¤   ¤   ¤   /* Special PGP 3 header */
34da49 ¤   ¤   ¤   ¤   myself->write = DoSkip;
4396f2 ¤   ¤   ¤   ¤   size -= DoSkip (myself, buf, size, error);
34f622 ¤   ¤   ¤   ¤   break;
2da3a6 ¤   ¤   ¤   }
88a5b0 ¤   ¤   ¤   /* Else old-style packets; some PGPcompatible program does these */
497aad ¤   ¤   ¤   /*
349675 ¤   ¤   ¤   ·* That program uses "literal" length conventions, not
d2a349 ¤   ¤   ¤   ·* "oldliteral", so don't do this:
cd3516 ¤   ¤   ¤   ·*
13cedd ¤   ¤   ¤   ·* if (ctx->input.head.pktlen != ~0UL) {
c6ab0e ¤   ¤   ¤   ·* ··ctx->input.head.pktlen += 6 + p[1];
be38c8 ¤   ¤   ¤   ·* }
958753 ¤   ¤   ¤   ·*/
09173d ¤   ¤   ¤   ctx->state = 0;
b50fe4 ¤   ¤   }
a86f85 ¤   ¤   /* Get the name and timestamp fields */
a3c4c9 ¤   ¤   len = inputMerge(&ctx->input, buf, size, 6+p[1], error);
2ce14c ¤   ¤   buf += len;
70e2d5 ¤   ¤   size -= len;
06e966 ¤   ¤   /* Size may be zero here if output file is zero length */
c6cf31 ¤   ¤   if (*error)
01cdcb ¤   ¤   ¤   break;
b08d70 ¤   ¤   if (inputMerged(&ctx->input) < (unsigned)6+p[1]) {
6c14f7 ¤   ¤   ¤   if( size == 0 )
cdf622 ¤   ¤   ¤   ¤   break;
d6057a ¤   ¤   ¤   /* Size is non-zero but we haven't got desired? ·EOP */
b5a897 ¤   ¤   ¤   pgpAssert(inputFinished(&ctx->input.head));
9cdb9d ¤   ¤   ¤   *error = ctx->tail->annotate(ctx->tail, myself,
a02395 ¤   ¤   ¤   ·····························PGPANN_PACKET_SHORT,
--c5d3 000f6b037f340100197 Page 22 of pgpPrsBin.c
2e3f22 ¤   ¤   ¤   ¤   ¤   ¤   ·····0, 0);
7fb5c5 ¤   ¤   ¤   if (*error)
76f622 ¤   ¤   ¤   ¤   break;
e428dd ¤   ¤   ¤   myself->write = nextScope;
bc819b ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
d6cdcb ¤   ¤   ¤   break;
9a0fe4 ¤   ¤   }
44af5a
3d6a4c ¤   ¤   ctx->subtype = p[0];
193a6c ¤   ¤   ctx->needcallback = 1;
5e660a ¤   ¤   ctx->end_scope = PGPANN_LITERAL_END;
234adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
8df220 ¤   ¤   ······························PGPANN_LITERAL_BEGIN, 0, 0);
49cf31 ¤   ¤   if (*error)
c0cdcb ¤   ¤   ¤   break;
18af5a
6cdeb7 ¤   ¤   ctx->state++;
188224 ¤   ¤   /* FALLTHROUGH */
eba2b3 ¤   case 1:
9f696f ¤   ¤   p = inputMergedPtr(&ctx->input);
f24252 ¤   ¤   if (ctx->subtype == PGP_LITERAL_TEXT) {
c4c420 ¤   ¤   ¤   /* See if looks like PGP message, set as RECURSE type */
afd109 ¤   ¤   ¤   len = inputMerge(&ctx->input, buf, size,
949980 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·6+p[1]+sizeof(pgp_message_begin)-1, error);
569bb8 ¤   ¤   ¤   buf += len;
015304 ¤   ¤   ¤   size -= len;
6cb5c5 ¤   ¤   ¤   if (*error)
a6f622 ¤   ¤   ¤   ¤   break;
da396a ¤   ¤   ¤   if (inputMerged(&ctx->input) < 6+p[1]+sizeof(pgp_message_begin)-1){
032890 ¤   ¤   ¤   ¤   /* Get more data if not enough to check */
9061ff ¤   ¤   ¤   ¤   if (!inputFinished(&ctx->input.head))
a114c3 ¤   ¤   ¤   ¤   ¤   break;
76042d ¤   ¤   ¤   } else {
beb633 ¤   ¤   ¤   ¤   if (memcmp (p+p[1]+6, pgp_message_begin,
0367c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(pgp_message_begin)-1) == 0) {
be2c8e ¤   ¤   ¤   ¤   ¤   /* Looks like PGP message, set type as RECURSE */
cdb99f ¤   ¤   ¤   ¤   ¤   ctx->subtype = PGP_LITERAL_RECURSE;
ca2613 ¤   ¤   ¤   ¤   }
bca3a6 ¤   ¤   ¤   }
21b7ab ¤   ¤   ¤   ctx->beginlength = inputMerged(&ctx->input) - (p[1]+6);
7c17b7 ¤   ¤   ¤   pgpAssert (ctx->beginlength <= sizeof(ctx->beginline));
b9c7a2 ¤   ¤   ¤   pgpCopyMemory (p+p[1]+6, ctx->beginline, ctx->beginlength);
4a0fe4 ¤   ¤   }
1d4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
c9b6bf ¤   ¤   ······························PGPANN_LITERAL_TYPE, &ctx->subtype, 1);
9ccf31 ¤   ¤   if (*error)
39cdcb ¤   ¤   ¤   break;
be1b52 ¤   ¤
1cdeb7 ¤   ¤   ctx->state++;
c58224 ¤   ¤   /* FALLTHROUGH */
6f4dd7 ¤   case 2:
31696f ¤   ¤   p = inputMergedPtr(&ctx->input);
244adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
ae551b ¤   ¤   ······························PGPANN_LITERAL_NAME,
5cab2b ¤   ¤   ······························p+2, (size_t)p[1]);
71cf31 ¤   ¤   if (*error)
e0cdcb ¤   ¤   ¤   break;
7aaf5a
dbdeb7 ¤   ¤   ctx->state++;
d48224 ¤   ¤   /* FALLTHROUGH */
84170b ¤   case 3:
d9f3e1 ¤   ¤   /* Parse 4-byte timestamp */
fa696f ¤   ¤   p = inputMergedPtr(&ctx->input);
c94adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
2fc706 ¤   ¤   ······························PGPANN_LITERAL_TIMESTAMP,
bdbb92 ¤   ¤   ······························p+2+p[1], 4);
b5cf31 ¤   ¤   if (*error)
5fcdcb ¤   ¤   ¤   break;
22af5a
64deb7 ¤   ¤   ctx->state++;
398224 ¤   ¤   /* FALLTHROUGH */
f69b0e ¤   case 4:
--adb4 0004fefc29240100197 Page 23 of pgpPrsBin.c
9e4607 ¤   ¤   if (ctx->needcallback) {
8d6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
061d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
c2b5c5 ¤   ¤   ¤   if (*error)
2df622 ¤   ¤   ¤   ¤   break;
cd0fe4 ¤   ¤   }
09deb7 ¤   ¤   ctx->state++;
198224 ¤   ¤   /* FALLTHROUGH */
f1c1d2 ¤   case 5:
da4607 ¤   ¤   if (ctx->needcallback) {
d6b0dc ¤   ¤   ¤   *error = ProcessCallback (myself,
e146e5 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPANN_PARSER_PROCESS,
b679cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
7ab5c5 ¤   ¤   ¤   if (*error)
5af622 ¤   ¤   ¤   ¤   break;
e30fe4 ¤   ¤   }
2fdeb7 ¤   ¤   ctx->state++;
2fdc54 ¤   ¤   /* Zero length files don't produce output, do an extra write here */
9e525c ¤   ¤   if( myself->write == DoWrite && (size+ctx->beginlength) == 0 ) {
dd0290 ¤   ¤   ¤   ctx->tail->write( ctx->tail, buf, 0, error );
d30fe4 ¤   ¤   }
75cf31 ¤   ¤   if (*error)
0fcdcb ¤   ¤   ¤   break;
d68cc8 ¤   ¤   /* Write any chars we peeked-ahead above */
99e28c ¤   ¤   ctx->input.head.pktlen += ctx->beginlength;¤/* counted this already */
e7da87 ¤   ¤   len = myself->write(myself, ctx->beginline, ctx->beginlength, error);
96cf31 ¤   ¤   if (*error)
71cdcb ¤   ¤   ¤   break;
76104e ¤   ¤   /* We assume it will accept them all! */
0ae82f ¤   ¤   pgpAssert(len == ctx->beginlength);
214585 ¤   ¤   /* Write remaining chars from buf */
feb0a1 ¤   ¤   size -= myself->write(myself, buf, size, error);
2e2f68 ¤   ¤   break;
172f72 ¤   default:
13cc7c ¤   ¤   pgpAssert (0);¤ /* I should never get here */
4a9371 ¤   }
91af5a
1e3084 ¤   return size0-size;
a2efe6 }
b6af5a
675d09 static size_t
339648 parseCipher (PGPPipeline *myself, PGPByte const *buf, size_t size,
11fb43 ¤   ·····PGPError *error)
e6bb36 {
5ae07e ¤   PrsBinContext *ctx;
61a371 ¤   size_t written = 0;
43af5a
5229be ¤   pgpAssert (myself);
2e70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
004866 ¤   pgpAssert (error);
08af5a
478808 ¤   ctx = (PrsBinContext *)myself->priv;
4ed6bc ¤   pgpAssert (ctx);
e71728 ¤   pgpAssert (ctx->tail);
202aee ¤   pgpAssert (!size || !ctx->eof);
91af5a
ed9096 ¤   *error = kPGPError_NoErr;
e6af5a
046f5c ¤   switch (ctx->state) {
92f86f ¤   case 0:
e11db7 ¤   ¤   /* Parse header; needed before callbacks are allowed */
49dd21 ¤   ¤   written = inputMerge(&ctx->input, buf, size, IVLEN, error);
87d06f ¤   ¤   buf += written;
5d28a7 ¤   ¤   size -= written;
954802 ¤   ¤   if (*error || !size)
91cdcb ¤   ¤   ¤   break;
a73814 ¤   ¤   /* Size is non-zero but we haven't got desired? ·EOP */
41247f ¤   ¤   if (inputMerged(&ctx->input) < IVLEN) {
9aa897 ¤   ¤   ¤   pgpAssert(inputFinished(&ctx->input.head));
4adb9d ¤   ¤   ¤   *error = ctx->tail->annotate(ctx->tail, myself,
d72395 ¤   ¤   ¤   ·····························PGPANN_PACKET_SHORT,
4f3f22 ¤   ¤   ¤   ¤   ¤   ¤   ·····0, 0);
--d5ec 000974da91940100197 Page 24 of pgpPrsBin.c
5bb5c5 ¤   ¤   ¤   if (*error)
bcf622 ¤   ¤   ¤   ¤   break;
3a28dd ¤   ¤   ¤   myself->write = nextScope;
92819b ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
d6cdcb ¤   ¤   ¤   break;
4d0fe4 ¤   ¤   }
0baf5a
0b3a6c ¤   ¤   ctx->needcallback = 1;
a7af5a
b61b17 ¤   ¤   /*
e6e413 ¤   ¤   ·* If we're already in an encrypted scope (we've already
0f0b4c ¤   ¤   ·* sent some ESKs to the user), don't bother sending another
f54000 ¤   ¤   ·* one.
f99de3 ¤   ¤   ·*/
b97e7c ¤   ¤   if (ctx->end_scope) {¤  /* Scope alreay open? */
39a285 ¤   ¤   ¤   ctx->state = 2;
374e12 ¤   ¤   ¤   goto got_esk;
7a0fe4 ¤   ¤   }
76f195 ¤   ¤   /* No ESKs seen yet - open the scope */
1e9d98 ¤   ¤   ctx->end_scope = PGPANN_CIPHER_END;
5c4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
97576d ¤   ¤   ······························PGPANN_CIPHER_BEGIN, 0, 0);
9dcf31 ¤   ¤   if (*error)
5ecdcb ¤   ¤   ¤   break;
46af5a
f1deb7 ¤   ¤   ctx->state++;
538224 ¤   ¤   /* FALLTHROUGH */
aaa2b3 ¤   case 1:
c558d0 ¤   ¤   /* No ESKs seen yet - dummy one up */
084adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
083a92 ¤   ¤   ······························PGPANN_SKCIPHER_ESK, 0, 0);
29cf31 ¤   ¤   if (*error)
5acdcb ¤   ¤   ¤   break;
3aaf5a
21deb7 ¤   ¤   ctx->state++;
428224 ¤   ¤   /* FALLTHROUGH */
e94dd7 ¤   case 2:
c8a9ec ¤   got_esk:
9f6d7a ¤   ¤   /* Okay, do a commit */
b84607 ¤   ¤   if (ctx->needcallback) {
126c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
0b1d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
f4b5c5 ¤   ¤   ¤   if (*error)
c1f622 ¤   ¤   ¤   ¤   break;
1b0fe4 ¤   ¤   }
20deb7 ¤   ¤   ctx->state++;
958224 ¤   ¤   /* FALLTHROUGH */
20170b ¤   case 3:
034607 ¤   ¤   if (ctx->needcallback) {
6fb0dc ¤   ¤   ¤   *error = ProcessCallback (myself,
f438bd ¤   ¤   ¤   ¤   ¤   ¤   ··PGPANN_PARSER_PASSTHROUGH,
fd79cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
f1b5c5 ¤   ¤   ¤   if (*error)
c7f622 ¤   ¤   ¤   ¤   break;
650fe4 ¤   ¤   }
8bdeb7 ¤   ¤   ctx->state++;
2eb770 ¤   ¤   written += myself->write(myself, buf, size, error);
da2f68 ¤   ¤   break;
5b2f72 ¤   default:
cb9132 ¤   ¤   pgpAssert (0);
139371 ¤   }
72af5a
0a279e ¤   return written;
36efe6 }
4baf5a
ab5d09 static size_t
3f15ac parseCompressed (PGPPipeline *myself, PGPByte const *buf, size_t size,
5a70bc ¤   ¤   ·PGPError *error)
34bb36 {
49e07e ¤   PrsBinContext *ctx;
9fa371 ¤   size_t written = 0;
97af5a
--9fe5 0002060e38b40100197 Page 25 of pgpPrsBin.c
c629be ¤   pgpAssert (myself);
7770c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
1c4866 ¤   pgpAssert (error);
e8af5a
4e8808 ¤   ctx = (PrsBinContext *)myself->priv;
4ad6bc ¤   pgpAssert (ctx);
381728 ¤   pgpAssert (ctx->tail);
462aee ¤   pgpAssert (!size || !ctx->eof);
9faf5a
e29096 ¤   *error = kPGPError_NoErr;
18af5a
756f5c ¤   switch (ctx->state) {
19f86f ¤   case 0:
70612b ¤   ¤   /* Make sure we have the compression type */
a21a0d ¤   ¤   written = inputMerge(&ctx->input, buf, size, 1, error);
ebd06f ¤   ¤   buf += written;
9b28a7 ¤   ¤   size -= written;
d64802 ¤   ¤   if (*error || !size)
0ccdcb ¤   ¤   ¤   break;
da3814 ¤   ¤   /* Size is non-zero but we haven't got desired? ·EOP */
351479 ¤   ¤   if (inputMerged(&ctx->input) < 1) {
b3a897 ¤   ¤   ¤   pgpAssert(inputFinished(&ctx->input.head));
fadb9d ¤   ¤   ¤   *error = ctx->tail->annotate(ctx->tail, myself,
782395 ¤   ¤   ¤   ·····························PGPANN_PACKET_SHORT,
b73f22 ¤   ¤   ¤   ¤   ¤   ¤   ·····0, 0);
91b5c5 ¤   ¤   ¤   if (*error)
03f622 ¤   ¤   ¤   ¤   break;
3b28dd ¤   ¤   ¤   myself->write = nextScope;
eb819b ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
04cdcb ¤   ¤   ¤   break;
b70fe4 ¤   ¤   }
6daf5a
2e3a6c ¤   ¤   ctx->needcallback = 1;
ad7963 ¤   ¤   ctx->end_scope = PGPANN_COMPRESSED_END;
c74adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
38336f ¤   ¤   ······························PGPANN_COMPRESSED_BEGIN,
a155fa ¤   ¤   ······························inputMergedPtr(&ctx->input), 1);
b2cf31 ¤   ¤   if (*error)
06cdcb ¤   ¤   ¤   break;
bdaf5a
80deb7 ¤   ¤   ctx->state++;
448224 ¤   ¤   /* FALLTHROUGH */
99a2b3 ¤   case 1:
934607 ¤   ¤   if (ctx->needcallback) {
0d6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
d81d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
94b5c5 ¤   ¤   ¤   if (*error)
5bf622 ¤   ¤   ¤   ¤   break;
a30fe4 ¤   ¤   }
32deb7 ¤   ¤   ctx->state++;
2b8224 ¤   ¤   /* FALLTHROUGH */
d34dd7 ¤   case 2:
374607 ¤   ¤   if (ctx->needcallback) {
c9b0dc ¤   ¤   ¤   *error = ProcessCallback (myself,
d02669 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPANN_PARSER_RECURSE,
0079cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
b7b5c5 ¤   ¤   ¤   if (*error)
9af622 ¤   ¤   ¤   ¤   break;
b50fe4 ¤   ¤   }
f0deb7 ¤   ¤   ctx->state++;
45b770 ¤   ¤   written += myself->write(myself, buf, size, error);
5b2f68 ¤   ¤   break;
092f72 ¤   default:
db9132 ¤   ¤   pgpAssert (0);
829371 ¤   }
3eaf5a
be279e ¤   return written;
59efe6 }
c9af5a
8238e5 /*
50e18b ·* Parse a general headerless packet. ·Unknown packets, comment packets
20a04a ·* and, in fact, things that aren't packets at all!
--6af7 0004a487ecf40100197 Page 26 of pgpPrsBin.c
47495d ·*/
ff5d09 static size_t
54c1eb parseUnknown (PGPPipeline *myself, PGPByte const *buf, size_t size,
17a900 ¤   PGPError *error)
a7bb36 {
31e07e ¤   PrsBinContext *ctx;
0fa371 ¤   size_t written = 0;
dbffd4 ¤   PGPByte b;
67d172 ¤   int begintype;
c3af5a
7329be ¤   pgpAssert (myself);
f670c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
944866 ¤   pgpAssert (error);
bcaf5a
9c8808 ¤   ctx = (PrsBinContext *)myself->priv;
90d6bc ¤   pgpAssert (ctx);
1e1728 ¤   pgpAssert (ctx->tail);
6c2aee ¤   pgpAssert (!size || !ctx->eof);
d6af5a
999096 ¤   *error = kPGPError_NoErr;
e5af5a
3b6f5c ¤   switch (ctx->state) {
42f86f ¤   case 0:
dc1b17 ¤   ¤   /*
e55398 ¤   ¤   ·* As a convenience, we merge a leading prefix of the packet
bced8c ¤   ¤   ·* for identification purposes.
029de3 ¤   ¤   ·*/
ebd1ee ¤   ¤   written = inputMerge(&ctx->input, buf, size, 256, error);
8bd06f ¤   ¤   buf += written;
a828a7 ¤   ¤   size -= written;
bacf31 ¤   ¤   if (*error)
f2ab0f ¤   ¤   ¤   return written;
9f4ea9 ¤   ¤   if (inputMerged(&ctx->input) < 256 &&
d8d3e5 ¤   ¤   ····!inputFinished(&ctx->input.head))
ac5b34 ¤   ¤   {
8a87b9 ¤   ¤   ¤   pgpAssert(!size);
58ab0f ¤   ¤   ¤   return written;
d00fe4 ¤   ¤   }
9baf5a
e51b17 ¤   ¤   /*
4b76b2 ¤   ¤   ·* We use this one function to provide different
b5c3a7 ¤   ¤   ·* annotations for non-packets, comment packets, and
7990d6 ¤   ¤   ·* unknown packets. ·Figure out the right one to use.
209de3 ¤   ¤   ·*/
066212 ¤   ¤   b = ctx->input.buffer[0];
9fd81c ¤   ¤   if (!IS_OLD_PKTBYTE(b) && !IS_NEW_PKTBYTE(b)) {
c266bf ¤   ¤   ¤   begintype = PGPANN_NONPACKET_BEGIN;
21afcf ¤   ¤   ¤   ctx->end_scope = PGPANN_NONPACKET_END;
b241c4 ¤   ¤   } else if (PKTBYTE_TYPE (b) == PKTBYTE_COMMENT) {
c4edbf ¤   ¤   ¤   begintype = PGPANN_COMMENT_BEGIN;
fd3bc7 ¤   ¤   ¤   ctx->end_scope = PGPANN_COMMENT_END;
e145a6 ¤   ¤   } else {
a1882c ¤   ¤   ¤   begintype = PGPANN_UNKNOWN_BEGIN;
343767 ¤   ¤   ¤   ctx->end_scope = PGPANN_UNKNOWN_END;
a30fe4 ¤   ¤   }
e71b52 ¤   ¤
2b3a6c ¤   ¤   ctx->needcallback = 1;
461ddf ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself, begintype,
4d8c3e ¤   ¤   ······························inputMergedPtr(&ctx->input),
ad62b8 ¤   ¤   ······························inputMerged(&ctx->input));
e0cf31 ¤   ¤   if (*error)
6fcdcb ¤   ¤   ¤   break;
3aaf5a
fcdeb7 ¤   ¤   ctx->state++;
538224 ¤   ¤   /* FALLTHROUGH */
65a2b3 ¤   case 1:
074607 ¤   ¤   if (ctx->needcallback) {
5a6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
961d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
36b5c5 ¤   ¤   ¤   if (*error)
f4f622 ¤   ¤   ¤   ¤   break;
4a0fe4 ¤   ¤   }
--3f2e 000b16a2b7440100197 Page 27 of pgpPrsBin.c
78deb7 ¤   ¤   ctx->state++;
0a8224 ¤   ¤   /* FALLTHROUGH */
514dd7 ¤   case 2:
ef4607 ¤   ¤   if (ctx->needcallback) {
16df39 ¤   ¤   ¤   *error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
ff79cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
b6b5c5 ¤   ¤   ¤   if (*error)
61f622 ¤   ¤   ¤   ¤   break;
180fe4 ¤   ¤   }
b1deb7 ¤   ¤   ctx->state++;
82ff92 ¤   ¤   return written + myself->write(myself, buf, size, error);
ba6d15 ¤   ¤   /* NOTREACHED */
4b2f72 ¤   default:
649132 ¤   ¤   pgpAssert (0);
ec9371 ¤   }
f4af5a
9a279e ¤   return written;
c3efe6 }
24af5a
9138e5 /*
a0c125 ·* This is called for most all key-type packets. ·Keys are just output
cdcb68 ·* within a key annotation scope. ·There is no callback, since no
840f7e ·* processing is done.
bf495d ·*/
865d09 static size_t
ee7d4a parseKey (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
0cbb36 {
28e07e ¤   PrsBinContext *ctx;
4675b0 ¤   PGPPipeline *tail;
7f6d88 ¤   size_t size0 = size;
618b0f ¤   PGPByte const *p;
6df20c ¤   size_t len;
1eaf5a
cb29be ¤   pgpAssert (myself);
5770c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
324866 ¤   pgpAssert (error);
5baf5a
518808 ¤   ctx = (PrsBinContext *)myself->priv;
fdd6bc ¤   pgpAssert (ctx);
e6af5a
560097 ¤   tail = ctx->tail;
c3ac3e ¤   pgpAssert (tail);
e62aee ¤   pgpAssert (!size || !ctx->eof);
a1af5a
509096 ¤   *error = kPGPError_NoErr;
b0b079 ¤   if (ctx->end_scope && ctx->end_scope != PGPANN_PGPKEY_END) {
318243 ¤   ¤   /* Umm.. Key block within another scope??? Why??? */
db908a ¤   ¤   *error = kPGPError_WrongScope;
8bbbde ¤   ¤   return 0;
d59371 ¤   }
07af5a
073972 ¤   /* If we haven't output the begin annotation, do so now. */
d5d7a3 ¤   if (!ctx->end_scope) {
68bfa3 ¤   ¤   *error = tail->annotate (tail, myself, PGPANN_PGPKEY_BEGIN,
9c86e9 ¤   ¤   ¤   ¤   ¤   ·NULL, 0);
6dcf31 ¤   ¤   if (*error)
118144 ¤   ¤   ¤   return 0;
59af5a
8ae6f6 ¤   ¤   ctx->end_scope = PGPANN_PGPKEY_END;
01af5a
e38631 ¤   ¤   /* Set the flag to add a header module */
037799 ¤   ¤   ctx->needcallback++;
159371 ¤   }
c0af5a
ea4bd2 ¤   /* Make sure we only send the annotations once! */
fd6f5c ¤   switch (ctx->state) {
0df86f ¤   case 0:
011b17 ¤   ¤   /*
ba8154 ¤   ¤   ·* Ask the user what to do with these keys... ·Really,
efc915 ¤   ¤   ·* the only real answers are "EatIt" or "Process"..
bc451b ¤   ¤   ·* "Recurse" gets mapped to "Process", and
b1202f ¤   ¤   ·* "PassThrough" has the same effect. ·But let the
--c73a 0006614ec8440100197 Page 28 of pgpPrsBin.c
dd7eb5 ¤   ¤   ·* user decide, anyways. ·They may wish to eatit.
509de3 ¤   ¤   ·*/
b74607 ¤   ¤   if (ctx->needcallback) {
9d760e ¤   ¤   ¤   *error = tail->annotate (tail, myself, PGPANN_COMMIT,
e803a0 ¤   ¤   ¤   ¤   ¤   ¤   ·0, 0);
55b5c5 ¤   ¤   ¤   if (*error)
e246f1 ¤   ¤   ¤   ¤   return 0;
1e0fe4 ¤   ¤   }
97deb7 ¤   ¤   ctx->state++;
388224 ¤   ¤   /* FALLTHROUGH */
20a2b3 ¤   case 1:
ae4607 ¤   ¤   if (ctx->needcallback) {
f0b0dc ¤   ¤   ¤   *error = ProcessCallback (myself,
4c46e5 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPANN_PARSER_PROCESS,
8dfd10 ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, 0);
dab5c5 ¤   ¤   ¤   if (*error)
6846f1 ¤   ¤   ¤   ¤   return 0;
3c0fe4 ¤   ¤   }
219371 ¤   }
a0af5a
070e6d ¤   /* output this packet */
eeae80 ¤   /* empty out the buffered data and then the packet */
bc220e ¤   for (;;) {
4c3ef0 ¤   ¤   p = inputRawPeek(&ctx->input, buf, size, &len);
f1c1b1 ¤   ¤   if (!len)
aacdcb ¤   ¤   ¤   break;
1541ed ¤   ¤   len = tail->write (tail, p, len, error);
b2afd5 ¤   ¤   len = inputRawSeek (&ctx->input, buf, size, len);
12e14c ¤   ¤   buf += len;
3ce2d5 ¤   ¤   size -= len;
b4cf31 ¤   ¤   if (*error)
e6c64d ¤   ¤   ¤   return size0-size;
ef9371 ¤   }
7bd8af ¤   /*
1bba5f ¤   ·* If we've hit the end of the packet, check if we have
f9f0ee ¤   ·* another one. ·If so, check if it is a key certificate
f1277b ¤   ·* packet. ·If so, go parse the new packet. ·Otherwise, end
74804b ¤   ·* this scope.
b7651c ¤   ·* NOTE: This is not robust against the addition of new kinds of
79ae00 ¤   ·* key packets. ·We should instead assume that we are still in the
d79750 ¤   ·* keyring until we hit a known non-key packet, or we get an
1f7bc0 ¤   ·* annotation from the ascii armor parser that we are no longer
13fcf9 ¤   ·* in the same input block.
2ba4e3 ¤   ·*/
ac8dc4 ¤   if (inputFinished (&ctx->input.head) && (size || ctx->eof)) {
d46cd8 ¤   ¤   /* End of input */
89f72c ¤   ¤   if (size)
3e837d ¤   ¤   ¤   switch (PKTBYTE_TYPE (*buf)) {
25b9ee ¤   ¤   ¤   case PKTBYTE_SECKEY:
ce82dc ¤   ¤   ¤   case PKTBYTE_PUBKEY:
9919d8 ¤   ¤   ¤   case PKTBYTE_SECSUBKEY:
5c78c4 ¤   ¤   ¤   case PKTBYTE_PUBSUBKEY:
839459 ¤   ¤   ¤   case PKTBYTE_TRUST:
b7a95b ¤   ¤   ¤   case PKTBYTE_NAME:
648484 ¤   ¤   ¤   case PKTBYTE_ATTRIBUTE:
952d7f ¤   ¤   ¤   case PKTBYTE_SIG:
d9d17b ¤   ¤   ¤   case PKTBYTE_COMMENT:
a2a99a ¤   ¤   ¤   ¤   ctx->findpkt = 1;
ae8c95 ¤   ¤   ¤   ¤   myself->write = parsePacket;
a92fcd ¤   ¤   ¤   ¤   size -= parsePacket (myself, buf, size, error);
d1f622 ¤   ¤   ¤   ¤   break;
fcdb68 ¤   ¤   ¤   default:
f02691 ¤   ¤   ¤   ¤   myself->write = nextScope;
db639b ¤   ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
4ef622 ¤   ¤   ¤   ¤   break;
69a3a6 ¤   ¤   ¤   }
7807e0 ¤   ¤   else {
b528dd ¤   ¤   ¤   myself->write = nextScope;
ea819b ¤   ¤   ¤   size -= nextScope (myself, buf, size, error);
9f0fe4 ¤   ¤   }
129371 ¤   }
66af5a
--3a0c 0007cf2a69d40100197 Page 29 of pgpPrsBin.c
c03084 ¤   return size0-size;
bbefe6 }
c0af5a
f91fbb /* Shared entry point for 1-pass and old-style sig header parsing */
335d09 static size_t
466051 parseSignature (PGPPipeline *myself, PGPByte const *buf, size_t size,
e918d1 ¤   ¤   PGPError *error)
d9bb36 {
14e07e ¤   PrsBinContext *ctx;
c4a371 ¤   size_t written = 0;
2aaf5a
1529be ¤   pgpAssert (myself);
b570c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
2c4866 ¤   pgpAssert (error);
92af5a
bb8808 ¤   ctx = (PrsBinContext *)myself->priv;
a8d6bc ¤   pgpAssert (ctx);
6d1728 ¤   pgpAssert (ctx->tail);
152aee ¤   pgpAssert (!size || !ctx->eof);
b9af5a
5a6f5c ¤   switch (ctx->state) {
4af86f ¤   case 0:
8972dd ¤   ¤   /* Suck in the whole packet */
c7af5a
e207e2 ¤   ¤   written = inputMerge(&ctx->input, buf, size, (unsigned)-1, error);
83d06f ¤   ¤   buf += written;
2f28a7 ¤   ¤   size -= written;
71af5a
931b17 ¤   ¤   /*
077d58 ¤   ¤   ·* Proceed with our key signature test if finished or overfull;
5cd20d ¤   ¤   ·* we can handle oversized sigs in keyrings as we're just passing
67f73c ¤   ¤   ·* them through.
3e9de3 ¤   ¤   ·*/
80fc7f ¤   ¤   if ( !( inputFinished(&ctx->input.head) ||
ec3fe1 ¤   ¤   ¤   ¤   inputOverfull(&ctx->input) ) )
3bab0f ¤   ¤   ¤   return written;
ecaf5a
3971d8 ¤   ¤   /* We need at least one byte of look-ahead for next test */
b6d672 ¤   ¤   if (!size && !ctx->eof)
d3ab0f ¤   ¤   ¤   return written;
c2af5a
f5b69d ¤   ¤   /* Check if this is a key signature */
e25b34 ¤   ¤   {
2096d9 ¤   ¤   ¤   int type;
97af5a
507527 ¤   ¤   ¤   type = pgpSigSigType (inputMergedPtr (&ctx->input),
6ef00b ¤   ¤   ¤   ¤   ¤   ······inputMerged(&ctx->input));
5d9239 ¤   ¤   ¤   if (type < 0) {
3302e8 ¤   ¤   ¤   ¤   *error = (PGPError)type;
dc0651 ¤   ¤   ¤   ¤   return written;
58a3a6 ¤   ¤   ¤   }
20af5a
ae3564 ¤   ¤   ¤   if (type & 0xF0) {
2b0dd5 ¤   ¤   ¤   ¤   /* This is a key signature */
65ea1c ¤   ¤   ¤   ¤   myself->write = parseKey;
02c1be ¤   ¤   ¤   ¤   return written + parseKey (myself, buf, size,
957a32 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···error);
e8a3a6 ¤   ¤   ¤   }
acaf5a
5ac8fc ¤   ¤   ¤   /* A buggy keyring could have a non-key signature in it.
28b31a ¤   ¤   ¤   ·* We recognize that by being in a PGPKEY scope and having
ee8698 ¤   ¤   ¤   ·* the next packet not being a literal. ·This could eliminate
d2e590 ¤   ¤   ¤   ·* some extremely rare cases where a key block was followed by
6726e3 ¤   ¤   ¤   ·* a signature on a non-literal, but sigs on non-literals are
d05a8a ¤   ¤   ¤   ·* themselves rare.
688753 ¤   ¤   ¤   ·*/
a26efa ¤   ¤   ¤   if (ctx->end_scope == PGPANN_PGPKEY_END &&
09addc ¤   ¤   ¤   ¤   !ctx->eof &&
55e064 ¤   ¤   ¤   ¤   PKTBYTE_TYPE(*buf) != PKTBYTE_LITERAL &&
364ff3 ¤   ¤   ¤   ¤   PKTBYTE_TYPE(*buf) != PKTBYTE_OLDLITERAL) {
ac2fc4 ¤   ¤   ¤   ¤   /* Treat as a key signature */
7cea1c ¤   ¤   ¤   ¤   myself->write = parseKey;
--2360 0006dc4e2a540100197 Page 30 of pgpPrsBin.c
73c1be ¤   ¤   ¤   ¤   return written + parseKey (myself, buf, size,
457a32 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···error);
21a3a6 ¤   ¤   ¤   }
4c0fe4 ¤   ¤   }
acaf5a
ebf75d ¤   ¤   /* Report a packet larger than the buffer */
4891b8 ¤   ¤   if (inputOverfull(&ctx->input)) {
226c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
9e2fa6 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNATURE_TOO_BIG,
e50d2a ¤   ¤   ¤   ¤   ¤   ¤   ···inputMergedPtr(&ctx->input),
731cdd ¤   ¤   ¤   ¤   ¤   ¤   ···inputMerged(&ctx->input));
40b5c5 ¤   ¤   ¤   if (*error)
c80651 ¤   ¤   ¤   ¤   return written;
6eaf5a
c62eb0 ¤   ¤   ¤   /* Skip the body of the packet */
b31f1c ¤   ¤   ¤   myself->write = DoSkip;
9af7e1 ¤   ¤   ¤   return written + DoSkip(myself, buf, size, error);
b10fe4 ¤   ¤   }
05af5a
ea7f6b ¤   ¤   /* Have we sucked in the whole packet? */
1580c0 ¤   ¤   if (!inputFinished(&ctx->input.head))
a3ab0f ¤   ¤   ¤   return written;
40af5a
7b1b17 ¤   ¤   /*
7039e4 ¤   ¤   ·* We can get here if there is a normal signed message
0c9277 ¤   ¤   ·* just after a key packet. ·In this case we need to
106828 ¤   ¤   ·* end the PGPKEY scope and then start a new one.
5f9de3 ¤   ¤   ·*/
c033e8 ¤   ¤   if (ctx->end_scope == PGPANN_PGPKEY_END) {
5f6ca7 ¤   ¤   ¤   /* we need to end the PGPKEY scope. ·Yikes! */
ad6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
05bdb3 ¤   ¤   ¤   ¤   ¤   ¤   ······ctx->end_scope, NULL, 0);
b9b5c5 ¤   ¤   ¤   if (*error)
ff46f1 ¤   ¤   ¤   ¤   return 0;
ecaf5a
1e45d2 ¤   ¤   ¤   ctx->end_scope = 0;
c00fe4 ¤   ¤   }
efaf5a
9b0ff8 ¤   ¤   if (ctx->eof ||
3c4c3e ¤   ¤   ····(!IS_OLD_PKTBYTE(*buf) && !IS_NEW_PKTBYTE(*buf)))
7c5b34 ¤   ¤   {
6666f7 ¤   ¤   ¤   /* Do separate signature thing */
4afa81 ¤   ¤   ¤   ctx->state = 20;
275747 ¤   ¤   ¤   goto sepsig;
b50fe4 ¤   ¤   }
cdaf5a
9f0995 ¤   ¤   if (PKTBYTE_TYPE(*buf) == PKTBYTE_LITERAL ||
6fb520 ¤   ¤   ¤   PKTBYTE_TYPE(*buf) == PKTBYTE_OLDLITERAL) {
5aa3de ¤   ¤   ¤   /* Do signature on literal */
71df4c ¤   ¤   ¤   ctx->state = 10;
0320c2 ¤   ¤   ¤   goto sigliteral;
fc0fe4 ¤   ¤   }
f1af5a
75deb7 ¤   ¤   ctx->state++;
998224 ¤   ¤   /* FALLTHROUGH */
17a2b3 ¤   case 1:
253b92 ¤   ¤   /* It's a signed PGP file (not a literal) */
8d3a6c ¤   ¤   ctx->needcallback = 1;
00fc77 ¤   ¤   /* Send only one BEGIN annotation */
80dd84 ¤   ¤   if (ctx->end_scope != PGPANN_SIGNED_END) {
8acfac ¤   ¤   ¤   ctx->end_scope = PGPANN_SIGNED_END;
286c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
323291 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNED_BEGIN,0,0);
82b5c5 ¤   ¤   ¤   if (*error)
fdf622 ¤   ¤   ¤   ¤   break;
7e0fe4 ¤   ¤   }
5bdeb7 ¤   ¤   ctx->state++;
1d8224 ¤   ¤   /* FALLTHROUGH */
6e4dd7 ¤   case 2:
f0c2e8 ¤   ¤   /* Dump the signature as an annotation */
2c4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
6de44b ¤   ¤   ······························PGPANN_SIGNED_SIG,
--236f 0007bc0008e40100197 Page 31 of pgpPrsBin.c
098c3e ¤   ¤   ······························inputMergedPtr(&ctx->input),
e262b8 ¤   ¤   ······························inputMerged(&ctx->input));
d9cf31 ¤   ¤   if (*error)
64cdcb ¤   ¤   ¤   break;
47deb7 ¤   ¤   ctx->state++;
318224 ¤   ¤   /* FALLTHROUGH */
a1170b ¤   case 3:
9788c7 ¤   ¤   if (ctx->sig1pass) {
a0902a ¤   ¤   ¤   if (!pgpSigNestFlag(inputMergedPtr(&ctx->input),
f3fc05 ¤   ¤   ¤   ¤   ¤   ·inputMerged(&ctx->input))) {
acef10 ¤   ¤   ¤   ¤   /* No nest flag means another sighdr follows */
682691 ¤   ¤   ¤   ¤   myself->write = nextScope;
0cec11 ¤   ¤   ¤   ¤   break;¤ /* Call nextScope next time */
c27108 ¤   ¤   ¤   } else if (IS_NEW_PKTBYTE(*buf) &&
df6bd8 ¤   ¤   ¤   ¤   ···PKTBYTE_TYPE(*buf)==PKTBYTE_SIG) {
44980e ¤   ¤   ¤   ¤   /*
160c29 ¤   ¤   ¤   ¤   ·* A 1-pass header immediately followed by
db2ae0 ¤   ¤   ¤   ¤   ·* a 1-pass footer can only mean one thing:
09a2e4 ¤   ¤   ¤   ¤   ·* a separate signature. ·With these, the
b7acaf ¤   ¤   ¤   ¤   ·* reader will try to check sigs as soon as
1a62aa ¤   ¤   ¤   ¤   ·* we ask it to commit. ·So we can't do that
5a5978 ¤   ¤   ¤   ¤   ·* until we have read our footer signatures.
981020 ¤   ¤   ¤   ¤   ·*/
0156b8 ¤   ¤   ¤   ¤   ctx->sepsig = 1;
a95421 ¤   ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail,
449cd4 ¤   ¤   ¤   ¤   ¤   ¤   ······myself,
8a34d2 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNED_SEP, 0, 0);
34af5a
59bad3 ¤   ¤   ¤   ¤   /* Process end of message sigs */
132691 ¤   ¤   ¤   ¤   myself->write = nextScope;
f23c4e ¤   ¤   ¤   ¤   break; /* Call nextScope next time */
11a3a6 ¤   ¤   ¤   }
d80fe4 ¤   ¤   }
e4af5a
05af5a
d54607 ¤   ¤   if (ctx->needcallback) {
466c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
711d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
b8b5c5 ¤   ¤   ¤   if (*error)
b9f622 ¤   ¤   ¤   ¤   break;
d30fe4 ¤   ¤   }
63deb7 ¤   ¤   ctx->state++;
698224 ¤   ¤   /* FALLTHROUGH */
409b0e ¤   case 4:
1d4607 ¤   ¤   if (ctx->needcallback) {
d5b0dc ¤   ¤   ¤   *error = ProcessCallback (myself,
2e2669 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPANN_PARSER_RECURSE,
1079cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
28b5c5 ¤   ¤   ¤   if (*error)
47f622 ¤   ¤   ¤   ¤   break;
640fe4 ¤   ¤   }
2de158 ¤   ¤   ctx->state = 0;
29b770 ¤   ¤   written += myself->write(myself, buf, size, error);
572f68 ¤   ¤   break;
08af5a
73e3dd ¤   /* Signature on literal case */
d5ed30 ¤   case 10:
8e1050 sigliteral:
043a6c ¤   ¤   ctx->needcallback = 1;
8dfc77 ¤   ¤   /* Send only one BEGIN annotation */
c9dd84 ¤   ¤   if (ctx->end_scope != PGPANN_SIGNED_END) {
f8cfac ¤   ¤   ¤   ctx->end_scope = PGPANN_SIGNED_END;
436c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
323291 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNED_BEGIN,0,0);
afb5c5 ¤   ¤   ¤   if (*error)
fef622 ¤   ¤   ¤   ¤   break;
b10fe4 ¤   ¤   }
89deb7 ¤   ¤   ctx->state++;
078224 ¤   ¤   /* FALLTHROUGH */
6fb7ec ¤   case 11:
0dc2e8 ¤   ¤   /* Dump the signature as an annotation */
7b4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
--1c7d 0008073932f40100197 Page 32 of pgpPrsBin.c
068c9d ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNED_SIG,
938c3e ¤   ¤   ······························inputMergedPtr(&ctx->input),
fd62b8 ¤   ¤   ······························inputMerged(&ctx->input));
8ecf31 ¤   ¤   if (*error)
a0cdcb ¤   ¤   ¤   break;
d7deb7 ¤   ¤   ctx->state++;
bd8224 ¤   ¤   /* FALLTHROUGH */
525888 ¤   case 12:
0d4607 ¤   ¤   if (ctx->needcallback) {
276c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
e41d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
5bb5c5 ¤   ¤   ¤   if (*error)
bcf622 ¤   ¤   ¤   ¤   break;
ec0fe4 ¤   ¤   }
e1deb7 ¤   ¤   ctx->state++;
718224 ¤   ¤   /* FALLTHROUGH */
ef0254 ¤   case 13:
d94607 ¤   ¤   if (ctx->needcallback) {
0fb0dc ¤   ¤   ¤   *error = ProcessCallback (myself,
fd2669 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPANN_PARSER_RECURSE,
6c79cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
62b5c5 ¤   ¤   ¤   if (*error)
def622 ¤   ¤   ¤   ¤   break;
7e0fe4 ¤   ¤   }
ade158 ¤   ¤   ctx->state = 0;
98b770 ¤   ¤   written += myself->write(myself, buf, size, error);
072f68 ¤   ¤   break;
d7af5a
4fe744 ¤   /* Separate signature case */
d1c8fd ¤   case 20:
f196f6 sepsig:
063a6c ¤   ¤   ctx->needcallback = 1;
c8fc77 ¤   ¤   /* Send only one BEGIN annotation */
a6dd84 ¤   ¤   if (ctx->end_scope != PGPANN_SIGNED_END) {
50cfac ¤   ¤   ¤   ctx->end_scope = PGPANN_SIGNED_END;
f16c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
b93291 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNED_BEGIN,0,0);
eab5c5 ¤   ¤   ¤   if (*error)
95f622 ¤   ¤   ¤   ¤   break;
520fe4 ¤   ¤   }
a4deb7 ¤   ¤   ctx->state++;
058224 ¤   ¤   /* FALLTHROUGH */
a79221 ¤   case 21:
a01b17 ¤   ¤   /*
7ed52a ¤   ¤   ·* Say that this will be a separate signature.
75b07e ¤   ¤   ·* Note that we don't set the sepsig flag here, as we don't
6140b0 ¤   ¤   ·* need to know. ·That flag is just for 1-pass signatures.
b19de3 ¤   ¤   ·*/
184adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
996b88 ¤   ¤   ······························PGPANN_SIGNED_SEP, 0, 0);
96cf31 ¤   ¤   if (*error)
eecdcb ¤   ¤   ¤   break;
cfdeb7 ¤   ¤   ctx->state++;
778224 ¤   ¤   /* FALLTHROUGH */
957d45 ¤   case 22:
144adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
e0e44b ¤   ¤   ······························PGPANN_SIGNED_SIG,
ed8c3e ¤   ¤   ······························inputMergedPtr(&ctx->input),
ae62b8 ¤   ¤   ······························inputMerged(&ctx->input));
2fcf31 ¤   ¤   if (*error)
3acdcb ¤   ¤   ¤   break;
01deb7 ¤   ¤   ctx->state++;
718224 ¤   ¤   /* FALLTHROUGH */
3b2799 ¤   case 23:
4e4607 ¤   ¤   if (ctx->needcallback) {
336c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
1c1d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
60b5c5 ¤   ¤   ¤   if (*error)
5ff622 ¤   ¤   ¤   ¤   break;
240fe4 ¤   ¤   }
9fdeb7 ¤   ¤   ctx->state++;
808224 ¤   ¤   /* FALLTHROUGH */
--3e3e 0003ade624440100197 Page 33 of pgpPrsBin.c
83ab9c ¤   case 24:
7f4607 ¤   ¤   if (ctx->needcallback) {
dedf39 ¤   ¤   ¤   *error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
eb79cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
54b5c5 ¤   ¤   ¤   if (*error)
0ff622 ¤   ¤   ¤   ¤   break;
950fe4 ¤   ¤   }
3ae158 ¤   ¤   ctx->state = 0;
85b770 ¤   ¤   written += myself->write(myself, buf, size, error);
3c2f68 ¤   ¤   break;
7caf5a
202f72 ¤   default:
a69132 ¤   ¤   pgpAssert (0);
999371 ¤   }
3daf5a
b4279e ¤   return written;
1fefe6 }
79af5a
53af5a
5038e5 /*
4f19bd ·* Parse 2nd signature packet after the signed packet after a
3218ee ·* 1-pass signature packet. ·These are the "sig footer" packets
fd0091 ·* which are full-sized signature packets, paired with the 1-pass
553070 ·* sig header packets.
27495d ·*/
dd5d09 static size_t
1a08c6 parseSignature1Pass2 (PGPPipeline *myself, PGPByte const *buf,
bea1aa ¤   ¤   size_t size, PGPError *error)
05bb36 {
7fe07e ¤   PrsBinContext *ctx;
daa371 ¤   size_t written = 0;
fcaf5a
4d29be ¤   pgpAssert (myself);
8b70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
ae4866 ¤   pgpAssert (error);
8baf5a
598808 ¤   ctx = (PrsBinContext *)myself->priv;
71d6bc ¤   pgpAssert (ctx);
791728 ¤   pgpAssert (ctx->tail);
942aee ¤   pgpAssert (!size || !ctx->eof);
abaf5a
316f5c ¤   switch (ctx->state) {
23f86f ¤   case 0:
a9f4dc ¤   ¤   /* Suck in the whole signature packet */
efaf5a
b007e2 ¤   ¤   written = inputMerge(&ctx->input, buf, size, (unsigned)-1, error);
0cd06f ¤   ¤   buf += written;
7d28a7 ¤   ¤   size -= written;
03af5a
ce3284 ¤   ¤   /* Handle a packet larger than the buffer somehow */
8b91b8 ¤   ¤   if (inputOverfull(&ctx->input)) {
3a6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
042fa6 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_SIGNATURE_TOO_BIG,
490d2a ¤   ¤   ¤   ¤   ¤   ¤   ···inputMergedPtr(&ctx->input),
5b1cdd ¤   ¤   ¤   ¤   ¤   ¤   ···inputMerged(&ctx->input));
50b5c5 ¤   ¤   ¤   if (*error)
fe0651 ¤   ¤   ¤   ¤   return written;
f3af5a
c72eb0 ¤   ¤   ¤   /* Skip the body of the packet */
8f1f1c ¤   ¤   ¤   myself->write = DoSkip;
c6f7e1 ¤   ¤   ¤   return written + DoSkip(myself, buf, size, error);
f50fe4 ¤   ¤   }
d4af5a
d27f6b ¤   ¤   /* Have we sucked in the whole packet? */
3180c0 ¤   ¤   if (!inputFinished(&ctx->input.head))
65ab0f ¤   ¤   ¤   return written;
2a8224 ¤   ¤   /* FALLTHROUGH */
48a2b3 ¤   case 1:
de436a ¤   ¤   /* Dump the signature data as an annotation */
383a6c ¤   ¤   ctx->needcallback = 1;
2f4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
3ab104 ¤   ¤   ······························PGPANN_SIGNED_SIG2,
--df4c 000ed0e60de40100197 Page 34 of pgpPrsBin.c
882ba3 ¤   ¤   ¤   ¤   ¤   ······inputMergedPtr(&ctx->input),
97f00b ¤   ¤   ¤   ¤   ¤   ······inputMerged(&ctx->input));
8dcf31 ¤   ¤   if (*error)
d3cdcb ¤   ¤   ¤   break;
44af5a
378f19 ¤   ¤   /* Decrement count of sig footers needing to be seen */
416771 ¤   ¤   --ctx->sig1pass;
96af5a
4c28ec ¤   ¤   if (!ctx->sepsig || ctx->sig1pass != 0) {
a17aad ¤   ¤   ¤   /*
69eea6 ¤   ¤   ¤   ·* In normal case, we are done now.
53956c ¤   ¤   ¤   ·* nextScope will end sig scope if sig1pass is 0.
668753 ¤   ¤   ¤   ·*/
5528dd ¤   ¤   ¤   myself->write = nextScope;
9dc045 ¤   ¤   ¤   written += nextScope(myself, buf, size, error);
86cdcb ¤   ¤   ¤   break;
ee0fe4 ¤   ¤   }
2aaf5a
9aec77 ¤   ¤   /* Here on last sig footer of separate signature */
d8deb7 ¤   ¤   ctx->state++;
353a6c ¤   ¤   ctx->needcallback = 1;
ac8224 ¤   ¤   /* FALLTHROUGH */
414dd7 ¤   case 2:
bb4607 ¤   ¤   if (ctx->needcallback) {
506c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
771d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
9cb5c5 ¤   ¤   ¤   if (*error)
65f622 ¤   ¤   ¤   ¤   break;
6e0fe4 ¤   ¤   }
d9deb7 ¤   ¤   ctx->state++;
268224 ¤   ¤   /* FALLTHROUGH */
cf170b ¤   case 3:
f74607 ¤   ¤   if (ctx->needcallback) {
32df39 ¤   ¤   ¤   *error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
a879cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
34b5c5 ¤   ¤   ¤   if (*error)
54f622 ¤   ¤   ¤   ¤   break;
ea0fe4 ¤   ¤   }
03e158 ¤   ¤   ctx->state = 0;
12b770 ¤   ¤   written += myself->write(myself, buf, size, error);
7d2f68 ¤   ¤   break;
879371 ¤   }
f0af5a
51279e ¤   return written;
51efe6 }
c0af5a
795d09 static size_t
2c8c8d parseESK (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
f7bb36 {
11e07e ¤   PrsBinContext *ctx;
59a371 ¤   size_t written = 0;
f8ffd4 ¤   PGPByte b;
e7af5a
90af5a
c829be ¤   pgpAssert (myself);
7a70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
3b4866 ¤   pgpAssert (error);
90af5a
808808 ¤   ctx = (PrsBinContext *)myself->priv;
6fd6bc ¤   pgpAssert (ctx);
d51728 ¤   pgpAssert (ctx->tail);
5c2aee ¤   pgpAssert (!size || !ctx->eof);
eeaf5a
d9ffd7 ¤   b = PKTBYTE_TYPE (ctx->input.buffer[0]);
0d9096 ¤   *error = kPGPError_NoErr;
31af5a
316f5c ¤   switch (ctx->state) {
bcf86f ¤   case 0:
82440c ¤   ¤   /* It's a public-key-encrypted PGP file */
1dc38b ¤   ¤   if (!ctx->end_scope) {
1f85c8 ¤   ¤   ¤   ctx->end_scope = PGPANN_CIPHER_END;
ed6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
--4ae0 0000159db0540100197 Page 35 of pgpPrsBin.c
6c40e8 ¤   ¤   ¤   ······························PGPANN_CIPHER_BEGIN,
9725f8 ¤   ¤   ¤   ······························0, 0);
3eb5c5 ¤   ¤   ¤   if (*error)
9af622 ¤   ¤   ¤   ¤   break;
440fe4 ¤   ¤   }
ecdeb7 ¤   ¤   ctx->state++;
ab8224 ¤   ¤   /* FALLTHROUGH */
cea2b3 ¤   case 1:
7707e2 ¤   ¤   written = inputMerge(&ctx->input, buf, size, (unsigned)-1, error);
d4d06f ¤   ¤   buf += written;
7528a7 ¤   ¤   size -= written;
2faf5a
7d3284 ¤   ¤   /* Handle a packet larger than the buffer somehow */
0791b8 ¤   ¤   if (inputOverfull(&ctx->input)) {
606c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
29ca21 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPANN_ESK_TOO_BIG,
c70d2a ¤   ¤   ¤   ¤   ¤   ¤   ···inputMergedPtr(&ctx->input),
7b1cdd ¤   ¤   ¤   ¤   ¤   ¤   ···inputMerged(&ctx->input));
78b5c5 ¤   ¤   ¤   if (*error)
d70651 ¤   ¤   ¤   ¤   return written;
15af5a
012eb0 ¤   ¤   ¤   /* Skip the body of the packet */
c11f1c ¤   ¤   ¤   myself->write = DoSkip;
37f7e1 ¤   ¤   ¤   return written + DoSkip(myself, buf, size, error);
ba0fe4 ¤   ¤   }
95af5a
287f6b ¤   ¤   /* Have we sucked in the whole packet? */
5280c0 ¤   ¤   if (!inputFinished(&ctx->input.head))
11ab0f ¤   ¤   ¤   return written;
12af5a
3bdeb7 ¤   ¤   ctx->state++;
368224 ¤   ¤   /* FALLTHROUGH */
864dd7 ¤   case 2:
467c95 ¤   ¤   /* Dump the ESK as an annotation */
3f4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
6c27d2 ¤   ¤   ¤   ¤   ¤   ······(b == PKTBYTE_ESK ?
83a48c ¤   ¤   ¤   ¤   ¤   ·······PGPANN_PKCIPHER_ESK :
e2d3d6 ¤   ¤   ¤   ¤   ¤   ·······(b == PKTBYTE_CONVESK ?
efaf05 ¤   ¤   ¤   ¤   ¤   ¤   PGPANN_SKCIPHER_ESK :
ba3b3d ¤   ¤   ¤   ¤   ¤   ¤   -1)), /* XXX */
cc8c3e ¤   ¤   ······························inputMergedPtr(&ctx->input),
f562b8 ¤   ¤   ······························inputMerged(&ctx->input));
9fcf31 ¤   ¤   if (*error)
b1cdcb ¤   ¤   ¤   break;
3eaf5a
f1dde2 ¤   ¤   ctx->state++;¤  /* This really isn't needed */
b985bf ¤   ¤   myself->write = nextESK;
18adf3 ¤   ¤   return written + nextESK(myself, buf, size, error);
e26d15 ¤   ¤   /* NOTREACHED */
7d2f72 ¤   default:
e89132 ¤   ¤   pgpAssert (0);
569371 ¤   }
c6af5a
5b279e ¤   return written;
87efe6 }
94af5a
2338e5 /*
34e09c ·* This just sends appropriate messages about the lack of text downstream.
a0495d ·*/
0b5d09 static size_t
fd7b46 parseCipherNoText (PGPPipeline *myself, PGPByte const *buf, size_t size,
80a0d2 ···················PGPError *error)
92bb36 {
9fe07e ¤   PrsBinContext *ctx;
9aaf5a
0229be ¤   pgpAssert (myself);
9270c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
254866 ¤   pgpAssert (error);
19af5a
2d8808 ¤   ctx = (PrsBinContext *)myself->priv;
29d6bc ¤   pgpAssert (ctx);
011728 ¤   pgpAssert (ctx->tail);
--feaa 0002d87a42440100197 Page 36 of pgpPrsBin.c
692aee ¤   pgpAssert (!size || !ctx->eof);
80af5a
1f9096 ¤   *error = kPGPError_NoErr;
4faf5a
a46f5c ¤   switch (ctx->state) {
66f86f ¤   case 0:
f03a6c ¤   ¤   ctx->needcallback = 1;
325926 ¤   ¤   /* Send an annotation */
fb4adc ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
83da8d ¤   ¤   ······························PGPANN_CIPHER_NOTEXT, 0, 0);
fccf31 ¤   ¤   if (*error)
01cdcb ¤   ¤   ¤   break;
e4deb7 ¤   ¤   ctx->state++;
13fc9f ¤   ¤   /*FALLTHROUGH*/
a0a2b3 ¤   case 1:
699358 ¤   ¤   /* Send a commit */
8b4607 ¤   ¤   if (ctx->needcallback) {
496c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
b91d55 ¤   ¤   ¤   ······························PGPANN_COMMIT, 0, 0);
04b5c5 ¤   ¤   ¤   if (*error)
bbf622 ¤   ¤   ¤   ¤   break;
dc0fe4 ¤   ¤   }
76deb7 ¤   ¤   ctx->state++;
db8224 ¤   ¤   /* FALLTHROUGH */
6e4dd7 ¤   case 2:
864607 ¤   ¤   if (ctx->needcallback) {
a5df39 ¤   ¤   ¤   *error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
6f79cd ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0);
9cb5c5 ¤   ¤   ¤   if (*error)
12f622 ¤   ¤   ¤   ¤   break;
be0fe4 ¤   ¤   }
41deb7 ¤   ¤   ctx->state++;
a2b1dd ¤   ¤   return myself->write(myself, buf, size, error);
652f72 ¤   default:
609132 ¤   ¤   pgpAssert (0);
9f47d1 ¤   }·
6e7bf1 ¤   return 0;¤  /* Never executed; makes compilers happy. */
bfefe6 }
2aaf5a
b438e5 /*
1d2fa2 ·* The default state when starting to parse a packet. ·Once the type and
2257ed ·* size of the packet has been determined, we don't come back until
43910c ·* the end of the packet. ·This function *is* called after each packet
9a8c57 ·* (by the sizeAdvise(0) handler if necessary), because post-packet
54bc8b ·* cleanup code also resides here.
a5775e ·*
2b0cfb ·* Because the functions in this module rely heavily on tail recursion,
54270f ·* if we get called with a large packet (say 16K), it could have literally
b5c24d ·* hundreds of objects on it, and we go hundreds of levels deep on recursion.
6f12df ·* This exhausts stack space. ·Therefore we will limit the amount of data we
d5553f ·* will accept on one call to PARSER_SIZE_LIMIT.
8b495d ·*/
295d09 static size_t
b03673 parsePacket (PGPPipeline *myself, PGPByte const *buf, size_t size,
d4fb43 ¤   ·····PGPError *error)
68bb36 {
78e07e ¤   PrsBinContext *ctx;
2da371 ¤   size_t written = 0;
4a5d99 ¤   unsigned b;
99af5a
a429be ¤   pgpAssert (myself);
d370c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
534866 ¤   pgpAssert (error);
f60ccc #if PGP_MACINTOSH
c9e157 ¤   pgpAssert( StackSpace() >= 4096 );
427454 #endif
eeaf5a
218808 ¤   ctx = (PrsBinContext *)myself->priv;
08d6bc ¤   pgpAssert (ctx);
5e1728 ¤   pgpAssert (ctx->tail);
852aee ¤   pgpAssert (!size || !ctx->eof);
2daf5a
--8463 0005c39db4440100197 Page 37 of pgpPrsBin.c
969096 ¤   *error = kPGPError_NoErr;
daaf5a
c19de6 ¤   /* Prevent excessive recursion within this module */
94605a ¤   size = pgpMin(size, PARSER_SIZE_LIMIT);
5aaf5a
d7d8af ¤   /*
13cc6f ¤   ·* findpkt is set to 1 by create and every time we change to
4cb843 ¤   ·* the parsePacket state, and indicates that the first packet
6e907a ¤   ·* byte has not been found.
ada4e3 ¤   ·*/
b46158 ¤   if (ctx->findpkt) {
7018f5 ¤   ¤   inputReset(&ctx->input);
cdaf5a
6f1853 ¤   ¤   if (!size)
83483d ¤   ¤   ¤   return 0;¤  /* I need a packet header! */
624d1a ¤   ¤   ctx->findpkt = 0;
f7fe03 ¤   ¤   b = *(buf++);
8daa85 ¤   ¤   size--;
0e1b52 ¤   ¤
04bef3 ¤   ¤   if (inputStart(&ctx->input, (PGPByte)b) < 0) {
87ea33 ¤   ¤   ¤   ctx->state = 0;¤/* Need to set this */
6a983b ¤   ¤   ¤   ¤   ¤   /* before jumping ahead */
db20b7 ¤   ¤   ¤   myself->write = parseUnknown;
2bb485 ¤   ¤   ¤   return 1+parseUnknown (myself, buf, size, error);
920fe4 ¤   ¤   }
181b52 ¤   ¤
1e6624 ¤   ¤   written = 1;
409371 ¤   }
a3af5a
5ad8af ¤   /*
bbb9a0 ¤   ·* Okay, now we have a packet, with the parser state set up
42a5c1 ¤   ·* and the header byte in ctx->input.buffer[0].
1e9714 ¤   ·*
6c9763 ¤   ·* The packet-specific parsers use a state variable, and
6e7d9d ¤   ·* expect it to be set to 0 when they begin.
8da4e3 ¤   ·*/
aa9bac ¤   ctx->state = 0;
baaf5a
92ffd7 ¤   b = PKTBYTE_TYPE (ctx->input.buffer[0]);
b1af5a
45d94b ¤   if (ctx->end_scope == PGPANN_CIPHER_END) {
bb43b5 ¤   ¤   switch (b) {
a30122 ¤   ¤   case PKTBYTE_CONVENTIONAL:
fd00b1 ¤   ¤   ¤   myself->write = parseCipher;
3ccdcb ¤   ¤   ¤   break;
e4a6f4 ¤   ¤   case PKTBYTE_CONVESK:
c7915f ¤   ¤   case PKTBYTE_ESK:
dd8334 ¤   ¤   ¤   myself->write = parseESK;
76cdcb ¤   ¤   ¤   break;
c29ae3 ¤   ¤   default:
b0fb39 ¤   ¤   ¤   myself->write = parseCipherNoText;
92cdcb ¤   ¤   ¤   break;
b00fe4 ¤   ¤   }
f6f037 ¤   } else {
d043b5 ¤   ¤   switch (b) {
bf0122 ¤   ¤   case PKTBYTE_CONVENTIONAL:
8900b1 ¤   ¤   ¤   myself->write = parseCipher;
36cdcb ¤   ¤   ¤   break;
4f6024 ¤   ¤   case PKTBYTE_OLDLITERAL:
647aad ¤   ¤   ¤   /*
b60eea ¤   ¤   ¤   ·* This may be a dummy header we created, or it may be a
61b935 ¤   ¤   ¤   ·* mistaken value from a PGP compatible program, or it may
cff6f4 ¤   ¤   ¤   ·* conceivably be an obsolete old-style literal packet from a
1bec28 ¤   ¤   ¤   ·* pre-release version of PGP 2.0!
fff939 ¤   ¤   ¤   ·* Flag special treatment, and distinguish the cases in
cce539 ¤   ¤   ¤   ·* parseLiteral.
408753 ¤   ¤   ¤   ·*/
55df4c ¤   ¤   ¤   ctx->state = 10;
da0b70 ¤   ¤   ¤   /* FALLTHROUGH */
57cd70 ¤   ¤   case PKTBYTE_LITERAL:
0f05b5 ¤   ¤   ¤   myself->write = parseLiteral;
5ccdcb ¤   ¤   ¤   break;
--bf76 000a7e37c5440100197 Page 38 of pgpPrsBin.c
d85890 ¤   ¤   case PKTBYTE_COMPRESSED:
7391b8 ¤   ¤   ¤   myself->write = parseCompressed;
76cdcb ¤   ¤   ¤   break;
77a42b ¤   ¤   case PKTBYTE_SIG:
2d8601 ¤   ¤   ¤   if (ctx->sig1pass)
ebefec ¤   ¤   ¤   ¤   myself->write = parseSignature1Pass2;
b7bb8c ¤   ¤   ¤   else
d81b67 ¤   ¤   ¤   ¤   myself->write = parseSignature;
05cdcb ¤   ¤   ¤   break;
bceb11 ¤   ¤   case PKTBYTE_1PASSSIG:
c20f5d ¤   ¤   ¤   ++ctx->sig1pass;
0294b0 ¤   ¤   ¤   ctx->sig1nest = 0;
60b732 ¤   ¤   ¤   ctx->sepsig = 0;
280337 ¤   ¤   ¤   myself->write = parseSignature;
68cdcb ¤   ¤   ¤   break;
94a6f4 ¤   ¤   case PKTBYTE_CONVESK:
36915f ¤   ¤   case PKTBYTE_ESK:
fa8334 ¤   ¤   ¤   myself->write = parseESK;
6ecdcb ¤   ¤   ¤   break;
4602b8 ¤   ¤   case PKTBYTE_SECKEY:
02398a ¤   ¤   case PKTBYTE_PUBKEY:
009224 ¤   ¤   case PKTBYTE_SECSUBKEY:
4df338 ¤   ¤   case PKTBYTE_PUBSUBKEY:
153907 ¤   ¤   case PKTBYTE_TRUST:
61bd73 ¤   ¤   case PKTBYTE_NAME:
cee673 ¤   ¤   case PKTBYTE_COMMENT:
01d6f2 ¤   ¤   ¤   myself->write = parseKey;
01cdcb ¤   ¤   ¤   break;
079ae3 ¤   ¤   default:
bd9ea9 ¤   ¤   ¤   /* If found in keyring, assume still in one */
1d02c0 ¤   ¤   ¤   if (ctx->end_scope == PGPANN_PGPKEY_END)
b8ea1c ¤   ¤   ¤   ¤   myself->write = parseKey;
dfbb8c ¤   ¤   ¤   else
621972 ¤   ¤   ¤   ¤   myself->write = parseUnknown;
b3cdcb ¤   ¤   ¤   break;
a50fe4 ¤   ¤   }
179371 ¤   }
3b586c ¤   /* continue processing, if we can */
b7cd31 ¤   return written + myself->write (myself, buf, size, error);
4defe6 }
22af5a
f738e5 /*
93a863 ·* Start a new packet. ·This mostly cleans up after old ones, then
363099 ·* falls through to parsePacket.
a4495d ·*/
b15d09 static size_t
675a2e nextScope (PGPPipeline *myself, PGPByte const *buf, size_t size,
4718d1 ¤   ¤   PGPError *error)
b1bb36 {
05e07e ¤   PrsBinContext *ctx;
60a371 ¤   size_t written = 0;
d6af5a
ca29be ¤   pgpAssert (myself);
7f70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
c74866 ¤   pgpAssert (error);
62af5a
d48808 ¤   ctx = (PrsBinContext *)myself->priv;
b3d6bc ¤   pgpAssert (ctx);
a31728 ¤   pgpAssert (ctx->tail);
392aee ¤   pgpAssert (!size || !ctx->eof);
b7af5a
969096 ¤   *error = kPGPError_NoErr;
daaf5a
ff9bd8 ¤   /* Get rid of any buffered data */
5b9e76 ¤   inputPurge(&ctx->input);
56af5a
d45eda ¤   /* Clean up any pipeline set up to process the packet. */
e0f584 ¤   if (ctx->end) {
b4981d ¤   ¤   *error = ctx->tail->sizeAdvise (ctx->tail, 0);
94cf31 ¤   ¤   if (*error)
84ab0f ¤   ¤   ¤   return written;
a7af5a
--0f2b 000857c609240100197 Page 39 of pgpPrsBin.c
8c4baa ¤   ¤   parsePipelineTeardown (ctx);
616f7f ¤   ¤   ctx->nextparser = NULL;
6d9371 ¤   }
f6af5a
94d8af ¤   /*
dc4256 ¤   ·* Special handling at end of 1 pass sig signed packet.
6a8a46 ¤   ·* Retain hashes and end_scope; parsePacket will then handle
b69339 ¤   ·* the following signature packet.
0a5f8a ¤   ·* XXX
65a1c9 ¤   ·* Need to recognize error of having another packet type there.
1ba4e3 ¤   ·*/
16b1f1 ¤   if (!ctx->sig1pass) {
0daf5a
e91412 ¤   ¤   /* Send the end-scope annotation for the last scope, if any. */
cb832f ¤   ¤   if (ctx->end_scope) {
7e6c69 ¤   ¤   ¤   *error = ctx->tail->annotate (ctx->tail, myself,
6714d3 ¤   ¤   ¤   ¤   ¤   ¤   ······ctx->end_scope, 0, 0);
69b5c5 ¤   ¤   ¤   if (*error)
d00651 ¤   ¤   ¤   ¤   return written;
7daf5a
9845d2 ¤   ¤   ¤   ctx->end_scope = 0;
595462 ¤   ¤   ¤   ctx->input.silent_trunc = 0;
a50fe4 ¤   ¤   }
39af5a
857c10 ¤   ¤   /* Clean up any pending hashes */
922d26 ¤   ¤   if (ctx->hashes) {
82b2c7 ¤   ¤   ¤   pgpHashListDestroy ( ctx->hashes );
5db250 ¤   ¤   ¤   ctx->hashes = 0;
8f0fe4 ¤   ¤   }
83af5a
279371 ¤   }
72af5a
05d073 ¤   ctx->findpkt = 1;
8bb2a8 ¤   myself->write = parsePacket;
6201b0 ¤   return parsePacket (myself, buf, size, error);
88efe6 }
9eaf5a
ce38e5 /*
375641 ·* After an ESK, call this function, which copies the current packet to
9ba0b6 ·* the byte FIFO, and sets things up for parsePacket again.
1b3041 ·* It doesn't flush the FIFO or end the current scope.
96495d ·*/
815d09 static size_t
c8c2b8 nextESK (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
51bb36 {
71e07e ¤   PrsBinContext *ctx;
65af5a
1729be ¤   pgpAssert (myself);
5070c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
444866 ¤   pgpAssert (error);
2aaf5a
a08808 ¤   ctx = (PrsBinContext *)myself->priv;
06d6bc ¤   pgpAssert (ctx);
231728 ¤   pgpAssert (ctx->tail);
412aee ¤   pgpAssert (!size || !ctx->eof);
0aaf5a
f782e1 ¤   *error = inputToFifo(&ctx->input);
145842 ¤   if (*error)
18bbde ¤   ¤   return 0;
1eaf5a
53d073 ¤   ctx->findpkt = 1;
83b2a8 ¤   myself->write = parsePacket;
0801b0 ¤   return parsePacket (myself, buf, size, error);
c1efe6 }
16af5a
9aaf5a
5bf1ae static PGPError
62d02e Flush (PGPPipeline *myself)
20bb36 {
91e07e ¤   PrsBinContext *ctx;
195b01 ¤   PGPError¤   error = kPGPError_NoErr;
85af5a
--fbc0 00008448df940100197 Page 40 of pgpPrsBin.c
c629be ¤   pgpAssert (myself);
7770c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
a1af5a
368808 ¤   ctx = (PrsBinContext *)myself->priv;
a6d6bc ¤   pgpAssert (ctx);
bd1728 ¤   pgpAssert (ctx->tail);
9caf5a
73c9e4 ¤   /* Do a write to force out any hanging data */
9173ed ¤   myself->write (myself, (PGPByte const *)0, (size_t)0, &error);
93b957 ¤   return error ? error : ctx->tail->flush (ctx->tail);
7defe6 }
75af5a
65f1ae static PGPError
4d13c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
79b0b1 ¤   ··PGPByte const *string, size_t size)
97bb36 {
0ee07e ¤   PrsBinContext *ctx;
7587a6 ¤   PGPError¤   error;
9df2d7 ¤   PGPByte const *oldbufptr;
0f6654 ¤   size_t (*oldwrite)(PGPPipeline *, PGPByte const *, size_t, PGPError *);
44af5a
ae29be ¤   pgpAssert (myself);
4170c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
c0af5a
e78808 ¤   ctx = (PrsBinContext *)myself->priv;
c4d6bc ¤   pgpAssert (ctx);
081728 ¤   pgpAssert (ctx->tail);
18af5a
bd7f93 ¤   /* Do any expected callbacks */
eafd51 ¤   if (ctx->needcallback) {
cd6cfd ¤   ¤   switch (type) {
d40695 ¤   ¤   case PGPANN_PARSER_EATIT:
c844e6 ¤   ¤   case PGPANN_PARSER_PASSTHROUGH:
e39044 ¤   ¤   case PGPANN_PARSER_PROCESS:
81f0c8 ¤   ¤   case PGPANN_PARSER_RECURSE:
657578 ¤   ¤   ¤   return ProcessCallback (myself, type, string, size);
650fe4 ¤   ¤   }
859371 ¤   }
66af5a
3ad8af ¤   /*
f335f4 ¤   ·* If this is a hash request callback, and we have the
054b4b ¤   ·* requested hash being computed, copy it, hash in the
f19380 ¤   ·* extra bytes, and pass back the resultant hash.
01a4e3 ¤   ·*/
1dd1b1 ¤   if (type == PGPANN_HASH_REQUEST) {
b9113f ¤   ¤   PGPHashContext const *hc;
cd345a ¤   ¤   PGPHashContext *temp_hc;
41af5a
a837e0 ¤   ¤   if (!size || IsNull( ctx->hashes ))
e1ce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
0bd4aa ¤   ¤   hc = pgpHashListFind(ctx->hashes,
8c20e9 ¤   ¤   ¤   ¤   ·····pgpHashByNumber( (PGPHashAlgorithm) string[1]));
9d397f ¤   ¤   if (!hc)
ebce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
88ed0e ¤   ¤   temp_hc = pgpHashCopy (hc);
34fe11 ¤   ¤   if (!temp_hc)
157cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
0ee30d ¤   ¤   PGPContinueHash (temp_hc, string+2, size-2);
87ecd1 ¤   ¤   if (string[0] == PGPVERSION_4) {
0b8c3f ¤   ¤   ¤   /* New hash format includes an anti-aliasing postscript */
e46ecc ¤   ¤   ¤   PGPByte postscript[6];
17f66a ¤   ¤   ¤   postscript[0] = PGPVERSION_4;¤  /* actually a 4! */
3782f5 ¤   ¤   ¤   postscript[1] = 0xff;¤  ¤   ¤   /* different from sig type */
5ed3b9 ¤   ¤   ¤   postscript[2] = (PGPByte)((size-2)>>24);
94d7f0 ¤   ¤   ¤   postscript[3] = (PGPByte)((size-2)>>16);
64246f ¤   ¤   ¤   postscript[4] = (PGPByte)((size-2)>> 8);
4de144 ¤   ¤   ¤   postscript[5] = (PGPByte)((size-2)>> 0);
c1b946 ¤   ¤   ¤   PGPContinueHash (temp_hc, postscript, sizeof(postscript));
d10fe4 ¤   ¤   }
e9332b ¤   ¤   error = ctx->tail->annotate (ctx->tail, origin,
4901b7 ¤   ¤   ¤   ¤   ¤   ·····PGPANN_HASH_VALUE,
08f398 ¤   ¤   ·····························(PGPByte *) pgpHashFinal(temp_hc),
--12d5 000adbd5b2f40100197 Page 41 of pgpPrsBin.c
f971fe ¤   ¤   ·····························pgpHashGetVTBL( hc )->hashsize);
8b8c0d ¤   ¤   PGPFreeHashContext (temp_hc);
18af5a
76fcee ¤   ¤   return error;
289371 ¤   }
6aaf5a
e4d8af ¤   /*
c8263e ¤   ·* Now, ensure that we have written out everything buffered that
ad2efd ¤   ·* we plan on writing out. ·Run the state machine forward until
09eb70 ¤   ·* it stops changing.
bba4e3 ¤   ·*/
8c43ab ¤   do {
19204b ¤   ¤   oldbufptr = ctx->input.bufptr;
85360e ¤   ¤   oldwrite = myself->write;
0632cd ¤   ¤   (void)oldwrite(myself, 0, 0, &error);
8be3c2 ¤   ¤   if (error)
4a3b5b ¤   ¤   ¤   return error;
e3e767 ¤   } while (ctx->input.bufptr != oldbufptr || myself->write != oldwrite);
2eaf5a
114e2e ¤   return ctx->tail->annotate (ctx->tail, origin, type, string, size);
42efe6 }
a7af5a
84f1ae static PGPError
d34b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
3abb36 {
c5e07e ¤   PrsBinContext *ctx;
f387a6 ¤   PGPError¤   error;
7ef2d7 ¤   PGPByte const *oldbufptr;
706654 ¤   size_t (*oldwrite)(PGPPipeline *, PGPByte const *, size_t, PGPError *);
66af5a
d829be ¤   pgpAssert (myself);
e970c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
aeaf5a
438808 ¤   ctx = (PrsBinContext *)myself->priv;
b2d6bc ¤   pgpAssert (ctx);
3b1728 ¤   pgpAssert (ctx->tail);
c2af5a
cad8af ¤   /*
4d8dcc ¤   ·* If we're in the middle of a packet that can be truncated
02d793 ¤   ·* without error, deal with it.
3ea4e3 ¤   ·*/
484c89 ¤   if (ctx->input.silent_trunc && ctx->input.head.pktlen > bytes)
766b06 ¤   ¤   ctx->input.head.pktlen = bytes;
4dd8af ¤   /*
a77de2 ¤   ·* Set eof flag, which a few of the parsing functions need
49eba5 ¤   ·* to do special things at EOF when the default processing here
1714da ¤   ·* is not desired.
55a4e3 ¤   ·*/
aca8f9 ¤   if (!bytes)
bbf745 ¤   ¤   ctx->eof = 1;
e4d8af ¤   /*
44263e ¤   ·* Now, ensure that we have written out everything buffered that
c72efd ¤   ·* we plan on writing out. ·Run the state machine forward until
1beb70 ¤   ·* it stops changing.
40a4e3 ¤   ·*/
de43ab ¤   do {
a3204b ¤   ¤   oldbufptr = ctx->input.bufptr;
7a360e ¤   ¤   oldwrite = myself->write;
a732cd ¤   ¤   (void)oldwrite(myself, 0, 0, &error);
43e3c2 ¤   ¤   if (error)
a53b5b ¤   ¤   ¤   return error;
a1e767 ¤   } while (ctx->input.bufptr != oldbufptr || myself->write != oldwrite);
1eaf5a
35d8af ¤   /*
162fc7 ¤   ·* Are we shutting down, yet not in a clean-shutdown state?
ca0cf2 ¤   ·* (No pending packets, no bytes waiting to be parsed.)
33a4e3 ¤   ·*/
e19b18 ¤   if (!bytes && !inputFinished(&ctx->input.head)) {
e78eab ¤   ¤   if (!ctx->input.silent_trunc) {
99f561 ¤   ¤   ¤   error = (PGPError)(ctx->end_scope ? PGPANN_SCOPE_TRUNCATED :
c624ca ¤   ¤   ¤   ¤   ¤   ¤   ·PGPANN_PACKET_TRUNCATED);
ad1432 ¤   ¤   ¤   error = ctx->tail->annotate (ctx->tail, myself,
--f79a 000d902415040100197 Page 42 of pgpPrsBin.c
58fdf1 ¤   ¤   ¤   ·····························error, 0, 0);
51d82b ¤   ¤   ¤   if (error)
b5b20f ¤   ¤   ¤   ¤   return error;
97a1eb ¤   ¤   ¤   ctx->input.silent_trunc = 1;¤   /* Don't repeat */
4b0fe4 ¤   ¤   }
b4af5a
ac4eab ¤   ¤   /* Let nextScope do the cleanup. */
79692e ¤   ¤   myself->write = nextScope;
9aa5ef ¤   ¤   (void)nextScope(myself, 0, 0, &error);
61e3c2 ¤   ¤   if (error)
303b5b ¤   ¤   ¤   return error;
8d9371 ¤   }
5daf5a
9cd8af ¤   /*
2b7c62 ¤   ·* Send down a final annotation...
74a4e3 ¤   ·*/
27210f ¤   if (!bytes && ctx->end_scope == 0)
8a716a ¤   ¤   return ctx->tail->sizeAdvise (ctx->tail, 0);
77151e ¤   return kPGPError_NoErr;
63efe6 }
88af5a
8bf1ae static PGPError
bdc7e1 Teardown (PGPPipeline *myself)
50bb36 {
38e07e ¤   PrsBinContext *ctx;
17e9fa ¤   PGPContextRef¤  cdkContext;
bb67c5 ¤
dd3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
93696e ¤   cdkContext¤ = myself->cdkContext;
c8af5a
7229be ¤   pgpAssert (myself);
1f70c7 ¤   pgpAssert (myself->magic == PARSERMAGIC);
eaaf5a
848808 ¤   ctx = (PrsBinContext *)myself->priv;
bdd6bc ¤   pgpAssert (ctx);
b0af5a
5f36ed ¤   if (ctx->tail)
c4f61c ¤   ¤   ctx->tail->teardown (ctx->tail);
ccaf5a
7cf693 ¤   pgpFifoDestroy (&pgpByteFifoDesc, ctx->input.fifo);
71fd9c ¤   pgpClearMemory( ctx, ·sizeof (*ctx));
a066c5 ¤   pgpContextMemFree( cdkContext, ctx);
9567c5 ¤
b9151e ¤   return kPGPError_NoErr;
22efe6 }
15af5a
c141cd PGPPipeline **
1b164e pgpParseBinCreate (
53fdf9 ¤   PGPContextRef cdkContext,
57a296 ¤   PGPPipeline **head, PGPEnv const *env,
a956eb ¤   PGPUICb const *ui, void *ui_arg )
abbb36 {
0e0df0 ¤   PGPPipeline *mod;
c5e07e ¤   PrsBinContext *ctx;
a9af5a
ef92bd ¤   if (!head || !env)
447ed2 ¤   ¤   return NULL;
85af5a
0737bf ¤   ctx = (PrsBinContext *)pgpContextMemAlloc( cdkContext,
f7faef ¤   ¤   sizeof (*ctx), kPGPMemoryMgrFlags_Clear);
59a2ae ¤   if (!ctx)
6b7ed2 ¤   ¤   return NULL;
9a3efe ¤   mod = &ctx->pipe;
65af5a
5a1c28 ¤   ctx->input.fifo = pgpFifoCreate (cdkContext, &pgpByteFifoDesc);
f4fa20 ¤   if (!ctx->input.fifo) {
83607d ¤   ¤   pgpContextMemFree( cdkContext, ctx);
dd7ed2 ¤   ¤   return NULL;
499371 ¤   }
8aa3a3 ¤   inputReset(&ctx->input);
02d073 ¤   ctx->findpkt = 1;
d929b1 ¤   ctx->env = env;
--98a2 00191917aa940100197 Page 43 of pgpPrsBin.c
def10a ¤   ctx->ui = ui;
4db2c2 ¤   ctx->ui_arg = ui_arg;
3caf5a
37afa8 ¤   mod->magic = PARSERMAGIC;
243dbc ¤   mod->write = parsePacket;
08ac4e ¤   mod->flush = Flush;
7c0aaf ¤   mod->sizeAdvise = SizeAdvise;
40d3a2 ¤   mod->annotate = Annotate;
8d96de ¤   mod->teardown = Teardown;
1d1e14 ¤   mod->name = "PGP Message Parser";
caf051 ¤   mod->priv = ctx;
9fa99e ¤   mod->cdkContext¤= cdkContext;
acaf5a
9329d6 ¤   ctx->tail = *head;
e22d11 ¤   *head = mod;
1956ab ¤   return &ctx->tail;
91efe6 }
--d1cd 001fd13665240100198 Page 1 of pgpPrsBin.h
bc38e5 /*
349102 ·* pgpPrsBin.h -- The PGP Binary Message parser
50775e ·*
227ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
3e775e ·*
b5d625 ·* $Id: pgpPrsBin.h,v 1.9 1998/06/03 20:31:59 hal Exp $
bc495d ·*/
f8af5a
fb6de4 #ifndef Included_pgpPrsBin_h
72ecd2 #define Included_pgpPrsBin_h
68af5a
97adb8 #include "pgpOpaqueStructs.h"
97e82c #include "pgpPubTypes.h"
e0d11f #include "pgpUsuals.h"
a9af5a
af99c6 PGP_BEGIN_C_DECLARATIONS
c1af5a
95af5a
7338e5 /*
be5176 ·* Create a binary parser module. ·This module will read in data,
e932c5 ·* figure out what kind of PGP message it is, and create the
db867c ·* appropriate sub-modules to actually decode the message, depending
618876 ·* on the user's wishes.
84775e ·*
68ccfb ·* It communicated with the Annotation Reader, which is a part of the
edbb43 ·* User Interface, to explain exactly what is going on with the
21952e ·* decoding process. ·This module, once the pipeline is put into
3dfd5a ·* action, will add and delete modules downstream.
4a495d ·*/
8ca738 PGPPipeline ·**pgpParseBinCreate (
c5bdc1 ¤   ¤   PGPContextRef cdkContext, PGPPipeline **head,
124d12 ¤   ¤   ¤   ¤   ¤   PGPEnv const *env, PGPUICb const *ui, void *ui_arg);
ebaf5a
8d1254 PGP_END_C_DECLARATIONS
2aaf5a
fdfb88 #endif /* Included_pgpPrsBin_h */
--1161 000704eafcf40100199 Page 1 of pgpReadAnn.c
bc38e5 /*
e613df ·* pgpReadAnn.c -- Annotation Reader
43775e ·*
1a9f38 ·* Written by:¤ Colin Plumb and Derek Atkins <warlord@MIT.EDU>
4d775e ·*
c3aaf7 ·* $Id: pgpReadAnn.c,v 1.27 1998/07/08 20:04:45 hal Exp $
8c495d ·*/
a2e2ff #include "pgpConfig.h"
3faf5a
c1feb2 #include <stdio.h>
13495d #include <errno.h>
e8324c #include <string.h>
25af5a
86a146 #include "pgpDebug.h"
ceb4d8 #include "pgpReadAnn.h"
bf3baa #include "pgpVrfySig.h"
2c6aaa #include "pgpAnnotate.h"
b657c7 #include "pgpESK.h"
ca5417 #include "pgpHashPriv.h"
a30d08 #include "pgpMem.h"
4b2f8d #include "pgpErrors.h"
af1bea #include "pgpMsg.h"
a1e117 #include "pgpUI.h"
862ece #include "pgpPipeline.h"
6b43bc #include "pgpSig.h"
003576 #include "pgpTextFilt.h"
acd11f #include "pgpUsuals.h"
6ac26c #include "pgpContext.h"
01af5a
c39f0c #define READANNOTATIONMAGIC¤0xf00b0b
f8af5a
c7236a /* should never have more than this many nested scopes! */
ce0ddd #define MAX_RECURSE 50
d0af5a
923ab5 typedef struct ReadAnnContext {
97f8fb ¤   PGPPipeline¤¤   pipe;
a167c5 ¤
5221b1 ¤   int stack[MAX_RECURSE];
fad39a ¤   int sp;
1ac78e ¤   int file_sp;
ab29f6 ¤   int type;
f72d7d ¤   char *name;
6d75b0 ¤   PGPPipeline *tail;
bb470a ¤   PGPUICb const *ui;
f4ee3d ¤   PGPEnv const *env;
415f9a ¤   void *ui_arg;
2fbf96 ¤   PGPESK *esklist;
c275d1 ¤   PGPSig *siglist[MAX_RECURSE];
2d640c ¤   PGPByte sepsig[MAX_RECURSE];
7e9255 ¤   /* For the sigverify callback-callback to check the signature */
9f7ac8 ¤   PGPSig const *cursig;
838c36 ¤   /* flag -- do we need a new output? */
2607d8 ¤   PGPByte newoutput;
c2f3a8 ¤   DEBUG_STRUCT_CONSTRUCTOR( ReadAnnContext )
fcba69 } ReadAnnContext;
a3af5a
5f2066 typedef struct TryCB {
6a3b4b ¤   PGPPipeline *myself, *origin;
78f394 ¤   int reply;
99bc71 } TryCB;
67af5a
d65d09 static size_t
1bf37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
d5bb36 {
4c28ad ¤   ReadAnnContext *context;
6eaf5a
d629be ¤   pgpAssert (myself);
445213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
9caf5a
1a58a3 ¤   context = (ReadAnnContext *)myself->priv;
02d30a ¤   pgpAssert (context);
704866 ¤   pgpAssert (error);
--a47c 000515ec99b40100199 Page 2 of pgpReadAnn.c
e0af5a
4c3828 ¤   if (context->newoutput) {
675292 ¤   ¤   *error = (PGPError)context->ui->newOutput (context->ui_arg,
1596c1 ¤   ¤   ¤   ¤   ¤   ¤   ·&context->tail,
da4437 ¤   ¤   ¤   ¤   ¤   ¤   ·context->type,
978ba7 ¤   ¤   ¤   ¤   ¤   ¤   ·context->name);
a2cf31 ¤   ¤   if (*error)
6d33bc ¤   ¤   ¤   return kPGPError_NoErr;
a1af5a
4a18be ¤   ¤   /* Remember scope to close output */
ef2414 ¤   ¤   context->file_sp = context->sp;
01c6a0 ¤   ¤   context->newoutput = 0;
1e9371 ¤   }
4aaf5a
42ebf4 ¤   pgpAssert (context->tail);
bbf618 ¤   return context->tail->write (context->tail, buf, size, error);¤
f4efe6 }
deaf5a
be66dd ¤   static PGPError
bdec9b sighash(PGPPipeline *myself, PGPPipeline *origin, int reply)
b5bb36 {
3528ad ¤   ReadAnnContext *context;
abd259 ¤   PGPByte *buf;
bab42e ¤   PGPError¤   ·err;
50c6b5 ¤   unsigned len;
9de9fa ¤   PGPContextRef¤  cdkContext;
4c67c5 ¤
d73982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
b6696e ¤   cdkContext¤ = myself->cdkContext;
4caf5a
e629be ¤   pgpAssert (myself);
3d5213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
a4af5a
c358a3 ¤   context = (ReadAnnContext *)myself->priv;
1dd30a ¤   pgpAssert (context);
39af5a
82aea3 ¤   /* Build list of hashes we need */
7b4463 ¤   len = pgpSigDistinctHashCount(context->siglist[context->sp-1]);
fc1bef ¤   buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
d9ca51 ¤   ¤   len, kPGPMemoryMgrFlags_Clear);
7120df ¤   if (!buf)
ed4030 ¤   ¤   return kPGPError_OutOfMemory;
f3c2fd ¤   pgpSigDistinctHashes(context->siglist[context->sp-1], buf);
49af5a
804a01 ¤   /* Tell the parser to do the hashes */
ce36d0 ¤   err = origin->annotate (origin, myself, reply, buf, len);
f10449 ¤   pgpContextMemFree( cdkContext, buf);
aa5ea8 ¤   return err;
b4efe6 }
2daf5a
4a5e0b /* Try out all the hashes */
643501 /* (Note that this is called with context->sp already decremented) */
1cbeb7 static int
7e52e0 sigtry (PGPPipeline *myself, PGPPipeline *origin)
34bb36 {
3228ad ¤   ReadAnnContext *context;
99d259 ¤   PGPByte *buf;
0c69cc ¤   PGPByte const *extra;
b527ed ¤   unsigned extralen;
f32cac ¤   PGPSig const *sig;
0a87a6 ¤   PGPError¤   error;
97af5a
1a29be ¤   pgpAssert (myself);
e65213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
beaf5a
5c58a3 ¤   context = (ReadAnnContext *)myself->priv;
71d30a ¤   pgpAssert (context);
caaf5a
a06312 ¤   for (sig = context->siglist[context->sp]; sig;
bf776e ¤   ¤   ¤   ¤   ¤   ··sig = pgpSigNext (sig)) {
1c5884 ¤   ¤   extra = pgpSigExtra(sig, &extralen);
51ea3d ¤   ¤   buf = (PGPByte *)pgpContextMemAlloc(myself->cdkContext, extralen+2, 0);
--a0ba 0004877b33840100199 Page 3 of pgpReadAnn.c
f9094c ¤   ¤   if( IsNull( buf ) )
8d7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
d6ef65 ¤   ¤   buf[0] = pgpSigVersion(sig);
3ac45e ¤   ¤   buf[1] = pgpSigHash(sig)->algorithm;
a11697 ¤   ¤   memcpy(buf+2, extra, extralen);
a353ec ¤   ¤   context->cursig = sig;
672308 ¤   ¤   /* This ends up invoking sigverify, below */
8ab33a ¤   ¤   error = origin->annotate (origin, myself,
2ed52c ¤   ¤   ¤   ¤   ¤   ··PGPANN_HASH_REQUEST,
bee7ba ¤   ¤   ¤   ¤   ¤   ··buf, extralen+2);
b6e7f8 ¤   ¤   if (error) {
347a70 ¤   ¤   ¤   context->ui->message (context->ui_arg, error,
d1059c ¤   ¤   ¤   ¤   ¤   ······PGPMSG_SIG_ERROR, 0);
060fe4 ¤   ¤   }
ab7106 ¤   ¤   pgpClearMemory( buf, ·extralen+2 );
91c05b ¤   ¤   pgpContextMemFree( myself->cdkContext, buf );
d59371 ¤   }
9fd892 ¤   context->cursig = 0;
716f79 ¤   pgpSigFreeList (context->siglist[context->sp]);
3979cc ¤   context->siglist[context->sp] = 0;
453e6b ¤   return 0;
87efe6 }
d1af5a
599693 /* Get the callback from the callback... */
2d3501 /* (Note that this is called with context->sp already decremented) */
05beb7 static int
674cc2 sigverify(PGPPipeline *myself, PGPByte const *string, size_t size)
41bb36 {
8a28ad ¤   ReadAnnContext *context;
793d22 ¤   PGPHashVTBL const *hash;
a4af5a
532308 ¤   (void)size;¤¤   /* Avoid warning */
8529be ¤   pgpAssert (myself);
605213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
66af5a
9858a3 ¤   context = (ReadAnnContext *)myself->priv;
ddd30a ¤   pgpAssert (context);
393718 ¤   pgpAssert (context->cursig);
9baf5a
2f6012 ¤   hash = pgpSigHash (context->cursig);
fd2269 ¤   pgpAssert (hash);
f253c1 ¤   pgpAssert (size == hash->hashsize);
09af5a
501bbe ¤   return context->ui->sigVerify (context->ui_arg, context->cursig,
e9bb4a ¤   ¤   ¤   ¤   ·······string);
b3efe6 }
5caf5a
e6beb7 static int
2be9cb sepsighash (ReadAnnContext *context)
98bb36 {
7017e6 ¤   int err;
00af5a
09145c ¤   err = pgpSepsigVerify (context->siglist[context->sp-1], context->env,
10c5e4 ¤   ¤   ¤   ·······context->ui, context->ui_arg);
30543d ¤   pgpSigFreeList (context->siglist[context->sp-1]);
1d6a84 ¤   context->siglist[context->sp-1] = 0;
6baf5a
745ea8 ¤   return err;
9eefe6 }
8eaf5a
0338e5 /*
a9d7a8 ·* Try a single key to see if it works.
86495d ·*/
f0beb7 static int
d3373e eskTryKey (void *arg, PGPByte const *key, PGPSize keylen)
edbb36 {
fc6bc3 ¤   TryCB const *cb = (TryCB *)arg;
23af5a
aae6f5 ¤   pgpAssert (cb);
f6fc1f ¤   pgpAssert (cb->myself);
558afd ¤   pgpAssert (cb->myself->magic == READANNOTATIONMAGIC);
4857cd ¤   pgpAssert (cb->origin);
--fa27 000f6a6b5ba40100199 Page 4 of pgpReadAnn.c
e0af5a
c4c9da ¤   return cb->origin->annotate (cb->origin, cb->myself, cb->reply,
b7075a ¤   ¤   ¤   ¤   ·····key, keylen);
c7efe6 }
83af5a
ae38e5 /*
ea0a12 ·* Decrypt an PGPESK from an esklist -- this calls the UI function to
a31bef ·* decrypt an esklist. ·Uses the eskTryKey function to try the keys,
e998f9 ·* and pre-allocates a buffer which is the largest possible PGPESK from
f05c9d ·* all the PgpESKs in the list. ·Returns 0 or an error.
5e495d ·*/
aabeb7 static int
04507b eskdecrypt (PGPPipeline *myself, PGPPipeline *origin, int reply)
c0bb36 {
083a4b ¤   TryCB cb;
7128ad ¤   ReadAnnContext *context;
11137d ¤   PGPESK const *esk;
db69f7 ¤   PGPByte *buf = 0;
a0ea78 ¤   int i, buflen = 0;
428f1d ¤   PGPSize keylen = 0;
59e9fa ¤   PGPContextRef¤  cdkContext;
7c67c5 ¤
063982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
80696e ¤   cdkContext¤ = myself->cdkContext;
7faf5a
2c29be ¤   pgpAssert (myself);
5d5213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
41af5a
4b58a3 ¤   context = (ReadAnnContext *)myself->priv;
83d30a ¤   pgpAssert (context);
5baf5a
e9a8c6 ¤   cb.myself = myself;
8e6d90 ¤   cb.origin = origin;
6bbee0 ¤   cb.reply = reply;
c1af5a
15acb0 ¤   /* Figure out the size of the largest PGPESK */
232179 ¤   for (esk = context->esklist; esk; esk = pgpEskNext(esk)) {
3e700c ¤   ¤   i = pgpEskMaxKeySize (esk);
06af5a
d3df99 ¤   ¤   if (buflen < i)
eb386a ¤   ¤   ¤   buflen = i;
c69371 ¤   }
32af5a
3e339a ¤   if (buflen) {
e274dc ¤   ¤   buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
fc73af ¤   ¤   ¤   buflen, kPGPMemoryMgrFlags_Clear);
dda56a ¤   ¤   if (!buf)
257cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
242be7 ¤   } else
f562b5 ¤   ¤   return kPGPError_BadParams;
75af5a
569ab5 ¤   keylen = (size_t)buflen;
ef0166 ¤   i = context->ui->eskDecrypt (context->ui_arg, context->esklist, buf,
093c91 ¤   ¤   ¤   ¤   ·····&keylen, eskTryKey, &cb);
9daf5a
ac0337 ¤   pgpClearMemory( buf, ·buflen);
2e0449 ¤   pgpContextMemFree( cdkContext, buf);
03dcfc ¤   pgpEskFreeList (context->esklist);
3c4ff3 ¤   context->esklist = 0;
8baf5a
3614b5 ¤   if (i) {
53544e ¤   ¤   /* Cannot decrypt... ·Either eatit or passthrough */
bc730f ¤   ¤   if (i != PGPANN_PARSER_EATIT && i != PGPANN_PARSER_PASSTHROUGH)
bc9eb9 ¤   ¤   ¤   return i;
f8af5a
22c909 ¤   ¤   cb.reply = i;¤  /* What to do? */
f095fe ¤   ¤   i = eskTryKey (&cb, NULL, 0);
9b9371 ¤   }
f8af5a
0b2196 ¤   return i;
1fefe6 }
f6af5a
--7694 000ca2b9ae240100199 Page 5 of pgpReadAnn.c
f3f1ae static PGPError
c713c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
42b0b1 ¤   ··PGPByte const *string, size_t size)
9dbb36 {
b828ad ¤   ReadAnnContext *context;
395b01 ¤   PGPError¤   error = kPGPError_NoErr;
5a4ba4 ¤   int i;
bee79a ¤   PgpUICbArg msgarg1;
15e9fa ¤   PGPContextRef¤  cdkContext;
4967c5 ¤
883982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
72696e ¤   cdkContext¤ = myself->cdkContext;
11af5a
7c29be ¤   pgpAssert (myself);
205213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
60af5a
3c58a3 ¤   context = (ReadAnnContext *)myself->priv;
6bd30a ¤   pgpAssert (context);
aaaf5a
b376c7 ¤   if (PGP_IS_SCOPE_MARKER (type)) {
505414 ¤   ¤   if (PGP_IS_BEGIN_SCOPE (type)) {
50c10f ¤   ¤   ¤   context->stack[context->sp++] = type;
f045a6 ¤   ¤   } else {
c2453b ¤   ¤   ¤   pgpAssert(PGP_IS_END_SCOPE (type));
c8af5a
e1eeff ¤   ¤   ¤   if (context->stack[context->sp - 1] != type - 1)
767931 ¤   ¤   ¤   ¤   context->ui->message (context->ui_arg,
dce33b ¤   ¤   ¤   ¤   ¤   ¤   ······kPGPError_UnbalancedScope,
c629f3 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPMSG_UNBALANCED_SCOPE,
24e4af ¤   ¤   ¤   ¤   ¤   ¤   ······0);
c0e543 ¤   ¤   ¤   else {
1782e0 ¤   ¤   ¤   ¤   context->stack[--context->sp] = 0;
19d0b0 ¤   ¤   ¤   ¤   context->sepsig[context->sp] = 0;
72a3a6 ¤   ¤   ¤   }
f1af5a
b40fe4 ¤   ¤   }
aa1b17 ¤   ¤   /*
965f5c ¤   ¤   ·* For clearsigned messages, preserve type. ·See comments
6451c1 ¤   ¤   ·* re PGPANN_CLEARSIG_BEGIN/END below. ·Otherwise go back
ad71a3 ¤   ¤   ·* to type of next annotation on the stack.
c29de3 ¤   ¤   ·*/
c1d3c3 ¤   ¤   if (!(type==PGPANN_ARMOR_BEGIN &&
87e50d ¤   ¤   ¤   ¤   ¤   ······context->type==PGP_LITERAL_TEXT))
7c4cd9 ¤   ¤   ¤   if (context->sp)
c66729 ¤   ¤   ¤   ¤   context->type = context->stack[context->sp-1];
bd9371 ¤   }
9baf5a
1aa43c ¤   if (context->ui->annotate) {
313d43 ¤   ¤   error = (PGPError)context->ui->annotate (context->ui_arg, origin,
e002d4 ¤   ¤   ¤   ¤   ¤   ·······type, string, size);
a2e3c2 ¤   ¤   if (error)
ca3b5b ¤   ¤   ¤   return error;
789371 ¤   }
b6af5a
b81609 ¤   switch (type) {
9646d7 ¤   case PGPANN_COMMIT:
e94392 ¤   ¤   do {
0a19ff ¤   ¤   ¤   i = context->ui->doCommit·
6b566f ¤   ¤   ¤   ¤   (context->ui_arg,
fcb23f ¤   ¤   ¤   ¤   ·context->stack[context->sp - 1]);
f3af5a
86ef4a ¤   ¤   ¤   /* Allow commit function to abort us */
ff8a35 ¤   ¤   ¤   if (i < 0) {
65590c ¤   ¤   ¤   ¤   return i;
f6a3a6 ¤   ¤   ¤   }
2faf5a
07609e ¤   ¤   ¤   if (i != PGPANN_PARSER_PASSTHROUGH &&
af4413 ¤   ¤   ¤   ····i != PGPANN_PARSER_EATIT &&
11f295 ¤   ¤   ¤   ····i != PGPANN_PARSER_PROCESS &&
f0f8ca ¤   ¤   ¤   ····i != PGPANN_PARSER_RECURSE) {
526116 ¤   ¤   ¤   ¤   msgarg1.type = PGP_UI_ARG_INT;
cac4c1 ¤   ¤   ¤   ¤   msgarg1.val.i = i;
--dc38 000109d758740100199 Page 6 of pgpReadAnn.c
537931 ¤   ¤   ¤   ¤   context->ui->message (context->ui_arg,
4343bd ¤   ¤   ¤   ¤   ¤   ¤   ······kPGPError_InvalidCommit,
450ed9 ¤   ¤   ¤   ¤   ¤   ¤   ······PGPMSG_COMMIT_INVALID,
cabdb7 ¤   ¤   ¤   ¤   ¤   ¤   ······1,
84ae21 ¤   ¤   ¤   ¤   ¤   ¤   ······&msgarg1);
63d040 ¤   ¤   ¤   ¤   continue;
a3a3a6 ¤   ¤   ¤   }
e5af5a
12ca18 ¤   ¤   ¤   if (i < PGPANN_PARSER_PROCESS) {
314333 ¤   ¤   ¤   ¤   error = origin->annotate (origin, myself, i,
172534 ¤   ¤   ¤   ¤   ··························0, 0);
ee4c20 ¤   ¤   ¤   ¤   if (error)·
12aa19 ¤   ¤   ¤   ¤   ¤   context->ui->message
6e8052 ¤   ¤   ¤   ¤   ¤   ¤   (context->ui_arg, error,
a675ff ¤   ¤   ¤   ¤   ¤   ¤   ·PGPMSG_ANNOTATE_ERROR, 0);
67b3b7 ¤   ¤   ¤   } else if (context->stack[context->sp-1] ==
76d0e5 ¤   ¤   ¤   ··························PGPANN_CIPHER_BEGIN) {
307ed3 ¤   ¤   ¤   ¤   error = (PGPError)eskdecrypt(myself, origin, i);
4f6274 ¤   ¤   ¤   ¤   if (error) {
ebaa19 ¤   ¤   ¤   ¤   ¤   context->ui->message
7f8052 ¤   ¤   ¤   ¤   ¤   ¤   (context->ui_arg, error,
ce0553 ¤   ¤   ¤   ¤   ¤   ¤   ·PGPMSG_ESK_NODECRYPT, 0);
d714c3 ¤   ¤   ¤   ¤   ¤   break;
922613 ¤   ¤   ¤   ¤   }
41b3b7 ¤   ¤   ¤   } else if (context->stack[context->sp-1] ==
8b4ee1 ¤   ¤   ¤   ··························PGPANN_SIGNED_BEGIN) {
05ed00 ¤   ¤   ¤   ¤   if (context->sepsig[context->sp-1]) {
fb37ea ¤   ¤   ¤   ¤   ¤   error = (PGPError)sepsighash(context);
1fd922 ¤   ¤   ¤   ¤   ¤   if (error) {
79aca1 ¤   ¤   ¤   ¤   ¤   ¤   context->ui->message
b1b89c ¤   ¤   ¤   ¤   ¤   ¤   ···(context->ui_arg, error,
a5a1c3 ¤   ¤   ¤   ¤   ¤   ¤   ····PGPMSG_SEPSIG_NOVERIFY, 0);
d300eb ¤   ¤   ¤   ¤   ¤   ¤   break;
8c1c89 ¤   ¤   ¤   ¤   ¤   }
91b5fc ¤   ¤   ¤   ¤   } else {
9ead04 ¤   ¤   ¤   ¤   ¤   error = (PGPError)sighash(myself, origin, i);
ecd922 ¤   ¤   ¤   ¤   ¤   if (error) {
24aca1 ¤   ¤   ¤   ¤   ¤   ¤   context->ui->message
37b89c ¤   ¤   ¤   ¤   ¤   ¤   ···(context->ui_arg, error,
8dab1f ¤   ¤   ¤   ¤   ¤   ¤   ····PGPMSG_SIG_NOVERIFY, 0);
9100eb ¤   ¤   ¤   ¤   ¤   ¤   break;
901c89 ¤   ¤   ¤   ¤   ¤   }
ab2613 ¤   ¤   ¤   ¤   }
e1042d ¤   ¤   ¤   } else {
ba4333 ¤   ¤   ¤   ¤   error = origin->annotate (origin, myself, i,
132534 ¤   ¤   ¤   ¤   ··························0, 0);
153aca ¤   ¤   ¤   ¤   if (error)
89aa19 ¤   ¤   ¤   ¤   ¤   context->ui->message
2c8052 ¤   ¤   ¤   ¤   ¤   ¤   (context->ui_arg, error,
f575ff ¤   ¤   ¤   ¤   ¤   ¤   ·PGPMSG_ANNOTATE_ERROR, 0);
92a3a6 ¤   ¤   ¤   }
f6867c ¤   ¤   ¤   /* The idea of looping until the error goes away does not seem
708c77 ¤   ¤   ¤   ·* practical. ·If it failed once, it will almost always fail
0cc71f ¤   ¤   ¤   ·* again.
2e8753 ¤   ¤   ¤   ·*/
6fd82b ¤   ¤   ¤   if (error)
a4b20f ¤   ¤   ¤   ¤   return error;
3434f6 ¤   ¤   } while (error);
d42f68 ¤   ¤   break;
7caf93 ¤   case PGPANN_PKCIPHER_ESK:
092cad ¤   case PGPANN_SKCIPHER_ESK:
74406a ¤   ¤   i = pgpEskAdd( cdkContext, &context->esklist, type, string, size);
2f69c6 ¤   ¤   if (i != 0) {
b917be ¤   ¤   ¤   context->ui->message (context->ui_arg, i,
a8d55e ¤   ¤   ¤   ¤   ¤   ······PGPMSG_ESK_ADD_ERROR, 0);
c70fe4 ¤   ¤   }
ba2f68 ¤   ¤   break;
47af5a
6dc08d ¤   case PGPANN_SIGNED_SIG:
328017 ¤   case PGPANN_SIGNED_SIG2:
bbb72a ¤   ¤   /* Add signature for */
10bba4 ¤   ¤   i = pgpSigAdd ( cdkContext, &context->siglist[context->sp-1], type,
--1055 000a349b7ac40100199 Page 7 of pgpReadAnn.c
eb6de2 ¤   ¤   ¤   ·······string, size);
6169c6 ¤   ¤   if (i != 0) {
c717be ¤   ¤   ¤   context->ui->message (context->ui_arg, i,
d7ea89 ¤   ¤   ¤   ¤   ¤   ······PGPMSG_SIG_ADD_ERROR, 0);
ff0fe4 ¤   ¤   }
d62f68 ¤   ¤   break;
8daf5a
1a5e29 ¤   case PGPANN_SIGNED_SEP:
301547 ¤   ¤   /* This signature context is for a separate signature */
b4dfe6 ¤   ¤   context->sepsig[context->sp-1] = 1;
112f68 ¤   ¤   break;
9ff710 ¤   case PGPANN_SIGNED_END:
cf305b ¤   ¤   error = (PGPError)sigtry(myself, origin);
6a2f68 ¤   ¤   break;
129976 ¤   case PGPANN_HASH_VALUE:
4e17f2 ¤   ¤   error = (PGPError)sigverify(myself, string, size);
382f68 ¤   ¤   break;
8928cd ¤   case PGPANN_LITERAL_TYPE:
96f72c ¤   ¤   if (size)
7a78df ¤   ¤   ¤   context->type = string[0];
9b2f68 ¤   ¤   break;
61e53d ¤   case PGPANN_LITERAL_NAME:
53c2d4 ¤   ¤   if (size) {
c5b880 ¤   ¤   ¤   if (context->name)
94d30f ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, context->name);
573652 ¤   ¤   ¤   context->name = (char *)pgpContextMemAlloc( cdkContext,
b9ae6a ¤   ¤   ¤   ¤   size+1, kPGPMemoryMgrFlags_Clear);
3cb880 ¤   ¤   ¤   if (context->name)
b9f776 ¤   ¤   ¤   {
9d0362 ¤   ¤   ¤   ¤   memcpy (context->name, string, size);
246019 ¤   ¤   ¤   ¤   context->name[size] = 0;
f6a3a6 ¤   ¤   ¤   }
28bb8c ¤   ¤   ¤   else
0c2f55 ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
9d0fe4 ¤   ¤   }
872f68 ¤   ¤   break;
16d8af ¤   /*
f5dbad ¤   ·* The actual sequence is: PGPANN_CLEARSIG_BEGIN, PGPANN_CLEARSIG_END,
05fed3 ¤   ·* PGPANN_ARMOR_BEGIN, and then we do a Write when we want our type
e8b96f ¤   ·* to be PGP_LITERAL_TEXT. ·So it takes some careful work here and
bd55f1 ¤   ·* above.
d9a4e3 ¤   ·*/
7cf708 ¤   case PGPANN_CLEARSIG_BEGIN:
f92ba8 ¤   case PGPANN_CLEARSIG_END:
bea100 ¤   ¤   /* Clearsigned messages are always text! */
efdb96 ¤   ¤   context->type = PGP_LITERAL_TEXT;
dc2f68 ¤   ¤   break;
a92f72 ¤   default:
7f4779 ¤   ¤   ; /* Do nothing */
049371 ¤   }
0faf5a
5d3332 ¤   /* At end of scope, shut down output */
ba993a ¤   if (!error && PGP_IS_END_SCOPE (type) && context-> sp < context->file_sp)
92c7a1 ¤   {
535deb ¤   ¤   /* We are now closing tail during the annotation callback */
0629e4 ¤   ¤   if (context->tail)
3b1c40 ¤   ¤   ¤   error = context->tail->sizeAdvise (context->tail, 0);
7e47b6 ¤   ¤   if (!error) {
f27e78 ¤   ¤   ¤   if (context->name) {
3dd30f ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, context->name);
fe6863 ¤   ¤   ¤   ¤   context->name = NULL;
4ea3a6 ¤   ¤   ¤   }
ddd630 ¤   ¤   ¤   context->type = -1;
911780 ¤   ¤   ¤   context->newoutput = 1;
270fe4 ¤   ¤   }
c89371 ¤   }
cbaf5a
b2c674 ¤   return error;
2defe6 }
3faf5a
5bf1ae static PGPError
a3d02e Flush (PGPPipeline *myself)
--7914 00022319b6440100199 Page 8 of pgpReadAnn.c
2cbb36 {
fe28ad ¤   ReadAnnContext *context;
0faf5a
b129be ¤   pgpAssert (myself);
685213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
2faf5a
3a58a3 ¤   context = (ReadAnnContext *)myself->priv;
79d30a ¤   pgpAssert (context);
f5af5a
680e36 ¤   if (!context->tail)
06a117 ¤   ¤   return( kPGPError_NoErr );
c1af5a
aa9819 ¤   return context->tail->flush (context->tail);
ffefe6 }
41af5a
0af1ae static PGPError
0c4b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
7abb36 {
5628ad ¤   ReadAnnContext *context;
465b01 ¤   PGPError¤   error = kPGPError_NoErr;
16e9fa ¤   PGPContextRef¤  cdkContext;
b067c5 ¤
a73982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
30696e ¤   cdkContext¤ = myself->cdkContext;
41af5a
ca29be ¤   pgpAssert (myself);
955213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
23af5a
8e58a3 ¤   context = (ReadAnnContext *)myself->priv;
79d30a ¤   pgpAssert (context);
d4af5a
30bfd2 ¤   if (!bytes && context->tail) {
778d61 ¤   ¤   error = context->tail->sizeAdvise (context->tail, bytes);
0547b6 ¤   ¤   if (!error) {
0a7e78 ¤   ¤   ¤   if (context->name) {
c3d30f ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, context->name);
1d6863 ¤   ¤   ¤   ¤   context->name = NULL;
eea3a6 ¤   ¤   ¤   }
04d630 ¤   ¤   ¤   context->type = -1;
091780 ¤   ¤   ¤   context->newoutput = 1;
1c0fe4 ¤   ¤   }
689371 ¤   }
0ec674 ¤   return error;
4befe6 }
55af5a
b9f1ae static PGPError
5ec7e1 Teardown (PGPPipeline *myself)
b9bb36 {
8a28ad ¤   ReadAnnContext *context;
19e9fa ¤   PGPContextRef¤  cdkContext;
6c67c5 ¤
a13982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
d6696e ¤   cdkContext¤ = myself->cdkContext;
40af5a
2f29be ¤   pgpAssert (myself);
df5213 ¤   pgpAssert (myself->magic == READANNOTATIONMAGIC);
97af5a
be58a3 ¤   context = (ReadAnnContext *)myself->priv;
96d30a ¤   pgpAssert (context);
12af5a
d4dcfc ¤   pgpEskFreeList (context->esklist);
f64ff3 ¤   context->esklist = 0;
6d4e49 ¤   if (context->name)
2fd4d6 ¤   ¤   pgpContextMemFree( cdkContext, context->name);
cf6e4d ¤   context->name = 0;
c7cb05 ¤   if (context->tail)
071e8a ¤   ¤   context->tail->teardown (context->tail);
cdaf5a
1a3736 ¤   pgpClearMemory( context, ·sizeof (*context));
15fa6e ¤   pgpContextMemFree( cdkContext, context);
8e67c5 ¤
22151e ¤   return kPGPError_NoErr;
--ad41 001f8a7e06540100199 Page 9 of pgpReadAnn.c
7aefe6 }
46af5a
4841cd PGPPipeline **
ee8d79 pgpAnnotationReaderCreate (
f5fdf9 ¤   PGPContextRef cdkContext,
e98941 ¤   PGPPipeline **head,
ec596d ¤   ¤   ¤   ···PGPEnv const *env,
fdcc48 ¤   ¤   ¤   ···PGPUICb const *ui, void *arg)
f9bb36 {
770df0 ¤   PGPPipeline *mod;
da28ad ¤   ReadAnnContext *context;
96af5a
f892bd ¤   if (!head || !env)
607ed2 ¤   ¤   return NULL;
5faf5a
e22338 ¤   *head = 0;
90af5a
dfcca5 ¤   context = (ReadAnnContext *)pgpContextMemAlloc( cdkContext,
f1d680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
ef1ea4 ¤   if (!context)
8f7ed2 ¤   ¤   return NULL;
559228 ¤   mod = &context->pipe;
d7af5a
fe1628 ¤   mod->magic = READANNOTATIONMAGIC;
a01f83 ¤   mod->write = Write;
35ac4e ¤   mod->flush = Flush;
9e0aaf ¤   mod->sizeAdvise = SizeAdvise;
75d3a2 ¤   mod->annotate = Annotate;
3d96de ¤   mod->teardown = Teardown;
4ebe25 ¤   mod->name = "Simple Annotation Reader";
a201ea ¤   mod->priv = context;
10a99e ¤   mod->cdkContext¤= cdkContext;
c4af5a
1e7d87 ¤   context->ui = ui;
e2eb04 ¤   context->ui_arg = arg;
685b61 ¤   context->env = env;
783122 ¤   context->newoutput = 1;
c98d0b ¤   context->type = -1;
84af5a
e82d11 ¤   *head = mod;
f47fa2 ¤   return &context->tail;
f8efe6 }
--1e43 001dc7dfea64010019a Page 1 of pgpReadAnn.h
bc38e5 /*
8cdbcc ·* pgpReadAnn.h -- A debugging Annotation Reader.
83775e ·*
1e7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
4a775e ·*
e7bde0 ·* $Id: pgpReadAnn.h,v 1.8 1997/06/25 19:40:09 lloyd Exp $
64495d ·*/
5daf5a
5d8343 #ifndef Included_pgpReadAnn_h
19d777 #define Included_pgpReadAnn_h
eaaf5a
11adb8 #include "pgpOpaqueStructs.h"
65e82c #include "pgpPubTypes.h"
7baf5a
1199c6 PGP_BEGIN_C_DECLARATIONS
3caf5a
85af5a
9238e5 /*
209655 ·* Create an annotation reader. ·This will create output files as
6bac15 ·* appropriate. ·If filename is non-NULL, it will use that filename
132b6c ·* as the output file. ·Otherwise it will ask the user or use the name
a59249 ·* out of the message.
5b495d ·*/
19f481 PGPPipeline ·**
688d79 pgpAnnotationReaderCreate (
68fdf9 ¤   PGPContextRef cdkContext,
eb8941 ¤   PGPPipeline **head,
a536a4 ¤   PGPEnv const *env,
e08b7a ¤   PGPUICb const *ui, void *arg);
f3af5a
541254 PGP_END_C_DECLARATIONS
92af5a
dc9c0c #endif /* Included_pgpReadAnn_h */
--d37a 0007d2c6bc84010019b Page 1 of pgpVerifyRa.c
bc38e5 /*
9c0ff1 ·* pgpVerifyRa.c -- An Annotation Reader to do Signature Verification
1f775e ·*
047ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
a9775e ·*
b6e3db ·* $Id: pgpVerifyRa.c,v 1.24 1997/12/12 01:14:04 heller Exp $
83495d ·*/
abe2ff #include "pgpConfig.h"
2faf5a
33feb2 #include <stdio.h>
19af5a
23a146 #include "pgpDebug.h"
b49bb3 #include "pgpVerifyRa.h"
0b3baa #include "pgpVrfySig.h"
7d6aaa #include "pgpAnnotate.h"
4b115d #include "pgpDevNull.h"
d05417 #include "pgpHashPriv.h"
2e421a #include "pgpJoin.h"
dc0d08 #include "pgpMem.h"
bd0d6d #include "pgpEnv.h"
3c2f8d #include "pgpErrors.h"
dc1bea #include "pgpMsg.h"
98e117 #include "pgpUI.h"
662ece #include "pgpPipeline.h"
3d43bc #include "pgpSig.h"
d2c26c #include "pgpContext.h"
1eaf5a
0a8239 #define VERIFYRAMAGICS¤ 0x519c43c7
ed7176 #define VERIFYRAMAGICT¤ 0x519c43c8
25af5a
b0d8e6 typedef struct VerifyRaContext {
b6f212 ¤   PGPPipeline¤¤   smod;
41eec3 ¤   PGPPipeline¤¤   tmod;
c867c5 ¤
240261 ¤   PGPPipeline *¤  joinhead;
cace72 ¤   PGPPipeline *¤  jointext;
c93571 ¤   PGPPipeline¤**¤ jointail;
ea67c5 ¤
518113 ¤   PGPHashListRef hashes;
a91dfe ¤   PGPSig *siglist;
fbee3d ¤   PGPEnv const *env;
f5470a ¤   PGPUICb const *ui;
d75f9a ¤   void *ui_arg;
2bc0cb ¤   int numhashes;
cd7929 ¤   int scope_depth;
61ea2c ¤   int ignore_depth;
e3cb56 ¤   PGPByte ignore_text;
98c39b ¤   PGPByte textclosed;
cf1c2d ¤   PGPByte sigclosed;
35c954 ¤   PGPByte textdone;
eb0724 ¤   PGPByte sigdone;
46c557 ¤   DEBUG_STRUCT_CONSTRUCTOR( VerifyRaContext )
1626be } VerifyRaContext;
a0af5a
0af1ae static PGPError
de2099 verifySizeAdvise (VerifyRaContext *ctx)
48bb36 {
b05b01 ¤   PGPError¤   error = kPGPError_NoErr;
f2af5a
884b05 ¤   /* when both text and sig are done, verify the signature */
e9d6e1 ¤   if (¤   ctx->textclosed &&
798ac1 ¤   ¤   ¤   ctx->sigclosed &&
8590e8 ¤   ¤   ¤   IsntNull( ctx->siglist ) &&
62fe6c ¤   ¤   ¤   IsntNull( ctx->hashes ) )
82c7a1 ¤   {
c182a6 ¤   ¤   error¤  = pgpSigVerify (ctx->siglist, ctx->hashes,
259fd8 ¤   ¤   ¤   ¤   ······ctx->ui, ctx->ui_arg);
03af5a
44cca1 ¤   ¤   pgpSigFreeList(ctx->siglist);
ac943a ¤   ¤   ctx->siglist¤   = NULL;
a61b52 ¤   ¤
7d5fb3 ¤   ¤   pgpHashListDestroy(ctx->hashes );
--0de1 000d93bf9f64010019b Page 2 of pgpVerifyRa.c
83f6ed ¤   ¤   ctx->hashes¤¤   = NULL;
9f1cba ¤   ¤   ctx->numhashes¤ = 0;
b29371 ¤   }
a7af5a
33c674 ¤   return error;
eaefe6 }
fcaf5a
c12978 static void
a6e542 verifyTeardown (PGPPipeline *myself)
f7bb36 {
2671fb ¤   VerifyRaContext *ctx = (VerifyRaContext *)myself->priv;
86e9fa ¤   PGPContextRef¤  cdkContext;
5467c5 ¤
1b3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
be696e ¤   cdkContext¤ = myself->cdkContext;
0baf5a
099f25 ¤   pgpAssert (ctx->joinhead);
87bdf3 ¤   pgpAssert (ctx->jointext);
7baf5a
d10dea ¤   if (!ctx->textdone || !ctx->sigdone)
b699bf ¤   ¤   return;
97af5a
cae927 ¤   ctx->joinhead->teardown (ctx->joinhead);
1c7684 ¤   ctx->joinhead¤  = NULL;
99289b ¤   ctx->jointext->teardown (ctx->jointext);
8bca66 ¤   ctx->jointext¤  = NULL;
31af5a
e8cfc7 ¤   if (ctx->hashes) {
0d4d64 ¤   ¤   pgpHashListDestroy (ctx->hashes);
e51863 ¤   ¤   ctx->hashes = NULL;
3d4032 ¤   }¤  ¤
1baf5a
d8934a ¤   if (ctx->siglist) {
c6be35 ¤   ¤   pgpSigFreeList (ctx->siglist);
053fa6 ¤   ¤   ctx->siglist = 0;
d79371 ¤   }
96af5a
30fd9c ¤   pgpClearMemory( ctx, ·sizeof (*ctx));
e566c5 ¤   pgpContextMemFree( cdkContext, ctx);
c1efe6 }
b9af5a
a4f1ae static PGPError
c9af76 tFlush (PGPPipeline *myself)
f4bb36 {
17f6b9 ¤   VerifyRaContext *context;
1eaf5a
4a29be ¤   pgpAssert (myself);
74633e ¤   pgpAssert (myself->magic == VERIFYRAMAGICT);
b2af5a
cebea7 ¤   context = (VerifyRaContext *)myself->priv;
0dd30a ¤   pgpAssert (context);
28fb28 ¤   pgpAssert (context->jointext);
a0af5a
6d127b ¤   return context->jointext->flush (context->jointext);
e6efe6 }
dcaf5a
945d09 static size_t
41e56e tWrite (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
31bb36 {
a2f6b9 ¤   VerifyRaContext *context;
77af5a
c429be ¤   pgpAssert (myself);
47633e ¤   pgpAssert (myself->magic == VERIFYRAMAGICT);
484866 ¤   pgpAssert (error);
02af5a
a0bea7 ¤   context = (VerifyRaContext *)myself->priv;
87d30a ¤   pgpAssert (context);
8ffb28 ¤   pgpAssert (context->jointext);
26af5a
a801cf ¤   return context->jointext->write (context->jointext, buf, size, error);
edefe6 }
d9af5a
--e7f3 0007bdee7ab4010019b Page 3 of pgpVerifyRa.c
f3f1ae static PGPError
ab47dd tAnnotate (PGPPipeline *myself, PGPPipeline *origin, int type,
a4b011 ¤   ···PGPByte const *string, size_t size)
d7bb36 {
83f6b9 ¤   VerifyRaContext *context;
a0af5a
9a29be ¤   pgpAssert (myself);
46633e ¤   pgpAssert (myself->magic == VERIFYRAMAGICT);
abaf5a
5ebea7 ¤   context = (VerifyRaContext *)myself->priv;
02d30a ¤   pgpAssert (context);
9ffb28 ¤   pgpAssert (context->jointext);
b8af5a
8ea0a5 ¤   return context->jointext->annotate (context->jointext, origin, type,
ab396e ¤   ¤   ¤   ¤   ¤   ····string, size);
11efe6 }
64af5a
ecf1ae static PGPError
3e83fb tSizeAdvise (PGPPipeline *myself, unsigned long bytes)
38bb36 {
9af6b9 ¤   VerifyRaContext *context;
ed87a6 ¤   PGPError¤   error;
dcaf5a
c729be ¤   pgpAssert (myself);
c0633e ¤   pgpAssert (myself->magic == VERIFYRAMAGICT);
22af5a
21bea7 ¤   context = (VerifyRaContext *)myself->priv;
83d30a ¤   pgpAssert (context);
b3af5a
4f56b6 ¤   if (bytes)
79b840 ¤   ¤   return kPGPError_NoErr;
09af5a
b9c565 ¤   error = context->jointext->sizeAdvise (context->jointext, 0);
0e0161 ¤   if (error)
aefcee ¤   ¤   return error;
cf67c5 ¤
a96430 ¤   context->textclosed = 1;
faaf5a
6c04af ¤   return verifySizeAdvise (context);
86efe6 }
8caf5a
d8f1ae static PGPError
4cf1cc tTeardown (PGPPipeline *myself)
f8bb36 {
43f6b9 ¤   VerifyRaContext *context;
76e9fa ¤   PGPContextRef¤  cdkContext;
b867c5 ¤
c23982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
07696e ¤   cdkContext¤ = myself->cdkContext;
0caf5a
e729be ¤   pgpAssert (myself);
e0633e ¤   pgpAssert (myself->magic == VERIFYRAMAGICT);
f5af5a
fcbea7 ¤   context = (VerifyRaContext *)myself->priv;
24d30a ¤   pgpAssert (context);
12af5a
d37a06 ¤   context->textdone = 1;
8a4026 ¤   verifyTeardown (myself);
fa67c5 ¤
bd151e ¤   return kPGPError_NoErr;
64efe6 }
b5af5a
74f1ae static PGPError
8c50c3 sFlush (PGPPipeline *myself)
08bb36 {
aaf6b9 ¤   VerifyRaContext *context;
9faf5a
d229be ¤   pgpAssert (myself);
d3341f ¤   pgpAssert (myself->magic == VERIFYRAMAGICS);
3aaf5a
e9bea7 ¤   context = (VerifyRaContext *)myself->priv;
7bd30a ¤   pgpAssert (context);
--eda1 000b82953b04010019b Page 4 of pgpVerifyRa.c
e0af5a
a5151e ¤   return kPGPError_NoErr;
6aefe6 }
f8af5a
405d09 static size_t
56c0f7 sWrite (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
06bb36 {
09f6b9 ¤   VerifyRaContext *context;
e2af5a
d529be ¤   pgpAssert (myself);
03341f ¤   pgpAssert (myself->magic == VERIFYRAMAGICS);
1b4866 ¤   pgpAssert (error);
6eaf5a
67bea7 ¤   context = (VerifyRaContext *)myself->priv;
46d30a ¤   pgpAssert (context);
0aaf5a
c02cc6 ¤   (void) buf;
40af5a
f155a7 ¤   if (size) {
85b6b3 ¤   ¤   if (context->ignore_text)
3206a0 ¤   ¤   ¤   return size;
15af5a
52fbdd ¤   ¤   *error = kPGPError_BadParams;
c1bbde ¤   ¤   return 0;
119371 ¤   }
b6af5a
703e6b ¤   return 0;
8befe6 }
89af5a
a5f1ae static PGPError
d1b12c sAnnotate (PGPPipeline *myself, PGPPipeline *origin, int type,
c8b011 ¤   ···PGPByte const *string, size_t size)
2ebb36 {
e7f6b9 ¤   VerifyRaContext *context;
f15b01 ¤   PGPError¤   error = kPGPError_NoErr;
39e9fa ¤   PGPContextRef¤  cdkContext;
a267c5 ¤
353982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
a1696e ¤   cdkContext¤ = myself->cdkContext;
acaf5a
4e29be ¤   pgpAssert (myself);
e1341f ¤   pgpAssert (myself->magic == VERIFYRAMAGICS);
4baf5a
60bea7 ¤   context = (VerifyRaContext *)myself->priv;
d9d30a ¤   pgpAssert (context);
dbaf5a
c81b82 ¤   (void)origin;
a6d8af ¤   /*
65c83d ¤   ·* We only accept a few annotations here. ·Things we dont know
4d1c38 ¤   ·* are considered an error. ·Only a known set of annotations are
0b5904 ¤   ·* accepted, and most of these are ignored. ·We are allowed to be
491f38 ¤   ·* in armor, and only a sepsig is allowed.
ae9714 ¤   ·*
2ac555 ¤   ·* Text is only ignored if it is within a NONPGP scope. ·Otherwise
833e88 ¤   ·* it is not ignored and an error will be returned.
809714 ¤   ·*
37e524 ¤   ·* Commit requests are ignored, too.
67a4e3 ¤   ·*/
bdaf5a
6e1609 ¤   switch (type) {
6db3c7 ¤   case PGPANN_ARMOR_BEGIN:
12e294 ¤   case PGPANN_ARMOR_END:
fbaa6d ¤   case PGPANN_FILE_BEGIN:
4d6df4 ¤   case PGPANN_FILE_END:
f905ec ¤   case PGPANN_INPUT_BEGIN:
be82f9 ¤   case PGPANN_INPUT_END:
bf46d7 ¤   case PGPANN_COMMIT:
d81f47 ¤   case PGPANN_SIGNED_BEGIN:
bbf710 ¤   case PGPANN_SIGNED_END:
7f5e29 ¤   case PGPANN_SIGNED_SEP:
942f68 ¤   ¤   break;
b8af5a
--d2fd 0001160bd5d4010019b Page 5 of pgpVerifyRa.c
259950 ¤   case PGPANN_NONPGP_BEGIN:
fcb6b3 ¤   ¤   if (context->ignore_text)
f7cdcb ¤   ¤   ¤   break;
a5af5a
1683b1 ¤   ¤   context->ignore_text = 1;
9ddcbe ¤   ¤   context->ignore_depth = context->scope_depth + 1;
ac2f68 ¤   ¤   break;
38af5a
2f2def ¤   case PGPANN_NONPGP_END:
c7a37d ¤   ¤   pgpAssert (context->ignore_text);
6caf5a
ef504e ¤   ¤   if (context->ignore_depth == context->scope_depth)
1a361e ¤   ¤   ¤   context->ignore_text = 0;
79af5a
fc2f68 ¤   ¤   break;
1faf5a
9fc08d ¤   case PGPANN_SIGNED_SIG:
bc88e2 ¤   ¤   error = (PGPError)pgpSigAdd ( cdkContext,
5cc346 ¤   ¤   ¤   &context->siglist, type, string, size);
50e7f8 ¤   ¤   if (error) {
b77a70 ¤   ¤   ¤   context->ui->message (context->ui_arg, error,
18ea89 ¤   ¤   ¤   ¤   ¤   ······PGPMSG_SIG_ADD_ERROR, 0);
4f0fe4 ¤   ¤   }
bb2f68 ¤   ¤   break;
62af5a
f22f72 ¤   default:
36d5d3 ¤   ¤   error = kPGPError_BadParams;
359371 ¤   }
b9af5a
86e3f0 ¤   PGP_SCOPE_DEPTH_UPDATE (context->scope_depth, type);
9e5709 ¤   pgpAssert (context->scope_depth != -1);
ebaf5a
18c674 ¤   return error;
87efe6 }
a7af5a
f7f1ae static PGPError
9cfeb2 sSizeAdvise (PGPPipeline *myself, unsigned long bytes)
3cbb36 {
eff6b9 ¤   VerifyRaContext *context;
5e5b01 ¤   PGPError¤   error = kPGPError_NoErr;
50af5a
5f29be ¤   pgpAssert (myself);
4b341f ¤   pgpAssert (myself->magic == VERIFYRAMAGICS);
47af5a
1cbea7 ¤   context = (VerifyRaContext *)myself->priv;
c4d30a ¤   pgpAssert (context);
f1af5a
5656b6 ¤   if (bytes)
a3b840 ¤   ¤   return kPGPError_NoErr;
68af5a
f77713 ¤   /* setup the hashes, then close the join module */
e052d4 ¤   if (!context->siglist)
07ccae ¤   ¤   return kPGPError_NoErr;¤/* No signatures??? */
9d67c5 ¤
67ad46 ¤   if (!context->numhashes)
6eab39 ¤   ¤   error = (PGPError)pgpSigSetupHashes(
e301d4 ¤   ¤   ¤   myself->cdkContext,
001959 ¤   ¤   ¤   context->jointail, context->env,
5f1162 ¤   ¤   ¤   ·&context->hashes,
c2d8e5 ¤   ¤   ¤   ·context->siglist, context->ui, context->ui_arg);
d90161 ¤   if (error)
17fcee ¤   ¤   return error;
e949a8 ¤   context->numhashes¤ = pgpHashListGetSize( context->hashes );
7c67c5 ¤
82d142 ¤   /* now turn on the pipe to verify the text */
3eeb69 ¤   error = context->joinhead->sizeAdvise (context->joinhead, 0);
980161 ¤   if (error)
26fcee ¤   ¤   return error;
2a67c5 ¤
e3846d ¤   context->sigclosed = 1;
bdaf5a
1104af ¤   return verifySizeAdvise (context);
--8256 0006865251a4010019b Page 6 of pgpVerifyRa.c
7aefe6 }
46af5a
9cf1ae static PGPError
efbdf3 sTeardown (PGPPipeline *myself)
ebbb36 {
4ef6b9 ¤   VerifyRaContext *context;
c7e9fa ¤   PGPContextRef¤  cdkContext;
7767c5 ¤
8f3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
99696e ¤   cdkContext¤ = myself->cdkContext;
8eaf5a
1629be ¤   pgpAssert (myself);
c0341f ¤   pgpAssert (myself->magic == VERIFYRAMAGICS);
39af5a
c5bea7 ¤   context = (VerifyRaContext *)myself->priv;
2ed30a ¤   pgpAssert (context);
21af5a
c8abee ¤   context->sigdone = 1;
124026 ¤   verifyTeardown (myself);
e167c5 ¤
52151e ¤   return kPGPError_NoErr;
53efe6 }
51af5a
9ff07b PGPPipeline *
f12934 pgpVerifyReaderCreate (
f7fdf9 ¤   PGPContextRef cdkContext,
72cc23 ¤   PGPPipeline **texthead,
67892e ¤   PGPPipeline **sighead,
ceadaa ¤   PGPEnv const *env, PGPFifoDesc const *fd,
23cf99 ¤   PGPByte const *hashlist, unsigned hashlen, int textmode,
398a9f ¤   PGPUICb const *ui, void *ui_arg)
b2bb36 {
30bedc ¤   PGPPipeline *smod, *tmod;
53c019 ¤   PGPPipeline *¤  joinhead = NULL;
4f90c4 ¤   PGPPipeline *¤  jointext¤   = NULL;
f95b37 ¤   PGPPipeline **¤ jointail¤   = NULL;
51096e ¤   VerifyRaContext *context¤   = NULL;
1cef31 ¤   PGPHashListRef hashes = NULL;
a2cd08 ¤   int numhashes = 0, err;
72af5a
022a75 ¤   if (!texthead || !sighead || !env)
ed7ed2 ¤   ¤   return NULL;
79af5a
6a2266 ¤   context = (VerifyRaContext *)pgpContextMemAlloc( cdkContext,
08d680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
0a1ea4 ¤   if (!context)
077ed2 ¤   ¤   return NULL;
332bb5 ¤   smod = &context->smod;
cc9228 ¤   tmod = &context->tmod;
d367c5 ¤
04fb5b ¤   jointail = pgpJoinCreate ( cdkContext, &joinhead, fd);
b59f62 ¤   if (!jointail) {
daa8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
0b7ed2 ¤   ¤   return NULL;
7d9371 ¤   }
4d9d57 ¤   jointext = pgpJoinAppend (joinhead);
6758ef ¤   if (!jointext) {
d585ee ¤   ¤   joinhead->teardown (joinhead);
1ea8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
327ed2 ¤   ¤   return NULL;
309371 ¤   }
2b267e ¤   if (hashlist && hashlen) {
a9fae4 ¤   ¤   PGPByte const *charmap;
8aaf5a
39cb84 ¤   ¤   if (!pgpDevNullCreate ( cdkContext, jointail)) {
9e8ba2 ¤   ¤   ¤   joinhead->teardown (joinhead);
799af4 ¤   ¤   ¤   jointext->teardown (jointext);
5cfbe8 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context);
eccf03 ¤   ¤   ¤   return NULL;
590fe4 ¤   ¤   }
db318d ¤   ¤   charmap = (PGPByte const *)
68930a ¤   ¤   ¤   pgpenvGetPointer (env, PGPENV_CHARMAPTOLATIN1, NULL);
--1a6e 00179805b734010019b Page 7 of pgpVerifyRa.c
9628bd ¤   ¤   err = pgpSigSetupPipeline ( cdkContext, jointail, &hashes,
eb7028 ¤   ¤   ¤   ¤   ¤   ···hashlist, (PGPUInt16)hashlen,
ca7b4d ¤   ¤   ¤   ¤   ¤   ···(textmode ? charmap : NULL));
6fa0ae ¤   ¤   numhashes¤  = IsntNull( hashes ) ? pgpHashListGetSize( hashes ) : 0;
90bfa7 ¤   ¤   if (err || numhashes <= 0) {
098ba2 ¤   ¤   ¤   joinhead->teardown (joinhead);
949af4 ¤   ¤   ¤   jointext->teardown (jointext);
34fbe8 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context);
91cf03 ¤   ¤   ¤   return NULL;
810fe4 ¤   ¤   }
48660c ¤   ¤   err = joinhead->sizeAdvise (joinhead, 0);
0c68f3 ¤   ¤   if (err) {
fd8ba2 ¤   ¤   ¤   joinhead->teardown (joinhead);
6c9af4 ¤   ¤   ¤   jointext->teardown (jointext);
fdd2ed ¤   ¤   ¤   pgpHashListDestroy (hashes);
1cfbe8 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context);
2ccf03 ¤   ¤   ¤   return NULL;
950fe4 ¤   ¤   }
939371 ¤   }
73af5a
5b128d ¤   smod->magic = VERIFYRAMAGICS;
fba137 ¤   smod->write = sWrite;
03a775 ¤   smod->flush = sFlush;
aea48c ¤   smod->sizeAdvise = sSizeAdvise;
9e09e8 ¤   smod->annotate = sAnnotate;
a613cb ¤   smod->teardown = sTeardown;
c87626 ¤   smod->name = "Signature Verification Annotation Reader (sighead)";
2ace3c ¤   smod->priv = context;
a22071 ¤   smod->cdkContext¤   = cdkContext;
03af5a
ad7c51 ¤   tmod->magic = VERIFYRAMAGICT;
bf7b99 ¤   tmod->write = tWrite;
7f7ddb ¤   tmod->flush = tFlush;
5bf0f0 ¤   tmod->sizeAdvise = tSizeAdvise;
ecd376 ¤   tmod->annotate = tAnnotate;
6bc955 ¤   tmod->teardown = tTeardown;
dbe987 ¤   tmod->name = "Signature Verification Annotation Reader (texthead)";
0b889c ¤   tmod->priv = context;
ca9d73 ¤   tmod->cdkContext¤   = cdkContext;
deaf5a
5f1ed1 ¤   context->joinhead = joinhead;
95770c ¤   context->jointext = jointext;
993d49 ¤   context->jointail = jointail;
7a5b61 ¤   context->env = env;
3d7d87 ¤   context->ui = ui;
b3f47a ¤   context->ui_arg = ui_arg;
e0237f ¤   context->hashes = hashes;
489687 ¤   context->numhashes = numhashes;
96af5a
d818f2 ¤   *sighead = smod;
53756e ¤   *texthead = tmod;
502cc0 ¤   return smod;
79efe6 }
--08cc 0018ee9bc6b4010019c Page 1 of pgpVerifyRa.h
bc38e5 /*
18cf7f ·* pgpVerifyRa.h -- Signature Verification Annotation Reader
9f775e ·*
cf7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
b2775e ·*
72fbeb ·* $Id: pgpVerifyRa.h,v 1.9 1997/06/25 19:40:10 lloyd Exp $
62495d ·*/
dff5b8 #ifndef Included_pgpVerifyRa_h
f3824b #define Included_pgpVerifyRa_h
f6af5a
3cadb8 #include "pgpOpaqueStructs.h"
d1e82c #include "pgpPubTypes.h"
39af5a
2a99c6 PGP_BEGIN_C_DECLARATIONS
5faf5a
ddaf5a
9737cb PGPPipeline ·*
7c2934 pgpVerifyReaderCreate (
fafdf9 ¤   PGPContextRef cdkContext,
6ccc23 ¤   PGPPipeline **texthead,
ee892e ¤   PGPPipeline **sighead,
6d36a4 ¤   PGPEnv const *env,
cffc19 ¤   PGPFifoDesc const *fd,
70d6b6 ¤   PGPByte const *hashlist,
4c702e ¤   unsigned hashlen,
8c36c2 ¤   int textmode,
569f93 ¤   PGPUICb const *ui,
fa0b81 ¤   void *ui_arg);
3daf5a
311254 PGP_END_C_DECLARATIONS
74af5a
8eb367 #endif /* Included_pgpVerifyRa_h */
--4fed 000b5204b404010019d Page 1 of pgpVrfySig.c
bc38e5 /*
10a34c ·* pgpVrfySig.c -- Code shared between readann and verifyra to deal with
9dd233 ·* checking and verifying signatures.
17775e ·*
d57ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
60775e ·*
488e83 ·* $Id: pgpVrfySig.c,v 1.27 1998/07/28 00:03:36 heller Exp $
74495d ·*/
4de2ff #include "pgpConfig.h"
dcaf5a
e1feb2 #include <stdio.h>
99af5a
d73baa #include "pgpVrfySig.h"
c5115d #include "pgpDevNull.h"
585417 #include "pgpHashPriv.h"
18c49c #include "pgpHashMod.h"
f90d08 #include "pgpMem.h"
e32ece #include "pgpPipeline.h"
800d6d #include "pgpEnv.h"
462f8d #include "pgpErrors.h"
2d1bea #include "pgpMsg.h"
83e117 #include "pgpUI.h"
4d43bc #include "pgpSig.h"
2f3576 #include "pgpTextFilt.h"
04c26c #include "pgpContext.h"
0baf5a
a4af5a
32892e #define kPGPError_VERBOSE_0¤0
1caf5a
f0af5a
a34d2f int
2a724a pgpSigSetupPipeline (
4afdf9 ¤   PGPContextRef cdkContext,
708941 ¤   PGPPipeline **head,
32f2a4 ¤   PGPHashListRef *hashes,
d8d6b6 ¤   PGPByte const *hashlist,
12610b ¤   PGPUInt16 hashlen,
8ff19b ¤   PGPByte const *charmap)
6fbb36 {
fec879 ¤   int num;
d8c02a ¤   PGPPipeline *mod = NULL, **tail = &mod;
875ad6 ¤   PGPError error;
b3c3f1 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
27af5a
2f1877 ¤   pgpAssertAddrValid( head, PGPPipeline );
edbc23 ¤   pgpAssertAddrValid( hashes, PGPHashListRef );
1c19f9 ¤   pgpAssertAddrValid( hashlist, PGPByte );
6e67c5 ¤
fe20be ¤   if (!head || !hashes || !hashlist || hashlen == 0 )
c5bbde ¤   ¤   return 0;
4baf5a
e5c134 ¤   error = pgpHashListCreate ( memoryMgr, hashlist, hashes, hashlen);
11534a ¤   if( IsPGPError( error ) )
77fcee ¤   ¤   return error;
1baf5a
ecceff ¤   num = pgpHashListGetSize( *hashes );
b1aad2 ¤   if (num <= 0)
b1bbde ¤   ¤   return 0;
54af5a
8d1925 ¤   if (charmap) {
81748e ¤   ¤   tail = pgpTextFiltCreate ( cdkContext,
6e0c4b ¤   ¤   ¤   tail, charmap, 0, kPGPLineEnd_CRLF);
e2f36a ¤   ¤   if (!tail) {
c517d5 ¤   ¤   ¤   pgpHashListDestroy (*hashes);
d17cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
540fe4 ¤   ¤   }
e29371 ¤   }
13af5a
422966 ¤   tail = pgpHashModListCreate ( cdkContext, tail, *hashes, num);
05b2e1 ¤   if (!tail) {
1f2b3b ¤   ¤   pgpHashListDestroy (*hashes);
b5f1b1 ¤   ¤   mod->teardown (mod);
--2c66 000366a961b4010019d Page 2 of pgpVrfySig.c
c34030 ¤   ¤   return kPGPError_OutOfMemory;
689371 ¤   }
20af5a
27bfde ¤   /* splice in the modules */
d3ea64 ¤   *tail = *head;
f22d11 ¤   *head = mod;
d83e6b ¤   return 0;
2fefe6 }
96af5a
1e38e5 /*
666cbc ·* Given a bunch of signatures, setup a string of hash modules and
ef6a4f ·* hashes in order to process the signatures.
7b495d ·*/
264d2f int
f2b6d3 pgpSigSetupHashes (PGPContextRef cdkContext,
3df40f ¤   PGPPipeline **tail,
4436a4 ¤   PGPEnv const *env,
a2137c ¤   PGPHashListRef *hashlist,
8dcaa6 ¤   PGPSig const *siglist,
e99f93 ¤   PGPUICb const *ui,
97f9bb ¤   void *ui_arg)
4abb36 {
a834c1 ¤   PGPUInt16 len;
9117e6 ¤   int err;
e2d259 ¤   PGPByte *buf;
dd8113 ¤   PGPHashListRef hashes;
2457ba ¤   PGPByte const *charmap;
0269cc ¤   PGPByte const *extra;
e527ed ¤   unsigned extralen;
69af5a
f4f2cd ¤   if (!tail || !siglist || !hashlist || !ui)
3a62b5 ¤   ¤   return kPGPError_BadParams;
11af5a
48c8fb ¤   *hashlist = NULL;
45af5a
66a6c3 ¤   len = pgpSigDistinctHashCount (siglist);
5b1bef ¤   buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
a3ca51 ¤   ¤   len, kPGPMemoryMgrFlags_Clear);
2d20df ¤   if (!buf)
6c4030 ¤   ¤   return kPGPError_OutOfMemory;
78aa9f ¤   pgpSigDistinctHashes (siglist, buf);
55af5a
c3fce0 ¤   if (!pgpDevNullCreate (cdkContext, tail)) {
0b3996 ¤   ¤   ui->message (ui_arg, kPGPError_OutOfMemory, PGPMSG_DEVNULL_CREATE, 0);
9002f1 ¤   ¤   pgpContextMemFree( cdkContext, buf);
c04030 ¤   ¤   return kPGPError_OutOfMemory;
f49371 ¤   }
7faf5a
1d4c71 ¤   extra = pgpSigExtra (siglist, &extralen);
0246b0 ¤   charmap = (PGPByte const *)pgpenvGetPointer (env, PGPENV_CHARMAPTOLATIN1,
131520 ¤   ¤   ¤   ¤   ¤   ¤   ··NULL);
06003c ¤   err = pgpSigSetupPipeline ( cdkContext, tail, &hashes, buf, len,·
9ebac6 ¤   ¤   ¤   ¤   ···((extra && extra[0]) ? charmap : NULL));
260449 ¤   pgpContextMemFree( cdkContext, buf);
0440ac ¤   if ( IsPGPError( err ) ) {
200d75 ¤   ¤   (*tail)->teardown (*tail);
819371 ¤   }
14af5a
4f51db ¤   if ( pgpHashListGetSize( hashes ) == 0) {
930d75 ¤   ¤   (*tail)->teardown (*tail);
980533 ¤   ¤   ui->message (ui_arg, kPGPError_VERBOSE_0, PGPMSG_SIG_NO_CHECK, 0);
4b7fff ¤   ¤   pgpHashListDestroy( hashes );
5adf23 ¤   ¤   return kPGPError_CantHash;
ca9371 ¤   }
94af5a
25ed83 ¤   *hashlist = hashes;
573e6b ¤   return 0;
62efe6 }
05af5a
f438e5 /*
391f66 ·* Verify a Signature with a list of hashes
36495d ·*/
--a239 000ef8bcbac4010019d Page 3 of pgpVrfySig.c
d3c744 ¤   PGPError
c4240c pgpSigVerify (PGPSig const *siglist, PGPHashListRef hashes,
671f30 ¤   ·PGPUICb const *ui, void *ui_arg)
afbb36 {
1b7cdb ¤   unsigned¤   ¤   ¤   ¤   i;
efcd02 ¤   unsigned¤   ¤   ¤   ¤   len, extralen;
067651 ¤   PGPByte const *¤¤   ¤   buf;
acb2fe ¤   PGPByte const *¤¤   ¤   extra;
4c4522 ¤   PGPHashContext *¤   ¤   temp_hc;
696e33 ¤   PGPSig const *¤ ¤   ¤   sig;
033cbe ¤   PGPError¤   ¤   ¤   ¤   err = kPGPError_NoErr;
2e6d9b ¤   PGPUInt32¤  ¤   ¤   ¤   numHashes;
feaf5a
5d0c77 ¤   PGPValidatePtr( siglist );
ac09f5 ¤   PGPValidatePtr( hashes );
14786f ¤   PGPValidatePtr( ui );
e1af5a
65b51e ¤   /* Now, verify the signatures */
fc70ae ¤   numHashes¤  = pgpHashListGetSize( hashes );
2eeee0 ¤   len = 0;
c1c981 ¤   for (i = 0; i < numHashes; i++)
8ec7a1 ¤   {
2d7871 ¤   ¤   PGPHashVTBL const *¤vtbl;
f55b62 ¤   ¤   PGPHashContext *¤   hashContext;
541b52 ¤   ¤
6e6f33 ¤   ¤   hashContext¤= pgpHashListGetIndHash( hashes, i );
0aca18 ¤   ¤   vtbl¤   ¤   = pgpHashGetVTBL( hashContext );
fd1b52 ¤   ¤
a97418 ¤   ¤   if (len < vtbl->hashsize)
65b0fb ¤   ¤   ¤   len = vtbl->hashsize;
8b9371 ¤   }
b267c5 ¤
d74ea0 ¤   for (sig = siglist; IsntNull( sig ); sig = pgpSigNext (sig))
c4c7a1 ¤   {
d9cc61 ¤   ¤   PGPHashContextRef¤  hc¤ = NULL;
5767c5 ¤
9e9981 ¤   ¤   hc = pgpHashListFind (hashes, pgpSigHash (sig));
8563d3 ¤   ¤   if ( IsNull( hc ) )
a05b34 ¤   ¤   {
e8fa4a ¤   ¤   ¤   /* not necessarily an error; could be a future format */
1d8774 ¤   ¤   ¤   ui->message (ui_arg, kPGPError_BadHashNumber,
359893 ¤   ¤   ¤   ¤   ·····PGPMSG_SIG_BADHASH, 0);
ed17f5 ¤   ¤   ¤   continue;
f60fe4 ¤   ¤   }
301b52 ¤   ¤
249428 ¤   ¤   err = PGPCopyHashContext(hc, &temp_hc );
1bbe18 ¤   ¤   if ( IsPGPError( err ) )
c0cdcb ¤   ¤   ¤   break;
54af5a
41e2f9 ¤   ¤   extra = pgpSigExtra (sig, &extralen);
9baf5a
cc47fc ¤   ¤   PGPContinueHash (temp_hc, extra, extralen);
c919d8 ¤   ¤   buf¤¤   = (PGPByte *) pgpHashFinal (temp_hc);
67c7e5 ¤   ¤   /* buf is not allocated so we don't need to free it */
1dbf7c ¤   ¤   err ¤   = ui->sigVerify (ui_arg, sig, buf);
078c0d ¤   ¤   PGPFreeHashContext (temp_hc);
54be18 ¤   ¤   if ( IsPGPError( err ) )
35cdcb ¤   ¤   ¤   break;
c19371 ¤   }
3367c5 ¤
165ea8 ¤   return err;
bbefe6 }
15af5a
6b4d2f int
e8245c pgpSepsigVerify (PGPSig const *siglist, PGPEnv const *env,
9823de ¤   ¤   ·PGPUICb const *ui, void *ui_arg)
c3bb36 {
3b3474 ¤   PGPPipeline *head = 0, **tail = &head;
fde4b5 ¤   PGPHashListRef¤ hashes = NULL;
ff89b5 ¤   int err = 0;
a8af5a
efbbcc ¤   if (!siglist) {
--e56d 00118f19f554010019d Page 4 of pgpVrfySig.c
5435dd ¤   ¤   ui->message (ui_arg, kPGPError_BadParams, PGPMSG_SIG_NOSIGS, 0);
5dbbde ¤   ¤   return 0;
e19371 ¤   }
4eaf5a
a57a55 ¤   ui->message (ui_arg, kPGPError_VERBOSE_0, PGPMSG_SEPSIG, 0);
87af5a
3ea3ac ¤   err = pgpSigSetupHashes ( pgpenvGetContext( env ),
0236a5 ¤   ¤   ¤   tail, env, &hashes, siglist, ui, ui_arg);
cba09a ¤   if (err)
dab43c ¤   ¤   goto cleanup2;
5e1b52 ¤   ¤
fb3979 ¤   /* Ask the UI to input the message to verify the signature */
c12d72 ¤   err = ui->needInput (ui_arg, head);
07a09a ¤   if (err)
07b43c ¤   ¤   goto cleanup2;
72af5a
0cfebe ¤   err = pgpSigVerify (siglist, hashes, ui, ui_arg);
04af5a
70a78d cleanup2:
663354 ¤   if (head)
039acd ¤   ¤   head->teardown (head);
bcea68 ¤   pgpHashListDestroy (hashes);
da5ea8 ¤   return err;
40efe6 }
1851b2 /*¤ requires pgpSigListDestroy (); */
--f413 001c6e6b0e34010019e Page 1 of pgpVrfySig.h
bc38e5 /*
3b0de5 ·* pgpVrfySig.h -- Signature Verification Code
47775e ·*
eb7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
68775e ·*
fe771b ·* $Id: pgpVrfySig.h,v 1.10 1997/07/31 22:51:48 lloyd Exp $
fa495d ·*/
47a178 #ifndef Included_pgpVrfySig_h
43f54c #define Included_pgpVrfySig_h
64af5a
61adb8 #include "pgpOpaqueStructs.h"
07e82c #include "pgpPubTypes.h"
efaf5a
eb99c6 PGP_BEGIN_C_DECLARATIONS
e1af5a
d0fb6c int pgpSigSetupPipeline (
3fcaf1 ¤   ¤   PGPContextRef cdkContext,
e37f24 ¤   ¤   PGPPipeline **head,
c85ffa ¤   ¤   PGPHashListRef *hashes,
9b258d ¤   ¤   PGPByte const *hashlist, PGPUInt16 numHashes,
b491dd ¤   ¤   PGPByte const *charmap);
35af5a
6616cc int pgpSigSetupHashes (
96caf1 ¤   ¤   PGPContextRef cdkContext,
342f3a ¤   ¤   PGPPipeline **tail, PGPEnv const *env,
fe2474 ¤   ¤   PGPHashListRef *hashlist,
82de8e ¤   ¤   PGPSig const *siglist,
f2503a ¤   ¤   PGPUICb const *ui, void *ui_arg);
00af5a
4a6ab0 PGPError¤   pgpSigVerify (PGPSig const *siglist, PGPHashListRef hashes,
c2555d ¤   ¤   ¤   ¤   PGPUICb const *ui, void *arg);
cdaf5a
8437dc int pgpSepsigVerify (PGPSig const *siglist, PGPEnv const *env,
7ccd62 ¤   ¤   ·····PGPUICb const *ui, void *ui_arg);
79af5a
d71254 PGP_END_C_DECLARATIONS
b3af5a
c62387 #endif /* Included_pgpVrfySig_h */
--6768 0012d3e2b244010019f Page 1 of Makefile.in
5ea601 #
cec71f # priv/crypto/pipe/sig/
5fa601 #
856ddf # $Id: Makefile.in,v 1.2 1997/05/04 10:30:11 mhw Exp $
b2a601 #
beaf5a
85ac3b OBJS=¤  pgpSigMod.o pgpHashMod.o
f5c906 PRIVHDRS= pgpHashMod.h pgpSigMod.h
cdaf5a
3cb7a3 all:: DONE
2daf5a
--3ec0 000c22566d9401001a0 Page 1 of pgpHashMod.c
bc38e5 /*
20e5e0 ·* pgpHashMod.c -- module to hash data
c8775e ·*
07f49c ·* Written by:¤ Derek Atkins <warlord@MIT.EDU> and Colin Plumb
b4775e ·*
a0d4e5 ·* $Id: pgpHashMod.c,v 1.17 1997/12/12 01:14:06 heller Exp $
d1495d ·*/
b7e2ff #include "pgpConfig.h"
4faf5a
1bfeb2 #include <stdio.h>
a9af5a
75a146 #include "pgpDebug.h"
80c49c #include "pgpHashMod.h"
535417 #include "pgpHashPriv.h"
cc0d08 #include "pgpMem.h"
a32ece #include "pgpPipeline.h"
5fc26c #include "pgpContext.h"
bdaf5a
b91712 #define HASHMODMAGIC¤   0x8a5430d1
0daf5a
303d3b typedef struct HashModContext {
e9f8fb ¤   PGPPipeline¤¤   pipe;
bc67c5 ¤
62ab40 ¤   PGPHashContext *hash;
2375b0 ¤   PGPPipeline *tail;
000c1e } HashModContext;
a1af5a
38f1ae static PGPError
08c966 Flush(PGPPipeline *myself)
a3bb36 {
55145a ¤   HashModContext *context;
59af5a
22b81b ¤   pgpAssert(myself);
4dbf44 ¤   pgpAssert(myself->magic == HASHMODMAGIC);
f6af5a
312730 ¤   context = (HashModContext *)myself->priv;
0e213c ¤   pgpAssert(context);
d5bdf0 ¤   pgpAssert(context->tail);
09af5a
0bd780 ¤   return context->tail->flush(context->tail);
e8efe6 }
dcaf5a
eb5d09 static size_t
fe2e8a Write(PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
babb36 {
f3145a ¤   HashModContext *context;
34ac29 ¤   size_t written;
64af5a
c0b81b ¤   pgpAssert(myself);
1cbf44 ¤   pgpAssert(myself->magic == HASHMODMAGIC);
414ca3 ¤   pgpAssert(error);
64af5a
822730 ¤   context = (HashModContext *)myself->priv;
f6213c ¤   pgpAssert(context);
68bdf0 ¤   pgpAssert(context->tail);
63af5a
8a745b ¤   written = context->tail->write(context->tail, buf, size, error);
23af5a
d422f2 ¤   if (written)
7c8be4 ¤   ¤   PGPContinueHash(context->hash, buf, written);
7baf5a
8be765 ¤   return written;¤
34efe6 }
50af5a
a8f1ae static PGPError
e54ddc Annotate(PGPPipeline *myself, PGPPipeline *origin, int type,
27b0b1 ¤   ··PGPByte const *string, size_t size)
c2bb36 {
8f145a ¤   HashModContext *context;
e2af5a
89b81b ¤   pgpAssert(myself);
c2bf44 ¤   pgpAssert(myself->magic == HASHMODMAGIC);
--cb4e 0005074028b401001a0 Page 2 of pgpHashMod.c
e0af5a
d92730 ¤   context = (HashModContext *)myself->priv;
35213c ¤   pgpAssert(context);
c3bdf0 ¤   pgpAssert(context->tail);
61af5a
755331 ¤   return context->tail->annotate(context->tail, origin, type,
a93153 ¤   ¤   ¤   ¤   ¤   string, size);
2cefe6 }
93af5a
c6f1ae static PGPError
fe99d0 SizeAdvise(PGPPipeline *myself, unsigned long bytes)
cbbb36 {
74145a ¤   HashModContext *context;
87af5a
cdb81b ¤   pgpAssert(myself);
5bbf44 ¤   pgpAssert(myself->magic == HASHMODMAGIC);
c8af5a
602730 ¤   context = (HashModContext *)myself->priv;
20213c ¤   pgpAssert(context);
87bdf0 ¤   pgpAssert(context->tail);
afaf5a
e6b368 ¤   return context->tail->sizeAdvise(context->tail, bytes);
c8efe6 }
c5af5a
a7f1ae static PGPError
00bf01 Teardown(PGPPipeline *myself)
f4bb36 {
a1145a ¤   HashModContext *context;
2be9fa ¤   PGPContextRef¤  cdkContext;
9867c5 ¤
7b3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
c9696e ¤   cdkContext¤ = myself->cdkContext;
63af5a
50b81b ¤   pgpAssert(myself);
5ebf44 ¤   pgpAssert(myself->magic == HASHMODMAGIC);
bfaf5a
5e2730 ¤   context = (HashModContext *)myself->priv;
33213c ¤   pgpAssert(context);
23af5a
00cb05 ¤   if (context->tail)
855c22 ¤   ¤   context->tail->teardown(context->tail);
feaf5a
5495a3 ¤   pgpClearMemory( context, ·sizeof(*context));
08fa6e ¤   pgpContextMemFree( cdkContext, context);
cf67c5 ¤
02151e ¤   return kPGPError_NoErr;
28efe6 }
c7af5a
b941cd PGPPipeline **
1eeb5e pgpHashModCreate(
69fdf9 ¤   PGPContextRef cdkContext,
c9404a ¤   PGPPipeline **head, PGPHashContext *hash)
49bb36 {
63145a ¤   HashModContext *context;
419ecf ¤   PGPPipeline *mod¤   = NULL;
cbaf5a
32c72d ¤   pgpAssert(hash);
ceaf5a
dbbb3d ¤   if (!head)
317ed2 ¤   ¤   return NULL;
21af5a
71d129 ¤   context = (HashModContext *)pgpContextMemAlloc(
462ff5 ¤   ¤   cdkContext, sizeof(*context), kPGPMemoryMgrFlags_Clear);
4fe31e ¤   if ( IsNull( context ) )
b77ed2 ¤   ¤   return NULL;
08af5a
e21b31 ¤   mod¤¤   ¤   ¤   = &context->pipe;
6f9fa0 ¤   mod->magic¤ ¤   = HASHMODMAGIC;
7ab327 ¤   mod->write¤ ¤   = Write;
410a98 ¤   mod->flush¤ ¤   = Flush;
271d63 ¤   mod->sizeAdvise¤= SizeAdvise;
50b5a2 ¤   mod->annotate¤  = Annotate;
--2043 001a88cd3c9401001a0 Page 3 of pgpHashMod.c
a905ac ¤   mod->teardown¤  = Teardown;
beea43 ¤   mod->name¤  ¤   = "Hash Module";
0f7fc7 ¤   mod->priv¤  ¤   = context;
7aa99e ¤   mod->cdkContext¤= cdkContext;
d6af5a
1113a2 ¤   context->hash = hash;
ecaf5a
e265ad ¤   context->tail = *head;
b12d11 ¤   *head = mod;
947fa2 ¤   return &context->tail;
e2efe6 }
8aaf5a
0841cd PGPPipeline **
03d381 pgpHashModListCreate(
47fdf9 ¤   PGPContextRef cdkContext,
d98941 ¤   PGPPipeline **head,
0104fe ¤   PGPHashListRef¤ hashes,
445ad9 ¤   unsigned num)
0fbb36 {
a3ea91 ¤   PGPPipeline *th = 0, **tt = &th;
cd7c53 ¤   PGPUInt32¤  ¤   hashIndex = 0;
eeaf5a
25a209 ¤   while (num--) {
2fc0cf ¤   ¤   PGPHashContext *¤   hash;
511b52 ¤   ¤
17851c ¤   ¤   hash¤   = pgpHashListGetIndHash( hashes, hashIndex );
f6b859 ¤   ¤   ++hashIndex;
3b1b52 ¤   ¤
dd0eb1 ¤   ¤   tt = pgpHashModCreate( cdkContext, tt, hash);
21e3e1 ¤   ¤   if (!tt) {
c2380f ¤   ¤   ¤   if (th)
051422 ¤   ¤   ¤   ¤   th->teardown(th);
dc8144 ¤   ¤   ¤   return 0;
cd0fe4 ¤   ¤   }
279371 ¤   }
f9e021 ¤   *tt = *head;
aeb514 ¤   *head = th;
02f521 ¤   return tt;
a8efe6 }
--57af 00145733917401001a1 Page 1 of pgpHashMod.h
bc38e5 /*
f85c4f ·* pgpHashMod.h -- A Generic Hash Module.
88775e ·*
977ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
06775e ·*
963d29 ·* $Id: pgpHashMod.h,v 1.10 1997/09/18 01:35:24 lloyd Exp $
70495d ·*/
a15800 #ifndef Included_pgpHashMod_h
760c34 #define Included_pgpHashMod_h
81af5a
da99c6 PGP_BEGIN_C_DECLARATIONS
50af5a
98adb8 #include "pgpOpaqueStructs.h"
50e82c #include "pgpPubTypes.h"
b1af5a
dbaf5a
1238e5 /*
bbbc93 ·* Create a module that will hash its input and copy it to the output,
d030c9 ·* using the passed-in PGPHashContext. ·The caller assumes control of the
f6be01 ·* PGPHashContext, and when this module returns success from a
3435cb ·* sizeAdvise(0), the PGPHashContext is valid for use.
b9775e ·*
97a97e ·* Note: the calling function must destroy the PGPHashContext.
a9495d ·*/
f9f481 PGPPipeline ·**
157d77 pgpHashModCreate ( PGPContextRef cdkContext,
722390 ¤   ¤   ¤   ¤   PGPPipeline **head, PGPHashContext *hash);
cfaf5a
0af481 PGPPipeline ·**
9d9d76 pgpHashModListCreate ( PGPContextRef cdkContext,
4e77b4 ¤   PGPPipeline **head, PGPHashListRef hashes, unsigned num);
c2af5a
821254 PGP_END_C_DECLARATIONS
08af5a
457454 #endif
--bf67 000ad052b86401001a2 Page 1 of pgpSigMod.c
bc38e5 /*
c9c7a7 ·* $Id: pgpSigMod.c,v 1.29 1998/06/11 18:27:55 hal Exp $
b2495d ·*/
49af5a
fde2ff #include "pgpConfig.h"
97324c #include <string.h>
23af5a
4da146 #include "pgpDebug.h"
010bbe #include "pgpCopyMod.h"
22c305 #include "pgpMakeSig.h"
7d9c38 #include "pgpPktByte.h"
fd2886 #include "pgpSigMod.h"
b06aaa #include "pgpAnnotate.h"
525417 #include "pgpHashPriv.h"
b2c49c #include "pgpHashMod.h"
db421a #include "pgpJoin.h"
f40d08 #include "pgpMem.h"
4b2ece #include "pgpPipeline.h"
d62f8d #include "pgpErrors.h"
60f5ab #include "pgpSigSpec.h"
78d11f #include "pgpUsuals.h"
32c26c #include "pgpContext.h"
16af5a
394c3e #define SIGMODMAGIC 0x519a10fe
efaf5a
03af5a
cbee03 typedef struct PerSignature {
57ca43 ¤   struct PerSignature *next;
ef347f ¤   PGPSigSpec const *spec;
75e2ba ¤   PGPHashContext *hc;
fb67dc ¤   DEBUG_STRUCT_CONSTRUCTOR( PerSignature )
556249 } PerSignature;
b0af5a
14a413 typedef struct SigModContext {
398b60 ¤   PGPPipeline¤pipe;
0c67c5 ¤
8675b0 ¤   PGPPipeline *tail;
1528a4 ¤   PGPPipeline *join, *joinlast, *newjoin;
625834 ¤   PGPPipeline **jointail;
ff69f4 ¤   PGPPipeline **texttail;
3faae2 ¤   PerSignature *siglist;
ada473 ¤   PerSignature *sigptr;
9193dc ¤   PGPRandomContext const *rc;
4dc5ae ¤   PgpVersion version;
cbd259 ¤   PGPByte *buf;
aa0fbc ¤   unsigned buflen;
124fdd ¤   PGPByte const *sig;
5d52f1 ¤   int siglen;
9d7929 ¤   int scope_depth;
c33bec ¤   PGPByte onepass;
ae5cfc ¤   DEBUG_STRUCT_CONSTRUCTOR( SigModContext )
c5d95d } SigModContext;
ecaf5a
cd38e5 /*
768036 ·* For each signature on the signature list, get rid of it.
68fcce ·* The fact that duplicate PgpHashContexts are allowed complicates
2f149e ·* this a little bit.
48495d ·*/
12af5a
6af1ae static PGPError
963b47 TeardownSigList(
fd3163 ¤   PGPContextRef¤  cdkContext,
160cc3 ¤   PerSignature *siglist)
dcbb36 {
fce2ef ¤   PerSignature *ps;
81e2ba ¤   PGPHashContext *hc;
64af5a
7a22c8 ¤   while (siglist) {
21fc95 ¤   ¤   hc = siglist->hc;
2bfb46 ¤   ¤   if (hc) {
e4cece ¤   ¤   ¤   /* Walk to end of list deleting duplicates */
ad3f4a ¤   ¤   ¤   for (ps = siglist->next; ps; ps = ps->next)
--9fee 0000af9a0de401001a2 Page 2 of pgpSigMod.c
f8ed1c ¤   ¤   ¤   ¤   if (ps->hc == hc)
13c41c ¤   ¤   ¤   ¤   ¤   ps->hc = 0;
27b185 ¤   ¤   ¤   PGPFreeHashContext(hc);
2a0fe4 ¤   ¤   }
ab0cef ¤   ¤   ps = siglist->next;
d7f210 ¤   ¤   pgpClearMemory( siglist, ·sizeof(*siglist));
2e6f80 ¤   ¤   pgpContextMemFree( cdkContext, siglist);
d8e600 ¤   ¤   siglist = ps;
229371 ¤   }
b967c5 ¤
bc151e ¤   return kPGPError_NoErr;
43efe6 }
b7af5a
cd5d09 static size_t
f52e8a Write(PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
f4bb36 {
d07447 ¤   SigModContext *context;
37af5a
70b81b ¤   pgpAssert(myself);
61aa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
a64ca3 ¤   pgpAssert(error);
c6af5a
f53c77 ¤   context = (SigModContext *)myself->priv;
f8213c ¤   pgpAssert(context);
aebdf0 ¤   pgpAssert(context->tail);
e8af5a
2bd8af ¤   /*
c7e480 ¤   ·* If we're doing 1-pass signatures we might need to open a
84d2b9 ¤   ·* new input (for the real signature data) which is appended
946228 ¤   ·* to the current data using pgpSigTextInsert, just like the
ebf86e ¤   ·* data did. ·Then we need to close the current input, tear it
8e65c0 ¤   ·* down, and replace it with the new one. ·Finally, we need to
0d9162 ¤   ·* set a flag that says that we did this, so we don't do it
006f8c ¤   ·* again. ·*/
abaf5a
133438 ¤   if (context->version > PGPVERSION_3 &&·
6efec6 ¤   ····context->joinlast != context->join) {
4c1b17 ¤   ¤   /*
e83ed6 ¤   ¤   ·* Do the switch if we have new version packets and
7a90b9 ¤   ¤   ·* pgpSigTextInsert() was called
339de3 ¤   ¤   ·*/
6ff927 ¤   ¤   PGPPipeline *head = NULL, **tail;
f2af5a
601ab5 ¤   ¤   switch (context->onepass) {
46e2df ¤   ¤   case 0:
738385 ¤   ¤   ¤   /* Create the new module... */
73239e ¤   ¤   ¤   tail = pgpSigTextInsert (myself, &head);
8542bb ¤   ¤   ¤   if (!tail) {
5d72db ¤   ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
eb46f1 ¤   ¤   ¤   ¤   return 0;
93a3a6 ¤   ¤   ¤   }
a11294 ¤   ¤   ¤   context->newjoin = head;
270425 ¤   ¤   ¤   context->onepass++;
a50b70 ¤   ¤   ¤   /* FALLTHROUGH */
dab803 ¤   ¤   case 1:
2cdf8b ¤   ¤   ¤   /* close the old one... */
c51b01 ¤   ¤   ¤   *error = context->join->sizeAdvise (context->join, 0);
a8b5c5 ¤   ¤   ¤   if (*error)
df46f1 ¤   ¤   ¤   ¤   return 0;
730425 ¤   ¤   ¤   context->onepass++;
c50b70 ¤   ¤   ¤   /* FALLTHROUGH */
245767 ¤   ¤   case 2:
429df5 ¤   ¤   ¤   /* ...and shut it down... */
a4c5ab ¤   ¤   ¤   context->join->teardown (context->join);
cbaf5a
18e2fb ¤   ¤   ¤   /* inserting the new one in its place */
6048bc ¤   ¤   ¤   context->join = context->newjoin;
320425 ¤   ¤   ¤   context->onepass++;
0e9ae3 ¤   ¤   default:
81cdcb ¤   ¤   ¤   break;
7b0fe4 ¤   ¤   }
0a9371 ¤   }
--834e 000d7726ee8401001a2 Page 3 of pgpSigMod.c
e0af5a
0f3cfa ¤   return context->tail->write(context->tail, buf, size, error);
5befe6 }
59af5a
e6f1ae static PGPError
ce4ddc Annotate(PGPPipeline *myself, PGPPipeline *origin, int type,
c4b0b1 ¤   ··PGPByte const *string, size_t size)
2bbb36 {
127447 ¤   SigModContext *context;
2987a6 ¤   PGPError¤   error;
fdaf5a
58b81b ¤   pgpAssert(myself);
66aa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
baaf5a
be3c77 ¤   context = (SigModContext *)myself->priv;
79213c ¤   pgpAssert(context);
78bdf0 ¤   pgpAssert(context->tail);
9daf5a
5cf9ef ¤   error = context->tail->annotate(context->tail, origin, type,
489aba ¤   ································string, size);
6eff2e ¤   if (!error)
026467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
dd04c8 ¤   pgpAssert(context->scope_depth != -1);
9daf5a
13c674 ¤   return error;
09efe6 }
69af5a
b6f1ae static PGPError
4999d0 SizeAdvise(PGPPipeline *myself, unsigned long bytes)
3ebb36 {
cb7447 ¤   SigModContext *context;
d2e2ef ¤   PerSignature *ps;
3487a6 ¤   PGPError¤   error;
840d4c ¤   int¤¤   ¤   i, len;
2fe002 ¤   size_t size;
b1e9fa ¤   PGPContextRef¤  cdkContext;
7e67c5 ¤
803982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
f1696e ¤   cdkContext¤ = myself->cdkContext;
9faf5a
adb81b ¤   pgpAssert(myself);
80aa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
6aaf5a
bb3c77 ¤   context = (SigModContext *)myself->priv;
6d213c ¤   pgpAssert(context);
16bdf0 ¤   pgpAssert(context->tail);
03af5a
1e1364 ¤   i = context->tail->sizeAdvise(context->tail, bytes);
7b9978 ¤   if (i || bytes || context->scope_depth)
3b2051 ¤   ¤   return (PGPError)i;
f9af5a
fcd8af ¤   /*
391d99 ¤   ·* Not inside any scope and got a sizeAdvise(0): EOF!
1a8560 ¤   ·* So write out all the signatures. ·*/
91af5a
e10331 ¤   /* Find out how big a buffer we need and allocate it */
d305db ¤   if (context->sigptr && !context->buf) {
d75b71 ¤   ¤   len = 0;
0f7bc6 ¤   ¤   for (ps = context->sigptr; ps; ps = ps->next) {
326c00 ¤   ¤   ¤   i = pgpMakeSigMaxSize(ps->spec);
a8bbb5 ¤   ¤   ¤   if (len < i)
4db4d6 ¤   ¤   ¤   ¤   len = i;
c10fe4 ¤   ¤   }
2aaf5a
b0fabc ¤   ¤   context->buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
d5d730 ¤   ¤   ¤   (unsigned)len+3, kPGPMemoryMgrFlags_Clear);
32fb10 ¤   ¤   if (!context->buf)
ff7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
90903e ¤   ¤   context->buflen = (unsigned)len+3;
4e9371 ¤   }
7aaf5a
d7a3fb ¤   /* Walk the list of signatures writing them out. */
--ac6a 0002df23c3f401001a2 Page 4 of pgpSigMod.c
1196fb ¤   ps = context->sigptr;
c2edd9 ¤   while (ps || context->siglen) {
9c5089 ¤   ¤   /* Write any partial signature */
5ba3ca ¤   ¤   if (context->siglen) {
19ec5f ¤   ¤   ¤   pgpAssert(context->sig);
e656b7 ¤   ¤   ¤   pgpAssert(context->join);
177611 ¤   ¤   ¤   /* Dump it down the join module */
b41875 ¤   ¤   ¤   size = context->join->write(context->join,
b369ab ¤   ¤   ¤   ¤   ¤   ¤   ····context->sig,
044e9c ¤   ¤   ¤   ¤   ¤   ¤   ····context->siglen,
965b30 ¤   ¤   ¤   ¤   ¤   ¤   ····&error);
97537b ¤   ¤   ¤   context->sig += size;
65c376 ¤   ¤   ¤   context->siglen -= size;
1bd82b ¤   ¤   ¤   if (error)
41b20f ¤   ¤   ¤   ¤   return error;
d417f5 ¤   ¤   ¤   continue;
360fe4 ¤   ¤   }
eeaf5a
d8bcae ¤   ¤   /* Okay, now, make a new signature. */
2c45a3 ¤   ¤   pgpAssert(context->buflen >= 3u+pgpMakeSigMaxSize(ps->spec));
58bfcb ¤   ¤   i = pgpMakeSig(context->buf+3, ps->spec, context->rc, ps->hc);
a2ad75 ¤   ¤   if (i < 0)
668d0f ¤   ¤   ¤   return (PGPError)i;
dbaf5a
6c20ac ¤   ¤   if (context->version > PGPVERSION_3) {
047da8 ¤   ¤   ¤   if (PKTLEN_ONE_BYTE(i)) {
7569b5 ¤   ¤   ¤   ¤   context->buf[1] =
969a3b ¤   ¤   ¤   ¤   ¤   PKTBYTE_BUILD_NEW(PKTBYTE_SIG);
cf2004 ¤   ¤   ¤   ¤   context->buf[2] = PKTLEN_1BYTE(i);
d5d5d2 ¤   ¤   ¤   ¤   context->sig = context->buf+1;
797191 ¤   ¤   ¤   ¤   context->siglen = (unsigned)i+2;
20042d ¤   ¤   ¤   } else {
0a62f1 ¤   ¤   ¤   ¤   context->buf[0] =
509a3b ¤   ¤   ¤   ¤   ¤   PKTBYTE_BUILD_NEW(PKTBYTE_SIG);
069f19 ¤   ¤   ¤   ¤   context->buf[1] = PKTLEN_BYTE0(i);
c168c4 ¤   ¤   ¤   ¤   context->buf[2] = PKTLEN_BYTE1(i);
38dfef ¤   ¤   ¤   ¤   context->sig = context->buf;
662b4d ¤   ¤   ¤   ¤   context->siglen = (unsigned)i+3;
d8a3a6 ¤   ¤   ¤   }
b345a6 ¤   ¤   } else {
fbb177 #if 0
87eaa7 /* PGP 2.6.2 screws up on this */
b10f78 ¤   ¤   ¤   if (i < 256) {
b969b5 ¤   ¤   ¤   ¤   context->buf[1] =
a43412 ¤   ¤   ¤   ¤   ¤   PKTBYTE_BUILD(PKTBYTE_SIG, 0);
771a4b ¤   ¤   ¤   ¤   context->buf[2] = (PGPByte)i;
3bd5d2 ¤   ¤   ¤   ¤   context->sig = context->buf+1;
197191 ¤   ¤   ¤   ¤   context->siglen = (unsigned)i+2;
ebe875 ¤   ¤   ¤   } else {}
407454 #endif
ea6148 ¤   ¤   ¤   context->buf[0] = PKTBYTE_BUILD(PKTBYTE_SIG, 1);
a2baf5 ¤   ¤   ¤   context->buf[1] = (PGPByte)(i>>8);
8a238e ¤   ¤   ¤   context->buf[2] = (PGPByte)i;
dfd957 ¤   ¤   ¤   context->sig = context->buf;
0279d0 ¤   ¤   ¤   context->siglen = (unsigned)i+3;
c20fe4 ¤   ¤   }
0248e0 ¤   ¤   /* Okay, signature made */
2fc9ff ¤   ¤   context->sigptr = ps = ps->next;
449371 ¤   }
2aaf5a
f3cfbf ¤   TeardownSigList( cdkContext, context->siglist);
d2f7bd ¤   context->siglist = 0;
41af5a
34203a ¤   if (context->buf) {
a20347 ¤   ¤   pgpClearMemory(context->buf, context->buflen);
0306b7 ¤   ¤   pgpContextMemFree( cdkContext, context->buf);
5b4872 ¤   ¤   context->buf = 0;
f99371 ¤   }
40af5a
c636cc ¤   if (context->join) {
78d69c ¤   ¤   error = context->join->sizeAdvise(context->join, 0);
2de3c2 ¤   ¤   if (error)
--6c89 0009b41f09f401001a2 Page 5 of pgpSigMod.c
193b5b ¤   ¤   ¤   return error;
f4b177 #if 0
5817bc /* Take this out; simple pgp lib later queries downstream memmod */
969240 ¤   ¤   context->join->teardown(context->join);
5687b9 ¤   ¤   context->join = 0;
867454 #endif
589371 ¤   }
a5af5a
76151e ¤   return kPGPError_NoErr;
57efe6 }
78af5a
3aaf5a
0af1ae static PGPError
adc966 Flush(PGPPipeline *myself)
45bb36 {
a17447 ¤   SigModContext *context;
d187a6 ¤   PGPError¤   error;
87af5a
aab81b ¤   pgpAssert(myself);
28aa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
e0af5a
fe3c77 ¤   context = (SigModContext *)myself->priv;
f1213c ¤   pgpAssert(context);
2baf5a
f9fd0c ¤   /* XXX Do nothing */
6ecd10 ¤   if (context->tail) {
94801e ¤   ¤   error = context->tail->flush(context->tail);
bae3c2 ¤   ¤   if (error)
893b5b ¤   ¤   ¤   return error;
e99371 ¤   }
b036cc ¤   if (context->join) {
f7a9cb ¤   ¤   error = context->join->flush(context->join);
17e3c2 ¤   ¤   if (error)
1d3b5b ¤   ¤   ¤   return error;
bd9371 ¤   }
9b151e ¤   return kPGPError_NoErr;
dcefe6 }
e8af5a
9ef1ae static PGPError
45bf01 Teardown(PGPPipeline *myself)
3dbb36 {
2b7447 ¤   SigModContext *context;
4fe9fa ¤   PGPContextRef¤  cdkContext;
6067c5 ¤
473982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
d5696e ¤   cdkContext¤ = myself->cdkContext;
feaf5a
2eb81b ¤   pgpAssert(myself);
9daa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
ffaf5a
163c77 ¤   context = (SigModContext *)myself->priv;
c7213c ¤   pgpAssert(context);
d9cb05 ¤   if (context->tail)
fe5c22 ¤   ¤   context->tail->teardown(context->tail);
7a6417 ¤   if (context->join)
439240 ¤   ¤   context->join->teardown(context->join);
86cfbf ¤   TeardownSigList( cdkContext, context->siglist);
69203a ¤   if (context->buf) {
550347 ¤   ¤   pgpClearMemory(context->buf, context->buflen);
3a06b7 ¤   ¤   pgpContextMemFree( cdkContext, context->buf);
809371 ¤   }
72af5a
fe95a3 ¤   pgpClearMemory( context, ·sizeof(*context));
76fa6e ¤   pgpContextMemFree( cdkContext, context);
ed67c5 ¤
2e151e ¤   return kPGPError_NoErr;
7cefe6 }
96af5a
6441cd PGPPipeline **
4333d1 pgpSigCreate(
fffdf9 ¤   PGPContextRef cdkContext,
9b8941 ¤   PGPPipeline **head,
--cc70 0002dd02dd2401001a2 Page 6 of pgpSigMod.c
731d37 ¤   PgpVersion version,
2afc19 ¤   PGPFifoDesc const *fd,
dc35fd ¤   PGPRandomContext const *rc)
17bb36 {
fc0df0 ¤   PGPPipeline *mod;
d62c96 ¤   PGPPipeline **tail;
9a7447 ¤   SigModContext *context;
51af5a
5cbb3d ¤   if (!head)
1b7ed2 ¤   ¤   return NULL;
90af5a
f5fdff ¤   context = (SigModContext *)pgpContextMemAlloc( cdkContext,
dbf235 ¤   ¤   sizeof(*context), kPGPMemoryMgrFlags_Clear);
8a1ea4 ¤   if (!context)
017ed2 ¤   ¤   return NULL;
559228 ¤   mod = &context->pipe;
0baf5a
d47161 ¤   /* Create the join module for stuffing the signatures into. */
1d3f2e ¤   context->jointail = pgpJoinCreate( cdkContext, &context->join, fd);
969863 ¤   if (!context->jointail) {
30a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
8e7ed2 ¤   ¤   return NULL;
af9371 ¤   }
eb5ae7 ¤   context->joinlast = context->join;
7c96ed ¤   context->rc = rc;
0e46a2 ¤   context->version = version;
1aaf5a
95436c ¤   /* Tack a copy mod onto the output to provide a stable tail pointer. */
4165ad ¤   context->tail = *head;
ebcb7a ¤   tail = pgpCopyModCreate( cdkContext, &context->tail);
3ab2e1 ¤   if (!tail) {
c49240 ¤   ¤   context->join->teardown(context->join);
89a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
9a9371 ¤   }
38af5a
eaa293 ¤   /* Finally, fill in all the values */
6f2062 ¤   mod->magic = SIGMODMAGIC;
f91f83 ¤   mod->write = Write;
81ac4e ¤   mod->flush = Flush;
e90aaf ¤   mod->sizeAdvise = SizeAdvise;
33d3a2 ¤   mod->annotate = Annotate;
7b96de ¤   mod->teardown = Teardown;
c7737c ¤   mod->name = "Signature";
7101ea ¤   mod->priv = context;
3aa99e ¤   mod->cdkContext¤= cdkContext;
2eaf5a
432d11 ¤   *head = mod;
05ca79 ¤   return tail;
79efe6 }
52af5a
ea38e5 /*
585883 ·* This adds one signature to the signing module. ·It returns a tail pointer
dc446b ·* which the signatures will come out of. ·Each call returns the same
c38e50 ·* tail pointer - this joins them together internally.
8a495d ·*/
e1e73a static PGPPipeline **
075219 addSignature (PGPPipeline *myself, PGPSigSpec *spec,
cf9467 ¤   ······PGPByte clearsig, PGPByte nest)
66bb36 {
1b7190 ¤   SigModContext *context = (SigModContext *)myself->priv;
85c705 ¤   PerSignature *ps, *ps2;
a19b60 ¤   PGPHashVTBL const *hash = pgpSigSpecHash(spec);
abe2ba ¤   PGPHashContext *hc;
4ee9fa ¤   PGPContextRef¤  cdkContext;
c0f0bf ¤   PGPMemoryMgrRef¤memoryMgr¤  = NULL;
7c67c5 ¤
953982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
29696e ¤   cdkContext¤ = myself->cdkContext;
5c1c1f ¤   memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
0baf5a
7ab81b ¤   pgpAssert(myself);
2daa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
--955d 000eee31676401001a2 Page 7 of pgpSigMod.c
e0af5a
be3c77 ¤   context = (SigModContext *)myself->priv;
02213c ¤   pgpAssert(context);
01af5a
dc46a4 ¤   ps = (PerSignature *)pgpContextMemAlloc( cdkContext,
18851a ¤   ¤   sizeof(*ps), kPGPMemoryMgrFlags_Clear);
2fbc23 ¤   if ( IsNull( ps ) )
44c7a1 ¤   {
b3ef86 ¤   ¤   return( NULL );
7d9371 ¤   }
3d67c5 ¤
84457f ¤   /* If we already have a request for this hash, use it */
e0123e ¤   hc = 0;
0b1fba ¤   for (ps2 = context->siglist; ps2; ps2 = ps2->next) {
62b6c1 ¤   ¤   if ( pgpHashGetVTBL( ps2->hc ) == hash) {
43698e ¤   ¤   ¤   hc = ps2->hc;
a1cdcb ¤   ¤   ¤   break;
9b0fe4 ¤   ¤   }
e89371 ¤   }
1faf5a
17819d ¤   /* If not, generate a new one, and a module to make it. */
56f69a ¤   if (!hc) {
2d96fb ¤   ¤   hc = pgpHashCreate( memoryMgr, hash);
f61439 ¤   ¤   if (!hc) {
d2dab0 ¤   ¤   ¤   pgpContextMemFree( cdkContext, ps);
008144 ¤   ¤   ¤   return 0;
2a0fe4 ¤   ¤   }
f26f3d ¤   ¤   if (!pgpHashModCreate( myself->cdkContext, &context->tail, hc)) {
6ab185 ¤   ¤   ¤   PGPFreeHashContext(hc);
05dab0 ¤   ¤   ¤   pgpContextMemFree( cdkContext, ps);
898144 ¤   ¤   ¤   return 0;
d60fe4 ¤   ¤   }
dc9371 ¤   }
b6af5a
cbc819 ¤   /* Fill in the PerSignature structure */
3bca40 ¤   ps->spec = spec;
98d0b7 ¤   ps->hc = hc;
29af5a
138e8e ¤   if (!clearsig && context->version > PGPVERSION_3) {
c41b17 ¤   ¤   /*
4e36b5 ¤   ¤   ·* Add the 1-pass signature header here. ·It gets
07a0ad ¤   ¤   ·* buffered in the order the signatures come in, in a
b4c676 ¤   ¤   ·* LIFO stack. ·For clearsigs we don't do this, there is
5466fb ¤   ¤   ·* just the sig at the end. ·The hash info goes in the
3a0fe5 ¤   ¤   ·* clear.
889de3 ¤   ¤   ·*/
29e8c3 ¤   ¤   PGPByte *buf;
1c47a5 ¤   ¤   int len;
ce1b52 ¤   ¤
f5d1f8 ¤   ¤   len = pgpMakeSigHeaderMaxSize (spec);
aab157 ¤   ¤   pgpAssert (PKTLEN_ONE_BYTE(len));
9c74dc ¤   ¤   buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
f0c660 ¤   ¤   ¤   len+2, kPGPMemoryMgrFlags_Clear);
13a56a ¤   ¤   if (!buf)
c8cf03 ¤   ¤   ¤   return NULL;
5e0078 ¤   ¤   len = pgpMakeSigHeader (buf+2, spec, nest);
eba6f0 ¤   ¤   buf[0] = PKTBYTE_BUILD_NEW (PKTBYTE_1PASSSIG);
5e0f63 ¤   ¤   buf[1] = PKTLEN_1BYTE (len);
7e1b52 ¤   ¤
a814c3 ¤   ¤   len -= pgpJoinBuffer (context->join, buf, len+2);
bdb6bc ¤   ¤   pgpClearMemory( buf, ·sizeof (buf));
0b02f1 ¤   ¤   pgpContextMemFree( cdkContext, buf);
69b831 ¤   ¤   if (len != -2)
15cf03 ¤   ¤   ¤   return NULL;
029371 ¤   }
f6af5a
9abc7b ¤   /* Add to the beginning of the list, reversing the stack */
a2e34b ¤   ps->next = context->siglist;
a1b8ba ¤   context->siglist = ps;
0dad52 ¤   context->sigptr = context->siglist;
faaf5a
ee1b4b ¤   /* And we're done... */
--f50a 00159786e95401001a2 Page 8 of pgpSigMod.c
901d74 ¤   return context->jointail;
d1efe6 }
15af5a
b638e5 /*
9fa046 ·* Set up to create a(nother) signature. ·Clearsig tells us not to try to
b8340e ·* use the 1-pass sigs.
f3495d ·*/
2041cd PGPPipeline **
1bd2b7 pgpSigSignature(PGPPipeline *myself, PGPSigSpec *spec,
c1533c ¤   ¤   PGPByte clearsig)
0ebb36 {
2f7447 ¤   SigModContext *context;
f7007a ¤   PGPSigSpec *ss;
c42c96 ¤   PGPPipeline **tail;
62af5a
00b81b ¤   pgpAssert(myself);
5daa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
f1af5a
3a115e ¤   /* Just checking ! */
dc3c77 ¤   context = (SigModContext *)myself->priv;
dc213c ¤   pgpAssert(context);
cdaf5a
436f60 ¤   /* Only one signature on a PGPVERSION_3 packet */
937893 ¤   if (context->version <= PGPVERSION_3)
58c1af ¤   ¤   return addSignature (myself, spec, clearsig, 0);
4eaf5a
bdae5e ¤   /* PGPVERSION_4 packets can have multiple signatures */
3a40e2 ¤   tail = NULL;
e16121 ·······¤for (ss = spec; ss; ss = pgpSigSpecNext (ss)) {
000ad9 ¤   ¤   tail = addSignature (myself, ss, clearsig,
20d066 ¤   ¤   ¤   ¤   ·····(PGPBoolean)((pgpSigSpecNext (ss))?0:1));
2224d0 ¤   ¤   if (!tail)
9a3a23 ¤   ¤   ¤   return tail;
799371 ¤   }
49ca79 ¤   return tail;
65efe6 }
cbaf5a
2238e5 /*
3bb809 ·* This inserts some text into the signature output in the appropriate place
2a485b ·* to make a signed message, as opposed to separate signatures.
c470b6 ·* It is possible that you might take the output of the signature from
41535a ·* pgpSigCreate, apply some processing (such as compression, or encapsulation
b08fe4 ·* in a literal which PGP does right now) and feed it back into here.
678cdd ·* (Should we hide *that* processing, too?)
cc495d ·*/
8f41cd PGPPipeline **
3044d7 pgpSigTextInsert(PGPPipeline *myself, PGPPipeline **head)
0fbb36 {
727447 ¤   SigModContext *context;
122e0b ¤   PGPPipeline *newjoin;
11af5a
afb81b ¤   pgpAssert(myself);
6baa72 ¤   pgpAssert(myself->magic == SIGMODMAGIC);
2daf5a
bd3c77 ¤   context = (SigModContext *)myself->priv;
5e213c ¤   pgpAssert(context);
ae8ecc ¤   pgpAssert(context->join);
3ce09b ¤   pgpAssert(context->joinlast);
bfaf5a
a2bb3d ¤   if (!head)
9b7ed2 ¤   ¤   return NULL;
b5af5a
3364a5 ¤   newjoin = pgpJoinAppend(context->joinlast);
52b58d ¤   if (newjoin) {
09c726 ¤   ¤   *head = context->joinlast = newjoin;
932a7c ¤   ¤   return context->jointail;
26f037 ¤   } else {
00bbde ¤   ¤   return 0;
329371 ¤   }
59efe6 }
--8471 001e397ab9a401001a3 Page 1 of pgpSigMod.h
bc38e5 /*
1a04f3 ·* pgpSigMod.h -- A module that is used to make a signed message.
b8775e ·*
698190 ·* This is a Public API Function Header.
32775e ·*
796c2e ·* $Id: pgpSigMod.h,v 1.10 1997/06/25 19:40:14 lloyd Exp $
74495d ·*/
b1af5a
8847f7 #ifndef Included_pgpSigMod_h
98c6c1 #define Included_pgpSigMod_h
faaf5a
02d11f #include "pgpUsuals.h"
33af5a
f399c6 PGP_BEGIN_C_DECLARATIONS
c3af5a
e5adb8 #include "pgpOpaqueStructs.h"
09e82c #include "pgpPubTypes.h"
56af5a
1b38e5 /*
4ddc6f ·* This creates a signing module. ·Initially, it just passes through its
28a507 ·* input data unmodified.
d6495d ·*/
388fd5 PGPPipeline ·**pgpSigCreate ( PGPContextRef cdkContext,
695986 ¤   ¤   ¤   ¤   PGPPipeline **head,
22cdf0 ¤   ¤   ¤   ¤   PgpVersion version,
aa25bd ¤   ¤   ¤   ¤   PGPFifoDesc const *fd,
111242 ¤   ¤   ¤   ¤   PGPRandomContext const *rc);
d338e5 /*
2e46ce ·* This adds a signature to the signing module. ·It returns a tail pointer
9d446b ·* which the signatures will come out of. ·Each call returns the same
3e921f ·* tail pointer - this joins them together internally. ·If clearsig is
f62b16 ·* true it won't try to output the special one-pass signature.
50495d ·*/
07562f PGPPipeline ·**pgpSigSignature (PGPPipeline *pipe,
0ce978 ¤   ¤   ¤   ¤   ······PGPSigSpec *spec, PGPByte clearsig);
c438e5 /*
c4b809 ·* This inserts some text into the signature output in the appropriate place
ed485b ·* to make a signed message, as opposed to separate signatures.
7270b6 ·* It is possible that you might take the output of the signature from
a2d8c0 ·* pgpSigCreate, apply some processing (such as compression, or encapsulation·
ef8fe4 ·* in a literal which PGP does right now) and feed it back into here.
dd8cdd ·* (Should we hide *that* processing, too?)
4a495d ·*/
03e5e7 PGPPipeline ·**pgpSigTextInsert (PGPPipeline *pipe,
5b917a ¤   ¤   ¤   ¤   ·······PGPPipeline **head);
9faf5a
f91254 PGP_END_C_DECLARATIONS
edaf5a
e34f3a #endif /* Included_pgpSigMod_h */
--05c0 001148c1ddf401001a4 Page 1 of Makefile.in
5ea601 #
45aa9c # priv/crypto/pipe/text/
7ba601 #
29ea31 # $Id: Makefile.in,v 1.2 1997/05/04 10:30:12 mhw Exp $
26a601 #
f1af5a
5701ad OBJS=¤  pgpCompMod.o pgpDefMod.o pgpInfMod.o pgpLiteral.o pgpTextFilt.o \
178843 ¤   pgpZBits.o pgpZDeflate.o pgpZTrees.o
3bc242 PRIVHDRS= pgpCompMod.h pgpLiteral.h pgpTextFilt.h
4daf5a
8db7a3 all:: DONE
14af5a
--5b53 000b852fd61401001a5 Page 1 of pgpCompMod.c
bc38e5 /*
61250c ·* pgpCompMod.c -- General Compression and Decompression Module
06775e ·*
637ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
49775e ·*
6e3121 ·* $Id: pgpCompMod.c,v 1.9 1998/07/08 20:08:33 hal Exp $
92495d ·*/
f4e2ff #include "pgpConfig.h"
24af5a
9abea3 #include <stdlib.h>
5777c6 #include "pgpAddHdr.h"
2655fb #include "pgpCompMod.h"
efffb1 #include "pgpDefMod.h"
d6a3ee #include "pgpInfMod.h"
cb9c38 #include "pgpPktByte.h"
bbc19b #include "pgpCompress.h"
a02ece #include "pgpPipeline.h"
192f8d #include "pgpErrors.h"
e5af5a
a441cd PGPPipeline **
a8dfd9 pgpCompressModCreate (
4d58f9 ¤   PGPContextRef¤  ¤   cdkContext,
0d0d82 ¤   PGPPipeline **¤ ¤   head,
325efe ¤   PgpVersion¤ ¤   ¤   version,
81f138 ¤   PGPFifoDesc const *¤fd,
24f69e ¤   PGPByte¤¤   ¤   ¤   type,
0d7523 ¤   int¤¤   ¤   ¤   ¤   quality)
51bb36 {
e44d92 ¤   PGPPipeline *newhead = NULL, **tail = &newhead;
02af5a
21bb3d ¤   if (!head)
1f7ed2 ¤   ¤   return NULL;
c3af5a
e11609 ¤   switch (type) {
d9196a ¤   case PGP_COMPRESSALG_ZIP:
b98250 ¤   ¤   tail = defModCreate ( cdkContext, tail, quality);
492f68 ¤   ¤   break;
fa2f72 ¤   default:
e00169 ¤   ¤   tail = NULL;
089371 ¤   }
2aaf5a
0608ec ¤   if (tail) {
11e500 ¤   ¤   tail = pgpAddHeaderCreate ( cdkContext, tail, version, fd,
7e537b ¤   ¤   ¤   ¤   ¤   ···PKTBYTE_COMPRESSED, 3, &type, 1);
98af5a
f4f36a ¤   ¤   if (!tail) {
ca928d ¤   ¤   ¤   newhead->teardown (newhead);
e6cf03 ¤   ¤   ¤   return NULL;
380fe4 ¤   ¤   }
79af5a
5fd18d ¤   ¤   *tail = *head;
f5e68c ¤   ¤   *head = newhead;
b39371 ¤   }
08ca79 ¤   return tail;
52efe6 }
d4af5a
d841cd PGPPipeline **
1b1f0f pgpDecompressModCreate (
af3163 ¤   PGPContextRef¤  cdkContext,
046733 ¤   PGPPipeline **¤ head,
257a59 ¤   PGPByte¤¤   ¤   type,
e12e5d ¤   PGPError¤   ¤   *error)
f6bb36 {
342c96 ¤   PGPPipeline **tail;
1daf5a
81bb3d ¤   if (!head)
dd7ed2 ¤   ¤   return NULL;
c8af5a
1f1609 ¤   switch (type) {
97196a ¤   case PGP_COMPRESSALG_ZIP:
17195f ¤   ····tail = infModCreate ( cdkContext, head);
b87acc ¤   ¤   if (tail == NULL)
--1355 001b2335ad5401001a5 Page 2 of pgpCompMod.c
806a8b ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
328bf2 ¤   ¤   return tail;
a62f72 ¤   default:
7c9833 ¤   ¤   *error = kPGPError_BadPacket;
707ed2 ¤   ¤   return NULL;
ef9371 ¤   }
b2efe6 }
--9183 0017f4c04cd401001a6 Page 1 of pgpCompMod.h
bc38e5 /*
133b6f ·* pgpCompMod.h -- this defines the compression and decompression
32931f ·* functions for PGP.. It provides a generalized interface to the
5ba59a ·* compression modules, and keeps applications from requiring
e835e1 ·* knowledge of all the different types of compression that may be
c087d9 ·* supported.
69775e ·*
787ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
72775e ·*
45384e ·* $Id: pgpCompMod.h,v 1.10 1998/07/08 20:04:47 hal Exp $
4f495d ·*/
ebaf5a
209ec5 #ifndef Included_pgpCompMod_h
4fcaf1 #define Included_pgpCompMod_h
f0af5a
a2d11f #include "pgpUsuals.h"
d9af5a
8999c6 PGP_BEGIN_C_DECLARATIONS
b7af5a
a8275d #include "pgpPipelineOpaqueStructs.h"
7eaf5a
5eaf5a
8038e5 /*
567f09 ·* Create a compression module of the appropriate type (must be one of
c294b1 ·* the COMPRESSALG_* types) with the appropriate compression quality.
e1775e ·*
e26b14 ·* Note: ·There can only be one ZIP compression module in existance
d74127 ·* at a time, since the underlying ZIP code is not re-entrant.
3f495d ·*/
3983a6 PGPPipeline ·**pgpCompressModCreate ( PGPContextRef cdkContext,
520f32 ¤   PGPPipeline **head, PgpVersion version,
8dac8c ¤   PGPFifoDesc const *fd, PGPByte type, int quality);
0daf5a
7b38e5 /*
c78e08 ·* Create a decompression module of the appropriate type.
ee495d ·*/
f0f7e3 PGPPipeline ·**pgpDecompressModCreate ( PGPContextRef cdkContext,
5c62a5 ¤   PGPPipeline **head, PGPByte type, PGPError *error);
d1af5a
a21254 PGP_END_C_DECLARATIONS
02af5a
7f63d0 #endif /* Included_pgpCompMod_h */
--0570 0000de48653401001a7 Page 1 of pgpDefMod.c
bc38e5 /*
d27954 ·* pgpDefMod.c -- Deflate (compression) module
47775e ·*
e57ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
6a775e ·*
2146b9 ·* $Id: pgpDefMod.c,v 1.19 1997/12/12 01:14:08 heller Exp $
a0495d ·*/
23e2ff #include "pgpConfig.h"
2baf5a
cbfeb2 #include <stdio.h>
9caf5a
d4a146 #include "pgpDebug.h"
6583d5 #include "pgpByteFIFO.h"
80ffb1 #include "pgpDefMod.h"
408619 #include "pgpZip.h"
bf6aaa #include "pgpAnnotate.h"
430d08 #include "pgpMem.h"
052ece #include "pgpPipeline.h"
ffc26c #include "pgpContext.h"
a7af5a
4abc64 #define DEFMODMAGIC¤0x0def1a1e
93af5a
4eb0f9 typedef struct DefModContext {
848b60 ¤   PGPPipeline¤pipe;
7e67c5 ¤
d73566 ¤   PGPFifoContext *fifo;
c575b0 ¤   PGPPipeline *tail;
2bca55 ¤   struct ZDeflateContext *zdcontext;
4a6339 ¤   struct ZTreesContext *ztcontext;
e4eef6 ¤   struct ZBitsContext *zbcontext;
d6f48e ¤   int finished;
937929 ¤   int scope_depth;
a44816 ¤   DEBUG_STRUCT_CONSTRUCTOR( DefModContext )
719209 } DefModContext;
68af5a
cbf1ae static PGPError
21b8bd DoFlush (DefModContext *context)
25bb36 {
275b01 ¤   PGPError¤   error = kPGPError_NoErr;
b1a617 ¤   PGPByte const *ptr;
52875f ¤   PGPSize len;
3d6c75 ¤   size_t retlen;
cbaf5a
5b16d3 ¤   /* Try to flush anything that we have buffered */
c4f69e ¤   bi_flush(context->zbcontext);
c0f3b0 ¤   ptr = byteFifoPeek (context->fifo, &len);
0b85aa ¤   while (len) {
7bec77 ¤   ¤   retlen = context->tail->write (context->tail, ptr, len,
9d48b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
3c3d1c ¤   ¤   byteFifoSeek (context->fifo, retlen);
ace3c2 ¤   ¤   if (error)
843b5b ¤   ¤   ¤   return error;
19bc8e ¤   ¤   ptr = byteFifoPeek (context->fifo, &len);
339371 ¤   }
0dc674 ¤   return error;
12efe6 }
69af5a
22f1ae static PGPError
80d02e Flush (PGPPipeline *myself)
e5bb36 {
9b90c8 ¤   DefModContext *context;
9b87a6 ¤   PGPError¤   error;
0aaf5a
d829be ¤   pgpAssert (myself);
a401c7 ¤   pgpAssert (myself->magic == DEFMODMAGIC);
d6af5a
0302aa ¤   context = (DefModContext *)myself->priv;
5cd30a ¤   pgpAssert (context);
95ebf4 ¤   pgpAssert (context->tail);
93af5a
e863fd ¤   error = DoFlush (context);
0d0161 ¤   if (error)
--d7dd 000ee38d473401001a7 Page 2 of pgpDefMod.c
a2fcee ¤   ¤   return error;
fbaf5a
6c9819 ¤   return context->tail->flush (context->tail);
89efe6 }
ffaf5a
215d09 static size_t
50f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
79bb36 {
0e90c8 ¤   DefModContext *context;
55af5a
8729be ¤   pgpAssert (myself);
bb01c7 ¤   pgpAssert (myself->magic == DEFMODMAGIC);
394866 ¤   pgpAssert (error);
d3af5a
da02aa ¤   context = (DefModContext *)myself->priv;
d1d30a ¤   pgpAssert (context);
1cebf4 ¤   pgpAssert (context->tail);
9caf5a
cb3970 ¤   zip_input (context->zdcontext, context->ztcontext, context->zbcontext,
16f467 ¤   ¤   ¤   ···(char const *)buf, size);
060479 ¤   *error = DoFlush (context);
7daf5a
2af6fa ¤   return size;
fcefe6 }
c1af5a
aef1ae static PGPError
b213c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
2bb0b1 ¤   ··PGPByte const *string, size_t size)
2fbb36 {
3790c8 ¤   DefModContext *context;
e287a6 ¤   PGPError¤   error;
73af5a
0929be ¤   pgpAssert (myself);
8e01c7 ¤   pgpAssert (myself->magic == DEFMODMAGIC);
c8af5a
ab02aa ¤   context = (DefModContext *)myself->priv;
72d30a ¤   pgpAssert (context);
6febf4 ¤   pgpAssert (context->tail);
ccaf5a
7763fd ¤   error = DoFlush (context);
c70161 ¤   if (error)
e3fcee ¤   ¤   return error;
08af5a
4b32ab ¤   error = context->tail->annotate (context->tail, origin, type,
643153 ¤   ¤   ¤   ¤   ¤   string, size);
3cff2e ¤   if (!error)
c46467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
2b04c8 ¤   pgpAssert(context->scope_depth != -1);
cec674 ¤   return error;
beefe6 }
22af5a
bcf1ae static PGPError
304b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
0fbb36 {
4e90c8 ¤   DefModContext *context;
b887a6 ¤   PGPError¤   error;
29af5a
b829be ¤   pgpAssert (myself);
1c01c7 ¤   pgpAssert (myself->magic == DEFMODMAGIC);
50af5a
6202aa ¤   context = (DefModContext *)myself->priv;
6cd30a ¤   pgpAssert (context);
afebf4 ¤   pgpAssert (context->tail);
4baf5a
36bcce ¤   if (bytes || context->scope_depth)
4aa117 ¤   ¤   return( kPGPError_NoErr );
01af5a
78f97a ¤   if (!context->finished) {
fe174c ¤   ¤   /* It is a Bad Thing to call zip_finish multiple times. */
327ec6 ¤   ¤   zip_finish (context->zdcontext, context->ztcontext,
81abe8 ¤   ¤   ¤   ¤   ¤   context->zbcontext);
ee6d33 ¤   ¤   context->finished = 1;
--831b 000b145819d401001a7 Page 3 of pgpDefMod.c
a19371 ¤   }
3163fd ¤   error = DoFlush (context);
5d0161 ¤   if (error)
6afcee ¤   ¤   return error;
3baf5a
54e248 ¤   return context->tail->sizeAdvise (context->tail, 0);
deefe6 }
0daf5a
02f1ae static PGPError
cfc7e1 Teardown (PGPPipeline *myself)
bcbb36 {
7890c8 ¤   DefModContext *context;
48e9fa ¤   PGPContextRef¤  cdkContext;
2d67c5 ¤
653982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
d9696e ¤   cdkContext¤ = myself->cdkContext;
44af5a
5e29be ¤   pgpAssert (myself);
a501c7 ¤   pgpAssert (myself->magic == DEFMODMAGIC);
f3af5a
9d02aa ¤   context = (DefModContext *)myself->priv;
95d30a ¤   pgpAssert (context);
f3af5a
7ecb05 ¤   if (context->tail)
301e8a ¤   ¤   context->tail->teardown (context->tail);
87af5a
afbd7c ¤   bi_free (context->zbcontext);¤  ¤   /* Free bits data structures */
ec8eee ¤   ct_free (context->ztcontext);¤  ¤   /* Free code tree buffers */
d92a5a ¤   lm_free (context->zdcontext);¤  ¤   /* Free longest match buffers */
48103e ¤   byteFifoDestroy (context->fifo);
6767c5 ¤
663736 ¤   pgpClearMemory( context, ·sizeof (*context));
bcfa6e ¤   pgpContextMemFree( cdkContext, context);
ffaf5a
50151e ¤   return kPGPError_NoErr;
f7efe6 }
b2af5a
b441cd PGPPipeline **
3a177c defModCreate (
c4fdf9 ¤   PGPContextRef cdkContext,
347d95 ¤   PGPPipeline **head, int quality)
d8bb36 {
d50df0 ¤   PGPPipeline *mod;
de90c8 ¤   DefModContext *context;
d83566 ¤   PGPFifoContext *fifo;
6bca55 ¤   struct ZDeflateContext *zdcontext;
786339 ¤   struct ZTreesContext *ztcontext;
f1af5a
95bb3d ¤   if (!head)
ad7ed2 ¤   ¤   return NULL;
00af5a
914772 ¤   if (IsNull( zdcontext = lm_init (cdkContext, quality) ) )
c87ed2 ¤   ¤   return NULL;
97146c ¤   if (IsNull( ztcontext = ct_init (cdkContext) ) ) {
a3a4b4 ¤   ¤   lm_free (zdcontext);
737ed2 ¤   ¤   return NULL;
339371 ¤   }
a7400e ¤   context = (DefModContext *)pgpContextMemAlloc( cdkContext,
61d680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
b7fa17 ¤   if (!context) {
e16ab9 ¤   ¤   ct_free (ztcontext);
f9a4b4 ¤   ¤   lm_free (zdcontext);
6b7ed2 ¤   ¤   return NULL;
c49371 ¤   }
da3118 ¤   mod = ·&context->pipe;
4667c5 ¤
3e677b ¤   fifo = byteFifoCreate (cdkContext);
c21c5f ¤   if (!fifo) {
5b6ab9 ¤   ¤   ct_free (ztcontext);
4da4b4 ¤   ¤   lm_free (zdcontext);
02a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
b17ed2 ¤   ¤   return NULL;
--5ff5 001df35f355401001a7 Page 4 of pgpDefMod.c
a19371 ¤   }
9967c5 ¤
e038fa ¤   mod->magic = DEFMODMAGIC;
4d1f83 ¤   mod->write = Write;
35ac4e ¤   mod->flush = Flush;
ff0aaf ¤   mod->sizeAdvise = SizeAdvise;
f4d3a2 ¤   mod->annotate = Annotate;
f196de ¤   mod->teardown = Teardown;
fe6fda ¤   mod->name = "Deflation Module";
5401ea ¤   mod->priv = context;
24a99e ¤   mod->cdkContext¤= cdkContext;
beaf5a
e3d5cd ¤   context->fifo = fifo;
bee106 ¤   context->zdcontext = zdcontext;
21f62e ¤   context->ztcontext = ztcontext;
d89e65 ¤   context->zbcontext = bi_init (cdkContext, fifo);
e9af5a
8465ad ¤   context->tail = *head;
142d11 ¤   *head = mod;
197fa2 ¤   return &context->tail;
dfefe6 }
--4d96 0011d1b27bd401001a8 Page 1 of pgpDefMod.h
bc38e5 /*
660d2f ·* pgpDefMod.h -- Header for ZIP Compression (deflation)
10775e ·*
0a7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
8c775e ·*
0be39d ·* This is a PRIVATE header file, for use only within the PGP Library.
702979 ·* You should not be using these functions in an application.
dd775e ·*
d838d4 ·* $Id: pgpDefMod.h,v 1.6 1997/06/25 19:40:15 lloyd Exp $
22495d ·*/
46af5a
b7adb8 #include "pgpOpaqueStructs.h"
36e82c #include "pgpPubTypes.h"
8aaf5a
1b99c6 PGP_BEGIN_C_DECLARATIONS
a1af5a
8d003f PGPPipeline **defModCreate ( PGPContextRef cdkContext,
32c652 ¤   ¤   ¤   PGPPipeline **head, int quality);
f8af5a
1d1254 PGP_END_C_DECLARATIONS
--e5fc 000c38076f9401001a9 Page 1 of pgpInfMod.c
bc38e5 /*
01ad97 ·* pgpInfMod.c -- Inflation (decompression) module
3a775e ·*
5a7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
91775e ·*
3c8a8d ·* $Id: pgpInfMod.c,v 1.16 1997/12/12 01:14:09 heller Exp $
81495d ·*/
3de2ff #include "pgpConfig.h"
27af5a
a1feb2 #include <stdio.h>
cdaf5a
caa146 #include "pgpDebug.h"
62a3ee #include "pgpInfMod.h"
02f4ef #include "pgpZInflate.h"
3d6aaa #include "pgpAnnotate.h"
010d08 #include "pgpMem.h"
482ece #include "pgpPipeline.h"
a7c26c #include "pgpContext.h"
00af5a
043641 #define INFMODMAGIC¤0x01258aef
f3af5a
ffcf43 typedef struct InfModContext {
a0f8fb ¤   PGPPipeline¤¤   pipe;
5c67c5 ¤
e040dd ¤   InflateContext *inf;
5e75b0 ¤   PGPPipeline *tail;
4c7929 ¤   int scope_depth;
3737ac ¤   DEBUG_STRUCT_CONSTRUCTOR( InfModContext )
d4cfb5 } InfModContext;
c9af5a
b9f1ae static PGPError
78b0bc DoFlush (InfModContext *context)
b2bb36 {
bc5b01 ¤   PGPError¤   error = kPGPError_NoErr;
d8c6b5 ¤   unsigned len;
18a617 ¤   PGPByte const *ptr;
cd6c75 ¤   size_t retlen;
3caf5a
4516d3 ¤   /* Try to flush anything that we have buffered */
ea23c9 ¤   ptr = infGetBytes (context->inf, &len);
5385aa ¤   while (len) {
9988b9 ¤   ¤   retlen = context->tail->write (context->tail,
870cba ¤   ¤   ¤   ¤   ¤   ·······ptr, len,
a948b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
75c06c ¤   ¤   infSkipBytes (context->inf, retlen);
521b52 ¤   ¤
02e3c2 ¤   ¤   if (error)
e63b5b ¤   ¤   ¤   return error;
2aaf5a
c03b99 ¤   ¤   ptr = infGetBytes (context->inf, &len);
499371 ¤   }
e9c674 ¤   return error;
4cefe6 }
62af5a
69f1ae static PGPError
c8d02e Flush (PGPPipeline *myself)
51bb36 {
7a98c9 ¤   InfModContext *context;
ca87a6 ¤   PGPError¤   error;
86af5a
3429be ¤   pgpAssert (myself);
844068 ¤   pgpAssert (myself->magic == INFMODMAGIC);
f8af5a
705ca1 ¤   context = (InfModContext *)myself->priv;
28d30a ¤   pgpAssert (context);
7bebf4 ¤   pgpAssert (context->tail);
7caf5a
bb63fd ¤   error = DoFlush (context);
e50161 ¤   if (error)
80fcee ¤   ¤   return error;
36af5a
c39819 ¤   return context->tail->flush (context->tail);
--3565 000c4ece4df401001a9 Page 2 of pgpInfMod.c
7aefe6 }
46af5a
c45d09 static size_t
13f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
3dbb36 {
4398c9 ¤   InfModContext *context;
243d84 ¤   size_t written, retlen = 0;
71af5a
1729be ¤   pgpAssert (myself);
a94068 ¤   pgpAssert (myself->magic == INFMODMAGIC);
9c4866 ¤   pgpAssert (error);
7eaf5a
665ca1 ¤   context = (InfModContext *)myself->priv;
c6d30a ¤   pgpAssert (context);
33ebf4 ¤   pgpAssert (context->tail);
a6af5a
6b7577 ¤   /* Flush what is buffered */
970479 ¤   *error = DoFlush (context);
9e5842 ¤   if (*error)
2d90e3 ¤   ¤   return retlen;
41af5a
9843ab ¤   do {
047ac4 ¤   ¤   /* Process data */
12f6ed ¤   ¤   written = infWrite (context->inf, (PGPByte *)buf, size, error);
4bc98e ¤   ¤   retlen += written;
16d06f ¤   ¤   buf += written;
0b28a7 ¤   ¤   size -= written;
3ccf31 ¤   ¤   if (*error)
397202 ¤   ¤   ¤   return retlen;
c8af5a
c1ecf5 ¤   ¤   /* And flush it! */
428f85 ¤   ¤   *error = DoFlush (context);
eccf31 ¤   ¤   if (*error)
937202 ¤   ¤   ¤   return retlen;
c8af5a
750fea ¤   } while (size);
b9f11d ¤   /* Continue until we have left to read */
36af5a
39ab0a ¤   return retlen;
3fefe6 }
89af5a
34f1ae static PGPError
2013c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
c2b0b1 ¤   ··PGPByte const *string, size_t size)
5ebb36 {
0f98c9 ¤   InfModContext *context;
6187a6 ¤   PGPError¤   error;
47af5a
4f29be ¤   pgpAssert (myself);
f64068 ¤   pgpAssert (myself->magic == INFMODMAGIC);
ecaf5a
555ca1 ¤   context = (InfModContext *)myself->priv;
5ad30a ¤   pgpAssert (context);
52ebf4 ¤   pgpAssert (context->tail);
ddaf5a
9c63fd ¤   error = DoFlush (context);
f00161 ¤   if (error)
24fcee ¤   ¤   return error;
aaaf5a
2432ab ¤   error = context->tail->annotate (context->tail, origin, type,
683153 ¤   ¤   ¤   ¤   ¤   string, size);
12ff2e ¤   if (!error)
6b6467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
555709 ¤   pgpAssert (context->scope_depth != -1);
0ec674 ¤   return error;
d2efe6 }
faaf5a
8ef1ae static PGPError
f94b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
d5bb36 {
5398c9 ¤   InfModContext *context;
c4ac9b ¤   PGPError eoferr;
--6a3e 000d5c9d0f4401001a9 Page 3 of pgpInfMod.c
d287a6 ¤   PGPError¤   error;
a3af5a
2e29be ¤   pgpAssert (myself);
1b4068 ¤   pgpAssert (myself->magic == INFMODMAGIC);
b0af5a
c95ca1 ¤   context = (InfModContext *)myself->priv;
64d30a ¤   pgpAssert (context);
c0ebf4 ¤   pgpAssert (context->tail);
f7af5a
aabe73 ¤   if (!bytes && !context->scope_depth) {
ed4392 ¤   ¤   do {
ccde02 ¤   ¤   ¤   eoferr = (PGPError)infEOF (context->inf);
d12346 ¤   ¤   ¤   if (eoferr < 0)
d5e73f ¤   ¤   ¤   ¤   return eoferr;
46af5a
a3ae71 ¤   ¤   ¤   error = DoFlush (context);
78d82b ¤   ¤   ¤   if (error)
15b20f ¤   ¤   ¤   ¤   return error;
dea597 ¤   ¤   } while (eoferr);
079371 ¤   }
36af5a
28e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
20efe6 }
d5af5a
a9f1ae static PGPError
9dc7e1 Teardown (PGPPipeline *myself)
76bb36 {
4398c9 ¤   InfModContext *context;
60e9fa ¤   PGPContextRef¤  cdkContext;
e867c5 ¤
8b3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
69696e ¤   cdkContext¤ = myself->cdkContext;
d6af5a
d529be ¤   pgpAssert (myself);
214068 ¤   pgpAssert (myself->magic == INFMODMAGIC);
56af5a
345ca1 ¤   context = (InfModContext *)myself->priv;
50d30a ¤   pgpAssert (context);
87af5a
47cb05 ¤   if (context->tail)
a61e8a ¤   ¤   context->tail->teardown (context->tail);
69af5a
d89300 ¤   infFree (context->inf);
3c3736 ¤   pgpClearMemory( context, ·sizeof (*context));
e7fa6e ¤   pgpContextMemFree( cdkContext, context);
ca67c5 ¤
97151e ¤   return kPGPError_NoErr;
38efe6 }
e0af5a
1e41cd PGPPipeline **
fb4ac0 infModCreate (
113163 ¤   PGPContextRef¤  cdkContext,
a1198b ¤   PGPPipeline **¤ head)
90bb36 {
6d0df0 ¤   PGPPipeline *mod;
6198c9 ¤   InfModContext *context;
00af5a
63bb3d ¤   if (!head)
fa7ed2 ¤   ¤   return NULL;
f5af5a
537546 ¤   context = (InfModContext *)pgpContextMemAlloc( cdkContext,
98d680 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear);
cb1ea4 ¤   if (!context)
be7ed2 ¤   ¤   return NULL;
049228 ¤   mod = &context->pipe;
89af5a
a38b89 ¤   mod->magic = INFMODMAGIC;
511f83 ¤   mod->write = Write;
02ac4e ¤   mod->flush = Flush;
140aaf ¤   mod->sizeAdvise = SizeAdvise;
31d3a2 ¤   mod->annotate = Annotate;
d596de ¤   mod->teardown = Teardown;
--bfdb 0018637e3a9401001a9 Page 4 of pgpInfMod.c
f7e5ee ¤   mod->name = "Inflation Module";
7a01ea ¤   mod->priv = context;
dfa99e ¤   mod->cdkContext¤= cdkContext;
53af5a
e071b8 ¤   context->inf = infAlloc ( cdkContext );
89af5a
cd65ad ¤   context->tail = *head;
eb2d11 ¤   *head = mod;
3f7fa2 ¤   return &context->tail;
86efe6 }
--3783 001a1e13634401001aa Page 1 of pgpInfMod.h
bc38e5 /*
15664b ·* pgpInfMod.h -- inflation module
c3775e ·*
0e7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
51775e ·*
4fe39d ·* This is a PRIVATE header file, for use only within the PGP Library.
f52979 ·* You should not be using these functions in an application.
56775e ·*
7fa2f9 ·* $Id: pgpInfMod.h,v 1.5 1997/06/25 19:40:16 lloyd Exp $
19495d ·*/
94af5a
e299c6 PGP_BEGIN_C_DECLARATIONS
c5af5a
1f275d #include "pgpPipelineOpaqueStructs.h"
bde82c #include "pgpPubTypes.h"
3caf5a
02c726 PGPPipeline **infModCreate (PGPContextRef cdkContext, PGPPipeline **head);
81af5a
a11254 PGP_END_C_DECLARATIONS
--2fcd 001c19b9451401001ab Page 1 of pgpLiteral.c
bc38e5 /*
455468 ·* pgpLiteral.c -- create a literal packet
56775e ·*
0e7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
cb775e ·*
ce538a ·* $Id: pgpLiteral.c,v 1.10 1997/09/18 01:35:24 lloyd Exp $
f1495d ·*/
f3e2ff #include "pgpConfig.h"
d3af5a
1bfeb2 #include <stdio.h>
d1324c #include <string.h>
52af5a
0577c6 #include "pgpAddHdr.h"
580ce3 #include "pgpLiteral.h"
5e9c38 #include "pgpPktByte.h"
512ece #include "pgpPipeline.h"
eb0d08 #include "pgpMem.h"
10af5a
0641cd PGPPipeline **
cc6305 pgpLiteralCreate (
3758f9 ¤   PGPContextRef¤  ¤   cdkContext,
060d82 ¤   PGPPipeline **¤ ¤   head,
675efe ¤   PgpVersion¤ ¤   ¤   version,
08f138 ¤   PGPFifoDesc const *¤fd,
e1f69e ¤   PGPByte¤¤   ¤   ¤   type,
6ce817 ¤   PGPByte *¤  ¤   ¤   name,
6ce3da ¤   PGPByte¤¤   ¤   ¤   len,
363d31 ¤   PGPUInt32¤  ¤   ¤   timestamp)
68bb36 {
070467 ¤   PGPByte header[261];¤   /* Maximum size of a literal header */
dc4ba4 ¤   int i;
f7f61b ¤   PGPPipeline **mod;
4eaf5a
4abb3d ¤   if (!head)
087ed2 ¤   ¤   return NULL;
ecaf5a
742267 ¤   header[0] = type;
ef17a8 ¤   header[1] = len;
7b460f ¤   memcpy (header+2, name, len);
982a01 ¤   len += 2;
fe2dd3 ¤   for (i=3; i > 0; i--) {
7fd4c6 ¤   ¤   header[len+i] = (PGPByte) (timestamp & 0xff);
46f518 ¤   ¤   timestamp >>= 8;
949371 ¤   }
f3af5a
efe6b7 ¤   mod = pgpAddHeaderCreate ( cdkContext,
ed4ee9 ¤   ¤   ¤   head, version, fd, PKTBYTE_LITERAL, 0, header, len+4);
80af5a
8debd2 ¤   pgpClearMemory( header, ·sizeof (header));
1ae1d8 ¤   if (mod)
d5bba5 ¤   ¤   (*head)->name = "Literal Module";
d2af5a
861fea ¤   return mod;
c1efe6 }
--68bb 0011925475b401001ac Page 1 of pgpLiteral.h
bc38e5 /*
ffb3b1 ·* pgpLiteral.h -- Create a Literal Packet Module
a0775e ·*
087ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
a1775e ·*
b1373b ·* $Id: pgpLiteral.h,v 1.10 1997/06/25 19:40:17 lloyd Exp $
1e495d ·*/
feaf5a
1d5b2e #ifndef Included_pgpLiteral_h
1f0f1a #define Included_pgpLiteral_h
f6af5a
55d11f #include "pgpUsuals.h"
65af5a
5d99c6 PGP_BEGIN_C_DECLARATIONS
7daf5a
9daf5a
c6af5a
b438e5 /*
a07c0d ·* This creates a module for a literal packet. ·The type should be
ee7d2f ·* either 'b' or 't' for binary or text. ·The name is len bytes which
a38810 ·* specifies the name of the file. ·The timestamp is the timestamp of
e86d4a ·* the file.
2a495d ·*/
97f481 PGPPipeline ·**
2a14ec pgpLiteralCreate (PGPContextRef cdkContext,
400f32 ¤   PGPPipeline **head, PgpVersion version,
3b65b3 ¤   PGPFifoDesc const *fd, PGPByte type, PGPByte *name,
c7cb38 ¤   PGPByte len, PGPUInt32 timestamp);
0eaf5a
ee1254 PGP_END_C_DECLARATIONS
e1af5a
19f7c5 #endif /* Included_pgpLiteral_h */
--5b5e 00093776b00401001ad Page 1 of pgpTextFilt.c
bc38e5 /*
558ba6 ·* pgpTextFilt.c -- filter text
59775e ·*
3df49c ·* Written by:¤ Derek Atkins <warlord@MIT.EDU> and Colin Plumb
d3775e ·*
b356f0 ·* $Id: pgpTextFilt.c,v 1.23 1997/12/12 01:14:09 heller Exp $
2a495d ·*/
a6e2ff #include "pgpConfig.h"
53af5a
f5feb2 #include <stdio.h>
1f324c #include <string.h>
43af5a
91a146 #include "pgpDebug.h"
903576 #include "pgpTextFilt.h"
820d08 #include "pgpMem.h"
622ece #include "pgpPipeline.h"
b92f8d #include "pgpErrors.h"
92d11f #include "pgpUsuals.h"
e6c26c #include "pgpContext.h"
a9af5a
0aec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
19b0e3 #define kPGPFiltBufSize¤¤   16384
aedb21 #else
668e97 #define kPGPFiltBufSize¤¤   BUFSIZ
d07454 #endif
a4af5a
3307ca #define TEXTFILTMAGIC¤  0x1e81f111
60af5a
8f406e typedef struct TextFiltContext {
a48b60 ¤   PGPPipeline¤pipe;
4367c5 ¤
90fc43 ¤   PGPByte buffer[kPGPFiltBufSize];
94c98f ¤   PGPByte *bufptr;
58c822 ¤   size_t buflen;
2e75b0 ¤   PGPPipeline *tail;
8e6fd2 ¤   PGPByte const *map;¤/* 256-entry mapping table */
1161ab ¤   int crlf;¤  ¤   /* 0=nothing, 1=LF, 2=CRLF, 3=CR */
3a44ac ¤   int stripspace;
b9ee81 ¤   size_t spaces;
1beece ¤   int ignorelf;
045ddf ¤   DEBUG_STRUCT_CONSTRUCTOR( TextFiltContext )
d847e2 } TextFiltContext;
faaf5a
0ff1ae static PGPError
b2821f DoFlush (TextFiltContext *context)
bcbb36 {
855b01 ¤   PGPError¤   error = kPGPError_NoErr;
3b6c75 ¤   size_t retlen;
8aaf5a
7816d3 ¤   /* Try to flush anything that we have buffered */
a949b8 ¤   while (context->buflen) {
bf88b9 ¤   ¤   retlen = context->tail->write (context->tail,
65d239 ¤   ¤   ¤   ¤   ¤   ·······context->bufptr,
64ee65 ¤   ¤   ¤   ¤   ¤   ·······context->buflen,
6a48b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
8de166 ¤   ¤   context->buflen -= retlen;
d89c96 ¤   ¤   pgpClearMemory (context->bufptr, retlen);
ee060f ¤   ¤   context->bufptr += retlen;
cae3c2 ¤   ¤   if (error)
2d3b5b ¤   ¤   ¤   return error;
f49371 ¤   }
2bc674 ¤   return error;
75efe6 }
faaf5a
a938e5 /*
ee6ad0 ·* Note: it is assumed that \r, \n and ' ' use the identity mapping.
a12cfe ·* This will need fixing for EBCDIC.
ee495d ·*/
585d09 static size_t
f9ba2c textFilt (TextFiltContext *context, PGPByte const *in, size_t inlen)
3dbb36 {
93faae ¤   size_t spaces = context->spaces;
--82af 000ca0d8c00401001ad Page 2 of pgpTextFilt.c
ec36e1 ¤   int ignorelf = context->ignorelf;
7f826c ¤   PGPByte *out = context->bufptr+context->buflen;
aea058 ¤   size_t outlen = context->buffer+sizeof(context->buffer)-out;
f78bbc ¤   size_t inlen0 = inlen;
e7a508 ¤   PGPByte c;
07af5a
1ddff1 ¤   pgpAssert (outlen);
abaf5a
79fb45 ¤   while (inlen && outlen) {
3a1dd8 ¤   ¤   c = *in;
d6af5a
bc0f85 ¤   ¤   if (ignorelf) {
fc5a90 ¤   ¤   ¤   ignorelf = 0;
a6e2f0 ¤   ¤   ¤   if (c == '\n') {
6575ba ¤   ¤   ¤   ¤   in++;
dac679 ¤   ¤   ¤   ¤   inlen--;
74d040 ¤   ¤   ¤   ¤   continue;
14a3a6 ¤   ¤   ¤   }
8c0fe4 ¤   ¤   }
292f85 ¤   ¤   if (c == '\n' || c == '\r') {
72c0e5 ¤   ¤   ¤   if (context->crlf) {
896e2e ¤   ¤   ¤   ¤   if (context->crlf == kPGPLineEnd_CRLF) {
cea5c8 ¤   ¤   ¤   ¤   ¤   if (outlen < 2)
7d00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
a34c05 ¤   ¤   ¤   ¤   ¤   outlen--;
992613 ¤   ¤   ¤   ¤   }
a58db6 ¤   ¤   ¤   ¤   if (context->crlf & kPGPLineEnd_CR)
12fd46 ¤   ¤   ¤   ¤   ¤   *out++ = '\r';
14d9bb ¤   ¤   ¤   ¤   if (context->crlf & kPGPLineEnd_LF)
fba9d3 ¤   ¤   ¤   ¤   ¤   *out++ = '\n';
21c551 ¤   ¤   ¤   ¤   outlen--;
1775ba ¤   ¤   ¤   ¤   in++;
5fc679 ¤   ¤   ¤   ¤   inlen--;
4bd650 ¤   ¤   ¤   ¤   ignorelf = (c == '\r');
be83e0 ¤   ¤   ¤   ¤   spaces = 0;
ecd040 ¤   ¤   ¤   ¤   continue;
04a3a6 ¤   ¤   ¤   }
487585 ¤   ¤   ¤   spaces = 0;
b70fe4 ¤   ¤   }
e4afb9 ¤   ¤   if (context->stripspace && c == ' ') {
69fb81 ¤   ¤   ¤   spaces++;
254f20 ¤   ¤   ¤   in++;
6677a8 ¤   ¤   ¤   inlen--;
5917f5 ¤   ¤   ¤   continue;
c60fe4 ¤   ¤   }
b8c8a3 ¤   ¤   if (spaces) {
a815ba ¤   ¤   ¤   int i = pgpMin (spaces, outlen);
c4af5a
8a0ff8 ¤   ¤   ¤   pgpFillMemory (out, i, ' ');
2e7b59 ¤   ¤   ¤   outlen -= i;
a4ac8e ¤   ¤   ¤   spaces -= i;
1ec93d ¤   ¤   ¤   out += i;
4517f5 ¤   ¤   ¤   continue;
910fe4 ¤   ¤   }
c304f9 ¤   ¤   *out++ = context->map[c];
2cca95 ¤   ¤   in++;
48387e ¤   ¤   outlen--;
7c3623 ¤   ¤   inlen--;
8d9371 ¤   }
68af5a
a73180 ¤   context->spaces = spaces;
24acdb ¤   context->ignorelf = ignorelf;
df8588 ¤   context->buflen = out - context->bufptr;
eccbe0 ¤   return inlen0 - inlen;
4eefe6 }
22af5a
45f1ae static PGPError
8bd02e Flush (PGPPipeline *myself)
a9bb36 {
15fddf ¤   TextFiltContext *context;
b787a6 ¤   PGPError¤   error;
caaf5a
--e196 000eebd0396401001ad Page 3 of pgpTextFilt.c
c629be ¤   pgpAssert (myself);
700ca1 ¤   pgpAssert (myself->magic == TEXTFILTMAGIC);
0daf5a
e96600 ¤   context = (TextFiltContext *)myself->priv;
73d30a ¤   pgpAssert (context);
63ebf4 ¤   pgpAssert (context->tail);
09af5a
0463fd ¤   error = DoFlush (context);
e40161 ¤   if (error)
86fcee ¤   ¤   return error;
a9af5a
5f9819 ¤   return context->tail->flush (context->tail);
32efe6 }
bdaf5a
a45d09 static size_t
88f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
f0bb36 {
5bfddf ¤   TextFiltContext *context;
423d84 ¤   size_t written, retlen = 0;
c3af5a
4329be ¤   pgpAssert (myself);
650ca1 ¤   pgpAssert (myself->magic == TEXTFILTMAGIC);
e04866 ¤   pgpAssert (error);
a8af5a
1c6600 ¤   context = (TextFiltContext *)myself->priv;
73d30a ¤   pgpAssert (context);
7eebf4 ¤   pgpAssert (context->tail);
3aaf5a
da43ab ¤   do {
838f85 ¤   ¤   *error = DoFlush (context);
9ccf31 ¤   ¤   if (*error)
4b7202 ¤   ¤   ¤   return retlen;
22af5a
711b17 ¤   ¤   /*
5c4511 ¤   ¤   ·* Now that we dont have anything buffered, bring in more
353604 ¤   ¤   ·* data from the passed-in buffer, process it, and buffer
4c4169 ¤   ¤   ·* that to write out.
879de3 ¤   ¤   ·*/
55fe69 ¤   ¤   context->bufptr = context->buffer;
168c9f ¤   ¤   written = textFilt (context, buf, size);
0dfb77 ¤   ¤   /* context->buflen is set by textFilt() */
30d06f ¤   ¤   buf += written;
5a28a7 ¤   ¤   size -= written;
3ac98e ¤   ¤   retlen += written;
3caf5a
5664ca ¤   } while (context->buflen > 0);
adc130 ¤   /* Continue until we have nothing buffered */
9aaf5a
67ab0a ¤   return retlen;
78efe6 }
73af5a
19f1ae static PGPError
c213c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
e9b0b1 ¤   ··PGPByte const *string, size_t size)
07bb36 {
2bfddf ¤   TextFiltContext *context;
6487a6 ¤   PGPError¤   error;
1caf5a
ee29be ¤   pgpAssert (myself);
7b0ca1 ¤   pgpAssert (myself->magic == TEXTFILTMAGIC);
14af5a
5d6600 ¤   context = (TextFiltContext *)myself->priv;
21d30a ¤   pgpAssert (context);
82ebf4 ¤   pgpAssert (context->tail);
3baf5a
bf63fd ¤   error = DoFlush (context);
b20161 ¤   if (error)
45fcee ¤   ¤   return error;
63af5a
fc0df2 ¤   return context->tail->annotate (context->tail, origin, type,
043153 ¤   ¤   ¤   ¤   ¤   string, size);
eeefe6 }
--9c9e 0009e5fac1e401001ad Page 4 of pgpTextFilt.c
e0af5a
c1f1ae static PGPError
054b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
6abb36 {
aafddf ¤   TextFiltContext *context;
7387a6 ¤   PGPError¤   error;
70af5a
fb29be ¤   pgpAssert (myself);
100ca1 ¤   pgpAssert (myself->magic == TEXTFILTMAGIC);
6eaf5a
cf6600 ¤   context = (TextFiltContext *)myself->priv;
e6d30a ¤   pgpAssert (context);
92ebf4 ¤   pgpAssert (context->tail);
1daf5a
7063fd ¤   error = DoFlush (context);
b666ed ¤   if (error || (bytes && (context->stripspace || context->crlf)))
1cfcee ¤   ¤   return error;
42af5a
02e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
50efe6 }
abaf5a
d6f1ae static PGPError
c3c7e1 Teardown (PGPPipeline *myself)
33bb36 {
a1fddf ¤   TextFiltContext *context;
42e9fa ¤   PGPContextRef¤  cdkContext;
2d67c5 ¤
f83982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
06696e ¤   cdkContext¤ = myself->cdkContext;
69af5a
7029be ¤   pgpAssert (myself);
ff0ca1 ¤   pgpAssert (myself->magic == TEXTFILTMAGIC);
62af5a
3a6600 ¤   context = (TextFiltContext *)myself->priv;
35d30a ¤   pgpAssert (context);
cbaf5a
5bcb05 ¤   if (context->tail)
1a1e8a ¤   ¤   context->tail->teardown (context->tail);
70af5a
653736 ¤   pgpClearMemory( context, ·sizeof (*context));
10fa6e ¤   pgpContextMemFree( cdkContext, context);
5b67c5 ¤
53151e ¤   return kPGPError_NoErr;
dfefe6 }
06af5a
b541cd PGPPipeline **
763aa5 pgpTextFiltCreate (
07fdf9 ¤   PGPContextRef cdkContext,
558941 ¤   PGPPipeline **head,
6baef4 ¤   PGPByte const *map,
979c35 ¤   int stripspace,
e9ffe2 ¤   PGPLineEndType crlf)
7ebb36 {
660df0 ¤   PGPPipeline *mod;
0efddf ¤   TextFiltContext *context;
98af5a
d598d2 ¤   pgpAssert (map);
6eaf5a
93bb3d ¤   if (!head)
0f7ed2 ¤   ¤   return NULL;
e7af5a
5f5de4 ¤   context = (TextFiltContext *)pgpContextMemAlloc( cdkContext,
434db0 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear );
3c1ea4 ¤   if (!context)
b57ed2 ¤   ¤   return NULL;
9d9228 ¤   mod = &context->pipe;
51af5a
341239 ¤   mod->magic = TEXTFILTMAGIC;
151f83 ¤   mod->write = Write;
19ac4e ¤   mod->flush = Flush;
7b0aaf ¤   mod->sizeAdvise = SizeAdvise;
9ed3a2 ¤   mod->annotate = Annotate;
--be94 001ab9dd119401001ad Page 5 of pgpTextFilt.c
3896de ¤   mod->teardown = Teardown;
a0ba1f ¤   mod->name = "Text Filter Module";
4801ea ¤   mod->priv = context;
f0a99e ¤   mod->cdkContext¤= cdkContext;
97af5a
c0f025 ¤   context->bufptr = context->buffer;
e1d008 ¤   context->map = map;
91b068 ¤   context->stripspace = stripspace;
32ab13 ¤   context->crlf = crlf;
2baf5a
2365ad ¤   context->tail = *head;
0c2d11 ¤   *head = mod;
857fa2 ¤   return &context->tail;
abefe6 }
--f30e 001cb500416401001ae Page 1 of pgpTextFilt.h
bc38e5 /*
cab35e ·* pgpTextFilt.h -- Text Filter Module
a6775e ·*
037ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
62775e ·*
ed8190 ·* This is a Public API Function Header.
f1775e ·*
b3995e ·* $Id: pgpTextFilt.h,v 1.10 1997/07/25 00:52:38 hal Exp $
2c495d ·*/
88af5a
4662a3 #ifndef Included_pgpTextFilt_h
1c1550 #define Included_pgpTextFilt_h
99af5a
11d11f #include "pgpUsuals.h"
d3af5a
2899c6 PGP_BEGIN_C_DECLARATIONS
acaf5a
1badb8 #include "pgpOpaqueStructs.h"
cbe82c #include "pgpPubTypes.h"
1f9f63 #include "pgpEncode.h"
54af5a
d938e5 /*
48df4a ·* Create a text filtering module. ·It will use the appropriate
92f468 ·* character map to map input to output characters. ·It will optionally
d67ef3 ·* strip ending spaces off the end of lines, if stripspace is non-zero.
4719d3 ·* It will also convert line-endings to the appropriate type if
8a0e33 ·* crlf is non-zero. ·Use TEXTFILT_* to designate the line-ending
652a1a ·* required.
c7495d ·*/
6af481 PGPPipeline ·**
8f3aa5 pgpTextFiltCreate (
e1fdf9 ¤   PGPContextRef cdkContext,
b8c5ef ¤   PGPPipeline **head, PGPByte const *map, int stripspace,
9ac4c3 ¤   PGPLineEndType crlf);
1aaf5a
d81254 PGP_END_C_DECLARATIONS
9faf5a
cb4b01 #endif /* Included_pgpTextFilt_h */
--5c05 00058e7757a401001af Page 1 of pgpZBits.c
bc38e5 /*
5d775e ·*
416f50 ·* Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup
847cf3 ·* Gailly. ·Permission is granted to any individual or institution to use,
fadab6 ·* copy, or redistribute this software so long as all of the original
f86d2c ·* files are included unmodified, that it is not sold for profit, and
df29ea ·* that this copyright notice is retained.
23775e ·*
b452ef ·* Hacked up for PGP by Colin Plumb
28775e ·*
bde5dd ·* $Id: pgpZBits.c,v 1.12 1997/12/12 01:14:10 heller Exp $
d3495d ·*/
e4af5a
5b38e5 /*
70e3f2 ·* ·bits.c by Jean-loup Gailly.
04775e ·*
62761a ·* ·This is a new version of im_bits.c originally written by Richard B. Wales
b6775e ·*
17b0e2 ·* ·PURPOSE
dc775e ·*
6d69c1 ·* ·····Output variable-length bit strings.
b4775e ·*
bae174 ·* ·DISCUSSION
03775e ·*
0aa578 ·* ·····The PKZIP "deflate" file format interprets compressed file data
23a9c0 ·* ·····as a sequence of bits. ·Multi-bit strings in the file may cross
f4aae0 ·* ·····byte boundaries without restriction.
e8775e ·*
398e7a ·* ·····The first bit of each byte is the low-order bit.
b3775e ·*
c892de ·* ·····The routines in this file allow a variable-length bit value to
7f5f6e ·* ·····be output right-to-left (useful for literal values). For
073bac ·* ·····left-to-right output (useful for code strings from the tree routines),
071dcc ·* ·····the bits must have been reversed first with bi_reverse().
d5775e ·*
ce6c07 ·* ·INTERFACE
58775e ·*
a15fd8 ·* ·····void bi_init (PGPFifoContext *zipfifo)
25339b ·* ·········Initialize the bit string routines. ·If zipfifo is
20eff4 ·* ·········non-NULL, does a hard reset. ·If it is NULL, just
d284f1 ·* ·········sets variables to re-fetch the FIFO write pointer,
77634c ·* ·········because it has been invalidated by FIFO reads.
e3775e ·*
489ae8 ·* ·····void send_bits (int value, int length)
0bd785 ·* ·········Write out a bit string, taking the source bits right to
7cbedb ·* ·········left.
f7775e ·*
862936 ·* ·····int bi_reverse (int value, int length)
3e6cd9 ·* ·········Reverse the bits of a bit string, taking the source bits left to
e9db11 ·* ·········right and emitting them right to left.
d0775e ·*
3f2869 ·* ·····void bi_windup (void)
86e58f ·* ·········Write out any remaining bits in an incomplete byte.
4e775e ·*
e34782 ·* ·····void copy_block(char const far *buf, unsigned len, int header)
e3e99a ·* ·········Copy a stored block to the zip file, storing first the length and
6d4fa8 ·* ·········its one's complement if requested.
0f775e ·*
aa495d ·*/
6eaf5a
1fe2ff #include "pgpConfig.h"
08af5a
eb83d5 #include "pgpByteFIFO.h"
03c26c #include "pgpContext.h"
e18619 #include "pgpZip.h"
f4af5a
56da25 /* ===========================================================================
4681f2 ·* Local data used by the "bit string" routines.
1e495d ·*/
95af5a
919b6f #define Buf_size 16
58b4fd /* Number of bits used within bi_buf. (bi_buf might be implemented on
--e19b 0004168f2c3401001af Page 2 of pgpZBits.c
67f7fd ·* more than 16 bits on some systems.)
98495d ·*/
c2af5a
cd7dd3 typedef struct ZBitsContext {
a9af5a
978060 ¤   PGPContextRef¤  ¤   cdkContext;
1eaf5a
c16e2c ¤   unsigned¤   ·bi_buf;
dcf93f ¤   /* Output buffer. bits are inserted starting at the bottom (least
af01e2 ¤   ·* significant bits). ·High-order unused bits are always zero.
8ea4e3 ¤   ·*/
35af5a
3e7fb7 ¤   int¤ bi_valid; ···············/* number of valid bits in bi_buf */
ca0b2c ¤   /* All bits above the last valid bit are always zero.
25a4e3 ¤   ·*/
34af5a
50f404 ¤   /* The current output buffer */
6b2d5f ¤   unsigned char *outptr;
ddf20f ¤   PGPSize¤outtotal;
e77fe5 ¤   PGPSize¤outleft;
6aaf5a
c8e0db ¤   /* How to do output. */
904ce2 ¤   PGPFifoContext *zfifo;
9503ae } ZBitsContext;
87af5a
663e0f #ifdef ZIPDEBUG
0cb51c PGPUInt32 bits_sent; ··/* bit length of the compressed data */
8e7454 #endif
3baf5a
70af5a
caaf5a
60a805 #define bi_getspace(ctx, len) byteFifoGetSpace((ctx)->zfifo, (len))
e10aad #define bi_skipspace(ctx, len) byteFifoSkipSpace((ctx)->zfifo, (len))
04af5a
19048d #define PUTBYTE(ctx, c) ((ctx)->outleft = ((ctx)->outleft ? (ctx)->outleft : \
40f5a7 ·····································(bi_skipspace((ctx), (ctx)->outtotal), \
5643d4 ·····································(ctx)->outptr = \
1df660 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   bi_getspace((ctx), &(ctx)->outtotal), \
052438 ·········································(ctx)->outtotal))-1, \
85141e ····················¤   *(ctx)->outptr++ = (unsigned char)(c))
c3af5a
bdec0f #define PUTSHORT(ctx, w) (PUTBYTE((ctx), w), PUTBYTE((ctx), (w)>>8))
0baf5a
7baf5a
a1cdc0 ZBitsContext *
a6b5cb bi_init(PGPContextRef cdkContext, PGPFifoContext *zipfifo)
2abb36 {
8196e1 ¤   ZBitsContext *ctx;
15af5a
ee6e80 ¤   ctx = (ZBitsContext *) pgpContextMemAlloc (cdkContext, sizeof(*ctx),
e2e023 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear);
f78b42 ¤   if (IsNull (ctx) )
a67ed2 ¤   ¤   return NULL;
ec8b52 ¤   ctx->cdkContext = cdkContext;
b7af5a
9a86ce ¤   ctx->outleft = ctx->outtotal = 0;
a071d4 ¤   ctx->zfifo = zipfifo;
edaf5a
020c03 ¤   ctx->bi_buf = 0;
cbc4aa ¤   ctx->bi_valid = 0;
613e0f #ifdef ZIPDEBUG
4a6c98 ¤   bits_sent = 0L;
507454 #endif
315dd0 ¤   return ctx;
4fefe6 }
83af5a
77314a void
c9abf0 bi_free(ZBitsContext *ctx)
43bb36 {
345626 ¤   /* Caller is responsible for freeing fifo */
6c2560 ¤   PGPContextRef cdkContext;
41af5a
--722f 0009edee873401001af Page 3 of pgpZBits.c
a6f0ec ¤   cdkContext = ctx->cdkContext;
bcb33c ¤   pgpClearMemory( ctx, sizeof(*ctx) );
b758a9 ¤   pgpContextMemFree( cdkContext, ctx );
98efe6 }
5caf5a
8938e5 /*
08a8b9 ·* Make sure that all data written out is recorded, and invalidate
22ecae ·* the cached pointers because reading the output buffer might
f822d6 ·* move things around. ·PUTBYTE will re-fetch the appropriate data.
08495d ·*/
82314a void
0b79a4 bi_flush(ZBitsContext *ctx)
3cbb36 {
362391 ¤   bi_skipspace(ctx, ctx->outtotal-ctx->outleft);
d386ce ¤   ctx->outleft = ctx->outtotal = 0;
06efe6 }
b8af5a
4f314a void
41d71c bi_windup(ZBitsContext *ctx)
1bbb36 {
27f96a ¤   if (ctx->bi_valid > 8) {
8b0832 ¤   ¤   PUTSHORT(ctx, ctx->bi_buf);
62824e ¤   } else if (ctx->bi_valid > 0) {
49da44 ¤   ¤   PUTBYTE(ctx, ctx->bi_buf);
949371 ¤   }
070c03 ¤   ctx->bi_buf = 0;
ffc4aa ¤   ctx->bi_valid = 0;
4d3e0f #ifdef ZIPDEBUG
6da560 ¤   bits_sent = (bits_sent+7) & ~7;
cb7454 #endif
f2af5a
0b2391 ¤   bi_skipspace(ctx, ctx->outtotal-ctx->outleft);
d520d1 ¤   ctx->outptr = bi_getspace(ctx, &ctx->outtotal);
d3141a ¤   ctx->outleft = ctx->outtotal;
01efe6 }
47af5a
81314a void
fc0e3b copy_block(ZBitsContext *ctx, char const far *buf, unsigned len, int header)
37bb36 {
1b1518 ¤   bi_windup(ctx); ··········/* align on byte boundary */
85af5a
dd3e0f #ifdef ZIPDEBUG
bddb94 ¤   bits_sent += (PGPUInt32)len<<3;
5a7454 #endif
73af5a
d07cfb ¤   if (header) {
5026fa ¤   ¤   PUTSHORT(ctx, (PGPUInt16)len);
64c985 ¤   ¤   PUTSHORT(ctx, (PGPUInt16)~len);
6b3e0f #ifdef ZIPDEBUG
250c2f ¤   ¤   bits_sent += 2*16;
ee7454 #endif
1b9371 ¤   }
a35d2b ¤   while (len >= ctx->outleft) {
ccf9e0 ¤   ¤   memcpy(ctx->outptr, buf, ctx->outleft);
34fb3a ¤   ¤   len -= ctx->outleft;
3bbcb0 ¤   ¤   buf += ctx->outleft;
bd03d1 ¤   ¤   bi_skipspace(ctx, ctx->outtotal);
3a757d ¤   ¤   ctx->outptr = bi_getspace(ctx, &ctx->outtotal);
6ffb69 ¤   ¤   ctx->outleft = ctx->outtotal;
ec9371 ¤   }
815678 ¤   if (len) {
b2a63a ¤   ¤   memcpy(ctx->outptr, buf, len);
ece414 ¤   ¤   ctx->outptr += len;
85ca7c ¤   ¤   ctx->outleft -= len;
6f9371 ¤   }
14efe6 }
c9af5a
5baf5a
57da25 /* ===========================================================================
f782ec ·* Send a value made up of a given number of bits.
3e0b96 ·* IN assertion: length <= 15 and value < (1 << length).
9e495d ·*/
--3369 00147d07347401001af Page 4 of pgpZBits.c
b3314a void
4a1517 send_bits(ZBitsContext *ctx, int value, int length)
d0bb36 {
083e0f #ifdef ZIPDEBUG
e8249e ¤   Tracevv((stderr," l %2d v %4x ", length, value));
5b0232 ¤   ZipAssert(length > 0 && length <= 15, "invalid length");
f7ad00 ¤   ZipAssert(value < (1 << length), "invalid value");
fdb030 ¤   bits_sent += (PGPUInt32)length;
967454 #endif
0ed8af ¤   /*
0d73b8 ¤   ·* Add extra bits to bi_buf and add length to bi_valid. ·If this
ece502 ¤   ·* fills bi_buf, copy Buf_size bits to the output, decrementing
55b123 ¤   ·* bi_valid appropriately and set bi_buf to the remaining bi_valid
7a8e33 ¤   ·* high bits of value. ·(value >> (length - bi_valid)).
30a4e3 ¤   ·*/
2f7f76 ¤   ctx->bi_buf |= (value << ctx->bi_valid);
e1b531 ¤   ctx->bi_valid += length;
5cb72c ¤   if (ctx->bi_valid >= (int)Buf_size) {
4a0832 ¤   ¤   PUTSHORT(ctx, ctx->bi_buf);
0c335a ¤   ¤   ctx->bi_valid -= (int)Buf_size;
0d8492 ¤   ¤   ctx->bi_buf = (unsigned)value >> (length - ctx->bi_valid);
619371 ¤   }
47efe6 }
--e984 0002ff1bcac401001b0 Page 1 of pgpZDeflate.c
bc38e5 /*
dc4fec ·* Copyright (C) 1990-1993 Mark Adler, Richard B. Wales, Jean-loup Gailly,
caab83 ·* Kai Uwe Rommel and Igor Mandrichenko.
e647d7 ·* Permission is granted to any individual or institution to use, copy,
f0d9ba ·* or redistribute this software so long as all of the original files
af7285 ·* are included, that it is not sold for profit, and that this copyright
5d12f8 ·* notice is retained.
b3775e ·*
2f52ef ·* Hacked up for PGP by Colin Plumb
98775e ·*
c3c199 ·* $Id: pgpZDeflate.c,v 1.10 1997/12/12 01:14:11 heller Exp $
5d495d ·*/
09af5a
cb38e5 /*
de77dd ·* deflate.c by Jean-loup Gailly.
8e775e ·*
fb1524 ·* PURPOSE
87775e ·*
7aa6ab ·* ··Identify new text as repetitions of old text within a fixed-
1daada ·* ··length sliding window trailing behind the new text.
f3775e ·*
c1ec70 ·* DISCUSSION
63775e ·*
84ae38 ·* ··The "deflation" process depends on being able to identify portions
858c67 ·* ··of the input text which are identical to earlier input (within a
ac3099 ·* ··sliding window trailing behind the input currently being processed).
cc775e ·*
8c43ab ·* ··The most straightforward technique turns out to be the fastest for
da1bf3 ·* ··most input files: try all possible matches and select the longest.
639e87 ·* ··The key feature of this algorithm is that insertions into the string
695f55 ·* ··dictionary are very simple and thus fast, and deletions are avoided
307cdd ·* ··completely. Insertions are performed at each input character,
d722d9 ·* ··whereas string matches are performed only when the previous match
a68531 ·* ··ends. So it is preferable to spend more time in matches to allow very
bfd4f7 ·* ··fast string insertions and avoid deletions. The matching algorithm
bed8ed ·* ··for small strings is inspired from that of Rabin & Karp. ·A brute
9d1c17 ·* ··force approach is used to find longer strings when a small match has
6d61b2 ·* ··been found. ·A similar algorithm is used in comic (by Jan-Mark Wams)
88776c ·* ··and freeze (by Leonid Broukhis).
8b775e ·*
fe8d2b ·* ··A previous version of this file used a more sophisticated algorithm
c13b06 ·* ··(by Fiala and Greene) which is guaranteed to run in linear amortized
25d0a6 ·* ··time, but has a larger average cost, uses more memory and is patented.
ef018a ·* ··However the F&G algorithm may be faster for some highly redundant
a308d5 ·* ··files if the parameter max_chain_length (described below) is too large.
35775e ·*
cdd469 ·* ACKNOWLEDGEMENTS
83775e ·*
d4b6e6 ·* ··The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
fa776f ·* ··I found it in 'freeze' written by Leonid Broukhis.
12765e ·* ··Thanks to many info-zippers for bug reports and testing.
d7775e ·*
e5fe91 ·* REFERENCES
02775e ·*
cc69d0 ·* ··APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
1c775e ·*
899da4 ·* ··A description of the Rabin and Karp algorithm is given in the book
4bc141 ·* ·····"Algorithms" by R. Sedgewick, Addison-Wesley, p252.
7f775e ·*
c075fb ·* ··Fiala,E.R., and Greene,D.H.
4711ff ·* ·····Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
8a775e ·*
b400da ·* INTERFACE
73775e ·*
ee369a ·* ··int lm_init (int pack_level)
3a841e ·* ······Initialize the "longest match" routines for a new file
02775e ·*
c10bea ·* ··PGPUInt32 deflate (void)
e2b6f0 ·* ······Processes a new input file and return its compressed length. Sets
df2d3c ·* ······the compressed length, crc, deflate flags and internal file
e1d447 ·* ······attributes.
2f495d ·*/
--3fd2 0007a176d55401001b0 Page 2 of pgpZDeflate.c
e0af5a
64e2ff #include "pgpConfig.h"
38c26c #include "pgpContext.h"
08af5a
e38619 #include "pgpZip.h"
3daf5a
f7da25 /* ===========================================================================
4e6cd7 ·* Configuration parameters
39495d ·*/
75af5a
5038e5 /*
64c06e ·* Compile with MEDIUM_MEM to reduce the memory requirements or
20c986 ·* with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
d99617 ·* entire input file can be held in memory (not possible on 16 bit systems).
6817c3 ·* Warning: defining these symbols affects HASH_BITS (see below) and thus
4e5589 ·* affects the compression ratio. The compressed output
c05ffe ·* is still correct, and might even be smaller in some cases.
f8495d ·*/
efaf5a
e95cbb #ifdef SMALL_MEM
7eb58f # ··define HASH_BITS ·13 ·/* Number of bits used to hash strings */
c77454 #endif
bf243c #ifdef MEDIUM_MEM
051acd # ··define HASH_BITS ·14
9a7454 #endif
b41c1a #ifndef HASH_BITS
c80315 # ··define HASH_BITS ·15
2857cb ···/* For portability to 16 bit machines, do not use values above 15. */
177454 #endif
0eaf5a
ccb248 #define HASH_SIZE (unsigned)(1<<HASH_BITS)
ffd410 #define HASH_MASK (HASH_SIZE-1)
24ac31 #define WMASK ····(WSIZE-1)
528044 /* HASH_SIZE and WSIZE must be powers of two */
b2af5a
7da516 #define NIL 0
c1b6c6 /* Tail of hash chains */
eeaf5a
0e37e8 #ifndef TOO_FAR
ada808 # ·define TOO_FAR 4096
477454 #endif
f8a832 /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
d7af5a
f2af9b #ifdef ATARI_ST
e0c76e # ·undef MSDOS /* avoid the processor specific parts */
d5b17f ···/* (but the Atari should never define MSDOS anyway ...) */
a17454 #endif
f9deb2 #if defined(MSDOS) && !defined(NO_ASM) && !defined(ASMV)
65b396 # ·define ASMV
057454 #endif
01f9f1 #if defined(ASMV) && !defined(MSDOS) && defined(DYN_ALLOC)
df58a8 ··error: DYN_ALLOC not yet supported in match.s
4b7454 #endif
8aaf5a
b9da25 /* ===========================================================================
d4f9e6 ·* Local data used by the "longest match" routines.
f3495d ·*/
47af5a
08b7b7 #if defined(BIG_MEM) || defined(MMAP)
6c1f96 ··typedef size_t Pos; /* must be at least 32 bits */
53db21 #else
d4f257 ··typedef PGPUInt16 Pos;
a97454 #endif
588282 typedef unsigned IPos;
dbd3e8 /* A Pos is an index in the character window. We use short instead of int to
9741fe ·* save space in the various tables. IPos is used only for parameter passing.
99495d ·*/
b3af5a
e58b84 /* Private context structure for use by all functions. */
7c7892 typedef struct ZDeflateContext {
aeaf5a
7a8060 ¤   PGPContextRef¤  ¤   cdkContext;
--6151 0003e8fa3ec401001b0 Page 3 of pgpZDeflate.c
e0af5a
b29bda #ifndef DYN_ALLOC
c4ec0c ¤   PGPByte window[2L*WSIZE];
781f1d ¤   /* Sliding window. ·Input bytes are read into the second half of
b25af0 ¤   ·* the window, and move to the first half later to keep a
058800 ¤   ·* dictionary of at least WSIZE bytes. ·With this organization,
b96fce ¤   ·* matches are limited to a distance of WSIZE-MAX_MATCH bytes, but
3be81e ¤   ·* this ensures that IO is always performed with a length multiple
4b31b1 ¤   ·* of the block size. ·Also, it limits the window size to 64K,
96f5c3 ¤   ·* which is quite useful on MSDOS. ·To do: limit the window size
614963 ¤   ·* to WSIZE+BSZ if SMALL_MEM (the code would be less efficient
e1185f ¤   ·* since the data would have to be copied WSIZE/BSZ times)
b1a4e3 ¤   ·*/
0677eb ¤   Pos prev[WSIZE];
fe75f8 ¤   /* Link to older string with same hash index. To limit the size of this
2c2015 ¤   ·* array to 64K, this link is maintained only for the last 32K strings.
a75fce ¤   ·* An index in this array is thus a window index modulo 32K.
37a4e3 ¤   ·*/
b99aa9 ¤   Pos head[HASH_SIZE];
545fdc ¤   /* Heads of the hash chains or NIL. If your compiler thinks that
96c9c1 ¤   ·* HASH_SIZE is a dynamic value, recompile with -DDYN_ALLOC.
c3a4e3 ¤   ·*/
43db21 #else
72d8af ¤   /*
ffea8f ¤   ·* MS-DOS adjusts the pointers for zero offset, so we store the
474050 ¤   ·* original pointers in these variables for later free()ing
5ca4e3 ¤   ·*/
b55ef4 ¤   PGPByte * near o_window;
6c3cf3 ¤   Pos ·* near o_prev;
279946 ¤   Pos ·* near o_head;
c79671 ¤   PGPByte * near window;
027be4 ¤   Pos ·* near prev;
02de51 ¤   Pos ·* near head;
357454 #endif
7faf5a
9590d6 ¤   PGPUInt32 window_size;
127ac6 ¤   /* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
cf1705 ¤   ·* input file length plus MIN_LOOKAHEAD.
faa4e3 ¤   ·*/
f8af5a
cd7165 ¤   long block_start;
253ec6 ¤   /* window position at the beginning of the current output block. Gets
0e73b8 ¤   ·* negative when the window is moved backwards.
f8a4e3 ¤   ·*/
d5af5a
8ecf89 ¤   unsigned ins_h; ·/* hash index of string to be inserted */
5e4e21 ¤   unsigned int near prev_length;
ce2fb2 ¤   /* Length of the best match at previous step. Matches not greater than this
d733c4 ¤   ·* are discarded. This is used in the lazy match evaluation.
91a4e3 ¤   ·*/
b2af5a
4454da ¤   unsigned near strstart; ········/* start of string to insert */
b71755 ¤   unsigned near match_start; ·····/* start of matching string */
0145ff ¤   int ··········eofile; ···/* flag set at end of input file */
567f4d ¤   unsigned ·····lookahead; /* number of valid bytes ahead in window */
c1af5a
2eb29b ¤   /* Saved copies of lazy match variables */
61082f ¤   int s_match_available;
4bc245 ¤   int s_match_length;
5daf5a
e13155 ¤   unsigned near max_chain_length;
092e02 ¤   /* To speed up deflation, hash chains are never searched beyond
8c04bd ¤   ·* this length. ·A higher limit improves compression ratio but
93f77b ¤   ·* degrades the speed.
74a4e3 ¤   ·*/
4baf5a
d75b8c ¤   unsigned int max_lazy_match;
30f155 ¤   /* Attempt to find a better match only when the current match is strictly
3f9f6e ¤   ·* smaller than this value. This mechanism is used only for compression
730397 ¤   ·* levels >= 4.
b5a4e3 ¤   ·*/
3ea4bc #define max_insert_length ·max_lazy_match
--7d82 000f621f53a401001b0 Page 4 of pgpZDeflate.c
a06ded ¤   /* Insert new strings in the hash table only if the match length
4c75f3 ¤   ·* is not greater than this length. This saves time but degrades
f669f7 ¤   ·* compression. ·max_insert_length is used only for compression
ad87c4 ¤   ·* levels <= 3.
eba4e3 ¤   ·*/
40af5a
20f565 ¤   unsigned near good_match;
c96ba2 ¤   /* Use a faster search when the previous match is longer than this */
ecaf5a
8cc7be #ifdef ·FULL_SEARCH
4a3a49 # define nice_match MAX_MATCH
65db21 #else
a267d9 ¤   ··int near nice_match; /* Stop searching when current match exceeds this */
567454 #endif
dfaf5a
36c917 ¤   /*¤ DEBUG_STRUCT_CONSTRUCTOR( ZDeflateContext ) */
73704b } ZDeflateContext;
2aaf5a
80af5a
25338d #define H_SHIFT ·((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
5031e9 /* Number of bits by which ins_h and del_h must be shifted at each
5af296 ·* input step. It must be such that after MIN_MATCH steps, the oldest
b2dec0 ·* byte no longer takes part in the hash key, that is:
ad36e6 ·* ··H_SHIFT * MIN_MATCH >= HASH_BITS
f0495d ·*/
b1af5a
37af5a
9ea24c /* Values for max_lazy_match, good_match and max_chain_length, depending on
f81e13 ·* the desired pack level (0..9). The values given below have been tuned to
cf3d93 ·* exclude worst case performance for pathological files. Better values may be
c47ac6 ·* found for specific files.
44495d ·*/
b9af5a
3a08a9 static const struct {
5a32f2 ···PGPUInt16 good_length; /* reduce lazy search above this match length */
6309fc ···PGPUInt16 max_lazy;/* don't perform lazy search above this match length */
b47bb7 ···PGPUInt16 nice_length; /* quit search above this match length */
6ab667 ···PGPUInt16 max_chain;
e8f27f } configuration_table[10] = {
bb6c41 /* ·····good lazy nice chain */
83cb45 /* 0 */ {0, ···0, ·0, ···0},¤   /* store only */
27a6ff /* 1 */ {4, ···4, ·8, ···4},¤   /* maximum speed, no lazy matches */
2e1f07 /* 2 */ {4, ···5, 16, ···8},
f1313c /* 3 */ {4, ···6, 32, ··32},
16af5a
aa2a81 /* 4 */ {4, ···4, 16, ··16},¤   /* lazy matches */
cab177 #if 0
3e720c /* 5 */ {8, ··16, 32, ··32},¤   /* Change to new? */
77db21 #else
8d82d9 ¤   {8, ··64, 258, 128},¤   /* Match old PGP params */
e13199 #endif·
729775 /* 6 */ {8, ··16, 128, 128},
c5ab2b /* 7 */ {8, ··32, 128, 256},
94932b /* 8 */ {32, 128, 258, 1024},
7a2a5c /* 9 */ {32, 258, 258, 4096}};¤ /* maximum compression */
0baf5a
877c80 /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
024e2b ·* For deflate_fast() (levels <= 3) good is ignored and lazy has a different
96ce6c ·* meaning.
25495d ·*/
abaf5a
5bda25 /* ===========================================================================
fc55fb ·* ·Prototypes for local functions.
ff495d ·*/
f6af5a
d40de4 static void slide_window(ZDeflateContext *);
2d57e4 static int deflate_sub(ZDeflateContext *, struct ZTreesContext *,
f6205b ¤   struct ZBitsContext *);
3baf5a
8d9d6b int ·longest_match(ZDeflateContext *, IPos cur_match);
7287c8 #ifdef ASMV
f658db void match_init(void); /* asm code initialization */
--532d 000d82fc9a0401001b0 Page 5 of pgpZDeflate.c
a07454 #endif
e0af5a
c63e0f #ifdef ZIPDEBUG
ef7187 static void check_match(ZDeflateContext *, IPos start, IPos match, int length);
9d7454 #endif
b6af5a
24da25 /* ===========================================================================
f7eb29 ·* Update a hash value with the given input byte
6e4f2d ·* IN ·assertion: all calls to to UPDATE_HASH are made with consecutive
02632d ·* ···input characters, so that a running hash key can be computed from the
9c8d96 ·* ···previous key instead of complete recalculation each time.
cd495d ·*/
75132b #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
78af5a
77da25 /* ===========================================================================
193043 ·* Insert string s in the dictionary and set match_head to the previous head
a1e9de ·* of the hash chain (the most recent string with same hash key). Return
6ce7d8 ·* the previous length of the hash chain.
e42568 ·* IN ·assertion: all calls to to INSERT_STRING are made with consecutive
e9c5a7 ·* ···input characters and the first MIN_MATCH bytes of s are valid
7f0e1d ·* ···(except for the last MIN_MATCH-1 bytes of the input file).
80495d ·*/
6fd135 #define INSERT_STRING(ctx, s, match_head) \
2d91ad ··(UPDATE_HASH((ctx)->ins_h, (ctx)->window[(s) + MIN_MATCH-1]), \
b80faf ··(ctx)->prev[(s) & WMASK] = (Pos)((match_head) = (ctx)->head[(ctx)->ins_h]), \
de90f0 ··(ctx)->head[(ctx)->ins_h] = (Pos)(s))
a6af5a
32da25 /* ===========================================================================
4facaf ·* Initialize the "longest match" routines for a new file
03775e ·*
edd29b ·* IN assertion: window_size is > 0 if the input file is already read or
f48f70 ·* ···mmap'ed in the window[] array, 0 otherwise. In the first case,
a45b9e ·* ···window_size is sufficient to contain the whole input file plus
a6ce07 ·* ···MIN_LOOKAHEAD bytes (to avoid referencing memory beyond the end
55c084 ·* ···of window[] when looking for matches towards the end).
b7495d ·*/
589c04 ZDeflateContext *
e9e52e lm_init(PGPContextRef cdkContext, int pack_level)
dbb32d ¤   /* 0: store, 1: best speed, 9: best compression */
03bb36 {
dcfab7 ¤   ZDeflateContext *ctx;
adaf5a
e0c702 ····if (pack_level < 1 || pack_level > 9)
a87ed2 ¤   ¤   return NULL;
fcda82 ¤   /* error("bad pack level"); */
7eaf5a
4e2b48 ¤   ctx = (ZDeflateContext *) pgpContextMemAlloc (cdkContext,·
0444c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(*ctx), kPGPMemoryMgrFlags_Clear);
fe8b42 ¤   if (IsNull (ctx) )
747ed2 ¤   ¤   return NULL;
388b52 ¤   ctx->cdkContext = cdkContext;
2caf5a
62b64b ····/* Do not slide the window if the whole input is already in memory
97c1b9 ·····* (window_size > 0)
0fd48d ·····*/
0884b5 ····if (ctx->window_size == 0)
be3e43 ¤   ¤   ctx->window_size = (PGPUInt32)2*WSIZE;
82af5a
b61f53 ····/* Use dynamic allocation if compiler does not like big static arrays: */
188652 ····/* The +8 is for MS-DOS, so the pointers can be segment-aligned */
ac4ffa #ifdef DYN_ALLOC
21fe42 ¤   pgpAssert (ctx->o_window == NULL);
d450c6 ¤   ctx->window = ctx->o_window = (PGPByte *)pgpContextMemAlloc (cdkContext,
212439 ¤   ¤   ¤   ¤   ¤   ¤   (WSIZE+8)*2*sizeof(PGPByte), kPGPMemoryMgrFlags_Clear);
80c115 ¤   if (ctx->o_window == NULL) {
1610a7 ¤   ¤   pgpContextMemFree (cdkContext, ctx);
847ed2 ¤   ¤   return NULL;
c7e2d4 ¤   ¤   /* err(ZE_MEM, "window allocation"); */
5b9371 ¤   }
e869e6 ¤   pgpAssert (ctx->o_prev == NULL);
b1844d ¤   ctx->prev = ctx->o_prev = (Pos*) pgpContextMemAlloc (cdkContext,
d82568 ¤   ¤   ¤   ¤   (WSIZE+8) * sizeof(Pos), kPGPMemoryMgrFlags_Clear);
--faa4 000f50fcb3f401001b0 Page 6 of pgpZDeflate.c
6f91ec ¤   ctx->head = ctx->o_head = (Pos*) pgpContextMemAlloc (cdkContext,
d54438 ¤   ¤   ¤   ¤   (HASH_SIZE+8) * sizeof(Pos), kPGPMemoryMgrFlags_Clear);
ca559c ¤   if (ctx->o_prev == NULL || ctx->o_head == NULL) {
f75d48 ¤   ¤   if (ctx->o_prev)
8a3d27 ¤   ¤   ¤   pgpContextMemFree (cdkContext, ctx->o_prev);
8dc0c2 ¤   ¤   pgpContextMemFree (cdkContext, ctx->o_window);
7b10a7 ¤   ¤   pgpContextMemFree (cdkContext, ctx);
027ed2 ¤   ¤   return NULL;
f48b2a ¤   ¤   /* err(ZE_MEM, "hash table allocation"); */
d69371 ¤   }
fbf0e1 #endif /* DYN_ALLOC */
59af5a
96257e ····/* Initialize the hash table (avoiding 64K overflow for 16 bit systems).
b35e4a ·····* prev[] will be initialized on the fly.
88d48d ·····*/
edae2b ····ctx->head[HASH_SIZE-1] = NIL;
901b57 ····pgpClearMemory((char*)ctx->head, (unsigned)(HASH_SIZE-1)*
f0f934 ¤   ¤   ¤   ¤   ···¤¤   ¤   ¤   ¤   sizeof(*ctx->head));
30af5a
efea0f ····/* Set the default configuration parameters:
63d48d ·····*/
c66a92 ····ctx->max_lazy_match ··= configuration_table[pack_level].max_lazy;
25ff88 ····ctx->good_match ······= configuration_table[pack_level].good_length;
b4f885 #ifndef FULL_SEARCH
ab3a00 ····ctx->nice_match ······= configuration_table[pack_level].nice_length;
927454 #endif
9d5c2a ····ctx->max_chain_length = configuration_table[pack_level].max_chain;
a855ac ····/* ??? reduce max_chain_length for binary files */
a9af5a
79a798 ····ctx->strstart = 0;
e85e43 ····ctx->block_start = 0L;
7487c8 #ifdef ASMV
7eb6bc ····match_init(ctx); /* initialize the asm code */
bc7454 #endif
c5af5a
30c2c4 ····ctx->lookahead = 0;
fd39a2 ····ctx->eofile = 0;
2eaf5a
0cdcbe ····ctx->s_match_available = 0; /* set if previous match exists */
8e9514 ····ctx->s_match_length = MIN_MATCH-1; /* length of best match */
7daf5a
89af90 ····return ctx;
b7efe6 }
e5af5a
beda25 /* ===========================================================================
cd0e37 ·* Free the window and hash table
bb495d ·*/
cf314a void
261699 lm_free(ZDeflateContext *ctx)
57bb36 {
242560 ¤   PGPContextRef cdkContext;
9baf5a
e5f0ec ¤   cdkContext = ctx->cdkContext;
64af5a
1e4ffa #ifdef DYN_ALLOC
e42560 ¤   /* Wipe and free buffers */
bf3d84 ····if (ctx->o_window != NULL) {
fa41d1 ¤   ¤   pgpClearMemory(ctx->o_window, (WSIZE+8)*2*sizeof(PGPByte));
98c0c2 ¤   ¤   pgpContextMemFree (cdkContext, ctx->o_window);
756fe7 ····}
95bf4b ····if (ctx->o_prev != NULL) {
848cbc ¤   ¤   pgpClearMemory(ctx->o_prev, (WSIZE+8) * sizeof(Pos));
b990d8 ¤   ¤   pgpClearMemory(ctx->o_head, (HASH_SIZE+8) * sizeof(Pos));
755214 ¤   ¤   pgpContextMemFree (cdkContext, ctx->o_prev);
beb097 ¤   ¤   pgpContextMemFree (cdkContext, ctx->o_head);
7c6fe7 ····}
13f0e1 #endif /* DYN_ALLOC */
4faf5a
085ca0 ¤   /* Wipe everything else */
984c25 ¤   pgpClearMemory (ctx, sizeof(*ctx));
0f161f ¤   pgpContextMemFree (cdkContext, ctx);
f5efe6 }
--b670 000256bb0e0401001b0 Page 7 of pgpZDeflate.c
e0af5a
ebda25 /* ===========================================================================
7e0e5e ·* Set match_start to the longest match starting at the given string and
c994b1 ·* return its length. Matches shorter or equal to prev_length are discarded,
05e9ce ·* in which case the result is equal to prev_length and match_start is
f4062a ·* garbage.
a204a2 ·* IN assertions: cur_match is the head of the hash chain for the current
017891 ·* ··string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
bd495d ·*/
0f16cd #ifndef ASMV
aae7e2 /* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or
27ab85 ·* match.s. The code is functionally equivalent, so you can use the C version
80b03a ·* if desired. ·A 68000 version is in amiga/match_68.a -- this could be used
a42818 ·* with other 68000 based systems such as Macintosh with a little effort.
a2495d ·*/
854d2f int
5dfacd longest_match(ZDeflateContext *ctx, IPos cur_match)
cbbb36 {
1efbbf ····unsigned chain_length = ctx->max_chain_length; /* max hash chain length */
060976 ····register PGPByte *scan = ctx->window + ctx->strstart; /* current string */
37acfb ····register PGPByte *match; ···················/* matched string */
0db60f ····register int len; ··························/* length of current match */
2a5d2c ····int best_len = ctx->prev_length; ···········/* best match length so far */
169029 ····IPos limit = ctx->strstart > (IPos)MAX_DIST ?
5b0e65 ¤   ¤   ¤   ¤   ¤   ¤   ctx->strstart - (IPos)MAX_DIST : NIL;
9a1a45 ····/* Stop when cur_match becomes <= limit. ·To simplify the code,
e85dee ·····* we prevent matches with the string of window index 0.
fcd48d ·····*/
78af5a
0c84f7 /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
23492b ·* It is easy to get rid of this optimization if necessary.
25495d ·*/
748dda #if HASH_BITS < 8 || MAX_MATCH != 258
7610b0 # error Code too clever
497454 #endif
57af5a
6d399c #if UNALIGNED_OK
e0651a ····/* Compare two bytes at a time. Note: this is not always beneficial.
604cd0 ·····* Try with and without -DUNALIGNED_OK to check.
4fd48d ·····*/
876be3 ····register PGPByte *strend = ctx->window + ctx->strstart + MAX_MATCH - 1;
8ec9d2 ····register PGPUInt16 scan_start = *(PGPUInt16 *)scan;
95ede6 ····register PGPUInt16 scan_end ··= *(PGPUInt16 *)(scan+best_len-1);
3bdb21 #else
9554ee ····register PGPByte *strend = ctx->window + ctx->strstart + MAX_MATCH;
dd1010 ····register PGPByte scan_end1 ·= scan[best_len-1];
1be562 ····register PGPByte scan_end ··= scan[best_len];
097454 #endif
8baf5a
7b6f7d ····/* Do not waste too much time if we already have a good match: */
7329e0 ····if (ctx->prev_length >= ctx->good_match)
836a76 ········chain_length >>= 2;
06ae9a ····ZipAssert(ctx->strstart <= ctx->window_size-MIN_LOOKAHEAD,
cc26ce ¤   ¤   ¤   ··¤ "insufficient lookahead");
6baf5a
77c9a3 ····do {
ae5728 ¤   ¤   ZipAssert(cur_match < ctx->strstart, "no future");
42788b ¤   ¤   match = ctx->window + cur_match;
d6af5a
71aea0 ········/* Skip to next match if the match length cannot increase
07f464 ·········* or if the match length is less than 2:
6f9de3 ¤   ¤   ·*/
b24542 #if UNALIGNED_OK && MAX_MATCH == 258
d28a71 ¤   ¤   /* This code assumes sizeof(unsigned short) == 2. Do not use
dc9c07 ·········* UNALIGNED_OK if your compiler uses a different size.
d75af3 ·········*/
7ec7e8 ¤   ¤   if (*(PGPUInt16 *)(match+best_len-1) != scan_end ||
f765af ············*(PGPUInt16 *)match != scan_start) continue;
d2af5a
d646fa ········/* It is not necessary to compare scan[2] and match[2] since they are
151bec ¤   ¤   ·* always equal when the other bytes match, given that the hash keys
25da75 ·········* are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
--0684 000e36545e6401001b0 Page 8 of pgpZDeflate.c
92bedb ·········* strstart+3, +5, ... up to strstart+257. We check for insufficient
18c6a5 ¤   ¤   ·* lookahead only every 4th comparison; the 128th check will be made
17ed15 ¤   ¤   ·* at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
6a14bf ·········* necessary to put more guard bytes at the end of the window, or
fddf39 ·········* to check more often for insufficient lookahead.
ca5af3 ·········*/
83412c ········scan++, match++;
9a53d4 ········do {
6cf4ab ········} while (*(PGPUInt16 *)(scan+=2) == *(PGPUInt16 *)(match+=2) &&
80905b ¤   ¤   ¤   ¤   ·*(PGPUInt16 *)(scan+=2) == *(PGPUInt16 *)(match+=2) &&
310fd6 ·················*(PGPUInt16 *)(scan+=2) == *(PGPUInt16 *)(match+=2) &&
880fd6 ·················*(PGPUInt16 *)(scan+=2) == *(PGPUInt16 *)(match+=2) &&
fd83a8 ·················scan < strend);
1d915d ········/* The funny "do {}" generates better code on most compilers */
efaf5a
56b6c0 ········/* Here, scan <= window+strstart+257 */
b88ce2 ········ZipAssert(scan <= ctx->window+(unsigned)(ctx->window_size-1),
093b14 ¤   ¤   ¤   ¤   ··"wild scan");
94d26a ········if (*scan == *match)
ad619b ¤   ¤   ¤   scan++;
6eaf5a
ffa859 ¤   ¤   len = (MAX_MATCH - 1) - (int)(strend-scan);
55bcaf ¤   ¤   scan = strend - (MAX_MATCH-1);
30af5a
f11401 #else /* UNALIGNED_OK */
16af5a
608a3d ········if (match[best_len] ··!= scan_end ·||
d13855 ¤   ¤   ¤   match[best_len-1] != scan_end1 ||
bff9a3 ············*match ···········!= *scan ····||
953787 ············*++match ·········!= scan[1]) ·····continue;
a5af5a
1dd0a5 ········/* The check at best_len-1 can be removed because it will be made
5d24e8 ·········* again later. (This heuristic is not always a win.)
3d2a31 ·········* It is not necessary to compare scan[2] and match[2] since they
9fefa8 ¤   ¤   ·* are always equal when the other bytes match, given that
85af2b ·········* the hash keys are equal and that HASH_BITS >= 8.
925af3 ·········*/
320b03 ········scan += 2, match++;
60af5a
2d1d19 ········/* We check for insufficient lookahead only every 8th comparison;
ad5dfe ·········* the 256th check will be made at strstart+258.
5c5af3 ·········*/
b453d4 ········do {
24c9b4 ········} while (*++scan == *++match && *++scan == *++match &&
dfead7 ·················*++scan == *++match && *++scan == *++match &&
fd8e68 ¤   ¤   ¤   ¤   ·*++scan == *++match && *++scan == *++match &&
c1ead7 ·················*++scan == *++match && *++scan == *++match &&
2e83a8 ·················scan < strend);
73af5a
984a8b ········len = MAX_MATCH - (int)(strend - scan);
a868f9 ········scan = strend - MAX_MATCH;
c1af5a
02cab8 #endif /* UNALIGNED_OK */
71af5a
35ebdd ¤   ¤   if (len > best_len) {
2d5e7f ¤   ¤   ¤   ctx->match_start = cur_match;
a4e361 ¤   ¤   ¤   best_len = len;
a33be5 ¤   ¤   ¤   if (len >= ctx->nice_match)
95f622 ¤   ¤   ¤   ¤   break;
d1399c #if UNALIGNED_OK
855dcd ¤   ¤   ¤   scan_end = *(PGPUInt16 *)(scan+best_len-1);
c3db21 #else
f09e2d ¤   ¤   ¤   scan_end1 ·= scan[best_len-1];
8ff964 ¤   ¤   ¤   scan_end ··= scan[best_len];
297454 #endif
fb0fe4 ¤   ¤   }
b9ce86 ····} while ((cur_match = ctx->prev[cur_match & WMASK]) > limit
da4bdd ·············&& --chain_length != 0);
11af5a
cc54d1 ····return best_len;
50efe6 }
e37d77 #endif /* ASMV */
--8ffb 000f6181dc6401001b0 Page 9 of pgpZDeflate.c
e0af5a
373e0f #ifdef ZIPDEBUG
a8da25 /* ===========================================================================
f93ce4 ·* Check that the match at match_start is indeed a match.
25495d ·*/
ef2978 static void
93a811 check_match(ZDeflateContext *ctx, IPos start, IPos match, int length)
11bb36 {
55ddbc ····/* check that the match is indeed a match */
328560 ····if (memcmp(ctx->window + match, ctx->window + start, length) != 0) {
5b5324 ········fprintf(stderr, " start %d, match %d, length %d\n",
11adad ················start, match, length);
f62ee2 ········error("invalid match");
766fe7 ····}
f24c87 ····if (ctx->verbose > 1) {
8b5f12 ¤   ¤   fprintf(stderr,"\\[%d,%d]", start-match, length);
473922 ¤   ¤   do { putc(ctx->window[start++], stderr); } while (--length != 0);
0b6fe7 ····}
6eefe6 }
cfdb21 #else
fc4d58 # ·define check_match(ctx, start, match, length)
877454 #endif
1caf5a
8d2978 static void
54cfc9 slide_window(ZDeflateContext *ctx)
11bb36 {
b479ac ····register unsigned n, m;
e5af5a
08b1d9 ····memcpy(ctx->window, ctx->window+WSIZE, (size_t)WSIZE);
96eb89 ····ctx->match_start -= WSIZE;
b4ba3c ····ctx->strstart ···-= WSIZE; /* we now have strstart >= MAX_DIST: */
10af5a
3e8a3e ····ctx->block_start -= (long) WSIZE;
feaf5a
76df28 ····for (n = 0; n < HASH_SIZE; n++) {
855232 ¤   ¤   m = ctx->head[n];
79c9ed ¤   ¤   ctx->head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
cc6fe7 ····}
5a82fc ····for (n = 0; n < WSIZE; n++) {
8e308a ¤   ¤   m = ctx->prev[n];
cb569b ¤   ¤   ctx->prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
1a498d ¤   ¤   /* If n is not on any hash chain, prev[n] is garbage but
bf048d ¤   ¤   ·* its value will never be used.
aa9de3 ¤   ¤   ·*/
596fe7 ····}
a2efe6 }
fcaf5a
35da25 /* ===========================================================================
c37695 ·* Flush the current block, with given end-of-file flag.
21b9d3 ·* IN assertion: strstart is set to the end of the current match.
cc495d ·*/
4e8403 #define FLUSH_BLOCK(ctx, ztctx, zbctx, eof) \
423a89 ···flush_block((ztctx), (zbctx), (ctx)->block_start >= 0L ? \
3e0be6 ¤   ¤   (char*)&(ctx)->window[(unsigned)(ctx)->block_start] : \
20cb75 ¤   ¤   (char*)NULL, (PGPUInt32)(ctx)->strstart - (ctx)->block_start, (eof), \
0f675a ¤   ¤   (ctx)->window)
c5af5a
9fda25 /* ===========================================================================
2ede6d ·* Same as above, but achieves better compression. We use a lazy
fc617f ·* evaluation for matches: a match is finally adopted only if there is
da7d6f ·* no better match at the next window position.
30495d ·*/
1bbeb7 static int
51d70c deflate_sub(ZDeflateContext *ctx, struct ZTreesContext *ztcontext,
7248d7 ¤   struct ZBitsContext *zbcontext)
76bb36 {
a7dece ····IPos hash_head; ·········/* head of hash chain */
985bb3 ····IPos prev_match; ········/* previous match */
9d3b0d ····int flush; ··············/* set if current block must be flushed */
9a1fff ····int match_available = 0; /* set if previous match exists */
a16693 ····register unsigned match_length = MIN_MATCH-1; /* length of best match */
f6af5a
--6d33 000b38a3d2b401001b0 Page 10 of pgpZDeflate.c
0cb177 #if 0
2c9026 ····if (ctx->level <= 3) return deflate_fast(ctx); /* optimized for speed */
777454 #endif
3faf5a
be14dd ····match_available = ctx->s_match_available;
80217e ····match_length = ctx->s_match_length;
79af5a
aa26ca ····/* Process the input block. */
0b40c3 ····while (ctx->lookahead != 0) {
7ccbdf ········/* Insert the string window[strstart .. strstart+2] in the
baf63f ·········* dictionary, and set hash_head to the head of the hash chain:
955af3 ·········*/
d7cb8c ········INSERT_STRING(ctx, ctx->strstart, hash_head);
bcaf5a
f4a937 ¤   ¤   /* Find the longest match, discarding those <= prev_length.
d39de3 ¤   ¤   ·*/
58f909 ¤   ¤   ctx->prev_length = match_length, prev_match = ctx->match_start;
897626 ········match_length = MIN_MATCH-1;
a4af5a
9a13b2 ········if (hash_head != NIL && ctx->prev_length < ctx->max_lazy_match &&
c28e0b ¤   ¤   ¤   ctx->strstart - hash_head <= MAX_DIST) {
d1ee53 ············/* To simplify the code, we prevent matches with the string
daef3d ·············* of window index 0 (in particular we have to avoid a match
e5eab9 ¤   ¤   ¤   ·* of the string with itself at the start of the input file).
b1b203 ·············*/
6fc888 ············match_length = longest_match (ctx, hash_head);
51373e ············/* longest_match() sets match_start */
fbfbda ············if (match_length > ctx->lookahead) match_length = ctx->lookahead;
1baf5a
547b4b ············/* Ignore a length 3 match if it is too distant: */
5b1581 ············if (match_length == MIN_MATCH &&
f745c0 ¤   ¤   ¤   ¤   ctx->strstart-ctx->match_start > TOO_FAR){
37e39d ················/* If prev_match is also MIN_MATCH, match_start is garbage
528e14 ·················* but we will ignore the current match anyway.
1a1020 ¤   ¤   ¤   ¤   ·*/
fd229e ¤   ¤   ¤   ¤   match_length--;
42a3a6 ¤   ¤   ¤   }
bd7fb0 ········}
f30749 ········/* If there was a match at the previous step and the current
4b4c3c ·········* match is not better, output the previous match:
ae5af3 ·········*/
f85d56 ¤   ¤   if (ctx->prev_length >= MIN_MATCH &&
0ea61a ¤   ¤   ¤   match_length <= ctx->prev_length) {
33af5a
54461d ············check_match(ctx, ctx->strstart-1, prev_match, ctx->prev_length);
12af5a
3f5248 ············flush = ct_tally(ztcontext, ctx->strstart-1-prev_match,
0265e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·ctx->prev_length - MIN_MATCH,
af5284 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·ctx->block_start, ctx->strstart);
1faf5a
021cff ············/* Insert in hash table all strings up to the end of the match.
dcda47 ·············* strstart-1 and strstart are already inserted.
898753 ¤   ¤   ¤   ·*/
86e10d ············ctx->lookahead -= ctx->prev_length-1;
7a5fe3 ¤   ¤   ¤   ctx->prev_length -= 2;
76a4b3 ············do {
e09520 ················ctx->strstart++;
8e910b ················INSERT_STRING(ctx, ctx->strstart, hash_head);
b76c6a ¤   ¤   ¤   ¤   /* strstart never exceeds WSIZE-MAX_MATCH, so there are
a35f48 ·················* always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
e75a5a ·················* these bytes are garbage, but it does not matter since the
cfcf18 ¤   ¤   ¤   ¤   ·* next lookahead bytes will always be emitted as literals.
440a4b ·················*/
881e90 ············} while (--ctx->prev_length != 0);
65f710 ············match_available = 0;
f11c4a ············match_length = MIN_MATCH-1;
4f415d ············ctx->strstart++;
03c4f1 ············if (flush) {
8e2274 ¤   ¤   ¤   ¤   FLUSH_BLOCK(ctx, ztcontext, zbcontext, 0);
30a6c4 ¤   ¤   ¤   ¤   ctx->block_start = ctx->strstart;
eca3a6 ¤   ¤   ¤   }
b3af5a
--19f5 0001822b3b7401001b0 Page 11 of pgpZDeflate.c
14fe57 ········} else if (match_available) {
f79b6a ¤   ¤   ¤   /* If there was no match at the previous position, output a
6a261f ·············* single literal. If there was a match but the current match
ffac68 ¤   ¤   ¤   ·* is longer, truncate the previous match to a single literal.
c4b203 ·············*/
c5c294 ············Tracevv((stderr,"%c",ctx->window[ctx->strstart-1]));
f55895 ············if (ct_tally (ztcontext, 0, ctx->window[ctx->strstart-1],
baa687 ¤   ¤   ¤   ¤   ¤   ¤   ··ctx->block_start, ctx->strstart)) {
e25a41 ················FLUSH_BLOCK(ctx, ztcontext, zbcontext, 0);
e2a6c4 ¤   ¤   ¤   ¤   ctx->block_start = ctx->strstart;
cc7812 ············}
a9c697 ¤   ¤   ¤   ctx->strstart++;
b9dcc0 ¤   ¤   ¤   ctx->lookahead--;
1d9d1e ········} else {
ec694f ············/* There is no previous match to compare with, wait for
fb7e4b ·············* the next step to decide.
7bb203 ·············*/
e1ca52 ¤   ¤   ¤   match_available = 1;
4bc697 ¤   ¤   ¤   ctx->strstart++;
2fdcc0 ¤   ¤   ¤   ctx->lookahead--;
0d0fe4 ¤   ¤   }
69af5a
ca443b ¤   ¤   /* Make sure that we always have enough lookahead, except
bd4aca ¤   ¤   ·* at the end of the input file. We need MAX_MATCH bytes
8d961a ¤   ¤   ·* for the next match, plus MIN_MATCH bytes to insert the
1f8a1f ¤   ¤   ·* string following the next match.
369de3 ¤   ¤   ·*/
0b7f00 ¤   ¤   if (ctx->lookahead < MIN_LOOKAHEAD && !ctx->eofile) {
9cbe03 ¤   ¤   ¤   ctx->s_match_available = match_available;
40f3e2 ¤   ¤   ¤   ctx->s_match_length = match_length;
e78144 ¤   ¤   ¤   return 0;
a1f850 ¤   ¤   ¤   /* fill_window();*/
9a0fe4 ¤   ¤   }
b16fe7 ····}
53f2e1 ····if (match_available) ct_tally (ztcontext, 0, ctx->window[ctx->strstart-1],
27d02e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···ctx->block_start, ctx->strstart);
61af5a
c8406f ····return FLUSH_BLOCK(ctx, ztcontext, zbcontext, 1); /* eof */
c7efe6 }
b3af5a
08af5a
a9f04f /* Zip a buffer of input */
23314a void
0cd19c zip_input(ZDeflateContext *ctx, struct ZTreesContext *ztcontext,
4f32ac ¤   struct ZBitsContext *zbcontext, char const *buf, unsigned len)
aabb36 {
3c24e0 ····unsigned more;
2caf5a
e51751 ····while (len) {
ca7860 ¤   ¤   more = (unsigned)((PGPUInt32)2*WSIZE - ctx->lookahead - ctx->strstart);
1baf5a
1e7199 ¤   ¤   if (more <= 1) {
47c876 ¤   ¤   ¤   slide_window(ctx);
999cc3 ¤   ¤   ¤   more += WSIZE;
560fe4 ¤   ¤   }
ba6001 ¤   ¤   if (more > len)
6624d8 ¤   ¤   ¤   more = len;
176829 ¤   ¤   memcpy(ctx->window+ctx->strstart+ctx->lookahead, buf, more);
9b19d2 ¤   ¤   ctx->lookahead += more;
faaf5a
4f0ea2 ¤   ¤   if (ctx->lookahead >= MIN_LOOKAHEAD) {
b096c3 ¤   ¤   ¤   if (!ctx->strstart) {¤  /* First time */
792b2d ¤   ¤   ¤   ¤   register int j;
f66426 ¤   ¤   ¤   ¤   ctx->ins_h = 0;
7853f8 ¤   ¤   ¤   ¤   for (j=0; j<MIN_MATCH-1; j++)
6a7636 ¤   ¤   ¤   ¤   ¤   UPDATE_HASH(ctx->ins_h, ctx->window[j]);
94a3a6 ¤   ¤   ¤   }
09107a ¤   ¤   ¤   deflate_sub(ctx, ztcontext, zbcontext);
767fb0 ········}
600747 ¤   ¤   buf += more;
a43aac ¤   ¤   len -= more;
186fe7 ····}
--c9c8 0010488b08a401001b0 Page 12 of pgpZDeflate.c
e0af5a
c53471 ····return;
c4efe6 }
14af5a
d6cbbb /* Zip EOF */
5d314a void
d5ca53 zip_finish(ZDeflateContext *ctx, struct ZTreesContext *ztcontext,
1448d7 ¤   struct ZBitsContext *zbcontext)
d1bb36 {
1d637e ····ctx->eofile = 1;
8aaf5a
560234 ····if (!ctx->strstart) {¤  /* First time */
1b7016 ¤   ¤   register int j;
7f3f1d ¤   ¤   ctx->ins_h = 0;
e556d3 ¤   ¤   for (j=0; j<MIN_MATCH-1; j++)
b73fb0 ¤   ¤   ¤   UPDATE_HASH(ctx->ins_h, ctx->window[j]);
506fe7 ····}
4baf5a
bc6eea ····deflate_sub(ctx, ztcontext, zbcontext);
52af5a
253471 ····return;
04efe6 }
--e4cc 0004ed48440401001b1 Page 1 of pgpZMatch.asm
dcfd50 ;
754406 ; Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
5756e0 ; Permission is granted to any individual or institution to use, copy, or
513df7 ; redistribute this software so long as all of the original files are included
18e4a0 ; unmodified, that it is not sold for profit, and that this copyright notice
f5659e ; is retained.
e8fd50 ;
d913d0 ; match.asm by Jean-loup Gailly.
66fd50 ;
fb7393 ; $Id: pgpZMatch.asm,v 1.2 1997/05/09 20:20:36 lloyd Exp $
bbaf5a
958260 ; match.asm, optimized version of longest_match() in deflate.c
3ecb65 ; Must be assembled with masm -ml. To be used only with C large model.
432e5d ; (For compact model, follow the instructions given below.)
5b522e ; This file is only optional. If you don't have masm or tasm, use the
a9c387 ; C version (add -DNO_ASM to CFLAGS in makefile.msc and remove match.obj
7ba5f0 ; from OBJI). If you have reduced WSIZE in pgpZip.h, then change its value
87f0a2 ; below.
e0fd50 ;
fc54ac ; Turbo C 2.0 does not support static allocation of more than 64K bytes per
216678 ; file, and does not have SS == DS. So TC and BC++ users must use:
051a9b ; ··tasm -ml -DDYN_ALLOC -DSS_NEQ_DS match;
15fd50 ;
0b86e5 ; To simplify the code, the option -DDYN_ALLOC is supported for OS/2
b74be6 ; only if the arrays are guaranteed to have zero offset (allocated by
64bcd6 ; halloc). We also require SS==DS. This is satisfied for MSC but not Turbo C.
7eaf5a
bcda2d ········name ···match
c4af5a
e18812 ; define LCODE as follows:
b79e09 ; model: ·······compact large (small and medium not supported here)
095405 ; LCODE ··········0 ······1
e3af5a
9565f6 LCODE equ 1
c85c6f ; Better define them on the command line
1c03c5 DYN_ALLOC equ 1
f718f1 ;SS_NEQ_DS equ 1
6cc726 ; For Turbo C, define SS_NEQ_DS as 1, but for MSC you can leave it undefined.
79e033 ; The code is a little better when SS_NEQ_DS is not defined.
b0af5a
737fed ifndef DYN_ALLOC
2fe69f ········extrn ··_prev ········: word
33f456 ········extrn ··_window ······: PGPByte
5a37e0 ········prev ···equ ·_prev ···; offset part
c7e0de ········window ·equ ·_window
d0bfb9 endif
f6af5a
442884 _DATA ···segment ·word public 'DATA'
b0953c ········extrn ··_match_start ·: word
91dd9f ········extrn ··_prev_length ·: word
c3d1c9 ········extrn ··_good_match ··: word
f9db9a ········extrn ··_strstart ····: word
e791c9 ········extrn ··_max_chain_length : word
f56e29 ifdef DYN_ALLOC
10e69f ········extrn ··_prev ········: word
b8b794 ········extrn ··_window ······: word
a9b287 ········prev ···equ 0 ········; offset forced to zero
c6cd65 ········window ·equ 0
7edf98 ········window_seg equ _window[2]
ce6139 ¤   window_off equ 0
d4523c else
d06a93 ¤   wseg ···dw seg _window
a63f8c ········window_seg equ wseg
e6b8e0 ¤   window_off equ offset _window
5cbfb9 endif
1095ef _DATA ···ends
c8af5a
969e64 DGROUP ·group _DATA
80af5a
493748 if LCODE
1632d7 ¤   extrn ··_exit : far
4e523c else
--1acd 0007baf4429401001b1 Page 2 of pgpZMatch.asm
347163 ¤   extrn ··_exit : near
b3bfb9 endif
0caf5a
53b894 _TEXT ··segment word public 'CODE'
55eb37 ········assume ·cs: _TEXT, ds: DGROUP
5daf5a
1c57e3 ¤   public _match_init
b76c11 ········public _longest_match
0caf5a
b0c75b ¤   MIN_MATCH ····equ 3
4b1466 ········MAX_MATCH ····equ 258
86a204 ¤   WSIZE ········equ 8192¤ ¤   ; keep in sync with pgpZip.h !
89054c ¤   WMASK ········equ (WSIZE-1)
33fdf2 ¤   MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
739d69 ¤   MAX_DIST ·····equ (WSIZE-MIN_LOOKAHEAD)
75af5a
6d39d1 prev_ptr ···dw ·seg _prev¤  ¤   ; pointer to the prev array
f4eea6 ifdef SS_NEQ_DS
b0da65 ····match_start dw ·0¤  ¤   ¤   ; copy of _match_start if SS != DS
b8bfb9 endif
41af5a
ae8f40 ; initialize or check the variables used in match.asm.
f5af5a
fd3748 if LCODE
b87568 _match_init proc far
6e523c else
f83c58 _match_init proc near
a9bfb9 endif
d4eea6 ifdef SS_NEQ_DS
475c9a ········ma_start equ cs:match_start¤; does not work on OS/2
13523c else
476103 ¤   assume ss: DGROUP
0bc468 ········ma_start equ ss:_match_start
9c9afd ········mov ····ax,ds
c49f10 ········mov ····bx,ss
096b50 ········cmp ····ax,bx ··················; SS == DS?
9e6acf ········jne ····error
c7bfb9 endif
786e29 ifdef DYN_ALLOC
9e43b3 ¤   mov¤ax,_window[0]¤  ¤   ; force zero offset
e739ad ¤   add ····ax,15
07a34f ¤   mov ····cx,4
d609d3 ¤   shr ····ax,cl
5a4cf0 ¤   add ····_window[2],ax
2697e0 ¤   mov ····_window[0],0
8faf5a
83f6ed ¤   mov¤ax,_prev[0]¤¤   ; force zero offset
0339ad ¤   add ····ax,15
a0a34f ¤   mov ····cx,4
a909d3 ¤   shr ····ax,cl
378988 ¤   add ····_prev[2],ax
6655e7 ¤   mov ····_prev[0],0
22a5b8 ··ifdef SS_NEQ_DS
a7d0b7 ¤   mov¤ax,_prev[2]¤¤   ; segment value
3e2223 ¤   mov ····cs:prev_ptr,ax¤ ¤   ; ugly write to code, crash on OS/2
c0a61f ········prev_seg ·equ cs:prev_ptr
601bd0 ··else
8d5ef0 ········prev_seg ·equ ss:_prev[2]¤  ; works on OS/2 if SS == DS
479292 ··endif
79523c else
54a61f ········prev_seg ·equ cs:prev_ptr
a9bfb9 endif
c28a83 ¤   ret
0a6b55 error: ·call ···_exit
f7af5a
48dca8 _match_init endp
f4af5a
6aaf84 ; -----------------------------------------------------------------------
99cbdc ; Set match_start to the longest match starting at the given string and
fab38e ; return its length. Matches shorter or equal to prev_length are discarded,
03837c ; in which case the result is equal to prev_length and match_start is
7b30ce ; garbage.
--9174 000e49add69401001b1 Page 3 of pgpZMatch.asm
faa37d ; IN assertions: cur_match is the head of the hash chain for the current
b65fae ; ··string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
24af5a
36ba60 ; int longest_match(cur_match)
90af5a
e23748 if LCODE
b94cba _longest_match ·proc far
18523c else
01c9fe _longest_match ·proc near
08bfb9 endif
af0c45 ········push ···bp
8fef58 ········mov ····bp,sp
c39815 ········push ···di
1ad8c2 ¤   push¤   si
2db9b3 ¤   push¤   ds
0daf5a
e63748 if LCODE
e144ae ········cur_match ···equ word ptr [bp+6]
a8523c else
c2f116 ········cur_match ···equ word ptr [bp+4]
b3bfb9 endif
4f8d7e ; ······window¤ ·····equ es:window (es:0 for DYN_ALLOC)
d587a5 ; ······prev¤   ·····equ ds:prev
4b9857 ; ······match ·······equ es:si
626317 ; ······scan ········equ es:di
2d7f21 ; ······chain_length equ bp
8d98a0 ; ······best_len ····equ bx
3b0020 ; ······limit ·······equ dx
baaf5a
6c1c87 ¤   mov¤si,cur_match ···········; use bp before it is destroyed
2ee872 ········mov ····bp,_max_chain_length ···; chain_length = max_chain_length
f364d3 ¤   mov¤di,_strstart
b487de ¤   mov¤dx,di
6d5e80 ¤   sub¤dx,MAX_DIST ············; limit = strstart-MAX_DIST
e91e1d ¤   jae¤limit_ok
d8df70 ¤   sub¤dx,dx¤  ¤   ¤   ; limit = NIL
e9a23b limit_ok:
b2ec64 ········add ····di,2+window_off ········; di = offset(window + strstart + 2)
9b88be ········mov ····bx,_prev_length ········; best_len = prev_length
84a07a ¤   mov ····es,window_seg
d1355b ········mov ····ax,es:[bx+di-3] ········; ax = scan[best_len-1..best_len]
e75376 ········mov ····cx,es:[di-2] ···········; cx = scan[0..1]
11521c ¤   cmp¤bx,_good_match¤ ¤   ; do we have a good match already?
c9fa51 ········mov ····ds,prev_seg ···¤¤   ; (does not destroy the flags)
bf62a5 ········assume ·ds: nothing
831cc6 ········jb ·····do_scan¤¤   ¤   ; good match?
2ebb32 ¤   shr¤bp,1¤   ¤   ¤   ; chain_length >>= 2
1b3b12 ¤   shr¤bp,1
dc9426 ········jmp ····short do_scan
14af5a
9cab7a ········even ···························; align destination of branch
b7419e long_loop:
d6ffb9 ; at this point, ds:di == scan+2, ds:si == cur_match
1b9298 ········mov ····ax,[bx+di-3] ···········; ax = scan[best_len-1..best_len]
b9d8ca ········mov ····cx,[di-2] ··············; cx = scan[0..1]
e9c794 ········mov ····ds,prev_seg ···¤¤   ; reset ds to address the prev array
789f3e short_loop:
1eeb1a ········dec ····bp ·····················; --chain_length
2c1644 ········jz ·····the_end
5cd956 ; at this point, di == scan+2, si = cur_match,
e12bbd ; ax = scan[best_len-1..best_len] and cx = scan[0..1]
54e70c if (WSIZE-32768)
409c5e ········and ····si,WMASK
25bfb9 endif
8165bf ········shl ····si,1 ···················; cur_match as word index
965095 ········mov ····si,prev[si] ············; cur_match = prev[cur_match]
434414 ········cmp ····si,dx¤  ¤   ¤   ; cur_match <= limit ?
16afdf ········jbe ····the_end
cd26b5 do_scan:
569ebd ········cmp ····ax,word ptr es:window[bx+si-1] ; check match at best_len-1
d2f184 ········jne ····short_loop
e4a849 ········cmp ····cx,word ptr es:window[si] ·····; check min_match_length match
--cd1b 0010eec9e53401001b1 Page 4 of pgpZMatch.asm
9df184 ········jne ····short_loop
f1af5a
d48ee1 ········lea ····si,window[si+2] ········; si = match
881786 ········mov ····ax,di ··················; ax = scan+2
b4c877 ········mov ····cx,es
56766d ········mov ····ds,cx¤  ¤   ¤   ; ds = es = window
817e08 ········mov ····cx,(MAX_MATCH-2)/2 ·····; scan for at most MAX_MATCH bytes
0abea5 ········repe ···cmpsw ··················; loop until mismatch
e4cb5c ········je ·····maxmatch ···············; match of length MAX_MATCH?
288305 mismatch:
5e4c5f ········mov ····cl,[di-2] ··············; mismatch on first or second PGPByte?
9b5acb ········sub ····cl,[si-2] ··············; cl = 0 if first bytes equal
9e4685 ········xchg ···ax,di ··················; di = scan+2, ax = end of scan
453247 ········sub ····ax,di ··················; ax = len
75b006 ¤   sub¤si,ax¤  ¤   ¤   ; si = cur_match + 2 + offset(window)
939677 ¤   sub¤si,2+window_off ········; si = cur_match
a413cc ········sub ····cl,1 ···················; set carry if cl == 0 (can't use DEC)
c7d96c ········adc ····ax,0 ···················; ax = carry ? len+1 : len
b6440e ········cmp ····ax,bx ··················; len > best_len ?
c9c72a ········jle ····long_loop
db6955 ········mov ····ma_start,si ············; match_start = cur_match
9b0966 ········mov ····bx,ax ··················; bx = best_len = len
34890d ········cmp ····ax,MAX_MATCH ···········; len >= MAX_MATCH ?
4d9a0c ········jl ·····long_loop
7934bd the_end:
5bbe34 ¤   pop¤ds
f2b1b0 ········assume ·ds: DGROUP
e5eea6 ifdef SS_NEQ_DS
1ac6a0 ¤   mov¤ax,ma_start¤¤   ; garbage if no match found
c99548 ¤   mov¤ds:_match_start,ax
f8bfb9 endif
251836 ········pop ····si
c111a6 ········pop ····di
5885f6 ········pop ····bp
9e718a ········mov ····ax,bx ··················; result = ax = best_len
887493 ········ret
84a167 maxmatch: ······························; come here if maximum match
7e95c9 ········cmpsb ··························; increment si and di
879c80 ········jmp ····mismatch ···············; force match_length = MAX_LENGTH
1e508e ········
add44e _longest_match ·endp
b6af5a
781d30 _TEXT ··ends
0e4f8a end
--64db 000eac505cf401001b2 Page 1 of pgpZTailor.h
061676 /* tailor.h -- Not copyrighted 1991 Mark Adler */
8c38e5 /*
44e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
032979 ·* You should not be using these functions in an application.
07775e ·*
cb0346 ·* $Id: pgpZTailor.h,v 1.3 1997/11/06 20:00:21 lloyd Exp $
75495d ·*/
edaf5a
496756 #ifndef MSDOS
727108 # ·ifdef __MSDOS__
ec8784 # ···define MSDOS 1
6bbf38 # ·endif
e37454 #endif
6aaf5a
062f61 /* A couple of other compilers also behave like Turbo C */
f5136b #ifndef __TURBOC__
166b99 # ·ifdef __POWERC ················/* For Power C too */
8c9248 # ···define __TURBOC__
d5bf38 # ·endif
0d07fe # ·ifdef __BORLANDC__
d39248 # ···define __TURBOC__
e3bf38 # ·endif
8b7454 #endif
adaf5a
f138e5 /*
d3051b ·* We use MSDOS to signal a need for 16-bit kludges and all the near/far crap,
80a5be ·* so DJGPP basically isn't MSDOS.
af495d ·*/
f1d1d1 #ifdef __GNUC__
6c52db # ·undef ·MSDOS
0d7454 #endif
85af5a
5738e5 /*
63d649 ·* Likewise we don't need DOS kludges for 32 bit windows versions
c5495d ·*/
15eb0f #ifdef PGP_WIN32
dd52db # ·undef ·MSDOS
bf7454 #endif
f9af5a
5038e5 /*
453297 ·* Allow far and huge allocation for small model (Microsoft C or Turbo C)
1e5e5c ·* unless NOFAR defined (needed for ANSI mode compilations)
51050b ·* But if we're using DJGPP, and want to use the optimized 386 assembler
a2088d ·* zmatch routines, we can't use DYN_ALLOC. ·But gcc has virtual memory...
7d495d ·*/
6a306a #ifdef MSDOS
faaf5a
d1b867 # ·ifndef DYN_ALLOC
73eb68 # ···define DYN_ALLOC 1
42bf38 # ·endif
0a8e87 # ·define far ·__far
645f41 # ·define near __near
c8af5a
3af7d6 #else /* !MSDOS */
d4af5a
26fdb6 /* This used to do #define DYN_ALLOC 0, but since #ifdef DYN_ALLOC is used
967acd ·* everywhere the effect was to turn on dynamic allocation, which did not
766bdf ·* seem likely to be what was intended, because of the 0. ·So for now we
f09300 ·* will leave DYN_ALLOC in whatever defined or undefined state it has been
8f2837 ·* set in previously.
78495d ·*/
8baf5a
246b3b # ·define far
f75c58 # ·define near
0caf5a
ca65ea #endif /* !MSDOS */
f3af5a
cbbea3 #include <stdlib.h>
77af5a
e7b8d1 /* Define this symbol if your target allows access to unaligned data.
940d8d ·* This is not mandatory, just a speed optimization. The compressed
eaf7c8 ·* output is strictly identical.
--5292 0012217ee7c401001b2 Page 2 of pgpZTailor.h
47495d ·*/
b27f61 #ifndef UNALIGNED_OK
a04696 #if defined(MSDOS) || defined(M_XENIX) || defined(i386) || defined(__i386__)
f75803 # ·define UNALIGNED_OK 1
332266 #elif defined(mc68020) || defined(__mc68020__)
8f5803 # ·define UNALIGNED_OK 1
a4a5ca #elif defined(vax) || defined(__vax__)
305803 # ·define UNALIGNED_OK 1
99db21 #else
9041db # ·define UNALIGNED_OK 0
4d7454 #endif
7c7454 #endif
4daf5a
229e40 /* end of tailor.h */
--ecea 00034313132401001b3 Page 1 of pgpZTrees.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
fcd2f1 ¤   $Id: pgpZTrees.c,v 1.13.12.1 1998/11/12 03:21:26 heller Exp $
6cf7f7 ____________________________________________________________________________*/
73af5a
4a38e5 /*
554fec ·* Copyright (C) 1990-1993 Mark Adler, Richard B. Wales, Jean-loup Gailly,
11ab83 ·* Kai Uwe Rommel and Igor Mandrichenko.
be47d7 ·* Permission is granted to any individual or institution to use, copy,
62d9ba ·* or redistribute this software so long as all of the original files
ed7285 ·* are included, that it is not sold for profit, and that this copyright
8912f8 ·* notice is retained.
c2775e ·*
ca7a78 ·* $Id: pgpZTrees.c,v 1.13.12.1 1998/11/12 03:21:26 heller Exp $
fa495d ·*/
05d83c ·
2baf5a
3e38e5 /*
8c520c ·* ·trees.c by Jean-loup Gailly
ae775e ·*
a24dc6 ·* ·This is a new version of im_ctree.c originally written by Richard B. Wales
a41110 ·* ·for the defunct implosion method.
55775e ·*
04b0e2 ·* ·PURPOSE
9d775e ·*
14e0a5 ·* ·····Encode various sets of source values using variable-length
d5a582 ·* ·····binary code trees.
9b775e ·*
3fe174 ·* ·DISCUSSION
9e775e ·*
a863ed ·* ·····The PKZIP "deflation" process uses several Huffman trees. The more
89fb24 ·* ·····common source values are represented by shorter bit sequences.
5b775e ·*
946df1 ·* ·····Each code tree is stored in the ZIP file in a compressed form
9c7f9a ·* ·····which is itself a Huffman encoding of the lengths of
512dda ·* ·····all the code strings (in ascending order by source values).
dab134 ·* ·····The actual code strings are reconstructed from the lengths in
f27d84 ·* ·····the UNZIP process, as described in the "application note"
85cee9 ·* ·····(APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
92775e ·*
acf395 ·* ·REFERENCES
43775e ·*
97249d ·* ·····Lynch, Thomas J.
11d9df ·* ·········Data Compression: ·Techniques and Applications, pp. 53-55.
0e01bf ·* ·········Lifetime Learning Publications, 1985. ·ISBN 0-534-03418-7.
27775e ·*
56a35b ·* ·····Storer, James A.
14b8e3 ·* ·········Data Compression: ·Methods and Theory, pp. 49-50.
7db3b5 ·* ·········Computer Science Press, 1988. ·ISBN 0-7167-8156-5.
67775e ·*
0b801a ·* ·····Sedgewick, R.
865751 ·* ·········Algorithms, p290.
c9bdbe ·* ·········Addison-Wesley, 1983. ISBN 0-201-06672-6.
98775e ·*
c86c07 ·* ·INTERFACE
ef775e ·*
5f155c ·* ·····void ct_init (void))
59725e ·* ·········Allocate the match buffer and initialize the various tables.
c1775e ·*
a2abb5 ·* ·····void ct_tally (unsigned dist, unsigned lc);
9b4bda ·* ·········Save the match info and tally the frequency counts.
70775e ·*
29853b ·* ·····long flush_block (char const *buf, PGPUInt32 stored_len, int eof)
ad9018 ·* ·········Determine the best encoding for the current block: dynamic trees,
d7c165 ·* ·········static trees or store, and output the encoded block to the zip
2016b7 ·* ·········file. Returns the total compressed length for the file so far.
3c775e ·*
34495d ·*/
--26a3 000048d7839401001b3 Page 2 of pgpZTrees.c
e0af5a
64e2ff #include "pgpConfig.h"
0baf5a
edb1cb #include <ctype.h>
1b8619 #include "pgpZip.h"
29af5a
d6da25 /* ===========================================================================
bdd601 ·* Constants
0c495d ·*/
aeaf5a
aa57ca #define MAX_BITS 15
ef4046 /* All codes must not exceed MAX_BITS bits */
feaf5a
533d62 #define MAX_BL_BITS 7
acd4dc /* Bit length codes must not exceed MAX_BL_BITS bits */
34af5a
4b5494 #define LENGTH_CODES 29
036756 /* number of length codes, not counting the special END_BLOCK code */
c5af5a
6997c4 #define LITERALS ·256
3067af /* number of literal bytes 0..255 */
2caf5a
0e29df #define END_BLOCK 256
b8332d /* end of block literal code */
87af5a
aa61f5 #define L_CODES (LITERALS+1+LENGTH_CODES)
6c7c55 /* number of Literal or Length codes, including the END_BLOCK code */
feaf5a
b97346 #define D_CODES ··30
4dd28f /* number of distance codes */
f3af5a
d6d6f2 #define BL_CODES ·19
9b6d4c /* number of codes used to transfer the bit lengths */
0caf5a
41af5a
7b0462 /* extra bits for each length code */
d3afc0 static int const near extra_lbits[LENGTH_CODES]
46427f ···= {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};
1daf5a
7cb941 /* extra bits for each distance code */
f14ad0 static int const near extra_dbits[D_CODES]
db1df9 ···= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
f7af5a
46f745 /* extra bits for each bit length code */
3aa266 static int const near extra_blbits[BL_CODES]
a8bb6d ···= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
edaf5a
78195c static PGPByte const near bl_order[BL_CODES]
83e6f2 ···= {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
80fd83 /* The lengths of the bit length codes are sent in order of decreasing
b752c6 ·* probability, to avoid transmitting the lengths for unused bit length codes.
b1495d ·*/
91af5a
0eceda #define STORED_BLOCK 0
8e878d #define STATIC_TREES 1
239a35 #define DYN_TREES ···2
03f110 /* The three kinds of block type */
95af5a
ae4c1a #ifndef LIT_BUFSIZE
45f3b9 # ·ifdef SMALL_MEM
dcead7 # ···define LIT_BUFSIZE ·0x2000
fbd33c # ·else
f6fab0 # ···ifdef MEDIUM_MEM
b411cd # ·····define LIT_BUFSIZE ·0x4000
258e51 # ···else
4c66fd # ·····define LIT_BUFSIZE ·0x8000
ad0786 # ···endif
b6bf38 # ·endif
017454 #endif
0788ee #define DIST_BUFSIZE ·LIT_BUFSIZE
6458ba /* Sizes of match buffers for literals/lengths and distances. ·There are
04b2fa ·* 4 reasons for limiting LIT_BUFSIZE to < 64K:
--df2b 0001c2834ef401001b3 Page 3 of pgpZTrees.c
6adf67 ·* ··- frequencies can be kept in 16 bit counters
00b2f6 ·* ··- if compression is not successful for the first block, all input data is
6a4549 ·* ····still in the window so we can still emit a stored block even when input
064d1b ·* ····comes from standard input. ·(This can also be done for all blocks if
c1a500 ·* ····LIT_BUFSIZE is not greater than 32K.)
aaecef ·* ··- if compression is not successful for a file smaller than 64K, we can
4793e4 ·* ····even emit a stored file instead of a stored block (saving 5 bytes).
8a6448 ·* ··- creating new Huffman trees less frequently may not provide fast
24bf0a ·* ····adaptation to changes in the input data statistics. (Take for
8de39c ·* ····example a binary file with poorly compressible code followed by
1a7021 ·* ····a highly compressible string table.) Smaller buffer sizes give
4feadb ·* ····fast adaptation but have of course the overhead of transmitting trees
1c0fd3 ·* ····more frequently.
3d6ddc ·* ··- I can't count above 4
65e48a ·* The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
f967d0 ·* memory at the expense of compression). Some optimizations would be possible
62f7a0 ·* if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
4b495d ·*/
e8af5a
45c3c5 #define REP_3_6 ·····16
00ee81 /* repeat previous bit length 3-6 times (2 bits of repeat count) */
01af5a
a5deb7 #define REPZ_3_10 ···17
8acf9d /* repeat a zero length 3-10 times ·(3 bits of repeat count) */
d8af5a
d8ea1d #define REPZ_11_138 ·18
bfff6b /* repeat a zero length 11-138 times ·(7 bits of repeat count) */
8eaf5a
7bda25 /* ===========================================================================
207ef5 ·* Local data
59495d ·*/
5eaf5a
65c60f /* Data structure describing a single value and its code string. */
54e607 typedef struct ct_data
70bb36 {
1155e4 ····union {
3f3935 ········PGPUInt16 freq; ······/* frequency count */
4701e3 ¤   PGPUInt16 code; ······/* bit string */
26451f ····} fc;
c155e4 ····union {
c78253 ········PGPUInt16 dad; ·······/* father node in Huffman tree */
9267d2 ········PGPUInt16 len; ·······/* length of bit string */
1836ae ····} dl;
d6c052 } ct_data;
72af5a
de678c #define Freq fc.freq
b41a8a #define Code fc.code
5edee3 #define Dad ·dl.dad
b1c0f4 #define Len ·dl.len
03af5a
637d90 #define HEAP_SIZE (2*L_CODES+1)
67cd16 /* maximum heap size */
e1af5a
9fd040 typedef struct tree_desc {
693620 ····ct_data near *dyn_tree; ···/* the dynamic tree */
341f9b ····ct_data near *static_tree; /* corresponding static tree or NULL */
314676 ····int ·····const near *extra_bits; ·/* extra bits for each code or NULL */
9970fc ····int ·················extra_base; ·/* base index for extra_bits */
d275f9 ····int ·················elems; ······/* max number of elements in the tree */
d6cfb6 ····int ·················max_length; ·/* max bit length for the codes */
c2b968 ····int ·················max_code; ···/* largest code with non zero frequency*/
badabf } tree_desc;
16af5a
dc26f7 /* Tables for initializing context tables. ·The local pointers are set up in
758ec8 ·* ct_init.
d6495d ·*/
84af5a
67648d static const tree_desc near l_desc_init =
97064e {/*dyn_ltree*/0, /*static_ltree*/0, extra_lbits, LITERALS+1, L_CODES,
af1fd9 ¤   MAX_BITS, 0};
90af5a
1c8bee static const tree_desc near d_desc_init =
--0617 000c3aac318401001b3 Page 4 of pgpZTrees.c
30ed71 {/*dyn_dtree*/0, /*fstatic_dtree*/0, extra_dbits, 0, D_CODES, MAX_BITS, 0};
49af5a
377b3c static const tree_desc near bl_desc_init =
c745e5 {/*bl_tree*/0, NULL, ··extra_blbits, 0, ········BL_CODES, MAX_BL_BITS, 0};
7faf5a
79bea3 typedef struct ZTreesContext {
16af5a
8b8060 ¤   PGPContextRef¤  ¤   cdkContext;
41af5a
c0f232 ¤   ct_data near dyn_ltree[HEAP_SIZE]; ··/* literal and length tree*/
409cff ¤   ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */
37af5a
c3e2dc ¤   ct_data near static_ltree[L_CODES+2];
d7ed9a ¤   /* The static literal tree. Since the bit lengths are imposed, there is no
09ea88 ¤   ·* need for the L_CODES extra codes used during heap construction. However
29929a ¤   ·* The codes 286 and 287 are needed to build a canonical tree (see ct_init
5adf19 ¤   ·* below).
a1a4e3 ¤   ·*/
23af5a
68c6d8 ¤   ct_data near static_dtree[D_CODES];
c0a821 ¤   /* The static distance tree. (Actually a trivial tree since all codes use
f6a3b4 ¤   ·* 5 bits.)
61a4e3 ¤   ·*/
63af5a
d531cd ¤   ct_data near bl_tree[2*BL_CODES+1];
389ae0 ¤   /* Huffman tree for the bit lengths */
dbaf5a
86af5a
7a9c01 ¤   tree_desc near l_desc;
9eb1bd ¤   tree_desc near d_desc;
1f0003 ¤   tree_desc near bl_desc;
12af5a
24c4aa ¤   PGPUInt16 near bl_count[MAX_BITS+1];
c2bc23 ¤   /* number of codes at each bit length for an optimal tree */
d0af5a
4992d3 ¤   int near heap[2*L_CODES+1]; /*heap used to build the Huffman trees*/
73e09c ¤   int heap_len; ··············/* number of elements in the heap */
4ce94f ¤   int heap_max; ··············/* element of largest frequency */
d9e0a1 ¤   /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
7f9fd3 ¤   ·* The same heap array is used to build all trees.
99a4e3 ¤   ·*/
7aaf5a
e5266e ¤   PGPByte near depth[2*L_CODES+1];
18f71a ¤   /* Depth of each subtree used as tie breaker for trees of equal frequency*/
74af5a
3c412b ¤   PGPByte length_code[MAX_MATCH-MIN_MATCH+1];
07c3ac ¤   /* length code for each normalized match length (0 == MIN_MATCH) */
dcaf5a
bbd59b ¤   PGPByte dist_code[512];
2e12b8 ¤   /* distance codes. The first 256 values correspond to the distances
1d1e85 ¤   ·* 3 .. 258, the last 256 values correspond to the top 8 bits of
86b41f ¤   ·* the 15 bit distances.
3ca4e3 ¤   ·*/
b1af5a
b648b8 ¤   int near base_length[LENGTH_CODES];
ba2ea6 ¤   /* First normalized length for each code (0 = MIN_MATCH) */
6eaf5a
d23185 ¤   int near base_dist[D_CODES];
48d2f8 ¤   /* First normalized distance for each code (0 = distance of 1) */
17af5a
689bda #ifndef DYN_ALLOC
d2b5d2 ¤   ··PGPByte far l_buf[LIT_BUFSIZE]; ·/* buffer for literals/lengths */
54e4e3 ¤   ··PGPUInt16 far d_buf[DIST_BUFSIZE]; /* buffer for distances */
74db21 #else
65a595 ¤   ··PGPByte far *l_buf;
3c6304 ¤   ··PGPUInt16 far *d_buf;
1d7454 #endif
06af5a
bee192 ¤   PGPByte near flag_buf[(LIT_BUFSIZE/8)];
2c4f87 ¤   /* flag_buf is a bit array distinguishing literals from lengths in
e6576f ¤   ·* l_buf, and thus indicating the presence or absence of a distance.
c3a4e3 ¤   ·*/
--0956 000865aacd1401001b3 Page 5 of pgpZTrees.c
e0af5a
735249 ¤   unsigned last_lit; ···/* running index in l_buf */
9f9444 ¤   unsigned last_dist; ··/* running index in d_buf */
9a7186 ¤   unsigned last_flags; ·/* running index in flag_buf */
cc92bd ¤   PGPByte flags; ·······/* current flags not yet saved in flag_buf */
de01ed ¤   PGPByte flag_bit; ····/* current bit used in flags */
d2f153 ¤   /* bits are filled in flags starting at bit 0 (least significant).
7a72a9 ¤   ·* Note: these flags are overkill in the current code since we don't
1ddde9 ¤   ·* take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
83a4e3 ¤   ·*/
57af5a
9a02b4 ¤   /* bit length of current block with optimal trees*/
a7ca40 ¤   PGPUInt32 opt_len;
e3dced ¤   /* bit length of current block with static trees */
b1ef54 ¤   PGPUInt32 static_len;
16af5a
5f42dc ¤   PGPUInt32 compressed_len; /* total bit length of compressed file */
4caf5a
8797ec ¤   PGPUInt32 input_len; ·····/* total byte length of input file */
8a028c ¤   /* input_len is for debugging only since we can get it by other means. */
57b8e7 } ZTreesContext;
d2af5a
873e0f #ifdef ZIPDEBUG
2cef68 extern PGPUInt32 bits_sent; ·/* bit length of the compressed data */
527a67 extern PGPUInt32 isize; ·····/* byte length of input file */
287454 #endif
c9af5a
bada25 /* ===========================================================================
b04d50 ·* Local (static) routines in this file.
3a495d ·*/
4eaf5a
7bc5a1 static void init_block(ZTreesContext *);
c74b04 static void pqdownheap(ZTreesContext *, ct_data near *tree, int k);
5a410d static void gen_bitlen(ZTreesContext *, tree_desc near *desc);
f18467 static void gen_codes(ZTreesContext *, ct_data near *tree, int max_code);
c7cdd0 static void build_tree(ZTreesContext *, tree_desc near *desc);
2beb30 static void scan_tree(ZTreesContext *, ct_data near *tree, int max_code);
68635f static void send_tree(ZTreesContext *, struct ZBitsContext *,
75ea28 ¤   ct_data near *tree, int max_code);
f45477 static int ·build_bl_tree(ZTreesContext *);
9a56c6 static void send_all_trees(ZTreesContext *, struct ZBitsContext *,
63ff28 ¤   int lcodes, int dcodes, int blcodes);
b4a8c0 static void compress_block(ZTreesContext *, struct ZBitsContext *,
cfd4cd ¤   ct_data near *ltree, ct_data near *dtree);
81af5a
d2af5a
5183fd #ifndef ZIPDEBUG
1ff380 # ·define send_code(zbctx, c, tree)¤send_bits(zbctx, tree[c].Code, tree[c].Len)
038a44 ···/* Send a code of the given tree. c and tree must not have side effects */
92af5a
f0f800 #else /* ZIPDEBUG */
d05a6d # ·define send_code(zbctx, c, tree) \
fa347d ·····{ if (verbose > 1) fprintf(stderr,"\ncd %3d ",(c)); \
edf093 ·······send_bits(zbctx, tree[c].Code, tree[c].Len); }
927454 #endif
63af5a
484c1a #define d_code(ctx, dist) \
ff16a9 ···((dist) < 256 ? (ctx)->dist_code[dist] : (ctx)->dist_code[256+((dist)>>7)])
9bad76 /* Mapping from a distance to a distance code. dist is the distance - 1 and
62bd88 ·* must not have side effects. dist_code[256] and dist_code[257] are never
078867 ·* used.
65495d ·*/
93af5a
c71612 #define MAX(a,b) (a >= b ? a : b)
fee425 /* the arguments must not have side effects */
6baf5a
edda25 /* ===========================================================================
a00a42 ·* Reverse k low-order bits in a word. ·Not speed-critical.
8c495d ·*/
ef65bf static unsigned
ad4547 bit_reverse(unsigned value, int len)
86bb36 {
--02d5 000db5a29bc401001b3 Page 6 of pgpZTrees.c
0fd410 ¤   unsigned result = 0;
f7af5a
5743ab ¤   do {
7fd87c ¤   ¤   result <<= 1;
103a66 ¤   ¤   result |= value & 1;
d29f78 ¤   ¤   value >>= 1;
83c57e ¤   } while (--len);
695d73 ¤   return result;
f6efe6 }
54af5a
84da25 /* ===========================================================================
7bc3ec ·* Allocate the match buffer and initialize the various tables.
61495d ·*/
118f19 ZTreesContext *
739154 ct_init(PGPContextRef cdkContext)
ffbb36 {
fa6529 ¤   ZTreesContext *ctx;
f36b52 ····int n; ·······/* iterates over tree elements */
a36f78 ····int bits; ····/* bit counter */
fe2a43 ····int length; ··/* length value */
844a97 ····int code; ····/* code value */
264f72 ····int dist; ····/* distance index */
d9af5a
4d5b55 ¤   ctx = (ZTreesContext *) pgpContextMemAlloc (cdkContext,
6f44c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(*ctx), kPGPMemoryMgrFlags_Clear);
358b42 ¤   if (IsNull (ctx) )
687ed2 ¤   ¤   return NULL;
6f8b52 ¤   ctx->cdkContext = cdkContext;
5caf5a
314338 ¤   /* Initialize tables */
5f5592 ¤   pgpCopyMemory (&l_desc_init, ·&ctx->l_desc, ·sizeof(l_desc_init));
b024f5 ¤   ctx->l_desc.dyn_tree = ctx->dyn_ltree;
903ebf ¤   ctx->l_desc.static_tree = ctx->static_ltree;
eaaf5a
ba30c6 ¤   pgpCopyMemory (&d_desc_init, ·&ctx->d_desc, ·sizeof(d_desc_init));
0164d3 ¤   ctx->d_desc.dyn_tree = ctx->dyn_dtree;
669183 ¤   ctx->d_desc.static_tree = ctx->static_dtree;
07af5a
d7aa7d ¤   pgpCopyMemory (&bl_desc_init, &ctx->bl_desc, sizeof(bl_desc_init));
33c357 ¤   ctx->bl_desc.dyn_tree = ctx->bl_tree;
8cc655 ¤   ctx->bl_desc.static_tree = NULL;
38af5a
7a4477 ····ctx->compressed_len = ctx->input_len = 0L;
01af5a
924ffa #ifdef DYN_ALLOC
de4dea ····/* Allocate the buffers */
8baf5a
e6b918 ····ctx->d_buf = (PGPUInt16 far *)pgpContextMemAlloc (cdkContext,
bb3ea2 ¤   ¤   ¤   ¤   DIST_BUFSIZE * sizeof(PGPUInt16), kPGPMemoryMgrFlags_Clear);
706f3e ····if (ctx->d_buf == NULL) {
db10a7 ¤   ¤   pgpContextMemFree (cdkContext, ctx);
957ed2 ¤   ¤   return NULL;
849371 ¤   }
1c31a7 ····ctx->l_buf = (PGPByte far *)pgpContextMemAlloc (cdkContext,
53a9a8 ¤   ¤   ¤   ¤   (LIT_BUFSIZE/2) * 2, kPGPMemoryMgrFlags_Clear);
ca0712 ····/* Avoid using the value 64K on 16 bit machines */
0fef46 ····if (ctx->l_buf == NULL) {
e626ce ¤   ¤   pgpContextMemFree (cdkContext, ctx->d_buf);
4b10a7 ¤   ¤   pgpContextMemFree (cdkContext, ctx);
b17ed2 ¤   ¤   return NULL;
a16fe7 ····}
08dcf7 /* ···if (ctx->l_buf == NULL || ctx->d_buf == NULL)
2d4fd1 ·*¤ ¤   ··error("ct_init: out of memory");
8f495d ·*/
177454 #endif
295a0f ····/* Initialize the counts for the first block */
0d5ee7 ····init_block(ctx);
aaaf5a
f6d11c ····/* The following initializes constant data - it may be skipped */
26e7bd ····if (ctx->static_dtree[0].Len != 0) return 0; /* ct_init already called */
bcaf5a
dbedaf ····/* Initialize the mapping length (0..255) -> length code (0..28) */
--a1eb 000861de170401001b3 Page 7 of pgpZTrees.c
b306da ····length = 0;
7bed24 ····for (code = 0; code < LENGTH_CODES-1; code++) {
623358 ¤   ¤   ctx->base_length[code] = length;
ed6fa7 ¤   ¤   for (n = 0; n < (1<<extra_lbits[code]); n++) {
f0aa92 ¤   ¤   ¤   ctx->length_code[length++] = (PGPByte)code;
f10fe4 ¤   ¤   }
486fe7 ····}
7591a3 ····ZipAssert (length == 256, "ct_init: length != 256");
132f58 ····/* Note that the length 255 (match length 258) can be represented
966486 ·····* in two different ways: code 284 + 5 bits or code 285, so we
968cde ·····* overwrite length_code[255] to use the best encoding:
d9d48d ·····*/
3b8620 ····ctx->length_code[length-1] = (PGPByte)code;
dbaf5a
d7c4d1 ····/* Initialize the mapping dist (0..32K) -> dist code (0..29) */
dfcc66 ····dist = 0;
cc4617 ····for (code = 0 ; code < 16; code++) {
dc912b ¤   ¤   ctx->base_dist[code] = dist;
a4dcd6 ¤   ¤   for (n = 0; n < (1<<extra_dbits[code]); n++) {
a15068 ¤   ¤   ¤   ctx->dist_code[dist++] = (PGPByte)code;
210fe4 ¤   ¤   }
4e6fe7 ····}
dae6aa ····ZipAssert (dist == 256, "ct_init: dist != 256");
5b18c9 ····dist >>= 7; /* from now on, all distances are divided by 128 */
b6e4a2 ····for ( ; code < D_CODES; code++) {
741221 ¤   ¤   ctx->base_dist[code] = dist << 7;
662163 ¤   ¤   for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
a6a213 ¤   ¤   ¤   ctx->dist_code[256 + dist++] = (PGPByte)code;
590fe4 ¤   ¤   }
016fe7 ····}
35a661 ····ZipAssert (dist == 256, "ct_init: 256+dist != 512");
32af5a
383ac9 ····/* Construct the codes of the static literal tree */
9393b3 ····for (bits = 0; bits <= MAX_BITS; bits++)
1db21b ¤   ¤   ctx->bl_count[bits] = 0;
2bdde6 ····n = 0;
a20267 ····while (n <= 143) ctx->static_ltree[n++].Len = 8, ctx->bl_count[8]++;
970c5d ····while (n <= 255) ctx->static_ltree[n++].Len = 9, ctx->bl_count[9]++;
b89419 ····while (n <= 279) ctx->static_ltree[n++].Len = 7, ctx->bl_count[7]++;
7268c0 ····while (n <= 287) ctx->static_ltree[n++].Len = 8, ctx->bl_count[8]++;
43a692 ····/* Codes 286 and 287 do not exist, but we must include them in the
b35a0d ·····* tree construction to get a canonical Huffman tree (longest code
f2b5aa ·····* all ones)
0cd48d ·····*/
61816b ····gen_codes(ctx, (ct_data near *)ctx->static_ltree, L_CODES+1);
d5af5a
7b1975 ····/* The static distance tree is trivial: */
623192 ····for (n = 0; n < D_CODES; n++) {
8c433c ¤   ¤   ctx->static_dtree[n].Len = 5;
b5f1cb ¤   ¤   ctx->static_dtree[n].Code = bit_reverse(n, 5);
626fe7 ····}
73af5a
03af90 ····return ctx;
f4efe6 }
44af5a
c4f29d void ct_free(ZTreesContext *ctx)
b3bb36 {
cd2560 ¤   PGPContextRef cdkContext;
bfaf5a
f9f0ec ¤   cdkContext = ctx->cdkContext;
acaf5a
164ffa #ifdef DYN_ALLOC
1c68cc ····/* Wipe and free buffers */
77e13b ····pgpClearMemory(ctx->d_buf, DIST_BUFSIZE * sizeof(PGPUInt16));
9a2b3a ····pgpClearMemory(ctx->l_buf, LIT_BUFSIZE);
ff0d6e ····pgpContextMemFree (cdkContext, ctx->d_buf);
1820d2 ····pgpContextMemFree (cdkContext, ctx->l_buf);
b47454 #endif
96af5a
df8c1f ····/* Wipe everything else */
9eb33c ¤   pgpClearMemory( ctx, sizeof(*ctx) );
8658a9 ¤   pgpContextMemFree( cdkContext, ctx );
--eaee 00021874a02401001b3 Page 8 of pgpZTrees.c
7aefe6 }
46af5a
afda25 /* ===========================================================================
844dce ·* Initialize a new block.
65495d ·*/
4a2978 static void
c42326 init_block(ZTreesContext *ctx)
b9bb36 {
e31ec0 ····int n; /* iterates over tree elements */
cfaf5a
1edb7e ····/* Initialize the trees. */
c5dc9a ····for (n = 0; n < L_CODES; ·n++) ctx->dyn_ltree[n].Freq = 0;
2b0085 ····for (n = 0; n < D_CODES; ·n++) ctx->dyn_dtree[n].Freq = 0;
6615c0 ····for (n = 0; n < BL_CODES; n++) ctx->bl_tree[n].Freq = 0;
94af5a
8915e0 ····ctx->dyn_ltree[END_BLOCK].Freq = 1;
7569f8 ····ctx->opt_len = ctx->static_len = 0L;
3bc527 ····ctx->last_lit = ctx->last_dist = ctx->last_flags = 0;
a7da02 ····ctx->flags = 0; ctx->flag_bit = 1;
28efe6 }
d2af5a
c28375 #define SMALLEST 1
47bf0e /* Index within the heap array of least frequent node in the Huffman tree */
b1af5a
04af5a
60da25 /* ===========================================================================
1ffaf1 ·* Remove the smallest element from the heap and recreate the heap with
8ca7e7 ·* one less element. Updates heap and heap_len.
10495d ·*/
4a0794 #define pqremove(ctx, tree, top) \
b17c73 {\
6cc997 ····top = (ctx)->heap[SMALLEST]; \
2d5288 ····(ctx)->heap[SMALLEST] = (ctx)->heap[(ctx)->heap_len--]; \
6c5504 ····pqdownheap(ctx, tree, SMALLEST); \
15efe6 }
ecaf5a
24da25 /* ===========================================================================
896d33 ·* Compares to subtrees, using the tree depth as tie breaker when
78556c ·* the subtrees have equal frequency. This minimizes the worst case length.
da495d ·*/
5970f6 #define smaller(ctx, tree, n, m) \
e934e9 ···(tree[n].Freq < tree[m].Freq || \
1062ed ···(tree[n].Freq == tree[m].Freq && (ctx)->depth[n] <= (ctx)->depth[m]))
99af5a
ebda25 /* ===========================================================================
fa7b2c ·* Restore the heap property by moving down the tree starting at node k,
999ff3 ·* exchanging a node with the smallest of its two sons if necessary, stopping
f439dc ·* when the heap property is re-established (each father smaller than its
5fd2a2 ·* two sons).
80495d ·*/
9e2978 static void
182277 pqdownheap(ZTreesContext *ctx, ct_data near *tree, int k)
69bb36 {
c7c306 ····int v = ctx->heap[k];
3a5ab6 ····int j = k << 1; ·/* left son of k */
91d546 ····int htemp; ······/* required because of bug in SASC compiler */
3eaf5a
48c27c ····while (j <= ctx->heap_len) {
7dc3d5 ········/* Set j to the smallest of the two sons: */
cb7adb ········if (j < ctx->heap_len && smaller(ctx, tree, ctx->heap[j+1],
3ddcd6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·ctx->heap[j])) j++;
c0af5a
b9d339 ········/* Exit if v is smaller than both sons */
2e82b5 ········htemp = ctx->heap[j];
8a771a ········if (smaller(ctx, tree, v, htemp)) break;
5aaf5a
b30649 ········/* Exchange v with the smallest son */
2c5078 ¤   ¤   ctx->heap[k] = htemp;
bb5bc3 ········k = j;
8baf5a
a88b3f ········/* And continue down the tree, setting j to the left son of k */
21b9aa ········j <<= 1;
--e849 00048450ed0401001b3 Page 9 of pgpZTrees.c
9f6fe7 ····}
7cec2f ····ctx->heap[k] = v;
7defe6 }
15af5a
02da25 /* ===========================================================================
ea3298 ·* Compute the optimal bit lengths for a tree and update the total bit length
926c88 ·* for the current block.
e0e015 ·* IN assertion: the fields freq and dad are set, heap[heap_max] and
f3ea62 ·* ···above are the tree nodes sorted by increasing frequency.
04edc9 ·* OUT assertions: the field len is set to the optimal bit length, the
299ae8 ·* ····array bl_count contains the frequencies for each bit length.
092529 ·* ····The length opt_len is updated; static_len is also updated if stree is
b85819 ·* ····not null.
68495d ·*/
242978 static void
f6fb26 gen_bitlen(ZTreesContext *ctx, tree_desc near *desc)
19bb36 {
d97dff ····ct_data near *tree ·= desc->dyn_tree;
db5095 ····int const near *extra ·····= desc->extra_bits;
4f4c19 ····int base ··················= desc->extra_base;
207e2c ····int max_code ··············= desc->max_code;
9dd1a8 ····int max_length ············= desc->max_length;
6fd45c ····ct_data near *stree = desc->static_tree;
422b0e ····int h; ·············/* heap index */
17fa8d ····int n, m; ··········/* iterate over the tree elements */
4ef594 ····int bits; ··········/* bit length */
a56c2e ····int xbits; ·········/* extra bits */
054f69 ····PGPUInt16 f; ··········/* frequency */
02bfa0 ····int overflow = 0; ··/* number of elements with bit length too large */
faaf5a
b693b3 ····for (bits = 0; bits <= MAX_BITS; bits++)
c57b12 ········ctx->bl_count[bits] = 0;
59af5a
083f4c ····/* In a first pass, compute the optimal bit lengths (which may
ded65c ·····* overflow in the case of the bit length tree).
c8d48d ·····*/
0154cb ····tree[ctx->heap[ctx->heap_max]].Len = 0; /* root of the heap */
f8af5a
dd10de ····for (h = ctx->heap_max+1; h < HEAP_SIZE; h++) {
b521eb ········n = ctx->heap[h];
2217c3 ········bits = tree[tree[n].Dad].Len + 1;
f4f316 ········if (bits > max_length) {
9cb175 ············bits = max_length;
8d783c ············overflow++;
800fe4 ¤   ¤   }
7b4a1b ········tree[n].Len = (PGPUInt16)bits;
d4bb40 ········/* We overwrite tree[n].Dad which is no longer needed */
04af5a
7a869c ········if (n > max_code)
23b207 ············continue; /* not a leaf node */
84af5a
d51b61 ········ctx->bl_count[bits]++;
f7b712 ········xbits = 0;
343c55 ········if (n >= base)
4e64f5 ············xbits = extra[n-base];
5d93c6 ········f = tree[n].Freq;
f19a70 ········ctx->opt_len += (PGPUInt32)f * (bits + xbits);
216d69 ········if (stree)
fca571 ············ctx->static_len += (PGPUInt32)f * (stree[n].Len + xbits);
1a6fe7 ····}
ccd179 ····if (overflow == 0) return;
5faf5a
89ef12 ····Trace((stderr,"\nbit length overflow\n"));
12356e ····/* This happens for example on obj2 and pic of the Calgary corpus */
f1af5a
b59d99 ····/* Find the first bit length which could increase: */
38c9a3 ····do {
872460 ········bits = max_length-1;
1e736a ········while (ctx->bl_count[bits] == 0)
d83b4e ············bits--;
c4029b ········ctx->bl_count[bits]--; ·····/* move one leaf down the tree */
484590 ········ctx->bl_count[bits+1] += 2; /* move one overflow item as its brother */
--17e3 000ea24c21f401001b3 Page 10 of pgpZTrees.c
b09b02 ········ctx->bl_count[max_length]--;
37a06e ········/* The brother of the overflow item also moves one step up,
48fc0b ·········* but this does not affect bl_count[max_length]
475af3 ·········*/
7d2f92 ········overflow -= 2;
014fb7 ····} while (overflow > 0);
16af5a
b43849 ····/* Now recompute all bit lengths, scanning in increasing frequency.
ce25ae ·····* h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
8b0a02 ·····* lengths instead of fixing only the wrong ones. This idea is taken
e1bd7a ·····* from 'ar' written by Haruhiko Okumura.)
8ad48d ·····*/
01fbb0 ····for (bits = max_length; bits != 0; bits--) {
6a8120 ········n = ctx->bl_count[bits];
714874 ········while (n != 0) {
b8b56b ············m = ctx->heap[--h];
2a8e40 ············if (m > max_code)
b3823c ················continue;
4ea46f ············if (tree[m].Len != (unsigned) bits) {
f9ef62 ················Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
21bb85 ················ctx->opt_len += ((long)bits - tree[m].Len) * tree[m].Freq;
019691 ················tree[m].Len = (PGPUInt16)bits;
017812 ············}
c27ec3 ············n--;
837fb0 ········}
546fe7 ····}
87efe6 }
c9af5a
5ada25 /* ===========================================================================
86467b ·* Generate the codes for a given tree and bit counts (which need not be
8daa2e ·* optimal).
b4150a ·* IN assertion: the array bl_count contains the bit length statistics for
c3804a ·* ···the given tree and the field len is set for all tree elements.
71ef66 ·* OUT assertion: the field code is set for all tree elements of non
111f05 ·* ····zero code length.
26495d ·*/
0a2978 static void
699b3d gen_codes(ZTreesContext *ctx, ct_data near *tree, int max_code)
b0bb36 {
f6609b ····PGPUInt16 next_code[MAX_BITS+1]; /* next code value for each bit length */
0aaaa4 ····PGPUInt16 code = 0; ·············/* running code value */
17ec0e ····int bits; ····················/* bit index */
24cf9d ····int n; ·······················/* code index */
c5af5a
4f1197 ····/* The distribution counts are first used to generate the code values
3b7e18 ·····* without bit reversal.
38d48d ·····*/
8a6a82 ····for (bits = 1; bits <= MAX_BITS; bits++)
8a3f9c ········next_code[bits] = code = (code + ctx->bl_count[bits-1]) << 1;
ef758a ····/* Check that the bit counts in bl_count are consistent. The last code
0662b5 ·····* must be all ones.
bad48d ·····*/
d2d375 ····ZipAssert (code + ctx->bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
da9874 ············"inconsistent bit counts");
b81262 ····Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
ceaf5a
dc9302 ····for (n = 0; ·n <= max_code; n++) {
f5625d ········int len = tree[n].Len;
24a06d ········if (len == 0)
49a511 ············continue;
0cc503 ········/* Now reverse the bits */
1dbdb0 ········tree[n].Code = bit_reverse(next_code[len]++, len);
63af5a
fee399 ¤   ¤   Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
324448 ·············n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
356fe7 ····}
22efe6 }
28af5a
b9da25 /* ===========================================================================
0087df ·* Construct one Huffman tree and assigns the code bit strings and lengths.
40b422 ·* Update the total bit length for the current block.
ea79aa ·* IN assertion: the field freq is set for all tree elements.
--f218 0008d1ad1cf401001b3 Page 11 of pgpZTrees.c
a8f13b ·* OUT assertions: the fields len and code are set to the optimal bit length
49f1a3 ·* ····and corresponding code. The length opt_len is updated; static_len is
8187a8 ·* ····also updated if stree is not null. The field max_code is set.
29495d ·*/
c02978 static void
605a01 build_tree(ZTreesContext *ctx, tree_desc near *desc)
3fbb36 {
de6518 ····ct_data near *tree ··= desc->dyn_tree;
6db9e5 ····ct_data near *stree ·= desc->static_tree;
5ec755 ····int elems ···········= desc->elems;
33bda4 ····int n, m; ·········/* iterate over heap elements */
48f6fe ····int max_code = -1; /* largest code with non zero frequency */
704298 ····int node = elems; ·/* next internal node of the tree */
82af5a
e39f6a ····/* Construct the initial heap, with least frequent element in
d6ad03 ·····* heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
c46370 ·····* heap[0] is not used.
13d48d ·····*/
6090f4 ····ctx->heap_len = 0, ctx->heap_max = HEAP_SIZE;
26af5a
f5572d ····for (n = 0; n < elems; n++) {
d991d5 ········if (tree[n].Freq != 0) {
2ec8a2 ············ctx->heap[++ctx->heap_len] = max_code = n;
226765 ············ctx->depth[n] = 0;
ec45a6 ¤   ¤   } else {
5ed8f8 ············tree[n].Len = 0;
bd0fe4 ¤   ¤   }
296fe7 ····}
7daf5a
16d7ec ····/* The pkzip format requires that at least one distance code exists,
129603 ·····* and that at least one bit should be sent even if there is only one
5d8f47 ·····* possible code. So to avoid special checks later on we force at least
209ff4 ·····* two codes of non zero frequency.
0bd48d ·····*/
b06cc9 ····while (ctx->heap_len < 2) {
5846f5 ········n = ctx->heap[++ctx->heap_len] = (max_code < 2 ? ++max_code : 0);
9c923a ········tree[n].Freq = 1;
aea3f2 ········ctx->depth[n] = 0;
c57aea ········ctx->opt_len--;
de6d69 ········if (stree)
1cdb47 ············ctx->static_len -= stree[n].Len;
2d7a80 ········/* n is 0 or 1 so it does not have extra bits */
1f6fe7 ····}
41dff6 ····desc->max_code = max_code;
d7af5a
83fe05 ····/* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
fd4ef2 ·····* establish sub-heaps of increasing lengths:
6bd48d ·····*/
9aba68 ····for (n = ctx->heap_len/2; n >= 1; n--)
cdd2a1 ········pqdownheap(ctx, tree, n);
deaf5a
b81a59 ····/* Construct the Huffman tree by repeatedly combining the least two
f8f1a8 ·····* frequent nodes.
dcd48d ·····*/
4bc9a3 ····do {
f312a7 ········pqremove(ctx, tree, n); ··/* n = node of least frequency */
8f7368 ········m = ctx->heap[SMALLEST]; ·/* m = node of next least frequency */
a9af5a
ed9453 ········ctx->heap[--ctx->heap_max] = n; /* keep the nodes sorted by frequency*/
938e04 ········ctx->heap[--ctx->heap_max] = m;
63af5a
778713 ········/* Create a new node father of n and m */
55f532 ¤   ¤   tree[node].Freq = tree[n].Freq + tree[m].Freq;
03e3ad ········ctx->depth[node] = (PGPByte)(MAX(ctx->depth[n], ctx->depth[m]) + 1);
310525 ········tree[n].Dad = tree[m].Dad = (PGPUInt16)node;
902cf4 #ifdef DUMP_BL_TREE
aacad4 ········if (tree == ctx->bl_tree)
9f5f30 ············fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
53fe05 ····················node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
407454 #endif
cd04d4 ········/* and insert the new node in the heap */
8de015 ········ctx->heap[SMALLEST] = node++;
--51f1 0009bf5cc0c401001b3 Page 12 of pgpZTrees.c
74e178 ········pqdownheap(ctx, tree, SMALLEST);
9daf5a
3a315a ····} while (ctx->heap_len >= 2);
33af5a
3a22a3 ····ctx->heap[--ctx->heap_max] = ctx->heap[SMALLEST];
dfaf5a
039a0d ····/* At this point, the fields freq and dad are set. We can now
51f267 ·····* generate the bit lengths.
87d48d ·····*/
6d8d5c ····gen_bitlen(ctx, desc);
6caf5a
1bf8f2 ····/* The field len is now set, we can generate the bit codes */
1e097e ····gen_codes (ctx, tree, max_code);
11efe6 }
c0af5a
cdda25 /* ===========================================================================
fe7b9f ·* Scan a literal or distance tree to determine the frequencies of the codes
9bb27c ·* in the bit length tree. Updates opt_len to take into account the repeat
665744 ·* counts. ·(The contribution of the bit length codes will be added later
0c55fe ·* during the construction of bl_tree.)
62495d ·*/
ba2978 static void
149e33 scan_tree(ZTreesContext *ctx, ct_data near *tree, int max_code)
87bb36 {
ae7a29 ····int n; ····················/* iterates over all tree elements */
26f556 ····int prevlen = -1; ·········/* last emitted length */
4913e1 ····int curlen; ···············/* length of current code */
4c252e ····int nextlen = tree[0].Len; /* length of next code */
ce638e ····int count = 0; ············/* repeat count of the current code */
726544 ····int max_count = 7; ········/* max repeat count */
0f3d40 ····int min_count = 4; ········/* min repeat count */
76af5a
c7fade ····if (nextlen == 0)
242df4 ········max_count = 138, min_count = 3;
2a2538 ····tree[max_code+1].Len = (PGPUInt16)-1; /* guard */
34af5a
2f7a84 ····for (n = 0; n <= max_code; n++) {
105f3e ········curlen = nextlen; nextlen = tree[n+1].Len;
2a40d1 ········if (++count < max_count && curlen == nextlen) {
fea511 ············continue;
bf4ff1 ········} else if (count < min_count) {
cf2cc5 ············ctx->bl_tree[curlen].Freq += count;
e5580c ········} else if (curlen != 0) {
83ec3e ············if (curlen != prevlen)
7a29da ················ctx->bl_tree[curlen].Freq++;
bd4c9b ············ctx->bl_tree[REP_3_6].Freq++;
70707c ········} else if (count <= 10) {
3d5488 ············ctx->bl_tree[REPZ_3_10].Freq++;
4e9d1e ········} else {
72edf3 ············ctx->bl_tree[REPZ_11_138].Freq++;
917fb0 ········}
a74589 ········count = 0; prevlen = curlen;
63907f ········if (nextlen == 0) {
435513 ············max_count = 138, min_count = 3;
5f7c16 ¤   ¤   } else if (curlen == nextlen) {
fe505e ············max_count = 6, min_count = 3;
9d45a6 ¤   ¤   } else {
8b24bc ············max_count = 7, min_count = 4;
327fb0 ········}
036fe7 ····}
03efe6 }
3aaf5a
8bda25 /* ===========================================================================
dc227b ·* Send a literal or distance tree in compressed form, using the codes in
784993 ·* bl_tree.
99495d ·*/
ea2978 static void
627dce send_tree(ZTreesContext *ctx, struct ZBitsContext *zbcontext,
b36e3d ¤   ct_data near *tree, int max_code)
6cbb36 {
b77a29 ····int n; ····················/* iterates over all tree elements */
9bf556 ····int prevlen = -1; ·········/* last emitted length */
--9690 000d17a7f34401001b3 Page 13 of pgpZTrees.c
d813e1 ····int curlen; ···············/* length of current code */
46252e ····int nextlen = tree[0].Len; /* length of next code */
2b638e ····int count = 0; ············/* repeat count of the current code */
896544 ····int max_count = 7; ········/* max repeat count */
ab3d40 ····int min_count = 4; ········/* min repeat count */
58af5a
a76697 ····/* tree[max_code+1].Len = -1; */ ·/* guard already set */
41fade ····if (nextlen == 0)
3f2df4 ········max_count = 138, min_count = 3;
fbaf5a
827a84 ····for (n = 0; n <= max_code; n++) {
386e7a ········curlen = nextlen;
470e0b ········nextlen = tree[n+1].Len;
ea40d1 ········if (++count < max_count && curlen == nextlen) {
c0a511 ············continue;
ca4ff1 ········} else if (count < min_count) {
97a4b3 ············do {
5f051a ················send_code(zbcontext, curlen, ctx->bl_tree);
f8288d ············} while (--count != 0);
6c580c ········} else if (curlen != 0) {
250362 ¤   ¤   ¤   if (curlen != prevlen) {
72051a ················send_code(zbcontext, curlen, ctx->bl_tree);
d57b9b ················count--;
7b7812 ············}
1304c9 ············ZipAssert(count >= 3 && count <= 6, " 3_6?");
f66dde ············send_code(zbcontext, REP_3_6, ctx->bl_tree);
9ac25a ············send_bits(zbcontext, count-3, 2);
30707c ········} else if (count <= 10) {
c1dfcb ············send_code(zbcontext, REPZ_3_10, ctx->bl_tree);
f5dee1 ············send_bits(zbcontext, count-3, 3);
c79d1e ········} else {
ba7de3 ············send_code(zbcontext, REPZ_11_138, ctx->bl_tree);
4ca326 ············send_bits(zbcontext, count-11, 7);
0a7fb0 ········}
934589 ········count = 0; prevlen = curlen;
85907f ········if (nextlen == 0) {
995513 ············max_count = 138, min_count = 3;
201f2f ········} else if (curlen == nextlen) {
38505e ············max_count = 6, min_count = 3;
489d1e ········} else {
bf24bc ············max_count = 7, min_count = 4;
f77fb0 ········}
3b6fe7 ····}
8fefe6 }
7aaf5a
e6da25 /* ===========================================================================
f7c39c ·* Construct the Huffman tree for the bit lengths and return the index in
01c515 ·* bl_order of the last bit length code to send.
ac495d ·*/
5cbeb7 static int
ee5c1c build_bl_tree(ZTreesContext *ctx)
1ebb36 {
8eee60 ····int max_blindex; ·/* index of last bit length code of non zero freq */
adaf5a
172e42 ····/* Determine the bit length frequencies for literal and distance trees */
7187e3 ····scan_tree(ctx, ctx->dyn_ltree, ctx->l_desc.max_code);
e07725 ····scan_tree(ctx, ctx->dyn_dtree, ctx->d_desc.max_code);
5eaf5a
590de2 ····/* Build the bit length tree: */
ab500c ····build_tree(ctx, &ctx->bl_desc);
f0e188 ····/* opt_len now includes the length of the tree representations, except
5dc380 ·····* the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
71d48d ·····*/
1eaf5a
ae1c45 ····/* Determine the number of bit length codes to send. The pkzip format
5513e3 ·····* requires that at least 4 bit length codes be sent. (appnote.txt says
a600d4 ·····* 3 but the actual value used is 4.)
fcd48d ·····*/
e70028 ····for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
4e8052 ········if (ctx->bl_tree[bl_order[max_blindex]].Len != 0)
478632 ············break;
d16fe7 ····}
--c350 000ca0a8c33401001b3 Page 14 of pgpZTrees.c
70d405 ····/* Update opt_len to include the bit length tree and counts */
df8874 ····ctx->opt_len += 3*(max_blindex+1) + 5+5+4;
c7e1ad ····Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", ctx->opt_len,
9f2950 ¤   ¤   ¤   ctx->static_len));
dfaf5a
4899d9 ····return max_blindex;
f5efe6 }
49af5a
7cda25 /* ===========================================================================
656e35 ·* Send the header for a block using dynamic Huffman trees: the counts, the
daae45 ·* lengths of the bit length codes, the literal tree and the distance tree.
5420d2 ·* IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
0c495d ·*/
7c2978 static void
6b2696 send_all_trees(ZTreesContext *ctx, struct ZBitsContext *zbcontext,
dcc778 ¤   int lcodes, int dcodes, int blcodes)
e1bb36 {
61bb7d ····int rank; ···················/* index in bl_order */
ffaf5a
3d3ff1 ····ZipAssert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4,
fb85d7 ············"not enough codes");
3df2e1 ····ZipAssert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
9b5aff ············"too many codes");
cefeb7 ····Tracev((stderr, "\nbl counts: "));
1c12e4 ····send_bits(zbcontext, lcodes-257, 5);
ef741d ····/* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */
b77573 ····send_bits(zbcontext, dcodes-1, ··5);
0b861c ····send_bits(zbcontext, blcodes-4, ·4); /* not -3 as stated in appnote.txt */
efe782 ····for (rank = 0; rank < blcodes; rank++) {
561ca1 ········Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
bd568a ········send_bits(zbcontext, ctx->bl_tree[bl_order[rank]].Len, 3);
ad6fe7 ····}
0d0c9b ····Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
d8af5a
4d9da2 ····/* send the literal tree */
ef5d4c ····send_tree(ctx, zbcontext, (ct_data near *)ctx->dyn_ltree, lcodes-1);
333891 ····Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
e0af5a
27ea1e ····/* send the distance tree */
0c1ea9 ····send_tree(ctx, zbcontext, (ct_data near *)ctx->dyn_dtree, dcodes-1);
790ce4 ····Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
96efe6 }
e3af5a
71da25 /* ===========================================================================
b1eda7 ·* Determine the best encoding for the current block: dynamic trees, static
05812c ·* trees or store, and output the encoded block to the zip file. This function
f4e4a2 ·* returns the total compressed length for the file so far.
66775e ·*
79cadd ·* buf: the input block, or NULL if too old
4b123e ·* stored_len: the length of the input block
be3d92 ·* eof: true if this is the last block for the file
3f495d ·*/
9bbccf PGPUInt32
c28fa6 flush_block(ZTreesContext *ctx, struct ZBitsContext *zbcontext,
1e689e ¤   char const *buf, PGPUInt32 stored_len, int eof, PGPByte *window)
afbb36 {
b99771 ····PGPUInt32 opt_lenb, static_lenb; /* opt_len and static_len in bytes */
dfee60 ····int max_blindex; ·/* index of last bit length code of non zero freq */
d5af5a
17e1f8 ¤   /* Save the flags for the last 8 items */
4ff6e6 ····ctx->flag_buf[ctx->last_flags] = ctx->flags;
74af5a
d91729 ····/* Construct the literal and distance trees */
013bf8 ····build_tree(ctx, (tree_desc near *)(&ctx->l_desc));
6f2809 ····Tracev((stderr, "\nlit data: dyn %ld, stat %ld", ctx->opt_len,
4c2950 ¤   ¤   ¤   ctx->static_len));
80af5a
cc52d1 ····build_tree(ctx, (tree_desc near *)(&ctx->d_desc));
aaac66 ····Tracev((stderr, "\ndist data: dyn %ld, stat %ld", ctx->opt_len,
272950 ¤   ¤   ¤   ctx->static_len));
04dce1 ····/* At this point, opt_len and static_len are the total bit lengths of
ca736e ·····* the compressed block data, excluding the tree representations.
--4d75 0004abb92c5401001b3 Page 15 of pgpZTrees.c
dbd48d ·····*/
56af5a
072e09 ····/* Build the bit length tree for the above two trees, and get the index
872f36 ·····* in bl_order of the last bit length code to send.
fad48d ·····*/
ff19da ····max_blindex = build_bl_tree(ctx);
28af5a
c9a9f5 ····/* Determine the best encoding. Compute first the block length in bytes */
3bf1ad ····opt_lenb = (ctx->opt_len+3+7)>>3;
3d25ae ····static_lenb = (ctx->static_len+3+7)>>3;
6ccc65 ····ctx->input_len += stored_len; /* for debugging only */
3caf5a
313ad0 ····Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
01e0ef ¤   ¤   ···opt_lenb, ctx->opt_len, static_lenb, ctx->static_len, stored_len,
5ed999 ¤   ¤   ···ctx->last_lit, ctx->last_dist));
03af5a
4822f5 ····if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
75af5a
e7fb88 #ifndef PGP /* PGP can't handle stored files - disable this test */
7f29ec ····/*
cd95bd ·····* If compression failed and this is the first and last block,
a29da5 ·····* and if the zip file can be seeked (to rewrite the local header),
14b817 ·····* the whole file is transformed into a stored file:
87d48d ·····*/
958ad4 #ifdef FORCE_METHOD
c1717d ····if (ctx->level == 1 && eof && ctx->compressed_len == 0L) {
69eec6 ¤   ¤   /* force stored file */
47db21 #else
63f95b ····if (stored_len <= opt_lenb && eof && ctx->compressed_len == 0L &&
03e467 ¤   ¤   seekable()) {
5b7454 #endif
4a07f6 ········/* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
5ee61e ········if (buf == NULL) error ("block vanished");
c4af5a
a6e43a ¤   ¤   /* without header */
539ba6 ········copy_block(zbcontext, buf, (unsigned)stored_len, 0);
013359 ········ctx->compressed_len = stored_len << 3;
e5ce75 ····} else
0c5a12 #endif /* PGP */
3faf5a
c78ad4 #ifdef FORCE_METHOD
d0bb47 ¤   if (ctx->level == 2 && buf != (char*)NULL) { /* force stored block */
d6db21 #else
61bc67 ¤   if (stored_len+4 <= opt_lenb && buf != (char*)NULL) {
5f8c8e ¤   ¤   /* 4: two words for the lengths */
4f7454 #endif
80f9f0 ········/* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
ecc9f7 ·········* Otherwise we can't have processed more than WSIZE input bytes since
75ed67 ·········* the last block flush, because compression would have been
a355ae ·········* successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
26c10a ·········* transform a block into a stored block.
445af3 ·········*/
f6ec88 ········send_bits(zbcontext, (STORED_BLOCK<<1)+eof, 3); ·/* send block type */
ddcec3 ········ctx->compressed_len = (ctx->compressed_len + 3 + 7) & ~7L;
2eb9fd ¤   ¤   ctx->compressed_len += (stored_len + 4) << 3;
e2af5a
31c1b0 ¤   ¤   copy_block(zbcontext, buf, (unsigned)stored_len, 1); /* with header */
11af5a
b98ad4 #ifdef FORCE_METHOD
bbe4a5 ····} else if (ctx->level == 3) { /* force static trees */
9bdb21 #else
a1d666 ····} else if (static_lenb == opt_lenb) {
567454 #endif
b82f1c ········send_bits(zbcontext, (STATIC_TREES<<1)+eof, 3);
49681c ········compress_block(ctx, zbcontext,
9183c0 ¤   ¤   ¤   ¤   ¤   ···(ct_data near *)ctx->static_ltree,
29d2ae ¤   ¤   ¤   ¤   ¤   ···(ct_data near *)ctx->static_dtree);
95edae ········ctx->compressed_len += 3 + ctx->static_len;
4c6a79 ····} else {
c9dd0c ········send_bits(zbcontext, (DYN_TREES<<1)+eof, 3);
cade22 ········send_all_trees(ctx, zbcontext, ctx->l_desc.max_code+1,
4a07c7 ¤   ¤   ¤   ¤   ¤   ···ctx->d_desc.max_code+1, max_blindex+1);
--5f06 00039442fdc401001b3 Page 16 of pgpZTrees.c
89681c ········compress_block(ctx, zbcontext,
870a33 ¤   ¤   ¤   ¤   ¤   ···(ct_data near *)ctx->dyn_ltree,
cc1733 ¤   ¤   ¤   ¤   ¤   ···(ct_data near *)ctx->dyn_dtree);
72c366 ········ctx->compressed_len += 3 + ctx->opt_len;
f06fe7 ····}
14dfbe ····ZipAssert (ctx->compressed_len == bits_sent, "bad compressed size");
6c5ee7 ····init_block(ctx);
3eaf5a
f883ca ····if (eof) {
f5bdf3 #if defined(PGP) && !defined(MMAP)
2b857a ········/* Wipe out sensitive data for pgp */
63589a ········pgpClearMemory( window,
b27491 ········¤   (unsigned)(2*WSIZE-1)); /* -1 needed if WSIZE=32K */
2ee21f #else /* !PGP */
27506f ········ZipAssert (ctx->input_len == ctx->isize, "bad input size");
137454 #endif
748ba3 ¤   ¤   bi_windup(zbcontext);
7fdcec ········ctx->compressed_len += 7; ·/* align on byte boundary */
a06fe7 ····}
689e1d ····Tracev((stderr,"\ncomprlen %lu(%lu) ", ctx->compressed_len>>3,
655d15 ¤   ¤   ¤   ctx->compressed_len-7*eof));
b0af5a
69cf34 ····return ctx->compressed_len >> 3;
bbefe6 }
53af5a
f1da25 /* ===========================================================================
6ed112 ·* Save the match info and tally the frequency counts. Return true if
b914f9 ·* the current block must be flushed.
bd775e ·*
d2e4de ·* dist is the distance to the matched string, or 0 if none.
4df8d4 ·* lc is the length of the match, or the character if dist == 0.
39495d ·*/
284d2f int
35d50b ct_tally(ZTreesContext *ctx, unsigned dist, unsigned lc, long block_start,
d2312b ¤   unsigned strstart)
87bb36 {
f8bc02 ····ctx->l_buf[ctx->last_lit++] = (PGPByte)lc;
854120 ····if (dist == 0) {
8ba6bd ········/* lc is the unmatched char */
8a8a51 ········ctx->dyn_ltree[lc].Freq++;
be6a79 ····} else {
39f12e ········/* Here, lc is the match length - MIN_MATCH */
900d2a ········dist--; ············/* dist = match distance - 1 */
1a5a89 ········ZipAssert((PGPUInt16)dist < (PGPUInt16)MAX_DIST &&
ec2b6e ···············(PGPUInt16)lc <= (PGPUInt16)(MAX_MATCH-MIN_MATCH) &&
78fb9a ···············(PGPUInt16)d_code(ctx, dist) < (PGPUInt16)D_CODES,·
785a28 ···············"ct_tally: bad match");
34af5a
412316 ········ctx->dyn_ltree[ctx->length_code[lc]+LITERALS+1].Freq++;
a614b1 ········ctx->dyn_dtree[d_code(ctx, dist)].Freq++;
97af5a
973dac ········ctx->d_buf[ctx->last_dist++] = (PGPUInt16)dist;
f7a417 ········ctx->flags |= ctx->flag_bit;
786fe7 ····}
e1bdd3 ····ctx->flag_bit <<= 1;
09af5a
9d685d ····/* Output the flags if they fill a byte: */
b692fc ····if ((ctx->last_lit & 7) == 0) {
967420 ········ctx->flag_buf[ctx->last_flags++] = ctx->flags;
d3083e ········ctx->flags = 0, ctx->flag_bit = 1;
5c6fe7 ····}
55f123 ····/* Try to guess if it is profitable to stop the current block here */
f46069 ····if (/* ctx->level > 2 && */ (ctx->last_lit & 0xfff) == 0) {
feeccf ········/* Compute an upper bound for the compressed length */
94beee ········PGPUInt32 out_length = (PGPUInt32)ctx->last_lit*8L;
366e71 ········PGPUInt32 in_length = (PGPUInt32)strstart-block_start;
8151f0 ········int dcode;
f6af5a
548585 ········for (dcode = 0; dcode < D_CODES; dcode++)
362b20 ············out_length += (PGPUInt32)
86a258 ¤   ¤   ¤   ¤   ctx->dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]);
398961 ········out_length >>= 3;
--6bb1 0012f0e207c401001b3 Page 17 of pgpZTrees.c
0e7e7f ········Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
383f58 ···············ctx->last_lit, ctx->last_dist, in_length, out_length,
97e71f ···············100L - out_length*100L/in_length));
9c0b58 ········if (ctx->last_dist < ctx->last_lit/2 && out_length < in_length/2)
5adb98 ¤   ¤   ¤   return 1;
f76fe7 ····}
eda8c6 ····return (ctx->last_lit == LIT_BUFSIZE-1 || ctx->last_dist == DIST_BUFSIZE);
d3a137 ····/* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
2048b6 ·····* on 16 bit machines and because stored blocks are restricted to
4ec415 ·····* 64K-1 bytes.
54d48d ·····*/
a8efe6 }
2eaf5a
3eda25 /* ===========================================================================
ee8063 ·* Send the block data compressed using the given Huffman trees
ed495d ·*/
4b2978 static void
06a457 compress_block(ZTreesContext *ctx, struct ZBitsContext *zbcontext,
f170f2 ¤   ct_data near *ltree, ct_data near *dtree)
f2bb36 {
7baa13 ····unsigned dist; ·····/* distance of matched string */
d9919f ····int lc; ············/* match length or unmatched char (if dist == 0) */
0a8eda ····unsigned lx = 0; ···/* running index in l_buf */
7780c0 ····unsigned dx = 0; ···/* running index in d_buf */
6a569b ····unsigned fx = 0; ···/* running index in flag_buf */
e4fb41 ····PGPByte flag = 0; ······/* current flags */
23588a ····unsigned code; ·····/* the code to send */
4b4561 ····int extra; ·········/* number of extra bits to send */
8faf5a
aac6f2 ····if (ctx->last_lit != 0) do {
568fc6 ········if ((lx & 7) == 0)
e9c717 ¤   ¤   ¤   flag = ctx->flag_buf[fx++];
bd82e6 ········lc = ctx->l_buf[lx++];
4f6bea ········if ((flag & 1) == 0) {
ae6151 ············send_code(zbcontext, lc, ltree); /* send a literal byte */
e2bc07 ············Tracecv(isgraph(lc), (stderr," '%c' ", lc));
d19d1e ········} else {
b53793 ············/* Here, lc is the match length - MIN_MATCH */
6cf342 ············code = ctx->length_code[lc];
c97f2b ¤   ¤   ¤   /* send the length code */
e3308f ············send_code(zbcontext, code+LITERALS+1, ltree);
1abab8 ············extra = extra_lbits[code];
b31d86 ············if (extra != 0) {
37bc8f ················lc -= ctx->base_length[code];
e407ce ¤   ¤   ¤   ¤   /* send the extra length bits */
0c3156 ················send_bits(zbcontext, lc, extra);
277812 ············}
1ae947 ············dist = ctx->d_buf[dx++];
bae3df ············/* Here, dist is the match distance - 1 */
6a5fe1 ············code = d_code(ctx, dist);
920647 ············ZipAssert (code < D_CODES, "bad d_code");
75af5a
5e2658 ¤   ¤   ¤   send_code(zbcontext, code, dtree); ···/* send the distance code */
35780f ¤   ¤   ¤   extra = extra_dbits[code];
257457 ¤   ¤   ¤   if (extra != 0) {
b94773 ¤   ¤   ¤   ¤   dist -= ctx->base_dist[code];
47a7db ¤   ¤   ¤   ¤   /* send the extra distance bits */
b6ddad ¤   ¤   ¤   ¤   send_bits(zbcontext, dist, extra);
c0a3a6 ¤   ¤   ¤   }
a50f62 ¤   ¤   } /* literal or match pair ? */
e70cc2 ¤   ¤   flag >>= 1;
98308d ····} while (lx < ctx->last_lit);
10af5a
37f919 ····send_code(zbcontext, END_BLOCK, ltree);
2fefe6 }
--f8d5 0001d6cebfc401001b4 Page 1 of pgpZip.h
bc38e5 /*
d26f50 ·* Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup
0a7cf3 ·* Gailly. ·Permission is granted to any individual or institution to use,
19cb89 ·* copy, or redistribute this software so long as all of the original files
4f3f3c ·* are included unmodified, that it is not sold for profit, and that this
df1f01 ·* copyright notice is retained.
57775e ·*
210af8 ·* $Id: pgpZip.h,v 1.9 1997/11/06 20:00:23 lloyd Exp $
81495d ·*/
e1af5a
d738e5 /*
5887cb ·* pgpZip.h by Mark Adler.
10495d ·*/
9eaf5a
0d38e5 /*
1fe39d ·* This is a PRIVATE header file, for use only within the PGP Library.
052979 ·* You should not be using these functions in an application.
2f495d ·*/
51af5a
8072fa /* Set up portability */
bed11f #include "pgpUsuals.h"
d6c26c #include "pgpContext.h"
620d08 #include "pgpMem.h"
366af8 #include "pgpZTailor.h"
4aadb8 #include "pgpOpaqueStructs.h"
10af5a
0794e5 /* Local data structures are defined in each module */
f48d5b struct ZDeflateContext;
3eab50 struct ZBitsContext;
90a6be struct ZTreesContext;
76af5a
b0910b /* PGP defines */
dd9d7c #define PGP¤1
82306a #ifdef MSDOS
7c8c53 #define SMALL_MEM 1
c97454 #endif
694987 /* DYN_ALLOC is defined in pgpZTailor.h */
c8af5a
b84dc6 #define MIN_MATCH ·3
c4a82c #define MAX_MATCH ·258
303016 /* The minimum and maximum match lengths */
b8af5a
42da8e #define WSIZE¤  8192
17c2c2 /* The Window size must be 8k to be compatible with PGP 2.6.2 */
b0af5a
24acd4 #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
5b5b90 /* Minimum amount of lookahead, except at the end of the input file.
91dc1a ·* See deflate.c for comments about the MIN_MATCH+1.
03495d ·*/
95af5a
c03c9b #define MAX_DIST ·(WSIZE-MIN_LOOKAHEAD)
45d547 /* In order to simplify the code, particularly on 16 bit machines, match
5e6ca1 ·* distances are limited to MAX_DIST instead of WSIZE.
8e495d ·*/
6caf5a
42324c #include <string.h>
62af5a
a699c6 PGP_BEGIN_C_DECLARATIONS
85af5a
bc720e /* Diagnostic functions */
83bc29 #if ZIPDEBUG
8b5816 ··extern int verbose;¤  /* Verbose reporting flag */
4d181c # ifdef MSDOS
e85a03 # ·undef ·stderr
8d1617 # ·define stderr stdout
16e01a # endif
0c901b # define ZipAssert(cond,msg) {if(!(cond)) error(msg);}
cb91e3 # define Trace(x) fprintf x
89d0a5 # define Tracev(x) {if (verbose) fprintf x ;}
45ae62 # define Tracevv(x) {if (verbose>1) fprintf x ;}
6025d9 # define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
1dac45 # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
--b8e9 00192a71211401001b4 Page 2 of pgpZip.h
0fdb21 #else
3a5668 # define ZipAssert(cond,msg)
f1bc75 # define Trace(x)
259a64 # define Tracev(x)
da9b4a # define Tracevv(x)
6a8f66 # define Tracec(c,x)
43aebf # define Tracecv(c,x)
7b7454 #endif
bfaf5a
e0af5a
8e6319 /* Public function prototypes */
d2af5a
4ff965 ········/* in pgpZDeflate.c */
2ad0a2 struct ZDeflateContext * lm_init(PGPContextRef cdkContext, int pack_level );
02cf7c void lm_free(struct ZDeflateContext *zdcontext);
51af5a
ad8a3a ¤   /* in pgpZTrees.c */
8f13d2 struct ZTreesContext * ct_init(PGPContextRef cdkContext);
56a3a6 int ct_tally(struct ZTreesContext *ztcontext, unsigned dist, unsigned lc,
3d6646 ¤   long block_start, unsigned strstart);
a8abab void ct_free(struct ZTreesContext *ztcontext);
1928f4 PGPUInt32 flush_block(struct ZTreesContext *ztcontext,
e76b13 ¤   struct ZBitsContext *zbcontext, char const *buf, PGPUInt32 stored_len,
67aea0 ¤   int eof, PGPByte *window);
26af5a
d99981 ¤   /* in pgpZBits.c */
f8aa7e struct ZBitsContext * bi_init(PGPContextRef cdkContext,
a9b6a6 ¤   PGPFifoContext *zipfifo);
7fac79 void bi_free(struct ZBitsContext *zbcontext);
044732 void send_bits(struct ZBitsContext *zbcontext, int value, int length);
053c59 void bi_flush(struct ZBitsContext *zbcontext);
20bbc7 void bi_windup(struct ZBitsContext *zbcontext);
9802ac void copy_block(struct ZBitsContext *zbcontext,
4cd4b8 ¤   char const far *buf, unsigned len, int header);
ccaf5a
fa25d3 ¤   /* in pgpZDeflate.c */
5a9852 void zip_input(struct ZDeflateContext *zdcontext,
3d02dd ¤   struct ZTreesContext *ztcontext, struct ZBitsContext *zbcontext,
18a36d ¤   char const *buf, unsigned len);
4ff42c void zip_finish(struct ZDeflateContext *zdcontext,
8434f7 ¤   struct ZTreesContext *ztcontext, struct ZBitsContext *zbcontext);
69af5a
ce1254 PGP_END_C_DECLARATIONS
3faf5a
927fa5 /* end of pgpZip.h */
--6699 001ad476de9401001b5 Page 1 of Makefile.in
5ea601 #
42caed # priv/crypto/pipe/utils/
63a601 #
afd9ce # $Id: Makefile.in,v 1.3 1997/05/25 06:27:55 hal Exp $
b9a601 #
faaf5a
a2247a OBJS=¤  pgpAddHdr.o pgpBufMod.o pgpCopyMod.o pgpDevNull.o pgpMemMod.o \
b04510 ¤   pgpJoin.o pgpSplit.o pgpVMemMod.o
dfa911 PRIVHDRS= pgpBufMod.h pgpDevNull.h pgpJoin.h pgpMemMod.h pgpPipeline.h \
fc0cfd ¤   pgpSplit.h pgpAddHdr.h pgpCopyMod.h pgpVMemMod.h
43af5a
20b7a3 all:: DONE
adaf5a
--235c 0002c21e643401001b6 Page 1 of pgpAddHdr.c
bc38e5 /*
172f51 ·* pgpAddHdr.c -- Add a PGP Packet Header to a data stream.
4d775e ·*
d67ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
81775e ·*
adcf5f ·* $Id: pgpAddHdr.c,v 1.24 1998/06/11 18:27:56 hal Exp $
fc495d ·*/
99e2ff #include "pgpConfig.h"
1caf5a
81feb2 #include <stdio.h>
54324c #include <string.h>
66af5a
a2a146 #include "pgpDebug.h"
b777c6 #include "pgpAddHdr.h"
eb9c38 #include "pgpPktByte.h"
726aaa #include "pgpAnnotate.h"
a0910a #include "pgpFIFO.h"
910d08 #include "pgpMem.h"
df2ece #include "pgpPipeline.h"
fa2f8d #include "pgpErrors.h"
aac26c #include "pgpContext.h"
feaf5a
2b7b5d #define ADDHEADERMAGIC¤ 0xadd0b11e
4196c0 #define BLOCK_SIZE 12
93140c #define BUFFER_SIZE (1 << BLOCK_SIZE)¤  /* 2^10 == 4k */
c4af5a
45b95c typedef struct AddHdrContext {
aff8fb ¤   PGPPipeline¤¤   pipe;
0667c5 ¤
a018b9 ¤   PGPFifoDesc const *fifod;
9b3566 ¤   PGPFifoContext *fifo;
b875b0 ¤   PGPPipeline *tail;
7dc263 ¤   PGPByte header[5];¤ ¤   ¤   /* pktbyte + 4byte length */
1d8ade ¤   PGPByte *ptr;
f3c63c ¤   int hdrlen;¤¤   ¤   /* actual header length */
c5d8af ¤   int dowrite;
d9a998 ¤   int sizeknown;¤ ¤   ¤   /* bytes is valid */
5bb397 ¤   unsigned long bytes;¤   ¤   /* sizeAdvise() promise */
acc5ae ¤   PgpVersion version;
e6994d ¤   PGPByte *buffer;
2a6e13 ¤   PGPByte *bufwrite;
f8c98f ¤   PGPByte *bufptr;
f8884e ¤   int buflen;
984c7c ¤   int midflush;
b87929 ¤   int scope_depth;
e241b3 ¤   DEBUG_STRUCT_CONSTRUCTOR( AddHdrContext )
767f90 } AddHdrContext;
a1af5a
e338e5 /*
47278b ·* Return the largest x such that 2^x <= n, n>0
a5910b ·* Return -1 if n==0
e6495d ·*/
81beb7 static int
a0f3c1 NumToBits(unsigned int n)
5dbb36 {
0e4ba4 ¤   int i;
3eaf5a
29d854 ¤   if (!n)
f8043c ¤   ¤   return -1;
c7af5a
af85cd ¤   for (i=0; n > 1; i++)
fa611a ¤   ¤   n >>= 1;
00af5a
462196 ¤   return i;
22efe6 }
5faf5a
c3f1ae static PGPError
605be4 FlushHeader(AddHdrContext *context)
aebb36 {
c687a6 ¤   PGPError¤   error;
f86c75 ¤   size_t retlen;
2caf5a
--14da 00091f9e248401001b6 Page 2 of pgpAddHdr.c
ee8710 ¤   while (context->hdrlen) {
bc3c2e ¤   ¤   retlen = context->tail->write(context->tail,
89bd3c ¤   ¤   ¤   ¤   ¤   ·······context->ptr,
57b0b6 ¤   ¤   ¤   ¤   ¤   ·······context->hdrlen,
0548b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
726215 ¤   ¤   context->ptr += retlen;
8f76f2 ¤   ¤   context->hdrlen -= retlen;
28e3c2 ¤   ¤   if (error)
df3b5b ¤   ¤   ¤   return error;
169371 ¤   }
bf2d68 ¤   return( kPGPError_NoErr );
f5efe6 }
20af5a
43f1ae static PGPError
c0b4d1 FlushBuffer(AddHdrContext *context)
06bb36 {
4e87a6 ¤   PGPError¤   error;
286c75 ¤   size_t retlen;
afaf5a
4649b8 ¤   while (context->buflen) {
b43c2e ¤   ¤   retlen = context->tail->write(context->tail,
25d239 ¤   ¤   ¤   ¤   ¤   ·······context->bufptr,
82ee65 ¤   ¤   ¤   ¤   ¤   ·······context->buflen,
2c48b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
24060f ¤   ¤   context->bufptr += retlen;
21e166 ¤   ¤   context->buflen -= retlen;
57e3c2 ¤   ¤   if (error)
523b5b ¤   ¤   ¤   return error;
c19371 ¤   }
8f2d68 ¤   return( kPGPError_NoErr );
a2efe6 }
f2af5a
f2f1ae static PGPError
7b827b ForceFlush(AddHdrContext *context)
9abb36 {
0687a6 ¤   PGPError¤   error;
29f439 ¤   int bufl, flushed;
2eaf5a
9b49b8 ¤   while (context->buflen) {
2ebc08 ¤   ¤   /* First, flush out any mid-flush we might have */
9daf5a
89c3f7 ¤   ¤   bufl = context->buflen;
bdca8c ¤   ¤   flushed = context->midflush;
a92916 ¤   ¤   context->buflen = context->midflush;
14af5a
cb9326 ¤   ¤   error = FlushBuffer(context);
c9af5a
a08948 ¤   ¤   flushed -= context->buflen;
8e0815 ¤   ¤   context->midflush = context->buflen;
b34ea8 ¤   ¤   context->buflen = bufl - flushed;
f9af5a
e7e3c2 ¤   ¤   if (error)
8c3b5b ¤   ¤   ¤   return error;
35af5a
b51b17 ¤   ¤   /*
e662ec ¤   ¤   ·* Now, figure out how much should be sent in the
7c3851 ¤   ¤   ·* next sub-packet
319de3 ¤   ¤   ·*/
811067 ¤   ¤   bufl = NumToBits(context->buflen);
2ce00d ¤   ¤   if (bufl < 0)
cdcdcb ¤   ¤   ¤   break;
fcaf5a
917d18 ¤   ¤   context->bufptr--;
2061e3 ¤   ¤   context->buflen++;
2c3b98 ¤   ¤   *(context->bufptr) = 0xE0 + bufl;
48c874 ¤   ¤   context->midflush = (2^bufl) + 1;
1a9371 ¤   }
8faf5a
5a2d68 ¤   return( kPGPError_NoErr );
07efe6 }
32af5a
91f1ae static PGPError
--b0e7 0005ebfd218401001b6 Page 3 of pgpAddHdr.c
e15cec DoFlush(AddHdrContext *context)
8bbb36 {
2b5b01 ¤   PGPError¤   error = kPGPError_NoErr;
a96c75 ¤   size_t retlen;
5b8b0f ¤   PGPByte const *p;
dd875f ¤   PGPSize len;
c5af5a
6c70a8 ¤   error = FlushHeader(context);
db0161 ¤   if (error)
61fcee ¤   ¤   return error;
4aaf5a
7ca197 ¤   /* Next, try to flush anything that we have buffered in the fifo */
ff6160 ¤   p = pgpFifoPeek (context->fifod, context->fifo, &len);
8a85aa ¤   while (len) {
c33c2e ¤   ¤   retlen = context->tail->write(context->tail,
9c24b0 ¤   ¤   ¤   ¤   ¤   ·······p, len, &error);
4402cd ¤   ¤   pgpFifoSeek (context->fifod, context->fifo, retlen);
04e3c2 ¤   ¤   if (error)
333b5b ¤   ¤   ¤   return error;
e71b52 ¤   ¤
576182 ¤   ¤   p = pgpFifoPeek (context->fifod, context->fifo, &len);
c19371 ¤   }
b1c674 ¤   return error;
baefe6 }
98af5a
27f1ae static PGPError
6cc966 Flush(PGPPipeline *myself)
c3bb36 {
c03b82 ¤   AddHdrContext *context;
b387a6 ¤   PGPError¤   error;
1caf5a
e0b81b ¤   pgpAssert(myself);
d48f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
34af5a
cd845d ¤   context = (AddHdrContext *)myself->priv;
03213c ¤   pgpAssert(context);
20bdf0 ¤   pgpAssert(context->tail);
e8af5a
aa5db4 ¤   if (context->buffer) {
df9fdb ¤   ¤   error = FlushHeader(context);
86e3c2 ¤   ¤   if (error)
333b5b ¤   ¤   ¤   return error;
adaf5a
5207bf ¤   ¤   /* Using the new packets -- force a flush of the buffer */
bbbd33 ¤   ¤   if (context->dowrite) {
d5afc8 ¤   ¤   ¤   error = FlushBuffer(context);
24d82b ¤   ¤   ¤   if (error)
46b20f ¤   ¤   ¤   ¤   return error;
7a45a6 ¤   ¤   } else {
b3a103 ¤   ¤   ¤   error = ForceFlush(context);
01d82b ¤   ¤   ¤   if (error)
97b20f ¤   ¤   ¤   ¤   return error;
380fe4 ¤   ¤   }
ebaf5a
48f037 ¤   } else {
b21c0b ¤   ¤   /* Using the fifo */
7baf5a
260b88 ¤   ¤   if (!context->dowrite)
c7a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
86af5a
d042d1 ¤   ¤   error = DoFlush(context);
5ce3c2 ¤   ¤   if (error)
273b5b ¤   ¤   ¤   return error;
8b9371 ¤   }
9aaf5a
6ad780 ¤   return context->tail->flush(context->tail);
0befe6 }
d3af5a
66cb0f /* Only called after args are checked, so I don't have to check them */
895d09 static size_t
9fd065 BufferWrite(PGPPipeline *myself, PGPByte const *buf, size_t size,
5efb43 ¤   ·····PGPError *error)
--a28d 0008d4ebedd401001b6 Page 4 of pgpAddHdr.c
2cbb36 {
c03b82 ¤   AddHdrContext *context;
686d88 ¤   size_t size0 = size;
2f314e ¤   int t;
d2af5a
18b81b ¤   pgpAssert(myself);
368f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
f34ca3 ¤   pgpAssert(error);
1eaf5a
5b845d ¤   context = (AddHdrContext *)myself->priv;
0b213c ¤   pgpAssert(context);
01bdf0 ¤   pgpAssert(context->tail);
9b7c78 ¤   pgpAssert(context->buffer);
b5af5a
e53778 ¤   *error = FlushHeader(context);
a75842 ¤   if (*error)
23bbde ¤   ¤   return 0;
71af5a
1443ab ¤   do {
b4df3b ¤   ¤   /* If we are in the middle of a block, flush it out */
e1bd33 ¤   ¤   if (context->dowrite) {
39743a ¤   ¤   ¤   *error = FlushBuffer(context);
eab5c5 ¤   ¤   ¤   if (*error)
d3f622 ¤   ¤   ¤   ¤   break;
68af5a
cd9841 ¤   ¤   ¤   context->dowrite = 0;
77614f ¤   ¤   ¤   context->bufptr = context->buffer + 2;
055d47 ¤   ¤   ¤   context->bufwrite = context->bufptr;
3f0fe4 ¤   ¤   }
9faf5a
d3c81c ¤   ¤   /* Try to fill up the buffer */
7e250a ¤   ¤   t = pgpMin(((size_t)(BUFFER_SIZE - context->buflen)), size);
236910 ¤   ¤   if (t) {
977a13 ¤   ¤   ¤   memcpy(context->bufwrite, buf, t);
f31652 ¤   ¤   ¤   buf += t;
8504f4 ¤   ¤   ¤   size -= t;
4d1439 ¤   ¤   ¤   context->bufwrite += t;
12ad4e ¤   ¤   ¤   context->buflen += t;
8d0fe4 ¤   ¤   }
71af5a
9b1b17 ¤   ¤   /*
b7e75e ¤   ¤   ·* If we have a full block, write out the length
161d27 ¤   ¤   ·* and then write out the block
f09de3 ¤   ¤   ·*/
408e11 ¤   ¤   if (context->buflen == BUFFER_SIZE) {
f5c29d ¤   ¤   ¤   context->dowrite = 1;
326930 ¤   ¤   ¤   context->bufptr--;
be75cb ¤   ¤   ¤   context->buflen++;
4da7b4 ¤   ¤   ¤   *(context->bufptr) = 0xE0 + BLOCK_SIZE;
78af5a
9817f5 ¤   ¤   ¤   continue;
e10fe4 ¤   ¤   }
6baf5a
970fea ¤   } while (size);
caaf5a
edb5d3 ¤   return size0 - size;
19efe6 }
d2af5a
a05d09 static size_t
af2e8a Write(PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
bcbb36 {
b53b82 ¤   AddHdrContext *context;
53af5a
e6b81b ¤   pgpAssert(myself);
c68f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
5c4ca3 ¤   pgpAssert(error);
30af5a
ed845d ¤   context = (AddHdrContext *)myself->priv;
cf213c ¤   pgpAssert(context);
6dbdf0 ¤   pgpAssert(context->tail);
4651eb ¤   pgpAssert(context->fifo);
8daf5a
--6258 00026638252401001b6 Page 5 of pgpAddHdr.c
258cfe ¤   if (!context->dowrite) {
40a711 ¤   ¤   /* Buffer into the fifo until we get a sizeadvise */
1daf5a
1f1c4a ¤   ¤   return pgpFifoWrite (context->fifod, context->fifo, buf, size);
9b9371 ¤   }
a9af5a
00d8af ¤   /*
d3d0f1 ¤   ·* Ok, we've been given our size. ·Flush the fifo and then be
cbbf02 ¤   ·* a write-through
b7a4e3 ¤   ·*/
77d7fd ¤   *error = DoFlush(context);
985842 ¤   if (*error)
55bbde ¤   ¤   return 0;
90b48b ¤   if (context->sizeknown && size > context->bytes) {
837036 ¤   ¤   pgpAssert(0);
68fc41 ¤   ¤   *error = kPGPError_SizeAdviseFailure;
d0bbde ¤   ¤   return 0;
959371 ¤   }
86af5a
4ef2d6 ¤   size = context->tail->write(context->tail, buf, size, error);
a9fe03 ¤   context->bytes -= size;
e0f6fa ¤   return size;
8eefe6 }
9baf5a
b7f1ae static PGPError
254ddc Annotate(PGPPipeline *myself, PGPPipeline *origin, int type,
42b0b1 ¤   ··PGPByte const *string, size_t size)
cfbb36 {
0d3b82 ¤   AddHdrContext *context;
4a87a6 ¤   PGPError¤   error;
caaf5a
7db81b ¤   pgpAssert(myself);
f88f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
ddaf5a
ac845d ¤   context = (AddHdrContext *)myself->priv;
f1213c ¤   pgpAssert(context);
89bdf0 ¤   pgpAssert(context->tail);
88af5a
55f9ef ¤   error = context->tail->annotate(context->tail, origin, type,
da3153 ¤   ¤   ¤   ¤   ¤   string, size);
8cff2e ¤   if (!error)
5e6467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
3404c8 ¤   pgpAssert(context->scope_depth != -1);
eac674 ¤   return error;
9befe6 }
c8af5a
4df1ae static PGPError
286aa7 BufferSizeAdvise(PGPPipeline *myself, unsigned long size)
4abb36 {
b73b82 ¤   AddHdrContext *context;
8487a6 ¤   PGPError¤   error;
4c4ba4 ¤   int i;
13af5a
55b81b ¤   pgpAssert(myself);
198f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
13af5a
d8845d ¤   context = (AddHdrContext *)myself->priv;
e3213c ¤   pgpAssert(context);
88bdf0 ¤   pgpAssert(context->tail);
487c78 ¤   pgpAssert(context->buffer);
49af5a
ca6143 ¤   /* Do not pass non-zero sizeAdvise -- I can't do that! */
90491d ¤   if (size || context->scope_depth)
c2a117 ¤   ¤   return( kPGPError_NoErr );
50af5a
7788c9 ¤   /* Okay, we're at end of input. */
517793 ¤   if (context->buflen) {
0be5d1 ¤   ¤   /* We have a bug when file length is zero; we get here without having
08871b ¤   ¤   ·* flushed the header. ·We can't easily distinguish between a zero
948a5f ¤   ¤   ·* length file and the EOF sizeadvise, but we don't need to.
fe9de3 ¤   ¤   ·*/
269fdb ¤   ¤   error = FlushHeader(context);
--111c 000fabf877e401001b6 Page 6 of pgpAddHdr.c
c8e3c2 ¤   ¤   if (error)
fb3b5b ¤   ¤   ¤   return error;
c9bd33 ¤   ¤   if (context->dowrite) {
aaafc8 ¤   ¤   ¤   error = FlushBuffer(context);
0ccdde ¤   ¤   } else if (context->midflush) {
8aa103 ¤   ¤   ¤   error = ForceFlush(context);
3745a6 ¤   ¤   } else {
6b7069 ¤   ¤   ¤   i = context->buflen;
257da8 ¤   ¤   ¤   if (PKTLEN_ONE_BYTE(i)) {
4ce54f ¤   ¤   ¤   ¤   context->bufptr--;
18f9b4 ¤   ¤   ¤   ¤   context->buflen++;
d22337 ¤   ¤   ¤   ¤   context->bufptr[0] = PKTLEN_1BYTE(i);
b1042d ¤   ¤   ¤   } else {
5153fc ¤   ¤   ¤   ¤   context->bufptr -= 2;
559292 ¤   ¤   ¤   ¤   context->buflen += 2;
826fdc ¤   ¤   ¤   ¤   context->bufptr[0] = PKTLEN_BYTE0(i);
40c2aa ¤   ¤   ¤   ¤   context->bufptr[1] = PKTLEN_BYTE1(i);
f1a3a6 ¤   ¤   ¤   }
ce5a88 ¤   ¤   ¤   context->midflush = context->buflen;
f5a103 ¤   ¤   ¤   error = ForceFlush(context);
850fe4 ¤   ¤   }
cae3c2 ¤   ¤   if (error)
ea3b5b ¤   ¤   ¤   return error;
6b9371 ¤   }
e867c5 ¤
ef9465 ¤   return context->tail->sizeAdvise(context->tail, 0);
5defe6 }
e3af5a
49f1ae static PGPError
6f065b SizeAdvise(PGPPipeline *myself, unsigned long len)
28bb36 {
313b82 ¤   AddHdrContext *context;
b466a2 ¤   unsigned long size;
8487a6 ¤   PGPError¤   error;
344ba4 ¤   int i;
4daf5a
a2b81b ¤   pgpAssert(myself);
a18f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
84af5a
c8845d ¤   context = (AddHdrContext *)myself->priv;
50213c ¤   pgpAssert(context);
7ebdf0 ¤   pgpAssert(context->tail);
2f51eb ¤   pgpAssert(context->fifo);
24af5a
03cc58 ¤   if (context->scope_depth)
62d65f ¤   ¤   return( kPGPError_NoErr );¤ /* Can't pass it through */
e5af5a
3fd8af ¤   /*
cf698e ¤   ·* The actual size myself module will output is the byte size
0ff7ee ¤   ·* passed in (size), plus the size of the buffered header,
a195a9 ¤   ·* plus the size of the data in the fifo. ·However the packet
3fd5ed ¤   ·* size does not include the header size, so add in the header
7ba836 ¤   ·* size after we compute the header.
f4a4e3 ¤   ·*/
3baf5a
9dd8af ¤   /*
a99f30 ¤   ·* Set the header packet up properly, if we haven't already
8ae5fc ¤   ·* done so. ·We know how long the length-of-length should be,
e5c552 ¤   ·* so fill that many bytes of the header in MSB-first order.
57a4e3 ¤   ·*/
cb8cfe ¤   if (!context->dowrite) {
58410e ¤   ¤   size = len + pgpFifoSize (context->fifod, context->fifo);
1267c5 ¤
b733f0 ¤   ¤   i = PKTBYTE_LLEN(context->header[0]);
1a66a8 ¤   ¤   if (size >= 0x10000 && i <= 2)
3fc9cd ¤   ¤   ¤   i = 2;
f7348b ¤   ¤   else if (size >= 0x100 && i <= 1)
1d26a9 ¤   ¤   ¤   i = 1;
ca01f6 ¤   ¤   context->header[0] = (context->header[0] & ~3) | i;
67af5a
f185ad ¤   ¤   i = LLEN_TO_BYTES(i);
fa6454 ¤   ¤   context->hdrlen = i+1;
--7f95 0007ba2be01401001b6 Page 7 of pgpAddHdr.c
87b0f4 ¤   ¤   while (i--) {
fab65b ¤   ¤   ¤   context->header[i+1] = (PGPByte)(size & 0xff);
0a20ff ¤   ¤   ¤   size >>= 8;
8f0fe4 ¤   ¤   }
499371 ¤   }
0eaf5a
89bda3 ¤   if (!context->sizeknown) {
074248 ¤   ¤   context->bytes = len;
b3c065 ¤   ¤   context->sizeknown = 1;
31ca49 ¤   } else if (context->bytes != len) {
057011 ¤   ¤   return kPGPError_SizeAdviseFailure;
2f9371 ¤   }
9faf5a
41d8af ¤   /*
2baf58 ¤   ·* Now add in the header size, sizeAdvise the next module, and
8e665b ¤   ·* if everything is ok, set the state to dowrite and flush.
6027a5 ¤   ·*/¤ ··
04e85a ¤   size = len + pgpFifoSize (context->fifod, context->fifo)
c81fa9 ¤   ¤   + context->hdrlen;
6f8539 ¤   error = context->tail->sizeAdvise(context->tail, size);
220161 ¤   if (error)
49fcee ¤   ¤   return error;
a9af5a
437cc1 ¤   context->dowrite = 1;
90af5a
6775d9 ¤   error = DoFlush(context);
5dd8af ¤   /*
9a2ba9 ¤   ·* Just in case we got a sizeAdvise(0) without anything else.
f78aed ¤   ·* calling sizeAdvise(0) twice is ok!
08a4e3 ¤   ·*/
a6dcde ¤   if (!error && !len)
508125 ¤   ¤   error = context->tail->sizeAdvise(context->tail, 0);
39af5a
5cc674 ¤   return error;
8cefe6 }
27af5a
4cf1ae static PGPError
ecbf01 Teardown(PGPPipeline *myself)
b7bb36 {
fe3b82 ¤   AddHdrContext *context;
4be9fa ¤   PGPContextRef¤  cdkContext;
7067c5 ¤
5d3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
63696e ¤   cdkContext¤ = myself->cdkContext;
07af5a
4fb81b ¤   pgpAssert(myself);
3e8f1d ¤   pgpAssert(myself->magic == ADDHEADERMAGIC);
aaaf5a
57845d ¤   context = (AddHdrContext *)myself->priv;
c8213c ¤   pgpAssert(context);
46af5a
b5cb05 ¤   if (context->tail)
e45c22 ¤   ¤   context->tail->teardown(context->tail);
8baf5a
b4865e ¤   if (context->fifo)
2b2c04 ¤   ¤   pgpFifoDestroy (context->fifod, context->fifo);
aaaf5a
e45db4 ¤   if (context->buffer) {
d29f50 ¤   ¤   pgpClearMemory(context->buffer, BUFFER_SIZE+2);
10a4fd ¤   ¤   pgpContextMemFree( cdkContext, context->buffer);
eb9371 ¤   }
6367c5 ¤
71dd40 ¤   pgpClearMemory(context, sizeof(*context));
89fa6e ¤   pgpContextMemFree( cdkContext, context);
0467c5 ¤
ba151e ¤   return kPGPError_NoErr;
98efe6 }
31af5a
dc41cd PGPPipeline **
5e9241 pgpAddHeaderCreate(
e258f9 ¤   PGPContextRef¤  ¤   cdkContext,
7b0d82 ¤   PGPPipeline **¤ ¤   head,
--b646 0003606dfd8401001b6 Page 8 of pgpAddHdr.c
10e786 ¤   PgpVersion¤ ¤   ¤   vers,
e7f138 ¤   PGPFifoDesc const *¤fd,
6b3b41 ¤   PGPByte¤¤   ¤   ¤   pkttype,
b97430 ¤   PGPByte llen,
267f86 ¤   PGPByte *hdr,
80e0ad ¤   size_t headerlen)
dcbb36 {
ce0df0 ¤   PGPPipeline *mod;
af34fe ¤   PGPFifoContext *fifop = NULL;
f33b82 ¤   AddHdrContext *context;
308d7c ¤   PGPByte *buf = NULL;
f5fb86 ¤   PGPByte pktbite;
f3af5a
74bb3d ¤   if (!head)
577ed2 ¤   ¤   return NULL;
87af5a
6c8ce3 ¤   pgpAssert(fd);
baaf5a
b61d2a ¤   /* XXX If we have versions > 2.6, ignore llen */
1c0fd5 ¤   if (vers > PGPVERSION_3)
ab802b ¤   ¤   pktbite = PKTBYTE_BUILD_NEW(pkttype);
9a0e24 ¤   else
0484c6 ¤   ¤   pktbite = PKTBYTE_BUILD(pkttype, llen);
58af5a
d0c033 ¤   context = (AddHdrContext *)pgpContextMemAlloc( cdkContext,
f1afb2 ¤   ¤   sizeof(*context), kPGPMemoryMgrFlags_Clear );
9e1ea4 ¤   if (!context)
0f7ed2 ¤   ¤   return NULL;
539228 ¤   mod = &context->pipe;
0daf5a
6a1203 ¤   if (vers > PGPVERSION_3) {
0b74dc ¤   ¤   buf = (PGPByte *)pgpContextMemAlloc( cdkContext,
7cbe19 ¤   ¤   ¤   BUFFER_SIZE + 2, kPGPMemoryMgrFlags_Clear);
6ba1f5 ¤   ¤   if (!buf) {
adfbe8 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context);
5ccf03 ¤   ¤   ¤   return NULL;
350fe4 ¤   ¤   }
116c7f ¤   ¤   memcpy(buf+2, hdr, headerlen);
53af5a
c8f037 ¤   } else {
c7631a ¤   ¤   fifop = pgpFifoCreate ( cdkContext, fd);
44a192 ¤   ¤   if (!fifop) {
d3fbe8 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context);
99cf03 ¤   ¤   ¤   return NULL;
7a0fe4 ¤   ¤   }
7daf5a
1c7b68 ¤   ¤   if (pgpFifoWrite (fd, fifop, hdr, headerlen) != headerlen) {
65fbe8 ¤   ¤   ¤   pgpContextMemFree( cdkContext, context);
e0b126 ¤   ¤   ¤   pgpFifoDestroy (fd, fifop);
a2cf03 ¤   ¤   ¤   return NULL;
0d0fe4 ¤   ¤   }
7c9371 ¤   }
d2af5a
211003 ¤   mod->magic = ADDHEADERMAGIC;
a6ac4e ¤   mod->flush = Flush;
871f83 ¤   mod->write = Write;
ea0aaf ¤   mod->sizeAdvise = SizeAdvise;
cfd3a2 ¤   mod->annotate = Annotate;
9796de ¤   mod->teardown = Teardown;
52e421 ¤   mod->name = "Add Header Module";
c301ea ¤   mod->priv = context;
3aa99e ¤   mod->cdkContext¤= cdkContext;
2eaf5a
91c8c9 ¤   if (buf) {
39fc91 ¤   ¤   mod->write = BufferWrite;
705eb7 ¤   ¤   mod->sizeAdvise = BufferSizeAdvise;
cf9371 ¤   }
36af5a
96ae49 ¤   context->fifod = fd;
ff32cc ¤   context->fifo = fifop;
a41427 ¤   context->ptr = context->header;
36274d ¤   context->header[0] = pktbite;
--aef7 00199b0b608401001b6 Page 9 of pgpAddHdr.c
06387f ¤   context->hdrlen = 1;
c1fcf4 ¤   context->version = vers;
aab675 ¤   context->buffer = buf;
459fe8 ¤   context->bufptr = buf + 2;
ee8d08 ¤   context->bufwrite = context->bufptr + headerlen;
b1af5a
b80fd5 ¤   if (vers > PGPVERSION_3)
f1e8a8 ¤   ¤   context->buflen = headerlen;
02d56c ¤   else if (llen == 3)
f3f595 ¤   ¤   context->dowrite = 1;
5967c5 ¤
2565ad ¤   context->tail = *head;
2e2d11 ¤   *head = mod;
817fa2 ¤   return &context->tail;
99efe6 }
--3d28 001cc34648f401001b7 Page 1 of pgpAddHdr.h
bc38e5 /*
e439e5 ·* pgpAddHdr.h -- header file for a module to add a packet header.
d9775e ·*
417ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
5f775e ·*
64e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
f92979 ·* You should not be using these functions in an application.
f7775e ·*
466017 ·* $Id: pgpAddHdr.h,v 1.7 1997/06/25 19:40:19 lloyd Exp $
2e495d ·*/
cdaf5a
7ae82c #include "pgpPubTypes.h"
a4adb8 #include "pgpOpaqueStructs.h"
ebd11f #include "pgpUsuals.h"
92af5a
6899c6 PGP_BEGIN_C_DECLARATIONS
c9af5a
4d41cd PGPPipeline **
57c2c8 pgpAddHeaderCreate ( PGPContextRef cdkContext,
478123 ¤   ¤   ¤   PGPPipeline **head, PgpVersion version,
e2319e ¤   ¤   ····PGPFifoDesc const *fd, PGPByte pkttype, PGPByte llen,
86935c ¤   ¤   ····PGPByte *header, size_t hdrlen);
f1af5a
cc1254 PGP_END_C_DECLARATIONS
--519f 0007f0a1dcf401001b8 Page 1 of pgpBufMod.c
bc38e5 /*
c19781 ·* pgpBufMod.c -- A Buffering Module; buffer until the first sizeAdvise
f4775e ·*
fc7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
21775e ·*
b22b63 ·* $Id: pgpBufMod.c,v 1.26 1997/12/12 01:14:14 heller Exp $
23495d ·*/
f6e2ff #include "pgpConfig.h"
cc0d08 #include "pgpMem.h"
efaf5a
c6feb2 #include <stdio.h>
2f324c #include <string.h>
4eaf5a
36a146 #include "pgpDebug.h"
4a6aaa #include "pgpAnnotate.h"
30910a #include "pgpFIFO.h"
da0d08 #include "pgpMem.h"
3f2f8d #include "pgpErrors.h"
f42ece #include "pgpPipeline.h"
5ec26c #include "pgpContext.h"
53e8f7 #include "pgpBufMod.h"
cdaf5a
91a760 #define kPGPBufModCmdArgSize¤   4096
deaf5a
4b38e5 /*
cea0a8 ·* This is a magic number for use within this module. ·It is used to
20e67a ·* make sure the passed-in module is a member of this type. ·Just a
1dc916 ·* little extra sanity-checking.
6c775e ·*
e2d7f0 ·* You should set this value to some "random" 32-bit number.
0f495d ·*/
15d83c ·
e8922c #define BUFMODMAGIC¤0xb3ffe43d
7faf5a
10f046 typedef struct BufModContext
86bb36 {
18f8fb ¤   PGPPipeline¤¤   pipe;
f167c5 ¤
3f2480 ¤   PGPFifoDesc const *fd;
c73566 ¤   PGPFifoContext *fifo;
0d855a ¤   PGPFifoContext *ann; /* Fifo to hold the saved annotations */
0175b0 ¤   PGPPipeline *tail;
5d1d6d ¤   PGPByte cmdarg[kPGPBufModCmdArgSize];
29ed70 ¤   unsigned cmdlen;
ef7929 ¤   int scope_depth;
a28e64 ¤   PGPByte writing;
2bd6a1 ¤   DEBUG_STRUCT_CONSTRUCTOR( BufModContext )
6dfc33 } BufModContext;
15af5a
9e38e5 /*
b26e26 ·* Buffer a command at the current spot in the data stream. ·This is only
13f4db ·* called when ctx->buffering is true. ·What it does is find the delta
2272eb ·* of this command in the data fifo from the last command in order to replay
0e290a ·* the commands at the proper place. ·It saves off context->written as
6c83bd ·* the offset and then resets the value to 0.
df775e ·*
2ee516 ·* The return value is 0 on success or an error code.
79775e ·*
128166 ·* Command Byte Syntax: <arglen><arg>
7c495d ·*/
d7f1ae static PGPError
cf7534 bufferCommand (BufModContext *ctx, const PGPByte *arg, unsigned arglen)
18bb36 {
dc2947 ¤   /* Make sure the command argument fits the buffer size */
b242ab ¤   if (arglen > sizeof (ctx->cmdarg))
3462b5 ¤   ¤   return kPGPError_BadParams;
65af5a
e56207 ¤   if (pgpFifoWrite (ctx->fd, ctx->ann, (PGPByte *)&arglen,
7e47ef ¤   ¤   ¤   ··sizeof (arglen)) != sizeof (arglen))
234030 ¤   ¤   return kPGPError_OutOfMemory;
09af5a
7f1ea3 ¤   if (pgpFifoWrite (ctx->fd, ctx->ann, arg, arglen) != arglen)
--9761 000a5bbe55c401001b8 Page 2 of pgpBufMod.c
c34030 ¤   ¤   return kPGPError_OutOfMemory;
e6af5a
ad2d68 ¤   return( kPGPError_NoErr );
cdefe6 }
d6af5a
6af84e /* Buffer up an annotation */
5af1ae static PGPError
efb632 bufferAnnotation (BufModContext *ctx, PGPPipeline *origin, int type,
c68974 ¤   ¤   ··PGPByte const *string, size_t size)
cabb36 {
754a61 ¤   PGPByte *arg, *argp;
cf1232 ¤   PGPError retval;
fc8060 ¤   PGPContextRef¤  ¤   cdkContext;
7caf5a
1d87ad ¤   pgpAssertAddrValid( origin, PGPPipeline );
e8ff14 ¤   cdkContext¤ = origin->cdkContext;
25af5a
e24017 ¤   arg = argp = (PGPByte *)
27331d ¤   ¤   pgpContextMemAlloc( cdkContext, sizeof (origin) + sizeof (type) +
97711e ¤   ¤   ¤   ¤   ¤   size + sizeof (size), 0);
ce30ee ¤   if (!arg)
f14030 ¤   ¤   return kPGPError_OutOfMemory;
3eaf5a
c1837e ¤   memcpy (argp, (PGPByte *)&origin, sizeof (origin));
a50bfc ¤   argp += sizeof (origin);
51af5a
2a7752 ¤   memcpy (argp, (PGPByte *)&type, sizeof (type));
293916 ¤   argp += sizeof (type);
1faf5a
7b23a3 ¤   memcpy (argp, (PGPByte *)&size, sizeof (size));
fff016 ¤   argp += sizeof (size);
bfaf5a
205afe ¤   memcpy (argp, string, size);
fb8201 ¤   argp += size;
4eaf5a
fd3127 ¤   retval = bufferCommand (ctx, arg, argp-arg);
682453 ¤   pgpContextMemFree( cdkContext, arg);
1d94b6 ¤   return retval;
cbefe6 }
b5af5a
63f1ae static PGPError
af46c0 parseAnnotation (BufModContext *ctx)
75bb36 {
ddcf07 ¤   PGPPipeline *origin;
1229f6 ¤   int type;
08e002 ¤   size_t size;
3c72d5 ¤   PGPByte *string, *argp = ctx->cmdarg;
fc1232 ¤   PGPError retval;
b64351 ¤   PGPContextRef¤  cdkContext¤ = ctx->pipe.cdkContext;
b3af5a
6b0a7f ¤   pgpAssert (ctx->cmdlen >= sizeof (origin) + sizeof (type) +
dfb1e4 ¤   ¤   sizeof (size));
6caf5a
0a6950 ¤   pgpCopyMemory ( argp, (PGPByte *)&origin, sizeof (origin));
630bfc ¤   argp += sizeof (origin);
cbaf5a
ff7e7b ¤   pgpCopyMemory ( argp, (PGPByte *)&type, sizeof (type));
5b3916 ¤   argp += sizeof (type);
e8af5a
f22a8a ¤   pgpCopyMemory ( argp, (PGPByte *)&size, sizeof (size));
05f016 ¤   argp += sizeof (size);
8eaf5a
870c72 ¤   /* make sure we have the right number of bytes remaining */
72139e ¤   pgpAssert (ctx->cmdlen - size == (unsigned)(argp - ctx->cmdarg));
f3af5a
a14eba ¤   string = (PGPByte *)pgpContextMemAlloc( cdkContext, size, 0);
c7c643 ¤   if (string == NULL)
a04030 ¤   ¤   return kPGPError_OutOfMemory;
97af5a
e9d0b8 ¤   pgpCopyMemory (argp, string, size);
b0af5a
a5d4dd ¤   retval = ctx->tail->annotate (ctx->tail, origin, type, string, size);
--a068 0006f360a82401001b8 Page 3 of pgpBufMod.c
e0af5a
2e3598 ¤   pgpContextMemFree( cdkContext, string);
8794b6 ¤   return retval;
5befe6 }
47af5a
f90dc6 /* <len><cmd> */
20f1ae static PGPError
c931a7 flushCommands (BufModContext *ctx)
ddbb36 {
1c87a6 ¤   PGPError¤   error;
105f73 ¤   unsigned cmdlen = pgpFifoSize (ctx->fd, ctx->ann);
94af5a
ef43ab ¤   do {
1d107d ¤   ¤   if (ctx->cmdlen) {
758511 ¤   ¤   ¤   error = parseAnnotation (ctx);
10d82b ¤   ¤   ¤   if (error)
14b20f ¤   ¤   ¤   ¤   return error;
db87c7 ¤   ¤   ¤
e46f69 ¤   ¤   ¤   ctx->cmdlen = 0;
3b0fe4 ¤   ¤   }
9caf5a
83036c ¤   ¤   if (cmdlen) {¤  ¤   ¤
9dec37 ¤   ¤   ¤   if (pgpFifoRead (ctx->fd, ctx->ann,
e94eed ¤   ¤   ¤   ¤   ¤   ·(PGPByte *)&ctx->cmdlen,
bc2612 ¤   ¤   ¤   ¤   ¤   ·sizeof (ctx->cmdlen)) !=
b4e9c6 ¤   ¤   ¤   ····sizeof (ctx->cmdlen))
18bc38 ¤   ¤   ¤   ¤   return kPGPError_FIFOReadError;
fe99e3 ¤   ¤   ¤   cmdlen -= sizeof (ctx->cmdlen);
b71b52 ¤   ¤
0b60b5 ¤   ¤   ¤   if (pgpFifoRead (ctx->fd, ctx->ann, ctx->cmdarg,
8ce175 ¤   ¤   ¤   ¤   ¤   ·ctx->cmdlen) != ctx->cmdlen)
e1bc38 ¤   ¤   ¤   ¤   return kPGPError_FIFOReadError;
ae1abb ¤   ¤   ¤   cmdlen -= ctx->cmdlen;
ac1b52 ¤   ¤
f70fe4 ¤   ¤   }
b5a733 ¤   } while (ctx->cmdlen);
56af5a
bc2d68 ¤   return( kPGPError_NoErr );
22efe6 }
3eaf5a
51f1ae static PGPError
aeb72c DoFlush (BufModContext *context)
61bb36 {
155b01 ¤   PGPError¤   error = kPGPError_NoErr;
79a617 ¤   PGPByte const *ptr;
586c75 ¤   size_t retlen;
e3875f ¤   PGPSize len;
cbaf5a
b30d14 ¤   /* first, flush out any commands */
79c93d ¤   error = flushCommands (context);
070161 ¤   if (error)
a2fcee ¤   ¤   return error;
f1af5a
65b797 ¤   ptr = pgpFifoPeek (context->fd, context->fifo, &len);
b185aa ¤   while (len) {
1e88b9 ¤   ¤   retlen = context->tail->write (context->tail,
b5b815 ¤   ¤   ¤   ¤   ¤   ·······ptr, len, &error);
262cf7 ¤   ¤   pgpFifoSeek (context->fd, context->fifo, retlen);
51e3c2 ¤   ¤   if (error)
4d3b5b ¤   ¤   ¤   return error;
521b52 ¤   ¤
305597 ¤   ¤   ptr = pgpFifoPeek (context->fd, context->fifo, &len);
cd9371 ¤   }
5caf5a
87c674 ¤   return error;
29efe6 }
f9af5a
c6f1ae static PGPError
37d02e Flush (PGPPipeline *myself)
6cbb36 {
979f59 ¤   BufModContext *context;
6f87a6 ¤   PGPError¤   error;
--72ac 00046b81654401001b8 Page 4 of pgpBufMod.c
e0af5a
7a29be ¤   pgpAssert (myself);
b7557a ¤   pgpAssert (myself->magic == BUFMODMAGIC);
9caf5a
ed2b6f ¤   context = (BufModContext *)myself->priv;
cfd30a ¤   pgpAssert (context);
95ebf4 ¤   pgpAssert (context->tail);
6baf5a
dc5633 ¤   if (!context->writing)
7eadbe ¤   ¤   return kPGPError_LazyProgrammer;¤   /* XXX */
eaaf5a
9a63fd ¤   error = DoFlush (context);
2b0161 ¤   if (error)
5afcee ¤   ¤   return error;
5baf5a
c59819 ¤   return context->tail->flush (context->tail);
2cefe6 }
81af5a
355d09 static size_t
6bf37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
7fbb36 {
849f59 ¤   BufModContext *context;
8caf5a
9529be ¤   pgpAssert (myself);
78557a ¤   pgpAssert (myself->magic == BUFMODMAGIC);
8c4866 ¤   pgpAssert (error);
afaf5a
c62b6f ¤   context = (BufModContext *)myself->priv;
e7d30a ¤   pgpAssert (context);
1bebf4 ¤   pgpAssert (context->tail);
ebaf5a
fb600e ¤   if (!context->writing) {
dba79e ¤   ¤   *error = kPGPError_NoErr;
17167a ¤   ¤   return pgpFifoWrite (context->fd, context->fifo, buf, size);
d99371 ¤   }
6a0479 ¤   *error = DoFlush (context);
1d5842 ¤   if (*error)
55bbde ¤   ¤   return 0;
5aaf5a
c2d39f ¤   return context->tail->write (context->tail, buf, size, error);
c5efe6 }
0caf5a
eaf1ae static PGPError
f613c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
6db0b1 ¤   ··PGPByte const *string, size_t size)
79bb36 {
9e9f59 ¤   BufModContext *context;
8687a6 ¤   PGPError¤   error;
78af5a
9829be ¤   pgpAssert (myself);
1d557a ¤   pgpAssert (myself->magic == BUFMODMAGIC);
5daf5a
1a2b6f ¤   context = (BufModContext *)myself->priv;
44d30a ¤   pgpAssert (context);
aeebf4 ¤   pgpAssert (context->tail);
94af5a
46600e ¤   if (!context->writing) {
e07824 ¤   ¤   /* Make sure there isn't any data buffered! */
aa0e98 ¤   ¤   pgpAssert (!pgpFifoSize (context->fd, context->fifo));
68af5a
7d5f47 ¤   ¤   error = bufferAnnotation (context, origin, type, string, size);
632be7 ¤   } else
1f2788 ¤   ¤   error = context->tail->annotate (context->tail, origin, type,
f51665 ¤   ¤   ¤   ¤   ¤   ¤   ·string, size);
9fff2e ¤   if (!error)
536467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
e804c8 ¤   pgpAssert(context->scope_depth != -1);
1bc674 ¤   return error;
32efe6 }
69af5a
2ff1ae static PGPError
464b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
--4923 00058b44867401001b8 Page 5 of pgpBufMod.c
2cbb36 {
1d9f59 ¤   BufModContext *context;
3a87a6 ¤   PGPError¤   error;
fdaf5a
5b29be ¤   pgpAssert (myself);
73557a ¤   pgpAssert (myself->magic == BUFMODMAGIC);
3caf5a
bc2b6f ¤   context = (BufModContext *)myself->priv;
3dd30a ¤   pgpAssert (context);
cfebf4 ¤   pgpAssert (context->tail);
2daf5a
c62dab ¤   context->writing = 1;
c563fd ¤   error = DoFlush (context);
9c0161 ¤   if (error)
77fcee ¤   ¤   return error;
60af5a
b0e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
8fefe6 }
88af5a
3ef1ae static PGPError
52c7e1 Teardown (PGPPipeline *myself)
25bb36 {
e39f59 ¤   BufModContext *context;
31e9fa ¤   PGPContextRef¤  cdkContext;
c467c5 ¤
1f3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
38696e ¤   cdkContext¤ = myself->cdkContext;
dbaf5a
2829be ¤   pgpAssert (myself);
dd557a ¤   pgpAssert (myself->magic == BUFMODMAGIC);
b2af5a
262b6f ¤   context = (BufModContext *)myself->priv;
a8d30a ¤   pgpAssert (context);
87af5a
bccb05 ¤   if (context->tail)
001e8a ¤   ¤   context->tail->teardown (context->tail);
96af5a
df8bb6 ¤   pgpFifoDestroy (context->fd, context->ann);
423cff ¤   pgpFifoDestroy (context->fd, context->fifo);
fb67c5 ¤
c5bad7 ¤   pgpClearMemory (context, sizeof (*context));
17fa6e ¤   pgpContextMemFree( cdkContext, context);
b867c5 ¤
a3151e ¤   return kPGPError_NoErr;
a5efe6 }
53af5a
8941cd PGPPipeline **
625e83 pgpBufferModCreate (
4cfdf9 ¤   PGPContextRef cdkContext,
3e8941 ¤   PGPPipeline **head,
2082a1 ¤   PGPFifoDesc const *fd)
a4bb36 {
350df0 ¤   PGPPipeline *mod;
879f59 ¤   BufModContext *context;
36f955 ¤   PGPFifoContext *fifo, *ann;
f0af5a
8011ed ¤   if (!head || !fd)
c67ed2 ¤   ¤   return NULL;
64af5a
698cf3 ¤   context = (BufModContext *)pgpContextMemAlloc( cdkContext,
064db0 ¤   ¤   sizeof (*context), kPGPMemoryMgrFlags_Clear );
941ea4 ¤   if (!context)
fb7ed2 ¤   ¤   return NULL;
189228 ¤   mod = &context->pipe;
59af5a
df8491 ¤   fifo = pgpFifoCreate (cdkContext, fd);
381c5f ¤   if (!fifo) {
47a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
de7ed2 ¤   ¤   return NULL;
2e9371 ¤   }
dd175a ¤   ann = pgpFifoCreate (cdkContext, fd);
58ab5d ¤   if (!ann) {
--a8f0 001cf5349fb401001b8 Page 6 of pgpBufMod.c
b355db ¤   ¤   pgpFifoDestroy (fd, fifo);
d3a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
517ed2 ¤   ¤   return NULL;
c89371 ¤   }
c9af5a
6630cc ¤   mod->magic = BUFMODMAGIC;
431f83 ¤   mod->write = Write;
b5ac4e ¤   mod->flush = Flush;
940aaf ¤   mod->sizeAdvise = SizeAdvise;
10d3a2 ¤   mod->annotate = Annotate;
6d96de ¤   mod->teardown = Teardown;
9dd0ce ¤   mod->name = "Buffer Module";
4b01ea ¤   mod->priv = context;
a5a99e ¤   mod->cdkContext¤= cdkContext;
3aaf5a
49f7da ¤   context->fd = fd;
62d5cd ¤   context->fifo = fifo;
d8eb2d ¤   context->ann = ann;
40af5a
ca65ad ¤   context->tail = *head;
ac2d11 ¤   *head = mod;
bf7fa2 ¤   return &context->tail;
cfefe6 }
--08ba 001867a9706401001b9 Page 1 of pgpBufMod.h
bc38e5 /*
86fc42 ·* pgpBufMod.h -- A Buffering Module; buffer until the first sizeAdvise
45775e ·*
f57ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
27775e ·*
36425d ·* $Id: pgpBufMod.h,v 1.9 1997/09/18 01:35:28 lloyd Exp $
e1495d ·*/
22af5a
450a51 #ifndef Included_pgpBufMod_h
448b67 #define Included_pgpBufMod_h
11af5a
45adb8 #include "pgpOpaqueStructs.h"
90af5a
b699c6 PGP_BEGIN_C_DECLARATIONS
2aaf5a
258df0 PGPPipeline ·**¤¤   pgpBufferModCreate ( PGPContextRef cdkContext,
855f93 ¤   ¤   ¤   ¤   ¤   ¤   PGPPipeline **head, PGPFifoDesc const *fd);
f8af5a
c51254 PGP_END_C_DECLARATIONS
b8af5a
86602a #endif /* Included_pgpBufMod_h */
--68ce 0009dd3c8cf401001ba Page 1 of pgpCopyMod.c
bc38e5 /*
ec66b8 ·* pgpCopyMod.c -- Module to copy input to output
88775e ·*
f37ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
f9775e ·*
7216a7 ·* $Id: pgpCopyMod.c,v 1.14 1997/12/12 01:14:15 heller Exp $
e8495d ·*/
84e2ff #include "pgpConfig.h"
f8af5a
b6feb2 #include <stdio.h>
48af5a
c9a146 #include "pgpDebug.h"
df0bbe #include "pgpCopyMod.h"
cb0d08 #include "pgpMem.h"
6e2ece #include "pgpPipeline.h"
05c26c #include "pgpContext.h"
bfaf5a
13e6ee #define COPYMODMAGIC¤   0xc09430d
66af5a
0f5d09 static size_t
832e8a Write(PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
debb36 {
e475b0 ¤   PGPPipeline *tail;
c4af5a
1fb81b ¤   pgpAssert(myself);
ec493c ¤   pgpAssert(myself->magic == COPYMODMAGIC);
754ca3 ¤   pgpAssert(error);
faaf5a
e8cf73 ¤   tail = *(PGPPipeline **)&myself->priv;
7b497a ¤   pgpAssert(tail);
b1af5a
6b2abc ¤   return tail->write(tail, buf, size, error);
a2efe6 }
22af5a
def1ae static PGPError
61c966 Flush(PGPPipeline *myself)
f5bb36 {
5275b0 ¤   PGPPipeline *tail;
a3af5a
b3b81b ¤   pgpAssert(myself);
e2493c ¤   pgpAssert(myself->magic == COPYMODMAGIC);
05af5a
01cf73 ¤   tail = *(PGPPipeline **)&myself->priv;
51497a ¤   pgpAssert(tail);
f2af5a
caed6b ¤   return tail->flush(tail);
7eefe6 }
c6af5a
c0f1ae static PGPError
474ddc Annotate(PGPPipeline *myself, PGPPipeline *origin, int type,
b4b0b1 ¤   ··PGPByte const *string, size_t size)
1cbb36 {
4175b0 ¤   PGPPipeline *tail;
97af5a
bfb81b ¤   pgpAssert(myself);
b7493c ¤   pgpAssert(myself->magic == COPYMODMAGIC);
11af5a
eccf73 ¤   tail = *(PGPPipeline **)&myself->priv;
a4497a ¤   pgpAssert(tail);
09af5a
1c1479 ¤   return tail->annotate(tail, origin, type, string, size);
5defe6 }
a4af5a
6bf1ae static PGPError
0399d0 SizeAdvise(PGPPipeline *myself, unsigned long bytes)
d3bb36 {
b475b0 ¤   PGPPipeline *tail;
52af5a
4bb81b ¤   pgpAssert(myself);
8b493c ¤   pgpAssert(myself->magic == COPYMODMAGIC);
e2af5a
9dcf73 ¤   tail = *(PGPPipeline **)&myself->priv;
--e8c7 0017f2e646e401001ba Page 2 of pgpCopyMod.c
79497a ¤   pgpAssert(tail);
deaf5a
665bc1 ¤   return tail->sizeAdvise(tail, bytes);
27efe6 }
d1af5a
60f1ae static PGPError
e5bf01 Teardown(PGPPipeline *myself)
d7bb36 {
09f5c7 ¤   PGPPipeline *¤  ¤   tail;
75e9fa ¤   PGPContextRef¤  cdkContext;
2567c5 ¤
1d3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
45696e ¤   cdkContext¤ = myself->cdkContext;
87af5a
5ab81b ¤   pgpAssert(myself);
45493c ¤   pgpAssert(myself->magic == COPYMODMAGIC);
ddaf5a
dfcf73 ¤   tail = *(PGPPipeline **)&myself->priv;
e84e1a ¤   if (tail)
bac388 ¤   ¤   tail->teardown(tail);
3faf5a
724836 ¤   pgpClearMemory( myself, ·sizeof(*myself));
da0f16 ¤   pgpContextMemFree( cdkContext, myself);
1067c5 ¤
90151e ¤   return kPGPError_NoErr;
77efe6 }
a6af5a
8441cd PGPPipeline **
4d1d26 pgpCopyModCreate(
6dfdf9 ¤   PGPContextRef cdkContext,
eef7f9 ¤   PGPPipeline **head)
82bb36 {
a30df0 ¤   PGPPipeline *mod;
29af5a
bcbb3d ¤   if (!head)
8a7ed2 ¤   ¤   return NULL;
70af5a
23ea91 ¤   mod = (PGPPipeline *)pgpContextMemAlloc( cdkContext,
e6c15d ¤   ¤   sizeof(*mod), kPGPMemoryMgrFlags_Clear);
ede094 ¤   if (!mod)
d07ed2 ¤   ¤   return NULL;
f4af5a
303c91 ¤   mod->magic = COPYMODMAGIC;
541f83 ¤   mod->write = Write;
d6ac4e ¤   mod->flush = Flush;
ff0aaf ¤   mod->sizeAdvise = SizeAdvise;
8fd3a2 ¤   mod->annotate = Annotate;
2e96de ¤   mod->teardown = Teardown;
3ce31c ¤   mod->name = "Copy Module";
82e151 ¤   mod->priv = *head;
e0a99e ¤   mod->cdkContext¤= cdkContext;
8eaf5a
5e2d11 ¤   *head = mod;
e1af5a
dba01e ¤   return (PGPPipeline **)&mod->priv;
b9efe6 }
d0af5a
a77e4d /*__Editor_settings____
0caf5a
d64126 ¤   Local Variables:
e77b17 ¤   tab-width: 4
640e6c ¤   End:
d35f8c ¤   vi: ts=4 sw=4
859e9b ¤   vim: si
7fd062 _____________________*/
--0813 001e8cdcbc5401001bb Page 1 of pgpCopyMod.h
bc38e5 /*
f396d5 ·* pgpCopyMod.h -- Copy the input directly to the output.
bf775e ·*
e77ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
e4775e ·*
cff6e7 ·* $Id: pgpCopyMod.h,v 1.6 1997/06/25 19:40:23 lloyd Exp $
9d495d ·*/
98af5a
3a3e59 #ifndef Included_pgpCopyMod_h
146a6d #define Included_pgpCopyMod_h
0eaf5a
6a99c6 PGP_BEGIN_C_DECLARATIONS
1daf5a
0dadb8 #include "pgpOpaqueStructs.h"
83e82c #include "pgpPubTypes.h"
3aaf5a
eaaf5a
39a5f5 PGPPipeline **pgpCopyModCreate ( PGPContextRef cdkContext, PGPPipeline **head);
c6af5a
c91254 PGP_END_C_DECLARATIONS
81af5a
e8e0f5 #endif /* Included_pgpCopyMod_h */
--bc50 0006cc8a3fb401001bc Page 1 of pgpDevNull.c
bc38e5 /*
d370c0 ·* pgpDevNull.c -- sink module to eat all input.
01775e ·*
8b7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
3d775e ·*
958775 ·* $Id: pgpDevNull.c,v 1.13 1997/12/12 01:14:16 heller Exp $
3a495d ·*/
f1e2ff #include "pgpConfig.h"
0daf5a
18feb2 #include <stdio.h>
a3af5a
76a146 #include "pgpDebug.h"
6c115d #include "pgpDevNull.h"
640d08 #include "pgpMem.h"
202ece #include "pgpPipeline.h"
38c26c #include "pgpContext.h"
beaf5a
4646fd #define DEVNULLMAGIC¤   0xde557711
adaf5a
535d09 static size_t
53f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
97bb36 {
9bb81b ¤   pgpAssert(myself);
e9e7ae ¤   pgpAssert(myself->magic == DEVNULLMAGIC);
c0af5a
0827fd ¤   /* To shut up compiler warnings */
b9b3cc ¤   (void)myself;
76c6a9 ¤   (void)buf;
33af5a
424ca3 ¤   pgpAssert(error);
9a9096 ¤   *error = kPGPError_NoErr;
79af5a
23f6fa ¤   return size;
21efe6 }
81af5a
b8f1ae static PGPError
04d02e Flush (PGPPipeline *myself)
edbb36 {
8db81b ¤   pgpAssert(myself);
65e7ae ¤   pgpAssert(myself->magic == DEVNULLMAGIC);
33af5a
ff27fd ¤   /* To shut up compiler warnings */
5bb3cc ¤   (void)myself;
09af5a
2e2d68 ¤   return( kPGPError_NoErr );
06efe6 }
dbaf5a
c3f1ae static PGPError
6c13c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
37b0b1 ¤   ··PGPByte const *string, size_t size)
b8bb36 {
a8b81b ¤   pgpAssert(myself);
a1e7ae ¤   pgpAssert(myself->magic == DEVNULLMAGIC);
f2af5a
4a27fd ¤   /* To shut up compiler warnings */
51b3cc ¤   (void)myself;
5c1b82 ¤   (void)origin;
a40e94 ¤   (void)type;
85e647 ¤   (void)string;
067aab ¤   (void)size;
04af5a
492d68 ¤   return( kPGPError_NoErr );
a8efe6 }
86af5a
f9f1ae static PGPError
de4b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
7bbb36 {
acb81b ¤   pgpAssert(myself);
c4e7ae ¤   pgpAssert(myself->magic == DEVNULLMAGIC);
80af5a
6127fd ¤   /* To shut up compiler warnings */
6cb3cc ¤   (void)myself;
--3167 001684bf388401001bc Page 2 of pgpDevNull.c
24d223 ¤   (void)bytes;
4baf5a
ab2d68 ¤   return( kPGPError_NoErr );
cfefe6 }
07af5a
d2f1ae static PGPError
25c7e1 Teardown (PGPPipeline *myself)
48bb36 {
6be9fa ¤   PGPContextRef¤  cdkContext;
0967c5 ¤
0c3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
dc696e ¤   cdkContext¤ = myself->cdkContext;
4c67c5 ¤
29b81b ¤   pgpAssert(myself);
92e7ae ¤   pgpAssert(myself->magic == DEVNULLMAGIC);
30af5a
5b251e ¤   pgpClearMemory( myself, ·sizeof (*myself));
d30f16 ¤   pgpContextMemFree( cdkContext, myself);
cb67c5 ¤
08151e ¤   return kPGPError_NoErr;
95efe6 }
b5af5a
28f07b PGPPipeline *
f91417 pgpDevNullCreate (
d8fdf9 ¤   PGPContextRef cdkContext,
13f7f9 ¤   PGPPipeline **head)
6ebb36 {
870df0 ¤   PGPPipeline *mod;
e9af5a
c0bb3d ¤   if (!head)
c77ed2 ¤   ¤   return NULL;
98af5a
902992 ¤   mod = (PGPPipeline *)
26f31f ¤   ¤   pgpContextMemAlloc( cdkContext, sizeof(*mod), kPGPMemoryMgrFlags_Clear);
8dac0b ¤   if (mod) {
3b70f5 ¤   ¤   mod->magic = DEVNULLMAGIC;
4be9e6 ¤   ¤   mod->write = Write;
f25a2b ¤   ¤   mod->flush = Flush;
16e5dc ¤   ¤   mod->sizeAdvise = SizeAdvise;
d2e4aa ¤   ¤   mod->annotate = Annotate;
c1a1d6 ¤   ¤   mod->teardown = Teardown;
3ea7cc ¤   ¤   mod->name = "Dev Null";
a546ed ¤   ¤   mod->cdkContext¤= cdkContext;
e2af5a
4a6c9a ¤   ¤   *head = mod;
883030 ¤   ¤   return *head;
789371 ¤   }
493f59 ¤   return NULL;
68efe6 }
--a3bc 001260c39af401001bd Page 1 of pgpDevNull.h
bc38e5 /*
72223b ·* pgpDevNull.h -- A pipeline going nowhere
ec775e ·*
9d7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
7d775e ·*
ed8190 ·* This is a Public API Function Header.
6d775e ·*
93014d ·* $Id: pgpDevNull.h,v 1.8 1997/06/25 19:40:23 lloyd Exp $
a9495d ·*/
a3af5a
880ce3 #ifndef Included_pgpDevNull_h
6a58d7 #define Included_pgpDevNull_h
47af5a
5d99c6 PGP_BEGIN_C_DECLARATIONS
fbaf5a
d1275d #include "pgpPipelineOpaqueStructs.h"
54e82c #include "pgpPubTypes.h"
dfaf5a
2a38e5 /*
c301d8 ·* Create a module that will eat all of its input.
36495d ·*/
5fe844 PGPPipeline ·*pgpDevNullCreate ( PGPContextRef, PGPPipeline **head);
37af5a
fc1254 PGP_END_C_DECLARATIONS
61af5a
269cdf #endif /* Included_pgpDevNull_h */
--df63 000ddb4c8a7401001be Page 1 of pgpJoin.c
bc38e5 /*
25af26 ·* pgpJoin.c -- join multiple modules into a single stream
45775e ·*
d27ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
2e775e ·*
fd586f ·* $Id: pgpJoin.c,v 1.22 1997/12/12 01:14:17 heller Exp $
5c495d ·*/
85e2ff #include "pgpConfig.h"
aaaf5a
94feb2 #include <stdio.h>
24af5a
eda146 #include "pgpDebug.h"
43421a #include "pgpJoin.h"
646aaa #include "pgpAnnotate.h"
44910a #include "pgpFIFO.h"
110d08 #include "pgpMem.h"
8d2f8d #include "pgpErrors.h"
412ece #include "pgpPipeline.h"
56c26c #include "pgpContext.h"
42af5a
53aaed #define JOINMAGIC¤  0x00112233
c3af5a
bda7c7 typedef struct JoinContext {
56f8fb ¤   PGPPipeline¤¤   pipe;
2467c5 ¤
8d2480 ¤   PGPFifoDesc const *fd;
923566 ¤   PGPFifoContext *fifo;
c075b0 ¤   PGPPipeline *tail;
feaf53 ¤   PGPPipeline *next;
640e20 ¤   PGPPipeline *top;
6966a2 ¤   unsigned long size;
4a2a2f ¤   int sizevalid;
30aebe ¤   int canwrite;
aab93c ¤   int eof;
2dab54 ¤   int teardown;
4a894a ¤   DEBUG_STRUCT_CONSTRUCTOR( JoinContext )
4868da } JoinContext;
6baf5a
06f1ae static PGPError
03b562 DoFlush(JoinContext *context)
d9bb36 {
615b01 ¤   PGPError¤   error = kPGPError_NoErr;
16a617 ¤   PGPByte const *ptr;
9b875f ¤   PGPSize len;
886c75 ¤   size_t retlen;
82ecac ¤   JoinContext *topp = (JoinContext *)context->top->priv;
bf9ea4 ¤   PGPPipeline *tailp = topp->tail;
59af5a
bbc0ec ¤   pgpAssert(tailp);
c0af5a
fd16d3 ¤   /* Try to flush anything that we have buffered */
cd63ae ¤   if (context->fifo) {
c25597 ¤   ¤   ptr = pgpFifoPeek (context->fd, context->fifo, &len);
c3bf30 ¤   ¤   while (len) {
c4a44c ¤   ¤   ¤   retlen = tailp->write(tailp, ptr, len, &error);
77cef7 ¤   ¤   ¤   pgpFifoSeek (context->fd, context->fifo, retlen);
f3fd93 ¤   ¤   ¤   if (context->sizevalid)
0115c3 ¤   ¤   ¤   ¤   context->size -= retlen;
2ad82b ¤   ¤   ¤   if (error)
1cb20f ¤   ¤   ¤   ¤   return error;
4787c7 ¤   ¤   ¤
18e98e ¤   ¤   ¤   ptr = pgpFifoPeek (context->fd, context->fifo, &len);
5a0fe4 ¤   ¤   }
599371 ¤   }
9ce74a ¤   /* If we get here, we have nothing left buffered in the fifo */
73af5a
6dd8af ¤   /*
e785a2 ¤   ·* Now, check if we are in an EOF condition. ·If so, then we
8f3796 ¤   ·* can tell the next input that it is allowed to write, and
32567c ¤   ·* then we can try to flush out that buffer as well.
9fa4e3 ¤   ·*/
dddfcd ¤   if (context->eof && context->next) {
--75f2 000af3a93ad401001be Page 2 of pgpJoin.c
b77ef8 ¤   ¤   JoinContext *ctx = (JoinContext *)context->next->priv;
a2af5a
626bea ¤   ¤   ctx->canwrite = 1;
6a8a52 ¤   ¤   error = DoFlush (ctx);
bc9371 ¤   }
38af5a
abc674 ¤   return error;
7befe6 }
f9af5a
14f1ae static PGPError
d7c966 Flush(PGPPipeline *myself)
95bb36 {
6298b7 ¤   JoinContext *context, *topp;
539a0e ¤   PGPPipeline *tailp;
dd87a6 ¤   PGPError¤   error;
71af5a
46b81b ¤   pgpAssert(myself);
01bf0f ¤   pgpAssert(myself->magic == JOINMAGIC);
10af5a
07b99e ¤   context = (JoinContext *)myself->priv;
7e213c ¤   pgpAssert(context);
8baf5a
f9af62 ¤   topp = (JoinContext *)context->top->priv;
adc169 ¤   pgpAssert(topp);
c7af5a
fc833b ¤   tailp = topp->tail;
d6af5a
861489 ¤   if (context->canwrite) {
b30759 ¤   ¤   pgpAssert(tailp);
21ef82 ¤   ¤   error = DoFlush (context);
59e3c2 ¤   ¤   if (error)
4e3b5b ¤   ¤   ¤   return error;
4b9371 ¤   }
16af5a
d60669 ¤   if (tailp)
04e470 ¤   ¤   return tailp->flush(tailp);
542d68 ¤   return( kPGPError_NoErr );
27efe6 }
1baf5a
da5d09 static size_t
cd5669 Write(PGPPipeline *myself, PGPByte const *buf, size_t len, PGPError *error)
b3bb36 {
6c98b7 ¤   JoinContext *context, *topp;
eb9a0e ¤   PGPPipeline *tailp;
a9ac29 ¤   size_t written;
7faf5a
5cb81b ¤   pgpAssert(myself);
6abf0f ¤   pgpAssert(myself->magic == JOINMAGIC);
194ca3 ¤   pgpAssert(error);
13af5a
ceb99e ¤   context = (JoinContext *)myself->priv;
45213c ¤   pgpAssert(context);
c9af5a
01af62 ¤   topp = (JoinContext *)context->top->priv;
bec169 ¤   pgpAssert(topp);
35af5a
027093 ¤   /* If we're not allowed to write, then buffer things up until we can */
e69096 ¤   *error = kPGPError_NoErr;
a2c082 ¤   if (!context->canwrite)
3b57c6 ¤   ¤   return pgpFifoWrite (context->fd, context->fifo, buf, len);
31af5a
16b12a ¤   /* At this point we are writing -- make sure we have a tail! */
b2833b ¤   tailp = topp->tail;
e2c0ec ¤   pgpAssert(tailp);
e2af5a
620479 ¤   *error = DoFlush (context);
295842 ¤   if (*error)
aebbde ¤   ¤   return 0;
cfaf5a
cc0265 ·¤  written = tailp->write(tailp, buf, len, error);
57db31 ¤   if (context->sizevalid)
afaf70 ¤   ¤   context->size -= written;
--d644 0002a150034401001be Page 3 of pgpJoin.c
e0af5a
39279e ¤   return written;
84efe6 }
aaaf5a
5ff1ae static PGPError
1c4ddc Annotate(PGPPipeline *myself, PGPPipeline *origin, int type,
7841cc ¤   ··PGPByte const *string, size_t len)
0fbb36 {
a498b7 ¤   JoinContext *context, *topp;
e41b22 ¤   PGPPipeline *tailp = NULL;
e9af5a
17b81b ¤   pgpAssert(myself);
88bf0f ¤   pgpAssert(myself->magic == JOINMAGIC);
e8af5a
16b99e ¤   context = (JoinContext *)myself->priv;
08213c ¤   pgpAssert(context);
59af5a
2faf62 ¤   topp = (JoinContext *)context->top->priv;
563556 ¤   if (topp)
fb755e ¤   ¤   tailp = topp->tail;
05af5a
54d8af ¤   /*
2ccbd9 ¤   ·* Pass most annotations through. ·Previously we did not do so,
822f16 ¤   ·* and just silently returned on the special ones below. ·For minimal
d4aebe ¤   ·* impact, continue with the old behavior on those but pass others
f9cafa ¤   ·* through.
a6a4e3 ¤   ·*/
a2af5a
671609 ¤   switch (type) {
b5aa6d ¤   case PGPANN_FILE_BEGIN:
ce6df4 ¤   case PGPANN_FILE_END:
dd05ec ¤   case PGPANN_INPUT_BEGIN:
4e82f9 ¤   case PGPANN_INPUT_END:
39a117 ¤   ¤   return( kPGPError_NoErr );
64f786 ¤   ¤   /*NOTREACHED*/
ef2f72 ¤   default:
11e4ca ¤   ¤   if (tailp)
0ab17e ¤   ¤   ¤   return tailp->annotate(tailp, origin, type, string, len);
a162b5 ¤   ¤   return kPGPError_BadParams;
669371 ¤   }
3ccc6f ¤   /*NOTREACHED*/
b3efe6 }
25af5a
9d38e5 /*
f4dfcf ·* context->size is the number of bytes in the fifo plus the number of
ef1d0f ·* bytes we still should expect to receive. ·Once this is set, we
7bcd9b ·* expect it to be held by the caller. ·Each input gets one of these.
817f28 ·* We decrement it, if it is valid, whenever we write data out to the
5b7f72 ·* tail.
fd775e ·*
e89773 ·* context->sizevalid is if the number in context->size is valid
af775e ·*
51d2ff ·* This function will first check to make sure that the size is valid,
c418ae ·* and that the passed-in size matches the expected size.
93775e ·*
946f13 ·* We also keep track of EOF -- if we get a sizeAdvise of 0 bytes,
94ccfe ·* then we set context->eof to 1, to signify that we have an EOF
7e5008 ·* condition and we do not expect any more bytes to be written from
5fbb49 ·* that input. ·This means that context->size is the number of bytes
99e76f ·* buffered in that context.
05775e ·*
f8cbd1 ·* Then it will see if all inputs have a valid size. ·If they do, then
768251 ·* it will add up all the sizes and send that as a sizeAdvise to the
ca7f72 ·* tail.
fc775e ·*
aeb3f2 ·* Next, we will flush out the buffered data, and if that returns
7f28ff ·* without an error we know that everything is flushed from all the
50fd06 ·* modules from this one to the end.
35775e ·*
83238c ·* Finally we check if everything is EOF. ·We know that if everything
a9ead2 ·* is at EOF, and we got this far, that there must not be anything in
2acef0 ·* any buffers, and we are not expecting anymore data to be written.
--9aba 0005a8f2b2f401001be Page 4 of pgpJoin.c
d376ec ·* Therefore, we pass a sizeAdvise (0) to the tail.
d1495d ·*/
05f1ae static PGPError
eb99d0 SizeAdvise(PGPPipeline *myself, unsigned long bytes)
07bb36 {
517174 ¤   JoinContext *ctx, *context, *topp;
8943ef ¤   PGPPipeline *current, *tailp;
87ad9e ¤   unsigned long fifolen;
2c450e ¤   unsigned long total;
b2364d ¤   int flag = 0;
8987a6 ¤   PGPError¤   error;
93af5a
61b81b ¤   pgpAssert(myself);
73bf0f ¤   pgpAssert(myself->magic == JOINMAGIC);
afaf5a
39b99e ¤   context = (JoinContext *)myself->priv;
d9213c ¤   pgpAssert(context);
7caf5a
dcaf62 ¤   topp = (JoinContext *)context->top->priv;
9dc169 ¤   pgpAssert(topp);
65af5a
4f833b ¤   tailp = topp->tail;
24af5a
87d8af ¤   /*
fdb187 ¤   ·* XXX If annotations get added, make sure we only consider calls
fb83f1 ¤   ·* outside them.
074ce8 ¤   ·* I.e. "if (context->scope_depth) return( kPGPError_NoErr );"
78a4e3 ¤   ·*/
44af5a
30cad7 ¤   /* save off the size of the buffered data */
676ec5 ¤   fifolen = pgpFifoSize (context->fd, context->fifo);
38af5a
3303eb ¤   /* Check/set the size */
e20c53 ¤   if (context->sizevalid) {
5fc75f ¤   ¤   if (bytes != context->size - fifolen)
bc821f ¤   ¤   ¤   /* It doesn't jibe -- this is an error */
c56841 ¤   ¤   ¤   return kPGPError_SizeAdviseFailure;
1ef037 ¤   } else {
4fffb7 ¤   ¤   context->sizevalid = 1;
53d8db ¤   ¤   context->size = bytes + fifolen;
c39371 ¤   }
0d67c5 ¤
6fa2d6 ¤   /* Set EOF, if needed */
fba8f9 ¤   if (!bytes)
2986e7 ¤   ¤   context->eof = 1;
40af5a
76b4f9 ¤   /* Check if all modules have valid size; add up the sizes */
747ed5 ¤   total = 0;
93a56f ¤   for (current = context->top; current; current = ctx->next) {
96be3c ¤   ¤   ctx = (JoinContext *)current->priv;
60f68a ¤   ¤   pgpAssert(ctx);
7caf5a
07ccab ¤   ¤   if (!ctx->sizevalid) {
fde593 ¤   ¤   ¤   flag = 1;
10cdcb ¤   ¤   ¤   break;
c40fe4 ¤   ¤   }
9b55c5 ¤   ¤   total += ctx->size;
ae9371 ¤   }
80aa0d ¤   if (!flag) {
8f3113 ¤   ¤   /* All the inputs have a valid sizes... Send a sizeAdvise */
2c0759 ¤   ¤   pgpAssert(tailp);
0faf5a
0ef56c ¤   ¤   error = tailp->sizeAdvise(tailp, total);
5fe3c2 ¤   ¤   if (error)
c43b5b ¤   ¤   ¤   return error;
049371 ¤   }
e2af5a
95d8af ¤   /*
5c3ef2 ¤   ·* If we cannot write, then we cannot flush! ·Just accept that
ee2342 ¤   ·* the sizeAdvise worked to this point and return success.
cea4e3 ¤   ·*/
5ac082 ¤   if (!context->canwrite)
--1b25 0005d4deae6401001be Page 5 of pgpJoin.c
f2a117 ¤   ¤   return( kPGPError_NoErr );
15af5a
08c0ec ¤   pgpAssert(tailp);
23d8af ¤   /*
967ae3 ¤   ·* Flush the data. ·This will return an error, or everything
9878fe ¤   ·* will be flushed out of the fifo.
6da4e3 ¤   ·*/
7e63fd ¤   error = DoFlush (context);
460161 ¤   if (error)
cefcee ¤   ¤   return error;
66af5a
99af5a
57b3db ¤   /* At this point, check if everything is EOF. */
17a56f ¤   for (current = context->top; current; current = ctx->next) {
fcbe3c ¤   ¤   ctx = (JoinContext *)current->priv;
6ef68a ¤   ¤   pgpAssert(ctx);
4e1b52 ¤   ¤
9ab7cb ¤   ¤   if (!ctx->eof)
131051 ¤   ¤   ¤   /* Something isn't done -- just return success */
00e0e4 ¤   ¤   ¤   return( kPGPError_NoErr );
2c9371 ¤   }
e7af5a
87dccd ¤   /* Send a sizeAdvise (0) -- all the inputs are done writing. */
1f2ac3 ¤   return tailp->sizeAdvise(tailp, 0);
81efe6 }
ffaf5a
30f1ae static PGPError
f0bf01 Teardown(PGPPipeline *myself)
97bb36 {
0043ef ¤   PGPPipeline *current, *tailp;
917174 ¤   JoinContext *ctx, *context, *topp;
2fe9fa ¤   PGPContextRef¤  cdkContext;
0967c5 ¤
5f3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
a7696e ¤   cdkContext¤ = myself->cdkContext;
cbaf5a
10b81b ¤   pgpAssert(myself);
97bf0f ¤   pgpAssert(myself->magic == JOINMAGIC);
05af5a
f4b99e ¤   context = (JoinContext *)myself->priv;
60213c ¤   pgpAssert(context);
afaf5a
c9af62 ¤   topp = (JoinContext *)context->top->priv;
ddc169 ¤   pgpAssert(topp);
deaf5a
b0833b ¤   tailp = topp->tail;
85af5a
0f94e9 ¤   context->teardown = 1;
0caf5a
92a56f ¤   for (current = context->top; current; current = ctx->next) {
c7be3c ¤   ¤   ctx = (JoinContext *)current->priv;
5af68a ¤   ¤   pgpAssert(ctx);
54af5a
238e3f ¤   ¤   if (!ctx->teardown)
a9a1ea ¤   ¤   ¤   return( kPGPError_NoErr );;
479371 ¤   }
d2af5a
665490 ¤   /* Everything can be torn down, now. */
f10669 ¤   if (tailp)
94c8e6 ¤   ¤   tailp->teardown(tailp);
79af5a
40c073 ¤   for (current = context->top; current; current = myself) {
9ebe3c ¤   ¤   ctx = (JoinContext *)current->priv;
baf68a ¤   ¤   pgpAssert(ctx);
4b1b52 ¤   ¤
41c1bd ¤   ¤   myself = ctx->next;
8caf5a
108727 ¤   ¤   pgpFifoDestroy (ctx->fd, ctx->fifo);
f0d1a5 ¤   ¤   pgpClearMemory( ctx, ·sizeof(*ctx));
77607d ¤   ¤   pgpContextMemFree( cdkContext, ctx);
9e9371 ¤   }
5d67c5 ¤
--ae9e 00086d045c3401001be Page 6 of pgpJoin.c
ee2d68 ¤   return( kPGPError_NoErr );
01efe6 }
b0af5a
af15e8 static PGPPipeline *
4042f4 joinDoCreate(
adfdf9 ¤   PGPContextRef cdkContext,
6a71f9 ¤   int dowrite,·
41be98 ¤   PGPFifoDesc const *fifod)
b6bb36 {
8e0df0 ¤   PGPPipeline *mod;
6234fe ¤   PGPFifoContext *fifop = NULL;
b963bb ¤   JoinContext *context;
63af5a
d24663 ¤   context = (JoinContext *)pgpContextMemAlloc( cdkContext,
f5f235 ¤   ¤   sizeof(*context), kPGPMemoryMgrFlags_Clear);
251ea4 ¤   if (!context)
297ed2 ¤   ¤   return NULL;
6c9228 ¤   mod = &context->pipe;
03af5a
e048b2 ¤   fifop = pgpFifoCreate (cdkContext, fifod);
9f9b08 ¤   if (!fifop) {
81a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
157ed2 ¤   ¤   return NULL;
9f9371 ¤   }
9caf5a
bab1d5 ¤   mod->magic = JOINMAGIC;
721f83 ¤   mod->write = Write;
8cac4e ¤   mod->flush = Flush;
9f0aaf ¤   mod->sizeAdvise = SizeAdvise;
9dd3a2 ¤   mod->annotate = Annotate;
5896de ¤   mod->teardown = Teardown;
7f3957 ¤   mod->name = "Join Module";
c701ea ¤   mod->priv = context;
b9a99e ¤   mod->cdkContext¤= cdkContext;
dbaf5a
909d73 ¤   context->fd = fifod;
f432cc ¤   context->fifo = fifop;
360010 ¤   context->canwrite = dowrite;
ffaf5a
101fea ¤   return mod;
4eefe6 }
c0af5a
d841cd PGPPipeline **
3bd6a5 pgpJoinCreate(
71fdf9 ¤   PGPContextRef cdkContext,
9f8941 ¤   PGPPipeline **head,
a9be98 ¤   PGPFifoDesc const *fifod)
fdbb36 {
9f0df0 ¤   PGPPipeline *mod;
4663bb ¤   JoinContext *context;
5aaf5a
33bb3d ¤   if (!head)
c17ed2 ¤   ¤   return NULL;
4caf5a
a2df1f ¤   pgpAssert(fifod);
2baf5a
132e78 ¤   mod = joinDoCreate ( cdkContext, 1, fifod);
40e094 ¤   if (!mod)
e47ed2 ¤   ¤   return NULL;
9caf5a
cee9d7 ¤   context = (JoinContext *)mod->priv;
69af5a
f0813b ¤   context->top = mod;
6f65ad ¤   context->tail = *head;
e92d11 ¤   *head = mod;
e97fa2 ¤   return &context->tail;
fbefe6 }
baaf5a
d1f07b PGPPipeline *
22a2af pgpJoinAppend(PGPPipeline *head)
babb36 {
860df0 ¤   PGPPipeline *mod;
--bc0d 0013dfa20dd401001be Page 7 of pgpJoin.c
c79d78 ¤   JoinContext *context, *ctx;
94af5a
e7bb3d ¤   if (!head)
147ed2 ¤   ¤   return NULL;
24af5a
3629d7 ¤   pgpAssert(head->magic == JOINMAGIC);
87af5a
7a9e9b ¤   context = (JoinContext *)head->priv;
14213c ¤   pgpAssert(context);
f1af5a
7dfcc6 ¤   mod = joinDoCreate( head->cdkContext, 0, context->fd);
d8e094 ¤   if (!mod)
b57ed2 ¤   ¤   return NULL;
f9af5a
da94b5 ¤   mod->name = "Join Module Appendage";
351e93 ¤   ctx = (JoinContext *)mod->priv;
e3af5a
3a7914 ¤   /* Splice in myself module */
e5ab05 ¤   ctx->next = context->next;
099859 ¤   context->next = mod;
31af5a
2f0f62 ¤   ctx->top = context->top;
56af5a
4f1fea ¤   return mod;
e2efe6 }
47af5a
c644d2 size_t
33d383 pgpJoinBuffer(PGPPipeline *myself, PGPByte const *buf, size_t len)
38bb36 {
a063bb ¤   JoinContext *context;
63af5a
19b81b ¤   pgpAssert(myself);
5dbf0f ¤   pgpAssert(myself->magic == JOINMAGIC);
f9af5a
d6b99e ¤   context = (JoinContext *)myself->priv;
f4213c ¤   pgpAssert(context);
7eaf5a
b76aa8 ¤   return pgpFifoWrite (context->fd, context->fifo, buf, len);
3defe6 }
--1d5d 00192f77dfb401001bf Page 1 of pgpJoin.h
bc38e5 /*
81fce6 ·* pgpJoin.h -- Append multiple streams together into a single output, and
a1f711 ·* buffer as needed
89775e ·*
7b7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
35775e ·*
331bf7 ·* $Id: pgpJoin.h,v 1.9 1997/06/25 19:40:24 lloyd Exp $
4b495d ·*/
67af5a
c638e5 /*
075d9d ·* A join module will combine multiple inputs into a single output.
898aff ·* It will first take all the data from the first input (the input
7b9130 ·* from the creation function) until it gets a SizeAdvise(0). ·Then it
85c33e ·* will start reading from the next input in line, until it is done,
9c9468 ·* and so on down the list of inputs.
13775e ·*
4ae95c ·* If an input pipeline that is not the current writer tries to write
ffa203 ·* data, it will be buffered in that input's fifo.
33775e ·*
57aff8 ·* Data that is buffered will be flushed out when that input is
be1da1 ·* allowed to write, which is when all previous writers have sent
be3776 ·* a sizeAdvise(0).
59495d ·*/
26af5a
60f76f #ifndef Included_pgpJoin_h
a59319 #define Included_pgpJoin_h
05af5a
33d11f #include "pgpUsuals.h"
08af5a
0e99c6 PGP_BEGIN_C_DECLARATIONS
cbaf5a
5aadb8 #include "pgpOpaqueStructs.h"
36e82c #include "pgpPubTypes.h"
4eaf5a
5838e5 /*
3f2719 ·* Create a join module. ·The caller needs to save the head pointer
887e99 ·* for later use. ·*/
427064 PGPPipeline ·**pgpJoinCreate (PGPContextRef cdkContext, PGPPipeline **head,
0eef23 ¤   ¤   ¤   ¤   ····PGPFifoDesc const *fd);
23af5a
2338e5 /*
464f99 ·* Append a new input to the join module. ·This will insert the
7a035f ·* new pipeline just after the pointer to the head passed in. ·This
e3f42e ·* function returns a pointer to the join module associated with
182ec2 ·* myself input.
77495d ·*/
a39446 PGPPipeline ·*pgpJoinAppend ( PGPPipeline *head);
57af5a
3e38e5 /*
e2df9d ·* Add data to the buffer in the pipeline module passed in. ·This
99da6a ·* data will be flushed out later.
97495d ·*/
18210a size_t ·pgpJoinBuffer (PGPPipeline *myself, PGPByte const *buf,
b1fa93 ¤   size_t len);
b0af5a
7e1254 PGP_END_C_DECLARATIONS
acaf5a
92b3c0 #endif /* Included_pgpJoin_h */
--5663 0006bb05dcc401001c0 Page 1 of pgpMemMod.c
bc38e5 /*
4a93be ·* pgpMemMod.c -- Module to output to a fixed-size memory buffer
96775e ·*
a7397e ·* If we overflow the buffer, we discard the rest. ·That is not an error.
648a05 ·* However we provide an annotation to allow reading how much we would
2d28ab ·* have written.
12775e ·*
3b901c ·* Copyright (C) 1996, 1997 Network Associates, Inc. and its affiliates.
a320c7 ·* All rights reserved
4b775e ·*
3073cf ·* $Id: pgpMemMod.c,v 1.22.12.1 1998/11/12 03:21:27 heller Exp $
bd495d ·*/
1eaf5a
1ee2ff #include "pgpConfig.h"
66af5a
ddfeb2 #include <stdio.h>
88324c #include <string.h>
3aaf5a
bda146 #include "pgpDebug.h"
a11dd3 #include "pgpMemMod.h"
866aaa #include "pgpAnnotate.h"
ce0d08 #include "pgpMem.h"
4e2f8d #include "pgpErrors.h"
e82ece #include "pgpPipeline.h"
a1d11f #include "pgpUsuals.h"
5ac26c #include "pgpContext.h"
bfaf5a
b8814c #define MEMMODMAGIC¤0xfeedbabe
17af5a
d438e5 /*
01f723 ·* Note that byte_count may come to exceed buf_size, in which case we
02d14d ·* discard the overflow. ·We provide an annotation to read the total number
71215a ·* of bytes written.
67495d ·*/
514971 typedef struct memModContext {
0d8b60 ¤   PGPPipeline¤pipe;
fa67c5 ¤
317929 ¤   int scope_depth;
92ef24 ¤   PGPBoolean enable;¤ /* True if accepting data, false to discard */
791a88 ¤   size_t buf_size;¤   /* Total size of memory buffer */
18ea3e ¤   size_t byte_count;¤ /* Number of bytes we have been given */
874b6f ¤   PGPByte *buf;¤  ¤   /* Start of memory buffer */
78b19e ¤   DEBUG_STRUCT_CONSTRUCTOR( memModContext )
43e517 } memModContext;
ccaf5a
b3af5a
45f1ae static PGPError
edd43d memFlush (PGPPipeline *myself)
fabb36 {
32a0fe ¤   memModContext *context;
51af5a
8929be ¤   pgpAssert (myself);
e81d4c ¤   pgpAssert (myself->magic == MEMMODMAGIC);
59af5a
bb0951 ¤   context = (memModContext *)myself->priv;
3ed30a ¤   pgpAssert (context);
b5af5a
642d68 ¤   return( kPGPError_NoErr );
99efe6 }
83af5a
a5b400 /* Write what is given, but disard any overflows. */
165d09 static size_t
6e3e93 memWrite (PGPPipeline *myself, PGPByte const *buffer, size_t size,
d50431 ¤   ···PGPError *error)
15bb36 {
fda0fe ¤   memModContext *context;
33af5a
f229be ¤   pgpAssert (myself);
4b1d4c ¤   pgpAssert (myself->magic == MEMMODMAGIC);
62af5a
010951 ¤   context = (memModContext *)myself->priv;
6bd30a ¤   pgpAssert (context);
--9df9 00067a9f72f401001c0 Page 2 of pgpMemMod.c
e0af5a
8070a0 ¤   /* If disabled, discard data */
85e4c4 ¤   if (!context->enable)
ddb771 ¤   ¤   return size;
9baf5a
d886a1 ¤   if (context->buf_size > context->byte_count) {
ff0101 ¤   ¤   size_t avail = context->buf_size - context->byte_count;
4da624 ¤   ¤   size_t to_write = pgpMin (avail, size);
61af5a
e1454c ¤   ¤   if (to_write)
a919c6 ¤   ¤   ¤   memcpy (context->buf + context->byte_count, buffer, to_write);
68af5a
54cc42 ¤   ¤   /* Store an uncounted null beyond the end of the buffer */
bf90ff ¤   ¤   if (context->byte_count+to_write < context->buf_size)
5dd463 ¤   ¤   ¤   context->buf[context->byte_count+to_write] = '\0';
9e9371 ¤   }
7daf5a
c50161 ¤   if (error)
8aa79e ¤   ¤   *error = kPGPError_NoErr;
2c7904 ¤   context->byte_count += size;
6af6fa ¤   return size;
faefe6 }
dbaf5a
a238e5 /*
696584 ·* We accept an annotation to return the number of bytes we were asked
483670 ·* to write. ·We also provide an annotation to return the size of the
e62392 ·* buffer.
74a347 ·* We return our results in the passed-in string pointer, which must be
cef7f6 ·* of size sizeof(size_t).
a30560 ·* The ENABLE annotation causes us to turn on and off whether we accept data.
dc495d ·*/
e1f1ae static PGPError
f7ddb7 memAnnotate (PGPPipeline *myself, PGPPipeline *origin, int type,
51b533 ¤   ······PGPByte const *string, size_t size)
aabb36 {
44a0fe ¤   memModContext *context;
01af5a
f9df26 ¤   (void)origin;¤  /* Avoid warning */
ac7aab ¤   (void)size;
28af5a
f629be ¤   pgpAssert (myself);
511d4c ¤   pgpAssert (myself->magic == MEMMODMAGIC);
fdaf5a
5a0951 ¤   context = (memModContext *)myself->priv;
91d30a ¤   pgpAssert (context);
26af5a
831609 ¤   switch (type) {
c2d314 ¤   case PGPANN_MEM_BYTECOUNT:
95e555 ¤   ¤   pgpAssert (string);
34b663 ¤   ¤   pgpAssert (size == sizeof(size_t));
36ec35 ¤   ¤   *(size_t *)string = context->byte_count;
efa117 ¤   ¤   return( kPGPError_NoErr );
bd8f00 ¤   case PGPANN_MEM_BUFSIZE:
2ae555 ¤   ¤   pgpAssert (string);
b8b663 ¤   ¤   pgpAssert (size == sizeof(size_t));
409f97 ¤   ¤   *(size_t *)string = context->buf_size;
bea117 ¤   ¤   return( kPGPError_NoErr );
b34f2b ¤   case PGPANN_MEM_ENABLE:
a7e555 ¤   ¤   pgpAssert (string);
324314 ¤   ¤   pgpAssert (size == 1);
81ab39 ¤   ¤   context->enable = *(PGPByte *)string;
5da117 ¤   ¤   return( kPGPError_NoErr );
e14fd2 ¤   case PGPANN_MEM_PREPEND:
07895e ¤   ¤   /* This means that we have some data in buffer already to skip */
cf0775 ¤   ¤   if ( context->buf != (PGPByte *)string )
02a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
8e7610 ¤   ¤   context->byte_count += size;¤   ¤   /* Skip past data */
247898 ¤   ¤   if (context->byte_count > context->buf_size)
d6cd40 ¤   ¤   ¤   context->byte_count = context->buf_size;
e6a117 ¤   ¤   return( kPGPError_NoErr );
aa2f72 ¤   default:
67d30b ¤   ¤   ;¤  ¤   /* do nothing */
--605b 000f38d3b9c401001c0 Page 3 of pgpMemMod.c
a19371 ¤   }
93af5a
9aeb30 ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
9f04c8 ¤   pgpAssert(context->scope_depth != -1);
8aaf5a
8c2d68 ¤   return( kPGPError_NoErr );
39efe6 }
5caf5a
5af1ae static PGPError
e6b0ba memSizeAdvise (PGPPipeline *myself, unsigned long bytes)
e9bb36 {
15a0fe ¤   memModContext *context;
68af5a
5dd223 ¤   (void)bytes;
70af5a
1929be ¤   pgpAssert (myself);
7b1d4c ¤   pgpAssert (myself->magic == MEMMODMAGIC);
6daf5a
6d0951 ¤   context = (memModContext *)myself->priv;
31d30a ¤   pgpAssert (context);
f5af5a
9e2d68 ¤   return( kPGPError_NoErr );
97efe6 }
63af5a
e5f1ae static PGPError
38ca70 memTeardown (PGPPipeline *myself)
3cbb36 {
eaa0fe ¤   memModContext *context;
1ce9fa ¤   PGPContextRef¤  cdkContext;
0a67c5 ¤
0c3982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
32696e ¤   cdkContext¤ = myself->cdkContext;
48af5a
f529be ¤   pgpAssert (myself);
001d4c ¤   pgpAssert (myself->magic == MEMMODMAGIC);
1aaf5a
df0951 ¤   context = (memModContext *)myself->priv;
6bd30a ¤   pgpAssert (context);
c6af5a
1d3736 ¤   pgpClearMemory( context, ·sizeof (*context));
38fa6e ¤   pgpContextMemFree( cdkContext, context);
dd67c5 ¤
632d68 ¤   return( kPGPError_NoErr );
f0efe6 }
dfaf5a
d2f07b PGPPipeline *
a68f0d pgpMemModCreate (
f5fdf9 ¤   PGPContextRef cdkContext,
8d8941 ¤   PGPPipeline **head,
bf4149 ¤   char *buf,
605082 ¤   size_t buf_size)
f7bb36 {
410df0 ¤   PGPPipeline *mod;
eca0fe ¤   memModContext *context;
11af5a
08bb3d ¤   if (!head)
ec7ed2 ¤   ¤   return NULL;
c0af5a
ee2338 ¤   *head = 0;
1baf5a
515390 ¤   context = (memModContext *)pgpContextMemAlloc( cdkContext,
04f235 ¤   ¤   sizeof(*context), kPGPMemoryMgrFlags_Clear);
641ea4 ¤   if (!context)
1f7ed2 ¤   ¤   return NULL;
699228 ¤   mod = &context->pipe;
aeaf5a
5c5226 ¤   mod->magic = MEMMODMAGIC;
347938 ¤   mod->write = memWrite;
92ee12 ¤   mod->flush = memFlush;
765b08 ¤   mod->sizeAdvise = memSizeAdvise;
333c14 ¤   mod->annotate = memAnnotate;
f37657 ¤   mod->teardown = memTeardown;
--3708 001e6395ee3401001c0 Page 4 of pgpMemMod.c
6c27da ¤   mod->name = "Write memory";
ed01ea ¤   mod->priv = context;
8fa99e ¤   mod->cdkContext¤= cdkContext;
deaf5a
c70243 ¤   context->buf = (PGPByte *)buf;
96a390 ¤   context->buf_size = buf_size;
f90257 ¤   context->enable = 1;
eeaf5a
c42d11 ¤   *head = mod;
071fea ¤   return mod;
e6efe6 }
--3a3b 0019da54bc7401001c1 Page 1 of pgpMemMod.h
bc38e5 /*
08f4bb ·* pgpMemMod.h -- Module to output to a fixed-size memory buffer
3b775e ·*
a5901c ·* Copyright (C) 1996, 1997 Network Associates, Inc. and its affiliates.
d320c7 ·* All rights reserved
e5775e ·*
81ff43 ·* $Id: pgpMemMod.h,v 1.8.30.1 1998/11/12 03:21:28 heller Exp $
ff495d ·*/
0caf5a
64b183 #ifndef Included_pgpMemMod_h
8330b5 #define Included_pgpMemMod_h
3faf5a
8999c6 PGP_BEGIN_C_DECLARATIONS
61af5a
3badb8 #include "pgpOpaqueStructs.h"
c4e82c #include "pgpPubTypes.h"
b5af5a
b5af5a
ada06d PGPPipeline ·*¤ pgpMemModCreate( PGPContextRef cdkContext,
a63ca4 ¤   ¤   ¤   ¤   ¤   PGPPipeline **head, char *buf, size_t buf_size);
97af5a
a91254 PGP_END_C_DECLARATIONS
28af5a
9d845b #endif /* Included_pgpMemMod_h */
--2500 00145c697fd401001c2 Page 1 of pgpPipeline.h
bc38e5 /*
e7d0ab ·* pgpPipeline.h -- This is the code that is the public part of a pipeline
1e838e ·* module, and defines everything that all the pipelines should export.
1a775e ·*
667ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
3d775e ·*
260dd2 ·* This is a Public API Function/Structure Header.
fc775e ·*
0cc43a ·* $Id: pgpPipeline.h,v 1.12 1997/12/11 23:12:47 lloyd Exp $
63495d ·*/
a3af5a
450308 #ifndef Included_pgpPipeline_h
6874fb #define Included_pgpPipeline_h
8aaf5a
3ce82c #include "pgpPubTypes.h"
906773 #include "pgpMemoryMgr.h"
78af5a
2799c6 PGP_BEGIN_C_DECLARATIONS
8eaf5a
e90c97 struct PGPPipeline
13bb36 {
e31ae0 ¤   /* A means to check if this is a valid module -- put a magic
53bda2 ¤   ·* number in the structure for each different pipeline module
6bea75 ¤   ·* and compare it. ·Simple, eh?
8ea4e3 ¤   ·*/
0cb3cd ¤   PGPUInt32¤  magic;
1eaf5a
c96b3d ¤   /* Exported Pipeline Functions that all Pipelines support */
624d38 ¤   size_t¤ ¤   (*write) (PGPPipeline *myself, PGPByte const *buffer,
479caf ¤   ¤   ¤   ¤   ¤   ··size_t size, PGPError *error);
f32b21 ¤   PGPError¤   (*flush) (PGPPipeline *myself);
69e94f ¤   PGPError¤   (*annotate) (PGPPipeline *myself,
b33fb0 ¤   ¤   ¤   ·····PGPPipeline *origin, int type,·
ed408f ¤   ¤   ¤   ·····PGPByte const *string, size_t size);
fc7cf3 ¤   PGPError¤   (*sizeAdvise) (PGPPipeline *myself,
8d7f9c ¤   ¤   ¤   ¤   unsigned long bytes);
0cdb84 ¤   PGPError¤   (*teardown) (PGPPipeline *myself);
3aaf5a
473f1f ¤   /* Some exported information about this particular module */
78f5fd ¤   char const *¤   name;
bdaf5a
e5e9fa ¤   PGPContextRef¤  cdkContext;
0667c5 ¤
aefaa3 ¤   /* A pointer to module-specfic data */
55fb58 ¤   PGPUserValue¤   priv;
9e82f7 };
2aaf5a
f2af5a
f31254 PGP_END_C_DECLARATIONS
5daf5a
4511fd #endif /* Included_pgpPipeline_h */
--0c65 0001c9d2e73401001c3 Page 1 of pgpProtoMod.c
bc38e5 /*
15dc6a ·* pgpProtoMod.c -- a prototype module for PGP
67775e ·*
3f7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
e9775e ·*
b33305 ·* $Id: pgpProtoMod.c,v 1.8 1997/07/26 19:37:32 lloyd Exp $
66495d ·*/
12e2ff #include "pgpConfig.h"
5caf5a
2cfeb2 #include <stdio.h>
8baf5a
47a146 #include "pgpDebug.h"
976aaa #include "pgpAnnotate.h"
560d08 #include "pgpMem.h"
962ece #include "pgpPipeline.h"
37af5a
7938e5 /*
bda0a8 ·* This is a magic number for use within this module. ·It is used to
b3e67a ·* make sure the passed-in module is a member of this type. ·Just a
7bc916 ·* little extra sanity-checking.
90775e ·*
e3d7f0 ·* You should set this value to some "random" 32-bit number.
bb495d ·*/
6cd83c ·
200444 #define MAGIC¤  0x0
2faf5a
397317 Context {
2f6df5 ¤   PGPByte buffer[BUFSIZ];
acc98f ¤   PGPByte *bufptr;
7bc822 ¤   size_t buflen;
a475b0 ¤   PGPPipeline *tail;
c17929 ¤   int scope_depth;
a582f7 };
2caf5a
3cbeb7 static int
f84618 DoFlush (Context *context)
09bb36 {
215b01 ¤   PGPError¤   error = kPGPError_NoErr;
af6c75 ¤   size_t retlen;
aaaf5a
2916d3 ¤   /* Try to flush anything that we have buffered */
f349b8 ¤   while (context->buflen) {
0988b9 ¤   ¤   retlen = context->tail->write (context->tail,
fed239 ¤   ¤   ¤   ¤   ¤   ·······context->bufptr,
d9ee65 ¤   ¤   ¤   ¤   ¤   ·······context->buflen,
b348b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
e0e166 ¤   ¤   context->buflen -= retlen;
2c65bd ¤   ¤   memset (context->bufptr, 0, retlen);
8c060f ¤   ¤   context->bufptr += retlen;
c9e3c2 ¤   ¤   if (error)
f23b5b ¤   ¤   ¤   return error;
b09371 ¤   }
87c674 ¤   return error;
fdefe6 }
d9af5a
a6beb7 static int
bfd02e Flush (PGPPipeline *myself)
19bb36 {
3d7b84 ¤   Context *context;
0087a6 ¤   PGPError¤   error;
93af5a
4e29be ¤   pgpAssert (myself);
9d1ba4 ¤   pgpAssert (myself->magic == MAGIC);
a8af5a
83ee0b ¤   context = myself->priv;
7bd30a ¤   pgpAssert (context);
eaebf4 ¤   pgpAssert (context->tail);
f1af5a
7663fd ¤   error = DoFlush (context);
a20161 ¤   if (error)
f1fcee ¤   ¤   return error;
1caf5a
--520f 0006d197b98401001c3 Page 2 of pgpProtoMod.c
279819 ¤   return context->tail->flush (context->tail);
49efe6 }
94af5a
6e5d09 static size_t
f0f37b Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
57bb36 {
0b7b84 ¤   Context *context;
07a371 ¤   size_t written = 0;
62af5a
fe29be ¤   pgpAssert (myself);
931ba4 ¤   pgpAssert (myself->magic == MAGIC);
9a4866 ¤   pgpAssert (error);
3aaf5a
6eee0b ¤   context = myself->priv;
b6d30a ¤   pgpAssert (context);
7debf4 ¤   pgpAssert (context->tail);
74af5a
4943ab ¤   do {
0c8f85 ¤   ¤   *error = DoFlush (context);
f1cf31 ¤   ¤   if (*error)
d7ab0f ¤   ¤   ¤   return written;
46af5a
481b17 ¤   ¤   /*
c70ad6 ¤   ¤   ·* Now that we don't have anything buffered, bring in more
af3604 ¤   ¤   ·* data from the passed-in buffer, process it, and buffer
5b4169 ¤   ¤   ·* that to write out.
c19de3 ¤   ¤   ·*/
cffe69 ¤   ¤   context->bufptr = context->buffer;
fbecd0 ¤   ¤   /* XXX Set context->buflen to length of read-in material */
1a1d29 ¤   ¤   /* XXX Read/processed data into context->buffer */
46bdd6 ¤   ¤   buf += context->buflen;
0177c4 ¤   ¤   size -= context->buflen;
11aa82 ¤   ¤   written += context->buflen;
e7af5a
d564ca ¤   } while (context->buflen > 0);
f4c130 ¤   /* Continue until we have nothing buffered */
f8af5a
06e765 ¤   return written;¤
21efe6 }
84af5a
2bbeb7 static int
bd13c8 Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
92b0b1 ¤   ··PGPByte const *string, size_t size)
93bb36 {
6a7b84 ¤   Context *context;
2b87a6 ¤   PGPError¤   error;
a9af5a
8a29be ¤   pgpAssert (myself);
081ba4 ¤   pgpAssert (myself->magic == MAGIC);
74af5a
c8ee0b ¤   context = myself->priv;
d9d30a ¤   pgpAssert (context);
62ebf4 ¤   pgpAssert (context->tail);
f5af5a
ce63fd ¤   error = DoFlush (context);
690161 ¤   if (error)
4efcee ¤   ¤   return error;
5d32ab ¤   error = context->tail->annotate (context->tail, origin, type,
923153 ¤   ¤   ¤   ¤   ¤   string, size);
dbff2e ¤   if (!error)
456467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
d004c8 ¤   pgpAssert(context->scope_depth != -1);
86c674 ¤   return error;
0eefe6 }
b7af5a
61beb7 static int
e64b7b SizeAdvise (PGPPipeline *myself, unsigned long bytes)
88bb36 {
0a7b84 ¤   Context *context;
4687a6 ¤   PGPError¤   error;
beaf5a
6d29be ¤   pgpAssert (myself);
--a1ae 00123153f7a401001c3 Page 3 of pgpProtoMod.c
521ba4 ¤   pgpAssert (myself->magic == MAGIC);
1faf5a
d6ee0b ¤   context = myself->priv;
3cd30a ¤   pgpAssert (context);
4cebf4 ¤   pgpAssert (context->tail);
99af5a
c963fd ¤   error = DoFlush (context);
720161 ¤   if (error)
7efcee ¤   ¤   return error;
bbaf5a
b8ab86 ¤   return context->tail->sizeAdvise (context->tail, bytes)
66efe6 }
a8af5a
482978 static void
8cc7e1 Teardown (PGPPipeline *myself)
dabb36 {
b97b84 ¤   Context *context;
c0af5a
a129be ¤   pgpAssert (myself);
2f1ba4 ¤   pgpAssert (myself->magic == MAGIC);
92af5a
5bee0b ¤   context = myself->priv;
c2d30a ¤   pgpAssert (context);
91af5a
45cb05 ¤   if (context->tail)
d01e8a ¤   ¤   context->tail->teardown (context->tail);
f8af5a
c5d039 ¤   memset (context, 0, sizeof (*context));
e5fa6e ¤   pgpContextMemFree( cdkContext, context);
65d18c ¤   memset (myself, 0, sizeof (*myself));
8e0f16 ¤   pgpContextMemFree( cdkContext, myself);
7eefe6 }
34af5a
6541cd PGPPipeline **
81bbf3 Create (PGPPipeline **head)
e8bb36 {
3e0df0 ¤   PGPPipeline *mod;
437b84 ¤   Context *context;
35af5a
90bb3d ¤   if (!head)
597ed2 ¤   ¤   return NULL;
b6af5a
28973a ¤   context = pgpContextMemAlloc( cdkContext, sizeof (*context));
001ea4 ¤   if (!context)
3d7ed2 ¤   ¤   return NULL;
0b51b1 ¤   mod = pgpContextMemAlloc( cdkContext, sizeof (*mod));
3a5244 ¤   if (!mod) {
c7a8f3 ¤   ¤   pgpContextMemFree( cdkContext, context);
517ed2 ¤   ¤   return NULL;
789371 ¤   }
64af5a
dcf7cb ¤   mod->magic = MAGIC;
291f83 ¤   mod->write = Write;
f9ac4e ¤   mod->flush = Flush;
d20aaf ¤   mod->sizeAdvise = SizeAdvise;
94d3a2 ¤   mod->annotate = Annotate;
f296de ¤   mod->teardown = Teardown;
028f0b ¤   mod->name = "Prototype"; ·/* XXX Set myself to the module name! */
3001ea ¤   mod->priv = context;
51af5a
1cd039 ¤   memset (context, 0, sizeof (*context));
6af025 ¤   context->bufptr = context->buffer;
b0af5a
a965ad ¤   context->tail = *head;
ad2d11 ¤   *head = mod;
547fa2 ¤   return &context->tail;
23efe6 }
--669c 00097e6a84b401001c4 Page 1 of pgpRot13Mod.c
bc38e5 /*
1567f3 ·* pgpRot13Mod.c -- A pipeline module to rotate by 13 characters. ·A stupid
10e13f ·* encryption/decryption link for PGP!
a5775e ·*
a82195 ·* $Id: pgpRot13Mod.c,v 1.6 1997/06/25 19:40:25 lloyd Exp $
2c495d ·*/
d6af5a
bee2ff #include "pgpConfig.h"
4baf5a
01feb2 #include <stdio.h>
29af5a
cea146 #include "pgpDebug.h"
ec2ece #include "pgpPipeline.h"
04c32d #include "pgpRot13Mod.h"
d4af5a
60ea78 #define ROT13MAGIC¤ 0x13263952
8caf5a
c4eff5 Rot13Context {
a46df5 ¤   PGPByte buffer[BUFSIZ];
a9c98f ¤   PGPByte *bufptr;
e2c822 ¤   size_t buflen;
d075b0 ¤   PGPPipeline *tail;
5c82f7 };
a0af5a
845d09 static size_t
65d478 rot13 (PGPByte const *input, size_t inlen, PGPByte *output, size_t outlen)
e8bb36 {
11d18d ¤   size_t len = 0;
e30273 ¤   char c;
52af5a
21fb45 ¤   while (inlen && outlen) {
6b78d7 ¤   ¤   c = input[len];
dda91b ¤   ¤   output[len++] = (((c >= 'a' && c <= 'm') ||
c354e7 ¤   ¤   ¤   ¤   ··(c >= 'A' && c <= 'M')) ? c + 13 :
ae79cc ¤   ¤   ¤   ¤   ·((c >= 'n' && c <= 'z') ||
a3250f ¤   ¤   ¤   ¤   ··(c >= 'N' && c <= 'Z')) ? c - 13 :
24183f ¤   ¤   ¤   ¤   ·c);
ab3623 ¤   ¤   inlen--;
b4387e ¤   ¤   outlen--;
469371 ¤   }
e8bb7a ¤   return len;
19efe6 }
8aaf5a
1dbeb7 static int
d89836 DoFlush (Rot13Context *context)
4ebb36 {
bb6c75 ¤   size_t retlen;
0f5b01 ¤   PGPError¤   error = kPGPError_NoErr;
23af5a
0116d3 ¤   /* Try to flush anything that we have buffered */
ae49b8 ¤   while (context->buflen) {
fa88b9 ¤   ¤   retlen = context->tail->write (context->tail,
cad239 ¤   ¤   ¤   ¤   ¤   ·······context->bufptr,
d3ee65 ¤   ¤   ¤   ¤   ¤   ·······context->buflen,
c248b9 ¤   ¤   ¤   ¤   ¤   ·······&error);
94e166 ¤   ¤   context->buflen -= retlen;
5265bd ¤   ¤   memset (context->bufptr, 0, retlen);
98060f ¤   ¤   context->bufptr += retlen;
48c0b1 ¤   ¤   if (error)·
ec3b5b ¤   ¤   ¤   return error;
4a9371 ¤   }
dcc674 ¤   return error;
b7efe6 }
ceaf5a
e3beb7 static int
26d02e Flush (PGPPipeline *myself)
33bb36 {
a0323d ¤   Rot13Context *context;
d687a6 ¤   PGPError¤   error;
70af5a
2229be ¤   pgpAssert (myself);
974ab4 ¤   pgpAssert (myself->magic == ROT13MAGIC);
--d512 0001164f645401001c4 Page 2 of pgpRot13Mod.c
e0af5a
e2ee0b ¤   context = myself->priv;
71d30a ¤   pgpAssert (context);
35ebf4 ¤   pgpAssert (context->tail);
7eaf5a
0063fd ¤   error = DoFlush (context);
000161 ¤   if (error)
5bfcee ¤   ¤   return error;
88af5a
5e9819 ¤   return context->tail->flush (context->tail);
2defe6 }
57af5a
9c5d09 static size_t
952bcf rot13Write (PGPPipeline *myself, PGPByte const *buf, size_t size,
d597ae ¤   ····PGPError *error)
26bb36 {
01323d ¤   Rot13Context *context;
68103a ¤   PGPError myerror = kPGPError_NoErr;
c1c1bb ¤   size_t retlen, written = 0;
ffaf5a
da29be ¤   pgpAssert (myself);
1a4ab4 ¤   pgpAssert (myself->magic == ROT13MAGIC);
1eaf5a
baee0b ¤   context = myself->priv;
a6d30a ¤   pgpAssert (context);
a2ebf4 ¤   pgpAssert (context->tail);
dcaf5a
de43ab ¤   do {
be7ced ¤   ¤   myerror = DoFlush (context);
822996 ¤   ¤   if (myerror) {
18d82b ¤   ¤   ¤   if (error)
6c52c6 ¤   ¤   ¤   ¤   *error = myerror;
ffab0f ¤   ¤   ¤   return written;
1d0fe4 ¤   ¤   }
deaf5a
d21b17 ¤   ¤   /*
e64511 ¤   ¤   ·* Now that we dont have anything buffered, bring in more
03bbe3 ¤   ¤   ·* data from the passed-in buffer, rot13 it, and buffer
464169 ¤   ¤   ·* that to write out.
369de3 ¤   ¤   ·*/
05fe69 ¤   ¤   context->bufptr = context->buffer;
9501b9 ¤   ¤   context->buflen = rot13 (buf, size, context->buffer, BUFSIZ);
52bdd6 ¤   ¤   buf += context->buflen;
3b77c4 ¤   ¤   size -= context->buflen;
37aa82 ¤   ¤   written += context->buflen;
1eaf5a
d964ca ¤   } while (context->buflen > 0);
f3c130 ¤   /* Continue until we have nothing buffered */
89af5a
44279e ¤   return written;
26efe6 }
ebaf5a
4cbeb7 static int
f6a2bb rot13Annotate (PGPPipeline *myself, PGPPipeline *origin,
8b9bb8 ¤   ·······int type, PGPByte const *string, size_t size)
24bb36 {
61323d ¤   Rot13Context *context;
c25b01 ¤   PGPError¤   error = kPGPError_NoErr;
50af5a
1029be ¤   pgpAssert (myself);
f44ab4 ¤   pgpAssert (myself->magic == ROT13MAGIC);
7faf5a
f5ee0b ¤   context = myself->priv;
c5d30a ¤   pgpAssert (context);
f0ebf4 ¤   pgpAssert (context->tail);
34af5a
3363fd ¤   error = DoFlush (context);
9a0161 ¤   if (error)
b3fcee ¤   ¤   return error;
28af5a
9c0df2 ¤   return context->tail->annotate (context->tail, origin, type,
113153 ¤   ¤   ¤   ¤   ¤   string, size);
--4378 000db5f839f401001c4 Page 3 of pgpRot13Mod.c
7aefe6 }
46af5a
88beb7 static int
46f6c8 rot13SizeAdvise (PGPPipeline *myself, unsigned long bytes)
28bb36 {
a0323d ¤   Rot13Context *context;
615b01 ¤   PGPError¤   error = kPGPError_NoErr;
e4af5a
3329be ¤   pgpAssert (myself);
6a4ab4 ¤   pgpAssert (myself->magic == ROT13MAGIC);
0daf5a
88ee0b ¤   context = myself->priv;
f6d30a ¤   pgpAssert (context);
1bebf4 ¤   pgpAssert (context->tail);
c5af5a
8063fd ¤   error = DoFlush (context);
160161 ¤   if (error)
e1fcee ¤   ¤   return error;
10af5a
35e1b5 ¤   return context->tail->sizeAdvise (context->tail, bytes);
54efe6 }
f1af5a
cf2978 static void
9577a0 rot13Teardown (PGPPipeline *myself)
babb36 {
e4323d ¤   Rot13Context *context;
71af5a
da29be ¤   pgpAssert (myself);
114ab4 ¤   pgpAssert (myself->magic == ROT13MAGIC);
a6af5a
daee0b ¤   context = myself->priv;
cad30a ¤   pgpAssert (context);
04af5a
b1cb05 ¤   if (context->tail)
b81e8a ¤   ¤   context->tail->teardown (context->tail);
dfaf5a
19d039 ¤   memset (context, 0, sizeof (*context));
ac1963 ¤   memFree (context);
a7d18c ¤   memset (myself, 0, sizeof (*myself));
0e2cb2 ¤   memFree (myself);
18efe6 }
0caf5a
3341cd PGPPipeline **
942a66 rot13Create (PGPPipeline **head)
c6bb36 {
740df0 ¤   PGPPipeline *mod;
5d323d ¤   Rot13Context *context;
69af5a
02bb3d ¤   if (!head)
d37ed2 ¤   ¤   return NULL;
3faf5a
f96913 ¤   context = memAlloc (sizeof (*context));
341ea4 ¤   if (!context)
dc7ed2 ¤   ¤   return NULL;
a5d77c ¤   mod = memAlloc (sizeof (*mod));
62940b ¤   if (!mod){
defb82 ¤   ¤   memFree (context);
ea7ed2 ¤   ¤   return NULL;
6d9371 ¤   }
55af5a
7c2bbb ¤   mod->magic = ROT13MAGIC;
15f362 ¤   mod->write = rot13Write;
2a25a3 ¤   mod->write = Flush;
2934bb ¤   mod->sizeAdvise = rot13SizeAdvise;
4a8451 ¤   mod->annotate = rot13Annotate;
20f9c2 ¤   mod->teardown = rot13Teardown;
b89862 ¤   mod->name = "Rot 13 Module";
2e01ea ¤   mod->priv = context;
c7af5a
25d039 ¤   memset (context, 0, sizeof (*context));
e4f025 ¤   context->bufptr = context->buffer;
dbaf5a
--03e4 001f1b18adf401001c4 Page 4 of pgpRot13Mod.c
9765ad ¤   context->tail = *head;
de2d11 ¤   *head = mod;
d87fa2 ¤   return &context->tail;
f1efe6 }
--50b6 001f1d1fccc401001c5 Page 1 of pgpRot13Mod.h
bc38e5 /*
1acaef ·* definitions for a stupid encryption pipeline: rot13
7a775e ·*
86b06c ·* $Id: pgpRot13Mod.h,v 1.5 1997/06/25 19:40:25 lloyd Exp $
ea495d ·*/
f8af5a
5dadb8 #include "pgpOpaqueStructs.h"
b1af5a
6899c6 PGP_BEGIN_C_DECLARATIONS
64af5a
6585c0 PGPPipeline **rot13Create (PGPPipeline **head);
9faf5a
f11254 PGP_END_C_DECLARATIONS
--72b5 0003857e686401001c6 Page 1 of pgpSplit.c
bc38e5 /*
965a6d ·* $Id: pgpSplit.c,v 1.19 1997/12/12 01:14:18 heller Exp $
57495d ·*/
bcaf5a
f7e2ff #include "pgpConfig.h"
80af5a
dcfeb2 #include <stdio.h>
3a324c #include <string.h>
50af5a
cfa146 #include "pgpDebug.h"
5327c0 #include "pgpSplit.h"
646aaa #include "pgpAnnotate.h"
2a0d08 #include "pgpMem.h"
a82ece #include "pgpPipeline.h"
e8d11f #include "pgpUsuals.h"
1bc26c #include "pgpContext.h"
4faf5a
1dec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
75e514 #define kPGPSplitBufSize¤   16384
08db21 #else
b90df2 #define kPGPSplitBufSize¤   BUFSIZ
567454 #endif
48af5a
107408 #define SPLITMAGIC¤ 0x11223344
b9af5a
cf0ca1 #define MAXTAILS¤   2
fcaf5a
96e1a6 typedef struct SplitContext
66bb36 {
64f8fb ¤   PGPPipeline¤¤   pipe;
7267c5 ¤
ce5ad0 ¤   PGPByte¤¤   ¤   buffer[kPGPSplitBufSize];
55e2e6 ¤   PGPByte const *¤bufptr;
e33cb1 ¤   PGPByte const *¤bufend;
019412 ¤   int¤¤   ¤   ¤   curtail;
75eccb ¤   int¤¤   ¤   ¤   numtails;
d28ac9 ¤   PGPPipeline *¤  tail[MAXTAILS];
be0963 ¤   int¤¤   ¤   ¤   scope_depth;
834f00 ¤   DEBUG_STRUCT_CONSTRUCTOR( SplitContext )
0df4f0 } SplitContext;
f5af5a
9f38e5 /*
d729e3 ·* If we got an error while writing, the pending write data gets copied to
1b5998 ·* the context's buffer for re-transmission later. ·(Yes, this is needed to
7e495f ·* preserve the semantics of write().)
49495d ·*/
e0f1ae static PGPError
8873c3 DoFlush(SplitContext *context)
c0bb36 {
e39a0e ¤   PGPPipeline *tailp;
2187a6 ¤   PGPError¤   error;
6ff20c ¤   size_t len;
9aaf5a
a216d3 ¤   /* Try to flush anything that we have buffered */
9e673e ¤   len = context->bufend - context->bufptr;
daf440 ¤   while (context->curtail != context->numtails) {
f94b46 ¤   ¤   tailp = context->tail[context->curtail];
c69d75 ¤   ¤   while (len != 0) {
2a616c ¤   ¤   ¤   len = tailp->write(tailp, context->bufptr,
c3e453 ¤   ¤   ¤   ¤   ¤   ···len, &error);
6c99a0 ¤   ¤   ¤   context->bufptr += len;
07d82b ¤   ¤   ¤   if (error)
55b20f ¤   ¤   ¤   ¤   return error;
850fe4 ¤   ¤   }
10fe69 ¤   ¤   context->bufptr = context->buffer;
4035a3 ¤   ¤   len = context->bufend - context->bufptr;
06313c ¤   ¤   context->curtail++;
669371 ¤   }
db546e ¤   pgpClearMemory(context->buffer, len);
14141d ¤   context->bufptr = context->bufend = context->buffer;
8caf5a
38151e ¤   return kPGPError_NoErr;
--3744 000b4555856401001c6 Page 2 of pgpSplit.c
7aefe6 }
46af5a
9cf1ae static PGPError
f4c966 Flush(PGPPipeline *myself)
87bb36 {
659a0e ¤   PGPPipeline *tailp;
bbae55 ¤   SplitContext *context;
f187a6 ¤   PGPError¤   error;
48772c ¤   int¤¤   ¤   i;
f2af5a
27b81b ¤   pgpAssert(myself);
5c7681 ¤   pgpAssert(myself->magic == SPLITMAGIC);
c4af5a
f50a75 ¤   context = (SplitContext *)myself->priv;
aa213c ¤   pgpAssert(context);
83bdf0 ¤   pgpAssert(context->tail);
c6af5a
d175d9 ¤   error = DoFlush(context);
1e0161 ¤   if (error)
d4fcee ¤   ¤   return error;
eaaf5a
cc6938 ¤   for (i = 0; i < context->numtails; i++) {
08e820 ¤   ¤   tailp = context->tail[i];
955316 ¤   ¤   error = tailp->flush(tailp);
c5e3c2 ¤   ¤   if (error)
ab3b5b ¤   ¤   ¤   return error;
b79371 ¤   }
afaf5a
1e151e ¤   return kPGPError_NoErr;
4eefe6 }
a6af5a
a75d09 static size_t
7c2e8a Write(PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
c2bb36 {
1b9a0e ¤   PGPPipeline *tailp;
c2ae55 ¤   SplitContext *context;
e7505f ¤   size_t block, pending, myselfwrite;
7bfab9 ¤   PGPByte const *tmpbuf;
bfa371 ¤   size_t written = 0;
204ba4 ¤   int i;
0daf5a
64b81b ¤   pgpAssert(myself);
7e7681 ¤   pgpAssert(myself->magic == SPLITMAGIC);
4f4ca3 ¤   pgpAssert(error);
d5af5a
0e0a75 ¤   context = (SplitContext *)myself->priv;
ee213c ¤   pgpAssert(context);
0bbdf0 ¤   pgpAssert(context->tail);
13af5a
cd8d54 ¤   /* Write out anything still hanging around from last time */
6dd7fd ¤   *error = DoFlush(context);
685842 ¤   if (*error)
5a5d6a ¤   ¤   return written;
e0af5a
7df510 ¤   /* Okay, now write out the new stuff. */
96a0eb ¤   while (size) {
7ab5c7 ¤   ¤   /* Never write more in one block than we can buffer */
3f759e ¤   ¤   block = pgpMin(size, sizeof(context->buffer));
5eaf5a
549b82 ¤   ¤   /* Now write out the current block to each of the tails. */
e72606 ¤   ¤   for (i = 0; i < context->numtails; i++) {
c3a301 ¤   ¤   ¤   tailp = context->tail[i];¤  /* Current tail */
111ebd ¤   ¤   ¤   tmpbuf = buf;¤  ¤   /* Current write pointer */
01b5a6 ¤   ¤   ¤   pending = block;¤   /* Current size */
9df603 ¤   ¤   ¤   do {
a6f9ed ¤   ¤   ¤   ¤   myselfwrite = tailp->write(tailp, tmpbuf,
68e509 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···pending, error);
a13418 ¤   ¤   ¤   ¤   tmpbuf += myselfwrite;
c1dfb5 ¤   ¤   ¤   ¤   pending -= myselfwrite;
ae2648 ¤   ¤   ¤   ¤   if (!*error)
dc5914 ¤   ¤   ¤   ¤   ¤   continue;
b4b0d5 ¤   ¤   ¤   ¤   /* -- Error handling -- */
--a564 000fb7fc300401001c6 Page 3 of pgpSplit.c
506367 ¤   ¤   ¤   ¤   /* Remember how far we've gotten */
615143 ¤   ¤   ¤   ¤   context->curtail = i;
50980e ¤   ¤   ¤   ¤   /*
93291c ¤   ¤   ¤   ¤   ·* If we get an error while writing to the
bf027e ¤   ¤   ¤   ¤   ·* first tail, we don't need to buffer the
de6f45 ¤   ¤   ¤   ¤   ·* bytes after the current write pointer,
81a301 ¤   ¤   ¤   ¤   ·* since we've never done anything with them,
e461d7 ¤   ¤   ¤   ¤   ·* so we aren't responsible for them.
bd1020 ¤   ¤   ¤   ¤   ·*/
6d1822 ¤   ¤   ¤   ¤   if (i == 0)
430b74 ¤   ¤   ¤   ¤   ¤   block -= pending;
89980e ¤   ¤   ¤   ¤   /*
6a291c ¤   ¤   ¤   ¤   ·* If we get an error while writing to the
5de64d ¤   ¤   ¤   ¤   ·* last tail, we don't need to remember the
b00d02 ¤   ¤   ¤   ¤   ·* bytes we've managed to write to every
6a2b05 ¤   ¤   ¤   ¤   ·* tail; only the following bytes, which
c11ec9 ¤   ¤   ¤   ¤   ·* we've accepted responsibility for by
be335c ¤   ¤   ¤   ¤   ·* writing out somewhere else.
4a1020 ¤   ¤   ¤   ¤   ·*/
7dd486 ¤   ¤   ¤   ¤   if (i == context->numtails-1) {
ffdba0 ¤   ¤   ¤   ¤   ¤   buf = tmpbuf;
927904 ¤   ¤   ¤   ¤   ¤   written += block-pending;
b31d40 ¤   ¤   ¤   ¤   ¤   block = pending;
642613 ¤   ¤   ¤   ¤   }
a56369 ¤   ¤   ¤   ¤   /* Copy data to buffer for later DoFlush() */
60c5ca ¤   ¤   ¤   ¤   memcpy(context->buffer, buf, block);
8303b7 ¤   ¤   ¤   ¤   context->bufend = context->buffer+block;
9d0d67 ¤   ¤   ¤   ¤   context->bufptr = context->bufend-pending;
93650d ¤   ¤   ¤   ¤   /* And return the amount written plus buffer */
1ea77b ¤   ¤   ¤   ¤   return written + block;
75c816 ¤   ¤   ¤   } while (pending);
c20fe4 ¤   ¤   }
1eaaaf ¤   ¤   /* Advance pointers and go on... */
c62358 ¤   ¤   buf += block;
8bdf86 ¤   ¤   size -= block;
f2879e ¤   ¤   written += block;
5a9371 ¤   }
e1af5a
0ee765 ¤   return written;¤
b9efe6 }
01af5a
0938e5 /*
f4b2ac ·* Annotate is a bit magic. ·The problem is that annotations are
a790c1 ·* defined, as a class, to atomically succeed or fail. ·One particular
0a3dd9 ·* annotation might play fast & loose with this, but we aren't allowed
807a42 ·* to break it for *all* annotations.
94775e ·*
de4867 ·* But if we pass an annotation down the first tail, and it succeeds
15a4ab ·* (no error returned), then pass it down the second, and get an error,
b3ec42 ·* things are a bit screwed up, because lots of modules saw the annotation
0ad2ad ·* succeed and altered their state accordingly.
4f775e ·*
5370a9 ·* The solution seems to be to pass annotations down *one tail only*,
4e94a3 ·* which we use the first tail for. ·Other tails see data, but no
6f1b33 ·* annotations.
fa495d ·*/
77f1ae static PGPError
d84ddc Annotate(PGPPipeline *myself, PGPPipeline *origin, int type,
9bb0b1 ¤   ··PGPByte const *string, size_t size)
04bb36 {
6eae55 ¤   SplitContext *context;
2687a6 ¤   PGPError¤   error;
aaaf5a
6eb81b ¤   pgpAssert(myself);
2a7681 ¤   pgpAssert(myself->magic == SPLITMAGIC);
91af5a
bf0a75 ¤   context = (SplitContext *)myself->priv;
d6213c ¤   pgpAssert(context);
2abdf0 ¤   pgpAssert(context->tail);
faaf5a
a375d9 ¤   error = DoFlush(context);
fb0161 ¤   if (error)
--24ab 000e0ec25c5401001c6 Page 4 of pgpSplit.c
a2fcee ¤   ¤   return error;
fbaf5a
db74a1 ¤   error = context->tail[0]->annotate(context->tail[0], origin, type,
09096e ¤   ¤   ¤   ¤   ¤   ···string, size);
09ff2e ¤   if (!error)
046467 ¤   ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
8d04c8 ¤   pgpAssert(context->scope_depth != -1);
e0c674 ¤   return error;
ffefe6 }
1faf5a
7d38e5 /*
cbc32f ·* Note that because of the way we do annotations, if a SizeAdvise
ce7a99 ·* arrives while we're inside a scope, we can't pass it down to any but
557871 ·* the first tail; it is meaningless to the others. ·So we bail out
c246fa ·* of the loop early in that case.
92495d ·*/
88f1ae static PGPError
bc99d0 SizeAdvise(PGPPipeline *myself, unsigned long bytes)
dcbb36 {
b8ae55 ¤   SplitContext *context;
f887a6 ¤   PGPError¤   error;
954ba4 ¤   int i;
d3af5a
e2b81b ¤   pgpAssert(myself);
fa7681 ¤   pgpAssert(myself->magic == SPLITMAGIC);
45af5a
f40a75 ¤   context = (SplitContext *)myself->priv;
35213c ¤   pgpAssert(context);
16bdf0 ¤   pgpAssert(context->tail);
aeaf5a
3d75d9 ¤   error = DoFlush(context);
760161 ¤   if (error)
10fcee ¤   ¤   return error;
3baf5a
3a54dd ¤   for (i = 0; i < context->numtails; i++) ·{
a59e98 ¤   ¤   error = context->tail[i]->sizeAdvise(context->tail[i], bytes);
f617c7 ¤   ¤   if (error || context->scope_depth)
9c3b5b ¤   ¤   ¤   return error;
0a9371 ¤   }
7b151e ¤   return kPGPError_NoErr;
e4efe6 }
ebaf5a
e1f1ae static PGPError
53bf01 Teardown(PGPPipeline *myself)
75bb36 {
8350a5 ¤   SplitContext *¤ myContext;
4ed312 ¤   int¤¤   ¤   ¤   i;
10e9fa ¤   PGPContextRef¤  cdkContext;
0eaf5a
0eb81b ¤   pgpAssert(myself);
c07681 ¤   pgpAssert(myself->magic == SPLITMAGIC);
6baf5a
1e4d66 ¤   myContext = (SplitContext *)myself->priv;
2cb81b ¤   pgpAssert(myself);
11696e ¤   cdkContext¤ = myself->cdkContext;
5caf5a
86174f ¤   for (i = 0; i < myContext->numtails; i++)
11c7a1 ¤   {
f6b889 ¤   ¤   if ( IsntNull( myContext->tail[i] ) )
b939a9 ¤   ¤   ¤   myContext->tail[i]->teardown(myContext->tail[i]);
b99371 ¤   }
5daf5a
eb3599 ¤   pgpClearMemory( myContext, ·sizeof(*myContext));
dabaf7 ¤   pgpContextMemFree( cdkContext, myContext);
f867c5 ¤
31151e ¤   return kPGPError_NoErr;
9aefe6 }
34af5a
01a36e ¤   PGPPipeline **
f63622 pgpSplitCreate(
f83163 ¤   PGPContextRef¤  cdkContext,
e0198b ¤   PGPPipeline **¤ head)
--e720 001e25dc244401001c6 Page 5 of pgpSplit.c
2cbb36 {
1ed0e6 ¤   PGPPipeline *¤  mod;
5950a5 ¤   SplitContext *¤ myContext;
c4af5a
92bb3d ¤   if (!head)
dc7ed2 ¤   ¤   return NULL;
e2af5a
5ad93f ¤   myContext = (SplitContext *)pgpContextMemAlloc( cdkContext,
a09b36 ¤   ¤   sizeof(*myContext), kPGPMemoryMgrFlags_Clear );
9f9b02 ¤   if ( IsNull( myContext ) )
717ed2 ¤   ¤   return NULL;
871b52 ¤   ¤
6ed680 ¤   mod = &myContext->pipe;
45af5a
703af3 ¤   mod->magic¤ ¤   = SPLITMAGIC;
0eb327 ¤   mod->write¤ ¤   = Write;
9f0a98 ¤   mod->flush¤ ¤   = Flush;
d81d63 ¤   mod->sizeAdvise¤= SizeAdvise;
bbb5a2 ¤   mod->annotate¤  = Annotate;
6b05ac ¤   mod->teardown¤  = Teardown;
578b57 ¤   mod->name¤  ¤   = "Split module";
4cd251 ¤   mod->priv ¤ ¤   = myContext;
93a99e ¤   mod->cdkContext¤= cdkContext;
51af5a
dc7d1f ¤   myContext->bufptr¤  = myContext->buffer;
cf1625 ¤   myContext->curtail ¤= myContext->numtails = 1;
1a85a5 ¤   myContext->bufptr¤  = myContext->bufend = myContext->buffer;
f8af5a
fbd835 ¤   myContext->tail[0] = *head;
a02d11 ¤   *head = mod;
2adbda ¤   return &myContext->tail[0];
c6efe6 }
1baf5a
9741cd PGPPipeline **
81e951 pgpSplitAdd(PGPPipeline *myself)
9fbb36 {
45ae55 ¤   SplitContext *context;
1bde63 ¤   PGPPipeline **tailp;
bfaf5a
a6b81b ¤   pgpAssert(myself);
987681 ¤   pgpAssert(myself->magic == SPLITMAGIC);
cfaf5a
c10a75 ¤   context = (SplitContext *)myself->priv;
89213c ¤   pgpAssert(context);
3bbdf0 ¤   pgpAssert(context->tail);
10af5a
26531a ¤   if (context->numtails == MAXTAILS)
f5bbde ¤   ¤   return 0;
321f26 ¤   if (context->curtail != context->numtails)
105197 ¤   ¤   return 0;¤  /* We're in the middle of things! */
c8af5a
94d08e ¤   tailp = ·&context->tail[context->numtails++];
9d4886 ¤   context->curtail = context->numtails;
6dc17c ¤   return tailp;
e2efe6 }
--23b4 001e0bb313a401001c7 Page 1 of pgpSplit.h
bc38e5 /*
a66702 ·* Split module - one input, multiple outputs.
a590e9 ·* All outputs get data, but ONLY THE ORIGINAL OUTPUT
86dc58 ·* GETS ANNOTATIONS. ·(Error-handling is impossible otherwise.)
ca775e ·*
bb33d7 ·* $Id: pgpSplit.h,v 1.7 1997/06/25 19:40:26 lloyd Exp $
20495d ·*/
f1af5a
7299c6 PGP_BEGIN_C_DECLARATIONS
79af5a
68adb8 #include "pgpOpaqueStructs.h"
96e82c #include "pgpPubTypes.h"
4eaf5a
9faf5a
5a0bba PGPPipeline ·**pgpSplitCreate ( PGPContextRef cdkContext,
e2d8fa ¤   ¤   ¤   ¤   PGPPipeline **head);
11551a PGPPipeline ·**pgpSplitAdd (PGPPipeline *myself);
a5af5a
e01254 PGP_END_C_DECLARATIONS
--fcc1 0007d704f97401001c8 Page 1 of pgpVMemMod.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
af77fd ¤   Module to output to a variable-sized memory buffer
49af5a
50540a ¤   We do allow a maximum size to be specified. ·If we overflow that size,
fd2648 ¤   we discard the rest.
f0c4c4 ¤   We provide an annotation to tell how much we wrote or would have written.
85af5a
f1b4e5 ¤   $Id: pgpVMemMod.c,v 1.23.4.1.2.1 1998/11/12 03:21:28 heller Exp $
b6f7f7 ____________________________________________________________________________*/
6faf5a
b0e2ff #include "pgpConfig.h"
9baf5a
47feb2 #include <stdio.h>
7b324c #include <string.h>
a4af5a
f9a146 #include "pgpDebug.h"
3745ee #include "pgpVMemMod.h"
1b6aaa #include "pgpAnnotate.h"
1e0d08 #include "pgpMem.h"
852f8d #include "pgpErrors.h"
7c2ece #include "pgpPipeline.h"
66d11f #include "pgpUsuals.h"
59910a #include "pgpFIFO.h"
845430 #include "pgpUtilitiesPriv.h"
f2c26c #include "pgpContext.h"
a8af5a
eba433 #define VMEMMODMAGIC¤   0xdeafbabe
33af5a
3b38e5 /*
97f723 ·* Note that byte_count may come to exceed buf_size, in which case we
2dd14d ·* discard the overflow. ·We provide an annotation to read the total number
3b215a ·* of bytes written.
16495d ·*/
992bbe typedef struct vmemModContext {
a88b60 ¤   PGPPipeline¤pipe;
4c67c5 ¤
ca7929 ¤   int scope_depth;
442f18 ¤   PGPBoolean enable;¤ ¤   ¤   /* True if accepting data, false to discard */
5c7274 ¤   size_t max_size;¤   ¤   ¤   /* Max number of bytes we will accept */
1fb85a ¤   size_t byte_count;¤ ¤   ¤   /* Number of bytes we have been given */
856610 ¤   size_t fifo_count;¤ ¤   ¤   /* Number of bytes in fifo */
31f5eb ¤   PGPFifoDesc const *fd;¤ ¤   /* Type of fifo we use */
bea323 ¤   PGPFifoContext *fifo;¤  ¤   /* Fifo we store into */
b8fbd4 ¤   PGPBoolean secure;¤ ¤   ¤   /* Use secure memory allocations */
72e2a3 ¤   DEBUG_STRUCT_CONSTRUCTOR( vmemModContext )
bc3868 } vmemModContext;
96af5a
beaf5a
8df1ae static PGPError
980cd4 vmemFlush (PGPPipeline *myself)
d8bb36 {
13a5dd ¤   vmemModContext *context;
fbaf5a
7029be ¤   pgpAssert (myself);
878621 ¤   pgpAssert (myself->magic == VMEMMODMAGIC);
f2af5a
3d6b83 ¤   context = (vmemModContext *)myself->priv;
29d30a ¤   pgpAssert (context);
d6af5a
b62d68 ¤   return( kPGPError_NoErr );
80efe6 }
e3af5a
dab400 /* Write what is given, but disard any overflows. */
665d09 static size_t
017b47 vmemWrite (PGPPipeline *myself, PGPByte const *buffer, size_t size,
fb0431 ¤   ···PGPError *error)
6ebb36 {
77a5dd ¤   vmemModContext *context;
7daf5a
--409a 000c9cbde73401001c8 Page 2 of pgpVMemMod.c
c629be ¤   pgpAssert (myself);
888621 ¤   pgpAssert (myself->magic == VMEMMODMAGIC);
99af5a
e16b83 ¤   context = (vmemModContext *)myself->priv;
59d30a ¤   pgpAssert (context);
67af5a
1470a0 ¤   /* If disabled, discard data */
b2e4c4 ¤   if (!context->enable)
b0b771 ¤   ¤   return size;
89af5a
df5ca9 ¤   if (context->max_size > context->byte_count) {
6f03c3 ¤   ¤   size_t avail = context->max_size - context->byte_count;
b2a624 ¤   ¤   size_t to_write = pgpMin (avail, size);
ebaf5a
d99d07 ¤   ¤   while (to_write) {
620e8d ¤   ¤   ¤   size_t written = pgpFifoWrite (context->fd, context->fifo,
9acdb5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···buffer, to_write);
d977ba ¤   ¤   ¤   context->fifo_count += written;
41f127 ¤   ¤   ¤   buffer += written;
21a4c0 ¤   ¤   ¤   to_write -= written;
010fe4 ¤   ¤   }
df9371 ¤   }
d9af5a
d60161 ¤   if (error)
a7a79e ¤   ¤   *error = kPGPError_NoErr;
db7904 ¤   context->byte_count += size;
cff6fa ¤   return size;
6aefe6 }
10af5a
1e38e5 /*
ca6584 ·* We accept an annotation to return the number of bytes we were asked
6624e4 ·* to write. ·We also provide an annotation to return the max size of the
4816e9 ·* buffer. ·Plus there is one to return the number of bytes in the FIFO.
f754e8 ·* Another annotation makes us copy our FIFO data to a buffer and return
84f082 ·* its pointer.
22a347 ·* We return our results in the passed-in string pointer, which must be
a7f7f6 ·* of size sizeof(size_t).
3b0560 ·* The ENABLE annotation causes us to turn on and off whether we accept data.
42495d ·*/
5ff1ae static PGPError
aa9ca8 vmemAnnotate (PGPPipeline *myself, PGPPipeline *origin, int type,
9eb533 ¤   ······PGPByte const *string, size_t size)
87bb36 {
28a5dd ¤   vmemModContext *context;
7898ec ¤   PGPByte const *¤fbuf;
87f0bf ¤   PGPMemoryMgrRef¤memoryMgr¤  = NULL;
1b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
43af5a
d1df26 ¤   (void)origin;¤  /* Avoid warning */
1a7aab ¤   (void)size;
e0af5a
d929be ¤   pgpAssert (myself);
818621 ¤   pgpAssert (myself->magic == VMEMMODMAGIC);
baaf5a
6c6b83 ¤   context = (vmemModContext *)myself->priv;
30d30a ¤   pgpAssert (context);
ee67c5 ¤
6fb417 ¤   memoryMgr¤  = PGPGetContextMemoryMgr( myself->cdkContext );
adaf5a
9c1609 ¤   switch (type) {
afd314 ¤   case PGPANN_MEM_BYTECOUNT:
d0d671 ¤   ¤   /* Number of bytes we were asked to write */
fce555 ¤   ¤   pgpAssert (string);
07b663 ¤   ¤   pgpAssert (size == sizeof(size_t));
5fec35 ¤   ¤   *(size_t *)string = context->byte_count;
26a117 ¤   ¤   return( kPGPError_NoErr );
378f00 ¤   case PGPANN_MEM_BUFSIZE:
db166b ¤   ¤   /* Return number of bytes in FIFO */
52e555 ¤   ¤   pgpAssert (string);
3bb663 ¤   ¤   pgpAssert (size == sizeof(size_t));
cef62a ¤   ¤   *(size_t *)string = context->fifo_count;
c9a117 ¤   ¤   return( kPGPError_NoErr );
--f4d3 000713d4b48401001c8 Page 3 of pgpVMemMod.c
316766 ¤   case PGPANN_MEM_MAXSIZE:
7d2bc6 ¤   ¤   /* Return maximum size of buffer */
28e555 ¤   ¤   pgpAssert (string);
6eb663 ¤   ¤   pgpAssert (size == sizeof(size_t));
b1994f ¤   ¤   *(size_t *)string = context->max_size;
56a117 ¤   ¤   return( kPGPError_NoErr );
001b52 ¤   ¤
e14fd2 ¤   case PGPANN_MEM_PREPEND:
f91d53 ¤   ¤   /* This provides some data to stick into fifo */
e89b02 ¤   ¤   while (size) {
db0e8d ¤   ¤   ¤   size_t written = pgpFifoWrite (context->fd, context->fifo,
1cfa13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPByte *)string, size);
0f77ba ¤   ¤   ¤   context->fifo_count += written;
6ff986 ¤   ¤   ¤   context->byte_count += written;
219e52 ¤   ¤   ¤   string += written;
c71cfa ¤   ¤   ¤   size -= written;
7d0fe4 ¤   ¤   }
f9a117 ¤   ¤   return( kPGPError_NoErr );
17af5a
a5f047 ¤   case PGPANN_MEM_MEMBUF:
fdc7a1 ¤   {
cca0fd ¤   ¤   PGPByte *¤  membuf¤ = NULL;
174353 ¤   ¤   PGPByte *¤  tbuf¤   = NULL;
3744f3 ¤   ¤   PGPSize¤¤   length;
e067c5 ¤
c1092b ¤   ¤   /* Return memory buffer with fifo data. This removes data from fifo */
32a5fd ¤   ¤   /* Produces a null pointer if couldn't allocate data */
70b3df ¤   ¤   /* Always stores a null byte beyond data (not counted in length) */
98e555 ¤   ¤   pgpAssert (string);
90f335 ¤   ¤   pgpAssert (size == sizeof(PGPByte *));
731b52 ¤   ¤
f9a229 ¤   ¤   /* this data is returned to the caller so we use PGPNewData */
b1b2e2 ¤   ¤   if( context->secure ) {
ab6431 ¤   ¤   ¤   tbuf = membuf = (PGPByte *)
6813ed ¤   ¤   ¤   ¤   PGPNewSecureData( memoryMgr, context->fifo_count + 1, 0);
7545a6 ¤   ¤   } else {
d56431 ¤   ¤   ¤   tbuf = membuf = (PGPByte *)
e6065c ¤   ¤   ¤   ¤   PGPNewData( memoryMgr, context->fifo_count + 1, 0);
660fe4 ¤   ¤   }
fae644 ¤   ¤   if ( IsntNull( membuf ) )
a15b34 ¤   ¤   {
60dabf ¤   ¤   ¤   membuf[ context->fifo_count ] = '\0';¤  /* Null beyond buffer */
642b85 ¤   ¤   ¤   ¤
498abb ¤   ¤   ¤   fbuf = pgpFifoPeek( context->fd, context->fifo, &length );
ede7fc ¤   ¤   ¤   while( length != 0 )
10f776 ¤   ¤   ¤   {
136d1e ¤   ¤   ¤   ¤   pgpCopyMemory( fbuf, tbuf, length );
86257a ¤   ¤   ¤   ¤   if ( IsntNull( membuf ) ) {
792bfd ¤   ¤   ¤   ¤   ¤   tbuf += length;
7ac7e1 ¤   ¤   ¤   ¤   ¤   pgpFifoSeek( context->fd, context->fifo, length );
682613 ¤   ¤   ¤   ¤   }
b42b85 ¤   ¤   ¤   ¤
2869e2 ¤   ¤   ¤   ¤   fbuf¤   = pgpFifoPeek( context->fd,
3b8c6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   context->fifo, &length );
0ba3a6 ¤   ¤   ¤   }
010fe4 ¤   ¤   }
160e1d ¤   ¤   else
bd5b34 ¤   ¤   {
e7124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
910fe4 ¤   ¤   }
1f1b52 ¤   ¤
58733c ¤   ¤   *(PGPByte **)string = membuf;
67e55e ¤   ¤   return( err );
1a9371 ¤   }
0367c5 ¤
9d4f2b ¤   case PGPANN_MEM_ENABLE:
71e555 ¤   ¤   pgpAssert (string);
ad4314 ¤   ¤   pgpAssert (size == 1);
97ab39 ¤   ¤   context->enable = *(PGPByte *)string;
12a117 ¤   ¤   return( kPGPError_NoErr );
022f72 ¤   default:
71d30b ¤   ¤   ;¤  ¤   /* do nothing */
--44db 000ccd1dcfd401001c8 Page 4 of pgpVMemMod.c
a19371 ¤   }
93af5a
9aeb30 ¤   PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
9f04c8 ¤   pgpAssert(context->scope_depth != -1);
8aaf5a
8c2d68 ¤   return( kPGPError_NoErr );
39efe6 }
5caf5a
5af1ae static PGPError
345ab9 vmemSizeAdvise (PGPPipeline *myself, unsigned long bytes)
7fbb36 {
bfa5dd ¤   vmemModContext *context;
fcaf5a
9bd223 ¤   (void)bytes;
07af5a
eb29be ¤   pgpAssert (myself);
ad8621 ¤   pgpAssert (myself->magic == VMEMMODMAGIC);
21af5a
cb6b83 ¤   context = (vmemModContext *)myself->priv;
5dd30a ¤   pgpAssert (context);
cfaf5a
712d68 ¤   return( kPGPError_NoErr );
91efe6 }
6caf5a
16f1ae static PGPError
fdce34 vmemTeardown (PGPPipeline *myself)
7ebb36 {
b2a5dd ¤   vmemModContext *context;
3867c5 ¤
c73982 ¤   pgpAssertAddrValid( myself, PGPPipeline );
85af5a
7629be ¤   pgpAssert (myself);
938621 ¤   pgpAssert (myself->magic == VMEMMODMAGIC);
19af5a
316b83 ¤   context = (vmemModContext *)myself->priv;
8bd30a ¤   pgpAssert (context);
bfaf5a
2e7ccf ¤   pgpFifoDestroy( context->fd, context->fifo );
4e67c5 ¤
863736 ¤   pgpClearMemory( context, ·sizeof (*context));
436cf3 ¤   PGPFreeData( context );
6b67c5 ¤
562d68 ¤   return( kPGPError_NoErr );
7defe6 }
60af5a
8c15e8 static PGPPipeline *
6da1cb vmemCreate (
483163 ¤   PGPContextRef¤  cdkContext,
286733 ¤   PGPPipeline **¤ head,
3de86e ¤   size_t¤ ¤   ¤   max_size,
b180ed ¤   PGPBoolean¤ ¤   secure)
a9bb36 {
a20df0 ¤   PGPPipeline *mod;
b3a5dd ¤   vmemModContext *context;
d5c3f1 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
6e67c5 ¤
a0bb3d ¤   if (!head)
427ed2 ¤   ¤   return NULL;
5aaf5a
712338 ¤   *head = 0;
2caf5a
6ac8f5 ¤   context = (vmemModContext *)PGPNewData( memoryMgr,
c8f235 ¤   ¤   sizeof(*context), kPGPMemoryMgrFlags_Clear);
6b1ea4 ¤   if (!context)
c87ed2 ¤   ¤   return NULL;
4c9228 ¤   mod = &context->pipe;
89af5a
41d6a4 ¤   mod->magic = VMEMMODMAGIC;
562b15 ¤   mod->write = vmemWrite;
10bec2 ¤   mod->flush = vmemFlush;
c3b7d3 ¤   mod->sizeAdvise = vmemSizeAdvise;
cc009e ¤   mod->annotate = vmemAnnotate;
--4a01 001c910f3ac401001c8 Page 5 of pgpVMemMod.c
c9d3c6 ¤   mod->teardown = vmemTeardown;
b67ad4 ¤   mod->name = secure¤ ? "Securely write variable-sized memory"
ff2b94 ¤   ¤   ¤   ¤   ¤   ¤   : "Write variable-sized memory";
8b01ea ¤   mod->priv = context;
e0a99e ¤   mod->cdkContext¤= cdkContext;
e7af5a
c71af8 ¤   context->fd = secure ? &pgpSecureByteFifoDesc : &pgpByteFifoDesc;
05e58f ¤   context->fifo = pgpFifoCreate( cdkContext, context->fd );
41df6b ¤   context->max_size = max_size;
e10257 ¤   context->enable = 1;
df2b3a ¤   context->secure = secure;
beaf5a
772d11 ¤   *head = mod;
7a1fea ¤   return mod;
4befe6 }
64af5a
3aaf5a
6ef07b PGPPipeline *
1f6dff pgpVariableMemModCreate (
0c3163 ¤   PGPContextRef¤  cdkContext,
ee6733 ¤   PGPPipeline **¤ head,
6a96d6 ¤   size_t¤ ¤   ¤   max_size)
15bb36 {
0b44cb ¤   return vmemCreate (cdkContext, head, max_size, FALSE);
9aefe6 }
03af5a
28f07b PGPPipeline *
44526d pgpSecureVariableMemModCreate (
d53163 ¤   PGPContextRef¤  cdkContext,
6d6733 ¤   PGPPipeline **¤ head,
a696d6 ¤   size_t¤ ¤   ¤   max_size)
36bb36 {
bf7849 ¤   return vmemCreate (cdkContext, head, max_size, TRUE);
c9efe6 }
--69f0 001c28adf0a401001c9 Page 1 of pgpVMemMod.h
bc38e5 /*
dce3cd ·* pgpVMemMod.h -- Module to output to a variable-size memory buffer
24775e ·*
a4901c ·* Copyright (C) 1996, 1997 Network Associates, Inc. and its affiliates.
b320c7 ·* All rights reserved
8b775e ·*
74976b ·* $Id: pgpVMemMod.h,v 1.5.4.1.2.1 1998/11/12 03:21:29 heller Exp $
b6495d ·*/
8baf5a
550ad5 #ifndef Included_pgpVMemMod_h
8e5ee1 #define Included_pgpVMemMod_h
28af5a
2899c6 PGP_BEGIN_C_DECLARATIONS
13af5a
e3275d #include "pgpPipelineOpaqueStructs.h"
13e82c #include "pgpPubTypes.h"
7c6773 #include "pgpMemoryMgr.h"
b9af5a
4baf5a
18af8d PGPPipeline ·*¤ pgpVariableMemModCreate(
f6a813 ¤   ¤   PGPContextRef context,
a27ffc ¤   ¤   PGPPipeline **head, size_t max_size);
75af5a
e82374 PGPPipeline ·*¤ pgpSecureVariableMemModCreate(
bfa813 ¤   ¤   PGPContextRef context,
327ffc ¤   ¤   PGPPipeline **head, size_t max_size);
bdaf5a
371254 PGP_END_C_DECLARATIONS
d0af5a
c29878 #endif /* Included_pgpVMemMod_h */

--e033 0017a2fc53a401001ca Page 1 of Makefile.in
5ea601 #
d58e3d # priv/crypto/random/
3ca601 #
e4f392 # $Id: Makefile.in,v 1.5 1997/06/25 01:17:18 hal Exp $
07a601 #
f8af5a
7bcbd2 OBJS=pgpRandomPool.o pgpRndUnix.o pgpRndSeed.o pgpRandomX9_17.o
8ee502 PRIVHDRS=pgpRnd.h pgpRndSeed.h pgpRandomX9_17.h pgpRandomContext.h \
432e9c ¤   pgpRandomPoolPriv.h
c5af5a
45b7a3 all:: DONE
7aaf5a
--dcde 0012a1fe76c401001cb Page 1 of pgpRandomContext.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
ad4f75 ¤   $Id: pgpRandomContext.h,v 1.5.10.1 1998/11/12 03:21:30 heller Exp $
ddf7f7 ____________________________________________________________________________*/
fe7949 #ifndef Included_pgpRandomContext_h¤/* [ */
359bb5 #define Included_pgpRandomContext_h
fcaf5a
44af5a
e1adb8 #include "pgpOpaqueStructs.h"
6ee82c #include "pgpPubTypes.h"
85af5a
6099c6 PGP_BEGIN_C_DECLARATIONS
f9af5a
681f9e struct PGPRandomVTBL
98bb36 {
32f5fd ¤   char const *¤   name;
65e47f ¤   void¤   (*addBytes) (void *priv, PGPByte const *buf, PGPUInt32 len);
161880 ¤   void¤   (*getBytesEntropy) (void *priv, PGPByte *buf, PGPUInt32 len,·
0e25d3 ¤   ·························PGPUInt32 bits);
76ec9b ¤   void¤   (*stir) (void *priv);
ea2fa1 } ;
e8af5a
5aaf5a
298c76 struct PGPRandomContext
dabb36 {
f6429f ¤   PGPContextRef¤  ¤   ¤   context;
c599ca ¤   PGPRandomVTBL const *¤  vtbl;
8a55ae ¤   void *¤ ¤   ¤   ¤   ¤   priv;
d2749a ¤   void (*destroy)¤¤   ¤   (PGPRandomContext *rc);
da82f7 };
21af5a
b6af5a
785df0 #define pgpRandomAddBytes(rc,b,l) (rc)->vtbl->addBytes((rc)->priv, b, l)
f95f9c #define pgpRandomGetBytesEntropy(rc,b,l,t) \
23fc5a ¤   (rc)->vtbl->getBytesEntropy((rc)->priv, b, l, t)
9faaf4 #define pgpRandomStir(rc) (rc)->vtbl->stir((rc)->priv)
a1a8fa #define pgpRandomDestroy(rc)¤   \
4c3397 ¤   if ( IsntNull( (rc)->destroy ) ) \
ef1149 ¤   ¤   (rc)->destroy(rc);\
4e4f55 ¤   else\
8a18d4 ¤   ¤   pgpContextMemFree( rc->context, rc )
78af5a
03af5a
8faf5a
3067c5 ¤
bf1254 PGP_END_C_DECLARATIONS
59af5a
ca7233 #endif /* ] Included_pgpRandomContext_h */
45af5a
f6af5a
bd7e4d /*__Editor_settings____
37af5a
5d4126 ¤   Local Variables:
077b17 ¤   tab-width: 4
410e6c ¤   End:
535f8c ¤   vi: ts=4 sw=4
af9e9b ¤   vim: si
70d062 _____________________*/
2aaf5a
--3b63 00016b30b66401001cc Page 1 of pgpRandomPool.c
bc38e5 /*
019e83 ·* True random number computation and storage
9d775e ·*
5510a4 ·* Wrtten by Colin Plumb.
dc775e ·*
09a93f ·* This performs a strong hash on the data as it is fed into the
35a40a ·* pool, and the pool is again strongly hashed to produce the output
521e75 ·* of the random-number generator. ·This is overkill, as either step
d79295 ·* should produce high-quality numbers.
ae775e ·*
5ef77a ·* $Id: pgpRandomPool.c,v 1.14 1998/06/19 13:56:56 pbj Exp $
08495d ·*/
b6ed82 #include ·"pgpConfig.h"
53af5a
12bea3 #include <stdlib.h>
6a324c #include <string.h>
b9af5a
acc5d5 #include "pgpBase.h"
1c0d08 #include "pgpMem.h"
46af5a
0b99fe #include "pgpSHA.h"
b4dd74 #include "pgpRnd.h"
35af5a
cca146 #include "pgpDebug.h"
04adc0 #include "pgpRandomPoolPriv.h"
cac77e #include "pgpRndSeed.h"
c351b9 #include "pgpRMWOLock.h"
a3af5a
20c821 /* We import the following things from the SHA code */
426e5a #define HashTransform pgpSHATransform
bab697 #define HASH_INWORDS 16
2be3c8 #define HASH_OUTWORDS 5
95af5a
b338e5 /*
f20cdd ·* The pool must be a multiple of the hash input size and the hash
fcc2d5 ·* output size. ·For SHA, these are 16 and 5 words, respectively,
d66bac ·* so the pool must be a multiple of 80 words. ·If the hash were
cc46fe ·* MD5, it would have to be a multiple of 16 and of 4, or a multiple
565a11 ·* of 16 all together. ·(80 words is 2560 bits.)
c8495d ·*/
cf8ee2 #define RANDPOOLWORDS 160¤  /* 5,120 bits */
9108e4 #define RANDPOOLBITS (32*RANDPOOLWORDS)
9f835f #if RANDPOOLWORDS % HASH_OUTWORDS
5bc120 #error RANDPOOLWORDS must be a multiple of HASH_OUTWORDS
cc7454 #endif
3e5fa5 #if RANDPOOLWORDS % HASH_INWORDS
4124e5 #error RANDPOOLWORDS must be a multiple of HASH_INWORDS
ad7454 #endif
b4af5a
fdaf5a
f2d867 /* minimum number of bytes to consider the random pool seeded */
9ebc96 #define kMinimumSeedBytes¤  ¤   24
825918 #define kMinimumSeedBits¤   ¤   ( 8 * kMinimumSeedBytes )
e8af5a
3f194a typedef struct RandomPool
afbb36 {
00d8af ¤   /*
e9cd64 ¤   ·* Accumulators to estimate entropy in the pool.
70a4e3 ¤   ·*/
6ac928 ¤   PGPUInt32¤  randBits; /* Bits of entropy in pool */
96f789 ¤   PGPUInt32¤  randFrac; /* Fraction of a bit of entropy in pool */
4c74a3 ¤   PGPUInt32¤  randInBits; /* Bits of entropy added to pool */
c367c5 ¤
3459c2 ¤   /* Must be word-aligned, so make it words. ·Cast to bytes as needed. */
ac61fe ¤   PGPUInt32¤  randPool[RANDPOOLWORDS];¤   /* Random pool */
aba7ac ¤   PGPUInt32¤  randPoolAddPos;¤/* Position to encrypt into (words) */
63af5a
71bbe5 ¤   PGPUInt32¤  randKey[HASH_INWORDS];¤ /* Random input buffer */
079576 ¤   PGPUInt32¤  randKeyAddPos;¤ /* Position to add to (bytes) */
27af5a
f59982 ¤   PGPUInt32¤  randOut[HASH_OUTWORDS];¤/* Random output buffer */
16c27a ¤   PGPUInt32¤  randOutGetPos; /* Position to get from (b) */
--0da5 00099bab20a401001cc Page 2 of pgpRandomPool.c
e0af5a
b07ab5 ¤   /* Keeps track of when we need to do another hashing step */
b66a33 ¤   PGPUInt32¤  randHashCounter;
ac67c5 ¤
0be7b2 ¤   PGPRMWOLock¤criticalLock;
4c1b52 ¤   ¤
289af4 } RandomPool;
04af5a
ab22f6 /* This is the global random pool */
c8dd94 static RandomPool¤  sPool¤  = {0,};
4de1c7 #define GetPool()¤  ¤   ( &sPool )
d0af5a
a1af5a
00c744 ¤   PGPError
605a19 pgpInitGlobalRandomPool()
01bb36 {
e684ba ¤   RandomPool *¤   pool¤   = NULL;
5667c5 ¤
a22ed5 ¤   pool¤   = GetPool();
8567c5 ¤
5c2eef ¤   pool->randBits¤ ¤   ¤   = 0;
d0824b ¤   pool->randFrac¤ ¤   ¤   = 0;
1d5f67 ¤   pool->randInBits¤   ¤   = 0;
f0563b ¤   pool->randPoolAddPos¤   = 0;
30ea12 ¤   pool->randKeyAddPos¤¤   = 0;
bf617e ¤   pool->randOutGetPos¤¤   = sizeof( pool->randOut);
76b024 ¤   pool->randHashCounter¤  = 0;
a867c5 ¤
9d5686 ¤   InitializePGPRMWOLock( &pool->criticalLock );
ac67c5 ¤
572d68 ¤   return( kPGPError_NoErr );
a0efe6 }
cfaf5a
2e38e5 /*
8ca7b5 ·* To mix input into the pool, we insert it into a key buffer and then
6615ce ·* use the key buffer to CBC-encrypt the pool. ·Actually, to make sure
168e55 ·* that the input (which includes such sensitive information as passphrase
3dbc88 ·* keystrokes) is not left in memory, we XOR it with the old contents of
0798bb ·* the key buffer along with some of the the data about to be encrypted.
ff43e4 ·* Since none of the disguising data depends on the byte, this does
66ddbd ·* not destroy any entropy inherent in the input byte.
1c775e ·*
66c40f ·* To reduce burstiness in the timing, rather than wait until the key
506f3b ·* buffer is full to encrypt the entire pool, we update part of the key
cc01e3 ·* and then encrypt part of the pool. ·The randHashCounter keeps track
48ebd7 ·* of what's going on to ensure that a byte of key is not overwritten
d27554 ·* until it has participated in the encryption of every block of the pool.
2e775e ·*
e0ceca ·* The pool contains RANDPOOLWORDS/HASH_OUTWORDS blocks. ·We must do
be41a0 ·* that many hash-encrpytion steps before 4*HASH_INWORDS bytes of the
a7c16a ·* key have been overwritten. ·So randHashCounter is incremented by
2a31ca ·* RANDPOOLWORDS/HASH_OUTWORDS each time a byte is added, and when this
281698 ·* exceeds 4*HASH_INWORDS, it is decreased by that amount and a hashing
6c8729 ·* step is performed. ·It should be easy to see that that guarantees
dd4859 ·* correct behaviour.
08775e ·*
5c5a32 ·* The bits deposited need not have any particular distribution; the
ec91e5 ·* stirring operation transforms them to uniformly-distributed bits.
7f495d ·*/
5833c8 ¤   static void
5ac58d sRandPoolAddByte(
16ebbf ¤   RandomPool *¤   pool,
b40dea ¤   PGPByte¤¤   ¤   b)
77bb36 {
ddd312 ¤   int¤¤   ¤   ¤   i;
c9c153 ¤   PGPUInt32¤  ¤   pos;
02af5a
1fd0ee ¤   /* Mix new byte into pool */
0bb979 ¤   ((PGPByte *)pool->randKey)[pool->randKeyAddPos] ^= b;
66d281 ¤   if (++pool->randKeyAddPos == sizeof(pool->randKey))
b3b9af ¤   ¤   pool->randKeyAddPos = 0;
99af5a
--ebee 000df5760bf401001cc Page 3 of pgpRandomPool.c
69d8af ¤   /*
a1ff19 ¤   ·* If we've reached the end of a word, mask the next word with
36b8ca ¤   ·* a soon-to-be-overwritten byte of the pool. ·With a 64-byte input
2b10a0 ¤   ·* hash, this will use a different word for masking each of the
ec4c38 ¤   ·* 16 words as long as there are at least 16 output blocks
b36532 ¤   ·* (64 words at 4 words per output block, or 512 bits total) in the
1e54ca ¤   ·* pool. ·Just to be sure, let's enforce it...
13a4e3 ¤   ·*/
c2b683 #if HASH_INWORDS > RANDPOOLWORDS / HASH_OUTWORDS
912e80 #error Please make RANDPOOLWORDS bigger than HASH_INWORDS * HASH_OUTWORDS.
1f7454 #endif
b08193 ¤   if (pool->randKeyAddPos % sizeof(PGPUInt32) == 0)
fe9c7d ¤   ¤   *(PGPUInt32 *)((PGPByte *)pool->randKey + pool->randKeyAddPos) ^=
0344b7 ¤   ¤   ····························pool->randPool[pool->randPoolAddPos];
91af5a
c3f191 ¤   /* Do a hashing step if required */
5ed976 ¤   pool->randHashCounter += RANDPOOLWORDS/HASH_OUTWORDS;
c342c7 ¤   while (pool->randHashCounter >= 4*HASH_INWORDS) {
796dbb ¤   ¤   pool->randHashCounter -= 4*HASH_INWORDS;
e8af5a
dfce9a ¤   ¤   /* CBC-encrypt the current block */
9d3d4c ¤   ¤   pos = pool->randPoolAddPos;
656b60 ¤   ¤   HashTransform(pool->randPool + pos, pool->randKey);
ebaf5a
877647 ¤   ¤   /* Get the offset of the next block and XOR this one in */
410442 ¤   ¤   pool->randPoolAddPos = pos + HASH_OUTWORDS;
0311e3 ¤   ¤   if (pool->randPoolAddPos == RANDPOOLWORDS)
775fbd ¤   ¤   ¤   pool->randPoolAddPos = 0;
65078f ¤   ¤   for (i = 0; i < HASH_OUTWORDS; i++)
7106cb ¤   ¤   ¤   pool->randPool[pool->randPoolAddPos + i] ^= pool->randPool[pos+i];
f69371 ¤   }
55efe6 }
ccaf5a
d638e5 /*
b95fe0 ·* Make a deposit of information (entropy) into the pool.
00495d ·*/
7c33c8 ¤   static void
fe4ab4 sRandPoolAddBytes(
8f9db8 ¤   void *¤ ¤   ¤   priv,
828581 ¤   PGPByte const *¤p,
be956c ¤   unsigned¤   ¤   len)
90bb36 {
8f8fb3 ¤   RandomPool *pool¤   = GetPool();
d267c5 ¤
5e8fd9 ¤   pgpAssert( pool );
9baf5a
0909e7 ¤   (void)priv;
7eaf5a
9dcae5 ¤   while (len--) {
4f1b13 ¤   ¤   sRandPoolAddByte( pool, *p++ );
659371 ¤   }
b3af5a
25679a ¤   /* Pool has changed, randOut is out of date */
d84c8f ¤   pool->randOutGetPos = sizeof(pool->randOut);
deefe6 }
10af5a
2c2978 static void
41ef15 sRandGetOutput( RandomPool *¤   pool )
c9bb36 {
7e4ba4 ¤   int i;
9baf5a
1bd8af ¤   /*
74f071 ¤   ·* Hash the pending input and the entire pool, with the old
057d88 ¤   ·* randOut as IV.
cca4e3 ¤   ·*/
ea8bad ¤   HashTransform( pool->randOut, pool->randKey );
b5f6df ¤   for (i = 0; i < RANDPOOLWORDS; i += HASH_INWORDS)
e54f57 ¤   ¤   HashTransform( pool->randOut, pool->randPool + i );
b8af5a
c6952d ¤   /* Okay, we can now fetch starting at the beginning of randOut */
5742e8 ¤   pool->randOutGetPos = 0;
dfefe6 }
--f28d 00068ac77b6401001cc Page 4 of pgpRandomPool.c
e0af5a
d338e5 /*
be9f83 ·* Withdraw some bits from the pool. ·Regardless of the distribution of the
0cb6d7 ·* input bits, the bits returned are uniformly distributed, although they
6e9f47 ·* cannot, of course, contain more Shannon entropy than the input bits.
10495d ·*/
e833c8 ¤   static void
5efd77 sRandPoolGetBytesEntropy(
f99db8 ¤   void *¤ ¤   ¤   priv,
5320fc ¤   PGPByte *¤  ¤   buf,
85ebd4 ¤   unsigned¤   ¤   len,
b2aefa ¤   unsigned¤   ¤   bits)
d9bb36 {
188fb3 ¤   RandomPool *pool¤   = GetPool();
e70ed5 ¤   unsigned t;
b567c5 ¤
868fd9 ¤   pgpAssert( pool );
79af5a
6d09e7 ¤   (void)priv;
1faf5a
f2a65a ¤   if (pool->randBits >= bits)
eb4fb0 ¤   ¤   pool->randBits -= bits;
840e24 ¤   else
1eddc3 ¤   ¤   pool->randFrac = pool->randBits = 0;
34af5a
07c5f3 ¤   while (len > (t = sizeof(pool->randOut) - pool->randOutGetPos)) {
a9a9af ¤   ¤   pgpCopyMemory( (PGPByte *)pool->randOut + pool->randOutGetPos, buf, t);
ed2cc8 ¤   ¤   buf += t;
a767e1 ¤   ¤   len -= t;
5aab58 ¤   ¤   sRandGetOutput( pool );
409371 ¤   }
97af5a
cb5678 ¤   if (len) {
88b9d8 ¤   ¤   pgpCopyMemory( (PGPByte *)pool->randOut+pool->randOutGetPos, buf, len);
f92813 ¤   ¤   pool->randOutGetPos += len;
989371 ¤   }
c7efe6 }
6eaf5a
ddaf5a
8338e5 /*
e376c0 ·* Destroys already-used random numbers. ·Ensures no sensitive data
3bb250 ·* remains in memory that can be recovered later. ·This repeatedly
c8d7e2 ·* mixes the output of the generator back into itself until all internal
92e871 ·* state has been overwritten.
2e495d ·*/
0a33c8 ¤   static void
2dc8ee sRandPoolStir(void *¤   priv )
89bb36 {
a88fb3 ¤   RandomPool *pool¤   = GetPool();
445156 ¤   unsigned¤   i;
1f67c5 ¤
758fd9 ¤   pgpAssert( pool );
efaf5a
8709e7 ¤   (void)priv;
1faf5a
e98497 ¤   for (i = 0; i < 5*sizeof(pool->randKey)/sizeof(pool->randOut); i++) {
bac7a0 ¤   ¤   sRandPoolAddBytes(priv, (PGPByte *)pool->randOut,
44ebb8 ¤   ¤   ¤   ¤   ¤   ¤   ··sizeof(pool->randOut));
00ab58 ¤   ¤   sRandGetOutput( pool );
6f9371 ¤   }
4cefe6 }
19af5a
0b33c8 ¤   static void
aea4ed sRandPoolAddBytesLock(
1d9db8 ¤   void *¤ ¤   ¤   priv,
708581 ¤   PGPByte const *¤p,
a7956c ¤   unsigned¤   ¤   len)
8fbb36 {
618fb3 ¤   RandomPool *pool¤   = GetPool();
1867c5 ¤
8baa08 ¤   PGPRMWOLockStartWriting( &pool->criticalLock );
687f69 ¤   ¤   sRandPoolAddBytes( priv, p, len );
--9070 000fe30848d401001cc Page 5 of pgpRandomPool.c
b8bfca ¤   PGPRMWOLockStopWriting( &pool->criticalLock );
bbefe6 }
e1af5a
4833c8 ¤   static void
0cbcbe sRandPoolGetBytesEntropyLock(
599db8 ¤   void *¤ ¤   ¤   priv,
2f20fc ¤   PGPByte *¤  ¤   buf,
11ebd4 ¤   unsigned¤   ¤   len,
b8aefa ¤   unsigned¤   ¤   bits)
4fbb36 {
bc8fb3 ¤   RandomPool *pool¤   = GetPool();
0567c5 ¤
8baa08 ¤   PGPRMWOLockStartWriting( &pool->criticalLock );
4535cc ¤   ¤   sRandPoolGetBytesEntropy( priv, buf, len, bits );
27bfca ¤   PGPRMWOLockStopWriting( &pool->criticalLock );
62efe6 }
1baf5a
ff33c8 ¤   static void
f0326b sRandPoolStirLock(void *priv)
fabb36 {
af8fb3 ¤   RandomPool *pool¤   = GetPool();
dc67c5 ¤
3baa08 ¤   PGPRMWOLockStartWriting( &pool->criticalLock );
5caba9 ¤   ¤   sRandPoolStir( priv );
21bfca ¤   PGPRMWOLockStopWriting( &pool->criticalLock );
50efe6 }
2faf5a
a734a2 static const PGPRandomVTBL sGlobalRandomPoolVTBL =
32bb36 {
0e8fd3 ¤   "Global true random-number pool",
61216c ¤   sRandPoolAddBytesLock,
d4ecd6 ¤   sRandPoolGetBytesEntropyLock,
2c13d8 ¤   sRandPoolStir
6082f7 };
b5af5a
59af5a
4810cb ¤   PGPRandomVTBL const *
12abb7 pgpGetGlobalRandomPoolVTBL( void )
68bb36 {
9062d4 ¤   return( &sGlobalRandomPoolVTBL );
0aefe6 }
b1af5a
50af5a
5938e5 /*
a3f79c ·* Used for cases where we want to create a temporary PGPRandomContext
fb3c0d ·* which wraps the random pool.
a1495d ·*/
766d52 ¤   void
daa75b pgpInitGlobalRandomPoolContext( PGPRandomContext *rc )
f1bb36 {
f5fa6f ¤   rc->context¤= NULL;
ce05ce ¤   rc->vtbl¤   = pgpGetGlobalRandomPoolVTBL();
509d86 ¤   rc->priv¤   = NULL;
a68e9c ¤   rc->destroy¤= NULL;
a5efe6 }
abaf5a
17af5a
dbaf5a
f4af5a
5138e5 /*
bb453e ·* True random bit accumulation. ·These are extra functions exported
324bce ·* for entropy estimation.
89775e ·*
05fbe5 ·* Entropy is expressed in terms of a delta, essentially the difference
3127d9 ·* between the observed value and the expected value, whose logarithm
261baf ·* is a measure of entropy. ·(The logarithm to the base 2 is entropy
c05c56 ·* expressed in bits.)
72775e ·*
216bfb ·* The internal amount-of-entropy accumulator is maintained in two
995773 ·* halves: a counter of bits, and a fraction of a bit, expressed
c30652 ·* in the form of a normalized delta. ·If 0 <= f < 1 is a fraction
fe0763 ·* of a bit, then 1 <= 2^f < 2, so it's remembered as
--ad81 00027204b34401001cc Page 6 of pgpRandomPool.c
f39854 ·* 0 <= x = 2^f - 1 < 1, a fixed-point number.
d0775e ·*
e132fa ·* Given a new fractional-bit delta, 1+y in similar form (obtained
b21a6e ·* by normalizing the delta into the desired form), the output
fd8708 ·* fractional bit delta 1+z = (1+x) * (1+y). ·If this exceeds 2,
33fecc ·* divide it by 2 and add a full bit to the bit counter.
60775e ·*
228cb9 ·* The implementation, of course, actually computes z = x + y + x*y,
115e2f ·* where 0 <= z < 3. ·This can be done by adding each of the three terms
b38f97 ·* (each of which is less than 1) and noticing the overflow. ·If the
deb907 ·* addition does not overflow, z < 1 and nothing needs to be done.
63775e ·*
917d03 ·* If one addition overflows, 1 <= z < 2, but after overflow we get
14ec49 ·* z-1. ·We want (1+z)/2-1 = (z-1)/2, so just divide the result of
c8e766 ·* the wrapped addition by 2.
8f775e ·*
0978ad ·* If both additions overflow, the addition wraps to z-2, but we
9d9294 ·* still want (z-1)/2 = (z-2)/2 + 1/2, so divide the wrapped result
d06509 ·* by 2 and add 1/2.
9f775e ·*
75d7e2 ·* Due to the way that the fixed-point numbers are stored, the x*y part is
0f8cc2 ·* the high half of the 32-bit unsigned product of x and y. ·This can be
14e816 ·* safely underestimated if desired, if a 64-bit product is difficult to
279025 ·* compute.
07775e ·*
6386f0 ·* The simplest snd safest definition is
8c7144 ·* #define UMULH_32(r,a,b) (r) = 0
ca495d ·*/
ccbb42 #ifndef UMULH_32
566fb7 #if defined(__GNUC__) && defined(__i386__)
d738e1 /* Inline asm goodies */
837f54 #define UMULH_32(r,a,b) __asm__("mull %2" : "=d"(r) : "%a"(a), "mr"(b) : "ax")
323644 #elif HAVE64
18878a #define UMULH_32(r,a,b) ((r) = (PGPUInt32)((word64)(a) * (b) >> 32))
31db21 #else
7fd157 /* Underestimate the product */
7a7271 #define UMULH_32(r,a,b) ((r) = ((a) >> 16) * ((b) >> 16))
d07454 #endif
f919ae #endif /* !UMULH_32 */
99af5a
e5695d #define DERATING 2¤ /* # of bits to underestimate */
b2af5a
561964 ¤   static PGPUInt32
456d3e pgpGlobalRandomPoolEntropyWasAdded(
d6ce58 ¤   PGPUInt32¤  ¤   delta )
05bb36 {
c895ee ¤   PGPUInt32¤  ¤   frac,
c485eb ¤   ¤   ¤   ¤   ¤   t;
ab0c1e ¤   unsigned¤   ¤   n;
2ac0be ¤   RandomPool¤ *¤  pool¤   = GetPool();
52af5a
750182 ¤   if (delta < 1 << DERATING)
93bbde ¤   ¤   return 0;
0267c5 ¤
65bb5f ¤   n = 31-DERATING;
4e84e1 ¤   if (!(delta & 0xffff0000))
fa40a8 ¤   ¤   delta <<= 16, n -= 16;
7a1a31 ¤   if (!(delta & 0xff000000))
8a7991 ¤   ¤   delta <<= 8, n -= 8;
6471ca ¤   if (!(delta & 0xf0000000))
723ecd ¤   ¤   delta <<= 4, n -= 4;
e67a0e ¤   if (!(delta & 0xc0000000))
b21d63 ¤   ¤   delta <<= 2, n -= 2;
9f8457 ¤   if (!(delta & 0x80000000))
d50cb4 ¤   ¤   delta <<= 1, n -= 1;
918c56 ¤   pgpAssert(n < 32);
fdaf5a
b1bc28 ¤   /* Lose high-order bit of delta */
af2ff0 ¤   pgpAssert(delta & 0x80000000);
98a620 ¤   delta <<= 1;
88af5a
270972 ¤   frac = pool->randFrac;
--5fac 000e3cf570a401001cc Page 7 of pgpRandomPool.c
95d8cd ¤   UMULH_32(t,delta,frac);
bf2422 ¤   if ((frac += t) < t) {
865eb1 ¤   ¤   if ((frac += delta) < delta)
08006a ¤   ¤   ¤   frac = (frac >> 1) + 0x80000000ul;
f60e1d ¤   ¤   else
9c714b ¤   ¤   ¤   frac >>= 1;
9004a1 ¤   ¤   n++;
4e69b0 ¤   } else if ((frac += delta) < delta) {
db0bbf ¤   ¤   frac >>= 1;
aa04a1 ¤   ¤   n++;
a89371 ¤   }
16af5a
0802ba ¤   /* n is now the count of whole bits */
55c336 ¤   if ((pool->randBits += n) >= RANDPOOLBITS) {
b8b1f7 ¤   ¤   /* Overflow - saturate at RANDPOOLBITS */
6730f6 ¤   ¤   pool->randBits = RANDPOOLBITS;
9020bd ¤   ¤   pool->randFrac = 0;
cc9371 ¤   }
02cfe8 ¤   /* Also count the inflow without regard to outflow */
790475 ¤   if ((pool->randInBits += n) >= RANDPOOLBITS) {
c80ec8 ¤   ¤   pool->randInBits = RANDPOOLBITS;
999371 ¤   }
9167c5 ¤
62ad93 ¤   return n;
e0efe6 }
6daf5a
3b108d ¤   PGPUInt32
1681b7 PGPGlobalRandomPoolGetEntropy()
3fbb36 {
9a9c6b ¤   PGPUInt32¤  randBits;
b2ef1c ¤   RandomPool¤ *pool = GetPool();
92af5a
e994b7 ¤   PGPRMWOLockStartReading( &pool->criticalLock );
910f6c ¤   ¤   randBits = pool->randBits;
888175 ¤   PGPRMWOLockStopReading( &pool->criticalLock );
1a67c5 ¤
70da16 ¤   return( randBits );
c4efe6 }
28af5a
c6108d ¤   PGPUInt32
f825c9 PGPGlobalRandomPoolGetSize()
84bb36 {
721f8a ¤   return RANDPOOLBITS;
67efe6 }
4faf5a
77af5a
5eaf5a
52108d ¤   PGPUInt32
892c3c pgpGlobalRandomPoolGetInflow()
3cbb36 {
15dd76 ¤   PGPUInt32¤  randInBits;
44ef1c ¤   RandomPool¤ *pool = GetPool();
25af5a
d694b7 ¤   PGPRMWOLockStartReading( &pool->criticalLock );
9a693a ¤   ¤   randInBits = pool->randInBits;
5e8175 ¤   PGPRMWOLockStopReading( &pool->criticalLock );
a367c5 ¤
d59b2f ¤   return( randInBits );
a3efe6 }
f7af5a
21af5a
9338e5 /*
d75cd1 ·* Returns true if we have enough entropy to proceed with signature or
959e8f ·* encryption functions. ·We go ahead if we have either seeded the RNG
2441ea ·* successfully from the disk, or if we have acquired a certain
e26516 ·* minimum of bits from the environment during our run.
82495d ·*/
8316ea ¤   PGPBoolean
8a3350 PGPGlobalRandomPoolHasMinimumEntropy( void )
81bb36 {
717e23 ¤   return ·pgpGlobalRandomPoolIsSeeded() ||
e30445 ¤   ¤   ····pgpGlobalRandomPoolGetInflow() >= kMinimumSeedBits ;
--c295 0002aeab122401001cc Page 8 of pgpRandomPool.c
7aefe6 }
46af5a
2e38e5 /*
2bf0dd ·* Returns the minimum amount of entropy we would like to see in the random
cc33d7 ·* pool before signing or encryption. ·Before doing one of those functions,
b37ce7 ·* we first use PGPGlobalRandomPoolHasMinimumEntropy to determine whether
ce2861 ·* to proceed. ·If that returns FALSE, we should acquire entropy until the
473695 ·* amount in the random pool is at least equal to what this function returns.
474ee4 ·* Note that PGPGlobalRandomPoolHasMinimumEntropy uses the inflow value,
f48fd8 ·* while if that returns false we will use the actual amount of randomness
a92f07 ·* in the pool, which is always <= the inflow value. ·Using the inflow value
1cccd6 ·* is safe enough as it indicates that we are seeded, but once we decide we
8f1cb0 ·* need to go to the effort of acquiring more entropy from the environment,
3dddd6 ·* we might as well use the GetEntropy() value, which is more conservative.
f5495d ·*/
28108d ¤   PGPUInt32
fb8205 PGPGlobalRandomPoolGetMinimumEntropy( void )
58bb36 {
199032 ¤   return kMinimumSeedBits;
a3efe6 }
34af5a
fcaf5a
c29401 /* Number of elements in the given array */
3e6e51 #define elemsof(x) ( (PGPUInt32)( sizeof(x) / sizeof(*x) ) )
dcaf5a
1b38e5 /*
e88906 ·* Estimate the amount of entropy in an input value x by seeing how
af2626 ·* different it is from what has come before.
d2775e ·*
b8cbc0 ·* This is based on computing the delta from the previous value, and the
5a5753 ·* second-order delta from the previous delta, and so on, for h orders.
437856 ·* The minimum of any of those deltas is returned as the entropy estimate.
b499c9 ·* (Which must, of course, have a logarithm taken to produce a "number
5b0413 ·* of bits" output.)
60775e ·*
62f30c ·* This requires a pointer to a h-word history table of previous deltas.
07b528 ·* A value of h = 3 is generally good, but some things (like keystroke
91b8d6 ·* timings) feed deltas and not input values into this, so that removes
f81aa5 ·* the first level.
8a495d ·*/
2858ef static PGPUInt32
a3791c randEstimate(PGPUInt32 x, PGPUInt32 *history, unsigned h)
ebbb36 {
5a7a36 ¤   PGPUInt32¤  ¤   t,
6a295d ¤   ¤   ¤   ¤   ¤   min = x;
acaf5a
6915bb ¤   while (h--) {
45632a ¤   ¤   t = history[h];¤¤   ¤   /* Last delta */
76b368 ¤   ¤   t = (x > t) ? x - t : t - x;¤   /* |x - history[h]| */
38e6da ¤   ¤   history[h] = x;
e2d1dd ¤   ¤   x = t;
f7b53a ¤   ¤   if (min > x)
5cacd1 ¤   ¤   ¤   min = x;
e49371 ¤   }
75270a ¤   return min;
9aefe6 }
e7af5a
8daf5a
df1964 ¤   static PGPUInt32
0eba3f sCollectEntropy()
d0bb36 {
185e1b ¤   PGPUInt32¤  ¤   ¤   delta;
8950d2 ¤   PGPRandomContext¤   rc;
6e67c5 ¤
0a7f51 ¤   /* call machine specific routine to get some entropy */
459523 ¤   pgpInitGlobalRandomPoolContext( &rc );
5fb533 ¤   delta¤  = pgpRandomCollectEntropy( &rc );
c467c5 ¤
902882 ¤   return( delta );
ffefe6 }
85af5a
2aaf5a
--3624 000bcf78b61401001cc Page 9 of pgpRandomPool.c
bc38e5 /*
a25c9a ·* Gather and estimate entropy from keyboard timings. ·Double letters
758fe5 ·* are allowed, but triples and more are considered suspiscious and
cb76d6 ·* entropy is not counted. ·(The actual criterion is that the current
0df9b2 ·* letter has appeared more than once in the previous four letters,
09732f ·* which rejects aaaa... and ababa...)
9e775e ·*
c88e63 ·* The "letter" can be generalized to mouse-clicks, button-pushes, menu
63d4dc ·* selections, or anything else that can be categorized into a finite
a12b97 ·* number of events.
12775e ·*
988927 ·* Question: is there a way to achieve this effect without remembering
ba4e4f ·* the recent keystrokes so explicitly? ·It seems like a possible
f5fbe7 ·* security hole.
ee775e ·*
d94a96 ·* We incorporate entropy from the first 3 samples, but don't count them
2975df ·* since only after that many do we get reliable per-sample entropy estimates.
7b97e9 ·* (This is time for the two entries in teh hist array to get initialized,
3cc588 ·* plus the one level of delta history implicitly included in the
49ff89 ·* ranGetEntropy timing. ·It has to be there unless we want to export
74ebae ·* knowledge about the modulus at which the timer it uses wraps.)
5b495d ·*/
0a108d ¤   PGPUInt32
17d645 PGPGlobalRandomPoolAddKeystroke( PGPInt32 event)
f9bb36 {
e196b7 ¤   static PGPInt32¤¤   pastevent[4];¤  /* Last 4 events */
177c08 ¤   static PGPUInt32¤   hist[2];
190e25 ¤   static unsigned¤¤   histcount=elemsof(hist)+1;
ac9ac9 ¤   ¤   ¤   ¤   ¤   ¤   /* # invalid entries in hist array */
ed5e1b ¤   PGPUInt32¤  ¤   ¤   delta;
00035e ¤   unsigned¤   ¤   ¤   n = 0;
c85d14 ¤   int¤¤   ¤   ¤   ¤   i;
997683 ¤   RandomPool¤ ¤   ¤   *pool = GetPool();
2e5ba6 ¤   PGPUInt32¤  ¤   ¤   result;
8a67c5 ¤
a4af5a
1cfae0 ¤   delta = sCollectEntropy();
bfd819 ¤   delta = randEstimate(delta, hist, elemsof(hist));
31869e ····
daaa08 ¤   PGPRMWOLockStartWriting( &pool->criticalLock );
27af5a
b959da ¤   sRandPoolAddBytes(NULL, (PGPByte *)&event, sizeof(event));
c5af5a
aa90dc ¤   /* Check for repetitive keystroke patterns */
407f69 ¤   i = elemsof(pastevent) - 1;
235805 ¤   n = (event == pastevent[i]);
e443ab ¤   do {
92971d ¤   ¤   n += (event == (pastevent[i] = pastevent[i-1]));
18c496 ¤   } while (--i);
2dba84 ¤   pastevent[0] = event;
88af5a
3c4ccd ¤   if (histcount > 0) {
0f4134 ¤   ¤   /* Not yet filled hist array */
38ff04 ¤   ¤   --histcount;
2f4a29 ¤   ¤   result = 0;
b39371 ¤   }
d2f9d2 ¤   else if( n > 1 )
11c7a1 ¤   {
eb4a29 ¤   ¤   result = 0;
2d9371 ¤   }
150e24 ¤   else
7cc7a1 ¤   {
5b9772 ¤   ¤   result = pgpGlobalRandomPoolEntropyWasAdded(delta);
599371 ¤   }
2d67c5 ¤
21bfca ¤   PGPRMWOLockStopWriting( &pool->criticalLock );
0caf5a
104c6e ¤   return( result );
7fefe6 }
1baf5a
1038e5 /*
bc51d6 ·* Generate entropy from mouse motion. ·This simply measures entropy
--ddd6 000dd8f4ffb401001cc Page 10 of pgpRandomPool.c
cf9ba6 ·* in both directions independently. ·Also includes entropy of timing,
748684 ·* although that may be pretty low due to OS synchrony.
dd775e ·*
524733 ·* In essence, we try to predict the mouse position from past positions,
06c34a ·* using three predictors: constant position, constant velocity, and
84e0cd ·* constant acceleration. ·The minimum misprediction distance is used
0a4245 ·* to extimate entropy from.
a79ec0 ·*·
f94a96 ·* We incorporate entropy from the first 3 samples, but don't count them
8946bf ·* since only after that many do the predictors start working.
dd130b ·* (Note that the timing history array is one shorter, because one extra
39ba34 ·* level of delta computation is buried in ranGetEntropy().)
98495d ·*/
25108d ¤   PGPUInt32
19f29a PGPGlobalRandomPoolAddMouse(
aadf95 ¤   PGPUInt32¤  ¤   x,
3efbf1 ¤   PGPUInt32¤  ¤   y)
37bb36 {
9e7404 ¤   static PGPUInt32¤   histx[3], histy[3]; /* X and Y position history */
8afec8 ¤   static PGPUInt32¤   hist[2];¤   ¤   ¤   /* Timing history */
640e3f ¤   static unsigned¤¤   histxcount=elemsof(histx);
cd42f9 ¤   ¤   ¤   ¤   ¤   ¤   /* # invalid entries in histx array */
4efa00 ¤   PGPUInt32¤  ¤   ¤   delta;¤ ¤   ¤   ¤   /* Timing delta */
3f8685 ¤   PGPUInt32¤  ¤   ¤   deltax;¤¤   ¤   ¤   /* X delta */
9d2a25 ¤   PGPUInt32¤  ¤   ¤   deltay;¤¤   ¤   ¤   /* Y delta */
c27683 ¤   RandomPool¤ ¤   ¤   *pool = GetPool();
d45ba6 ¤   PGPUInt32¤  ¤   ¤   result;
ba67c5 ¤
3cfae0 ¤   delta = sCollectEntropy();
04d819 ¤   delta = randEstimate(delta, hist, elemsof(hist));
095439 ¤   deltax = randEstimate(x, histx, elemsof(histx));
2a5224 ¤   deltay = randEstimate(y, histy, elemsof(histy));
69af5a
5faa08 ¤   PGPRMWOLockStartWriting( &pool->criticalLock );
5faf5a
8bb1cd ¤   sRandPoolAddBytes(NULL, (PGPByte *)&x, sizeof(x));
cef2a3 ¤   sRandPoolAddBytes(NULL, (PGPByte *)&y, sizeof(y));
b4af5a
f8f5c5 ¤   /* Wait until we have filled our arrays to start counting entropy */
72d729 ¤   if (histxcount > 0)
1fc7a1 ¤   {
a2c0d9 ¤   ¤   --histxcount;
744a29 ¤   ¤   result = 0;
d69371 ¤   }
b60e24 ¤   else
78c7a1 ¤   {
ee391a ¤   ¤   result = ·pgpGlobalRandomPoolEntropyWasAdded(delta) +
eb8fe5 ·¤  ···¤¤   ¤   ¤   pgpGlobalRandomPoolEntropyWasAdded(deltax) +
f603bf ¤   ····¤   ¤   ¤   pgpGlobalRandomPoolEntropyWasAdded(deltay);
119371 ¤   }
f467c5 ¤
d3bfca ¤   PGPRMWOLockStopWriting( &pool->criticalLock );
5467c5 ¤
bd4c6e ¤   return( result );
38efe6 }
12af5a
24af5a
01af5a
3baf5a
6daf5a
c1af5a
dbaf5a
a5af5a
d238e5 /*
a30a49 ·*¤ DUMMY POOL
10775e ·*
141f2f ·*¤ The dummy pool is a pluggable replacement for the RandPool to be used
d2e3de ·*¤ for generating values which we want to be unique but don't have to be
bf195c ·*¤ cryptographically strong: such as the p and q values used in discrete
dd9bfa ·*¤ log keys. ·We prefer not to use the regular RandPool for such values
0d55a8 ·*¤ so that we don't leak information about the secret values which are
ddd633 ·*¤ calculated in close proximity.
--e57a 001fecd49c9401001cc Page 11 of pgpRandomPool.c
4f775e ·*
a6118d ·*¤ The dummy pool should be used as the "base" paramater for
ea7ed4 ·*¤ pgpRandomCreateX9_17. ·It always returns 0 values, and the X9.17 RNG
755e56 ·*¤ will then produce non-cryptographically-strong pseudo-random numbers.
62775e ·*
6ca30a ·*¤ Use pgpRandomAddBytes on the X9.17 RandomContext to seed it.
99495d ·*/
b9af5a
a0ab23 /* Dummy pool always returns zeros */
0033c8 ¤   static void
bc9dd7 sDummyPoolGetBytesEntropy(
d89db8 ¤   void *¤ ¤   ¤   priv,
fd20fc ¤   PGPByte *¤  ¤   buf,
43ebd4 ¤   unsigned¤   ¤   len,
c1aefa ¤   unsigned¤   ¤   bits)
8ebb36 {
f509e7 ¤   (void)priv;
96c13e ¤   (void)bits;
5c67c5 ¤
59dafe ¤   pgpClearMemory( buf, len );
80efe6 }
c8af5a
5233c8 ¤   static void
5a5970 sDummyPoolAddBytes(
4f9db8 ¤   void *¤ ¤   ¤   priv,
b68581 ¤   PGPByte const *¤p,
54956c ¤   unsigned¤   ¤   len)
d0bb36 {
3109e7 ¤   (void)priv;
0585aa ¤   (void)p;
46a272 ¤   (void)len;
55efe6 }
3a33c8 ¤   static void
7c62bc sDummyPoolStir(void *priv)
4abb36 {
9409e7 ¤   (void)priv;
2aefe6 }
afaf5a
00459d static const PGPRandomVTBL sDummyRandomPoolVTBL =
0abb36 {
bc0bb5 ¤   "Dummy random-number pool",
1044e4 ¤   sDummyPoolAddBytes,
32ee9f ¤   sDummyPoolGetBytesEntropy,
cda0da ¤   sDummyPoolStir
be82f7 };
5aaf5a
9daf5a
f510cb ¤   PGPRandomVTBL const *
ddd6d7 pgpGetGlobalDummyRandomPoolVTBL( void )
01bb36 {
7895df ¤   return( &sDummyRandomPoolVTBL );
81efe6 }
55af5a
cdaf5a
0daf5a
22af5a
fcaf5a
9baf5a
58af5a
98af5a
a3af5a
a8af5a
f6af5a
36af5a
807e4d /*__Editor_settings____
7caf5a
ee4126 ¤   Local Variables:
637b17 ¤   tab-width: 4
f50e6c ¤   End:
0e5f8c ¤   vi: ts=4 sw=4
8b9e9b ¤   vim: si
fed062 _____________________*/
--2f07 001133bb568401001cd Page 1 of pgpRandomPoolPriv.h
a70335 /*____________________________________________________________________________
022e9c ¤   pgpRandomPoolPriv.h
e267c5 ¤
6cc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
bf4b0f ¤   All rights reserved.
8667c5 ¤
01bcdf ¤   Random pool and dummy random pool, used globally.
1faf5a
cafb14 ¤   $Id: pgpRandomPoolPriv.h,v 1.5.30.1 1998/11/12 03:21:31 heller Exp $
c2f7f7 ____________________________________________________________________________*/
3dfd74 #ifndef Included_pgpRandomPoolPriv_h
e51485 #define Included_pgpRandomPoolPriv_h
d3af5a
3fc9be #include "pgpRandomPool.h"
d30f03 #include "pgpRandomContext.h"
cbaf5a
0daf5a
7099c6 PGP_BEGIN_C_DECLARATIONS
29af5a
3eaf5a
05c74e PGPError¤   ¤   pgpInitGlobalRandomPool( void );
fac8d8 void¤   ¤   ¤   pgpInitGlobalRandomPoolContext( PGPRandomContext *rc );
15af5a
bfaccc /* one could create multiple instances of the global random pool */
1ef3d0 PGPRandomVTBL const *¤  pgpGetGlobalRandomPoolVTBL( void );
571c0f PGPRandomVTBL const *¤  pgpGetGlobalDummyRandomPoolVTBL( void );
65af5a
ff38e5 /*
135775 ·* Return the number of bits added to the rand pool over its lifetime.
97ad21 ·* This does not count any seed bits that were read from the file.
2f495d ·*/
c3f43d PGPUInt32 ¤ ¤   ¤   ¤   pgpGlobalRandomPoolGetInflow( void );
a5af5a
4eaf5a
ba1254 PGP_END_C_DECLARATIONS
89af5a
13dc78 #endif /* Included_pgpRandomPoolPriv_h */
--957d 000bc7a3d31401001ce Page 1 of pgpRandomX9_17.c
bc38e5 /*
11a21b ·* pgpRandomX9_17.c -- a general RNG interface
53775e ·*
fe9f38 ·* Written by:¤ Colin Plumb and Derek Atkins <warlord@MIT.EDU>
1e775e ·*
e90ae8 ·* $Id: pgpRandomX9_17.c,v 1.14 1998/06/18 19:17:19 heller Exp $
bf495d ·*/
d3e2ff #include "pgpConfig.h"
16af5a
e70d08 #include "pgpMem.h"
30c26c #include "pgpContext.h"
db1e2d #include "pgpCFBPriv.h"
010e2f #include "pgpSymmetricCipherPriv.h"
bbadc0 #include "pgpRandomPoolPriv.h"
122c96 #include "pgpRandomX9_17.h"
8faf5a
4baf5a
8eaf5a
0602e3 /* X9.17 interface */
e7af5a
faadf8 typedef struct X9_17Context
aebb36 {
26cfbe ¤   PGPCFBContext *cfb;
9e7ff8 ¤   PGPRandomContext const *base_rc;
d24f47 } X9_17Context;
c9af5a
fc2978 static void
b89647 randomX9_17AddBytes(void *priv, PGPByte const *buf, unsigned len)
5cbb36 {
974396 ¤   X9_17Context *ctx = (X9_17Context *)priv;
f6fd31 ¤   PGPCFBRandomWash(ctx->cfb, buf, len);
d4efe6 }
29af5a
cf2978 static void
e788df randomX9_17GetBytesEntropy(
9138d8 ¤   void *priv,
0c0ac0 ¤   PGPByte *buf,
7a1e2c ¤   unsigned len,
94d5c8 ¤   unsigned bits)
3abb36 {
3e4396 ¤   X9_17Context *ctx = (X9_17Context *)priv;
d97de5 ¤   PGPByte salt[ PGP_CFB_MAXBLOCKSIZE ];
6b63e6 ¤   PGPUInt32¤  blocksize;
60fa34 ¤   PGPSize t;
3caf5a
24906a ¤   blocksize¤  = pgpCFBGetBlockSize( ctx->cfb );
ccaf5a
309697 ¤   /* Charge the entropy to the base RNG */
258b4b ¤   pgpRandomGetBytesEntropy(ctx->base_rc, buf, 0, bits);
62af5a
b810e0 ¤   (void)PGPCFBGetRandom(ctx->cfb, len, buf, &t);
d0e254 ¤   len -= t;
b1a97d ¤   buf += t;
ebaf5a
4385aa ¤   while (len) {
b2738f ¤   ¤   pgpRandomGetBytesEntropy(ctx->base_rc, salt, blocksize, 0);
655067 ¤   ¤   PGPCFBRandomCycle(ctx->cfb, salt);
6b01c7 ¤   ¤   (void)PGPCFBGetRandom(ctx->cfb, len, buf, &t);
d967e1 ¤   ¤   len -= t;
402cc8 ¤   ¤   buf += t;
049371 ¤   }
f2efe6 }
b6af5a
e02978 static void
4277b4 randomX9_17Stir(void *priv)
e1bb36 {
a54396 ¤   X9_17Context *ctx = (X9_17Context *)priv;
27d926 ¤   PGPCFBRandomWash(ctx->cfb, (PGPByte const *)"", 0);
35b747 ¤   pgpRandomStir(ctx->base_rc);
deefe6 }
5aaf5a
bccebe PGPRandomVTBL X9_17Desc = {
--5015 0000c4c05cd401001ce Page 2 of pgpRandomX9_17.c
49eedf ¤   "X9.17-based cryptographic PRNG",
1f0f86 ¤   randomX9_17AddBytes, randomX9_17GetBytesEntropy,
ceb213 ¤   randomX9_17Stir
f482f7 };
fbaf5a
19e1a7 /* Forward reference */
e84158 static void randomX9_17Destroy (PGPRandomContext *rc);
e0af5a
680334 ¤   PGPRandomContext *
9de6c9 pgpRandomCreateX9_17(
1f883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
98f235 ¤   PGPCipherAlgorithm¤ ¤   ¤   algorithm,
91e55e ¤   PGPRandomContext const *¤   base)
99bb36 {
cda911 ¤   PGPRandomContext *¤ ¤   ¤   rc;
ba0b0c ¤   PGPCFBContextRef¤   cfb;
0e3a9a ¤   X9_17Context *¤ ¤   ¤   ¤   ctx;
b279cd ¤   PGPByte ¤   ¤   ¤   ¤   ¤   buf[32];
8645ec ¤   PGPMemoryMgrRef¤¤   ¤   ¤   memoryMgr¤  = PGPGetContextMemoryMgr( context );
50af5a
2c4163 ¤   pgpAssert( context );
857bcf ¤   pgpAssert( base );
10af5a
fbc202 ¤   cfb = pgpCFBCreate( memoryMgr, pgpCipherGetVTBL( algorithm ) );
a8ae96 ¤   if (!cfb)
10bbde ¤   ¤   return 0;
20717d ¤   rc = (PGPRandomContext *)pgpContextMemAlloc( context, sizeof(*rc),
d0b207 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
939d24 ¤   if (!rc) {
68128e ¤   ¤   PGPFreeCFBContext( cfb );
6fbbde ¤   ¤   return 0;
c49371 ¤   }
0eaf5a
e41e69 ¤   ctx = (X9_17Context *)pgpContextMemAlloc( context, sizeof(*ctx),
a1179b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPMemoryMgrFlags_Clear );
147880 ¤   if (!ctx) {
7e128e ¤   ¤   PGPFreeCFBContext( cfb );
476eda ¤   ¤   pgpContextMemFree( context, rc );
31bbde ¤   ¤   return 0;
a69371 ¤   }
7baf5a
250cf5 ¤   /* Get a reasonable initial state */
74170a ¤   pgpRandomGetBytesEntropy( base, buf, sizeof(buf), 0 );
b138cf ¤   PGPCFBRandomWash( cfb, buf, sizeof(buf) );
c8b2ac ¤   pgpClearMemory( buf, sizeof(buf) );
63af5a
c3d1a5 ¤   rc->vtbl = &X9_17Desc;
3a635d ¤   rc->priv = ctx;
bf24f2 ¤   rc->context¤= context;
bc0278 ¤   rc->destroy = randomX9_17Destroy;
d54d2a ¤   ctx->cfb = cfb;
cdc290 ¤   ctx->base_rc = base;
a0af5a
edb72b ¤   return rc;
e6efe6 }
73af5a
c1f6b9 /* The default: X9.17, with CAST5, based on the pgpRandomPool. */
3c0334 ¤   PGPRandomContext *
e2d865 pgpRandomCreate(PGPContextRef context)
c6bb36 {
4810ac ¤   PGPRandomContext * randomContext;
e267c5 ¤
d94163 ¤   pgpAssert( context );
f3af5a
048ba5 ¤   randomContext¤  = pgpContextGetGlobalPoolRandomContext( context );
2ac86c ¤   pgpAssert( randomContext );
72af5a
9e1c89 ¤   return pgpRandomCreateX9_17( context, kPGPCipherAlgorithm_CAST5,
75a7c9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·randomContext );
a5efe6 }
c9af5a
0c38e5 /*
--509a 00024727193401001ce Page 3 of pgpRandomX9_17.c
ad0f1d ·* Pseudo-random number generator based on the dummy pool (which
c13e47 ·* always produces zeros). ·This is useful for public data where we
aa9be6 ·* just want uniqueness but don't need cryptographic strength, and where
72c4da ·* we don't want to draw down the randomness in the true random pool.
abe770 ·* An example would be generating the public prime in DSA key.
db271a ·* Use pgpRandomAddBytes to seed it.
09775e ·*
166893 ·* Note that you need to seed this with some really random data
44888e ·* (using pgpRandomAddBytes) or it will generate the same data every time.
3c775e ·*
c5552b ·* DO NOT USE THIS unless you know what you're doing.
0e495d ·*/
c20334 ¤   PGPRandomContext *
4355ab pgpPseudoRandomCreate(PGPContextRef context)
efbb36 {
6910ac ¤   PGPRandomContext * randomContext;
1667c5 ¤
314163 ¤   pgpAssert( context );
f7af5a
ea2ebb ¤   randomContext¤  = pgpContextGetDummyRandomContext( context );
6ac86c ¤   pgpAssert( randomContext );
f1af5a
881c89 ¤   return pgpRandomCreateX9_17( context, kPGPCipherAlgorithm_CAST5,
31a7c9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·randomContext );
50efe6 }
65af5a
c8af5a
e738e5 /*
a596b6 ·* The simple get-byte function... entropy charged is the number of
863a02 ·* bits read out.
e0495d ·*/
b9314a void
7717db pgpRandomGetBytes(
334b45 ¤   PGPRandomContext const *rc,
e7a28e ¤   void *¤ ¤   ¤   ¤   ¤   buf,
411836 ¤   PGPSize¤¤   ¤   ¤   ¤   len)
0cbb36 {
b3ea0c ¤   pgpRandomGetBytesEntropy(rc, (PGPByte *) buf, len, 8*len);
84efe6 }
a8af5a
342978 static void
2b146f randomX9_17Destroy (PGPRandomContext *rc)
0ebb36 {
3467c1 ¤   X9_17Context *¤ ¤   ¤   ¤   ctx = (X9_17Context *)rc->priv;
11ca5d ¤   PGPCFBContextRef¤   cfbp = ctx->cfb;
8b78a7 ¤   PGPContextRef¤  ¤   ¤   ¤   cdkContext;
99af5a
861964 ¤   pgpAssertAddrValid( rc, PGPRandomContext );
0f3153 ¤   cdkContext¤ = rc->context;
1faf5a
ac87f4 ¤   pgpCFBWipe( cfbp );
1f5d17 ¤   PGPFreeCFBContext( cfbp );
70af5a
6cb33c ¤   pgpClearMemory( ctx, sizeof(*ctx) );
d558a9 ¤   pgpContextMemFree( cdkContext, ctx );
25af5a
1443e8 ¤   pgpClearMemory( rc, sizeof(*rc) );
a8940c ¤   pgpContextMemFree( cdkContext, rc );
c5efe6 }
24af5a
fcaf5a
4538e5 /*
b4daea ·* Generate a uniformly distributed random number from 0..range-1.
7ef4ba ·* range is limited to 65536.
83775e ·*
cd3c37 ·* This is very careful to avoid all bias in its selection, without
e597db ·* using too many input bytes. ·For a range of 256 or less, it uses
a1b33b ·* one byte if possible, and an average of less then two, even for
71178e ·* the worst-case range=129.
d8495d ·*/
44108d ¤   PGPUInt32
24d2a9 pgpRandomRange(
--21f4 0015648bf44401001ce Page 4 of pgpRandomX9_17.c
a1619c ¤   PGPRandomContext const *¤   rc,
b48f51 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   range)
b7bb36 {
01f050 ····PGPUInt32¤  ¤   d,
e75332 ¤   ¤   ¤   ¤   ¤   r;
45e13e ¤   PGPByte¤¤   ¤   b[2];
8aaf5a
720c7c ····if (range <= 1)
3b82c5 ········return 0;
2aaf5a
771b3f ¤   if (range <= 256) {
0663d4 ¤   ¤   d = 256/range;
cf4392 ¤   ¤   do {
79b61c ¤   ¤   ¤   pgpRandomGetBytes(rc, b, 1);
fdb671 ¤   ¤   ¤   r = b[0]/d;
987fe9 ¤   ¤   } while (r >= range);
8bf037 ¤   } else {
d580bb ¤   ¤   d = (unsigned)(65536/range);
a64392 ¤   ¤   do {
6193d1 ¤   ¤   ¤   pgpRandomGetBytes(rc, b, 2);
0b8aa5 ¤   ¤   ¤   r = ((unsigned)b[0] << 8 | b[1])/d;
b67fe9 ¤   ¤   } while (r >= range);
74d592 ¤   ¤   b[1] = 0;
679371 ¤   }
8dd198 ¤   b[0] = 0;
b78da5 ¤   return r;
ebefe6 }
61af5a
15af5a
3eaf5a
5c7e4d /*__Editor_settings____
bbaf5a
dd4126 ¤   Local Variables:
c37b17 ¤   tab-width: 4
e50e6c ¤   End:
135f8c ¤   vi: ts=4 sw=4
3c9e9b ¤   vim: si
56d062 _____________________*/
--6378 001ec1fa0b5401001cf Page 1 of pgpRandomX9_17.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
3aaf5a
b7a8bc ¤   $Id: pgpRandomX9_17.h,v 1.4.12.1 1998/11/12 03:21:32 heller Exp $
a6f7f7 ____________________________________________________________________________*/
de372b #ifndef Included_pgpRandomX9_17_h¤  /* [ */
07f992 #define Included_pgpRandomX9_17_h
18af5a
10e603 #include "pgpSymmetricCipher.h"
c50f03 #include "pgpRandomContext.h"
f5af5a
a699c6 PGP_BEGIN_C_DECLARATIONS
3faf5a
c19ac2 void¤   pgpRandomGetBytes(PGPRandomContext const *rc,
283ff7 ¤   ¤   ¤   void *buf, PGPSize len);
fcaf5a
6a38e5 /*
5e2e7f ·* Another: The X9.17 generator, with a specified cipher and
f140fa ·* base random generator used to seed it.
c3495d ·*/
844c22 PGPRandomContext ·*¤pgpRandomCreateX9_17(
90c9a4 ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context, PGPCipherAlgorithm alg,
05acd6 ¤   ¤   ¤   ¤   ¤   ¤   PGPRandomContext const *base_rc);
faaf5a
47ebc4 /* The default: X9.17, with CAST5, based on the pgpRandomPool */
99108f PGPRandomContext ·*¤pgpRandomCreate (PGPContextRef context);
7eaf5a
a538e5 /*
219bff ·* A non-strong pseudo-random number generator. ·Use this only when
b75781 ·* you don't need cryptographic strength, but just want some unique
72973c ·* values, and don't want to draw down the random pool (for example,
9b8b9c ·* generating the public primes in a DSA key). ·Based on the dummy
5a9469 ·* pool, which always produces zeros, and a CAST5 cipher used per
4bd186 ·* X9.17 to generate the pseudo random values.
80775e ·*
736893 ·* Note that you need to seed this with some really random data
b8888e ·* (using pgpRandomAddBytes) or it will generate the same data every time.
67775e ·*
fe552b ·* DO NOT USE THIS unless you know what you're doing.
c9495d ·*/
7af5a3 PGPRandomContext ·*pgpPseudoRandomCreate ( PGPContextRef context );
29af5a
750560 /* Generate a random number in the specified range */
f6ebd3 PGPUInt32¤  ¤   pgpRandomRange(PGPRandomContext const *rc, PGPUInt32 range);
4267c5 ¤
3267c5 ¤
451254 PGP_END_C_DECLARATIONS
49af5a
c1a16c #endif /* ] Included_pgpRandomX9_17_h */
caaf5a
cfaf5a
e57e4d /*__Editor_settings____
d0af5a
064126 ¤   Local Variables:
ef7b17 ¤   tab-width: 4
0b0e6c ¤   End:
c65f8c ¤   vi: ts=4 sw=4
f09e9b ¤   vim: si
7cd062 _____________________*/
ecaf5a
--2449 001b8bc8f4b401001d0 Page 1 of pgpRnd.h
bc38e5 /*
d94333 ·* pgpRnd.h - system-specific gathering of high-resolution timers for RNG.
57775e ·*
fde39d ·* This is a PRIVATE header file, for use only within the PGP Library.
bc2979 ·* You should not be using these functions in an application.
de775e ·*
fa35ed ·* The interface is system-independent, but the implementation should be
03dc20 ·* highly system-dependent, to get at as much state as possible.
8d775e ·*
94bc37 ·* $Id: pgpRnd.h,v 1.8 1997/06/25 17:58:53 lloyd Exp $
0c495d ·*/
85af5a
49d11f #include "pgpUsuals.h"
3fadb8 #include "pgpOpaqueStructs.h"
9caf5a
3099c6 PGP_BEGIN_C_DECLARATIONS
efaf5a
6584b0 /* formerly rndGetEntropy */
3faf5a
08f735 PGPUInt32 pgpRandomCollectEntropy(PGPRandomContext const *rc);
49af5a
b81254 PGP_END_C_DECLARATIONS
--108c 000570d01fc401001d1 Page 1 of pgpRndMSDOS.c
bc38e5 /*
2a3da7 ·* Get high-resolution timing information to seed the random number
428611 ·* generator. ·MS-DOS version.
4c775e ·*
de5e7c ·* $Id: pgpRndMSDOS.c,v 1.6 1997/06/25 17:58:54 lloyd Exp $
56495d ·*/
d0af5a
92e2ff #include "pgpConfig.h"
98af5a
d5c085 #include <time.h>¤  /* For time measurement code */
22af5a
0be3ec #if __BORLANDC__
4e3a9b #ifndef far
7bae4c #define far __far ··/* Borland C++ 3.1's <dos.h> kacks in ANSI mode. ·Ugh! */
397454 #endif
9f7454 #endif
72af5a
b4264a #include <dos.h>¤   /* for enable() and disable() */
d67f62 #include <conio.h>¤ /* for inp() and outp() */
14af5a
72227a #include "pgpRndom.h"
01d11f #include "pgpUsuals.h"
bddd74 #include "pgpRnd.h"
79af5a
d638e5 /*
ad346b ·* This code gets as much information as possible out of 8253/8254 timer 0,
0991ae ·* which ticks every .84 microseconds. ·There are three cases:
099b5d ·* 1) Original 8253. ·15 bits available, as the low bit is unused.
67feb8 ·* 2) 8254, in mode 3. ·The 16th bit is available from the status register.
3c4c0d ·* 3) 8254, in mode 2. ·All 16 bits of the counters are available.
c997d3 ·* ···(This is not documented anywhere, but I've seen it!)
48775e ·*
2e1204 ·* This code repeatedly tries to latch the status (ignored by an 8253) and
6f1b38 ·* sees if it looks like xx1101x0. ·If not, it's definitely not an 8254.
7055bb ·* Repeat this a few times to make sure it is an 8254.
ea495d ·*/
71beb7 static int
e64a27 has8254(void)
57bb36 {
0df11b ¤   int i, s1, s2;
c2af5a
71e7d4 ¤   for (i = 0; i < 5; i++) {
474e00 ¤   ¤   _disable();
06a44e ¤   ¤   outp(0x43, 0xe2);¤  /* Latch status for timer 0 */
bc2e14 ¤   ¤   s1 = inp(0x40);¤¤   /* If 8253, read timer low PGPByte */
7ba44e ¤   ¤   outp(0x43, 0xe2);¤  /* Latch status for timer 0 */
bb51c3 ¤   ¤   s2 = inp(0x40);¤¤   /* If 8253, read timer high PGPByte */
3b7033 ¤   ¤   _enable();
36eb6f ¤   ¤   if ((s1 & 0x3d) != 0x34 || (s2 & 0x3d) != 0x34)
d12f61 ¤   ¤   ¤   return 0;¤  /* Ignoring status latch; 8253 */
319371 ¤   }
178938 ¤   return 1;¤  /* Status reads as expected; 8254 */
a2efe6 }
3aaf5a
a565bf static unsigned
085b8c read8254(void)
47bb36 {
6433fc ¤   unsigned status, count;
ffaf5a
c3d973 ¤   _disable();
d2976d ¤   outp(0x43, 0xc2);¤  /* Latch status and count for timer 0 */
085c1b ¤   status = inp(0x40);
2f56b2 ¤   count = inp(0x40);
7a10a2 ¤   count |= inp(0x40) << 8;
959290 ¤   _enable();
2a52c7 ¤   /* The timer is usually in mode 3, but some motherboards use mode 2. */
07b689 ¤   if (status & 2)
115f88 ¤   ¤   count = count>>1 | (status & 0x80)<<8;
3daf5a
db1368 ¤   return count;
65efe6 }
57af5a
--b2fd 0014d815403401001d1 Page 2 of pgpRndMSDOS.c
f065bf static unsigned
83c782 read8253(void)
9dbb36 {
b5f268 ¤   unsigned count;
75af5a
bcd973 ¤   _disable();
930743 ¤   outp(0x43, 0x00);¤  /* Latch count for timer 0 */
9cdfe5 ¤   count = (inp(0x40) & 0xff);
612727 ¤   count |= (inp(0x40) & 0xff) << 8;
189290 ¤   _enable();
07af5a
5a12d0 ¤   return count >> 1;
6cefe6 }
71af5a
5538e5 /*
912db1 ·* Add as much timing-dependent random noise as possible
a5cc85 ·* to the randPool. ·Typically, this involves reading the most
3e6319 ·* accurate system clocks available.
10775e ·*
769ef3 ·* Returns the number of ticks that have passed since the last call,
b65e27 ·* for entropy estimation purposes.
22495d ·*/
26bccf PGPUInt32
5aea7d ranGetEntropy(PGPRandomContext const *rc)
28bb36 {
997eef ¤   PGPUInt32 delta;
f0aad4 ¤   static unsigned deltamask = 0;
8dfc9d ¤   static unsigned prevt;
c10ed5 ¤   unsigned t;
c29834 ¤   time_t tnow;
be2bcc ¤   clock_t cnow;
fbaf5a
4a8954 ¤   if (deltamask == 0)
86d629 ¤   ¤   deltamask = has8254() ? 0xffff : 0x7fff;
bf792c ¤   t = (deltamask & 0x8000) ? read8254() : read8253();
10d30f ¤   pgpRandomAddBytes(rc, (PGPByte const *)&t, sizeof(t));
f72fd0 ¤   delta = deltamask & (t - prevt);
467c6d ¤   prevt = t;
bcaf5a
99459c ¤   /* Add more-significant time components. */
715675 ¤   cnow = clock();
e54086 ¤   pgpRandomAddBytes(rc, (PGPByte *)&cnow, sizeof(cnow));
d46195 ¤   tnow = time((time_t *)0);
d96d07 ¤   pgpRandomAddBytes(rc, (PGPByte *)&tnow, sizeof(tnow));
a2af5a
36bb7d ¤   return delta;
4defe6 }
--afe0 00023d11666401001d2 Page 1 of pgpRndMac.c
bc38e5 /*
368d9c ·* Get high-resolution timing information to seed the random number generator.
35759d ·* Mac version. ·(The complicated one.)
47775e ·*
23b7b4 ·* $Id: pgpRndMac.c,v 1.10 1997/09/18 01:35:31 lloyd Exp $
a9495d ·*/
90af5a
21e2ff #include "pgpConfig.h"
e1af5a
6dbcf5 #include <stdlib.h>¤/* For qsort() */
73af5a
75b935 #include <Timer.h>
bbaf5a
2ddd74 #include "pgpRnd.h"
9badc0 #include "pgpRandomPoolPriv.h"
d7d11f #include "pgpUsuals.h"
4caf5a
2b0338 #define MINTICK 0
beaf5a
afc59b /* Number of deltas to try (at least 5, preferably odd) */
717352 #define kNumDeltas 15¤
47af5a
b55f42 typedef UnsignedWide timetype;
a4af5a
ceb964 /* Function needed for qsort() */
89beb7 static int
475fad ranCompare(void const *p1, void const *p2)
acbb36 {
21893e ¤   return *(PGPUInt32 const *)p1 > *(PGPUInt32 const *)p2 ? ·1 :
5994dc ¤   ·······*(PGPUInt32 const *)p1 < *(PGPUInt32 const *)p2 ? -1 : 0;
ecefe6 }
acaf5a
5638e5 /*
fe34e9 ·* XXX: Not necessarily accurate!
09775e ·*
5e512d ·* This returns t1 - t2 if it fits in an unsigned long, or else it returns 0
027ee4 ·* if negative or ULONG_MAX if out of range.
39495d ·*/
fc006a static unsigned long
13d2ea tickdiff(UnsignedWide const t1, UnsignedWide const t2)
84bb36 {
37569a ¤   if (t1.hi == t2.hi)
edc7a1 ¤   {
0c61da ¤   ¤   if (t1.lo >= t2.lo)
603b8c ¤   ¤   ¤   return t1.lo - t2.lo;
670e1d ¤   ¤   else
368144 ¤   ¤   ¤   return 0;
589371 ¤   }
116435 ¤   else if (t1.hi == t2.hi + 1)
3ac7a1 ¤   {
b5b37f ¤   ¤   if (t1.lo < t2.lo)
467689 ¤   ¤   ¤   return t1.lo - t2.lo;¤  /* This underflows, */
7be979 ¤   ¤   ¤   ¤   ¤   ¤   /* and that's the intent */
fb0e1d ¤   ¤   else
9c169f ¤   ¤   ¤   return ULONG_MAX;
ea9371 ¤   }
0b2968 ¤   else if (t1.hi < t2.hi)
fbbbde ¤   ¤   return 0;
a60e24 ¤   else
ac9fcb ¤   ¤   return ULONG_MAX;
28efe6 }
4caf5a
3838e5 /*
6b5f07 ·* Find the resolution of the high-resolution clock by sampling successive
55f41d ·* values until a tick boundary, at which point the delta is entered into
79b48a ·* a table. ·An average near the median of the table is taken and returned
b391c0 ·* as the system tick size to eliminate outliers due to descheduling (high)
6ebe82 ·* or tv0 not being the "zero" time in a given tick (low).
c9775e ·*
dbf6af ·* Some trickery is needed to defeat the habit systems have of always
3b4e1c ·* incrementing the microseconds field from gettimeofday() results so that
230167 ·* no two calls return the same value. ·Thus, a "tick boundary" is assumed
--6c26 000714d00a8401001d2 Page 2 of pgpRndMac.c
a8b153 ·* when successive calls return a difference of more than MINTICK ticks.
b565f1 ·* (For gettimeofday(), this is set to 2 us.) ·This catches cases where at
bf7e6d ·* most one other task reads the clock between successive reads by this task.
9eeef2 ·* More tasks in between are rare enough that they'll get cut off by the
c1a08a ·* median filter.
db775e ·*
ca6bd9 ·* When a tick boundary is found, the *first* time read during the previous
581928 ·* tick (tv0) is subtracted from the new time to get microseconds per tick.
3b775e ·*
aea48c ·* Suns have a 1 us timer, and as of SunOS 4.1, they return that timer, but
44fe56 ·* there is ~50 us of system-call overhead to get it, so this overestimates
bac114 ·* the tick size considerably. ·On SunOS 5.x/Solaris, the overhead has been
9ad9d0 ·* cut to about 2.5 us, so the measured time alternates between 2 and 3 us.
7c36bf ·* Some better algorithms will be required for future machines that really
1e23b4 ·* do achieve 1 us granularity.
cd775e ·*
8da06c ·* Current best idea: discard all this hair and use Ueli Maurer's entropy
f9133e ·* estimation scheme. ·Assign each input event (delta) a sequence number.
3d925d ·* 16 bits should be more than adequate. ·Make a table of the last time
b60dad ·* (by sequence number) each possibe input event occurred. ·For practical
8c23be ·* implementation, hash the event to a fixed-size code and consider two
4347c6 ·* events identical if they have the same hash code. ·This will only ever
cc5718 ·* underestimate entropy. ·Then use the number of bits in the difference
e67ddb ·* between the current sequence number and the previous one as the entropy
d2c8e2 ·* estimate.
e2775e ·*
966a86 ·* If it's desirable to use longer contexts, Maurer's original technique
076e2c ·* just groups events into non-overlapping pairs and uses the technique on
cfbc52 ·* the pairs. ·If you want to increment the entropy numbers on each keystroke
c2ca8a ·* for user-interface niceness, you can do the operation each time, but you
b106cf ·* have to halve the sequence number difference before starting, and then you
f91e9e ·* have to halve the number of bits of entropy computed because you're adding
31d7ec ·* them twice.
71775e ·*
e3d74c ·* You can put the even and odd events into separate tables to close Maurer's
beaa7b ·* model exactly, or you can just dump them into the same table, which will
a5ef7e ·* be more conservative.
a9495d ·*/
da58ef static PGPUInt32
50b643 ranTickSize(void)
9cbb36 {
91ae71 ¤   int i = 0, j = 0;
b6ddc9 ¤   PGPUInt32¤  diff, d[kNumDeltas];
617ca3 ¤   timetype¤   tv0, tv1, tv2;
9967c5 ¤
36d8af ¤   /*
54b996 ¤   ·* TODO Get some per-run data to seed the RNG with.
dfc586 ¤   ·* pid, ppid, etc.
9fa4e3 ¤   ·*/
7acbf4 ¤   Microseconds(&tv0);
f47a6c ¤   tv1 = tv0;
7943ab ¤   do {
db04e7 ¤   ¤   Microseconds(&tv2);
b4fceb ¤   ¤   diff = tickdiff(tv2, tv1);
72bd37 ¤   ¤   if (diff > MINTICK) {
d1eaad ¤   ¤   ¤   d[i++] = diff;
105b63 ¤   ¤   ¤   tv0 = tv2;
78d41b ¤   ¤   ¤   j = 0;
23ef6c ¤   ¤   } else if (++j >= 4096)¤/* Always getting <= MINTICK units */
f36635 ¤   ¤   ¤   return MINTICK + !MINTICK;
6b2d77 ¤   ¤   tv1 = tv2;
d4d4e1 ¤   } while (i < kNumDeltas);
0faf5a
9ba8ff ¤   /* Return average of middle 5 values (rounding up) */
7cd9b8 ¤   qsort(d, kNumDeltas, sizeof(d[0]), ranCompare);
ea72b6 ¤   diff = (d[kNumDeltas / 2 - 2] + d[kNumDeltas / 2 - 1] +
10a198 ¤   ¤   ¤   d[kNumDeltas / 2] + d[kNumDeltas / 2 + 1] +
89c888 ¤   ¤   ¤   d[kNumDeltas/2 + 2] + 4) / 5;
f9e926 #if NOISEDEBUG
474ed7 ¤   fprintf(stderr, "Tick size is %u\n", diff);
057454 #endif
71136a ¤   return diff;
--90c5 001665be776401001d2 Page 3 of pgpRndMac.c
7aefe6 }
46af5a
2e38e5 /*
e32db1 ·* Add as much timing-dependent random noise as possible
33cc85 ·* to the randPool. ·Typically, this involves reading the most
c06319 ·* accurate system clocks available.
2d775e ·*
369ef3 ·* Returns the number of ticks that have passed since the last call,
a75e27 ·* for entropy estimation purposes.
9b495d ·*/
e5108d ¤   PGPUInt32
10cefe pgpRandomCollectEntropy(PGPRandomContext const *rc)
a9bb36 {
4a7eef ¤   PGPUInt32 delta;
07c6ea ¤   timetype t;
2f1bdd ¤   static PGPUInt32 ticksize = 0;
58cece ¤   static timetype prevt;
ab67c5 ¤
c280fa ¤   Microseconds(&t);
1cd30f ¤   pgpRandomAddBytes(rc, (PGPByte const *)&t, sizeof(t));
f6af5a
2609b0 ¤   if (!ticksize)
fcc7a1 ¤   {
7af301 ¤   ¤   ticksize = ranTickSize();
ee9ece ¤   ¤   prevt = t;
ce9371 ¤   }
ba7a4f ¤   delta = (PGPUInt32)(tickdiff(t, prevt) / ticksize);
287c6d ¤   prevt = t;
a6af5a
b4bb7d ¤   return delta;
66efe6 }
--8686 0005d7aa98d401001d3 Page 1 of pgpRndSeed.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
7c769c ¤   $Id: pgpRndSeed.c,v 1.36.10.1 1998/11/12 03:21:32 heller Exp $
3af7f7 ____________________________________________________________________________*/
e9e2ff #include "pgpConfig.h"
0faf5a
afa146 #include "pgpDebug.h"
df0d08 #include "pgpMem.h"
4caf5a
57dd74 #include "pgpRnd.h"
ec0859 #include "pgpCFB.h"
502f8d #include "pgpErrors.h"
b03427 #include "pgpFileUtilities.h"
2aaf5a
99c77e #include "pgpRndSeed.h"
cbadc0 #include "pgpRandomPoolPriv.h"
ae0f03 #include "pgpRandomContext.h"
ef2c96 #include "pgpRandomX9_17.h"
884919 #include "pgpUtilities.h"
0a0d6d #include "pgpEnv.h"
45c26c #include "pgpContext.h"
9b91b9 #include "pgpSDKPrefs.h"
aca4b2 #include "pgpFileRef.h"
cdaf5a
5daf5a
d638e5 /*
96c0ef ·* Save the state of the random number generator to "file" using "cfb"
f3643f ·* as the washing mechanism. ·If cfb is NULL, do not wash the output.
8a775e ·*
d21874 ·* Try to write "bytes", or a reasonable minimum size, whichever is the
fbeba9 ·* greater. ·Returns the number of bytes actually written.
f2495d ·*/
2066dd ¤   static PGPError
463696 pgpRandSeedWriteBytes (
15f550 ¤   PGPIORef¤   ¤   ¤   ¤   ¤   io,
51619c ¤   PGPRandomContext const *¤   rc,
47214a ¤   PGPCFBContext *¤¤   ¤   ¤   cfb,
0bd6dc ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   requestCount,
c54cf2 ¤   PGPSize *¤  ¤   ¤   ¤   ¤   writeCount)
57bb36 {
8e2a87 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   total¤  = 0;
fa95fd ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   minsize;
d12e94 ¤   PGPRandomContext¤   ¤   ¤   randPoolContext;
56c3b5 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   buf[ 512 ];
f19981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
d667c5 ¤
0aced0 ¤   pgpAssertAddrValid( io, VoidAlign );
109752 ¤   if ( IsntNull( writeCount ) )
5ed4f0 ¤   ¤   *writeCount¤= 0;
a4af5a
822c9b ¤   pgpInitGlobalRandomPoolContext( &randPoolContext );
9caf5a
a61fca ¤   /* If no randomcontext passed, default to the global pool */
b4c928 ¤   if ( IsNull( rc ) )
e4c7a1 ¤   {
370e84 ¤   ¤   rc = (PGPRandomContext const *)&randPoolContext;
559371 ¤   }
afaf5a
6e8d09 ¤   /* Figure out a "reasonable minimum size" */
819040 ¤   minsize = (PGPGlobalRandomPoolGetSize()+7)/8;
f7b7b9 ¤   if (minsize < PGP_SEED_MIN_BYTES)
7443d7 ¤   ¤   minsize = PGP_SEED_MIN_BYTES;
fb9b21 ¤   else if (minsize > 512)
9f5d1a ¤   ¤   minsize = 512;
12af5a
0bdf5e ¤   /* Always try to write at least this "reasonable minimum size" */
39e6db ¤   if (requestCount < minsize)
5d7333 ¤   ¤   requestCount = minsize;
--805b 000882eb390401001d3 Page 2 of pgpRndSeed.c
e0af5a
78c42a ¤   /* Add entropy to the global random pool based on current time */
625ff0 ¤   (void)pgpRandomCollectEntropy( &randPoolContext );
8daf5a
9ae3fd ¤   /* Stir, to hide patterns */
8db052 ¤   pgpRandomStir(rc);
13af5a
737ed5 ¤   total = 0;
c4b88c ¤   while (total < requestCount)
14c7a1 ¤   {
1f39f9 ¤   ¤   PGPUInt32¤  len;
7e1b52 ¤   ¤
0420d2 ¤   ¤   len¤= requestCount - total;
61115b ¤   ¤   if ( len > sizeof( buf ) )
a1a8e9 ¤   ¤   ¤   len¤= sizeof( buf );
e2af5a
10e85d ¤   ¤   pgpRandomGetBytes(rc, buf, len);
b12123 ¤   ¤   if( IsntNull( cfb ) )
ec552f ¤   ¤   ¤   PGPCFBEncrypt (cfb, buf, len, buf);
51af64 ¤   ¤   err = PGPIOWrite( io, len, buf );
b9be18 ¤   ¤   if ( IsPGPError( err ) )
24cdcb ¤   ¤   ¤   break;
fd87c7 ¤   ¤   ¤
afffa6 ¤   ¤   total += len;
ff9371 ¤   }
65a863 ¤   /* is there any security reason to do this? */
07b2ac ¤   pgpClearMemory( buf, sizeof(buf) );
b167c5 ¤
b89752 ¤   if ( IsntNull( writeCount ) )
e5cf52 ¤   ¤   *writeCount¤= total;
ed67c5 ¤
91deb7 ¤   return( err );
e1efe6 }
5aaf5a
e5af5a
ac38e5 /*
08b4c1 ·* Save the "state" of the random number generator to "file" using
84c71e ·* "cfb" as the washing mechanism. ·If cfb is NULL, do not wash
4cc9e0 ·* the output.
e1495d ·*/
4733c8 ¤   static void
e81a3a pgpRandSeedWrite(
dcf550 ¤   PGPIORef¤   ¤   ¤   ¤   ¤   io,
51619c ¤   PGPRandomContext const *¤   rc,
93aadc ¤   PGPCFBContext *¤cfb)
1abb36 {
d5ced0 ¤   pgpAssertAddrValid( io, VoidAlign );
f5af5a
5e1fa0 ¤   (void)pgpRandSeedWriteBytes( io, rc, cfb, 0, NULL );
ceefe6 }
71af5a
82af5a
e0af5a
c338e5 /*
dab0dc ·* Load the RNG state from the file on disk (randseed.rnd).
4042ec ·* Returns 0 on success, <0 on error.
c068d9 ·* Must read at least 24 bytes (the size of the X9.17 generator's
e6de7a ·* state) to be considered successful. ·Any additional data is just
3a4c1c ·* dumped into the "true" randpool.
46495d ·*/
c566dd ¤   static PGPError
65efe8 pgpRandSeedRead(
0bf550 ¤   PGPIORef¤   ¤   ¤   ¤   ¤   io,
7c1f24 ¤   PGPRandomContext const *¤   rc)
63bb36 {
b5d912 ¤   PGPSize¤¤   ¤   ¤   total, rewriteCount;
47a53b ¤   PGPRandomContext¤   randPoolContext;
25d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
1067c5 ¤
38211b ¤   pgpAssert( IsntNull( io ) );
6d3b97 ¤   if ( IsNull( io ) )
8862b5 ¤   ¤   return kPGPError_BadParams;
--ca68 0005e7568a4401001d3 Page 3 of pgpRndSeed.c
e0af5a
e52c9b ¤   pgpInitGlobalRandomPoolContext( &randPoolContext );
98af5a
e98e28 ¤   /* Dump the file into the random number generator */
e87ed5 ¤   total = 0;
d372c9 ¤   while ( TRUE )
6ac7a1 ¤   {
61fd28 ¤   ¤   PGPByte¤¤   ¤   ¤   buf[ 512 ];
837a47 ¤   ¤   PGPSize¤¤   ¤   ¤   actualCount;
b91b52 ¤   ¤
d4de1e ¤   ¤   err¤= PGPIORead( io, sizeof( buf ), buf, &actualCount );
f7be18 ¤   ¤   if ( IsPGPError( err ) )
4bcdcb ¤   ¤   ¤   break;
0c87c7 ¤   ¤   ¤
e3febb ¤   ¤   total += actualCount;
e5c13e ¤   ¤   /* Add the data both to the X9.17 layer and the underlying pool */
3c6421 ¤   ¤   if ( IsntNull( rc ) )
bc5b34 ¤   ¤   {
07f8a4 ¤   ¤   ¤   pgpRandomAddBytes(rc, buf, actualCount);
e20fe4 ¤   ¤   }
875b64 ¤   ¤   pgpRandomAddBytes( &randPoolContext, buf, actualCount );
309371 ¤   }
16af5a
3b2081 ¤   /* Write it back out again */
566c2d ¤   err¤= PGPIOSetPos( io, 0 );
cff1e7 ¤   if ( IsntPGPError( err ) )
c3c7a1 ¤   {
9f8ef4 ¤   ¤   err = pgpRandSeedWriteBytes( io, rc, NULL, total, &rewriteCount );
9b9371 ¤   }
ea0e24 ¤   else
d9c7a1 ¤   {
ffc36c ¤   ¤   rewriteCount¤   = 0;
289371 ¤   }
0caf5a
b2d8af ¤   /*
480051 ¤   ·* If we can't rewrite it, we may have the same seed as
ed4bb3 ¤   ·* another run of the program, which means it's not entropy
d92993 ¤   ·* at all. ·We try not to depend *totally* on the seed file,
6b65f8 ¤   ·* but paranoia is many levels deep.
71a4e3 ¤   ·*/
ea57c3 ¤   /* If we didn't read enough *or* rewrite enough, complain */
11444b ¤   if (total < PGP_SEED_MIN_BYTES || rewriteCount < PGP_SEED_MIN_BYTES)
08ac70 ¤   ¤   return kPGPError_RandomSeedTooSmall;
eb1b52 ¤   ¤
30151e ¤   return kPGPError_NoErr;
8cefe6 }
3daf5a
a2af5a
c9af5a
2e66dd ¤   static PGPError
78e044 GetRandSeedFileRef(
02a1bc ¤   PGPContextRef¤  ¤   context,
6d41c3 ¤   PFLFileSpecRef¤ *¤  outRef)
82bb36 {
2ed591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
7daf5a
44a8ba ¤   PGPValidateParam( outRef );
b93652 ¤   *outRef¤= NULL;
9af3ca ¤   PGPValidateContext( context );
8067c5 ¤
38d4cf ¤   if ( IsNull( pgpContextGetPrefs( context ) ) )
f3c7a1 ¤   {
e1d263 ¤   ¤   /* loading prefs has the side effect of copying into env */
c02ff3 ¤   ¤   err¤= PGPsdkLoadDefaultPrefs( context );
229371 ¤   }
4ef1e7 ¤   if ( IsntPGPError( err ) )
93c7a1 ¤   {
272473 ¤   ¤   err¤= PGPsdkPrefGetFileSpec( context,
8df993 ¤   ¤   ¤   kPGPsdkPref_RandomSeedFile, (PGPFileSpecRef *)outRef );
d39371 ¤   }
4667c5 ¤
5e5ea8 ¤   return err;
--956a 000be760c88401001d3 Page 4 of pgpRndSeed.c
7aefe6 }
46af5a
8eaf5a
79af5a
0866dd ¤   static PGPError
2178b9 sSeedRandomPool(
e7a1bc ¤   PGPContextRef¤  ¤   context,
af1ac7 ¤   PGPRandomContext *¤ randomContext)
0bbb36 {
29d4f6 ¤   PFLFileSpecRef¤ ¤   randSeedRef¤= NULL;
519372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
5567c5 ¤
3cb149 ¤   (void)pgpInitGlobalRandomPool();
d167c5 ¤
5ecb20 ¤   /* Read in the randseed file */
ed4f40 ¤   err¤= GetRandSeedFileRef( context, &randSeedRef);
0fac23 ¤   if ( IsntPGPError( err ) ·)
53c7a1 ¤   {
e1ec4e ¤   ¤   PGPFileIORef¤   fileIO¤ = NULL;
3f1b52 ¤   ¤
c219d5 ¤   ¤   err¤= PGPOpenFileSpec( randSeedRef, kPFLFileOpenFlags_ReadWrite,
fee0f2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fileIO );
7b8d41 ¤   ¤   PFLFreeFileSpec(randSeedRef);
2b1b52 ¤   ¤
207d98 ¤   ¤   if ( IsntPGPError( err ) )
2b5b34 ¤   ¤   {
f140a8 ¤   ¤   ¤   err¤= pgpRandSeedRead( (PGPIORef)fileIO, randomContext );
2d532a ¤   ¤   ¤   PGPFreeIO( (PGPIORef)fileIO );
04c980 ¤   ¤   ¤   fileIO¤ = NULL;
ab0fe4 ¤   ¤   }
4a9371 ¤   }
92af5a
a1deb7 ¤   return( err );
5aefe6 }
93af5a
f2af5a
2283b5 /* evil, but the random pool IS global */
079e6d static PGPBoolean¤  sIsSeeded¤  = FALSE;
c9af5a
f1d2f7 ¤   PGPBoolean¤
e60ed8 pgpGlobalRandomPoolIsSeeded( void )
60bb36 {
d9c2c3 ¤   return( sIsSeeded );
cbefe6 }
daaf5a
74c744 ¤   PGPError
820dc9 pgpSeedGlobalRandomPool( PGPContextRef context )
a0bb36 {
70d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
237af6 ¤   PGPRandomContext *¤ randomContext¤  = NULL;
abaf5a
e98c7b ¤   if ( sIsSeeded )·
99a117 ¤   ¤   return( kPGPError_NoErr );
2067c5 ¤
6f8ba5 ¤   randomContext¤  = pgpContextGetGlobalPoolRandomContext( context );
7e7090 ¤   if ( IsntNull( randomContext ) )
3bc7a1 ¤   {
1af84d ¤   ¤   err¤= sSeedRandomPool( context, randomContext );
6d9371 ¤   }
9467c5 ¤
3b2ab5 ¤   /* be conservative, assume not seeded if error */
a81bf0 ¤   sIsSeeded¤  = IsntPGPError( err );
5967c5 ¤
03deb7 ¤   return( err );
98efe6 }
39af5a
8baf5a
2daf5a
1a0335 /*____________________________________________________________________________
adc874 ¤   Add file data into the pool. ·Used to add existing random pool file data
57efb4 ¤   into the random pool before overwiting it. ·This fixes a problem where
be4ec3 ¤   the last client to quit wipes out contributions of previous clients to
--59c0 000b23b40b3401001d3 Page 5 of pgpRndSeed.c
5aee87 ¤   the random pool.
b6f7f7 ____________________________________________________________________________*/
3333c8 ¤   static void
64e66c sAddFileToPool(
03f550 ¤   PGPIORef¤   ¤   ¤   ¤   ¤   io,
ae1f24 ¤   PGPRandomContext const *¤   rc)
01bb36 {
1d9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
85ee03 ¤   PGPFileOffset¤  startPos;
ad67c5 ¤
f5562b ¤   err¤= PGPIOGetPos( io, &startPos );
69f1e7 ¤   if ( IsntPGPError( err ) )
06e7d1 ¤   ¤   err¤= PGPIOSetPos( io, 0 );
1167c5 ¤
db2814 ¤   while ( IsntPGPError( err ) )
aac7a1 ¤   {
244f0f ¤   ¤   PGPByte¤¤   ¤   buffer[ 512 ];
fff6ce ¤   ¤   PGPSize¤¤   ¤   actualCount;
fb1b52 ¤   ¤
1fcbf1 ¤   ¤   err¤= PGPIORead( io, sizeof( buffer ), buffer, &actualCount );
e2a4ab ¤   ¤   if ( IsntPGPError( err ) || err == kPGPError_EOF )
605b34 ¤   ¤   {
1b7028 ¤   ¤   ¤   pgpRandomAddBytes( rc, buffer, actualCount);
f80fe4 ¤   ¤   }
2c0e1d ¤   ¤   else
315b34 ¤   ¤   {
26144d ¤   ¤   ¤   pgpAssertNoErr( err );
ab0fe4 ¤   ¤   }
b09371 ¤   }
6267c5 ¤
d2d906 ¤   (void)PGPIOSetPos( io, startPos );
edefe6 }
25af5a
5daf5a
53c744 ¤   PGPError
ab76c1 pgpSaveGlobalRandomPool( PGPContextRef context )
57bb36 {
bb26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6f6006 ¤   PFLFileSpecRef¤ randSeedRef¤= NULL;
bf8e42 ¤   PGPEnv¤ ¤   *pgpEnv¤¤   = NULL;
40af5a
3fe49e ¤   pgpEnv = pgpContextGetEnvironment( context );
07af5a
29318b ¤   err = GetRandSeedFileRef( context, &randSeedRef );
a4f1e7 ¤   if ( IsntPGPError( err ) )
37c7a1 ¤   {
f39278 ¤   ¤   PGPFileIORef¤   fileIO;
f9af5a
d019d5 ¤   ¤   err¤= PGPOpenFileSpec( randSeedRef, kPFLFileOpenFlags_ReadWrite,
e1e0f2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fileIO );
63af5a
164218 ¤   ¤   if( err == kPGPError_FileNotFound )
825b34 ¤   ¤   {
db90b2 ¤   ¤   ¤   pgpCreateFile( randSeedRef, kPGPFileTypeRandomSeed );
6f840f ¤   ¤   ¤   err¤= PGPOpenFileSpec( randSeedRef, kPFLFileOpenFlags_ReadWrite,
c1769d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&fileIO );
570fe4 ¤   ¤   }
acaf5a
1b8d41 ¤   ¤   PFLFreeFileSpec(randSeedRef);
c41b52 ¤   ¤
377d98 ¤   ¤   if ( IsntPGPError( err ) )
a55b34 ¤   ¤   {
59b91b ¤   ¤   ¤   PGPRandomContext *¤ randomContext¤  = NULL;
9c87c7 ¤   ¤   ¤
c6b629 ¤   ¤   ¤   randomContext¤  = pgpContextGetGlobalPoolRandomContext( context );
861b52 ¤   ¤
2283ac ¤   ¤   ¤   sAddFileToPool( (PGPIORef)fileIO, randomContext );
1faf5a
015cd8 ¤   ¤   ¤   pgpRandSeedWrite( (PGPIORef)fileIO, randomContext, NULL);
b1532a ¤   ¤   ¤   PGPFreeIO( (PGPIORef)fileIO );
b50fe4 ¤   ¤   }
b29371 ¤   }
--6e79 001ae42b06e401001d3 Page 6 of pgpRndSeed.c
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
40af5a
c6af5a
23af5a
bcaf5a
b1af5a
25af5a
e9af5a
8baf5a
187e4d /*__Editor_settings____
acaf5a
bd4126 ¤   Local Variables:
077b17 ¤   tab-width: 4
130e6c ¤   End:
d35f8c ¤   vi: ts=4 sw=4
7c9e9b ¤   vim: si
aed062 _____________________*/
--f03c 0012dd41d20401001d4 Page 1 of pgpRndSeed.h
bc38e5 /*
7d00fc ·* pgpRndSeed.h -- read and write the randseed.rnd file.
bc775e ·*
337ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
5a775e ·*
d38190 ·* This is a Public API Function Header.
01775e ·*
7422b7 ·* $Id: pgpRndSeed.h,v 1.14 1998/04/14 05:00:12 wprice Exp $
9e495d ·*/
43af5a
7fa233 #ifndef Included_pgpRndSeed_h
12f607 #define Included_pgpRndSeed_h
e4af5a
83feb2 #include <stdio.h>
50af5a
0c99c6 PGP_BEGIN_C_DECLARATIONS
0daf5a
6cadb8 #include "pgpOpaqueStructs.h"
d4af5a
73db2d /* We want to see at least this many bytes in randseed */
ad2afc #define PGP_SEED_MIN_BYTES¤ ¤   24
acaf5a
dbaf5a
3daf5a
9097e1 PGPError¤   pgpSeedGlobalRandomPool( PGPContextRef context );
141bd2 PGPError¤   pgpSaveGlobalRandomPool( PGPContextRef context );
29d278 PGPBoolean¤ pgpGlobalRandomPoolIsSeeded( void );
e3af5a
5b1254 PGP_END_C_DECLARATIONS
91af5a
2d263f #endif /* Included_pgpRndSeed_h */
--32a4 0002f8923ca401001d5 Page 1 of pgpRndUnix.c
bc38e5 /*
368d9c ·* Get high-resolution timing information to seed the random number generator.
172190 ·* Unix version. ·(The complicated one.)
c2775e ·*
5dc5ae ·* $Id: pgpRndUnix.c,v 1.10 1997/08/30 03:08:08 hal Exp $
2d495d ·*/
a2af5a
b7e2ff #include "pgpConfig.h"
5daf5a
a838e5 /*
e8e06a ·* This code uses five different timers, if available. ·Each possibility
1ce1bc ·* can be specifically enabled or disabled by predefining USE_XX to 1
1ab37b ·* or 0. ·For some, the code attempts to detect availability automatically.
64ccb6 ·* If the symbols HAVE_XX are defined, they are used. ·If not, they are set
318489 ·* to reasonable defaults while other clues are checked. ·The choices,
e13648 ·* and the auto-detection methods used, are:
c4fc39 ·* - gethrtime(), if HAVE_GETHRTIME is set to 1.
031bea ·* - clock_gettime(CLOCK_REALTIME,...), if CLOCK_REALTIME is in <time.h>
99d878 ·* - gettimeofday(), assumed available unless HAVE_GETTIMEOFDAY=0
f9336a ·* - getitimer(ITIMER_REAL,...), if ITIMER_REAL is defined in <sys/time.h>
d052bb ·* - ftime(), assumed available unless HAVE_FTIME=0
4e775e ·*
0534de ·* These are all accessed through the gettime(), timetype, and tickdiff()
8f934d ·* macros. ·The MINTICK constant is something to avoid the gettimeofday()
dd3239 ·* glitch wherein it increments the return value even if no tick has occurred.
69ca26 ·* When measuring the tick interval, if the difference between two successive
8100fe ·* times is not at least MINTICK ticks, it is ignored.
da495d ·*/
b7af5a
d455ad #ifndef TIME_WITH_SYS_TIME
9c35b7 #define TIME_WITH_SYS_TIME 1¤   /* Assume true if not told */
0f7454 #endif
43af5a
d538e5 /*
21a40b ·* Include <time.h> and <sys/time.h>
c6495d ·*/
eea635 #if HAVE_SYS_TIME_H
cd5d8c #include <sys/time.h>
765a6b #if TIME_WITH_SYS_TIME
ef0a8b #include <time.h>
0b7454 #endif
7edb21 #else
7f0a8b #include <time.h>
497454 #endif
93af5a
78f15e #include <sys/types.h>
ed693b #include <sys/times.h>¤ /* for times() */
28bcf5 #include <stdlib.h>¤/* For qsort() */
15af5a
abdd74 #include "pgpRnd.h"
860f03 #include "pgpRandomContext.h"
edd11f #include "pgpUsuals.h"
5baf5a
663f25 #ifndef USE_GETHRTIME
cd22f2 #define USE_GETHRTIME HAVE_GETHRTIME
917454 #endif
5faf5a
9e1309 #if USE_GETHRTIME
ceada3 typedef hrtime_t timetype;
88a2bc #define gettime(s) (*(s) = gethrtime())
cae052 #define tickdiff(s,t) ((s)-(t))
c60338 #define MINTICK 0
42af5a
f7db21 #else
ce2fba #ifndef USE_CLOCK_GETTIME
80ec68 #ifndef HAVE_CLOCK_GETTIME
c277a0 #define HAVE_CLOCK_GETTIME 1
f07454 #endif
16e3ae #if HAVE_CLOCK_GETTIME
d08476 #ifdef CLOCK_REALTIME
c7785f #define USE_CLOCK_GETTIME 1
2f7454 #endif
--5ea2 0002d765e54401001d5 Page 2 of pgpRndUnix.c
a07454 #endif
b07454 #endif
ccaf5a
849145 #if USE_CLOCK_GETTIME
58af5a
90ecbc #define CHOICE_CLOCK_GETTIME 1
857b7a typedef struct timespec timetype;
2fccc2 #define gettime(s) (void)clock_gettime(CLOCK_REALTIME, s)
b804f8 #define tickdiff(s,t) (((s).tv_sec-(t).tv_sec)*1000000000 + \
5e083d ¤   (s).tv_nsec - (t).tv_nsec)
fc651a #ifndef HAVE_CLOCK_GETRES
983afe #define HAVE_CLOCK_GETRES 1
397454 #endif
2eaf5a
37db21 #else
5faf5a
934ec3 #ifndef USE_GETTIMEOFDAY
a5b856 #ifndef HAVE_GETTIMEOFDAY
bbebcd #define HAVE_GETTIMEOFDAY 1¤/* Assume we have it... */
e87454 #endif
96bd94 #define USE_GETTIMEOFDAY HAVE_GETTIMEOFDAY
bf7454 #endif
21af5a
2262c8 #if USE_GETTIMEOFDAY
e3cc5b typedef struct timeval timetype;
4fa1ec #define gettime(s) (void)gettimeofday(s, (struct timezone *)0)
364d90 #define tickdiff(s,t) (((s).tv_sec-(t).tv_sec)*1000000+(s).tv_usec-(t).tv_usec)
5c1ae0 #define MINTICK 1
f2af5a
b1db21 #else
76af5a
d31c89 #ifndef USE_GETITIMER
16b1ca #ifndef HAVE_GETITIMER
0ea053 #define HAVE_GETITIMER 1
427454 #endif
c1d304 #ifndef HAVE_SETITIMER
8db0fd #define HAVE_SETITIMER 1
a57454 #endif
b60d13 #if HAVE_GETITIMER && HAVE_SETITIMER
d221a8 #ifdef ITIMER_REAL
811709 #define USE_GETITIMER 1
617454 #endif
717454 #endif
6d7454 #endif
c0af5a
7b30a5 #if USE_GETITIMER
12e46c #define CHOICE_GETITIMER 1
045a0a #include <signal.h>¤/* For signal(), SIGALRM, SIG_IGN ·*/
0feeae typedef struct itimerval timetype;
6f6903 #define gettime(s) (void)getitimer(ITIMER_REAL, s)
b8863a /* Subtract *backwards* because timer is counting *down* */
2b495e #define tickdiff(s,t) (((t).it_value.tv_sec-(s).it_value.tv_sec)*1000000 + \
0418bd ¤   (t).it_value.tv_usec - (s).it_value.tv_usec)
881ae0 #define MINTICK 1
80af5a
b7db21 #else
09af5a
b25b7d #ifndef USE_FTIME
5e18ce #ifndef HAVE_FTIME
804cac #define HAVE_FTIME 1
0f7454 #endif
81d1b1 #ifndef HAVE_SYS_TIMEB_H
51f0a5 #define HAVE_SYS_TIMEB_H 1
417454 #endif
aa3dfa #define USE_FTIME HAVE_FTIME && HAVE_SYS_TIMEB_H
f57454 #endif
09af5a
68cbeb #if USE_FTIME
028ea4 #include <sys/timeb.h>
6536ee typedef struct timeb timetype;
e87d26 #define gettime(s) (void)ftime(s)
2dc401 #define tickdiff(s,t) (((s).time-(t).time)*1000 + (s).millitm - (t).millitm)
--25b9 0004316ff9a401001d5 Page 3 of pgpRndUnix.c
1c6cb5 #define MINTICK¤0
cfaf5a
e6db21 #else
02af5a
00ff22 #error No clock available
33af5a
ddb999 #endif /* USE_FTIME */
bc3ddf #endif /* USE_GETITIMER */
c2c55f #endif /* USE_GETTIMEOFDAY */
c31c58 #endif /* USE_CLOCK_GETTIME */
eb9ef0 #endif /* USE_GETHRTIME */
68af5a
1526f5 #if CHOICE_CLOCK_GETTIME && HAVE_CLOCK_GETRES
57af5a
2165bf static unsigned
86b643 ranTickSize(void)
77bb36 {
612fe1 ¤   struct timespec res;
13af5a
802c47 ¤   clock_getres(CLOCK_REALTIME, &res);
d68300 ¤   return (unsigned)res.tv_nsec;
93efe6 }
05af5a
1d80b3 #else /* Normal clock resolution estimation */
96af5a
c2e926 #if NOISEDEBUG
25feb2 #include <stdio.h>
257454 #endif
cdaf5a
eed509 #define N 15¤   /* Number of deltas to try (at least 5, preferably odd) */
e2af5a
0cb964 /* Function needed for qsort() */
87beb7 static int
945fad ranCompare(void const *p1, void const *p2)
33bb36 {
9a1961 ¤   return *(unsigned const *)p1 > *(unsigned const *)p2 ? ·1 :
8bde9a ¤   ·······*(unsigned const *)p1 < *(unsigned const *)p2 ? -1 : 0;
53efe6 }
2eaf5a
a638e5 /*
145f07 ·* Find the resolution of the high-resolution clock by sampling successive
13f41d ·* values until a tick boundary, at which point the delta is entered into
bfb48a ·* a table. ·An average near the median of the table is taken and returned
e891c0 ·* as the system tick size to eliminate outliers due to descheduling (high)
0bbe82 ·* or tv0 not being the "zero" time in a given tick (low).
b2775e ·*
dbf6af ·* Some trickery is needed to defeat the habit systems have of always
9e4e1c ·* incrementing the microseconds field from gettimeofday() results so that
760167 ·* no two calls return the same value. ·Thus, a "tick boundary" is assumed
51b153 ·* when successive calls return a difference of more than MINTICK ticks.
e565f1 ·* (For gettimeofday(), this is set to 2 us.) ·This catches cases where at
e17e6d ·* most one other task reads the clock between successive reads by this task.
8ceef2 ·* More tasks in between are rare enough that they'll get cut off by the
74a08a ·* median filter.
3b775e ·*
286bd9 ·* When a tick boundary is found, the *first* time read during the previous
361928 ·* tick (tv0) is subtracted from the new time to get microseconds per tick.
e4775e ·*
6ba48c ·* Suns have a 1 us timer, and as of SunOS 4.1, they return that timer, but
59fe56 ·* there is ~50 us of system-call overhead to get it, so this overestimates
f7c114 ·* the tick size considerably. ·On SunOS 5.x/Solaris, the overhead has been
8ed9d0 ·* cut to about 2.5 us, so the measured time alternates between 2 and 3 us.
ff36bf ·* Some better algorithms will be required for future machines that really
7223b4 ·* do achieve 1 us granularity.
33775e ·*
13a06c ·* Current best idea: discard all this hair and use Ueli Maurer's entropy
00133e ·* estimation scheme. ·Assign each input event (delta) a sequence number.
d3925d ·* 16 bits should be more than adequate. ·Make a table of the last time
580dad ·* (by sequence number) each possibe input event occurred. ·For practical
8623be ·* implementation, hash the event to a fixed-size code and consider two
5c47c6 ·* events identical if they have the same hash code. ·This will only ever
435718 ·* underestimate entropy. ·Then use the number of bits in the difference
--e68c 000cd90f051401001d5 Page 4 of pgpRndUnix.c
987ddb ·* between the current sequence number and the previous one as the entropy
2bc8e2 ·* estimate.
12775e ·*
6f6a86 ·* If it's desirable to use longer contexts, Maurer's original technique
bf6e2c ·* just groups events into non-overlapping pairs and uses the technique on
60bc52 ·* the pairs. ·If you want to increment the entropy numbers on each keystroke
70ca8a ·* for user-interface niceness, you can do the operation each time, but you
3e06cf ·* have to halve the sequence number difference before starting, and then you
921e9e ·* have to halve the number of bits of entropy computed because you're adding
75d7ec ·* them twice.
73775e ·*
25d74c ·* You can put the even and odd events into separate tables to close Maurer's
4caa7b ·* model exactly, or you can just dump them into the same table, which will
a1ef7e ·* be more conservative.
f9495d ·*/
5965bf static unsigned
68b643 ranTickSize(void)
77bb36 {
1564d9 ¤   unsigned i = 0, j = 0, ·diff, d[N];
4a5776 ¤   timetype tv0, tv1, tv2;
32d8af ¤   /*
a4b996 ¤   ·* TODO Get some per-run data to seed the RNG with.
9ac586 ¤   ·* pid, ppid, etc.
57a4e3 ¤   ·*/
a1818e ¤   gettime(&tv0);
a17a6c ¤   tv1 = tv0;
e143ab ¤   do {
268311 ¤   ¤   gettime(&tv2);
0e010c ¤   ¤   diff = (unsigned)tickdiff(tv2, tv1);
f1bd37 ¤   ¤   if (diff > MINTICK) {
30eaad ¤   ¤   ¤   d[i++] = diff;
895b63 ¤   ¤   ¤   tv0 = tv2;
aad41b ¤   ¤   ¤   j = 0;
81ef6c ¤   ¤   } else if (++j >= 4096)¤/* Always getting <= MINTICK units */
8e6635 ¤   ¤   ¤   return MINTICK + !MINTICK;
0a2d77 ¤   ¤   tv1 = tv2;
b0b05a ¤   } while (i < N);
91af5a
88a8ff ¤   /* Return average of middle 5 values (rounding up) */
72a7d5 ¤   qsort(d, N, sizeof(d[0]), ranCompare);
19860a ¤   diff = (d[N/2-2]+d[N/2-1]+d[N/2]+d[N/2+1]+d[N/2+2]+4)/5;
18e926 #if NOISEDEBUG
7e4ed7 ¤   fprintf(stderr, "Tick size is %u\n", diff);
957454 #endif
4f136a ¤   return diff;
1befe6 }
70af5a
68e96d #endif /* Clock resolution measurement selection */
39af5a
5f38e5 /*
e12db1 ·* Add as much timing-dependent random noise as possible
78cc85 ·* to the randPool. ·Typically, this involves reading the most
076319 ·* accurate system clocks available.
1d775e ·*
439ef3 ·* Returns the number of ticks that have passed since the last call,
2f5e27 ·* for entropy estimation purposes.
ed495d ·*/
d9bccf PGPUInt32
edcefe pgpRandomCollectEntropy(PGPRandomContext const *rc)
c5bb36 {
867eef ¤   PGPUInt32 delta;
b8c6ea ¤   timetype t;
2de413 ¤   static unsigned ticksize = 0;
b9cece ¤   static timetype prevt;
d4af5a
0eb335 ¤   gettime(&t);
07f761 #if CHOICE_GETITIMER
a7dc5c ¤   /* If itimer isn't started, start it */
ae59e8 ¤   if (t.it_value.tv_sec == 0 && t.it_value.tv_usec == 0) {
6c1b17 ¤   ¤   /*
0fe6b0 ¤   ¤   ·* start the timer - assume that PGP won't be running for
cd4727 ¤   ¤   ·* more than 31 days...
--1e80 001462a337a401001d5 Page 5 of pgpRndUnix.c
509de3 ¤   ¤   ·*/
daeafb ¤   ¤   t.it_value.tv_sec = 1000000000;
62a7d5 ¤   ¤   t.it_interval.tv_sec = 1000000000;
b0dcd9 ¤   ¤   t.it_interval.tv_usec = 0;
9c9eb5 #ifdef SIGALRM
88569d ¤   ¤   signal(SIGALRM, SIG_IGN);¤  /* just in case.. */
9d7454 #endif
33ac43 ¤   ¤   setitimer(ITIMER_REAL, &t, NULL);
80bd07 ¤   ¤   t.it_value.tv_sec = 0;
869371 ¤   }
b73b69 ¤   pgpRandomAddBytes(rc, (PGPByte const *)&t.it_value, sizeof(t.it_value));
8adb21 #else
38d30f ¤   pgpRandomAddBytes(rc, (PGPByte const *)&t, sizeof(t));
447454 #endif
8daf5a
5709b0 ¤   if (!ticksize)
e7f301 ¤   ¤   ticksize = ranTickSize();
2a7a4f ¤   delta = (PGPUInt32)(tickdiff(t, prevt) / ticksize);
0f7c6d ¤   prevt = t;
51af5a
e4bb7d ¤   return delta;
46efe6 }
--dbca 000b213f3e9401001d6 Page 1 of pgpRndVMS.c
bc38e5 /*
eb7417 ·* Get environmental noise to seed the random number generator.
1d7bc6 ·* VMS version.
15775e ·*
4d4cb0 ·* This hasn't been examined in a long time (December, 1995).
947972 ·* Could someone who knows VMS please have a look at it and determine
b080f2 ·* if this is still good?
8d775e ·*
9b9ae7 ·* $Id: pgpRndVMS.c,v 1.6 1997/06/25 17:58:55 lloyd Exp $
a1495d ·*/
73af5a
6ee2ff #include "pgpConfig.h"
12af5a
2add74 #include "pgpRnd.h"
b6227a #include "pgpRndom.h"
c3d11f #include "pgpUsuals.h"
9caf5a
3838e5 /*
bc301b ·* Add as much environmentally-derived random noise as possible
a3cc85 ·* to the randPool. ·Typically, this involves reading the most
5d6319 ·* accurate system clocks available.
6f775e ·*
d49ef3 ·* Returns the number of ticks that have passed since the last call,
1d5e27 ·* for entropy estimation purposes.
27495d ·*/
e9bccf PGPUInt32
b5ea7d ranGetEntropy(PGPRandomContext const *rc)
45bb36 {
697eef ¤   PGPUInt32 delta;
9d6a4a ¤   PGPUInt32 d1;¤  /* MSW of difference */
d75bf2 ¤   PGPUInt32 t[2];¤/* little-endian 64-bit timer */
f531d1 ¤   static PGPUInt32 prevt[2];
73af5a
a695b5 ¤   SYS$GETTIM(t);¤ /* VMS hardware clock increments by 100000 per tick */
3da8ef ¤   pgpRandomAddBytes(rc, (PGPByte const *)t, sizeof(t));
e4c4be ¤   /* Get difference in d1 and delta, and old time in prevt */
4ab731 ¤   d1 = t[1] - prevt[1] + (t[0] < prevt[0]);
c58b87 ¤   prevt[1] = t[1];
86c749 ¤   delta = t[0] - prevt[0];
25c2ad ¤   prevt[0] = t[0];
a467c5 ¤
16a882 ¤   /* Now, divide the 64-bit value by 100000 = 2^5 * 5^5 = 32 * 3125 */
9e9fe4 ¤   /* Divide value, MSW in d1 and LSW in delta, by 32 */
e2faac ¤   delta >>= 5;
ff6dd1 ¤   delta |= d1 << (32-5);
99d91c ¤   d1 >>= 5;
b9d8af ¤   /*
a913d7 ¤   ·* Divide by 3125. ·This fits into 16 bits, so the following
a8664c ¤   ·* code is possible. ·2^32 = 3125 * 1374389 + 1671.
059714 ¤   ·*
90a9f8 ¤   ·* This code has confused people reading it, so here's a detailed
6e40a4 ¤   ·* explanation. ·First, since we only want a 32-bit result,
ca94db ¤   ·* reduce the input mod 3125 * 2^32 before starting. ·This
88ae31 ¤   ·* amounts to reducing the most significant word mod 3125 and
87d60c ¤   ·* leaving the least-significant word alone.
5a9714 ¤   ·*
160bb1 ¤   ·* Then, using / for mathematical (real, not integer) division, we
d2067a ¤   ·* want to compute floor((d1 * 2^32 + d0) / 3125), which I'll denote
428e96 ¤   ·* using the old [ ] syntax for floor, so it's
33cb21 ¤   ·* ··[ (d1 * 2^32 + d0) / 3125 ]
c6ee70 ¤   ·* = [ (d1 * (3125 * 1374389 + 1671) + d0) / 3125 ]
52a050 ¤   ·* = [ d1 * 1374389 + (d1 * 1671 + d0) / 3125 ]
cadb81 ¤   ·* = d1 * 137438 + [ (d1 * 1671 + d0) / 3125 ]
752d08 ¤   ·* = d1 * 137438 + [ d0 / 3125 ] + [ (d1 * 1671 + d0 % 3125) / 3125 ]
809714 ¤   ·*
b2016e ¤   ·* The C / operator, applied to integers, performs [ a / b ], so
16e732 ¤   ·* this can be implemented in C, and since d1 < 3125 (by the first
c19caa ¤   ·* modulo operation), d1 * 1671 + d0 % 3125 < 3125 * 1672, which
ebbaff ¤   ·* is 5225000, less than 2^32, so it all fits into 32 bits.
d8a4e3 ¤   ·*/
4ade06 ¤   d1 %= 3125;¤/* Ignore overflow past 32 bits */
b25a3e ¤   delta = delta/3125 + d1*1374389 + (delta%3125 + d1*1671) / 3125;
--10b8 001e2d46dea401001d6 Page 2 of pgpRndVMS.c
e0af5a
11bb7d ¤   return delta;
e2efe6 }
--7e16 001f141441a401001d7 Page 1 of pgpRndWin32.c
bc38e5 /*
2a3da7 ·* Get high-resolution timing information to seed the random number
24ed86 ·* generator. ·Win32 version.
a7775e ·*
13e11e ·* $Id: pgpRndWin32.c,v 1.7 1997/06/25 17:58:56 lloyd Exp $
33495d ·*/
f6af5a
2ee2ff #include "pgpConfig.h"
90af5a
a65655 #include <windows.h>
faaf5a
230f03 #include "pgpRandomContext.h"
0cdd74 #include "pgpRnd.h"
b2af5a
9d38e5 /*
5f2db1 ·* Add as much timing-dependent random noise as possible
59cc85 ·* to the randPool. ·Typically, this involves reading the most
9c6319 ·* accurate system clocks available.
87775e ·*
7b9ef3 ·* Returns the number of ticks that have passed since the last call,
a05e27 ·* for entropy estimation purposes.
58495d ·*/
0fbccf PGPUInt32
92cefe pgpRandomCollectEntropy(PGPRandomContext const *rc)
a7bb36 {
2f7eef ¤   PGPUInt32 delta;
3c1b98 ¤   static WORD oldms;
05f75c ¤   static DWORD oldlow;
397f25 ¤   LARGE_INTEGER newperf;
093169 ¤   SYSTEMTIME stime;
1faf5a
efe9fb ¤   if (QueryPerformanceCounter(&newperf)) {
d796c0 ¤   ¤   pgpRandomAddBytes(rc, (PGPByte *)&newperf, sizeof(newperf));
7796ba ¤   ¤   delta = newperf.LowPart - oldlow;
43e5f9 ¤   ¤   oldlow = newperf.LowPart;
9df037 ¤   } else {
8fce2c ¤   ¤   GetSystemTime(&stime);
e438ae ¤   ¤   pgpRandomAddBytes(rc, (PGPByte *)&stime, sizeof(stime));
d6fcbc ¤   ¤   delta = stime.wMilliseconds - oldms;
275ad6 ¤   ¤   oldms = stime.wMilliseconds;
b64196 ¤   ¤   delta /= 10;¤   /* crude resolution */
3d9371 ¤   }
f7af5a
19bb7d ¤   return delta;
f1efe6 }
--095b 001f908fd07401001d8 Page 1 of Makefile.in
5ea601 #
b9c531 # priv/crypto/secshare/
f1a601 #
9a32d5 # $Id: Makefile.in,v 1.1 1997/12/15 01:48:35 hal Exp $
37a601 #
efaf5a
f64765 OBJS=¤  pgpShamir.o
64a900 PRIVHDRS=·
2caf5a
b1b7a3 all:: DONE
f9af5a
--31a9 000023960fa401001d9 Page 1 of pgpShamir.c
a70335 /*____________________________________________________________________________
0c0b9d ¤   pgpShamir.c
e167c5 ¤
9545b9 ¤   Shamir threshold secret sharing (polynomial based)
0caf5a
21c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
7d4b0f ¤   All rights reserved.
f767c5 ¤
4167c5 ¤
2faf5a
4531a7 ¤   $Id: pgpShamir.c,v 1.4.12.1 1998/11/12 03:21:34 heller Exp $
9cf7f7 ____________________________________________________________________________*/
c7e2ff #include "pgpConfig.h"
f3af5a
d30d08 #include "pgpMem.h"
3b2f8d #include "pgpErrors.h"
afc26c #include "pgpContext.h"
16a076 #include "pgpKeys.h"
5f2c96 #include "pgpRandomX9_17.h"
faaf5a
098a20 /* Output array consists of a share header followed by the share body, for
38b217 ·* each share, all concatenated together.
38495d ·*/
4da1b8 struct PGPShareHeader
f5bb36 {
f6b281 ¤   PGPByte¤¤   ¤   version;¤   ¤   /* Version/algorithm of share */
71d60c ¤   PGPByte¤¤   ¤   xCoordinate;¤   /* X coordinate of share */
58f540 ¤   PGPByte¤¤   ¤   threshold;¤ ¤   /* Number of shares needed to combine */
e1d0f7 ¤   PGPByte¤¤   ¤   lagrange;¤  ¤   /* Temp value used during split/join */
2382f7 };
21af5a
94f7ff /* Version for this algorithm */
4478e2 #define kPGPShare_Version1¤ 0x21
98af5a
3fe7e8 /* X coordinate of secret value */
1b8360 #define X0¤ ¤   0
55af5a
0caf5a
584ebc /* Pointer to nth share body in output */
e76c96 #define BODY(array,bodysize,n) ((PGPByte *)(array) + \
60cc80 ¤   ¤   (n)*((bodysize)+kPGPShareHeaderSize) + kPGPShareHeaderSize)
c4af5a
c36692 /* Pointer to nth share header in output */
4ed61d #define HEADER(array,bodysize,n) ((struct PGPShareHeader *) \
2f023d ¤   ¤   ((PGPByte *)(array) + (n)*((bodysize)+kPGPShareHeaderSize)))
4faf5a
17af5a
8f38e5 /*
f5a74b ·* The magic of Lagrange polynomial interpolation...
54775e ·*
fcb550 ·* Given (x1,y1), (x2,y2)...,(xn,yn) and x0, you want to find y0.
3ea826 ·* This is hardly unique unless you specify that you want a polynomial in x
822522 ·* fitted to the given points and evaluated at x0. ·If the polynomial is
1fd2f9 ·* constrained to be of degree <= n-1 (in the unknown x), then it is unique.
1c775e ·*
dec8e9 ·* We use this to make shares, by letting y1 be the secret,
469b65 ·* choosing y2, ..., yn arbitrarily, and using that to find the
c0b489 ·* extra shares, and to reassemble shares, by trying to recover y1.
4e775e ·*
ffb9be ·* The easy way to find this polynomial is to use a set of degreen n-1 basis
2c4d65 ·* polynomials bi(x) which are 1 at a single xi and 0 at all the other
6cd784 ·* xj, j != i. ·(Needless to say, this is only possible if xi != xj.)
ceb940 ·* Then you can just evaluate y = b1(x)*y1 + ... + bn(x)*yn.
f5775e ·*
d5e3c5 ·* The zeroness is assured by including the factors (x-x1), ... (x-xn)
77ea02 ·* in the numerator of the polynomial bi(x), omitting only (x-xi).
ad9e05 ·* This makes a polynomial of degree n-1 in x, as desired. ·Ensuring
873f42 ·* that bi(xi) == 1 requires dividing by the appropriate constant,
f67600 ·* (xi-x1)*...*(xi-xn), the numerator evaluated at xi, again omitting the
4de0a9 ·* (xi-xi) term.
3d775e ·*
0296f3 ·* In more concrete terms,
--0710 0001af36c70401001d9 Page 2 of pgpShamir.c
4f775e ·*
7a626c ·* ··················(x0-x2)*(x0-x3)*(x0-x4)*...*(x0-xn)
1beb7c ·* y0 = y1 * -------------------------------------------
3a022d ·* ··················(x1-x2)*(x1-x3)*(x1-x4)*...*(x1-xn)
9a775e ·*
21b354 ·* ··········(x0-x1)* ·······(x0-x3)*(x0-x4)*...*(x0-xn)
d8df76 ·* ···+ y2 * -------------------------------------------
71d7cb ·* ··········(x2-x0)* ·······(x2-x3)*(x2-x4)*...*(x2-xn)
169ec0 ·*·
1fafa8 ·* ···+ ...
bb775e ·*
daebbf ·* It turns out to be easier in practice to pre-compute (x0-x1)*...*(x0-xn)
e46c3d ·* and then add the appropriate (x0-xi) term to the denominator to cancel
37a996 ·* the unneeded numerator term.
d1775e ·*
b649a6 ·* Oh, by the way, this is done over the finite field F_256 (encoded
b8d459 ·* in a PGPByte type). ·Multiplication is done through log and antilog
8940b8 ·* tables, f_log[] and f_exp[]. ·The f_exp[] table is double-sized
c93bad ·* so that the sum of two logs can be looked up in it without range
5f5543 ·* reduction, although larger accumulations require reduction modulo
c7c65e ·* the order of the multiplicative group, namely 256-1 = 255.
15775e ·*
1df9e0 ·* Most compilers can optimize division and remainder by a power
19191c ·* of 2, but this one-off is usually handled by a general division,
3c3873 ·* which is slow on most machines. ·There is a much faster version,
4ff601 ·* using the fact that x*FIELD_SIZE == x (mod FIELD_SIZE-1). ·Thus,
a0a134 ·* x == (x%FIELD_SIZE) + (x/FIELD_SIZE) (mod FIELD_SIZE-1), using
26091e ·* truncating integer division. ·This obviously reduces the range of
c04c9e ·* the output x. ·It can't reduce it below 0..FIELD_SIZE-1, but we
eb4077 ·* the antilog table is already big enough for that.
cb775e ·*
17421b ·* The smallest x which is mapped to FIELD_SIZE or larger under this
dfdd5a ·* reduction is 2*FIELD_SIZE-1. ·The smallest x which is reduced to
3ec101 ·* *that* or larger is FIELD_SIZE^2 - 1. ·So adding up FIELD_SIZE+1
ec680b ·* entries with all values of FIELD_SIZE-1 wil require a third
dffb54 ·* iteration to achieve complete reduction, but less than that (all
3656fd ·* that we ever do here) requires only two.
9e495d ·*/
2baf5a
87af5a
50c8ea #define FIELD_SIZE 256
357c91 #define FIELD_POLY 0x169
9faf5a
3cf369 /* Just to make the application clear... */
2b85b0 #define f_add(x,y) ((x)^(y))
0c71ec #define f_sub(x,y) f_add(x,y)
99af5a
3938e5 /*
39addf ·* The possible primitive polynomials of degree 8 are
291a5c ·* 0x11d, 0x12b, 0x12d, 0x14d, 0x15f, 0x163, 0x165, 0x169,
afa4a1 ·* 0x171, 0x187, 0x18d, 0x1a9, 0x1c3, 0x1cf, 0x1e7, 0x1f5
d954a7 ·* Other polynomials (irreducible but not primitive) are possible
892828 ·* if you use something other than x as the generator.
d8495d ·*/
68af5a
424147 #if PGP_STATIC_SHAMIR_ARRAYS
4aaf5a
c23053 /* Code to dynamically construct these arrays is below as an alternative */
28af5a
03d187 static const PGPByte f_exp[2*FIELD_SIZE] = {
42441a ····0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
e77788 ····0x69, 0xd2, 0xcd, 0xf3, 0x8f, 0x77, 0xee, 0xb5,
e044d5 ····0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xe9,
adc29e ····0xbb, 0x1f, 0x3e, 0x7c, 0xf8, 0x99, 0x5b, 0xb6,
ebde0d ····0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x29, 0x52,
f9e9be ····0xa4, 0x21, 0x42, 0x84, 0x61, 0xc2, 0xed, 0xb3,
417b54 ····0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x89, 0x7b, 0xf6,
52e069 ····0x85, 0x63, 0xc6, 0xe5, 0xa3, 0x2f, 0x5e, 0xbc,
2e9e9d ····0x11, 0x22, 0x44, 0x88, 0x79, 0xf2, 0x8d, 0x73,
91ea94 ····0xe6, 0xa5, 0x23, 0x46, 0x8c, 0x71, 0xe2, 0xad,
74ea2b ····0x33, 0x66, 0xcc, 0xf1, 0x8b, 0x7f, 0xfe, 0x95,
1a5c3c ····0x43, 0x86, 0x65, 0xca, 0xfd, 0x93, 0x4f, 0x9e,
--74ce 00091acb115401001d9 Page 3 of pgpShamir.c
29f7e1 ····0x55, 0xaa, 0x3d, 0x7a, 0xf4, 0x81, 0x6b, 0xd6,
67e5b1 ····0xc5, 0xe3, 0xaf, 0x37, 0x6e, 0xdc, 0xd1, 0xcb,
dfc033 ····0xff, 0x97, 0x47, 0x8e, 0x75, 0xea, 0xbd, 0x13,
9e544f ····0x26, 0x4c, 0x98, 0x59, 0xb2, 0x0d, 0x1a, 0x34,
e7989b ····0x68, 0xd0, 0xc9, 0xfb, 0x9f, 0x57, 0xae, 0x35,
03783f ····0x6a, 0xd4, 0xc1, 0xeb, 0xbf, 0x17, 0x2e, 0x5c,
42b4ed ····0xb8, 0x19, 0x32, 0x64, 0xc8, 0xf9, 0x9b, 0x5f,
d0de6b ····0xbe, 0x15, 0x2a, 0x54, 0xa8, 0x39, 0x72, 0xe4,
21291c ····0xa1, 0x2b, 0x56, 0xac, 0x31, 0x62, 0xc4, 0xe1,
45f396 ····0xab, 0x3f, 0x7e, 0xfc, 0x91, 0x4b, 0x96, 0x45,
6d1c1e ····0x8a, 0x7d, 0xfa, 0x9d, 0x53, 0xa6, 0x25, 0x4a,
ccf7e9 ····0x94, 0x41, 0x82, 0x6d, 0xda, 0xdd, 0xd3, 0xcf,
bb06fb ····0xf7, 0x87, 0x67, 0xce, 0xf5, 0x83, 0x6f, 0xde,
4522f7 ····0xd5, 0xc3, 0xef, 0xb7, 0x07, 0x0e, 0x1c, 0x38,
607604 ····0x70, 0xe0, 0xa9, 0x3b, 0x76, 0xec, 0xb1, 0x0b,
b29d4b ····0x16, 0x2c, 0x58, 0xb0, 0x09, 0x12, 0x24, 0x48,
40912d ····0x90, 0x49, 0x92, 0x4d, 0x9a, 0x5d, 0xba, 0x1d,
d2feec ····0x3a, 0x74, 0xe8, 0xb9, 0x1b, 0x36, 0x6c, 0xd8,
9f92dd ····0xd9, 0xdb, 0xdf, 0xd7, 0xc7, 0xe7, 0xa7, 0x27,
754c99 ····0x4e, 0x9c, 0x51, 0xa2, 0x2d, 0x5a, 0xb4, 0x01,
72dab5 ····0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x69,
1841b1 ····0xd2, 0xcd, 0xf3, 0x8f, 0x77, 0xee, 0xb5, 0x03,
65e688 ····0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xe9, 0xbb,
619aa6 ····0x1f, 0x3e, 0x7c, 0xf8, 0x99, 0x5b, 0xb6, 0x05,
a79dd1 ····0x0a, 0x14, 0x28, 0x50, 0xa0, 0x29, 0x52, 0xa4,
80f543 ····0x21, 0x42, 0x84, 0x61, 0xc2, 0xed, 0xb3, 0x0f,
5f70ef ····0x1e, 0x3c, 0x78, 0xf0, 0x89, 0x7b, 0xf6, 0x85,
b3b42d ····0x63, 0xc6, 0xe5, 0xa3, 0x2f, 0x5e, 0xbc, 0x11,
a7b5a7 ····0x22, 0x44, 0x88, 0x79, 0xf2, 0x8d, 0x73, 0xe6,
ba2793 ····0xa5, 0x23, 0x46, 0x8c, 0x71, 0xe2, 0xad, 0x33,
c15360 ····0x66, 0xcc, 0xf1, 0x8b, 0x7f, 0xfe, 0x95, 0x43,
82d5c0 ····0x86, 0x65, 0xca, 0xfd, 0x93, 0x4f, 0x9e, 0x55,
79f412 ····0xaa, 0x3d, 0x7a, 0xf4, 0x81, 0x6b, 0xd6, 0xc5,
28db0e ····0xe3, 0xaf, 0x37, 0x6e, 0xdc, 0xd1, 0xcb, 0xff,
6a0e48 ····0x97, 0x47, 0x8e, 0x75, 0xea, 0xbd, 0x13, 0x26,
35873f ····0x4c, 0x98, 0x59, 0xb2, 0x0d, 0x1a, 0x34, 0x68,
ff361b ····0xd0, 0xc9, 0xfb, 0x9f, 0x57, 0xae, 0x35, 0x6a,
f72119 ····0xd4, 0xc1, 0xeb, 0xbf, 0x17, 0x2e, 0x5c, 0xb8,
ee087b ····0x19, 0x32, 0x64, 0xc8, 0xf9, 0x9b, 0x5f, 0xbe,
923f0a ····0x15, 0x2a, 0x54, 0xa8, 0x39, 0x72, 0xe4, 0xa1,
e98f20 ····0x2b, 0x56, 0xac, 0x31, 0x62, 0xc4, 0xe1, 0xab,
e1e117 ····0x3f, 0x7e, 0xfc, 0x91, 0x4b, 0x96, 0x45, 0x8a,
b5732f ····0x7d, 0xfa, 0x9d, 0x53, 0xa6, 0x25, 0x4a, 0x94,
b81ba3 ····0x41, 0x82, 0x6d, 0xda, 0xdd, 0xd3, 0xcf, 0xf7,
a01009 ····0x87, 0x67, 0xce, 0xf5, 0x83, 0x6f, 0xde, 0xd5,
6b51a6 ····0xc3, 0xef, 0xb7, 0x07, 0x0e, 0x1c, 0x38, 0x70,
600c1b ····0xe0, 0xa9, 0x3b, 0x76, 0xec, 0xb1, 0x0b, 0x16,
0e799d ····0x2c, 0x58, 0xb0, 0x09, 0x12, 0x24, 0x48, 0x90,
256edc ····0x49, 0x92, 0x4d, 0x9a, 0x5d, 0xba, 0x1d, 0x3a,
ad4057 ····0x74, 0xe8, 0xb9, 0x1b, 0x36, 0x6c, 0xd8, 0xd9,
0907cf ····0xdb, 0xdf, 0xd7, 0xc7, 0xe7, 0xa7, 0x27, 0x4e,
6a3179 ····0x9c, 0x51, 0xa2, 0x2d, 0x5a, 0xb4, 0x01, 0x02
7182f7 };
80af5a
3b45cc static const PGPByte f_log[FIELD_SIZE] =
91bb36 {
30e231 ····0xff, 0x00, 0x01, 0x10, 0x02, 0x20, 0x11, 0xcc,
1199cb ····0x03, 0xdc, 0x21, 0xd7, 0x12, 0x7d, 0xcd, 0x30,
5e09a8 ····0x04, 0x40, 0xdd, 0x77, 0x22, 0x99, 0xd8, 0x8d,
f04944 ····0x13, 0x91, 0x7e, 0xec, 0xce, 0xe7, 0x31, 0x19,
344154 ····0x05, 0x29, 0x41, 0x4a, 0xde, 0xb6, 0x78, 0xf7,
8f8f11 ····0x23, 0x26, 0x9a, 0xa1, 0xd9, 0xfc, 0x8e, 0x3d,
cce600 ····0x14, 0xa4, 0x92, 0x50, 0x7f, 0x87, 0xed, 0x6b,
c80023 ····0xcf, 0x9d, 0xe8, 0xd3, 0x32, 0x62, 0x1a, 0xa9,
d35786 ····0x06, 0xb9, 0x2a, 0x58, 0x42, 0xaf, 0x4b, 0x72,
3e13d1 ····0xdf, 0xe1, 0xb7, 0xad, 0x79, 0xe3, 0xf8, 0x5e,
437398 ····0x24, 0xfa, 0x27, 0xb4, 0x9b, 0x60, 0xa2, 0x85,
dca8d2 ····0xda, 0x7b, 0xfd, 0x1e, 0x8f, 0xe5, 0x3e, 0x97,
2c221f ····0x15, 0x2c, 0xa5, 0x39, 0x93, 0x5a, 0x51, 0xc2,
4a2cfa ····0x80, 0x08, 0x88, 0x66, 0xee, 0xbb, 0x6c, 0xc6,
a1e3dd ····0xd0, 0x4d, 0x9e, 0x47, 0xe9, 0x74, 0xd4, 0x0d,
9112a1 ····0x33, 0x44, 0x63, 0x36, 0x1b, 0xb1, 0xaa, 0x55,
--5085 0008a58072b401001d9 Page 4 of pgpShamir.c
d70ecd ····0x07, 0x65, 0xba, 0xc5, 0x2b, 0x38, 0x59, 0xc1,
d9b8ad ····0x43, 0x35, 0xb0, 0x54, 0x4c, 0x46, 0x73, 0x0c,
720849 ····0xe0, 0xac, 0xe2, 0x5d, 0xb8, 0x57, 0xae, 0x71,
6b72f8 ····0x7a, 0x1d, 0xe4, 0x96, 0xf9, 0xb3, 0x5f, 0x84,
8e9d85 ····0x25, 0xa0, 0xfb, 0x3c, 0x28, 0x49, 0xb5, 0xf6,
e2f4b0 ····0x9c, 0xd2, 0x61, 0xa8, 0xa3, 0x4f, 0x86, 0x6a,
f694c8 ····0xdb, 0xd6, 0x7c, 0x2f, 0xfe, 0x0f, 0x1f, 0xcb,
823eb8 ····0x90, 0xeb, 0xe6, 0x18, 0x3f, 0x76, 0x98, 0x8c,
7948e1 ····0x16, 0x8a, 0x2d, 0xc9, 0xa6, 0x68, 0x3a, 0xf4,
7db8f6 ····0x94, 0x82, 0x5b, 0x6f, 0x52, 0x0a, 0xc3, 0xbf,
85143b ····0x81, 0x6e, 0x09, 0xbe, 0x89, 0xc8, 0x67, 0xf3,
04870c ····0xef, 0xf0, 0xbc, 0xf1, 0x6d, 0xbd, 0xc7, 0xf2,
b246e2 ····0xd1, 0xa7, 0x4e, 0x69, 0x9f, 0x3b, 0x48, 0xf5,
67b537 ····0xea, 0x17, 0x75, 0x8b, 0xd5, 0x2e, 0x0e, 0xca,
116b18 ····0x34, 0x53, 0x45, 0x0b, 0x64, 0xc4, 0x37, 0xc0,
e0a52a ····0x1c, 0x95, 0xb2, 0x83, 0xab, 0x5c, 0x56, 0x70
7482f7 };
96af5a
370a91 #else¤  /* PGP_STATIC_SHAMIR_ARRAYS */
69af5a
1cc8e7 static PGPByte f_exp[2*FIELD_SIZE];
65b51d static PGPByte f_log[FIELD_SIZE];
81af5a
e4af5a
b02b97 /* Code to dynamically struct f_log and f_exp arrays */
6338e5 /*
c91e10 ·* Initialize the f_exp and f_log arrays (if necessary).
fef1c6 ·* Safe (and fast) to call redundantly, so any convenient time will do.
ff495d ·*/
5333c8 ¤   static void
b744a1 s_FSetup(void)
83bb36 {
c637e6 ¤   unsigned i, x;
81af5a
c38643 ¤   if (!f_log[0]) {
80ee16 ¤   ¤   x = 1;
746d8b ¤   ¤   for (i = 0; i < FIELD_SIZE-1; i++) {
ed27e6 ¤   ¤   ¤   f_exp[i] = x;
f9d1a9 ¤   ¤   ¤   f_exp[i+FIELD_SIZE-1] = x;
ae6ad5 ¤   ¤   ¤   f_log[x] = i;
9544f7 ¤   ¤   ¤   x <<= 1;
b8af52 ¤   ¤   ¤   if (x & FIELD_SIZE)
d07524 ¤   ¤   ¤   ¤   x ^= FIELD_POLY;
630fe4 ¤   ¤   }
64ecaa ¤   ¤   /* x should be 1 here */
223313 ¤   ¤   f_exp[2*FIELD_SIZE-2] = f_exp[0];
98f7d6 ¤   ¤   f_exp[2*FIELD_SIZE-1] = f_exp[1];
aee424 ¤   ¤   f_log[0] = i;¤  /* Bogus value, FIELD_SIZE-1 */
199371 ¤   }
58efe6 }
6daf5a
a9012d #endif¤ /* PGP_STATIC_SHAMIR_ARRAYS */
b4af5a
2938e5 /*
10d0d1 ·* This is the core of secret sharing. ·This computes the coefficients
d221c4 ·* used in Lagrange polynomial interpolation, returning the
158303 ·* vector of logarithms of b1(xtarget), b2(xtarget), ..., bn(xtarget).
f352c7 ·* Takes values from the "xCoordinate" header element, inserts the
dbefe3 ·* results in the "lagrange" header element.
2299f0 ·* The interpolation values come from the headers of the "shares" array,
1248b2 ·* plus one additional value, xInput, which is the value we are going
c19b8d ·* to interpolate to.
4e9ec0 ·*·
65ef74 ·* Returns kPGPError_OK on success, error if not all x[i] are unique.
e2495d ·*/
8d66dd ¤   static PGPError
0a0999 sInterp(PGPByte *shares, PGPSize bodySize, PGPByte xInput, PGPUInt32 nShares)
12bb36 {
90f236 ¤   PGPUInt32¤  ¤   i, j;
719f9d ¤   PGPByte¤¤   ¤   xi, xj;
3db5e1 ¤   PGPUInt32¤  ¤   numer, denom;
8aaf5a
--176c 000da192e60401001d9 Page 5 of pgpShamir.c
de833e #if !PGP_STATIC_SHAMIR_ARRAYS
b5d4d2 ¤   s_FSetup();
6ea294 #endif /* !PGP_STATIC_SHAMIR_ARRAYS */
55af5a
502b20 ¤   /* First, accumulate the numerator, Prod(xInput-x[i],i=0..n) */
c213b8 ¤   numer = 0;
5a237b ¤   for (i = 0; i < nShares; i++)
d4c7a1 ¤   {
e73f54 ¤   ¤   xi = HEADER(shares,bodySize,i)->xCoordinate;
a761d6 ¤   ¤   numer += f_log[ f_sub(xi, xInput) ];
fe9371 ¤   }
ea320d ¤   /* Preliminary partial reduction */
2e283d ¤   numer = (numer%FIELD_SIZE) + (numer/FIELD_SIZE);
dfaf5a
ae2ee8 ¤   /* Then, for each coefficient, compute the corresponding denominator */
26cc82 ¤   for (i = 0; i < nShares; i++) {
623f54 ¤   ¤   xi = HEADER(shares,bodySize,i)->xCoordinate;
796828 ¤   ¤   denom = 0;
783e8a ¤   ¤   for (j = 0; j < nShares; j++) {
0e5c48 ¤   ¤   ¤   xj = (i == j) ? xInput : HEADER(shares,bodySize,j)->xCoordinate;
589a24 ¤   ¤   ¤   if (xi == xj)
1edd34 ¤   ¤   ¤   ¤   return -1;
1c1311 ¤   ¤   ¤   denom += f_log[f_sub(xi,xj)];
d80fe4 ¤   ¤   }
bb3976 ¤   ¤   denom = (denom%FIELD_SIZE)+(denom/FIELD_SIZE);
ffe762 ¤   ¤   /* 0 <= denom < 2*FIELD_SIZE-1. */
f2af5a
8406db ¤   ¤   /* Now find numer/denom. ·In log form, that's a subtract. */
8cc6f9 ¤   ¤   denom = numer + 2*FIELD_SIZE-2 - denom;
2a3976 ¤   ¤   denom = (denom%FIELD_SIZE)+(denom/FIELD_SIZE);
2d3976 ¤   ¤   denom = (denom%FIELD_SIZE)+(denom/FIELD_SIZE);
6daf5a
4b1fd1 ¤   ¤   HEADER(shares,bodySize,i)->lagrange = (PGPByte)denom;
219371 ¤   }
5a6dd4 ¤   return kPGPError_NoErr;¤/* Success */
efefe6 }
cfaf5a
18af5a
8faf5a
3b38e5 /*
b9c35d ·* This actually does the interpolation, using the coefficients
40ffcc ·* computed by sInterp(). ·Uses shares at offset byteNumber within the
92477a ·* bodies.
2821bf ·* The Lagrange values come from the headers of the "shares" array.
24495d ·*/
16d790 ¤   static PGPByte
32d51f sDoInterp(PGPByte *shares, PGPSize bodySize, PGPUInt32 nShares,
5adbe4 ¤   PGPUInt32 byteNumber)
d4bb36 {
d84ee7 ¤   PGPByte x, y;
ed196d ¤   PGPByte lagrange;
a751fc ¤   PGPUInt32 i;
72af5a
5bd570 ¤   x = 0;
7cd265 ¤   for( i=0; i < nShares; ++i )
27c7a1 ¤   {
c188d2 ¤   ¤   y = BODY(shares, bodySize, i)[byteNumber];
15bc8f ¤   ¤   if (y != 0)
935b34 ¤   ¤   {
311ab7 ¤   ¤   ¤   lagrange = HEADER(shares, bodySize, i)->lagrange;
2ecd5f ¤   ¤   ¤   y = f_exp[lagrange + f_log[y]];
490fe4 ¤   ¤   }
ee46b5 ¤   ¤   x = f_add(x,y);
2e9371 ¤   }
13af5a
8afedf ¤   return x;
25efe6 }
70af5a
c5af5a
46af5a
dbc744 ¤   PGPError
da0ddf PGPSecretShareData(
--419e 00091a17171401001d9 Page 6 of pgpShamir.c
e3a1bc ¤   PGPContextRef¤  ¤   context,
58e2c7 ¤   void const *¤   ¤   input,
e5f017 ¤   PGPSize¤¤   ¤   ¤   inputBytes,
abeea1 ¤   PGPUInt32¤  ¤   ¤   threshold,
bf0c5d ¤   PGPUInt32¤  ¤   ¤   nShares,
9e493c ¤   void *¤ ¤   ¤   ¤   output
6c27e6 ¤   )
53bb36 {
1f418f ¤   PGPUInt32¤  ¤   ¤   i, j;
da462d ¤   PGPByte¤¤   ¤   ¤   xupdate;
d3cccc ¤   PGPRandomContext¤   *rng;¤  ¤   ¤   /* Random state */
70af5a
b54ae2 ¤   rng = pgpContextGetX9_17RandomContext( context );
7faf5a
43404a ¤   /* Set X coordinate randomly for each share */
2f84a3 ¤   for( i=0; i<nShares; ++i )
5dc7a1 ¤   {
ff0400 ¤   ¤   PGPBoolean xok = FALSE;
cb7040 ¤   ¤   /* Pick a unique, random x coordinate != X0 */
71b7a2 ¤   ¤   while( !xok )
745b34 ¤   ¤   {
a8c8ae ¤   ¤   ¤   pgpRandomGetBytes( rng,
6c0389 ¤   ¤   ¤   ¤   ¤   ¤   ···&(HEADER(output,inputBytes,i)->xCoordinate), 1 );
488983 ¤   ¤   ¤   if( HEADER(output,inputBytes,i)->xCoordinate != X0 )
edf776 ¤   ¤   ¤   {
23c05f ¤   ¤   ¤   ¤   for( j=0; j<i; ++j )
cc72c3 ¤   ¤   ¤   ¤   {
c04c9a ¤   ¤   ¤   ¤   ¤   if( HEADER(output,inputBytes,i)->xCoordinate ==
c8d8a4 ¤   ¤   ¤   ¤   ¤   ¤   HEADER(output,inputBytes,j)->xCoordinate )
ba00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
1a2613 ¤   ¤   ¤   ¤   }
ee17e6 ¤   ¤   ¤   ¤   if( j == i )
3772c3 ¤   ¤   ¤   ¤   {
b395b7 ¤   ¤   ¤   ¤   ¤   xok = TRUE;
352613 ¤   ¤   ¤   ¤   }
b8a3a6 ¤   ¤   ¤   }
c40fe4 ¤   ¤   }
e45076 ¤   ¤   /* Set other header values as well */
0824aa ¤   ¤   HEADER(output,inputBytes,i)->version = kPGPShare_Version1;
d8a08a ¤   ¤   HEADER(output,inputBytes,i)->threshold = threshold;
ebdca1 ¤   ¤   HEADER(output,inputBytes,i)->lagrange = 0;
5b9371 ¤   }
eeaf5a
deb498 ¤   /* Initialize thresh-1 bodies to random numbers */
ede851 ¤   for( i=0; i<threshold-1; ++i )
15c7a1 ¤   {
2c4311 ¤   ¤   pgpRandomGetBytes( rng, BODY(output,inputBytes,i), inputBytes );
e09371 ¤   }
99af5a
107cb9 ¤   /* Copy input to the first share body past the random ones */
5221d9 ¤   pgpCopyMemory( input, BODY(output,inputBytes,threshold-1), inputBytes );
511b52 ¤   ¤
3257f8 ¤   /* Put X0 into xCoordinate for that header */
29d8e7 ¤   /* xupdate holds the X value for the share we will be updating */
04969a ¤   xupdate = HEADER(output,inputBytes,threshold-1)->xCoordinate;
d0960b ¤   HEADER(output,inputBytes,threshold-1)->xCoordinate = X0;
42af5a
e0d8af ¤   /*
e4dd48 ¤   ·* Now set each of the remaining bodies via interpolation.
8be87d ¤   ·* Work from last to threshold-1 so we can leave our input copy in
497efc ¤   ·* the threshold slot.
44a4e3 ¤   ·*/
a474d3 ¤   for( i=nShares-1; i!=threshold-2; --i )
62c7a1 ¤   {
70690e ¤   ¤   PGPByte tmp;
74af5a
79c9af ¤   ¤   /* Interpolate to that value */
3bfb0c ¤   ¤   sInterp( (unsigned char *) output, inputBytes, xupdate, threshold );
d33fcd ¤   ¤   for( j=0; j<inputBytes; ++j )
3e5b34 ¤   ¤   {
e84288 ¤   ¤   ¤   BODY(output, inputBytes, i)[j] =
91e3a6 ¤   ¤   ¤   ¤   sDoInterp( (unsigned char *) output, inputBytes, threshold, j );
--c515 000b9ceaf14401001d9 Page 7 of pgpShamir.c
b50fe4 ¤   ¤   }
e067f3 ¤   ¤   /* Swap in xupdate value for share we just calculated */
a4ffec ¤   ¤   tmp = HEADER(output,inputBytes,i)->xCoordinate;
be7779 ¤   ¤   HEADER(output,inputBytes,i)->xCoordinate = xupdate;
83aead ¤   ¤   xupdate = tmp;
239371 ¤   }
a0af5a
4a5856 ¤   /* Zero lagrange values, were just temporary */
5d84a3 ¤   for( i=0; i<nShares; ++i )
43c7a1 ¤   {
31dca1 ¤   ¤   HEADER(output,inputBytes,i)->lagrange = 0;
be9371 ¤   }
93151e ¤   return kPGPError_NoErr;
63efe6 }
8daf5a
f6af5a
78c744 ¤   PGPError
56d392 PGPSecretReconstructData(
a1a1bc ¤   PGPContextRef¤  ¤   context,
b27ac8 ¤   void *¤ ¤   ¤   ¤   input,
1c2d65 ¤   PGPSize¤¤   ¤   ¤   outputBytes,
330c5d ¤   PGPUInt32¤  ¤   ¤   nShares,
d6493c ¤   void *¤ ¤   ¤   ¤   output
dc27e6 ¤   )
51bb36 {
b9418f ¤   PGPUInt32¤  ¤   ¤   i, j;
1dbcac ¤   PGPByte¤¤   ¤   ¤   threshold;
4a7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
e0af5a
9e6d02 ¤   (void) context;
17af5a
bc8e7b ¤   /* Verify version and threshold consistency */
65dda7 ¤   threshold = HEADER(input,outputBytes,0)->threshold;
95af5a
fd84a3 ¤   for( i=0; i<nShares; ++i )
1bc7a1 ¤   {
806c12 ¤   ¤   if( HEADER(input,outputBytes,i)->version != kPGPShare_Version1 )
da5b34 ¤   ¤   {
ba61a4 ¤   ¤   ¤   pgpDebugMsg( "Error: invalid Reconstruction version" );
f95820 ¤   ¤   ¤   err = kPGPError_BadParams;
5ced19 ¤   ¤   ¤   goto error;
610fe4 ¤   ¤   }
dc64d2 ¤   ¤   if( HEADER(input,outputBytes,i)->threshold != threshold )
9c5b34 ¤   ¤   {
135ec5 ¤   ¤   ¤   pgpDebugMsg( "Error: inconsistent threshold in reconstruction" );
aa5820 ¤   ¤   ¤   err = kPGPError_BadParams;
8ded19 ¤   ¤   ¤   goto error;
0f0fe4 ¤   ¤   }
929371 ¤   }
28af5a
3e35d4 ¤   /* Make sure we have enough shares */
0b1523 ¤   if (nShares < threshold)
30c7a1 ¤   {
b72b18 ¤   ¤   pgpDebugMsg( "Error: insufficient shares in reconstruction" );
ca19d3 ¤   ¤   err = kPGPError_BadParams;
7597ed ¤   ¤   goto error;
569371 ¤   }
efaf5a
718714 ¤   /* Set up Lagrange coefficients to interpolate to x=X0 */
1c20fe ¤   sInterp( (unsigned char *) input, outputBytes, X0, threshold );
10af5a
b9844d ¤   /* For each byte j, interpolate to output[j] using coordinates */
be8512 ¤   for( j=0; j<outputBytes; ++j )
98c7a1 ¤   {
79b44d ¤   ¤   ((PGPByte *)output)[j] =
4d2b90 ¤   ¤   ¤   ¤   sDoInterp( (PGPByte *)input, outputBytes, threshold, j );
bd9371 ¤   }
a867c5 ¤
3e5856 ¤   /* Zero lagrange values, were just temporary */
1484a3 ¤   for( i=0; i<nShares; ++i )
54c7a1 ¤   {
b9bb8d ¤   ¤   HEADER(input,outputBytes,i)->lagrange = 0;
--02de 0016bc96e44401001d9 Page 8 of pgpShamir.c
a19371 ¤   }
93af5a
9060ff error:
d1af5a
e25ea8 ¤   return err;
28efe6 }
56af5a
31af5a
71af5a
19af5a
be7e4d /*__Editor_settings____
e9af5a
cc4126 ¤   Local Variables:
b27b17 ¤   tab-width: 4
7b0e6c ¤   End:
3c5f8c ¤   vi: ts=4 sw=4
9e9e9b ¤   vim: si
6bd062 _____________________*/
--e9e4 001b76d22c0401001da Page 1 of Makefile.in
5ea601 #
70a797 # priv/debug/
40a601 #
d066a4 # $Id: Makefile.in,v 1.2 1997/05/04 10:44:46 mhw Exp $
7aa601 #
44af5a
3027b0 OBJS= pgpDEBUGStartup.o
6c7f47 PRIVHDRS= pgpDEBUGStartup.h
83af5a
d0b7a3 all:: DONE
b7af5a
--7187 00194af36e0401001db Page 1 of pgpDEBUGStartup.c
a70335 /*____________________________________________________________________________
7e90d0 ¤   PGPsdkDEBUGStartup.c
3367c5 ¤
aac97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
3c4b0f ¤   All rights reserved.
6467c5 ¤
ae67c5 ¤
b0af5a
a1ed52 ¤   $Id: pgpDEBUGStartup.c,v 1.5.24.1 1998/11/12 03:21:35 heller Exp $
25f7f7 ____________________________________________________________________________*/
a4e2ff #include "pgpConfig.h"
13af5a
81e85e #if PGP_DEBUG¤  /* [ */
e6af5a
881b87 #include "pgpErrorsPriv.h"
acaf5a
f8fdbe #include "pgpDEBUGStartup.h"
58af5a
77af5a
c3af5a
9f6d52 ¤   void
fc4327 PGPDebugStartup()
1bbb36 {
e3efe6 }
30af5a
dbaf5a
27ab79 #endif¤ /* ] PGP_DEBUG */
c9af5a
8d7e4d /*__Editor_settings____
93af5a
cd4126 ¤   Local Variables:
b27b17 ¤   tab-width: 4
370e6c ¤   End:
255f8c ¤   vi: ts=4 sw=4
b29e9b ¤   vim: si
94d062 _____________________*/
--69eb 0016fbe9c32401001dc Page 1 of pgpDEBUGStartup.h
a70335 /*____________________________________________________________________________
a99633 ¤   pgpDEBUGStartup.h
9667c5 ¤
aac97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
814b0f ¤   All rights reserved.
1867c5 ¤
3067c5 ¤
a5af5a
198ed3 ¤   $Id: pgpDEBUGStartup.h,v 1.2.30.1 1998/11/12 03:21:36 heller Exp $
16f7f7 ____________________________________________________________________________*/
a2bbe7 #ifndef Included_pgpDEBUGStartup_h¤ /* [ */
be89bd #define Included_pgpDEBUGStartup_h
28af5a
7aaf5a
a9af5a
8ce85e #if PGP_DEBUG¤  /* [ */
f6af5a
5d99c6 PGP_BEGIN_C_DECLARATIONS
e1af5a
cdede2 void¤   PGPDebugStartup( void );
04af5a
4aaf5a
fb1254 PGP_END_C_DECLARATIONS
6caf5a
62f754 #else¤  /* ] [ */
c7af5a
d5eeed #define PGPDebugStartup()¤  {/*nothing*/}
b8af5a
8c3167 #endif¤ /* ] */
e5af5a
9ba7e4 #endif /* ] Included_pgpDEBUGStartup_h */
cfaf5a
adaf5a
907e4d /*__Editor_settings____
a7af5a
074126 ¤   Local Variables:
337b17 ¤   tab-width: 4
930e6c ¤   End:
7a5f8c ¤   vi: ts=4 sw=4
099e9b ¤   vim: si
6fd062 _____________________*/

--b778 001284d1b4a401001dd Page 1 of Makefile.in
5ea601 #
0fc100 # priv/encrypt/
c2a601 #
8c7f21 # $Id: Makefile.in,v 1.5 1997/07/28 23:43:19 mhw Exp $
36a601 #
cdaf5a
9f8975 OBJS= pgpEncode.o pgpEvent.o pgpEncSubr.o pgpDecode.o
b0e177 PRIVHDRS= pgpEventPriv.h pgpEncodePriv.h
07af5a
4fb7a3 all:: DONE
28af5a
--5f8c 0006531e9f8401001de Page 1 of pgpDecode.c
a70335 /*____________________________________________________________________________
b0702f ¤   pgpDecode.c
5eaaef ¤   High level decode functionality
fc67c5 ¤
68c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
6f4b0f ¤   All rights reserved.
0567c5 ¤
9b67c5 ¤
80af5a
c3bafa ¤   $Id: pgpDecode.c,v 1.97.2.2.2.1 1998/11/12 03:21:37 heller Exp $
c2f7f7 ____________________________________________________________________________*/
0cd224 #include "pgpConfig.h"¤ /* or pgpConfig.h in the CDK */
e8af5a
2c324c #include <string.h>
52af5a
23eb3d /* Public headers */
b1e82c #include "pgpPubTypes.h"
f1c26c #include "pgpContext.h"
f49f63 #include "pgpEncode.h"
242f8d #include "pgpErrors.h"
8aa076 #include "pgpKeys.h"
320d08 #include "pgpMem.h"
5aaf5a
9a622b /* Private headers */
183051 #include "pgpSDKBuildFlags.h"
10a146 #include "pgpDebug.h"
278b0d #include "pgpEncodePriv.h"
7d6aaa #include "pgpAnnotate.h"
c8f476 #include "pgpArmor.h"
bfe8f7 #include "pgpBufMod.h"
d40e2f #include "pgpSymmetricCipherPriv.h"
1f27ba #include "pgpConvKey.h"
26d1d7 #include "pgpDecPipe.h"
2e115d #include "pgpDevNull.h"
ca0d6d #include "pgpEnv.h"
2a57c7 #include "pgpESK.h"
c62d40 #include "pgpEventPriv.h"
a1910a #include "pgpFIFO.h"
5d72de #include "pgpFile.h"
5a3709 #include "pgpFileMod.h"
75a4b2 #include "pgpFileRef.h"
77894b #include "pgpFileSpec.h"
4a39d3 #include "pgpFileType.h"
2c9f72 #include "pgpHash.h"
77711b #include "pgpKeyDB.h"
a27ca7 #include "pgpKeyIDPriv.h"
e7979a #include "pgpKDBInt.h"
260d08 #include "pgpMem.h"
9b1dd3 #include "pgpMemMod.h"
abfb31 #include "pgpOptionList.h"
bf2ece #include "pgpPipeline.h"
47cdc2 #include "pgpPubKey.h"
c0adc0 #include "pgpRandomPoolPriv.h"
f826e3 #include "pgpRngPub.h"
1843bc #include "pgpSig.h"
8e3576 #include "pgpTextFilt.h"
80ae6d #include "pgpTrstPkt.h"
e0e117 #include "pgpUI.h"
f645ee #include "pgpVMemMod.h"
11af5a
26d622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
f5af5a
a31bee /************************** Types and Constants ***************************/
afaf5a
f1af5a
4c8582 /* All state information for pgpDecode is kept in a struct like this */
ee2501 struct PGPDecodeJob_
44bb36 {
80ad10 ¤   PGPContextRef¤  ¤   ·context;¤  ¤   /* Context pointer */
891d4d ¤   PGPOptionListRef¤   ·optionList;¤   /* List of all our options */
25e96b ¤   PGPOptionListRef¤   ·newOptionList;¤/* New options from user callback */
650837 ¤   PGPUICb ·············ui;¤   ¤   ¤   /* Callback functions */
--d49c 000845ebd2f401001de Page 2 of pgpDecode.c
79c2a8 ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error */
26b7fc ¤   PGPEnv¤ ¤   ¤   ¤   *env;¤  ¤   ¤   /* Environment for low-level fns */
08cccc ¤   PGPRandomContext¤   *rng;¤  ¤   ¤   /* Random state */
46a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
2c0df3 ¤   PGPBoolean¤ ¤   ¤   ·fUsedDetachedSigOp; ·/* Have used detachedsig op */
9f185c ¤   PGPPipeline¤¤   ¤   *head, **tail;¤ /* Low level pipeline */
73e370 ¤   PGPPipeline¤¤   ¤   *outPipe;¤  ¤   /* Dynamic memory output module */
c6db76 ¤   PGPFile¤¤   ¤   ¤   *pfout;¤¤   ¤   /* Output file handle */
c67bf9 ¤   PGPPipeline¤¤   ¤   *outKey;¤   ¤   /* Key data output module */
214a46 ¤   PGPPipeline¤¤   ¤   *prevStarOutput;/* Deferred tail of output pipeline */
5965c9 ¤   PGPPipeline¤¤   ···**prevOutput;¤   /* Address of pointer to pipe tail */
4ca8d2 ¤   PGPPipeline¤¤   ¤   *prevOutPipe;¤  /* Dynamic memory mod for prevoutput */
f9756b ¤   PGPFile¤¤   ¤   ¤   *prevPFout;¤¤   /* Output file handle for prevoutput */
1c31ab ¤   PGPBoolean¤ ¤   ¤   ·fPrevOutput;¤  /* Have set prevOutput */
6ae9bf ¤   PFLConstFileSpecRef¤ inFileRef;¤¤   /* Input filename handle */
d0bb84 ¤   PGPFileRead¤¤   ¤   *pfrin;¤¤   ¤   /* Input file reading structure */
3ff05f ¤   PGPByte¤¤   ¤   ¤   *inBufPtr;¤ ¤   /* Input buffer pointer */
fdc787 ¤   PGPSize¤¤   ¤   ¤   ·inBufLength;¤  /* Size of input buffer */
9c4c31 ¤   PFLFileSpecRef¤ ¤   ·outFileRef;¤   /* Output filename handle */
a3fa91 ¤   PGPByte¤¤   ¤   ¤   *outBufPtr;¤¤   /* Output buffer pointer */
df59d7 ¤   PGPByte¤¤   ¤   ···**outBufPtrPtr;¤ /* Dynamically allocated buf ptr */
1a5021 ¤   PGPSize¤¤   ¤   ¤   ·outBufMaxLength; /* Allocated size of outBufPtr */
9a670b ¤   PGPSize¤¤   ¤   ¤   *outBufUsedLength; /* Amount output to outBufPtr */
ba05cd ¤   PGPBoolean¤ ¤   ¤   ·outDiscard;¤   /* True if want to discard output */
d36e5b ¤   PGPBoolean¤ ¤   ¤   ·fixedOutput;¤  /* Use same output throughout */
26c59c ¤   PGPBoolean¤ ¤   ¤   ·fAppendOutput;¤/* Append output to buffer or file */
13314e ¤   PGPEventHandlerProcPtr func;¤   ¤   /* Pointer to user callback func */
2601b2 ¤   PGPUserValue¤   ¤   ·userValue;¤¤   /* Arg to callback func */
679ab2 ¤   PGPBoolean¤ ¤   ¤   ·fNullEvents;¤  /* True if user wants null events */
a2b087 ¤   PGPUInt32¤  ¤   ¤   ·localEncodeFlags; /* Macbinary etc. for output */
97047f ¤   PGPLineEndType¤ ¤   ·lineEnd;¤  ¤   /* Line endings for text output */
0a2109 ¤   PGPKeySetRef¤   ¤   ·keySet;¤   ¤   /* Keyset to check sigs, decrypt */
014288 ¤   PGPByte¤¤   ¤   ¤   *passPhrase;¤   /* Pass phrase from user */
54e8b8 ¤   PGPSize¤¤   ¤   ¤   ·passLength;¤   /* Length of passPhrase */
18d62e ¤   PGPBoolean¤ ¤   ¤   ·hashedPhrase;¤ /* True if given passkey */
fa7250 ¤   PGPUInt32¤  ¤   ¤   sectionNumber;¤ /* Number of section we are on */
ba0291 ¤   PGPAnalyzeType¤ ¤   analyzeType;¤   /* Type of section we found */
8f1c65 ¤   PGPInt32¤   ¤   ¤   analyzeState;¤  /* kAnalyze status */
50dd97 ¤   PGPInt32¤   ¤   ¤   scopeLevel;¤/* Nesting scope */
37d27c ¤   PGPInt32¤   ¤   ¤   scopeSegment;¤  /* scopeLevel at start of segment */
02694d ¤   PGPSize¤¤   ¤   ¤   sectOffset;¤¤   /* Offset in input to start of sect */
fb6c92 ¤   PGPBoolean¤ ¤   ¤   passThrough;¤   /* True if outputing without change */
4bcb8e ¤   PGPFifoContext¤ ¤   *passThroughFifo; /* Accumulate some passthrough data*/
bf299e ¤   PGPByte¤¤   ¤   ¤   literalType;¤   /* type of literal packet */
a3dfe8 ¤   PGPBoolean¤ ¤   ¤   recurse;¤   ¤   /* Recursing on decode */
8182f7 };
ba8ecb typedef struct PGPDecodeJob_ PGPDecodeJob;
51af5a
cbdb8f /* analyzeState values */
c073f4 enum {
056db3 ¤   kAnalyzeWaiting = 1,
091bfd ¤   kAnalyzeGotType,
1b4b16 ¤   kAnalyzeSegmentEndWait
6e82f7 };
0caf5a
08af5a
5f3b5f /*********** Functions to set up data structures for pipeline *************/
57af5a
35af5a
256454 /* Parse output specifications */
25af5a
3838e5 /*
e46dc7 ·* Note that any outFileRef returned will be a fresh copy, which the
ecab5b ·* caller is responsible for freeing after use.
7e495d ·*/
5666dd ¤   static PGPError
019c23 pgpSetupOutput(
11edf4 ¤   PGPOptionListRef¤   ··optionList,
1b4aa6 ¤   PGPEnv¤ ¤   ¤   ¤   ·*env,
57f3c8 ¤   PFLFileSpecRef¤ ¤   ·*outFileRef,¤  /* Output params */
9c0310 ¤   PGPByte¤¤   ¤   ¤   **outBufPtr,
849909 ¤   PGPByte¤¤   ¤   ···***outBufPtrPtr,
--63d4 000d75b8b80401001de Page 3 of pgpDecode.c
32ce07 ¤   PGPSize¤¤   ¤   ¤   ·*outBufLength,
eba685 ¤   PGPSize¤¤   ¤   ¤   **outBufUsed,
f687cc ¤   PGPBoolean¤ ¤   ¤   ·*outDiscard,
fc9afa ¤   PGPUInt32¤  ¤   ¤   ·*localEncodeFlags,
3f8795 ¤   PGPLineEndType¤ ¤   ·*lineEnd,
afa1ab ¤   PGPBoolean¤ ¤   ¤   ·*pAppendOutput
a727e6 ¤   )
04bb36 {
b4a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
f26ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
434358 ¤   PGPUInt32¤  ¤   ¤   ·localEncode;¤  /* Enum for macbinary, etc. */
776300 ¤   PFLConstFileSpecRef¤ lOutFileRef;¤  /* Local copy of outfileref */
60404e ¤   PGPFileSpecRef¤ ·¤  ·lOutFileRefPGP;/* Another local copy of outfileref */
8c2d0d ¤   PGPUInt32¤  ¤   ¤   ·fDiscard;¤ ¤   /* Discard output option flag */
d72882 ¤   PGPUInt32¤  ¤   ¤   ·fAppendOutput;¤/* Append to output flag */
85af5a
eb9a3b ¤   (void) env;
03af5a
6bdec5 ¤   /* Init return data to default states */
b12c54 ¤   pgpa( pgpaAddrValid( outFileRef, PFLConstFileSpecRef ) );
790fed ¤   pgpa( pgpaAddrValid( outBufPtr, PGPByte * ) );
414f1a ¤   pgpa( pgpaAddrValid( outBufLength, PGPSize ) );
b41ecf ¤   pgpa( pgpaAddrValid( outBufUsed, PGPSize * ) );
5e82cd ¤   pgpa( pgpaAddrValid( outDiscard, PGPBoolean ) );
4ed916 ¤   pgpa( pgpaAddrValid( localEncodeFlags, PGPUInt32 ) );
df73d7 ¤   pgpa( pgpaAddrValid( lineEnd, PGPLineEndType ) );
799837 ¤   *outFileRef = NULL;
a87725 ¤   *outBufPtr = NULL;
edf3e6 ¤   *outBufLength = 0;
566016 ¤   *outBufUsed = NULL;
99d828 ¤   *outDiscard = FALSE;
134c53 ¤   *localEncodeFlags = 0;
a03d70 ¤   *lineEnd = pgpGetDefaultLineEndType ();
b87036 ¤   *pAppendOutput = FALSE;
3daf5a
2e8f4f ¤   /* Test for append flag */
0d7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
bf15aa ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_AppendOutput, FALSE,
35400c ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fAppendOutput ) ) )
9d97ed ¤   ¤   goto error;
ae19ee ¤   *pAppendOutput = (PGPBoolean)fAppendOutput;
f1af5a
f8c248 ¤   /* See if there is an output file specified */
9a7e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
b00c29 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputFileRef, &op ) ) )
3f97ed ¤   ¤   goto error;
fbaf5a
847343 ¤   if( IsOp( op ) ) {
8e4ada ¤   ¤   /* Have an output file specified */
a37f02 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)&lOutFileRefPGP ) ) )
6eed19 ¤   ¤   ¤   goto error;
410c05 ¤   ¤   lOutFileRef = (PFLConstFileSpecRef) lOutFileRefPGP;
cbfb17 ¤   ¤   if( IsPGPError( err = PFLCopyFileSpec( lOutFileRef, outFileRef ) ) )
47ed19 ¤   ¤   ¤   goto error;
139371 ¤   }
baaf5a
f54fcf ¤   /* See if there is an output buffer specified */
8a7e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
576b9b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputBuffer, &op ) ) )
7b97ed ¤   ¤   goto error;
baaf5a
857343 ¤   if( IsOp( op ) ) {
e46d62 ¤   ¤   /* Have an output buffer specified */
8df865 ¤   ¤   if( IsntNull( *outFileRef ) ) {
97bc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
fa5820 ¤   ¤   ¤   err = kPGPError_BadParams;
d7ed19 ¤   ¤   ¤   goto error;
060fe4 ¤   ¤   }
fb67c5 ¤
85a152 ¤   ¤   if( IsPGPError( err = pgpOptionPtrLengthPtr( &op, (void **)outBufPtr,
cd0416 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outBufLength, (void **)outBufUsed ) ) )
d7ed19 ¤   ¤   ¤   goto error;
--b310 000bccfdd48401001de Page 4 of pgpDecode.c
e0af5a
059371 ¤   }
02af5a
c72c97 ¤   /* Check for variable-sized output buffer specification */
457e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
d3eabc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputAllocatedBuffer, &op ) ) )
fb97ed ¤   ¤   goto error;
9aaf5a
697343 ¤   if( IsOp( op ) ) {
7f6d62 ¤   ¤   /* Have an output buffer specified */
0894c9 ¤   ¤   if( IsntNull( *outFileRef ) || IsntNull( *outBufPtr ) ) {
6cbc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
255820 ¤   ¤   ¤   err = kPGPError_BadParams;
5fed19 ¤   ¤   ¤   goto error;
7e0fe4 ¤   ¤   }
b967c5 ¤
4d05a6 ¤   ¤   if( IsPGPError( err = pgpOptionPtrLengthPtr( &op,
77a505 ¤   ¤   ¤   ¤   (void **)outBufPtrPtr, outBufLength, (void **)outBufUsed ) ) )
53ed19 ¤   ¤   ¤   goto error;
499371 ¤   }
5faf5a
c860d2 ¤   /* Check for request to discard output (send to devnull module) */
e67bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
8718f3 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_DiscardOutput, FALSE,
c5c0c9 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fDiscard ) ) )
c197ed ¤   ¤   goto error;
2c3513 ¤   if( fDiscard ) {
70493b ¤   ¤   /* User wants to go to /dev/null */
2ee29d ¤   ¤   if( IsntNull( *outFileRef ) || IsntNull( *outBufPtr ) ||
27cf45 ¤   ¤   ¤   IsntNull( *outBufPtrPtr ) ) {
c1bc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
5f5820 ¤   ¤   ¤   err = kPGPError_BadParams;
45ed19 ¤   ¤   ¤   goto error;
4e0fe4 ¤   ¤   }
71e36b ¤   ¤   *outDiscard = TRUE;
6a9371 ¤   }
85af5a
51e496 ¤   /* Read output local encoding and line endings */
367e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
623082 ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_LocalEncoding, &op ) ) )
2fed19 ¤   ¤   ¤   goto error;
c77343 ¤   if( IsOp( op ) ) {
4bd040 ¤   ¤   if( IsPGPError( err = pgpOptionUInt( &op, &localEncode ) ) )
b3ed19 ¤   ¤   ¤   goto error;
ba4066 ¤   ¤   *localEncodeFlags = pgpLocalEncodingToFlags( localEncode );
7e9371 ¤   }
6d7e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
4b75e7 ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_OutputLineEndType, &op ) ) )
8897ed ¤   ¤   goto error;
247343 ¤   if( IsOp( op ) ) {
a1f858 ¤   ¤   PGPUInt32 uintLineEnd;
20536d ¤   ¤   if( IsPGPError( err = pgpOptionUInt( &op, &uintLineEnd ) ) )
39ed19 ¤   ¤   ¤   goto error;
91a9be ¤   ¤   *lineEnd = (PGPLineEndType) uintLineEnd;
579371 ¤   }
15af5a
72151e ¤   return kPGPError_NoErr;
00af5a
b060ff error:
b7af5a
f19837 ¤   *outFileRef = NULL;
1f7725 ¤   *outBufPtr = NULL;
8efbc3 ¤   *outBufPtrPtr = NULL;
4ff3e6 ¤   *outBufLength = 0;
2fd828 ¤   *outDiscard = FALSE;
b34c53 ¤   *localEncodeFlags = 0;
46aad9 ¤   *lineEnd = pgpGetDefaultLineEndType();
6c0c50 ¤   return err;·
63efe6 }
89af5a
28af5a
bcef14 /* Get keyring set from user if specified */
--0bc7 0009f3bbbed401001de Page 5 of pgpDecode.c
e0af5a
5866dd ¤   static PGPError
4fb417 pgpSetupKeySet(
d0edf4 ¤   PGPOptionListRef¤   ··optionList,
31e48c ¤   PGPKeySetRef¤   ¤   ·*keySet¤   ¤   /* Output params */
2c27e6 ¤   )
64bb36 {
3ba22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
216ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
66af5a
addec5 ¤   /* Init return data to default states */
b8d588 ¤   pgpa( pgpaAddrValid( keySet, PGPKeySetRef ) );
980236 ¤   *keySet = NULL;
02af5a
a1de31 ¤   /* See if there is a keyset specified */
2b7e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
236f0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_KeySetRef, &op ) ) )
e997ed ¤   ¤   goto error;
15af5a
e57343 ¤   if( IsOp( op ) ) {
4e3ee2 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)keySet ) ) )
74ed19 ¤   ¤   ¤   goto error;
329371 ¤   }
a8af5a
30151e ¤   return kPGPError_NoErr;
f2af5a
0260ff error:
8a0236 ¤   *keySet = NULL;
855ea8 ¤   return err;
dcefe6 }
c167c5 ¤
3238e5 /*
35e876 ·* Get passphrase from user. ·We make a copy of the passphrase because if
9a93ab ·* it is specified from a callback, when we free the optionlist it will
6a9b5a ·* go away.
76495d ·*/
79af5a
6d66dd ¤   static PGPError
8b4bd3 pgpSetupDecodePassphrase(
f1476e ¤   PGPContextRef¤  ·¤  ··context,¤ ¤   /* Input params */
74edf4 ¤   PGPOptionListRef¤   ··optionList,
c7be8a ¤   PGPByte¤¤   ¤   ¤   **passPhrase,¤  /* Output params */
a7475c ¤   PGPSize¤¤   ¤   ¤   ·*passLength,
09e356 ¤   PGPBoolean¤ ¤   ¤   ·*hashedPhrase
5427e6 ¤   )
82bb36 {
26cd0f ¤   void¤   ¤   ¤   ¤   *vPassPhrase;¤  /* Pointer to option pphrase */
94c294 ¤   PGPByte¤¤   ¤   ¤   *lPassPhrase;¤  /* Local allocated passphrase */
f2dc9c ¤   PGPSize¤¤   ¤   ¤   ·lPassLength;¤  /* Local copy of pphrase length */
4f6ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
1baf5a
71dec5 ¤   /* Init return data to default states */
3c3331 ¤   pgpa( pgpaAddrValid( passPhrase, PGPByte * ) );
160b5d ¤   pgpa( pgpaAddrValid( passLength, PGPSize ) );
8bd429 ¤   pgpa( pgpaAddrValid( passLength, PGPBoolean ) );
bf819a ¤   *passPhrase = NULL;
29c66e ¤   *passLength = (PGPSize)0;
b1b881 ¤   *hashedPhrase = FALSE;
50af5a
465c37 ¤   /* See if there is a pass phrase specified */
7e7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e64dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
ba576f ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &vPassPhrase, &lPassLength ) ) )
db97ed ¤   ¤   goto error;
96b137 ¤   if( IsNull( vPassPhrase ) ) {
265d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
d4925d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passkey, FALSE,
87424c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &vPassPhrase, &lPassLength ) ) )
7eed19 ¤   ¤   ¤   goto error;
3dea28 ¤   ¤   if( IsntNull( vPassPhrase ) )
881c01 ¤   ¤   ¤   *hashedPhrase = TRUE;
9f9371 ¤   }
--4b66 000980ecceb401001de Page 6 of pgpDecode.c
84ab85 ¤   if( IsntNull( vPassPhrase ) ) {
2a96e6 ¤   ¤   lPassPhrase = (PGPByte *)
57a739 ¤   ¤   ¤   PGPNewSecureData(PGPGetContextMemoryMgr(context), lPassLength, 0);
5bae5b ¤   ¤   if( IsNull( lPassPhrase ) ) {
f5b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
a4ed19 ¤   ¤   ¤   goto error;
770fe4 ¤   ¤   }
2c4094 ¤   ¤   pgpCopyMemory( vPassPhrase, lPassPhrase, lPassLength );
b9cd61 ¤   ¤   *passPhrase = lPassPhrase;
5943d3 ¤   ¤   *passLength = lPassLength;
bf9371 ¤   }
41151e ¤   return kPGPError_NoErr;
87af5a
5e60ff error:
7d819a ¤   *passPhrase = NULL;
52c66e ¤   *passLength = (PGPSize)0;
225ea8 ¤   return err;
deefe6 }
4daf5a
4eaf5a
1438e5 /*
f515f2 ·* Handle options requesting that we pass clearsigned data and/or keys
77e73b ·* through to the output, unchanged. ·We still do the signature checking
97bbcc ·* on signed text, and we still do the key callbacks. ·This just affects
683d03 ·* what goes into the output.
54495d ·*/
7caf5a
b466dd ¤   static PGPError
7f0148 pgpSetupPassThrough(
8e476e ¤   PGPContextRef¤  ·¤  ··context,¤ ¤   /* Input params */
56edf4 ¤   PGPOptionListRef¤   ··optionList,
1168b4 ¤   PGPPipeline¤¤   ¤   ·*pipeHead,
03b0f3 ¤   PGPFifoContext¤ ¤   **fifo,¤¤   ¤   /* Output params */
629871 ¤   PGPBoolean¤ ¤   ¤   *recurse
f927e6 ¤   )
afbb36 {
59366d ¤   PGPUInt32¤  ¤   ¤   ·fPassClear;¤   ¤   /* True if passthroughcleartext */
11117b ¤   PGPUInt32¤  ¤   ¤   ·fPassKeys;¤¤   ¤   /* True if passthroughkeys */
0ee913 ¤   PGPUInt32¤  ¤   ¤   ·fRecurse;¤ ¤   ¤   /* True if recursivelydecode */
8089e1 ¤   PGPByte¤¤   ¤   ¤   ·boolFlag = TRUE;¤  /* Flag for turning on modes */
a7987e ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   ¤   /* Error return code */
c1af5a
bfdec5 ¤   /* Init return data to default states */
9ecba4 ¤   pgpa( pgpaAddrValid( fifo, PGPByte * ) );
93cb35 ¤   pgpa( pgpaAddrValid( recurse, PGPBoolean ) );
21f48d ¤   *fifo = NULL;
a24403 ¤   *recurse = FALSE;
b0af5a
8ff97a ¤   /* Read our passthroughoptions */
157bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e193ed ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_PassThroughClearSigned, FALSE,
dc7d09 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fPassClear ) ) )
2297ed ¤   ¤   goto error;
ad7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
4ab246 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_PassThroughKeys, FALSE,
bd7803 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fPassKeys ) ) )
b397ed ¤   ¤   goto error;
237bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
f2f3c1 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_RecursivelyDecode, FALSE,
34d83c ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fRecurse ) ) )
b797ed ¤   ¤   goto error;
c31971 ¤   *recurse = (PGPBoolean)fRecurse;
3daf5a
53ba27 ¤   fPassClear |= fRecurse;¤¤   /* Recurse needs passthroughclearsigned */
f4af5a
4e734a ¤   if( fPassClear || fPassKeys ) {
c266a0 ¤   ¤   *fifo = pgpFifoCreate( context, &pgpByteFifoDesc );
4c70f4 ¤   ¤   if (*fifo == NULL) {
beb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
25ed19 ¤   ¤   ¤   goto error;
e70fe4 ¤   ¤   }
989371 ¤   }
--3602 000a2bc61c9401001de Page 7 of pgpDecode.c
2a67c5 ¤
f6e311 ¤   if( fPassClear ) {
002a14 ¤   ¤   pipeHead->annotate( pipeHead, NULL, PGPANN_PASSTHROUGH_CLEARSIGN,
c0c2d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &boolFlag, 1 );
a09371 ¤   }
4baf5a
66f114 ¤   if( fPassKeys ) {
a44ef1 ¤   ¤   pipeHead->annotate( pipeHead, NULL, PGPANN_PASSTHROUGH_KEYS,
eec2d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &boolFlag, 1 );
259371 ¤   }
4aaf5a
36151e ¤   return kPGPError_NoErr;
7faf5a
d360ff error:
7cd9d0 ¤   if( IsntNull( *fifo ) ) {
bbb77e ¤   ¤   pgpFifoDestroy( &pgpByteFifoDesc, *fifo );
9dce17 ¤   ¤   *fifo = NULL;
619371 ¤   }
755ea8 ¤   return err;
42efe6 }
9eaf5a
7faf5a
a6675d /* Burn a passphrase from the job state structure, if any */
9b33c8 ¤   static void
1f8837 pgpBurnDecodePassphrase ( PGPDecodeJob *s )
05bb36 {
e4a21a ¤   if( IsntNull( s->passPhrase ) ) {
b56d1c ¤   ¤   pgpClearMemory( s->passPhrase, s->passLength );
04b209 ¤   ¤   PGPFreeData( s->passPhrase );
ca70a0 ¤   ¤   s->passPhrase = NULL;
e2ee22 ¤   ¤   s->passLength = 0;
ad9371 ¤   }
7defe6 }
aeaf5a
05af5a
57b68f /*********************** Subroutines for callbacks *************************/
04af5a
63af5a
f12a8a /* Close an existing output pipeline and do appropriate cleanup */
66af5a
b966dd ¤   static PGPError
8c1f48 pgpCloseOutput(
7b4811 ¤   PGPDecodeJob¤   ¤   ·*s,
25cbb5 ¤   PGPPipeline¤¤   ¤   **output
e327e6 ¤   )
2dbb36 {
ff9c27 ¤   PGPError¤   ¤   ¤   ··err;
f9af5a
554bb5 ¤   if( IsntNull( *output ) ) {
ce0972 ¤   ¤   (*output)->sizeAdvise (*output, 0);
836236 ¤   ¤   if( IsntNull( s->outPipe ) ) {
df9ba7 ¤   ¤   ¤   /* Return buffer sizes to user */
0389fa ¤   ¤   ¤   if( IsntNull( s->outBufPtrPtr ) ) {
917c1b ¤   ¤   ¤   ¤   /* Dynamically allocated buffer - tell user size & position */
15ea1d ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpGetVariableMemOutput( s->outPipe,
9a1e71 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufMaxLength, s->outBufPtrPtr,
174c98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufUsedLength ) ) )
2cb622 ¤   ¤   ¤   ¤   ¤   goto error;
73042d ¤   ¤   ¤   } else {
83de6f ¤   ¤   ¤   ¤   /* Fixed size buffer - tell user actual size used */
c9663a ¤   ¤   ¤   ¤   pgpAssert( IsntNull( s->outBufPtr ) );
9a5f59 ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpGetMemOutput( s->outPipe,
b71840 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufMaxLength, s->outBufUsedLength ) ) )
d5b622 ¤   ¤   ¤   ¤   ¤   goto error;
2aa3a6 ¤   ¤   ¤   }
f08568 ¤   ¤   ¤   s->outPipe = NULL;
a80fe4 ¤   ¤   }
aee8f5 ¤   ¤   (*output)->teardown (*output);
ea65c6 ¤   ¤   *output = NULL;
5f9110 ¤   ¤   if( s->pfout ) {
0131f2 ¤   ¤   ¤   pgpFileClose( s->pfout );
a2c4ba ¤   ¤   ¤   s->pfout = NULL;
--7d41 00036e96370401001de Page 8 of pgpDecode.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
3f151e ¤   return kPGPError_NoErr;
8060ff error:
eb5ea8 ¤   return err;
64efe6 }
2eaf5a
7caf5a
142e00 /* Close an existing buffer saving a key and do appropriate cleanup */
9caf5a
ac66dd ¤   static PGPError
736dec pgpCloseKeyOutput(
f540b4 ¤   PGPDecodeJob¤   ¤   *s
eb27e6 ¤   )
2abb36 {
5fa22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
14010b ¤   PGPByte¤¤   ¤   ¤   *bufPtr;¤   ¤   /* Buffer pointer for key data */
a2e0d1 ¤   PGPSize¤¤   ¤   ¤   ·bufLength;¤¤   /* Length of key buffer */
077afd ¤   PGPKeySet¤  ¤   ¤   *keySet;¤   ¤   /* Keyset for key data */
164093 ¤   PGPKeySet¤  ¤   ¤   *importKeySet;¤ /* Keyset we are adding to for user */
2875f8 ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error code */
a28060 ¤   PGPContextRef¤  ¤   cdkContext;
6eaf5a
d07355 ¤   pgpAssertAddrValid( s, PGPDecodeJob );
0f1b8d ¤   cdkContext¤ = s->context;
91af5a
c67812 ¤   keySet = NULL;
feb96f ¤   importKeySet = NULL;
14938e ¤   bufPtr = NULL;
edaf5a
61cb3b ¤   /* Get buffer and length where key data is */
f5e106 ¤   pgpAssert( IsntNull( s->outKey ) );
a1e977 ¤   if( IsPGPError( err = pgpGetVariableMemOutput( s->outKey,
e0345d ¤   ¤   ¤   ¤   ¤   (PGPSize)~0, &bufPtr, &bufLength ) ) )
c197ed ¤   ¤   goto error;
f9af5a
5d56f2 ¤   /* Close down output portion of pipeline */
8b1db2 ¤   s->outKey = NULL;
267e5c ¤   pgpAssert( s->fPrevOutput );
cf01f8 ¤   pgpAssert( IsntNull( s->prevOutput ) );
c9b497 ¤   pgpAssert( IsNull( s->outPipe ) );
43c35f ¤   if( IsPGPError( err = pgpCloseOutput(s, ·s->prevOutput ) ) )
f697ed ¤   ¤   goto error;
61af5a
23a469 ¤   /* Translate into a keyset holding any imported key(s) */
ebc38a ¤   if( IsPGPError( err = pgpImportKeyBinary( s->context,
ae8b4c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··bufPtr, bufLength, &keySet ) ) )
3897ed ¤   ¤   goto error;
7d2ca3 ¤   PGPFreeData( bufPtr );
50938e ¤   bufPtr = NULL;
aaaf5a
1febb9 ¤   /* See if there is a keyset specified for adding keys to */
6bd83f ¤   if( IsPGPError( err = pgpSearchOptionSingle( s->optionList,
ae0d44 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ImportKeysTo, &op ) ) )
9d97ed ¤   ¤   goto error;
387343 ¤   if( IsOp( op ) ) {
a38f6c ¤   ¤   /* Add keys to user-specified keyset */
55d292 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)&importKeySet ) ) )
1eed19 ¤   ¤   ¤   goto error;
c99dca ¤   ¤   pgpa(pgpaPGPKeySetValid(importKeySet));
070ac0 ¤   ¤   if( !pgpKeySetIsValid(importKeySet) ) {
c0edd6 ¤   ¤   ¤   pgpDebugMsg( "Error: invalid ImportKeysTo keyset" );
9f5820 ¤   ¤   ¤   err = kPGPError_BadParams;
46ed19 ¤   ¤   ¤   goto error;
110fe4 ¤   ¤   }
eb579c ¤   ¤   if( IsPGPError( err = PGPAddKeys( keySet, importKeySet) ) )
4ded19 ¤   ¤   ¤   goto error;
a7573c ¤   ¤   if( IsPGPError( err = PGPCommitKeyRingChanges( importKeySet ) ) )
2aed19 ¤   ¤   ¤   goto error;
673b1a ¤   ¤   PGPFreeKeySet( keySet );
e943fb ¤   ¤   keySet = NULL;
36f037 ¤   } else {
--5582 0009e95d2e0401001de Page 9 of pgpDecode.c
0b6b57 ¤   ¤   /* Else see if we should ask user what to do with keys */
ec5468 ¤   ¤   PGPUInt32 fKeyEvents;
de977e ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( s->optionList,
8bba46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_SendEventIfKeyFound, FALSE,
3fcbec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fKeyEvents ) ) )
a4ed19 ¤   ¤   ¤   goto error;
81f567 ¤   ¤   if( fKeyEvents ) {
981a68 ¤   ¤   ¤   err = pgpEventKeyFound( s->context, &s->newOptionList,
da82e3 ¤   ¤   ¤   ¤   ¤   ¤   s->func, s->userValue, keySet );
de6b76 ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
1f59df ¤   ¤   ¤   if( IsPGPError( err ) )
011b7c ¤   ¤   ¤   ¤   goto error;
d80fe4 ¤   ¤   }
8bf031 ¤   ¤   /* User has dealt with it if he wants, now we can delete data */
b13b1a ¤   ¤   PGPFreeKeySet( keySet );
7143fb ¤   ¤   keySet = NULL;
6f9371 ¤   }
b3151e ¤   return kPGPError_NoErr;
4860ff error:
669ed3 ¤   if( IsntNull( bufPtr ) )
3b388b ¤   ¤   PGPFreeData( bufPtr );
527430 ¤   if( IsntNull( keySet ) )
a93b1a ¤   ¤   PGPFreeKeySet( keySet );
b85ea8 ¤   return err;
c31862 }¤
89af5a
4caf5a
0e95d7 /*·
ac6c90 ·* Use when we first open output in passthrough mode. ·We drain the
475be7 ·* contents of the passthrough fifo (which holds header data and such
53c425 ·* which we read before we got the begin annotation).
91495d ·*/
4e2978 static void
729290 sDrainPassThroughFifo( PGPDecodeJob *s )
18bb36 {
dbcd35 ¤   PGPByte const *¤ptr;
acb7ff ¤   PGPSize¤¤   ¤   length;
a3fb19 ¤   PGPError¤   ¤   err;
40af5a
4d78a8 ¤   pgpAssert( IsntNull( s->prevStarOutput ) );
7fe15f ¤   pgpAssert( IsntNull( s->passThroughFifo ) );
07af5a
be70fd ¤   ptr = pgpFifoPeek(&pgpByteFifoDesc, s->passThroughFifo, &length);
4d70df ¤   while (length != 0) {
42b5c7 ¤   ¤   s->prevStarOutput->write( s->prevStarOutput, ptr, length, &err );
717413 ¤   ¤   pgpFifoSeek(&pgpByteFifoDesc, s->passThroughFifo, length);
0a664b ¤   ¤   ptr = pgpFifoPeek(&pgpByteFifoDesc, s->passThroughFifo, &length);
109371 ¤   }
50efe6 }
1eaf5a
ccaf5a
d338e5 /*
3c7b0b ·* Output state diversion. ·We sometimes want to suspend output to the
1e0bb1 ·* current pipeline temporarily while we deal with a key or non-pgp data.
4f62f8 ·* We save the current state in the "prev" class of variables, and later
51bd6a ·* restore them.
16495d ·*/
60af5a
582978 static void
361e31 sRestoreOutputState( PGPDecodeJob *s, PGPPipeline **output )
86bb36 {
7bd8af ¤   /*
d7e981 ¤   ·* In order for our cleanup in pgpDecodeInternal to work, the output
4ceabc ¤   ·* tail pointer from the module which calls us must always be the same.
fe0811 ¤   ·* The following assertion helps test for that. ·(During pgpDecodeInternal
d9b5b5 ¤   ·* we have no access to the output tail pointer, so we will assume that
fb9d1d ¤   ·* the prevOutput value matches what is needed.)
92a4e3 ¤   ·*/
0f1b17 ¤   pgpAssert( s->prevOutput == output );
1cfb84 ¤   *output = s->prevStarOutput;
2f2c7e ¤   s->outPipe = s->prevOutPipe;
9e8de7 ¤   s->pfout = s->prevPFout;
--edc4 000d4769b44401001de Page 10 of pgpDecode.c
86d395 ¤   s->prevStarOutput = NULL;
44fd22 ¤   s->prevOutPipe = NULL;
f23b9b ¤   s->prevPFout = NULL;
fcb37f ¤   s->fPrevOutput = FALSE;
fdefe6 }
85af5a
102978 static void
42539d sSaveOutputState( PGPDecodeJob *s, PGPPipeline **output )
52bb36 {
9d1b17 ¤   pgpAssert( s->prevOutput == output );
912113 ¤   s->prevStarOutput = *output;
d6870d ¤   s->prevOutPipe = s->outPipe;
a3a7c7 ¤   s->prevPFout = s->pfout;
7d04e6 ¤   s->fPrevOutput = TRUE;
2273a1 ¤   s->outPipe = NULL;
664136 ¤   s->pfout = NULL;
db1f32 ¤   *output = NULL;
b9efe6 }
c1af5a
f4af5a
05af5a
57af5a
33af5a
fdecf5 /***************** Callback functions from Aurora library *******************/
60af5a
b4169d static PGPError pgpDecodeDoCommit(void *arg, PGPInt32 scope);
5daf5a
4daf5a
4c38e5 /*
06ffd8 ·* The low-level Aurora library calls our analyze and commit functions
5896ef ·* for each recursive level of handling of a given message segment.
041044 ·* We only want to give one of these to the user. ·Accordingly we have
e0c7a9 ·* three states as far as getting segment-type information:
fe775e ·*
3a5f64 ·*¤ - Waiting for segment type info
f3063b ·*¤ - Got segment type info, waiting to give to user
a73344 ·* ¤- Gave segment info to user, waiting for end of segment
db775e ·*
f75c3d ·* We give segment info to the user from the commit call, because that
6f338d ·* is our opportunity to skip a section, which the user is allowed to do
277458 ·* on the analyze call.
8f495d ·*/
5e66dd ¤   static PGPError
e04a33 pgpDecodeHandleAnnotation(
83e865 ¤   void¤   ¤   ¤   ¤   *arg,
76f3ad ¤   PGPPipeline¤¤   ¤   *origin,
d9acf3 ¤   PGPInt32¤   ¤   ¤   ·type,
48f6af ¤   PGPByte const¤  ¤   *string,
4d4564 ¤   PGPSize¤¤   ¤   ¤   ·size
e627e6 ¤   )
1dbb36 {
ecfd08 ¤   PGPDecodeJob¤   ¤   *s;¤¤   ¤   ¤   /* Parameters for callbacks */
8de356 ¤   PGPUInt32¤  ¤   ¤   ·passThroughNonPGP;
5305a0 ¤   PGPError¤   ¤   ¤   ·err = kPGPError_NoErr;
98af5a
987c16 ¤   s = (PGPDecodeJob *) arg;
a840e1 ¤   (void) origin;
60bd24 ¤   (void) string;
25e1b0 ¤   (void) size;
7eaf5a
af4b62 ¤   /* Keep track of our nesting status */
528229 ¤   PGP_SCOPE_DEPTH_UPDATE(s->scopeLevel, type);
5faf5a
9bb373 ¤   /* Handle passthrough data */
706ce1 ¤   if (type == PGPANN_CLEARDATA) {
dbe345 ¤   ¤   /* Passthrough data gets buffered or handed to suspended output */
5e6396 ¤   ¤   s->passThrough = TRUE;
e302b5 ¤   ¤   if( IsntNull( s->prevStarOutput ) ) {
ee7846 ¤   ¤   ¤   s->prevStarOutput->write( s->prevStarOutput,
7bb7b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··string, size, &err );
ed45a6 ¤   ¤   } else {
d450ca ¤   ¤   ¤   /* We get a few lines of header before the data starts,
--7e1d 0005307d656401001de Page 11 of pgpDecode.c
6c9a8b ¤   ¤   ¤   ·* so we buffer that here and will drain it in
279328 ¤   ¤   ¤   ·* NewOutput.
308753 ¤   ¤   ¤   ·*/
e5dd77 ¤   ¤   ¤   pgpAssert( IsntNull( s->passThroughFifo ) );
8b48c7 ¤   ¤   ¤   pgpFifoWrite(&pgpByteFifoDesc, s->passThroughFifo,
561665 ¤   ¤   ¤   ¤   ¤   ¤   ·string, size);
490fe4 ¤   ¤   }
09367a ¤   } else if( type == PGPANN_LITERAL_TYPE ) {
8fcdb1 ¤   ¤   /* Remember type in case we want to recurse into it */
3c4314 ¤   ¤   pgpAssert (size == 1);
d40143 ¤   ¤   s->literalType = *(PGPByte *)string;
4af512 ¤   } else if( s->analyzeState == kAnalyzeWaiting ) {
a04a94 ¤   ¤   /* If looking for the start of a segment, figure out the type */
996cfd ¤   ¤   switch (type) {
c90891 ¤   ¤   case PGPANN_ARMOR_BEGIN:
196115 ¤   ¤   ¤   /* Just get the section offset for later callback */
083513 ¤   ¤   ¤   if( size == sizeof(s->sectOffset) )
71d318 ¤   ¤   ¤   ¤   s->sectOffset = *(PGPSize *)string;
08cdcb ¤   ¤   ¤   break;
3bf535 ¤   ¤   case PGPANN_PGPKEY_BEGIN:
2838a8 ¤   ¤   ¤   s->analyzeType = kPGPAnalyze_Key;
ef342f ¤   ¤   ¤   s->analyzeState = kAnalyzeGotType;
7a63c1 ¤   ¤   ¤   s->scopeSegment = s->scopeLevel;
18cdcb ¤   ¤   ¤   break;
5ec724 ¤   ¤   case PGPANN_CIPHER_BEGIN:
de81af ¤   ¤   ¤   s->analyzeType = kPGPAnalyze_Encrypted;
1d342f ¤   ¤   ¤   s->analyzeState = kAnalyzeGotType;
0b63c1 ¤   ¤   ¤   s->scopeSegment = s->scopeLevel;
4fcdcb ¤   ¤   ¤   break;
b8099c ¤   ¤   case PGPANN_COMPRESSED_BEGIN:
622f32 ¤   ¤   /* Signed may be a detached or a regular sig, need another anno */
40e2d8 ¤   ¤   /*¤ ¤   case PGPANN_SIGNED_BEGIN: */
1e6dd3 ¤   ¤   case PGPANN_SIGNED_SIG:
6b3b41 ¤   ¤   case PGPANN_SIGNED_SIG2:
05ee6c ¤   ¤   ¤   s->analyzeType = kPGPAnalyze_Signed;
fd342f ¤   ¤   ¤   s->analyzeState = kAnalyzeGotType;
7063c1 ¤   ¤   ¤   s->scopeSegment = s->scopeLevel;
05cdcb ¤   ¤   ¤   break;
fef377 ¤   ¤   case PGPANN_SIGNED_SEP:
13136e ¤   ¤   ¤   s->analyzeType = kPGPAnalyze_DetachedSignature;
f8342f ¤   ¤   ¤   s->analyzeState = kAnalyzeGotType;
0c63c1 ¤   ¤   ¤   s->scopeSegment = s->scopeLevel;
20cdcb ¤   ¤   ¤   break;
707cf4 ¤   ¤   case PGPANN_CLEARSIG_BEGIN:
bd7aad ¤   ¤   ¤   /*
6a460c ¤   ¤   ¤   ·* Clearsig doesn't go through binary parser, so we do some
6ad60b ¤   ¤   ¤   ·* shortcuts here. ·Call commit directly. ·We can't currently
6feb08 ¤   ¤   ¤   ·* skip clearsigned messages though. ·Note commit changes
276143 ¤   ¤   ¤   ·* analyzeState.
698753 ¤   ¤   ¤   ·*/
4aee6c ¤   ¤   ¤   s->analyzeType = kPGPAnalyze_Signed;
a6342f ¤   ¤   ¤   s->analyzeState = kAnalyzeGotType;
f063c1 ¤   ¤   ¤   s->scopeSegment = s->scopeLevel;
e73513 ¤   ¤   ¤   if( size == sizeof(s->sectOffset) )
9cd318 ¤   ¤   ¤   ¤   s->sectOffset = *(PGPSize *)string;
68af42 ¤   ¤   ¤   err = pgpDecodeDoCommit(arg, type);
4f4f55 ¤   ¤   ¤   if (err == PGPANN_PARSER_EATIT || err == PGPANN_PARSER_RECURSE)
d3bd37 ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
55cdcb ¤   ¤   ¤   break;
56ae58 ¤   ¤   case PGPANN_NONPGP_BEGIN:
507aad ¤   ¤   ¤   /*
ec409d ¤   ¤   ¤   ·* Non-PGP data is handled differently. ·Call commit directly.
7a695a ¤   ¤   ¤   ·* (Skip not supported though.) ·Note commit changes
fb6143 ¤   ¤   ¤   ·* analyzeState.
ee8753 ¤   ¤   ¤   ·*/
9407dc ¤   ¤   ¤   if( IsPGPError( pgpFindOptionArgs( s->optionList,
29bb9d ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PassThroughIfUnrecognized, FALSE,
61798d ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%d", &passThroughNonPGP ) ) )
131b7c ¤   ¤   ¤   ¤   goto error;
17721d ¤   ¤   ¤   if( passThroughNonPGP ) {
c29eb4 ¤   ¤   ¤   ¤   s->analyzeType = kPGPAnalyze_Unknown;
53ec9d ¤   ¤   ¤   ¤   s->analyzeState = kAnalyzeGotType;
--3329 00094c8e442401001de Page 12 of pgpDecode.c
66315c ¤   ¤   ¤   ¤   s->scopeSegment = s->scopeLevel;
ffa352 ¤   ¤   ¤   ¤   if( size == sizeof(s->sectOffset) )
6b86b4 ¤   ¤   ¤   ¤   ¤   s->sectOffset = *(PGPSize *)string;
c13903 ¤   ¤   ¤   ¤   err = pgpDecodeDoCommit(arg, type);
711a05 ¤   ¤   ¤   ¤   if (err == PGPANN_PARSER_EATIT || err == PGPANN_PARSER_RECURSE)
5db37b ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
f4a3a6 ¤   ¤   ¤   }
33cdcb ¤   ¤   ¤   break;
cd0fe4 ¤   ¤   }
066f24 ¤   } else if( s->analyzeState == kAnalyzeSegmentEndWait ) {
cb1b17 ¤   ¤   /*
9c2ada ¤   ¤   ·* Handle end of segment.
0087a0 ¤   ¤   ·* Special treatment for clearsig: it goes CLEARSIG_BEGIN,
aa3ea7 ¤   ¤   ·* CLEARSIG_END, ARMOR_BEGIN, ARMOR_END. ·We skip the CLEARSIG_END
4e221e ¤   ¤   ·* so we terminate the scope at the ARMOR_END.
029de3 ¤   ¤   ·*/
bc0c11 ¤   ¤   if( type == PGPANN_PGPKEY_END ) {
b80857 ¤   ¤   ¤   /* On close of PGPkey segment, deal with key data */
a6b479 ¤   ¤   ¤   /* May be nested within an encrypted segment so check here */
c30c00 ¤   ¤   ¤   if( IsPGPError( err = pgpCloseKeyOutput( s ) ) )
af1b7c ¤   ¤   ¤   ¤   goto error;
9a46d9 ¤   ¤   ¤   pgpAssert( s->fPrevOutput );
8b9433 ¤   ¤   ¤   sRestoreOutputState( s, s->prevOutput );
060fe4 ¤   ¤   }
0ac8ed ¤   ¤   if( s->scopeLevel < s->scopeSegment && type != PGPANN_CLEARSIG_END) {
19672d ¤   ¤   ¤   /* Close any open output so client can see his data */
c173a4 ¤   ¤   ¤   if( !s->fixedOutput && IsntNull( s->prevOutput ) ) {
7a0c01 ¤   ¤   ¤   ¤   /* If finished with a segment, close it */
cb044c ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpCloseOutput(s, ·s->prevOutput )))
02b622 ¤   ¤   ¤   ¤   ¤   goto error;
06a3a6 ¤   ¤   ¤   }
0a7e39 ¤   ¤   ¤   s->passThrough = FALSE;¤¤   /* End of segment */
16bd01 ¤   ¤   ¤   err = pgpEventEndLex( s->context, &s->newOptionList,
54e97f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, s->sectionNumber++ );
8b6b76 ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
68894b ¤   ¤   ¤   s->analyzeState = kAnalyzeWaiting;
8759df ¤   ¤   ¤   if( IsPGPError( err ) )
fe1b7c ¤   ¤   ¤   ¤   goto error;
83076d ¤   ¤   ¤   /* Handle one-section mode */
d0fecb ¤   ¤   ¤   if( s->sectionNumber == 1 ) {
e2a3db ¤   ¤   ¤   ¤   PGPUInt32 fOnlyOne;
8ee467 ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( s->optionList,
777123 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DecodeOnlyOne, FALSE,
079047 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%d", &fOnlyOne ) ) )
0eb622 ¤   ¤   ¤   ¤   ¤   goto error;
c0c482 ¤   ¤   ¤   ¤   if( fOnlyOne ) {
99b6e4 ¤   ¤   ¤   ¤   ¤   err = kPGPError_Interrupted;
872613 ¤   ¤   ¤   ¤   }
dba3a6 ¤   ¤   ¤   }
da0fe4 ¤   ¤   }
659371 ¤   }
e7c26e ¤   /* Detect bad parsing situations */
0f2f45 ¤   if (type == PGPANN_ESK_TOO_BIG
56cd60 ¤   ¤   || type == PGPANN_SIGNATURE_TOO_BIG
048bae ¤   ¤   || type == PGPANN_PACKET_SHORT
62415e ¤   ¤   || type == PGPANN_PACKET_TRUNCATED
4905b9 ¤   ¤   || type == PGPANN_SCOPE_TRUNCATED) {
f07a3d ¤   ¤   err = kPGPError_BadPacket;
9397ed ¤   ¤   goto error;
3de2d4 ¤   } else if (type == PGPANN_ARMOR_TOOLONG
788cbb ¤   ¤   || type == PGPANN_ARMOR_BADLINE
2ac642 ¤   ¤   || type == PGPANN_ARMOR_NOCRC
b10f1f ¤   ¤   || type == PGPANN_ARMOR_CRCCANT
8e276e ¤   ¤   || type == PGPANN_ARMOR_CRCBAD) {
79c940 ¤   ¤   err = kPGPError_AsciiParseIncomplete;
1597ed ¤   ¤   goto error;
729371 ¤   }
4091b1 ¤   /* Fall through */
1560ff error:
395ea8 ¤   return err;
acefe6 }
94af5a
--7835 000233e4442401001de Page 13 of pgpDecode.c
e0af5a
d338e5 /*
26aef0 ·* Display a message as appropriate.
b3aa25 ·* Nothing is appropriate for us, as we have no UI. ·Assert an error
6ef2d3 ·* if it happens. ·(Perhaps better simply to ignore it.)
a9495d ·*/
cd66dd ¤   static PGPError
b11d86 pgpDecodeShowMessage(
7ce865 ¤   void¤   ¤   ¤   ¤   *arg,
84acf3 ¤   PGPInt32¤   ¤   ¤   ·type,
955463 ¤   PGPInt32¤   ¤   ¤   ·msg,
4ed27c ¤   PGPUInt32¤  ¤   ¤   ·numargs,
d9c9f6 ¤   ...
4f27e6 ¤   )
77bb36 {
24fd08 ¤   PGPDecodeJob¤   ¤   *s;¤¤   ¤   ¤   /* Parameters for callbacks */
48af5a
007c16 ¤   s = (PGPDecodeJob *) arg;
1faf5a
840e94 ¤   (void)type;
c1bd13 ¤   (void)msg;
15cb25 ¤   (void)numargs;
c3151e ¤   return kPGPError_NoErr;
f3efe6 }
e6af5a
aaaf5a
6238e5 /*
48a93e ·* Decide whether to work on a section or to skip it.
91495d ·*/
9266dd ¤   static PGPError
d9d2a4 pgpDecodeDoCommit(
c0e865 ¤   void¤   ¤   ¤   ¤   *arg,
e814c4 ¤   PGPInt32¤   ¤   ¤   ·scope
6527e6 ¤   )
42bb36 {
6cfd08 ¤   PGPDecodeJob¤   ¤   *s;¤¤   ¤   ¤   /* Parameters for callbacks */
9f75f8 ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error code */
70af5a
f57c16 ¤   s = (PGPDecodeJob *) arg;
d5af5a
8ee34a ¤   if( s->analyzeState == kAnalyzeGotType ) {
1b011d ¤   ¤   /* Tell user of results, let him say if we should continue */
42b62b ¤   ¤   s->analyzeState = kAnalyzeSegmentEndWait;
baaf5a
04104c ¤   ¤   err = pgpEventBeginLex( s->context, &s->newOptionList,
38ee0c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->func, s->userValue, s->sectionNumber,
1f57a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->sectOffset );
8c7a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
41d223 ¤   ¤   if( IsPGPError( err ) )
0cb32f ¤   ¤   ¤   return err;
a0af5a
988e9e ¤   ¤   /* Give user analysis callback, let him tell us to skip section */
1ad75d ¤   ¤   err = pgpEventAnalyze( s->context, &s->newOptionList,
4eb350 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->func, s->userValue, s->analyzeType );
c57a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
d04cf6 ¤   ¤   if( err == kPGPError_SkipSection ) {
3246bb ¤   ¤   ¤   return PGPANN_PARSER_EATIT;
850fe4 ¤   ¤   }
26d223 ¤   ¤   if( IsPGPError( err ) )
6cb32f ¤   ¤   ¤   return err;
eb9371 ¤   }
c5c079 ¤   /* Don't recurse into literal recursion packets unless set up for it */
1d4a5b ¤   /* Must be in recurse and passthrough mode to do it, else don't recurse */
651670 ¤   if (scope == PGPANN_LITERAL_BEGIN && s->literalType == PGP_LITERAL_RECURSE
f8e1b5 ¤   ¤   && (s->passThroughFifo == NULL || !s->recurse))
b252ee ¤   ¤   return PGPANN_PARSER_PROCESS;
7edd11 ¤   return PGPANN_PARSER_RECURSE;
3cefe6 }
dbaf5a
650fe7 /* Set up the output pipeline as appropriate */
2baf5a
2366dd ¤   static PGPError
--b5ee 00022d34d4b401001de Page 14 of pgpDecode.c
554a46 pgpDecodeSetupNewOutput(
bff53f ¤   void¤   ¤   ¤   ¤   ·*arg,
673a54 ¤   PGPPipeline¤¤   ¤   **output,
67a751 ¤   PGPInt32¤   ¤   ¤   ··type,
46e11c ¤   char const¤ ¤   ¤   ·*suggested_name
e027e6 ¤   )
b0bb36 {
6cc6dc ¤   PGPDecodeJob¤   ¤   ·*s;¤   ¤   ¤   /* Parameters for callbacks */
e0f4a0 ¤   PGPError¤   ¤   ¤   ··err;¤ ¤   ¤   /* Error code */
e065ec ¤   PGPUInt32¤  ¤   ¤   ··outputCount;¤ /* How many output options we got */
7a28be ¤   PGPFileOpenFlags¤   ··fileFlags;¤   /* Flags for opening output file */
be56a1 ¤   PGPFileType¤¤   ¤   ··fileType;¤¤   /* Type field for output file */
d7cdcf ¤   PGPByte¤¤   ¤   ¤   ·*charMap;¤ ¤   /* Charmap for output text filter */
8dece2 ¤   PGPUInt32¤  ¤   ¤   ··passThroughNonPGP;
35327d ¤   PGPUInt32¤  ¤   ¤   ·dummyLocalEncodeFlags;
9f47ef ¤   PGPLineEndType¤ ¤   ·dummyLineEnd;
7318f8 ¤   PGPContextRef¤  ¤   cdkContext¤ = NULL;
20dc05 ¤   PGPMemoryMgrRef¤¤   memoryMgr¤  = NULL;
1b5b54 ¤   PGPBoolean¤ ¤   ¤   fFYEO = FALSE;
b767c5 ¤
157c16 ¤   s = (PGPDecodeJob *) arg;
7f6493 ¤   err = kPGPError_NoErr;
b11b8d ¤   cdkContext¤ = s->context;
c81c1f ¤   memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
c9af5a
62d8af ¤   /*
fb2853 ¤   ·* We need to adjust the pipeline at other stages, so we will save
0b89b7 ¤   ·* the output pointer. ·For those to work, it must always be the
ce935d ¤   ·* same whenever we are called. ·(The output pointer is the _address_
b4a2e0 ¤   ·* of a pointer to the output portion of the pipeline, not the pointer
afeebc ¤   ·* to the pipeline itself.)
fba4e3 ¤   ·*/
7bbb9b ¤   if( IsNull( s->prevOutput ) )
04d210 ¤   ¤   s->prevOutput = output;
451b17 ¤   pgpAssert( s->prevOutput == output );
fbaf5a
204109 ¤   /* If have a prevoutput pipeline saved, switch back to that first. */
e4ded6 ¤   if( s->fPrevOutput ) {
ea9e51 ¤   ¤   if( IsPGPError( err = pgpCloseOutput( s, output ) ) )
c4ed19 ¤   ¤   ¤   goto error;
761b48 ¤   ¤   sRestoreOutputState( s, output );
f99371 ¤   }
6daf5a
1ef093 ¤   if( type == PGPANN_PGPKEY_BEGIN && !s->passThrough ) {
871b17 ¤   ¤   /*
1adfd9 ¤   ¤   ·* Here we are adding a key. ·We must copy the data somewhere,
3ceed8 ¤   ¤   ·* and then convert it to a key set and then add it.
cf8830 ¤   ¤   ·* We handle keys in passthrough mode below.
d49de3 ¤   ¤   ·*/
0b4412 ¤   ¤   sSaveOutputState( s, output );
581ff0 ¤   ¤   if ( IsNull( s->outKey = pgpVariableMemModCreate( cdkContext,
4c3f96 ¤   ¤   ¤   ¤   ¤   output, ~(PGPSize)0 ) ) ) {
51b5bd ¤   ¤   ¤   /* Guess at the cause */
6eb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
690fe4 ¤   ¤   }
48cf4e ¤   ¤   /* Return with success or failure */
4997ed ¤   ¤   goto error;
8b9371 ¤   }
6baf5a
51bd0d ¤   if( type == PGPANN_NONPGP_BEGIN ) {
5ce5dc ¤   ¤   if( IsPGPError( pgpFindOptionArgs( s->optionList,
602647 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PassThroughIfUnrecognized, FALSE,
f67eb6 ¤   ¤   ¤   ¤   ¤   ¤   "%d", &passThroughNonPGP ) ) )
24ed19 ¤   ¤   ¤   goto error;
bf061d ¤   ¤   if( !passThroughNonPGP ) {
677aad ¤   ¤   ¤   /*
7bc1e0 ¤   ¤   ¤   ·* Trash non-PGP data if not requesting passthrough.
544ae3 ¤   ¤   ¤   ·* We will use the prevOutput mechanism to go back to what our
e47b56 ¤   ¤   ¤   ·* output was before when we are through with it.
eb8753 ¤   ¤   ¤   ·*/
324a5e ¤   ¤   ¤   sSaveOutputState( s, output );
225be7 ¤   ¤   ¤   if ( IsNull( pgpDevNullCreate ( cdkContext, output ) ) ) {
--e09a 000fcf68c01401001de Page 15 of pgpDecode.c
afb050 ¤   ¤   ¤   ¤   /* Guess at the cause */
c2bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
4da3a6 ¤   ¤   ¤   }
339dd3 ¤   ¤   ¤   /* Return with success or failure */
3bed19 ¤   ¤   ¤   goto error;
860fe4 ¤   ¤   }
669371 ¤   }
75af5a
726826 ¤   /* If have fixed output, just leave it open */
ba0672 ¤   if( s->fixedOutput && IsntNull( *output ) ) {
6a1c69 ¤   ¤   /* Leave things open */
710376 ¤   ¤   goto checkpassthrough;
589371 ¤   }
6aaf5a
e14920 ¤   /* Close previous output if any */
807c51 ¤   if( IsPGPError( err = pgpCloseOutput( s, output ) ) )
8697ed ¤   ¤   goto error;
fd1b52 ¤   ¤
4fdf14 ¤   if( !s->fixedOutput ) {
d93487 ¤   ¤   /* Get output for next part from user */
91ff22 ¤   ¤   pgpAssert( IsntNull( s->func ) );
e89970 ¤   ¤   fFYEO = IsntNull( suggested_name ) &&
a432c0 ¤   ¤   ¤   ¤   0==strcmp( suggested_name, "_CONSOLE" );
80475f ¤   ¤   /* Turn empty names and magic ones into a null suggested_name */
a8fe5b ¤   ¤   if( IsntNull( suggested_name ) &&
ca04b3 ¤   ¤   ¤   ( fFYEO || *suggested_name == '\0' ) )
5370aa ¤   ¤   ¤   suggested_name = NULL;
2107d3 ¤   ¤   if( IsPGPError (err = pgpEventOutput( s->context, &s->newOptionList,
7950f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue,
6e22db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··type, suggested_name, fFYEO ) ) )
f2ed19 ¤   ¤   ¤   goto error;
c12da6 ¤   ¤   /* Parse new output information if any */
2d29e3 ¤   ¤   if( IsntNull( s->outFileRef ) ) {
81c306 ¤   ¤   ¤   PFLFreeFileSpec( s->outFileRef );
ed5e05 ¤   ¤   ¤   s->outFileRef = NULL;
a30fe4 ¤   ¤   }
fa9b49 ¤   ¤   err = pgpSetupOutput( s->newOptionList,
068bb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->env, &s->outFileRef,
6bc2a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outBufPtr, &s->outBufPtrPtr,
f3dd47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outBufMaxLength, &s->outBufUsedLength,
be47f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outDiscard, &dummyLocalEncodeFlags,
ea2665 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &dummyLineEnd, &s->fAppendOutput );
b17a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
4ad223 ¤   ¤   if( IsPGPError( err ) )
6aed19 ¤   ¤   ¤   goto error;
6a78be ¤   ¤   /* Make sure he gave us exactly one output option */
cececb ¤   ¤   outputCount = !!IsntNull( s->outFileRef ) +
aaf5c0 ¤   ¤   ¤   ¤   ¤   ··!!IsntNull( s->outBufPtr ) +
72126c ¤   ¤   ¤   ¤   ¤   ··!!IsntNull( s->outBufPtrPtr ) +
c87134 ¤   ¤   ¤   ¤   ¤   ··!!s->outDiscard;
662b72 ¤   ¤   if( outputCount == 0 ) {
d5cb66 ¤   ¤   ¤   pgpDebugMsg( "Error: no output options" );
175820 ¤   ¤   ¤   err = kPGPError_BadParams;
16ed19 ¤   ¤   ¤   goto error;
0119ac ¤   ¤   } else if( outputCount > 1 ) {
a7bc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
ea5820 ¤   ¤   ¤   err = kPGPError_BadParams;
a1ed19 ¤   ¤   ¤   goto error;
7a0fe4 ¤   ¤   }
339371 ¤   }
18af5a
cad3b8 ¤   /* No support for other types than text or binary now */
9ebd0d ¤   if( type == PGPANN_NONPGP_BEGIN ) {
6a44ed ¤   ¤   /* Treat non-PGP data similarly to text input data */
87f3f6 ¤   ¤   type = PGP_LITERAL_TEXT;
794089 ¤   } else if( type != PGP_LITERAL_TEXT ) {
702391 ¤   ¤   type = PGP_LITERAL_BINARY;
4c9371 ¤   }
36af5a
9c9843 ¤   if( type==PGP_LITERAL_TEXT ) {
7be5cf ¤   ¤   /* Convert to local line endings if appropriate */
fce866 ¤   ¤   charMap = (PGPByte *)pgpenvGetPointer( s->env, PGPENV_CHARMAPTOLATIN1,
--5e10 000d7526a79401001de Page 16 of pgpDecode.c
95f63b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL );
c5c0db ¤   ¤   output = pgpTextFiltCreate( s->context,
0aa2dc ¤   ¤   ¤   output, charMap, 0, s->lineEnd );
eb9371 ¤   }
35af5a
4aca08 ¤   /* Now open output modules as needed */
bf150d ¤   if( IsntNull( s->outFileRef ) ) {
e6657b ¤   ¤   /* Open output file */
87259f ¤   ¤   pgpAssert((s->localEncodeFlags & ~(kPGPFileOpenMaybeLocalEncode
60d79c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··| kPGPFileOpenNoMacBinCRCOkay)) == 0);
1eaf5a
23baac ¤   ¤   /* Create output file pipeline */
162c3d ¤   ¤   fileFlags = s->fAppendOutput ? kPGPFileOpenStdAppendFlags :
eec2e2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileOpenStdWriteFlags ;
975cd6 ¤   ¤   fileFlags |= ·s->localEncodeFlags;
a13656 ¤   #if PGP_MACINTOSH
99b8e2 ¤   ¤   /* always force decoding of MacBinary */
cebf5e ¤   ¤   fileFlags¤  |= kPGPFileOpenForceLocalEncode;
84b7ec ¤   #endif
e79f34 ¤   ¤   fileType = ·type == PGP_LITERAL_TEXT ?
c0ad23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPFileTypeDecryptedText :
b774a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPFileTypeDecryptedBin;
bd8c05 ¤   ¤   s->pfout = pgpFileRefOpen( cdkContext,
5942ad ¤   ¤   ¤   ¤   ¤   ¤   (PFLConstFileSpecRef)s->outFileRef,
b3c799 ¤   ¤   ¤   ¤   ¤   ¤   fileFlags, fileType, &err );
180e8e ¤   ¤   if( IsNull( s->pfout ) )
8ded19 ¤   ¤   ¤   goto error;
151b52 ¤   ¤
dc86a6 ¤   ¤   /* Set up output pipeline */
9bf0c6 ¤   ¤   if( IsNull( pgpFileWriteCreate( cdkContext,
c0a116 ¤   ¤   ¤   ¤   output, s->pfout, 0 ) ) ) {
96b5bd ¤   ¤   ¤   /* Guess at the cause */
efb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
bb31f2 ¤   ¤   ¤   pgpFileClose( s->pfout );
04ed19 ¤   ¤   ¤   goto error;
360fe4 ¤   ¤   }
d6f845 ¤   } else if( IsntNull( s->outBufPtr ) ) {
32bc67 ¤   ¤   /* Open fixed-size memory buffer */
f86f26 ¤   ¤   if ( IsNull( s->outPipe = pgpMemModCreate( cdkContext, output,
8315be ¤   ¤   ¤   ¤   ¤   ¤   (char *)s->outBufPtr, s->outBufMaxLength ) ) ) {
ffb5bd ¤   ¤   ¤   /* Guess at the cause */
1bb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
b2ed19 ¤   ¤   ¤   goto error;
f00fe4 ¤   ¤   }
53f204 ¤   ¤   if( s->fAppendOutput ) {
dc41f2 ¤   ¤   ¤   /* Skip past existing buffer contents */
1fd769 ¤   ¤   ¤   if( IsPGPError( err = (s->outPipe)->annotate( s->outPipe, NULL,
d4a2ed ¤   ¤   ¤   ¤   ¤   ·PGPANN_MEM_PREPEND,
1e3df0 ¤   ¤   ¤   ¤   ¤   ·(unsigned char *)s->outBufPtr, *s->outBufUsedLength ) ) )
7c1b7c ¤   ¤   ¤   ¤   goto error;
db0fe4 ¤   ¤   }
87c70b ¤   } else if( IsntNull( s->outBufPtrPtr ) ) {
194bbf ¤   ¤   /* Open variable-size memory buffer */
a45646 ¤   ¤   /* Use secure mode if a FYEO buffer */
7a1fe3 ¤   ¤   s->outPipe = fFYEO¤ ? pgpSecureVariableMemModCreate( cdkContext,
a2ff50 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   output, s->outBufMaxLength )
6a4671 ¤   ¤   ¤   ¤   ¤   ¤   ¤   : pgpVariableMemModCreate( cdkContext,
be525a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   output, s->outBufMaxLength );
e01b52 ¤   ¤
03e0fa ¤   ¤   if ( IsNull( s->outPipe ) ) {
98b5bd ¤   ¤   ¤   /* Guess at the cause */
60b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
70ed19 ¤   ¤   ¤   goto error;
a90fe4 ¤   ¤   }
8a1142 ¤   ¤   if( s->fAppendOutput && *s->outBufUsedLength != 0 ) {
150581 ¤   ¤   ¤   /* Prepend existing buffer contents */
16d769 ¤   ¤   ¤   if( IsPGPError( err = (s->outPipe)->annotate( s->outPipe, NULL,
5af129 ¤   ¤   ¤   ¤   ¤   ·PGPANN_MEM_PREPEND, (unsigned char *)*s->outBufPtrPtr,
566e74 ¤   ¤   ¤   ¤   ¤   ·*s->outBufUsedLength ) ) )
1b1b7c ¤   ¤   ¤   ¤   goto error;
d5a798 ¤   ¤   ¤   /* Free buffer now that we have captured it */
d7f857 ¤   ¤   ¤   PGPFreeData( *s->outBufPtrPtr );
--77f4 0007826c73b401001de Page 17 of pgpDecode.c
e41b01 ¤   ¤   ¤   *s->outBufPtrPtr = NULL;
3d0fe4 ¤   ¤   }
823a4a ¤   } else if( s->outDiscard ) {
19d0b3 ¤   ¤   /* Pass to the bit bucket */
cb486b ¤   ¤   if ( IsNull( pgpDevNullCreate ( cdkContext, output ) ) ) {
2bb5bd ¤   ¤   ¤   /* Guess at the cause */
26b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
67ed19 ¤   ¤   ¤   goto error;
b30fe4 ¤   ¤   }
caf037 ¤   } else {
9b26be ¤   ¤   /* Checked for this case above */
b424da ¤   ¤   pgpAssert( 0 );
1e9371 ¤   }
55af5a
808cfb checkpassthrough:
39183f ¤   /* Passthrough mode means we want to use data from annotations for
dcfc80 ¤   ·* output rather than the data coming down the pipe. ·Save the output
9b56de ¤   ·* we've set up, and then convert output pipe to /dev/null for clearsign
f3c0af ¤   ·* or to a memmod buffer for keys.
7ba4e3 ¤   ·*/
114252 ¤   if( s->passThrough ) {
941b17 ¤   ¤   /*
b8cb15 ¤   ¤   ·* Handle passthrough for clearsign and keys.
d9e6ad ¤   ¤   ·* May have changed output temporarily for textfilt setup, so restore
e43bad ¤   ¤   ·* from prevOutput
2b9de3 ¤   ¤   ·*/
4ce470 ¤   ¤   output = s->prevOutput;
f54412 ¤   ¤   sSaveOutputState( s, output );
11c8db ¤   ¤   sDrainPassThroughFifo( s );
96cb32 ¤   ¤   if( s->analyzeType == kPGPAnalyze_Key ) {
f7d00b ¤   ¤   ¤   if ( IsNull( s->outKey = pgpVariableMemModCreate( s->context,
e9a9d7 ¤   ¤   ¤   ¤   ¤   ¤   output, ~(PGPSize)0 ) ) ) {
67b050 ¤   ¤   ¤   ¤   /* Guess at the cause */
18bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
dfa3a6 ¤   ¤   ¤   }
cb45a6 ¤   ¤   } else {
355be7 ¤   ¤   ¤   if ( IsNull( pgpDevNullCreate ( cdkContext, output ) ) ) {
68b050 ¤   ¤   ¤   ¤   /* Guess at the cause */
babfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
4ea3a6 ¤   ¤   ¤   }
0d0fe4 ¤   ¤   }
4a9371 ¤   }
10af5a
94151e ¤   return kPGPError_NoErr;
3f60ff error:
795ea8 ¤   return err;
1aefe6 }
afaf5a
74af5a
bd38e5 /*
d3c1ef ·* Look for input file when we find a detached signature.
ff495d ·*/
0966dd ¤   static PGPError
a31e15 pgpDecodeFindAltInput(
07e865 ¤   void¤   ¤   ¤   ¤   *arg,
5e451e ¤   PGPPipeline¤¤   ¤   *head
0027e6 ¤   )
e6bb36 {
c3fd08 ¤   PGPDecodeJob¤   ¤   *s;¤¤   ¤   ¤   /* Parameters for callbacks */
ddeb56 ¤   PFLConstFileSpecRef¤¤   ·detFileRef;¤   /* Input fileref */
c98aea ¤   PGPFileRead¤¤   ¤   *pfrdet;¤   ¤   /* Input PGPFile pointer */
e2a07f ¤   PGPByte¤¤   ¤   ¤   *detBufPtr;¤¤   /* Input buffer pointer */
1a870c ¤   PGPSize¤¤   ¤   ¤   ·detBufLength;¤ /* Input buffer length */
a5a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
8d1711 ¤   PGPOptionListRef¤   ·setupOp;¤  ¤   /* Optlist for setting up input */
59551b ¤   PGPBoolean¤ ¤   ¤   ·freshOp;¤  ¤   /* Got fresh op from user */
4904de ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error codes */
f119be ¤   PGPFileDataType¤¤   ·inFileDataType;¤   /* Unused */
6267c5 ¤
88a07d ¤   (void) head;
d0af5a
787c16 ¤   s = (PGPDecodeJob *) arg;
--ed9c 000db77cd43401001de Page 18 of pgpDecode.c
31068a ¤   freshOp = FALSE;
31af5a
dbf16f ¤   /* See if there was a detached-signature option specified */
d3d83f ¤   if( IsPGPError( err = pgpSearchOptionSingle( s->optionList,
2078e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_DetachedSignature, &op ) ) )
1e97ed ¤   ¤   goto error;
1e31e1 ¤   if( !s->fUsedDetachedSigOp && IsOp( op ) ·&& IsntNull( op.subOptions ) ) {
d9e896 ¤   ¤   /* Only use the detachedsig op once, after that we will ask user */
99ccd6 ¤   ¤   s->fUsedDetachedSigOp = TRUE;
e57bf4 ¤   ¤   setupOp = op.subOptions;
07f037 ¤   } else {
6963b3 ¤   ¤   /* Ask user for detached signature input */
49af5a
ac0ed0 ¤   ¤   if( IsNull( s->func ) ) {
452ce8 ¤   ¤   ¤   err = kPGPError_DetachedSignatureFound;
3fed19 ¤   ¤   ¤   goto error;
c50fe4 ¤   ¤   }
c3af5a
2af4f4 ¤   ¤   if( IsPGPError (err = pgpEventDetachedSignature( s->context,
0d6bd8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->newOptionList, s->func, s->userValue ) ) )
b3ed19 ¤   ¤   ¤   goto error;
3096b8 ¤   ¤   if( IsPGPError( err = pgpSearchOptionSingle( s->newOptionList,
fa551b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DetachedSignature, &op ) ) )
4eed19 ¤   ¤   ¤   goto error;
8f803f ¤   ¤   if( IsOp( op ) ·&& IsntNull( op.subOptions ) ) {
b5469c ¤   ¤   ¤   setupOp = op.subOptions;
2745a6 ¤   ¤   } else {
4d2ce8 ¤   ¤   ¤   err = kPGPError_DetachedSignatureFound;
f4ed19 ¤   ¤   ¤   goto error;
440fe4 ¤   ¤   }
3d00a2 ¤   ¤   freshOp = TRUE;
969371 ¤   }
58af5a
faff14 ¤   /* Set up input file or buffer */
f8641f ¤   err = pgpSetupInput( s->context, setupOp, NULL, NULL, TRUE, TRUE,
e17708 ¤   ¤   ¤   ¤   ¤   ¤   ·&detFileRef, &pfrdet, &inFileDataType, &detBufPtr,
d9f7ec ¤   ¤   ¤   ¤   ¤   ¤   ·&detBufLength );
7b7f7d ¤   if( IsPGPError( err ) )
7297ed ¤   ¤   goto error;
af67c5 ¤
29eecd ¤   /* Now pump the sig-check data through the pipes */
936383 ¤   if( detFileRef ) {
a9d399 ¤   ¤   /* File input */
2e4902 ¤   ¤   err = pgpFileReadPump( pfrdet, head );
124918 ¤   ¤   pgpFileReadDestroy( pfrdet );
fcd223 ¤   ¤   if( IsPGPError( err ) )
85ed19 ¤   ¤   ¤   goto error;
2cf037 ¤   } else {
12515f ¤   ¤   /* Buffer input */
5a6348 ¤   ¤   if( IsPGPError( err = pgpPumpMem( head, detBufPtr,
390bfd ¤   ¤   ¤   ¤   ¤   ¤   detBufLength, NULL, NULL ) ) )
23ed19 ¤   ¤   ¤   goto error;
7b9371 ¤   }
f76493 ¤   err = kPGPError_NoErr;
5a91b1 ¤   /* Fall through */
9d60ff error:
b870d9 ¤   /* Discard after one usage */
0d99f5 ¤   if( freshOp ) {
817a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
379371 ¤   }
085ea8 ¤   return err;
9defe6 }
95af5a
10af5a
b438e5 /*
af5dc8 ·* Given the signature structure, sig, verify it against the hash
b33a95 ·* to see if this signature is valid. ·This requires looking up the
6fad5a ·* public key in the keyring and validating the key.
c1775e ·*
080d41 ·* Returns 0 on success or an error code.
f1495d ·*/
db66dd ¤   static PGPError
--c676 0005d15287a401001de Page 19 of pgpDecode.c
0657bc pgpDecodeVerifySig(
c6e865 ¤   void¤   ¤   ¤   ¤   *arg,
ab18e7 ¤   PGPSig const¤   ¤   *sig,
a287ff ¤   PGPByte const¤  ¤   *hash
8d27e6 ¤   )
15bb36 {
13a0f7 #if PGP_VERIFY_DISABLE /* [ */
acaf5a
5bd698 ¤   (void)arg;
6e77e4 ¤   (void)sig;
2c4902 ¤   (void)hash;
7be63f ¤   return kPGPError_FeatureNotAvailable;
4faf5a
cc08c4 #else /* PGP_VERIFY_DISABLE */ ·/* ] ·[ */
0faf5a
45fd08 ¤   PGPDecodeJob¤   ¤   *s;¤¤   ¤   ¤   /* Parameters for callbacks */
a5895f ¤   PGPKeyRef¤  ¤   ¤   ·signKey;¤  ¤   /* Signing key as PGPKey */
d8bed3 ¤   PGPKeySetRef¤   ¤   ·alternateKeySet; /* Extra keyset to try lookup */
70813b ¤   RingObject¤ ¤   ¤   *ringKey;¤  ¤   /* Public key ring object */
ea5209 ¤   RingSet const¤  ¤   *ringSet;¤  ¤   /* Set holding ringKey */
d9709e ¤   PGPPubKey¤  ¤   ¤   *pubkey;¤   ¤   /* Public key for verify */
af9d9b ¤   PGPKeyID¤   ¤   ¤   keyid;¤ ¤   ¤   /* KeyID from signature */
64af0c ¤   PGPPublicKeyAlgorithm¤  pkalg;¤ ¤   /* Public key alg from signature */
d4948d ¤   PGPTime¤¤   ¤   ¤   ·timeStamp;¤¤   /* Issuance time of sig */
d2be1e ¤   PGPValidity¤¤   ¤   ·failValidity,¤ /* Fail on keys less valid */
da970e ¤   ¤   ¤   ¤   ¤   ¤   ·warnValidity;¤ /* Warn on keys less valid */
4f3849 ¤   PGPBoolean¤ ¤   ¤   ·fRevoked=FALSE,/* Status of signing key */
dcfb02 ¤   ¤   ¤   ¤   ¤   ¤   ·fExpired=FALSE,
00d8da ¤   ¤   ¤   ¤   ¤   ¤   ·fDisabled=FALSE,
f377dc ¤   ¤   ¤   ¤   ¤   ¤   ·fValidityThreshold=TRUE;
b0e743 ¤   PGPValidity¤¤   ¤   ·keyValidity=kPGPValidity_Unknown;
fb75f8 ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error code */
2567c5 ¤
507c16 ¤   s = (PGPDecodeJob *) arg;
be3d74 ¤   pubkey = NULL;
a6b997 ¤   alternateKeySet = NULL;
feaf5a
3139d8 ¤   if( IsNull( s->func ) ) {
cb81bc ¤   ¤   /* If can't report results, don't bother to do anything */
9270bb ¤   ¤   err = kPGPError_NoErr;
ce97ed ¤   ¤   goto error;
b89371 ¤   }
83af5a
f81240 ¤   /* Get info about sig */
24f1e9 ¤   err¤= pgpGetSigKeyID ( sig, &keyid );
66054e ¤   if ( IsPGPError( err ) )
9a97ed ¤   ¤   goto error;
011b52 ¤   ¤
9fd96d ¤   pkalg = (PGPPublicKeyAlgorithm)pgpSigPKAlg (sig);
21af5a
bcc06a ¤   timeStamp = pgpSigTimestamp (sig);
adaf5a
4ce8b8 retrykeyset:
09af5a
660bf3 ¤   if (pkalg >= kPGPPublicKeyAlgorithm_First &&
a657c9 ¤   ¤   ¤   ¤   ¤   pkalg <= kPGPPublicKeyAlgorithm_Last) {
310590 ¤   ¤   if( IsNull( s->keySet ) ) {
88f8a5 ¤   ¤   ¤   err = kPGPError_MissingKeySet;
3a45a6 ¤   ¤   } else {
405d54 ¤   ¤   ¤   err = PGPGetKeyByKeyID ( s->keySet, &keyid, pkalg, &signKey);
c90fe4 ¤   ¤   }
bd5bd7 ¤   ¤   if( IsPGPError( err ) && IsntNull( alternateKeySet ) ) {
05b1f6 ¤   ¤   ¤   err = PGPGetKeyByKeyID ( alternateKeySet, &keyid, pkalg, &signKey);
680fe4 ¤   ¤   }
189371 ¤   }
72af5a
8b190d ¤   if( IsPGPError( err ) ||
5174eb ¤   ¤   ¤   pkalg < kPGPPublicKeyAlgorithm_First ||
f41d23 ¤   ¤   ¤   pkalg > kPGPPublicKeyAlgorithm_Last) {
2592a3 ¤   ¤   /* Don't have signing key; notify him */
4cf5b6 ¤   ¤   err = pgpEventSignature( s->context, &s->newOptionList,
5d7f47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, &keyid, NULL,
--18e4 00023f9e8d0401001de Page 20 of pgpDecode.c
ec661f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
83a6d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··keyValidity, timeStamp );
5b948c ¤   ¤   if( IsntNull( alternateKeySet ) )
17a357 ¤   ¤   ¤   PGPFreeKeySet (alternateKeySet);
5d2380 ¤   ¤   pgpSetupKeySet (s->newOptionList, &alternateKeySet);
a53cb6 ¤   ¤   if( IsntNull( alternateKeySet ) ) {
eabd25 ¤   ¤   ¤   PGPIncKeySetRefCount( alternateKeySet );
b56b76 ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
e51c17 ¤   ¤   ¤   goto retrykeyset;
780fe4 ¤   ¤   }
047a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
b297ed ¤   ¤   goto error;
239371 ¤   }
c0af5a
e155df ¤   if( IsPGPError( err = pgpGetKeyRingObject( signKey, FALSE, &ringKey ) ) )
d997ed ¤   ¤   goto error;
a4471b ¤   if( IsPGPError( err = pgpGetKeyRingSet( signKey, FALSE, &ringSet ) ) )
7197ed ¤   ¤   goto error;
8067c5 ¤
b3c646 ¤   pubkey = ringKeyPubKey( ringSet, ringKey, PGP_PKUSE_SIGN );
5eaf5a
ced241 ¤   if (pubkey && !pubkey->verify) {
a1cd8f ¤   ¤   /* Make sure we can use this key */
9646fb ¤   ¤   pgpPubKeyDestroy (pubkey);
77069d ¤   ¤   pubkey = NULL;
bd9371 ¤   }
8467c5 ¤
294675 ¤   if (!pubkey) {
298165 ¤   ¤   /* Can't verify for some reason... notify him */
45f5b6 ¤   ¤   err = pgpEventSignature( s->context, &s->newOptionList,
6e31a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, &keyid, signKey,
75661f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
16a6d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··keyValidity, timeStamp );
4b948c ¤   ¤   if( IsntNull( alternateKeySet ) )
73a357 ¤   ¤   ¤   PGPFreeKeySet (alternateKeySet);
102380 ¤   ¤   pgpSetupKeySet (s->newOptionList, &alternateKeySet);
dd3cb6 ¤   ¤   if( IsntNull( alternateKeySet ) ) {
b3bd25 ¤   ¤   ¤   PGPIncKeySetRefCount( alternateKeySet );
c36b76 ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
9c1c17 ¤   ¤   ¤   goto retrykeyset;
500fe4 ¤   ¤   }
237a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
9297ed ¤   ¤   goto error;
889371 ¤   }
ce67c5 ¤
5f61d2 ¤   /* Determine validity of signing key */
1f85c5 ¤   if( IsPGPError( err = pgpGetMinValidity( s->optionList,
a66877 ¤   ¤   ¤   ¤   ¤   &failValidity, &warnValidity ) ) )
a497ed ¤   ¤   goto error;
549018 ¤   err = pgpCheckKeyValidity( s->context, s->optionList,
189a8e ¤   ¤   ¤   ¤   ¤   signKey, ringSet, failValidity, warnValidity, NULL,
28be10 ¤   ¤   ¤   ¤   ¤   &keyValidity );
bbaf5a
5d216c ¤   if( err == kPGPError_KeyInvalid ) {
7cd8c4 ¤   ¤   fValidityThreshold = FALSE;
6d2e88 ¤   } else if( err == kPGPError_KeyRevoked ||
4d18b5 ¤   ¤   ¤   ···err == kPGPError_KeyExpired ||
6076fe ¤   ¤   ¤   ···err == kPGPError_KeyDisabled ) {
aad8c4 ¤   ¤   fValidityThreshold = FALSE;
78aeec ¤   ¤   if( IsPGPError( err = PGPGetKeyBoolean( signKey, kPGPKeyPropIsRevoked,
2ac2bb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fRevoked ) ) )
2bed19 ¤   ¤   ¤   goto error;
a83682 ¤   ¤   if( IsPGPError( err = PGPGetKeyBoolean( signKey, kPGPKeyPropIsDisabled,
0b77c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fDisabled ) ) )
53ed19 ¤   ¤   ¤   goto error;
27fc2c ¤   ¤   if( IsPGPError( err = PGPGetKeyBoolean( signKey, kPGPKeyPropIsExpired,
1a65ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fExpired ) ) )
aded19 ¤   ¤   ¤   goto error;
85175b ¤   } else if( err != kPGPError_NoErr ) {
1997ed ¤   ¤   goto error;
209371 ¤   }
23af5a
--373c 0006cf9aa92401001de Page 21 of pgpDecode.c
05f66b ¤   /* Check signature, returns 1 if OK */
81de35 ¤   err = pgpSigCheck (sig, pubkey, hash);
bbca84 ¤   pgpPubKeyDestroy (pubkey);
003d74 ¤   pubkey = NULL;
02afbd ¤   if( err != 1 ) {
1ed223 ¤   ¤   if( IsPGPError( err ) )
4bed19 ¤   ¤   ¤   goto error;
e54f96 ¤   ¤   /* Notify of bad signature and exit */
7bf5b6 ¤   ¤   err = pgpEventSignature( s->context, &s->newOptionList,
e931a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, &keyid, signKey,
ac379e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··TRUE, FALSE, fDisabled, fRevoked, fExpired,
cca542 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··fValidityThreshold, keyValidity, timeStamp );
037a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
8397ed ¤   ¤   goto error;
6f9371 ¤   }
cb1b52 ¤   ¤
5931aa ¤   err = pgpEventSignature( s->context, &s->newOptionList,
322483 ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, &keyid, signKey,
d1feb3 ¤   ¤   ¤   ¤   ¤   ¤   ··TRUE, TRUE, fDisabled, fRevoked, fExpired,
f2be4b ¤   ¤   ¤   ¤   ¤   ¤   ··fValidityThreshold, keyValidity, timeStamp );
eca2e3 ¤   pgpCleanupOptionList( &s->newOptionList );
fdaf5a
ac91b1 ¤   /* Fall through */
4860ff error:
1135ee ¤   if ( IsntNull( pubkey ) )
cc3632 ¤   ¤   pgpPubKeyDestroy( pubkey );
3aa812 ¤   if ( IsntNull( alternateKeySet ) )
21af95 ¤   ¤   PGPFreeKeySet( alternateKeySet );
155ea8 ¤   return err;
39af5a
1f5156 #endif /* PGP_VERIFY_DISABLE */ /* ] */
fdefe6 }
e6af5a
3eaf5a
a038e5 /*
3ea1c1 ·* given a list of Encrypted Session Keys (esklist), try to decrypt
ca477c ·* them to get the session key. ·Fills in keylen with the length of
c562f8 ·* the session key buffer.
ae775e ·*
a95ad8 ·* Returns 0 on success or PGPANN_PARSER_EATIT on failure.
2f495d ·*/
a066dd ¤   static PGPError
ff8ef2 pgpDecodeDecryptESK(
89e865 ¤   void¤   ¤   ¤   ¤   *arg,
3f7a22 ¤   PGPESK const¤   ¤   *esklist,
d2a055 ¤   PGPByte¤¤   ¤   ¤   *key,
72e9a6 ¤   PGPSize¤¤   ¤   ¤   *keylen,
0be20b ¤   int¤¤   ¤   ¤   ···(*tryKey)(void *arg, PGPByte const *key, PGPSize keylen),
d6bc1c ¤   void¤   ¤   ¤   ¤   *tryarg
9427e6 ¤   )
02bb36 {
ac0545 #if PGP_DECRYPT_DISABLE /* [ */
e4af5a
b73cf7 ¤   (void) arg;
088d69 ¤   (void) esklist;
7d7151 ¤   (void) key;
ceb686 ¤   (void) keylen;
067740 ¤   (void) tryKey;
835a77 ¤   (void) tryarg;
d9e63f ¤   return kPGPError_FeatureNotAvailable;
97af5a
fc0d75 #else /* PGP_DECRYPT_DISABLE */ ·/* ] ·[ */
efaf5a
78fd08 ¤   PGPDecodeJob¤   ¤   *s;¤¤   ¤   ¤   /* Parameters for callbacks */
a06cf8 ¤   PGPESK const¤   ¤   *esk;¤  ¤   ¤   /* ESK being tested */
a06c2e ¤   PGPKeyRef¤  ¤   ¤   ·decKey;¤   ¤   /* PGPKey for decryption key */
1aff8a ¤   PGPKeySet¤  ¤   ¤   *decKeySet1;¤   /* Keyset with just decKey */
9bc009 ¤   PGPKeySet¤  ¤   ¤   *decKeySet;¤¤   /* Keyset with all decryption keys */
ae61a3 ¤   RingObject¤ ¤   ¤   *ringKey;¤  ¤   /* Secret key ring object */
a8ff98 ¤   RingSet const¤  ¤   *ringSet;¤  ¤   /* Lowlevel keyring set for key */
09dcb9 ¤   PGPSecKey¤  ¤   ¤   *seckey;¤   ¤   /* Secret key */
6c9503 ¤   PGPPublicKeyAlgorithm¤  ·pkalg;¤¤   ¤   /* Pubkey algorithm from ESK */
--67dd 000a94997a7401001de Page 22 of pgpDecode.c
1461eb ¤   PGPBoolean¤ ¤   ¤   ·success;¤  ¤   /* True if had a successful decrypt */
4e9079 ¤   PGPInt32¤   ¤   ¤   ·klen;¤ ¤   ¤   /* Return code from key func */
b31024 ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error from pgplib */
d4b117 ¤   PGPUInt32¤  ¤   ¤   ·passPhraseCount; /* Count of possible pphrases */
af4e3e ¤   PGPUInt32¤  ¤   ¤   ·keyIDCount;¤   /* # deckeys unavail */
2c280e ¤   PGPKeyID¤   ¤   ¤   *keyIDArray;¤   /* Array of ptrs to keyids */
bbb7e7 ¤   PGPCipherAlgorithm¤ ·cipheralg;¤¤   /* Decryption algorithm */
63af5a
e27c16 ¤   s = (PGPDecodeJob *) arg;
eb140a ¤   decKeySet = NULL;
85e630 ¤   decKeySet1 = NULL;
943670 ¤   seckey = NULL;
ecfc20 ¤   keyIDArray = NULL;
1267c5 ¤
a0bbc6 ¤   /* First loop over all ESK's to set up recipient list */
6335eb ¤   passPhraseCount = 0;
fc354d ¤   keyIDCount = 0;
10320c ¤   if( IsntNull( s->keySet ) ) {
2df50d ¤   ¤   if( IsPGPError( err = PGPNewEmptyKeySet( s->keySet, &decKeySet ) ) )
72ed19 ¤   ¤   ¤   goto error;
e19371 ¤   }
eea778 ¤   for( esk = esklist; IsntNull( esk ); esk = pgpEskNext( esk ) ) {
d16c3a ¤   ¤   switch( pgpEskType( esk ) ) {
f7f9c0 ¤   ¤   case PGP_ESKTYPE_PASSPHRASE:
edc531 ¤   ¤   ¤   passPhraseCount += 1;
ffcdcb ¤   ¤   ¤   break;
ca94d7 ¤   ¤   case PGP_ESKTYPE_PUBKEY:
db5b34 ¤   ¤   {
971ed5 ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   keyid;¤ ¤   ¤   /* Key ID from ESK */
5ffbda ¤   ¤   ¤   void *¤ ¤   ¤   ¤   vKeyIDArray;
1467c5 ¤
492951 ¤   ¤   ¤   err¤= pgpGetEskKeyID( esk, &keyid);
138370 ¤   ¤   ¤   if ( IsPGPError( err ) )
851b7c ¤   ¤   ¤   ¤   goto error;
e0af5a
8d01dd ¤   ¤   ¤   /* Save keyids in list */
15a3c3 ¤   ¤   ¤   vKeyIDArray = keyIDArray;
eaad46 ¤   ¤   ¤   err = pgpContextMemRealloc( s->context,
152e75 ¤   ¤   ¤   ¤   ···&vKeyIDArray,
1567a4 ¤   ¤   ¤   ¤   ···(keyIDCount+1) * sizeof(keyIDArray[ 0 ]), 0 );
1b59df ¤   ¤   ¤   if( IsPGPError( err ) )
321b7c ¤   ¤   ¤   ¤   goto error;
0a4416 ¤   ¤   ¤   keyIDArray = (PGPKeyID *)vKeyIDArray;
41e967 ¤   ¤   ¤   keyIDArray[keyIDCount++] = keyid;
1e2b85 ¤   ¤   ¤   ¤
62ef4f ¤   ¤   ¤   pkalg = (PGPPublicKeyAlgorithm)pgpEskPKAlg (esk);
67af5a
c496eb ¤   ¤   ¤   decKey = NULL;
d6d395 ¤   ¤   ¤   if( IsntNull( s->keySet ) &&
2d810a ¤   ¤   ¤   ¤   ¤   ¤   pkalg >= kPGPPublicKeyAlgorithm_First &&
2793d5 ¤   ¤   ¤   ¤   ¤   ¤   pkalg <= kPGPPublicKeyAlgorithm_Last) {
7e72bd ¤   ¤   ¤   ¤   (void)PGPGetKeyByKeyID ( s->keySet, &keyid, pkalg, &decKey);
b8a3a6 ¤   ¤   ¤   }
76af5a
79c32b ¤   ¤   ¤   if( IsNull( decKey ) ) {
275d8f ¤   ¤   ¤   ¤   /* We don't have the decryption key */
61042d ¤   ¤   ¤   } else {
8ecdae ¤   ¤   ¤   ¤   /* Accumulate into recipient key set */
ffd980 ¤   ¤   ¤   ¤   PGPKeySetRef newKeySet;
f1ea2a ¤   ¤   ¤   ¤   if( IsPGPError( err = PGPNewSingletonKeySet( decKey,
d15688 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &decKeySet1 ) ) )
cbb622 ¤   ¤   ¤   ¤   ¤   goto error;
78b742 ¤   ¤   ¤   ¤   if( IsPGPError( err = PGPUnionKeySets(
7a53b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   decKeySet1, decKeySet, &newKeySet ) ) )
c0b622 ¤   ¤   ¤   ¤   ¤   goto error;
0fabc7 ¤   ¤   ¤   ¤   PGPFreeKeySet( decKeySet );
723924 ¤   ¤   ¤   ¤   decKeySet = newKeySet;
26c472 ¤   ¤   ¤   ¤   PGPFreeKeySet( decKeySet1 );
ba9c86 ¤   ¤   ¤   ¤   decKeySet1 = NULL;
99a3a6 ¤   ¤   ¤   }
45cdcb ¤   ¤   ¤   break;
a90fe4 ¤   ¤   }
--baf9 000b2fd8009401001de Page 23 of pgpDecode.c
f11b52 ¤   ¤
989ae3 ¤   ¤   default:
29b783 ¤   ¤   ¤   pgpAssert(0);
8ecdcb ¤   ¤   ¤   break;
f40fe4 ¤   ¤   }
0f9371 ¤   }
fcaf5a
d9b79e ¤   /* Notify user about decryption keys */
f1f24a ¤   if( IsPGPError( err = pgpEventRecipients( s->context, &s->newOptionList,
5a565f ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, decKeySet, keyIDArray,
bf3b8c ¤   ¤   ¤   ¤   ¤   ¤   ··passPhraseCount, keyIDCount ) ) )
eb97ed ¤   ¤   goto error;
e7a2e3 ¤   pgpCleanupOptionList( &s->newOptionList );
f9a92f ¤   if( IsntNull( decKeySet ) ) {
29e6f4 ¤   ¤   PGPFreeKeySet( decKeySet );
c8d3bf ¤   ¤   decKeySet = NULL;
b59371 ¤   }
9aaf5a
fb8dbf ¤   /* Loop over all ESK's trying to find one we can decrypt */
b5acf7 ¤   /* decKeySet will hold decryption keys that we have secrets for */
237311 ¤   success = FALSE;
c3320c ¤   if( IsntNull( s->keySet ) ) {
6ef50d ¤   ¤   if( IsPGPError( err = PGPNewEmptyKeySet( s->keySet, &decKeySet ) ) )
12ed19 ¤   ¤   ¤   goto error;
7c9371 ¤   }
4eaf5a
a8cb1d ¤   while( !success ) {
842eab ¤   ¤   for( esk = esklist; IsntNull( esk ) && !success;
ceaabe ¤   ¤   ¤   ·¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   esk = pgpEskNext( esk ) ) {
4f50d4 ¤   ¤   ¤   switch( pgpEskType( esk ) ) {
fbfc2d ¤   ¤   ¤   case PGP_ESKTYPE_PASSPHRASE:
db632b ¤   ¤   ¤   ¤   /* Try the pass phrase */
d2e778 ¤   ¤   ¤   ¤   klen = pgpEskConvDecrypt (esk, s->env,
f7a28f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(char *)s->passPhrase, s->passLength, key);
127052 ¤   ¤   ¤   ¤   if( klen < 0 ) {
287288 ¤   ¤   ¤   ¤   ¤   err = klen;
2cb622 ¤   ¤   ¤   ¤   ¤   goto error;
1c2613 ¤   ¤   ¤   ¤   }
7f75f6 ¤   ¤   ¤   ¤   /* Else klen is length of key */
88a231 ¤   ¤   ¤   ¤   *keylen = klen;
6aaf5a
f7717b ¤   ¤   ¤   ¤   /* Returns 0 on success, nonzero on failure */
eb65ce ¤   ¤   ¤   ¤   if( tryKey (tryarg, key, *keylen) == 0 ) {
494e31 ¤   ¤   ¤   ¤   ¤   /* Success */
62a2db ¤   ¤   ¤   ¤   ¤   success = 1;
762613 ¤   ¤   ¤   ¤   }
06f622 ¤   ¤   ¤   ¤   break;
78af5a
2aa9bf ¤   ¤   ¤   case PGP_ESKTYPE_PUBKEY:
e9f776 ¤   ¤   ¤   {
7479d8 ¤   ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   keyid;¤ ¤   /* Key ID from ESK */
2b87c7 ¤   ¤   ¤
50a1c1 ¤   ¤   ¤   ¤   /* Look up key from ESK */
da320c ¤   ¤   ¤   ¤   err = pgpGetEskKeyID( esk, &keyid );
f7869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
cdb622 ¤   ¤   ¤   ¤   ¤   goto error;
cdae30 ¤   ¤   ¤   ¤   ¤
ea5356 ¤   ¤   ¤   ¤   pkalg = (PGPPublicKeyAlgorithm)pgpEskPKAlg (esk);
eeaf5a
c7683a ¤   ¤   ¤   ¤   /* If don't have key, go on to next one */
d782c3 ¤   ¤   ¤   ¤   decKey = NULL;
b1d52d ¤   ¤   ¤   ¤   if( IsntNull( s->keySet ) &&
00810a ¤   ¤   ¤   ¤   ¤   ¤   pkalg >= kPGPPublicKeyAlgorithm_First &&
1193d5 ¤   ¤   ¤   ¤   ¤   ¤   pkalg <= kPGPPublicKeyAlgorithm_Last) {
2485b1 ¤   ¤   ¤   ¤   ¤   (void)PGPGetKeyByKeyID( s->keySet, &keyid, pkalg, &decKey);
622613 ¤   ¤   ¤   ¤   }
df2b85 ¤   ¤   ¤   ¤
26282f ¤   ¤   ¤   ¤   if( IsNull( decKey ) )
d614c3 ¤   ¤   ¤   ¤   ¤   break;
f0af5a
72c3de ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpGetKeyRingSet( decKey, FALSE,
b29272 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &ringSet ) ) )
--a289 000d4c88be7401001de Page 24 of pgpDecode.c
d2b622 ¤   ¤   ¤   ¤   ¤   goto error;
07af5a
2b980e ¤   ¤   ¤   ¤   /*
01714e ¤   ¤   ¤   ¤   ·* Use lower-level function to look up proper subkey.
410c19 ¤   ¤   ¤   ¤   ·* If key has more than one subkey then ringSecSecKey won't
6aafb8 ¤   ¤   ¤   ¤   ·* choose the right one if we give it a top level key.
e91020 ¤   ¤   ¤   ¤   ·*/
7b9c91 ¤   ¤   ¤   ¤   ringKey = ringKeyById8 (ringSet, (PGPByte)pkalg,
545c8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpGetKeyBytes (&keyid));
141e17 ¤   ¤   ¤   ¤   if( IsNull( ringKey ) )
dc14c3 ¤   ¤   ¤   ¤   ¤   break;
61af5a
e62438 ¤   ¤   ¤   ¤   seckey = ringSecSecKey( ringSet, ringKey, PGP_PKUSE_ENCRYPT );
24af5a
e79275 ¤   ¤   ¤   ¤   /* See if have a good decryption key */
d007c6 ¤   ¤   ¤   ¤   if (seckey && !seckey->decrypt) {
7b42f2 ¤   ¤   ¤   ¤   ¤   /* A matching secret key of a type which can't decrypt? */
5912ff ¤   ¤   ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
8e772f ¤   ¤   ¤   ¤   ¤   seckey = NULL;
bb2613 ¤   ¤   ¤   ¤   }
1caf5a
8f4f7c ¤   ¤   ¤   ¤   if( IsNull( seckey ) )
9e14c3 ¤   ¤   ¤   ¤   ¤   break;
16af5a
446cca ¤   ¤   ¤   ¤   /* Try to unlock decryption key with passphrase */
af742d ¤   ¤   ¤   ¤   err = pgpSecKeyUnlock (seckey, s->env,
1810de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *)s->passPhrase, s->passLength,
594612 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->hashedPhrase );
1ade09 ¤   ¤   ¤   ¤   if (err <= 0) {
9e1f63 ¤   ¤   ¤   ¤   ¤   /* Pass phrase failed to unlock. ·Try next ESK. */
fe51e6 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef newKeySet;
8512ff ¤   ¤   ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
98772f ¤   ¤   ¤   ¤   ¤   seckey = NULL;
e60689 ¤   ¤   ¤   ¤   ¤   /* Accumulate signing keys into decKeySet */
d4ed5c ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err = PGPNewSingletonKeySet( decKey,
b1e904 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &decKeySet1 ) ) )
6d3dde ¤   ¤   ¤   ¤   ¤   ¤   goto error;
8cb079 ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err = PGPUnionKeySets(
5191a2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···decKeySet1, decKeySet, &newKeySet ) ) )
f43dde ¤   ¤   ¤   ¤   ¤   ¤   goto error;
24b397 ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( decKeySet );
1c3768 ¤   ¤   ¤   ¤   ¤   decKeySet = newKeySet;
9196ef ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( decKeySet1 );
18dd75 ¤   ¤   ¤   ¤   ¤   decKeySet1 = NULL;
1c14c3 ¤   ¤   ¤   ¤   ¤   break;
202613 ¤   ¤   ¤   ¤   }
cdaf5a
91fe2f ¤   ¤   ¤   ¤   /* Try decrypting the ESK */
5bee1d ¤   ¤   ¤   ¤   err = pgpEskPKdecrypt (esk, s->env, seckey, key);
ee8b53 ¤   ¤   ¤   ¤   *keylen = err;
c98367 ¤   ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
d4fb50 ¤   ¤   ¤   ¤   seckey = NULL;
12de09 ¤   ¤   ¤   ¤   if (err <= 0) {
5893d6 ¤   ¤   ¤   ¤   ¤   /* Failed to decrypt, indicates corrupt ESK */
9365fc ¤   ¤   ¤   ¤   ¤   if (err != kPGPError_CAPIUnsupportedKey)
e90ce3 ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_CorruptSessionKey;
4bb622 ¤   ¤   ¤   ¤   ¤   goto error;
652613 ¤   ¤   ¤   ¤   }
40af5a
8e33e1 ¤   ¤   ¤   ¤   /* Now try the decrypted ESK against the rest of the message */
5ba4d6 ¤   ¤   ¤   ¤   /* (save cipheralgorithm, first byte of key buffer) */
b567aa ¤   ¤   ¤   ¤   cipheralg = (PGPCipherAlgorithm)key[0];
1bf21b ¤   ¤   ¤   ¤   err = tryKey (tryarg, key, *keylen);
83b1fb ¤   ¤   ¤   ¤   if (err) {
9245a7 ¤   ¤   ¤   ¤   ¤   /* Failure, indicates corrupt ESK */
4f0bd8 ¤   ¤   ¤   ¤   ¤   err = kPGPError_CorruptSessionKey;
0db622 ¤   ¤   ¤   ¤   ¤   goto error;
fd2613 ¤   ¤   ¤   ¤   }
422b85 ¤   ¤   ¤   ¤
857487 ¤   ¤   ¤   ¤   /* Else it worked OK */
a1a3b4 ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpEventDecryption( s->context,
d4493b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&s->newOptionList, s->func,
--fe80 000f81791a0401001de Page 25 of pgpDecode.c
020309 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->userValue, cipheralg ) ) )
47b622 ¤   ¤   ¤   ¤   ¤   goto error;
9b6c4d ¤   ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
882b85 ¤   ¤   ¤   ¤
8e198d ¤   ¤   ¤   ¤   success = 1;
26f622 ¤   ¤   ¤   ¤   break;
9aa3a6 ¤   ¤   ¤   }
76af5a
9edb68 ¤   ¤   ¤   default:
05ff25 ¤   ¤   ¤   ¤   /* Unknown ESK type */
8567fb ¤   ¤   ¤   ¤   pgpAssert (0);
6df622 ¤   ¤   ¤   ¤   break;
6ca3a6 ¤   ¤   ¤   }
120fe4 ¤   ¤   }
d2d5a2 ¤   ¤   if( !success ) {
e45826 ¤   ¤   ¤   /* Get new passphrase from user */
4be1a3 ¤   ¤   ¤   if( IsNull( s->func ) ) {
b008d7 ¤   ¤   ¤   ¤   /* If no callback, just skip undecryptable messages */
6eb737 ¤   ¤   ¤   ¤   err = PGPANN_PARSER_EATIT;
4e1b7c ¤   ¤   ¤   ¤   goto error;
f7a3a6 ¤   ¤   ¤   }
638b3c ¤   ¤   ¤   if( IsPGPError( err = pgpEventPassphrase( s->context,
44f522 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&s->newOptionList, s->func,
4c834d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->userValue,
309ceb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPBoolean)(passPhraseCount>0),
ad076e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··decKeySet ) ) )
541b7c ¤   ¤   ¤   ¤   goto error;
774118 ¤   ¤   ¤   pgpBurnDecodePassphrase( s );
b2f351 ¤   ¤   ¤   err = pgpSetupDecodePassphrase( s->context,
e28ec3 ¤   ¤   ¤   ¤   ··s->newOptionList, &s->passPhrase, &s->passLength,
de35cc ¤   ¤   ¤   ¤   ··&s->hashedPhrase );
1b6b76 ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
1159df ¤   ¤   ¤   if( IsPGPError( err ) )
621b7c ¤   ¤   ¤   ¤   goto error;
2d8e7a ¤   ¤   ¤   /* If he specified no passphrase, we will eat the message */
ea592c ¤   ¤   ¤   if( IsNull( s->passPhrase ) ) {
d4b737 ¤   ¤   ¤   ¤   err = PGPANN_PARSER_EATIT;
2c1b7c ¤   ¤   ¤   ¤   goto error;
21a3a6 ¤   ¤   ¤   }
4b0fe4 ¤   ¤   }
d69371 ¤   }
65af5a
f66493 ¤   err = kPGPError_NoErr;
25af5a
2960ff error:
ffa92f ¤   if( IsntNull( decKeySet ) ) {
58e6f4 ¤   ¤   PGPFreeKeySet( decKeySet );
cfd3bf ¤   ¤   decKeySet = NULL;
5b9371 ¤   }
0623d5 ¤   if( IsntNull( decKeySet1 ) ) {
6cc727 ¤   ¤   PGPFreeKeySet( decKeySet1 );
d704d1 ¤   ¤   decKeySet1 = NULL;
379371 ¤   }
38f410 ¤   if( IsntNull( seckey ) ) {
372521 ¤   ¤   pgpSecKeyDestroy( seckey );
a40d99 ¤   ¤   seckey = NULL;
c99371 ¤   }
14ad62 ¤   if( IsntNull( keyIDArray ) ) {
f13878 ¤   ¤   pgpContextMemFree( s->context, keyIDArray );
361ec1 ¤   ¤   keyIDArray = NULL;
c99371 ¤   }
b2af5a
915ea8 ¤   return err;
65af5a
e02cfc #endif /* PGP_DECRYPT_DISABLE */ /* ] */
8aefe6 }
86af5a
23af5a
6fe06f /************************** Main decode function ****************************/
55af5a
75af5a
f8af5a
--4d7e 00025673004401001de Page 26 of pgpDecode.c
968104 /* Local callback function */
b6af5a
2066dd ¤   static PGPError
eab614 decodeLocalCallBack (
8be865 ¤   void¤   ¤   ¤   ¤   *arg,
12a5b7 ¤   PGPFileOffset¤  ¤   soFar,
d99f4a ¤   PGPFileOffset¤  ¤   total
4827e6 ¤   )
dabb36 {
9d9761 ¤   PGPError¤   ¤   ¤   ··err = kPGPError_NoErr;
d34089 ¤   PGPDecodeJob¤   ¤   ·*s = ( PGPDecodeJob * ) arg;
c9af5a
615185 ¤   if( IsntNull( s->func ) ·&& ·s->fNullEvents ) {
23853b ¤   ¤   err = pgpEventNull( s->context, &s->newOptionList, s->func,
bc95e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->userValue, soFar, total );
cb7a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
bb9371 ¤   }
7f5ea8 ¤   return err;
c0efe6 }
6caf5a
45af5a
b98b86 static const PGPOptionType decodeOptionSet[] = {
115ceb ¤   kPGPOptionType_InputFileRef,
ebd59a ¤   kPGPOptionType_InputBuffer,
f5be74 ¤   kPGPOptionType_OutputFileRef,
096c2f ¤   kPGPOptionType_OutputBuffer,
f10a04 ¤   kPGPOptionType_OutputAllocatedBuffer,
ebbbd2 ¤   kPGPOptionType_AppendOutput,
8540be ¤   kPGPOptionType_DiscardOutput,
feb15b ¤   kPGPOptionType_LocalEncoding,
c74990 ¤   kPGPOptionType_Passphrase,
294590 ¤   kPGPOptionType_Passkey,
00a576 ¤   kPGPOptionType_DetachedSignature,
056856 ¤   kPGPOptionType_FailBelowValidity,
b42baf ¤   kPGPOptionType_WarnBelowValidity,
f4165b ¤   kPGPOptionType_OutputLineEndType,
a5074a ¤   kPGPOptionType_EventHandler,
f2bf11 ¤   kPGPOptionType_SendNullEvents,
936734 ¤   kPGPOptionType_ImportKeysTo,
d53d63 ¤   kPGPOptionType_SendEventIfKeyFound,
3cde09 ¤   kPGPOptionType_DecodeOnlyOne,
91c7c2 ¤   kPGPOptionType_PassThroughIfUnrecognized,
7e333d ¤   kPGPOptionType_PassThroughClearSigned,
109c60 ¤   kPGPOptionType_PassThroughKeys,
ea50c0 ¤   kPGPOptionType_KeySetRef,
582882 ¤   kPGPOptionType_RecursivelyDecode,
3c037b ¤   kPGPOptionType_X509Encoding ··/* allow calling from pgpimportkeyset */
9182f7 };
9baf5a
050006 /* Main entry point for this module */
cdaf5a
60c744 ¤   PGPError
6b3660 pgpDecodeInternal(
7aa1bc ¤   PGPContextRef¤  ¤   context,
d11efc ¤   PGPOptionListRef¤   optionList
c527e6 ¤   )
d0bb36 {
657c97 ¤   PGPDecodeJob¤   ¤   ·jobState,¤ ¤   /* State in a struct */
38c8a7 ¤   ¤   ¤   ¤   ¤   ¤   *s=&jobState;¤  /* Use s-> to access all state ·*/
3119be ¤   PGPFileDataType¤¤   ·inFileDataType;¤   /* Unused */
3267c5 ¤
1e5942 ¤   /* Initialize pointers to NULL for easier error cleanup */
98fc16 ¤   pgpClearMemory( s, sizeof( *s ) );
c87083 ¤   s->context = context;
08a635 ¤   s->optionList = optionList;
995908 ¤   s->tail = &s->head;
45169f ¤   s->analyzeState = kAnalyzeWaiting;
ceaf5a
0c1d47 ¤   if (IsPGPError( s->err = pgpCheckOptionsInSet( optionList,
b4406a ¤   ¤   ¤   ¤   ¤   ¤   decodeOptionSet, elemsof( decodeOptionSet ) ) ) )
08c6bb ¤   ¤   return s->err;
25af5a
--107e 0004ba9b893401001de Page 27 of pgpDecode.c
ed2031 ¤   /* Get copies of info from context */
231267 ¤   s->env = pgpContextGetEnvironment( s->context );
42fbbf ¤   s->rng = pgpContextGetX9_17RandomContext ( s->context );
4567c5 ¤
efac33 ¤   /* Setup the UI callback functions & args */
061845 ¤   s->ui.message¤  ¤   = pgpDecodeShowMessage;
d64776 ¤   s->ui.doCommit¤ ¤   = pgpDecodeDoCommit;
0a1741 ¤   s->ui.newOutput¤¤   = pgpDecodeSetupNewOutput;
c8d706 ¤   s->ui.needInput¤¤   = pgpDecodeFindAltInput;
486b9d ¤   s->ui.sigVerify¤¤   = pgpDecodeVerifySig;
f94438 ¤   s->ui.eskDecrypt¤   = pgpDecodeDecryptESK;
bf4e80 ¤   s->ui.annotate¤ ¤   = pgpDecodeHandleAnnotation;
ccaf5a
1c98f4 ¤   /* Set up callback pointers and data */
db1f9e ¤   if( IsPGPError( s->err = pgpSetupCallback( s->optionList,
c8e05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&s->func, &s->userValue, &s->fNullEvents ) ) )
ce97ed ¤   ¤   goto error;
a692fd ¤   s->err = pgpEventInitial( s->context, &s->newOptionList,
78b16e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue );
e6a2e3 ¤   pgpCleanupOptionList( &s->newOptionList );
2f1d7a ¤   if( IsPGPError( s->err ) )
e997ed ¤   ¤   goto error;
f3af5a
38ff14 ¤   /* Set up input file or buffer */
3357df ¤   if( IsPGPError( s->err = pgpSetupInput( s->context, s->optionList,
afd1b1 ¤   ¤   ¤   ¤   ¤   NULL, NULL, FALSE, FALSE, &s->inFileRef, &s->pfrin,
36c9f0 ¤   ¤   ¤   ¤   ¤   &inFileDataType, &s->inBufPtr, &s->inBufLength ) ) )
ef97ed ¤   ¤   goto error;
0faf5a
a8af5a
99e547 ¤   /* Get keyset, passphrase data from user */
fdbeee ¤   if( IsPGPError( s->err = pgpSetupKeySet( s->optionList,
f4004c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->keySet ) ) )
4197ed ¤   ¤   goto error;
3d8aab ¤   if( IsPGPError( s->err = pgpSetupDecodePassphrase( s->context,
f5b2f6 ¤   ¤   ¤   ¤   ¤   ¤   s->optionList, &s->passPhrase, &s->passLength,
526958 ¤   ¤   ¤   ¤   ¤   ¤   &s->hashedPhrase ) ) )
4a97ed ¤   ¤   goto error;
daaf5a
17995f ¤   /* Parse output information if any */
4b33b6 ¤   if( IsPGPError( s->err = pgpSetupOutput( s->optionList,
3a8bb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->env, &s->outFileRef,
57c2a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outBufPtr, &s->outBufPtrPtr,
e8dd47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outBufMaxLength, &s->outBufUsedLength,
6fe749 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outDiscard, &s->localEncodeFlags,
118f4c ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->lineEnd, &s->fAppendOutput ) ) )
2c97ed ¤   ¤   goto error;
48af5a
d1d9fa ¤   /* If he set up output already, keep it throughout. ·Otherwise we need
ec69b4 ¤   ·* to see a callback function. */
43708f ¤   s->fixedOutput = IsntNull( s->outFileRef ) || IsntNull( s->outBufPtr ) ||
70fd1f ¤   ¤   ¤   ¤   ¤   ··IsntNull( s->outBufPtrPtr ) || s->outDiscard;
40af5a
8897eb ¤   if( !s->fixedOutput && IsNull( s->func ) ) {
9bda41 ¤   ¤   pgpDebugMsg( "Error: no output options" );
6a31f7 ¤   ¤   s->err = kPGPError_BadParams;
db97ed ¤   ¤   goto error;
5e9371 ¤   }
fdaf5a
43c80c ¤   /* Set up pipeline */
2754e1 ¤   s->tail = pgpDecryptPipelineCreate ( context,
095fc1 ¤   ¤   ¤   ¤   &s->head, s->env, NULL, &s->ui, s);
0faf5a
dab8c4 ¤   /* Handle clearsign and key passthroughs (nonpgp is in NewOutput) */
f6f5e8 ¤   if( IsPGPError( s->err = pgpSetupPassThrough( s->context, s->optionList,
cae822 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->head,
202b82 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&s->passThroughFifo,
4acf19 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&s->recurse ) ) )
f297ed ¤   ¤   goto error;
aaaf5a
b80b9b ¤   /* Now pump the data through the pipes */
4bdb07 ¤   if( s->inFileRef ) {
--11e0 000652775e9401001de Page 28 of pgpDecode.c
5dd399 ¤   ¤   /* File input */
5e4649 ¤   ¤   if( IsntNull( s->func ) && s->fNullEvents ) {
578b3f ¤   ¤   ¤   pgpFileReadSetCallBack( s->pfrin, decodeLocalCallBack, s );
e70fe4 ¤   ¤   }
71fb61 ¤   ¤   s->err = pgpFileReadPump( s->pfrin, s->head );
f3d223 ¤   ¤   pgpFileReadDestroy( s->pfrin );
871f7f ¤   ¤   s->pfrin = NULL;
ae9105 ¤   ¤   if( IsPGPError( s->err ) )
46ed19 ¤   ¤   ¤   goto error;
69ce29 ¤   ¤   s->head->sizeAdvise( s->head, 0 );
43f037 ¤   } else {
18515f ¤   ¤   /* Buffer input */
6f4649 ¤   ¤   if( IsntNull( s->func ) && s->fNullEvents ) {
d0ff43 ¤   ¤   ¤   s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
bb9845 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·decodeLocalCallBack, s );
cd45a6 ¤   ¤   } else {
6bff43 ¤   ¤   ¤   s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
b69f15 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·NULL, NULL );
130fe4 ¤   ¤   }
d59105 ¤   ¤   if( IsPGPError( s->err ) )
efed19 ¤   ¤   ¤   goto error;
639371 ¤   }
64af5a
cb9f2d ¤   /* Clean up if we had diverted the output in the last section */
3eded6 ¤   if( s->fPrevOutput ) {
a47fa6 ¤   ¤   (*s->prevOutput)->teardown( *s->prevOutput );
97c728 ¤   ¤   sRestoreOutputState( s, s->prevOutput );
8f9371 ¤   }
c6af5a
469a91 ¤   /* Get output buffer bytes-used info if appropriate */
732d41 ¤   if( s->outPipe ) {
e691aa ¤   ¤   if( IsntNull( s->outBufPtrPtr ) ) {
63913c ¤   ¤   ¤   /* Dynamically allocated buffer - tell user size & position */
319a58 ¤   ¤   ¤   if( IsPGPError( s->err = pgpGetVariableMemOutput( s->outPipe,
479434 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufMaxLength, s->outBufPtrPtr,
6b4fef ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufUsedLength ) ) )
511b7c ¤   ¤   ¤   ¤   goto error;
8e45a6 ¤   ¤   } else {
28542a ¤   ¤   ¤   /* Fixed size buffer - tell user actual size used */
05771d ¤   ¤   ¤   pgpAssert( IsntNull( s->outBufPtr ) );
070aa6 ¤   ¤   ¤   if( IsPGPError( s->err = pgpGetMemOutput( s->outPipe,
9a0ef6 ¤   ¤   ¤   ¤   ¤   ¤   s->outBufMaxLength, s->outBufUsedLength ) ) )
781b7c ¤   ¤   ¤   ¤   goto error;
800fe4 ¤   ¤   }
319140 ¤   ¤   s->outPipe = NULL;
e69371 ¤   }
c9af5a
cfc557 ¤   /* Now we can tear down the pipeline */
9d27eb ¤   s->head->teardown( s->head );
70db0d ¤   s->head = NULL;
dc1b83 ¤   if( IsntNull( s->pfout ) ) {
39de81 ¤   ¤   pgpFileClose( s->pfout );
28f0e7 ¤   ¤   s->pfout = NULL;
b09371 ¤   }
c2af5a
e2c9ba ¤   /* Done, clean up and return */
cc4d1a ¤   s->err = kPGPError_NoErr;
97af5a
2d60ff error:
9daf5a
dbbbb7 ¤   if( IsntNull( s->head ) ) {
f1c898 ¤   ¤   s->head->teardown( s->head );
13a1f9 ¤   ¤   s->head = NULL;
499371 ¤   }
13fe53 ¤   if( IsntNull( s->pfrin ) ) {
9bd223 ¤   ¤   pgpFileReadDestroy( s->pfrin );
c41f7f ¤   ¤   s->pfrin = NULL;
239371 ¤   }
f51b83 ¤   if( IsntNull( s->pfout ) ) {
1bde81 ¤   ¤   pgpFileClose( s->pfout );
0ef0e7 ¤   ¤   s->pfout = NULL;
659371 ¤   }
--b845 001cab9be36401001de Page 29 of pgpDecode.c
be150d ¤   if( IsntNull( s->outFileRef ) ) {
d1fac3 ¤   ¤   PFLFreeFileSpec( s->outFileRef );
d9690d ¤   ¤   s->outFileRef = NULL;
1d9371 ¤   }
55af5a
6b896a ¤   if( IsntNull( s->passThroughFifo ) ) {
d1a0e3 ¤   ¤   pgpFifoDestroy( &pgpByteFifoDesc, s->passThroughFifo );
7456c9 ¤   ¤   s->passThroughFifo = NULL;
5e9371 ¤   }
6daf5a
cd4cc6 ¤   /* Burn passphrase from job structure, if any */
eb9285 ¤   pgpBurnDecodePassphrase( s );
d9af5a
aeb927 ¤   /* Interruption error is used to abort early in the process */
22b1c3 ¤   if( s->err == kPGPError_Interrupted )
067a12 ¤   ¤   s->err = kPGPError_NoErr;
97af5a
b794b8 ¤   /* Notify user via callback of error if requested */
b45dc9 ¤   if( IsPGPError( s->err ) && IsntNull( s->func ) ) {
549a7b ¤   ¤   (void)pgpEventError( s->context, &s->newOptionList, s->func,
f86e77 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·s->userValue, s->err, NULL );
627a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
cc9371 ¤   }
071b52 ¤   ¤
9f8c1f ¤   (void)pgpEventFinal( s->context, &s->newOptionList, s->func,
e8026f ¤   ¤   ¤   ¤   ¤   ¤   ·s->userValue );
c2a2e3 ¤   pgpCleanupOptionList( &s->newOptionList );
2aaf5a
5dfd52 ¤   return s->err;
58efe6 }
c9af5a
89af5a
217e4d /*__Editor_settings____
afaf5a
0f4126 ¤   Local Variables:
547b17 ¤   tab-width: 4
34f72f ¤   comment-column: 40
2b0e6c ¤   End:
e15f8c ¤   vi: ts=4 sw=4
ff9e9b ¤   vim: si
cad062 _____________________*/
--e073 000fe3b32c3401001df Page 1 of pgpEncSubr.c
a70335 /*____________________________________________________________________________
0eebc4 ¤   pgpEncSubr.c
9e4a30 ¤   Helper subroutines for encode/decode API
0067c5 ¤
e7c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
194b0f ¤   All rights reserved.
a667c5 ¤
0267c5 ¤
88af5a
5cc8e3 ¤   $Id: pgpEncSubr.c,v 1.54.2.1.2.1 1998/11/12 03:21:38 heller Exp $
42f7f7 ____________________________________________________________________________*/
73d224 #include "pgpConfig.h"¤ /* or pgpConfig.h in the CDK */
beaf5a
fdd92d #include <stdarg.h>
d5324c #include <string.h>
c0af5a
5feb3d /* Public headers */
aae82c #include "pgpPubTypes.h"
c6c26c #include "pgpContext.h"
529f63 #include "pgpEncode.h"
c32f8d #include "pgpErrors.h"
72a4b2 #include "pgpFileRef.h"
6da076 #include "pgpKeys.h"
d90d08 #include "pgpMem.h"
aaaf5a
59622b /* Private headers */
05a146 #include "pgpDebug.h"
246aaa #include "pgpAnnotate.h"
b7115d #include "pgpDevNull.h"
d28b0d #include "pgpEncodePriv.h"
ea0d6d #include "pgpEnv.h"
6c2d40 #include "pgpEventPriv.h"
551dd3 #include "pgpMemMod.h"
2e2ece #include "pgpPipeline.h"
920f03 #include "pgpRandomContext.h"
3b26e3 #include "pgpRngPub.h"
f845ee #include "pgpVMemMod.h"
214919 #include "pgpUtilities.h"
e1af5a
fcaf5a
a517a3 /******************* Misc functions for encode/decode ********************/
63af5a
6f38e5 /*
71164b ·* Convert the user flags used to specify local encoding into a flag value
65adb3 ·* from pgpFileRef.h
4a495d ·*/
3a522a ¤   PGPFileOpenFlags
2f5cdb pgpLocalEncodingToFlags( PGPUInt32 localEncode )
3abb36 {
a4b1f6 ¤   PGPFileOpenFlags¤   flags = (PGPFileOpenFlags)0;
0faf5a
6e41e8 ¤   /* Wrapper function ensured that only one of these was given */
1a6679 ¤   if( localEncode & kPGPLocalEncoding_Auto )
dad7a3 ¤   ¤   flags = kPGPFileOpenMaybeLocalEncode;
f8af38 ¤   else if( localEncode & kPGPLocalEncoding_Force )
e74b41 ¤   ¤   flags = kPGPFileOpenForceLocalEncode;
56af5a
7c6f67 ¤   /* Add optional modifier flags */
0f17e0 ¤   if( localEncode & kPGPLocalEncoding_NoMacBinCRCOkay )
a7baf2 ¤   ¤   flags |= kPGPFileOpenNoMacBinCRCOkay;
3aaf5a
9c0380 ¤   return flags;
eeefe6 }
06af5a
94af5a
2aaf5a
30e325 /******************* Helper functions for encode/decode ********************/
b5af5a
11af5a
49af5a
0038e5 /*
fe7305 ·* Pump data from the memory buffer at inBufPtr, of size InBufLength,
--e2b0 000eb5c1450401001df Page 2 of pgpEncSubr.c
866834 ·* into head. ·Do the terminating sizeAdvise but don't do the teardown.
3d495d ·*/
81af5a
0cc744 ¤   PGPError
9b72a7 pgpPumpMem(
132103 ¤   PGPPipeline¤¤   ¤   *head,
3a82bd ¤   PGPByte¤¤   ¤   ¤   *inBufPtr,
cf4b64 ¤   PGPSize¤¤   ¤   ¤   ·inBufLength,
e9ce63 ¤   PGPProgressCallBack¤ callBack,
3acb11 ¤   void¤   ¤   ¤   ¤   ·*callBackArg
9e27e6 ¤   )
dbbb36 {
f7c3ec ¤   PGPSize¤¤   ¤   ¤   totalSize;
467d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
4fb844 ¤   PGPSize¤¤   ¤   ¤   written;
c7af5a
591e12 ¤   totalSize = inBufLength;
30f7ca ¤   err = head->sizeAdvise( head, inBufLength );
daaf5a
1aa0c7 ¤   while( inBufLength>0 && IsntPGPError( err ) ) {
79990e ¤   ¤   written = head->write( head, inBufPtr,
9dbda6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···pgpMin(inBufLength, 4096), &err );
6ddb16 ¤   ¤   inBufPtr += written;
e5e7dc ¤   ¤   inBufLength -= written;
a9d223 ¤   ¤   if( IsPGPError( err ) )
87cdcb ¤   ¤   ¤   break;
f212c7 ¤   ¤   if( IsntNull( callBack ) )
a21d95 ¤   ¤   ¤   err = callBack( callBackArg, totalSize - inBufLength, totalSize );
829371 ¤   }
28b1f0 ¤   if( IsntPGPError( err ) )
471a53 ¤   ¤   err = head->sizeAdvise( head, 0 );
055ea8 ¤   return err;
24efe6 }
d7af5a
71af5a
932a3a /* Send a warning event to the user if he is set up for events */
01af5a
9fc744 ¤   PGPError
204ac9 pgpWarnUser(
024eaa ¤   PGPContextRef¤  ·¤  ·context,¤  ¤   /* Input parameters */
8ee099 ¤   PGPOptionListRef¤   ·optionList,
7e0b79 ¤   PGPError¤   ¤   ¤   ·errCode,
6aa59f ¤   void¤   ¤   ¤   ¤   *warnArg
ec27e6 ¤   )
43bb36 {
3c2259 ¤   PGPError¤   ¤   ¤   ·err;
9957f7 ¤   PGPEventHandlerProcPtr handler;
bba0c0 ¤   PGPUserValue¤   ¤   ·arg;
d8f2ba ¤   PGPOptionListRef¤   dummyOptionList = NULL;
c2af5a
0c7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
c00b14 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_EventHandler, FALSE,
129095 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%p", &handler, &arg ) ) )
1c97ed ¤   ¤   goto error;
5daf5a
acc5d5 ¤   if( IsntNull( handler ) ) {
c1dc33 ¤   ¤   if( IsPGPError( err = pgpEventWarning( context, &dummyOptionList,
0e65ea ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··handler, arg, errCode, warnArg ) ) )
30ed19 ¤   ¤   ¤   goto error;
f07ba3 ¤   ¤   pgpCleanupOptionList( &dummyOptionList );
629371 ¤   }
9f151e ¤   return kPGPError_NoErr;
01af5a
1060ff error:
2f5ea8 ¤   return err;
f9efe6 }
97af5a
a6af5a
cc9f3c /* Set fail-below validity values for failure and warning */
caaf5a
d2c744 ¤   PGPError
eb298d pgpGetMinValidity(
--c0b1 0009569c7da401001df Page 3 of pgpEncSubr.c
6ae099 ¤   PGPOptionListRef¤   ·optionList,
a4bb36 ¤   PGPValidity¤¤   ¤   *failValidity,¤ /* Output parameters */
d669af ¤   PGPValidity¤¤   ¤   *warnValidity
fb27e6 ¤   )
42bb36 {
bf2259 ¤   PGPError¤   ¤   ¤   ·err;
0faff3 ¤   PGPOption¤  ¤   ¤   ·op;
47cd71 ¤   PGPUInt32¤  ¤   ¤   temp;
60af5a
2c8a4d ¤   /* Init return pointers */
430779 ¤   pgpa( pgpaAddrValid( failValidity, PGPValidity ) );
e87cbe ¤   pgpa( pgpaAddrValid( warnValidity, PGPValidity ) );
7285d6 ¤   /* XXX Need to fix these based on trust model and other aspects */
1d7145 ¤   *failValidity = kPGPValidity_Unknown;
24a00f ¤   *warnValidity = kPGPValidity_Marginal;
12af5a
537e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
d1b56e ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_FailBelowValidity, &op ) ) )
c297ed ¤   ¤   goto error;
007343 ¤   if( IsOp( op ) ) {
b81b52 ¤   ¤
9e3dce ¤   ¤   if( IsPGPError( err = pgpOptionUInt( &op, &temp ) ) )
2eed19 ¤   ¤   ¤   goto error;
26619c ¤   ¤   *failValidity¤  = (PGPValidity)temp;
f09371 ¤   }
187e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
b84d6e ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_WarnBelowValidity, &op ) ) )
ad97ed ¤   ¤   goto error;
a17343 ¤   if( IsOp( op ) ) {
a33dce ¤   ¤   if( IsPGPError( err = pgpOptionUInt( &op, &temp ) ) )
57ed19 ¤   ¤   ¤   goto error;
418067 ¤   ¤   *warnValidity¤  = (PGPValidity)temp;
f69371 ¤   }
4b151e ¤   return kPGPError_NoErr;
76af5a
9460ff error:
415ea8 ¤   return err;
aeefe6 }
87af5a
0e67c5 ¤
baaf5a
f1af5a
0bc176 /* Check a key for encryption or signature-verification validity. ·Return
74b3ed ···an error if it is no good, no error to proceed */
c5af5a
e8c744 ¤   PGPError
5a8b78 pgpCheckKeyValidity(
d64eaa ¤   PGPContextRef¤  ·¤  ·context,¤  ¤   /* Input parameters */
8ae099 ¤   PGPOptionListRef¤   ·optionList,
deddfd ¤   PGPKey¤ ¤   ¤   ¤   *key,
edf3b9 ¤   RingSet const¤  ¤   *ringSet,
84b298 ¤   PGPValidity¤¤   ¤   ·failValidity,
61295d ¤   PGPValidity¤¤   ¤   ·warnValidity,
a5ae11 ¤   PGPKeySet¤  ¤   ¤   *warnKeySet,¤   /* Output parameters */
34ebc7 ¤   PGPValidity¤¤   ¤   *pValidity
0327e6 ¤   )
48bb36 {
597738 ¤   PGPValidity¤¤   ¤   ·validity;
24a1ca ¤   PgpTrustModel¤  ¤   ·pgptrustmodel;
2b2259 ¤   PGPError¤   ¤   ¤   ·err;
3e3a23 ¤   PGPBoolean¤ ¤   ¤   ·fRevoked,
3b4375 ¤   ¤   ¤   ¤   ¤   ¤   ·fExpired,
4a21e0 ¤   ¤   ¤   ¤   ¤   ¤   ·fDisabled;
deaf5a
9d6d02 ¤   (void) context;
52e00f ¤   (void) optionList;
04af5a
01af41 ¤   if( IsntNull( pValidity ) )
f4231e ¤   ¤   *pValidity = kPGPValidity_Unknown;
23af5a
d60ece ¤   pgptrustmodel = pgpTrustModel (ringSetPool (ringSet));
95af5a
--402c 00013ea09b7401001df Page 4 of pgpEncSubr.c
c8c144 ¤   /* First calculate validity level */
e99068 ¤   if (pgptrustmodel == PGPTRUST0) {
cf9132 ¤   ¤   if( IsPGPError( err = PGPGetKeyNumber( key, kPGPKeyPropValidity,
7a2f8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPInt32 *)&validity ) ) )
7eed19 ¤   ¤   ¤   goto error;
fcf037 ¤   } else {
1c2d77 ¤   ¤   /* Not yet supported */
569132 ¤   ¤   if( IsPGPError( err = PGPGetKeyNumber( key, kPGPKeyPropValidity,
4c2f8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPInt32 *)&validity ) ) )
5ded19 ¤   ¤   ¤   goto error;
1f9371 ¤   }
57af5a
9aaf41 ¤   if( IsntNull( pValidity ) )
940d50 ¤   ¤   *pValidity = validity;
85af5a
ae4b4d ¤   if( IsPGPError( err = PGPGetKeyBoolean( key, kPGPKeyPropIsRevoked,
ba06a7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fRevoked ) ) )
7097ed ¤   ¤   goto error;
b14d6f ¤   if( fRevoked ) {
6cb374 ¤   ¤   err = kPGPError_KeyRevoked;
b297ed ¤   ¤   goto error;
019371 ¤   }
3caf5a
8082e4 ¤   if( IsPGPError( err = PGPGetKeyBoolean( key, kPGPKeyPropIsDisabled,
45aded ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fDisabled ) ) )
af97ed ¤   ¤   goto error;
380ebf ¤   if( fDisabled ) {
c4ff57 ¤   ¤   err = kPGPError_KeyDisabled;
a497ed ¤   ¤   goto error;
a09371 ¤   }
e1af5a
7b198d ¤   if( IsPGPError( err = PGPGetKeyBoolean( key, kPGPKeyPropIsExpired,
1fa1b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &fExpired ) ) )
1a97ed ¤   ¤   goto error;
d6a7b2 ¤   if( fExpired ) {
5be1b4 ¤   ¤   err = kPGPError_KeyExpired;
c897ed ¤   ¤   goto error;
bb9371 ¤   }
64af5a
4f3cb1 ¤   if( validity < failValidity ) {
531f3c ¤   ¤   /* Return an error */
1fdc0b ¤   ¤   err = kPGPError_KeyInvalid;
fa97ed ¤   ¤   goto error;
9cb016 ¤   } else if( validity < warnValidity && IsntNull( warnKeySet ) ) {
771e5b ¤   ¤   /* Send a warning */
7f6403 ¤   ¤   PGPKeySet *tmpKeySet;
0fff8e ¤   ¤   if( IsPGPError( err = PGPNewSingletonKeySet( key,
9c1bd7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&tmpKeySet ) ) )
c4ed19 ¤   ¤   ¤   goto error;
653ba0 ¤   ¤   if( IsNull( tmpKeySet ) ) {
5eb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
8eed19 ¤   ¤   ¤   goto error;
e10fe4 ¤   ¤   }
ddcbe7 ¤   ¤   if( IsPGPError( err = PGPAddKeys( tmpKeySet, warnKeySet ) ) )
30ed19 ¤   ¤   ¤   goto error;
1615ad ¤   ¤   if( IsPGPError( err = PGPFreeKeySet( tmpKeySet ) ) )
29ed19 ¤   ¤   ¤   goto error;
419371 ¤   }
e1af5a
ade97f ¤   /* Everything is OK, proceed */
17151e ¤   return kPGPError_NoErr;
31af5a
c760ff error:
d55ea8 ¤   return err;
52efe6 }
9daf5a
0a38e5 /*
25464a ·* Set *outputBufferLen from pipeBuf.
647140 ·* bufferSize is the allocated size of the buffer, and we return an error
1b7c81 ·* if we exceeded the allocated size. ·(We don't actually write beyond
e052a7 ·* the end of the buffer, of course.)
13495d ·*/
--faf8 000326ae738401001df Page 5 of pgpEncSubr.c
e0af5a
01c744 ¤   PGPError
2bdc70 pgpGetMemOutput(
5e9e6e ¤   PGPPipeline¤¤   ¤   *pipeBuf,
da642f ¤   PGPSize¤¤   ¤   ¤   ·bufferSize,
6cb2a7 ¤   PGPSize¤¤   ¤   ¤   *outputBufferLen
e027e6 ¤   )
a7bb36 {
8504df ¤   pgpa( pgpaAddrValid( pipeBuf, PGPPipeline ) );
a7af5a
6a377e ¤   pipeBuf->annotate( pipeBuf, NULL,
105eff ¤   ¤   ¤   ¤   ¤   ···PGPANN_MEM_BYTECOUNT, (PGPByte *)outputBufferLen,
432b83 ¤   ¤   ¤   ¤   ¤   ···sizeof( *outputBufferLen ) );
2b0767 ¤   if( *outputBufferLen > bufferSize )
275264 ¤   ¤   return kPGPError_OutputBufferTooSmall;
9d151e ¤   return kPGPError_NoErr;
ebefe6 }
86af5a
1daf5a
9138e5 /*
f747d1 ·* Set *outputBufferPtr and *outputBufferLen from pipeBuf. ·maxSize
6cfc38 ·* was our limit on the allocated size of the buffer, and we return an
82d3f2 ·* error if we exceeded the max size. ·(We don't actually write more data
b2a8c8 ·* than that into our dynamically allocated buffer, though.) ·The difference
0c2a0b ·* from the above is that in this case the buffer was dynamically allocated
024ba2 ·* while in the previous routine it was a static buffer we were given.
d6495d ·*/
43af5a
a7c744 ¤   PGPError
3ea2d1 pgpGetVariableMemOutput(
369e6e ¤   PGPPipeline¤¤   ¤   *pipeBuf,
f91602 ¤   PGPSize¤¤   ¤   ¤   ·maxSize,
933f61 ¤   PGPByte¤¤   ¤   ···**outputBufferPtr,
9db2a7 ¤   PGPSize¤¤   ¤   ¤   *outputBufferLen
4a27e6 ¤   )
6fbb36 {
9726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5267c5 ¤
6c04df ¤   pgpa( pgpaAddrValid( pipeBuf, PGPPipeline ) );
4caf5a
4127f9 ¤   err¤= pipeBuf->annotate( pipeBuf, NULL,
7ff516 ¤   ¤   ¤   ¤   ·PGPANN_MEM_BYTECOUNT, (PGPByte *)outputBufferLen,
1e2229 ¤   ¤   ¤   ¤   ·sizeof( *outputBufferLen ) );
1df1e7 ¤   if ( IsntPGPError( err ) )
62c7a1 ¤   {
ca0b90 ¤   ¤   pipeBuf->annotate( pipeBuf, NULL,
69ebac ¤   ¤   ¤   PGPANN_MEM_MEMBUF, (PGPByte *)outputBufferPtr,
537e80 ¤   ¤   ¤   sizeof( *outputBufferPtr ) );
209371 ¤   }
e467c5 ¤
34f1e7 ¤   if ( IsntPGPError( err ) )
3fc7a1 ¤   {
66bc92 ¤   ¤   if( *outputBufferLen > maxSize )
296d7c ¤   ¤   ¤   err¤= kPGPError_OutputBufferTooSmall;
c39371 ¤   }
8f1b52 ¤   ¤
ae5ea8 ¤   return err;
e8efe6 }
8caf5a
a0af5a
8f38e5 /*
220681 ·* See if optionList specifies PGPMIME encoding, and if so, get MIME body
35e2b2 ·* offset and return it to caller.
9a495d ·*/
e5c744 ¤   PGPError
5c5afb pgpGetPGPMIMEBodyOffset(
d89e6e ¤   PGPPipeline¤¤   ¤   *pipeBuf,
ec9e21 ¤   PGPOptionListRef¤   ·optionList)
82bb36 {
a995a8 ¤   PGPSize¤¤   ¤   ¤   *mimeBodyOffPtr;
8ece70 ¤   PGPSize¤¤   ¤   ¤   ·mimeBodyOff;
328b04 ¤   char¤   ¤   ¤   ¤   *mimeSeparator;
--8bc7 000f1bc79f8401001df Page 6 of pgpEncSubr.c
79e035 ¤   PGPUInt32¤  ·¤  ¤   ·mimeHeaderLines;
5c582a ¤   PGPUInt32¤  ¤   ¤   ·mimeFlag;
8852bf ¤   PGPUInt32¤  ¤   ¤   ·lineEndFlag;
13f23f ¤   PGPLineEndType¤ ¤   ·lineEnd;
4a7cc4 ¤   PGPUInt32¤  ¤   ¤   ·uintLineEnd;
ee05a0 ¤   PGPError¤   ¤   ¤   ·err = kPGPError_NoErr;
77af5a
847bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
735d04 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_PGPMIMEEncoding, FALSE,
5b8a5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%d%p%p", &mimeFlag, &mimeBodyOffPtr,
b5bc4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&mimeSeparator) ) )
9797ed ¤   ¤   goto error;
bdfd00 ¤   if( mimeFlag ) {
18ec0d ¤   ¤   if( IsntNull( mimeBodyOffPtr ) ) {
dc097a ¤   ¤   ¤   if( IsPGPError( err = pipeBuf->annotate( pipeBuf, NULL,
2b7fb9 ¤   ¤   ¤   ¤   ¤   ·PGPANN_PGPMIME_HEADER_SIZE,
0bd260 ¤   ¤   ¤   ¤   ¤   ·(unsigned char *)&mimeBodyOff, sizeof(mimeBodyOff) ) ) )
e9b5aa ¤   ¤   ¤   ···goto error;
bf8723 ¤   ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
b826a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_OutputLineEndType, FALSE,
bc12ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··"%b%d", &lineEndFlag, &uintLineEnd ) ) )
641b7c ¤   ¤   ¤   ¤   goto error;
abd649 ¤   ¤   ¤   if( lineEndFlag )
0653be ¤   ¤   ¤   ¤   lineEnd = (PGPLineEndType)uintLineEnd;
45bb8c ¤   ¤   ¤   else
8841a2 ¤   ¤   ¤   ¤   lineEnd = pgpGetDefaultLineEndType ();
e9595f ¤   ¤   ¤   if( lineEnd == kPGPLineEnd_CRLF ) {
17470d ¤   ¤   ¤   ¤   if( IsPGPError( err = pipeBuf->annotate( pipeBuf, NULL,
70b1ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPANN_PGPMIME_HEADER_LINES,
db126d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (unsigned char *)&mimeHeaderLines,
18e4db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(mimeHeaderLines) ) ) )
5eb622 ¤   ¤   ¤   ¤   ¤   goto error;
08fcc3 ¤   ¤   ¤   ¤   mimeBodyOff += mimeHeaderLines;
c2a3a6 ¤   ¤   ¤   }
b96b6f ¤   ¤   ¤   *mimeBodyOffPtr = mimeBodyOff;
da0fe4 ¤   ¤   }
d4fb1f ¤   ¤   if( IsntNull( mimeSeparator ) ) {
6b097a ¤   ¤   ¤   if( IsPGPError( err = pipeBuf->annotate( pipeBuf, NULL,
6cd855 ¤   ¤   ¤   ¤   ¤   ·PGPANN_PGPMIME_SEPARATOR,
6f8414 ¤   ¤   ¤   ¤   ¤   ·(unsigned char *)mimeSeparator,
b0514f ¤   ¤   ¤   ¤   ¤   ·kPGPMimeSeparatorSize ) ) )
7c1b7c ¤   ¤   ¤   ¤   goto error;
7e0fe4 ¤   ¤   }
ac9371 ¤   }
5960ff error:
6e5ea8 ¤   return err;
2befe6 }
1baf5a
f0af5a
2baf5a
4caf5a
eb929c /* Line ending control */
8caf5a
34d8b7 ¤   PGPLineEndType
5a28d0 pgpGetDefaultLineEndType ()
b1bb36 {
ab3574 #if defined(PGP_MSDOS) || defined(PGP_WIN32)
b64091 ¤   return kPGPLineEnd_CRLF;
0a5ff3 #elif PGP_MACINTOSH
0e5d0e ¤   return kPGPLineEnd_CR;
5edb21 #else
c60903 ¤   return kPGPLineEnd_LF;
957454 #endif
e6efe6 }
64af5a
adaf5a
0caf5a
b8af5a
2e8343 /* Parse an optionlist structure and extract callback info */
8baf5a
c1c744 ¤   PGPError
f13b02 pgpSetupCallback(
--985c 000969bd040401001df Page 7 of pgpEncSubr.c
6fedf4 ¤   PGPOptionListRef¤   ··optionList,
012c73 ¤   PGPEventHandlerProcPtr *func,¤  ¤   /* Output params */
e5ec44 ¤   PGPUserValue¤   ¤   ·*userValue,
4e9e89 ¤   PGPBoolean¤ ¤   ¤   ·*fNullEvents
2a27e6 ¤   )
42bb36 {
249c27 ¤   PGPError¤   ¤   ¤   ··err;
030d7c ¤   PGPBoolean¤ ¤   ¤   ··lNullEvents;
18af5a
65dec5 ¤   /* Init return data to default states */
2efca8 ¤   pgpa( pgpaAddrValid( func, PGPEventHandlerProcPtr ) );
5f996c ¤   pgpa( pgpaAddrValid( userValue, PGPUserValue ) );
a40749 ¤   pgpa( pgpaAddrValid( fNullEvents, PGPBoolean ) );
058bd0 ¤   *func = NULL;
6be6ed ¤   *userValue = (PGPUserValue)0;
4103f8 ¤   *fNullEvents = FALSE;
5faf5a
657bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
230b14 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_EventHandler, FALSE,
56c636 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%p", func, userValue ) ) )
f897ed ¤   ¤   goto error;
85af5a
aa7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
ccdf4a ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_SendNullEvents, FALSE,
9ed733 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b", &lNullEvents ) ) )
6e97ed ¤   ¤   goto error;
a62e79 ¤   if( lNullEvents ) {
f7249a ¤   ¤   /* Wants notification of null events */
f1b067 ¤   ¤   if( IsNull (*func) ) {
444013 ¤   ¤   ¤   pgpDebugMsg(
83140b ¤   ¤   ¤   ¤   ···"Error: Null events requested without event handler" );
df5820 ¤   ¤   ¤   err = kPGPError_BadParams;
36ed19 ¤   ¤   ¤   goto error;
890fe4 ¤   ¤   }
aa145e ¤   ¤   *fNullEvents = TRUE;
299371 ¤   }
a9151e ¤   return kPGPError_NoErr;
a0af5a
e260ff error:
ce8bd0 ¤   *func = NULL;
93e6ed ¤   *userValue = (PGPUserValue)0;
de03f8 ¤   *fNullEvents = FALSE;
e0af5a
415ea8 ¤   return err;
34efe6 }
b4af5a
b01b52 ¤   ¤
a2af5a
6465bc /* Open input specification if there is one. ·Optionally set up filename
7e80bd ·* literal structure, and seed RNG.
4e495d ·*/
07af5a
d0c744 ¤   PGPError
29bc96 pgpSetupInput(
40476e ¤   PGPContextRef¤  ·¤  ··context,¤ ¤   /* Input params */
94edf4 ¤   PGPOptionListRef¤   ··optionList,
045cf4 ¤   PgpLiteralParams¤   ·*literal,
40a895 ¤   PGPRandomContext¤   ·*rng,
473d48 ¤   PGPBoolean¤ ¤   ¤   ··inputMode,
145cfb ¤   PGPBoolean¤ ¤   ¤   ··detachedSignature,
8341c1 ¤   PFLConstFileSpecRef¤ *inFileRef,¤   /* Output params */
45fe1a ¤   PGPFileRead ········**pfrin,
0c8c3e ¤   PGPFileDataType¤¤   ·*inFileDataType,
8bd0e8 ¤   PGPByte¤¤   ¤   ¤   **inBufPtr,
d31e2a ¤   PGPSize¤¤   ¤   ¤   ·*inBufLength
f427e6 ¤   )
9bbb36 {
10a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
b06ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
84f629 ¤   static char¤¤   ¤   ·fyeomagic[] = "_CONSOLE"; /* Display-only mode */
4d4c77 ¤   PGPUInt32¤  ¤   ¤   ·localEncode;¤  /* Special input encoding (macbin) */
96d34f ¤   PGPFileOpenFlags¤   ·localEncodeFlags;¤ /* Flag form of localEncode */
--a587 0003701664d401001df Page 8 of pgpEncSubr.c
b521a9 ¤   PGPByte const¤  ¤   *peekBuf;¤  ¤   /* For RNG seeding from file */
f6762f ¤   PGPSize¤¤   ¤   ¤   ·peekLength;¤   /* Length of peekBuf */
b4af5a
dbdec5 ¤   /* Init return data to default states */
8780e9 ¤   pgpa( pgpaAddrValid( inFileRef, PFLConstFileSpecRef ) );
8c5c34 ¤   pgpa( pgpaAddrValid( pfrin, PGPFileRead * ) );
e5b265 ¤   pgpa( pgpaAddrValid( inFileDataType, PGPFileDataType ) );
74b9f4 ¤   pgpa( pgpaAddrValid( inBufPtr, PGPByte * ) );
8cc2ec ¤   pgpa( pgpaAddrValid( inBufLength, PGPSize ) );
b6fab8 ¤   *inFileRef = NULL;
0b30da ¤   *pfrin = NULL;
c140eb ¤   *inFileDataType = kPGPFileDataType_Unknown;
3df654 ¤   *inBufPtr = NULL;
1c7297 ¤   *inBufLength = 0;
6cd207 ¤   if( IsntNull( literal) ) {
0d8760 ¤   ¤   pgpa( pgpaAddrValid( literal, PgpLiteralParams ) );
c6caa8 ¤   ¤   literal->filename = NULL;
dca4e9 ¤   ¤   literal->timestamp = ( PGPUInt32 ) 0;
009371 ¤   }
eeaf5a
305423 ¤   if( IsntNull( literal ) ) {
09efd9 ¤   ¤   /* First check "for your eyes only" mode, flag with magic filename */
0cc074 ¤   ¤   PGPUInt32 fFYEO;
085d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
9b1d02 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ForYourEyesOnly, FALSE,
16fcde ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fFYEO ) ) )
f3ed19 ¤   ¤   ¤   goto error;
b4a304 ¤   ¤   if( fFYEO ) {
a0cb4e ¤   ¤   ¤   literal->filename = pgpAllocCString( context, fyeomagic );
710fe4 ¤   ¤   }
dd9371 ¤   }
6daf5a
6fc4b8 ¤   /* See if there is an input file specified */
9f7e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
152027 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_InputFileRef, &op ) ) )
4897ed ¤   ¤   goto error;
617343 ¤   if( IsOp( op ) ) {
5fd399 ¤   ¤   /* File input */
4bed11 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)inFileRef ) ) )
c7ed19 ¤   ¤   ¤   goto error;
6fdfdf ¤   ¤   if( IsntNull( literal ) ) {
d12a17 ¤   ¤   ¤   if( IsNull( literal->filename ) ) {
240a9f ¤   ¤   ¤   ¤   char *filerefname;
55de04 ¤   ¤   ¤   ¤   void *vfilerefname;
350d66 ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
6648e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_InputFileName, FALSE,
64a2db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &vfilerefname ) ) )
8eb622 ¤   ¤   ¤   ¤   ¤   goto error;
fd1dc5 ¤   ¤   ¤   ¤   filerefname = (char *)vfilerefname;
1f55db ¤   ¤   ¤   ¤   if( IsntNull( filerefname ) ) {
7ff92c ¤   ¤   ¤   ¤   ¤   literal->filename = pgpAllocCString( context,
d2c669 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·filerefname );
cdb5fc ¤   ¤   ¤   ¤   } else {
ab0e24 ¤   ¤   ¤   ¤   ¤   filerefname = pgpGetFileRefName( *inFileRef );
d6f92c ¤   ¤   ¤   ¤   ¤   literal->filename = pgpAllocCString( context,
bac669 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·filerefname );
147957 ¤   ¤   ¤   ¤   ¤   PGPFreeData( filerefname );
7f2613 ¤   ¤   ¤   ¤   }
6aa3a6 ¤   ¤   ¤   }
e10fe4 ¤   ¤   }
8d9f02 ¤   ¤   localEncodeFlags = (PGPFileOpenFlags)0;
b394bc ¤   ¤   if( inputMode ) {
7b2e1e ¤   ¤   ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
3b01c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_LocalEncoding, &op ) ) )
201b7c ¤   ¤   ¤   ¤   goto error;
13858a ¤   ¤   ¤   if( IsOp( op ) ) {
b84aec ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpOptionUInt( &op, &localEncode ) ) )
77b622 ¤   ¤   ¤   ¤   ¤   goto error;
816656 ¤   ¤   ¤   ¤   localEncodeFlags = pgpLocalEncodingToFlags( localEncode );
0fa3a6 ¤   ¤   ¤   }
5f0fe4 ¤   ¤   }
37fa11 ¤   ¤   localEncodeFlags |= kPGPFileOpenReadPerm;
--7c21 0008348afcc401001df Page 9 of pgpEncSubr.c
c8f0f1 ¤   ¤   if( detachedSignature) {
d4a352 ¤   ¤   ¤   localEncodeFlags |= kPGPFileOpenLocalEncodeHashOnly;
8d0fe4 ¤   ¤   }
73af5a
d51973 ¤   ¤   /* Open input file */
b0c9a2 ¤   ¤   *pfrin = pgpFileRefReadCreate( context, *inFileRef,
b3ff0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   localEncodeFlags, &err, inFileDataType );
8e8f1b ¤   ¤   if( IsNull( *pfrin ) ) {
9aed19 ¤   ¤   ¤   goto error;
dc0fe4 ¤   ¤   }
3fe479 ¤   ¤   if( IsntNull( rng ) ) {
3511b2 ¤   ¤   ¤   /* Add some data from the file to the RNG for more entropy */
71acc5 ¤   ¤   ¤   peekBuf = pgpFileReadPeek( *pfrin, &peekLength );
8cd335 ¤   ¤   ¤   pgpRandomAddBytes( rng, peekBuf, peekLength );
aa0fe4 ¤   ¤   }
9a9371 ¤   }
82af5a
20a4d0 ¤   /* See if there is a buffer specified */
507e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
2b0f66 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_InputBuffer, &op ) ) )
6d97ed ¤   ¤   goto error;
467343 ¤   if( IsOp( op ) ) {
e9515f ¤   ¤   /* Buffer input */
39fe61 ¤   ¤   if ( IsntNull( *inFileRef ) ) {
6e035c ¤   ¤   ¤   /* Error if buffer input also specified */
d03b5c ¤   ¤   ¤   pgpDebugMsg( "Error: multiple input options" );
325820 ¤   ¤   ¤   err = kPGPError_BadParams;
2aed19 ¤   ¤   ¤   goto error;
a30fe4 ¤   ¤   }
e6dfdf ¤   ¤   if( IsntNull( literal ) ) {
e57aad ¤   ¤   ¤   /*
fb1885 ¤   ¤   ¤   ·* Fake up filename if FYEO mode above didn't set it.
23f6b8 ¤   ¤   ¤   ·* Earlier versions of PGP used the fake filename "stdin".
757089 ¤   ¤   ¤   ·* However this cannot be distinguished from the case where
146249 ¤   ¤   ¤   ·* a file with that name is encrypted. ·We will change to using
26d001 ¤   ¤   ¤   ·* an empty string for this case, if no name was specified.
aa8753 ¤   ¤   ¤   ·*/
432a17 ¤   ¤   ¤   if( IsNull( literal->filename ) ) {
280a9f ¤   ¤   ¤   ¤   char *filerefname;
e5de04 ¤   ¤   ¤   ¤   void *vfilerefname;
f30d66 ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
5748e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_InputFileName, FALSE,
86a2db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &vfilerefname ) ) )
5ab622 ¤   ¤   ¤   ¤   ¤   goto error;
4e1dc5 ¤   ¤   ¤   ¤   filerefname = (char *)vfilerefname;
69f052 ¤   ¤   ¤   ¤   if( IsNull( filerefname ) ) {
37a413 ¤   ¤   ¤   ¤   ¤   filerefname = (char *)"";
3d2613 ¤   ¤   ¤   ¤   }
f3674c ¤   ¤   ¤   ¤   literal->filename = pgpAllocCString( context, filerefname );
38a3a6 ¤   ¤   ¤   }
9a0fe4 ¤   ¤   }
20f2b6 ¤   ¤   if( IsPGPError( err = pgpOptionPtrLength( &op,
ac2fd5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(void **)inBufPtr, inBufLength ) ) )
07ed19 ¤   ¤   ¤   goto error;
b9e479 ¤   ¤   if( IsntNull( rng ) ) {
901214 ¤   ¤   ¤   /* Pre-seed RNG with some entropy from buffer */
de2ed4 ¤   ¤   ¤   pgpRandomAddBytes( rng, *inBufPtr, pgpMin( 1024, *inBufLength ) );
720fe4 ¤   ¤   }
d19371 ¤   }
d5af5a
768a9a ¤   /* Must have some input */
fb7b71 ¤   if ( IsNull( *inBufPtr ) && IsNull( *inFileRef ) ) {
685769 ¤   ¤   pgpDebugMsg( "Error: no input options" );
9319d3 ¤   ¤   err = kPGPError_BadParams;
5997ed ¤   ¤   goto error;
5a9371 ¤   }
da151e ¤   return kPGPError_NoErr;
78af5a
e160ff error:
14fab8 ¤   *inFileRef = NULL;
766b6e ¤   if( IsntNull( *pfrin ) ) {
83c963 ¤   ¤   pgpFileReadDestroy( *pfrin );
--6ea3 000389980d5401001df Page 10 of pgpEncSubr.c
580b33 ¤   ¤   *pfrin = NULL;
c59371 ¤   }
39f654 ¤   *inBufPtr = NULL;
0d7297 ¤   *inBufLength = 0;
485423 ¤   if( IsntNull( literal ) ) {
36b128 ¤   ¤   if( IsntNull( literal->filename ) ) {
be52a8 ¤   ¤   ¤   pgpContextMemFree( context, (char *)literal->filename );
8225db ¤   ¤   ¤   literal->filename = NULL;
960fe4 ¤   ¤   }
b99371 ¤   }
7f5ea8 ¤   return err;
4aefe6 }
8caf5a
45af5a
b8af5a
9baf5a
7faf5a
0c6883 /* Set up output file pipeline */
65af5a
d0c744 ¤   PGPError
67ecb4 pgpSetupOutputPipeline(
0b476e ¤   PGPContextRef¤  ·¤  ··context,¤ ¤   /* Input params */
dfedf4 ¤   PGPOptionListRef¤   ··optionList,
a84aa6 ¤   PGPEnv¤ ¤   ¤   ¤   ·*env,
611e13 ¤   PGPBoolean¤ ¤   ¤   ··fEncrypt,
b37d3e ¤   PGPBoolean¤ ¤   ¤   ··fSign,
850020 ¤   PGPBoolean¤ ¤   ¤   ··fDetachedSig,
53aae3 ¤   PGPBoolean¤ ¤   ¤   ··fAppendOutput,
4ba6e7 ¤   PGPPipeline¤¤   ···***tail,¤¤   ¤   /* Input/output param */
262692 ¤   PFLConstFileSpecRef¤ *outFileRef,¤  /* Output params */
02c18b ¤   PGPFile¤¤   ¤   ¤   ·**pfout,
2c0310 ¤   PGPByte¤¤   ¤   ¤   **outBufPtr,
ad9909 ¤   PGPByte¤¤   ¤   ···***outBufPtrPtr,
1ece07 ¤   PGPSize¤¤   ¤   ¤   ·*outBufLength,
dda685 ¤   PGPSize¤¤   ¤   ¤   **outBufUsed,
2bfc4f ¤   PGPPipeline¤¤   ¤   **outPipe
9627e6 ¤   )
63bb36 {
2ea22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
ac6ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
4399ad ¤   PGPFileType¤¤   ¤   ·filetype;¤ ¤   /* Type of output file we open */
eb2d0d ¤   PGPUInt32¤  ¤   ¤   ·fDiscard;¤ ¤   /* Discard output option flag */
4e4676 ¤   PGPBoolean¤ ¤   ¤   ·fArmor;¤   ¤   /* Ascii armor */
01dc05 ¤   PGPMemoryMgrRef¤¤   memoryMgr¤  = NULL;
0eaf5a
fbdec5 ¤   /* Init return data to default states */
652c54 ¤   pgpa( pgpaAddrValid( outFileRef, PFLConstFileSpecRef ) );
a50257 ¤   pgpa( pgpaAddrValid( pfout, PGPFile * ) );
6d0fed ¤   pgpa( pgpaAddrValid( outBufPtr, PGPByte * ) );
4d4f1a ¤   pgpa( pgpaAddrValid( outBufLength, PGPSize ) );
df1ecf ¤   pgpa( pgpaAddrValid( outBufUsed, PGPSize * ) );
25febe ¤   pgpa( pgpaAddrValid( outPipe, PGPPipeline * ) );
9c9837 ¤   *outFileRef = NULL;
1fdf42 ¤   *pfout = NULL;
b57725 ¤   *outBufPtr = NULL;
73f3e6 ¤   *outBufLength = 0;
3f6016 ¤   *outBufUsed = NULL;
ca99f2 ¤   *outPipe = NULL;
bd67c5 ¤
2f9cc2 ¤   memoryMgr¤  = PGPGetContextMemoryMgr( context );
d8af5a
f8c248 ¤   /* See if there is an output file specified */
077e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
1d0c29 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputFileRef, &op ) ) )
0897ed ¤   ¤   goto error;
caaf5a
337343 ¤   if( IsOp( op ) ) {
b64ada ¤   ¤   /* Have an output file specified */
77434d ¤   ¤   PGPFileOpenFlags flags;
52af5a
b70216 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)outFileRef ) ) )
38ed19 ¤   ¤   ¤   goto error;
--26ed 0005de628d3401001df Page 11 of pgpEncSubr.c
e0af5a
824adb ¤   ¤   /* See whether we are outputing an encrypted vs ascii armored file */
8b8c72 ¤   ¤   fArmor = pgpenvGetInt( env, PGPENV_ARMOR, NULL, NULL );
a7009f ¤   ¤   if( fArmor) {
388829 ¤   ¤   ¤   filetype = kPGPFileTypeArmorFile;
c6f899 ¤   ¤   } else if( fEncrypt ) {
a97038 ¤   ¤   ¤   filetype = kPGPFileTypeEncryptedData;
eb9748 ¤   ¤   } else if( fSign ) {
8efc60 ¤   ¤   ¤   if( fDetachedSig ) {
bf57eb ¤   ¤   ¤   ¤   filetype = kPGPFileTypeDetachedSig;
ee042d ¤   ¤   ¤   } else {
d14c7a ¤   ¤   ¤   ¤   filetype = kPGPFileTypeSignedData;
87a3a6 ¤   ¤   ¤   }
2c45a6 ¤   ¤   } else {
e7102f ¤   ¤   ¤   filetype = kPGPFileTypeNone;
790fe4 ¤   ¤   }
dbaf5a
97657b ¤   ¤   /* Open output file */
d9c456 ¤   ¤   flags = fAppendOutput ? kPGPFileOpenStdAppendFlags :
38f0df ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPFileOpenStdWriteFlags ;
965f70 ¤   ¤   *pfout = pgpFileRefOpen( context, *outFileRef, flags, filetype, &err );
1c6acb ¤   ¤   if( IsNull( *pfout ) ) {
95ed19 ¤   ¤   ¤   goto error;
350fe4 ¤   ¤   }
e71b52 ¤   ¤
e80f39 ¤   ¤   /* Set up output pipeline. ·This reads and writes *tail. */
082678 ¤   ¤   if( IsNull( pgpFileWriteCreate( context,
4db19b ¤   ¤   ¤   ¤   ¤   *tail, *pfout, 1 ) ) ) {
76b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
8eed19 ¤   ¤   ¤   goto error;
930fe4 ¤   ¤   }
5d9371 ¤   }
3faf5a
8f4fcf ¤   /* See if there is an output buffer specified */
167e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
896b9b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputBuffer, &op ) ) )
f897ed ¤   ¤   goto error;
48af5a
657343 ¤   if( IsOp( op ) ) {
776d62 ¤   ¤   /* Have an output buffer specified */
c3f865 ¤   ¤   if( IsntNull( *outFileRef ) ) {
edbc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
f15820 ¤   ¤   ¤   err = kPGPError_BadParams;
40ed19 ¤   ¤   ¤   goto error;
820fe4 ¤   ¤   }
6b67c5 ¤
61a152 ¤   ¤   if( IsPGPError( err = pgpOptionPtrLengthPtr( &op, (void **)outBufPtr,
c20416 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outBufLength, (void **)outBufUsed ) ) )
36ed19 ¤   ¤   ¤   goto error;
efaf5a
867977 ¤   ¤   *outPipe = pgpMemModCreate( context, *tail, (char *) *outBufPtr,
15c902 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *outBufLength);
a9aa90 ¤   ¤   if ( IsNull( *outPipe ) ) {
3ba75f ¤   ¤   ¤   err = kPGPError_OutOfMemory; /* What else could it be? */
66ed19 ¤   ¤   ¤   goto error;
f90fe4 ¤   ¤   }
d59dbc ¤   ¤   if( fAppendOutput ) {
de41f2 ¤   ¤   ¤   /* Skip past existing buffer contents */
327433 ¤   ¤   ¤   if( IsPGPError( err = (*outPipe)->annotate( *outPipe, NULL,
aba2ed ¤   ¤   ¤   ¤   ¤   ·PGPANN_MEM_PREPEND,
0e5f04 ¤   ¤   ¤   ¤   ¤   ·(unsigned char *)*outBufPtr, **outBufUsed ) ) )
3b1b7c ¤   ¤   ¤   ¤   goto error;
120fe4 ¤   ¤   }
2f9371 ¤   }
51af5a
e72c97 ¤   /* Check for variable-sized output buffer specification */
407e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
88eabc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputAllocatedBuffer, &op ) ) )
9797ed ¤   ¤   goto error;
2daf5a
b57343 ¤   if( IsOp( op ) ) {
5d6d62 ¤   ¤   /* Have an output buffer specified */
--4a5e 000f45324c5401001df Page 12 of pgpEncSubr.c
4694c9 ¤   ¤   if( IsntNull( *outFileRef ) || IsntNull( *outBufPtr ) ) {
4ebc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
9f5820 ¤   ¤   ¤   err = kPGPError_BadParams;
0bed19 ¤   ¤   ¤   goto error;
b60fe4 ¤   ¤   }
4d67c5 ¤
c105a6 ¤   ¤   if( IsPGPError( err = pgpOptionPtrLengthPtr( &op,
17a505 ¤   ¤   ¤   ¤   (void **)outBufPtrPtr, outBufLength, (void **)outBufUsed ) ) )
4bed19 ¤   ¤   ¤   goto error;
26af5a
9ba490 ¤   ¤   *outPipe = pgpVariableMemModCreate( context,
929c74 ¤   ¤   ¤   ¤   ¤   ¤   *tail, *outBufLength );
7caa90 ¤   ¤   if ( IsNull( *outPipe ) ) {
99a75f ¤   ¤   ¤   err = kPGPError_OutOfMemory; /* What else could it be? */
2aed19 ¤   ¤   ¤   goto error;
6a0fe4 ¤   ¤   }
dc5592 ¤   ¤   if( fAppendOutput && **outBufUsed != 0 ) {
870581 ¤   ¤   ¤   /* Prepend existing buffer contents */
407433 ¤   ¤   ¤   if( IsPGPError( err = (*outPipe)->annotate( *outPipe, NULL,
eba2ed ¤   ¤   ¤   ¤   ¤   ·PGPANN_MEM_PREPEND,
9b3018 ¤   ¤   ¤   ¤   ¤   ·(unsigned char *)**outBufPtrPtr, **outBufUsed ) ) )
891b7c ¤   ¤   ¤   ¤   goto error;
8ba798 ¤   ¤   ¤   /* Free buffer now that we have captured it */
169c94 ¤   ¤   ¤   PGPFreeData( **outBufPtrPtr );
66836e ¤   ¤   ¤   **outBufPtrPtr = NULL;
1f0fe4 ¤   ¤   }
be9371 ¤   }
7faf5a
947bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
1018f3 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_DiscardOutput, FALSE,
78c0c9 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fDiscard ) ) )
bf97ed ¤   ¤   goto error;
573513 ¤   if( fDiscard ) {
02493b ¤   ¤   /* User wants to go to /dev/null */
d5e29d ¤   ¤   if( IsntNull( *outFileRef ) || IsntNull( *outBufPtr ) ||
afcf45 ¤   ¤   ¤   IsntNull( *outBufPtrPtr ) ) {
b4bc03 ¤   ¤   ¤   pgpDebugMsg( "Error: multiple output options" );
8b5820 ¤   ¤   ¤   err = kPGPError_BadParams;
93ed19 ¤   ¤   ¤   goto error;
5f0fe4 ¤   ¤   }
24538e ¤   ¤   if ( IsNull( pgpDevNullCreate( context, *tail ) ) ) {
fda75f ¤   ¤   ¤   err = kPGPError_OutOfMemory; /* What else could it be? */
7aed19 ¤   ¤   ¤   goto error;
ec0fe4 ¤   ¤   }
6418bc ¤   } else if( IsNull( *outFileRef ) && IsNull( *outBufPtr )
8ae793 ¤   ¤   ¤   ···¤¤   ¤   ¤   ¤   ¤   ·&& IsNull( *outBufPtrPtr ) ) {
b1da41 ¤   ¤   pgpDebugMsg( "Error: no output options" );
f519d3 ¤   ¤   err = kPGPError_BadParams;
6297ed ¤   ¤   goto error;
4a9371 ¤   }
45151e ¤   return kPGPError_NoErr;
e9af5a
e960ff error:
07af5a
889837 ¤   *outFileRef = NULL;
fe8ebe ¤   if( IsntNull( *pfout ) ) {
ed5383 ¤   ¤   pgpFileClose( *pfout );
b6e4ab ¤   ¤   *pfout = NULL;
8d9371 ¤   }
557725 ¤   *outBufPtr = NULL;
edfbc3 ¤   *outBufPtrPtr = NULL;
1ff3e6 ¤   *outBufLength = 0;
7099f2 ¤   *outPipe = NULL;
520c50 ¤   return err;·
c2efe6 }
3aaf5a
a3af5a
7faf5a
72af5a
397e4d /*__Editor_settings____
9caf5a
f44126 ¤   Local Variables:
--cbdd 001d090f0b5401001df Page 13 of pgpEncSubr.c
2f7b17 ¤   tab-width: 4
030e6c ¤   End:
9e5f8c ¤   vi: ts=4 sw=4
269e9b ¤   vim: si
d0d062 _____________________*/
--7f61 00021eef53c401001e0 Page 1 of pgpEncode.c
a70335 /*____________________________________________________________________________
fa9abe ¤   pgpEncode.c
a43ebe ¤   High level encode functionality
4667c5 ¤
a4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
924b0f ¤   All rights reserved.
7267c5 ¤
0467c5 ¤
8aaf5a
f0b96d ¤   $Id: pgpEncode.c,v 1.92.2.2.2.1 1998/11/12 03:21:39 heller Exp $
6af7f7 ____________________________________________________________________________*/
95d224 #include "pgpConfig.h"¤ /* or pgpConfig.h in the CDK */
7daf5a
12324c #include <string.h>
9baf5a
e0eb3d /* Public headers */
35e82c #include "pgpPubTypes.h"
94c26c #include "pgpContext.h"
989f63 #include "pgpEncode.h"
c82f8d #include "pgpErrors.h"
6da076 #include "pgpKeys.h"
4c0d08 #include "pgpMem.h"
53af5a
2b622b /* Private headers */
caa146 #include "pgpDebug.h"
198b0d #include "pgpEncodePriv.h"
67f476 #include "pgpArmor.h"
90e8f7 #include "pgpBufMod.h"
ab0e2f #include "pgpSymmetricCipherPriv.h"
a227ba #include "pgpConvKey.h"
9e115d #include "pgpDevNull.h"
329906 #include "pgpEncPipe.h"
c40d6d #include "pgpEnv.h"
962d40 #include "pgpEventPriv.h"
f372de #include "pgpFile.h"
b63709 #include "pgpFileMod.h"
8da4b2 #include "pgpFileRef.h"
75894b #include "pgpFileSpec.h"
3639d3 #include "pgpFileType.h"
c89f72 #include "pgpHash.h"
fe711b #include "pgpKeyDB.h"
ce979a #include "pgpKDBInt.h"
a90d08 #include "pgpMem.h"
3b1dd3 #include "pgpMemMod.h"
a1fb31 #include "pgpOptionList.h"
5c2ece #include "pgpPipeline.h"
59cdc2 #include "pgpPubKey.h"
77adc0 #include "pgpRandomPoolPriv.h"
eec77e #include "pgpRndSeed.h"
e126e3 #include "pgpRngPub.h"
70f5ab #include "pgpSigSpec.h"
f53576 #include "pgpTextFilt.h"
97ae6d #include "pgpTrstPkt.h"
a645ee #include "pgpVMemMod.h"
d2af5a
74d622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
0eaf5a
2ba276 /*********************** Helper functions for below ************************/
4eaf5a
f1af5a
c6f7cc /* Set up PGPEnv structure for library internals */
3baf5a
c666dd ¤   static PGPError
65a562 pgpMakeEnvFromOptionList(
c0e099 ¤   PGPOptionListRef¤   ·optionList,
acc9aa ¤   PGPEnv¤ ¤   ¤   ¤   *env
ca27e6 ¤   )
74bb36 {
3533fd ¤   PGPError¤   ¤   ·err;¤  ¤   ¤   ¤   /* Error flag */
493044 ¤   PGPUInt32¤  ¤   ·hashalg;¤  ¤   ¤   /* Default hash alg */
51d052 ¤   PGPUInt32¤  ¤   ·cipheralg;¤¤   ¤   /* Default cipher alg */
2167a1 ¤   PGPUInt32¤  ¤   ·fOption;¤  ¤   ¤   /* Generic option flag */
--b999 000f71f720b401001e0 Page 2 of pgpEncode.c
2d9a14 ¤   PGPBoolean¤ ¤   ·fDefault;¤ ¤   ¤   /* True if have the option from usr */
fbe68e ¤   char¤   ¤   ¤   *comment;¤  ¤   ¤   /* Comment string for output */
62c83a ¤   char¤   ¤   ¤   *version;¤  ¤   ¤   /* Version string for output */
65af5a
322264 ¤   /* Ascii armor mode */
d77bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
f8c9e1 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ArmorOutput, FALSE,
491b87 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fOption ) ) )
1397ed ¤   ¤   goto error;
b07193 ¤   pgpenvSetInt( env, PGPENV_ARMOR, fOption, PGPENV_PRI_FORCE );
feaf5a
3750fe ¤   /* Text mode (as compared to binary) */
4e7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
ce7b09 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_DataIsASCII, FALSE,
ff1b87 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fOption ) ) )
7997ed ¤   ¤   goto error;
dd19e8 ¤   pgpenvSetInt( env, PGPENV_TEXTMODE, fOption, PGPENV_PRI_FORCE );
4daf5a
2786a1 ¤   /* Control of compression (default on) */
ff7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
850aea ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Compression, FALSE,
0f04a5 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &fDefault, &fOption ) ) )
0e97ed ¤   ¤   goto error;
7171e0 ¤   if( !fDefault )
05a9cf ¤   ¤   fOption = TRUE;
cc69d6 ¤   pgpenvSetInt( env, PGPENV_COMPRESS, fOption, PGPENV_PRI_FORCE );
20af5a
60901e ¤   /* Clearsign mode, implies textmode and ascii armor */
837bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
4995c2 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ClearSign, FALSE,
f81b87 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fOption ) ) )
6997ed ¤   ¤   goto error;
e18371 ¤   if( fOption ) {
f044d8 ¤   ¤   pgpenvSetInt( env, PGPENV_CLEARSIG, TRUE, PGPENV_PRI_FORCE );
67e2f7 ¤   ¤   pgpenvSetInt( env, PGPENV_TEXTMODE, TRUE, PGPENV_PRI_FORCE );
b6e136 ¤   ¤   pgpenvSetInt( env, PGPENV_ARMOR, TRUE, PGPENV_PRI_FORCE );
16f037 ¤   } else {
2ecf47 ¤   ¤   pgpenvSetInt( env, PGPENV_CLEARSIG, FALSE, PGPENV_PRI_FORCE );
ea9371 ¤   }
53af5a
481c42 ¤   /* PGP-MIME output, implies ascii armor */
207bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
6c606a ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_PGPMIMEEncoding, FALSE,
4e04a5 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &fDefault, &fOption ) ) )
ac97ed ¤   ¤   goto error;
8c3e01 ¤   if( fDefault ) {
64c212 ¤   ¤   pgpenvSetInt( env, PGPENV_PGPMIME, fOption, PGPENV_PRI_FORCE );
1ee136 ¤   ¤   pgpenvSetInt( env, PGPENV_ARMOR, TRUE, PGPENV_PRI_FORCE );
869371 ¤   }
a27bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
dbe300 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OmitMIMEVersion, FALSE,
7e1b87 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fOption ) ) )
a197ed ¤   ¤   goto error;
f6ee95 ¤   pgpenvSetInt( env, PGPENV_PGPMIMEVERSIONLINE, !fOption, PGPENV_PRI_FORCE );
d9af5a
bcc223 ¤   /* Non-default hash algorithm */
567bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
95e1c4 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_HashAlgorithm, FALSE,
c867f4 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &fDefault, &hashalg ) ) )
d397ed ¤   ¤   goto error;
b23e01 ¤   if( fDefault ) {
509e52 ¤   ¤   pgpenvSetInt( env, PGPENV_HASH, hashalg, PGPENV_PRI_FORCE );
cd9371 ¤   }
e8af5a
29c1b2 ¤   /* Non-default cipher algorithm - only effective with conv encr */
e57bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
46185d ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_CipherAlgorithm, FALSE,
fe19c4 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &fDefault, &cipheralg ) ) )
5f97ed ¤   ¤   goto error;
813e01 ¤   if( fDefault ) {
c646e1 ¤   ¤   if( IsNull( pgpCipherGetVTBL ( (PGPCipherAlgorithm)cipheralg ) ) ) {
f753a0 ¤   ¤   ¤   pgpDebugMsg( "Unsupported cipher algorithm" );
--95c2 00020303a8a401001e0 Page 3 of pgpEncode.c
82df78 ¤   ¤   ¤   err = kPGPError_FeatureNotAvailable;
d1ed19 ¤   ¤   ¤   goto error;
9a0fe4 ¤   ¤   }
f8e2d8 ¤   ¤   pgpenvSetInt( env, PGPENV_CIPHER, cipheralg, PGPENV_PRI_FORCE );
f49371 ¤   }
1daf5a
1d11f0 ¤   /* Comment string */
0d7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
3585a0 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_CommentString, FALSE,
854e02 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%p", &fDefault, &comment ) ) )
ec97ed ¤   ¤   goto error;
5f3e01 ¤   if( fDefault ) {
1f6029 ¤   ¤   pgpenvSetString( env, PGPENV_COMMENT, comment, PGPENV_PRI_FORCE );
339371 ¤   }
c9af5a
2111f0 ¤   /* Comment string */
a27bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e89e81 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_VersionString, FALSE,
6f7f63 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%p", &fDefault, &version ) ) )
9897ed ¤   ¤   goto error;
ff3e01 ¤   if( fDefault ) {
0d028d ¤   ¤   pgpenvSetString( env, PGPENV_VERSION_STRING,
2e7112 ¤   ¤   ¤   ¤   ¤   ¤   ·version, PGPENV_PRI_FORCE );
629371 ¤   }
ca151e ¤   return kPGPError_NoErr;
62af5a
4c60ff error:
c65ea8 ¤   return err;
6aefe6 }
fcaf5a
d5af5a
17af5a
11af5a
57af5a
87a1f8 /* Preferred algorithm calculations */
44af5a
7da202 /* Data structure to record preferences of recipients */
32c3ec struct PGPPreferredAlgs_ {
b8a37f ¤   PGPUInt32¤  ¤   ·n;¤¤   ¤   ¤   ¤   /* Number of algorithms */
3f7b10 ¤   PGPByte¤¤   ¤   *algok;¤¤   ¤   ¤   /* # recips who can accept this */
dcca0c ¤   PGPUInt32¤  ¤   *votes;¤¤   ¤   ¤   /* Preference voting, lower=better */
d5d394 ¤   PGPUInt32¤  ¤   counts;¤¤   ¤   ¤   /* Number of recips */
2582f7 };
c680b7 typedef struct PGPPreferredAlgs_ PGPPreferredAlgs;
83af5a
84af5a
d75219 /* Init the structure we will use to choose the conv encryption alg */
01af5a
a666dd ¤   static PGPError
127019 pgpInitPreferredAlgorithms(
7572f7 ¤   PGPContextRef¤  ·¤  ·context,
b6e82d ¤   PGPPreferredAlgs¤   *algInfo
5a27e6 ¤   )
4cbb36 {
577a80 ¤   PGPUInt32¤  ¤   ¤   n;
148f52 ¤   PGPError¤   ¤   ¤   err;
72af5a
064e9c ¤   pgpa( pgpaAddrValid( algInfo, PGPPreferredAlgs ) );
6daf5a
d7e33f ¤   pgpClearMemory( algInfo, sizeof( *algInfo ) );
5b67c5 ¤
9d1abc ¤   n = kPGPNumPossibleCipherAlgorithms;
8567c5 ¤
300242 ¤   algInfo->n = n;
217c3a ¤   algInfo->algok = (PGPByte *)pgpContextMemAlloc( context, n, 0 );
428335 ¤   if ( IsNull( algInfo->algok ) ) {
32bce1 ¤   ¤   err = kPGPError_OutOfMemory;
3b97ed ¤   ¤   goto error;
9e9371 ¤   }
81d6e0 ¤   algInfo->votes = (PGPUInt32 *)
bd5227 ¤   ¤   pgpContextMemAlloc( context, n * sizeof( PGPUInt32 ), 0 );
20de09 ¤   if ( IsNull( algInfo->votes ) ) {
--0876 0008c9e5cd5401001e0 Page 4 of pgpEncode.c
e1bce1 ¤   ¤   err = kPGPError_OutOfMemory;
9097ed ¤   ¤   goto error;
da9371 ¤   }
aa68cb ¤   pgpClearMemory( algInfo->algok, n );
836eef ¤   pgpClearMemory( algInfo->votes, n * sizeof( PGPUInt32 ) );
05151e ¤   return kPGPError_NoErr;
1baf5a
aa60ff error:
035fde ¤   if( IsntNull( algInfo->algok ) )
8bba37 ¤   ¤   pgpContextMemFree( context, algInfo->algok );
e7c469 ¤   if( IsntNull( algInfo->votes ) )
60fc58 ¤   ¤   pgpContextMemFree( context, algInfo->votes );
d05ea8 ¤   return err;
a8efe6 }
f667c5 ¤
4938e5 /*
8f4382 ·* Add info for the preferred algs for one recipient. ··We record which algs
0622ef ·* are acceptable and then use preference voting.
19495d ·*/
83af5a
df66dd ¤   static PGPError
800247 pgpCheckPreferredAlgorithms(
ec22b6 ¤   PGPPreferredAlgs¤   *algInfo,
84ddfd ¤   PGPKey¤ ¤   ¤   ¤   *key,
ae528a ¤   RingSet const¤  ¤   *ringSet
7827e6 ¤   )
24bb36 {
cb73af ¤   RingObject¤ ¤   ¤   *ringObj;
f1ea93 ¤   PGPByte const¤  ¤   *prefs;
da5790 ¤   PGPSize¤¤   ¤   ¤   ·plen;
916c3d ¤   PGPByte¤¤   ¤   ¤   ·algDefault[3];
cd2a44 ¤   PGPByte¤¤   ¤   ¤   ·alg;
deb312 ¤   PGPUInt32¤  ¤   ¤   ·i;
cd2259 ¤   PGPError¤   ¤   ¤   ·err;
62af5a
48af5a
892f23 ¤   if( IsPGPError( err = pgpGetKeyRingObject( key, TRUE, &ringObj ) ) )
4897ed ¤   ¤   goto error;
acaf5a
1b8e7d ¤   prefs = ringKeyFindSubpacket (ringObj, ringSet,
3c1447 ¤   ¤   ¤   ¤   ¤   SIGSUB_PREFERRED_ENCRYPTION_ALGS,
51ecd9 ¤   ¤   ¤   ¤   ¤   0, &plen, NULL, NULL, NULL, NULL, &err);
3ccb0d ¤   if( IsNull( prefs ) ) {
efff1b ¤   ¤   /* Use a default. ·RSA keys get IDEA, later get CAST. ·*/
a5290a ¤   ¤   PGPByte pkalg;
f667b7 ¤   ¤   ringKeyID8 (ringSet, ringObj, &pkalg, NULL);
fee022 ¤   ¤   if (pkalg <= kPGPPublicKeyAlgorithm_RSA+2) {
1ef02c ¤   ¤   ¤   algDefault[0] = kPGPCipherAlgorithm_IDEA;
4b0ea1 ¤   ¤   ¤   prefs = algDefault;
6b88f4 ¤   ¤   ¤   plen = 1;
2245a6 ¤   ¤   } else {
fc245b ¤   ¤   ¤   algDefault[0] = kPGPCipherAlgorithm_CAST5;
4e3518 ¤   ¤   ¤   algDefault[1] = kPGPCipherAlgorithm_IDEA;
88ae77 ¤   ¤   ¤   algDefault[2] = kPGPCipherAlgorithm_3DES;
8f0ea1 ¤   ¤   ¤   prefs = algDefault;
163d4c ¤   ¤   ¤   plen = 3;
d80fe4 ¤   ¤   }
be9371 ¤   }
cdaf5a
b7c77d ¤   ++algInfo->counts;
ca11ef ¤   for( i=0; i<plen; ++i ) {
759cd7 ¤   ¤   alg = prefs[i];
2a06c6 ¤   ¤   if( alg > algInfo->n )
7717f5 ¤   ¤   ¤   continue;
82aef5 ¤   ¤   algInfo->votes[alg-1] += i;¤ ·/* Preference voting, lower=better */
2ec49d ¤   ¤   ++algInfo->algok[alg-1];
6c9371 ¤   }
6c151e ¤   return kPGPError_NoErr;
6a60ff error:
955ea8 ¤   return err;
4defe6 }
8caf5a
--59f1 0008c87e15c401001e0 Page 5 of pgpEncode.c
e0af5a
d338e5 /*
5a244f ·* Choose the most popular algorithm of those which were acceptable to all,
74131b ·* taking into consideration sender preferences if any
3f495d ·*/
8caf5a
7c66dd ¤   static PGPError
015edb pgpSetPreferredAlgorithm(
2ce099 ¤   PGPOptionListRef¤   ·optionList,
7c22b6 ¤   PGPPreferredAlgs¤   *algInfo,
9ac9aa ¤   PGPEnv¤ ¤   ¤   ¤   *env
ba27e6 ¤   )
47bb36 {
5656ae ¤   PGPUInt32¤  ¤   ¤   ·bestvote = 0;¤ /* Silence warning */
a4daa7 ¤   PGPUInt32¤  ¤   ¤   ·bestalg = 0;
47b312 ¤   PGPUInt32¤  ¤   ¤   ·i;
c34125 ¤   PGPUInt32¤  ¤   ¤   ·algsOK = 0;¤   /* Number of acceptable algs */
8bdc56 ¤   PGPCipherAlgorithm¤ *prefalg;
d8f882 ¤   PGPCipherAlgorithm¤ ·alg;
60d122 ¤   PGPSize¤¤   ¤   ¤   ·prefalgLength;
3605a0 ¤   PGPError¤   ¤   ¤   ·err = kPGPError_NoErr;
ccaf5a
b92b14 ¤   /* See if sender has a preferred algorithm specification */
c57bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e26318 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PreferredAlgorithms, FALSE,
616b6a ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &prefalg, &prefalgLength ) ) )
0497ed ¤   ¤   goto error;
733597 ¤   /* Convert prefalgLength from bytes to number of entries */
d3f6ad ¤   prefalgLength /= sizeof(PGPCipherAlgorithm);
6767c5 ¤
692c7f ¤   /* If so, let sender have a veto vote too */
58a87a ¤   if( prefalgLength != 0 ) {
5a259c ¤   ¤   ++algInfo->counts;
d3a251 ¤   ¤   for( i=0; i<prefalgLength; ++i ) {
2f982b ¤   ¤   ¤   alg = prefalg[i];
5bc4ec ¤   ¤   ¤   if( (PGPUInt32)alg > algInfo->n )
6dd040 ¤   ¤   ¤   ¤   continue;
89f9f5 ¤   ¤   ¤   ++algInfo->algok[alg-1];
a0d42d ¤   ¤   ¤   /* Don't bother with a preference vote, handled below */
e50fe4 ¤   ¤   }
ac9371 ¤   }
06af5a
07a37a ¤   /* Loop for all algorithms we know about, see how many are OK */
26c58f ¤   for( i=0; i<algInfo->n; ++i ) {
19d248 ¤   ¤   if( algInfo->algok[i] == algInfo->counts ) {
83e4d5 ¤   ¤   ¤   /* This algorithm was acceptable to all */
86dcf5 ¤   ¤   ¤   /* Skip if not supported by this library */
583799 ¤   ¤   ¤   if( IsNull( pgpCipherGetVTBL( (PGPCipherAlgorithm)(i+1) ) ) )
75d040 ¤   ¤   ¤   ¤   continue;
144e85 ¤   ¤   ¤   algsOK += 1;
8c542e ¤   ¤   ¤   if (prefalgLength != 0) {
be7a9f ¤   ¤   ¤   ¤   PGPUInt32 j;
be4f2f ¤   ¤   ¤   ¤   /* Choose acceptable algorithm which sender likes best */
5c8a9e ¤   ¤   ¤   ¤   for( j=0; j<prefalgLength; ++j ) {
318940 ¤   ¤   ¤   ¤   ¤   if (prefalg[j] == (PGPCipherAlgorithm)(i+1))
0600eb ¤   ¤   ¤   ¤   ¤   ¤   break;
2a2613 ¤   ¤   ¤   ¤   }
0c19e1 ¤   ¤   ¤   ¤   pgpAssert (j < prefalgLength);
f022d3 ¤   ¤   ¤   ¤   if( bestalg == 0 || j < bestvote ) {
0fa635 ¤   ¤   ¤   ¤   ¤   /* First acceptable, or best one so far */
3b551f ¤   ¤   ¤   ¤   ¤   bestvote = j;
c99313 ¤   ¤   ¤   ¤   ¤   bestalg = i+1;
c72613 ¤   ¤   ¤   ¤   }
f6042d ¤   ¤   ¤   } else {
928f81 ¤   ¤   ¤   ¤   /* Case of no sender preferences, choose favorite of others */
8656d8 ¤   ¤   ¤   ¤   if( bestalg == 0 ·|| ·algInfo->votes[i] < bestvote ) {
eda635 ¤   ¤   ¤   ¤   ¤   /* First acceptable, or best one so far */
85a63a ¤   ¤   ¤   ¤   ¤   bestvote = algInfo->votes[i];
359313 ¤   ¤   ¤   ¤   ¤   bestalg = i+1;
cd2613 ¤   ¤   ¤   ¤   }
cda3a6 ¤   ¤   ¤   }
8c0fe4 ¤   ¤   }
--7f64 000f2c6d8ec401001e0 Page 6 of pgpEncode.c
a19371 ¤   }
93af5a
a9af5a
ac138e ¤   /* If no choice OK for all, choose sender's favorite if any */
d860f7 ¤   if (algsOK == 0 && prefalgLength != 0) {
ec45be ¤   ¤   for (i=0; i<prefalgLength; ++i) {
2da756 ¤   ¤   ¤   /* Find highest-sender-preference supported one */
a7a12f ¤   ¤   ¤   if( IsntNull( pgpCipherGetVTBL(
bc7436 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPCipherAlgorithm) prefalg[i] ) ) ) {
d3ab7b ¤   ¤   ¤   ¤   bestalg = prefalg[i];
aad226 ¤   ¤   ¤   ¤   algsOK = 1;
e6f622 ¤   ¤   ¤   ¤   break;
7aa3a6 ¤   ¤   ¤   }
170fe4 ¤   ¤   }
6f9371 ¤   }
0367c5 ¤
f94b59 ¤   /* If still no acceptable algorithms, choose most acceptable one */
412374 ¤   if (algsOK == 0) {
6f5fa1 ¤   ¤   /* Choose an algorithm which we support and most people accept */
4200da ¤   ¤   for( i=0; i<algInfo->n; ++i ) {
c03799 ¤   ¤   ¤   if( IsNull( pgpCipherGetVTBL( (PGPCipherAlgorithm)(i+1) ) ) )
e8d040 ¤   ¤   ¤   ¤   continue;
c24e85 ¤   ¤   ¤   algsOK += 1;
c105b0 ¤   ¤   ¤   if ( bestalg == 0 || algInfo->algok[i] > bestvote ) {
a1a6d7 ¤   ¤   ¤   ¤   /* First acceptable, or best one so far */
8672b3 ¤   ¤   ¤   ¤   bestvote = algInfo->algok[i];
d01f6c ¤   ¤   ¤   ¤   bestalg = i+1;
c2a3a6 ¤   ¤   ¤   }
e00fe4 ¤   ¤   }
759371 ¤   }
8167c5 ¤
f82374 ¤   if (algsOK == 0) {
4cefeb ¤   ¤   /* None of the algs we support are acceptable to anyone */
c421cb ¤   ¤   /* Just choose the first algorithm we support */
13d7f1 ¤   ¤   for (i=0; i<kPGPNumPossibleCipherAlgorithms; ++i) {
8b3799 ¤   ¤   ¤   if( IsNull( pgpCipherGetVTBL( (PGPCipherAlgorithm)(i+1) ) ) )
56d040 ¤   ¤   ¤   ¤   continue;
4c4e85 ¤   ¤   ¤   algsOK += 1;
a74a26 ¤   ¤   ¤   bestalg = i;
95cdcb ¤   ¤   ¤   break;
420fe4 ¤   ¤   }
ac9371 ¤   }
e4af5a
67cf3e ¤   pgpAssert (algsOK != 0);
c70127 ¤   pgpAssert (IsntNull( pgpCipherGetVTBL ( (PGPCipherAlgorithm)bestalg ) ) );
70af5a
15a589 ¤   /* Have choice in bestalg */
333a29 ¤   pgpenvSetInt (env, PGPENV_CIPHER, bestalg, PGPENV_PRI_FORCE);
caaf5a
6560ff error:
755ea8 ¤   return err;
4fefe6 }
8067c5 ¤
1866dd ¤   static PGPError
18a773 pgpCleanupPreferredAlgorithms (
f072f7 ¤   PGPContextRef¤  ·¤  ·context,
7ee82d ¤   PGPPreferredAlgs¤   *algInfo
0327e6 ¤   )
0fbb36 {
e1049b ¤   pgpContextMemFree (context, algInfo->votes);
5a4f9f ¤   pgpContextMemFree (context, algInfo->algok);
85151e ¤   return kPGPError_NoErr;
acefe6 }
13af5a
b4af5a
ddaf5a
533b5f /*********** Functions to set up data structures for pipeline *************/
53af5a
19af5a
bd025e /* Extract conventional encryption info from optionList */
09af5a
f266dd ¤   static PGPError
--46fe 000d869663c401001e0 Page 7 of pgpEncode.c
cb6ead pgpSetupConventionalEncryption(
0a0b0c ¤   PGPContextRef¤  ·¤  ··context,
e8edf4 ¤   PGPOptionListRef¤   ··optionList,
7f7e1e ¤   PGPEventHandlerProcPtr func,
2107ef ¤   PGPUserValue¤   ¤   ·userValue,
e4a22f ¤   PGPConvKey¤ ¤   ¤   **convkey
3d27e6 ¤   )
d4bb36 {
a2a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
496ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
bfda8d ¤   PGPByte¤¤   ¤   ¤   *passPhrase;¤   /* Pass phrase for conv encr */
65e8b8 ¤   PGPSize¤¤   ¤   ¤   ·passLength;¤   /* Length of passPhrase */
9baf5a
598878 ¤   (void)func;
4d9024 ¤   (void)userValue;
f6af5a
06bed2 ¤   /* Init return pointer */
fc0b84 ¤   pgpa( pgpaAddrValid( convkey, PGPConvKey * ) );
379d65 ¤   *convkey = NULL;
efaf5a
d07e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
0eb3a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ConventionalEncrypt, &op ) ) )
6b97ed ¤   ¤   goto error;
2c7343 ¤   if( IsOp( op ) ) {
4f654a ¤   ¤   /* Conventional encryption */
c73306 ¤   ¤   if( IsPGPError( err = pgpSearchOptionSingle( op.subOptions,
1f8931 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passphrase, &op ) ) )
445b34 ¤   ¤   {
9eed19 ¤   ¤   ¤   goto error;
b00fe4 ¤   ¤   }
744813 ¤   ¤   if( IsntOp( op ) ) {
32915c ¤   ¤   ¤   pgpDebugMsg( "no passphrase specified for conventional encrypt" );
0031d2 ¤   ¤   ¤   err = kPGPError_MissingPassphrase;
71ed19 ¤   ¤   ¤   goto error;
f345a6 ¤   ¤   } else {
c7f58d ¤   ¤   ¤   if( IsPGPError( err = pgpOptionPtrLength( &op,
474d29 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·( void ** )&passPhrase, &passLength ) ) )
581b7c ¤   ¤   ¤   ¤   goto error;
57194e ¤   ¤   ¤   if ( passLength == 0 ) {
308158 ¤   ¤   ¤   ¤   pgpDebugMsg( "passphrases of length 0 are "\
5b2ee3 ¤   ¤   ¤   ¤   ¤   "illegal for conventional encryption" );
20f381 ¤   ¤   ¤   ¤   err¤= kPGPError_BadParams;
bf1b7c ¤   ¤   ¤   ¤   goto error;
40a3a6 ¤   ¤   ¤   }
8b0fe4 ¤   ¤   }
566cf7 ¤   ¤   if( IsNull( ( *convkey = (PGPConvKey *)pgpContextMemAlloc(
d97d58 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··context, sizeof( PGPConvKey ),
6d62af ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··0 ) ) ) ) {
50b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
0aed19 ¤   ¤   ¤   goto error;
9b0fe4 ¤   ¤   }
a8f39b ¤   ¤   (*convkey)->pass = NULL;
c11a57 ¤   ¤   (*convkey)->next = NULL;
030870 ¤   ¤   (*convkey)->stringToKey = 0;
85b91f ¤   ¤   (*convkey)->pass = (char *)pgpContextMemAlloc( context, passLength,
f4201d ¤   ¤   ¤   ¤   ¤   0 );
ade3dd ¤   ¤   if( IsNull( (*convkey)->pass ) ) {
0bb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
a1ed19 ¤   ¤   ¤   goto error;
630fe4 ¤   ¤   }
6f36f7 ¤   ¤   pgpCopyMemory( passPhrase, (char *)(*convkey)->pass, passLength );
aaec16 ¤   ¤   (*convkey)->passlen = passLength;
c29371 ¤   }
e5151e ¤   return kPGPError_NoErr;
58af5a
ee60ff error:
2139a9 ¤   if( IsntNull( *convkey ) ) {
09c574 ¤   ¤   pgpClearMemory( (*convkey)->pass, (*convkey)->passlen );
8900c6 ¤   ¤   pgpContextMemFree( context, (char *)(*convkey)->pass );
22c94f ¤   ¤   pgpContextMemFree( context, *convkey );
cf9371 ¤   }
d85ea8 ¤   return err;
--f61a 0000c397530401001e0 Page 8 of pgpEncode.c
7aefe6 }
46af5a
8eaf5a
7d6983 /* Service routine for pgpSetupPublicKeyEncryption, to do checks for a
59c14b ·* single key, and append it to pubkeys list */
f7af5a
c366dd ¤   static PGPError
ede3d1 pgpSetupPubkey(
f40b0c ¤   PGPContextRef¤  ·¤  ··context,
1cedf4 ¤   PGPOptionListRef¤   ··optionList,
a1601c ¤   PGPKey¤ ¤   ¤   ¤   ·*key,
35b298 ¤   PGPValidity¤¤   ¤   ·failValidity,
b5295d ¤   PGPValidity¤¤   ¤   ·warnValidity,
96b416 ¤   PGPPreferredAlgs¤   *preferredAlgs,
e13f7c ¤   PGPPubKey¤  ¤   ···**pubkeys,
fa0c8f ¤   PGPKeySetRef¤   ¤   ·warnKeySet
7727e6 ¤   )
4ebb36 {
9a6ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
ebd696 ¤   RingObject¤ ¤   ¤   *ringKey;¤  ¤   /* Keyring obj for encryption key */
46095d ¤   RingSet const¤  ¤   *ringSet;¤  ¤   /* Lowlevel keyring set for enc key */
cf1ca5 ¤   PGPPubKey¤  ¤   ¤   *pubkey;¤   ¤   /* Internal struct for current key */
7baf5a
e499da ¤   if( IsPGPError( err = pgpGetKeyRingObject( key, FALSE, &ringKey ) ) )
cd97ed ¤   ¤   goto error;
dbec2f ¤   if( IsPGPError( err = pgpGetKeyRingSet( key, FALSE, &ringSet ) ) )
0597ed ¤   ¤   goto error;
ee38e8 ¤   if( IsPGPError( err = pgpCheckKeyValidity( context, optionList,
095bff ¤   ¤   ¤   ¤   ¤   key, ringSet, failValidity, warnValidity, warnKeySet,
a2a0d7 ¤   ¤   ¤   ¤   ¤   NULL ) ) )
0297ed ¤   ¤   goto error;
395507 ¤   if( IsPGPError( err = pgpCheckPreferredAlgorithms( preferredAlgs, key,
f45ffa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSet ) ) )
bc97ed ¤   ¤   goto error;
571b2d ¤   pubkey = ringKeyPubKey( ringSet, ringKey, PGP_PKUSE_ENCRYPT );
73e58d ¤   if( IsNull( pubkey ) ) {
a7fde4 /*¤ ¤   err = kPGPError_KeyUnusableForEncryption; */
a782df ¤   ¤   err = ringSetError( ringSet ) -> error;
1d97ed ¤   ¤   goto error;
1c9371 ¤   }
42b16c ¤   pubkey->next = *pubkeys;
62d376 ¤   *pubkeys = pubkey;
42151e ¤   return kPGPError_NoErr;
09af5a
e860ff error:
d85ea8 ¤   return err;
a7efe6 }
57af5a
9eaf5a
c767c5 ¤
d379b7 /* Extract public key encryption info from optionList */
e7af5a
8266dd ¤   static PGPError
bc8237 pgpSetupPublicKeyEncryption(
8a0b0c ¤   PGPContextRef¤  ·¤  ··context,
10edf4 ¤   PGPOptionListRef¤   ··optionList,
ad4aa6 ¤   PGPEnv¤ ¤   ¤   ¤   ·*env,
98ebc0 ¤   PGPPubKey¤  ¤   ¤   **pubkeys
d227e6 ¤   )
b7bb36 {
68a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
2a6ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
38d426 ¤   PGPInt32¤   ¤   ¤   ·keyCount;¤ ¤   /* Number of key we are doing */
b96a28 ¤   PGPKey¤ ¤   ¤   ¤   *key;¤  ¤   ¤   /* PGPKey structure for current key */
17fa53 ¤   PGPUserID¤  ¤   ¤   *userid;¤   ¤   /* UserID to encrypt to */
0908c1 ¤   PGPKeySet¤  ¤   ¤   *keySet;¤   ¤   /* Keyset to encrypt to */
3b4024 ¤   PGPKeyList¤ ¤   ¤   *keyList;¤  ¤   /* Sorted version of keySet */
61ceb1 ¤   PGPKeyIter¤ ¤   ¤   *keyIter;¤  ¤   /* Iterator over keyList */
37be1e ¤   PGPValidity¤¤   ¤   ·failValidity,¤ /* Fail on keys less valid */
5a970e ¤   ¤   ¤   ¤   ¤   ¤   ·warnValidity;¤ /* Warn on keys less valid */
117889 ¤   PGPPreferredAlgs¤   ·preferredAlgs;¤/* Preferred algorithm data */
0cd178 ¤   PGPKeySet¤  ¤   ¤   *warnKeySet;¤   /* Keys with warnable trusts */
--15eb 0002547ae4b401001e0 Page 9 of pgpEncode.c
e0af5a
53bed2 ¤   /* Init return pointer */
c478e7 ¤   pgpa( pgpaAddrValid( pubkeys, PGPPubKey * ) );
b41289 ¤   *pubkeys = NULL;
f904a9 ¤   warnKeySet = NULL;
fb77d2 ¤   keyList = NULL;
64973c ¤   keyIter = NULL;
2aaf5a
f96960 ¤   /* Initialize for loops below */
83a0ab ¤   if( IsPGPError( err = pgpInitPreferredAlgorithms( context,
e580e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&preferredAlgs ) ) )
0b97ed ¤   ¤   goto error;
f398d1 ¤   if( IsPGPError( err = pgpGetMinValidity( optionList,
0e6877 ¤   ¤   ¤   ¤   ¤   &failValidity, &warnValidity ) ) )
5097ed ¤   ¤   goto error;
6caf5a
ea21d9 ¤   /* Accumulate warning keys here */
cf8129 ¤   if( IsPGPError( err = PGPNewKeySet( context, &warnKeySet ) ) )
3f97ed ¤   ¤   goto error;
80af5a
02ad55 ¤   /* Find any encryption keys specified as keys */
ed974d ¤   keyCount = 0;
e0e037 ¤   if( IsPGPError( err = pgpSearchOption( optionList,
f14421 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EncryptToKey, keyCount, &op ) ) )
0997ed ¤   ¤   goto error;
7dd1fb ¤   while( IsOp( op ) ) {
ed14eb ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)&key ) ) )
64ed19 ¤   ¤   ¤   goto error;
a3c52b ¤   ¤   pgpa(pgpaPGPKeyValid(key));
e3f0a1 ¤   ¤   if( !pgpKeyIsValid(key) ) {
659273 ¤   ¤   ¤   pgpDebugMsg( "Error: invalid EncryptToKey keyref" );
bb5820 ¤   ¤   ¤   err = kPGPError_BadParams;
77ed19 ¤   ¤   ¤   goto error;
0a0fe4 ¤   ¤   }
4cc23e ¤   ¤   if( IsPGPError( err = pgpSetupPubkey( context, optionList, key,
0c4698 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··failValidity, warnValidity,
1dfa9a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&preferredAlgs, pubkeys,
b4de0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··warnKeySet ) ) )
47ed19 ¤   ¤   ¤   goto error;
0fe70c ¤   ¤   if( IsPGPError( err = pgpSearchOption( optionList,
e0992e ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_EncryptToKey, ++keyCount, &op ) ) )
b9ed19 ¤   ¤   ¤   goto error;
5e9371 ¤   }
a9af5a
c50ac6 ¤   /* Find any encryption keys specified as userids */
eb974d ¤   keyCount = 0;
4de037 ¤   if( IsPGPError( err = pgpSearchOption( optionList,
5f9d5f ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_EncryptToUserID, keyCount, &op ) ) )
2897ed ¤   ¤   goto error;
15d1fb ¤   while( IsOp( op ) ) {
adb0de ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)&userid ) ) )
f1ed19 ¤   ¤   ¤   goto error;
2dafe7 ¤   ¤   pgpa(pgpaPGPUserIDValid(userid));
c94535 ¤   ¤   if( !pgpUserIDIsValid(userid) ) {
09c0db ¤   ¤   ¤   pgpDebugMsg( "Error: invalid EncryptToUserID useridref" );
8c5820 ¤   ¤   ¤   err = kPGPError_BadParams;
2bed19 ¤   ¤   ¤   goto error;
1f0fe4 ¤   ¤   }
947304 ¤   ¤   if( IsPGPError( err = pgpGetUserIDKey( userid, FALSE, &key ) ) )
99ed19 ¤   ¤   ¤   goto error;
9ac23e ¤   ¤   if( IsPGPError( err = pgpSetupPubkey( context, optionList, key,
864698 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··failValidity, warnValidity,
09fa9a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&preferredAlgs, pubkeys,
f8de0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··warnKeySet ) ) )
83ed19 ¤   ¤   ¤   goto error;
66e70c ¤   ¤   if( IsPGPError( err = pgpSearchOption( optionList,
144849 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EncryptToUserID, ++keyCount, &op ) ) )
e2ed19 ¤   ¤   ¤   goto error;
299371 ¤   }
46af5a
eec5f0 ¤   /* Find any encryption keys specified as keysets */
25974d ¤   keyCount = 0;
--68b9 0004a7c3a96401001e0 Page 10 of pgpEncode.c
c8e037 ¤   if( IsPGPError( err = pgpSearchOption( optionList,
d3bbb4 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_EncryptToKeySet, keyCount, &op ) ) )
1297ed ¤   ¤   goto error;
86d1fb ¤   while( IsOp( op ) ) {
f7355a ¤   ¤   PGPUInt32 keySetCount;
7fc0e2 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)&keySet ) ) )
e0ed19 ¤   ¤   ¤   goto error;
758a0b ¤   ¤   pgpa(pgpaPGPKeySetValid(keySet));
3a04d1 ¤   ¤   if( !pgpKeySetIsValid(keySet) ) {
544291 ¤   ¤   ¤   pgpDebugMsg( "Error: invalid EncryptToKeySet keyset" );
275820 ¤   ¤   ¤   err = kPGPError_BadParams;
3aed19 ¤   ¤   ¤   goto error;
aa0fe4 ¤   ¤   }
77c2f8 ¤   ¤   if( IsPGPError( err = PGPCountKeys( keySet, &keySetCount ) ) )
d2ed19 ¤   ¤   ¤   goto error;
40f14b ¤   ¤   if ( keySetCount < 1 ) {
0988c3 ¤   ¤   ¤   pgpDebugMsg( "Error: empty EncryptToKeySet keyset" );
bb5820 ¤   ¤   ¤   err = kPGPError_BadParams;
f1ed19 ¤   ¤   ¤   goto error;
ba0fe4 ¤   ¤   }
b5bf6e ¤   ¤   if( IsPGPError( err = PGPOrderKeySet( keySet, kPGPAnyOrdering,
6bbb7a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&keyList ) ) )
5fed19 ¤   ¤   ¤   goto error;
f99914 ¤   ¤   if( IsPGPError( err = PGPNewKeyIter ( keyList, &keyIter ) ) )
63ed19 ¤   ¤   ¤   goto error;
ea67c5 ¤
4cb99e ¤   ¤   while( IsntPGPError( err = PGPKeyIterNext( keyIter, &key ) ) ) {
571b52 ¤   ¤
21d937 ¤   ¤   ¤   if( IsPGPError( err = pgpSetupPubkey( context, optionList, key,
df4698 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··failValidity, warnValidity,
61fa9a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&preferredAlgs, pubkeys,
09de0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··warnKeySet ) ) )
4a1b7c ¤   ¤   ¤   ¤   goto error;
ce0fe4 ¤   ¤   }
1e10a7 ¤   ¤   PGPFreeKeyIter( keyIter );
daedc8 ¤   ¤   keyIter = NULL;
0c6efb ¤   ¤   PGPFreeKeyList( keyList );
4b0d26 ¤   ¤   keyList = NULL;
4de70c ¤   ¤   if( IsPGPError( err = pgpSearchOption( optionList,
ec014c ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EncryptToKeySet, ++keyCount, &op ) ) )
3f1b7c ¤   ¤   ¤   ¤   goto error;
829371 ¤   }
beaf5a
1a4dcf ¤   if( IsntNull( warnKeySet ) ) {
79c390 ¤   ¤   PGPUInt32¤  numKeys;
c81b52 ¤   ¤
4f7102 ¤   ¤   if ( IsPGPError( PGPCountKeys( warnKeySet, &numKeys ) ) )
99ed19 ¤   ¤   ¤   goto error;
9687c7 ¤   ¤   ¤
f4e59e ¤   ¤   if( numKeys > 0 ) {
e4f1a3 ¤   ¤   ¤   if( IsPGPError( pgpWarnUser( context, optionList,
96bca9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPError_KeyInvalid, warnKeySet ) ) )
f11b7c ¤   ¤   ¤   ¤   goto error;
490fe4 ¤   ¤   }
96d005 ¤   ¤   PGPFreeKeySet( warnKeySet );
0de648 ¤   ¤   warnKeySet = NULL;
069371 ¤   }
feaf5a
c8c180 ¤   if( IsntNull( *pubkeys ) ) {
72bdab ¤   ¤   if( IsPGPError( err = pgpSetPreferredAlgorithm( optionList,
6be0b7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &preferredAlgs, env ) ) )
c7ed19 ¤   ¤   ¤   goto error;
4a9371 ¤   }
0859e3 ¤   pgpCleanupPreferredAlgorithms( context, &preferredAlgs );
ba151e ¤   return kPGPError_NoErr;
b0af5a
0760ff error:
a459e3 ¤   pgpCleanupPreferredAlgorithms( context, &preferredAlgs );
45dcac ¤   while( IsntNull( *pubkeys ) ) {
966863 ¤   ¤   PGPPubKey *pk1 = pgpPubKeyNext (*pubkeys);
9350f3 ¤   ¤   pgpPubKeyDestroy (*pubkeys);
4ad774 ¤   ¤   *pubkeys = pk1;
--c075 00054aff246401001e0 Page 11 of pgpEncode.c
a19371 ¤   }
9080f5 ¤   if( IsntNull( warnKeySet ) )
90d005 ¤   ¤   PGPFreeKeySet( warnKeySet );
b366e4 ¤   if( IsntNull( keyList ) )
d66efb ¤   ¤   PGPFreeKeyList( keyList );
8c00a7 ¤   if( IsntNull( keyIter ) )
cf10a7 ¤   ¤   PGPFreeKeyIter( keyIter );
d95ea8 ¤   return err;
32efe6 }
1aaf5a
59af5a
80af5a
1aaf5a
53b397 /* Extract public key signature info from optionList */
5c90c8 /* Currently only allows a single signing key */
22af5a
8666dd ¤   static PGPError
ea8506 pgpSetupSigning(
a60b0c ¤   PGPContextRef¤  ·¤  ··context,
e9edf4 ¤   PGPOptionListRef¤   ··optionList,
c5d853 ¤   PGPBoolean¤ ¤   ¤   ··fHaveEncryption,
964aa6 ¤   PGPEnv¤ ¤   ¤   ¤   ·*env,
467e1e ¤   PGPEventHandlerProcPtr func,
4add93 ¤   PGPUserValue¤   ¤   ··userValue,
241f35 ¤   PGPBoolean¤ ¤   ¤   ·knownBinaryInput,
382e34 ¤   PGPBoolean¤ ¤   ¤   ·sepsig,
437007 ¤   PGPSigSpec¤ ¤   ¤   **sigspec
9527e6 ¤   )
cdbb36 {
b9a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
ff6ddd ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error return code */
e6636c ¤   PGPKey¤ ¤   ¤   ¤   *signKey;¤  ¤   /* PGPKey struct for signing key */
5b702d ¤   PGPKeySet¤  ¤   ¤   *signKeySet;¤   /* PGPKeySet holding signKey */
7b20ce ¤   PGPSecKey¤  ¤   ¤   *seckey;¤   ¤   /* Internal struct for signKey */
01cdd5 ¤   RingObject¤ ¤   ¤   *ringKey;¤  ¤   /* Keyring obj for signing key */
6a095d ¤   RingSet const¤  ¤   *ringSet;¤  ¤   /* Lowlevel keyring set for enc key */
bda1ff ¤   PGPByte¤¤   ¤   ¤   ·signMode;¤ ¤   /* Text vs binary mode for sig */
7bdb77 ¤   PGPByte¤¤   ¤   ¤   *passPhrase;¤   /* Signing key pass phrase */
a4e8b8 ¤   PGPSize¤¤   ¤   ¤   ·passLength;¤   /* Length of passPhrase */
e3322f ¤   PGPBoolean¤ ¤   ¤   ·hashedPhrase = FALSE; /* True if passkey given */
22be1e ¤   PGPValidity¤¤   ¤   ·failValidity,¤ /* Fail on keys less valid */
6a970e ¤   ¤   ¤   ¤   ¤   ¤   ·warnValidity;¤ /* Warn on keys less valid */
6ef624 ¤   PGPInt32¤   ¤   ¤   ·rslt;¤ ¤   ¤   /* Success code on unlock */
c2af5a
6f8878 ¤   (void)func;
6c9024 ¤   (void)userValue;
afaf5a
568a4d ¤   /* Init return pointers */
30d7dc ¤   pgpa( pgpaAddrValid( sigspec, PGPSigSpec * ) );
1d7d7f ¤   *sigspec = NULL;
263670 ¤   seckey = NULL;
4dfe32 ¤   signKeySet = NULL;
9a67c5 ¤
1d0be8 ¤   /* See if signature requested. ·Only one signing key allowed. */
be7e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
081ea5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_SignWithKey, &op ) ) )
fe97ed ¤   ¤   goto error;
45af5a
f67343 ¤   if( IsOp( op ) ) {
83aee2 ¤   ¤   /* Get signing key and data */
e30113 ¤   ¤   if( IsPGPError( err = pgpOptionPtr( &op, (void **)&signKey ) ) )
40ed19 ¤   ¤   ¤   goto error;
e14302 ¤   ¤   pgpa(pgpaPGPKeyValid(signKey));
609847 ¤   ¤   if( !pgpKeyIsValid(signKey) ) {
c8ebd3 ¤   ¤   ¤   pgpDebugMsg( "Error: invalid SignWithKey keyref" );
985820 ¤   ¤   ¤   err = kPGPError_BadParams;
8eed19 ¤   ¤   ¤   goto error;
610fe4 ¤   ¤   }
e5644e ¤   ¤   if( IsPGPError( err = pgpGetKeyRingObject( signKey, FALSE, &ringKey )))
d4ed19 ¤   ¤   ¤   goto error;
48aa3c ¤   ¤   if( IsPGPError( err = pgpGetKeyRingSet( signKey, FALSE, &ringSet ) ) )
54ed19 ¤   ¤   ¤   goto error;
--c691 0008a04dcfc401001e0 Page 12 of pgpEncode.c
55be64 ¤   ¤   if( IsPGPError( err = pgpGetMinValidity( optionList,
f66f4c ¤   ¤   ¤   ¤   ¤   ¤   &failValidity, &warnValidity ) ) )
d3ed19 ¤   ¤   ¤   goto error;
81769f ¤   ¤   if( IsPGPError( err = pgpCheckKeyValidity( context, optionList,
53d222 ¤   ¤   ¤   ¤   ¤   ¤   signKey, ringSet, failValidity, warnValidity,
50e31c ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL ) ) )
82ed19 ¤   ¤   ¤   goto error;
479f06 ¤   ¤   seckey = ringSecSecKey( ringSet, ringKey, PGP_PKUSE_SIGN );
e11065 ¤   ¤   if( IsNull( seckey ) ) {
1fe11b /*¤ ¤   ¤   err = kPGPError_KeyUnusableForSignature; */
3f149e ¤   ¤   ¤   err = ringSetError( ringSet ) -> error;
17ed19 ¤   ¤   ¤   goto error;
d80fe4 ¤   ¤   }
20af5a
8ce1b1 ¤   ¤   /* Try to unlock secret key */
0e2a49 ¤   ¤   /* First see if a passphrase is needed at all for signing key */
48162c ¤   ¤   rslt = pgpSecKeyUnlock( seckey, env, NULL, 0, FALSE );
911789 ¤   ¤   if ( rslt <= 0 ) {
1b87df ¤   ¤   ¤   /* Failed, must try passphrase */
4d7c47 ¤   ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( op.subOptions,
0fc0a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
7502b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passPhrase, &passLength ) ) )
c01b7c ¤   ¤   ¤   ¤   goto error;
a08c6c ¤   ¤   ¤   if( IsNull( passPhrase ) ) {
1edca9 ¤   ¤   ¤   ¤   hashedPhrase = TRUE;
243230 ¤   ¤   ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( op.subOptions,
3a6030 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
7a85f4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passPhrase, &passLength ) ) )
09b622 ¤   ¤   ¤   ¤   ¤   goto error;
2e8ad4 ¤   ¤   ¤   ¤   if( IsNull( passPhrase ) ) {
1df847 ¤   ¤   ¤   ¤   ¤   err = kPGPError_MissingPassphrase;
7eb622 ¤   ¤   ¤   ¤   ¤   goto error;
652613 ¤   ¤   ¤   ¤   }
4ba3a6 ¤   ¤   ¤   }
aa8f54 ¤   ¤   ¤   rslt = pgpSecKeyUnlock( seckey, env, (char *) passPhrase,
3506b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passLength, hashedPhrase );
7cd5e6 ¤   ¤   ¤   if( rslt <= 0 ) {
0f4e98 ¤   ¤   ¤   ¤   err = kPGPError_BadPassphrase;
cc1b7c ¤   ¤   ¤   ¤   goto error;
99a3a6 ¤   ¤   ¤   }
f00fe4 ¤   ¤   }
39f6b9 ¤   ¤   /* At this point we have unlocked successfully */
845aa4 ¤   ¤   /* See if text or binary mode */
a697e8 ¤   ¤   if( knownBinaryInput )
c25b34 ¤   ¤   {
db8963 ¤   ¤   ¤   signMode = PGP_SIGTYPE_BINARY;
d20fe4 ¤   ¤   }
130e1d ¤   ¤   else
975b34 ¤   ¤   {
e83927 ¤   ¤   ¤   signMode =
e24dfc ¤   ¤   ¤   ¤   ( PGPByte ) ( pgpenvGetInt( env, PGPENV_TEXTMODE, NULL, NULL ) ?
5095ae ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGP_SIGTYPE_TEXT : PGP_SIGTYPE_BINARY );
430fe4 ¤   ¤   }
661b52 ¤   ¤
fe3ec8 ¤   ¤   *sigspec = pgpSigSpecCreate( env, seckey, signMode );
fe9371 ¤   }
87af5a
1494e2 ¤   if( sepsig && IsNull( *sigspec ) ) {
b7e285 ¤   ¤   /* Error, detached sig requested without signing! */
b866ff ¤   ¤   pgpDebugMsg( "Error: detached signature without signing key" );
3119d3 ¤   ¤   err = kPGPError_BadParams;
9697ed ¤   ¤   goto error;
e99371 ¤   }
dfc278 ¤   if( sepsig && fHaveEncryption ) {
cc55b7 ¤   ¤   /* Error, can't do detached sig if encrypting */
42d682 ¤   ¤   pgpDebugMsg( "Error: detached signature with encryption" );
3419d3 ¤   ¤   err = kPGPError_BadParams;
8e97ed ¤   ¤   goto error;
689371 ¤   }
68151e ¤   return kPGPError_NoErr;
d7af5a
8a60ff error:
--cbfb 000b96ff7e0401001e0 Page 13 of pgpEncode.c
8c32c9 ¤   if( IsntNull( *sigspec ) )
4ee83e ¤   ¤   pgpSigSpecDestroy (*sigspec);
c15790 ¤   if( IsntNull( seckey ) )
3dccd8 ¤   ¤   pgpSecKeyDestroy (seckey);
f50ee6 ¤   if( IsntNull( signKeySet ) )
aa9b2f ¤   ¤   PGPFreeKeySet( signKeySet );
8c5ea8 ¤   return err;
dfefe6 }
acaf5a
76af5a
96af5a
ad8c8d /************************** Main encode function ****************************/
75af5a
22af5a
af13d8 /* All state information for pgpEncode is kept in a struct like this */
89ed71 struct pgpEncodeJobState_
83bb36 {
06ad10 ¤   PGPContextRef¤  ¤   ·context;¤  ¤   /* Context pointer */
2a1d4d ¤   PGPOptionListRef¤   ·optionList;¤   /* List of all our options */
afbba3 ¤   PGPOptionListRef¤   ·newOptionList;¤/* Options changed by callback */
10c2a8 ¤   PGPError¤   ¤   ¤   ·err;¤  ¤   ¤   /* Error */
18185c ¤   PGPPipeline¤¤   ¤   *head, **tail;¤ /* Low level pipeline */
695599 ¤   PGPConvKey¤ ¤   ¤   *convkey;¤  ¤   /* Conventional encryption params */
5a3de2 ¤   PGPSigSpec¤ ¤   ¤   *sigspec;¤  ¤   /* Message signing params */
77194a ¤   PGPPubKey¤  ¤   ¤   *pubkeys;¤  ¤   /* Message encryption keys */
a12449 ¤   PgpLiteralParams¤   ·literal;¤  ¤   /* Filename, type info */
2bf644 ¤   PGPBoolean¤ ¤   ¤   ·sepsig;¤   ¤   /* Create detached signature */
e9e9bf ¤   PFLConstFileSpecRef¤ inFileRef;¤¤   /* Input filename handle */
6ebb84 ¤   PGPFileRead¤¤   ¤   *pfrin;¤¤   ¤   /* Input file reading structure */
def05f ¤   PGPByte¤¤   ¤   ¤   *inBufPtr;¤ ¤   /* Input buffer pointer */
81c787 ¤   PGPSize¤¤   ¤   ¤   ·inBufLength;¤  /* Size of input buffer */
b5d3fc ¤   PFLConstFileSpecRef¤ outFileRef;¤   /* Output filename handle */
a9ed08 ¤   PGPFile¤¤   ¤   ¤   *pfout;¤¤   ¤   /* Output file writing structure */
bdfa91 ¤   PGPByte¤¤   ¤   ¤   *outBufPtr;¤¤   /* Output buffer pointer */
9859d7 ¤   PGPByte¤¤   ¤   ···**outBufPtrPtr;¤ /* Dynamically allocated buf ptr */
825021 ¤   PGPSize¤¤   ¤   ¤   ·outBufMaxLength; /* Allocated size of outBufPtr */
a3670b ¤   PGPSize¤¤   ¤   ¤   *outBufUsedLength; /* Amount output to outBufPtr */
07e53b ¤   PGPPipeline¤¤   ¤   *outPipe;¤  ¤   /* Output-buffer pipeline module */
f4b7fc ¤   PGPEnv¤ ¤   ¤   ¤   *env;¤  ¤   ¤   /* Environment for low-level fns */
0bcccc ¤   PGPRandomContext¤   *rng;¤  ¤   ¤   /* Random state */
86a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
b2314e ¤   PGPEventHandlerProcPtr func;¤   ¤   /* Pointer to user callback func */
3101b2 ¤   PGPUserValue¤   ¤   ·userValue;¤¤   /* Arg to callback func */
379ab2 ¤   PGPBoolean¤ ¤   ¤   ·fNullEvents;¤  /* True if user wants null events */
1f82f7 };
f67f12 typedef struct pgpEncodeJobState_ pgpEncodeJobState;
75af5a
faaf5a
298104 /* Local callback function */
61af5a
4766dd ¤   static PGPError
0bf58c encodeLocalCallBack (
a5e865 ¤   void¤   ¤   ¤   ¤   *arg,
39a5b7 ¤   PGPFileOffset¤  ¤   soFar,
959f4a ¤   PGPFileOffset¤  ¤   total
b727e6 ¤   )
acbb36 {
029761 ¤   PGPError¤   ¤   ¤   ··err = kPGPError_NoErr;
983f34 ¤   pgpEncodeJobState¤  ·*s = ( pgpEncodeJobState * ) arg;
03af5a
625185 ¤   if( IsntNull( s->func ) ·&& ·s->fNullEvents ) {
4d853b ¤   ¤   err = pgpEventNull( s->context, &s->newOptionList, s->func,
2795e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->userValue, soFar, total );
2c7a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
3e9371 ¤   }
e25ea8 ¤   return err;
6fefe6 }
3faf5a
6366dd ¤   static PGPError
908e6e encodePKEncryptCallBack (
0ae865 ¤   void¤   ¤   ¤   ¤   *arg,
b93122 ¤   int¤¤   ¤   ¤   ¤   code
--89d3 0005268b6ef401001e0 Page 14 of pgpEncode.c
7f27e6 ¤   )
dbbb36 {
2d9761 ¤   PGPError¤   ¤   ¤   ··err = kPGPError_NoErr;
563f34 ¤   pgpEncodeJobState¤  ·*s = ( pgpEncodeJobState * ) arg;
33af5a
37f57b ¤   (void) code;
31af5a
355185 ¤   if( IsntNull( s->func ) ·&& ·s->fNullEvents ) {
6d853b ¤   ¤   err = pgpEventNull( s->context, &s->newOptionList, s->func,
fe0d0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->userValue, 0, 1 );
217a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
149371 ¤   }
005ea8 ¤   return err;
91efe6 }
e8af5a
39af5a
57af5a
bbaf5a
99c81e static const PGPOptionType encodeOptionSet[] = {
015ceb ¤   kPGPOptionType_InputFileRef,
d4d59a ¤   kPGPOptionType_InputBuffer,
d88511 ¤   kPGPOptionType_InputFileName,
69be74 ¤   kPGPOptionType_OutputFileRef,
206c2f ¤   kPGPOptionType_OutputBuffer,
430a04 ¤   kPGPOptionType_OutputAllocatedBuffer,
83bbd2 ¤   kPGPOptionType_AppendOutput,
ef40be ¤   kPGPOptionType_DiscardOutput,
bcb15b ¤   kPGPOptionType_LocalEncoding,
77e6dc ¤   kPGPOptionType_RawPGPInput,
c1c1ba ¤   kPGPOptionType_EncryptToKey,
2ab828 ¤   kPGPOptionType_EncryptToKeySet,
cab801 ¤   kPGPOptionType_EncryptToUserID,
fd96c7 ¤   kPGPOptionType_SignWithKey,
4c09eb ¤   kPGPOptionType_ConventionalEncrypt,
4c4990 ¤   kPGPOptionType_Passphrase,
154590 ¤   kPGPOptionType_Passkey,
68a576 ¤   kPGPOptionType_DetachedSignature,
d4150d ¤   kPGPOptionType_CipherAlgorithm,
524602 ¤   kPGPOptionType_HashAlgorithm,
196856 ¤   kPGPOptionType_FailBelowValidity,
062baf ¤   kPGPOptionType_WarnBelowValidity,
82b708 ¤   kPGPOptionType_PGPMIMEEncoding,
0a165b ¤   kPGPOptionType_OutputLineEndType,
a9074a ¤   kPGPOptionType_EventHandler,
abbf11 ¤   kPGPOptionType_SendNullEvents,
45600c ¤   kPGPOptionType_AskUserForEntropy,
39092a ¤   kPGPOptionType_ArmorOutput,
2bad8d ¤   kPGPOptionType_DataIsASCII,
2477d1 ¤   kPGPOptionType_ClearSign,
b8a8fb ¤   kPGPOptionType_ForYourEyesOnly,
d41811 ¤   kPGPOptionType_CommentString,
643a12 ¤   kPGPOptionType_Compression,
856aaf ¤   kPGPOptionType_VersionString,
a0d430 ¤   kPGPOptionType_OmitMIMEVersion,
678c4e ¤   kPGPOptionType_PreferredAlgorithms,
6fa7e9 ¤   /* really only for PGPExportKeySet, but that routine calls this */
c44ee8 ¤   kPGPOptionType_ExportPrivateKeys,
cacd2b ¤   kPGPOptionType_ExportPrivateSubkeys,
5b1b59 ¤   kPGPOptionType_ExportFormat
b182f7 };
7daf5a
38af5a
650006 /* Main entry point for this module */
9faf5a
f4c744 ¤   PGPError
d6317c pgpEncodeInternal(
83a1bc ¤   PGPContextRef¤  ¤   context,
471efc ¤   PGPOptionListRef¤   optionList
1227e6 ¤   )
78bb36 {
5f130c ¤   pgpEncodeJobState¤  ·jobState,¤ ¤   /* State in a struct */
52c8a7 ¤   ¤   ¤   ¤   ¤   ¤   *s=&jobState;¤  /* Use s-> to access all state ·*/
--6cd0 000679b4e87401001e0 Page 15 of pgpEncode.c
fc416d ¤   PGPByte¤¤   ¤   ¤   *charMap;¤  ¤   /* Charmap for armor output */
2c6e02 ¤   PGPLineEndType¤ ¤   ·lineEnd;¤  ¤   /* Line endings for armor output */
8d7795 ¤   PGPBoolean¤ ¤   ¤   ·fEncrypt;¤ ¤   /* Encryption */
e60c27 ¤   PGPBoolean¤ ¤   ¤   ·fSign;¤¤   ¤   /* Signature */
164ca3 ¤   PGPUInt32¤  ¤   ¤   ·fRawPGPInput;¤ /* Don't put on literal packet */
abea50 ¤   PGPUInt32¤  ¤   ¤   ·fAppendOutput;¤/* Append to existing outfile */
01a22f ¤   PGPOption¤  ¤   ¤   ·op;¤   ¤   ¤   /* Selected option from list */
ad7495 ¤   PGPFileDataType¤¤   ·inFileDataType;¤   /* Input file data trype (ascii or ¶
8ef668 binary) */¤
4767c5 ¤
455942 ¤   /* Initialize pointers to NULL for easier error cleanup */
3ffc16 ¤   pgpClearMemory( s, sizeof( *s ) );
087083 ¤   s->context = context;
eda635 ¤   s->optionList = optionList;
685908 ¤   s->tail = &s->head;
33af5a
061d47 ¤   if (IsPGPError( s->err = pgpCheckOptionsInSet( optionList,
baca7a ¤   ¤   ¤   ¤   ¤   ¤   encodeOptionSet, elemsof( encodeOptionSet ) ) ) )
d8c6bb ¤   ¤   return s->err;
71af5a
312031 ¤   /* Get copies of info from context */
f4fbbf ¤   s->rng = pgpContextGetX9_17RandomContext ( s->context );
ccaf5a
94131d ¤   /* Get a copy of the env to work with so our changes aren't permanent */
07c053 ¤   if( IsPGPError( pgpenvCopy( pgpContextGetEnvironment( s->context ),
b5cdbe ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->env ) ) )
2397ed ¤   ¤   goto error;
ac67c5 ¤
20a260 ¤   /* Set up PGPEnv structure for library internals */
fe9230 ¤   if( IsPGPError( s->err = pgpMakeEnvFromOptionList( s->optionList,
1ab8b7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->env ) ) )
1097ed ¤   ¤   goto error;
f7af5a
f798f4 ¤   /* Set up callback pointers and data */
7a1f9e ¤   if( IsPGPError( s->err = pgpSetupCallback( s->optionList,
6ce05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&s->func, &s->userValue, &s->fNullEvents ) ) )
b397ed ¤   ¤   goto error;
7e92fd ¤   s->err = pgpEventInitial( s->context, &s->newOptionList,
4fb16e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue );
9aa2e3 ¤   pgpCleanupOptionList( &s->newOptionList );
241d7a ¤   if( IsPGPError( s->err ) )
cb97ed ¤   ¤   goto error;
95af5a
4fe586 ¤   /* Set up for conventional encryption if requested */
698249 ¤   if( IsPGPError( s->err = pgpSetupConventionalEncryption( s->context,
e6187a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->optionList, s->func, s->userValue,
6b2c6f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&s->convkey ) ) )
8b97ed ¤   ¤   goto error;
26af5a
13b0f0 ¤   /* Set up for public key encryption if requested */
ff13f7 ¤   if( IsPGPError( s->err = pgpSetupPublicKeyEncryption( s->context,
f88b23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->optionList,
e285f0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->env, &s->pubkeys ) ) )
3397ed ¤   ¤   goto error;
4eaf5a
1c157d ¤   /* Determine if a detached signature has been requested */
5866d1 ¤   if( IsPGPError( s->err = pgpSearchOptionSingle( s->optionList,
714e12 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DetachedSignature, &op ) ) )
c097ed ¤   ¤   goto error;
e11b52 ¤   ¤
709312 ¤   s->sepsig = IsOp( op );
f467c5 ¤
435394 ¤   /* Set up input filenames and open file if any */
4a57df ¤   if( IsPGPError( s->err = pgpSetupInput( s->context, s->optionList,
a89ddc ¤   ¤   ¤   ¤   ¤   &s->literal, s->rng, TRUE, s->sepsig,
59c930 ¤   ¤   ¤   ¤   ¤   &s->inFileRef, &s->pfrin, &inFileDataType,
2222eb ¤   ¤   ¤   ¤   ¤   &s->inBufPtr, &s->inBufLength ) ) )
fd97ed ¤   ¤   goto error;
abaf5a
4a59ca ¤   /* Set up for any signing operation requested */
cd460b ¤   if( IsPGPError( s->err = pgpSetupSigning( s->context, s->optionList,
676813 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPBoolean) ( IsntNull( s->convkey )
--f247 00008c5fbc7401001e0 Page 16 of pgpEncode.c
e3c383 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·|| IsntNull( s->pubkeys ) ),
e7fc40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->env, s->func, s->userValue,
c9b3c3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPBoolean) (inFileDataType == kPGPFileDataType_¶
55b914 Binary),
05f540 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->sepsig, &s->sigspec ) ) )
9f97ed ¤   ¤   goto error;
c9af5a
8daf5a
4dc962 ¤   /* Set up main processing pipeline (will set up output afterwards) */
06340c ¤   if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
1bb9e7 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_RawPGPInput, FALSE,
25b8d6 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fRawPGPInput ) ) )
1797ed ¤   ¤   goto error;
f35e61 ¤   s->tail = pgpEncryptPipelineCreate( context, &s->head, s->env, NULL,
3f52dd ¤   ¤   ¤   s->rng, s->convkey, s->pubkeys, s->sigspec,
df97fe ¤   ¤   ¤   (fRawPGPInput?NULL:&s->literal), s->sepsig,
bcdb85 ¤   ¤   ¤   (PGPBoolean) (inFileDataType == kPGPFileDataType_Binary),
10332c ¤   ¤   ¤   encodePKEncryptCallBack, s, &s->err );
471d7a ¤   if( IsPGPError( s->err ) )
7797ed ¤   ¤   goto error;
5b67c5 ¤
f5790d ¤   /* Add a text conversion if needed for output */
f6b997 ¤   if( pgpenvGetInt( s->env, PGPENV_ARMOR, NULL, NULL ) ) {
87fb38 ¤   ¤   /* Ascii armoring output */
fce5cf ¤   ¤   /* Convert to local line endings if appropriate */
76e866 ¤   ¤   charMap = (PGPByte *)pgpenvGetPointer( s->env, PGPENV_CHARMAPTOLATIN1,
28f63b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL );
4b8837 ¤   ¤   lineEnd = pgpGetDefaultLineEndType ();
4cc903 ¤   ¤   if( IsPGPError( s->err = pgpSearchOptionSingle( optionList,
916fc8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPOptionType_OutputLineEndType, &s->op ) ) )
11ed19 ¤   ¤   ¤   goto error;
9cc08d ¤   ¤   if( IsOp( s->op ) ) {
977427 ¤   ¤   ¤   PGPUInt32 uintLineEnd;
87ce53 ¤   ¤   ¤   if( IsPGPError( s->err = pgpOptionUInt( &s->op, &uintLineEnd ) ) )
401b7c ¤   ¤   ¤   ¤   goto error;
444299 ¤   ¤   ¤   lineEnd = (PGPLineEndType)uintLineEnd;
b30fe4 ¤   ¤   }
56c41d ¤   ¤   s->tail = pgpTextFiltCreate( s->context, s->tail, charMap,0,lineEnd );
3f9371 ¤   }
cbaf5a
c3d8af ¤   /*
62807a ¤   ·* Check for sufficient entropy. ·Error if not enough, unless
5c477b ¤   ·* AskUserForEntropy option is specified, in which case we give an event.
27a4e3 ¤   ·*/
704890 ¤   if( IsntNull( s->sigspec ) || IsntNull( s->pubkeys ) ) {
857ad9 ¤   ¤   if( !PGPGlobalRandomPoolHasMinimumEntropy() ) {
445082 ¤   ¤   ¤   PGPUInt32 fEntropyEvent;
aaaa7c ¤   ¤   ¤   if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
32d976 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_AskUserForEntropy,
40983f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···FALSE, "%d", &fEntropyEvent ) ) )
8a1b7c ¤   ¤   ¤   ¤   goto error;
39c224 ¤   ¤   ¤   if( !fEntropyEvent ) {
7ff637 ¤   ¤   ¤   ¤   s->err = kPGPError_OutOfEntropy;
311b7c ¤   ¤   ¤   ¤   goto error;
ada3a6 ¤   ¤   ¤   }
cd3d3c ¤   ¤   ¤   while( !PGPGlobalRandomPoolHasMinimumEntropy() ) {
2aae65 ¤   ¤   ¤   ¤   PGPUInt32 entropy_needed;
c3ee6a ¤   ¤   ¤   ¤   entropy_needed = PGPGlobalRandomPoolGetMinimumEntropy() -
c0d028 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPGlobalRandomPoolGetEntropy();
a99ede ¤   ¤   ¤   ¤   s->err = pgpEventEntropy( s->context, &s->newOptionList,
15488a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··s->func, s->userValue, entropy_needed );
736c4d ¤   ¤   ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
58deba ¤   ¤   ¤   ¤   if( IsPGPError( s->err ) )
4ab622 ¤   ¤   ¤   ¤   ¤   goto error;
e9a3a6 ¤   ¤   ¤   }
e40fe4 ¤   ¤   }
b59371 ¤   }
1baf5a
b9bbce ¤   /* Set up output pipeline */
3d65df ¤   fEncrypt = (PGPBoolean) (IsntNull( s->pubkeys ) || IsntNull( s->convkey ));
8c51d1 ¤   fSign = (PGPBoolean) IsntNull( s->sigspec );
08340c ¤   if( IsPGPError( s->err = pgpFindOptionArgs( s->optionList,
--3a31 000f88055b1401001e0 Page 17 of pgpEncode.c
2715aa ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_AppendOutput, FALSE,
41400c ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fAppendOutput ) ) )
3297ed ¤   ¤   goto error;
3dc40e ¤   if( IsPGPError( s->err = pgpSetupOutputPipeline( s->context, s->optionList,
bc27ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->env, fEncrypt, fSign, s->sepsig,
7f7ba0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean)fAppendOutput,
8f8057 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->tail, &s->outFileRef, &s->pfout,
b4c2a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outBufPtr, &s->outBufPtrPtr,
badd47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outBufMaxLength, &s->outBufUsedLength,
a256d0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &s->outPipe ) ) )
c797ed ¤   ¤   goto error;
23af5a
6f0b9b ¤   /* Now pump the data through the pipes */
dddb07 ¤   if( s->inFileRef ) {
90d399 ¤   ¤   /* File input */
2b4649 ¤   ¤   if( IsntNull( s->func ) && s->fNullEvents ) {
4c693a ¤   ¤   ¤   pgpFileReadSetCallBack( s->pfrin, encodeLocalCallBack, s );
f90fe4 ¤   ¤   }
7cfb61 ¤   ¤   s->err = pgpFileReadPump( s->pfrin, s->head );
89d223 ¤   ¤   pgpFileReadDestroy( s->pfrin );
f31f7f ¤   ¤   s->pfrin = NULL;
689105 ¤   ¤   if( IsPGPError( s->err ) )
2eed19 ¤   ¤   ¤   goto error;
ebceb4 ¤   ¤   s->err = s->head->sizeAdvise( s->head, 0 );
7b9105 ¤   ¤   if( IsPGPError( s->err ) )
17ed19 ¤   ¤   ¤   goto error;
e3f037 ¤   } else {
df515f ¤   ¤   /* Buffer input */
c94649 ¤   ¤   if( IsntNull( s->func ) && s->fNullEvents ) {
08ff43 ¤   ¤   ¤   s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
487a40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·encodeLocalCallBack, s );
9245a6 ¤   ¤   } else {
33ff43 ¤   ¤   ¤   s->err = pgpPumpMem( s->head, s->inBufPtr, s->inBufLength,
3e9f15 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·NULL, NULL );
1d0fe4 ¤   ¤   }
3a9105 ¤   ¤   if( IsPGPError( s->err ) )
f0ed19 ¤   ¤   ¤   goto error;
c89371 ¤   }
10af5a
eb9a91 ¤   /* Get output buffer bytes-used info if appropriate */
b32d41 ¤   if( s->outPipe ) {
9191aa ¤   ¤   if( IsntNull( s->outBufPtrPtr ) ) {
b1913c ¤   ¤   ¤   /* Dynamically allocated buffer - tell user size & position */
b99a58 ¤   ¤   ¤   if( IsPGPError( s->err = pgpGetVariableMemOutput( s->outPipe,
a19434 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufMaxLength, s->outBufPtrPtr,
e74fef ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->outBufUsedLength ) ) )
311b7c ¤   ¤   ¤   ¤   goto error;
3645a6 ¤   ¤   } else {
d4542a ¤   ¤   ¤   /* Fixed size buffer - tell user actual size used */
5f771d ¤   ¤   ¤   pgpAssert( IsntNull( s->outBufPtr ) );
7d0aa6 ¤   ¤   ¤   if( IsPGPError( s->err = pgpGetMemOutput( s->outPipe,
3a0ef6 ¤   ¤   ¤   ¤   ¤   ¤   s->outBufMaxLength, s->outBufUsedLength ) ) )
b41b7c ¤   ¤   ¤   ¤   goto error;
f40fe4 ¤   ¤   }
a09371 ¤   }
10af5a
03a8dc ¤   /* Get PGPMIME header offset if appropriate */
86efea ¤   if( IsPGPError( s->err = pgpGetPGPMIMEBodyOffset( s->head,·
db1790 ¤   ¤   ¤   ¤   ¤   s->optionList ) ) )
bd97ed ¤   ¤   goto error;
8caf5a
e1c557 ¤   /* Now we can tear down the pipeline */
8e27eb ¤   s->head->teardown( s->head );
fadb0d ¤   s->head = NULL;
4aaf5a
95c9ba ¤   /* Done, clean up and return */
a54d1a ¤   s->err = kPGPError_NoErr;
b3af5a
f960ff error:
64af5a
ee3b36 ¤   if( IsntNull( s->env ) ) {
f81b3b ¤   ¤   pgpenvDestroy( s->env );
--1ca7 0019343289b401001e0 Page 18 of pgpEncode.c
064481 ¤   ¤   s->env = NULL;
8e9371 ¤   }
d7bbb7 ¤   if( IsntNull( s->head ) ) {
bbc898 ¤   ¤   s->head->teardown( s->head );
2aa1f9 ¤   ¤   s->head = NULL;
fe9371 ¤   }
0101aa ¤   if( IsntNull( s->sigspec ) ) {
22aced ¤   ¤   PGPSecKey *skey = pgpSigSpecSeckey(s->sigspec);
d966e3 ¤   ¤   if( IsntNull( skey ) )
ab802d ¤   ¤   ¤   pgpSecKeyDestroy(skey);
9cd19e ¤   ¤   pgpSigSpecDestroy( s->sigspec );
0275cd ¤   ¤   s->sigspec = NULL;
629371 ¤   }
114589 ¤   while( IsntNull( s->pubkeys ) ) {
1dae7d ¤   ¤   PGPPubKey *pk1 = pgpPubKeyNext( s->pubkeys );
305f66 ¤   ¤   pgpPubKeyDestroy( s->pubkeys );
b55f08 ¤   ¤   s->pubkeys = pk1;
f09371 ¤   }
28fc57 ¤   if( IsntNull( s->convkey ) ) {
3c264f ¤   ¤   pgpClearMemory( (s->convkey)->pass, (s->convkey)->passlen );
ba64db ¤   ¤   pgpContextMemFree( context, (char *)(s->convkey)->pass );
dd7e17 ¤   ¤   pgpContextMemFree( context, s->convkey );
5b95d7 ¤   ¤   s->convkey = NULL;
909371 ¤   }
5d91ca ¤   if( IsntNull( s->literal.filename ) ) {
e81633 ¤   ¤   pgpContextMemFree( context, (char *)s->literal.filename );
988edd ¤   ¤   s->literal.filename = NULL;
ec9371 ¤   }
4cfe53 ¤   if( IsntNull( s->pfrin ) ) {
ccd223 ¤   ¤   pgpFileReadDestroy( s->pfrin );
301f7f ¤   ¤   s->pfrin = NULL;
cd9371 ¤   }
6a07b7 ¤   if ( s->err != kPGPError_NoErr && IsntNull( s->outFileRef ) ) {
b1308a ¤   ¤   PFLFileSpecDelete( s->outFileRef );
1a690d ¤   ¤   s->outFileRef = NULL;
799371 ¤   }
e6af5a
2494b8 ¤   /* Notify user via callback of error if requested */
e05dc9 ¤   if( IsPGPError( s->err ) && IsntNull( s->func ) ) {
179a7b ¤   ¤   (void)pgpEventError( s->context, &s->newOptionList, s->func,
c56e77 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·s->userValue, s->err, NULL );
2d7a51 ¤   ¤   pgpCleanupOptionList( &s->newOptionList );
9a9371 ¤   }
141b52 ¤   ¤
d18c1f ¤   (void)pgpEventFinal( s->context, &s->newOptionList, s->func,
5a026f ¤   ¤   ¤   ¤   ¤   ¤   ·s->userValue );
b8a2e3 ¤   pgpCleanupOptionList( &s->newOptionList );
33af5a
b4fd52 ¤   return s->err;
e9efe6 }
0daf5a
4caf5a
84af5a
76af5a
5baf5a
8f7e4d /*__Editor_settings____
23af5a
884126 ¤   Local Variables:
5f7b17 ¤   tab-width: 4
8ef72f ¤   comment-column: 40
250e6c ¤   End:
5a5f8c ¤   vi: ts=4 sw=4
f69e9b ¤   vim: si
93d062 _____________________*/
--c1d8 0007d846e78401001e1 Page 1 of pgpEncodePriv.h
a70335 /*____________________________________________________________________________
925e64 ¤   pgpEncodePriv.h
ff67c5 ¤
edc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
2f4b0f ¤   All rights reserved.
0667c5 ¤
2857b9 ¤   $Id: pgpEncodePriv.h,v 1.29.4.1.2.1 1998/11/12 03:21:41 heller Exp $
f0f7f7 ____________________________________________________________________________*/
31af5a
647008 #ifndef Included_pgpEncodePriv_h¤   /* [ */
e6ae5a #define Included_pgpEncodePriv_h
3eaf5a
b3e82c #include "pgpPubTypes.h"
a09f63 #include "pgpEncode.h"
6c3709 #include "pgpFileMod.h"
39a4b2 #include "pgpFileRef.h"
db0141 #include "pgpOptionListPriv.h"
0b3576 #include "pgpTextFilt.h"
c8af5a
3a14e5 #include "pgpEncPipe.h"¤¤   ¤   /* for pgpLiteralParams */
50af5a
b04ea1 typedef PGPFileReadCallBack PGPProgressCallBack;
7faf5a
40af5a
16266b #define IsOp(x)¤¤   ((PGPBoolean)((x).type!=kPGPOptionType_InvalidOption))
54b02a #define IsntOp(x)¤  ((PGPBoolean)((x).type==kPGPOptionType_InvalidOption))
38af5a
79af5a
e1af5a
bd9cec struct PGPJob
f0bb36 {
e77925 ¤   PGPContextRef¤  ¤   context;
33f209 ¤   PGPOptionListRef¤   newOptionList;
d082f7 };
21d948 typedef struct PGPJob¤  PGPJob;
49af5a
6faf5a
c099c6 PGP_BEGIN_C_DECLARATIONS
b9af5a
0daf5a
d0c0d3 PGPError ¤  pgpEncodeInternal(PGPContextRef context,
c7870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
045646 PGPError ¤  pgpDecodeInternal(PGPContextRef context,
11870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
cbaf5a
f5af5a
7e6026 /* Helper functions for Encode/Decode */
69af5a
e4609e PGPError¤   pgpPumpMem(PGPPipeline *head, PGPByte *inBufPtr,
89b2cc ¤   ¤   ¤   ¤   ¤   ¤   PGPSize inBufLength, PGPProgressCallBack callBack,
014ce0 ¤   ¤   ¤   ¤   ¤   ¤   void *callBackArg);
43af5a
a60c3e PGPError¤   pgpWarnUser(PGPContextRef context, PGPOptionListRef optionList,
3fc2dd ¤   ¤   ¤   ¤   ¤   ¤   PGPError errCode, void *warnArg);
12af5a
95baae PGPError¤   pgpGetMinValidity(PGPOptionListRef optionList,
b26705 ¤   ¤   ¤   ¤   ¤   ¤   PGPValidity *failValidity, PGPValidity *warnValidity);
8aaf5a
846e48 PGPError¤   pgpCheckKeyValidity(PGPContextRef context,
bbffe0 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList, PGPKey *key,
1453a7 ¤   ¤   ¤   ¤   ¤   ¤   RingSet const *ringSet, PGPValidity failValidity,
c86a8b ¤   ¤   ¤   ¤   ¤   ¤   PGPValidity warnValidity, PGPKeySet *warnKeySet,
3a7dfe ¤   ¤   ¤   ¤   ¤   ¤   PGPValidity *pValidity);
deaf5a
11382c PGPError¤   pgpGetMemOutput(PGPPipeline *pipeBuf, PGPSize bufferSize,
2fae18 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outputBufferLen);
aeaf5a
fd7ea1 PGPError¤   pgpGetVariableMemOutput(PGPPipeline *pipeBuf, PGPSize maxSize,
06ac89 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **outputBufferPtr, PGPSize *outputBufferLen);
30af5a
bc3858 PGPError¤   pgpGetPGPMIMEBodyOffset(PGPPipeline *pipeBuf,
7d870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
--9451 0010d4de0bf401001e1 Page 2 of pgpEncodePriv.h
e0af5a
53b818 PGPLineEndType¤ pgpGetDefaultLineEndType (void);
53af5a
6cdd8a PGPFileOpenFlags¤   pgpLocalEncodingToFlags(PGPUInt32 localEncode);
80af5a
fb674d PGPError¤   pgpSetupCallback(PGPOptionListRef optionList,
b1269c ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr *func,
a0a807 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue *userValue, PGPBoolean *fNullEvents);
18af5a
d39818 PGPError¤   pgpSetupInput(PGPContextRef context, PGPOptionListRef optionList,
938415 ¤   ¤   ¤   ¤   ¤   ¤   PgpLiteralParams *literal, PGPRandomContext *rng,
0784b0 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean inputMode, PGPBoolean detachedSignature,
d43e9a ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef *inFileRef, PGPFileRead **pfrin,
2045a2 ¤   ¤   ¤   ¤   ¤   ¤   PGPFileDataType *inFileDataType,
409edb ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **inBufPtr, PGPSize *inBufLength);
1faf5a
74f5b4 PGPError¤   pgpSetupOutputPipeline(PGPContextRef context,
938d0e ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList, PGPEnv *env,
3b30d6 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean fEncrypt, PGPBoolean fSign,
94c02a ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean fDetachedSig, PGPBoolean fAppendOutput,
910154 ¤   ¤   ¤   ¤   ¤   ¤   PGPPipeline ***tail,
784631 ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef *outFileRef, PGPFile **pfout,
660c77 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **outBufPtr, PGPByte ***outBufPtrPtr,
605d0d ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outBufLength, PGPSize **outBufUsed,
457db0 ¤   ¤   ¤   ¤   ¤   ¤   PGPPipeline **outPipe);
16af5a
51af5a
891254 PGP_END_C_DECLARATIONS
2baf5a
9598d1 #endif /* ] Included_pgpEncodePriv_h */
5daf5a
a8af5a
357e4d /*__Editor_settings____
edaf5a
b74126 ¤   Local Variables:
d57b17 ¤   tab-width: 4
3f0e6c ¤   End:
275f8c ¤   vi: ts=4 sw=4
039e9b ¤   vim: si
0dd062 _____________________*/
--465a 0003d7e4abb401001e2 Page 1 of pgpEvent.c
a70335 /*____________________________________________________________________________
c1db47 ¤   pgpEvent.c
969641 ¤   Handle application event callbacks
5867c5 ¤
b7c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
fa4b0f ¤   All rights reserved.
d667c5 ¤
9a67c5 ¤
a4af5a
398b5f ¤   $Id: pgpEvent.c,v 1.31.10.1 1998/11/12 03:21:41 heller Exp $
96f7f7 ____________________________________________________________________________*/
dbd224 #include "pgpConfig.h"¤ /* or pgpConfig.h in the CDK */
70af5a
fd324c #include <string.h>
13af5a
c5eb3d /* Public headers */
0ce82c #include "pgpPubTypes.h"
8fc26c #include "pgpContext.h"
079f63 #include "pgpEncode.h"
592f8d #include "pgpErrors.h"
63a076 #include "pgpKeys.h"
d50d08 #include "pgpMem.h"
47af5a
3b622b /* Private headers */
a32d40 #include "pgpEventPriv.h"
5b8b0d #include "pgpEncodePriv.h"
caaf5a
edda95 /************************** User event callback ****************************/
acaf5a
e8c744 ¤   PGPError
748c05 pgpEventNull(
87a1bc ¤   PGPContextRef¤  ¤   context,
a636e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
2d7e1e ¤   PGPEventHandlerProcPtr func,
cc96f3 ¤   PGPUserValue¤   ¤   userValue,
3ca5b7 ¤   PGPFileOffset¤  ¤   soFar,
149f4a ¤   PGPFileOffset¤  ¤   total
be27e6 ¤   )
01cebb {¤
5b6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
3a8e3c ¤   PGPEvent¤   ¤   ¤   event;
c58f52 ¤   PGPError¤   ¤   ¤   err;
f0af5a
deff51 ¤   *newOptionList = NULL;
eac181 ¤   if( IsNull( func ) )
d7b840 ¤   ¤   return kPGPError_NoErr;
50af5a
f15054 ¤   job.context¤¤   ¤   = context;
956ba6 ¤   job.newOptionList¤  = NULL;
fbaf5a
aa88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
2f770d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   = &job;
b1b7f2 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_NullEvent;
7fe860 ¤   event.data.nullData.bytesWritten¤   = soFar;
aaf494 ¤   event.data.nullData.bytesTotal¤ ¤   = total;
6caf5a
b30ee7 ¤   err = func( context, &event, userValue );
0faf5a
68909a ¤   *newOptionList = job.newOptionList;
f65ea8 ¤   return err;
e3efe6 }
95af5a
46af5a
fdc744 ¤   PGPError
92ebbc pgpEventInitial(
daa1bc ¤   PGPContextRef¤  ¤   context,
0636e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
6f7e1e ¤   PGPEventHandlerProcPtr func,
862e8c ¤   PGPUserValue¤   ¤   userValue
4d27e6 ¤   )
61bb36 {
3d6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
--f9d8 000fc23069c401001e2 Page 2 of pgpEvent.c
528e3c ¤   PGPEvent¤   ¤   ¤   event;
4e8f52 ¤   PGPError¤   ¤   ¤   err;
eeaf5a
b6ff51 ¤   *newOptionList = NULL;
35c181 ¤   if( IsNull( func ) )
9ab840 ¤   ¤   return kPGPError_NoErr;
74af5a
095054 ¤   job.context¤¤   ¤   = context;
416ba6 ¤   job.newOptionList¤  = NULL;
bfaf5a
9388b9 ¤   pgpClearMemory( &event, sizeof( event ) );
41770d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   = &job;
dd39f7 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_InitialEvent;
95af5a
0f0ee7 ¤   err = func( context, &event, userValue );
b1af5a
0a909a ¤   *newOptionList = job.newOptionList;
955ea8 ¤   return err;
20efe6 }
3aaf5a
9eaf5a
75c744 ¤   PGPError
96bd40 pgpEventFinal(
96a1bc ¤   PGPContextRef¤  ¤   context,
b436e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
7c7e1e ¤   PGPEventHandlerProcPtr func,
0f2e8c ¤   PGPUserValue¤   ¤   userValue
c527e6 ¤   )
1bbb36 {
a46c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
818e3c ¤   PGPEvent¤   ¤   ¤   event;
a28f52 ¤   PGPError¤   ¤   ¤   err;
62af5a
0dff51 ¤   *newOptionList = NULL;
d5c181 ¤   if( IsNull( func ) )
61b840 ¤   ¤   return kPGPError_NoErr;
9eaf5a
af5054 ¤   job.context¤¤   ¤   = context;
ac6ba6 ¤   job.newOptionList¤  = NULL;
24af5a
7e88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
a6770d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   = &job;
4f2688 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_FinalEvent;
84af5a
060ee7 ¤   err = func( context, &event, userValue );
ffaf5a
68909a ¤   *newOptionList = job.newOptionList;
315ea8 ¤   return err;
58efe6 }
22af5a
59af5a
86c744 ¤   PGPError
bf8207 pgpEventError(
3aa1bc ¤   PGPContextRef¤  ¤   context,
1336e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
b87e1e ¤   PGPEventHandlerProcPtr func,
0696f3 ¤   PGPUserValue¤   ¤   userValue,
b35891 ¤   PGPError¤   ¤   ¤   error,
bcf475 ¤   void¤   ¤   ¤   ···*errorArg
cd27e6 ¤   )
a3bb36 {
956c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
c48e3c ¤   PGPEvent¤   ¤   ¤   event;
a28f52 ¤   PGPError¤   ¤   ¤   err;
96af5a
ceff51 ¤   *newOptionList = NULL;
54c181 ¤   if( IsNull( func ) )
35b840 ¤   ¤   return kPGPError_NoErr;
d4af5a
c25054 ¤   job.context¤¤   ¤   = context;
9a6ba6 ¤   job.newOptionList¤  = NULL;
fcaf5a
--9ef2 000d564d4d7401001e2 Page 3 of pgpEvent.c
6788b9 ¤   pgpClearMemory( &event, sizeof( event ) );
35770d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   = &job;
98297d ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_ErrorEvent;
6666b7 ¤   event.data.errorData.error¤ ¤   ¤   = error;
29f985 ¤   event.data.errorData.errorArg¤  ¤   = errorArg;
5baf5a
0c0ee7 ¤   err = func( context, &event, userValue );
3aaf5a
72909a ¤   *newOptionList = job.newOptionList;
385ea8 ¤   return err;
1defe6 }
80af5a
0cc744 ¤   PGPError
984de5 pgpEventWarning(
91a1bc ¤   PGPContextRef¤  ¤   context,
d336e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
957e1e ¤   PGPEventHandlerProcPtr func,
1a96f3 ¤   PGPUserValue¤   ¤   userValue,
fa6c33 ¤   PGPError¤   ¤   ¤   warning,
be2e56 ¤   void¤   ¤   ¤   ···*warningArg
3527e6 ¤   )
64bb36 {
a06c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
ce8e3c ¤   PGPEvent¤   ¤   ¤   event;
158f52 ¤   PGPError¤   ¤   ¤   err;
b6af5a
a8ff51 ¤   *newOptionList = NULL;
75c181 ¤   if( IsNull( func ) )
5db840 ¤   ¤   return kPGPError_NoErr;
01af5a
105054 ¤   job.context¤¤   ¤   = context;
f96ba6 ¤   job.newOptionList¤  = NULL;
70af5a
fe88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
a2770d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   = &job;
0bf456 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_WarningEvent;
6e435b ¤   event.data.warningData.warning¤ ¤   = warning;
44940a ¤   event.data.warningData.warningArg¤  = warningArg;
afaf5a
fa0ee7 ¤   err = func( context, &event, userValue );
c4af5a
16909a ¤   *newOptionList = job.newOptionList;
2e5ea8 ¤   return err;
91efe6 }
9caf5a
04c744 ¤   PGPError
ff7045 pgpEventEntropy(
d7a1bc ¤   PGPContextRef¤  ¤   context,
8136e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
3a7e1e ¤   PGPEventHandlerProcPtr func,
2f96f3 ¤   PGPUserValue¤   ¤   userValue,
625d83 ¤   PGPUInt32¤  ¤   ¤   entropyBitsNeeded
2827e6 ¤   )
87bb36 {
756c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
b98e3c ¤   PGPEvent¤   ¤   ¤   event;
a98f52 ¤   PGPError¤   ¤   ¤   err;
efaf5a
5bff51 ¤   *newOptionList = NULL;
c1c181 ¤   if( IsNull( func ) )
81b840 ¤   ¤   return kPGPError_NoErr;
feaf5a
2c5054 ¤   job.context¤¤   ¤   = context;
9c6ba6 ¤   job.newOptionList¤  = NULL;
e4af5a
e888b9 ¤   pgpClearMemory( &event, sizeof( event ) );
9a90bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
5e6cac ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_EntropyEvent;
4b1a4d ¤   event.data.entropyData.entropyBitsNeeded¤   = entropyBitsNeeded;
4aaf5a
040ee7 ¤   err = func( context, &event, userValue );
d5af5a
--961f 000e21d5c37401001e2 Page 4 of pgpEvent.c
10909a ¤   *newOptionList = job.newOptionList;
425ea8 ¤   return err;
83efe6 }
52af5a
00c744 ¤   PGPError
ef2e43 pgpEventPassphrase(
71a1bc ¤   PGPContextRef¤  ¤   context,
8236e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
a57e1e ¤   PGPEventHandlerProcPtr func,
1196f3 ¤   PGPUserValue¤   ¤   userValue,
e0502c ¤   PGPBoolean¤ ¤   ¤   fConventional,
41b783 ¤   PGPKeySetRef¤   ¤   keyset
9027e6 ¤   )
4ebb36 {
d56c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
228e3c ¤   PGPEvent¤   ¤   ¤   event;
cf8f52 ¤   PGPError¤   ¤   ¤   err;
29af5a
99ff51 ¤   *newOptionList = NULL;
b4c181 ¤   if( IsNull( func ) )
a6b840 ¤   ¤   return kPGPError_NoErr;
17af5a
dd5054 ¤   job.context¤¤   ¤   = context;
ff6ba6 ¤   job.newOptionList¤  = NULL;
84af5a
0a88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
bd90bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
73f272 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_PassphraseEvent;
0d6d09 ¤   event.data.passphraseData.fConventional¤¤   = fConventional;
16bf8f ¤   event.data.passphraseData.keyset¤   ¤   ¤   = keyset;
b4af5a
2f0ee7 ¤   err = func( context, &event, userValue );
fcaf5a
a0909a ¤   *newOptionList = job.newOptionList;
0b5ea8 ¤   return err;
8aefe6 }
94af5a
74c744 ¤   PGPError
170298 pgpEventAnalyze(
b9a1bc ¤   PGPContextRef¤  ¤   context,
6b36e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
3d7e1e ¤   PGPEventHandlerProcPtr func,
4496f3 ¤   PGPUserValue¤   ¤   userValue,
d51849 ¤   PGPAnalyzeType¤ ¤   type
ed27e6 ¤   )
c8bb36 {
9a6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
958e3c ¤   PGPEvent¤   ¤   ¤   event;
098f52 ¤   PGPError¤   ¤   ¤   err;
53af5a
b5ff51 ¤   *newOptionList = NULL;
c0c181 ¤   if( IsNull( func ) )
50b840 ¤   ¤   return kPGPError_NoErr;
c7af5a
bd5054 ¤   job.context¤¤   ¤   = context;
706ba6 ¤   job.newOptionList¤  = NULL;
85af5a
5a88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
fa90bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
968cdc ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_AnalyzeEvent;
8b40a8 ¤   event.data.analyzeData.sectionType¤ ¤   ¤   = type;
21af5a
ab0ee7 ¤   err = func( context, &event, userValue );
54af5a
bc909a ¤   *newOptionList = job.newOptionList;
525ea8 ¤   return err;
faefe6 }
d5af5a
cdc744 ¤   PGPError
76147e pgpEventRecipients(
37a1bc ¤   PGPContextRef¤  ¤   context,
e236e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
--6e33 000e12b7e5a401001e2 Page 5 of pgpEvent.c
517e1e ¤   PGPEventHandlerProcPtr func,
5396f3 ¤   PGPUserValue¤   ¤   userValue,
96bcb4 ¤   PGPKeySetRef¤   ¤   recipientSet,
3a81b6 ¤   PGPKeyID¤   ¤   ¤   *keyIDArray,
aadc73 ¤   PGPUInt32¤  ¤   ¤   passphraseCount,
02451e ¤   PGPUInt32¤  ¤   ¤   keyCount
1427e6 ¤   )
c9bb36 {
3b6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
898e3c ¤   PGPEvent¤   ¤   ¤   event;
d58f52 ¤   PGPError¤   ¤   ¤   err;
88af5a
b7ff51 ¤   *newOptionList = NULL;
1bc181 ¤   if( IsNull( func ) )
2ab840 ¤   ¤   return kPGPError_NoErr;
d2af5a
745054 ¤   job.context¤¤   ¤   = context;
986ba6 ¤   job.newOptionList¤  = NULL;
57af5a
dc88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
a990bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
c3ca8b ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_RecipientsEvent;
da0b74 ¤   event.data.recipientsData.recipientSet¤ ¤   = recipientSet;
d36625 ¤   event.data.recipientsData.keyIDArray¤   ¤   = keyIDArray;
bfa62a ¤   event.data.recipientsData.conventionalPassphraseCount
49d2ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = passphraseCount;
46e702 ¤   event.data.recipientsData.keyCount¤ ¤   ¤   = keyCount;
72af5a
730ee7 ¤   err = func( context, &event, userValue );
ecaf5a
59909a ¤   *newOptionList = job.newOptionList;
075ea8 ¤   return err;
21efe6 }
d5af5a
a3c744 ¤   PGPError
b090d6 pgpEventKeyFound(
9da1bc ¤   PGPContextRef¤  ¤   context,
c436e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
907e1e ¤   PGPEventHandlerProcPtr func,
7396f3 ¤   PGPUserValue¤   ¤   userValue,
fc38d0 ¤   PGPKeySetRef¤   ¤   keySet
c227e6 ¤   )
5abb36 {
796c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
248e3c ¤   PGPEvent¤   ¤   ¤   event;
008f52 ¤   PGPError¤   ¤   ¤   err;
cbaf5a
17ff51 ¤   *newOptionList = NULL;
78c181 ¤   if( IsNull( func ) )
aeb840 ¤   ¤   return kPGPError_NoErr;
70af5a
2b5054 ¤   job.context¤¤   ¤   = context;
d86ba6 ¤   job.newOptionList¤  = NULL;
e8af5a
b988b9 ¤   pgpClearMemory( &event, sizeof( event ) );
3590bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
3276be ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_KeyFoundEvent;
6ca639 ¤   event.data.keyFoundData.keySet¤ ¤   ¤   ¤   = keySet;
6baf5a
960ee7 ¤   err = func( context, &event, userValue );
44af5a
8f909a ¤   *newOptionList = job.newOptionList;
3c5ea8 ¤   return err;
40efe6 }
20af5a
fec744 ¤   PGPError
219d08 pgpEventOutput(
97a1bc ¤   PGPContextRef¤  ¤   context,
8836e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
4f7e1e ¤   PGPEventHandlerProcPtr func,
da96f3 ¤   PGPUserValue¤   ¤   userValue,
e115ca ¤   PGPUInt32¤  ¤   ¤   messageType,
--30a6 00011b343c6401001e2 Page 6 of pgpEvent.c
d5caa7 ¤   char const¤ ¤   ···*suggestedName,
afd4da ¤   PGPBoolean¤ ¤   ¤   FYEO
4927e6 ¤   )
3dbb36 {
bbee5a ¤   PGPJob¤ ¤   job;
06557d ¤   PGPEvent¤   event;
d161e0 ¤   PGPError¤   err;
d268aa ¤   char¤   ¤   *canonicalName = NULL;
0367c5 ¤
97ff51 ¤   *newOptionList = NULL;
59c181 ¤   if( IsNull( func ) )
59b840 ¤   ¤   return kPGPError_NoErr;
09af5a
7b5054 ¤   job.context¤¤   ¤   = context;
606ba6 ¤   job.newOptionList¤  = NULL;
29af5a
be420f ¤   if( IsntNull( suggestedName ) )
93c7a1 ¤   {
6baca5 ¤   ¤   /* Convert all illegal characters to underscores */
b91b52 ¤   ¤
a16b4c ¤   ¤   canonicalName = (char *) PGPNewData( PGPGetContextMemoryMgr( context ),
c7b4ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( suggestedName ) + 1, 0 );
ea062d ¤   ¤   if( IsntNull( canonicalName ) )
b55b34 ¤   ¤   {
8a99cf ¤   ¤   ¤   char¤   *cur = canonicalName;
e587c7 ¤   ¤   ¤
05faf7 ¤   ¤   ¤   strcpy( canonicalName, suggestedName );
4187c7 ¤   ¤   ¤
31f1e3 ¤   ¤   #if PGP_MACINTOSH
f4bf1d ¤   ¤   ¤   /* Macs are unhappy with filenames starting with '.' */
06a6da ¤   ¤   ¤   if( *cur == '.' )
3bbbc3 ¤   ¤   ¤   ¤   *cur = '_';
8ed656 ¤   ¤   #endif
401b52 ¤   ¤
f73fd5 ¤   ¤   ¤   while( *cur != 0 )
43f776 ¤   ¤   ¤   {
1a78b7 ¤   ¤   ¤   #if PGP_MACINTOSH
778739 ¤   ¤   ¤   ¤   if( *cur < ' ' || *cur == ':' )
64dfc9 ¤   ¤   ¤   #elif PGP_WIN32 || PGP_UNIX
6e886d ¤   ¤   ¤   ¤   if ((*cur < ' ') ·|| (*cur == ':') || (*cur == '/') ||·
f8c5f4 ¤   ¤   ¤   ¤   ¤   (*cur == '?') || (*cur == '*') || (*cur == '"') ||·
17eb1b ¤   ¤   ¤   ¤   ¤   (*cur == '>') || (*cur == '\\') || (*cur == '|') ||·
535c05 ¤   ¤   ¤   ¤   ¤   (*cur == 0x5C) )¤   /* \ */
ff6e43 ¤   ¤   ¤   #else
dab2c9 ¤   ¤   ¤   ¤   #error Unknown platform
cc34f5 ¤   ¤   ¤   #endif
1872c3 ¤   ¤   ¤   ¤   {
dc169d ¤   ¤   ¤   ¤   ¤   *cur = '_';
502613 ¤   ¤   ¤   ¤   }
a62b85 ¤   ¤   ¤   ¤
b48651 ¤   ¤   ¤   ¤   ++cur;
86a3a6 ¤   ¤   ¤   }
a00fe4 ¤   ¤   }
f49371 ¤   }
6b67c5 ¤
1a88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
2390bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
d1efe6 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_OutputEvent;
45e721 ¤   event.data.outputData.messageType¤  ¤   ¤   = messageType;
38c05a ¤   event.data.outputData.suggestedName¤¤   ¤   = canonicalName;
43072a ¤   event.data.outputData.forYourEyesOnly¤  ¤   = FYEO;
c0af5a
a80ee7 ¤   err = func( context, &event, userValue );
2faf5a
ae909a ¤   *newOptionList = job.newOptionList;
0167c5 ¤
43c378 ¤   if( IsntNull( canonicalName ) )
57bd15 ¤   ¤   PGPFreeData( canonicalName );
cd1b52 ¤   ¤
9e5ea8 ¤   return err;
b2efe6 }
11af5a
--4c27 0002e97885f401001e2 Page 7 of pgpEvent.c
d3c744 ¤   PGPError
b2a731 pgpEventSignature(
69a1bc ¤   PGPContextRef¤  ¤   context,
4c36e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
267e1e ¤   PGPEventHandlerProcPtr func,
8996f3 ¤   PGPUserValue¤   ¤   userValue,
3dd0db ¤   PGPKeyID const *¤   signingKeyID,
0d6e01 ¤   PGPKeyRef¤  ¤   ¤   signingKey,
6de818 ¤   PGPBoolean¤ ¤   ¤   checked,
feb762 ¤   PGPBoolean¤ ¤   ¤   verified,
988dd9 ¤   PGPBoolean¤ ¤   ¤   keyDisabled,
e70eb2 ¤   PGPBoolean¤ ¤   ¤   keyRevoked,
e35c72 ¤   PGPBoolean¤ ¤   ¤   keyExpired,
5c814c ¤   PGPBoolean¤ ¤   ¤   keyValidityThreshold,
36e141 ¤   PGPValidity¤¤   ¤   keyValidity,
821bad ¤   PGPTime¤¤   ¤   ¤   creationTime
c227e6 ¤   )
72bb36 {
c56c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
918e3c ¤   PGPEvent¤   ¤   ¤   event;
de8f52 ¤   PGPError¤   ¤   ¤   err;
f5af5a
a3ff51 ¤   *newOptionList = NULL;
a5c181 ¤   if( IsNull( func ) )
40b840 ¤   ¤   return kPGPError_NoErr;
edaf5a
4b5054 ¤   job.context¤¤   ¤   = context;
756ba6 ¤   job.newOptionList¤  = NULL;
cdaf5a
5c88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
7490bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
c92557 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_SignatureEvent;
9603bf ¤   event.data.signatureData.signingKeyID¤  ¤   = *signingKeyID;
442068 ¤   event.data.signatureData.signingKey¤¤   ¤   = signingKey;
955703 ¤   event.data.signatureData.checked¤   ¤   ¤   = checked;
5dfb45 ¤   event.data.signatureData.verified¤  ¤   ¤   = verified;
ab5c76 ¤   event.data.signatureData.keyDisabled¤   ¤   = keyDisabled;
0da2b0 ¤   event.data.signatureData.keyRevoked¤¤   ¤   = keyRevoked;
2c61d0 ¤   event.data.signatureData.keyExpired¤¤   ¤   = keyExpired;
a9c5a2 ¤   event.data.signatureData.keyMeetsValidityThreshold = keyValidityThreshold;
bd338c ¤   event.data.signatureData.keyValidity¤   ¤   = keyValidity;
83133b ¤   event.data.signatureData.creationTime¤  ¤   = creationTime;
efaf5a
f90ee7 ¤   err = func( context, &event, userValue );
18af5a
bb909a ¤   *newOptionList = job.newOptionList;
ea5ea8 ¤   return err;
f5efe6 }
09af5a
33af5a
aec744 ¤   PGPError
6207d8 pgpEventDecryption(
16a1bc ¤   PGPContextRef¤  ¤   context,
cd36e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
a17e1e ¤   PGPEventHandlerProcPtr func,
b496f3 ¤   PGPUserValue¤   ¤   userValue,
755d2f ¤   PGPCipherAlgorithm¤ cipheralg
1927e6 ¤   )
1abb36 {
c66c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
a28e3c ¤   PGPEvent¤   ¤   ¤   event;
ca8f52 ¤   PGPError¤   ¤   ¤   err;
92af5a
6fff51 ¤   *newOptionList = NULL;
08c181 ¤   if( IsNull( func ) )
e2b840 ¤   ¤   return kPGPError_NoErr;
4eaf5a
915054 ¤   job.context¤¤   ¤   = context;
3a6ba6 ¤   job.newOptionList¤  = NULL;
7eaf5a
ca88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
2e90bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
--c311 000d588c486401001e2 Page 8 of pgpEvent.c
f5fdbb ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_DecryptionEvent;
9b6c24 ¤   event.data.decryptionData.cipherAlgorithm¤  = cipheralg;
e4af5a
0c0ee7 ¤   err = func( context, &event, userValue );
3daf5a
97909a ¤   *newOptionList = job.newOptionList;
c55ea8 ¤   return err;
03efe6 }
72af5a
beaf5a
a0c744 ¤   PGPError
f8a567 pgpEventBeginLex(
95a1bc ¤   PGPContextRef¤  ¤   context,
a736e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
fb7e1e ¤   PGPEventHandlerProcPtr func,
1196f3 ¤   PGPUserValue¤   ¤   userValue,
12980e ¤   PGPUInt32¤  ¤   ¤   sectionNumber,
bc3b29 ¤   PGPSize¤¤   ¤   ¤   sectionOffset
b927e6 ¤   )
39bb36 {
366c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
648e3c ¤   PGPEvent¤   ¤   ¤   event;
a08f52 ¤   PGPError¤   ¤   ¤   err;
e8af5a
8cff51 ¤   *newOptionList = NULL;
bcc181 ¤   if( IsNull( func ) )
4ab840 ¤   ¤   return kPGPError_NoErr;
dcaf5a
f85054 ¤   job.context¤¤   ¤   = context;
5e6ba6 ¤   job.newOptionList¤  = NULL;
47af5a
df88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
ae2c4d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
683214 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_BeginLexEvent;
2e3a20 ¤   event.data.beginLexData.sectionNumber¤  = sectionNumber;
2fa5da ¤   event.data.beginLexData.sectionOffset¤  = sectionOffset;
3caf5a
340ee7 ¤   err = func( context, &event, userValue );
82af5a
e9909a ¤   *newOptionList = job.newOptionList;
8e5ea8 ¤   return err;
5defe6 }
09af5a
7bc744 ¤   PGPError
cbffc3 pgpEventEndLex(
b1a1bc ¤   PGPContextRef¤  ¤   context,
0736e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
907e1e ¤   PGPEventHandlerProcPtr func,
9b96f3 ¤   PGPUserValue¤   ¤   userValue,
30a362 ¤   PGPUInt32¤  ¤   ¤   sectionNumber
bc27e6 ¤   )
88bb36 {
7e6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
8d8e3c ¤   PGPEvent¤   ¤   ¤   event;
b58f52 ¤   PGPError¤   ¤   ¤   err;
6aaf5a
55ff51 ¤   *newOptionList = NULL;
e6c181 ¤   if( IsNull( func ) )
57b840 ¤   ¤   return kPGPError_NoErr;
0caf5a
ac5054 ¤   job.context¤¤   ¤   = context;
b36ba6 ¤   job.newOptionList¤  = NULL;
b0af5a
7888b9 ¤   pgpClearMemory( &event, sizeof( event ) );
e72c4d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
c2a451 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_EndLexEvent;
a5d0d0 ¤   event.data.endLexData.sectionNumber¤¤   = sectionNumber;
38af5a
f70ee7 ¤   err = func( context, &event, userValue );
62af5a
35909a ¤   *newOptionList = job.newOptionList;
d55ea8 ¤   return err;
--a147 000967e3595401001e2 Page 9 of pgpEvent.c
7aefe6 }
46af5a
b0c744 ¤   PGPError
e83a2f pgpEventDetachedSignature(
53a1bc ¤   PGPContextRef¤  ¤   context,
9836e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
077e1e ¤   PGPEventHandlerProcPtr func,
1d2e8c ¤   PGPUserValue¤   ¤   userValue
5c27e6 ¤   )
8dbb36 {
e46c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
988e3c ¤   PGPEvent¤   ¤   ¤   event;
138f52 ¤   PGPError¤   ¤   ¤   err;
ddaf5a
5eff51 ¤   *newOptionList = NULL;
fac181 ¤   if( IsNull( func ) )
0db840 ¤   ¤   return kPGPError_NoErr;
6aaf5a
955054 ¤   job.context¤¤   ¤   = context;
646ba6 ¤   job.newOptionList¤  = NULL;
bbaf5a
f088b9 ¤   pgpClearMemory( &event, sizeof( event ) );
08770d ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   = &job;
28f502 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_DetachedSignatureEvent;
87af5a
9b0ee7 ¤   err = func( context, &event, userValue );
17af5a
ad909a ¤   *newOptionList = job.newOptionList;
335ea8 ¤   return err;
c0efe6 }
fdaf5a
32c744 ¤   PGPError
a8da83 pgpEventKeyGen(
40a1bc ¤   PGPContextRef¤  ¤   context,
6736e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
4f7e1e ¤   PGPEventHandlerProcPtr func,
4096f3 ¤   PGPUserValue¤   ¤   userValue,
6fd316 ¤   PGPUInt32¤  ¤   ¤   state
f727e6 ¤   )
0abb36 {
796c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
038e3c ¤   PGPEvent¤   ¤   ¤   event;
f88f52 ¤   PGPError¤   ¤   ¤   err;
0baf5a
ccff51 ¤   *newOptionList = NULL;
7ac181 ¤   if( IsNull( func ) )
e9b840 ¤   ¤   return kPGPError_NoErr;
d0af5a
f55054 ¤   job.context¤¤   ¤   = context;
116ba6 ¤   job.newOptionList¤  = NULL;
b6af5a
1088b9 ¤   pgpClearMemory( &event, sizeof( event ) );
2790bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
5f63c9 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_KeyGenEvent;
a4a197 ¤   event.data.keyGenData.state¤¤   ¤   ¤   ¤   = state;
a6af5a
820ee7 ¤   err = func( context, &event, userValue );
49af5a
eb909a ¤   *newOptionList = job.newOptionList;
6b5ea8 ¤   return err;
70efe6 }
e6af5a
b5c744 ¤   PGPError
45372f pgpEventKeyServer(
31a1bc ¤   PGPContextRef¤  ¤   context,
ef7e1e ¤   PGPEventHandlerProcPtr func,
8b96f3 ¤   PGPUserValue¤   ¤   userValue,
d2c308 ¤   PGPKeyServerRef¤¤   keyServerRef,
ddd365 ¤   PGPUInt32¤  ¤   ¤   state)
9cbb36 {
de6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
968e3c ¤   PGPEvent¤   ¤   ¤   event;
--a9de 0002f51f98e401001e2 Page 10 of pgpEvent.c
118f52 ¤   PGPError¤   ¤   ¤   err;
f8af5a
5ec181 ¤   if( IsNull( func ) )
6ab840 ¤   ¤   return kPGPError_NoErr;
d9af5a
555054 ¤   job.context¤¤   ¤   = context;
8a6ba6 ¤   job.newOptionList¤  = NULL;
e1af5a
2f88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
fd90bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
9f1e60 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_KeyServerEvent;
571bd9 ¤   event.data.keyServerData.state¤ ¤   ¤   ¤   = state;
dc843c ¤   event.data.keyServerData.keyServerRef¤  ¤   = keyServerRef;
2caf5a
f50ee7 ¤   err = func( context, &event, userValue );
b7af5a
025ea8 ¤   return err;
90efe6 }
81af5a
54c744 ¤   PGPError
49fa60 pgpEventKeyServerSign(
cea1bc ¤   PGPContextRef¤  ¤   context,
3136e8 ¤   PGPOptionListRef ··*newOptionList,¤ /* Output parameter */
317e1e ¤   PGPEventHandlerProcPtr func,
0396f3 ¤   PGPUserValue¤   ¤   userValue,
13bdb0 ¤   PGPKeyServerRef¤¤   keyServerRef)
dbbb36 {
ee6c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
e48e3c ¤   PGPEvent¤   ¤   ¤   event;
fc8f52 ¤   PGPError¤   ¤   ¤   err;
25af5a
b4ff51 ¤   *newOptionList = NULL;
30c181 ¤   if( IsNull( func ) )
dbb840 ¤   ¤   return kPGPError_NoErr;
dcaf5a
fa5054 ¤   job.context¤¤   ¤   = context;
ce6ba6 ¤   job.newOptionList¤  = NULL;
24af5a
cf88b9 ¤   pgpClearMemory( &event, sizeof( event ) );
6390bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
89f0bd ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_KeyServerSignEvent;
c4e323 ¤   event.data.keyServerSignData.keyServerRef¤  = keyServerRef;
f5af5a
0d0ee7 ¤   err = func( context, &event, userValue );
c2af5a
26909a ¤   *newOptionList = job.newOptionList;
2f5ea8 ¤   return err;
1fefe6 }
2caf5a
b3af5a
0daf5a
a3c744 ¤   PGPError
13a396 pgpEventKeyServerTLS(
b5a1bc ¤   PGPContextRef¤  ¤   context,
537e1e ¤   PGPEventHandlerProcPtr func,
1a96f3 ¤   PGPUserValue¤   ¤   userValue,
97c308 ¤   PGPKeyServerRef¤¤   keyServerRef,
e4addd ¤   PGPUInt32¤  ¤   ¤   state,
4ad6f4 ¤   PGPtlsSessionRef¤   tlsSession)
ccbb36 {
e26c3c ¤   PGPJob¤ ¤   ¤   ¤   job;
5f8e3c ¤   PGPEvent¤   ¤   ¤   event;
448f52 ¤   PGPError¤   ¤   ¤   err;
c8af5a
1ec181 ¤   if( IsNull( func ) )
64b840 ¤   ¤   return kPGPError_NoErr;
18af5a
845054 ¤   job.context¤¤   ¤   = context;
896ba6 ¤   job.newOptionList¤  = NULL;
93af5a
5388b9 ¤   pgpClearMemory( &event, sizeof( event ) );
2f90bf ¤   event.job¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = &job;
--5c75 00171b51425401001e2 Page 11 of pgpEvent.c
961471 ¤   event.type¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   = kPGPEvent_KeyServerTLSEvent;
01c021 ¤   event.data.keyServerTLSData.state¤  ¤   ¤   = state;
a53c62 ¤   event.data.keyServerTLSData.keyServerRef¤   = keyServerRef;
0d61dd ¤   event.data.keyServerTLSData.tlsSession¤ ¤   = tlsSession;
f3af5a
760ee7 ¤   err = func( context, &event, userValue );
3caf5a
f85ea8 ¤   return err;
d5efe6 }
63af5a
6a7e4d /*__Editor_settings____
45af5a
1d4126 ¤   Local Variables:
df7b17 ¤   tab-width: 4
fc0e6c ¤   End:
0b5f8c ¤   vi: ts=4 sw=4
fc9e9b ¤   vim: si
71d062 _____________________*/
--4a1e 000ff2bd4b6401001e3 Page 1 of pgpEventPriv.h
a70335 /*____________________________________________________________________________
223fef ¤   pgpEvent.h
c467c5 ¤
6bc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
2a4b0f ¤   All rights reserved.
9c67c5 ¤
966a17 ¤   This file contains the types and prototypes for functions which manipulate
e74383 ¤   PGPEvent data structures
e3af5a
dfa88d ¤   $Id: pgpEventPriv.h,v 1.19.12.1 1998/11/12 03:21:42 heller Exp $
c7f7f7 ____________________________________________________________________________*/
8daf5a
41ebdd #ifndef Included_pgpEvent_h¤/* [ */
704537 #define Included_pgpEvent_h
71af5a
63e82c #include "pgpPubTypes.h"
a89f63 #include "pgpEncode.h"
bcaf5a
9aaf5a
a299c6 PGP_BEGIN_C_DECLARATIONS
2ecbcf #if PRAGMA_IMPORT_SUPPORTED
83b981 #pragma import on
5c7454 #endif
07af5a
e004c4 PGPError ¤  ¤   pgpEventNull(PGPContextRef context,
39da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
9d2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
abc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
f599f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFileOffset soFar, PGPFileOffset total);
dfaf5a
1742e4 PGPError ¤  ¤   pgpEventInitial(PGPContextRef context,
9eda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
612e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
81a3a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue);
9caf5a
7a5420 PGPError ¤  ¤   pgpEventFinal(PGPContextRef context,
beda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
fa2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
98a3a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue);
90af5a
609b3b PGPError ¤  ¤   pgpEventError(PGPContextRef context,
32da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
8f2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
f5c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
43a9fb ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPError error, void *errorArg);
f9af5a
c84080 PGPError ¤  ¤   pgpEventWarning(PGPContextRef context,
f3da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
ef2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
2fc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
8b5795 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPError warning, void *warningArg);
61af5a
23336b PGPError ¤  ¤   pgpEventEntropy(PGPContextRef context,
cbda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
a92e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
d1c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
7a415c ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 entropyBitsNeeded);
55af5a
cb0a7d PGPError ¤  ¤   pgpEventPassphrase(PGPContextRef context,
fdda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
762e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
bac27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
691cb8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean fConventional, PGPKeySetRef keyset);
5eaf5a
6af0da PGPError ¤  ¤   pgpEventAnalyze(PGPContextRef context,
3cda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
6c2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
6dc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
6870d0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPAnalyzeType type);
dcaf5a
f85de8 PGPError ¤  ¤   pgpEventRecipients(PGPContextRef context,
ffda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
--45a9 00037851a0d401001e3 Page 2 of pgpEventPriv.h
482e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
96c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
886ef1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef recipientSet,
1656d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID *keyIDArray,
6238d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 passPhraseCount,
5cee70 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyCount);
4faf5a
3f52da PGPError ¤  ¤   pgpEventKeyFound(PGPContextRef context,
e5da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
752e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
77c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
3ee4da ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keySet);
99af5a
107f84 PGPError ¤  ¤   pgpEventOutput(PGPContextRef context,
1cda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
932e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
6bc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
dc3b96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 messageType,
e2fcc3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *suggestedName,
1f4983 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean FYEO);
18af5a
c319fc PGPError ¤  ¤   pgpEventSignature(PGPContextRef context,
88da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
c22e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
dec27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
fe66a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID const * signingKeyID,
d65b92 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef signingKey, PGPBoolean checked,
89b79d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean verified, PGPBoolean keyDisabled,
c425da ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean keyRevoked, PGPBoolean keyExpired,
044adf ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean keyValidityThreshold,
5100d4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPValidity keyValidity,
16cfdc ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPTime creationTime);
aeaf5a
727ff1 PGPError¤   ¤   pgpEventDecryption(PGPContextRef context,
ceda5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
292e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
50c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
f6e5de ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPCipherAlgorithm cipheralg);
40af5a
fffe67 PGPError ¤  ¤   pgpEventBeginLex(PGPContextRef context,
76da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
ea2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
4fc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
232a25 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 sectionNumber,
96a6f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize sectionOffset);
90af5a
1ff841 PGPError ¤  ¤   pgpEventEndLex(PGPContextRef context,
54da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
9b2e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
26c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
c64f18 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 sectionNumber);
a3af5a
cc9541 PGPError ¤  ¤   pgpEventDetachedSignature(PGPContextRef context,
f9da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
642e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
64a3a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue);
64af5a
dbc2a0 PGPError ¤  ¤   pgpEventKeyGen(PGPContextRef context,
f9da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
162e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
ebc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
eb1662 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 state);
8baf5a
48509e PGPError ¤  ¤   pgpEventKeyServer(PGPContextRef context,
a92e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
22c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
13803a ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef keyServerRef,
a41662 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 state);
12af5a
c3da5f PGPError ¤  ¤   pgpEventKeyServerSign(PGPContextRef context,
f4da5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *newOptionList,
372e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
--e7cc 00170a06b1e401001e3 Page 3 of pgpEventPriv.h
e3c27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
05a7c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef keyServerRef);
2aaf5a
1953f7 PGPError ¤  ¤   pgpEventKeyServerTLS(PGPContextRef context,
492e96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr func,
1fc27e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue,
f9803a ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef keyServerRef,
908dce ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 state,
ea5125 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionRef tlsSession);
73af5a
0fcbcf #if PRAGMA_IMPORT_SUPPORTED
842ced #pragma import reset
217454 #endif
601254 PGP_END_C_DECLARATIONS
28af5a
2c021f #endif /* ] Included_pgpEvent_h */
a1af5a
417e4d /*__Editor_settings____
2aaf5a
de4126 ¤   Local Variables:
8b7b17 ¤   tab-width: 4
ee0e6c ¤   End:
ae5f8c ¤   vi: ts=4 sw=4
ff9e9b ¤   vim: si
70d062 _____________________*/

--6320 001d38dccbf401001e4 Page 1 of Makefile.in
5ea601 #
d7e309 # priv/include/
a3a601 #
89447c # $Id: Makefile.in,v 1.3 1997/07/28 23:43:19 mhw Exp $
5ba601 #
d3af5a
--0b4f 0007fd0eec8401001e5 Page 1 of pgpAnnotate.h
bc38e5 /*
f28068 ·* pgpAnnotate.h -- This is the list of known annotations. ·Each
69be65 ·* annotation has its own number, to make it unique. ·In addition,
a7a9a6 ·* this list really should not change too much over time.
86775e ·*
67f49c ·* Written by:¤ Derek Atkins <warlord@MIT.EDU> and Colin Plumb
d9775e ·*
358190 ·* This is a Public API Function Header.
b0775e ·*
9b06fb ·* $Id: pgpAnnotate.h,v 1.11 1997/11/26 01:47:06 hal Exp $
bb495d ·*/
6aaf5a
6b532e #ifndef Included_pgpAnnotate_h
9024dd #define Included_pgpAnnotate_h
13af5a
68c5d5 #include "pgpBase.h"
22af5a
3199c6 PGP_BEGIN_C_DECLARATIONS
50af5a
405fb2 /* Convert a scope type (via a begin) to a string */
b52d30 const char ·*pgpScopeName (int type);
79af5a
22b142 /* NOTE: Begin scope always ends in 0x00, End scope always ends in 0x01 */
d45548 #define PGP_IS_SCOPE_MARKER(x)¤ (((x) & 0xfe) == 0x00)
8c6b32 #define PGP_IS_END_SCOPE(x)¤¤   (((x) & 0xff) == 0x01)
b3693c #define PGP_IS_BEGIN_SCOPE(x)¤  (((x) & 0xff) == 0x00)
b8af5a
bb38e5 /*
76895e ·* Given an annotation type, update the current scope depth accordingly.
df2014 ·* Can be followed with "pgpAssert(depth != -1)".
74495d ·*/
cedf4b #define PGP_SCOPE_DEPTH_UPDATE(depth,x) \
e27232 ¤   if (PGP_IS_SCOPE_MARKER(x)) \
06ac63 ¤   ¤   (depth) += PGP_IS_BEGIN_SCOPE(x) ? 1 : -1
9faf5a
be27bb /* Commit to sending the current packet: e.g., request a callback! */
7c1998 #define PGPANN_COMMIT¤  ¤   ¤   0x002
8a38e5 /*
f40c05 ·* There are four possible packet-ended-too-early cases, based on
981275 ·* two binary options. ·The first binary option is whether the
afbf64 ·* end is caused by EOF or a short packet length. ·(E.g. an
bcff1c ·* encrypted packet that does not at least contain an IV.)
72e67a ·* These are called the _TRUNCATED and _SHORT cases, respectively.
8a27c1 ·* The second is whether the problem applies to the current scope
ea638b ·* or not. ·I.e. is it at the current parsing level, or one level
b9ff9c ·* down? ·These are marked as _SCOPE_ and _PACKET_, respectively.
84495d ·*/
7a65b4 #define PGPANN_PACKET_TRUNCATED¤¤   0x010
611996 #define PGPANN_PACKET_SHORT¤¤   0x011
404e2d #define PGPANN_SCOPE_TRUNCATED¤ ¤   0x012
64b590 #define PGPANN_SCOPE_SHORT¤ ¤   0x013
bbaf5a
5bddd9 /* A signature is too damn big to pass as an annotation */
082e23 #define PGPANN_SIGNATURE_TOO_BIG¤   0x020
b387f4 /* An encrypted session key is too damn big */
175aa8 #define PGPANN_ESK_TOO_BIG¤ ¤   0x021
ccaf5a
32c2ce /* For a FileWrite module: start a new file. */
4c6a15 #define PGPANN_NEWFILE_START¤   ¤   0x030
91af5a
0da4a2 /* Memory buffer output module; size of buffer, bytes requested to write */
5ef54a #define PGPANN_MEM_BUFSIZE¤ ¤   ¤   0x40
f0b293 #define PGPANN_MEM_BYTECOUNT¤   ¤   0x41
0e7c9a #define PGPANN_MEM_ENABLE¤  ¤   ¤   0x42
1fccc1 #define PGPANN_MEM_MAXSIZE¤ ¤   ¤   0x43
58ceb9 #define PGPANN_MEM_MEMBUF¤  ¤   ¤   0x44
ae862b #define PGPANN_MEM_PREPEND¤ ¤   ¤   0x45
a3af5a
51bbac /* Status requests of the ascii armor parser */
793f1f #define PGPANN_PARSEASC_MSG_COUNT¤  0x050
491db2 #define PGPANN_PARSEASC_MSG_LEFT¤   0x051
7fd96b #define PGPANN_PARSEASC_MSG_CURRENT¤0x052
--5ae6 000bc9eb870401001e5 Page 2 of pgpAnnotate.h
4f50b8 #define PGPANN_PARSEASC_MSG_PARTS¤  0x053
748710 #define PGPANN_PARSEASC_MSG_PARTINFO¤   0x054
ffaf5a
6b9747 /* Parser Callbacks */
2b3e5b #define PGPANN_PARSER_EATIT¤¤   0x102
cd0131 #define PGPANN_PARSER_PASSTHROUGH¤  0x103
9025df #define PGPANN_PARSER_PROCESS¤  ¤   0x104
95b12d #define PGPANN_PARSER_RECURSE¤  ¤   0x105
eeaf5a
ca5b32 /* Unrecognized packet type (EATIT, PASSTHROUGH, PROCESS options only) */
47653d #define PGPANN_UNKNOWN_BEGIN¤   ¤   0x200
311fee #define PGPANN_UNKNOWN_END¤ ¤   0x201
e3af5a
267f0d /* Literal Packet information */
3bc1a8 #define PGPANN_LITERAL_BEGIN¤   ¤   0x300
005838 #define PGPANN_LITERAL_END¤ ¤   0x301
cce9a1 #define PGPANN_LITERAL_TYPE¤¤   0x302
97ceae #define PGPANN_LITERAL_NAME¤¤   0x303
2d2b31 #define PGPANN_LITERAL_TIMESTAMP¤   0x304
85af5a
745eba /* Cipher Packet Information */
50cd97 #define PGPANN_CIPHER_BEGIN¤¤   0x400
5fffa3 #define PGPANN_CIPHER_END¤  ¤   0x401
2a5902 #define PGPANN_CIPHER_NOTEXT¤   ¤   0x402
8ca0dc #define PGPANN_SKCIPHER_ESK¤¤   0x403
2d7f9e #define PGPANN_PKCIPHER_ESK¤¤   0x404
fbaf5a
56f4d2 /* Compressed Packet Information */
c9f2b5 #define PGPANN_COMPRESSED_BEGIN¤¤   0x500
09c081 #define PGPANN_COMPRESSED_END¤  ¤   0x501
d4af5a
41fb36 /* Comment Packet Information */
610f6c #define PGPANN_COMMENT_BEGIN¤   ¤   0x600
fd236e #define PGPANN_COMMENT_END¤ ¤   0x601
6eaf5a
3982bd /* Signed messages */
b157de #define PGPANN_SIGNED_BEGIN¤¤   0x900
d665ea #define PGPANN_SIGNED_END¤  ¤   0x901
51a1a0 #define PGPANN_SIGNED_SIG¤  ¤   0x902
2d9252 #define PGPANN_SIGNED_SIG2¤ ¤   0x903
8d2aeb #define PGPANN_SIGNED_SEP¤  ¤   0x904
6b67c5 ¤
47cc86 /* Hash Packets */
36b24f #define PGPANN_HASH_REQUEST¤¤   0x910¤  /* Callback */
9f6d19 #define PGPANN_HASH_VALUE¤  ¤   0x920¤  /* Double callback (!) */
ceaf5a
cf887c /* PGP Key Data */
33fa2a #define PGPANN_PGPKEY_BEGIN¤¤   0xF00
d2c81e #define PGPANN_PGPKEY_END¤  ¤   0xF01
00af5a
f18db8 /* Not a packet at all (EATIT, PASSTHROUGH options only) */
eaae11 #define PGPANN_NONPACKET_BEGIN¤ ¤   0x1000
1e6821 #define PGPANN_NONPACKET_END¤   ¤   0x1001
79af5a
1f1c30 /* From the Armor Parser. ·text not in armor */
2bebd8 #define PGPANN_NONPGP_BEGIN¤¤   0x1100
1fdf49 #define PGPANN_NONPGP_END¤  ¤   0x1101
18af5a
3338e5 /* Ascii Armor'ed data */
143d6a #define PGPANN_ARMOR_BEGIN¤ ¤   0x1200
32fb5a #define PGPANN_ARMOR_END¤   ¤   0x1201
d777e6 #define PGPANN_ARMOR_PART¤  ¤   0x1202
c9d73a #define PGPANN_ARMOR_BADLINE¤   ¤   0x1203
b10160 #define PGPANN_ARMOR_BADHEADER¤ ¤   0x1204
391c08 #define PGPANN_ARMOR_TOOLONG¤   ¤   0x1205
a5ac86 #define PGPANN_ARMOR_NOCRC¤ ¤   0x1206
efa8d7 #define PGPANN_ARMOR_CRCCANT¤   ¤   0x1207
3bf6ee #define PGPANN_ARMOR_CRCBAD¤¤   0x1208
59af5a
a8a782 /* Clearsigned Data */
3a43b8 #define PGPANN_CLEARSIG_BEGIN¤  ¤   0x1300
bc78b5 #define PGPANN_CLEARSIG_END¤¤   0x1301
--5e34 00176b9e8e6401001e5 Page 3 of pgpAnnotate.h
e0af5a
a9781f /* Data from passthrough for both armor and clearsign */
c3059d #define PGPANN_CLEARDATA¤   ¤   ¤   ¤   0x1302
90f8d2 #define PGPANN_PASSTHROUGH_CLEARSIGN¤   0x1303
d99b33 #define PGPANN_PASSTHROUGH_KEYS¤¤   ¤   0x1304
d1af5a
e090e8 /* Main input scope -- only an application should send this annotation */
6fe2a0 #define PGPANN_INPUT_BEGIN¤ ¤   0x1400
282490 #define PGPANN_INPUT_END¤   ¤   0x1401
26af5a
a05680 /* Independent files. */
072afb #define PGPANN_FILE_BEGIN¤  ¤   0x1500
2e4f76 #define PGPANN_FILE_END¤¤   ¤   0x1501
4baf5a
d8c31d /* Armor Multipart messages */
675a30 #define PGPANN_MULTIARMOR_BEGIN¤¤   0x1600
c66ea1 #define PGPANN_MULTIARMOR_END¤  ¤   0x1601
85af5a
9c1324 /* PGP-MIME information */
2d38e5 /*
bc1dc9 ·* HEADER_SIZE tells size of mime headers, offset of body, assuming newlines
1eac1e ·* are 1 char long. ·Add HEADER_LINES if output is padded to two chars per
94b2c6 ·* newline
93495d ·*/
133dd8 #define PGPANN_PGPMIME_HEADER_SIZE¤ 0x1610
827a2c #define PGPANN_PGPMIME_HEADER_LINES¤0x1611
5a8d22 #define PGPANN_PGPMIME_SEPARATOR¤   0x1612
6eaf5a
40af5a
e71254 PGP_END_C_DECLARATIONS
24af5a
7617e8 #endif /* Included_pgpAnnotate_h */
--a538 001205133aa401001e6 Page 1 of pgpConvKey.h
bc38e5 /*
00ec4d ·* pgpConvKey.h -- Conventional Encryption Keys for PGP
d8775e ·*
025a45 ·* Written By:¤ Derek Atkins <warlord@MIT.EDU>
f4775e ·*
8a9b59 ·* $Id: pgpConvKey.h,v 1.6 1997/07/29 20:31:01 lloyd Exp $
7b495d ·*/
d9af5a
dc50a4 #ifndef Included_pgpConvKey_h
b20490 #define Included_pgpConvKey_h
a3af5a
fdd11f #include "pgpUsuals.h"
85af5a
d999c6 PGP_BEGIN_C_DECLARATIONS
73af5a
2aaf5a
709740 struct PGPConvKey {
c66b88 ¤   PGPConvKey const *¤ ¤   next;
a67cfc ¤   PGPStringToKey const *¤ stringToKey;
7992dc ¤   char ·*¤¤   ¤   pass;
f667ad ¤   size_t¤ ¤   ¤   ¤   ¤   passlen;
3482f7 };
36af5a
a6af5a
b31254 PGP_END_C_DECLARATIONS
bdaf5a
206cfb #endif /* Included_pgpConvKey_h */
--58fd 0001f4142de401001e7 Page 1 of pgpKeyFilterPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
641389 ¤   $Id: pgpKeyFilterPriv.h,v 1.21.22.1 1998/11/12 03:21:43 heller Exp $
c1f7f7 ____________________________________________________________________________*/
43af5a
e43dce #ifndef Included_pgpKeyFilterPriv_h¤/* [ */
9a6c78 #define Included_pgpKeyFilterPriv_h
abaf5a
5afeb2 #include <stdio.h>
67af5a
aaa076 #include "pgpKeys.h"
b1c5d5 #include "pgpBase.h"
f22f8d #include "pgpErrors.h"
6101ab #include "pgpKeyDBOpaqueStructs.h"
a154b0 #include "pgpRingOpaqueStructs.h"
02af5a
c0af5a
7d5b71 /* Definitions of key filters */
f6af5a
05e28e enum PGPFilterType_
cbcebb {¤
fe1bc8 ¤   kPGPFilterTypeStart = 1,
efaf5a
948234 ¤   kPGPFilterTypeKeyKeyID = 2,
ceeeb3 ¤   kPGPFilterTypeKeyEncryptAlgorithm = 3,
8b6d0f ¤   kPGPFilterTypeKeyFingerPrint = 4,
cca8eb ¤   kPGPFilterTypeKeyCreationTime = 5,
ea09e8 ¤   kPGPFilterTypeKeyExpirationTime = 6,
3b5d41 ¤   kPGPFilterTypeKeyRevoked = 7,
533228 ¤   kPGPFilterTypeKeyDisabled = 8,
72b091 ¤   kPGPFilterTypeKeySigAlgorithm = 9,
4a7e02 ¤   kPGPFilterTypeKeyEncryptKeySize = 10,·
c7e3f9 ¤   kPGPFilterTypeKeySigKeySize = 11,
c39d31 /*¤ kPGPFilterTypeUNUSED = 12,¤ ¤   ¤   */
c9d51b /*¤ kPGPFilterTypeUNUSED = 13,¤ ¤   ¤   */
3dc4a8 ¤   kPGPFilterTypeKeySubKeyID = 14,
e0478e ¤   kPGPFilterTypeUserIDString = 15,
ab6fc7 ¤   kPGPFilterTypeUserIDEmail = 16,
1ead96 ¤   kPGPFilterTypeUserIDName = 17,
5e5c17 /*¤ kPGPFilterTypeUNUSED = 18,¤ ¤   ¤   */
a9af5a
b3143d /*¤ kPGPFilterTypeUNUSED = 19,¤ ¤   ¤   */
f89744 /*¤ kPGPFilterTypeUNUSED = 20,¤ ¤   ¤   */
19df6e /*¤ kPGPFilterTypeUNUSED = 21,¤ ¤   ¤   */
4f0710 /*¤ kPGPFilterTypeUNUSED = 22,¤ ¤   ¤   */
46e5d4 ¤   kPGPFilterTypeSigKeyID = 23,
4bbffd /*¤ kPGPFilterTypeUNUSED = 24,¤ ¤   ¤   */
65af5a
561e18 ¤   /* Logical operations */
6aa1fb ¤   kPGPFilterTypeNot = 25,
28f5c6 ¤   kPGPFilterTypeAnd = 26,
081a83 ¤   kPGPFilterTypeOr = 27,
a4af5a
0f5541 ¤   kPGPFilterTypeEnd = 28,
85af5a
d61410 ¤   PGP_ENUM_FORCE( PGPFilterType_ )
cd82f7 };
7645ac PGPENUM_TYPEDEF( PGPFilterType_, PGPFilterType );
90af5a
82af5a
7bdfa0 #define kPGPFilterClassDefault¤ 0x01
34af5a
afc2fb typedef PGPUInt16¤  PGPFilterClass;
42af5a
279827 #define kPGPFilterMagic¤¤   0x46494c54¤ /* 'FILT' */
3070fe struct PGPFilter
f6bb36 {
1ffe45 ¤   PGPUInt32¤  ¤   ¤   ¤   magic;
--1c9c 0009eaf634a401001e7 Page 2 of pgpKeyFilterPriv.h
d0429f ¤   PGPContextRef¤  ¤   ¤   context;
aff65c ¤   PGPUInt32¤  ¤   ¤   ¤   refCount;
ed9575 ¤   PGPMatchCriterion¤  ¤   match;
eeedb8 ¤   PGPFilterClass¤ ¤   ¤   filterClass;
77356c ¤   PGPFilterType¤  ¤   ¤   filterType;¤
ce67c5 ¤
fbdbc3 ¤   /* Select element of union based on type */
c88ae4 ¤   union·
7ec7a1 ¤   {
3f9759 ¤   ¤   PGPKeyID¤   ¤   ¤   keyKeyID;
c71b52 ¤   ¤
439753 ¤   ¤   PGPPublicKeyAlgorithm¤  keyEncryptAlgorithm;
bd2b33 ¤   ¤   struct
015b34 ¤   ¤   {
6108b7 ¤   ¤   ¤   PGPByte *¤  ¤   keyFingerPrintData;
8dada7 ¤   ¤   ¤   PGPUInt32¤  ¤   keyFingerPrintLength;¤  /* 16 or 20 */
e2951e ¤   ¤   } keyFingerPrint;
3437bd ¤   ¤   PGPTime¤¤   ¤   ¤   keyCreationTime;
20ed1d ¤   ¤   PGPTime¤¤   ¤   ¤   keyExpirationTime;
5e9cab ¤   ¤   PGPTime¤¤   ¤   ¤   keyLastModifyTime;
29397f ¤   ¤   PGPBoolean¤ ¤   ¤   keyRevoked;¤¤   ¤   ¤
b150ad ¤   ¤   PGPBoolean¤ ¤   ¤   keyDisabled;
5e39cc ¤   ¤   PGPByte¤¤   ¤   ¤   keySigAlgorithm;¤   ¤
986733 ¤   ¤   PGPUInt32¤  ¤   ¤   keyEncryptKeySize;
57e5df ¤   ¤   PGPUInt32¤  ¤   ¤   keySigKeySize;
03768b ¤   ¤   PGPByte¤¤   ¤   ¤   keyVersion;
983934 ¤   ¤   PGPKeyID¤   ¤   ¤   keySubKeyID;
d9af5a
eb5ffc ¤   ¤   char *¤ ¤   ¤   ¤   userIDString;
ebdd29 ¤   ¤   char *¤ ¤   ¤   ¤   userIDEmail;
392a16 ¤   ¤   char *¤ ¤   ¤   ¤   userIDName;
4ee5e0 ¤   ¤   PGPByte¤¤   ¤   ¤   userIDVersion;
27af5a
df3934 ¤   ¤   PGPByte¤¤   ¤   ¤   sigHashAlgorithm;
10ab3d ¤   ¤   PGPPublicKeyAlgorithm¤  sigKeyAlgorithm;
70ed9e ¤   ¤   PGPByte¤¤   ¤   ¤   sigClassification;
f18cf9 ¤   ¤   PGPTime¤¤   ¤   ¤   sigCreationTime;
ce0778 ¤   ¤   PGPKeyID¤   ¤   ¤   sigKeyID;
83af5a
4bd8e9 ¤   ¤   PGPByte¤¤   ¤   ¤   sigVersion;
5daf5a
e1944e ¤   ¤   PGPFilter *¤¤   ¤   notFilter;
f8267f ¤   ¤   struct·
e25b34 ¤   ¤   {
bf37ae ¤   ¤   ¤   PGPFilter *¤¤   andFilter1;
04d8ca ¤   ¤   ¤   PGPFilter *¤¤   andFilter2;
e669b7 ¤   ¤   } andFilter;
91267f ¤   ¤   struct·
305b34 ¤   ¤   {
c8b840 ¤   ¤   ¤   PGPFilter *¤¤   orFilter1;
835724 ¤   ¤   ¤   PGPFilter *¤¤   orFilter2;
bd8571 ¤   ¤   } orFilter;
1dbcff ¤   } value;
ca82f7 };
69af5a
9216ea ¤   PGPBoolean
7a5ed3 pgpKeyObjMatchesFilter(
2039e0 ¤   PGPFilterRef¤   ¤   filter,
3eae29 ¤   RingSet const *¤¤   ringSet,
0cd158 ¤   RingObject *¤   ¤   keyObj);
ddaf5a
9116ea ¤   PGPBoolean
3fd3f2 pgpKeyMatchesFilter(
ee39e0 ¤   PGPFilterRef¤   ¤   filter,
eee5bb ¤   PGPKeyRef¤  ¤   ¤   key);
0aaf5a
67af5a
fa290a PGPBoolean¤ ¤   PGPFilterIsValid( PGPFilterRef¤ filter );
dba208 #define PGPValidateFilter( filter ) \
97d732 ¤   PGPValidateParam( PGPFilterIsValid( filter ) )
cbaf5a
9eaf5a
--341e 001b4a7a9a1401001e7 Page 3 of pgpKeyFilterPriv.h
e0af5a
f5b6d6 #endif /* ] Included_pgpKeyFilterPriv_h */
5caf5a
1938e5 /*
56e6c5 ·* Local Variables:
909b19 ·* tab-width: 4
26e7a4 ·* End:
a1b612 ·* vi: ts=4 sw=4
806c42 ·* vim: si
b4495d ·*/
--d770 000cbfe75cb401001e8 Page 1 of pgpKludge.h
bc38e5 /*
f6b7c8 ·* Kludges for not-quite-ANSI systems.
2dfc2c ·* This should always be the last file included, because it may
ea6d3d ·* mess up some system header files.
9a775e ·*
82fc57 ·* $Id: pgpKludge.h,v 1.3 1997/05/13 01:19:26 mhw Exp $
01495d ·*/
95af5a
f13432 #ifndef Included_pgpKludge_h
22b504 #define Included_pgpKludge_h
69af5a
4699c6 PGP_BEGIN_C_DECLARATIONS
e6af5a
b74626 #if NO_FPOS_T¤  /* The whole fpos_t/fgetpos/fsetpos thing is missing */
b03f88 typedef long fpos_t;
363eab #define fgetpos(stream, pos) ((*(pos) = ftell(stream)) < 0 ? -1 : 0)
f40f44 #define fsetpos(stream, pos) fseek(stream, *(pos), SEEK_SET)
ff7454 #endif
7eaf5a
01822e #if NO_MEMMOVE¤ /* memove() not in libraries */
05148b #define memmove(dest,src,len) bcopy(src,dest,len)
947454 #endif
2eaf5a
4ba6fe #if NO_STRERROR¤/* strerror() not in libraries */
bcaf5a
03b728 #ifndef sys_nerr
ed0616 extern int sys_nerr;
517454 #endif
5959b1 #ifndef sys_errlist
4b80a0 extern char *sys_errlist[];
c67454 #endif
4411be #define strerror(err) ((err) < sys_nerr ? sys_errlist[err] : "Unknwon error")
5eaf5a
18d59b #endif /* NO_STRERROR */
27af5a
5ba54a #if NO_STRTOUL¤ /* strtoul() not in libraries */
6ad2e6 #define strtoul strtol¤ /* Close enough */
4c7454 #endif
abaf5a
5936a4 #if NO_RAISE¤   /* raise() not in libraries */
9aaf7c #include <sys/types.h>¤ /* For getpid() - kill() is in <signal.h> */
babb46 #define raise(sig) kill(getpid(),sig)
6c7454 #endif
a0af5a
1a38e5 /*
65a091 ·* Would you believe that there exist (non-ANSI, of course) <stdio.h>'s that
14e60c ·* don't define the SEEK_ macros? ·If EOF is defined (a giveaway that
c8d7ec ·* <stdio.h> has been included), define these to their usual meanings.
e4495d ·*/
209e71 #if defined(EOF)
35af5a
eaefd5 #ifndef SEEK_SET
f86c00 #define¤SEEK_SET¤   0¤  /* Set file pointer to "offset" */
c15a6a #define¤SEEK_CUR¤   1¤  /* Set file pointer to current plus "offset" */
02e171 #define¤SEEK_END¤   2¤  /* Set file pointer to EOF plus "offset" */
227454 #endif
1eaf5a
2ce0d2 #ifndef STDIN_FILENO
305943 #define STDIN_FILENO¤   0
247908 #define STDOUT_FILENO¤  1
9e7454 #endif
45af5a
f30012 #if NO_SIZE_T
ede0c5 typedef unsigned size_t; /* Actually, "int" gets used a lot... */
f57454 #endif
8faf5a
4f8b65 #if NO_STDIO_PROTOS¤/* Missing prototypes for "simple" functions */
66fde8 int (puts)(char const *);
e3816d int (fputs)(char const *, FILE *);
99c216 void (rewind)(FILE *);
b9449f int (fflush)(FILE *);
cbac42 int (fclose)(FILE *);
--6c27 001f5f40f2b401001e8 Page 2 of pgpKludge.h
661aae int (printf)(char const *, ...);
6fc6eb int (fprintf)(FILE *, char const *, ...);
d27406 int (fseek)(FILE *, long, int);
7980ad int (remove)(char const *);
0660b2 int (rename)(char const *, char const *);
4f45c2 void (perror)(char const *);
0a0dd2 int (system)(char const *);¤/* Really in <stdlib.h>, but this'll do... */
8fc481 int (pclose)(FILE *);
478735 /* If we have a sufficiently old-fashioned stdio, it probably uses these... */
35baac int (_flsbuf)(unsigned char, FILE *);
23d5de int (_filbuf)(FILE *);
177f6c int (ungetc)(int, FILE *);
409a28 size_t (fread)(char *, size_t, size_t, FILE *);
ce8edc size_t (fwrite)(char const *, size_t, size_t, FILE *);
dbf318 #if defined(va_start) || defined(va_arg) || defined(va_end)
b3c299 int (vfprintf)(FILE *, char const *, ...);
027454 #endif
3e8a23 #endif /* NO_STDIO_PROTOS */
deaf5a
08b1f8 #endif /* EOF */
2eaf5a
ad1254 PGP_END_C_DECLARATIONS
d2af5a
f5a6b1 #endif /* Included_pgpKludge_h */
--4495 000ebce535a401001e9 Page 1 of pgpMsg.h
bc38e5 /*
6db05f ·* pgpMsg.h -- A file of PGP Messages
1f775e ·*
d27ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
ef775e ·*
ec8190 ·* This is a Public API Function Header.
36775e ·*
710dc4 ·* $Id: pgpMsg.h,v 1.6 1997/06/16 22:48:46 lloyd Exp $
c2495d ·*/
64af5a
dcf6d5 #ifndef Included_pgpMsg_h
bfbec2 #define Included_pgpMsg_h
01af5a
f7072c #ifndef PGPMSG
baaf5a
ce99c6 PGP_BEGIN_C_DECLARATIONS
d1af5a
4c16f7 #define PGPMSG(num, string)¤/* nothing */
b3a473 const char ·*pgpmsgString (int type);
e0af5a
291254 PGP_END_C_DECLARATIONS
51af5a
7a7454 #endif
18af5a
19e86e #define PGPMSG_NONE¤0
c3fcba PGPMSG (PGPMSG_NONE,¤   ¤   "")
95af5a
23af00 #define PGPMSG_NO_KEY¤  1000
0aa1c9 PGPMSG (PGPMSG_NO_KEY,¤ ¤   "Error getting public key")
53af5a
0303b1 #define PGPMSG_SIG_UNKNOWN_KEYID¤   1050
5b9680 PGPMSG (PGPMSG_SIG_UNKNOWN_KEYID,
c01f8a ¤   "Signature by unknown keyid: %.*s")
027686 #define PGPMSG_SIG_ERROR¤   1051
340cb9 PGPMSG (PGPMSG_SIG_ERROR,¤  "Signature check got an error")
2c1578 #define PGPMSG_SIG_NOVERIFY¤1052
8b1b26 PGPMSG (PGPMSG_SIG_NOVERIFY,¤   "Signature verification unsuccessful")
4400a7 #define PGPMSG_SIG_ADD_ERROR¤   1053
3c8c71 PGPMSG (PGPMSG_SIG_ADD_ERROR,¤  "Error adding Sig")
e58d6f #define PGPMSG_SIG_NO_CHECK¤1054
5caa8a PGPMSG (PGPMSG_SIG_NO_CHECK,
27f8b5 ¤   "None of the signatures were understood; can't check")
3af5a3 #define PGPMSG_SIG_BADHASH¤ 1055
5ffa89 PGPMSG (PGPMSG_SIG_BADHASH,
0d16fb ¤   "unknown hash: unable to verify signature")
e1137e #define PGPMSG_SIG_NOSIGS¤  1056
b6c8ac PGPMSG (PGPMSG_SIG_NOSIGS,¤ "No signatures to check")
00af5a
14e36b #define PGPMSG_ENCRYPTED_PASSPHRASE¤1100
86db1a PGPMSG (PGPMSG_ENCRYPTED_PASSPHRASE,
abc34c ¤   "This message is encrypted with a pass phrase")
bdaf5a
5774f1 #define PGPMSG_UNBALANCED_SCOPE¤1150
a9b8c4 PGPMSG (PGPMSG_UNBALANCED_SCOPE,¤   "Unbalanced Scope")
44af5a
a04968 #define PGPMSG_NO_PUBKEY¤   1200
a3e09f PGPMSG (PGPMSG_NO_PUBKEY,¤  "No public key available")
385bb4 #define PGPMSG_NO_SECKEY¤   1201
ef505b PGPMSG (PGPMSG_NO_SECKEY, ¤ "No secret key available")
4caf5a
fb1c4f #define PGPMSG_COMMIT_INVALID¤  1250
8588cb PGPMSG (PGPMSG_COMMIT_INVALID,
c5cda3 ¤   "Invalid response from commit: %d")·
acaf5a
fdd018 #define PGPMSG_ESK_NODECRYPT¤   1300
798846 PGPMSG (PGPMSG_ESK_NODECRYPT,¤  "Decryption unsuccessful")
6e1907 #define PGPMSG_ESK_ADD_ERROR¤   1301
e6fd4b PGPMSG (PGPMSG_ESK_ADD_ERROR,¤  "Error adding ESK")
4ec41e #define PGPMSG_ESK_BADTYPE¤ 1302
fee32c PGPMSG (PGPMSG_ESK_BADTYPE,¤"Bad ESK Type... skipping")
eea826 #define PGPMSG_ESK_BADPASS¤ 1303
eb7875 PGPMSG (PGPMSG_ESK_BADPASS,¤"Passphrase incorrect. ·Try Again.")
--ce08 001842c577e401001e9 Page 2 of pgpMsg.h
e0af5a
a04015 #define PGPMSG_SEPSIG_NOVERIFY¤ 1350
89261a PGPMSG (PGPMSG_SEPSIG_NOVERIFY,¤"Separate signature unsuccessful")
962808 #define PGPMSG_SEPSIG¤  ¤   1351
4bdf0b PGPMSG (PGPMSG_SEPSIG,¤ ¤   "This signature applies to another message")
b9af5a
1d405e #define PGPMSG_ANNOTATE_ERROR¤  1400
ba9520 PGPMSG (PGPMSG_ANNOTATE_ERROR,¤ "Annotate returned an error")
75af5a
954049 #define PGPMSG_PKE_ENCRYPTED¤   1450
374389 PGPMSG (PGPMSG_PKE_ENCRYPTED,
e17992 ¤   "This message is public key encrypted using pke type %d")
83af5a
d36162 #define PGPMSG_TRY_AGAIN¤   1500
d65eef PGPMSG (PGPMSG_TRY_AGAIN,¤  "Try again")
03af5a
afa4da #define PGPMSG_DEVNULL_CREATE¤  1550
7399bb PGPMSG (PGPMSG_DEVNULL_CREATE,¤ "Cannot create Dev Null Module")
f5af5a
d03222 #define PGPMSG_ALLOC_HASH_BUFFER¤   1600
d8facd PGPMSG (PGPMSG_ALLOC_HASH_BUFFER,¤  "Failed to allocate hash buffer")
b1d826 #define PGPMSG_ALLOC_HASH_CLONE¤1601
084e13 PGPMSG (PGPMSG_ALLOC_HASH_CLONE,¤   "unable to clone hash; bailing")
d2af5a
7a80fb #define PGPMSG_CONFIG_AMBIGUOUS¤¤   1650·
669f7e PGPMSG (PGPMSG_CONFIG_AMBIGUOUS,
08ee9d ¤   "line %u: ambigious key %.*s, matches %s and %s.")
704dc2 #define PGPMSG_CONFIG_UNKNOWN_KEYWORD¤  1651
ef0a29 PGPMSG (PGPMSG_CONFIG_UNKNOWN_KEYWORD,¤ "line %u: unknown keyword %.*s")
c9784c #define PGPMSG_CONFIG_STRINGEND¤¤   1652
9d0a0f PGPMSG (PGPMSG_CONFIG_STRINGEND,¤   "line %u: unterminated string %.*s")
009c07 #define PGPMSG_CONFIG_MISSING_EQUAL¤1653·
a2cc20 PGPMSG (PGPMSG_CONFIG_MISSING_EQUAL,¤   "line %u: Missing '=' after %.*s")
d26447 #define PGPMSG_CONFIG_MISSING_BOOLEAN¤  1654
2e7ab5 PGPMSG (PGPMSG_CONFIG_MISSING_BOOLEAN,
66c399 ¤   "line %u: Missing argument to boolean option %.*s")
faab2a #define PGPMSG_CONFIG_UNKNOWN_BOOLEAN¤  1655
dc69aa PGPMSG (PGPMSG_CONFIG_UNKNOWN_BOOLEAN,
5dfe0c ¤   "line %u: Unrecognized argument to boolean option %.*s: %.*s")
642457 #define PGPMSG_CONFIG_UNKNOWN_INTEGER¤  1656
61e3b2 PGPMSG (PGPMSG_CONFIG_UNKNOWN_INTEGER,
10b296 ¤   "line %u: Unrecognized argument to integer option %.*s: %.*s")
8aeb3a #define PGPMSG_CONFIG_MISSING_INTEGER¤  1657
52f0ad PGPMSG (PGPMSG_CONFIG_MISSING_INTEGER,
a212b6 ¤   "line %u: Missing argument to integer option %.*s")
13064b #define PGPMSG_CONFIG_INT_TOO_HIGH¤ 1658
9cb91a PGPMSG (PGPMSG_CONFIG_INT_TOO_HIGH,
e689c1 ¤   "line %u: Argument to %.*s is too high: %d, max %d")
ee9c6a #define PGPMSG_CONFIG_INT_TOO_LOW¤  1659
5e5468 PGPMSG (PGPMSG_CONFIG_INT_TOO_LOW,
301162 ¤   "line %u: Argument to %.*s is too low: %d, min %d")
98fde5 #define PGPMSG_CONFIG_INVALID_INTEGER¤  1660
002670 PGPMSG (PGPMSG_CONFIG_INVALID_INTEGER,
8cccd7 ¤   "line %u: Invalid argument to integer option %.*s: %.*s")
bf4036 #define PGPMSG_CONFIG_STRING_TOO_LONG¤  1661
bed47b PGPMSG (PGPMSG_CONFIG_STRING_TOO_LONG,
9dba7c ¤   "line %u: Argument to %.*s is too long %d")
2899cc #define PGPMSG_CONFIG_INVALID_STRING¤   1662
cb6699 PGPMSG (PGPMSG_CONFIG_INVALID_STRING,
094a72 ¤   "line %u: Invalid argument to string option %.*s: %.*s")
b199e3 #define PGPMSG_CONFIG_NO_FILE¤  ¤   1663
a92192 PGPMSG (PGPMSG_CONFIG_NO_FILE,¤ "Cannot open configuration file %s")
b0af68 #define PGPMSG_CONFIG_LINE_TOO_LONG¤1664
3a3195 PGPMSG (PGPMSG_CONFIG_LINE_TOO_LONG,¤   "line %u: Line too long %s")
6838b2 #define PGPMSG_CONFIG_BAD_CHAR¤ ¤   1665
b5ffd6 PGPMSG (PGPMSG_CONFIG_BAD_CHAR,¤"line %u: Bad Character\n%s\nOffset %d")
ff5551 #define PGPMSG_CONFIG_MAX_ERRORS¤   1666
500f1a PGPMSG (PGPMSG_CONFIG_MAX_ERRORS,¤  "Processing halted after %d errors")
76a4b1 #define PGPMSG_CONFIG_NUM_ERRORS¤   1667
4d5d0a PGPMSG (PGPMSG_CONFIG_NUM_ERRORS,¤  "%d error(s) detected")
17af5a
84dbf1 #endif /* Included_pgpMsg_h */
--9d7f 00024fb998b401001ea Page 1 of pgpPktByte.h
bc38e5 /*
78407e ·* pgpPktByte.h -- Definitions of packet byte types
34775e ·*
92e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
912979 ·* You should not be using these functions in an application.
0a775e ·*
cc8312 ·* $Id: pgpPktByte.h,v 1.7 1998/06/03 20:10:42 hal Exp $
62495d ·*/
a929fa #ifndef Included_pgpPktByte_h
d27dce #define Included_pgpPktByte_h
4caf5a
91d11f #include "pgpUsuals.h"
b5af5a
6699c6 PGP_BEGIN_C_DECLARATIONS
22af5a
fb91b0 #define IS_OLD_PKTBYTE(pktbyte) ·(((pktbyte) & 0xC0) == 0x80)
5f10f1 #define IS_NEW_PKTBYTE(pktbyte) (((pktbyte) & 0xC0) == 0xC0)
198f82 #define OLD_PKTBYTE_TYPE(pktbyte) (((pktbyte) >> 2) & 0xF)
6b63f1 #define NEW_PKTBYTE_TYPE(pktbyte) ((pktbyte) & 0x3F)
b809a4 #define PKTBYTE_TYPE(pktbyte) (IS_OLD_PKTBYTE (pktbyte) ? \
238c34 ¤   ¤   ¤   ·······OLD_PKTBYTE_TYPE(pktbyte) : \
cf6422 ¤   ¤   ¤   ·······NEW_PKTBYTE_TYPE(pktbyte))
de1305 #define PKTBYTE_LLEN(pktbyte) ((pktbyte) & 3)
2a1aba #define PKTBYTE_BUILD(type, llen) ((type)>0xf ? \
29066c ¤   PKTBYTE_BUILD_NEW(type) : PKTBYTE_BUILD_OLD(type, llen))
e20d11 #define PKTBYTE_BUILD_OLD(type, llen) ((PGPByte)(0x80 | ((type) & 0xF) <<2 \
0007e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   | (llen)))
670ab6 #define PKTBYTE_BUILD_NEW(type) ((PGPByte)(0xC0 | ((type) & 0x3F)))
c9b70b #define LLEN_TO_BYTES(llen) ((1 << (llen)) & 7)
acaf5a
2938e5 /*
f9600c ·* For the new packet formats -- macros for creating the length byte(s)
1c08a4 ·* of terminating subpackets. ·The format is:
ea52af ·*¤ Format¤ ¤   ¤   Length¤ ¤   Macro
79a09b ·* ¤0sssssss¤   ¤   0-127¤  ¤   PKTLEN_1BYTE()
b38a2d ·* ¤10ssssss¤   ¤   128-191¤¤   PKTLEN_1BYTE()
130c9f ·*¤ 110sssss ssssssss¤  192-8383¤   PKTLEN_BYTE0(),PKTLEN_BYTE1()
73775e ·*
bc3afa ·* PKTLEN_ONE_BYTE() is used to determine if the length is 1 byte (use
bbd3e2 ·* PKTLEN_1BYTE()) or two bytes (use PKTLEN_BYTE0() then
6b821a ·* PKTLEN_BYTE1()). ·PKTLEN_TWO_BYTES() is false if it needs more than 2.
d8495d ·*/
2a9723 #define PKTLEN_ONE_BYTE(len)¤   ((len) < 192)
3cab7b #define PKTLEN_TWO_BYTES(len)¤  ((len) < 8384)
433d38 #define PKTLEN_1BYTE(len)¤  (PGPByte)(len & 0xFF)
9be323 #define PKTLEN_BYTE0(len)¤  (PGPByte)(0xC0 + (((len-192) >> 8) & 0x1F))
3f9067 #define PKTLEN_BYTE1(len)¤  (PGPByte)((len-192) & 0xFF)
d5f1fe #define PKTLEN_PARTIAL(po2)¤(PGPByte)(0xE0 + (po2))
b5af5a
2138e5 /*
06fee0 ·* A non-terminating subpacket (followed by another subpacket) is
da4778 ·* a power of two bytes long and has a length byte encoded as
737234 ·* follows:
7de3fe ·* ·····111xxxxx¤   ¤   2^0-2^31 bytes
c3495d ·*/
6167c5 ¤
6582ed /* Types */
073736 enum pktbyte {
03ed68 ¤   PKTBYTE_ESK = 1,
8c95b6 ¤   PKTBYTE_SIG = 2,
ed3cdb ¤   PKTBYTE_CONVESK = 3,
e9d951 ¤   PKTBYTE_1PASSSIG = 4,
b618ff ¤   PKTBYTE_SECKEY = 5,
792d17 ¤   PKTBYTE_PUBKEY = 6,
02e44a ¤   PKTBYTE_SECSUBKEY = 7,
301e1c ¤   PKTBYTE_COMPRESSED = 8,
2b728b ¤   PKTBYTE_CONVENTIONAL = 9,
ddc4e3 ¤   PKTBYTE_OLDLITERAL = 10,¤   /* pkt length doesn't include filename, etc. */
1a0df3 ¤   PKTBYTE_LITERAL = 11,
af97ec ¤   PKTBYTE_TRUST = 12,
c49bbe ¤   PKTBYTE_NAME = 13,
24c28a /* We are replacing the old comment packets with the new subkey
--6c46 00189e61f54401001ea Page 2 of pgpPktByte.h
43c9d3 ·* packets. ·This will allow older versions of PGP to skip over the
583b40 ·* subkey packets gracefully. ·The new comment packets will be skipped
e2e5eb ·* by this version.
35775e ·*
f1022a ·*¤ PKTBYTE_COMMENT = 14,
f1495d ·*/
337be1 ¤   PKTBYTE_PUBSUBKEY = 14,
dc8d88 ¤   /* 15 is reserved for internal use in the ring parsing code */
963f34 ¤   /* 16 and up use the new packet header formats */
0ad37c ¤   PKTBYTE_COMMENT = 16,
f8b5b8 ¤   PKTBYTE_ATTRIBUTE = 17,
4c6d2f ¤   /* Update this to be the maximum known packet tag */
1a6b12 ¤   PKTBYTE_MAXIMUM = PKTBYTE_ATTRIBUTE
3682f7 };
5eaf5a
f31254 PGP_END_C_DECLARATIONS
3baf5a
89d8df #endif /* Included_pgpPktByte_h */
--dfbc 000b7e52a20401001eb Page 1 of pgpSDKBuildFlags.h
a70335 /*____________________________________________________________________________
46cbf8 ¤   pgpSDKBuildFlags.h
6567c5 ¤
e78de7 ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.·
954b0f ¤   All rights reserved.
0067c5 ¤
cf67c5 ¤
28af5a
42b789 ¤   $Id: pgpSDKBuildFlags.h,v 1.37.2.24.2.1 1998/11/12 03:21:44 heller Exp $
2cf7f7 ____________________________________________________________________________*/
42c664 #ifndef Included_pgpSDKBuildFlags_h¤/* [ */
9f3a6b #define Included_pgpSDKBuildFlags_h
15af5a
8fb883 #define PGP_RSA¤¤   ¤   ¤   1
694d03 #define PGP_RSA_KEYGEN¤ ¤   1
d0af5a
3ac4f6 #define PGP_USECAPIFORRSA¤  0¤  /* Try to use Microsoft CAPI library for RSA */
f90da0 #define PGP_USECAPIFORMD2¤  0¤  /* Try to use Microsoft CAPI library for MD2 */
0cf4c3 #define PGP_USEBSAFEFORRSA¤ 0¤  /* Use RSA's BSAFE library for RSA support */
4743cb #define PGP_USEPGPFORRSA¤   1¤  /* Use the PGP implementation for RSA support */
b273f2 #define PGP_USERSAREF¤  ¤   0¤  /* Use the non-commercial RSAREF library for RS¶
c13ad5 A */
8aaf5a
c0af5a
2ac853 /* These probably will always be on */
6a1d99 #define PGP_CAST5¤  ¤   1
bd5372 #define PGP_DES3¤   ¤   1
324a9d /* It turns out that IDEA is used on some DH keys, so it needs to be enabled
e2f93d ···even if RSA is off */
80d312 #define PGP_IDEA¤   ¤   1
b5af5a
99dd67 /* Allows turning off signing/verification capability in library */
a7f70e #ifndef PGP_SIGN_DISABLE
056eef ¤   #define PGP_SIGN_DISABLE¤   0
6c7454 #endif
21af5a
2d7972 #ifndef PGP_VERIFY_DISABLE
99673c ¤   #define PGP_VERIFY_DISABLE¤ 0
f97454 #endif
9caf5a
c86878 /* Allows turning off encryption/decryption capability in library */
94e574 #ifndef PGP_ENCRYPT_DISABLE
8a420f ¤   #define PGP_ENCRYPT_DISABLE¤0
d97454 #endif
c9af5a
2de268 #ifndef PGP_DECRYPT_DISABLE
500a81 ¤   #define PGP_DECRYPT_DISABLE¤0
257454 #endif
f8af5a
d00335 /*____________________________________________________________________________
7f7bfe ¤   Check for invalid combinations of build flags
a6f7f7 ____________________________________________________________________________*/
61af5a
3631fd #if !( defined(PGP_MACINTOSH) || defined(PGP_UNIX) || defined(PGP_WIN32) )
b8593c #error one of {PGP_MACINTOSH, PGP_UNIX, PGP_WIN32} must be defined
697454 #endif
46af5a
be3bd1 #if PGP_RSA¤/* [ */
06af5a
3c2f41 ¤   #if ! PGP_IDEA
b41ba4 ¤   #error PGP_RSA requires PGP_IDEA
1fb7ec ¤   #endif
f7af5a
331cf3 ¤   #if (PGP_USECAPIFORRSA + PGP_USEBSAFEFORRSA + PGP_USERSAREF + \
faeed7 ¤   ¤   ¤   PGP_USEPGPFORRSA) != 1
a4ab05 ¤   #error Must enable exactly one RSA implementation option
31b7ec ¤   #endif
87af5a
5df16b ¤   #if PGP_USECAPIFORRSA && (PGP_MACINTOSH || PGP_UNIX)
8d491d ¤   #error Cannot enable CAPI RSA implementation on this platform
1eb7ec ¤   #endif
b767c5 ¤
--237f 001d134c4ff401001eb Page 2 of pgpSDKBuildFlags.h
910efd #else¤  /* ] PGP_RSA [ */
c0af5a
9ff42d ¤   #if PGP_RSA_KEYGEN
e9d1b9 ¤   #error Cannot enable PGP_RSA_KEYGEN without PGP_RSA
0bb7ec ¤   #endif
92af5a
fc1cf3 ¤   #if (PGP_USECAPIFORRSA + PGP_USEBSAFEFORRSA + PGP_USERSAREF + \
07f70f ¤   ¤   ¤   PGP_USEPGPFORRSA) != 0
96297f ¤   #error Cannot enable any RSA implementation options without PGP_RSA
45b7ec ¤   #endif
41af5a
c09a74 #endif¤ /* ] PGP_RSA */
b7af5a
b3bb13 #if PGP_USECAPIFORMD2 && ! PGP_USECAPIFORRSA
3e691e #error Cannot use CAPI MD2 without CAPI RSA
0d7454 #endif
adaf5a
b15b00 #endif /* ] Included_pgpSDKBuildFlags_h */
42af5a
95af5a
027e4d /*__Editor_settings____
38af5a
2a4126 ¤   Local Variables:
b67b17 ¤   tab-width: 4
320e6c ¤   End:
985f8c ¤   vi: ts=4 sw=4
709e9b ¤   vim: si
d1d062 _____________________*/
--0ddc 0003a803b95401001ec Page 1 of pgpUI.h
bc38e5 /*
907ada ·* pgpUI.h -- Header for PGP UI Callback defintions.
8e775e ·*
e87ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
86775e ·*
a98190 ·* This is a Public API Function Header.
31775e ·*
b43bb3 ·* $Id: pgpUI.h,v 1.8 1997/07/16 01:44:50 heller Exp $
0c495d ·*/
12af5a
97d705 #ifndef Included_pgpUI_h
7694ef #define Included_pgpUI_h
4caf5a
57d11f #include "pgpUsuals.h"
c7af5a
3c99c6 PGP_BEGIN_C_DECLARATIONS
63af5a
e738e5 /*
86865d ·* This is the structure that contains the callback function pointers
ce636a ·* for the PGP UI callbacks. ·An application fills in this structure
044de4 ·* with the appropriate functions to perform the callbacks. ·Some
79dbe7 ·* callbacks support additional arguments to the msg. ·Callback
669960 ·* functions should use stdarg, where each argument is of type "struct
85c70c ·* PgpUICbArg const *"
36495d ·*/
6a6aa3 struct PGPUICb
b6bb36 {
151c43 ¤   /* required callbacks */
ba91ad ¤   int (*message) (void *arg, int type, int msg, unsigned numargs, ...);
b53ad0 ¤   int (*doCommit) (void *arg, int scope);
912f9f ¤   int (*newOutput) (void *arg, PGPPipeline **output,
7f053c ¤   ¤   ¤   ··int type, char const *suggested_name);
fe5c77 ¤   int (*needInput) (void *arg, PGPPipeline *head);
bad599 ¤   int (*sigVerify) (void *arg, PGPSig const *sig,
f8bf3e ¤   ¤   ¤   ···PGPByte const *hash);
19eb0e ¤   int (*eskDecrypt) (void *arg, PGPESK const *esklist,
3b8d3a ¤   ¤   ¤   ···PGPByte *key, PGPSize *keylen,
79e89c ¤   ¤   ¤   ···int (*tryKey) (void *arg, PGPByte const *key,
88de13 ¤   ¤   ¤   ¤   ¤   ··PGPSize keylen),
30203f ¤   ¤   ¤   ···void *tryarg);
30edf5 ¤   /* optional callbacks below this line */
3dc087 ¤   int (*annotate) (void *arg, PGPPipeline *origin, int type,
0c9a3e ¤   ¤   ¤   ·PGPByte const *string, PGPSize size);
702fa1 } ;
85af5a
91af5a
f4af5a
089ee4 /* Define whether a callback argument is an int or a string */
7e9d87 #define PGP_UI_ARG_INT¤ ¤   1
e2a46b #define PGP_UI_ARG_UNSIGNED¤2
28e37e #define PGP_UI_ARG_WORD32¤  3
df6b69 #define PGP_UI_ARG_STRING¤  4
1d2b34 #define PGP_UI_ARG_BUFFER¤  5
73af5a
8a38e5 /*
6a506f ·* This structure is used for callback arguments. ·Whenever a callback
61f19e ·* of any sort requires arguments, this structure is used to hold the
faea36 ·* arguments. ·The type is any PGP_UI_ARG_* and the appropriate entry
c3e2fa ·* in val is used.
94495d ·*/
0fe84a typedef struct PgpUICbArg
4fbb36 {
ca29f6 ¤   int type;
bbe29a ¤   union {
c7759c ¤   ¤   int¤i;
b1c37a ¤   ¤   unsigned u;
837299 ¤   ¤   PGPUInt32¤  w32;
3da45f ¤   ¤   char const *s;
9dc86c ¤   ¤   struct {
aea5ab ¤   ¤   ¤   PGPByte const *buf;
673b9a ¤   ¤   ¤   unsigned len;
3ab58c ¤   ¤   } buf;
--7eb7 0018647323f401001ec Page 2 of pgpUI.h
978f51 ¤   } val;
4efb24 } PgpUICbArg ;
19af5a
201254 PGP_END_C_DECLARATIONS
52af5a
86d759 #endif /* Included_pgpUI_h */
--e6ba 001bc6279fa401001ed Page 1 of pgpUsuals.h
bc38e5 /*
f608f6 ·* pgpUsuals.h - Typedefs and #defines used widely.
2f775e ·*
228e68 ·* $Id: pgpUsuals.h,v 1.14 1998/06/11 18:27:57 hal Exp $
4c495d ·*/
fe21e9 #ifndef Included_pgpUsuals_h
66a0df #define Included_pgpUsuals_h
43af5a
8bc5d5 #include "pgpBase.h"
80af5a
b9adb8 #include "pgpOpaqueStructs.h"
5daf5a
6699c6 PGP_BEGIN_C_DECLARATIONS
93af5a
efaf5a
7bbab6 #if PGP_HAVE64
5e2b3d typedef PGPUInt64¤  bnword64;
507454 #endif
ecaf5a
56af5a
5faf5a
754a40 /* A way to hold the PGP Version number */
c4c3e6 typedef int PgpVersion;
c31801 #define PGPVERSION_2¤   2¤  /* 2.0 through 2.5 */
a1fb0d #define PGPVERSION_3¤   3¤  /* 2.6.x */
0b38da #define PGPVERSION_4 ···4 ······/* 3.0 */
a0af5a
b3af5a
2fc2f9 /* The PGP Library Cipher IV Length */
0ddcff #define IVLEN¤  10
57af5a
7e851a /* Literal Message Types */
a4b746 #define PGP_LITERAL_TEXT¤   '\164' /* Ascii 't' */
b384f8 #define PGP_LITERAL_BINARY¤ '\142' /* Ascii 'b' */
c757c5 /* Used only internally for now, when looks like PGP msg inside literal */
c647b0 #define PGP_LITERAL_RECURSE¤'\162' /* Ascii 'r' */
77af5a
fe1254 PGP_END_C_DECLARATIONS
15af5a
bceb31 #endif /* Included_pgpUsuals_h */
--48b1 001b58e9729401001ee Page 1 of pgpBigNumOpaqueStructs.h
a70335 /*____________________________________________________________________________
8d8075 ¤   BigNumOpaqueTypes.h
2767c5 ¤
d7c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
e54b0f ¤   All rights reserved.
a767c5 ¤
cd67c5 ¤
baaf5a
11f46c ¤   $Id: pgpBigNumOpaqueStructs.h,v 1.1.30.1 1998/11/12 03:21:46 heller Exp $
76f7f7 ____________________________________________________________________________*/
54e049 #ifndef Included_pgpBigNumOpaqueStructs_h¤  /* [ */
f23617 #define Included_pgpBigNumOpaqueStructs_h
15af5a
1aaf5a
b3a821 #ifndef TYPE_BigNum
773fcd #define TYPE_BigNum 1
5cbbb3 typedef struct BigNum BigNum;
677454 #endif
97af5a
d5af5a
7ce673 #endif /* ] Included_pgpBigNumOpaqueStructs_h */
5caf5a
4d7e4d /*__Editor_settings____
0daf5a
ff4126 ¤   Local Variables:
5e7b17 ¤   tab-width: 4
ea0e6c ¤   End:
515f8c ¤   vi: ts=4 sw=4
ef9e9b ¤   vim: si
b5d062 _____________________*/
--cff9 001f0f84b62401001ef Page 1 of pgpKeyDBOpaqueStructs.h
a70335 /*____________________________________________________________________________
439788 ¤   pgpKeyDBOpaqueStructs.h
1f67c5 ¤
55c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
844b0f ¤   All rights reserved.
1e67c5 ¤
b467c5 ¤
52af5a
bcbb66 ¤   $Id: pgpKeyDBOpaqueStructs.h,v 1.7.22.1 1998/11/12 03:21:47 heller Exp $
63f7f7 ____________________________________________________________________________*/
2f2ecd #ifndef Included_pgpKeyDBOpaqueStructs_h¤   /* [ */
f20c03 #define Included_pgpKeyDBOpaqueStructs_h
15af5a
7daf5a
2a3856 typedef struct PGPKeyDB¤¤   PGPKeyDB;
1ec4d0 typedef struct PGPUserID¤   PGPUserID;
fd209d typedef struct PGPSubKey¤   PGPSubKey;
28153f typedef struct PGPSig¤  ¤   PGPSig;
e3fd7e typedef struct PGPKey¤  ¤   PGPKey;
dc599c typedef struct PGPKeySet¤   PGPKeySet;
b11b52 typedef struct PGPKeyList¤  PGPKeyList;
9d0954 typedef struct PGPKeyIter¤  PGPKeyIter;
a0e5e5 typedef struct PGPFilter¤   PGPFilter;
b5af5a
64af5a
2ce4f9 #endif /* ] Included_pgpKeyDBOpaqueStructs_h */
0baf5a
647e4d /*__Editor_settings____
bdaf5a
6d4126 ¤   Local Variables:
7e7b17 ¤   tab-width: 4
f00e6c ¤   End:
305f8c ¤   vi: ts=4 sw=4
3c9e9b ¤   vim: si
f0d062 _____________________*/
--c431 0019751976f401001f0 Page 1 of pgpOpaqueStructs.h
a70335 /*____________________________________________________________________________
42e3f1 ¤   pgpOpaqueStructs.h
0467c5 ¤
ebc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
d84b0f ¤   All rights reserved.
9667c5 ¤
2f67c5 ¤
62af5a
abacaa ¤   $Id: pgpOpaqueStructs.h,v 1.18.22.1 1998/11/12 03:21:47 heller Exp $
82f7f7 ____________________________________________________________________________*/
0cd708 #ifndef Included_pgpOpaqueStructs_h¤/* [ */
821262 #define Included_pgpOpaqueStructs_h
f6af5a
73af5a
b854b0 #include "pgpRingOpaqueStructs.h"
63bdbd #include "pgpBigNumOpaqueStructs.h"
d701ab #include "pgpKeyDBOpaqueStructs.h"
95275d #include "pgpPipelineOpaqueStructs.h"
d3af5a
22af5a
20001e typedef struct PGPPubKey¤   ¤   PGPPubKey;
53227d typedef struct PGPSecKey¤   ¤   PGPSecKey;
fff28d typedef struct PGPKeySpec¤  ¤   PGPKeySpec;
9422d9 typedef struct PGPSigSpec¤  ¤   PGPSigSpec;
6512b0 typedef struct PGPRandomContext¤PGPRandomContext;
934b7c typedef struct PGPEnv¤  ¤   ¤   PGPEnv;
840a60 typedef struct PGPUICb¤ ¤   ¤   PGPUICb;
66c155 typedef struct PGPESK¤  ¤   ¤   PGPESK;
56718c typedef struct PGPConvKey¤  ¤   PGPConvKey;
0dbf37 typedef struct PGPFile¤ ¤   ¤   PGPFile;
0d90ce typedef struct PGPFileError¤¤   PGPFileError;
d8d50b typedef struct PGPFileRead¤ ¤   PGPFileRead;
c47035 typedef struct PGPStringToKey¤  PGPStringToKey;
c6288a typedef struct PGPPkAlg¤¤   ¤   PGPPkAlg;
cef5cd typedef struct PGPFifoContext¤  PGPFifoContext;
ea4e82 typedef struct RingError¤   ¤   RingError;
f835ea typedef struct PGPPassCache¤¤   PGPPassCache;
bf3c55 typedef struct PGPFileSpec¤ ¤   PGPFileSpec;
0e5348 typedef struct MemPool¤ ¤   ¤   MemPool;
0767dd typedef struct PGPKeyIDPriv¤¤   PGPKeyIDPriv;
e5af5a
c7545e typedef struct PGPHashList¤ ¤   ¤   ¤   ¤   PGPHashList;
e0aac1 typedef struct PGPHashList *¤   ¤   ¤   ¤   PGPHashListRef;
2caf5a
88a292 typedef struct PGPHashVTBL¤ ¤   ¤   ¤   ¤   PGPHashVTBL;
e745d0 typedef struct PGPPublicKeyContext¤ ¤   ¤   PGPPublicKeyContext;
3e9931 typedef struct PGPPrivateKeyContext¤¤   ¤   PGPPrivateKeyContext;
21bc49 typedef struct PGPCipherVTBL¤   ¤   ¤   ¤   PGPCipherVTBL;
c33085 typedef struct PGPHashContext¤  ¤   ¤   ¤   PGPHashContext;
93b21e typedef struct PGPCFBContext¤   ¤   ¤   ¤   PGPCFBContext;
70b26a typedef struct PGPCBCContext¤   ¤   ¤   ¤   PGPCBCContext;
f8d46f typedef struct PGPSymmetricCipherContext¤   PGPSymmetricCipherContext;
44af5a
6dfcd7 typedef struct PGPRandomVTBL¤   ¤   ¤   ¤   PGPRandomVTBL;
97af5a
b0af5a
c5af5a
232aed #endif /* ] Included_pgpOpaqueStructs_h */
f4af5a
c27e4d /*__Editor_settings____
cdaf5a
574126 ¤   Local Variables:
227b17 ¤   tab-width: 4
9a0e6c ¤   End:
485f8c ¤   vi: ts=4 sw=4
7c9e9b ¤   vim: si
97d062 _____________________*/
--f6ae 001e07a59ea401001f1 Page 1 of pgpPipelineOpaqueStructs.h
a70335 /*____________________________________________________________________________
751f52 ¤   pgpPipelineOpaqueStructs.h
2f67c5 ¤
7ec97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
4f4b0f ¤   All rights reserved.
a167c5 ¤
ff67c5 ¤
e1af5a
28f739 ¤   $Id: pgpPipelineOpaqueStructs.h,v 1.4.30.1 1998/11/12 03:21:48 heller Exp $
5cf7f7 ____________________________________________________________________________*/
79b12c #ifndef Included_pgpPipelineOpaqueStructs_h¤/* [ */
0cdcc3 #define Included_pgpPipelineOpaqueStructs_h
79af5a
43af5a
c8637e typedef struct PGPPipeline¤ ¤   PGPPipeline;
af9d85 typedef struct PGPFifoDesc¤ ¤   PGPFifoDesc;
a0af5a
9aaf5a
1d2a9f #endif /* ] Included_pgpPipelineOpaqueStructs_h */
b4af5a
6d7e4d /*__Editor_settings____
67af5a
e04126 ¤   Local Variables:
957b17 ¤   tab-width: 4
650e6c ¤   End:
b85f8c ¤   vi: ts=4 sw=4
e09e9b ¤   vim: si
e0d062 _____________________*/
--c2be 0016b0756a8401001f2 Page 1 of pgpRingOpaqueStructs.h
a70335 /*____________________________________________________________________________
74c512 ¤   RingOpaqueStructs.h
6067c5 ¤
21c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
a44b0f ¤   All rights reserved.
9f67c5 ¤
a967c5 ¤
eeaf5a
c8b034 ¤   $Id: pgpRingOpaqueStructs.h,v 1.3.30.1 1998/11/12 03:21:49 heller Exp $
47f7f7 ____________________________________________________________________________*/
b64afe #ifndef Included_pgpRingOpaqueStructs_h¤/* [ */
57d94c #define Included_pgpRingOpaqueStructs_h
66af5a
12af5a
67375e typedef union ·RingObject¤  ¤   RingObject;
dfdf62 typedef struct RingSet¤ ¤   ¤   RingSet;
8421bc typedef struct RingIterator¤¤   RingIterator;
fd6d82 typedef struct RingFile¤¤   ¤   RingFile;
d2e6d7 typedef struct RingPool¤¤   ¤   RingPool;
b3b848 typedef struct RingTrouble¤ ¤   RingTrouble;
76af5a
bdaf5a
4f7fc1 #endif /* ] Included_pgpRingOpaqueStructs_h */
ceaf5a
217e4d /*__Editor_settings____
24af5a
b14126 ¤   Local Variables:
867b17 ¤   tab-width: 4
a70e6c ¤   End:
755f8c ¤   vi: ts=4 sw=4
329e9b ¤   vim: si
6bd062 _____________________*/
--ed64 00148246a63401001f3 Page 1 of Makefile.in
5ea601 #
739b65 # priv/keys/
4fa601 #
65b250 # $Id: Makefile.in,v 1.2 1997/07/28 23:43:20 mhw Exp $
0ea601 #
63af5a
e71518 SUBDIRS=keydb keys pubkey
d11319 LIBDONE=keydb/DONE keys/DONE pubkey/DONE
19af5a
96211d all:: LIBDONE
48af5a
--7a79 001f11cccaf401001f4 Page 1 of Makefile.in
5ea601 #
f06e7b # priv/keys/keys/
30a601 #
10e67d # $Id: Makefile.in,v 1.2 1997/05/04 10:30:20 mhw Exp $
44a601 #
45af5a
57d808 OBJS= pgpMemPool.o pgpRngPub.o pgpRngPriv.o pgpRngPkt.o pgpRngPars.o \
81fa07 ¤   pgpRngRead.o pgpRngMnt.o pgpTrust.o pgpTrstPkt.o
5054ee PRIVHDRS= pgpRngMnt.h pgpRngPub.h pgpRngRead.h pgpTrust.h pgpTrstPkt.h \
b1ed31 ¤   pgpRngPriv.h pgpRngPkt.h pgpRngPars.h pgpMemPool.h
0aaf5a
c8b7a3 all:: DONE
f1af5a
--8c80 0000e0e58ed401001f5 Page 1 of pgpMemPool.c
bc38e5 /*
f46f5a ·* pgpMemPool.c - Pooled memory allocation, similar to GNU obstacks.
e5775e ·*
5868c2 ·* Written by Colin Plumb.
43775e ·*
d60224 ·* $Id: pgpMemPool.c,v 1.9 1997/07/29 20:01:40 hal Exp $
19495d ·*/
f5e2ff #include "pgpConfig.h"
22af5a
b5feb2 #include <stdio.h>
10324c #include <string.h>
c7af5a
33a146 #include "pgpDebug.h"
c695a9 #include "pgpMemPool.h"
ea0d08 #include "pgpMem.h"
52c26c #include "pgpContext.h"
21af5a
aa0596 #ifndef NULL
94699b #define NULL 0
be7454 #endif
06af5a
613f62 /* Define this symbol to cause secure wiping */
78418d #ifndef SECURE
e19333 #define SECURE 1
607454 #endif
88af5a
0638e5 /*
b99985 ·* The memory pool allocation functions
93775e ·*
f08154 ·* These are based on a linked list of memory blocks, usually of uniform
22bfdd ·* size. ·New memory is allocated from the tail of the current block,
f441cf ·* until that is inadequate, then a new block is allocated.
e05b44 ·* The entire pool can be freed at once by calling memPoolFree().
c1495d ·*/
28af5a
c9be8c typedef struct PoolBuf {
fe6c12 ¤   struct PoolBuf *next;
fec87c ¤   unsigned size;
88dfc4 ¤   /* Data follows */
b8f81d } PoolBuf;
1faf5a
4c1e15 /* Page size to use */
14306a #ifdef MSDOS
d7ee3c #define ALLOC_UNIT 1024
fbdb21 #else
c9d27e #define ALLOC_UNIT 4096
0e7454 #endif
e8af5a
d72685 static MemPool const EmptyPool =
a50506 ¤   { NULL, NULL, NULL, 0, ALLOC_UNIT, 0, (int (*)(void *))NULL, NULL};
5faf5a
76af5a
7438e5 /*
411aa8 ·* Initialize the pool for first use
9f495d ·*/
92314a void
5ad95b memPoolInit(
9c520e ¤   PGPContextRef¤  context,
afc03f ¤   MemPool *¤  ¤   pool)
4cbb36 {
d898ce ¤   *pool = EmptyPool;
0a67c5 ¤
c2abd9 ¤   pool->context¤  = context;
9cefe6 }
8baf5a
a9eb07 /* Set the pool's purge function */
f4314a void
bfbbd5 memPoolSetPurge(MemPool *pool, int (*purge)(void *), void *arg)
79bb36 {
835b2f ¤   pool->purge = purge;
b05430 ¤   pool->purgearg = arg;
0eefe6 }
--a3c6 000e5b9b1e7401001f5 Page 2 of pgpMemPool.c
e0af5a
d338e5 /*
148c8b ·* Free all the memory in the pool
7c495d ·*/
92314a void
45bf2d memPoolEmpty(MemPool *pool)
3ebb36 {
baf350 ¤   PoolBuf *buf;
46af5a
af013e ¤   while ((buf = pool->head) != NULL) {
f92f66 ¤   ¤   pool->head = buf->next;
98adcb #if SECURE
c7340f ¤   ¤   pgpClearMemory( buf, ·buf->size);
577454 #endif
0f8476 ¤   ¤   pgpContextMemFree( pool->context, buf);
de9371 ¤   }
6881f1 ¤   pool->freespace = 0;
aecc7c ¤   pool->totalsize = 0;
94efe6 }
fdaf5a
93af5a
b838e5 /*
d36c3c ·* Restore a pool to a marked position, freeing subsequently allocated
e2e68e ·* memory.
ce495d ·*/
e0314a void
2b3250 memPoolCutBack(MemPool *pool, MemPool const *cutback)
90bb36 {
61f350 ¤   PoolBuf *buf;
d5af5a
f32436 ¤   pgpAssert(pool);
bd386f ¤   pgpAssert(cutback);
9caf5a
6838ae ¤   pgpAssert(pool->totalsize >= cutback->totalsize);
62af5a
fe5932 ¤   while((buf = pool->head) != cutback->head) {
522f66 ¤   ¤   pool->head = buf->next;
dcadcb #if SECURE
ce340f ¤   ¤   pgpClearMemory( buf, ·buf->size);
e67454 #endif
29df5b ¤   ¤   pgpContextMemFree( pool->context, buf );
919371 ¤   }
02c150 ¤   *pool = *cutback;
e4efe6 }
7baf5a
daaf5a
5538e5 /*
6019a5 ·* Structure and string allocations.
f297b6 ·* To make alingment work, strings and other objects
89bb91 ·* are allocated from different pools.
50495d ·*/
b8af5a
aa38e5 /*
3f3ccb ·* Allocate a chunk of memory for a structure, with the given alignment.
a4b127 ·* This is more space-efficient than malloc() for small objects
86af8b ·* with loose alignment restrictions - like short strings.
ebd320 ·* Note that alignment is relative to the beginning of a chunk returned from
585330 ·* malloc(), which is guaranteed by ANSI to be as aligned as can possibly
a2a0b1 ·* matter.
91495d ·*/
ae9a44 void *
89517d memPoolAlloc(MemPool *pool, unsigned len, unsigned alignment)
54bb36 {
d3813a ¤   char *p;
460ed5 ¤   unsigned t;
f7af5a
fa2675 ¤   /* Where to allocate next object */
cb135b ¤   p = pool->freeptr;
ba8bca ¤   /* How far it is from the beginning of the chunk. */
683cfb ¤   t = p - (char *)pool->head;
5dd8af ¤   /*
e5f2f6 ¤   ·* How much padding to add to freeptr to make alignment. ·The first
--d954 0019f250171401001f5 Page 3 of pgpMemPool.c
e4b663 ¤   ·* case (not a power of 2) will never happen, but we do it right
8d4d82 ¤   ·* for bragging rights in the ANSI C compliance department.
fba4e3 ¤   ·*/
ad32a6 ¤   if (alignment & (alignment-1))
ff11f3 ¤   ¤   t = alignment-1 - (t-1)%alignment;¤ /* Never called */
0b0e24 ¤   else
113857 ¤   ¤   t = -(int)t & (alignment-1);¤   /* This one always */
b6af5a
6ca569 ¤   /* Okay, does it fit? */
f01ca5 ¤   if (pool->freespace >= len+t) {
3e7718 ¤   ¤   pool->freespace -= len+t;
0e5910 ¤   ¤   p += t;
a2eb83 ¤   ¤   pool->freeptr = p + len;
fabda8 ¤   ¤   return p;
9b9371 ¤   }
c7af5a
26833d ¤   /* It does not fit in the current chunk. ·Allocate a new chunk. */
2daf5a
fb3654 ¤   /* First, figure out how padding is needed after the header. */
6132a6 ¤   if (alignment & (alignment-1))
037697 ¤   ¤   alignment -= 1 + (sizeof(PoolBuf)-1) % alignment;
3a0e24 ¤   else
e83e24 ¤   ¤   alignment = (alignment-1) & -(int)sizeof(PoolBuf);
8d6bac ¤   alignment += sizeof(PoolBuf);
550659 ¤   /* Then, figure out a chunk size that will fit */
8eec1c ¤   t = pool->chunksize;
832ef7 ¤   pgpAssert(t);
649c3a ¤   while (len + alignment > t)
879b4a ¤   ¤   t *= 2;
897fbb ¤   while ((p = (char *)
f6fe9c ¤   ¤   pgpContextMemAlloc( pool->context, t, 0)) == NULL)
a4c7a1 ¤   {
8aa82e ¤   ¤   /* If that didn't work, try purging or smaller allocations */
43cb6a ¤   ¤   if (!pool->purge || !pool->purge(pool->purgearg)) {
c3f93f ¤   ¤   ¤   if (len + alignment == t)
f4fb5e ¤   ¤   ¤   ¤   return NULL;
de18be ¤   ¤   ¤   t /= 2;
c4797a ¤   ¤   ¤   if (t < len+alignment)
688f92 ¤   ¤   ¤   ¤   t = len+alignment;
ec0fe4 ¤   ¤   }
049371 ¤   }
b0af5a
d4ee5f ¤   /* Update the various pointers. */
9ba469 ¤   pool->totalsize += t;
b68387 ¤   ((PoolBuf *)p)->next = pool->head;
0dbda2 ¤   ((PoolBuf *)p)->size = t;
05ddd1 ¤   pool->head = (PoolBuf *)p;
71e060 ¤   pool->freespace = t - len - alignment;
519917 ¤   p += alignment;
9650d5 ¤   pool->freeptr = p + len;
1aaf5a
40381d ¤   return p;
97efe6 }
b3af5a
f057de #ifdef DEADCODE
de38e5 /*
ff129d ·* Store a string in the table, returning a pointer to the string.
26495d ·*/
bd5cc8 char const *
b9d429 memPoolStore(MemPool *pool, char const *str)
50bb36 {
93aa98 ¤   unsigned len = strlen(str) + 1;
00813a ¤   char *p;
edaf5a
f3806f ¤   p = memPoolAlloc(pool, len, 1);
0568fc ¤   if (p)
04de73 ¤   ¤   memcpy(p, str, len);
4aaf5a
ca381d ¤   return p;
61efe6 }
9f7454 #endif
--8109 0011babcf65401001f6 Page 1 of pgpMemPool.h
bc38e5 /*
24ea8b ·* $Id: pgpMemPool.h,v 1.8 1997/06/21 00:25:35 lloyd Exp $
2b495d ·*/
66af5a
74f063 #ifndef Included_pgpMemPool_h
aaa457 #define Included_pgpMemPool_h
feaf5a
64af5a
2dadb8 #include "pgpOpaqueStructs.h"
b1e82c #include "pgpPubTypes.h"
5baf5a
c199c6 PGP_BEGIN_C_DECLARATIONS
58af5a
2ff324 struct MemPool
6fbb36 {
498a97 ¤   PGPContextRef¤  context;
5867c5 ¤
f5cbbf ¤   struct PoolBuf *head;
1c269b ¤   char *freeptr;
bc4276 ¤   unsigned freespace;
8c4a3f ¤   unsigned chunksize;¤/* Default starting point */
8a4934 ¤   unsigned long totalsize;
22f921 ¤   int (*purge)(void *);¤  /* Return non-zero to retry alloc */
bdb4f0 ¤   void *purgearg;
6282f7 };
ddaf5a
5baf5a
b738e5 /*
9af456 ·* Nice clean interfaces
a0495d ·*/
068901 #define memPoolIsEmpty(pool) ((pool)->head == 0)
1daf5a
a8c823 void·
091858 memPoolInit(PGPContextRef context, MemPool *pool);
b3af5a
9ac823 void·
d181bb memPoolSetPurge(MemPool *pool, int (*purge)(void *), void *arg);
9daf5a
30c823 void·
b6fa78 memPoolEmpty(MemPool *pool);
c8af5a
2ac823 void·
e004ca memPoolCutBack(MemPool *dest, MemPool const *cutback);
4daf5a
e7fed5 void ·*
a8a813 memPoolAlloc(MemPool *pool, unsigned len, unsigned alignment);
3eaf5a
5357de #ifdef DEADCODE
a9b077 char const ·*
fbbc37 memPoolStore(MemPool *pool, char const *str);
477454 #endif
37af5a
8fda72 /* Lookie here! ·An ASNI-compliant alignment finder! */
e4cbc2 #define alignof(type) (sizeof(struct{type _x; char _y;}) - sizeof(type))
d5af5a
d9e554 #define memPoolNew(pool, type) memPoolAlloc(pool, sizeof(type), alignof(type))
05af5a
1e1254 PGP_END_C_DECLARATIONS
51af5a
1b459b #endif /* Included_pgpMemPool_h */
--c8ad 0001706f3c5401001f7 Page 1 of pgpRngMnt.c
bc38e5 /*
c584d6 ·* pgpRngMnt.c - Perform the maintenance pass over a keyring.
ff5d51 ·* This is a lot more efficient that the way PGP 2.x did it and,
b8d098 ·* I modestly think, easier to understand to boot.
ce775e ·*
9bfbf7 ·* Written by Colin Plumb
87775e ·*
d933cc ·* $Id: pgpRngMnt.c,v 1.63 1998/07/22 03:03:33 hal Exp $
d7495d ·*/
73e2ff #include "pgpConfig.h"
fbaf5a
e42cb0 #include <string.h>¤/* For strlen() */
4a0a8b #include <time.h>
807cab #include <stddef.h>
a7af5a
39a146 #include "pgpDebug.h"
c4c305 #include "pgpMakeSig.h"
c50d08 #include "pgpMem.h"
189c38 #include "pgpPktByte.h"
805d53 #include "pgpRegExp.h"
545d28 #include "pgpRngMnt.h"
332e22 #include "pgpRngPars.h"
777a44 #include "pgpRngPriv.h"
bad229 #include "pgpRngPkt.h"
56806a #include "pgpRngRead.h"
de5a03 #include "pgpTrust.h"
a2ae6d #include "pgpTrstPkt.h"
df2266 #include "pgpTimeDate.h"
895417 #include "pgpHashPriv.h"
f82f8d #include "pgpErrors.h"
73cdc2 #include "pgpPubKey.h"
7c65ec #include "pgpRngRead.h"¤/* for ringFetchObject */
4243bc #include "pgpSig.h"
e6f5ab #include "pgpSigSpec.h"
21d11f #include "pgpUsuals.h"
f1675a #include "pgpTypes.h"
66d2c2 #include "pgpX509Priv.h"
25af5a
640596 #ifndef NULL
10699b #define NULL 0
217454 #endif
99af5a
f538e5 /*
43ac76 ·* This symbol marks code which prints the progress of the maintenance
35e01f ·* pass. ·That code assumes stdio, which is not portable across GUIs, so
38d403 ·* something will need to be done about it. ·The prints are left in the
cf4494 ·* source to make the location of the replacements obvious. ·The code
8ab7af ·* assumes a non-existent "FILE *f" to print to, so just #defining this
ff8610 ·* symbol will NOT work.
88495d ·*/
98f612 #undef PRINT_PROGRESS
09af5a
f338e5 /*
38eac6 ·* The trust models...
681252 ·* All models start from a number of axiomatic "the buck stops here"
fc9c26 ·* keys. ·These are the keys owned by the PGP user. ·This is the
d8140f ·* initial set of trusted keys. ·Each key has a trust value - a
3e821e ·* level of confidence that the user places in signatures made by
5db3db ·* that key.
a19ec0 ·*·
009ec0 ·*·
556cd1 ·* -- The old trust model (PGPTRUSTMODEL==0) --
85775e ·*
0c9f58 ·* Each key has an introducer trust, either ultimate, complete, or
1b93b3 ·* partial. ·These have scores of 1, 1/x and 1/y. ·For each key on the
4e2f5b ·* axiomatically trusted list, and each signature made by that key on
2c097c ·* a name, the introducer trust is added to the name's validity score.
3119c0 ·* If that score reaches 1, the name's key is added to the next introducer
f8c2c7 ·* list and its introducer trust is used for the level after that.
58775e ·*
3118eb ·* At the end, names are graded according to their score.
17a19e ·* If it is >= 1, they are completely valid. ·If it is >= 1/2,
--dcc8 000aac90c3c401001f7 Page 2 of pgpRngMnt.c
e6b69e ·* they are partially valid. ·If < 1/2, they are not valid at all.
a48a61 ·* Partial versus lack of validity only affects the warning messages
1ade84 ·* printed out. ·If a key does not have any comletely valid names,
0b1538 ·* its introducer trust is set to 0.
d3775e ·*
8fd7a6 ·* There are actually three kinds of zero introducer trust:
0d7b0f ·* - Undefined, meaning that it has not been set. ·If a key has
a64b58 ·* ··a completely valid name and undefined introducer trust, the
172df6 ·* ··user is asked to set one.
67c8ee ·* - Unknown
f66c10 ·* - Untrusted
3b62b7 ·* ··These latter two are equivalent valid "set" values, with the
5f15dd ·* ··only difference being for user-interface purposes.
82775e ·*
a8775e ·*
b9cc09 ·* -- The new trust model (PGPTRUSTMODEL == 1 or 2) --
94775e ·*
362383 ·* This is based on a much more rigorous treatment of trust by Ueli
154cb3 ·* Maurer. ·See "Modelling a Public-Key Infrastructure", Ueli Maurer,
d04471 ·* Proceedings 1996 European Symposium on Research in Computer Security
8bb05d ·* (ESORICS '96), E. Bertino (Ed.), Lecture Notes in Computer Science,
9734e7 ·* Berlin: Springer-Verlag, Rome, Italy, Sept. 1996. ·Also available from
24db06 ·* <URL: http://www.inf.ethz.ch/personal/maurer/publications>.
73775e ·*
0eb08a ·* Consider the graph formed by taking each key as a node and
c31797 ·* each signature as an edge, and assign each signature an independent
54c1f4 ·* probability of being correct. ·(The probabilities don't have to be
ec3a8d ·* independent, but it gets messy fast if they aren't, so the possibility
b2e7e8 ·* isn't considered any further.) ·For each possible combination of
affa09 ·* valid and invalid signatures, assign it a probability based on the
4b2eeb ·* probability of each signature being correct, and if there is a path
407057 ·* of valid signatures from the root set to a given name, it is correct.
b4cef0 ·* Add up the probabilities of all the cases in which the name is correct,
1d75d1 ·* and you have the computed probability that the name is correct.
14775e ·*
2fe990 ·* For PGPTRUSTMODEL==1:
82775e ·*
10a2c7 ·* Basically, you have to consider every possible path from the root
b04a75 ·* set of axiomatically trusted keys to the name in question and correct
7d716c ·* for overlaps and loops. ·This can't be done in a reasonable amount of
988e33 ·* time, but a conservative approximation can be made. ·By leaving out
f3d056 ·* some of the more complex paths, a lower probability can be computed.
eac841 ·* Since it is lower than the ideal computation, it can still be trusted.
38f3e7 ·* A good approximation is fast to compute and yet approaches the ideal
4f66c2 ·* approximation well.
ce775e ·*
69aa5b ·* Since PGP supports multiple names on a key, the question arises
b44222 ·* which validity value is used. ·The solution here is to assign a trust
30c295 ·* value to each of the names, take the validity*trust product for each
dc4bd5 ·* name, and take the maximum. ·A name which is meaningless to the user
905369 ·* (e.g. a name in an unknown character set, such as cyrillic or kanji)
049dd1 ·* can't be trusted, but that doesn't mean that a second name which *is*
6f3c9f ·* intelligible should be penalized.
dc775e ·*
a7e38c ·* The approximation that PGP uses is as follows:
96691a ·* - Clear all trust accumulators to 0.
340529 ·* - Starting with a root set of keys (level 0), each of which have some
1f8d19 ·* ··specified confidence, take that confidence directly as the trust.
d9f191 ·* ··This is currently assumed to be ultimate. ·For each signature made
b7c084 ·* ··by such a key, add the confidence to the name's valididty score.
05d05a ·* - Using this provisional validity, multiply each names's confidence
e6f011 ·* ··by its validity to get a provisional trust. ·Use this trust to
edf59a ·* ··increase the validity score of each name already processed.
9cb00e ·* - Multiply the final validity by the confidence to get the final trust
f9dd69 ·* ··on the key, which is used
80775e ·*
0ae278 ·* Description of PGPTRUSTMODEL==2:
85775e ·*
66fd96 ·* This implements the basic Maurer trust model fairly literally. ·The
16b71a ·* Maurer model is often considered to be "intractably complex" (an
8a5fea ·* out of context quote from his paper), but with certain
aaafe8 ·* simplifications it should be feasible:
--7108 00035098bfe401001f7 Page 3 of pgpRngMnt.c
4f775e ·*
13d98a ·* - Focus on on-the-fly validation so we only have to find the validity of
1d9192 ·* ··a single key.
28910b ·* - Use a ringset composed only of trusted introducers and the target key.
a91201 ·* - Search for paths from the target key back to an axiomatic key such that
1cbce2 ·* ··all keys on the path are trusted introducers (nonzero confidence).
670ba5 ·* - Limit this search by a depth constraint, and possibly limit the total
388819 ·* ··number of nodes we will look at if the depth constraint is inadequate.
25d5f5 ·* - Find the basic trust contribution of each of the resulting paths (not yet
e3eb51 ·* ··considering interactions) as the product of the trust of each segment on
a7d5ff ·* ··the path.
bc8172 ·* - Sort the paths by this value and prune to keep just the top 10 or
70549e ·* ··so paths.
ece38f ·* - Apply Maurer's algorithm, considering all subsets of paths (2**n of them,
1bfc2a ·* ··where n is the number of paths). ·For each subset, form the union of all
4bc294 ·* ··segments on the paths in that subset, and take the product of the segment
7ba38e ·* ··trusts. ·Subsets with an odd number of paths add confidence, those with an
570da7 ·* ··even number of paths subtract.
b1775e ·*
9b5dc0 ·* By limiting ourselves to just the trusted introducers (plus one
716801 ·* other) the total number of keys to be considered should not become
cf7f8a ·* too large. ·Given practical and customary limitations on the number
0407ab ·* of signatures a key will usually have, it should be possible to
e8adc8 ·* find paths back to the axiomatic keys in a reasonable amount of
096308 ·* time, especially if the algorithm only needs to be run for a single
563628 ·* key (or a small number of keys) when we encrypt or check a
55a2e7 ·* signature. ·Then when we prune the list of paths to just the top
1f3482 ·* 10, we should still be able to get a reasonably accurate
697a39 ·* (under)estimate of the actual trust, unless the key gained trust by
ef3e5c ·* having a large number of paths each with only a small amount of
904153 ·* trust. ·That case must be neglected for efficiency in this
94b603 ·* algorithm. ·Having pruned the paths to a small enough set we can
a6c5ec ·* then apply Maurer's algorithm efficiently.
c9775e ·*
9198b9 ·* There is an additional complication specific to the PGP trust
9cbc27 ·* model. ·Maurer's algorithm is expressed in terms of paths where
0cc980 ·* each segment has an associated trust level. ·These trusts are
ef0416 ·* described in PGP as user-defined confidence levels specified for
744129 ·* the name(s) on a key. ·This means that the output of the
48b517 ·* calculation above is a validity value for a particular name on a
82b2e7 ·* key, based on the signatures on that name. ·The inputs need to be
920295 ·* based on the user defined confidence values for the names. ·The
1767bd ·* complication arises for keys which have more than one name (userid)
2d77c7 ·* with different user-defined confidence levels. ·It is not clear how
edfb82 ·* to map this situation to Maurer's trust model.
04775e ·*
bc9b55 ·* For keys with only one name, the confidence of that name is used.
ef4fb0 ·* If there is more than one name, a conservative approach is to use
4afdea ·* the name with the smallest user-defined confidence value. ·(Names
d39da7 ·* for which the user has not specified a confidence level do not
0188ff ·* enter into this calculation.) ·If all of the names (of those with
90b75b ·* non-zero confidence) have validity values (from earlier runs of the
451695 ·* trust calculation) then we can choose the confidence of the name
cda783 ·* with the highest validity as in PGPTRUSTMODEL==1.
59775e ·*
20718a ·* Not all of the optimizations above are implemented in the current
a215bf ·* code, nor has it been thoroughly tested. ·In particular, the
853840 ·* ringMnt function is still used and tries to run the algorithm on
0bdcfb ·* all keys in the set. ·Although a depth limitation is used there is
4945b6 ·* no other way of limiting the construction of the paths.
3f775e ·*
77c0d3 ·* Some further ideas for improvement:
47775e ·*
6943cd ·* - Paths don't need to include the last step to the trusted
5ea6f5 ·* ··introducer, since that always has confidence of 1.0.
32775e ·*
8cb20b ·* - For creating the path subset unions, a linear search for overlap
cd3904 ·* ··is used now. ·This may be OK for short paths but a more efficient
5aa64a ·* ··algorithm would be better. ·Perhaps a hash table for path segments
f4f311 ·* ··in the subset would be worthwhile.
91775e ·*
35ceee ·* - When adding/subtracting the pathconf values, maybe it would be
--aff1 000c446a252401001f7 Page 4 of pgpRngMnt.c
551f96 ·* ··better to accumulate 1-confidence rather than confidence? ·I am
53cd01 ·* ··worried about roundoff error for values very close to 1.0.
f6775e ·*
48301d ·* - Could use a Gray code to go through path subsets in a sequence
8f7367 ·* ··which would alternate even and odd parity subsets, so we would
1a9acd ·* ··alternately add and subtract trust. ·This might help with
e364c3 ·* ··accuracy. ·(A Gray code is a binary counter which has the property
ad3a48 ·* ··that only one bit changes each step. ·One example is:
c841ed ·* ··++j, i ^= j & (j ^ (j-1)); which counts j as a regular counter and
18c14a ·* ··i as a Gray code counter.)
8b495d ·*/
30af5a
4caf5a
95af5a
3faf5a
d5558a /********************** REGEXP Support ***************************/
fcaf5a
62af5a
5af5be /* Clear key regexp pointers */
df33c8 ¤   static void
c98cfa mntClearKeyRegexps( RingSet const *set )
44bb36 {
6f6032 ¤   RingPool *pool = set->pool;
f0f78a ¤   RingObject *key;
50af5a
ca5f62 ¤   for (key=pool->keys; key; key=key->g.next) {
f2639f ¤   ¤   if (!pgpIsRingSetMember(set, key))
9017f5 ¤   ¤   ¤   continue;
8fcaed ¤   ¤   key->k.regexp = NULL;
769371 ¤   }
19efe6 }
8daf5a
ffaf5a
a8af5a
3caf5a
da39c8 /* Check whether a sig is made illegal due to regexp considerations.
73ab1b ·* return TRUE if OK, FALSE if not. ·If we have some error handling the regexp,
e44180 ·* we say the sig is not OK.
8a495d ·*/
b1df0d ¤   static int
73c1b6 mntSigOKWithRegexp( RingSet const *set, RingSig const *sig )
16bb36 {
d011ea ¤   RingObject *parent;
e142c1 ¤   RingObject *signer;
4388ca ¤   char const *sname;
07875f ¤   PGPSize len;
e5f678 ¤   int rslt;
e5af5a
47691c ¤   /* See if signing key got its trust conditioned with a regexp */
213770 ¤   signer = sig->by;
b324d3 ¤   if (!signer->k.regexp)
03836c ¤   ¤   return TRUE;
5caf5a
235a9e ¤   /* Can only handle sigs on names for regexps */
1641eb ¤   parent = sig->up;
f24fc7 ¤   if (!OBJISNAME(parent))
9398aa ¤   ¤   return FALSE;
54af5a
65e93a ¤   /* See if name matches regexp */
bcb9ad ¤   sname = ringNameName (set, parent, &len);
a6c1e6 ¤   rslt = pgpRegExec( (regexp *)signer->k.regexp, sname );
600167 ¤   if (rslt == 1)
51836c ¤   ¤   return TRUE;
f3a230 ¤   return FALSE;
16efe6 }
bfaf5a
67af5a
6daf5a
14e8cf /******************** Signature Utility Functions **********************/
afaf5a
7eaf5a
c438e5 /*
--c82e 0008b637062401001f7 Page 5 of pgpRngMnt.c
08eb03 ·* Check to see if the signature is valid at this point in time. ·
c1775e ·*
a465a5 ·* To avoid overflow problems with 65535 days being larger than a 32-bit
6f27a6 ·* timestamp, compute how old the signature is in days, and compare
3684a6 ·* that with the validity period. ·If its age, in days rounded down,
251acb ·* is < the validity period, it is valid. ·To deal with a validity
d1f448 ·* period of 0 being infinite, subtract one from the validity using
0d5c93 ·* unsigned arithmetic and change the < to <=. ·(n < 5 iff n <= 4, for
484c56 ·* integer n). ·0 will wrap to UINT_MAX, and every unsigned number
c0ca04 ·* compared <= UINT_MAX, so the test will always be true.
84775e ·*
78bba9 ·* An intelligent 8086 or 68000 compiler would evaluate the division by
7b1d2e ·* 86400 = 675 * 128 as (x>>7)/675, which can use a 32/16 bit divide
256467 ·* (which can't overflow), but I'd be surprised if any PC compilers
a8408f ·* actually did it that way.
50495d ·*/
e656b6 static PGPBoolean
980a76 mntSigIsValid(PGPUInt32 timenow, PGPUInt32 tstamp, unsigned validity)
39bb36 {
cb111d ····return·
a03d0e ¤   ··(timenow <= tstamp || (unsigned)((timenow-tstamp)/86400) <= validity-1u);
64efe6 }
1faf5a
0f7534 /* True if signature is a valid, checked, unexpired key signature. ·If
44a66c ·* set is non-null it also checks that sig is in the set.
5c495d ·*/
f656b6 static PGPBoolean
28c85c mntSigIsValidKeySig(RingObject const *sig, RingSet const *set,
5904c0 ¤   PGPUInt32 timenow)
cabb36 {
ee0536 ¤   return OBJISSIG(sig)
71d3e0 ¤   ¤   && (sig->s.trust & PGP_SIGTRUSTF_CHECKED)
2e9008 ¤   ¤   && (IsNull(set) || pgpIsRingSetMember(set, sig))
20953e ¤   ¤   && (sig->s.type & 0xF0) == PGP_SIGTYPE_KEY_GENERIC
800f97 ¤   ¤   && (IsNull(set) || mntSigOKWithRegexp( set, &sig->s ))
2dbed8 ¤   ¤   && mntSigIsValid(timenow, sig->s.tstamp, sig->s.validity);
54efe6 }
b91b52 ¤   ¤
3baf5a
0b38e5 /*
b99a4d ·* Return the newest sibling signature, based on the nextby fields.
ec6ed1 ·* Advances *sig to point beyond the sigs on this object
62495d ·*/
399c97 static RingSig *
22a5f7 mntNewestValidSiblingSig(RingSig const **sig, RingSet const *set,
8504c0 ¤   PGPUInt32 timenow)
4fbb36 {
d99c32 ¤   RingSig *newest;
7daf5a
67c022 ¤   pgpAssert(SIGISSIG(*sig));
ce4ab8 ¤   newest = (RingSig *)(*sig);
ed36ee ¤   while ((*sig = (*sig)->nextby) != NULL && (*sig)->up == newest->up) {
6c53b4 ¤   ¤   if ((*sig)->trust & PGP_SIGTRUSTF_CHECKED
5b936c ¤   ¤   ¤   && pgpIsRingSetMember (set, (RingObject *)(*sig))
6319a5 ¤   ¤   ¤   && newest->tstamp < (*sig)->tstamp
c3dfde ¤   ¤   ¤   && mntSigOKWithRegexp( set, *sig )
6ee1ed ¤   ¤   ¤   && mntSigIsValid(timenow, (*sig)->tstamp, (*sig)->validity))
120411 ¤   ¤   ¤   newest = (RingSig *)(*sig);
749371 ¤   }
6ce8dd ¤   return newest;
67efe6 }
46af5a
58af5a
998cd6 /* True if a non-exportable sig for which we don't have the secret */
7956b6 static PGPBoolean
2d3185 mntForeignSignature(RingSig const *sig, RingSet const *set)
39bb36 {
9037a8 ¤   RingObject *key = sig->by;
ecef05 ¤   RingObject *sec;
62af5a
f986ce ¤   /* False if exportable */
8b99d4 ¤   if (SIGISEXPORTABLE(sig))
--c921 0003f2a4e18401001f7 Page 6 of pgpRngMnt.c
5b98aa ¤   ¤   return FALSE;
2a0410 ¤   /* False if by axiomatic key */
d0b249 ¤   if (key->k.trust & PGP_KEYTRUSTF_BUCKSTOP)
6498aa ¤   ¤   return FALSE;
49cbde ¤   sec = key->g.down;
d277ac ¤   for (sec=key->g.down; sec; sec=sec->g.next) {
be949a ¤   ¤   /* False if by a key for which we have secret object */
831e42 ¤   ¤   if (OBJISSEC(sec) && pgpIsRingSetMember(set, sec))
c95f1f ¤   ¤   ¤   return FALSE;
379371 ¤   }
8cd182 ¤   /* Else true, a non-exportable sig by a non-secret key */
88c2e7 ¤   return TRUE;
791862 }¤
66af5a
ddaf5a
8daf5a
c62910 /********************** Trust Model 2 ***************************/
5daf5a
082095 #if PGPTRUSTMODEL==2
8aaf5a
1f2b9d #define LOOKINGAT(key) ((key)->confidence & 1)
8ac9b2 #define SETLOOKINGAT(key) ((key)->confidence |= 1)
dcde8b #define CLEARLOOKINGAT(key) ((key)->confidence &= ~1)
33af5a
4d38e5 /*
a3f7a8 ·* Maximum number of paths we will keep.
43f467 ·* Must calculate trust for each subset.
1a495d ·*/
05987f #define TOTALPATHMAX 10
0eaf5a
eeaf5a
0f38e5 /*
1f6793 ·* The Path and PathList routines use a convention copied from the
4f249e ·* PGPPipeline package for tail pointers. ·The tail pointer points
7ca909 ·* at the "next" pointer of the last packet, or if there are no packets
663a0d ·* it points at the "head" pointer for the whole list. ·This allows a
df7935 ·* uniform interface for adding packets whether they are the first or
03ab06 ·* not.
6e495d ·*/
02af5a
46b2b6 #undef DEBUGPATH
59af5a
423aea #ifdef DEBUGPATH
96af5a
715993 static char const hexchar[16] = {
e618dd ¤   '0','1','2','3','4','5','6','7',
935670 ¤   '8','9','A','B','C','D','E','F'
2782f7 };
06af5a
5cbeb7 static int
f0d17a ringTtyPrintKeyID(FILE *f, RingObject *key)
8bbb36 {
6bd259 ¤   PGPByte *buf;
f14ba4 ¤   int i;
1daf5a
07c2a6 ¤   pgpAssert (OBJISKEY(key));
9201b2 ¤   buf = key->k.keyID;
15527a ¤   for (i = 4; i < 8; i++) {
e246fb ¤   ¤   putc(hexchar[buf[i] >> 4 & 15], f);
b37c9c ¤   ¤   putc(hexchar[buf[i] & 15], f);
109371 ¤   }
c9f8a9 ¤   return 8;
3befe6 }
09af5a
6cbeb7 static int
fb5959 ringTtyPrintKeyName(FILE *f, RingObject *key, RingPool *pool)
61bb36 {
05ae4c ¤   RingSet *set = ringSetCreate(pool);
5388ca ¤   char const *sname;
8a06fb ¤   char bname[256];
9ff20c ¤   size_t len;
3faf5a
--351b 0007bd8ca5b401001f7 Page 7 of pgpRngMnt.c
04a55c ¤   key = key->g.down;
e2cf23 ¤   while (!OBJISNAME(key)) {
2e660d ¤   ¤   key = key->g.next;
459371 ¤   }
713084 ¤   ringSetAddObject (set, key);
8ce0ac ¤   sname = ringNameName (set, key, &len);
fa8465 ¤   strncpy (bname, sname, len);
b2ee34 ¤   bname[len] = '\0';
56798c ¤   fputs (bname, f);
3dd2f5 ¤   ringSetDestroy (set);
633e6b ¤   return 0;
22efe6 }
f6af5a
e9beb7 static int
676bcb ringTtyPrintKey(FILE *f, RingObject *key, RingPool *pool)
8abb36 {
1eaf5a
1f5ab1 ¤   ringTtyPrintKeyID (f, key);
187b07 ¤   fprintf (f, "(");
0550be ¤   ringTtyPrintKeyName (f, key, pool);
a47043 ¤   fprintf (f, ")");
1f3e6b ¤   return 0;
29efe6 }
d9af5a
5f2978 static void
48b8ae ringTtyPrintPath(FILE *f, Path *path, RingPool *pool)
8cbb36 {
e11b08 ¤   fprintf (f, " Path ");
1bb101 ¤   while (path) {
7b4b0d ¤   ¤   fprintf (f, "from ");
79d39c ¤   ¤   ringTtyPrintKey (f, path->src, pool);
b84af3 ¤   ¤   fprintf (f, " to ");
f3971a ¤   ¤   ringTtyPrintKey (f, path->dest, pool);
12967c ¤   ¤   fprintf (f, ", conf: %g\n", path->confidence);
d242fc ¤   ¤   path = path->next;
6ef04c ¤   ¤   if (path)
6f0ea0 ¤   ¤   ¤   fprintf (f, " ·...segment ");
629371 ¤   }
51efe6 }
38af5a
a72978 static void
0c6657 ringTtyPrintPathList(FILE *f, PathList *pl, RingPool *pool)
90bb36 {
d31a00 ¤   fprintf (f, "Begin PathList\n");
520062 ¤   while (pl) {
98563d ¤   ¤   fprintf (f, " (conf=%g) ", pl->confidence);
767304 ¤   ¤   ringTtyPrintPath (f, pl->path, pool);
0d0e6d ¤   ¤   pl = pl->next;
e79371 ¤   }
589624 ¤   fprintf (f, "End PathList\n");
56efe6 }
29af5a
75fb08 #endif /* DEBUGPATH */
65af5a
d2af5a
c1a6ae /* Allocate a Path segment */
cfde73 static Path *
934e54 pathAlloc (RingPool *pool)
98bb36 {
21d3cf ¤   Path ······*path = pool->paths;
d0af5a
65444d ¤   if (path) {
a63e1d ¤   ¤   pool->paths = path->next;
b2f037 ¤   } else {
d7d222 ¤   ¤   path = (Path *) memPoolAlloc (&pool->pathpool, sizeof(Path),
5dbec5 ¤   ¤   ¤   alignof(Path));
7a9371 ¤   }
7af19a ¤   return path;
03efe6 }
f9af5a
a01eb0 /* Free a Path segment */
7b2978 static void
--b6ef 000bd28f6ff401001f7 Page 8 of pgpRngMnt.c
8e6e1e pathFree (Path *path, RingPool *pool)
1fbb36 {
d2fd90 ¤   if (!path)
4799bf ¤   ¤   return;
64bfeb ¤   path->next = pool->paths;
5d7e46 ¤   pool->paths = path;
9befe6 }
4daf5a
fd3e14 /* Free an entire Path */
712978 static void
4b1d93 pathFreeAll (Path *phead, RingPool *pool)
d0bb36 {
f940ba ¤   Path **ptail;
f2af5a
61a868 ¤   if (!phead)
0799bf ¤   ¤   return;
7aded0 ¤   ptail = &phead->next;
126f10 ¤   while (*ptail) {
649d3a ¤   ¤   ptail = &(*ptail)->next;
e09371 ¤   }
1eadf5 ¤   *ptail = pool->paths;
308d5c ¤   pool->paths = phead;
66efe6 }
fdaf5a
0d2bdf /* Allocate a PathList element */
f0e533 static PathList *
a435c7 pathListAlloc (RingPool *pool)
b0bb36 {
53bd10 ¤   PathList ··*plist = pool->pathlists;
c2af5a
f1cb1d ¤   if (plist) {
27b63f ¤   ¤   pool->pathlists = plist->next;
86205d ¤   ¤   plist->next = NULL;
49f037 ¤   } else {
5f84e2 ¤   ¤   plist = (PathList *) memPoolAlloc (&pool->pathpool,
2f8e38 ¤   ¤   ¤   ¤   ¤   sizeof(PathList), alignof(PathList));
bb9371 ¤   }
6089ec ¤   return plist;
f3efe6 }
58af5a
b0b177 #if 0
1f1b24 /* Free a PathList element, also freeing any path it points to */
ee2978 static void
318698 pathListFree (PathList *plist, RingPool *pool)
8abb36 {
503509 ¤   if (plist->path)
24deca ¤   ¤   pathFreeAll (plist->path, pool);
700de6 ¤   plist->path = 0;
1a8cb6 ¤   plist->confidence = 0.;
f05847 ¤   plist->next = pool->pathlists;
406b9c ¤   pool->pathlists = plist;
f3efe6 }
707454 #endif
5faf5a
3abf8b /* Free a whole PathList, also freeing the Paths it points to */
342978 static void
94b0cd pathListFreeAll (PathList *plhead, RingPool *pool)
0cbb36 {
762940 ¤   PathList **pltail = &plhead->next;
cdf51e ¤   while (*pltail)
98429e ¤   ¤   pltail = &(*pltail)->next;
879e25 ¤   *pltail = pool->pathlists;
a4b18f ¤   pool->pathlists = plhead;
b90d4a ¤   while (plhead != *pltail) {
3bf9a0 ¤   ¤   pathFreeAll (plhead->path, pool);
ec8812 ¤   ¤   plhead->path = 0;
b865b4 ¤   ¤   plhead->confidence = 0.;
672394 ¤   ¤   plhead = plhead->next;
589371 ¤   }
bbefe6 }
95af5a
bdaf5a
--8200 0002a05e0e4401001f7 Page 9 of pgpRngMnt.c
737270 /* Add a Path segment to a Path
0b775e ·*
b3869c ·* Returns¤ updated Path tail pointer
6f775e ·*
991243 ·* tail¤¤   tail pointer for Path to be added to
e4bc07 ·* seg¤ ¤   pointer to Path segment to add
48775e ·*
4c495d ·*/
bacdab static Path **
82f50f pathAddSeg (Path **tail, Path *seg)
92bb36 {
1951fb ¤   seg->next = *tail;
4999d7 ¤   *tail = seg;
126ac4 ¤   return &seg->next;
3aefe6 }
c6af5a
5838e5 /*
e138c4 ·* Make a copy of a Path, leaving the original untouched. ·Optionally return a
16c882 ·* pointer to the tail of the new Path.
20775e ·*
68fbbf ·* Returns¤ pointer to new cloned path
07775e ·*
c8371f ·* p1¤  ¤   pointer to the path to be cloned
ca978e ·* ptl¤ ¤   optional return parameter for tail pointer of new path
e37ec5 ·* pool¤¤   ringpool used for allocations of new path segments
f8775e ·*
4d495d ·*/
91de73 static Path *
14826a pathClone (Path *p1, Path ***ptl, RingPool *pool)
53bb36 {
fc4744 ¤   Path ······*phead = NULL,
d55b35 ¤   ··········**ptail = &phead;
48af5a
060974 ¤   while (p1) {
2bb513 ¤   ¤   *ptail = pathAlloc(pool);
1189cc ¤   ¤   if (!*ptail)
20cf03 ¤   ¤   ¤   return NULL;
b70d82 ¤   ¤   **ptail = *p1;
97edc0 ¤   ¤   p1 = p1->next;
bc9d3a ¤   ¤   ptail = &(*ptail)->next;
ed9371 ¤   }
3cec9a ¤   if (ptl)
da691d ¤   ¤   *ptl = ptail;
cc9132 ¤   return phead;
b8efe6 }
7faf5a
ddaf5a
5af1ad /* Add a copy of a Path to the PathList
22775e ·*
0542c0 ·* Returns¤ tail pointer of updated PathList
90775e ·*
3e30fb ·* tail¤¤   tail pointer of PathList to be added to
670b9f ·* path¤¤   pointer to Path to add to the PathList
10f96d ·* pool¤¤   ringpool to use for memory allocations
ee775e ·*
28495d ·*/
ea8f94 static PathList **
ec0956 pathListAddPathClone (PathList **tail, Path *path, RingPool *pool)
93bb36 {
acc6d1 ¤   PathList ··*pl;
0aaf5a
2e19e5 ¤   pl = pathListAlloc(pool);
07e050 ¤   if (!pl)
0a7ed2 ¤   ¤   return NULL;
5475f9 ¤   if (path)
b9e917 ¤   ¤   pl->path = pathClone (path, &pl->ptail, pool);
53665a ¤   else {
3a1476 ¤   ¤   pl->path = NULL;
4b5207 ¤   ¤   pl->ptail = &pl->path;
859371 ¤   }
32d4c2 ¤   pl->next = *tail;
2ad5c9 ¤   *tail = pl;
--1066 000a4f6f233401001f7 Page 10 of pgpRngMnt.c
589d8c ¤   return &pl->next;
69efe6 }
e2af5a
82af5a
fac25b /* Calculate the confidence associated with a path. */
96ef7c static double
522dff pathConfidence (Path *path)
0fbb36 {
c9da97 ¤   double ····conf = 1.0;
19af5a
b6b101 ¤   while (path) {
b1581d ¤   ¤   conf *= path->confidence;
4c42fc ¤   ¤   path = path->next;
a29371 ¤   }
36d1fb ¤   return conf;
b3efe6 }
7caf5a
c738e5 /*
575906 ·* Prune the PathList to keep only the highest-confidence pathmax Paths.
18af49 ·* Return the new PathList, free the no longer used Paths.
3b775e ·*
b1c281 ·* Returns¤ new PathList with no more than pathmax paths
77775e ·*
ac1d21 ·* plist¤   PathList to be pruned
b0e6bf ·* pathmax¤ maximum number of paths to allow
2ef96d ·* pool¤¤   ringpool to use for memory allocations
7c775e ·*
79495d ·*/
8de533 static PathList *
3f55cb pathListPrune (PathList *plist, unsigned pathmax, RingPool *pool)
f2bb36 {
093221 ¤   PathList ··*iplist;¤¤   ¤   /* Copy of plist */
8a2627 ¤   PathList ·**pl1,¤   ¤   ¤   /* Iterator over plist */
bd56da ¤   ··········**maxpl1;¤¤   ¤   /* Max confidence pl1 pointer */
99d5c2 ¤   PathList ··*nplist,¤¤   ¤   /* New pathlist head */
545edc ¤   ··········**nptail;¤¤   ¤   /* New pathlist tail */
8523cd ¤   unsigned ···npaths,¤¤   ¤   /* Number of paths in plist initially */
93fb42 ¤   ············newnpaths;¤ ¤   /* Number of paths in final nplist */
434cd8 ¤   double ·····maxconf;¤   ¤   /* Best confidence value so far */
ecaf5a
c1190b ¤   /* Calculate confidence value for each path */
c423e9 ¤   iplist = plist;
66abbe ¤   npaths = 0;
1a4380 ¤   while (plist) {
ea3f50 ¤   ¤   npaths += 1;
b254b2 ¤   ¤   plist->confidence = pathConfidence (plist->path);
3dbbaf ¤   ¤   plist = plist->next;
009371 ¤   }
450ad2 ¤   plist = iplist;
acaf5a
fc5d8a ¤   /* Initialize the new path list */
dc91aa ¤   nplist = plist;
5be2c0 ¤   if (npaths > pathmax) {
418328 ¤   ¤   nplist = NULL;
a6685a ¤   ¤   nptail = &nplist;
65c32b ¤   ¤   newnpaths = pgpMin (pathmax, npaths);
89dc04 ¤   ¤   while (newnpaths--) {
efa646 ¤   ¤   ¤   /* Add the best path from plist to nplist */
1a1db5 ¤   ¤   ¤   pl1 = &plist;
849a4c ¤   ¤   ¤   maxconf = 0.;
9282b7 ¤   ¤   ¤   maxpl1 = pl1;
741da1 ¤   ¤   ¤   while (*pl1) {
9c7b5f ¤   ¤   ¤   ¤   /* Find best path in plist in **maxpl1 */
031746 ¤   ¤   ¤   ¤   if ((*pl1)->confidence > maxconf) {
611330 ¤   ¤   ¤   ¤   ¤   maxconf = (*pl1)->confidence;
ed3ceb ¤   ¤   ¤   ¤   ¤   maxpl1 = pl1;
832613 ¤   ¤   ¤   ¤   }
e85244 ¤   ¤   ¤   ¤   pl1 = &(*pl1)->next;
c4a3a6 ¤   ¤   ¤   }
4a2d80 ¤   ¤   ¤   *nptail = *maxpl1;
282a0f ¤   ¤   ¤   *maxpl1 = (*maxpl1)->next;
a42b54 ¤   ¤   ¤   nptail = &(*nptail)->next;
--799e 000eb439fc4401001f7 Page 11 of pgpRngMnt.c
a9ee96 ¤   ¤   ¤   *nptail = NULL;
140fe4 ¤   ¤   }
4aaf5a
25ac5a ¤   ¤   if (plist)
656c39 ¤   ¤   ¤   pathListFreeAll (plist, pool);
849371 ¤   }
38b512 ¤   return nplist;
98efe6 }
48af5a
94af5a
5638e5 /*
e4b447 ·* Append a (copy of a) second path to the first, removing common segments.
4e9abe ·* Return pointer to "next" pointer of last segment (and pass that as ptail)
24775e ·*
dc69a5 ·* Return¤  tail pointer for updated Path
fa775e ·*
7e52b9 ·* phead¤   pointer to Path which gets appended to
eb2b84 ·* ptail¤   tail pointer for Path which gets appended to
a50a7c ·* p2¤  ¤   pointer to Path to append (a copy of)
71f96d ·* pool¤¤   ringpool to use for memory allocations
8d775e ·*
77495d ·*/
f4cdab static Path **
4076fb pathUnion (Path *phead, Path **ptail, Path *p2, RingPool *pool)
54bb36 {
5a15b7 ¤   Path ······*p1;
fb191b ¤   Path ·····**iptail = ptail;
6daf5a
7032f1 ¤   /* Add path p2 but skip those segments in p1 */
4fb3d4 ¤   for ( ; p2; p2 = p2->next) {
c413ce ¤   ¤   p1 = phead;
d758b8 ¤   ¤   for (p1=phead; p1 && p1 != *iptail; p1 = p1->next) {
66bf46 ¤   ¤   ¤   /* Eliminate path segments which are in there already */
ecf453 ¤   ¤   ¤   if (p2->src == p1->src && p2->dest == p1->dest) {
237673 ¤   ¤   ¤   ¤   /* Make sure our confidence rules are working */
2f90cf ¤   ¤   ¤   ¤   pgpAssert (p2->confidence == p1->confidence);
10f622 ¤   ¤   ¤   ¤   break;
fea3a6 ¤   ¤   ¤   }
eb0fe4 ¤   ¤   }
b7c539 ¤   ¤   if (p1 && p1 != *iptail)
5b17f5 ¤   ¤   ¤   continue;
f8b513 ¤   ¤   *ptail = pathAlloc(pool);
7e89cc ¤   ¤   if (!*ptail)
5acf03 ¤   ¤   ¤   return NULL;
c5e2e6 ¤   ¤   **ptail = *p2;
459d3a ¤   ¤   ptail = &(*ptail)->next;
5c90c1 ¤   ¤   *ptail = NULL;
d69371 ¤   }
31ec7c ¤   return ptail;
daefe6 }
04af5a
3a38e5 /*
881c7a ·* Calculate the confidence for a list of paths. ·We add the confidence for
92c95a ·* each path, subtrace the confidence for the unions of all pairs of paths,
561eaf ·* add the confidence for the unions for all the triples, and so on.
c2c1df ·* We actually do this by taking each subset of the paths, unioning them,
114183 ·* calculating the confidence for that path, and adding or subtracting it
25f593 ·* based on the parity.
70495d ·*/
abef7c static double
d0dc99 pathListConfidence (PathList *plist, RingPool *pool)
ffbb36 {
17f557 ····unsigned ·······pathcount,
07f8c0 ····················mask,
611533 ¤   ················tmask;
8fe49c ····PathList ······*iplist = plist;
895549 ····double ·········conf = 0.;
cbaf5a
7f3aea #ifdef DEBUGPATH
d5ff93 ¤   fprintf (stdout, "Maurer alg:\n");
4d7454 #endif
ebaf5a
--5e04 00008830447401001f7 Page 12 of pgpRngMnt.c
fabb19 ¤   pathcount = 0;
c84380 ¤   while (plist) {
49c819 ¤   ¤   ++pathcount;
d0bbaf ¤   ¤   plist = plist->next;
599371 ¤   }
980ad2 ¤   plist = iplist;
5caf5a
b54da0 ¤   pgpAssert (pathcount < sizeof(unsigned) * 8);
e3353f ¤   for (mask=1; mask < (1U<<pathcount); ++mask) {
198ffc ¤   ¤   double pathconf;
5d8dc0 ¤   ¤   Path *phead=NULL, **ptail=&phead;
a7e92e ¤   ¤   int oddparity = 0;
457026 ¤   ¤   plist = iplist;
0c5826 ¤   ¤   tmask = mask;
6e4bed ¤   ¤   while (plist && tmask) {
e26ce3 ¤   ¤   ¤   if (tmask & 1) {
c33944 ¤   ¤   ¤   ¤   ptail = pathUnion (phead, ptail, plist->path, pool);
a4a292 ¤   ¤   ¤   ¤   oddparity = !oddparity;
11a3a6 ¤   ¤   ¤   }
7e00f9 ¤   ¤   ¤   plist = plist->next;
e9ae00 ¤   ¤   ¤   tmask >>= 1;
130fe4 ¤   ¤   }
6f587e ¤   ¤   pathconf = pathConfidence (phead);
c13aea #ifdef DEBUGPATH
db5112 ¤   ¤   fprintf (stdout, "%sing %g: ", oddparity?" add":" subb",pathconf);
b3eed7 ¤   ¤   ringTtyPrintPath (stdout, phead, pool);
9c7454 #endif
13dba1 ¤   ¤   if (oddparity)
ece4fb ¤   ¤   ¤   conf += pathconf;
5d0e1d ¤   ¤   else
c01cea ·¤  ¤   ¤   conf -= pathconf;
1c5d26 ¤   ¤   pathFreeAll (phead, pool);
f1cba2 ¤   ¤   phead = NULL;
d5c398 ¤   ¤   ptail = &phead;
c49371 ¤   }
313aea #ifdef DEBUGPATH
051e27 ¤   fprintf (stdout, "Net of %g\n", conf);
6a7454 #endif
71d1fb ¤   return conf;
48efe6 }
71af5a
3d38e5 /*
1ef52a ·* Find the confidence level to use for the given key.
71e571 ·* This is difficult in this trust model because we generally don't
3bb3cd ·* have validity on the names associated with the key, since there is
b032b1 ·* no well defined (nor arbitrarily imposed) ordering of the graph.
403ead ·* The result is that when we do our calculation we may end up with a
577d89 ·* de facto validity on a key/name that has no relation to the (cached)
e7d43f ·* validity stored on the key.
e8775e ·*
a02abb ·* So we have a set of heuristics to choose the confidence associated
0dddc8 ·* with some name, to wit:
49775e ·*
600491 ·* If all the names have at least some validity, we choose the confidence
f93c29 ·* associated with the most valid name. ·Otherwise we just choose the
9b5ad4 ·* lowest confidence of all the names. ·The reason for the second case is so
887d26 ·* that if we have a true name and a false name, but the true name doesn't
abc8a5 ·* have validity yet, while the false name has a little tiny bit of validity,
430ee6 ·* we don't want to choose the confidence of the false name, which might be
c342a6 ·* very high. ·It might be that the next step in the path will give high
b944c3 ·* validity to the true (but low confidence) name. ·We would end up counting
03c88b ·* this key as both high confidence and high validity, which may be wrong.
92775e ·*
ab5be0 ·* This heuristic might seem to have the problem that if you get a new name
64107a ·* for a trusted
6c5a93 ·* key its trust will go away until either the new name gets some validity
bd1d8c ·* or you set the confidence level on the new name. ·But this does not
db7ebb ·* happen because such names are not included in the confident set.
3c775e ·*
ad659e ·* A worse problem is that Snidely could get Nell's name on his key, get
05d2b7 ·* some low-confidence signer to sign Nell, and get an even lower conf-
08aed1 ·* idence signer to sign his own. ·Then we would use Nell's confidence
--a90a 00020fdb7ee401001f7 Page 13 of pgpRngMnt.c
29e6d5 ·* on Snidely's key, and if there were also a good signer on Snidely's name,
371fdc ·* which we hadn't run into yet, we would again count Snidely's signatures
bba52c ·* too highly.
b6775e ·*
be373e ·* So this suggests a safer heuristic which is to take either the lowest
f7d063 ·* confidence, or else perhaps to downgrade the confidence by the
0a2904 ·* validities. ·However doing this if all the validities are accurate will
0ff3d3 ·* end up squaring them. ·Maybe we could just downgrade by the relative
7a863f ·* validities, best to worst...
aa775e ·*
612f81 ·* (For now we have an #if below to always use the lowest confidence)
21775e ·*
a98f90 ·* An idea suggested by Mark is to base the confidence on the particular
3c811c ·* name which is the next step in the path. ·However this complicates the
7a8cbb ·* union operation.
59232b ·* Either a path no longer has a well defined confidence, preventing
a4ed73 ·* Maurer's algorithm from working, or else we have
3704a6 ·* to define a path as being from name to name, and if a key has two
d69c9e ·* names (different email addresses, say, home and work) we would end up
da5ec6 ·* counting its contribution to trust twice. ·(This is essentially because
33a6af ·* the assumption of independence fails spectacularly in this case!)
34775e ·*
f35eea ·* Keep in mind that despite all these difficulties, if there is only one
3e8053 ·* name then there is no problem! ·We just use the confidence on that name.
d9495d ·*/
86ef7c static double
93478b pathKeyConfidence (RingObject *key, RingSet const *set)
3ebb36 {
845654 ¤   RingObject ····*name;
965d57 ¤   double ·········minconfidence = 1.0,
c3c7ae ¤   ················confidence,
acb450 ¤   ················errorchance,
d610cc ¤   ¤   ¤   ¤   ¤   nameconfidence,
4770ad ¤   ¤   ¤   ¤   ¤   keyconfidence,
080c78 ¤   ················maxvalidconfidence = 0.;
d772f3 ¤   PGPUInt16 ······maxvalidity = 0;
92673e ¤   PGPBoolean¤ ¤   allvalid = TRUE;¤   /* True if all names have validity */
3ad347 ¤   PGPBoolean¤ ¤   validname = FALSE;¤ /* True if at least one valid name */
f8af5a
25673b ¤   for (name = key->g.down; name; name = name->g.next) {
de7cdb ¤   ¤   if (!OBJISNAME(name) || !pgpIsRingSetMember(set, name))
2117f5 ¤   ¤   ¤   continue;
e7aa23 ¤   ¤   if (name->n.confidence == PGP_NEWTRUST_UNDEFINED)
df17f5 ¤   ¤   ¤   continue;
1f1c12 ¤   ¤   validname = TRUE;
fceb89 ¤   ¤   errorchance = ·ringTrustToDouble (
f7b994 ¤   ¤   ····················ringTrustToIntern(name->n.confidence));
9b752b ¤   ¤   confidence = 1. - 1. / errorchance;
d38756 ¤   ¤   if (confidence < minconfidence)
35506a ¤   ¤   ¤   minconfidence = confidence;
bba85f ¤   ¤   if (!name->n.valid) {
8a387f ¤   ¤   ¤   allvalid = 0;
28deeb ¤   ¤   } else if (name->n.valid > maxvalidity ||
fc507a ¤   ¤   ¤   ¤   ¤   ¤   (name->n.valid == maxvalidity &&
f582d7 ¤   ¤   ¤   ¤   ¤   ¤   ·confidence < maxvalidconfidence)) {
f465fc ¤   ¤   ¤   maxvalidity = name->n.valid;
6a53d3 ¤   ¤   ¤   maxvalidconfidence = confidence;
040fe4 ¤   ¤   }
7b9371 ¤   }
011105 ¤   /* If called with no valid name, minconfidence is 0 */
5a976e ¤   if (!validname)
26bf4e ¤   ¤   minconfidence = 0.;
ccd8af ¤   /*
0efb59 ¤   ·* If all names have known validity, use the most valid name's confidence.
2851f3 ¤   ·* Else choose the lowest established confidence of any name.
1ba4e3 ¤   ·*/
ffb177 #if 0
0a8656 /* Too risky to use this heuristic, just take minimum confidence */
2165de ¤   if (allvalid)
fcd676 ¤   ¤   nameconfidence = maxvalidconfidence;
e20e24 ¤   else
207454 #endif
--9b17 0007814efd4401001f7 Page 14 of pgpRngMnt.c
4ca5a1 ¤   ¤   nameconfidence = minconfidence;
b5af5a
2171ef ¤   keyconfidence = 0.;
00b49d ¤   if (key->k.signedTrust != 0) {
9beb89 ¤   ¤   errorchance = ·ringTrustToDouble (
3b154e ¤   ¤   ····················ringTrustToIntern(key->k.signedTrust));
81ab72 ¤   ¤   keyconfidence = 1. - 1. / errorchance;
d19371 ¤   }
8baf5a
1175f6 ¤   return pgpMax (keyconfidence, nameconfidence);
40efe6 }
1aaf5a
8e85c2 /* Prototype */
328f94 static PathList **
400cc2 ringFindPathsKey (RingObject *start, PathList **ppath,
13c726 ¤   Path **predh, Path **predt, unsigned depth,
53a32c ····unsigned maxdepth, RingSet const *confset, RingSet const *allset,
847128 ¤   PGPUInt32 timenow, RingPool *pool);
1daf5a
54e270 /* Helper routines for ringFindPathsName */
99af5a
235041 /* Return the newest valid signature by the given key on the given name */
b2832c static RingObject *
f550d0 ringNewestValidSig (RingObject *name, RingObject *key,
ee4424 ¤   RingSet const *set, PGPUInt32 timenow)
80bb36 {
de6cfa ¤   RingObject¤ ¤   *bestsig = NULL,
99f883 ¤   ¤   ¤   ¤   ¤   *sig;
84af5a
de9c88 ¤   pgpAssert (OBJISNAME(name));
d3c2a6 ¤   pgpAssert (OBJISKEY(key));
2faf5a
0a8b2a ¤   for (sig = name->g.down; sig; sig = sig->g.next) {
84f825 ¤   ¤   if (OBJISSIG(sig)
d07de1 ¤   ¤   ¤   && (sig->s.trust & PGP_SIGTRUSTF_CHECKED)
e3d1e3 ¤   ¤   ¤   && pgpIsRingSetMember(set, sig)
98957a ¤   ¤   ¤   && sig->s.by == key
e5d07d ¤   ¤   ¤   && mntSigOKWithRegexp( set, &sig->s )
03fbd8 ¤   ¤   ¤   && mntSigIsValid(timenow, sig->s.tstamp, sig->s.validity)) {
672fb6 ¤   ¤   ¤   /* Good sig by key, see if it is newer than bestsig */
0e413b ¤   ¤   ¤   if (!bestsig
a079f3 ¤   ¤   ¤   ¤   || bestsig->s.tstamp < sig->s.tstamp) {
a2dba3 ¤   ¤   ¤   ¤   bestsig = sig;
61a3a6 ¤   ¤   ¤   }
330fe4 ¤   ¤   }
3a9371 ¤   }
f00a0c ¤   return bestsig;
07efe6 }
bcaf5a
f038e5 /*
7e7899 ·* Return true if there is a signature by the key on an earlier sibling
90bb68 ·* of this name. ·This alerts us to a condition which could cause duplicate
a4d830 ·* paths, which will waste resources.
21495d ·*/
fbbeb7 static int
8902a0 ringEarlierValidSig (RingObject *name, RingObject *key, RingSet const *set,
9904c0 ¤   PGPUInt32 timenow)
2bbb36 {
209a87 ¤   RingObject¤ ¤   *parent,
160b1d ¤   ¤   ¤   ¤   ¤   *sibname,
18f883 ¤   ¤   ¤   ¤   ¤   *sig;
43af5a
c39c88 ¤   pgpAssert (OBJISNAME(name));
b9c2a6 ¤   pgpAssert (OBJISKEY(key));
bfaf5a
6ecda7 ¤   parent = name->g.up;
c67c26 ¤   pgpAssert (OBJISKEY(parent));
b5af5a
5f19e2 ¤   for (sibname=parent->g.down; sibname!=name; sibname=sibname->g.next) {
fa7225 ¤   ¤   if (!OBJISNAME(sibname)
f851e2 ¤   ¤   ¤   || !pgpIsRingSetMember(set, sibname))
7817f5 ¤   ¤   ¤   continue;
--5a2b 000fe8e0ab1401001f7 Page 15 of pgpRngMnt.c
747f56 ¤   ¤   for (sig=sibname->g.down; sig; sig=sig->g.next) {
487171 ¤   ¤   ¤   if (OBJISSIG(sig)
a57de1 ¤   ¤   ¤   && (sig->s.trust & PGP_SIGTRUSTF_CHECKED)
57d1e3 ¤   ¤   ¤   && pgpIsRingSetMember(set, sig)
a2957a ¤   ¤   ¤   && sig->s.by == key
08d07d ¤   ¤   ¤   && mntSigOKWithRegexp( set, &sig->s )
d0fbd8 ¤   ¤   ¤   && mntSigIsValid(timenow, sig->s.tstamp, sig->s.validity)) {
df5269 ¤   ¤   ¤   ¤   /* Have an earlier signature we are looking for */
c606e0 ¤   ¤   ¤   ¤   return TRUE;
f3a3a6 ¤   ¤   ¤   }
d10fe4 ¤   ¤   }
9b9371 ¤   }
f6a230 ¤   return FALSE;
d7efe6 }
0eaf5a
0d38e5 /*
a59c40 ·* See if the specified key is in the special "pairing" relationship with
cc68e2 ·* the specified name. ·We are called with key signing name. ·The main point
5ee88a ·* is whether key has a name which matches. ·If so, we return that name.
39e238 ·* It is also necessary that name be self-signed, so we will check for that
d37606 ·* here. ·The signing key must be valid as well.
be495d ·*/
85832c static RingObject *
8af267 ringPairedName (RingObject *name, RingObject *key, RingSet const *set)
e8bb36 {
0e92cf ¤   RingObject¤ ¤   ¤   *keyname;¤  /* Names on key */
8f964c ¤   RingObject¤ ¤   ¤   *namekey;¤  /* Key parent of name */
68900b ¤   RingObject¤ ¤   ¤   *namesig;¤  /* Sigs on name */
a27fc6 ¤   PGPByte const¤  ¤   *smatchname; /* Actual name of *name */
fb2908 ¤   PGPByte const¤  ¤   *sname;¤¤   /* Actual name of *keyname */
a15252 ¤   PGPSize¤¤   ¤   ·¤  lmatchname; /* Length of smatchname */
3fd6b5 ¤   PGPSize¤¤   ¤   ¤   lname;¤ ¤   /* Length of sname */
4967c5 ¤
00c2a6 ¤   pgpAssert (OBJISKEY(key));
d59c88 ¤   pgpAssert (OBJISNAME(name));
65af5a
546abb ¤   /* Check for key validity */
b1575e ¤   if (key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
c07ed2 ¤   ¤   return NULL;
5f67c5 ¤
e2d561 ¤   /* Check that name is self-signed */
d14dc9 ¤   namekey = name->n.up;
8fe63b ¤   pgpAssert (OBJISKEY(namekey));
9c57c3 ¤   for (namesig = name->n.down; namesig; namesig = namesig->g.next) {
6f2529 ¤   ¤   if (!OBJISSIG(namesig))
7e17f5 ¤   ¤   ¤   continue;
eab698 ¤   ¤   /* XXX Should check expiration */
095e12 ¤   ¤   if ((namesig->s.trust & PGP_SIGTRUSTF_CHECKED)
beb735 ¤   ¤   ¤   && pgpIsRingSetMember(set, namesig)
e5ea1a ¤   ¤   ¤   && (namesig->s.type & 0xF0) == PGP_SIGTYPE_KEY_GENERIC) {
a64cc3 ¤   ¤   ¤   break;¤ ¤   ¤   ¤   /* Exit with namesig nonnull on success */
9c0fe4 ¤   ¤   }
909371 ¤   }
9a88bb ¤   if (!namesig)¤  ¤   ¤   ¤   /* NULL namesig means no self sig */
847ed2 ¤   ¤   return NULL;
ab1b52 ¤   ¤
2d1ba1 ¤   /* Get userid string of name */
d388cf ¤   smatchname = (PGPByte const *)ringFetchObject(set, name, &lmatchname);
8caf5a
e8f33c ¤   /* See if any names on keyname match */
733fb8 ¤   for (keyname = key->k.down; keyname; keyname = keyname->n.next) {
77d79c ¤   ¤   if (!OBJISNAME(keyname))
4717f5 ¤   ¤   ¤   continue;
6997fb ¤   ¤   sname = (PGPByte const *)ringFetchObject(set, name, &lname);
b8e3e6 ¤   ¤   if (lname == lmatchname && !memcmp (sname, smatchname, lname)) {
c1b9f7 ¤   ¤   ¤   /* Have a matching name! */
fb53df ¤   ¤   ¤   return keyname;
e30fe4 ¤   ¤   }
959371 ¤   }
193f59 ¤   return NULL;
5aefe6 }
feaf5a
--9783 00040404d55401001f7 Page 16 of pgpRngMnt.c
e0af5a
d338e5 /*
470403 ·* Find all the paths from the starting name back to an axiomatically
2b6ac9 ·* trusted key.
40486c ·* pred holds the path which leads to the starting key from some target.
1280d5 ·* lastseg points at the last segment of the path, which already has
9320b2 ·* the key this name is on as the dest. ·We just have to fill it in
eb9b8c ·* and recurse, or check for buckstop keys.
9d775e ·*
049829 ·* We reject paths which are to keys which have
61969a ·* already been processed as signing this key. ·This can happen
de449a ·* if there are two names on a key, both signed by another key. ·Otherwise
a301e8 ·* these would be treated as two different paths, but they
b32211 ·* end up being identical. ·The Maurer algorithm correctly accounts for this,
7cd4c4 ·* but it is a waste. ·What we do is, for each signature, we check
d821c2 ·* all our earlier name siblings and see if they have a signature from the
7aef27 ·* same key. ·If so we skip this sig.
49775e ·*
ad4619 ·* Returns¤ tail pointer for updated PathList
1f775e ·*
338cde ·* name¤¤   starting name object for search backwards through web of trust
85cd59 ·* ppath¤   tail pointer of PathList to add our new paths to
bc84bb ·* predh¤   pointer to the (head of the) Path we will add to
e25f70 ·* predt¤   tail pointer to the Path we will add to (&newseg->tail)
d0074f ·* depth¤   length of path so far, counting newseg (e.g. 1 at outer level)
cf78f5 ·* maxdepth¤maximum length of paths we allow
d6d0e3 ·* confset¤ ringset for trusted keys
e623fa ·* allset¤  ringset for all keys
4d3528 ·* timenow¤ current timestamp
9ef96d ·* pool¤¤   ringpool to use for memory allocations
5fd405 ·* skipsigs list of signatures, chained by next, not to follow key of
07775e ·*
15495d ·*/
2b8f94 static PathList **
ae60f1 ringFindPathsName (RingObject *name, PathList **ppath,
3bc726 ¤   Path **predh, Path **predt, unsigned depth,
30a32c ····unsigned maxdepth, RingSet const *confset, RingSet const *allset,
a91e71 ¤   PGPUInt32 timenow, RingPool *pool, RingObject *skipsigs)
adbb36 {
cb1efc ¤   RingObject ····*sig,
8ef54b ¤   ···············*sigkey,
e3b288 ¤   ¤   ¤   ¤   ···*pairedname,
dc0cc8 ¤   ¤   ¤   ¤   ···*ssig;
e9a9a7 ¤   Path¤   ¤   ···*newseg;
5d8078 ¤   Path ·········**newpredt;
6b9293 ¤   double¤ ¤   ¤   confidence;
1eaf5a
048b2a ¤   for (sig = name->g.down; sig; sig = sig->g.next) {
8401e1 ¤   ¤   if (!OBJISSIG(sig))
ff17f5 ¤   ¤   ¤   continue;
338d3d ¤   ¤   /* Skip if invalid sig */
599a93 ¤   ¤   if (!(sig->s.trust & PGP_SIGTRUSTF_CHECKED)
16084f ¤   ¤   ¤   || !pgpIsRingSetMember((depth>1?confset:allset), sig)
df1935 ¤   ¤   ¤   || !mntSigIsValid(timenow, sig->s.tstamp, sig->s.validity)
b3f152 ¤   ¤   ¤   || !mntSigOKWithRegexp( allset, &sig->s )
6e9e12 ¤   ¤   ¤   || (sig->s.type & 0xF0) != PGP_SIGTYPE_KEY_GENERIC)
6a17f5 ¤   ¤   ¤   continue;
18d58a ¤   ¤   /* Skip if signing key not in signer set */
3a271e ¤   ¤   sigkey = sig->s.by;
dc8161 ¤   ¤   if (!pgpIsRingSetMember(confset, sigkey))
9617f5 ¤   ¤   ¤   continue;
fbbaba ¤   ¤   /* Skip if there is a newer valid sig by the same key */
739fa3 ¤   ¤   if (ringNewestValidSig (name, sigkey, (depth>1?confset:allset),
41e462 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   timenow) != sig)
2d17f5 ¤   ¤   ¤   continue;
ed07ea ¤   ¤   /* Skip if we have already done this key on an earlier sibling */
990926 ¤   ¤   if (depth>1 && ringEarlierValidSig (name, sigkey, confset, timenow))
3917f5 ¤   ¤   ¤   continue;
1c1b17 ¤   ¤   /*
65db8b ¤   ¤   ·* Skip if signing key is in skipsigs list. ·This is for the "paired
459cac ¤   ¤   ·* keys" feature.
409de3 ¤   ¤   ·*/
--cad1 000a37d7634401001f7 Page 17 of pgpRngMnt.c
11dd03 ¤   ¤   for (ssig = skipsigs; ssig; ssig = ssig->g.next) {
24c62f ¤   ¤   ¤   if (OBJISSIG(ssig) && sigkey == ssig->s.by)
059d5d ¤   ¤   ¤   ¤   break;¤ ¤   ¤   /* Exit from loop with ssig nonnull on match */
590fe4 ¤   ¤   }
a30d1c ¤   ¤   if (ssig)¤  ¤   ¤   ¤   /* Non-null ssig means it was on skip list */
b317f5 ¤   ¤   ¤   continue;
b1af5a
2a4c0e ¤   ¤   /* OK, investigate this signer further */
7e3f74 ¤   ¤   if (sigkey->k.trust & PGP_KEYTRUSTF_BUCKSTOP
5c319a ¤   ¤   ¤   && !(sigkey->k.trust & (PGP_KEYTRUSTF_REVOKED |
e42763 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGP_KEYTRUSTF_EXPIRED))
e2dd16 ¤   ¤   ¤   /*&& !(key->k.trust & PGP_KEYTRUSTF_DISABLED)*/) {
8bcb5b ¤   ¤   ¤   /* Found a path */
8e3db9 ¤   ¤   ¤   ppath = pathListAddPathClone (ppath, *predh, pool);
458c3a ¤   ¤   ¤   if (!ppath) {
9b9ab0 ¤   ¤   ¤   ¤   /* Out of memory */
0efb5e ¤   ¤   ¤   ¤   return NULL;
c2a3a6 ¤   ¤   ¤   }
5c3a8f ¤   ¤   } else if (depth < maxdepth &&
026b2f ¤   ¤   ¤   ¤   ···!LOOKINGAT(&sigkey->k) &&
3aa756 ¤   ¤   ¤   ¤   ···(confidence = pathKeyConfidence(sigkey, confset)) != 0) {
67cc6e ¤   ¤   ¤   /* Recurse */
39f55f ¤   ¤   ¤   newseg = pathAlloc(pool);
3d4184 ¤   ¤   ¤   if (!newseg) {
db9ab0 ¤   ¤   ¤   ¤   /* Out of memory */
28fb5e ¤   ¤   ¤   ¤   return NULL;
14a3a6 ¤   ¤   ¤   }
f58f18 ¤   ¤   ¤   newseg->dest = name->g.up;
6efa97 ¤   ¤   ¤   newseg->src = sigkey;
8b030e ¤   ¤   ¤   newseg->next = NULL;
d69906 ¤   ¤   ¤   newseg->confidence = confidence;
10dd71 ¤   ¤   ¤   newpredt = pathAddSeg (predt, newseg);
96a4bc ¤   ¤   ¤   ppath = ringFindPathsKey (sigkey, ppath, predh, newpredt,
18a355 ¤   ¤   ¤   ¤   ¤   ·depth+1, maxdepth, confset, allset, timenow, pool);
dd1950 ¤   ¤   ¤   pathFree (newseg, pool);
b166ad ¤   ¤   ¤   *predt = NULL;
f88c3a ¤   ¤   ¤   if (!ppath) {
4a9ab0 ¤   ¤   ¤   ¤   /* Out of memory */
a5fb5e ¤   ¤   ¤   ¤   return NULL;
daa3a6 ¤   ¤   ¤   }
893a8f ¤   ¤   } else if (depth < maxdepth &&
7e6b2f ¤   ¤   ¤   ¤   ···!LOOKINGAT(&sigkey->k) &&
3c0475 ¤   ¤   ¤   ¤   ···(pairedname =
94b412 ¤   ¤   ¤   ¤   ¤   ¤   ringPairedName(name, sigkey, confset)) != NULL) {
167aad ¤   ¤   ¤   /*
f9fb9a ¤   ¤   ¤   ·* We have a signature by a sibling key, one which matches our
bccbc0 ¤   ¤   ¤   ·* name. ·Recurse from that name. ·The resulting path element
126a8a ¤   ¤   ¤   ·* will have as source, signer of that paired name, and as
c1e03c ¤   ¤   ¤   ·* destination, this key. ·Even though there is no "actual"
77559d ¤   ¤   ¤   ·* signature in such a form, there is an implied signature.
1fa02f ¤   ¤   ¤   ·* We won't increment depth in this case.
90ef58 ¤   ¤   ¤   ·* Here we use the skipsigs feature - we don't want to follow
35058b ¤   ¤   ¤   ·* any sigs from our pair which we are also following here.
005700 ¤   ¤   ¤   ·* This is the only place it is used (at this writing!).
f88753 ¤   ¤   ¤   ·*/
fff55f ¤   ¤   ¤   newseg = pathAlloc(pool);
a74184 ¤   ¤   ¤   if (!newseg) {
2b9ab0 ¤   ¤   ¤   ¤   /* Out of memory */
7cfb5e ¤   ¤   ¤   ¤   return NULL;
b7a3a6 ¤   ¤   ¤   }
9d8f18 ¤   ¤   ¤   newseg->dest = name->g.up;
80fa97 ¤   ¤   ¤   newseg->src = sigkey;
b1030e ¤   ¤   ¤   newseg->next = NULL;
778b95 ¤   ¤   ¤   newseg->confidence = 1.0;
63dd71 ¤   ¤   ¤   newpredt = pathAddSeg (predt, newseg);
0b25d2 ¤   ¤   ¤   ppath = ringFindPathsName (pairedname, ppath, predh, newpredt,
70e6a2 ¤   ¤   ¤   ¤   depth, maxdepth, confset, allset, timenow, pool, name->g.down);
021950 ¤   ¤   ¤   pathFree (newseg, pool);
be66ad ¤   ¤   ¤   *predt = NULL;
7e8c3a ¤   ¤   ¤   if (!ppath) {
cb9ab0 ¤   ¤   ¤   ¤   /* Out of memory */
a3fb5e ¤   ¤   ¤   ¤   return NULL;
--50b2 000a11f188d401001f7 Page 18 of pgpRngMnt.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
959371 ¤   }
fad79f ¤   return ppath;
75efe6 }
1aaf5a
b4af5a
9338e5 /*
7d454a ·* Find all the paths from the starting key back to an axiomatically
536ac9 ·* trusted key.
2c775e ·*
a64619 ·* Returns¤ tail pointer for updated PathList
76775e ·*
26c8fd ·* start¤   starting key object for search backwards through web of trust
38cd59 ·* ppath¤   tail pointer of PathList to add our new paths to
da84bb ·* predh¤   pointer to the (head of the) Path we will add to
9763c2 ·* predt¤   tail pointer to the Path we will add to
edcbe3 ·* depth¤   length of path, counting segment added in ringFindPathsName
5678f5 ·* maxdepth¤maximum length of paths we allow
77d0e3 ·* confset¤ ringset for trusted keys
6223fa ·* allset¤  ringset for all keys
223528 ·* timenow¤ current timestamp
96f96d ·* pool¤¤   ringpool to use for memory allocations
f4775e ·*
44495d ·*/
878f94 static PathList **
730cc2 ringFindPathsKey (RingObject *start, PathList **ppath,
93c726 ¤   Path **predh, Path **predt, unsigned depth,
cea32c ····unsigned maxdepth, RingSet const *confset, RingSet const *allset,
779f52 ¤   PGPUInt32 timenow, RingPool *pool)
68bb36 {
195654 ¤   RingObject ····*name;
4c9771 ¤   PGPBoolean¤ ¤   firstname;
92af5a
d16348 ¤   /* It's a key but not axiomatic */
9ba007 ¤   pgpAssert (OBJISKEY(start));
4ad51a ¤   pgpAssert (!(start->k.trust & PGP_KEYTRUSTF_BUCKSTOP));
67af5a
8d3690 ¤   SETLOOKINGAT(&start->k);
1ad55a ¤   firstname = TRUE;
8b3396 ¤   for (name = start->g.down; name; name = name->g.next) {
0c7302 ¤   ¤   if (!OBJISNAME(name))
c717f5 ¤   ¤   ¤   continue;
27d8bf ¤   ¤   if ((name->n.confidence != 0 &&
018422 ¤   ¤   ¤   ·name->n.confidence != PGP_NEWTRUST_UNDEFINED) ||
214050 ¤   ¤   ¤   (start->k.signedTrust != 0 && firstname)) {
1b4f2e ¤   ¤   ¤   ppath = ringFindPathsName (name, ppath, predh, predt,
6a4311 ¤   ¤   ¤   ¤   ¤   ¤   depth, maxdepth, confset, allset, timenow, pool, NULL);
8e7572 ¤   ¤   ¤   if (!ppath)¤¤   ¤   ¤   /* out of memory */
d1f622 ¤   ¤   ¤   ¤   break;
380fe4 ¤   ¤   }
d92ea8 ¤   ¤   firstname = FALSE;
ec9371 ¤   }
f374c0 ¤   CLEARLOOKINGAT(&start->k);
64d79f ¤   return ppath;
c7efe6 }
73af5a
91af5a
deaf5a
4b38e5 /*
a0fc45 ·* Find all paths backwards from the specified target name to some key
e16291 ·* which is axiomatically trusted.
4a775e ·*
ee534b ·* Returns¤ tail pointer for new PathList
05775e ·*
ad8cde ·* name¤¤   starting name object for search backwards through web of trust
d15157 ·* ppath¤   address of PathList pointer we set to point to head of PathList
0d78f5 ·* maxdepth¤maximum length of paths we allow
46d0e3 ·* confset¤ ringset for trusted keys
6323fa ·* allset¤  ringset for all keys
fa3528 ·* timenow¤ current timestamp
a1f96d ·* pool¤¤   ringpool to use for memory allocations
--c7a3 0006358c8e7401001f7 Page 19 of pgpRngMnt.c
4f775e ·*
4e495d ·*/
9a8f94 static PathList **
d9f50e ringFindPathsBack (RingObject *name, PathList **ppath, unsigned maxdepth,
2bffd7 ¤   RingSet const *confset, RingSet const *allset, PGPUInt32 const timenow,
4a2063 ¤   RingPool *pool)
d2bb36 {
778db4 ····Path ··········*phead = NULL,
bc5165 ··················**ptail = &phead;
d3af5a
ce9c88 ¤   pgpAssert (OBJISNAME(name));
d3c4f7 ¤   pgpAssert (pgpIsRingSetMember(allset, name));
2a307a ¤   /* Don't SETLOOKINGAT here; must allow use of endpoint key as signer */
39e0b4 ¤   ppath = ringFindPathsName (name, ppath, &phead, ptail, 1, maxdepth,
b8d99c ¤   ¤   ······confset, allset, timenow, pool, NULL);
aed79f ¤   return ppath;
4befe6 }
4eaf5a
3c38e5 /*
d74fb8 ·* Create a copy of the given ringSet, but containing only keys which have
c2fb37 ·* at least one name with defined confidence.
24495d ·*/
340dcb static RingSet *
93ea66 ringSetConfidentSet (RingSet const *set)
40bb36 {
02e4b9 ¤   RingSet¤¤   ···¤*trustedset;
89f62f ¤   RingIterator¤   *iter;
e4af5a
f4c0b6 ¤   trustedset = ringSetCreate (ringSetPool (set));
9abd42 ¤   if (!trustedset)
a1bbde ¤   ¤   return 0;
71fd79 ¤   iter = ringIterCreate (set);
1af222 ¤   if (!iter) {
c3a29f ¤   ¤   ringSetDestroy (trustedset);
58bbde ¤   ¤   return 0;
ad9371 ¤   }
280c4d ¤   ringSetAddSet (trustedset, set);
f93f8b ¤   while (ringIterNextObject (iter, 1)) {
85a01d ¤   ¤   int goodconf = 0;¤  ¤   ¤   ¤   /* True if key has a conf. name */
847b69 ¤   ¤   PGPBoolean firstname = TRUE;
22346b ¤   ¤   RingObject *key = ringIterCurrentObject (iter, 1);
09a26e ¤   ¤   while (ringIterNextObject (iter, 2)) {
9f324f ¤   ¤   ¤   union RingObject *nameobj;
4376de ¤   ¤   ¤   nameobj = ringIterCurrentObject (iter, 2);
7a9329 ¤   ¤   ¤   if (!OBJISNAME(nameobj))
c5d040 ¤   ¤   ¤   ¤   continue;
ac7539 ¤   ¤   ¤   /* Remove names with undefined or zero confidence */
608303 ¤   ¤   ¤   if (key->k.signedTrust != 0 && firstname) {
829318 ¤   ¤   ¤   ¤   goodconf = 1;
c0909c ¤   ¤   ¤   } else if (ringKeyAxiomatic (set, key)) {
289318 ¤   ¤   ¤   ¤   goodconf = 1;
cd7e83 ¤   ¤   ¤   } else if (nameobj->n.confidence == PGP_NEWTRUST_UNDEFINED ||
612d15 ¤   ¤   ¤   ¤   ¤   ···nameobj->n.confidence == 0) {
5d1987 ¤   ¤   ¤   ¤   ringSetRemObject (trustedset, nameobj);
7e042d ¤   ¤   ¤   } else {
a59318 ¤   ¤   ¤   ¤   goodconf = 1;
76a3a6 ¤   ¤   ¤   }
153a80 ¤   ¤   ¤   firstname = FALSE;
6e0fe4 ¤   ¤   }
dab9b0 ¤   ¤   if (!goodconf) {
f7ddfa ¤   ¤   ¤   ringSetRemObject (trustedset, ringIterCurrentObject (iter, 1));
510fe4 ¤   ¤   }
a59371 ¤   }
eefedf ¤   ringIterDestroy (iter);
8fc680 ¤   ringSetFreeze (trustedset);
b3154a ¤   return trustedset;
97efe6 }
bcaf5a
c0cc15 #endif /* PGPTRUSTMODEL==2 */
cbaf5a
fbaf5a
63ab69 /********************** Trust Model 0 ***************************/
--afa3 0004f9f2edd401001f7 Page 20 of pgpRngMnt.c
e0af5a
1aaf5a
e31325 #if PGPTRUSTMODEL==0
bbaf5a
c038e5 /*
d41621 ·* Add "inc" trust to the name signed by the given sig.
4e00b9 ·* If the trust passes "thresh", mark the name with the level
535f41 ·* and add the key that owns it to the list. ·Return the expanded list.
81775e ·*
3f22e8 ·* TODO: Do something sensible with signatures on keys.
37495d ·*/
becdf7 static RingKey const *
9bec18 mntDoSig(RingSig const *sig, RingKey const *list,
c3421e ¤   int const inc, int const thresh, PGPUInt32 const timenow, int const level)
46bb36 {
a5b89a ¤   union RingObject *name, *key;
fda7af ¤   PGPByte sigtype;
9eaf5a
07e3a3 ¤   (void)timenow;¤ /* Avoid warning */
f4a3f8 ¤   pgpAssert(mntSigIsValid(timenow, sig->tstamp, sig->validity));
d6af5a
c73210 ¤   name = sig->up;
491485 ¤   if (!OBJISNAME(name)) {
939327 ¤   ¤   /* @@@ do anything with sigs on keys? */
3eee62 ¤   ¤   return list;
da9371 ¤   }
27af5a
02b177 #if 0
0e8ba0 ¤   /* ·Ignore self-signature */
e300f1 ¤   key = name->n.up;
a294a2 ¤   pgpAssert(OBJISKEY(key));
8972f8 ¤   if (key == sig->by)
8dac94 ¤   ····return list;
9d7454 #endif
21af5a
499b0a ¤   sigtype = sig->type & 0xF0;
1ac50f ¤   if (sigtype != PGP_SIGTYPE_KEY_GENERIC)
40ee62 ¤   ¤   return list;
04af5a
103db1 #if PRINT_PROGRESS
4bc022 ¤   printf(" ·Trust %d/%d -> %d/%d on name ",
d2e0af ¤   ·······name->n.trustval, thresh,
5f20c8 ¤   ·······name->trustval + inc, thresh);
5826b7 ¤   (void)ringTtyPutString(name->name, name->len, -1u, stdout, '"', '"');
ed4965 ¤   putchar('\n');
a67454 #endif
e2b159 ¤   name->n.trustval += inc;
0ad8af ¤   /*
af3e8f ¤   ·* If we are not yet at the valid level or have already
a9d962 ¤   ·* marked this name as validated, bail out.
f2a4e3 ¤   ·*/
df23ce ¤   if (name->n.trustval < thresh || NAMELEVEL(&name->n))
6aee62 ¤   ¤   return list;
401742 ¤   /* Passed threshold - label with certification level. */
674e8b ¤   NAMESETLEVEL(&name->n, level);
5c00f1 ¤   key = name->n.up;
f394a2 ¤   pgpAssert(OBJISKEY(key));
a47b3f ¤   if (key->g.flags & KEYF_TRUSTED ||¤ ·/* Already listed? */
1e9567 ¤   ····key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
b9ee62 ¤   ¤   return list;
ff3db1 #if PRINT_PROGRESS
74e368 ¤   ringKeyIDprint(stdout,
f79809 " ···Potential introducer: first userID trust >= 1 on keyID ",
452284 ¤   ¤   ¤   ·······key->keyID);
357454 #endif
053239 ¤   key->k.util = (RingKey *)list;
52b3ba ¤   key->g.flags |= KEYF_TRUSTED;
0f0812 ¤   return &key->k;
afefe6 }
f5af5a
32af5a
4f38e5 /*
--2a6c 0006ba57406401001f7 Page 21 of pgpRngMnt.c
97dfbf ·* Look for other keys signed by the grandparent of sig which have the same
f8275b ·* name. ·Propagate the same trust to those names. ·(Don't do it if they
9616ff ·* have a sig by the same signing key.) ·The reasoning is that the same
35df95 ·* person owns both keys, he has the same name, so sigs on the first name
219633 ·* can be treated as though they are on the other name. ·This will facilitate
e35fe6 ·* moving to a new key from an old one.
1e775e ·*
f64011 ·* One issue not dealt with here is that if the grandparent key here is also
0027b1 ·* a trusted introducer, trust will move to the destination key in two ways:
16535c ·* here, by direct "pair propagation" from signatures on that key's names
1eb3e5 ·* which match the names here; and also by normal trust propagation due to
1de701 ·* the signature. ·This could end up counting some trust twice, although
72f7b8 ·* in this trust model it doesn't look like it introduces any significant
c87c9d ·* weaknesses.
e2495d ·*/
20af5a
b9cdf7 static RingKey const *
c578f4 mntDoMatchingNames(RingSig const *sig, RingKey const *list,
bce848 ¤   RingSet const *set, int const inc, int const thresh,
3a71fa ¤   PGPUInt32 const timenow,
d37917 ¤   int const level)
7bbb36 {
45e93b ¤   RingObject¤ ¤   ¤   *name;¤ ¤   /* Name which sig is on */
4e8259 ¤   RingObject¤ ¤   ¤   *key;¤  ¤   /* Key which name is on */
1505f6 ¤   RingObject¤ ¤   ¤   *propsig;¤  /* All sigs by key */
0c3aac ¤   RingObject¤ ¤   ¤   *propname;¤ /* Name which propsig is on */
c8eff4 ¤   RingObject¤ ¤   ¤   *propkey;¤  /* Key which propname is on */
a70c2f ¤   RingObject¤ ¤   ¤   *namesig;¤  /* All sigs on propname */
614b97 ¤   PGPByte¤¤   ¤   ¤   ·sigtype;
9c13b2 ¤   PGPByte¤¤   ¤   ¤   ·selfsigfound;
e0af5a
80a3f8 ¤   pgpAssert(mntSigIsValid(timenow, sig->tstamp, sig->validity));
88af5a
9da630 ¤   /* Ignore sigs not on names */
ab3210 ¤   name = sig->up;
f2fa56 ¤   if (!OBJISNAME(name))
89ee62 ¤   ¤   return list;
afaf5a
0bb01b ¤   /* Ignore self signatures, invalid keys, and keys which don't sign */
fa00f1 ¤   key = name->n.up;
f694a2 ¤   pgpAssert(OBJISKEY(key));
9172f8 ¤   if (key == sig->by)
72ac94 ¤   ····return list;
29575e ¤   if (key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
54ee62 ¤   ¤   return list;
71af5a
eff7d7 ¤   /* Ignore funny kinds of sigantures */
fa9b0a ¤   sigtype = sig->type & 0xF0;
83c50f ¤   if (sigtype != PGP_SIGTYPE_KEY_GENERIC)
8eee62 ¤   ¤   return list;
d61b52 ¤   ¤
eed8af ¤   /*
e61f7f ¤   ·* As a short-term security precaution, only propagate for fully valid
23c7c5 ¤   ·* names. ·The problem is that otherwise, someone could have two keys,
a4cb60 ¤   ·* A and B, which both are marginally valid. ·If both A and B sign key
eced1c ¤   ·* C which has the same name, the marginally valid signatures combine
bf14a2 ¤   ·* to give full validity to C. ·We have a solution to this but it is
0c55e8 ¤   ·* complex. ·For now we will only do propagation from names which are
fe57d3 ¤   ·* fully valid, which will mean that only fully valid keys get their
e3a1ff ¤   ·* trust propagated to matching names.
50a4e3 ¤   ·*/
7ba15e ¤   if (!NAMELEVEL(&name->n))
c0ee62 ¤   ¤   return list;
2eaf5a
1d9f15 ¤   /* Look for other keys with same name */
715b67 ¤   for (propsig = key->k.sigsby; propsig;
6bbabf ¤   ¤   ¤   ¤   ¤   ¤   propsig = (RingObject *)propsig->s.nextby) {
54c5c5 ¤   ¤   if (!pgpIsRingSetMember(set, propsig))
0617f5 ¤   ¤   ¤   continue;
fbb663 ¤   ¤   propname = propsig->s.up;
24af5a
6be7c3 ¤   ¤   /* Ignore sigs not on names */
--80f6 0000581a310401001f7 Page 22 of pgpRngMnt.c
211e95 ¤   ¤   if (!OBJISNAME(propname))
6617f5 ¤   ¤   ¤   continue;
838903 ¤   ¤   propkey = propname->n.up;
85af5a
f2c543 ¤   ¤   /* Ignore nonkeys(?) or self sigs */
1c064c ¤   ¤   if (!OBJISKEY(propkey) || propkey == key)
1e17f5 ¤   ¤   ¤   continue;
2baf5a
6924e9 ¤   ¤   /* Make sure signature is valid */
1eb715 ¤   ¤   if (!mntSigIsValidKeySig(propsig, set, timenow))
2017f5 ¤   ¤   ¤   continue;
a3af5a
8d5c3c ¤   ¤   /* See if names match */
93fe26 ¤   ¤   if (ringNamesDiffer (set, name, propname))
fd17f5 ¤   ¤   ¤   continue;
c4af5a
affaf4 ¤   ¤   /* Skip if name already has a sig from our signer */
ac27e3 ¤   ¤   /* Also, this must be the newest sig by us */
d3cf45 ¤   ¤   /* Also, it must have a self signature */
63d020 ¤   ¤   selfsigfound = 0;
05edf1 ¤   ¤   for (namesig=propname->n.down; namesig; namesig=namesig->s.next) {
056c92 ¤   ¤   ¤   if (!OBJISSIG(namesig) || !pgpIsRingSetMember(set, namesig))
8dd040 ¤   ¤   ¤   ¤   continue;
148564 ¤   ¤   ¤   if (namesig->s.by == sig->by)
78d599 ¤   ¤   ¤   ¤   break;¤ ¤   /* Break out with nonnull namesig on match */
c59d0e ¤   ¤   ¤   if (namesig != propsig && namesig->s.by == key
94e84f ¤   ¤   ¤   ¤   ¤   ¤   && namesig->s.tstamp >= propsig->s.tstamp)
ae5191 ¤   ¤   ¤   ¤   break;¤ ¤   /* Break outwith nonnull namesig if not newest */
9f490b ¤   ¤   ¤   /* Check for valid self signature */
832193 ¤   ¤   ¤   if (namesig->s.by == propkey
3c4cfc ¤   ¤   ¤   ¤   && mntSigIsValidKeySig(namesig, set, timenow)) {
0434a0 ¤   ¤   ¤   ¤   selfsigfound = 1;
98a3a6 ¤   ¤   ¤   }
300fe4 ¤   ¤   }
58af5a
485090 ¤   ¤   /* If namesig is non-null it had a matching sig, skip this name */
1aae35 ¤   ¤   /* Also if there was no self signature */
5250f7 ¤   ¤   if (namesig || !selfsigfound)
3317f5 ¤   ¤   ¤   continue;
f4af5a
525376 ¤   ¤   /* OK, we have a name suitable for propagating trust to */
7d6030 ¤   ¤   list = mntDoSig(&propsig->s, list, inc, thresh, timenow, level);
7f9371 ¤   }
f8afe9 ¤   return list;
41efe6 }
78af5a
71af5a
ec38e5 /*
467764 ·* Add "inc" trust to each name signed by a valid signature on
2af2ae ·* the "sigs" list. ·If the trust passes "thresh", add the resultant
543c75 ·* key to the list. ·Return the expanded list.
1d775e ·*
57fbcc ·* Signatures that are expired or have been superseded are weeded out.
35f5d2 ·* Note that a postdated signature does not supersede one dated yesterday!
48495d ·*/
c6cdf7 static RingKey const *
f24d0d mntWalkSigList(RingSig const *sigs, RingKey const *list,
b55ea2 ¤   RingSet const *set, int const inc, int const signedinc,
46af0f ¤   int const thresh, PGPUInt32 const timenow, int const level)
6fbb36 {
d65a6d ¤   RingSig const *cur;
17c38c ¤   int effectivetrustinc;
2daf5a
b1585c ¤   while (sigs) {
d46814 ¤   ¤   /* Find the first valid checked signature in the set. */
d8db21 ¤   ¤   if (!(sigs->trust & PGP_SIGTRUSTF_CHECKED)
6a0d32 ¤   ¤   ¤   || !pgpIsRingSetMember(set, (RingObject *)sigs)
3710b8 ¤   ¤   ····|| !mntSigIsValid(timenow, sigs->tstamp, sigs->validity)
83138c ¤   ¤   ¤   || mntForeignSignature(sigs, set))
2d5b34 ¤   ¤   {
9be414 ¤   ¤   ¤   sigs = sigs->nextby;
0517f5 ¤   ¤   ¤   continue;
--d5d0 000765dd878401001f7 Page 23 of pgpRngMnt.c
b50fe4 ¤   ¤   }
5f5f00 ¤   ¤   /* The first candidate signature */
f73a33 ¤   ¤   cur = mntNewestValidSiblingSig( &sigs, set, timenow );
d1af5a
2a8f4a ¤   ¤   /* Don't count signedinc if signature is limited by regexp */
3d5c13 ¤   ¤   if (signedinc <= 0 || !mntSigOKWithRegexp( set, cur ) )
965dc0 ¤   ¤   ¤   effectivetrustinc = inc;
090e1d ¤   ¤   else
83adc9 ¤   ¤   ¤   effectivetrustinc = pgpMax( inc, signedinc );
2faf5a
001774 ¤   ¤   if( effectivetrustinc <= 0 )
ad17f5 ¤   ¤   ¤   continue;
b8af5a
99614e ¤   ¤   /* Do the trust computations on the resultant signature. */
5117fb ¤   ¤   list = mntDoSig(cur, list, effectivetrustinc, thresh, timenow, level);
e2af5a
350cfa ¤   ¤   /* Propagate sig info also to linked keys with matching names */
046044 ¤   ¤   list = mntDoMatchingNames(cur, list, set, effectivetrustinc, thresh,
14af01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··timenow, level);
faaf5a
8a9371 ¤   }
4fafe9 ¤   return list;
57efe6 }
c7af5a
ec38e5 /*
ae0c4c ·* Walk a list of keys (linked through the util field), adding the
44ae2e ·* appropriate trust values to the names the key has signed.
83495d ·*/
3acdf7 static RingKey const *
a7ee62 mntList(RingKey const *list, RingSet const *set, int const add[8],
090838 ¤   int const threshold, PGPUInt32 const timenow, unsigned const level)
54bb36 {
6f7e84 ¤   RingKey const *newlist;
d1e744 ¤   int trustinc;¤  ¤   ¤   ¤   /* Trust from trust packets */
178b9d ¤   int signedtrustinc;¤¤   ¤   /* Trust from signatures */
2eaf5a
537195 ¤   for (newlist = 0; list; list = list->util) {
47ede6 ¤   ¤   pgpAssert(list->flags & KEYF_TRUSTED);
c51858 ¤   ¤   trustinc = add[list->trust & kPGPKeyTrust_Mask];
a2ee36 ¤   ¤   signedtrustinc = add[list->signedTrust & kPGPKeyTrust_Mask];
0b3db1 #if PRINT_PROGRESS
b2cc5d ¤   ¤   printf(, "Adding %d/%d trust from ", trustinc, threshold);
fac61d ¤   ¤   ringKeyPrint(stdout, (RingPool *)0, "", list);
0a7454 #endif
cdb177 #if 0
951b17 ¤   ¤   /*
12008f ¤   ¤   ·* @@@ PGP 2.x allows disabled keys to participate in
524f49 ¤   ¤   ·* trust computation. ·Should this be added?
fe9de3 ¤   ¤   ·*/
19494a ¤   ¤   if (list->trust & (PGP_KEYTRUSTF_DISABLED))
ef17f5 ¤   ¤   ¤   continue;
6c7454 #endif
05eaa2 ¤   ¤   if (trustinc <= 0 && signedtrustinc <= 0)
7517f5 ¤   ¤   ¤   continue;
1ba8bf ¤   ¤   newlist = mntWalkSigList(&list->sigsby->s, newlist, set, trustinc,
9fbb5f ¤   ¤   ·························signedtrustinc, threshold, timenow, level);
3e9371 ¤   }
45af5a
becbab ¤   return newlist;
bbefe6 }
6faf5a
ebaf5a
f9beb9 /******************** Trust Model 1&2 Helpers *************************/
32af5a
a26ba4 #else /* PGPTRUSTMODEL>0 */
c5af5a
1238e5 /*
52d547 ·* This finds the combined trust value given two trusts which
dacd2c ·* are arranged in series. ·Trust values are actually the
7c632a ·* scaled negative logarithms of *distrust*, so assuming
971900 ·* independent failures, two signatures in parallel have a
7698bd ·* distrust which is the product of the input distrusts, and
--046f 0005238f917401001f7 Page 24 of pgpRngMnt.c
94e510 ·* we only have to add the trust values. ·But when they're
deecdd ·* in series, we want to multiply the *trusts*, and it gets hairier...
3e9b36 ·* This is a quick and dirty brute-force-and-ignorance approach.
344800 ·* I know of better solutions, but haven't had time to do the
a10f67 ·* necessary numerical analysis.
e5775e ·*
7b8a0f ·* @@@ Optimize this code
79775e ·*
87d107 ·* Given t1 = log(p1)/k and t2 = log(p2)/k, where p1 and p2 are
90387b ·* probabilities that are bounded between 0 < p1,p2 <= 1, find
c19205 ·* t3 = log(1-(1-p1)*(1-p2))/k
532c10 ·* ···= log(1-(1-exp(t1*k))*(1-exp(t2*k)))/k.
5c10db ·* ···= log(p1 + p2 - p1*p2)
6a8297 ·* ···= log(exp(t1*k) + exp(t2*k) - exp(t1*k)*exp(t2*k))/k
29953e ·* k is chosen to make the logs come out right,
2c3a90 ·* so that an increment of TRUST_DECADE corresponds to 1/10.
af8640 ·* I.e. exp(TRUST_DECADE*k) = 1/10
6d23ff ·* ··=> ·····TRUST_DECADE*k = log(1/10)
977f76 ·* ··=> ··················k = -log(10)/TRUST_DECADE;
f582da ·* Well, actually there's an additional factor of TRUST_CERTSHIFT
5b388f ·* thrown in there, a factor of 64 which allows probabilities down to
9ff713 ·* 10^-25 and a granularity of +/-0.09% in trust values.
8f2e3f ·* Note that p1+p2-p1*p2 = p1 + p2*(1-p1) >= p1, so the output
d172bf ·* probability is always greater than either of the input probabilities,
ff9297 ·* so t3 is always less than t1 or t2. ·Thus, the computation can't
ccf0d9 ·* overflow.
d3775e ·*
b05665 ·* I'd prefer to somehow evaluate it directly in log form, using
5fc896 ·* something like Zech's log function to evaluate it.
7c522f ·* H'm... an alternate evaluation technique...
50e6d5 ·* ··p1 * (1 + p2/p1(1-p1))
896b26 ·* = p1 * (1 + p2*(1/p1-1))
999835 ·* Choose p1 as the larger of the two... does this lead to anything?
7b9f86 ·* Yes. ·Two tables of size 771 (= ceil(log(2)*40*64)) will allow you
c5ab6a ·* to evaluate (1/p1-1) directly, guaranteed to round down, and then
aa13be ·* I think something similar will do for (t+1). ·For the (1/p1-1)
bb4de1 ·* evaluation, do the entries for p1 from 1 to 1/2 directly, and
56dc95 ·* past that, the value of (1/p1-1) differes from the value of
0573bd ·* 1/p1 by at most 771. ·Record in another table the values at
c6bcc0 ·* which the delta changes, do a binary search, and use the index as
2793de ·* the delta.
e6495d ·*/
5638ab #include <math.h>
e514c6 #ifndef M_LN10
47d44b #define M_LN10¤ 2.30258509299404568402¤ /* ln(10) */
447454 #endif
878a37 static PGPUInt16
c6a0a2 mergetrust(PGPUInt16 t1, PGPUInt16 t2)
72bb36 {
83b504 ¤   static double const k = -M_LN10 / PGP_TRUST_DECADE;
527dcf ¤   double p, q;
eaaf5a
a88b0e ¤   /* Saturate at infinity */
3838e2 ¤   if (t1 == (PGPUInt16) PGP_TRUST_INFINITE)
29c72d ¤   ¤   return t2;
43fe12 ¤   if (t2 == (PGPUInt16) PGP_TRUST_INFINITE)
902849 ¤   ¤   return t1;
f17422 ¤   p = exp(t1*k);
bd3075 ¤   q = exp(t2*k);
b3af5a
51bca8 ¤   /* Round down for conservative estimate */
f2bf51 ¤   return (PGPUInt16)floor(log(p + q - p*q)/k);
dcefe6 }
a8af5a
2f38e5 /*
2dbaa2 ·* Compute the trust value associated with a key. ·This is the
6fac31 ·* weight given to signatures made by that key. ·The decision is based
d64601 ·* on the validity of the key's name (how sure are we that the name
207ee2 ·* belongs to that key) and confidence (how much do we trust the
27ed79 ·* named individual). ·The product of those two gives the trust in
516989 ·* the key as a whole.
52775e ·*
--1e5c 000b1c921a8401001f7 Page 25 of pgpRngMnt.c
b72acb ·* If the key is a buckstop key, ignore the validity and just take the
b752b2 ·* confidence as-is.
86775e ·*
027e4f ·* If there are multiple names on a key, compute the trust for each and
f53b8c ·* use the maximum.
df775e ·*
765a98 ·* BESTVALID alternate algorithm
91775e ·*
890cda ·* If BESTVALID if set, then the overall trust in a key is determined
f966bb ·* from the name with the highest validity. ·In the case of a tie,
cfb086 ·* then the best validity*confidence is taken. ·Thus, overall trust
301d1b ·* is computed from the name this key is most likely to belong to.
0a495d ·*/
e5e250 #ifndef BESTVALID
5f6e0d #define BESTVALID 1
f97454 #endif
9aaf5a
888a37 static PGPUInt16
5f7434 calctrust(RingKey const *k, RingSet const *set)
98bb36 {
a5595a ¤   union RingObject const *n;
effff7 ¤   PGPUInt16 cur, best = 0;
ec72c6 #if BESTVALID
9bebf8 ¤   PGPUInt16 bestvalid = 0;
5a7454 #endif
3faf5a
1b06a5 ¤   pgpAssert(KEYISKEY(k));
c7af5a
2e5f7f ¤   /* For BUCKSTOP keys, validity and confidence are infinite.
d13a3b ¤   ···Revoked or expired keys have no validity or confidence. */
6532dc ¤   if (k->trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
c2bbde ¤   ¤   return 0;
9e3cab ¤   if (k->trust & PGP_KEYTRUSTF_BUCKSTOP)
98c8aa ¤   ¤   return PGP_TRUST_INFINITE;
ceaf5a
6bdcb3 ¤   for (n = k->down; n; n = n->g.next) {
2172c6 #if BESTVALID
41b9b1 ¤   ¤   if (OBJISNAME(n) && pgpIsRingSetMember(set, n) &&·
74598d ¤   ¤   ····n->n.valid >= bestvalid)
badb21 #else
97e886 ¤   ¤   if (OBJISNAME(n) && pgpIsRingSetMember(set, n))
a67454 #endif
ae5b34 ¤   ¤   {
ef5ed4 ¤   ¤   ¤   cur = n->n.confidence;
6b46ea ¤   ¤   ¤   if (cur == PGP_NEWTRUST_INFINITE)
e6fe5c ¤   ¤   ¤   ¤   cur = n->n.valid;
ca82f6 ¤   ¤   ¤   else if (cur == PGP_NEWTRUST_UNDEFINED)
686228 ¤   ¤   ¤   ¤   cur = 0;
b3bb8c ¤   ¤   ¤   else
672f33 ¤   ¤   ¤   ¤   cur = mergetrust((PGPUInt16)(cur << TRUST_CERTSHIFT),
c1fe31 ¤   ¤   ¤   ¤   ·················n->n.valid);
8f72c6 #if BESTVALID
56ab23 ¤   ¤   ¤   if (n->n.valid > bestvalid ||
55c690 ¤   ¤   ¤   ····(n->n.valid == bestvalid && cur > best)) {
d96dee ¤   ¤   ¤   ·········best = cur;
15ce1e ¤   ¤   ¤   ¤   ·bestvalid = n->n.valid;
b6a3a6 ¤   ¤   ¤   }
1bdb21 #else
561459 ¤   ¤   ¤   if (cur > best)
7a5a64 ¤   ¤   ¤   ¤   best = cur;
947454 #endif
260fe4 ¤   ¤   }
0c9371 ¤   }
e8e17b ¤   return best;
47efe6 }
a4af5a
ff411c PGPUInt16·
4a6e60 ringKeyCalcTrust(RingSet const *set, union RingObject *key)
adbb36 {
54fcc1 ¤   PGPUInt16 trust;
150dfd ¤   double confidence;
b194a2 ¤   pgpAssert(OBJISKEY(key));
--e568 000015442e9401001f7 Page 26 of pgpRngMnt.c
f74abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
252095 #if PGPTRUSTMODEL==2
2ccb4f ¤   confidence = pathKeyConfidence (key, set);
f4bf31 ¤   if (confidence >= 1.)
d2ae95 ¤   ¤   trust = PGP_TRUST_INFINITE;
bd0e24 ¤   else
100e78 ¤   ¤   trust = ringDoubleToTrust (1. / (1.-confidence));
39db21 #else
298f40 ¤   (void) confidence;
ee8f33 ¤   trust = calctrust (&key->k, set);
b07454 #endif
545ef8 ¤   return trust;
99efe6 }
fc4c16 ¤   ·······
53b8d3 #endif /* PGPTRUSTMODEL>0 */
43af5a
d9af5a
f16e5d /********************** Trust Model 1 ***************************/
b0af5a
a90afd #if PGPTRUSTMODEL==1
63af5a
3738e5 /*
57e958 ·* Add confidence to the name signed by the given sig, and if the name
480b69 ·* has confidence and the key has not already been processed, add it
032f45 ·* to the list. ·Return the expanded list.
c3775e ·*
9e22e8 ·* TODO: Do something sensible with signatures on keys.
66495d ·*/
69e5ac static RingKey *
dee385 mntDoSig(RingSig const *sig, RingKey *list,
12888c ¤   PGPUInt16 confidence, PGPUInt32 const timenow, int const level,
3531e6 ¤   int pass2)
21bb36 {
2fb89a ¤   union RingObject *name, *key;
914ba4 ¤   int i;
5aa7af ¤   PGPByte sigtype;
3faf5a
c1a3f8 ¤   pgpAssert(mntSigIsValid(timenow, sig->tstamp, sig->validity));
a2af5a
4d3f27 ¤   /* Okay, it hasn't expired, check that we have a name signature */
763210 ¤   name = sig->up;
2eaf5a
671485 ¤   if (!OBJISNAME(name)) {
cb834a ¤   ¤   /* @@@ Do anything here with signatures on keys? */
05ee62 ¤   ¤   return list;
329371 ¤   }
e6af5a
d99b0a ¤   sigtype = sig->type & 0xF0;
a8c50f ¤   if (sigtype != PGP_SIGTYPE_KEY_GENERIC)
dfee62 ¤   ¤   return list;
1f00f1 ¤   key = name->n.up;
5994a2 ¤   pgpAssert(OBJISKEY(key));
3cf7cd ¤   /* Do not add confidence from a key to itself */
f072f8 ¤   if (key == sig->by)
47ee62 ¤   ¤   return list;
3ed8af ¤   /*
f99b99 ¤   ·* There are two passes: first we add trust from keys at one level
b26410 ¤   ·* to keys on the next level, then we add trust from keys at
7792f0 ¤   ·* that level to each other. ·Pass2 is a flag controlling which
248657 ¤   ·* we do.
57da0b ¤   ·* Oh, names which we have no confidence in as introducers
c7cbab ¤   ·* get their certainty added from all levels, since they cannot
26528c ¤   ·* participate in cycles. ·This is done during pass 1.
6b35b6 ¤   ·* So, during pass 1:
942023 ¤   ·* - Ignore names on keys that we have already recorded that are
8f0f48 ¤   ·* ··at levels less than the current one.
bad343 ¤   ·* And during pass 2:
73cab1 ¤   ·* - Ignore names other than ones at the specified level on keys
3fe28b ¤   ·* ··that *are* trusted. ·(On keys that are not will get added
c7f166 ¤   ·* ··next iteration).
64a4e3 ¤   ·*/
017c68 ¤   i = NAMELEVEL(&name->n);
--f54d 000a4a6aba2401001f7 Page 27 of pgpRngMnt.c
ef0cbb ¤   if (!pass2) {
f47bbf ¤   ¤   /* Pass 1 */
804ee1 ¤   ¤   if (!i)
170134 ¤   ¤   ¤   NAMESETLEVEL(&name->n, level);
9f8a14 ¤   ¤   else if (i < level && key->g.flags & KEYF_TRUSTED)
6b5fb3 ¤   ¤   ¤   return list;
d3f037 ¤   } else {
776673 ¤   ¤   /* Pass 2 */
e7c860 ¤   ¤   if (i != level || !(key->g.flags & KEYF_TRUSTED))
0b5fb3 ¤   ¤   ¤   return list;
b09371 ¤   }
abaf5a
4cd57a ¤   /* Okay, now add the confidence if needed. ·Do special
39751e ¤   ···checks for infinite confidence and validity. ·*/
31af5a
c448aa ¤   if (confidence == PGP_TRUST_INFINITE)
d90f92 ¤   ¤   name->n.valid = PGP_TRUST_INFINITE;
a3b9c5 ¤   else if (name->n.valid != PGP_TRUST_INFINITE) {
869319 ¤   ¤   name->n.valid += confidence;
b21b17 ¤   ¤   /*
6524f4 ¤   ¤   ·* Saturate on overflow. ·65535 is reserved for "perfect".
9929dd ¤   ¤   ·* 65534 is 2.5164 * 10^-26, 2^-85. ·
159de3 ¤   ¤   ·*/
77dab4 ¤   ¤   if (name->n.valid + 1 <= confidence)
7df6ce ¤   ¤   ¤   name->n.valid = (PGPUInt16) PGP_TRUST_MAX;·
de9371 ¤   }
50af5a
15d8af ¤   /*
e5c051 ¤   ·* Don't add keys to the list if:
7fd8ff ¤   ·* - Already on list
6fbfba ¤   ·* - Key is revoked (confidence is zero then)
b7933d ¤   ·* - Key is expired (same as revoked)
5d0bb1 ¤   ·* - Name has no confidence
5e0121 ¤   ·* Currently, disabled keys *are* allowed on the list,
c36b83 ¤   ·* to participate in trust transactions. ·Disabling only
6aae5f ·¤  ·* affects key selection. ·This is PGP 2.x compatible.
719714 ¤   ·*
373990 ¤   ·* Once a key is on the list, only one more round of adding
3689eb ¤   ·* certainty to its names is possible, since two rounds could
50d8d1 ¤   ·* create cycles that correcting for is difficult. ·Thus,
288e52 ¤   ·* we want to avoid putting things on the list unnecessarily,
26fa0f ¤   ·* but prefer to weed out everything possible now.
81a4e3 ¤   ·*/
1dcfe7 ¤   if (key->g.flags & KEYF_TRUSTED¤/* Already listed? */
293e47 ¤   ····|| key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED)
dd9b5c /*¤ ····|| key->k.trust & PGP_KEYTRUSTF_DISABLED */ /*PGP 2.x compatible*/
445f59 ¤   ····|| !name->n.confidence)
bcee62 ¤   ¤   return list;
413239 ¤   key->k.util = (RingKey *)list;
d1b3ba ¤   key->g.flags |= KEYF_TRUSTED;
6d0812 ¤   return &key->k;
aaefe6 }
d0af5a
3338e5 /*
4cb182 ·* Add confidence to each name signed by a valid signature on
0ff2ae ·* the "sigs" list. ·If the trust passes "thresh", add the resultant
233c75 ·* key to the list. ·Return the expanded list.
5b775e ·*
53fbcc ·* Signatures that are expired or have been superseded are weeded out.
eaf5d2 ·* Note that a postdated signature does not supersede one dated yesterday!
09495d ·*/
d5e5ac static RingKey *
ce5b2c mntWalkSigList(RingSig const *sigs, RingKey *list,
912d27 ¤   PGPUInt16 confidence, RingSet const *set, PGPUInt32 const timenow,
b9db93 ¤   int const level, int pass2)
9dbb36 {
6c5a6d ¤   RingSig const *cur;
18af5a
3f585c ¤   while (sigs) {
606814 ¤   ¤   /* Find the first valid checked signature in the set. */
e7db21 ¤   ¤   if (!(sigs->trust & PGP_SIGTRUSTF_CHECKED)
a40d32 ¤   ¤   ¤   || !pgpIsRingSetMember(set, (RingObject *)sigs)
--ba52 00050514558401001f7 Page 28 of pgpRngMnt.c
5b9fd2 ¤   ¤   ····|| !mntSigIsValid(timenow, sigs->tstamp, sigs->validity))
d85b34 ¤   ¤   {
fee414 ¤   ¤   ¤   sigs = sigs->nextby;
8117f5 ¤   ¤   ¤   continue;
800fe4 ¤   ¤   }
525f00 ¤   ¤   /* The first candidate signature */
39f24c ¤   ¤   cur = sigs;
e0af5a
941b17 ¤   ¤   /*
8918bb ¤   ¤   ·* Search all other signatures by this key on the same object
601d72 ¤   ¤   ·* for the most recent valid signature, which is the only
d29ce3 ¤   ¤   ·* one which is accorded any weight. ·We use the fact that
7c0a74 ¤   ¤   ·* after ringPoolListSigsBy places all signatures on
6f9099 ¤   ¤   ·* the same object together in the sigsby list.
5f9de3 ¤   ¤   ·*/
908aa1 ¤   ¤   while ((sigs = sigs->nextby) != NULL && sigs->up == cur->up)
ec5b34 ¤   ¤   {
b97aad ¤   ¤   ¤   /*
ca3846 ¤   ¤   ¤   ·* So now that the signature at the front of the sigs
0e38af ¤   ¤   ¤   ·* list is on the same thing as "cusrig", consider
bed771 ¤   ¤   ¤   ·* replacing cur, if the new signature is is
b7a097 ¤   ¤   ¤   ·* checked good, valid, in the set, and
6888bf ¤   ¤   ¤   ·* more recent than cur.
da50ce ¤   ¤   ¤   ·*·
8e8753 ¤   ¤   ¤   ·*/
192f66 ¤   ¤   ¤   if (sigs->trust & PGP_SIGTRUSTF_CHECKED
fae7aa ¤   ¤   ¤   ¤   && pgpIsRingSetMember(set, (RingObject *)sigs)
1f5013 ¤   ¤   ¤   ····&& cur->tstamp < sigs->tstamp
bb0568 ¤   ¤   ¤   ····&& mntSigIsValid(timenow, sigs->tstamp,
8c3fed ¤   ¤   ¤   ·····················sigs->validity))
ac7edd ¤   ¤   ¤   ¤   cur = sigs;
cd0fe4 ¤   ¤   }
f3af5a
8b614e ¤   ¤   /* Do the trust computations on the resultant signature. */
4bb04c ¤   ¤   list = mntDoSig(cur, list, confidence, timenow, level, pass2);
f89371 ¤   }
d0afe9 ¤   return list;
6aefe6 }
0eaf5a
6c38e5 /*
b30c4c ·* Walk a list of keys (linked through the util field), adding the
f0ae2e ·* appropriate trust values to the names the key has signed.
7c495d ·*/
36cdf7 static RingKey const *
d99a82 mntList(RingKey const *list, RingSet const *set,
4cd62d ¤   PGPUInt32 const timenow, unsigned const level)
fabb36 {
a3ceb7 ¤   RingKey *newlist;
a169c6 ¤   RingKey *cur;
ff3efd ¤   PGPUInt16 confidence;
2eaf5a
d20938 ¤   /* Do first pass, adding trust from old list to new things */
5eba2f ¤   for (newlist = NULL; list; list = list->util) {
f4ede6 ¤   ¤   pgpAssert(list->flags & KEYF_TRUSTED);
9f8005 ¤   ¤   confidence = calctrust(list, set);
a239da ¤   ¤   if (!confidence)
f417f5 ¤   ¤   ¤   continue;
cd4660 ¤   ¤   newlist = mntWalkSigList(&list->sigsby->s, newlist, confidence,
3f9161 ¤   ¤   ·························set, timenow, level, 0);
909371 ¤   }
64d8af ¤   /*
7a585d ¤   ·* Do second pass, adding trust from new list to itself.
a5f6b3 ¤   ·* The overall confidence for each key must be calculated·
8350cf ¤   ·* before the second pass begins to avoid artificially high
c80818 ¤   ·* confidence values caused by loops. ·Using a new field
b5780a ¤   ·* 'list->confidence' increases the size of each key object·
e9b9f7 ¤   ·* by 2 bytes (@@@ can we avoid this?)
caa4e3 ¤   ·*/
c91581 ¤   for (cur = newlist; cur; cur = cur->util) {
84c3d3 ¤   ¤   pgpAssert(cur->flags & KEYF_TRUSTED);
f6a8aa ¤   ¤   cur->confidence = calctrust(cur, set);
509371 ¤   }
--d0a6 0004cdcd82e401001f7 Page 29 of pgpRngMnt.c
131581 ¤   for (cur = newlist; cur; cur = cur->util) {
e0a214 ¤   ¤   if (!cur->confidence)
1217f5 ¤   ¤   ¤   continue;
52fcde ¤   ¤   newlist = mntWalkSigList(&cur->sigsby->s, newlist,
932218 ¤   ¤   ·························cur->confidence,
e78dda ¤   ¤   ·························set, timenow, level, 1);
499371 ¤   }
86af5a
6bcbab ¤   return newlist;
a4efe6 }
c9af5a
2fd1d9 #endif /* PGPTRUSTMODEL==1 */
87af5a
6baf5a
46af5a
edc620 /* Meta-Introducer and trust signature support */
acaf5a
6baf5a
5faf5a
6f38e5 /*
0a9956 ·* Given a signature of level >= 1, a current trust level, and an allowed
587678 ·* further recursion depth, calculate the signedTrust levels for the key,
fa2c30 ·* and propagate further if level > 1. ·depthLimit tells how many levels
b3bc0c ·* max we can propagate, counting this as one. ·That is used to enforce
3094dc ·* both a maximum limit on how deep this process goes, and for each
71e2f7 ·* MI/MMI etc. to limit how far forward trust goes depending on the
aae4c1 ·* amount of "meta", that is, the level.
3c775e ·*
32271f ·* A level of 0 means an ordinary signature; those aren't considered here.
7b3c14 ·* A level of 1 means a trust signature, typically issued by a meta-
882625 ·* introducer, but also possibly by an axiomatic key. ·Those are applied
1950e1 ·* here to form the signedTrust level on the key. ·A simple maximum is
610a23 ·* used to deal with multiple signed trusts on the key (e.g. if both a
c104e4 ·* MI and the user specified trust on the key).
02a285 ·* A level of 2 means a meta introducer. ·Any trust signatures by him
ab747d ·* get propagated via one level of recursion.
1cd659 ·* Higher levels allow more levels of recursion.
de775e ·*
6f4719 ·* We apply several simplifications which future versions may enhance.
dcee0a ·* We only allow 2nd-level (meta and above) propagation if fully
0bcfeb ·* trusted. ·That is, meta introducers, and the user himself, can specify
02f9b6 ·* partial trust levels. ·But the MI, or an MMI, etc., must be given
52460e ·* full trust. ·In this trust model we can't easily handle gracefully
7f50ad ·* degrading trust.
e6495d ·*/
802978 static void
bb5274 mntApplyTrustSig (RingSig const *sig, RingSet const *set, PGPByte trustValue,
ffa24b ¤   ¤   ¤   ¤   ··PGPUInt32 depthLimit, int thresh, PGPUInt32 timenow)
9abb36 {
92b438 ¤   RingObject¤ ¤   *key;
6a37d3 ¤   PGPByte¤¤   ¤   ·trustVal;
5caf5a
00797f ¤   /* First calculate signed trust on this key. */
c3af5a
205261 ¤   /* Don't count nonexportable sigs by others */
4c609e ¤   if (mntForeignSignature(sig, set))
1199bf ¤   ¤   return;
c0af5a
09fd89 ¤   /* For now support only full trust on meta introducer signatures */
e962de ¤   if (trustValue < thresh && sig->trustLevel >= 2)
8599bf ¤   ¤   return;
c7af5a
7bd8af ¤   /*
6c5e6a ¤   ·* See if trust signature is ruled out by regexp.
dd813f ¤   ·* (Note that this looks not at the sig's regexp, but at any on the
8101fe ¤   ·* signing key. ·E.g. a meta introducer may include a regexp on a sig
506699 ¤   ·* it issues.)
12a4e3 ¤   ·*/
9622ed ¤   if (!mntSigOKWithRegexp( set, sig ) )
a199bf ¤   ¤   return;
26af5a
4c4aed ¤   /* Find signed key */
--08f1 000ba839baf401001f7 Page 30 of pgpRngMnt.c
15b91d ¤   key = sig->up;
9abfad ¤   while (!OBJISTOPKEY(key))
866452 ¤   ¤   key = key->g.up;
1867c5 ¤
7ad8af ¤   /*
2ed9e7 ¤   ·* For now only use the maximum value of signed trusts, don't try
7d84c1 ¤   ·* to accumulate them. ·Thorny problems!
a0a4e3 ¤   ·*/
3fb351 ¤   trustVal = sig->trustValue;
411325 #if PGPTRUSTMODEL==0
21f104 ¤   trustVal = ringTrustExternToOld(set->pool, trustVal);
897454 #endif
96af5a
46d8af ¤   /*
a9a6b3 ¤   ·* Mark trust value. ·If ours is used, copy any regexp associated with
8b8917 ¤   ·* the signature.
82786b ¤   ·* Have some heuristics to compare regexp and non-regexp sigs.
66a4e3 ¤   ·*/
0f2ae9 ¤   if (SIGUSESREGEXP( sig )) {
f0ad26 ¤   ¤   if( key->k.signedTrust > 0 && !key->k.regexp ) {
221bde ¤   ¤   ¤   /* Key already has some non-regexp trust, so leave it */
97a5bf ¤   ¤   } else if (trustVal > key->k.signedTrust) {
2c5354 ¤   ¤   ¤   /* Key had no trust or regexp trust, and we are stronger */
54e6a0 ¤   ¤   ¤   void *rexp = ringSigRegexp( set, (RingObject *)sig );
32ddab ¤   ¤   ¤   /* Abort this chain if some problem parsing regexp */
e7d5ff ¤   ¤   ¤   if (!rexp)
2f7438 ¤   ¤   ¤   ¤   return;
c31b72 ¤   ¤   ¤   key->k.signedTrust = trustVal;
d7c203 ¤   ¤   ¤   key->k.regexp = rexp;
b60fe4 ¤   ¤   }
53f037 ¤   } else {
ff8497 ¤   ¤   if( key->k.regexp || trustVal > key->k.signedTrust ) {
087aad ¤   ¤   ¤   /*
5a0f89 ¤   ¤   ¤   ·* Key had regexp trust, but we don't; or key had no regexp trust,
66f70f ¤   ¤   ¤   ·* but we are stronger.
0b8753 ¤   ¤   ¤   ·*/
fbfde5 ¤   ¤   ¤   key->k.regexp = NULL;
6c1b72 ¤   ¤   ¤   key->k.signedTrust = trustVal;
5d0fe4 ¤   ¤   }
cb9371 ¤   }
3d67c5 ¤
74d8af ¤   /*
561b9e ¤   ·* Then, if level > 1 and we have not reached depthLimit,
e3c9fb ¤   ·* propagate forwards
7aa4e3 ¤   ·*/
85af5a
ba8081 ¤   if (sig->trustLevel > 1 && depthLimit > 1) {
c09546 ¤   ¤   RingSig const *keysig = &key->k.sigsby->s;
e45152 ¤   ¤   while (keysig) {
558be3 ¤   ¤   ¤   RingSig *newestsig;
1c1743 ¤   ¤   ¤   pgpAssert( SIGISSIG( keysig ) );
aa684c ¤   ¤   ¤   newestsig = mntNewestValidSiblingSig(&keysig, set, timenow);
83ea8b ¤   ¤   ¤   /* Skip if not a trust sig */
eaef76 ¤   ¤   ¤   if (newestsig->trustLevel < 1)
8dd040 ¤   ¤   ¤   ¤   continue;
019da9 ¤   ¤   ¤   /* Skip if not a valid key sig */
a15ec2 ¤   ¤   ¤   if (!mntSigIsValidKeySig ((RingObject *)newestsig, set, timenow))
d9d040 ¤   ¤   ¤   ¤   continue;
ec7aad ¤   ¤   ¤   /*
49df5c ¤   ¤   ¤   ·* Here we have a good trust or metaintroducer sig.
807d1d ¤   ¤   ¤   ·* Propagate it forward.
8a8753 ¤   ¤   ¤   ·*/
f92c1b ¤   ¤   ¤   mntApplyTrustSig (newestsig, set, sig->trustValue,
d6b17b ¤   ¤   ¤   ¤   ¤   ·pgpMin(sig->trustLevel-1, (PGPByte)depthLimit-1),
e8cf86 ¤   ¤   ¤   ¤   ¤   ·thresh, timenow);
180fe4 ¤   ¤   }
539371 ¤   }
40efe6 }
e0af5a
5daf5a
533ff4 /********************** Utility Routines * ***************************/
baaf5a
--2df8 00083e15b77401001f7 Page 31 of pgpRngMnt.c
e0af5a
117847 #if SORT_NAMES
8e38e5 /*
28d71d ·* Return 1 if n1 should be listed before n2; 0 if they're
4799ae ·* equivalent and the relative order should be unchanged, and -1
c7b4a5 ·* if it should be the other way around.
a2775e ·*
9a35ff ·* All non-names should be before all names; non-names are left in
073067 ·* their original order.
e4495d ·*/
0ebeb7 static int
8f3ea2 mntCompareNames(union RingObject const *n1, union RingObject const *n2,
880f42 ¤   PGPUInt32 const timenow)
b1bb36 {
3a322d ¤   PGPUInt32 t1, t2;
bec2f5 ¤   union RingObject const *sig;
e14ba4 ¤   int i;
33af5a
972f55 ¤   /* Test 0: non-names always come first */
f0c083 ¤   if (!OBJISNAME(n1))
eccb9e ¤   ¤   return OBJISNAME(n2) ? 1 : 0;
cae54e ¤   if (!OBJISNAME(n2))
37043c ¤   ¤   return -1;
09af5a
59a087 ¤   /* Test 1: more trusted */
6f0cc8 ¤   i = (n1->n.trust & kPGPNameTrust_Mask) -
a61916 ¤   ¤   (n2->n.trust & kPGPNameTrust_Mask);
347177 ¤   if (i)
1c792d ¤   ¤   return i > 0 ? 1 : -1;
1caf5a
3e5fce ¤   /* Test 2: more recent self-signature */
023750 ¤   t1 = 0;
2d8442 ¤   for (sig = n1->g.down; sig; sig = sig->g.next) {
01a9ca ¤   ¤   if (!OBJISSIG(sig) || sig->s.by != n1->g.up)
e48bcb ¤   ¤   ¤   continue;¤  /* Not a self-sig */
704201 ¤   ¤   if ((sig->s.trust & PGP_SIGTRUSTF_CHECKED) == 0)
254314 ¤   ¤   ¤   continue;¤  /* Not valid */
d7e41d ¤   ¤   if (sig->s.tstamp <= t1)
c26a5f ¤   ¤   ¤   continue;¤  /* Too old */
39438d ¤   ¤   if (timenow > sig->s.tstamp &&
ac7fbf ¤   ¤   ¤   (unsigned)((timenow-sig->s.tstamp) / 86400) > sig->s.validity-1u)
07a41d ¤   ¤   ¤   continue;¤  /* expired */
3a7f9c ¤   ¤   t1 = sig->s.tstamp;
b09371 ¤   }
e3af5a
6b9f3e ¤   t2 = 0;
8842b2 ¤   for (sig = n2->g.down; sig; sig = sig->g.next) {
1ba9ca ¤   ¤   if (!OBJISSIG(sig) || sig->s.by != n1->g.up)
878bcb ¤   ¤   ¤   continue;¤  /* Not a self-sig */
a14201 ¤   ¤   if ((sig->s.trust & PGP_SIGTRUSTF_CHECKED) == 0)
b74314 ¤   ¤   ¤   continue;¤  /* Not valid */
2974f8 ¤   ¤   if (sig->s.tstamp <= t2)¤
a66a5f ¤   ¤   ¤   continue;¤  /* Too old */
fb438d ¤   ¤   if (timenow > sig->s.tstamp &&
687fbf ¤   ¤   ¤   (unsigned)((timenow-sig->s.tstamp) / 86400) > sig->s.validity-1u)
9ea41d ¤   ¤   ¤   continue;¤  /* expired */
e9c256 ¤   ¤   t2 = sig->s.tstamp;
5e9371 ¤   }
330ec5 ¤   if (t1 != t2)
490234 ¤   ¤   return (t1 > t2 ? 1 : -1);
1eaf5a
271325 #if PGPTRUSTMODEL==0
ff1b92 ¤   /* Test 3: lower certification depth */
cf1774 ¤   if (NAMELEVEL(&n1->n) != NAMELEVEL(&n2->n)) {
8cb8b8 ¤   ¤   return ((unsigned)NAMELEVEL(&n1->n) - 1u <
52e874 ¤   ¤   ········(unsigned)NAMELEVEL(&n2->n) - 1u) ? 1 : -1;
a39371 ¤   }
b3af5a
566f7b ¤   /* Test 4: more trust accumulated */
ff4a66 ¤   if (n1->n.trustval != n2->n.trustval)
efc1d8 ¤   ¤   return n1->n.trustval > n2->n.trustval ? 1 : -1;
83db21 #else
--cd55 0002a54bfb9401001f7 Page 32 of pgpRngMnt.c
4b8760 ¤   /* Test 3: More certainty */
bcd92b ¤   if (n1->n.valid != n2->n.valid)
a1d8d9 ¤   ¤   return n1->n.valid > n2->n.valid ? 1 : -1;
e6af5a
9d57ad ¤   /* Test 4: lower certification depth */
051774 ¤   if (NAMELEVEL(&n1->n) != NAMELEVEL(&n2->n)) {
eeb8b8 ¤   ¤   return ((unsigned)NAMELEVEL(&n1->n) - 1u <
d7e874 ¤   ¤   ········(unsigned)NAMELEVEL(&n2->n) - 1u) ? 1 : -1;
129371 ¤   }
c57454 #endif
c3af5a
45633a ¤   /* Okay, give up - declare 'em equal */
743e6b ¤   return 0;
08efe6 }
92af5a
d338e5 /*
707ff7 ·* Sort the names in the given list according to a "goodness" measure.
d539df ·* This may result in some keyrings getting dirtied. ·The mask of such
0f96bc ·* keyrings is returned.
2c775e ·*
a53a69 ·* This is a selection sort, not wonderfully efficient, but n^2 is okay
2596e1 ·* for the small n we have here (5 names on a key is pretty unusual!),
766c8b ·* and it makes figuring out which keyrings need dirtying much easier.
3b775e ·*
b5daad ·* The technique is perhaps not entirely obvious, so I'll explain it.
44066e ·* Selection sort involves searching the unsorted list for the object (name)
a6d7d5 ·* that should go first (referred to as the best element in the code), and
1fb854 ·* then removing it and placing it at the end of the (initially empty)
638b3c ·* sorted new list. ·We keep track of the union of the masks of the objects
1d5c5e ·* that the best object skips in front of. ·When we reach the end of the
794ae3 ·* unsorted list, and the best pointer (and the bestmask) is known for
9fdb27 ·* sure, all keyrings which the best object is in and have been skipped
33a7e7 ·* over (i.e. bestmask & best->mask) are dirty.
ab495d ·*/
f5f1ae static PGPError
337ade mntSortNameList(RingPool *pool, union RingObject **objp,
7c00ba ¤   PGPUInt32 const timenow, PGPVirtMask *omask)
c2bb36 {
8c92b0 ¤   union RingObject *newhead, **newtail;
d470c9 ¤   union RingObject *cur, **curp;
c43c9b ¤   union RingObject *best, **bestp;
3ca3f3 ¤   PGPVirtMask curmask, bestmask;
c0c4af ¤   PGPVirtMask dirtymask;
49af5a
1a903a ¤   pgpVirtMaskInit (pool, &curmask);
6ba9dc ¤   pgpVirtMaskInit (pool, &bestmask);
1a922b ¤   pgpVirtMaskInit (pool, &dirtymask);
22c44b ¤   pgpVirtMaskCleanup (pool, omask);
b0af5a
ce0ff4 ¤   newtail = &newhead;
cdaf5a
333682 ¤   /* Loop until unsorted list is empty */
aa08c6 ¤   while (*objp) {
a4a407 ¤   ¤   /* Default best is head of list */
625608 ¤   ¤   bestp = objp;
4b49ad ¤   ¤   best = *bestp;
dfa87b ¤   ¤   pgpVirtMaskCleanup (pool, &bestmask); /* set to zero */
b3af5a
d4a9fc ¤   ¤   /* Search rest of list for a better name */
04c01b ¤   ¤   curp = &best->g.next;
630726 ¤   ¤   pgpVirtMaskCopy (pool, &best->g.mask, &curmask);
4a72b6 ¤   ¤   while ((cur = *curp) != 0) {
703210 ¤   ¤   ¤   if (mntCompareNames(best, cur, timenow) < 0) {
458bf8 ¤   ¤   ¤   ¤   bestp = curp;
6c5a64 ¤   ¤   ¤   ¤   best = cur;
7a7001 ¤   ¤   ¤   ¤   pgpVirtMaskCopy (pool, &curmask, &bestmask);
29a3a6 ¤   ¤   ¤   }
1c52ef ¤   ¤   ¤   pgpVirtMaskOR (pool, &cur->g.mask, &curmask);
ee6f0b ¤   ¤   ¤   curp = &cur->g.next;
9a0fe4 ¤   ¤   }
3aaf5a
2afb9a ¤   ¤   *bestp = best->g.next;
--fb75 000df7c8a97401001f7 Page 33 of pgpRngMnt.c
9eb8b1 ¤   ¤   pgpVirtMaskAND (pool, &best->g.mask, &bestmask);
45c6dd ¤   ¤   pgpVirtMaskOR (pool, &bestmask, &dirtymask);
6e2d43 ¤   ¤   *newtail = best;
8df8b6 ¤   ¤   newtail = &best->g.next;
969371 ¤   }
6c35e0 ¤   *objp = newhead;
8b42b0 ¤   *newtail = NULL;
89617d ¤   pgpVirtMaskCleanup (pool, &curmask);
e09f96 ¤   pgpVirtMaskCleanup (pool, &bestmask);
6eb4c8 ¤   *omask = dirtymask;
8b151e ¤   return kPGPError_NoErr;
b1efe6 }
f5af5a
5d38e5 /*
a64f1f ·* Sort the names of each key under the given mask with the mntSortNameList
b5dafe ·* function. ·The mask applies only to the keys; all names are sorted,
b1342a ·* even if they don't fall under the mask. ·And any keyrings may be dirtied
da0730 ·* by this operation.
02495d ·*/
6c2978 static void
f1da19 mntSortNames(RingSet const *set, PGPUInt32 const timenow)
2abb36 {
0ab957 ¤   union RingObject *key;
84c4af ¤   PGPVirtMask dirtymask;
1fe00f ¤   PGPVirtMask tmpmask;
bcaf5a
f685c9 ¤   pgpVirtMaskInit (set->pool, &dirtymask);
1ca765 ¤   pgpVirtMaskInit (set->pool, &tmpmask);
6daf5a
105f5f ¤   /* Sort all the keys */
294bcd ¤   for (key = set->pool->keys; key; key = key->g.next) {
4ba3aa ¤   ¤   pgpAssert(OBJISKEY(key));
7eb3f6 ¤   ¤   if (pgpIsRingSetMember(set, key)) {
8cab84 ¤   ¤   ¤   dirtymask |= mntSortNameList(set->pool, &key->g.down, timenow,
a6d005 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&tmpmask);
8beb88 ¤   ¤   ¤   pgpVirtMaskOR (set->pool, &tmpmask, &dirtymask);
bb0fe4 ¤   ¤   }
359371 ¤   }
18af5a
7826b9 ¤   /* Deal with the dirtymask */
252861 ¤   ringPoolMarkDirty(set->pool, &dirtymask);
fd415f ¤   pgpVirtMaskCleanup (set->pool, &dirtymask);
143d0b ¤   pgpVirtMaskCleanup (set->pool, &tmpmask);
6eefe6 }
286d6e #endif ·/* SORT_NAMES */
38af5a
c138e5 /*
175705 ·* Add the "interesting" objects under the given parent to the destset.
b64911 ·* An signature is interesting if it's by the given key or by a trusted
759792 ·* introducer. ·A name is interesting if its trust is above a given threshold.
484c4f ·* Anything else (the only real choice is a secret) is by definition
e2be2b ·* interesting.
7f495d ·*/
be1325 #if PGPTRUSTMODEL==0
4f2978 static void
5f7ea3 mntMarkInteresting(union RingObject *obj, union RingObject const *key,
457a83 ¤   int thresh, RingSet const *srcset, RingSet *destset)
5bbb36 {
e98d03 ¤   for (obj = obj->g.down; obj;obj = obj->g.next) {
da6671 ¤   ¤   if (!pgpIsRingSetMember(srcset, obj))
9917f5 ¤   ¤   ¤   continue;
5b3ea3 ¤   ¤   switch(ringObjectType(obj)) {
c97db2 ¤   ¤   ··case RINGTYPE_SIG:
89b9f4 ¤   ¤   ¤   if (obj->s.by == key
9e4da6 ¤   ¤   ¤   ····|| (obj->s.by->g.flags & KEYF_TRUSTED
5d6617 ¤   ¤   ¤   ········&& (obj->s.by->k.trust & kPGPKeyTrust_Mask)
e609f3 ¤   ¤   ¤   ···········>= kPGPKeyTrust_Marginal))
9af622 ¤   ¤   ¤   ¤   break;
d917f5 ¤   ¤   ¤   continue;
5bb4e2 ¤   ¤   ··case RINGTYPE_NAME:
0d030c ¤   ¤   ¤   if (obj->n.trustval >= thresh)
dff622 ¤   ¤   ¤   ¤   break;
--9f83 0005c57cdca401001f7 Page 34 of pgpRngMnt.c
a017f5 ¤   ¤   ¤   continue;
cb1584 ¤   ¤   ··default:
cacdcb ¤   ¤   ¤   break;
320fe4 ¤   ¤   }
bc0a8b ¤   ¤   ringSetAddObject(destset, obj);
e03504 ¤   ¤   if (!OBJISBOT(obj))
078962 ¤   ¤   ¤   mntMarkInteresting(obj, key, thresh, srcset, destset);
409371 ¤   }
feefe6 }
42db21 #else
022978 static void
027ea3 mntMarkInteresting(union RingObject *obj, union RingObject const *key,
cb4984 ¤   ·¤  ···PGPUInt16 thresh, RingSet const *srcset, RingSet *destset)
94bb36 {
ac8d03 ¤   for (obj = obj->g.down; obj;obj = obj->g.next) {
356671 ¤   ¤   if (!pgpIsRingSetMember(srcset, obj))
1517f5 ¤   ¤   ¤   continue;
843ea3 ¤   ¤   switch(ringObjectType(obj)) {
797db2 ¤   ¤   ··case RINGTYPE_SIG:
47b9f4 ¤   ¤   ¤   if (obj->s.by == key
9a4da6 ¤   ¤   ¤   ····|| (obj->s.by->g.flags & KEYF_TRUSTED
edf50d ¤   ¤   ¤   ········&& (obj->s.by->k.confidence > 0)))
bbf622 ¤   ¤   ¤   ¤   break;
fb17f5 ¤   ¤   ¤   continue;
62b4e2 ¤   ¤   ··case RINGTYPE_NAME:
21225e ¤   ¤   ¤   if (obj->n.valid >= thresh)
0ef622 ¤   ¤   ¤   ¤   break;
ed17f5 ¤   ¤   ¤   continue;
071584 ¤   ¤   ··default:
83cdcb ¤   ¤   ¤   break;
1a0fe4 ¤   ¤   }
5c0a8b ¤   ¤   ringSetAddObject(destset, obj);
6f3504 ¤   ¤   if (!OBJISBOT(obj))
368962 ¤   ¤   ¤   mntMarkInteresting(obj, key, thresh, srcset, destset);
2a9371 ¤   }
51efe6 }
aa7454 #endif
15af5a
b7af5a
d83a51 /******************** Trust Propagation Main *************************/
5faf5a
67af5a
dcaf5a
de38e5 /*
5ab2e4 ·* Run the maintenance pass on the keyring. ·At the end, any keys which
211b5d ·* are flagged with KEYF_TRUSTED but still have kPGPKeyTrust_Undefined need
27539e ·* to have their trusts updated. ·Returns the number of such keys, or
dfb94e ·* <0 on error. ·(Currently impossible.)
ee495d ·*/
da4d2f int
320534 ringMnt(RingSet const *set, RingSet *dest, PGPUInt32 const timenow)
1dbb36 {
0bad2e ¤   RingKey const *list;
c9e91d ¤   union RingObject *key, *child;
78a51a ¤   RingSig *sig;
28cf3a ¤   unsigned tmptrust;
640ed5 ¤   unsigned t;
67bea0 ¤   unsigned long count;¤   /* Count of keys needing trust assigned */
c60267 ¤   PGPVirtMask changemask;¤/* Keyrings with altered trust */
276032 ¤   RingPool *pool = set->pool;
b67dec #if PGPTRUSTMODEL>0
a36b1d ¤   PGPUInt16 validity;
94a997 ¤   union RingObject *obj;
00db21 #else
ee266b ¤   int trust[kPGPKeyTrust_Mask + 1];
8c089b ¤   int thresh;
b0adc2 ¤   unsigned level;¤/* Trust level and certification depth */
deaf5a
ded8af ¤   /*
f2f717 ¤   ·* Set up the trust table. ·The non-zero entries are 1/partials,
8bb5da ¤   ·* 1/completes, and 1, all scaled by completes*partials, except
5c1ec0 ¤   ·* that completes or partials set to 0 means "infinite".
--5408 00071917e5b401001f7 Page 35 of pgpRngMnt.c
60a4e3 ¤   ·*/
c08f1b ¤   for (t = 0; t < sizeof(trust)/sizeof(*trust); t++)
3786cd ¤   ¤   trust[t] = 0;
e3e139 ¤   trust[kPGPKeyTrust_Marginal] = 1;
192618 ¤   trust[kPGPKeyTrust_Complete] = 1;
34b256 ¤   trust[kPGPKeyTrust_Ultimate] = 1;
70d46f ¤   if (set->pool->num_marginals) {
8857c3 ¤   ¤   trust[kPGPKeyTrust_Complete] = set->pool->num_marginals;
561683 ¤   ¤   trust[kPGPKeyTrust_Ultimate] = set->pool->num_marginals;
46f037 ¤   } else {
b7870b ¤   ¤   trust[kPGPKeyTrust_Marginal] = 0;
ce9371 ¤   }
6a270b ¤   if (set->pool->num_completes) {
4eeefb ¤   ¤   trust[kPGPKeyTrust_Marginal] = set->pool->num_completes;
92ab4a ¤   ¤   trust[kPGPKeyTrust_Ultimate] *= set->pool->num_completes;
c9f037 ¤   } else {
26402a ¤   ¤   trust[kPGPKeyTrust_Complete] = 0;
6c9371 ¤   }
18acac ¤   thresh = trust[kPGPKeyTrust_Ultimate];
fa7454 #endif
e0af5a
fba9b0 ¤   pgpVirtMaskInit (set->pool, &changemask);
e3af5a
9dfba1 ¤   pgpAssert(!dest || set->pool == dest->pool);
5f6c09 ¤   pgpAssert(!dest || RINGSETISMUTABLE(dest));
36af5a
6ad8af ¤   /*
01b9a8 ¤   ·* Preprocessing: reset all name trusts to 0, and initialize list
7445e0 ¤   ·* of trusted keys to the axiomatic ones.
9fa4e3 ¤   ·*/
8e0eaf ¤   list = 0;
994bcd ¤   for (key = set->pool->keys; key; key = key->g.next) {
eea3aa ¤   ¤   pgpAssert(OBJISKEY(key));
9c639f ¤   ¤   if (!pgpIsRingSetMember(set, key))
ca17f5 ¤   ¤   ¤   continue;
c3af5a
8a6b32 ¤   ¤   key->g.flags &= ~KEYF_TRUSTED;
dddf5a ¤   ¤   key->k.signedTrust = 0;
dc2095 #if PGPTRUSTMODEL==2
1404dc ¤   ¤   CLEARLOOKINGAT(&key->k);
c27454 #endif
283344 ¤   ¤   for (child = key->k.down; child; child = child->g.next) {
a47e7e ¤   ¤   ¤   if (pgpIsRingSetMember(set, child) && OBJISNAME(child)) {
321325 #if PGPTRUSTMODEL==0
0562d5 ¤   ¤   ¤   ¤   child->n.trustval = 0;
8edb21 #else
976385 ¤   ¤   ¤   ¤   child->n.valid = 0;
ee7454 #endif
af06f6 ¤   ¤   ¤   ¤   NAMESETLEVEL(&child->n, 0);
50a3a6 ¤   ¤   ¤   }
4f0fe4 ¤   ¤   }
a11b17 ¤   ¤   /*
2adc93 ¤   ¤   ·* Find each key's revoked status - find
f9a420 ¤   ¤   ·* the most important self-signature.
279de3 ¤   ¤   ·*/
f44896 ¤   ¤   sig = 0;
577a7c ¤   ¤   for (child = key->g.down; child; child = child->g.next) {
e87aad ¤   ¤   ¤   /*
2356da ¤   ¤   ¤   ·* Ignore sigs by others, unchecked sigs,
6c9b72 ¤   ¤   ¤   ·* postdated sigs, and expired sigs.
9897e8 ¤   ¤   ¤   ·* @@@ TODO: change the CHECKED and TRIED bits
c96e9a ¤   ¤   ¤   ·* For untried revocation sigs, accept them if key's
2684a2 ¤   ¤   ¤   ·* trust bits already show it as revoked. ·PGP 2 does
3ceaca ¤   ¤   ¤   ·* not store trust packets on revocation signatures, and so
b5cc1e ¤   ¤   ¤   ·* neither does this library, to avoid crashing older PGP's
c877fa ¤   ¤   ¤   ·* when they are run on our keyrings.
108753 ¤   ¤   ¤   ·*/
47b7c8 ¤   ¤   ¤   if (pgpIsRingSetMember(set, child)
5a371f ¤   ¤   ¤   ¤   && OBJISSIG(child)
375c5d ¤   ¤   ¤   ····&& mntSigIsValid(timenow, child->s.tstamp,
200d3f ¤   ¤   ¤   ······················child->s.validity)) {
71af5a
--71e6 000daafce46401001f7 Page 36 of pgpRngMnt.c
b6ed3b ¤   ¤   ¤   ····/* Any revocation certificate wins, period. */
75e8a6 ¤   ¤   ¤   ¤   if (sigRevokesKey(set, child)) {
f9dcf6 ¤   ¤   ¤   ¤   ····sig = &child->s;
0214c3 ¤   ¤   ¤   ¤   ¤   break;
182613 ¤   ¤   ¤   ¤   }
40bf28 ¤   ¤   ¤   ¤   /* Among others, choose the most recent */
25ed53 ¤   ¤   ¤   ¤   if (!sig ||
05ce2c ¤   ¤   ¤   ¤   ¤   sig->tstamp < child->s.tstamp)
85dcf6 ¤   ¤   ¤   ¤   ····sig = &child->s;
9aa3a6 ¤   ¤   ¤   }
950fe4 ¤   ¤   }
65af5a
9f74b4 ¤   ¤   tmptrust = key->k.trust;
a5c007 ¤   ¤   /* Revocation is a function of revocation certificates.
cd3444 ¤   ¤   ···Make sure axiomatic (buckstop) bit is not set. */
af6bda ¤   ¤   if (sig && sig->type == PGP_SIGTYPE_KEY_REVOKE) {
a8dead ¤   ¤   ¤   tmptrust &= ~(PGP_KEYTRUSTF_BUCKSTOP | kPGPKeyTrust_Mask);
55dbb3 ¤   ¤   ¤   tmptrust |= kPGPKeyTrust_Never | PGP_KEYTRUSTF_REVOKED;
cf0fe4 ¤   ¤   }
820e1d ¤   ¤   else
d05681 ¤   ¤   ¤   tmptrust &= ~PGP_KEYTRUSTF_REVOKED;
85af5a
62435b ¤   ¤   /* Check if key has expired */
2a7635 ¤   ¤   if (key->k.tstamp < timenow && key->k.validity > 0 &&
e1f51e ¤   ¤   ¤   ·(unsigned)((timenow - key->k.tstamp)/86400) >= key->k.validity) {
37dead ¤   ¤   ¤   tmptrust &= ~(PGP_KEYTRUSTF_BUCKSTOP | kPGPKeyTrust_Mask);
238973 ¤   ¤   ¤   tmptrust |= kPGPKeyTrust_Never | PGP_KEYTRUSTF_EXPIRED;
490fe4 ¤   ¤   }
460e1d ¤   ¤   else
720441 ¤   ¤   ¤   tmptrust &= ~PGP_KEYTRUSTF_EXPIRED;
e2af5a
8b9a5f ¤   ¤   if (key->k.trust != tmptrust) {
1bf6fc ¤   ¤   ¤   key->k.trust = (PGPByte)tmptrust;
90093c ¤   ¤   ¤   key->g.flags |= (RINGOBJF_TRUST | RINGOBJF_TRUSTCHANGED);
773ae8 ¤   ¤   ¤   pgpVirtMaskOR (pool, &key->g.mask, &changemask);
740fe4 ¤   ¤   }
5caf5a
d521a9 ¤   ¤   /* ·Check any subkeys for revocation or expiration. ·*/
b77a7c ¤   ¤   for (child = key->g.down; child; child = child->g.next) {
baa644 ¤   ¤   ····if (pgpIsRingSetMember(set, child) && OBJISSUBKEY(child)) {
03e47d ¤   ¤   ¤   ····tmptrust = child->k.trust;
d7f858 ¤   ¤   ¤   ¤   tmptrust &= ~(PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED);
b5d017 ¤   ¤   ¤   ¤   for (sig = (RingSig *) child->g.down; sig;·
6517d0 ¤   ¤   ¤   ¤   ¤   ·sig = (RingSig *) sig->next) {
516e2f ¤   ¤   ¤   ········if (SIGISSIG(sig) &&
c14a2a ¤   ¤   ¤   ¤   ¤   ¤   sigRevokesKey(set, (RingObject *)sig) &&
2b6563 ¤   ¤   ¤   ¤   ¤   ¤   mntSigIsValid (timenow, sig->tstamp,
891be1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···sig->validity)) {
d69a2b ¤   ¤   ¤   ¤   ········tmptrust |= PGP_KEYTRUSTF_REVOKED;
7a00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
c01c89 ¤   ¤   ¤   ¤   ¤   }
ea2613 ¤   ¤   ¤   ¤   }
e1311b ¤   ¤   ¤   ¤   if (child->k.tstamp < timenow && child->k.validity > 0 &&
65a510 ¤   ¤   ¤   ¤   ¤   ·(unsigned)((timenow - child->k.tstamp)/86400) >=·
d44066 ¤   ¤   ¤   ¤   ¤   ·child->k.validity)
e5cfd0 ¤   ¤   ¤   ········tmptrust |= PGP_KEYTRUSTF_EXPIRED;
932b85 ¤   ¤   ¤   ¤
e80246 ¤   ¤   ¤   ¤   if (child->k.trust != tmptrust) {
608ca5 ¤   ¤   ¤   ¤   ····child->k.trust = (PGPByte) tmptrust;
452d9a ¤   ¤   ¤   ¤   ¤   child->g.flags |= (RINGOBJF_TRUST | RINGOBJF_TRUSTCHANGED);
ec9eea ¤   ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &child->g.mask, &changemask);
b22613 ¤   ¤   ¤   ¤   }
75a3a6 ¤   ¤   ¤   }
ba0fe4 ¤   ¤   }
39af5a
a6d367 ¤   ¤   /* Search for axiomatic keys at root of graph. ·Buckstop bit must be·
8dcac9 ¤   ¤   ···set, and key must not be revoked or expired. */
abf54c ¤   ¤   if (pgpIsRingSetMember(set, key)
702c62 ¤   ¤   ····&& key->k.trust & PGP_KEYTRUSTF_BUCKSTOP
bbd77e ¤   ¤   ····&& !(key->k.trust & (PGP_KEYTRUSTF_REVOKED|PGP_KEYTRUSTF_EXPIRED))
9a1bfd /*¤ ¤   ····&& !(key->k.trust & PGP_KEYTRUSTF_DISABLED) */¤ )
da5b34 ¤   ¤   {
--29b5 000c84cd706401001f7 Page 37 of pgpRngMnt.c
f4e057 ¤   ¤   ····/* Make sure key marked as axiomatic has a secret component.
9f4aeb ¤   ¤   ¤   ···(This may not be true if a public keyring is opened, but
90660e ¤   ¤   ¤   ···*not* its corresponding secret keyring). If not, reset
ac2374 ¤   ¤   ¤   ···the buckstop bit and set trust to 'never'. */
5fc730 ¤   ¤   ····tmptrust = key->k.trust & ~PGP_KEYTRUSTF_BUCKSTOP;
cf6618 ¤   ¤   ····for (child = key->g.down; child; child = child->g.next) {
6db2c2 ¤   ¤   ¤   ····if (OBJISSEC(child) && pgpIsRingSetMember(set, child)) {
485e06 ¤   ¤   ¤   ¤   ····tmptrust |= PGP_KEYTRUSTF_BUCKSTOP;
8c7678 ¤   ¤   ¤   ¤   ¤   break; ·····/* secret component found */
612613 ¤   ¤   ¤   ¤   }
50a3a6 ¤   ¤   ¤   }
118fe1 ¤   ¤   ¤   if (!(tmptrust & PGP_KEYTRUSTF_BUCKSTOP)) {
0c8627 ¤   ¤   ¤   ····/* Don't have private key */ ·
022c2b ¤   ¤   ¤   ····tmptrust &= ~kPGPKeyTrust_Mask;
b278ae ¤   ¤   ¤   ¤   tmptrust |= kPGPKeyTrust_Never;
892e53 ¤   ¤   ¤   ····key->k.trust = tmptrust;
a6e0c1 ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &key->g.mask, &changemask);
f71f8a ¤   ¤   ¤   ¤   key->g.flags |= (RINGOBJF_TRUST | RINGOBJF_TRUSTCHANGED);
e1a3a6 ¤   ¤   ¤   }
92e543 ¤   ¤   ¤   else {
f1551e ¤   ¤   ¤   ····/* Yes, we do have private key */·
463db1 #if PRINT_PROGRESS
d6b001 ¤   ¤   ¤   ····ringKeyPrint(stdout, "Axiomatic key: ", set, key);
b17454 #endif
18ec1e ¤   ¤   ¤   ¤   key->k.util = (RingKey *)list;
85ead3 ¤   ¤   ¤   ¤   list = &key->k;
ed59e2 ¤   ¤   ¤   ¤   key->g.flags |= KEYF_TRUSTED;
2f1325 #if PGPTRUSTMODEL==0
407aaa ¤   ¤   ¤   ¤   /* ·Axiomatic key should have ultimate trust */
1964a5 ¤   ¤   ¤   ¤   if ((key->k.trust & kPGPKeyTrust_Mask) !=·
3adfc3 ¤   ¤   ¤   ¤   ¤   ····························kPGPKeyTrust_Ultimate) {
0b1df7 ¤   ¤   ¤   ¤   ····key->k.trust &= ~kPGPKeyTrust_Mask;
f2c517 ¤   ¤   ¤   ¤   ¤   key->k.trust |= kPGPKeyTrust_Ultimate;
5b6a84 ¤   ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &key->g.mask, &changemask);
5866c0 ¤   ¤   ¤   ¤   ¤   key->g.flags |= (RINGOBJF_TRUST | RINGOBJF_TRUSTCHANGED);
512613 ¤   ¤   ¤   ¤   }
b1db21 #else
3a7ec9 ¤   ¤   ¤   ¤   for (child = key->g.down;child;child = child->g.next) {
cfe6dd ¤   ¤   ¤   ¤   ····if (OBJISNAME(child))
09a967 ¤   ¤   ¤   ¤   ¤   ····child->n.valid = (PGPUInt16) PGP_TRUST_INFINITE;
c12613 ¤   ¤   ¤   ¤   }
25b8d3 #endif /* PGPTRUSTMODEL>0 */
9ea3a6 ¤   ¤   ¤   }
de0fe4 ¤   ¤   }
f59371 ¤   }
3daf5a
2d0811 ¤   /* The actual trust computation */
00af5a
10b232 ¤   ringPoolListSigsBy(set->pool);¤ /* Canonicalize these pointers */
d5af5a
5a9c41 ¤   /* Propagate meta introducer trust forwards first */
0c0eea ¤   /* At this point, "list" contains axiomatic keys */
ce67c5 ¤
abc7a1 ¤   {
afabc5 ¤   ¤   RingKey const *axkey;
92eafd ¤   ¤   for (axkey = list; axkey; axkey = axkey->util) {
fcb888 ¤   ¤   ¤   RingSig const *axsig = &axkey->sigsby->s;
d9ae72 ¤   ¤   ¤   while (axsig) {
f7001f ¤   ¤   ¤   ¤   RingSig *newestsig;
e061fd ¤   ¤   ¤   ¤   pgpAssert( SIGISSIG( axsig ) );
c75447 ¤   ¤   ¤   ¤   newestsig = mntNewestValidSiblingSig(&axsig, set, timenow);
5dd34e ¤   ¤   ¤   ¤   /* Skip if not a trust sig */
647eee ¤   ¤   ¤   ¤   if (newestsig->trustLevel < 1)
085914 ¤   ¤   ¤   ¤   ¤   continue;
75d297 ¤   ¤   ¤   ¤   /* Skip if not a valid key sig */
bdf783 ¤   ¤   ¤   ¤   if (!mntSigIsValidKeySig ((RingObject *)newestsig,
ffdbbc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··set, timenow))
8b5914 ¤   ¤   ¤   ¤   ¤   continue;
7a980e ¤   ¤   ¤   ¤   /*
89597e ¤   ¤   ¤   ¤   ·* Here we have a good trust or metaintroducer signature by us.
f878f0 ¤   ¤   ¤   ¤   ·* Propagate it forward.
c81020 ¤   ¤   ¤   ¤   ·*/
--0982 00010477e5f401001f7 Page 38 of pgpRngMnt.c
e063d0 ¤   ¤   ¤   ¤   mntApplyTrustSig (newestsig, set, PGP_NEWTRUST_INFINITE,
64f8d7 ¤   ¤   ¤   ¤   ¤   ¤   set->pool->certdepth, set->pool->completeconfidence,
cdf15e ¤   ¤   ¤   ¤   ¤   ¤   timenow);
38a3a6 ¤   ¤   ¤   }
5e0fe4 ¤   ¤   }
1f9371 ¤   }
3daf5a
fd2095 #if PGPTRUSTMODEL==2
78af5a
58c7a1 ¤   {
a2a5c6 ········PathList ······*pathlist = NULL;
2e3d2e ········RingObject ····*name;
d5da5e ¤   ¤   RingSet¤¤   ···*confidentset;
935501 ········unsigned ·······maxdepth = set->pool->certdepth;
566e04 ········double ·········confidence;
fcaf5a
9424e5 ¤   ¤   confidentset = ringSetConfidentSet (set);
47a9cd ¤   ¤   for (key = set->pool->keys; key; key = key->g.next) {
4b4cd9 ¤   ¤   ¤   pgpAssert(OBJISKEY(key));
8cf207 ¤   ¤   ¤   if (!pgpIsRingSetMember(set, key))
7ed040 ¤   ¤   ¤   ¤   continue;
02af5a
0c3922 ¤   ¤   ¤   for (name = key->g.down; name; name = name->g.next) {
330fc2 ¤   ¤   ¤   ¤   if (!OBJISNAME(name) || !pgpIsRingSetMember(set, name))
915914 ¤   ¤   ¤   ¤   ¤   continue;
bdf7f3 ¤   ¤   ¤   ¤   /* ·Calculate "real" validity for names. ·If the key
2723e9 ¤   ¤   ¤   ¤   ¤   is axiomatic, this will be overidden when the·
f094fe ¤   ¤   ¤   ¤   ¤   validity is returned by¤ringNameValidity. */
15b177 #if 0
e20b1c ¤   ¤   ¤   ¤   if (key->k.trust & PGP_KEYTRUSTF_BUCKSTOP
d14e86 ¤   ¤   ¤   ¤   ¤   && !(key->k.trust &
028fe4 ¤   ¤   ¤   ¤   ¤   ¤   ·(PGP_KEYTRUSTF_REVOKED|PGP_KEYTRUSTF_EXPIRED)
ac3341 ¤   ¤   ¤   ¤   ¤   /* && !(key->k.trust & PGP_KEYTRUSTF_DISABLED) */)) {
65d42f ¤   ¤   ¤   ¤   ¤   name->n.valid = PGP_TRUST_INFINITE;
c85914 ¤   ¤   ¤   ¤   ¤   continue;
ea2613 ¤   ¤   ¤   ¤   }
8e7454 #endif
ff980e ¤   ¤   ¤   ¤   /*
8146ab ¤   ¤   ¤   ¤   ·* Find all paths back from this name, among only trusted
20e625 ¤   ¤   ¤   ¤   ·* introducers, to an axiomatic key.
6c6d73 ¤   ¤   ¤   ¤   ·* (We are scaling up maxdepth because the other algorithms
57c3f0 ¤   ¤   ¤   ¤   ·* have no limit).
a61020 ¤   ¤   ¤   ¤   ·*/
97b73d ¤   ¤   ¤   ¤   ringFindPathsBack (name, &pathlist, maxdepth*2,
e07f20 ¤   ¤   ¤   ¤   ¤   confidentset, set, timenow, set->pool);
ab3661 ¤   ¤   ¤   ¤   if (pathlist) {
23b295 ¤   ¤   ¤   ¤   ¤   pathlist = pathListPrune (pathlist, TOTALPATHMAX,
79d82f ¤   ¤   ¤   ¤   ¤   ·············set->pool);
233aea #ifdef DEBUGPATH
677b81 ¤   ¤   ¤   ¤   ¤   fprintf (stdout, "Found path for ");
695ef0 ¤   ¤   ¤   ¤   ¤   ringTtyPrintKey (stdout, key, set->pool);
1603c1 ¤   ¤   ¤   ¤   ¤   fprintf (stdout, "\n");
927454 #endif
856a1a ¤   ¤   ¤   ¤   ¤   confidence = pathListConfidence (pathlist, set->pool);
dfd2f0 ¤   ¤   ¤   ¤   ¤   if (confidence >= 1.)
155b78 ¤   ¤   ¤   ¤   ¤   ¤   name->n.valid = PGP_TRUST_INFINITE;
1f4bd6 ¤   ¤   ¤   ¤   ¤   else
4de120 ¤   ¤   ¤   ¤   ¤   ¤   name->n.valid = ringDoubleToTrust (1. /
eda4e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(1.-confidence));
e565c3 ¤   ¤   ¤   ¤   ¤   pathListFreeAll (pathlist, set->pool);
7e2b99 ¤   ¤   ¤   ¤   ¤   pathlist = NULL;
c32613 ¤   ¤   ¤   ¤   }
83a3a6 ¤   ¤   ¤   }
fe0fe4 ¤   ¤   }
9fb794 ¤   ¤   memPoolEmpty(&set->pool->pathpool);
3785cd ¤   ¤   set->pool->paths = NULL;
7a2590 ¤   ¤   set->pool->pathlists = NULL;
a56537 ¤   ¤   ringSetDestroy (confidentset);
a99371 ¤   }
8787c7 ¤   ¤   ¤
9dcfad #else /* PGPTRUSTMODEL!=2 */
10af5a
--3ce8 000dd830c47401001f7 Page 39 of pgpRngMnt.c
e98995 ¤   /* Propagate the trust upwards */
062875 ·¤  t = (unsigned)set->pool->certdepth;
782d8f ¤   for (level = 1; list && level < t; level++) {
ef3db1 #if PRINT_PROGRESS
d16e39 ¤   ¤   printf("\nProcessing certification level %d\n", level);
187454 #endif
d11325 #if PGPTRUSTMODEL==0
f38287 ¤   ¤   list = mntList(list, set, trust, thresh, timenow, level);
22db21 #else
d5bf33 ¤   ¤   list = mntList(list, set, timenow, level);
ef7454 #endif
e59371 ¤   }
fbd5c8 #endif /* PGPTRUSTMODEL */
60af5a
aa14bc ¤   /* Postprocessing: set the various trust bytes, */
da381c ¤   count = 0;
a01325 #if PGPTRUSTMODEL==0
d44bcd ¤   for (key = set->pool->keys; key; key = key->g.next) {
72639f ¤   ¤   if (!pgpIsRingSetMember(set, key))
8d17f5 ¤   ¤   ¤   continue;
a9fb62 ¤   ¤   /* Set the key trust bytes */
e84bc6 ¤   ¤   t = key->k.trust;
122096 ¤   ¤   if (t & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED)) {
9c26fe ¤   ¤   ¤   tmptrust = kPGPKeyTrust_Never;
010fe4 ¤   ¤   }
54a5d4 #if ONLY_TRUST_VALID_KEYS
fa9cc6 ······¤ else if (!(key->k.flags & KEYF_TRUSTED)) {
d1ee1c ¤   ¤   ¤   tmptrust = kPGPKeyTrust_Undefined;·
090fe4 ¤   ¤   }
fc3199 #endif·
dfe6bf ········else if ((tmptrust = (t&kPGPKeyTrust_Mask)) ==
d8239f ¤   ¤   ¤   ¤   ·kPGPKeyTrust_Undefined) {
0417b8 ¤   ¤   ¤   /* Key in need of a trust decision */
daae59 ¤   ¤   ¤   count++;
6c254e ¤   ¤   ¤   /* Record the key as interesting */
2054bb ¤   ¤   ¤   if (dest) {
1cc599 ¤   ¤   ¤   ¤   ringSetAddObject(dest, key);
b1b43e ¤   ¤   ¤   ¤   mntMarkInteresting(key, key, thresh, set, dest);
3fa3a6 ¤   ¤   ¤   }
0b0fe4 ¤   ¤   }
dcaf5a
c351ca ¤   ¤   t = tmptrust | (key->k.trust & ~kPGPKeyTrust_Mask);
52563a ¤   ¤   if (key->k.trust != t) {
317bf0 ¤   ¤   ¤   key->k.trust = t;
c21f79 ¤   ¤   ¤   key->g.flags |= RINGOBJF_TRUSTCHANGED;
b33ae8 ¤   ¤   ¤   pgpVirtMaskOR (pool, &key->g.mask, &changemask);
a60fe4 ¤   ¤   }
78eba0 ¤   ¤   key->g.flags |= RINGOBJF_TRUST;
04af5a
21d2de ¤   ¤   /* Set the signature trusts to match the key */
111cc6 ¤   ¤   for (sig = &key->k.sigsby->s; sig; sig = sig->nextby) {
e6d1b4 ¤   ¤   ¤   if (!pgpIsRingSetMember(set, (RingObject *)sig))
9dd040 ¤   ¤   ¤   ¤   continue;
491678 ¤   ¤   ¤   /* Trust is either key's, or NEVER if it's a bad sig */
11c726 ¤   ¤   ¤   t = sig->trust & ~kPGPKeyTrust_Mask;
9b0bd2 ¤   ¤   ¤   if (sig->trust & PGP_SIGTRUSTF_CHECKED)
34dd80 ¤   ¤   ¤   ¤   t |= tmptrust;
b2bb8c ¤   ¤   ¤   else
fe0cb3 ¤   ¤   ¤   ¤   t |= kPGPKeyTrust_Never;
9d7658 ¤   ¤   ¤   if (sig->trust != t)
e2f776 ¤   ¤   ¤   {
ca9a9d ¤   ¤   ¤   ¤   sig->trust = t;
99be07 ¤   ¤   ¤   ¤   sig->flags |= RINGOBJF_TRUSTCHANGED;
9b5043 ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &sig->mask, &changemask);
18a3a6 ¤   ¤   ¤   }
a4084e ¤   ¤   ¤   sig->flags |= RINGOBJF_TRUST;
5c0fe4 ¤   ¤   }
3eaf5a
23e87f ¤   ¤   /* Update each name's trust byte */
fe3344 ¤   ¤   for (child = key->k.down; child; child = child->g.next) {
3a78da ¤   ¤   ¤   if (!pgpIsRingSetMember(set, child) || !OBJISNAME(child))
ddd040 ¤   ¤   ¤   ¤   continue;
--be53 0000f6af14d401001f7 Page 40 of pgpRngMnt.c
b10f47 ¤   ¤   ¤   t = child->n.trust & ~kPGPNameTrust_Mask;
1ac641 ¤   ¤   ¤   if (key->k.trust & PGP_KEYTRUSTF_REVOKED)
55f37c ¤   ¤   ¤   ¤   t |= kPGPNameTrust_Untrusted;
bf14a8 ¤   ¤   ¤   else if (child->n.trustval >= thresh)
31fc2d ¤   ¤   ¤   ¤   t |= kPGPNameTrust_Complete;
fd0c51 ¤   ¤   ¤   else if (2 * child->n.trustval >= thresh)
195c9b ¤   ¤   ¤   ¤   t |= kPGPNameTrust_Marginal;
7cbb8c ¤   ¤   ¤   else
37f37c ¤   ¤   ¤   ¤   t |= kPGPNameTrust_Untrusted;
59af5a
5f8b35 ¤   ¤   ¤   if (child->n.trust != t) {
ec0e4a ¤   ¤   ¤   ¤   child->n.trust = t;
9472eb ¤   ¤   ¤   ¤   child->g.flags |= RINGOBJF_TRUSTCHANGED;
668d66 ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &child->g.mask, &changemask);
99a3a6 ¤   ¤   ¤   }
c247b8 ¤   ¤   ¤   child->g.flags |= RINGOBJF_TRUST;
ea0fe4 ¤   ¤   }
cc9371 ¤   }
6a6ba4 #else /* PGPTRUSTMODEL>0 */
7baf5a
54edec ¤   /* Note: For the new trust model, we need to find keys that
bd434b ¤   ···have interesting names, as trust is no longer assigned to
349f7a ¤   ···the key, but to each name. ·*/
d1af5a
824bcd ¤   for (key = set->pool->keys; key; key = key->g.next) {
4e639f ¤   ¤   if (!pgpIsRingSetMember(set, key))
bc17f5 ¤   ¤   ¤   continue;
35af5a
0f9c61 ¤   ¤   /* Set the key trust bytes. ·The overall confidence
a17a0b ¤   ¤   ···value must be calculated (k.confidence contains
944b30 ¤   ¤   ···the first-pass confidence value prior to this point) */
c6af5a
49afad ¤   ¤   key->k.confidence = calctrust(&key->k, set);
2f4bc6 ¤   ¤   t = key->k.trust;
4fd71c ¤   ¤   if (t & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED)
5a925d ¤   ¤   ····|| !(key->k.flags & KEYF_TRUSTED)) {
076e74 ¤   ¤   ¤   key->k.confidence = 0;
130fe4 ¤   ¤   }
33ebb1 ¤   ¤   else if (key->k.confidence == 0) {
7faf5a
187031 ¤   ¤   ¤   /* If at least one name has undefined confidence,
9601b4 ¤   ¤   ¤   ···mark the key as interesting. */
7daf5a
f9a794 ¤   ¤   ¤   for (obj = key->k.down; obj; obj = obj->g.next) {
a2aec1 ¤   ¤   ¤   ¤   if (OBJISNAME(obj) &&
1cb413 ¤   ¤   ¤   ¤   ···obj->n.confidence==PGP_NEWTRUST_UNDEFINED) {
572bd5 ¤   ¤   ¤   ¤   ¤   count++;
95e6a3 ¤   ¤   ¤   ¤   ¤   /* Record the key as interesting */
180f80 ¤   ¤   ¤   ¤   ¤   if (dest) {
c6c41f ¤   ¤   ¤   ¤   ¤   ¤   ringSetAddObject(dest, key);
df7833 ¤   ¤   ¤   ¤   ¤   ¤   mntMarkInteresting(key, key, 0, set, dest);
481c89 ¤   ¤   ¤   ¤   ¤   }
1c14c3 ¤   ¤   ¤   ¤   ¤   break;
3d2613 ¤   ¤   ¤   ¤   }
1b2bf6 ¤   ¤   ¤   } /* end for */
730fe4 ¤   ¤   }
3aaf5a
288641 ¤   ¤   tmptrust = key->k.trust & kPGPKeyTrust_Mask;
d5d2de ¤   ¤   /* Set the signature trusts to match the key */
921cc6 ¤   ¤   for (sig = &key->k.sigsby->s; sig; sig = sig->nextby) {
0ad1b4 ¤   ¤   ¤   if (!pgpIsRingSetMember(set, (RingObject *)sig))
75d040 ¤   ¤   ¤   ¤   continue;
a61678 ¤   ¤   ¤   /* Trust is either key's, or NEVER if it's a bad sig */
8ac726 ¤   ¤   ¤   t = sig->trust & ~kPGPKeyTrust_Mask;
e60bd2 ¤   ¤   ¤   if (sig->trust & PGP_SIGTRUSTF_CHECKED)
d1dd80 ¤   ¤   ¤   ¤   t |= tmptrust;
6cbb8c ¤   ¤   ¤   else
fa0cb3 ¤   ¤   ¤   ¤   t |= kPGPKeyTrust_Never;
5a7658 ¤   ¤   ¤   if (sig->trust != t)
44f776 ¤   ¤   ¤   {
009a9d ¤   ¤   ¤   ¤   sig->trust = t;
0fbe07 ¤   ¤   ¤   ¤   sig->flags |= RINGOBJF_TRUSTCHANGED;
--1c04 000594d01c5401001f7 Page 41 of pgpRngMnt.c
f35043 ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &sig->mask, &changemask);
43a3a6 ¤   ¤   ¤   }
33084e ¤   ¤   ¤   sig->flags |= RINGOBJF_TRUST;
6b0fe4 ¤   ¤   }
aaaf5a
76dea8 ¤   ¤   /* Update each name's validity byte */
f93344 ¤   ¤   for (child = key->k.down; child; child = child->g.next) {
ec78da ¤   ¤   ¤   if (!pgpIsRingSetMember(set, child) || !OBJISNAME(child))
acd040 ¤   ¤   ¤   ¤   continue;
cbc641 ¤   ¤   ¤   if (key->k.trust & PGP_KEYTRUSTF_REVOKED)
b8d083 ¤   ¤   ¤   ¤   validity = 0;
98bc8a ¤   ¤   ¤   else if (child->n.valid == PGP_TRUST_INFINITE)
216c89 ¤   ¤   ¤   ¤   validity = PGP_NEWTRUST_INFINITE;
6fe543 ¤   ¤   ¤   else {
372bad ¤   ¤   ¤   ¤   validity = child->n.valid >> TRUST_CERTSHIFT;
3639ce ¤   ¤   ¤   ¤   if (validity > PGP_NEWTRUST_MAX)
fbe610 ¤   ¤   ¤   ¤   ¤   ··validity = PGP_NEWTRUST_MAX;
56a3a6 ¤   ¤   ¤   }
4d0fe7 ¤   ¤   ¤   if (validity != child->n.validity) {
070cab ¤   ¤   ¤   ¤   child->n.validity = (PGPByte) validity;
1972eb ¤   ¤   ¤   ¤   child->g.flags |= RINGOBJF_TRUSTCHANGED;
2a8d66 ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &child->g.mask, &changemask);
f4a3a6 ¤   ¤   ¤   }
38af5a
132429 ¤   ¤   ¤   /* Convert back to old KEYLEGIT values. */
4ab465 ¤   ¤   ¤   if (validity >= set->pool->threshold)
28c9e6 ¤   ¤   ¤   ¤   tmptrust = kPGPNameTrust_Complete;
c92484 ¤   ¤   ¤   else if (validity >= set->pool->threshold/2)
036950 ¤   ¤   ¤   ¤   tmptrust = kPGPNameTrust_Marginal;
9dbb8c ¤   ¤   ¤   else
438b96 ¤   ¤   ¤   ¤   tmptrust = kPGPNameTrust_Untrusted;
e0e453 ¤   ¤   ¤   t = tmptrust | (child->n.trust & ~kPGPNameTrust_Mask);
f162b0 ¤   ¤   ¤   if (t != child->n.trust) {
680e4a ¤   ¤   ¤   ¤   child->n.trust = t;
9772eb ¤   ¤   ¤   ¤   child->g.flags |= RINGOBJF_TRUSTCHANGED;
238d66 ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &child->g.mask, &changemask);
0da3a6 ¤   ¤   ¤   }
69af5a
435703 ¤   ¤   ¤   /* Reset n.valid with adjusted value. */
9422ba ¤   ¤   ¤   if (child->n.validity == PGP_NEWTRUST_INFINITE)
6b10fd ¤   ¤   ¤   ¤   child->n.valid = PGP_TRUST_INFINITE;
8fbb8c ¤   ¤   ¤   else
409040 ¤   ¤   ¤   ¤   child->n.valid =·
3720c0 ¤   ¤   ¤   ¤   ····child->n.validity << TRUST_CERTSHIFT;
8447b8 ¤   ¤   ¤   child->g.flags |= RINGOBJF_TRUST;
850fe4 ¤   ¤   }
8d9371 ¤   }
077454 #endif
7aaf5a
47e98b ¤   /* Clean up after regexp processing */
e1891c ¤   mntClearKeyRegexps( set );
11af5a
1665d7 ¤   /* Rebuild the hash table */
d3f43e ¤   ringPoolHash(set->pool);
75af5a
ce3f65 ¤   /* Mark all keyrings under "changemask" as having had trust change */
2e85c9 ¤   ringPoolMarkTrustChanged(set->pool, &changemask);
d258cb ¤   pgpVirtMaskCleanup (set->pool, &changemask);
d2af5a
9a2c98 ¤   /* Sort the names @@@ do we want this? ·Not for now... */
617847 #if SORT_NAMES
cebb27 ¤   mntSortNames(set, timenow);
3a7454 #endif
71af5a
b1103c ¤   /* Et voila, we're done! ·Return number of trust decisions needed. */
0441ab ¤   /* (Saturate on overflow if 16-bit ints.) */
62f7bd ¤   return count > INT_MAX ? INT_MAX : (int)count;
b9efe6 }
a4af5a
4aaf5a
8a38e5 /*
593acf ·* Keyring checking code.
--2f99 0006a3379e0401001f7 Page 42 of pgpRngMnt.c
47495d ·*/
44af5a
d838e5 /*
28999b ·* Count the number of unchecked signatures, if needed for a progress bar.
e6c36d ·* The return value is the number of times the progress func() function
3aec56 ·* will be called by ringPoolCheck().
cede3e ·* NOTE: this tries to be as accurate as possible, but user code
2fe611 ·* should not die if it is slightly incorrect.
a8495d ·*/
44a091 ¤   int
040248 ringPoolCheckCount(RingSet const *sigset, RingSet const *keyset,
64a9a2 ¤   PGPBoolean allflag, PGPBoolean revocationonly)
86bb36 {
482e2f ¤   union RingObject const *key;
b30690 ¤   RingSig const *sig;
3ca875 ¤   unsigned long count = 0;
35af5a
354738 ¤   pgpAssert(keyset->pool == sigset->pool);
28e9a7 ¤   ringPoolListSigsBy(sigset->pool);
77af5a
b58a95 ¤   for (key = sigset->pool->keys; key; key = key->g.next) {
1fa3aa ¤   ¤   pgpAssert(OBJISKEY(key));
070d39 ¤   ¤   if (!pgpIsRingSetMember(keyset, key) || key->g.flags & KEYF_ERROR)
f8f430 ¤   ¤   ¤   continue;¤  /* Skip dummy keys */
8b1cc6 ¤   ¤   for (sig = &key->k.sigsby->s; sig; sig = sig->nextby) {
c97aad ¤   ¤   ¤   /*
8331b5 ¤   ¤   ¤   ·* Reasons why a signature might not be checked:
bf7b8a ¤   ¤   ¤   ·* - Already tested and not allflag
b9a946 ¤   ¤   ¤   ·* - Not in sigset
938753 ¤   ¤   ¤   ·*/
25d1a1 ¤   ¤   ¤   if (pgpIsRingSetMember(sigset, (RingObject *)sig)
8b515d ¤   ¤   ¤   ····&& (allflag
af94a1 ¤   ¤   ¤   ¤   ¤   || !(sig->trust&PGP_SIGTRUSTF_CHECKED_TRIED))
65e391 ¤   ¤   ¤   ¤   && (!revocationonly
e073d6 ¤   ¤   ¤   ¤   ¤   || sig->type == PGP_SIGTYPE_KEY_REVOKE))
561f88 ¤   ¤   ¤   ¤   count++;
740fe4 ¤   ¤   }
029371 ¤   }
60af5a
adf7bd ¤   return count > INT_MAX ? INT_MAX : (int)count;
97efe6 }
a6af5a
4438e5 /*
047a7c ·* Set the signature trust to the given value. ·Returns the bitmask of
578b52 ·* changed keyrings.
5b495d ·*/
3ef1ae static PGPError
a4cbfc setSigTrust(RingPool *pool, RingSig *sig, PGPByte trust, PGPVirtMask *omask)
f8bb36 {
7f3e1d ¤   if (sig->trust == trust)
7dbbde ¤   ¤   return 0;
627648 ¤   sig->trust = trust;
ffb939 ¤   sig->flags |= RINGOBJF_TRUSTCHANGED;
b39f05 ¤   pgpVirtMaskCleanup(pool, omask);
f8e492 ¤   pgpVirtMaskCopy (pool, &sig->mask, omask);
ba151e ¤   return kPGPError_NoErr;
f9efe6 }
3daf5a
4656b6 static PGPBoolean
add189 ringSigX509Valid (RingSet const *set, RingObject *obj,
206e1a ¤   PGPPubKey const *pub)
31bb36 {
98d259 ¤   PGPByte *buf;
dcac22 ¤   PGPByte *x509cert;
4d47bf ¤   PGPByte *hashedbuf;
254bb7 ¤   PGPByte *sigbuf;
40875f ¤   PGPSize len;
9a60d8 ¤   PGPSize x509len;
d48ced ¤   PGPSize hashedlen;
1df066 ¤   PGPSize siglen;
bf7e88 ¤   PGPInt32 rslt;
6ae2ba ¤   PGPHashContext *hc;
--f44b 00099b6610d401001f7 Page 43 of pgpRngMnt.c
2d9102 ¤   RingObject const *parentkey;
933881 ¤   RingObject const *parentname;
63af5a
b7af5a
8ad8af ¤   /*
5548c5 ¤   ·* Steps:
d0f04e ¤   ·* 1) Compare the key and name data with that in the cert.
f7387b ¤   ·* 2) Validate the signature in the cert, using pub
d6a4e3 ¤   ·*/
21af5a
034492 ¤   parentname = obj->g.up;
9af8d3 ¤   if (!OBJISNAME(parentname)) {
a898aa ¤   ¤   return FALSE;
799371 ¤   }
6273f0 ¤   parentkey = parentname->g.up;
655e39 ¤   if (!OBJISTOPKEY(parentkey)) {
df98aa ¤   ¤   return FALSE;
f69371 ¤   }
b2af5a
4a03ff ¤   /* Find embedded X509 cert */
729586 ¤   buf = (PGPByte *)ringFetchObject(set, obj, &len);
a1801e ¤   if (IsNull( buf ) )
5b98aa ¤   ¤   return FALSE;
2b4cb8 ¤   x509cert = (PGPByte *)ringSigFindSubpacket(buf, SIGSUB_X509, 0, &x509len,
379120 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, NULL, NULL);
ee4bb9 ¤   if (IsNull( x509cert ) )
d098aa ¤   ¤   return FALSE;
faaf5a
6dd77e ¤   /* Make a copy of the cert, we'll overwrite it */
5339a2 ¤   buf = (PGPByte *) pgpContextMemAlloc (set->pool->context, x509len, 0);
f527de ¤   if (IsNull (buf)) {
8698aa ¤   ¤   return FALSE;
109371 ¤   }
d516cd ¤   pgpCopyMemory (x509cert, buf, x509len);
7a9fbb ¤   x509cert = buf;
7caf5a
c5b6f4 ¤   /* Check to see if data from X.509 cert matches parent key and name */
f1af5a
9d160d ¤   pgpX509CertToKeyBuffer (set->pool, x509cert, x509len,
382bf6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &set->pool->pktbuflen);
575cf8 ¤   if (keysdiffer(set->pool->files[MEMRINGBIT], parentkey, PKTBYTE_PUBKEY)) {
a83df3 ¤   ¤   pgpContextMemFree (set->pool->context, x509cert);
a898aa ¤   ¤   return FALSE;
f09371 ¤   }
5b68d4 ¤   pgpX509CertToNameBuffer (set->pool, x509cert, x509len,
8170b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&set->pool->pktbuflen);
827e3a ¤   if (namesdiffer(set->pool->files[MEMRINGBIT], parentname, FALSE)) {
f03df3 ¤   ¤   pgpContextMemFree (set->pool->context, x509cert);
2898aa ¤   ¤   return FALSE;
a89371 ¤   }
c953a3 ¤   pgpX509CertToSigBuffer (set->pool, x509cert, x509len,
5e2bf6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &set->pool->pktbuflen);
7f25ff ¤   if (sigsdiffer(set->pool->files[MEMRINGBIT], obj)) {
993df3 ¤   ¤   pgpContextMemFree (set->pool->context, x509cert);
bd98aa ¤   ¤   return FALSE;
a49371 ¤   }
50af5a
5b3383 ¤   /* Check X.509 certificate signature */
f4af5a
dad3e7 ¤   pgpX509CertPartition (x509cert, x509len, &hashedbuf, &hashedlen,
363ba5 ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, &sigbuf, &siglen);
78af5a
d3fe27 ¤   /* Hash the data */
9be5fd ¤   hc = pgpHashCreate(
d46dd3 ¤   ¤   ···PGPGetContextMemoryMgr( set->pool->context ),
d0997b ¤   ¤   ···pgpHashByNumber( (PGPHashAlgorithm)obj->s.hashalg ) );
a998a0 ¤   PGPContinueHash(hc, hashedbuf, hashedlen);
d367c5 ¤
10a3ae ¤   /* Verify the signature: rslt==1 means OK, else failure */
786aea ¤   rslt = pgpPubKeyVerify (pub, sigbuf, siglen, pgpHashGetVTBL(hc),
972185 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPByte *) pgpHashFinal(hc),
99c571 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyMessageFormat_X509);
--a6e4 000d5603164401001f7 Page 44 of pgpRngMnt.c
7a3e84 ¤   pgpContextMemFree (set->pool->context, x509cert);
8934ef ¤   PGPFreeHashContext (hc);
e4af5a
9b7223 ¤   if (rslt != 1)
7598aa ¤   ¤   return FALSE;
9caf5a
b41a9b ¤   /* All OK */
74c2e7 ¤   return TRUE;
d1efe6 }
65af5a
3aaf5a
de38e5 /*
f1a845 ·* Check the signatures on a keyring. ·Checks unchecked signatures,
f6582c ·* or all signatures if allflag is true.
07775e ·*
913556 ·* Checks signatures in "sigset" if they are made by keys in "keyset".
40775e ·*
c0745f ·* If func is non-null, calls it with each checked signature, after
fd5d36 ·* checking. ·This is for progress indications. ·If func returns a
7cf479 ·* negative value, the check is aborted.
09775e ·*
8a600e ·* Question: should signatures be checked in order of the key they're
de7730 ·* on, or the key they're by? ·Should this be guaranteed? ·For now, use
bd3e18 ·* the 2.x order.
69495d ·*/
14c744 ¤   PGPError
94c183 ringPoolCheck(RingSet const *sigset, RingSet const *keyset,
2ad71a ¤   PGPBoolean allflag, PGPBoolean revocationonly,
f12b6c ¤   PGPError (*func)(void *, RingIterator *, int), void *arg)
37bb36 {
271170 ¤   RingIterator *iter = NULL;
52f1d5 ¤   union RingObject *obj, *key;
a90680 ¤   union RingObject *sigparent=NULL, *sigowner=NULL;
d4bb4c ¤   int sp = 0;¤/* Iterator level (stack pointer) */
053fed ¤   union RingObject *hashed[RINGMAXDEPTH];
ebe2ba ¤   PGPHashContext *hc;
71137e ¤   PGPHashContext *hcstack[RINGMAXDEPTH];
1208a4 ¤   PGPHashVTBL const *h, *hnew = NULL;
5cd259 ¤   PGPByte *buf;
aeff0a ¤   PGPByte const *extrabuf;
9aa299 ¤   PGPPubKey *pub;
ae875f ¤   PGPSize len;
7b27ed ¤   unsigned extralen;
e1be4f ¤   PGPVirtMask changemask;¤¤   /* Sets that have had trust changed */
820537 ¤   PGPVirtMask tmask;
70bf0a ¤   PGPByte tmpbuf[5];
eca346 ¤   PGPByte t;¤ ¤   ¤   ¤   ¤   /* Trust on current signature */
757a4f ¤   int sighashnew;¤¤   ¤   ¤   /* True if sig uses new hash conventions */
865dcd ¤   int namehashnew=0;¤ ¤   ¤   /* True if name hash cache uses new "" */
504ba4 ¤   int i;
c73d81 ¤   union RingObject *name;
eeaf5a
0078b9 ¤   pgpAssert(sigset->pool == keyset->pool);
49af5a
c22605 ¤   pgpVirtMaskInit (sigset->pool, &changemask);
d602ed ¤   pgpVirtMaskInit (sigset->pool, &tmask);
f5af5a
2db0f6 ¤   for (i = 0; i < RINGMAXDEPTH; i++) {
d6f714 ¤   ¤   hashed[i] = (union RingObject *)0;
80852c ¤   ¤   hcstack[i] = (PGPHashContext *)0;
839371 ¤   }
dbaf5a
5f8737 ¤   iter = ringIterCreate(sigset);
7cf222 ¤   if (!iter) {
9fbf07 ¤   ¤   pgpVirtMaskCleanup (sigset->pool, &changemask);
6050bd ¤   ¤   pgpVirtMaskCleanup (sigset->pool, &tmask);
e94030 ¤   ¤   return kPGPError_OutOfMemory;
079371 ¤   }
e8af5a
a8c88c ¤   h = (PGPHashVTBL const *)0;
d1af5a
d59abd ¤   while ((sp = ringIterNextObjectAnywhere(iter)) > 0) {
--a274 000df49852d401001f7 Page 45 of pgpRngMnt.c
c8c66e ¤   ¤   obj = ringIterCurrentObject(iter, (unsigned)sp);
44bec6 ¤   ¤   if (!OBJISSIG(obj))
d217f5 ¤   ¤   ¤   continue;
ae2a68 ¤   ¤   t = obj->s.trust; ····
c8af5a
189b36 ¤   ¤   /* See if we have the key */
b480d4 ¤   ¤   key = ringSigMaker(sigset, obj, keyset);
eeaf5a
f67148 ¤   ¤   /* ·If NOT allflag, and sig has been successfully checked,
2d0a51 ¤   ¤   ¤   ignore it. ·Previously we cleared flags if signing key was
3e505c ¤   ¤   ¤   not present in sigset, but that makes it difficult to
1bbe45 ¤   ¤   ¤   cumulatively check disjoint sigsets as the basis for a
deb6d1 ¤   ¤   ¤   signature. ·Can always do test with allflag set if we want
521ca2 ¤   ¤   ¤   to test for bogus CHECKED_TRIED flags. ·*/
2df87e ¤   ¤   if (!allflag && (t & PGP_SIGTRUSTF_CHECKED_TRIED)) {
52a767 ¤   ¤   ····ringObjectRelease (key);
b017f5 ¤   ¤   ¤   continue;
820fe4 ¤   ¤   }
9eaf5a
fa1252 ¤   ¤   /* If revocationonly, only check key revocation signatures. ·This is
9b92a5 ¤   ¤   ·* used when importing a pre PGP 5.0 keyring, which does not save
62b884 ¤   ¤   ·* trust packets on such signatures.
789de3 ¤   ¤   ·*/
08378d ¤   ¤   if (revocationonly && (obj->s.type != PGP_SIGTYPE_KEY_REVOKE)) {
0fa767 ¤   ¤   ····ringObjectRelease (key);
6f17f5 ¤   ¤   ¤   continue;
bd0fe4 ¤   ¤   }
77af5a
6ea0b6 ¤   ¤   /* If the superior object is a name, reset the
10a08e ¤   ¤   ···WARNONLY flag. */
b3af5a
892d4f ¤   ¤   name = ringIterCurrentObject(iter,·
1353e4 ¤   ¤   ¤   ¤   ¤   ·····ringIterCurrentLevel(iter)-1);
281680 ¤   ¤   if (OBJISNAME(name) &&
6d6886 ¤   ¤   ¤   ¤   (name->n.trust & PGP_NAMETRUSTF_WARNONLY)) {
712382 ¤   ¤   ··name->n.trust &= ~PGP_NAMETRUSTF_WARNONLY;
96c412 ¤   ¤   ··pgpVirtMaskOR (sigset->pool, &name->g.mask, &changemask);
b20fe4 ¤   ¤   }
09af5a
cb1898 ¤   ¤   /* We now have a signature to check - clear the bits */
337c9b ¤   ¤   t &= ~PGP_SIGTRUSTF_CHECKED_TRIED;
9daf5a
ad7cc0 ¤   ¤   if (!key) {
49fb21 ¤   ¤   ¤   /* No key, so sig cannot be considered good. */
684bfe ¤   ¤   ¤   setSigTrust(sigset->pool, &obj->s, t, &tmask);
025b10 ¤   ¤   ¤   pgpVirtMaskOR (sigset->pool, &tmask, &changemask);
4f17f5 ¤   ¤   ¤   continue;
260fe4 ¤   ¤   }
74af5a
4bc201 ¤   ¤   /* The new hash style includes the name header and count */
44c16d ¤   ¤   sighashnew = ·obj->s.version > PGPVERSION_3;
10af5a
2dba54 ¤   ¤   /* Get the key that made the signature */
d05f4f ¤   ¤   pub = ringKeyPubKey(keyset, key, PGP_PKUSE_SIGN);
1c2642 ¤   ¤   ringObjectRelease(key);
b70e97 ¤   ¤   if (!pub) {
0ec7c8 ¤   ¤   ¤   i = ringSetError(keyset)->error;
571160 ¤   ¤   ¤   /* @@@ ViaCrypt self-signs encryption-only keys
c2847b ¤   ¤   ¤   ···(as they're RSA, it's possible), but PGP 3·
6b3907 ¤   ¤   ¤   ···doesn't like this. ·Ignore this type of
9f38c7 ¤   ¤   ¤   ···signature. */
475ca5 ¤   ¤   ¤   if( pgpIsKeyRelatedError( i ) )
c76228 ¤   ¤   ¤   ¤   goto uncheckable;
01d79d ¤   ¤   ¤   goto fatal;¤/* I/O or memory error */
f40fe4 ¤   ¤   }
96af5a
84b7f6 ¤   ¤   /* Some reasons that we might not be able to check it */
7356d9 ¤   ¤   if (obj->g.flags & SIGF_ERROR
fae9fe ¤   ¤   ····|| key->g.flags & KEYF_ERROR
afeb83 ¤   ¤   ····|| ( !SIGISX509(&obj->s) &&
cb1f64 ¤   ¤   ¤   ¤   ·(hnew =
df76a2 ¤   ¤   ¤   ¤   ··pgpHashByNumber( (PGPHashAlgorithm)obj->s.hashalg)) == 0) )
--a864 0008f968356401001f7 Page 46 of pgpRngMnt.c
e35b34 ¤   ¤   {
9eadbe ¤   ¤   ¤   ringObjectRelease(key);
5163a7 ¤   ¤   ¤   pgpPubKeyDestroy(pub);
121a1d ¤   ¤   ¤   pub = NULL;
c45520 ¤   ¤   ¤   goto uncheckable;
580fe4 ¤   ¤   }
faaf5a
59642e ¤   ¤   /* Special verification rules for X.509 signatures */
263691 ¤   ¤   if (SIGISX509(&obj->s)) {
5bc97d ¤   ¤   ¤   /* i encodes signature validity for callback, 1 == good */
197c75 ¤   ¤   ¤   i = 0;
e68acb ¤   ¤   ¤   t |= PGP_SIGTRUSTF_TRIED;
cd23e3 ¤   ¤   ¤   if (ringSigX509Valid (sigset, obj, pub)) {
843a4d ¤   ¤   ¤   ¤   t |= PGP_SIGTRUSTF_CHECKED;
321d40 ¤   ¤   ¤   ¤   i = 1;
d8a3a6 ¤   ¤   ¤   }
f83ccd ¤   ¤   ¤   /* Fall into code where we report the results */
c463a7 ¤   ¤   ¤   pgpPubKeyDestroy(pub);
351a1d ¤   ¤   ¤   pub = NULL;
c25520 ¤   ¤   ¤   goto uncheckable;
bb0fe4 ¤   ¤   }
61af5a
f05bfb ¤   ¤   /* Okay, "hnew" is the current hash. ·Do checking. */
c39ed6 ¤   ¤   i = 0;
8cc0ad ¤   ¤   for (;;) {
353dfb ¤   ¤   ¤   obj = ringIterCurrentObject(iter, ++i);
fe27ed ¤   ¤   ¤   hc = hcstack[i-1];
d42e29 ¤   ¤   ¤   if (hc && pgpHashGetVTBL( hc ) != hnew) {
e774d0 ¤   ¤   ¤   ¤   PGPFreeHashContext(hc);
9ae509 ¤   ¤   ¤   ¤   hc = 0;
81a3a6 ¤   ¤   ¤   }
8b2fd0 ¤   ¤   ¤   if (!hc) {
c4353a ¤   ¤   ¤   ¤   hc = pgpHashCreate(
1b7650 ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( keyset->pool->context ), hnew);
5dc925 ¤   ¤   ¤   ¤   if (!hc)
367a8f ¤   ¤   ¤   ¤   ¤   goto nomem;
fc86a7 ¤   ¤   ¤   ¤   hcstack[i-1] = hc;
3a1601 ¤   ¤   ¤   ¤   hashed[i-1] = (union RingObject *)0;
f5740b ¤   ¤   ¤   } else if (hashed[i-1] == obj) {
f765a3 ¤   ¤   ¤   ¤   /* Right hash, right object */
05eaa1 ¤   ¤   ¤   ¤   /* Detect whether name has same hash style as we need */
a77826 ¤   ¤   ¤   ¤   if (!OBJISNAME(obj) || namehashnew==sighashnew)
345914 ¤   ¤   ¤   ¤   ¤   continue;
d3a3a6 ¤   ¤   ¤   }
87af5a
83ced4 ¤   ¤   ¤   buf = (PGPByte *)ringFetchObject(sigset, obj, &len);
d49ff0 ¤   ¤   ¤   if (!buf)
cdf776 ¤   ¤   ¤   {
e30239 ¤   ¤   ¤   ¤   i¤  = kPGPError_UnknownError;
c5fd8b ¤   ¤   ¤   ¤   goto fatal;
daa3a6 ¤   ¤   ¤   }
7faf5a
c3bcd3 ¤   ¤   ¤   if (i == sp)
928d95 ¤   ¤   ¤   ¤   break;¤ /* We've hit the signature */
28af5a
6fb49b ¤   ¤   ¤   if (i == 1)
343229 ¤   ¤   ¤   ¤   PGPResetHash(hc);
10bb8c ¤   ¤   ¤   else
64cfb5 ¤   ¤   ¤   ¤   pgpHashCopyData(hcstack[i-2], hc);
48af5a
c1e6af ¤   ¤   ¤   /* We use this format even for subkeys */
95acae ¤   ¤   ¤   if (OBJISKEY(obj)) {
b865f7 ¤   ¤   ¤   ¤   tmpbuf[0] = PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1);
221c1c ¤   ¤   ¤   ¤   tmpbuf[1] = (PGPByte)(len>>8);
0e6c4e ¤   ¤   ¤   ¤   tmpbuf[2] = (PGPByte)len;
999819 ¤   ¤   ¤   ¤   PGPContinueHash(hc, tmpbuf, 3);
edc74d ¤   ¤   ¤   ¤   sigparent = obj;¤   /* Remember key above sig for below */
786685 ¤   ¤   ¤   ¤   if (OBJISTOPKEY(obj)) {
bf5dba ¤   ¤   ¤   ¤   ¤   sigowner = obj;¤/* Also top key of sig for below */
c12613 ¤   ¤   ¤   ¤   }
4e042d ¤   ¤   ¤   } else {
8fdebb ¤   ¤   ¤   ¤   /* Not a signature, this must be a name */
--b263 000ef4a0447401001f7 Page 47 of pgpRngMnt.c
6b5e34 ¤   ¤   ¤   ¤   pgpAssert(i == 2);
36607c ¤   ¤   ¤   ¤   pgpAssert(OBJISNAME(obj));
8c0b68 ¤   ¤   ¤   ¤   if (sighashnew) {
8a0c84 ¤   ¤   ¤   ¤   ¤   tmpbuf[0] = NAMEISATTR(&obj->n) ?
550f88 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PKTBYTE_BUILD(PKTBYTE_ATTRIBUTE, 0) :
0f4a47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PKTBYTE_BUILD(PKTBYTE_NAME, 0);
c5783b ¤   ¤   ¤   ¤   ¤   tmpbuf[1] = (PGPByte)(len>>24);
98500c ¤   ¤   ¤   ¤   ¤   tmpbuf[2] = (PGPByte)(len>>16);
e34531 ¤   ¤   ¤   ¤   ¤   tmpbuf[3] = (PGPByte)(len>> 8);
f5bd88 ¤   ¤   ¤   ¤   ¤   tmpbuf[4] = (PGPByte)(len>> 0);
4f45c2 ¤   ¤   ¤   ¤   ¤   PGPContinueHash(hc, tmpbuf, 5);
3c2613 ¤   ¤   ¤   ¤   }
f3b70d ¤   ¤   ¤   ¤   namehashnew = sighashnew;
0ba3a6 ¤   ¤   ¤   }
cba3e5 ¤   ¤   ¤   PGPContinueHash(hc, buf, len);
9d5d55 ¤   ¤   ¤   hashed[i-1] = obj;
5b0fe4 ¤   ¤   }
9b1b17 ¤   ¤   /*
898c93 ¤   ¤   ·* Okay, "obj" is the signature again, "hc" is the
f01066 ¤   ¤   ·* appropriate hash context, and the signature has
060c2f ¤   ¤   ·* been fetched.
0d9de3 ¤   ¤   ·*/
fcaf5a
cbc293 ¤   ¤   extrabuf = ringSigParseExtra(buf, len, &extralen);
13af5a
7d1b17 ¤   ¤   /*
fae478 ¤   ¤   ·* extralen != 5 legal only if sig is on key directly,
3c5226 ¤   ¤   ·* or it is a new-format EXTENDED type.
c89de3 ¤   ¤   ·*/
3877a6 ¤   ¤   i = -1;¤¤   /* flag error on func call below */
41db7e ¤   ¤   if (sp == 2¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* Sig directly on key */
b0ff73 ¤   ¤   ¤   || extralen == 5¤   ¤   ¤   ¤   ¤   ¤   /* Traditional case */
807aad ¤   ¤   ¤   /*
57b58d ¤   ¤   ¤   ·* This was an earlier idea for forward compatibility, replaced
d9e463 ¤   ¤   ¤   ·* by the newer-version packets.
fc5786 ¤   ¤   ¤   ·* || (extralen > 5
64b113 ¤   ¤   ¤   ·* ····&& extrabuf[extralen-5]&PGP_SIGTYPEF_EXTENDED)
688753 ¤   ¤   ¤   ·*/
5b3894 ¤   ¤   ¤   || obj->s.version > PGPVERSION_3¤   ¤   /* New format packets */
0da78b ¤   ¤   ¤   || sighashnew) {¤   ¤   ¤   ¤   ¤   ¤   /* DSA keys fix bug */
27cca0 ¤   ¤   ¤   /* Hash in extra bytes for signature */
0d9317 ¤   ¤   ¤   pgpHashCopyData(hcstack[sp-2], hc );
ada882 ¤   ¤   ¤   PGPContinueHash(hc, extrabuf, extralen);
2daf5a
913c60 ¤   ¤   ¤   if (sighashnew) {
3f4409 ¤   ¤   ¤   ¤   /* Make sure hash can't match any old or doc hashes */
cc2f3f ¤   ¤   ¤   ¤   PGPByte postscript[6];
49cb04 ¤   ¤   ¤   ¤   postscript[0] = PGPVERSION_4;¤  /* actually a 4! */
b3fbbf ¤   ¤   ¤   ¤   postscript[1] = 0xff;¤  ¤   ¤   /* different from sig type */
a33e2a ¤   ¤   ¤   ¤   postscript[2] = (PGPByte)(extralen>>24);
3c3a63 ¤   ¤   ¤   ¤   postscript[3] = (PGPByte)(extralen>>16);
bcc9fc ¤   ¤   ¤   ¤   postscript[4] = (PGPByte)(extralen>> 8);
370cd7 ¤   ¤   ¤   ¤   postscript[5] = (PGPByte)(extralen>> 0);
1bec40 ¤   ¤   ¤   ¤   PGPContinueHash (hc, postscript, sizeof(postscript));
36a3a6 ¤   ¤   ¤   }
12af5a
dccbf1 ¤   ¤   ¤   i = pgpSigCheckBuf((PGPByte *)buf, len, pub, pgpHashFinal(hc));
4b7622 ¤   ¤   ¤   if (i == kPGPError_OutOfMemory)
9cb959 ¤   ¤   ¤   ¤   goto nomem;¤/* Fatal error */
5a4e54 ¤   ¤   ¤   /* @@@ TODO: use more error info */
44c52d ¤   ¤   ¤   if (i == 1) {
41103a ·¤  ¤   ¤   ¤   t |= PGP_SIGTRUSTF_CHECKED;
f5980e ¤   ¤   ¤   ¤   /*
9dffb2 ¤   ¤   ¤   ¤   ·* On finding a valid self signature, apply any info in sig
797458 ¤   ¤   ¤   ¤   ·* to parent key which goes there. ·"key" is signer, sigowner
96151c ¤   ¤   ¤   ¤   ·* is top level key above this sig, sigparent is closest
fcd8cb ¤   ¤   ¤   ¤   ·* key above this sig (may differ for DSA/ElG keys).
9d1020 ¤   ¤   ¤   ¤   ·*/
c5068e ¤   ¤   ¤   ¤   if (key == sigowner) {
a37980 ¤   ¤   ¤   ¤   ¤   /* Self signature */
6640fa ¤   ¤   ¤   ¤   ¤   PGPByte const *pk;
eff697 ¤   ¤   ¤   ¤   ¤   /* Look for expiration date, apply to key above us */
--c662 000b8c4d541401001f7 Page 48 of pgpRngMnt.c
4c92e9 ¤   ¤   ¤   ¤   ¤   /* Note that this may alter the contents of buf */
53b6c6 ¤   ¤   ¤   ¤   ¤   pk = ringSigFindSubpacket (buf, SIGSUB_KEY_EXPIRATION,
371ad9 ¤   ¤   ¤   ¤   ¤   ¤   0, NULL, NULL, NULL, NULL, NULL);
31b6f5 ¤   ¤   ¤   ¤   ¤   if (pk) {
d6f840 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyexp;
7f8cd5 ¤   ¤   ¤   ¤   ¤   ¤   keyexp = (PGPUInt32)
514acb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ((unsigned)pk[0]<<8|pk[1]) << 16 |
0df5d4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ((unsigned)pk[2]<<8|pk[3]);
f811a0 ¤   ¤   ¤   ¤   ¤   ¤   if (sigparent) {
bb8fa6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sigparent->k.validity =
438a97 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16)(keyexp/(24*3600));
0bdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
d71c89 ¤   ¤   ¤   ¤   ¤   }
742613 ¤   ¤   ¤   ¤   }
16a3a6 ¤   ¤   ¤   }
08af5a
708acb ¤   ¤   ¤   t |= PGP_SIGTRUSTF_TRIED;
a60fe4 ¤   ¤   }
f8efd8 ¤   ¤   pgpPubKeyDestroy(pub);
3660e9 ¤   ¤   pub = NULL;
84a18f uncheckable:
da4cc5 ¤   ¤   setSigTrust(sigset->pool, &obj->s, t, &tmask);
8d5bf2 ¤   ¤   pgpVirtMaskOR (sigset->pool, &tmask, &changemask);
3a631a ¤   ¤   if (func) {
882ef4 ¤   ¤   ¤   i = (int)func(arg, iter, i);
7c8e41 ¤   ¤   ¤   if ( i < 0 )
37fd8b ¤   ¤   ¤   ¤   goto fatal;
f30fe4 ¤   ¤   }
909371 ¤   }
c01d89 ¤   ringIterDestroy(iter);
c200ee ¤   iter = NULL;
5aaf5a
fcc0c7 ¤   for (sp = 0; sp < (int)(sizeof(hcstack)/sizeof(*hcstack)); sp++) {
8bd3d8 ¤   ¤   if( IsntNull( hcstack[sp] ) ) {
783d2c ¤   ¤   ¤   PGPFreeHashContext(hcstack[sp]);
250fe4 ¤   ¤   }
7a9371 ¤   }
9daf5a
28b177 #if 0
b266a6 ¤   /* Set the trustchanged bits under the mask */
1bdc8e ¤   ringPoolMarkTrustChanged(ring, changemask);
207454 #endif
80fedf ¤   ringIterDestroy (iter);
09eaab ¤   pgpVirtMaskCleanup (sigset->pool, &changemask);
86880f ¤   pgpVirtMaskCleanup (sigset->pool, &tmask);
db151e ¤   return kPGPError_NoErr;
beaf5a
8fac52 nomem:
e030c4 ¤   i = kPGPError_OutOfMemory;
3ed697 ¤   ringSimpleErr(sigset->pool, (PGPError)i);
e18608 fatal:
c0a9db ¤   if (iter)
e009a1 ¤   ¤   ringIterDestroy(iter);
5be03a ¤   if (pub)
59efd8 ¤   ¤   pgpPubKeyDestroy(pub);
24c0c7 ¤   for (sp = 0; sp < (int)(sizeof(hcstack)/sizeof(*hcstack)); sp++) {
4cd3d8 ¤   ¤   if( IsntNull( hcstack[sp] ) ) {
2c3d2c ¤   ¤   ¤   PGPFreeHashContext(hcstack[sp]);
fa0fe4 ¤   ¤   }
2b9371 ¤   }
a5eaab ¤   pgpVirtMaskCleanup (sigset->pool, &changemask);
dd880f ¤   pgpVirtMaskCleanup (sigset->pool, &tmask);
efd634 ¤   return (PGPError)i;
1aefe6 }
e9af5a
de38e5 /*
c6bd1b ·* Update the hash context with the data in the object.
6c775e ·*
3c562f ·* hc¤  ¤   HashContext to update
bb358b ·* obj¤ ¤   Object to update it with
cd057d ·* set¤ ¤   Set which holds object, used for fetching its data
b867cc ·* hashnamelength¤  If true, include the length of a name packet in hash
--11e6 0009e694572401001f7 Page 49 of pgpRngMnt.c
4f775e ·*
a14b38 ·* Return¤  0 on success, or an error code
05495d ·*/
f34270 int ringHashObj (PGPHashContext *hc, union RingObject *obj,
fa8c34 ¤   ¤   ·RingSet const *set, int hashnamelength)
d6bb36 {
1bd321 ¤   PGPSize objlen;
6b74e7 ¤   PGPByte const *objbuf;
09bf0a ¤   PGPByte tmpbuf[5];
24af5a
90adc6 ¤   if (!hc || !obj || !set)
d162b5 ¤   ¤   return kPGPError_BadParams;
d0af5a
b9f582 ¤   objbuf = (PGPByte const *)ringFetchObject(set, obj, &objlen);
bcf994 ¤   if (!objbuf)
dce1c3 ¤   ¤   return ringSetError(set)->error;
7e0790 ¤   /* We use this format even for subkeys */
7323a5 ¤   if (OBJISKEY(obj)) {
09a3ff ¤   ¤   pgpAssert(objlen <= 65535);
628480 ¤   ¤   tmpbuf[0] = PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1);
a6a346 ¤   ¤   tmpbuf[1] = (PGPByte)(objlen>>8);
96020c ¤   ¤   tmpbuf[2] = (PGPByte)objlen;
18082f ¤   ¤   PGPContinueHash(hc, tmpbuf, 3);
eefe73 ¤   } else if (OBJISNAME(obj) && hashnamelength) {
ee1b17 ¤   ¤   /*
d72c5d ¤   ¤   ·* Use four bytes for name length for future expansion. ·Can't do
1d3018 ¤   ¤   ·* it for keys due to backwards compatibility.
af9de3 ¤   ¤   ·*/
f84cbd ¤   ¤   tmpbuf[0] = NAMEISATTR(&obj->n) ? PKTBYTE_BUILD(PKTBYTE_ATTRIBUTE, 0) :
b2e55a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PKTBYTE_BUILD(PKTBYTE_NAME, 0);
39131a ¤   ¤   tmpbuf[1] = (PGPByte)(objlen>>24);
7f6d93 ¤   ¤   tmpbuf[2] = (PGPByte)(objlen>>16);
0db2cb ¤   ¤   tmpbuf[3] = (PGPByte)(objlen>> 8);
062d6b ¤   ¤   tmpbuf[4] = (PGPByte)(objlen>> 0);
c943b5 ¤   ¤   PGPContinueHash(hc, tmpbuf, 5);
489371 ¤   }
8debe0 ¤   PGPContinueHash(hc, objbuf, objlen);
ca3e6b ¤   return 0;
4cefe6 }
27af5a
1338e5 /*
05f6e4 ·* Sign the specified object obj, along with its parents.
3a7372 ·* Should be member of RingSet dest, which may be mutable or immutable.
9422d0 ·* Place signature into sig buffer.
d1c7f4 ·* sig buffer should be at least pgpMakeSigMaxSize(spec) bytes long.
d52912 ·* Returns size of sig in bytes on success, negative on error.
b6495d ·*/
0bfcf4 int·
b92767 ringSignObj(PGPByte *sig, RingSet *dest, union RingObject *obj,
ee8429 ¤   ····PGPSigSpec *spec, PGPRandomContext const *rc)
26bb36 {
2ce2ba ¤   PGPHashContext *hc;
8bafce ¤   union RingObject *parents[RINGMAXDEPTH];
34f234 ¤   int len;
05beaf ¤   int level;
8a13a5 ¤   int retval;
8229f7 ¤   int sighashnew;
39af5a
d03e0c ¤   /* Initialize hash */
8ee5fd ¤   hc = pgpHashCreate(
4a35a7 ¤   ¤   ¤   PGPGetContextMemoryMgr( dest->pool->context ),
6b462e ¤   ¤   ¤   pgpSigSpecHash(spec));
a6a1eb ¤   if (hc==NULL)
c5467c ¤   ¤   return kPGPError_BadHashNumber;
c7af5a
77b750 ¤   /* Use new hashing convention (include name length) on new formats */
bfe5d9 ¤   sighashnew = pgpSigSpecVersion(spec) > PGPVERSION_3;
58af5a
94b03b ¤   /* Trace object's parents up to top level */
080f79 ¤   level = 0;
c05870 ¤   for ( ; ; ) {
9ea713 ¤   ¤   pgpAssert (level < RINGMAXDEPTH);
--11a9 000f66ad4a2401001f7 Page 50 of pgpRngMnt.c
e5c107 ¤   ¤   parents[level++] = obj;
5dc8ed ¤   ¤   if (OBJISTOP(obj))
3fcdcb ¤   ¤   ¤   break;
2e5f84 ¤   ¤   obj = obj->g.up;
ae9371 ¤   }
3aaf5a
b02be8 ¤   /* Hash downwards from top to object */
fad912 ¤   while (--level >= 0) {
ad5a22 ¤   ¤   retval = ringHashObj (hc, parents[level], dest, sighashnew);
f72e6b ¤   ¤   if (retval) {
53b2d1 ¤   ¤   ¤   PGPFreeHashContext (hc);
864dbe ¤   ¤   ¤   return retval;
ba0fe4 ¤   ¤   }
739371 ¤   }
b41d8b ¤   len = pgpMakeSig (sig, spec, rc, hc);
d59727 ¤   PGPFreeHashContext(hc);
47bb7a ¤   return len;
5defe6 }
2aaf5a
d9572e /*********** ·DYNAMIC KEY EVALUATION FOR NON-TRUSTED KEY SOURCES *********/
d5af5a
a72bd9 /* Dynamic evaluation functions. ·This is a bottom-up algorithm rather
38c0fb ···than the top-down algorithm used by the static evaluation functions.
64f411 ···To evaluate a name, its signatures must be evaluated, which in turn
9068b3 ···require evaluation of the signing keys names. ·Thus, the algorithm
d7e4d7 ···is recursive. ·The recursion terminates when one of the following
480fc1 ···conditions are detected:
10af5a
8cc58f ···- The key to which the name is attached is axiomatic
bad1ec ···- The key to which the name is attached is revoked
7e1609 ···- The signature is bad
b29242 ···- The signature is retired
cac948 ···- The signing key is axiomatic
63076e ···- The signing key is revoked
bdd1d3 ···- The signing key has expired
0e5385 ···- A certification loop is detected
d59c4f ···- Cert depth is exceeded
9ce8c6 ···
c84b35 ···Certification loops are detected by maintaining a stack that represents
4f9030 ···the certification path currently being evaluated. ·If the key we're
57c149 ···looking at is already on the stack, then it's a loop. ·Loops are handled·
ee23e5 ···in a better manner than the static top-down algorithm (which sometimes
73007c ···discards perfectly good signatures), resulting in more accurate results.
ccaf5a
5fc8bd ···Objects from untrusted keyrings (keyfiles) do not have the RINGOBJF_TRUST
396a2e ···bit set. ·When we compute the validity of such an object, the
18b0e7 ···RINGOBJF_TRUSTCHANGED bit is set as a record that this has been done.
48af5a
1fee8e ···@@@ TODO: Optimize
eeaf5a
687435 ···The comment below is the discovery by Colin of the problem with
b3201a ···PGPTRUSTMODEL 1 that trust along shared paths is not properly discounted:
9baf5a
929b7b ···@@@ XXX
0398f3 ···@@@ XXX This code is buggy! ·It does not compute the right answer!
ae0150 ···@@@ XXX Let "X->Y" mean "X signs Y". ·Consider A->B->C->E, A->B->D->E.
9ae94d ···@@@ XXX If A is perfectly valid and all signers are 90% valid,
470fee ···@@@ XXX then·
87af5a
997fe0 */
96af5a
4e8a37 static PGPUInt16
218cc7 ringMntIntValidateName (RingSet *set, union RingObject *name,·
d77867 ¤   ¤   ¤   int depth);
efaf5a
299db7 /* @@@ NOTE: This is not thread-safe */
2eaf5a
68a0e4 static union RingObject *keystack[10];¤ /* max certdepth == 10 */
ab2511 static int keystack_ptr = 0;
1e1325 #if PGPTRUSTMODEL==0
3af6b6 static PGPUInt16 trust[kPGPKeyTrust_Mask + 1];
f6e2ec static PGPUInt16 thresh;
--4afe 00088896e57401001f7 Page 51 of pgpRngMnt.c
da6b95 static RingPool *trustpool = NULL;
9baf5a
f32978 static void
264864 ringMntInitTrust (RingSet const *set)
dfbb36 {
cf44dd ········unsigned t;
c567c5 ¤
f95bdf ¤   /* Set up trust table once only, unless pool changes */
b8af5a
f02456 ¤   if (trustpool == set->pool)
e8f19a ¤   ········return;·
0f438f ¤   trustpool = set->pool;
4dd8af ¤   /*
d0a33f ¤   ·* This is a simple scoring system. ·Multiply the number of completes
28b5aa ¤   ·* required by the number of marginals required. ·This gives the
d90862 ¤   ·* 'ultimate' score. ·Divide the total by the number of completes to
517913 ¤   ·* give the 'score' for a complete, and by the number of marginals to·
cb2fc5 ¤   ·* give the 'score' for a marginal.
35a4e3 ¤   ·*/
c88f1b ¤   for (t = 0; t < sizeof(trust)/sizeof(*trust); t++)
e986cd ¤   ¤   trust[t] = 0;
e8e139 ¤   trust[kPGPKeyTrust_Marginal] = 1;
612618 ¤   trust[kPGPKeyTrust_Complete] = 1;
21b256 ¤   trust[kPGPKeyTrust_Ultimate] = 1;
85d46f ¤   if (set->pool->num_marginals) {
5d57c3 ¤   ¤   trust[kPGPKeyTrust_Complete] = set->pool->num_marginals;
891683 ¤   ¤   trust[kPGPKeyTrust_Ultimate] = set->pool->num_marginals;
a5f037 ¤   } else {
32870b ¤   ¤   trust[kPGPKeyTrust_Marginal] = 0;
389371 ¤   }
ac270b ¤   if (set->pool->num_completes) {
eceefb ¤   ¤   trust[kPGPKeyTrust_Marginal] = set->pool->num_completes;
b5ab4a ¤   ¤   trust[kPGPKeyTrust_Ultimate] *= set->pool->num_completes;
03f037 ¤   } else {
8b402a ¤   ¤   trust[kPGPKeyTrust_Complete] = 0;
7f9371 ¤   }
0cacac ¤   thresh = trust[kPGPKeyTrust_Ultimate];
44efe6 }
c87454 #endif
a3af5a
ca2de2 /* Check various attributes of key: revocation status, axiomatic, expired.
23b758 ···Ensure all sigs attached to the key have been checked */
b3af5a
37daaa static void·
119eac ringMntIntCheckKey (RingSet const *set, union RingObject *key,
93b37f ¤   ¤   ····int *revoked, int *axiomatic, int *expired)
aebb36 {
90dbf3 ¤   union RingObject *obj, *obj2;
69a42b ¤   RingSet *tmpset;
1eaf5a
d5bc3c ¤   pgpAssert (set);
f87b06 ¤   pgpAssert (key && OBJISKEY (key));
5dbdc5 ¤   pgpAssert (revoked && axiomatic && expired);
fee0ca ¤   *revoked = 0; *axiomatic = 0; *expired = 0;
e867c5 ¤
c584f0 ¤   if (key->k.tstamp > 0 && key->k.validity > 0 &&
52e396 ¤   ····(PGPTime) (key->k.tstamp +·
89c550 ¤   ····(key->k.validity * 24 * 3600)) < PGPGetTime())
c03132 ¤   ¤   *expired = 1;
3faf5a
2fb249 ¤   if (key->k.trust & PGP_KEYTRUSTF_BUCKSTOP)
fe9ff5 ¤   ¤   /* Must be verified by passphrase check, not by simply looking
0aa07f ¤   ¤   ···for a secret key. ·So, key must be on a local ring and
874cb5 ¤   ¤   ···must have the buckstop bit set. */
bbe4db ¤   ¤   *axiomatic = 1;¤·
e8af5a
66ac01 ¤   /* Ensure all sigs have been checked for this key. ·Copy the
8de676 ¤   ···key to a temporary set and pass it to ringPoolCheck */
d8af5a
fbb673 ¤   tmpset = ringSetCreate (set->pool);
a8f02c ¤   pgpAssert (tmpset);
8846e3 ¤   for (obj = key->k.down; obj; obj = obj->g.next) {
--cfaa 0002ab2d929401001f7 Page 52 of pgpRngMnt.c
2c50d2 ¤   ¤   if (OBJISBOT (obj))
4ef74d ¤   ¤   ¤   ringSetAddObject (tmpset, obj);
fe07e0 ¤   ¤   else {
77ece6 ¤   ¤   ¤   for (obj2 = obj->g.down; obj2; obj2 = obj2->g.next)
b8f832 ¤   ¤   ¤   ¤   ringSetAddObject (tmpset, obj2);
3f0fe4 ¤   ¤   }
e29371 ¤   }
dc07e6 ¤   ringSetFreeze (tmpset);
25b177 #if 0
61c7a1 ¤   {
5682ed ¤   ¤   ··int count = 0;
d0800a ¤   ¤   ··fprintf (stdout, "Checking key:\n");
317948 ¤   ¤   ··ringKeyPrint (stdout, set, key, 0);
3a58e9 ¤   ¤   ··if (*axiomatic)
eead09 ¤   ¤   ····fprintf (stdout, "AXIOMATIC KEY\n");
9f13d2 ¤   ¤   ··if ((count = ringPoolCheckCount (tmpset, set, 0)) > 0)
c570a0 ¤   ¤   ····fprintf (stdout, "Checking %d signatures...\n",
6d45d5 ¤   ¤   ¤   ·····count);
049371 ¤   }
cb7454 #endif
3890ff ¤   ringPoolCheck (tmpset, set, FALSE, FALSE, NULL, NULL);
f999ed ¤   ringSetDestroy (tmpset);
9b8d97 ¤   ringGarbageCollect (set->pool);
24af5a
af46e3 ¤   for (obj = key->k.down; obj; obj = obj->g.next) {
286bb2 ¤   ¤   if (pgpIsRingSetMember(set, obj) && OBJISSIG (obj)) {
e94f95 ¤   ¤   ¤   if (obj->s.type == PGP_SIGTYPE_KEY_REVOKE &&
773ae4 ¤   ¤   ¤   ····obj->s.by == key &&
5a174b ¤   ¤   ¤   ····obj->s.trust & PGP_SIGTRUSTF_CHECKED)·
837251 ¤   ¤   ¤   ¤   *revoked = 1;
140fe4 ¤   ¤   }
069371 ¤   }
bdefe6 }
fdaf5a
3cd4b6 /* Check that the sig is good. ·Ensure that it has been checked, that
6d377e ···it has not expired, that it a key signature, that it has not been
22b420 ···superseded, and that is has not been retired. ·Expiration or revocation
41c0d7 ···of the signing key is checked elsewhere.·
707fe0 */
4daf5a
d5649c #if PGPTRUSTMODEL!=2¤   /* [ */
95af5a
06df0d ¤   static int
4ac029 ringMntGoodSig (RingSet const *set, union RingObject *sig,·
ec8c91 ¤   ¤   ¤   ¤   PGPUInt32 const timenow)
dcbb36 {
93c386 ¤   union RingObject *sig2;
ab604e ¤   (void) set;
9faf5a
d61d6a ¤   pgpAssert (sig && OBJISSIG (sig));
db13af ¤   if (!(sig->s.trust & PGP_SIGTRUSTF_CHECKED) ||
d87ba9 ¤   ····!mntSigIsValid (timenow, sig->s.tstamp, sig->s.validity) ||
4440dd ¤   ····sig->s.type != PGP_SIGTYPE_KEY_GENERIC)
debbde ¤   ¤   return 0;
54af5a
69c68d ¤   for (sig2 = sig->s.up->g.down; sig2; sig2 = sig2->s.next) {
884d3a ¤   ····if (sig2->s.by == sig->s.by) {
3f94e5 ¤   ¤   ····/* If we find a revocation sig that's newer, assume
9c3236 ¤   ¤   ¤   ···the old sig is bad even if the revocation sig has
7ea5b1 ¤   ¤   ¤   ···not been checked (it's the safest option in case
02d87d ¤   ¤   ¤   ···a good revocation sig has been corrupted) */
a0d7a0 ¤   ¤   ····if (SIGISREVOCABLE(&sig->s) &&
b3a7cc ¤   ¤   ¤   ¤   ¤   sig2->s.type == PGP_SIGTYPE_KEY_UID_REVOKE &&
a0d792 ¤   ¤   ¤   ¤   ····sig2->s.tstamp > sig->s.tstamp)
a0ed11 ¤   ¤   ¤   ····return 0;
c82ff9 ¤   ¤   ¤   /* Otherwise, see if we have a newer sig that's been
e1d11d ¤   ¤   ¤   ···checked and is valid. */
c49f6e ¤   ¤   ¤   if (sig2->s.trust & PGP_SIGTRUSTF_CHECKED &&
530f9d ¤   ¤   ¤   ¤   ····sig2->s.tstamp > sig->s.tstamp &&
ba4e33 ¤   ¤   ¤   ¤   ····mntSigIsValid (timenow, sig2->s.tstamp, sig2->s.validity))
11ed11 ¤   ¤   ¤   ····return 0;
2a0fe4 ¤   ¤   }
--8f38 00002946cd0401001f7 Page 53 of pgpRngMnt.c
a19371 ¤   }
077ce5 ¤   return 1; ··/* good */
6eefe6 }
cdaf5a
0338e5 /*
163994 ·* NO_RECURSION==1 causes sig validation to use the trust and confidence
2ed414 ·* values on the signing key and its names. ·It is most appropriate for a
f5bb7c ·* model where trusted introducers are kept on a local keyring and the
1406dc ·* regular maintenance pass is used to keep their trust information up to
84e9f2 ·* date.
1c775e ·*
ea1a64 ·* NO_RECURSION==0 (e.g. recursion) causes sig validation to recursively
dd3e51 ·* dynamically check the validity of the signing key. ·That is most
459605 ·* appropriate for the case where none of the public keys have trust
4a084d ·* information and the dynamic validation is run each time a key is used.
73495d ·*/
46af5a
5e7240 #define NO_RECURSION 1
6faf5a
bbaf5a
98bd12 /* Validate a signature. ·May be necessary to recursively validate the
03827b ···names attached to the signing key. */
3caf5a
f860fa static PGPUInt16·
48a7bb ringMntIntValidateSig (RingSet *set, union RingObject *sig, int depth)
e3bb36 {
de2011 ········union RingObject *key = sig->s.by;
764ba4 ¤   int i;
dd1aef ¤   int revoked = 0, axiomatic = 0, expired = 0;
b918d8 ¤   union RingObject *name = NULL;
e7cf94 #if !NO_RECURSION
721bf0 ¤   PGPUInt16 validity = 0;
33c605 ¤   PGPUInt16 best_trust = 0;
ef7dec #if PGPTRUSTMODEL>0
b72781 ¤   PGPUInt16 confidence = 0, trust = 0;·
b75fb1 ¤   PGPUInt16 best_validity = 0;
fa7454 #endif
947454 #endif
2caf5a
e0bc3c ¤   pgpAssert (set);
0ce01f ¤   pgpAssert (OBJISKEY (key));
50673f ¤   if (depth > set->pool->certdepth)
08c702 ¤   ¤   return 0;¤  ¤   /* exceeded cert depth */
3cb177 #if 0
bac462 ¤   fprintf (stdout, "Validating sig, depth = %d\n", depth);
9d7454 #endif
a2af5a
bf7365 ¤   /* Check the stack for a certification loop */
93f1bb ¤   for (i = 0; i < keystack_ptr; i++)
54af73 ¤   ¤   if (key == keystack[i])
581c83 ¤   ¤   ¤   return 0;¤  /* certification loop detected */
5467c5 ¤
5ef4d3 ¤   if (pgpVirtMaskIsEmpty(&key->g.mask))
dc245b ¤   ¤   return 0;¤  ¤   /* dummy key */
e5af5a
60d8af ¤   /*
975c09 ¤   ·* See if key has any potential to be a trusted introducer, return 0
ea4beb ¤   ·* if not
17a4e3 ¤   ·*/
8a1325 #if PGPTRUSTMODEL==0
d5c6df ¤   if ((key->k.trust & kPGPKeyTrust_Mask) <= kPGPKeyTrust_Never)
58b85f ¤   ········return 0;
b3db21 #else
042235 ¤   for (name = key->g.down; name; name = name->n.next) {
ce1680 ¤   ¤   if (OBJISNAME(name) &&
35a038 ¤   ¤   ¤   name->n.confidence != PGP_NEWTRUST_UNDEFINED &&
a7ce61 ¤   ¤   ¤   ¤   ¤   name->n.confidence != 0)
c9fc1e ¤   ¤   ¤   break;¤ ¤   ¤   ¤   /* exit loop with name<>NULL if trusted intr */
4b9371 ¤   }
62433f ¤   if (!name)
8dbbde ¤   ¤   return 0;
027454 #endif
--0262 000f9fc8f6a401001f7 Page 54 of pgpRngMnt.c
e0af5a
f8d8af ¤   /*
6db5f4 ¤   ·* This call may be overkill as it checks all sigs on key,
3202ca ¤   ·* while if we are
ed90de ¤   ·* not recursing we are only interested in revocation sigs.
11a4e3 ¤   ·*/
32846a ¤   ringMntIntCheckKey (set, key, &revoked, &axiomatic, &expired);
d3458b ¤   if (revoked || expired)
97bbde ¤   ¤   return 0;
90ccc8 ¤   if (axiomatic)
21518b ¤   ¤   return 0;¤  /* XXX Shouldn't axiomatic sigs be full valid? */
1faf5a
721773 #if NO_RECURSION
f04ba8 ¤   /* If a full dynamic validation is not required, simply
4928f1 ¤   ···get the confidence value from the pre-computed name
fb70bb ¤   ···validities. ·For old trust model, we must check for at least one
fadefe ¤   ···valid name, and then return the trust in the key as a
e1a7fd ¤   ···"score" */
481325 #if PGPTRUSTMODEL==0
dc2235 ¤   for (name = key->g.down; name; name = name->n.next) {
bee918 ¤   ········if (OBJISNAME (name) &&·
e183ae ¤   ¤   ····(name->n.trust & kPGPNameTrust_Mask) >·
f385f6 ¤   ¤   ····kPGPNameTrust_Untrusted)
a64cca ¤   ¤   ········return trust[key->k.trust & kPGPKeyTrust_Mask];
419371 ¤   }
d73e6b ¤   return 0;
a7db21 #else
3ad642 ¤   return calctrust (&key->k, set);
6b7454 #endif
7d556f #else ··/* !NO_RECURSION */
00af5a
3471e7 ¤   /* Recurse down (or up, whichever you prefer) and dynamically
3ca7f8 ¤   ···validate the signing key. */
e9af5a
f564c8 ¤   for (name = key->k.down; name; name = name->g.next) {
0d7149 ¤   ¤   if (!OBJISNAME (name))
0917f5 ¤   ¤   ¤   continue;
fe53f0 #if PGPTRUSTMODEL==0·
d86295 ¤   ¤   /* If the total "score" for a name exceeds thresh,
760366 ¤   ¤   ···then we consider the key to be valid and can
2e5e36 ¤   ¤   ···return its trust as a "score" */
ffaf5a
57069b ¤   ¤   validity = ringMntIntValidateName (set, name, depth);
54d0e2 ¤   ¤   if (validity >= thresh) ··/* scored a winner! */
0d4cca ¤   ¤   ········return trust[key->k.trust & kPGPKeyTrust_Mask];
2a6ba4 #else /* PGPTRUSTMODEL>0 */
970bf1 ¤   ¤   /* Get the validity of the name, and combine with the
832f91 ¤   ¤   ···confidence to get overall trust in the name.
010238 ¤   ¤   ···Keep track of the 'best' as this will be returned as
fe3966 ¤   ¤   ···the trust in the signing key. */
26af5a
1318a4 ¤   ¤   if (name->n.confidence == PGP_NEWTRUST_INFINITE)
8935ee ¤   ¤   ¤   confidence = PGP_TRUST_INFINITE;
afc3ef ¤   ¤   else if (name->n.confidence == PGP_NEWTRUST_UNDEFINED)
0c1a09 ¤   ¤   ¤   confidence = 0;
930e1d ¤   ¤   else
0d2e9b ¤   ¤   ¤   confidence = name->n.confidence << TRUST_CERTSHIFT;
6eaf5a
5682ec ¤   ¤   /* Don't bother validating name if its confidence is 0,
b7461f ¤   ¤   ···as it won't contribute to the confidence in the sig */
d3af5a
62236f ¤   ¤   if (confidence > 0) {
99ba82 ¤   ¤   ¤   validity = ringMntIntValidateName (set, name, depth);
aced61 ¤   ¤   ¤   trust = mergetrust (confidence, validity);
b41047 ¤   ¤   ¤   if (validity > best_validity ||·
a3be86 ¤   ¤   ¤   ····(validity == best_validity &&·
10da5e ¤   ¤   ¤   ·····trust > best_trust)) {
a7801c ¤   ¤   ¤   ¤   best_validity = validity;
bce64f ¤   ¤   ¤   ¤   best_trust = trust;
cca3a6 ¤   ¤   ¤   }
090fe4 ¤   ¤   }
f97454 #endif
--60a3 0002340d2e8401001f7 Page 55 of pgpRngMnt.c
a19371 ¤   }
e805a5 ¤   return best_trust;
2b7454 #endif
daefe6 }
67af5a
42296c #endif¤ /* ] PGPTRUSTMODEL!=2 */
bcaf5a
7cc593 /* Internal name validation function. ·Check all the signatures on the
f69f98 ···name. ·We can stop early if we hit infinite validity. */
4faf5a
bc8a37 static PGPUInt16
73bdb3 ringMntIntValidateName (RingSet *set, union RingObject *name, int depth)
dfbb36 {
422abf ¤   RingObject ····*key;
4faa81 ¤   PGPUInt16 ······validity = 0;
247c15 ¤   ················
b82095 #if PGPTRUSTMODEL==2
ff0c0a ¤   PathList ······*pathlist = NULL;
b1352d ¤   RingSet¤¤   ···*confidentset;
b0f444 ¤   unsigned ·······maxdepth = set->pool->certdepth;
6a6454 ¤   double ·········confidence;
2ddb21 #else
4b9675 ¤   PGPUInt32 ·¤¤   timenow = PGPGetTime ();
263a7f ¤   RingObject ····*obj;
eadead ¤   PGPUInt16¤  ¤   v = 0;
8d7454 #endif
09af5a
99bc3c ¤   pgpAssert (set);
0084e6 ¤   pgpAssert (OBJISNAME (name));
0300f1 ¤   key = name->n.up;
3db177 #if 0
144041 ¤   fprintf (stdout, "Validating name, depth = %d\n", depth);
707454 #endif
4daf5a
992095 #if PGPTRUSTMODEL==2
38af5a
87095a ¤   (void) depth;
9a67c5 ¤
1e6bdb ¤   confidentset = ringSetConfidentSet (set);
a1f61b ¤   ringFindPathsBack (name, &pathlist, maxdepth, confidentset, set,
2452f8 ¤   ¤   ¤   ¤   ¤   ···PGPGetTime(), set->pool);
0117ae ¤   if (pathlist) {
fcc521 ¤   ¤   pathlist = pathListPrune (pathlist, TOTALPATHMAX, set->pool);
7f24c1 ¤   ¤   confidence = pathListConfidence (pathlist, set->pool);
fc9e0b ¤   ¤   if (confidence == 1.)
7db5fa ¤   ¤   ¤   validity = PGP_TRUST_INFINITE;
f80e1d ¤   ¤   else
ab216d ¤   ¤   ¤   validity = ringDoubleToTrust (1. / (1.-confidence));
56ab6d ¤   ¤   pathListFreeAll (pathlist, set->pool);
ab99fa ¤   ¤   pathlist = NULL;
e99371 ¤   }
73af5a
183ff2 ¤   memPoolEmpty(&set->pool->pathpool);
bc3e9b ¤   set->pool->paths = NULL;
1918f8 ¤   set->pool->pathlists = NULL;
9624c4 ¤   ringSetDestroy (confidentset);
cbaf5a
2f923e #else /* PGPTRUSTMODEL!=2*/
e3af5a
f6669d ¤   keystack[keystack_ptr++] = key;¤¤   /* push key on the stack */
e7af5a
af4f43 ¤   /* Combine the trust in each signature to get the validity of
a0be4e ¤   ···the name. Must be careful to check for overflow, and need
081cf8 ¤   ···special handling for infinite trust. */
42af5a
44a4f8 ¤   validity = 0;
5d939e ¤   for (obj = name->n.down; obj; obj = obj->g.next) {
711faa ¤   ¤   pgpAssert (OBJISSIG (obj));
d473da ¤   ¤   if (pgpIsRingSetMember(set, obj) && obj->s.by != key) {
9ebdd8 ¤   ¤   ¤   if (ringMntGoodSig (set, obj, timenow)) {
6420ff ¤   ¤   ¤   ¤   v = ringMntIntValidateSig (set, obj,·
23ed65 ¤   ¤   ¤   ¤   ···························depth + 1);·
--ba2d 000ef99162e401001f7 Page 56 of pgpRngMnt.c
991325 #if PGPTRUSTMODEL==0
01d891 ¤   ¤   ¤   ¤   validity += v; ·/* add in "score" for sig */
275c9b ¤   ¤   ¤   ¤   if (validity >= thresh)
f660be ¤   ¤   ¤   ¤   ········break; ·/* name is valid */
00aa67 #else¤  ¤   ¤   ·······
1b1b79 ¤   ¤   ¤   ¤   if (v == PGP_TRUST_INFINITE) {
903724 ¤   ¤   ¤   ¤   ¤   validity = v;
b05e7c ¤   ¤   ¤   ¤   ¤   break; /* can't do better than this! */
642613 ¤   ¤   ¤   ¤   }
05060e ¤   ¤   ¤   ¤   else if (validity < PGP_TRUST_MAX) {
be92ca ¤   ¤   ¤   ¤   ¤   validity += v;
e5ed40 ¤   ¤   ¤   ¤   ¤   if (validity + 1 <= v)
5ea305 ¤   ¤   ¤   ¤   ¤   ··validity = PGP_TRUST_MAX;
f42613 ¤   ¤   ¤   ¤   }
449009 #endif¤ ¤   ¤   ¤
fca3a6 ¤   ¤   ¤   }
6b0fe4 ¤   ¤   }
ca9371 ¤   }
738f43 ¤   keystack_ptr--;¤¤   /* pop key off the stack */
940321 #endif /*PGPTRUSTMODEL!=2*/
d3ede2 ¤   return validity;
9befe6 }
23af5a
fa60de /* Validate a name from an untrusted keyfile. Externally visible. */
25af5a
1d314a void
16083c ringMntValidateName (RingSet const *set, union RingObject *name)
7bbb36 {
cf1bf0 ¤   PGPUInt16 validity = 0;
eebfe6 ¤   RingSet *allkeys;
8f1f80 ¤   int axiomatic = 0, revoked = 0, expired = 0;
89af5a
0ea758 /* Disable this code for now, not fully tested. */
67a91a /* pgpFixBeforeShip( "Later, make on-the-fly validation work" ); */
35ba0f return;
3eaf5a
dbbc3c ¤   pgpAssert (set);
049761 ¤   pgpAssert (name && OBJISNAME (name));
9b2c5c ¤   if (name->g.flags & (RINGOBJF_TRUST | RINGOBJF_TRUSTCHANGED))
1b66e1 ¤   ¤   return;¤ ······/* already done */
e7af5a
9adc5f ¤   if (!(name->g.flags & RINGOBJF_TRUSTCHANGED)) {
68af5a
e0e1ce ¤   ¤   /* Here's a real cheat. ·We copy the set and then
488c71 ¤   ¤   ···copy the allocmask from the parent pool for an instant
9cef5f ¤   ¤   ···union of all keys in the pool. */
483e31 ¤   ··
dcfdc1 ¤   ¤   allkeys = ringSetCopy (set);
5a9229 ¤   ¤   pgpAssert (allkeys);
d67483 ¤   ¤   ringSetFreeze (allkeys);
2c0481 ¤   ¤   ringAllocMask (set->pool, NULL, &allkeys->mask);
25af5a
72b48b ¤   ¤   ringMntIntCheckKey (allkeys, name->n.up, &revoked, &axiomatic,·
6de018 ¤   ¤   ¤   ¤   ····&expired);
9c1325 #if PGPTRUSTMODEL==0
59a043 ¤   ¤   ringMntInitTrust (allkeys);
1fb879 ¤   ¤   if (revoked)
30cdad ¤   ¤   ¤   validity = kPGPNameTrust_Untrusted;
505394 ¤   ¤   else if (axiomatic)
80d6e2 ¤   ¤   ¤   validity = kPGPNameTrust_Complete;
9907e0 ¤   ¤   else {
b94cf6 ¤   ¤   ¤   validity = ringMntIntValidateName (allkeys, name, 0);
5899ce ¤   ¤   ¤   if (validity >= thresh)
600e50 ¤   ¤   ¤   ¤   validity = kPGPNameTrust_Complete;
4ed306 ¤   ¤   ········else if (validity * 2 >= thresh)
c0aee6 ¤   ¤   ¤   ¤   validity = kPGPNameTrust_Marginal;
51bb8c ¤   ¤   ¤   else
405bec ¤   ¤   ¤   ¤   validity = kPGPNameTrust_Untrusted;
4e0fe4 ¤   ¤   }
f9ee0f ¤   ¤   name->n.trust = (name->n.trust & ~kPGPNameTrust_Mask) |·
910602 ¤   ¤   ··validity;
efdb21 #else
--beae 00138eec495401001f7 Page 57 of pgpRngMnt.c
6e3e3d ¤   ¤   name->n.valid = 0;
d7b879 ¤   ¤   if (revoked)
ae2a15 ¤   ¤   ¤   name->n.valid = 0;
925394 ¤   ¤   else if (axiomatic)
4317c2 ¤   ¤   ¤   name->n.valid = PGP_TRUST_INFINITE;
f8ee26 ¤   ¤   else·
1b9040 ¤   ¤   ········name->n.valid = ringMntIntValidateName·
5aefa0 ¤   ¤   ¤   ·······················(allkeys, name, 0);
d4ebca ¤   ¤   if (name->n.valid == PGP_TRUST_INFINITE) {
f2217e ¤   ¤   ¤   name->n.validity = PGP_NEWTRUST_INFINITE;
0545a6 ¤   ¤   } else {
6903b1 ¤   ¤   ¤   validity = name->n.valid >> TRUST_CERTSHIFT;
fac20f ¤   ¤   ¤   name->n.validity = (validity > PGP_NEWTRUST_MAX) ?
2b7299 ¤   ¤   ¤   ···················PGP_NEWTRUST_MAX : (PGPByte) validity;
f50fe4 ¤   ¤   }
357454 #endif
5096a4 ¤   ¤   name->g.flags |= RINGOBJF_TRUSTCHANGED;
f64690 ¤   ¤   ringSetDestroy (allkeys);
5d9371 ¤   }
ffefe6 }
5caf5a
75bb6d /* Validate a key from an untrusted keyfile. ·Externally visible. */
c0af5a
cdc823 void·
bcf3a4 ringMntValidateKey (RingSet const *set, union RingObject *key)
16bb36 {
513d81 ¤   union RingObject *name;
4a1aef ¤   int revoked = 0, axiomatic = 0, expired = 0;
1d67c5 ¤
82a758 /* Disable this code for now, not fully tested. */
49a91a /* pgpFixBeforeShip( "Later, make on-the-fly validation work" ); */
04ba0f return;
8faf5a
67bc3c ¤   pgpAssert (set);
da7b06 ¤   pgpAssert (key && OBJISKEY (key));
fdaf5a
ddcee3 ¤   if (!(key->g.flags & (RINGOBJF_TRUST | RINGOBJF_TRUSTCHANGED))) {
8c97e6 ¤   ¤   ringMntIntCheckKey (set, key, &revoked, &axiomatic, &expired);
1fb879 ¤   ¤   if (revoked)
781ffd ¤   ¤   ¤   key->k.trust |= PGP_KEYTRUSTF_REVOKED;
06c7cb ¤   ¤   key->g.flags |= RINGOBJF_TRUSTCHANGED;
2a9371 ¤   }
fcaf5a
7e21c6 ¤   for (name = key->k.down; name; name = name->n.next) {
d9bd02 ¤   ¤   if (ringObjectType (name) == RINGTYPE_NAME)
f1f477 ¤   ¤   ¤   ringMntValidateName (set, name);
e39371 ¤   }
34efe6 }
59af5a
b438e5 /*
cce6c5 ·* Local Variables:
5b9b19 ·* tab-width: 4
99e7a4 ·* End:
5eb612 ·* vi: ts=4 sw=4
086c42 ·* vim: si
38495d ·*/
--5d0f 0018c3dacd1401001f8 Page 1 of pgpRngMnt.h
bc38e5 /*
19bb89 ·* $Id: pgpRngMnt.h,v 1.15 1998/06/03 20:24:45 hal Exp $
78495d ·*/
39af5a
825ee1 #ifndef Included_pgpRngMnt_h
6edfd7 #define Included_pgpRngMnt_h
0faf5a
87d11f #include "pgpUsuals.h"
6caf5a
cf99c6 PGP_BEGIN_C_DECLARATIONS
2aaf5a
b3adb8 #include "pgpOpaqueStructs.h"
deaf5a
e92b05 PGPUInt16¤  ringKeyCalcTrust(RingSet const *set,
db7d1f ¤   ¤   ¤   ¤   ¤   union RingObject *key);
e28d77 int¤¤   ¤   ringMnt(RingSet const *set, RingSet *dest,·
c5bedf ¤   ¤   ¤   ¤   ····PGPUInt32 const timenow);
049346 int¤¤   ¤   ringPoolCheckCount(RingSet const *sigset, RingSet const *keyset,
5fa518 ¤   ¤   ¤   ¤   ¤   PGPBoolean allflag, PGPBoolean revocationonly);
7c8f3f PGPError¤   ringPoolCheck(RingSet const *sigset, RingSet const *keyset,
3d4c18 ¤   ¤   ¤   ¤   ¤   PGPBoolean allflag, PGPBoolean revocationonly,
190a9d ¤   ¤   ¤   ¤   ¤   PGPError (*func)(void *, RingIterator *, int), void *arg);
bbb6c6 int¤¤   ¤   ringHashObj (PGPHashContext *hc, union RingObject *obj,
1e7fe2 ¤   ¤   ¤   ¤   ¤   RingSet const *set, int hashnamelength);
50bbe3 int¤¤   ¤   ringSignObj(PGPByte *sig, RingSet *dest,
fb1e26 ¤   ¤   ¤   ¤   ¤   union RingObject *obj, PGPSigSpec *spec,
5340df ¤   ¤   ¤   ¤   ¤   PGPRandomContext const *rc);
7d2f2c void¤   ¤   ringMntValidateName (RingSet const *set, union RingObject *name);
68bed8 void¤   ¤   ringMntValidateKey (RingSet const *set, union RingObject *key);
5baf5a
4c1254 PGP_END_C_DECLARATIONS
cbaf5a
8c5eff #endif /* Included_pgpRngMnt_h */
--1a07 00051b0c3cc401001f9 Page 1 of pgpRngPars.c
bc38e5 /*
a38fbf ·* pgpRngPars.c - parse structures from a keyring. ·Validates its
922fd2 ·* inpout very carefully, for use by ringopen.c.
157157 ·* Also includes routines to "unparse" and assemble keyring packets.
4a775e ·*
2c68c2 ·* Written by Colin Plumb.
ff775e ·*
6ac4cf ·* $Id: pgpRngPars.c,v 1.37 1998/06/11 18:28:11 hal Exp $
ae495d ·*/
12e2ff #include "pgpConfig.h"
f1af5a
19324c #include <string.h>
2aaf5a
7fa146 #include "pgpDebug.h"
642e22 #include "pgpRngPars.h"
9855d0 #include "pgpRngPriv.h"¤/* For ringHashBuf, pgpFingerprint20HashBuf */
545417 #include "pgpHashPriv.h"
1dd11f #include "pgpUsuals.h"
d2c5b0 #include "pgpKeySpec.h"
042f8d #include "pgpErrors.h"
d5cdc2 #include "pgpPubKey.h"
149c38 #include "pgpPktByte.h"
78f5ab #include "pgpSigSpec.h"
af0d08 #include "pgpMem.h"
31af5a
850596 #ifndef NULL
ed699b #define NULL 0
507454 #endif
87af5a
d8af5a
1938e5 /*
c8976f ·* Read a key from the buffer and extract vital statistics.
a3d1b7 ·* If the KeyID cannot be determined, a fake keyID with a 32-bit CRC
2bee48 ·* stuffed in the middle is created. ·This is designed to assist
dc2685 ·* matching of bad keys.
d0775e ·*
d03182 ·* A key is:
862c79 ·* ·0 Version: 1 byte
f95783 ·* ·1 Timestamp: 4 bytes
05f7bc ·* ·5 Validity: 2 bytes ·(skipped if version PGPVERSION_4)
4260af ·* ·7 Algorithm: 1 byte
31cca6 ·* [Algorithm-specific portion]
1f770b ·* ·8 Some MP number from which we can extract key ID: modulus, etc.
4058c2 ·* [Other algorithm-specific fields]
55fe70 ·* [with possible extra data if it's a secret key]
d0775e ·*
3b35e9 ·* If "secretf" is set, additional data is allowed at the end of the
2c1215 ·* packet. ·If it is clear, additional data results in kPGPError_KEY_LONG.
0c0a80 ·* (The format of the extra data is not checked.)
07495d ·*/
174d2f int
cd3863 ringKeyParse(PGPContextRef context, PGPByte const *buf, size_t len,
5d5bfa ¤   ¤   PGPByte *pkalg, PGPByte keyID[8], PGPUInt16 *keybits,
a3d750 ¤   ¤   PGPUInt32 *tstamp, PGPUInt16 *validity, PGPByte *v3, int secretf)
9dbb36 {
d6377e ¤   unsigned mlen, elen;
8e17e6 ¤   int err;
dc6932 ¤   unsigned vsize;
2caf5a
7706ff ¤   /* Defaults in case of error */
bf26ff ¤   if (v3)
639425 ¤   ¤   *v3 = 0;
3c0a73 ¤   if (keyID)
e62f97 ¤   ¤   pgpClearMemory( keyID, ·8);
93d878 ¤   if (keybits)
18ce4b ¤   ¤   *keybits = 0;
6d867a ¤   if (tstamp)
f7c9d0 ¤   ¤   *tstamp = 0;
69d281 ¤   if (validity)
d774f8 ¤   ¤   *validity = 0;
1c13a1 ¤   if (pkalg)
511e51 ¤   ¤   *pkalg = 0;
--85ee 00016350852401001f9 Page 2 of pgpRngPars.c
e0af5a
880ece ¤   if (len < 1)
004d9f ¤   ¤   goto fakeid_short;
d6af5a
aae833 ¤   if (!KNOWN_PGP_VERSION(buf[0])) {
72557f ¤   ¤   err = kPGPError_UnknownKeyVersion;
9c4ad0 ¤   ¤   goto fakeid;
019371 ¤   }
ec4bde ¤   /* PGPVERSION_4 keys have no validity field */
6cbc29 ¤   if (buf[0] == PGPVERSION_4) {
7b6668 ¤   ¤   *v3 = FALSE;
c673d8 ¤   ¤   vsize = 0;
98f037 ¤   } else {
888605 ¤   ¤   *v3 = TRUE;
0ec660 ¤   ¤   vsize = 2;
7b9371 ¤   }
c36daf ¤   if (len < 5)
2a4d9f ¤   ¤   goto fakeid_short;
97af5a
c5867a ¤   if (tstamp)
606a38 ¤   ¤   *tstamp = (PGPUInt32)((unsigned)buf[1] << 8 | buf[2]) << 16 |
1a4e6a ¤   ¤   ¤   ((unsigned)buf[3] << 8 | buf[4]);
0c9e10 ¤   if (len < 5 + vsize)
6c4d9f ¤   ¤   goto fakeid_short;
dc033e ¤   if (validity ·&& ·vsize)
f7ee2e ¤   ¤   *validity = (unsigned)buf[5] << 8 | buf[6];
b960a3 ¤   if (len < 6 + vsize)
c44d9f ¤   ¤   goto fakeid_short;
1a13a1 ¤   if (pkalg)
9c2e56 ¤   ¤   *pkalg = buf[5 + vsize];
13297e ¤   if (len < 8 + vsize)
b34d9f ¤   ¤   goto fakeid_short;
85af5a
799ad7 ¤   /* Get bytes in modulus */
0a89ba ¤   mlen = (unsigned)buf[6 + vsize] << 8 | buf[7 + vsize];
2dd878 ¤   if (keybits)
11fd4b ¤   ¤   *keybits = (PGPUInt16)mlen;
fcaf5a
b4bbb2 ¤   if (mlen && len > 8 + vsize && buf[8 + vsize] >> ((mlen-1)&7) != 1) {
71e3ae ¤   ¤   err = kPGPError_MalformedKeyModulus;
f94ad0 ¤   ¤   goto fakeid;
2f9371 ¤   }
1a84cc ¤   mlen = (mlen + 7) / 8;
368cfc ¤   if (len < 8 + vsize + mlen)
4e4d9f ¤   ¤   goto fakeid_short;
a7af5a
67841c ¤   if (len < 10 + vsize + mlen)
65a27a ¤   ¤   return kPGPError_KeyPacketTruncated;
d5af5a
d5847c ¤   if (buf[5 + vsize] == kPGPPublicKeyAlgorithm_RSA ||
55a586 ¤   ····buf[5 + vsize] == kPGPPublicKeyAlgorithm_RSAEncryptOnly ||
e91e39 ¤   ¤   buf[5 + vsize] == kPGPPublicKeyAlgorithm_RSASignOnly) {
42b617 ¤   ¤   /* Sanity checks on the exponent */
5f21f2 ¤   ¤   elen = (unsigned)buf[8+vsize+mlen] << 8 | buf[9+vsize+mlen];
a1ee7a ¤   ¤   if (elen && len > 10+vsize+mlen &&
f0962f ¤   ¤   ¤   ¤   buf[10+vsize+mlen] >> ((elen-1)&7) != 1)
5baacf ¤   ¤   ¤   return kPGPError_MalformedKeyExponent;
d4af9a ¤   ¤   elen = (elen + 7) / 8;
c3af5a
9aa894 ¤   ¤   if (len < 10+vsize+mlen+elen)
4ef0e7 ¤   ¤   ¤   return kPGPError_KeyPacketTruncated;
76a0d8 ¤   ¤   if ((buf[8 + vsize + mlen-1] & 1) == 0)
b664df ¤   ¤   ¤   return kPGPError_RSAPublicModulusIsEven;
e5b87f ¤   ¤   if ((buf[10+vsize+mlen+elen-1] & 1) == 0)
4379a2 ¤   ¤   ¤   return kPGPError_RSAPublicExponentIsEven;
fc1ac1 ¤   ¤   if (len > 10+vsize+mlen+elen && !secretf)
cdc4a6 ¤   ¤   ¤   return kPGPError_KEY_LONG;
fa9371 ¤   }
77be81 ¤   if (keyID) {
b4b5c7 ¤   ¤   if (buf[0] < PGPVERSION_4) {
b61f17 ¤   ¤   ¤   /* Old keyid rules, low 64 bits of modulus */
16efc0 ¤   ¤   ¤   memcpy(keyID, buf + 8 + vsize + mlen - 8, 8);
--8f26 00041cc3031401001f9 Page 3 of pgpRngPars.c
fa3c6e ¤   ¤   ¤   if (mlen < 8)
796512 ¤   ¤   ¤   ¤   pgpClearMemory( keyID, ·8 - mlen);
c345a6 ¤   ¤   } else {
e37aad ¤   ¤   ¤   /*
8415f2 ¤   ¤   ¤   ·* PGPVERSION_4 (aka V4) keys use newer keyID algorithm.
e1e47d ¤   ¤   ¤   ·* Low bits of fingerprint20 hash of key, but we can't
d8b7ae ¤   ¤   ¤   ·* use that function directly as key is not assembled yet.
178753 ¤   ¤   ¤   ·*/
31d8ff ¤   ¤   ¤   PGPByte hash[20];
707d4a ¤   ¤   ¤   if (secretf)
044400 ¤   ¤   ¤   ¤   len = ringKeyParsePublicPrefix(buf, len);
95b21e ¤   ¤   ¤   err = pgpFingerprint20HashBuf(context, buf, len, hash);
40555a ¤   ¤   ¤   if (err < 0)
f2454a ¤   ¤   ¤   ¤   return err;
bce246 ¤   ¤   ¤   pgpAssert (err == sizeof(hash));
c6d2ee ¤   ¤   ¤   memcpy(keyID, hash+sizeof(hash)-8, 8);
610fe4 ¤   ¤   }
6e9371 ¤   }
3faf5a
843e6b ¤   return 0;
4daf5a
5847ba fakeid_short:
b9b04c ¤   err = kPGPError_KeyPacketTruncated;
953ab0 fakeid:
99d8af ¤   /*
943de7 ¤   ·* We couldn't read a KeyID. ·Create a bogus one.
a017ab ¤   ·* The low 32 bits are 0 (which really stands out in a
1bfe25 ¤   ·* keyring listing and is impossible in the usual case),
5c2ddf ¤   ·* but the high 32 bits are a CRC of the packet, to reduce
c71815 ¤   ·* reports of keyID collisions.
dba4e3 ¤   ·*/
99be81 ¤   if (keyID) {
97f804 ¤   ¤   PGPUInt32 fake = ringHashBuf(buf, len);
f3f8b0 ¤   ¤   keyID[0] = (PGPByte)(fake >> 24);
db1214 ¤   ¤   keyID[1] = (PGPByte)(fake >> 16);
86c3fa ¤   ¤   keyID[2] = (PGPByte)(fake >> 8);
0d383c ¤   ¤   keyID[3] = (PGPByte)fake;
d49371 ¤   }
445ea8 ¤   return err;
f6efe6 }
34af5a
870e99 /* Extract the modulus from a key and return it (buffer & length) */
a5d929 PGPByte const *
bb5e0e ringKeyParseModulus(PGPByte const *buf, size_t len, unsigned *lenp)
8dbb36 {
03aa79 ¤   unsigned msize;
d46932 ¤   unsigned vsize;
8baf5a
d9f8a9 ¤   *lenp = 0;
1bbc29 ¤   if (buf[0] == PGPVERSION_4) {
db73d8 ¤   ¤   vsize = 0;
8ef037 ¤   } else {
d7c660 ¤   ¤   vsize = 2;
289371 ¤   }
5faf5a
a32171 ¤   if (len < 8+vsize || !KNOWN_PGP_VERSION(buf[0]) ||·
8f6781 ¤   ····(buf[5+vsize] != kPGPPublicKeyAlgorithm_RSA &&
9636d7 ¤   ·····buf[5+vsize] != kPGPPublicKeyAlgorithm_RSAEncryptOnly &&
db2c18 ¤   ¤   ·buf[5+vsize] != kPGPPublicKeyAlgorithm_RSASignOnly))
45bbde ¤   ¤   return 0;
0aaf5a
1b9ad7 ¤   /* Get bytes in modulus */
3f7ca3 ¤   msize = (unsigned)buf[6+vsize] << 8 | buf[7+vsize];
0e2856 ¤   msize = (msize + 7) / 8;
5baf5a
7d9595 ¤   *lenp = msize;
b84fb0 ¤   return buf + 8 + vsize;
17efe6 }
11af5a
29f3f7 /* Extract the exponent from a key and return it (buffer & length) */
3ed929 PGPByte const *
410c14 ringKeyParseExponent(PGPByte const *buf, size_t len, unsigned *lenp)
--b3cc 00084f16a61401001f9 Page 4 of pgpRngPars.c
2cbb36 {
64c87c ¤   unsigned size;
1d6932 ¤   unsigned vsize;
e2af5a
1bf8a9 ¤   *lenp = 0;
3faf5a
dcbc29 ¤   if (buf[0] == PGPVERSION_4) {
6b73d8 ¤   ¤   vsize = 0;
6ef037 ¤   } else {
16c660 ¤   ¤   vsize = 2;
799371 ¤   }
38af5a
93dfdc ¤   if (len < 10+vsize || !KNOWN_PGP_VERSION(buf[0]) ||·
ad6781 ¤   ····(buf[5+vsize] != kPGPPublicKeyAlgorithm_RSA &&
de36d7 ¤   ·····buf[5+vsize] != kPGPPublicKeyAlgorithm_RSAEncryptOnly &&
d72c18 ¤   ¤   ·buf[5+vsize] != kPGPPublicKeyAlgorithm_RSASignOnly))
537ed2 ¤   ¤   return NULL;
00af5a
d29ad7 ¤   /* Get bytes in modulus */
edd2a0 ¤   size = (unsigned)buf[6+vsize] << 8 | buf[7+vsize];
c8d83c ¤   size = (size + 7) / 8;
37af5a
e181a4 ¤   if (len < 10 + vsize + size)
a37ed2 ¤   ¤   return NULL;
54af5a
418c23 ¤   /* Skip modulus */
8a192a ¤   size += 8 + vsize;
cde39e ¤   buf += size;
52de75 ¤   len -= size;
78af5a
5b86f4 ¤   /* Get bytes in exponent */
851f54 ¤   size = (unsigned)buf[0] << 8 | buf[1];
61d83c ¤   size = (size + 7) / 8;
18af5a
e834cb ¤   if (len < 2 + size)
0b7ed2 ¤   ¤   return NULL;
55af5a
ecd7a2 ¤   *lenp = size;
e23e1b ¤   return buf + 2;
1aefe6 }
6faf5a
8e38e5 /*
94ca29 ·* Return a pointer to the "extra" part of the signature packet, the part
49e660 ·* which gets hashed. ·We use two different conventions, one for PGP 2.6
21218a ·* and earlier, and the other for the later version packets. ·The latter
34ba98 ·* includes the whole packet up through the variable part.
06775e ·*
f0d481 ·* buf¤ ¤   Signature buffer pointer
a93e4e ·* len¤ ¤   buf length in bytes
d6e7eb ·* lenp¤¤   Return pointer to length of extra buffer
33495d ·*/
b1d929 PGPByte const *
f8679b ringSigParseExtra(PGPByte const *buf, size_t len, unsigned *lenp)
c6bb36 {
0c63ed ¤   *lenp = 0;¤ ¤   ¤   ¤   ¤   /* In case of error */
5ebc29 ¤   if (buf[0] == PGPVERSION_4) {
f7c50c ¤   ¤   unsigned extralen;
1b58e8 ¤   ¤   if (len < 6)¤   ¤   ¤   /* Too short */
59cf03 ¤   ¤   ¤   return NULL;
9355f3 ¤   ¤   extralen = (unsigned)buf[4]<<8 | buf[5];
238ae7 ¤   ¤   if (len < 6 + extralen)
598b14 ¤   ¤   ¤   return NULL;¤   ¤   /* Too short */
0dcd7d ¤   ¤   *lenp = 6 + extralen;
e548d2 ¤   ¤   return buf;
adf037 ¤   } else {
8dc5ef ¤   ¤   /* Format from version 2.6 and earlier */
0b402b ¤   ¤   if (len < 2 || !KNOWN_PGP_VERSION(buf[0]) || len < 2u + buf[1])
09d563 ¤   ¤   ¤   return NULL;¤   /* Too short or bad version */
707228 ¤   ¤   *lenp = buf[1];
70dc5a ¤   ¤   return buf+2;
f49371 ¤   }
84efe6 }
--bede 000d9d259b2401001f9 Page 5 of pgpRngPars.c
e0af5a
e59731 /* Extract the RSA integer from a sig and return it (buffer & length) */
3fd929 PGPByte const *
ef06f1 ringSigParseInteger(PGPByte const *buf, size_t len, unsigned *lenp)
c7bb36 {
e7c87c ¤   unsigned size;
27af5a
caf8a9 ¤   *lenp = 0;
a9af5a
b3d2c2 ¤   if (len < 2 || !KNOWN_PGP_VERSION(buf[0]))
acd258 ¤   ¤   return NULL;¤   /* Too short or bad version */
f35e19 ¤   if (len < 16u + buf[1])
b32f4f ¤   ¤   return NULL;¤   /* Too short */
2449fb ¤   /* Skip forward to PK algorithm */
9a7687 ¤   len -= 10 + buf[1];
0dd092 ¤   buf += 10 + buf[1];
21ce17 ¤   if (buf[0] != kPGPPublicKeyAlgorithm_RSA &&
da89ac ¤   ····buf[0] != kPGPPublicKeyAlgorithm_RSAEncryptOnly &&
b61669 ¤   ····¤   buf[0] != kPGPPublicKeyAlgorithm_RSASignOnly)
dbdd9f ¤   ¤   return NULL;¤   /* Not RSA */
52af5a
089ad7 ¤   /* Get bytes in modulus */
9b9617 ¤   size = (unsigned)buf[4] << 8 | buf[5];
56d83c ¤   size = (size + 7) / 8;
7baf5a
008457 ¤   if (len < 6 + size)
077ed2 ¤   ¤   return NULL;
b9af5a
c1d7a2 ¤   *lenp = size;
3f5d7a ¤   return buf + 6;
bdefe6 }
89af5a
f6e1a7 /* Forward reference */
a7beb7 static int
c10326 ringSigParse3(PGPByte const *buf, size_t len, PGPByte *pkalg, PGPByte keyID[8],
e7327b ¤   PGPUInt32 *tstamp, PGPUInt16 *validity, PGPByte *type, PGPByte *hashalg,
3157f2 ¤   size_t *extralen, PGPByte *version, PGPBoolean *exportable,
5d4ba9 ¤   PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
25d802 ¤   PGPBoolean *hasRegExp, PGPBoolean *isX509);
77beb7 static int
ca0572 ringSigParseSubpackets(PGPByte const *buf, PGPByte keyID[8],
eb70bf ¤   PGPUInt32 *tstamp, PGPUInt16 *validity, PGPBoolean *exportable,
894ba9 ¤   PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
8cd802 ¤   PGPBoolean *hasRegExp, PGPBoolean *isX509);
6caf5a
f8af5a
5238e5 /*
7d23f9 ·* Read a signature from the file, positioned just after the header.
97dbbb ·* "len" is the length of the signature packet. ·Leaves the file
5725cc ·* pointed after the length.
66775e ·*
aecf14 ·* A signature is:
5c2c79 ·* ·0 Version: 1 byte
cd615c ·* ·1 Length of following material: 1 byte (must be 5!)
9e435d ·* ·2 Signature type: 1 byte
00395b ·* ·3 Timestamp: 4 bytes
878f3e ·* ·7 KeyID: 8 bytes
0c674f ·* 15 Public-key algorithm: 1 byte
77ab05 ·* 16 Hash algorithm: 1 byte
7328fb ·* 17 First 2 bytes of hash: 2 bytes
f640ff ·* 19 MPI of signature (header)
13329d ·* 21 MPI of signature (data)
54775e ·*
056ea7 ·* This reads up to the keyID (15 bytes) into a buffer,
3529ab ·* then sets up the various fields.
31495d ·*/
134d2f int
54751e ringSigParse(PGPByte const *buf, size_t len, PGPByte *pkalg, PGPByte keyID[8],
d3327b ¤   PGPUInt32 *tstamp, PGPUInt16 *validity, PGPByte *type, PGPByte *hashalg,
5057f2 ¤   size_t *extralen, PGPByte *version, PGPBoolean *exportable,
dd4ba9 ¤   PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
d9df3e ¤   PGPBoolean *hasRegExp, PGPBoolean *isX509)
--a46c 000eea778dd401001f9 Page 6 of pgpRngPars.c
2cbb36 {
7973b1 ¤   unsigned l;¤/* extralen */
8e0ed5 ¤   unsigned t;
93afba ¤   PGPByte alg;
0eaf5a
e526e0 ¤   /* Default settings in case of error */
8f13a1 ¤   if (pkalg)
9c1e51 ¤   ¤   *pkalg = 0;
970a73 ¤   if (keyID)
232f97 ¤   ¤   pgpClearMemory( keyID, ·8);
74867a ¤   if (tstamp)
fbc9d0 ¤   ¤   *tstamp = 0;
48d281 ¤   if (validity)
8774f8 ¤   ¤   *validity = 0;
6d06a6 ¤   if (type)
a999f3 ¤   ¤   *type = 255;
5e4255 ¤   if (hashalg)
c8c64d ¤   ¤   *hashalg = 255;
eae8cf ¤   if (extralen)
8539d9 ¤   ¤   *extralen = 0;
086379 ¤   if (version)
4a7114 ¤   ¤   *version = 0;
14d1f4 ¤   if (exportable)
e9895f ¤   ¤   *exportable = TRUE;
cabc35 ¤   if (revocable)
2a2578 ¤   ¤   *revocable = TRUE;
a28c67 ¤   if (trustLevel)
c42e79 ¤   ¤   *trustLevel = 0;
ee6702 ¤   if (trustValue)
45f9cd ¤   ¤   *trustValue = 0;
365236 ¤   if (hasRegExp)
4de0c0 ¤   ¤   *hasRegExp = FALSE;
b04fc8 ¤   if (isX509)
6f2eaf ¤   ¤   *isX509 = FALSE;
60af5a
6d0ece ¤   if (len < 1)
77ef4d ¤   ¤   return kPGPError_TruncatedSignature;
4329db ¤   /* Forward compatibility */
0abc29 ¤   if (buf[0] == PGPVERSION_4) {
eb3ce5 ¤   ¤   return ringSigParse3(buf, len, pkalg, keyID, tstamp, validity, type,
f86cc2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·hashalg, extralen, version, exportable,
ca0652 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·revocable, trustLevel, trustValue, hasRegExp,
01c096 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·isX509);
219371 ¤   }
6f6379 ¤   if (version)
76e29a ¤   ¤   *version = buf[0];
13a714 ¤   if (!KNOWN_PGP_VERSION(buf[0]))
a1f13b ¤   ¤   return kPGPError_UnknownSignatureVersion;
11e1aa ¤   if (len < 2)
44ef4d ¤   ¤   return kPGPError_TruncatedSignature;
04b2fd ¤   l = buf[1];
ade8cf ¤   if (extralen)
171f99 ¤   ¤   *extralen = l;
362e69 ¤   if (l >= 1) {
47fafd ¤   ¤   if (len < 3)
92bdd0 ¤   ¤   ¤   return kPGPError_TruncatedSignature;
a68313 ¤   ¤   if (type)
6267b6 ¤   ¤   ¤   *type = buf[2];
50cb47 ¤   ¤   if (l >= 5 && tstamp) {
c3284d ¤   ¤   ¤   if (len < 7)
3ceecb ¤   ¤   ¤   ¤   return kPGPError_TruncatedSignature;
e3c829 ¤   ¤   ¤   *tstamp = (PGPUInt32)((unsigned)buf[3]<<8|buf[4]) << 16 |
bb9cae ¤   ¤   ¤   ··················((unsigned)buf[5]<<8|buf[6]);
8c0fe4 ¤   ¤   }
975b13 ¤   ¤   if (l >= 7 && tstamp) {
8a3856 ¤   ¤   ¤   if (len < 9)
a9eecb ¤   ¤   ¤   ¤   return kPGPError_TruncatedSignature;
bbb738 ¤   ¤   ¤   *tstamp = (PGPUInt16)buf[7]<<8 | buf[8];
ba0fe4 ¤   ¤   }
769371 ¤   }
a29d28 ¤   if (!extralen && l != 5)
eeccaf ¤   ¤   return kPGPError_ExtraSignatureMaterial;
--a0eb 000103708a3401001f9 Page 7 of pgpRngPars.c
97b29f ¤   if (len < l+10)
0eef4d ¤   ¤   return kPGPError_TruncatedSignature;
c30a73 ¤   if (keyID)
1b481c ¤   ¤   memcpy(keyID, buf + 7, 8);
77e843 ¤   if (len < l+11)
05ef4d ¤   ¤   return kPGPError_TruncatedSignature;
fd0b1e ¤   alg = buf[l+10];
d713a1 ¤   if (pkalg)
8ac8a3 ¤   ¤   *pkalg = alg;
aeb177 #if 0
73619d ¤   if (buf[l+10] != kPGPPublicKeyAlgorithm_RSA &&
f7f35a ¤   ····buf[l+10] != kPGPPublicKeyAlgorithm_RSAEncryptOnly &&
61b902 ¤   ····¤   buf[l+10] != kPGPPublicKeyAlgorithm_RSASignOnly)
476aad ¤   ¤   return kPGPError_UnknownSignatureAlgorithm;
fd7454 #endif
050727 ¤   if (len < l+12)
dcef4d ¤   ¤   return kPGPError_TruncatedSignature;
434255 ¤   if (hashalg)
0bec36 ¤   ¤   *hashalg = buf[l+11];
0d6446 ¤   if (len < l+16)
38ef4d ¤   ¤   return kPGPError_TruncatedSignature;
b25699 ¤   t = (unsigned)buf[l+14] << 8 | buf[l+15];
352df8 ¤   if (t && len > l+16 && buf[l+16] >> ((t-1)&7) != 1)
6abc73 ¤   ¤   return kPGPError_MalformedSignatureInteger;
fe783b ¤   l += 16 + (t+7)/8;
0202b0 ¤   if (alg == kPGPPublicKeyAlgorithm_RSA ||
5bc681 ¤   ····alg == kPGPPublicKeyAlgorithm_RSAEncryptOnly ||
7fb01d ¤   ····alg == kPGPPublicKeyAlgorithm_RSASignOnly) {
22ec6d ¤   ¤   if (len != l)
d1b903 ¤   ¤   ¤   return len < l ? kPGPError_TruncatedSignature : kPGPError_SIG_LONG;
a39371 ¤   }
853e6b ¤   return 0;
a8efe6 }
c2af5a
5f38e5 /*
018c15 ·* Version of ringSigParse for the signature packet formats being designed
d3a41e ·* for a future version. ·We do not fully handle them here, but we do a
cd693f ·* basic parse on the sigs and we make sure there are no critical fields
c92a27 ·* that we can't handle.
89775e ·*
6224ea ·* Sig layout:
c2775e ·*
8fe13a ·* Offset,Length ·Meaning
aecdd8 ·*¤ 0¤  ¤   1¤  Version byte (=4)
63ba53 ·*¤ 1¤  ¤   1¤  Signature type (included in hash) (nested flag)
ce62d3 ·*¤ 2¤  ¤   1¤  PK algorithm (1 = RSA) (included in hash)
fccf37 ·*¤ 3¤  ¤   1¤  Hash algorithm (1 = MD5) (included in hash)
4a97b9 ·*¤ 4¤  ¤   2¤  Length of extra material included in hash (=y)
ba2ceb ·*¤ 6¤  ¤   y¤  Subpackets (hashed)
b34dc8 ·* ·6+y¤¤   2¤  Length of extra material not included in hash (=z)
6e8899 ·* ·8+y¤¤   z¤  Subpackets (unhashed)
157d36 ·*=====
90c943 ·*remainder not present on sig headers
c87d36 ·*=====
96b52a ·*¤ 8+y+z¤  2¤  First 2 bytes of message digest (16-bit checksum)
757730 ·*¤ 10+y+z¤ 2+w¤MPI of PK-signed integer
da5f5e ·*¤ 12+y+z+w
28775e ·*
ca495d ·*/
19beb7 static int
2c0326 ringSigParse3(PGPByte const *buf, size_t len, PGPByte *pkalg, PGPByte keyID[8],
09327b ¤   PGPUInt32 *tstamp, PGPUInt16 *validity, PGPByte *type, PGPByte *hashalg,
d057f2 ¤   size_t *extralen, PGPByte *version, PGPBoolean *exportable,
b44ba9 ¤   PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
37df3e ¤   PGPBoolean *hasRegExp, PGPBoolean *isX509)
6cbb36 {
9105d3 ¤   unsigned¤   l;¤ ¤   ¤   ¤   /* extralen */
9c8a01 ¤   unsigned¤   t;¤ ¤   ¤   ¤   /* bit count of first MPI */
f70e8c ¤   size_t¤ ¤   mpiend;¤¤   ¤   /* byte position past first MPI */
e1b519 ¤   PGPByte¤¤   alg;¤   ¤   ¤   /* pk alg for sig */
e1af5a
106379 ¤   if (version)
--8ad5 000ab72c1d0401001f9 Page 8 of pgpRngPars.c
7ce29a ¤   ¤   *version = buf[0];
ef92d0 ¤   if (len < 8)
23ef4d ¤   ¤   return kPGPError_TruncatedSignature;
c806a6 ¤   if (type)
77b41e ¤   ¤   *type = buf[1];
64f020 ¤   alg = buf[2];
0e13a1 ¤   if (pkalg)
5ec8a3 ¤   ¤   *pkalg = alg;
394255 ¤   if (hashalg)
84470e ¤   ¤   *hashalg = buf[3];
ae7cae ¤   l = (unsigned)buf[4]<<8 | buf[5];¤  ¤   /* extra material */
ffe8cf ¤   if (extralen)
961f99 ¤   ¤   *extralen = l;
edf7c4 ¤   if (len < 6+l+2)
9cef4d ¤   ¤   return kPGPError_TruncatedSignature;
f65784 ¤   l += (unsigned)buf[l+6]<<8 | buf[l+7];¤ /* unhashed extra material */
0cd744 ¤   if (len < 8+l+2+2)
7bef4d ¤   ¤   return kPGPError_TruncatedSignature;
2f1e9a ¤   t = (unsigned)buf[l+10] << 8 | buf[l+11]; /* first MPI size in bits */
9ea53e ¤   mpiend = 8+l+2+2+(t+7)/8;
b0b440 ¤   if (len < mpiend)
42ef4d ¤   ¤   return kPGPError_TruncatedSignature;
bc6f54 ¤   if (t && buf[l+12] >> ((t-1)&7) != 1)
c0bc73 ¤   ¤   return kPGPError_MalformedSignatureInteger;
be9671 ¤   /* Special checking for RSA sigs */
a002b0 ¤   if (alg == kPGPPublicKeyAlgorithm_RSA ||
b6c681 ¤   ····alg == kPGPPublicKeyAlgorithm_RSAEncryptOnly ||
ec4627 ¤   ¤   alg == kPGPPublicKeyAlgorithm_RSASignOnly) {
f72bbb ¤   ¤   if (len > mpiend)
005487 ¤   ¤   ¤   return kPGPError_SIG_LONG;
7c9371 ¤   }
b587c7 ¤   ¤   ¤
275411 ¤   /* Now parse subpackets, pick up keyid, timestamp and validity info */
ee244a ¤   return ringSigParseSubpackets (buf+4, keyID, tstamp, validity, exportable,
189fd7 ¤   ¤   revocable, trustLevel, trustValue, hasRegExp, isX509);
afefe6 }
eeaf5a
b3af5a
0d38e5 /*
db8b5d ·* Parse the "extra data" on the new-style signature packets.
f7775e ·*
b0ec7b ·* This is a chain of subpackets, with the following format:
d8e13a ·* Offset,Length ·Meaning
5fae2c ·*¤ 0¤  x(1-2)¤ Subpacket length (=y)
d6aa3f ·*¤ x¤  1¤  Subpacket type (with critical flag)
5aad88 ·*¤ x+1¤y-1¤Subpacket data
d8775e ·*
eae8e1 ·* We are only parsing a few of the subpackets now, returning an error
74af28 ·* if we see any critical ones that we don't handle. ·Also, we require
0beef8 ·* there to be a keyid subpacket at present or it is an error.
90775e ·*
29c687 ·* There are two such chains, each preceded by a two-byte count. ·The
ee47e3 ·* first is hashed and the second is not.
8d495d ·*/
0ebeb7 static int
bf0572 ringSigParseSubpackets(PGPByte const *buf, PGPByte keyID[8],
d670bf ¤   PGPUInt32 *tstamp, PGPUInt16 *validity, PGPBoolean *exportable,
a94ba9 ¤   PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
fddf3e ¤   PGPBoolean *hasRegExp, PGPBoolean *isX509)
99bb36 {
b00d8f ¤   unsigned¤   len;¤   ¤   ¤   ····/* Length of chain of subpackets */
bf7a2a ¤   unsigned¤   sublen;¤¤   ¤   ¤   /* Length of subpacket */
1aefdd ¤   unsigned¤   offset;¤¤   ¤   ¤   /* Offset to next subpacket */
0e913f ¤   int ¤   ¤   type;¤  ¤   ¤   ¤   /* Type of subpacket */
288b76 ¤   int¤¤   ¤   critical;¤  ¤   ¤   /* Critical flag on subpacket */
8617b8 ¤   int¤¤   ¤   found_X509 = 0;¤¤   /* True if found an X509 subpacket */
1c4962 ¤   int¤¤   ¤   found_keyid = 0;¤   /* True if found a keyid subpacket */
5a0927 ¤   int¤¤   ¤   hashed;¤¤   ¤   ¤   /* True if parsing hashed subpackets */
5314c9 ¤   int¤¤   ¤   hashedExportable=0; /* True if exportable in hashed portion */
75a7e6 ¤   PGPUInt32¤  ¤   creationtime = 0;¤  /* Creation time from subpacket */
a3f01d ¤   PGPUInt32¤  ¤   expirationtime = 0;¤/* Expiration time from subpacket */
abaf5a
--f555 00093fd4e6b401001f9 Page 9 of pgpRngPars.c
cc2fd0 ¤   hashed = 1;
4a8a3c ¤   /* Loop twice, once with hashed = 1 and once with hashed = 0 */
1b43ab ¤   do {
ef6241 ¤   ¤   len = (unsigned)buf[0]<<8 | buf[1];
72fc67 ¤   ¤   buf += 2;
bbbf30 ¤   ¤   while (len) {
da11f0 ¤   ¤   ¤   if (len < 2)
f0e61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
c79992 ¤   ¤   ¤   /* Subpacket length may be one or two bytes */
4259e6 ¤   ¤   ¤   sublen = (unsigned)buf[0];
d8694f ¤   ¤   ¤   if (sublen < 0xc0) {
3a6431 ¤   ¤   ¤   ¤   /* sublen is the length */
09136a ¤   ¤   ¤   ¤   offset = sublen;
b8a505 ¤   ¤   ¤   ¤   len -= 1;
1eee2c ¤   ¤   ¤   ¤   buf += 1;
81950c ¤   ¤   ¤   } else if ((sublen & 0xe0) == 0xc0) {
222c3f ¤   ¤   ¤   ¤   sublen &= 0x3f;
a75ea4 ¤   ¤   ¤   ¤   sublen = (sublen << 8) + (unsigned)buf[1] + 192;
39136a ¤   ¤   ¤   ¤   offset = sublen;
584a61 ¤   ¤   ¤   ¤   len -= 2;
710148 ¤   ¤   ¤   ¤   buf += 2;
ec3bb5 ¤   ¤   ¤   } else if (sublen == 0xff) {
43a9a8 ¤   ¤   ¤   ¤   if (len < 5)
dae126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
0c2b17 ¤   ¤   ¤   ¤   sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
88136a ¤   ¤   ¤   ¤   offset = sublen;
34c664 ¤   ¤   ¤   ¤   len -= 5;
ef8d4d ¤   ¤   ¤   ¤   buf += 5;
92042d ¤   ¤   ¤   } else {
cd980e ¤   ¤   ¤   ¤   /*
010a46 ¤   ¤   ¤   ¤   ·* Variable length subpacket; add up sizes of parts.
99e0fd ¤   ¤   ¤   ¤   ·* We don't consolidate them, so these can't be used for
2ac377 ¤   ¤   ¤   ¤   ·* the types we are scanning for below.
481020 ¤   ¤   ¤   ¤   ·*/
49bd91 ¤   ¤   ¤   ¤   unsigned partlen;
2b57ed ¤   ¤   ¤   ¤   PGPByte const *bp;
a8d2e7 ¤   ¤   ¤   ¤   PGPBoolean final = FALSE;
d5a505 ¤   ¤   ¤   ¤   len -= 1;
bfee2c ¤   ¤   ¤   ¤   buf += 1;
122dee ¤   ¤   ¤   ¤   sublen = 1 << (sublen & 0x1f);
02f17b ¤   ¤   ¤   ¤   partlen = sublen;
19c385 ¤   ¤   ¤   ¤   bp = buf + partlen;
a4ce08 ¤   ¤   ¤   ¤   while (!final) {
1050bf ¤   ¤   ¤   ¤   ¤   partlen = (unsigned)*bp++;
aad2c6 ¤   ¤   ¤   ¤   ¤   if (partlen < 0xe0) {
ad99ba ¤   ¤   ¤   ¤   ¤   ¤   final = TRUE;
37154b ¤   ¤   ¤   ¤   ¤   ¤   if (partlen >= 0xc0)
b9ffc4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   partlen = ((partlen&0x3f) << 8)
123014 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   + (unsigned)*bp++ + 192;
4081a1 ¤   ¤   ¤   ¤   ¤   } else {
00beb7 ¤   ¤   ¤   ¤   ¤   ¤   partlen = 1 << (partlen & 0x1f);
b41c89 ¤   ¤   ¤   ¤   ¤   }
22084e ¤   ¤   ¤   ¤   ¤   sublen += partlen;
88c8de ¤   ¤   ¤   ¤   ¤   bp += partlen;
ed2613 ¤   ¤   ¤   ¤   }
2b8432 ¤   ¤   ¤   ¤   offset = bp - buf;
a7a3a6 ¤   ¤   ¤   }
27fe94 ¤   ¤   ¤   if (len < 1)
75e61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
08717d ¤   ¤   ¤   type = buf[0];
dbd297 ¤   ¤   ¤   critical = type & SIGSUBF_CRITICAL;
5426e9 ¤   ¤   ¤   type &= ~SIGSUBF_CRITICAL;
592999 ¤   ¤   ¤   buf += 1;
ae62b0 ¤   ¤   ¤   len -= 1;
bddb46 ¤   ¤   ¤   sublen -= 1;
04740c ¤   ¤   ¤   offset -= 1;
38ae59 ¤   ¤   ¤   if (len < sublen)
63e61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
56a327 ¤   ¤   ¤   /* Illegal to have critical packets in unhashed region */
23b159 ¤   ¤   ¤   if (critical && !hashed)
77e61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
939a98 ¤   ¤   ¤   switch (type) {
--61a9 000dc96ea20401001f9 Page 10 of pgpRngPars.c
84bc98 ¤   ¤   ¤   case SIGSUB_CREATION:
ad0bd0 ¤   ¤   ¤   ¤   if (sublen != 4)
afe126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
4d55a7 ¤   ¤   ¤   ¤   if (!tstamp && critical)
c8e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
868860 ¤   ¤   ¤   ¤   creationtime = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
974805 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···((unsigned)buf[2]<<8|buf[3]);
f29d98 ¤   ¤   ¤   ¤   if (tstamp)
5a8774 ¤   ¤   ¤   ¤   ¤   *tstamp = creationtime;
73f622 ¤   ¤   ¤   ¤   break;
d0a085 ¤   ¤   ¤   case SIGSUB_EXPIRATION:
33e2b3 ¤   ¤   ¤   ¤   if (sublen != 4 || !hashed)
7de126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
5a4c28 ¤   ¤   ¤   ¤   if (!validity && critical)
81e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
230721 ¤   ¤   ¤   ¤   expirationtime = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
394805 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···((unsigned)buf[2]<<8|buf[3]);
d7b75c ¤   ¤   ¤   ¤   /* Store it as days. ·expirationtime is really valid period */
d5f21d ¤   ¤   ¤   ¤   if (validity && creationtime)
41e83a ¤   ¤   ¤   ¤   ¤   *validity = (PGPUInt16) (expirationtime / (24 * 3600));
3bf622 ¤   ¤   ¤   ¤   break;
3d5982 ¤   ¤   ¤   case SIGSUB_KEYID:
b3c924 ¤   ¤   ¤   ¤   /* Allow longer than 8 byte keyid's unless critical */
c17d8c ¤   ¤   ¤   ¤   if (sublen < 8)
d9e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
d43fb0 ¤   ¤   ¤   ¤   if (critical && (!keyID || sublen != 8))
b4e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
0531d8 ¤   ¤   ¤   ¤   if (keyID)
820ae0 ¤   ¤   ¤   ¤   ¤   memcpy(keyID, buf + sublen - 8, 8);
57eca5 ¤   ¤   ¤   ¤   found_keyid = 1;
c6f622 ¤   ¤   ¤   ¤   break;
ee5c40 ¤   ¤   ¤   case SIGSUB_EXPORTABLE:
8c01f7 ¤   ¤   ¤   ¤   /* Allow exportability attribute not to be hashed */
b0326d ¤   ¤   ¤   ¤   if (sublen != 1)
33e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
08bb3b ¤   ¤   ¤   ¤   /* hashed version overrides unhashed */
e36b7a ¤   ¤   ¤   ¤   if (hashedExportable && !hashed)
0be126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
9ebb7b ¤   ¤   ¤   ¤   if (IsntNull( exportable ) ) {
3f6041 ¤   ¤   ¤   ¤   ¤   *exportable = *buf != 0;
7d49d0 ¤   ¤   ¤   ¤   ¤   hashedExportable = hashed;
4a2613 ¤   ¤   ¤   ¤   }
edf622 ¤   ¤   ¤   ¤   break;
43f6fc ¤   ¤   ¤   case SIGSUB_REVOCABLE:
0f6fe0 ¤   ¤   ¤   ¤   if (sublen != 1 || !hashed)
58e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
179962 ¤   ¤   ¤   ¤   if (IsntNull( revocable ) )
aefdf7 ¤   ¤   ¤   ¤   ¤   *revocable = *buf != 0;
a5f622 ¤   ¤   ¤   ¤   break;
184674 ¤   ¤   ¤   case SIGSUB_TRUST:
6af2c8 ¤   ¤   ¤   ¤   /* Packet format not fully decided, use 1st two bytes */
f969f5 ¤   ¤   ¤   ¤   if (sublen < 2 || !hashed)
3ce126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
43f775 ¤   ¤   ¤   ¤   if (IsntNull( trustLevel ) )
a4bc27 ¤   ¤   ¤   ¤   ¤   *trustLevel = buf[0];
6bc6b4 ¤   ¤   ¤   ¤   if (IsntNull( trustValue ) )
2d7c51 ¤   ¤   ¤   ¤   ¤   *trustValue = buf[1];
0af622 ¤   ¤   ¤   ¤   break;
5e6740 ¤   ¤   ¤   case SIGSUB_REGEXP:
9a5481 ¤   ¤   ¤   ¤   if (!hashed)
40e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
f5058f ¤   ¤   ¤   ¤   if (IsntNull( hasRegExp ) )
5def03 ¤   ¤   ¤   ¤   ¤   *hasRegExp = TRUE;
13f622 ¤   ¤   ¤   ¤   break;
22bfd7 ¤   ¤   ¤   case SIGSUB_X509:
3f5481 ¤   ¤   ¤   ¤   if (!hashed)
85e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
a6abe6 ¤   ¤   ¤   ¤   if (IsntNull( isX509 ) )
5bc528 ¤   ¤   ¤   ¤   ¤   *isX509 = TRUE;
2cb43d ¤   ¤   ¤   ¤   found_X509 = TRUE;
f6f622 ¤   ¤   ¤   ¤   break;
dcdb68 ¤   ¤   ¤   default:
--00dc 00080da138d401001f9 Page 11 of pgpRngPars.c
b3a5ce ¤   ¤   ¤   ¤   if (critical)
2be126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
bda3a6 ¤   ¤   ¤   }
a11c65 ¤   ¤   ¤   buf += offset;
6dfb32 ¤   ¤   ¤   len -= offset;
eb0fe4 ¤   ¤   }
2b4ff1 ¤   ¤   hashed = !hashed;
8825f0 ¤   } while (!hashed);¤ ¤   ¤   /* Two iterations */
bd1812 ¤   /* We must have a keyid, unless it is an X509 key */
9443cf ¤   if (keyID && !found_keyid && !found_X509)
9f2f88 ¤   ¤   return kPGPError_ExtraDateOnSignature;
b9151e ¤   return kPGPError_NoErr;
d3efe6 }
a2af5a
1995d7 /*·
88d71f ·* Look for a particular subpacket associated with the given signature.
234689 ·* See comments above for format of subpackets. ·Return pointer to the
9e901b ·* subpacket data, after the length and type field.
d66eba ·* Critical and hashed tell whether the packet was critical and/or in the
87f4e5 ·* hashed region, respectively (return parameters).
06eb9f ·* We don't need to do consistency checking, it's already been checked.
b6775e ·*
0a1084 ·* This may alter the contents of buf, so should only be called once on
064c7f ·* any given buffer.
79775e ·*
bf8145 ·* nth should be set to 0 to find first match, 1 for second, etc.
517a32 ·* Returns number of matches total in *pmatches.
8e495d ·*/
aad929 PGPByte const *
f6ca5a ringSigFindSubpacket(PGPByte *buf, int subpacktype, unsigned nth,
9d826f ¤   PGPSize *plen, int *pcritical, int *phashed, PGPUInt32 *pcreation,
993a90 ¤   unsigned *pmatches)
9ebb36 {
a60d8f ¤   unsigned¤   len;¤   ¤   ¤   ····/* Length of chain of subpackets */
d97a2a ¤   unsigned¤   sublen;¤¤   ¤   ¤   /* Length of subpacket */
a4efdd ¤   unsigned¤   offset;¤¤   ¤   ¤   /* Offset to next subpacket */
d6913f ¤   int ¤   ¤   type;¤  ¤   ¤   ¤   /* Type of subpacket */
188b76 ¤   int¤¤   ¤   critical;¤  ¤   ¤   /* Critical flag on subpacket */
100927 ¤   int¤¤   ¤   hashed;¤¤   ¤   ¤   /* True if parsing hashed subpackets */
db944b ¤   unsigned¤   nmatches = 0;¤  ¤   /* Number of matches so far */
9c8eb3 ¤   PGPByte const *pbuf = NULL;¤¤   /* Return buffer pointer */
4baf5a
2accf2 ¤   if (buf[0] < PGPVERSION_4)
6a7ed2 ¤   ¤   return NULL;
a6af5a
da0410 ¤   subpacktype &= ~SIGSUBF_CRITICAL;
75af0b ¤   buf += 4;
e62fd0 ¤   hashed = 1;
298a3c ¤   /* Loop twice, once with hashed = 1 and once with hashed = 0 */
2c43ab ¤   do {
c96241 ¤   ¤   len = (unsigned)buf[0]<<8 | buf[1];
9afc67 ¤   ¤   buf += 2;
5bbf30 ¤   ¤   while (len) {
c811f0 ¤   ¤   ¤   if (len < 2)
59fb5e ¤   ¤   ¤   ¤   return NULL;
4a9992 ¤   ¤   ¤   /* Subpacket length may be one or two bytes */
8759e6 ¤   ¤   ¤   sublen = (unsigned)buf[0];
8f694f ¤   ¤   ¤   if (sublen < 0xc0) {
b96431 ¤   ¤   ¤   ¤   /* sublen is the length */
10136a ¤   ¤   ¤   ¤   offset = sublen;
96a505 ¤   ¤   ¤   ¤   len -= 1;
7cee2c ¤   ¤   ¤   ¤   buf += 1;
eb950c ¤   ¤   ¤   } else if ((sublen & 0xe0) == 0xc0) {
c92c3f ¤   ¤   ¤   ¤   sublen &= 0x3f;
025ea4 ¤   ¤   ¤   ¤   sublen = (sublen << 8) + (unsigned)buf[1] + 192;
89136a ¤   ¤   ¤   ¤   offset = sublen;
4c4a61 ¤   ¤   ¤   ¤   len -= 2;
e00148 ¤   ¤   ¤   ¤   buf += 2;
6b3bb5 ¤   ¤   ¤   } else if (sublen == 0xff) {
9ba9a8 ¤   ¤   ¤   ¤   if (len < 5)
e44008 ¤   ¤   ¤   ¤   ¤   return NULL;
802b17 ¤   ¤   ¤   ¤   sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
--746c 000af11461c401001f9 Page 12 of pgpRngPars.c
a9136a ¤   ¤   ¤   ¤   offset = sublen;
2cc664 ¤   ¤   ¤   ¤   len -= 5;
6d8d4d ¤   ¤   ¤   ¤   buf += 5;
4b042d ¤   ¤   ¤   } else {
5a6550 ¤   ¤   ¤   ¤   /* Variable length subpacket; concatenate data */
26bd91 ¤   ¤   ¤   ¤   unsigned partlen;
ce4aa1 ¤   ¤   ¤   ¤   PGPByte *bp;
4dd2e7 ¤   ¤   ¤   ¤   PGPBoolean final = FALSE;
83a505 ¤   ¤   ¤   ¤   len -= 1;
dfee2c ¤   ¤   ¤   ¤   buf += 1;
7c2dee ¤   ¤   ¤   ¤   sublen = 1 << (sublen & 0x1f);
fef17b ¤   ¤   ¤   ¤   partlen = sublen;
22c385 ¤   ¤   ¤   ¤   bp = buf + partlen;
2bce08 ¤   ¤   ¤   ¤   while (!final) {
af50bf ¤   ¤   ¤   ¤   ¤   partlen = (unsigned)*bp++;
6ad2c6 ¤   ¤   ¤   ¤   ¤   if (partlen < 0xe0) {
c199ba ¤   ¤   ¤   ¤   ¤   ¤   final = TRUE;
ce154b ¤   ¤   ¤   ¤   ¤   ¤   if (partlen >= 0xc0)
34ffc4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   partlen = ((partlen&0x3f) << 8)
273014 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   + (unsigned)*bp++ + 192;
3b81a1 ¤   ¤   ¤   ¤   ¤   } else {
37beb7 ¤   ¤   ¤   ¤   ¤   ¤   partlen = 1 << (partlen & 0x1f);
501c89 ¤   ¤   ¤   ¤   ¤   }
c7f4ec ¤   ¤   ¤   ¤   ¤   pgpCopyMemory (bp, buf+sublen, partlen);
83084e ¤   ¤   ¤   ¤   ¤   sublen += partlen;
78c8de ¤   ¤   ¤   ¤   ¤   bp += partlen;
fe2613 ¤   ¤   ¤   ¤   }
6c8432 ¤   ¤   ¤   ¤   offset = bp - buf;
58a3a6 ¤   ¤   ¤   }
f1fe94 ¤   ¤   ¤   if (len < 1)
a3fb5e ¤   ¤   ¤   ¤   return NULL;
ab717d ¤   ¤   ¤   type = buf[0];
c8d297 ¤   ¤   ¤   critical = type & SIGSUBF_CRITICAL;
f626e9 ¤   ¤   ¤   type &= ~SIGSUBF_CRITICAL;
722999 ¤   ¤   ¤   buf += 1;
1c62b0 ¤   ¤   ¤   len -= 1;
a4db46 ¤   ¤   ¤   sublen -= 1;
e5740c ¤   ¤   ¤   offset -= 1;
2caf5a
25292d ¤   ¤   ¤   if (type == subpacktype) {
8967fd ¤   ¤   ¤   ¤   /* Match! */
d9101c ¤   ¤   ¤   ¤   if (nmatches == nth) {
edd392 ¤   ¤   ¤   ¤   ¤   if (pcritical)
d63829 ¤   ¤   ¤   ¤   ¤   ¤   *pcritical = critical;
2dbbdd ¤   ¤   ¤   ¤   ¤   if (phashed)
544ed8 ¤   ¤   ¤   ¤   ¤   ¤   *phashed = hashed;
5df180 ¤   ¤   ¤   ¤   ¤   if (plen)
52f62c ¤   ¤   ¤   ¤   ¤   ¤   *plen = sublen;
de21b3 ¤   ¤   ¤   ¤   ¤   pbuf = buf;
f42613 ¤   ¤   ¤   ¤   }
0dc297 ¤   ¤   ¤   ¤   nmatches += 1;
35a3a6 ¤   ¤   ¤   }
0caf5a
d515c7 ¤   ¤   ¤   if (type == SIGSUB_CREATION) {
2b969d ¤   ¤   ¤   ¤   pgpAssert (sublen == 4);
8f4b05 ¤   ¤   ¤   ¤   if (pcreation) {
b94b01 ¤   ¤   ¤   ¤   ¤   *pcreation = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
1ebd39 ¤   ¤   ¤   ¤   ¤   ¤   ((unsigned)buf[2]<<8|buf[3]);
ce2613 ¤   ¤   ¤   ¤   }
73a3a6 ¤   ¤   ¤   }
f3af5a
0f1794 ¤   ¤   ¤   /* Skip to next packet */
dc1c65 ¤   ¤   ¤   buf += offset;
27fb32 ¤   ¤   ¤   len -= offset;
890fe4 ¤   ¤   }
524ff1 ¤   ¤   hashed = !hashed;
d725f0 ¤   } while (!hashed);¤ ¤   ¤   /* Two iterations */
d4e0d2 ¤   if (pmatches)
a85827 ¤   ¤   *pmatches = nmatches;
4612fd ¤   return pbuf;¤   ¤   ¤   ¤   /* Will be non-null if we matched nth */
1befe6 }
afaf5a
--03cf 0003f2944ae401001f9 Page 13 of pgpRngPars.c
e0af5a
952ae4 #define SFLAGS(critical,hashed) \
6c2d53 ¤   (((critical)?kPGPSigFlags_Critical:0)|((hashed)?0:kPGPSigFlags_Unhashed))
eaaf5a
2538e5 /*
f77bb1 ·* Add info from subpackets to a sigspec structure.
62495d ·*/
a5c77d PGPError
8c1d01 ringSigSubpacketsSpec(PGPSigSpec *spec, PGPByte const *buf)
d8bb36 {
160d8f ¤   unsigned¤   len;¤   ¤   ¤   ····/* Length of chain of subpackets */
917a2a ¤   unsigned¤   sublen;¤¤   ¤   ¤   /* Length of subpacket */
aeefdd ¤   unsigned¤   offset;¤¤   ¤   ¤   /* Offset to next subpacket */
56913f ¤   int ¤   ¤   type;¤  ¤   ¤   ¤   /* Type of subpacket */
e48b76 ¤   int¤¤   ¤   critical;¤  ¤   ¤   /* Critical flag on subpacket */
220927 ¤   int¤¤   ¤   hashed;¤¤   ¤   ¤   /* True if parsing hashed subpackets */
db560b ¤   PGPUInt32¤  dat;
85af5a
63b2a4 ¤   pgpAssert (buf[0] >= PGPVERSION_4);
51af0b ¤   buf += 4;
21af5a
c12fd0 ¤   hashed = 1;
458a3c ¤   /* Loop twice, once with hashed = 1 and once with hashed = 0 */
af43ab ¤   do {
f86241 ¤   ¤   len = (unsigned)buf[0]<<8 | buf[1];
31fc67 ¤   ¤   buf += 2;
9abf30 ¤   ¤   while (len) {
0a11f0 ¤   ¤   ¤   if (len < 2)
4ae61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
f99992 ¤   ¤   ¤   /* Subpacket length may be one or two bytes */
1659e6 ¤   ¤   ¤   sublen = (unsigned)buf[0];
32694f ¤   ¤   ¤   if (sublen < 0xc0) {
456431 ¤   ¤   ¤   ¤   /* sublen is the length */
31136a ¤   ¤   ¤   ¤   offset = sublen;
f9a505 ¤   ¤   ¤   ¤   len -= 1;
a0ee2c ¤   ¤   ¤   ¤   buf += 1;
2e950c ¤   ¤   ¤   } else if ((sublen & 0xe0) == 0xc0) {
092c3f ¤   ¤   ¤   ¤   sublen &= 0x3f;
6c5ea4 ¤   ¤   ¤   ¤   sublen = (sublen << 8) + (unsigned)buf[1] + 192;
ef136a ¤   ¤   ¤   ¤   offset = sublen;
1a4a61 ¤   ¤   ¤   ¤   len -= 2;
3a0148 ¤   ¤   ¤   ¤   buf += 2;
2a3bb5 ¤   ¤   ¤   } else if (sublen == 0xff) {
63a9a8 ¤   ¤   ¤   ¤   if (len < 5)
47e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
892b17 ¤   ¤   ¤   ¤   sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
6a136a ¤   ¤   ¤   ¤   offset = sublen;
f3c664 ¤   ¤   ¤   ¤   len -= 5;
7c8d4d ¤   ¤   ¤   ¤   buf += 5;
0a042d ¤   ¤   ¤   } else {
3b980e ¤   ¤   ¤   ¤   /*
ef0a46 ¤   ¤   ¤   ¤   ·* Variable length subpacket; add up sizes of parts.
fae0fd ¤   ¤   ¤   ¤   ·* We don't consolidate them, so these can't be used for
50c377 ¤   ¤   ¤   ¤   ·* the types we are scanning for below.
551020 ¤   ¤   ¤   ¤   ·*/
fdbd91 ¤   ¤   ¤   ¤   unsigned partlen;
2157ed ¤   ¤   ¤   ¤   PGPByte const *bp;
90d2e7 ¤   ¤   ¤   ¤   PGPBoolean final = FALSE;
c1a505 ¤   ¤   ¤   ¤   len -= 1;
80ee2c ¤   ¤   ¤   ¤   buf += 1;
982dee ¤   ¤   ¤   ¤   sublen = 1 << (sublen & 0x1f);
cff17b ¤   ¤   ¤   ¤   partlen = sublen;
46c385 ¤   ¤   ¤   ¤   bp = buf + partlen;
32ce08 ¤   ¤   ¤   ¤   while (!final) {
3550bf ¤   ¤   ¤   ¤   ¤   partlen = (unsigned)*bp++;
91d2c6 ¤   ¤   ¤   ¤   ¤   if (partlen < 0xe0) {
4e99ba ¤   ¤   ¤   ¤   ¤   ¤   final = TRUE;
73154b ¤   ¤   ¤   ¤   ¤   ¤   if (partlen >= 0xc0)
ccffc4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   partlen = ((partlen&0x3f) << 8)
843014 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   + (unsigned)*bp++ + 192;
1e81a1 ¤   ¤   ¤   ¤   ¤   } else {
3fbeb7 ¤   ¤   ¤   ¤   ¤   ¤   partlen = 1 << (partlen & 0x1f);
--92a6 000921905aa401001f9 Page 14 of pgpRngPars.c
b61c89 ¤   ¤   ¤   ¤   ¤   }
8d084e ¤   ¤   ¤   ¤   ¤   sublen += partlen;
3dc8de ¤   ¤   ¤   ¤   ¤   bp += partlen;
0f2613 ¤   ¤   ¤   ¤   }
2b8432 ¤   ¤   ¤   ¤   offset = bp - buf;
5ba3a6 ¤   ¤   ¤   }
13fe94 ¤   ¤   ¤   if (len < 1)
e4e61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
00717d ¤   ¤   ¤   type = buf[0];
d7d297 ¤   ¤   ¤   critical = type & SIGSUBF_CRITICAL;
2926e9 ¤   ¤   ¤   type &= ~SIGSUBF_CRITICAL;
3e2999 ¤   ¤   ¤   buf += 1;
0462b0 ¤   ¤   ¤   len -= 1;
34db46 ¤   ¤   ¤   sublen -= 1;
89740c ¤   ¤   ¤   offset -= 1;
89ae59 ¤   ¤   ¤   if (len < sublen)
3ce61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
e3a327 ¤   ¤   ¤   /* Illegal to have critical packets in unhashed region */
a5b159 ¤   ¤   ¤   if (critical && !hashed)
15e61d ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
459a98 ¤   ¤   ¤   switch (type) {
babc98 ¤   ¤   ¤   case SIGSUB_CREATION:
d70bd0 ¤   ¤   ¤   ¤   if (sublen != 4)
1fe126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
5b3493 ¤   ¤   ¤   ¤   dat = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
304805 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···((unsigned)buf[2]<<8|buf[3]);
111eaa ¤   ¤   ¤   ¤   pgpSigSpecSetTimestamp (spec, dat);
84f622 ¤   ¤   ¤   ¤   break;
baa085 ¤   ¤   ¤   case SIGSUB_EXPIRATION:
990bd0 ¤   ¤   ¤   ¤   if (sublen != 4)
e2e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
483493 ¤   ¤   ¤   ¤   dat = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
d64805 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···((unsigned)buf[2]<<8|buf[3]);
8e683f ¤   ¤   ¤   ¤   pgpSigSpecSetSigExpiration (spec, SFLAGS(critical, hashed),
c12441 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dat);
f0f622 ¤   ¤   ¤   ¤   break;
bd166e ¤   ¤   ¤   case SIGSUB_KEY_EXPIRATION:
190bd0 ¤   ¤   ¤   ¤   if (sublen != 4)
bfe126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
963493 ¤   ¤   ¤   ¤   dat = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
ee4805 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···((unsigned)buf[2]<<8|buf[3]);
083629 ¤   ¤   ¤   ¤   pgpSigSpecSetKeyExpiration (spec, SFLAGS(critical, hashed),
402441 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dat);
c2f622 ¤   ¤   ¤   ¤   break;
405982 ¤   ¤   ¤   case SIGSUB_KEYID:
179eb9 ¤   ¤   ¤   ¤   /* This was processed beforehand to set up the sigspec */
59ae73 ¤   ¤   ¤   ¤   if (sublen != 8)
28e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
0af622 ¤   ¤   ¤   ¤   break;
435c40 ¤   ¤   ¤   case SIGSUB_EXPORTABLE:
6301f7 ¤   ¤   ¤   ¤   /* Allow exportability attribute not to be hashed */
ec326d ¤   ¤   ¤   ¤   if (sublen != 1)
41e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
58967e ¤   ¤   ¤   ¤   pgpSigSpecSetExportable (spec, SFLAGS(critical, hashed),
c7289d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean)(buf[0]!=0));
c9f622 ¤   ¤   ¤   ¤   break;
adf6fc ¤   ¤   ¤   case SIGSUB_REVOCABLE:
5b326d ¤   ¤   ¤   ¤   if (sublen != 1)
2ae126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
c04540 ¤   ¤   ¤   ¤   pgpSigSpecSetRevocable (spec, SFLAGS(critical, hashed),
cc289d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean)(buf[0]!=0));
84f622 ¤   ¤   ¤   ¤   break;
4e4674 ¤   ¤   ¤   case SIGSUB_TRUST:
d7f2c8 ¤   ¤   ¤   ¤   /* Packet format not fully decided, use 1st two bytes */
7ddd09 ¤   ¤   ¤   ¤   if (sublen != 2)
c1e126 ¤   ¤   ¤   ¤   ¤   return kPGPError_ExtraDateOnSignature;
750eb8 ¤   ¤   ¤   ¤   pgpSigSpecSetTrustLevel (spec, SFLAGS(critical, hashed),
64eaec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(PGPBoolean)(buf[0]!=0),
1559e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(PGPBoolean)(buf[1]!=0));
4bf622 ¤   ¤   ¤   ¤   break;
ab6740 ¤   ¤   ¤   case SIGSUB_REGEXP:
923e7f ¤   ¤   ¤   ¤   pgpSigSpecSetRegExp (spec, SFLAGS(critical, hashed),
--53b0 0001329f6b3401001f9 Page 15 of pgpRngPars.c
ea2527 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(char *)buf);
aaf622 ¤   ¤   ¤   ¤   break;
962c64 ¤   ¤   ¤   case SIGSUB_PREFERRED_ENCRYPTION_ALGS:
405033 ¤   ¤   ¤   ¤   pgpSigSpecSetPrefAlgs (spec, SFLAGS(critical, hashed),
bc0699 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·buf, sublen);
d7f622 ¤   ¤   ¤   ¤   break;
198b8e ¤   ¤   ¤   case SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST:
d9d4ce ¤   ¤   ¤   ¤   pgpSigSpecSetAdditionalRecipientRequest (spec,
685619 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SFLAGS(critical, hashed), buf, sublen);
06f622 ¤   ¤   ¤   ¤   break;
efbdef ¤   ¤   ¤   case SIGSUB_KEY_REVOCATION_KEY:
7066af ¤   ¤   ¤   ¤   pgpSigSpecSetRevocationKey (spec,
305619 ¤   ¤   ¤   ¤   ¤   ¤   ¤   SFLAGS(critical, hashed), buf, sublen);
22f622 ¤   ¤   ¤   ¤   break;
dadb68 ¤   ¤   ¤   default:
71d0b9 ¤   ¤   ¤   ¤   pgpSigSpecSetPacket (spec, SFLAGS(critical, hashed),
a5c5c5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·buf-1, sublen+1);
d6f622 ¤   ¤   ¤   ¤   break;
81a3a6 ¤   ¤   ¤   }
141c65 ¤   ¤   ¤   buf += offset;
46fb32 ¤   ¤   ¤   len -= offset;
2b0fe4 ¤   ¤   }
d94ff1 ¤   ¤   hashed = !hashed;
5f25f0 ¤   } while (!hashed);¤ ¤   ¤   /* Two iterations */
d4151e ¤   return kPGPError_NoErr;
d0efe6 }
11af5a
cdaf5a
5faf5a
f6af5a
2f38e5 /*
31a190 ·* Return data for nth subpacket in an attribute object.
fb81f8 ·* Data is in buf.
3d8917 ·* Format is as for signature subpacket portion:
f1e338 ·* A chain of subpackets, with the following format:
79e13a ·* Offset,Length ·Meaning
eeae2c ·*¤ 0¤  x(1-2)¤ Subpacket length (=y)
62aa3f ·*¤ x¤  1¤  Subpacket type (with critical flag)
e6ad88 ·*¤ x+1¤y-1¤Subpacket data
f5775e ·*
221084 ·* This may alter the contents of buf, so should only be called once on
214c7f ·* any given buffer.
a4775e ·*
9e45c2 ·* nth should be set to 0 to find first subpacket, 1 for second, etc.
204361 ·* Returns type of subpacket and its size.
71495d ·*/
bed929 PGPByte const *
6eddf9 ringAttrSubpacket(PGPByte *buf, PGPSize len, PGPUInt32 nth,
56e8a4 ¤   PGPUInt32 *subpacktype, PGPSize *plen)
6bbb36 {
06d9cb ¤   PGPSize¤¤   sublen;¤¤   ¤   ¤   /* Length of subpacket */
53488f ¤   PGPSize¤¤   offset;¤¤   ¤   ¤   /* Offset to next subpacket */
843e66 ¤   PGPUInt32¤  type;¤  ¤   ¤   ¤   /* Type of subpacket */
b8b47c ¤   PGPUInt32¤  npackets = 0;¤  ¤   /* Number of matches so far */
9caf5a
2385aa ¤   while (len) {
24a021 ¤   ¤   if (len < 2)
ffcf03 ¤   ¤   ¤   return NULL;
37e041 ¤   ¤   /* Subpacket length may be one or two bytes, or variable-length */
97af4b ¤   ¤   sublen = (PGPSize)buf[0];
5bd219 ¤   ¤   if (sublen < 0xc0) {
3a6a7d ¤   ¤   ¤   /* sublen is the length */
2ba83c ¤   ¤   ¤   offset = sublen;
9862b0 ¤   ¤   ¤   len -= 1;
ec2999 ¤   ¤   ¤   buf += 1;
26da32 ¤   ¤   } else if ((sublen & 0xe0) == 0xc0) {
268161 ¤   ¤   ¤   sublen &= 0x3f;
32bcbb ¤   ¤   ¤   sublen = (sublen << 8) + (PGPSize)buf[1] + 192;
2ba83c ¤   ¤   ¤   offset = sublen;
7d8dd4 ¤   ¤   ¤   len -= 2;
0ec6fd ¤   ¤   ¤   buf += 2;
133e58 ¤   ¤   } else if (sublen == 0xff) {
--bde3 00018d41b92401001f9 Page 16 of pgpRngPars.c
9c2c61 ¤   ¤   ¤   sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
12a83c ¤   ¤   ¤   offset = sublen;
3301d1 ¤   ¤   ¤   len -= 5;
384af8 ¤   ¤   ¤   buf += 5;
8345a6 ¤   ¤   } else {
a1d949 ¤   ¤   ¤   /* Variable length subpacket; concatenate data */
db757a ¤   ¤   ¤   PGPSize partlen;
fb7efc ¤   ¤   ¤   PGPByte *bp;
14ee09 ¤   ¤   ¤   PGPBoolean final = FALSE;
c362b0 ¤   ¤   ¤   len -= 1;
552999 ¤   ¤   ¤   buf += 1;
f3bc76 ¤   ¤   ¤   sublen = 1 << (sublen & 0x1f);
44c673 ¤   ¤   ¤   partlen = sublen;
544879 ¤   ¤   ¤   bp = buf + partlen;
df755e ¤   ¤   ¤   while (!final) {
55fa21 ¤   ¤   ¤   ¤   partlen = (PGPSize)*bp++;
8eee28 ¤   ¤   ¤   ¤   if (partlen < 0xe0) {
6876c9 ¤   ¤   ¤   ¤   ¤   final = TRUE;
a113f3 ¤   ¤   ¤   ¤   ¤   if (partlen >= 0xc0)
da9601 ¤   ¤   ¤   ¤   ¤   ¤   partlen = ((partlen&0x3f) << 8) + (PGPSize)*bp++ + 192;
b3b5fc ¤   ¤   ¤   ¤   } else {
ecd184 ¤   ¤   ¤   ¤   ¤   partlen = 1 << (partlen & 0x1f);
102613 ¤   ¤   ¤   ¤   }
68d259 ¤   ¤   ¤   ¤   pgpCopyMemory (bp, buf+sublen, partlen);
6b49bd ¤   ¤   ¤   ¤   sublen += partlen;
cd44a1 ¤   ¤   ¤   ¤   bp += partlen;
e8a3a6 ¤   ¤   ¤   }
8b084d ¤   ¤   ¤   offset = bp - buf;
8b0fe4 ¤   ¤   }
504f45 ¤   ¤   if (len < 1)
21cf03 ¤   ¤   ¤   return NULL;
fe939c ¤   ¤   type = buf[0];
db1303 ¤   ¤   buf += 1;
aa582a ¤   ¤   len -= 1;
2f6a97 ¤   ¤   sublen -= 1;
31c5dd ¤   ¤   offset -= 1;
40af5a
0ecfdb ¤   ¤   if (npackets++ == nth) {
e5bf61 ¤   ¤   ¤   if (plen)
62b885 ¤   ¤   ¤   ¤   *plen = sublen;
b23b20 ¤   ¤   ¤   if (subpacktype)
d7a92f ¤   ¤   ¤   ¤   *subpacktype = type;
113226 ¤   ¤   ¤   return buf;
f30fe4 ¤   ¤   }
ed9371 ¤   }
c5af5a
6a503b ¤   /* Get here if fewer than n+1 subpackets */
3a3f59 ¤   return NULL;
1befe6 }
3daf5a
d30514 /* Return the number of subpackets in the buffer */
8ebccf PGPUInt32
2cc38a ringAttrCountSubpackets(PGPByte const *buf, PGPSize len)
aebb36 {
73d9cb ¤   PGPSize¤¤   sublen;¤¤   ¤   ¤   /* Length of subpacket */
b2488f ¤   PGPSize¤¤   offset;¤¤   ¤   ¤   /* Offset to next subpacket */
fc3e66 ¤   PGPUInt32¤  type;¤  ¤   ¤   ¤   /* Type of subpacket */
72b47c ¤   PGPUInt32¤  npackets = 0;¤  ¤   /* Number of matches so far */
64af5a
2d85aa ¤   while (len) {
eda021 ¤   ¤   if (len < 2)
b68144 ¤   ¤   ¤   return 0;
8cae72 ¤   ¤   /* Subpacket length may be 1/2/4 bytes, or variable-length */
44af4b ¤   ¤   sublen = (PGPSize)buf[0];
03d219 ¤   ¤   if (sublen < 0xc0) {
506a7d ¤   ¤   ¤   /* sublen is the length */
cea83c ¤   ¤   ¤   offset = sublen;
6a62b0 ¤   ¤   ¤   len -= 1;
122999 ¤   ¤   ¤   buf += 1;
9dda32 ¤   ¤   } else if ((sublen & 0xe0) == 0xc0) {
fd8161 ¤   ¤   ¤   sublen &= 0x3f;
18bcbb ¤   ¤   ¤   sublen = (sublen << 8) + (PGPSize)buf[1] + 192;
--462d 00001cb8c92401001f9 Page 17 of pgpRngPars.c
bea83c ¤   ¤   ¤   offset = sublen;
778dd4 ¤   ¤   ¤   len -= 2;
5bc6fd ¤   ¤   ¤   buf += 2;
c83e58 ¤   ¤   } else if (sublen == 0xff) {
9c2c61 ¤   ¤   ¤   sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
8ba83c ¤   ¤   ¤   offset = sublen;
6501d1 ¤   ¤   ¤   len -= 5;
294af8 ¤   ¤   ¤   buf += 5;
e845a6 ¤   ¤   } else {
b06e45 ¤   ¤   ¤   /* Variable length subpacket */
e8757a ¤   ¤   ¤   PGPSize partlen;
aadb92 ¤   ¤   ¤   PGPByte const *bp;
9aee09 ¤   ¤   ¤   PGPBoolean final = FALSE;
6462b0 ¤   ¤   ¤   len -= 1;
cd2999 ¤   ¤   ¤   buf += 1;
f6bc76 ¤   ¤   ¤   sublen = 1 << (sublen & 0x1f);
aac673 ¤   ¤   ¤   partlen = sublen;
0d4879 ¤   ¤   ¤   bp = buf + partlen;
0b755e ¤   ¤   ¤   while (!final) {
87fa21 ¤   ¤   ¤   ¤   partlen = (PGPSize)*bp++;
2cee28 ¤   ¤   ¤   ¤   if (partlen < 0xe0) {
1b76c9 ¤   ¤   ¤   ¤   ¤   final = TRUE;
5213f3 ¤   ¤   ¤   ¤   ¤   if (partlen >= 0xc0)
b09601 ¤   ¤   ¤   ¤   ¤   ¤   partlen = ((partlen&0x3f) << 8) + (PGPSize)*bp++ + 192;
80b5fc ¤   ¤   ¤   ¤   } else {
0cd184 ¤   ¤   ¤   ¤   ¤   partlen = 1 << (partlen & 0x1f);
232613 ¤   ¤   ¤   ¤   }
6449bd ¤   ¤   ¤   ¤   sublen += partlen;
2844a1 ¤   ¤   ¤   ¤   bp += partlen;
57a3a6 ¤   ¤   ¤   }
c3084d ¤   ¤   ¤   offset = bp - buf;
df0fe4 ¤   ¤   }
6c4f45 ¤   ¤   if (len < 1)
e98144 ¤   ¤   ¤   return 0;
1a939c ¤   ¤   type = buf[0];
db1303 ¤   ¤   buf += 1;
a6582a ¤   ¤   len -= 1;
586a97 ¤   ¤   sublen -= 1;
8bc5dd ¤   ¤   offset -= 1;
7faf5a
9ad07a ¤   ¤   ++npackets;
289371 ¤   }
16af5a
038eb9 ¤   return npackets;
47efe6 }
b0af5a
82af5a
ec38e5 /*
37a2f9 ·* Return the length of the prefix of a secret key which is a public key,
0b62bc ·* or 0 if it can't be determined. ·A key's prefix is:
77902e ·* 0 1 - Version
0b50eb ·* 1 4 - Creation time
beb6e5 ·* 5 2 - Vaidity period (days)
eaf2b3 ·* 7 1 - Algorithm
7db0b4 ·* 8 ? - Algorithm-specific parameters
fc495d ·*/
7244d2 size_t
cd30dd ringKeyParsePublicPrefix(PGPByte const *buf, size_t len)
b3bb36 {
28e002 ¤   size_t size;
e86932 ¤   unsigned vsize;
40af5a
b8bc29 ¤   if (buf[0] == PGPVERSION_4) {
5a73d8 ¤   ¤   vsize = 0;
72f037 ¤   } else {
9ac660 ¤   ¤   vsize = 2;
419371 ¤   }
80af5a
6d1622 ¤   /* Check version bytes */
6f26dd ¤   if (!KNOWN_PGP_VERSION(buf[0]) || len < 6+vsize)
edbbde ¤   ¤   return 0;
019c06 ¤   size = pgpPubKeyPrefixSize(buf[5+vsize], buf+6+vsize, len-6-vsize);
--0e5f 000c1cfd990401001f9 Page 18 of pgpRngPars.c
8a7299 ¤   if (size)
5f3658 ¤   ¤   size += 6+vsize;
47f6fa ¤   return size;
3befe6 }
d1af5a
204d2f int
e7539c ringKeyParseFingerprint16(PGPContextRef context, PGPByte const *kbuf,
74b26d ¤   ¤   ¤   ¤   ¤   ¤   ··size_t klen, PGPByte *fingerprint)
35bb36 {
93602d ¤   PGPHashVTBL const *h;
54e2ba ¤   PGPHashContext *hc;
f4fe90 ¤   PGPByte const *buf;
fbc6b5 ¤   unsigned len;
6fea04 ····PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( context );
6caf5a
1c8d18 ¤   h = pgpHashByNumber (kPGPHashAlgorithm_MD5);
da0e8d ¤   if (!h)
d0467c ¤   ¤   return kPGPError_BadHashNumber;
c4dfe0 ¤   hc = pgpHashCreate( memoryMgr, h);
538cee ¤   if (!hc)
324030 ¤   ¤   return kPGPError_OutOfMemory;
f5af5a
03a97c ········buf = ringKeyParseModulus(kbuf, klen, &len);
4f9c71 ········if (!buf)
8097ed ¤   ¤   goto error;
c992c9 ········PGPContinueHash(hc, buf, len);
45af5a
63fef9 ········buf = ringKeyParseExponent(kbuf, klen, &len);
249c71 ········if (!buf)
5797ed ¤   ¤   goto error;
0492c9 ········PGPContinueHash(hc, buf, len);
47af5a
68882e ¤   buf = (PGPByte *) pgpHashFinal(hc);
8347c3 ¤   memcpy(fingerprint, buf, h->hashsize);
829727 ¤   PGPFreeHashContext(hc);
bbaf5a
ad5783 ¤   return h->hashsize;¤/* Success */
de60ff error:
f99727 ¤   PGPFreeHashContext(hc);
6afc2a ¤   pgpClearMemory( fingerprint, ·16);
66c9df ¤   return ringKeyParse(context, kbuf, klen, NULL, NULL, NULL, NULL, NULL,
250366 ¤   ¤   ¤   ¤   ¤   ¤   NULL, 0);
26415f ¤   /* ·····························Pkalg KeyID KeybitTstampValid */
a9efe6 }
a5af5a
82af5a
352451 /* Return the size which will be used to create the key prefix buffer */
de44d2 size_t
64130b ringKeyBufferLength(PGPKeySpec const *ks, PGPByte pkalg)
c2bb36 {
aa9734 ¤   (void)pkalg;
ed6717 ¤   if (pgpKeySpecVersion(ks)==PGPVERSION_4)
be04cc ¤   ¤   return 6;¤  /* version(1)+timestamp(4)+pkalg(1) */
9d0e24 ¤   else
8bac3a ¤   ¤   return 8;¤  /* version(1)+timestamp(4)+validity(2)+pkalg(1) */
4fefe6 }
24af5a
6ea8d0 /* Create the key prefix buffer */
b94d2f int
15ef38 ringKeyToBuffer(PGPByte *buf, PGPKeySpec const *ks, PGPByte pkalg)
a9bb36 {
51e0c3 ¤   PGPUInt32 tstamp;
146b1d ¤   PGPUInt16 validity;
386932 ¤   unsigned vsize;
93af5a
53af5a
3dd3f1 ¤   buf[0] = pgpKeySpecVersion(ks);
4fbc29 ¤   if (buf[0] == PGPVERSION_4) {
ed73d8 ¤   ¤   vsize = 0;
b3f037 ¤   } else {
c2c660 ¤   ¤   vsize = 2;
c19371 ¤   }
--692c 001c9119da3401001f9 Page 19 of pgpRngPars.c
80b03a ¤   tstamp = pgpKeySpecCreation(ks);
263738 ¤   buf[1] = (PGPByte)(tstamp>>24);
8149b1 ¤   buf[2] = (PGPByte)(tstamp>>16);
2496e9 ¤   buf[3] = (PGPByte)(tstamp>> 8);
366ef6 ¤   buf[4] = (PGPByte)(tstamp ···);
d41fbf ¤   if (vsize) {
192d1f ¤   ¤   validity = pgpKeySpecValidity(ks);
e112fc ¤   ¤   buf[5] = (PGPByte)(validity>>8);
002e0a ¤   ¤   buf[6] = (PGPByte)(validity ··);
a59371 ¤   }
dafea5 ¤   buf[5+vsize] = pkalg;
8e3e6b ¤   return 0;
79efe6 }
dfaf5a
a2dc7c /* Return the size of a prefix buffer for a secret key */
cc44d2 size_t
225bd1 ringSecBufferLength(PGPKeySpec const *ks, PGPByte pkalg)
15bb36 {
171b57 ¤   return ringKeyBufferLength(ks, pkalg);
f3efe6 }
2baf5a
d921d5 /* Create the prefix buffer for a secret key */
8f4d2f int
4a6629 ringSecToBuffer(PGPByte *buf, PGPKeySpec const *ks, PGPByte pkalg)
84bb36 {
357504 ¤   return ringKeyToBuffer(buf, ks, pkalg);
1defe6 }
c9af5a
--5618 0019a95d6e2401001fa Page 1 of pgpRngPars.h
bc38e5 /*
51b49b ·* $Id: pgpRngPars.h,v 1.18 1998/06/11 18:28:12 hal Exp $
7f495d ·*/
abaf5a
3f803d #ifndef Included_pgpRngPars_h
21d409 #define Included_pgpRngPars_h
ebaf5a
e4c546 #include <stddef.h>¤/* For size_t */
67af5a
c6c26c #include "pgpContext.h"
58d11f #include "pgpUsuals.h"
86af5a
eb99c6 PGP_BEGIN_C_DECLARATIONS
0faf5a
c91d63 struct PGPKeySpec;
a5af5a
592d1c int ringKeyParse(PGPContextRef context, PGPByte const *buf, size_t len,
2c0f17 ¤   PGPByte *pkalg, PGPByte keyID[8], PGPUInt16 *keybits, PGPUInt32 *tstamp,
f0bad9 ¤   PGPUInt16 *validity, PGPByte *v3, int secretf);
995a7d size_t ringKeyParsePublicPrefix(PGPByte const *buf, size_t len);
5590e4 PGPByte const *ringKeyParseModulus(PGPByte const *buf, size_t len,
aa8e71 ¤   unsigned *lenp);
678227 PGPByte const *ringKeyParseExponent(PGPByte const *buf, size_t len,
b78e71 ¤   unsigned *lenp);
03af5a
b767bc int ringKeyParseFingerprint16(PGPContextRef context, PGPByte const *kbuf,
310309 ¤   size_t klen, PGPByte *fingerprint);
d0fbed int ringSigParse(PGPByte const *buf, size_t len, PGPByte *pkalg,
7b4484 ¤   PGPByte keyID[8], PGPUInt32 *tstamp, PGPUInt16 *validity, PGPByte *type,
8436b4 ¤   PGPByte *hashalg, size_t *extralen, PGPByte *version,
766ef4 ¤   PGPBoolean *exportable, PGPBoolean *revocable, PGPByte *trustLevel,
3b254a ¤   PGPByte *trustValue, PGPBoolean *hasRegExp, PGPBoolean *isX509);
3926ce PGPByte const *ringSigParseExtra(PGPByte const *buf, size_t len,
2d8e71 ¤   unsigned *lenp);
68a2ca PGPByte const *ringSigParseInteger(PGPByte const *buf, size_t len,
d38e71 ¤   unsigned *lenp);
d75fac PGPByte const * ringSigFindSubpacket(PGPByte *buf, int subpacktype,
cd9698 ¤   unsigned nth, PGPSize *plen, int *pcritical, int *phashed,
25fe33 ¤   PGPUInt32 *pcreation, unsigned *pmatches);
5f0875 PGPError ringSigSubpacketsSpec(PGPSigSpec *spec, PGPByte const *buf);
9b01c0 PGPByte const *ringAttrSubpacket(PGPByte *buf, PGPSize len, unsigned nth,
98e3e6 ¤   PGPUInt32 *subpacktype, PGPSize *plen);
834a61 PGPUInt32 ringAttrCountSubpackets(PGPByte const *buf, PGPSize len);
65af5a
42e9e5 size_t ringKeyBufferLength(PGPKeySpec const *ks, PGPByte pkalg);
5aa87b int ringKeyToBuffer(PGPByte *buf, PGPKeySpec const *ks, PGPByte pkalg);
62907a size_t ringSecBufferLength(PGPKeySpec const *ks, PGPByte pkalg);
34a9fa int ringSecToBuffer(PGPByte *buf, PGPKeySpec const *ks, PGPByte pkalg);
f8af5a
dc1254 PGP_END_C_DECLARATIONS
a4af5a
9a26a7 #endif /* Included_pgpRngPars_h */
--6aaa 00018fbe52f401001fb Page 1 of pgpRngPkt.c
bc38e5 /*
161bcf ·* Low-level keyring packet handling routines.
d2775e ·*
3b68c2 ·* Written by Colin Plumb.
b5775e ·*
d9e504 ·* $Id: pgpRngPkt.c,v 1.11 1998/03/14 00:28:25 hal Exp $
15495d ·*/
a8e2ff #include "pgpConfig.h"
ddaf5a
89feb2 #include <stdio.h>
889d88 #include <string.h>¤/* For memset() and memcmp() */
15af5a
84a146 #include "pgpDebug.h"
d29c38 #include "pgpPktByte.h"
6bd229 #include "pgpRngPkt.h"
aa2f8d #include "pgpErrors.h"
54d11f #include "pgpUsuals.h"
1572de #include "pgpFile.h"
3d0d08 #include "pgpMem.h"
0baf5a
180596 #ifndef NULL
b0699b #define NULL 0
367454 #endif
23af5a
6357de #ifdef DEADCODE
0a4f80 char const * const packet_type[16] = {
ba5d9f ¤   "0: Unknown packet type",
29afe8 ¤   "1: Public-key encrypted packet",
6ce480 ¤   "2: Signature packet",
755112 ¤   "3: Unknown packet type",
9d4c73 ¤   "4: Unknown packet type",
65591a ¤   "5: Secret key",
ab5975 ¤   "6: Public key",
0240fe ¤   "7: Unknown packet type",
fc8ccc ¤   "8: Compressed packet",
716f3b ¤   "9: Conventional-key encrypted",
9687e5 ¤   "A: Unknown packet type",
69c98d ¤   "B: Literal packet",
e9fbc8 ¤   "C: Trust packet",
0966da ¤   "D: Key name packet",
de5adc ¤   "E: Comment packet",
733940 ¤   "F: Unknown packet type"
e282f7 };
497454 #endif
a4af5a
84af5a
f838e5 /*
8bde81 ·* Helper function for pktByteGet; read new-style length, returning
1cf11c ·* length and also length of first subpacket. ·If no subpackets are used
5f8ae1 ·* the second length will be the same as the first.
0c495d ·*/
44beb7 static int
473d69 pktLengthNew(PGPFile *f, PGPSize *lenp, PGPSize *len1p)
04bb36 {
df3672 ¤   PGPBoolean final = FALSE;
c837a9 ¤   long fpos = 0;
386d78 ¤   PGPByte c;¤ ¤   ¤   ¤   /* Length character we read */
9a0a18 ¤   PGPByte arr4[4];¤   ¤   /* For reading four byte lengths */
2cb90a ¤   PGPSize len = 0;¤   ¤   /* Length we return */
b28ff4 ¤   PGPSize len0 = 0;¤  ¤   /* Length of subpacket */
d7f6e6 ¤   PGPSize lenfirst = 0;¤  /* Length of first subpacket, if more than 1 */
c1c55b ¤   PGPError err = kPGPError_NoErr;
67af5a
3343ab ¤   do {
31c26e ¤   ¤   if (pgpFileRead(&c, 1, f) != 1)
f5ed19 ¤   ¤   ¤   goto error;
f2ee67 ¤   ¤   len0 = c;
87c2c8 ¤   ¤   if (len0 < 0xc0) {
4c3888 ¤   ¤   ¤   /* len0 is the length */
b7892a ¤   ¤   ¤   len += len0;
51c895 ¤   ¤   ¤   final = TRUE;
1886d2 ¤   ¤   } else if ((len0 & 0xe0) == 0xc0) {
--b34f 0006506cbd3401001fb Page 2 of pgpRngPkt.c
4ea1fb ¤   ¤   ¤   len0 &= 0x3f;
374a08 ¤   ¤   ¤   if (pgpFileRead(&c, 1, f) != 1)
7d1b7c ¤   ¤   ¤   ¤   goto error;
6ac1bf ¤   ¤   ¤   len += (len0 << 8) + (PGPSize)c + 192;
99c895 ¤   ¤   ¤   final = TRUE;
b4c184 ¤   ¤   } else if (len0 == 0xff) {
e56144 ¤   ¤   ¤   if (pgpFileRead(arr4, 4, f) != 4)
c11b7c ¤   ¤   ¤   ¤   goto error;
bde626 ¤   ¤   ¤   len += (((((arr4[0]<<8)|arr4[1])<<8)|arr4[2])<<8)|arr4[3];
4ac895 ¤   ¤   ¤   final = TRUE;
6545a6 ¤   ¤   } else {
ddb867 ¤   ¤   ¤   /* Indeterminate length. ·Count partial size and add up to total */
31f60f ¤   ¤   ¤   len0 = 1 << (len0 & 0x1f);
f8892a ¤   ¤   ¤   len += len0;
fabb9b ¤   ¤   ¤   /* Remember first packet position and size */
b983e4 ¤   ¤   ¤   if (lenfirst == 0) {
70e002 ¤   ¤   ¤   ¤   pgpAssert (len0 != 0);
af7b65 ¤   ¤   ¤   ¤   fpos = pgpFileTell(f);
bf3580 ¤   ¤   ¤   ¤   lenfirst = len0;
34a3a6 ¤   ¤   ¤   }
263251 ¤   ¤   ¤   err = pgpFileSeek( f, len0, 1 );
75d8c0 ¤   ¤   ¤   if( IsPGPError( err ) ) {
e85662 ¤   ¤   ¤   ¤   pgpFileSeek( f, fpos, 0 );
23454a ¤   ¤   ¤   ¤   return err;
09a3a6 ¤   ¤   ¤   }
69d007 ¤   ¤   ¤   /* Loop for next subpacket */
e70fe4 ¤   ¤   }
5de719 ¤   } while (!final);
87af5a
3e6cf5 ¤   if (lenfirst != 0) {
b6c410 ¤   ¤   err = pgpFileSeek( f, fpos, 0 );
26d223 ¤   ¤   if( IsPGPError( err ) )
e0b32f ¤   ¤   ¤   return err;
c7a9ac ¤   ¤   *len1p = lenfirst;
dbf037 ¤   } else {
03c106 ¤   ¤   *len1p = len;
de9371 ¤   }
8ce15a ¤   *lenp = len;
c0151e ¤   return kPGPError_NoErr;
afaf5a
3760ff error:
6f90a5 ¤   if (!pgpFileError(f))
ec1497 ¤   ¤   return kPGPError_EOF;
ed3c98 ¤   pgpFileClearError(f);
436328 ¤   return kPGPError_ReadFailed;
68efe6 }
deaf5a
3338e5 /*
9a4c13 ·* Returns packet byte, 0 on normal EOF, or error code < 0.
ab1802 ·* Returns length of whole packet, plus length of first sub-packet for
601d0b ·* case of indefinite-length packets.
dd495d ·*/
034d2f int
9ec5c9 pktByteGet(PGPFile *f, PGPSize *lenp, PGPSize *len1p, PGPSize *posp)
a4bb36 {
d14fc6 ¤   PGPByte pktbyte;
63baf6 ¤   PGPByte buf4[4];
0f9833 ¤   PGPSize len = 0;
53af5a
d130dd ¤   if (posp) {
e02f89 ¤   ¤   *posp = pgpFileTell(f);
caf1a6 ¤   ¤   if (*posp == (PGPSize)-1)
4c14d1 ¤   ¤   ¤   return kPGPError_FileOpFailed;
a39371 ¤   }
99af5a
c2305a ¤   if (pgpFileRead(&pktbyte, 1, f) != 1)
109fb4 ¤   ¤   return pgpFileError(f) ? kPGPError_ReadFailed : 0;
fcaf5a
6e4db4 ¤   if (IS_OLD_PKTBYTE(pktbyte)) {
6bcb7d ¤   ¤   switch(PKTBYTE_LLEN(pktbyte)) {
e33a80 ¤   ¤   ··case 3:
654fd5 ¤   ¤   ¤   /* Indeterminate length, can't handle that */
--29e2 000d47dc262401001fb Page 3 of pgpRngPkt.c
98c40e ¤   ¤   ¤   return kPGPError_BadPacket;
a7605c ¤   ¤   ··case 2:
1599bb ¤   ¤   ¤   if (pgpFileRead(buf4, 4, f) != 4)
301b7c ¤   ¤   ¤   ¤   goto error;
b49128 ¤   ¤   ¤   len = (PGPSize)buf4[0]<<24 | (PGPSize)buf4[1]<<16 |
5bebb2 ¤   ¤   ¤   ¤   ¤   ¤   ·(PGPSize)buf4[2]<<8 | (PGPSize)buf4[3];
d8cdcb ¤   ¤   ¤   break;
6c8f38 ¤   ¤   ··case 1:
8c48af ¤   ¤   ¤   if (pgpFileRead(buf4, 2, f) != 2)
831b7c ¤   ¤   ¤   ¤   goto error;
02c13b ¤   ¤   ¤   len = (PGPSize)buf4[0]<<8 | (PGPSize)buf4[1];
f2cdcb ¤   ¤   ¤   break;
67d5e4 ¤   ¤   ··case 0:
aa2025 ¤   ¤   ¤   if (pgpFileRead(buf4, 1, f) != 1)
a31b7c ¤   ¤   ¤   ¤   goto error;
549990 ¤   ¤   ¤   len = (PGPSize)buf4[0];
74cdcb ¤   ¤   ¤   break;
a90fe4 ¤   ¤   }
f3bcc0 ¤   } else if (IS_NEW_PKTBYTE(pktbyte)) {
bfacc3 ¤   ¤   PGPError err = pktLengthNew( f, lenp, len1p );
50d223 ¤   ¤   if( IsPGPError( err ) )
5eb32f ¤   ¤   ¤   return err;
53fbda ¤   ¤   return (int)pktbyte;
aa2be7 ¤   } else
7f015b ¤   ¤   return kPGPError_BadPacket;
00af5a
ccb410 ¤   *lenp = *len1p = len;
15cf87 ¤   return (int)pktbyte;
08af5a
2a60ff error:
c990a5 ¤   if (!pgpFileError(f))
ce1497 ¤   ¤   return kPGPError_EOF;
063c98 ¤   pgpFileClearError(f);
ee6328 ¤   return kPGPError_ReadFailed;
32efe6 }
a2af5a
89af5a
f838e5 /*
c45ef8 ·* Read the body of a ring packet. ·Len is the length of the whole packet,
316c04 ·* and len1 is the length of the first subpacket. ·If these are equal we
9bdca9 ·* just read raw data. ·Else we read len1 bytes and then deal with the
f40d39 ·* additional subpackets. ·We return the number of bytes read.
1b495d ·*/
f431ca PGPSize
634e62 pktBodyRead(void *ptr, PGPSize len, PGPSize len1, PGPFile *f)
5dbb36 {
9e47c6 ¤   PGPBoolean final;
3230bf ¤   PGPSize nread = 0;
770cdb ¤   PGPSize n;
5ca508 ¤   PGPByte c;
3d2a40 ¤   PGPByte arr4[4];
93af5a
197f0b ¤   if (len == len1) {
0cb140 ¤   ¤   return pgpFileRead (ptr, len, f);
ba9371 ¤   }
69af5a
5820eb ¤   /* Must read multiple subpackets */
c12ba7 ¤   final = FALSE;
d55870 ¤   for ( ; ; ) {
1de7a7 ¤   ¤   n = pgpFileRead (ptr, len1, f);
69afca ¤   ¤   if (n != len1)
b4cdcb ¤   ¤   ¤   break;
fe876b ¤   ¤   nread += len1;
54dc85 ¤   ¤   if (final)
efcdcb ¤   ¤   ¤   break;
f9950f ¤   ¤   ptr = (PGPByte *)ptr + len1;
17c26e ¤   ¤   if (pgpFileRead(&c, 1, f) != 1)
63cdcb ¤   ¤   ¤   break;
8171b2 ¤   ¤   len1 = c;
df479d ¤   ¤   if (len1 < 0xc0) {
e58cdb ¤   ¤   ¤   /* One byte length, final packet */
d4c895 ¤   ¤   ¤   final = TRUE;
--8069 00097adfb37401001fb Page 4 of pgpRngPkt.c
8cb1be ¤   ¤   } else if ((len1 & 0xe0) == 0xc0) {
5f7899 ¤   ¤   ¤   /* Two byte length, final packet */
fef46a ¤   ¤   ¤   len1 &= 0x3f;
ef4a08 ¤   ¤   ¤   if (pgpFileRead(&c, 1, f) != 1)
9af622 ¤   ¤   ¤   ¤   break;
bc4937 ¤   ¤   ¤   len1 = (len1 << 8) + (PGPSize)c + 192;
bdc895 ¤   ¤   ¤   final = TRUE;
b4c429 ¤   ¤   } else if (len1 == 0xff) {
e1d0c6 ¤   ¤   ¤   /* Four byte length, final packet */
9c6144 ¤   ¤   ¤   if (pgpFileRead(arr4, 4, f) != 4)
fef622 ¤   ¤   ¤   ¤   break;
23ee51 ¤   ¤   ¤   len1 = (((((arr4[0]<<8)|arr4[1])<<8)|arr4[2])<<8)|arr4[3];
f2c895 ¤   ¤   ¤   final = TRUE;
ef45a6 ¤   ¤   } else {
f50404 ¤   ¤   ¤   /* Indeterminate length, non-final packet */
8df8da ¤   ¤   ¤   len1 = 1 << (len1 & 0x1f);
a90fe4 ¤   ¤   }
8c9371 ¤   }
75af5a
7ac964 ¤   return nread;
bbefe6 }
0aaf5a
a1af5a
2f38e5 /*
224d66 ·* Returns the number of bytes which will be output by pktBytePut with the
4447ca ·* corresponding args.
cd495d ·*/
b24d2f int
2f881d pktByteLen (PGPByte pktbyte, PGPSize len)
59bb36 {
2d4db4 ¤   if (IS_OLD_PKTBYTE(pktbyte)) {
3d0bf8 ¤   ¤   /* "Promote" packet byte llen field */
1357ba ¤   ¤   /* if necessary to accomodate length */
a715ec ¤   ¤   if (len == 0xfffffff) {
318ee3 ¤   ¤   ¤   pktbyte |= 3;
67c6f9 ¤   ¤   } else if (len > 0xffff) {
634264 ¤   ¤   ¤   if (!(pktbyte & 2))
039a90 ¤   ¤   ¤   ¤   pktbyte = (pktbyte & ~3) | 2;
f84f57 ¤   ¤   } else if (len > 0xff) {
24b281 ¤   ¤   ¤   if ((pktbyte & 3) == 0)
06b20f ¤   ¤   ¤   ¤   pktbyte |= 1;
370fe4 ¤   ¤   }
a7c3f8 ¤   ¤   switch(pktbyte & 3) {
823a80 ¤   ¤   ··case 3:
bf8cc0 ¤   ¤   ¤   ··return 1;
7b605c ¤   ¤   ··case 2:
beefa1 ¤   ¤   ¤   ··return 5;
f88f38 ¤   ¤   ··case 1:
493978 ¤   ¤   ¤   ··return 3;
c2d5e4 ¤   ¤   ··case 0:
7b63a4 ¤   ¤   ¤   ··return 2;
ef0fe4 ¤   ¤   }
3ef037 ¤   } else {
fb23f4 ¤   ¤   pgpAssert(IS_NEW_PKTBYTE(pktbyte));
688586 ¤   ¤   if (PKTLEN_ONE_BYTE(len)) {
0d34fc ¤   ¤   ¤   return 2;
82919e ¤   ¤   } else if (PKTLEN_TWO_BYTES(len)) {
c06e20 ¤   ¤   ¤   return 3;
b445a6 ¤   ¤   } else {
3b579d ¤   ¤   ¤   return 6;
c70fe4 ¤   ¤   }
cc9371 ¤   }
6267c5 ¤
681df4 ¤   /* Avoid warning */
e14aac ¤   pgpAssert(0);
8b3e6b ¤   return 0;
deefe6 }
40af5a
a738e5 /*
3f4009 ·* Returns the packet byte actually written, whose llen field may be greater
ad8718 ·* than the one passed in, but will not be less, or error code < 0.
97f739 ·* Also optionally returns the size of the first subpacket, for cases where
--ac08 000a011dcb8401001fb Page 5 of pgpRngPkt.c
a213d7 ·* multiple subpackets are being used.
df495d ·*/
af4d2f int
329f76 pktBytePut(PGPFile *f, PGPByte pktbyte, PGPSize len, PGPSize *len1p)
a4bb36 {
a82395 ¤   PGPByte¤¤   buf6[6];
9886cd ¤   PGPUInt32¤  llen;
f73340 ¤   PGPByte¤¤   len1;
5faf5a
234db4 ¤   if (IS_OLD_PKTBYTE(pktbyte)) {
b00bf8 ¤   ¤   /* "Promote" packet byte llen field */
ba57ba ¤   ¤   /* if necessary to accomodate length */
b915ec ¤   ¤   if (len == 0xfffffff) {
cf8ee3 ¤   ¤   ¤   pktbyte |= 3;
b0c6f9 ¤   ¤   } else if (len > 0xffff) {
8f4264 ¤   ¤   ¤   if (!(pktbyte & 2))
299a90 ¤   ¤   ¤   ¤   pktbyte = (pktbyte & ~3) | 2;
484f57 ¤   ¤   } else if (len > 0xff) {
dbb281 ¤   ¤   ¤   if ((pktbyte & 3) == 0)
f0b20f ¤   ¤   ¤   ¤   pktbyte |= 1;
d20fe4 ¤   ¤   }
deaf5a
62357b ¤   ¤   if (pgpFileWrite(&pktbyte, 1, f) != 1)
fad165 ¤   ¤   ¤   return kPGPError_WriteFailed;
6baf5a
8fc3f8 ¤   ¤   switch(pktbyte & 3) {
b83a80 ¤   ¤   ··case 3:
4acb6a ¤   ¤   ¤   /* no length field */
9547c9 ¤   ··¤ ¤   break;
98605c ¤   ¤   ··case 2:
26176c ¤   ¤   ¤   buf6[0] = (PGPByte)(len >> 24);
df619e ¤   ¤   ¤   buf6[1] = (PGPByte)(len >> 16);
b488c9 ¤   ¤   ¤   buf6[2] = (PGPByte)(len >> ·8);
86be10 ¤   ¤   ¤   buf6[3] = (PGPByte)(len ·····);
92cf1f ¤   ¤   ¤   if (pgpFileWrite(buf6, 4, f) != 4)
38e8a0 ¤   ¤   ¤   ¤   return kPGPError_WriteFailed;
2ccdcb ¤   ¤   ¤   break;
718f38 ¤   ¤   ··case 1:
252c59 ¤   ¤   ¤   buf6[0] = (PGPByte)(len >> ·8);
9c1a80 ¤   ¤   ¤   buf6[1] = (PGPByte)(len ·····);
811e0b ¤   ¤   ¤   if (pgpFileWrite(buf6, 2, f) != 2)
20e8a0 ¤   ¤   ¤   ¤   return kPGPError_WriteFailed;
decdcb ¤   ¤   ¤   break;
e7d5e4 ¤   ¤   ··case 0:
a0d47a ¤   ¤   ¤   buf6[0] = (PGPByte)len;
1b7681 ¤   ¤   ¤   if (pgpFileWrite(buf6, 1, f) != 1)
77e8a0 ¤   ¤   ¤   ¤   return kPGPError_WriteFailed;
8ecdcb ¤   ¤   ¤   break;
940fe4 ¤   ¤   }
8df106 ¤   ¤   if (len1p)
b506b3 ¤   ¤   ¤   *len1p = len;
10f037 ¤   } else {
5e23f4 ¤   ¤   pgpAssert(IS_NEW_PKTBYTE(pktbyte));
f9f8dc ¤   ¤   buf6[0] = (PGPByte)pktbyte;
7e0f9b ¤   ¤   if (PKTLEN_TWO_BYTES(len)) {
f440d3 ¤   ¤   ¤   if (PKTLEN_ONE_BYTE(len)) {
630830 ¤   ¤   ¤   ¤   buf6[1] = PKTLEN_1BYTE(len);
d3abc2 ¤   ¤   ¤   ¤   llen = 2;
85042d ¤   ¤   ¤   } else {
798d69 ¤   ¤   ¤   ¤   buf6[1] = PKTLEN_BYTE0(len);
3be11a ¤   ¤   ¤   ¤   buf6[2] = PKTLEN_BYTE1(len);
23f11e ¤   ¤   ¤   ¤   llen = 3;
1da3a6 ¤   ¤   ¤   }
a6caef ¤   ¤   ¤   if (len1p)
3e8fe7 ¤   ¤   ¤   ¤   *len1p = len;
5045a6 ¤   ¤   } else {
6cb177 #if 0
c83df9 // Must change value in pktBodyWrite also
f180bd ¤   ¤   ¤   /* Use four byte mode */
de14e6 ¤   ¤   ¤   buf6[1] = 0xff;
7db3fc ¤   ¤   ¤   buf6[2] = (PGPByte)(len >> 24);
a0c50e ¤   ¤   ¤   buf6[3] = (PGPByte)(len >> 16);
--fbe2 000e518c107401001fb Page 6 of pgpRngPkt.c
f26d68 ¤   ¤   ¤   buf6[4] = (PGPByte)(len >> ·8);
c7daf8 ¤   ¤   ¤   buf6[5] = (PGPByte)(len >> ·0);
010f16 ¤   ¤   ¤   llen = 6;
fbcaef ¤   ¤   ¤   if (len1p)
1b8fe7 ¤   ¤   ¤   ¤   *len1p = len;
7edb21 #else
4ac7e8 /* This is used if we are using variable length subpackets */
087bae ¤   ¤   ¤   /* Just output length for first subpacket */
de27af ¤   ¤   ¤   len1 = 0;
562f76 ¤   ¤   ¤   while (len>>=1)
97ed8c ¤   ¤   ¤   ¤   ++len1;
1aa5ce ¤   ¤   ¤   buf6[1] = PKTLEN_PARTIAL(len1);
386c77 ¤   ¤   ¤   llen = 2;
c18278 ¤   ¤   ¤   pgpAssert(len1p);
6dd028 ¤   ¤   ¤   *len1p = 1<<len1;
a17454 #endif
7d0fe4 ¤   ¤   }
1360f7 ¤   ¤   if (pgpFileWrite(buf6, llen, f) != llen)
00d165 ¤   ¤   ¤   return kPGPError_WriteFailed;
879371 ¤   }
ca7203 ¤   return pktbyte;
eaefe6 }
f2af5a
a738e5 /*
291034 ·* Write the body of a ring packet. ·Len is the length of the whole packet,
7f6c04 ·* and len1 is the length of the first subpacket. ·If these are equal we
76cebe ·* just rite raw data. ·Else we write len1 bytes and then deal with the
2e9202 ·* additional subpackets. ·We return the number of bytes written.
92495d ·*/
1e31ca PGPSize
495bfe pktBodyWrite(void const *ptr, PGPSize len, PGPSize len1, PGPFile *f)
4abb36 {
d3b9ad ¤   PGPSize nwritten = 0;
bc0cdb ¤   PGPSize n;
4aa266 ¤   PGPByte buf5[5];
2b719a ¤   PGPUInt32 llen;
56af5a
3a7f0b ¤   if (len == len1) {
95cf94 ¤   ¤   return pgpFileWrite (ptr, len, f);
5c9371 ¤   }
f0af5a
5d4c81 ¤   /* Must write multiple subpackets */
c85870 ¤   for ( ; ; ) {
c21fc0 ¤   ¤   n = pgpFileWrite (ptr, len1, f);
b6afca ¤   ¤   if (n != len1)
b2cdcb ¤   ¤   ¤   break;
53e828 ¤   ¤   nwritten += len1;
ce950f ¤   ¤   ptr = (PGPByte *)ptr + len1;
45c638 ¤   ¤   len -= len1;
7fb969 ¤   ¤   if (len == 0)
fdcdcb ¤   ¤   ¤   break;
200f9b ¤   ¤   if (PKTLEN_TWO_BYTES(len)) {
6940d3 ¤   ¤   ¤   if (PKTLEN_ONE_BYTE(len)) {
fd0c95 ¤   ¤   ¤   ¤   buf5[0] = PKTLEN_1BYTE(len);
f344a6 ¤   ¤   ¤   ¤   llen = 1;
c4042d ¤   ¤   ¤   } else {
2e89cc ¤   ¤   ¤   ¤   buf5[0] = PKTLEN_BYTE0(len);
645337 ¤   ¤   ¤   ¤   buf5[1] = PKTLEN_BYTE1(len);
15abc2 ¤   ¤   ¤   ¤   llen = 2;
20a3a6 ¤   ¤   ¤   }
8d9bf0 ¤   ¤   ¤   len1 = len;
7145a6 ¤   ¤   } else {
e0b177 #if 0
bba955 // Must change value in pktBytePut also
944f80 ¤   ¤   ¤   buf5[0] = 0xff;
f34666 ¤   ¤   ¤   buf5[1] = (PGPByte)(len >> 24);
099404 ¤   ¤   ¤   buf5[2] = (PGPByte)(len >> 16);
bbd9c3 ¤   ¤   ¤   buf5[3] = (PGPByte)(len >> ·8);
508bf2 ¤   ¤   ¤   buf5[4] = (PGPByte)(len >> ·0);
fce072 ¤   ¤   ¤   llen = 5;
c79bf0 ¤   ¤   ¤   len1 = len;
e5db21 #else
--adbc 000ed5fb0c0401001fb Page 7 of pgpRngPkt.c
20c7e8 /* This is used if we are using variable length subpackets */
d7258c ¤   ¤   ¤   /* Output length for next subpacket */
f78da3 ¤   ¤   ¤   PGPSize tlen = len;
0127af ¤   ¤   ¤   len1 = 0;
6925df ¤   ¤   ¤   while (tlen>>=1)
dded8c ¤   ¤   ¤   ¤   ++len1;
e0f4c4 ¤   ¤   ¤   buf5[0] = PKTLEN_PARTIAL(len1);
078313 ¤   ¤   ¤   llen = 1;
e1cc45 ¤   ¤   ¤   len1 = 1 << len1;
027454 #endif
490fe4 ¤   ¤   }
c83943 ¤   ¤   if (pgpFileWrite(buf5, llen, f) != llen)
c5cdcb ¤   ¤   ¤   break;
f89371 ¤   }
1daf5a
843a69 ¤   return nwritten;
b2efe6 }
acaf5a
c7af5a
c7af5a
1438e5 /*
2d7956 ·* Compare data from a file to a supplied buffer, returning < 0
8f99ce ·* on a read error, 0 on equal, and 1 on unequal. ·Len is the length
e19736 ·* of the data, len1 is the size of the first subpacket to compare to.
08917e ·* We may be called with len less than the size of the whole packet.
14495d ·*/
be4d2f int
a0dee2 fileUnequalBuf(PGPFile *f, void const *buf, PGPSize len, PGPSize len1)
e0bb36 {
77b87b ¤   char buf2[256];
b93d81 ¤   PGPSize amount;
d3a508 ¤   PGPByte c;
e82a40 ¤   PGPByte arr4[4];
b3af5a
b085aa ¤   while (len) {
f255c2 ¤   ¤   if (len < len1)
389bf0 ¤   ¤   ¤   len1 = len;
2cc638 ¤   ¤   len -= len1;
11ca3c ¤   ¤   while (len1) {
d2eeb8 ¤   ¤   ¤   amount = len1 < sizeof(buf2) ? len1 : sizeof(buf2);
7df64a ¤   ¤   ¤   amount = pgpFileRead(buf2, amount, f);
9183b5 ¤   ¤   ¤   if (!amount)
392298 ¤   ¤   ¤   ¤   return pgpFileError(f) ? kPGPError_ReadFailed
e0fb63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···: kPGPError_EOF;
4e85a9 ¤   ¤   ¤   if (memcmp(buf, buf2, amount) != 0)
6f1c2d ¤   ¤   ¤   ¤   return 1;
deaf5a
319f00 ¤   ¤   ¤   len1 -= amount;
6bac44 ¤   ¤   ¤   buf = (PGPByte *)buf + amount;
460fe4 ¤   ¤   }
50b4db ¤   ¤   if (len) {
7dd9cf ¤   ¤   ¤   /* Read next subpacket size */
4d4a08 ¤   ¤   ¤   if (pgpFileRead(&c, 1, f) != 1)
c42298 ¤   ¤   ¤   ¤   return pgpFileError(f) ? kPGPError_ReadFailed
78fb63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···: kPGPError_EOF;
734b28 ¤   ¤   ¤   len1 = c;
7b53b5 ¤   ¤   ¤   if (len1 < 0xc0) {
8f1a9a ¤   ¤   ¤   ¤   /* One byte length, final packet */
f3a9ee ¤   ¤   ¤   } else if ((len1 & 0xe0) == 0xc0) {
51eed8 ¤   ¤   ¤   ¤   /* Two byte length, final packet */
ce7d3e ¤   ¤   ¤   ¤   len1 &= 0x3f;
e65258 ¤   ¤   ¤   ¤   if (pgpFileRead(&c, 1, f) != 1)
b09e81 ¤   ¤   ¤   ¤   ¤   return pgpFileError(f) ? kPGPError_ReadFailed
b3fb63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···: kPGPError_EOF;
845810 ¤   ¤   ¤   ¤   len1 = (len1 << 8) + (PGPSize)c + 192;
ab85da ¤   ¤   ¤   } else if (len1 == 0xff) {
7f83dd ¤   ¤   ¤   ¤   /* Four byte length, final packet */
712e7a ¤   ¤   ¤   ¤   if (pgpFileRead(arr4, 4, f) != 4)
fe9e81 ¤   ¤   ¤   ¤   ¤   return pgpFileError(f) ? kPGPError_ReadFailed
11fb63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···: kPGPError_EOF;
813efa ¤   ¤   ¤   ¤   len1 = (((((arr4[0]<<8)|arr4[1])<<8)|arr4[2])<<8)|arr4[3];
ed042d ¤   ¤   ¤   } else {
--e216 00077138c4e401001fb Page 8 of pgpRngPkt.c
fc22b1 ¤   ¤   ¤   ¤   /* Indeterminate length, non-final packet */
60f696 ¤   ¤   ¤   ¤   len1 = 1 << (len1 & 0x1f);
a4a3a6 ¤   ¤   ¤   }
630fe4 ¤   ¤   }
5c9371 ¤   }
da63fd ¤   return 0;¤  /* Match */
2befe6 }
b0af5a
6daf5a
20af5a
3faf5a
7a38e5 /*
930dfb ·* Returns the number of size bytes which will be output by
24fff9 ·* pktSubpacketCreate with the corresponding length.
6e495d ·*/
ad31ca PGPSize
c6af6b pktSubpacketByteLen (PGPSize len)
87bb36 {
0daf5a
83a8af #if 1
d23950 ¤   /* Use fixed size headers: 0xff then four bytes of length */
b0481d ¤   (void) len;
3507d6 ¤   return 5;
64db21 #else
8003cb ¤   /* Use variable sized headers */
945bfe ¤   PGPSize count = 0;
7eaf5a
bc5870 ¤   for ( ; ; ) {
e1d888 ¤   ¤   PGPSize tlen;
b1533b ¤   ¤   PGPUInt32 len1;
26af5a
3e8586 ¤   ¤   if (PKTLEN_ONE_BYTE(len)) {
5394e7 ¤   ¤   ¤   return count+1;
b045a6 ¤   ¤   } else {
f67b83 ¤   ¤   ¤   return count+2;
040fe4 ¤   ¤   }
81af5a
089479 ¤   ¤   /* Calculate length for next subpacket */
cc8594 ¤   ¤   tlen = len;
161d35 ¤   ¤   len1 = 0;
851182 ¤   ¤   while (tlen>>=1)
4d9778 ¤   ¤   ¤   ++len1;
c456fb ¤   ¤   ++count;
e01f32 ¤   ¤   pgpAssert ((PGPSize)(1 << len1) <= len);
ddcdef ¤   ¤   len -= 1 << len1;
03b969 ¤   ¤   if (len == 0)
f9ee47 ¤   ¤   ¤   return count;
1a9371 ¤   }
607454 #endif
35efe6 }
beaf5a
5baf5a
4e38e5 /*
45ef13 ·* Create a subpacket with the given type and data, outputting to the
fc36b4 ·* specified buffer. ·Return number of bytes written, which should equal
019c48 ·* len + 1 plus the amount returned by pktSubpacketByteLen( len+1 ).
43495d ·*/
bc31ca PGPSize
c64840 pktSubpacketCreate (PGPByte type, PGPByte const *data, PGPSize len,
7c1e30 ¤   PGPByte *pktbuf)
8bbb36 {
d6a8af #if 1
30df1c ¤   /* Use fixed size buffer headers */
09f163 ¤   *pktbuf++ = 0xff;
0eb255 ¤   *pktbuf++ = (PGPByte) ((len+1) >> 24);
db96ef ¤   *pktbuf++ = (PGPByte) ((len+1) >> 16);
128960 ¤   *pktbuf++ = (PGPByte) ((len+1) >> ·8);
eb6cb8 ¤   *pktbuf++ = (PGPByte) ((len+1) >> ·0);
938f05 ¤   *pktbuf++ = type;
1d265f ¤   pgpCopyMemory (data, pktbuf, len);
386dcb ¤   return len + 1 + 5;
77db21 #else
--4f35 001ff7406bf401001fb Page 9 of pgpRngPkt.c
3803cb ¤   /* Use variable sized headers */
23b9ad ¤   PGPSize nwritten = 0;
177ce0 ¤   PGPSize len1 = 0;
d23d36 ¤   PGPBoolean first;
ccaf5a
00c809 ¤   /* Count extra type byte */
2bc565 ¤   len += 1;
f48991 ¤   first = 1;
d5af5a
ec85aa ¤   while (len) {
290f9b ¤   ¤   if (PKTLEN_TWO_BYTES(len)) {
c840d3 ¤   ¤   ¤   if (PKTLEN_ONE_BYTE(len)) {
ff5727 ¤   ¤   ¤   ¤   *pktbuf++ = PKTLEN_1BYTE(len);
4ef626 ¤   ¤   ¤   ¤   nwritten += 1;
04042d ¤   ¤   ¤   } else {
9ad27e ¤   ¤   ¤   ¤   *pktbuf++ = PKTLEN_BYTE0(len);
9b53c1 ¤   ¤   ¤   ¤   *pktbuf++ = PKTLEN_BYTE1(len);
361942 ¤   ¤   ¤   ¤   nwritten += 2;
aca3a6 ¤   ¤   ¤   }
319bf0 ¤   ¤   ¤   len1 = len;
9745a6 ¤   ¤   } else {
d2258c ¤   ¤   ¤   /* Output length for next subpacket */
ff8da3 ¤   ¤   ¤   PGPSize tlen = len;
aa27af ¤   ¤   ¤   len1 = 0;
8e25df ¤   ¤   ¤   while (tlen>>=1)
a8ed8c ¤   ¤   ¤   ¤   ++len1;
88ab0f ¤   ¤   ¤   *pktbuf++ = PKTLEN_PARTIAL(len1);
f6cc45 ¤   ¤   ¤   len1 = 1 << len1;
3de20e ¤   ¤   ¤   nwritten += 1;
e30fe4 ¤   ¤   }
deb7fb ¤   ¤   if( first ) {
f4c1e4 ¤   ¤   ¤   *pktbuf++ = type;
1767a5 ¤   ¤   ¤   len1 -= 1;
c562b0 ¤   ¤   ¤   len -= 1;
4be20e ¤   ¤   ¤   nwritten += 1;
e4492f ¤   ¤   ¤   first = FALSE;
a90fe4 ¤   ¤   }
5e3446 ¤   ¤   pgpCopyMemory (data, pktbuf, len1);
c0021c ¤   ¤   pktbuf += len1;
e08ecb ¤   ¤   data += len1;
99e828 ¤   ¤   nwritten += len1;
bfc638 ¤   ¤   len -= len1;
c29371 ¤   }
2baf5a
d73a69 ¤   return nwritten;
dd7454 #endif
ffefe6 }
--aecf 001424ee04e401001fc Page 1 of pgpRngPkt.h
bc38e5 /*
d182b8 ·* Low-level packet-handling routines for keyring management.
4f775e ·*
efad4d ·* $Id: pgpRngPkt.h,v 1.8 1998/01/28 22:17:46 hal Exp $
cd495d ·*/
6c0fda #ifndef Included_pgpRngPkt_h
d88eec #define Included_pgpRngPkt_h
beaf5a
17d11f #include "pgpUsuals.h"
d5af5a
a799c6 PGP_BEGIN_C_DECLARATIONS
02af5a
d10828 struct PGPFile;
41af5a
9e57de #ifdef DEADCODE
3b212d extern char const * const packet_type[16];
be3707 #endif /* DEADCODE */
aad83c ·
d66f08 int pktByteGet(PGPFile *f, PGPSize *lenp, PGPSize *len1p, PGPSize *posp);
70222e int pktBytePut(PGPFile *f, PGPByte pktbyte, PGPSize len, PGPSize *len1p);
ca7d6e int pktByteLen (PGPByte pktbyte, PGPSize len);
f99076 int fileUnequalBuf(PGPFile *f, void const *buf, PGPSize len, PGPSize len1);
acbbb2 PGPSize pktBodyRead(void *ptr, PGPSize len, PGPSize len1, PGPFile *f);
186cfb PGPSize pktBodyWrite(void const *ptr, PGPSize len, PGPSize len1, PGPFile *f);
1f6120 PGPSize pktSubpacketByteLen (PGPSize len);
05ee29 PGPSize pktSubpacketCreate (PGPByte type, PGPByte const *data, PGPSize len,
f831bd ¤   PGPByte *pktbuf);
c0af5a
181254 PGP_END_C_DECLARATIONS
85d83c ·
423bd8 #endif /* Included_pgpRngPkt_h */
--cfee 0003106ea06401001fd Page 1 of pgpRngPriv.c
bc38e5 /*
4b0d46 ·* Private helper functions for keyring manipulation.
e3775e ·*
5768c2 ·* Written by Colin Plumb.
03775e ·*
a8e0da ·* $Id: pgpRngPriv.c,v 1.39 1998/08/07 05:06:23 hal Exp $
3a495d ·*/
7fe2ff #include "pgpConfig.h"
7faf5a
2c495d #include <errno.h>
49324c #include <string.h>
e2feb2 #include <stdio.h>
aaaf5a
afa146 #include "pgpDebug.h"
349c38 #include "pgpPktByte.h"
577a44 #include "pgpRngPriv.h"
3b2e22 #include "pgpRngPars.h"
e96197 #include "pgpRngRead.h"¤¤   /* For ringFilePurgeTrouble */
46ae6d #include "pgpTrstPkt.h"
3a5417 #include "pgpHashPriv.h"
b40d6d #include "pgpEnv.h"
d12f8d #include "pgpErrors.h"
b10d08 #include "pgpMem.h"
a4d646 #include "pgpSigSpec.h"¤/* for PGP_SIGTYPE */
ea5a03 #include "pgpTrust.h"
d5c26c #include "pgpContext.h"
f65d53 #include "pgpRegExp.h"
e6af5a
d30596 #ifndef NULL
ed699b #define NULL 0
eb7454 #endif
79af5a
afcbca #define PGP_TRUST_DECADE_INTERNAL (PGP_TRUST_DECADE >> 6)
c4fb0a #define PGP_TRUST_OCTAVE_INTERNAL (PGP_TRUST_OCTAVE >> 6)
c9af5a
a338e5 /*
4af703 ·* Virtual ring mask functions
f6495d ·*/
31af5a
87765a #if !VIRTMASK
4baf5a
adc6d6 /* Use old data structure for backwards compatibility */
87af5a
bec77d PGPError
6cfabe pgpVirtMaskInit (RingPool const *pool, PGPVirtMask *mask)
bdbb36 {
17e7bd ¤   (void) pool;
0629fa ¤   (void) mask;
64f6fe ¤   *mask = (PGPVirtMask)0;
88151e ¤   return kPGPError_NoErr;
b3efe6 }
67af5a
ab62cf /* Need a lighter weight memory allocation package! */
4cc77d PGPError
497729 pgpVirtMaskCleanup (RingPool const *pool, PGPVirtMask *mask)
99bb36 {
abe7bd ¤   (void) pool;
bb29fa ¤   (void) mask;
b7f6fe ¤   *mask = (PGPVirtMask)0;
de151e ¤   return kPGPError_NoErr;
30efe6 }
45af5a
ccc77d PGPError
590564 pgpVirtMaskOR (RingPool const *pool, PGPVirtMask const *imask,
47eca1 ¤   PGPVirtMask *omask)
46bb36 {
2ee7bd ¤   (void) pool;
9bc049 ¤   *omask |= *imask;
e6151e ¤   return kPGPError_NoErr;
7befe6 }
78af5a
31c77d PGPError
--7b48 00087cd8e03401001fd Page 2 of pgpRngPriv.c
168731 pgpVirtMaskAND (RingPool const *pool, PGPVirtMask const *imask,
4ceca1 ¤   PGPVirtMask *omask)
01bb36 {
2ce7bd ¤   (void) pool;
8b6b81 ¤   *omask &= *imask;
ab151e ¤   return kPGPError_NoErr;
f0efe6 }
91af5a
adc77d PGPError
6137a3 pgpVirtMaskANDNOT (RingPool const *pool, PGPVirtMask const *imask,
a7eca1 ¤   PGPVirtMask *omask)
18bb36 {
84e7bd ¤   (void) pool;
600529 ¤   *omask &= ~*imask;
a1151e ¤   return kPGPError_NoErr;
0cefe6 }
8eaf5a
b1c77d PGPError
84d4e1 pgpVirtMaskSetBit (RingPool const *pool, PGPVirtMask *mask,
32a792 ¤   PGPUInt32 bitnumber)
c2bb36 {
9ee7bd ¤   (void) pool;
2a02ca ¤   *mask |= (1 << bitnumber);
ae151e ¤   return kPGPError_NoErr;
4aefe6 }
51af5a
04c77d PGPError
8b5d62 pgpVirtMaskClearBit (RingPool const *pool, PGPVirtMask *mask,
7da792 ¤   PGPUInt32 bitnumber)
b2bb36 {
4be7bd ¤   (void) pool;
97d08d ¤   *mask &= ~(1 << bitnumber);
47151e ¤   return kPGPError_NoErr;
d1efe6 }
02af5a
11c77d PGPError
bd83f4 pgpVirtMaskClearGreaterBits (RingPool const *pool, PGPVirtMask *mask,
20bfa9 ¤   PGPUInt32 firstbitnumber)
37bb36 {
bce7bd ¤   (void) pool;
dbdfa5 ¤   if (firstbitnumber < 32)
cb1b58 ¤   ¤   *mask &= (1 << firstbitnumber) - 1;
59151e ¤   return kPGPError_NoErr;
f3efe6 }
aaaf5a
36af5a
b3c77d PGPError
a382d4 pgpVirtMaskCopy (RingPool const *pool, PGPVirtMask const *imask,
23eca1 ¤   PGPVirtMask *omask)
c1bb36 {
8ae7bd ¤   (void) pool;
8d9eec ¤   *omask = *imask;
23151e ¤   return kPGPError_NoErr;
4eefe6 }
ecaf5a
00c77d PGPError
3cbb4e pgpVirtMaskNOT (RingPool const *pool, PGPVirtMask *mask,
b1ec2b ¤   PGPUInt32 highbitnumber)
68bb36 {
32e7bd ¤   (void) pool;
a78eff ¤   *mask = ~*mask;
b415f3 ¤   if (highbitnumber < 32)
6d0bb7 ¤   ¤   *mask &= (1 << highbitnumber) - 1;
63151e ¤   return kPGPError_NoErr;
47efe6 }
d3af5a
751e45 PGPInt32
3b76c3 pgpVirtMaskLSBit (PGPVirtMask const *mask)
b5bb36 {
381e1e ¤   return ringLsBitFind (*mask);
c5efe6 }
87af5a
--4630 000458bb62b401001fd Page 3 of pgpRngPriv.c
9b7750 PGPBoolean
08ed1b pgpVirtMaskIsEmpty (PGPVirtMask const *mask)
a1bb36 {
9f6b90 ¤   return !*mask;
c3efe6 }
e7af5a
b27750 PGPBoolean
51c69e pgpVirtMaskIsEqual (PGPVirtMask const *mask1, PGPVirtMask const *mask2)
c0bb36 {
68d8b8 ¤   return *mask1 == *mask2;
40efe6 }
4eaf5a
867750 PGPBoolean
df1ec2 pgpVirtMaskIsOverlapping (PGPVirtMask const *mask1, PGPVirtMask const *mask2)
e5bb36 {
94179d ¤   return (*mask1 & *mask2) != 0;
fcefe6 }
0caf5a
08af5a
0fba58 #else /* VIRTMASK */
45af5a
9d38e5 /*
7c5cda ·* The original design included a fixed size mask with a bit for
35f369 ·* each ringset in the system. ·However this tended to become
b77d57 ·* exhausted with sufficient user windows open. ·This package
1071f5 ·* provides an (almost) unlimited size virtual ring mask function
27da57 ·* to be compatible with the previous logic but to remove the limits
2c1ea9 ·* on the number of ringsets being manipulated.
49495d ·*/
9faf5a
97c77d PGPError
8dfabe pgpVirtMaskInit (RingPool const *pool, PGPVirtMask *mask)
a5bb36 {
0a7ca6 ¤   (void)pool;
5a6d0e ¤   mask->nwords = 0;
1bb32b ¤   mask->words = NULL;
fe151e ¤   return kPGPError_NoErr;
1aefe6 }
f0af5a
4bb02e #define PVM_LEAKS 0
f8af5a
b86cbe #if PVM_LEAKS
25de45 /* leak detection */
7b5ed0 static struct pvm {
da1973 ¤   struct pvm *next;
57c879 ¤   int num;
a8c1ec ¤   void *addr;
933465 } *pvm_head;
a84efd static int pvm_index;
08af5a
972978 static void
23bf06 pvm_remember (PGPContextRef c, void *addr)
adbb36 {
a7f245 ¤   struct pvm *n;
c3af5a
d9d341 ¤   n = (struct pvm *)pgpContextMemAlloc (c, sizeof(struct pvm), 0);
1da083 ¤   n->next = pvm_head;
5c245c ¤   n->num = pvm_index++;
e18ba5 ¤   n->addr = addr;
275616 ¤   pvm_head = n;
d8efe6 }
05af5a
1b2978 static void
60c576 pvm_forget (PGPContextRef c, void *addr)
83bb36 {
e46c57 ¤   struct pvm *n = pvm_head;
f0e5ec ¤   struct pvm *pn = NULL;
ee065d ¤   while (n) {
a32ba1 ¤   ¤   if (n->addr == addr) {
d79c3a ¤   ¤   ¤   if (pn)
73a49c ¤   ¤   ¤   ¤   pn->next = n->next;
45bb8c ¤   ¤   ¤   else
--b802 000d36e6e6e401001fd Page 4 of pgpRngPriv.c
6ba302 ¤   ¤   ¤   ¤   pvm_head = n->next;
8be366 ¤   ¤   ¤   pgpContextMemFree (c, n);
670ecc ¤   ¤   ¤   return;
540fe4 ¤   ¤   }
25c3fd ¤   ¤   pn = n;
f7bf80 ¤   ¤   n = n->next;
cb9371 ¤   }
db4aac ¤   pgpAssert(0);
74efe6 }
977454 #endif
08af5a
f262cf /* Need a lighter weight memory allocation package! */
54c77d PGPError
b67729 pgpVirtMaskCleanup (RingPool const *pool, PGPVirtMask *mask)
09bb36 {
e4c55b ¤   PGPError err = kPGPError_NoErr;
bec146 ¤   if (mask->nwords != 0) {
4a7180 ¤   ¤   err = pgpContextMemFree (pool->context, mask->words);
056cbe #if PVM_LEAKS
72b639 ¤   ¤   pvm_forget (pool->context, mask->words);
0c7454 #endif
839371 ¤   }
dcb32b ¤   mask->words = NULL;
d16d0e ¤   mask->nwords = 0;
f25ea8 ¤   return err;
d9efe6 }
a2af5a
54f1ae static PGPError
779dce pgpVirtMaskSizeUp (RingPool const *pool, PGPVirtMask *mask,
913f4c ¤   ¤   ¤   ¤   ···PGPUInt32 minwords)
66bb36 {
9b0040 ¤   PGPError err;
7faf5a
77fa4e ¤   /* Make minwords a multiple of 4 to reduce number of resizes */
577459 ¤   minwords += (-minwords) & 3;
16af5a
71b408 ¤   if (mask->nwords < minwords) {
ba2b39 ¤   ¤   if (IsntNull (mask->words)) {
e0f30b ¤   ¤   ¤   void *vptr = mask->words;
656cbe #if PVM_LEAKS
5311a3 ¤   ¤   ¤   pvm_forget (pool->context, vptr);
f67454 #endif
2211e6 ¤   ¤   ¤   err = pgpContextMemRealloc (pool->context, &vptr,
3e152f ¤   ¤   ¤   ¤   minwords * sizeof(*mask->words), kPGPMemoryMgrFlags_Clear);
1c2562 #if PVM_LEAKS¤  ¤   ¤
424ffe ¤   ¤   ¤   pvm_remember (pool->context, vptr);
f07454 #endif
b50dfb ¤   ¤   ¤   if (IsPGPError(err))
3b454a ¤   ¤   ¤   ¤   return err;
9977c2 ¤   ¤   ¤   mask->words = vptr;
9295eb ¤   ¤   ¤   mask->nwords = minwords;
2a45a6 ¤   ¤   } else {
851792 ¤   ¤   ¤   mask->words = pgpContextMemAlloc (pool->context,
84152f ¤   ¤   ¤   ¤   minwords * sizeof(*mask->words), kPGPMemoryMgrFlags_Clear);
a0ec2d ¤   ¤   ¤   if (IsNull(mask->words))
4a451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
ba6cbe #if PVM_LEAKS
61ce5d ¤   ¤   ¤   pvm_remember(pool->context, mask->words);
2d7454 #endif
0f95eb ¤   ¤   ¤   mask->nwords = minwords;
360fe4 ¤   ¤   }
ca9371 ¤   }
2e151e ¤   return kPGPError_NoErr;
7aefe6 }
16af5a
9ac77d PGPError
970564 pgpVirtMaskOR (RingPool const *pool, PGPVirtMask const *imask,
81eca1 ¤   PGPVirtMask *omask)
fdbb36 {
0e0040 ¤   PGPError err;
b851fc ¤   PGPUInt32 i;
d3af5a
--3b8b 0001f3e6662401001fd Page 5 of pgpRngPriv.c
617ec7 ¤   err = pgpVirtMaskSizeUp (pool, omask, imask->nwords);
1bde9b ¤   if (IsPGPError (err))
65c9db ¤   ¤   return err;
a1581a ¤   for (i=0; i<pgpMin(imask->nwords, omask->nwords); ++i)
2ae9e1 ¤   ¤   omask->words[i] |= imask->words[i];
10151e ¤   return kPGPError_NoErr;
4fefe6 }
94af5a
11c77d PGPError
f08731 pgpVirtMaskAND (RingPool const *pool, PGPVirtMask const *imask,
61eca1 ¤   PGPVirtMask *omask)
bfbb36 {
ab51fc ¤   PGPUInt32 i;
84af5a
fb7ca6 ¤   (void)pool;
79581a ¤   for (i=0; i<pgpMin(imask->nwords, omask->nwords); ++i)
e86ee1 ¤   ¤   omask->words[i] &= imask->words[i];
d6f6c7 ¤   for ( ; i<omask->nwords; ++i)
eb2b61 ¤   ¤   omask->words[i] = 0;
6e151e ¤   return kPGPError_NoErr;
adaf5a
6defe6 }
cdaf5a
10c77d PGPError
b637a3 pgpVirtMaskANDNOT (RingPool const *pool, PGPVirtMask const *imask,
81eca1 ¤   PGPVirtMask *omask)
76bb36 {
5451fc ¤   PGPUInt32 i;
d8af5a
9f7ca6 ¤   (void)pool;
f9581a ¤   for (i=0; i<pgpMin(imask->nwords, omask->nwords); ++i)
7ef736 ¤   ¤   omask->words[i] &= ~imask->words[i];
d8151e ¤   return kPGPError_NoErr;
fcaf5a
28efe6 }
24af5a
49c77d PGPError
ecd4e1 pgpVirtMaskSetBit (RingPool const *pool, PGPVirtMask *mask,
b2a792 ¤   PGPUInt32 bitnumber)
9fbb36 {
2c6ee7 ¤   PGPUInt32 bitword;
770040 ¤   PGPError err;
6eaf5a
90f1f5 ¤   bitword = bitnumber / 32;
6df7a1 ¤   err = pgpVirtMaskSizeUp (pool, mask, bitword + 1);
0482f0 ¤   if (IsPGPError(err))
4dc9db ¤   ¤   return err;
2228bc ¤   mask->words[bitword] |= 1 << (bitnumber % 32);
d3151e ¤   return kPGPError_NoErr;
6eefe6 }
8eaf5a
a5c77d PGPError
345d62 pgpVirtMaskClearBit (RingPool const *pool, PGPVirtMask *mask,
f6a792 ¤   PGPUInt32 bitnumber)
babb36 {
d46ee7 ¤   PGPUInt32 bitword;
c9af5a
c1e7bd ¤   (void) pool;
5df1f5 ¤   bitword = bitnumber / 32;
ed415f ¤   if (bitword < mask->nwords)
2b297c ¤   ¤   mask->words[bitword] &= ~ (1 << (bitnumber % 32) );
6c151e ¤   return kPGPError_NoErr;
9fefe6 }
cfaf5a
49c77d PGPError
6383f4 pgpVirtMaskClearGreaterBits (RingPool const *pool, PGPVirtMask *mask,
11bfa9 ¤   PGPUInt32 firstbitnumber)
c1bb36 {
486ee7 ¤   PGPUInt32 bitword;
43af5a
f2e7bd ¤   (void) pool;
1f24be ¤   bitword = firstbitnumber / 32;
--c76c 000c1da4596401001fd Page 6 of pgpRngPriv.c
1b415f ¤   if (bitword < mask->nwords)
77e37e ¤   ¤   mask->words[bitword] &= (1 << (firstbitnumber % 32) ) - 1;
d146d4 ¤   for (++bitword; bitword < mask->nwords; ++bitword) {
57f7f9 ¤   ¤   mask->words[bitword] = 0;
439371 ¤   }
a0151e ¤   return kPGPError_NoErr;
b2efe6 }
a9af5a
638656 /* Complements a mask up to one less than the specified number of bits */
a7c77d PGPError
3cbb4e pgpVirtMaskNOT (RingPool const *pool, PGPVirtMask *mask,
cbec2b ¤   PGPUInt32 highbitnumber)
b9bb36 {
c12835 ¤   PGPUInt32 highbitword;
8a51fc ¤   PGPUInt32 i;
270040 ¤   PGPError err;
beaf5a
f9bfc0 ¤   highbitword = highbitnumber / 32;
2b4550 ¤   err = pgpVirtMaskSizeUp (pool, mask, highbitword + 1);
5582f0 ¤   if (IsPGPError(err))
22c9db ¤   ¤   return err;
2dd20a ¤   for (i=0; i<highbitword; ++i)
8eb51f ¤   ¤   mask->words[i] = ~mask->words[i];
25cf6a ¤   mask->words[highbitword] = ((1 << (highbitnumber % 32)) - 1) &
a81593 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ~mask->words[highbitword];
0c151e ¤   return kPGPError_NoErr;
5befe6 }
b567c5 ¤
69af5a
70c77d PGPError
5a82d4 pgpVirtMaskCopy (RingPool const *pool, PGPVirtMask const *imask,
84eca1 ¤   PGPVirtMask *omask)
7bbb36 {
be0040 ¤   PGPError err;
6951fc ¤   PGPUInt32 i;
61af5a
757ec7 ¤   err = pgpVirtMaskSizeUp (pool, omask, imask->nwords);
80de9b ¤   if (IsPGPError (err))
88c9db ¤   ¤   return err;
016124 ¤   for (i=0; i<imask->nwords; ++i)
b5e2d4 ¤   ¤   omask->words[i] = imask->words[i];
2af6c7 ¤   for ( ; i<omask->nwords; ++i)
382b61 ¤   ¤   omask->words[i] = 0;
24151e ¤   return kPGPError_NoErr;
eaefe6 }
56af5a
3f1e45 PGPInt32
1476c3 pgpVirtMaskLSBit (PGPVirtMask const *mask)
e7bb36 {
1751fc ¤   PGPUInt32 i;
c9af5a
be3a47 ¤   for (i=0; i<mask->nwords; ++i) {
32db13 ¤   ¤   if (mask->words[i])
17c808 ¤   ¤   ¤   return 32*i + ringLsBitFind (mask->words[i]);
279371 ¤   }
dbe69f ¤   return -1;
6aefe6 }
0eaf5a
857750 PGPBoolean
2ced1b pgpVirtMaskIsEmpty (PGPVirtMask const *mask)
5ebb36 {
7651fc ¤   PGPUInt32 i;
c7af5a
75c63b ¤   for (i=0; i<mask->nwords; ++i)
7fdb13 ¤   ¤   if (mask->words[i])
7898aa ¤   ¤   return FALSE;
dcc2e7 ¤   return TRUE;
faefe6 }
87af5a
057750 PGPBoolean
53c69e pgpVirtMaskIsEqual (PGPVirtMask const *mask1, PGPVirtMask const *mask2)
c1bb36 {
--8011 0005b429c71401001fd Page 7 of pgpRngPriv.c
1251fc ¤   PGPUInt32 i;
20af5a
bb37d8 ¤   /* First compare common length portion */
fe1499 ¤   for (i=0; i<pgpMin(mask1->nwords, mask2->nwords); ++i)
d6f049 ¤   ¤   if (mask1->words[i] != mask2->words[i])
5a5f1f ¤   ¤   ¤   return FALSE;
b902da ¤   /* The excess must be all zeros */
1410f9 ¤   if (mask1->nwords < mask2->nwords) {
14cdf8 ¤   ¤   for ( ; i < mask2->nwords; ++i)
3f2086 ¤   ¤   ¤   if (mask2->words[i])
94d64b ¤   ¤   ¤   ¤   return FALSE;
03f037 ¤   } else {
0a57d9 ¤   ¤   for ( ; i < mask1->nwords; ++i)
bd2e71 ¤   ¤   ¤   if (mask1->words[i])
dcd64b ¤   ¤   ¤   ¤   return FALSE;
909371 ¤   }
66c2e7 ¤   return TRUE;
7befe6 }
ffaf5a
bf7750 PGPBoolean
ce1ec2 pgpVirtMaskIsOverlapping (PGPVirtMask const *mask1, PGPVirtMask const *mask2)
b6bb36 {
2b51fc ¤   PGPUInt32 i;
69af5a
8d1499 ¤   for (i=0; i<pgpMin(mask1->nwords, mask2->nwords); ++i)
717f96 ¤   ¤   if (mask1->words[i] & mask2->words[i])
7432bd ¤   ¤   ¤   return TRUE;
17a230 ¤   return FALSE;
72efe6 }
f4af5a
4a12c1 #endif /* VIRTMASK */
65af5a
c2af5a
1a38e5 /*
674f24 ·* Small helpers to report errors
49495d ·*/
4aa18f /* Report an general I/O error */
04314a void
8e39d3 ringErr(RingFile *file, PGPUInt32 pos, PGPError code)
b1bb36 {
42f54a ¤   RingError *err = &file->set.pool->e;
e6af5a
081381 ¤   err->f = file;
d09d7d ¤   err->fpos = pos;
5816e3 ¤   err->error = code;
24d652 ¤   err->syserrno = errno;
aaefe6 }
fdaf5a
42227f /* Report a non-I/O error */
ec314a void
e57743 ringSimpleErr(RingPool *pool, PGPError code)
cabb36 {
00856f ¤   pool->e.f = (RingFile *)NULL;
dbc1b1 ¤   pool->e.fpos = (PGPUInt32)-1;
b5f5a1 ¤   pool->e.error = code;
aa1f56 ¤   pool->e.syserrno = errno;
efefe6 }
7baf5a
1f5fe3 /* Report an allocation failure (called from many places) */
ed314a void
730237 ringAllocErr(RingPool *pool)
d6bb36 {
60d416 ¤   ringSimpleErr(pool, kPGPError_OutOfMemory);
2defe6 }
d9af5a
0938e5 /*
53b9b6 ·* Hash a string of bytes. ·Uses the CRC-32 polynomial, preset
f61508 ·* to -1, non-invert. ·Used to reduce userID collisions and to
b131e8 ·* create a fake keyID for unparseable keys.
7a775e ·*
752077 ·* CRC-32 polynomial in little-endian order:
5b8996 ·* ··1+x+x^2+x^4+x^5+x^7+x^8+x^10+x^11+x^12+x^16+x^22+x^23+x^26+x^32
--5d02 000ff2dd8a7401001fd Page 8 of pgpRngPriv.c
4e312f ·* ··············1 ··1 ··2 ··2 ··2 ··3
81e3ba ·* ··0 ··4 ··8 ··2 ··6 ··0 ··4 ··8 ··2
de2e46 ·* = 111011011011100010000011001000001
d42a08 ·* = ···e ··d ··b ··8 ··8 ··3 ··2 ··0
fb645f ·* = 0xedb88320
cf495d ·*/
fcdbb5 #define CRCPOLY 0xedb88320
6bbccf PGPUInt32
d53217 ringHashBuf(PGPByte const *buf, size_t len)
cdbb36 {
6851db ¤   PGPUInt32 crc;
34927e ¤   int i, j;
a5b4a7 ¤   static PGPUInt32 crctable[256];
52af5a
58f099 ¤   if (!crctable[255]) {
5be263 ¤   ¤   /* crctable[0] is already 0 */
50b2da ¤   ¤   crctable[128] = crc = CRCPOLY;
c9b258 ¤   ¤   i = 64;
9f4392 ¤   ¤   do {
4d6edf ¤   ¤   ¤   crc = crc>>1 ^ (crc & 1 ? CRCPOLY : 0);
fa40d1 ¤   ¤   ¤   for (j = 0; j < 256; j += 2*i)
5771fb ¤   ¤   ¤   ¤   crctable[i+j] = crc ^ crctable[j];
6b14d3 ¤   ¤   } while (i >>= 1);
ba9371 ¤   }
2eaf5a
931f6b ¤   crc = 0xffffffff;
ffe87e ¤   while (len--)
a7806e ¤   ¤   crc = (crc >> 8) ^ crctable[(crc ^ *buf++) & 255];
2cba79 ¤   return crc;
bcefe6 }
91af5a
5738e5 /*
e85e7f ·* Return the index of the least significant bit in the given mask,
db0602 ·* or -1 if the mask is all 0. ·This uses (almost) no branches,
d0ed39 ·* so should be nice and fast on modern processors.
1d775e ·*
79bfbb ·* Oh, how does it *work*, you ask? ·I do confess that this uses
b472be ·* two evil bit-twiddling tricks. ·The first is one to get a mask
4e0302 ·* of the least-significant set bit in few instructions.
3559d8 ·* Consider a binary number x, be it 11010000 or 00101111.
795e49 ·* Then think about the form of x-1, 11001111 or 00101110.
801161 ·* Notice that the only difference is that some least-significant
f4e999 ·* bits have been complemented. ·The bits complemented are
2c14ed ·* those up to and including the least-significant set bit.
3909c8 ·* (x+1 does the same with *clear* bits). ·So ANDing the two
713400 ·* results in a number like the original, only without the
4c6efb ·* least-significant set bit. ·XORing them produces a mask
36295d ·* with a number of least-significant bits set, depending on
bd2861 ·* the least-significant set bit, ···00011111 or 00000001.
e1775e ·*
a57bc0 ·* Other tricks: x & (x-1) returns x, but with the least-significant
688ddb ·* bit cleared. ·Twos complement negation is -x = ~x+1 = ~(x-1),
03c83b ·* so x & -x = x & ~(x-1) returns only the least-significant bit
8e8896 ·* set in x.
04775e ·*
895357 ·* All we need is a routine to count the bits, and we're done.
e09240 ·* This is the *second* trick. ·Consider an 8-bit word:
9601cd ·* +-+-+-+-+-+-+-+-+
4afe6d ·* |a|b|c|d|e|f|g|h|
0901cd ·* +-+-+-+-+-+-+-+-+
5831ac ·* Now copy this word, shift one copy down one bit, and AND both
d83845 ·* copies with 0x55 (01010101), to produce even and odd bits:
beb123 ·* +-+-+-+-+-+-+-+-+ ·+-+-+-+-+-+-+-+-+
33ea1d ·* | |b| |d| |f| |h| ·| |a| |c| |e| |g| (the blank squares are zero)
feb123 ·* +-+-+-+-+-+-+-+-+ ·+-+-+-+-+-+-+-+-+
68a5b6 ·* Then add the words together:
1c01cd ·* +-+-+-+-+-+-+-+-+
dc9b34 ·* |a+b|c+d|e+f|g+h|
f101cd ·* +-+-+-+-+-+-+-+-+
0cbda4 ·* Note that each two-bit field contains a count of the number of
382149 ·* bits set in that part of the original word. ·Repeating this produces:
ffcca3 ·* +-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+
--f91b 000148896d0401001fd Page 9 of pgpRngPriv.c
6769ac ·* | ··|c+d| ··|g+h| + | ··|a+b| ··|e+f| = |a+b+c+d|e+f+g+h|
0ccca3 ·* +-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+
9f26df ·* and once more produces:
57cca3 ·* +-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+
09811c ·* | ······|e+f+g+h| + | ······|a+b+c+d| = |a+b+c+d+e+f+g+h|
cacca3 ·* +-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+ ··+-+-+-+-+-+-+-+-+
35775e ·*
a48cf4 ·* Ther masking is needed so that fields don't overflow into
9b3b5e ·* adjacent fields. ·Once the fields have gotten wide enough,
5b86be ·* some of it can be reduced or eliminated. ·In the last step,
99c776 ·* ab+c+d and e+f+g+h are both at most 4 (binary 100) and
ca8c40 ·* their sum is at most 8 (binary 1000), which still fits into a
cb6f54 ·* 4-bit field, so it is possible to not mask the inputs to
cb9e40 ·* the addition. ·It's still necessary to mask the output, though,
36aa86 ·* since the next step (adding up to a maximum of 16) won't
89fc9c ·* fit into a 4-bit field. ·Once you have an 8-bit field, though,
584724 ·* you can stop masking until the very end unless you have a
92088f ·* 256-bit word.
0d495d ·*/
4ea2d7 #define SIZEOFMASK¤ 32
444d2f int
ff3258 ringLsBitFind(PGPUInt32 mask)
63bb36 {
9e32ba ¤   if (!mask)
7b043c ¤   ¤   return -1;
094a81 ¤   mask ^= mask-1;¤/* Number of bits set is position of lsbit + 1 */
178e42 #if SIZEOFMASK > 32
c29c91 ¤   mask = (mask & 0x5555555555555555) + (mask >> 1 & 0x5555555555555555);
9d1959 ¤   mask = (mask & 0x3333333333333333) + (mask >> 2 & 0x3333333333333333);
e663be ¤   mask = (mask + (mask >> 4)) & 0x0F0F0F0F0F0F0F0F;
57eceb ¤   mask += mask >> 8;
045f0d ¤   mask += mask >> 16;
03051a ¤   mask += mask >> 32;
7d0719 ¤   return (int)(mask & 255)-1;
a609ee #elif SIZEOFMASK > 16
e5b953 ¤   mask = (mask & 0x55555555) + (mask >> 1 & 0x55555555);
9a714a ¤   mask = (mask & 0x33333333) + (mask >> 2 & 0x33333333);
38e2d4 ¤   mask = (mask + (mask >> 4)) & 0x0F0F0F0F;
44eceb ¤   mask += mask >> 8;
4e5f0d ¤   mask += mask >> 16;
c30719 ¤   return (int)(mask & 255)-1;
ae8a64 #elif SIZEOFMASK > 8
f0c61a ¤   mask = (mask & 0x5555) + (mask >> 1 & 0x5555);
de6db1 ¤   mask = (mask & 0x3333) + (mask >> 2 & 0x3333);
d05f7d ¤   mask = (mask + (mask >> 4)) & 0x0F0F;
e4eceb ¤   mask += mask >> 8;
840719 ¤   return (int)(mask & 255)-1;
48db21 #else
adeb10 ¤   mask = (mask & 0x55) + (mask >> 1 & 0x55);
5fc379 ¤   mask = (mask & 0x33) + (mask >> 2 & 0x33);
f2422f ¤   mask = (mask + (mask >> 4)) & 0x0F;
03fb31 ¤   return (int)(mask - 1);
1b7454 #endif
8befe6 }
ffaf5a
9f38e5 /*
ce4e2e ·* Return in *omask the mask of bits which are actually in use, excepting the
3e3aaa ·* given RingSet, if non-null. ·I.e. the mask which would be in use
27bcce ·* if that RingSet were discarded. ·RingFile structures are not
66fb18 ·* included on the sets list, so they are accounted for in the
b35d67 ·* pool->filemask.
a1495d ·*/
70c77d PGPError
9cc51e ringAllocMask(RingPool const *pool, RingSet const *set0,
87ad8f ¤   ¤   ¤   ··PGPVirtMask *omask)
2cbb36 {
71d777 ¤   RingSet const *set;
bc45d1 ¤   PGPVirtMask mask;
bcc55b ¤   PGPError err = kPGPError_NoErr;
61af5a
3440b4 ¤   if (IsPGPError(err = pgpVirtMaskCleanup (pool, omask)))
14c9db ¤   ¤   return err;
--d699 000726ff63a401001fd Page 10 of pgpRngPriv.c
d302bb ¤   if (IsPGPError(err = pgpVirtMaskInit (pool, &mask)))
dbc9db ¤   ¤   return err;
9297f9 ¤   if (IsPGPError(err = pgpVirtMaskCopy (pool, &pool->filemask, &mask)))
81c9db ¤   ¤   return err;
80af5a
0c37d7 ¤   for (set = pool->sets; set; set = set->next) {
c5ca70 ¤   ¤   if (IsPGPError( err =
90b29d ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &set->mask, &mask)))
76b32f ¤   ¤   ¤   return err;
759371 ¤   }
db0468 ¤   if (set0) {¤¤   /* set0 may or may not be on the sets list */
f2ca70 ¤   ¤   if (IsPGPError( err =
f4adcf ¤   ¤   ¤   ¤   pgpVirtMaskANDNOT (pool, &set0->mask, &mask)))
56b32f ¤   ¤   ¤   return err;
d39371 ¤   }
3333df ¤   *omask = mask;
ccac33 ¤   /* No cleanup on mask since it is copied to the output */
e75ea8 ¤   return err;
eeefe6 }
35af5a
832331 /* Helper function for ringGarbageCollect */
70c77d PGPError
dbfb19 ringClearMask(RingPool *pool, union RingObject **objp, PGPVirtMask *andmask,
3caa5e ¤   ¤   ¤   ··PGPVirtMask *andnotmask, PGPVirtMask *omask)
59bb36 {
69d743 ¤   union RingObject *robj;
835b7a ¤   PGPVirtMask objmask;
def22a ¤   PGPVirtMask remmask;
75e00f ¤   PGPVirtMask tmpmask;
c4c55b ¤   PGPError err = kPGPError_NoErr;
1baf5a
6ceced ¤   if (IsPGPError( err = pgpVirtMaskInit (pool, &objmask) ) )
cd97ed ¤   ¤   goto error;
3daa32 ¤   if (IsPGPError( err = pgpVirtMaskInit (pool, &remmask) ) )
2897ed ¤   ¤   goto error;
fc7b1b ¤   if (IsPGPError( err = pgpVirtMaskInit (pool, &tmpmask) ) )
e997ed ¤   ¤   goto error;
7d94f7 ¤   while ((robj = *objp) != (union RingObject *) 0) {
a37fbc ¤   ¤   if (IsntNull(andmask) &&
f61812 ¤   ¤   ¤   IsPGPError( err =
4ab951 ¤   ¤   ¤   ¤   pgpVirtMaskAND (pool, andmask, &robj->g.mask) ) )
53ed19 ¤   ¤   ¤   goto error;
25638c ¤   ¤   if (IsntNull(andnotmask) &&
e81812 ¤   ¤   ¤   IsPGPError( err =
e61faf ¤   ¤   ¤   ¤   pgpVirtMaskANDNOT (pool, andnotmask, &robj->g.mask) ) )
14ed19 ¤   ¤   ¤   goto error;
32ca70 ¤   ¤   if (IsPGPError( err =
8da3a3 ¤   ¤   ¤   ¤   pgpVirtMaskCopy (pool, &robj->g.mask, &objmask) ) )
d9ed19 ¤   ¤   ¤   goto error;
453912 ¤   ····if (!OBJISBOT(robj)) {
99da7e ¤   ¤   ¤   if (IsPGPError( err =·
824226 ¤   ¤   ¤   ¤   ringClearMask (pool, &robj->g.down, andmask,
a821f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···andnotmask, &tmpmask) ) )
7b1b7c ¤   ¤   ¤   ¤   goto error;
36fd78 ¤   ¤   ¤   if (IsPGPError( err =
1e030f ¤   ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &tmpmask, &remmask) ) )
6f1b7c ¤   ¤   ¤   ¤   goto error;
e30fe4 ¤   ¤   }
d42684 ¤   ····/* ·Skip dummy objects (robj->g.mask == 0), but delete
25d66a ¤   ········objects that are only in the memory ring. Also skip
f4c3cd ¤   ¤   ¤   keys which must be kept as dummy keys (because they've
ca0066 ¤   ¤   ¤   signed something). */
e8899e ¤   ¤   if (!pgpVirtMaskIsEmpty(&robj->g.mask)) {
09fd78 ¤   ¤   ¤   if (IsPGPError( err =
79831f ¤   ¤   ¤   ¤   ¤   pgpVirtMaskCopy(pool, &objmask, &tmpmask) ) )
e21b7c ¤   ¤   ¤   ¤   goto error;
29fd78 ¤   ¤   ¤   if (IsPGPError( err =
7a1ac2 ¤   ¤   ¤   ¤   ¤   pgpVirtMaskANDNOT(pool, &pool->memringmask, &tmpmask) ) )
b11b7c ¤   ¤   ¤   ¤   goto error;
d4ec19 ¤   ¤   ¤   if (pgpVirtMaskIsEmpty (&tmpmask)) {
40609b ¤   ¤   ¤   ¤   /* Therefore object is ONLY on MEMRING */
72daf5 ¤   ¤   ¤   ¤   if (!(OBJISTOPKEY(robj) && robj->k.sigsby != NULL)) {
--77f8 000bb4f481c401001fd Page 11 of pgpRngPriv.c
cd8a97 ¤   ¤   ¤   ¤   ¤   /* Also object hasn't made any sigs */
8ca3e7 ¤   ¤   ¤   ¤   ¤   /*
31ef82 ¤   ¤   ¤   ¤   ¤   ·* Delete no-longer-used object.
568ae1 ¤   ¤   ¤   ¤   ¤   ·* This does not free the memring data area, however
aebc2e ¤   ¤   ¤   ¤   ¤   ·* it will be reclaimed in ringGarbageCollect once no
b55cf4 ¤   ¤   ¤   ¤   ¤   ·* objects are using that area.
426ad4 ¤   ¤   ¤   ¤   ¤   ·*/
a549f6 ¤   ¤   ¤   ¤   ¤   pgpAssert(OBJISBOT(robj) || !robj->g.down);
c77fdd ¤   ¤   ¤   ¤   ¤   *objp = robj->g.next;
35027d ¤   ¤   ¤   ¤   ¤   ringFreeObject(pool, robj);
145914 ¤   ¤   ¤   ¤   ¤   continue;
da2613 ¤   ¤   ¤   ¤   }
4da3a6 ¤   ¤   ¤   }
da0fe4 ¤   ¤   }
a463b6 ¤   ¤   /* Skip to next object */
a82fa6 ¤   ¤   if( IsPGPError( err =·
606e3f ¤   ¤   ¤   ¤   pgpVirtMaskOR (pool, &objmask, &remmask) ) )
a8ed19 ¤   ¤   ¤   goto error;
46f29c ¤   ¤   objp = &robj->g.next;
d59371 ¤   }
86c44b ¤   pgpVirtMaskCleanup (pool, omask);
2b4625 ¤   *omask = remmask;
b560ff error:
63fceb ¤   pgpVirtMaskCleanup (pool, &tmpmask);
f0d87a ¤   pgpVirtMaskCleanup (pool, &objmask);
c05ea8 ¤   return err;
9fefe6 }
86af5a
4838e5 /*
3b7c3e ·* Reclaim all unused bits and delete any unreferenced memory objects.
e3f1a0 ·* Return TRUE if did some reclamation.
66495d ·*/
af7750 PGPBoolean
9842de ringGarbageCollect(RingPool *pool)
12bb36 {
4845d1 ¤   PGPVirtMask mask;
700040 ¤   PGPError err;
91af5a
93430b ¤   /* ·Build sig lists so we know which keys act as signers.
1729bc ¤   ····These should be left as dummy keys rather than freed. */
87d9d8 ¤   ringPoolListSigsBy (pool);
1118f9 ¤   if (IsPGPError( err = pgpVirtMaskInit (pool, &mask) ) )
fa98aa ¤   ¤   return FALSE;
c08c66 ¤   if (IsPGPError (err = ringAllocMask(pool, (RingSet const *)NULL, &mask)))
7e98aa ¤   ¤   return FALSE;
914a1d ¤   if (!pgpVirtMaskIsEqual (&mask, &pool->allocmask)) {
6f9bbc ¤   ¤   pgpVirtMaskCopy (pool, &mask, &pool->allocmask);
bde9e5 ¤   ¤   if (IsPGPError( err = ringClearMask(pool, &pool->keys, &mask,
9de9e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, &mask)))
915f1f ¤   ¤   ¤   return FALSE;
f69694 ¤   ¤   pgpVirtMaskAND(pool, &pool->memringmask, &mask);
f7e58d ¤   ¤   if (pgpVirtMaskIsEmpty(&mask)) {
265393 ¤   ¤   ¤   memPoolEmpty(&pool->files[MEMRINGBIT]->strings);
cbaaf9 ¤   ¤   ¤   memPoolEmpty(&pool->files[MEMRINGBIT]->fpos);
ff82fd ¤   ¤   ¤   pool->files[MEMRINGBIT]->freepos = NULL;
780892 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
55a538 ¤   ¤   ¤   return TRUE;¤   /* Something freed */
f00fe4 ¤   ¤   }
0b9371 ¤   }
e00db9 ¤   pgpVirtMaskCleanup (pool, &mask);
5f123d ¤   return FALSE;¤  /* Nothing freed */
c5efe6 }
02af5a
971713 /* Remove a single key from its hash chain */
dc2978 static void
a5195b ringGarbageHackKey(RingPool *pool, RingKey *key)
9cbb36 {
a4383f ¤   RingKey **keyp;
bd67c5 ¤
c41673 ¤   keyp = &pool->hashtable[key->keyID[0]];
bbaf5a
bbe84f ¤   while (*keyp != key) {
--9408 00033e26715401001fd Page 12 of pgpRngPriv.c
31436a ¤   ¤   pgpAssert(*keyp);
3b0b5f ¤   ¤   keyp = &(*keyp)->util;
629371 ¤   }
c1af5a
a13da8 ¤   *keyp = key->util;
04efe6 }
9caf5a
8d71b9 /* Remove a single signature from its sigsby list */
1a2978 static void
7cf41a ringGarbageHackSig(RingSig *sig)
d3bb36 {
e8d9e1 ¤   RingKey *key;
54ef66 ¤   RingSig **sigp;
8167c5 ¤
944019 ¤   key = &sig->by->k;
2b19ee ¤   pgpAssert(KEYISKEY(key));
09af5a
38d8af ¤   /*
0f1b4a ¤   ·* This could be one loop but for type rules, sigh...
ca2d05 ¤   ·* The problem doesn't happen often, fortunately.
57f92c ¤   ·* (The single loop can be expressed in C using the
813192 ¤   ·* cheat sigp = (RingSig **)&key->sigsby; but
5ae0a4 ¤   ·* while that's portable in practice, we eschew it
5548b2 ¤   ·* for the sake of ANSI C purity.)
68a4e3 ¤   ·*/
469e1c ¤   if (&key->sigsby->s == sig) {
e71ab0 ¤   ¤   key->sigsby = (union RingObject *)sig->nextby;
93f037 ¤   } else {
7b7978 ¤   ¤   sigp = &key->sigsby->s.nextby;
c0c0a6 ¤   ¤   while (*sigp != sig)
66c30e ¤   ¤   ¤   sigp = &(*sigp)->nextby;
1f8405 ¤   ¤   *sigp = sig->nextby;
869371 ¤   }
86efe6 }
9aaf5a
a438e5 /*
9b456b ·* Delete a single object from the global pool if it is an unreferenced
8ff6ef ·* memory object.
1f495d ·*/
cd314a void
b298ef ringGarbageCollectObject(RingPool *pool, union RingObject *robj)
c3bb36 {
f2f39b ¤   union RingObject **objp;
27af5a
db787a ¤   if (pgpVirtMaskIsEqual (&robj->g.mask, &pool->memringmask)) {
97c438 ¤   ¤   pgpAssert(!robj->g.down);
1c1c2e ¤   ¤   objp = OBJISTOP(robj) ? &pool->keys : &robj->g.up->g.down;
22223e ¤   ¤   while (*objp != robj) {
a61015 ¤   ¤   ¤   pgpAssert(*objp);
18d03d ¤   ¤   ¤   objp = &(*objp)->g.next;
e40fe4 ¤   ¤   }
1e9b48 ¤   ¤   *objp = robj->g.next;
c43378 ¤   ¤   if (OBJISKEY(robj))
67da38 ¤   ¤   ¤   ringGarbageHackKey(pool, &robj->k);
69ab62 ¤   ¤   else if (OBJISSIG(robj))
42c632 ¤   ¤   ¤   ringGarbageHackSig(&robj->s);
7e571e ¤   ¤   ringFreeObject(pool, robj);
0f9371 ¤   }
f6efe6 }
65af5a
a3827d /* Find and allocate a new, unused mask bit. ·Search through all bits
606c28 ·* until we find one unused.
65495d ·*/
65c77d PGPError
3a55db ringBitAlloc(RingPool *pool, PGPUInt32 *newbit)
eebb36 {
ae45d1 ¤   PGPVirtMask mask;
71af5a
eb8999 #if VIRTMASK
679b7a ¤   PGPUInt32 maskbit;
e10040 ¤   PGPError err;
33af5a
--0fed 000f7a67a9e401001fd Page 13 of pgpRngPriv.c
df7fcf ¤   maskbit = MEMRINGBIT + 1;
6b916d ¤   if( IsPGPError( err = pgpVirtMaskInit (pool, &mask) ) )
41c9db ¤   ¤   return err;
ee5870 ¤   for ( ; ; ) {
24baaa ¤   ¤   if( IsPGPError( err =
3f2fa9 ¤   ¤   ¤   ¤   pgpVirtMaskSetBit (pool, &mask, maskbit) ) )
dcb32f ¤   ¤   ¤   return err;
82a1eb ¤   ¤   if (!pgpVirtMaskIsOverlapping (&mask, &pool->allocmask)) {
0e0154 ¤   ¤   ¤   /* Occasionally reclaim unused bits */
48931d ¤   ¤   ¤   if (maskbit % 32 == 0) {
fe8f8f ¤   ¤   ¤   ¤   ringGarbageCollect(pool);
2fa3a6 ¤   ¤   ¤   }
fc4bbd ¤   ¤   ¤   *newbit = maskbit;
1ab85e ¤   ¤   ¤   err = pgpVirtMaskCleanup (pool, &mask);
82b32f ¤   ¤   ¤   return err;
260fe4 ¤   ¤   }
9c1562 ¤   ¤   pgpVirtMaskClearBit (pool, &mask, maskbit);
0706aa ¤   ¤   ++maskbit;
769371 ¤   }
20dcc4 ¤   /* NOTREACHED */
8edb21 #else
5d89eb ¤   /* Allocate a new bit */
5b14fb ¤   pgpVirtMaskInit (pool, &mask);
6dbc4a ¤   pgpVirtMaskCopy (pool, &pool->allocmask, &mask);
7f7349 ¤   pgpVirtMaskNOT (pool, &mask, 32);
33e060 ¤   if (pgpVirtMaskIsEmpty(&mask)) {
0f6ce9 ¤   ¤   /* Wups, out of bits - try something before dying */
2e5c12 ¤   ¤   ringGarbageCollect(pool);
84d379 ¤   ¤   pgpVirtMaskCopy (pool, &pool->allocmask, &mask);
844fa7 ¤   ¤   pgpVirtMaskNOT (pool, &mask, 32);
4ae58d ¤   ¤   if (pgpVirtMaskIsEmpty(&mask)) {
fa5613 ¤   ¤   ¤   ringSimpleErr(pool, kPGPError_OutOfRings);
c54b58 ¤   ¤   ¤   return kPGPError_OutOfRings;
8d0fe4 ¤   ¤   }
da9371 ¤   }
d2fdf8 ¤   *newbit = pgpVirtMaskLSBit(&mask);
f2151e ¤   return kPGPError_NoErr;
937454 #endif
dfefe6 }
0baf5a
d138e5 /*
3b6a03 ·* Allocate and deallocate useful structures.
01496f ·* Note the interesting shenanigans used to allocate
a41d62 ·* a structure the alignment of an enclosing union, ensuring
ef3f0c ·* that even on a maximally-perverse ANSI C implementation,
0a13f0 ·* it is safe to cast the returned structure pointer to a union
2d701c ·* pointer.
30495d ·*/
55614e union RingObject *
1c2946 ringNewObject(RingPool *pool, int objtype)
86bb36 {
b6d743 ¤   union RingObject *robj;
62792b ¤   /* How to initialize each object to empty */
496468 ¤   static RingKey const nullkey = NULLRINGKEY;
518f18 ¤   static RingSec const nullsec = NULLRINGSEC;
bab540 ¤   static RingName const nullname = NULLRINGNAME;
1545c8 ¤   static RingSig const nullsig = NULLRINGSIG;
aa15c5 ¤   static RingUnk const nullunk = NULLRINGUNK;
c5a94d ¤   static void const *nullobjs[RINGTYPE_MAX] = {
637379 ¤   ¤   &nullkey, &nullsec, &nullname, &nullsig, &nullunk
6662bd ¤   };
019570 ¤   size_t const sizes[RINGTYPE_MAX] = {
b14244 ¤   ¤   sizeof(RingKey), sizeof(RingSec),
092499 ¤   ¤   sizeof(RingName), sizeof(RingSig),
de9f47 ¤   ¤   sizeof(RingUnk)
2562bd ¤   };
a5af5a
c1effb ¤   /* Object types are 1-based */
1c5c16 ¤   pgpAssert(objtype > 0);
bf57a7 ¤   pgpAssert(objtype <= RINGTYPE_MAX);
deaf5a
f7ec7d ¤   robj = pool->freeobjs[objtype-1];
--abc9 0003e5ac692401001fd Page 14 of pgpRngPriv.c
de85c1 ¤   if (robj) {
199bcb ¤   ¤   pool->freeobjs[objtype-1] = robj->g.next;
e6f037 ¤   } else {
0adb11 ¤   ¤   robj = (union RingObject *)
177c7c ¤   ¤   ¤   memPoolAlloc(&pool->structs, sizes[objtype-1],
ee734e ¤   ¤   ¤   ¤   ·····alignof(union RingObject));
0d7e47 ¤   ¤   if (!robj) {
d6e8ed ¤   ¤   ¤   ringAllocErr(pool);
28cf03 ¤   ¤   ¤   return NULL;
da0fe4 ¤   ¤   }
eb9371 ¤   }
f3df2c ¤   memcpy(robj, nullobjs[objtype-1], sizes[objtype-1]);
e68b08 ¤   pgpAssert(ringObjectType(robj) == objtype);
8ba5f7 ¤   return robj;
65efe6 }
dfaf5a
5f38e5 /*
6cd40f ·* Free an object. ·This does not do any cleanup with any pointers in the
885e2c ·* object, except the regexp which belongs to sig objects.
35495d ·*/
b5314a void
1aabf4 ringFreeObject(RingPool *pool, union RingObject *obj)
9abb36 {
854a84 ¤   int type = ringObjectType(obj);
ddaf5a
c99158 ¤   pgpAssert(type > 0);
43e596 ¤   pgpAssert(type <= RINGTYPE_MAX);
35af5a
158dc7 ¤   if (OBJISSIG(obj)) {
e57a19 ¤   ¤   if (obj->s.regexp) {
91bd0d ¤   ¤   ¤   pgpContextMemFree( pool->context, obj->s.regexp );
14b078 ¤   ¤   ¤   obj->s.regexp = NULL;
580fe4 ¤   ¤   }
479371 ¤   }
5aaf5a
9ca03b ¤   pgpVirtMaskCleanup (pool, &obj->g.mask);
99af5a
7bf159 ¤   obj->g.next = pool->freeobjs[type-1];
72bf07 ¤   pool->freeobjs[type-1] = obj;
44efe6 }
abaf5a
3e38e5 /*
2a16eb ·* Remove an object from its parent and free it. ·This does not do
81a360 ·* anything with the object's FilePos list.
98495d ·*/
2b314a void
c2675c ringRemObject(RingPool *pool, union RingObject *obj)
60bb36 {
bff39b ¤   union RingObject **objp;
36af5a
5519ec ¤   pgpAssert(!OBJISTOP(obj));
6a67bc ¤   objp = &obj->g.up->g.down;
55af5a
f56cd0 ¤   /* Unlink the object from its parent */
833e7d ¤   while (*objp != obj) {
349941 ¤   ¤   pgpAssert(*objp);
eded55 ¤   ¤   objp = &(*objp)->g.next;
749371 ¤   }
e83a40 ¤   *objp = obj->g.next;
05be8a ¤   ringFreeObject(pool, obj);
cfefe6 }
6caf5a
5138e5 /*
94e209 ·* Rebuild the pool's hash table from scratch,
d9635b ·* inserting all keys and subkeys.
fb495d ·*/
9e314a void
7ecff9 ringPoolHash(RingPool *pool)
9dbb36 {
dab9df ¤   union RingObject *key, *subkey;
344ba4 ¤   int i;
3eaf5a
--71f5 000cabb18af401001fd Page 15 of pgpRngPriv.c
b8f151 ¤   for (i = 0; i < 256; i++)
6dd5ae ¤   ¤   pool->hashtable[i] = NULL;
eeaf5a
d85753 ¤   for (key = pool->keys; key; key = key->g.next) {
bfa3aa ¤   ¤   pgpAssert(OBJISKEY(key));
2575f9 ¤   ¤   RINGPOOLHASHKEY(pool, key);
e4668d ¤   ¤   for (subkey = key->g.down; subkey; subkey = subkey->g.next) {
a9ea43 ¤   ¤   ¤   if (OBJISKEY(subkey))
651a4f ¤   ¤   ¤   ¤   RINGPOOLHASHKEY(pool, subkey);
fe0fe4 ¤   ¤   }
a89371 ¤   }
50efe6 }
d4af5a
1238e5 /*
83a476 ·* Find a key given a keyID.
25775e ·*
0765f3 ·* ViaCrypt added pkalgs 2 and 3 which are limited RSA, but doesn't
43ae13 ·* completely distinguish beterrn them, so this doesn't either. ·Sigh.
55495d ·*/
14614e union RingObject *
b33352 ringPoolFindKey(RingPool const *pool, PGPByte pkalg, PGPByte const keyID[8])
0bbb36 {
01d9e1 ¤   RingKey *key;
2baf5a
d052e7 ¤   if ((pkalg | 1) == 3)
9c69b0 ¤   ¤   pkalg = 1;
cd70c1 ¤   for (key = pool->hashtable[keyID[0]]; key; key = key->util) {
d96627 ¤   ¤   if (memcmp(keyID, key->keyID, 8) == 0) {
2bbfe7 ¤   ¤   ¤   if (pkalg == key->pkalg)
32f622 ¤   ¤   ¤   ¤   break;
25f25f ¤   ¤   ¤   /* Cope with ViaCrypt's things */
372cb8 ¤   ¤   ¤   if (pkalg == 1 && (key->pkalg | 1) == 3)
1af622 ¤   ¤   ¤   ¤   break;
620fe4 ¤   ¤   }
389371 ¤   }
27af5a
cc6bdc ¤   return (union RingObject *)key;
eaefe6 }
bfaf5a
c4af5a
d338e5 /*
1038b0 ·* Ensure that each key's list of the signatures by it is
d3eef1 ·* valid. ·This also establishes the extra invariant (used in
8e3312 ·* pgpRngMnt.c) that all signatures by one key on another object
eb25ac ·* are adjacent on that key's sigsby list.
1d495d ·*/
28314a void
3a116f ringPoolListSigsBy(RingPool *pool)
4fbb36 {
ad11d4 ¤   union RingObject *key, *n, *s;
ccaf5a
fa1134 ¤   /* Initialize sigsby lists to null */
cc5753 ¤   for (key = pool->keys; key; key = key->g.next) {
01ce9d ¤   ¤   pgpAssert(OBJISTOPKEY(key));
48afcb ¤   ¤   key->k.sigsby = NULL;
c49371 ¤   }
55af5a
0d1d7d ¤   /* Install every sig on a sigsby list */
475753 ¤   for (key = pool->keys; key; key = key->g.next) {
9c4463 ¤   ····for (n = key->k.down; n; n = n->g.next) {
91a14d ¤   ········if (OBJISSIG(n)) {
c4f2b3 ¤   ¤   ····n->s.nextby = (RingSig *) n->s.by->k.sigsby;
960cd9 ¤   ¤   ····n->s.by->k.sigsby = n;
7f7209 ¤   ¤   } else for (s = n->g.down; s; s = s->g.next) {
24ce03 ¤   ¤   ····if (OBJISSIG(s)) {
ba3a60 ¤   ¤   ········s->s.nextby = (RingSig *) s->s.by->k.sigsby;
8d62c9 ¤   ¤   ¤   s->s.by->k.sigsby = s;
315f30 ¤   ¤   ····}
140fe4 ¤   ¤   }
fef372 ¤   ····}
019371 ¤   }
caefe6 }
--72ab 000cf1bcd4a401001fd Page 16 of pgpRngPriv.c
e0af5a
1aaf5a
9938e5 /*
28f481 ·* Return the mask of RingFiles that are "better" (higher priority
7ba11e ·* for fetching) than *any* home of the specified object.
ed495d ·*/
41c744 ¤   PGPError
fbeac1 ringObjBetters(union RingObject const *obj, RingPool const *pool,
98b703 ¤   ¤   ¤   ···PGPVirtMask *omask)
06bb36 {
a38ffd ¤   PGPVirtMask better;
0545d1 ¤   PGPVirtMask mask;
b06a1b ¤   PGPInt32 bit;
e3af5a
98c44b ¤   pgpVirtMaskCleanup (pool, omask);
41af5a
73be1b ¤   pgpVirtMaskInit (pool, &better);
7814fb ¤   pgpVirtMaskInit (pool, &mask);
5fa62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
11c530 ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
a7f04e ¤   pgpVirtMaskCopy (pool, &pool->filemask, &better);
30af5a
b633d5 ¤   pgpAssert(!pgpVirtMaskIsEmpty(&mask));
87af5a
cef953 ¤   while (!pgpVirtMaskIsEmpty(&mask)) {
6b514a ¤   ¤   bit = pgpVirtMaskLSBit(&mask);
47c92d ¤   ¤   pgpVirtMaskAND (pool, &pool->files[bit]->higherpri, &better);
72a958 ¤   ¤   pgpVirtMaskClearBit(pool, &mask, bit);
ea9371 ¤   }
8aaf5a
540db9 ¤   pgpVirtMaskCleanup (pool, &mask);
99035c ¤   *omask = better;
51151e ¤   return kPGPError_NoErr;
85efe6 }
0eaf5a
28af5a
7b38e5 /*
1c41e2 ·* Return TRUE if the specified subkey has a valid sig from the main key.
a32314 ·* Assumes subkey sigs are always tried, which should happen when they are
a51ef2 ·* created or added to the keyring. ·The only time this isn't true is when
f9ecab ·* we are considering adding a key. ·We will give the sig the benefit of
e34299 ·* the doubt in that case as we aren't using it yet.
77495d ·*/
c74d2f int
ea7856 ringSubkeyValid(RingSet const *set, union RingObject *subkey,
3ad1e5 ¤   PGPBoolean unExpired)
29bb36 {
ac558d ¤   union RingObject *sig;
e2b957 ¤   union RingObject *key;
5f2858 ¤   PGPUInt32¤  ¤   ··curtime;
890121 ¤   PGPUInt32¤  ¤   ··exptime;
a6af5a
d6202b ¤   pgpAssert(OBJISSUBKEY(subkey));
9b7cd0 ¤   pgpAssert(pgpIsRingSetMember(set, subkey));
64d9fa ¤   key = subkey->g.up;
05f3f5 ¤   pgpAssert(OBJISTOPKEY(key));
14af5a
98619a ¤   if (subkey->k.trust & PGP_KEYTRUSTF_REVOKED)
ed103e ¤   ····return 0;
030dc1 ¤   if (unExpired) {
c9638c ¤   ¤   /* Don't use key if has expired or creation time is > 24 hours
a86405 ¤   ¤   ¤   in future */
806041 ¤   ¤   if (subkey->k.trust & PGP_KEYTRUSTF_EXPIRED)
3e8144 ¤   ¤   ¤   return 0;
29d853 ¤   ¤   curtime = (PGPUInt32) PGPGetTime();
c6a22d ¤   ¤   exptime = (PGPUInt32) ringKeyExpiration(set, subkey);
f6606d ¤   ¤   if ((exptime != 0 ·&& ·curtime > exptime) ·||
396202 ¤   ¤   ¤   curtime < ringKeyCreation(set, subkey) - 24*60*60)
df8144 ¤   ¤   ¤   return 0;
149371 ¤   }
687db4 ¤   /* Check legality of subkey */
cfe754 ¤   for (sig = subkey->g.down; sig; sig = sig->g.next) {
--9b7a 000364b8e8b401001fd Page 17 of pgpRngPriv.c
d8d6e8 ¤   ¤   if (OBJISSIG(sig) &&
a5acf2 ¤   ¤   ¤   pgpIsRingSetMember(set, sig) &&
58f50d ¤   ¤   ····ringSigMaker(set, sig, set)==key &&
a70668 ¤   ¤   ····ringSigType(set, sig) == PGP_SIGTYPE_KEY_SUBKEY) {
05a22b ¤   ¤   ¤   if (!ringSigTried(set, sig))
8833d7 ¤   ¤   ¤   ¤   return 1; /* could check it here... */
695790 ¤   ¤   ¤   if (ringSigChecked(set, sig))
8b1c2d ¤   ¤   ¤   ¤   return 1;
010fe4 ¤   ¤   }
d69371 ¤   }
5e3e6b ¤   return 0;
41efe6 }
faaf5a
94314a void
1dec2b ringPurgeCachedName(RingPool const *pool, RingName *name, PGPVirtMask *mask)
45bb36 {
f0ca11 ¤   pgpAssert(NAMEISNAME(name));
38af5a
028023 ¤   if (NAMEISCACHED(name)) {
7d8ede ¤   ¤   PGPInt32 bit = NAMEFILEMASK(name);
4de7d6 ¤   ¤   PGPVirtMask tmask;
d071b6 ¤   ¤   pgpVirtMaskInit (pool, &tmask);
de7986 ¤   ¤   pgpVirtMaskSetBit (pool, &tmask, bit);
feaf5a
a617ae ¤   ¤   if (pgpVirtMaskIsOverlapping (&tmask, mask)) {
f16e5a ¤   ¤   ¤   /* Replace buffer with a hash of it */
a3897c ¤   ¤   ¤   name->name.hash = ringHashBuf((PGPByte const *)name->name.ptr,
6621c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··name->len);
47e27f ¤   ¤   ¤   NAMECLEARCACHED(name);
920fe4 ¤   ¤   }
65dba0 ¤   ¤   pgpVirtMaskCleanup (pool, &tmask);
ea9371 ¤   }
e3efe6 }
97af5a
a438e5 /*
31fade ·* This function is called by the MemPool code when it runs out of memory.
2e4f1a ·* We try to free up more memory by purging the uids from cache.
84dabf ·* Returns zero if it was unable to make more memory available;
f93591 ·* non-zero if it might be useful to retry an allocation.
e3495d ·*/
f3beb7 static int
695d55 ringPurgeUidCache(void *arg)
26bb36 {
f6460b ¤   RingPool *pool = (RingPool *)arg;
c82520 ¤   PGPVirtMask notmemringmask;
93f177 ¤   union RingObject *k, *n;
27743f ¤   unsigned i;
8eaf5a
ddd8af ¤   /*
99a7c8 ¤   ·* Quick check to see if we can do anything. ·As memory gets
ab35e7 ¤   ·* full, the full walk needed to clear the cache gets expensive,
75488a ¤   ·* so avoid it unless it does some good.
cda4e3 ¤   ·*/
6bf0f9 ¤   i = MEMRINGBIT+1;
4e2146 ¤   while (IsntNull(pool->files[i]) &&
27031b ¤   ¤   ···memPoolIsEmpty(&pool->files[i]->strings)) {
bfc2ee ¤   ¤   if (++i == pool->nfiles) /* Last resort: try garbage collect */
5a42ba ¤   ¤   ¤   return ringGarbageCollect(pool);
5c9371 ¤   }
aaaf5a
aad8af ¤   /*
611970 ¤   ·* Okay, we have something cached to free; replace all the
517416 ¤   ·* pointers to non-MEMRINGBIT cached named with hashes
ea8858 ¤   ·* of the names and then deallocate the names.
93a4e3 ¤   ·*/
68af5a
390a44 ¤   pgpVirtMaskInit (pool, &notmemringmask);
133988 ¤   pgpVirtMaskCopy (pool, &pool->memringmask, &notmemringmask);
b3eebb ¤   pgpVirtMaskNOT (pool, &notmemringmask, pool->nfiles);
c4af5a
825d14 ¤   for (k = pool->keys; k; k = k->g.next) {
36d237 ¤   ¤   pgpAssert(OBJISKEY(k));
--7c44 000e15796ee401001fd Page 18 of pgpRngPriv.c
47939d ¤   ¤   for (n = k->g.down; n; n = n->g.next) {
f48670 ¤   ¤   ¤   if (OBJISNAME(n))
8dc3b9 ¤   ¤   ¤   ¤   ringPurgeCachedName(pool, &n->n, &notmemringmask);
f10fe4 ¤   ¤   }
279371 ¤   }
c7af5a
784532 ¤   /* Free the pools */
d4674d ¤   for (i = 0; i < pool->nfiles; i++)
7a2676 ¤   ¤   if (IsntNull(pool->files[i]))
0d82f7 ¤   ¤   ¤   memPoolEmpty(&pool->files[i]->strings);
a8af5a
b3ced2 ¤   pgpVirtMaskCleanup (pool, &notmemringmask);
58af5a
8741bb ¤   return 1;¤  /* We freed some memory */
35efe6 }
95af5a
6895d7 /*·
b5e57b ·* Initialize a new RingFile structure. ·This does not set the mask field.
c5495d ·*/
5f2978 static void
9fcdc0 ringFileInit(
02763a ¤   RingPool *pool, RingFile *file)
bebb36 {
d0b29f ¤   pgpAssert( pgpContextIsValid( pool->context ) );
a167c5 ¤
6e6223 ¤   file->set.pool = pool;
4da554 ¤   file->set.next = NULL;
917f87 ¤   pgpVirtMaskInit (pool, &file->set.mask);
c88d42 ¤   file->set.type = RINGSET_FILE;
5faf5a
e59c2f ¤   file->f = NULL;
eeae51 ¤   file->destructor = NULL;
d8f705 ¤   file->arg = NULL;
e8ed4e ¤   memPoolInit( pool->context, &file->strings);
969127 ¤   memPoolInit( pool->context, &file->troublepool);
4798c3 ¤   memPoolSetPurge(&file->troublepool, ringPurgeUidCache, (void *)pool);
ef69b5 ¤   file->trouble = NULL;
fbb3ab ¤   file->troubletail = &file->trouble;
b58301 ¤   memPoolInit( pool->context, &file->fpos);
77c9b2 ¤   memPoolSetPurge(&file->fpos, ringPurgeUidCache, (void *)pool);
14473b ¤   file->freepos = NULL;
149152 ¤   pgpVirtMaskInit (pool, &file->higherpri);
26e1e2 ¤   file->flags = 0;
9cefe6 }
73af5a
6438e5 /*
664c24 ·* Initialize pool->files to hold entries so we can access newfile
3f495d ·*/
23314a void
77324a ringFilesInit(RingPool *pool, PGPUInt32 newfile)
0ebb36 {
1c1d94 ¤   void *vfiles;
bbff7f ¤   RingFile *file;
32af5a
cf7126 ¤   if (pool->nfiles < newfile+1) {
d52a82 ¤   ¤   vfiles = pool->files;
6ad190 ¤   ¤   pgpContextMemRealloc (pool->context, &vfiles,
c25eb8 ¤   ¤   ¤   ¤   ··(newfile+1) * sizeof(RingFile *), kPGPMemoryMgrFlags_Clear);
180c22 ¤   ¤   pool->files = (RingFile **) vfiles;
79c55c ¤   ¤   pool->nfiles = newfile+1;
e89371 ¤   }
094ceb ¤   /* Init newly allocated file struct */
d04ff6 ¤   pool->files[newfile] = (RingFile *)pgpContextMemAlloc (pool->context,
862fca ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(RingFile), kPGPMemoryMgrFlags_Clear);
c8fc09 ¤   file = pool->files[newfile];
ebb8b9 ¤   ringFileInit (pool, file);
9167c5 ¤
3453b4 ¤   pgpVirtMaskSetBit (pool, &file->set.mask, newfile);
1cefe6 }
69af5a
da38e5 /*
e1307c ·* Initialize a newly allocated RingPool.
--517d 0003eecd289401001fd Page 19 of pgpRngPriv.c
47495d ·*/
6f314a void
6298b6 ringPoolInit(
23520e ¤   PGPContextRef¤  context,
021d38 ¤   RingPool *¤ ¤   pool,
c381d0 ¤   PGPEnv const *¤ env)
1fbb36 {
2a4ba4 ¤   int i;
8daf5a
5e8679 ¤   pgpAssert( pgpContextIsValid( context ) );
8d67c5 ¤
42abd9 ¤   pool->context¤  = context;
8c67c5 ¤
869fb1 ¤   memPoolInit( context, &pool->structs);
a2faf0 ¤   memPoolSetPurge(&pool->structs, ringPurgeUidCache, (void *)pool);
b67dc2 ¤   pool->keys = NULL;
e4af5a
6861c8 ¤   for (i = 0; i < RINGTYPE_MAX; i++)
1f424e ¤   ¤   pool->freeobjs[i] = NULL;
3bbd14 ¤   pool->sets = NULL;
1e3a4e ¤   pool->freesets = NULL;
7bded2 ¤   pool->freeiter = NULL;
68af5a
4d3220 ¤   pool->pktbuf = NULL;
3fa855 ¤   pool->pktbuflen = 0;
03ba7e ¤   pool->pktbufalloc = 0;
f2af5a
549c15 ¤   /* Reserve first keyring for memory */
34c03d ¤   pgpVirtMaskInit (pool, &pool->memringmask);
6d330c ¤   pgpVirtMaskInit (pool, &pool->allocmask);
c98317 ¤   pgpVirtMaskInit (pool, &pool->filemask);
9f7233 ¤   pgpVirtMaskSetBit (pool, &pool->memringmask, MEMRINGBIT);
e73f5f ¤   pgpVirtMaskCopy (pool, &pool->memringmask, &pool->allocmask);
20b0db ¤   pgpVirtMaskCopy (pool, &pool->memringmask, &pool->filemask);
89af5a
b2fc85 ¤   pool->flags = 0;
52af5a
c1d404 ¤   if (env) {
f3c2bd ¤   ¤   i = pgpenvGetInt(env, PGPENV_CERTDEPTH, NULL, NULL);
9f7a96 ¤   ¤   pool->certdepth = i;
89af5a
3eb946 ¤   ¤   /* Values used for TRUSTMODEL 0 */
7a41c6 ¤   ¤   i = pgpenvGetInt(env, PGPENV_MARGINALS, NULL, NULL);
9cfa36 ¤   ¤   pool->num_marginals = (i < 0) ? 0 : (i > 255) ? 255 : i;
4ec91f ¤   ¤   i = pgpenvGetInt(env, PGPENV_COMPLETES, NULL, NULL);
e60015 ¤   ¤   pool->num_completes = (i < 0) ? 0 : (i > 255) ? 255 : i;
dbaf5a
42b202 ¤   ¤   /* Values used for TRUSTMODEL 1 */
7ef424 ¤   ¤   i = pgpenvGetInt(env, PGPENV_TRUSTED, NULL, NULL);
7de440 ¤   ¤   pool->threshold = (i > PGP_NEWTRUST_INFINITE) ?
2b226d ¤   ¤   ¤   PGP_NEWTRUST_INFINITE : (i < 0) ? 0 : i;
0aaf5a
6d41c6 ¤   ¤   i = pgpenvGetInt(env, PGPENV_MARGINALS, NULL, NULL);
092b85 ¤   ¤   i = (i < 1) ? 0 : (pool->threshold+i-1)/i;
a0b0c8 ¤   ¤   pool->marginalconfidence = i;
6667c5 ¤
e2c91f ¤   ¤   i = pgpenvGetInt(env, PGPENV_COMPLETES, NULL, NULL);
a62b85 ¤   ¤   i = (i < 1) ? 0 : (pool->threshold+i-1)/i;
133811 ¤   ¤   pool->completeconfidence = i;
f6f037 ¤   } else {
0b060a ¤   ¤   pool->certdepth = 4;
70caaf ¤   ¤   pool->num_marginals = 2;
d2e2ea ¤   ¤   pool->num_completes = 1;
e30204 ¤   ¤   pool->threshold = 3*PGP_TRUST_DECADE_INTERNAL;
88df4a ¤   ¤   pool->marginalconfidence = 3*PGP_TRUST_DECADE_INTERNAL/2;
c2311d ¤   ¤   pool->completeconfidence = 3*PGP_TRUST_DECADE_INTERNAL;
509371 ¤   }
d62095 #if PGPTRUSTMODEL==2
0319bb ¤   memPoolInit (context, &pool->pathpool);
02b085 ¤   pool->paths = NULL;
8169ec ¤   pool->pathlists = NULL;
3e7454 #endif
--10b0 00075b1ea41401001fd Page 20 of pgpRngPriv.c
2a67c5 ¤
142040 ¤   ringPoolClearError(pool);
54af5a
8af151 ¤   for (i = 0; i < 256; i++)
6bd5ae ¤   ¤   pool->hashtable[i] = NULL;
76af5a
18c7cd ¤   pool->nfiles = 0;
b5ed0d ¤   pool->files = NULL;
0983c3 ¤   ringFilesInit (pool, MEMRINGBIT);
f4af5a
31765c ¤   /* Also purge strings cache if needed to create a new object. */
e9ce3a ¤   memPoolSetPurge(&pool->files[MEMRINGBIT]->strings,
bb95d1 ¤   ················ringPurgeUidCache, (void *)pool);
cbefe6 }
44af5a
0438e5 /*
876ff4 ·* Deallocate everything in sight on a RingPool preparatory to
7b704f ·* deallocating it.
c0495d ·*/
7c314a void
18f59b ringPoolFini(RingPool *pool)
33bb36 {
96ff7f ¤   RingFile *file;
f6f257 ¤   int bit;
6c67c5 ¤
22d8af ¤   /*
1af811 ¤   ·* Do this first part, until the destructors are called,
4992c4 ¤   ·* "properly" so structures aren't dangling undefined.
36a4e3 ¤   ·*/
4e8f13 ¤   for (bit = 0; bit < (int)pool->nfiles; bit++)
4bd74f ¤   ¤   if (IsntNull(pool->files[bit]))
422172 ¤   ¤   ¤   ringFilePurgeTrouble(pool->files[bit]);
b6af5a
950871 ¤   for (bit = 0; bit < (int)pool->nfiles; bit++) {
4b96cf ¤   ¤   file = pool->files[bit];
46c36d ¤   ¤   if (file && file->destructor) {
e36452 ¤   ¤   ¤   file->destructor(file, file->f, file->arg);
8c286f ¤   ¤   ¤   file->destructor = NULL;
e20fe4 ¤   ¤   }
429371 ¤   }
d3af5a
4af9cc ¤   memPoolEmpty(&pool->structs);
602095 #if PGPTRUSTMODEL==2
7ecf63 ¤   memPoolEmpty (&pool->pathpool);
fa7454 #endif
2eaf5a
7d0871 ¤   for (bit = 0; bit < (int)pool->nfiles; bit++) {
1b96cf ¤   ¤   file = pool->files[bit];
2771f3 ¤   ¤   if (IsntNull(file)) {
dc3c9c ¤   ¤   ¤   memPoolEmpty(&file->strings);
1187d4 ¤   ¤   ¤   memPoolEmpty(&file->fpos);
61123e ¤   ¤   ¤   pgpVirtMaskCleanup(pool, &file->set.mask);
f80034 ¤   ¤   ¤   pgpContextMemFree (pool->context, file);
0aa5bd ¤   ¤   ¤   pool->files[bit] = NULL;
b50fe4 ¤   ¤   }
999371 ¤   }
96af5a
5e066f ¤   if (IsntNull (pool->files)) {
0e7eee ¤   ¤   pgpContextMemFree (pool->context, pool->files);
e51b68 ¤   ¤   pool->files = NULL;
370078 ¤   ¤   pool->nfiles = 0;
289371 ¤   }
87af5a
c66c27 ¤   if( IsntNull( pool->pktbuf ) )
313c20 ¤   ¤   pgpContextMemFree( pool->context, pool->pktbuf);
9aaf5a
b53257 ¤   pgpVirtMaskCleanup (pool, &pool->memringmask);
f1c277 ¤   pgpVirtMaskCleanup (pool, &pool->allocmask);
b34781 ¤   pgpVirtMaskCleanup (pool, &pool->filemask);
73af5a
19c787 ¤   /* Nuke the lot */
755723 ¤   pgpClearMemory( pool, ·sizeof(*pool));
--ec49 000738277c5401001fd Page 21 of pgpRngPriv.c
7aefe6 }
46af5a
2e38e5 /*
bbfd74 ·* This is defined as a macro.
13775e ·*
6f849a ·* void
13ae3a ·* ringFileMarkDirty(RingFile *file)
c885a8 ·* {
101f34 ·*¤ file->flags |= RINGFILEF_DIRTY;
a8d178 ·* }
8f495d ·*/
a6af5a
b738e5 /*
effd96 ·* Mark every file under a given mask as dirty.
db495d ·*/
35314a void
0239a8 ringPoolMarkDirty(RingPool *pool, PGPVirtMask *mask)
eebb36 {
b00537 ¤   PGPVirtMask tmask;
dbaf5a
23b4e3 ¤   pgpVirtMaskInit (pool, &tmask);
d1d4d7 ¤   pgpVirtMaskCopy (pool, mask, &tmask);
51cced ¤   pgpVirtMaskAND (pool, &pool->filemask, &tmask);
13af5a
e19793 ¤   while (!pgpVirtMaskIsEmpty (&tmask)) {
c3bfca ¤   ¤   PGPInt32 bit = pgpVirtMaskLSBit (&tmask);
ade8cb ¤   ¤   pgpAssert (bit >= 0);
08ac90 ¤   ¤   ringFileMarkDirty(pool->files[bit]);
586539 ¤   ¤   pgpVirtMaskClearBit (pool, &tmask, bit);
479371 ¤   }
05d5ec ¤   pgpVirtMaskCleanup (pool, &tmask);
e3efe6 }
ceaf5a
d9314a void
a878e9 ringPoolMarkTrustChanged(RingPool *pool, PGPVirtMask *mask)
3cbb36 {
240537 ¤   PGPVirtMask tmask;
5caf5a
20b4e3 ¤   pgpVirtMaskInit (pool, &tmask);
9ed4d7 ¤   pgpVirtMaskCopy (pool, mask, &tmask);
9dcced ¤   pgpVirtMaskAND (pool, &pool->filemask, &tmask);
8aaf5a
229793 ¤   while (!pgpVirtMaskIsEmpty (&tmask)) {
3fbfca ¤   ¤   PGPInt32 bit = pgpVirtMaskLSBit (&tmask);
a1e8cb ¤   ¤   pgpAssert (bit >= 0);
1f68a5 ¤   ¤   pool->files[bit]->flags |= RINGFILEF_TRUSTCHANGED;
d06539 ¤   ¤   pgpVirtMaskClearBit (pool, &tmask, bit);
bd9371 ¤   }
cbd5ec ¤   pgpVirtMaskCleanup (pool, &tmask);
07efe6 }
7eaf5a
66af5a
5038e5 /*
92762b ·* Do a fingerprint20 (SHA-1) hash on the specified buffer, which
f59ae0 ·* should be key data. ·We prefix it with the type and length bytes
089d38 ·* for compatibility with key signature hashes (once they become SHA
e27802 ·* based). ·Return the number of bytes in the hash, or negative on
7f2f13 ·* error.
47495d ·*/
6a4d2f int
426a86 pgpFingerprint20HashBuf(PGPContextRef context, PGPByte const *buf, size_t len,
5a1814 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *hash)
5abb36 {
2c602d ¤   PGPHashVTBL const *h;
f4e2ba ¤   PGPHashContext *hc;
d2f490 ¤   PGPByte tmpbuf[3];
c48b0f ¤   PGPByte const *p;
4fea04 ····PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( context );
27af5a
9aa993 ¤   h = pgpHashByNumber (kPGPHashAlgorithm_SHA);
2c0e8d ¤   if (!h)
73467c ¤   ¤   return kPGPError_BadHashNumber;
--c238 00026aede66401001fd Page 22 of pgpRngPriv.c
c0dfe0 ¤   hc = pgpHashCreate( memoryMgr, h);
7b8cee ¤   if (!hc)
614030 ¤   ¤   return kPGPError_OutOfMemory;
740790 ¤   /* We use this format even for subkeys */
572a81 ¤   tmpbuf[0] = PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1);
85c23b ¤   tmpbuf[1] = (PGPByte)(len>>8);
7588db ¤   tmpbuf[2] = (PGPByte)len;
64cd7a ¤   PGPContinueHash(hc, tmpbuf, 3);
13ec5a ¤   PGPContinueHash(hc, buf, len);
cf593d ¤   p = (PGPByte *) pgpHashFinal(hc);
16c08c ¤   memcpy(hash, p, h->hashsize);
b69727 ¤   PGPFreeHashContext(hc);
e236f0 ¤   return h->hashsize;
e2efe6 }
06af5a
51b369 /* Call this for sigs known to use a regexp, to return the regexp. ·Loads
d9ca0e ·* from disk if necessary. ·Returns NULL on error.
07495d ·*/
ea59fc ¤   void *
bb8bf8 ringSigRegexp( RingSet const *set, RingObject *sig )
abbb36 {
f7d259 ¤   PGPByte *buf;
67875f ¤   PGPSize len;
314b77 ¤   regexp *rexp;
a385a5 ¤   char const *packet;
7daf5a
73f8fe ¤   pgpAssert( OBJISSIG( sig ) );
5e5a19 ¤   pgpAssert( pgpIsRingSetMember(set, sig) );
6986af ¤   pgpAssert( SIGUSESREGEXP( &sig->s ) );
5faf5a
7650a5 ¤   if( !sig->s.regexp ) {
c65d53 ¤   ¤   /* Here we must load the regexp */
9faf5a
253b38 ¤   ¤   buf = (PGPByte *)ringFetchObject(set, sig, &len);
9fa490 ¤   ¤   if( !buf )
b5cf03 ¤   ¤   ¤   return NULL;
e60c7b ¤   ¤   /* Note that this may alter the contents of buf */
41c4c1 ¤   ¤   packet = (char *)ringSigFindSubpacket(buf, SIGSUB_REGEXP, 0, &len,
c69886 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, NULL, NULL);
afead5 ¤   ¤   pgpAssert( packet );
6699a5 ¤   ¤   if (IsPGPError( pgpRegComp( set->pool->context, packet, &rexp ) ) )
6ecf03 ¤   ¤   ¤   return NULL;
e982ef ¤   ¤   sig->s.regexp = (void *) rexp;
bb9371 ¤   }
a1ed36 ¤   return sig->s.regexp;
7aefe6 }
33af5a
3367c5 ¤
a738e5 /*
394d15 ·* Return true if sig is a valid revocation signature. ·It must either be
c2003c ·* a self sig, or it must be by a revocation key. ·May be on either a subkey
1375e4 ·* or main key. ·This does not check for expirations.
da495d ·*/
0416ea ¤   PGPBoolean
217c30 sigRevokesKey (RingSet const *set, RingObject *sig)
22bb36 {
386069 ¤   RingObject ¤¤   ¤   *parent;
969232 ¤   RingObject ¤¤   ¤   *top;
2baf5a
bfc154 ¤   pgpAssert (OBJISSIG (sig));
9476fe ¤   pgpAssert (pgpIsRingSetMember(set, sig));
1f67c5 ¤
15b687 ¤   parent = sig->g.up;
5e526e ¤   if (!OBJISKEY(parent))
6a98aa ¤   ¤   return FALSE;
a082c9 ¤   top = parent;
b9755f ¤   while (!OBJISTOPKEY(top))
8aaf12 ¤   ¤   top = top->g.up;
0eaf5a
2538ae ¤   if (sig->s.type != ( (top==parent) ? PGP_SIGTYPE_KEY_REVOKE
fcbfb9 ¤   ¤   ¤   ¤   ¤   ¤   ·¤  ¤   ¤   ···: PGP_SIGTYPE_KEY_SUBKEY_REVOKE ))
2698aa ¤   ¤   return FALSE;
--3602 001fe4831d5401001fd Page 23 of pgpRngPriv.c
e3aeb1 ¤   if ((sig->s.trust & PGP_SIGTRUSTF_TRIED) &&
fc19df ¤   ¤   !(sig->s.trust & PGP_SIGTRUSTF_CHECKED))
5598aa ¤   ¤   return FALSE;
b8d8af ¤   /*
ea1de1 ¤   ·* If untried, don't accept on a subkey. ·Accept on a top-level key
60973c ¤   ·* if already shown as revoked because we don't store trust packets
bcb0ec ¤   ·* on such keys, so as not to break PGP 2.X.
a6a4e3 ¤   ·*/
8df433 ¤   if (!(sig->s.trust & PGP_SIGTRUSTF_TRIED) &&
6feb2a ¤   ¤   ((top != parent) ||
eb57fb ¤   ¤   ·!(parent->k.trust & PGP_KEYTRUSTF_REVOKED)))
e198aa ¤   ¤   return FALSE;
f4af5a
8383f3 ¤   if (sig->s.by == top)
b9836c ¤   ¤   return TRUE;
0aaf5a
4dd8af ¤   /*
8ed514 ¤   ·* Here we have a revocation signature which is valid but is by some
b4deb9 ¤   ·* other key. ·We will accept it only if that is a key which is marked
1cf953 ¤   ·* as a revocation authorization key by this one.
bca4e3 ¤   ·*/
33af5a
232ffd ¤   return ringKeyIsRevocationKey (top, set, sig->s.by);
feefe6 }
--1e03 0005317152c401001fe Page 1 of pgpRngPriv.h
bc38e5 /*
b16ba7 ·* $Id: pgpRngPriv.h,v 1.30 1998/08/03 04:47:30 hal Exp $
c3495d ·*/
3eaf5a
0e530b #ifndef Included_pgpRngPriv_h
2d073f #define Included_pgpRngPriv_h
9faf5a
c564bd #include <stdio.h>¤ /* For size_t */
ad26e3 #include "pgpRngPub.h"
c0af5a
dc66e7 /* Private */
5daf5a
2595a9 #include "pgpMemPool.h"
dfaf5a
6899c6 PGP_BEGIN_C_DECLARATIONS
cbaf5a
b4e020 /* See pgpRngMnt.c for a definition of the various trust models */
b1af5a
ad1610 #ifndef PGPTRUSTMODEL
945c7e #define PGPTRUSTMODEL 2
557454 #endif
33af5a
2faf5a
1505e9 /* VIRTMASK enables virtual bitmask for unlimited number of sets */
efaf5a
1daf5a
6fb64d #ifndef VIRTMASK
498083 #define VIRTMASK 0
2b7454 #endif
09af5a
a8af5a
dfd25f #define MEMRINGBIT 0
deaf5a
6f8999 #if VIRTMASK
01af5a
882e30 typedef struct virtmask
d3bb36 {
d33fcf ¤   PGPUInt32¤  nwords;
cd4ce0 ¤   PGPUInt32¤  *words;
a73698 } PGPVirtMask;
13af5a
b29b19 #define VIRTMASKZERO {0,NULL}
4eaf5a
90ba58 #else /* VIRTMASK */
3faf5a
69af5a
6d38e5 /*
0b28a6 ·* This number should probably be increased for multiple keyrings and GUIs.
ed0ecd ·* At the moment, it is low to help memory consumption.
d8495d ·*/
d12007 #ifndef RINGMASKBITS
be5918 #define RINGMASKBITS 32
f67454 #endif
56af5a
2c1d81 #if RINGMASKBITS <= 8
3db336 typedef PGPByte ringmask;
83f72c #elif RINGMASKBITS <= 16
6771b6 typedef PGPUInt16 ringmask;
ad25f4 #elif RINGMASKBITS <= 32
fa7f9a typedef PGPUInt32 ringmask;
1edb21 #else
22e2eb #error Invalid RINGMASKBITS value
2f7454 #endif
6daf5a
24fa28 #define MEMRINGMASK ((ringmask)1<<MEMRINGBIT)
c3af5a
ecaf5a
4aa062 typedef ringmask PGPVirtMask;
ceaf5a
151104 #define VIRTMASKZERO (PGPVirtMask)0
98af5a
5312c1 #endif /* VIRTMASK */
--f12e 000c348e980401001fe Page 2 of pgpRngPriv.h
e0af5a
7ca77d /* PGP version information */
2c0ba0 #define PGPVERSION_2 2
c7d1c8 #define KNOWN_PGP_VERSION(x) ((x)==PGPVERSION_2 || (x) == PGPVERSION_3 || \
2694af ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(x)==PGPVERSION_4)
9faf5a
e1d873 /* Position in a file */
def402 typedef struct FilePos {
79e29a ¤   union {
f1c4b2 ¤   ¤   struct FilePos *next;
8bfc04 ¤   ¤   void *buf;
7e8cb1 ¤   } ptr;
6d3da0 ¤   PGPUInt32 fpos;
7432d5 } FilePos;
13af5a
2a0326 #define NULLFILEPOS { { (FilePos *)0 }, (PGPUInt32)0 }
e8af5a
4d95d7 /*·
7ddaa3 ·* Since C requires in-order allocation of structure fields, a poor choice of
164c3d ·* field order can cause lots of holes in a structure for alignment reasons.
90cfbc ·* E.g. long/char/long/char/long/char/long/char assuming the usual 4-byte
da6a65 ·* longs aligned on 4-byte boundaries requires 32 bytes of storage, while
58a62c ·* long/long/long/long/char/char/char/char requires only 20.
287995 ·* Storage required can be minimized by allocating the largest fields in
386a15 ·* the structure at the ends, against the aligned edges of the structure,
9953a8 ·* and filling the hole in the middle with progressively less aligned
de6f75 ·* fields. ·We use this by declaring the common (generic) fields in
e9923f ·* largest-to-smallest order, then the type-specific extensions in
37b764 ·* smallest-to-largest.
9a775e ·*
e92960 ·* The sizes listed are for the platform where memory consumption is the
073bc4 ·* greatest concern - the IBM PC. ·Other platforms aren't quite as tight.
fc495d ·*/
13af5a
7149ed struct RingGeneric·
90bb36 {
4fe3ae /* 0*/¤ union RingObject *next, *down, *up;
0b75c1 /*12*/¤ FilePos pos;
f0d5b9 /*20*/¤ PGPVirtMask mask;
16212b /*24*/¤ PGPByte flags;
5fcf90 /*25*/¤ PGPByte¤flags2;
f66cc8 /*26*/
1382f7 };
89af5a
bdb90f /* Generic flags (apply to more than one type) */
de1c0e #define RINGOBJF_TRUST 128
ce5eec #define RINGOBJF_TRUSTCHANGED 64
3738e5 /*
8ed630 ·* The type bits are encoded as follows:
ddd277 ·* 76543210
bb2234 ·* ··0000 - Unknown keyring object
9ca45f ·* ··0001 - Secret (We use the letter "c" for this)
343910 ·* ··0010 - Topkey
0f3e24 ·* ··0011 - Subkey (letter "B")
5ee50b ·* ··0100 - Signature (s)
7e90b5 ·* ··0101 - Name (n)
68d179 ·* Changes here need to be propagated to ringObjectType().
5e495d ·*/
d4973a #define RINGOBJF_TYPE¤  ¤   0x3c¤   /* Mask for object type */
557029 #define RINGOBJF_KEYTYPE¤   0x38¤   /* Mask ignoring diff among keys */
950146 #define RINGOBJ_SHIFT¤  ¤   2¤  ¤   /* Shift down for type */
2aaf5a
0e8de7 #define RINGOBJF_UNK¤   ¤   0x00¤   /* Unknown object type */
8a6649 #define RINGOBJF_SEC¤   ¤   0x04¤   /* Secret component object */
326182 #define RINGOBJF_KEY¤   ¤   0x08¤   /* Key (top) object */
847bb0 #define RINGOBJF_SUBKEY¤¤   0x0c¤   /* Subkey object */
5d330d #define RINGOBJF_SIG¤   ¤   0x10¤   /* Signature object */
3490fb #define RINGOBJF_NAME¤  ¤   0x14¤   /* Name object */
b1af5a
4c7809 #define OBJISNAME(obj) (((obj)->g.flags & RINGOBJF_TYPE) == RINGOBJF_NAME)
e6db2d #define OBJISSIG(obj) (((obj)->g.flags & RINGOBJF_TYPE) == RINGOBJF_SIG)
c3add4 /* Note that this includes top-level keys *and* subkeys */
--cf64 000247c661f401001fe Page 3 of pgpRngPriv.h
69757d #define OBJISKEY(obj) (((obj)->g.flags & RINGOBJF_KEYTYPE) == RINGOBJF_KEY)
a94460 #define OBJISTOPKEY(obj) (((obj)->g.flags & RINGOBJF_TYPE) == RINGOBJF_KEY)
a6af93 #define OBJISSUBKEY(obj) (((obj)->g.flags & RINGOBJF_TYPE) == RINGOBJF_SUBKEY)
a319d3 #define OBJISSEC(obj) (((obj)->g.flags & RINGOBJF_TYPE) == RINGOBJF_SEC)
5287c0 #define OBJISUNK(obj) (((obj)->g.flags & RINGOBJF_TYPE) == RINGOBJF_UNK)
eaaf5a
aed03e /* These versions are for pgpAssert() macro use */
333137 #define NAMEISNAME(name) (((name)->flags & RINGOBJF_TYPE) == RINGOBJF_NAME)
06fc0f #define SIGISSIG(sig) ··(((sig)->flags & RINGOBJF_TYPE) == RINGOBJF_SIG)
b40f07 #define KEYISKEY(key) ··(((key)->flags & RINGOBJF_KEYTYPE) == RINGOBJF_KEY)
18beaf #define KEYISTOPKEY(key) ··(((key)->flags & RINGOBJF_TYPE) == RINGOBJF_KEY)
5f9f74 #define KEYISSUBKEY(key) ··(((key)->flags & RINGOBJF_TYE) == RINGOBJF_SUBKEY)
06af5a
3ae2c6 #define OBJFLAGS_NAME¤  RINGOBJF_NAME
08112c #define OBJFLAGS_SIG¤   RINGOBJF_SIG
3426a6 #define OBJFLAGS_KEY¤   RINGOBJF_KEY
6158c2 #define OBJFLAGS_SUBKEY¤RINGOBJF_SUBKEY
a8cf4a #define OBJFLAGS_SEC¤   RINGOBJF_SEC
9348e9 #define OBJFLAGS_UNK¤   RINGOBJF_UNK
96af5a
e21b42 /* Does this object's up pointer point to a meaningful parent? */
669c6f #define OBJISTOP OBJISTOPKEY
fd5e2d /* Does this object's down pointer point to a meaningful child? */
0dafb1 #define OBJISBOT(obj) (OBJISSIG(obj)||OBJISSEC(obj))
99af5a
f63389 /* Maximum depth of nesting in a keyring */
b4c33a #define RINGMAXDEPTH 3
42af5a
443897 /* A subkey is the same, but the "sigsby" pointer is "up" */
4325e8 struct RingKey
febb36 {
2e3b13 ¤   union RingObject *next, *down, *sigsby;
2d7f46 ¤   FilePos pos;
c145d1 ¤   PGPVirtMask mask;
55c5d7 ¤   PGPByte flags;
863ec9 ¤   PGPByte flags2;
facaee /*26*/¤ PGPByte trust;
b69ff4 /*27*/¤ PGPByte pkalg;
4aadb9 /*28*/¤ PGPUInt16 validity;¤/* Validity period, in days */
2e7dec #if PGPTRUSTMODEL>0
d58520 /*30*/ ·PGPUInt16 confidence;¤  /* A trust value temporary */
397454 #endif
d2679b /*32*/¤ PGPUInt16 keybits;
0b6fe9 /*34*/¤ PGPByte signedTrust;¤   /* Trust from sigs on key */
f84241 /*35*/
09076a /*36*/¤ PGPUInt32 tstamp;
aa2ec0 /*40*/¤ PGPByte keyID[8];
5ea7cc /*48*/¤ struct RingKey *util;
b6f97e /*52*/¤ void *regexp;
f95c14 /*56*/
2482f7 };
471189 typedef struct RingKey RingKey;
99af5a
587dec #if PGPTRUSTMODEL>0
a53fad #define NULLRINGKEY { (union RingObject *)0, (union RingObject *)0,¤¤   \
a6a670 ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_KEY, 0,¤ \
19a3a2 ¤   0, 0, (PGPUInt16)0, (PGPUInt16)0, (PGPUInt16)0, 0, (PGPUInt32)0, ¤  \
76b10f ¤   { 0, 0, 0, 0, 0, 0, 0, 0 }, (RingKey *)0, 0¤}
7caf5a
f050f0 #define NULLRINGSUBKEY { (union RingObject *)0, (union RingObject *)0,¤ ¤   \
56c26b ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_SUBKEY, 0,¤  \
7e0607 ¤   0, 0, (PGPUInt16)0, (PGPUInt16)0, (PGPUInt16)0, 0, (PGPUInt32)0,¤   ¤   \
abb10f ¤   { 0, 0, 0, 0, 0, 0, 0, 0 }, (RingKey *)0, 0¤}
fddb21 #else
b43fad #define NULLRINGKEY { (union RingObject *)0, (union RingObject *)0,¤¤   \
fea670 ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_KEY, 0,¤ \
e324e3 ¤   0, 0, (PGPUInt16)0, (PGPUInt16)0, 0, (PGPUInt32)0,¤ ¤   ¤   ¤   ¤   \
fbb10f ¤   { 0, 0, 0, 0, 0, 0, 0, 0 }, (RingKey *)0, 0¤}
6faf5a
a850f0 #define NULLRINGSUBKEY { (union RingObject *)0, (union RingObject *)0,¤ ¤   \
93c26b ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_SUBKEY, 0,¤  \
2465ba ¤   0, 0, (PGPUInt16)0, (PGPUInt16)0, 0, (PGPUInt32)0,¤ ¤   ¤   ¤   ¤   ¤   \
--78a0 000a669bf2d401001fe Page 4 of pgpRngPriv.h
b8b10f ¤   { 0, 0, 0, 0, 0, 0, 0, 0 }, (RingKey *)0, 0¤}
d37454 #endif
f9af5a
ff5f65 /* The key has some sort of error */
d81088 #define KEYF_ERROR 1
74af5a
dfa5f6 /* The key is a trusted introducer, used in the maintenance pass. */
08c5a3 #define KEYF_TRUSTED 2
9daf5a
be8a60 /* Access the flags2 field */
c4af5a
4cea56 /* V2 or V3 key, something earlier than V4 */
f1154a #define KEYF2_V3¤   ¤   128
7aaf5a
dae752 #define KEYISV3(key) ((key)->flags2 & KEYF2_V3)
a2f1d7 #define KEYSETV3(key) ((key)->flags2 |= KEYF2_V3)
9e5cfb #define KEYCLEARV3(key) ((key)->flags2 &= ~KEYF2_V3)
43af5a
d5af5a
95af5a
8638e5 /*
a03e92 ·* This is used to record information about the locations for a key's
9af4b2 ·* secret components. ·If present, it is always the FIRST child of a
9ec8e4 ·* key. ·This is a very boring structure, as there's nothing we can
3d24ae ·* read in about the encrypted secret componenets without the passphrase.
a7d5f0 ·* (Option: have multiples of these for different encrypted forms of the
ec6adb ·* secret components?)
4a775e ·*
9b41eb ·* The FilePos entries on this are a subset of the entries in the
a79967 ·* parent RingKey's.
b8495d ·*/
c86b70 struct RingSec
85bb36 {
a2432b ¤   union RingObject *next, *down, *up;
1f7f46 ¤   FilePos pos;
9445d1 ¤   PGPVirtMask mask;
70c5d7 ¤   PGPByte flags;
d93ec9 ¤   PGPByte flags2;
856cc8 /*26*/
d4906b /*28*/¤ PGPUInt32 hash;¤/* Hash of secret fr matching purposes */
fa1560 /*32*/
1a82f7 };
33c87e typedef struct RingSec ·RingSec;
0daf5a
03597e #define NULLRINGSEC { (union RingObject *)0, (union RingObject *)0,¤\
e0dc29 ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_SEC, 0, 0 }
c8af5a
ee38e5 /*
5c93c3 ·* If SECF_VERSION_BUG is set, then patch the version byte from 3 to 2
33fca5 ·* when using the secret key. ·This is to fix a bug in 2.6 through early 2.9
bc075b ·* that, when editing a secret key, would write out the edited secret key
8c3676 ·* with a version byte of 3 even if it originally had a version byte
67077a ·* of 2. ·This has been fixed in 2.9, but it is common enough (due to 2.6)
944b42 ·* that we need to kludge around it.
fb495d ·*/
2b9203 #define SECF_VERSION_BUG 1
1baf5a
381325 #if PGPTRUSTMODEL==0
c390e8 struct RingName
b1bb36 {
3e432b ¤   union RingObject *next, *down, *up;
0d7f46 ¤   FilePos pos;
3545d1 ¤   PGPVirtMask mask;
d2c5d7 ¤   PGPByte flags;
5d3ec9 ¤   PGPByte flags2;
e7caee /*26*/¤ PGPByte trust;
627073 /*27*/
dff89f /*28*/¤ int trustval;
e2fc67 /*30*/¤ size_t len;
0a7e58 /*32*/¤ union {
3a3a1c ¤   ¤   char const *ptr;¤   /* If cached, pointer to string */
a60200 ¤   ¤   PGPUInt32 hash;¤¤   /* If not cached, hash code */
--a3e9 000a4c9946d401001fe Page 5 of pgpRngPriv.h
05af08 ¤   } name;
2c759a /*36*/¤ PGPUInt32 filemaskindex;¤   /* PGPFile for cached name */
811cca /*40*/
3482f7 };
84f55b typedef struct RingName¤RingName;
faaf5a
e4df9e #define NULLRINGNAME { (union RingObject *)0, (union RingObject *)0,¤   \
16353a ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_NAME, 0,¤\
6e4fbd ¤   0, 0, (size_t)0, { (char const *)0 }}
63af5a
c9341f #else /* New trust */
e190e8 struct RingName
9dbb36 {
aa432b ¤   union RingObject *next, *down, *up;
417f46 ¤   FilePos pos;
2a45d1 ¤   PGPVirtMask mask;
36c5d7 ¤   PGPByte flags;
533ec9 ¤   PGPByte flags2;
13caee /*26*/¤ PGPByte trust;
6f5123 /*27*/¤ PGPByte validity;¤  ¤   /* Stored validity */
4e3a4b /*28*/¤ PGPByte confidence;¤/* Stored confidence */
6dde31 /*29*/
e7224e /*30*/¤ PGPUInt16 valid;¤   ¤   /* Computed validity */
70dc79 /*32*/¤ size_t len;
ff68ec /*36*/¤ union {
523a1c ¤   ¤   char const *ptr;¤   /* If cached, pointer to string */
1d0200 ¤   ¤   PGPUInt32 hash;¤¤   /* If not cached, hash code */
8eaf08 ¤   } name;
0df16d /*40*/¤ PGPUInt32 filemaskindex;¤   /* PGPFile for cached name */
8f6e26 /*44*/
b182f7 };
ddf55b typedef struct RingName¤RingName;
e7af5a
3b38e5 /*
9c81bf ·* The intermediate validity results are 16 bits wide instead of 8.
0a21e3 ·* This is used for extra precision (fraction bits) and extra range.
deb1c7 ·* This is the number of extra precision bits. ·(4 more range bits
cfd4d6 ·* increases the upper bound to 10^-25.)
2a495d ·*/
6cbff3 #define TRUST_CERTSHIFT 6
bdaf5a
30df9e #define NULLRINGNAME { (union RingObject *)0, (union RingObject *)0,¤   \
c8fb13 ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_NAME,¤   0,¤ \
d10a80 ¤   0, 0, 0, 0, (size_t)0, { (char const *)0 }, 0}
bb7454 #endif
7baf5a
6a8a60 /* Access the flags2 field */
ca829e #define NAMEF2_ISCACHED¤128
f17589 #define NAMEF2_NEWTRUST 64
2dc303 #define NAMEF2_ATTR¤¤   32
c06a15 #define NAMEF2_LEVELMASK 31
36af5a
4ca933 #define NAMEISCACHED(name) ((name)->flags2 & NAMEF2_ISCACHED)
c0fa9c #define NAMESETCACHED(name) ((name)->flags2 |= NAMEF2_ISCACHED)
edb8cf #define NAMECLEARCACHED(name) ((name)->flags2 &= ~NAMEF2_ISCACHED)
92af5a
9adeb5 /* Has new-style trust info */
352aa8 #define NAMEHASNEWTRUST(name) ((name)->flags2 & NAMEF2_NEWTRUST)
e846c5 #define NAMESETNEWTRUST(name) ((name)->flags2 |= NAMEF2_NEWTRUST)
59dd29 #define NAMECLEARNEWTRUST(name) ((name)->flags2 &= ~NAMEF2_NEWTRUST)
43af5a
d636fc /* Is general attribute */
7b34b4 #define NAMEISATTR(name) ((name)->flags2 & NAMEF2_ATTR)
ffa0ef #define NAMESETATTR(name) ((name)->flags2 |= NAMEF2_ATTR)
3c39ce #define NAMECLEARATTR(name) ((name)->flags2 &= ~NAMEF2_ATTR)
66af5a
59a448 /* Certification depth */
fe04bf #define NAMELEVEL(name) ((name)->flags2 & NAMEF2_LEVELMASK)
6500b8 #define NAMESETLEVEL(name,lv) \
d568ce ¤   ((name)->flags2 = ((name)->flags2 & ~NAMEF2_LEVELMASK) + lv)
e6af5a
a4db49 #define NAMEF_FILEMASK 0xffffffff
--184a 0005d3a7fdc401001fe Page 6 of pgpRngPriv.h
e0af5a
ade4ca /* File mask value tells where name is cached from */
1bd3de #define NAMEFILEMASK(name) ((name)->filemaskindex & NAMEF_FILEMASK)
024f27 #define NAMESETFILEMASK(name,val) ((name)->filemaskindex = \
1e9bcc ¤   ((name)->filemaskindex &~NAMEF_FILEMASK) | ((val)&NAMEF_FILEMASK))
63af5a
caa9b3 struct RingSig
5dbb36 {
29c47e ¤   union RingObject *next, *by, *up;
497f46 ¤   FilePos pos;
d845d1 ¤   PGPVirtMask mask;
94c5d7 ¤   PGPByte flags;
de3ec9 ¤   PGPByte flags2;
4ca7e0 ¤   /* Prefix */
a5caee /*26*/¤ PGPByte trust;
428e1c /*27*/¤ PGPByte type;
50d995 /*28*/¤ PGPByte hashalg;
a251e4 /*29*/¤ PGPByte version;
179951 /*30*/¤ PGPUInt16 validity;
5f306c /*32*/¤ PGPUInt32 tstamp;
1f27cd /*36*/¤ struct RingSig *nextby;
b808ab /*40*/¤ void *regexp;
896701 /*41*/¤ PGPByte trustLevel;¤/* 0 for regular sig, 1 for trust, 2 for meta */
f6313b /*42*/¤ PGPByte¤trustValue;¤/* new "extern" format, valid if trustLevel>0 */
963907 /*43*/
9282f7 };
867a9e typedef struct RingSig¤ RingSig;
a4af5a
3db94d #define NULLRINGSIG { (union RingObject *)0, (union RingObject *)0,¤¤   \
95966b ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_SIG, 0,¤ \
42b106 ¤   0, 0, 0, 0, (PGPUInt16)0, (PGPUInt32)0, (RingSig *)0, 0, 0, 0 }
08af5a
a4f591 /* Signature has some sort of parsing error */
5e5032 #define SIGF_ERROR 1
bf93ab /* Extra bytes are non-obvious */
a1bf09 #define SIGF_NONFIVE¤   2
37af5a
918a60 /* Access the flags2 field */
5d017e #define SIGF2_EXPORTABLE¤   128¤¤   /* Sig can be exported to others */
b4b5e6 #define SIGF2_USESREGEXP¤   ·64¤¤   /* (Trust) sig qualified with regexp */
b4fd76 #define SIGF2_REVOCABLE¤¤   ·32¤¤   /* Sig can be revoked */
38ef30 #define SIGF2_X509¤ ¤   ¤   ·16¤¤   /* Sig is an imported X.509 cert */
aeaf5a
fa09c6 #define SIGSETEXPORTABLE(sig)¤  ¤   (sig)->flags2 |= SIGF2_EXPORTABLE
c34ff4 #define SIGSETNONEXPORTABLE(sig)¤   (sig)->flags2 &= ~SIGF2_EXPORTABLE
c26c41 #define SIGISEXPORTABLE(sig)¤   ¤   (((sig)->flags2 & SIGF2_EXPORTABLE)!=0)
e87827 #define SIGSETUSESREGEXP(sig)¤  ¤   (sig)->flags2 |= SIGF2_USESREGEXP
a82159 #define SIGCLEARUSESREGEXP(sig)¤¤   (sig)->flags2 &= ~SIGF2_USESREGEXP
887179 #define SIGUSESREGEXP(sig)¤ ¤   ¤   (((sig)->flags2 & SIGF2_USESREGEXP)!=0)
475ab0 #define SIGSETREVOCABLE(sig)¤   ¤   (sig)->flags2 |= SIGF2_REVOCABLE
37057c #define SIGSETNONREVOCABLE(sig)¤¤   (sig)->flags2 &= ~SIGF2_REVOCABLE
f11846 #define SIGISREVOCABLE(sig)¤¤   ¤   (((sig)->flags2 & SIGF2_REVOCABLE)!=0)
f309b7 #define SIGSETX509(sig)¤¤   ¤   ¤   (sig)->flags2 |= SIGF2_X509
011814 #define SIGCLEARX509(sig)¤  ¤   ¤   (sig)->flags2 &= ~SIGF2_X509
0dea89 #define SIGISX509(sig)¤ ¤   ¤   ¤   (((sig)->flags2 & SIGF2_X509)!=0)
93af5a
8eaf5a
3338e5 /*
2adcad ·* An unknown packet in a keyring. ·"pktbyte" is the type.
a47d92 ·* This is so we can at least propagate the thing, even if it's
faf6f2 ·* incomprehensible.
1a495d ·*/
73c78c struct RingUnk
29bb36 {
a4432b ¤   union RingObject *next, *down, *up;
bb7f46 ¤   FilePos pos;
ba45d1 ¤   PGPVirtMask mask;
09c5d7 ¤   PGPByte flags;
1b3ec9 ¤   PGPByte flags2;
72a7e0 ¤   /* Prefix */
5ccaee /*26*/¤ PGPByte trust;
5dc8b2 /*27*/¤ PGPByte pktbyte;
--5097 00043c67795401001fe Page 7 of pgpRngPriv.h
bc1066 /*28*/¤ PGPUInt32 hash;
8c1560 /*32*/
fb82f7 };
02097a typedef struct RingUnk RingUnk;
c3af5a
699768 #define NULLRINGUNK { (union RingObject *)0, (union RingObject *)0,¤¤   \
70e7c6 ¤   (union RingObject *)0, NULLFILEPOS, VIRTMASKZERO, OBJFLAGS_UNK, 0,¤ \
c3881f ¤   0, 0, (PGPUInt32)0 }
c5af5a
0938e5 /*
abdf1f ·* A generic RingObject. ·"obj->x.foo" occurs so often that the brevity
871c7a ·* of the one-letter tags has advantages in clarity that override any
719331 ·* documentation gains from greater verbosity.
e5495d ·*/
e6ab61 union RingObject {
a7ff1d ¤   struct RingGeneric g;
e07355 ¤   RingKey k;
a98ffa ¤   RingSec c;¤ /* Note this odd choice of letter */
f024fa ¤   RingName n;
bdbf2b ¤   RingSig s;
e25ade ¤   RingUnk u;
7982f7 };
25af5a
c838e5 /*
b01248 ·* The basic collection-of-keys type.
93af4c ·* This comes in two flavours: mutable and immutable.
810952 ·* A mutable set can have members added and removed,
532a13 ·* while an immutable one cannot.
79495d ·*/
45af5a
51d434 struct RingPool;
3672e6 struct RingSet {
ac72ce ¤   RingSet *next;
588642 ¤   RingPool *pool;
8b0d20 ¤   RingError err;
8c45d1 ¤   PGPVirtMask mask;
fd928c ¤   char type;
e082f7 };
d4af5a
be1cd0 #define RINGSET_MUTABLE 0
74fcc5 #define RINGSET_IMMUTABLE 1
0d40df #define RINGSET_ITERATOR 2¤ /* Also immutable */
c43ce4 #define RINGSET_FILE 3¤ /* Also immutable */
6a023e #define RINGSET_FREE 4¤ /* Free flag */
03af5a
eef9bc #define RINGSETISMUTABLE(set) (!(set)->type)
44af5a
1f53cf struct RingTrouble;
6faf5a
671f67 /* A file that holds information about a file */
ca8c57 struct RingFile {
55bae5 ¤   RingSet set;
ceb208 ¤   PGPFile *f;¤/* File handle */
5566e5 ¤   void (*destructor)(RingFile *, PGPFile *, void *);
7e0e96 ¤   void *arg;
597d6f ¤   MemPool strings;¤   /* Cache of name strings */
1a3c87 ¤   MemPool troublepool;
9abf6b ¤   struct RingTrouble const *trouble, **troubletail;
3b4494 ¤   MemPool fpos;
bff114 ¤   FilePos *freepos;
ca625c ¤   PGPVirtMask higherpri;¤ /* see ringFetchPacket in pgpRngRead.c */
efc5d7 ¤   PGPByte flags;
3d865d ········PgpVersion version; ····
de82f7 };
20af5a
4e6434 #if PGPTRUSTMODEL>1
aaaf5a
162e0c /* This is a path or a path segment. ·next->src may be unequal to dest. */
d29b16 typedef struct Path {
f8bda2 ¤   struct Path ········*next;
320510 ¤   RingObject ·········*src,
432ae5 ¤   ····················*dest;
--e040 000b50dd466401001fe Page 8 of pgpRngPriv.h
abd1c9 ¤   double ··············confidence;
b1e12d ¤   DEBUG_STRUCT_CONSTRUCTOR( Path )
e681ed } Path, *pPath;
e5af5a
889e58 /* This is a list of paths. ·Some segments may be on multiple paths. */
f4a32e typedef struct PathList {
b65337 ¤   struct PathList ····*next;
527224 ¤   Path ···············*path;
c2869b ¤   Path ··············**ptail;
b6d1c9 ¤   double ··············confidence;
01741b ¤   DEBUG_STRUCT_CONSTRUCTOR( PathList )
8738f1 } PathList, *pPathList;
777454 #endif
daaf5a
2e6006 /* Flags kept updated about a file */
46f785 #define RINGFILEF_DIRTY¤1
600acb #define RINGFILEF_TRUSTCHANGED¤ 2
3aaf5a
e11980 /* The home of a lot of keys */
5b9d06 struct RingPool {
f18a97 ¤   PGPContextRef¤  context;
9967c5 ¤
759a99 ¤   MemPool structs;
08e617 ¤   union RingObject *keys;
3cbcc0 ¤   union RingObject *freeobjs[RINGTYPE_MAX];
735743 ¤   RingSet *sets;¤ /* Dynamically allocated sets (not files!) */
bd469e ¤   RingSet *freesets;
e7fde3 ¤   RingIterator *freeiter;
ea8a2d ¤   char *pktbuf;
2f7d70 ¤   size_t pktbuflen;
2286eb ¤   size_t pktbufalloc;
ed5606 ¤   PGPVirtMask allocmask;¤ /* Bits in use (cache) */
bbbf3a ¤   PGPVirtMask filemask;¤  /* Bits in use for files */
e45bbe ¤   PGPVirtMask memringmask;¤   /* Const, has MEMRING bit set */
4bc612 ¤   PGPUInt32 flags;
b5af5a
c8ee3d ¤   PGPEnv const *env;
079bf1 ¤   int certdepth;
0b5c63 ¤   /* TRUSTMODEL 0 values */
574795 ¤   int num_marginals;
219788 ¤   int num_completes;
dfd936 ¤   /* TRUSTMODEL 1 values */
aee702 ¤   /* Translations from old to new trust models */
66fefa ¤   PGPByte marginalconfidence;
81f9d7 ¤   PGPByte completeconfidence;
6c7f6f ¤   int threshold;
dd2095 #if PGPTRUSTMODEL==2
021bcd ····MemPool pathpool;
9d80e4 ····Path *paths;
24a37e ¤   PathList *pathlists;
157454 #endif
268b39 ¤   MemPool regexps;
f1af5a
9d3d82 ¤   /* In case of error, the following is set */
faed60 ¤   RingError e;
09af5a
c9db7e ¤   /* Some large items go at the end... */
8d0ac5 ¤   RingKey *hashtable[256];
5bd9a5 ¤   PGPUInt32 nfiles;
72e432 ¤   RingFile **files;
bd82f7 };
c9af5a
8e9f7c /* Values for erraction */
e44e90 #define ACTERR_NONE¤0
a60c52 #define ACTERR_READ¤1
0d14d3 #define ACTERR_WRITE¤   2
1c3fde #define ACTERR_SEEK¤3
f84096 #define ACTERR_OPEN ····4
7fba26 #define ACTERR_CLOSE ···5
2aae61 #define ACTERR_FLUSH ···6
dd618f #define ACTERR_HUGE¤7
b5af5a
--e13d 0001b747e51401001fe Page 9 of pgpRngPriv.h
51cf36 #define ACTERR_EOF¤ ¤   101
0bd701 #define ACTERR_BADPKTBYTE¤  102
3da9c7 #define ACTERR_WRONGPKTBYTE¤103
cc96f8 #define ACTERR_WRONGLEN¤¤   104
80af5a
4be90c #define ACTERR_ALLOC¤   201
b1af5a
52c8ca /* Test for membership of a RingObj in a RingSet */
63d22b #define pgpIsRingSetMember(s,o)¤\
afd4a6 ¤   pgpVirtMaskIsOverlapping(&(s)->mask, &(o)->g.mask)
49af5a
5438e5 /*
0658d5 ·* How to distinguish starting from stopping?
cd2b5a ·* It's NULL pointers either way.
54e5f5 ·* Ah, wait! ·"level" is the most recent level.
0cea6e ·* If it's 0, start the ring. ·If it's 1, and the stack is NULL,
74012a ·* we're at the end. ·Yes, that works!
50775e ·*
2f09d4 ·* Okay, so it works like this:
cf9a71 ·* The stack[i] array holds the object which is the head of the
a54d8b ·* current list, the last object returned at level i+1.
4229a2 ·* The last object returned, which defines the maximum depth to
e75e1b ·* which the stack is valid, is at "level". ·Stack entries
5939d7 ·* up to level-1 are valid.
fe3e1a ·* If a stack entry is NULL, is is the last entry at level-1,
1221ef ·* and indicates that the list at this level is finished.
b41740 ·* Repeated calls will keep returning NULL.
78775e ·*
d58b6f ·* If asked for a level one greater than the stored level, that's
a0ae93 ·* a clue to start at the beginning of the list.
ee9ec0 ·*·
79a9fc ·* stack[-1], corresponding to a level of 0, is implicitly the
4b9ec3 ·* RingPool.
16495d ·*/
7cdc36 struct RingIterator {
14bae5 ¤   RingSet set;
61c079 ¤   unsigned level;¤/* 1-based */
88b3a7 ¤   union RingObject *stack[RINGMAXDEPTH];
b782f7 };
7aaf5a
7eaf5a
9095a7 PGPError pgpVirtMaskInit (RingPool const *pool, PGPVirtMask *mask);
c76b08 PGPError pgpVirtMaskCleanup (RingPool const *pool, PGPVirtMask *mask);
af5b56 PGPError pgpVirtMaskOR (RingPool const *pool, PGPVirtMask const *imask,
c7b44f ¤   PGPVirtMask *omask);
d495fe PGPError pgpVirtMaskAND (RingPool const *pool, PGPVirtMask const *imask,
38b44f ¤   PGPVirtMask *omask);
6cd1df PGPError pgpVirtMaskANDNOT (RingPool const *pool, PGPVirtMask const *imask,
71b44f ¤   PGPVirtMask *omask);
13dc68 PGPError pgpVirtMaskSetBit (RingPool const *pool, PGPVirtMask *mask,
d2b71c ¤   PGPUInt32 bitnumber);
108afe PGPError pgpVirtMaskClearBit (RingPool const *pool, PGPVirtMask *mask,
80b71c ¤   PGPUInt32 bitnumber);
441bc6 PGPError pgpVirtMaskClearGreaterBits (RingPool const *pool, PGPVirtMask *mask,
803854 ¤   PGPUInt32 firstbitnumber);
0e5305 PGPError pgpVirtMaskNOT (RingPool const *pool, PGPVirtMask *mask,
ed9f1d ¤   PGPUInt32 highbitnumber);
f3bc3d PGPError pgpVirtMaskCopy (RingPool const *pool, PGPVirtMask const *imask,
19b44f ¤   PGPVirtMask *omask);
2e9e4c PGPInt32 pgpVirtMaskLSBit (PGPVirtMask const *mask);
e6d4aa PGPBoolean pgpVirtMaskIsEmpty (PGPVirtMask const *mask);
cdec5a PGPBoolean pgpVirtMaskIsEqual (PGPVirtMask const *mask1,
c22485 ¤   PGPVirtMask const *mask2);
126667 PGPBoolean pgpVirtMaskIsOverlapping (PGPVirtMask const *mask1,
ca2485 ¤   PGPVirtMask const *mask2);
d2af5a
41ec60 void ringErr(RingFile *file, PGPUInt32 fpos, PGPError code);
f2a33b void ringSimpleErr(RingPool *pool, PGPError code);
a4468f void ringAllocErr(RingPool *pool);
5eaf5a
689cb2 PGPUInt32 ringHashBuf(PGPByte const *buf, size_t len);
1bea18 int ringLsBitFind(PGPUInt32 mask);
--c9b3 00135cd0287401001fe Page 10 of pgpRngPriv.h
ecd86b PGPError ringAllocMask(RingPool const *pool, RingSet const *,
14b44f ¤   PGPVirtMask *omask);
08c77d PGPError
7cfb19 ringClearMask(RingPool *pool, union RingObject **objp, PGPVirtMask *andmask,
e42f76 ¤   PGPVirtMask *andnotmask, PGPVirtMask *omask);
759779 PGPBoolean ringGarbageCollect(RingPool *pool);
85b937 void ringGarbageCollectObject(RingPool *pool, union RingObject *obj);
476448 PGPError ringBitAlloc(RingPool *pool, PGPUInt32 *newbit);
b7af5a
5cd71a /* Misc utility functions */
a69c28 union RingObject *ringNewObject(RingPool *pool, int objtype);
19349c #define ringNewKey(pool) ringNewObject(pool, RINGTYPE_KEY)
cc4081 #define ringNewSec(pool) ringNewObject(pool, RINGTYPE_SEC)
36ed72 #define ringNewName(pool) ringNewObject(pool, RINGTYPE_NAME)
76ff54 #define ringNewSig(pool) ringNewObject(pool, RINGTYPE_SIG)
3e8f05 #define ringNewUnk(pool) ringNewObject(pool, RINGTYPE_UNK)
153285 void ringFreeObject(RingPool *pool, union RingObject *obj);
dd0d59 void ringRemObject(RingPool *pool, union RingObject *obj);
f2af5a
e57e02 /* Insert a single key into the pool's hash table */
39fb35 #define RINGPOOLHASHKEY(pool, key) ·\
a7008b ¤   ((key)->k.util = (pool)->hashtable[(key)->k.keyID[0]], \
de1512 ¤   ·(pool)->hashtable[(key)->k.keyID[0]] = &(key)->k)
936930 void ringPoolHash(RingPool *pool);
19614e union RingObject *
4f7184 ringPoolFindKey(RingPool const *pool, PGPByte pkalg, PGPByte const keyID[8]);
a3c535 void ringPoolListSigsBy(RingPool *pool);
fd2038 #define ringFileMarkDirty(file)¤((file)->flags |= RINGFILEF_DIRTY)
b4bcac void ringPoolMarkDirty(RingPool *pool, PGPVirtMask *mask);
a5794b void ringPoolMarkTrustChanged(RingPool *pool, PGPVirtMask *mask);
acaf5a
0c9030 PGPError ringObjBetters(union RingObject const *obj, RingPool const *pool,
5fb44f ¤   PGPVirtMask *omask);
6dcb43 int ringSubkeyValid(RingSet const *set, union RingObject *subkey,
dbb052 ¤   PGPBoolean unExpired);
71f89f void ringPurgeCachedName(RingPool const *pool, RingName *name,
b37bb0 ¤   PGPVirtMask *mask);
92af5a
feb7e3 void ringFilesInit(RingPool *pool, PGPUInt32 nfiles);
adef0f void ringPoolInit( PGPContextRef context, RingPool *pool, PGPEnv const *env);
cf291e void ringPoolFini(RingPool *pool);
cfaf5a
0980e1 int pgpFingerprint20HashBuf(PGPContextRef context, PGPByte const *buf,
44ad4e ¤   ¤   ¤   ¤   ¤   ¤   ¤   size_t len, PGPByte *hash);
04af5a
80e468 void * ringSigRegexp(RingSet const *set, RingObject *sig);
beaf5a
30fc3a PGPBoolean sigRevokesKey(RingSet const *set, RingObject *sig);
0daf5a
861254 PGP_END_C_DECLARATIONS
45af5a
350383 #endif /* Included_pgpRngPriv_h */
--e997 000f386f6dc401001ff Page 1 of pgpRngPub.c
bc38e5 /*
c0dc95 ·* pgpRngPub.c - keyring management public functions.
84775e ·*
3968c2 ·* Written by Colin Plumb.
98775e ·*
51af40 ·* $Id: pgpRngPub.c,v 1.67.2.1 1998/10/10 21:05:59 hal Exp $
a3495d ·*/
a0e2ff #include "pgpConfig.h"
5b324c #include <string.h>
a1af5a
2cf115 #include <ctype.h>¤ /* For tolower() */
2baf5a
1ca146 #include "pgpDebug.h"
8e7a44 #include "pgpRngPriv.h"
c12e22 #include "pgpRngPars.h"
12ae6d #include "pgpTrstPkt.h"
1a5a03 #include "pgpTrust.h"
c05d28 #include "pgpRngMnt.h"
1c2f8d #include "pgpErrors.h"
26cdc2 #include "pgpPubKey.h"
6f26e3 #include "pgpRngPub.h"
8d806a #include "pgpRngRead.h"
51f5ab #include "pgpSigSpec.h"
4f0d08 #include "pgpMem.h"
02c26c #include "pgpContext.h"
990d6d #include "pgpEnv.h"
967ca7 #include "pgpKeyIDPriv.h"
4faf5a
f50596 #ifndef NULL
61699b #define NULL 0
b17454 #endif
80af5a
9a38e5 /*
38c30e ·* The four type bits are encoded as described in pgpRngPriv.h.
bf495d ·*/
ee4d2f int
818a30 ringObjectType(union RingObject const *obj)
b2bb36 {
41cc8a ¤   int const types[] = {
d4cf04 ¤   ¤   RINGTYPE_UNK, RINGTYPE_SEC, RINGTYPE_KEY, RINGTYPE_KEY,
2876c2 ¤   ¤   RINGTYPE_SIG, RINGTYPE_NAME };
040da9 ¤   PGPByte type_index;
5faf5a
719247 ¤   pgpAssert (obj);
b4e34c ¤   type_index = (obj->g.flags&RINGOBJF_TYPE) >> RINGOBJ_SHIFT;
97c9f7 ¤   pgpAssert (type_index < sizeof(types)/sizeof(types[0]));
b9844a ¤   return types[type_index];
feefe6 }
1daf5a
ad38e5 /*
728f15 ·* These are intended to track reference counts for swapping
6065e9 ·* pieces of keyring out of memory, but are currently no-ops.
14775e ·*
a04694 ·* They're called in a few places in the code as placeholders, but
da39be ·* that's just for documentation purposes.
b5495d ·*/
ca314a void
919d15 ringObjectHold(union RingObject *obj)
49bb36 {
fb8bfe ¤   (void)obj;
58efe6 }
3daf5a
2d314a void
875dc8 ringObjectRelease(union RingObject *obj)
93bb36 {
168bfe ¤   (void)obj;
96efe6 }
caaf5a
ee5568 RingPool *
46c78f ringSetPool(RingSet const *set)
b7bb36 {
f36c57 ¤   if (!set)
--6578 00020c2c3f0401001ff Page 2 of pgpRngPub.c
327ed2 ¤   ¤   return NULL;
8f04d2 ¤   return set->pool;
6aefe6 }
77af5a
f938e5 /*
aa7f96 ·* Return errors in all sorts of cases.
c0495d ·*/
60618d RingError const *
bf6877 ringPoolError(RingPool const *pool)
6ebb36 {
6ec172 ¤   pgpAssert (pool);
a829fa ¤   return &pool->e;
d4efe6 }
51af5a
7b314a void
227d84 ringPoolClearError(RingPool *pool)
4fbb36 {
3080e9 ¤   if (pool) {
5c6a1c ¤   ¤   pool->e.f = (RingFile *)NULL;
072ec2 ¤   ¤   pool->e.fpos = (PGPUInt32)-1;
7ce50a ¤   ¤   pool->e.error = kPGPError_NoErr;
6b4ee8 ¤   ¤   pool->e.syserrno = 0;
879371 ¤   }
0eefe6 }
94af5a
3e618d RingError const *
d6b1a1 ringSetError(RingSet const *set)
7dbb36 {
43bc3c ¤   pgpAssert (set);
eb0025 ¤   return &set->pool->e;
8aefe6 }
6caf5a
3c314a void
789bba ringSetClearError(RingSet *set)
55bb36 {
396d1b ¤   if (set)
77b946 ¤   ¤   ringPoolClearError(set->pool);
a1efe6 }
fdaf5a
ae618d RingError const *
82d438 ringIterError(RingIterator const *iter)
76bb36 {
177b5c ¤   pgpAssert (iter);
6ac38c ¤   return &iter->set.pool->e;
b2efe6 }
64af5a
07314a void
76a93c ringIterClearError(RingIterator *iter)
20bb36 {
c6a9db ¤   if (iter)
c6307b ¤   ¤   ringPoolClearError(iter->set.pool);
56efe6 }
c8af5a
1f618d RingError const *
f1e893 ringFileError(RingFile const *f)
45bb36 {
513457 ¤   pgpAssert (f);
0c38b4 ¤   return &f->set.pool->e;
89efe6 }
54af5a
48314a void
31d690 ringFileClearError(RingFile *f)
7dbb36 {
0d3bb0 ¤   if (f)
a309eb ¤   ¤   ringPoolClearError(f->set.pool);
64efe6 }
c4af5a
0cc77d PGPError
b28a8e ringFileSwitchFile(RingFile *file, PGPFile *newPGPFile)
4bbb36 {
cafcad ¤   pgpAssertAddrValid(file, RingFile);
2098a0 ¤   file->f = newPGPFile;
--d9af 0004a1de18f401001ff Page 3 of pgpRngPub.c
cd151e ¤   return kPGPError_NoErr;
00efe6 }
23af5a
a938e5 /*
fc12cb ·* Is the object a member of the set?
0b9479 ·* Returns the level of the object, or 0 if it is not.
41495d ·*/
384d2f int
e043ff ringSetIsMember(RingSet const *set, union RingObject const *obj)
c3bb36 {
40af74 ¤   int level = 1;
adaf5a
3d01ed ¤   while (pgpIsRingSetMember(set, obj)) {
88c8ed ¤   ¤   if (OBJISTOP(obj))
874033 ¤   ¤   ¤   return level;
725f84 ¤   ¤   obj = obj->g.up;
6a3402 ¤   ¤   level++;
939371 ¤   }
a5f07d ¤   return 0;¤  /* Not a member of the iterator */
d2efe6 }
92af5a
c4a4c7 RingSet const *
27b1f5 ringIterSet(RingIterator const *iter)
66bb36 {
bc21b2 ¤   if (!iter)
287ed2 ¤   ¤   return NULL;
967c8d ¤   return &iter->set;
b2efe6 }
83af5a
47a4c7 RingSet const *
9ecf4a ringFileSet(RingFile const *file)
7fbb36 {
0a24fc ¤   if (!file)
eb7ed2 ¤   ¤   return NULL;
30b240 ¤   return &file->set;
6eefe6 }
d4af5a
5fa6d1 PgpVersion
e30fad ringFileVersion(RingFile const *file)
1bbb36 {
ca6834 ········if (!file)
97b85f ¤   ········return 0;
228df5 ¤   return file->version;
57efe6 }
feaf5a
3638e5 /*
273d64 ·* An iterator involves a current position which is a stack, with an
761d50 ·* accessible stack-depth value. ·The stack depth equals the level
bab933 ·* of the last ringIterNextObject call, and the stack entries
acf0db ·* are the return values. ·If a query is made for a level which
18fd8a ·* is greater than the stack depth, the first entry on the list
7183f4 ·* of descendants of the top entry on the stack is returned.
140979 ·* Only the highest-level entry may be NULL; that indicates that the
7e9584 ·* end of the list there has been reached. ·It is illegal to
49025d ·* ask for descendants of a NULL entry; although returning NULL
61c5db ·* is another reasonable option, the usefulness is unclear and the
31daf5 ·* stricter rule has the advantage of catching bugs faster.
57495d ·*/
7faf5a
5438e5 /*
199c2b ·* Find the next object of the given level in the given iterator.
6d8691 ·* Returns <0 on error, 0 if there is no object, or the level if
0d5e7b ·* there is one.
a7495d ·*/
e94d2f int
8c79a9 ringIterNextObject(RingIterator *iter, unsigned level)
c2bb36 {
d4a997 ¤   union RingObject *obj;
1caf5a
129e18 ¤   pgpAssert(iter);
d4a396 ¤   pgpAssert(level);
4a3e02 ¤   pgpAssert(iter->set.type == RINGSET_ITERATOR);
--3b3e 0007e0ed055401001ff Page 4 of pgpRngPub.c
e0af5a
ad098e ¤   /* Get the head of the list to search */
bccde7 ¤   if (level <= iter->level) {
e3588b ¤   ¤   /* Going along an existing level */
c71a74 ¤   ¤   iter->level = level;
fc4b3e ¤   ¤   obj = iter->stack[level-1];
c7e83d ¤   ¤   if (!obj)
2e8144 ¤   ¤   ¤   return 0;
1f5849 ¤   ¤   pgpAssert (pgpIsRingSetMember (&iter->set, obj));
89e2b6 ¤   ¤   obj = obj->g.next;
1df037 ¤   } else {
11a570 ¤   ¤   /* Going down a level */
90a7c5 ¤   ¤   pgpAssert(level == iter->level+1);
31af5a
534c0e ¤   ¤   if (level > 1) {
9baba6 ¤   ¤   ¤   obj = iter->stack[level-2];
e24414 ¤   ¤   ¤   pgpAssert(obj);
f9ba49 ¤   ¤   ¤   pgpAssert (pgpIsRingSetMember (&iter->set, obj));
01f09b ¤   ¤   ¤   if (OBJISBOT(obj))
8946f1 ¤   ¤   ¤   ¤   return 0;
cfd72e ¤   ¤   ¤   obj = obj->g.down;
c545a6 ¤   ¤   } else {
c98b2b ¤   ¤   ¤   obj = iter->set.pool->keys;
cc0fe4 ¤   ¤   }
611a74 ¤   ¤   iter->level = level;
749371 ¤   }
a4af5a
1163a4 ¤   /* Search for the next item of interest */
18a1d5 ¤   while (obj && !pgpIsRingSetMember (&iter->set, obj))
a5e2b6 ¤   ¤   obj = obj->g.next;
c4af5a
53b383 ¤   pgpAssert(level <= RINGMAXDEPTH);
d89098 ¤   iter->stack[level-1] = obj;
36bb35 ¤   return obj ? level : 0;
3fefe6 }
89af5a
43af5a
ab38e5 /*
b4cd58 ·* More complex because we need to find the head of the enclosing list and
d37d33 ·* search forwards for the last matching object that's not the target object.
34495d ·*/
214d2f int
7016c8 ringIterPrevObject(RingIterator *iter, unsigned level)
5bbb36 {
6f5bad ¤   union RingObject *obj, *found, *target;
c4af5a
939e18 ¤   pgpAssert(iter);
1ca396 ¤   pgpAssert(level);
4e3e02 ¤   pgpAssert(iter->set.type == RINGSET_ITERATOR);
63af5a
cfa522 ¤   /* There's nothing before the beginning of a list */
0fa1f9 ¤   if (level > iter->level) {
6ca7c5 ¤   ¤   pgpAssert(level == iter->level+1);
afbbde ¤   ¤   return 0;
e59371 ¤   }
56af5a
41f41c ¤   /* The thing we want the predecessor of */
9bcb70 ¤   target = iter->stack[level-1];
fdaf5a
0d8e28 ¤   /* The head of the list to search along */
bbfddf ¤   if (level > 1) {
ba6ef3 ¤   ¤   obj = iter->stack[level-2];
06b271 ¤   ¤   pgpAssert(obj);
9a5849 ¤   ¤   pgpAssert (pgpIsRingSetMember (&iter->set, obj));
a6c306 ¤   ¤   obj = obj->g.down;
c3edfd ¤   ¤   /* obj = iter->stack[level-2]->g.down; */
a2f037 ¤   } else {
354e7e ¤   ¤   obj = iter->set.pool->keys;
739371 ¤   }
74af5a
e1d8af ¤   /*
7e5ad2 ¤   ·* Search forward along the list until we hit the current
--1a33 00030d4ce66401001ff Page 5 of pgpRngPub.c
01130c ¤   ·* object, kepping track of the last object in the desired
688818 ¤   ·* ringSet.
6aa4e3 ¤   ·*/
ce3855 ¤   found = NULL;
cfaf5a
2e544f ¤   while (obj != target) {
6bb271 ¤   ¤   pgpAssert(obj);
f4280a ¤   ¤   if (pgpIsRingSetMember (&iter->set, obj))
bd56db ¤   ¤   ¤   found = obj;
23e2b6 ¤   ¤   obj = obj->g.next;
ef9371 ¤   }
1daf5a
430665 ¤   if (!found) {
cc9883 ¤   ¤   /* Hit beginning of list, set up as beginning */
e3f21c ¤   ¤   iter->level = level-1;
57bbde ¤   ¤   return 0;
6b9371 ¤   }
6dba09 ¤   iter->stack[level-1] = found;
f81cdf ¤   if (OBJISBOT(found)) {
cf3253 ¤   ¤   /* Found an object, but no children. */
311e7b ¤   ¤   return iter->level = level;
abf037 ¤   } else {
de9f4a ¤   ¤   /* An object with children - set up that list at end */
e08f6d ¤   ¤   pgpAssert(level <= RINGMAXDEPTH);
355a15 ¤   ¤   iter->stack[level] = NULL;
4eb986 ¤   ¤   iter->level = level+1;
af9371 ¤   }
efe981 ¤   return (int)level;
83efe6 }
beaf5a
0b6d2d /* The level of the most recent ringIterNextObject() call */
ea536c unsigned
2a2e25 ringIterCurrentLevel(RingIterator const *iter)
21bb36 {
539c96 ¤   return iter->level;
d6efe6 }
36af5a
4638e5 /*
b560c1 ·* A trivial little function that just returns the current object
88ffd9 ·* at a given level, again.
aa495d ·*/
fd614e union RingObject *
3663c8 ringIterCurrentObject(RingIterator const *iter, unsigned level)
2abb36 {
329e18 ¤   pgpAssert(iter);
afa396 ¤   pgpAssert(level);
ae3e02 ¤   pgpAssert(iter->set.type == RINGSET_ITERATOR);
01af5a
ebf5a3 ¤   return level > iter->level ? NULL : iter->stack[level-1];
7aefe6 }
87af5a
4e38e5 /*
153b47 ·* Seek to the next object at the deepest level possible.
98775e ·*
d83d52 ·* Equivalent to:
073501 ·* int i;
1be039 ·* unsigned l = ringIterCurrentLevel(iter)+1;
8b775e ·*
3dbd5b ·* while (l && !(i = ringIterNextObject(iter, l)))
75ffb4 ·*¤ --l;
8d7d28 ·* return i;
30495d ·*/
a84d2f int
813d85 ringIterNextObjectAnywhere(RingIterator *iter)
44bb36 {
ada997 ¤   union RingObject *obj;
64fd8a ¤   unsigned level = iter->level;
2faf5a
f79e18 ¤   pgpAssert(iter);
263e02 ¤   pgpAssert(iter->set.type == RINGSET_ITERATOR);
8caf5a
305ad3 ¤   /* Find first object to be considered */
--fd0c 000ea383d13401001ff Page 6 of pgpRngPub.c
211bed ¤   if (!level) {
f1b706 ¤   ¤   level = 1;
ad4e7e ¤   ¤   obj = iter->set.pool->keys;
e8f037 ¤   } else {
414b3e ¤   ¤   obj = iter->stack[level-1];
34af5a
232d74 ¤   ¤   if (obj) {
f8ba49 ¤   ¤   ¤   pgpAssert (pgpIsRingSetMember (&iter->set, obj));
44c10d ¤   ¤   ¤   if (OBJISBOT(obj)) {
d57ae1 ¤   ¤   ¤   ¤   obj = obj->g.next;
02042d ¤   ¤   ¤   } else {
a4c458 ¤   ¤   ¤   ¤   level++;
105b51 ¤   ¤   ¤   ¤   obj = obj->g.down;
6fa3a6 ¤   ¤   ¤   }
1e0fe4 ¤   ¤   }
7c9371 ¤   }
18af5a
ca220e ¤   for (;;) {
6b269f ¤   ¤   while (obj) {
5f665a ¤   ¤   ¤   if (pgpIsRingSetMember(&iter->set, obj)) {
785657 ¤   ¤   ¤   ¤   iter->stack[level-1] = obj;
839c4a ¤   ¤   ¤   ¤   iter->level = level;
2d9337 ¤   ¤   ¤   ¤   return (int)level;
08a3a6 ¤   ¤   ¤   }
01f69e ¤   ¤   ¤   obj = obj->g.next;
ba0fe4 ¤   ¤   }
4fa4c3 ¤   ¤   if (!--level)
a0cdcb ¤   ¤   ¤   break;
a34b3e ¤   ¤   obj = iter->stack[level-1];
b2b271 ¤   ¤   pgpAssert(obj);
37e2b6 ¤   ¤   obj = obj->g.next;
db9371 ¤   }
1faf5a
1b5434 ¤   /* End of list, no luck */
f5b40c ¤   iter->stack[0] = NULL;
e640ff ¤   iter->level = 1;
3f3e6b ¤   return 0;
9cefe6 }
72af5a
1a22cd /* Reset the iterator to the beginning of the given level */
184d2f int
0e56d8 ringIterRewind(RingIterator *iter, unsigned level)
f6bb36 {
50a396 ¤   pgpAssert(level);
6aa90b ¤   pgpAssert(iter->level >= level - 1);
b6e634 ¤   iter->level = level-1;
383e6b ¤   return 0;
01efe6 }
08af5a
d3f1ee /* Reset the iterator to the end of the given level */
f74d2f int
f991ac ringIterFastForward(RingIterator *iter, unsigned level)
cebb36 {
f2a396 ¤   pgpAssert(level);
8bd58a ¤   pgpAssert(level <= iter->level + 1);
dedbce ¤   if (level > RINGMAXDEPTH)
597deb ¤   ¤   level = RINGMAXDEPTH;
550e24 ¤   else
fe884b ¤   ¤   iter->stack[level-1] = NULL;
042e29 ¤   iter->level = level;
3a3e6b ¤   return 0;
1defe6 }
b1af5a
5638e5 /*
df2968 ·* Seek the iterator to the given object, state as if it just
8645e4 ·* returned the object.¤ Returns the level of the object, or <0
7e4e9f ·* on error.
aa495d ·*/
f64d2f int
e3e584 ringIterSeekTo(RingIterator *iter, union RingObject *obj)
46bb36 {
eab9ce ¤   union RingObject *p, *pp;
--1b7b 000a9e1e90e401001ff Page 7 of pgpRngPub.c
69beaf ¤   int level;
32af5a
e63e02 ¤   pgpAssert(iter->set.type == RINGSET_ITERATOR);
c0af5a
629321 ¤   if (!pgpIsRingSetMember (&iter->set, obj))
5ac992 ¤   ¤   return 0;¤  /* Not a member */
c4af5a
7f67a8 ¤   /* A bit ad-hoc; there is a general way. */
f3ec8f ¤   if (OBJISTOP(obj)) {
463edd ¤   ¤   iter->stack[0] = obj;
71b706 ¤   ¤   level = 1;
5ff037 ¤   } else {
a71e77 ¤   ¤   p = obj->g.up;
35fc3f ¤   ¤   pgpAssert(pgpIsRingSetMember(&iter->set, p));
c37e39 ¤   ¤   if (OBJISTOP(p)) {
74fa89 ¤   ¤   ¤   iter->stack[0] = p;
4b25f2 ¤   ¤   ¤   iter->stack[1] = obj;
05638b ¤   ¤   ¤   level = 2;
8245a6 ¤   ¤   } else {
570643 ¤   ¤   ¤   pp = p->g.up;
f4dab8 ¤   ¤   ¤   pgpAssert(pgpIsRingSetMember(&iter->set, pp));
4734a5 ¤   ¤   ¤   pgpAssert(OBJISTOP(pp));
5a36c3 ¤   ¤   ¤   iter->stack[0] = pp;
0d7b36 ¤   ¤   ¤   iter->stack[1] = p;
40519b ¤   ¤   ¤   iter->stack[2] = obj;
8e3957 ¤   ¤   ¤   level = 3;
570fe4 ¤   ¤   }
8b9371 ¤   }
509587 ¤   return iter->level = level;
c2efe6 }
7baf5a
c02978 static void
2b280b ringSetCountList(union RingObject const *obj, PGPVirtMask const *mask,
01d824 ·················unsigned *counts, unsigned depth)
68bb36 {
3e1c05 ¤   while (obj) {
06a57b ¤   ¤   if (pgpVirtMaskIsOverlapping (&obj->g.mask, mask)) {
a7c1d0 ¤   ¤   ¤   counts[0]++;
7bd5f9 ¤   ¤   ¤   if (depth && !OBJISBOT(obj)) {
ea63c1 ¤   ¤   ¤   ¤   ringSetCountList(obj->g.down, mask,
eb1507 ¤   ¤   ¤   ¤   ·················counts+1, depth-1);
5fa3a6 ¤   ¤   ¤   }
800fe4 ¤   ¤   }
a1e2b6 ¤   ¤   obj = obj->g.next;
d79371 ¤   }
59efe6 }
daaf5a
6b38e5 /*
9b4aa9 ·* Count the number of objects in an iterator down to a given depth.
11495d ·*/
b04d2f int
b5a45d ringSetCount(RingSet const *set, unsigned *counts, unsigned depth)
bdbb36 {
db6287 ¤   unsigned i = 0;
49af5a
afd0a8 ¤   for (i = 0; i < depth; i++)
f95118 ¤   ¤   counts[i] = 0;
8756ac ¤   if (IsntNull(set) && !pgpVirtMaskIsEmpty(&set->mask) && depth > 0)
01c6c6 ¤   ¤   ringSetCountList(set->pool->keys, &set->mask, counts, depth-1);
9a3e6b ¤   return 0;
26efe6 }
99af5a
262978 static void
bcdb25 ringSetCountTypesList(union RingObject const *obj, PGPVirtMask const *mask,
428095 ······················unsigned *counts, unsigned max)
cabb36 {
8f314e ¤   int t;
89af5a
561c05 ¤   while (obj) {
028114 ¤   ¤   if (pgpVirtMaskIsOverlapping (mask, &obj->g.mask)) {
c42e91 ¤   ¤   ¤   t = ringObjectType(obj);
a98103 ¤   ¤   ¤   if ((unsigned)t <= max)
--2521 00052a98740401001ff Page 8 of pgpRngPub.c
c6dc36 ¤   ¤   ¤   ¤   counts[t-1]++;
6d985a ¤   ¤   ¤   if (!OBJISBOT(obj))
89973c ¤   ¤   ¤   ¤   ringSetCountTypesList(obj->g.down, mask,
805613 ¤   ¤   ¤   ¤   ·················counts, max);
800fe4 ¤   ¤   }
77e2b6 ¤   ¤   obj = obj->g.next;
ac9371 ¤   }
4aefe6 }
bfaf5a
fa38e5 /*
af85e4 ·* Count the number of objects in an iterator of various types.
4f495d ·*/
844d2f int
5ffe39 ringSetCountTypes(RingSet const *set, unsigned *counts, unsigned max)
dcbb36 {
006287 ¤   unsigned i = 0;
d7af5a
abac4a ¤   for (i = 0; i < max; i++)
d05118 ¤   ¤   counts[i] = 0;
6ceb58 ¤   if (IsntNull(set) && !pgpVirtMaskIsEmpty(&set->mask) && max > 0)
21241d ¤   ¤   ringSetCountTypesList(set->pool->keys, &set->mask, counts, max);
ec3e6b ¤   return 0;
ccefe6 }
06af5a
8da9ad RingIterator *
404229 ringIterCreate(RingSet const *set)
33bb36 {
e76032 ¤   RingPool *pool = set->pool;
cc3bb6 ¤   RingIterator *iter;
8faf5a
702388 ¤   pgpAssert(!RINGSETISMUTABLE(set));
c0af5a
0c0dc9 ¤   /* Allocate the structure */
f2efa4 ¤   iter = pool->freeiter;
95482f ¤   if (iter) {
b7d0c6 ¤   ¤   pool->freeiter = (RingIterator *)iter->set.next;
b918bc ¤   ¤   pgpAssert(iter->set.type == RINGSET_FREE);
a5f037 ¤   } else {
6f1beb ¤   ¤   iter = (RingIterator *)memPoolNew(&pool->structs,
c4b556 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·RingIterator);
b4b3a9 ¤   ¤   if (!iter) {
a2e8ed ¤   ¤   ¤   ringAllocErr(pool);
d5cf03 ¤   ¤   ¤   return NULL;
070fe4 ¤   ¤   }
b49371 ¤   }
9baf5a
97109d ¤   /* Okay, allocated - fill it in */
8a078f ¤   iter->set.pool = pool;
e1394c ¤   iter->set.next = pool->sets;
7f642b ¤   iter->set.type = RINGSET_ITERATOR;
71d75e ¤   pool->sets = &iter->set;
8c6677 ¤   iter->set.mask = set->mask;
d1eeef ¤   iter->level = 0;¤   /* Rewind to beginning */
082db8 ¤   return iter;
52efe6 }
e8af5a
09314a void
feedf1 ringIterDestroy(RingIterator *iter)
84bb36 {
648642 ¤   RingPool *pool;
c93afe ¤   RingSet **setp;
54af5a
a7482f ¤   if (iter) {
6a0fb2 ¤   ¤   pool = iter->set.pool;
fdaf5a
a62f25 ¤   ¤   pgpAssert(iter->set.type == RINGSET_ITERATOR);
72d428 ¤   ¤   iter->set.type = RINGSET_FREE;
eeaf5a
cda889 ¤   ¤   /* Remove it from the list of allocated sets */
f8988d ¤   ¤   setp = &pool->sets;
9abb43 ¤   ¤   while (*setp != &iter->set) {
52dd6f ¤   ¤   ¤   pgpAssert(*setp);
--c23f 00046f0a5f5401001ff Page 9 of pgpRngPub.c
5ce093 ¤   ¤   ¤   setp = &(*setp)->next;
3a0fe4 ¤   ¤   }
2612f6 ¤   ¤   *setp = iter->set.next;
3caf5a
0c5605 ¤   ¤   /* Add to the list of free iterators. */
d12cf9 ¤   ¤   iter->set.next = (RingSet *)pool->freeiter;
f5d81b ¤   ¤   pool->freeiter = iter;
059371 ¤   }
97efe6 }
ddaf5a
1a0dcb static RingSet *
c4763a ringSetAlloc(RingPool *pool)
dcbb36 {
5ac958 ¤   RingSet *set;
3eaf5a
a90dc9 ¤   /* Allocate the structure */
52314d ¤   set = pool->freesets;
8302ad ¤   if (set) {
ce8588 ¤   ¤   pool->freesets = set->next;
42f037 ¤   } else {
42fb2b ¤   ¤   set = (RingSet *)memPoolNew(&pool->structs,
e18c87 ¤   ¤   ¤   ¤   ¤   ¤   ···RingSet);
b96b91 ¤   ¤   if (!set) {
38e8ed ¤   ¤   ¤   ringAllocErr(pool);
68cf03 ¤   ¤   ¤   return NULL;
b50fe4 ¤   ¤   }
b29371 ¤   }
65af5a
86109d ¤   /* Okay, allocated - fill it in */
f9e6d0 ¤   set->pool = pool;
306406 ¤   set->next = pool->sets;
0ce6cf ¤   pool->sets = set;
f9dd79 ¤   pgpVirtMaskInit (pool, &set->mask);
72bc0c ¤   /* set->type uninitialized */
a8af5a
449329 ¤   return set;
f7efe6 }
97af5a
aee9eb RingSet *
2cc45a ringSetCreate(RingPool *pool)
eabb36 {
7a45d1 ¤   PGPVirtMask mask;
8bc958 ¤   RingSet *set;
0bc6d6 ¤   unsigned bit;
370040 ¤   PGPError err;
ecaf5a
f4fcfd ¤   if (!pool)
477ed2 ¤   ¤   return NULL;
e5af5a
5389eb ¤   /* Allocate a new bit */
b8dbf9 ¤   err = ringBitAlloc(pool, &bit);
fb1065 ¤   if (IsPGPError(err)) {
12dbca ¤   ¤   ringSimpleErr(pool, err);
747ed2 ¤   ¤   return NULL;
e59371 ¤   }
14af5a
e614fb ¤   pgpVirtMaskInit (pool, &mask);
33ad5e ¤   pgpVirtMaskSetBit (pool, &mask, bit);
31af5a
190dc9 ¤   /* Allocate the structure */
dd794e ¤   set = ringSetAlloc(pool);
5302ad ¤   if (set) {
3feda7 ¤   ¤   pgpVirtMaskCopy (pool, &mask, &set->mask);
90fb65 ¤   ¤   set->type = RINGSET_MUTABLE;
81212c ¤   ¤   pgpVirtMaskOR (pool, &mask, &pool->allocmask);
839371 ¤   }
ad0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
879329 ¤   return set;
82efe6 }
74af5a
ec314a void
4670e1 ringSetDestroy(RingSet *set)
--b278 000aa64ae56401001ff Page 10 of pgpRngPub.c
2cbb36 {
968642 ¤   RingPool *pool;
9a3afe ¤   RingSet **setp;
50af5a
c802ad ¤   if (set) {
d61515 ¤   ¤   pool = set->pool;
bd3ad5 ¤   ¤   pgpAssert(set->type < RINGSET_FREE);
8790a5 ¤   ¤   set->type = RINGSET_FREE;
01af5a
11a889 ¤   ¤   /* Remove it from the list of allocated sets */
17988d ¤   ¤   setp = &pool->sets;
e726d1 ¤   ¤   while (*setp != set) {
95dd6f ¤   ¤   ¤   pgpAssert(*setp);
03e093 ¤   ¤   ¤   setp = &(*setp)->next;
cf0fe4 ¤   ¤   }
01acde ¤   ¤   *setp = set->next;
afaf5a
b2a189 ¤   ¤   pgpVirtMaskCleanup (pool, &set->mask);
4eaf5a
7a757a ¤   ¤   /* Add to the list of free sets. */
1c9b95 ¤   ¤   set->next = pool->freesets;
b82528 ¤   ¤   pool->freesets = set;
a49371 ¤   }
55efe6 }
f3af5a
3038e5 /*
844e2f ·* Freeze a RingSet so that you can start doing set operations
85aa20 ·* on it, copying it, etc.
33495d ·*/
0bc744 ¤   PGPError
003f9e ringSetFreeze(RingSet *set)
62bb36 {
b302ad ¤   if (set) {
c61c12 ¤   ¤   if (set->type == RINGSET_MUTABLE)
b96d54 ¤   ¤   ¤   set->type = RINGSET_IMMUTABLE;
fffbc3 ¤   ¤   pgpAssert(set->type == RINGSET_IMMUTABLE);
a89371 ¤   }
02151e ¤   return kPGPError_NoErr;
d2efe6 }
60af5a
f3e9eb RingSet *
29ee3d ringSetCopy(RingSet const *s)
05bb36 {
1cc958 ¤   RingSet *set;
67af5a
90a2be ¤   if (!s)
5e7ed2 ¤   ¤   return NULL;
f6af5a
6fb9e2 ¤   pgpAssert(!RINGSETISMUTABLE(s));
d77176 ¤   set = ringSetAlloc(s->pool);
e302ad ¤   if (set) {
0ab8a4 ¤   ¤   pgpVirtMaskCopy (s->pool, &s->mask, &set->mask);
716318 ¤   ¤   set->type = RINGSET_IMMUTABLE;
959371 ¤   }
6d9329 ¤   return set;
b4efe6 }
7faf5a
a8a103 /* This accepts NULL as an alias for "no such set" */
96e9eb RingSet *
d593cb ringSetUnion(RingSet const *s1, RingSet const *s2)
80bb36 {
e7c958 ¤   RingSet *set;
10af5a
bdb901 ¤   if (!s1)
24ba01 ¤   ¤   return ringSetCopy(s2);
d4af5a
888330 ¤   set = ringSetCopy(s1);
6d891c ¤   if (set && s2) {
035fb9 ¤   ¤   pgpAssert(s1->pool == s2->pool);
913bea ¤   ¤   pgpAssert(!RINGSETISMUTABLE(s2));
6c4b5c ¤   ¤   pgpVirtMaskOR (s1->pool, &s2->mask, &set->mask);
aa9371 ¤   }
--852e 0006eff6384401001ff Page 11 of pgpRngPub.c
ca9329 ¤   return set;
bfefe6 }
2eaf5a
71af5a
f7482a /** The following operations only apply to mutable RingSets **/
66af5a
7738e5 /*
88cbd8 ·* Add an object to a mutable RingSet. ·That includes the all of the
3518b2 ·* object's parents in order to main the proper RingSet invariants.
96495d ·*/
6fa091 ¤   int
c8680f ringSetAddObject(RingSet *set, union RingObject *obj)
91bb36 {
a06211 ¤   pgpAssert(RINGSETISMUTABLE(set));
62af5a
7479c7 ¤   if (IsntNull(obj) && !pgpIsRingSetMember(set, obj)) {
8c58ca ¤   ¤   pgpVirtMaskOR (set->pool, &set->mask, &obj->g.mask);
8a9590 ¤   ¤   /* Ensure all parents are added, too. */
138a7d ¤   ¤   while (!OBJISTOP(obj)) {
376bd9 ¤   ¤   ¤   obj = obj->g.up;
d6d145 ¤   ¤   ¤   if (pgpIsRingSetMember(set, obj))
a2f622 ¤   ¤   ¤   ¤   break;
9b82e3 ¤   ¤   ¤   pgpVirtMaskOR (set->pool, &set->mask, &obj->g.mask);
bc0fe4 ¤   ¤   }
e39371 ¤   }
eb3e6b ¤   return 0;
18efe6 }
c1af5a
a238e5 /*
89ac66 ·* Add an object and its children to a mutable RingSet. ·Also will do
22f283 ·* the object's parents. ·src RingSet controls which children are added.
96495d ·*/
79a091 ¤   int
683cf8 ringSetAddObjectChildren(RingSet *dest, RingSet const *src,
b50fb6 ¤   union RingObject *obj)
b6bb36 {
bffec1 ¤   RingSet const *srcx;
113bb6 ¤   RingIterator *iter;
5e5547 ¤   int level, initlevel;
1a44e1 ¤   int nobjs;
bb17e6 ¤   int err;
ecaf5a
c08644 ¤   /* Need to iterate over src, make a copy if necessary */
faaefd ¤   srcx = src;
a391fa ¤   if (RINGSETISMUTABLE(src)) {
c470f4 ¤   ¤   RingSet *src1 = ringSetCreate (ringSetPool (src));
8731bf ¤   ¤   if (!src1)
99a198 ¤   ¤   ¤   return ringSetError(src)->error;
5c2e87 ¤   ¤   ringSetAddSet (src1, src);
6f72b9 ¤   ¤   ringSetFreeze (src1);
fde2b8 ¤   ¤   src = (RingSet const *)src1;
d49371 ¤   }
1887c7 ¤   ¤   ¤
1487b4 ¤   /* First add the object */
e4f34a ¤   if ((err= (PGPError)ringSetAddObject(dest, obj)) < 0)
51c9db ¤   ¤   return err;
76af5a
6caf91 ¤   iter = ringIterCreate(src);
c121b2 ¤   if (!iter)
3ba720 ¤   ¤   return ringSetError(src)->error;
47af5a
0e121e ¤   nobjs = 1;
a35482 ¤   initlevel=ringIterSeekTo(iter, obj);
fca4fd ¤   if (initlevel < 0)
3cf2ef ¤   ¤   return initlevel;
4ccda7 ¤   level = initlevel + 1;
37997e ¤   while (level > initlevel) {
d938a1 ¤   ¤   union RingObject *child;
1d6b5f ¤   ¤   err = (PGPError)ringIterNextObject(iter, level);
c40239 ¤   ¤   if (err < 0) {
4385de ¤   ¤   ¤   ringIterDestroy(iter);
6eb32f ¤   ¤   ¤   return err;
--8b6f 0000f2064ed401001ff Page 12 of pgpRngPub.c
b50fe4 ¤   ¤   }
e73582 ¤   ¤   if (err > 0) {
d05ddc ¤   ¤   ¤   child = ringIterCurrentObject(iter, level);
68a4f7 ¤   ¤   ¤   if (!child)
05f305 ¤   ¤   ¤   ¤   return ringSetError(src)->error;
4eaf98 ¤   ¤   ¤   if ((err=ringSetAddObject(dest, child)) < 0)
fe454a ¤   ¤   ¤   ¤   return err;
6e434a ¤   ¤   ¤   ++nobjs;
d0b904 ¤   ¤   ¤   ++level;
ae45a6 ¤   ¤   } else {
d000aa ¤   ¤   ¤   --level;
0e0fe4 ¤   ¤   }
be9371 ¤   }
4b1d89 ¤   ringIterDestroy(iter);
2ff444 ¤   /* Destroy set copy if we made one */
267454 ¤   if (src != srcx)
32fdae ¤   ¤   ringSetDestroy ((RingSet *)src);
cd4752 ¤   return nobjs;
5eefe6 }
b8af5a
6538e5 /*
375f79 ·* Remove an object from a mutable RingSet. ·That includes the all of the
59c3e9 ·* object's children in order to main the proper RingSet invariants.
ed9575 ·* (Done recursively.)
5a495d ·*/
874d2f int
2308aa ringSetRemObject(RingSet *set, union RingObject *obj)
cabb36 {
426211 ¤   pgpAssert(RINGSETISMUTABLE(set));
49af5a
c4d8af ¤   /*
12bb8e ¤   ·* Remove this object and all its children.
81878a ¤   ·* As an optimization, omit scanning children if the
627f31 ¤   ·* object is not already in the set.
a6a4e3 ¤   ·*/
916338 ¤   if (IsntNull(obj) && pgpIsRingSetMember (set, obj)) {
61ca39 ¤   ¤   if (!OBJISBOT(obj)) {
78bd2b ¤   ¤   ¤   union RingObject *obj2 = obj;
04ccf1 ¤   ¤   ¤   for (obj2 = obj2->g.down; obj2; obj2 = obj2->g.next)
2a98cc ¤   ¤   ¤   ¤   ringSetRemObject(set, obj2);
000fe4 ¤   ¤   }
af030b ¤   ¤   pgpVirtMaskANDNOT (set->pool, &set->mask, &obj->g.mask);
09e06c ¤   ¤   ringGarbageCollectObject(set->pool, obj);
d39371 ¤   }
1f3e6b ¤   return 0;
feefe6 }
f5af5a
cb2f5c /* Helper function for ringSetAddSet */
042978 static void
18768d ringSetAddList(union RingObject *obj, RingSet *dest, RingSet const *src)
77bb36 {
c31c05 ¤   while (obj) {
0a6a1e ¤   ¤   if (pgpIsRingSetMember(src, obj)) {
bf75b1 ¤   ¤   ¤   pgpVirtMaskOR (dest->pool, &dest->mask, &obj->g.mask);
3d985a ¤   ¤   ¤   if (!OBJISBOT(obj))
0743b0 ¤   ¤   ¤   ¤   ringSetAddList(obj->g.down, dest, src);
e80fe4 ¤   ¤   }
6ae2b6 ¤   ¤   obj = obj->g.next;
a89371 ¤   }
adefe6 }
e0af5a
724d2f int
48c551 ringSetAddSet(RingSet *set, RingSet const *set2)
e8bb36 {
d06211 ¤   pgpAssert(RINGSETISMUTABLE(set));
a29821 ¤   if (set2) {
3106ee ¤   ¤   pgpAssert(set->pool == set2->pool);
cdaf5a
4ddc16 ¤   ¤   ringSetAddList(set->pool->keys, set, set2);
a49371 ¤   }
f23e6b ¤   return 0;
0fefe6 }
--2aea 0008035dcda401001ff Page 13 of pgpRngPub.c
e0af5a
d338e5 /*
e083a7 ·* Subtracting sets is simplified by the proper-set requirement.
a87c93 ·* If I remove a key (because it's in set2), I have to remove all
1f0545 ·* children of the key, so I just use ringClearMask to do
a05e66 ·* the job. ·If I don't (because it's not in set2), then it's
79113d ·* guaranteed that none of its children are in set2 either,
b26c2d ·* so there's no need to examine any children.
92495d ·*/
ed4d2f int
c1554b ringSetSubtractSet(RingSet *set, RingSet const *set2)
6fbb36 {
80a997 ¤   union RingObject *obj;
5d0537 ¤   PGPVirtMask tmask;
fdaf5a
116211 ¤   pgpAssert(RINGSETISMUTABLE(set));
8caf5a
2c10bd ¤   pgpVirtMaskInit (set->pool, &tmask);
69af5a
e2f855 ¤   if (IsntNull(set2) && !pgpVirtMaskIsEmpty(&set2->mask)) {
e406ee ¤   ¤   pgpAssert(set->pool == set2->pool);
9014d9 ¤   ¤   for (obj = set->pool->keys; obj; obj = obj->g.next) {
704050 ¤   ¤   ¤   if (pgpIsRingSetMember (set, obj)
946a78 ¤   ¤   ¤   ¤   && pgpIsRingSetMember (set2, obj)) {
c78e38 ¤   ¤   ¤   ¤   pgpVirtMaskANDNOT (set->pool, &set->mask, &obj->g.mask);
151242 ¤   ¤   ¤   ¤   if (!OBJISBOT(obj)) {
8b09f2 ¤   ¤   ¤   ¤   ¤   ringClearMask(set->pool, &obj->g.down, NULL,
3255fa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&set->mask, &tmask);
9e2613 ¤   ¤   ¤   ¤   }
20a3a6 ¤   ¤   ¤   }
870fe4 ¤   ¤   }
5d9371 ¤   }
d8ff1e ¤   pgpVirtMaskCleanup (set->pool, &tmask);
803e6b ¤   return 0;
1befe6 }
7aaf5a
6dbeb7 static int
4d4c70 ringSetIntersectList(union RingObject *obj, RingSet const *s1,
f22ab4 ¤   RingSet const *s2, RingSet const *dest)
9bbb36 {
89364d ¤   int flag = 0;
73af5a
471c05 ¤   while (obj) {
e033cb ¤   ¤   if (pgpIsRingSetMember(s1,obj) &&
b0f085 ¤   ¤   ¤   pgpIsRingSetMember(s2,obj)) {
d9e593 ¤   ¤   ¤   flag = 1;
3c853c ¤   ¤   ¤   pgpVirtMaskOR (s1->pool, &dest->mask, &obj->g.mask);
be985a ¤   ¤   ¤   if (!OBJISBOT(obj))
ba61c8 ¤   ¤   ¤   ¤   ringSetIntersectList(obj->g.down, s1, s2, dest);
6f0fe4 ¤   ¤   }
ede2b6 ¤   ¤   obj = obj->g.next;
009371 ¤   }
273095 ¤   return flag;
32efe6 }
1caf5a
47e9eb RingSet *
207b0d ringSetIntersection(RingSet const *s1, RingSet const *s2)
38bb36 {
19c958 ¤   RingSet *set;
1a45d1 ¤   PGPVirtMask mask;
12af5a
7886a7 ¤   if (!s1 || !s2)
1838ec ¤   ¤   return (RingSet *)NULL;
b4af5a
fce895 ¤   pgpVirtMaskInit (s1->pool, &mask);
aaaf5a
935a54 ¤   pgpAssert(s1->pool == s2->pool);
d01ac8 ¤   pgpAssert(!RINGSETISMUTABLE(s1));
d20704 ¤   pgpAssert(!RINGSETISMUTABLE(s2));
98af5a
321d19 ¤   /* Do a few trivial cases without allocating bits. */
809dc5 ¤   pgpVirtMaskCopy (s1->pool, &s1->mask, &mask);
--39f4 0007ac26174401001ff Page 14 of pgpRngPub.c
a5c082 ¤   pgpVirtMaskANDNOT (s1->pool, &s2->mask, &mask);
c985f8 ¤   if (!pgpVirtMaskIsEmpty(&mask)) {¤  /* s1 is a subset of s2 - copy s1 */
f7e71a ¤   ¤   pgpVirtMaskCleanup (s1->pool, &mask);
a79fcc ¤   ¤   return ringSetCopy(s1);
0b9371 ¤   }
b8af5a
f1add4 ¤   pgpVirtMaskCopy (s1->pool, &s2->mask, &mask);
3ef093 ¤   pgpVirtMaskANDNOT (s1->pool, &s1->mask, &mask);
0280ef ¤   if (!pgpVirtMaskIsEmpty(&mask)) {¤  /* s2 is a subset of s1 - copy s2 */
8fe71a ¤   ¤   pgpVirtMaskCleanup (s1->pool, &mask);
72ba01 ¤   ¤   return ringSetCopy(s2);
879371 ¤   }
91af5a
e2ee6f ¤   set = ringSetCreate(s1->pool);
2702ad ¤   if (set) {
166c9b ¤   ¤   if (!ringSetIntersectList(s1->pool->keys, s1, s2, set))
5c5b34 ¤   ¤   {
9c2f54 ¤   ¤   ¤   /* Empty set - free bit */
0875c5 ¤   ¤   ¤   pgpVirtMaskANDNOT (s1->pool, &set->mask, &s1->pool->allocmask);
52be1a ¤   ¤   ¤   pgpVirtMaskCleanup (s1->pool, &set->mask);
bb0fe4 ¤   ¤   }
4d6318 ¤   ¤   set->type = RINGSET_IMMUTABLE;
c99371 ¤   }
0ededf ¤   pgpVirtMaskCleanup (s1->pool, &mask);
5e9329 ¤   return set;
d8efe6 }
fdaf5a
852978 static void
3ce413 ringSetDiffList(union RingObject *obj, RingSet const *s1, RingSet const *s2,
5d567c ¤   ¤   ¤   ¤   RingSet const *dest)
abbb36 {
fe1c05 ¤   while (obj) {
045d0d ¤   ¤   if (pgpIsRingSetMember(s1, obj) &&
c13220 ¤   ¤   ¤   !pgpIsRingSetMember(s2, obj)) {
14853c ¤   ¤   ¤   pgpVirtMaskOR (s1->pool, &dest->mask, &obj->g.mask);
79985a ¤   ¤   ¤   if (!OBJISBOT(obj))
d1b10e ¤   ¤   ¤   ¤   ringSetDiffList(obj->g.down, s1, s2, dest);
680fe4 ¤   ¤   }
fae2b6 ¤   ¤   obj = obj->g.next;
e09371 ¤   }
11efe6 }
88af5a
0c6c71 /* Return s1-s2. */
54e9eb RingSet *
11a25d ringSetDifference(RingSet const *s1, RingSet const *s2)
a4bb36 {
43c958 ¤   RingSet *set;
2a45d1 ¤   PGPVirtMask mask;
dfaf5a
0336c5 ¤   if (IsNull(s1))
d17ed2 ¤   ¤   return NULL;
c2fe4e ¤   if (IsNull(s2) || pgpVirtMaskIsEmpty(&s2->mask))
3d9fcc ¤   ¤   return ringSetCopy(s1);
e4af5a
755a54 ¤   pgpAssert(s1->pool == s2->pool);
581ac8 ¤   pgpAssert(!RINGSETISMUTABLE(s1));
5e0704 ¤   pgpAssert(!RINGSETISMUTABLE(s2));
2aaf5a
7be895 ¤   pgpVirtMaskInit (s1->pool, &mask);
5f9dc5 ¤   pgpVirtMaskCopy (s1->pool, &s1->mask, &mask);
73c082 ¤   pgpVirtMaskANDNOT (s1->pool, &s2->mask, &mask);
8fe060 ¤   if (pgpVirtMaskIsEmpty(&mask)) {
818231 ¤   ¤   /* s1->mask is a subset of s2->mask, so result is empty */
0c7727 ¤   ¤   set = ringSetAlloc(s1->pool);
21e00e ¤   ¤   if (set) {
26be1a ¤   ¤   ¤   pgpVirtMaskCleanup (s1->pool, &set->mask);
b86d54 ¤   ¤   ¤   set->type = RINGSET_IMMUTABLE;
0b0fe4 ¤   ¤   }
2ff037 ¤   } else {
6baf9c ¤   ¤   set = ringSetCreate(s1->pool);
ede00e ¤   ¤   if (set) {
7a0482 ¤   ¤   ¤   ringSetDiffList(s1->pool->keys, s1, s2, set);
--a88c 00058b7d3bd401001ff Page 15 of pgpRngPub.c
106d54 ¤   ¤   ¤   set->type = RINGSET_IMMUTABLE;
930fe4 ¤   ¤   }
209371 ¤   }
7adedf ¤   pgpVirtMaskCleanup (s1->pool, &mask);
079329 ¤   return set;
caefe6 }
5daf5a
4b4d2f int
e2c956 ringFileIsDirty(RingFile const *file)
abbb36 {
9b88e5 ¤   return file ? file->flags & RINGFILEF_DIRTY : 0;
65efe6 }
44af5a
984d2f int
4a77f5 ringFileIsTrustChanged(RingFile const *file)
94bb36 {
1ac4d8 ¤   return file ? file->flags & RINGFILEF_TRUSTCHANGED : 0;
d7efe6 }
9caf5a
015568 RingPool *
d23299 ringPoolCreate(PGPEnv const *env)
78bb36 {
fd8642 ¤   RingPool *pool;
7ac640 ¤   PGPContextRef¤  context¤= pgpenvGetContext( env );
1caf5a
f2db76 ¤   pool = (RingPool *)pgpContextMemAlloc( context,
85359c ¤   ¤   sizeof(*pool), kPGPMemoryMgrFlags_Clear );
257494 ¤   if (pool)
afcc54 ¤   ¤   ringPoolInit( context, pool, env);
0af0f7 ¤   return pool;
00efe6 }
d9af5a
2c314a void
7d1ee6 ringPoolDestroy(RingPool *pool)
1cbb36 {
c480e9 ¤   if (pool) {
a2d627 ¤   ¤   PGPContextRef cdkContext = pool->context;
6ec9c4 ¤   ¤   ringPoolFini(pool);
b31641 ¤   ¤   pgpContextMemFree( cdkContext, pool);
8c9371 ¤   }
7cefe6 }
7aaf5a
1a5d4d PGPContextRef
38a997 ringPoolContext(RingPool *pool)
efbb36 {
f18fd9 ¤   pgpAssert( pool );
b3be5d ¤   return pool->context;
e3efe6 }
40af5a
38614e union RingObject *
35af38 ringKeyById8(
0d7e9b ¤   RingSet const *¤¤   set,
10e99f ¤   PGPByte¤¤   ¤   ¤   pkalg,
c9e4b5 ¤   PGPByte const *¤¤   keyID)
cbbb36 {
96d9e1 ¤   RingKey *key;
a7af5a
23f059 ¤   if ((pkalg|1) == 3)¤/* viacrypt */
4669b0 ¤   ¤   pkalg = 1;
d9c677 ¤   for (key = set->pool->hashtable[keyID[0]]; key; key = key->util) {
bdd9d9 ¤   ¤   if ((((key->pkalg|1) == 3) ? 1 : key->pkalg) == pkalg &&
1ba53e ¤   ¤   ····memcmp(keyID, key->keyID, 8) == 0) {
ce3cbd ¤   ¤   ¤   if (!pgpIsRingSetMember(set, (union RingObject *)key))
4ef622 ¤   ¤   ¤   ¤   break;
c4cb12 ¤   ¤   ¤   ringObjectHold((union RingObject *)key);
9f26ef ¤   ¤   ¤   return (union RingObject *)key;
b80fe4 ¤   ¤   }
209371 ¤   }
2b9442 ¤   /* Failed */
4c3f59 ¤   return NULL;
dfefe6 }
58af5a
--b631 000c1ec7b02401001ff Page 16 of pgpRngPub.c
0cb177 #if 0
1c614e union RingObject *
000a9b ringKeyById4(
f67e9b ¤   RingSet const *¤¤   set,
c7e99f ¤   PGPByte¤¤   ¤   ¤   pkalg,
2ee4b5 ¤   PGPByte const *¤¤   keyID)
23bb36 {
dfd9e1 ¤   RingKey *key;
b5fe8d ¤   RingKey *bestKey = NULL;
f1af5a
14f059 ¤   if ((pkalg|1) == 3)¤/* viacrypt */
2769b0 ¤   ¤   pkalg = 1;
a21b52 ¤   ¤
6383db ¤   for (key = set->pool->hashtable[keyID[0]]; key; key = key->util)
e7c7a1 ¤   {
01d9d9 ¤   ¤   if ((((key->pkalg|1) == 3) ? 1 : key->pkalg) == pkalg &&
01fe2a ¤   ¤   ····memcmp(keyID, &key->keyID[4], 4) == 0)
965b34 ¤   ¤   {
d1e8c5 ¤   ¤   ¤   if (pgpIsRingSetMember(set, (union RingObject *)key))
d2f776 ¤   ¤   ¤   {
ebe763 ¤   ¤   ¤   ¤   if( IsNull( bestKey ) )
dd72c3 ¤   ¤   ¤   ¤   {
b26997 ¤   ¤   ¤   ¤   ¤   bestKey = key;
e62613 ¤   ¤   ¤   ¤   }
0ffa07 ¤   ¤   ¤   ¤   else
8972c3 ¤   ¤   ¤   ¤   {
91911e ¤   ¤   ¤   ¤   ¤   /* Non-unique match. Fail */
188b31 ¤   ¤   ¤   ¤   ¤   bestKey = NULL;
a714c3 ¤   ¤   ¤   ¤   ¤   break;
3d2613 ¤   ¤   ¤   ¤   }
03a3a6 ¤   ¤   ¤   }
9a0fe4 ¤   ¤   }
829371 ¤   }
b067c5 ¤
66ca19 ¤   if( IsntNull( bestKey ) )
13c7a1 ¤   {
ff4698 ¤   ¤   ringObjectHold((union RingObject *)bestKey);
ac9371 ¤   }
b17bdc ¤   return (union RingObject *)bestKey;
12efe6 }
33db21 #else
3f614e union RingObject *
7a0a9b ringKeyById4(
ef7e9b ¤   RingSet const *¤¤   set,
65e99f ¤   PGPByte¤¤   ¤   ¤   pkalg,
9fe4b5 ¤   PGPByte const *¤¤   keyID)
3ebb36 {
01b9df ¤   union RingObject *key, *subkey;
01f7e0 ¤   union RingObject *bestKey = NULL;
daaf5a
93f059 ¤   if ((pkalg|1) == 3)¤/* viacrypt */
6669b0 ¤   ¤   pkalg = 1;
4e1b52 ¤   ¤
bc7df6 ¤   for (key = set->pool->keys; key; key = key->g.next)
85c7a1 ¤   {
dc6825 ¤   ¤   if ((((key->k.pkalg|1) == 3) ? 1 : key->k.pkalg) == pkalg &&
f9e61d ¤   ¤   ····memcmp(keyID, &key->k.keyID[4], 4) == 0)
1a5b34 ¤   ¤   {
5a1759 ¤   ¤   ¤   if (pgpIsRingSetMember(set, key))
20f776 ¤   ¤   ¤   {
dde763 ¤   ¤   ¤   ¤   if( IsNull( bestKey ) )
d072c3 ¤   ¤   ¤   ¤   {
6e6997 ¤   ¤   ¤   ¤   ¤   bestKey = key;
992613 ¤   ¤   ¤   ¤   }
f7fa07 ¤   ¤   ¤   ¤   else
8272c3 ¤   ¤   ¤   ¤   {
41911e ¤   ¤   ¤   ¤   ¤   /* Non-unique match. Fail */
1d8b31 ¤   ¤   ¤   ¤   ¤   bestKey = NULL;
f8e3d2 ¤   ¤   ¤   ¤   ¤   goto exit;
372613 ¤   ¤   ¤   ¤   }
8da3a6 ¤   ¤   ¤   }
c10fe4 ¤   ¤   }
--9cd5 000615343b7401001ff Page 17 of pgpRngPub.c
f11b52 ¤   ¤
b48be5 ¤   ¤   for (subkey = key->g.down; subkey; subkey = subkey->g.next)
695b34 ¤   ¤   {
f79ae8 ¤   ¤   ¤   if ((((subkey->k.pkalg|1) == 3) ? 1 : subkey->k.pkalg) == pkalg &&
7e549d ¤   ¤   ¤   ····memcmp(keyID, &subkey->k.keyID[4], 4) == 0)
a9f776 ¤   ¤   ¤   {
438b5b ¤   ¤   ¤   ¤   if (pgpIsRingSetMember(set, subkey))
e872c3 ¤   ¤   ¤   ¤   {
0f6f05 ¤   ¤   ¤   ¤   ¤   if( IsNull( bestKey ) )
274859 ¤   ¤   ¤   ¤   ¤   {
6798ae ¤   ¤   ¤   ¤   ¤   ¤   bestKey = subkey;
341c89 ¤   ¤   ¤   ¤   ¤   }
2e4bd6 ¤   ¤   ¤   ¤   ¤   else
024859 ¤   ¤   ¤   ¤   ¤   {
e9c205 ¤   ¤   ¤   ¤   ¤   ¤   /* Non-unique match. Fail */
904e64 ¤   ¤   ¤   ¤   ¤   ¤   bestKey = NULL;
766fad ¤   ¤   ¤   ¤   ¤   ¤   goto exit;
c11c89 ¤   ¤   ¤   ¤   ¤   }
e02613 ¤   ¤   ¤   ¤   }
41a3a6 ¤   ¤   ¤   }
3e0fe4 ¤   ¤   }
689371 ¤   }
9caf5a
cabb53 exit:
38af5a
7bca19 ¤   if( IsntNull( bestKey ) )
a9c7a1 ¤   {
4eb217 ¤   ¤   ringObjectHold( bestKey );
e29371 ¤   }
0367c5 ¤
818647 ¤   return bestKey;
1fefe6 }
687454 #endif
b6af5a
cef48a /*** Access functions for information about objects ***/
f0af5a
ae4d2f int
51ce30 ringKeyError(RingSet const *set, union RingObject *key)
77bb36 {
de8b0f ¤   PGPByte const *p;
dd875f ¤   PGPSize len;
70af5a
1794a2 ¤   pgpAssert(OBJISKEY(key));
ee4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
4baf5a
5526a8 ¤   if (!(key->g.flags & KEYF_ERROR))
12bbde ¤   ¤   return 0;
04af5a
7c55bd ¤   p = (PGPByte const *)ringFetchObject(set, key, &len);
844dda ¤   if (!p)
ede1c3 ¤   ¤   return ringSetError(set)->error;
4cdc34 ¤   return ringKeyParse(set->pool->context, p, len, NULL, NULL, NULL, NULL,
29f33f ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, 0);
76efe6 }
76af5a
c4536c unsigned
29b5e1 ringKeyBits(RingSet const *set, union RingObject *key)
ddbb36 {
2694a2 ¤   pgpAssert(OBJISKEY(key));
984abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
3f8a21 ¤   (void)set;
2cc90f ¤   return key->k.keybits;
88efe6 }
edaf5a
11bccf PGPUInt32
c4d78a ringKeyCreation(RingSet const *set, union RingObject *key)
e4bb36 {
1294a2 ¤   pgpAssert(OBJISKEY(key));
0f4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
d88a21 ¤   (void)set;
64edc9 ¤   return key->k.tstamp;
61efe6 }
--3ad7 00096672cc8401001ff Page 18 of pgpRngPub.c
e0af5a
04bccf PGPUInt32
04f879 ringKeyExpiration(RingSet const *set, union RingObject *key)
0cbb36 {
9e94a2 ¤   pgpAssert(OBJISKEY(key));
894abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
1a8a21 ¤   (void)set;
7dcaf6 ¤   if (key->k.tstamp == 0 || key->k.validity == 0)
cdccba ¤   ¤   return 0; ···/* valid indefinitely */
d90e24 ¤   else
a261f5 ¤   ¤   return key->k.tstamp + (key->k.validity * 3600 * 24);
44efe6 }
8aaf5a
f038e5 /*
a47510 ·* If called for a subkey, force to just encryption.
6d01b8 ·* If called for a key with a subkey, return the "or" of both.
22873c ·* Else just do the key itself.
3c3eb2 ·* Internal form of ringKeyUse - if unExpired is true, check that the
0eed12 ·* subkeys are unexpired before saying it has encryption usage.
c5b0e5 ·* ringKeyUse and ringKeyUnexpiredUse are macros that call this now.
57495d ·*/
074d2f int
9db51d ringKeyUseInternal(RingSet const *set, union RingObject *key,
dfa411 ¤   ¤   ¤   ¤   ···PGPBoolean unExpired)
84bb36 {
96b68d ¤   int use;
62af5a
e394a2 ¤   pgpAssert(OBJISKEY(key));
b44abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
bdaf5a
2e22a7 ¤   use = pgpKeyUse(pgpPkalgByNumber(key->k.pkalg));
b683f5 ¤   if (OBJISSUBKEY(key))
adae0e ¤   ¤   use &= PGP_PKUSE_ENCRYPT;
e3121e ¤   for (key=key->g.down; key; key=key->g.next) {
bdffc3 ¤   ¤   if (pgpIsRingSetMember(set, key) &&
0fed57 ¤   ¤   ¤   OBJISSUBKEY(key) && ringSubkeyValid(set, key, unExpired))
2bf10b ¤   ¤   ¤   use |= pgpKeyUse(pgpPkalgByNumber(key->k.pkalg));
109371 ¤   }
b7ffc3 ¤   return use;
1fefe6 }
2eaf5a
0eaf5a
b65d74 PGPByte
bdd6fc ringKeyTrust(RingSet const *set, union RingObject *key)
66bb36 {
3794a2 ¤   pgpAssert(OBJISKEY(key));
fa4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
d88a21 ¤   (void)set;
11aa17 ¤   if (!(key->g.flags & (RINGOBJF_TRUST)))
e80889 ¤   ¤   ringMntValidateKey (set, key);¤
7368ca ¤   return pgpMax(key->k.trust & kPGPKeyTrust_Mask,
af53bd ¤   ¤   ¤   ¤   ··key->k.signedTrust & kPGPKeyTrust_Mask);
67efe6 }
d9af5a
cf314a void
283b33 ringKeySetTrust(RingSet const *set, union RingObject *key, PGPByte trust)
0ebb36 {
2e94a2 ¤   pgpAssert(OBJISKEY(key));
184abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
583865 ¤   pgpAssert(trust==kPGPKeyTrust_Unknown ·|| trust==kPGPKeyTrust_Never ||
1d3b05 ¤   ·······trust==kPGPKeyTrust_Marginal || trust==kPGPKeyTrust_Complete);
069c30 ¤   pgpAssert (!(key->k.trust & PGP_KEYTRUSTF_BUCKSTOP));
f9575e ¤   if (key->k.trust & (PGP_KEYTRUSTF_REVOKED | PGP_KEYTRUSTF_EXPIRED))
cf2ec1 ¤   ····return;
2f77b4 ¤   if ((key->k.trust & kPGPKeyTrust_Mask) != trust) {
439b8f ¤   ¤   key->k.trust = (key->k.trust & ~kPGPKeyTrust_Mask) + trust;
a1c7cb ¤   ¤   key->g.flags |= RINGOBJF_TRUSTCHANGED;
1f10d9 ¤   ¤   ringPoolMarkTrustChanged (set->pool, &key->g.mask);
569371 ¤   }
952ef5 ¤   key->g.flags |= RINGOBJF_TRUST;
6eefe6 }
96af5a
--f89e 000ee569d92401001ff Page 19 of pgpRngPub.c
e0af5a
d338e5 /*
6e0630 ·* Used to set a key as an "axiomatic" key, that is, one for which
fe7d22 ·* we hold the private key. ·This also involves setting each name on that
aeea8b ·* key as having complete validity.
31495d ·*/
e8314a void
07f773 ringKeySetAxiomatic(RingSet const *set, union RingObject *key)
26bb36 {
c218d8 ¤   union RingObject *name = NULL;
abaf5a
82c364 ¤   (void)name;
a89614 ····pgpAssert(OBJISKEY(key));
1e4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
85fdc1 ····if (!ringKeyIsSec (set, key) ||·
b74e98 ¤   key->k.trust & (PGP_KEYTRUSTF_BUCKSTOP | PGP_KEYTRUSTF_REVOKED))
289a66 ········return; ·······/* already axiomatic or can't set */
b74e2c ····key->k.trust &= ~kPGPKeyTrust_Mask;
152e22 ····key->k.trust |= (PGP_KEYTRUSTF_BUCKSTOP | kPGPKeyTrust_Ultimate);
7778ca ····ringPoolMarkTrustChanged (set->pool, &key->g.mask);
6128bd ····key->g.flags |= (RINGOBJF_TRUSTCHANGED | RINGOBJF_TRUST);
837dec #if PGPTRUSTMODEL>0
da45ef ¤   /* Make sure all names have axiomatic confidence */
8f507b ¤   for (name=key->g.down; name; name=name->g.next) {
7768be ¤   ¤   if (OBJISNAME(name) && pgpIsRingSetMember(set, name))
86772f ¤   ¤   ¤   name->n.confidence = PGP_NEWTRUST_INFINITE;
4c9371 ¤   }
267454 #endif
9fefe6 }
18af5a
09af5a
ef793a /* ·Reset an axiomatic key. ·Trust is set to undefined. */
21af5a
9b314a void
0e160f ringKeyResetAxiomatic (RingSet const *set, union RingObject *key)
91bb36 {
f918d8 ¤   union RingObject *name = NULL;
d6af5a
6bc364 ¤   (void)name;
4f9614 ····pgpAssert(OBJISKEY(key));
0a4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
e252b0 ····if (!(key->k.trust & PGP_KEYTRUSTF_BUCKSTOP))
e46cfd ········return; ··········/* not axiomatic */
3c44f4 ····key->k.trust &= ~PGP_KEYTRUSTF_BUCKSTOP;
4e9a11 ····key->k.trust = (key->k.trust & ~kPGPKeyTrust_Mask) +·
6e8580 ···························kPGPKeyTrust_Undefined;
b678ca ····ringPoolMarkTrustChanged (set->pool, &key->g.mask);
da28bd ····key->g.flags |= (RINGOBJF_TRUSTCHANGED | RINGOBJF_TRUST);
907dec #if PGPTRUSTMODEL>0
5c7450 ¤   /* Make sure all names have undefined confidence */
ec507b ¤   for (name=key->g.down; name; name=name->g.next) {
2f68be ¤   ¤   if (OBJISNAME(name) && pgpIsRingSetMember(set, name))
c4069b ¤   ¤   ¤   name->n.confidence = PGP_NEWTRUST_UNDEFINED;
069371 ¤   }
147454 #endif
9befe6 }
26af5a
c04d2f int
37a641 ringKeyAxiomatic(RingSet const *set, union RingObject *key)
8dbb36 {
8bf5b8 ¤   (void)set;¤ /* Avoid warning */
bf94a2 ¤   pgpAssert(OBJISKEY(key));
8a4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
f17f14 ¤   return key->k.trust & PGP_KEYTRUSTF_BUCKSTOP;
5befe6 }
00af5a
73af5a
09312d /* Return TRUE if the key is a subkey */
034d2f int
f25126 ringKeyIsSubkey (RingSet const *set, union RingObject const *key)
0cbb36 {
ee115b ·····(void)set;
--a354 0000504fd3b401001ff Page 20 of pgpRngPub.c
cda4fa ·····return OBJISSUBKEY(key);
90efe6 }
acaf5a
54af5a
c84d2f int
556069 ringKeyDisabled(RingSet const *set, union RingObject *key)
65bb36 {
14f5b8 ¤   (void)set;¤ /* Avoid warning */
4194a2 ¤   pgpAssert(OBJISKEY(key));
564abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
1f08f3 ¤   return key->k.trust & PGP_KEYTRUSTF_DISABLED;
9fefe6 }
2eaf5a
a5314a void
b07ddc ringKeyDisable(RingSet const *set, union RingObject *key)
00bb36 {
c694a2 ¤   pgpAssert(OBJISKEY(key));
b24abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
7865ea ¤   if (!(key->k.trust & PGP_KEYTRUSTF_DISABLED)) {
927348 ¤   ¤   key->k.trust |= PGP_KEYTRUSTF_DISABLED;
6cc7cb ¤   ¤   key->g.flags |= RINGOBJF_TRUSTCHANGED;
c510d9 ¤   ¤   ringPoolMarkTrustChanged (set->pool, &key->g.mask);
e99371 ¤   }
5b2ef5 ¤   key->g.flags |= RINGOBJF_TRUST;
18efe6 }
5faf5a
a3314a void
a5bbe1 ringKeyEnable(RingSet const *set, union RingObject *key)
b9bb36 {
2b94a2 ¤   pgpAssert(OBJISKEY(key));
904abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
1f6f39 ¤   if (key->k.trust & PGP_KEYTRUSTF_DISABLED) {
aef4ff ¤   ¤   key->k.trust &= ~PGP_KEYTRUSTF_DISABLED;
d4c7cb ¤   ¤   key->g.flags |= RINGOBJF_TRUSTCHANGED;
7b10d9 ¤   ¤   ringPoolMarkTrustChanged (set->pool, &key->g.mask);
e29371 ¤   }
0d2ef5 ¤   key->g.flags |= RINGOBJF_TRUST;
5aefe6 }
0aaf5a
7faf5a
0faf5a
4c4d2f int
e6437c ringKeyRevoked(RingSet const *set, union RingObject *key)
8ebb36 {
9194a2 ¤   pgpAssert(OBJISKEY(key));
554abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
298a21 ¤   (void)set;
ab7dec #if PGPTRUSTMODEL>0
f0aa17 ¤   if (!(key->g.flags & (RINGOBJF_TRUST)))
a185f6 ¤   ¤   ringMntValidateKey (set, key);
587454 #endif
55bbb7 ¤   return key->k.trust & PGP_KEYTRUSTF_REVOKED;
49efe6 }
6aaf5a
6baf5a
6495d7 /*·
0b351e ·* Return true if the specified signature has been revoked, that is,
cdd7f4 ·* if there is a newer signature by the same key which is of type
24a4ac ·* UID_REVOKE.
cd495d ·*/
5e4d2f int
98a551 ringSigRevoked (RingSet const *set, union RingObject *sig)
d8bb36 {
a99a87 ¤   RingObject¤ ¤   *parent,
571187 ¤   ¤   ¤   ¤   ¤   *sibling;
2eaf5a
d1f5b8 ¤   (void)set;¤ /* Avoid warning */
bf7d94 ¤   pgpAssert (OBJISSIG(sig));
39c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
acaf5a
828448 ¤   /* Sigs can be declared irrevocable at creation time */
05d8b8 ¤   if (!SIGISREVOCABLE(&sig->s))
--b8a7 000e17218bc401001ff Page 21 of pgpRngPub.c
5b98aa ¤   ¤   return FALSE;
22af5a
4ab687 ¤   parent = sig->g.up;
488dc9 ¤   for (sibling = parent->g.down; sibling ; sibling = sibling->g.next) {
918e61 ¤   ¤   if (!OBJISSIG(sibling) || sibling == sig)
5717f5 ¤   ¤   ¤   continue;
6aa91f ¤   ¤   if (sibling->s.by == sig->s.by) {
8eeb0e ¤   ¤   ¤   if (sibling->s.trust & PGP_SIGTRUSTF_CHECKED) {
25f042 ¤   ¤   ¤   ¤   if (sibling->s.tstamp > sig->s.tstamp) {
ee5780 ¤   ¤   ¤   ¤   ¤   if (sibling->s.type == PGP_SIGTYPE_KEY_UID_REVOKE) {
ec4bf9 ¤   ¤   ¤   ¤   ¤   ¤   /* Valid revocation */
0480de ¤   ¤   ¤   ¤   ¤   ¤   return TRUE;
711c89 ¤   ¤   ¤   ¤   ¤   }
4d2613 ¤   ¤   ¤   ¤   }
6ea3a6 ¤   ¤   ¤   }
320fe4 ¤   ¤   }
739371 ¤   }
3da230 ¤   return FALSE;
93efe6 }
d1af5a
40af5a
c80f96 PgpTrustModel
445189 pgpTrustModel (RingPool const *pool)
16bb36 {
4a7ca6 ¤   (void)pool;
3f1325 #if PGPTRUSTMODEL==0
438d08 ¤   return PGPTRUST0;
317454 #endif
e80afd #if PGPTRUSTMODEL==1
40d7d4 ¤   return PGPTRUST1;
197454 #endif
cb2095 #if PGPTRUSTMODEL==2
4438b0 ¤   return PGPTRUST2;
307454 #endif
52efe6 }
f4af5a
d66e17 PGPUInt16
1ed375 ringKeyConfidence(RingSet const *set, union RingObject *key)
d5bb36 {
541325 #if PGPTRUSTMODEL==0
b88a21 ¤   (void)set;
679b3e ¤   (void)key;
d54aac ¤   pgpAssert(0);
ab3e6b ¤   return 0;
fadb21 #else
9d94a2 ¤   pgpAssert(OBJISKEY(key));
714abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
678a21 ¤   (void)set;
eeaf5a
8f9ead ¤   /* Don't try on-the-fly validation, assume it's been done */
be8859 ¤   /* if (!(key->g.flags & (RINGOBJF_TRUST))) */
80caff ¤   /* ¤ringMntValidateKey (set, key); */
f7af5a
fbafa8 ¤   /* ·ringKeyCalcTrust handles revoked/expired keys */
c51059 ¤   return ringKeyCalcTrust (set, key);
c17454 #endif
a0efe6 }
2caf5a
a6314a void
fba99b ringKeyID8(
7c0fee ¤   RingSet const *set,
34f6b6 ¤   union RingObject const *key,
c96500 ¤   PGPByte *pkalg,
6d0d45 ¤   PGPKeyID *keyID)
a6bb36 {
3594a2 ¤   pgpAssert(OBJISKEY(key));
274abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
e68a21 ¤   (void)set;
bb5f4a ¤   if (pkalg) {
b85b09 ¤   ¤   *pkalg = key->k.pkalg;
417392 ¤   ¤   if ((*pkalg | 1) == 3)¤ ¤   /* ViaCrypt */
e13e79 ¤   ¤   ¤   *pkalg = 1;
--3492 00088aa5ceb401001ff Page 22 of pgpRngPub.c
a19371 ¤   }
310a73 ¤   if (keyID)
d8c7a1 ¤   {
d9bd44 ¤   ¤   pgpNewKeyIDFromRawData( key->k.keyID, 8, keyID );
4e9371 ¤   }
89efe6 }
ddaf5a
67314a void
4d0c38 ringKeyID4(
880fee ¤   RingSet const *set,
0af6b6 ¤   union RingObject const *key,
516500 ¤   PGPByte *pkalg,
fc0d45 ¤   PGPKeyID *keyID)
c7bb36 {
d194a2 ¤   pgpAssert(OBJISKEY(key));
b34abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
7a8a21 ¤   (void)set;
b15f4a ¤   if (pkalg) {
7a5b09 ¤   ¤   *pkalg = key->k.pkalg;
ed7392 ¤   ¤   if ((*pkalg | 1) == 3)¤ ¤   /* ViaCrypt */
2d3e79 ¤   ¤   ¤   *pkalg = 1;
dc9371 ¤   }
d40a73 ¤   if (keyID)
91c7a1 ¤   {
483bab ¤   ¤   pgpNewKeyIDFromRawData( &key->k.keyID[4], 4, keyID );
679371 ¤   }
2befe6 }
47af5a
307750 PGPBoolean
d95842 ringKeyV3(RingSet const *set, union RingObject const *key)
efbb36 {
8b94a2 ¤   pgpAssert(OBJISKEY(key));
264abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
6d8a21 ¤   (void)set;
fd8f4f ¤   return !!KEYISV3(&key->k);
77efe6 }
5caf5a
eb4d2f int
21935f ringKeyFingerprint16(RingSet const *set, union ·RingObject *key,
b67478 ¤   PGPByte *buf)
bdbb36 {
f08b0f ¤   PGPByte const *p;
6e875f ¤   PGPSize len;
b0af5a
3f94a2 ¤   pgpAssert(OBJISKEY(key));
444abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
38af5a
3c55bd ¤   p = (PGPByte const *)ringFetchObject(set, key, &len);
ea4dda ¤   if (!p)
d6e1c3 ¤   ¤   return ringSetError(set)->error;
64be97 ¤   return ringKeyParseFingerprint16(set->pool->context, p, len, buf);
99efe6 }
80af5a
c84d2f int
3875e5 ringKeyFingerprint20(RingSet const *set, union RingObject *key,
aa7478 ¤   PGPByte *buf)
6fbb36 {
3cd321 ¤   PGPSize objlen;
7c74e7 ¤   PGPByte const *objbuf;
84af5a
3494a2 ¤   pgpAssert(OBJISKEY(key));
b74abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
10af5a
57f99b ¤   objbuf = (PGPByte const *)ringFetchObject(set, key, &objlen);
da6294 ¤   return pgpFingerprint20HashBuf(set->pool->context, objbuf, objlen, buf);
dfefe6 }
4daf5a
7d4d2f int
9455c9 ringKeyAddSigsby(RingSet const *set, union RingObject *key,
0d3df4 ¤   RingSet *dest)
2abb36 {
88a51a ¤   RingSig *sig;
--8440 000ad45c446401001ff Page 23 of pgpRngPub.c
828034 ¤   int i = 0;
18af5a
b5f3f5 ¤   pgpAssert(OBJISTOPKEY(key));
6e4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
31e3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
22af5a
e3d8da ¤   for (sig = &key->k.sigsby->s; sig; sig = sig->nextby) {
379501 ¤   ¤   if (pgpIsRingSetMember(set, (union RingObject *)sig)) {
4481ec ¤   ¤   ¤   i++;
218b99 ¤   ¤   ¤   ringSetAddObject(dest, (union RingObject *)sig);
a00fe4 ¤   ¤   }
4f9371 ¤   }
c22196 ¤   return i;
ddefe6 }
9caf5a
ab92cf /* Return TRUE if the key has a secret in the given set */
044d2f int
16ec91 ringKeyIsSec(RingSet const *set, union RingObject *key)
cfbb36 {
2c94a2 ¤   pgpAssert(OBJISKEY(key));
1a4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
e9af5a
994cc5 ¤   for (key = key->g.down; key; key = key->g.next)
0c7af1 ¤   ¤   if (pgpIsRingSetMember(set, key) && OBJISSEC(key))
a3db98 ¤   ¤   ¤   return 1;
ec3e6b ¤   return 0;
baefe6 }
7faf5a
d038e5 /*
7b158a ·* Return TRUE if the key comes only from sources where it has secret
9c671e ·* objects. ·In other words, the key comes from a secret key ring. ·This
a6a07e ·* is used in adding that key so that we only add it to the secret ring,
919d3f ·* which is necessary due to complications relating to the "version bug".
207a14 ·* Otherwise if we add a secret keyring we may end up putting the key on
324654 ·* the pubring, and it could have the incorrect version.
a047a5 ·* (See pgpRngRead.c for discussion of the version bug.)
843957 ·* Don't count if just on MEMRING, otherwise newly created keys return TRUE.
78495d ·*/
c24d2f int
5cd1a1 ringKeyIsSecOnly(RingSet const *set, union RingObject *key)
03bb36 {
976032 ¤   RingPool *pool = set->pool;
1729e2 ¤   PGPVirtMask keyfilemask;
383897 ¤   PGPVirtMask secfilemask;
600f91 ¤   PGPBoolean seconly;
20af5a
f3ed19 ¤   pgpVirtMaskInit (pool, &keyfilemask);
04c922 ¤   pgpVirtMaskInit (pool, &secfilemask);
75af5a
dfae60 ¤   pgpVirtMaskCopy (pool, &key->g.mask, &keyfilemask);
3e9b68 ¤   pgpVirtMaskAND (pool, &pool->filemask, &keyfilemask);
5caf5a
10c624 ¤   if (pgpVirtMaskIsEqual (&keyfilemask, &pool->memringmask)) {
ce28fa ¤   ¤   pgpVirtMaskCleanup (pool, &keyfilemask);
c20cc1 ¤   ¤   pgpVirtMaskCleanup (pool, &secfilemask);
b79499 ¤   ¤   return 0;¤  ¤   ¤   /* Newly generated keys */
569371 ¤   }
6f1b52 ¤   ¤
3ccaec ¤   /* Accumulate all sec objects into secfilemask */
54f70d ¤   for (key = key->g.down; key; key = key->g.next) {
91727a ¤   ¤   if (pgpIsRingSetMember(set, key) && OBJISSEC(key)) {
72a96b ¤   ¤   ¤   pgpVirtMaskOR (pool, &key->g.mask, &secfilemask);
bc0fe4 ¤   ¤   }
849371 ¤   }
11bf53 ¤   pgpVirtMaskAND (pool, &pool->filemask, &secfilemask);
acbae1 ¤   pgpVirtMaskANDNOT (pool, &secfilemask, &keyfilemask);
52ba7d ¤   seconly = pgpVirtMaskIsEmpty(&keyfilemask);
4daf5a
6a7a67 ¤   pgpVirtMaskCleanup (pool, &keyfilemask);
3a5e5c ¤   pgpVirtMaskCleanup (pool, &secfilemask);
b6af5a
ad51d4 ¤   return seconly;
--e412 000cdc20224401001ff Page 24 of pgpRngPub.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
01b61b ·* Return the most recent subkey associated with the key, if there is one.
35495d ·*/
ba614e union RingObject *
898ead ringKeySubkey(RingSet const *set, union RingObject const *key)
d5bb36 {
9a39f8 ¤   union RingObject *obj, *best = NULL;
80d7f4 ¤   PGPUInt32 objtime, besttime = 0;
a8af5a
1894a2 ¤   pgpAssert(OBJISKEY(key));
eb974c ¤   for (obj = key->g.down; obj; obj = obj->g.next) {
4a2302 ¤   ¤   if (pgpIsRingSetMember(set, obj) && OBJISSUBKEY(obj)
2f9f85 ¤   ¤   ····&& ringSubkeyValid(set, obj, TRUE)) {
93aa2a ¤   ¤   ¤   objtime = ringKeyCreation(set, obj);
054a03 ¤   ¤   ¤   if (besttime <= objtime) {
f2fa83 ¤   ¤   ¤   ¤   best = obj;
93b07e ¤   ¤   ¤   ¤   besttime = objtime;
82a3a6 ¤   ¤   ¤   }
320fe4 ¤   ¤   }
da9371 ¤   }
e3e17b ¤   return best;
5cefe6 }
6faf5a
14f712 /* Given a subkey, return its master key */
10614e union RingObject *
460dcf ringKeyMasterkey (RingSet const *set, union RingObject const *subkey)
fabb36 {
6c8a21 ¤   (void)set;
c1af5a
8b7e7d ¤   pgpAssert (OBJISSUBKEY(subkey));
eaa35a ¤   pgpAssert (OBJISTOPKEY(subkey->g.up));
3f28bf ¤   return subkey->g.up;
53efe6 }
ceaf5a
fcaf5a
ee38e5 /*
5f9e9e ·* Given a public key on the keyring, get the corresponding PGPPubKey.
35e2d3 ·* Use is a usage code which limits the kinds of keys we will accept.
40f868 ·* For keys which have subkeys this chooses which one to use. ·If use is
7025ed ·* 0 we do a straight conversion of the key or subkey; if nonzero we
13ff3a ·* verify that the key has the required use. ·Return NULL if we can't
5cce94 ·* get a key with the required use.
fc495d ·*/
aa40b4 PGPPubKey *
a210ff ringKeyPubKey(RingSet const *set, union RingObject *key, int use)
dbbb36 {
808b0f ¤   PGPByte const *p;
66875f ¤   PGPSize len;
54a299 ¤   PGPPubKey *pub;
298ada ¤   union RingObject *subkey = NULL;
916932 ¤   unsigned vsize;
22d54b ¤   PGPError i;
9a8a97 ¤   PGPContextRef¤  context;
80af5a
6a090d ¤   pgpAssertAddrValid( set, RingSet );
3a250c ¤   pgpAssertAddrValid( set->pool, RingPool );
791daf ¤   context¤= set->pool->context;
9eaf5a
4394a2 ¤   pgpAssert(OBJISKEY(key));
ad4abb ¤   pgpAssert(pgpIsRingSetMember(set, key));
a2af5a
714924 ¤   /* Select between subkey and key if necessary */
7e0731 ¤   if (use && ·(OBJISSUBKEY(key)
690a1e ¤   ¤   ¤   || ((subkey=ringKeySubkey(set, key)) != NULL))) {
da8e1f ¤   ¤   if (use == PGP_PKUSE_SIGN_ENCRYPT) {
8002bb ¤   ¤   ¤   ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
0dcf03 ¤   ¤   ¤   return NULL;
b20fe4 ¤   ¤   }
cd7a10 ¤   ¤   if (use == PGP_PKUSE_ENCRYPT) {
--9c4e 000ed2f90aa401001ff Page 25 of pgpRngPub.c
a13cdb ¤   ¤   ¤   if (OBJISTOPKEY(key)) {
96ee0c ¤   ¤   ¤   ¤   pgpAssert(subkey);
435a07 ¤   ¤   ¤   ¤   key = subkey;
46e6ed ¤   ¤   ¤   ¤   pgpAssert (OBJISSUBKEY(key));
4fa3a6 ¤   ¤   ¤   }
fead80 ¤   ¤   } else if (use == PGP_PKUSE_SIGN) {
1859f6 ¤   ¤   ¤   if (OBJISSUBKEY(key)) {
9deb59 ¤   ¤   ¤   ¤   key = key->g.up;
97fdeb ¤   ¤   ¤   ¤   pgpAssert (OBJISTOPKEY(key));
6fa3a6 ¤   ¤   ¤   }
4d0fe4 ¤   ¤   }
5f9371 ¤   }
a7af5a
d02906 ¤   /* Verify key satisfies required usage */
6e28f7 ¤   if (use && ((pgpKeyUse(pgpPkalgByNumber(key->k.pkalg)) & use) != use)){
654ccc ¤   ¤   ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
337ed2 ¤   ¤   return NULL;
f39371 ¤   }
06af5a
c155bd ¤   p = (PGPByte const *)ringFetchObject(set, key, &len);
cc4dda ¤   if (!p)
9c7ed2 ¤   ¤   return NULL;
53e442 ¤   if (key->g.flags & KEYF_ERROR || len < 8) {
3fc60f ¤   ¤   i = (PGPError)ringKeyParse(context, p, len, NULL, NULL, NULL, NULL,
479b52 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL, 0);
90f584 ¤   ¤   ringSimpleErr(set->pool, i);
337ed2 ¤   ¤   return NULL;
8a9371 ¤   }
35d8af ¤   /*
284e4c ¤   ·* A key starts with 5 or 7 bytes of data, an algorithm byte, and
fa3ce0 ¤   ·* the public components.
48a4e3 ¤   ·*/
e89631 ¤   if (p[0] == PGPVERSION_4) {
6373d8 ¤   ¤   vsize = 0;
c0f037 ¤   } else {
5ac660 ¤   ¤   vsize = 2;
0a9371 ¤   }
ef873e ¤   pgpAssert(p[5+vsize] == key->k.pkalg);¤ /* Checked by ringKeyVerify */
968b0f ¤   pub = pgpPubKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize, &i);
7099e4 ¤   if (!pub) {
35edb5 ·¤  ¤   ringSimpleErr(set->pool, i);
967ed2 ¤   ¤   return NULL;
9c9371 ¤   }
e894c4 ¤   memcpy(pub->keyID, key->k.keyID, sizeof(key->k.keyID));
621e08 ¤   return pub;
39efe6 }
88af5a
5e38e5 /*
1e4d55 ·* Find the best Secret which is a descendant of the given key,
257950 ·* in the given set.
6d495d ·*/
af614e union RingObject *
e45320 ringBestSec(RingSet const *set, union RingObject const *key)
a3bb36 {
9a8ffd ¤   PGPVirtMask better;
6dffba ¤   union RingObject *obj, *best = 0;
59af5a
780544 ¤   pgpVirtMaskInit (set->pool, &better);
36a82a ¤   pgpVirtMaskNOT (set->pool, &better, set->pool->nfiles);
5baf5a
8c94a2 ¤   pgpAssert(OBJISKEY(key));
f0974c ¤   for (obj = key->g.down; obj; obj = obj->g.next) {
21acb1 ¤   ¤   if (pgpVirtMaskIsOverlapping (&obj->g.mask, &better)
525d77 ¤   ¤   ¤   && pgpIsRingSetMember (set, obj)
648a9b ¤   ¤   ····&& OBJISSEC(obj)) {
160ce6 ¤   ¤   ¤   best = obj;
3b2000 ¤   ¤   ¤   ringObjBetters(obj, set->pool, &better);
6b0fe4 ¤   ¤   }
f89371 ¤   }
c3923a ¤   pgpVirtMaskCleanup (set->pool, &better);
97e17b ¤   return best;
edaf5a
--281b 000cfd0455c401001ff Page 26 of pgpRngPub.c
7aefe6 }
46af5a
2e38e5 /*
075297 ·* Return the version for a secret key. ·Also permissible to pass a key.
572ced ·* This should be used when we edit a pass phrase to preserve the version
3ca0a3 ·* number and avoid the infamous "version bug".
0d495d ·*/
fda6d1 PgpVersion
b3c958 ringSecVersion (RingSet const *set, union RingObject *sec)
afbb36 {
1c1eaf ¤   PGPByte *secdata;
29d552 ¤   PGPSize secdatalen;
e4af5a
7d50be ¤   if (!OBJISSEC(sec)) {
a05adf ¤   ¤   sec = ringBestSec(set, sec);
84ef0d ¤   ¤   if (!sec) {
4e9da5 ¤   ¤   ¤   ringSimpleErr(set->pool, kPGPError_SecretKeyNotFound);
79a091 ¤   ¤   ¤   return (PgpVersion)0;
ac0fe4 ¤   ¤   }
1d9371 ¤   }
01f01d ¤   secdata = (PGPByte *)ringFetchObject (set, sec, &secdatalen);
92a7d1 ¤   return (PgpVersion)secdata[0];
41efe6 }
27af5a
d5af5a
e138e5 /*
bc3056 ·* Given a secret on a keyring, get a PGPSecKey (possibly locked).
218300 ·* As a hack to help the lazy programmer, you can also pass a key.
2ce2d3 ·* Use is a usage code which limits the kinds of keys we will accept.
abd3ee ·* For keys which have subkeys this chooses which one to use.
49495d ·*/
7a521e PGPSecKey *
3e82f8 ringSecSecKey(RingSet const *set, union RingObject *sec, int use)
a6bb36 {
1d8b0f ¤   PGPByte const *p;
9f875f ¤   PGPSize len;
214bdc ¤   PGPSecKey *seckey;
aeb957 ¤   union RingObject *key;
b28ada ¤   union RingObject *subkey = NULL;
236932 ¤   unsigned vsize;
b0d54b ¤   PGPError i;
288a97 ¤   PGPContextRef¤  context;
caaf5a
7d090d ¤   pgpAssertAddrValid( set, RingSet );
01250c ¤   pgpAssertAddrValid( set->pool, RingPool );
761daf ¤   context¤= set->pool->context;
64af5a
d85dd5 ¤   if (OBJISSEC(sec)) {
70b219 ¤   ¤   key = sec->g.up;
73f037 ¤   } else {
e37063 ¤   ¤   key = sec;
ff9371 ¤   }
b694a2 ¤   pgpAssert(OBJISKEY(key));
f3d976 ¤   pgpAssert(pgpIsRingSetMember(set, sec));
74af5a
594924 ¤   /* Select between subkey and key if necessary */
9a617d ¤   if (use¤ && ·(OBJISSUBKEY(key)
2a0a1e ¤   ¤   ¤   || ((subkey=ringKeySubkey(set, key)) != NULL))) {
256c83 ¤   ¤   int newkey = 0;
288e1f ¤   ¤   if (use == PGP_PKUSE_SIGN_ENCRYPT) {
d002bb ¤   ¤   ¤   ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
cbcf03 ¤   ¤   ¤   return NULL;
3b0fe4 ¤   ¤   }
8a7a10 ¤   ¤   if (use == PGP_PKUSE_ENCRYPT) {
773cdb ¤   ¤   ¤   if (OBJISTOPKEY(key)) {
b6ee0c ¤   ¤   ¤   ¤   pgpAssert(subkey);
005a07 ¤   ¤   ¤   ¤   key = subkey;
b8e6ed ¤   ¤   ¤   ¤   pgpAssert (OBJISSUBKEY(key));
1990b7 ¤   ¤   ¤   ¤   newkey = 1;
dfa3a6 ¤   ¤   ¤   }
c9ad80 ¤   ¤   } else if (use == PGP_PKUSE_SIGN) {
cf59f6 ¤   ¤   ¤   if (OBJISSUBKEY(key)) {
--1376 000a1e40b6d401001ff Page 27 of pgpRngPub.c
67eb59 ¤   ¤   ¤   ¤   key = key->g.up;
1cfdeb ¤   ¤   ¤   ¤   pgpAssert (OBJISTOPKEY(key));
4590b7 ¤   ¤   ¤   ¤   newkey = 1;
0fa3a6 ¤   ¤   ¤   }
a70fe4 ¤   ¤   }
838737 ¤   ¤   if (newkey || !OBJISSEC(sec)) {
8023d5 ¤   ¤   ¤   sec = ringBestSec(set, key);
0395f9 ¤   ¤   ¤   if (!sec) {
1e8e29 ¤   ¤   ¤   ¤   ringSimpleErr(set->pool, kPGPError_SecretKeyNotFound);
cbfb5e ¤   ¤   ¤   ¤   return NULL;
16a3a6 ¤   ¤   ¤   }
770fe4 ¤   ¤   }
38bf34 ¤   } else if (OBJISKEY(sec)) {
1f5adf ¤   ¤   sec = ringBestSec(set, sec);
cfef0d ¤   ¤   if (!sec) {
9d9da5 ¤   ¤   ¤   ringSimpleErr(set->pool, kPGPError_SecretKeyNotFound);
88cf03 ¤   ¤   ¤   return NULL;
d80fe4 ¤   ¤   }
5e9371 ¤   }
4baf5a
532906 ¤   /* Verify key satisfies required usage */
d728f7 ¤   if (use && ((pgpKeyUse(pgpPkalgByNumber(key->k.pkalg)) & use) != use)){
734ccc ¤   ¤   ringSimpleErr(set->pool, kPGPError_PublicKeyUnimplemented);
f07ed2 ¤   ¤   return NULL;
849371 ¤   }
27af5a
a5a9bc ¤   p = (PGPByte const *)ringFetchObject(set, sec, &len);
034dda ¤   if (!p)
9c7ed2 ¤   ¤   return NULL;
d13b59 ¤   if (sec->g.up->g.flags & KEYF_ERROR || len < 8) {
a9c0d7 ¤   ¤   i = (PGPError)ringKeyParse(set->pool->context, p, len, NULL, NULL,
f66d61 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL, NULL, NULL, 0);
30f584 ¤   ¤   ringSimpleErr(set->pool, i);
ce7ed2 ¤   ¤   return NULL;
d39371 ¤   }
549631 ¤   if (p[0] == PGPVERSION_4) {
cd73d8 ¤   ¤   vsize = 0;
aaf037 ¤   } else {
f7c660 ¤   ¤   vsize = 2;
2f9371 ¤   }
622d16 ¤   pgpAssert(p[5+vsize] == sec->g.up->k.pkalg); /* Checked by ringKeyVerify */
bb8357 ¤   seckey = pgpSecKeyFromBuf( context, p[5+vsize], p+6+vsize, len-6-vsize,
447d1a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPBoolean)!!KEYISV3(&sec->g.up->k), &i);
ba4c37 ¤   if (!seckey) {
35edb5 ·¤  ¤   ringSimpleErr(set->pool, i);
e97ed2 ¤   ¤   return NULL;
049371 ¤   }
6f71f9 ¤   memcpy(seckey->keyID, sec->g.up->k.keyID, sizeof(sec->g.up->k.keyID));
3c4d98 ¤   return seckey;
e7efe6 }
7faf5a
ceaf5a
a2462e /* There ain't much to know about a name... */
665cc8 char const *
82ad78 ringNameName(RingSet const *set, union RingObject *name, PGPSize *lenp)
95bb36 {
a42706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
2fcc5b ¤   pgpAssert(OBJISNAME(name));
ea4491 ¤   return (char const *)ringFetchObject(set, name, lenp);
d5efe6 }
a3af5a
537750 PGPBoolean
807136 ringNameIsAttribute(RingSet const *set, union RingObject *name)
80bb36 {
df18be ¤   (void) set; /* Avoid warning */
f767c5 ¤
722706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
59cc5b ¤   pgpAssert(OBJISNAME(name));
2e67c5 ¤
9f604e ¤   (void) set;
2d587f ¤   (void) name;
a167c5 ¤
--305a 00031337f3d401001ff Page 28 of pgpRngPub.c
2cf6ce ¤   return (PGPBoolean)NAMEISATTR(&name->n);
faefe6 }
76af5a
fabccf PGPUInt32
6a5786 ringNameCountAttributes(RingSet const *set, union RingObject *name)
21bb36 {
eba4eb ¤   PGPByte¤¤   ¤   *p;
69de55 ¤   PGPSize¤¤   ¤   len;
9667c5 ¤
932706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
cbcc5b ¤   pgpAssert(OBJISNAME(name));
d8c360 ¤   if (!NAMEISATTR(&name->n))
9abbde ¤   ¤   return 0;
a0af5a
f6a0a6 ¤   p = (PGPByte *)ringFetchObject(set, name, &len);
e6f0dd ¤   if (!p) {
bbbbde ¤   ¤   return 0;
989371 ¤   }
d5af5a
1a1225 ¤   return ringAttrCountSubpackets (p, len);
7eefe6 }
1caf5a
3fd929 PGPByte const *
b4c719 ringNameAttributeSubpacket (RingObject *name, RingSet const *set,
6c431c ¤   PGPUInt32 nth, PGPUInt32 *subpacktype, PGPSize *plen, PGPError *error)
b5bb36 {
81a4eb ¤   PGPByte¤¤   ¤   *p;
3ade55 ¤   PGPSize¤¤   ¤   len;
896032 ¤   RingPool *pool = set->pool;
3067c5 ¤
a3cc5b ¤   pgpAssert(OBJISNAME(name));
522706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
a8af5a
c00161 ¤   if (error)
72a79e ¤   ¤   *error = kPGPError_NoErr;
4caf5a
545ab5 ¤   if (!NAMEISATTR(&name->n)) {
6fe3c2 ¤   ¤   if (error)
93c733 ¤   ¤   ¤   *error = kPGPError_BadParams;
3f7ed2 ¤   ¤   return NULL;
cd9371 ¤   }
d8af5a
90a0a6 ¤   p = (PGPByte *)ringFetchObject(set, name, &len);
05af5a
c83f04 ¤   /* ringAttrSubpacket munges the packets so make a copy */
882bba ¤   if (IsntNull(p) ·&& ·p != (PGPByte *)pool->pktbuf) {
17792d ¤   ¤   PGPByte *pktbuf = (PGPByte *)ringReserve(pool, len);
fd7e3c ¤   ¤   if (IsntNull(pktbuf)) {
f34de2 ¤   ¤   ¤   pgpCopyMemory(p, pktbuf, len);
5b0fe4 ¤   ¤   }
ee5833 ¤   ¤   p = pktbuf;
7d9371 ¤   }
26f0dd ¤   if (!p) {
8be3c2 ¤   ¤   if (error)
b99c64 ¤   ¤   ¤   *error = ringSetError(set)->error;
957ed2 ¤   ¤   return NULL;
2b9371 ¤   }
c6af5a
873bd3 ¤   return ringAttrSubpacket(p, len, nth, subpacktype, plen);
751862 }¤
beaf5a
87af5a
20aa0b /* ·Return the validity (*not* the trust) of a name */
1daf5a
715d74 PGPByte
87fbb7 ringNameTrust(RingSet const *set, union RingObject *name)
cbbb36 {
10a176 ····union RingObject *key;
0267c5 ¤
1181f7 ····pgpAssert(OBJISNAME(name));
d62706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
316d84 ····(void)set;
--5994 0008dedaab4401001ff Page 29 of pgpRngPub.c
e6ae7d ····key = name->g.up;
2b9cde ····pgpAssert(OBJISTOPKEY(key));
6429ec ····/*
37015d ¤   ·* Force returned value if key is revoked or axiomatic.
e1364c ¤   ·* Allow expired keys to stay valid, so users can know what their status
a84916 ¤   ·* was before they expired.
91a4e3 ¤   ·*/
d145e5 ····if (key->k.trust & PGP_KEYTRUSTF_REVOKED)
fc0a3c ········return kPGPNameTrust_Untrusted;
6f9871 ····if (key->k.trust & PGP_KEYTRUSTF_BUCKSTOP)
394333 ········return kPGPNameTrust_Complete;
c24ca0 ····if (!(name->g.flags & (RINGOBJF_TRUST)))
ee5eee ········ringMntValidateName (set, name);
af9788 ····return name->n.trust & kPGPNameTrust_Mask;
28efe6 }
1baf5a
064d2f int
d90b7d ringNameWarnonly(RingSet const *set, union RingObject *name)
d6bb36 {
cbcc5b ¤   pgpAssert(OBJISNAME(name));
352706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
948a21 ¤   (void)set;
6c12d0 ¤   return name->n.trust & PGP_NAMETRUSTF_WARNONLY;
24efe6 }
09af5a
ff314a void
c7e356 ringNameSetWarnonly(RingSet const *set, union RingObject *name)
25bb36 {
36cc5b ¤   pgpAssert(OBJISNAME(name));
3e2706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
345c51 ¤   if (!(name->n.trust & PGP_NAMETRUSTF_WARNONLY)) {
d96dfa ¤   ¤   name->n.trust |= PGP_NAMETRUSTF_WARNONLY;
c296a4 ¤   ¤   name->g.flags |= RINGOBJF_TRUSTCHANGED;
41b1ea ¤   ¤   ringPoolMarkTrustChanged (set->pool, &name->g.mask);
ee9371 ¤   }
5d104e ¤   name->g.flags |= RINGOBJF_TRUST;
deefe6 }
93af5a
1e6e17 PGPUInt16
cf5c16 ringNameValidity(RingSet const *set, union RingObject *name)
31bb36 {
591325 #if PGPTRUSTMODEL==0
8b6d84 ····(void)set;
753124 ····(void)name;
53d857 ····pgpAssert(0);
9b958b ····return 0;
27db21 #else
f3a176 ····union RingObject *key;
d481f7 ····pgpAssert(OBJISNAME(name));
e62706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
106d84 ····(void)set;
6bae7d ····key = name->g.up;
57880d ····pgpAssert (OBJISTOPKEY(key));
b9d8af ¤   /*
43015d ¤   ·* Force returned value if key is revoked or axiomatic.
50364c ¤   ·* Allow expired keys to stay valid, so users can know what their status
fb4916 ¤   ·* was before they expired.
d1a4e3 ¤   ·*/
1445e5 ····if (key->k.trust & PGP_KEYTRUSTF_REVOKED)
e682c5 ········return 0;
c59871 ····if (key->k.trust & PGP_KEYTRUSTF_BUCKSTOP)
ab447f ········return PGP_TRUST_INFINITE;
db4ca0 ····if (!(name->g.flags & (RINGOBJF_TRUST)))
305eee ········ringMntValidateName (set, name);
f48386 ····return ringTrustToIntern (name->n.validity);·
f37454 #endif
94efe6 }
1eaf5a
736e17 PGPUInt16
a68230 ringNameConfidence(RingSet const *set, union RingObject *name)
dcbb36 {
8d1325 #if PGPTRUSTMODEL==0
--9e67 000d040381b401001ff Page 30 of pgpRngPub.c
c38a21 ¤   (void)set;
c8c364 ¤   (void)name;
d24aac ¤   pgpAssert(0);
733e6b ¤   return 0;
5bdb21 #else
28cc5b ¤   pgpAssert(OBJISNAME(name));
e22706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
5c8a21 ¤   (void)set;
20d62e ¤   return ringTrustToIntern (name->n.confidence);
1c7454 #endif
8aefe6 }
93af5a
61fcf4 int·
efce7a ringNameConfidenceUndefined(RingSet const *set, union RingObject *name)
2bbb36 {
341325 #if PGPTRUSTMODEL==0
7e8a21 ¤   (void)set;
18c364 ¤   (void)name;
ea4aac ¤   pgpAssert(0);
c73e6b ¤   return 0;
1fdb21 #else
b6cc5b ¤   pgpAssert(OBJISNAME(name));
992706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
f18a21 ¤   (void)set;
4f20e5 ¤   return (name->n.confidence == PGP_NEWTRUST_UNDEFINED);
e07454 #endif
d8efe6 }
9faf5a
4aaf5a
d7314a void
e95055 ringNameSetConfidence(RingSet const *set, union RingObject *name,
c642e1 ¤   ¤   ······PGPUInt16 confidence)
1abb36 {
631325 #if PGPTRUSTMODEL==0
438a21 ¤   (void)set;
05c364 ¤   (void)name;
c2992c ¤   (void)confidence;
ba4aac ¤   pgpAssert(0);
59db21 #else
4fcc5b ¤   pgpAssert(OBJISNAME(name));
912706 ¤   pgpAssert(pgpIsRingSetMember(set, name));
01af5a
ee7897 ¤   confidence = (PGPUInt16) ringTrustToExtern (confidence);
ee67c5 ¤
d7b8b3 ¤   if (name->n.confidence != confidence) {
6f4bc5 ¤   ¤   name->n.confidence = (PGPByte) confidence;
7896a4 ¤   ¤   name->g.flags |= RINGOBJF_TRUSTCHANGED;
00b1ea ¤   ¤   ringPoolMarkTrustChanged (set->pool, &name->g.mask);
b59371 ¤   }
f0104e ¤   name->g.flags |= RINGOBJF_TRUST;
3e7454 #endif
2eefe6 }
69af5a
c34d2f int
edd666 ringSigError(RingSet const *set, union RingObject *sig)
53bb36 {
468b0f ¤   PGPByte const *p;
74875f ¤   PGPSize len;
28af5a
3c2b90 ¤   pgpAssert(OBJISSIG(sig));
ddc592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
3baf5a
ae3413 ¤   if (!(sig->g.flags & SIGF_ERROR))
5bbbde ¤   ¤   return 0;
5baf5a
2cfbdf ¤   p = (PGPByte const *)ringFetchObject(set, sig, &len);
864dda ¤   if (!p)
16e1c3 ¤   ¤   return ringSetError(set)->error;
cf708b ¤   return ringSigParse(p, len, NULL, NULL, NULL, NULL, NULL, NULL,
6d2540 ¤   ¤   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
20efe6 }
d0af5a
--6e6a 000b79bc8b3401001ff Page 31 of pgpRngPub.c
fb614e union RingObject *
520679 ringSigMaker(RingSet const *sset, union RingObject *sig,
3bde75 ¤   RingSet const *kset)
94bb36 {
1e879a ¤   (void)sset;¤/* Avoid warning */
6f2b90 ¤   pgpAssert(OBJISSIG(sig));
826a42 ¤   pgpAssert(pgpIsRingSetMember(sset, sig));
a2af5a
79045e ¤   sig = sig->s.by;
8ac378 ¤   pgpAssert(OBJISKEY(sig));¤  /* "sig" is now a key! */
9c9d2d ¤   if (!pgpIsRingSetMember(kset, sig))
8a7ed2 ¤   ¤   return NULL;
47c4f3 ¤   ringObjectHold(sig);
7c6eec ¤   return sig;
23efe6 }
2baf5a
eb314a void
e00fb3 ringSigID8(RingSet const *set, union RingObject const *sig,
0bd420 ¤   PGPByte *pkalg, PGPKeyID *keyID)
78bb36 {
432b90 ¤   pgpAssert(OBJISSIG(sig));
2fc592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
8b8a21 ¤   (void)set;
3d045e ¤   sig = sig->s.by;
c91b8b ¤   pgpAssert(OBJISKEY(sig));
4c5f4a ¤   if (pkalg) {
0e4198 ¤   ¤   *pkalg = sig->k.pkalg;
c54b8d ¤   ¤   if ((*pkalg | 1) == 3)
27ae88 ¤   ¤   ¤   *pkalg = 1;¤/* ViaCrypt */
969371 ¤   }
708cf9 ¤   if ( keyID )
ecc7a1 ¤   {
1ae5c4 ¤   ¤   pgpNewKeyIDFromRawData( sig->k.keyID, 8, keyID );
bd9371 ¤   }
75efe6 }
30af5a
505d74 PGPByte
94ceaa ringSigTrust(RingSet const *set, union RingObject *sig)
f1bb36 {
5c2b90 ¤   pgpAssert(OBJISSIG(sig));
0ac592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
f98a21 ¤   (void)set;
d461cc ¤   if (ringSigError (set, sig))
daf88b ¤   ¤   return PGP_SIGTRUST_INVALID;
c5f207 ¤   if (sig->s.by == NULL)
3e5779 ¤   ¤   return PGP_SIGTRUST_NOKEY;
32f7e1 ¤   if (!(sig->s.trust & PGP_SIGTRUSTF_TRIED))
3d8f26 ¤   ¤   return PGP_SIGTRUST_UNTRIED;
d25392 ¤   if (!(sig->s.trust & PGP_SIGTRUSTF_CHECKED))
ec0bb6 ¤   ¤   return PGP_SIGTRUST_BAD;
a9dd75 ¤   if (!(sig->g.flags & (RINGOBJF_TRUST))) {
ace861 ¤   ¤   ringMntValidateKey (set, sig->s.by);
b9553d ¤   ¤   return sig->s.by->k.trust & kPGPKeyTrust_Mask;
3b9371 ¤   }
ed0e24 ¤   else
fb7c8e ¤   ········return sig->s.trust & kPGPKeyTrust_Mask;
85efe6 }
76af5a
4d4d2f int
29c769 ringSigChecked(RingSet const *set, union RingObject const *sig)
58bb36 {
eb2b90 ¤   pgpAssert(OBJISSIG(sig));
e7c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
238a21 ¤   (void)set;
c62e6a ¤   return sig->s.trust & PGP_SIGTRUSTF_CHECKED;
b1efe6 }
ccaf5a
434d2f int
667d7c ringSigTried(RingSet const *set, union RingObject const *sig)
98bb36 {
c22b90 ¤   pgpAssert(OBJISSIG(sig));
b7c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
--f436 000b39d9026401001ff Page 32 of pgpRngPub.c
c38a21 ¤   (void)set;
87fa87 ¤   return sig->s.trust & PGP_SIGTRUSTF_TRIED;
90efe6 }
1aaf5a
494d2f int
b24c74 ringSigExportable(RingSet const *set, union RingObject const *sig)
57bb36 {
8c2b90 ¤   pgpAssert(OBJISSIG(sig));
dbc592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
f08a21 ¤   (void)set;
e91885 ¤   return SIGISEXPORTABLE(&sig->s);
a2efe6 }
e9af5a
aa5d74 PGPByte
f60ed3 ringSigTrustLevel(RingSet const *set, union RingObject const *sig)
d2bb36 {
292b90 ¤   pgpAssert(OBJISSIG(sig));
81c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
b18a21 ¤   (void)set;
d51bf0 ¤   return sig->s.trustLevel;
ddefe6 }
c5af5a
a65d74 PGPByte
7b5791 ringSigTrustValue(RingSet const *set, union RingObject const *sig)
58bb36 {
ce8840 ¤   PGPByte trustValue;
b5af5a
e82b90 ¤   pgpAssert(OBJISSIG(sig));
62c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
518a21 ¤   (void)set;
999bbf ¤   trustValue = sig->s.trustValue;
c11325 #if PGPTRUSTMODEL==0
8d3f4e ¤   trustValue = ringTrustExternToOld(set->pool, trustValue);
aa7454 #endif
69f095 ¤   return sig->s.trustValue;
abefe6 }
7aaf5a
cf3398 /* Call ringSigTrust to get sig status, then call this function if
178b2c ···sig is good and the confidence is required. */
b5af5a
0a6e17 PGPUInt16
87c70d ringSigConfidence(RingSet const *set, union RingObject *sig)
51bb36 {
671325 #if PGPTRUSTMODEL==0
c88a21 ¤   (void)set;
3277e4 ¤   (void)sig;
a54aac ¤   pgpAssert(0);
163e6b ¤   return 0;
addb21 #else
842b90 ¤   pgpAssert(OBJISSIG(sig));
9fc592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
2e8a21 ¤   (void)set;
c5c158 ¤   if (sig->s.by != NULL) {
0bcab9 ¤   ¤   if (pgpIsRingSetMember(set, sig->s.by)) {
140851 ¤   ¤   ¤   if (!(sig->s.by->g.flags & (RINGOBJF_TRUST)))
23e9e7 ¤   ¤   ¤   ¤   ringMntValidateKey (set, sig->s.by);
54bbd7 ¤   ¤   ¤   if (sig->s.by->k.trust & PGP_KEYTRUSTF_REVOKED)
3d46f1 ¤   ¤   ¤   ¤   return 0;
3fbb8c ¤   ¤   ¤   else
47af23 ¤   ¤   ¤   ¤   return ringKeyCalcTrust (set, sig->s.by);
fd0fe4 ¤   ¤   }
ac0e1d ¤   ¤   else
298144 ¤   ¤   ¤   return 0;
cf9371 ¤   }
c70e24 ¤   else
c9bbde ¤   ¤   return 0;
537454 #endif
7eefe6 }
1aaf5a
73af5a
624d2f int
b324f6 ringSigType(RingSet const *set, union RingObject const *sig)
--6f7a 0009ba613ea401001ff Page 33 of pgpRngPub.c
2cbb36 {
2d2b90 ¤   pgpAssert(OBJISSIG(sig));
a9c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
b38a21 ¤   (void)set;
cee139 ¤   return sig->s.type;
a1efe6 }
38af5a
79bccf PGPUInt32
460228 ringSigTimestamp(RingSet const *set, union RingObject const *sig)
3fbb36 {
962b90 ¤   pgpAssert(OBJISSIG(sig));
a7c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
7e8a21 ¤   (void)set;
d3d3a8 ¤   return sig->s.tstamp;
f6efe6 }
56af5a
c6bccf PGPUInt32
760f75 ringSigExpiration(RingSet const *set, union RingObject const *sig)
d6bb36 {
652b90 ¤   pgpAssert(OBJISSIG(sig));
41c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
498a21 ¤   (void)set;
dde130 ¤   if (sig->s.tstamp == 0 || sig->s.validity == 0)
ccccba ¤   ¤   return 0; ···/* valid indefinitely */
950e24 ¤   else
82749b ¤   ¤   return sig->s.tstamp + (sig->s.validity * 3600 * 24);
35efe6 }
f7af5a
ae38e5 /*
3af653 ·* True if sig is a self-sig.
4c495d ·*/
fc7750 PGPBoolean
536c48 ringSigIsSelfSig(RingSet const *set, RingObject const *sig)
95bb36 {
3a7da7 ¤   RingObject const¤   *parent;
d7af5a
e38a21 ¤   (void)set;
7c2b90 ¤   pgpAssert(OBJISSIG(sig));
20c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
1aaf5a
36ba1e ¤   /* Find top-level key */
13533d ¤   parent = sig;
a08d83 ¤   while (!OBJISTOPKEY(parent))
8a78d2 ¤   ¤   parent = parent->g.up;
10af5a
0730ab ¤   /* No good if not signed by top-level key (selfsig) */
072b35 ¤   if (sig->s.by != parent)
8b98aa ¤   ¤   return FALSE;
85af5a
071a9b ¤   /* All OK */
33c2e7 ¤   return TRUE;
ffefe6 }
42af5a
74af5a
a1af5a
d738e5 /*
894abf ·* True if sig is an X509 sig.
c0495d ·*/
8e7750 PGPBoolean
c252a1 ringSigIsX509(RingSet const *set, RingObject const *sig)
06bb36 {
ce8a21 ¤   (void)set;
bb2b90 ¤   pgpAssert(OBJISSIG(sig));
ebc592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
a9af5a
52322f ¤   return SIGISX509(&sig->s) != 0;
1cefe6 }
81af5a
641f9c PGPByte *
75fff1 ringSigX509Certificate(RingSet const *set, RingObject *sig, PGPSize *len)
f9bb36 {
9b8ade ¤   PGPByte *ptr;
--9ab8 0002a6f8661401001ff Page 34 of pgpRngPub.c
e0af5a
552b90 ¤   pgpAssert(OBJISSIG(sig));
65c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
311d6e ¤   pgpAssert(IsntNull(len));
a8af5a
96df49 ¤   *len = 0;
71390c ¤   if (!SIGISX509 (&sig->s))
ba7ed2 ¤   ¤   return NULL;
601ecf ¤   ptr = (PGPByte *)ringFetchObject(set, sig, len);
0f1dc0 ¤   if (IsNull( ptr ) )
257ed2 ¤   ¤   return NULL;
d29145 ¤   ptr = (PGPByte *)ringSigFindSubpacket(ptr, SIGSUB_X509, 0, len,
788b0a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, NULL, NULL);
2d8726 ¤   return ptr;
46efe6 }
9daf5a
0daf5a
04af5a
25e9ca /** Filtering functions to get sets from sets **/
7daf5a
1bbf0b /* The generic one - according to the predicate */
84af5a
914d2f int
f2b010 ringSetFilter(RingSet const *src, RingSet *dest,
e29ab6 ¤   ······int (*predicate)(void *arg, RingIterator *iter,
060a0f ¤   ¤   ···············union RingObject *object, unsigned level),
f55c40 ¤   ······void *arg)
3bbb36 {
ee3bb6 ¤   RingIterator *iter;
7ca997 ¤   union RingObject *obj;
2b5c1c ¤   unsigned level;
b44ba4 ¤   int i;
627c4c ¤   unsigned total = 0;
6caf5a
bfd02d ¤   if (!src || !dest)
aebbde ¤   ¤   return 0;
a9af5a
78f975 ¤   pgpAssert(!RINGSETISMUTABLE(src));
d7e3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
6eaf5a
34af91 ¤   iter = ringIterCreate(src);
cd21b2 ¤   if (!iter)
d3a720 ¤   ¤   return ringSetError(src)->error;
3c55a5 ¤   level = 1;
de220e ¤   for (;;) {
7fb371 ¤   ¤   i = ringIterNextObject(iter, level);
550c5f ¤   ¤   if (i > 0) {
cb900d ¤   ¤   ¤   obj = ringIterCurrentObject(iter, level);
7d484b ¤   ¤   ¤   i = predicate(arg, iter, obj, level);
d48a35 ¤   ¤   ¤   if (i < 0) {
c6c42d ¤   ¤   ¤   ¤   ringIterDestroy(iter);
1d590c ¤   ¤   ¤   ¤   return i;
0da3a6 ¤   ¤   ¤   }
76e0af ¤   ¤   ¤   if (i) {
6c2e7d ¤   ¤   ¤   ¤   /* Calculate total number of keys */
66281e ¤   ¤   ¤   ¤   total += (level == 1);
8c3387 ¤   ¤   ¤   ¤   /* ringSetAddObject(dest, obj) */
532bb8 ¤   ¤   ¤   ¤   pgpVirtMaskOR (src->pool, &dest->mask, &obj->g.mask);
2f2bbe ¤   ¤   ¤   ¤   ++level; /* Recurse! */
b12e51 ¤   ¤   ¤   ¤   ringIterRewind(iter, level);
aaa3a6 ¤   ¤   ¤   }
f245a6 ¤   ¤   } else {
3af4cf ¤   ¤   ¤   if (i < 0 || !--level)
b2f622 ¤   ¤   ¤   ¤   break;
6b0fe4 ¤   ¤   }
2b9371 ¤   }
a71d89 ¤   ringIterDestroy(iter);
fd35b0 ¤   /* Return error or number of keys found */
e0423c ¤   return (i < 0) ? i : (total < INT_MAX) ? total : INT_MAX;
abefe6 }
92af5a
2a38e5 /*
--6f18 000f8b7c746401001ff Page 35 of pgpRngPub.c
12ef15 ·* Return pointer to first instance of (s1,l1) in (s0,l0),
c97692 ·* ignoring case. ·Uses a fairly simple-minded algorithm.
d27a2b ·* Search for the first char of s1 in s0, and when we have it,
4a84a0 ·* scan for the rest.
ef775e ·*
fd7937 ·* Is it worth mucking with Boyer-Moore or the like?
1e495d ·*/
7bd10a static char const *
4b0d1d xmemimem(char const *s0, size_t l0, char const *s1, size_t l1)
8ebb36 {
0874c5 ¤   char c0, c1, c2;
47b9b0 ¤   size_t l;
b8af5a
98d8af ¤   /*
4eddcb ¤   ·* The trivial cases - this means that NULL inputs are very legal
0a52ae ¤   ·* if the corresponding lengths are zero.
f7a4e3 ¤   ·*/
27d7b6 ¤   if (l0 < l1)
967ed2 ¤   ¤   return NULL;
1fc859 ¤   if (!l1)
1825b4 ¤   ¤   return s0;
eac6c4 ¤   l0 -= l1;
75af5a
ff99f1 ¤   c1 = tolower((unsigned char)*s1);
c543ab ¤   do {
e3f9c7 ¤   ¤   c0 = tolower((unsigned char)*s0);
16d228 ¤   ¤   if (c0 == c1) {
c68cd6 ¤   ¤   ¤   l = 0;
84f603 ¤   ¤   ¤   do {
79895a ¤   ¤   ¤   ¤   if (++l == l1)
50e894 ¤   ¤   ¤   ¤   ¤   return s0;
33108c ¤   ¤   ¤   ¤   c0 = tolower((unsigned char)s0[l]);
ad952b ¤   ¤   ¤   ¤   c2 = tolower((unsigned char)s1[l]);
c87244 ¤   ¤   ¤   } while (c0 == c2);
910fe4 ¤   ¤   }
74b5f1 ¤   ¤   s0++;
087014 ¤   } while (l0--);
6a3f59 ¤   return NULL;
4defe6 }
7caf5a
d01d23 typedef struct KeySpec
22bb36 {
8d3075 ¤   char const *keyid, *name;
d87364 ¤   size_t keyidlen, namelen;
1fb68d ¤   int use;
662859 ¤   DEBUG_STRUCT_CONSTRUCTOR( KeySpec )
b8a78f } KeySpec;
9eaf5a
e238e5 /*
656156 ·* Allowed formats for the keyspec are:
650e24 ·* NULL, "", "*" - Match everything
ed0933 ·* "0x123c" - match everything with a keyID containing "123c"
37c476 ·* "Name" - match everything with a name containing "name" (case-insensitive)
0697a0 ·* "0x123c:name" - match everything satisfying both requirements
3e775e ·*
308702 ·* This returns pointers to "keyidspec" and "uidspec", the portions of the
2f0ae9 ·* input keyspec string which should match the keyID and userID portions,
99812a ·* or NULL if there are no such portions (which means "always mauch").
f2775e ·*
2c249b ·* This function cannot have any errors. ·At worst, the entire string
220433 ·* is taken to be a uid match. ·Some corner cases:
68775e ·*
02c365 ·* 0 ·············-> No keyidspec, namespec of "0"
b9f413 ·* 0x ············-> Empty keyidspec, no namespec
77efb5 ·* 0x: ···········-> Empty keyidspec, empty namespec
b3a95c ·* 0x12345678: ···-> Keyidspec of "12345678", empty namespec
cb726c ·* 0x12345678:foo -> Keyidspec of "12345678", namespec of "foo"
db793e ·* 0x12345678;foo -> No keyidspec, namespec of "0x12345678;foo"
a37667 ·* 0x12345678¤  ··-> Keyidspec of "12345678", no namespec
cb775e ·*
ead236 ·* Keyid's are now allowed to be up to 16 characters long. ·If they are
f86f30 ·* 8 chars or less, they are only matched against the low 32 bits of
--91f3 000184bde76401001ff Page 36 of pgpRngPub.c
f7175b ·* the key's keyid. ·If greater, they are matched against the full 64
7f7ef1 ·* bits of keyid.
14495d ·*/
b12978 static void
b2c1f7 keyspecSplit(char const *string, int use, KeySpec *spec)
22bb36 {
26743f ¤   unsigned i;
a3af5a
5d779b ¤   spec->use = use;
99af5a
5bafab ¤   spec->keyidlen = spec->namelen = 0;¤/* Match anything */
cbaf5a
62e93a ¤   /* NULL is nothing */
a609e6 ¤   if (!string)
5c99bf ¤   ¤   return;
d5af5a
5c391f ¤   /* Does it look like it might start with a keyID spec? */
aab84b ¤   if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X')) {
662b6e ¤   ¤   i = 2;
f678c7 ¤   ¤   /* Accept no more than 16 hex digits */
420fbc ¤   ¤   while (isxdigit(string[i]) && ++i != 2+16)
a4b110 ¤   ¤   ¤   ;
d0d949 ¤   ¤   /* Then check for proper termination: NULL or : */
1944b8 ¤   ¤   if (!string[i]) {
5d3d13 ¤   ¤   ¤   spec->keyid = string+2;
0662df ¤   ¤   ¤   spec->keyidlen = i-2;
3d0ecc ¤   ¤   ¤   return;
873441 ¤   ¤   } else if (string[i] == ':') {
9f3d13 ¤   ¤   ¤   spec->keyid = string+2;
e362df ¤   ¤   ¤   spec->keyidlen = i-2;
967aec ¤   ¤   ¤   string += i+1;
6162f1 ¤   ¤   } /* Otherwise forget it, it's all namespec */
df9371 ¤   }
3eaf5a
e5e976 ¤   /* If not "*", it's a pattern */
f1dbb4 ¤   if (string[0] != '*' || string[1]) {
2994e1 ¤   ¤   spec->name = string;
99f1dd ¤   ¤   spec->namelen = strlen(string);
929371 ¤   }
5befe6 }
15af5a
d738e5 /*
1f9e0a ·* Return true if string "arg" (terminated by null or ':') appears in
1a916f ·* the hex expansion of the given keyID. ·Case-insensitive.
f3495d ·*/
c9beb7 static int
46bd06 matchKeyID(PGPByte const keyID[8], char const *pat, size_t len)
4bbb36 {
22e69f ¤   char buf[16];
f039e5 ¤   char const hex[16] = {
b08ee9 ¤   ¤   '0', '1', '2', '3', '4', '5', '6', '7',
f3f569 ¤   ¤   '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
7362bd ¤   };
00af5a
82c5eb ¤   buf[ 8] = hex[ keyID[4] >> 4 ];
0b9f50 ¤   buf[ 9] = hex[ keyID[4] & 15 ];
0f5d2a ¤   buf[10] = hex[ keyID[5] >> 4 ];
290791 ¤   buf[11] = hex[ keyID[5] & 15 ];
1b0709 ¤   buf[12] = hex[ keyID[6] >> 4 ];
755db2 ¤   buf[13] = hex[ keyID[6] & 15 ];
c1b739 ¤   buf[14] = hex[ keyID[7] >> 4 ];
5ded82 ¤   buf[15] = hex[ keyID[7] & 15 ];
97af5a
dff01b ¤   if (len <= 8) {
bbc20c ¤   ¤   return xmemimem(buf+8, 8, pat, len) != NULL;
6d9371 ¤   }
a0af5a
68c584 ¤   /* Here if input keyID was > 8 chars, we look at full 64 bit keyid */
6f1e16 ¤   buf[0] = hex[ keyID[0] >> 4 ];
e344ad ¤   buf[1] = hex[ keyID[0] & 15 ];
7eef17 ¤   buf[2] = hex[ keyID[1] >> 4 ];
18b5ac ¤   buf[3] = hex[ keyID[1] & 15 ];
--a6bf 000a81e4163401001ff Page 37 of pgpRngPub.c
20f405 ¤   buf[4] = hex[ keyID[2] >> 4 ];
2aaebe ¤   buf[5] = hex[ keyID[2] & 15 ];
0d0504 ¤   buf[6] = hex[ keyID[3] >> 4 ];
da5fbf ¤   buf[7] = hex[ keyID[3] & 15 ];
e6af5a
00855d ¤   return xmemimem(buf, 16, pat, len) != NULL;
3cefe6 }
8aaf5a
d4beb7 static int
34eadf predicateFilterName(void *arg, RingIterator *iter,
4b8cd8 ¤   union RingObject *obj, unsigned level)
a9bb36 {
e34da9 ¤   KeySpec const *spec;
e7d777 ¤   RingSet const *set;
b5c0ff ¤   PGPKeyID¤   ¤   keyID;
13b754 ¤   char const *nam;
13875f ¤   PGPSize len;
344ba4 ¤   int i;
2e67c5 ¤
15af5a
3ade23 ¤   if (level > 1)
bc60d2 ¤   ¤   return 1;¤  /* All children included if top level is */
68af5a
6a4e89 ¤   pgpAssert(OBJISKEY(obj));
1caf5a
373c33 ¤   spec = (KeySpec const *)arg;
4b1f84 ¤   set = ringIterSet(iter);
4baf5a
693fab ¤   /* Check for usage */
24f286 ¤   if (spec->use ·&& ·(ringKeyUse(set,obj)&spec->use) != spec->use)
deff91 ¤   ¤   return 0;¤  /* Doesn't have required usage */
b9af5a
1479e6 ¤   if (spec->keyidlen) {
905836 ¤   ¤   ringKeyID8(set, obj, NULL, &keyID);
a75d55 ¤   ¤   if (!matchKeyID( pgpGetKeyBytes( &keyID ),
1b6e17 ¤   ¤   ¤   ¤   spec->keyid, spec->keyidlen))
375b34 ¤   ¤   {
ff5dd9 ¤   ¤   ¤   union RingObject *subkey = ringKeySubkey(set, obj);
f167ca ¤   ¤   ¤   if (!subkey)
4646f1 ¤   ¤   ¤   ¤   return 0;
e7c5da ¤   ¤   ¤   ringKeyID8(set, subkey, NULL, &keyID);
1f4c72 ¤   ¤   ¤   if (!matchKeyID( pgpGetKeyBytes( &keyID ),
5b2129 ¤   ¤   ¤   ¤   ¤   spec->keyid, spec->keyidlen))
3946f1 ¤   ¤   ¤   ¤   return 0;
4a0fe4 ¤   ¤   }
a99371 ¤   }
50af5a
b1d8af ¤   /*
007217 ¤   ·* This isn't quite consistent, because it'll accept a key
59c4ec ¤   ·* with *no* names if the name specification is empty.
c0a4e3 ¤   ·*/
12a662 ¤   if (spec->namelen == 0)
4f733e ¤   ¤   return 1;¤  /* Match! */
a8d8af ¤   /*
4d8f95 ¤   ·* Search names for a matching name. ·If *one* is found,
0f48ef ¤   ·* the entire key, including all names, is taken
14a4e3 ¤   ·*/
ca44a5 ¤   while ((i = ringIterNextObject(iter, 2)) > 0) {
0f0439 ¤   ¤   obj = ringIterCurrentObject(iter, 2);
08204b ¤   ¤   if (ringObjectType(obj) != RINGTYPE_NAME)
8e17f5 ¤   ¤   ¤   continue;
f93b38 ¤   ¤   nam = ringNameName(set, obj, &len);
794ab1 ¤   ¤   if (!nam)
4ee77b ¤   ¤   ¤   return ringSetError(set)->error;
c11b4e ¤   ¤   if (xmemimem(nam, len, spec->name, spec->namelen))
d3ee49 ¤   ¤   ¤   return 1;¤  /* Match, take it! */
429371 ¤   }
102381 ¤   return i;¤  /* No match or error */
44efe6 }
73af5a
4d38e5 /*
a8cd85 ·* Perform filtering based on a keyspec.
--2c64 0005de3d500401001ff Page 38 of pgpRngPub.c
a28559 ·* Use is a PGP_PKUSE value to specify the purpose of the key.
a66cb4 ·* Pass 0 to match all keys. ·PGP_PKUSE_SIGN_ENCRYPT gets only ones which
c1464a ·* can do both things.
67495d ·*/
df4d2f int
18a763 ringSetFilterSpec(RingSet const *src, RingSet *dest,
2cd0c9 ¤   char const *string, int use)
71bb36 {
5081e4 ¤   KeySpec spec;
d2af5a
e0ae28 ¤   keyspecSplit(string, use, &spec);
791ed0 ¤   return ringSetFilter(src, dest, predicateFilterName, (void *)&spec);
c1efe6 }
20af5a
d3af5a
2538e5 /*
bf9794 ·* Find the most recent secret key matching a keyspec.
6cb777 ·* Limit keys to those which have the specified use. ·Pass 0 to match
2e3aaa ·* all uses. ·If tstamp is nonzero, also checks for expiration of keys.
c8495d ·*/
20614e union RingObject *
4cc025 ringLatestSecret(RingSet const *set, char const *string,
613cc7 ¤   ¤   ······PGPUInt32 tstamp, int use)
31bb36 {
1281e4 ¤   KeySpec spec;
783bb6 ¤   RingIterator *iter;
bf39f8 ¤   union RingObject *obj, *best = NULL;
20d7f4 ¤   PGPUInt32 objtime, besttime = 0;
572ed5 ¤   PGPUInt32 exptime;
2c4ba4 ¤   int i;
c5af5a
d76c57 ¤   if (!set)
fa7ed2 ¤   ¤   return NULL;
a1af5a
44bf8d ¤   iter = ringIterCreate(set);
e021b2 ¤   if (!iter)
30ea37 ¤   ¤   return NULL;¤   /* How to distinguish from no luck? */
96ae28 ¤   keyspecSplit(string, use, &spec);
b8af5a
566823 ¤   while (ringIterNextObject(iter, 1) > 0) {
3b21f4 ¤   ¤   obj = ringIterCurrentObject(iter, 1);
49b271 ¤   ¤   pgpAssert(obj);
55c3d2 ¤   ¤   if (!ringKeyIsSec(set, obj))
a917f5 ¤   ¤   ¤   continue;
e2caf3 ¤   ¤   if (ringKeyRevoked(set, obj))
fa17f5 ¤   ¤   ¤   continue;
4c693d ¤   ¤   i = predicateFilterName((void *)&spec, iter, obj, 1);
d54ee1 ¤   ¤   if (!i)
8217f5 ¤   ¤   ¤   continue;
ee3be4 ¤   ¤   if (i < 0) {
0b3f5d ¤   ¤   ¤   ringObjectRelease(best);
482f46 ¤   ¤   ¤   best = NULL;
5acdcb ¤   ¤   ¤   break;
500fe4 ¤   ¤   }
caaf5a
5ef8b7 ¤   ¤   objtime = ringKeyCreation(set, obj);
5181b2 ¤   ¤   exptime = ringKeyExpiration(set, obj);
27a2fd ¤   ¤   if (besttime <= objtime && (!tstamp || !exptime ||
b90aff ¤   ¤   ¤   ¤   ¤   ····tstamp <= exptime)) {
0c3890 ¤   ¤   ¤   ringObjectRelease(best);¤   /* OK if best = NULL */
160ce6 ¤   ¤   ¤   best = obj;
6697a0 ¤   ¤   ¤   ringObjectHold(best);
b43b82 ¤   ¤   ¤   besttime = objtime;
db0fe4 ¤   ¤   }
c99371 ¤   }
b11d89 ¤   ringIterDestroy(iter);
e7e17b ¤   return best;
52efe6 }
7faf5a
adaf5a
1738e5 /*
5d3cee ·* Return key self-sig subpacket information. ·Searches all sigs below
--9214 0003f9cb8bb401001ff Page 39 of pgpRngPub.c
8ecee0 ·* the key for a self sig, finds most recent one with desired info.
d44a8f ·* nth is 0 to find first matching packet, 1 for second, etc. ·The
14b585 ·* semantics have changed from earlier versions in order to facilitate
dc7d64 ·* dynamically adding new packets without invalidating old ones. ·All
25fe7f ·* non-revoked sigs which contain packets of the type we are
92380c ·* interested in get counted. ·pmatches is filled in with the total
2d3637 ·* number of instances in all packets. ·The plen, pcritical, phashed,
b41ff7 ·* and pcreated values are filled in with the signature packet
91c605 ·* corresponding to the nth instance of the data we want.
b2775e ·*
6c82f5 ·* key¤ ¤   ¤   key to use
efd0cc ·* set¤ ¤   ¤   set containing key
cc034c ·* subpacktype¤ subpacket type to search for
64aa26 ·* nth¤ ¤   ¤   nth matching subpacket to find
f38e3a ·* *plen¤   ¤   return length of data
d0d0d1 ·* *pcritical¤  return criticality field of subpacket
a49912 ·* *phashed¤¤   return whether subpacket was in hashed region
abd52b ·* *pcreation¤  return creation time of matching signature
b3dea8 ·* *pmatches¤   return number of matches of this subpack type
325675 ·* *error¤  ¤   return error code
b2775e ·*
24c453 ·* Function returns pointer to the data, of length *plen, or NULL with *error
830636 ·* set for error code. ·If matching packet is not found, return NULL
463c5f ·* with *error = 0.
06495d ·*/
48d929 PGPByte const *
6180e5 ringKeyFindSubpacket (RingObject *obj, RingSet const *set,
5f6738 ¤   int subpacktype, unsigned nth,
d6826f ¤   PGPSize *plen, int *pcritical, int *phashed, PGPUInt32 *pcreation,
3424ce ¤   unsigned *pmatches, PGPError *error)
09bb36 {
8b2034 ¤   RingObject¤ ¤   *sig, *bestsig;
56f62f ¤   RingIterator¤   *iter;
296881 ¤   PGPUInt32¤  ¤   bestcreation;
760aa5 ¤   PGPUInt32¤  ¤   totalmatches;
1d8625 ¤   PGPUInt32¤  ¤   skippedmatches;
08a4eb ¤   PGPByte¤¤   ¤   *p;
367a68 ¤   PGPByte const¤  *bestp;
07dec0 ¤   PGPSize¤¤   ¤   bestlen;
5f3752 ¤   int¤¤   ¤   ¤   bestcritical;
34433e ¤   int¤¤   ¤   ¤   besthashed;
4eaf5a
324e89 ¤   pgpAssert(OBJISKEY(obj));
9d9090 ¤   pgpAssert(pgpIsRingSetMember(set, obj));
3f67c5 ¤
5a1964 ¤   bestlen = bestcritical = besthashed = bestcreation = 0;
2df7c6 ¤   totalmatches = skippedmatches = 0;
177f75 ¤   sig = NULL;
31ee10 ¤   bestp = NULL;
c8a4d0 ¤   bestsig = NULL;
77af5a
d40161 ¤   if (error)
49a79e ¤   ¤   *error = kPGPError_NoErr;
affd79 ¤   iter = ringIterCreate (set);
96f222 ¤   if (!iter) {
2be3c2 ¤   ¤   if (error)
869c64 ¤   ¤   ¤   *error = ringSetError(set)->error;
9f7ed2 ¤   ¤   return NULL;
929371 ¤   }
442a12 ¤   ringIterSeekTo (iter, obj);
58f2a5 ¤   while (TRUE) {
7dcac3 ¤   ¤   int¤¤   level;
6a3362 ¤   ¤   PGPUInt32¤  creation;
795c8f ¤   ¤   uint¤   ¤   matches;
76d3da ¤   ¤   PGPSize¤len;
dbaf5a
f865ff ¤   ¤   if ((level = ringIterNextObjectAnywhere (iter)) <= 0)
8fcdcb ¤   ¤   ¤   break;
27b5e1 ¤   ¤   sig = ringIterCurrentObject (iter, level);
0d1b17 ¤   ¤   /*
b8cfd2 ¤   ¤   ·* Abort when we come to a subkey or another key. ·Sigs on subkeys
3feb9c ¤   ¤   ·* shouldn't count, I don't think.
--1330 000c453950f401001ff Page 40 of pgpRngPub.c
509de3 ¤   ¤   ·*/
4e4077 ¤   ¤   if (OBJISKEY(sig))
44cdcb ¤   ¤   ¤   break;
9401e1 ¤   ¤   if (!OBJISSIG(sig))
7017f5 ¤   ¤   ¤   continue;
c17da4 ¤   ¤   /* Only count self-sigs that have been validated */
6cab6a ¤   ¤   if (ringSigMaker (set, sig, set) != obj)
d217f5 ¤   ¤   ¤   continue;
91d7e9 ¤   ¤   if ((ringSigType (set, sig) & 0xf0) != PGP_SIGTYPE_KEY_GENERIC)
b217f5 ¤   ¤   ¤   continue;
ca11cc ¤   ¤   if (!ringSigChecked (set, sig) || ringSigRevoked (set, sig))
0717f5 ¤   ¤   ¤   continue;
30b322 ¤   ¤   /* Here we have a self signature */
20c284 ¤   ¤   p = (PGPByte *)ringFetchObject(set, sig, &len);
ac7568 ¤   ¤   if (!p) {
86d82b ¤   ¤   ¤   if (error)
ad44d6 ¤   ¤   ¤   ¤   *error = ringSetError(set)->error;
1fcf03 ¤   ¤   ¤   return NULL;
7d0fe4 ¤   ¤   }
a94a94 ¤   ¤   p = (PGPByte *)ringSigFindSubpacket (p, subpacktype, 0, NULL, NULL,
1de08a ¤   ¤   ¤   NULL, &creation, &matches);
104400 ¤   ¤   if (p) {
64d2ba ¤   ¤   ¤   totalmatches += matches;
f4e9d7 ¤   ¤   ¤   if (nth >= totalmatches-matches && nth < totalmatches) {
aeb275 ¤   ¤   ¤   ¤   /* This packet has the nth instance */
d28534 ¤   ¤   ¤   ¤   skippedmatches = totalmatches-matches;
86f64d ¤   ¤   ¤   ¤   bestcreation = creation;
d8dba3 ¤   ¤   ¤   ¤   bestsig = sig;
352778 ¤   ¤   ¤   ¤   ringObjectHold (bestsig);
179fcf ¤   ¤   ¤   ¤   /* If don't need to count all matches, done now */
1f875b ¤   ¤   ¤   ¤   if (!pmatches)
8514c3 ¤   ¤   ¤   ¤   ¤   break;
cea3a6 ¤   ¤   ¤   }
0d0fe4 ¤   ¤   }
f39371 ¤   }
75fedf ¤   ringIterDestroy (iter);
b756d5 ¤   if (bestsig) {
e39219 ¤   ¤   /* This had the sig with the nth instance of the type we need */
b8079f ¤   ¤   p = (PGPByte *)ringFetchObject(set, bestsig, &bestlen);
248785 ¤   ¤   pgpAssert (p);
6e0712 ¤   ¤   /* Note that this may alter the contents of p */
f023af ¤   ¤   bestp = ringSigFindSubpacket (p, subpacktype, nth-skippedmatches,
565581 ¤   ¤   ¤   &bestlen, &bestcritical, &besthashed, NULL, NULL);
d12bca ¤   ¤   ringObjectRelease (bestsig);
c99371 ¤   }
75004e ¤   if (plen)
62d7fc ¤   ¤   *plen = bestlen;
bb92cd ¤   if (pcritical)
57b4a9 ¤   ¤   *pcritical = bestcritical;
d9c48c ¤   if (phashed)
0b022f ¤   ¤   *phashed = besthashed;
eaccf8 ¤   if (pcreation)
c31184 ¤   ¤   *pcreation = bestcreation;
6ae0d2 ¤   if (pmatches)
af004c ¤   ¤   *pmatches = totalmatches;
34e245 ¤   return bestp;
84efe6 }
e1af5a
c2af5a
c038e5 /*
9bdd3b ·* Find an additional decryption key for the given key, if one exists.
2ed33b ·* nth tells which one to find. ·*pkeys is set to the number of add'l
070a9e ·* decryption keys, *pclass is set to the class byte associated with
c2e4c0 ·* the decryption key. ·*pkalg and *keyid are set to the algorithm and
6af1f2 ·* keyid of the nth ADK key. ·Returns NULL but no error in *error if
6f80c7 ·* the ADK key is not in the specified ringset. ·Return *error as
720004 ·* kPGPError_ItemNotFound if there are fewer than n+1 ADKs.
e9495d ·*/
e3614e union RingObject *
db8f9c ringKeyAdditionalRecipientRequestKey (RingObject *obj, RingSet const *set,
ac2680 ¤   unsigned nth, PGPByte *pkalg, PGPKeyID *keyid,
c40976 ¤   PGPByte *pclass, unsigned *pkeys, PGPError *error)
--11d6 0001a11153a401001ff Page 41 of pgpRngPub.c
2cbb36 {
f2e21d ¤   RingObject¤ ···*rkey;¤  ¤   ¤   /* Additional decryption key */
929dbf ¤   PGPByte const ·*krpdata;¤   ¤   /* Pointer to key decryption data */
301163 ¤   PGPSize¤¤   ¤   krdatalen;¤ ¤   /* Length of krdata */
395966 ¤   int¤¤   ¤   ¤   critical;¤  ¤   /* True if decryption field was critical */
7c5ae7 ¤   unsigned¤   ¤   matches;¤   ¤   /* Number of adk's found */
d6650d ¤   PGPByte¤¤   ¤   fingerp[20];¤   /* Fingerprint of adk */
11518f ¤   PGPByte¤¤   ¤   krdata[22];¤¤   /* Copy of key decryption data packet */
ceaf5a
8c4e89 ¤   pgpAssert(OBJISKEY(obj));
3a9090 ¤   pgpAssert(pgpIsRingSetMember(set, obj));
7f4866 ¤   pgpAssert (error);
a5af5a
5531ff ¤   *error¤ = kPGPError_NoErr;
1cd2c0 ¤   if( IsntNull( pkeys ) )
ce8fb3 ¤   ¤   *pkeys¤ = 0;
c23500 ¤   if( IsntNull( pclass ) )
fed08d ¤   ¤   *pclass¤= 0;
f9d368 ¤   if( IsntNull( pkalg ) )
a31e51 ¤   ¤   *pkalg = 0;
fc4db5 ¤   if( IsntNull( keyid ) )
eec7a1 ¤   {
4404c0 ¤   ¤   pgpClearMemory( keyid, sizeof( *keyid ) );
f39371 ¤   }
2567c5 ¤
c81c05 ¤   krpdata = ringKeyFindSubpacket (obj, set,
1ba1bc ¤   ¤   SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST, nth, &krdatalen,
3cfef0 ¤   ¤   &critical, NULL, NULL, &matches, error);
e5d2d2 ¤   if (!krpdata) {
99e405 ¤   ¤   if (IsntPGPError(*error))
c1e395 ¤   ¤   ¤   *error = kPGPError_ItemNotFound;
0d7ed2 ¤   ¤   return NULL;
4f9371 ¤   }
8ad8af ¤   /*
413c4e ¤   ·* krdata is 1 byte of class, 1 of pkalg, 20 bytes of fingerprint.
18030b ¤   ·* Last 8 of 20 are keyid. ·Make a copy because data is volatile when
f2225d ¤   ·* we do other operations.
4aa4e3 ¤   ·*/
70af5a
9725c5 ¤   if (krdatalen < sizeof(krdata)) {
c5cca9 ¤   ¤   /* malformed packet, can't use it */
00e52d ¤   ¤   *error = kPGPError_ItemNotFound;
3a7ed2 ¤   ¤   return NULL;
859371 ¤   }
c8b7c2 ¤   pgpCopyMemory (krpdata, krdata, sizeof(krdata));
d8af5a
7b0b76 ¤   /* Do we have ADK? */
e2fc3a ¤   rkey = ringKeyById8 (set, krdata[1], krdata+2+20-8);
e62231 ¤   if (IsntNull (rkey)) {
cf9bb2 ¤   ¤   if (pgpVirtMaskIsEmpty(&rkey->g.mask)) {
320917 ¤   ¤   ¤   rkey = NULL;
0645a6 ¤   ¤   } else {
9e083b ¤   ¤   ¤   ringKeyFingerprint20 (set, rkey, fingerp);
d09561 ¤   ¤   ¤   if (memcmp (fingerp, krdata+2, 20) != 0) {
1c50e2 ¤   ¤   ¤   ¤   /* Have a key that matches in keyid but wrong fingerprint */
aa3d4a ¤   ¤   ¤   ¤   rkey = NULL;
32a3a6 ¤   ¤   ¤   }
c80fe4 ¤   ¤   }
f69371 ¤   }
df0d42 ¤   /* Success */
54ff5b ¤   if (pkeys) {
b620f9 ¤   ¤   *pkeys = matches;
5c9371 ¤   }
3c78ef ¤   if (pclass) {
ee8087 ¤   ¤   *pclass = krdata[0];
5c9371 ¤   }
515f4a ¤   if (pkalg) {
22e068 ¤   ¤   *pkalg = krdata[1];
579371 ¤   }
d85b70 ¤   if (keyid) {
185f44 ¤   ¤   pgpNewKeyIDFromRawData( krdata+2+20-8, 8, keyid );
1a9371 ¤   }
--6925 000f8d654d6401001ff Page 42 of pgpRngPub.c
76b537 ¤   return rkey;
21efe6 }
cbaf5a
ca67c5 ¤
7138e5 /*
2feff1 ·* Find a key revocation key and keyid for the given key. ·nth tells
b88165 ·* which one to find. ·*pkeys is set to the number of key revocation
8663eb ·* keys, *pclass is set to the class byte associated with the
3f5057 ·* revocation key. ·Returns NULL but no error in *error if the ADK key
54ddc3 ·* is not in the specified ringset. ·Return *error as
16641c ·* kPGPError_ItemNotFound if there are fewer than n+1 ADKs. ·The class
93ddcb ·* byte is intended for future expansion; for now the high order bit
427d64 ·* is used to indicate a revocation authorization. ·Later we could use
0d94df ·* the other bits to authorize other kinds of signatures, perhaps.
b0495d ·*/
c8614e union RingObject *
3db0f7 ringKeyRevocationKey (union RingObject *obj, RingSet const *set, unsigned nth,
655889 ¤   PGPByte *pkalg, PGPKeyID *keyid, PGPByte *pclass, unsigned *pkeys,
b8a900 ¤   PGPError *error)
2bbb36 {
095fe0 ¤   RingObject¤ ···*rkey;¤  ¤   ¤   /* Message revocation key */
2a5620 ¤   PGPByte const ·*krpdata;¤   ¤   /* Pointer to key revocation data */
261163 ¤   PGPSize¤¤   ¤   krdatalen;¤ ¤   /* Length of krdata */
3510e7 ¤   int¤¤   ¤   ¤   critical;¤  ¤   /* True if revocation field was critical */
174e65 ¤   unsigned¤   ¤   matches;¤   ¤   /* Number of revkey packets found */
1202ca ¤   PGPByte¤¤   ¤   fingerp[20];¤   /* Fingerprint of revkey */
ae51f9 ¤   PGPByte¤¤   ¤   krdata[22];¤¤   /* Copy of key revocation data packet */
1baf5a
494e89 ¤   pgpAssert(OBJISKEY(obj));
709090 ¤   pgpAssert(pgpIsRingSetMember(set, obj));
934866 ¤   pgpAssert (error);
f1af5a
ed31ff ¤   *error¤ = kPGPError_NoErr;
dfd2c0 ¤   if( IsntNull( pkeys ) )
ab8fb3 ¤   ¤   *pkeys¤ = 0;
1b3500 ¤   if( IsntNull( pclass ) )
a7d08d ¤   ¤   *pclass¤= 0;
d1d368 ¤   if( IsntNull( pkalg ) )
0f1e51 ¤   ¤   *pkalg = 0;
2c4db5 ¤   if( IsntNull( keyid ) )
3ac7a1 ¤   {
0d04c0 ¤   ¤   pgpClearMemory( keyid, sizeof( *keyid ) );
009371 ¤   }
f567c5 ¤
c52816 ¤   krpdata = ringKeyFindSubpacket (obj, set, SIGSUB_KEY_REVOCATION_KEY, nth,
5c8f7d ¤   ¤   &krdatalen, &critical, NULL, NULL, &matches, error);
eed2d2 ¤   if (!krpdata) {
39e405 ¤   ¤   if (IsntPGPError(*error))
9ee395 ¤   ¤   ¤   *error = kPGPError_ItemNotFound;
647ed2 ¤   ¤   return NULL;
ac9371 ¤   }
a3d8af ¤   /*
4e3c4e ¤   ·* krdata is 1 byte of class, 1 of pkalg, 20 bytes of fingerprint.
ab030b ¤   ·* Last 8 of 20 are keyid. ·Make a copy because data is volatile when
24225d ¤   ·* we do other operations.
c1a4e3 ¤   ·*/
35af5a
db25c5 ¤   if (krdatalen < sizeof(krdata)) {
90cca9 ¤   ¤   /* malformed packet, can't use it */
cee52d ¤   ¤   *error = kPGPError_ItemNotFound;
af7ed2 ¤   ¤   return NULL;
979371 ¤   }
85b7c2 ¤   pgpCopyMemory (krpdata, krdata, sizeof(krdata));
9aaf5a
06fd42 ¤   /* Do we have revocation packet? */
07fc3a ¤   rkey = ringKeyById8 (set, krdata[1], krdata+2+20-8);
f2642c ¤   if (IsntNull (rkey) ) {
e79bb2 ¤   ¤   if (pgpVirtMaskIsEmpty(&rkey->g.mask)) {
3d0917 ¤   ¤   ¤   rkey = NULL;
2345a6 ¤   ¤   } else {
d4083b ¤   ¤   ¤   ringKeyFingerprint20 (set, rkey, fingerp);
f89561 ¤   ¤   ¤   if (memcmp (fingerp, krdata+2, 20) != 0) {
--736f 000b3521c90401001ff Page 43 of pgpRngPub.c
7450e2 ¤   ¤   ¤   ¤   /* Have a key that matches in keyid but wrong fingerprint */
193d4a ¤   ¤   ¤   ¤   rkey = NULL;
04a3a6 ¤   ¤   ¤   }
8e0fe4 ¤   ¤   }
6c9371 ¤   }
4d41d3 ¤   /* Else success */
c9ff5b ¤   if (pkeys) {
5a20f9 ¤   ¤   *pkeys = matches;
419371 ¤   }
3d78ef ¤   if (pclass) {
fc8087 ¤   ¤   *pclass = krdata[0];
da9371 ¤   }
d45f4a ¤   if (pkalg) {
49e068 ¤   ¤   *pkalg = krdata[1];
009371 ¤   }
325b70 ¤   if (keyid) {
1f5f44 ¤   ¤   pgpNewKeyIDFromRawData( krdata+2+20-8, 8, keyid );
9b9371 ¤   }
7cb537 ¤   return rkey;
b9efe6 }
87af5a
48af5a
ec38e5 /*
9a1a8f ·* Return true if rkey is a revocation key for key.
06e6ec ·* Includes case where rkey is a dummy key which has issued a signature
08b941 ·* but is not local to the keyring. ·In that case we just check for match
9ad703 ·* on keyid and pkalg.
99495d ·*/
e67750 PGPBoolean
a94476 ringKeyIsRevocationKey (RingObject *key, RingSet const *set, RingObject *rkey)
fabb36 {
17e67c ¤   PGPByte¤¤   ¤   ¤   ·revClass;
21190e ¤   PGPUInt32¤  ¤   ¤   ·nRevKeys;
c1ddfb ¤   PGPUInt32¤  ¤   ¤   ·iRevKeys;
af9263 ¤   PGPByte¤¤   ¤   ¤   ·revAlg;
00d64d ¤   PGPByte¤¤   ¤   ¤   ·rKeyAlg;
71bf4a ¤   PGPKeyID¤   ¤   ¤   ·revKeyID;
f3d170 ¤   PGPKeyID¤   ¤   ¤   ·rKeyID;
aff893 ¤   PGPBoolean¤ ¤   ¤   ·nonLocal;
ff1a4f ¤   PGPError¤   ¤   ¤   ·error;
48af5a
2029b0 ¤   nonLocal = pgpVirtMaskIsEmpty(&rkey->g.mask);
92aa62 ¤   if (nonLocal) {
dc8663 ¤   ¤   ringKeyID8 (set, rkey, &rKeyAlg, &rKeyID);
009371 ¤   }
89af5a
26d66b ¤   nRevKeys = 1;
a2fc30 ¤   iRevKeys = 0;
ef9675 ¤   while (iRevKeys < nRevKeys) {
e637c2 ¤   ¤   RingObject const *revkey;
ca132b ¤   ¤   revkey = ringKeyRevocationKey(key, set, iRevKeys++, &revAlg, &revKeyID,
862af0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&revClass, &nRevKeys, &error);
a897ad ¤   ¤   if (IsPGPError(error))
a2cdcb ¤   ¤   ¤   break;
8e7f49 ¤   ¤   if (!(revClass & 0x80))
c117f5 ¤   ¤   ¤   continue;
b4d096 ¤   ¤   if (nonLocal) {
c982c0 ¤   ¤   ¤   if (rKeyAlg == revAlg &&
2b3c0e ¤   ¤   ¤   ¤   0 == PGPCompareKeyIDs (&rKeyID, &revKeyID))
b506e0 ¤   ¤   ¤   ¤   return TRUE;
ae5418 ¤   ¤   } else if (revkey == rkey) {
9632bd ¤   ¤   ¤   return TRUE;
3e0fe4 ¤   ¤   }
8a9371 ¤   }
cda230 ¤   return FALSE;
35efe6 }
4867c5 ¤
38af5a
8a38e5 /*
fb7122 ·* True if there is a third party revocation signature on the given
f7dd06 ·* key. ·Return the key (if local) and the keyid of the revoking key.
b3fbf3 ·* Note that this requires that there be both a revoking authorization
--879d 00032d10d3c401001ff Page 44 of pgpRngPub.c
8a46f0 ·* on the revoker key and a revocation issued by that key.
68495d ·*/
d07750 PGPBoolean
32e036 ringKeyHasThirdPartyRevocation (RingObject *obj, RingSet const *set,
a09db8 ¤   RingObject **revkey, PGPByte *pkalg, PGPKeyID *keyid, PGPError *error)
30bb36 {
048465 ¤   RingObject¤ ¤   *topkey;
b158e2 ¤   RingObject¤ ¤   *sig;
f713fa ¤   PGPByte¤¤   ¤   ·rKeyAlg;
47167b ¤   PGPKeyID¤   ¤   ·rKeyID;
e2af5a
054e89 ¤   pgpAssert(OBJISKEY(obj));
819090 ¤   pgpAssert(pgpIsRingSetMember(set, obj));
b64866 ¤   pgpAssert (error);
d2af5a
5b31ff ¤   *error¤ = kPGPError_NoErr;
448f8d ¤   if( IsntNull( revkey ) )
4d3743 ¤   ¤   *revkey = NULL;
97d368 ¤   if( IsntNull( pkalg ) )
bd1e51 ¤   ¤   *pkalg = 0;
5b4db5 ¤   if( IsntNull( keyid ) )
12c7a1 ¤   {
4704c0 ¤   ¤   pgpClearMemory( keyid, sizeof( *keyid ) );
aa9371 ¤   }
30af5a
ff5e51 ¤   /* May be called on subkey, so find top level key */
c637ec ¤   topkey = obj;
631a32 ¤   if (OBJISSUBKEY(topkey))
535fb6 ¤   ¤   topkey = ringKeyMasterkey (set, topkey );
1267c5 ¤
d80029 ¤   /* Search for a revocation signature on this key */
0fdf88 ¤   for (sig=obj->g.down; sig; sig=sig->g.next) {
f301e1 ¤   ¤   if (!OBJISSIG(sig))
9417f5 ¤   ¤   ¤   continue;
5323f4 ¤   ¤   if (sig->s.type != ( (topkey==obj) ? PGP_SIGTYPE_KEY_REVOKE
e7331a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···: PGP_SIGTYPE_KEY_SUBKEY_REVOKE ))
4317f5 ¤   ¤   ¤   continue;
8cc5a2 ¤   ¤   if (sig->s.by == topkey)
9217f5 ¤   ¤   ¤   continue;
f2af5a
78ed1d ¤   ¤   if (ringKeyIsRevocationKey (topkey, set, sig->s.by))
1fcdcb ¤   ¤   ¤   break;
519371 ¤   }
d4af5a
bbfd61 ¤   if (IsNull (sig)) {
0f8a09 ¤   ¤   /* No luck */
bd98aa ¤   ¤   return FALSE;
be9371 ¤   }
c9af5a
cf8b3c ¤   if( IsntNull( revkey ) ) {
ec4a5c ¤   ¤   if (!pgpVirtMaskIsEmpty (&sig->s.by->g.mask))
a81878 ¤   ¤   *revkey = sig->s.by;
579371 ¤   }
02af5a
c35c16 ¤   ringKeyID8 (set, sig->s.by, &rKeyAlg, &rKeyID);
8d67c5 ¤
515f4a ¤   if (pkalg) {
3389ff ¤   ¤   *pkalg = rKeyAlg;
4a9371 ¤   }
255b70 ¤   if (keyid) {
bcca9a ¤   ¤   *keyid = rKeyID;
ee9371 ¤   }
00c2e7 ¤   return TRUE;
53efe6 }
73af5a
0baf5a
9a38e5 /*
8ccfe5 ·* Create a SigSpec structure which represents the given signature.
08e7d2 ·* We must have the signing key as a private key. ·We would have to
e87cc7 ·* change the initialization of pgpSigSpec to avoid this, but normally
db2db4 ·* the reason for doing this is to re-issue a modified signature, so it
32699a ·* is a reasonable restriction.
--59a4 000447f4cc2401001ff Page 45 of pgpRngPub.c
47495d ·*/
d59d57 PGPSigSpec *
47a0a7 ringSigSigSpec (RingObject *sig, RingSet const *set,
17a900 ¤   PGPError *error)
a7bb36 {
f02560 ¤   PGPContextRef cdkContext;
4ca3d2 ¤   PGPEnv *env;
e7dafa ¤   PGPSecKey *signkey;
324cc9 ¤   PGPByte *p;
620f2f ¤   PGPSigSpec *spec;
21875f ¤   PGPSize len;
e1af5a
148a21 ¤   (void)set;
552b90 ¤   pgpAssert(OBJISSIG(sig));
25c592 ¤   pgpAssert(pgpIsRingSetMember(set, sig));
b25aed ¤   pgpAssert( IsntNull( error ) );
659096 ¤   *error = kPGPError_NoErr;
22af5a
91540f ¤   cdkContext = set->pool->context;
57d153 ¤   env = pgpContextGetEnvironment( cdkContext );
12af5a
fef720 ¤   /* Get signing key - note that this corrupts ringFetchObject buffer */
9868f6 ¤   signkey = ringSecSecKey (set, sig->s.by, PGP_PKUSE_SIGN);
f3a126 ¤   if (!signkey) {
f20dfc ¤   ¤   *error = ringSetError(set)->error;
fa7ed2 ¤   ¤   return NULL;
419371 ¤   }
94af5a
069c41 ¤   spec = pgpSigSpecCreate (env, signkey, sig->s.type);
2e686e ¤   pgpSecKeyDestroy (signkey);
47c611 ¤   if( IsNull( spec ) ) {
10e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
a57ed2 ¤   ¤   return NULL;
dc9371 ¤   }
95af5a
5ea5be ¤   /* Fetch data for sig */
039728 ¤   p = (PGPByte *)ringFetchObject(set, sig, &len);
15f24d ¤   if( IsNull( p ) ) {
6efde9 ¤   ¤   pgpSigSpecDestroy (spec);
c80dfc ¤   ¤   *error = ringSetError(set)->error;
a27ed2 ¤   ¤   return NULL;
4d9371 ¤   }
daaf5a
affc0b ¤   pgpSigSpecSetHashtype (spec, sig->s.hashalg);
cd322b ¤   pgpSigSpecSetVersion (spec, p[0]);
2484be ¤   pgpSigSpecSetTimestamp (spec, sig->s.tstamp);
1faf5a
0f75aa ¤   /* Incorporate data from subpackets if present */
3b169d ¤   if (pgpSigSpecVersion(spec) == PGPVERSION_4) {
1e5752 ¤   ¤   *error = ringSigSubpacketsSpec (spec, p);
e366e7 ¤   ¤   if (IsPGPError(*error)) {
64129a ¤   ¤   ¤   pgpSigSpecDestroy (spec);
4dcf03 ¤   ¤   ¤   return NULL;
4b0fe4 ¤   ¤   }
9e9371 ¤   }
06b45f ¤   return spec;
daefe6 }
daaf5a
2730c4 /* Check obj for consistency, make sure valid mask bits are in
252474 ·* parent mask
72495d ·*/
fe2978 static void
d548a1 ringObjCheck (RingPool *pool, union RingObject *obj, PGPVirtMask *validmask,
08b99c ¤   ¤   ¤   ··PGPVirtMask *parentmask)
0abb36 {
9045d1 ¤   PGPVirtMask mask;
cce8c6 ···
3714fb ¤   pgpVirtMaskInit (pool, &mask);
32a62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
0deaa8 ¤   pgpVirtMaskAND (pool, validmask, &mask);
3c1086 ¤   pgpVirtMaskANDNOT (pool, parentmask, &mask);
44a6dc ¤   if (!pgpVirtMaskIsEmpty(&mask)) {
--6952 00168c26c5c401001ff Page 46 of pgpRngPub.c
7fb6cc ¤   ¤   pgpDebugMsg( "Child ringobj set not subset of parent set" );
5c9371 ¤   }
99af5a
218dc7 ¤   if (OBJISSIG(obj)) {
54a174 ¤   ····/* ·sig should point to top-level key */·
6769d6 ¤   ¤   if (!OBJISTOPKEY(obj->s.by)) {
7074e0 ¤   ¤   ¤   pgpDebugMsg( "Signature by other than top-level key" );
be0fe4 ¤   ¤   }
989371 ¤   }
7f436d ¤   if (!OBJISBOT(obj)) {
faa9b3 ¤   ¤   for (obj=obj->g.down; obj; obj=obj->g.next) {
55e093 ¤   ¤   ¤   pgpVirtMaskCopy (pool, parentmask, &mask);
a90c62 ¤   ¤   ¤   pgpVirtMaskAND (pool, &obj->g.mask, &mask);
1deb1d ¤   ¤   ¤   ringObjCheck (pool, obj, validmask, &mask);
be0fe4 ¤   ¤   }
0b9371 ¤   }
550db9 ¤   pgpVirtMaskCleanup (pool, &mask);
eaefe6 }
d7af5a
43723a /* Perform a consistency check on ring pool data structures */
5c314a void
be2561 ringPoolConsistent (RingPool *pool, int *pnsets, int *pnfiles)
b7bb36 {
a4d71b ¤   PGPVirtMask allocmask;
b945d1 ¤   PGPVirtMask mask;
b4c958 ¤   RingSet *set;
a4a997 ¤   union RingObject *obj;
e66a1b ¤   PGPInt32 bit;
82af5a
326197 ¤   pgpVirtMaskInit (pool, &allocmask);
3214fb ¤   pgpVirtMaskInit (pool, &mask);
58af5a
cbec34 ¤   for (set = pool->sets; set; set = set->next)
d2f49a ¤   ¤   pgpVirtMaskOR (pool, &set->mask, &allocmask);
25af5a
3f42b7 ¤   pgpAssert (!pgpVirtMaskIsOverlapping (&allocmask, &pool->filemask));
02af5a
ea464f ¤   pgpVirtMaskCopy (pool, &allocmask, &mask);
e98329 ¤   pgpVirtMaskOR (pool, &pool->filemask, &mask);
feaf5a
57f5cb ¤   for (obj=pool->keys; obj; obj=obj->g.next) {
c317ff ¤   ¤   ringObjCheck (pool, obj, &mask, &mask);
b39371 ¤   }
1bec50 ¤   if (pnsets) {
3b008a ¤   ¤   int nsets = 0;
2cb7e0 ¤   ¤   while (!pgpVirtMaskIsEmpty(&allocmask)) {
9f6d31 ¤   ¤   ¤   ++nsets;
6854e7 ¤   ¤   ¤   bit = pgpVirtMaskLSBit(&allocmask);
7e0887 ¤   ¤   ¤   pgpVirtMaskClearBit (pool, &allocmask, bit);
d10fe4 ¤   ¤   }
0b7117 ¤   ¤   *pnsets = nsets;
eb9371 ¤   }
a61bcb ¤   pgpVirtMaskCopy (pool, &pool->filemask, &mask);
abf942 ¤   if (pnfiles) {
afc12c ¤   ¤   int nfiles = 0;
0bffeb ¤   ¤   while (!pgpVirtMaskIsEmpty(&mask)) {
baf236 ¤   ¤   ¤   ++nfiles;
d45f06 ¤   ¤   ¤   bit = pgpVirtMaskLSBit(&mask);
725c06 ¤   ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
bd0fe4 ¤   ¤   }
12d9fd ¤   ¤   *pnfiles = nfiles;
889371 ¤   }
b8af5a
ee8cff ¤   pgpVirtMaskCleanup (pool, &allocmask);
050db9 ¤   pgpVirtMaskCleanup (pool, &mask);
68efe6 }
--e047 000dc9d5ce540100200 Page 1 of pgpRngPub.h
bc38e5 /*
26e070 ·* $Id: pgpRngPub.h,v 1.43.2.1 1998/10/10 21:06:00 hal Exp $
3c495d ·*/
07af5a
9a5219 #ifndef Included_pgpRngPub_h
abd32f #define Included_pgpRngPub_h
037d66 /* Public */
66af5a
3bd11f #include "pgpUsuals.h"
474c8a #include "pgpContext.h"¤¤   /* for PGPContextRef */
20af5a
f999c6 PGP_BEGIN_C_DECLARATIONS
d6af5a
64ed84 typedef enum {
8eb466 ¤   PGPTRUST0=0, PGPTRUST1, PGPTRUST2
39507d } PgpTrustModel;
11af5a
b6299f /* Signature subpacket types. ·Many of these are not supported yet. */
0f8b12 enum sigsubbyte {
30d3f3 ¤   /* Signature specific properties */
f9a1b7 ¤   SIGSUB_VERSION¤ ¤   ¤   = 1,
38eaa8 ¤   SIGSUB_CREATION,
b968ee ¤   SIGSUB_EXPIRATION,
b3942b ¤   SIGSUB_EXPORTABLE,
4091b4 ¤   SIGSUB_TRUST,
b43396 ¤   SIGSUB_REGEXP,
085524 ¤   SIGSUB_REVOCABLE,
945e95 ¤   /* Properties of key being self signed */
725acf ¤   SIGSUB_KEY_CAPABILITIES = 8,
5218cc ¤   SIGSUB_KEY_EXPIRATION,
fb7421 ¤   SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST,
faf053 ¤   SIGSUB_PREFERRED_ENCRYPTION_ALGS,
4dadb4 ¤   SIGSUB_KEY_REVOCATION_KEY,
f2bdf0 ¤   /* Hints to find signer */
00175b ¤   SIGSUB_KEYID¤   ¤   ¤   = 16,
18f7b8 ¤   SIGSUB_USERID,
90bc51 ¤   SIGSUB_URL,
f701c7 ¤   SIGSUB_FINGER,
8a03ed ¤   /* Miscellaneous packets */
6bbea7 ¤   SIGSUB_NOTATION¤¤   ¤   = 20,
d48228 ¤   SIGSUB_PREFERRED_HASH_ALGS,
aad24b ¤   SIGSUB_PREFERRED_COMPRESSION_ALGS,
473418 ¤   SIGSUB_KEYSERVER_PREFERENCES,
9f5d32 ¤   SIGSUB_PREFERRED_KEYSERVER,
10390f ¤   SIGSUB_PRIMARY_USERID,
818570 ¤   SIGSUB_POLICY_URL,
69940f ¤   SIGSUB_KEYFLAGS,
534e77 ¤   SIGSUB_SIGNER_USERID¤   = 28,
72c745 ¤   SIGSUB_REVOCATION_REASON,
b20fb6 ¤   /* X509 imported certificate */
5f9320 ¤   SIGSUB_X509¤¤   ¤   ¤   = 32,
37e20b ¤   /* Used internally for unrecognized packet types */
0dfb45 ¤   SIGSUB_UNRECOGNIZED¤¤   = 255¤  /* crit bit is ignored here */
4b82f7 };
40af5a
46b3e2 /* Critical bit means we must handle this subpacket */
f6f285 #define SIGSUBF_CRITICAL¤   0x80
7eaf5a
58382a /* Flag bits within SIGSUB_KEYFLAGS */
98e30a #define SIGSUBF_KEYFLAG0_USAGE_CERTIFY¤ ¤   ¤   0x01
f31a14 #define SIGSUBF_KEYFLAG0_USAGE_SIGN¤¤   ¤   ¤   0x02
6a295e #define SIGSUBF_KEYFLAG0_USAGE_ENCRYPT_COMM¤¤   0x04
ba2dd6 #define SIGSUBF_KEYFLAG0_USAGE_ENCRYPT_STORAGE¤ 0x08
c00b19 /* Meaningful only on self signature */
494725 #define SIGSUBF_KEYFLAG0_PRIVATE_SPLIT¤ ¤   ¤   0x10
99ea50 #define SIGSUBF_KEYFLAG0_PRIVATE_SHARED¤¤   ¤   0x80
89af5a
b067d5 /* Flag bits within SIGSUB_KEYSERVER_PREFERENCES */
eed9f9 #define SIGSUBF_KEYSERVER0_
2aaf5a
76af5a
dcadb8 #include "pgpOpaqueStructs.h"
--7092 000cac71f3040100200 Page 2 of pgpRngPub.h
e0af5a
d338e5 /*
1a0008 ·* Okay, finally we start the function declarations.
d1495d ·*/
78d294 RingPool ·*ringPoolCreate(PGPEnv const *env);
f83a36 /* Destroy everything immediately, dropping all locks! */
e895fc void ·ringPoolDestroy(RingPool *);
080b13 PGPContextRef ringPoolContext(RingPool *pool);
cdaf5a
8d7c03 struct RingError
96bb36 {
e40694 ¤   RingFile *¤ f;¤ /* The RingFile for I/O errors */
c07e9c ¤   PGPUInt32¤  fpos;¤  /* The file position for I/O errors */
3fe08c ¤   PGPError¤   error;¤ /* PGP error code - kPGPError_* */
42d308 ¤   int¤¤   ¤   syserrno;¤  /* Don't use plain "errno"; that's a macro! */
c982f7 };
f2af5a
c450d7 RingError const ·*ringPoolError(RingPool const *);
e23e56 void ·ringPoolClearError(RingPool *);
f7af5a
6a38e5 /*
343996 ·* A RingSet is the root of a tree of objects. ·The RingSet itself
70913d ·* is not a RingObject, but everything else under it is.
52ef0f ·* A full tree looks basically like this:
02c02a ·* RingSet
dcaa32 ·* ·+--Key
9652b7 ·* ·| ··+--Secret (0 or more)
f5736f ·* ·| ··+--Signature (0 or more)
86736f ·* ·| ··+--Signature (0 or more)
6f458b ·* ·| ··+--Name (0 or more)
6e93ea ·* ·| ··| ··+--Signature (0 or more)
b3508a ·* ·| ··| ··\--Signature (0 or more)
4c810b ·* ·| ··\--Name (0 or more)
92a0c7 ·* ·| ······\--Signature (0 or more)
edaa32 ·* ·+--Key
0a629b ·* ·| ··+--etc.
8fe6ce ·* etc.
e7775e ·*
f98c63 ·* A "secret" object is present if the key's secret components are
472ebf ·* available. ·In the standard PGP keyring file format, this is
39399a ·* actually stored with the key as a different type of key packet,
3afa19 ·* but the representation here is logically equivalent.
6e775e ·*
7bbbe1 ·* There is one secret object per encrypted form of the secret
a574f4 ·* components. ·Barring duplicate key errors, there is only one
902a36 ·* secret object per file (if you attempt to write out more, the
fee0f4 ·* library will make a guess at the best and write that out), but,
6f23d9 ·* for example, changing the passphrase will create a second secret.
35775e ·*
62b332 ·* Some sets are mutable, and RingObjects can be added to or deleted from
e9115d ·* them, but the tree property is always preserved. ·Adding an object
5c87b8 ·* implicitly adds all of its parents. ·Deleting an object implicitly
7b814c ·* deletes all of its children.
cd495d ·*/
ed1dc5 int ·ringObjectType(union RingObject const *obj);
22de5a /* Type 0 is reserved for application use; it will never be allocated */
0ed35e #define RINGTYPE_KEY¤   1
ca25f6 #define RINGTYPE_SEC¤   2
d07fea #define RINGTYPE_NAME¤  3
902532 #define RINGTYPE_SIG¤   4
82830f #define RINGTYPE_UNK¤   5¤  /* Object of unknown type */
19992a #define RINGTYPE_MAX¤   5
4a409e /* Adding a new type needs to update ringObjectType() and ringNewObject() */
eaaf5a
1038e5 /*
21df87 ·* Increase and decrease RingObject reference counts. ·The ringIter
84d495 ·* functions hold their current objects (at the current level and all
ec9d20 ·* parent levels) automatically and release them when the ringIterator is
fe5475 ·* advanced to another location. ·If you wish to refer to them after
21b0a4 ·* advancing the RingIterator, Other functions that return RingObject
5255e9 ·* pointers hold them automatically, and they must be released explicitly
ca7a50 ·* by ringObjectRelease().
--0c81 000e017ca5840100200 Page 3 of pgpRngPub.h
47495d ·*/
23ee35 void ·ringObjectHold(union RingObject *obj);
5d5e68 void ·ringObjectRelease(union RingObject *obj);
d9af5a
0826d6 /* Operations on RingSets */
53af5a
bad69f RingPool ·*ringSetPool(RingSet const *);
98af5a
567054 RingError const ·*ringSetError(RingSet const *);
47043f void ·ringSetClearError(RingSet *);
91af5a
cb0bcb int ·ringSetIsMember(RingSet const *set,
ac530e ¤   union RingObject const *object);
aff54e int ·ringSetCount(RingSet const *set, unsigned *counts,
501212 ¤   unsigned depth);
7ce748 int ·ringSetCountTypes(RingSet const *set, unsigned *counts,
2673ed ¤   unsigned max);
ccaf5a
88bf59 /* Create a new mutable RingSet */
29d0c0 RingSet ·*ringSetCreate(RingPool *pool);
0ea030 /* Free a RingSet (mutable or immutable) */
3af89f void ·ringSetDestroy(RingSet *set);
cdaf5a
0c49ba /* Operate on a mutable RingSet */
4ec924 int ·ringSetAddObject(RingSet *set, union RingObject *obj);
913be3 int ·ringSetRemObject(RingSet *set, union RingObject *obj);
e00758 int ·ringSetAddSet(RingSet *set, RingSet const *set2);
eba08b int ·ringSetSubtractSet(RingSet *set,
a9f792 ¤   RingSet const *set2);
85aa03 int ·ringSetAddObjectChildren(RingSet *dest,
d680bb ¤   RingSet const *src, union RingObject *obj);
46725e /* Convert a mutable RingSet to immutable */
6d64cd PGPError ·ringSetFreeze(RingSet *set);
87af5a
3fed39 /* Operate on immutable RingSets */
28c753 RingSet ·*ringSetCopy(RingSet const *s);
e2a35b RingSet ·*
2c786c ringSetUnion(RingSet const *s1, RingSet const *s2);
5da35b RingSet ·*
2edbbe ringSetIntersection(RingSet const *s1, RingSet const *s2);
3ea35b RingSet ·*
f689e2 ringSetDifference(RingSet const *s1, RingSet const *s2);
fbaf5a
62756e /* Lookups by keyID */
0c5174 union RingObject ·*
e3e1fb ringKeyById4(RingSet const *set, PGPByte pkalg, PGPByte const *keyid);
b45174 union RingObject ·*
10548b ringKeyById8(RingSet const *set, PGPByte pkalg, PGPByte const *keyid);
8baf5a
da9a33 /* Operations on RingIterators */
4faf5a
43869f RingIterator ·*ringIterCreate(RingSet const *set);
51c683 void ·ringIterDestroy(RingIterator *iter);
31ff6e RingSet const ·*ringIterSet(RingIterator const *iter);
1b3787 RingError const ·*ringIterError(
dc0a11 ¤   RingIterator const *iter);
3818e1 void ·ringIterClearError(RingIterator *iter);
a412f9 int ·ringIterNextObject(RingIterator *iter, unsigned level);
646019 int ·ringIterPrevObject(RingIterator *iter, unsigned level);
b081dc unsigned ·ringIterCurrentLevel(RingIterator const *iter);
f11571 union RingObject ·*ringIterCurrentObject(
472358 ¤   RingIterator const *iter, unsigned level);
f6af5a
41f529 int ·ringIterNextObjectAnywhere(RingIterator *iter);
5a7d25 int ·ringIterRewind(RingIterator *iter, unsigned level);
2db228 int ·ringIterFastForward(RingIterator *iter, unsigned level);
993041 int ·ringIterSeekTo(RingIterator *iter, union RingObject *obj);
9caf5a
561987 /* RingFile access functions */
cfaf5a
cc53d5 struct PGPFile ·*ringFileFile(RingFile const *file);
e002b0 RingSet const ·*ringFileSet(RingFile const *file);
--5bb5 000f65bb69440100200 Page 4 of pgpRngPub.h
355576 PgpVersion ·ringFileVersion(RingFile const *file);
7aaf5a
27247a int ·ringFileIsDirty(RingFile const *file);
3d8d3b int ·ringFileIsTrustChanged(RingFile const *file);
2caf5a
8a6afe PGPError ·ringFileSwitchFile(RingFile *file, struct PGPFile *newPGPFile);
b1af5a
e78e48 /* Alias for ringSetError(ringFileSet(file)) */
f8aaee RingError const ·*ringFileError(RingFile const *file);
eff814 void ·ringFileClearError(RingFile *file);
1eaf5a
03fcf4 int·
c9b010 ringSetFilter(RingSet const *src, RingSet *dest,
1ec346 ··············int (*predicate)(void *arg, RingIterator *iter,
ef5950 ·······························union RingObject *object, unsigned level),
39eeaa ··············void *arg);
4fa4ea int ·ringSetFilterSpec(RingSet const *src,
b1d452 ¤   RingSet *dest, char const *string, int use);
ceaf5a
ab5174 union RingObject ·*
bbec96 ringLatestSecret(RingSet const *set, char const *string, PGPUInt32 tstamp,
a56f56 ¤   int use);
0caf5a
14af5a
778d79 /* Object access functions */
b8af5a
21dbf1 PgpTrustModel ·pgpTrustModel(RingPool const *pool);
cdec92 int ·ringKeyError(RingSet const *set, union RingObject *key);
2e78f2 unsigned ·ringKeyBits(RingSet const *set,
f7168e ¤   union RingObject *key);
170f3a PGPUInt32 ·ringKeyCreation(RingSet const *set,
3d168e ¤   union RingObject *key);
001a27 PGPUInt32 ·ringKeyExpiration(RingSet const *set,
d1168e ¤   union RingObject *key);
6efdc4 void ·ringKeyID4(RingSet const *set,
9e45c1 ¤   union RingObject const *key, PGPByte *pkalg, PGPKeyID *keyID);
242a2f void ·ringKeyID8(RingSet const *set,
b145c1 ¤   union RingObject const *key, PGPByte *pkalg, PGPKeyID *keyID);
673546 PGPBoolean ringKeyV3(RingSet const *set, union RingObject const *key);
fd33b0 int ·ringKeyUseInternal(RingSet const *set, union RingObject *key,
05b052 ¤   PGPBoolean unExpired);
e898be #define ringKeyUse(s,k)¤¤   ¤   ¤   ¤   ringKeyUseInternal(s,k,FALSE)
b30675 #define ringKeyUnexpiredUse(s,k)¤   ¤   ringKeyUseInternal(s,k,TRUE)
18cddc PGPByte ·ringKeyTrust(RingSet const *set, union RingObject *key);
a671ce void ·ringKeySetTrust(RingSet const *set,
2a0b7e ¤   union RingObject *key, PGPByte trust);
ffb9dd int ·ringKeyDisabled(RingSet const *set,
1b168e ¤   union RingObject *key);
53d191 void ·ringKeyDisable(RingSet const *set,
5a168e ¤   union RingObject *key);
39e45f void ·ringKeyEnable(RingSet const *set,
32168e ¤   union RingObject *key);
4b39f7 int ·ringKeyRevoked(RingSet const *set,
29168e ¤   union RingObject *key);
db9280 void ·ringKeySetAxiomatic(RingSet const *set,
5e168e ¤   union RingObject *key);
fc1e55 void ·ringKeyResetAxiomatic(RingSet const *set,
dc168e ¤   union RingObject *key);
3bbf7e int ·ringKeyAxiomatic(RingSet const *set,
ce168e ¤   union RingObject *key);
24aa67 int ·ringKeyIsSubkey(RingSet const *set,
63e9d6 ¤   union RingObject const *key);
0daf5a
479bde int ·ringKeyFingerprint16(RingSet const *set,
cdc7ae ¤   union RingObject *key, PGPByte *buf);
3fe669 int ·ringKeyFingerprint20(RingSet const *set,
26c7ae ¤   union RingObject *key, PGPByte *buf);
b39cf8 int ·ringKeyAddSigsby(RingSet const *set,
08d7a0 ¤   union RingObject *key, RingSet *dest);
49af5a
5565f7 /* Given a Ring Object, obtain a PGPPubKey or a PGPSecKey */
f65833 int ·ringKeyIsSec(RingSet const *set, union RingObject *key);
--f01c 000f36298d040100200 Page 5 of pgpRngPub.h
30c8dc int ·ringKeyIsSecOnly(RingSet const *set,
a7f579 ¤   ¤   ¤   ¤   union RingObject *key);
f5f9d2 union RingObject ·*ringKeySubkey(RingSet const *set,
3b038e ¤   ¤   ¤   ¤   union RingObject const *key);
d1048a union RingObject ·*ringKeyMasterkey(RingSet const *set,
e52d52 ¤   ¤   ¤   ¤   union RingObject const *subkey);
782268 PGPPubKey ·*ringKeyPubKey(RingSet const *set,
8c490f ¤   ¤   ¤   ¤   union RingObject *key, int use);
7374fa PGPSecKey ·*ringSecSecKey(RingSet const *set,
66c67b ¤   ¤   ¤   ¤   union RingObject *sec, int use);
3d3eb0 union RingObject *ringBestSec(RingSet const *set,
e5e9d6 ¤   union RingObject const *key);
519dc4 PgpVersion ·ringSecVersion (RingSet const *set,
a1899e ¤   ¤   ¤   ¤   union RingObject *sec);
a5af5a
34a004 char const ·*ringNameName(RingSet const *set,
75f502 ¤   union RingObject *name, PGPSize *lenp);
9ec9af PGPBoolean ringNameIsAttribute(RingSet const *set, union RingObject *name);
c71efb PGPUInt32 ringNameCountAttributes(RingSet const *set, union RingObject *name);
fe42a7 PGPByte const *ringNameAttributeSubpacket(RingObject *name, RingSet const *set,
e2da8e ¤   PGPUInt32 nth, PGPUInt32 *subpacktype, PGPSize *plen, PGPError *error);
f66e9c PGPByte ·ringNameTrust(RingSet const *set,
40a5b1 ¤   union RingObject *name);
d46b5c int ·ringNameWarnonly(RingSet const *set,
a7a5b1 ¤   union RingObject *name);
d665c5 void ·ringNameSetWarnonly(RingSet const *set,
03a5b1 ¤   union RingObject *name);
b5af5a
33db39 int ·ringSigError(RingSet const *set, union RingObject *sig);
e42dcd union RingObject ·*ringSigMaker(RingSet const *sset,
e360e5 ¤   union RingObject *sig, RingSet const *kset);
c4ae7f void ·ringSigID8(RingSet const *set,
ee1fc9 ¤   union RingObject const *sig, PGPByte *pkalg, PGPKeyID *buf);
54fa77 PGPByte ·ringSigTrust(RingSet const *set, union RingObject *sig);
dbdf77 PGPByte ·ringSigTrustLevel(RingSet const *set, union RingObject const *sig);
2fbe38 PGPByte ·ringSigTrustValue(RingSet const *set, union RingObject const *sig);
bdd694 int ·ringSigChecked(RingSet const *set, union RingObject const *sig);
edc7df int ·ringSigTried(RingSet const *set, union RingObject const *sig);
4bbb21 int ·ringSigType(RingSet const *Set, union RingObject const *sig);
089a1a PGPUInt32 ·ringSigTimestamp(RingSet const *Set, union RingObject const *sig);
eb5402 PGPUInt32 ·ringSigExpiration(RingSet const *set, union RingObject const *sig);
c16a39 int ·ringSigRevoked (RingSet const *set, union RingObject *sig);
de6685 int¤ringSigExportable (RingSet const *set, union RingObject const *sig);
9e631e PGPBoolean ringSigIsSelfSig(RingSet const *set, RingObject const *sig);
4343f8 PGPBoolean ringSigIsX509(RingSet const *set, RingObject const *sig);
50418d PGPByte *ringSigX509Certificate(RingSet const *set, RingObject *sig,
6922f0 ···PGPSize *len);
89af5a
eea0d3 /* Only valid if PgpTrustModel > PGPTRUST0 */
b6f230 PGPUInt16 ·ringKeyConfidence(RingSet const *set,
17168e ¤   union RingObject *key);
bad868 PGPUInt16 ·ringNameValidity(RingSet const *set,
2da5b1 ¤   union RingObject *name);
e62a9e PGPUInt16 ·ringNameConfidence(RingSet const *set,
10a5b1 ¤   union RingObject *name);
0a2a8c int ·ringNameConfidenceUndefined(RingSet const *set,·
3d2662 ¤   ¤   ¤   ¤   union RingObject *name);
3e3a2f void ·ringNameSetConfidence(RingSet const *set,·
02789b ¤   ¤   ¤   ·····union RingObject *name, PGPUInt16 confidence);
8695f1 PGPUInt16 ·ringSigConfidence(RingSet const *set,
e56fb5 ¤   union RingObject *sig);
47af5a
774675 PGPByte const ·*
3280e5 ringKeyFindSubpacket (RingObject *obj, RingSet const *set,
c96738 ¤   int subpacktype, unsigned nth,
28826f ¤   PGPSize *plen, int *pcritical, int *phashed, PGPUInt32 *pcreation,
c62f76 ¤   unsigned *pmatches, PGPError *error);
155174 union RingObject ·*
398f9c ringKeyAdditionalRecipientRequestKey (RingObject *obj, RingSet const *set,
51bd82 ¤   ¤   ¤   ¤   ¤   unsigned nth, PGPByte *pkalg, PGPKeyID *keyid,
222eca ¤   ¤   ¤   ¤   ¤   PGPByte *pclass, unsigned *pkeys, PGPError *error);
f35174 union RingObject ·*
--61bd 00146082eaf40100200 Page 6 of pgpRngPub.h
77b0f7 ringKeyRevocationKey (union RingObject *obj, RingSet const *set, unsigned nth,
a62423 ¤   ¤   ¤   ¤   ¤   PGPByte *pkalg, PGPKeyID *keyid,
c82eca ¤   ¤   ¤   ¤   ¤   PGPByte *pclass, unsigned *pkeys, PGPError *error);
497750 PGPBoolean
6ea8e5 ringKeyIsRevocationKey (RingObject *key, RingSet const *set,
4cf925 ¤   ¤   ¤   ¤   ¤   RingObject *rkey);
1a7750 PGPBoolean
c5e036 ringKeyHasThirdPartyRevocation (RingObject *obj, RingSet const *set,
64d45c ¤   ¤   ¤   ¤   ¤   RingObject **revkey, PGPByte *pkalg, PGPKeyID *keyid,
a69613 ¤   ¤   ¤   ¤   ¤   PGPError *error);
cb9d57 PGPSigSpec *
49a0a7 ringSigSigSpec (RingObject *sig, RingSet const *set,
de9613 ¤   ¤   ¤   ¤   ¤   PGPError *error);
60af5a
e445cc void ringPoolConsistent (RingPool *pool, int *pnsets,
d78c29 ¤   int *pnfiles);
94af5a
2baf5a
0f1254 PGP_END_C_DECLARATIONS
5faf5a
46bda9 #endif /* Included_pgpRngPub_h */
--b696 000514781e640100201 Page 1 of pgpRngRead.c
bc38e5 /*
f76169 ·* pgpRngRead.c - Read in various parts of a keyring.
81775e ·*
25d432 ·* The big function (>500 lines, yeep!) is ringFileOpen(); it opens another
18f62d ·* keyring and merges it with the collection in memory.¤ Most of the others
3dc42b ·* are its helpers. ·This is where PGPlib's great robustness in the face of
ffd698 ·* badly mangled keyrings is achieved.¤ *Every* keyring comes through here,
98f514 ·* and it validates its inputs to the point of paranoia.
b1775e ·*
50a57e ·* This file is too big - what should be split out?
98c0af ·* There are a lot of similar-but-not-quite functions.¤ Perhaps some
5407f0 ·* rethinking will allow parts of them to be merged?
4f775e ·*
8068c2 ·* Written by Colin Plumb.
3d775e ·*
33236f ·* $Id: pgpRngRead.c,v 1.84 1998/08/04 23:49:18 hal Exp $
c8495d ·*/
bde2ff #include "pgpConfig.h"
8baf5a
2a495d #include <errno.h>
91feb2 #include <stdio.h>
fb324c #include <string.h>
8daf5a
fea146 #include "pgpDebug.h"
fac305 #include "pgpMakeSig.h"
2e95a9 #include "pgpMemPool.h"
c29c38 #include "pgpPktByte.h"
4b5d28 #include "pgpRngMnt.h"
3f2e22 #include "pgpRngPars.h"
cfd229 #include "pgpRngPkt.h"
957a44 #include "pgpRngPriv.h"
c25a03 #include "pgpTrust.h"
1004d2 #include "pgpTrstPkt.h"¤¤   /* for PGP_SIGTRUSTF_CHECKED_TRIED */
459f72 #include "pgpHash.h"
e3c5b0 #include "pgpKeySpec.h"
dc0d08 #include "pgpMem.h"
5d0e2f #include "pgpSymmetricCipherPriv.h"
280d6d #include "pgpEnv.h"
402f8d #include "pgpErrors.h"
dfcdc2 #include "pgpPubKey.h"
8c72de #include "pgpFile.h"
5c806a #include "pgpRngRead.h"
8ff5ab #include "pgpSigSpec.h"
8ac26c #include "pgpContext.h"
6fd2c2 #include "pgpX509Priv.h"
4baf5a
830596 #ifndef NULL
4f699b #define NULL 0
d17454 #endif
a5af5a
63b8de static PGPContextRef
5f1cac RingSetGetContext( const RingSet *set )
e3bb36 {
dadee4 ¤   pgpAssert( pgpContextIsValid( set->pool->context ) );
dcd476 ¤   return( set->pool->context );
aaefe6 }
53af5a
9baf5a
0e38e5 /*
470e34 ·* The largest legal PGP key uses a 64Kbit key, which is 8Kbytes.
d50ebe ·* As a public key, there's also 12 bytes of overhead, plus a
92ef13 ·* public exponent (usually 1 byte, sometimes 3, it's just stupid
0c0ea2 ·* to make it any larger). ·
117d1f ·* Stored in a secret key an extra 11+IV bytes of overhead and
ba088c ·* the secret exponent (8K), factors p and q (4+4=8K), and multiplicative
fe068d ·* inverse u (4K). ·A total of 28K of data, plus 23+IV+e extra bytes.
83a4e9 ·* With an 8-byte IV, that's 31+e bytes. ·Add an extra byte to allow
65b04b ·* for p and q of differing lengths.
590580 ·* But for now, reduce this by a factor of 8, to 8Kbits, which changes
f96856 ·* the maximum sizes to 1K+overhead and 3.5K + overhead.
d9775e ·*
515236 ·* Without these limits, a non-fatal error (object too big) becomes
--b5e8 0003add1dcc40100201 Page 2 of pgpRngRead.c
1520b6 ·* a fatal error (out of memory) and the implementation becomes
8f3152 ·* less robust. ·However, the limits can be set quite high without
a46fea ·* harm. ·(Keep the maximum key size to 64K, though.)
4f775e ·*
9cd972 ·* The limits above were derived for RSA keys. ·DSA/ElG keys have a prime
7713ee ·* p, a small (~160 bit) prime q, a generator g, and a public exponent y.
d5f2e9 ·* That's four numbers, one of them small. ·If we allow enough space for four
7e3720 ·* full-sized numbers that should be safe. ·Secrets have in addition a
9486b1 ·* secret exponent x, generally small, so allow an additional number.
857b0f ·* Signatures are small with DSA, two 160 bit numbers. ·However the new
c5b599 ·* signature packets can in principle have a lot of data. ·Allow two full
27c0b1 ·* sized numbers to give us plenty of room; we may have to increase the value
7a0b08 ·* in the future.
d4495d ·*/
410462 #define RINGMPI_MAX¤1024¤   ¤   ¤   ¤   /* Maximum 8Kbits */
8dbf5e #define RINGKEY_MAXLEN¤ (4*RINGMPI_MAX)¤/* Public key maximum size */
62d1b4 #define RINGSEC_MAXLEN¤ (5*RINGMPI_MAX)¤/* Secret key maximum size */
1e8425 #define RINGNAME_MAXLEN¤128000¤ ¤   ¤   /* Name/attribute maximum size */
03aec6 #define RINGSIG_MAXLEN¤ (2*RINGMPI_MAX)¤/* Signature maximum size */
815322 #define RINGUNK_MAXLEN¤ RINGSEC_MAXLEN
26d7e3 /* RINGTRUST_MAXLEN is implicit */
a9af5a
0fc927 /* Threshold for caching name/attribute objects in memory */
7ea3f5 #define NAMECACHETHRESHOLD¤ 1024
3caf5a
f5f523 /*** Working with the FilePos chain ***/
0baf5a
ea38e5 /*
8a2dd0 ·* A note about the FilePos chain. ·Each object has one FilePos right
4e6d9c ·* inside itself, which is the head of a list of external (allocated)
15c203 ·* ones. ·There is one FilePos for each key file an object exists in,
401939 ·* and they are kept in increasing order by bit number.
020213 ·* Every object (except dummy keys, which aren't excessively numerous,
fad32b ·* especially in large keyrings) is present in at least one physical
dc1953 ·* keyring, so this saves one next pointer when we're trying to conserve
ee4f06 ·* memory for MS-DOS, at the expense of complicating the task of
6eb687 ·* adding to and removing from the list.
1d775e ·*
6c6298 ·* This is because the first entry in the chain is statically allocated.
84bb5a ·* An actual allocation is performed when an entry is added to the
c182dd ·* chain in a location other than the first, or is bumped from first
dcfc54 ·* place by something else. ·A FilePos is freed when an entry is deleted
dc830b ·* from the chain, or the first one is deleted and the second moves into
c771c0 ·* its place.
92775e ·*
a126c4 ·* One more special feature: the MEMRING filepos is put as the last entry
76de5b ·* in the chain. ·In that filepos, the "next" pointer actually points at
cc903f ·* the memory data, and the fpos field holds the size of the memory block.
3c495d ·*/
eaaf5a
b75edf /* Find the position of an object in the given file */
5b4425 static FilePos *
3cde49 ringFilePos(union RingObject const *obj, RingFile const *file)
efbb36 {
60fbde ¤   FilePos const *pos = &obj->g.pos;
e445d1 ¤   PGPVirtMask mask;
0fc975 ¤   RingPool *pool = file->set.pool;
f4af5a
4014fb ¤   pgpVirtMaskInit (pool, &mask);
e4a62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
23c530 ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
da98ba ¤   /* Keep only bits before the one we are interested in */
aabdca ¤   /* But for MEMRING go to the last in the chain */
b93a4a ¤   pgpVirtMaskANDNOT(pool, &pool->memringmask, &mask);
191d78 ¤   if (!pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
faebe0 ¤   ¤   PGPInt32 filebit = pgpVirtMaskLSBit (&file->set.mask);
0b9257 ¤   ¤   pgpVirtMaskClearGreaterBits (pool, &mask, filebit);
c29371 ¤   }
d4f953 ¤   while (!pgpVirtMaskIsEmpty(&mask)) {
846540 ¤   ¤   PGPInt32 bit = pgpVirtMaskLSBit (&mask);
15e8cb ¤   ¤   pgpAssert (bit >= 0);
3aca47 ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
--cd34 0002cd7b51940100201 Page 3 of pgpRngRead.c
7544ae ¤   ¤   pos = pos->ptr.next;
239371 ¤   }
4b0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
70e29b ¤   return (FilePos *)pos;
93efe6 }
05af5a
ae1719 /* Allocate a FilePos from a RingFile. */
ef4425 static FilePos *
caf9cf ringFileNewFilePos(RingFile *file)
73bb36 {
8d9aec ¤   FilePos *pos = file->freepos;
9daf5a
aab311 ¤   if (pos) {
d467ef ¤   ¤   file->freepos = pos->ptr.next;
71f037 ¤   } else {
c79e3f ¤   ¤   pos = (FilePos *)memPoolNew(&file->fpos,FilePos);
d2a485 ¤   ¤   if (!pos)
7806d1 ¤   ¤   ¤   ringAllocErr(file->set.pool);
659371 ¤   }
82af5a
42de4e ¤   return pos;
c9efe6 }
e4af5a
422978 static void
41107d ringFileFreeFilePos(RingFile *file, FilePos *pos)
9fbb36 {
6e8447 ¤   pos->ptr.next = file->freepos;
a96385 ¤   file->freepos = pos;
dbefe6 }
2faf5a
3638e5 /*
494398 ·* Allocate and add a FilePos to the object's chain in the right place.
2354fa ·* This function makes no attempt to initialize the resultant FilePos.
05775e ·*
acb6d6 ·* NOTE that the bit specified to add may or may not be present in
6523ad ·* the ring's filemask. ·This function must not care.
75495d ·*/
594425 static FilePos *
a2eddf ringAddFilePos(union RingObject *obj, RingFile *file)
31bb36 {
ebc975 ¤   RingPool *pool = file->set.pool;
39312d ¤   PGPVirtMask mask, tmpmask;
c9898d ¤   FilePos *pos, *pos2;
fa6a1b ¤   PGPInt32 bit;
a717b1 ¤   RingFile *file2;
48af5a
9e14fb ¤   pgpVirtMaskInit (pool, &mask);
0e0dac ¤   pgpVirtMaskInit (pool, &tmpmask);
14af5a
1fa62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
b6c530 ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
ecaf5a
8ca741 ¤   pgpAssert (!pgpVirtMaskIsOverlapping (&mask, &file->set.mask));
80af5a
1fc316 ¤   pgpVirtMaskCopy (pool, &mask, &tmpmask);
130b68 ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &tmpmask);
2484ea ¤   if (!pgpVirtMaskIsEqual(&pool->memringmask, &file->set.mask)) {
15ebe0 ¤   ¤   PGPInt32 filebit = pgpVirtMaskLSBit (&file->set.mask);
0cb84d ¤   ¤   pgpVirtMaskClearGreaterBits (pool, &tmpmask, filebit);
da9371 ¤   }
a49e3b ¤   if (!pgpVirtMaskIsEmpty (&tmpmask)) {
23fdeb ¤   ¤   /* FilePos to add is not the first in the chain */
4b673c ¤   ¤   pgpVirtMaskCopy (pool, &tmpmask, &mask);
8d66e5 ¤   ¤   pos2 = ringFileNewFilePos(file);
afd933 ¤   ¤   if (!pos2)
7ccf03 ¤   ¤   ¤   return NULL;
8a8039 ¤   ¤   /* Find the predecessor of the one to be added */
cffdf7 ¤   ¤   pos = &obj->g.pos;
0897be ¤   ¤   bit = pgpVirtMaskLSBit (&mask);
22e8cb ¤   ¤   pgpAssert (bit >= 0);
86ca47 ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
2c2fdd ¤   ¤   while ((bit = pgpVirtMaskLSBit (&mask)) >= 0) {
--de13 00005a8e48a40100201 Page 4 of pgpRngRead.c
62fff8 ¤   ¤   ¤   pos = pos->ptr.next;
10207c ¤   ¤   ¤   pgpAssert(IsntNull(pos));
be5c06 ¤   ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
4a0fe4 ¤   ¤   }
1b8c4a ¤   ¤   /* Insert pos2 into the chain after pos */
5c1213 ¤   ¤   pos2->ptr.next = pos->ptr.next;
204b41 ¤   ¤   pos->ptr.next = pos2;
2ef037 ¤   } else {
faf33d ¤   ¤   /* First FilePos in the chain */
4f8743 ¤   ¤   pos2 = &obj->g.pos;
55e58d ¤   ¤   if (pgpVirtMaskIsEmpty(&mask)) {
450262 ¤   ¤   ¤   /* First and only FilePos on chain */
9c82a5 ¤   ¤   ¤   pos = NULL;
6a45a6 ¤   ¤   } else {
d884bb ¤   ¤   ¤   /* First FilePos; bump down the old first */
045f06 ¤   ¤   ¤   bit = pgpVirtMaskLSBit(&mask);
d8bad3 ¤   ¤   ¤   pgpAssert(bit >= 0);
a02d62 ¤   ¤   ¤   /* Allocate pos from pool for existing bit */
e0547b ¤   ¤   ¤   file2 = file->set.pool->files[bit];
7029d8 ¤   ¤   ¤   pos = ringFileNewFilePos(file2);
ca9e1f ¤   ¤   ¤   if (!pos)
c6fb5e ¤   ¤   ¤   ¤   return NULL;
753d00 ¤   ¤   ¤   *pos = *pos2;
720fe4 ¤   ¤   }
237b12 ¤   ¤   pos2->ptr.next = pos;
3d9371 ¤   }
728eb9 ¤   pgpVirtMaskOR (pool, &file->set.mask, &obj->g.mask);
460db9 ¤   pgpVirtMaskCleanup (pool, &mask);
93fceb ¤   pgpVirtMaskCleanup (pool, &tmpmask);
c2379a ¤   return pos2;
7defe6 }
bdaf5a
23beb7 static int
1511ff ringAddPos(union RingObject *obj, RingFile *file, PGPUInt32 fpos)
82bb36 {
01049f ¤   FilePos *pos;
daaf5a
5b1181 ¤   pos = ringAddFilePos(obj, file);
832130 ¤   if (!pos)
984030 ¤   ¤   return kPGPError_OutOfMemory;
9d1b75 ¤   pos->fpos = fpos;
193e6b ¤   return 0;
bbefe6 }
e4af5a
fd38e5 /*
547c38 ·* This is needed in one obscure error case to keep things
2273ae ·* consistent. ·The case is when a secret key appears in the same
f38216 ·* file as the corresponding public key, only later.
1c495d ·*/
0f2978 static void
fcba75 ringAlterFilePos(union RingObject *obj, RingFile const *file,
d39b81 ¤   PGPUInt32 fpos)
c6bb36 {
2945d1 ¤   PGPVirtMask mask;
7ac975 ¤   RingPool *pool = file->set.pool;
97049f ¤   FilePos *pos;
35af5a
0614fb ¤   pgpVirtMaskInit (pool, &mask);
05a62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
6fc530 ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
ddaf5a
5fdc83 ¤   pgpAssert (pgpVirtMaskIsOverlapping(&mask, &file->set.mask));
6b67c5 ¤
1f686d ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
24af5a
b11d78 ¤   if (!pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
a5ebe0 ¤   ¤   PGPInt32 filebit = pgpVirtMaskLSBit (&file->set.mask);
899257 ¤   ¤   pgpVirtMaskClearGreaterBits (pool, &mask, filebit);
c99371 ¤   }
bc1f16 ¤   pos = &obj->g.pos;
b40b17 ¤   while (!pgpVirtMaskIsEmpty (&mask)) {
056540 ¤   ¤   PGPInt32 bit = pgpVirtMaskLSBit (&mask);
--84be 000d052b27040100201 Page 5 of pgpRngRead.c
78ca47 ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
c444ae ¤   ¤   pos = pos->ptr.next;
449371 ¤   }
8c1b75 ¤   pos->fpos = fpos;
cf0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
13efe6 }
60af5a
9c38e5 /*
ebaba8 ·* Remove a FilePos from an object's list.
53775e ·*
de32d9 ·* file is the filepos corresponding to "bit", pos is the head of a
332183 ·* FilePos chain, mask is the bitmask of physical key rings, and
796092 ·* bit is the number of the ring to have its position removed.
e4775e ·*
983ac1 ·* NOTE that the bit specified to remove may or may not be present in
de32fa ·* the ring->filemask. ·This function must not care.
ed495d ·*/
582978 static void
03bee0 ringRemFilePos(union RingObject *obj, RingFile *file)
9fbb36 {
38312d ¤   PGPVirtMask mask, tmpmask;
42c975 ¤   RingPool *pool = file->set.pool;
9b898d ¤   FilePos *pos, *pos2;
bf6a1b ¤   PGPInt32 bit;
5217b1 ¤   RingFile *file2;
aeaf5a
3d14fb ¤   pgpVirtMaskInit (pool, &mask);
110dac ¤   pgpVirtMaskInit (pool, &tmpmask);
06af5a
80a62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
f2c530 ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
a4af5a
042f2d ¤   /* Is the bit to remove *not* the least significant bit? */
87c316 ¤   pgpVirtMaskCopy (pool, &mask, &tmpmask);
600b68 ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &tmpmask);
681d78 ¤   if (!pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
41a097 ¤   ¤   bit = pgpVirtMaskLSBit (&file->set.mask);
2aadf1 ¤   ¤   pgpVirtMaskClearGreaterBits (pool, &tmpmask, bit);
859371 ¤   }
3b9e3b ¤   if (!pgpVirtMaskIsEmpty (&tmpmask)) {
75625d ¤   ¤   /* FilePos to remove is not the first in the chain */
a7d85a ¤   ¤   /* Find the predecessor of the one to be removed */
80673c ¤   ¤   pgpVirtMaskCopy (pool, &tmpmask, &mask);
1ffdf7 ¤   ¤   pos = &obj->g.pos;
2f97be ¤   ¤   bit = pgpVirtMaskLSBit (&mask);
12e8cb ¤   ¤   pgpAssert (bit >= 0);
12ca47 ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
732fdd ¤   ¤   while ((bit = pgpVirtMaskLSBit (&mask)) >= 0) {
f4fff8 ¤   ¤   ¤   pos = pos->ptr.next;
7d207c ¤   ¤   ¤   pgpAssert(IsntNull(pos));
9d5c06 ¤   ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
9f0fe4 ¤   ¤   }
c38d86 ¤   ¤   /* pos->next is the one to be removed */
f8c57d ¤   ¤   pos2 = pos->ptr.next;
353b99 ¤   ¤   pgpAssert(IsntNull(pos2));
87dd57 ¤   ¤   pos->ptr = pos2->ptr;
040316 ¤   ¤   if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask))
c12cab ¤   ¤   ¤   pos->ptr.next = NULL;¤  /* debugging aid */
bfbb0d ¤   ¤   file2 = file;
9cf037 ¤   } else {
2f14ee ¤   ¤   /* First FilePos - copy second to first, remove second */
0daf5a
fb07d2 ¤   ¤   /* Clear this bit from the mask (in case we need to) */
8ae5fb ¤   ¤   pgpVirtMaskANDNOT (pool, &file->set.mask, &mask);
c4af5a
d01b17 ¤   ¤   /*
096b3c ¤   ¤   ·* That's it? ·Well, return then. ·The caller better
570289 ¤   ¤   ·* deallocate this object, 'cause it no longer exists
1c51d8 ·¤  ¤   ·* anywhere. ·Use position -1 to mark an unused slot.
fe9de3 ¤   ¤   ·*/
3ee58d ¤   ¤   if (pgpVirtMaskIsEmpty(&mask)) {
d07988 ¤   ¤   ¤   pgpVirtMaskANDNOT (pool, &file->set.mask, &obj->g.mask);
--a975 000c698a3d840100201 Page 6 of pgpRngRead.c
fe15a0 ¤   ¤   ¤   if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask))
276cf2 ¤   ¤   ¤   ¤   obj->g.pos.ptr.next = NULL;¤¤   /* Debugging aid */
c3fd55 ¤   ¤   ¤   obj->g.pos.fpos = (PGPUInt32)-1;¤   /* Debugging aid */
d10892 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
49a8ce ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &tmpmask);
1f0ecc ¤   ¤   ¤   return;
120fe4 ¤   ¤   }
26af5a
5b364f ¤   ¤   /* Find the bit of the fpos we are removing, the 2nd fpos in list */
9ad263 ¤   ¤   /* Note we have already cleared the bit for the 1st fpos */
c74ed8 ¤   ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
97f7c4 ¤   ¤   if (pgpVirtMaskIsEmpty(&mask))
f4a6d3 ¤   ¤   ¤   bit = 0;
fb0e1d ¤   ¤   else
271fd8 ¤   ¤   ¤   bit = pgpVirtMaskLSBit (&mask);
520185 ¤   ¤   pgpAssert(bit >= 0);
99bcf2 ¤   ¤   file2 = file->set.pool->files[bit];¤/* where to stash reclaimed pos */
4aaf5a
0959d2 ¤   ¤   /* Copy the next pos to the current one */
50b5ea ¤   ¤   pos2 = obj->g.pos.ptr.next;
9f3b99 ¤   ¤   pgpAssert(IsntNull(pos2));
3bc756 ¤   ¤   obj->g.pos = *pos2;
b39371 ¤   }
c10a05 ¤   /* Free the FilePos */
514850 ¤   ringFileFreeFilePos(file2, pos2);
c629e4 ¤   pgpVirtMaskANDNOT (pool, &file->set.mask, &obj->g.mask);
ba0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
85fceb ¤   pgpVirtMaskCleanup (pool, &tmpmask);
08efe6 }
76af5a
4caf5a
e37727 /* Remove an object and its children from a specific file */
65916a /* If an object is left unhomed, delete it */
7e2978 static void
da68bc ringRemFileObjChildren(union RingObject *obj, RingFile *file)
f6bb36 {
81c975 ¤   RingPool *pool = file->set.pool;
9b8bed ¤   RingObject *obj1, *nextobj1;
33e7b7 ¤   RingObject *obj2, *nextobj2;
97af5a
f27c3b ¤   if (pgpIsRingSetMember(&file->set, obj)) {
874f82 ¤   ¤   ringRemFilePos(obj, file);
60ca39 ¤   ¤   if (!OBJISBOT(obj)) {
c971c1 ¤   ¤   ¤   for (obj1=obj->g.down; obj1; obj1=nextobj1) {
b8c410 ¤   ¤   ¤   ¤   nextobj1 = obj1->g.next;
51b51e ¤   ¤   ¤   ¤   if (pgpIsRingSetMember(&file->set, obj1)) {
ea0000 ¤   ¤   ¤   ¤   ¤   ringRemFilePos(obj1, file);
0719c0 ¤   ¤   ¤   ¤   ¤   if (!OBJISBOT(obj1)) {
54b77e ¤   ¤   ¤   ¤   ¤   ¤   for (obj2=obj1->g.down; obj2; obj2=nextobj2) {
ee3ca5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextobj2 = obj2->g.next;
8e0e66 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (pgpIsRingSetMember(&file->set, obj2)) {
ee38d3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringRemFilePos(obj2, file);
978efb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (!pgpVirtMaskIsOverlapping (&obj2->g.mask,
b32a18 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &pool->filemask))
6f328c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringRemObject (pool, obj2);
b05268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
45db3c ¤   ¤   ¤   ¤   ¤   ¤   }
cd1c89 ¤   ¤   ¤   ¤   ¤   }
900a97 ¤   ¤   ¤   ¤   ¤   if (!pgpVirtMaskIsOverlapping (&obj1->g.mask,
e0aed5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&pool->filemask)) {
65e1f5 ¤   ¤   ¤   ¤   ¤   ¤   /* Parents share all homes of children */
7db5ce ¤   ¤   ¤   ¤   ¤   ¤   pgpAssert (OBJISBOT(obj1) || IsNull(obj1->g.down));
ca09a6 ¤   ¤   ¤   ¤   ¤   ¤   ringRemObject (pool, obj1);
211c89 ¤   ¤   ¤   ¤   ¤   }
eb2613 ¤   ¤   ¤   ¤   }
9ca3a6 ¤   ¤   ¤   }
bd0fe4 ¤   ¤   }
258ab2 ¤   ¤   if (!pgpVirtMaskIsOverlapping (&obj->g.mask, &pool->filemask)) {
c33754 ¤   ¤   ¤   pgpAssert (OBJISBOT(obj) || IsNull(obj->g.down));
f36c89 ¤   ¤   ¤   ringRemObject (pool, obj);
d90fe4 ¤   ¤   }
c69371 ¤   }
--c9d7 000b8cb394340100201 Page 7 of pgpRngRead.c
7aefe6 }
46af5a
8eaf5a
79af5a
85af5a
3bd6b0 /*** Closing a Ringfile ***/
79af5a
d238e5 /*
624309 ·* Set the destruction function for a RingFile.
21495d ·*/
54314a void
7cfc0a ringFileSetDestructor(RingFile *file,
d2be7c ¤   void (*destructor)(RingFile *, PGPFile *, void *),
c4a8b7 ¤   void *arg)
1cbb36 {
794a0a ¤   file->destructor = destructor;
75efbe ¤   file->arg = arg;
1defe6 }
1aaf5a
9f38e5 /*
bf993f ·* Helper function for ringFileDoClose.
37775e ·*
373c16 ·* Delete the given file's FilePos entries from the objects in
c94f80 ·* the given list, and delete the objects if they are no longer
427a33 ·* needed (mask has gone to 0). ·Recurse as necessary.
08775e ·*
3edf92 ·* Note that this is not used on the main keys list, because
1976ac ·* there we need to preserve dummy keys which this does not
5981d3 ·* understand.
84775e ·*
aacbfe ·* This also removes any cached names from objects.
62495d ·*/
792978 static void
2d9794 ringFileCloseList(union RingObject **objp, RingFile *file)
f9bb36 {
12a997 ¤   union RingObject *obj;
1d45d1 ¤   PGPVirtMask mask;
a9c975 ¤   RingPool *pool = file->set.pool;
71af5a
2914fb ¤   pgpVirtMaskInit (pool, &mask);
f2af5a
37534a ¤   while ((obj = *objp) != NULL) {
b51b17 ¤   ¤   /*
e2034e ¤   ¤   ·* Delete low-level objects with mask==0 as well as objects on
075a81 ¤   ¤   ·* the ringfile which is going away. ·We create those objects, e.g.
ed18c2 ¤   ¤   ·* when importing a non-exportable sig, and then they prevent the
4690ed ¤   ¤   ·* parent objects from being deleted properly, later leading to
85f483 ¤   ¤   ·* an assertion in keysdiffer.
5f9de3 ¤   ¤   ·*/
2936a2 ¤   ¤   if (pgpIsRingSetMember(&file->set, obj) ||
815560 ¤   ¤   ¤   pgpVirtMaskIsEmpty (&obj->g.mask)) {
ca985a ¤   ¤   ¤   if (!OBJISBOT(obj))
b6746d ¤   ¤   ¤   ¤   ringFileCloseList(&obj->g.down, file);
820e71 ¤   ¤   ¤   ringRemFilePos(obj, file);
2f7aad ¤   ¤   ¤   /*
d09d01 ¤   ¤   ¤   ·* Delete objects which have no homes other than MEMRING.
7616a9 ¤   ¤   ¤   ·* Except if they have children, because they may have a
d019f7 ¤   ¤   ¤   ·* child obj in the MEMRING which didn't get deleted
9c8ec0 ¤   ¤   ¤   ·* because it was not in this RingFile.
d68753 ¤   ¤   ¤   ·*/
6fc130 ¤   ¤   ¤   pgpVirtMaskCopy (pool, &pool->filemask, &mask);
0694f1 ¤   ¤   ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
5d7a92 ¤   ¤   ¤   if (!pgpVirtMaskIsOverlapping (&mask, &obj->g.mask) &&
32e6b4 ¤   ¤   ¤   ¤   ·(OBJISBOT(obj) || !obj->g.down)) {
b38823 ¤   ¤   ¤   ¤   *objp = obj->g.next;
73770d ¤   ¤   ¤   ¤   ringFreeObject(file->set.pool, obj);
f4042d ¤   ¤   ¤   } else {
76980e ¤   ¤   ¤   ¤   /*
2b71c9 ¤   ¤   ¤   ¤   ·* If a name is cached from the file which is closing,
0a1a59 ¤   ¤   ¤   ¤   ·* purge it since the file's strings table holds the cached
199366 ¤   ¤   ¤   ¤   ·* names and it's going away.
b81020 ¤   ¤   ¤   ¤   ·*/
--abd3 00044809ee840100201 Page 8 of pgpRngRead.c
cb9cb7 ¤   ¤   ¤   ¤   if (OBJISNAME(obj))
9e213c ¤   ¤   ¤   ¤   ¤   ringPurgeCachedName(file->set.pool, &obj->n,
df2d25 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &file->set.mask);
bf0ae9 ¤   ¤   ¤   ¤   objp = &obj->g.next;
c7a3a6 ¤   ¤   ¤   }
0c4a5d ¤   ¤   } else
473781 ¤   ¤   ¤   objp = &obj->g.next;
2b9371 ¤   }
4e0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
77efe6 }
d0af5a
7338e5 /*
b126bc ·* Close the given Ringfile. ·Returns an error if it can't due to
28afb1 ·* conflicts, in which case the file is NOT closed.
be775e ·*
d36482 ·* This performs four passes over the pool.
da8f4d ·* 1. The first does the bulk of the deletion, removing the
007efc ·* ···FilePos from the objects and deleting all things
5169f7 ·* ···at levels greater than 1.
d40d44 ·* 2. The second rebuilds the sigs-by lists which were broken by
250695 ·* ···deleting objects in the middle of them.
799341 ·* 3. The third finds all keys that are not referenced and do not
7b69b3 ·* ···make any signatures, and deletes those keys.
4532c6 ·* 4. The fourth rebuilds the hash index of the remaining keys.
cf775e ·*
d17990 ·* Note that the second and third passes delete any allocated-but-not
f4e095 ·* linked keys, which are left by ringFileOpen if it runs out of memory
0d6de7 ·* in mid-operation.
d9495d ·*/
712978 static void
0aa4da ringFileDoClose(RingFile *file)
2ebb36 {
5282ab ¤   union RingObject *obj, **objp;
a1c975 ¤   RingPool *pool = file->set.pool;
a34ba4 ¤   int i;
48d71b ¤   PGPVirtMask allocmask;
c345d1 ¤   PGPVirtMask mask;
008a94 ¤   PGPUInt32 filebit;
aeaf5a
df6197 ¤   pgpVirtMaskInit (pool, &allocmask);
1b14fb ¤   pgpVirtMaskInit (pool, &mask);
1eaf5a
e7c9e4 ¤   ringAllocMask (pool, &file->set, &allocmask);
a1af5a
a36b05 ¤   /* Free some memory right away */
1302df ¤   ringFilePurgeTrouble(file);
35af5a
423cd6 ¤   /* 1: Remove everything in the keyring, but don't delete the keys */
4c898e ¤   for (obj = pool->keys; obj; obj = obj->g.next) {
1248b9 ¤   ¤   if (pgpIsRingSetMember (&file->set, obj)) {
fa985a ¤   ¤   ¤   if (!OBJISBOT(obj))
5b746d ¤   ¤   ¤   ¤   ringFileCloseList(&obj->g.down, file);
640e71 ¤   ¤   ¤   ringRemFilePos(obj, file);
060fe4 ¤   ¤   }
979371 ¤   }
cdaf5a
9fb6ab ¤   /* 2: Recreate the shattered sigs-by lists */
a94fae ¤   ringPoolListSigsBy(pool);
46af5a
f22fd2 ¤   /* 3: Now purge the unneeded keys */
f95ff3 ¤   objp = &pool->keys;
b7534a ¤   while ((obj = *objp) != NULL) {
0114b6 ¤   ¤   pgpAssert(OBJISTOPKEY(obj));
3df530 ¤   ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
694ed8 ¤   ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
20dd9e ¤   ¤   if (pgpVirtMaskIsOverlapping (&mask, &pool->filemask) || obj->g.down) {
033781 ¤   ¤   ¤   objp = &obj->g.next;
517fba ¤   ¤   } else if (obj->k.sigsby) {
e85426 ¤   ¤   ¤   /* Retain key as a dummy key */
713f25 ¤   ¤   ¤   pgpAssert(!pgpVirtMaskIsOverlapping (&mask, &allocmask));
736b9e ¤   ¤   ¤   pgpAssert(!obj->g.down);
44a1bd ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &obj->g.mask);
--8aec 000cc8e8c5a40100201 Page 9 of pgpRngRead.c
963781 ¤   ¤   ¤   objp = &obj->g.next;
ee45a6 ¤   ¤   } else {
0cb2ea ¤   ¤   ¤   /* Delete the key */
de3f25 ¤   ¤   ¤   pgpAssert(!pgpVirtMaskIsOverlapping (&mask, &allocmask));
356b9e ¤   ¤   ¤   pgpAssert(!obj->g.down);
14b54b ¤   ¤   ¤   *objp = obj->g.next;
237306 ¤   ¤   ¤   ringFreeObject(pool, obj);
ea0fe4 ¤   ¤   }
3b9371 ¤   }
4faf5a
e81657 ¤   /* 4: Re-initialize the hash chains */
55e417 ¤   ringPoolHash(pool);
5eaf5a
19dd76 ¤   /* Clean up the file's memory pools */
5fef01 ¤   memPoolEmpty(&file->strings);
6c473b ¤   file->freepos = NULL;
d14a58 ¤   memPoolEmpty(&file->fpos);
a4af5a
561b00 ¤   pgpAssert(!file->set.next);
1faf5a
67d8af ¤   /*
b015cc ¤   ·* If there's nothing in the structs MemPool that's
4b87a6 ¤   ·* allocated, purge all the memory.
21a4e3 ¤   ·*/
1ccde3 ¤   if (!pool->keys && !pool->sets) {
436f84 ¤   ¤   for (i = 0; i < RINGTYPE_MAX; i++)
69ad3d ¤   ¤   ¤   pool->freeobjs[i] = NULL;
102e66 ¤   ¤   pool->freesets = NULL;
8bcafa ¤   ¤   pool->freeiter = NULL;
d516bf ¤   ¤   memPoolEmpty(&pool->structs);
b39371 ¤   }
71af5a
e41fd3 ¤   /* Cal the file's destructor function, if any */
acff0b ¤   if (file->destructor) {
2531fe ¤   ¤   file->destructor(file, file->f, file->arg);
3a1507 ¤   ¤   file->destructor = NULL;
979371 ¤   }
5caf5a
cbc92d ¤   /* Final deallocation of the file */
7be1e2 ¤   file->flags = 0;
a3d99d ¤   pgpVirtMaskANDNOT (pool, &file->set.mask, &pool->filemask);
cbaf5a
3853ef ¤   filebit = pgpVirtMaskLSBit (&file->set.mask);
11bb11 ¤   pgpVirtMaskCleanup (pool, &file->set.mask);
636029 ¤   pgpVirtMaskCleanup (pool, &file->higherpri);
d1ed55 ¤   pgpAssert (pool->files[filebit] == file);
4b01b2 ¤   pgpContextMemFree (pool->context, file);
e231a7 ¤   pool->files[filebit] = NULL;
01af5a
f70db9 ¤   pgpVirtMaskCleanup (pool, &mask);
188cff ¤   pgpVirtMaskCleanup (pool, &allocmask);
52efe6 }
78af5a
9838e5 /*
b301d3 ·* Check to see if an object anywhere on the list (including children,
3330c9 ·* recursively) is included in "allocmask" but not in "filemask."
71a891 ·* Such an object is orphaned, an undesirable state of affairs.
4ea234 ·* We have to check the entire keyring, recursively, because a
5097fb ·* given key or name might be duplicated in another keyring, but
ac9345 ·* a signature lower down might not be.
4f495d ·*/
74beb7 static int
8ff0dc ringFileCheckList(union RingObject const *obj, PGPVirtMask *filemask,
30386a ¤   PGPVirtMask *allocmask)
4dbb36 {
9f1c05 ¤   while (obj) {
f2804d ¤   ¤   if (pgpVirtMaskIsOverlapping (&obj->g.mask, allocmask)) {
df3620 ¤   ¤   ¤   /* Would closing orphan this object? */
fb7175 ¤   ¤   ¤   if (!pgpVirtMaskIsOverlapping (&obj->g.mask, filemask))
e31c2d ¤   ¤   ¤   ¤   return 1;
822013 ¤   ¤   ¤   /* Would closing orphan its children? */
cc5240 ¤   ¤   ¤   if (!OBJISBOT(obj) && ringFileCheckList(obj->g.down,
--56b5 00099e72b1b40100201 Page 10 of pgpRngRead.c
be6774 ¤   ¤   ¤   ········································filemask,
263ed8 ¤   ¤   ¤   ········································allocmask))
d11c2d ¤   ¤   ¤   ¤   return 1;
0c0fe4 ¤   ¤   }
cde2b6 ¤   ¤   obj = obj->g.next;
419371 ¤   }
3e3e6b ¤   return 0;
ffefe6 }
36af5a
988777 /* Is it safe to close the given file? */
904d2f int
7c3d7c ringFileCheckClose(RingFile const *file)
81bb36 {
afdc83 ¤   RingPool const *pool = file->set.pool;
ca5da8 ¤   int rtrn;
b6d71b ¤   PGPVirtMask allocmask;
eb45d1 ¤   PGPVirtMask mask;
83af5a
6324fc ¤   if (!file)
70bbde ¤   ¤   return 0;
006197 ¤   pgpVirtMaskInit (pool, &allocmask);
5214fb ¤   pgpVirtMaskInit (pool, &mask);
d5c9e4 ¤   ringAllocMask (pool, &file->set, &allocmask);
101bcb ¤   pgpVirtMaskCopy (pool, &pool->filemask, &mask);
cfe68c ¤   pgpVirtMaskANDNOT (pool, &file->set.mask, &mask);
34af5a
b504e5 ¤   rtrn = ringFileCheckList(pool->keys, &mask, &allocmask);
e4af5a
c98cff ¤   pgpVirtMaskCleanup (pool, &allocmask);
c10db9 ¤   pgpVirtMaskCleanup (pool, &mask);
0ef69b ¤   return rtrn;
dcefe6 }
b4af5a
9938e5 /*
e126bc ·* Close the given Ringfile. ·Returns an error if it can't due to
d3afb1 ·* conflicts, in which case the file is NOT closed.
95495d ·*/
41c744 ¤   PGPError
11831c ringFileClose(RingFile *file)
b2bb36 {
ca24fc ¤   if (!file)
e72849 ¤   ¤   return kPGPError_NoErr;¤/* close(NULL) is defines as harmless */
3baf5a
7b2be5 ¤   if (ringFileCheckClose(file))
7da39c ¤   ¤   return kPGPError_LazyProgrammer;
ccaf5a
93eebf ¤   /* Okay, nothing can fail now */
74f586 ¤   ringFileDoClose(file);
5eaf5a
91151e ¤   return kPGPError_NoErr;
1aefe6 }
c3af5a
452e1c /*** Routines for fetching things from the keyring ***/
62af5a
a0be61 /* Make sure the pool's packet buffer is large enough */
bc11e4 char *
2fa5be ringReserve(RingPool *pool, size_t len)
b5bb36 {
4a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
58af5a
e508b0 ¤   if (pool->pktbufalloc >= len)
0f536f ¤   ¤   return pool->pktbuf;
f867c5 ¤
c19aa5 ¤   if( IsNull( pool->pktbuf ) ) {
a23aca ¤   ¤   pool->pktbuf = (char *)
35eadf ¤   ¤   ¤   pgpContextMemAlloc( pool->context, len, 0 );
ad2b85 ¤   ¤   ¤   ¤
e032f5 ¤   ¤   if( IsNull( pool->pktbuf ) )
64b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
18f037 ¤   } else {
1eb395 ¤   ¤   void *vpktbuf = pool->pktbuf;
994090 ¤   ¤   err¤= pgpContextMemRealloc( pool->context, &vpktbuf, len,
--b063 000881f1fcf40100201 Page 11 of pgpRngRead.c
d39793 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0 );
dd3b02 ¤   ¤   pool->pktbuf = (char *)vpktbuf;
b19371 ¤   }
6c054e ¤   if ( IsPGPError( err ) )
44c7a1 ¤   {
3b45b3 ¤   ¤   ringAllocErr(pool);
337ed2 ¤   ¤   return NULL;
999371 ¤   }
d2927f ¤   pool->pktbufalloc = len;
806732 ¤   return pool->pktbuf;
b8efe6 }
1baf5a
12af5a
2438e5 /*
e16a9f ·* File priorities are handled by a "higherpri" mask with each file,
cf3659 ·* which is a mask of other files of higher priority than that file.
407d46 ·* If obj->g.mask & pool->filmask && file->higherpri is 0,
38d496 ·* this is the highest-priority file.
22495d ·*/
68701e /* Set file to the highest priority, except for the memory file */
3f314a void
303276 ringFileHighPri(RingFile *file)
2ebb36 {
17c975 ¤   RingPool *pool = file->set.pool;
eb743f ¤   unsigned i;
60af5a
442dd4 ¤   /* Add this file to everything else's higher priority mask */
77674d ¤   for (i = 0; i < pool->nfiles; i++)
612676 ¤   ¤   if (IsntNull(pool->files[i]))
b03837 ¤   ¤   ¤   pgpVirtMaskOR (pool, &file->set.mask, &pool->files[i]->higherpri);
6e8235 ¤   /* The only thing higher priority than this file is MEMRING */
5b9d01 ¤   pgpVirtMaskCopy (pool, &pool->memringmask, &file->higherpri);
11efe6 }
55af5a
c64f66 /* Set file to the lowest priority */
45314a void
ab6649 ringFileLowPri(RingFile *file)
d0bb36 {
03c975 ¤   RingPool *pool = file->set.pool;
ed743f ¤   unsigned i;
31af5a
2b82f0 ¤   /* Remove this file from everything else's higher priority mask */
822ad0 ¤   for (i = 0; i < pool->nfiles; i++) {
fb2b57 ¤   ¤   if (IsntNull(pool->files[i])) {
f9ae32 ¤   ¤   ¤   pgpVirtMaskANDNOT (pool, &file->set.mask,
6ded31 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&pool->files[i]->higherpri);
bfe87d ¤   ¤   ¤   if (pool->files[i] != file)
879f69 ¤   ¤   ¤   ¤   pgpVirtMaskSetBit (pool, &file->higherpri, i);
c70fe4 ¤   ¤   }
899371 ¤   }
c0efe6 }
deaf5a
c4af5a
4b0c05 /* The mask of sets that this key has *any* secret components in */
e1f1ae static PGPError
ab3a89 ringKeySecMask(RingPool *pool, RingObject const *obj, PGPVirtMask *omask)
84bb36 {
cc4e89 ¤   pgpAssert(OBJISKEY(obj));
87af5a
0dc44b ¤   pgpVirtMaskCleanup (pool, omask);
f69213 ¤   for (obj = obj->g.down; obj; obj = obj->g.next)
a6ebf9 ¤   ¤   if (OBJISSEC(obj)) {
6f3d08 ¤   ¤   ¤   pgpVirtMaskOR (pool, &obj->g.mask, omask);
5c0fe4 ¤   ¤   }
d0151e ¤   return kPGPError_NoErr;
f2efe6 }
5caf5a
0938e5 /*
f6dea0 ·* Given an object, find the best RingFile to fetch it from,
59db6c ·* for fetching purposes. ·Bits set in "avoidmask" are
9eabda ·* NOT valid for fetching, if avoidmask is nonnull.
88495d ·*/
--891f 0005008b84740100201 Page 12 of pgpRngRead.c
0a65df static RingFile *
b8db84 ringBestFile(RingPool *pool, union RingObject const *obj,
a1d7f1 ¤   PGPVirtMask *avoidmask)
3abb36 {
da312d ¤   PGPVirtMask mask, tmpmask;
04ff7f ¤   RingFile *file;
b6f257 ¤   int bit;
7eaf5a
0c14fb ¤   pgpVirtMaskInit (pool, &mask);
3b0dac ¤   pgpVirtMaskInit (pool, &tmpmask);
8caf5a
51a62b ¤   pgpVirtMaskCopy (pool, &obj->g.mask, &mask);
dfc530 ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
c6af5a
54c316 ¤   pgpVirtMaskCopy (pool, &mask, &tmpmask);
168040 ¤   if (IsntNull(avoidmask))
4fdff8 ¤   ¤   pgpVirtMaskANDNOT (pool, avoidmask, &tmpmask);
bdb83c ¤   if (pgpVirtMaskIsEmpty (&tmpmask)) {
db3157 ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
5ffa53 ¤   ¤   pgpVirtMaskCleanup (pool, &tmpmask);
d47ed2 ¤   ¤   return NULL;
889371 ¤   }
74af5a
737b2b ¤   /* find highest-priority fetchable file */
70220e ¤   for (;;) {
1e4f03 ¤   ¤   /* Is least-significant bit set in mask fetchable? */
8497be ¤   ¤   bit = pgpVirtMaskLSBit (&mask);
90fa53 ¤   ¤   pgpVirtMaskCleanup (pool, &tmpmask);
fdfae7 ¤   ¤   pgpVirtMaskSetBit (pool, &tmpmask, bit);
bc9a2c ¤   ¤   if (IsNull(avoidmask) ||
c4ae1e ¤   ¤   ¤   !pgpVirtMaskIsOverlapping (&tmpmask, avoidmask)) {
3baba7 ¤   ¤   ¤   file = pool->files[bit];
54c890 ¤   ¤   ¤   /* Is it highest priority? */
91c290 ¤   ¤   ¤   pgpVirtMaskCopy (pool, &mask, &tmpmask);
cc067e ¤   ¤   ¤   if (IsntNull(avoidmask))
89d821 ¤   ¤   ¤   ¤   pgpVirtMaskANDNOT (pool, avoidmask, &tmpmask);
e3f35a ¤   ¤   ¤   if (!pgpVirtMaskIsOverlapping (&tmpmask, &file->higherpri))
76f622 ¤   ¤   ¤   ¤   break;
6a4034 ¤   ¤   ¤   pgpAssert(file->f);
de0fe4 ¤   ¤   }
08ca47 ¤   ¤   pgpVirtMaskClearBit (pool, &mask, bit);
91a24d ¤   ¤   pgpAssert(!pgpVirtMaskIsEmpty(&mask));
d89371 ¤   }
350db9 ¤   pgpVirtMaskCleanup (pool, &mask);
bffceb ¤   pgpVirtMaskCleanup (pool, &tmpmask);
0928f6 ¤   return file;
2befe6 }
f2af5a
7f711c /* Macro wrapper to inline the important part */
1017dc #define ringReserve(pool, len) \
b0bb3f ¤   ((pool)->pktbufalloc < (len) ? ringReserve(pool, len) : (pool)->pktbuf)
edaf5a
d095d7 /*·
b4b169 ·* This is the routine which fetches a packet from a keyring file.
74cfb4 ·* It tries the highest-priority file that the object is in which is also
84d804 ·* listed in "avoidmask." ·If the memory keyring is one of those, it has
07a5d2 ·* absolute priority. ·(It is also not verified; it is assumed correct.)
468ea0 ·* Otherwise, the object is fetched from the highest-priority open file.
42775e ·*
2bcc9f ·* The files are assigned priorities for fetching. ·The default is
600eb6 ·* that the first opened file is highest and subsequent files are of
7f16f2 ·* lower priority. ·This is done by having each Ringfile keep a mask
a18480 ·* of higher-priority RingFiles. ·We walk along the list until we hit
97ebc8 ·* a RingFile whose higher-priority mask doesn't include any files that
b93246 ·* the object being sought is in.
77775e ·*
c25875 ·* The packet fetched must pass the following validity checks:
69f9db ·* - It must be of the given packet type.
14f487 ·* - It must be no longer than "maxlen".
ca30b1 ·* - If those pass, it must be read into memory successfully.
4141ae ·* - It must then pass the caller-supplied "verify" function,
509248 ·* ··which checks object-type-specific information against the
--4ce1 0007ec219d140100201 Page 13 of pgpRngRead.c
0684a6 ·* ··summary information stored in the RingObject.
34775e ·*
eaaee5 ·* Question: what to return when the avoidmask doesn't allow anything to
e61af1 ·* be fetched? ·Is this case just an error?
39495d ·*/
719c71 static void const *
4d1139 ringFetchPacket(RingPool *pool, union RingObject const *obj,
c93eb8 ¤   PGPVirtMask *avoidmask, int pkttype, PGPSize maxlen, PGPSize *lenp,
e24401 ¤   int (*verify)(RingPool *pool, union RingObject const *, PGPByte const *,
7c3c42 ¤   ¤   ¤   ¤   ··size_t))
0dbb36 {
caff7f ¤   RingFile *file;
cd9087 ¤   FilePos const *pos;
72ade5 ¤   PGPSize len, len1;
f04ba4 ¤   int i;
98141e ¤   void *p;
18af5a
4b7b2b ¤   /* find highest-priority fetchable file */
9889b6 ¤   file = ringBestFile(pool, obj, avoidmask);
d779f9 ¤   if (!file) {
15fae4 ¤   ¤   *lenp = (size_t)0;
1c0441 ¤   ¤   return NULL;¤   /* Is this The Right Thing? */
c59371 ¤   }
06af5a
05880f ¤   pos = ringFilePos(obj, file);
2ef10a ¤   pgpAssert(pos);
9daf5a
7828e4 ¤   /* If it's in memory, that was easy... */
2b76da ¤   if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
471a58 ¤   ¤   pgpAssert (!verify
bbd5ee ¤   ¤   ········|| verify(pool, obj, (PGPByte *)pos->ptr.buf, pos->fpos) == 0);
bf370b ¤   ¤   *lenp = pos->fpos;
34c175 ¤   ¤   return pos->ptr.buf;
c99371 ¤   }
8daf5a
26f2a5 ¤   /* We now have highest-priority fetchable file */
681b0f ¤   pgpAssert(file->f);
3ff4cb ¤   if (pgpFileSeek(file->f, pos->fpos, SEEK_SET) != 0) {
4e20ba ¤   ¤   i = kPGPError_FileOpFailed;
351dec ¤   ¤   goto err;
2a9371 ¤   }
269581 ¤   i = pktByteGet(file->f, &len, &len1, (PGPSize *)NULL);
fb07eb ¤   if (i <= 0)
8f1dec ¤   ¤   goto err;
55c124 ¤   if (PKTBYTE_TYPE(i) != pkttype || len > maxlen) {
39bfe5 ¤   ¤   i = kPGPError_BadPacket;
ca1dec ¤   ¤   goto err;
9f9371 ¤   }
3f40e9 ¤   p = ringReserve(pool, (size_t)len);
314dda ¤   if (!p)
492aaf ¤   ¤   goto errmem;¤   /* ringErr() already called */
166677 ¤   pool->pktbuflen = len;
892aae ¤   i = pktBodyRead(pool->pktbuf, len, len1, file->f);
027012 ¤   if ((size_t)i != (size_t)len) {
cf7ae7 ¤   ¤   i = pgpFileError(file->f) ? kPGPError_ReadFailed :
dbcbf8 ¤   ¤   ¤   ¤   ¤   ····kPGPError_EOF;
681dec ¤   ¤   goto err;
939371 ¤   }
bbe959 ¤   p = pool->pktbuf;
d0af5a
0ba9dd ¤   /* Okay, now verify with supplied function */
e3d613 ¤   if (verify && (i = verify(pool, obj, (PGPByte const *)p, len)) != 0) {
a8cf7f ¤   ¤   if (pkttype == PKTBYTE_SECKEY
4a0149 ¤   ¤   ····&& len
bf8289 ¤   ¤   ····&& obj->g.flags & SECF_VERSION_BUG
3dbece ¤   ¤   ····&& ((PGPByte *)p)[0] == PGPVERSION_3) {
537aad ¤   ¤   ¤   /*
212ee5 ¤   ¤   ¤   ·* Failure may be due to version bug; fix and try
c8500f ¤   ¤   ¤   ·* again. ·If success, put it back so we behave
92228b ¤   ¤   ¤   ·* consistently. ·Verify doesn't always fail with
259c24 ¤   ¤   ¤   ·* version bug, it depends on whether sec or pub was
7e1992 ¤   ¤   ¤   ·* seen first.
--86a8 0004d0b14c940100201 Page 14 of pgpRngRead.c
398753 ¤   ¤   ¤   ·*/
c8db34 ¤   ¤   ¤   ((PGPByte *)p)[0] = PGPVERSION_2;
b32a3e ¤   ¤   ¤   if (verify &&
1505dd ¤   ¤   ¤   ····(i = verify(pool, obj, (PGPByte const *)p, len)) != 0)
16e0c3 ¤   ¤   ¤   ¤   goto err;
6881e8 ¤   ¤   ¤   ((PGPByte *)p)[0] = PGPVERSION_3;
a745a6 ¤   ¤   } else {
822776 ¤   ¤   ¤   goto err;
d10fe4 ¤   ¤   }
a89371 ¤   }
b4af5a
8f7d9d ¤   /* Success! */
66e15a ¤   *lenp = len;
02381d ¤   return p;
16af5a
a485fc ¤   /* Error cases (out of line) */
23353c err:
4f0f3c ¤   ringErr(file, pos->fpos, (PGPError)i);
fd9b0e errmem:
33f8a9 ¤   *lenp = 0;
b53f59 ¤   return NULL;
02efe6 }
4daf5a
e838e5 /*
81e893 ·* The verify functions here should *never* fail under normal
c53db4 ·* conditions. ·They fail only if the keyring file has been
426695 ·* changed while PGP is accessing it (which causes a fatal error).
0d5bcf ·* Did I mention that this code is *paranoid*?
bd2632 ·* ("The computer is your friend. ·The computer wants you to be happy.")
b3775e ·*
c13e49 ·* They operate by re-parsing the fetched data and checking that
81334e ·* the cached data matches the data just fetched.
16495d ·*/
2aaf5a
c90a4d /* Verify that the key we just read looks like the one we wanted to read. */
10beb7 static int
87a1d6 ringKeyVerify(RingPool *pool, union RingObject const *obj,
c72329 ¤   PGPByte const *p, size_t len)
1cbb36 {
534ba4 ¤   int i;
9204e1 ¤   PGPByte pkalg, keyID[8];
8f82df ¤   PGPUInt16 keybits, validity;
92e0c3 ¤   PGPUInt32 tstamp;
e7e7f9 ¤   PGPByte v3;
79af5a
0555cd ¤   i = ringKeyParse(pool->context, p, len, &pkalg, keyID, &keybits,
7e8172 ¤   ·················&tstamp, &validity, &v3, 0);
78af5a
76fca6 ¤   if (memcmp(keyID, obj->k.keyID, 8) == 0
4a9c7e ¤   ····&& keybits ·== obj->k.keybits
28c95c ¤   ····&& tstamp ··== obj->k.tstamp
a82658 /*¤ ····&& validity == obj->k.validity ·Validity sometimes stored elsewhere */
ddbc3b ¤   ····&& pkalg ···== obj->k.pkalg
22512d ¤   ¤   && v3¤  ¤   == !!KEYISV3(&obj->k)
0ef237 ¤   ····&& (i == 0) == !(obj->g.flags & KEYF_ERROR))
219057 ¤   ¤   return 0;¤  /* All copascetic */
91af5a
c08aa7 ¤   return kPGPError_BadPacket;
8aefe6 }
feaf5a
f1958c /* Verify that the secret we just read looks like the one we wanted to read. */
69beb7 static int
4ccdd1 ringSecVerify(RingPool *pool, union RingObject const *obj,
962329 ¤   PGPByte const *p, size_t len)
c3bb36 {
d34ba4 ¤   int i;
4b04e1 ¤   PGPByte pkalg, keyID[8];
d582df ¤   PGPUInt16 keybits, validity;
37e0c3 ¤   PGPUInt32 tstamp;
45e7f9 ¤   PGPByte v3;
b9a27a ¤   union RingObject *key = obj->g.up;
4daf5a
--b6ab 000545c0ed940100201 Page 15 of pgpRngRead.c
4a98c2 ¤   pgpAssert(OBJISSEC(obj));
6094a2 ¤   pgpAssert(OBJISKEY(key));
d8af5a
df55cd ¤   i = ringKeyParse(pool->context, p, len, &pkalg, keyID, &keybits,
d59dc9 ¤   ·················&tstamp, &validity, &v3, 1);
65af5a
a92d93 ¤   if (ringHashBuf(p, len) == obj->c.hash
720803 ¤   ····&& memcmp(keyID, key->k.keyID, 8) == 0
519067 ¤   ····&& keybits ·== key->k.keybits
b7b090 ¤   ····&& tstamp ··== key->k.tstamp
4d02b0 /*¤ ····&& validity == key->k.validity¤ Validity sometimes stored elsewhere */
f9a7e1 ¤   ····&& pkalg ···== key->k.pkalg
f0ce26 ¤   ¤   && v3¤  ¤   == !!KEYISV3(&key->k)
6c8fb8 ¤   ····&& (i == 0) == !(key->g.flags & KEYF_ERROR))
329057 ¤   ¤   return 0;¤  /* All copascetic */
83af5a
3b8aa7 ¤   return kPGPError_BadPacket;
57efe6 }
a9af5a
3438e5 /*
4fae39 ·* Verify that the signature we just read looks like the one we wanted to read.
46495d ·*/
09beb7 static int
eb13f1 ringSigVerify(RingPool *pool, union RingObject const *obj,
ec2329 ¤   PGPByte const *p, size_t len)
42bb36 {
ea4ba4 ¤   int i;
1f04e1 ¤   PGPByte pkalg, keyID[8];
c0e0c3 ¤   PGPUInt32 tstamp;
a36b1d ¤   PGPUInt16 validity;
ce1613 ¤   size_t extralen;
7694db ¤   PGPByte type, hashalg;
4f5bd0 ¤   PGPByte version;
5b7d67 ¤   PGPBoolean exportable;
a5f8be ¤   PGPBoolean revocable;
2e16bd ¤   PGPBoolean hasRegExp;
763eb3 ¤   PGPBoolean isX509;
af6325 ¤   PGPByte trustLevel;
588840 ¤   PGPByte trustValue;
50af5a
f8e7bd ¤   (void) pool;
6caf5a
e70cb3 ¤   i = ringSigParse(p, len, &pkalg, keyID, &tstamp, &validity,
a95966 ¤   ·················&type, &hashalg, &extralen, &version, &exportable,
3b77b5 ¤   ¤   ¤   ¤   ¤   ·&revocable, &trustLevel, &trustValue, &hasRegExp,
a2f6e9 ¤   ¤   ¤   ¤   ¤   ·&isX509);
206704 ¤   /* Allow mismatch on keyid on X509 sigs */
c67180 ¤   if ((isX509 || memcmp(keyID, obj->s.by->k.keyID, 8) == 0)
2e199b ¤   ¤   && version == obj->s.version
c7318f ¤   ····&& tstamp == obj->s.tstamp
13b90e ¤   ····&& validity == obj->s.validity
5589e9 ¤   ····&& type == obj->s.type
454c07 ¤   ····&& hashalg == obj->s.hashalg
e204ae ¤   ····&& (extralen == 5) == !(obj->g.flags & SIGF_NONFIVE)
252d54 ¤   ····&& (i == 0) == !(obj->g.flags & SIGF_ERROR)
c5144a ¤   ¤   && (!exportable == !SIGISEXPORTABLE(&obj->s))
241f75 ¤   ¤   && (!revocable == !SIGISREVOCABLE(&obj->s))
4b0c1d ¤   ¤   && (!hasRegExp == !SIGUSESREGEXP(&obj->s))
5c673a ¤   ¤   && (!isX509 == !SIGISX509(&obj->s)))
399057 ¤   ¤   return 0;¤  /* All copascetic */
93af5a
d48aa7 ¤   return kPGPError_BadPacket;
65efe6 }
90af5a
fc38e5 /*
442a33 ·* Verify that the unknown we just read looks like the one we wanted to read.
49495d ·*/
f2beb7 static int
af05f2 ringUnkVerify(RingPool *pool, union RingObject const *obj,
9c2329 ¤   PGPByte const *p, size_t len)
99bb36 {
54e7bd ¤   (void) pool;
--e106 0006acbb77a40100201 Page 16 of pgpRngRead.c
e0af5a
f146f7 ¤   if (ringHashBuf(p, len) == obj->u.hash)
449057 ¤   ¤   return 0;¤  /* All copascetic */
37af5a
af8aa7 ¤   return kPGPError_BadPacket;
adefe6 }
5baf5a
3038e5 /*
913a43 ·* Getting names is special due to the in-memory cache.
065480 ·* We don't have to support "avoidmask", though.
fe775e ·*
144281 ·* Return a pointer to a name string. ·Note that the string is NOT
ff5b35 ·* null-terminated; all 256 values are legal! ·The "lenp" argument
2aa133 ·* returns the length. ·Tries to get it from memory if possible,
e0d7b8 ·* then tries to load it into the cache. ·If it can't load it into
faf8f5 ·* the preferred file cache, load it into the pktbuf. ·If even
bbf2aa ·* that fails, try to find another cache that it wil fit into.
f3775e ·*
079122 ·* (Note: although strings are not in general null-terminated, hence we
649a20 ·* return a length field, we do in fact put a null character at name[length]
9cfec1 ·* so that callers can be sure that there is a null either within or just
2186b6 ·* beyond the name itself. ·This facilitates our regexp matching.)
00775e ·*
56109b ·* Note that ringNamesDiffer() uses the fact that this either returns
8da63c ·* with NAMEISCACHED(name) true, *or* the buffer returned is the
1e00a5 ·* pktbuf. ·Never both, and never a third choice.
c0775e ·*
462698 ·* @@@ Is the ability to hande a pool==NULL still useful?
14495d ·*/
02d10a static char const *
6740a4 ringPoolGetName(RingPool *pool, RingName *name, PGPSize *lenp)
59bb36 {
9d4ba4 ¤   int i;
24ecb0 ¤   MemPool cut;
c845d1 ¤   PGPVirtMask mask;
e2931f ¤   RingFile *file, *file2;
fa9087 ¤   FilePos const *pos;
a6dc9b ¤   char *str;
eaade5 ¤   PGPSize len, len1;
d6af5a
c2192f ¤   *lenp = name->len;
bbaf5a
6b384f ¤   /* If we already have it, boom. */
561898 ¤   if (NAMEISCACHED(name))
a50d70 ¤   ¤   return name->name.ptr;
d8af5a
9430f0 ¤   /* If we weren't given a pool, we can't fetch it */
c7fcfd ¤   if (!pool)
c27ed2 ¤   ¤   return NULL;
faaf5a
c914fb ¤   pgpVirtMaskInit (pool, &mask);
d1af5a
4c7b2b ¤   /* find highest-priority fetchable file */
567e8c ¤   file = ringBestFile(pool, (union RingObject *)name, 0);
0d3567 ¤   pgpAssert(file);
8180b2 ¤   pgpAssert(file->f ||
6ef023 ¤   ¤   ¤   ··pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask));
d5af5a
d30c30 ¤   pos = ringFilePos((union RingObject *)name, file);
94f10a ¤   pgpAssert(pos);
ecaf5a
c54db1 ¤   /* If it's in memory, that was fast - set cached if it wasn't already*/
1776da ¤   if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
2aa78d ¤   ¤   pgpAssert(pos->fpos == name->len);
73c64d ¤   ¤   pgpAssert(ringHashBuf((PGPByte *)pos->ptr.buf, name->len) ==
754f6a ¤   ¤   ·······name->name.hash);
e799ab ¤   ¤   NAMESETCACHED(name);
e8b9f5 ¤   ¤   NAMESETFILEMASK(name, MEMRINGBIT);
a53157 ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
83efbc ¤   ¤   return name->name.ptr = (char *)pos->ptr.buf;
7b9371 ¤   }
6aaf5a
--f481 000921d072d40100201 Page 17 of pgpRngRead.c
ab8613 ¤   /* Allocate cache space for it */
fd67a2 ¤   /* Dummy loop to break out of */
5443ab ¤   do {
30ca8b ¤   ¤   /* Try the preferred cache */
61bb0d ¤   ¤   file2 = file;
197087 ¤   ¤   cut = file2->strings;¤  /* Remember cutback position */
ceb21a ¤   ¤   str = (char *)memPoolAlloc(&file2->strings, name->len + 1, 1);
5dd149 ¤   ¤   if (str)
53cdcb ¤   ¤   ¤   break;
51e5cf ¤   ¤   /* Try the pktbuf */
3c3f69 ¤   ¤   str = ringReserve(pool, name->len + 1);
209d0d ¤   ¤   if (str) {
ba6b17 ¤   ¤   ¤   file2 = NULL;
9f2b9c ¤   ¤   ¤   pool->pktbuflen = name->len;
fecdcb ¤   ¤   ¤   break;
d80fe4 ¤   ¤   }
530393 ¤   ¤   /* Okay, desperation time - look for any cache */
4757bd ¤   ¤   pgpVirtMaskCopy (pool, &name->mask, &mask);
40d417 ¤   ¤   pgpVirtMaskAND (pool, &pool->filemask, &mask);
3a4ed8 ¤   ¤   pgpVirtMaskANDNOT (pool, &pool->memringmask, &mask);
123daa ¤   ¤   pos = &name->pos;
32c0ad ¤   ¤   for (;;) {
b84684 ¤   ¤   ¤   i = pgpVirtMaskLSBit(&mask);
294353 ¤   ¤   ¤   pgpAssert(i >= 0);
b0699b ¤   ¤   ¤   pgpAssert(pool->files[i]->f);
21da16 ¤   ¤   ¤   file2 = pool->files[i];
967dda ¤   ¤   ¤   cut = file2->strings;
8219b4 ¤   ¤   ¤   str = (char *)memPoolAlloc(&file2->strings,
f08eec ¤   ¤   ¤   ···························name->len + 1, 1);
be90c2 ¤   ¤   ¤   if (str)
22f622 ¤   ¤   ¤   ¤   break;
080bdb ¤   ¤   ¤   pgpVirtMaskClearBit (pool, &mask, i);
680d3d ¤   ¤   ¤   if (pgpVirtMaskIsEmpty (&mask)) {
8e6311 ¤   ¤   ¤   ¤   ringAllocErr(pool);
c847ac ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
c0fb5e ¤   ¤   ¤   ¤   return NULL;
cfa3a6 ¤   ¤   ¤   }
fcfff8 ¤   ¤   ¤   pos = pos->ptr.next;
7f0fe4 ¤   ¤   }
83bcdb ¤   } while (0);¤   /* Dummy loop to break out of */
89af5a
398f4e ¤   /* Okay, we got buffer space... get the packet */
fcaf5a
74f4cb ¤   if (pgpFileSeek(file->f, pos->fpos, SEEK_SET) != 0) {
aa20ba ¤   ¤   i = kPGPError_FileOpFailed;
e997ed ¤   ¤   goto error;
989371 ¤   }
fb9581 ¤   i = pktByteGet(file->f, &len, &len1, (PGPSize *)NULL);
644fd6 ¤   if (i < 0)
c297ed ¤   ¤   goto error;
8faa52 ¤   if (PKTBYTE_TYPE(i) !=
243b27 ¤   ¤   ¤   ¤   ¤   (NAMEISATTR(name) ? PKTBYTE_ATTRIBUTE : PKTBYTE_NAME)
7c60ba ¤   ¤   ¤   || len != name->len)
be4f70 ¤   ¤   goto badpkt;
25af5a
63cf51 ¤   i = pktBodyRead(str, len, len1, file->f);
2ac527 ¤   str[len] = '\0';¤   ¤   ¤   /* null char beyond end of name */
f57012 ¤   if ((size_t)i != (size_t)len) {
a67ae7 ¤   ¤   i = pgpFileError(file->f) ? kPGPError_ReadFailed :
dacbf8 ¤   ¤   ¤   ¤   ¤   ····kPGPError_EOF;
6797ed ¤   ¤   goto error;
529371 ¤   }
faaf5a
1933b0 ¤   /* Double-check that we got the right thing. */
6ca9da ¤   if (ringHashBuf((PGPByte *)str, len) != name->name.hash)
ea4f70 ¤   ¤   goto badpkt;
feaf5a
5b8a8f ¤   /* Success at last! */
5857a4 ¤   if (file2) {
ad746c ¤   ¤   /* It's cached in file2 - set flags appropriately */
7b99ab ¤   ¤   NAMESETCACHED(name);
923363 ¤   ¤   NAMESETFILEMASK(name, pgpVirtMaskLSBit(&file2->set.mask));
--7f5d 0002ea0fee740100201 Page 18 of pgpRngRead.c
abc106 ¤   ¤   name->name.ptr = str;
d69371 ¤   }
dd0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
309aea ¤   return str;
ec67c5 ¤
d23f10 badpkt:
ee04b3 ¤   i = kPGPError_BadPacket;
7e60ff error:
68c9ba ¤   if (file2)
926d66 ¤   ¤   memPoolCutBack(&file2->strings, &cut);
680f3c ¤   ringErr(file, pos->fpos, (PGPError)i);
920db9 ¤   pgpVirtMaskCleanup (pool, &mask);
2b3f59 ¤   return NULL;
1cefe6 }
f2af5a
eeaf5a
2311b3 void const *
e5f203 ringFetchObject(RingSet const *set, union RingObject *obj, PGPSize *lenp)
dbbb36 {
6739ca ¤   PGPByte const *buf = NULL;
090475 ¤   PGPVirtMask secmask, bestfile;¤ /* Needed in RINGTYPE_KEY */
237194 ¤   PGPVirtMask notsecmask;
dd6032 ¤   RingPool *pool = set->pool;
954fc6 ¤   PGPByte pktbyte;
f9af5a
24673b ¤   pgpVirtMaskInit (pool, &secmask);
820a58 ¤   pgpVirtMaskInit (pool, &notsecmask);
e78ef8 ¤   pgpVirtMaskInit (pool, &bestfile);
5e67c5 ¤
099090 ¤   pgpAssert(pgpIsRingSetMember(set, obj));
cdc1d6 ¤   pgpAssert(pgpVirtMaskIsOverlapping(&obj->g.mask, &pool->filemask));
cfaf5a
b68ccb ¤   switch (ringObjectType(obj)) {
e13db6 ¤   ··case RINGTYPE_NAME:
33c6b9 ¤   ¤   buf = (PGPByte const *)ringPoolGetName(pool, &obj->n, lenp);
9a2f68 ¤   ¤   break;
9449ef ¤   ··case RINGTYPE_SIG:
b11318 ¤   ¤   buf = (PGPByte const *)ringFetchPacket(pool, obj, NULL, PKTBYTE_SIG,
4c5ea1 ¤   ¤   ¤   ¤   ¤   ··RINGSIG_MAXLEN, lenp, ringSigVerify);
cc2f68 ¤   ¤   break;
1980f5 ¤   ··case RINGTYPE_UNK:
35d179 ¤   ¤   buf = (PGPByte const *)ringFetchPacket(pool, obj, NULL,
3a0f1b ¤   ¤   ··························PKTBYTE_TYPE(obj->u.pktbyte),
127362 ¤   ¤   ¤   ¤   ¤   ··RINGUNK_MAXLEN, lenp, ringUnkVerify);
802f68 ¤   ¤   break;
55bdba ¤   ··case RINGTYPE_SEC:
2c343b ¤   ·······pktbyte = OBJISTOPKEY(obj->g.up) ? PKTBYTE_SECKEY :
56867b ¤   ¤   ·······PKTBYTE_SECSUBKEY;
e8d179 ¤   ¤   buf = (PGPByte const *)ringFetchPacket(pool, obj, NULL,
0bd661 ¤   ¤   ··························pktbyte, RINGSEC_MAXLEN,
3ad4e5 ¤   ¤   ··························lenp, ringSecVerify);
0e7d75 ···············/* Compensate for version bug */
a59803 ¤   ¤   if (buf
aa9604 ¤   ¤   ····&& *lenp > 0
a08289 ¤   ¤   ····&& obj->g.flags & SECF_VERSION_BUG
48dc43 ¤   ¤   ····&& buf[0] == PGPVERSION_3)
f1010e ¤   ¤   ¤   ((PGPByte *)buf)[0] = PGPVERSION_2;
9d2f68 ¤   ¤   break;
65a535 ¤   ··case RINGTYPE_KEY:
ca4f51 ¤   ¤   /* File we'd like to fetch from */
936b80 ¤   ¤   pgpVirtMaskCopy (pool,
acc603 ¤   ¤   ¤   ¤   ¤   ¤   ·&(ringBestFile(pool, obj, 0)->set.mask), &bestfile);
55c9f3 ¤   ¤   /* Where secrets are located */
15cfa3 ¤   ¤   ringKeySecMask(pool, obj, &secmask);
6aaf5a
8fcb9c ¤   ¤   /* Is where we want to fetch from secret? */
d3c73f ¤   ¤   if (pgpVirtMaskIsOverlapping (&bestfile, &secmask)) {
cc3fe8 ¤   ¤   ¤   pktbyte = OBJISTOPKEY(obj) ? PKTBYTE_SECKEY :
e2739c ¤   ¤   ¤   ¤   PKTBYTE_SECSUBKEY;
18ba86 ¤   ¤   ¤   /* Have to fetch the secret key and extract. */
72d72e ¤   ¤   ¤   obj = obj->g.down;
2effd6 ¤   ¤   ¤   while (!pgpVirtMaskIsOverlapping(&obj->g.mask, &bestfile)
--005e 000c4bde4bc40100201 Page 19 of pgpRngRead.c
fbfee3 ¤   ¤   ¤   ¤   ···|| !OBJISSEC(obj)) {
387ae1 ¤   ¤   ¤   ¤   obj = obj->g.next;
abe94a ¤   ¤   ¤   ¤   pgpAssert(obj);
46a3a6 ¤   ¤   ¤   }
238b85 ¤   ¤   ¤   pgpVirtMaskCopy(pool, &secmask, &notsecmask);
db7209 ¤   ¤   ¤   pgpVirtMaskNOT(pool, &notsecmask, pool->nfiles);
02c255 ¤   ¤   ¤   buf = (PGPByte const *)ringFetchPacket(pool, obj,
c89f19 ¤   ¤   ¤   ¤   ¤   &notsecmask, pktbyte, RINGSEC_MAXLEN,
029662 ¤   ¤   ¤   ¤   ¤   lenp, ringSecVerify);
a61183 ¤   ¤   ¤   if (buf) {
44e9ee ¤   ¤   ¤   ¤   size_t len;
d4af5a
ec7906 ¤   ¤   ¤   ¤   /* Compensate for version bug */
fbcf98 ¤   ¤   ¤   ¤   if (*lenp > 0
274b1c ¤   ¤   ¤   ¤   ····&& obj->g.flags & SECF_VERSION_BUG
f14397 ¤   ¤   ¤   ¤   ····&& buf[0] == PGPVERSION_3)
bbc2e3 ¤   ¤   ¤   ¤   ¤   ((PGPByte *)buf)[0] = PGPVERSION_2;
9aaf5a
09262f ¤   ¤   ¤   ¤   len = ringKeyParsePublicPrefix(buf, *lenp);
a55568 ¤   ¤   ¤   ¤   /* If unparseable, take the whole thing. */
b50083 ¤   ¤   ¤   ¤   if (len)
789e0b ¤   ¤   ¤   ¤   ¤   *lenp = len;
81a3a6 ¤   ¤   ¤   }
c345a6 ¤   ¤   } else {
b92d42 ¤   ¤   ¤   pktbyte = OBJISTOPKEY(obj) ? PKTBYTE_PUBKEY :
fb1280 ¤   ¤   ¤   ¤   PKTBYTE_PUBSUBKEY;
0815b3 ¤   ¤   ¤   /* Fetch public components */
1409c8 ¤   ¤   ¤   buf = (PGPByte const *)ringFetchPacket(pool, obj, &secmask,
01f30b ¤   ¤   ¤   ······················pktbyte, RINGKEY_MAXLEN,
d69505 ¤   ¤   ¤   ······················lenp, ringKeyVerify);
600fe4 ¤   ¤   }
102f68 ¤   ¤   break;
0cf727 ¤   ··default:
257036 ¤   ¤   pgpAssert(0);
b92f68 ¤   ¤   break;
6b9371 ¤   }
6eb8b2 ¤   pgpVirtMaskCleanup (pool, &bestfile);
cd967c ¤   pgpVirtMaskCleanup (pool, &secmask);
fae5fb ¤   pgpVirtMaskCleanup (pool, &notsecmask);
36dfa1 ¤   return buf;
d7efe6 }
03af5a
021adf /*** Various bookkeeping helper functions ***/
05af5a
7e38e5 /*
cfa4f2 ·* Sort all the keys in a pool into keyID order. ·This uses 8 passes
05d99f ·* of a byte-wise radix sort. ·Each pass is stable, so sorting on the
10d76e ·* least significant byte, proceeding to the most will result in a
2dbbdd ·* completely sorted list.
a2775e ·*
bcf578 ·* Actually, it's sorted with the *visible* part (the low 32 bits) of the
b79ea8 ·* keyID more significant than the invisible part. ·This makes the ordering
9b8fc1 ·* more sensible to a human watching what's going on.
c7775e ·*
4c70aa ·* There are 256 lists, with a head and a tail pointer.¤ The tail
79bfe4 ·* pointer is a pointer to a pointer, namely the slot the pointer to
d75098 ·* the next entry to be added to the list goes in. ·It is initialized
da15cf ·* to point to the head pointer. ·So adding an element to the list
53dfd6 ·* consists of setting *tail = object; and then tail = &object->next;
2b775e ·*
1e9321 ·* After each pass, concatenate the lists, starting at the end.
7327ca ·* Begin with an empty list and keep appending the current list to
058dde ·* the tail of the one before it, grabbing the head as the new
7392a2 ·* current list.
90495d ·*/
55b177 #if 0
8fbeb7 static int
2a891b ringKeyIDcmp(PGPByte const id1[8], PGPByte const id2[8])
a2bb36 {
6f4ba4 ¤   int i;
2faf5a
c4d187 ¤   i = memcmp(id1+4, id2+4, 4);
--f9c2 000606b63ab40100201 Page 20 of pgpRngRead.c
4dcbf7 ¤   return i ? i : memcmp(id1, id2, 4);
ddefe6 }
2f7454 #endif
52af5a
c22978 static void
7dc8c0 ringSortKeys(RingPool *pool)
f6bb36 {
87a8af #if 1
7e7869 ¤   /*·
3f247d ¤   ·* Disable sort, users who switch back to old versions of
fbf303 ¤   ·* PGP are unhappy to see their keyring reordered. ·The reason
d2e78a ¤   ·* for the sort was to hide the order with which keys had been
45dd72 ¤   ·* added to the keyring, and to make merges more efficient.
abe4af ¤   ·* For now neither of those is compelling enough to keep.
2ea4e3 ¤   ·*/
017ca6 ¤   (void)pool;
e7db21 #else
22927e ¤   int i, j;
36a1bb ¤   int pass;
5d1cb2 ¤   int lastpass;
b8e7b3 ¤   union RingObject *list = pool->keys;
81f43b ¤   union RingObject *head[256];
d4ec1b ¤   union RingObject **tail[256];
48af5a
f6bb6c ¤   for (pass=0; pass<9; ++pass) {
07477b ¤   ¤   /* XXX Experimental backwards compat code - put DSA keys at end */
e03e95 ¤   ¤   /* On last pass we sort by pkalg */
cd2e56 ¤   ¤   lastpass = (pass==8);
582008 ¤   ¤   i = (pass < 4) ? (3-pass) : (11-pass); /* 3,2,1,0,7,6,5,4 */
7eaf5a
9d1cbd ¤   ¤   /* Clear the table for the next distribution pass */
3f011f ¤   ¤   for (j = 0; j < 256; j++)
e8ee71 ¤   ¤   ¤   tail[j] = head+j;
d1af5a
e5df43 ¤   ¤   /* Distribute the list elements among the sublists */
d6ebbf ¤   ¤   while (list) {
7391b0 ¤   ¤   ¤   if (lastpass)
9e7bb5 ¤   ¤   ¤   ¤   j = list->k.pkalg;
8dbb8c ¤   ¤   ¤   else
cd43fb ¤   ¤   ¤   ¤   j = list->k.keyID[i];
9a4065 ¤   ¤   ¤   *tail[j] = list;
3a04a2 ¤   ¤   ¤   tail[j] = &list->k.next;
68bcaa ¤   ¤   ¤   list = list->k.next;
9a0fe4 ¤   ¤   }
b5af5a
d7c68c ¤   ¤   j = 256;
e8e26c ¤   ¤   /* list is already 0 from the previous loop */
f8af5a
5f65f7 ¤   ¤   /* Gather the sublists back into one big list */
00189a ¤   ¤   while (j--) {
be4065 ¤   ¤   ¤   *tail[j] = list;
e28bc9 ¤   ¤   ¤   list = head[j];
fe0fe4 ¤   ¤   }
dc9371 ¤   }
96af5a
73af5a
d4ed72 ¤   pool->keys = list;
4a7454 #endif
b6efe6 }
8daf5a
422978 static void
0f806f ringPoolLinkKey(RingPool *pool, union RingObject *parent,
c010ff ¤   union RingObject *key, PGPByte pkalg, PGPByte const keyID[8])
3bbb36 {
cfa3aa ¤   union RingObject **ptr;
f7af5a
ee94a2 ¤   pgpAssert(OBJISKEY(key));
b7547d ¤   pgpCopyMemory( keyID, key->k.keyID, 8 );
63e250 ¤   key->k.pkalg = pkalg;
1caf5a
b7a0a5 ¤   if (parent) {
60fff4 ¤   ¤   key->g.up = parent;
--cd90 000488e61ec40100201 Page 21 of pgpRngRead.c
5a3620 ¤   ¤   ptr = &parent->g.down;
a96373 ¤   ¤   while (*ptr)
da5dda ¤   ¤   ¤   ptr = &(*ptr)->g.next;
7ff037 ¤   } else {
3a16c0 ¤   ¤   ptr = &pool->keys;
b59371 ¤   }
e64cbe ¤   key->g.next = *ptr;
3db646 ¤   *ptr = key;
18fe05 ¤   RINGPOOLHASHKEY(pool, key);
bfefe6 }
6daf5a
03143b /* Remove specified key from the top-level keys list */
f72978 static void
53c393 ringPoolUnlinkKey(RingPool *pool, union RingObject *key)
66bb36 {
7482ab ¤   union RingObject *obj, **objp;
71af5a
08ae32 ¤   pgpAssert(pool && key);
58af5a
d15ff3 ¤   objp = &pool->keys;
0886f3 ¤   while ((obj = *objp) != NULL && obj != key) {
da8cd7 ¤   ¤   objp = &obj->g.next;
649371 ¤   }
674fa1 ¤   pgpAssert(obj == key);
6f219a ¤   *objp = key->g.next;
45a2f9 ¤   key->g.next = NULL;
31830f ¤   return;
f3efe6 }
9aaf5a
fa38e5 /*
cf140f ·* Search for an X.509 key which signed this one. ·Information on the
d54d06 ·* current key is in the pool->pktbuf.
b4495d ·*/
2f984a static union RingObject *
15321a ringPoolFindDummyX509Key(RingPool *pool, RingFile *file)
b4bb36 {
1e6d20 ¤   PGPByte *certbuf;¤  ¤   ¤   /* X.509 cert we want to find signer of */
78cfbb ¤   PGPSize certlen;
881e92 ¤   PGPByte *certinfo;¤ ¤   ¤   /* cert info subpart of cert */
183f1f ¤   PGPSize certinfolen;
a4f09b ¤   PGPByte *issuername;¤   ¤   /* issuer name subpart of cert */
5be88f ¤   PGPSize issuerlen;
c05ac5 ¤   PGPByte *subjectname;¤  ¤   /* subject name of other key's cert */
0861dd ¤   PGPSize subjectlen;
85a14a ¤   PGPByte *pktcopy;¤  ¤   ¤   /* copy of signature packet */
d803c0 ¤   PGPSize pktlen;
546fa6 ¤   PGPByte *sigbuf;¤   ¤   ¤   /* sig of other X.509 key */
e5f066 ¤   PGPSize siglen;
c8f426 ¤   PGPByte hash[20];¤  ¤   ¤   /* hash of issuer name */
a8ac31 ¤   PGPByte *keyid;¤¤   ¤   ¤   /* faked-up keyid for dummy key */
6de310 ¤   RingObject *keys, *names, *sigs;
682558 ¤   PGPUInt32 fpos;¤¤   ¤   ¤   /* File pos */
0daf5a
0113ba ¤   certbuf = (PGPByte *)ringSigFindSubpacket ((PGPByte *)pool->pktbuf,
d381b7 ¤   ¤   ¤   ¤   ¤   SIGSUB_X509, 0, &certlen, NULL, NULL, NULL, NULL);
4a67c5 ¤
be926d ¤   pgpAssert (IsntNull( certbuf ) );
6867c5 ¤
14efe9 ¤   /* Find issuer name in cert */
1b8eba ¤   pgpX509CertPartition (certbuf, certlen, &certinfo, &certinfolen,
051008 ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, NULL, NULL);
6ff6d1 ¤   pgpX509CertInfoPartition (certinfo, certinfolen, NULL, NULL,
6f57a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, &issuername, &issuerlen, NULL, NULL,
9e012f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, NULL, NULL);
40af5a
8c6276 ¤   /* Calculate hash of issuer name */
a846c7 ¤   pgpFingerprint20HashBuf(pool->context, issuername, issuerlen, hash);
e67b7a ¤   keyid = hash + sizeof(hash) - 8;
04af5a
28d8af ¤   /*
24794f ¤   ·* First look to see if we have a key with that keyid. ·We set this
48f04f ¤   ·* on dummy keys that we create.
--6091 000161c282440100201 Page 22 of pgpRngRead.c
60a4e3 ¤   ·*/
2ea5de ¤   keys = ringPoolFindKey(pool, 0, keyid);
d9ced5 ¤   if (IsntNull( keys ) && pgpVirtMaskIsEmpty (&keys->g.mask))
75d528 ¤   ¤   return keys;
08af5a
cffa46 ¤   /* Make a copy of the pktbuf area, we'll overwrite it */
beed11 ¤   pktlen = pool->pktbuflen;
df5b6a ¤   pktcopy = (PGPByte *) pgpContextMemAlloc (pool->context,
1b543c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pool->pktbuflen, 0);
9dcf09 ¤   if (IsNull (pktcopy)) {
944257 ¤   ¤   ringSimpleErr(pool, kPGPError_OutOfMemory);
e97ed2 ¤   ¤   return NULL;
379371 ¤   }
345a4b ¤   pgpCopyMemory (pool->pktbuf, pktcopy, pktlen);
095877 ¤   /* Correct issurename pointer to be in copy */
af33d9 ¤   issuername = pktcopy + (issuername - (PGPByte *)pool->pktbuf);
f8af5a
f4935a ¤   /* We may move our file pointer below */
8cb35c ¤   fpos = pgpFileTell(file->f);
86af5a
afc24d ¤   /* Search for an X.509 key with subject name equal to our issuer name */
66c87e ¤   for (keys=pool->keys; keys; keys=keys->g.next) {
52e358 ¤   ¤   if (!OBJISTOPKEY(keys))
ff17f5 ¤   ¤   ¤   continue;
c5da42 ¤   ¤   for (names=keys->g.down; names; names = names->g.next) {
0b00a7 ¤   ¤   ¤   if (!OBJISNAME(names))
b6d040 ¤   ¤   ¤   ¤   continue;
b4ef80 ¤   ¤   ¤   for (sigs=names->g.down; sigs; sigs = sigs->g.next) {
b44857 ¤   ¤   ¤   ¤   if (OBJISSIG(sigs) && SIGISX509(&sigs->s)) {
f16e21 ¤   ¤   ¤   ¤   ¤   sigbuf = (PGPByte *)ringFetchPacket (pool, sigs, NULL,
1847c4 ¤   ¤   ¤   ¤   ¤   ¤   PKTBYTE_SIG, RINGSIG_MAXLEN, &siglen,
d11b2b ¤   ¤   ¤   ¤   ¤   ¤   ·ringSigVerify);
483af6 ¤   ¤   ¤   ¤   ¤   /* Find subject name, compare with issuer name above */
f80b73 ¤   ¤   ¤   ¤   ¤   certbuf = (PGPByte *)ringSigFindSubpacket (sigbuf,
6b511c ¤   ¤   ¤   ¤   ¤   ¤   SIGSUB_X509, 0, &certlen, NULL, NULL, NULL, NULL);
8acdf2 ¤   ¤   ¤   ¤   ¤   pgpX509CertPartition (certbuf, pool->pktbuflen,
d8a0b9 ¤   ¤   ¤   ¤   ¤   ¤   &certinfo, &certinfolen, NULL, NULL, NULL, NULL);
9ac6fa ¤   ¤   ¤   ¤   ¤   pgpX509CertInfoPartition (certinfo, certinfolen,
4b048e ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
75ab3d ¤   ¤   ¤   ¤   ¤   ¤   &subjectname, &subjectlen, NULL, NULL);
c1c55a ¤   ¤   ¤   ¤   ¤   if (issuerlen == subjectlen &&
2717cf ¤   ¤   ¤   ¤   ¤   ¤   0 == memcmp (issuername, subjectname, issuerlen)) {
b39936 ¤   ¤   ¤   ¤   ¤   ¤   /* Have a match! */
0300eb ¤   ¤   ¤   ¤   ¤   ¤   break;
691c89 ¤   ¤   ¤   ¤   ¤   }
652613 ¤   ¤   ¤   ¤   }
d1a3a6 ¤   ¤   ¤   }
35d6d4 ¤   ¤   ¤   if (sigs)
90f622 ¤   ¤   ¤   ¤   break;
640fe4 ¤   ¤   }
d38343 ¤   ¤   if (names)
47cdcb ¤   ¤   ¤   break;
429371 ¤   }
7755a4 ¤   /* Here, if keys is non-NULL, we found a match */
b5af5a
6e654a ¤   /* Restore pool->pktbuf */
7e6666 ¤   ringReserve (pool, pktlen);
aa9538 ¤   pgpCopyMemory( pktcopy, pool->pktbuf, pktlen );
633678 ¤   pool->pktbuflen = pktlen;
132849 ¤   pgpContextMemFree (pool->context, pktcopy);
b02462 ¤   pgpFileSeek (file->f, fpos, SEEK_SET);
b067c5 ¤
62a1d4 ¤   if( IsNull( keys ) ) {
33af5a
cf0dae ¤   ¤   /* Must make dummy key, set keyid from hash of issuer name */
39c231 ¤   ¤   keys = ringNewKey(pool);
23e6ea ¤   ¤   if (IsntNull (keys)) {
f0c084 ¤   ¤   ¤   ringPoolLinkKey (pool, NULL, keys, 0, keyid);
b90fe4 ¤   ¤   }
9f9371 ¤   }
1aaf5a
1694a3 ¤   return keys;
--7833 00084c6313840100201 Page 23 of pgpRngRead.c
7aefe6 }
46af5a
8eaf5a
79af5a
ab38e5 /*
6af921 ·* Same as ringPoolFindKey, but creates a dummy key with the given parent
bc4cf7 ·* if one is not found.
7e5534 ·* Note that a dummy key is a RingObject with its mask set to 0.
5c495d ·*/
94984a static union RingObject *
eecba9 ringPoolFindDummyKey(RingPool *pool, RingFile *file, RingObject *parent,
a51988 ¤   PGPByte pkalg, PGPByte const keyID[8], PGPBoolean isX509)
95bb36 {
d4b957 ¤   union RingObject *key;
a8af5a
8375ee ¤   if (isX509) {
ea118d ¤   ¤   pgpAssert (IsNull (parent));
f597ec ¤   ¤   key = ringPoolFindDummyX509Key (pool, file);
23a565 ¤   ¤   pgpAssert (IsntNull (key));
b52be7 ¤   } else
640228 ¤   ¤   key = ringPoolFindKey(pool, pkalg, keyID);
77af5a
6cebb3 ¤   if (!key) {
e5046a ¤   ¤   key = ringNewKey(pool);
0ff75f ¤   ¤   if (key) {
908c17 ¤   ¤   ¤   if (parent)
1315c1 ¤   ¤   ¤   ¤   key->k.flags |= RINGOBJF_SUBKEY;
c0e690 ¤   ¤   ¤   ringPoolLinkKey(pool, parent, key, pkalg, keyID);
610fe4 ¤   ¤   }
5a9371 ¤   }
138236 ¤   return key;
adefe6 }
6aaf5a
8738e5 /*
66eba7 ·* Free an entire tree of objects.
db6316 ·* This does not do anything with the FilePos chain, but since the
1a8e72 ·* first entry is preallocated, if the object has at most one FilePos,
f028b1 ·* (as is the case in newly created objects), no memory is leaked.
64495d ·*/
ad2978 static void
4ce0c5 ringFreeTree(RingPool *pool, union RingObject *obj)
1cbb36 {
6f439e ¤   union RingObject *down;
84af5a
b7436d ¤   if (!OBJISBOT(obj)) {
6d4e56 ¤   ¤   while ((down = obj->g.down) != NULL) {
5bbeeb ¤   ¤   ¤   obj->g.down = down->g.next;
8bc8d2 ¤   ¤   ¤   ringFreeTree(pool, down);
0e0fe4 ¤   ¤   }
e19371 ¤   }
35be8a ¤   ringFreeObject(pool, obj);
05efe6 }
83af5a
ce38e5 /*
8f6c94 ·* Free up a newly created dummy key.·
603bf5 ·* Unlink it from the pool and free it and all descendents.
9d495d ·*/
fb2978 static void
34206e ringFreeDummyKey(RingPool *pool, union RingObject *key)
9cbb36 {
faf39b ¤   union RingObject **objp;
ffaf5a
8594a2 ¤   pgpAssert(OBJISKEY(key));
0daf5a
e21ec1 ¤   /* Find head of list this object is on */
8dec10 ¤   if (OBJISTOP(key))
b3a996 ¤   ¤   objp = &pool->keys;
ce0e24 ¤   else
3174a2 ¤   ¤   objp = &key->g.up->g.down;
cdaf5a
fbe456 ¤   while (*objp != key) {
849941 ¤   ¤   pgpAssert(*objp);
--4be2 0003ef0010f40100201 Page 24 of pgpRngRead.c
dfed55 ¤   ¤   objp = &(*objp)->g.next;
bd9371 ¤   }
90219a ¤   *objp = key->g.next;
abfb21 ¤   ringFreeTree(pool, key);
ecefe6 }
71af5a
6238e5 /*
d1f811 ·* Return 0 if the packet in the pktbuf is the same as the packet in
50718d ·* the given file at the given offset, and the file packet is of type
224a51 ·* pkttype. ·Returns 1 if they differ, and -1 (and sets the ring's error
0d7934 ·* status) if there is an error, including an unexpected packet byte.
fd64b6 ·* Compare at most max bytes.
b1775e ·*
4921b9 ·* This does NOT examine any more of the object than its filepos
313847 ·* chain; in particular, it does NOT examine the object's type.
0deccb ·* Thus, it is possible to have a key object and use it to
eda774 ·* fetch a secret-key packet.
76775e ·*
659dce ·* Special case: returns pktbuf[0] if pktbuf[0] is 2 or 3 and the file's
747c23 ·* packet begins with 5-pktbuf[0]. ·This is used by the key difference
f10d9f ·* code to detect the version byte bug. ·The other things can ignore it,
2cc63f ·* and just treat all positive return values as "different".
67495d ·*/
3fbeb7 static int
276094 ringPacketDiffers(RingFile *file, union RingObject const *obj,
2728ad ¤   int pkttype, PGPUInt32 max)
9dbb36 {
a9c975 ¤   RingPool *pool = file->set.pool;
ee9087 ¤   FilePos const *pos;
f14cc9 ¤   PGPByte *p;
e0103d ¤   PGPFile *f;
9cade5 ¤   PGPSize len, len1;
8a4ba4 ¤   int i;
a5a508 ¤   PGPByte c;
a95321 ¤   int magic;
00af5a
95880f ¤   pos = ringFilePos(obj, file);
21af5a
4243cb ¤   /* Memory file, special case for comparison */
1a76da ¤   if (pgpVirtMaskIsEqual (&file->set.mask, &pool->memringmask)) {
e540cd ¤   ¤   len = pos->fpos;
f02aba ¤   ¤   if (len > max)
08f63d ¤   ¤   ¤   len = max;
7e9cc3 ¤   ¤   if (max > pool->pktbuflen)
6ef11d ¤   ¤   ¤   max = pool->pktbuflen;
b56e75 ¤   ¤   if (len != max)
b66f79 ¤   ¤   ¤   return 1;¤  /* Different */
63c1b1 ¤   ¤   if (!len)
298144 ¤   ¤   ¤   return 0;
5508a2 ¤   ¤   /* Check first character specially */
862270 ¤   ¤   p = (PGPByte *)pos->ptr.buf;
499828 ¤   ¤   magic = 0;
a1ec75 ¤   ¤   if (p[0] != ((PGPByte *)pool->pktbuf)[0]) {
1a3034 ¤   ¤   ¤   if ((p[0] ^ ((PGPByte *)pool->pktbuf)[0]) != 1
6d0867 ¤   ¤   ¤   ····|| (p[0] & ((PGPByte *)pool->pktbuf)[0]) != 2)
225b34 ¤   ¤   {
bc2504 ¤   ¤   ¤   return 1;¤  /* First char different */
950fe4 ¤   ¤   }
20df67 ¤   ¤   ¤   magic = ((PGPByte *)pool->pktbuf)[0]; /* First char magic */
170fe4 ¤   ¤   }
5934a3 ¤   ¤   return memcmp(p+1, pool->pktbuf+1, (size_t)len-1) ? 1 : magic;
da9371 ¤   }
29af5a
1a4f3f ¤   /* Usual case - external file */
c041d5 ¤   f = file->f;
69d420 ¤   pgpAssert(f);
13af5a
33e708 ¤   i = pgpFileSeek(f, pos->fpos, SEEK_SET);
7a535c ¤   if (i != 0) {
4b4c0e ¤   ¤   ringErr(file, pos->fpos, kPGPError_FileOpFailed);
bd1a9d ¤   ¤   return kPGPError_FileOpFailed;
3e9371 ¤   }
--bb7d 00056f6272440100201 Page 25 of pgpRngRead.c
0d3147 ¤   i = pktByteGet(f, &len, &len1, (PGPSize *)NULL);
2e7a6f ¤   if (i < 0) {
c89ea4 ¤   ¤   ringErr(file, pos->fpos, (PGPError)i);
2aa423 ¤   ¤   return i;
4b9371 ¤   }
6d26c7 ¤   if (PKTBYTE_TYPE(i) != pkttype) {
d18c0e ¤   ¤   ringErr(file, pos->fpos, kPGPError_BadPacket);
b8015b ¤   ¤   return kPGPError_BadPacket;
f19371 ¤   }
a31153 ¤   if (len > max)
0acdd4 ¤   ¤   len = max;
cf10bc ¤   if (max > pool->pktbuflen)
1f7d62 ¤   ¤   max = pool->pktbuflen;
581481 ¤   if (len != max)
00aa2c ¤   ¤   return 1;¤  /* Different */
a14404 ¤   if (!len)
f5bbde ¤   ¤   return 0;
e83167 ¤   /* Check first character specially */
720c8c ¤   if (pgpFileRead(&c, 1, f) != 1) ·{
24c375 ¤   ¤   i = pgpFileError(f) ? kPGPError_ReadFailed : kPGPError_EOF;
ad9ea4 ¤   ¤   ringErr(file, pos->fpos, (PGPError)i);
8ca423 ¤   ¤   return i;
5a9371 ¤   }
88853d ¤   i = c & 255;
ae2d0f ¤   magic = 0;¤ /* First char the same */
21f3a2 ¤   if (i != ((PGPByte *)pool->pktbuf)[0]) {
b5976b ¤   ¤   if ((i ^ ((PGPByte *)pool->pktbuf)[0]) != 1
ef2ca5 ¤   ¤   ¤   || (i & ((PGPByte *)pool->pktbuf)[0]) != 2)
43db98 ¤   ¤   ¤   return 1;
66d811 ¤   ¤   magic = ((PGPByte *)pool->pktbuf)[0]; /* First char magic */
b49371 ¤   }
763a0e ¤   i = fileUnequalBuf(f, pool->pktbuf+1, len-1, len1-1);
594fd6 ¤   if (i < 0)
7c9ea4 ¤   ¤   ringErr(file, pos->fpos, (PGPError)i);
1caf5a
0db930 ¤   return i ? i : magic;
9befe6 }
0baf5a
fe38e5 /*
5ee5f6 ·* Return 1 if the key in the ring's pktbuf differs from the
cc2c03 ·* key in its other homes, 0 if it is the same, and <0 if there
32f9e8 ·* is some sort of error.
aca35f ·* Does *not* alter file1's read position unless there is an error.
bc83e5 ·* (I.e. if it needs to seek file1, it saves and restores the file
61d03b ·* position. ·It doesn't bother for other files. ·Use the MEMRING file
a188b4 ·* if you don't need this feature.)
3d775e ·*
f1ca70 ·* SPECIAL CASE:
2a9192 ·* Returns >1 if the version byte bug was detected. ·This is the case
c9b83d ·* wherein version 2.6 would write out an edited secret key with a
7fb684 ·* version byte of 3 even if it was originally 2.
87b60e ·* This function returns the current pktbuf's version byte (2 or 3)
3efb22 ·* if the keys are identical except that the version byte differs
9749ce ·* from something read previously.
d6d420 ·* The caller must decide what sort of trouble to log.
64495d ·*/
cd4d2f int
eec0e4 keysdiffer(RingFile *file1, union RingObject const *key, int pktbyte)
4dbb36 {
fc9cdd ¤   RingPool *pool = file1->set.pool;
e317b1 ¤   RingFile *file2;
a1c35f ¤   size_t savelen, publen;
ce39f6 ¤   PGPVirtMask secmask;
b27a3c ¤   PGPUInt32 max;
f351dd ¤   int i, type;
655b7d ¤   long retpos=0;
ecaf5a
76673b ¤   pgpVirtMaskInit (pool, &secmask);
e5af5a
6a94a2 ¤   pgpAssert(OBJISKEY(key));
6b394b ¤   pgpAssert(file1->f ||
567f1b ¤   ¤   ¤   ··pgpVirtMaskIsEqual(&file1->set.mask, &pool->memringmask));
--6fa8 000f8ea34cf40100201 Page 26 of pgpRngRead.c
e0af5a
1aaf5a
6dd8af ¤   /*
78f7b0 ¤   ·* If this is a secret key, find the prefix which is a public key,
ca4280 ¤   ·* and limit it to that if reasonable.
c5a4e3 ¤   ·*/
7e6eac ¤   savelen = pool->pktbuflen;
46a22a ¤   if ((PKTBYTE_TYPE(pktbyte) == PKTBYTE_SECKEY ||
c481df ¤   ¤   ·PKTBYTE_TYPE(pktbyte) == PKTBYTE_SECSUBKEY)
1038d0 ¤   ····&& !(key->g.flags & KEYF_ERROR))
d2c7a1 ¤   {
0d14d2 ¤   ¤   publen = ringKeyParsePublicPrefix((PGPByte const *)pool->pktbuf,
910613 ¤   ¤   ··································pool->pktbuflen);
a30972 ¤   ¤   if (publen)
3087a1 ¤   ¤   ¤   pool->pktbuflen = publen;
7b9371 ¤   }
d6af5a
f5a6b0 ¤   /* Find a file containing the key - try for public first */
f04457 ¤   ringKeySecMask(pool, key, &secmask);
c2af5a
884b97 ¤   file2 = ringBestFile(pool, key, &secmask);
5c57a4 ¤   if (file2) {
8a7b7c ¤   ¤   max = (PGPUInt32)-1;
0e2204 ¤   ¤   type = OBJISTOPKEY(key) ? PKTBYTE_PUBKEY : PKTBYTE_PUBSUBKEY;
62f037 ¤   } else {
63f8d2 ¤   ¤   file2 = ringBestFile(pool, key, 0);
61e380 ¤   ¤   pgpAssert(file2);
f2b29d ¤   ¤   max = (PGPUInt32)pool->pktbuflen;
cbd8ae ¤   ¤   type = OBJISTOPKEY(key) ? PKTBYTE_SECKEY : PKTBYTE_SECSUBKEY;
2b9371 ¤   }
60af5a
efc848 ¤   if (file2 == file1 && file1->f && (retpos=pgpFileTell(file1->f)) < 0) {
e57df5 ¤   ¤   ringErr(file1, pgpFileTell(file1->f), kPGPError_FileOpFailed);
5c90c4 ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
cc1a9d ¤   ¤   return kPGPError_FileOpFailed;
be9371 ¤   }
ea1b52 ¤   ¤
0d9261 ¤   /* Note that we don't need to seek file2 here, ringPacketDiffers does */
d1f6df ¤   i = ringPacketDiffers(file2, key, type, max);
28af5a
f6d8af ¤   /*
846dc7 ¤   ·* If we compared against a secret key, and encountered the version
9b27ea ¤   ·* bug, and the version bug has already been noted, ignore the
5378c5 ¤   ·* difference.
fba4e3 ¤   ·*/
b8ee60 ¤   if (i == PGPVERSION_2
8031f0 ············&& type == PKTBYTE_SECKEY
f49679 ¤   ····&& key->g.flags & SECF_VERSION_BUG)
029ed6 ¤   ¤   i = 0;
41af5a
bee398 ¤   if (file2 == file1 && file1->f &&
c2e56c ¤   ¤   ¤   pgpFileSeek(file1->f, retpos, SEEK_SET) != 0) {
747df5 ¤   ¤   ringErr(file1, pgpFileTell(file1->f), kPGPError_FileOpFailed);
7990c4 ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
bb1a9d ¤   ¤   return kPGPError_FileOpFailed;
719371 ¤   }
5167c5 ¤
d996c5 ¤   /* Restore pktbuflen, may have been changed above */
2636ea ¤   pool->pktbuflen = savelen;
91af5a
3c967c ¤   pgpVirtMaskCleanup (pool, &secmask);
282196 ¤   return i;
64efe6 }
27af5a
3c38e5 /*
ba938e ·* Return 1 if the secret in the ring's pktbuf differs from the
802c03 ·* key in its other homes, 0 if it is the same, and <0 if there
61f9e8 ·* is some sort of error.
c9a35f ·* Does *not* alter file1's read position unless there is an error.
63775e ·*
bfca70 ·* SPECIAL CASE:
f89192 ·* Returns >1 if the version byte bug was detected. ·This is the case
--1fb2 000fc1c3b0e40100201 Page 27 of pgpRngRead.c
c4b83d ·* wherein version 2.6 would write out an edited secret key with a
d0b684 ·* version byte of 3 even if it was originally 2.
aab60e ·* This function returns the current pktbuf's version byte (2 or 3)
7bfb22 ·* if the keys are identical except that the version byte differs
9c49ce ·* from something read previously.
37d420 ·* The caller must decide what sort of trouble to log.
15495d ·*/
9c38e5 /*
763243 ·* Return 1 if the signature in the ring's pktbuf differs from the
3e1430 ·* sig in its various homes, 0 if it is the same, and <0 if there
2cf9e8 ·* is some sort of error.
46a35f ·* Does *not* alter file1's read position unless there is an error.
0783e5 ·* (I.e. if it needs to seek file1, it saves and restores the file
f9d03b ·* position. ·It doesn't bother for other files. ·Use the MEMRING file
9488b4 ·* if you don't need this feature.)
fe495d ·*/
31beb7 static int
f227e2 secsdiffer(RingFile *file1, union RingObject const *sec)
ddbb36 {
789cdd ¤   RingPool *pool = file1->set.pool;
cd17b1 ¤   RingFile *file2;
e85b7d ¤   long retpos=0;
df4fc6 ¤   PGPByte pktbyte;
714ba4 ¤   int i;
6daf5a
ffd124 ¤   pgpAssert(OBJISSEC(sec));
0baf5a
d300a7 ¤   /* Find a matching signature */
caac74 ¤   file2 = ringBestFile(pool, sec, 0);
5b20f0 ¤   pgpAssert (file2);
328574 ¤   pgpAssert (file2->f ||
1a12d7 ¤   ¤   ¤   ···pgpVirtMaskIsEqual (&file2->set.mask, &pool->memringmask));
58c848 ¤   if (file2 == file1 && file1->f && (retpos=pgpFileTell(file1->f)) < 0) {
257df5 ¤   ¤   ringErr(file1, pgpFileTell(file1->f), kPGPError_FileOpFailed);
e41a9d ¤   ¤   return kPGPError_FileOpFailed;
a49371 ¤   }
a9af5a
6729ec ¤   pktbyte = OBJISTOPKEY(sec->g.up) ? PKTBYTE_SECKEY :
8633ec ¤   ··········PKTBYTE_SECSUBKEY;
23af5a
369261 ¤   /* Note that we don't need to seek file2 here, ringPacketDiffers does */
05094c ¤   i = ringPacketDiffers(file2, sec, pktbyte, (PGPUInt32)-1);
ec4fd6 ¤   if (i < 0)
9fa423 ¤   ¤   return i;
c6af5a
9fe398 ¤   if (file2 == file1 && file1->f &&
fae56c ¤   ¤   ¤   pgpFileSeek(file1->f, retpos, SEEK_SET) != 0) {
c5cbd2 ¤   ¤   ringErr(file1, sec->g.pos.fpos, kPGPError_FileOpFailed);
6d1a9d ¤   ¤   return kPGPError_FileOpFailed;
559371 ¤   }
992196 ¤   return i;
acefe6 }
ecaf5a
1a984a static union RingObject *
68c83e ringFindSec(RingFile *file, union RingObject *parent)
8cbb36 {
cdc975 ¤   RingPool *pool = file->set.pool;
0b32ff ¤   union RingObject *sec, **secp;
3b4ba4 ¤   int i;
f1af5a
ada8ed ¤   /* Properties of the secret */
d343a0 ¤   PGPUInt32 hash;
ccaf5a
d66877 ¤   hash = ringHashBuf((PGPByte const *)pool->pktbuf, pool->pktbuflen);
2b67c5 ¤
b58322 ¤   /* Search for matching sigs */
edc394 ¤   for (secp=&parent->g.down; (sec=*secp) != NULL; secp=&sec->g.next) {
285864 ¤   ¤   if (OBJISSEC(sec)
2df471 ¤   ¤   ····&& sec->c.hash == hash
c04d8d ¤   ¤   ····&& (i = secsdiffer(file, sec)) <= 0)
44958c ¤   ¤   ¤   return i<0 ? NULL : sec;
fc9371 ¤   }
--ec4b 000a5b00d9140100201 Page 28 of pgpRngRead.c
e0af5a
11255e ¤   /* Not found - allocate a new secret */
66d404 ¤   sec = ringNewSec(pool);
438631 ¤   if (sec) {
271b17 ¤   ¤   /*
40ba43 ¤   ¤   ·* Make secret object the first thing. ·This is assumed by
54a073 ¤   ¤   ·* ringFindSig which tries to keep sigs together just past
843604 ¤   ¤   ·* the sec obj. ·Especially important with subkeys where it's
508edb ¤   ¤   ·* hard to tell which sigs go with which keys as we read.
859de3 ¤   ¤   ·*/
3dc8d8 ¤   ¤   sec->g.next = parent->g.down;
5cad04 ¤   ¤   parent->g.down = sec;
dd5880 ¤   ¤   sec->g.up = parent;
00703d ¤   ¤   sec->c.hash = hash;
0d9371 ¤   }
da9ab9 ¤   return sec;
e2efe6 }
15af5a
1938e5 /*
03d142 ·* Return 1 if the name in the ring's pktbuf differs from the
19402e ·* name in its various homes, 0 if it is the same, and <0 if there
38f9e8 ·* is some sort of error.
2ca35f ·* Does *not* alter file1's read position unless there is an error.
5f83e5 ·* (I.e. if it needs to seek file1, it saves and restores the file
c5d03b ·* position. ·It doesn't bother for other files. ·Use the MEMRING file
2e88b4 ·* if you don't need this feature.)
c3495d ·*/
c94d2f int
354e1d namesdiffer(RingFile *file1, union RingObject const *name,
db6dd0 ¤   ¤   ¤   PGPBoolean fAttribute)
46bb36 {
2c9cdd ¤   RingPool *pool = file1->set.pool;
6317b1 ¤   RingFile *file2;
e15b7d ¤   long retpos=0;
3b4ba4 ¤   int i;
c6af5a
ba5100 ¤   /* Find a matching name */
991463 ¤   file2 = ringBestFile(pool, name, 0);
1f20f0 ¤   pgpAssert (file2);
5d8574 ¤   pgpAssert (file2->f ||
6812d7 ¤   ¤   ¤   ···pgpVirtMaskIsEqual (&file2->set.mask, &pool->memringmask));
56c848 ¤   if (file2 == file1 && file1->f && (retpos=pgpFileTell(file1->f)) < 0) {
977df5 ¤   ¤   ringErr(file1, pgpFileTell(file1->f), kPGPError_FileOpFailed);
aa1a9d ¤   ¤   return kPGPError_FileOpFailed;
729371 ¤   }
1caf5a
039261 ¤   /* Note that we don't need to seek file2 here, ringPacketDiffers does */
84da56 ¤   i = ringPacketDiffers(file2, name,
a1b550 ¤   ¤   ¤   (fAttribute?PKTBYTE_ATTRIBUTE:PKTBYTE_NAME), (PGPUInt32)-1);
64af5a
e7e398 ¤   if (file2 == file1 && file1->f &&
6de56c ¤   ¤   ¤   pgpFileSeek(file1->f, retpos, SEEK_SET) != 0) {
39c6b6 ¤   ¤   ringErr(file1, name->g.pos.fpos, kPGPError_FileOpFailed);
b51a9d ¤   ¤   return kPGPError_FileOpFailed;
ac9371 ¤   }
4f2196 ¤   return i;
1befe6 }
b4af5a
5438e5 /*
2ff481 ·* Exported variant of namesdiffer. ·This has a similar function, but
8e27d0 ·* a very different interface - it does not assume that the name has been
a78c0c ·* fetched into the pktbuf.
b5154c ·* Returns 1 if the two names differ, 0 if the same, < 0 on error.
d5495d ·*/
874d2f int
bf726d ringNamesDiffer (RingSet const *set, union RingObject *name1,
57afa3 ¤   union RingObject *name2)
9dbb36 {
6cc782 ¤   char const *buf1, *buf2;¤   /* Pointers to the names */
4c9658 ¤   PGPSize len, tlen;
688368 ¤   PGPUInt32 hash1, hash2;¤¤   /* HAshes of the two names */
a567c5 ¤
--13ea 0001d7da8cf40100201 Page 29 of pgpRngRead.c
b9d6b1 ¤   pgpAssert (OBJISNAME(name1));
4fcb7d ¤   pgpAssert (OBJISNAME(name2));
8cf099 ¤   pgpAssert (pgpIsRingSetMember(set, name1));
e2ed55 ¤   pgpAssert (pgpIsRingSetMember(set, name2));
67af5a
571462 ¤   /* Quick test of lengths */
cdf0af ¤   len = name1->n.len;
a73c62 ¤   if (len != name2->n.len)
a1e102 ¤   ¤   return 1;
c6af5a
f07406 ¤   /* Trivial case: both names are in memory */
22bb6a ¤   if (NAMEISCACHED(&name1->n) && NAMEISCACHED(&name2->n))
a85812 ¤   ¤   return memcmp(name1->n.name.ptr, name2->n.name.ptr, len) != 0;
13af5a
b03e22 ¤   /* First, compare hashes to see what's what */
600cd0 ¤   hash1 = NAMEISCACHED(&name1->n)·
4dc0e3 ¤   ¤   ? ringHashBuf((const unsigned char *) name1->n.name.ptr, len)
c587b6 ¤   ¤   : name1->n.name.hash;
56a7fc ¤   hash2 = NAMEISCACHED(&name2->n)·
40a908 ¤   ¤   ? ringHashBuf((const unsigned char *) name2->n.name.ptr, len)
4b1d97 ¤   ¤   : name2->n.name.hash;
64e9c5 ¤   if (hash1 != hash2)
f2e102 ¤   ¤   return 1;
55d8af ¤   /*
5fdebb ¤   ·* At this point, we're 99% sure the names are the same, but
09e33c ¤   ·* we need to confirm...
4b6e8d ¤   ·* Load the first name. ·This may go into a cache, or the pktbuf.
75a4e3 ¤   ·*/
c87a84 ¤   buf1 = ringPoolGetName(ringSetPool(set), &name1->n, &tlen);
93cb0c ¤   if (!buf1)
9de1c3 ¤   ¤   return ringSetError(set)->error;
b4d215 ¤   pgpAssert(tlen == len);
ef1e89 ¤   /* If name2 is available without using the pktbuf, great. */
49411e ¤   if (NAMEISCACHED(&name2->n)) {
b48aeb ¤   ¤   buf2 = name2->n.name.ptr;
33011d ¤   ¤   return memcmp(buf1, buf2, len) != 0;
7e9371 ¤   }
11d8af ¤   /*
a87b56 ¤   ·* Otherwise, if name1 isn't in the pktbuf, we can fetch name2
f52e76 ¤   ·* without fear of clobbering it.
f6a4e3 ¤   ·*/
7b9719 ¤   if (NAMEISCACHED(&name1->n)) {
751bc9 ¤   ¤   pgpAssert(buf1 == name1->n.name.ptr);
7ab2b3 ¤   ¤   buf2 = ringPoolGetName(ringSetPool(set), &name2->n, &tlen);
ffc6cb ¤   ¤   if (!buf2)
4be77b ¤   ¤   ¤   return ringSetError(set)->error;
857f4b ¤   ¤   pgpAssert(tlen == len);
0f011d ¤   ¤   return memcmp(buf1, buf2, len) != 0;
f79371 ¤   }
9e1615 ¤   /* name1 is not cached, so it's in the pktbuf... */
60276e ¤   pgpAssert(buf1 == ringSetPool(set)->pktbuf);
84d8af ¤   /*
dea89d ¤   ·* Otherwise, compare name1 in pktbuf to name2 on disk.
7f25c8 ¤   ·* Use MEMRING as dummy entry for file1; it is only used to
4c450c ¤   ·* make sure that any seeks which move its position get undone,
c302b0 ¤   ·* and we don't care about that at this point.
caa4e3 ¤   ·*/
26d89c ¤   return namesdiffer(ringSetPool(set)->files[MEMRINGBIT], name2,
dec2f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean)NAMEISATTR(&name1->n));
73efe6 }
f467c5 ¤
deaf5a
fd38e5 /*
ff4b8d ·* Get a RingName on the given chain matching the one in the ring's
887639 ·* pktbuf. ·Returns 0 if it runs out of memory or can't read the file.
2e95a7 ·* (The ring's error is set to reflect this.)
25aec9 ·* It does *not* add the FilePos or set the mask bit.
35c9d0 ·* Does *not* alter the given file's read position unless there is an error.
39495d ·*/
28984a static union RingObject *
024ebf ringFindName(RingFile *file, union RingObject *parent, PGPBoolean fAttribute)
1dbb36 {
--8c45 00003bfb53140100201 Page 30 of pgpRngRead.c
b6c975 ¤   RingPool *pool = file->set.pool;
0231cb ¤   union RingObject *name, **np, **pname=NULL;
ae991e ¤   size_t const len = pool->pktbuflen;
dc43a0 ¤   PGPUInt32 hash;
8b4ba4 ¤   int i;
3707fb ¤   char *buf;¤ /* Used when trying to cache name */
d9af5a
c5b8f7 ¤   hash = ringHashBuf((PGPByte const *)pool->pktbuf, len);
c6af5a
e4d2cf ¤   pname = &parent->g.down;
cd82e9 ¤   for (np = &parent->g.down; (name=*np) != NULL; np = &name->g.next) {
956acc ¤   ¤   /* Position name after names, key-sigs, sec's */
f5bbe5 ¤   ¤   if (OBJISNAME(name) || OBJISSIG(name) || OBJISSEC(name))
72e23d ¤   ¤   ¤   pname = &name->g.next;
99ff30 ¤   ¤   /* If not a name or wrong length, no match */
0bad2d ¤   ¤   if (!OBJISNAME(name) || name->n.len != len
18ec66 ¤   ¤   ¤   || !NAMEISATTR(&name->n)!=!fAttribute)
0217f5 ¤   ¤   ¤   continue;
16af5a
14a718 ¤   ¤   /* If in memory, compare that */
2062b7 ¤   ¤   if (NAMEISCACHED(&name->n)) {
ce0f31 ¤   ¤   ¤   if (memcmp(name->n.name.ptr, pool->pktbuf, len) == 0)
c6dc1f ¤   ¤   ¤   ¤   return name;¤   /* Success */
7b45a6 ¤   ¤   } else {
1285c3 ¤   ¤   ¤   if (name->n.name.hash == hash
29d5a7 ¤   ¤   ¤   ····&& (i = namesdiffer(file, name, fAttribute)) <= 0)
d315fa ¤   ¤   ¤   ¤   return i<0 ? NULL : name;
5b0fe4 ¤   ¤   }
2d9371 ¤   }
47af5a
301c43 ¤   /* Failed to find a name - create one */
6752a6 ¤   name = ringNewName(pool);
59348f ¤   if (name) {
6ad492 ¤   ¤   name->g.next = *pname;
988714 ¤   ¤   *pname = name;
01acc3 ¤   ¤   name->g.up = parent;
d11cac ¤   ¤   name->n.len = len;
1b20be ¤   ¤   name->n.name.hash = hash;¤  /* May overwrite below */
b250bf ¤   ¤   /* Default new names to unknown trust */
5baca4 ¤   ¤   name->n.trust = kPGPNameTrust_Unknown;
8d530e ¤   ¤   if( fAttribute )
247772 ¤   ¤   ¤   NAMESETATTR(&name->n);
967dec #if PGPTRUSTMODEL>0
7c183a ¤   ¤   name->n.valid = name->n.validity = 0;
4769a8 ¤   ¤   name->n.confidence = PGP_NEWTRUST_UNDEFINED;
1a5b83 ¤   ¤   NAMESETNEWTRUST(&name->n);
497454 #endif
c7a8af #if 1
daed5c ¤   ¤   /* You might want to disable this for MSDOS */
1c4398 ¤   ¤   /* Don't "cache" in memring, it is for new creations */
6fc36f ¤   ¤   if (!pgpVirtMaskIsEqual(&file->set.mask, &pool->memringmask) &&
da75e3 ¤   ¤   ¤   ¤   ¤   len < NAMECACHETHRESHOLD) {
cbe04b ¤   ¤   ¤   buf = (char *)memPoolAlloc(&file->strings, len+1, 1);
ef1183 ¤   ¤   ¤   if (buf) {
925d60 ¤   ¤   ¤   ¤   pgpCopyMemory( pool->pktbuf, buf, len );
c75bee ¤   ¤   ¤   ¤   buf[len] = '\0'; /* null after names in memory */
81c7ff ¤   ¤   ¤   ¤   name->n.name.ptr = buf;
a67f3e ¤   ¤   ¤   ¤   NAMESETFILEMASK(&name->n, pgpVirtMaskLSBit(&file->set.mask));
517eee ¤   ¤   ¤   ¤   NAMESETCACHED(&name->n);
54a3a6 ¤   ¤   ¤   }
a90fe4 ¤   ¤   }
947454 #endif
899371 ¤   }
a94f35 ¤   return name;
77efe6 }
4aaf5a
0938e5 /*
0b3243 ·* Return 1 if the signature in the ring's pktbuf differs from the
171430 ·* sig in its various homes, 0 if it is the same, and <0 if there
85f9e8 ·* is some sort of error.
51a35f ·* Does *not* alter file1's read position unless there is an error.
03495d ·*/
--a7f0 000509d93b140100201 Page 31 of pgpRngRead.c
af4d2f int
17cf77 sigsdiffer(RingFile *file1, union RingObject const *sig)
99bb36 {
599cdd ¤   RingPool *pool = file1->set.pool;
0317b1 ¤   RingFile *file2;
085b7d ¤   long retpos=0;
dd4ba4 ¤   int i;
ffaf5a
3000a7 ¤   /* Find a matching signature */
caf860 ¤   file2 = ringBestFile(pool, sig, 0);
c620f0 ¤   pgpAssert (file2);
da8574 ¤   pgpAssert (file2->f ||
b412d7 ¤   ¤   ¤   ···pgpVirtMaskIsEqual (&file2->set.mask, &pool->memringmask));
30e398 ¤   if (file2 == file1 && file1->f &&
1a0e13 ¤   ¤   ¤   (retpos = pgpFileTell(file1->f)) < 0) {
3a7df5 ¤   ¤   ringErr(file1, pgpFileTell(file1->f), kPGPError_FileOpFailed);
d61a9d ¤   ¤   return kPGPError_FileOpFailed;
279371 ¤   }
f7af5a
7f9261 ¤   /* Note that we don't need to seek file2 here, ringPacketDiffers does */
98f8dc ¤   i = ringPacketDiffers(file2, sig, PKTBYTE_SIG, (PGPUInt32)-1);
a3af5a
b4e398 ¤   if (file2 == file1 && file1->f &&
57e56c ¤   ¤   ¤   pgpFileSeek(file1->f, retpos, SEEK_SET) != 0) {
494eb8 ¤   ¤   ringErr(file1, sig->g.pos.fpos, kPGPError_FileOpFailed);
261a9d ¤   ¤   return kPGPError_FileOpFailed;
8b9371 ¤   }
a32196 ¤   return i;
06efe6 }
22af5a
e5984a static union RingObject *
dfb825 ringFindSig(RingFile *file, union RingObject *parent)
e1bb36 {
e7c975 ¤   RingPool *pool = file->set.pool;
14b957 ¤   union RingObject *key;
5fe2e7 ¤   union RingObject *sig, **sigp, **fsigp;
bc4ba4 ¤   int i;
09af5a
ceb0ee ¤   /* Properties of the signature */
a617e6 ¤   int err;
d204e1 ¤   PGPByte pkalg, keyID[8];
f0e0c3 ¤   PGPUInt32 tstamp;
826b1d ¤   PGPUInt16 validity;
8fcdc1 ¤   PGPByte type;¤
bd7afc ¤   PGPByte hashalg;
995bd0 ¤   PGPByte version;
8f7d67 ¤   PGPBoolean exportable;
a4f8be ¤   PGPBoolean revocable;
1d16bd ¤   PGPBoolean hasRegExp;
263eb3 ¤   PGPBoolean isX509;
2b6325 ¤   PGPByte trustLevel;
4c8840 ¤   PGPByte trustValue;
411613 ¤   size_t extralen;
ceaf5a
48d1cf ¤   pkalg = 0;
91b921 ¤   err = ringSigParse((PGPByte const *)pool->pktbuf, pool->pktbuflen,
85254f ¤   ···················&pkalg, keyID, &tstamp, &validity, &type,
dcc370 ¤   ···················&hashalg, &extralen, &version, &exportable,
18cfd0 ¤   ¤   ¤   ¤   ¤   ···&revocable, &trustLevel, &trustValue, &hasRegExp,
6251b1 ¤   ¤   ¤   ¤   ¤   ···&isX509);
cdaf5a
b2edec ¤   /* Get key this signature is by */
3ca3bc ¤   key = ringPoolFindDummyKey(pool, file, NULL, pkalg, keyID, isX509);
397d48 ¤   if (!key)
427ed2 ¤   ¤   return NULL;
cbaf5a
6f8322 ¤   /* Search for matching sigs */
443602 ¤   fsigp = &parent->g.down;
56d797 ¤   for (sigp = fsigp; (sig=*sigp) != NULL; sigp = &sig->g.next) {
357ab2 ¤   ¤   if (OBJISSEC(sig) || OBJISSIG(sig))
e43acc ¤   ¤   ¤   fsigp = &sig->g.next; /* predecessor to new sig */
50f825 ¤   ¤   if (OBJISSIG(sig)
--4df1 000d0e0f85d40100201 Page 32 of pgpRngRead.c
04bda2 ¤   ¤   ····&& sig->s.by ······== key
790151 ¤   ¤   ····&& (sig->s.by->k.pkalg == pkalg || pkalg==1) /* ViaCrypt */
da4cc7 ¤   ¤   ····&& sig->s.tstamp¤   ¤   == tstamp
4f57b9 ¤   ¤   ····&& sig->s.type¤ ¤   ¤   == type
a60c79 ¤   ¤   ¤   && sig->s.version¤  ¤   == version
fbd545 ¤   ¤   ····&& sig->s.validity¤ ¤   == validity
907707 ¤   ¤   ····&& sig->s.hashalg¤  ¤   == hashalg
7c8367 ¤   ¤   ····&& sig->s.trustLevel¤   == trustLevel
509328 ¤   ¤   ····&& sig->s.trustValue¤   == trustValue
df13d4 ¤   ¤   ····&& !(sig->g.flags & SIGF_ERROR) == !err
66b8e9 ¤   ¤   ····&& !(sig->g.flags & SIGF_NONFIVE) == (extralen == 5)
44bbdc ¤   ¤   ¤   && !SIGISEXPORTABLE(&sig->s) == !exportable
ba2a01 ¤   ¤   ¤   && !SIGISREVOCABLE(&sig->s) == !revocable
0dda43 ¤   ¤   ¤   && !SIGUSESREGEXP(&sig->s) == !hasRegExp
5c1eb2 ¤   ¤   ¤   && !SIGISX509(&sig->s) == !isX509
4f3e02 ¤   ¤   ····&& (i = sigsdiffer(file, sig)) <= 0)
675b34 ¤   ¤   {
0f61d9 ¤   ¤   ¤   return i<0 ? NULL : sig;
810fe4 ¤   ¤   }
d69371 ¤   }
aaaf5a
1204dd ¤   /* Not found - allocate a new sig */
3dde08 ¤   sig = ringNewSig(pool);
149ad5 ¤   if (sig) {
9cbf0a ¤   ¤   /* Add new sig before any user ID's */
e9a250 ¤   ¤   sig->g.next = *fsigp;
67ebaa ¤   ¤   *fsigp = sig;
097e90 ¤   ¤   sig->s.by = (union RingObject *)key;
6d4425 ¤   ¤   sig->g.up = parent;
22150b ¤   ¤   if (err)
f93fc2 ¤   ¤   ¤   sig->g.flags |= SIGF_ERROR;
f8b8d0 ¤   ¤   if (extralen != 5)
cd0900 ¤   ¤   ¤   sig->g.flags |= SIGF_NONFIVE;
d01680 ¤   ¤   sig->s.tstamp = tstamp;
6af321 ¤   ¤   sig->s.validity = validity;
e1fcf3 ¤   ¤   sig->s.type = type;
d1b980 ¤   ¤   sig->s.version = version;
765768 ¤   ¤   sig->s.hashalg = hashalg;
eae490 ¤   ¤   sig->s.trust = 0;
e69fa5 ¤   ¤   sig->s.trustLevel = trustLevel;
0cee3a ¤   ¤   sig->s.trustValue = trustValue;
b9ab00 ¤   ¤   if (exportable)
370a3e ¤   ¤   ¤   SIGSETEXPORTABLE(&sig->s);
700e1d ¤   ¤   else
f038f2 ¤   ¤   ¤   SIGSETNONEXPORTABLE(&sig->s);
3d87dc ¤   ¤   if (revocable)
7ac4ef ¤   ¤   ¤   SIGSETREVOCABLE(&sig->s);
850e1d ¤   ¤   else
c593ec ¤   ¤   ¤   SIGSETNONREVOCABLE(&sig->s);
3a69df ¤   ¤   if (hasRegExp)
31b9b4 ¤   ¤   ¤   SIGSETUSESREGEXP(&sig->s);
730e1d ¤   ¤   else
881b7a ¤   ¤   ¤   SIGCLEARUSESREGEXP(&sig->s);
79d8bb ¤   ¤   if (isX509)
15668c ¤   ¤   ¤   SIGSETX509(&sig->s);
7e0e1d ¤   ¤   else
b682a4 ¤   ¤   ¤   SIGCLEARX509(&sig->s);
209371 ¤   }
846eec ¤   return sig;
e8efe6 }
66af5a
2038e5 /*
4d1a42 ·* Return 1 if the blob in the ring's pktbuf differs from the
4e4869 ·* blob in its various homes, 0 if it is the same, and <0 if there
01f9e8 ·* is some sort of error.
e7a35f ·* Does *not* alter file1's read position unless there is an error.
8e495d ·*/
1d4d2f int
6fbfde unkdiffer(RingFile *file1, union RingObject const *unk)
dcbb36 {
039cdd ¤   RingPool *pool = file1->set.pool;
d017b1 ¤   RingFile *file2;
--16c4 000d4a8ef4940100201 Page 33 of pgpRngRead.c
5f5b7d ¤   long retpos=0;
cf4ba4 ¤   int i;
e0af5a
bd5bbe ¤   /* Find a matching unk */
cc71eb ¤   file2 = ringBestFile(pool, unk, 0);
8820f0 ¤   pgpAssert (file2);
7e8574 ¤   pgpAssert (file2->f ||
2c12d7 ¤   ¤   ¤   ···pgpVirtMaskIsEqual (&file2->set.mask, &pool->memringmask));
67c848 ¤   if (file2 == file1 && file1->f && (retpos=pgpFileTell(file1->f)) < 0) {
d67df5 ¤   ¤   ringErr(file1, pgpFileTell(file1->f), kPGPError_FileOpFailed);
181a9d ¤   ¤   return kPGPError_FileOpFailed;
5a9371 ¤   }
6daf5a
179261 ¤   /* Note that we don't need to seek file2 here, ringPacketDiffers does */
d9292c ¤   i = ringPacketDiffers(file2, unk, PKTBYTE_TYPE(unk->u.pktbyte),
b159d2 ¤   ······················pool->pktbuflen+1);
74af5a
e0e398 ¤   if (file2 == file1 && file1->f &&
a8e56c ¤   ¤   ¤   pgpFileSeek(file1->f, retpos, SEEK_SET) != 0) {
3e104d ¤   ¤   ringErr(file1, unk->g.pos.fpos, kPGPError_FileOpFailed);
9f1a9d ¤   ¤   return kPGPError_FileOpFailed;
999371 ¤   }
ed2196 ¤   return i;
8cefe6 }
01af5a
a138e5 /*
5e0807 ·* Get a RingUnk on the given chain matching the one in the ring's
662427 ·* pktbuf with the given pktbyte. ·Returns 0 if it runs out of memory
0423bb ·* or can't read the file. ·(The ring's error is set to reflect this.)
16aec9 ·* It does *not* add the FilePos or set the mask bit.
64c9d0 ·* Does *not* alter the given file's read position unless there is an error.
cf495d ·*/
f8984a static union RingObject *
083dc1 ringFindUnk(RingFile *file, union RingObject *parent, PGPByte pktbyte)
c1bb36 {
89c975 ¤   RingPool *pool = file->set.pool;
fea477 ¤   union RingObject *unk, **unkp;
3643a0 ¤   PGPUInt32 hash;
e84ba4 ¤   int i;
c1af5a
686877 ¤   hash = ringHashBuf((PGPByte const *)pool->pktbuf, pool->pktbuflen);
c5af5a
0a1ccd ¤   for (unkp = &parent->g.down; (unk=*unkp) != NULL;
b2d22d ¤   ¤   ¤   unkp = &unk->g.next) {
0e1b17 ¤   ¤   /*
a8a9d3 ¤   ¤   ·* If the type, hash and pktbyte match, try to compare...
14bf68 ¤   ¤   ·* Note that the pktbyte *must* match or namesdiffer()
2c2a7e ¤   ¤   ·* will complain loudly.
7f9de3 ¤   ¤   ·*/
a0b8b4 ¤   ¤   if (OBJISUNK(unk)
e5ebac ¤   ¤   ····&& unk->u.hash ···== hash
bc1f1c ¤   ¤   ····&& unk->u.pktbyte == pktbyte
8c6d9c ¤   ¤   ····&& (i = unkdiffer(file, unk)) <= 0)
085b34 ¤   ¤   {
4ca8c3 ¤   ¤   ¤   return i<0 ? NULL : unk;
e10fe4 ¤   ¤   }
e29371 ¤   }
f3af5a
b71c43 ¤   /* Failed to find a name - create one */
820e8b ¤   unk = ringNewUnk(pool);
b6a9f9 ¤   if (unk) {
f8f89e ¤   ¤   *unkp = unk;
5473df ¤   ¤   unk->g.up = parent;
0fe9af ¤   ¤   unk->u.pktbyte = pktbyte;
2e416b ¤   ¤   unk->u.hash = hash;
f750bf ¤   ¤   /* Default new names to unknown trust */
e79371 ¤   }
aca7f6 ¤   return unk;
fcefe6 }
0daf5a
5b95e3 /* Return the list of trpuble associated with a RingFile. */
d4cc8f RingTrouble const *
--e105 000cfa2b38340100201 Page 34 of pgpRngRead.c
dbbe1b ringFileTrouble(RingFile const *file)
55bb36 {
4f1982 ¤   return file->trouble;
7eefe6 }
93af5a
8938e5 /*
950e41 ·* Functions for manipulating the Trouble list.
b6495d ·*/
d9af5a
48b2e2 /* Zero out a RingFile's Trouble list; it has been dealt with. */
dc314a void
58de9e ringFilePurgeTrouble(RingFile *file)
edbb36 {
ef80d1 ¤   memPoolEmpty(&file->troublepool);
fb69b5 ¤   file->trouble = NULL;
1db3ab ¤   file->troubletail = &file->trouble;
19efe6 }
a7af5a
8e38e5 /*
e86cc4 ·* Log some trouble with a RingFile.
9f495d ·*/
63beb7 static int
45fd56 ringFileLog(RingFile *file, union RingObject *obj, PGPUInt32 num,
947f55 ¤   ····PGPUInt32 fpos, int type)
c0bb36 {
b2bfb7 ¤   RingTrouble *t;
a1af5a
ffcce8 ¤   t = (RingTrouble *)memPoolNew(&file->troublepool,
3e1925 ¤   ¤   ¤   RingTrouble);
1b2ebb ¤   if (!t)
f54030 ¤   ¤   return kPGPError_OutOfMemory;
7aaf5a
1c3e8c ¤   t->next = NULL;
abb695 ¤   t->obj = obj;
e90f80 ¤   t->num = num;
ae1743 ¤   t->fpos = fpos;
67a76f ¤   t->type = type;
47af5a
aac0ad ¤   *file->troubletail = t;
83c24b ¤   file->troubletail = &t->next;
813e6b ¤   return 0;
5fefe6 }
90af5a
c638e5 /*
88079d ·* @@@ This needs fixing - we should complain about a key without
84d7a5 ·* names in *this* file, even if it has names in others.
39495d ·*/
583e99 static union RingObject const *
460f1f ringKeyHasName(union RingObject const *obj)
c5bb36 {
719213 ¤   for (obj = obj->g.down; obj; obj = obj->g.next)
1cba15 ¤   ¤   if (OBJISNAME(obj))
03cdcb ¤   ¤   ¤   break;
4092f6 ¤   return obj;
1befe6 }
3daf5a
c8af5a
bcaf5a
d638e5 /*
baf736 ·* Keep only one name attribute object with the specified type.
4e6fef ·* Keep the one with the newest self sig.
ec495d ·*/
02beb7 static int
1eccad ringAttributeKeepNewest(RingObject *key, RingFile *file, PGPUInt32 atype)
38bb36 {
65a8af #if 1
44af3e /* This function does not really accomplish what we were hoping to
520494 ·* achieve. ·It does prevent imports from bringing in more than one
2507bb ·* photo id per key. ·But it does not deal with the problem that the
e495dc ·* base key ring may have a different photo id than the one being
7dd4d9 ·* imported. ·In that case we may need to go back and remove the photo
cf4193 ·* id which is part of the base key ring. ·That is difficult to do
--c349 0001302d8ab40100201 Page 35 of pgpRngRead.c
f90cd3 ·* safely from here. ·For now we will disable this functionality.
3d495d ·*/
957151 ¤   (void) key;
cc3fbc ¤   (void) file;
106395 ¤   (void) atype;
7b151e ¤   return kPGPError_NoErr;
8cdb21 #else
1aee37 ¤   RingObject *name, *sig, *nextname;
fcefbf ¤   PGPUInt32 attrtype;
f513d1 ¤   PGPUInt32 attrtime;
720162 ¤   RingObject *prevattr = NULL;
6bab97 ¤   PGPUInt32 prevattrtime = 0;
d7dd48 ¤   PGPUInt32 sigtime;
894408 ¤   RingObject *newestsig = NULL;
2f06cf ¤   PGPUInt32 newestsigtime;
42f6dc ¤   RingSet *set = &file->set;
71227f ¤   long pos = 0;
05af5a
c957f4 ¤   for (name=key->g.down; name; name=nextname) {
dd4be0 ¤   ¤   /* May delete name so must do iteration here */
4e9d61 ¤   ¤   nextname = name->g.next;
a5decf ¤   ¤   /* Skip if not an attribute name */
ae7302 ¤   ¤   if (!OBJISNAME(name))
7417f5 ¤   ¤   ¤   continue;
8632c0 ¤   ¤   if (!pgpIsRingSetMember(set, name))
8f17f5 ¤   ¤   ¤   continue;
f94f1f ¤   ¤   if (!NAMEISATTR(&name->n))
9617f5 ¤   ¤   ¤   continue;
d5a69b ¤   ¤   /* Skip if not the right kind of attribute */
4a4f19 ¤   ¤   /* This call may change the file pointer! */
e3406c ¤   ¤   pos = pgpFileTell(file->f);
fe039d ¤   ¤   if (pos == -1)
dd14d1 ¤   ¤   ¤   return kPGPError_FileOpFailed;
ac62d8 ¤   ¤   attrtype = 0;
1461bc ¤   ¤   ringNameAttributeSubpacket (name, set, 0, &attrtype, NULL, NULL);
018b56 ¤   ¤   if (pgpFileSeek(file->f, pos, SEEK_SET) != 0)
8514d1 ¤   ¤   ¤   return kPGPError_FileOpFailed;
a6edda ¤   ¤   if (attrtype != atype)
ee17f5 ¤   ¤   ¤   continue;
08e8cd ¤   ¤   /* Here, have the desired attribute. ·Find date of newest self sig. */
767ce9 ¤   ¤   attrtime = 0;
d3cc73 ¤   ¤   newestsigtime = 0;
ad713c ¤   ¤   newestsig = NULL;
0b1ad7 ¤   ¤   for (sig=name->g.down; sig; sig=sig->g.next) {
c7acbf ¤   ¤   ¤   if (!OBJISSIG(sig))
e3d040 ¤   ¤   ¤   ¤   continue;
eb8b3c ¤   ¤   ¤   if (!pgpIsRingSetMember(set, sig))
e7d040 ¤   ¤   ¤   ¤   continue;
e3c3b9 ¤   ¤   ¤   if (sig->s.by != key)
93d040 ¤   ¤   ¤   ¤   continue;
b419b8 ¤   ¤   ¤   /* Have self sig on name */
dba2b9 ¤   ¤   ¤   sigtime = ringSigTimestamp(set, sig);
dd7495 ¤   ¤   ¤   if (sigtime > newestsigtime) {
48e06b ¤   ¤   ¤   ¤   newestsig = sig;
47b447 ¤   ¤   ¤   ¤   newestsigtime = sigtime;
6fa3a6 ¤   ¤   ¤   }
a60fe4 ¤   ¤   }
931922 ¤   ¤   if (IsntNull(newestsig) &&
f961dc ¤   ¤   ¤   ····(newestsig->s.type & 0xF0) == PGP_SIGTYPE_KEY_GENERIC) {
2809ad ¤   ¤   ¤   attrtime = newestsigtime;
580fe4 ¤   ¤   }
d73e8a ¤   ¤   if (prevattr) {
6204ac ¤   ¤   ¤   if (prevattrtime < attrtime) {
e49526 ¤   ¤   ¤   ¤   /* Previous attribute is superceded by this one */
7146ed ¤   ¤   ¤   ¤   ringRemFileObjChildren (prevattr, file);
5b6971 ¤   ¤   ¤   ¤   prevattr = name;
fd75f4 ¤   ¤   ¤   ¤   prevattrtime = attrtime;
a7042d ¤   ¤   ¤   } else {
bf33df ¤   ¤   ¤   ¤   /* This attribute is superceded by previously seen one */
027b8c ¤   ¤   ¤   ¤   ringRemFileObjChildren (name, file);
2da3a6 ¤   ¤   ¤   }
1345a6 ¤   ¤   } else {
--f295 0002e069bbb40100201 Page 36 of pgpRngRead.c
a4d227 ¤   ¤   ¤   prevattr = name;
577019 ¤   ¤   ¤   prevattrtime = attrtime;
f30fe4 ¤   ¤   }
129371 ¤   }
e23e6b ¤   return 0;
5c7454 #endif
15efe6 }
0baf5a
1caf5a
cf38e5 /*
b86460 ·* Return true if sig is nonimportable. ·We normally treat nonexportable
21b598 ·* sigs as nonimportable, but there may be some exceptions.
b9495d ·*/
02beb7 static int
3fc5fc ringSigNonimportable(RingObject *sig, RingFile *file, RingSet *set)
d1bb36 {
1b4cc9 ¤   PGPByte *p;
65875f ¤   PGPSize len;
db4615 ¤   PGPUInt32 i = 0;
2d227f ¤   long pos = 0;
a7af5a
de36e6 ¤   pgpAssert (pgpIsRingSetMember (set, sig));
897d94 ¤   pgpAssert (OBJISSIG(sig));
57af5a
0bb85e ¤   if (SIGISEXPORTABLE(&sig->s))
d8bbde ¤   ¤   return 0;
ddaf5a
6f1f0e ¤   /* Import sig if it makes us a revoker for this key */
1ea273 ¤   /* (Preserve file position) */
b0cb90 ¤   pos = pgpFileTell(file->f);
483874 ¤   if (pos == -1)
3b1a9d ¤   ¤   return kPGPError_FileOpFailed;
3c9728 ¤   p = (PGPByte *)ringFetchObject(set, sig, &len);
b32557 ¤   if (pgpFileSeek(file->f, pos, SEEK_SET) != 0)
b61a9d ¤   ¤   return kPGPError_FileOpFailed;
1eaf5a
f5d3a5 ¤   while (p) {
250d10 ¤   ¤   RingObject *rkey;
a27853 ¤   ¤   RingSet *allkeys;
2ceff8 ¤   ¤   PGPByte *subp;
c9af5a
d88357 ¤   ¤   /* Look for ith revocation subpacket */
906dde ¤   ¤   subp = (PGPByte *)ringSigFindSubpacket (p,
6c36dc ¤   ¤   ¤   ¤   ¤   ¤   ¤   SIGSUB_KEY_REVOCATION_KEY, i++, NULL, NULL,
5e727e ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, NULL);
52e745 ¤   ¤   if (IsNull(subp)) {
1e485d ¤   ¤   ¤   p = NULL;
a5cdcb ¤   ¤   ¤   break;
ab0fe4 ¤   ¤   }
3faf5a
9c4d7b ¤   ¤   /* Hack to create keyset of all keys in pool */
65fdc1 ¤   ¤   allkeys = ringSetCopy (set);
718f10 ¤   ¤   if (IsNull( allkeys ) ) {
f7e77b ¤   ¤   ¤   return ringSetError(set)->error;
8a0fe4 ¤   ¤   }
fa0481 ¤   ¤   ringAllocMask (set->pool, NULL, &allkeys->mask);
a0af5a
6b284d ¤   ¤   /* See if we have revoking key as a secret key */
0cf619 ¤   ¤   rkey = ringKeyById8 (allkeys, subp[1], subp+2+20-8);
4ae3e8 ¤   ¤   if (rkey && !pgpVirtMaskIsEmpty (&rkey->g.mask) &&
52491d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringKeyIsSec (allkeys, rkey)) {
43a0ef ¤   ¤   ¤   /* Break w/p non-null, we are revoker */
6ebbbd ¤   ¤   ¤   ringSetDestroy(allkeys);
7fcdcb ¤   ¤   ¤   break;
690fe4 ¤   ¤   }
0d86d5 ¤   ¤   ringSetDestroy(allkeys);
069371 ¤   }
d3af5a
cf7790 ¤   /* If p is non-null, we are revoker and can keep it */
85cce0 ¤   return IsNull(p);
b2efe6 }
2eaf5a
--7305 0003c3f2e2d40100201 Page 37 of pgpRngRead.c
bc38e5 /*
f68478 ·* Eliminate nonexportable signatures, except in special cases.
a03d5b ·* This function may harm the pktbuf so should not be called when it holds
e1388b ·* necessary data.
0d495d ·*/
fabeb7 static int
18d26e ringKeyCleanupNonexportables(RingObject *key, RingFile *file)
ebbb36 {
ea3941 ¤   RingObject *name, *nextname;
2ca2a2 ¤   RingObject *sig, *nextsig;
11f6dc ¤   RingSet *set = &file->set;
6daf5a
5757f4 ¤   for (name=key->g.down; name; name=nextname) {
789d61 ¤   ¤   nextname = name->g.next;
6032c0 ¤   ¤   if (!pgpIsRingSetMember(set, name))
1217f5 ¤   ¤   ¤   continue;
2a1d1a ¤   ¤   if (OBJISSIG(name)) {
8dfd34 ¤   ¤   ¤   if (ringSigNonimportable(name, file, set)) {
447b8c ¤   ¤   ¤   ¤   ringRemFileObjChildren (name, file);
d2a3a6 ¤   ¤   ¤   }
0445a6 ¤   ¤   } else {
583cb3 ¤   ¤   ¤   for (sig=name->g.down; sig; sig=nextsig) {
cdf9b8 ¤   ¤   ¤   ¤   nextsig = sig->g.next;
28538e ¤   ¤   ¤   ¤   if (!pgpIsRingSetMember(set, sig))
af5914 ¤   ¤   ¤   ¤   ¤   continue;
822743 ¤   ¤   ¤   ¤   if (!OBJISSIG(sig))
0e5914 ¤   ¤   ¤   ¤   ¤   continue;
a7988d ¤   ¤   ¤   ¤   if (ringSigNonimportable(sig, file, set)) {
74bb39 ¤   ¤   ¤   ¤   ¤   ringRemFileObjChildren (sig, file);
672613 ¤   ¤   ¤   ¤   }
4da3a6 ¤   ¤   ¤   }
cd0fe4 ¤   ¤   }
6f9371 ¤   }
033e6b ¤   return 0;
98efe6 }
8aaf5a
d8fc2b /* Called when we have finished reading in a key and all its children,
dae73a ·* to make sure that it is kosher - must have a name, etc.
da7c44 ·* We can also eliminate redundant or nonimportable objects here.
953d5b ·* This function may harm the pktbuf so should not be called when it holds
f6388b ·* necessary data.
3b495d ·*/
febeb7 static int
b00f57 ringKeyCleanup(RingFile *file, union RingObject *key, int trusted)
b9bb36 {
194ba4 ¤   int i;
53af5a
9f94a2 ¤   pgpAssert(OBJISKEY(key));
a4af5a
9566be ¤   /* Complain about a key with no Names */
144425 ¤   if (!ringKeyHasName(key)) {
252cc0 ¤   ¤   i = ringFileLog(file, key, 0,
887475 ¤   ¤   ¤   ¤   ¤   ¤   ringFilePos(key, file)->fpos,
edb5d7 ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleBareKey);
e43be4 ¤   ¤   if (i < 0) {
c19eb9 ¤   ¤   ¤   return i;
740fe4 ¤   ¤   }
f79371 ¤   }
bbaf5a
772f10 ¤   if (!trusted) {
008771 ¤   ¤   /* If importing a nonexportable signature, delete it */
6c4b9b ¤   ¤   i = ringKeyCleanupNonexportables (key, file);
ea9371 ¤   }
d7af5a
f61544 #define PHOTOATTRIBUTE 1
b32f10 ¤   if (!trusted) {
eb0fa6 ¤   ¤   /* Only allow one photo userid */
37a70d ¤   ¤   i = ringAttributeKeepNewest(key, file, PHOTOATTRIBUTE);
233be4 ¤   ¤   if (i < 0) {
219eb9 ¤   ¤   ¤   return i;
5a0fe4 ¤   ¤   }
3c9371 ¤   }
--4fae 0005e2af50940100201 Page 38 of pgpRngRead.c
e0af5a
347b3d ¤   /* @@@ Should we not care about this? */
6c336a ¤   /* If keys not in sorted order, dirty */
f9b177 #if 0
8c77a5 ¤   /* @@@ ringSortKeys orders keys by algorithm
e0a3ea ¤   ···so this test no longer works. */
2f4ea9 ¤   if (ringKeyIDcmp(key->k.keyID, keyID) > 0)
1330eb ¤   ¤   ringFileMarkDirty(file);
277454 #endif
17af5a
ae89ee ¤   return 0;¤  /* All OK */
5eefe6 }
05af5a
78af5a
1438e5 /*
000a2a ·* How to skip things. ·Various helper functions return either
4ece2c ·* negative fatal error codes or these codes indicating what to
1668e8 ·* do to recover from any warnings. ·These never exceed 15 bits,
ab3d6c ·* so "int" is the right type.
08495d ·*/
b2af5a
66b6e5 typedef int skip_t;
846f28 #define SKIP_TRUST 1
800776 #define SKIP_SIG 2
aca4b6 #define SKIP_NAME 4
b920d3 #define SKIP_SUBKEY 8
41c6a3 #define SKIP_KEY 16
c1af5a
598ab4 #define SKIP_SIGS (SKIP_TRUST | SKIP_SIG)
f582cf #define SKIP_TO_KEY (SKIP_SIGS | SKIP_NAME | SKIP_SUBKEY)
23af5a
e2f8c2 #define PB_PUBKEY(key) (OBJISTOPKEY(key) ? \
748f7a ¤   PKTBYTE_BUILD(PKTBYTE_PUBKEY, 0) : \
8dad36 ¤   PKTBYTE_BUILD(PKTBYTE_PUBSUBKEY, 0))
b15bb3 #define PB_SECKEY(key) (OBJISTOPKEY(key) ? \
2e847e ¤   PKTBYTE_BUILD(PKTBYTE_SECKEY, 0) : \
3ca632 ¤   PKTBYTE_BUILD(PKTBYTE_SECSUBKEY, 0))
a0aed3 #define PB_SIG PKTBYTE_BUILD(PKTBYTE_SIG, 0)
80af5a
3b38e5 /*
e3e474 ·* Add a new key to the Pool, with its *parent* at the given level
16ee2e ·* (0 means adding top-level key) in the RingIterator. ·Leave the
40c72b ·* RingIterator pointing to the newly created key. ·Return <0 on error,
dbd0df ·* 0 if the key was created, and a skip code > 0 if it was created with
cdaf7e ·* a warning of some sort.
bd495d ·*/
e2beb7 static int
af6375 ringAddKey(RingFile *file, RingIterator *iter, PGPUInt32 fpos,
f1dc23 ¤   int trusted, PGPByte pkttype)
96bb36 {
b3b499 ¤   union RingObject *key, *sec, *parent;
fc04e1 ¤   PGPByte pkalg, keyID[8];
113ab6 ¤   PGPUInt16 keybits;
0ae0c3 ¤   PGPUInt32 tstamp;
706b1d ¤   PGPUInt16 validity;
56e7f9 ¤   PGPByte v3;
3357be ¤   PGPVirtMask secmask, pubmask;
23c975 ¤   RingPool *pool = file->set.pool;
b347b8 ¤   int i, err, level;
2eaf5a
ad37f4 ¤   (void) trusted;
51af5a
2a673b ¤   pgpVirtMaskInit (pool, &secmask);
de6d79 ¤   pgpVirtMaskInit (pool, &pubmask);
5faf5a
f0d1cf ¤   pkalg = 0;
153840 ¤   err = ringKeyParse(file->set.pool->context,
f64b78 ¤   ¤   ¤   ¤   ¤   ···(PGPByte const *)file->set.pool->pktbuf,
788f93 ¤   ···················file->set.pool->pktbuflen, &pkalg,
56c348 ¤   ···················keyID, &keybits, &tstamp, &validity, &v3, 0);
6daf5a
5e039e ¤   if (pkttype == PKTBYTE_PUBSUBKEY) {
--6189 000c962794640100201 Page 39 of pgpRngRead.c
bbf311 ¤   ¤   /* Subkey */
35d198 ¤   ¤   if (!iter->level) {
39d58d ¤   ¤   ¤   i = ringFileLog(file, NULL, 0, fpos,
d7cdeb ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleUnexpectedSubKey);
d0c259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
76c81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
c3940e ¤   ¤   ¤   return i < 0 ? i : SKIP_SIGS;
c40fe4 ¤   ¤   }
695a1a ¤   ¤   parent = iter->stack[0];
4fb706 ¤   ¤   level = 1;
f5f037 ¤   } else {
76c389 ¤   ¤   parent = NULL;
2dedda ¤   ¤   level = 0;
839371 ¤   }
79af5a
80eb65 ¤   /* Find the matching key structure */
af651f ¤   key = ringPoolFindDummyKey(file->set.pool, file, parent, pkalg, keyID,
b07e76 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···FALSE);
7cebb3 ¤   if (!key) {
9d90c4 ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
739a86 ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
38ad8f ¤   ¤   return ringFileError(file)->error;
579371 ¤   }
45af5a
c1dfab ¤   /* See if it's a new key or the same key */
07e545 ¤   if (pgpVirtMaskIsEmpty (&key->g.mask)) {
13ed86 ¤   ¤   /* Newly created dummy key; fill in info */
425826 ¤   ¤   if (pkttype == PKTBYTE_PUBSUBKEY ·&& ·OBJISTOPKEY(key)) {
ae7aad ¤   ¤   ¤   /*
3cda55 ¤   ¤   ¤   ·* Here on a former dummy top-level key which
eddfec ¤   ¤   ¤   ·* has turned out to be a subkey. ·Dummy key
54a50b ¤   ¤   ¤   ·* would have been created if we saw a sig by
502fa1 ¤   ¤   ¤   ·* it. ·Change key to a subkey.
c78753 ¤   ¤   ¤   ·*/
91d58d ¤   ¤   ¤   i = ringFileLog(file, NULL, 0, fpos,
5e30b5 ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleSigSubKey);
298a35 ¤   ¤   ¤   if (i < 0) {
f19142 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
6a9b00 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
c6590c ¤   ¤   ¤   ¤   return i;
62a3a6 ¤   ¤   ¤   }
b520e2 ¤   ¤   ¤   ringPoolUnlinkKey(file->set.pool, key);
05475c ¤   ¤   ¤   key->k.flags |= RINGOBJF_SUBKEY;
2a0c0d ¤   ¤   ¤   ringPoolLinkKey(file->set.pool, parent, key,
f2a6e9 ¤   ¤   ¤   ¤   ¤   pkalg, keyID);
720fe4 ¤   ¤   }
21af5a
26cb9c ¤   ¤   key->k.pkalg = pkalg;¤  /* ViaCrypt */
6397a2 ¤   ¤   key->k.tstamp = tstamp;
bf1334 ¤   ¤   key->k.validity = validity;
21ce13 ¤   ¤   key->k.keybits = keybits;
8197b3 ¤   ¤   key->k.trust = 0;
9d3c4f ¤   ¤   if (v3)
4f6d73 ¤   ¤   ¤   KEYSETV3(&key->k);
cf150b ¤   ¤   if (err)
cdc3a1 ¤   ¤   ¤   key->g.flags |= KEYF_ERROR;
5aaf5a
4d10f0 ¤   } else if (keybits ····!= key->k.keybits
26b872 ¤   ¤   ···|| pkalg ···!= key->k.pkalg¤ ¤   /* ViaCrypt */
148508 ¤   ¤   ···|| tstamp ··!= key->k.tstamp
3a1e71 /*¤ ¤   ···|| validity != key->k.validity¤  Validity may be in sig */
bb7e77 ¤   ¤   ···|| parent ··!= (OBJISTOP(key) ? NULL : key->g.up)
f92525 ¤   ¤   ···|| v3¤   ···!= !!KEYISV3(&key->k)
601677 ¤   ¤   ···|| !(key->g.flags & KEYF_ERROR) != !err)
dcc7a1 ¤   {
5d71d6 ¤   ¤   i = ringFileLog(file, key, 0, fpos,
02c78a ¤   ¤   ················kPGPError_TroubleDuplicateKeyID);
1a90c4 ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
539a86 ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
83ec40 ¤   ¤   return i < 0 ? i : SKIP_TO_KEY;
83af5a
c9b8dd ¤   } else if ((i=keysdiffer(file,key,PB_PUBKEY(key))) != 0) {
--fb92 0004feb88ce40100201 Page 40 of pgpRngRead.c
fe3be4 ¤   ¤   if (i < 0) {
edc259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
7ec81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
6d9eb9 ¤   ¤   ¤   return i;
270fe4 ¤   ¤   }
b49bf2 ¤   ¤   if ((OBJISTOPKEY(key) && pkttype==PKTBYTE_PUBSUBKEY) ||
1f7989 ¤   ¤   ····(OBJISSUBKEY(key) && pkttype==PKTBYTE_PUBKEY)) {
056986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
f2cc4a ¤   ¤   ¤   ¤   kPGPError_TroubleKeySubKey);
3cc259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
bcc81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
e303df ¤   ¤   ¤   return (i < 0) ? i : SKIP_TO_KEY;
e80fe4 ¤   ¤   }
eafc2f /* KLUDGE: version byte bug */
731b17 ¤   ¤   /*
a91596 ¤   ¤   ·* A key with a version byte of 2 only overrides previous
fe5b1c ¤   ¤   ·* keys with a byte of 3 if they are all untrusted
760925 ¤   ¤   ·* secret keys.
c74689 ¤   ¤   ·* A key with a version byte
d39105 ¤   ¤   ·* of 3 is only overridden if it's secret and previous
02a18a ¤   ¤   ·* keys include a secret key or a trusted public key.
c75fbf ¤   ¤   ·* We will relax the previous rules to allow public keys with
e3cb68 ¤   ¤   ·* version 2 to override even when not from a trusted keyring.
af8f15 ¤   ¤   ·* This happens when we import secret and public keyfiles as
5318ba ¤   ¤   ·* when we move our keyring. ·Normally this should not introduce
19519f ¤   ¤   ·* a weakness as the first keyrings we open will be trusted and
224575 ¤   ¤   ·* therefore the key will have at least one public keyring as a
d96723 ¤   ¤   ·* home before we begin opening untrusted rings.
b59de3 ¤   ¤   ·*/
4042ef ¤   ¤   ringKeySecMask(pool, key, &secmask);
c448c5 ¤   ¤   pgpVirtMaskCopy (pool, &key->g.mask, &pubmask);
39cc00 ¤   ¤   pgpVirtMaskANDNOT (pool, &secmask, &pubmask);
c06734 ¤   ¤   if (i == PGPVERSION_2
ed9ab7 ¤   ¤   ····&& !(key->g.flags & RINGOBJF_TRUST)
5c0bda ¤   ¤   ¤   && !pgpVirtMaskIsOverlapping (&pubmask, &pool->filemask))
7c5b34 ¤   ¤   {
476986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
a9193b ¤   ¤   ¤   ·······kPGPError_TroubleVersionBugPrev);
fa8a35 ¤   ¤   ¤   if (i < 0) {
1d9142 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
6c9b00 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
7d590c ¤   ¤   ¤   ¤   return i;
1ca3a6 ¤   ¤   ¤   }
e9ad17 ¤   ¤   ¤   /* Set all those secret version bug flags */
a0ae2d ¤   ¤   ¤   for (sec = key->g.down; sec; sec = sec->g.next)
9d1b2c ¤   ¤   ¤   ¤   if (OBJISSEC(sec))
53b901 ¤   ¤   ¤   ¤   ¤   sec->g.flags |= SECF_VERSION_BUG;
c845a6 ¤   ¤   } else {
3f7d86 /* End of KLUDGE */
ac6986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
69086e ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleDuplicateKeyID);
a9c259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
7ec81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
f16426 ¤   ¤   ¤   return i < 0 ? i : SKIP_TO_KEY;
890fe4 ¤   ¤   }
b89371 ¤   }
bfaf5a
63d8af ¤   /*
9d83ed ¤   ·* Already present in this keyring?
9bc4e6 ¤   ·* If so, accept following sigs & userids (they may
b32260 ¤   ·* not be duplicates), but flag a warning.
50a4e3 ¤   ·*/
47e330 ¤   if (pgpIsRingSetMember(&file->set, key)) {
4c73bb ¤   ¤   i = ringFileLog(file, key, 0, fpos, kPGPError_TroubleDuplicateKey);
67ad75 ¤   ¤   if (i < 0)
c83507 ¤   ¤   ¤   goto failed;
2b2433 ¤   ¤   i = SKIP_TRUST;
4ef037 ¤   } else {
0b4b94 ¤   ¤   /* Add the FilePos */
68a246 ¤   ¤   i = ringAddPos(key, file, fpos);
48ad75 ¤   ¤   if (i < 0)
4f3507 ¤   ¤   ¤   goto failed;
--eb00 000e24d89cb40100201 Page 41 of pgpRngRead.c
a19371 ¤   }
578b7f ¤   /* Add successful; indicate it in the mask */
06e523 ¤   pgpVirtMaskOR (pool, &iter->set.mask, &key->g.mask);
70cf38 ¤   iter->stack[level] = key;
8badae ¤   iter->level = level+1;
fa967c ¤   pgpVirtMaskCleanup (pool, &secmask);
829c3e ¤   pgpVirtMaskCleanup (pool, &pubmask);
662196 ¤   return i;
85af5a
b6f4b6 failed:
97f4d3 ¤   if (pgpVirtMaskIsEmpty(&key->g.mask))
58d1f2 ¤   ¤   ringFreeDummyKey(file->set.pool, key);
29967c ¤   pgpVirtMaskCleanup (pool, &secmask);
4a9c3e ¤   pgpVirtMaskCleanup (pool, &pubmask);
1c2196 ¤   return i;
6defe6 }
80af5a
4338e5 /*
96b2e5 ·* Add a new secret to the Pool, as two objects: a key (with its *parent*
c8e9cf ·* at the given level in the RingIterator; 0 means add a top-level key)
64612b ·* and a signature as its child. ·Leave the RingIterator pointing to the
726696 ·* newly created secret. ·Return <0 on error, 0 if the key was created,
9cee4a ·* and a skip code >0 if they key was created with a warning of some sort.
f6775e ·*
5bcf5b ·* This is *ridiculously* hairy. ·Is there a way to clean it up?
fdc188 ·* @@@ TODO: Add kPGPError_TroubleOldSecretKey and _NEWSEC handling.
6e495d ·*/
39beb7 static int
1d17a6 ringAddSec(RingFile *file, RingIterator *iter, PGPUInt32 fpos,
c5c141 ¤   PGPByte pkttype)
6ebb36 {
30b499 ¤   union RingObject *key, *sec, *parent;
df04e1 ¤   PGPByte pkalg, keyID[8];
613ab6 ¤   PGPUInt16 keybits;
7be0c3 ¤   PGPUInt32 tstamp;
7b6b1d ¤   PGPUInt16 validity;
4257be ¤   PGPVirtMask secmask, pubmask;
5be7f9 ¤   PGPByte v3;
08c975 ¤   RingPool *pool = file->set.pool;
30e32d ¤   int i, err;
ecbeaf ¤   int level;
1f160a ¤   int flags = 0;
b0af5a
ba673b ¤   pgpVirtMaskInit (pool, &secmask);
ea6d79 ¤   pgpVirtMaskInit (pool, &pubmask);
e0af5a
3ad1cf ¤   pkalg = 0;
0e3840 ¤   err = ringKeyParse(file->set.pool->context,
7d4b78 ¤   ¤   ¤   ¤   ¤   ···(PGPByte const *)file->set.pool->pktbuf,
998f93 ¤   ···················file->set.pool->pktbuflen, &pkalg,
40dff3 ¤   ···················keyID, &keybits, &tstamp, &validity, &v3, 1);
7aaf5a
e04d20 ¤   if (pkttype == PKTBYTE_SECSUBKEY) {
9df311 ¤   ¤   /* Subkey */
38d198 ¤   ¤   if (!iter->level) {
ffd58d ¤   ¤   ¤   i = ringFileLog(file, NULL, 0, fpos,
aecdeb ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleUnexpectedSubKey);
b3c259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
0bc81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
8d940e ¤   ¤   ¤   return i < 0 ? i : SKIP_SIGS;
170fe4 ¤   ¤   }
c95a1a ¤   ¤   parent = iter->stack[0];
bcb706 ¤   ¤   level = 1;
7df037 ¤   } else {
e7c389 ¤   ¤   parent = NULL;
f6edda ¤   ¤   level = 0;
9c9371 ¤   }
f1af5a
ddeb65 ¤   /* Find the matching key structure */
8d651f ¤   key = ringPoolFindDummyKey(file->set.pool, file, parent, pkalg, keyID,
6d7e76 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···FALSE);
e2ebb3 ¤   if (!key) {
--d965 000666da0e940100201 Page 42 of pgpRngRead.c
2d90c4 ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
ee9a86 ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
f1ad8f ¤   ¤   return ringFileError(file)->error;
b49371 ¤   }
2daf5a
8bdfab ¤   /* See if it's a new key or the same key */
c8e545 ¤   if (pgpVirtMaskIsEmpty (&key->g.mask)) {
1ced86 ¤   ¤   /* Newly created dummy key; fill in info */
0b3a8b ¤   ¤   if (pkttype == PKTBYTE_SECSUBKEY ·&& ·OBJISTOPKEY(key)) {
467aad ¤   ¤   ¤   /*
1eda55 ¤   ¤   ¤   ·* Here on a former dummy top-level key which
32dfec ¤   ¤   ¤   ·* has turned out to be a subkey. ·Dummy key
33a50b ¤   ¤   ¤   ·* would have been created if we saw a sig by
0d2fa1 ¤   ¤   ¤   ·* it. ·Change key to a subkey.
7b8753 ¤   ¤   ¤   ·*/
89d58d ¤   ¤   ¤   i = ringFileLog(file, NULL, 0, fpos,
2430b5 ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleSigSubKey);
918a35 ¤   ¤   ¤   if (i < 0) {
5d9142 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
3f9b00 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
0d590c ¤   ¤   ¤   ¤   return i;
f3a3a6 ¤   ¤   ¤   }
1c20e2 ¤   ¤   ¤   ringPoolUnlinkKey(file->set.pool, key);
eb475c ¤   ¤   ¤   key->k.flags |= RINGOBJF_SUBKEY;
4a0c0d ¤   ¤   ¤   ringPoolLinkKey(file->set.pool, parent, key,
baa6e9 ¤   ¤   ¤   ¤   ¤   pkalg, keyID);
bb0fe4 ¤   ¤   }
2baf5a
5ced86 ¤   ¤   /* Newly created dummy key; fill in info */
70cb9c ¤   ¤   key->k.pkalg = pkalg;¤  /* ViaCrypt */
2197a2 ¤   ¤   key->k.tstamp = tstamp;
771334 ¤   ¤   key->k.validity = validity;
2ece13 ¤   ¤   key->k.keybits = keybits;
2797b3 ¤   ¤   key->k.trust = 0;
943c4f ¤   ¤   if (v3)
346d73 ¤   ¤   ¤   KEYSETV3(&key->k);
01150b ¤   ¤   if (err)
fac3a1 ¤   ¤   ¤   key->g.flags |= KEYF_ERROR;
4caf5a
4c10f0 ¤   } else if (keybits ····!= key->k.keybits
88b872 ¤   ¤   ···|| pkalg ···!= key->k.pkalg¤ ¤   /* ViaCrypt */
518508 ¤   ¤   ···|| tstamp ··!= key->k.tstamp
da1e71 /*¤ ¤   ···|| validity != key->k.validity¤  Validity may be in sig */
287e77 ¤   ¤   ···|| parent ··!= (OBJISTOP(key) ? NULL : key->g.up)
472525 ¤   ¤   ···|| v3¤   ···!= !!KEYISV3(&key->k)
821677 ¤   ¤   ···|| !(key->g.flags & KEYF_ERROR) != !err)
30c7a1 ¤   {
31c7da ¤   ¤   i = ringFileLog(file, key, 0, fpos, kPGPError_TroubleDuplicateKeyID);
e290c4 ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
ea9a86 ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
9cec40 ¤   ¤   return i < 0 ? i : SKIP_TO_KEY;
deaf5a
29fa8e ¤   } else if ((i=keysdiffer(file,key,PB_SECKEY(key))) != 0) {
c23be4 ¤   ¤   if (i < 0) {
34c259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
48c81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
4e9eb9 ¤   ¤   ¤   return i;
740fe4 ¤   ¤   }
e39bf2 ¤   ¤   if ((OBJISTOPKEY(key) && pkttype==PKTBYTE_PUBSUBKEY) ||
2c7989 ¤   ¤   ····(OBJISSUBKEY(key) && pkttype==PKTBYTE_PUBKEY)) {
3e6986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
facc4a ¤   ¤   ¤   ¤   kPGPError_TroubleKeySubKey);
1cc259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
99c81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
0a03df ¤   ¤   ¤   return (i < 0) ? i : SKIP_TO_KEY;
6d0fe4 ¤   ¤   }
5cfc2f /* KLUDGE: version byte bug */
721b17 ¤   ¤   /*
771596 ¤   ¤   ·* A key with a version byte of 2 only overrides previous
3be927 ¤   ¤   ·* keys with a PGPByte of 3 if they are all untrusted
cc157f ¤   ¤   ·* secret keys and this is either a secret key or from
66f3bc ¤   ¤   ·* a trusted public keyring. ·A key with a version byte
--dd49 0003c0ceb1a40100201 Page 43 of pgpRngRead.c
479105 ¤   ¤   ·* of 3 is only overridden if it's secret and previous
20a18a ¤   ¤   ·* keys include a secret key or a trusted public key.
1a9de3 ¤   ¤   ·*/
1a42ef ¤   ¤   ringKeySecMask(pool, key, &secmask);
d848c5 ¤   ¤   pgpVirtMaskCopy (pool, &key->g.mask, &pubmask);
2bcc00 ¤   ¤   pgpVirtMaskANDNOT (pool, &secmask, &pubmask);
e06734 ¤   ¤   if (i == PGPVERSION_2
409ab7 ¤   ¤   ····&& !(key->g.flags & RINGOBJF_TRUST)
790bda ¤   ¤   ¤   && !pgpVirtMaskIsOverlapping (&pubmask, &pool->filemask))
035b34 ¤   ¤   {
146986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
81193b ¤   ¤   ¤   ·······kPGPError_TroubleVersionBugPrev);
e38a35 ¤   ¤   ¤   if (i < 0) {
969142 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
bc9b00 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
1b590c ¤   ¤   ¤   ¤   return i;
1aa3a6 ¤   ¤   ¤   }
e8ad17 ¤   ¤   ¤   /* Set all those secret version bug flags */
91ae2d ¤   ¤   ¤   for (sec = key->g.down; sec; sec = sec->g.next)
881b2c ¤   ¤   ¤   ¤   if (OBJISSEC(sec))
beb901 ¤   ¤   ¤   ¤   ¤   sec->g.flags |= SECF_VERSION_BUG;
5c2dc0 ¤   ¤   } else if (i == PGPVERSION_3
47de01 ¤   ¤   ···········&& (key->g.flags & RINGOBJF_TRUST
743d36 ¤   ¤   ¤   ¤   ¤   ···|| !pgpVirtMaskIsEmpty (&secmask)))
fe5b34 ¤   ¤   {
586986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
a7571d ¤   ¤   ¤   ·······kPGPError_TroubleVersionBugCur);
928a35 ¤   ¤   ¤   if (i < 0) {
cc9142 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
d29b00 ¤   ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
ad590c ¤   ¤   ¤   ¤   return i;
28a3a6 ¤   ¤   ¤   }
898b6d ¤   ¤   ¤   flags |= SECF_VERSION_BUG;
0fd077 ¤   ¤   ¤   /* Fix the problem */
61dc0d ¤   ¤   ¤   ((PGPByte *)file->set.pool->pktbuf)[0] = PGPVERSION_2;
b845a6 ¤   ¤   } else {
567d86 /* End of KLUDGE */
1c6986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
9d086e ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleDuplicateKeyID);
55c259 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &secmask);
35c81b ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &pubmask);
766426 ¤   ¤   ¤   return i < 0 ? i : SKIP_TO_KEY;
230fe4 ¤   ¤   }
639371 ¤   }
64af5a
802e2f ¤   /* Okay, we've got the public key. ·Now add the secret. */
f8af5a
935f92 ¤   sec = ringFindSec(file, key);
b3787e ¤   if (!sec) {
cb8029 ¤   ¤   i = ringFileError(file)->error;
f084d6 ¤   ¤   goto failed;
489371 ¤   }
9ce4a8 ¤   sec->c.flags |= flags;
00af5a
875c89 ¤   if (pgpIsRingSetMember (&file->set, sec)) {
e42cc0 ¤   ¤   i = ringFileLog(file, key, 0,
5a40f5 ¤   ¤   ¤   ¤   fpos, kPGPError_TroubleDuplicateSecretKey);
e3ad75 ¤   ¤   if (i < 0)
413507 ¤   ¤   ¤   goto failed;
582433 ¤   ¤   i = SKIP_TRUST;
01f037 ¤   } else {
d04b94 ¤   ¤   /* Add the FilePos */
0b4efb ¤   ¤   i = ringAddPos(sec, file, fpos);
083be4 ¤   ¤   if (i < 0) {
691383 ¤   ¤   ¤   pgpAssert(!pgpVirtMaskIsEmpty(&sec->g.mask));
e53507 ¤   ¤   ¤   goto failed;
670fe4 ¤   ¤   }
d29371 ¤   }
08af5a
ebd8af ¤   /*
2d83ed ¤   ·* Already present in this keyring?
3cc4e6 ¤   ·* If so, accept following sigs & userids (they may
--58f0 000d45a94c640100201 Page 44 of pgpRngRead.c
a02260 ¤   ·* not be duplicates), but flag a warning.
0f1499 ¤   ·* If the previous instances were all public keys,
6afdf0 ¤   ·* but this is a secret key, "upgrade" the reference.
f4a4e3 ¤   ·*/
6441f3 ¤   if (pgpIsRingSetMember (&file->set, key)) {
7d1ae7 ¤   ¤   /* Only do this if it wasn't a duplicate *secret* */
f8464f ¤   ¤   if (i != SKIP_TRUST) {
ad6986 ¤   ¤   ¤   i = ringFileLog(file, key, 0, fpos,
7e9d3c ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleDuplicateKey);
53969c ¤   ¤   ¤   if (i < 0)
8b015a ¤   ¤   ¤   ¤   goto failed;
9225fe ¤   ¤   ¤   ringAlterFilePos(key, file, fpos);
78d256 ¤   ¤   ¤   i = SKIP_TRUST;
d50fe4 ¤   ¤   }
d6f037 ¤   } else {
3d4b94 ¤   ¤   /* Add the FilePos */
21b59e ¤   ¤   err = i;
7ca246 ¤   ¤   i = ringAddPos(key, file, fpos);
44ad75 ¤   ¤   if (i < 0)
e93507 ¤   ¤   ¤   goto failed;
d771b4 ¤   ¤   i = err;
d49371 ¤   }
228b7f ¤   /* Add successful; indicate it in the mask */
28e523 ¤   pgpVirtMaskOR (pool, &iter->set.mask, &key->g.mask);
8ac118 ¤   pgpVirtMaskOR (pool, &iter->set.mask, &sec->g.mask);
ebcf38 ¤   iter->stack[level] = key;
056da0 ¤   iter->stack[level+1] = sec;
c642ca ¤   iter->level = level+2;
a0967c ¤   pgpVirtMaskCleanup (pool, &secmask);
8c9c3e ¤   pgpVirtMaskCleanup (pool, &pubmask);
082196 ¤   return i;
f0af5a
8af4b6 failed:
1ef4d3 ¤   if (pgpVirtMaskIsEmpty(&key->g.mask))
e9d1f2 ¤   ¤   ringFreeDummyKey(file->set.pool, key);
f5967c ¤   pgpVirtMaskCleanup (pool, &secmask);
ed9c3e ¤   pgpVirtMaskCleanup (pool, &pubmask);
8b2196 ¤   return i;
c6efe6 }
b9af5a
9638e5 /*
ace176 ·* Add the name in the RingPool's pktbuf to the sets mentioned
b879c6 ·* in the given iterator, which points to the location where the
ee5588 ·* name should be added. ·Leaves the RingIterator pointing to the
88904d ·* name just added. ·fAttribute is true if it is a generalized attribute
911710 ·* packet.
bf495d ·*/
6bbeb7 static int
fb12f3 ringAddName(RingFile *file, RingIterator *iter, PGPUInt32 fpos,
9ff587 ¤   PGPBoolean fAttribute)
18bb36 {
3e3d81 ¤   union RingObject *name;
ca4ba4 ¤   int i;
ffaf5a
ecfa35 ¤   pgpAssert(iter->level >= 1);
f1096d ¤   name = ringFindName(file, iter->stack[0], fAttribute);
07433f ¤   if (!name)
2ead8f ¤   ¤   return ringFileError(file)->error;
c9af5a
00d8af ¤   /*
c283ed ¤   ·* Already present in this keyring?
fb9714 ¤   ·*
5457d8 ¤   ·* If so, accept following sigs (they may not be
f0d89a ¤   ·* duplicates), but flag a warning.
e1a4e3 ¤   ·*/
675d69 ¤   if (pgpIsRingSetMember (&file->set, name)) {
5981d5 ¤   ¤   i = ringFileLog(file, name, 0, fpos, kPGPError_TroubleDuplicateName);
c2ad75 ¤   ¤   if (i < 0)
9b9eb9 ¤   ¤   ¤   return i;
9f2433 ¤   ¤   i = SKIP_TRUST;
27f037 ¤   } else {
d44b94 ¤   ¤   /* Add the FilePos */
--c2f8 000ea532d6440100201 Page 45 of pgpRngRead.c
e43e63 ¤   ¤   i = ringAddPos(name, file, fpos);
cb3be4 ¤   ¤   if (i < 0) {
0f81d9 ¤   ¤   ¤   pgpAssert (!pgpVirtMaskIsEmpty(&name->g.mask));
8a9eb9 ¤   ¤   ¤   return i;
dc0fe4 ¤   ¤   }
df9371 ¤   }
39f700 ¤   pgpVirtMaskOR (file->set.pool, &iter->set.mask, &name->g.mask);
b891f1 ¤   iter->stack[1] = name;
dbaf9b ¤   iter->level = 2;
ce2196 ¤   return i;
78efe6 }
efaf5a
abaf5a
9938e5 /*
2bb144 ·* Given an X.509 sig in the pktbuf, look for any dummy keys which
af95ad ·* might have been created to represent the top-level key above this
5b81c3 ·* sig. ·When we read in X.509 certs where we can't find the signer,
3f7902 ·* we create dummy keys with keyids set as the hash of the issuer
3887ac ·* name. ·We will see if there are any such dummy keys whose keyid
138430 ·* matches the hash of our subject name, and if so, we will change all
95bec4 ·* sigs whose "by" pointers point at the dummy so that they point at
1d5c32 ·* our top level instead. ·Then we will delete the dummy (otherwise
837f04 ·* the next X.509 cert we read will point to it instead of searching
137c13 ·* for our top level key).
19495d ·*/
44f1ae static PGPError
5aca6d ringSigFixupX509Dummy (RingPool *pool, RingObject *topkey)
6fbb36 {
d604e5 ¤   PGPByte *certbuf;
88cfbb ¤   PGPSize certlen;
ce8e8c ¤   PGPByte *certinfo;
253f1f ¤   PGPSize certinfolen;
699873 ¤   PGPByte *subjectname;
9761dd ¤   PGPSize subjectlen;
e0961e ¤   PGPByte hash[20];
bf2823 ¤   PGPByte *keyid;
c2eb31 ¤   RingObject *keys;
4bb843 ¤   RingObject *k, *n, *s;
eab718 ¤   RingObject **pkey;
d3af5a
0813ba ¤   certbuf = (PGPByte *)ringSigFindSubpacket ((PGPByte *)pool->pktbuf,
f3923b ¤   ¤   ¤   ¤   SIGSUB_X509, 0, &certlen, NULL, NULL, NULL, NULL);
dfefe9 ¤   /* Find issuer name in cert */
578eba ¤   pgpX509CertPartition (certbuf, certlen, &certinfo, &certinfolen,
091008 ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, NULL, NULL);
e2f6d1 ¤   pgpX509CertInfoPartition (certinfo, certinfolen, NULL, NULL,
946c26 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, NULL, NULL, NULL, NULL,
323291 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&subjectname, &subjectlen, NULL, NULL);
c50f88 ¤   pgpFingerprint20HashBuf(pool->context, subjectname, subjectlen, hash);
227b7a ¤   keyid = hash + sizeof(hash) - 8;
fba5de ¤   keys = ringPoolFindKey(pool, 0, keyid);
7fc586 ¤   if (IsntNull( keys ) && pgpVirtMaskIsEmpty (&keys->g.mask)) {
897946 ¤   ¤   /* Yes, we must fix all pointers. ·No easy way to do this! */
03526c ¤   ¤   for (k=pool->keys; k; k=k->g.next) {
d8210a ¤   ¤   ¤   if (!OBJISTOPKEY(k))
0dd040 ¤   ¤   ¤   ¤   continue;
653811 ¤   ¤   ¤   for (n=k->g.down; n; n=n->g.next) {
ef95d4 ¤   ¤   ¤   ¤   if (!OBJISNAME(n))
405914 ¤   ¤   ¤   ¤   ¤   continue;
7bb527 ¤   ¤   ¤   ¤   for (s=n->g.down; s; s=s->g.next) {
b922eb ¤   ¤   ¤   ¤   ¤   if (OBJISSIG(s) && SIGISX509(&s->s) &&
b7a288 ¤   ¤   ¤   ¤   ¤   ¤   keys == s->s.by)
2748c4 ¤   ¤   ¤   ¤   ¤   ¤   /* Fix pointer to our grandparent */
435cff ¤   ¤   ¤   ¤   ¤   ¤   s->s.by = topkey;
cd2613 ¤   ¤   ¤   ¤   }
6ea3a6 ¤   ¤   ¤   }
880fe4 ¤   ¤   }
10c1a1 ¤   ¤   /* Remove dummy key from the keys list */
d44e97 ¤   ¤   pkey = &pool->keys;
8c8cbb ¤   ¤   while (*pkey != keys)
341098 ¤   ¤   ¤   pkey = &(*pkey)->g.next;
eaebee ¤   ¤   *pkey = keys->g.next;
--5361 000621140bf40100201 Page 46 of pgpRngRead.c
e51837 ¤   ¤   /* And from the hash chain */
162984 ¤   ¤   pkey = (RingObject **)&pool->hashtable[keys->k.keyID[0]];
378cbb ¤   ¤   while (*pkey != keys)
22c683 ¤   ¤   ¤   pkey = (RingObject **)&(*pkey)->k.util;
4abaae ¤   ¤   *pkey = (RingObject *)keys->k.util;
d3af5a
7d438e ¤   ¤   ringFreeObject(pool, keys);
709371 ¤   }
d3151e ¤   return kPGPError_NoErr;
2cefe6 }
5eaf5a
35af5a
22beb7 static int
468ff2 ringAddSig(RingFile *file, RingIterator *iter, PGPUInt32 fpos, int trusted)
3cbb36 {
8c558d ¤   union RingObject *sig;
e8beaf ¤   int level;
784ba4 ¤   int i;
35af5a
076632 ¤   (void)trusted;
93af5a
36fa35 ¤   pgpAssert(iter->level >= 1);
701713 ¤   /* Stack position of parent: 0 or 1 */
71c9a7 ¤   level = (iter->level > 1 &&
270dd2 ¤   ¤   ·(OBJISNAME(iter->stack[1]) || OBJISSUBKEY(iter->stack[1])));
f2b598 ¤   sig = ringFindSig(file, iter->stack[level]);
0b9192 ¤   if (!sig)
ddad8f ¤   ¤   return ringFileError(file)->error;
06af5a
e3a549 ¤   /* Already present in this keyring? ·Complain. */
a95f7c ¤   if (pgpIsRingSetMember(&file->set, sig)) {
e76b47 ¤   ¤   i = ringFileLog(file, sig, 0, fpos,
393faa ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleDuplicateSignature);
2cad75 ¤   ¤   if (i < 0)
b79eb9 ¤   ¤   ¤   return i;
ea2433 ¤   ¤   i = SKIP_TRUST;
bcf037 ¤   } else {
c14b94 ¤   ¤   /* Add the FilePos */
0da6dd ¤   ¤   i = ringAddPos(sig, file, fpos);
403be4 ¤   ¤   if (i < 0) {
a019ed ¤   ¤   ¤   pgpAssert(!pgpVirtMaskIsEmpty(&sig->g.mask));
c89eb9 ¤   ¤   ¤   return i;
d00fe4 ¤   ¤   }
279371 ¤   }
45c44c ¤   pgpVirtMaskOR (file->set.pool, &iter->set.mask, &sig->g.mask);
b699f5 ¤   iter->stack[level+1] = sig;
d442ca ¤   iter->level = level+2;
96af5a
3c7de0 ¤   /* Upon adding an X.509 signature, see if there is a dummy key
5cccfe ¤   ·* with keyid which matches the hash of the sig's subject name.
0e983c ¤   ·* If so, delete the dummy key and replace the s.by's which point
0ddbc0 ¤   ·* at it with pointers to the top level key.
04a4e3 ¤   ·*/
fa1875 ¤   if (SIGISX509 (&sig->s)) {
d6cad9 ¤   ¤   ringSigFixupX509Dummy (file->set.pool, iter->stack[0]);
179371 ¤   }
2aaf5a
e12196 ¤   return i;
88efe6 }
10af5a
ce38e5 /*
bf10c9 ·* Add the unknown object in the RingPool's pktbuf to the sets mentioned
0979c6 ·* in the given iterator, which points to the location where the
eca783 ·* object should be added. ·Leaves the RingIterator pointing to the
5e8660 ·* object just added.
71495d ·*/
e4beb7 static int
ff04f7 ringAddUnk(RingFile *file, RingIterator *iter, PGPUInt32 fpos,
36e9e7 ¤   PGPByte pktbyte)
02bb36 {
629c97 ¤   union RingObject *unk;
62beaf ¤   int level;
--44b4 000c291c6c240100201 Page 47 of pgpRngRead.c
6e4ba4 ¤   int i;
01af5a
adfa35 ¤   pgpAssert(iter->level >= 1);
3f67c5 ¤
d71713 ¤   /* Stack position of parent: 0 or 1 */
40d9f8 ¤   level = iter->level - 1;
be9ad1 ¤   /* Place this */
32da67 ¤   if (OBJISUNK(iter->stack[level]) && level)
1ea941 ¤   ¤   level--;
bedf26 ¤   /* Can't put it below a bottom-level object, make it a sib */
49b3c8 ¤   if (OBJISBOT(iter->stack[level]) && level)
8ca941 ¤   ¤   level--;
7c0f39 ¤   unk = ringFindUnk(file, iter->stack[level], pktbyte);
a75888 ¤   if (!unk)
97ad8f ¤   ¤   return ringFileError(file)->error;
90af5a
6fd8af ¤   /*
1ea308 ¤   ·* Already present in this keyring? ·If so, warn...
2ea4e3 ¤   ·*/
79b421 ¤   if (pgpIsRingSetMember(&file->set, unk)) {
0d327e ¤   ¤   i = ringFileLog(file, unk, 0, fpos, kPGPError_TroubleDuplicateUnknown);
90ad75 ¤   ¤   if (i < 0)
da9eb9 ¤   ¤   ¤   return i;
682433 ¤   ¤   i = SKIP_TRUST;
2ef037 ¤   } else {
314b94 ¤   ¤   /* Add the FilePos */
cfac26 ¤   ¤   i = ringAddPos(unk, file, fpos);
d03be4 ¤   ¤   if (i < 0) {
1eea5b ¤   ¤   ¤   pgpAssert(!pgpVirtMaskIsEmpty(&unk->g.mask));
4d9eb9 ¤   ¤   ¤   return i;
770fe4 ¤   ¤   }
629371 ¤   }
d176c0 ¤   /* All done, we're happy... */
96ddf8 ¤   pgpVirtMaskOR (file->set.pool, &iter->set.mask, &unk->g.mask);
2a50ef ¤   iter->stack[level+1] = unk;
cd42ca ¤   iter->level = level+2;
4c2196 ¤   return i;
fcefe6 }
95af5a
01af5a
d534af /*** The feature presentation ***/
b9af5a
0a38e5 /*
1d711f ·* KLUDGE: PGP 2.6 had a bug wherein if you changed the passphrase on
7edd68 ·* a secret key, the newly encrpyted secret key would be written out
e1ed04 ·* with a version byte of PGPVERSION_3 (= 3), even if the original
f2b42d ·* was PGPVERSION_2 (= 2). ·PGP 2.6 didn't notice the problem and
81427b ·* would continue to function very happily with the problem.
75775e ·*
5ad5e9 ·* The code here notices and attempts to undo the problem,
4d4f3e ·* "overriding" the version byte of 3 and forming a consistent
f6f7b6 ·* idea of the key's version byte.
dc1bb8 ·* The only problem is avoiding a denial-of-service attack if
aae254 ·* someone sends me a public key with a version byte of 2 and
6145f8 ·* I compare it with my secret key with a (correct) version
9a97db ·* byte of 3, and fix my secret key to 2 to correspond.
0c2952 ·* It could cause problems unfixable except with a binary file
f8af4a ·* editor. ·So we only accept evidence of the bug under certain
8f6fc8 ·* conditions. ·To be precise:
40775e ·*
63fd16 ·* - A key with a version byte of 2 can only override the previous
1bdfa9 ·* ··version bytes of 3 if all previous keys are secret keys
1db7bb ·* ··without trust information and the key is either a secret key
edd6e4 ·* ··or from a trusted public keyring.
712cb4 ·* - A key with a version byte of 3 is only overridden by previous
3cec55 ·* ··keys if it is a secret key and the previous keys include a
fe412c ·* ··secret key or a key from a trusted keyring.
05775e ·*
dc4407 ·* A Trouble record is logged in either case. ·TROUBLE_VERSION_BUG_PREV
15d062 ·* if previous keys had the version bug and TROUBLE_VERSION_BUG_CUR if
de8e44 ·* the current key has it.
c2775e ·*
--f2f9 000c4664a2640100201 Page 48 of pgpRngRead.c
3064b0 ·* - Fixing instructions:
facc5a ·* ··- We want to split out a function to add a single object.
4e983f ·* ··- Replace parse tree state with ringIterator.
b077fa ·* ··- Fiddle with trust packets somehow.
e9c633 ·* ··- Use the fact that ringFileDoClose gets rid of half-built
b899c4 ·* ····keys to simplify the public-key-gathering part.
3392d2 ·* DANGER, WILL ROBINSON: What about running out of memory when creating
f760a2 ·* a new key? ·That's one case when it's *not* desirable to close
913017 ·* the whole file. ·Grumble moan bitch complain...
ee775e ·*
24385f ·* Okay a few cases:
7a1e69 ·* - The secret is old, as is the key.
cd4b50 ·* ··In that case, we're only ZZ
3c495d ·*/
624439 RingFile *
c0454a ringFileOpen(RingPool *pool, PGPFile *f, int trusted, PGPError *error)
60bb36 {
038f45 ¤   /* Oy, what a lot of variables! */
68af5a
2d02d7 ¤   /* The RingFile being opened */
fbff7f ¤   RingFile *file;
4245d1 ¤   PGPVirtMask mask;
2bc6d6 ¤   unsigned bit;
7daf5a
e4bc49 ¤   /* The current state of the parse tree */
cac4f6 ¤   RingIterator iter;
15a997 ¤   union RingObject *obj;
91af5a
f1bfe8 ¤   /* Current packet info */
a2509e ¤   int pktbyte;
297ecf ¤   PGPSize len, len1, fpos;
d9290c ¤   char *buf;¤ ¤   /* Current pktbuf */
8caf5a
f74bdb ¤   /* Information from selfsig subpackets associated with parent key */
4f5b51 ¤   union RingObject ··*sigkeyparent = NULL;
c8a041 ¤   PGPUInt32¤  ¤   ¤   ¤   sigkeyvalidity = 0;
0baf5a
00ac50 ¤   /* Various temporaries */
8bf2f3 ¤   int i;¤ ¤   ¤   /* Multi-purpose temp */
c07dec #if PGPTRUSTMODEL>0
5e4493 ¤   int j, k;¤  ¤   /* Additional trust packet bytes */
bc7454 #endif
ff8773 ¤   PGPByte c;¤ ¤   ¤   /* for pgpFileRead */
6fc0d4 ¤   size_t size;¤   ¤   /* Return value from pgpFileRead() */
542f30 ¤   PGPByte *tp;¤   ¤   /* Pointer to trust byte */
66853e ¤   RingTrouble const *trouble;
01af5a
991260 ¤   /* Flags */
67a0c2 ¤   int dirty = 0, trustdirty = 0;
3b6f6a ¤   skip_t skip;
bbb5ab ¤   int trustf;¤¤   /* 1 for trust, 2 for optional trust */
7c3410 ¤   int trustmissing;¤  /* OR of trustf values */
bbaf5a
640040 ¤   PGPError err;
14af5a
edd8af ¤   /*
939927 ¤   ·* The code starts here
afa4e3 ¤   ·*/
93af5a
193e4a ¤   if (!f || !pool) {
fda79e ¤   ¤   *error = kPGPError_NoErr;
3ae017 ¤   ¤   return (RingFile *)NULL;
fb9371 ¤   }
701b52 ¤   ¤
5ddbf9 ¤   err = ringBitAlloc(pool, &bit);
1e1065 ¤   if (IsPGPError(err)) {
0d91c3 ¤   ¤   *error = err;
b87ed2 ¤   ¤   return NULL;
2d9371 ¤   }
5eaf5a
0714fb ¤   pgpVirtMaskInit (pool, &mask);
c4af5a
--f555 00000018ed140100201 Page 49 of pgpRngRead.c
24857e ¤   /* Make sure enough pool->files entries are allocated */
0205a7 ¤   ringFilesInit (pool, bit);
b0af5a
90ad5e ¤   pgpVirtMaskSetBit (pool, &mask, bit);
d72d99 ¤   file = pool->files[bit];
e2168f ¤   pgpAssert(pgpVirtMaskIsEqual (&file->set.mask, &mask));
94af5a
2c9c24 ¤   pgpVirtMaskOR (pool, &mask, &pool->filemask);
e7300b ¤   pgpVirtMaskOR (pool, &mask, &pool->allocmask);
1eaf5a
e44058 ¤   /* Set this file as the lowest-priority file */
e5d9ba ¤   ringFileLowPri(file);
71af5a
b21b00 ¤   pgpAssert(!file->set.next);
73af5a
447696 ¤   file->f = f;
89ae51 ¤   file->destructor = NULL;
daf705 ¤   file->arg = NULL;
30a5c4 ¤   file->version = PGPVERSION_2;
83af5a
b31bcb ¤   /* Start out with a clean slate */
449096 ¤   *error = kPGPError_NoErr;
8eaf5a
b49591 ¤   /* Initialize a null RingIterator */
254671 ¤   iter.set.pool = pool;
f140d0 ¤   pgpVirtMaskInit (pool, &iter.set.mask);
59af5a
dfddde ¤   /* There is no current key */
6b6c38 ¤   iter.level = 0;
1be33c ¤   /* There is no current packet to give trust to */
94b34f ¤   trustf = 0;
f449a7 ¤   /* No trust is missing, yet */
f52544 ¤   trustmissing = 0;
16d6f7 ¤   /* Pay attention to all the packets */
23f806 ¤   skip = 0;
f567c5 ¤
3baf5a
b0d8af ¤   /*
b5b7ba ¤   ·* The main loop over each packet.
e9a4e3 ¤   ·*/
5283dc ¤   while ((pktbyte = pktByteGet(file->f, &len, &len1, &fpos)) > 0) {
2ed2d5 ¤   ¤   switch (PKTBYTE_TYPE(pktbyte)) {
e185bb skipkey:
6cffba ¤   ¤   ¤   skip = SKIP_TO_KEY;
32c0ed ¤   ¤   ¤   goto skippkt;
1853db skipname:
068d80 ¤   ¤   ¤   skip = SKIP_SIGS;
c3c0ed ¤   ¤   ¤   goto skippkt;
0fa07b skipunk:
3f6961 skipsig:
2ec16a ¤   ¤   ¤   skip = SKIP_TRUST;
b5c0ed ¤   ¤   ¤   goto skippkt;
721584 ¤   ¤   ··default:
b37aad ¤   ¤   ¤   /*
877d72 ¤   ¤   ¤   ·* Add it as an unknown object if it's not the first
b7123c ¤   ¤   ¤   ·* thing in the keyring...
2f8753 ¤   ¤   ¤   ·*/
77d043 ¤   ¤   ¤   if (!iter.level) {
517837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
e8b8e2 ¤   ¤   ¤   ¤   ¤   0, fpos, kPGPError_TroubleUnexpectedUnknown);
13747d ¤   ¤   ¤   ¤   if (i < 0)
36ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
8dcee8 ¤   ¤   ¤   ¤   goto skipunk;
ffa3a6 ¤   ¤   ¤   }
3d98d2 ¤   ¤   ¤   if (len > RINGUNK_MAXLEN) {¤/* Too big */
527837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
6634f8 ¤   ¤   ¤   ¤   ¤   len, fpos, kPGPError_TroubleUnknownTooBig);
69747d ¤   ¤   ¤   ¤   if (i < 0)
b0ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
51cee8 ¤   ¤   ¤   ¤   goto skipunk;
eda3a6 ¤   ¤   ¤   }
002af6 ¤   ¤   ¤   /* Read in the unknown for hashing */
--3a8f 000cffbfa1140100201 Page 50 of pgpRngRead.c
1b4eef ¤   ¤   ¤   buf = ringReserve(pool, (size_t)len);
229ff0 ¤   ¤   ¤   if (!buf)
b9fd8b ¤   ¤   ¤   ¤   goto fatal;
8577d1 ¤   ¤   ¤   size = pktBodyRead(buf, len, len1, file->f);
9656f2 ¤   ¤   ¤   if (size != (size_t)len)
0fc6b6 ¤   ¤   ¤   ¤   goto readerr;
5e0b60 ¤   ¤   ¤   pool->pktbuflen = size;
66af5a
c03ceb ¤   ¤   ¤   i = ringAddUnk(file, &iter, fpos, (PGPByte)pktbyte);
57969c ¤   ¤   ¤   if (i < 0)
eb015a ¤   ¤   ¤   ¤   goto failed;
df0857 ¤   ¤   ¤   obj = iter.stack[iter.level-1];
d187c7 ¤   ¤   ¤
f80fad ¤   ¤   ¤   /* Unexpected packet */
dd044f ¤   ¤   ¤   i = ringFileLog(file, obj, pktbyte, fpos,·
e57178 ¤   ¤   ¤   ················kPGPError_TroubleUnknownPacketByte);
ec969c ¤   ¤   ¤   if (i < 0)
eb015a ¤   ¤   ¤   ¤   goto failed;
82cdcb ¤   ¤   ¤   break;
bc0e75 ¤   ¤   ··case PKTBYTE_COMMENT:
47296b ¤   ¤   ¤   /* Silently ignore this packet */
d8272a skippkt:
faf6ed ¤   ¤   ¤   trustmissing |= trustf;
725ec8 ¤   ¤   ¤   trustf = 0;
e149b8 ¤   ¤   ¤   dirty = 1;
961390 skiptrust:
fa392d ¤   ¤   ¤   i = pgpFileSeek(file->f, len, SEEK_CUR);
379d03 ¤   ¤   ¤   if (i != 0)
aac6b6 ¤   ¤   ¤   ¤   goto readerr;
32cdcb ¤   ¤   ¤   break;
11af5a
054995 ¤   ¤   ··case PKTBYTE_PUBKEY:
52ccae ¤   ¤   ··case PKTBYTE_PUBSUBKEY:
ceaf5a
bd9be4 ¤   ¤   ¤   if (iter.level > 0 && PKTBYTE_TYPE(pktbyte) == PKTBYTE_PUBKEY) {
1c28d6 ¤   ¤   ¤   ¤   /* Check validity of previous key */
685706 ¤   ¤   ¤   ¤   i = ringKeyCleanup(file, iter.stack[0], trusted);
19747d ¤   ¤   ¤   ¤   if (i < 0)
78ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
4da3a6 ¤   ¤   ¤   }
53af5a
48f6ed ¤   ¤   ¤   trustmissing |= trustf;
b40414 ¤   ¤   ¤   trustf = 1;
eaaf5a
dbed6f ¤   ¤   ¤   if (skip & SKIP_KEY)
5649b9 ¤   ¤   ¤   ¤   goto skippkt;
354729 ¤   ¤   ¤   skip = 0;
4eaf5a
69feaf ¤   ¤   ¤   /* Check for grossly oversized key */
0cb571 ¤   ¤   ¤   if (len > RINGKEY_MAXLEN) {
f77837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
96619a ¤   ¤   ¤   ¤   ¤   len, fpos, kPGPError_TroubleKeyTooBig);
87747d ¤   ¤   ¤   ¤   if (i < 0)
79ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
cfeb28 ¤   ¤   ¤   ¤   goto skipkey;
1da3a6 ¤   ¤   ¤   }
6a4eef ¤   ¤   ¤   buf = ringReserve(pool, (size_t)len);
8c9ff0 ¤   ¤   ¤   if (!buf)
18fd8b ¤   ¤   ¤   ¤   goto fatal;
8177d1 ¤   ¤   ¤   size = pktBodyRead(buf, len, len1, file->f);
4256f2 ¤   ¤   ¤   if (size != (size_t)len)
68c6b6 ¤   ¤   ¤   ¤   goto readerr;
cf0b60 ¤   ¤   ¤   pool->pktbuflen = size;
5daf5a
529ef0 ¤   ¤   ¤   i = ringAddKey(file, &iter, fpos, trusted,
8bc25d ¤   ¤   ¤   ¤   (PGPByte)PKTBYTE_TYPE(pktbyte));
03969c ¤   ¤   ¤   if (i < 0)
42015a ¤   ¤   ¤   ¤   goto failed;
ed58d4 ¤   ¤   ¤   skip = i;
640414 ¤   ¤   ¤   trustf = 1;
aeaf5a
cfcdcb ¤   ¤   ¤   break;
--c2cb 000e5308b7140100201 Page 51 of pgpRngRead.c
e0af5a
4972a7 ¤   ¤   ··case PKTBYTE_SECKEY:
89adb2 ¤   ¤   ··case PKTBYTE_SECSUBKEY:
35af5a
a791a6 ¤   ¤   ¤   if (iter.level > 0 && PKTBYTE_TYPE(pktbyte) == PKTBYTE_SECKEY) {
6828d6 ¤   ¤   ¤   ¤   /* Check validity of previous key */
ec5706 ¤   ¤   ¤   ¤   i = ringKeyCleanup(file, iter.stack[0], trusted);
83747d ¤   ¤   ¤   ¤   if (i < 0)
6fba0c ¤   ¤   ¤   ¤   ¤   goto failed;
4da3a6 ¤   ¤   ¤   }
47af5a
6bf6ed ¤   ¤   ¤   trustmissing |= trustf;
610414 ¤   ¤   ¤   trustf = 1;
62af5a
7bed6f ¤   ¤   ¤   if (skip & SKIP_KEY)
7349b9 ¤   ¤   ¤   ¤   goto skippkt;
9d4729 ¤   ¤   ¤   skip = 0;
91af5a
fffeaf ¤   ¤   ¤   /* Check for grossly oversized key */
ea914a ¤   ¤   ¤   if (len > RINGSEC_MAXLEN) {
3d7837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
cd619a ¤   ¤   ¤   ¤   ¤   len, fpos, kPGPError_TroubleKeyTooBig);
4a747d ¤   ¤   ¤   ¤   if (i < 0)
f3ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
daeb28 ¤   ¤   ¤   ¤   goto skipkey;
71a3a6 ¤   ¤   ¤   }
ce4eef ¤   ¤   ¤   buf = ringReserve(pool, (size_t)len);
299ff0 ¤   ¤   ¤   if (!buf)
befd8b ¤   ¤   ¤   ¤   goto fatal;
0a77d1 ¤   ¤   ¤   size = pktBodyRead(buf, len, len1, file->f);
af56f2 ¤   ¤   ¤   if (size != (size_t)len)
bcc6b6 ¤   ¤   ¤   ¤   goto readerr;
760b60 ¤   ¤   ¤   pool->pktbuflen = size;
3caf5a
b9db3f ¤   ¤   ¤   i = ringAddSec(file, &iter, fpos, (PGPByte)PKTBYTE_TYPE(pktbyte));
15969c ¤   ¤   ¤   if (i < 0)
0e015a ¤   ¤   ¤   ¤   goto failed;
d658d4 ¤   ¤   ¤   skip = i;
180414 ¤   ¤   ¤   trustf = 1;
b6af5a
dbcdcb ¤   ¤   ¤   break;
4baf5a
2830ee ¤   ¤   ··case PKTBYTE_ATTRIBUTE:
b2d6b7 ¤   ¤   ··case PKTBYTE_NAME:
8df6ed ¤   ¤   ¤   trustmissing |= trustf;
440414 ¤   ¤   ¤   trustf = 1;
d7af5a
311529 ¤   ¤   ¤   if (skip & SKIP_NAME)
8049b9 ¤   ¤   ¤   ¤   goto skippkt;
734729 ¤   ¤   ¤   skip = 0;
2caf5a
96dfb2 ¤   ¤   ¤   if (iter.level < 1) {
897837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
515381 ¤   ¤   ¤   ¤   ¤   0, fpos, kPGPError_TroubleUnexpectedName);
19747d ¤   ¤   ¤   ¤   if (i < 0)
81ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
fbb6a3 ¤   ¤   ¤   ¤   goto skipname;
c0a3a6 ¤   ¤   ¤   }
c207bc ¤   ¤   ¤   /* Check for grossly oversized name */
f1cbbe ¤   ¤   ¤   if (len > RINGNAME_MAXLEN) {
127837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
9dfda4 ¤   ¤   ¤   ¤   ¤   len, fpos, kPGPError_TroubleNameTooBig);
43747d ¤   ¤   ¤   ¤   if (i < 0)
eeba0c ¤   ¤   ¤   ¤   ¤   goto failed;
b3b6a3 ¤   ¤   ¤   ¤   goto skipname;
eda3a6 ¤   ¤   ¤   }
7c4eef ¤   ¤   ¤   buf = ringReserve(pool, (size_t)len);
0b9ff0 ¤   ¤   ¤   if (!buf)
bffd8b ¤   ¤   ¤   ¤   goto fatal;
c577d1 ¤   ¤   ¤   size = pktBodyRead(buf, len, len1, file->f);
c156f2 ¤   ¤   ¤   if (size != (size_t)len)
e5c6b6 ¤   ¤   ¤   ¤   goto readerr;
--69c3 000690f990640100201 Page 52 of pgpRngRead.c
220b60 ¤   ¤   ¤   pool->pktbuflen = size;
66af5a
aecfea ¤   ¤   ¤   i = ringAddName(file, &iter, fpos,
13c9d3 ¤   ¤   ¤   ¤   ¤   ··(PGPBoolean)(PKTBYTE_TYPE(pktbyte)==PKTBYTE_ATTRIBUTE));
22969c ¤   ¤   ¤   if (i < 0)
0c015a ¤   ¤   ¤   ¤   goto failed;
4358d4 ¤   ¤   ¤   skip = i;
c7af5a
930414 ¤   ¤   ¤   trustf = 1;
edaf5a
3fcdcb ¤   ¤   ¤   break;
cfaf5a
6626c3 ¤   ¤   ··case PKTBYTE_SIG:
1ff6ed ¤   ¤   ¤   trustmissing |= trustf;
4c0414 ¤   ¤   ¤   trustf = 1;
5787c7 ¤   ¤   ¤
2101b5 ¤   ¤   ¤   if (skip & SKIP_SIG)
1449b9 ¤   ¤   ¤   ¤   goto skippkt;
044729 ¤   ¤   ¤   skip = 0;
7faf5a
5c7e3c ¤   ¤   ¤   if (iter.level < 1) {¤  /* No key yet - huh? */
9c7837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
9d3257 ¤   ¤   ¤   ¤   ¤   0, fpos, kPGPError_TroubleUnexpectedSignature);
25747d ¤   ¤   ¤   ¤   if (i < 0)
2dba0c ¤   ¤   ¤   ¤   ¤   goto failed;
0407f2 ¤   ¤   ¤   ¤   goto skipsig;
80a3a6 ¤   ¤   ¤   }
f2ff1d ¤   ¤   ¤   if (len > RINGSIG_MAXLEN) {¤/* Sig too damn big */
007837 ¤   ¤   ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL,
986845 ¤   ¤   ¤   ¤   ¤   len, fpos, kPGPError_TroubleSignatureTooBig);
72747d ¤   ¤   ¤   ¤   if (i < 0)
d1ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
9407f2 ¤   ¤   ¤   ¤   goto skipsig;
f1a3a6 ¤   ¤   ¤   }
c038ef ¤   ¤   ¤   /* Read in the signature for future analysis */
574eef ¤   ¤   ¤   buf = ringReserve(pool, (size_t)len);
849ff0 ¤   ¤   ¤   if (!buf)
3dfd8b ¤   ¤   ¤   ¤   goto fatal;
9077d1 ¤   ¤   ¤   size = pktBodyRead(buf, len, len1, file->f);
7356f2 ¤   ¤   ¤   if (size != (size_t)len)
5cc6b6 ¤   ¤   ¤   ¤   goto readerr;
470b60 ¤   ¤   ¤   pool->pktbuflen = size;
6daf5a
a129a8 ¤   ¤   ¤   i = ringAddSig(file, &iter, fpos, trusted);
f3969c ¤   ¤   ¤   if (i < 0)
94015a ¤   ¤   ¤   ¤   goto failed;
ed58d4 ¤   ¤   ¤   skip = i;
030414 ¤   ¤   ¤   trustf = 1;
e8af5a
053bf4 ¤   ¤   ¤   /* We will put these values into the key if sig is valid */
e7c4ee ¤   ¤   ¤   sigkeyparent = NULL;
41c115 ¤   ¤   ¤   sigkeyvalidity = 0;
340857 ¤   ¤   ¤   obj = iter.stack[iter.level-1];
2dce69 ¤   ¤   ¤   if (i == 0) {
a72275 ¤   ¤   ¤   ¤   /* See if a self signature; if so, store some info */
40aa5b ¤   ¤   ¤   ¤   RingObject *sigowner = obj; ··/* top level key above sig */
997e00 ¤   ¤   ¤   ¤   RingObject *sigparent = NULL; /* first key above sig */
c9c156 ¤   ¤   ¤   ¤   /* Find key above sig */
4bb788 ¤   ¤   ¤   ¤   do {
e226ab ¤   ¤   ¤   ¤   ¤   sigowner = sigowner->g.up;
879dd9 ¤   ¤   ¤   ¤   ¤   if (OBJISKEY(sigowner) && !sigparent) {
04e860 ¤   ¤   ¤   ¤   ¤   ¤   sigparent = sigowner;
051c89 ¤   ¤   ¤   ¤   ¤   }
78469f ¤   ¤   ¤   ¤   } while (!OBJISTOPKEY(sigowner));
86e710 ¤   ¤   ¤   ¤   if (obj->s.by == sigowner) {
e57980 ¤   ¤   ¤   ¤   ¤   /* Self signature */
ee40fa ¤   ¤   ¤   ¤   ¤   PGPByte const *pk;
5992e9 ¤   ¤   ¤   ¤   ¤   /* Note that this may alter the contents of buf */
d0b257 ¤   ¤   ¤   ¤   ¤   pk = ringSigFindSubpacket ( (PGPByte *)buf,
a65ebc ¤   ¤   ¤   ¤   ¤   ¤   SIGSUB_KEY_EXPIRATION,
fb1ad9 ¤   ¤   ¤   ¤   ¤   ¤   0, NULL, NULL, NULL, NULL, NULL);
69b6f5 ¤   ¤   ¤   ¤   ¤   if (pk) {
--bfdf 000583cc65c40100201 Page 53 of pgpRngRead.c
cef840 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyexp;
69511c ¤   ¤   ¤   ¤   ¤   ¤   keyexp = (PGPUInt32)((unsigned)pk[0]<<8|pk[1]) << 16 |
b183f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ((unsigned)pk[2]<<8|pk[3]);
347229 ¤   ¤   ¤   ¤   ¤   ¤   /* These values will be used later if sig is trusted */
7293fa ¤   ¤   ¤   ¤   ¤   ¤   sigkeyparent = sigparent;
602da3 ¤   ¤   ¤   ¤   ¤   ¤   sigkeyvalidity = (PGPUInt16) (keyexp / (24 * 3600));
b71c89 ¤   ¤   ¤   ¤   ¤   }
112613 ¤   ¤   ¤   ¤   }
b2a3a6 ¤   ¤   ¤   }
e4cdcb ¤   ¤   ¤   break;
42af5a
d3b944 ¤   ¤   ··case PKTBYTE_TRUST:
2eaf5a
99f277 ¤   ¤   ¤   if (!trustf) {
7cd8e8 ¤   ¤   ¤   ¤   i = ringFileLog(file, NULL, len, fpos,
1bc2de ¤   ¤   ¤   ¤   ················kPGPError_TroubleUnexpectedTrust);
38747d ¤   ¤   ¤   ¤   if (i < 0)
b9ba0c ¤   ¤   ¤   ¤   ¤   goto failed;
2b49b9 ¤   ¤   ¤   ¤   goto skippkt;
3ca3a6 ¤   ¤   ¤   }
0864bf ¤   ¤   ¤   pgpAssert(iter.level);
645ec8 ¤   ¤   ¤   trustf = 0;
c61178 ¤   ¤   ¤   if (skip & SKIP_TRUST)
c049b9 ¤   ¤   ¤   ¤   goto skippkt;
6e4729 ¤   ¤   ¤   skip = 0;
40fb85 ¤   ¤   ¤   /* If not a trusted keyring, ignore trust packets */
8fb97d ¤   ¤   ¤   if (!trusted)
13afbe ¤   ¤   ¤   ¤   goto skiptrust;
fb0857 ¤   ¤   ¤   obj = iter.stack[iter.level-1];
c550af ¤   ¤   ¤   if (OBJISSEC(obj)) {
64a7d7 ¤   ¤   ¤   ¤   pgpAssert(iter.level >= 2);
b235ca ¤   ¤   ¤   ¤   obj = iter.stack[iter.level-2];
b9a3a6 ¤   ¤   ¤   }
0b1325 #if PGPTRUSTMODEL==0
983a42 ¤   ¤   ¤   /* Skip bad trust packets */
c3cc4b ¤   ¤   ¤   if (len != 1) {
7671cd ¤   ¤   ¤   ¤   i = ringFileLog(file, obj, len, fpos,
ecf485 ¤   ¤   ¤   ¤   ¤   kPGPError_TroubleBadTrust);
4449b9 ¤   ¤   ¤   ¤   goto skippkt;
73a3a6 ¤   ¤   ¤   }
e69cb5 ¤   ¤   ¤   if (pgpFileRead(&c, 1, file->f) != 1)
f4c6b6 ¤   ¤   ¤   ¤   goto readerr;
f77567 ¤   ¤   ¤   i = c & 255;
f7af5a
4db74e ¤   ¤   ¤   /* Set the appropriate flags */
276c72 ¤   ¤   ¤   pgpAssert(!OBJISSEC(obj));
8ec374 ¤   ¤   ¤   switch (ringObjectType(obj)) {
f52e6d ¤   ¤   ¤   ··default:
3c3ed7 ¤   ¤   ¤   ¤   pgpAssert(0);
d02a3e ¤   ¤   ¤   ··case RINGTYPE_KEY:
0c4c05 ¤   ¤   ¤   ¤   tp = &obj->k.trust;
fdf622 ¤   ¤   ¤   ¤   break;
b183ea ¤   ¤   ¤   ··case RINGTYPE_NAME:
f13e1d ¤   ¤   ¤   ¤   tp = &obj->n.trust;
87f622 ¤   ¤   ¤   ¤   break;
f5c6e4 ¤   ¤   ¤   ··case RINGTYPE_SIG:
eacc5b ¤   ¤   ¤   ¤   tp = &obj->s.trust;
27f622 ¤   ¤   ¤   ¤   break;
fe0ffe ¤   ¤   ¤   ··case RINGTYPE_UNK:
286844 ¤   ¤   ¤   ¤   tp = &obj->u.trust;
b9f622 ¤   ¤   ¤   ¤   break;
78a3a6 ¤   ¤   ¤   }
681203 ¤   ¤   ¤   if (obj->g.flags & RINGOBJF_TRUST) {
fce2f2 ¤   ¤   ¤   ¤   if (i != *tp)
6f2fc6 ¤   ¤   ¤   ¤   ¤   trustdirty = 1;
83042d ¤   ¤   ¤   } else {
d2202a ¤   ¤   ¤   ¤   *tp = (PGPByte)i;
169ba6 ¤   ¤   ¤   ¤   obj->g.flags |= RINGOBJF_TRUST;
03a3a6 ¤   ¤   ¤   }
9935e1 #else /* NEWTRUST */
050d87 ¤   ¤   ¤   if (OBJISNAME(obj)) {
58980e ¤   ¤   ¤   ¤   /*
--31cf 000b6da85cd40100201 Page 54 of pgpRngRead.c
64cb04 ¤   ¤   ¤   ¤   ·* Name trust packets can be up to 3 bytes
b9b4a6 ¤   ¤   ¤   ¤   ·* long:
8566c3 ¤   ¤   ¤   ¤   ·* Byte 1: old-style trust packet
f35332 ¤   ¤   ¤   ¤   ·* Byte 2: validity of name
64abfa ¤   ¤   ¤   ¤   ·* Byte 3: confidence in name as introducer
b51020 ¤   ¤   ¤   ¤   ·*/
4bc5ef ¤   ¤   ¤   ¤   if (len < 1 || len > 3) {
270106 ¤   ¤   ¤   ¤   ¤   i = ringFileLog(file, obj, len,
26df61 ¤   ¤   ¤   ¤   ¤   ¤   fpos, kPGPError_TroubleBadTrust);
697eb1 ¤   ¤   ¤   ¤   ¤   goto skippkt;
592613 ¤   ¤   ¤   ¤   }
9132b4 ¤   ¤   ¤   ¤   if (pgpFileRead(&c, 1, file->f) != 1)
0ef1be ¤   ¤   ¤   ¤   ¤   goto readerr;
2f413a ¤   ¤   ¤   ¤   i = c & 255;
2efaf6 ¤   ¤   ¤   ¤   /* Default trust and validity bytes */
17de02 ¤   ¤   ¤   ¤   switch (i & kPGPNameTrust_Mask) {
de5197 ¤   ¤   ¤   ¤   ··case kPGPNameTrust_Complete:
18ae4f ¤   ¤   ¤   ¤   ·····/* j = pool->threshold; */
f21e86 ¤   ¤   ¤   ¤   ¤   j = pool->completeconfidence;
de14c3 ¤   ¤   ¤   ¤   ¤   break;
aff121 ¤   ¤   ¤   ¤   ··case kPGPNameTrust_Marginal:
d018e4 ¤   ¤   ¤   ¤   ·····/* j = pool->threshold/2; */
2119ab ¤   ¤   ¤   ¤   ¤   j = pool->marginalconfidence;
5014c3 ¤   ¤   ¤   ¤   ¤   break;
89cc8c ¤   ¤   ¤   ¤   ··default:
3d0d13 ¤   ¤   ¤   ¤   ¤   j = 0;
8314c3 ¤   ¤   ¤   ¤   ¤   break;
d42613 ¤   ¤   ¤   ¤   }
d4aaec ¤   ¤   ¤   ¤   pgpAssert(OBJISKEY(obj->g.up));
4b3e94 ¤   ¤   ¤   ¤   k = ringTrustOldToExtern(pool, obj->g.up->k.trust);
e1af5a
878828 ¤   ¤   ¤   ¤   if (len > 1) {
14eba4 ¤   ¤   ¤   ¤   ········file->version = PGPVERSION_4;
e34d1c ¤   ¤   ¤   ¤   ¤   /* Fetch validity */
0a31c3 ¤   ¤   ¤   ¤   ¤   if (pgpFileRead(&c, 1, file->f) != 1)
bb1ecd ¤   ¤   ¤   ¤   ¤   ¤   goto readerr;
72f49b ¤   ¤   ¤   ¤   ¤   j = c & 255;
8d199b ¤   ¤   ¤   ¤   ¤   if (len > 2) {
2c0afa ¤   ¤   ¤   ¤   ¤   ¤   /* Fetch confidence */
5e46e0 ¤   ¤   ¤   ¤   ¤   ¤   if (pgpFileRead(&c, 1, file->f)
835b6d ¤   ¤   ¤   ¤   ¤   ¤   ····!= 1)
4c2223 ¤   ¤   ¤   ¤   ¤   ¤   ¤   goto readerr;
2ccc5e ¤   ¤   ¤   ¤   ¤   ¤   k = c & 255;
821c89 ¤   ¤   ¤   ¤   ¤   }
732613 ¤   ¤   ¤   ¤   }
834118 ¤   ¤   ¤   ¤   if (obj->g.flags & RINGOBJF_TRUST) {
f95155 ¤   ¤   ¤   ¤   ¤   if (i != obj->n.trust
234aff ¤   ¤   ¤   ¤   ¤   ····|| j != obj->n.validity
515795 ¤   ¤   ¤   ¤   ¤   ····|| k != obj->n.confidence
2e56ca ¤   ¤   ¤   ¤   ¤   ····|| (len == 1) !=
ac272e ¤   ¤   ¤   ¤   ¤   ·······!NAMEHASNEWTRUST(&obj->n))
54ea93 ¤   ¤   ¤   ¤   ¤   ¤   trustdirty = 1;
e0b5fc ¤   ¤   ¤   ¤   } else {
1a1d75 ¤   ¤   ¤   ¤   ¤   obj->n.trust = (PGPByte)i;
37d6a6 ¤   ¤   ¤   ¤   ¤   obj->n.validity = (PGPByte)j;
044be9 ¤   ¤   ¤   ¤   ¤   obj->n.confidence = (PGPByte)k;
7f0de7 ¤   ¤   ¤   ¤   ¤   obj->g.flags |= RINGOBJF_TRUST;
116717 ¤   ¤   ¤   ¤   ¤   if (len > 1)
96b8db ¤   ¤   ¤   ¤   ¤   ¤   NAMESETNEWTRUST(&obj->n);
221201 ¤   ¤   ¤   ¤   ¤   obj->n.valid = ringTrustToIntern ((PGPByte)j);
332613 ¤   ¤   ¤   ¤   }
cfd5e7 ¤   ¤   ¤   } else {¤   /* Not a name */
c66115 ¤   ¤   ¤   ¤   if (len != 1) {
530106 ¤   ¤   ¤   ¤   ¤   i = ringFileLog(file, obj, len,
a2df61 ¤   ¤   ¤   ¤   ¤   ¤   fpos, kPGPError_TroubleBadTrust);
937eb1 ¤   ¤   ¤   ¤   ¤   goto skippkt;
8d2613 ¤   ¤   ¤   ¤   }
5832b4 ¤   ¤   ¤   ¤   if (pgpFileRead(&c, 1, file->f) != 1)
bff1be ¤   ¤   ¤   ¤   ¤   goto readerr;
e2413a ¤   ¤   ¤   ¤   i = c & 255;
97af5a
b6af1e ¤   ¤   ¤   ¤   /* Set the appropriate flags */
--b734 000db8a024040100201 Page 55 of pgpRngRead.c
9e623e ¤   ¤   ¤   ¤   pgpAssert(!OBJISSEC(obj));
a352ec ¤   ¤   ¤   ¤   switch (ringObjectType(obj)) {
94cc8c ¤   ¤   ¤   ¤   ··default:
e809df ¤   ¤   ¤   ¤   ¤   pgpAssert(0);
861756 ¤   ¤   ¤   ¤   ··case RINGTYPE_KEY:
218950 ¤   ¤   ¤   ¤   ¤   tp = &obj->k.trust;
ef14c3 ¤   ¤   ¤   ¤   ¤   break;
07fb8c ¤   ¤   ¤   ¤   ··case RINGTYPE_SIG:
c3090e ¤   ¤   ¤   ¤   ¤   tp = &obj->s.trust;
e614c3 ¤   ¤   ¤   ¤   ¤   break;
123296 ¤   ¤   ¤   ¤   ··case RINGTYPE_UNK:
84ad11 ¤   ¤   ¤   ¤   ¤   tp = &obj->u.trust;
f614c3 ¤   ¤   ¤   ¤   ¤   break;
c62613 ¤   ¤   ¤   ¤   }
c44118 ¤   ¤   ¤   ¤   if (obj->g.flags & RINGOBJF_TRUST) {
f0d5fa ¤   ¤   ¤   ¤   ¤   if (i != *tp)
dbea93 ¤   ¤   ¤   ¤   ¤   ¤   trustdirty = 1;
e3b5fc ¤   ¤   ¤   ¤   } else {
03cf59 ¤   ¤   ¤   ¤   ¤   *tp = (PGPByte)i;
aa0de7 ¤   ¤   ¤   ¤   ¤   obj->g.flags |= RINGOBJF_TRUST;
d02613 ¤   ¤   ¤   ¤   }
07a3a6 ¤   ¤   ¤   }
e97454 #endif
d1c695 ¤   ¤   ¤   /* Handle information from self-signatures */
9c6417 ¤   ¤   ¤   if (OBJISSIG(obj) && (obj->s.trust & PGP_SIGTRUSTF_CHECKED)) {
34007d ¤   ¤   ¤   ¤   if (sigkeyparent) {
abe764 ¤   ¤   ¤   ¤   ¤   sigkeyparent->k.validity = sigkeyvalidity;
80fc6b ¤   ¤   ¤   ¤   ¤   sigkeyparent = NULL;
bf8fbc ¤   ¤   ¤   ¤   ¤   sigkeyvalidity = 0;
8d2613 ¤   ¤   ¤   ¤   }
f2a3a6 ¤   ¤   ¤   }
f6af5a
c5cdcb ¤   ¤   ¤   break;
c02bf8 ¤   ¤   } /* switch (PKTBYTE_TYPE(pktbyte)) */
7caf5a
cad4a0 ¤   } /* while ((pktbyte = pktByteGet(file->f)) > 0) */
72af5a
75411f ¤   /* Check validity of final key */
300179 ¤   if (iter.level) {
83091f ¤   ¤   i = ringKeyCleanup(file, iter.stack[0], trusted);
9ead75 ¤   ¤   if (i < 0)
073507 ¤   ¤   ¤   goto failed;
d29371 ¤   }
0daf5a
b2c242 ¤   /* Okay, we're done - handle errors in pktByteGet() and return */
23221f ¤   if (pktbyte < 0) {
1e1b17 ¤   ¤   /*
b562fd ¤   ¤   ·* Call it fatal if it was on the first packet. ·May not
cc4e14 ¤   ¤   ·* have been a keyring file at all.
bd9de3 ¤   ¤   ·*/
78b6df ¤   ¤   if (iter.level == 0) {
6f39de ¤   ¤   ¤   ringErr (file, fpos, (PGPError)pktbyte);
e90bee ¤   ¤   ¤   goto fatal;
e00fe4 ¤   ¤   }
c4259a ¤   ¤   len = (PGPUInt32)errno;¤/* Capture before *ANY* libc calls */
0e2121 ioerror:
024fb8 ¤   ¤   *error = (PGPError)pktbyte;
e0b63d ¤   ¤   i = ringFileLog(file, (union RingObject *)NULL, len,
021052 ¤   ¤   ················fpos, pktbyte);
3cad75 ¤   ¤   if (i < 0)
ad3507 ¤   ¤   ¤   goto failed;
bc251d ¤   ¤   /* A keyring with errors is *always* dirty */
ca7251 ¤   ¤   dirty = 1;
a99371 ¤   }
07af5a
33d8af ¤   /*
804557 ¤   ·* Did we get any bad trouble reports? ·"Dirty" means that
9bc6ce ¤   ·* the result of writing out the RingFile's set will not
d975cf ·¤  ·* be the same as the original file. ·Some troubles don't
d0f988 ¤   ·* have that property.
87a4e3 ¤   ·*/
dbaad8 ¤   for (trouble = file->trouble; trouble; trouble = trouble->next) {
--2773 0000f66af0240100201 Page 56 of pgpRngRead.c
1d94d2 ¤   ¤   if (trouble->type != kPGPError_TroubleVersionBugPrev
9325a9 ¤   ¤   ····&& trouble->type != kPGPError_TroubleOldSecretKey
7f204b ¤   ¤   ····&& trouble->type != kPGPError_TroubleNewSecretKey
1487b0 ¤   ¤   ····&& trouble->type != kPGPError_TroubleBareKey)
5b5b34 ¤   ¤   {
30cdcb ¤   ¤   ¤   break;
600fe4 ¤   ¤   }
509371 ¤   }
2ae7c3 ¤   if (dirty || trouble)
85ed79 ¤   ¤   ringPoolMarkDirty(pool, &mask);
d0d844 ¤   if (trusted && (trustdirty || (trustmissing & 1)))
090e53 ¤   ¤   ringPoolMarkTrustChanged(pool, &mask);
5faf5a
1403ec ¤   ringSortKeys(pool);
704fae ¤   ringPoolListSigsBy(pool);
860db9 ¤   pgpVirtMaskCleanup (pool, &mask);
a1af5a
c828f6 ¤   return file;
b7af5a
3ad8af ¤   /*
dafd31 ¤   ·* Read error: figure out error code and use general error
745ee0 ¤   ·* handler. ·Not fatal.
6aa4e3 ¤   ·*/
69a825 readerr:
7fcae4 ¤   /* If an error, or neither error nor eof (i.e. unknown), error */
c36721 ¤   len = (PGPUInt32)errno;¤/* Capture before *ANY* libc cals */
1a40d5 ¤   if (pgpFileError(file->f) || !pgpFileEof(file->f))
5cab98 ¤   ¤   pktbyte = kPGPError_ReadFailed;
fa0e24 ¤   else
0020f9 ¤   ¤   pktbyte = kPGPError_EOF;
3b3bc9 ¤   goto ioerror;
4baf5a
d3d8af ¤   /*
374758 ¤   ·* Fatal errors: undo all work in memory, return NULL,
cda7b1 ¤   ·* *error is non-zero.
2ba4e3 ¤   ·*/
468608 fatal:
69fa0f ¤   i = ringPoolError(pool)->error;
676372 failed:¤¤   ¤   /* Generic fatal entry point, error in "i" */
0b73e2 ¤   *error = (PGPError)i;
99cc5a ¤   (void)ringFileClose(file);
5baf5a
4a0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
673f59 ¤   return NULL;
4fefe6 }
b9af5a
4bb93c /** Keyring writing (this is a *lot* simpler!) **/
74af5a
8a38e5 /*
d5bb77 ·* Write out the trust packet for an object.
b7775e ·*
08ea9f ·* This is generally pretty simple, but there are different formats based
7bff15 ·* on the object type and version, and there is a kludge to omit
b5ff9a ·* writing out trust on signatures on keys if the signature is good.
32d7c6 ·* This is a PGP 2.x compatibility feature, since that chokes if it
2d0a94 ·* finds a trust packet on a key signature.
d8495d ·*/
05beb7 static int
2f444c ringCopyTrust(union RingObject const *obj, PGPFile *f,
a75f31 ··············PgpVersion version)
a9bb36 {
29fcbe ¤   char trust[3];
eb80eb ¤   size_t trustlen = 1;
374ba4 ¤   int i;
57af5a
749a46 ¤   (void)version;
e38ccb ¤   switch (ringObjectType(obj)) {
b1a535 ¤   ··case RINGTYPE_KEY:
06a76b ¤   ¤   trust[0] = (char)obj->k.trust;
db2f68 ¤   ¤   break;
9dbdba ¤   ··case RINGTYPE_SEC:
0f070b ¤   ¤   trust[0] = (char)obj->g.up->k.trust;
--9081 00076e0762840100201 Page 57 of pgpRngRead.c
4f2f68 ¤   ¤   break;
5f3db6 ¤   ··case RINGTYPE_NAME:
b01b17 ¤   ¤   /*
ad8dba ¤   ¤   ·* Names have 1 to 3 bytes of trust. ·The first byte
81816c ¤   ¤   ·* is a 2.x-compatible trust byte. ·The second is
35f0d7 ¤   ¤   ·* a validity value (how sure are we that this name
059bfa ¤   ¤   ·* is correct - computed), and the third is a confidence
91db85 ¤   ¤   ·* in the named individual as an introducer.
c554ac ¤   ¤   ·*
25788e ¤   ¤   ·* Note: ·If we are requested to write out a pre-PGP 3.0
d92c9a ¤   ¤   ·* keyring, the name validity is not converted back to
1d310e ¤   ¤   ·* an old KEYLEGIT value. ·We could do this, but it's·
ec5b6d ¤   ¤   ·* better that a maintenance pass is run prior to·
a16932 ¤   ¤   ·* using such a keyring.
384e73 ¤   ¤   ·* @@@ Is this really the best way to handle it?
169de3 ¤   ¤   ·*/
06d573 ¤   ¤   trust[0] = (char)obj->n.trust;
beb177 #if 0
0e34c2 /* Output only one byte trust packets for backwards compatibility */
3c7dec #if PGPTRUSTMODEL>0
227636 ¤   ¤   if (version >= PGPVERSION_4) {
1b280e ¤   ¤   ········trust[1] = (char)obj->n.validity;
f9908e ¤   ¤   ········trust[2] = (char)obj->n.confidence;
c27be0 ¤   ¤   ········trustlen = 3;
820fe4 ¤   ¤   }
ec7454 #endif
dd7454 #endif
fd2f68 ¤   ¤   break;
3249ef ¤   ··case RINGTYPE_SIG:
7a1b17 ¤   ¤   /*
3dd3ba ¤   ¤   ·* 2.x compatibility kludge: Don't write trust
c08022 ¤   ¤   ·* on good compromise certificates. ·PGP 2.x
8bbcdc ¤   ¤   ·* maintenance dies (assert fail) if it finds
03692d ¤   ¤   ·* trust packets on key sigs.
809de3 ¤   ¤   ·*/
d42735 ¤   ¤   trust[0] = (char)obj->s.trust;
fff1d5 ¤   ¤   if (/*version < PGPVERSION_4 &&*/
056cf5 ¤   ¤   ····OBJISKEY(obj->g.up) && obj->g.up == obj->s.by
98c9ab ¤   ¤   ····&& obj->s.type == PGP_SIGTYPE_KEY_REVOKE)
4c8144 ¤   ¤   ¤   return 0;
272f68 ¤   ¤   break;
55f727 ¤   ··default:
9d7036 ¤   ¤   pgpAssert(0);
d39371 ¤   }
7484e2 ¤   i = pktBytePut(f, PKTBYTE_BUILD(PKTBYTE_TRUST, 0), trustlen, NULL);
2e4fd6 ¤   if (i < 0)
b3a423 ¤   ¤   return i;
75fbff ¤   if (pgpFileWrite(trust, trustlen, f) != trustlen)
23ed8b ¤   ¤   return kPGPError_WriteFailed;
683e6b ¤   return 0;
dfefe6 }
d7af5a
ab38e5 /*
8b9f7e ·* Copy the packet to the given file. ·If "trust" is non-negative,
ee5308 ·* it is appended as a trust packet. ·If "file" is non-NULL and the
7f2e21 ·* write is successful, the location in that file is listed as a
e9801c ·* position for the object.
59775e ·*
d7f454 ·* This function is careful to not add a FilePos to the object until
29dd51 ·* it is known to be completely written out.
14775e ·*
1c2edf ·* If keyobj is non-null, it is a key object corresponding to the secret
3f404a ·* object we are writing out, and we must set the FilePos for it, too.
3c495d ·*/
4ebeb7 static int
4a4854 ringCopyObject(RingSet const *set, union RingObject *obj,
f449cb ¤   union RingObject *keyobj, PGPFile *f, int writetrust,
45b446 ¤   PgpVersion version, RingFile *file)
67bb36 {
3e3bd6 ¤   void const *buf;
c2ade5 ¤   PGPSize len, len1;
764ba4 ¤   int i;
--27bf 000c985bc4040100201 Page 58 of pgpRngRead.c
b74fc6 ¤   PGPByte pktbyte;
b04b8f ¤   long pos = 0;¤  /* Initialized to suppress warnings */
75af5a
40319c ¤   static int const pktbytes[RINGTYPE_MAX] = {
4539be ¤   ¤   PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1),
76e332 ¤   ¤   PKTBYTE_BUILD(PKTBYTE_SECKEY, 1),
45f957 ¤   ¤   PKTBYTE_BUILD(PKTBYTE_NAME, 0),
1889ac ¤   ¤   PKTBYTE_BUILD(PKTBYTE_SIG, 1)
4e62bd ¤   };
23af5a
b949a6 ¤   buf = ringFetchObject(set, obj, &len);
d520df ¤   if (!buf)
31e1c3 ¤   ¤   return ringSetError(set)->error;
b2af5a
065940 ¤   /* ·If this is a secret object and it has the version bug,
d3350d ¤   ····then *do not* fix it on disk. ·This ensures that if the
e818a6 ¤   ····packet exists in more than ringFile, the packets remain
5475ae ¤   ····consistent. We'll always have to check for the bug in
ba0fba ¤   ····the future anyway, so doing this doesn't cause any harm. */
cbda86 ¤   ····
c052dc ¤   if (OBJISSEC(obj) && (obj->g.flags & SECF_VERSION_BUG))
7a3d61 ¤   ····((PGPByte *) buf)[0] = PGPVERSION_3;
18af5a
e9c3f4 ¤   if (file) {
e1fa36 ¤   ¤   pos = pgpFileTell(f);
68039d ¤   ¤   if (pos == -1)
8e14d1 ¤   ¤   ¤   return kPGPError_FileOpFailed;
819371 ¤   }
17af5a
83d950 ¤   i = ringObjectType(obj);
77e16a ¤   pgpAssert(i > 0 && i <= RINGTYPE_MAX);
ff45e9 ¤   if (OBJISSUBKEY(obj))
b6b7f1 ¤   ¤   pktbyte = PKTBYTE_BUILD(PKTBYTE_PUBSUBKEY, 1);
d94d9d ¤   else if (OBJISSEC(obj) && OBJISSUBKEY(obj->g.up))
29bcf5 ¤   ¤   pktbyte = PKTBYTE_BUILD(PKTBYTE_SECSUBKEY, 1);
5cfa96 ¤   else if (OBJISNAME(obj) && NAMEISATTR(&obj->n))
6f7688 ¤   ¤   pktbyte = PKTBYTE_BUILD_NEW(PKTBYTE_ATTRIBUTE);
0d0e24 ¤   else
998f31 ¤   ¤   pktbyte = (i == RINGTYPE_UNK) ? obj->u.pktbyte : pktbytes[i-1];
74af5a
083b87 ¤   i = pktBytePut(f, pktbyte, len, &len1);
ed4fd6 ¤   if (i < 0)
34a423 ¤   ¤   return i;
ed0424 ¤   if (pktBodyWrite(buf, len, len1, f) != len)
b8ed8b ¤   ¤   return kPGPError_WriteFailed;
96c6f4 ¤   if (writetrust) {
6cdfe4 ¤   ¤   i = ringCopyTrust(obj, f, version);
50ad75 ¤   ¤   if (i < 0)
679eb9 ¤   ¤   ¤   return i;
599371 ¤   }
72af5a
2d8cc7 ¤   /* All successful - add to file if requested */
ecc3f4 ¤   if (file) {
7d8477 ¤   ¤   i = ringAddPos (obj, file, (PGPUInt32)pos);
a633cb ¤   ¤   if (keyobj && !i)
9ec78f ¤   ¤   ¤   i = ringAddPos (keyobj, file, (PGPUInt32)pos);
89a423 ¤   ¤   return i;
269371 ¤   }
d33e6b ¤   return 0;
3eefe6 }
aaaf5a
b1c744 ¤   PGPError
653e3d ringSetWrite(RingSet const *set, PGPFile *f,
325f66 ¤   RingFile **filep, PgpVersion version, int flags)
d4bb36 {
7eff7f ¤   RingFile *file;
e83bb6 ¤   RingIterator *iter;
91e95a ¤   union RingObject *obj, *sec;
cb4db9 ¤   union RingObject *keyobj;
275c1c ¤   unsigned level;
5245d1 ¤   PGPVirtMask mask;
c9c6d6 ¤   unsigned bit;
--7091 000a4787acd40100201 Page 59 of pgpRngRead.c
6e4ba4 ¤   int i;
0c0f16 ¤   int writetrust;
3a6032 ¤   RingPool *pool = set->pool;
020040 ¤   PGPError err;
4aaf5a
46e6fe ¤   pgpAssert(set);
4fd420 ¤   pgpAssert(f);
a2af5a
fc14fb ¤   pgpVirtMaskInit (pool, &mask);
84af5a
21800e ¤   if (filep) {
67dd2d ¤   ¤   /* Set up a RingFile to add to */
b5eeba ¤   ¤   pgpAssert(f);
58af5a
374568 ¤   ¤   err = ringBitAlloc(set->pool, &bit);
80044d ¤   ¤   if (IsPGPError(err)) {
262e10 ¤   ¤   ¤   *filep = (RingFile *)0;
570892 ¤   ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
3fb32f ¤   ¤   ¤   return err;
a40fe4 ¤   ¤   }
5eaf5a
4f5f57 ¤   ¤   /* Make sure enough pool->files entries are allocated */
ab978b ¤   ¤   ringFilesInit (set->pool, bit);
2faf5a
95b580 ¤   ¤   file = set->pool->files[bit];
87949b ¤   ¤   pgpVirtMaskSetBit (pool, &mask, bit);
b5d293 ¤   ¤   pgpAssert(pgpVirtMaskIsEqual (&file->set.mask, &mask));
a1269d ¤   ¤   pgpAssert(!pgpVirtMaskIsOverlapping (&pool->filemask, &mask));
ceaf5a
a73225 ¤   ¤   pgpVirtMaskOR (pool, &mask, &pool->filemask);
73212c ¤   ¤   pgpVirtMaskOR (pool, &mask, &pool->allocmask);
e8af5a
f715f4 ¤   ¤   /* Set this file as the lowest-priority file */
2a50ee ¤   ¤   ringFileLowPri(file);
89af5a
0390fc ¤   ¤   pgpAssert(!file->set.next);
03af5a
b1371d ¤   ¤   file->f = f;
92af11 ¤   ¤   file->destructor = NULL;¤   /* May be set later */
611ef7 ¤   ¤   file->arg = 0;
f40a43 ¤   ¤   *filep = NULL;¤ /* For now, to be fixed later */
bdf037 ¤   } else {
ce14c5 ¤   ¤   file = NULL;
ef9371 ¤   }
e5af5a
8ebf8d ¤   iter = ringIterCreate(set);
08f222 ¤   if (!iter) {
b5e963 ¤   ¤   ringFileClose(file);¤   /* Okay for file to be NULL */
563157 ¤   ¤   pgpVirtMaskCleanup (pool, &mask);
76e1c3 ¤   ¤   return ringSetError(set)->error;
409371 ¤   }
f8af5a
cb27b6 ¤   /* Okay, the main loop */
6d55a5 ¤   level = 1;
39153e ¤   writetrust = 0;¤/* Silence warnings */
9caf5a
71ea31 ¤   while ((i = ringIterNextObjectAnywhere(iter)) > 0) {
5ee413 ¤   ¤   obj = ringIterCurrentObject(iter, (unsigned)i);
f18146 ¤   ¤   keyobj = NULL;
3fb271 ¤   ¤   pgpAssert(obj);
ab17f8 ¤   ¤   if (OBJISKEY(obj)) {
42f797 ¤   ¤   ¤   writetrust = flags & PGP_RINGSETWRITE_PUBTRUST;
28e5c9 ¤   ¤   ¤   sec = ringBestSec(set, obj);
a95f7b ¤   ¤   ¤   if (sec) {
3b101c ¤   ¤   ¤   ¤   keyobj = obj;
44797d ¤   ¤   ¤   ¤   obj = sec;¤ /* Write out the sec */
2d50ba ¤   ¤   ¤   ¤   if (OBJISTOP(obj))
ee2182 ¤   ¤   ¤   ¤   ¤   writetrust = flags&PGP_RINGSETWRITE_SECTRUST;
62a3a6 ¤   ¤   ¤   }
0d4ab8 ¤   ¤   } else if (OBJISSEC(obj)) {
6917f5 ¤   ¤   ¤   continue;
a4a11e ¤   ¤   } else if (OBJISSIG(obj) && !flags && !SIGISEXPORTABLE(&obj->s)) {
--947f 000e9a246bd40100201 Page 60 of pgpRngRead.c
61aa38 ¤   ¤   ¤   /* Don't output non-exportable sigs to untrusted sets */
5017f5 ¤   ¤   ¤   continue;
e70fe4 ¤   ¤   }
dfe1e8 ¤   ¤   i = ringCopyObject(set, obj, keyobj, f, writetrust, version, file);
57ad75 ¤   ¤   if (i < 0)
a0cdcb ¤   ¤   ¤   break;
d165ff ¤   } /* while ringIternextObjectAnywhere */
2a1d89 ¤   ringIterDestroy(iter);
a867c5 ¤
3ed8af ¤   /*
e65a9f ¤   ·* If we broke out on error, close the output file. ·We could leave
c8ea40 ¤   ·* the partial file open, as all the pointers that exist are valid.
db4be5 ¤   ·* Is that useful?
86a4e3 ¤   ·*/
e10a3f ¤   if (i < 0 && file)
48a8d1 ¤   ¤   ringFileClose(file);
d9050d ¤   else if (filep)
3b58a2 ¤   ¤   *filep = file;
6aaf5a
0d0db9 ¤   pgpVirtMaskCleanup (pool, &mask);
e8af5a
e8d634 ¤   return (PGPError)i;
27efe6 }
aeaf5a
7aaf5a
0e38e5 /*
a0b6fc ·* Bring an object into the MEMRING.
62495d ·*/
fabeb7 static int
478ffb ringCacheObject(RingSet *set, union RingObject *obj)
20bb36 {
d6d259 ¤   PGPByte *buf;
40a406 ¤   PGPByte const *pktbuf;
3d2ad9 ¤   PGPSize buflen;
50ecb0 ¤   MemPool cut;
8dff7f ¤   RingFile *file;
c117e6 ¤   int err;
35af5a
43c499 ¤   /* Do nothing if already there */
cd6792 ¤   if (pgpVirtMaskIsOverlapping(&obj->g.mask, &set->pool->memringmask)) {
05bbde ¤   ¤   return 0;
fd9371 ¤   }
4f67c5 ¤
1596d3 ¤   /* Get the object into the pktbuf */
f04082 ¤   pktbuf = (PGPByte const *)ringFetchObject (set, obj, &buflen);
eef9c8 ¤   if (!pktbuf) {
49e1c3 ¤   ¤   return ringSetError(set)->error;
9e9371 ¤   }
6767c5 ¤
41cd51 ¤   /* Allocate space in memory ringfile */
689f2b ¤   file = set->pool->files[MEMRINGBIT];
62aead ¤   cut = file->strings;
e918b7 ¤   buf = (PGPByte *)memPoolAlloc(&file->strings, (unsigned)buflen, 1);
363686 ¤   if (!buf) {
3c4030 ¤   ¤   return kPGPError_OutOfMemory;
a69371 ¤   }
c8af5a
734331 ¤   /* Copy to memory file buffer */
a74aee ¤   pgpCopyMemory( pktbuf, buf, buflen );
b4af5a
33c2c0 ¤   /* Add the FilePos */
210cf0 ¤   err = ringAddPos(obj, file, (PGPUInt32)buflen);
a539d0 ¤   if (err < 0) {
5ea6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
32e1c3 ¤   ¤   return ringSetError(set)->error;
9f9371 ¤   }
06b5f8 ¤   ringFilePos(obj, file)->ptr.buf = buf;
bfaf5a
ac3e6b ¤   return 0;
81efe6 }
9daf5a
e938e5 /*
--d9b7 0009fbc03e540100201 Page 61 of pgpRngRead.c
d0307a ·* Bring the ancestors of an object into the MEMRING.
9e775e ·*
37eff5 ·* When we create a new object using the routines below, it is necessary
5856ef ·* that any parents of the object be brought into the MEMRING. ·This is
5dfe5b ·* so that we can maintain our global invariant that all of an object's
ae8de2 ·* ancestors are in all sets that the object is in.
12495d ·*/
08beb7 static int
750f4b ringCacheParents (RingSet *set, union RingObject *obj)
2cbb36 {
1617e6 ¤   int err;
4caf5a
9aec8f ¤   if (OBJISTOP(obj)) {
b7bbde ¤   ¤   return 0;
629371 ¤   }
e4af5a
b943ab ¤   do {
4f5f84 ¤   ¤   obj = obj->g.up;
d3c5a5 ¤   ¤   err = ringCacheObject(set, obj);
12e48b ¤   ¤   if (err < 0)
6fb32f ¤   ¤   ¤   return err;
bfe0ce ¤   } while (!OBJISTOP(obj));
4c67c5 ¤
393e6b ¤   return 0;
d0efe6 }
3faf5a
2daf5a
dc38e5 /*
5f775e ·*
3a502f ·* Create a new name in a mutable RingSet.
b1775e ·*
2b495d ·*/
c4614e union RingObject *
6768fc ringCreateName(RingSet *dest, union RingObject *key,
1541a2 ¤   char const *str, size_t len)
76bb36 {
c4c4f6 ¤   RingIterator iter;
66ecb0 ¤   MemPool cut;
1eff7f ¤   RingFile *file;
fe0e1e ¤   PGPByte *pktbuf, *buf;
2a4ba4 ¤   int i;
59af5a
b7e3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
d094a2 ¤   pgpAssert(OBJISKEY(key));
8431df ¤   pgpAssert(pgpIsRingSetMember(dest, key));
a4af5a
9c217d ¤   iter.set = *dest;
42af5a
82eff7 ¤   if (len >= RINGNAME_MAXLEN) {
8efc9a ¤   ¤   ringSimpleErr(dest->pool, kPGPError_TroubleNameTooBig);
d57ed2 ¤   ¤   return NULL;
6a9371 ¤   }
33af5a
5725f3 ¤   pktbuf = (PGPByte *)ringReserve(dest->pool, len);
caf9c8 ¤   if (!pktbuf) {
1608c6 ¤   ¤   ringAllocErr(dest->pool);
df7ed2 ¤   ¤   return NULL;
e29371 ¤   }
baaf5a
46179c ¤   /* Add to memory file */
9bfdc5 ¤   file = dest->pool->files[MEMRINGBIT];
76aead ¤   cut = file->strings;
e6b5cd ¤   /* Allocate an extra byte in buf so we can put a null after name */
ff1140 ¤   buf = (PGPByte *)memPoolAlloc(&file->strings, (unsigned)len+1, 1);
943686 ¤   if (!buf) {
ce08c6 ¤   ¤   ringAllocErr(dest->pool);
e77ed2 ¤   ¤   return NULL;
0f9371 ¤   }
dcaf5a
ff419c ¤   pgpCopyMemory( str, pktbuf, len );
edbba4 ¤   dest->pool->pktbuflen = len;
9f453a ¤   iter.stack[0] = key;
--4639 000c251cfd540100201 Page 62 of pgpRngRead.c
1c36e4 ¤   iter.level = 1;
d8ff18 ¤   i = ringAddName(file, &iter, (PGPUInt32)len, FALSE);
cbffce ¤   pgpAssert(i < 0 || iter.level == 2);¤   /* error or object created */
62af5a
913bcc ¤   /* ringAddName returns <0 on error, and >0 on duplicate!·
106e08 ¤   ···Note: ·"Duplicate" means it's already on the memring,
eb4c8c ¤   ···*not* that it's already on dest. ·ringAddName adds
cf76a8 ¤   ···it to dest, so we can't easily check to see if it's a·
d64930 ¤   ···real duplicate. */
18535c ¤   if (i != 0) {
91a6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
e267b5 ¤   ¤   return i < 0 ? NULL : iter.stack[1];·
a49371 ¤   }
eaaf5a
94b45f ¤   /* Make sure name's parent key is in the MEMRING too */
c0303e ¤   i = ringCacheParents(dest, iter.stack[1]);
587a6f ¤   if (i < 0) {
56a6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
417ed2 ¤   ¤   return NULL;
e79371 ¤   }
0faf5a
f062fa ¤   /* Okay, success - we can't fail */
fed8af ¤   /*
e251ed ¤   ·* Remember that the memory pool's FilePos pointers are a bit
11ee65 ¤   ·* wierd. ·Instead of pos->ptr.next, we have pos->ptr.buf,
3cf081 ¤   ·* a pointer to a buffer holding the object. ·And pos->fpos
42fcf4 ¤   ·* is the length of the object. ·That is already filled in
1e95ba ¤   ·* by ringAddName(), but the ptr->buf needs to be done
644614 ¤   ·* explicitly. ·(The ringAddName() code is optimized for
88bbd1 ¤   ·* the reading-from-a-file case, since that's by far the
29267d ¤   ·* most common one.)
41a4e3 ¤   ·*/
ba3cdd ¤   pgpCopyMemory( str, buf, len );
d5784c ¤   buf[len] = '\0';¤   ¤   ¤   /* null after name in memory */
6c01a5 ¤   ringFilePos(iter.stack[1], file)->ptr.buf = buf;
ffaf5a
180ddb ¤   /* Ta-dah! */
7d696f ¤   return iter.stack[1];
40efe6 }
a9af5a
5138e5 /*
10775e ·*
b09271 ·* Create a new attribute object (variant of Name) in a mutable RingSet.
21775e ·*
61495d ·*/
ec614e union RingObject *
1fbf8e ringCreateAttribute(RingSet *dest, union RingObject *key,
f4a413 ¤   ¤   ¤   ¤   ¤   PGPByte attributeType, PGPByte const *data, size_t len)
82bb36 {
10c4f6 ¤   RingIterator iter;
bcecb0 ¤   MemPool cut;
ccff7f ¤   RingFile *file;
560e1e ¤   PGPByte *pktbuf, *buf;
728ad4 ¤   PGPSize totallen;
924ba4 ¤   int i;
9baf5a
71e3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
9694a2 ¤   pgpAssert(OBJISKEY(key));
6231df ¤   pgpAssert(pgpIsRingSetMember(dest, key));
97af5a
3b217d ¤   iter.set = *dest;
faaf5a
b4eff7 ¤   if (len >= RINGNAME_MAXLEN) {
2efc9a ¤   ¤   ringSimpleErr(dest->pool, kPGPError_TroubleNameTooBig);
bd7ed2 ¤   ¤   return NULL;
cf9371 ¤   }
dcaf5a
60d543 ¤   totallen = len + 1;¤¤   /* account for attribute type */
d97d53 ¤   totallen += pktSubpacketByteLen (totallen);
dbaf5a
4c34a7 ¤   pktbuf = (PGPByte *)ringReserve(dest->pool, totallen);
c2f9c8 ¤   if (!pktbuf) {
--fbd3 0006c8bce8540100201 Page 63 of pgpRngRead.c
da08c6 ¤   ¤   ringAllocErr(dest->pool);
5b7ed2 ¤   ¤   return NULL;
7e9371 ¤   }
57af5a
98179c ¤   /* Add to memory file */
37fdc5 ¤   file = dest->pool->files[MEMRINGBIT];
2baead ¤   cut = file->strings;
c9d4b4 ¤   buf = (PGPByte *)memPoolAlloc(&file->strings, totallen, 1);
e23686 ¤   if (!buf) {
5108c6 ¤   ¤   ringAllocErr(dest->pool);
0a7ed2 ¤   ¤   return NULL;
3a9371 ¤   }
9caf5a
a42dbb ¤   pktSubpacketCreate (attributeType, data, len, pktbuf);
89af5a
4ff679 ¤   /* ringCacheParents corrupts pktbuf, so copy to buf here */
60036a ¤   pgpCopyMemory( pktbuf, buf, totallen );
edaf5a
518958 ¤   dest->pool->pktbuflen = totallen;
dd453a ¤   iter.stack[0] = key;
9f36e4 ¤   iter.level = 1;
c96fd9 ¤   i = ringAddName(file, &iter, totallen, TRUE);
0effce ¤   pgpAssert(i < 0 || iter.level == 2);¤   /* error or object created */
21af5a
583bcc ¤   /* ringAddName returns <0 on error, and >0 on duplicate!·
426e08 ¤   ···Note: ·"Duplicate" means it's already on the memring,
454c8c ¤   ···*not* that it's already on dest. ·ringAddName adds
fb76a8 ¤   ···it to dest, so we can't easily check to see if it's a·
654930 ¤   ···real duplicate. */
83535c ¤   if (i != 0) {
aea6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
8c67b5 ¤   ¤   return i < 0 ? NULL : iter.stack[1];·
8b9371 ¤   }
22af5a
68b45f ¤   /* Make sure name's parent key is in the MEMRING too */
f1303e ¤   i = ringCacheParents(dest, iter.stack[1]);
217a6f ¤   if (i < 0) {
ada6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
0f7ed2 ¤   ¤   return NULL;
c99371 ¤   }
c5af5a
6162fa ¤   /* Okay, success - we can't fail */
6bd8af ¤   /*
7e51ed ¤   ·* Remember that the memory pool's FilePos pointers are a bit
c8ee65 ¤   ·* wierd. ·Instead of pos->ptr.next, we have pos->ptr.buf,
3bf081 ¤   ·* a pointer to a buffer holding the object. ·And pos->fpos
84fcf4 ¤   ·* is the length of the object. ·That is already filled in
b095ba ¤   ·* by ringAddName(), but the ptr->buf needs to be done
3b4614 ¤   ·* explicitly. ·(The ringAddName() code is optimized for
90bbd1 ¤   ·* the reading-from-a-file case, since that's by far the
96267d ¤   ·* most common one.)
98a4e3 ¤   ·*/
e001a5 ¤   ringFilePos(iter.stack[1], file)->ptr.buf = buf;
76af5a
4c0ddb ¤   /* Ta-dah! */
5a696f ¤   return iter.stack[1];
06efe6 }
43af5a
e138e5 /*
d214b6 ·* Create a new signature object in a mutable RingSet.
0a495d ·*/
90614e union RingObject *
9d2f3c ringCreateSig(RingSet *dest, union RingObject *obj,
f0ce94 ¤   PGPByte *sig, size_t siglen)
14bb36 {
afc4f6 ¤   RingIterator iter;
64ecb0 ¤   MemPool cut;
48ff7f ¤   RingFile *file;
941f60 ¤   union RingObject *newsig;
320e1e ¤   PGPByte *pktbuf, *buf;
8d4ba4 ¤   int i;
6caf5a
--91a8 000aec0f51940100201 Page 64 of pgpRngRead.c
83e3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
f4ebf4 ¤   pgpAssert(pgpIsRingSetMember(dest, obj));
6daf5a
f4217d ¤   iter.set = *dest;
d24e0d ¤   iter.set.type = RINGSET_ITERATOR; /* kludge for ringIterSeekTo() */
69af5a
7f9fa0 ¤   i = ringIterSeekTo(&iter, obj);
deb59a ¤   pgpAssert(i >= 0);
31af5a
b1b1d4 ¤   if (siglen >= RINGSIG_MAXLEN) {
82c197 ¤   ¤   ringSimpleErr(dest->pool, kPGPError_TroubleSignatureTooBig);
377ed2 ¤   ¤   return NULL;
4f9371 ¤   }
2daf5a
2da6cd ¤   pktbuf = (PGPByte *)ringReserve(dest->pool, siglen);
d4f9c8 ¤   if (!pktbuf) {
ff08c6 ¤   ¤   ringAllocErr(dest->pool);
847ed2 ¤   ¤   return NULL;
569371 ¤   }
7baf5a
86179c ¤   /* Add to memory file */
43fdc5 ¤   file = dest->pool->files[MEMRINGBIT];
91aead ¤   cut = file->strings;
a537a7 ¤   buf = (PGPByte *)memPoolAlloc(&file->strings, (unsigned)siglen, 1);
293686 ¤   if (!buf) {
ff08c6 ¤   ¤   ringAllocErr(dest->pool);
887ed2 ¤   ¤   return NULL;
8e9371 ¤   }
41af5a
4af822 ¤   pgpCopyMemory( sig, pktbuf, siglen );
1e4af6 ¤   dest->pool->pktbuflen = siglen;
f7db6d ¤   i = ringAddSig(file, &iter, (PGPUInt32)siglen, 1);
eed4fc ¤   newsig = iter.stack[iter.level - 1];
3eaf5a
8d1ca5 ¤   /* ringAddSig returns <0 on error, and >0 on duplicate! */
60535c ¤   if (i != 0) {
fea6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
31e173 ¤   ¤   return i < 0 ? NULL : newsig;
929371 ¤   }
adaf5a
446e9f ¤   /* Make sure sig's parent objects are in the MEMRING too */
44fdbc ¤   i = ringCacheParents(dest, newsig);
f37a6f ¤   if (i < 0) {
57a6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
9d7ed2 ¤   ¤   return NULL;
a79371 ¤   }
81af5a
b762fa ¤   /* Okay, success - we can't fail */
b6d8af ¤   /*
f651ed ¤   ·* Remember that the memory pool's FilePos pointers are a bit
f0ee65 ¤   ·* wierd. ·Instead of pos->ptr.next, we have pos->ptr.buf,
69f081 ¤   ·* a pointer to a buffer holding the object. ·And pos->fpos
5afcf4 ¤   ·* is the length of the object. ·That is already filled in
ee95ba ¤   ·* by ringAddName(), but the ptr->buf needs to be done
454614 ¤   ·* explicitly. ·(The ringAddName() code is optimized for
10bbd1 ¤   ·* the reading-from-a-file case, since that's by far the
a1267d ¤   ·* most common one.)
e3a4e3 ¤   ·*/
48265a ¤   pgpCopyMemory( sig, buf, siglen );
bf0d6d ¤   ringFilePos(newsig, file)->ptr.buf = buf;
48af5a
0012fb ¤   return newsig;
cfefe6 }
06af5a
6caf5a
5638e5 /*
973bc4 ·* Create a new public key in a mutable RingSet. ·To create a
8eeed0 ·* public/secret key pair, use ringCreateSec. ·That is normally
a0d970 ·* the routine to use, not this one.
30495d ·*/
2c614e union RingObject *
ae2c30 ringCreateKey(RingSet *dest, union RingObject *parent,
--eee4 000e7b3f59840100201 Page 65 of pgpRngRead.c
402cd3 ¤   PGPPubKey const *key, PGPKeySpec const *ks, PGPByte pkalg)
31bb36 {
f8c4f6 ¤   RingIterator iter;
acecb0 ¤   MemPool cut;
55ff7f ¤   RingFile *file;
bbf3ba ¤   union RingObject *newkey;
300e1e ¤   PGPByte *pktbuf, *buf;
3f1a96 ¤   size_t len, prefixlen;
b56760 ¤   PGPByte pkttype;
154ba4 ¤   int i;
09af5a
12e3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
9d67c5 ¤
870ca2 ¤   prefixlen = ringKeyBufferLength(ks, pkalg);
ee825b ¤   len = prefixlen + pgpPubKeyBufferLength(key);
e8d604 ¤   if (len >= RINGKEY_MAXLEN) {
7d578b ¤   ¤   ringSimpleErr(dest->pool, kPGPError_TroubleKeyTooBig);
627ed2 ¤   ¤   return NULL;
8a9371 ¤   }
a7af5a
216a9e ¤   /* Add to pktbuf for compatibility with other routines */
4325f3 ¤   pktbuf = (PGPByte *)ringReserve(dest->pool, len);
4ff9c8 ¤   if (!pktbuf) {
c708c6 ¤   ¤   ringAllocErr(dest->pool);
377ed2 ¤   ¤   return NULL;
139371 ¤   }
b6af5a
36f13a ¤   ringKeyToBuffer(pktbuf, ks, pkalg);
10cead ¤   pgpPubKeyToBuffer(key, pktbuf+prefixlen);
0ebba4 ¤   dest->pool->pktbuflen = len;
9baf5a
2db1a8 ¤   /* Add to memory file as permanent home for data */
d1fdc5 ¤   file = dest->pool->files[MEMRINGBIT];
93aead ¤   cut = file->strings;
9ae608 ¤   buf = (PGPByte *)memPoolAlloc(&file->strings, (unsigned)len, 1);
633686 ¤   if (!buf) {
0308c6 ¤   ¤   ringAllocErr(dest->pool);
467ed2 ¤   ¤   return NULL;
f79371 ¤   }
1b583c ¤   pgpCopyMemory( pktbuf, buf, len );
14af5a
7f1b06 ¤   /* Set iter to point at beginning */
03217d ¤   iter.set = *dest;
4aa0a5 ¤   if (parent) {
973f28 ¤   ¤   iter.stack[0] = parent;
804c10 ¤   ¤   iter.level = 1;
43f037 ¤   } else {
5e16cc ¤   ¤   iter.level = 0;
459371 ¤   }
7567c5 ¤
4cf1eb ¤   pkttype = parent ? PKTBYTE_PUBSUBKEY : PKTBYTE_PUBKEY;
70af5a
beb925 ¤   i = ringAddKey(file, &iter, (PGPUInt32)len, 1/*trusted*/, pkttype);
f5af5a
85661f ¤   /* ringAddKey returns <0 on error, and >0 on duplicate! */
47ef13 ¤   pgpAssert(i < 0 || (int)iter.level == 1 + (parent != NULL));
a0af5a
b7535c ¤   if (i != 0) {
5ea6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
31fd40 ¤   ¤   return i < 0 ? NULL : iter.stack[1];
cd9371 ¤   }
fb67c5 ¤
f20455 ¤   /* Set buffer pointer in FilePos */
9704a7 ¤   newkey = iter.stack[0];
7bb43d ¤   pgpAssert(OBJISKEY(newkey));
ce893d ¤   ringFilePos(newkey, file)->ptr.buf = buf;
7caf5a
2cbbf1 ¤   /* Put key into right place in key ring (sorted by keyID) */
a256b6 ¤   ringSortKeys(file->set.pool);
08af5a
03fe21 ¤   return newkey;
e7efe6 }
--b4ac 000e8ee292640100201 Page 66 of pgpRngRead.c
e0af5a
1aaf5a
9938e5 /*
40500b ·* Create a new public/secret keypair. ·Return pointer to the RingKey object,
1135c5 ·* which will be followed by a RingSec.
74495d ·*/
5c614e union RingObject *
2e9bc7 ringCreateSec(RingSet *dest, union RingObject *parent,
42ed68 ¤   PGPSecKey const *sec, PGPKeySpec const *ks, PGPByte pkalg)
12bb36 {
37c4f6 ¤   RingIterator iter;
ebecb0 ¤   MemPool cut;
99ff7f ¤   RingFile *file;
e63876 ¤   union RingObject *newkey, *newsec;
7d0e1e ¤   PGPByte *pktbuf, *buf;
641a96 ¤   size_t len, prefixlen;
8d6760 ¤   PGPByte pkttype;
544ba4 ¤   int i;
bdaf5a
0fe3d6 ¤   pgpAssert(RINGSETISMUTABLE(dest));
4d67c5 ¤
59b083 ¤   prefixlen = ringSecBufferLength(ks, pkalg);
e4e7ed ¤   len = prefixlen + pgpSecKeyBufferLength(sec);
93f23f ¤   if (len >= RINGSEC_MAXLEN) {
b2e82a ¤   ¤   ringSimpleErr(dest->pool, kPGPError_TroubleSecretKeyTooBig);
517ed2 ¤   ¤   return NULL;
999371 ¤   }
56af5a
7b6a9e ¤   /* Add to pktbuf for compatibility with other routines */
0425f3 ¤   pktbuf = (PGPByte *)ringReserve(dest->pool, len);
91f9c8 ¤   if (!pktbuf) {
8f08c6 ¤   ¤   ringAllocErr(dest->pool);
0d7ed2 ¤   ¤   return NULL;
659371 ¤   }
c9af5a
f24d33 ¤   ringSecToBuffer(pktbuf, ks, pkalg);
5ffc91 ¤   pgpSecKeyToBuffer(sec, pktbuf+prefixlen);
a0bba4 ¤   dest->pool->pktbuflen = len;
07af5a
c2b1a8 ¤   /* Add to memory file as permanent home for data */
d4fdc5 ¤   file = dest->pool->files[MEMRINGBIT];
e7aead ¤   cut = file->strings;
86e608 ¤   buf = (PGPByte *)memPoolAlloc(&file->strings, (unsigned)len, 1);
5d3686 ¤   if (!buf) {
f508c6 ¤   ¤   ringAllocErr(dest->pool);
cc7ed2 ¤   ¤   return NULL;
2a9371 ¤   }
a0583c ¤   pgpCopyMemory( pktbuf, buf, len );
7aaf5a
e31b06 ¤   /* Set iter to point at beginning */
58217d ¤   iter.set = *dest;
64a0a5 ¤   if (parent) {
d13f28 ¤   ¤   iter.stack[0] = parent;
b14c10 ¤   ¤   iter.level = 1;
24f037 ¤   } else {
9616cc ¤   ¤   iter.level = 0;
3c9371 ¤   }
8aaf5a
f0516f ¤   pkttype = parent ? PKTBYTE_SECSUBKEY : PKTBYTE_SECKEY;
23af5a
68d8af ¤   /*
32244d ¤   ·* Clear trouble list so we can distinguish duplicate keys from
4cd199 ¤   ·* duplicate sigs
1ea4e3 ¤   ·*/
9402df ¤   ringFilePurgeTrouble(file);
3aaf5a
d2fe6a ¤   /* Create the secret object and the parent key */
afe78a ¤   i = ringAddSec(file, &iter, (PGPUInt32)len, pkttype);
1aaf5a
c54052 ¤   /* ringAddSec returns <0 on error, and >0 on duplicate! */
567d59 ¤   pgpAssert(i < 0 || (int)iter.level == 2 + (parent != NULL));
e8af5a
--d8ef 00029abb3fb40100201 Page 67 of pgpRngRead.c
bf4dd4 ¤   if (i > 0) {
e4dc43 ¤   ¤   RingTrouble const *trouble = ringFileTrouble(file);
964747 ¤   ¤   pgpAssert (trouble);
8e1b17 ¤   ¤   /*
59b720 ¤   ¤   ·* If this sec was a dup, just return it; if it was
6e1517 ¤   ¤   ·* something else it was probably a duplicate key and
ecfa1d ¤   ¤   ·* so we can ignore it and use the new mempool data
459de3 ¤   ¤   ·*/
16c78b ¤   ¤   if (trouble->type == kPGPError_TroubleDuplicateSecretKey) {
8fe9d3 ¤   ¤   ¤   memPoolCutBack(&file->strings, &cut);
57d733 ¤   ¤   ¤   return iter.stack[1];
330fe4 ¤   ¤   }
be9371 ¤   }
b67a6f ¤   if (i < 0) {
aea6ed ¤   ¤   memPoolCutBack(&file->strings, &cut);
417ed2 ¤   ¤   return NULL;
999371 ¤   }
6267c5 ¤
cc0455 ¤   /* Set buffer pointer in FilePos */
b36d58 ¤   newkey = iter.stack[iter.level-2];
d9b43d ¤   pgpAssert(OBJISKEY(newkey));
2cf49c ¤   newsec = iter.stack[iter.level-1];
ed03cb ¤   pgpAssert(OBJISSEC(newsec));
42893d ¤   ringFilePos(newkey, file)->ptr.buf = buf;
636b14 ¤   ringFilePos(newsec, file)->ptr.buf = buf;
7167c5 ¤
69bbf1 ¤   /* Put key into right place in key ring (sorted by keyID) */
0856b6 ¤   ringSortKeys(file->set.pool);
d2af5a
33fe21 ¤   return newkey;
e7efe6 }
f0af5a
4c38e5 /*
1d5b35 ·* Takes a name and moves it to the front of the list of names on a
228c4e ·* key. ·Normally ringCreateName puts the new name at the end; this can
8f0734 ·* move it up.
e9495d ·*/
d54d2f int
87194b ringRaiseName(RingSet *dest, union RingObject *name)
10bb36 {
2fb957 ¤   union RingObject *key;
699c77 ¤   union RingObject **np, **np1;
36af5a
34ff0b ¤   pgpAssert (RINGSETISMUTABLE(dest));
e69c88 ¤   pgpAssert (OBJISNAME(name));
7b49ba ¤   pgpAssert (pgpIsRingSetMember(dest, name));
2cceb7 ¤   pgpAssert (!OBJISTOP(name));
002582 ¤   key = name->g.up;
09c2a6 ¤   pgpAssert (OBJISKEY(key));
2867c5 ¤
15328d ¤   /* Guaranteed to hit at least one name, ours */
12ef90 ¤   np = &key->g.down;
172e8b ¤   while (!pgpIsRingSetMember(dest, *np) ·&& ·OBJISNAME(*np)) {
9ec5b4 ¤   ¤   np = &(*np)->g.next;
079371 ¤   }
77af5a
f5788e ¤   /* Continue till we hit pointer to our name */
9de9bd ¤   np1 = np;
de28ab ¤   while (*np1 != name)
59e1e8 ¤   ¤   np1 = &(*np1)->g.next;
c9af5a
6dbc80 ¤   /* Swap if not already first */
eaad0a ¤   if (np != np1) {
48572f ¤   ¤   *np1 = name->g.next;¤   /* Delete name from the list */
6a0f8d ¤   ¤   name->g.next = *np;¤/* Set its tail pointer as *np */
11859d ¤   ¤   *np = name;¤¤   /* Insert it in new spot */
349371 ¤   }
083e6b ¤   return 0;
04efe6 }
deaf5a
03af5a
2938e5 /*
--ec35 000fead081840100201 Page 68 of pgpRngRead.c
5f8e32 ·* Signs an object (and its parents); then deposits the new signature
655688 ·* object in place on the set.
9a495d ·*/
b0c744 ¤   PGPError
5ab1d9 ringSignObject(RingSet *set, union RingObject *obj,
f9513a ¤   ·······PGPSigSpec *spec, PGPRandomContext const *rc)
46bb36 {
eb6314 ¤   PGPByte *sig;
a752f1 ¤   int siglen;
336842 ¤   union RingObject *sigobj¤   = NULL;
bc840a ¤   PGPContextRef¤  cdkContext¤ = RingSetGetContext( set );
e99372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
88af5a
dcd8af ¤   /*
ce9d6a ¤   ·* Force signatures with newer-than-RSA keys to use version 4,
700653 ¤   ·* and also if the hash is newer than those supported by PGP 5.0.
4dd1ff ¤   ·* A bug in PGP 5.0 won't let it load keyrings using version 2.6 sigs
61dd43 ¤   ·* which have a hash not recognized by it. ·
9bb320 ¤   ·* The exception is revocation sigs on top-level keys. ·A different
03f23a ¤   ·* bug in PGP 5.0 won't let it validate V4 sigs on top-level keys.
da40a1 ¤   ·* The only sigs it tries to recognize on top-level keys are revocation
402f4b ¤   ·* sigs. ·So those we leave as V3.
48a4e3 ¤   ·*/
e09915 ¤   if( pgpSigSpecVersion (spec) == PGPVERSION_3 ) {
6250b5 ¤   ¤   PGPSecKey *seckey = pgpSigSpecSeckey (spec);
6d6b02 ¤   ¤   PGPByte pkAlg = seckey->pkAlg;
e5a875 ¤   ¤   PGPByte hashtype = pgpSigSpecHashtype (spec);
96ebe2 ¤   ¤   PGPByte const *extra = pgpSigSpecExtra (spec, NULL);
581318 ¤   ¤   if( ! (extra[0] == PGP_SIGTYPE_KEY_REVOKE && OBJISTOPKEY(obj)) ) {
0d6c4e ¤   ¤   ¤   if( pkAlg > kPGPPublicKeyAlgorithm_RSA + 2
535a00 ¤   ¤   ¤   ¤   ¤   ¤   || hashtype > kPGPHashAlgorithm_RIPEMD160 ) {
705e20 ¤   ¤   ¤   ¤   pgpSigSpecSetVersion( spec, PGPVERSION_4 );
39a3a6 ¤   ¤   ¤   }
c70fe4 ¤   ¤   }
609371 ¤   }
72af5a
9ab6fa ¤   siglen = pgpMakeSigMaxSize (spec);
e6d1f2 ¤   sig = (PGPByte *)pgpContextMemAlloc( cdkContext,
b198d7 ¤   ¤   siglen, kPGPMemoryMgrFlags_Clear);
2ec037 ¤   if ( IsntNull( sig ) )
4fc7a1 ¤   {
2b82f4 ¤   ¤   siglen = ringSignObj (sig, set, obj, spec, rc);
9def74 ¤   ¤   if (siglen < 0)
9f5b34 ¤   ¤   {
a2c93c ¤   ¤   ¤   pgpContextMemFree( cdkContext, sig);
9d8f9a ¤   ¤   ¤   return (PGPError)siglen;
810fe4 ¤   ¤   }
a5ff83 ¤   ¤   if (!siglen)
aa5b34 ¤   ¤   {
fec93c ¤   ¤   ¤   pgpContextMemFree( cdkContext, sig);
9a7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
b70fe4 ¤   ¤   }
67a878 ¤   ¤   sigobj = ringCreateSig (set, obj, sig, siglen);
7652b1 ¤   ¤   sigobj->s.trust = PGP_SIGTRUSTF_CHECKED_TRIED | kPGPKeyTrust_Complete;
98af5a
fe9ba1 ¤   ¤   pgpContextMemFree( cdkContext, sig);
169371 ¤   }
030e24 ¤   else
25c7a1 ¤   {
2317a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
b49371 ¤   }
5867c5 ¤
c9fc23 ¤   return sigobj ? kPGPError_NoErr : kPGPError_OutOfMemory;
e0efe6 }
36af5a
6538e5 /*
84bf02 ·* Given a seckey, two mutable ringsets, and some other information,
331156 ·* create the ring objects and put them on the appropriate ringsets.
16b400 ·* Then self-sign the pubkey.
d2495d ·*/
110eee RingObject *
fec07a ringCreateKeypair (PGPEnv const *env, PGPSecKey *seckey,
--049e 000bfe07a9540100201 Page 69 of pgpRngRead.c
b4ab87 ¤   ¤   ···PGPKeySpec *keyspec,
0b02fd ¤   ¤   ···char const *name, size_t namelen,
063739 ¤   ¤   ···PGPRandomContext const *rc,
11bec7 ¤   ¤   ···RingSet *pubset, RingSet *secset,
497dd9 ¤   ¤   ···RingSet const *rakset, PGPByte rakclass,
809e4d ¤   ¤   ···PGPByte *prefAlg, size_t prefAlgLength,
715640 ¤   ¤   ···RingSet const *adkset, PGPByte adkclass,
f8f254 ¤   ¤   ···PGPError *error)
c4bb36 {
9452f5 ¤   union RingObject *keyobj=NULL, *nameobj;
fe9f53 ¤   PGPSigSpec *sigspec = NULL;
e7fef1 ¤   RingIterator *rakIter = NULL;
7ca5cb ¤   RingIterator *adkIter = NULL;
806b1d ¤   PGPUInt16 validity;
11b006 ¤   int keyv4;
d7af5a
711a95 ¤   pgpAssert( error );
df9096 ¤   *error = kPGPError_NoErr;
c7af5a
d99e88 #define CHECKRETVAL(val, err) if (val) { *error = err; goto cleanup; }
07af5a
15ca12 ¤   /* SECRET KEY stuff */
a1af5a
7cd8af ¤   /*
8dc60a ¤   ·* If we ever create V4 RSA keys, rsaSecGenerate must
f06b59 ¤   ·* be updated as well to clear its v3 flag.
e3a4e3 ¤   ·*/
ca6a8c ¤   keyv4 = seckey->pkAlg > kPGPPublicKeyAlgorithm_RSA + 2;
db74a0 ¤   if (keyv4)
0d0d65 ¤   ¤   pgpKeySpecSetVersion (keyspec, PGPVERSION_4);
f927c1 ¤   keyobj = ringCreateSec (secset, NULL, seckey, keyspec, seckey->pkAlg);
0f83e9 ¤   CHECKRETVAL (!keyobj, kPGPError_OutOfMemory);
21c2a0 ¤   pgpAssert(OBJISKEY(keyobj));
535bea ¤   pgpCopyMemory( keyobj->k.keyID, seckey->keyID, sizeof(keyobj->k.keyID) );
51c084 ¤   nameobj = ringCreateName (secset, keyobj, name, namelen);
3e0b36 ¤   CHECKRETVAL (!nameobj, kPGPError_OutOfMemory);
dcaf5a
ede529 ¤   /* PUBLIC KEY stuff */
a22e27 ¤   *error = (PGPError)ringSetAddObject (pubset, keyobj);
fa2cf2 ¤   CHECKRETVAL (*error, *error);
983eb4 ¤   *error = (PGPError)ringSetAddObject (pubset, nameobj);
8a2cf2 ¤   CHECKRETVAL (*error, *error);
22af5a
b1b0bc ¤   /* Self-Sign the new pubkey */
edbc2a ¤   if (pgpKeyUse(pgpPkalgByNumber(seckey->pkAlg)) & PGP_PKUSE_SIGN) {
b9f51a ¤   ¤   sigspec = pgpSigSpecCreate (env, seckey,
8b340a ¤   ¤   ¤   ¤   ¤   ····PGP_SIGTYPE_KEY_GENERIC);
6accf2 ¤   ¤   CHECKRETVAL (!sigspec, kPGPError_OutOfMemory);
0710a0 ¤   ¤   if (keyv4) {
8c9455 ¤   ¤   ¤   /* New keys self-sign with special info! */
2d09ff ¤   ¤   ¤   static PGPByte defaultPrefAlg[] = {kPGPCipherAlgorithm_CAST5,
59886c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPCipherAlgorithm_IDEA,
b47231 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPCipherAlgorithm_3DES};
e267c6 ¤   ¤   ¤   if( IsntNull( prefAlg ) ) {
9494a2 ¤   ¤   ¤   ¤   pgpSigSpecSetPrefAlgs (sigspec, 0, prefAlg, prefAlgLength);
f5042d ¤   ¤   ¤   } else {
73436a ¤   ¤   ¤   ¤   pgpSigSpecSetPrefAlgs (sigspec, 0, defaultPrefAlg,
9559fe ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···sizeof(defaultPrefAlg));
38a3a6 ¤   ¤   ¤   }
e96973 ¤   ¤   ¤   pgpSigSpecSetVersion (sigspec, PGPVERSION_4);
ab6226 ¤   ¤   ¤   if ((validity=pgpKeySpecValidity (keyspec)) != 0) {
88e5cb ¤   ¤   ¤   ¤   pgpSigSpecSetKeyExpiration (sigspec, 0,
345fea ¤   ¤   ¤   ¤   ¤   (PGPUInt32)validity*24*60*60);
b187d0 ¤   ¤   ¤   ¤   keyobj->k.validity = validity;
32a3a6 ¤   ¤   ¤   }
989647 ¤   ¤   ¤   /* Add any additional decryption packets requested */
4af846 ¤   ¤   ¤   if (IsntNull (adkset) ) {
0763fd ¤   ¤   ¤   ¤   adkIter = ringIterCreate (adkset);
a82e1c ¤   ¤   ¤   ¤   if (!adkIter) {
9648a5 ¤   ¤   ¤   ¤   ¤   *error = ringSetError(adkset)->error;
9b3150 ¤   ¤   ¤   ¤   ¤   goto cleanup;
bf2613 ¤   ¤   ¤   ¤   }
--fde8 0006b261ad640100201 Page 70 of pgpRngRead.c
e0481f ¤   ¤   ¤   ¤   while (ringIterNextObject (adkIter, 1) > 0) {
9e4920 ¤   ¤   ¤   ¤   ¤   PGPByte adinfo[22];
2a8b60 ¤   ¤   ¤   ¤   ¤   RingObject *adkey = ringIterCurrentObject (adkIter, 1);
37213d ¤   ¤   ¤   ¤   ¤   adinfo[0] = adkclass;
046347 ¤   ¤   ¤   ¤   ¤   adinfo[1] = adkey->k.pkalg;
5a19e6 ¤   ¤   ¤   ¤   ¤   ringKeyFingerprint20 (adkset, adkey, adinfo+2);
c7a722 ¤   ¤   ¤   ¤   ¤   *error = pgpSigSpecSetAdditionalRecipientRequest (sigspec,
dcb58a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, adinfo, sizeof(adinfo) );
a88994 ¤   ¤   ¤   ¤   ¤   CHECKRETVAL (*error, *error);
ee2613 ¤   ¤   ¤   ¤   }
e55ae4 ¤   ¤   ¤   ¤   ringIterDestroy (adkIter);
4c912f ¤   ¤   ¤   ¤   adkIter = NULL;
24a3a6 ¤   ¤   ¤   }
870fe4 ¤   ¤   }
e7ae81 ¤   ¤   *error = ringSignObject (pubset, nameobj, sigspec, rc);
449d7c ¤   ¤   if (IsntPGPError(*error) && keyv4 && IsntNull (rakset)) {
1c623e ¤   ¤   ¤   /* Add any Revocation Authorization Keys requested */
ba1ded ¤   ¤   ¤   /* These go in a separate, irrevocable signature on the key */
b75c1d ¤   ¤   ¤   pgpSigSpecDestroy (sigspec);
1ba601 ¤   ¤   ¤   sigspec = pgpSigSpecCreate (env, seckey,
4edb86 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGP_SIGTYPE_KEY_PROPERTY);
22cbc9 ¤   ¤   ¤   CHECKRETVAL (!sigspec, kPGPError_OutOfMemory);
0adfde ¤   ¤   ¤   rakIter = ringIterCreate (rakset);
9e900f ¤   ¤   ¤   if (!rakIter) {
c710e8 ¤   ¤   ¤   ¤   *error = ringSetError(rakset)->error;
850658 ¤   ¤   ¤   ¤   goto cleanup;
d7a3a6 ¤   ¤   ¤   }
bb6894 ¤   ¤   ¤   while (ringIterNextObject (rakIter, 1) > 0) {
b40010 ¤   ¤   ¤   ¤   PGPByte krinfo[22];
7cca21 ¤   ¤   ¤   ¤   RingObject *krkey = ringIterCurrentObject (rakIter, 1);
e0c524 ¤   ¤   ¤   ¤   /* Note that rakclass must have 0x80 set to be effective */
7e2c7d ¤   ¤   ¤   ¤   krinfo[0] = rakclass;
281824 ¤   ¤   ¤   ¤   krinfo[1] = krkey->k.pkalg;
909869 ¤   ¤   ¤   ¤   ringKeyFingerprint20 (rakset, krkey, krinfo+2);
9960f3 ¤   ¤   ¤   ¤   *error = pgpSigSpecSetRevocationKey (sigspec, 0, krinfo,
b57c19 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(krinfo) );
23c6aa ¤   ¤   ¤   ¤   CHECKRETVAL (*error, *error);
54a3a6 ¤   ¤   ¤   }
fd808b ¤   ¤   ¤   ringIterDestroy (rakIter);
c1674b ¤   ¤   ¤   rakIter = NULL;
7b5888 ¤   ¤   ¤   /* Make this signature non-revocable */
94c227 ¤   ¤   ¤   pgpSigSpecSetRevocable (sigspec, 0, FALSE);
3b503a ¤   ¤   ¤   *error = ringSignObject (pubset, keyobj, sigspec, rc);
960fe4 ¤   ¤   }
839371 ¤   }
edaf5a
9df99b ¤   /* This sets both key and name trust */
39ac6c ¤   ringKeySetAxiomatic(secset, keyobj);
edaf5a
13702f ·cleanup:
f6a99c ¤   if (sigspec)
e859f0 ¤   ¤   pgpSigSpecDestroy (sigspec);
aa64c0 ¤   if (rakIter)
8ac178 ¤   ¤   ringIterDestroy (rakIter);
c6da32 ¤   if (adkIter)
4a155b ¤   ¤   ringIterDestroy (adkIter);
464022 ¤   return keyobj;
b3efe6 }
94af5a
55af5a
0038e5 /*
4dbf02 ·* Given a seckey, two mutable ringsets, and some other information,
4eef98 ·* create subkey ring objects and put them on the appropriate ringsets.
e5616c ·* Then sign the pubkey using the master signature key.
481938 ·* seckey is the secret key coresponding to the master signature key,
05b1f7 ·* subseckey is the secret key to be used for creating the new subkey.
20495d ·*/
0d0eee RingObject *
1939cc ringCreateSubkeypair (PGPEnv const *env, PGPSecKey *seckey,
1dd03e ¤   PGPSecKey *subseckey, PGPKeySpec *keyspec,
f44b45 ¤   PGPRandomContext const *rc,
6b28f1 ¤   RingSet *pubset, RingSet *secset,
--decb 001f317e68040100201 Page 71 of pgpRngRead.c
41a900 ¤   PGPError *error)
88bb36 {
094db9 ¤   union RingObject *keyobj;
ed7815 ¤   union RingObject *subkeyobj = NULL;
899f53 ¤   PGPSigSpec *sigspec = NULL;
4b6b1d ¤   PGPUInt16 validity;
1cb006 ¤   int keyv4;
0caf5a
a01a95 ¤   pgpAssert( error );
d49096 ¤   *error = kPGPError_NoErr;
eeaf5a
73d8af ¤   /*
0a1e2f ¤   ·* If we ever create PGPVERSION_4 (aka V4) RSA keys, rsaSecGenerate must
2f6b59 ¤   ·* be updated as well to clear its v3 flag.
a7a4e3 ¤   ·*/
d46a8c ¤   keyv4 = seckey->pkAlg > kPGPPublicKeyAlgorithm_RSA + 2;
a374a0 ¤   if (keyv4)
d90d65 ¤   ¤   pgpKeySpecSetVersion (keyspec, PGPVERSION_4);
30af5a
6e50d8 ¤   /* Get keyobj for the master key */
05ecb1 ¤   keyobj = ringKeyById8(secset, seckey->pkAlg, seckey->keyID);
994acb ¤   pgpAssert(keyobj);
67af5a
b90dc9 ¤   /* Create the subkey object on the secret keyring */
53a831 ¤   subkeyobj = ringCreateSec (secset, keyobj, subseckey,
cd8383 ¤   ¤   ¤   ¤   ······keyspec, subseckey->pkAlg);
169dff ¤   if (!subkeyobj) {
f9e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
897ed2 ¤   ¤   return NULL;
9c9371 ¤   }
9b479e ¤   pgpCopyMemory( subkeyobj->k.keyID, subseckey->keyID,
a590ec ¤   ·······sizeof(subkeyobj->k.keyID) );
4faf5a
6cbfe1 ¤   /* Add it to the public keyring */
69ec8e ¤   *error = (PGPError)ringSetAddObject (pubset, subkeyobj);
255842 ¤   if (*error)
fe7ed2 ¤   ¤   return NULL;
edaf5a
a7051c ¤   /* Sign the encryption key with the master signature key */
90a3f1 ¤   sigspec = pgpSigSpecCreate (env, seckey, PGP_SIGTYPE_KEY_SUBKEY);
bf7b20 ¤   if (!sigspec) {
e8e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
1d7ed2 ¤   ¤   return NULL;
4c9371 ¤   }
90512b ¤   if (keyv4) {
3baa6b ¤   ¤   /* New keys self-sign with special info */
5ba63a ¤   ¤   if ((validity=pgpKeySpecValidity (keyspec)) != 0) {
0e6973 ¤   ¤   ¤   pgpSigSpecSetVersion (sigspec, PGPVERSION_4);
c3b067 ¤   ¤   ¤   pgpSigSpecSetKeyExpiration (sigspec, 0,
a12540 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt32)validity*24*3600);
04bcb9 ¤   ¤   ¤   subkeyobj->k.validity = validity;
940fe4 ¤   ¤   }
229371 ¤   }
6d537c ¤   *error = ringSignObject (pubset, subkeyobj, sigspec, rc);
9f5842 ¤   if (*error)
6a48b9 ¤   ¤   goto cleanup;
d17c22 ¤   ringKeySetAxiomatic(secset, subkeyobj);
b3af5a
4968cb cleanup:
a0af5a
3ba99c ¤   if (sigspec)
0259f0 ¤   ¤   pgpSigSpecDestroy (sigspec);
6eaf5a
461d5b ¤   return subkeyobj;¤  ¤   /* success */
f3efe6 }
--9359 000f7339eb240100202 Page 1 of pgpRngRead.h
bc38e5 /*
f9ecb6 ·* $Id: pgpRngRead.h,v 1.25 1998/06/19 19:08:21 hal Exp $
82495d ·*/
dbaf5a
409a26 #ifndef Included_pgpRngRead_h
10ce12 #define Included_pgpRngRead_h
c8af5a
3764bd #include <stdio.h>¤ /* For size_t */
c4af5a
fbd11f #include "pgpUsuals.h"
75af5a
fb99c6 PGP_BEGIN_C_DECLARATIONS
c6af5a
3aadb8 #include "pgpOpaqueStructs.h"
b0af5a
19f786 /* Semi-public (you can use this, but probably don't want to) */
cd7d6e void const ·*
f93582 ringFetchObject(RingSet const *set, union RingObject *obj,
f0ab14 ¤   PGPSize *lenp);
ddaf5a
f07d66 /* Public */
c4af5a
5eef24 RingFile ·*ringFileOpen(RingPool *pool,
51696d ¤   PGPFile *f, int trusted, PGPError *error);
fc3266 void ·ringFileSetDestructor(RingFile *file,
84be7c ¤   void (*destructor)(RingFile *, PGPFile *, void *),
f1c1bc ¤   void *arg);
d6af5a
a94c07 void ·ringFileHighPri(RingFile *file);
c2be5b void ·ringFileLowPri(RingFile *file);
fdaf5a
e6d4dd struct RingTrouble {
2e40e9 ¤   struct RingTrouble const *next;
9b0a57 ¤   union RingObject *obj;¤ /* The pertinent object, if applicable */
0bd16d ¤   PGPUInt32 num;¤ /* An integer parameter, if applicable */
60892a ¤   PGPUInt32 fpos;¤/* File position related to the error */
13031a ¤   int type;¤  /* kPGPError_ code from pgpErrors.h */
a082f7 };
01af5a
4caf5a
eaf78d RingTrouble const ·*ringFileTrouble(
2fe333 ¤   RingFile const *file);
5eb365 void ·ringFilePurgeTrouble(RingFile *file);
b4af5a
1b0534 int ·ringFileCheckClose(RingFile const *file);
b40a85 PGPError ·ringFileClose(RingFile *file);
9baf5a
1fce3e #define PGP_RINGSETWRITE_PUBTRUST¤  ¤   1
6d3de5 #define PGP_RINGSETWRITE_SECTRUST¤  ¤   2
37dc05 #define PGP_RINGSETWRITE_EXPORTSIGS¤¤   4
d668f2 PGPError ·ringSetWrite(RingSet const *set, PGPFile *f,
1ee738 ¤   ¤   ¤   RingFile **filep, PgpVersion version, int flags);
feaf5a
5a3f04 char *ringReserve(RingPool *pool, size_t len);
6deaad int ringNamesDiffer(RingSet const *set, union RingObject *name1,
dc971e ¤   union RingObject *name2);
2caf5a
70841f union RingObject ·*ringCreateName(RingSet *dest,
6595dc ¤   union RingObject *key, char const *str, size_t len);
b7e02a union RingObject *ringCreateAttribute(RingSet *dest, union RingObject *key,
51e85e ¤   PGPByte attributeType, PGPByte const *data, size_t len);
4a58f7 union RingObject ·*ringCreateSig(RingSet *dest,
deaed1 ¤   union RingObject *obj, PGPByte *sig, size_t siglen);
d772a9 union RingObject ·*ringCreateKey(RingSet *dest,
815c2f ¤   union RingObject *parent, PGPPubKey const *key,
022ee5 ¤   PGPKeySpec const *ks, PGPByte pkalg);
5d1c2b union RingObject ·*ringCreateSec(RingSet *dest,
f11fea ¤   union RingObject *parent, PGPSecKey const *sec,
002ee5 ¤   PGPKeySpec const *ks, PGPByte pkalg);
fae4de int ·ringRaiseName(RingSet *dest, union RingObject *name);
76af5a
f7b1ad PGPError ·ringSignObject(RingSet *set, union RingObject *obj,
--152b 0017bfee5ae40100202 Page 2 of pgpRngRead.h
c43a60 ¤   ¤   ···PGPSigSpec *spec, PGPRandomContext const *rc);
95af5a
1680fc int keysdiffer(RingFile *file1, union RingObject const *key, int pktbyte);
d55d9d int namesdiffer(RingFile *file1, union RingObject const *name,
f0d6c0 ¤   ¤   ¤   PGPBoolean fAttribute);
151ef4 int sigsdiffer(RingFile *file1, union RingObject const *sig);
3ed5e5 int unkdiffer(RingFile *file1, union RingObject const *unk);
ccaf5a
83af5a
8b4239 union RingObject ·*ringCreateKeypair (PGPEnv const *env,
461c14 ¤   ¤   ·······PGPSecKey *seckey,
1810e8 ¤   ¤   ·······PGPKeySpec *keyspec,
85fc8d ¤   ¤   ·······char const *name, size_t namelen,
ac651f ¤   ¤   ·······PGPRandomContext const *rc,
b640b7 ¤   ¤   ·······RingSet *pubset, RingSet *secset,
a62875 ¤   ¤   ¤   ···RingSet const *rakset, PGPByte rakclass,
e08f6a ¤   ¤   ¤   ···PGPByte *prefAlg, size_t prefAlgLength,
f703ec ¤   ¤   ¤   ···RingSet const *adkset, PGPByte adkclass,
7baf25 ¤   ¤   ¤   ···PGPError *error);
c28ece union RingObject ·*ringCreateSubkeypair (PGPEnv const *env,
b7a136 ¤   ¤   ¤   ··PGPSecKey *seckey,
708769 ¤   ¤   ¤   ··PGPSecKey *subseckey,
916e05 ¤   ¤   ¤   ··PGPKeySpec *keyspec,
ac956b ¤   ¤   ¤   ··PGPRandomContext const *rc,
820abc ¤   ¤   ¤   ··RingSet *pubset, RingSet *secset,
f9e88a ¤   ¤   ¤   ··PGPError *error);
0faf5a
bc1254 PGP_END_C_DECLARATIONS
ebaf5a
7be275 #endif /* Included_pgpRngRead_h */
--c41b 000b9dd8e1540100203 Page 1 of pgpTrstPkt.c
bc38e5 /*
4e5399 ·* pgpTrust.c - manage translations of trust description strings
aede11 ·* for the maintenence display.
f5775e ·*
a768c2 ·* Written by Colin Plumb.
94775e ·*
1543d8 ·* $Id: pgpTrstPkt.c,v 1.2 1997/05/02 22:45:48 lloyd Exp $
da495d ·*/
08e2ff #include "pgpConfig.h"
d8af5a
b5324c #include <string.h>
33af5a
81ae6d #include "pgpTrstPkt.h"
c495a9 #include "pgpMemPool.h"
abaf5a
cfada1 #define USERTRANS(x) x
375528 #define userTrans(x) x
ecaf5a
2f0dea char const *keyTrustTable[14] = {
4e915f ¤   USERTRANS("undefined"),
67323c ¤   USERTRANS("unknown"),
8cfe1b ¤   USERTRANS("untrusted"),
5fd943 ¤   "<3>",
23e99f ¤   "<4>",
42088d ¤   USERTRANS("marginal"),
7bc339 ¤   USERTRANS("complete"),
bf9ba9 ¤   USERTRANS("ultimate"),
cc6060 /* Some special cases displayed in the same column */
45c8d1 ¤   "",
cbe7e0 ¤   USERTRANS("retired"),
14955b ¤   USERTRANS("revoked"),
de1364 ¤   USERTRANS("untested"),
43f422 ¤   USERTRANS("INVALID"),
b25331 ¤   USERTRANS("** BAD **")
bc82f7 };
53af5a
a6b264 char const *uidValidityTable[4] = {
f9915f ¤   USERTRANS("undefined"),
257da6 ¤   USERTRANS("invalid"),
48088d ¤   USERTRANS("marginal"),
9cc339 ¤   USERTRANS("complete"),
1982f7 };
eaaf5a
a838e5 /*
45d129 ·* Translate the trust tables at once, to avoid massive overhead while
62ea48 ·* displaying the output.
de495d ·*/
5fb177 #if 0
95314a void
b6e79d trustInitTables(void)
5abb36 {
b2f3e0 ¤   static int initialized = 0;
6e06ff ¤   int i, len;
a89fb6 ¤   char const *s;
85813a ¤   char *p;
d8af5a
328625 ¤   if (initialized)
c399bf ¤   ¤   return;
7aaf5a
78c569 ¤   for (i = 0; i < sizeof(keyTrustTable)/sizeof(*keyTrustTable); i++) {
ae9826 ¤   ¤   s = userTrans(keyTrustTable[i]);
676f25 ¤   ¤   if (s != keyTrustTable[i]) {
5f78cc ¤   ¤   ¤   len = strlen(s)+1;
ef16bc ¤   ¤   ¤   p = memPoolAlloc(&MiscPool, len, 1);
2b058b ¤   ¤   ¤   if (p) {
ef8ef4 ¤   ¤   ¤   ¤   memcpy(p, s, len);
16db7f ¤   ¤   ¤   ¤   keyTrustTable[i] = p;
28a3a6 ¤   ¤   ¤   }
ac0fe4 ¤   ¤   }
cd9371 ¤   }
25c951 ¤   for (i = 0; i < sizeof(uidValidityTable)/sizeof(*uidValidityTable);
b927cd ¤   ¤   ¤   i++)
--bf10 001d791c16b40100203 Page 2 of pgpTrstPkt.c
f7c7a1 ¤   {
8a7bf9 ¤   ¤   s = userTrans(uidValidityTable[i]);
007aa5 ¤   ¤   if (s != uidValidityTable[i]) {
5978cc ¤   ¤   ¤   len = strlen(s)+1;
e916bc ¤   ¤   ¤   p = memPoolAlloc(&MiscPool, len, 1);
f0058b ¤   ¤   ¤   if (p) {
b78ef4 ¤   ¤   ¤   ¤   memcpy(p, s, len);
a2933b ¤   ¤   ¤   ¤   uidValidityTable[i] = p;
22a3a6 ¤   ¤   ¤   }
070fe4 ¤   ¤   }
759371 ¤   }
23efe6 }
257454 #endif
59af5a
1aaf5a
9caf5a
d7af5a
--339e 000e5cad29040100204 Page 1 of pgpTrstPkt.h
bc38e5 /*
d3847d ·* $Id: pgpTrstPkt.h,v 1.10 1997/06/16 22:48:54 lloyd Exp $
4d495d ·*/
89af5a
f9e7f9 #ifndef Included_pgpTrstPkt_h
2db3cd #define Included_pgpTrstPkt_h
1caf5a
fac5d5 #include "pgpBase.h"
dcaf5a
cd38e5 /*
0d443d ·* Key trust byte:
2087ff ·* 8 +--+
952eda ·* ··| ·| BUCKSTOP bit - this is an axiomatic key
4c9e0b ·* 7 +--+
b6b96c ·* ··| ·|·
fb01de ·* 6 +--+
27f2eb ·* ··| ·| Disabled - don't use at user request
2fa9b0 ·* 5 +--+
e65eab ·* ··| ·| Revoked - don't use at issuer request
b53665 ·* 4 +--+
79b96c ·* ··| ·|·
86f17d ·* 3 +--+
6bfd42 ·* ··| ·| Introducer trust. ·6 levels are used:
04588b ·* 2 + ·+ 000 - undefined, need to ask user
0de663 ·* ··| ·| 001 - Unknown, consider to be zero
1690b3 ·* 1 + ·+ 010 - Not trusted
526de8 ·* ··| ·| 011 - unused
7a0bb6 ·* 0 +--+ 100 - unused
3d33c3 ·* ·······101 - Marginal - partially trusted·
cfc04d ·* ·······110 - Complete - completely trusted
da12e0 ·* ·······111 - Ultimate - ultimately trusted
ad495d ·*/
acaf5a
897686 #define PGP_KEYTRUSTF_BUCKSTOP¤ 0x80u
084bc8 #define PGP_KEYTRUSTF_EXPIRED ··0x40u
fb11c5 #define PGP_KEYTRUSTF_DISABLED¤ 0x20u
8e2fd9 #define PGP_KEYTRUSTF_REVOKED¤  0x10u
e8af5a
6aa076 #include "pgpKeys.h"
5faf5a
a3af5a
0e38e5 /*
2b9bf1 ·* Name trust byte:
6287ff ·* 8 +--+
37aa21 ·* ··| ·| WARNONLY bit - yes, it's okay to use even though not fully trusted
e89e0b ·* 7 +--+
75de2a ·* ··| ·| unused
8801de ·* 6 +--+
cfde2a ·* ··| ·| unused
11a9b0 ·* 5 +--+
27de2a ·* ··| ·| unused
863665 ·* 4 +--+
01de2a ·* ··| ·| unused
a6f17d ·* 3 +--+
bade2a ·* ··| ·| unused
3c6ea8 ·* 2 +--+
a2dc8a ·* ··| ·| Confidence in name's validity.
450dc7 ·* 1 + ·+ 00 - Not known
74d7ec ·* ··| ·| 01 - Not trusted
73b8b7 ·* 0 +--+ 10 - Partially trusted
fe2ae9 ·* ·······11 - Completely trusted
8d775e ·*
004e7e ·* New trust packets are followed by up to two more bytes, which are the
d3e0e9 ·* certainty PGP has of the name's validity and the confidence the user
487c26 ·* has assigned to this name as an introducer, respectively. ·The byte
2367ec ·* b represents probability of 10^(-b/40) that the name is incorrect,
000a73 ·* up to 252. ·255 means "total confidence", 253 means confidence is
f7b301 ·* undefined, and 254 is reserved for now.
24775e ·*
592da3 ·* @@@ Reserve 0 for "undefined/I dunno", 1 for "untrusted" and offset
783438 ·* ····everything that way. ·It might be more natural...
e5775e ·*
--d034 0002a215c2440100204 Page 2 of pgpTrstPkt.h
6b0adb ·* The following pattern repeats each 40:
71775e ·*
112f29 ·* ·0 = 1.00000 ··9 = 1.67880 ·18 = 2.81838 ·27 = 4.73151 ·36 = 7.94328 ·
73375b ·* ·1 = 1.05925 ·10 = 1.77828 ·19 = 2.98538 ·28 = 5.01187 ·37 = 8.41395 ·
68da71 ·* ·2 = 1.12202 ·11 = 1.88365 ·20 = 3.16228 ·29 = 5.30884 ·38 = 8.91251 ·
840fd3 ·* ·3 = 1.18850 ·12 = 1.99526 ·21 = 3.34965 ·30 = 5.62341 ·39 = 9.44061 ·
bdfe5e ·* ·4 = 1.25893 ·13 = 2.11349 ·22 = 3.54813 ·31 = 5.95662 ·40 = 10.0000 ·
2d2e44 ·* ·5 = 1.33352 ·14 = 2.23872 ·23 = 3.75837 ·32 = 6.30957 ·41 = 10.5925
c290ee ·* ·6 = 1.41254 ·15 = 2.37137 ·24 = 3.98107 ·33 = 6.68344 ·42 = 11.2202
ebc945 ·* ·7 = 1.49624 ·16 = 2.51189 ·25 = 4.21697 ·34 = 7.07946 ·43 = 11.8850
03a55c ·* ·8 = 1.58489 ·17 = 2.66073 ·26 = 4.46684 ·35 = 7.49894 ·44 = 12.5893
6d775e ·*
83043e ·* As you can see, f(12) ~= 2, f(19) ~= 3, * and f(24) ~= 4.
598ac3 ·* The converse of this is that f(40-12) = f(28) = 10/f(12) ~= 10/2 = 5
79a391 ·* and similarly f(21) ~= 10/3 = 3.33 and f(16) ~= 10/4 = 2.5.
199265 ·* The system was chosen because all of those nice integer ratios
a2420b ·* work out.
7b775e ·*
3f3e4b ·* This is very close to 2^(-b/12), the difference being the 1024/1000
552eb9 ·* mismatch that programmers are used to ignoring. ·Thus, each 12 steps
a471d6 ·* is an octave and each single step is a semitone.
99775e ·*
de7ac1 ·* From the API, these values are translated to 16-bit values, which are
c4a3e0 ·* all the programmer sees. ·The 16-bit values are shifted by 6 bits,
ec03f3 ·* giving a minimum representable error of abut 2.5*10^-26.
b0495d ·*/
6983f8 #define PGP_NAMETRUSTF_WARNONLY¤0x80u
73af5a
11af5a
7170b1 /* The following bytes apply to validity and confidence bytes on names */
e21e98 #define PGP_NEWTRUST_MAX ··········252
df2715 #define PGP_NEWTRUST_UNDEFINED ····253
b4814f #define PGP_NEWTRUST_INFINITE ·····255
47af5a
e338e5 /*
c6d4e1 ·* Signature trust byte:
2487ff ·* 8 +--+
08de2a ·* ··| ·| unused
609e0b ·* 7 +--+
faa7d4 ·* ··| ·| Checked - Signature is good
6e01de ·* 6 +--+
6a25fa ·* ··| ·| Tried - Signature verification attempted
36a9b0 ·* 5 +--+
23de2a ·* ··| ·| unused
553665 ·* 4 +--+
9bde2a ·* ··| ·| unused
12f17d ·* 3 +--+
279f61 ·* ··| ·| Introducer trust, copied from key that makes it
fa1f24 ·* 2 + ·+
fee918 ·* ··| ·|
feb74a ·* 1 + ·+
a3e918 ·* ··| ·|
f95913 ·* 0 +--+
3b495d ·*/
c1af5a
0a38e5 /*
4b0a87 ·* The low 3 bits of a signature's trust are generally the same as
44cddc ·* the corresponding key's trust (kPGPKeyTrust_Undefined if none), but
c8a82b ·* the following signature pseudo-trusts used in some printing contexts:
4f495d ·*/
c93344 #define PGP_SIGTRUST_NOKEY¤ 0x8u¤   /* No corresponding key */
465699 #define PGP_SIGTRUST_RETIRED ···0x9u ···/* Retired/sig revoked */
1b444e #define PGP_SIGTRUST_REVOKED ···0xAu ···/* Signing key revoked */
337269 #define PGP_SIGTRUST_UNTRIED¤   0xBu¤   /* Signature has not been tried */
7141c4 #define PGP_SIGTRUST_INVALID¤   0xCu¤   /* Invalid signature or something */
b7484b #define PGP_SIGTRUST_BAD¤   0xDu¤   /* BAD SIGNATURE */
66af5a
1838e5 /*
a227d6 ·* There are four possible signature states worth noting, actually:
50fdf9 ·* - No verification attempted (includes key not found)
7c9ede ·* - Verification impossible (format problem or key length)
2aa8d9 ·* - Verified bad (format correct, but signature is no good)
--b317 001482bc66240100204 Page 3 of pgpTrstPkt.h
1b09b0 ·* - Verified good
5b775e ·*
14d1eb ·* In practice, the middle two can be merged, and the last marked by
d2fb04 ·* the PGP_SIGTRUSTF_CHECKED bit for compatibility with 2.x. ·The first two
0c0149 ·* can be distinguidhed through the use of the PGP_SIGTRUSTF_TRIED bit.
cbcc84 ·* If clear, the signature's verification has never been attempted.
79775e ·*
5eb7f5 ·* At some future point, we should make CHECKED=1 and TRIED=0 mean that
531fe7 ·* a signature was bad, but postpone on that for a while; the state is
71cef2 ·* CHECKED=0, TRIED=1 for now. ·If we see CHECKED set, that implies
61735b ·* TRIED.
64495d ·*/
8b834d #define PGP_SIGTRUSTF_TRIED¤0x20u¤  /* Visited by sig check (-kc) */
6f1380 #define PGP_SIGTRUSTF_CHECKED¤  0x40u¤  /* Checked out good */
280914 #define PGP_SIGTRUSTF_CHECKED_TRIED (PGP_SIGTRUSTF_CHECKED | \
80c1bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGP_SIGTRUSTF_TRIED)
1baf5a
4c99c6 PGP_BEGIN_C_DECLARATIONS
a7af5a
fa2026 extern char const ·*keyTrustTable[];
a2c9eb extern char const ·*uidValidityTable[];
0aaf5a
f21254 PGP_END_C_DECLARATIONS
7baf5a
486701 #endif /* Included_pgpTrstPkt_h */
--5478 000aa6fa73740100205 Page 1 of pgpTrust.c
bc38e5 /*
331bab ·* $Id: pgpTrust.c,v 1.7 1998/07/10 23:55:13 hal Exp $
2f495d ·*/
5faf5a
3838ab #include <math.h>
95af5a
d0e2ff #include "pgpConfig.h"
f9af5a
3ba146 #include "pgpDebug.h"
467a44 #include "pgpRngPriv.h"
965a03 #include "pgpTrust.h"
1dae6d #include "pgpTrstPkt.h"
3daf5a
985d74 PGPByte
c62461 ringTrustToExtern(PGPUInt16 trust)
00bb36 {
921325 #if PGPTRUSTMODEL==0
f31d78 ¤   (void)trust;
964aac ¤   pgpAssert(0);
8e3e6b ¤   return 0;
09db21 #else
491ed9 ¤   if (trust == PGP_TRUST_INFINITE)
141cbc ¤   ¤   return (PGPByte) PGP_NEWTRUST_INFINITE;
772537 ¤   trust >>= TRUST_CERTSHIFT;
04b353 ¤   if (trust > PGP_NEWTRUST_MAX)
30679e ¤   ¤   trust = PGP_NEWTRUST_MAX;
d088ea ¤   return (PGPByte) trust;
667454 #endif
6eefe6 }
54af5a
726e17 PGPUInt16
faf743 ringTrustToIntern(PGPByte trust)
d5bb36 {
651325 #if PGPTRUSTMODEL==0
131d78 ¤   (void)trust;
1e4aac ¤   pgpAssert(0);
033e6b ¤   return 0;
dedb21 #else
cdb5f8 ¤   if (trust > PGP_NEWTRUST_MAX) {
b10830 ¤   ¤   if (trust == PGP_NEWTRUST_INFINITE)
096486 ¤   ¤   ¤   return (PGPUInt16) PGP_TRUST_INFINITE;
fb0e1d ¤   ¤   else
859f4f ¤   ¤   ¤   return 0;¤  /* Undefined */
8d9371 ¤   }
87078e ¤   return (PGPUInt16) trust << TRUST_CERTSHIFT;
a57454 #endif
9aefe6 }
9caf5a
d8f89b /* Convert from old 3-level trust to the new 256-level (extern format) */
be5d74 PGPByte
3c88aa ringTrustOldToExtern(RingPool const *pool, PGPByte oldTrust)
dcbb36 {
a387cd ¤   PGPByte externTrust;
3eaf5a
75e613 ¤   switch (oldTrust & kPGPKeyTrust_Mask) {
23ea23 ¤   ··case kPGPKeyTrust_Ultimate:
94ac43 ¤   ¤   externTrust = PGP_NEWTRUST_INFINITE;
e02f68 ¤   ¤   break;
bd2c14 ¤   ··case kPGPKeyTrust_Complete:
300cd3 ¤   ¤   externTrust = pool->completeconfidence;
c72f68 ¤   ¤   break;
448ca2 ¤   ··case kPGPKeyTrust_Marginal:
190bfe ¤   ¤   externTrust = pool->marginalconfidence;
992f68 ¤   ¤   break;
c7aaf9 ¤   ··case kPGPKeyTrust_Undefined:
5daf2a ¤   ¤   externTrust = PGP_NEWTRUST_UNDEFINED;
392f68 ¤   ¤   break;
dff727 ¤   ··default:
e6d3b5 ¤   ¤   externTrust = 0;
882f68 ¤   ¤   break;
a89371 ¤   }
aaab92 ¤   return externTrust;
--891f 000f647bc8540100205 Page 2 of pgpTrust.c
7aefe6 }
46af5a
d1945e /* Convert from new 256-level (extern format) to old 3-level trust ·*/
32ecb4 /* Divide into intervals so a series of Complete trust signatures will
725829 ·* not decay to a Marginal after just two are put together. */
4e5d74 PGPByte
39cdba ringTrustExternToOld(RingPool const *pool, PGPByte externTrust)
3cbb36 {
d1b704 ¤   if (externTrust >= PGP_NEWTRUST_INFINITE)
4eaec6 ¤   ¤   return kPGPKeyTrust_Ultimate;
f3bec9 ¤   if (externTrust >=
c4d3cb ¤   ¤   ¤   (2*pool->completeconfidence+pool->marginalconfidence)/3)
4768f1 ¤   ¤   return kPGPKeyTrust_Complete;
a0dcef ¤   if (externTrust >= (2*pool->marginalconfidence)/3)
80c847 ¤   ¤   return kPGPKeyTrust_Marginal;
33134b ¤   return kPGPKeyTrust_Unknown;
80efe6 }
00af5a
fa4d2f int
deed34 ringTrustValid(RingSet const *set, PGPUInt16 validity)
f9bb36 {
ba1325 #if PGPTRUSTMODEL==0
f48a21 ¤   (void)set;
0e8d00 ¤   (void)validity;
634aac ¤   pgpAssert(0);
b63e6b ¤   return 0;
92db21 #else
a83b60 ¤   if (validity >= (set->pool->threshold << TRUST_CERTSHIFT))
1ce102 ¤   ¤   return 1;
c10e24 ¤   else
41bbde ¤   ¤   return 0;
e07454 #endif
8defe6 }
8daf5a
9de53e static double k1, k2;
39cc73 static double kmaxt;¤   /* Maximum value of trust in terms of 1/n error prob */
78af5a
dd2978 static void
787484 ringTrustInit(void)
f8bb36 {
ea0c35 ¤   double d = log(10.0);
4faf5a
9b3521 ¤   k1 = d/PGP_TRUST_DECADE;
332fd5 ¤   k2 = PGP_TRUST_DECADE/d;
201c87 ¤   kmaxt = exp (PGP_TRUST_MAX * k1);
02efe6 }
faaf5a
f7c1c3 #define RINGTRUSTINIT(k) if (!k) ringTrustInit()
33af5a
aa536c unsigned
e5804e ringIntToTrust(unsigned long r)
cbbb36 {
246f28 ¤   RINGTRUSTINIT(k2);
2c1316 ¤   return (unsigned) (log ((double) r) * k2 + 0.5);
8defe6 }
a4af5a
3be5f9 unsigned long
dda03c ringTrustToInt(unsigned t)
c9bb36 {
cf4ae5 ¤   RINGTRUSTINIT(k1);
487e59 ¤   return (unsigned long) (exp (t * k1) + 0.5);
2befe6 }
e3af5a
121b83 #ifdef __GNUC__¤¤   /* XXX: Should be something like HAS_LONG_LONG */
50d7be unsigned long long
29d0f2 ringTrustToUll(unsigned t)
36bb36 {
6f4ae5 ¤   RINGTRUSTINIT(k1);
6deb9b ¤   return (unsigned long long) (exp (t * k1) + 0.5);
24efe6 }
fe7454 #endif
f6af5a
--c8d0 000b60df2b440100205 Page 3 of pgpTrust.c
9ff6a7 double
0d40c8 ringTrustToDouble(unsigned t)
25bb36 {
344ae5 ¤   RINGTRUSTINIT(k1);
7a1d82 ¤   return exp (t * k1);
b8efe6 }
d7af5a
3c536c unsigned
6c7e99 ringDoubleToTrust(double d)
49bb36 {
561a96 ¤   pgpAssert (d >= .9);
236f28 ¤   RINGTRUSTINIT(k2);
fcdd21 ¤   if (d >= kmaxt)
dedb9f ¤   ¤   return PGP_NEWTRUST_MAX;
2e0e24 ¤   else
9f75d5 ¤   ¤   return (unsigned) (log (d) * k2 + 0.5);
adefe6 }
3faf5a
a2b177 #if 0
befeb2 #include <stdio.h>
abaf5a
4c2978 static void
29d2c7 prettytrust(unsigned t, int wid)
77bb36 {
4f1e10 ¤   int d = t - PGP_TRUST_DECADE - PGP_TRUST_OCTAVE;¤   /* Tweak this*/
45ad05 ¤   char buf[10];
154ba4 ¤   int i;
e1c8c3 ¤   unsigned long l;
d9af5a
674c04 ¤   if (d >= 0) {
862e7c ¤   ¤   /* Straightforward */
58d1a4 ¤   ¤   d -= d % PGP_TRUST_DECADE;
8086e0 ¤   ¤   i = d / PGP_TRUST_DECADE;
c8e7e7 ¤   ¤   l = ringTrustToInt(t-d);
b110cd ¤   ¤   if (i)
587b9e ¤   ¤   ¤   wid -= printf("1/%lu%0*u", l, i, 0);
aa0e1d ¤   ¤   else
583650 ¤   ¤   ¤   wid -= printf("1/%lu", l);
7df037 ¤   } else {
46cf73 ¤   ¤   /* Do decimal point thing */
fd9ed6 ¤   ¤   i = 0;
9b4392 ¤   ¤   do {
b681ec ¤   ¤   ¤   i++;
628033 ¤   ¤   ¤   d += PGP_TRUST_DECADE;
f65c2b ¤   ¤   ¤   t += PGP_TRUST_DECADE;
494f51 ¤   ¤   } while (d < 0);
55af5a
59bd7d ¤   ¤   sprintf(buf, "%lu", ringTrustToInt(t));
ea622b ¤   ¤   i = (int)strlen(buf) - i;
c7af5a
1ac0ec ¤   ¤   wid -= printf("1/%.*s.%s", i, buf, buf+i);
b69371 ¤   }
cd6dc7 ¤   while (--wid >= 0)
b8184c ¤   ¤   putchar(' ');
acefe6 }
ddaf5a
a94d2f int
287f68 main(void)
73bb36 {
300ed5 ¤   unsigned t;
119745 ¤   unsigned long long j;
2caf5a
594e8a ¤   for (t = 0; t <= 65535; t++) {
1bac3e ¤   ¤   j = ringTrustToUll(t);
9fd4ab ¤   ¤   printf("%5u = 1/%-9Lu = ", t, j);
8bab6d ¤   ¤   prettytrust(t, 28);
f2728c ¤   ¤   putchar('\n');
269371 ¤   }
223e6b ¤   return 0;
afefe6 }
6b7454 #endif
b6af5a
--fadf 001e0d5e91e40100205 Page 4 of pgpTrust.c
e0af5a
--2a69 001c8b0440b40100206 Page 1 of pgpTrust.h
bc38e5 /*
d59629 ·* $Id: pgpTrust.h,v 1.9 1997/07/14 04:27:14 hal Exp $
e3495d ·*/
f6af5a
706cd7 #ifndef Included_pgpTrust_h
b17a02 #define Included_pgpTrust_h
b7af5a
2cd11f #include "pgpUsuals.h"
c6af5a
14b29d #define PGP_TRUST_DECADE (40*64)
4355fd #define PGP_TRUST_OCTAVE (12*64)
92f994 #define PGP_TRUST_MAX 0xfffe
d24af2 #define PGP_TRUST_INFINITE 0xffff
ebaf5a
2999c6 PGP_BEGIN_C_DECLARATIONS
5daf5a
55fd16 PGPByte ·······ringTrustToExtern(PGPUInt16 trust);
01f1db PGPUInt16 ·····ringTrustToIntern(PGPByte trust);
225ede PGPByte¤¤   ···ringTrustExternToOld(RingPool const *pool, PGPByte externTrust);
29a0b6 PGPByte¤¤   ···ringTrustOldToExtern(RingPool const *pool, PGPByte oldTrust);
ab2762 unsigned ······ringIntToTrust(unsigned long r);
30127a unsigned long ·ringTrustToInt(unsigned t);
d9e6a8 unsigned ······ringDoubleToTrust(double d);
3c7dcb double ········ringTrustToDouble(unsigned t);
bd0b4b int ···········ringTrustValid(RingSet const *set,
f5fb02 ¤   PGPUInt16 validity);
7b1b83 #ifdef __GNUC__¤¤   /* XXX: Should be something like HAS_LONG_LONG */
c16a0a unsigned long long ·ringTrustToUll(unsigned t);
a47454 #endif
b4af5a
991254 PGP_END_C_DECLARATIONS
3eaf5a
c8c539 #endif /* Included_pgpTrust_h */
--6a2c 001464749d440100207 Page 1 of Makefile.in
5ea601 #
8f7665 # prib/keys/pubkey/
30a601 #
491424 # $Id: Makefile.in,v 1.5.2.1 1998/10/14 22:44:28 hal Exp $
06a601 #
f7af5a
e90bb6 OBJS= pgpPubKey.o pgpRSAKey.o pgpRSAGlue.o pgpFixedKey.o pgpESK.o pgpSig.o \
6e5d2e ¤   pgpPktList.o pgpMakeSig.o pgpKeySpec.o pgpElGKey.o pgpDSAKey.o \
e4edcf ¤   pgpKeyMisc.o pgpPublicKey.o pgpBSRSAGlue.o pgpAltRSAGlu.o
e3b49a PRIVHDRS= pgpESK.h pgpFixedKey.h pgpPubKey.h pgpSig.h pgpKeySpec.h \
ad2408 ¤   pgpRSAKey.h pgpMakeSig.h pgpElGKey.h pgpDSAKey.h pgpKeyMisc.h \
bc9e61 ¤   pgpPktList.h pgpMSRSAGlue.h
1aaf5a
2eb7a3 all:: DONE
46af5a
--d0f3 000e059c02e40100208 Page 1 of pgpAltRSAGlu.c
bc38e5 /*
ba8d27 ·* pgpAltRSAGlu.c - Interface to RSAREF Cryptographic toolkit from
1e2987 ·* RSA Data Security, Inc.
20775e ·*
156997 ·* This is an alternative to pgpRSAGlue.c, and should be used if the
9ad769 ·* use of the RSAREF library is required for legal reasons.
12775e ·*
7d5236 ·* This file uses RSAREF to perform the actual encryption and decryption.
c4db59 ·* It must be linked with the RSAREF library (rsaref.a, rsaref.lib,
045e3c ·* or whatever it's called on your system) to function.
60775e ·*
3485a1 ·* This code only accepts PKCS-style padding. ·Very old versions of PGP
2de92a ·* used a different padding style, which will not be compatible with
ca8700 ·* this module.
87775e ·*
b4b713 ·* $Id: pgpAltRSAGlu.c,v 1.13.2.1 1998/10/14 22:44:35 hal Exp $
8e495d ·*/
e7d83c ·
6738e5 /*
a22486 ·* An alternative version of this module is used if RSAREF is NOT needed.
fdbd56 ·* This entire source file is under the control of the following conditional:
3c495d ·*/
38af5a
883051 #include "pgpSDKBuildFlags.h"
f3af5a
5716b4 #if PGP_USERSAREF¤  /* [ */
abaf5a
ade205 /* Default to using our MPI library */
f39a70 #ifndef PGP_USEMPILIBWITHRSAREF
8c65ea #define PGP_USEMPILIBWITHRSAREF 1
40a567 #endif /* PGP_USEMPILIBWITHRSAREF */
73af5a
28d83c ·
3ae2ff #include "pgpConfig.h"
c4af5a
c9a146 #include "pgpDebug.h"
e18c41 #include "pgpRSAGlue.h"
dc007f #include "pgpKeyMisc.h"
4039fc #include "bn.h"
e72f8d #include "pgpErrors.h"
ff2c96 #include "pgpRandomX9_17.h"
f50d08 #include "pgpMem.h"
e7af5a
5caf5a
6638e5 /*
7d0097 ·* If you're using a legally encumbered library this will be
4dd924 ·* printed in the program banner.
66495d ·*/
1501f1 char const banner_legalese[] = "\
dda198 Uses the RSAREF(tm) Toolkit, which is copyright RSA Data Security, Inc.\n\
45ab31 Distributed by the Massachusetts Institute of Technology.\n";
42af5a
9b13a5 /* Include files from RSAREF */
a73d9e #include <global.h>
d1c30b #include <rsaref.h>
cf696e #include <rsa.h>
d9af5a
4838e5 /*
ca21af ·* The functions we call in rsa.h are:
aa7a7d ·* ·RSAPublicEncrypt
6bda93 ·* ·RSAPrivateEncrypt
0b8d40 ·* ·RSAPublicDecrypt
2e2dae ·* ·RSAPrivateDecrypt
40495d ·*/
8faf5a
4faf5a
2638e5 /*
dc36ba ·* This returns TRUE if the key is too big, returning the
c4aecf ·* maximum number of bits that the library can accept.
e3495d ·*/
bf4d2f int
e04a31 rsaKeyTooBig(RSApub const *pub, RSAsec const *sec)
--a93b 000e24a556940100208 Page 2 of pgpAltRSAGlu.c
2cbb36 {
bb557c ¤   unsigned maxsize = MAX_RSA_MODULUS_BITS;
0c67ab ¤   if (pub) {
d62056 ¤   ¤   if (bnBits(&pub->n) > maxsize)
0cc704 ¤   ¤   ¤   return maxsize;
db4c0b ¤   ¤   if (bnBits(&pub->e) > maxsize)
15c704 ¤   ¤   ¤   return maxsize;
3b9371 ¤   }
c28631 ¤   if (sec) {
9169ab ¤   ¤   if (bnBits(&sec->d) > maxsize)
5ac704 ¤   ¤   ¤   return maxsize;
41a1ef ¤   ¤   if (bnBits(&sec->p) > MAX_RSA_PRIME_BITS)
99c704 ¤   ¤   ¤   return maxsize;
bba594 ¤   ¤   if (bnBits(&sec->q) > MAX_RSA_PRIME_BITS)
c3c704 ¤   ¤   ¤   return maxsize;
45b478 ¤   ¤   if (bnBits(&sec->u) > MAX_RSA_PRIME_BITS)
0cc704 ¤   ¤   ¤   return maxsize;
d49371 ¤   }
c5b379 ¤   /* Else OK */
a83e6b ¤   return 0;
d4efe6 }
83af5a
459582 /* Initialize RSAREF pubkey structure from a RSApub. */
f82978 static void
810461 rpubk_init(R_RSA_PUBLIC_KEY *rpubk, RSApub const *pub)
3cbb36 {
4da5d8 ¤   pgpClearMemory(rpubk, sizeof (*rpubk));
ad6ad3 ¤   rpubk->bits = bnBits(&pub->n);
025992 ¤   bnExtractBigBytes(&pub->n, rpubk->modulus, 0, MAX_RSA_MODULUS_LEN);
db5f74 ¤   bnExtractBigBytes(&pub->e, rpubk->exponent, 0, MAX_RSA_MODULUS_LEN);
7eefe6 }
57af5a
3bb636 /* Initialize RSAREF privkey structure from a RSAsec. */
952978 static void
863c73 rprivk_init(R_RSA_PRIVATE_KEY *rprivk, RSAsec const *sec,
7e19f8 ¤   PGPMemoryMgrRef¤mgr)
73bb36 {
b69d46 ¤   BigNum dmodp, dmodq, tmp;
28af5a
d03d0e ¤   pgpClearMemory(rprivk, sizeof (*rprivk));
c4af5a
fd9946 ¤   /* Calculate d mod p-1 and d mod q-1 */
430202 ¤   bnBegin(&dmodp, mgr, TRUE);
c24a28 ¤   bnBegin(&dmodq, mgr, TRUE);
245c21 ¤   bnBegin(&tmp, mgr, TRUE);
4c8d99 ¤   bnCopy(&tmp, &sec->p);
adf1b8 ¤   bnSubQ(&tmp, 1);
5467f3 ¤   bnMod(&dmodp, &sec->d, &tmp);
9f9122 ¤   bnCopy(&tmp, &sec->q);
23f1b8 ¤   bnSubQ(&tmp, 1);
f4f4ba ¤   bnMod(&dmodq, &sec->d, &tmp);
13af5a
a165b0 ¤   /* Fill in structure */
dff695 ¤   rprivk->bits = bnBits(&sec->n);
b7f207 ¤   bnExtractBigBytes(&sec->n, rprivk->modulus, 0, MAX_RSA_MODULUS_LEN);
3ede39 ¤   bnExtractBigBytes(&sec->e, rprivk->publicExponent, 0,
b3c37b ¤   ¤   ¤   ··MAX_RSA_MODULUS_LEN);
3732d6 ¤   bnExtractBigBytes(&sec->d, rprivk->exponent, 0, MAX_RSA_MODULUS_LEN);
b979eb ¤   /* RSAREF uses convention p > q, the opposite of ours */
e3e7ad ¤   bnExtractBigBytes(&sec->q, rprivk->prime[0], 0, MAX_RSA_PRIME_LEN);
f535a2 ¤   bnExtractBigBytes(&sec->p, rprivk->prime[1], 0, MAX_RSA_PRIME_LEN);
a95fc3 ¤   bnExtractBigBytes(&dmodq, rprivk->primeExponent[0], 0,
8498be ¤   ¤   ¤   ··MAX_RSA_PRIME_LEN);
61b774 ¤   bnExtractBigBytes(&dmodp, rprivk->primeExponent[1], 0,
f698be ¤   ¤   ¤   ··MAX_RSA_PRIME_LEN);
73a2db ¤   bnExtractBigBytes(&sec->u, rprivk->coefficient, 0, MAX_RSA_PRIME_LEN);
2aaf5a
380425 ¤   bnEnd(&dmodp);
8f189e ¤   bnEnd(&dmodq);
cf1dd8 ¤   bnEnd(&tmp);
f2efe6 }
e2af5a
--de56 0009c7d413840100208 Page 3 of pgpAltRSAGlu.c
bc38e5 /*
08addc ·* Encrypt a buffer holding a session key with an RSA public key
71495d ·*/
a54d2f int
4bab93 rsaPublicEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
42e64b ¤   RSApub const *pub, PGPRandomContext const *rc)
e3bb36 {
faf7a5 #ifndef PGP_DISABLE_RSAREF_ENCRYPT
41af5a
0c96ed ¤   R_RSA_PUBLIC_KEY rpubk;
bdd796 ¤   R_RANDOM_STRUCT rrs;
73b08d ¤   PGPByte buf[MAX_RSA_MODULUS_LEN];
636c39 ¤   unsigned int bufsize;
bd17e6 ¤   int err;
90af5a
f1af5a
2eda15 ¤   /* Set the return number to 0 to start */
1df43e ¤   (void)bnSetQ(bn, 0);
09af5a
582513 ¤   /* Initialize RSAREF public key structure */
8336c7 ¤   rpubk_init(&rpubk, pub);
aeaf5a
091ab3 ¤   /* Initialize RSAREF random numbers */
017c89 ¤   R_RandomInit(&rrs);
ee43ab ¤   do {
75d5b7 ¤   ¤   R_GetRandomBytesNeeded(&bufsize, &rrs);
5196de ¤   ¤   if (bufsize > sizeof(buf))
f99eb4 ¤   ¤   ¤   bufsize = sizeof(buf);
58aa37 ¤   ¤   if (bufsize) {
edc32e ¤   ¤   ¤   pgpRandomGetBytes(rc, buf, bufsize);
87d1a4 ¤   ¤   ¤   R_RandomUpdate(&rrs, buf, bufsize);
500fe4 ¤   ¤   }
41b41c ¤   } while (bufsize);
1daf5a
de03b2 ¤   /* Pad and encrypt */
abb8ac ¤   err = RSAPublicEncrypt(buf, &bufsize, (PGPByte *)in, len, &rpubk, &rrs);
f986ca ¤   R_RandomFinal(&rrs);
f9af5a
de8a50 ¤   if (err) {
e27abc ¤   ¤   memset(buf, 0, sizeof(buf));
00e960 ¤   ¤   memset(&rpubk, 0, sizeof(rpubk));
fb9dc2 ¤   ¤   if (err==RE_LEN)
f620ce ¤   ¤   ¤   return kPGPError_PublicKeyTooSmall;
9f70d7 ¤   ¤   return kPGPError_UnknownError;
b79371 ¤   }
d1af5a
d74414 ¤   /* Return to bn format */
d81534 ¤   bnInsertBigBytes(bn, buf, 0, bufsize);
3747d4 ¤   memset(buf, 0, sizeof(buf));
4fd58e ¤   memset(&rpubk, 0, sizeof(rpubk));
40af5a
7d3e6b ¤   return 0;
24af5a
669f27 #else /* PGP_DISABLE_RSAREF_ENCRYPT */
61af5a
e88a69 ¤   (void)in;
5aa272 ¤   (void)len;
500700 ¤   (void)pub;
ea76a2 ¤   (void)rc;
69af5a
fdf43e ¤   (void)bnSetQ(bn, 0);
b50b93 ¤   return kPGPError_PublicKeyUnimplemented;
27af5a
a934bd #endif /* PGP_DISABLE_RSAREF_ENCRYPT */
f4efe6 }
d5af5a
bdaf5a
1938e5 /*
30322b ·* Do an RSA signing operation using the secret key
92495d ·*/
ed4d2f int
9cb4a4 rsaPrivateEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
--5d63 0007a3dcd7f40100208 Page 4 of pgpAltRSAGlu.c
c184e6 ¤   RSAsec const *sec)
d8bb36 {
0e0a12 #ifndef PGP_DISABLE_RSAREF_SIGN
69af5a
b87288 ¤   R_RSA_PRIVATE_KEY rprivk;
91b08d ¤   PGPByte buf[MAX_RSA_MODULUS_LEN];
666c39 ¤   unsigned int bufsize;
e117e6 ¤   int err;
519353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
e6af5a
9dd8d7 ¤   /* SET the return number to 0 to start */
76f43e ¤   (void)bnSetQ(bn, 0);
40af5a
27f786 ¤   /* Initialize RSAREF private key structure */
574572 ¤   rprivk_init(&rprivk, sec, mgr);
2baf5a
5ccdf5 ¤   err = RSAPrivateEncrypt(buf, &bufsize, (PGPByte *)in, len, &rprivk);
07af5a
288a50 ¤   if (err) {
037abc ¤   ¤   memset(buf, 0, sizeof(buf));
a8e231 ¤   ¤   memset(&rprivk, 0, sizeof(rprivk));
659dc2 ¤   ¤   if (err==RE_LEN)
0220ce ¤   ¤   ¤   return kPGPError_PublicKeyTooSmall;
5c70d7 ¤   ¤   return kPGPError_UnknownError;
1b9371 ¤   }
c4af5a
074414 ¤   /* Return to bn format */
221534 ¤   bnInsertBigBytes(bn, buf, 0, bufsize);
9347d4 ¤   memset(buf, 0, sizeof(buf));
926a57 ¤   memset(&rprivk, 0, sizeof(rprivk));
3e67c5 ¤
b43e6b ¤   return 0;
ceaf5a
3a4404 #else /* PGP_DISABLE_RSAREF_SIGN */
04af5a
f18a69 ¤   (void)in;
08a272 ¤   (void)len;
1483b1 ¤   (void)sec;
2caf5a
63f43e ¤   (void)bnSetQ(bn, 0);
f80b93 ¤   return kPGPError_PublicKeyUnimplemented;
1eaf5a
510ccf #endif /* PGP_DISABLE_RSAREF_SIGN */
35efe6 }
e3af5a
4638e5 /*
d731cb ·* These destroy (actually, replace with a decrypted version) the
773a47 ·* input bignum bn.
e2775e ·*
48f594 ·* Performs an RSA signature check. ·Returns a prefix of the unwrapped
f1140d ·* data in the given buf. ·Returns the length of the untruncated
645d6b ·* data, which may exceed "len". Returns <0 on error.
6a495d ·*/
d54d2f int
59d7d4 rsaPublicDecrypt(PGPByte *outbuf, unsigned len, BigNum *bn,
d44678 ¤   RSApub const *pub)
20bb36 {
620579 #ifndef PGP_DISABLE_RSAREF_VERIFY
47af5a
3396ed ¤   R_RSA_PUBLIC_KEY rpubk;
0eb08d ¤   PGPByte buf[MAX_RSA_MODULUS_LEN];
fc6c39 ¤   unsigned int bufsize;
d717e6 ¤   int err;
8daf5a
e92513 ¤   /* Initialize RSAREF public key structure */
0236c7 ¤   rpubk_init(&rpubk, pub);
a7af5a
40e1f9 ¤   bufsize = (bnBits(bn) + 7) / 8;
0c1aa1 ¤   if (bufsize > sizeof(buf))
f012cb ¤   ¤   bufsize = sizeof(buf);
57d44a ¤   bnExtractBigBytes(bn, buf, 0, bufsize);
7aaf5a
--c51f 000149fd0e440100208 Page 5 of pgpAltRSAGlu.c
4ff129 ¤   err = RSAPublicDecrypt(buf, &bufsize, buf, bufsize, &rpubk);
3a8a50 ¤   if (err) {
fa7abc ¤   ¤   memset(buf, 0, sizeof(buf));
dee960 ¤   ¤   memset(&rpubk, 0, sizeof(rpubk));
f69dc2 ¤   ¤   if (err==RE_LEN)
4a20ce ¤   ¤   ¤   return kPGPError_PublicKeyTooSmall;
c270d7 ¤   ¤   return kPGPError_UnknownError;
529371 ¤   }
2baf5a
9720ef ¤   /* Copy result to buffer */
b7f38e ¤   if (len > bufsize)
604faa ¤   ¤   len = bufsize;
d1a879 ¤   memcpy(outbuf, buf, len);
21af5a
e247d4 ¤   memset(buf, 0, sizeof(buf));
ead58e ¤   memset(&rpubk, 0, sizeof(rpubk));
b467c5 ¤
a8a3f3 ¤   return bufsize;
12af5a
a99dc2 #else /* PGP_DISABLE_RSAREF_VERIFY */
adaf5a
a21ff6 ¤   (void)outbuf;
0ba272 ¤   (void)len;
654a7c ¤   (void)bn;
c40700 ¤   (void)pub;
2caf5a
f80b93 ¤   return kPGPError_PublicKeyUnimplemented;
9caf5a
fe7d8c #endif /* PGP_DISABLE_RSAREF_VERIFY */
83efe6 }
5daf5a
8e38e5 /*
f09e39 ·* Performs an RSA decryption. ·Returns a prefix of the unwrapped
ef140d ·* data in the given buf. ·Returns the length of the untruncated
7b5d6b ·* data, which may exceed "len". Returns <0 on error.
4b495d ·*/
ba4d2f int
87749c rsaPrivateDecrypt(PGPByte *outbuf, unsigned len, BigNum *bn,
5884e6 ¤   RSAsec const *sec)
febb36 {
450098 #ifndef PGP_DISABLE_RSAREF_DECRYPT
99af5a
4d7288 ¤   R_RSA_PRIVATE_KEY rprivk;
11b08d ¤   PGPByte buf[MAX_RSA_MODULUS_LEN];
fa6c39 ¤   unsigned int bufsize;
3017e6 ¤   int err;
099353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
f3af5a
10f786 ¤   /* Initialize RSAREF private key structure */
3c4572 ¤   rprivk_init(&rprivk, sec, mgr);
2baf5a
07e1f9 ¤   bufsize = (bnBits(bn) + 7) / 8;
f61aa1 ¤   if (bufsize > sizeof(buf))
5b12cb ¤   ¤   bufsize = sizeof(buf);
14d44a ¤   bnExtractBigBytes(bn, buf, 0, bufsize);
59af5a
34e9db ¤   err = RSAPrivateDecrypt(buf, &bufsize, buf, bufsize, &rprivk);
84af5a
258a50 ¤   if (err) {
c97abc ¤   ¤   memset(buf, 0, sizeof(buf));
78e231 ¤   ¤   memset(&rprivk, 0, sizeof(rprivk));
359dc2 ¤   ¤   if (err==RE_LEN)
ef20ce ¤   ¤   ¤   return kPGPError_PublicKeyTooSmall;
4b70d7 ¤   ¤   return kPGPError_UnknownError;
a19371 ¤   }
1baf5a
3d20ef ¤   /* Copy result to buffer */
2df38e ¤   if (len > bufsize)
024faa ¤   ¤   len = bufsize;
71a879 ¤   memcpy(outbuf, buf, len);
a8af5a
1447d4 ¤   memset(buf, 0, sizeof(buf));
--f970 0006f33cce540100208 Page 6 of pgpAltRSAGlu.c
c46a57 ¤   memset(&rprivk, 0, sizeof(rprivk));
9267c5 ¤
64a3f3 ¤   return bufsize;
9daf5a
c7d7f6 #else /* PGP_DISABLE_RSAREF_DECRYPT */
e3af5a
bc1ff6 ¤   (void)outbuf;
a3a272 ¤   (void)len;
0e4a7c ¤   (void)bn;
ad83b1 ¤   (void)sec;
39af5a
e70b93 ¤   return kPGPError_PublicKeyUnimplemented;
33af5a
9f7c6c #endif /* PGP_DISABLE_RSAREF_DECRYPT */
c3efe6 }
66af5a
e7af5a
1438e5 /*
410339 ·* Optional code to replace RSAREF's NN_ModExp with code from the
b93d7f ·* BigNum library, which is much faster.
2eb515 ·* Note that we are still using RSAREF, but we are just using a faster
39b84b ·* modulo exponentiation routine.
d34787 ·* If you comment out the following block of code, you get a (much slower)
460100 ·* pure RSAREF version.
e0495d ·*/
9e4063 #if PGP_USEMPILIBWITHRSAREF¤/* [ */
b3af5a
adf339 typedef PGPUInt32 NN_DIGIT;
d7af5a
3b38e5 /*
125564 ·* Within the RSAREF NN module, values are stored in 32 bit units,
7fdf88 ·* in little-endian order. ·Unfortunately this does not map well onto
5eb595 ·* our bignum format and we have to do some shuffling.
e5495d ·*/
3b2b4e /* Convert an RSAREF NN number to a BigNum */
072978 static void
727ee5 nntobn(BigNum *bn, NN_DIGIT *nn, unsigned nnlen)
13bb36 {
91b08d ¤   PGPByte buf[MAX_RSA_MODULUS_LEN];
6eb61e ¤   PGPByte *bp = buf;
4a743f ¤   unsigned i;
95af5a
b3f55f ¤   pgpAssert (nnlen*4 <= MAX_RSA_MODULUS_LEN);
7e981b ¤   for (i=0; i<nnlen; ++i) {
991b68 ¤   ¤   PGPUInt32 v = nn[i];
65f455 ¤   ¤   *bp++ = v ········& 0xff;
035991 ¤   ¤   *bp++ = (v >> ·8) & 0xff;
10b941 ¤   ¤   *bp++ = (v >> 16) & 0xff;
c6958d ¤   ¤   *bp++ = (v >> 24) & 0xff;
089371 ¤   }
87b395 ¤   bnInsertLittleBytes(bn, buf, 0, nnlen*4);
feefe6 }
c2af5a
2d26e5 /* Convert a BigNum to an RSAREF NN number */
b02978 static void
d5a155 bntonn(BigNum *bn, NN_DIGIT *nn, unsigned nnlen)
24bb36 {
53b08d ¤   PGPByte buf[MAX_RSA_MODULUS_LEN];
00b61e ¤   PGPByte *bp = buf;
ee743f ¤   unsigned i;
18af5a
c5f55f ¤   pgpAssert (nnlen*4 <= MAX_RSA_MODULUS_LEN);
0ff024 ¤   bnExtractLittleBytes(bn, buf, 0, nnlen*4);
eb981b ¤   for (i=0; i<nnlen; ++i) {
43dc51 ¤   ¤   PGPUInt32 v = *bp++;
11909d ¤   ¤   v |= (*bp++) << 8;
a249c0 ¤   ¤   v |= (*bp++) << 16;
d0d9b5 ¤   ¤   v |= (*bp++) << 24;
320301 ¤   ¤   nn[i] = v;
5c9371 ¤   }
83efe6 }
6faf5a
--88e4 001e361227840100208 Page 7 of pgpAltRSAGlu.c
b3314a void
1517e6 NN_ModExp (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned cDigits,
0708b6 ¤   ···NN_DIGIT *d, unsigned dDigits);
34af5a
7338e5 /*
4b7151 ·* Calculate b to the c mod d, result in a.
ca97c2 ·* This is called by the RSAREF library and provides higher performance
c7ebd7 ·* modular exponentiation.
14495d ·*/
cc314a void
7717e6 NN_ModExp (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned cDigits,
c6d688 ¤   ···NN_DIGIT *d, unsigned dDigits)
2abb36 {
d58526 ¤   BigNum bnres, bnbase, bnexp, bnmod;
b60330 ¤   PGPMemoryMgrRef bnmgr;
e6af5a
b798ef ¤   (void) PGPNewMemoryMgr ( 0, &bnmgr);
12af5a
6b2006 ¤   bnBegin(&bnres, bnmgr, TRUE);
15173e ¤   bnBegin(&bnbase, bnmgr, TRUE);
1b865a ¤   bnBegin(&bnexp, bnmgr, TRUE);
027893 ¤   bnBegin(&bnmod, bnmgr, TRUE);
65af5a
be07ec ¤   nntobn(&bnbase, b, dDigits);
4aef57 ¤   nntobn(&bnexp, c, cDigits);
753d88 ¤   nntobn(&bnmod, d, dDigits);
3e67c5 ¤
bbcb8c ¤   bnExpMod(&bnres, &bnbase, &bnexp, &bnmod);
d3af5a
2ba1b5 ¤   bntonn(&bnres, a, dDigits);
2faf5a
90e81c ¤   bnEnd(&bnres);
24ceee ¤   bnEnd(&bnbase);
855b84 ¤   bnEnd(&bnexp);
bc4f0d ¤   bnEnd(&bnmod);
4befe6 }
39af5a
53a98b #endif¤ /* ] PGP_USEMPILIBWITHRSAREF */
98af5a
e3195d #endif¤ /* ] PGP_USERSAREF */
--73c5 0003fccbed040100209 Page 1 of pgpBSRSAGlue.c
bc38e5 /*
78b2c2 ·* pgpBSRSAGlue.c - Interface to BSafe Cryptographic toolkit from
6b2987 ·* RSA Data Security, Inc.
18775e ·*
566997 ·* This is an alternative to pgpRSAGlue.c, and should be used if the
8adc72 ·* use of the BSafe library is required for legal reasons.
c2775e ·*
7efc7b ·* This file uses BSafe to perform the actual encryption and decryption.
33aa96 ·* It must be linked with the BSafe library to function.
ee775e ·*
3085a1 ·* This code only accepts PKCS-style padding. ·Very old versions of PGP
f2e92a ·* used a different padding style, which will not be compatible with
4b8700 ·* this module.
78775e ·*
e44d54 ·* $Id: pgpBSRSAGlue.c,v 1.5.2.1 1998/10/06 22:42:10 hal Exp $
5b495d ·*/
67d83c ·
a838e5 /*
9edbeb ·* An alternative version of this module is used if BSafe is NOT needed.
94bd56 ·* This entire source file is under the control of the following conditional:
0e495d ·*/
fdaf5a
fd3051 #include "pgpSDKBuildFlags.h"
2eaf5a
6c5596 #if PGP_USEBSAFEFORRSA¤ /* [ */
44af5a
b70ccc #if PGP_MACINTOSH
dd36e5 #include "string.h"
727454 #endif
c0af5a
e2e2ff #include "pgpConfig.h"
d5af5a
2ea146 #include "pgpDebug.h"
c08c41 #include "pgpRSAGlue.h"
67007f #include "pgpKeyMisc.h"
9339fc #include "bn.h"
4b2f8d #include "pgpErrors.h"
6e2c96 #include "pgpRandomX9_17.h"
6c0d08 #include "pgpMem.h"
5aaf5a
f9af5a
9838e5 /*
e00097 ·* If you're using a legally encumbered library this will be
d0d924 ·* printed in the program banner.
46495d ·*/
4601f1 char const banner_legalese[] = "\
2ece7a Uses the BSafe(tm) Toolkit, which is copyright RSA Data Security, Inc.\n";
5faf5a
6baf5a
b4bec0 /* Include files from BSafe */
98e17b #include "aglobal.h"
da3ecf #include "bsafe.h"
36af5a
e8af5a
4152cf /* Control what is linked in from BSafe */
962b8d static B_ALGORITHM_METHOD *RSA_CHOOSER[] = {
c21b19 ¤   &AM_RSA_ENCRYPT,
c57db2 ¤   &AM_RSA_CRT_DECRYPT,
6d5ef3 ¤   (B_ALGORITHM_METHOD *)NULL
9f82f7 };
59af5a
e5af5a
1435d4 /* Return a standard error code on BSAFE errors */
faf047 #define CHKERR(err) \
b8138e ¤   if (err != 0) { \
79c2c4 ¤   ¤   err = kPGPError_PublicKeyUnimplemented; \
b91c9b ¤   ¤   goto error; \
3f9371 ¤   }
23af5a
a938e5 /*
1e36ba ·* This returns TRUE if the key is too big, returning the
3faecf ·* maximum number of bits that the library can accept.
--30ba 000d085264f40100209 Page 2 of pgpBSRSAGlue.c
47495d ·*/
82e556 #define MAXSIZE 2048
e14d2f int
294a31 rsaKeyTooBig(RSApub const *pub, RSAsec const *sec)
21bb36 {
f167ab ¤   if (pub) {
7f6b85 ¤   ¤   if (bnBits(&pub->n) > MAXSIZE)
278cd7 ¤   ¤   ¤   return MAXSIZE;
7b9371 ¤   }
a18631 ¤   if (sec) {
f430cf ¤   ¤   if (bnBits(&sec->n) > MAXSIZE)
388cd7 ¤   ¤   ¤   return MAXSIZE;
a59371 ¤   }
bd2354 ¤   return 0; /* OK */
0fefe6 }
2eaf5a
69367a /* Initialize BSafe pubkey structure from a RSApub. */
c5beb7 static int
530c93 rpubk_init(B_KEY_OBJ rpubk, RSApub const *pub,
3519f8 ¤   PGPMemoryMgrRef¤mgr)
2dbb36 {
9a0ed0 ¤   A_RSA_KEY kdata;
c0d259 ¤   PGPByte *buf;
1161fa ¤   PGPSize bufsize;
1017e6 ¤   int err;
7aaf5a
c9963e ¤   bufsize = bnBytes(&pub->n) + bnBytes(&pub->e);
0866b2 ¤   buf = PGPNewSecureData( mgr, bufsize, 0 );
388b27 ¤   kdata.modulus.data = buf;
dd41fd ¤   kdata.modulus.len = bnBytes(&pub->n);
007271 ¤   kdata.exponent.data = buf + kdata.modulus.len;
a2d7b8 ¤   kdata.exponent.len = bnBytes(&pub->e);
da5cfb ¤   bnExtractBigBytes (&pub->n, kdata.modulus.data, 0,
486ecd ¤   ¤   ¤   ¤   ¤   ¤   kdata.modulus.len);
f423ad ¤   bnExtractBigBytes (&pub->e, kdata.exponent.data, 0,
89cb9b ¤   ¤   ¤   ¤   ¤   ¤   kdata.exponent.len);
e03aa5 ¤   err = B_SetKeyInfo (rpubk, KI_RSAPublic, (POINTER)&kdata);
ac021a ¤   pgpAssert (err == 0);
09e675 ¤   pgpClearMemory (buf, bufsize);
b2a0b2 ¤   PGPFreeData (buf);
7c5ea8 ¤   return err;
cdefe6 }
29af5a
8ecd52 /* Initialize BSafe privkey structure from a RSAsec. */
d6beb7 static int
7ec31e rprivk_init(B_KEY_OBJ rprivk, RSAsec const *sec,
8119f8 ¤   PGPMemoryMgrRef¤mgr)
f8bb36 {
4a9d46 ¤   BigNum dmodp, dmodq, tmp;
7805ec ¤   A_RSA_CRT_KEY kdata;
91d259 ¤   PGPByte *buf;
7a61fa ¤   PGPSize bufsize;
b617e6 ¤   int err;
77af5a
e19946 ¤   /* Calculate d mod p-1 and d mod q-1 */
6f0202 ¤   bnBegin(&dmodp, mgr, TRUE);
d34a28 ¤   bnBegin(&dmodq, mgr, TRUE);
da5c21 ¤   bnBegin(&tmp, mgr, TRUE);
198d99 ¤   bnCopy(&tmp, &sec->p);
dff1b8 ¤   bnSubQ(&tmp, 1);
9567f3 ¤   bnMod(&dmodp, &sec->d, &tmp);
4d9122 ¤   bnCopy(&tmp, &sec->q);
81f1b8 ¤   bnSubQ(&tmp, 1);
29f4ba ¤   bnMod(&dmodq, &sec->d, &tmp);
92af5a
b18522 ¤   bufsize = bnBytes(&sec->n) + bnBytes(&sec->q) + bnBytes(&sec->p)
ba6d2f ¤   ¤   ¤   + bnBytes(&dmodq) + bnBytes(&dmodp) + bnBytes(&sec->u);
b266b2 ¤   buf = PGPNewSecureData( mgr, bufsize, 0 );
048b27 ¤   kdata.modulus.data = buf;
db5357 ¤   kdata.modulus.len = bnBytes(&sec->n);
941b46 ¤   kdata.prime[0].data = kdata.modulus.data + kdata.modulus.len;
d0d9ff ¤   kdata.prime[0].len = bnBytes(&sec->q);
--bc7a 000ca78e88a40100209 Page 3 of pgpBSRSAGlue.c
dc3617 ¤   kdata.prime[1].data = kdata.prime[0].data + kdata.prime[0].len;
41970c ¤   kdata.prime[1].len = bnBytes(&sec->p);
2be42d ¤   kdata.primeExponent[0].data = kdata.prime[1].data
73e9a2 ¤   ¤   ¤   ¤   + kdata.prime[1].len;
be65ee ¤   kdata.primeExponent[0].len = bnBytes(&dmodq);
3861e9 ¤   kdata.primeExponent[1].data = kdata.primeExponent[0].data
be9307 ¤   ¤   ¤   ¤   + kdata.primeExponent[0].len;
dbb405 ¤   kdata.primeExponent[1].len = bnBytes(&dmodp);
f89dfa ¤   kdata.coefficient.data = kdata.primeExponent[1].data
4312b8 ¤   ¤   ¤   ¤   + kdata.primeExponent[1].len;
9fbcbe ¤   kdata.coefficient.len = bnBytes(&sec->u);
54fd95 ¤   bnExtractBigBytes (&sec->n, kdata.modulus.data, 0,
4d6ecd ¤   ¤   ¤   ¤   ¤   ¤   kdata.modulus.len);
76a9ba ¤   bnExtractBigBytes (&sec->q, kdata.prime[0].data, 0,
790e21 ¤   ¤   ¤   ¤   ¤   ¤   kdata.prime[0].len);
597ea7 ¤   bnExtractBigBytes (&sec->p, kdata.prime[1].data, 0,
8943dc ¤   ¤   ¤   ¤   ¤   ¤   kdata.prime[1].len);
ef06bd ¤   bnExtractBigBytes (&dmodq, kdata.primeExponent[0].data, 0,
079523 ¤   ¤   ¤   ¤   ¤   ¤   kdata.primeExponent[0].len);
b18ed1 ¤   bnExtractBigBytes (&dmodp, kdata.primeExponent[1].data, 0,
80d8de ¤   ¤   ¤   ¤   ¤   ¤   kdata.primeExponent[1].len);
4cea24 ¤   bnExtractBigBytes (&sec->u, kdata.coefficient.data, 0,
dc3369 ¤   ¤   ¤   ¤   ¤   ¤   kdata.coefficient.len);
aee331 ¤   err = B_SetKeyInfo (rprivk, KI_RSA_CRT, (POINTER)&kdata);
48021a ¤   pgpAssert (err == 0);
86e675 ¤   pgpClearMemory (buf, bufsize);
4da0b2 ¤   PGPFreeData (buf);
78af5a
2b0425 ¤   bnEnd(&dmodp);
5b189e ¤   bnEnd(&dmodq);
a11dd8 ¤   bnEnd(&tmp);
fd5ea8 ¤   return err;
6cefe6 }
1faf5a
cc38e5 /*
f0addc ·* Encrypt a buffer holding a session key with an RSA public key
fd495d ·*/
4a4d2f int
89ab93 rsaPublicEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
4de64b ¤   RSApub const *pub, PGPRandomContext const *rc)
76bb36 {
d89163 ¤   unsigned bytes = bnBytes(&pub->n);
b28d7c ¤   PGPByte *buf = NULL;
3e6245 ¤   B_ALGORITHM_OBJ bobj = NULL;
634923 ¤   B_KEY_OBJ rpubk = NULL;
242477 ¤   unsigned int bufoutlen;
529353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
7c89b5 ¤   int err = 0;
daaf5a
7cbe92 ¤   pgpPKCSPack(bn, in, len, PKCS_PAD_ENCRYPTED, bytes, rc);
8461e5 ¤   buf = PGPNewSecureData (mgr, bytes, 0);
62e24f ¤   if (buf == NULL) {
37bce1 ¤   ¤   err = kPGPError_OutOfMemory;
a097ed ¤   ¤   goto error;
e19371 ¤   }
c6586c ¤   bnExtractBigBytes (bn, buf, 0, bytes);
ab137a ¤   bnSetQ (bn, 0);
30af5a
cd8353 ¤   /* Initialize BSafe public key structure */
ef5ac9 ¤   err = B_CreateAlgorithmObject (&bobj);
065ce8 ¤   CHKERR(err);
4924cd ¤   err = B_SetAlgorithmInfo (bobj, AI_RSAPublic, NULL);
615ce8 ¤   CHKERR(err);
68332d ¤   err = B_CreateKeyObject (&rpubk);
4c5ce8 ¤   CHKERR(err);
442022 ¤   err = rpubk_init(rpubk, pub, mgr);
e95ce8 ¤   CHKERR(err);
e7fb53 ¤   err = B_EncryptInit (bobj, rpubk, RSA_CHOOSER, (A_SURRENDER_CTX *)0);
f05ce8 ¤   CHKERR(err);
dbaf5a
9e2753 ¤   /* Encrypt data */
ca5b28 ¤   err = B_EncryptUpdate (bobj, buf, &bufoutlen, bytes, buf, bytes,
--7791 00004ccacd440100209 Page 4 of pgpBSRSAGlue.c
83e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
4f5ce8 ¤   CHKERR(err);
3623b0 ¤   err = B_EncryptFinal (bobj, buf+bufoutlen, &bufoutlen, bytes-bufoutlen,
d1e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
c45ce8 ¤   CHKERR(err);
8eaf5a
68904f ¤   B_DestroyKeyObject (&rpubk);
d43de3 ¤   rpubk = NULL;
5c6a02 ¤   B_DestroyAlgorithmObject (&bobj);
00a036 ¤   bobj = NULL;
36af5a
494414 ¤   /* Return to bn format */
ba12db ¤   bnInsertBigBytes (bn, buf, 0, bytes);
362119 ¤   pgpClearMemory (buf, bytes);
e0a0b2 ¤   PGPFreeData (buf);
605065 ¤   buf = NULL;
29af5a
a960ff error:
1dc8c9 ¤   if (buf) {
8d1c71 ¤   ¤   pgpClearMemory (buf, bytes);
c74253 ¤   ¤   PGPFreeData (buf);
b59371 ¤   }
33d93e ¤   if (rpubk)
7ead27 ¤   ¤   B_DestroyKeyObject (&rpubk);
bf6324 ¤   if (bobj)
1a56ec ¤   ¤   B_DestroyAlgorithmObject (&bobj);
1a67c5 ¤
f75ea8 ¤   return err;
83efe6 }
8faf5a
0aaf5a
4838e5 /*
30322b ·* Do an RSA signing operation using the secret key
b2495d ·*/
284d2f int
57b4a4 rsaPrivateEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
f084e6 ¤   RSAsec const *sec)
03bb36 {
fb83c9 ¤   unsigned bytes = bnBytes(&sec->n);
688d7c ¤   PGPByte *buf = NULL;
c46245 ¤   B_ALGORITHM_OBJ bobj = NULL;
cbbb8a ¤   B_KEY_OBJ rprivk = NULL;
002477 ¤   unsigned int bufoutlen;
909353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
f617e6 ¤   int err;
98af5a
979a62 ¤   pgpPKCSPack(bn, in, len, PKCS_PAD_SIGNED, bytes,
7f968c ¤   ¤   (PGPRandomContext const *)NULL);
ed61e5 ¤   buf = PGPNewSecureData (mgr, bytes, 0);
1de24f ¤   if (buf == NULL) {
c0bce1 ¤   ¤   err = kPGPError_OutOfMemory;
5b97ed ¤   ¤   goto error;
1e9371 ¤   }
d6586c ¤   bnExtractBigBytes (bn, buf, 0, bytes);
d3137a ¤   bnSetQ (bn, 0);
a2af5a
8db524 ¤   /* Initialize BSafe private key structure */
6b5ac9 ¤   err = B_CreateAlgorithmObject (&bobj);
f65ce8 ¤   CHKERR(err);
80f29a ¤   err = B_SetAlgorithmInfo (bobj, AI_RSAPrivate, NULL);
135ce8 ¤   CHKERR(err);
eac711 ¤   err = B_CreateKeyObject (&rprivk);
ab5ce8 ¤   CHKERR(err);
7b2273 ¤   err = rprivk_init(rprivk, sec, mgr);
845ce8 ¤   CHKERR(err);
033fdb ¤   err = B_DecryptInit (bobj, rprivk, RSA_CHOOSER, (A_SURRENDER_CTX *)0);
055ce8 ¤   CHKERR(err);
36af5a
a56065 ¤   /* "Decrypt" (actually sign) data */
4e69e5 ¤   err = B_DecryptUpdate (bobj, buf, &bufoutlen, bytes, buf, bytes,
4ae12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
045ce8 ¤   CHKERR(err);
--faea 000c5302aed40100209 Page 5 of pgpBSRSAGlue.c
c48362 ¤   err = B_DecryptFinal (bobj, buf+bufoutlen, &bufoutlen, bytes-bufoutlen,
e2e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
f75ce8 ¤   CHKERR(err);
85af5a
9a87a6 ¤   B_DestroyKeyObject (&rprivk);
8b7df2 ¤   rprivk = NULL;
726a02 ¤   B_DestroyAlgorithmObject (&bobj);
95a036 ¤   bobj = NULL;
beaf5a
4a4414 ¤   /* Return to bn format */
c912db ¤   bnInsertBigBytes (bn, buf, 0, bytes);
d62119 ¤   pgpClearMemory (buf, bytes);
b5a0b2 ¤   PGPFreeData (buf);
705065 ¤   buf = NULL;
9367c5 ¤
8e60ff error:
b5c8c9 ¤   if (buf) {
b81c71 ¤   ¤   pgpClearMemory (buf, bytes);
ed4253 ¤   ¤   PGPFreeData (buf);
e59371 ¤   }
dfdef8 ¤   if (rprivk)
e668d5 ¤   ¤   B_DestroyKeyObject (&rprivk);
ec6324 ¤   if (bobj)
8256ec ¤   ¤   B_DestroyAlgorithmObject (&bobj);
4d67c5 ¤
555ea8 ¤   return err;
01efe6 }
ffaf5a
2f38e5 /*
4431cb ·* These destroy (actually, replace with a decrypted version) the
e13a47 ·* input bignum bn.
14775e ·*
aef594 ·* Performs an RSA signature check. ·Returns a prefix of the unwrapped
d9140d ·* data in the given buf. ·Returns the length of the untruncated
6c5d6b ·* data, which may exceed "len". Returns <0 on error.
73495d ·*/
f84d2f int
80d7d4 rsaPublicDecrypt(PGPByte *outbuf, unsigned len, BigNum *bn,
9e4678 ¤   RSApub const *pub)
eebb36 {
629163 ¤   unsigned bytes = bnBytes(&pub->n);
8d8d7c ¤   PGPByte *buf = NULL;
a06245 ¤   B_ALGORITHM_OBJ bobj = NULL;
a54923 ¤   B_KEY_OBJ rpubk = NULL;
932477 ¤   unsigned int bufoutlen;
999353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
b817e6 ¤   int err;
abaf5a
2b61e5 ¤   buf = PGPNewSecureData (mgr, bytes, 0);
22e24f ¤   if (buf == NULL) {
e4bce1 ¤   ¤   err = kPGPError_OutOfMemory;
4697ed ¤   ¤   goto error;
679371 ¤   }
cd586c ¤   bnExtractBigBytes (bn, buf, 0, bytes);
ffaf5a
f18353 ¤   /* Initialize BSafe public key structure */
a85ac9 ¤   err = B_CreateAlgorithmObject (&bobj);
ec5ce8 ¤   CHKERR(err);
8a24cd ¤   err = B_SetAlgorithmInfo (bobj, AI_RSAPublic, NULL);
aa5ce8 ¤   CHKERR(err);
0c332d ¤   err = B_CreateKeyObject (&rpubk);
ff5ce8 ¤   CHKERR(err);
c32022 ¤   err = rpubk_init(rpubk, pub, mgr);
645ce8 ¤   CHKERR(err);
fcfb53 ¤   err = B_EncryptInit (bobj, rpubk, RSA_CHOOSER, (A_SURRENDER_CTX *)0);
d55ce8 ¤   CHKERR(err);
10af5a
6e6131 ¤   /* Do an RSA encryption to recover PKCS-1 padded signature */
e35b28 ¤   err = B_EncryptUpdate (bobj, buf, &bufoutlen, bytes, buf, bytes,
72e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
5d5ce8 ¤   CHKERR(err);
c523b0 ¤   err = B_EncryptFinal (bobj, buf+bufoutlen, &bufoutlen, bytes-bufoutlen,
--e584 000353251d540100209 Page 6 of pgpBSRSAGlue.c
83e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
4f5ce8 ¤   CHKERR(err);
caaf5a
a9904f ¤   B_DestroyKeyObject (&rpubk);
3d3de3 ¤   rpubk = NULL;
0c6a02 ¤   B_DestroyAlgorithmObject (&bobj);
82a036 ¤   bobj = NULL;
fdaf5a
cd4414 ¤   /* Return to bn format */
0a137a ¤   bnSetQ (bn, 0);
9112db ¤   bnInsertBigBytes (bn, buf, 0, bytes);
3f2119 ¤   pgpClearMemory (buf, bytes);
66a0b2 ¤   PGPFreeData (buf);
b85065 ¤   buf = NULL;
f667c5 ¤
6116d7 ¤   err = pgpPKCSUnpack(outbuf, len, bn, PKCS_PAD_SIGNED, bytes);
46af5a
e860ff error:
e9c8c9 ¤   if (buf) {
321c71 ¤   ¤   pgpClearMemory (buf, bytes);
534253 ¤   ¤   PGPFreeData (buf);
749371 ¤   }
bad93e ¤   if (rpubk)
72ad27 ¤   ¤   B_DestroyKeyObject (&rpubk);
d96324 ¤   if (bobj)
5a56ec ¤   ¤   B_DestroyAlgorithmObject (&bobj);
f467c5 ¤
a95ea8 ¤   return err;
20efe6 }
e0af5a
a738e5 /*
469e39 ·* Performs an RSA decryption. ·Returns a prefix of the unwrapped
59140d ·* data in the given buf. ·Returns the length of the untruncated
035d6b ·* data, which may exceed "len". Returns <0 on error.
db495d ·*/
314d2f int
14749c rsaPrivateDecrypt(PGPByte *outbuf, unsigned len, BigNum *bn,
1a84e6 ¤   RSAsec const *sec)
35bb36 {
4183c9 ¤   unsigned bytes = bnBytes(&sec->n);
8a8d7c ¤   PGPByte *buf = NULL;
f26245 ¤   B_ALGORITHM_OBJ bobj = NULL;
c7bb8a ¤   B_KEY_OBJ rprivk = NULL;
d52477 ¤   unsigned int bufoutlen;
9b9353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
b417e6 ¤   int err;
76af5a
a861e5 ¤   buf = PGPNewSecureData (mgr, bytes, 0);
cfe24f ¤   if (buf == NULL) {
93bce1 ¤   ¤   err = kPGPError_OutOfMemory;
0597ed ¤   ¤   goto error;
219371 ¤   }
3e586c ¤   bnExtractBigBytes (bn, buf, 0, bytes);
d9af5a
ebb524 ¤   /* Initialize BSafe private key structure */
1e5ac9 ¤   err = B_CreateAlgorithmObject (&bobj);
605ce8 ¤   CHKERR(err);
c8f29a ¤   err = B_SetAlgorithmInfo (bobj, AI_RSAPrivate, NULL);
565ce8 ¤   CHKERR(err);
93c711 ¤   err = B_CreateKeyObject (&rprivk);
c85ce8 ¤   CHKERR(err);
5d2273 ¤   err = rprivk_init(rprivk, sec, mgr);
635ce8 ¤   CHKERR(err);
0d3fdb ¤   err = B_DecryptInit (bobj, rprivk, RSA_CHOOSER, (A_SURRENDER_CTX *)0);
c15ce8 ¤   CHKERR(err);
c1af5a
32eb23 ¤   /* Do an RSA decryption to recover PKCS-1 padded key */
ea69e5 ¤   err = B_DecryptUpdate (bobj, buf, &bufoutlen, bytes, buf, bytes,
71e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
525ce8 ¤   CHKERR(err);
4d8362 ¤   err = B_DecryptFinal (bobj, buf+bufoutlen, &bufoutlen, bytes-bufoutlen,
35e12f ¤   ¤   ¤   ¤   ¤   ¤   (B_ALGORITHM_OBJ)NULL, (A_SURRENDER_CTX *)NULL);
--7f61 00057a5b47540100209 Page 7 of pgpBSRSAGlue.c
485ce8 ¤   CHKERR(err);
4daf5a
5087a6 ¤   B_DestroyKeyObject (&rprivk);
667df2 ¤   rprivk = NULL;
1f6a02 ¤   B_DestroyAlgorithmObject (&bobj);
efa036 ¤   bobj = NULL;
d9af5a
794414 ¤   /* Return to bn format */
0e137a ¤   bnSetQ (bn, 0);
4012db ¤   bnInsertBigBytes (bn, buf, 0, bytes);
472119 ¤   pgpClearMemory (buf, bytes);
2ea0b2 ¤   PGPFreeData (buf);
355065 ¤   buf = NULL;
1667c5 ¤
12f6aa ¤   err = pgpPKCSUnpack(outbuf, len, bn, PKCS_PAD_ENCRYPTED, bytes);
c3af5a
fc60ff error:
5cc8c9 ¤   if (buf) {
ae1c71 ¤   ¤   pgpClearMemory (buf, bytes);
604253 ¤   ¤   PGPFreeData (buf);
889371 ¤   }
20def8 ¤   if (rprivk)
6268d5 ¤   ¤   B_DestroyKeyObject (&rprivk);
b36324 ¤   if (bobj)
7456ec ¤   ¤   B_DestroyAlgorithmObject (&bobj);
ed67c5 ¤
f05ea8 ¤   return err;
e2efe6 }
19af5a
4caf5a
ed3c9f /************************* BSAFE Required Functions *******************/
69af5a
1338e5 /*
ce4882 ·* These functions are called by the BSAFE library to perform elementary
da948f ·* operations
13495d ·*/
d5af5a
a1af5a
8167da void CALL_CONV T_memset (p, c, count)
125b91 POINTER p;
7ffb66 int c;
7168b6 unsigned int count;
54bb36 {
c6f046 ¤   if (count != 0)
63bda0 ¤   ¤   pgpFillMemory (p, count, c);
bdefe6 }
99af5a
70a107 void CALL_CONV T_memcpy (d, s, count)
d9f36b POINTER d, s;
1168b6 unsigned int count;
50bb36 {
48f046 ¤   if (count != 0)
1850e3 ¤   ¤   pgpCopyMemory (s, d, count);
d1efe6 }
3baf5a
84ee93 void CALL_CONV T_memmove (d, s, count)
edf36b POINTER d, s;
2668b6 unsigned int count;
89bb36 {
9cf046 ¤   if (count != 0)
3c50e3 ¤   ¤   pgpCopyMemory (s, d, count);
44efe6 }
09af5a
f091db int CALL_CONV T_memcmp (s1, s2, count)
1e0f10 POINTER s1, s2;
7468b6 unsigned int count;
48bb36 {
a48302 ¤   if (count == 0)
03bbde ¤   ¤   return 0;
80e4c3 ····return memcmp (s1, s2, count);
cdefe6 }
57af5a
--2756 001a4f56c6940100209 Page 8 of pgpBSRSAGlue.c
efb8f7 POINTER CALL_CONV T_malloc (size)
5def02 unsigned int size;
13bb36 {
4c0958 ¤   PGPMemoryMgrRef mgr = PGPGetDefaultMemoryMgr();
6b67c5 ¤
84ba74 ¤   if (IsNull (mgr))
697ed2 ¤   ¤   return NULL;
853d48 ¤   return (POINTER) PGPNewSecureData( mgr, size, 0 );
e7efe6 }
83af5a
438ebc POINTER CALL_CONV T_realloc (p, size)
935b91 POINTER p;
05ef02 unsigned int size;
5cbb36 {
100958 ¤   PGPMemoryMgrRef mgr = PGPGetDefaultMemoryMgr();
7667c5 ¤
37ba74 ¤   if (IsNull (mgr))
4e7ed2 ¤   ¤   return NULL;
eb55a4 ¤   /* pgpReallocData will not know to do securely if pass null ptr */
fa2f1f ¤   if (IsNull (p))
d33a73 ¤   ¤   return (POINTER) PGPNewSecureData( mgr, size, 0 );
d615cc ¤   PGPReallocData (mgr, &p, size, 0);
be381d ¤   return p;
6cefe6 }
95af5a
e98384 void CALL_CONV T_free (p)
8b5b91 POINTER p;
f7bb36 {
8dae48 ¤   if (IsntNull (p))
014bbf ¤   ¤   PGPFreeData (p);
a5efe6 }
59af5a
38af5a
98af5a
a4c3ed #endif¤ /* ] PGP_USEBSAFEFORRSA */
--2eee 0001c99d5cb4010020a Page 1 of pgpDSAKey.c
bc38e5 /*
5926a4 ·* pgpDSAKey.c
cb97fe ·* Signatures using the Digital Signature Algorithm
fb775e ·*
84b035 ·* $Id: pgpDSAKey.c,v 1.51.2.1 1998/09/24 18:39:27 hal Exp $
21495d ·*/
d1af5a
b2324c #include <string.h>
63e2ff #include "pgpConfig.h"
c66773 #include "pgpMemoryMgr.h"
e3af5a
4aa146 #include "pgpDebug.h"
f6c00a #include "pgpDSAKey.h"
34007f #include "pgpKeyMisc.h"
f139fc #include "bn.h"
4f0e2f #include "pgpSymmetricCipherPriv.h"
211e2d #include "pgpCFBPriv.h"
a35417 #include "pgpHashPriv.h"
720d08 #include "pgpMem.h"
5e2f8d #include "pgpErrors.h"
87c223 #include "pgpFixedKey.h"
1312ca #include "bnprime.h"
4acdc2 #include "pgpPubKey.h"
afc9be #include "pgpRandomPool.h"
130f03 #include "pgpRandomContext.h"
ac2c96 #include "pgpRandomX9_17.h"
425579 #include "pgpStr2Key.h"
fbc26c #include "pgpContext.h"
d70d6d #include "pgpEnv.h"
b5af5a
c70596 #ifndef NULL
e8699b #define NULL 0
987454 #endif
8eaf5a
28dd16 #define ASSERTDSA(alg) pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_DSA)
82af5a
f107e1 #define MAX_DSA_PRIME_BITS¤ ¤   1024
13af5a
0d2a0f typedef struct DSApub {
715c6f ¤   BigNum p;¤  ¤   /* Public prime */
353703 ¤   BigNum q;¤  ¤   /* Public order of generator */
eea84e ¤   BigNum g;¤  ¤   /* Public generator */
3d7e6c ¤   BigNum y;¤  ¤   /* Public key, g**x mod p */
35ee07 } DSApub;
cfaf5a
f58e89 typedef struct DSAsec {
0ed34b ¤   BigNum p;¤  ¤   /* Copy of public parameters */
762c74 ¤   BigNum q;
ae7f38 ¤   BigNum g;
50eab6 ¤   BigNum y;
8f3dbf ¤   BigNum x;¤  ¤   /* Secret key, discrete log of y */
6f6ab6 } DSAsec;
09af5a
7baf5a
af8628 /* A PGPSecKey's priv points to this, an DSAsec plus the encrypted form... */
ffa225 /* This struct is always allocated using PGPNewSecureData */
310838 typedef struct DSAsecPlus
f1bb36 {
378a97 ¤   PGPContextRef¤  context;
ffedcf ¤   DSAsec s;
e5775a ¤   PGPByte *cryptkey;
6e2d33 ¤   size_t ckalloc, cklen;
47b3fc ¤   int locked;
62ca70 } DSAsecPlus;
5aaf5a
40bfda /** Public key functions **/
45af5a
7c2978 static void
fb8acd dsaPubDestroy(PGPPubKey *pubkey)
b4bb36 {
f0d25c ¤   DSApub *pub = (DSApub *)pubkey->priv;
1c7925 ¤   PGPContextRef¤  ¤   context;
--d562 0007e1a3d1f4010020a Page 2 of pgpDSAKey.c
e0af5a
2e1511 ¤   pgpAssertAddrValid( pubkey, PGPPubKey );
438235 ¤   context¤= pubkey->context;
70af5a
a28679 ¤   pgpAssert( pgpContextIsValid( context ) );
bc67c5 ¤
237b53 ¤   ASSERTDSA(pubkey->pkAlg);
9767c5 ¤
4d7511 ¤   bnEnd(&pub->p);
8369aa ¤   bnEnd(&pub->q);
4be191 ¤   bnEnd(&pub->g);
8c8c72 ¤   bnEnd(&pub->y);
420e47 ¤   pgpClearMemory( pub, ·sizeof(pub));
b5fa7b ¤   pgpContextMemFree( context, pub);
d45d33 ¤   pgpClearMemory( pubkey, ·sizeof(pubkey));
b02ba6 ¤   pgpContextMemFree( context, pubkey);
39efe6 }
1faf5a
25af5a
13beb7 static int
1ca5a8 dsaKeyTooBig(struct DSApub const *pub, struct DSAsec const *sec)
05bb36 {
fd73bd ¤   unsigned maxsize = MAX_DSA_PRIME_BITS;
5d67ab ¤   if (pub) {
df178f ¤   ¤   if (bnBits(&pub->p) > maxsize)
3fc704 ¤   ¤   ¤   return maxsize;
c29371 ¤   }
648631 ¤   if (sec) {
974cc5 ¤   ¤   if (bnBits(&sec->p) > maxsize)
90c704 ¤   ¤   ¤   return maxsize;
539371 ¤   }
75b379 ¤   /* Else OK */
a53e6b ¤   return 0;
51efe6 }
30af5a
5daf5a
0da863 /* Return the largest possible PGPESK size for a given key */
8d5d09 static size_t
1beec1 dsaPubMaxesk(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
34bb36 {
aef2e1 ¤   (void)pubkey;
f61c0d ¤   (void)format;
670b93 ¤   return kPGPError_PublicKeyUnimplemented;
45efe6 }
89af5a
495d09 static size_t
3c06d6 dsaPubMaxdecrypted(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
fbbb36 {
74f2e1 ¤   (void)pubkey;
3d1c0d ¤   (void)format;
900b93 ¤   return kPGPError_PublicKeyUnimplemented;
bfefe6 }
6caf5a
745d09 static size_t
0122e9 dsaPubMaxsig(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
4dbb36 {
904cc5 ¤   DSApub const *pub = (DSApub *)pubkey->priv;
4eaf5a
f47b53 ¤   ASSERTDSA(pubkey->pkAlg);
3e9850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
6ba5eb ¤   ¤   return 2*( 2 + bnBytes(&pub->q) );
3561bb ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1)
f5eceb ¤   ¤   return 2*( bnBytes(&pub->q) );
5069ae ¤   else if (format == kPGPPublicKeyMessageFormat_X509) {
3d5cbb ¤   ¤   /* BITSTRING, length, 0, SEQUENCE, length, INT, INT */
9170fe ¤   ¤   PGPUInt32 len, lenlen;
57fe24 ¤   ¤   PGPUInt32 qbytes = bnBytes(&pub->q);
16fca1 ¤   ¤   len = 2*(pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1);
0bf385 ¤   ¤   lenlen = pgpBnX509LenLen(len);
47a5e1 ¤   ¤   return 1 + pgpBnX509LenLen(1+lenlen+len) + 1 + 1 + lenlen + len;
179371 ¤   }
7e4aac ¤   pgpAssert(0);
--19cc 000f4a7826f4010020a Page 3 of pgpDSAKey.c
303e6b ¤   return 0;
06efe6 }
aeaf5a
64af5a
4daf5a
2438e5 /*
551034 ·* Given a buffer of at least "maxesk" bytes, make an PGPESK
f74d6c ·* into it and return the size of the PGPESK, or <0.
fa495d ·*/
a4beb7 static int
a05315 dsaEncrypt(PGPPubKey const *pubkey, PGPByte const *key,
7ce590 ···········size_t keylen, PGPByte *esk, size_t *esklen,
326387 ···········PGPRandomContext const *rc, PGPPublicKeyMessageFormat format)
e5bb36 {
6df2e1 ¤   (void)pubkey;
349b3e ¤   (void)key;
2cede5 ¤   (void)keylen;
ef4290 ¤   (void)esk;
e17a0a ¤   (void)esklen;
2a76a2 ¤   (void)rc;
da1c0d ¤   (void)format;
1e0b93 ¤   return kPGPError_PublicKeyUnimplemented;
0defe6 }
3daf5a
75af5a
70af5a
0e38e5 /*
e5503a ·* Return 1 if (sig,siglen) is a valid MPI which signs
2f6aba ·* hash, of type h. ·Verify that the type is SHA.1 and
2c88c8 ·* the hash itself matches.
1d495d ·*/
80beb7 static int
353252 dsaVerify(PGPPubKey const *pubkey, PGPByte const *sig,
83414d ¤   size_t siglen, PGPHashVTBL const *h, PGPByte const *hash,
6e6fc3 ¤   PGPPublicKeyMessageFormat format)
1bbb36 {
90a0f7 #if PGP_VERIFY_DISABLE /* [ */
3eaf5a
d9f2e1 ¤   (void)pubkey;
2677e4 ¤   (void)sig;
1651a9 ¤   (void)siglen;
7ac6fd ¤   (void)h;
374902 ¤   (void)hash;
bf1c0d ¤   (void)format;
39e63f ¤   return kPGPError_FeatureNotAvailable;
1daf5a
6508c4 #else /* PGP_VERIFY_DISABLE */ ·/* ] ·[ */
79af5a
664cc5 ¤   DSApub const *pub = (DSApub *)pubkey->priv;
14e6b5 ¤   BigNum r, s, w, u2;
b14ba4 ¤   int i;
844776 ¤   unsigned qbytes;
fc0ccf ¤   size_t off;
dd16d3 ¤   PGPMemoryMgrRef¤mgr¤= PGPGetContextMemoryMgr( pubkey->context );
eaaf5a
4f7b53 ¤   ASSERTDSA(pubkey->pkAlg);
9aaf5a
385c43 ¤   /* Hashsize must be at least as big as size of q for legal sig */
38f423 ¤   if (h->hashsize*8 < bnBits(&pub->q)) {
ebbbde ¤   ¤   return 0;
ae9371 ¤   }
8baf5a
c2b177 #if 0
56eaca ¤   /* Allow generalizations of SHA, as long as they are big enough */
1c38f4 ¤   if (h->algorithm != kPGPHashAlgorithm_SHA)
cfbad8 ¤   ¤   return 0;¤  /* No match for sure! */
567454 #endif
0baf5a
e1192e ¤   bnBegin(&r, mgr, FALSE );
050921 ¤   bnBegin(&s, mgr, FALSE );
2b491d ¤   bnBegin(&w, mgr, FALSE );
f40079 ¤   bnBegin(&u2, mgr, FALSE );
--079f 0008509d1eb4010020a Page 4 of pgpDSAKey.c
e0af5a
7e7039 ¤   qbytes = bnBytes(&pub->q);
b3af5a
002713 ¤   /* sig holds two values. ·Get first, r, from sig. */
b96cdb ¤   off = 0;
8c7e57 ¤   if (format == kPGPPublicKeyMessageFormat_X509) {
8b8e0d ¤   ¤   /* Parse BITSTRING/SEQUENCE header for 509 sig data */
5ab5c9 ¤   ¤   PGPByte const *sigp = sig + off;
8e6b31 ¤   ¤   PGPUInt32 len;
00ce40 ¤   ¤   if (pgpBnX509TagLen(&sigp, &len) != X509_TAG_BITSTRING) {
1772d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
3d1dc4 ¤   ¤   ¤   goto done;
320fe4 ¤   ¤   }
19a54d ¤   ¤   /* BITSTRING should have 0 leftover bits */
380ec4 ¤   ¤   if (*sigp++ != 0) {
ae72d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
f21dc4 ¤   ¤   ¤   goto done;
920fe4 ¤   ¤   }
b1080b ¤   ¤   if (pgpBnX509TagLen(&sigp, &len) != X509_TAG_SEQUENCE) {
ca72d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
fc1dc4 ¤   ¤   ¤   goto done;
ae0fe4 ¤   ¤   }
36428c ¤   ¤   off += sigp - sig;
2a8859 ¤   ¤   if (len != siglen - off) {
c872d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
df1dc4 ¤   ¤   ¤   goto done;
3c0fe4 ¤   ¤   }
e29371 ¤   }
3544b8 ¤   i = pgpBnGetFormatted(&r, sig+off, siglen-off, qbytes, format);
9207eb ¤   if (i <= 0)
4e84fc ¤   ¤   goto fail;
b2089d ¤   /* Get 2nd value, s, from SIG */
490f96 ¤   off += i;
b3da6f ¤   i = pgpBnGetFormatted(&s, sig+off, siglen-off, qbytes, format);
5307eb ¤   if (i <= 0)
9584fc ¤   ¤   goto fail;
e40f96 ¤   off += i;
f88e1c ¤   if (off != siglen) {
43e5ca ¤   ¤   i = kPGPError_BadSignatureSize;
22262d ¤   ¤   goto done;
8d9371 ¤   }
99af5a
42d8af ¤   /*
ce6d7c ¤   ·* Sanity-check r and s against the subprime q. ·Both should
72a23a ¤   ·* be less than q. ·If not, the signature is clearly bad.
56a4e3 ¤   ·*/
156276 ¤   if (bnCmp(&r, &pub->q) >= 0 || bnCmp(&s, &pub->q) >= 0) {
aefcbf ¤   ¤   i = 0;¤ /* FAIL */
59262d ¤   ¤   goto done;
179371 ¤   }
0567c5 ¤
49d76d ¤   /* Reconstruct hash as u2 */
71c518 ¤   if (bnInsertBigBytes(&u2, hash, 0, bnBytes(&pub->q)) < 0)
7d5b40 ¤   ¤   goto nomem;
e6af5a
b6d8af ¤   /*
ac2934 ¤   ·* Calculate DSS check function....
61aa51 ¤   ·* Given signature (r,s) and hash H (in bn), compute:
d3fec1 ¤   ·* w = s^-1 mod q
dc0efd ¤   ·* u1 = H * w mod q
dda2e3 ¤   ·* u2 = r * w mod q
3d7a68 ¤   ·* v = g^u1 * y^u2 mod p
6751a0 ¤   ·* if v == r mod q, the signature checks.
379714 ¤   ·*
4f20fe ¤   ·* To save space, we put u1 into s, H into u2, and v into w.
2ca4e3 ¤   ·*/
02b1e4 ¤   if (bnInv(&w, &s, &pub->q) < 0)
315b40 ¤   ¤   goto nomem;
4d73dd ¤   if (bnMul(&s, &u2, &w) < 0 || bnMod(&s, &s, &pub->q) < 0)
235b40 ¤   ¤   goto nomem;
19a44f ¤   if (bnMul(&u2, &r, &w) < 0 || bnMod(&u2, &u2, &pub->q) < 0)
855b40 ¤   ¤   goto nomem;
--e51e 0003efe2c334010020a Page 5 of pgpDSAKey.c
e0af5a
d21faf ········/* Now for the expensive part... */
4baf5a
ee9120 ········if (bnDoubleExpMod(&w, &pub->g, &s, &pub->y, &u2, &pub->p) < 0)
36ff22 ················goto nomem;
0e5421 ········if (bnMod(&w, &w, &pub->q) < 0)
11ff22 ················goto nomem;
25af5a
5e1509 ¤   /* Compare result with r, should be equal */
731700 ¤   i = bnCmp(&w, &r) == 0;
72af5a
2bc48e ¤   goto done;
74af5a
0c115d fail:
4c5451 ¤   if (!i)
1ae5ca ¤   ¤   i = kPGPError_BadSignatureSize;
a5c48e ¤   goto done;
6eac52 nomem:
a730c4 ¤   i = kPGPError_OutOfMemory;
35c48e ¤   goto done;
5ab38c done:
c0c4ba ¤   bnEnd(&u2);
6ab586 ¤   bnEnd(&w);
8bc76a ¤   bnEnd(&s);
7fdbd1 ¤   bnEnd(&r);
82af5a
202196 ¤   return i;
58af5a
0a5156 #endif /* PGP_VERIFY_DISABLE */ /* ] */
14efe6 }
65af5a
a5af5a
3538e5 /*
4d5ebc ·* Turn a PGPPubKey into the algorithm-specific parts of a public key.
4b00dd ·* A public key's DSA-specific part is:
dd775e ·*
d7682a ·* ·0 ·····2+i ·MPI for prime
bb7a31 ·* 2+i ····2+t ·MPI for order
759a50 ·* 4+i+t ··2+u¤ MPI for generator
96ed4a ·* 6+i+t+u 2+v¤ MPI for public key
7c34d4 ·* 8+i+t+u+v
86495d ·*/
ba5d09 static size_t
43e06e dsaPubBufferLength(PGPPubKey const *pubkey)
35bb36 {
4c4cc5 ¤   DSApub const *pub = (DSApub *)pubkey->priv;
44af5a
1e9cd8 ¤   return 8 + bnBytes(&pub->p) + bnBytes(&pub->q) +
cbcc19 ¤   ¤   ···bnBytes(&pub->g) + bnBytes(&pub->y);
9cefe6 }
feaf5a
e82978 static void
0270ce dsaPubToBuffer(PGPPubKey const *pubkey, PGPByte *buf)
29bb36 {
dc4cc5 ¤   DSApub const *pub = (DSApub *)pubkey->priv;
d53876 ¤   unsigned off;
67af5a
196cdb ¤   off = 0;
426b62 ¤   off += pgpBnPutPlain(&pub->p, buf+off);
e56ecf ¤   off += pgpBnPutPlain(&pub->q, buf+off);
dc29f1 ¤   off += pgpBnPutPlain(&pub->g, buf+off);
a243a7 ¤   off += pgpBnPutPlain(&pub->y, buf+off);
94efe6 }
e9af5a
fdaf5a
a8bbab /* A little helper function that's used twice */
d22978 static void
d38eda dsaFillPubkey(PGPPubKey *pubkey, DSApub *pub)
96bb36 {
5f1756 ¤   pubkey->next¤   ·= NULL;
0e6ddc ¤   pubkey->pkAlg¤  ·= kPGPPublicKeyAlgorithm_DSA;
3e67ea ¤   pubkey->priv¤   ·= pub;
--cae3 0000b7c088a4010020a Page 6 of pgpDSAKey.c
f95db6 ¤   pubkey->destroy ·= dsaPubDestroy;
a19d5d ¤   pubkey->maxesk ··= dsaPubMaxesk;
479e49 ¤   pubkey->maxsig ··= dsaPubMaxsig;
031b3a ¤   pubkey->maxdecrypted ··= dsaPubMaxdecrypted;
d06f05 ¤   pubkey->encrypt ·= dsaEncrypt;
ec8daa ¤   pubkey->verify ··= dsaVerify;
4018bb ¤   pubkey->bufferLength ·= dsaPubBufferLength;
f2820c ¤   pubkey->toBuffer = dsaPubToBuffer;
31efe6 }
1eaf5a
9caf5a
8338e5 /*
145a5c ·* Turn the algorithm-specific parts of a public key into a PGPPubKey
e7da23 ·* structure. ·A public key's DSA-specific part is:
0a775e ·*
eb682a ·* ·0 ·····2+i ·MPI for prime
a87a31 ·* 2+i ····2+t ·MPI for order
ac9a50 ·* 4+i+t ··2+u¤ MPI for generator
02ed4a ·* 6+i+t+u 2+v¤ MPI for public key
a834d4 ·* 8+i+t+u+v
6e495d ·*/
5b40b4 PGPPubKey *
6a9071 dsaPubFromBuf(
85520e ¤   PGPContextRef¤  context,
a24d2b ¤   PGPByte const *¤buf,
b439e0 ¤   size_t¤ ¤   ¤   size,
3d6429 ¤   PGPError *¤ ¤   error)
d1bb36 {
c536c1 ¤   PGPPubKey *pubkey;
71553b ¤   DSApub *pub;
3d914c ¤   unsigned i, t, u, v;
f8de2a ¤   int w;
1ce74e ¤   PGPError¤   err = kPGPError_OutOfMemory;
296479 ¤   PGPMemoryMgrRef¤mgr¤= PGPGetContextMemoryMgr( context );
6267c5 ¤
42bac4 ¤   bnInit();
0faf5a
05cffc ¤   w = pgpBnParse(buf, size, 4, &i, &t, &u, &v);
005e2e ¤   if (w < 0) {
cb6f38 ¤   ¤   *error = (PGPError)w;
de7ed2 ¤   ¤   return NULL;
1c9371 ¤   }
0e07eb ¤   if (t <= i+2 || (buf[t-1] & 1) == 0) {¤ /* Too small or even prime p */
318997 ¤   ¤   *error = kPGPError_MalformedKeyComponent;
6a7ed2 ¤   ¤   return NULL;
619371 ¤   }
fd59b9 ¤   if (u <= t+2 || (buf[u-1] & 1) == 0) {¤ /* Too small or even order q */
698997 ¤   ¤   *error = kPGPError_MalformedKeyComponent;
bb7ed2 ¤   ¤   return NULL;
109371 ¤   }
bd0cec ¤   pub = (DSApub *)pgpContextMemAlloc( context,
9430c7 ¤   ¤   sizeof(*pub), kPGPMemoryMgrFlags_Clear);
f267ab ¤   if (pub) {
9d545a ¤   ¤   pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
9e7dcd ¤   ¤   ¤   sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
70d646 ¤   ¤   if (pubkey) {
a0aa14 ¤   ¤   ¤   pubkey->context¤= context;
ed87c7 ¤   ¤   ¤
2dcf5c ¤   ¤   ¤   bnBegin(&pub->p, mgr, FALSE );
c5df53 ¤   ¤   ¤   bnBegin(&pub->q, mgr, FALSE );
50b790 ¤   ¤   ¤   bnBegin(&pub->g, mgr, FALSE );
5e5f2b ¤   ¤   ¤   bnBegin(&pub->y, mgr, FALSE );
30cd8c ¤   ¤   ¤   if (bnInsertBigBytes(&pub->p, buf+i+2, 0, t-i-2) >= 0
4c378f ¤   ¤   ¤   ·&& bnInsertBigBytes(&pub->q, buf+t+2, 0, u-t-2) >= 0
3aaa64 ¤   ¤   ¤   ·&& bnInsertBigBytes(&pub->g, buf+u+2, 0, v-u-2) >= 0
c454ff ¤   ¤   ¤   ·&& bnInsertBigBytes(&pub->y, buf+v+2, 0, w-v-2) >= 0)
ebf776 ¤   ¤   ¤   {
d8a426 ¤   ¤   ¤   ¤   if (dsaKeyTooBig (pub, NULL)) {
804f2b ¤   ¤   ¤   ¤   ¤   err = kPGPError_KeyTooLarge;
e4b5fc ¤   ¤   ¤   ¤   } else {
3bbc5b ¤   ¤   ¤   ¤   ¤   dsaFillPubkey(pubkey, pub);
0b346a ¤   ¤   ¤   ¤   ¤   *error = 0;
--5954 000239b3e394010020a Page 7 of pgpDSAKey.c
3937f5 ¤   ¤   ¤   ¤   ¤   return pubkey;
f02613 ¤   ¤   ¤   ¤   }
94a3a6 ¤   ¤   ¤   }
739865 ¤   ¤   ¤   /* Failed = clean up and return NULL */
9ef980 ¤   ¤   ¤   bnEnd(&pub->p);
f5e53b ¤   ¤   ¤   bnEnd(&pub->q);
566d00 ¤   ¤   ¤   bnEnd(&pub->g);
0200e3 ¤   ¤   ¤   bnEnd(&pub->y);
cb7f83 ¤   ¤   ¤   pgpContextMemFree( context, pubkey);
0c0fe4 ¤   ¤   }
26c695 ¤   ¤   pgpContextMemFree( context, pub);
3f9371 ¤   }
f4ab59 ¤   *error = err;
313f59 ¤   return NULL;
c0efe6 }
9baf5a
a338e5 /*
b9439a ·* Return the size of the public portion of a key buffer.
bd495d ·*/
634d2f int
337aa5 dsaPubKeyPrefixSize(PGPByte const *buf, size_t size)
a5bb36 {
9bbf70 ¤   return pgpBnParse(buf, size, 4, NULL, NULL, NULL, NULL);
b0efe6 }
48af5a
6eaf5a
d6114d /** Secret key functions **/
cdaf5a
8f2978 static void
9bb334 dsaSecDestroy(PGPSecKey *seckey)
1abb36 {
11a807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
2c7925 ¤   PGPContextRef¤  ¤   context;
afaf5a
834813 ¤   pgpAssertAddrValid( seckey, PGPSecKey );
655b86 ¤   context¤= seckey->context;
5aaf5a
c93d7c ¤   ASSERTDSA(seckey->pkAlg);
733273 ¤   bnEnd(&sec->s.p);
a72ec8 ¤   bnEnd(&sec->s.q);
6ba6f3 ¤   bnEnd(&sec->s.g);
1acb10 ¤   bnEnd(&sec->s.y);
65d7ab ¤   bnEnd(&sec->s.x);
b756f8 ¤   pgpClearMemory(sec->cryptkey, sec->ckalloc);
045bb1 ¤   pgpContextMemFree( context, sec->cryptkey);
560d92 ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
fe1464 ¤   pgpClearMemory( seckey, ·sizeof(seckey));
f3390c ¤   pgpContextMemFree( context, seckey);
45efe6 }
78af5a
8438e5 /*
a33521 ·* Generate a PGPPubKey from a PGPSecKey
b4495d ·*/
8bc2ad static PGPPubKey *
6e5769 dsaPubkey(PGPSecKey const *seckey)
a1bb36 {
24fcf7 ¤   DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;
9e36c1 ¤   PGPPubKey *pubkey;
06553b ¤   DSApub *pub;
777925 ¤   PGPContextRef¤  ¤   context;
e92955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
63af5a
ab4813 ¤   pgpAssertAddrValid( seckey, PGPSecKey );
5f5b86 ¤   context¤= seckey->context;
78faf1 ¤   mgr¤= PGPGetContextMemoryMgr( context );
c6af5a
193d7c ¤   ASSERTDSA(seckey->pkAlg);
b30cec ¤   pub = (DSApub *)pgpContextMemAlloc( context,
ce30c7 ¤   ¤   sizeof(*pub), kPGPMemoryMgrFlags_Clear);
e767ab ¤   if (pub) {
3e545a ¤   ¤   pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
237dcd ¤   ¤   ¤   sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
--6d4b 000e114c36a4010020a Page 8 of pgpDSAKey.c
e3d646 ¤   ¤   if (pubkey) {
1eaa14 ¤   ¤   ¤   pubkey->context¤= context;
2987c7 ¤   ¤   ¤
78cf5c ¤   ¤   ¤   bnBegin(&pub->p, mgr, FALSE );
8edf53 ¤   ¤   ¤   bnBegin(&pub->q, mgr, FALSE );
81b790 ¤   ¤   ¤   bnBegin(&pub->g, mgr, FALSE );
535f2b ¤   ¤   ¤   bnBegin(&pub->y, mgr, FALSE );
22ced5 ¤   ¤   ¤   if (bnCopy(&pub->p, &sec->s.p) >= 0
63c2c4 ¤   ¤   ¤   ····&& bnCopy(&pub->q, &sec->s.q) >= 0
298b81 ¤   ¤   ¤   ····&& bnCopy(&pub->g, &sec->s.g) >= 0
b393f7 ¤   ¤   ¤   ····&& bnCopy(&pub->y, &sec->s.y) >= 0)
44f776 ¤   ¤   ¤   {
eaa40b ¤   ¤   ¤   ¤   dsaFillPubkey(pubkey, pub);
007c58 ¤   ¤   ¤   ¤   pubkey->pkAlg = seckey->pkAlg;
a7d49b ¤   ¤   ¤   ¤   memcpy(pubkey->keyID, seckey->keyID,
7a4c85 ¤   ¤   ¤   ¤   ·······sizeof(pubkey->keyID));
bcbb8a ¤   ¤   ¤   ¤   return pubkey;
04a3a6 ¤   ¤   ¤   }
879865 ¤   ¤   ¤   /* Failed = clean up and return NULL */
2ff980 ¤   ¤   ¤   bnEnd(&pub->p);
4ee53b ¤   ¤   ¤   bnEnd(&pub->q);
1e6d00 ¤   ¤   ¤   bnEnd(&pub->g);
5b00e3 ¤   ¤   ¤   bnEnd(&pub->y);
5c7f83 ¤   ¤   ¤   pgpContextMemFree( context, pubkey);
1e0fe4 ¤   ¤   }
51c695 ¤   ¤   pgpContextMemFree( context, pub);
6f9371 ¤   }
e23f59 ¤   return NULL;
96efe6 }
0daf5a
8c38e5 /*
0a887a ·* Yes, there *is* a reason that this is a function and not a variable.
e7a3bd ·* On a hardware device with an automatic timeout,
7f6854 ·* it actually might need to do some work to find out.
c7495d ·*/
3abeb7 static int
c8f507 dsaIslocked(PGPSecKey const *seckey)
e2bb36 {
9afcf7 ¤   DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;
77af5a
163d7c ¤   ASSERTDSA(seckey->pkAlg);
d4096c ¤   return sec->locked;
47efe6 }
c1af5a
e038e5 /*
9ac3dc ·* Return the algorithm and (symmetric) key size used for locking/unlocking
a5f175 ·* the secret key.
38495d ·*/
16f1ae static PGPError
46ac44 dsaLockingAlgorithm(
56b573 ¤   PGPSecKey const *seckey,
3a6f43 ¤   PGPCipherAlgorithm *pAlg,
50b91d ¤   PGPSize *pAlgKeySize
ec27e6 ¤   )
cbbb36 {
2ba807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
e408c6 ¤   PGPCipherVTBL const *cipher;
48afba ¤   PGPByte alg;
ee4ba4 ¤   int i;
83af5a
823d7c ¤   ASSERTDSA(seckey->pkAlg);
2daf5a
8b0ec4 ¤   if( IsntNull( pAlg ) )
6f7a59 ¤   ¤   *pAlg = (PGPCipherAlgorithm) 0;
c17929 ¤   if( IsntNull( pAlgKeySize ) )
68301e ¤   ¤   *pAlgKeySize = (PGPSize) 0;
c7af5a
3284c6 ¤   /* Check packet for basic consistency */
f31045 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 4, NULL, NULL, NULL, NULL);
d04fd6 ¤   if (i < 0)
1a2051 ¤   ¤   return (PGPError)i;
e1af5a
--41ec 0003d3829a14010020a Page 9 of pgpDSAKey.c
d6b604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
5ce893 ¤   alg = sec->cryptkey[i] & 255;
5baf5a
2d9fab ¤   /* New style has 255 then algorithm value */
a6130c ¤   if (alg == 255)
00acc2 ¤   ¤   alg = sec->cryptkey[i+1] & 255;
8faf5a
f9c7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
f9b637 ¤   if (!cipher)
e7fb6d ¤   ¤   return kPGPError_BadCipherNumber;
5caf5a
da0d42 ¤   /* Success */
f80ec4 ¤   if( IsntNull( pAlg ) )
812341 ¤   ¤   *pAlg = (PGPCipherAlgorithm) alg;
5b7929 ¤   if( IsntNull( pAlgKeySize ) )
edf60c ¤   ¤   *pAlgKeySize = cipher->keysize;
8faf5a
b6151e ¤   return kPGPError_NoErr;
7aefe6 }
15af5a
ebaf5a
1438e5 /*
3fd2ee ·* Return the StringToKey type for unlocking the given key. ·We use
0e4eb5 ·* kPGPStringToKey_Literal to flag a secret split unlocking buffer.
4b9d12 ·* Returns kPGPStringToKey_Simple if key has no passphrase.
81495d ·*/
55f1ae static PGPError
dfa0e3 dsaS2KType(
e9b573 ¤   PGPSecKey const *seckey,
159e5a ¤   PGPStringToKeyType *s2kType
3e27e6 ¤   )
aebb36 {
6ea807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
f3afba ¤   PGPByte alg;
604ba4 ¤   int i;
67af5a
903d7c ¤   ASSERTDSA(seckey->pkAlg);
e9af5a
9355b6 ¤   /* note that 0 is a valid type, but use it as default anyway */
89dab9 ¤   if( IsntNull( s2kType ) )
e0bc38 ¤   ¤   *s2kType = (PGPStringToKeyType) 0;
4eaf5a
8d84c6 ¤   /* Check packet for basic consistency */
9a1045 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 4, NULL, NULL, NULL, NULL);
eb4fd6 ¤   if (i < 0)
212051 ¤   ¤   return (PGPError)i;
23af5a
94b604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
a3e893 ¤   alg = sec->cryptkey[i] & 255;
eaaf5a
c440cd ¤   if (alg == 255) {
523446 ¤   ¤   /* New style has 255 then algorithm value then S2K */
49d66f ¤   ¤   *s2kType = (PGPStringToKeyType) sec->cryptkey[i+2];
36f037 ¤   } else {
db4191 ¤   ¤   /* Unencrypted or old-style simple encryption */
28c21f ¤   ¤   *s2kType = kPGPStringToKey_Simple;
6f9371 ¤   }
f7af5a
5d151e ¤   return kPGPError_NoErr;
93efe6 }
1faf5a
c138e5 /*
0771a1 ·* Convert a passphrase into a s2k literal buffer for the key.
a55514 ·* Returns error code. ·Output buffer will be size of the *pAlgKeySize
fd2df7 ·* parameter from pgpSecKeyLockingalgorithm.
55495d ·*/
dff1ae static PGPError
68a423 dsaConvertPassphrase(PGPSecKey *seckey, PGPEnv const *env,
329820 ¤   ··char const *phrase, PGPSize plen, PGPByte *outbuf)
95bb36 {
fca807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
3dbfb0 ¤   PGPStringToKey *s2k;
--5ea8 000c5c0320e4010020a Page 10 of pgpDSAKey.c
f4afba ¤   PGPByte alg;
080306 ¤   PGPBoolean hasS2K;
6608c6 ¤   PGPCipherVTBL const *cipher;
d44ba4 ¤   int i;
14af5a
ae3d7c ¤   ASSERTDSA(seckey->pkAlg);
a76bb2 ¤   pgpAssert (IsntNull( outbuf ) );
81af5a
6c84c6 ¤   /* Check packet for basic consistency */
931045 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 4, NULL, NULL, NULL, NULL);
704fd6 ¤   if (i < 0)
112051 ¤   ¤   return (PGPError)i;
70af5a
e4b604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
988aa2 ¤   alg = sec->cryptkey[i++] & 255;
7baf5a
ffeaa8 ¤   hasS2K = (alg == 255);
1eaf5a
ad9fab ¤   /* New style has 255 then algorithm value */
d2727d ¤   if (hasS2K)
384ff7 ¤   ¤   alg = sec->cryptkey[i++] & 255;
ebaf5a
1bcb98 ¤   /* Now we are looking at the s2k object if there is one. */
200d7e ¤   if (alg == 0) {
61cc33 ¤   ¤   /* Key is not locked */
1f62b5 ¤   ¤   return kPGPError_BadParams;
f79371 ¤   }
d6c7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
45b04e ¤   if( IsNull( cipher ) )
24fb6d ¤   ¤   return kPGPError_BadCipherNumber;
88af5a
61db5e ¤   if (hasS2K) {
f80162 ¤   ¤   pgpS2Kdecode(&s2k, env, sec->cryptkey+i, sec->cklen-i);
9df037 ¤   } else {
39176e ¤   ¤   s2k = pgpS2Ksimple(env, pgpHashByNumber(kPGPHashAlgorithm_MD5));
249371 ¤   }
266f18 ¤   if (IsNull( s2k ) )
194030 ¤   ¤   return kPGPError_OutOfMemory;
7da401 ¤   pgpStringToKey(s2k, phrase, plen, outbuf, cipher->keysize);
fefdac ¤   pgpS2Kdestroy (s2k);
da67c5 ¤
c9151e ¤   return kPGPError_NoErr;
9fefe6 }
99af5a
c4af5a
bb38e5 /*
2c2d14 ·* Try to decrypt the secret key wih the given passphrase. ·Returns >0
a193d2 ·* if it was the correct passphrase. =0 if it was not, and <0 on error.
effa8a ·* Does not alter the key even if it's the wrong passphrase and already
db9458 ·* unlocked. ·A NULL passphrae will work if the key is unencrypted.
ae9ec0 ·*·
5dbd2f ·* A (secret) key's DSA-specific part is:
a3775e ·*
42adc3 ·* ·0 ···············2+u ·MPI for prime p
54b630 ·* ·2+u ·············2+v ·MPI for order q
b49b31 ·* ·4+u+v ···········2+w ·MPI for generator g
a7eb38 ·* ·6+u+v+w¤ ····2+x ·MPI for public key y
7b18b5 ·* ·8+u+v+w+x ·······1 ···Encryption algorithm (0 for none, 1 for IDEA)
f7061f ·* ·9+u+v+w+x ·······t ···Encryption IV: 0 or 8 bytes
00454b ·* ·9+t+u+v+w+x ·····2+y ·MPI for x (discrete log of public key)
dae926 ·* 11+t+u+v+w+x+y ···2 ···Checksum
6e1c1f ·* 13+t+u+v+w+x+y
a0775e ·*
c9ee8f ·* Actually, that's the old-style, if pgpS2KoldVers is true.
dd2462 ·* If it's false, the algoruthm is 255, and is followed by the
6b8f61 ·* algorithm, then the (varaible-length, self-delimiting)
db217f ·* string-to-key descriptor.
95495d ·*/
3faf5a
10beb7 static int
f9f6c3 dsaUnlock(PGPSecKey *seckey, PGPEnv const *env,
c57e27 ¤   ··char const *phrase, size_t plen, PGPBoolean hashedPhrase)
--b6d8 000cb2de6114010020a Page 11 of pgpDSAKey.c
2cbb36 {
f5a807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
33b06a ¤   BigNum x;
6a1f93 ¤   PGPCFBContext *cfb = NULL;
85bb6d ¤   unsigned v;
6bdfbc ¤   unsigned alg;
201b07 ¤   unsigned checksum;
984ba4 ¤   int i;
562955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
4a67c5 ¤
d91e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
5faf5a
c42f13 ¤   bnBegin(&x, mgr, TRUE);
8baf5a
363d7c ¤   ASSERTDSA(seckey->pkAlg);
8faf5a
9884c6 ¤   /* Check packet for basic consistency */
ddd75f ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 4, &v, NULL, NULL, NULL);
9707eb ¤   if (i <= 0)
bd84fc ¤   ¤   goto fail;
39af5a
d820ee ¤   /* OK, read the public data */
f52c91 ¤   i = pgpBnGetPlain(&sec->s.p, sec->cryptkey+v, sec->cklen-v);
ce07eb ¤   if (i <= 0)
c684fc ¤   ¤   goto fail;
4224fb ¤   v += i;
d021a8 ¤   i = pgpBnGetPlain(&sec->s.q, sec->cryptkey+v, sec->cklen-v);
ce07eb ¤   if (i <= 0)
e284fc ¤   ¤   goto fail;
de24fb ¤   v += i;
89dcae ¤   i = pgpBnGetPlain(&sec->s.g, sec->cryptkey+v, sec->cklen-v);
e307eb ¤   if (i <= 0)
e684fc ¤   ¤   goto fail;
cf24fb ¤   v += i;
284860 ¤   i = pgpBnGetPlain(&sec->s.y, sec->cryptkey+v, sec->cklen-v);
ad07eb ¤   if (i <= 0)
1684fc ¤   ¤   goto fail;
a524fb ¤   v += i;
b5af5a
1bb604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
13547e ¤   alg ·= sec->cryptkey[v];
adaf5a
133563 ¤   /* If the phrase is empty, set it to NULL */
6ec08b ¤   if (plen == 0)
2a6f28 ¤   ¤   phrase = NULL;
21d8af ¤   /*
3eb08f ¤   ·* We need a pass if it is encrypted, and we cannot have a
1c7664 ¤   ·* password if it is NOT encrypted. ·I.e., this is a logical
ef887b ¤   ·* xor (^^)
f1a4e3 ¤   ·*/
71bb71 ¤   if (!phrase != !sec->cryptkey[v])
90a8d5 ¤   ¤   goto badpass;
d0af5a
da1ca2 ¤   i = pgpCipherSetup(sec->cryptkey + v, sec->cklen - v, phrase, plen,
621001 ¤   ¤   ¤   ¤   ¤   ···hashedPhrase, env, &cfb);
904fd6 ¤   if (i < 0)
fb262d ¤   ¤   goto done;
bb24fb ¤   v += i;
a3af5a
fea2f0 ¤   checksum = 0;
5c814c ¤   i = pgpBnGetNew(&x, sec->cryptkey + v, sec->cklen - v, cfb, &checksum);
8b07eb ¤   if (i <= 0)
fda8d5 ¤   ¤   goto badpass;
8824fb ¤   v += i;
6a40e2 ¤   if (bnCmp(&x, &sec->s.q) >= 0)
b3a249 ¤   ¤   goto badpass;¤  /* Wrong passphrase: x must be < q */
5baf5a
224e68 ¤   /* Check that we ended in the right place */
ea8c8c ¤   if (sec->cklen - v != 2) {
cae85e ¤   ¤   i = kPGPError_KEY_LONG;
eb84fc ¤   ¤   goto fail;
cb9371 ¤   }
--a0f8 0007049bd944010020a Page 12 of pgpDSAKey.c
20afa6 ¤   checksum &= 0xffff;
1d977c ¤   if (checksum != pgpChecksumGetNew(sec->cryptkey+v, cfb))
e6a8d5 ¤   ¤   goto badpass;
f5af5a
4ed8af ¤   /*
c77b44 ¤   ·* Note that the "nomem" case calls bnEnd()
3d5307 ¤   ·* more than once, but this is guaranteed harmless.
2c9c20 ·¤  ·*/
be2599 ¤   if (bnCopy(&sec->s.x, &x) < 0)
9e5b40 ¤   ¤   goto nomem;
beaf5a
cf2f6d ¤   i = 1;¤ /* Decrypted! */
9d0162 ¤   sec->locked = 0;
e5c48e ¤   goto done;
eeaf5a
ffac52 nomem:
7c30c4 ¤   i = kPGPError_OutOfMemory;
e3c48e ¤   goto done;
a5115d fail:
6a5451 ¤   if (!i)
48a3b2 ¤   ¤   i = kPGPError_KeyPacketTruncated;
1dc48e ¤   goto done;
c588a7 badpass:
06f1b7 ¤   i = 0;¤ /* Incorrect passphrase */
dcc48e ¤   goto done;
f8b38c done:
f7077f ¤   bnEnd(&x);
56afda ¤   if (cfb)
5cd6b0 ¤   ¤   PGPFreeCFBContext(cfb);
022196 ¤   return i;
d9efe6 }
8caf5a
6538e5 /*
8b3dfc ·* Relock the key.
3f495d ·*/
452978 static void
91b36b dsaLock(PGPSecKey *seckey)
47bb36 {
6fa807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
52af5a
3b3d7c ¤   ASSERTDSA(seckey->pkAlg);
195bbe ¤   sec->locked = 1;
4d9e4a ¤   /* bnEnd is documented as also doing a bnBegin */
a5d7ab ¤   bnEnd(&sec->s.x);
f6efe6 }
e6af5a
fe38e5 /*
247d83 ·* Try to decrypt the given esk. ·If the key is locked, try the given
350169 ·* passphrase. ·It may or may not leave the key unlocked in such a case.
f88bf9 ·* (Some hardware implementations may insist on a password per usage.)
32495d ·*/
a8beb7 static int
de1a97 dsaDecrypt(PGPSecKey *seckey, PGPEnv const *env,
e7509e ¤   ···PGPByte const *esk, size_t esklen,
fa4cd4 ¤   ···PGPByte *key, size_t *keylen, char const *phrase, size_t plen,
e3ff4d ¤   ···PGPPublicKeyMessageFormat format)
febb36 {
49c9d3 ¤   (void)seckey;
ca7054 ¤   (void)env;
2d4290 ¤   (void)esk;
537a0a ¤   (void)esklen;
419b3e ¤   (void)key;
30ede5 ¤   (void)keylen;
e7cf72 ¤   (void)phrase;
d2087c ¤   (void)plen;
a21c0d ¤   (void)format;
430b93 ¤   return kPGPError_PublicKeyUnimplemented;
c0efe6 }
34af5a
ec38e5 /*
d3f5ac ·* Return the size of the buffer needed, worst-case, for the decrypted
704909 ·* output.
--2aaf 000e5ac2b764010020a Page 13 of pgpDSAKey.c
47495d ·*/
ff5d09 static size_t
f24d13 dsaSecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
b1bb36 {
46c9d3 ¤   (void)seckey;
681c0d ¤   (void)format;
1f0b93 ¤   return kPGPError_PublicKeyUnimplemented;
71efe6 }
65af5a
b25d09 static size_t
3bb8a8 dsaSecMaxesk(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
4abb36 {
58c9d3 ¤   (void)seckey;
951c0d ¤   (void)format;
530b93 ¤   return kPGPError_PublicKeyUnimplemented;
20efe6 }
5daf5a
825d09 static size_t
197480 dsaSecMaxsig(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
9dbb36 {
ebfcf7 ¤   DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;
b8af5a
d03d7c ¤   ASSERTDSA(seckey->pkAlg);
6f9850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
ca2bae ¤   ¤   return 2*( 2 + bnBytes(&sec->s.q) );
5461bb ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1)
85f46b ¤   ¤   return 2*( bnBytes(&sec->s.q) );
e369ae ¤   else if (format == kPGPPublicKeyMessageFormat_X509) {
905cbb ¤   ¤   /* BITSTRING, length, 0, SEQUENCE, length, INT, INT */
2570fe ¤   ¤   PGPUInt32 len, lenlen;
1fd822 ¤   ¤   PGPUInt32 qbytes = bnBytes(&sec->s.q);
74fca1 ¤   ¤   len = 2*(pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1);
8df385 ¤   ¤   lenlen = pgpBnX509LenLen(len);
c1a5e1 ¤   ¤   return 1 + pgpBnX509LenLen(1+lenlen+len) + 1 + 1 + lenlen + len;
e99371 ¤   }
3aaf5a
bf4aac ¤   pgpAssert(0);
633e6b ¤   return 0;
c1efe6 }
9eaf5a
7338e5 /*
76a719 ·* Helper function: seed a RandomContext from a BigNum.
d16bf5 ·* Be very sure to leave nothing in memory!
e4495d ·*/
272978 static void
3fff3b pgpRandomBnSeed(PGPRandomContext const *rc, BigNum const *bn)
f9bb36 {
8fa87f ¤   PGPByte buf[32];¤   /* Big enough for 99.9% of all keys */
88bb14 ¤   unsigned bytes = (bnBits(bn) + 7)/8;
ff2e86 ¤   unsigned off = 0;
aaaf5a
81c557 ¤   while (bytes > sizeof(buf)) {
566581 ¤   ¤   bnExtractLittleBytes(bn, buf, off, sizeof(buf));
96e1ba ¤   ¤   pgpRandomAddBytes(rc, buf, sizeof(buf));
36da6d ¤   ¤   bytes -= sizeof(buf);
ab0383 ¤   ¤   off += sizeof(buf);
7a9371 ¤   }
581ae0 ¤   bnExtractLittleBytes(bn, buf, off, bytes);
3d2abb ¤   pgpRandomAddBytes(rc, buf, bytes);
51af5a
a0718a ¤   pgpClearMemory( buf, ·sizeof(buf));
73efe6 }
48af5a
9faf5a
21af5a
02beb7 static int
7dd10e dsaSign(PGPSecKey *seckey, PGPHashVTBL const *h, PGPByte const *hash,
dc6564 ¤   PGPByte *sig, size_t *siglen, PGPRandomContext const *rc,
dd6fc3 ¤   PGPPublicKeyMessageFormat format)
e8bb36 {
79ccf3 #if PGP_SIGN_DISABLE /* [ */
e5af5a
--6d37 00053da48244010020a Page 14 of pgpDSAKey.c
3ac9d3 ¤   (void)seckey;
28c6fd ¤   (void)h;
0f4902 ¤   (void)hash;
a377e4 ¤   (void)sig;
8b51a9 ¤   (void)siglen;
a476a2 ¤   (void)rc;
321c0d ¤   (void)format;
a8e63f ¤   return kPGPError_FeatureNotAvailable;
2aaf5a
2c7e3d #else /* PGP_SIGN_DISABLE */ ·/* ] ·[ */
eaaf5a
75a807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
b57ad4 ¤   BigNum r, s, bn, k;
4f0ed5 ¤   unsigned t;
b715bf ¤   unsigned qbits;
754776 ¤   unsigned qbytes;
e34ba4 ¤   int i;
cbecc6 ¤   PGPRandomContext *rc2;
1d2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
1867c5 ¤
751e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
88af5a
24c6fd ¤   (void)h;
690fe9 ¤   /* We don't need this argument, although other algorithms may... */
8f1c0d ¤   (void)format;
3daf5a
683d7c ¤   ASSERTDSA(seckey->pkAlg);
fc7a5b ¤   /* Allow generalizations of SHA as long as they are big enough */
b1b177 #if 0
f9bc25 ¤   pgpAssert(h->algorithm == kPGPHashAlgorithm_SHA);
f1db21 #else
fb7462 ¤   pgpAssert(h->hashsize*8 >= bnBits(&sec->s.q));
e00ba1 ¤   /* Make sure that q is the right size of we are using regular SHA hash */
b4c614 ¤   pgpAssert( ! (h->algorithm == kPGPHashAlgorithm_SHA
a1ece3 ¤   ¤   ¤   ¤   && bnBits(&sec->s.q) != h->hashsize*8) );
357454 #endif
20af5a
54d2c6 ¤   if (sec->locked)
35035c ¤   ¤   return kPGPError_KeyIsLocked;
57af5a
1dd8af ¤   /*
ace666 ¤   ·* DSA requires a secret k. ·This k is *very* important
ddf349 ¤   ·* to keep secret. ·Consider, the DSA signing equations are:
ca29c5 ¤   ·* r = (g^k mod p) mod q, and
382bad ¤   ·* s = k^-1 * (H(m) + x*r) mod q,
4e12a1 ¤   ·* so if you know k (and, the signature r, s and H), then
26770c ¤   ·* x = r^-1 * (k*s - H(m))
21b3a9 ¤   ·* If we ever pick two k values the same, then
28beaa ¤   ·* r = (g^k mod p) mod q is the same for both signatures, and
dd3bec ¤   ·* s1 = k^-1 * (H1 + x * r)·
27b08f ¤   ·* s2 = k^-1 * (H2 + x * r)·
926615 ¤   ·* k = (H1-H2) / (s1-s2)
d537a7 ¤   ·* and proceed from there.
c99714 ¤   ·*
97929e ¤   ·* So we need to make *very* sure there's no problem. ·To make
0db1dc ¤   ·* sure, we add a layer on top of the passed-in RNG. ·We assume
526ee7 ¤   ·* the passed-in RNG is good enough to never repeat (not a
cd23d3 ¤   ·* difficult task), and apply an additional X9.17 generator on
fe62ae ¤   ·* top of that, seeded with the secret x, which is destroyed
369150 ¤   ·* before leaving this function.
249714 ¤   ·*
d67947 ¤   ·* In addition, we add entropy from the hash to the original RNG.
444d18 ¤   ·* This will prevent us from using the same k value twice if the
3d0afb ¤   ·* messages are different.
a4a4e3 ¤   ·*/
c8d2b0 ¤   pgpRandomAddBytes(rc, hash, bnBytes(&sec->s.q));
c6db01 ¤   rc2 = pgpRandomCreateX9_17( rc->context, kPGPCipherAlgorithm_CAST5, rc);
a6fc26 ¤   if (!rc2)
ed4030 ¤   ¤   return kPGPError_OutOfMemory;
a5b2d0 ¤   pgpRandomBnSeed(rc2, &sec->s.x);
59af5a
53d8af ¤   /*
--da7f 000f72242504010020a Page 15 of pgpDSAKey.c
bdb4ca ¤   ·* Of these values, only k is inherently sensitive, but others may
f159cb ¤   ·* hold some intermediate results we would prefer not to have leaked.
7d22b7 ¤   ·* So mark all as sensitive.
78a4e3 ¤   ·*/
c3afae ¤   bnBegin(&r, mgr, TRUE );
4f21be ¤   bnBegin(&s, mgr, TRUE );
8b06c7 ¤   bnBegin(&bn, mgr, TRUE );
1ad0f2 ¤   bnBegin(&k, mgr, TRUE );
83af5a
72d8af ¤   /*
776519 ¤   ·* Choose the random k value to be used for this signature.
865660 ¤   ·* Make it a bit bigger than q so it is fairly uniform mod q.
5ca4e3 ¤   ·*/
689599 ¤   qbits = bnBits(&sec->s.q);
6e90bd ¤   qbytes = bnBytes(&sec->s.q);
152d94 ¤   if (pgpBnGenRand(&k, rc2, qbits+8, 0, 1, qbits) < 0 ||
20383c ¤   ····bnMod(&k, &k, &sec->s.q) < 0)
d65b40 ¤   ¤   goto nomem;
7367c5 ¤
29b850 ¤   /* Raise g to k power mod p then mod q to get r */
839165 ¤   if (bnExpMod(&r, &sec->s.g, &k, &sec->s.p) < 0 ||
4156ad ¤   ····bnMod(&r, &r, &sec->s.q) < 0)
515b40 ¤   ¤   goto nomem;
f30cca ¤   ······
310db7 ¤   /* r*x mod q into s */
66b395 ¤   if (bnMul(&s, &r, &sec->s.x) < 0 ||
754c2d ¤   ····bnMod(&s, &s, &sec->s.q) < 0)
ae5b40 ¤   ¤   goto nomem;
15af5a
8ea0cf ¤   /* Pack message hash M into buffer bn */
13ef6c ¤   if (bnInsertBigBytes(&bn, hash, 0, bnBytes(&sec->s.q)) < 0)
6d5b40 ¤   ¤   goto nomem;
532f01 ¤   if (bnMod(&bn, &bn, &sec->s.q) < 0)
9a5b40 ¤   ¤   goto nomem;
a9af5a
b6a8a8 ¤   /* Add into s */
24dccd ¤   if (bnAdd(&s, &bn) < 0 ||
c24c2d ¤   ····bnMod(&s, &s, &sec->s.q) < 0)
ba5b40 ¤   ¤   goto nomem;
18af5a
9d57f6 ¤   /* Divide by k, mod q (k inverse held in bn) */
03b6ac ¤   if (bnInv(&bn, &k, &sec->s.q) < 0 ||
08fa1b ¤   ····bnMul(&s, &s, &bn) < 0 ||
994c2d ¤   ····bnMod(&s, &s, &sec->s.q) < 0)
d65b40 ¤   ¤   goto nomem;
2eaf5a
2bd6f8 ¤   /* That's it, now to pack r and then s into the buffer */
9a64ea ¤   t = 0;
e27e57 ¤   if (format == kPGPPublicKeyMessageFormat_X509) {
b79b43 ¤   ¤   /* Put in BITSTRING/SEQUENCE header for 509 sig data */
0e438d ¤   ¤   PGPUInt32 len_seq, len_bitstr, lenlen_seq, lenlen_bitstr;
6ba2fb ¤   ¤   /* Count size of sequence, counting a 0 byte if hi bit is set */
b15826 ¤   ¤   if (8*qbytes == bnBits(&r))
a205a7 ¤   ¤   ¤   len_seq = pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1;
d30e1d ¤   ¤   else
71d527 ¤   ¤   ¤   len_seq = pgpBnX509LenLen(qbytes) + 1 + qbytes;
bd449d ¤   ¤   if (8*qbytes == bnBits(&s))
03b89e ¤   ¤   ¤   len_seq += pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1;
120e1d ¤   ¤   else
c14120 ¤   ¤   ¤   len_seq += pgpBnX509LenLen(qbytes) + 1 + qbytes;
2abc78 ¤   ¤   lenlen_seq = pgpBnX509LenLen(len_seq);
719d75 ¤   ¤   len_bitstr = 1 + 1 + lenlen_seq + len_seq;
e404ed ¤   ¤   lenlen_bitstr = pgpBnX509LenLen(len_bitstr);
3adb75 ¤   ¤   sig[t++] = X509_TAG_BITSTRING;
d4b347 ¤   ¤   if (--lenlen_bitstr == 0) {
a10df5 ¤   ¤   ¤   sig[t++] = len_bitstr;
ae45a6 ¤   ¤   } else {
eff017 ¤   ¤   ¤   sig[t++] = 0x80 | lenlen_bitstr;
46571b ¤   ¤   ¤   len_bitstr <<= 8 * (4-lenlen_bitstr);
01b3ef ¤   ¤   ¤   while (lenlen_bitstr--) {
3369af ¤   ¤   ¤   ¤   sig[t++] = (PGPByte)(len_bitstr >> 24);
f7555c ¤   ¤   ¤   ¤   len_bitstr <<= 8;
--3dd2 0004f907beb4010020a Page 16 of pgpDSAKey.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
414e22 ¤   ¤   sig[t++] = 0;¤  ¤   /* No excess bits in bitstring */
b559ec ¤   ¤   sig[t++] = X509_TAG_SEQUENCE | X509_TAG_CONSTRUCTED;
e122cc ¤   ¤   if (--lenlen_seq == 0) {
1e80d6 ¤   ¤   ¤   sig[t++] = len_seq;
6245a6 ¤   ¤   } else {
9d97aa ¤   ¤   ¤   sig[t++] = 0x80 | lenlen_seq;
657a6a ¤   ¤   ¤   len_seq <<= 8 * (4-lenlen_seq);
0c4145 ¤   ¤   ¤   while (lenlen_seq--) {
a0fa15 ¤   ¤   ¤   ¤   sig[t++] = (PGPByte)(len_seq >> 24);
f518ea ¤   ¤   ¤   ¤   len_seq <<= 8;
6fa3a6 ¤   ¤   ¤   }
a60fe4 ¤   ¤   }
439371 ¤   }
29cec8 ¤   t += pgpBnPutFormatted(&r, sig+t, qbytes, format);
5d9c80 ¤   t += pgpBnPutFormatted(&s, sig+t, qbytes, format);
030405 ¤   if (siglen)
04c8b2 ¤   ¤   *siglen = (size_t)t;
bbaf5a
52ff6c ¤   i = 0;
0ac48e ¤   goto done;
d9af5a
eaac52 nomem:
2930c4 ¤   i = kPGPError_OutOfMemory;
95dab0 ¤   /* fall through */
61b38c done:
f41505 ¤   pgpRandomDestroy(rc2);
58e113 ¤   bnEnd(&k);
750204 ¤   bnEnd(&bn);
7cc76a ¤   bnEnd(&s);
33dbd1 ¤   bnEnd(&r);
f12196 ¤   return i;
cfaf5a
23adb6 #endif /* PGP_SIGN_DISABLE */ /* ] */
5fefe6 }
6daf5a
76af5a
6138e5 /*
cdb989 ·* Re-encrypt a PGPSecKey with a new urn a PGPSecKey into a secret key.
8e13db ·* A secret key is, after a non-specific prefix:
f43dd0 ·* ·0 ······1 ···Version (= 2 or 3)
14e351 ·* ·1 ······4 ···Timestamp
aa0e90 ·* ·5 ······2 ···Validity (=0 at present)
4b8c33 ·* ·7 ······1 ···Algorithm (=kPGPPublicKeyAlgorithm_DSA for DSA)
e89455 ·* The following:
55adc3 ·* ·0 ···············2+u ·MPI for prime p
03b630 ·* ·2+u ·············2+v ·MPI for order q
1e9b31 ·* ·4+u+v ···········2+w ·MPI for generator g
66eb38 ·* ·6+u+v+w¤ ····2+x ·MPI for public key y
6618b5 ·* ·8+u+v+w+x ·······1 ···Encryption algorithm (0 for none, 1 for IDEA)
be061f ·* ·9+u+v+w+x ·······t ···Encryption IV: 0 or 8 bytes
77454b ·* ·9+t+u+v+w+x ·····2+y ·MPI for x (discrete log of public key)
02e926 ·* 11+t+u+v+w+x+y ···2 ···Checksum
f41c1f ·* 13+t+u+v+w+x+y
8d775e ·*
85d1aa ·* The Encryption algorithm is the cipher algorithm for the old-style
c84ff3 ·* string-to-key conversion. ·For the new type, it's 255, then a cipher
872fc9 ·* algorithm, then a string-to-key algorithm (variable-length),
ffd7a3 ·* then the encryption IV. ·That's 16 bytes plus the string-to-key
6df861 ·* conversion length.
b3495d ·*/
c40ccc #if PGP_MACINTOSH
5d9221 #pragma global_optimizer on
3b7454 #endif
9eaf5a
06beb7 static int
e6c31c dsaChangeLock(PGPSecKey *seckey, PGPEnv const *env,·
d45ff1 ¤   PGPRandomContext const *rc, char const *phrase, size_t plen,
aaab73 ¤   PGPStringToKeyType s2ktype)
24bb36 {
4fa807 ¤   DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
--31d9 000a227c8cb4010020a Page 17 of pgpDSAKey.c
cd8c63 ¤   PGPStringToKey *s2k = NULL;¤/* Shut up warnings */
ddbfad ¤   PGPCipherVTBL const *cipher = NULL;¤/* Shut up warnings */
d7bf66 ¤   PGPCFBContext *cfb = NULL;¤ /* This is realy needed */
804cc9 ¤   PGPByte *p;
8701ca ¤   int oldf = 0;¤  ¤   ¤   ¤   /* Shut up warnings */
a0c6b5 ¤   unsigned len;
d81b07 ¤   unsigned checksum;
0faf5a
bb3d7c ¤   ASSERTDSA(seckey->pkAlg);
b2d2c6 ¤   if (sec->locked)
ac035c ¤   ¤   return kPGPError_KeyIsLocked;
d5e646 ¤   len = bnBytes(&sec->s.p) + bnBytes(&sec->s.q) + bnBytes(&sec->s.g) +
74abde ¤   ······bnBytes(&sec->s.y) + bnBytes(&sec->s.x) + 13;
1d358f ¤   if (phrase) {
6d0506 ¤   ¤   s2k = pgpS2Kcreate(env, rc, s2ktype);
c0a487 ¤   ¤   if (!s2k)
8c7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
55bb77 ¤   ¤   cipher = pgpCipherDefaultKey(env);
69a7cf ¤   ¤   pgpAssert(cipher);
dbdb89 ¤   ¤   if (!cipher) {
254835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
c47cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
c60fe4 ¤   ¤   }
83e9ea ¤   ¤   len += cipher->blocksize;
b79b42 ¤   ¤   cfb = pgpCFBCreate(
1a614f ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( pgpenvGetContext( env ) ), cipher);
d15dfd ¤   ¤   if (!cfb) {
7a4835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
b67cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
d70fe4 ¤   ¤   }
529484 ¤   ¤   oldf = pgpS2KisOldVers(s2k);
38cfc4 ¤   ¤   if (!oldf)
9f0bcc ¤   ¤   ¤   len += 1 + s2k->encodelen;
4c9371 ¤   }
f19613 ¤   if (len > sec->ckalloc) {
26000e ¤   ¤   PGPError err = kPGPError_NoErr;
63d409 ¤   ¤   if( IsNull( sec->cryptkey ) ) {
93f6b5 ¤   ¤   ¤   sec->cryptkey = (PGPByte *)
077694 ¤   ¤   ¤   ¤   pgpContextMemAlloc( sec->context, len, 0 );
525c6f ¤   ¤   ¤   if( IsNull( sec->cryptkey ) ) {
05bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
5ea3a6 ¤   ¤   ¤   }
fb45a6 ¤   ¤   } else {
8ada85 ¤   ¤   ¤   err = pgpContextMemRealloc( sec->context,
bea54f ¤   ¤   ¤   ¤   (void **)&sec->cryptkey, len, 0 );
320fe4 ¤   ¤   }
e537b3 ¤   ¤   if( IsPGPError( err ) ) {
6c5d4c ¤   ¤   ¤   PGPFreeCFBContext(cfb);
c34835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
69b32f ¤   ¤   ¤   return err;
750fe4 ¤   ¤   }
2678cc ¤   ¤   sec->ckalloc = (size_t)len;
5b9371 ¤   }
5e6cd9 ¤   sec->cklen = len;
bda8ca ¤   p = sec->cryptkey;
5eaf5a
d814eb ¤   /* Okay, no more errors possible! ··Start installing data */
a375f6 ¤   p += pgpBnPutPlain(&sec->s.p, p);
c5ea23 ¤   p += pgpBnPutPlain(&sec->s.q, p);
200727 ¤   p += pgpBnPutPlain(&sec->s.g, p);
0434cf ¤   p += pgpBnPutPlain(&sec->s.y, p);
76af5a
edc4c6 ¤   /* Encryption parameters */
159f26 ¤   if (!phrase) {
cb7625 ¤   ¤   *p++ = 0;¤  /* Unencrypted */
2cf037 ¤   } else {
6634b3 ¤   ¤   if (oldf) {
2dce24 ¤   ¤   ¤   *p++ = cipher->algorithm;
6245a6 ¤   ¤   } else {
150c31 ¤   ¤   ¤   *p++ = 255;
7dce24 ¤   ¤   ¤   *p++ = cipher->algorithm;
a2682f ¤   ¤   ¤   memcpy(p, s2k->encoding, s2k->encodelen);
--c6ab 000084790b24010020a Page 18 of pgpDSAKey.c
cfcb5d ¤   ¤   ¤   p += s2k->encodelen;
880fe4 ¤   ¤   }
baf1d5 ¤   ¤   /* Create IV */
d58277 ¤   ¤   pgpRandomGetBytes(rc, p, cipher->blocksize);
264eef ¤   ¤   /* Use data buffer as temp holding space for key */
7a6961 ¤   ¤   pgpAssert(sec->ckalloc-cipher->blocksize >= cipher->keysize);
c6ff98 ¤   ¤   pgpStringToKey(s2k, phrase, plen, p+cipher->blocksize,
f5ecbe ¤   ¤   ¤   cipher->keysize);
161e9c ¤   ¤   PGPInitCFB(cfb, p+cipher->blocksize, p);
a0e56b ¤   ¤   pgpS2Kdestroy(s2k);
28d63b ¤   ¤   p += cipher->blocksize;
171b01 ¤   ¤   /* Wipe key *immediately* */
16ab67 ¤   ¤   pgpClearMemory( p, ·cipher->keysize);
8a9371 ¤   }
e6af5a
5e0f6e ¤   /* Now install x, encrypted */
6ca2f0 ¤   checksum = 0;
1aca75 ¤   p += pgpBnPutNew(&sec->s.x, p, cfb, &checksum);
46fa97 ¤   pgpChecksumPutNew(checksum, p, cfb);
7d930f ¤   p += 2;
c9d0ef ¤   pgpAssert((ptrdiff_t)len == p - sec->cryptkey);
2eaf5a
0fafda ¤   if (cfb)
0ed6b0 ¤   ¤   PGPFreeCFBContext(cfb);
c029fb ¤   return 0;¤  /* Success */
7eefe6 }
ab0ccc #if PGP_MACINTOSH
6ce4a1 #pragma global_optimizer reset
e27454 #endif
e0af5a
c45d09 static size_t
fa9b29 dsaSecBufferLength(PGPSecKey const *seckey)
74bb36 {
9cfcf7 ¤   DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;
3faf5a
b4b0e6 ¤   return sec->cklen;
16efe6 }
ebaf5a
002978 static void
75938d dsaSecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
72bb36 {
eefcf7 ¤   DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;
27af5a
670030 ¤   memcpy(buf, sec->cryptkey, sec->cklen);
a9af5a
2998c6 ¤   /* Return only algorithm-dependent portion */
feefe6 }
71af5a
c2af5a
4df03c /* Fill in secret key structure */
d62978 static void
b9dbdb dsaFillSecKey(PGPSecKey *seckey, DSAsecPlus *sec)
33bb36 {
1be98c ¤   seckey->pkAlg¤  ············= kPGPPublicKeyAlgorithm_DSA;
5fba80 ¤   seckey->priv¤   ············= sec;
33c3ee ¤   seckey->destroy ············= dsaSecDestroy;
47b6e3 ¤   seckey->pubkey ·············= dsaPubkey;
7e1b48 ¤   seckey->islocked ···········= dsaIslocked;
99b669 ¤   seckey->lockingalgorithm ···= dsaLockingAlgorithm;
9c2013 ¤   seckey->s2ktype ············= dsaS2KType;
9ae330 ¤   seckey->convertpassphrase ··= dsaConvertPassphrase;
3cb7f5 ¤   seckey->unlock ·············= dsaUnlock;
66f42c ¤   seckey->lock ···············= dsaLock;
fdf7ce ¤   seckey->decrypt ············= dsaDecrypt;
471e8e ¤   seckey->maxdecrypted ·······= dsaSecMaxdecrypted;
702d05 ¤   seckey->maxesk ·············= dsaSecMaxesk;
19a1cb ¤   seckey->maxsig ·············= dsaSecMaxsig;
474ab0 ¤   seckey->sign ···············= dsaSign;
761469 ¤   seckey->changeLock ·········= dsaChangeLock;
fc5312 ¤   seckey->bufferLength ·······= dsaSecBufferLength;
c202fd ¤   seckey->toBuffer ···········= dsaSecToBuffer;
08efe6 }
--1d30 0009e6e5cbe4010020a Page 19 of pgpDSAKey.c
e0af5a
1aaf5a
6e521e PGPSecKey *
e64afd dsaSecFromBuf(
61520e ¤   PGPContextRef¤  context,
be4d2b ¤   PGPByte const *¤buf,
ce39e0 ¤   size_t¤ ¤   ¤   size,
7c6429 ¤   PGPError *¤ ¤   error)
f7bb36 {
434bdc ¤   PGPSecKey *seckey;
d4f0b3 ¤   DSAsecPlus *sec;
d2e99a ¤   PGPByte *cryptk;
a44c08 ¤   PGPError¤   err¤= kPGPError_OutOfMemory;
dcf9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
9aca2b ¤   PGPEnv *¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( context );
dbaf5a
f5bac4 ¤   bnInit();
5fdee6 ¤   cryptk = (PGPByte *)pgpContextMemAlloc( context,
772217 ¤   ¤   size, kPGPMemoryMgrFlags_Clear);
7d7809 ¤   if (cryptk) {
12cb9b ¤   ¤   sec = (DSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
c16492 ¤   ¤   if (sec) {
e8ae3f ¤   ¤   ¤   pgpClearMemory( sec, sizeof(*sec) );
7a2da8 ¤   ¤   ¤   sec->context¤   = context;
4187c7 ¤   ¤   ¤
2078b7 ¤   ¤   ¤   seckey = (PGPSecKey *) pgpContextMemAlloc( context,
d9480b ¤   ¤   ¤   ¤   ¤   sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
cf1bb1 ¤   ¤   ¤   if (seckey) {
06e337 ¤   ¤   ¤   ¤   seckey->context¤= context;
0f87c7 ¤   ¤   ¤
e2bc41 ¤   ¤   ¤   ¤   memcpy(cryptk, buf, size);
2acae5 ¤   ¤   ¤   ¤   bnBegin(&sec->s.p, mgr, FALSE );
80daea ¤   ¤   ¤   ¤   bnBegin(&sec->s.q, mgr, FALSE );
39b229 ¤   ¤   ¤   ¤   bnBegin(&sec->s.g, mgr, FALSE );
e85a92 ¤   ¤   ¤   ¤   bnBegin(&sec->s.y, mgr, FALSE );
7891ef ¤   ¤   ¤   ¤   bnBegin(&sec->s.x, mgr, TRUE );
fb4699 ¤   ¤   ¤   ¤   sec->cryptkey = cryptk;
88b1a8 ¤   ¤   ¤   ¤   sec->cklen = sec->ckalloc = size;
bb6564 ¤   ¤   ¤   ¤   sec->locked = 1;
eabc1d ¤   ¤   ¤   ¤   /* We only need this to try unlocking... */
ed8dff ¤   ¤   ¤   ¤   seckey->pkAlg = kPGPPublicKeyAlgorithm_DSA;
4e22e9 ¤   ¤   ¤   ¤   seckey->priv = sec;
e82b85 ¤   ¤   ¤   ¤
0e8113 ¤   ¤   ¤   ¤   if (dsaUnlock(seckey, pgpEnv, NULL, 0, FALSE) >= 0) {
ba347d ¤   ¤   ¤   ¤   ¤   if (dsaKeyTooBig (NULL, &sec->s)) {
9b9807 ¤   ¤   ¤   ¤   ¤   ¤   bnEnd(&sec->s.p);
8c84bc ¤   ¤   ¤   ¤   ¤   ¤   bnEnd(&sec->s.q);
a50c87 ¤   ¤   ¤   ¤   ¤   ¤   bnEnd(&sec->s.g);
d96164 ¤   ¤   ¤   ¤   ¤   ¤   bnEnd(&sec->s.y);
191c30 ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_KeyTooLarge;
c281a1 ¤   ¤   ¤   ¤   ¤   } else {
286068 ¤   ¤   ¤   ¤   ¤   ¤   dsaFillSecKey(seckey, sec);
24bf96 ¤   ¤   ¤   ¤   ¤   ¤   *error = 0;
890a17 ¤   ¤   ¤   ¤   ¤   ¤   return seckey;¤ /* Success! */
5a1c89 ¤   ¤   ¤   ¤   ¤   }
422613 ¤   ¤   ¤   ¤   }
62af5a
fb26c6 ¤   ¤   ¤   ¤   /* Ka-boom. ·Delete and free everything. */
7fd423 ¤   ¤   ¤   ¤   pgpClearMemory( cryptk, ·size);
0e3e32 ¤   ¤   ¤   ¤   pgpContextMemFree( context, seckey);
86a3a6 ¤   ¤   ¤   }
6646d9 ¤   ¤   ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
a90fe4 ¤   ¤   }
d4718e ¤   ¤   pgpContextMemFree( context, cryptk);
b59371 ¤   }
32ab59 ¤   *error = err;
533f59 ¤   return NULL;
e9efe6 }
d5af5a
2eaf5a
e338e5 /*
9edd33 ·* Generate an DSA secret key with prime of the specified number of bits.
--850e 0008ca4cf5e4010020a Page 20 of pgpDSAKey.c
03dce8 ·* Make callbacks to progress function periodically.
2b7af8 ·* Secret key is returned in the unlocked form, with no passphrase set.
e9fae6 ·* fastgen tells us to use canned primes if available.
09775e ·*
306364 ·* PGP attempts to acquire enough true random entropy in the randpool to
aa256c ·* make the keys it generates fully random and unpredictable, even if the
084a58 ·* RNG used to generate them were later found to have some weaknesses. ·With
15c3c6 ·* RSA keys it gets as many bits as the size of the modulus since the sizes
c5149c ·* of the secret primes p and q will add up to the size of the modulus.
85b031 ·* (This is slight overkill since the entropy in a random prime is less
d4b04e ·* than the entropy of a random number because not all numbers are prime.)
f8775e ·*
bc411a ·* With discrete log based keys, DSA and ElGamal, only the private exponent
60b25b ·* x needs to be kept secret. ·However, the public values are generated at
8d6ced ·* the same time as x, and are seeded ultimately from the same randpool.
8c22cd ·* These values could theoretically leak information about the state of the
145a43 ·* randpool when they were generated, and therefore about x. ·This would
0dc556 ·* require a very powerful attack which will probably never be possible,
794c0f ·* but we want to defend against it. ·One approach would simply be to acquire
a98c0d ·* as much additional entropy as is needed for the public values, but that
655223 ·* is wasteful. ·The public values don't need to be random, we just want them
155b92 ·* to be different among users.
26775e ·*
e98846 ·* Instead, we create a "firewall" between the randpool and the public
0915e9 ·* key values. ·We instantiate a second PGPRandomContext which is not
58b16f ·* based on the randpool but is a simple pseudo RNG, and seed it with
942bdc ·* a fixed number of bits from the true RNG. ·We choose enough bits
0d225f ·* for the seeding that different keys will not share the same public
93ff22 ·* values. ·Only this fixed number of bits reflects the state of the
b17c1b ·* randpool, so we acquire that many bits of additional entropy before
99fd80 ·* beginning the keygen. ·This second RNG, rcdummy below and in the
66342c ·* ElGamal keygen, is used to generate the public values for the discrete
c285ef ·* log key.
3b495d ·*/
4f521e PGPSecKey *
34aba5 dsaSecGenerate(
ba520e ¤   PGPContextRef¤  context,
b88285 ¤   unsigned bits, PGPBoolean fastgen,
5c4b45 ¤   PGPRandomContext const *rc,
9402ee ¤   int progress(void *arg, int c), void *arg, PGPError *error)
3cbb36 {
4d49fe ¤   PGPSecKey *seckey¤  = NULL;
01f0b3 ¤   DSAsecPlus *sec;
cc9c71 ¤   PGPRandomContext *rcdummy = NULL;
0b35ff ¤   BigNum h;
b2ca80 ¤   BigNum e;
0f15bf ¤   unsigned qbits;
5c4ba4 ¤   int i;
ec2680 ¤   PGPByte dummyseed[DSADUMMYBITS/8];
eaf9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
94ca2b ¤   PGPEnv *¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( context );
3aaf5a
1a9096 ¤   *error = kPGPError_NoErr;
beaf5a
ad208e ¤   /* Initialize local pointers (simplify cleanup below) */
ad3670 ¤   seckey = NULL;
b32d16 ¤   sec = NULL;
8eb1a9 ¤   bnBegin(&h, mgr, FALSE );
cf61e2 ¤   bnBegin(&e, mgr, FALSE );
ff67c5 ¤
835011 ¤   /* Limit the size we will generate at this time */
5639a3 ¤   if (bits > MAX_DSA_PRIME_BITS) {
27dc80 ¤   ¤   *error = kPGPError_PublicKeyTooLarge;
7d262d ¤   ¤   goto done;
849371 ¤   }
71af5a
2eaf5a
07af5a
860e57 ¤   /* Allocate data structures */
392ab1 ¤   seckey = (PGPSecKey *)pgpContextMemAlloc( context,
ac56ec ¤   ¤   sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
8c2672 ¤   if (!seckey)
--4c6d 000e59b42854010020a Page 21 of pgpDSAKey.c
15718c ¤   ¤   goto memerror;
f820f7 ¤   seckey->context¤= context;
6edeb8 ¤   sec = (DSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
3365c7 ¤   if (!sec)
a7718c ¤   ¤   goto memerror;
d8fa1a ¤   pgpClearMemory( sec, sizeof(*sec) );
03e024 ¤   sec->context¤   = context;
3167c5 ¤
639b2d ¤   bnBegin(&sec->s.p, mgr, FALSE );
f18b22 ¤   bnBegin(&sec->s.q, mgr, FALSE );
11e3e1 ¤   bnBegin(&sec->s.g, mgr, FALSE );
020b5a ¤   bnBegin(&sec->s.y, mgr, FALSE );
53c48c ¤   bnBegin(&sec->s.x, mgr, TRUE );
3caf5a
45f9fb ¤   /* Use fixed primes and generator if in our table */
f60233 ¤   if (fastgen) {
25e9c6 ¤   ¤   PGPByte const *fixedp, *fixedq;
55c1ee ¤   ¤   size_t fixedplen, fixedqlen;
fd229c ¤   ¤   if (pgpDSAfixed (bits, &fixedp, &fixedplen, &fixedq, &fixedqlen) > 0) {
fcf2e5 ¤   ¤   ¤   bnInsertBigBytes (&sec->s.q, fixedq, 0, fixedqlen);
efeb3f ¤   ¤   ¤   if (progress)
77c69e ¤   ¤   ¤   ¤   progress(arg, ' ');
ed5887 ¤   ¤   ¤   bnInsertBigBytes (&sec->s.p, fixedp, 0, fixedplen);
f0eb3f ¤   ¤   ¤   if (progress)
61c69e ¤   ¤   ¤   ¤   progress(arg, ' ');
7a595e ¤   ¤   ¤   qbits = bnBits (&sec->s.q);
1c8d11 ¤   ¤   ¤   goto choose_g;
de0fe4 ¤   ¤   }
769371 ¤   }
f5af5a
24fe1a ¤   /* Set up and seed local random number generator for p and q */
4fb5b9 ¤   rcdummy = pgpPseudoRandomCreate ( rc->context );
38727a ¤   if (!rcdummy)
4d718c ¤   ¤   goto memerror;
72b76f ¤   pgpRandomGetBytes (rc, dummyseed, sizeof(dummyseed));
205239 ¤   pgpRandomAddBytes (rcdummy, dummyseed, sizeof(dummyseed));
b5af5a
f1d8af ¤   /*
cf439f ¤   ·* Choose a random starting place for q, in the high end of the range
aaa4e3 ¤   ·*/
7b3a3a ¤   if (bits <= 1024)
6d7e3a ¤   ¤   qbits = 160;¤   /* Follow the published standard */
1a0e24 ¤   else
400576 ¤   ¤   qbits = pgpDiscreteLogQBits(bits);
7cd392 ¤   if (pgpBnGenRand(&sec->s.q, rcdummy, qbits, 0xFF, 1, qbits-9) < 0)
cf5b40 ¤   ¤   goto nomem;
6f9b4f ¤   /* And search for a prime */
1d1210 ¤   i = bnPrimeGen(&sec->s.q, NULL, progress, arg, 0);
c24fd6 ¤   if (i < 0)
555b40 ¤   ¤   goto nomem;
1d1610 ¤   if (progress)
6ee03c ¤   ¤   progress(arg, ' ');
f7af5a
f54191 ¤   /* ...and now a random start for p (we discard qbits bits of it) */
981e57 ¤   (void)bnSetQ(&sec->s.p, 0);
fcfb76 ¤   if (pgpBnGenRand(&sec->s.p, rcdummy, bits, 0xC0, 1, bits-qbits) < 0)
9b5b40 ¤   ¤   goto nomem;
ddaf5a
710aaa ¤   /* Temporarily double q */
40892a ¤   if (bnLShift(&sec->s.q, 1) < 0)
2c5b40 ¤   ¤   goto nomem;
ccaf5a
a44fb1 ¤   /* Set p = p - (p mod q) + 1, i.e. congruent to 1 mod 2*q */
2c9312 ¤   if (bnMod(&e, &sec->s.p, &sec->s.q) < 0)
0f5b40 ¤   ¤   goto nomem;
d82d34 ¤   if (bnSub(&sec->s.p, &e) < 0 || bnAddQ(&sec->s.p, 1) < 0)
145b40 ¤   ¤   goto nomem;
88af5a
ebfa6e ¤   /* And search for a prime, 1+2kq for some k */
3c2d72 ¤   i = bnPrimeGenStrong(&sec->s.p, &sec->s.q, progress, arg);
c14fd6 ¤   if (i < 0)
e55b40 ¤   ¤   goto nomem;
--efa3 0005152b43b4010020a Page 22 of pgpDSAKey.c
121610 ¤   if (progress)
f4e03c ¤   ¤   progress(arg, ' ');
bfaf5a
9734dd ¤   /* Reduce q again */
576a5b ¤   bnRShift(&sec->s.q, 1);
65af5a
07d349 ¤   /* May get here directly from above if fixed primes are used */
217c41 choose_g:
abaf5a
d582ca ¤   /* Now hunt for a suitable g - first, find (p-1)/q */
fe5217 ¤   if (bnDivMod(&e, &h, &sec->s.p, &sec->s.q) < 0)
8f5b40 ¤   ¤   goto nomem;
d2b0e3 ¤   /* e is now the exponent (p-1)/q, and h is the remainder (one!) */
e48f0d ¤   pgpAssert(bnBits(&h)==1);
a2af5a
ba1610 ¤   if (progress)
a08184 ¤   ¤   progress(arg, '.');
84af5a
1467bf ¤   /* Search for a suitable h */
947e73 ¤   if (bnSetQ(&h, 2) < 0 ||
33e4e3 ¤   ····bnTwoExpMod(&sec->s.g, &e, &sec->s.p) < 0)
875b40 ¤   ¤   goto nomem;
e7fcfa ¤   while (bnBits(&sec->s.g) < 2) {
9d2c8a ¤   ¤   if (progress)
222cda ¤   ¤   ¤   progress(arg, '.');
2f13c0 ¤   ¤   if (bnAddQ(&h, 1) < 0 ||
37f569 ¤   ¤   ····bnExpMod(&sec->s.g, &h, &e, &sec->s.p) < 0)
4021b4 ¤   ¤   ¤   goto nomem;
f69371 ¤   }
d71610 ¤   if (progress)
ace03c ¤   ¤   progress(arg, ' ');
fcaf5a
f698ff ¤   /* Choose a random 0 < x < q of reasonable size as secret key */
5554fc ¤   if (pgpBnGenRand(&sec->s.x, rc, qbits + 8, 0, 0, qbits) < 0 ||
77e6fa ¤   ····bnMod(&sec->s.x, &sec->s.x, &sec->s.q) < 0)
795b40 ¤   ¤   goto nomem;
56323c ¤   /* prob. failure < 2^-140 is awful unlikely... */
f71f0c ¤   pgpAssert(bnBits(&sec->s.x) > 20);
d8af5a
177de8 ¤   /* And calculate g**x as public key */
75f32a ¤   if (bnExpMod(&sec->s.y, &sec->s.g, &sec->s.x, &sec->s.p) < 0)
745b40 ¤   ¤   goto nomem;
90af5a
a21fb6 ¤   /* And that's it... success! */
f3af5a
192d0e ¤   /* Fill in structs */
f9c257 ¤   sec->cryptkey = NULL;
70a3cb ¤   sec->ckalloc = sec->cklen = 0;
a30162 ¤   sec->locked = 0;
0f28b6 ¤   dsaFillSecKey(seckey, sec);
78af5a
6eb736 ¤   /* Fill in cryptkey structure, unencrypted */
787adb ¤   dsaChangeLock (seckey, pgpEnv, NULL, NULL, 0, kPGPStringToKey_Simple);
d3af5a
47c48e ¤   goto done;
54af5a
0fac52 nomem:
e23273 ¤   bnEnd(&sec->s.p);
252ec8 ¤   bnEnd(&sec->s.q);
62a6f3 ¤   bnEnd(&sec->s.g);
decb10 ¤   bnEnd(&sec->s.y);
a7d7ab ¤   bnEnd(&sec->s.x);
af91b1 ¤   /* Fall through */
be623d memerror:
3f54f2 ¤   if ( IsntNull( seckey ) )
683fb4 ¤   ¤   pgpContextMemFree( context, seckey);
d46101 ¤   if ( IsntNull( sec ) )
6882c5 ¤   ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
553670 ¤   seckey = NULL;
2c27b8 ¤   *error = kPGPError_OutOfMemory;
6e91b1 ¤   /* Fall through */
51b38c done:
--2228 001f4b4a3ec4010020a Page 23 of pgpDSAKey.c
73c4de ¤   bnEnd(&h);
474f51 ¤   bnEnd(&e);
bbaf5a
4ea925 ¤   if (rcdummy)
bd12fa ¤   ¤   pgpRandomDestroy (rcdummy);
91af5a
8f4d98 ¤   return seckey;
60efe6 }
f4af5a
--2864 0012fe62aae4010020b Page 1 of pgpDSAKey.h
bc38e5 /*
076fbd ·* $Id: pgpDSAKey.h,v 1.10 1997/06/25 19:40:54 lloyd Exp $
b8495d ·*/
00af5a
63bde8 #ifndef Included_pgpDSAKey_h
4e3cde #define Included_pgpDSAKey_h
4daf5a
5fa395 #include "pgpPubTypes.h"¤   /* For PGPByte */
f1adb8 #include "pgpOpaqueStructs.h"
89c546 #include <stddef.h>¤/* For size_t */
4eaf5a
3599c6 PGP_BEGIN_C_DECLARATIONS
ceaf5a
ac25e5 /* Bits for uniqueness of p, q */
4f385a #define DSADUMMYBITS¤   64
5aaf5a
97af5a
be150d PGPPubKey *dsaPubFromBuf( PGPContextRef¤context,
fbfe12 ¤   ¤   ¤   ¤   PGPByte const *buf, size_t len, PGPError *error);
232b85 ¤   ¤   ¤   ¤
4715df PGPSecKey *dsaSecFromBuf( PGPContextRef¤context,
a7fe12 ¤   ¤   ¤   ¤   PGPByte const *buf, size_t len, PGPError *error);
a42b85 ¤   ¤   ¤   ¤
91dcad int¤¤   ¤   dsaPubKeyPrefixSize(PGPByte const *buf, size_t size);
86af5a
6d4fd8 PGPSecKey *¤dsaSecGenerate(PGPContextRef context,
5cc5e3 ¤   ¤   ¤   ¤   unsigned bits, PGPBoolean fastgen,
258d8a ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
881ebb ¤   ¤   ¤   ¤   int progress(void *arg, int c), void *arg, PGPError *error);
b4af5a
851254 PGP_END_C_DECLARATIONS
46af5a
2f0110 #endif /* Included_pgpDSAKey_h */
--b490 00065374f774010020c Page 1 of pgpESK.c
bc38e5 /*
a71f66 ·* $Id: pgpESK.c,v 1.29 1998/04/02 05:37:32 hal Exp $
cb495d ·*/
6daf5a
2ce2ff #include "pgpConfig.h"
37af5a
36a146 #include "pgpDebug.h"
7557c7 #include "pgpESK.h"
15ba29 #include "pgpPktList.h"
ad6aaa #include "pgpAnnotate.h"
d11e2d #include "pgpCFBPriv.h"
ab0e2f #include "pgpSymmetricCipherPriv.h"
a55417 #include "pgpHashPriv.h"
050d08 #include "pgpMem.h"
2e2f8d #include "pgpErrors.h"
cbcdc2 #include "pgpPubKey.h"
c55579 #include "pgpStr2Key.h"
1bd11f #include "pgpUsuals.h"
310d6d #include "pgpEnv.h"
727ca7 #include "pgpKeyIDPriv.h"
59af5a
67baf8 #define ESKTYPE_CONV¤   (PGP_ESKTYPE_PASSPHRASE<<8)
6480ca #define ESKTYPE_NEWCONV ((PGP_ESKTYPE_PASSPHRASE<<8)+1)
d67e9d #define ESKTYPE_PK¤ (PGP_ESKTYPE_PUBKEY<<8)
eebf9b #define ESKTYPE_RSA¤((PGP_ESKTYPE_PUBKEY<<8)+kPGPPublicKeyAlgorithm_RSA)
1faf5a
24f933 struct PGPESK
6ebb36 {
827de6 ¤   PktList pkt;
ac2fa1 } ;
97af5a
0b38e5 /*
899376 ·* A PK ESK is:
d17a48 ·* ·0 ·1 ···Version
2f8142 ·* ·1 ·8 ···KeyID
9131d6 ·* ·9 ·1 ···PK alg
274147 ·* 10 ······Algorithm specific data
64495d ·*/
7cbeb7 static int
f47dd7 eskPubkeyValidate(PGPByte const *buf, size_t len)
febb36 {
6173e9 ¤   unsigned bits;
92af5a
240ece ¤   if (len < 1)
e17298 ¤   ¤   return kPGPError_BadSessionKeySize;
e3c1ae ¤   if (buf[0] != 2 && buf[0] != 3 && buf[0] != 4)¤ /* Version byte */
55333f ¤   ¤   return kPGPError_UnknownVersion;
3c90f6 ¤   if (len < 10)
d07298 ¤   ¤   return kPGPError_BadSessionKeySize;
4d7e45 ¤   switch (buf[9]) {¤  /* Algorithm Byte */
c139f8 ¤   ··case kPGPPublicKeyAlgorithm_RSA:
9fa6b1 ¤   ¤   bits = ((unsigned)buf[10]<<8) + buf[11];
09bcb5 ¤   ¤   if (len != 12+(bits+7)/8)
0853fa ¤   ¤   ¤   return len < 12+(bits+7)/8 ? kPGPError_BadSessionKeySize :
38b1bb ¤   ¤   ¤   ¤   ¤   ¤   ·····kPGPError_BadSessionKeySize;
66ea79 ¤   ¤   return ESKTYPE_RSA;
ba9371 ¤   }
c96b7b ¤   return ESKTYPE_PK + buf[9];
15efe6 }
43af5a
ca38e5 /*
a26dc5 ·* A SK ESK is:
a97a48 ·* ·0 ·1 ···Version
5c0b03 ·* ·1 ·1 ···Cipher
a10fa3 ·* ·2 ·x ···StringToKey (x >= 1)
289732 ·* 2+x y ···ESK (y >= 0)
eb495d ·*/
6cbeb7 static int
3678b2 eskConvkeyValidate (PGPByte const *buf, size_t len)
9ebb36 {
329bc0 ¤   PGPCipherVTBL const *c;
65d123 ¤   int ret;
--44b4 0007ca12a974010020c Page 2 of pgpESK.c
e0af5a
604404 ¤   if (!len)
8223ac ¤   ¤   return ESKTYPE_CONV;
aabb76 ¤   if (len < 3)
017298 ¤   ¤   return kPGPError_BadSessionKeySize;
0ed1ec ¤   if (buf[0] != 4)¤   /* Version byte */
68333f ¤   ¤   return kPGPError_UnknownVersion;
ceaf5a
b815a7 ¤   /* Try to decode the ESK */
c72699 ¤   c = pgpCipherGetVTBL ( (PGPCipherAlgorithm)buf[1]);
3c272b ¤   if (!c)
f1db01 ¤   ¤   return kPGPError_BadSessionKeyAlgorithm;
86af5a
2d5da8 ¤   /* Decode the string to key algorithm */
8411bf ¤   ret = pgpS2Kdecode (NULL, NULL, buf+2, len-2);
d32ccd ¤   if (ret < 0)
b10f1e ¤   ¤   return ret;
b3adf1 ¤   if (ret == 0)
fedb01 ¤   ¤   return kPGPError_BadSessionKeyAlgorithm;
126011 ¤   len -= 2+ret;
6283f3 ¤   if (len == 0)
09de3b ¤   ¤   return ESKTYPE_NEWCONV;
bcc6a5 ¤   /* Note that message may be encrypted with different algorithm than ESK */
797365 ¤   return ESKTYPE_NEWCONV;
76efe6 }
9faf5a
bf257d static PGPESK **
c40faa eskListTail(PGPESK **head)
acbb36 {
141e6d ¤   while (*head)
1d8b55 ¤   ¤   head = (PGPESK **)&(*head)->pkt.next;
4cb737 ¤   return head;
36efe6 }
4aaf5a
a9c45d /* Add an PGPESK to a list thereof */
0f4d2f int
5f6df2 pgpEskAdd(
ff3163 ¤   PGPContextRef¤  cdkContext,
ed4cdf ¤   PGPESK **esklist, int type, PGPByte const *buf, size_t len)
19bb36 {
66c33c ¤   PGPESK *esk;
a24ba4 ¤   int i;
47af5a
851609 ¤   switch (type) {
0514a0 ¤   ··case PGPANN_SKCIPHER_ESK:
768417 ¤   ¤   i = eskConvkeyValidate(buf, len);
b9ad75 ¤   ¤   if (i < 0)
f29eb9 ¤   ¤   ¤   return i;
6d2f68 ¤   ¤   break;
cc979e ¤   ··case PGPANN_PKCIPHER_ESK:
dc7c33 ¤   ¤   i = eskPubkeyValidate(buf, len);
7ead75 ¤   ¤   if (i < 0)
389eb9 ¤   ¤   ¤   return i;
ee2f68 ¤   ¤   break;
9df727 ¤   ··default:
2d62b5 ¤   ¤   return kPGPError_BadParams;
679371 ¤   }
846f97 ¤   esk = (PGPESK *)pgpPktListNew( cdkContext, i, buf, len);
e2281a ¤   *eskListTail(esklist) = esk;
713fa2 ¤   return esk ? 0 : kPGPError_OutOfMemory;
93efe6 }
c9af5a
fc27a1 /* A few trivial access functions */
bbaf5a
bc314a void
7d5f13 pgpEskFreeList (PGPESK *esklist)
72bb36 {
d721b1 ¤   pgpPktListFreeList((PktList *)esklist);
21efe6 }
d3af5a
0148bf PGPESK *
7c4f97 pgpEskNext (PGPESK const *esk)
--2ebd 0000226e8b14010020c Page 3 of pgpESK.c
2cbb36 {
02a5aa ¤   if (esk)
8a01b6 ¤   ¤   return (PGPESK *)esk->pkt.next;
1daf5a
c43f59 ¤   return NULL;
80efe6 }
64af5a
8c4d2f int
e44e65 pgpEskType(PGPESK const *esk)
fabb36 {
67077c ¤   return esk->pkt.type >> 8;
42efe6 }
a5af5a
98e338 /* Returns PGP_PKALG_xxx */
954d2f int
4c00b7 pgpEskPKAlg(PGPESK const *esk)
8cbb36 {
0b219b ¤   pgpAssert(esk->pkt.type >> 8 == PGP_ESKTYPE_PUBKEY);
bb90a7 ¤   return esk->pkt.type & 255;
a5efe6 }
7baf5a
f2b85e ¤   static PGPByte const *
56818b pgpEskId8(PGPESK const *esk)
60bb36 {
03219b ¤   pgpAssert(esk->pkt.type >> 8 == PGP_ESKTYPE_PUBKEY);
4ae2d8 ¤   return esk->pkt.buf+1;
a1efe6 }
e7af5a
ffaf5a
35c744 ¤   PGPError
b6c275 pgpGetEskKeyID(
4118fb ¤   PGPESK const *¤ esk,
4556fa ¤   PGPKeyID *¤ ¤   outRef )
d1bb36 {
9326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
1467c5 ¤
278202 ¤   err¤= pgpNewKeyIDFromRawData( pgpEskId8( esk ), 8, outRef );
1a67c5 ¤
b3deb7 ¤   return( err );
43efe6 }
d0af5a
dfaf5a
1e38e5 /*
b5d6d5 ·* Return the size of the largest possible key that may
1f3b43 ·* be produced as output from and eskXXdecrypt() function.
5b495d ·*/
2844d2 size_t
fff375 pgpEskMaxKeySize (PGPESK const *esk)
ebbb36 {
cbd2f5 ¤   switch (pgpEskType (esk)) {
3bc4a8 ¤   case PGP_ESKTYPE_PASSPHRASE:
f2d9e9 ¤   ¤   return (size_t) (pgpMax ((int)25, (int)(((int)esk->pkt.len)-3)));
552f81 ¤   case PGP_ESKTYPE_PUBKEY:
1a789b ¤   ¤   /* XXX -- this only works with RSA, no? ·Need a PGPSecKey
6cc695 ¤   ¤   ···object to do better, though.*/
5004fb ¤   ¤   return pgpMax (25, esk->pkt.len-10);
e59371 ¤   }
f13e6b ¤   return 0;
1aefe6 }
85af5a
6138e5 /*
70ef7b ·* The "key" is from a pass phrase. ·Returns the length of the key,
dc1333 ·* which is <algorithm identifier><key bits>. ·The actual key is
3a0301 ·* obtained via a string-to-key operation.
e9495d ·*/
5f4d2f int
72baa1 pgpEskConvDecrypt(PGPESK const *esk, PGPEnv const *env,
c933aa ¤   ¤   ··char const *pass, size_t plen, PGPByte *buf)
08bb36 {
e25cb3 ¤   PGPStringToKey *s2k = NULL;
d11f93 ¤   PGPCFBContext *cfb = NULL;
020078 ¤   int ret = 0;
--130a 00008b7659c4010020c Page 4 of pgpESK.c
3ec520 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( env );
b9af5a
0d09b0 ¤   switch (esk->pkt.type & 0xff) {
d78674 ¤   ¤   PGPHashVTBL const *hash;
45369e ¤   ¤   PGPCipherVTBL const *c;
36b554 ¤   ¤   PGPByte *key;
2192ed ¤   ¤   PGPByte const *off;
5047a5 ¤   ¤   int len;
0df86f ¤   case 0:
f986d1 ¤   ¤   /* Old-style (non ConvESK) */
3baa22 ¤   ¤   hash = pgpHashByNumber(kPGPHashAlgorithm_MD5);
ae2bfa ¤   ¤   if (!hash)
c5ce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
114b23 ¤   ¤   c = pgpCipherGetVTBL (kPGPCipherAlgorithm_IDEA);
293d9b ¤   ¤   if (!c)
54c2a8 ¤   ¤   ¤   return kPGPError_BadCipherNumber;
15e218 ¤   ¤   s2k = pgpS2Ksimple (env, hash);
9d21f2 ¤   ¤   buf[0] = kPGPCipherAlgorithm_IDEA;
38947f ¤   ¤   ret = pgpStringToKey (s2k, pass, plen, buf+1, c->keysize);
2be2a6 ¤   ¤   if (!ret)
2614eb ¤   ¤   ¤   ret = c->keysize+1;
902f68 ¤   ¤   break;
32a2b3 ¤   case 1:
1be352 ¤   ¤   c = pgpCipherGetVTBL ( (PGPCipherAlgorithm)esk->pkt.buf[1]);
543d9b ¤   ¤   if (!c)
8dc2a8 ¤   ¤   ¤   return kPGPError_BadCipherNumber;
df5b44 ¤   ¤   ret = pgpS2Kdecode (&s2k, env, esk->pkt.buf+2, esk->pkt.len-2);
e66d46 ¤   ¤   if (ret < 0)
2275ea ¤   ¤   ¤   return ret;
76a487 ¤   ¤   if (!s2k)
e07cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
a12a00 ¤   ¤   if (esk->pkt.len-2-ret != 0) {
ff14f6 ¤   ¤   ¤   /* We have an ESK in the packet */
7ffc90 ¤   ¤   ¤   off = esk->pkt.buf+2+ret; /* ESK starts here */
5e105e ¤   ¤   ¤   len = esk->pkt.len-2-ret; /* ESK length */
d5af5a
da270e ¤   ¤   ¤   cfb = pgpCFBCreate ( PGPGetContextMemoryMgr( cdkContext ), c);
be2709 ¤   ¤   ¤   if (!cfb) {
22b51b ¤   ¤   ¤   ¤   ret = kPGPError_OutOfMemory;
a4f622 ¤   ¤   ¤   ¤   break;
69a3a6 ¤   ¤   ¤   }
34e2ce ¤   ¤   ¤   key = (PGPByte *)pgpContextMemAlloc( cdkContext,
e31311 ¤   ¤   ¤   ¤   c->keysize, kPGPMemoryMgrFlags_Clear);
ca0634 ¤   ¤   ¤   if (!key) {
e3b51b ¤   ¤   ¤   ¤   ret = kPGPError_OutOfMemory;
09f622 ¤   ¤   ¤   ¤   break;
8ba3a6 ¤   ¤   ¤   }
0bf3a1 ¤   ¤   ¤   ret = pgpStringToKey (s2k, pass, plen, key,
09dddf ¤   ¤   ¤   ¤   ¤   ······c->keysize);
364432 ¤   ¤   ¤   if (ret) {
9489a5 ¤   ¤   ¤   ¤   pgpClearMemory( key, ·c->keysize);
c5e31c ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, key);
e9f622 ¤   ¤   ¤   ¤   break;
dba3a6 ¤   ¤   ¤   }
1914fc ¤   ¤   ¤   PGPInitCFB (cfb, key, NULL);
005117 ¤   ¤   ¤   pgpClearMemory( key, ·c->keysize);
fab007 ¤   ¤   ¤   pgpContextMemFree( cdkContext, key);
570b4d ¤   ¤   ¤   PGPCFBDecrypt (cfb, off, len, buf);
c36f04 ¤   ¤   ¤   pgpCFBWipe (cfb);
c9ffe5 ¤   ¤   ¤   ret = len;
5645a6 ¤   ¤   } else {
3d275f ¤   ¤   ¤   /* this is just a key to use */
59b825 ¤   ¤   ¤   buf[0] = c->algorithm;
4273e6 ¤   ¤   ¤   ret = pgpStringToKey (s2k, pass, plen, buf+1,
bcdddf ¤   ¤   ¤   ¤   ¤   ······c->keysize);
96d83c ¤   ¤   ¤   if (!ret)
f29f17 ¤   ¤   ¤   ¤   ret = c->keysize+1;
020fe4 ¤   ¤   }
3d2f68 ¤   ¤   break;
e42f72 ¤   default:
197cab ¤   ¤   ret = kPGPError_BadParams;
089371 ¤   }
--cf0c 0010586b84c4010020c Page 5 of pgpESK.c
e0af5a
16207e ¤   if (s2k)
cdc9f1 ¤   ¤   pgpS2Kdestroy (s2k);
45afda ¤   if (cfb)
96d6b0 ¤   ¤   PGPFreeCFBContext(cfb);
0baf5a
4a986d ¤   return ret;
82efe6 }
51af5a
d438e5 /*
f01820 ·* Do public-key decryption - buf must be "big enough" as defined by
c614e9 ·* pgpSecKeyMaxDecrypted(). ·Returns the length of the decrypted key, or
04e3b2 ·* <0 on error.
8d495d ·*/
b94d2f int
5ea3af pgpEskPKdecrypt(PGPESK const *esk, PGPEnv const *env,
112477 ¤   ¤   PGPSecKey *sec, PGPByte *buf)
fbbb36 {
5af20c ¤   size_t len;
b817e6 ¤   int err;
c4af5a
33c6a7 ¤   pgpAssert (sec->decrypt);
35bda3 ¤   /* XXX should "die" gracefully, here */
0faf5a
9d8dc5 ¤   err = pgpSecKeyDecrypt(sec, env, esk->pkt.buf+10, esk->pkt.len-10,
5d378e ¤   ¤   ¤   ¤   ¤   ¤   ···buf, &len, NULL, 0, kPGPPublicKeyMessageFormat_PGP);
d5a09a ¤   if (err)
11c9db ¤   ¤   return err;
3cec7a ¤   return (int) len;
05efe6 }
--338c 001c6c2e16e4010020d Page 1 of pgpESK.h
bc38e5 /*
a466e0 ·* pgpESK.h -- Encrypted Session Key handler.
63775e ·*
26c866 ·* $Id: pgpESK.h,v 1.11 1997/10/08 01:48:25 lloyd Exp $
59495d ·*/
d6af5a
faaf7b #ifndef Included_pgpESK_h
d6e76c #define Included_pgpESK_h
5daf5a
0fc26c #include "pgpContext.h"
3daf5a
5399c6 PGP_BEGIN_C_DECLARATIONS
75af5a
d23446 /* Return values from eskType */
94e50e #define PGP_ESKTYPE_PASSPHRASE 0
1e6776 #define PGP_ESKTYPE_PUBKEY 1
b3af5a
a5adb8 #include "pgpOpaqueStructs.h"
60af5a
5c920d /* Some access functions. */
e21f85 int ·pgpEskType (PGPESK const *esk);
3aa08d int ·pgpEskPKAlg (PGPESK const *esk);
f4af5a
f8af5a
4836a4 /* caller must free the key ID */
df8736 PGPError¤   pgpGetEskKeyID( PGPESK const *esk, PGPKeyID *outRef);
38ae30 ¤   ¤   ¤   ¤   ¤
3f2cda /* How big might the output key possibly be? */
428339 size_t ·pgpEskMaxKeySize (PGPESK const *esk);
3238e5 /*
012a87 ·* The "key" is a passphrase. ·Returns the length of the key, which
b3d75a ·* is <algorithm identifier><key bits>
78495d ·*/
67900d int ·pgpEskConvDecrypt (PGPESK const *esk,
3b5e3a ¤   PGPEnv const *env, char const *pass, size_t plen, PGPByte *buf);
87af5a
39c0dc /* Do public-key decryption */
1d84b0 int ·pgpEskPKdecrypt (PGPESK const *esk,
f3076f ¤   PGPEnv const *env, PGPSecKey *sec, PGPByte *buf);
46af5a
41f27b PGPESK ·*pgpEskNext (PGPESK const *esklist);
26af5a
3c7961 int ·pgpEskAdd ( PGPContextRef¤ cdkContext,
3c7cb5 ¤   ¤   PGPESK **esklist, int type, PGPByte const *buf,
01bb18 ¤   ¤   size_t len);
ecc111 void ·pgpEskFreeList (PGPESK *esklist);
a4af5a
3c1254 PGP_END_C_DECLARATIONS
fcaf5a
c6c0d2 #endif /* Included_pgpESK_h */
--da74 000b6bd1b7e4010020e Page 1 of pgpElGKey.c
bc38e5 /*
716fae ·* pgpElGKey.c
c4d728 ·* El Gamal encryption
58775e ·*
a8e612 ·* $Id: pgpElGKey.c,v 1.48.2.1 1998/09/24 18:39:27 hal Exp $
14495d ·*/
dfaf5a
2ce2ff #include "pgpConfig.h"
7c324c #include <string.h>
6f7cab #include <stddef.h>
58af5a
7ea146 #include "pgpDebug.h"
2c6f19 #include "pgpElGKey.h"
12007f #include "pgpKeyMisc.h"
0a39fc #include "bn.h"
f212ca #include "bnprime.h"
6c1e2d #include "pgpCFBPriv.h"
1d0e2f #include "pgpSymmetricCipherPriv.h"
675417 #include "pgpHashPriv.h"
60c223 #include "pgpFixedKey.h"
4447e2 #include "bngermain.h"
4e9f72 #include "pgpHash.h"
410d08 #include "pgpMem.h"
d62f8d #include "pgpErrors.h"
a812ca #include "bnprime.h"
d9cdc2 #include "pgpPubKey.h"
472c96 #include "pgpRandomX9_17.h"
c65579 #include "pgpStr2Key.h"
d9c26c #include "pgpContext.h"
6c0d6d #include "pgpEnv.h"
a5af5a
ef0596 #ifndef NULL
51699b #define NULL 0
307454 #endif
3aaf5a
3f2b51 #define ASSERTELG(alg) pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_ElGamal)
a4af5a
ff7970 typedef struct ELGpub
cbbb36 {
235c6f ¤   BigNum p;¤  ¤   /* Public prime */
07a84e ¤   BigNum g;¤  ¤   /* Public generator */
9c7e6c ¤   BigNum y;¤  ¤   /* Public key, g**x mod p */
fddb7f } ELGpub;
f0af5a
24c0f0 typedef struct ELGsec
1cbb36 {
4dd34b ¤   BigNum p;¤  ¤   /* Copy of public parameters */
137f38 ¤   BigNum g;
91eab6 ¤   BigNum y;
983dbf ¤   BigNum x;¤  ¤   /* Secret key, discrete log of y */
cc5fce } ELGsec;
89af5a
579148 /* A PGPSecKey's priv points to this, an ELGsec plus the encrypted form... */
88a225 /* This struct is always allocated using PGPNewSecureData */
1d8638 typedef struct ELGsecPlus
06bb36 {
8c8a97 ¤   PGPContextRef¤  context;
f667c5 ¤
86b5e5 ¤   ELGsec s;
76775a ¤   PGPByte *cryptkey;
312d33 ¤   size_t ckalloc, cklen;
8db3fc ¤   int locked;
76cafe } ELGsecPlus;
5baf5a
71bfda /** Public key functions **/
9eaf5a
242978 static void
ade57f elgPubDestroy(PGPPubKey *pubkey)
abbb36 {
b56a8b ¤   ELGpub *pub = (ELGpub *)pubkey->priv;
dba1df ¤   PGPContextRef¤  context¤= pubkey->context;
b6af5a
--e3dd 0005de18e464010020e Page 2 of pgpElGKey.c
2080bc ¤   ASSERTELG(pubkey->pkAlg);
1c67c5 ¤
187511 ¤   bnEnd(&pub->p);
a6e191 ¤   bnEnd(&pub->g);
bd8c72 ¤   bnEnd(&pub->y);
2d0e47 ¤   pgpClearMemory( pub, ·sizeof(pub));
dcfa7b ¤   pgpContextMemFree( context, pub);
e15d33 ¤   pgpClearMemory( pubkey, ·sizeof(pubkey));
3e2ba6 ¤   pgpContextMemFree( context, pubkey);
b6efe6 }
21af5a
6838e5 /*
8c5400 ·* Return the largest possible PGPESK size for a given key.
823d95 ·* Must hold two numbers up to p in size.
6d495d ·*/
be5d09 static size_t
c39f04 elgPubMaxesk(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
acbb36 {
6d6de7 ¤   ELGpub const *pub = (ELGpub *)pubkey->priv;
15af5a
c880bc ¤   ASSERTELG(pubkey->pkAlg);
d19850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
f9a1c0 ¤   ¤   return 2*( 2 + bnBytes(&pub->p) );
6b61bb ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1)
73e8c0 ¤   ¤   return 2*( bnBytes(&pub->p) );
44af5a
894aac ¤   pgpAssert(0);
323e6b ¤   return 0;
13efe6 }
31af5a
4d38e5 /*
d3f5ac ·* Return the size of the buffer needed, worst-case, for the decrypted
6f6727 ·* output. ·A trivially padded key (random padding length = 0)
8a6493 ·* can just be 0 2 0 <key>.
1c495d ·*/
325d09 static size_t
760b95 elgPubMaxdecrypted(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
42bb36 {
1a6de7 ¤   ELGpub const *pub = (ELGpub *)pubkey->priv;
b5e002 ¤   size_t size;
93af5a
d280bc ¤   ASSERTELG(pubkey->pkAlg);
1e476e ¤   (void) format;
dbaf5a
39701d ¤   size = bnBytes(&pub->p);
b2de44 ¤   return size < 3 ? 0 : size-3;
dcefe6 }
28af5a
6eaf5a
5a5d09 static size_t
53532c elgPubMaxsig(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
5fbb36 {
2cf2e1 ¤   (void)pubkey;
f91c0d ¤   (void)format;
ac0b93 ¤   return kPGPError_PublicKeyUnimplemented;
f8efe6 }
d6af5a
c6af5a
cd38e5 /*
4a1034 ·* Given a buffer of at least "maxesk" bytes, make an PGPESK
f44d6c ·* into it and return the size of the PGPESK, or <0.
ad775e ·*
ecef01 ·* ElGamal encryption is a simple variant on non-interactove
58aaae ·* Diffie-Hellman. ·The recipient publishes g, p, and y = g**x mod p.
af1fe0 ·* the sender picks a random xx, computes yy = g**xx mod p, and
1b0f06 ·* the shared secret z = y**xx mod p = yy**x mod p = g**(x*xx) mod p, then
389bef ·* then sends z*m, where m is the message. ·(Padded in the usual
73f991 ·* PKCS manner.)
1a495d ·*/
11beb7 static int
225f2a elgEncrypt(PGPPubKey const *pubkey, PGPByte const *key,
5de590 ···········size_t keylen, PGPByte *esk, size_t *esklen,
--973c 000b8d0720e4010020e Page 3 of pgpElGKey.c
3c6387 ···········PGPRandomContext const *rc, PGPPublicKeyMessageFormat format)
30bb36 {
65a247 #if PGP_ENCRYPT_DISABLE /* [ */
8faf5a
c8f2e1 ¤   (void)pubkey;
b19b3e ¤   (void)key;
1cede5 ¤   (void)keylen;
114290 ¤   (void)esk;
627a0a ¤   (void)esklen;
eb76a2 ¤   (void)rc;
8b1c0d ¤   (void)format;
27e63f ¤   return kPGPError_FeatureNotAvailable;
ddaf5a
6da6dd #else /* PGP_ENCRYPT_DISABLE */ ·/* ] ·[ */
93af5a
f76de7 ¤   ELGpub const *pub = (ELGpub *)pubkey->priv;
8142b1 ¤   BigNum xx;¤ ¤   /* Random exponent */
21a4e8 ¤   BigNum yy;¤ ¤   /* g**xx mod p */
35bdae ¤   BigNum z;¤  ¤   /* y**xx mod p */
d30ed5 ¤   unsigned t;
86c541 ¤   unsigned xxbits, pbytes;
d64ba4 ¤   int i;
692955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
7c67c5 ¤
dd4578 ¤   mgr¤= PGPGetContextMemoryMgr( pubkey->context );
8aaf5a
150fe9 ¤   /* We don't need this argument, although other algorithms may... */
091c0d ¤   (void)format;
9367c5 ¤
55d8af ¤   /*
cc6626 ¤   ·* Of these values, only xx is inherently sensitive, but others may
3159cb ¤   ·* hold some intermediate results we would prefer not to have leaked.
3e22b7 ¤   ·* So mark all as sensitive.
fea4e3 ¤   ·*/
ad339b ¤   bnBegin(&xx, mgr, TRUE );
6dad84 ¤   bnBegin(&yy, mgr, TRUE );
10ff6a ¤   bnBegin(&z, mgr, TRUE );
eaaf5a
9680bc ¤   ASSERTELG(pubkey->pkAlg);
90a4dc ¤   t = bnBits(&pub->p);
ff3c57 ¤   if (t > 0xffff)
9650d0 ¤   ¤   return kPGPError_PublicKeyTooLarge;
49d188 ¤   pbytes = (t + 7) / 8;
220f53 ¤   if (keylen > pbytes)
8fe75b ¤   ¤   return kPGPError_PublicKeyTooSmall; /* data too big for pubkey */
38af5a
bb7905 ¤   if( format == kPGPPublicKeyMessageFormat_PGP ) {
73d2d6 ¤   ¤   /* Add checksum to key, place temporarily in esk buffer */
380550 ¤   ¤   t = 0;
a4544f ¤   ¤   esk[0] = key[0];
9f5ccb ¤   ¤   for (i = 1; i < (int)keylen; i++)
7d4738 ¤   ¤   ¤   t += esk[i] = key[i];
d007b1 ¤   ¤   esk[keylen] = (PGPByte)(t >> 8 & 255);
dcaada ¤   ¤   esk[keylen+1] = (PGPByte)(t & 255);
21cc35 ¤   ¤   keylen += 2;
c9b142 ¤   ¤   key = esk;
d39371 ¤   }
05af5a
0e4443 ¤   /* Choose the random xx value to be used for this encryption */
a98547 ¤   xxbits = pgpDiscreteLogExponentBits(bnBits(&pub->p))*3/2;
6af44e ¤   if (pgpBnGenRand(&xx, rc, xxbits, 0, 0, xxbits) < 0)
c45b40 ¤   ¤   goto nomem;
b7af5a
9fe2b4 ¤   /* Do the two exponentiations necessary to compute yy and z */
b91142 ¤   if (bnExpMod(&yy, &pub->g, &xx, &pub->p) < 0 ||
3c4f1f ¤   ····bnExpMod(&z, ·&pub->y, &xx, &pub->p) < 0)
065b40 ¤   ¤   goto nomem;
e7af5a
fe30cc ¤   /* Re-use xx to hold the PKCS-padded conventional key */
f470b7 ¤   if (pgpPKCSPack(&xx, key, keylen, PKCS_PAD_ENCRYPTED, pbytes, rc)<0)
d25b40 ¤   ¤   goto nomem;
b8aa1c ¤   pgpAssert (bnCmp(&xx, &pub->p) < 0);
--809d 000958fc11e4010020e Page 4 of pgpElGKey.c
2a67c5 ¤
94248a ¤   /* Compute xx*z mod p, the encrypted session key we will transmit */
9d8ffa ¤   if (bnMul(&z, &z, &xx) < 0 ||
1a54e2 ¤   ····bnMod(&z, &z, &pub->p) < 0)
875b40 ¤   ¤   goto nomem;
3aaf5a
6bae93 ¤   /* Pack the two values into the esk, first yy and then k+z */
3705d3 ¤   t ·= pgpBnPutFormatted(&yy, esk, pbytes, format);
a16d45 ¤   t += pgpBnPutFormatted(&z, esk+t, pbytes, format);
5f2fa6 ¤   if (esklen)
566abf ¤   ¤   *esklen = (size_t)t;
5f67c5 ¤
82ff6c ¤   i = 0;
1dc48e ¤   goto done;
d7ac52 nomem:
7d30c4 ¤   i = kPGPError_OutOfMemory;
4ab38c done:
c13e09 ¤   bnEnd(&z);
236528 ¤   bnEnd(&yy);
5f72d7 ¤   bnEnd(&xx);
622196 ¤   return i;
67af5a
f67bb3 #endif /* PGP_ENCRYPT_DISABLE */ /* ] */
49efe6 }
35af5a
feaf5a
67af5a
6738e5 /*
f7503a ·* Return 1 if (sig,siglen) is a valid MPI which signs
b5d58c ·* (hash, hashlen).
aecd3e ·* Not implementing ElGamal signatures, using DSS.
08495d ·*/
95beb7 static int
e56d9e elgVerify(PGPPubKey const *pubkey, PGPByte const *sig,
b5414d ¤   size_t siglen, PGPHashVTBL const *h, PGPByte const *hash,
846fc3 ¤   PGPPublicKeyMessageFormat format)
32bb36 {
80f2e1 ¤   (void)pubkey;
1b77e4 ¤   (void)sig;
9e51a9 ¤   (void)siglen;
58c6fd ¤   (void)h;
ff4902 ¤   (void)hash;
641c0d ¤   (void)format;
7c0b93 ¤   return kPGPError_PublicKeyUnimplemented;
f4efe6 }
19af5a
c138e5 /*
635ebc ·* Turn a PGPPubKey into the algorithm-specific parts of a public key.
5d23d0 ·* A public key's ELG-specific part is:
88775e ·*
0a682a ·* ·0 ·····2+i ·MPI for prime
cf1735 ·* 2+i ····2+t ·MPI for generator
f82027 ·* 4+i+t ··2+u¤ MPI for public key
ae884c ·* 6+i+t+u
ad495d ·*/
765d09 static size_t
e51a8a elgPubBufferLength(PGPPubKey const *pubkey)
75bb36 {
f26de7 ¤   ELGpub const *pub = (ELGpub *)pubkey->priv;
6aaf5a
baf9ee ¤   return 6 + bnBytes(&pub->p) + bnBytes(&pub->g) +
4d4a92 ¤   ¤   bnBytes(&pub->y);
c0efe6 }
2baf5a
b22978 static void
345143 elgPubToBuffer(PGPPubKey const *pubkey, PGPByte *buf)
32bb36 {
c66de7 ¤   ELGpub const *pub = (ELGpub *)pubkey->priv;
743876 ¤   unsigned off;
fcaf5a
d16cdb ¤   off = 0;
956b62 ¤   off += pgpBnPutPlain(&pub->p, buf+off);
--895f 000ba54c2bc4010020e Page 5 of pgpElGKey.c
c729f1 ¤   off += pgpBnPutPlain(&pub->g, buf+off);
3843a7 ¤   off += pgpBnPutPlain(&pub->y, buf+off);
09efe6 }
b3af5a
65af5a
b4bbab /* A little helper function that's used twice */
282978 static void
a93580 elgFillPubkey(PGPPubKey *pubkey, ELGpub *pub)
5abb36 {
081756 ¤   pubkey->next¤   ·= NULL;
aefc95 ¤   pubkey->pkAlg¤  ·= kPGPPublicKeyAlgorithm_ElGamal;
c967ea ¤   pubkey->priv¤   ·= pub;
5e4141 ¤   pubkey->destroy ·= elgPubDestroy;
e18b81 ¤   pubkey->maxesk ··= elgPubMaxesk;
cee0d5 ¤   pubkey->maxdecrypted ··= elgPubMaxdecrypted;
5b8895 ¤   pubkey->maxsig ··= elgPubMaxsig;
666f8b ¤   pubkey->encrypt ·= elgEncrypt;
1d03aa ¤   pubkey->verify ··= elgVerify;
bbe354 ¤   pubkey->bufferLength ·= elgPubBufferLength;
8b0120 ¤   pubkey->toBuffer = elgPubToBuffer;
edefe6 }
4caf5a
37af5a
5838e5 /*
375a5c ·* Turn the algorithm-specific parts of a public key into a PGPPubKey
22f92e ·* structure. ·A public key's ELG-specific part is:
1f775e ·*
2f682a ·* ·0 ·····2+i ·MPI for prime
411735 ·* 2+i ····2+t ·MPI for generator
962027 ·* 4+i+t ··2+u¤ MPI for public key
f4884c ·* 6+i+t+u
0a495d ·*/
1040b4 PGPPubKey *
a18c86 elgPubFromBuf(
ad520e ¤   PGPContextRef¤  context,
397347 ¤   PGPByte const *buf, size_t size, PGPError *error)
98bb36 {
c336c1 ¤   PGPPubKey *pubkey;
75384d ¤   ELGpub *pub;
728672 ¤   unsigned i, t, u;
9484f6 ¤   int v;
fc4c08 ¤   PGPError¤   err¤= kPGPError_OutOfMemory;
6ef9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
cf67c5 ¤
25bac4 ¤   bnInit();
9baf5a
fee0a1 ¤   v = pgpBnParse(buf, size, 3, &i, &t, &u);
8e13d3 ¤   if (v < 0) {
0235e4 ¤   ¤   *error = (PGPError)v;
b47ed2 ¤   ¤   return NULL;
df9371 ¤   }
7b851b ¤   if ((buf[t-1] & 1) == 0) {¤ /* Too small or even prime p */
128997 ¤   ¤   *error = kPGPError_MalformedKeyComponent;
b57ed2 ¤   ¤   return NULL;
f69371 ¤   }
b2af5a
e86ffd ¤   pub = (ELGpub *)pgpContextMemAlloc( context,
ea63dc ¤   ¤   ¤   sizeof(*pub), kPGPMemoryMgrFlags_Clear);
e467ab ¤   if (pub) {
57545a ¤   ¤   pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
3e7dcd ¤   ¤   ¤   sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
0ad646 ¤   ¤   if (pubkey) {
d6aa14 ¤   ¤   ¤   pubkey->context¤= context;
3fcf5c ¤   ¤   ¤   bnBegin(&pub->p, mgr, FALSE );
7cb790 ¤   ¤   ¤   bnBegin(&pub->g, mgr, FALSE );
525f2b ¤   ¤   ¤   bnBegin(&pub->y, mgr, FALSE );
74cd8c ¤   ¤   ¤   if (bnInsertBigBytes(&pub->p, buf+i+2, 0, t-i-2) >= 0
d41885 ¤   ¤   ¤   ····&& bnInsertBigBytes(&pub->g, buf+t+2, 0,
2bd73e ¤   ¤   ¤   ¤   ¤   ¤   u-t-2) >= 0
4cd241 ¤   ¤   ¤   ····&& bnInsertBigBytes(&pub->y, buf+u+2, 0,
19254d ¤   ¤   ¤   ¤   ¤   ¤   v-u-2) >= 0)
baf776 ¤   ¤   ¤   {
--939a 0004cf5f15f4010020e Page 6 of pgpElGKey.c
caec89 ¤   ¤   ¤   ¤   elgFillPubkey(pubkey, pub);
85af5a
7f7403 ¤   ¤   ¤   ¤   *error = kPGPError_NoErr;
fabb8a ¤   ¤   ¤   ¤   return pubkey;
1aa3a6 ¤   ¤   ¤   }
46bb8c ¤   ¤   ¤   else
67f776 ¤   ¤   ¤   {
99959d ¤   ¤   ¤   ¤   err¤= kPGPError_UnknownError;
4da3a6 ¤   ¤   ¤   }
3887c7 ¤   ¤   ¤
b89865 ¤   ¤   ¤   /* Failed = clean up and return NULL */
95f980 ¤   ¤   ¤   bnEnd(&pub->p);
816d00 ¤   ¤   ¤   bnEnd(&pub->g);
ab00e3 ¤   ¤   ¤   bnEnd(&pub->y);
c77f83 ¤   ¤   ¤   pgpContextMemFree( context, pubkey);
c40fe4 ¤   ¤   }
30c695 ¤   ¤   pgpContextMemFree( context, pub);
609371 ¤   }
ed67c5 ¤
7cab59 ¤   *error = err;
d53f59 ¤   return NULL;
e8efe6 }
35af5a
0338e5 /*
70439a ·* Return the size of the public portion of a key buffer.
8a495d ·*/
df4d2f int
98f585 elgPubKeyPrefixSize(PGPByte const *buf, size_t size)
a5bb36 {
f93919 ¤   return pgpBnParse(buf, size, 3, NULL, NULL, NULL);
92efe6 }
c0af5a
cbaf5a
e8114d /** Secret key functions **/
4aaf5a
4e2978 static void
26dc86 elgSecDestroy(PGPSecKey *seckey)
febb36 {
65a8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
b97925 ¤   PGPContextRef¤  ¤   context;
eeaf5a
f04813 ¤   pgpAssertAddrValid( seckey, PGPSecKey );
f55b86 ¤   context¤= seckey->context;
dc67c5 ¤
658679 ¤   pgpAssert( pgpContextIsValid( context ) );
13af5a
7dc693 ¤   ASSERTELG(seckey->pkAlg);
483273 ¤   bnEnd(&sec->s.p);
76a6f3 ¤   bnEnd(&sec->s.g);
67cb10 ¤   bnEnd(&sec->s.y);
d5d7ab ¤   bnEnd(&sec->s.x);
f556f8 ¤   pgpClearMemory(sec->cryptkey, sec->ckalloc);
485bb1 ¤   pgpContextMemFree( context, sec->cryptkey);
f10d92 ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
521464 ¤   pgpClearMemory( seckey, ·sizeof(seckey));
35390c ¤   pgpContextMemFree( context, seckey);
daefe6 }
89af5a
2d38e5 /*
6f3521 ·* Generate a PGPPubKey from a PGPSecKey
38495d ·*/
cfc2ad static PGPPubKey *
9ce78a elgPubkey(
5ccbcb ¤   PGPSecKey const *seckey)
bfbb36 {
0f5a26 ¤   ELGsecPlus const *sec = (ELGsecPlus *)seckey->priv;
5236c1 ¤   PGPPubKey *pubkey;
09384d ¤   ELGpub *pub;
8f7925 ¤   PGPContextRef¤  ¤   context;
b32955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
3faf5a
4c4813 ¤   pgpAssertAddrValid( seckey, PGPSecKey );
--ce24 000092fd9ec4010020e Page 7 of pgpElGKey.c
7c5b86 ¤   context¤= seckey->context;
0efaf1 ¤   mgr¤= PGPGetContextMemoryMgr( context );
53af5a
fec693 ¤   ASSERTELG(seckey->pkAlg);
f96ffd ¤   pub = (ELGpub *)pgpContextMemAlloc( context,
5430c7 ¤   ¤   sizeof(*pub), kPGPMemoryMgrFlags_Clear);
5b67ab ¤   if (pub) {
80545a ¤   ¤   pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
057dcd ¤   ¤   ¤   sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
d5d646 ¤   ¤   if (pubkey) {
74aa14 ¤   ¤   ¤   pubkey->context¤= context;
b587c7 ¤   ¤   ¤
2dcf5c ¤   ¤   ¤   bnBegin(&pub->p, mgr, FALSE );
8ab790 ¤   ¤   ¤   bnBegin(&pub->g, mgr, FALSE );
805f2b ¤   ¤   ¤   bnBegin(&pub->y, mgr, FALSE );
72ced5 ¤   ¤   ¤   if (bnCopy(&pub->p, &sec->s.p) >= 0
b78b81 ¤   ¤   ¤   ····&& bnCopy(&pub->g, &sec->s.g) >= 0
5193f7 ¤   ¤   ¤   ····&& bnCopy(&pub->y, &sec->s.y) >= 0)
b3f776 ¤   ¤   ¤   {
30ec89 ¤   ¤   ¤   ¤   elgFillPubkey(pubkey, pub);
3a7c58 ¤   ¤   ¤   ¤   pubkey->pkAlg = seckey->pkAlg;
c3d49b ¤   ¤   ¤   ¤   memcpy(pubkey->keyID, seckey->keyID,
bb4c85 ¤   ¤   ¤   ¤   ·······sizeof(pubkey->keyID));
e3bb8a ¤   ¤   ¤   ¤   return pubkey;
63a3a6 ¤   ¤   ¤   }
0f9865 ¤   ¤   ¤   /* Failed = clean up and return NULL */
4cf980 ¤   ¤   ¤   bnEnd(&pub->p);
456d00 ¤   ¤   ¤   bnEnd(&pub->g);
ae00e3 ¤   ¤   ¤   bnEnd(&pub->y);
0e7f83 ¤   ¤   ¤   pgpContextMemFree( context, pubkey);
3b0fe4 ¤   ¤   }
fec695 ¤   ¤   pgpContextMemFree( context, pub);
899371 ¤   }
4a3f59 ¤   return NULL;
4defe6 }
e3af5a
4a38e5 /*
4bd39c ·* Yes, there *is* a reason that this is a function and no a variable.
28a3bd ·* On a hardware device with an automatic timeout,
0d6854 ·* it actually might need to do some work to find out.
5c495d ·*/
3cbeb7 static int
ace267 elgIslocked(PGPSecKey const *seckey)
48bb36 {
ca5a26 ¤   ELGsecPlus const *sec = (ELGsecPlus *)seckey->priv;
ffaf5a
05c693 ¤   ASSERTELG(seckey->pkAlg);
24096c ¤   return sec->locked;
86efe6 }
e5af5a
4caf5a
6038e5 /*
9ac3dc ·* Return the algorithm and (symmetric) key size used for locking/unlocking
28f175 ·* the secret key.
f4495d ·*/
e5f1ae static PGPError
9bb346 elgLockingAlgorithm(
03b573 ¤   PGPSecKey const *seckey,
ff6f43 ¤   PGPCipherAlgorithm *pAlg,
32b91d ¤   PGPSize *pAlgKeySize
f027e6 ¤   )
97bb36 {
e5a8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
e208c6 ¤   PGPCipherVTBL const *cipher;
24afba ¤   PGPByte alg;
9f4ba4 ¤   int i;
e8af5a
13c693 ¤   ASSERTELG(seckey->pkAlg);
d9af5a
700ec4 ¤   if( IsntNull( pAlg ) )
077a59 ¤   ¤   *pAlg = (PGPCipherAlgorithm) 0;
097929 ¤   if( IsntNull( pAlgKeySize ) )
--fc43 0002a54c0bf4010020e Page 8 of pgpElGKey.c
07301e ¤   ¤   *pAlgKeySize = (PGPSize) 0;
84af5a
e984c6 ¤   /* Check packet for basic consistency */
0e42e6 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 3, NULL, NULL, NULL);
6f4fd6 ¤   if (i < 0)
112051 ¤   ¤   return (PGPError)i;
2aaf5a
9db604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
16e893 ¤   alg = sec->cryptkey[i] & 255;
f6af5a
9f9fab ¤   /* New style has 255 then algorithm value */
20130c ¤   if (alg == 255)
abacc2 ¤   ¤   alg = sec->cryptkey[i+1] & 255;
b9af5a
b0c7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
d9b637 ¤   if (!cipher)
f9fb6d ¤   ¤   return kPGPError_BadCipherNumber;
1caf5a
130d42 ¤   /* Success */
660ec4 ¤   if( IsntNull( pAlg ) )
642341 ¤   ¤   *pAlg = (PGPCipherAlgorithm) alg;
997929 ¤   if( IsntNull( pAlgKeySize ) )
94f60c ¤   ¤   *pAlgKeySize = cipher->keysize;
23af5a
95151e ¤   return kPGPError_NoErr;
abefe6 }
25af5a
8faf5a
5038e5 /*
f5d2ee ·* Return the StringToKey type for unlocking the given key. ·We use
ef4eb5 ·* kPGPStringToKey_Literal to flag a secret split unlocking buffer.
a19d12 ·* Returns kPGPStringToKey_Simple if key has no passphrase.
36495d ·*/
cef1ae static PGPError
49a06d elgS2KType(
1bb573 ¤   PGPSecKey const *seckey,
cc9e5a ¤   PGPStringToKeyType *s2kType
2227e6 ¤   )
53bb36 {
1ba8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
05afba ¤   PGPByte alg;
024ba4 ¤   int i;
a6af5a
25c693 ¤   ASSERTELG(seckey->pkAlg);
deaf5a
e655b6 ¤   /* note that 0 is a valid type, but use it as default anyway */
4fdab9 ¤   if( IsntNull( s2kType ) )
07bc38 ¤   ¤   *s2kType = (PGPStringToKeyType) 0;
36af5a
cd84c6 ¤   /* Check packet for basic consistency */
7342e6 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 3, NULL, NULL, NULL);
444fd6 ¤   if (i < 0)
262051 ¤   ¤   return (PGPError)i;
49af5a
d7b604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
a0e893 ¤   alg = sec->cryptkey[i] & 255;
f1af5a
e640cd ¤   if (alg == 255) {
e23446 ¤   ¤   /* New style has 255 then algorithm value then S2K */
dfd66f ¤   ¤   *s2kType = (PGPStringToKeyType) sec->cryptkey[i+2];
b5f037 ¤   } else {
254191 ¤   ¤   /* Unencrypted or old-style simple encryption */
00c21f ¤   ¤   *s2kType = kPGPStringToKey_Simple;
e99371 ¤   }
43af5a
e2151e ¤   return kPGPError_NoErr;
8fefe6 }
a9af5a
b038e5 /*
0071a1 ·* Convert a passphrase into a s2k literal buffer for the key.
525514 ·* Returns error code. ·Output buffer will be size of the *pAlgKeySize
2a2df7 ·* parameter from pgpSecKeyLockingalgorithm.
--9086 000823f501e4010020e Page 9 of pgpElGKey.c
47495d ·*/
41f1ae static PGPError
b2c1ea elgConvertPassphrase(PGPSecKey *seckey, PGPEnv const *env,
f69820 ¤   ··char const *phrase, PGPSize plen, PGPByte *outbuf)
81bb36 {
46a8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
2dbfb0 ¤   PGPStringToKey *s2k;
97afba ¤   PGPByte alg;
420306 ¤   PGPBoolean hasS2K;
7108c6 ¤   PGPCipherVTBL const *cipher;
e64ba4 ¤   int i;
cbaf5a
e7c693 ¤   ASSERTELG(seckey->pkAlg);
916bb2 ¤   pgpAssert (IsntNull( outbuf ) );
8daf5a
7d84c6 ¤   /* Check packet for basic consistency */
796a3d ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 3, NULL, NULL, NULL, NULL);
c64fd6 ¤   if (i < 0)
592051 ¤   ¤   return (PGPError)i;
14af5a
d7b604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
a28aa2 ¤   alg = sec->cryptkey[i++] & 255;
aeaf5a
4deaa8 ¤   hasS2K = (alg == 255);
56af5a
b79fab ¤   /* New style has 255 then algorithm value */
5f727d ¤   if (hasS2K)
fe4ff7 ¤   ¤   alg = sec->cryptkey[i++] & 255;
68af5a
b9cb98 ¤   /* Now we are looking at the s2k object if there is one. */
fd0d7e ¤   if (alg == 0) {
19cc33 ¤   ¤   /* Key is not locked */
ec62b5 ¤   ¤   return kPGPError_BadParams;
4d9371 ¤   }
1cc7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
d9b04e ¤   if( IsNull( cipher ) )
c8fb6d ¤   ¤   return kPGPError_BadCipherNumber;
ddaf5a
efdb5e ¤   if (hasS2K) {
b50162 ¤   ¤   pgpS2Kdecode(&s2k, env, sec->cryptkey+i, sec->cklen-i);
8ef037 ¤   } else {
d2176e ¤   ¤   s2k = pgpS2Ksimple(env, pgpHashByNumber(kPGPHashAlgorithm_MD5));
b49371 ¤   }
7b6f18 ¤   if (IsNull( s2k ) )
9d4030 ¤   ¤   return kPGPError_OutOfMemory;
d4a401 ¤   pgpStringToKey(s2k, phrase, plen, outbuf, cipher->keysize);
ab130e ¤   pgpS2Kdestroy(s2k);
f0af5a
d9151e ¤   return kPGPError_NoErr;
ceefe6 }
dbaf5a
21af5a
f338e5 /*
212d14 ·* Try to decrypt the secret key wih the given passphrase. ·Returns >0
0c93d2 ·* if it was the correct passphrase. =0 if it was not, and <0 on error.
36fa8a ·* Does not alter the key even if it's the wrong passphrase and already
639458 ·* unlocked. ·A NULL passphrae will work if the key is unencrypted.
cc9ec0 ·*·
1a9e22 ·* A (secret) key's ELG-specific part is:
2e775e ·*
65cc75 ·* ·0 ···············2+u ·MPI for prime
a7cb7c ·* ·2+u ·············2+v ·MPI for generator
6b661a ·* ·4+u+v¤  ·····2+w ·MPI for public key
5baa0a ·* ·6+u+v+w ·········1 ···Encryption algorithm (0 for none, 1 for IDEA)
b1331b ·* ·7+u+v+w ·········t ···Encryption IV: 0 or 8 bytes
851656 ·* ·7+t+u+v+w ·······2+x ·MPI for x (discrete log of public key)
8f43ca ·* ·9+t+u+v+w+x ·····2 ···Checksum
442320 ·* 11+t+u+v+w+x
ec775e ·*
5eee8f ·* Actually, that's the old-style, if pgpS2KoldVers is true.
c85b0b ·* If it's false, the algorithm is 255, and is followed by the
828f61 ·* algorithm, then the (varaible-length, self-delimiting)
--0621 000287452ad4010020e Page 10 of pgpElGKey.c
be217f ·* string-to-key descriptor.
71495d ·*/
e5af5a
06beb7 static int
a0cfeb elgUnlock(PGPSecKey *seckey, PGPEnv const *env,
357e27 ¤   ··char const *phrase, size_t plen, PGPBoolean hashedPhrase)
d9bb36 {
6fa8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
bdb06a ¤   BigNum x;
a81f93 ¤   PGPCFBContext *cfb = NULL;
14bb6d ¤   unsigned v;
afdfbc ¤   unsigned alg;
d81b07 ¤   unsigned checksum;
294ba4 ¤   int i;
5a2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
1b1e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
02af5a
dec693 ¤   ASSERTELG(seckey->pkAlg);
d8bac4 ¤   bnInit();
dcaf5a
fa84c6 ¤   /* Check packet for basic consistency */
7aa5cd ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 3, &v, NULL, NULL, NULL);
914fd6 ¤   if (i < 0)
02a423 ¤   ¤   return i;
dbaf5a
8520ee ¤   /* OK, read the public data */
c22c91 ¤   i = pgpBnGetPlain(&sec->s.p, sec->cryptkey+v, sec->cklen-v);
4407eb ¤   if (i <= 0)
4984fc ¤   ¤   goto fail;
fa24fb ¤   v += i;
e6dcae ¤   i = pgpBnGetPlain(&sec->s.g, sec->cryptkey+v, sec->cklen-v);
9c07eb ¤   if (i <= 0)
1884fc ¤   ¤   goto fail;
9a24fb ¤   v += i;
404860 ¤   i = pgpBnGetPlain(&sec->s.y, sec->cryptkey+v, sec->cklen-v);
1a07eb ¤   if (i <= 0)
bb84fc ¤   ¤   goto fail;
f324fb ¤   v += i;
e3af5a
4eb604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
54547e ¤   alg ·= sec->cryptkey[v];
a8af5a
fe3563 ¤   /* If the phrase is empty, set it to NULL */
8ec08b ¤   if (plen == 0)
9a6f28 ¤   ¤   phrase = NULL;
79d8af ¤   /*
19b08f ¤   ·* We need a pass if it is encrypted, and we cannot have a
407664 ¤   ·* password if it is NOT encrypted. ·I.e., this is a logical
8a887b ¤   ·* xor (^^)
3ca4e3 ¤   ·*/
71c441 ¤   if (!phrase != !alg)
d6bbde ¤   ¤   return 0;
03af5a
a51ca2 ¤   i = pgpCipherSetup(sec->cryptkey + v, sec->cklen - v, phrase, plen,
691001 ¤   ¤   ¤   ¤   ¤   ···hashedPhrase, env, &cfb);
324fd6 ¤   if (i < 0)
95262d ¤   ¤   goto done;
d724fb ¤   v += i;
b9af5a
61a2f0 ¤   checksum = 0;
70eb5b ¤   bnBegin(&x, mgr, TRUE );
b9814c ¤   i = pgpBnGetNew(&x, sec->cryptkey + v, sec->cklen - v, cfb, &checksum);
8f07eb ¤   if (i <= 0)
a4a8d5 ¤   ¤   goto badpass;
ec24fb ¤   v += i;
320d1f ¤   if (bnCmp(&x, &sec->s.p) >= 0)
eba90d ¤   ¤   goto badpass;¤  /* Wrong passphrase: x must be < p */
98af5a
ca4e68 ¤   /* Check that we ended in the right place */
3e8c8c ¤   if (sec->cklen - v != 2) {
39e85e ¤   ¤   i = kPGPError_KEY_LONG;
28262d ¤   ¤   goto done;
--5731 0004efd84d24010020e Page 11 of pgpElGKey.c
a19371 ¤   }
98afa6 ¤   checksum &= 0xffff;
f4ded2 ¤   if (checksum != pgpChecksumGetNew(sec->cryptkey + v, cfb))
30a8d5 ¤   ¤   goto badpass;
7faf5a
4cd8af ¤   /*
967b44 ¤   ·* Note that the "nomem" case calls bnEnd()
3e5307 ¤   ·* more than once, but this is guaranteed harmless.
cd9c20 ·¤  ·*/
1d2599 ¤   if (bnCopy(&sec->s.x, &x) < 0)
705b40 ¤   ¤   goto nomem;
7d077f ¤   bnEnd(&x);
7caf5a
332f6d ¤   i = 1;¤ /* Decrypted! */
5c0162 ¤   sec->locked = 0;
74afda ¤   if (cfb)
4fd6b0 ¤   ¤   PGPFreeCFBContext(cfb);
7340ed ¤   return 1;¤  /* Decrypted */
ceaf5a
eeac52 nomem:
3a30c4 ¤   i = kPGPError_OutOfMemory;
ffc48e ¤   goto done;
62115d fail:
b05451 ¤   if (!i)
89a3b2 ¤   ¤   i = kPGPError_KeyPacketTruncated;
7dc48e ¤   goto done;
f988a7 badpass:
5af1b7 ¤   i = 0;¤ /* Incorrect passphrase */
59c48e ¤   goto done;
85b38c done:
52077f ¤   bnEnd(&x);
d9afda ¤   if (cfb)
f7d6b0 ¤   ¤   PGPFreeCFBContext(cfb);
d22196 ¤   return i;
0defe6 }
81af5a
cb38e5 /*
a63dfc ·* Relock the key.
08495d ·*/
c22978 static void
926581 elgLock(PGPSecKey *seckey)
7fbb36 {
d9a8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
f7af5a
14c693 ¤   ASSERTELG(seckey->pkAlg);
185bbe ¤   sec->locked = 1;
0b9e4a ¤   /* bnEnd is documented as also doing a bnBegin */
48d7ab ¤   bnEnd(&sec->s.x);
cbefe6 }
17af5a
3e5d09 static size_t
b252e5 elgSecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format);
37af5a
deaf5a
83af5a
3538e5 /*
2c7d83 ·* Try to decrypt the given esk. ·If the key is locked, try the given
0b0169 ·* passphrase. ·It may or may not leave the key unlocked in such a case.
1d8bf9 ·* (Some hardware implementations may insist on a password per usage.)
d0495d ·*/
c3beb7 static int
c8b7e4 elgDecrypt(PGPSecKey *seckey, PGPEnv const *env,
d5695b ¤   ¤   ···PGPByte const *esk, size_t esklen,
8077cb ¤   ¤   ···PGPByte *key, size_t *keylen,
7540b7 ¤   ¤   ···char const *phrase, size_t plen,
18f9f5 ¤   ¤   ···PGPPublicKeyMessageFormat format)
84bb36 {
db0545 #if PGP_DECRYPT_DISABLE /* [ */
d5af5a
37c9d3 ¤   (void)seckey;
5f7054 ¤   (void)env;
4e4290 ¤   (void)esk;
--25b0 000e85dce844010020e Page 12 of pgpElGKey.c
c37a0a ¤   (void)esklen;
479b3e ¤   (void)key;
13ede5 ¤   (void)keylen;
52cf72 ¤   (void)phrase;
dc087c ¤   (void)plen;
c91c0d ¤   (void)format;
56e63f ¤   return kPGPError_FeatureNotAvailable;
89af5a
050d75 #else /* PGP_DECRYPT_DISABLE */ ·/* ] ·[ */
17af5a
ffa8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
9ae247 ¤   BigNum k, yy;
94927e ¤   int i, j;
ef470c ¤   unsigned t, pbytes;
a4f20c ¤   size_t len;
9f0ccf ¤   size_t off;
952955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
e51e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
8eaf5a
23c693 ¤   ASSERTELG(seckey->pkAlg);
1da092 ¤   if (sec->locked) {
3e9746 ¤   ¤   i = elgUnlock(seckey, env, phrase, plen, FALSE);
6d9098 ¤   ¤   if (i <= 0)
9011b7 ¤   ¤   ¤   return i ? i : kPGPError_KeyIsLocked;
3eef50 ¤   ¤   pgpAssert(!sec->locked);
f49371 ¤   }
aeaf5a
5ad0f2 ¤   bnBegin(&k, mgr, TRUE );
cfad84 ¤   bnBegin(&yy, mgr, TRUE );
5f3735 ¤   pbytes = (bnBits(&sec->s.p) + 7) / 8;
b2af5a
b24535 ¤   /* ESK holds two values. ·Get first, yy, from ESK. */
496cdb ¤   off = 0;
88518b ¤   i = pgpBnGetFormatted(&yy, esk+off, esklen-off, pbytes, format);
f907eb ¤   if (i <= 0)
5784fc ¤   ¤   goto fail;
940a81 ¤   /* Get 2nd value, k, from ESK */
da0f96 ¤   off += i;
144809 ¤   i = pgpBnGetFormatted(&k, esk+off, esklen-off, pbytes, format);
5607eb ¤   if (i <= 0)
4884fc ¤   ¤   goto fail;
280f96 ¤   off += i;
4b945a ¤   if (off != esklen) {
f3b289 ¤   ¤   i = kPGPError_BadSessionKeySize;
f2262d ¤   ¤   goto done;
559371 ¤   }
e067c5 ¤
3dd784 ¤   /* Calculate yy = yy**x mod p, which is what is multiplied by k */
02b0fc ¤   if (bnExpMod(&yy, &yy, &sec->s.x, &sec->s.p) < 0)
7c5b40 ¤   ¤   goto nomem;
61af5a
a25f9a ¤   /* Set k = k / (new)yy , revealing PKCS padded session key */
39faf8 ¤   if (bnInv(&yy, &yy, &sec->s.p) < 0 ||
59e8c5 ¤   ¤   bnMul(&k, &k, &yy) < 0 ||
f58999 ¤   ¤   bnMod(&k, &k, &sec->s.p) < 0) {
9521b4 ¤   ¤   ¤   goto nomem;
7e9371 ¤   }
dc6528 ¤   bnEnd(&yy);
0167c5 ¤
f58c18 ¤   /* k is now suitable for unpacking */
f83f16 ¤   len = elgSecMaxdecrypted(seckey, format);
9322a8 ¤   i = pgpPKCSUnpack (key, len, &k, PKCS_PAD_ENCRYPTED, pbytes);
95e113 ¤   bnEnd(&k);
004fd6 ¤   if (i < 0)
d4a423 ¤   ¤   return i;
43af5a
e50041 ¤   if (format == kPGPPublicKeyMessageFormat_PGP) {
411cc3 ¤   ¤   /* Check checksum */
2b0550 ¤   ¤   t = 0;
3919f9 ¤   ¤   for (j = 1; j < i-2; j++)
bf1e00 ¤   ¤   ¤   t += key[j];
e89f82 ¤   ¤   if (t != ((unsigned)key[i-2]<<8) + key[i-1])
--bb19 0008001cb584010020e Page 13 of pgpElGKey.c
9eb933 ¤   ¤   ¤   return kPGPError_CorruptData;
bf72e5 ¤   ¤   pgpClearMemory(key+i-2, 2);
10af5a
d22981 ¤   ¤   /* The actual key */
9a2f3a ¤   ¤   if (keylen)
807f6d ¤   ¤   ¤   *keylen = (size_t)i-2;
dbf037 ¤   } else {
9539d9 ¤   ¤   if( keylen)
07b2df ¤   ¤   ¤   *keylen = (size_t)i;
2e9371 ¤   }
7867c5 ¤
b43e6b ¤   return 0;
67af5a
ec115d fail:
ef5451 ¤   if (!i)
97b289 ¤   ¤   i = kPGPError_BadSessionKeySize;
dec48e ¤   goto done;
64ac52 nomem:
c130c4 ¤   i = kPGPError_OutOfMemory;
58c48e ¤   goto done;
42b38c done:
a86528 ¤   bnEnd(&yy);
e9e113 ¤   bnEnd(&k);
c02196 ¤   return i;
22af5a
292cfc #endif /* PGP_DECRYPT_DISABLE */ /* ] */
a4efe6 }
63af5a
eaaf5a
01af5a
c238e5 /*
69f5ac ·* Return the size of the buffer needed, worst-case, for the decrypted
ba6727 ·* output. ·A trivially padded key (random padding length = 0)
1c6493 ·* can just be 0 2 0 <key>.
5d495d ·*/
f05d09 static size_t
644050 elgSecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
66bb36 {
005a26 ¤   ELGsecPlus const *sec = (ELGsecPlus *)seckey->priv;
b8e002 ¤   size_t size;
76af5a
bec693 ¤   ASSERTELG(seckey->pkAlg);
33476e ¤   (void) format;
fbaf5a
edcc7e ¤   size = bnBytes(&sec->s.p);
7bde44 ¤   return size < 3 ? 0 : size-3;
caefe6 }
dcaf5a
3f5d09 static size_t
52c96d elgSecMaxesk(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
76bb36 {
d65a26 ¤   ELGsecPlus const *sec = (ELGsecPlus *)seckey->priv;
b5af5a
e7c693 ¤   ASSERTELG(seckey->pkAlg);
b69850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
662f85 ¤   ¤   return 2*( 2 + bnBytes(&sec->s.p) );
c761bb ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1)
61f040 ¤   ¤   return 2*( bnBytes(&sec->s.p) );
c0af5a
4b4aac ¤   pgpAssert(0);
493e6b ¤   return 0;
8aefe6 }
2baf5a
c45d09 static size_t
280545 elgSecMaxsig(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
54bb36 {
a4c9d3 ¤   (void)seckey;
bc1c0d ¤   (void)format;
400b93 ¤   return kPGPError_PublicKeyUnimplemented;
30efe6 }
feaf5a
80beb7 static int
--af35 000863654174010020e Page 14 of pgpElGKey.c
74065e elgSign(PGPSecKey *seckey, PGPHashVTBL const *h, PGPByte const *hash,
636564 ¤   PGPByte *sig, size_t *siglen, PGPRandomContext const *rc,
d86fc3 ¤   PGPPublicKeyMessageFormat format)
a7bb36 {
3bc9d3 ¤   (void)seckey;
b5c6fd ¤   (void)h;
d94902 ¤   (void)hash;
da77e4 ¤   (void)sig;
9a51a9 ¤   (void)siglen;
db76a2 ¤   (void)rc;
031c0d ¤   (void)format;
100b93 ¤   return kPGPError_PublicKeyUnimplemented;
01efe6 }
62af5a
3b38e5 /*
2413d2 ·* Re-encrypt a PGPSecKey with a new passphrase.
c213db ·* A secret key is, after a non-specific prefix:
923dd0 ·* ·0 ······1 ···Version (= 2 or 3)
14e351 ·* ·1 ······4 ···Timestamp
850e90 ·* ·5 ······2 ···Validity (=0 at present)
17511e ·* ·7 ······1 ···Algorithm (=kPGPPublicKeyAlgorithm_ElGamal for ELG)
a29455 ·* The following:
2acc75 ·* ·0 ···············2+u ·MPI for prime
6ccb7c ·* ·2+u ·············2+v ·MPI for generator
26661a ·* ·4+u+v¤  ·····2+w ·MPI for public key
b6aa0a ·* ·6+u+v+w ·········1 ···Encryption algorithm (0 for none, 1 for IDEA)
8d331b ·* ·7+u+v+w ·········t ···Encryption IV: 0 or 8 bytes
a11656 ·* ·7+t+u+v+w ·······2+x ·MPI for x (discrete log of public key)
8b43ca ·* ·9+t+u+v+w+x ·····2 ···Checksum
4f2320 ·* 11+t+u+v+w+x
d3775e ·*
fad1aa ·* The Encryption algorithm is the cipher algorithm for the old-style
b54ff3 ·* string-to-key conversion. ·For the new type, it's 255, then a cipher
642fc9 ·* algorithm, then a string-to-key algorithm (variable-length),
ead7a3 ·* then the encryption IV. ·That's 16 bytes plus the string-to-key
16f861 ·* conversion length.
bc495d ·*/
5aaf5a
6dbeb7 static int
954c3c elgChangeLock(PGPSecKey *seckey, PGPEnv const *env,·
f35ff1 ¤   PGPRandomContext const *rc, char const *phrase, size_t plen,
7bab73 ¤   PGPStringToKeyType s2ktype)
73bb36 {
2ea8c1 ¤   ELGsecPlus *sec = (ELGsecPlus *)seckey->priv;
e18c63 ¤   PGPStringToKey *s2k = NULL;¤/* Shut up warnings */
6ebfad ¤   PGPCipherVTBL const *cipher = NULL;¤/* Shut up warnings */
75bf66 ¤   PGPCFBContext *cfb = NULL;¤ /* This is realy needed */
bf4cc9 ¤   PGPByte *p;
0601ca ¤   int oldf = 0;¤  ¤   ¤   ¤   /* Shut up warnings */
eec6b5 ¤   unsigned len;
ab1b07 ¤   unsigned checksum;
abc640 ¤   PGPContextRef¤  context¤= pgpenvGetContext( env );
9caf5a
fbc693 ¤   ASSERTELG(seckey->pkAlg);
29d2c6 ¤   if (sec->locked)
82035c ¤   ¤   return kPGPError_KeyIsLocked;
bfaf5a
51b3a0 ¤   len = bnBytes(&sec->s.p) + bnBytes(&sec->s.g) +
921e66 ¤   ······bnBytes(&sec->s.y) + bnBytes(&sec->s.x) + 11;
1d358f ¤   if (phrase) {
580506 ¤   ¤   s2k = pgpS2Kcreate(env, rc, s2ktype);
4aa487 ¤   ¤   if (!s2k)
617cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
61bb77 ¤   ¤   cipher = pgpCipherDefaultKey(env);
0da7cf ¤   ¤   pgpAssert(cipher);
23db89 ¤   ¤   if (!cipher) {
ae4835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
6f7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
1c0fe4 ¤   ¤   }
eee9ea ¤   ¤   len += cipher->blocksize;
33a96b ¤   ¤   cfb = pgpCFBCreate( PGPGetContextMemoryMgr( context ), cipher);
865dfd ¤   ¤   if (!cfb) {
--9672 000542845864010020e Page 15 of pgpElGKey.c
974835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
317cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
c20fe4 ¤   ¤   }
e09484 ¤   ¤   oldf = pgpS2KisOldVers(s2k);
69cfc4 ¤   ¤   if (!oldf)
7b0bcc ¤   ¤   ¤   len += 1 + s2k->encodelen;
f79371 ¤   }
7b9613 ¤   if (len > sec->ckalloc) {
a5000e ¤   ¤   PGPError err = kPGPError_NoErr;
7dd409 ¤   ¤   if( IsNull( sec->cryptkey ) ) {
34f6b5 ¤   ¤   ¤   sec->cryptkey = (PGPByte *)
00df13 ¤   ¤   ¤   ¤   pgpContextMemAlloc( sec->context, len,
41201d ¤   ¤   ¤   ¤   ¤   0 );
0c5c6f ¤   ¤   ¤   if( IsNull( sec->cryptkey ) ) {
6ebfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
a9a3a6 ¤   ¤   ¤   }
ed45a6 ¤   ¤   } else {
075ce8 ¤   ¤   ¤   err = pgpContextMemRealloc( context,
31a54f ¤   ¤   ¤   ¤   (void **)&sec->cryptkey, len, 0 );
800fe4 ¤   ¤   }
f037b3 ¤   ¤   if( IsPGPError( err ) ) {
2e5d4c ¤   ¤   ¤   PGPFreeCFBContext(cfb);
914835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
a2b32f ¤   ¤   ¤   return err;
d10fe4 ¤   ¤   }
5078cc ¤   ¤   sec->ckalloc = (size_t)len;
999371 ¤   }
f06cd9 ¤   sec->cklen = len;
08a8ca ¤   p = sec->cryptkey;
7baf5a
c714eb ¤   /* Okay, no more errors possible! ··Start installing data */
e875f6 ¤   p += pgpBnPutPlain(&sec->s.p, p);
ea0727 ¤   p += pgpBnPutPlain(&sec->s.g, p);
3634cf ¤   p += pgpBnPutPlain(&sec->s.y, p);
9daf5a
a0c4c6 ¤   /* Encryption parameters */
a89f26 ¤   if (!phrase) {
ca7625 ¤   ¤   *p++ = 0;¤  /* Unencrypted */
3ff037 ¤   } else {
b434b3 ¤   ¤   if (oldf) {
bfce24 ¤   ¤   ¤   *p++ = cipher->algorithm;
7945a6 ¤   ¤   } else {
cf0c31 ¤   ¤   ¤   *p++ = 255;
e6ce24 ¤   ¤   ¤   *p++ = cipher->algorithm;
95682f ¤   ¤   ¤   memcpy(p, s2k->encoding, s2k->encodelen);
8dcb5d ¤   ¤   ¤   p += s2k->encodelen;
160fe4 ¤   ¤   }
60f1d5 ¤   ¤   /* Create IV */
138277 ¤   ¤   pgpRandomGetBytes(rc, p, cipher->blocksize);
994eef ¤   ¤   /* Use data buffer as temp holding space for key */
df6961 ¤   ¤   pgpAssert(sec->ckalloc-cipher->blocksize >= cipher->keysize);
1dff98 ¤   ¤   pgpStringToKey(s2k, phrase, plen, p+cipher->blocksize,
b2ecbe ¤   ¤   ¤   cipher->keysize);
e91e9c ¤   ¤   PGPInitCFB(cfb, p+cipher->blocksize, p);
45e56b ¤   ¤   pgpS2Kdestroy(s2k);
33d63b ¤   ¤   p += cipher->blocksize;
681b01 ¤   ¤   /* Wipe key *immediately* */
d2ab67 ¤   ¤   pgpClearMemory( p, ·cipher->keysize);
a39371 ¤   }
fbaf5a
a10f6e ¤   /* Now install x, encrypted */
0aa2f0 ¤   checksum = 0;
bfca75 ¤   p += pgpBnPutNew(&sec->s.x, p, cfb, &checksum);
38fa97 ¤   pgpChecksumPutNew(checksum, p, cfb);
36930f ¤   p += 2;
a5d0ef ¤   pgpAssert((ptrdiff_t)len == p - sec->cryptkey);
22af5a
b3afda ¤   if (cfb)
37d6b0 ¤   ¤   PGPFreeCFBContext(cfb);
5829fb ¤   return 0;¤  /* Success */
f6efe6 }
54af5a
--b440 000b310739d4010020e Page 16 of pgpElGKey.c
215d09 static size_t
7061cd elgSecBufferLength(PGPSecKey const *seckey)
b0bb36 {
815a26 ¤   ELGsecPlus const *sec = (ELGsecPlus *)seckey->priv;
9faf5a
c9b0e6 ¤   return sec->cklen;
63efe6 }
6aaf5a
642978 static void
1ab200 elgSecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
70bb36 {
295a26 ¤   ELGsecPlus const *sec = (ELGsecPlus *)seckey->priv;
77af5a
220030 ¤   memcpy(buf, sec->cryptkey, sec->cklen);
55af5a
7a98c6 ¤   /* Return only algorithm-dependent portion */
72efe6 }
fbaf5a
63af5a
8cf03c /* Fill in secret key structure */
222978 static void
347187 elgFillSecKey(PGPSecKey *seckey, ELGsecPlus *sec)
7cbb36 {
da460e ¤   seckey->pkAlg¤  ············= kPGPPublicKeyAlgorithm_ElGamal;
29ba80 ¤   seckey->priv¤   ············= sec;
6adf19 ¤   seckey->destroy ············= elgSecDestroy;
bd38e3 ¤   seckey->pubkey ·············= elgPubkey;
62763e ¤   seckey->islocked ···········= elgIslocked;
bda96b ¤   seckey->lockingalgorithm ···= elgLockingAlgorithm;
dc209d ¤   seckey->s2ktype ············= elgS2KType;
05c03d ¤   seckey->convertpassphrase ··= elgConvertPassphrase;
0d39f5 ¤   seckey->unlock ·············= elgUnlock;
040bd6 ¤   seckey->lock ···············= elgLock;
8af740 ¤   seckey->decrypt ············= elgDecrypt;
a2e561 ¤   seckey->maxdecrypted ·······= elgSecMaxdecrypted;
380343 ¤   seckey->maxesk¤ ¤   ········= elgSecMaxesk;
84b717 ¤   seckey->maxsig ·············= elgSecMaxsig;
a9b54a ¤   seckey->sign ···············= elgSign;
64089e ¤   seckey->changeLock ·········= elgChangeLock;
68a8fd ¤   seckey->bufferLength ·······= elgSecBufferLength;
9681d1 ¤   seckey->toBuffer ···········= elgSecToBuffer;
cfefe6 }
00af5a
70af5a
10521e PGPSecKey *
59560a elgSecFromBuf(
dd520e ¤   PGPContextRef¤  context,
db4d2b ¤   PGPByte const *¤buf,
9439e0 ¤   size_t¤ ¤   ¤   size,
f46429 ¤   PGPError *¤ ¤   error)
75bb36 {
804bdc ¤   PGPSecKey *seckey;
ba1b5e ¤   ELGsecPlus *sec;
29e99a ¤   PGPByte *cryptk;
1f4c08 ¤   PGPError¤   err¤= kPGPError_OutOfMemory;
0df9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
b1ca2b ¤   PGPEnv *¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( context );
67af5a
27bac4 ¤   bnInit();
4bdee6 ¤   cryptk = (PGPByte *)pgpContextMemAlloc( context,
ac2217 ¤   ¤   size, kPGPMemoryMgrFlags_Clear);
b17809 ¤   if (cryptk) {
ef9457 ¤   ¤   sec = (ELGsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
466492 ¤   ¤   if (sec) {
beae3f ¤   ¤   ¤   pgpClearMemory( sec, sizeof(*sec) );
e82da8 ¤   ¤   ¤   sec->context¤   = context;
c587c7 ¤   ¤   ¤
9978b7 ¤   ¤   ¤   seckey = (PGPSecKey *) pgpContextMemAlloc( context,
d4480b ¤   ¤   ¤   ¤   ¤   sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
ca1bb1 ¤   ¤   ¤   if (seckey) {
b1e337 ¤   ¤   ¤   ¤   seckey->context¤= context;
b32b85 ¤   ¤   ¤   ¤
--a598 0007677abcf4010020e Page 17 of pgpElGKey.c
c0bc41 ¤   ¤   ¤   ¤   memcpy(cryptk, buf, size);
dacae5 ¤   ¤   ¤   ¤   bnBegin(&sec->s.p, mgr, FALSE );
bdb229 ¤   ¤   ¤   ¤   bnBegin(&sec->s.g, mgr, FALSE );
0d5a92 ¤   ¤   ¤   ¤   bnBegin(&sec->s.y, mgr, FALSE );
5e91ef ¤   ¤   ¤   ¤   bnBegin(&sec->s.x, mgr, TRUE );
eb4699 ¤   ¤   ¤   ¤   sec->cryptkey = cryptk;
1fb1a8 ¤   ¤   ¤   ¤   sec->cklen = sec->ckalloc = size;
4a6564 ¤   ¤   ¤   ¤   sec->locked = 1;
36bc1d ¤   ¤   ¤   ¤   /* We only need this to try unlocking... */
a85faa ¤   ¤   ¤   ¤   seckey->pkAlg = kPGPPublicKeyAlgorithm_ElGamal;
8a22e9 ¤   ¤   ¤   ¤   seckey->priv = sec;
032b85 ¤   ¤   ¤   ¤
36c0a2 ¤   ¤   ¤   ¤   if (elgUnlock(seckey, pgpEnv, NULL, 0, FALSE) >= 0) {
4bbeab ¤   ¤   ¤   ¤   ¤   elgFillSecKey(seckey, sec);
654dc6 ¤   ¤   ¤   ¤   ¤   *error = kPGPError_NoErr;
171b30 ¤   ¤   ¤   ¤   ¤   return seckey;¤ /* Success! */
cf2613 ¤   ¤   ¤   ¤   }
0afa07 ¤   ¤   ¤   ¤   else
2672c3 ¤   ¤   ¤   ¤   {
18daa3 ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_UnknownError;
2e2613 ¤   ¤   ¤   ¤   }
c6af5a
2126c6 ¤   ¤   ¤   ¤   /* Ka-boom. ·Delete and free everything. */
50d423 ¤   ¤   ¤   ¤   pgpClearMemory( cryptk, ·size);
d23e32 ¤   ¤   ¤   ¤   pgpContextMemFree( context, seckey);
2fa3a6 ¤   ¤   ¤   }
6e46d9 ¤   ¤   ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
240fe4 ¤   ¤   }
cc718e ¤   ¤   pgpContextMemFree( context, cryptk);
dc9371 ¤   }
2cab59 ¤   *error = err;
5f3f59 ¤   return NULL;
49efe6 }
32af5a
0af514 /* Generate super-strong primes? (Warning: slow!) */
17a091 #ifndef ELG_GERMAIN
029033 #define ELG_GERMAIN 0
897454 #endif
dfaf5a
d938e5 /*
27b8fa ·* Generate an ELG secret key with prime of the specified number of bits.
6adce8 ·* Make callbacks to progress function periodically.
517af8 ·* Secret key is returned in the unlocked form, with no passphrase set.
50fae6 ·* fastgen tells us to use canned primes if available.
56775e ·*
2c52c1 ·* If ELG_GERMAIN is set to 1, we generate p such that (p-1)/2 is also
d94e7a ·* prime. ·This takes long time. ·(Pseudoprimality tests take time
08f290 ·* cubic in the number of bits, and the number of tests needed is
78f3e9 ·* linear in the number of bits, so it's quartic overall. ·Searching
72b9a3 ·* for Sophier Germain primes makes it quintic(!), although the constant
4974d4 ·* factor improves to make up for a lot of that.
3c775e ·*
4fcd6b ·* The alternative (which is really just as safe, really) is to generate
e74050 ·* primes which have a large prime factor q about 10 bits shorter than
70b32f ·* the requested length. ·We will guarantee that 2 is a generator of a
6fe6af ·* subgroup with period at least q.
0f775e ·*
4f7691 ·* If it is OK, we could speed it up more by generating multiple primes
b559db ·* qi such that p = 2*k*q1*q2*q3*...*qn + 1, and where each qi is greater
7a44a0 ·* than 2**160 (or whatever exponent value we are using). ·Again, once we
66bc05 ·* verify that 2's period is > 2k we know it as at least min(qi), which
2241ce ·* should be long enough for prevention of discrete log attacks.
13775e ·*
04bc5f ·* A bit of theory: the average density of primes around n is 1/ln(n),
be8e03 ·* so the average gap between primes is ln(n). ·However, the maximum
1e084f ·* gap is ln(n)^2. ·The fact that we're searching in steps other than
207c29 ·* 1 doesn't matter - it'll take an average of ln(n) steps.
6c775e ·*
7be890 ·* So to produce a prime of the desired size, we should have p/q at
0813ec ·* least ln(p) and to guarantee it, we need p/q = ln(p)^2. ·This
5c5575 ·* means that we want
7643cf ·* log2(ln(p)) ··········< log2(p/q) ········< log2(ln(p)^2)
--cb52 000b61f96174010020e Page 18 of pgpElGKey.c
9557db ·* log2(0.693*log2(p)) ··< log2(p) - log2(q) < 2 * log2(0.693 * log2(p))
758e18 ·* log2(log2(p)) - 0.529 < log2(p) - log2(q) < 2 * log2(log2(p)) - 1.058
9c775e ·*
8335b3 ·* At this point, it's safe to start getting crude, because if we're
90e20a ·* only counting bits, 2^(bits(x)-1) <= x < 2^bits(x) <= 2*x, or
46970f ·* bits(x)-1 <= log2(x) < bits(x) <= log2(x)+1. ·Another way of looking
9986da ·* at all this is that log2(x) is bits(x) - 0.5 +/- 0.5.
48356e ·* So let's split the difference and use 1.5 * bits(bits(p)) - 1 as the
61b9fe ·* difference in bits between p and q. ·
39775e ·*
8f3934 ·* See the discussion preceding the DSA keygen routine dsaSecGenerate
43ae03 ·* in pgpDSAKey.c for an explanation of the rcdummy random number
ba6347 ·* generator below. ·It serves to limit leakage of the state of the
4c55f9 ·* randpool into the public values generated as part of the key.
32495d ·*/
a7521e PGPSecKey *
642889 elgSecGenerate(
43520e ¤   PGPContextRef¤  context,
b28285 ¤   unsigned bits, PGPBoolean fastgen,
594b45 ¤   PGPRandomContext const *rc,
2602ee ¤   int progress(void *arg, int c), void *arg, PGPError *error)
77bb36 {
da4bdc ¤   PGPSecKey *seckey;
801b5e ¤   ELGsecPlus *sec;
f19c71 ¤   PGPRandomContext *rcdummy = NULL;
c5e682 ¤   unsigned bits2;
d063ab #if !ELG_GERMAIN
03bfc8 ¤   unsigned lengthdiff;
5e7015 ¤   BigNum q, h, e;
464ba4 ¤   int i;
0d7454 #endif
fdcd6d ¤   PGPByte dummyseed[ELGDUMMYBITS/8];
c3f9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
a8ca2b ¤   PGPEnv *¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( context );
a7af5a
679096 ¤   *error = kPGPError_NoErr;
ecaf5a
cf208e ¤   /* Initialize local pointers (simplify cleanup below) */
493670 ¤   seckey = NULL;
7b2d16 ¤   sec = NULL;
a9af5a
360e57 ¤   /* Allocate data structures */
722ab1 ¤   seckey = (PGPSecKey *)pgpContextMemAlloc( context,
7c56ec ¤   ¤   sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
432672 ¤   if (!seckey)
dc718c ¤   ¤   goto memerror;
5d20f7 ¤   seckey->context¤= context;
5a8174 ¤   sec = (ELGsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
a5e024 ¤   sec->context¤   = context;
ff65c7 ¤   if (!sec)
b8718c ¤   ¤   goto memerror;
2a67c5 ¤
029b2d ¤   bnBegin(&sec->s.p, mgr, FALSE );
8fe3e1 ¤   bnBegin(&sec->s.g, mgr, FALSE );
d20b5a ¤   bnBegin(&sec->s.y, mgr, FALSE );
f2c48c ¤   bnBegin(&sec->s.x, mgr, TRUE );
c5af5a
2679b3 ¤   /* Use a fixed prime and generator if in our table */
ba0233 ¤   if (fastgen) {
0aba8a ¤   ¤   PGPByte const *fixedp, *fixedg;
d79ba4 ¤   ¤   size_t fixedplen, fixedglen;
b73e50 ¤   ¤   if (pgpElGfixed (bits, &fixedp, &fixedplen, &fixedg, &fixedglen) > 0) {
3deb3f ¤   ¤   ¤   if (progress)
b2c69e ¤   ¤   ¤   ¤   progress(arg, ' ');
1a5887 ¤   ¤   ¤   bnInsertBigBytes (&sec->s.p, fixedp, 0, fixedplen);
e0eb3f ¤   ¤   ¤   if (progress)
50c69e ¤   ¤   ¤   ¤   progress(arg, ' ');
37e110 ¤   ¤   ¤   bnInsertBigBytes (&sec->s.g, fixedg, 0, fixedglen);
ac4243 ¤   ¤   ¤   goto choose_x;
1e0fe4 ¤   ¤   }
799371 ¤   }
b6af5a
--1c64 0009dfa10a74010020e Page 19 of pgpElGKey.c
00cdbe ¤   /* Set up local random number generator for p and q */
b3b5b9 ¤   rcdummy = pgpPseudoRandomCreate ( rc->context );
85727a ¤   if (!rcdummy)
50718c ¤   ¤   goto memerror;
15b76f ¤   pgpRandomGetBytes (rc, dummyseed, sizeof(dummyseed));
c25239 ¤   pgpRandomAddBytes (rcdummy, dummyseed, sizeof(dummyseed));
19af5a
b57995 #if ELG_GERMAIN
5e0882 ¤   /* Strong ("sophie germain") prime search */
6aaf5a
af2820 ¤   /* Find p - choose a starting place */
914ede ¤   if (pgpBnGenRand(&sec->s.p, rcdummy, bits, 0xC0, 3, bits-4) < 0)
d25b40 ¤   ¤   goto nomem;
9aaf5a
e49b4f ¤   /* And search for a prime */
503642 ¤   if (bnGermainPrimeGen(&sec->s.p, 1, progress, arg) < 0)
215b40 ¤   ¤   goto nomem;
0aaf5a
467c22 ¤   /* We have chosen p so 2 is a good choice for generator */
5b2293 ¤   if (bnSetQ(&sec->s.g, 2) < 0)
4f5b40 ¤   ¤   goto nomem;
abaf5a
6ae462 ¤   /* Choose a random x of reasonable size as secret key */
9f63f3 ¤   expbits = elgExpBits(bits);
6b62ba ¤   if (pgpBnGenRand(&sec->s.x, rc, expbits, 0, 0, expbits) < 0)
195b40 ¤   ¤   goto nomem;
2daf5a
dd7de8 ¤   /* And calculate g**x as public key */
e54cee ¤   if (bnTwoExpMod(&sec->s.y, &sec->s.x, &sec->s.p) < 0)
0d5b40 ¤   ¤   goto nomem;
50cc48 #else /* !ELG_GERMAIN - the faster version */
36293f ¤   bnBegin(&q, mgr, FALSE );
ddb1a9 ¤   bnBegin(&h, mgr, FALSE );
8c61e2 ¤   bnBegin(&e, mgr, FALSE );
c5af5a
d7d8af ¤   /*
fef4ef ¤   ·* Choose a random starting place for q, a bit less than p.
501677 ¤   ·* (See function header comment above for the theory behind this.)
56a4e3 ¤   ·*/
fe37b6 ¤   lengthdiff = 0;
fd1032 ¤   for (bits2 = bits; bits2; bits2 >>= 1)
e1324d ¤   ¤   lengthdiff++;
ec9c55 ¤   lengthdiff += (lengthdiff+1)/2;
cf6a67 ¤   bits2 = bits - lengthdiff;
1aaf5a
28492b ¤   if (pgpBnGenRand(&q, rcdummy, bits2, 0x80, 1, bits2-2) < 0)
da5b40 ¤   ¤   goto nomem;
cd9b4f ¤   /* And search for a prime */
48e86a ¤   i = bnPrimeGen(&q, NULL, progress, arg, 0);
f34fd6 ¤   if (i < 0)
035b40 ¤   ¤   goto nomem;
9c1610 ¤   if (progress)
bee03c ¤   ¤   progress(arg, ' ');
14af5a
f8ec3e ¤   /* ...and now a random start for p */
681e57 ¤   (void)bnSetQ(&sec->s.p, 0);
2a5242 ¤   if (pgpBnGenRand(&sec->s.p, rcdummy, bits, 0xC0, 1, bits-bits2-3) < 0)
515b40 ¤   ¤   goto nomem;
d7af5a
056159 ¤   /* Double q to make it a suitable stride */
5c24ad ¤   if (bnLShift(&q, 1) < 0)
6b5b40 ¤   ¤   goto nomem;
91af5a
9fe2e6 ¤   /* Set p = p - (p mod 2q) + 1, i.e. congruent to 1 mod 2q */
cda15b ¤   if (bnMod(&h, &sec->s.p, &q) < 0)
235b40 ¤   ¤   goto nomem;
8d6a48 ¤   if (bnSub(&sec->s.p, &h) < 0 || bnAddQ(&sec->s.p, 1) < 0)
ef5b40 ¤   ¤   goto nomem;
1caf5a
71c0f3 ¤   /* This loop is very rarely executed */
10165f retry:
9dfa6e ¤   /* And search for a prime, 1+2kq for some k */
--752f 000902bdf504010020e Page 20 of pgpElGKey.c
ec97c6 ¤   i = bnPrimeGenStrong(&sec->s.p, &q, progress, arg);
4a4fd6 ¤   if (i < 0)
1f5b40 ¤   ¤   goto nomem;
931610 ¤   if (progress)
a3e03c ¤   ¤   progress(arg, ' ');
a2af5a
98ae8d ¤   /* Now check two as g: first, find (p-1)/q = 2*((p-1)/(2*q)) */
777e8c ¤   if (bnDivMod(&e, &h, &sec->s.p, &q) < 0 || bnLShift(&e, 1) < 0)
685b40 ¤   ¤   goto nomem;
cd9f2e ¤   /* e is now (p-1)/q, and h is the remainder (one!) */
dbd0c0 ¤   pgpAssert (bnBits(&h) == 1);
a4af5a
10d8af ¤   /*
c0a257 ¤   ·* Make sure 2**((p-1)/q) mod p is not small. ·This should imply
912f74 ¤   ·* that the period of 2 as a generator has at least q as a factor,
91891c ¤   ·* meaning it is very big.
952398 ¤   ·* With (p-1)/q as small as it is, the chances are *excellent*
6682c9 ¤   ·* that it will work. ·If (p-1)/q were less than a few hundred
03662c ¤   ·* 2**((p-1)/q) would be less than p and coundn't possibly be 1.
91a4e3 ¤   ·*/
3c6b17 ¤   if (bnTwoExpMod(&h, &e, &sec->s.p) < 0)
905b40 ¤   ¤   goto nomem;
5e108a ¤   if (bnBits(&h) < 2) {
b72c8a ¤   ¤   if (progress)
4c4d62 ¤   ¤   ¤   progress(arg, ' ');
8be14d ¤   ¤   goto retry;
219371 ¤   }
ff4f51 ¤   bnEnd(&e);
ffc4de ¤   bnEnd(&h);
e5fe1c ¤   bnEnd(&q);
fa7454 #endif
5384b6 ¤   /* We have done things so 2 is a good choice for generator */
8f2293 ¤   if (bnSetQ(&sec->s.g, 2) < 0)
015b40 ¤   ¤   goto nomem;
9caf5a
26d349 ¤   /* May get here directly from above if fixed primes are used */
feb313 choose_x:
48af5a
2ee462 ¤   /* Choose a random x of reasonable size as secret key */
484f79 ¤   bits2 = pgpDiscreteLogExponentBits(bits)*3/2;
4f482b ¤   if (pgpBnGenRand(&sec->s.x, rc, bits2, 0, 0, bits2) < 0)
ea5b40 ¤   ¤   goto nomem;
2daf5a
ca7de8 ¤   /* And calculate g**x as public key */
60f32a ¤   if (bnExpMod(&sec->s.y, &sec->s.g, &sec->s.x, &sec->s.p) < 0)
235b40 ¤   ¤   goto nomem;
1d67c5 ¤
adaf5a
161fb6 ¤   /* And that's it... success! */
2faf5a
db2d0e ¤   /* Fill in structs */
70c257 ¤   sec->cryptkey = NULL;
51a3cb ¤   sec->ckalloc = sec->cklen = 0;
d30162 ¤   sec->locked = 0;
f16034 ¤   elgFillSecKey(seckey, sec);
9caf5a
9bb736 ¤   /* Fill in cryptkey structure, unencrypted */
992889 ¤   elgChangeLock (seckey, pgpEnv, NULL, NULL, 0, kPGPStringToKey_Simple);
45af5a
f2c48e ¤   goto done;
a8af5a
1fac52 nomem:
7a63ab #if !ELG_GERMAIN
1c4f51 ¤   bnEnd(&e);
0ac4de ¤   bnEnd(&h);
bdfe1c ¤   bnEnd(&q);
417454 #endif
443273 ¤   bnEnd(&sec->s.p);
78a6f3 ¤   bnEnd(&sec->s.g);
66cb10 ¤   bnEnd(&sec->s.y);
49d7ab ¤   bnEnd(&sec->s.x);
9091b1 ¤   /* Fall through */
--72af 001e0afa5cb4010020e Page 21 of pgpElGKey.c
94623d memerror:
ec54f2 ¤   if ( IsntNull( seckey ) )
e23fb4 ¤   ¤   pgpContextMemFree( context, seckey);
2b6101 ¤   if ( IsntNull( sec ) )
ac82c5 ¤   ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
bd3670 ¤   seckey = NULL;
ee27b8 ¤   *error = kPGPError_OutOfMemory;
1eaf5a
0ab38c done:
45a925 ¤   if (rcdummy)
4612fa ¤   ¤   pgpRandomDestroy (rcdummy);
741b52 ¤   ¤
564d98 ¤   return seckey;
7aefe6 }
e0af5a
--519f 001bb5cacc24010020f Page 1 of pgpElGKey.h
bc38e5 /*
27ff9f ·* $Id: pgpElGKey.h,v 1.10 1997/06/25 19:40:55 lloyd Exp $
52495d ·*/
38af5a
4af4e2 #ifndef Included_pgpElGKey_h
ef75d4 #define Included_pgpElGKey_h
86af5a
8fa395 #include "pgpPubTypes.h"¤   /* For PGPByte */
35adb8 #include "pgpOpaqueStructs.h"
bdaf5a
0299c6 PGP_BEGIN_C_DECLARATIONS
a9af5a
0b25e5 /* Bits for uniqueness of p, q */
8f3866 #define ELGDUMMYBITS¤   64
7aaf5a
07105a PGPPubKey *¤elgPubFromBuf( PGPContextRef context,
90fe12 ¤   ¤   ¤   ¤   PGPByte const *buf, size_t len, PGPError *error);
e72b85 ¤   ¤   ¤   ¤
61f9e5 PGPSecKey *¤elgSecFromBuf( PGPContextRef context,
a1fe12 ¤   ¤   ¤   ¤   PGPByte const *buf, size_t len, PGPError *error);
9387c7 ¤   ¤   ¤
33fd20 int¤¤   ¤   elgPubKeyPrefixSize(PGPByte const *buf, size_t size);
57af5a
a12cc9 PGPSecKey *¤elgSecGenerate(PGPContextRef context,
1dc5e3 ¤   ¤   ¤   ¤   unsigned bits, PGPBoolean fastgen,
1b8d8a ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
ff1ebb ¤   ¤   ¤   ¤   int progress(void *arg, int c), void *arg, PGPError *error);
04af5a
e81254 PGP_END_C_DECLARATIONS
a5af5a
bbe314 #endif /* Included_pgpElGKey_h */
--d948 000387e7dd140100210 Page 1 of pgpFixedKey.c
bc38e5 /*
70771d ·* A single, fixed PGP key for decryption operations.
e150a5 ·* Also contains fixed primes and generators for discrete log keys which
d60bc6 ·* can share these.
5d775e ·*
f9765d ·* $Id: pgpFixedKey.c,v 1.8 1997/09/30 21:03:01 lloyd Exp $
c8495d ·*/
c3e2ff #include "pgpConfig.h"
b6af5a
dad11f #include "pgpUsuals.h"
00c223 #include "pgpFixedKey.h"
72af5a
677887 /* Fixed p, q, g values for DSA keys */
77af5a
d1b177 #if 0
ead457 static PGPByte const DSA1024p[] = {
a730e6 ¤   0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4,
d33411 ¤   0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B, 0x33, 0x6C, 0x38, 0x0D,
574b58 ¤   0x45, 0x1D, 0x0F, 0x7C, 0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D,
5de23a ¤   0x8E, 0xF6, 0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
3fd766 ¤   0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3,
bf2fb8 ¤   0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C,
796bed ¤   0xDE, 0x33, 0x21, 0x2C, 0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1,
bcd779 ¤   0x29, 0x40, 0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
055f79 ¤   0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29, 0x7A, 0xCA,
063721 ¤   0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x50, 0x9B,
f140df ¤   0x02, 0x46, 0xD3, 0x08, 0x3D, 0x66, 0xA4, 0xB0, 0xB6, 0x51,
e5fc02 ¤   0xE2, 0xBA, 0xE5, 0x4E, 0x44, 0x39, 0x7C, 0x9F, 0x2A, 0x5E,
130250 ¤   0x31, 0x2F, 0xF6, 0xDB, 0x5C, 0x75, 0xAE, 0x81
bdaf5a
ef82f7 };
4955e8 static PGPByte const DSA1024q[] = {
aa07bb ¤   0xFF, 0x9F, 0x9C, 0x7C, 0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26,
8881d9 ¤   0xBA, 0xAB, 0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x27, 0xC2, 0xB1
4982f7 };
037454 #endif
56684e static PGPByte const DSA1536p[] = {
4867df ¤   0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F, 0x3D, 0x3D,
723396 ¤   0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57, 0x92, 0x59, 0xCD, 0xFD,
a58700 ¤   0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5,
4358fc ¤   0x47, 0x30, 0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
e30ea8 ¤   0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3, 0x5B, 0x9E,
4b9f29 ¤   0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4, 0x1A, 0xF0, 0xBF, 0x46,
267b7a ¤   0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49,
9d8141 ¤   0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
fc0f9c ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C, 0x88, 0xB3,
ed0373 ¤   0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6, 0xF3, 0xC9, 0x23, 0xC0,
9257c8 ¤   0x43, 0xF0, 0xA5, 0x5B, 0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C,
582624 ¤   0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
55f3f4 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C, 0xB5, 0x2A,
6eaf69 ¤   0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18, 0x11, 0x8D, 0x7C,
192331 ¤   0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8,
afabb7 ¤   0x07, 0x29, 0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
435799 ¤   0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x47, 0x2C, 0xCB, 0xA6, 0x82,
95fea3 ¤   0xA5, 0xEB, 0xA2, 0x84, 0x3E, 0xE3, 0x3D, 0x56, 0xE7, 0xA9,
f3dc9c ¤   0xF3, 0xE1, 0xC4, 0x3D, 0x22, 0x98, 0x80, 0xF3, 0xC3, 0x08,
9e03b6 ¤   0x49, 0x8F
6a82f7 };
25e9f1 static PGPByte const DSA1536q[] = {
ca954d ¤   0x3F, 0xFD, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C, 0xBD,
4d34d0 ¤   0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2, 0x5E, 0xC3,
fcb42d ¤   0x55, 0xE9, 0x27, 0xC2, 0x43
ce82f7 };
2ffb44 static PGPByte const DSA2048p[] = {
fa828a ¤   0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17, 0x72, 0xA2,
1ca908 ¤   0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05, 0xE8, 0xF9, 0x53, 0x11,
a7ad4d ¤   0x39, 0x4F, 0xB6, 0xF1, 0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA,
d05571 ¤   0x01, 0xA7, 0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
cfe5f4 ¤   0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD, 0xF7, 0x4C,
072d85 ¤   0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83, 0xBD, 0x65, 0xE9, 0x17,
3d755a ¤   0xD4, 0xA1, 0xD3, 0x50, 0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76,
38492c ¤   0x52, 0x4F, 0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
--9341 000151cc53a40100210 Page 2 of pgpFixedKey.c
f7e6cc ¤   0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC,
73ef0c ¤   0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30, 0x61, 0xCE, 0x7C, 0xC9,
e297d8 ¤   0x66, 0xFF, 0x15, 0xF9, 0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01,
139e1f ¤   0xAA, 0xD3, 0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
584c5e ¤   0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88,
9713b4 ¤   0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4,
8e3994 ¤   0x91, 0x07, 0x36, 0x6B, 0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D,
3b05a5 ¤   0x0F, 0x7C, 0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
9de0e5 ¤   0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B, 0x18, 0x8D,
a0e34e ¤   0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD,
0abf76 ¤   0x7C, 0x17, 0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33,
c94e96 ¤   0x21, 0x2C, 0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
821992 ¤   0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86,
6ecbe8 ¤   0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29, 0x7A, 0xCA, 0x95, 0x0C,
14e7b7 ¤   0xD9, 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x51, 0xB8, 0x4F, 0xCF,
55974a ¤   0x7E, 0xC9, 0x6A, 0x96, 0xFA, 0x9E, 0x4E, 0xDC, 0x9F, 0x93,
d2c486 ¤   0x37, 0x21, 0x13, 0x1D, 0xE3, 0xDD, 0x3D, 0xE0, 0x7D, 0x1D,
63a34c ¤   0x6B, 0xCE, 0x09, 0x83, 0x11, 0xB5
aa82f7 };
a17afb static PGPByte const DSA2048q[] = {
18c6f8 ¤   0x01, 0xFE, 0x46, 0xD3, 0x08, 0x3D, 0x66, 0xA4, 0x5D, 0x41,
8eef6f ¤   0x9F, 0x9C, 0x7C, 0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA,
4bd638 ¤   0xAB, 0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x27, 0xC2, 0xCF
3482f7 };
8cee48 static PGPByte const DSA3072p[] = {
5235db ¤   0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2, 0xC4, 0xF0,
8a5a30 ¤   0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E, 0x92, 0x13, 0x61, 0xF6,
8a5ab9 ¤   0xDB, 0xEB, 0x25, 0x0E, 0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8,
c83fd9 ¤   0x7C, 0x79, 0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
e54f1c ¤   0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60, 0xC3, 0xE3,
bd9499 ¤   0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28, 0x26, 0x0B, 0xAE, 0xA9,
84e5e2 ¤   0xAE, 0xB3, 0x65, 0x0F, 0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C,
336503 ¤   0xD6, 0xAB, 0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
a2ee91 ¤   0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4, 0x40, 0xE9,
a2e869 ¤   0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D, 0x02, 0x36, 0xC1, 0x26,
24b398 ¤   0xCB, 0x68, 0x5E, 0x9D, 0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E,
75f171 ¤   0x2D, 0xED, 0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
412a3d ¤   0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32, 0xF6, 0x42,
89f2d5 ¤   0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17, 0x72, 0xA2, 0xBA, 0xD6,
c7c111 ¤   0xA9, 0x42, 0xF3, 0x05, 0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F,
4d091c ¤   0xB6, 0xF1, 0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
6b402b ¤   0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3, 0xD0, 0x07,
4dcb17 ¤   0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD, 0xF7, 0x4C, 0x64, 0x86,
b2d1ce ¤   0x49, 0xF8, 0x0C, 0x83, 0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1,
bebd05 ¤   0xD3, 0x50, 0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
0ecf6f ¤   0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57, 0x92, 0x59,
a85443 ¤   0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC, 0x76, 0xBC,
8bf7be ¤   0x83, 0xC5, 0x47, 0x30, 0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF,
d9873e ¤   0x15, 0xF9, 0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
99ee7b ¤   0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4, 0x1A, 0xF0,
2d6541 ¤   0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88, 0xFD, 0x58,
2948bf ¤   0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07,
c74a94 ¤   0x36, 0x6B, 0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
269029 ¤   0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6, 0xF3, 0xC9,
f23e1f ¤   0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B, 0x18, 0x8D, 0x8E, 0xBB,
d9ec87 ¤   0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17,
83524f ¤   0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
dae8b8 ¤   0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18, 0x11,
a5e64f ¤   0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4, 0x03,
3f21bb ¤   0x19, 0xC8, 0x07, 0x29, 0x7A, 0xCA, 0x95, 0x0C, 0xDB, 0x13,
1f58a7 ¤   0xD8, 0xA2, 0x1A, 0x8F, 0x32, 0x6B, 0x11, 0xEB, 0xA3, 0xF2,
603e82 ¤   0x71, 0x5E, 0xF5, 0xC5, 0x43, 0x6D, 0x84, 0x4B, 0xF6, 0xFE,
4b54a1 ¤   0x52, 0xB9, 0x60, 0x5A, 0x8E, 0x09, 0xCE, 0xCB, 0xFE, 0x94,
e1d052 ¤   0xBC, 0xEF, 0x23, 0x5B
ef82f7 };
686ff7 static PGPByte const DSA3072q[] = {
b35ddf ¤   0x3F, 0xEB, 0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
4ff7c3 ¤   0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C, 0xBD, 0x89,
19dece ¤   0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2, 0x5E, 0xC3, 0x55,
fbbe1a ¤   0xE9, 0x27, 0xC3, 0x1D
a4af5a
1582f7 };
--e914 000aff1211540100210 Page 3 of pgpFixedKey.c
b2d2ce static PGPByte const DSA4096p[] = {
7edeae ¤   0xF9, 0x18, 0xA0, 0x7E, 0x5A, 0x06, 0x61, 0x7A, 0x43, 0x90,
d23f78 ¤   0x95, 0xDC, 0x05, 0x6C, 0x87, 0x86, 0xEC, 0x61, 0xEC, 0xCD,
8fb550 ¤   0x45, 0x1F, 0x0E, 0xD8, 0xE0, 0xA3, 0x79, 0xC6, 0xC9, 0xDC,
78cef5 ¤   0x7A, 0x0B, 0xAC, 0xE4, 0x3F, 0xE3, 0x46, 0x94, 0xB6, 0x30,
1df0e9 ¤   0x4A, 0x53, 0xD7, 0x7C, 0x02, 0x16, 0x48, 0x80, 0xB5, 0x15,
f7d80f ¤   0xE5, 0x29, 0x99, 0xA9, 0x9F, 0x07, 0x74, 0xD3, 0xFF, 0xE3,
9c46e2 ¤   0xA1, 0xC5, 0x96, 0x20, 0x4E, 0x98, 0x65, 0xB8, 0xD8, 0x0D,
b1930f ¤   0xEE, 0x10, 0x5D, 0xAB, 0xB6, 0x17, 0x1C, 0x51, 0xD8, 0x50,
9e2457 ¤   0xCA, 0x22, 0x57, 0x43, 0x29, 0xBE, 0x95, 0xE8, 0x56, 0x2B,
621f3a ¤   0x38, 0x78, 0x5C, 0x0B, 0xDB, 0xF8, 0x4C, 0x4D, 0xD5, 0xE3,
31dbd2 ¤   0xAA, 0x46, 0xCC, 0xFB, 0xCE, 0x17, 0xE8, 0x2A, 0x9D, 0x14,
b1e0c5 ¤   0x61, 0xE3, 0x84, 0xA9, 0x4F, 0xD1, 0x83, 0x84, 0xA8, 0x79,
55a915 ¤   0xB6, 0xEF, 0x8F, 0xA7, 0x43, 0x46, 0x08, 0xC6, 0xCC, 0x1D,
44bc09 ¤   0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2, 0xC4, 0xF0, 0xE8, 0x8E,
9150b3 ¤   0x13, 0x67, 0x97, 0x4E, 0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB,
ff680c ¤   0x25, 0x0E, 0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
bb111c ¤   0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1, 0x73, 0xC4,
0c2655 ¤   0x83, 0x11, 0x26, 0x2B, 0x43, 0x60, 0xC3, 0xE3, 0xE8, 0xD6,
82e075 ¤   0x0A, 0xFD, 0xA1, 0x28, 0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3,
ef287b ¤   0x65, 0x0F, 0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
fc6309 ¤   0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F, 0x74, 0x84,
2a8e26 ¤   0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4, 0x40, 0xE9, 0xD7, 0xD2,
b2fac3 ¤   0x77, 0xB6, 0x42, 0x2D, 0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68,
f23b38 ¤   0x5E, 0x9D, 0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
ee7584 ¤   0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B, 0x18, 0x8E,
8fe038 ¤   0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32, 0xF6, 0x42, 0x57, 0xB7,
c20883 ¤   0x08, 0x7F, 0x08, 0x17, 0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42,
869fcb ¤   0xF3, 0x05, 0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
d7d3a9 ¤   0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7, 0x56, 0xA3,
871d86 ¤   0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3, 0xD0, 0x07, 0xC6, 0xCB,
859e62 ¤   0x43, 0xA9, 0x94, 0xAD, 0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8,
242d35 ¤   0x0C, 0x83, 0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
d067df ¤   0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F, 0x3D, 0x3D,
e93396 ¤   0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57, 0x92, 0x59, 0xCD, 0xFD,
678700 ¤   0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5,
9d58fc ¤   0x47, 0x30, 0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
370ea8 ¤   0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3, 0x5B, 0x9E,
e69f29 ¤   0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4, 0x1A, 0xF0, 0xBF, 0x46,
237b7a ¤   0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49,
6b8141 ¤   0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
b20f9c ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C, 0x88, 0xB3,
e10373 ¤   0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6, 0xF3, 0xC9, 0x23, 0xC0,
6157c8 ¤   0x43, 0xF0, 0xA5, 0x5B, 0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C,
1e2624 ¤   0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
2cf3f4 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C, 0xB5, 0x2A,
82af69 ¤   0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18, 0x11, 0x8D, 0x7C,
292331 ¤   0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8,
9a945d ¤   0x07, 0x29, 0x88, 0x50, 0x05, 0x4B, 0xFE, 0x24, 0x36, 0x96,
01d54f ¤   0x47, 0xAB, 0x40, 0x4A, 0xA2, 0xE5, 0xB3, 0xCB, 0x0E, 0x0F,
e770b4 ¤   0x2A, 0x1C, 0x45, 0x17, 0x3D, 0xD9, 0x5D, 0xED, 0x9F, 0x0D,
4362ed ¤   0x33, 0xDA, 0x04, 0xC9, 0x19, 0xA9, 0x9D, 0x3F, 0x40, 0xF3,
d28c95 ¤   0xF4, 0x2D
b082f7 };
855371 static PGPByte const DSA4096q[] = {
836189 ¤   0x01, 0xFF, 0x0C, 0xD9, 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x50,
9e86be ¤   0x9B, 0x02, 0x46, 0xD3, 0x08, 0x3D, 0x66, 0xA4, 0x5D, 0x41,
59ef6f ¤   0x9F, 0x9C, 0x7C, 0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA,
b2b5f1 ¤   0xAB, 0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x27, 0xC2, 0x65
f8af5a
fa82f7 };
5faf5a
264b17 static struct {
14b731 ¤   unsigned¤   bits;
aa8b0f ¤   PGPByte const *p;
9f6bfe ¤   unsigned¤   psize;
fcd1d3 ¤   PGPByte const *q;
21f42b ¤   unsigned¤   qsize;
acbd2d } DSAtab[] = {
19b177 #if 0
25c3da ¤   {1024, DSA1024p, sizeof(DSA1024p),
af055e ¤   ·¤  DSA1024q, sizeof(DSA1024q)},
--51c7 0003330316640100210 Page 4 of pgpFixedKey.c
a07454 #endif
097018 ¤   {1536, DSA1536p, sizeof(DSA1536p),
6e50ec ¤   ·¤  DSA1536q, sizeof(DSA1536q)},
590d3c ¤   {2048, DSA2048p, sizeof(DSA2048p),
ef6f02 ¤   ·¤  DSA2048q, sizeof(DSA2048q)},
5931b5 ¤   {3072, DSA3072p, sizeof(DSA3072p),
e9f68c ¤   ·¤  DSA3072q, sizeof(DSA3072q)},
6a7a28 ¤   {4096, DSA4096p, sizeof(DSA4096p),
042ddd ¤   ·¤  DSA4096q, sizeof(DSA4096q)}
0882f7 };
d8af5a
f1af5a
0b4e4a /* Return >0 if we find one, and fill in pointers, else return 0 */
724d2f int
13b0f9 pgpDSAfixed (unsigned bits, PGPByte const **p, size_t *plen,
ffa591 ¤   PGPByte const **q, size_t *qlen)
04bb36 {
b4743f ¤   unsigned i;
69af5a
24e276 ¤   for (i=0; i<sizeof(DSAtab)/sizeof(DSAtab[0]); ++i) {
0f87f4 ¤   ¤   if (DSAtab[i].bits > bits)
0f8144 ¤   ¤   ¤   return 0;
408119 ¤   ¤   if (DSAtab[i].bits == bits) {
b0ebe5 ¤   ¤   ¤   if (p)
686ac7 ¤   ¤   ¤   ¤   *p = DSAtab[i].p;
1dbf61 ¤   ¤   ¤   if (plen)
4e4d24 ¤   ¤   ¤   ¤   *plen = DSAtab[i].psize;
31b139 ¤   ¤   ¤   if (q)
b62014 ¤   ¤   ¤   ¤   *q = DSAtab[i].q;
cbbb4a ¤   ¤   ¤   if (qlen)
3789b5 ¤   ¤   ¤   ¤   *qlen = DSAtab[i].qsize;
8cdb98 ¤   ¤   ¤   return 1;
e60fe4 ¤   ¤   }
579371 ¤   }
923e6b ¤   return 0;
24efe6 }
12af5a
5caf5a
49af5a
2038e5 /*
5ae083 ·* Fixed p, g values for ElG keys. ·The p values are all "strong" primes,
9529fe ·* such that (p-1)/2 is also prime. ·This makes 2 an appropriate generator
da0d4e ·* in each case.
07495d ·*/
29af5a
a4b177 #if 0
116d1f static PGPByte const ElG1024p[] = {
207e5b ¤   0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
f96df6 ¤   0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
3fa996 ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
e802c5 ¤   0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
93a562 ¤   0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
a6aeb2 ¤   0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
9b1a67 ¤   0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
063a28 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
5693e7 ¤   0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
201936 ¤   0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
054ca3 ¤   0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
46d544 ¤   0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
8df48f ¤   0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
366c42 ¤   0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
44b3f9 ¤   0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
2199c5 ¤   0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2F, 0x78, 0xC7
a982f7 };
66aa69 static PGPByte const ElG1024g[] = {
819bb2 ¤   0x02
ca82f7 };
c37454 #endif
acaf5a
94d106 static PGPByte const ElG1536p[] = {
0adbe8 ¤   0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
3323ff ¤   0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
--128d 00028a5882f40100210 Page 5 of pgpFixedKey.c
418c6e ¤   0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
06e8b1 ¤   0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
febcaa ¤   0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
0d1b2c ¤   0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
05d844 ¤   0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
fe5734 ¤   0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
307e5b ¤   0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
d96df6 ¤   0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
21a996 ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
b602c5 ¤   0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
11a562 ¤   0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
b2aeb2 ¤   0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
eb1a67 ¤   0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
3c3a28 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
a093e7 ¤   0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
9d1936 ¤   0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
6e4ca3 ¤   0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
1cd544 ¤   0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
ecf48f ¤   0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
a26c42 ¤   0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
5eb3f9 ¤   0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
ca9bc3 ¤   0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x58, 0x7C, 0x47
1682f7 };
261670 static PGPByte const ElG1536g[] = {
3a9bb2 ¤   0x02
6e82f7 };
ee420c static PGPByte const ElG2048p[] = {
122ad3 ¤   0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
ae9520 ¤   0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
af8094 ¤   0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
e61cdb ¤   0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
1d3485 ¤   0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
75fcf9 ¤   0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
1ffc3f ¤   0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
fdab31 ¤   0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
1fdbe8 ¤   0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
f523ff ¤   0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
db8c6e ¤   0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
36e8b1 ¤   0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
41bcaa ¤   0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
b91b2c ¤   0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
61d844 ¤   0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
175734 ¤   0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
f47e5b ¤   0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
116df6 ¤   0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
67a996 ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
8b02c5 ¤   0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
44a562 ¤   0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
a2aeb2 ¤   0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
af1a67 ¤   0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
893a28 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
2793e7 ¤   0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
1b1936 ¤   0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
c64ca3 ¤   0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
60d544 ¤   0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
fff48f ¤   0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
656c42 ¤   0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
83b3f9 ¤   0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
f15bbd ¤   0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x32, 0x0B, 0x3B
5a82f7 };
5c857a static PGPByte const ElG2048g[] = {
3e9bb2 ¤   0x02
d282f7 };
b85700 static PGPByte const ElG3072p[] = {
7c87f4 ¤   0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2,
4935c1 ¤   0xC4, 0xF0, 0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E,
dc6ed5 ¤   0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB, 0x25, 0x0E,
9f184a ¤   0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
9ad50d ¤   0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
21cade ¤   0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60,
c29465 ¤   0xC3, 0xE3, 0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28,
2848c7 ¤   0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3, 0x65, 0x0F,
--cccd 00048d01bbb40100210 Page 6 of pgpFixedKey.c
729be2 ¤   0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
47ad70 ¤   0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
06556b ¤   0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4,
830300 ¤   0x40, 0xE9, 0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D,
2a7a4c ¤   0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68, 0x5E, 0x9D,
668524 ¤   0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
0f1356 ¤   0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
31b65f ¤   0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32,
8c2ad3 ¤   0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
579520 ¤   0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
ce8094 ¤   0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
9c1cdb ¤   0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
0d3485 ¤   0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
4efcf9 ¤   0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
88fc3f ¤   0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
6eab31 ¤   0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
d4dbe8 ¤   0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
5b23ff ¤   0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
998c6e ¤   0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
59e8b1 ¤   0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
c0bcaa ¤   0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
3a1b2c ¤   0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
d6d844 ¤   0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
8b5734 ¤   0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
fb7e5b ¤   0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
a06df6 ¤   0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
dca996 ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
3502c5 ¤   0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
76a562 ¤   0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
e8aeb2 ¤   0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
901a67 ¤   0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
aa3a28 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
6193e7 ¤   0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
f91936 ¤   0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
f14ca3 ¤   0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
9cd544 ¤   0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
f7f48f ¤   0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
646c42 ¤   0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
1cb3f9 ¤   0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
a3e534 ¤   0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x4C, 0x32, 0x6F
8e82f7 };
109076 static PGPByte const ElG3072g[] = {
b39bb2 ¤   0x02
c782f7 };
ac6b86 static PGPByte const ElG4096p[] = {
fa9154 ¤   0xF9, 0x18, 0xA0, 0x7E, 0x5A, 0x06, 0x61, 0x7A,
a37129 ¤   0x43, 0x90, 0x95, 0xDC, 0x05, 0x6C, 0x87, 0x86,
bcd5a7 ¤   0xEC, 0x61, 0xEC, 0xCD, 0x45, 0x1F, 0x0E, 0xD8,
57d134 ¤   0xE0, 0xA3, 0x79, 0xC6, 0xC9, 0xDC, 0x7A, 0x0B,
e0585e ¤   0xAC, 0xE4, 0x3F, 0xE3, 0x46, 0x94, 0xB6, 0x30,
b41739 ¤   0x4A, 0x53, 0xD7, 0x7C, 0x02, 0x16, 0x48, 0x80,
8962c4 ¤   0xB5, 0x15, 0xE5, 0x29, 0x99, 0xA9, 0x9F, 0x07,
877b51 ¤   0x74, 0xD3, 0xFF, 0xE3, 0xA1, 0xC5, 0x96, 0x20,
63c7ed ¤   0x4E, 0x98, 0x65, 0xB8, 0xD8, 0x0D, 0xEE, 0x10,
40920c ¤   0x5D, 0xAB, 0xB6, 0x17, 0x1C, 0x51, 0xD8, 0x50,
ed6bf8 ¤   0xCA, 0x22, 0x57, 0x43, 0x29, 0xBE, 0x95, 0xE8,
9ef245 ¤   0x56, 0x2B, 0x38, 0x78, 0x5C, 0x0B, 0xDB, 0xF8,
63e48c ¤   0x4C, 0x4D, 0xD5, 0xE3, 0xAA, 0x46, 0xCC, 0xFB,
ae05e7 ¤   0xCE, 0x17, 0xE8, 0x2A, 0x9D, 0x14, 0x61, 0xE3,
544fc6 ¤   0x84, 0xA9, 0x4F, 0xD1, 0x83, 0x84, 0xA8, 0x79,
69c04b ¤   0xB6, 0xEF, 0x8F, 0xA7, 0x43, 0x46, 0x08, 0xC6,
e287f4 ¤   0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2,
e435c1 ¤   0xC4, 0xF0, 0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E,
516ed5 ¤   0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB, 0x25, 0x0E,
62184a ¤   0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
12d50d ¤   0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
f9cade ¤   0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60,
369465 ¤   0xC3, 0xE3, 0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28,
0c48c7 ¤   0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3, 0x65, 0x0F,
b19be2 ¤   0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
c7ad70 ¤   0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
48556b ¤   0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4,
--8bad 0008f80f4d640100210 Page 7 of pgpFixedKey.c
3a0300 ¤   0x40, 0xE9, 0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D,
427a4c ¤   0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68, 0x5E, 0x9D,
098524 ¤   0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
871356 ¤   0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
77b65f ¤   0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32,
762ad3 ¤   0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
459520 ¤   0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
1d8094 ¤   0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
061cdb ¤   0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
173485 ¤   0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
9dfcf9 ¤   0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
e8fc3f ¤   0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
ebab31 ¤   0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
d2dbe8 ¤   0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
8623ff ¤   0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
e08c6e ¤   0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
d9e8b1 ¤   0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
79bcaa ¤   0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
0b1b2c ¤   0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
16d844 ¤   0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
585734 ¤   0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
3d7e5b ¤   0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
2c6df6 ¤   0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
02a996 ¤   0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
b302c5 ¤   0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
ffa562 ¤   0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
d5aeb2 ¤   0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
fc1a67 ¤   0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
1a3a28 ¤   0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
4493e7 ¤   0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
441936 ¤   0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
e54ca3 ¤   0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
c6d544 ¤   0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
1cf48f ¤   0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
266c42 ¤   0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
e7b3f9 ¤   0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
dd7aa2 ¤   0xA2, 0x5E, 0xC3, 0x55, 0xEB, 0x3D, 0xD6, 0x17
ba82f7 };
02acf0 static PGPByte const ElG4096g[] = {
8e9bb2 ¤   0x02
0582f7 };
25af5a
c64b17 static struct {
a5b731 ¤   unsigned¤   bits;
c78b0f ¤   PGPByte const *p;
8f6bfe ¤   unsigned¤   psize;
83829f ¤   PGPByte const *g;
d5192f ¤   unsigned¤   gsize;
27fbeb } ElGtab[] = {
20b177 #if 0
56b047 ¤   {1024, ElG1024p, sizeof(ElG1024p),
83becc ¤   ¤   ElG1024g, sizeof(ElG1024g)},
637454 #endif
8d0385 ¤   {1536, ElG1536p, sizeof(ElG1536p),
caeb7e ¤   ¤   ElG1536g, sizeof(ElG1536g)},
967ea1 ¤   {2048, ElG2048p, sizeof(ElG2048p),
2fd490 ¤   ¤   ElG2048g, sizeof(ElG2048g)},
a74228 ¤   {3072, ElG3072p, sizeof(ElG3072p),
be4d1e ¤   ¤   ElG3072g, sizeof(ElG3072g)},
4909b5 ¤   {4096, ElG4096p, sizeof(ElG4096p),
284483 ¤   ¤   ElG4096g, sizeof(ElG4096g)}
1d82f7 };
cfaf5a
fcaf5a
804e4a /* Return >0 if we find one, and fill in pointers, else return 0 */
ee4d2f int
482405 pgpElGfixed (unsigned bits, PGPByte const **p, size_t *plen,
0a9718 ¤   PGPByte const **g, size_t *glen)
eebb36 {
2d743f ¤   unsigned i;
eaaf5a
8fdd5b ¤   for (i=0; i<sizeof(ElGtab)/sizeof(ElGtab[0]); ++i) {
--0621 001312af19f40100210 Page 8 of pgpFixedKey.c
e3ded7 ¤   ¤   if (ElGtab[i].bits > bits)
a78144 ¤   ¤   ¤   return 0;
8869a9 ¤   ¤   if (ElGtab[i].bits == bits) {
70ebe5 ¤   ¤   ¤   if (p)
e82c01 ¤   ¤   ¤   ¤   *p = ElGtab[i].p;
9cbf61 ¤   ¤   ¤   if (plen)
cbedc8 ¤   ¤   ¤   ¤   *plen = ElGtab[i].psize;
67e275 ¤   ¤   ¤   if (g)
715d5d ¤   ¤   ¤   ¤   *g = ElGtab[i].g;
e6e100 ¤   ¤   ¤   if (glen)
578bc1 ¤   ¤   ¤   ¤   *glen = ElGtab[i].gsize;
ebdb98 ¤   ¤   ¤   return 1;
000fe4 ¤   ¤   }
7b9371 ¤   }
ec3e6b ¤   return 0;
44efe6 }
31af5a
--ea63 001a91c6d9940100211 Page 1 of pgpFixedKey.h
bc38e5 /*
70771d ·* A single, fixed PGP key for decryption operations.
18775e ·*
bb176d ·* $Id: pgpFixedKey.h,v 1.10 1997/09/30 21:03:01 lloyd Exp $
1a495d ·*/
87af5a
03e82c #include "pgpPubTypes.h"
ebadb8 #include "pgpOpaqueStructs.h"
c2af5a
0a99c6 PGP_BEGIN_C_DECLARATIONS
25af5a
607a0b /* Return > 0 if find fixed prime params of the specified size, 0 if not */
644d2f int
37b0f9 pgpDSAfixed (unsigned bits, PGPByte const **p, size_t *plen,
128585 ¤   PGPByte const **q, size_t *qlen);
d94d2f int
ea2405 pgpElGfixed (unsigned bits, PGPByte const **p, size_t *plen,
ae9c7e ¤   PGPByte const **g, size_t *glen);
0caf5a
11af5a
a91254 PGP_END_C_DECLARATIONS
--7633 0002bbc72c840100212 Page 1 of pgpKeyMisc.c
bc38e5 /*
b07ee5 ·* pgpKeyMisc.c
f132c4 ·* Miscellaneous helper functions for public key modules.
7e1528 ·* Including packing and unpacking for PKCS compatibility.
38775e ·*
36549e ·* $Id: pgpKeyMisc.c,v 1.28 1998/02/24 22:38:23 hal Exp $
a1495d ·*/
54af5a
6baf5a
4ae2ff #include "pgpConfig.h"
95324c #include <string.h>
5baf5a
1fd92d #include <stdarg.h>
d7af5a
42a146 #include "pgpDebug.h"
85007f #include "pgpKeyMisc.h"
d539fc #include "bn.h"
411e2d #include "pgpCFBPriv.h"
5b0e2f #include "pgpSymmetricCipherPriv.h"
2542aa #include "pgpPublicKey.h"
115417 #include "pgpHashPriv.h"
bd0d08 #include "pgpMem.h"
952f8d #include "pgpErrors.h"
a8cdc2 #include "pgpPubKey.h"
302c96 #include "pgpRandomX9_17.h"
a35579 #include "pgpStr2Key.h"
28d11f #include "pgpUsuals.h"
3e4919 #include "pgpUtilities.h"
5f0d6d #include "pgpEnv.h"
26af5a
dd4d60 #ifndef PKCS_COMPAT
99d0d0 #define PKCS_COMPAT 1
f77454 #endif
02af5a
ebaf5a
6038e5 /*
bb1ed5 ·* Given a number of bits in a modulus, compute the minimum exponent size
36047b ·* needed to provide equivalent security from small-exponent attacks.
f901bf ·* Adding padding on top of this is not an entirely evil idea.
ab775e ·*
94cd9c ·* This is based on a paper from Michael Wiener ··| This extension to
651e76 ·* on the difficulty of the two attacks, which ···| the table is not
df96ad ·* the following table: ··························| part of the original.
0f9ae5 ·* ···············································|
96561a ·* ··Table 1: Subgroup Sizes to Match Field Sizes | ··THIS FUNCTION
599ae5 ·* ···············································|
ba0851 ·* ·Size of p ··Cost of each attack ···Size of q ·| ·Output ··Error
48ba33 ·* ··(bits) ····(instructions or ·······(bits) ···| ········(+ is safe)
eb45ae ·* ··············modular multiplies) ·············|
629ae5 ·* ···············································|
d42bc3 ·* ····512 ··········9 x 10^17 ··········119 ·····| ··137 ·····+18
1a0bad ·* ····768 ··········6 x 10^21 ··········145 ·····| ··153 ·····+8
5e8aeb ·* ···1024 ··········7 x 10^24 ··········165 ·····| ··169 ·····+4
e48f90 ·* ···1280 ··········3 x 10^27 ··········183 ·····| ··184 ·····+1
27e38b ·* ···1536 ··········7 x 10^29 ··········198 ·····| ··198 ·····+0
20eb00 ·* ···1792 ··········9 x 10^31 ··········212 ·····| ··212 ·····+0
bdf948 ·* ···2048 ··········8 x 10^33 ··········225 ·····| ··225 ·····+0
8944c5 ·* ···2304 ··········5 x 10^35 ··········237 ·····| ··237 ·····+0
cd7a94 ·* ···2560 ··········3 x 10^37 ··········249 ·····| ··249 ·····+0
b3e50f ·* ···2816 ··········1 x 10^39 ··········259 ·····| ··260 ·····+1
bb1363 ·* ···3072 ··········3 x 10^40 ··········269 ·····| ··270 ·····+1
d7364e ·* ···3328 ··········8 x 10^41 ··········279 ·····| ··280 ·····+1
c5cda1 ·* ···3584 ··········2 x 10^43 ··········288 ·····| ··289 ·····+1
af8d6e ·* ···3840 ··········4 x 10^44 ··········296 ·····| ··297 ·····+1
c915e8 ·* ···4096 ··········7 x 10^45 ··········305 ·····| ··305 ·····+0
ac39f4 ·* ···4352 ··········1 x 10^47 ··········313 ·····| ··313 ·····+0
a5203f ·* ···4608 ··········2 x 10^48 ··········320 ·····| ··321 ·····+1
704ba1 ·* ···4864 ··········2 x 10^49 ··········328 ·····| ··329 ·····+1
70c3f5 ·* ···5120 ··········3 x 10^50 ··········335 ·····| ··337 ·····+2
b5775e ·*
48ae7e ·* This function fits a curve to this, which overestimates the size
2b244c ·* of q required, but by a very small amount in the important 1000-4000
--a490 000cdb15f1340100212 Page 2 of pgpKeyMisc.c
0d8c8b ·* bit range. ·It is a quadratic curve up to 3840 bits, and a linear
69493b ·* curve past that. ·They are designed to be C(1) (have the same value
bcf316 ·* and the same slope) at the point where they meet.
cf495d ·*/
02b213 #define AN ·····1 ······/* a = -AN/AD/65536, the quadratic coefficient */
223a19 #define AD ·····3
1e2455 #define M ······8 ······/* Slope = M/256, i.e. 1/32 where linear starts */
fa8116 #define TX ·····3840 ···/* X value at the slope point, where linear starts */
245cba #define TY ·····297 ····/* Y value at the slope point, where linear starts */
aa38e5 /*
8a55cf ·* For a slope of M at the point (TX,TY), we only have one degree of
cb9864 ·* freedom left in a quadratic curve, so use the coefficient of x^2,
65653b ·* namely a, as that free parameter.
27775e ·*
7da1a6 ·* y = -AN/AD*((x-TX)/256)^2 + M*(x-TX)/256 + TY
1a9ae4 ·* ··= -AN*(x-TX)*(x-TX)/AD/256/256 + M*x/256 - M*TX/256 + TY
7751e3 ·* ··= -AN*x*x/AD/256/256 + 2*AN*x*TX/AD/256/256 - AN*TX*TX/AD/256/256 \
f7291f ·* ·····+ M*x/256 - M*TX/256 + TY
3f3c3d ·* ··= -AN*(x/256)^2/AD + 2*AN*(TX/256)*(x/256)/AD + M*(x/256) \
b5141c ·* ·····- AN*(TX/256)^2/AD - M*(TX/256) + TY
32279c ·* ··= (AN*(2*TX/256 - x/256) + M*AD)*x/256/AD - (AN*(TX/256)/AD + M)*TX/256 \
36dd11 ·* ·····+ TY
7020e7 ·* ··= (AN*(2*TX/256 - x/256) + M*AD)*x/256/AD \
ccc0a9 ·* ·····- (AN*(TX/256) + M*AD)*TX/256/AD + TY
fdc706 ·* ··= ·((M*AD + AN*(2*TX/256 - x/256))*x - (AN*(TX/256)+M*AD)*TX)/256/AD + TY
7db42f ·* ··= ·((M*AD + AN*(2*TX - x)/256)*x - (AN*(TX/256)+M*AD)*TX)/256/AD + TY
441e36 ·* ··= ·((M*AD + AN*(2*TX - x)/256)*x - (M*AD + AN*TX/256)*TX)/256/AD + TY
d5da33 ·* ··= ·(((256*M*AD+2*AN*TX-AN*x)/256)*x - (M*AD + AN*TX/256)*TX)/256/AD + TY
0d775e ·*
4cc76d ·* Since this is for the range 0...TX, in order to avoid having any
ec47b4 ·* intermediate results less than 0, we need one final rearrangement, and
6186fb ·* a compiler can easily take the constant-folding from there...
c7775e ·*
a259d0 ·* ··= ·TY + (((256*M*AD+2*AN*TX-AN*x)/256)*x - (M*AD + AN*TX/256)*TX)/256/AD
728f5c ·* ··= ·TY - ((M*AD + AN*TX/256)*TX - ((256*M*AD+2*AN*TX-AN*x)/256)*x)/256/AD
18495d ·*/
55af5a
de6897 #define BITS(x) \
1bcea2 ········TY - ((M*AD + AN*TX/256)*TX - ((256*M*AD+AN*2*TX-AN*x)/256)*x)/(AD*256)
8aaf5a
f2536c unsigned
fb647e pgpDiscreteLogExponentBits(unsigned modbits)
13bb36 {
ba50da ¤   unsigned expbits;
1daf5a
7caa45 ¤   if (modbits > TX)
1d3137 ¤   ¤   expbits = M*modbits/256 - M*TX/256 + TY; ···/* Linear */
2d0e24 ¤   else
2eda54 ¤   ¤   expbits = BITS(modbits); ······/* Quadratic */
5da65d ¤   return expbits;
bfefe6 }
8daf5a
6fd5ae /* For the Q prime in the DSA, we round up to a multiple of 8 bits.
81eeed ·* That way when we make the signature, we can bring our hash output over
e9c9ff ·* in a multiple of bytes.
9f495d ·*/
fd536c unsigned
08a8e3 pgpDiscreteLogQBits(unsigned modbits)
74bb36 {
a9afef ¤   return ((pgpDiscreteLogExponentBits(modbits)+7)/8)*8;
aaefe6 }
aaaf5a
c118ab #undef BITS
f6a18c #undef TY
acb854 #undef TX
8f8479 #undef M
e9384d #undef AD
02c53d #undef AN
1daf5a
1038e5 /*
95d0cb ·* Fill the given bignum, from bytes high-1 through low (where 0 is
cddbff ·* the least significant byte), with non-zero random data.
--e329 000c2e8943d40100212 Page 3 of pgpKeyMisc.c
47495d ·*/
7dbeb7 static int
857ae6 randomPad(PGPRandomContext const *rc, BigNum *bn,
cdff35 ¤   unsigned high, unsigned low)
97bb36 {
bcd112 ¤   unsigned i, l;
9cb4f6 ¤   PGPByte padding[64]; ··/* This can be any size (>0) whatsoever */
8aaf5a
8b2c8d ¤   high -= low;
4c57e4 ¤   while (high) {
9ebae0 ¤   ¤   l = high < sizeof(padding) ? high : sizeof(padding);
22fac6 ¤   ¤   pgpRandomGetBytes(rc, padding, l);
af8471 ················for (i = 0; i < l; i++) { ······/* Replace all zero bytes */·
cc172d ························while(padding[i] == 0)
81430c ¤   ¤   ¤   ¤   pgpRandomGetBytes(rc, padding+i, 1);
ed6f5c ················}
12078d ¤   ¤   high -= l;
ac1177 ¤   ¤   if (bnInsertBigBytes(bn, padding, high+low, l) < 0)
d27cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
999371 ¤   }
b9af5a
42b497 ¤   pgpClearMemory( padding, ·sizeof(padding));
083e6b ¤   return 0;
41efe6 }
53af5a
a938e5 /*
0dd0cb ·* Fill the given bignum, from bytes high-1 through low (where 0 is
05f754 ·* the least significant byte), with all ones (0xFF) data.
61495d ·*/
98beb7 static int
fc66bf onesPad(BigNum *bn, unsigned high, unsigned low)
43bb36 {
f74d82 ¤   unsigned l;
8fdba8 ¤   static PGPByte const padding[] = {
47762c ¤   ¤   255,255,255,255,255,255,255,255,
40c71b ¤   ¤   255,255,255,255,255,255,255,255
fd62bd ¤   };
22af5a
862c8d ¤   high -= low;
8c57e4 ¤   while (high) {
0fbae0 ¤   ¤   l = high < sizeof(padding) ? high : sizeof(padding);
f6078d ¤   ¤   high -= l;
a41177 ¤   ¤   if (bnInsertBigBytes(bn, padding, high+low, l) < 0)
097cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
549371 ¤   }
e43e6b ¤   return 0;
8defe6 }
a2af5a
80af5a
8b38e5 /*
3edbd6 ·* The Basic Encoding Rules (of which the Distinguished Encoding Rules
a6cee6 ·* are a simple minimal-sized subset) are supposed to be compact. ·Humph.
8e315e ·* Maybe they are, but the ASN.1 they're encoding is less than concise.
ba5e06 ·* It's sequence(sequence(object_id(1.2.840.113549.2.5)),octet_string(...))
73495d ·*/
52f581 static PGPByte const MD5_prefix[] = {
f7eef2 ¤   0x30, /* Universal, Constructed, Sequence */
81de2a ¤   0x20, /* Length 32 (bytes following) */
62bde9 ¤   ¤   0x30, /* Universal, Constructed, Sequence */
329f04 ¤   ¤   0x0c, /* Length 12 */
106507 ¤   ¤   ¤   0x06, /* Universal, Primitive, object-identifier */
45745e ¤   ¤   ¤   0x08, /* Length 8 */
175b93 ¤   ¤   ¤   ¤   0x2a, /* 42 = ISO(1)*40 + Member bodies(2) */
43adb4 ¤   ¤   ¤   ¤   0x86, 0x48, /* 840 = US (ANSI) */
43bc6f ¤   ¤   ¤   ¤   0x86, 0xF7, 0x0D, /* 113549 = RSADSI */
3e2e94 ¤   ¤   ¤   ¤   0x02, /* 2 = Hash functions */
131a63 ¤   ¤   ¤   ¤   0x05, /* 5 = MD5 */
a6c238 ¤   ¤   ¤   0x05, /* Universal, Primitive, NULL */
51d131 ¤   ¤   ¤   0x00, /* Length 0 */
796fe2 ¤   ¤   0x04, /* Universal, Primitive, Octet string */
e8ca9a ¤   ¤   0x10 /* Length 16 */
c20921 ¤   ¤   ¤   /* 16 MD5 digest bytes go here */
--0e3f 000eb0a87e340100212 Page 4 of pgpKeyMisc.c
8082f7 };
abaf5a
6ba8d9 /* This is the PGP 2.2 MD5 identification byte */
901668 static PGPByte const pgp22_MD5_byte = 1;
87af5a
54af5a
e638e5 /*
d63f1f ·* Wrap a PKCS wrapper around some data.
16b188 ·* Type 1 is for signature, type 2 for encryption.
5b775e ·*
222cd5 ·* Type 2 wrappers:
ad775e ·*
6b7aaf ·* If the modulus is n bytes long, with the most significant byte
567cd7 ·* being n-1 and the least significant, 0, the wrapper looks like:
02775e ·*
d8bc89 ·* Position ····Value ··Function
267444 ·* n-1 ··········0 ·····This is needed to ensure that the padded number
2f3c59 ·* ·····················is less than the modulus.
4ca236 ·* n-2 ··········2 ·····The padding type (non-zero random).
1d7081 ·* n-3..len+1 ··??? ····Non-zero random padding bytes to "salt" the
5eb9d8 ·* ·····················output and prevent duplicate plaintext attacks.
7e20ea ·* len ··········0 ·····Zero byte to mark the end of the padding
76ee04 ·* len-1..0 ····data ···Supplied payload data.
a4775e ·*
e7775e ·*
21d35f ·* In the case of PGP, the payload is a byte indicating the type of
fa9de9 ·* conventional cipher, currently always set to 1 to indicate IDEA,
9907ca ·* and a 16-byte IDEA key followed by a 16-bit checksum.
29775e ·*
93a502 ·* Versions of PGP up to 2.2 generated a "broken" version of this format,
c5f5cc ·* which had the components (except for the most significant zero byte)
a23a77 ·* in the opposite order. ·This is controlled by PKCS_COMPAT.
2a9233 ·* There's no security difference, it's just nice if everyone does it
565f72 ·* the same way.
6a775e ·*
303cdf ·* Position ····Value
a821d3 ·* n-1 ··········0
60368e ·* n-2..n-len-1 data ···Supplied payload data.
787cbf ·* n-len-2 ······0 ·····Zero byte to mark the end of the padding
07c5e3 ·* n-len-3..1 ··??? ····Non-zero random padding bytes to "salt" the
60b9d8 ·* ·····················output and prevent duplicate plaintext attacks.
3a6ff7 ·* 0 ············2 ·····The padding type (non-zero random).
c1775e ·*
97b7e5 ·* On decryption, the fact that the first (most significant) byte of
635e29 ·* payload data is 1 for the <= 2.2 format, and a padding type of 1
3445e4 ·* (fixed, all ones) is never used for public-key encryption lets
7bbf60 ·* these be distinguished.
4a775e ·*
b19fbe ·* There really should be several bytes of padding, although this
3aaadd ·* routine will not fail to encrypt unless it will not fit, even
9bde05 ·* with no padding bytes.
45775e ·*
06775e ·*
76e255 ·* Type 1 padding:
dc775e ·*
f0775e ·*
a0c1ba ·* The type is 1, and the padding is all 1's
4484e0 ·* (hex 0xFF). ·In addition, if the data is a DER-padded MD5 hash, there's
7600d7 ·* an option for encoding it with the old PGP 2.2 format, in which case
76dd55 ·* that's all replaced by a 1 byte indicating MD5.
ce775e ·*
50ccb6 ·* When decrypting, distinguishing these is a bit trickier, since the
bd097f ·* second most significant byte is 1 in both cases, but in general,
fecd97 ·* it could only cause confusion if the PGP hash were all 1's.
4e775e ·*
eb95b6 ·* To summarize, the formats are:
bc775e ·*
e5bc89 ·* Position ····Value ··Function
3e7444 ·* n-1 ··········0 ·····This is needed to ensure that the padded number
d33c59 ·* ·····················is less than the modulus.
b812fd ·* n-2 ··········1 ·····The padding type (all ones).
eb6014 ·* n-3..len+1 ··255 ····All ones padding to ensure signatures are rare.
--b3a5 00074805e4140100212 Page 5 of pgpKeyMisc.c
6120ea ·* len ··········0 ·····Zero byte to mark the end of the padding
c43a50 ·* len-1..x ····ASN.1¤  The ASN.1 DER magic cookie (18 bytes)
1e38d8 ·* x-1..0 ······data ···The payload MD5 hash (16 bytes).
3e775e ·*
11775e ·*
cc3cdf ·* Position ····Value
cf21d3 ·* n-1 ··········0
4fa982 ·* n-2 ··········1¤ "This is MD5"
ba6738 ·* n-2..n-len-2 data ···Supplied payload MD5 hash (len == 16).
0e7cbf ·* n-len-2 ······0 ·····Zero byte to mark the end of the padding
024a94 ·* n-len-3..1 ··255 ····All ones padding.
8e639e ·* 0 ············1 ·····The padding type (all ones).
85775e ·*
5a775e ·*
3a8d13 ·* The reason for the all 1's padding is an extra consistency check.
59d40a ·* A randomly invented signature will not decrypt to have the long
13862f ·* run of ones necessary for acceptance.
f7775e ·*
27c57f ·* Oh... the public key isn't needed to decrypt, but it's passed in
63ae49 ·* because a different glue library may need it for some reason.
c0775e ·*
a71fc2 ·* TODO: Have the caller put on the PKCS wrapper. ·We can notice and
c265c3 ·* strip it off if we're trying to be compatible.
55495d ·*/
71af5a
cf4d2f int
1b7a80 pgpPKCSPack(BigNum *bn, PGPByte const *in, unsigned len, PGPByte padtype,
93ee5e ¤   unsigned bytes, PGPRandomContext const *rc)
14bb36 {
77958a ¤   if (len+3 > bytes)
ca2194 ¤   ¤   return kPGPError_PublicKeyTooSmall;¤/* data won't fit in pubkey! */
efaf5a
02285d ¤   /* Set the entire number to 0 to start */
2ff43e ¤   (void)bnSetQ(bn, 0);
ab67c5 ¤
ad7888 ¤   if (padtype == PKCS_PAD_ENCRYPTED) {
1e9c69 ¤   ¤   /* Random padding */
d40ac0 ¤   ¤   if (PKCS_COMPAT || in[0] != 1) {
e5c2f8 ¤   ¤   ¤   if (bnInsertBigBytes(bn, &padtype, bytes-2, 1) < 0 ||
9b0ef8 ¤   ¤   ¤   ····randomPad(rc, bn, bytes-2, len+1) < 0 ||
6a89d9 ¤   ¤   ¤   ····bnInsertBigBytes(bn, in, 0, len) < 0)
05451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
f945a6 ¤   ¤   } else {
2f1c34 ¤   ¤   ¤   /* Old <= 2.2 broken format */
447ba6 ¤   ¤   ¤   if (bnInsertBigBytes(bn, in, bytes-len-1, len) < 0 ||
9ff4b9 ¤   ¤   ¤   ····randomPad(rc, bn, bytes-len-2, 1) < 0 ||
e72791 ¤   ¤   ¤   ····bnInsertBigBytes(bn, &padtype, 0, 1) < 0)
ea451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
c80fe4 ¤   ¤   }
0ef037 ¤   } else {
ca0d40 ¤   ¤   pgpAssert (padtype == PKCS_PAD_SIGNED);
e64d8d ¤   ¤   /* Constant padding */
066acb ¤   ¤   if (PKCS_COMPAT
eaf26d ¤   ¤   ····|| len != sizeof(MD5_prefix)+16
a328a5 ¤   ¤   ····|| memcmp(in, MD5_prefix, sizeof(MD5_prefix)) != 0)
a35b34 ¤   ¤   {
72c2f8 ¤   ¤   ¤   if (bnInsertBigBytes(bn, &padtype, bytes-2, 1) < 0 ||
63b65b ¤   ¤   ¤   ····onesPad(bn, bytes-2, len+1) < 0 ||
e789d9 ¤   ¤   ¤   ····bnInsertBigBytes(bn, in, 0, len) < 0)
1d451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
a445a6 ¤   ¤   } else {
157940 ¤   ¤   ¤   /* Old <= 2.2 format - no DER prefix */
c477ab ¤   ¤   ¤   len -= sizeof(MD5_prefix);
914d9d ¤   ¤   ¤   in += sizeof(MD5_prefix);
890f27 ¤   ¤   ¤   if (len+3+1 > bytes)
c007b4 ¤   ¤   ¤   ¤   return kPGPError_PublicKeyTooSmall;¤/* won't fit */
0c8f22 ¤   ¤   ¤   if (bnInsertBigBytes(bn, &pgp22_MD5_byte, bytes-1, 1)
81f3de ¤   ¤   ¤   ¤   ¤   < 0 ||
70af83 ¤   ¤   ¤   ····bnInsertBigBytes(bn, in, bytes-len-2, len) < 0 ||
b44c1a ¤   ¤   ¤   ····onesPad(bn, bytes-len-2, 1) < 0 ||
252791 ¤   ¤   ¤   ····bnInsertBigBytes(bn, &padtype, 0, 1) < 0)
74451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
--ab1b 0000cc9ea1440100212 Page 6 of pgpKeyMisc.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
f53e6b ¤   return 0;
b6efe6 }
abaf5a
65af5a
5738e5 /*
f532c5 ·* Searches bytes, beginning with start-1 and progressing to 0,
a8f767 ·* until one that is not 0xff is found. ·The idex of the last 0xff
0d78c4 ·* byte is returned (or start if start-1 is not 0xff.)
0c495d ·*/
6065bf static unsigned
c8790c bnSearchNonOneFromHigh(BigNum const *bn, unsigned start)
edbb36 {
5ec0aa ¤   PGPByte buf[16];¤   /* Size is arbitrary */
f34d82 ¤   unsigned l;
15743f ¤   unsigned i;
b2af5a
823984 ¤   while (start) {
031a70 ¤   ¤   l = start < sizeof(buf) ? start : sizeof(buf);
f7f0b4 ¤   ¤   start -= l;
73e965 ¤   ¤   bnExtractBigBytes(bn, buf, start, l);
5116fb ¤   ¤   for (i = 0; i < l; i++) {
ac0d6b ¤   ¤   ¤   if (buf[i] != 0xff) {
1b77fd ¤   ¤   ¤   ¤   pgpClearMemory( buf, ·sizeof(buf));
af5891 ¤   ¤   ¤   ¤   return start + l - i;
7ba3a6 ¤   ¤   ¤   }
630fe4 ¤   ¤   }
c29371 ¤   }
6bf787 ¤   /* Nothing found */
c0718a ¤   pgpClearMemory( buf, ·sizeof(buf));
b23e6b ¤   return 0;
05efe6 }
d6af5a
6c38e5 /*
bd2d4a ·* Searches bytes, beginning with start and going up (towards more
fc2412 ·* significant bytes), until one that is not 0xff is found. ·Since the
c77805 ·* input number is finite, there must be zeros eventually.
eba704 ·* The index of the first non-0xff byte is returned.
18495d ·*/
e665bf static unsigned
d13e8a bnSearchNonOneFromLow(BigNum const *bn, unsigned start)
04bb36 {
87c0aa ¤   PGPByte buf[16];¤   /* Size is arbitrary */
2d743f ¤   unsigned i;
6faf5a
32220e ¤   for (;;) {
75ff96 ¤   ¤   bnExtractBigBytes(bn, buf, start, sizeof(buf));
bcc367 ¤   ¤   i = sizeof(buf);
2cd1f3 ¤   ¤   start += i;
a34392 ¤   ¤   do {
835ee0 ¤   ¤   ¤   if (buf[--i] != 0xff) {
2e77fd ¤   ¤   ¤   ¤   pgpClearMemory( buf, ·sizeof(buf));
e8490c ¤   ¤   ¤   ¤   return start - i - 1;
9ba3a6 ¤   ¤   ¤   }
ed253a ¤   ¤   } while (i);
0b9371 ¤   }
82cc6f ¤   /*NOTREACHED*/
d6efe6 }
d8af5a
abaf5a
cdaf5a
3038e5 /*
5432c5 ·* Searches bytes, beginning with start-1 and progressing to 0,
cbebca ·* until finding one that is zero, or the end of the array.
582295 ·* The index of the last non-zero byte is returned (0 if the array
c73cf5 ·* is all non-zero, or start if start-1 is zero).
bc495d ·*/
2965bf static unsigned
3a839b bnSearchZeroFromHigh(BigNum const *bn, unsigned start)
a4bb36 {
0cc0aa ¤   PGPByte buf[16];¤   /* Size is arbitrary */
--7020 0005a8fca5c40100212 Page 7 of pgpKeyMisc.c
324d82 ¤   unsigned l;
45743f ¤   unsigned i;
dcaf5a
933984 ¤   while (start) {
201a70 ¤   ¤   l = start < sizeof(buf) ? start : sizeof(buf);
49f0b4 ¤   ¤   start -= l;
93e965 ¤   ¤   bnExtractBigBytes(bn, buf, start, l);
1e16fb ¤   ¤   for (i = 0; i < l; i++) {
b14311 ¤   ¤   ¤   if (buf[i] == 0) {
b777fd ¤   ¤   ¤   ¤   pgpClearMemory( buf, ·sizeof(buf));
8b5891 ¤   ¤   ¤   ¤   return start + l - i;
36a3a6 ¤   ¤   ¤   }
050fe4 ¤   ¤   }
a49371 ¤   }
85f787 ¤   /* Nothing found */
de718a ¤   pgpClearMemory( buf, ·sizeof(buf));
e23e6b ¤   return 0;
96efe6 }
01af5a
8938e5 /*
9e2d4a ·* Searches bytes, beginning with start and going up (towards more
ebaa91 ·* significant bytes), until one that is zero is found. ·Since the
9a7805 ·* input number is finite, there must be zeros eventually.
2e82ab ·* The index of the first zero byte is returned.
61495d ·*/
a765bf static unsigned
894ea7 bnSearchZeroFromLow(BigNum const *bn, unsigned start)
79bb36 {
88c0aa ¤   PGPByte buf[16];¤   /* Size is arbitrary */
8e743f ¤   unsigned i;
5faf5a
8b220e ¤   for (;;) {
23ff96 ¤   ¤   bnExtractBigBytes(bn, buf, start, sizeof(buf));
bec367 ¤   ¤   i = sizeof(buf);
acd1f3 ¤   ¤   start += i;
bd4392 ¤   ¤   do {
95b243 ¤   ¤   ¤   if (buf[--i] == 0) {
0177fd ¤   ¤   ¤   ¤   pgpClearMemory( buf, ·sizeof(buf));
f0490c ¤   ¤   ¤   ¤   return start - i - 1;
e9a3a6 ¤   ¤   ¤   }
76253a ¤   ¤   } while (i);
4f9371 ¤   }
4acc6f ¤   /*NOTREACHED*/
6defe6 }
aaaf5a
4238e5 /*
c863e0 ·* Performs a PKCS unpack operation. ·Returns a prefix of the unwrapped
58140d ·* data in the given buf. ·Returns the length of the untruncated
af5d6b ·* data, which may exceed "len". Returns <0 on error.
e6775e ·*
095606 ·* For the constant-padding (signature checking) case,
25e274 ·* it recongizes the PGP 2.2 format, but not in all its generality;
00f6d9 ·* only the one case (framing byte = 1, length = 16) which was ever
a852b7 ·* generated. ·It fakes the DER prefix in that case.
59495d ·*/
474d2f int
148865 pgpPKCSUnpack(PGPByte *buf, unsigned len, BigNum *bn, PGPByte padtype,
41d682 ¤   unsigned bytes)
e7bb36 {
ec51f7 ¤   PGPByte tmp[2];
40af5a
a870ad ¤   bnExtractBigBytes(bn, tmp, bytes-2, 2);
dfe43a ¤   if (tmp[0] != 0) {
c79638 ¤   ¤   pgpClearMemory( tmp, ·2);
1d85dd ¤   ¤   return kPGPError_CorruptData;
b19371 ¤   }
0faf5a
767888 ¤   if (padtype == PKCS_PAD_ENCRYPTED) {
4f7b85 ¤   ¤   /* Decryption case, random padding */
d21e58 ¤   ¤   /* Special case: PGP <= 2.2 hack */
324631 ¤   ¤   bnExtractBigBytes(bn, tmp, 0, 1);
5a626a ¤   ¤   if (tmp[1] == 1 && tmp[0] == padtype &&
--4940 000d8b7956240100212 Page 8 of pgpKeyMisc.c
68eb03 ¤   ¤   ····bnSearchZeroFromLow(bn, 1) == bytes-1-1-16-2-1)
245b34 ¤   ¤   {
1b061a ¤   ¤   ¤   /* Aha, it's PGP <= 2.2 */
cd8704 ¤   ¤   ¤   if (len > 1+16+2)
19f59f ¤   ¤   ¤   ¤   len = 1+16+2;
861f41 ¤   ¤   ¤   bnExtractBigBytes(bn, buf, bytes-1-len, len);
b76d2d ¤   ¤   ¤   return 1+16+2;
320fe4 ¤   ¤   }
5aaf5a
36c137 ¤   ¤   /* Okay, assume it's PKCS.1 */
7c45c2 ¤   ¤   if (tmp[1] != 2) {
ac794b ¤   ¤   ¤   pgpClearMemory( tmp, ·2);
7bb933 ¤   ¤   ¤   return kPGPError_CorruptData;
080fe4 ¤   ¤   }
299638 ¤   ¤   pgpClearMemory( tmp, ·2);
9baf5a
7fe076 ¤   ¤   bytes = bnSearchZeroFromHigh(bn, bytes-2);
a7e90a ¤   ¤   if (bytes-- == 0)
d7b933 ¤   ¤   ¤   return kPGPError_CorruptData;
f5f037 ¤   } else {
13ddf5 ¤   ¤   pgpAssert (padtype==PKCS_PAD_SIGNED);
cad765 ¤   ¤   /* Signature check, constant padding */
40ebeb ¤   ¤   if (tmp[1] != padtype) {
399c19 ¤   ¤   ¤   pgpClearMemory( tmp, ·sizeof(tmp));
bfb933 ¤   ¤   ¤   return kPGPError_CorruptData;
1f0fe4 ¤   ¤   }
1baf5a
e01b17 ¤   ¤   /*
972ee4 ¤   ¤   ·* Special-case hack: is is PGP <= 2.2 format?¤ This is
d5db49 ¤   ¤   ·* identified by a least significant byte of 1, a byte
1685cd ¤   ¤   ·* of 0 between the 16-byte MD5 hash and the padding,
e81936 ¤   ¤   ·* and all ones padding.
fc9de3 ¤   ¤   ·*/
1b7e06 ¤   ¤   bnExtractBigBytes(bn, tmp, 0, 1); ·/* Should be 1 if <= 2.2 */
fa9d74 ¤   ¤   bnExtractBigBytes(bn, tmp+1, bytes-19, 1); /* zero if <= 2.2 */
58af5a
d78253 ¤   ¤   if (tmp[0] == padtype && tmp[1] == 0 &&
c65e3f ¤   ¤   ····bnSearchNonOneFromLow(bn, 1) == bytes-19)
e85b34 ¤   ¤   {
96c47e ¤   ¤   ¤   /* Aha, it's PGP <= 2.2 - fake up the DER prefix */
8bc580 ¤   ¤   ¤   if (len <= sizeof(MD5_prefix)) {
a9b7ac ¤   ¤   ¤   ¤   memcpy(buf, MD5_prefix, len);
bd042d ¤   ¤   ¤   } else {
b51cf3 ¤   ¤   ¤   ¤   memcpy(buf, MD5_prefix, sizeof(MD5_prefix));
1da4b5 ¤   ¤   ¤   ¤   buf += sizeof(MD5_prefix);
3579e7 ¤   ¤   ¤   ¤   len -= sizeof(MD5_prefix);
5d3a02 ¤   ¤   ¤   ¤   if (len > 16)
1af5ca ¤   ¤   ¤   ¤   ¤   len = 16;
00f3b6 ¤   ¤   ¤   ¤   bnExtractBigBytes(bn, buf, bytes-2-len, len);
46a3a6 ¤   ¤   ¤   }
a40fef ¤   ¤   ¤   return 16 + sizeof(MD5_prefix);
b50fe4 ¤   ¤   }
23af5a
e90f44 ¤   ¤   /* Okay, assume it's PKCS format thing. */
faaf5a
91cd47 ¤   ¤   bytes = bnSearchNonOneFromHigh(bn, bytes-2);
7186bf ¤   ¤   if (bytes < 1)
fbb933 ¤   ¤   ¤   return kPGPError_CorruptData;
d5fb89 ¤   ¤   bytes--;
e10f25 ¤   ¤   tmp[1] = 0;
335daf ¤   ¤   bnExtractBigBytes(bn, tmp, bytes, 1);
3d06db ¤   ¤   if (tmp[0] != 0) {
c59c19 ¤   ¤   ¤   pgpClearMemory( tmp, ·sizeof(tmp));
2ab933 ¤   ¤   ¤   return kPGPError_CorruptData;
8e0fe4 ¤   ¤   }
f7148b ¤   ¤   /* Note: tmp isn't secret any more because it's a constant! */
4c9371 ¤   }
3faf5a
1a7a28 ¤   /* Success! Return the data */
b1338f ¤   if (len > bytes)
b5b25c ¤   ¤   len = bytes;
d8243a ¤   bnExtractBigBytes(bn, buf, bytes-len, len);
--acb7 000fe8d379740100212 Page 9 of pgpKeyMisc.c
dc91a3 ¤   return bytes;
fdefe6 }
50af5a
ca38e5 /*
7ec79a ·* Convert a big-endian byte buffer (with bit-count prefix) to an MPI.
fb31a4 ·* Returns number of bytes read from buffer, or <= 0 on error.
e73663 ·* (Returns 0 if the buffer is too short.)
a6495d ·*/
464d2f int
352bb3 pgpBnGetPlain(BigNum *bn, PGPByte const *buf, unsigned size)
28bb36 {
170ed5 ¤   unsigned t;
51af5a
e70fc2 ¤   if (size < 2)
c5bbde ¤   ¤   return 0;
666bf2 ¤   t = ((unsigned)buf[0] << 8) + buf[1];
80e597 ¤   t = (t+7)/8;
21d93c ¤   if (size < t+2)
25bbde ¤   ¤   return 0;
6faf5a
a0aa90 ¤   if (bnInsertBigBytes(bn, buf+2, 0, t) < 0)
224030 ¤   ¤   return kPGPError_OutOfMemory;
67b716 ¤   return (int)t+2;
14efe6 }
7caf5a
43620e /* Read start of an X.509 object */
265d74 PGPByte
fb1eb2 pgpBnX509TagLen(PGPByte const **buf, PGPUInt32 *length)
79bb36 {
7b1969 ¤   PGPByte tag = *(*buf)++ & 0x1f;
b610fe ¤   PGPUInt32 len = *(*buf)++;
cbde77 ¤   if (len & 0x80) {
29c694 ¤   ¤   PGPUInt32 lenlen = len & 0x7f;
275b71 ¤   ¤   len = 0;
3c6f5c ¤   ¤   while (lenlen--) {
8a63b4 ¤   ¤   ¤   len <<= 8;
bf33ec ¤   ¤   ¤   len |= *(*buf)++;
310fe4 ¤   ¤   }
6a9371 ¤   }
045c15 ¤   *length = len;
08bbe8 ¤   return tag;
b0efe6 }
d0af5a
fcbccf PGPUInt32
3666e3 pgpBnX509LenLen(PGPUInt32 length)
e0bb36 {
b8cb3e ¤   if (length < 0x80)
dbe102 ¤   ¤   return 1;
2136d8 ¤   if (length < 0x100)
610e66 ¤   ¤   return 2;
085129 ¤   if (length < 0x10000)
aa54ba ¤   ¤   return 3;
8a2340 ¤   if (length < 0x1000000)
30d8bf ¤   ¤   return 4;
6907d6 ¤   return 5;
aeefe6 }
aaaf5a
a238e5 /*
685c2e ·* Convert a big-endian byte buffer to an MPI. ·PGP format uses a
8d5dd2 ·* bitcount prefix.
cc31a4 ·* Returns number of bytes read from buffer, or <= 0 on error.
323663 ·* (Returns 0 if the buffer is too short.)
57495d ·*/
4d4d2f int
c432e7 pgpBnGetFormatted(BigNum *bn, PGPByte const *buf, unsigned size,
81a0cf ¤   unsigned modbytes, PGPPublicKeyMessageFormat format)
63bb36 {
50b1d8 ¤   unsigned extra = 0;
dfaf5a
540041 ¤   if (format == kPGPPublicKeyMessageFormat_PGP) {
2f7303 ¤   ¤   return pgpBnGetPlain( bn, buf, size );
fe9371 ¤   }
--bc3c 000b0895c5f40100212 Page 10 of pgpKeyMisc.c
e0af5a
f27e57 ¤   if (format == kPGPPublicKeyMessageFormat_X509) {
ae6b31 ¤   ¤   PGPUInt32 len;
8a0f3c ¤   ¤   PGPByte const *bp = buf;
9cc0ee ¤   ¤   if (pgpBnX509TagLen(&buf, &len) != X509_TAG_INTEGER)
84638f ¤   ¤   ¤   return kPGPError_MalformedKeyComponent;
40316c ¤   ¤   extra = buf - bp;
41154e ¤   ¤   size -= extra;
56076b ¤   ¤   if (len > size)
4c638f ¤   ¤   ¤   return kPGPError_MalformedKeyComponent;
29c41f ¤   ¤   modbytes = len;
3bf037 ¤   } else {
697c38 ¤   ¤   pgpAssert( format == kPGPPublicKeyMessageFormat_PKCS1 );
a39371 ¤   }
f1af5a
514c7d ¤   if (size < modbytes)
85bbde ¤   ¤   return 0;
07af5a
6849fe ¤   if (bnInsertBigBytes(bn, buf, 0, modbytes) < 0)
ad4030 ¤   ¤   return kPGPError_OutOfMemory;
344533 ¤   return (int)(modbytes + extra);
b8efe6 }
20af5a
f9af5a
ab38e5 /*
d4aae5 ·* Helper function for key unlocking.
1716df ·* Convert a big-endian byte buffer to an MPI, with optional decryption and
a9be91 ·* checksums. ·Accepts cfb == NULL to mean "unencrypted".
3131a4 ·* Returns number of bytes read from buffer, or <= 0 on error.
a13663 ·* (Returns 0 if the buffer is too short.)
c2775e ·*
94edfc ·* If "old" is true, this does it in the PGP 2.x way, where the length
2c946c ·* of the data is unencrypted and the CFB is resynced each step.
bad9c1 ·* If "old" is false, this assumes that just everything is encrypted
e29691 ·* and·
74495d ·*/
964d2f int
1a953d pgpBnGet(BigNum *bn, PGPByte const *buf, unsigned size,
435456 ¤   PGPCFBContext *cfb, unsigned *checksump, int old)
c0bb36 {
f101e8 ¤   PGPByte tmp[64];¤   /* This can be any (non-zero) size >= 2 */
bca67d ¤   unsigned t, l;
d2af5a
2eca8e ¤   if (!cfb) {
c02a1e ¤   ¤   int i;
a5af5a
c3be20 ¤   ¤   i = pgpBnGetPlain(bn, buf, size);
4630ce ¤   ¤   if (i >= 0 && checksump) {
df0059 ¤   ¤   ¤   for (t = 0; t < (unsigned)i; t++)
f6decb ¤   ¤   ¤   ¤   *checksump += buf[t];
350fe4 ¤   ¤   }
2ba423 ¤   ¤   return i;
519371 ¤   }
9faf5a
fd0fc2 ¤   if (size < 2)
a4bbde ¤   ¤   return 0;
6d97cd ¤   if (old) {
35a519 ¤   ¤   /* Length it bits is not encrypted */
f5f84d ¤   ¤   PGPCFBSync(cfb);
86f46e ¤   ¤   if (checksump)
8e10c3 ¤   ¤   ¤   *checksump += (unsigned)buf[0] + buf[1];
165237 ¤   ¤   t = ((unsigned)buf[0] << 8) + buf[1];
89f037 ¤   } else {
06ab58 ¤   ¤   /* Length in bits is encrypted */
f66389 ¤   ¤   PGPCFBDecrypt(cfb, buf, 2, tmp );
3df46e ¤   ¤   if (checksump)
a5e4e3 ¤   ¤   ¤   *checksump += (unsigned)tmp[0] + tmp[1];
d0af50 ¤   ¤   t = ((unsigned)tmp[0] << 8) + tmp[1];
639371 ¤   }
9879d2 ¤   buf += 2;
14e597 ¤   t = (t+7)/8;
b0d93c ¤   if (size < t+2)
--6d25 0001a750fc440100212 Page 11 of pgpKeyMisc.c
79bbde ¤   ¤   return 0;
89af5a
ccd8af ¤   /*
88b21f ¤   ·* Descrypt and convert in pieces. ·It's done from the
0ed350 ¤   ·* most-significnt end to force allocation of the result
16ec76 ¤   ·* number all at once rather than reallocating it bit by bit.
ada4e3 ¤   ·*/
8c9229 ¤   size = t;
76a0eb ¤   while (size) {
b0bb00 ¤   ¤   l = size < sizeof(tmp) ? size : sizeof(tmp);
1eaf5a
2e577d ¤   ¤   PGPCFBDecrypt(cfb, buf, l, tmp);
347c4a ¤   ¤   size -= l;
956f9f ¤   ¤   buf += l;
52ac7e ¤   ¤   if (bnInsertBigBytes(bn, tmp, size, l) < 0) {
429c19 ¤   ¤   ¤   pgpClearMemory( tmp, ·sizeof(tmp));
217cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
a60fe4 ¤   ¤   }
50af5a
aae3b0 ¤   ¤   /* Checksum */
c98599 ¤   ¤   if (checksump) {
e0f603 ¤   ¤   ¤   do {
77ed86 ¤   ¤   ¤   ¤   *checksump += tmp[--l];
66fabc ¤   ¤   ¤   } while (l);
df0fe4 ¤   ¤   }
1f9371 ¤   }
480c2f ¤   pgpClearMemory( tmp, ·sizeof(tmp));
90af5a
a8b716 ¤   return (int)t+2;
68efe6 }
f3af5a
2238e5 /*
9a8001 ·* Read the 2-byte simple checksum (as computed above) from the
770aa0 ·* buffer for comparison. ·Old-style is unencrypted, new-style is
390b57 ·* encrypted.
68495d ·*/
d0536c unsigned
5d4718 pgpChecksumGet(PGPByte const *buf, PGPCFBContext *cfb, int old)
d2bb36 {
2951f7 ¤   PGPByte tmp[2];
c91b07 ¤   unsigned checksum;
50af5a
d23b11 ¤   if (old || !cfb) {
aed628 ¤   ¤   checksum = ((unsigned)buf[0] << 8) + buf[1];
c7f037 ¤   } else {
c6955f ¤   ¤   PGPCFBDecrypt(cfb, buf, 2, tmp);
2c2b4f ¤   ¤   checksum = ((unsigned)tmp[0] << 8) + tmp[1];
b69638 ¤   ¤   pgpClearMemory( tmp, ·2);
bf9371 ¤   }
79eb46 ¤   return checksum;
28efe6 }
20af5a
9638e5 /*
807982 ·* Convert an MPI to a big-endian byte buffer, with a length prefix.
65091d ·* Returns number of bytes put into buffer.
d3495d ·*/
ae536c unsigned
5ae794 pgpBnPutPlain(BigNum const *bn, PGPByte *buf)
c4bb36 {
2e0ed5 ¤   unsigned t;
85af5a
23798f ¤   t = bnBits(bn);
e0ded1 ¤   buf[0] = (PGPByte)(t>>8 & 255);
44d0ef ¤   buf[1] = (PGPByte)(t & 255);
03e597 ¤   t = (t+7)/8;
723599 ¤   bnExtractBigBytes(bn, buf+2, 0, t);
09cbaf ¤   return t+2;
e3efe6 }
11af5a
2d38e5 /*
0fc2ea ·* Convert an MPI to a big-endian byte buffer. ·PGP format uses a
1ab797 ·* length prefix.
--a047 0009dbf09dd40100212 Page 12 of pgpKeyMisc.c
5c091d ·* Returns number of bytes put into buffer.
43495d ·*/
72536c unsigned
3fab90 pgpBnPutFormatted(BigNum const *bn, PGPByte *buf,
08a0cf ¤   unsigned modbytes, PGPPublicKeyMessageFormat format)
17bb36 {
3bb1d8 ¤   unsigned extra = 0;
09af5a
390041 ¤   if (format == kPGPPublicKeyMessageFormat_PGP) {
a122c9 ¤   ¤   return pgpBnPutPlain( bn, buf );
9a9371 ¤   }
e9af5a
8a7e57 ¤   if (format == kPGPPublicKeyMessageFormat_X509) {
c59cbd ¤   ¤   /* Insert integer prefix in DER encoding */
90db2a ¤   ¤   PGPUInt32 lenlen;
0a6b31 ¤   ¤   PGPUInt32 len;
0d2e46 ¤   ¤   if (bnBits(bn) == 8*modbytes)
b59f33 ¤   ¤   ¤   modbytes += 1;
e97e88 ¤   ¤   len = modbytes;
8e9f5c ¤   ¤   *buf++ = X509_TAG_INTEGER;
5bb3ae ¤   ¤   ++extra;
63f385 ¤   ¤   lenlen = pgpBnX509LenLen(len);
4db928 ¤   ¤   if (--lenlen == 0) {
29cc48 ¤   ¤   ¤   *buf++ = len;
6af225 ¤   ¤   ¤   ++extra;
b245a6 ¤   ¤   } else {
0438ac ¤   ¤   ¤   *buf++ = 0x80 | lenlen;
eef225 ¤   ¤   ¤   ++extra;
6c198e ¤   ¤   ¤   len <<= 8 * (4-lenlen);
af7b74 ¤   ¤   ¤   while (lenlen--) {
51ab55 ¤   ¤   ¤   ¤   *buf++ = (PGPByte)(len >> 24);
a443f4 ¤   ¤   ¤   ¤   ++extra;
bc8155 ¤   ¤   ¤   ¤   len <<= 8;
a4a3a6 ¤   ¤   ¤   }
030fe4 ¤   ¤   }
869371 ¤   }
38e610 ¤   bnExtractBigBytes(bn, buf, 0, modbytes);
75f33a ¤   return modbytes + extra;
a5efe6 }
05af5a
1e38e5 /*
030cc3 ·* Helper function for ChangeLock.
81912f ·* Convert an MPI to a big-endian byte buffer, with optional encryption and
a4be91 ·* checksums. ·Accepts cfb == NULL to mean "unencrypted".
12091d ·* Returns number of bytes put into buffer.
42495d ·*/
ec536c unsigned
a01027 pgpBnPut(BigNum const *bn, PGPByte *buf,
0a5456 ¤   PGPCFBContext *cfb, unsigned *checksump, int old)
00bb36 {
3cbff6 ¤   unsigned t, u;
09af5a
74f2f2 ¤   t = pgpBnPutPlain(bn, buf);
f4cf87 ¤   if (checksump)
cc821e ¤   ¤   for (u = 0; u < t; u++)
812d03 ¤   ¤   ¤   *checksump += buf[u];
c034c1 ¤   if (cfb) {
e1756e ¤   ¤   if (old) {
66cc10 ¤   ¤   ¤   PGPCFBSync(cfb);
b74aae ¤   ¤   ¤   PGPCFBEncrypt(cfb, buf+2, t-2, buf+2);
ea45a6 ¤   ¤   } else {
28bac5 ¤   ¤   ¤   PGPCFBEncrypt(cfb, buf, t, buf);
fb0fe4 ¤   ¤   }
c49371 ¤   }
7c5b7c ¤   return t;
aeefe6 }
82af5a
0538e5 /*
c86a49 ·* Write the 2-byte simple checksum (as computed above) to the
4d0aa0 ·* buffer for comparison. ·Old-style is unencrypted, new-style is
0b0b57 ·* encrypted.
9d495d ·*/
--3cde 000dc12588040100212 Page 13 of pgpKeyMisc.c
b3314a void
f267c6 pgpChecksumPut(unsigned checksum, PGPByte *buf, PGPCFBContext *cfb,
08c3c0 ¤   int old)
fbbb36 {
38c58f ¤   buf[0] = (PGPByte)(checksum>>8 & 255);
69eba8 ¤   buf[1] = (PGPByte)(checksum & 255);
d86c81 ¤   if (cfb && !old)
3cfe01 ¤   ¤   PGPCFBEncrypt(cfb, buf, 2, buf);
f7efe6 }
7faf5a
b038e5 /*
555812 ·* Generate a random bignum of the specified length, with the given
36784e ·* high and low 8 bits. "High" is merged into the high 8 bits of the
b6ec67 ·* number. ·For example, set it to 0x80 to ensure that the number is
a0e42a ·* exactly "bits" bits long (i.e. 2^(bits-1) <= bn < 2^bits).
7bf371 ·* "Low" is merged into the low 8 bits. ·For example, set it to
18fb8e ·* 1 to ensure that you generate an odd number.
d4495d ·*/
384d2f int
c1e0f5 pgpBnGenRand(BigNum *bn, PGPRandomContext const *rc,
d0d953 ¤   ·····unsigned bits, PGPByte high, PGPByte low, unsigned effective)
86bb36 {
49c9e2 ¤   unsigned char buf[64];
b170a3 ¤   unsigned bytes;
b34d82 ¤   unsigned l;
8117e6 ¤   int err;
64af5a
984fed ¤   bnSetQ(bn, 0);
f1af5a
2e1d81 ¤   /* Get high random bits */
51eabb ¤   bytes = (bits+7) / 8;
372f64 ¤   l = bytes < sizeof(buf) ? bytes : sizeof(buf);
20afec ¤   pgpRandomGetBytesEntropy(rc, buf, l, effective);
d5af5a
1c7a5e ¤   /* Mask off excess high bits */
23f043 ¤   buf[0] &= 255 >> (-(int)bits & 7);
98322f ¤   /* Merge in specified high bits */
d6c71b ¤   buf[0] |= high >> (-(int)bits & 7);
8bedeb ¤   if (bits & 7)
63be69 ¤   ¤   buf[1] |= high << (bits & 7);
16af5a
f4220e ¤   for (;;) {
f113c6 ¤   ¤   bytes -= l;
1e98f3 ¤   ¤   if (!bytes)¤/* Last word - merge in low bits */
665226 ¤   ¤   ¤   buf[l-1] |= low;
41af99 ¤   ¤   err = bnInsertBigBytes(bn, buf, bytes, l);
12b286 ¤   ¤   if (!bytes || err < 0)
05cdcb ¤   ¤   ¤   break;
8b3e43 ¤   ¤   l = bytes < sizeof(buf) ? bytes : sizeof(buf);
ac34c2 ¤   ¤   pgpRandomGetBytesEntropy(rc, buf, l, 0);
a79371 ¤   }
5caf5a
6dc3ba ¤   /* Burn and return */
93718a ¤   pgpClearMemory( buf, ·sizeof(buf));
de5ea8 ¤   return err;
a2efe6 }
39af5a
4138e5 /*
77d327 ·* Parse a buffer containing n mpi format numbers (two bytes of length in bits,
c02838 ·* followed by data). ·Make sure data is well formed and doesn't exceed
097360 ·* buffer length. ·Take n pointers to offsets where the n numbers start
e2efd4 ·* (pointers may be null but must not be left off arg list).
4a03c7 ·* Return offset past last value, or negative for error.
f5495d ·*/
8c4d2f int
bac148 pgpBnParse(PGPByte const *buf, unsigned size, int n, ...)
babb36 {
bcfa20 ¤   va_list ap;
0881fc ¤   unsigned nb;
853876 ¤   unsigned off;
c42673 ¤   unsigned *poff;
dcaf5a
--6203 000d66b8d1640100212 Page 14 of pgpKeyMisc.c
f32f7c ¤   va_start (ap, n);
449f5d ¤   if (size < 2U*n)
28a27a ¤   ¤   return kPGPError_KeyPacketTruncated;
616cdb ¤   off = 0;
b14d76 ¤   while (n--) {
5f0939 ¤   ¤   poff = va_arg(ap, unsigned *);
3d1fc2 ¤   ¤   nb = ((unsigned)buf[0+off] << 8) + buf[1+off];
99a524 ¤   ¤   if (!nb || buf[2+off] >> ((nb-1) & 7) != 1)
12503a ¤   ¤   ¤   return kPGPError_MalformedKeyComponent; /* Bad bit length */
7db629 ¤   ¤   nb = (nb+7)/8;
d4b6cb ¤   ¤   /* Need nb+2 bytes for this, plus 2*n for remainder */
c9857f ¤   ¤   if (size-off < nb + 2 + 2*n)
d2f0e7 ¤   ¤   ¤   return kPGPError_KeyPacketTruncated;
d97b38 ¤   ¤   if (poff)
f1d0ab ¤   ¤   ¤   *poff = off;
59f89a ¤   ¤   off += nb+2;
999371 ¤   }
24468e ¤   va_end (ap);
db45b9 ¤   return off;
a6efe6 }
c0af5a
c638e5 /*
091f8a ·* Given a cipher algorithm descriptor in (buf,len) and a passphrase,
4c1da1 ·* initialize the passed-in PGPCFBContext pointer and return the
7efb32 ·* number of bytes of descriptor used, or <0 on error. ·(In which
ad0697 ·* case *cfbp is NULL.) ·If hashedPhrase is true, the passphrase has
55f458 ·* already been hashed using the s2k object and we use it literally
a332ed ·* as the key.
ef495d ·*/
d74d2f int
695981 pgpCipherSetup(
0fa471 PGPByte const *buf, unsigned len, char const *phrase, size_t plen,
d9001f ¤   PGPBoolean hashedPhrase, PGPEnv const *env, PGPCFBContext **cfbp)
b5bb36 {
8c08c6 ¤   PGPCipherVTBL const *cipher;
9abfb0 ¤   PGPStringToKey *s2k;
5cdfbc ¤   unsigned alg;
4ef245 ¤   int alglen;
8bf455 ¤   PGPByte key[PGP_CIPHER_MAXKEYSIZE];
a3c640 ¤   PGPContextRef¤  context¤= pgpenvGetContext( env );
0faf5a
28196f ¤   /* Sanity check on lengths, otherwise we take forever */
c393de ¤   pgpAssert( plen < 0x10000U );
478a03 ¤   pgpAssert( len < 0x10000U );
ddaf5a
819dbe ¤   /* First things first, in case of error... */
514e3b ¤   *cfbp = NULL;
18af5a
f90ece ¤   if (len < 1)
53a27a ¤   ¤   return kPGPError_KeyPacketTruncated;
74af5a
474b5a ¤   alg = buf[0] & 255;
0aaf5a
9ff4d0 ¤   if (!alg)¤  /* The key isn't encrypted; just read it in */
63e102 ¤   ¤   return 1;
1faf5a
1540cd ¤   if (alg == 255) {
a5602c ¤   ¤   /* New style, with a separate string-to-key */
c1af5a
31e3b5 ¤   ¤   if (len == 1)
31f0e7 ¤   ¤   ¤   return kPGPError_KeyPacketTruncated;
c8ef77 ¤   ¤   alg = buf[1];
45bd57 ¤   ¤   alglen = pgpS2Kdecode(&s2k, env, buf+2, len-2);
40f3d3 ¤   ¤   if (alglen < 0)
caac5e ¤   ¤   ¤   return alglen;
b15d26 ¤   ¤   alglen += 2;
ccb3e7 ¤   ¤   if (len < (unsigned)alglen)
98f0e7 ¤   ¤   ¤   return kPGPError_KeyPacketTruncated;
84f037 ¤   } else {
5d1139 ¤   ¤   /* Old-style string-to-key */
bd176e ¤   ¤   s2k = pgpS2Ksimple(env, pgpHashByNumber(kPGPHashAlgorithm_MD5));
d6a487 ¤   ¤   if (!s2k)
--515e 0011e2e198640100212 Page 15 of pgpKeyMisc.c
757cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
4c3408 ¤   ¤   alglen = 1;
359371 ¤   }
035783 ¤   /* Okay now, do the conversion */
70c7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
58e060 ¤   if (!cipher) {
c4e56b ¤   ¤   pgpS2Kdestroy(s2k);
32fb6d ¤   ¤   return kPGPError_BadCipherNumber;
f69371 ¤   }
4e9f5f ¤   if (len < alglen + cipher->blocksize) {
09e56b ¤   ¤   pgpS2Kdestroy(s2k);
2da27a ¤   ¤   return kPGPError_KeyPacketTruncated;
939371 ¤   }
77727c ¤   *cfbp = pgpCFBCreate( PGPGetContextMemoryMgr( context ), cipher);
582e48 ¤   if (!*cfbp) {
8be56b ¤   ¤   pgpS2Kdestroy(s2k);
064030 ¤   ¤   return kPGPError_OutOfMemory;
bc9371 ¤   }
986dab ¤   pgpAssert(cipher->keysize <= sizeof(key));
5f3e88 ¤   if (hashedPhrase) {
a9b371 ¤   ¤   pgpCopyMemory (phrase, key, plen);
51f037 ¤   } else {
447c44 ¤   ¤   pgpStringToKey(s2k, phrase, plen, key, cipher->keysize);
269371 ¤   }
e2ac4b ¤   PGPInitCFB(*cfbp, key, buf + alglen);
6a3661 ¤   pgpClearMemory( key, ·sizeof(key));
76130e ¤   pgpS2Kdestroy(s2k);
22af5a
842c08 ¤   return alglen + cipher->blocksize;
1eefe6 }
--7e0b 000fc9df3a640100213 Page 1 of pgpKeyMisc.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
7873a8 ¤   This is a PRIVATE header file, for use only within the PGP Library.
6a9c5a ¤   You should not be using these functions in an application.
92af5a
ef04e7 ¤   $Id: pgpKeyMisc.h,v 1.13.12.1 1998/11/12 03:22:11 heller Exp $
b9f7f7 ____________________________________________________________________________*/
c7a7e2 #ifndef Included_pgpKeyMisc_h
baf3d6 #define Included_pgpKeyMisc_h
8caf5a
6a03d5 #include "pgpUsuals.h"¤ ¤   /* for PGPByte */
370fc3 #include "pgpPublicKey.h"¤  /* for PGPPublicKeyMessageFormat */
6aaf5a
7b99c6 PGP_BEGIN_C_DECLARATIONS
41af5a
d8af5a
5a911f /* For future expansion to ignore certain bits of alg */
83d4b4 #define ALGMASK(alg) (alg)
faaf5a
069f51 /* Block types from PKCS */
da3908 #define PKCS_PAD_ZERO¤  ¤   0
f1e5ed #define PKCS_PAD_SIGNED¤¤   1
bd6fc4 #define PKCS_PAD_ENCRYPTED¤ 2
1baf5a
4c1267 /* Commonly used tag values from X509 */
6d3f09 #define X509_TAG_INTEGER¤   ¤   2
4c47a1 #define X509_TAG_BITSTRING¤ ¤   3
37328b #define X509_TAG_SEQUENCE¤  ¤   16
0395a5 #define X509_TAG_CONSTRUCTED¤   0x20
78af5a
f9af5a
a56a85 unsigned pgpDiscreteLogExponentBits(unsigned modbits);
47cf00 unsigned pgpDiscreteLogQBits(unsigned modbits);
5daf5a
6aaaec int pgpPKCSPack(BigNum *bn, PGPByte const *in, unsigned len,
6c2ce3 ¤   PGPByte padtype,
5bbb35 ¤   unsigned bytes, PGPRandomContext const *rc);
70a953 int pgpPKCSUnpack(PGPByte *buf, unsigned len, BigNum *bn, PGPByte padtype,
76a7ec ¤   unsigned bytes);
c8af5a
d428c2 PGPByte pgpBnX509TagLen(PGPByte const **buf, PGPUInt32 *length);
34743f PGPUInt32 pgpBnX509LenLen(PGPUInt32 length);
9c340e int pgpBnGetPlain(BigNum *bn, PGPByte const *buf, unsigned size);
709ec9 int pgpBnGetFormatted(BigNum *bn, PGPByte const *buf, unsigned size,
9c3e7b ¤   unsigned modbytes, PGPPublicKeyMessageFormat format);
da7a00 int pgpBnGet(BigNum *bn, PGPByte const *buf, unsigned size,
1f37c7 ¤   PGPCFBContext *cfb, unsigned *checksump, int old);
8efa8d #define pgpBnGetNew(bn,buf,size,cfb,cs) pgpBnGet(bn,buf,size,cfb,cs,0)
46c6bf #define pgpBnGetOld(bn,buf,size,cfb,cs) pgpBnGet(bn,buf,size,cfb,cs,1)
c3af5a
560d30 unsigned pgpChecksumGet(PGPByte const *buf,
93e199 ¤   PGPCFBContext *cfb, int old);
6d111b #define pgpChecksumGetNew(buf,cfb) pgpChecksumGet(buf,cfb,0)
2cee4f #define pgpChecksumGetOld(buf,cfb) pgpChecksumGet(buf,cfb,1)
a8af5a
ab6f51 unsigned pgpBnPutPlain(BigNum const *bn, PGPByte *buf);
228e8e unsigned pgpBnPutFormatted(BigNum const *bn, PGPByte *buf,
063e7b ¤   unsigned modbytes, PGPPublicKeyMessageFormat format);
5c8a15 unsigned pgpBnPut(BigNum const *bn, PGPByte *buf,
cb37c7 ¤   PGPCFBContext *cfb, unsigned *checksump, int old);
065ffa #define pgpBnPutNew(bn,buf,cfb,cs) pgpBnPut(bn,buf,cfb,cs,0)
73ed4c #define pgpBnPutOld(bn,buf,cfb,cs) pgpBnPut(bn,buf,cfb,cs,1)
cfaf5a
f5a3a1 void¤   pgpChecksumPut(unsigned csum,
12668f ¤   ¤   ¤   PGPByte *buf, PGPCFBContext *cfb, int old);
940bb3 #define pgpChecksumPutNew(csum,buf,cfb) pgpChecksumPut(csum,buf,cfb,0)
65db46 #define pgpChecksumPutOld(csum,buf,cfb) pgpChecksumPut(csum,buf,cfb,1)
2daf5a
44de9d int pgpBnGenRand(BigNum *bn, PGPRandomContext const *rc,
fc60e7 ¤   ·····unsigned bits, PGPByte high, PGPByte low, unsigned effective);
--00bc 001b4be89b340100213 Page 2 of pgpKeyMisc.h
51dd2d int pgpBnParse(PGPByte const *buf, unsigned size, int n, ...);
6aaf5a
15ea14 int¤¤   pgpCipherSetup(PGPByte const *buf, unsigned len,
c7e52f ¤   ¤   ¤   char const *phrase, size_t plen, PGPBoolean hashedPhrase,
6e8ad2 ¤   ¤   ¤   PGPEnv const *env, PGPCFBContext **cfbp);
67af5a
a81254 PGP_END_C_DECLARATIONS
d4af5a
b48d54 #endif /* Included_pgpKeyMisc_h */
--e196 000b824ce7040100214 Page 1 of pgpKeySpec.c
bc38e5 /*
c6cc9f ·* $Id: pgpKeySpec.c,v 1.18 1998/06/11 18:28:19 hal Exp $
82495d ·*/
26af5a
bae2ff #include "pgpConfig.h"
dcaf5a
430a8b #include <time.h>
af324c #include <string.h>
61af5a
fdc5b0 #include "pgpKeySpec.h"
310d08 #include "pgpMem.h"
bf0d6d #include "pgpEnv.h"
472f8d #include "pgpErrors.h"
432266 #include "pgpTimeDate.h"
2ad11f #include "pgpUsuals.h"
dac26c #include "pgpContext.h"
20af5a
6538e5 /*
f70875 ·* The things in a public key that aren't part of the (algorithm-specific)
7d7ed4 ·* mathematical public key. ·Personally, I'd prefer that this didn't exist!
92495d ·*/
8faacd struct PGPKeySpec
77bb36 {
e98a97 ¤   PGPContextRef¤  context;
22a47b ¤   PgpVersion version;¤¤   ¤   /* Version of key to create */
627b55 ¤   PGPUInt32 creation;¤¤   ¤   /* Creation date */
36515e ¤   PGPUInt16 expirationDays;¤  ¤   ¤   /* Validity period */
31e7e2 ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPKeySpec )
fe2fa1 } ;
b9af5a
7e0d76 PGPKeySpec *
de8980 pgpKeySpecCreate(PGPEnv const *env)
adbb36 {
0f66b9 ¤   PGPKeySpec *ks;
cfc520 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( env );
77af5a
29d9a8 ¤   ks = (PGPKeySpec *)pgpContextMemAlloc( cdkContext,
14f1c8 ¤   ¤   sizeof(*ks), kPGPMemoryMgrFlags_Clear);
44c6ce ¤   if (ks) {
d7b227 ¤   ¤   ks->context¤= cdkContext;
3a4261 ¤   ¤   /* Default values, based on environment */
1d9557 ¤   ¤   /*ks->version = pgpenvGetInt(env, PGPENV_VERSION, NULL, NULL);*/
d4438d ¤   ¤   ks->version = PGPVERSION_3;¤/* Default to this unless overridden */
710cd9 ¤   ¤   ks->creation = pgpTimeStamp(pgpenvGetInt(env, PGPENV_TZFIX,
f696cd ¤   ¤   ·········································NULL, NULL));
a7e54f ¤   ¤   ks->expirationDays = 0;¤/* Forever */
9c9371 ¤   }
ba087c ¤   return ks;
8befe6 }
97af5a
0d0d76 PGPKeySpec *
13f834 pgpKeySpecCopy(PGPKeySpec const *ks)
47bb36 {
21b412 ¤   PGPKeySpec *ks2;
cfaf5a
1b9046 ¤   ks2 = (PGPKeySpec *)pgpContextMemAlloc( ks->context,
5003cd ¤   ¤   sizeof(*ks2), kPGPMemoryMgrFlags_Clear);
eadbef ¤   if (ks2)
20ce2f ¤   ¤   memcpy(ks2, ks, sizeof(*ks2));
4925dd ¤   return ks2;
86efe6 }
21af5a
40314a void
6a86a8 pgpKeySpecDestroy(PGPKeySpec *ks)
95bb36 {
b98060 ¤   PGPContextRef¤  ¤   cdkContext;
5667c5 ¤
3c2e01 ¤   pgpAssertAddrValid( ks, PGPKeySpec );
86569e ¤   cdkContext¤ = ks->context;
e567c5 ¤
6b4833 ¤   pgpClearMemory( ks, ·sizeof(*ks));
b8b92a ¤   pgpContextMemFree( cdkContext, ks);
--deff 001c033597240100214 Page 2 of pgpKeySpec.c
7aefe6 }
46af5a
9aa6d1 PgpVersion
a8bef1 pgpKeySpecVersion(PGPKeySpec const *ks)
2dbb36 {
8f1be2 ¤   return ks->version;
a7efe6 }
fbaf5a
99bccf PGPUInt32
2ab4d2 pgpKeySpecCreation(PGPKeySpec const *ks)
19bb36 {
a233ae ¤   return ks->creation;
3eefe6 }
22af5a
b76e17 PGPUInt16
22083e pgpKeySpecValidity(PGPKeySpec const *ks)
76bb36 {
9e0c97 ¤   return ks->expirationDays;
96efe6 }
4daf5a
194d2f int
f73a03 pgpKeySpecSetVersion(PGPKeySpec *ks, PgpVersion ver)
4dbb36 {
b53a92 ¤   switch(ver) {
8f6fb8 ¤   ··case PGPVERSION_2:
a43564 ¤   ··case PGPVERSION_3:
29b961 ¤   ··case PGPVERSION_4:
1301e1 ¤   ¤   ks->version = ver;
acbbde ¤   ¤   return 0;
f39371 ¤   }
496f62 ¤   /* default */
d57467 ¤   return kPGPError_UnknownKeyVersion;
62efe6 }
f6af5a
f84d2f int
f72b34 pgpKeySpecSetCreation(PGPKeySpec *ks, PGPUInt32 creation)
e3bb36 {
83deae ¤   ks->creation = creation;
0b3e6b ¤   return 0;
33efe6 }
50af5a
e14d2f int
487f20 pgpKeySpecSetValidity(PGPKeySpec *ks, PGPUInt16 expirationDays )
2fbb36 {
476a97 ¤   ks->expirationDays = expirationDays;
e63e6b ¤   return 0;
c0efe6 }
--b3f4 001b659061c40100215 Page 1 of pgpKeySpec.h
bc38e5 /*
c9d16f ·* $Id: pgpKeySpec.h,v 1.9 1997/06/25 19:40:57 lloyd Exp $
c8495d ·*/
41af5a
5a7c11 #ifndef Included_pgpKeySpec_h
235f55 #define PGP_KEYSPEC_h
2daf5a
e6d11f #include "pgpUsuals.h"
2eaf5a
f899c6 PGP_BEGIN_C_DECLARATIONS
edaf5a
4ca16f PGPKeySpec ·*pgpKeySpecCreate(PGPEnv const *env);
a25828 PGPKeySpec ·*pgpKeySpecCopy(PGPKeySpec const *ks);
831ca4 void ·pgpKeySpecDestroy(PGPKeySpec *ks);
c3af5a
0e17f7 PgpVersion ·pgpKeySpecVersion(PGPKeySpec const *ks);
e0af5a
45a6a1 PGPUInt32 ·pgpKeySpecCreation(PGPKeySpec const *ks);
af454e PGPUInt16 ·pgpKeySpecValidity(PGPKeySpec const *ks);
e1af5a
9f2ab1 int ·pgpKeySpecSetVersion(PGPKeySpec *ks, PgpVersion ver);
938504 int ·pgpKeySpecSetCreation(PGPKeySpec *ks, PGPUInt32 creation);
fc0609 int ·pgpKeySpecSetValidity(PGPKeySpec *ks, PGPUInt16 validity);
30af5a
f61254 PGP_END_C_DECLARATIONS
6daf5a
b65597 #endif /* Included_pgpKeySpec_h */
--bea0 0003ccdfb8140100216 Page 1 of pgpMSRSAGlue.c
bc38e5 /*
4efbbf ·* pgpMSRSAGlue.c - Interface to Microsoft CryptoAPI for RSA support
9a775e ·*
8046b0 ·* This is an alternative to pgpRSAGlue.c, and should be used if that
caee72 ·* module cannot be used for legal reasons. ·It is only usable on
8522c2 ·* platforms which include Microsoft CAPI support.
1f775e ·*
ca85a1 ·* This code only accepts PKCS-style padding. ·Very old versions of PGP
c0e92a ·* used a different padding style, which will not be compatible with
688700 ·* this module.
32775e ·*
e2178b ·* $Id: pgpMSRSAGlue.c,v 1.10 1998/08/10 19:30:20 hal Exp $
db495d ·*/
e5d83c ·
763051 #include "pgpSDKBuildFlags.h"
8338e5 /*
27af5a
acbd56 ·* This entire source file is under the control of the following conditional:
ab495d ·*/
2daf5a
066856 #if PGP_USECAPIFORRSA¤  /* [ */
c4af5a
37af5a
1ce2ff #include "pgpConfig.h"
aaaf5a
22a146 #include "pgpDebug.h"
cfcdc2 #include "pgpPubKey.h"
748c41 #include "pgpRSAGlue.h"
13007f #include "pgpKeyMisc.h"
8539fc #include "bn.h"
382f8d #include "pgpErrors.h"
802c96 #include "pgpRandomX9_17.h"
2b0d08 #include "pgpMem.h"
555417 #include "pgpHashPriv.h"
ff4704 #include "pgpMSRSAGlue.h"
60af5a
5aa71e /* Early versions of wincrypt.h are missing these */
d873e8 #ifndef MS_ENH_PROV
9def07 #define MS_ENH_PROV_A ······"Microsoft Enhanced Cryptographic Provider v1.0"
8212d1 #define MS_ENH_PROV_W ······L"Microsoft Enhanced Cryptographic Provider v1.0"
b4d377 #ifdef UNICODE
713eda #define MS_ENH_PROV ········MS_ENH_PROV_W
3edb21 #else
38ff9b #define MS_ENH_PROV ········MS_ENH_PROV_A
6c7454 #endif
246dde #endif /* MS_ENH_PROV */
caaf5a
c2b815 #ifndef CALG_3DES
9a11b2 #define CALG_3DES 0x00006603
c1b9e7 #endif /* CALG_3DES */
80af5a
6faf5a
442eac /* Shorthand for accessing CAPI externs */
c74f7c #define ex pgp_CAPI_externs
f6af5a
ed76ea /* Our key container name, chosen not to conflict with a user name */
c151d1 #define PGPCONTAINER¤   "PGPreservedContainer"
f1af5a
b080df /* Magic values for blob headers */
b47086 #define RSAPUBMAGIC¤¤   0x31415352
0f8053 #define RSAPRIVMAGIC¤   0x32415352
f036d5 #define BVERSION¤   ¤   2
f0af5a
43ccc3 /* Byte packing macros, little endian */
0b9dd6 #define B4(val) (val)&0xff, ((val)>>8)&0xff, ((val)>>16)&0xff, ((val)>>24)&0xff
229a57 #define B2(val) (val)&0xff, ((val)>>8)&0xff
17af5a
0912eb /* Round n up to be a multiple of r */
28b976 #define MULOF(n,r) ((((n)+(r)-1)/(r))*(r))
09af5a
f9af5a
3c76c1 /* Blob definitions */
--f154 00003598b8d40100216 Page 2 of pgpMSRSAGlue.c
e0af5a
f45042 /* Blob header for all blobs */
857ba3 typedef struct _BLOBHEADER
10bb36 {
8b17af ¤   BYTE bType;
c577c7 ¤   BYTE bVersion;
c7b812 ¤   WORD reserved;
b13266 ¤   ALG_ID aiKeyAlg;
6a3a43 } BLOBHEADER;
aaaf5a
97af5a
3d8772 /* Public key blob header */
d42abc typedef struct _PUBLICKEYBLOBHDR
3ebb36 {
833f28 ¤   BLOBHEADER ·····header;
faecc9 ¤   RSAPUBKEY ······rsapubkey;
9cc98c } PUBLICKEYBLOBHDR;
c8b644 /* Followed by modulus, rsapubkey.bitlen bits long, little endian */
71af5a
65bd19 /* Note that this is the same as PUBLICKEYBLOBHDR, just what follows differs */
478574 typedef struct _PRIVATEKEYBLOBHDR
d2bb36 {
f33f28 ¤   BLOBHEADER ·····header;
32ecc9 ¤   RSAPUBKEY ······rsapubkey;
7f473f } PRIVATEKEYBLOBHDR;
a6256e /* Followed by (all in little endian form, bitlen rounded up to mul of 64):
55c51b ·*¤ modulus, rsapubkey.bitlen bits long,
368932 ·*¤ prime1, rsapubkey.bitlen/2 bits long,
298a38 ·* ·prime2, rsapubkey.bitlen/2 bits long, (prime1 > prime2)
0f4915 ·* ·exponent1, rsapubkey.bitlen/2 bits long (privateExponent % (prime1-1))
42f063 ·* ·exponent2, rsapubkey.bitlen/2 bits long (privateExponent % (prime2-1))
91e5b9 ·*¤ coefficient, rsapubkey.bitlen/2 bits long (inverse of prime2 mod prime1)
139a41 ·* ·privateExponent, rsapubkey.bitlen bits long
bc495d ·*/
b2af5a
52af5a
f9eb02 typedef struct _SIMPLEBLOBHDR
33bb36 {
d03f28 ¤   BLOBHEADER ·····header;
e043f5 ¤   ALG_ID ·········algid;¤ ¤   /* of pubkey which encrypts session key */
88acac } SIMPLEBLOBHDR;
f42a8c /* Followed by session key, encrypted in PKCS-1 format with a public key */
7eaf5a
68af5a
a2dbed /* Cache loadability information */
613bb8 static PGPBoolean sLoadabilityTested = FALSE;
2bd052 static PGPUInt32 sCAPIuse = 0;
020663 /* Cache library handles and entry point vectors */
8005cf static HINSTANCE hLibAdv;
efd1bb static HINSTANCE hLibCry;
655cb9 #if !PGP_USECAPIFORMD2
aa97e5 static
ae7454 #endif
b03704 ·······CAPIEntries pgp_CAPI_externs;¤   /* May be used by MD2 CAPI code */
acaf5a
a7b39f #define DUMMYBITS 384
1caf5a
3e38e5 /*
4543c5 ·* Dummy key, 384 bits, with public exponent = private exponent = 1
e05ada ·* Used when we don't want CAPI to do anything with our data.
37495d ·*/
2e32a9 static PGPByte dummyKeyBlob[] = {
daa029 ¤   /* Blob header */
ed63fe ¤   PRIVATEKEYBLOB, BVERSION, 0, 0, B4(CALG_RSA_KEYX),
b38808 ¤   /* RSAPUBKEY values */
07629c ¤   B4(RSAPRIVMAGIC), B4(DUMMYBITS), B4(1),
31af5a
f22007 ¤   /* Modulus */
73243f ¤   0xc9, 0xd7, 0x0e, 0x21, 0xbb, 0xe0, 0xb5, 0x7a,
571d55 ¤   0x09, 0x3f, 0x64, 0x2d, 0xd7, 0xd0, 0x5c, 0xd6,
bba5fc ¤   0x3b, 0xb3, 0xed, 0x00, 0xe3, 0x2f, 0x53, 0xd9,
03804f ¤   0x26, 0xee, 0x47, 0x2f, 0x3e, 0x40, 0x5f, 0xc0,
--d1a1 000ce3a8a0140100216 Page 3 of pgpMSRSAGlue.c
fc38d7 ¤   0xf3, 0xb4, 0x25, 0x55, 0xea, 0xcf, 0x0b, 0x8f,
7ff02f ¤   0x08, 0x28, 0x1a, 0xdd, 0x3b, 0x2a, 0x49, 0x8c,
d64bb2 ¤   /* Prime1 */
430b3b ¤   0xe7, 0xc0, 0xd7, 0x29, 0x28, 0x71, 0xe3, 0xc4,
19fea7 ¤   0x05, 0x8c, 0xee, 0x1b, 0x37, 0xf4, 0x81, 0xe6,
b193cd ¤   0x5e, 0xb8, 0x4d, 0x38, 0xd3, 0x56, 0x80, 0xfa,
94567e ¤   /* Prime2 */
5a7852 ¤   0xcf, 0x9b, 0x02, 0x98, 0x55, 0x23, 0x09, 0xc6,
14ce46 ¤   0x44, 0x82, 0x69, 0x63, 0xae, 0x68, 0xe1, 0xd2,
389652 ¤   0x25, 0xfc, 0xe6, 0xe6, 0xc4, 0x7b, 0x5d, 0x8f,
ed5c01 ¤   /* Exponent1 */
f56f1d ¤   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
a85926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0741cd ¤   /* Exponent2 */
256f1d ¤   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
fa5926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ae5926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8a5ce7 ¤   /* Coefficient */
069b0a ¤   0x12, 0x12, 0xcd, 0x7f, 0x49, 0x92, 0xdf, 0x92,
c28bad ¤   0x3e, 0x0c, 0xc6, 0x76, 0x8e, 0x6e, 0x72, 0xd7,
6b9ecd ¤   0xe6, 0x94, 0xdf, 0xd8, 0xc5, 0x7c, 0x7f, 0x1e,
f68b6c ¤   /* Private exponent */
466f1d ¤   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
475926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
f75926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
945926 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
d7bfd5 ¤   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
b682f7 };
9eaf5a
2caf5a
91af5a
f1af5a
7188ea /* Returns TRUE if we were able to find everything and can use CAPI */
6e56b6 static PGPBoolean
35c0c3 LoadCAPIEntryPoints ()
83bb36 {
9199f6 ¤   PGPBoolean success = FALSE;
b8af5a
0e4f17 ¤   if (!(ex.CryptAcquireContext = GetProcAddress (hLibAdv,
c762eb ¤   ¤   ¤   ¤   "CryptAcquireContextA")) &&
b18114 ¤   ¤   !(ex.CryptAcquireContext = GetProcAddress (hLibCry,
b25992 ¤   ¤   ¤   ¤   "CryptAcquireContextA")))
a2262d ¤   ¤   goto done;
0d6a15 ¤   if (!(ex.CryptReleaseContext = GetProcAddress (hLibAdv,
78145d ¤   ¤   ¤   ¤   "CryptReleaseContext")) &&
49a416 ¤   ¤   !(ex.CryptReleaseContext = GetProcAddress (hLibCry,
f8b51b ¤   ¤   ¤   ¤   "CryptReleaseContext")))
b8262d ¤   ¤   goto done;
99bacb ¤   if (!(ex.CryptImportKey = GetProcAddress (hLibAdv,
537f07 ¤   ¤   ¤   ¤   "CryptImportKey")) &&
fbd43b ¤   ¤   !(ex.CryptImportKey = GetProcAddress (hLibCry,
20bcc7 ¤   ¤   ¤   ¤   "CryptImportKey")))
6d262d ¤   ¤   goto done;
d12033 ¤   if (!(ex.CryptExportKey = GetProcAddress (hLibAdv,
a3c5d6 ¤   ¤   ¤   ¤   "CryptExportKey")) &&
484ec3 ¤   ¤   !(ex.CryptExportKey = GetProcAddress (hLibCry,
f8e9d4 ¤   ¤   ¤   ¤   "CryptExportKey")))
88262d ¤   ¤   goto done;
c42c39 ¤   if (!(ex.CryptDestroyKey = GetProcAddress (hLibAdv,
d67429 ¤   ¤   ¤   ¤   "CryptDestroyKey")) &&
a43adb ¤   ¤   !(ex.CryptDestroyKey = GetProcAddress (hLibCry,
4aa8e2 ¤   ¤   ¤   ¤   "CryptDestroyKey")))
0a262d ¤   ¤   goto done;
c6c4e8 ¤   if (!(ex.CryptCreateHash = GetProcAddress (hLibAdv,
93993b ¤   ¤   ¤   ¤   "CryptCreateHash")) &&
29d20a ¤   ¤   !(ex.CryptCreateHash = GetProcAddress (hLibCry,
a6964c ¤   ¤   ¤   ¤   "CryptCreateHash")))
ef262d ¤   ¤   goto done;
5a3296 ¤   if (!(ex.CryptHashData = GetProcAddress (hLibAdv,
ce759f ¤   ¤   ¤   ¤   "CryptHashData")) &&
--13e9 000b77f9c5840100216 Page 4 of pgpMSRSAGlue.c
8e91ad ¤   ¤   !(ex.CryptHashData = GetProcAddress (hLibCry,
5b6ae9 ¤   ¤   ¤   ¤   "CryptHashData")))
51262d ¤   ¤   goto done;
127f6b ¤   if (!(ex.CryptSetHashParam = GetProcAddress (hLibAdv,
4ec497 ¤   ¤   ¤   ¤   "CryptSetHashParam")) &&
57038c ¤   ¤   !(ex.CryptSetHashParam = GetProcAddress (hLibCry,
79a42f ¤   ¤   ¤   ¤   "CryptSetHashParam")))
05262d ¤   ¤   goto done;
de5fa2 ¤   if (!(ex.CryptDestroyHash = GetProcAddress (hLibAdv,
ec1c3f ¤   ¤   ¤   ¤   "CryptDestroyHash")) &&
c57aab ¤   ¤   !(ex.CryptDestroyHash = GetProcAddress (hLibCry,
152708 ¤   ¤   ¤   ¤   "CryptDestroyHash")))
ca262d ¤   ¤   goto done;
2d0a0d ¤   if (!(ex.CryptVerifySignature = GetProcAddress (hLibAdv,
0079d2 ¤   ¤   ¤   ¤   "CryptVerifySignatureA")) &&
09d95b ¤   ¤   !(ex.CryptVerifySignature = GetProcAddress (hLibCry,
aac405 ¤   ¤   ¤   ¤   "CryptVerifySignatureA")))
fd262d ¤   ¤   goto done;
ef16ff ¤   if (!(ex.CryptSignHash = GetProcAddress (hLibAdv,
8587a8 ¤   ¤   ¤   ¤   "CryptSignHashA")) &&
dfb5c4 ¤   ¤   !(ex.CryptSignHash = GetProcAddress (hLibCry,
ba663d ¤   ¤   ¤   ¤   "CryptSignHashA")))
67262d ¤   ¤   goto done;
c85640 ¤   success = TRUE;
b5af5a
45b38c done:
34bf3a ¤   if (!success) {
dc2063 ¤   ¤   if (hLibAdv)
54a51f ¤   ¤   ¤   FreeLibrary (hLibAdv);
2ff417 ¤   ¤   if (hLibCry)
fa9068 ¤   ¤   ¤   FreeLibrary (hLibCry);
7f9371 ¤   }
8c7e96 ¤   return success;
8cefe6 }
38af5a
1baf5a
9f9927 /* Test what CAPI features are available */
5a6cb3 /* The compiler seems to be storing above the stack frame */
b22d74 /* Try turning off optimizer */
23c1a1 #pragma optimize ("", off)
aabccf PGPUInt32
e7b7fd pgpCAPIuse ()
c2bb36 {
3ab62d ¤   HCRYPTPROV hProv;
7f41c1 ¤   PGPBoolean DEFLoadable, ENHLoadable;
32af5a
1b07a5 ¤   if (!sLoadabilityTested) {
cab665 ¤   ¤   sLoadabilityTested = TRUE;
770881 ¤   ¤   sCAPIuse = 0;
e7f68c ¤   ¤   hLibAdv = LoadLibrary ("advapi32.dll");
ef802d ¤   ¤   if (!hLibAdv)
138144 ¤   ¤   ¤   return 0;
0d2604 ¤   ¤   hLibCry = LoadLibrary ("crypt32.dll");
afb585 ¤   ¤   if (!LoadCAPIEntryPoints ())
6e8144 ¤   ¤   ¤   return 0;
3a698e ¤   ¤   /* See if DEF provider is available */
e71af9 ¤   ¤   DEFLoadable = ex.CryptAcquireContext (&hProv, NULL, MS_DEF_PROV,
8d64c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
f8e5eb ¤   ¤   if (DEFLoadable)
4b1af3 ¤   ¤   ¤   ex.CryptReleaseContext (hProv);
cabfd2 ¤   ¤   ENHLoadable = ex.CryptAcquireContext (&hProv, NULL, MS_ENH_PROV,
c764c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
7f2499 ¤   ¤   if (ENHLoadable)
1c1af3 ¤   ¤   ¤   ex.CryptReleaseContext (hProv);
bff35a ¤   ¤   sCAPIuse = (DEFLoadable ? PGP_PKUSE_SIGN : 0) |
c2cca1 ¤   ¤   ¤   ¤   ···(ENHLoadable ? PGP_PKUSE_ENCRYPT : 0);
719371 ¤   }
c8821c ¤   return sCAPIuse;
64efe6 }
b127a8 /* Restore default optimizations */
c28548 #pragma optimize ("", on)
b7af5a
--f5e2 0001adb255040100216 Page 5 of pgpMSRSAGlue.c
e0af5a
d338e5 /*
1059d9 ·* This returns nonzero if the key is too big, returning the
47aecf ·* maximum number of bits that the library can accept.
4590c9 ·* We will also use it to check for constraints on how CAPI works.
0d592e ·* This may mean that we will return an error even when the key is
6c7ef9 ·* smaller than the max.
3d495d ·*/
33bba1 #define MAXSIZE 4096
cb4d2f int
534a31 rsaKeyTooBig(RSApub const *pub, RSAsec const *sec)
9abb36 {
f367ab ¤   if (pub) {
4d6b85 ¤   ¤   if (bnBits(&pub->n) > MAXSIZE)
168cd7 ¤   ¤   ¤   return MAXSIZE;
e4af5a
b79c7f ¤   ¤   if (bnBytes(&pub->e) > sizeof(DWORD))
378cd7 ¤   ¤   ¤   return MAXSIZE;
599371 ¤   }
fd8631 ¤   if (sec) {
c730cf ¤   ¤   if (bnBits(&sec->n) > MAXSIZE)
058cd7 ¤   ¤   ¤   return MAXSIZE;
7baf5a
f3852e ¤   ¤   if (bnBytes(&sec->e) > sizeof(DWORD))
9a8cd7 ¤   ¤   ¤   return MAXSIZE;
899371 ¤   }
742354 ¤   return 0; /* OK */
e4efe6 }
b0af5a
cde198 /* Tell the size needed for a PUBLICKEYBLOB from a RSApub */
e5598d static PGPSize
70c205 rpubk_size(RSApub const *pub)
edbb36 {
f1771a ¤   PGPUInt32 bits = MULOF(bnBits(&pub->n), 64);
5a82c2 ¤   PGPUInt32 len = bits/8;
65af5a
99bc9f ¤   return sizeof(PUBLICKEYBLOBHDR) + len;
b0efe6 }
c2af5a
87e436 /* Tell the size needed for a PRIVATEKEYBLOB from a RSAsec */
2b598d static PGPSize
ea0fc6 rprivk_size(RSAsec const *sec)
27bb36 {
522ba1 ¤   PGPUInt32 bits = MULOF(bnBits(&sec->n), 64);
c382c2 ¤   PGPUInt32 len = bits/8;
d1af5a
10a60c ¤   return sizeof(PRIVATEKEYBLOBHDR) + (9*len)/2;
89efe6 }
bdaf5a
e1f6ec /* Tell the size needed for a SIMPLEKEYBLOB given encryption mod bits */
ca598d static PGPSize
e781bd rsesk_size(PGPUInt32 modbits)
bfbb36 {
b21216 ¤   modbits = MULOF(modbits, 8);
70ae41 ¤   return sizeof(SIMPLEBLOBHDR) + modbits/8;
82efe6 }
57af5a
0baf5a
738135 /* Initialize a PUBLICKEYBLOB pubkey structure from a RSApub. */
b62978 static void
7fd4c4 rpubk_init(PUBLICKEYBLOBHDR *rpubk, RSApub const *pub)
eabb36 {
c1771a ¤   PGPUInt32 bits = MULOF(bnBits(&pub->n), 64);
3182c2 ¤   PGPUInt32 len = bits/8;
f256be ¤   PGPByte *bnbuf;
ffaf5a
412fe1 ¤   pgpClearMemory(rpubk, sizeof (*rpubk) + len);
85af5a
e28830 ¤   rpubk->header.bType = PUBLICKEYBLOB;
919ab5 ¤   rpubk->header.bVersion = BVERSION;
016b29 ¤   rpubk->header.aiKeyAlg = CALG_RSA_KEYX;
1aaf5a
--0a89 000efd4cc6c40100216 Page 6 of pgpMSRSAGlue.c
feafbb ¤   rpubk->rsapubkey.magic = RSAPUBMAGIC;
2c27fd ¤   rpubk->rsapubkey.bitlen = MULOF(bnBits(&pub->n), 8);
f22a5d ¤   bnExtractLittleBytes(&pub->e, (PGPByte *)&rpubk->rsapubkey.pubexp, 0,
9a9112 ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(rpubk->rsapubkey.pubexp));
b0af5a
95eff2 ¤   bnbuf = (PGPByte *)rpubk + sizeof(*rpubk);
a30a1d ¤   bnExtractLittleBytes(&pub->n, bnbuf, 0, len);
0aefe6 }
a1af5a
a8af5a
7db636 /* Initialize RSAREF privkey structure from a RSAsec. */
522978 static void
b35595 rprivk_init(PRIVATEKEYBLOBHDR *rprivk, RSAsec const *sec,
5a17a4 ¤   PGPMemoryMgrRef¤mgr, PGPBoolean fSign)
dbbb36 {
842ba1 ¤   PGPUInt32 bits = MULOF(bnBits(&sec->n), 64);
9982c2 ¤   PGPUInt32 len = bits/8;
0b9d46 ¤   BigNum dmodp, dmodq, tmp;
1756be ¤   PGPByte *bnbuf;
0eaf5a
da39d9 ¤   pgpClearMemory(rprivk, sizeof (*rprivk) + (9*len)/2);
45af5a
599946 ¤   /* Calculate d mod p-1 and d mod q-1 */
fb0202 ¤   bnBegin(&dmodp, mgr, TRUE);
e94a28 ¤   bnBegin(&dmodq, mgr, TRUE);
025c21 ¤   bnBegin(&tmp, mgr, TRUE);
e08d99 ¤   bnCopy(&tmp, &sec->p);
4bf1b8 ¤   bnSubQ(&tmp, 1);
8867f3 ¤   bnMod(&dmodp, &sec->d, &tmp);
2f9122 ¤   bnCopy(&tmp, &sec->q);
33f1b8 ¤   bnSubQ(&tmp, 1);
16f4ba ¤   bnMod(&dmodq, &sec->d, &tmp);
07af5a
7265b0 ¤   /* Fill in structure */
ccef46 ¤   rprivk->header.bType = PRIVATEKEYBLOB;
d9a5fc ¤   rprivk->header.bVersion = BVERSION;
d2ff3b ¤   rprivk->header.aiKeyAlg = fSign ? CALG_RSA_SIGN : CALG_RSA_KEYX;
0aaf5a
7aeb2a ¤   rprivk->rsapubkey.magic = RSAPRIVMAGIC;
8e4592 ¤   rprivk->rsapubkey.bitlen = MULOF(bnBits(&sec->n), 8);
411cca ¤   bnExtractLittleBytes(&sec->e, (PGPByte *)&rprivk->rsapubkey.pubexp, 0,
817d6c ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(rprivk->rsapubkey.pubexp));
e0af5a
ac8cb0 ¤   bnbuf = (PGPByte *)rprivk + sizeof(*rprivk);
639294 ¤   bnExtractLittleBytes(&sec->n, bnbuf, 0, len);
591449 ¤   bnbuf += len;
eb8309 ¤   /* CAPI uses convention p > q, the opposite of ours */
0243d4 ¤   bnExtractLittleBytes(&sec->q, bnbuf, 0, len/2);
28cbaa ¤   bnbuf += len/2;
6574b8 ¤   bnExtractLittleBytes(&sec->p, bnbuf, 0, len/2);
05cbaa ¤   bnbuf += len/2;
d351c8 ¤   bnExtractLittleBytes(&dmodq, bnbuf, 0, len/2);
e7cbaa ¤   bnbuf += len/2;
2566a4 ¤   bnExtractLittleBytes(&dmodp, bnbuf, 0, len/2);
accbaa ¤   bnbuf += len/2;
299e64 ¤   bnExtractLittleBytes(&sec->u, bnbuf, 0, len/2);
65cbaa ¤   bnbuf += len/2;
d9061b ¤   bnExtractLittleBytes(&sec->d, bnbuf, 0, len);
f0af5a
b10425 ¤   bnEnd(&dmodp);
92189e ¤   bnEnd(&dmodq);
5f1dd8 ¤   bnEnd(&tmp);
7eefe6 }
79af5a
e4af5a
b738e5 /*
d83f7f ·* Initialize a SIMPLEBLOB structure from a buffer, where the blob
239ff8 ·* will be decrypted with a public key of the specified size in bits
74a9bc ·* Note that rsesk is sensitive and should be allocated securely.
bd495d ·*/
d32978 static void
efa9f5 rsesk_initfrom_buf(SIMPLEBLOBHDR *rsesk, PGPByte const *in, unsigned len,
--4a72 0002bbdd66340100216 Page 7 of pgpMSRSAGlue.c
8ac2fe ¤   ¤   ¤   ¤   ···PGPUInt32 modbits, PGPMemoryMgrRef mgr,
c9d655 ¤   ¤   ¤   ¤   ···PGPRandomContext const *rc)
90bb36 {
105d79 ¤   PGPUInt32 modlen;
8756be ¤   PGPByte *bnbuf;
9c8024 ¤   BigNum skbn;
2daf5a
ee1216 ¤   modbits = MULOF(modbits, 8);
0a0f4a ¤   modlen = modbits / 8;
16af5a
baf913 ¤   pgpClearMemory(rsesk, sizeof (*rsesk) + modlen);
94af5a
4f9539 ¤   rsesk->header.bType = SIMPLEBLOB;
4d7793 ¤   rsesk->header.bVersion = BVERSION;
50d7d5 ¤   rsesk->header.aiKeyAlg = CALG_3DES;
f82b69 ¤   rsesk->algid = CALG_RSA_KEYX;
08af5a
13b487 ¤   bnbuf = (PGPByte *)rsesk + sizeof(*rsesk);
e1af5a
df4261 ¤   bnBegin (&skbn, mgr, TRUE);
00605b ¤   pgpPKCSPack (&skbn, in, len, PKCS_PAD_ENCRYPTED, modlen, rc);
645582 ¤   bnExtractLittleBytes (&skbn, bnbuf, 0, modlen);
cbaf5a
44ad78 ¤   bnEnd (&skbn);
f6efe6 }
60af5a
2138e5 /*
1f3f7f ·* Initialize a SIMPLEBLOB structure from a buffer, where the blob
e19ff8 ·* will be decrypted with a public key of the specified size in bits
51495d ·*/
2d2978 static void
c35fd7 rsesk_initfrom_bn(SIMPLEBLOBHDR *rsesk, BigNum *bn, PGPUInt32 modbits)
e6bb36 {
cb5d79 ¤   PGPUInt32 modlen;
8056be ¤   PGPByte *bnbuf;
8caf5a
961216 ¤   modbits = MULOF(modbits, 8);
cd0f4a ¤   modlen = modbits / 8;
57af5a
6df913 ¤   pgpClearMemory(rsesk, sizeof (*rsesk) + modlen);
c5af5a
819539 ¤   rsesk->header.bType = SIMPLEBLOB;
c37793 ¤   rsesk->header.bVersion = BVERSION;
6dd7d5 ¤   rsesk->header.aiKeyAlg = CALG_3DES;
452b69 ¤   rsesk->algid = CALG_RSA_KEYX;
c4af5a
7eb487 ¤   bnbuf = (PGPByte *)rsesk + sizeof(*rsesk);
fbef78 ¤   bnExtractLittleBytes (bn, bnbuf, 0, modlen);
86efe6 }
acaf5a
11af5a
2338e5 /*
b9addc ·* Encrypt a buffer holding a session key with an RSA public key
c3495d ·*/
d94d2f int
e5ab93 rsaPublicEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
93e64b ¤   RSApub const *pub, PGPRandomContext const *rc)
f4bb36 {
6c2772 ¤   HCRYPTPROV hProv = 0;
1d4199 ¤   HCRYPTKEY hDummy = 0;
35a5e6 ¤   HCRYPTKEY hKey = 0;
c82780 ¤   HCRYPTKEY hSession = 0;
db462d ¤   PUBLICKEYBLOBHDR *rpubk = NULL;
4119bb ¤   SIMPLEBLOBHDR *rsesk = NULL;
68e6eb ¤   PGPUInt32 rpubksize;
6ab7d1 ¤   PGPUInt32 rsesksize;
a807a2 ¤   PGPByte *rseskdata;
fe0c5c ¤   PGPMemoryMgrRef mgr = pub->n.mgr;
60c55b ¤   PGPError err = kPGPError_NoErr;
faaf5a
cada15 ¤   /* Set the return number to 0 to start */
2bf43e ¤   (void)bnSetQ(bn, 0);
--e88e 0008d93375140100216 Page 8 of pgpMSRSAGlue.c
e0af5a
de584d ¤   if (!(pgpCAPIuse() & PGP_PKUSE_ENCRYPT))
81590e ¤   ¤   return kPGPError_PublicKeyUnimplemented;
f0af5a
24eda8 ¤   /* Get handle to the enhanced PROV_RSA_FULL provider */
23681e ¤   /* Use our reserved container name, always start with an empty one */
2bdf5a ¤   ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
c0bdf4 ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_DELETEKEYSET);
fb2342 ¤   if(!ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV,
acf7d2 ¤   ¤   ¤   ¤   ¤   ¤   PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
46761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
5c97ed ¤   ¤   goto error;
cc9371 ¤   }
17af5a
53904b ¤   /* Initialize CAPI public key structure */
ab9ed2 ¤   rpubksize = rpubk_size (pub);
78af5a
cb6f88 ¤   rpubk = PGPNewData (mgr, rpubksize, 0);
ca2c04 ¤   if (IsNull (rpubk)) {
f9bce1 ¤   ¤   err = kPGPError_OutOfMemory;
ab97ed ¤   ¤   goto error;
a49371 ¤   }
0aaf5a
a76dbc ¤   rpubk_init(rpubk, pub);
84af5a
3d3f61 ¤   /* Create dummy key for importing session key */
fe8cd1 ¤   if (!ex.CryptImportKey (hProv, (BYTE *)&dummyKeyBlob,
6133c8 ¤   ¤   ¤   ¤   ¤   ¤   sizeof(dummyKeyBlob), 0, 0, &hDummy)) {
0d761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
fd97ed ¤   ¤   goto error;
959371 ¤   }
81af5a
96e9e2 ¤   /* Initialize and import session key */
7782f6 ¤   rsesksize = rsesk_size (DUMMYBITS);
0aaf5a
ddbbf1 ¤   rsesk = PGPNewSecureData (mgr, rsesksize, 0);
3d8b67 ¤   if (IsNull (rsesk)) {
cdbce1 ¤   ¤   err = kPGPError_OutOfMemory;
3997ed ¤   ¤   goto error;
8e9371 ¤   }
16531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
8283d2 ¤   rsesk_initfrom_buf (rsesk, in, len, DUMMYBITS, mgr, rc);
e6af5a
a2df15 ¤   if (!ex.CryptImportKey (hProv, (BYTE *)rsesk, rsesksize, hDummy,
78ddb2 ¤   ¤   ¤   ¤   ¤   ¤   ·CRYPT_EXPORTABLE, &hSession)) {
be761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
1197ed ¤   ¤   goto error;
0e9371 ¤   }
b75ecf ¤   PGPFreeData (rsesk);
d50218 ¤   rsesk = NULL;
e6af5a
d6d21b ¤   /* Export session key now encrypted with user's public key */
72ccb1 ¤   if (!ex.CryptImportKey (hProv, (BYTE *)rpubk, rpubksize, 0, 0, &hKey)) {
33761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
3497ed ¤   ¤   goto error;
5c9371 ¤   }
c5af5a
a9f41e ¤   /* CAPI ovewrites more data than it should with nonstandard key sizes */
847319 ¤   rsesksize = sizeof(*rsesk) + MULOF(bnBytes(&pub->n), 8);
071464 ¤   rsesk = (SIMPLEBLOBHDR *)PGPNewData (mgr, rsesksize, 0);
800e54 ¤   if (!rsesk) {
2abce1 ¤   ¤   err = kPGPError_OutOfMemory;
5697ed ¤   ¤   goto error;
389371 ¤   }
1caf5a
e814c6 ¤   pgpAssert (sizeof(rsesksize) == sizeof(DWORD));
df0d25 ¤   if (!ex.CryptExportKey (hSession, hKey, SIMPLEBLOB, 0, (BYTE *)rsesk,
3f7234 ¤   ¤   ¤   ¤   ¤   ¤   ···&rsesksize)) {
d6761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
3c97ed ¤   ¤   goto error;
5a9371 ¤   }
8d2f55 ¤   pgpAssert (rsesksize == sizeof(*rsesk) + bnBytes(&pub->n));
--c70a 0006b5086e540100216 Page 9 of pgpMSRSAGlue.c
e0af5a
d079a7 ¤   /* Return in PGP bn format */
9ceb8d ¤   rseskdata = (PGPByte *)rsesk + sizeof(*rsesk);
18f256 ¤   bnInsertLittleBytes(bn, rseskdata, 0, bnBytes(&pub->n));
b4af5a
8d60ff error:
ffaf5a
4cb6a7 ¤   if (hSession)
0457de ¤   ¤   ex.CryptDestroyKey (hSession);
a83a7b ¤   if (hKey)
3eec5f ¤   ¤   ex.CryptDestroyKey (hKey);
061837 ¤   if (hDummy)
0bf9c6 ¤   ¤   ex.CryptDestroyKey (hDummy);
e5af5a
e7ac30 ¤   ex.CryptReleaseContext(hProv, 0);
d9df5a ¤   ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
f6ef69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_DELETEKEYSET);
39af5a
8fd50b ¤   if (rsesk) {
447cbf ¤   ¤   pgpClearMemory (rsesk, rsesksize);
7c6a92 ¤   ¤   PGPFreeData (rsesk);
f49371 ¤   }
43ac89 ¤   if (rpubk) {
f6c476 ¤   ¤   pgpClearMemory (rpubk, rpubksize);
9d3f48 ¤   ¤   PGPFreeData (rpubk);
269371 ¤   }
f8af5a
d65ea8 ¤   return err;
4cefe6 }
e7af5a
8daf5a
e6af5a
8f38e5 /*
d39e39 ·* Performs an RSA decryption. ·Returns a prefix of the unwrapped
b5140d ·* data in the given buf. ·Returns the length of the untruncated
e05d6b ·* data, which may exceed "len". Returns <0 on error.
f1495d ·*/
544d2f int
20749c rsaPrivateDecrypt(PGPByte *outbuf, unsigned len, BigNum *bn,
4284e6 ¤   RSAsec const *sec)
09bb36 {
712772 ¤   HCRYPTPROV hProv = 0;
e94199 ¤   HCRYPTKEY hDummy = 0;
c2a5e6 ¤   HCRYPTKEY hKey = 0;
a92780 ¤   HCRYPTKEY hSession = 0;
50e333 ¤   PRIVATEKEYBLOBHDR *rprivk = NULL;
c019bb ¤   SIMPLEBLOBHDR *rsesk = NULL;
f09e31 ¤   PGPUInt32 rprivksize;
eeb7d1 ¤   PGPUInt32 rsesksize;
3207a2 ¤   PGPByte *rseskdata;
b29353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
d9c55b ¤   PGPError err = kPGPError_NoErr;
08064c ¤   BigNum bnsk;
0aaf5a
e9584d ¤   if (!(pgpCAPIuse() & PGP_PKUSE_ENCRYPT))
d0590e ¤   ¤   return kPGPError_PublicKeyUnimplemented;
e8af5a
7f4cd3 ¤   /* CAPI has bugs with keys not mult of 64 bits */
7ed5f9 ¤   if ((bnBytes(bn) % 8) != 0)
44a54a ¤   ¤   return kPGPError_CAPIUnsupportedKey;
cb1b52 ¤   ¤
5beda8 ¤   /* Get handle to the enhanced PROV_RSA_FULL provider */
cc681e ¤   /* Use our reserved container name, always start with an empty one */
8ddf5a ¤   ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
e5bdf4 ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_DELETEKEYSET);
282342 ¤   if(!ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV,
0cf7d2 ¤   ¤   ¤   ¤   ¤   ¤   PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
60761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
b397ed ¤   ¤   goto error;
e79371 ¤   }
5baf5a
6b4a9d ¤   /* Initialize and import private key structure */
--9e05 0003a49d24540100216 Page 10 of pgpMSRSAGlue.c
4b76ac ¤   rprivksize = rprivk_size (sec);
56ee7c ¤   rprivk = PGPNewSecureData (mgr, rprivksize, 0);
d88ce7 ¤   if (IsNull (rprivk)) {
73bce1 ¤   ¤   err = kPGPError_OutOfMemory;
6b97ed ¤   ¤   goto error;
159371 ¤   }
772a11 ¤   rprivk_init(rprivk, sec, mgr, FALSE);
1eaf5a
4fd1db ¤   if (!ex.CryptImportKey (hProv, (BYTE *)rprivk, rprivksize, 0, 0, &hKey)) {
8e761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
3b97ed ¤   ¤   goto error;
969371 ¤   }
82af5a
a216b9 ¤   /* Create SIMPLEBLOB from encrypted session key in bn */
153b02 ¤   rsesksize = rsesk_size (bnBits(&sec->n));
33af5a
4842e7 ¤   rsesk = PGPNewData (mgr, rsesksize, 0);
288b67 ¤   if (IsNull (rsesk)) {
cfbce1 ¤   ¤   err = kPGPError_OutOfMemory;
b597ed ¤   ¤   goto error;
c19371 ¤   }
54ccab ¤   rsesk_initfrom_bn (rsesk, bn, bnBits(&sec->n));
d4af5a
edbd5e ¤   /* Import the blob, decrypting it with the private key */
e5af91 ¤   if (!ex.CryptImportKey (hProv, (BYTE *)rsesk, rsesksize, hKey,
18ddb2 ¤   ¤   ¤   ¤   ¤   ¤   ·CRYPT_EXPORTABLE, &hSession)) {
5b761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
2b97ed ¤   ¤   goto error;
ed9371 ¤   }
eb5ecf ¤   PGPFreeData (rsesk);
630218 ¤   rsesk = NULL;
51af5a
b524d8 ¤   /* Create a dummy key suitable for clearly exporting the session key */
ce8cd1 ¤   if (!ex.CryptImportKey (hProv, (BYTE *)&dummyKeyBlob,
15e29b ¤   ¤   ¤   ¤   ¤   ¤   ···sizeof(dummyKeyBlob), 0, 0, &hDummy)) {
08761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
c997ed ¤   ¤   goto error;
cd9371 ¤   }
63af5a
e74cd3 ¤   /* Export session key in the clear as a PKCS1 formatted SIMPLEBLOB */
765b55 ¤   rsesksize = sizeof (*rsesk) + DUMMYBITS/8;
f442e7 ¤   rsesk = PGPNewData (mgr, rsesksize, 0);
008b67 ¤   if (IsNull (rsesk)) {
5fbce1 ¤   ¤   err = kPGPError_OutOfMemory;
5497ed ¤   ¤   goto error;
4f9371 ¤   }
d3af5a
9a14c6 ¤   pgpAssert (sizeof(rsesksize) == sizeof(DWORD));
908fd7 ¤   if (!ex.CryptExportKey (hSession, hDummy, SIMPLEBLOB, 0, (BYTE *)rsesk,
b97234 ¤   ¤   ¤   ¤   ¤   ¤   ···&rsesksize)) {
30761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
f997ed ¤   ¤   goto error;
0b9371 ¤   }
46b214 ¤   pgpAssert (rsesksize == sizeof(*rsesk) + DUMMYBITS/8);
47af5a
022636 ¤   /* Unpack PKCS formatted exported session key and return it */
d7eb8d ¤   rseskdata = (PGPByte *)rsesk + sizeof(*rsesk);
445331 ¤   bnBegin (&bnsk, mgr, TRUE);
33a44f ¤   bnInsertLittleBytes (&bnsk, rseskdata, 0, DUMMYBITS/8);
f95617 ¤   err = (PGPError) pgpPKCSUnpack(outbuf, len, &bnsk, PKCS_PAD_ENCRYPTED,
e8bef6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···DUMMYBITS/8);
a842b0 ¤   bnEnd (&bnsk);
dcaf5a
4c60ff error:
42af5a
fdb6a7 ¤   if (hSession)
9357de ¤   ¤   ex.CryptDestroyKey (hSession);
753a7b ¤   if (hKey)
a5ec5f ¤   ¤   ex.CryptDestroyKey (hKey);
711837 ¤   if (hDummy)
fcf9c6 ¤   ¤   ex.CryptDestroyKey (hDummy);
3aaf5a
--c12e 00045d7bc0540100216 Page 11 of pgpMSRSAGlue.c
ecac30 ¤   ex.CryptReleaseContext(hProv, 0);
76df5a ¤   ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
85ef69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_DELETEKEYSET);
56af5a
6cd50b ¤   if (rsesk) {
9d7cbf ¤   ¤   pgpClearMemory (rsesk, rsesksize);
926a92 ¤   ¤   PGPFreeData (rsesk);
709371 ¤   }
20464c ¤   if (rprivk) {
de7ef6 ¤   ¤   pgpClearMemory (rprivk, rprivksize);
7ff3b6 ¤   ¤   PGPFreeData (rprivk);
c49371 ¤   }
9caf5a
d45ea8 ¤   return err;
1fefe6 }
c6af5a
d0af5a
fcaf5a
d838e5 /*
0e601d ·* Do an RSA signing operation using the secret key on the specified hash
77495d ·*/
fb4d2f int
333dab rsaSignHash(BigNum *bn, RSAsec const *sec, PGPHashVTBL const *h,
304359 ¤   PGPByte const *hash)
0bbb36 {
872772 ¤   HCRYPTPROV hProv = 0;
79a5e6 ¤   HCRYPTKEY hKey = 0;
e9cde5 ¤   HCRYPTHASH hHash = 0;
aae333 ¤   PRIVATEKEYBLOBHDR *rprivk = NULL;
5f55d2 ¤   ALG_ID capihashalg;
6f9e31 ¤   PGPUInt32 rprivksize;
764ba4 ¤   PGPByte *sigbuf = NULL;
925519 ¤   PGPUInt32 sigsize;
099353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
c3c55b ¤   PGPError err = kPGPError_NoErr;
88af5a
05d8d7 ¤   /* SET the return number to 0 to start */
4df43e ¤   (void)bnSetQ(bn, 0);
ddaf5a
4d280f ¤   if (!(pgpCAPIuse() & PGP_PKUSE_SIGN))
52590e ¤   ¤   return kPGPError_PublicKeyUnimplemented;
48af5a
5e4cd3 ¤   /* CAPI has bugs with keys not mult of 64 bits */
001bef ¤   if ((bnBytes(&sec->n) % 8) != 0)
8fa54a ¤   ¤   return kPGPError_CAPIUnsupportedKey;
351b52 ¤   ¤
acd9a6 ¤   /* Get handle to the base PROV_RSA_FULL provider */
65681e ¤   /* Use our reserved container name, always start with an empty one */
f1be66 ¤   ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_DEF_PROV, PROV_RSA_FULL,
67bdf4 ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_DELETEKEYSET);
4f96a5 ¤   if(!ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_DEF_PROV,
bef730 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
2e761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
a597ed ¤   ¤   goto error;
639371 ¤   }
a7af5a
6ce802 ¤   /* Determine what hash algorithm to use */
04b6da ¤   if (h->algorithm == kPGPHashAlgorithm_MD5) {
a3c621 ¤   ¤   capihashalg = CALG_MD5;
568836 ¤   } else if (h->algorithm == kPGPHashAlgorithm_MD2) {
844a24 ¤   ¤   capihashalg = CALG_MD2;
868215 ¤   } else if (h->algorithm == kPGPHashAlgorithm_SHA) {
c36754 ¤   ¤   capihashalg = CALG_SHA;
6ff037 ¤   } else {
ff761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
b797ed ¤   ¤   goto error;
789371 ¤   }
7caf5a
781ef5 ¤   /* Create and load the hash value */
d3c056 ¤   if (!ex.CryptCreateHash (hProv, capihashalg, 0, 0, &hHash)) {
df761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
4597ed ¤   ¤   goto error;
--6d8a 0002c349ddb40100216 Page 12 of pgpMSRSAGlue.c
a19371 ¤   }
e55197 ¤   if (!ex.CryptSetHashParam (hHash, HP_HASHVAL, (BYTE *)hash, 0)) {
76761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
9e97ed ¤   ¤   goto error;
089371 ¤   }
4caf5a
dec0fe ¤   /* Initialize private key structure */
e976ac ¤   rprivksize = rprivk_size (sec);
0bee7c ¤   rprivk = PGPNewSecureData (mgr, rprivksize, 0);
db8ce7 ¤   if (IsNull (rprivk)) {
0ebce1 ¤   ¤   err = kPGPError_OutOfMemory;
0697ed ¤   ¤   goto error;
989371 ¤   }
54ccf4 ¤   rprivk_init(rprivk, sec, mgr, TRUE);
f4af5a
1cd8af ¤   /*
b28153 ¤   ·* Importing private key into an otherwise empty key container should
e82472 ¤   ·* make it be used as the signing key.
7aa4e3 ¤   ·*/
deaf5a
c9d1db ¤   if (!ex.CryptImportKey (hProv, (BYTE *)rprivk, rprivksize, 0, 0, &hKey)) {
73761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
cd97ed ¤   ¤   goto error;
f99371 ¤   }
1faf5a
01951a ¤   /* Perform the signature operation */
64ba8f ¤   sigsize = bnBytes (&sec->n);
3c0f2d ¤   sigbuf = PGPNewData (mgr, sigsize, 0);
29f97b ¤   if (IsNull (sigbuf)) {
7fbce1 ¤   ¤   err = kPGPError_OutOfMemory;
2f97ed ¤   ¤   goto error;
349371 ¤   }
a1af5a
eeaaba ¤   pgpAssert (sizeof(sigsize) == sizeof(DWORD));
2c6c52 ¤   if (!ex.CryptSignHash (hHash, AT_SIGNATURE, 0, 0, sigbuf, &sigsize)) {
db761b ¤   ¤   err = kPGPError_PublicKeyUnimplemented;
5151b0 ¤   ¤   sigsize = 0;
1897ed ¤   ¤   goto error;
0d9371 ¤   }
ffe6e6 ¤   pgpAssert (sigsize = bnBytes(&sec->n));
20af5a
bd79a7 ¤   /* Return in PGP bn format */
70e902 ¤   bnInsertLittleBytes(bn, sigbuf, 0, sigsize);
6467c5 ¤
7160ff error:
d2af5a
463a7b ¤   if (hKey)
b9ec5f ¤   ¤   ex.CryptDestroyKey (hKey);
dcca06 ¤   if (hHash)
47d47f ¤   ¤   ex.CryptDestroyHash (hHash);
63af5a
09ac30 ¤   ex.CryptReleaseContext(hProv, 0);
d1df5a ¤   ex.CryptAcquireContext(&hProv, PGPCONTAINER, MS_ENH_PROV, PROV_RSA_FULL,
d6ef69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_DELETEKEYSET);
09af5a
af6d5a ¤   if (sigbuf) {
4d7460 ¤   ¤   pgpClearMemory (sigbuf, sigsize);
10b73c ¤   ¤   PGPFreeData (sigbuf);
7d9371 ¤   }
3d464c ¤   if (rprivk) {
a67ef6 ¤   ¤   pgpClearMemory (rprivk, rprivksize);
d6f3b6 ¤   ¤   PGPFreeData (rprivk);
889371 ¤   }
f4af5a
505ea8 ¤   return err;
07efe6 }
45af5a
37af5a
d138e5 /*
d0818c ·* Return TRUE if the bignum holding the signature value is valid.
4e495d ·*/
2c7750 PGPBoolean
--026a 0004de83a5d40100216 Page 13 of pgpMSRSAGlue.c
f31939 rsaVerifyHashSignature(BigNum *bn, RSApub const *pub, PGPHashVTBL const *h,
894359 ¤   PGPByte const *hash)
e4bb36 {
c52772 ¤   HCRYPTPROV hProv = 0;
37a5e6 ¤   HCRYPTKEY hKey = 0;
32cde5 ¤   HCRYPTHASH hHash = 0;
5e462d ¤   PUBLICKEYBLOBHDR *rpubk = NULL;
ed55d2 ¤   ALG_ID capihashalg;
a3e6eb ¤   PGPUInt32 rpubksize;
754ba4 ¤   PGPByte *sigbuf = NULL;
6b5519 ¤   PGPUInt32 sigsize;
949353 ¤   PGPMemoryMgrRef¤mgr¤= bn->mgr;
68c6e9 ¤   PGPBoolean valid = FALSE;
e3af5a
29280f ¤   if (!(pgpCAPIuse() & PGP_PKUSE_SIGN))
0f98aa ¤   ¤   return FALSE;
ecaf5a
b5d9a6 ¤   /* Get handle to the base PROV_RSA_FULL provider */
769551 ¤   /* Signature verification does not need a key container */
c3af5a
b78d10 #if PGP_USECAPIFORMD2¤  /* [ */
ac8606 ¤   if (h->algorithm == kPGPHashAlgorithm_MD2) {
3f3dd7 ¤   ¤   hProv = ((HCRYPTPROV *)hash)[0];
6f2be7 ¤   } else
627454 #endif
38c7a1 ¤   {
89b8ad ¤   ¤   if (!ex.CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
b6cb4c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   CRYPT_VERIFYCONTEXT)) {
54ed19 ¤   ¤   ¤   goto error;
140fe4 ¤   ¤   }
309371 ¤   }
3aaf5a
cce802 ¤   /* Determine what hash algorithm to use */
f1b6da ¤   if (h->algorithm == kPGPHashAlgorithm_MD5) {
7dc621 ¤   ¤   capihashalg = CALG_MD5;
208836 ¤   } else if (h->algorithm == kPGPHashAlgorithm_MD2) {
f54a24 ¤   ¤   capihashalg = CALG_MD2;
a58215 ¤   } else if (h->algorithm == kPGPHashAlgorithm_SHA) {
6c6754 ¤   ¤   capihashalg = CALG_SHA;
0af037 ¤   } else {
fa97ed ¤   ¤   goto error;
539371 ¤   }
78af5a
b01ef5 ¤   /* Create and load the hash value */
a48d10 #if PGP_USECAPIFORMD2¤  /* [ */
c78606 ¤   if (h->algorithm == kPGPHashAlgorithm_MD2) {
2468dc ¤   ¤   hHash = ((HCRYPTHASH *)hash)[1];
392be7 ¤   } else
96b437 #endif /* ] */
21c7a1 ¤   {
47d575 ¤   ¤   if (!ex.CryptCreateHash (hProv, capihashalg, 0, 0, &hHash)) {
6ced19 ¤   ¤   ¤   goto error;
c00fe4 ¤   ¤   }
824721 ¤   ¤   if (!ex.CryptSetHashParam (hHash, HP_HASHVAL, (BYTE *)hash, 0)) {
3ded19 ¤   ¤   ¤   goto error;
a20fe4 ¤   ¤   }
db9371 ¤   }
baaf5a
d5f52b ¤   /* Initialize and import public key structure */
d99ed2 ¤   rpubksize = rpubk_size (pub);
fd6f88 ¤   rpubk = PGPNewData (mgr, rpubksize, 0);
ff2c04 ¤   if (IsNull (rpubk)) {
f497ed ¤   ¤   goto error;
3c9371 ¤   }
2c6dbc ¤   rpubk_init(rpubk, pub);
9caf5a
c0ccb1 ¤   if (!ex.CryptImportKey (hProv, (BYTE *)rpubk, rpubksize, 0, 0, &hKey)) {
2a97ed ¤   ¤   goto error;
0f9371 ¤   }
77af5a
44adbe ¤   /* Extract and verify signature */
4d6de4 ¤   sigsize = bnBytes(&pub->n);
--09fc 0018f27f97540100216 Page 14 of pgpMSRSAGlue.c
600f2d ¤   sigbuf = PGPNewData (mgr, sigsize, 0);
c0f97b ¤   if (IsNull (sigbuf)) {
4297ed ¤   ¤   goto error;
cd9371 ¤   }
40af5a
972d7b ¤   bnExtractLittleBytes(bn, sigbuf, 0, sigsize);¤
a1af5a
c06d2b ¤   valid = ex.CryptVerifySignature (hHash, sigbuf, sigsize, hKey, 0, 0);
5caf5a
3460ff error:
9eaf5a
3f3a7b ¤   if (hKey)
10ec5f ¤   ¤   ex.CryptDestroyKey (hKey);
34ca06 ¤   if (hHash)
ead47f ¤   ¤   ex.CryptDestroyHash (hHash);
f0af5a
1fac30 ¤   ex.CryptReleaseContext(hProv, 0);
1baf5a
216d5a ¤   if (sigbuf) {
2c7460 ¤   ¤   pgpClearMemory (sigbuf, sigsize);
3cb73c ¤   ¤   PGPFreeData (sigbuf);
879371 ¤   }
84ac89 ¤   if (rpubk) {
2fc476 ¤   ¤   pgpClearMemory (rpubk, rpubksize);
f93f48 ¤   ¤   PGPFreeData (rpubk);
a99371 ¤   }
17af5a
c95830 ¤   return valid;
8aefe6 }
73af5a
9aaf5a
8f9514 #endif¤ /* ] PGP_USECAPIFORRSA */
--6036 001af72235440100217 Page 1 of pgpMSRSAGlue.h
8695d7 /*·
28323d ·* pgpMSRSAGlue.h - RSA support using Microsoft CAPI
68775e ·*
bae39d ·* This is a PRIVATE header file, for use only within the PGP Library.
782979 ·* You should not be using these functions in an application.
c8775e ·*
8dad40 ·* $Id: pgpMSRSAGlue.h,v 1.1 1998/07/10 04:16:13 hal Exp $
be495d ·*/
ebf983 #ifndef Included_pgpMSRSAGlue_h
423ce0 #define Included_pgpMSRSAGlue_h
17af5a
1c3051 #include "pgpSDKBuildFlags.h"
82af5a
89f297 #if PGP_USECAPIFORMD2 && !PGP_USECAPIFORRSA
1c4d0a #error "PGP_USECAPIFORMD2 requires PGP_USECAPIFORRSA"
8e7454 #endif
5faf5a
8df847 #if PGP_USECAPIFORRSA
11af5a
ec2502 /* Include CAPI headers */
e85655 #include <windows.h>
feca87 #define _WIN32_WINNT 0x0400
aec820 #include <wincrypt.h>
e2af5a
2ad11f #include "pgpUsuals.h"
24af5a
da99c6 PGP_BEGIN_C_DECLARATIONS
5aaf5a
e595d7 /*·
203e28 ·* Data structure for dynamic access to CAPI. ·Not all users have it
ff9758 ·* so we don't want to statically link with it.
4c495d ·*/
0c7f4b typedef struct _CAPIEntries {
ee730c ¤   FARPROC CryptAcquireContext;
304102 ¤   FARPROC CryptReleaseContext;
f9bc75 ¤   FARPROC CryptImportKey;
471063 ¤   FARPROC CryptExportKey;
54da5c ¤   FARPROC CryptDestroyKey;
d8723d ¤   FARPROC CryptCreateHash;
4a126b ¤   FARPROC CryptHashData;
c47c94 ¤   FARPROC CryptSetHashParam;
290957 ¤   FARPROC CryptDestroyHash;
9707bd ¤   FARPROC CryptVerifySignature;
454d13 ¤   FARPROC CryptSignHash;
42a6e5 } CAPIEntries;
96af5a
f87af9 /* Test for CAPI availability */
7fbccf PGPUInt32
2654c8 pgpCAPIuse (void);
ebaf5a
dfaf5a
5f1254 PGP_END_C_DECLARATIONS
01af5a
e11bad #endif /* PGP_USECAPIFORRSA */
e4af5a
af471a #endif /* !Included_pgpMSRSAGlue_h */
--20c9 000d19e257240100218 Page 1 of pgpMakeSig.c
bc38e5 /*
a3fad6 ·* $Id: pgpMakeSig.c,v 1.30 1998/06/11 18:28:19 hal Exp $
94495d ·*/
2baf5a
06e2ff #include "pgpConfig.h"
c4324c #include <string.h>
42af5a
0fa146 #include "pgpDebug.h"
59c305 #include "pgpMakeSig.h"
bf5417 #include "pgpHashPriv.h"
2a2f8d #include "pgpErrors.h"
ca0d08 #include "pgpMem.h"
109c38 #include "pgpPktByte.h"
47cdc2 #include "pgpPubKey.h"
e926e3 #include "pgpRngPub.h"
8cf5ab #include "pgpSigSpec.h"
afd11f #include "pgpUsuals.h"
ebaf5a
12af5a
c81b1c #define CRIT(flags) ·(((flags)&kPGPSigFlags_Critical) ? SIGSUBF_CRITICAL : 0)
6faf5a
e8af5a
e58645 /* Forward declaration */
37beb7 static int
b8b081 pgpMakeSigSubs (PGPByte *buf, PGPSigSpec const *spec,
fa0b3f ¤   ·PGPRandomContext const *rc, PGPHashContext const *hc);
42af5a
446d09 /* True if will need to be done as a V4 sig */
0ebeb7 static int
be5f9f pgpV4Sig (PGPSigSpec const *spec)
1bbb36 {
6f9ff2 ¤   return pgpSigSpecVersion( spec ) >= PGPVERSION_4;
e2efe6 }
39af5a
8f92b5 /* The maximum size of the signature */
194d2f int
609990 pgpMakeSigMaxSize(PGPSigSpec const *spec)
60bb36 {
ea1613 ¤   size_t extralen;
7ac120 ¤   char *regExp;
f8af5a
de6ff3 ¤   if (pgpV4Sig (spec)) {
cc5e43 ¤   ¤   PGPByte *dummyptr;
c90f5f ¤   ¤   PGPUInt32 dummyuint;
4eeff8 ¤   ¤   PGPBoolean dummybool;
ac496e ¤   ¤   PGPByte dummybyte;
1e39fa ¤   ¤   size_t krkeylen;
182a1e ¤   ¤   int i;
4baf5a
ab0a3e ¤   ¤   if (pgpSigSpecPrefAlgs(spec, &dummyptr, &extralen)
ed245a ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present) {
0a5f4c ¤   ¤   ¤   extralen += 2;
f60fe4 ¤   ¤   }
2bea9a ¤   ¤   extralen += 2 + 8;¤ ¤   /* Keyid subpacket */
9cfcb3 ¤   ¤   extralen += 2 + 4;¤ ¤   /* Sig creation subpacket */
b6ab83 ¤   ¤   if (pgpSigSpecSigExpiration(spec, &dummyuint) & kPGPSigFlags_Present)
dedb2b ¤   ¤   ¤   extralen += 2 + 4;
33a57d ¤   ¤   if (pgpSigSpecExportable(spec, &dummybool) & kPGPSigFlags_Present)
1ce296 ¤   ¤   ¤   extralen += 2 + 1;
60af3f ¤   ¤   if (pgpSigSpecRevocable(spec, &dummybool) & kPGPSigFlags_Present)
9be296 ¤   ¤   ¤   extralen += 2 + 1;
c2629b ¤   ¤   if (pgpSigSpecTrustLevel(spec, &dummybyte, &dummybyte)
66c3f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present)
3e0df2 ¤   ¤   ¤   extralen += 2 + 2;
5a8774 ¤   ¤   if (pgpSigSpecRegExp(spec, &regExp) & kPGPSigFlags_Present )
736c63 ¤   ¤   ¤   extralen += 2 + strlen(regExp) + 1;
b9fe8c ¤   ¤   if (pgpSigSpecKeyExpiration(spec, &dummyuint) & kPGPSigFlags_Present)
f7db2b ¤   ¤   ¤   extralen += 2 + 4;
85b360 ¤   ¤   for (i=0;
7e8d66 ¤   ¤   ¤   ·pgpSigSpecAdditionalRecipientRequest (spec, &dummyptr,
69fed9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&krkeylen, i) &
d124b0 ¤   ¤   ¤   ¤   ·kPGPSigFlags_Present;
--6874 0001a2541f340100218 Page 2 of pgpMakeSig.c
59b3f3 ¤   ¤   ¤   ¤   ¤   ++i)
d2a89a ¤   ¤   ¤   extralen += 2 + krkeylen;
3db360 ¤   ¤   for (i=0;
ce76dc ¤   ¤   ¤   ·pgpSigSpecRevocationKey (spec, &dummyptr, &krkeylen, i) &
a324b0 ¤   ¤   ¤   ¤   ·kPGPSigFlags_Present;
b2b3f3 ¤   ¤   ¤   ¤   ¤   ++i)
b0a89a ¤   ¤   ¤   extralen += 2 + krkeylen;
2f4c83 ¤   ¤   /* 4 bytes before subpackets, 2*2 length fields, 2 bytes of hash */
8e2b78 ¤   ¤   return 10 + extralen + pgpSecKeyMaxsig(pgpSigSpecSeckey(spec),
6994d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPPublicKeyMessageFormat_PGP);
b5f037 ¤   } else {
e92912 ¤   ¤   /* Old format */
bce5c5 ¤   ¤   (void)pgpSigSpecExtra(spec, &extralen);
4e0f1f ¤   ¤   return 14 + extralen + pgpSecKeyMaxsig(pgpSigSpecSeckey(spec),
e594d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPPublicKeyMessageFormat_PGP);
259371 ¤   }
68efe6 }
b267c5 ¤
1b38e5 /*
122e7c ·* Given a buffer of at least "pgpMakeSigMaxSize" bytes, make a signature
66658e ·* into it and return the size of the signature, or 0.
57775e ·*
18fbe1 ·* Format of signature packets:
11775e ·*
b763e8 ·* ·····Offset ·Length ·Meaning
38c28b ·* ······0 ·····1 ······Version byte (= 2 or 3).
daef49 ·* ······1 ·····1 ······Length of following material included in MD5 (x, = 5)
a1e861 ·* ······2 ·····1 ······Signature type
aee28d ·* ······3 ·····4 ······32-bit timestamp of signature
c3ab93 ·* -------- MD5 additional material stops here, at offset 7 ----------
0895f0 ·* ······2+x ···8 ······KeyID
499651 ·* ·····10+x ···1 ······PK algorithm type (1 = RSA)
c84a74 ·* ·····11+x ···1 ······MD algorithm type (1 = MD5)
a63387 ·* ·····12+x ···2 ······First 2 bytes of message digest (16-bit checksum)
1637f3 ·* ·····14+x ···2+? ····MPI of PK-encrypted integer
65495d ·*/
744d2f int
52636c pgpMakeSig (PGPByte *buf, PGPSigSpec const *spec,
1d47bb ¤   ·PGPRandomContext const *rc, PGPHashContext const *hc)
83bb36 {
c86896 ¤   PGPSecKey *sec;
c88f0c ¤   PGPHashContext *temp_hc;
091613 ¤   size_t extralen;
9d69cc ¤   PGPByte const *extra;
8de578 ¤   PGPByte const *hash;
5d4ba4 ¤   int i;
a065e2 ¤   size_t sigsize;
6667c5 ¤
196723 ¤   /* Use subpacket sig formats if requesting preferred algs */
d06ff3 ¤   if (pgpV4Sig (spec)) {
9e21e4 ¤   ¤   return pgpMakeSigSubs (buf, spec, rc, hc);
109371 ¤   }
dfaf5a
0c3bcc ¤   sec = pgpSigSpecSeckey(spec);
acaf5a
ee976f ¤   /* XXX should "die" gracefully here */
c457b8 ¤   pgpAssert (sec->sign);
c7af5a
1266f2 ¤   temp_hc = pgpHashCopy (hc);
f7c48b ¤   if (!temp_hc)
e84030 ¤   ¤   return kPGPError_OutOfMemory;
c1af5a
92ab4f ¤   extra = pgpSigSpecExtra(spec, &extralen);
d5d260 ¤   pgpAssert(extralen < 256);
40d1bd ¤   PGPContinueHash (temp_hc, extra, extralen);
ceaf5a
42bc13 ¤   hash = (PGPByte *) pgpHashFinal(temp_hc);
896b01 ¤   /* Copy the first 2 bytes over while they're available */
a67700 ¤   memcpy (buf+12+extralen, hash, 2);
560646 ¤   i = pgpSecKeySign(sec, pgpHashGetVTBL( hc ),
de32df ¤   ¤   ·hash, buf+14+extralen, &sigsize, rc, kPGPPublicKeyMessageFormat_PGP);
1af5d9 ¤   PGPFreeHashContext(temp_hc);
--e67c 000121bcfe740100218 Page 3 of pgpMakeSig.c
287a6f ¤   if (i < 0) {
5ce436 ¤   ¤   buf[12+extralen] = 0;
2ff439 ¤   ¤   buf[13+extralen] = 0;
e4a423 ¤   ¤   return i;
839371 ¤   }
5767c5 ¤
09679c ¤   /* Okay, build the signature packet - lots of magic numbers. */
ef4965 ¤   buf[0] = (PGPByte)PGPVERSION_3;¤¤   /* Force version 3 as format */
f5d91e ¤   buf[1] = extralen;
53d3c2 ¤   memcpy(buf+2, extra, extralen);
350ca4 ¤   memcpy(buf+2+extralen, sec->keyID, 8);
d967c5 ¤
d6c006 ¤   buf[10+extralen] = sec->pkAlg;
bc7b85 ¤   buf[11+extralen] = pgpHashGetVTBL( hc )->algorithm;
907155 ¤   /* First 2 bytes of hash are already copied in */
73af5a
29700b ¤   return (int)sigsize+14+(int)extralen;
c4efe6 }
1faf5a
ccaf5a
4caf5a
1038e5 /*
d84693 ·* Subpacket Sig layout:
86775e ·*
4ae13a ·* Offset,Length ·Meaning
c2cdd8 ·*¤ 0¤  ¤   1¤  Version byte (=4)
61ba53 ·*¤ 1¤  ¤   1¤  Signature type (included in hash) (nested flag)
1c62d3 ·*¤ 2¤  ¤   1¤  PK algorithm (1 = RSA) (included in hash)
08cf37 ·*¤ 3¤  ¤   1¤  Hash algorithm (1 = MD5) (included in hash)
0c97b9 ·*¤ 4¤  ¤   2¤  Length of extra material included in hash (=y)
172ceb ·*¤ 6¤  ¤   y¤  Subpackets (hashed)
714dc8 ·* ·6+y¤¤   2¤  Length of extra material not included in hash (=z)
7f8899 ·* ·8+y¤¤   z¤  Subpackets (unhashed)
8a7d36 ·*=====
1ec943 ·*remainder not present on sig headers
377d36 ·*=====
fab52a ·*¤ 8+y+z¤  2¤  First 2 bytes of message digest (16-bit checksum)
047730 ·*¤ 10+y+z¤ 2+w¤MPI of PK-signed integer
7e5f5e ·*¤ 12+y+z+w
9d775e ·*
5d3f64 ·* Remember, if adding new subpackets here, that they must go in increasing
d96ec2 ·* order of type value within each hashed/unhashed block.
6a495d ·*/
bfbeb7 static int
1bb081 pgpMakeSigSubs (PGPByte *buf, PGPSigSpec const *spec,
1a47bb ¤   ·PGPRandomContext const *rc, PGPHashContext const *hc)
a8bb36 {
ce6896 ¤   PGPSecKey *sec;
6f8f0c ¤   PGPHashContext *temp_hc;
001613 ¤   size_t extralen;
b4b395 ¤   unsigned l, l_init;
68c612 ¤   PGPUInt32 flags;
f3b229 ¤   size_t alglen;
7be2c7 ¤   size_t adkeylen;
0d69cc ¤   PGPByte const *extra;
c2e578 ¤   PGPByte const *hash;
5ffae0 ¤   PGPByte *algs;
a88a49 ¤   PGPByte *adkey;
86491b ¤   PGPByte trustLevel, trustValue;
53cc1d ¤   PGPBoolean bool1;
678efb ¤   PGPUInt32 dat;
d1f1b4 ¤   PGPByte *pack;
a2a5d3 ¤   PGPSize packlen;
1bc120 ¤   char *regExp;
ac4ba4 ¤   int i;
f765e2 ¤   size_t sigsize;
f1f69b ¤   PGPByte postscript[6];
36691f ¤   PGPBoolean hashedpart;
8167c5 ¤
4b3bcc ¤   sec = pgpSigSpecSeckey(spec);
efaf5a
12976f ¤   /* XXX should "die" gracefully here */
--d341 000354d7ac740100218 Page 4 of pgpMakeSig.c
1657b8 ¤   pgpAssert (sec->sign);
88af5a
8e66f2 ¤   temp_hc = pgpHashCopy (hc);
67c48b ¤   if (!temp_hc)
fc4030 ¤   ¤   return kPGPError_OutOfMemory;
d2af5a
a8ab4f ¤   extra = pgpSigSpecExtra(spec, &extralen);
d3ce95 ¤   pgpAssert(extralen == 5);
c867c5 ¤
c3679c ¤   /* Okay, build the signature packet - lots of magic numbers. */
7aca19 ¤   buf[0] = (PGPByte)PGPVERSION_4;
a55888 ¤   buf[1] = extra[0];¤ ¤   ¤   /* Signature type */
e50468 ¤   buf[2] = sec->pkAlg;
9d77c1 ¤   buf[3] = pgpHashGetVTBL( hc )->algorithm;
39af5a
48848e ¤   /* Fill in extralen after we figure out how much we need */
ee6cae ¤   l = 4;
dbec9b ¤   hashedpart = TRUE;
85af5a
c4902c ¤   /* Loop twice, hashedpart then !hashedpart */
8443ab ¤   do {
54f75b ¤   ¤   /* Remember where length will go, skip past it for now */
abd2da ¤   ¤   l_init = l;
31e9a5 ¤   ¤   l += 2;
b7af5a
2b22ee ¤   ¤   /* Signature creation, always present in hashed portion */
b8b80f ¤   ¤   if (hashedpart) {
f1b5d0 ¤   ¤   ¤   buf[l+1] = SIGSUB_CREATION;
f2c372 ¤   ¤   ¤   buf[l] = 4 + 1;¤¤   ¤   ¤   /* length */
9a8fdd ¤   ¤   ¤   pgpCopyMemory (extra+1, buf+l+2, 4);
011db7 ¤   ¤   ¤   l += 6;
9e0fe4 ¤   ¤   }
221b52 ¤   ¤
993c26 ¤   ¤   /* KeyID, always present in unhashed portion */
e9baa8 ¤   ¤   if (!hashedpart) {
37a017 ¤   ¤   ¤   buf[l+1] = SIGSUB_KEYID;
3157fb ¤   ¤   ¤   buf[l] = 8 + 1;
54d3ae ¤   ¤   ¤   pgpCopyMemory (sec->keyID, buf+l+2, 8);
a68f23 ¤   ¤   ¤   l += 8 + 2;
540fe4 ¤   ¤   }
9aaf5a
41d285 ¤   ¤   /* Sig expiration */
d04be3 ¤   ¤   if( (flags=pgpSigSpecSigExpiration (spec, &dat))
1f7751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
d7e669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
a33a7b ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_EXPIRATION | CRIT(flags);
b68221 ¤   ¤   ¤   ¤   buf[l] = 1 + 4;
ecc8d3 ¤   ¤   ¤   ¤   buf[l+2] = (PGPByte)(dat >> 24);
6cbe21 ¤   ¤   ¤   ¤   buf[l+3] = (PGPByte)(dat >> 16);
5d1647 ¤   ¤   ¤   ¤   buf[l+4] = (PGPByte)(dat >> ·8);
5aa1d7 ¤   ¤   ¤   ¤   buf[l+5] = (PGPByte)(dat >> ·0);
2446c8 ¤   ¤   ¤   ¤   l += 2 + 4;
9ca3a6 ¤   ¤   ¤   }
880fe4 ¤   ¤   }
9baf5a
15969f ¤   ¤   /* Exportability information */
aa2e09 ¤   ¤   if( (flags=pgpSigSpecExportable (spec, &bool1))
757751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
7ce669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
a203c6 ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_EXPORTABLE | CRIT(flags);
64bb9c ¤   ¤   ¤   ¤   buf[l] = 1 + 1;
292f7b ¤   ¤   ¤   ¤   buf[l+2] = bool1;
6e387f ¤   ¤   ¤   ¤   l += 1 + 2;
c6a3a6 ¤   ¤   ¤   }
220fe4 ¤   ¤   }
a8af5a
a5e435 ¤   ¤   /* Trust information */
e9ee32 ¤   ¤   if( (flags=pgpSigSpecTrustLevel(spec, &trustLevel, &trustValue))
187751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
5be669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
bb77f0 ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_TRUST | CRIT(flags);
3554f8 ¤   ¤   ¤   ¤   buf[l] = 1 + 2;
--90c9 000dcf972f940100218 Page 5 of pgpMakeSig.c
442b98 ¤   ¤   ¤   ¤   buf[l+2] = trustLevel;
25d0f2 ¤   ¤   ¤   ¤   buf[l+3] = trustValue;
239011 ¤   ¤   ¤   ¤   l += 2 + 2;
b8a3a6 ¤   ¤   ¤   }
7d0fe4 ¤   ¤   }
76af5a
79bb42 ¤   ¤   /* Regexp information */
569d44 ¤   ¤   if( (flags=pgpSigSpecRegExp (spec, &regExp))
7a7751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
9de669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
470313 ¤   ¤   ¤   ¤   size_t regExpLength = strlen(regExp) + 1;
72f8f6 ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_REGEXP | CRIT(flags);
85a2bc ¤   ¤   ¤   ¤   buf[l] = 1 + regExpLength;
6e1107 ¤   ¤   ¤   ¤   pgpCopyMemory( regExp, buf+l+2, regExpLength );
945b2f ¤   ¤   ¤   ¤   l += regExpLength + 2;
1ba3a6 ¤   ¤   ¤   }
f20fe4 ¤   ¤   }
d7af5a
a7c037 ¤   ¤   /* Revokability information */
45e534 ¤   ¤   if( (flags=pgpSigSpecRevocable (spec, &bool1))
4e7751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
13e669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
695bc9 ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_REVOCABLE | CRIT(flags);
2fbb9c ¤   ¤   ¤   ¤   buf[l] = 1 + 1;
f22f7b ¤   ¤   ¤   ¤   buf[l+2] = bool1;
8d387f ¤   ¤   ¤   ¤   l += 1 + 2;
95a3a6 ¤   ¤   ¤   }
1a0fe4 ¤   ¤   }
f1af5a
2b68de ¤   ¤   /* Key expiration (self sig) */
f419e2 ¤   ¤   if( (flags=pgpSigSpecKeyExpiration (spec, &dat))
d47751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
dee669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
e2423e ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_KEY_EXPIRATION | CRIT(flags);
788221 ¤   ¤   ¤   ¤   buf[l] = 1 + 4;
c7c8d3 ¤   ¤   ¤   ¤   buf[l+2] = (PGPByte)(dat >> 24);
65be21 ¤   ¤   ¤   ¤   buf[l+3] = (PGPByte)(dat >> 16);
af1647 ¤   ¤   ¤   ¤   buf[l+4] = (PGPByte)(dat >> ·8);
d3a1d7 ¤   ¤   ¤   ¤   buf[l+5] = (PGPByte)(dat >> ·0);
d646c8 ¤   ¤   ¤   ¤   l += 2 + 4;
29a3a6 ¤   ¤   ¤   }
d40fe4 ¤   ¤   }
79af5a
f9d915 ¤   ¤   /* Additional decryption fingerprint (self sig) */
2eb360 ¤   ¤   for (i=0;
8b2558 ¤   ¤   ¤   ·(flags=pgpSigSpecAdditionalRecipientRequest (spec, &adkey,
285988 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&adkeylen, i))
947225 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·& kPGPSigFlags_Present;
728d09 ¤   ¤   ¤   ·++i) {
6be669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
2ef6f9 ¤   ¤   ¤   ¤   pgpAssert (adkeylen + 1 < 192);
608bce ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST
7d22c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   | CRIT(flags);
c198d9 ¤   ¤   ¤   ¤   buf[l] = adkeylen + 1;
009165 ¤   ¤   ¤   ¤   pgpCopyMemory (adkey, buf+l+2, adkeylen);
4880fd ¤   ¤   ¤   ¤   l += adkeylen + 2;
96a3a6 ¤   ¤   ¤   }
b80fe4 ¤   ¤   }
6daf5a
6f46eb ¤   ¤   /* Preferred algorithms (self sig) */
a87b7f ¤   ¤   if( (flags=pgpSigSpecPrefAlgs (spec, &algs, &alglen))
aa7751 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   & kPGPSigFlags_Present ) {
34e669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
4d198b ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_PREFERRED_ENCRYPTION_ALGS | CRIT(flags);
734e47 ¤   ¤   ¤   ¤   buf[l] = alglen+1;
fd3dae ¤   ¤   ¤   ¤   pgpCopyMemory (algs, buf+l+2, alglen);
8e7f08 ¤   ¤   ¤   ¤   l += alglen + 2;
62a3a6 ¤   ¤   ¤   }
e10fe4 ¤   ¤   }
abaf5a
da7176 ¤   ¤   /* Key revocation key fingerprint (self sig) */
dcb360 ¤   ¤   for (i=0;
--d880 00012aeb79740100218 Page 6 of pgpMakeSig.c
53121b ¤   ¤   ¤   ·(flags=pgpSigSpecRevocationKey (spec, &adkey, &adkeylen, i))
47e364 ¤   ¤   ¤   ¤   ¤   ·¤  ¤   ¤   & kPGPSigFlags_Present;
158d09 ¤   ¤   ¤   ·++i) {
43e669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
acf6f9 ¤   ¤   ¤   ¤   pgpAssert (adkeylen + 1 < 192);
02bf1c ¤   ¤   ¤   ¤   buf[l+1] = SIGSUB_KEY_REVOCATION_KEY | CRIT(flags);
7b98d9 ¤   ¤   ¤   ¤   buf[l] = adkeylen + 1;
4a9165 ¤   ¤   ¤   ¤   pgpCopyMemory (adkey, buf+l+2, adkeylen);
d080fd ¤   ¤   ¤   ¤   l += adkeylen + 2;
06a3a6 ¤   ¤   ¤   }
060fe4 ¤   ¤   }
8baf5a
789611 ¤   ¤   /* Unrecognized subpackets we are copying verbatim */
c2b360 ¤   ¤   for (i=0;
b7e7ad ¤   ¤   ¤   ·(flags=pgpSigSpecPacket (spec, &pack, &packlen, i))
c7e364 ¤   ¤   ¤   ¤   ¤   ·¤  ¤   ¤   & kPGPSigFlags_Present;
d88d09 ¤   ¤   ¤   ·++i) {
3b8521 ¤   ¤   ¤   /* packlen includes the type byte */
59e669 ¤   ¤   ¤   if (!(flags & kPGPSigFlags_Unhashed) == hashedpart) {
d22fed ¤   ¤   ¤   ¤   if (PKTLEN_ONE_BYTE(packlen)) {
bfc426 ¤   ¤   ¤   ¤   ¤   buf[l] = packlen;
9ddbc1 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory (pack, buf+l+1, packlen);
7438fe ¤   ¤   ¤   ¤   ¤   buf[l+1] |= CRIT(flags);
e11b6e ¤   ¤   ¤   ¤   ¤   l += packlen + 1;
9dbcbb ¤   ¤   ¤   ¤   } else if (PKTLEN_TWO_BYTES(packlen)) {
432b64 ¤   ¤   ¤   ¤   ¤   buf[l ·] = PKTLEN_BYTE0(packlen);
4dc1ce ¤   ¤   ¤   ¤   ¤   buf[l+1] = PKTLEN_BYTE1(packlen);
75d536 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory (pack, buf+l+2, packlen);
6f8534 ¤   ¤   ¤   ¤   ¤   buf[l+2] |= CRIT(flags);
caf40a ¤   ¤   ¤   ¤   ¤   l += packlen + 2;
cdb5fc ¤   ¤   ¤   ¤   } else {
4dbbb9 ¤   ¤   ¤   ¤   ¤   buf[l ·] = 0xff;
25aa5d ¤   ¤   ¤   ¤   ¤   buf[l+1] = (packlen >> 24) & 0xff;
0585d3 ¤   ¤   ¤   ¤   ¤   buf[l+2] = (packlen >> 16) & 0xff;
3e9c32 ¤   ¤   ¤   ¤   ¤   buf[l+3] = (packlen >> ·8) & 0xff;
47df2d ¤   ¤   ¤   ¤   ¤   buf[l+4] = (packlen >> ·0) & 0xff;
3dcd75 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory (pack, buf+l+5, packlen);
9965f8 ¤   ¤   ¤   ¤   ¤   buf[l+5] |= CRIT(flags);
ec780f ¤   ¤   ¤   ¤   ¤   l += packlen + 5;
a82613 ¤   ¤   ¤   ¤   }
49a3a6 ¤   ¤   ¤   }
d40fe4 ¤   ¤   }
f21b52 ¤   ¤
eb0c87 ¤   ¤   /* Now can go back and fill in length field */
119263 ¤   ¤   buf[l_init ·] = (PGPByte)((l-l_init-2) >> 8);
384326 ¤   ¤   buf[l_init+1] = (PGPByte)((l-l_init-2) >> 0);
78af5a
b2b80f ¤   ¤   if (hashedpart) {
d20230 ¤   ¤   ¤   PGPContinueHash (temp_hc, buf, l);
c4af5a
8ed463 ¤   ¤   ¤   /* Add hash "postscript", ensure hashed data not alias anything */
48e746 ¤   ¤   ¤   postscript[0] = PGPVERSION_4; ·/* Hash-convention version */
08b99f ¤   ¤   ¤   postscript[1] = 0xff; ··/* 5th from end, != any sig type value */
5b507e ¤   ¤   ¤   postscript[2] = (PGPByte)(l >> 24);
e470bf ¤   ¤   ¤   postscript[3] = (PGPByte)(l >> 16);
c37251 ¤   ¤   ¤   postscript[4] = (PGPByte)(l >> ·8);
9493f2 ¤   ¤   ¤   postscript[5] = (PGPByte)(l >> ·0);
1fb946 ¤   ¤   ¤   PGPContinueHash (temp_hc, postscript, sizeof(postscript));
e70fe4 ¤   ¤   }
5f478d ¤   ¤   hashedpart = !hashedpart;
22d2da ¤   ¤   l_init = l;
ca006c ¤   } while (!hashedpart);
49af5a
1c9dee ¤   /* Now finish hash calculation, copy over 2 csum bytes, put in sig */
d3bc13 ¤   hash = (PGPByte *) pgpHashFinal(temp_hc);
edff5f ¤   pgpCopyMemory (hash, buf+l, 2);
ee9070 ¤   i = pgpSecKeySign(sec, pgpHashGetVTBL( hc ), hash, buf+l+2, &sigsize,
5244b6 ¤   ··················rc, kPGPPublicKeyMessageFormat_PGP);
80f5d9 ¤   PGPFreeHashContext(temp_hc);
637a6f ¤   if (i < 0) {
cf6e0b ¤   ¤   buf[l] = 0;
122d07 ¤   ¤   buf[l+1] = 0;
--cdba 00106f24dab40100218 Page 7 of pgpMakeSig.c
1aa423 ¤   ¤   return i;
789371 ¤   }
4baf5a
2fd1df ¤   return (int)sigsize+l+2;
b6efe6 }
36af5a
06af5a
3eaf5a
1fbca8 /* Routines for 1-pass signature headers */
90af5a
190784 /* Right now the header is always 13 bytes long */
e14d2f int
7da1e7 pgpMakeSigHeaderMaxSize (PGPSigSpec const *spec)
acbb36 {
50380e ¤   (void)spec;
f507b2 ¤   return 13;
73efe6 }
e1af5a
8338e5 /*
208e11 ·* Given a buffer of appropriate length (currently 13), create a
3486d5 ·* single-pass signature header, which is a "one-pass" signature that
13e864 ·* will have a real signature later on. ·Don't forget that you'll need
ab5bfc ·* the packet header (2 more bytes) before this. ·The format is:
38775e ·*
8763e8 ·* ·····Offset ·Length ·Meaning
cf8950 ·* ······0 ·····1 ······Version byte (=3)
8d8974 ·* ······1 ·····1 ······Signature type
7c737d ·* ······2 ·····1 ······Hash Algorithm
a6775e ·* ······3 ·····1 ······PK Algorithm
935f3c ·* ······4 ·····8 ······KeyID
00fc20 ·* ······12 ····1 ······nested flag
e2495d ·*/
ef4d2f int
7efeb0 pgpMakeSigHeader (PGPByte *buf, PGPSigSpec const *spec, PGPByte nest)
7bbb36 {
81602d ¤   PGPHashVTBL const *h;
a96dea ¤   PGPSecKey const *seckey;
9c69cc ¤   PGPByte const *extra;
281613 ¤   size_t extralen;
5eaf5a
6a2a12 ¤   extra = pgpSigSpecExtra (spec, &extralen);
93c4f6 ¤   h = pgpSigSpecHash (spec);
22aefb ¤   seckey = pgpSigSpecSeckey (spec);
75af5a
d30005 ¤   /* XXX: This should be more graceful */
929793 ¤   pgpAssert (extra);
5e9a15 ¤   pgpAssert (h);
e1c1b2 ¤   pgpAssert (seckey);
831498 ¤   pgpAssert (seckey->sign);
82af5a
3e4965 ¤   buf[0] = (PGPByte)PGPVERSION_3;¤¤   /* Force version 3 as format */
497b68 ¤   buf[1] = *extra;
9662ac ¤   buf[2] = h->algorithm;
61216e ¤   buf[3] = seckey->pkAlg;
675f7f ¤   memcpy(buf+4, seckey->keyID, 8);
a5d6ef ¤   buf[12] = nest;
03af5a
2007b2 ¤   return 13;
44efe6 }
06af5a
--e5c9 001286cc8ae40100219 Page 1 of pgpMakeSig.h
bc38e5 /*
818420 ·* pgpMakeSig.h -- Make a signature packet from a secret key, a hash, and
5dbb16 ·* extra data.
43775e ·*
ede39d ·* This is a PRIVATE header file, for use only within the PGP Library.
a32979 ·* You should not be using these functions in an application.
01775e ·*
837025 ·* $Id: pgpMakeSig.h,v 1.8 1997/06/25 19:40:58 lloyd Exp $
ca495d ·*/
b4af5a
e5f977 #ifndef Included_pgpMakeSig_h
8bad43 #define Included_pgpMakeSig_h
7daf5a
85d11f #include "pgpUsuals.h"
e1af5a
5d99c6 PGP_BEGIN_C_DECLARATIONS
b6af5a
1e95b7 struct PGPSigSpec;
113a38 struct PGPHashContext;
97161d struct PGPRandomContext;
39af5a
1492b5 /* The maximum size of the signature */
b92292 int pgpMakeSigMaxSize(PGPSigSpec const *spec);
7367c5 ¤
9438e5 /*
712e7c ·* Given a buffer of at least "pgpMakeSigMaxSize" bytes, make a signature
55658e ·* into it and return the size of the signature, or 0.
13495d ·*/
e84d2f int
7f6f51 pgpMakeSig(PGPByte *buf, PGPSigSpec const *spec,
125df5 ¤   PGPRandomContext const *rc, PGPHashContext const *hc);
9caf5a
82b2e1 /* The maximum size of a signature header (one-pass sig) */
b89b9d int pgpMakeSigHeaderMaxSize (PGPSigSpec const *spec);
c8af5a
59fdf9 /* Create a one-pass signature header block for "spec", putting it in buf */
059463 int pgpMakeSigHeader (PGPByte *buf, PGPSigSpec const *spec, PGPByte nest);
9baf5a
fd1254 PGP_END_C_DECLARATIONS
33af5a
287477 #endif /* Included_pgpMakeSig_h */
--a918 00175a9263c4010021a Page 1 of pgpPktList.c
bc38e5 /*
bf2114 ·* $Id: pgpPktList.c,v 1.11 1997/12/12 01:14:42 heller Exp $
75495d ·*/
1baf5a
fbe2ff #include "pgpConfig.h"
cdaf5a
747210 #include <string.h>¤/* For memcpy */
a32907 #include <stddef.h>¤/* For offsetof */
fcaf5a
8cba29 #include "pgpPktList.h"
8dc26c #include "pgpContext.h"
d90d08 #include "pgpMem.h"
f5af5a
d923f3 PktList *
d0724b pgpPktListNew(
7d520e ¤   PGPContextRef¤  context,
df98bd ¤   int type, PGPByte const *buf, size_t len)
f4bb36 {
356618 ¤   PktList *pkl;
f0af5a
1742cc ¤   pkl = (PktList *)pgpContextMemAlloc( context,
b29678 ¤   ¤   len + offsetof(PktList, buf), kPGPMemoryMgrFlags_Clear);
de7d01 ¤   if (pkl) {
61411e ¤   ¤   pkl->context¤   = context;
db90af ¤   ¤   pkl->next = (PktList *)0;
b16fdf ¤   ¤   pkl->type = type;
49e8d0 ¤   ¤   pkl->len = len;
158214 ¤   ¤   memcpy(pkl->buf, buf, len);
179371 ¤   }
cb63f0 ¤   return pkl;
51efe6 }
88af5a
84314a void
08e566 pgpPktListFreeOne(PktList *pkl)
dcbb36 {
24e9fa ¤   PGPContextRef¤  cdkContext;
efaf5a
5fdf04 ¤   pgpAssertAddrValid( pkl, PktList );
b853ef ¤   cdkContext¤ = pkl->context;
5567c5 ¤
3fdc0c ¤   pgpClearMemory( pkl, ·pkl->len + offsetof(PktList, buf));
5747f9 ¤   pgpContextMemFree( cdkContext, pkl);
f5efe6 }
15af5a
52314a void
aabcf7 pgpPktListFreeList(PktList *list)
14bb36 {
eb6199 ¤   PktList¤¤   ¤   ¤   *cur;
5a8060 ¤   PGPContextRef¤  ¤   cdkContext;
e0af5a
d5d5ad ¤   if( IsNull(list) )
7399bf ¤   ¤   return;
6d6670 ¤   cdkContext = list->context;
dbd056 ¤   while (list) {
6545ed ¤   ¤   /* If you don't understand this, yer a wimp. ·Belch. ·Grunt. */
0df155 ¤   ¤   list = (cur = list)->next;
68d566 ¤   ¤   pgpClearMemory( cur, ·cur->len + offsetof(PktList, buf));
9db797 ¤   ¤   pgpContextMemFree( cdkContext, cur);
899371 ¤   }
75efe6 }
--21e9 0015efdb40c4010021b Page 1 of pgpPktList.h
bc38e5 /*
87d2c8 ·* $Id: pgpPktList.h,v 1.7 1997/06/24 07:16:40 lloyd Exp $
66495d ·*/
a8af5a
d802ad #ifndef Included_pgpPktList_h
315699 #define Included_pgpPktList_h
8eaf5a
07c546 #include <stddef.h>¤/* For size_t */
98af5a
0ea395 #include "pgpPubTypes.h"¤   /* For PGPByte */
5faf5a
cc99c6 PGP_BEGIN_C_DECLARATIONS
95af5a
dc95d7 /*·
0702b1 ·* This is a trivial interface. ·You may just access the members
d1c87b ·* directly. ·buf may change from an included buffer to a pointer
689f1d ·* at some point, but that should not require any changes to the
c6608d ·* source code.
ca495d ·*/
43af5a
a13d62 typedef struct PktList
c3bb36 {
388a97 ¤   PGPContextRef¤  context;
8767c5 ¤
75e17b ¤   struct PktList *next;
c729f6 ¤   int type;
5cf20c ¤   size_t len;
c96c98 ¤   PGPByte buf[1];¤/* Extensible */
7baef7 } PktList ;
feaf5a
039f6c PktList *pgpPktListNew( PGPContextRef context,
476ed6 ¤   int type, PGPByte const *buf, size_t len);
160119 void pgpPktListFreeOne(PktList *list);
b39330 void pgpPktListFreeList(PktList *list);
2baf5a
801254 PGP_END_C_DECLARATIONS
ddaf5a
5e10a2 #endif /* Included_pgpPktList_h */
--f04a 000d58c06ee4010021c Page 1 of pgpPubKey.c
bc38e5 /*
7c7989 ·* $Id: pgpPubKey.c,v 1.23 1998/07/10 04:05:55 hal Exp $
dc495d ·*/
b7af5a
063051 #include "pgpSDKBuildFlags.h"
b4e2ff #include "pgpConfig.h"
d1af5a
17a146 #include "pgpDebug.h"
732f8d #include "pgpErrors.h"
a8cdc2 #include "pgpPubKey.h"
82007f #include "pgpKeyMisc.h"
4faf5a
3c99a4 #if PGP_RSA
62fa8a #include "pgpRSAKey.h"
b04704 #include "pgpMSRSAGlue.h"
fc7454 #endif
15af5a
6e6f19 #include "pgpElGKey.h"
b3c00a #include "pgpDSAKey.h"
43c223 #include "pgpFixedKey.h"
c3af5a
7fbe7a #ifndef PGP_RSA
0431da #error "PGP_RSA requires a value"
b67454 #endif
0faf5a
bc2486 #ifndef PGP_RSA_KEYGEN
ffadd9 #error "PGP_RSA_KEYGEN requires a value"
ab7454 #endif
81af5a
23cfd4 /* Error code used within this module for RSA not available */
26819c #define kPGPLocalError_RSANotAvailable¤ kPGPError_FeatureNotAvailable
6aaf5a
d8a67f struct PGPPkAlg
cabb36 {
767272 ¤   PGPByte pkAlg;
c3b68d ¤   int use;
8d2fa1 } ;
adaf5a
9a7d6f #if PGP_ENCRYPT_DISABLE && PGP_DECRYPT_DISABLE
439c76 #define LOCAL_ENCRYPT¤  0
67db21 #else
9aa28f #define LOCAL_ENCRYPT¤  PGP_PKUSE_ENCRYPT
267454 #endif
51af5a
cd4f21 #if PGP_SIGN_DISABLE && PGP_VERIFY_DISABLE
acae4e #define LOCAL_SIGN¤ ¤   0
f1db21 #else
8fc45a #define LOCAL_SIGN¤ ¤   PGP_PKUSE_SIGN
567454 #endif
b7af5a
e23ac7 #define LOCAL_SIGN_ENCRYPT (LOCAL_SIGN | LOCAL_ENCRYPT)
38af5a
e901cd static PGPPkAlg const pgpKnownPkAlgs[] = {
5999a4 #if PGP_RSA
af44be ¤   { kPGPPublicKeyAlgorithm_RSA, ····¤ ¤   ¤   LOCAL_SIGN_ENCRYPT },
80f4d4 ¤   { kPGPPublicKeyAlgorithm_RSASignOnly, ¤ ¤   LOCAL_SIGN },
f63a13 ¤   { kPGPPublicKeyAlgorithm_RSAEncryptOnly, ¤  LOCAL_ENCRYPT },
d6f4b0 #else¤  /* PGP_RSA */
a70da9 ¤   { kPGPPublicKeyAlgorithm_RSA, ····¤ ¤   ¤   0 },
3c0b46 ¤   { kPGPPublicKeyAlgorithm_RSASignOnly,¤  ¤   0 },
e37e3e ¤   { kPGPPublicKeyAlgorithm_RSAEncryptOnly, ¤  0 },
2592cd #endif¤ /* PGP_RSA */
44fdda ¤   { kPGPPublicKeyAlgorithm_ElGamal, ¤ ¤   ¤   LOCAL_ENCRYPT },
528ed1 ¤   { kPGPPublicKeyAlgorithm_DSA, ····¤ ¤   ¤   LOCAL_SIGN }
2e82f7 };
dfaf5a
75af5a
255882 /* Error codes which permit ringPoolCheck to continue */
627750 PGPBoolean
135c67 pgpIsKeyRelatedError( PGPError err )
21bb36 {
d51d23 ¤   if (err >= kPGPError_KEY_MIN && err <= kPGPError_KEY_MAX)
--591a 0001c2dbf2d4010021c Page 2 of pgpPubKey.c
00836c ¤   ¤   return TRUE;
189e63 ¤   if (err == kPGPLocalError_RSANotAvailable)
5d836c ¤   ¤   return TRUE;
91a230 ¤   return FALSE;
37efe6 }
e0af5a
bbaf5a
11cbaa /* Return whether an algorithm can sign, encrypt, or do both */
098fe4 PGPPkAlg const *
ac0c43 pgpPkalgByNumber(PGPByte pkalg)
4abb36 {
89743f ¤   unsigned i;
edaf5a
a40480 ¤   pkalg = ALGMASK(pkalg);
638989 ¤   for (i = 0; i < sizeof(pgpKnownPkAlgs)/sizeof(*pgpKnownPkAlgs); i++) {
8eaffd ¤   ¤   if (pgpKnownPkAlgs[i].pkAlg == pkalg)
835475 ¤   ¤   ¤   return pgpKnownPkAlgs + i;
9f9371 ¤   }
693f59 ¤   return NULL;
a1efe6 }
25af5a
af4d2f int
10a4cf pgpKeyUse(PGPPkAlg const *pkalg)
30bb36 {
bdedee ¤   if (!pkalg)
07f26e ¤   ¤   return 0;¤  ¤   /* It's no use... */
a7fbb5 #if PGP_RSA && PGP_USECAPIFORRSA
5d50a7 ¤   if (pkalg->pkAlg == kPGPPublicKeyAlgorithm_RSA) {
884d9c ¤   ¤   return pkalg->use & pgpCAPIuse();
3c9371 ¤   }
e07454 #endif
f64ef7 ¤   return pkalg->use;
57efe6 }
e1af5a
0d40b4 PGPPubKey *
089e8d pgpPubKeyFromBuf(
ad520e ¤   PGPContextRef¤  context,
6a3b31 ¤   PGPByte¤¤   ¤   pkAlg,
2e8581 ¤   PGPByte const *¤p,
815984 ¤   size_t¤ ¤   ¤   len,
086429 ¤   PGPError *¤ ¤   error)
22bb36 {
6ea299 ¤   PGPPubKey *pub;
b5af5a
eafd6b ¤   switch (ALGMASK(pkAlg)) {
4f39f8 ¤   ··case kPGPPublicKeyAlgorithm_RSA:
fbe2af ¤   ··case kPGPPublicKeyAlgorithm_RSASignOnly:
330ea7 ¤   ··case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
c099a4 #if PGP_RSA
a19d36 ¤   ¤   pub = rsaPubFromBuf( context, p, len, error);
e155ab ¤   ¤   if (pub)
96b277 ¤   ¤   ¤   pub->pkAlg = pkAlg;
69f4b0 #else¤  /* PGP_RSA */
917586 ¤   ¤   (void) p;
5cdf6e ¤   ¤   (void) len;
8960e9 ¤   ¤   pub = NULL;
cf8c58 ¤   ¤   *error = kPGPLocalError_RSANotAvailable;
7292cd #endif¤ /* PGP_RSA */
2b897b ¤   ¤   return pub;
e0a7d0 ¤   ··case kPGPPublicKeyAlgorithm_ElGamal:
fe04e5 ¤   ··¤ pub = elgPubFromBuf( context, p, len, error);
e755ab ¤   ¤   if (pub)
44b277 ¤   ¤   ¤   pub->pkAlg = pkAlg;
3b897b ¤   ¤   return pub;
10b620 ¤   ··case kPGPPublicKeyAlgorithm_DSA:
52d931 ¤   ··¤ pub = dsaPubFromBuf( context, p, len, error);
c955ab ¤   ¤   if (pub)
b2b277 ¤   ¤   ¤   pub->pkAlg = pkAlg;
a9897b ¤   ¤   return pub;
90f727 ¤   ··default:
0a7a4d ¤   ¤   *error = kPGPError_UnknownPublicKeyAlgorithm;
1cbbde ¤   ¤   return 0;
--06b5 0000fa16f6a4010021c Page 3 of pgpPubKey.c
a19371 ¤   }
9967c5 ¤
5cefe6 }
f5af5a
d6521e PGPSecKey *
e89589 pgpSecKeyFromBuf(
63520e ¤   PGPContextRef¤  context,
ae3b31 ¤   PGPByte¤¤   ¤   pkAlg,
228581 ¤   PGPByte const *¤p,
5d5984 ¤   size_t¤ ¤   ¤   len,
49bf97 ¤   PGPBoolean¤ ¤   v3,
1d6429 ¤   PGPError *¤ ¤   error)
afbb36 {
d06896 ¤   PGPSecKey *sec;
41af5a
d25362 ¤   switch(ALGMASK(pkAlg)) {
e639f8 ¤   ··case kPGPPublicKeyAlgorithm_RSA:
e1e2af ¤   ··case kPGPPublicKeyAlgorithm_RSASignOnly:
930ea7 ¤   ··case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
5299a4 #if PGP_RSA
093102 ¤   ¤   sec = rsaSecFromBuf( context, p, len, v3, error);
85d11a ¤   ¤   if (sec)
035f72 ¤   ¤   ¤   sec->pkAlg = pkAlg;
6ef4b0 #else¤  /* PGP_RSA */
2c7586 ¤   ¤   (void) p;
f1df6e ¤   ¤   (void) len;
836c33 ¤   ¤   (void) v3;
51ba65 ¤   ¤   sec = NULL;
728c58 ¤   ¤   *error = kPGPLocalError_RSANotAvailable;
5392cd #endif¤ /* PGP_RSA */
be0dca ¤   ¤   return sec;
90a7d0 ¤   ··case kPGPPublicKeyAlgorithm_ElGamal:
8bba32 ¤   ¤   sec = elgSecFromBuf( context, p, len, error);
a7d11a ¤   ¤   if (sec)
ae5f72 ¤   ¤   ¤   sec->pkAlg = pkAlg;
340dca ¤   ¤   return sec;
04b620 ¤   ··case kPGPPublicKeyAlgorithm_DSA:
ad67e6 ¤   ¤   sec = dsaSecFromBuf( context, p, len, error);
92d11a ¤   ¤   if (sec)
4a5f72 ¤   ¤   ¤   sec->pkAlg = pkAlg;
b30dca ¤   ¤   return sec;
f5f727 ¤   ··default:
197a4d ¤   ¤   *error = kPGPError_UnknownPublicKeyAlgorithm;
73bbde ¤   ¤   return 0;
cd9371 ¤   }
f4efe6 }
e0af5a
5938e5 /*
ee36fd ·* Scan a buffer and return the size of the part which corresponds to
749f57 ·* a public key. ·This is intended to be "lightweight" and not require
688f42 ·* the overhead of instantiating a PGPPubKey.
c8775e ·*
0f88c0 ·* This rturns 0 if the size is unknown.
25495d ·*/
5544d2 size_t
c7839d pgpPubKeyPrefixSize(PGPByte pkAlg, PGPByte const *p, size_t len)
efbb36 {
365362 ¤   switch(ALGMASK(pkAlg)) {
71f13f ¤   case kPGPPublicKeyAlgorithm_RSA:
5e4f45 ¤   case kPGPPublicKeyAlgorithm_RSASignOnly:
aa6bfb ¤   case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
c999a4 #if PGP_RSA
bd862e ¤   ¤   ··return rsaPubKeyPrefixSize(p, len);
24db21 #else
ab6083 ¤   ¤   ··/* We know it is 2 MPI values, just parse past those */
c8c7d5 ¤   ¤   ··return pgpBnParse(p, len, 2, NULL, NULL);
db7454 #endif
7a0770 ¤   case kPGPPublicKeyAlgorithm_ElGamal:
cacc17 ¤   ¤   ··return elgPubKeyPrefixSize(p, len);
e17ee7 ¤   case kPGPPublicKeyAlgorithm_DSA:
c76b45 ¤   ¤   ··return dsaPubKeyPrefixSize(p, len);
0f2f72 ¤   default:
--186e 0005ab4449a4010021c Page 4 of pgpPubKey.c
79bbde ¤   ¤   return 0;
a69371 ¤   }
fdefe6 }
c1af5a
5c38e5 /*
c0f504 ·* The "progress" function is called periodically during key
4c896b ·* generation to indicate that *something* is happening.
e906db ·* The "int c" gives a bit of indication as to *what* is
ff7eae ·* happening. ·In fact, this is just the character that text-mode
44bd37 ·* PGP prints! ·It will do as well as any other sort of enum
340800 ·* and makes life simple.
2f775e ·*
f85aed ·* The meaning of the character is somewhat type-dependent, but
17388c ·* the convention so far is:
d121f0 ·* '.' - Failed pseudoprimality test
1ea267 ·* '/' - Redoing initial setup work
5878b6 ·* '-' - Passed pseudoprimality test, further work needed
b49771 ·* '+' - Passed pseudoprimality test, further work needed
8b4e4b ·* '*' - Passed pseudoprimality test - almost done!
3ac330 ·* ' ' - Completed part of key generation, on to next phase.
001509 ·* ······(Sorry, no way to know how many phases there are...)
f4495d ·*/
deaf5a
f4521e PGPSecKey *
c99ed9 pgpSecKeyGenerate(
c2520e ¤   PGPContextRef¤  context,
2af6b6 ¤   PGPPkAlg const *alg, unsigned bits,
f73791 ¤   PGPBoolean fastgen,
0b4b45 ¤   PGPRandomContext const *rc,
fc770e ¤   int (*progress)(void *arg, int c), void *arg, PGPError *error)
66bb36 {
276896 ¤   PGPSecKey *sec;
e47272 ¤   PGPByte pkAlg;
e3d83c ·
c841d2 ¤   pgpAssert (alg);
d1da48 ¤   pkAlg = alg->pkAlg;
ac5362 ¤   switch(ALGMASK(pkAlg)) {
6f39f8 ¤   ··case kPGPPublicKeyAlgorithm_RSA:
864fe3 #if PGP_RSA && PGP_RSA_KEYGEN
bea439 ¤   ¤   sec = rsaSecGenerate( context, bits, fastgen, rc, progress, arg,
fadd42 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··error);
bed11a ¤   ¤   if (sec)
f25f72 ¤   ¤   ¤   sec->pkAlg = pkAlg;
b60dca ¤   ¤   return sec;
2ddb21 #else
ac8c58 ¤   ¤   *error = kPGPLocalError_RSANotAvailable;
eb7ed2 ¤   ¤   return NULL;
0a7454 #endif
8aa7d0 ¤   ··case kPGPPublicKeyAlgorithm_ElGamal:
a10ed3 ¤   ¤   sec = elgSecGenerate(context, bits, fastgen, rc, progress, arg, error);
34d11a ¤   ¤   if (sec)
a85f72 ¤   ¤   ¤   sec->pkAlg = pkAlg;
140dca ¤   ¤   return sec;
6cb620 ¤   ··case kPGPPublicKeyAlgorithm_DSA:
b39dc7 ¤   ¤   sec = dsaSecGenerate(context, bits, fastgen, rc, progress, arg, error);
1ed11a ¤   ¤   if (sec)
c25f72 ¤   ¤   ¤   sec->pkAlg = pkAlg;
af0dca ¤   ¤   return sec;
83f727 ¤   ··default:
5d7a4d ¤   ¤   *error = kPGPError_UnknownPublicKeyAlgorithm;
3abbde ¤   ¤   return 0;
c09371 ¤   }
78efe6 }
dbaf5a
fd38e5 /*
0e9ab4 ·* Return the amount of entropy needed to generate this key.
97b3e3 ·* Entropy is a security parameter, controlling the amount of
4d75d3 ·* unpredictability needed in the key.
d7eb01 ·* We have to be sure to return a value at least as big as the actual
b76d67 ·* depletion of the randpool which the keygen creates.
206d36 ·* For simplicity and predictability, we return the non-fastgen values
5a12fd ·* throughout, even though they are a bit larger for DSA & ELG keys.
--652c 0015594344b4010021c Page 5 of pgpPubKey.c
232724 ·* (The +64 in the RSA case, and +128 in the DSA case, is for the secret
bd56c8 ·* key encryption IV and salt when the secret key is encrypted with the
72d974 ·* passphrase.)
e5495d ·*/
af536c unsigned
8624dc pgpSecKeyEntropy(PGPPkAlg const *pkAlg, unsigned bits, PGPBoolean fastgen)
92bb36 {
405486 ¤   unsigned xbits;
82af5a
b04d1e ¤   (void)fastgen;
71af5a
6c0b18 ¤   pgpAssert (pkAlg);
c03c39 ¤   switch (ALGMASK(pkAlg->pkAlg)) {
6239f8 ¤   ··case kPGPPublicKeyAlgorithm_RSA:
eee2af ¤   ··case kPGPPublicKeyAlgorithm_RSASignOnly:
9e0ea7 ¤   ··case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
882e4c ¤   ¤   ··return bits + 64;
3ea7d0 ¤   ··case kPGPPublicKeyAlgorithm_ElGamal:
9b40f7 ¤   ¤   ··xbits = pgpDiscreteLogExponentBits(bits)*3/2 + 128;
39ad26 ¤   ¤   ··/* Always return fastgen value
02ac61 ¤   ¤   ···* if (!fastgen || !pgpElGfixed (bits, NULL, NULL, NULL, NULL))
dec971 ¤   ¤   ···*/
cde66b ¤   ¤   ¤   ··xbits += ELGDUMMYBITS;
9781e4 ¤   ¤   ··return xbits;
19b620 ¤   ··case kPGPPublicKeyAlgorithm_DSA:
9d3c21 ¤   ¤   ··/*
e145c7 ¤   ¤   ···* Count the ~160 bits each needed to generate the self signature
7d4a7b ¤   ¤   ···* on the key's userid, and on the subkey, in addition to the
00beba ¤   ¤   ···* "q bits" secret exponent. ·That is why the 2* below.
b6c971 ¤   ¤   ···*/
3391e6 ¤   ¤   ··xbits = 2*((bits<=1024)?160:pgpDiscreteLogExponentBits(bits))
4ae365 ¤   ¤   ¤   ··¤ + ((bits<=1024)?160:pgpDiscreteLogQBits(bits)) + 128;
2dad26 ¤   ¤   ··/* Always return fastgen value
48f344 ¤   ¤   ···* if (!fastgen || !pgpDSAfixed (bits, NULL, NULL, NULL, NULL))
4ec971 ¤   ¤   ···*/
7ef0b7 ¤   ¤   ¤   ··xbits += DSADUMMYBITS;
5981e4 ¤   ¤   ··return xbits;
b19371 ¤   }
3aaadb ¤   pgpAssert (0);
763e6b ¤   return 0;
55efe6 }
--199e 0003937d34e4010021d Page 1 of pgpPubKey.h
bc38e5 /*
07bce4 ·* pgpPubKey.h -- Structures for PGP Public/Private Keys
96775e ·*
647ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
d2775e ·*
3919d0 ·* $Id: pgpPubKey.h,v 1.25 1998/06/11 18:28:21 hal Exp $
b3495d ·*/
43af5a
5d1d35 #ifndef Included_pgpPubKey_h
ab9c03 #define Included_pgpPubKey_h
c1af5a
3ed11f #include "pgpUsuals.h"
deaf5a
4d99c6 PGP_BEGIN_C_DECLARATIONS
a5af5a
52adb8 #include "pgpOpaqueStructs.h"
cf42aa #include "pgpPublicKey.h"
2a5579 #include "pgpStr2Key.h"
62af5a
0aaf5a
77d914 struct PGPPubKey {
138a97 ¤   PGPContextRef¤  context;
8867c5 ¤
fa9526 ¤   PGPPubKey *next;
0a7272 ¤   PGPByte pkAlg;
806d21 ¤   PGPByte keyID[8];
eae041 ¤   void *priv;
c4a50d ¤   void (*destroy) (PGPPubKey *pubkey);
382889 ¤   /* The sizes of buffers required for encrypt, etc. */
0b4400 ¤   size_t (*maxesk) (PGPPubKey const *pubkey,
35a299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
2da0a0 ¤   size_t (*maxdecrypted) (PGPPubKey const *pubkey,
92a299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
f3a563 ¤   size_t (*maxsig) (PGPPubKey const *pubkey,
dca299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
c8aa24 ¤   int (*encrypt) (PGPPubKey const *pubkey, PGPByte const *key,
79e1a2 ¤   ¤   ¤   ¤   ¤   size_t keylen, PGPByte *esk, size_t *esklen,
2695da ¤   ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
b3a299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
01ac94 ¤   int (*verify) (PGPPubKey const *pubkey,
f9e297 ¤   ¤   ¤   ¤   ¤   PGPByte const *sig, size_t siglen,
5a502d ¤   ¤   ¤   ¤   ¤   PGPHashVTBL const *h, PGPByte const *hash,
aba299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
5ad0fd ¤   size_t (*bufferLength)(PGPPubKey const *pubkey);
c0d887 ¤   void (*toBuffer)(PGPPubKey const *pubkey, PGPByte *buf);
8682f7 };
71af5a
b6af5a
2fcbbe struct PGPSecKey {
498a97 ¤   PGPContextRef¤  context;
dc67c5 ¤
577272 ¤   PGPByte pkAlg;
fa6d21 ¤   PGPByte keyID[8];
03e041 ¤   void *priv;
116e14 ¤   void (*destroy) (PGPSecKey *seckey);
400c62 ¤   PGPPubKey * (*pubkey) (PGPSecKey const *seckey);
b66380 ¤   int (*islocked) (PGPSecKey const *seckey);
6531df ¤   PGPError (*lockingalgorithm) (PGPSecKey const *seckey,
70fa0e ¤   ¤   ¤   ¤   ¤   PGPCipherAlgorithm *alg, PGPSize *algKeySize);
dbc81f ¤   PGPError (*s2ktype) (PGPSecKey const *seckey,
4fe719 ¤   ¤   ¤   ¤   ¤   PGPStringToKeyType *s2kType);
c972dd ¤   PGPError (*convertpassphrase) (PGPSecKey *seckey, PGPEnv const *env,
9b4825 ¤   ¤   ¤   ¤   ¤   char const *phrase, PGPSize plen, PGPByte *outbuf);
32e18a ¤   int (*unlock) (PGPSecKey *seckey, PGPEnv const *env,
53dd01 ¤   ¤   ¤   ¤   ¤   char const *phrase, size_t plen, PGPBoolean hashedPhrase);
c1fcba ¤   void (*lock) (PGPSecKey *seckey);
cbf263 ¤   /* The sizes of buffers required for decrypt, etc. */
f03d61 ¤   size_t (*maxesk) (PGPSecKey const *seckey,
7da299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
84d9c1 ¤   size_t (*maxdecrypted) (PGPSecKey const *seckey,
0ca299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
39dc02 ¤   size_t (*maxsig) (PGPSecKey const *seckey,
--73eb 0002d39fe2b4010021d Page 2 of pgpPubKey.h
3ba299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
c5ac6b ¤   int (*decrypt) (PGPSecKey *seckey, PGPEnv const *env,
576b39 ¤   ¤   ¤   ¤   ¤   PGPByte const *esk, size_t esklen,
cd3222 ¤   ¤   ¤   ¤   ¤   PGPByte *key, size_t *keylen,
3eedd6 ¤   ¤   ¤   ¤   ¤   char const *phrase, size_t plen,
a3a299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
4dcffd ¤   int (*sign) (PGPSecKey *seckey,
70502d ¤   ¤   ¤   ¤   ¤   PGPHashVTBL const *h, PGPByte const *hash,
dd49d1 ¤   ¤   ¤   ¤   ¤   PGPByte *sig, size_t *siglen,
8e95da ¤   ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
16a299 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat format);
e2c709 ¤   int (*changeLock)(PGPSecKey *seckey, PGPEnv const *env,
f795da ¤   ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
a5edd6 ¤   ¤   ¤   ¤   ¤   char const *phrase, size_t plen,
502d37 ¤   ¤   ¤   ¤   ¤   PGPStringToKeyType s2ktype);
a0a20b ¤   size_t (*bufferLength)(PGPSecKey const *seckey);
34e748 ¤   void (*toBuffer)(PGPSecKey const *seckey, PGPByte *buf);
8f82f7 };
d9af5a
c2af5a
4f577e #include "pgpKeys.h"¤   /* to get 'PGPPublicKeyAlgorithm' type */
9d38e5 /*
71efa1 ·* Note on kPGPPublicKeyAlgorithm_RSAEncryptOnly/SignOnly:
2f775e ·*
f50ebf ·* These are ViaCrypt's "restricted" versions of RSA. ·There are reasons
7b0654 ·* to want PGP to limit you in this way. ·Some forces which might try
0d0d8d ·* to force disclosure of your key (such as courts) can be dissuaded on
02c0f7 ·* the grounds that nothing is being hidden by the keys.
d7775e ·*
4f15c3 ·* The *annoying* thing, however, is that ViaCrypt chose to leave the
c8fc7a ·* encrypted session kay and signature packets with a pkalg byte of 1.
997ce9 ·* Which means that various bits of code contain kludges to deal with
149779 ·* this fact.
f7495d ·*/
c2af5a
33a048 #define PGP_PKUSE_SIGN ·········0x01
18bc53 #define PGP_PKUSE_ENCRYPT ······0x02
06512c #define PGP_PKUSE_SIGN_ENCRYPT ·(PGP_PKUSE_SIGN | PGP_PKUSE_ENCRYPT)
8caf5a
c2cb68 #define pgpPubKeyNext(p)¤   (p)->next
b58681 #define pgpPubKeyDestroy(p)¤(p)->destroy(p)
2ce865 #define pgpPubKeyMaxesk(p,f)¤   (p)->maxesk(p,f)
d94fc1 #define pgpPubKeyMaxdecrypted(p,f)¤ (p)->maxdecrypted(p,f)
800470 #define pgpPubKeyMaxsig(p,f)¤   (p)->maxsig(p,f)
b34f86 #define pgpPubKeyMaxsighash(p,f)¤   (p)->maxsighash(p,f)
8415c3 #define pgpPubKeyEncrypt(p,k,kl,e,el,r,f)¤  (p)->encrypt(p,k,kl,e,el,r,f)
c0bd24 #define pgpPubKeyVerify(p,s,sl,h,ha,f)¤ (p)->verify(p,s,sl,h,ha,f)
7e6849 #define pgpPubKeyBufferLength(p)¤   (p)->bufferLength(p)
a90802 #define pgpPubKeyToBuffer(p,b)¤ ¤   (p)->toBuffer(p,b)
e7af5a
5a4797 #define pgpSecKeyDestroy(s)¤(s)->destroy(s)
df8054 #define pgpSecKeyPubkey(s)¤ (s)->pubkey(s)
e1e84b #define pgpSecKeyIslocked(s)¤   (s)->islocked(s)
6db65e #define pgpSecKeyLockingalgorithm(s,a,k)¤   (s)->lockingalgorithm(s,a,k)
cc708c #define pgpSecKeyS2Ktype(s,t)¤  (s)->s2ktype(s,t)
2c55f9 #define pgpSecKeyConvertPassphrase(s,e,p,l,o) \
4e428d ¤   ¤   ¤   ¤   ¤   (s)->convertpassphrase(s,e,p,l,o)
1fe84b #define pgpSecKeyIslocked(s)¤   (s)->islocked(s)
081499 #define pgpSecKeyUnlock(s,e,p,pl,hp)¤   (s)->unlock(s,e,p,pl,hp)
838c04 #define pgpSecKeyLock(s)¤   (s)->lock(s)
9ac548 #define pgpSecKeyMaxesk(s,f)¤   (s)->maxesk(s,f)
9791a1 #define pgpSecKeyMaxdecrypted(s,f)¤ (s)->maxdecrypted(s,f)
0a295d #define pgpSecKeyMaxsig(s,f)¤   (s)->maxsig(s,f)
6e5a9c #define pgpSecKeyMaxsighash(s,f)¤   (s)->maxsighash(s,f)
dad542 #define pgpSecKeyDecrypt(s,env,e,el,k,kl,p,pl,f)¤   (s)->decrypt(s,env,\
c0938a ¤   ¤   e,el,k,kl,p,pl,f)
dbc826 #define pgpSecKeySign(s,h,ha,si,sil,r,f)¤   (s)->sign(s,h,ha,si,sil,r,f)
393bd7 #define pgpSecKeyChangeLock(s,e,r,p,pl,t)¤  (s)->changeLock(s,e,r,p,pl,t)
867a61 #define pgpSecKeyBufferLength(s)¤   (s)->bufferLength(s)
72f1e6 #define pgpSecKeyToBuffer(s,b)¤ ¤   (s)->toBuffer(s,b)
caaf5a
2d5e48 PGPPkAlg const ·*pgpPkalgByNumber(PGPByte pkalg);
--4a68 001fd03d7ba4010021d Page 3 of pgpPubKey.h
efe381 int ·pgpKeyUse(PGPPkAlg const *pkAlg);·
53ba92 size_t ·pgpPubKeyPrefixSize(PGPByte pkAlg, PGPByte const *p, size_t len);
35af5a
524b89 PGPPubKey ·*¤   pgpPubKeyFromBuf(PGPContextRef¤ context,
1e31a6 ¤   ¤   ¤   ¤   ¤   PGPByte pkAlg, PGPByte const *p, size_t len,
4b9613 ¤   ¤   ¤   ¤   ¤   PGPError *error);
82ae30 ¤   ¤   ¤   ¤   ¤
d2b262 PGPSecKey ·*¤   pgpSecKeyFromBuf( PGPContextRef¤context,
226019 ¤   ¤   ¤   ¤   ¤   PGPByte pkAlg, PGPByte const *p, size_t len, PGPBoolean v3,
da9613 ¤   ¤   ¤   ¤   ¤   PGPError *error);
4aaf5a
b51af0 unsigned¤   ¤   ¤   pgpSecKeyEntropy(PGPPkAlg const *pkAlg,
a33636 ¤   ¤   ¤   ¤   ¤   ¤   unsigned bits, PGPBoolean fastgen);
0794aa ¤   ¤   ¤   ¤   ¤   ¤
7b674e PGPSecKey ·*¤   pgpSecKeyGenerate(PGPContextRef¤context,
bd7da7 ¤   ¤   ¤   ¤   ¤   PGPPkAlg const *pkAlg,
9fd4c4 ¤   ¤   ¤   ¤   ¤   unsigned bits, PGPBoolean fastgen,
f195da ¤   ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
d080d0 ¤   ¤   ¤   ¤   ¤   int (*progress)(void *arg, int c),
4333b9 ¤   ¤   ¤   ¤   ¤   void *arg, PGPError *error);
1eaf5a
66c044 PGPBoolean¤ ¤   pgpIsKeyRelatedError( PGPError err );
f6af5a
baaf5a
1e1254 PGP_END_C_DECLARATIONS
c3af5a
fdde9f #endif /* Included_pgpPubKey_h */
--210f 000c27d4ff84010021e Page 1 of pgpPublicKey.c
a70335 /*____________________________________________________________________________
fce482 ¤   pgpPublicKey.c
d267c5 ¤
00c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
de4b0f ¤   All rights reserved.
7267c5 ¤
4d67c5 ¤
92af5a
d6ae23 ¤   $Id: pgpPublicKey.c,v 1.13.10.1 1998/11/12 03:22:11 heller Exp $
27f7f7 ____________________________________________________________________________*/
6ae2ff #include "pgpConfig.h"
2d324c #include <string.h>
05af5a
f842aa #include "pgpPublicKey.h"
b89f72 #include "pgpHash.h"
fb0d08 #include "pgpMem.h"
4e2f8d #include "pgpErrors.h"
c3c26c #include "pgpContext.h"
bb5417 #include "pgpHashPriv.h"
cb5430 #include "pgpUtilitiesPriv.h"
fd979a #include "pgpKDBInt.h"
9bcdc2 #include "pgpPubKey.h"
0e007f #include "pgpKeyMisc.h"
cc0141 #include "pgpOptionListPriv.h"
5daf5a
a058d9 #define PGPValidatePublicKey( pkref )¤  \
40ea35 ¤   PGPValidateParam( pgpPublicKeyIsValid( pkref ) );
e30160 #define PGPValidatePrivateKey( pkref )¤ \
efb306 ¤   PGPValidateParam( pgpPrivateKeyIsValid( pkref ) );
12f73b #define PGPValidateMessageFormat( messageFormat ) \
4115b7 ¤   PGPValidateParam( pgpMessageFormatIsValid( messageFormat ) );
2067c5 ¤
67d622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
60af5a
355027 struct PGPPublicKeyContext
3abb36 {
fe7619 #define kPublicKeyMagic¤¤   ¤   ¤   0x58210770
4ebae3 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   magic;
81f0d4 ¤   PGPContextRef¤  ¤   ¤   ¤   ¤   context;
76fd83 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   ¤   key;
c60d26 ¤   PGPPublicKeyMessageFormat¤  ¤   format;
a39ed1 ¤   PGPPubKey¤  ¤   ¤   ¤   ¤   ¤   *enckey;
3bfd2d ¤   PGPPubKey¤  ¤   ¤   ¤   ¤   ¤   *signkey;
4482f7 };
c8af5a
9da555 struct PGPPrivateKeyContext
36bb36 {
aa7a71 #define kPrivateKeyMagic¤   ¤   ¤   0x58249779
d7bae3 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   magic;
d3f0d4 ¤   PGPContextRef¤  ¤   ¤   ¤   ¤   context;
20fd83 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   ¤   key;
cc0d26 ¤   PGPPublicKeyMessageFormat¤  ¤   format;
5e389c ¤   PGPSecKey¤  ¤   ¤   ¤   ¤   ¤   *enckey;
af646a ¤   PGPSecKey¤  ¤   ¤   ¤   ¤   ¤   *signkey;
9482f7 };
25af5a
8caf5a
ef6c2c ¤   static PGPBoolean
367522 pgpPublicKeyIsValid( const PGPPublicKeyContext * ref)
51bb36 {
26984c ¤   PGPBoolean¤ valid¤  = FALSE;
2a67c5 ¤
9eca94 ¤   valid¤  = IsntNull( ref ) && ref->magic¤ == kPublicKeyMagic;
4b67c5 ¤
5a0b09 ¤   return( valid );
8eefe6 }
63af5a
366c2c ¤   static PGPBoolean
20dad8 pgpPrivateKeyIsValid( const PGPPrivateKeyContext * ref)
32bb36 {
ba984c ¤   PGPBoolean¤ valid¤  = FALSE;
c267c5 ¤
--c91d 00083aab51f4010021e Page 2 of pgpPublicKey.c
476760 ¤   valid¤  = IsntNull( ref ) && ref->magic¤ == kPrivateKeyMagic;
9167c5 ¤
4a0b09 ¤   return( valid );
bdefe6 }
44af5a
726c2c ¤   static PGPBoolean
8efb5d pgpMessageFormatIsValid( PGPPublicKeyMessageFormat messageFormat )
36bb36 {
03984c ¤   PGPBoolean¤ valid¤  = FALSE;
5867c5 ¤
aa3c91 ¤   valid = (messageFormat == kPGPPublicKeyMessageFormat_PGP) ||
1eb941 ¤   ¤   ¤   (messageFormat == kPGPPublicKeyMessageFormat_PKCS1) ||
41072c ¤   ¤   ¤   (messageFormat == kPGPPublicKeyMessageFormat_X509);
bb67c5 ¤
ec0b09 ¤   return( valid );
7befe6 }
f6af5a
54af5a
448457 PGPError¤   ¤   sSetupPubkey( PGPPublicKeyContextRef ref );
9c53fc PGPError¤   ¤   sSetupPrivkey( PGPPrivateKeyContextRef ref,
61a37e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···char const *passphrase,
c8c65d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPSize passphraseLength,
3e52ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPBoolean hashedPhrase );
a5af5a
58af5a
f7af5a
8f0335 /*____________________________________________________________________________
355cd4 ¤   Exported routines, public key operations
3ff7f7 ____________________________________________________________________________*/
1aaf5a
36c744 ¤   PGPError
7906ad PGPNewPublicKeyContext(
389e7b ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   publicKeyRef,
a5659c ¤   PGPPublicKeyMessageFormat¤  messageFormat,
a9408a ¤   PGPPublicKeyContextRef *¤   outRef )
00bb36 {
483403 ¤   PGPPublicKeyContextRef¤ ¤   newRef¤ = NULL;
d550a5 ¤   PGPContextRef¤  ¤   ¤   ¤   context;
839981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
3267c5 ¤
3b3c76 ¤   PGPValidatePtr( outRef );
fe3652 ¤   *outRef¤= NULL;
709f58 ¤   PGPValidateKey( publicKeyRef );
eda11f ¤   PGPValidateMessageFormat( messageFormat );
7e67c5 ¤
d0f732 ¤   context = PGPGetKeyContext( publicKeyRef );
7eaf5a
385994 ¤   newRef¤ = (PGPPublicKeyContextRef) pgpContextMemAlloc( context,
24fdde ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *newRef ),
46da17 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
5a87c7 ¤   ¤   ¤
e66c1a ¤   if ( IsntNull( newRef ) )
20c7a1 ¤   {
ade316 ¤   ¤   newRef->magic¤  ¤   ¤   ¤   ¤   ¤   = kPublicKeyMagic;
3dd89d ¤   ¤   newRef->context¤¤   ¤   ¤   ¤   ¤   = context;
258b96 ¤   ¤   newRef->key¤¤   ¤   ¤   ¤   ¤   ¤   = publicKeyRef;
3a13dc ¤   ¤   newRef->format¤ ¤   ¤   ¤   ¤   ¤   = messageFormat;
aeaf5a
3a9810 ¤   ¤   err = sSetupPubkey( newRef );
5daf5a
5cd223 ¤   ¤   if( IsPGPError( err ) )
485b34 ¤   ¤   {
dc5669 ¤   ¤   ¤   pgpContextMemFree( context, newRef );
97fe46 ¤   ¤   ¤   newRef = NULL;
720fe4 ¤   ¤   }
6d9371 ¤   }
4f0e24 ¤   else
fec7a1 ¤   {
9b17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
519371 ¤   }
bb67c5 ¤
83cdaf ¤   *outRef¤= newRef;
--ba4f 00021b3a6304010021e Page 3 of pgpPublicKey.c
afdeb7 ¤   return( err );
b7efe6 }
35af5a
adaf5a
8daf5a
1e0335 /*____________________________________________________________________________
3df7f7 ____________________________________________________________________________*/
6f21ab ¤   PGPError·
1bb8d2 PGPFreePublicKeyContext( PGPPublicKeyContextRef ref )
7fbb36 {
d19372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b8d04d ¤   PGPContextRef¤  context¤= NULL;
8f67c5 ¤
b9d9e3 ¤   PGPValidatePublicKey( ref );
6baf5a
c26ee8 ¤   context¤= ref->context;
c367c5 ¤
e57c9b ¤   if( IsntNull( ref->enckey ) )
2f2fc7 ¤   ¤   pgpPubKeyDestroy( ref->enckey );
d99905 ¤   if( IsntNull( ref->signkey ) )
5342d2 ¤   ¤   pgpPubKeyDestroy( ref->signkey );
0967c5 ¤
a24500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
495cdb ¤   pgpContextMemFree( context, ref );
5667c5 ¤
5cdeb7 ¤   return( err );
e9efe6 }
5daf5a
76af5a
19af5a
7c0335 /*____________________________________________________________________________
37f7f7 ____________________________________________________________________________*/
b6c744 ¤   PGPError
a6392f PGPPublicKeyEncrypt(
f0cb1d ¤   PGPPublicKeyContextRef¤ ref,
2257de ¤   const void *¤   ¤   ¤   in,
7f9a94 ¤   PGPSize¤¤   ¤   ¤   ¤   inSize,
fdeed7 ¤   void *¤ ¤   ¤   ¤   ¤   out,
563d0f ¤   PGPSize *¤  ¤   ¤   ¤   outSize)
edbb36 {
ce71f6 ¤   PGPRandomContext *¤ ¤   ¤   randomContext;
7bcc63 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   lOutSize;
b99981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
9967c5 ¤
4c895b ¤   if( IsntNull( outSize ) )
6ac7a1 ¤   {
47f78b ¤   ¤   PGPValidatePtr( outSize );
d1f580 ¤   ¤   *outSize = 0;
299371 ¤   }
fd254f ¤   PGPValidatePtr( out );
24d9e3 ¤   PGPValidatePublicKey( ref );
323bf7 ¤   PGPValidatePtr( in );
b1b0af ¤   PGPValidateParam( inSize != 0 );
daaf5a
bec0fb ¤   if( IsNull( ref->enckey ) )
f1dffa ¤   ¤   return kPGPError_FeatureNotAvailable;
3eaf5a
d6fa6a ¤   randomContext = pgpContextGetX9_17RandomContext( ref->context );
43af5a
84ab51 ¤   err = pgpPubKeyEncrypt( ref->enckey, (const PGPByte *) in, inSize,
71148f ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPByte *) out, &lOutSize, randomContext,
021e84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ref->format );
7daf5a
13f869 ¤   if( IsntPGPError( err ) ·&& IsntNull( outSize ) )
d0c7a1 ¤   {
7465ff ¤   ¤   *outSize = lOutSize;
c29371 ¤   }
b4af5a
f5deb7 ¤   return( err );
3fefe6 }
07af5a
21af5a
--60bf 00090f0aea64010021e Page 4 of pgpPublicKey.c
a70335 /*____________________________________________________________________________
92f7f7 ____________________________________________________________________________*/
91c744 ¤   PGPError
f8d2a6 PGPPublicKeyVerifySignature(
bc00bf ¤   PGPPublicKeyContextRef¤ ¤   ref,
e65312 ¤   PGPHashContextRef¤  ¤   ¤   hashContext,
f7ab7b ¤   const void *¤   ¤   ¤   ¤   signature,
433a26 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   signatureSize)
c1bb36 {
779981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
8629d3 ¤   PGPHashVTBL const *¤¤   ¤   hashVTBL;
e349f1 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   hashSize;
23a280 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   hashData[100];
423ce0 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   rslt;
bb67c5 ¤
0bd9e3 ¤   PGPValidatePublicKey( ref );
1f0915 ¤   PGPValidatePtr( hashContext );
74bf61 ¤   PGPValidatePtr( signature );
a3199a ¤   PGPValidateParam( signatureSize != 0 );
b8af5a
47fabf ¤   if( IsNull( ref->signkey ) )
4bdffa ¤   ¤   return kPGPError_FeatureNotAvailable;
b6af5a
8a2e39 ¤   /* Hash too big for our array? */
308a19 ¤   PGPGetHashSize( hashContext, &hashSize );
f348cf ¤   if( hashSize > sizeof(hashData) )
55c7a1 ¤   {
6a79d3 ¤   ¤   PGPFreeHashContext( hashContext );
2362b5 ¤   ¤   return kPGPError_BadParams;
f29371 ¤   }
c7af5a
fbce78 ¤   hashVTBL = pgpHashGetVTBL( hashContext );
d9ea30 ¤   PGPFinalizeHash( hashContext, hashData );
10af5a
cf0173 ¤   /* Do the verification */
db0b9d ¤   rslt = pgpPubKeyVerify( ref->signkey, (const PGPByte *) signature,
23fce4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   signatureSize, hashVTBL, hashData, ref->format );
2faf5a
82779f ¤   PGPFreeHashContext( hashContext );
1eaf5a
c3ebff ¤   if( rslt != 1 )
09c7a1 ¤   {
37faaa ¤   ¤   err = kPGPError_BadSignature;
2b9371 ¤   }
69af5a
47deb7 ¤   return( err );
f5efe6 }
1eaf5a
d9af5a
910335 /*____________________________________________________________________________
f7f7f7 ____________________________________________________________________________*/
a6c744 ¤   PGPError
f5d0ef PGPPublicKeyVerifyRaw(
2100bf ¤   PGPPublicKeyContextRef¤ ¤   ref,
9afa35 ¤   const void *¤   ¤   ¤   ¤   signedData,
f03d3e ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   signedDataSize,
d4ab7b ¤   const void *¤   ¤   ¤   ¤   signature,
7e3a26 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   signatureSize)
09bb36 {
d89981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
39a04b ¤   PGPHashVTBL¤¤   ¤   ¤   ¤   dummyVTBL;
6c3ce0 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   rslt;
1c67c5 ¤
73d9e3 ¤   PGPValidatePublicKey( ref );
ba093b ¤   PGPValidatePtr( signedData );
59b4f6 ¤   PGPValidateParam( signedDataSize != 0 );
806b14 ¤   /* Raw mode supported only for PKCS sigs */
266407 ¤   if( ref->format != ¤kPGPPublicKeyMessageFormat_PKCS1 ) {
6b62b5 ¤   ¤   return kPGPError_BadParams;
ef9371 ¤   }
f1bf61 ¤   PGPValidatePtr( signature );
90199a ¤   PGPValidateParam( signatureSize != 0 );
--56b5 00061bd655c4010021e Page 5 of pgpPublicKey.c
e0af5a
0ffabf ¤   if( IsNull( ref->signkey ) )
cddffa ¤   ¤   return kPGPError_FeatureNotAvailable;
35af5a
27ee68 ¤   /* Set up value for hash size used by signature function */
afa7cf ¤   pgpClearMemory( &dummyVTBL, sizeof(dummyVTBL) );
c7bb12 ¤   dummyVTBL.hashsize = signedDataSize;
5eaf5a
a00173 ¤   /* Do the verification */
e90b9d ¤   rslt = pgpPubKeyVerify( ref->signkey, (const PGPByte *) signature,
3c221a ¤   ¤   ¤   ¤   ¤   ¤   ¤   signatureSize, &dummyVTBL,
caffd9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (const PGPByte *)signedData, ref->format );
a8af5a
2aebff ¤   if( rslt != 1 )
5dc7a1 ¤   {
5dfaaa ¤   ¤   err = kPGPError_BadSignature;
dc9371 ¤   }
baaf5a
39deb7 ¤   return( err );
c1efe6 }
0daf5a
d8af5a
cb0335 /*____________________________________________________________________________
a3c84e If we have an encrypt-only or sign only key, we return zeros for the
b8d666 one(s) which we don't support.
a8f7f7 ____________________________________________________________________________*/
2ac744 ¤   PGPError
74f98f PGPGetPublicKeyOperationSizes(
59cb1d ¤   PGPPublicKeyContextRef¤ ref,
802367 ¤   PGPSize *¤  ¤   ¤   ¤   maxDecryptedBufferSize,
46b736 ¤   PGPSize *¤  ¤   ¤   ¤   maxEncryptedBufferSize,
989a15 ¤   PGPSize *¤  ¤   ¤   ¤   maxSignatureSize )
02bb36 {
a8d9e3 ¤   PGPValidatePublicKey( ref );
301e5d ¤   if( IsntNull( maxDecryptedBufferSize ) )
39017f ¤   ¤   PGPValidatePtr( maxDecryptedBufferSize );
1db95f ¤   if( IsntNull( maxEncryptedBufferSize ) )
d919fd ¤   ¤   PGPValidatePtr( maxEncryptedBufferSize );
80bb7c ¤   if( IsntNull( maxSignatureSize ) )
5c060a ¤   ¤   PGPValidatePtr( maxSignatureSize );
6667c5 ¤
1bb95f ¤   if( IsntNull( maxEncryptedBufferSize ) )
adc7a1 ¤   {
9b4a3c ¤   ¤   if( IsntNull( ref->enckey ) ) {
2c9d3b ¤   ¤   ¤   *maxEncryptedBufferSize = pgpPubKeyMaxesk( ref->enckey,
5ac55f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···ref->format );
2845a6 ¤   ¤   } else {
46b448 ¤   ¤   ¤   *maxEncryptedBufferSize = 0;
bd0fe4 ¤   ¤   }
579371 ¤   }
81af5a
411e5d ¤   if( IsntNull( maxDecryptedBufferSize ) )
42c7a1 ¤   {
ad93e8 ¤   ¤   if( IsntNull( ref->enckey ) )
9f590c ¤   ¤   ¤   *maxDecryptedBufferSize = pgpPubKeyMaxdecrypted( ref->enckey,
a2068d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·ref->format );
7d0e1d ¤   ¤   else
ed97fd ¤   ¤   ¤   *maxDecryptedBufferSize = 0;
189371 ¤   }
2aaf5a
69bb7c ¤   if( IsntNull( maxSignatureSize ) )
5dc7a1 ¤   {
99d8f6 ¤   ¤   if( IsntNull( ref->signkey ) )
527c4b ¤   ¤   ¤   *maxSignatureSize = pgpPubKeyMaxsig( ref->signkey, ref->format );
260e1d ¤   ¤   else
218546 ¤   ¤   ¤   *maxSignatureSize = 0;
479371 ¤   }
11151e ¤   return kPGPError_NoErr;
45efe6 }
4caf5a
d6af5a
61af5a
--f132 0007866364d4010021e Page 6 of pgpPublicKey.c
a70335 /*____________________________________________________________________________
89aab4 ¤   Exported routines, private key operations
85f7f7 ____________________________________________________________________________*/
b7af5a
79af5a
33a72f /* Internal function to create a new private key context */
bd66dd ¤   static PGPError
c02abe sNewPrivateKeyContext (
bf4322 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   privateKeyRef,
c8659c ¤   PGPPublicKeyMessageFormat¤  messageFormat,
a50c71 ¤   char const *¤   ¤   ¤   ¤   passphrase,
2e45a0 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   passphraseLength,
cb2655 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   hashedPhrase,
5061d4 ¤   PGPPrivateKeyContextRef *¤  outRef )
2967c5 ¤
eebb36 {
f8f125 ¤   PGPPrivateKeyContextRef¤¤   newRef¤ = NULL;
4e50a5 ¤   PGPContextRef¤  ¤   ¤   ¤   context;
5e9981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
2567c5 ¤
7b51a4 ¤   context = PGPGetKeyContext( privateKeyRef );
45af5a
c876c9 ¤   newRef¤ = (PGPPrivateKeyContextRef) pgpContextMemAlloc( context,
d4fdde ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *newRef ),
60da17 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
f987c7 ¤   ¤   ¤
a16c1a ¤   if ( IsntNull( newRef ) )
cdc7a1 ¤   {
8cc053 ¤   ¤   newRef->magic¤  ¤   ¤   ¤   ¤   ¤   = kPrivateKeyMagic;
c1d89d ¤   ¤   newRef->context¤¤   ¤   ¤   ¤   ¤   = context;
2eaed5 ¤   ¤   newRef->key¤¤   ¤   ¤   ¤   ¤   ¤   = privateKeyRef;
eb13dc ¤   ¤   newRef->format¤ ¤   ¤   ¤   ¤   ¤   = messageFormat;
75af5a
07cf5d ¤   ¤   err = sSetupPrivkey( newRef, passphrase, passphraseLength,
f24f27 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·hashedPhrase );
05af5a
2bd223 ¤   ¤   if( IsPGPError( err ) )
b15b34 ¤   ¤   {
7d5669 ¤   ¤   ¤   pgpContextMemFree( context, newRef );
68fe46 ¤   ¤   ¤   newRef = NULL;
f00fe4 ¤   ¤   }
269371 ¤   }
540e24 ¤   else
1ec7a1 ¤   {
a417a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
629371 ¤   }
0d67c5 ¤
5bcdaf ¤   *outRef¤= newRef;
3adeb7 ¤   return( err );
41efe6 }
5faf5a
f7af5a
0eaf5a
d79411 static const PGPOptionType privctxOptionSet[] = {
ea28df ¤   ·kPGPOptionType_Passphrase,
8c7fbb ¤   ·kPGPOptionType_Passkey,
0b82f7 };
5daf5a
64af5a
8766dd ¤   static PGPError
dce2b9 pgpNewPrivateKeyContextInternal (
4e4322 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   privateKeyRef,
cc659c ¤   PGPPublicKeyMessageFormat¤  messageFormat,
c07871 ¤   PGPPrivateKeyContextRef *¤  outRef,
340a42 ¤   PGPOptionListRef¤   ¤   ¤   optionList
9f27e6 ¤   )
f1bb36 {
755037 ¤   char *¤ ¤   ¤   ¤   ¤   ¤   passphrase;
039d39 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   passphraseLength;
f401cf ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   hashedPhrase = FALSE;
613146 ¤   PGPError¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
78af5a
--6aee 000453943024010021e Page 7 of pgpPublicKey.c
ea4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
cb8140 ¤   ¤   ¤   ¤   ¤   privctxOptionSet, elemsof( privctxOptionSet ) ) ) )
08c9db ¤   ¤   return err;
45af5a
447bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
c54dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
798dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
ff97ed ¤   ¤   goto error;
980809 ¤   if (IsNull( passphrase )) {
8a5a97 ¤   ¤   hashedPhrase = TRUE;
175d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
3960d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
6ec392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
dbed19 ¤   ¤   ¤   goto error;
5c9371 ¤   }
17af5a
875213 ¤   err = sNewPrivateKeyContext( privateKeyRef, messageFormat, passphrase,
93c3ea ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·passphraseLength, hashedPhrase, outRef );
dfaf5a
ca60ff error:
1eaf5a
7b5ea8 ¤   return err;
47efe6 }
00af5a
a37ec2 /* Version of NewPrivateKeyContext which takes passphrase options */
fec744 ¤   PGPError
a0b3f0 PGPNewPrivateKeyContext(
884322 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   privateKeyRef,
60659c ¤   PGPPublicKeyMessageFormat¤  messageFormat,
5d7871 ¤   PGPPrivateKeyContextRef *¤  outRef,
2ab77a ¤   PGPOptionListRef¤   ¤   ¤   firstOption,
9ec9f6 ¤   ...
cd27e6 ¤   )
b5bb36 {
1e5108 ¤   PGPError¤   error¤  = kPGPError_NoErr;
9a67c5 ¤
c43c76 ¤   PGPValidatePtr( outRef );
753652 ¤   *outRef¤= NULL;
2e9d90 ¤   PGPValidateKey( privateKeyRef );
17a11f ¤   PGPValidateMessageFormat( messageFormat );
38af5a
42c7a1 ¤   {
b736db ¤   ¤   va_list¤¤   ¤   ¤   args;
24444d ¤   ¤   PGPContextRef¤  ¤   context;
28f888 ¤   ¤   PGPOptionListRef¤   optionList;
d2af5a
5f02bf ¤   ¤   context = PGPGetKeyContext( privateKeyRef );
3aaf5a
d602ff ¤   ¤   va_start( args, firstOption );
4a6bec ¤   ¤   optionList = pgpBuildOptionListArgs( context,
41b819 ¤   ¤   ¤   FALSE, firstOption, args );
14af5a
01b8fa ¤   ¤   error = pgpGetOptionListError( optionList );
76cb70 ¤   ¤   if( IsntPGPError( error ) )
0b5b34 ¤   ¤   {
ccde56 ¤   ¤   ¤   error = pgpNewPrivateKeyContextInternal( privateKeyRef,
30d50f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   messageFormat, outRef, optionList );
860fe4 ¤   ¤   }
0dc414 ¤   ¤   va_end( args );
7aaf5a
ad153d ¤   ¤   PGPFreeOptionList( optionList );
129371 ¤   }
6567c5 ¤
5057f8 ¤   return( error );
d5efe6 }
c6af5a
ceaf5a
58b177 #if 0
c680f0 /* Replaced by PGPOptionList version above */
b2c744 ¤   PGPError
46b3f0 PGPNewPrivateKeyContext(
454322 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   privateKeyRef,
--3e55 00076c99f5a4010021e Page 8 of pgpPublicKey.c
4b659c ¤   PGPPublicKeyMessageFormat¤  messageFormat,
3b0c71 ¤   char const *¤   ¤   ¤   ¤   passphrase,
ee61d4 ¤   PGPPrivateKeyContextRef *¤  outRef )
c9bb36 {
9c20c1 ¤   PGPSize¤¤   passphraseLength = 0;
b961e0 ¤   PGPError¤   err;
a8af5a
d83c76 ¤   PGPValidatePtr( outRef );
313652 ¤   *outRef¤= NULL;
939d90 ¤   PGPValidateKey( privateKeyRef );
f8a11f ¤   PGPValidateMessageFormat( messageFormat );
ecaf5a
2c2a79 ¤   if( IsntNull( passphrase ) )
fdc7a1 ¤   {
2251a5 ¤   ¤   PGPValidatePtr( passphrase );
e6a3a2 ¤   ¤   passphraseLength = strlen( passphrase );
b79371 ¤   }
c167c5 ¤
1c167c ¤   err = sNewPrivateKeyContext (privateKeyRef, messageFormat, passphrase,
7da5e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·passphraseLength, FALSE, outRef );
a65ea8 ¤   return err;
4befe6 }
687454 #endif
deaf5a
4caf5a
aeaf5a
510335 /*____________________________________________________________________________
95f7f7 ____________________________________________________________________________*/
9621ab ¤   PGPError·
836e61 PGPFreePrivateKeyContext( PGPPrivateKeyContextRef ref )
9dbb36 {
6a9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
fdd04d ¤   PGPContextRef¤  context¤= NULL;
0667c5 ¤
7015ba ¤   PGPValidatePrivateKey( ref );
d7af5a
006ee8 ¤   context¤= ref->context;
0867c5 ¤
7c7c9b ¤   if( IsntNull( ref->enckey ) )
276b23 ¤   ¤   pgpSecKeyDestroy( ref->enckey );
989905 ¤   if( IsntNull( ref->signkey ) )
2ee3bc ¤   ¤   pgpSecKeyDestroy( ref->signkey );
9d67c5 ¤
ea4500 ¤   pgpClearMemory( ref, sizeof( *ref ) );
e65cdb ¤   pgpContextMemFree( context, ref );
9167c5 ¤
fadeb7 ¤   return( err );
ffefe6 }
04af5a
b8af5a
ecaf5a
ba0335 /*____________________________________________________________________________
f1f7f7 ____________________________________________________________________________*/
41c744 ¤   PGPError
48a5a2 PGPPrivateKeyDecrypt(
ad9c48 ¤   PGPPrivateKeyContextRef¤¤   ref,
8241e0 ¤   const void *¤   ¤   ¤   ¤   in,
0c6239 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   inSize,
7fcdba ¤   void *¤ ¤   ¤   ¤   ¤   ¤   out,
1cb894 ¤   PGPSize *¤  ¤   ¤   ¤   ¤   outSize)
55bb36 {
77cc63 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   lOutSize;
9ad951 ¤   PGPEnv *¤   ¤   ¤   ¤   ¤   env;
089981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
f567c5 ¤
5a895b ¤   if( IsntNull( outSize ) )
abc7a1 ¤   {
b5f78b ¤   ¤   PGPValidatePtr( outSize );
adf580 ¤   ¤   *outSize = 0;
f89371 ¤   }
1d254f ¤   PGPValidatePtr( out );
7615ba ¤   PGPValidatePrivateKey( ref );
--5983 0006bd2b2a84010021e Page 9 of pgpPublicKey.c
b43bf7 ¤   PGPValidatePtr( in );
aeb0af ¤   PGPValidateParam( inSize != 0 );
96af5a
cdaf5a
bfc0fb ¤   if( IsNull( ref->enckey ) )
a8dffa ¤   ¤   return kPGPError_FeatureNotAvailable;
33af5a
64a0d8 ¤   env = pgpContextGetEnvironment( ref->context );
94af5a
089c12 ¤   err = pgpSecKeyDecrypt( ref->enckey, env, (const PGPByte *) in, inSize,
607239 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPByte *) out, &lOutSize, NULL, 0, ref->format );
fbaf5a
9cf869 ¤   if( IsntPGPError( err ) ·&& IsntNull( outSize ) )
b4c7a1 ¤   {
ad65ff ¤   ¤   *outSize = lOutSize;
139371 ¤   }
0faf5a
5edeb7 ¤   return( err );
3cefe6 }
ecaf5a
78af5a
cc0335 /*____________________________________________________________________________
02f7f7 ____________________________________________________________________________*/
a2c744 ¤   PGPError
0d4423 PGPPrivateKeySign(
b99c48 ¤   PGPPrivateKeyContextRef¤¤   ref,
e35312 ¤   PGPHashContextRef¤  ¤   ¤   hashContext,
a14d28 ¤   void *¤ ¤   ¤   ¤   ¤   ¤   signature,
eb1948 ¤   PGPSize *¤  ¤   ¤   ¤   ¤   signatureSize)
4dbb36 {
ec71f6 ¤   PGPRandomContext *¤ ¤   ¤   randomContext;
6e29d3 ¤   PGPHashVTBL const *¤¤   ¤   hashVTBL;
1c49f1 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   hashSize;
5da280 ¤   PGPByte¤¤   ¤   ¤   ¤   ¤   hashData[100];
be0bef ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   lSignatureSize;
1f9981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
7767c5 ¤
82adf2 ¤   if( IsntNull( signatureSize ) )
c0c7a1 ¤   {
bca50b ¤   ¤   PGPValidatePtr( signatureSize );
5cabd4 ¤   ¤   *signatureSize = 0;
079371 ¤   }
ac15ba ¤   PGPValidatePrivateKey( ref );
d80915 ¤   PGPValidatePtr( hashContext );
4bbf61 ¤   PGPValidatePtr( signature );
d5af5a
4dfabf ¤   if( IsNull( ref->signkey ) )
30dffa ¤   ¤   return kPGPError_FeatureNotAvailable;
cdaf5a
a02e39 ¤   /* Hash too big for our array? */
0c8a19 ¤   PGPGetHashSize( hashContext, &hashSize );
a448cf ¤   if( hashSize > sizeof(hashData) )
fdc7a1 ¤   {
0b79d3 ¤   ¤   PGPFreeHashContext( hashContext );
b462b5 ¤   ¤   return kPGPError_BadParams;
b39371 ¤   }
c9af5a
e4ce78 ¤   hashVTBL = pgpHashGetVTBL( hashContext );
29ea30 ¤   PGPFinalizeHash( hashContext, hashData );
efaf5a
97fa6a ¤   randomContext = pgpContextGetX9_17RandomContext( ref->context );
53af5a
7abdd4 ¤   /* Do the signature */
93477c ¤   err = pgpSecKeySign( ref->signkey, hashVTBL, hashData,
549eb4 ¤   ¤   ¤   ¤   ¤   ¤   ·(PGPByte *) signature, &lSignatureSize,
3f6f35 ¤   ¤   ¤   ¤   ¤   ¤   ··randomContext, ref->format );
83af5a
10779f ¤   PGPFreeHashContext( hashContext );
d8af5a
8f7cc3 ¤   if( IsntPGPError( err ) ·&& IsntNull( signatureSize ) )
65c7a1 ¤   {
6ba605 ¤   ¤   *signatureSize = lSignatureSize;
--de65 000e20ef9554010021e Page 10 of pgpPublicKey.c
a19371 ¤   }
93af5a
9bdeb7 ¤   return( err );
39efe6 }
9baf5a
1eaf5a
300335 /*____________________________________________________________________________
57f7f7 ____________________________________________________________________________*/
4ac744 ¤   PGPError
3f8387 PGPPrivateKeySignRaw(
f79c48 ¤   PGPPrivateKeyContextRef¤¤   ref,
18fa35 ¤   const void *¤   ¤   ¤   ¤   signedData,
0a3d3e ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   signedDataSize,
f1ab7b ¤   const void *¤   ¤   ¤   ¤   signature,
c91948 ¤   PGPSize *¤  ¤   ¤   ¤   ¤   signatureSize)
66bb36 {
8971f6 ¤   PGPRandomContext *¤ ¤   ¤   randomContext;
0a0bef ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   lSignatureSize;
6da04b ¤   PGPHashVTBL¤¤   ¤   ¤   ¤   dummyVTBL;
179981 ¤   PGPError¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
5267c5 ¤
10adf2 ¤   if( IsntNull( signatureSize ) )
eac7a1 ¤   {
6ca50b ¤   ¤   PGPValidatePtr( signatureSize );
e2abd4 ¤   ¤   *signatureSize = 0;
af9371 ¤   }
a715ba ¤   PGPValidatePrivateKey( ref );
36093b ¤   PGPValidatePtr( signedData );
f5b4f6 ¤   PGPValidateParam( signedDataSize != 0 );
5d6b14 ¤   /* Raw mode supported only for PKCS sigs */
986407 ¤   if( ref->format != ¤kPGPPublicKeyMessageFormat_PKCS1 ) {
8c62b5 ¤   ¤   return kPGPError_BadParams;
479371 ¤   }
6dbf61 ¤   PGPValidatePtr( signature );
73af5a
12fabf ¤   if( IsNull( ref->signkey ) )
7fdffa ¤   ¤   return kPGPError_FeatureNotAvailable;
0baf5a
0afa6a ¤   randomContext = pgpContextGetX9_17RandomContext( ref->context );
87af5a
f5ee68 ¤   /* Set up value for hash size used by signature function */
ffa7cf ¤   pgpClearMemory( &dummyVTBL, sizeof(dummyVTBL) );
77bb12 ¤   dummyVTBL.hashsize = signedDataSize;
dcaf5a
a0bdd4 ¤   /* Do the signature */
ee8993 ¤   err = pgpSecKeySign( ref->signkey, &dummyVTBL,
a8856c ¤   ¤   ¤   ¤   ¤   ¤   ·(const PGPByte *) signedData,
aa9eb4 ¤   ¤   ¤   ¤   ¤   ¤   ·(PGPByte *) signature, &lSignatureSize,
2d6f35 ¤   ¤   ¤   ¤   ¤   ¤   ··randomContext, ref->format );
dbaf5a
607cc3 ¤   if( IsntPGPError( err ) ·&& IsntNull( signatureSize ) )
17c7a1 ¤   {
90a605 ¤   ¤   *signatureSize = lSignatureSize;
f19371 ¤   }
07af5a
0adeb7 ¤   return( err );
40efe6 }
78af5a
84af5a
480335 /*____________________________________________________________________________
eec84e If we have an encrypt-only or sign only key, we return zeros for the
65d666 one(s) which we don't support.
eaf7f7 ____________________________________________________________________________*/
d7c744 ¤   PGPError
e65c85 PGPGetPrivateKeyOperationSizes(
61519b ¤   PGPPrivateKeyContextRef¤ref,
782367 ¤   PGPSize *¤  ¤   ¤   ¤   maxDecryptedBufferSize,
a4b736 ¤   PGPSize *¤  ¤   ¤   ¤   maxEncryptedBufferSize,
c29a15 ¤   PGPSize *¤  ¤   ¤   ¤   maxSignatureSize )
2fbb36 {
8c15ba ¤   PGPValidatePrivateKey( ref );
e21e5d ¤   if( IsntNull( maxDecryptedBufferSize ) )
--3900 000d711f4b64010021e Page 11 of pgpPublicKey.c
25017f ¤   ¤   PGPValidatePtr( maxDecryptedBufferSize );
c6b95f ¤   if( IsntNull( maxEncryptedBufferSize ) )
a319fd ¤   ¤   PGPValidatePtr( maxEncryptedBufferSize );
4ebb7c ¤   if( IsntNull( maxSignatureSize ) )
9f060a ¤   ¤   PGPValidatePtr( maxSignatureSize );
8767c5 ¤
2fb95f ¤   if( IsntNull( maxEncryptedBufferSize ) )
98c7a1 ¤   {
064a3c ¤   ¤   if( IsntNull( ref->enckey ) ) {
0fda54 ¤   ¤   ¤   *maxEncryptedBufferSize = pgpSecKeyMaxesk( ref->enckey,
7fc55f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···ref->format );
ae45a6 ¤   ¤   } else {
55b448 ¤   ¤   ¤   *maxEncryptedBufferSize = 0;
5d0fe4 ¤   ¤   }
899371 ¤   }
a7af5a
131e5d ¤   if( IsntNull( maxDecryptedBufferSize ) )
47c7a1 ¤   {
7493e8 ¤   ¤   if( IsntNull( ref->enckey ) )
6912ca ¤   ¤   ¤   *maxDecryptedBufferSize = pgpSecKeyMaxdecrypted( ref->enckey,
f0068d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·ref->format );
db0e1d ¤   ¤   else
7697fd ¤   ¤   ¤   *maxDecryptedBufferSize = 0;
d29371 ¤   }
64af5a
9dbb7c ¤   if( IsntNull( maxSignatureSize ) )
6ac7a1 ¤   {
22d8f6 ¤   ¤   if( IsntNull( ref->signkey ) )
7f28ba ¤   ¤   ¤   *maxSignatureSize = pgpSecKeyMaxsig( ref->signkey, ref->format );
760e1d ¤   ¤   else
7f8546 ¤   ¤   ¤   *maxSignatureSize = 0;
1a9371 ¤   }
85151e ¤   return kPGPError_NoErr;
a2efe6 }
37af5a
bcaf5a
6faf5a
c30335 /*____________________________________________________________________________
82dc55 Given the size of a prime modulus in bits, this returns an appropriate
dec9a2 size for an exponent in bits, such that the work factor to find a
875dcd discrete log modulo the modulus is approximately equal to half the
1f7f2d length of the exponent. ·This makes the exponent an appropriate size
fcd396 for a subgroup in a discrete log signature scheme. ·For encryption
d2eb5a schemes, where decryption attacks can be stealthy and undetected, we
cac567 use 3/2 times the returned exponent size.
4ff7f7 ____________________________________________________________________________*/
5eaf5a
58c744 ¤   PGPError
057908 PGPDiscreteLogExponentBits(
881b10 ¤   PGPUInt32¤  ¤   ¤   ¤   modulusBits,
9bc28d ¤   PGPUInt32¤  ¤   ¤   ···*exponentBits )
19bb36 {
4d8687 ¤   PGPValidatePtr( exponentBits );
69af5a
d54e3b ¤   *exponentBits = pgpDiscreteLogExponentBits( modulusBits );
8caf5a
af151e ¤   return kPGPError_NoErr;
65efe6 }
b5af5a
91af5a
75f66a #if PRAGMA_MARK_SUPPORTED
1265af #pragma mark --- Internal Routines ---
b17454 #endif
46af5a
83af5a
02af5a
15af5a
06af5a
6faf5a
6d0335 /*____________________________________________________________________________
1ff7f7 ____________________________________________________________________________*/
d7c744 ¤   PGPError
--f03f 000d6c9c4da4010021e Page 12 of pgpPublicKey.c
05d0bb sSetupPubkey( PGPPublicKeyContextRef ref )
37bb36 {
46f19f ¤   RingObject *¤   ¤   ringKey;
2f76b0 ¤   RingSet const *¤¤   ringSet;
e67d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
bbaf5a
0b4e7e ¤   if( IsPGPError( err = pgpGetKeyRingObject( ref->key, FALSE, &ringKey ) ) )
3197ed ¤   ¤   goto error;
8d0fdf ¤   if( IsPGPError( err = pgpGetKeyRingSet( ref->key, FALSE, &ringSet ) ) )
da97ed ¤   ¤   goto error;
4a67c5 ¤
554aa1 ¤   ref->enckey = ringKeyPubKey( (RingSet *)ringSet, ringKey,
553d5e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGP_PKUSE_ENCRYPT );
762753 ¤   ref->signkey = ringKeyPubKey( (RingSet *)ringSet, ringKey,
e224dc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGP_PKUSE_SIGN );
2767c5 ¤
b60df7 ¤   if( IsNull( ref->enckey ) ·&& IsNull( ref->signkey ) ) {
3682df ¤   ¤   err = ringSetError( ringSet ) -> error;
aa97ed ¤   ¤   goto error;
839371 ¤   }
9aaf5a
6060ff error:
71af5a
0b5ea8 ¤   return err;
c1efe6 }
38af5a
6c0335 /*____________________________________________________________________________
32f7f7 ____________________________________________________________________________*/
47c744 ¤   PGPError
7b4631 sSetupPrivkey( PGPPrivateKeyContextRef ref, char const *passphrase,
487752 ¤   PGPSize passphraseLength, PGPBoolean hashedPhrase )
55bb36 {
a4f19f ¤   RingObject *¤   ¤   ringKey;
c976b0 ¤   RingSet const *¤¤   ringSet;
f8515f ¤   PGPInt32¤   ¤   ¤   rslt;
e4b4c5 ¤   PGPEnv *¤   ¤   ¤   env;
cf7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
95af5a
d04e7e ¤   if( IsPGPError( err = pgpGetKeyRingObject( ref->key, FALSE, &ringKey ) ) )
ef97ed ¤   ¤   goto error;
6a0fdf ¤   if( IsPGPError( err = pgpGetKeyRingSet( ref->key, FALSE, &ringSet ) ) )
b097ed ¤   ¤   goto error;
ab67c5 ¤
7b58fc ¤   ref->enckey = ringSecSecKey( (RingSet *)ringSet, ringKey,
8b3d5e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGP_PKUSE_ENCRYPT );
f1350e ¤   ref->signkey = ringSecSecKey( (RingSet *)ringSet, ringKey,
e624dc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGP_PKUSE_SIGN );
1b67c5 ¤
140df7 ¤   if( IsNull( ref->enckey ) ·&& IsNull( ref->signkey ) ) {
2782df ¤   ¤   err = ringSetError( ringSet ) -> error;
5497ed ¤   ¤   goto error;
a49371 ¤   }
23af5a
9fa0d8 ¤   env = pgpContextGetEnvironment( ref->context );
81af5a
747c9b ¤   if( IsntNull( ref->enckey ) )
cbc7a1 ¤   {
6dba43 ¤   ¤   rslt = pgpSecKeyUnlock( ref->enckey, env, passphrase,
101fa6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passphraseLength, hashedPhrase );
56910b ¤   ¤   if( rslt != 1 )
e05b34 ¤   ¤   {
8d6d9b ¤   ¤   ¤   pgpSecKeyDestroy( ref->enckey );
41d6ba ¤   ¤   ¤   if( IsntNull( ref->signkey ) )
bbf776 ¤   ¤   ¤   {
889547 ¤   ¤   ¤   ¤   pgpSecKeyDestroy( ref->signkey );
d5a3a6 ¤   ¤   ¤   }
31df00 ¤   ¤   ¤   err = kPGPError_BadPassphrase;
57ed19 ¤   ¤   ¤   goto error;
d60fe4 ¤   ¤   }
ee9371 ¤   }
66af5a
d69905 ¤   if( IsntNull( ref->signkey ) )
--6967 001bd154fa54010021e Page 13 of pgpPublicKey.c
f7c7a1 ¤   {
7a5abb ¤   ¤   rslt = pgpSecKeyUnlock( ref->signkey, env, passphrase,
653b01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passphraseLength, FALSE );
32910b ¤   ¤   if( rslt != 1 )
6d5b34 ¤   ¤   {
e9da79 ¤   ¤   ¤   pgpSecKeyDestroy( ref->signkey );
67af06 ¤   ¤   ¤   if( IsntNull( ref->enckey ) )
90f776 ¤   ¤   ¤   {
a53f06 ¤   ¤   ¤   ¤   pgpSecKeyDestroy( ref->enckey );
aaa3a6 ¤   ¤   ¤   }
22df00 ¤   ¤   ¤   err = kPGPError_BadPassphrase;
37ed19 ¤   ¤   ¤   goto error;
c40fe4 ¤   ¤   }
549371 ¤   }
faaf5a
8160ff error:
9faf5a
a35ea8 ¤   return err;
5eefe6 }
f1af5a
50af5a
23af5a
91af5a
967e4d /*__Editor_settings____
cdaf5a
824126 ¤   Local Variables:
917b17 ¤   tab-width: 4
3d0e6c ¤   End:
515f8c ¤   vi: ts=4 sw=4
929e9b ¤   vim: si
bdd062 _____________________*/
--9cf3 0003d810e944010021f Page 1 of pgpRSAGlue.c
bc38e5 /*
7027d7 ·* pgpRSAGlue.c - The interface between bignum math and RSA operations.
bdfbda ·* This layer's primary reason for existence is to allow adaptation
307399 ·* to other RSA math libraries for legal reasons.
ae775e ·*
be68c2 ·* Written by Colin Plumb.
9c775e ·*
fe8dc8 ·* $Id: pgpRSAGlue.c,v 1.16.2.1 1998/10/08 00:18:44 heller Exp $
b9495d ·*/
d4af5a
433051 #include "pgpSDKBuildFlags.h"
c3af5a
48be7a #ifndef PGP_RSA
ae31da #error "PGP_RSA requires a value"
5e7454 #endif
a6af5a
9bd376 /* This entire module is dependent on RSA being enabled */
9a99a4 #if PGP_RSA
8aaf5a
e0e2ff #include "pgpConfig.h"
f3324c #include <string.h>
42af5a
33d83c ·
6738e5 /*
b9c09c ·* An alternative version of this module is used if RSAREF is needed. ·This
190e45 ·* entire source file is under the control of the following conditional:
94495d ·*/
44ff4b #if PGP_USEPGPFORRSA¤   /* [ */
cbaf5a
92af5a
328c41 #include "pgpRSAGlue.h"
d9007f #include "pgpKeyMisc.h"
b339fc #include "bn.h"
962f8d #include "pgpErrors.h"
d92c96 #include "pgpRandomX9_17.h"
1cd11f #include "pgpUsuals.h"
94af5a
5538e5 /*
619bc9 ·* This is handy for debugging, but VERY VERY DANGEROUS for production -
cf7795 ·* it nicely prints every detail of your secret key!
cd495d ·*/
767e00 #define BNDEBUG 0
38af5a
0d63d6 #if BNDEBUG
b96e87 /* Some debugging hooks which have been left in for now. */
23a1b3 #include "bnprint.h"
287b1d #define bndPut(prompt, bn) (fputs(prompt, stdout), bnPrint(stdout, bn), \
f72264 ¤   ¤   ¤   ¤   putchar('\n'))
541d7c #define bndPrintf printf
5fdb21 #else
5625fd #define bndPut(prompt, bn) ((void)(prompt),(void)(bn))
a8811f #if __GNUC__ > 1
a25bb0 /* Non-ANSI, but supresses warnings about expressions with no effect */
8783a9 #define bndPrintf(arg...) (void)0
4adb21 #else
713f9c /* ANSI-compliant - cast entire comma expression to void */
6a8d71 #define bndPrintf (void)
177454 #endif
167454 #endif
feaf5a
3aaf5a
1538e5 /*
3961e9 ·* If you're using a legally encumbered library (ugh!) this will be
ddd924 ·* printed in the program banner.
07495d ·*/
7976e4 char const banner_legalese[] = "";
1c38e5 /*
8e36ba ·* This returns TRUE if the key is too big, returning the
ddaecf ·* maximum number of bits that the library can accept.
86095c ·* The limit is currently set for pragmatic reasons.
f8495d ·*/
3dbba1 #define MAXSIZE 4096
--f667 000defe3c414010021f Page 2 of pgpRSAGlue.c
af4d2f int
424a31 rsaKeyTooBig(RSApub const *pub, RSAsec const *sec)
4abb36 {
2667ab ¤   if (pub) {
aa6b85 ¤   ¤   if (bnBits(&pub->n) > MAXSIZE)
548cd7 ¤   ¤   ¤   return MAXSIZE;
159371 ¤   }
dc8631 ¤   if (sec) {
2430cf ¤   ¤   if (bnBits(&sec->n) > MAXSIZE)
a78cd7 ¤   ¤   ¤   return MAXSIZE;
a69371 ¤   }
b12354 ¤   return 0; /* OK */
73efe6 }
61af5a
83af5a
704d2f int
24ab93 rsaPublicEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
c5e64b ¤   RSApub const *pub, PGPRandomContext const *rc)
21bb36 {
33ca77 ¤   unsigned bytes = (bnBits(&pub->n)+7)/8;
b7be92 ¤   pgpPKCSPack(bn, in, len, PKCS_PAD_ENCRYPTED, bytes, rc);
81af5a
29d515 bndPrintf("RSA encrypting.\n");
d50270 bndPut("plaintext = ", bn);
638db5 ¤   return bnExpMod(bn, bn, &pub->e, &pub->n);
24efe6 }
32af5a
9faf5a
cf38e5 /*
1d8a46 ·* This performs a modular exponentiation using the Chinese Remainder
f95a5b ·* Algorithm when the modulus is known to have two relatively prime
566d70 ·* factors n = p * q, and u = p^-1 (mod q) has been precomputed.
c8775e ·*
2d7b32 ·* The chinese remainder algorithm lets a computation mod n be performed
b98d79 ·* mod p and mod q, and the results combined. ·Since it takes
361d04 ·* (considerably) more than twice as long to perform modular exponentiation
b30e53 ·* mod n as it does to perform it mod p and mod q, time is saved.
e8775e ·*
a58253 ·* If x is the desired result, let xp and xq be the values of x mod p
a9e2c4 ·* and mod q, respectively. ·Obviously, x = xp + p * k for some k.
02e427 ·* Taking this mod q, xq == xp + p*k (mod q), so p*k == xq-xp (mod q)
43aab2 ·* and k == p^-1 * (xq-xp) (mod q), so k = u * (xq-xp mod q) mod q.
f9837c ·* After that, x = xp + p * k.
c2775e ·*
42226c ·* Another savings comes from reducing the exponent d modulo phi(p)
210000 ·* and phi(q). ·Here, we assume that p and q are prime, so phi(p) = p-1
e5e17c ·* and phi(q) = q-1.
2b495d ·*/
3fbeb7 static int
3f8034 bnExpModCRA(BigNum *x, BigNum const *d,
dbe699 ¤   BigNum const *p, BigNum const *q, BigNum const *u)
3abb36 {
f54bab ¤   BigNum xp, xq, k;
754ba4 ¤   int i;
2207bf ¤   PGPMemoryMgrRef¤mgr¤= x->mgr;
99af5a
b7ffef bndPrintf("Performing Chinese Remainder Algorithm\n");
607785 bndPut("x = ", x);
dd2ef7 bndPut("p = ", p);
7b67dd bndPut("q = ", q);
0cb0aa bndPut("d = ", d);
1f4b64 bndPut("u = ", u);
2aaf5a
ee435f ¤   bnBegin(&xp, mgr, TRUE);
250b75 ¤   bnBegin(&xq, mgr, TRUE);
c95589 ¤   bnBegin(&k, mgr, TRUE);
07af5a
4e5049 ¤   /* Compute xp = (x mod p) ^ (d mod p-1) mod p */
7e9d27 ¤   if (bnCopy(&xp, p) < 0)¤¤   /* First, use xp to hold p-1 */
cc84fc ¤   ¤   goto fail;
70e4b2 ¤   (void)bnSubQ(&xp, 1);¤  ¤   /* p > 1, so subtracting is safe. */
ded3bb ¤   if (bnMod(&k, d, &xp) < 0)¤ /* k = d mod (p-1) */
--ca18 00049b1fa794010021f Page 3 of pgpRSAGlue.c
8884fc ¤   ¤   goto fail;
79f07b bndPut("d mod p-1 = ", &k);
afd4a7 ¤   if (bnMod(&xp, x, p) < 0)¤  /* Now xp = (x mod p) */
d884fc ¤   ¤   goto fail;
48f7fe bndPut("x mod p = ", &xp);
a5fbd9 ¤   if (bnExpMod(&xp, &xp, &k, p) < 0)¤ /* xp = (x mod p)^k mod p */
5884fc ¤   ¤   goto fail;
df1165 bndPut("xp = x^d mod p = ", &xp);
92af5a
ca52e8 ¤   /* Compute xq = (x mod q) ^ (d mod q-1) mod q */
bb9405 ¤   if (bnCopy(&xq, q) < 0)¤¤   /* First, use xq to hold q-1 */
7184fc ¤   ¤   goto fail;
d1213a ¤   (void)bnSubQ(&xq, 1);¤  ¤   /* q > 1, so subtracting is safe. */
c39730 ¤   if (bnMod(&k, d, &xq) < 0)¤ /* k = d mod (q-1) */
9884fc ¤   ¤   goto fail;
d68e91 bndPut("d mod q-1 = ", &k);
a7536d ¤   if (bnMod(&xq, x, q) < 0)¤  /* Now xq = (x mod q) */
0084fc ¤   ¤   goto fail;
c8eee8 bndPut("x mod q = ", &xq);
8182aa ¤   if (bnExpMod(&xq, &xq, &k, q) < 0)¤ /* xq = (x mod q)^k mod q */
a084fc ¤   ¤   goto fail;
f10c08 bndPut("xq = x^d mod q = ", &xq);
deaf5a
7a6e31 ¤   /* xp < p and PGP has p < q, so this is a no-op, but just in case */
8dc00a ¤   if (bnMod(&k, &xp, q) < 0)
fca7d2 ¤   ¤   goto fail;¤
ff1724 bndPut("xp mod q = ", &k);
5667c5 ¤
c688fc ¤   i = bnSub(&xq, &k);
829f0e bndPut("xq - xp = ", &xq);
9b05d4 bndPrintf("With sign %d\n", i);
2b4fd6 ¤   if (i < 0)
1b84fc ¤   ¤   goto fail;
3b14b5 ¤   if (i) {
181b17 ¤   ¤   /*
4b571a ¤   ¤   ·* Borrow out - xq-xp is negative, so bnSub returned
122ba2 ¤   ¤   ·* xp-xq instead, the negative of the true answer.
3743f6 ¤   ¤   ·* Add q back (which is subtracting from the negative)
88d609 ¤   ¤   ·* so the sign flips again.
8c9de3 ¤   ¤   ·*/
a5c175 ¤   ¤   i = bnSub(&xq, q);
e9ad75 ¤   ¤   if (i < 0)
dabf15 ¤   ¤   ¤   goto fail;
cb4dad bndPut("xq - xp mod q = ", &xq);
d26247 bndPrintf("With sign %d\n", i);¤¤   /* Must be 1 */
b49371 ¤   }
65af5a
efd215 ¤   /* Compute k = xq * u mod q */
980072 ¤   if (bnMul(&k, u, &xq) < 0)
1f84fc ¤   ¤   goto fail;
6e0901 bndPut("(xq-xp) * u = ", &k);
91d6ef ¤   if (bnMod(&k, &k, q) < 0)
0a84fc ¤   ¤   goto fail;
79d7e4 bndPut("k = (xq-xp)*u % q = ", &k);
07af5a
357d37 ¤   /* Now x = k * p + xp is the final answer */
6396fe ¤   if (bnMul(x, &k, p) < 0)
7c84fc ¤   ¤   goto fail;
c3817b bndPut("k * p = ", x);
4473f5 ¤   if (bnAdd(x, &xp) < 0)
8884fc ¤   ¤   goto fail;
30ea47 bndPut("k*p + xp = ", x);
43af5a
98e7ce #if BNDEBUG¤/* @@@ DEBUG - do it the slow way for comparison */
d84379 ¤   if (bnMul(&xq, p, q) < 0)
3a84fc ¤   ¤   goto fail;
e7266e bndPut("n = p*q = ", &xq);
3c1c7f ¤   if (bnExpMod(&xp, x, d, &xq) < 0)
a684fc ¤   ¤   goto fail;
b247c5 bndPut("x^d mod n = ", &xp);
f232d9 ¤   if (bnCmp(x, &xp) != 0) {
49471e bndPrintf("Nasty!!!\n");
--de9e 00049cd43214010021f Page 4 of pgpRSAGlue.c
8884fc ¤   ¤   goto fail;
599371 ¤   }
5b24e9 ¤   bnSetQ(&k, 17);
d64c4a ¤   bnExpMod(&xp, &xp, &k, &xq);
9d5ca8 bndPut("x^17 mod n = ", &xp);
467454 #endif
faaf5a
12970f ¤   bnEnd(&xp);
e38bb4 ¤   bnEnd(&xq);
cbe113 ¤   bnEnd(&k);
ce3e6b ¤   return 0;
b3af5a
b7115d fail:
79970f ¤   bnEnd(&xp);
768bb4 ¤   bnEnd(&xq);
92e113 ¤   bnEnd(&k);
4baf43 ¤   return kPGPError_OutOfMemory;
72efe6 }
21af5a
1438e5 /*
20d292 ·* This does an RSA signing operation, which is very similar, except
ed3a62 ·* that the padding differs. ·The type is 1, and the padding is all 1's
b784e0 ·* (hex 0xFF). ·In addition, if the data is a DER-padded MD5 hash, there's
8600d7 ·* an option for encoding it with the old PGP 2.2 format, in which case
60dd55 ·* that's all replaced by a 1 byte indicating MD5.
8a775e ·*
ccccb6 ·* When decrypting, distinguishing these is a bit trickier, since the
43097f ·* second most significant byte is 1 in both cases, but in general,
b1cd97 ·* it could only cause confusion if the PGP hash were all 1's.
5d775e ·*
0d95b6 ·* To summarize, the formats are:
e7775e ·*
cebc89 ·* Position ····Value ··Function
967444 ·* n-1 ··········0 ·····This is needed to ensure that the padded number
cf3c59 ·* ·····················is less than the modulus.
c512fd ·* n-2 ··········1 ·····The padding type (all ones).
cb6014 ·* n-3..len+1 ··255 ····All ones padding to ensure signatures are rare.
1520ea ·* len ··········0 ·····Zero byte to mark the end of the padding
7d3a50 ·* len-1..x ····ASN.1¤  The ASN.1 DER magic cookie (18 bytes)
5f38d8 ·* x-1..0 ······data ···The payload MD5 hash (16 bytes).
50775e ·*
b6775e ·*
a73cdf ·* Position ····Value
1a21d3 ·* n-1 ··········0
42a982 ·* n-2 ··········1¤ "This is MD5"
236738 ·* n-2..n-len-2 data ···Supplied payload MD5 hash (len == 16).
ba7cbf ·* n-len-2 ······0 ·····Zero byte to mark the end of the padding
d64a94 ·* n-len-3..1 ··255 ····All ones padding.
ec639e ·* 0 ············1 ·····The padding type (all ones).
d5775e ·*
66775e ·*
de8d13 ·* The reason for the all 1's padding is an extra consistency check.
63d40a ·* A randomly invented signature will not decrypt to have the long
4f862f ·* run of ones necessary for acceptance.
e9775e ·*
d0c57f ·* Oh... the public key isn't needed to decrypt, but it's passed in
68ae49 ·* because a different glue library may need it for some reason.
82775e ·*
241fc2 ·* TODO: Have the caller put on the PKCS wrapper. ·We can notice and
4e65c3 ·* strip it off if we're trying to be compatible.
ec495d ·*/
01d313 static const PGPByte signedType = 1;
bbaf5a
954d2f int
ddb4a4 rsaPrivateEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
2284e6 ¤   RSAsec const *sec)
c3bb36 {
6596cc ¤   unsigned bytes = (bnBits(&sec->n)+7)/8;
9faf5a
6d9a62 ¤   pgpPKCSPack(bn, in, len, PKCS_PAD_SIGNED, bytes,
a4968c ¤   ¤   (PGPRandomContext const *)NULL);
49af5a
--067d 001ab86a2f44010021f Page 5 of pgpRSAGlue.c
f00ab8 bndPrintf("RSA signing.\n");
3e0270 bndPut("plaintext = ", bn);
2a418a ¤   return bnExpModCRA(bn, &sec->d, &sec->p, &sec->q, &sec->u);
d2efe6 }
2caf5a
1038e5 /*
eaf40f ·* Decrypt a message with a public key.
f631cb ·* These destroy (actually, replace with a decrypted version) the
c53a47 ·* input bignum bn.
b6775e ·*
77553b ·* It recongizes the PGP 2.2 format, but not in all its generality;
37f6d9 ·* only the one case (framing byte = 1, length = 16) which was ever
4d52b7 ·* generated. ·It fakes the DER prefix in that case.
ff775e ·*
66f594 ·* Performs an RSA signature check. ·Returns a prefix of the unwrapped
d6140d ·* data in the given buf. ·Returns the length of the untruncated
1e5d6b ·* data, which may exceed "len". Returns <0 on error.
7d495d ·*/
834d2f int
2109ce rsaPublicDecrypt(PGPByte *buf, unsigned len, BigNum *bn,
f44678 ¤   RSApub const *pub)
edbb36 {
9570a3 ¤   unsigned bytes;
0faf5a
2c0b5c bndPrintf("RSA signature checking.\n");
c19788 ¤   if (bnExpMod(bn, bn, &pub->e, &pub->n) < 0)
f74030 ¤   ¤   return kPGPError_OutOfMemory;
b27082 bndPut("decrypted = ", bn);
4ea165 ¤   bytes = (bnBits(&pub->n)+7)/8;
7c0aee ¤   return pgpPKCSUnpack(buf, len, bn, PKCS_PAD_SIGNED, bytes);
a0efe6 }
f8af5a
8eaf5a
ea38e5 /*
5b9e39 ·* Performs an RSA decryption. ·Returns a prefix of the unwrapped
31140d ·* data in the given buf. ·Returns the length of the untruncated
2e5d6b ·* data, which may exceed "len". Returns <0 on error.
cb495d ·*/
4f4d2f int
f43435 rsaPrivateDecrypt(PGPByte *buf, unsigned len, BigNum *bn,
e784e6 ¤   RSAsec const *sec)
62bb36 {
e270a3 ¤   unsigned bytes;
0caf5a
a5a6f5 bndPrintf("RSA decrypting\n");
fa287a ¤   if (bnExpModCRA(bn, &sec->d, &sec->p, &sec->q, &sec->u) < 0)
414030 ¤   ¤   return kPGPError_OutOfMemory;
7e7082 bndPut("decrypted = ", bn);
e2fdde ¤   bytes = (bnBits(&sec->n)+7)/8;
d2d02b ¤   return pgpPKCSUnpack(buf, len, bn, PKCS_PAD_ENCRYPTED, bytes);
7fefe6 }
5daf5a
d349fc #endif /* ] PGP_USEPGPFORRSA */
85af5a
ab92cd #endif¤ /* PGP_RSA */
--8545 000a27a525340100220 Page 1 of pgpRSAGlue.h
8695d7 /*·
602f00 ·* pgpRSAGlue.h - RSA encryption and decryption
16775e ·*
47e39d ·* This is a PRIVATE header file, for use only within the PGP Library.
8c2979 ·* You should not be using these functions in an application.
3c775e ·*
9a5ea1 ·* $Id: pgpRSAGlue.h,v 1.10 1998/07/10 04:05:56 hal Exp $
f5495d ·*/
29d1ea #ifndef Included_pgpRSAGlue_h
6585de #define Included_pgpRSAGlue_h
adaf5a
afaf5a
8d3051 #include "pgpSDKBuildFlags.h"
31af5a
88be7a #ifndef PGP_RSA
5231da #error "PGP_RSA requires a value"
7e7454 #endif
72af5a
3e99a4 #if PGP_RSA
e9af5a
43af5a
ce39fc #include "bn.h"
fed11f #include "pgpUsuals.h"
8cadb8 #include "pgpOpaqueStructs.h"
dbaf5a
9699c6 PGP_BEGIN_C_DECLARATIONS
7eaf5a
8f15c5 /* A structure to hold a public key */
d74f00 typedef struct RSApub
93bb36 {
934abb ¤   BigNum n;¤  /* The public modulus */
be71c5 ¤   BigNum e;¤  /* The public exponent */
65a8ce } RSApub;
70af5a
21be25 /* A structure to hold a secret key */
f3f680 typedef struct RSAsec
c1bb36 {
9f11a8 ¤   BigNum n;¤  /* Copy of public parameters */
57ca80 ¤   BigNum e;
efd680 ¤   BigNum d;¤  /* Decryption exponent */
03e2e4 ¤   BigNum p;¤  /* The smaller factor of n */
a9068b ¤   BigNum q;¤  /* The larger factor of n */
50abc9 ¤   BigNum u;¤  /* 1/p (mod q) */
d5274f } RSAsec ;
bdaf5a
ef5897 /* Declarations */
5cb3af int rsaKeyTooBig(RSApub const *pub, RSAsec const *sec);
92af5a
1621e2 /* Encrypt */
e21886 int rsaPublicEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
d3d8a8 ·····················RSApub const *pub,
aad77d ¤   ¤   ·····PGPRandomContext const *rc);
366e10 /* Sign */
c8f33b int rsaPrivateEncrypt(BigNum *bn, PGPByte const *in, unsigned len,
d25d98 ······················RSAsec const *sec);
e4049a /* Verify */
44e347 int rsaPublicDecrypt(PGPByte *buf, unsigned len, BigNum *bn,
a71007 ·····················RSApub const *pub);
7e6933 /* Decrypt */
292d16 int rsaPrivateDecrypt(PGPByte *buf, unsigned len, BigNum *bn,
3a5d98 ······················RSAsec const *sec);
7caf5a
ae2ada /* Slightly higher level functions for CAPI */
c5f847 #if PGP_USECAPIFORRSA
4a7750 PGPBoolean
521939 rsaVerifyHashSignature(BigNum *bn, RSApub const *pub, PGPHashVTBL const *h,
1dcf27 ¤   PGPByte const *hash);
e9af5a
fb4d2f int
6b3dab rsaSignHash(BigNum *bn, RSAsec const *sec, PGPHashVTBL const *h,
1dcf27 ¤   PGPByte const *hash);
a2af5a
--7219 001aac63bff40100220 Page 2 of pgpRSAGlue.h
6a1bad #endif /* PGP_USECAPIFORRSA */
edaf5a
90af5a
701254 PGP_END_C_DECLARATIONS
7faf5a
a77ead #endif /* PGP_RSA */
c2af5a
aa523c #endif /* !Included_pgpRSAGlue_h */
--a4ba 000252dfaea40100221 Page 1 of pgpRSAKey.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
69193d ¤   $Id: pgpRSAKey.c,v 1.55.2.2.2.1 1998/11/12 03:22:12 heller Exp $
fcf7f7 ____________________________________________________________________________*/
75af5a
fc3051 #include "pgpSDKBuildFlags.h"
4eaf5a
aebe7a #ifndef PGP_RSA
4031da #error "PGP_RSA requires a value"
f07454 #endif
15af5a
fa2486 #ifndef PGP_RSA_KEYGEN
6aadd9 #error "PGP_RSA_KEYGEN requires a value"
c67454 #endif
82af5a
03d376 /* This entire module is dependent on RSA being enabled */
6299a4 #if PGP_RSA
b8af5a
64e2ff #include "pgpConfig.h"
95324c #include <string.h>
bc7cab #include <stddef.h>
86af5a
92a146 #include "pgpDebug.h"
b6007f #include "pgpKeyMisc.h"
d58c41 #include "pgpRSAGlue.h"
2afa8a #include "pgpRSAKey.h"
c439fc #include "bn.h"
631e2d #include "pgpCFBPriv.h"
120e2f #include "pgpSymmetricCipherPriv.h"
985417 #include "pgpHashPriv.h"
bf0d08 #include "pgpMem.h"
172f8d #include "pgpErrors.h"
5312ca #include "bnprime.h"
28cdc2 #include "pgpPubKey.h"
6e2c96 #include "pgpRandomX9_17.h"
835579 #include "pgpStr2Key.h"
4bc26c #include "pgpContext.h"
050d6d #include "pgpEnv.h"
7aaf5a
43af5a
7caf5a
0851ad #define RSA_DEFAULT_EXPONENT¤   17
76af5a
715606 #define ASSERTRSA(alg) pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSA || \
4c10ef ¤   ¤   ¤   ······(ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSAEncryptOnly || \
cbf8a5 ¤   ¤   ¤   ······(ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSASignOnly)
3bedb0 #define ASSERTRSASIG(alg) \
f6c9f3 ¤   pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSA || \
457384 ¤   ·(ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSASignOnly)
019292 #define ASSERTRSAENC(alg) \
1275ea ¤   ¤   pgpAssert((ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSA || \
9c64e2 ¤   ¤   (ALGMASK(alg))==kPGPPublicKeyAlgorithm_RSAEncryptOnly)
2eaf5a
92af5a
50fe92 /* A PGPSecKey's priv points to this, an RSAsec plus the encrypted form... */
13a225 /* This struct is always allocated using PGPNewSecureData */
998c0a typedef struct RSAsecPlus
acbb36 {
9b8a97 ¤   PGPContextRef¤  context;
3f67c5 ¤
a45dc1 ¤   RSAsec¤ ¤   ¤   s;
ae8746 ¤   PGPByte *¤  ¤   cryptkey;
235b30 ¤   size_t¤ ¤   ¤   ckalloc;
1a669e ¤   size_t¤ ¤   ¤   cklen;
d8ddf7 ¤   int¤¤   ¤   ¤   locked;
54f436 ¤   PGPBoolean¤ ¤   v3;¤/* True if key is in a pre PGPVERSION_4 packet */
b61e6c ¤   DEBUG_STRUCT_CONSTRUCTOR( RSAsecPlus )
259860 } RSAsecPlus ;
--c64b 00077096c7340100221 Page 2 of pgpRSAKey.c
e0af5a
15bfda /** Public key functions **/
50af5a
032978 static void
8625e2 rsaPubDestroy(PGPPubKey *pubkey)
e2bb36 {
3c3868 ¤   RSApub *pub = (RSApub *)pubkey->priv;
068a97 ¤   PGPContextRef¤  context;
e0af5a
a71511 ¤   pgpAssertAddrValid( pubkey, PGPPubKey );
138235 ¤   context¤= pubkey->context;
e3af5a
0c3538 ¤   ASSERTRSA(pubkey->pkAlg);
9b67c5 ¤
1d18f2 ¤   bnEnd(&pub->n);
a8d8e7 ¤   bnEnd(&pub->e);
550e47 ¤   pgpClearMemory( pub, ·sizeof(pub));
68fa7b ¤   pgpContextMemFree( context, pub);
515d33 ¤   pgpClearMemory( pubkey, ·sizeof(pubkey));
69e9a9 ¤   pgpContextMemFree(context, pubkey);
51efe6 }
83af5a
76a863 /* Return the largest possible PGPESK size for a given key */
505d09 static size_t
7c5b6d rsaPubMaxesk(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
0abb36 {
09e101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
c4af5a
d5da1b ¤   ASSERTRSAENC(pubkey->pkAlg);
0b9850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
3f3db9 ¤   ¤   return 2 + bnBytes(&pub->n);
1bf515 ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
092095 ¤   ¤   ¤   ·format == kPGPPublicKeyMessageFormat_X509)
f6ab55 ¤   ¤   return bnBytes(&pub->n);
05af5a
ae4aac ¤   pgpAssert(0);
873e6b ¤   return 0;
01efe6 }
21af5a
68b426 /* Return the largest possible input size for rsaEncrypt */
ca5d09 static size_t
98cf30 rsaPubMaxdecrypted(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
57bb36 {
c2e101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
baaf5a
95476e ¤   (void) format;
dbda1b ¤   ASSERTRSAENC(pubkey->pkAlg);
19af5a
540e39 ¤   /* Minimum padding could be just 0 2 0 */
7b8449 ¤   return bnBytes(&pub->n) - 3;
c5efe6 }
b7af5a
106d2e /* Return the largest possible signature input to rsaVerify */
8a5d09 static size_t
bf9745 rsaPubMaxsig(PGPPubKey const *pubkey, PGPPublicKeyMessageFormat format)
c5bb36 {
a2e101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
e2af5a
a88f13 ¤   ASSERTRSASIG(pubkey->pkAlg);
b1af5a
709850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
303db9 ¤   ¤   return 2 + bnBytes(&pub->n);
8961bb ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1)
28ab55 ¤   ¤   return bnBytes(&pub->n);
d6b92c ¤   else if (format == kPGPPublicKeyMessageFormat_X509)
573d28 ¤   ¤   /* BITSTRING, length bytes, 0, data */
8c0a98 ¤   ¤   return 1 + bnBytes(&pub->n) + 1 + pgpBnX509LenLen(bnBytes(&pub->n)+1);
f6af5a
9e4aac ¤   pgpAssert(0);
653e6b ¤   return 0;
0eefe6 }
77af5a
--d8f2 000fe8aeb8740100221 Page 3 of pgpRSAKey.c
e0af5a
d338e5 /*
341034 ·* Given a buffer of at least "maxesk" bytes, make an PGPESK
074d6c ·* into it and return the size of the PGPESK, or <0.
9e495d ·*/
29beb7 static int
f2953a rsaEncrypt(PGPPubKey const *pubkey, PGPByte const *key,
58e590 ···········size_t keylen, PGPByte *esk, size_t *esklen,
fd6387 ···········PGPRandomContext const *rc, PGPPublicKeyMessageFormat format)
adbb36 {
f8a247 #if PGP_ENCRYPT_DISABLE /* [ */
6eaf5a
9bf2e1 ¤   (void)pubkey;
b59b3e ¤   (void)key;
d3ede5 ¤   (void)keylen;
4f4290 ¤   (void)esk;
a77a0a ¤   (void)esklen;
6276a2 ¤   (void)rc;
101c0d ¤   (void)format;
7ae63f ¤   return kPGPError_FeatureNotAvailable;
0faf5a
96a6dd #else /* PGP_ENCRYPT_DISABLE */ ·/* ] ·[ */
4eaf5a
d4e101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
29699d ¤   BigNum bn;
e60ed5 ¤   unsigned t;
464ba4 ¤   int i;
b22955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
e3af5a
ce80d5 ¤   /* We don't need these arguments, although other algorithms may... */
e276a2 ¤   (void)rc;
61af5a
ba4578 ¤   mgr¤= PGPGetContextMemoryMgr( pubkey->context );
70af5a
fada1b ¤   ASSERTRSAENC(pubkey->pkAlg);
9dc93f ¤   t = bnBits(&pub->n);
cc3c57 ¤   if (t > 0xffff)
fc50d0 ¤   ¤   return kPGPError_PublicKeyTooLarge;
80487d ¤   if (keylen > t)
c1e75b ¤   ¤   return kPGPError_PublicKeyTooSmall; /* data too big for pubkey */
6baf5a
747905 ¤   if( format == kPGPPublicKeyMessageFormat_PGP ) {
c1d2d6 ¤   ¤   /* Add checksum to key, place temporarily in esk buffer */
8f0550 ¤   ¤   t = 0;
44544f ¤   ¤   esk[0] = key[0];
0b5ccb ¤   ¤   for (i = 1; i < (int)keylen; i++)
634738 ¤   ¤   ¤   t += esk[i] = key[i];
6a07b1 ¤   ¤   esk[keylen] = (PGPByte)(t >> 8 & 255);
bdaada ¤   ¤   esk[keylen+1] = (PGPByte)(t & 255);
6dcc35 ¤   ¤   keylen += 2;
93b142 ¤   ¤   key = esk;
249371 ¤   }
1daf5a
f7ed59 ¤   bnBegin(&bn, mgr, TRUE);
d73f90 ¤   i = rsaPublicEncrypt(&bn, key, keylen, pub, rc);
b87a6f ¤   if (i < 0) {
5e9577 ¤   ¤   bnEnd(&bn);
94a423 ¤   ¤   return i;
429371 ¤   }
8f67c5 ¤
6989a8 ¤   t = pgpBnPutFormatted(&bn, esk, bnBytes(&pub->n), format);
520204 ¤   bnEnd(&bn);
1eaf5a
ee2fa6 ¤   if (esklen)
056abf ¤   ¤   *esklen = (size_t)t;
bd3e6b ¤   return 0;
0baf5a
5d7bb3 #endif /* PGP_ENCRYPT_DISABLE */ /* ] */
32efe6 }
f7af5a
bcaf5a
fe38e5 /*
--8c98 0007703c3b040100221 Page 4 of pgpRSAKey.c
91503a ·* Return 1 if (sig,siglen) is a valid MPI which signs
9907b8 ·* hash, of type h. ·Check the DER-encoded prefix and the
f310ba ·* hash itself.
da495d ·*/
59beb7 static int
181192 rsaVerify(PGPPubKey const *pubkey, PGPByte const *sig,
5f414d ¤   size_t siglen, PGPHashVTBL const *h, PGPByte const *hash,
e26fc3 ¤   PGPPublicKeyMessageFormat format)
92bb36 {
53a0f7 #if PGP_VERIFY_DISABLE /* [ */
2baf5a
aef2e1 ¤   (void)pubkey;
7d77e4 ¤   (void)sig;
2751a9 ¤   (void)siglen;
84c6fd ¤   (void)h;
ec4902 ¤   (void)hash;
7f1c0d ¤   (void)format;
8ce63f ¤   return kPGPError_FeatureNotAvailable;
6caf5a
bc08c4 #else /* PGP_VERIFY_DISABLE */ ·/* ] ·[ */
b8af5a
72e101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
db699d ¤   BigNum bn;
e7d6ff ¤   PGPByte buf[64];¤   /* largest hash size + DER prefix */
444ba4 ¤   int i;
e253b6 ¤   size_t off = 0;
6d16d3 ¤   PGPMemoryMgrRef¤mgr¤= PGPGetContextMemoryMgr( pubkey->context );
f5af5a
8e8f13 ¤   ASSERTRSASIG(pubkey->pkAlg);
ecaf5a
eb54df ¤   bnBegin(&bn, mgr, FALSE);
877e57 ¤   if (format == kPGPPublicKeyMessageFormat_X509) {
85f015 ¤   ¤   /* Parse BITSTRING header for 509 sig data */
33b5c9 ¤   ¤   PGPByte const *sigp = sig + off;
3f6b31 ¤   ¤   PGPUInt32 len;
57ce40 ¤   ¤   if (pgpBnX509TagLen(&sigp, &len) != X509_TAG_BITSTRING) {
a772d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
b41dc4 ¤   ¤   ¤   goto done;
360fe4 ¤   ¤   }
58a54d ¤   ¤   /* BITSTRING should have 0 leftover bits */
e70ec4 ¤   ¤   if (*sigp++ != 0) {
bf72d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
f41dc4 ¤   ¤   ¤   goto done;
7a0fe4 ¤   ¤   }
08428c ¤   ¤   off += sigp - sig;
fe0d96 ¤   ¤   if (len - 1 != siglen - off) {
ac72d3 ¤   ¤   ¤   i = kPGPError_MalformedKeyComponent;
631dc4 ¤   ¤   ¤   goto done;
690fe4 ¤   ¤   }
f59d39 ¤   ¤   /* The integer is directly embedded in the bitstring, not as an INT */
f00943 ¤   ¤   format = kPGPPublicKeyMessageFormat_PKCS1;
ac9371 ¤   }
71550a ¤   i = pgpBnGetFormatted(&bn, sig+off, siglen-off, bnBytes(&pub->n), format);
7607eb ¤   if (i <= 0)
cfc86c ¤   ¤   return kPGPError_BadSignatureSize;
e5af5a
d6f847 #if PGP_USECAPIFORRSA
f32e84 ¤   i = rsaVerifyHashSignature(&bn, pub, h, hash);
0ddb21 #else
3fd976 ¤   i = rsaPublicDecrypt(buf, sizeof(buf), &bn, pub);
e2af5a
a2b996 ¤   if (i >= 0) {
99c481 ¤   ¤   /* Check that the returned data is correct */
568610 ¤   ¤   unsigned t = h->DERprefixsize;
e90e52 ¤   ¤   i = (size_t)i <= sizeof(buf)
d41ff8 ¤   ¤   ····&& (unsigned)i == h->hashsize + t
30b62b ¤   ¤   ····&& memcmp(buf, h->DERprefix, t) == 0
1e6411 ¤   ¤   ····&& memcmp(buf+t, hash, h->hashsize) == 0;
349371 ¤   }
1a7454 #endif
fbb38c done:
770204 ¤   bnEnd(&bn);
--2280 000f8a1693c40100221 Page 5 of pgpRSAKey.c
7b718a ¤   pgpClearMemory( buf, ·sizeof(buf));
8f2196 ¤   return i;
46af5a
775156 #endif /* PGP_VERIFY_DISABLE */ /* ] */
d8efe6 }
2baf5a
57af5a
1c38e5 /*
665ebc ·* Turn a PGPPubKey into the algorithm-specific parts of a public key.
d82a5a ·* A public key's RSA-specific part is:
04775e ·*
28d61b ·* ·0 ·····2+i ·MPI for modulus
0f2551 ·* 2+i ····2+t ·MPI for exponent
9e54dd ·* 4+i+t
35495d ·*/
ab5d09 static size_t
d0bd37 rsaPubBufferLength(PGPPubKey const *pubkey)
3fbb36 {
fae101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
a9af5a
1ac2fe ¤   return 4 + bnBytes(&pub->n) + bnBytes(&pub->e);
c1efe6 }
25af5a
0d2978 static void
d3a2cc rsaPubToBuffer(PGPPubKey const *pubkey, PGPByte *buf)
3abb36 {
c5e101 ¤   RSApub const *pub = (RSApub *)pubkey->priv;
c19245 ¤   unsigned i, t;
72af5a
85fe61 ¤   i = bnBits(&pub->n);
6b001e ¤   pgpAssert(i <= 0xffff);
9f64d3 ¤   buf[0] = (PGPByte)(i >> 8);
40349c ¤   buf[1] = (PGPByte)i;
616093 ¤   i = (i+7)/8;
2ae9d6 ¤   bnExtractBigBytes(&pub->n, buf+2, 0, i);
09092a ¤   t = bnBits(&pub->e);
0cb4f9 ¤   pgpAssert(t <= 0xffff);
843b8b ¤   buf[2+i] = (PGPByte)(t >> 8);
864fc2 ¤   buf[3+i] = (PGPByte)t;
ede597 ¤   t = (t+7)/8;
d706df ¤   bnExtractBigBytes(&pub->e, buf+4+i, 0, t);
38efe6 }
eaaf5a
10af5a
5ebbab /* A little helper function that's used twice */
3b2978 static void
5c446b rsaFillPubkey(PGPPubKey *pubkey, RSApub *pub)
cabb36 {
321756 ¤   pubkey->next¤   ·= NULL;
0be204 ¤   pubkey->pkAlg¤  ·= kPGPPublicKeyAlgorithm_RSA;
3567ea ¤   pubkey->priv¤   ·= pub;
b347bf ¤   pubkey->destroy ·= rsaPubDestroy;
ae45e7 ¤   pubkey->maxesk ··= rsaPubMaxesk;
815551 ¤   pubkey->maxdecrypted ··= rsaPubMaxdecrypted;
9846f3 ¤   pubkey->maxsig ··= rsaPubMaxsig;
737d10 ¤   pubkey->encrypt ·= rsaEncrypt;
1e0998 ¤   pubkey->verify ··= rsaVerify;
2b56d0 ¤   pubkey->bufferLength ·= rsaPubBufferLength;
df1fd7 ¤   pubkey->toBuffer = rsaPubToBuffer;
14efe6 }
2faf5a
aaaf5a
da38e5 /*
9a5a5c ·* Turn the algorithm-specific parts of a public key into a PGPPubKey
0cf0a4 ·* structure. ·A public key's RSA-specific part is:
93775e ·*
dbd61b ·* ·0 ·····2+i ·MPI for modulus
f52551 ·* 2+i ····2+t ·MPI for exponent
bd54dd ·* 4+i+t
af495d ·*/
8240b4 PGPPubKey *
f88a78 rsaPubFromBuf(
--3dea 00032a16e0440100221 Page 6 of pgpRSAKey.c
08520e ¤   PGPContextRef¤  context,
d24d2b ¤   PGPByte const *¤buf,
4b39e0 ¤   size_t¤ ¤   ¤   size,
8c6429 ¤   PGPError *¤ ¤   error)
e3bb36 {
e336c1 ¤   PGPPubKey *pubkey;
2b1205 ¤   RSApub *pub;
579245 ¤   unsigned i, t;
304c08 ¤   PGPError¤   err¤= kPGPError_OutOfMemory;
256479 ¤   PGPMemoryMgrRef¤mgr¤= PGPGetContextMemoryMgr( context );
a0af5a
79bac4 ¤   bnInit();
6caf5a
6bd91b ¤   if (size < 4)
0a7ed2 ¤   ¤   return NULL;
35af5a
9ef807 ¤   i = ((unsigned)buf[0] << 8) + buf[1];
c7cace ¤   if (!i || buf[2] >> ((i-1) & 7) != 1) {
f92c22 ¤   ¤   *error = kPGPError_MalformedKeyModulus;
18d85a ¤   ¤   return NULL;¤   /* Bad bit length */
ba9371 ¤   }
f36093 ¤   i = (i+7)/8;
b16ab1 ¤   if (size < 4+i) {
66f073 ¤   ¤   *error = kPGPError_KeyPacketTruncated;
697ed2 ¤   ¤   return NULL;
dc9371 ¤   }
dce008 ¤   if ((buf[1+i] & 1) == 0) {¤ /* Too small or even modulus */
67f8fc ¤   ¤   *error = kPGPError_RSAPublicModulusIsEven;
9c7ed2 ¤   ¤   return NULL;
2a9371 ¤   }
e43ac0 ¤   t = ((unsigned)buf[2+i] << 8) + buf[3+i];
452252 ¤   if (!t || buf[4+i] >> ((t-1) & 7) != 1) {
80d4f2 ¤   ¤   *error = kPGPError_MalformedKeyExponent;
bfd85a ¤   ¤   return NULL;¤   /* Bad bit length */
ff9371 ¤   }
60e597 ¤   t = (t+7)/8;
fd98d9 ¤   if (size < 4+i+t) {
57f073 ¤   ¤   *error = kPGPError_KeyPacketTruncated;
1c7ed2 ¤   ¤   return NULL;
ab9371 ¤   }
3faf5a
511645 ¤   pub = (RSApub *)pgpContextMemAlloc( context,
f47bed ¤   ¤   sizeof(*pub), kPGPMemoryMgrFlags_Clear );
9367ab ¤   if (pub) {
ff545a ¤   ¤   pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
d57dcd ¤   ¤   ¤   sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
4ad646 ¤   ¤   if (pubkey) {
1caa14 ¤   ¤   ¤   pubkey->context¤= context;
62cf79 ¤   ¤   ¤   bnBegin(&pub->n, mgr, FALSE);
d6059c ¤   ¤   ¤   bnBegin(&pub->e, mgr, FALSE);
1b303b ¤   ¤   ¤   if (bnInsertBigBytes(&pub->n, buf+2, 0, i) >= 0
c9d48f ¤   ¤   ¤   ····&& bnInsertBigBytes(&pub->e, buf+4+i, 0, t) >= 0)
87f776 ¤   ¤   ¤   {
3c0347 ¤   ¤   ¤   ¤   if (rsaKeyTooBig (pub, NULL) ||
421db6 ¤   ¤   ¤   ¤   ¤   bnBits(&pub->n) > 2048 ) {
174f2b ¤   ¤   ¤   ¤   ¤   err = kPGPError_KeyTooLarge;
a9b5fc ¤   ¤   ¤   ¤   } else {
af8911 ¤   ¤   ¤   ¤   ¤   rsaFillPubkey(pubkey, pub);
34346a ¤   ¤   ¤   ¤   ¤   *error = 0;
0f37f5 ¤   ¤   ¤   ¤   ¤   return pubkey;
992613 ¤   ¤   ¤   ¤   }
63a3a6 ¤   ¤   ¤   }
e79865 ¤   ¤   ¤   /* Failed = clean up and return NULL */
ec9463 ¤   ¤   ¤   bnEnd(&pub->n);
0c5476 ¤   ¤   ¤   bnEnd(&pub->e);
057f83 ¤   ¤   ¤   pgpContextMemFree( context, pubkey);
c20fe4 ¤   ¤   }
55c695 ¤   ¤   pgpContextMemFree( context, pub);
489371 ¤   }
e0ab59 ¤   *error = err;
de3f59 ¤   return NULL;
32efe6 }
--6637 000a5dbbaca40100221 Page 7 of pgpRSAKey.c
e0af5a
d338e5 /*
1a439a ·* Return the size of the public portion of a key buffer.
c7495d ·*/
574d2f int
46d531 rsaPubKeyPrefixSize(PGPByte const *buf, size_t size)
7cbb36 {
744b0c ¤   return pgpBnParse(buf, size, 2, NULL, NULL);
38efe6 }
e5af5a
52af5a
beaf5a
8c114d /** Secret key functions **/
4eaf5a
d42978 static void
201c1b rsaSecDestroy(PGPSecKey *seckey)
c1bb36 {
eaccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
b68a97 ¤   PGPContextRef¤  context;
02af5a
164251 ¤   pgpAssertAddrValid( seckey, PGPPubKey );
6b5b86 ¤   context¤= seckey->context;
6eaf5a
6a7317 ¤   ASSERTRSA(seckey->pkAlg);
ac5f90 ¤   bnEnd(&sec->s.n);
949f85 ¤   bnEnd(&sec->s.e);
c0833e ¤   bnEnd(&sec->s.d);
353273 ¤   bnEnd(&sec->s.p);
5f2ec8 ¤   bnEnd(&sec->s.q);
775c24 ¤   bnEnd(&sec->s.u);
d756f8 ¤   pgpClearMemory(sec->cryptkey, sec->ckalloc);
dc5bb1 ¤   pgpContextMemFree( context, sec->cryptkey);
c80d92 ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
6e1464 ¤   pgpClearMemory( seckey, ·sizeof(seckey));
f0390c ¤   pgpContextMemFree( context, seckey);
83efe6 }
64af5a
5f38e5 /*
a13521 ·* Generate a PGPPubKey from a PGPSecKey
cc495d ·*/
c3c2ad static PGPPubKey *
faaa6f rsaPubkey(PGPSecKey const *seckey)
f6bb36 {
1bdb89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
8f36c1 ¤   PGPPubKey *pubkey;
801205 ¤   RSApub *pub;
328a97 ¤   PGPContextRef¤  context;
6d2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
4daf5a
b44813 ¤   pgpAssertAddrValid( seckey, PGPSecKey );
4f5b86 ¤   context¤= seckey->context;
85faf1 ¤   mgr¤= PGPGetContextMemoryMgr( context );
5daf5a
597317 ¤   ASSERTRSA(seckey->pkAlg);
ed30f3 ¤   pub = (RSApub *)pgpContextMemAlloc( context,·
1830c7 ¤   ¤   sizeof(*pub), kPGPMemoryMgrFlags_Clear);
3967ab ¤   if (pub) {
b7545a ¤   ¤   pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
dfd4fa ¤   ¤   ¤   sizeof(*pubkey), kPGPMemoryMgrFlags_Clear );
69d646 ¤   ¤   if (pubkey) {
80a978 ¤   ¤   ¤   pubkey->context¤= seckey->context;
3887c7 ¤   ¤   ¤
84cf79 ¤   ¤   ¤   bnBegin(&pub->n, mgr, FALSE);
6a059c ¤   ¤   ¤   bnBegin(&pub->e, mgr, FALSE);
cd1020 ¤   ¤   ¤   if (bnCopy(&pub->n, &sec->s.n) >= 0
a71e4c ¤   ¤   ¤   ····&& bnCopy(&pub->e, &sec->s.e) >= 0)
f2f776 ¤   ¤   ¤   {
9e9141 ¤   ¤   ¤   ¤   rsaFillPubkey(pubkey, pub);
fd7c58 ¤   ¤   ¤   ¤   pubkey->pkAlg = seckey->pkAlg;
11d49b ¤   ¤   ¤   ¤   memcpy(pubkey->keyID, seckey->keyID,
244c85 ¤   ¤   ¤   ¤   ·······sizeof(pubkey->keyID));
a5bb8a ¤   ¤   ¤   ¤   return pubkey;
--7473 000c16c9c6d40100221 Page 8 of pgpRSAKey.c
cfa3a6 ¤   ¤   ¤   }
bc9865 ¤   ¤   ¤   /* Failed = clean up and return NULL */
f49463 ¤   ¤   ¤   bnEnd(&pub->n);
405476 ¤   ¤   ¤   bnEnd(&pub->e);
287f83 ¤   ¤   ¤   pgpContextMemFree( context, pubkey);
6c0fe4 ¤   ¤   }
fa6424 ¤   ¤   pgpContextMemFree(context, pub);
b99371 ¤   }
313f59 ¤   return NULL;
dbefe6 }
84af5a
4b38e5 /*
d0d39c ·* Yes, there *is* a reason that this is a function and no a variable.
4fa3bd ·* On a hardware device with an automatic timeout,
a06854 ·* it actually might need to do some work to find out.
6d495d ·*/
35beb7 static int
448dbd rsaIslocked(PGPSecKey const *seckey)
63bb36 {
3edb89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
c5af5a
a47317 ¤   ASSERTRSA(seckey->pkAlg);
cd096c ¤   return sec->locked;
67efe6 }
b4af5a
11af5a
9438e5 /*
8bc3dc ·* Return the algorithm and (symmetric) key size used for locking/unlocking
84f175 ·* the secret key.
c5495d ·*/
0af1ae static PGPError
6371df rsaLockingAlgorithm(
1db573 ¤   PGPSecKey const *seckey,
196f43 ¤   PGPCipherAlgorithm *pAlg,
8fb91d ¤   PGPSize *pAlgKeySize
6227e6 ¤   )
41bb36 {
b5ccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
b908c6 ¤   PGPCipherVTBL const *cipher;
baafba ¤   PGPByte alg;
664ba4 ¤   int i;
46af5a
d07317 ¤   ASSERTRSA(seckey->pkAlg);
0aaf5a
570ec4 ¤   if( IsntNull( pAlg ) )
907a59 ¤   ¤   *pAlg = (PGPCipherAlgorithm) 0;
597929 ¤   if( IsntNull( pAlgKeySize ) )
12301e ¤   ¤   *pAlgKeySize = (PGPSize) 0;
9faf5a
e784c6 ¤   /* Check packet for basic consistency */
69bb74 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 2, NULL, NULL);
634fd6 ¤   if (i < 0)
5e2051 ¤   ¤   return (PGPError)i;
4eaf5a
2db604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
38e893 ¤   alg = sec->cryptkey[i] & 255;
3eaf5a
b89fab ¤   /* New style has 255 then algorithm value */
bb130c ¤   if (alg == 255)
39acc2 ¤   ¤   alg = sec->cryptkey[i+1] & 255;
53af5a
5bc7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
80b637 ¤   if (!cipher)
60fb6d ¤   ¤   return kPGPError_BadCipherNumber;
d1af5a
630d42 ¤   /* Success */
f80ec4 ¤   if( IsntNull( pAlg ) )
672341 ¤   ¤   *pAlg = (PGPCipherAlgorithm) alg;
7f7929 ¤   if( IsntNull( pAlgKeySize ) )
caf60c ¤   ¤   *pAlgKeySize = cipher->keysize;
a6af5a
c1151e ¤   return kPGPError_NoErr;
--1a58 000c8d58b5940100221 Page 9 of pgpRSAKey.c
7aefe6 }
46af5a
8eaf5a
b538e5 /*
37d2ee ·* Return the StringToKey type for unlocking the given key. ·We use
dc4eb5 ·* kPGPStringToKey_Literal to flag a secret split unlocking buffer.
459d12 ·* Returns kPGPStringToKey_Simple if key has no passphrase.
41495d ·*/
d3f1ae static PGPError
18b2f6 rsaS2KType(
95b573 ¤   PGPSecKey const *seckey,
b09e5a ¤   PGPStringToKeyType *s2kType
9c27e6 ¤   )
6fbb36 {
baccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
e0afba ¤   PGPByte alg;
fd4ba4 ¤   int i;
27af5a
a27317 ¤   ASSERTRSA(seckey->pkAlg);
1eaf5a
0f55b6 ¤   /* note that 0 is a valid type, but use it as default anyway */
c5dab9 ¤   if( IsntNull( s2kType ) )
a6bc38 ¤   ¤   *s2kType = (PGPStringToKeyType) 0;
16af5a
e684c6 ¤   /* Check packet for basic consistency */
8cbb74 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 2, NULL, NULL);
464fd6 ¤   if (i < 0)
532051 ¤   ¤   return (PGPError)i;
eaaf5a
4bb604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
f6e893 ¤   alg = sec->cryptkey[i] & 255;
e2af5a
5d40cd ¤   if (alg == 255) {
1c3446 ¤   ¤   /* New style has 255 then algorithm value then S2K */
84d66f ¤   ¤   *s2kType = (PGPStringToKeyType) sec->cryptkey[i+2];
33f037 ¤   } else {
294191 ¤   ¤   /* Unencrypted or old-style simple encryption */
64c21f ¤   ¤   *s2kType = kPGPStringToKey_Simple;
a09371 ¤   }
4caf5a
90151e ¤   return kPGPError_NoErr;
66efe6 }
99af5a
7baf5a
7438e5 /*
6571a1 ·* Convert a passphrase into a s2k literal buffer for the key.
c55514 ·* Returns error code. ·Output buffer will be size of the *pAlgKeySize
982df7 ·* parameter from pgpSecKeyLockingalgorithm.
96495d ·*/
99f1ae static PGPError
1173a5 rsaConvertPassphrase(PGPSecKey *seckey, PGPEnv const *env,
0a9820 ¤   ··char const *phrase, PGPSize plen, PGPByte *outbuf)
0bbb36 {
c3ccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
84bfb0 ¤   PGPStringToKey *s2k;
d7afba ¤   PGPByte alg;
4c0306 ¤   PGPBoolean hasS2K;
0308c6 ¤   PGPCipherVTBL const *cipher;
5b4ba4 ¤   int i;
6faf5a
ee7317 ¤   ASSERTRSA(seckey->pkAlg);
ba6bb2 ¤   pgpAssert (IsntNull( outbuf ) );
17af5a
1084c6 ¤   /* Check packet for basic consistency */
bfa423 ¤   i = pgpBnParse(sec->cryptkey, sec->cklen, 2, NULL, NULL, NULL, NULL);
e74fd6 ¤   if (i < 0)
c72051 ¤   ¤   return (PGPError)i;
40af5a
3fb604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
bf8aa2 ¤   alg = sec->cryptkey[i++] & 255;
24af5a
c8eaa8 ¤   hasS2K = (alg == 255);
--1b7b 000d239b9e940100221 Page 10 of pgpRSAKey.c
e0af5a
979fab ¤   /* New style has 255 then algorithm value */
7b727d ¤   if (hasS2K)
5e4ff7 ¤   ¤   alg = sec->cryptkey[i++] & 255;
c7af5a
4dcb98 ¤   /* Now we are looking at the s2k object if there is one. */
760d7e ¤   if (alg == 0) {
37cc33 ¤   ¤   /* Key is not locked */
e762b5 ¤   ¤   return kPGPError_BadParams;
dc9371 ¤   }
96c7a5 ¤   cipher = pgpCipherGetVTBL( (PGPCipherAlgorithm)alg);
c6b04e ¤   if( IsNull( cipher ) )
e2fb6d ¤   ¤   return kPGPError_BadCipherNumber;
67af5a
2adb5e ¤   if (hasS2K) {
e40162 ¤   ¤   pgpS2Kdecode(&s2k, env, sec->cryptkey+i, sec->cklen-i);
41f037 ¤   } else {
25176e ¤   ¤   s2k = pgpS2Ksimple(env, pgpHashByNumber(kPGPHashAlgorithm_MD5));
989371 ¤   }
ec6f18 ¤   if (IsNull( s2k ) )
bf4030 ¤   ¤   return kPGPError_OutOfMemory;
2ba401 ¤   pgpStringToKey(s2k, phrase, plen, outbuf, cipher->keysize);
bffdac ¤   pgpS2Kdestroy (s2k);
15af5a
8c151e ¤   return kPGPError_NoErr;
0fefe6 }
3aaf5a
daaf5a
f938e5 /*
482d14 ·* Try to decrypt the secret key wih the given passphrase. ·Returns >0
4293d2 ·* if it was the correct passphrase. =0 if it was not, and <0 on error.
f4fa8a ·* Does not alter the key even if it's the wrong passphrase and already
cb9458 ·* unlocked. ·A NULL passphrae will work if the key is unencrypted.
299ec0 ·*·
c697a8 ·* A (secret) key's RSA-specific part is:
24775e ·*
f5650a ·* ·0 ···············2+u ·MPI for modulus
99b12b ·* ·2+u ·············2+v ·MPI for exponent
adcef6 ·* ·4+u+v ···········1 ···Encryption algorithm (0 for none, 1 for IDEA)
9d460a ·* ·5+u+v ···········t ···Encryption IV: 0 or 8 bytes
a59e28 ·* ·5+t+u+v ·········2+w ·MPI for d
87910b ·* ·7+t+u+v+w ·······2+x ·MPI for p
fb5e6a ·* ·9+t+u+v+w+x ·····2+y ·MPI for q
671a35 ·* 11+t+u+v+w+x+y ···2+z ·MPI for u
481631 ·* 13+t+u+v+w+x+y+z ·2 ···Checksum
f30bee ·* 15+t+u+v+w+x+y+z
1d775e ·*
08ee8f ·* Actually, that's the old-style, if pgpS2KoldVers is true.
332462 ·* If it's false, the algoruthm is 255, and is followed by the
ee8f61 ·* algorithm, then the (varaible-length, self-delimiting)
9c217f ·* string-to-key descriptor.
54495d ·*/
bbaf5a
54beb7 static int
afa62a rsaUnlock(PGPSecKey *seckey, PGPEnv const *env,
8d7e27 ¤   ··char const *phrase, size_t plen, PGPBoolean hashedPhrase)
7ebb36 {
8eccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
4a69cc ¤   BigNum d, p, q, u, bn;
7c5ee2 ¤   PGPCFBContext *cfb = NULL;¤ /* Necessary */
9aed7c ¤   unsigned v, t;
cedfbc ¤   unsigned alg;
601b07 ¤   unsigned checksum;
a34ba4 ¤   int i;
1c2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
acaf5a
951e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
e0af5a
bc7317 ¤   ASSERTRSA(seckey->pkAlg);
b6bac4 ¤   bnInit();
41af5a
d2fb49 ¤   if (sec->cklen < 5)
--9985 00086af88e240100221 Page 11 of pgpRSAKey.c
86a27a ¤   ¤   return kPGPError_KeyPacketTruncated;
429e55 ¤   v = ((unsigned)sec->cryptkey[0] << 8) + sec->cryptkey[1];
b7e5a2 ¤   v = (v+7)/8;
359f5e ¤   if (sec->cklen < 5+v)
afa27a ¤   ¤   return kPGPError_KeyPacketTruncated;
e9ad0b ¤   if (bnInsertBigBytes(&sec->s.n, sec->cryptkey+2, 0, v) < 0)
774030 ¤   ¤   return kPGPError_OutOfMemory;
bcd193 ¤   t = ((unsigned)sec->cryptkey[2+v] << 8) + sec->cryptkey[3+v];
ffe597 ¤   t = (t+7)/8;
e94888 ¤   if (sec->cklen < 4+v+t)
a3a27a ¤   ¤   return kPGPError_KeyPacketTruncated;
52ccf8 ¤   if (bnInsertBigBytes(&sec->s.e, sec->cryptkey+4+v, 0, t) < 0)
8c4030 ¤   ¤   return kPGPError_OutOfMemory;
31df6e ¤   v += t + 4;
1bc9c3 ¤   if (sec->cklen < v+1)
b5a27a ¤   ¤   return kPGPError_KeyPacketTruncated;
c4af5a
aeb604 ¤   /* Get the encryption algorithm (cipher number). ·0 == no encryption */
56547e ¤   alg ·= sec->cryptkey[v];
c0af5a
fd3563 ¤   /* If the phrase is empty, set it to NULL */
6fc08b ¤   if (plen == 0)
666f28 ¤   ¤   phrase = NULL;
2ad8af ¤   /*
dfb08f ¤   ·* We need a pass if it is encrypted, and we cannot have a
297664 ¤   ·* password if it is NOT encrypted. ·I.e., this is a logical
b7887b ¤   ·* xor (^^)
25a4e3 ¤   ·*/
51c441 ¤   if (!phrase != !alg)
1bbbde ¤   ¤   return 0;
1faf5a
ba1ca2 ¤   i = pgpCipherSetup(sec->cryptkey + v, sec->cklen - v, phrase, plen,
a91001 ¤   ¤   ¤   ¤   ¤   ···hashedPhrase, env, &cfb);
214fd6 ¤   if (i < 0)
9fa423 ¤   ¤   return i;
7824fb ¤   v += i;
d4af5a
bca2f0 ¤   checksum = 0;
61f43c ¤   bnBegin(&d, mgr, TRUE);
387e61 ¤   bnBegin(&p, mgr, TRUE);
d5364b ¤   bnBegin(&q, mgr, TRUE);
ed1ef2 ¤   bnBegin(&u, mgr, TRUE);
ffed59 ¤   bnBegin(&bn, mgr, TRUE);
07af5a
78418f ¤   i = pgpBnGet(&d, sec->cryptkey + v, sec->cklen - v, cfb, &checksum,
800cda ¤   ¤   ¤   ¤   ·sec->v3);
a507eb ¤   if (i <= 0)
fe84fc ¤   ¤   goto fail;
bb24fb ¤   v += i;
001b5e ¤   if (bnCmp(&d, &sec->s.n) >= 0)
46b450 ¤   ¤   goto badpass;¤  /* Wrong passphrase: d must be < n */
49313f ¤   i = pgpBnGet(&p, sec->cryptkey + v, sec->cklen - v, cfb, &checksum,
830cda ¤   ¤   ¤   ¤   ·sec->v3);
1207eb ¤   if (i <= 0)
de84fc ¤   ¤   goto fail;
2ecfc7 ¤   if ((bnLSWord(&p) & 1) == 0)
36a8d5 ¤   ¤   goto badpass;
a824fb ¤   v += i;
4a6066 ¤   i = pgpBnGet(&q, sec->cryptkey + v, sec->cklen - v, cfb, &checksum,
6a0cda ¤   ¤   ¤   ¤   ·sec->v3);
f707eb ¤   if (i <= 0)
3084fc ¤   ¤   goto fail;
55b12d ¤   if ((bnLSWord(&q) & 1) == 0)
67a8d5 ¤   ¤   goto badpass;
e524fb ¤   v += i;
ceaf5a
ed4b01 ¤   /* Extremely high-powered check. ·Verify that p*q == n */
c9d4f5 ¤   if (bnMul(&bn, &p, &q) < 0)
635b40 ¤   ¤   goto nomem;
1f4574 ¤   if (bnCmp(&bn, &sec->s.n) != 0)
7ca8d5 ¤   ¤   goto badpass;
86af5a
--431a 00097053ad140100221 Page 12 of pgpRSAKey.c
f2eed8 ¤   /* Verify that d*e == 1 mod p-1 */
8739a8 ¤   (void)bnSubQ(&p, 1);
fa4090 ¤   if (bnMul(&bn, &d, &sec->s.e) < 0 || bnMod(&bn, &bn, &p) < 0)
035b40 ¤   ¤   goto nomem;
6af8c8 ¤   if (bnCmpQ(&bn, 1) != 0)
2ba8d5 ¤   ¤   goto badpass;
030dd8 ¤   (void)bnAddQ(&p, 1);
02af5a
d2710d ¤   /* Verify that d*e == 1 mod q-1 */
d7a67d ¤   (void)bnSubQ(&q, 1);
b8c12f ¤   if (bnMul(&bn, &d, &sec->s.e) < 0 || bnMod(&bn, &bn, &q) < 0)
615b40 ¤   ¤   goto nomem;
6ff8c8 ¤   if (bnCmpQ(&bn, 1) != 0)
f6a8d5 ¤   ¤   goto badpass;
91920d ¤   (void)bnAddQ(&q, 1);
e6af5a
542d13 ¤   i = pgpBnGet(&u, sec->cryptkey + v, sec->cklen - v, cfb, &checksum,
ee0cda ¤   ¤   ¤   ¤   ·sec->v3);
9b07eb ¤   if (i <= 0)
7784fc ¤   ¤   goto fail;
b224fb ¤   v += i;
a8af5a
134e68 ¤   /* Check that we ended in the right place */
e98c8c ¤   if (sec->cklen - v != 2) {
f4e85e ¤   ¤   i = kPGPError_KEY_LONG;
6084fc ¤   ¤   goto fail;
5a9371 ¤   }
24afa6 ¤   checksum &= 0xffff;
b97744 ¤   if (checksum != ((unsigned)sec->cryptkey[v]<<8) + sec->cryptkey[1+v])
69a8d5 ¤   ¤   goto badpass;
6caf5a
533542 ¤   /* Verify that u = p^-1 mod q is less than q */
2d2c6a ¤   if (bnCmp(&u, &q) >= 0)
f3a8d5 ¤   ¤   goto badpass;
9ae9cf ¤   /* Verify that u * p == 1 mod q */
4dc419 ¤   if (bnMul(&bn, &p, &u) < 0 || bnMod(&bn, &bn, &q) < 0)
d15b40 ¤   ¤   goto nomem;
67f8c8 ¤   if (bnCmpQ(&bn, 1) != 0)
97a8d5 ¤   ¤   goto badpass;
e4af5a
43d8af ¤   /*
1fa4bb ¤   ·* Okay, we've verified every single value in the secret key,
c3a4ac ¤   ·* against the public key, so it is *definitely* the right
6e6ce3 ¤   ·* secret key. ·Note that the "nomem" case calls bnEnd()
2d5307 ¤   ·* more than once, but this is guaranteed harmless.
f79c20 ·¤  ·*/
310204 ¤   bnEnd(&bn);
d95fc1 ¤   if (bnCopy(&sec->s.d, &d) < 0)
955b40 ¤   ¤   goto nomem;
6153ea ¤   bnEnd(&d);
2c02c9 ¤   if (bnCopy(&sec->s.p, &p) < 0)
c35b40 ¤   ¤   goto nomem;
76e2a7 ¤   bnEnd(&p);
360623 ¤   if (bnCopy(&sec->s.q, &q) < 0)
015b40 ¤   ¤   goto nomem;
7efe1c ¤   bnEnd(&q);
df158b ¤   if (bnCopy(&sec->s.u, &u) < 0)
365b40 ¤   ¤   goto nomem;
5e8cf0 ¤   bnEnd(&u);
9baf5a
c52f6d ¤   i = 1;¤ /* Decrypted! */
300162 ¤   sec->locked = 0;
f8afda ¤   if (cfb)
b0f65d ¤   ¤   PGPFreeCFBContext (cfb);
c040ed ¤   return 1;¤  /* Decrypted */
14af5a
21ac52 nomem:
ee30c4 ¤   i = kPGPError_OutOfMemory;
09c48e ¤   goto done;
a888a7 badpass:
baf1b7 ¤   i = 0;¤ /* Incorrect passphrase */
97c48e ¤   goto done;
--c2cc 00001e37a2f40100221 Page 13 of pgpRSAKey.c
b8115d fail:
a75451 ¤   if (!i)
12a3b2 ¤   ¤   i = kPGPError_KeyPacketTruncated;
6bc48e ¤   goto done;
9eb38c done:
bbafda ¤   if (cfb)
3ef65d ¤   ¤   PGPFreeCFBContext (cfb);
620204 ¤   bnEnd(&bn);
0e8cf0 ¤   bnEnd(&u);
e6fe1c ¤   bnEnd(&q);
3ee2a7 ¤   bnEnd(&p);
b753ea ¤   bnEnd(&d);
2c2196 ¤   return i;
0fefe6 }
82af5a
4538e5 /*
8c3dfc ·* Relock the key.
42495d ·*/
7f2978 static void
d55a1f rsaLock(PGPSecKey *seckey)
1fbb36 {
adccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
34af5a
ab7317 ¤   ASSERTRSA(seckey->pkAlg);
a15bbe ¤   sec->locked = 1;
939e4a ¤   /* bnEnd is documented as also doing a bnBegin */
d9833e ¤   bnEnd(&sec->s.d);
f03273 ¤   bnEnd(&sec->s.p);
932ec8 ¤   bnEnd(&sec->s.q);
9e5c24 ¤   bnEnd(&sec->s.u);
b7efe6 }
40af5a
e05d09 static size_t
e8a086 rsaSecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format);
05af5a
3eaf5a
3138e5 /*
4d7d83 ·* Try to decrypt the given esk. ·If the key is locked, try the given
570169 ·* passphrase. ·It may or may not leave the key unlocked in such a case.
ea8bf9 ·* (Some hardware implementations may insist on a password per usage.)
34495d ·*/
2ebeb7 static int
176008 rsaDecrypt(PGPSecKey *seckey, PGPEnv const *env,
f6695b ¤   ¤   ···PGPByte const *esk, size_t esklen,
6677cb ¤   ¤   ···PGPByte *key, size_t *keylen,
b940b7 ¤   ¤   ···char const *phrase, size_t plen,
bff9f5 ¤   ¤   ···PGPPublicKeyMessageFormat format)
dabb36 {
100545 #if PGP_DECRYPT_DISABLE /* [ */
faaf5a
b3c9d3 ¤   (void)seckey;
0f7054 ¤   (void)env;
c04290 ¤   (void)esk;
447a0a ¤   (void)esklen;
ae9b3e ¤   (void)key;
2aede5 ¤   (void)keylen;
21cf72 ¤   (void)phrase;
d0087c ¤   (void)plen;
c41c0d ¤   (void)format;
71e63f ¤   return kPGPError_FeatureNotAvailable;
c0af5a
a30d75 #else /* PGP_DECRYPT_DISABLE */ ·/* ] ·[ */
28af5a
61ccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
c6699d ¤   BigNum bn;
9a927e ¤   int i, j;
c10ed5 ¤   unsigned t;
63d8e8 ¤   size_t max;
bb2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
14af5a
381e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
01af5a
--d596 000283d4f3840100221 Page 14 of pgpRSAKey.c
f39c34 ¤   ASSERTRSAENC(seckey->pkAlg);
d5a092 ¤   if (sec->locked) {
ccf98f ¤   ¤   i = rsaUnlock(seckey, env, phrase, plen, FALSE);
d39098 ¤   ¤   if (i <= 0)
d311b7 ¤   ¤   ¤   return i ? i : kPGPError_KeyIsLocked;
3eef50 ¤   ¤   pgpAssert(!sec->locked);
1d9371 ¤   }
7aaf5a
5b8d55 ¤   if (esklen < 2)
d07298 ¤   ¤   return kPGPError_BadSessionKeySize;
5f67c5 ¤
2eed59 ¤   bnBegin(&bn, mgr, TRUE);
9e156c ¤   i = pgpBnGetFormatted(&bn, esk, esklen, bnBytes(&sec->s.n), format);
6507eb ¤   if (i <= 0)
247298 ¤   ¤   return kPGPError_BadSessionKeySize;
45af5a
148d54 ¤   max = rsaSecMaxdecrypted(seckey, format);
9f23a1 ¤   i = rsaPrivateDecrypt(key, max, &bn, &sec->s);
e20204 ¤   bnEnd(&bn);
a84fd6 ¤   if (i < 0)
fda423 ¤   ¤   return i;
734796 ¤   if ((size_t)i > max || i < 3)
e185dd ¤   ¤   return kPGPError_CorruptData;
2caf5a
020041 ¤   if (format == kPGPPublicKeyMessageFormat_PGP) {
34e893 ¤   ¤   /* Check checksum (should this be here?) */
560550 ¤   ¤   t = 0;
af19f9 ¤   ¤   for (j = 1; j < i-2; j++)
391e00 ¤   ¤   ¤   t += key[j];
139f82 ¤   ¤   if (t != ((unsigned)key[i-2]<<8) + key[i-1])
18b933 ¤   ¤   ¤   return kPGPError_CorruptData;
4f72e5 ¤   ¤   pgpClearMemory(key+i-2, 2);
80af5a
6f2981 ¤   ¤   /* The actual key */
f92f3a ¤   ¤   if (keylen)
777f6d ¤   ¤   ¤   *keylen = (size_t)i-2;
b2f037 ¤   } else {
0c2981 ¤   ¤   /* The actual key */
112f3a ¤   ¤   if (keylen)
15b2df ¤   ¤   ¤   *keylen = (size_t)i;
8e9371 ¤   }
83af5a
c63e6b ¤   return 0;
89af5a
7a2cfc #endif /* PGP_DECRYPT_DISABLE */ /* ] */
6fefe6 }
f8af5a
b5af5a
ab38e5 /*
8ef5ac ·* Return the size of the buffer needed, worst-case, for the decrypted
896727 ·* output. ·A trivially padded key (random padding length = 0)
f66493 ·* can just be 0 2 0 <key>.
10495d ·*/
ec5d09 static size_t
6b84f5 rsaSecMaxdecrypted(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
42bb36 {
eadb89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
63e002 ¤   size_t size;
a1af5a
24476e ¤   (void) format;
289c34 ¤   ASSERTRSAENC(seckey->pkAlg);
34af5a
15a19d ¤   size = bnBytes(&sec->s.n);
e3de44 ¤   return size < 3 ? 0 : size-3;
00efe6 }
78af5a
a1a863 /* Return the largest possible PGPESK size for a given key */
725d09 static size_t
2c0d04 rsaSecMaxesk(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
fabb36 {
3fdb89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
28af5a
--32e6 000412f7eea40100221 Page 15 of pgpRSAKey.c
f39c34 ¤   ASSERTRSAENC(seckey->pkAlg);
b59850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
2e8bf1 ¤   ¤   return 2 + bnBytes(&sec->s.n);
5bf515 ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1 ||
622095 ¤   ¤   ¤   ·format == kPGPPublicKeyMessageFormat_X509)
183a77 ¤   ¤   return bnBytes(&sec->s.n);
7caf5a
ec4aac ¤   pgpAssert(0);
893e6b ¤   return 0;
36efe6 }
acaf5a
cf5d09 static size_t
a1c12c rsaSecMaxsig(PGPSecKey const *seckey, PGPPublicKeyMessageFormat format)
74bb36 {
42db89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
d3af5a
55c93c ¤   ASSERTRSASIG(seckey->pkAlg);
009850 ¤   if (format == kPGPPublicKeyMessageFormat_PGP)
018bf1 ¤   ¤   return 2 + bnBytes(&sec->s.n);
8061bb ¤   else if (format == kPGPPublicKeyMessageFormat_PKCS1)
ca3a77 ¤   ¤   return bnBytes(&sec->s.n);
9ab92c ¤   else if (format == kPGPPublicKeyMessageFormat_X509)
033d28 ¤   ¤   /* BITSTRING, length bytes, 0, data */
1363f9 ¤   ¤   return 1 + bnBytes(&sec->s.n) + 1 +
d53379 ¤   ¤   ¤   ·¤  ¤   ¤   pgpBnX509LenLen(bnBytes(&sec->s.n)+1);
84af5a
ed4aac ¤   pgpAssert(0);
f93e6b ¤   return 0;
a5efe6 }
85af5a
c6beb7 static int
395348 rsaSign(PGPSecKey *seckey, PGPHashVTBL const *h, PGPByte const *hash,
5c6564 ¤   PGPByte *sig, size_t *siglen, PGPRandomContext const *rc,
a16fc3 ¤   PGPPublicKeyMessageFormat format)
0dbb36 {
a4ccf3 #if PGP_SIGN_DISABLE /* [ */
b9af5a
adc9d3 ¤   (void)seckey;
5bc6fd ¤   (void)h;
874902 ¤   (void)hash;
3577e4 ¤   (void)sig;
7b51a9 ¤   (void)siglen;
1976a2 ¤   (void)rc;
cf1c0d ¤   (void)format;
99e63f ¤   return kPGPError_FeatureNotAvailable;
95af5a
7adb21 #else
82af5a
0eccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
98699d ¤   BigNum bn;
984ba4 ¤   int i;
ca0ed5 ¤   unsigned t;
7b2955 ¤   PGPMemoryMgrRef¤¤   mgr¤= NULL;
dc67c5 ¤
4d1e32 ¤   mgr¤= PGPGetContextMemoryMgr( seckey->context );
86af5a
cf80d5 ¤   /* We don't need these arguments, although other algorithms may... */
6d76a2 ¤   (void)rc;
9b1c0d ¤   (void)format;
56af5a
1ec93c ¤   ASSERTRSASIG(seckey->pkAlg);
2bd2c6 ¤   if (sec->locked)
62035c ¤   ¤   return kPGPError_KeyIsLocked;
51af5a
aced59 ¤   bnBegin(&bn, mgr, TRUE);
26af5a
f5f847 #if PGP_USECAPIFORRSA
eb2da3 ¤   i = rsaSignHash(&bn, &sec->s, h, hash);
e0db21 #else
7d95c8 ¤   t = h->DERprefixsize;
112f13 ¤   if (t+h->hashsize ·> rsaSecMaxsig(seckey, format))
41389e ¤   ¤   return kPGPError_PublicKeyTooSmall;
--d861 000ac26ef8d40100221 Page 16 of pgpRSAKey.c
b5203c ¤   memcpy(sig, h->DERprefix, t);
aba924 ¤   memcpy(sig+t, hash, h->hashsize);
0fb56b ¤   t += h->hashsize;
a7af5a
e94f1c ¤   i = rsaPrivateEncrypt(&bn, sig, t, &sec->s);
13c07b ¤   pgpClearMemory( sig, ·t);
a07454 #endif
3db996 ¤   if (i >= 0) {
c90550 ¤   ¤   t = 0;
911164 ¤   ¤   if (format == kPGPPublicKeyMessageFormat_X509) {
b58643 ¤   ¤   ¤   /* Put in BITSTRING header for 509 sig data */
969647 ¤   ¤   ¤   PGPUInt32 len_bitstr, lenlen_bitstr;
3b4741 ¤   ¤   ¤   len_bitstr = 1 + bnBytes(&sec->s.n);
846bde ¤   ¤   ¤   lenlen_bitstr = pgpBnX509LenLen(len_bitstr);
c8d539 ¤   ¤   ¤   sig[t++] = X509_TAG_BITSTRING;
5f7612 ¤   ¤   ¤   if (--lenlen_bitstr == 0) {
cc4c06 ¤   ¤   ¤   ¤   sig[t++] = len_bitstr;
b4042d ¤   ¤   ¤   } else {
12a28a ¤   ¤   ¤   ¤   sig[t++] = 0x80 | lenlen_bitstr;
31f91a ¤   ¤   ¤   ¤   len_bitstr <<= 8 * (4-lenlen_bitstr);
278f01 ¤   ¤   ¤   ¤   while (lenlen_bitstr--) {
1fe6f8 ¤   ¤   ¤   ¤   ¤   sig[t++] = (PGPByte)(len_bitstr >> 24);
c8ba2f ¤   ¤   ¤   ¤   ¤   len_bitstr <<= 8;
c52613 ¤   ¤   ¤   ¤   }
00a3a6 ¤   ¤   ¤   }
b0af7f ¤   ¤   ¤   sig[t++] = 0;¤  /* no excess bits in bitstring */
b363e3 ¤   ¤   ¤   /* Value is put in bitstring directly, not formatted as an INT */
2a1864 ¤   ¤   ¤   format = kPGPPublicKeyMessageFormat_PKCS1;
180fe4 ¤   ¤   }
c10da6 ¤   ¤   t += pgpBnPutFormatted(&bn, sig+t, bnBytes(&sec->s.n), format);
2d9376 ¤   ¤   if (siglen)
ea73e4 ¤   ¤   ¤   *siglen = (size_t)t;
d49ed6 ¤   ¤   i = 0;
219371 ¤   }
760204 ¤   bnEnd(&bn);
ae2196 ¤   return i;
d5af5a
c1adb6 #endif /* PGP_SIGN_DISABLE */ /* ] */
c4efe6 }
23af5a
b1af5a
a538e5 /*
09c203 ·* Re-encrypt a PGpSecKey with a new urn a PGPSecKey into a secret key.
be13db ·* A secret key is, after a non-specific prefix:
a43dd0 ·* ·0 ······1 ···Version (= 2 or 3)
9ee351 ·* ·1 ······4 ···Timestamp
ff0e90 ·* ·5 ······2 ···Validity (=0 at present)
2f4c6b ·* ·7 ······1 ···Algorithm (=1 for RSA)
c99455 ·* The following:
e5650a ·* ·0 ···············2+u ·MPI for modulus
ffb12b ·* ·2+u ·············2+v ·MPI for exponent
21cef6 ·* ·4+u+v ···········1 ···Encryption algorithm (0 for none, 1 for IDEA)
1f460a ·* ·5+u+v ···········t ···Encryption IV: 0 or 8 bytes
759e28 ·* ·5+t+u+v ·········2+w ·MPI for d
bb910b ·* ·7+t+u+v+w ·······2+x ·MPI for p
755e6a ·* ·9+t+u+v+w+x ·····2+y ·MPI for q
201a35 ·* 11+t+u+v+w+x+y ···2+z ·MPI for u
3eb08e ·* 13+t+u+v+w+x+y+z ·2 ···Checksum (big-endian sum of all the bytes)
520bee ·* 15+t+u+v+w+x+y+z
89775e ·*
2bd1aa ·* The Encryption algorithm is the cipher algorithm for the old-style
5f4ff3 ·* string-to-key conversion. ·For the new type, it's 255, then a cipher
2f2fc9 ·* algorithm, then a string-to-key algorithm (variable-length),
f4d7a3 ·* then the encryption IV. ·That's 16 bytes plus the string-to-key
7ef861 ·* conversion length.
9e495d ·*/
16af5a
140ccc #if PGP_MACINTOSH
5f9221 #pragma global_optimizer on
947454 #endif
bfbeb7 static int
ac6c88 rsaChangeLock(PGPSecKey *seckey, PGPEnv const *env,·
--f9a2 0008f47d42d40100221 Page 17 of pgpRSAKey.c
f75ff1 ¤   PGPRandomContext const *rc, char const *phrase, size_t plen,
49ab73 ¤   PGPStringToKeyType s2ktype)
20bb36 {
4bccfc ¤   RSAsecPlus *sec = (RSAsecPlus *)seckey->priv;
228c63 ¤   PGPStringToKey *s2k = NULL;¤/* Shut up warnings */
12bfad ¤   PGPCipherVTBL const *cipher = NULL;¤/* Shut up warnings */
22bf66 ¤   PGPCFBContext *cfb = NULL;¤ /* This is realy needed */
d34cc9 ¤   PGPByte *p;
a201ca ¤   int oldf = 0;¤  ¤   ¤   ¤   /* Shut up warnings */
92c6b5 ¤   unsigned len;
101b07 ¤   unsigned checksum;
30af5a
ee7317 ¤   ASSERTRSA(seckey->pkAlg);
00d2c6 ¤   if (sec->locked)
c7035c ¤   ¤   return kPGPError_KeyIsLocked;
dcaf5a
dbf5c0 ¤   len = bnBytes(&sec->s.n) + bnBytes(&sec->s.e) +
44be5b ¤   ······bnBytes(&sec->s.d) + bnBytes(&sec->s.p) +
4f7f5c ¤   ······bnBytes(&sec->s.q) + bnBytes(&sec->s.u) + 15;
27358f ¤   if (phrase) {
7fca01 ¤   ¤   /* Create old-style s2k unless new features requested */
8dda6e ¤   ¤   if (s2ktype == kPGPStringToKey_Simple)
2ca634 ¤   ¤   ¤   s2k = pgpS2KdefaultV3(env, rc);
d60e1d ¤   ¤   else
b84a38 ¤   ¤   ¤   s2k = pgpS2Kcreate(env, rc, s2ktype);
4ba487 ¤   ¤   if (!s2k)
5d7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
600c78 ¤   ¤   cipher = pgpCipherDefaultKeyV3(env);
dca7cf ¤   ¤   pgpAssert(cipher);
34db89 ¤   ¤   if (!cipher) {
704835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
607cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
6e0fe4 ¤   ¤   }
3ee9ea ¤   ¤   len += cipher->blocksize;
b7febe ¤   ¤   cfb = pgpCFBCreate( PGPGetContextMemoryMgr( pgpenvGetContext( env ) ),
067eca ¤   ¤   ¤   ¤   ¤   ¤   ¤   cipher);
3c5dfd ¤   ¤   if (!cfb) {
f34835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
5f7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
d20fe4 ¤   ¤   }
619484 ¤   ¤   oldf = pgpS2KisOldVers(s2k);
66cfc4 ¤   ¤   if (!oldf)
320bcc ¤   ¤   ¤   len += 1 + s2k->encodelen;
719371 ¤   }
9c9613 ¤   if (len > sec->ckalloc) {
e5000e ¤   ¤   PGPError err = kPGPError_NoErr;
2bd409 ¤   ¤   if( IsNull( sec->cryptkey ) ) {
dbf6b5 ¤   ¤   ¤   sec->cryptkey = (PGPByte *)
477694 ¤   ¤   ¤   ¤   pgpContextMemAlloc( sec->context, len, 0 );
9d5c6f ¤   ¤   ¤   if( IsNull( sec->cryptkey ) ) {
d0bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
55a3a6 ¤   ¤   ¤   }
7045a6 ¤   ¤   } else {
71da85 ¤   ¤   ¤   err = pgpContextMemRealloc( sec->context,
68a54f ¤   ¤   ¤   ¤   (void **)&sec->cryptkey, len, 0 );
1d0fe4 ¤   ¤   }
0f37b3 ¤   ¤   if( IsPGPError( err ) ) {
595d4c ¤   ¤   ¤   PGPFreeCFBContext(cfb);
9c4835 ¤   ¤   ¤   pgpS2Kdestroy(s2k);
18b32f ¤   ¤   ¤   return err;
bb0fe4 ¤   ¤   }
9878cc ¤   ¤   sec->ckalloc = (size_t)len;
319371 ¤   }
4e6cd9 ¤   sec->cklen = len;
2fa8ca ¤   p = sec->cryptkey;
6daf5a
7e14eb ¤   /* Okay, no more errors possible! ··Start installing data */
3a461e ¤   p += pgpBnPutPlain(&sec->s.n, p);
9a309c ¤   p += pgpBnPutPlain(&sec->s.e, p);
16af5a
13c4c6 ¤   /* Encryption parameters */
8f9f26 ¤   if (!phrase) {
--7b26 0004436c0b340100221 Page 18 of pgpRSAKey.c
c77625 ¤   ¤   *p++ = 0;¤  /* Unencrypted */
42f037 ¤   } else {
d734b3 ¤   ¤   if (oldf) {
6ece24 ¤   ¤   ¤   *p++ = cipher->algorithm;
5945a6 ¤   ¤   } else {
aa0c31 ¤   ¤   ¤   *p++ = 255;
94ce24 ¤   ¤   ¤   *p++ = cipher->algorithm;
5d682f ¤   ¤   ¤   memcpy(p, s2k->encoding, s2k->encodelen);
42cb5d ¤   ¤   ¤   p += s2k->encodelen;
c80fe4 ¤   ¤   }
1ef1d5 ¤   ¤   /* Create IV */
ce8277 ¤   ¤   pgpRandomGetBytes(rc, p, cipher->blocksize);
d04eef ¤   ¤   /* Use data buffer as temp holding space for key */
fd6961 ¤   ¤   pgpAssert(sec->ckalloc-cipher->blocksize >= cipher->keysize);
05ff98 ¤   ¤   pgpStringToKey(s2k, phrase, plen, p+cipher->blocksize,
35ecbe ¤   ¤   ¤   cipher->keysize);
dc1e9c ¤   ¤   PGPInitCFB(cfb, p+cipher->blocksize, p);
ebe56b ¤   ¤   pgpS2Kdestroy(s2k);
38d63b ¤   ¤   p += cipher->blocksize;
0f1b01 ¤   ¤   /* Wipe key *immediately* */
c9ab67 ¤   ¤   pgpClearMemory( p, ·cipher->keysize);
7b9371 ¤   }
6caf5a
842ed3 ¤   /* Now install d, p, q and u, encrypted */
d6a2f0 ¤   checksum = 0;
4fad9c ¤   p += pgpBnPut(&sec->s.d, p, cfb, &checksum, sec->v3);
b63652 ¤   p += pgpBnPut(&sec->s.p, p, cfb, &checksum, sec->v3);
574130 ¤   p += pgpBnPut(&sec->s.q, p, cfb, &checksum, sec->v3);
6b94a9 ¤   p += pgpBnPut(&sec->s.u, p, cfb, &checksum, sec->v3);
f58ff9 ¤   pgpChecksumPutOld(checksum, p, cfb);
8f930f ¤   p += 2;
76d0ef ¤   pgpAssert((ptrdiff_t)len == p - sec->cryptkey);
3aaf5a
25afda ¤   if (cfb)
79d6b0 ¤   ¤   PGPFreeCFBContext(cfb);
5129fb ¤   return 0;¤  /* Success */
7aefe6 }
800ccc #if PGP_MACINTOSH
4fe4a1 #pragma global_optimizer reset
897454 #endif
66af5a
e25d09 static size_t
1cc670 rsaSecBufferLength(PGPSecKey const *seckey)
a3bb36 {
6bdb89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
6aaf5a
f2b0e6 ¤   return sec->cklen;
83efe6 }
d5af5a
df2978 static void
c1418f rsaSecToBuffer(PGPSecKey const *seckey, PGPByte *buf)
abbb36 {
9fdb89 ¤   RSAsecPlus const *sec = (RSAsecPlus *)seckey->priv;
88af5a
220030 ¤   memcpy(buf, sec->cryptkey, sec->cklen);
1defe6 }
88af5a
46f03c /* Fill in secret key structure */
952978 static void
cadf1c rsaFillSecKey(PGPSecKey *seckey, RSAsecPlus *sec)
d7bb36 {
726654 ¤   seckey->pkAlg¤  ············= kPGPPublicKeyAlgorithm_RSA;
15ba80 ¤   seckey->priv¤   ············= sec;
d5d9e7 ¤   seckey->destroy ············= rsaSecDestroy;
4a32d1 ¤   seckey->pubkey ·············= rsaPubkey;
d15c76 ¤   seckey->islocked ···········= rsaIslocked;
a76bf2 ¤   seckey->lockingalgorithm ···= rsaLockingAlgorithm;
b63206 ¤   seckey->s2ktype ············= rsaS2KType;
9ec9b7 ¤   seckey->convertpassphrase ··= rsaConvertPassphrase;
ab33c7 ¤   seckey->unlock ·············= rsaUnlock;
0dafa7 ¤   seckey->lock ···············= rsaLock;
44e5db ¤   seckey->decrypt ············= rsaDecrypt;
--6911 00015d9ee1c40100221 Page 19 of pgpRSAKey.c
f850e5 ¤   seckey->maxdecrypted ·······= rsaSecMaxdecrypted;
437971 ¤   seckey->maxsig ·············= rsaSecMaxsig;
25f5bf ¤   seckey->maxesk ·············= rsaSecMaxesk;
95113b ¤   seckey->sign ···············= rsaSign;
3b0e60 ¤   seckey->changeLock ·········= rsaChangeLock;
791d79 ¤   seckey->bufferLength ·······= rsaSecBufferLength;
2c9f26 ¤   seckey->toBuffer ···········= rsaSecToBuffer;
0aefe6 }
ceaf5a
50af5a
6e521e PGPSecKey *
0a50f4 rsaSecFromBuf(
20520e ¤   PGPContextRef¤  context,
a44d2b ¤   PGPByte const *¤buf,
cb39e0 ¤   size_t¤ ¤   ¤   size,
82bf97 ¤   PGPBoolean¤ ¤   v3,
276429 ¤   PGPError *¤ ¤   error)
a9bb36 {
b14bdc ¤   PGPSecKey *seckey;
819870 ¤   RSAsecPlus *sec;
06e99a ¤   PGPByte *cryptk;
1c4c08 ¤   PGPError¤   err¤= kPGPError_OutOfMemory;
c1f9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
88ca2b ¤   PGPEnv *¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( context );
49af5a
74bac4 ¤   bnInit();
d2dfb5 ¤   cryptk = (PGPByte *)pgpContextMemAlloc(context,
662217 ¤   ¤   size, kPGPMemoryMgrFlags_Clear);
ec7809 ¤   if (cryptk) {
4be85b ¤   ¤   sec = (RSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
676492 ¤   ¤   if (sec) {
55ae3f ¤   ¤   ¤   pgpClearMemory( sec, sizeof(*sec) );
be2da8 ¤   ¤   ¤   sec->context¤   = context;
ed4d30 ¤   ¤   ¤   sec->v3¤¤   ¤   = v3;
0af3b7 ¤   ¤   ¤   seckey = (PGPSecKey *)
b54d96 ¤   ¤   ¤   ¤   pgpContextMemAlloc(context,
ab480b ¤   ¤   ¤   ¤   ¤   sizeof(*seckey), kPGPMemoryMgrFlags_Clear);
3d1bb1 ¤   ¤   ¤   if (seckey) {
e8e337 ¤   ¤   ¤   ¤   seckey->context¤= context;
672b85 ¤   ¤   ¤   ¤
55bc41 ¤   ¤   ¤   ¤   memcpy(cryptk, buf, size);
a65e2c ¤   ¤   ¤   ¤   bnBegin(&sec->s.n, mgr, FALSE);
6194c9 ¤   ¤   ¤   ¤   bnBegin(&sec->s.e, mgr, FALSE);
0a8fd5 ¤   ¤   ¤   ¤   bnBegin(&sec->s.d, mgr, TRUE);
fa0588 ¤   ¤   ¤   ¤   bnBegin(&sec->s.p, mgr, TRUE);
a34da2 ¤   ¤   ¤   ¤   bnBegin(&sec->s.q, mgr, TRUE);
3c651b ¤   ¤   ¤   ¤   bnBegin(&sec->s.u, mgr, TRUE);
0a4699 ¤   ¤   ¤   ¤   sec->cryptkey = cryptk;
59b1a8 ¤   ¤   ¤   ¤   sec->cklen = sec->ckalloc = size;
4c6564 ¤   ¤   ¤   ¤   sec->locked = 1;
4cbc1d ¤   ¤   ¤   ¤   /* We only need this to try unlocking... */
4d0227 ¤   ¤   ¤   ¤   seckey->pkAlg = kPGPPublicKeyAlgorithm_RSA;
5422e9 ¤   ¤   ¤   ¤   seckey->priv = sec;
f22b85 ¤   ¤   ¤   ¤
3bed17 ¤   ¤   ¤   ¤   if (rsaUnlock(seckey, pgpEnv, NULL, 0, FALSE) >= 0) {
c1d35c ¤   ¤   ¤   ¤   ¤   if (rsaKeyTooBig (NULL, &sec->s) ||
7a91f5 ¤   ¤   ¤   ¤   ¤   ¤   bnBits(&sec->s.n) > 2048) {
931011 ¤   ¤   ¤   ¤   ¤   ¤   bnEnd (&sec->s.n);
cfd004 ¤   ¤   ¤   ¤   ¤   ¤   bnEnd (&sec->s.e);
e31c30 ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_KeyTooLarge;
3581a1 ¤   ¤   ¤   ¤   ¤   } else {
275522 ¤   ¤   ¤   ¤   ¤   ¤   rsaFillSecKey(seckey, sec);
99bf96 ¤   ¤   ¤   ¤   ¤   ¤   *error = 0;
5d0a17 ¤   ¤   ¤   ¤   ¤   ¤   return seckey;¤ /* Success! */
8f1c89 ¤   ¤   ¤   ¤   ¤   }
c12613 ¤   ¤   ¤   ¤   }
d1af5a
9026c6 ¤   ¤   ¤   ¤   /* Ka-boom. ·Delete and free everything. */
8ed423 ¤   ¤   ¤   ¤   pgpClearMemory( cryptk, ·size);
cf3e32 ¤   ¤   ¤   ¤   pgpContextMemFree( context, seckey);
51a3a6 ¤   ¤   ¤   }
1546d9 ¤   ¤   ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
--fab6 0001bb6596d40100221 Page 20 of pgpRSAKey.c
b50fe4 ¤   ¤   }
b73d5f ¤   ¤   pgpContextMemFree(context, cryptk);
269371 ¤   }
4aab59 ¤   *error = err;
373f59 ¤   return NULL;
35efe6 }
19af5a
dccfc4 #if PGP_RSA_KEYGEN
7faf5a
d038e5 /*
1f92e0 ·* PGPRandomContext to use for primeGen callback. ·We really should enhance
bae670 ·* primeGen to pass an arg parameter along with the limit value.
20495d ·*/
1168e5 static PGPRandomContext const *staticrc;
16af5a
ac6c4a /* Random callback for primeGen */
46f3a9 static unsigned randcallback(unsigned limit)
f8bb36 {
4f062d ¤   return pgpRandomRange(staticrc, limit);
bdefe6 }
4daf5a
5738e5 /*
5ba8f2 ·* Generate an RSA secret key with modulus of the specified number of bits.
05e919 ·* We choose public exponent from the #define value above.
ff278d ·* The high two bits of each prime are always
2d7125 ·* set to make the number more difficult to factor by forcing the
a7eca7 ·* number into the high end of the range.
16dce8 ·* Make callbacks to progress function periodically.
537af8 ·* Secret key is returned in the unlocked form, with no passphrase set.
6f9e6e ·* fastgen is an unused flag which is used by the discrete log keygens to
e27e7d ·* allow use of canned primes.
3a495d ·*/
af521e PGPSecKey *
79367e rsaSecGenerate(
fa520e ¤   PGPContextRef¤  context,
028285 ¤   unsigned bits, PGPBoolean fastgen,
aa4b45 ¤   PGPRandomContext const *rc,
8b02ee ¤   int progress(void *arg, int c), void *arg, PGPError *error)
99bb36 {
6b4bdc ¤   PGPSecKey *seckey;
309870 ¤   RSAsecPlus *sec;
73a446 ¤   BigNum t;¤  ¤   /* temporary */
9eff6a ¤   unsigned ent;¤  ¤   ¤   /* Entropy */
004ba4 ¤   int i;
4e38dd ¤   int exp = RSA_DEFAULT_EXPONENT;
6df9b8 ¤   PGPMemoryMgrRef¤¤   mgr¤= PGPGetContextMemoryMgr( context );
d8ca2b ¤   PGPEnv *¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( context );
3baf5a
531cd8 ¤   (void) fastgen;
0caf5a
759096 ¤   *error = kPGPError_NoErr;
b4af5a
93208e ¤   /* Initialize local pointers (simplify cleanup below) */
ef3670 ¤   seckey = NULL;
db2d16 ¤   sec = NULL;
af56d8 ¤   bnBegin(&t, mgr, TRUE);
06af5a
700e57 ¤   /* Allocate data structures */
638164 ¤   seckey = (PGPSecKey *)pgpContextMemAlloc( context,·
eae45a ¤   ¤   sizeof(*seckey), kPGPMemoryMgrFlags_Clear );
822672 ¤   if (!seckey)
58718c ¤   ¤   goto memerror;
3120f7 ¤   seckey->context¤= context;
47fd78 ¤   sec = (RSAsecPlus *)PGPNewSecureData( mgr, sizeof(*sec), 0 );
a865c7 ¤   if (!sec)
c1718c ¤   ¤   goto memerror;
05e024 ¤   sec->context¤   = context;
f0a867 ¤   sec->v3¤¤   ¤   = TRUE;
0367c5 ¤
4724be ¤   /* n is not inherently sensitive, but holds sensitive intermediates */
cf90d4 ¤   bnBegin(&sec->s.n, mgr, TRUE);
1bc1aa ¤   bnBegin(&sec->s.e, mgr, FALSE);
--766a 0005cf410be40100221 Page 21 of pgpRSAKey.c
cd51f2 ¤   bnBegin(&sec->s.d, mgr, TRUE);
8cdbaf ¤   bnBegin(&sec->s.p, mgr, TRUE);
939385 ¤   bnBegin(&sec->s.q, mgr, TRUE);
26bb3c ¤   bnBegin(&sec->s.u, mgr, TRUE);
6967c5 ¤
57e0e7 ¤   if (bnSetQ(&sec->s.e, exp))
9a2921 ¤   ¤   goto bnerror;
6daf5a
b02820 ¤   /* Find p - choose a starting place */
500766 ¤   if (pgpBnGenRand(&sec->s.p, rc, bits/2, 0xC0, 1, bits/2-3) < 0)
b12921 ¤   ¤   goto bnerror;
b2af5a
4c9b4f ¤   /* And search for a prime */
fdd46f ¤   staticrc = rc;
b2b53d ¤   i = bnPrimeGen(&sec->s.p, randcallback, progress, arg, exp, 0);
094fd6 ¤   if (i < 0)
7b2921 ¤   ¤   goto bnerror;
cd45ab ¤   pgpAssert(bnModQ(&sec->s.p, exp) != 1);
c8af5a
81b5e1 ¤   /* Make sure p and q aren't too close together */
7aaf5a
9c5e9b ¤   /* Bits of entropy needed to generate q. */
329cec ¤   ent = (bits+1)/2 - 3;
fdeb79 ¤   /* Pick random q until we get one not too close to p */
f443ab ¤   do {
fca51b ¤   ¤   /* Visual separator between the two progress indicators */
6f2c8a ¤   ¤   if (progress)
c84d62 ¤   ¤   ¤   progress(arg, ' ');
c4ba55 ¤   ¤   if (pgpBnGenRand(&sec->s.q, rc, (bits+1)/2, 0xC0, 1, ent) < 0)
94ee94 ¤   ¤   ¤   goto bnerror;
1a9e89 ¤   ¤   ent = 0;¤   /* No entropy charge next time around */
5d731b ¤   ¤   if (bnCopy(&sec->s.n, &sec->s.q) < 0)
54ee94 ¤   ¤   ¤   goto bnerror;
4eb3a0 ¤   ¤   if (bnSub(&sec->s.n, &sec->s.p) < 0)
a4ee94 ¤   ¤   ¤   goto bnerror;
787d1a ¤   ¤   /* Note that bnSub(a,b) returns abs(a-b) */
316578 ¤   } while (bnBits(&sec->s.n) < bits/2-5);
bdaf5a
7a2bea ¤   i = bnPrimeGen(&sec->s.q, randcallback, progress, arg, exp, 0);
184fd6 ¤   if (i < 0)
a22921 ¤   ¤   goto bnerror;
b545ab ¤   pgpAssert(bnModQ(&sec->s.p, exp) != 1);
fdaf5a
8db30b ¤   /* Wash the random number pool. */
60b052 ¤   pgpRandomStir(rc);
47af5a
024099 ¤   /* Ensure that q is larger */
39a524 ¤   if (bnCmp(&sec->s.p, &sec->s.q) > 0)
4767e1 ¤   ¤   bnSwap(&sec->s.p, &sec->s.q);
90af5a
afd8af ¤   /*
2ae45f ¤   ·* Now we compute d,
bdc6a3 ¤   ·* the decryption exponent, from the encryption exponent.
78a4e3 ¤   ·*/
97af5a
d6d3e6 ¤   /* Decrement q temporarily */
0c15cf ¤   (void)bnSubQ(&sec->s.q, 1);
6f9645 ¤   /* And u = p-1, to be divided by gcd(p-1,q-1) */
e9b0ae ¤   if (bnCopy(&sec->s.u, &sec->s.p) < 0)
072921 ¤   ¤   goto bnerror;
d07ab9 ¤   (void)bnSubQ(&sec->s.u, 1);
cbaf5a
980166 ¤   /* Use t to store gcd(p-1,q-1) */
2e18b0 ¤   if (bnGcd(&t, &sec->s.q, &sec->s.u) < 0) {
b62921 ¤   ¤   goto bnerror;
ee9371 ¤   }
acaf5a
8bb8b8 ¤   /* Let d = (p-1) / gcd(p-1,q-1) (n is scratch for the remainder) */
4d5fb9 ¤   i = bnDivMod(&sec->s.d, &sec->s.n, &sec->s.u, &t);
a44fd6 ¤   if (i < 0)
a62921 ¤   ¤   goto bnerror;
5c5845 ¤   pgpAssert(bnBits(&sec->s.n) == 0);
--4f3a 00148114e4e40100221 Page 22 of pgpRSAKey.c
e0af5a
be16e1 ¤   /* Now we have q-1 and d = (p-1) / gcd(p-1,q-1) */
a22ab9 ¤   /* Find the product, n = lcm(p-1,q-1) = c * d */
18161a ¤   if (bnMul(&sec->s.n, &sec->s.q, &sec->s.d) < 0)
6a2921 ¤   ¤   goto bnerror;
dbaf5a
48e75d ¤   /* Find the inverse of the exponent mod n */
845d5e ¤   i = bnInv(&sec->s.d, &sec->s.e, &sec->s.n);
254fd6 ¤   if (i < 0)
c22921 ¤   ¤   goto bnerror;
c741ca ¤   pgpAssert(!i);¤ /* We should NOT get an error here */
c6af5a
23d8af ¤   /*
cb71b6 ¤   ·* Now we have the comparatively simple task of computing
06afad ¤   ·* u = p^-1 mod q.
03a4e3 ¤   ·*/
15af5a
17ad71 ¤   /* But it *would* be nice to have q back first. */
09d3ff ¤   (void)bnAddQ(&sec->s.q, 1);
07af5a
04e87b ¤   /* Now compute u = p^-1 mod q */
2596ed ¤   i = bnInv(&sec->s.u, &sec->s.p, &sec->s.q);
8d4fd6 ¤   if (i < 0)
e12921 ¤   ¤   goto bnerror;
61bd77 ¤   pgpAssert(!i);¤ /* p and q had better be relatively prime! */
94af5a
f89f5c ¤   /* And finally, ·n = p * q */
b3494a ¤   if (bnMul(&sec->s.n, &sec->s.p, &sec->s.q) < 0)
d72921 ¤   ¤   goto bnerror;
79af5a
641fb6 ¤   /* And that's it... success! */
13af5a
262d0e ¤   /* Fill in structs */
16c257 ¤   sec->cryptkey = NULL;
95a3cb ¤   sec->ckalloc = sec->cklen = 0;
cf0162 ¤   sec->locked = 0;
5b1dfc ¤   rsaFillSecKey(seckey, sec);
5eaf5a
bbb736 ¤   /* Fill in cryptkey structure, unencrypted */
c667ec ¤   rsaChangeLock (seckey, pgpEnv, rc, NULL, 0, kPGPStringToKey_Simple);
95af5a
2bc48e ¤   goto done;
57af5a
a20953 bnerror:
1a5f90 ¤   bnEnd(&sec->s.n);
a19f85 ¤   bnEnd(&sec->s.e);
28833e ¤   bnEnd(&sec->s.d);
363273 ¤   bnEnd(&sec->s.p);
f72ec8 ¤   bnEnd(&sec->s.q);
455c24 ¤   bnEnd(&sec->s.u);
3591b1 ¤   /* Fall through */
e1623d memerror:
2754f2 ¤   if ( IsntNull( seckey ) )
f83fb4 ¤   ¤   pgpContextMemFree( context, seckey);
e66101 ¤   if ( IsntNull( sec ) )
0c82c5 ¤   ¤   PGPFreeData( sec );¤¤   ¤   /* Wipes as it frees */
443670 ¤   seckey = NULL;
9c27b8 ¤   *error = kPGPError_OutOfMemory;
3191b1 ¤   /* Fall through */
a0b38c done:
63904b ¤   bnEnd(&t);
624d98 ¤   return seckey;
79efe6 }
c4af5a
73a34f #endif /* PGP_RSA_KEYGEN */
e3af5a
e0af5a
487ead #endif /* PGP_RSA */
--828c 001061fd75140100222 Page 1 of pgpRSAKey.h
bc38e5 /*
a1f8c5 ·* $Id: pgpRSAKey.h,v 1.14 1998/06/11 18:28:23 hal Exp $
23495d ·*/
36af5a
9de663 #ifndef Included_pgpRSAKey_h
5a6755 #define Included_pgpRSAKey_h
eaaf5a
77af5a
2d3051 #include "pgpSDKBuildFlags.h"
9baf5a
1ebe7a #ifndef PGP_RSA
5f31da #error "PGP_RSA requires a value"
667454 #endif
80af5a
0199a4 #if PGP_RSA
9faf5a
190e50 #include "pgpPubTypes.h"¤   /* For PGPBoolean and PGPByte */
bbadb8 #include "pgpOpaqueStructs.h"
3caf5a
0c99c6 PGP_BEGIN_C_DECLARATIONS
1baf5a
80faf7 PGPPubKey *rsaPubFromBuf(PGPContextRef¤ context,
d7fe12 ¤   ¤   ¤   ¤   PGPByte const *buf, size_t len, PGPError *error);
0d2b85 ¤   ¤   ¤   ¤
670f76 PGPSecKey *rsaSecFromBuf( PGPContextRef¤context,
9d3d95 ¤   ¤   ¤   ¤   PGPByte const *buf, size_t len, PGPBoolean v3,
757960 ¤   ¤   ¤   ¤   PGPError *error);
fd2b85 ¤   ¤   ¤   ¤
74cf8f int rsaPubKeyPrefixSize(PGPByte const *buf, size_t size);
a8af5a
267249 PGPSecKey *rsaSecGenerate( PGPContextRef¤   context,
b3c5e3 ¤   ¤   ¤   ¤   unsigned bits, PGPBoolean fastgen,
af8d8a ¤   ¤   ¤   ¤   PGPRandomContext const *rc,
b51ebb ¤   ¤   ¤   ¤   int progress(void *arg, int c), void *arg, PGPError *error);
25af5a
5d1254 PGP_END_C_DECLARATIONS
ccaf5a
727ead #endif /* PGP_RSA */
70af5a
061305 #endif /* Included_pgpRSAKey_h */
--0261 0005c21ed8440100223 Page 1 of pgpSig.c
bc38e5 /*
6807bd ·* $Id: pgpSig.c,v 1.22 1998/06/11 18:28:23 hal Exp $
b6495d ·*/
19af5a
95e2ff #include "pgpConfig.h"
1f324c #include <string.h>
80af5a
d5a146 #include "pgpDebug.h"
d70d08 #include "pgpMem.h"
f3ba29 #include "pgpPktList.h"
6543bc #include "pgpSig.h"
3e6aaa #include "pgpAnnotate.h"
215417 #include "pgpHashPriv.h"
972f8d #include "pgpErrors.h"
99cdc2 #include "pgpPubKey.h"
ecd11f #include "pgpUsuals.h"
237ca7 #include "pgpKeyIDPriv.h"
832e22 #include "pgpRngPars.h"
0baf5a
c0e6a2 #define SIGBUF_1PASS(b,l) (((l) == 13) && ((b)[0] == PGPVERSION_3))
524187 #define SIGPKT_1PASS(p) SIGBUF_1PASS((p)->pkt.buf,(p)->pkt.len)
e7af5a
a7af5a
050e4f struct PGPSig
ecbb36 {
d57de6 ¤   PktList pkt;
282fa1 } ;
efaf5a
3138e5 /*
f9b783 ·* Format of one-pass signature packets:
d3775e ·*
fa63e8 ·* ·····Offset ·Length ·Meaning
9a8950 ·* ······0 ·····1 ······Version byte (=3)
828974 ·* ······1 ·····1 ······Signature type
dc737d ·* ······2 ·····1 ······Hash Algorithm
d8775e ·* ······3 ·····1 ······PK Algorithm
655f3c ·* ······4 ·····8 ······KeyID
20fc20 ·* ······12 ····1 ······nested flag
3e775e ·*
c8775e ·*
294fb1 ·* Format of regular signature packets:
28775e ·*
a863e8 ·* ·····Offset ·Length ·Meaning
8ac17b ·* ·····0 ······1 ······Version byte (= 2 or 3).
eaf233 ·* ·····1 ······1 ······x, Length of following material included in MD5 (=5)
9f5b6c ·* ·····2 ······1 ······Signature type (=0 or 1)
ab9b10 ·* ·····3 ······4 ······32-bit timestamp of signature
38bce1 ·* -------- MD5 additional material stops here, at offset 2+x ---------
2e5404 ·* ·····2+x ····8 ······KeyID
199651 ·* ·····10+x ···1 ······PK algorithm type (1 = RSA)
8e4a74 ·* ·····11+x ···1 ······MD algorithm type (1 = MD5)
8b3387 ·* ·····12+x ···2 ······First 2 bytes of message digest (16-bit checksum)
0a0d38 ·* ·····14+x ···2+y ····MPI of PK-encrypted integer
bd6800 ·* ·····16+x+y ·
28495d ·*/
adbeb7 static int
f3e3dd sigValidate(PGPByte const *sig, size_t len, PGPByte *pkalg)
d6bb36 {
01fe44 ¤   unsigned extra, bits;
c7afba ¤   PGPByte alg;
a83d22 ¤   PGPHashVTBL const *hash;
60af5a
c513a1 ¤   if (pkalg)
da1e51 ¤   ¤   *pkalg = 0;
9f0ece ¤   if (len < 1)
bec86c ¤   ¤   return kPGPError_BadSignatureSize;
da5c28 ¤   if (SIGBUF_1PASS(sig, len)) {
17643b ¤   ¤   /* One-pass signature packet */
f34508 ¤   ¤   if (len < 13)
a359f4 ¤   ¤   ¤   return kPGPError_BadSignatureSize;
294d5e ¤   ¤   if (len > 13)
5c59f4 ¤   ¤   ¤   return kPGPError_BadSignatureSize;
--5b5e 0002d57819640100223 Page 2 of pgpSig.c
050cbe ¤   ¤   alg = sig[3];
88f102 ¤   ¤   if (pkalg)
3c0f16 ¤   ¤   ¤   *pkalg = alg;
f8fd5c ¤   ¤   hash = pgpHashByNumber( (PGPHashAlgorithm) sig[2]);
6d2bfa ¤   ¤   if (!hash)
82ce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
33bbde ¤   ¤   return 0;
65548d ¤   } else if (sig[0] == PGPVERSION_4) {
8fdd3b ¤   ¤   /* New-format key signature packet - validated in pgpRngPars.c */
73bbde ¤   ¤   return 0;
c09371 ¤   }
dfca49 ¤   if (sig[0] != PGPVERSION_2 && sig[0] != PGPVERSION_3)
90333f ¤   ¤   return kPGPError_UnknownVersion;
a5e1aa ¤   if (len < 2)
b7c86c ¤   ¤   return kPGPError_BadSignatureSize;
767507 ¤   extra = sig[1];
eba6c6 ¤   if (len < 11+extra)
dec86c ¤   ¤   return kPGPError_BadSignatureSize;
b9f063 ¤   alg = sig[10+extra];
5413a1 ¤   if (pkalg)
e9c8a3 ¤   ¤   *pkalg = alg;
b2b177 #if 0
a438e5 /*
fb0a92 ·* Don't abort on bad hash as it may be for an alg we don't support yet.
c01a7a ·* Aborting here interferes with importing keys which have sigs with bad
1ab645 ·* hashes. ·Even though we can't check those sigs, we should still import
abae04 ·* the key.
f4495d ·*/
e14204 ¤   hash = pgpHashByNumber( (PGPHashAlgorithm) ( sig[11+extra] ) );
fbc959 ¤   if (!hash)
b0467c ¤   ¤   return kPGPError_BadHashNumber;
137454 #endif
929907 ¤   /* This part here gets RSA-specific */
cb4f24 ¤   if (len < 16+extra)
a5c86c ¤   ¤   return kPGPError_BadSignatureSize;
5f6f80 ¤   if (alg==kPGPPublicKeyAlgorithm_RSA) {
6543cb ¤   ¤   bits = ((unsigned)sig[14+extra]<<8) + sig[15+extra];
b8ed6f ¤   ¤   if (len != 16+extra+(bits+7)/8)
7b8335 ¤   ¤   ¤   return len < 16+extra+(bits+7)/8 ? kPGPError_BadSignatureSize
9540bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·: kPGPError_BadSignatureSize;
45c657 ¤   ¤   if (bits && sig[16+extra] >> ((bits-1) & 7) != 1)
38c9ff ¤   ¤   ¤   return kPGPError_SignatureBitsWrong;
2d9371 ¤   }
6c3e6b ¤   return 0;
afefe6 }
38af5a
673106 static PGPSig **
c04a23 sigListTail(PGPSig **head)
01bb36 {
621e6d ¤   while (*head)
72c167 ¤   ¤   head = (PGPSig **)&(*head)->pkt.next;
a0b737 ¤   return head;
c2efe6 }
0faf5a
5b4d2f int
c9c359 pgpSigSigType (PGPByte const *buf, size_t len)
d8bb36 {
cb4ba4 ¤   int i;
7caf5a
f55ae9 ¤   i = sigValidate(buf, len, NULL);
264fd6 ¤   if (i < 0)
1ea423 ¤   ¤   return i;
0c4c86 ¤   if (SIGBUF_1PASS(buf, len)) {
cb1e89 ¤   ¤   return buf[1];
4402d1 ¤   } else if (buf[0] == PGPVERSION_4) {
031e89 ¤   ¤   return buf[1];
b39371 ¤   }
655770 ¤   if (buf[1] < 1)
d32f88 ¤   ¤   return kPGPError_ExtraDateOnSignature;
56bccf ¤   return buf[2] & 255;
55efe6 }
2daf5a
--ae46 0008d625ec840100223 Page 3 of pgpSig.c
af4d2f int
7a3a51 pgpSigAdd (
213163 ¤   PGPContextRef¤  cdkContext,
31c74f ¤   PGPSig **siglist, int type, PGPByte const *buf, size_t len)
7bbb36 {
edadc7 ¤   PGPSig *sig;
5212b9 ¤   PGPSig **psig2;
5dc163 ¤   PGPByte pkalg, sigtype, hashalg, keyid[8];
053d68 ¤   PGPByte *b2;
a017e6 ¤   int err;
c1af5a
ad1609 ¤   switch (type) {
9110ec ········case PGPANN_SIGNED_SIG:
3c308c ¤   ¤   err = sigValidate (buf, len, &pkalg);
e4150b ¤   ¤   if (err)
08b32f ¤   ¤   ¤   return err;
6e5652 ¤   ¤   sig = (PGPSig *)pgpPktListNew( cdkContext, pkalg, buf, len);
f51427 ¤   ¤   if (!sig)
957cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
b8aa3d ¤   ¤   *sigListTail(siglist) = sig;
74bbde ¤   ¤   return 0;
e48017 ¤   case PGPANN_SIGNED_SIG2:
e7dd9e ¤   ¤   /* Second packet, should be merged with an existing one */
b0067a ¤   ¤   if (SIGBUF_1PASS(buf, len))
b29fbc ¤   ¤   ¤   return kPGPError_UnknownSignatureType;
b63a43 ¤   ¤   if (buf[1] != 5) /* extra bytes must be standard */
209fbc ¤   ¤   ¤   return kPGPError_UnknownSignatureType;
af308c ¤   ¤   err = sigValidate (buf, len, &pkalg);
60150b ¤   ¤   if (err)
24b32f ¤   ¤   ¤   return err;
7a9d36 ¤   ¤   /* Search for matching 1-pass signature on the list */
5b6386 ¤   ¤   if (buf[0] == PGPVERSION_3) {
02020f ¤   ¤   ¤   for (psig2=siglist; *psig2;
6e0399 ¤   ¤   ¤   ¤   ·¤  ¤   psig2 = (PGPSig **)&(*psig2)->pkt.next) {
adac40 ¤   ¤   ¤   ¤   if (!SIGPKT_1PASS(*psig2))
6c5914 ¤   ¤   ¤   ¤   ¤   continue;
9be45e ¤   ¤   ¤   ¤   b2 = (*psig2)->pkt.buf;
107c17 ¤   ¤   ¤   ¤   if (b2[1] != buf[2]) /* sig type */
985914 ¤   ¤   ¤   ¤   ¤   continue;
4416e7 ¤   ¤   ¤   ¤   if (b2[2] != buf[11+buf[1]]) /* hash alg */
655914 ¤   ¤   ¤   ¤   ¤   continue;
c36f5e ¤   ¤   ¤   ¤   if (b2[3] != buf[10+buf[1]])/* pkalg */
0b5914 ¤   ¤   ¤   ¤   ¤   continue;
73a1d5 ¤   ¤   ¤   ¤   if (memcmp(b2+4, buf+2+buf[1], 8)) /* key id */
ae5914 ¤   ¤   ¤   ¤   ¤   continue;
6eb84a ¤   ¤   ¤   ¤   /* Here we have a match */
c6f622 ¤   ¤   ¤   ¤   break;
87a3a6 ¤   ¤   ¤   }
dc45a6 ¤   ¤   } else {
7d1e95 ¤   ¤   ¤   /* V4 signatures */
b123aa ¤   ¤   ¤   pgpAssert (buf[0] == PGPVERSION_4);
12efba ¤   ¤   ¤   err = ringSigParse(buf, len, &pkalg, keyid, NULL, NULL,
467e80 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&sigtype, &hashalg, NULL, NULL, NULL,
694f4a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL, NULL, NULL, NULL);
eb8813 ¤   ¤   ¤   if (IsPGPError( err ) )
6d454a ¤   ¤   ¤   ¤   return err;
13af5a
2e020f ¤   ¤   ¤   for (psig2=siglist; *psig2;
a5f670 ¤   ¤   ¤   ¤   ¤   ¤   psig2 = (PGPSig **)&(*psig2)->pkt.next) {
93ac40 ¤   ¤   ¤   ¤   if (!SIGPKT_1PASS(*psig2))
cc5914 ¤   ¤   ¤   ¤   ¤   continue;
69e45e ¤   ¤   ¤   ¤   b2 = (*psig2)->pkt.buf;
c16791 ¤   ¤   ¤   ¤   if (b2[1] != sigtype) /* sig type */
e45914 ¤   ¤   ¤   ¤   ¤   continue;
356f53 ¤   ¤   ¤   ¤   if (b2[2] != hashalg) /* hash alg */
1b5914 ¤   ¤   ¤   ¤   ¤   continue;
e18be8 ¤   ¤   ¤   ¤   if (b2[3] != pkalg)¤/* pkalg */
c65914 ¤   ¤   ¤   ¤   ¤   continue;
1338ed ¤   ¤   ¤   ¤   if (memcmp(b2+4, keyid, 8)) /* key id */
e85914 ¤   ¤   ¤   ¤   ¤   continue;
9ab84a ¤   ¤   ¤   ¤   /* Here we have a match */
8df622 ¤   ¤   ¤   ¤   break;
--dce0 000b099e6a140100223 Page 4 of pgpSig.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
3c4728 ¤   ¤   /* Error if found no match */
4df287 ¤   ¤   if (!*psig2)
639fbc ¤   ¤   ¤   return kPGPError_UnknownSignatureType;
abaf5a
d1d77d ¤   ¤   /* Replace *psig2 with new sig */
235652 ¤   ¤   sig = (PGPSig *)pgpPktListNew( cdkContext, pkalg, buf, len);
c11427 ¤   ¤   if (!sig)
917cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
facc44 ¤   ¤   sig->pkt.next = (*psig2)->pkt.next;
9ba3a3 ¤   ¤   pgpPktListFreeOne((PktList *)*psig2);
d2d10d ¤   ¤   *psig2 = sig;
95af5a
2fbbde ¤   ¤   return 0;
e69371 ¤   }
501b52 ¤   ¤
0c5bb1 ········return kPGPError_UnknownSignatureType;
7fefe6 }
1eaf5a
9f6667 /* Return true if this signature is followed immediately by signed data */
3e4d2f int
eabbc1 pgpSigNestFlag(PGPByte const *buf, size_t len)
dbbb36 {
9ea272 ¤   (void)len;
908d86 ¤   if (SIGBUF_1PASS(buf, len))
e06c53 ¤   ¤   return buf[12];¤/* nest flag */
720e24 ¤   else
d89eb3 ¤   ¤   return 1;¤  /* always true for old packets */
e1efe6 }
57af5a
8e6cf9 /* How here come some access functions */
4d5d74 PGPByte
84579e pgpSigPKAlg(PGPSig const *sig)
6ebb36 {
f177a2 ¤   pgpAssert(sig);
95f674 ¤   if (SIGPKT_1PASS(sig))
ccfc3d ¤   ¤   return sig->pkt.buf[3];
19b11d ¤   else if (sig->pkt.buf[0] == PGPVERSION_4)
7ee086 ¤   ¤   return sig->pkt.buf[2];
fb0e24 ¤   else
4e7f89 ¤   ¤   return sig->pkt.buf[10+sig->pkt.buf[1]];
feefe6 }
5caf5a
4ef0c9 PGPHashVTBL const *
68fc36 pgpSigHash(PGPSig const *sig)
efbb36 {
c2eb3d ¤   int alg;
e8af5a
1077a2 ¤   pgpAssert(sig);
c3f674 ¤   if (SIGPKT_1PASS(sig))
e7d36e ¤   ¤   alg = sig->pkt.buf[2];
59b11d ¤   else if (sig->pkt.buf[0] == PGPVERSION_4)
29cfd5 ¤   ¤   alg = sig->pkt.buf[3];
bc0e24 ¤   else
c12541 ¤   ¤   alg = sig->pkt.buf[11+sig->pkt.buf[1]];
01940e ¤   return pgpHashByNumber( (PGPHashAlgorithm) alg);
26efe6 }
f3af5a
4510b2 PGPByte·
64d76f pgpSigType(PGPSig const *sig)
6dbb36 {
e477a2 ¤   pgpAssert(sig);
602b5d ¤   return (PGPByte)pgpSigSigType (sig->pkt.buf, sig->pkt.len);
51efe6 }
34af5a
f410b2 PGPByte·
2c55c2 pgpSigVersion(PGPSig const *sig)
8cbb36 {
0977a2 ¤   pgpAssert(sig);
1774ae ¤   return sig->pkt.buf[0];
b0efe6 }
--4132 0002aeba87240100223 Page 5 of pgpSig.c
e0af5a
efd929 PGPByte const *
bfa62e pgpSigExtra(PGPSig const *sig, unsigned *len)
31bb36 {
4e77a2 ¤   pgpAssert(sig);
0bce6a ¤   if (SIGPKT_1PASS(sig)) {
1e5afc ¤   ¤   *len = 0;
31bbde ¤   ¤   return 0;
9a0bf7 ¤   } else if (sig->pkt.buf[0] == PGPVERSION_4) {
b88dba ¤   ¤   *len = ((sig->pkt.buf[4] << 8) | sig->pkt.buf[5]) + 6;
6cfd0c ¤   ¤   return sig->pkt.buf;
e3f037 ¤   } else {
ed88de ¤   ¤   *len = sig->pkt.buf[1];
1cfb57 ¤   ¤   return sig->pkt.buf+2;
c79371 ¤   }
17efe6 }
30af5a
1bbccf PGPUInt32
c717f9 pgpSigTimestamp (PGPSig const *sig)
babb36 {
8969cc ¤   PGPByte const *extra;
0327ed ¤   unsigned extralen;
37af5a
872d60 ¤   pgpAssert (sig);
e1f674 ¤   if (SIGPKT_1PASS(sig))
30bbde ¤   ¤   return 0;
74af5a
a74843 ¤   if (sig->pkt.buf[0] == PGPVERSION_4) {
0d2776 ¤   ¤   PGPUInt32 tstamp;
c09b46 ¤   ¤   PGPError err = ringSigParse(sig->pkt.buf, sig->pkt.len, NULL, NULL,
87c55c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &tstamp, NULL, NULL, NULL, NULL, NULL,
7a16ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, NULL, NULL, NULL, NULL);
5803ef ¤   ¤   if (IsPGPError( err ) )
478144 ¤   ¤   ¤   return 0;
da6c74 ¤   ¤   return tstamp;
f19371 ¤   }
ee67c5 ¤
bbdb3c ¤   extra = pgpSigExtra (sig, &extralen);
fe8fb8 ¤   if (!extra || extralen < 5)·
d3bbde ¤   ¤   return 0;
8279b8 ¤   return ((PGPUInt32)extra[1]<<24) + ((PGPUInt32)extra[2]<<16) +
c96eec ¤   ········((PGPUInt32)extra[3]<<8) + (PGPUInt32)extra[4];
5fefe6 }
9baf5a
32af5a
91c744 ¤   PGPError
b8d833 pgpGetSigKeyID(
7c5392 ¤   PGPSig const *¤ sig,
d92b74 ¤   PGPKeyID *¤ ¤   outID )
1cbb36 {
fb26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5f3ae5 ¤   PGPByte¤¤   keyidbuf[8];
a85803 ¤   PGPByte const *rawkeyid;
4b67c5 ¤
f0ce6a ¤   if (SIGPKT_1PASS(sig)) {
129df4 ¤   ¤   rawkeyid = sig->pkt.buf+4;
e60bf7 ¤   } else if (sig->pkt.buf[0] == PGPVERSION_4) {
7db8d6 ¤   ¤   err = ringSigParse(sig->pkt.buf, sig->pkt.len, NULL, keyidbuf,
9fb6c6 ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL, NULL, NULL, NULL, NULL,
629a11 ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL, NULL, NULL, NULL, NULL);
a303ef ¤   ¤   if (IsPGPError( err ) )
42b32f ¤   ¤   ¤   return err;
c1a5e5 ¤   ¤   rawkeyid = keyidbuf;
0ef037 ¤   } else {
153ce7 ¤   ¤   rawkeyid = sig->pkt.buf+2+sig->pkt.buf[1];
599371 ¤   }
2daf5a
a7fd20 ¤   pgpNewKeyIDFromRawData( rawkeyid, 8, outID );
d767c5 ¤
7fdeb7 ¤   return( err );
84efe6 }
2aaf5a
--db4e 00003c213a740100223 Page 6 of pgpSig.c
e0af5a
38c977 /* Return a count of the number of distinct hash algorithms in the list */
59536c unsigned
f903e6 pgpSigDistinctHashCount(PGPSig const *sig)
60bb36 {
4da420 ¤   PktList const *next;
6f7a53 ¤   unsigned total;
a1b25c ¤   int alg, nextalg;
8faf5a
4b6c40 ¤   for (total = 0; sig; sig = (PGPSig const *)sig->pkt.next) {
a3b598 ¤   ¤   total++;
841b17 ¤   ¤   /*
ddffc8 ¤   ¤   ·* If another one later on the list has the same alg,
e606b4 ¤   ¤   ·* don't count this one.
499de3 ¤   ¤   ·*/
15e25c ¤   ¤   if (SIGPKT_1PASS(sig))
735f11 ¤   ¤   ¤   alg = sig->pkt.buf[2];
bcfe23 ¤   ¤   else if (sig->pkt.buf[0] == PGPVERSION_4)
6743aa ¤   ¤   ¤   alg = sig->pkt.buf[3];
1f0e1d ¤   ¤   else
d8b300 ¤   ¤   ¤   alg = sig->pkt.buf[11+sig->pkt.buf[1]];
1fc654 ¤   ¤   for (next = sig->pkt.next; next; next = next->next) {
f01be6 ¤   ¤   ¤   if (SIGBUF_1PASS(next->buf, next->len))
dd7403 ¤   ¤   ¤   ¤   nextalg = next->buf[2];
9660a4 ¤   ¤   ¤   else if (next->buf[0] == PGPVERSION_4)
b568b8 ¤   ¤   ¤   ¤   nextalg = next->buf[3];
c1bb8c ¤   ¤   ¤   else
f4bdf3 ¤   ¤   ¤   ¤   nextalg = next->buf[11+next->buf[1]];
aa87c7 ¤   ¤   ¤
ccda4a ¤   ¤   ¤   if (nextalg == alg) {
1fd881 ¤   ¤   ¤   ¤   total--;
57f622 ¤   ¤   ¤   ¤   break;
7ca3a6 ¤   ¤   ¤   }
3b0fe4 ¤   ¤   }
c09371 ¤   }
b59b53 ¤   return total;
82efe6 }
5caf5a
1638e5 /*
8f2867 ·* Return a buffer full of byte hash identifiers. ·The buffer must be
047f12 ·* of legnth sigDistincthashCount(len) length, and that number is
0f5fc8 ·* returned for convenience.
2c495d ·*/
28536c unsigned
3564f1 pgpSigDistinctHashes(PGPSig const *sig, PGPByte *buf)
82bb36 {
11c6b5 ¤   unsigned len;
b4eb3d ¤   int alg;
6baf5a
c1cec9 ¤   for (len = 0; sig; sig = (PGPSig const *)sig->pkt.next) {
f8e25c ¤   ¤   if (SIGPKT_1PASS(sig))
015f11 ¤   ¤   ¤   alg = sig->pkt.buf[2];
10fe23 ¤   ¤   else if (sig->pkt.buf[0] == PGPVERSION_4)
4d43aa ¤   ¤   ¤   alg = sig->pkt.buf[3];
a50e1d ¤   ¤   else
a8b300 ¤   ¤   ¤   alg = sig->pkt.buf[11+sig->pkt.buf[1]];
4254a6 ¤   ¤   if (!memchr(buf, alg, len))
bf1372 ¤   ¤   ¤   buf[len++] = (PGPByte)alg;
d09371 ¤   }
debb7a ¤   return len;
acefe6 }
90af5a
11af5a
d338e5 /*
9daf48 ·* The internal checking function, not for public use.
b6495d ·*/
8e4d2f int
7d33f4 pgpSigCheckBuf(PGPByte const *sig, PGPSize len, PGPPubKey const *pub,
b4dec3 ¤   ·······void const *hash)
21bb36 {
cc173d ¤   unsigned extra;
03d905 ¤   PGPByte type;
--5708 001edee01ab40100223 Page 7 of pgpSig.c
f8602d ¤   PGPHashVTBL const *h;
33af5a
92ea75 ¤   if (sig[0] == PGPVERSION_4) {
d3efcf ¤   ¤   /* New signature format; see pgpMakeSig.c */
ad978d ¤   ¤   extra = (unsigned)sig[4]<<8 | sig[5];
c1d88f ¤   ¤   extra += (unsigned)sig[extra+6]<<8 | sig[extra+7];
2fa8af ¤   ¤   /* Quick rejection test: check the given two bytes first */
11b4d4 ¤   ¤   if (memcmp (hash, sig+8+extra, 2) != 0)
2e8144 ¤   ¤   ¤   return 0;
12b564 ¤   ¤   h = pgpHashByNumber ( (PGPHashAlgorithm) sig[3]);
e65598 ¤   ¤   type = sig[1];
642149 ¤   ¤   /* Skip to signature data */
406324 ¤   ¤   extra += 10;
93f037 ¤   } else {
400ff3 ¤   ¤   extra = sig[1];
eaa8af ¤   ¤   /* Quick rejection test: check the given two bytes first */
c1e886 ¤   ¤   if (memcmp (hash, sig+12+extra, 2) != 0)
388144 ¤   ¤   ¤   return 0;
6990d4 ¤   ¤   h = pgpHashByNumber ( (PGPHashAlgorithm) ( sig[11+extra] ));
e97055 ¤   ¤   type = sig[2];
2c2149 ¤   ¤   /* Skip to signature data */
300045 ¤   ¤   extra += 14;
bd9371 ¤   }
74af5a
870bc1 ¤   /* XXX Should "die" gracefully here */
1d0bfe ¤   pgpAssert (pub->verify);
aeb835 ¤   return pgpPubKeyVerify (pub, sig+extra, len-extra, h, (PGPByte *) hash,
d7dd80 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyMessageFormat_PGP);
19efe6 }
28af5a
d238e5 /*
ca41a2 ·* Check a signature against a given public key and hash.
818e2c ·* Returns 0 if it did not check, and 1 if it did.
5d1008 ·* Returns <0 on some sort of error.
fee844 ·* (The hash better be the right algorithm.)
23495d ·*/
5b4d2f int
57ff73 pgpSigCheck(PGPSig const *sig, PGPPubKey const *pub,
22d993 ¤   ····PGPByte const *hash)
51bb36 {
d7571b ¤   return pgpSigCheckBuf(sig->pkt.buf, sig->pkt.len, pub, hash);
33efe6 }
b8af5a
1992eb PGPSig *
7118be pgpSigNext (PGPSig const *sig)
76bb36 {
4c90de ¤   if (sig)
7af43d ¤   ¤   return (PGPSig *)sig->pkt.next;
22af5a
fe3f59 ¤   return NULL;
fbefe6 }
a2af5a
51314a void
b4a0fd pgpSigFreeList (PGPSig *siglist)
acbb36 {
313bf7 ¤   pgpPktListFreeList((PktList *)siglist);
edefe6 }
--58ff 0016235501840100224 Page 1 of pgpSig.h
bc38e5 /*
8f3dc6 ·* $Id: pgpSig.h,v 1.14 1998/06/03 20:09:32 hal Exp $
35495d ·*/
deaf5a
34752f #ifndef Included_pgpSig_h
563d38 #define Included_pgpSig_h
4daf5a
23d11f #include "pgpUsuals.h"
79af5a
b899c6 PGP_BEGIN_C_DECLARATIONS
51af5a
11adb8 #include "pgpOpaqueStructs.h"
adaf5a
c87f35 /* These are the public access functions to the Sig object */
77af5a
fe0f95 PGPByte pgpSigType (PGPSig const *sig);
35344e PGPByte pgpSigVersion (PGPSig const *sig);
bef8b0 PGPByte pgpSigPKAlg (PGPSig const *sig);
04845a PGPHashVTBL const ·*pgpSigHash (PGPSig const *sig);
b2ea97 PGPByte const ·*pgpSigExtra (PGPSig const *sig, unsigned *len);
b2e95f PGPUInt32 ·pgpSigTimestamp (PGPSig const *sig);
7daf5a
a036a4 /* caller must free the key ID */
0ecafa PGPError¤   ¤   pgpGetSigKeyID( PGPSig const *sig, PGPKeyID *outRef);
e1af5a
4638e5 /*
5c41a2 ·* Check a signature against a given public key and hash.
1e8e2c ·* Returns 0 if it did not check, and 1 if it did.
1d1008 ·* Returns <0 on some sort of error.
236a58 ·* *Do* make sure it's the right hash you're passing in.
4b495d ·*/
039562 int ·pgpSigCheck (PGPSig const *sig,
6b6037 ¤   PGPPubKey const *pub, PGPByte const *hash);
84af5a
e738e5 /*
5b90db ·* Below this line are the internal functions that are used only
b7385f ·* inside the PGP Library. ·Applciations probably shouldn't be
34a96f ·* using these functions.
39495d ·*/
daaf5a
9838e5 /*
a8bb95 ·* Internal variant of pgpSigCheck, not for public use. ·Signature *must*
9d4cf7 ·* be known good.
12495d ·*/
024d2f int
065db6 pgpSigCheckBuf (PGPByte const *sig, PGPSize len, PGPPubKey const *pub,
65aed1 ¤   ¤   void const *hash);
beaf5a
4fe8cb /* Check the buffer for a valid signature block and obtain the sigtype */
88e936 int ·pgpSigSigType (PGPByte const *buf, size_t len);
3faf5a
44f18f int ·pgpSigNestFlag(PGPByte const *buf, size_t len);
e7af5a
18143d unsigned ·pgpSigDistinctHashCount (PGPSig const *siglist);
aa13c8 unsigned ·pgpSigDistinctHashes (PGPSig const *siglist,
c0ff9b ¤   PGPByte *buf);
b5af5a
5caea6 int ·pgpSigAdd ( PGPContextRef cdkContext,
09a438 ¤   PGPSig **siglist, int type, PGPByte const *buf,
3afa93 ¤   size_t len);
e2d193 PGPSig ·*pgpSigNext (PGPSig const *sig);
f5cf9e void ·pgpSigFreeList (PGPSig *siglist);
22af5a
5f1254 PGP_END_C_DECLARATIONS
5daf5a
62821b #endif /* Included_pgpSig_h */
--bedb 0015c083c2440100225 Page 1 of Makefile.in
5ea601 #
5e5262 # priv/keys/keydb/
b7a601 #
265bd0 # $Id: Makefile.in,v 1.11 1998/03/02 22:59:28 hal Exp $
89a601 #
e1af5a
95e6a6 OBJS= pgpFileDB.o pgpUnionDB.o pgpMemDB.o pgpKeyMan.o pgpKeyIter.o \
b737cc ¤   pgpKeySet.o pgpKeyLib.o pgpKeyUpd.o pgpKeyID.o \
ef0dc1 ¤   pgpDearmor.o pgpFilteredSet.o pgpKeyFilter.o pgpEnumeratedSet.o \
7ec305 ¤   pgpUnionSet.o pgpX509Keys.o
cc2a68 PRIVHDRS= pgpKeyDB.h pgpKDBInt.h pgpPrefsInt.h pgpKeyIDPriv.h \
58f0e7 ¤   pgpX509Priv.h
80af5a
bbb7a3 all:: DONE
5caf5a
--f5cd 00092299e4340100226 Page 1 of pgpDearmor.c
bc38e5 /*
666685 ·* pgpDearmor.c
2ac05e ·* Simple dearmoring module, with armoring routines too
5d775e ·*
72c9f2 ·* Remove ascii armor from key files (or mem buffers)
36775e ·*
12901c ·* Copyright (C) 1996, 1997 Network Associates, Inc. and its affiliates.
c4599a ·* All rights reserved.
5f775e ·*
0fc65e ·* $Id: pgpDearmor.c,v 1.32.2.1.2.1 1998/11/12 03:21:50 heller Exp $
fe495d ·*/
7e324c #include <string.h>
0caf5a
d5e2ff #include "pgpConfig.h"
9caf5a
28979a #include "pgpKDBInt.h"
bfaf5a
746aaa #include "pgpAnnotate.h"
25f476 #include "pgpArmor.h"
6dd1d7 #include "pgpDecPipe.h"
bc115d #include "pgpDevNull.h"
618b0d #include "pgpEncodePriv.h"
c60d6d #include "pgpEnv.h"
0857c7 #include "pgpESK.h"
25910a #include "pgpFIFO.h"
1572de #include "pgpFile.h"
ba3709 #include "pgpFileMod.h"
fd1dd3 #include "pgpMemMod.h"
a62ece #include "pgpPipeline.h"
71806a #include "pgpRngRead.h"
2f43bc #include "pgpSig.h"
343576 #include "pgpTextFilt.h"
5ee117 #include "pgpUI.h"
65c26c #include "pgpContext.h"
08af5a
63af5a
ee4a37 /* Struct for callbacks */
ceaf5a
917e09 typedef struct PGPDearmorUI
30bb36 {
808060 ¤   PGPContextRef¤  ¤   cdkContext;
dc1f70 ¤   PGPByte ············*outbuf;¤   ¤   ··/* Output buffer, alt. to filename */
cb9338 ¤   size_t ···········outbufsize;¤  ··/* Initial/final outbuf count */
54a87b ¤   PGPPipeline ·····*pipebuf;¤ ¤   ··/* Output buf pipeline pointer */
250f49 ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPDearmorUI )
c2a992 } PGPDearmorUI;
e4af5a
46af5a
7b1315 /* Callbacks for dearmor pass */
93af5a
a9beb7 static int
b8a4aa pgpDearmorMessage (void *arg, int type, int msg, unsigned numargs, ...)
c4bb36 {
bcceda ¤   /* Avoid warnings */
6dd698 ¤   (void)arg;
ca0e94 ¤   (void)type;
6dbd13 ¤   (void)msg;
e6cb25 ¤   (void)numargs;
c32d68 ¤   return( kPGPError_NoErr );
82efe6 }
8eaf5a
a9beb7 static int
edc02b pgpDearmorDoCommit (void *arg, int scope)
edbb36 {
3fceda ¤   /* Avoid warnings */
3cd698 ¤   (void)arg;
ca9e97 ¤   (void)scope;
29dd11 ¤   return PGPANN_PARSER_RECURSE;
7fefe6 }
29af5a
f5beb7 static int
920f4a pgpDearmorNeedInput (void *arg, PGPPipeline *head)
--2aaf 0000879853f40100226 Page 2 of pgpDearmor.c
2cbb36 {
1fceda ¤   /* Avoid warnings */
ead698 ¤   (void)arg;
8f3b66 ¤   (void)head;
7cc5ec ¤   return kPGPError_CantOpenFile;
a2efe6 }
33af5a
5ebeb7 static int
d4eca0 pgpDearmorSigVerify (void *arg, PGPSig const *sig, PGPByte const *hash)
44bb36 {
dcceda ¤   /* Avoid warnings */
66d698 ¤   (void)arg;
3a77e4 ¤   (void)sig;
964902 ¤   (void)hash;
272d68 ¤   return( kPGPError_NoErr );
96efe6 }
2aaf5a
dcbeb7 static int
1bd629 pgpDearmorEskDecrypt (void *arg, PGPESK const *esklist, PGPByte *key,
26d542 ¤   ¤   ··PGPSize *keylen,
c0f563 ¤   ¤   ··int (*tryKey) (void *arg, PGPByte const *key, PGPSize keylen),
b212b7 ¤   ¤   ··void *tryarg)
e6bb36 {
b3ceda ¤   /* Avoid warnings */
5ed698 ¤   (void)arg;
46dcaf ¤   (void)esklist;
389b3e ¤   (void)key;
99ede5 ¤   (void)keylen;
002c23 ¤   (void)tryKey;
000114 ¤   (void)tryarg;
f60812 ¤   return PGPANN_PARSER_EATIT;
dfefe6 }
68af5a
7b019a /* Send keys to outbuf, everything else to bit bucket */
12beb7 static int
3ac66d pgpDearmorNewOutput (void *arg, PGPPipeline **output, int type,
35500d ¤   char const *suggested_name)
eabb36 {
68e98b ¤   PGPDearmorUI ········*ui_arg; ····/* Parameters for callbacks */
d18d5e ¤   int ··················nullflag;¤ ·/* True if discarding output */
648060 ¤   PGPContextRef¤  ¤   cdkContext;
fdaf5a
0ae208 ¤   (void)suggested_name;¤  /* Avoid warning */
b9af5a
d1ee0a ¤   ui_arg = (PGPDearmorUI *) arg;
d766ea ¤   cdkContext¤ = ui_arg->cdkContext;
6b0f4b ¤   nullflag = 0;
3eaf5a
233d13 ¤   /* Try to keep output open if we have multiple key packets in a row */
8de42b ¤   if (*output && ui_arg->pipebuf && ui_arg->outbuf==NULL) {
b4a1bc ¤   ¤   PGPByte enable;
6740a2 ¤   ¤   if (type==PGPANN_NONPGP_BEGIN) {
927aad ¤   ¤   ¤   /*
2ab668 ¤   ¤   ¤   ·* Non-key material found between the two packets. ·We send a
6d730d ¤   ¤   ¤   ·* disable annotation to tell the pipebuf module to discard this
82c3b8 ¤   ¤   ¤   ·* intermediate data.
768753 ¤   ¤   ¤   ·*/
0b53f2 ¤   ¤   ¤   enable = 0;
48838b ¤   ¤   ¤   (ui_arg->pipebuf)->annotate(ui_arg->pipebuf, NULL,
0aca9d ¤   ¤   ¤   ¤   PGPANN_MEM_ENABLE, &enable, 1);
b0e0e4 ¤   ¤   ¤   return( kPGPError_NoErr );
cd8eec ¤   ¤   } else if (type==PGPANN_PGPKEY_BEGIN) {
517aad ¤   ¤   ¤   /*
4f4ba9 ¤   ¤   ¤   ·* A second or later key packet after first. ·We may have disabled
507051 ¤   ¤   ¤   ·* the mem buffer if there was nonkey material, so re-enable it
09f0a1 ¤   ¤   ¤   ·* now.
048753 ¤   ¤   ¤   ·*/
52092e ¤   ¤   ¤   enable = 1;
08838b ¤   ¤   ¤   (ui_arg->pipebuf)->annotate(ui_arg->pipebuf, NULL,
2eca9d ¤   ¤   ¤   ¤   PGPANN_MEM_ENABLE, &enable, 1);
d7e0e4 ¤   ¤   ¤   return( kPGPError_NoErr );
080fe4 ¤   ¤   }
--1464 000e38c362c40100226 Page 3 of pgpDearmor.c
a19371 ¤   }
18affe ¤   /* Discard non-key packets */
2cd40c ¤   if (type != PGPANN_PGPKEY_BEGIN || ui_arg->outbuf==NULL) {
b36f0d ¤   ¤   nullflag = 1;
a29371 ¤   }
e8af5a
3c1d17 ¤   /* Close old output pipeline */
26c0a4 ¤   if (*output) {
2c0712 ¤   ¤   if (ui_arg->pipebuf) {
6f838b ¤   ¤   ¤   (ui_arg->pipebuf)->annotate(ui_arg->pipebuf, NULL,
3f8eb6 ¤   ¤   ¤   ¤   PGPANN_MEM_BYTECOUNT, (PGPByte *)&ui_arg->outbufsize,
be7844 ¤   ¤   ¤   ¤   sizeof(ui_arg->outbufsize));
88fe20 ¤   ¤   ¤   ui_arg->pipebuf = 0;
ab0fe4 ¤   ¤   }
260972 ¤   ¤   (*output)->sizeAdvise (*output, 0);
a3e8f5 ¤   ¤   (*output)->teardown (*output);
2265c6 ¤   ¤   *output = NULL;
1f9371 ¤   }
baaf5a
4a5753 ¤   /* Handle discarded data */
d191c3 ¤   if (nullflag) {
f58484 ¤   ¤   pgpDevNullCreate ( cdkContext, output);
2fa117 ¤   ¤   return( kPGPError_NoErr );
d89371 ¤   }
9baf5a
def9a1 ¤   pgpAssert (ui_arg->outbuf);
1ad028 ¤   ui_arg->pipebuf = pgpMemModCreate ( ui_arg->cdkContext,
d96600 ¤   ¤   ¤   output, (char *)ui_arg->outbuf,
af9fec ¤   ¤   ui_arg->outbufsize);
8636ea ¤   ui_arg->outbuf = NULL;¤ ¤   /* Discard any following keys */
23908e ¤   if (!ui_arg->pipebuf)
384030 ¤   ¤   return kPGPError_OutOfMemory;
ffaf5a
08151e ¤   return kPGPError_NoErr;
d1efe6 }
a8af5a
bfaf5a
e1af5a
ebaf5a
f6af5a
a738e5 /*
32df67 ·* Common code for key dearmoring to a dynamically allocated memory buffer.
0ff13f ·* Returns *OutputBuffer as a buffer holding the dearmored key, suitable for
05f89f ·* passing to pgpContextMemFree. ·*OutputBufferLen holds the size of the buffer.
7247b2 ·* fFilein determines whether we take the key data from InputFileName or
6c5bac ·* from InputBuffer/InputBufferLen.
a8495d ·*/
1bc744 ¤   PGPError
effc91 pgpDearmorKey (
b8b46f ¤   PGPEnv *¤   ¤   env,
fd61c0 ¤   int¤¤   ¤   ¤   fFilein,
28fd4f ¤   PFLFileSpecRef¤ InputFileRef,
092cf4 ¤   PGPFileRead *¤  pfrin,
51ec35 ¤   PGPByte const *¤InputBuffer,
623542 ¤   PGPSize¤¤   ¤   InputBufferLen,
81ab80 ¤   PGPByte **¤ ¤   OutputBuffer,
a19d0b ¤   PGPSize *¤  ¤   OutputBufferLen)
d4bb36 {
b39b1d ¤   PGPPipeline ·········*head,¤¤   ··/* Pipeline head */
c88b36 ¤   ····················**tail; ······/* Pipeline tail pointer */
a863c4 ¤   PGPUICb ··············ui;¤  ¤   ··/* Callback functions */
102994 ¤   PGPDearmorUI ·········ui_arg; ····/* Parameters for callbacks */
a33f85 ¤   PGPByte ················*outbuf; ····/* Allocated output buffer */
7be820 ¤   size_t ···············outbuflen; ·/* Size of outbuf */
0c9e00 ¤   PGPError ·············err;¤ ¤   ··/* Error variable */
73ec52 ¤   PGPByte ·················dum1[1]; ···/* Dummy array for sizing pass */
39c520 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( env );
c3a7db ¤   PGPFileDataType¤¤   fileDataType;
8667c5 ¤
d9f11b ¤   head = NULL;
ccaf5a
e31be1 ¤   /* Setup the UI callback functions */
--412c 000115338db40100226 Page 4 of pgpDearmor.c
4eb904 ¤   ui.message¤ ¤   = pgpDearmorMessage;
f26e30 ¤   ui.doCommit¤¤   = pgpDearmorDoCommit;
cd6c81 ¤   ui.newOutput¤   = pgpDearmorNewOutput;
171025 ¤   ui.needInput¤   = pgpDearmorNeedInput;
6d529d ¤   ui.sigVerify¤   = pgpDearmorSigVerify;
d0a016 ¤   ui.eskDecrypt¤  = pgpDearmorEskDecrypt;
6d61e2 ¤   ui.annotate¤= NULL;
e3af5a
ee5304 ¤   /* Set up the UI argument. ·First pass will just get length. */
893079 ¤   pgpClearMemory (&ui_arg, sizeof (ui_arg));
67c5af ¤   ui_arg.outbuf = dum1;¤  ¤   ¤   ··/* Dummy output buffer */
72a1cc ¤   ui_arg.outbufsize = 0; ···········/* Will get length afterwards */
9e1c4b ¤   ui_arg.cdkContext¤  = pgpenvGetContext( env );
5caf5a
30c80c ¤   /* Set up pipeline */
bdc7df ¤   tail = pgpDecryptPipelineCreate ( pgpenvGetContext( env ),
2bf006 ¤   ¤   ¤   ¤   &head, env, NULL, &ui, &ui_arg);
17af5a
4c0e21 ¤   /* Send data through */
4b015c ¤   if (fFilein) {
0b6718 ¤   ¤   /* Open input file if caller has not already done so */
a92f21 ¤   ¤   if( IsNull( pfrin ) )
21ff9d ¤   ¤   ¤   pfrin = pgpFileRefReadCreate ( ui_arg.cdkContext,
382f28 ¤   ¤   ¤   ¤   ¤   ¤   InputFileRef, kPGPFileOpenReadPerm, &err, &fileDataType¶
356275 );
e72f21 ¤   ¤   if( IsNull( pfrin ) )
cbed19 ¤   ¤   ¤   goto error;
ef16bb ¤   ¤   err = pgpFileReadPump (pfrin, head);
b271a3 ¤   ¤   pgpFileReadDestroy (pfrin);
d133f7 ¤   ¤   head->sizeAdvise (head, 0);
fef037 ¤   } else {
57a37f ¤   ¤   /* Send data through */
7130cd ¤   ¤   PGPByte const *ibuf = InputBuffer;
2f7ea2 ¤   ¤   size_t ibuflen = InputBufferLen;
8ba73c ¤   ¤   err = head->sizeAdvise (head, ibuflen);
0222ab ¤   ¤   while (ibuflen && !err) {
f520b8 ¤   ¤   ¤   size_t written;
a296ed ¤   ¤   ¤   written = head->write (head, ibuf, ibuflen, &err);
205bde ¤   ¤   ¤   ibuf += written;
8cd4c0 ¤   ¤   ¤   ibuflen -= written;
e00fe4 ¤   ¤   }
9b33f7 ¤   ¤   head->sizeAdvise (head, 0);
0f9371 ¤   }
4b741f ¤   if (!err) {
3c187b ¤   ¤   /* Find out how many bytes we wrote */
a6a2fd ¤   ¤   if (!ui_arg.pipebuf) {
d37aad ¤   ¤   ¤   /*
beb160 ¤   ¤   ¤   ·* May have been closed in callback on multipart, or there may
a71ec7 ¤   ¤   ¤   ·* have been no ascii armor part at all.
ee8753 ¤   ¤   ¤   ·*/
f4ddde ¤   ¤   ¤   outbuflen = ui_arg.outbufsize;
8545a6 ¤   ¤   } else {
d6e67e ¤   ¤   ¤   (ui_arg.pipebuf)->annotate(ui_arg.pipebuf, NULL,
6f0e80 ¤   ¤   ¤   ¤   PGPANN_MEM_BYTECOUNT, (PGPByte *)&outbuflen, sizeof(outbuflen));
8c0fe4 ¤   ¤   }
019371 ¤   }
2e8ee5 ¤   head->teardown (head);
e8f11b ¤   head = NULL;
b60e0a ¤   ui_arg.pipebuf = NULL;
08a09a ¤   if (err)
f097ed ¤   ¤   goto error;
c8af5a
ac3a98 ¤   /* Now we know the size needed, allocate a buffer to hold it */
2ef000 ¤   outbuf = (PGPByte *)pgpContextMemAlloc( cdkContext,
b2775a ¤   ¤   outbuflen, kPGPMemoryMgrFlags_Clear);
dda207 ¤   if (!outbuf) {
18bce1 ¤   ¤   err = kPGPError_OutOfMemory;
8697ed ¤   ¤   goto error;
c59371 ¤   }
84d665 ¤   ui_arg.outbuf = outbuf;
521a91 ¤   ui_arg.outbufsize = outbuflen;
11af5a
--ae05 000f943cf5b40100226 Page 5 of pgpDearmor.c
aba118 ¤   /* Send data through again, this time with enough room */
07c7df ¤   tail = pgpDecryptPipelineCreate ( pgpenvGetContext( env ),
71a29b ¤   ¤   ¤   &head, env, NULL, &ui, &ui_arg);
9f015c ¤   if (fFilein) {
36c138 ¤   ¤   pfrin = pgpFileRefReadCreate ( pgpenvGetContext( env ),
05b824 ¤   ¤   ¤   ¤   ¤   InputFileRef, kPGPFileOpenReadPerm, &err, &fileDataType);
0e1487 ¤   ¤   if (!pfrin)
a8ed19 ¤   ¤   ¤   goto error;
c816bb ¤   ¤   err = pgpFileReadPump (pfrin, head);
9171a3 ¤   ¤   pgpFileReadDestroy (pfrin);
da33f7 ¤   ¤   head->sizeAdvise (head, 0);
7cf037 ¤   } else {
22a37f ¤   ¤   /* Send data through */
ac30cd ¤   ¤   PGPByte const *ibuf = InputBuffer;
057ea2 ¤   ¤   size_t ibuflen = InputBufferLen;
10a73c ¤   ¤   err = head->sizeAdvise (head, ibuflen);
5822ab ¤   ¤   while (ibuflen && !err) {
0f20b8 ¤   ¤   ¤   size_t written;
f096ed ¤   ¤   ¤   written = head->write (head, ibuf, ibuflen, &err);
fd5bde ¤   ¤   ¤   ibuf += written;
dad4c0 ¤   ¤   ¤   ibuflen -= written;
9f0fe4 ¤   ¤   }
5133f7 ¤   ¤   head->sizeAdvise (head, 0);
ea9371 ¤   }
2a8ee5 ¤   head->teardown (head);
f3f11b ¤   head = NULL;
ac8a50 ¤   if (err) {
268933 ¤   ¤   pgpContextMemFree( cdkContext, outbuf);
fb97ed ¤   ¤   goto error;
d59371 ¤   }
66af5a
88225c ¤   /* Return resulting buffer and size */
445668 ¤   *OutputBuffer = outbuf;
f1c541 ¤   *OutputBufferLen = outbuflen;
daaf5a
2460ff error:
8faf5a
9e3354 ¤   if (head)
7b9acd ¤   ¤   head->teardown (head);
8aaf5a
ff5ea8 ¤   return err;
b2efe6 }
14af5a
4f38e5 /*
7bd33e ·* Dearmor a key from a file and put it into a dynamically allocated memory
a42392 ·* buffer.
d8f13f ·* Returns *OutputBuffer as a buffer holding the dearmored key, suitable for
19f89f ·* passing to pgpContextMemFree. ·*OutputBufferLen holds the size of the buffer.
85495d ·*/
78c744 ¤   PGPError
bc965c pgpDearmorKeyFile (PGPEnv *env, PFLFileSpecRef InputFileRef,
83ec38 ¤   PGPByte **OutputBuffer, PGPSize *OutputBufferLen)
49bb36 {
1de6f0 ¤   return pgpDearmorKey (env, TRUE, InputFileRef, NULL, NULL, (size_t)0,
d87127 ¤   ¤   OutputBuffer, OutputBufferLen);
0fefe6 }
53af5a
4b38e5 /*
303ad8 ·* Dearmor a key from a buffer and put it into a dynamically allocated memory
482392 ·* buffer.
bbf13f ·* Returns *OutputBuffer as a buffer holding the dearmored key, suitable for
bdf89f ·* passing to pgpContextMemFree. ·*OutputBufferLen holds the size of the buffer.
9d495d ·*/
8ec744 ¤   PGPError
768a49 pgpDearmorKeyBuffer (
dc6c5c ¤   PGPEnv *¤   ¤   ¤   env,
673b90 ¤   PGPByte const *¤¤   InputBuffer,
5dcdef ¤   PGPSize¤¤   ¤   ¤   InputBufferLen,
956069 ¤   PGPByte **¤ ¤   ¤   OutputBuffer,
551890 ¤   PGPSize *¤  ¤   ¤   OutputBufferLen)
dabb36 {
f96d79 ¤   return pgpDearmorKey (env, FALSE, NULL, NULL, InputBuffer, InputBufferLen,
--769b 0009b33b6f240100226 Page 6 of pgpDearmor.c
ef7127 ¤   ¤   OutputBuffer, OutputBufferLen);
55efe6 }
38af5a
66af5a
4daf5a
a7af5a
f77c9a /* Some armoring routines too */
bdaf5a
36af5a
5caf5a
a795d7 /*·
2934fe ·* Write out the specified RingSet in ascii armor form to pipeline.
9e495d ·*/
23f1ae static PGPError
a5f634 pgpWriteArmoredSetPipe (PGPPipeline *pipe, RingSet const *set, PGPEnv *env)
7cbb36 {
d47718 ¤   PGPFile ·········*pfp;
9c433d ¤   PGPError ········rslt;
ebaf5a
348c3e ¤   if (!pgpArmorWriteCreate( pgpenvGetContext( env ),
7a0fb6 ¤   ¤   ¤   &pipe, env, &pgpByteFifoDesc,
baaca2 ¤   ¤   ¤   ¤   ·NULL, PGPVERSION_3, PGP_ARMOR_NORMAL)) {
1236be ¤   ¤   pipe->teardown(pipe);
a24030 ¤   ¤   return kPGPError_OutOfMemory;
f49371 ¤   }
da0393 ¤   pfp = pgpFilePipelineOpen(pipe);
9775e1 ¤   if (!pfp) {
1836be ¤   ¤   pipe->teardown(pipe);
664030 ¤   ¤   return kPGPError_OutOfMemory;
e49371 ¤   }
1f6654 ¤   rslt = ringSetWrite (set, pfp, NULL, PGPVERSION_3, 0);
9a7edf ¤   pgpFileClose (pfp);
245d4b ¤   return rslt;
5fefe6 }
d4af5a
775c59 /* Write out the specified RingSet in ascii armor form to fp. */
cdc744 ¤   PGPError
d4ba49 pgpWriteArmoredSetFile (FILE *fp, RingSet const *set, PGPEnv *env)
d5bb36 {
217718 ¤   PGPFile ·········*pfp;
c8ef9d ¤   PGPPipeline ·····*ppl = NULL;
a3c520 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( env );
ec67c5 ¤
8c777f ¤   pfp = pgpFileWriteOpen( cdkContext, fp, NULL);
3f75e1 ¤   if (!pfp) {
40f271 ¤   ¤   pgpStdIOClose(fp);
624030 ¤   ¤   return kPGPError_OutOfMemory;
e09371 ¤   }
45f99e ¤   if (!pgpFileWriteCreate ( cdkContext, &ppl, pfp, 1)) {
e0f3a6 ¤   ¤   pgpFileClose(pfp);
7d4030 ¤   ¤   return kPGPError_OutOfMemory;
de9371 ¤   }
6b45d5 ¤   return pgpWriteArmoredSetPipe (ppl, set, env);
8befe6 }
5aaf5a
7638e5 /*
fc7132 ·* Write out the specified RingSet in ascii armor form to buf.
fde961 ·* Set *buflen to number of bytes we wrote or would have written.
6c00f0 ·* Read the size of buf from *buflen on entry.
8c495d ·*/
45c744 ¤   PGPError
466c16 pgpWriteArmoredSetBuffer (PGPByte *buf, PGPSize *buflen, RingSet const *set,
9605f3 ¤   PGPEnv *env)
49bb36 {
033704 ¤   PGPPipeline ·····*ppl = NULL,
fe753b ¤   ·················*pipebuf;
087718 ¤   PGPFile ·········*pfp;
5b685a ¤   PGPSize ···········nbuf = *buflen,
b1dd2b ¤   ··················written;
0617e2 ¤   PGPError ·············rslt;
82e46f ¤   PGPLineEndType¤ ··lineEnd = pgpGetDefaultLineEndType();
9bba82 ¤   PGPContextRef¤  cdkContext¤ = pgpenvGetContext( env );
--e2f7 001e22fb6f840100226 Page 7 of pgpDearmor.c
2a67c5 ¤
84717b ¤   pipebuf = (PGPPipeline *)pgpMemModCreate ( cdkContext,
0b0a6b ¤   ¤   ¤   ¤   &ppl, (char *)buf, nbuf);
12af5a
d8a7b3 ¤   /* Convert to local line endings */
8806f0 ¤   if (!pgpTextFiltCreate ( cdkContext, &ppl,
62d63b ¤   ¤   ¤   ·(PGPByte *)pgpenvGetPointer (env, PGPENV_CHARMAPTOLATIN1, NULL),
c496ad ¤   ¤   ¤   ·0, lineEnd)) {
4e1742 ¤   ¤   ppl->teardown(ppl);
624030 ¤   ¤   return kPGPError_OutOfMemory;
bd9371 ¤   }
67af5a
92456d ¤   if (!pgpArmorWriteCreate( cdkContext, &ppl, env, &pgpByteFifoDesc,
d6aca2 ¤   ¤   ¤   ¤   ·NULL, PGPVERSION_3, PGP_ARMOR_NORMAL)) {
ae1742 ¤   ¤   ppl->teardown(ppl);
d24030 ¤   ¤   return kPGPError_OutOfMemory;
9e9371 ¤   }
321f76 ¤   pfp = pgpFilePipelineOpen(ppl);
f975e1 ¤   if (!pfp) {
2c1742 ¤   ¤   ppl->teardown(ppl);
f24030 ¤   ¤   return kPGPError_OutOfMemory;
d09371 ¤   }
8a6654 ¤   rslt = ringSetWrite (set, pfp, NULL, PGPVERSION_3, 0);
47d7c5 ¤   if (!rslt) {
397081 ¤   ¤   /* Figure out how many bytes would be written */
ea5c19 ¤   ¤   ppl->sizeAdvise (ppl, 0);
85bf82 ¤   ¤   pipebuf->annotate (pipebuf, NULL, PGPANN_MEM_BYTECOUNT,
93813d ¤   ¤   ¤   ¤   (PGPByte *)&written, sizeof (written));
aaf203 ¤   ¤   *buflen = written;
c09371 ¤   }
627edf ¤   pgpFileClose (pfp);
675d4b ¤   return rslt;
27efe6 }
c6af5a
8c38e5 /*
ade6c5 ·* Local Variables:
309b19 ·* tab-width: 4
bde7a4 ·* End:
c0b612 ·* vi: ts=4 sw=4
d76c42 ·* vim: si
e2495d ·*/
--fcf2 00048a979b840100227 Page 1 of pgpEnumeratedSet.c
bc38e5 /*
0a7ebc ·* pgpEnumeratedSet.c
d2a68c ·* Arbitrary enumerated subset variant of pgpKeySet.
d7775e ·*
3bbbeb ·* Copyright (C) 1997 Network Associates, Inc. and its affiliates.
1320c7 ·* All rights reserved
b3775e ·*
b079fa ·* $Id: pgpEnumeratedSet.c,v 1.10.12.1 1998/11/12 03:21:51 heller Exp $
0e495d ·*/
68af5a
6ae2ff #include "pgpConfig.h"
51af5a
e8ef82 #ifdef HAVE_STDLIB_H
52bea3 #include <stdlib.h>
657454 #endif
b2af5a
47324c #include <string.h>
9fb1cb #include <ctype.h>
beaf5a
ea979a #include "pgpKDBInt.h"
61a146 #include "pgpDebug.h"
f42f8d #include "pgpErrors.h"
2c675a #include "pgpTypes.h"
6d0d08 #include "pgpMem.h"
e7c26c #include "pgpContext.h"
327ca7 #include "pgpKeyIDPriv.h"
1726e3 #include "pgpRngPub.h"
6aaf5a
3caf5a
9b958b /* Private data for KeySet of type: enumerated subset */
2d44c1 typedef struct EnumeratedSubsetPriv
b6bb36 {
faf40c ¤   RingObject **¤  keyArray;¤  /* Array of keys, sorted by keyid */
9cec98 ¤   long¤   ¤   ¤   numKeys;
47d400 } EnumeratedSubsetPriv;
c4af5a
17af5a
fd1cd5 static PGPError¤NewEnumeratedSubsetInternal(PGPKeyDBRef¤¤   db,
43b64d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *¤ newSet);
01af5a
c4af5a
89d1b8 /* XXX Assumes that keyIDs are 8 bytes long */
d0df0d ¤   static int
dc36c5 compareRawKeyIDs(
075442 ¤   PGPKeyID const *¤   keyIDA,
d3c59e ¤   PGPKeyID const *¤   keyIDB)
60bb36 {
05b177 #if 0
e8d312 ¤   int¤¤   ¤   ¤   i;
89af5a
fe33e2 ¤   for (i = 0; i < 8; i++)
e2c7a1 ¤   {
132eb3 ¤   ¤   if (keyIDA->bytes[i] > keyIDB->bytes[i])
34db98 ¤   ¤   ¤   return 1;
309b73 ¤   ¤   else if (keyIDA->bytes[i] < keyIDB->bytes[i])
d63fd5 ¤   ¤   ¤   return -1;
cf9371 ¤   }
ed3e6b ¤   return 0;
6fdb21 #else
990eb9 ¤   return( PGPCompareKeyIDs( keyIDA, keyIDB ) );
7e7454 #endif
c3efe6 }
30af5a
9138e5 /*
ca6a75 ·* Check to see if a key is a member of an enumerated subset
e9495d ·*/
6c6c2c ¤   static PGPBoolean
5a0229 IsMemberOfEnumeratedSubset(
37bbbe ¤   PGPKeySetRef¤   ¤   ¤   set,
50c805 ¤   RingObject *¤   ¤   ¤   obj)
a5bb36 {
48577e ¤   EnumeratedSubsetPriv *¤ priv = (EnumeratedSubsetPriv *)set->priv;
--bb41 0009e8663c940100227 Page 2 of pgpEnumeratedSet.c
370fb5 ¤   RingSet const *¤¤   ¤   ringSet = pgpKeyDBRingSet(set->keyDB);
19cfac ¤   RingObject *¤   ¤   ¤   keyObj;
833f1b ¤   PGPKeyID¤   ¤   ¤   ¤   keyID;
ec1de7 ¤   long¤   ¤   ¤   ¤   ¤   lowerBound;
5e47b5 ¤   long¤   ¤   ¤   ¤   ¤   upperBoundPlusOne;
3898b1 ¤   long¤   ¤   ¤   ¤   ¤   indexOfEqualKeyID;
a75a92 ¤   long¤   ¤   ¤   ¤   ¤   indexTry¤   = 0;
217652 ¤   RingObject *¤   ¤   ¤   keyObjTry;
9f0c1d ¤   PGPKeyID¤   ¤   ¤   ¤   keyIDTry;
47da32 ¤   int¤¤   ¤   ¤   ¤   ¤   comparison;
b5af5a
e25e68 ¤   pgpa((
1de8b8 ¤   ¤   pgpaPGPKeySetValid(set),
24ef6b ¤   ¤   pgpaAddrValid(priv, EnumeratedSubsetPriv),
57bf04 ¤   ¤   pgpaAddrValid(obj, VoidAlign)));
68af5a
a92307 ¤   if (!ringSetIsMember(ringSet, obj))
8d98aa ¤   ¤   return FALSE;
e8af5a
acc7a1 ¤   {
d73f2a ¤   ¤   RingIterator *¤ ¤   ringIter;
99af5a
c7fb1d ¤   ¤   /* First get the master key object (XXX this may not be necessary) */
6ca079 ¤   ¤   ringIter = ringIterCreate(ringSet);
1f5d30 ¤   ¤   pgpAssert(ringIter != NULL);
71a1b7 ¤   ¤   ringIterSeekTo(ringIter, obj);
ea51d8 ¤   ¤   keyObj = ringIterCurrentObject(ringIter, 1);
f6137a ¤   ¤   pgpAssert(keyObj != NULL);
710204 ¤   ¤   ringIterDestroy(ringIter);
729371 ¤   }
5baf5a
98d3c5 ¤   /* Get the KeyID */
312ef7 ¤   ringKeyID8(ringSet, keyObj, NULL, &keyID);
77af5a
b60e3b ¤   /* Use binary search to find a key in the array with the same KeyID */
0af0a7 ¤   lowerBound = 0;
0b59cf ¤   upperBoundPlusOne = priv->numKeys;
2a9c42 ¤   while (lowerBound < upperBoundPlusOne)
76c7a1 ¤   {
8f0754 ¤   ¤   indexTry = (lowerBound + upperBoundPlusOne) / 2;
2711f2 ¤   ¤   keyObjTry = priv->keyArray[indexTry];
867d7e ¤   ¤   if (keyObjTry == keyObj)
2a19ba ¤   ¤   ¤   return TRUE;¤   /* Found it! */
49af5a
7faf2a ¤   ¤   ringKeyID8(ringSet, keyObjTry, NULL, &keyIDTry);
dd70ad ¤   ¤   comparison = compareRawKeyIDs(&keyID, &keyIDTry);
015d70 ¤   ¤   if (comparison > 0)
5f542a ¤   ¤   ¤   lowerBound = indexTry + 1;
46e3f9 ¤   ¤   else if (comparison < 0)
fd6168 ¤   ¤   ¤   upperBoundPlusOne = indexTry;
670e1d ¤   ¤   else
bacdcb ¤   ¤   ¤   break;
539371 ¤   }
9b7416 ¤   if (lowerBound >= upperBoundPlusOne)
7d5300 ¤   ¤   return FALSE;¤  /* Binary search failed */
c767c5 ¤
9cd8af ¤   /*
eb21b7 ¤   ·* We found a key with the same KeyID, but it's not the same key.
54d2b0 ¤   ·* Now we search the adjacent keys of equal KeyID looking for the key.
a1a4e3 ¤   ·*/
4b60a3 ¤   indexOfEqualKeyID = indexTry;
c8af5a
51c591 ¤   /* First search lower indices */
31436e ¤   while (--indexTry >= lowerBound)
66c7a1 ¤   {
c211f2 ¤   ¤   keyObjTry = priv->keyArray[indexTry];
157d7e ¤   ¤   if (keyObjTry == keyObj)
a819ba ¤   ¤   ¤   return TRUE;¤   /* Found it! */
b5af5a
39af2a ¤   ¤   ringKeyID8(ringSet, keyObjTry, NULL, &keyIDTry);
119c8d ¤   ¤   if (0 != compareRawKeyIDs(&keyID, &keyIDTry))
9ecdcb ¤   ¤   ¤   break;
--8254 0005c9706d140100227 Page 3 of pgpEnumeratedSet.c
a19371 ¤   }
93af5a
1fcee4 ¤   /* Then search higher indices */
8b0935 ¤   indexTry = indexOfEqualKeyID;
3eeb6e ¤   while (++indexTry < upperBoundPlusOne)
78c7a1 ¤   {
4a11f2 ¤   ¤   keyObjTry = priv->keyArray[indexTry];
4c7d7e ¤   ¤   if (keyObjTry == keyObj)
1419ba ¤   ¤   ¤   return TRUE;¤   /* Found it! */
67af5a
79af2a ¤   ¤   ringKeyID8(ringSet, keyObjTry, NULL, &keyIDTry);
139c8d ¤   ¤   if (0 != compareRawKeyIDs(&keyID, &keyIDTry))
69cdcb ¤   ¤   ¤   break;
409371 ¤   }
a6af5a
c8e877 ¤   /* Now we know for sure it's not in the set */
dfa230 ¤   return FALSE;
0eefe6 }
41af5a
4366dd ¤   static PGPError
e597f9 MakeUnionOfEnumeratedSubsets(
7848b6 ¤   PGPKeySetRef¤   ¤   set1,
c5a7d2 ¤   PGPKeySetRef¤   ¤   set2,
c16641 ¤   PGPKeySetRef *¤ ¤   newSet)
83bb36 {
c23c2c ¤   PGPContextRef¤  ¤   ¤   context¤= PGPGetKeySetContext(set1);
902872 ¤   RingSet const *¤¤   ¤   ringSet = pgpKeyDBRingSet(set1->keyDB);
846902 ¤   EnumeratedSubsetPriv *¤ priv1 = (EnumeratedSubsetPriv *)set1->priv;
64ad4b ¤   EnumeratedSubsetPriv *¤ priv2 = (EnumeratedSubsetPriv *)set2->priv;
ca1410 ¤   EnumeratedSubsetPriv *¤ priv;
f66adb ¤   RingObject **¤  ¤   ¤   keyArray1 = priv1->keyArray;
603d98 ¤   RingObject **¤  ¤   ¤   keyArray2 = priv2->keyArray;
a3adec ¤   RingObject **¤  ¤   ¤   keyArray;
42dd37 ¤   PGPKeyID¤   ¤   ¤   ¤   keyID1;
e43253 ¤   PGPKeyID¤   ¤   ¤   ¤   keyID2;
da6327 ¤   PGPKeySetRef¤   ¤   ¤   set;
519ea6 ¤   long¤   ¤   ¤   ¤   ¤   in1;
9671c2 ¤   long¤   ¤   ¤   ¤   ¤   in2;
419941 ¤   long¤   ¤   ¤   ¤   ¤   out;
20da32 ¤   int¤¤   ¤   ¤   ¤   ¤   comparison;
aa9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
aaaf5a
fecc57 ¤   *newSet = NULL;¤¤   ¤   /* In case there's an error */
20af5a
47e454 ¤   err = NewEnumeratedSubsetInternal(set1->keyDB, &set);
d482f0 ¤   if (IsPGPError(err))
47c9db ¤   ¤   return err;
bdaf5a
4e0482 ¤   priv = (EnumeratedSubsetPriv *)set->priv;
cb5c9a ¤   priv->numKeys = priv1->numKeys + priv2->numKeys;
56af5a
face86 ¤   keyArray = (RingObject **)pgpContextMemAlloc(context,
d7f436 ¤   ¤   ¤   ¤   ¤   ¤   ¤   priv->numKeys * sizeof(RingObject *), 0);
8a2adf ¤   if (IsNull(keyArray))
a3c7a1 ¤   {
f015a5 ¤   ¤   PGPFreeKeySet(set);
444030 ¤   ¤   return kPGPError_OutOfMemory;
b99371 ¤   }
17af5a
a0d725 ¤   in1 = in2 = out = 0;
63af5a
c31b8f ¤   /* Merge the two sorted arrays until we reach the end of one of them */
7accd0 ¤   while (in1 < priv1->numKeys && in2 < priv2->numKeys)
1dc7a1 ¤   {
a41b17 ¤   ¤   /*
7a6834 ¤   ¤   ·* Check for duplicate keys. ·Note that if keyIDs aren't unique
d5ede0 ¤   ¤   ·* then this won't necessarily remove duplicates. ·This isn't
097dbb ¤   ¤   ·* a bug, because duplicates needn't be removed for correctness.
9d2563 ¤   ¤   ·* It is merely an optimization.
469de3 ¤   ¤   ·*/
4fc9d2 ¤   ¤   if (keyArray1[in1] == keyArray2[in2])
5c5b34 ¤   ¤   {
--cc4b 0003ababdb840100227 Page 4 of pgpEnumeratedSet.c
0641dc ¤   ¤   ¤   in2++;
ed17f5 ¤   ¤   ¤   continue;
1e0fe4 ¤   ¤   }
9daf5a
eb2eb0 ¤   ¤   ringKeyID8(ringSet, keyArray1[in1], NULL, &keyID1);
908f5a ¤   ¤   ringKeyID8(ringSet, keyArray2[in2], NULL, &keyID2);
3daf5a
7df789 ¤   ¤   comparison = compareRawKeyIDs(&keyID1, &keyID2);
d7cf93 ¤   ¤   if (comparison <= 0)
22c360 ¤   ¤   ¤   keyArray[out++] = keyArray1[in1++];
86f571 ¤   ¤   else if (comparison > 0)
01bb74 ¤   ¤   ¤   keyArray[out++] = keyArray2[in2++];
029371 ¤   }
d0af5a
a2d8af ¤   /*
74d7c3 ¤   ·* Copy the rest of the remaining array.
515fd9 ¤   ·* (at most one of these loops will be non-empty)
e1a4e3 ¤   ·*/
017881 ¤   while (in1 < priv1->numKeys)
a7db30 ¤   ¤   keyArray[out++] = keyArray1[in1++];
019684 ¤   while (in2 < priv2->numKeys)
e2a324 ¤   ¤   keyArray[out++] = keyArray2[in2++];
c5af5a
3bed98 ¤   /* Shrink the resulting array, in case there were duplicates */
69c730 ¤   if (out < priv->numKeys)
9fc7a1 ¤   {
2eaa80 ¤   ¤   priv->numKeys = out;
1aaa88 ¤   ¤   err = pgpContextMemRealloc(context, (void **)&keyArray,
41fe9e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   out * sizeof(RingObject *), 0);
626a60 ¤   ¤   pgpAssert(IsntPGPError(err));¤  /* Shrinking should never fail */
419371 ¤   }
93af5a
024527 ¤   priv->keyArray = keyArray;
579fa7 ¤   *newSet = set;
dd151e ¤   return kPGPError_NoErr;
f1efe6 }
95af5a
f033c8 ¤   static void
888ebf RemoveKeyFromEnumeratedSubset(
247a49 ¤   PGPKeySetRef¤   set,
eab323 ¤   PGPKeyRef¤  ¤   key)
21bb36 {
43029b ¤   PGPContextRef¤  ¤   ¤   context¤= PGPGetKeySetContext(set);
41ed5f ¤   EnumeratedSubsetPriv *¤ priv¤   = (EnumeratedSubsetPriv *)set->priv;
172798 ¤   RingObject *¤   ¤   ¤   keyObj¤ = key->key;
636dce ¤   RingObject **¤  ¤   ¤   end¤¤   = priv->keyArray + priv->numKeys;
37c40f ¤   RingObject **¤  ¤   ¤   out;
f111e5 ¤   RingObject **¤  ¤   ¤   in;
5daf5a
823cb5 ¤   /* First a fast read-only scan to find the first occurrence of the key */
894136 ¤   in = priv->keyArray;
43d94b ¤   while (in < end && *in != keyObj)
1cca95 ¤   ¤   in++;
f4af5a
85d8af ¤   /*
38cdc2 ¤   ·* Then a slower read-write pass to move the rest of the keys
70cf50 ¤   ·* down in memory, finding duplicates as well.
6da4e3 ¤   ·*/
9e87bd ¤   out = in;
a63b20 ¤   for (; in < end; in++)
7dc418 ¤   ¤   if (*in != keyObj)
5b45d0 ¤   ¤   ¤   *out++ = *in;
72af5a
fed942 ¤   if (out < end)
3cc7a1 ¤   {
8a4957 ¤   ¤   priv->numKeys = out - priv->keyArray;
56af5a
6f401f ¤   ¤   /* Shrinking should never fail, but if it does we don't care */
84ad26 ¤   ¤   pgpContextMemRealloc(context, (void **)&priv->keyArray,
ceaf45 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·priv->numKeys * sizeof(RingObject *), 0);
ec9371 ¤   }
3aefe6 }
--a970 0007d1ba03040100227 Page 5 of pgpEnumeratedSet.c
e0af5a
1433c8 ¤   static void
84585a DestroyEnumeratedSubset(
c304f1 ¤   PGPKeySetRef¤   set)
b7bb36 {
57577e ¤   EnumeratedSubsetPriv *¤ priv = (EnumeratedSubsetPriv *)set->priv;
ec029b ¤   PGPContextRef¤  ¤   ¤   context¤= PGPGetKeySetContext(set);
1daf5a
193996 ¤   if (IsntNull(priv->keyArray))
44c7a1 ¤   {
f808ee ¤   ¤   pgpContextMemFree(context, priv->keyArray);
6350b6 ¤   ¤   priv->keyArray = NULL;
889371 ¤   }
139fd4 ¤   priv->numKeys = 0;
e25773 ¤   pgpContextMemFree(context, priv);
05efe6 }
0aaf5a
0e66dd ¤   static PGPError
e0fdb4 NewEnumeratedSubsetInternal(
7564b3 ¤   PGPKeyDBRef¤¤   ¤   db,
5b6641 ¤   PGPKeySetRef *¤ ¤   newSet)
99bb36 {
153734 ¤   PGPContextRef¤  ¤   ¤   context¤= pgpGetKeyDBContext(db);
7a1410 ¤   EnumeratedSubsetPriv *¤ priv;
7a6327 ¤   PGPKeySetRef¤   ¤   ¤   set;
719479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
77af5a
a85049 ¤   *newSet = NULL;¤¤   /* In case there's an error */
89af5a
f8c5a6 ¤   priv = (EnumeratedSubsetPriv *)pgpContextMemAlloc(context,
832cd9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(*priv), kPGPMemoryMgrFlags_Clear);
3c5786 ¤   if (IsNull(priv))
fe4030 ¤   ¤   return kPGPError_OutOfMemory;
dcaf5a
7c449e ¤   priv->keyArray = NULL;
c09fd4 ¤   priv->numKeys = 0;
6daf5a
ee2e10 ¤   err = pgpNewKeySetInternal(db, &set);
6182f0 ¤   if (IsPGPError(err))
24c9db ¤   ¤   return err;
b267c5 ¤
4dcf45 ¤   pgpAssertAddrValid(set, PGPKeySet);
3baf5a
901ac4 ¤   set->priv = priv;
7d7dd9 ¤   set->isMember = IsMemberOfEnumeratedSubset;
5576a4 ¤   set->makeUnion = MakeUnionOfEnumeratedSubsets;
4df13b ¤   set->removeKey = RemoveKeyFromEnumeratedSubset;
5f301b ¤   set->destroy = DestroyEnumeratedSubset;
0eaf5a
919fa7 ¤   *newSet = set;
43151e ¤   return kPGPError_NoErr;
9befe6 }
47af5a
4a38e5 /*
da074c ·* Create an empty enumerated key set
a8495d ·*/
42c744 ¤   PGPError
9b488c PGPNewEmptyKeySet(
38fd8f ¤   PGPKeySetRef¤   ¤   origSet,
796641 ¤   PGPKeySetRef *¤ ¤   newSet)
d1bb36 {
6e5ba4 ¤   PGPKeySetRef¤   ¤   set;
ebd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
45af5a
055808 ¤   PGPValidatePtr( newSet );
df897e ¤   *newSet = NULL;¤
220583 ¤   PGPValidateKeySet( origSet );
c2af5a
b5e750 ¤   err = NewEnumeratedSubsetInternal(origSet->keyDB, &set);
f882f0 ¤   if (IsPGPError(err))
1cc9db ¤   ¤   return err;
7daf5a
--e971 0012b832fee40100227 Page 6 of pgpEnumeratedSet.c
ab9fa7 ¤   *newSet = set;
ec2821 ¤   pgpAssertErrWithPtr( err, *newSet );
b15ea8 ¤   return err;
ddefe6 }
f8af5a
5938e5 /*
424538 ·* Create a singleton enumerated key set
1a495d ·*/
48c744 ¤   PGPError
c0caa0 PGPNewSingletonKeySet(
74fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
df6641 ¤   PGPKeySetRef *¤ ¤   newSet)
5fbb36 {
3dd7d6 ¤   PGPContextRef¤  ¤   ¤   context¤= PGPGetKeyContext(key);
5a1410 ¤   EnumeratedSubsetPriv *¤ priv;
466327 ¤   PGPKeySetRef¤   ¤   ¤   set;
599479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
2eaf5a
665808 ¤   PGPValidatePtr( newSet );
decc57 ¤   *newSet = NULL;¤¤   ¤   /* In case there's an error */
3cd5b3 ¤   PGPValidateKey( key );
49af5a
675ecc ¤   err = NewEnumeratedSubsetInternal(key->keyDB, &set);
ae82f0 ¤   if (IsPGPError(err))
5cc9db ¤   ¤   return err;
efaf5a
a90482 ¤   priv = (EnumeratedSubsetPriv *)set->priv;
f7c59e ¤   priv->keyArray = (RingObject **)pgpContextMemAlloc(context,
26bf16 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(RingObject *), 0);
f83e3c ¤   if (IsNull(priv->keyArray))
09c7a1 ¤   {
8115a5 ¤   ¤   PGPFreeKeySet(set);
4b4030 ¤   ¤   return kPGPError_OutOfMemory;
cf9371 ¤   }
3dc508 ¤   priv->numKeys = 1;
4cc404 ¤   priv->keyArray[0] = key->key;
10af5a
7f9fa7 ¤   *newSet = set;
bd2821 ¤   pgpAssertErrWithPtr( err, *newSet );
e35ea8 ¤   return err;
feefe6 }
54af5a
66af5a
e67e4d /*__Editor_settings____
c8af5a
934126 ¤   Local Variables:
d77b17 ¤   tab-width: 4
660e6c ¤   End:
4c5f8c ¤   vi: ts=4 sw=4
0e9e9b ¤   vim: si
2bd062 _____________________*/
--e067 0000f2eba5b40100228 Page 1 of pgpFileDB.c
bc38e5 /*
2b6039 ·* pgpFileDB.c
4d4958 ·* Manage PGPKeyDB's based on RingFiles
ec775e ·*
4094ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
9720c7 ·* All rights reserved
07775e ·*
a36e86 ·* $Id: pgpFileDB.c,v 1.78.10.1 1998/11/12 03:21:52 heller Exp $
67495d ·*/
88feb2 #include <stdio.h>
3c324c #include <string.h>
dcaf5a
a0e2ff #include "pgpConfig.h"
ec6773 #include "pgpMemoryMgr.h"
6aaf5a
51656b #if HAVE_FCNTL_H
ea1a5b #include <fcntl.h>¤ ¤   /* For O_CREAT, O_EXCL */
c67454 #endif
bbaf5a
8aabff #if HAVE_UNISTD_H
ca17c2 #include <unistd.h>
db7454 #endif
efaf5a
22be68 #if HAVE_SYS_STAT_H
47d4f4 #include <sys/stat.h>
9e7454 #endif
dfaf5a
d59e70 #ifndef W_OK
67cd38 #define W_OK 2
257454 #endif
4caf5a
e3979a #include "pgpKDBInt.h"
a1a4b2 #include "pgpFileRef.h"
19894b #include "pgpFileSpec.h"
9d3427 #include "pgpFileUtilities.h"
021b42 #include "pgpStrings.h"
507157 #include "pgpFileNames.h"
0aa146 #include "pgpDebug.h"
c372de #include "pgpFile.h"
e2806a #include "pgpRngRead.h"
02c26c #include "pgpContext.h"
77af5a
ec6490 /* Private data for RingFile type of PGPKeyDBRef */
f0ce0f typedef struct RingDB {
448a97 ¤   PGPContextRef¤  context;
fa990f ¤   RingFile *¤ ¤   ringFile;¤  ¤   /* RingFile for keys */
152162 ¤   PGPFile *¤  ¤   pgpFile;¤   ¤   /* PGPFile for keys */
765cf5 ¤   PFLFileSpecRef¤ mainFileRef;¤   /* Main keyring filename */
304ac4 ¤   PFLFileSpecRef¤ readFileRef;¤   /* Filename of keyring backing store */
56c95e ¤   FILE *¤ ¤   ¤   mainStdFile;¤   /* Main keyring FILE (for locking only) */
878982 ¤   RingSet *¤  ¤   mutableSet;¤¤   /* Mutable ringset */
8ca881 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* mutableSet will be NULL if !bwriteable */
5591f7 ¤   RingSet const *¤immutableSet;¤  /* Immutable ringset */
299ffd ¤   RingSet *¤  ¤   frozenSet;¤ ¤   /* Frozen copy of mutableSet */
b3b62f ¤   PGPBoolean¤ ¤   bwriteable;¤¤   /* True if a writeable database */
7cc4c2 ¤   PGPBoolean¤ ¤   bdirty;¤¤   ¤   /* True if mutableSet has been changed */
169ae7 ¤   PGPBoolean¤ ¤   bprivate;¤  ¤   /* True if a private keyring */
a6721e ¤   PGPBoolean¤ ¤   btrusted;¤  ¤   /* True if should get trust packets */
ed40c8 ¤   PGPBoolean¤ ¤   bmembuf;¤   ¤   /* True if memory-buffer based */
337a58 ¤   PGPBoolean¤ ¤   btempfile;¤ ¤   /* True if readFileRef is a temp file */
5201fb ¤   PGPKeyRingOpenFlags¤openFlags;¤ /* Flags used to open keyring */
e2af5a
0e4cff ¤   DEBUG_STRUCT_CONSTRUCTOR( RingDB )
3df8d4 } RingDB;
a8af5a
7caf5a
82ad2d /***************************** File IO ****************************/
0faf5a
6438e5 /*
a625b6 ·* Readers and writers can safely access the same key ring simultaneously.
aea1af ·* The only constraint is that at most one writer can access the file at
0f7303 ·* the same time.
--fca0 000473d5cf740100228 Page 2 of pgpFileDB.c
fe9ec0 ·*·
faab22 ·* This wasn't possible before because the bulk of the key data is loaded
df39f8 ·* on demand using an in-memory index which is built on open. This requires
75cc66 ·* that the file used for backing store never change. Our solution is to
32cbe2 ·* never use the main ring file for backing store, but instead use a static
55589b ·* copy of the file.
419ec0 ·*·
9fdc38 ·* But copying the file is a lot of overhead to suffer every time the key
db34ff ·* ring is opened. So we leave the copy lying around so the next user will
198a1d ·* be spared the overhead, amortizing the cost over several accesses.
d59ec0 ·*·
b3283a ·* These static copies are also useful as backups, and that's how they're
517c8f ·* named on disk. Every time a key ring is closed, old backups are purged.
514272 ·* Currently, all but the most recent 4 backups are removed.
31495d ·*/
a9af5a
c3900c ¤   static const char *
79c4d2 GetSeparator(
894404 ¤   PGPSize¤¤   maxFileLength )
43bb36 {
920ccc #if PGP_MACINTOSH
f302d6 ¤   (void)maxFileLength;¤   /* Avoid warning */
1faefb ¤   return " Backup ";
62db21 #else
f5c42e ¤   if ( maxFileLength >= 18 )
8b170d ¤   ¤   return "-bak-";
3f0e24 ¤   else
bedc29 ¤   ¤   return "-";
037454 #endif
9befe6 }
f8af5a
bd66dd ¤   static PGPError
5e2b51 FindMatchingBackup(
72f20a ¤   PFLFileSpecRef¤ ¤   mainFileRef,
69d2a1 ¤   PFLFileSpecRef *¤   readFileRef )
3ebb36 {
197d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
a9f9b8 ¤   PGPSize¤¤   ¤   ¤   maxFileLength;
edcaac ¤   char *¤ ¤   ¤   ¤   mainFileName = NULL;
1158a9 ¤   PFLFileInfo¤¤   ¤   mainFileInfo;
b76573 ¤   PFLDirectoryIterRef¤dirIter = kInvalidPFLDirectoryIterRef;
346bdd ¤   PFLFileSpecRef¤ ¤   fileRef = kInvalidPFLFileSpecRef;
db02ef ¤   char *¤ ¤   ¤   ¤   fileName = NULL;
72cf4d ¤   const char *¤   ¤   separator;
5d0bb2 ¤   PFLFileInfo¤¤   ¤   fileInfo;
f4d133 ¤   PFLFileSpecRef¤ ¤   newestFileRef = kInvalidPFLFileSpecRef;
619170 ¤   time_t¤ ¤   ¤   ¤   newestFileModTime = 0;¤ /* Avoid warning */
1b1f1a ¤   PGPBoolean¤ ¤   ¤   valid;
e65e41 ¤   PGPUInt32¤  ¤   ¤   number;
55af5a
fdf3ae ¤   *readFileRef = NULL;
b9af5a
ec375c ¤   err = PFLGetFileSpecName( mainFileRef, &mainFileName );
08054e ¤   if ( IsPGPError( err ) )
d348b9 ¤   ¤   goto cleanup;
d9af5a
07a4c3 ¤   err = PFLGetMaxFileSpecNameLength( mainFileRef, &maxFileLength );
f9054e ¤   if ( IsPGPError( err ) )
f448b9 ¤   ¤   goto cleanup;
43af5a
12af23 ¤   separator = GetSeparator( maxFileLength );
b1af5a
070ead ¤   err = PFLGetFileInfo( mainFileRef, &mainFileInfo );
53054e ¤   if ( IsPGPError( err ) )
d248b9 ¤   ¤   goto cleanup;
d4af5a
c37410 ¤   err = PFLGetParentDirectory( mainFileRef, &fileRef );
2d054e ¤   if ( IsPGPError( err ) )
dd48b9 ¤   ¤   goto cleanup;
edaf5a
04998f ¤   err = PFLNewDirectoryIter( fileRef, &dirIter );
47054e ¤   if ( IsPGPError( err ) )
--80ee 00022d72a1140100228 Page 3 of pgpFileDB.c
1848b9 ¤   ¤   goto cleanup;
f7af5a
558c1f ¤   PFLFreeFileSpec( fileRef );
80830a ¤   fileRef = NULL;
15af5a
5d5a6f ¤   while ( IsntPGPError( err = PFLNextFileInDirectory( dirIter, &fileRef ) ) )
64c7a1 ¤   {
e02541 ¤   ¤   err = PFLGetFileSpecName( fileRef, &fileName );
b6be18 ¤   ¤   if ( IsPGPError( err ) )
3c8f0c ¤   ¤   ¤   goto cleanup;
d3af5a
ffbf7c ¤   ¤   err = PGPVerifyNumberFileName( mainFileName, separator, fileName,
cb8e50 ¤   ¤   ¤   ¤   ¤   maxFileLength + 1, &valid, &number );
02be18 ¤   ¤   if ( IsPGPError( err ) )
fb8f0c ¤   ¤   ¤   goto cleanup;
89af5a
2dfa54 ¤   ¤   if ( valid )
955b34 ¤   ¤   {
360acc ¤   ¤   ¤   err = PFLGetFileInfo( fileRef, &fileInfo );
bd8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
8d0658 ¤   ¤   ¤   ¤   goto cleanup;
95af5a
8d7aad ¤   ¤   ¤   /*
11589d ¤   ¤   ¤   ·* XXX: We may want to rethink this heuristic.
e2103d ¤   ¤   ¤   ·* ·····In particular, what happens if a backup file
34b6d5 ¤   ¤   ¤   ·* ·····exists which is newer than the current time?
577d36 ¤   ¤   ¤   ·* ·····Also, it would be nice to check file meta
243eb9 ¤   ¤   ¤   ·* ·····info (like creator/type on the Mac) to make
31194c ¤   ¤   ¤   ·* ·····sure it matches.
be8753 ¤   ¤   ¤   ·*/
640c32 ¤   ¤   ¤   if ( ( fileInfo.flags & kPGPFileInfo_IsPlainFile ) &&
2a52ca ¤   ¤   ¤   ¤   ·fileInfo.dataLength == mainFileInfo.dataLength &&
67fd8e ¤   ¤   ¤   ¤   ·fileInfo.modificationTime >= mainFileInfo.modificationTime &&
9137bd ¤   ¤   ¤   ¤   ·( newestFileRef == kInvalidPFLFileSpecRef ||
431ac8 ¤   ¤   ¤   ¤   ···newestFileModTime < fileInfo.modificationTime ) )
63f776 ¤   ¤   ¤   {
353944 ¤   ¤   ¤   ¤   if ( newestFileRef != kInvalidPFLFileSpecRef )
55b1e6 ¤   ¤   ¤   ¤   ¤   PFLFreeFileSpec( newestFileRef );
85c253 ¤   ¤   ¤   ¤   newestFileRef = fileRef;
e1e83f ¤   ¤   ¤   ¤   fileRef = kInvalidPFLFileSpecRef;
97eac7 ¤   ¤   ¤   ¤   newestFileModTime = fileInfo.modificationTime;
41a3a6 ¤   ¤   ¤   }
340fe4 ¤   ¤   }
23af5a
da0184 ¤   ¤   if ( fileRef != kInvalidPFLFileSpecRef )
b05b34 ¤   ¤   {
71c2b6 ¤   ¤   ¤   PFLFreeFileSpec( fileRef );
9a0f9b ¤   ¤   ¤   fileRef = NULL;
eb0fe4 ¤   ¤   }
12af5a
2f4dea ¤   ¤   PGPFreeData( fileName );
4a42a0 ¤   ¤   fileName = NULL;
7c9371 ¤   }
c5d508 ¤   if ( err != kPGPError_EndOfIteration )
df48b9 ¤   ¤   goto cleanup;
e2af5a
7dce4b ¤   if ( newestFileRef == kInvalidPFLFileSpecRef )
29c7a1 ¤   {
d9e749 ¤   ¤   err = kPGPError_FileNotFound;
2a48b9 ¤   ¤   goto cleanup;
1e9371 ¤   }
b3af5a
f09b74 ¤   /* XXX: Maybe check file contents here, just to be sure? */
81af5a
cc6493 ¤   err = kPGPError_NoErr;
77a925 ¤   *readFileRef = newestFileRef;
f38df3 ¤   /* We're no longer responsible for this */
3eeb35 ¤   newestFileRef = kInvalidPFLFileSpecRef;¤
c367c5 ¤
c668cb cleanup:
155319 ¤   if ( fileRef != kInvalidPFLFileSpecRef )
2207e3 ¤   ¤   PFLFreeFileSpec( fileRef );
--e984 0009bfa7d4940100228 Page 4 of pgpFileDB.c
242fba ¤   if ( newestFileRef != kInvalidPFLFileSpecRef )
3e691c ¤   ¤   PFLFreeFileSpec( newestFileRef );
d9bd5a ¤   if ( dirIter != kInvalidPFLDirectoryIterRef )
35ff98 ¤   ¤   PFLFreeDirectoryIter( dirIter );
182912 ¤   if ( IsntNull( mainFileName ) )
0dba03 ¤   ¤   PGPFreeData( mainFileName );
505991 ¤   if ( IsntNull( fileName ) )
eb4dea ¤   ¤   PGPFreeData( fileName );
705ea8 ¤   return err;
f1efe6 }
21af5a
d166dd ¤   static PGPError
27ad8b CopyStdFile(
950185 ¤   PGPMemoryMgrRef¤memoryMgr,
5ed550 ¤   FILE *¤ ¤   ¤   origFile,
7ecf40 ¤   FILE *¤ ¤   ¤   destFile )
5bbb36 {
d54bfa ¤   int¤¤   ¤   stdErr;
6e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
0809d2 ¤   char *¤ ¤   buffer = NULL;
e9406f ¤   PGPSize¤¤   bufferSize = 16 * 1024L;
28b296 ¤   PGPSize¤¤   length;
5faf5a
01f37e ¤   rewind( origFile );
816579 ¤   rewind( destFile );
50af5a
25ce12 ¤   buffer = (char *)PGPNewData( memoryMgr, bufferSize, 0 );
647957 ¤   if ( IsNull( buffer ) )
5fc7a1 ¤   {
7fbce1 ¤   ¤   err = kPGPError_OutOfMemory;
4548b9 ¤   ¤   goto cleanup;
ab9371 ¤   }
ccaf5a
32dbc5 ¤   while ( ( length = fread( buffer, 1, bufferSize, origFile ) ) > 0 )
bac7a1 ¤   {
0027f0 ¤   ¤   if ( length != fwrite( buffer, 1, length, destFile ) )
8f5b34 ¤   ¤   {
aec037 ¤   ¤   ¤   stdErr = ferror( destFile );
798a8b ¤   ¤   ¤   if (
9fea97 ¤   ¤   ¤   ¤   ¤   0
99a7d6 #ifdef ENOSPC
ef399d ¤   ¤   ¤   ¤   ¤   || stdErr == ENOSPC
1e7454 #endif
b8ec94 #ifdef EFBIG
137eae ¤   ¤   ¤   ¤   ¤   || stdErr == EFBIG
947454 #endif
1ea81e ¤   ¤   ¤   ¤   ¤   )
17f776 ¤   ¤   ¤   {
3ee92a ¤   ¤   ¤   ¤   err = kPGPError_DiskFull;
7ea3a6 ¤   ¤   ¤   }
97bb8c ¤   ¤   ¤   else
5af776 ¤   ¤   ¤   {
5a120f ¤   ¤   ¤   ¤   err = kPGPError_WriteFailed;
f6a3a6 ¤   ¤   ¤   }
398f0c ¤   ¤   ¤   goto cleanup;
730fe4 ¤   ¤   }
299371 ¤   }
2627ce ¤   if ( !feof( origFile ) )
a4c7a1 ¤   {
4e580b ¤   ¤   err = kPGPError_ReadFailed;
9e48b9 ¤   ¤   goto cleanup;
219371 ¤   }
30af5a
9168cb cleanup:
b64794 ¤   if ( IsntNull( buffer ) )
6cf097 ¤   ¤   PGPFreeData( buffer );
dc5ea8 ¤   return err;
c9efe6 }
d7af5a
7666dd ¤   static PGPError
202127 MakeMatchingBackup(
9bf20a ¤   PFLFileSpecRef¤ ¤   mainFileRef,
--872e 000d30e7e7640100228 Page 5 of pgpFileDB.c
2c19f4 ¤   FILE *¤ ¤   ¤   ¤   mainStdFile,
18eda8 ¤   PGPFileType¤¤   ¤   fileType,
c1d2a1 ¤   PFLFileSpecRef *¤   readFileRef )
c3bb36 {
3d7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
0ac659 ¤   PGPMemoryMgrRef¤¤   memoryMgr = PFLGetFileSpecMemoryMgr( mainFileRef );
636bdd ¤   PFLFileSpecRef¤ ¤   fileRef = kInvalidPFLFileSpecRef;
2ca31d ¤   PFLFileSpecRef¤ ¤   tempFileRef = kInvalidPFLFileSpecRef;
c7caac ¤   char *¤ ¤   ¤   ¤   mainFileName = NULL;
5102ef ¤   char *¤ ¤   ¤   ¤   fileName = NULL;
5bf9b8 ¤   PGPSize¤¤   ¤   ¤   maxFileLength;
e4cf4d ¤   const char *¤   ¤   separator;
aa5e41 ¤   PGPUInt32¤  ¤   ¤   number;
9475c6 ¤   PGPBoolean¤ ¤   ¤   exists;
b0b72e ¤   PGPBoolean¤ ¤   ¤   weOpenedMainFile = FALSE;
e38b4f ¤   FILE *¤ ¤   ¤   ¤   stdFile = NULL;
42af5a
f1f3ae ¤   *readFileRef = NULL;
89af5a
0a8b59 ¤   /* First copy the ring to a temp file in the backup directory */
61af5a
57c94b ¤   err = PFLFileSpecGetUniqueSpec( mainFileRef, &tempFileRef );
da054e ¤   if ( IsPGPError( err ) )
e648b9 ¤   ¤   goto cleanup;
3aaf5a
0dacf7 ¤   err = pgpFileRefStdIOOpen( tempFileRef, kPGPFileOpenStdWriteFlags,
0dd478 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···fileType, &stdFile );
56054e ¤   if ( IsPGPError( err ) )
ea48b9 ¤   ¤   goto cleanup;
36af5a
0b9c0d ¤   if ( IsNull( mainStdFile ) )
4cc7a1 ¤   {
af88ac ¤   ¤   err = pgpFileRefStdIOOpen( mainFileRef, kPGPFileOpenReadPerm,
3a8449 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileTypeNone, &mainStdFile );
25be18 ¤   ¤   if ( IsPGPError( err ) )
1d8f0c ¤   ¤   ¤   goto cleanup;
acaf5a
8ed159 ¤   ¤   weOpenedMainFile = TRUE;
359371 ¤   }
3caf5a
6117aa ¤   err = CopyStdFile( memoryMgr, mainStdFile, stdFile );
19054e ¤   if ( IsPGPError( err ) )
fa48b9 ¤   ¤   goto cleanup;
d667c5 ¤
ff41b5 ¤   pgpStdIOClose( stdFile );
656df9 ¤   stdFile = NULL;
0caf5a
e0af5a
a607e8 ¤   /* Next, we find a new backup name to rename to */
5baf5a
34a4c3 ¤   err = PFLGetMaxFileSpecNameLength( mainFileRef, &maxFileLength );
57054e ¤   if ( IsPGPError( err ) )
4b48b9 ¤   ¤   goto cleanup;
71af5a
827a72 ¤   err = PFLCopyFileSpec( mainFileRef, &fileRef );
d9054e ¤   if ( IsPGPError( err ) )
4b48b9 ¤   ¤   goto cleanup;
f4af5a
8c375c ¤   err = PFLGetFileSpecName( mainFileRef, &mainFileName );
22054e ¤   if ( IsPGPError( err ) )
e148b9 ¤   ¤   goto cleanup;
b3af5a
73af23 ¤   separator = GetSeparator( maxFileLength );
a4af5a
0c9749 ¤   fileName = (char *)PGPNewData( memoryMgr, maxFileLength + 1, 0 );
e461ae ¤   if ( IsNull( fileName ) )
a2c7a1 ¤   {
71bce1 ¤   ¤   err = kPGPError_OutOfMemory;
2c48b9 ¤   ¤   goto cleanup;
c19371 ¤   }
f3af5a
d372c7 ¤   for (number = 1; ; number++ )
--d40e 000d59194d040100228 Page 6 of pgpFileDB.c
f7c7a1 ¤   {
1ead35 ¤   ¤   err = PGPNewNumberFileName( mainFileName, separator, number,
2cc33b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   maxFileLength + 1, fileName );
75be18 ¤   ¤   if ( IsPGPError( err ) )
cb8f0c ¤   ¤   ¤   goto cleanup;
a7af5a
e7a30c ¤   ¤   err = PFLSetFileSpecName( fileRef, fileName );
5dbe18 ¤   ¤   if ( IsPGPError( err ) )
e58f0c ¤   ¤   ¤   goto cleanup;
f3af5a
7e8064 ¤   ¤   err = PFLFileSpecExists( fileRef, &exists );
60be18 ¤   ¤   if ( IsPGPError( err ) )
478f0c ¤   ¤   ¤   goto cleanup;
25af5a
e1fd46 ¤   ¤   if ( !exists )
395b34 ¤   ¤   {
0aa376 ¤   ¤   ¤   err = PFLFileSpecRename( tempFileRef, fileName );
be3c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
e2f622 ¤   ¤   ¤   ¤   break;
3a6b56 ¤   ¤   ¤   else if ( err != kPGPError_ItemNotFound )
210658 ¤   ¤   ¤   ¤   goto cleanup;
a70fe4 ¤   ¤   }
1f9371 ¤   }
5faf5a
35212b ¤   *readFileRef = fileRef;
a9be47 ¤   fileRef = NULL;¤¤   /* We're no longer responsible for it */
a4af5a
f268cb cleanup:
ddf1e5 ¤   if ( tempFileRef != kInvalidPFLFileSpecRef )
9566d3 ¤   ¤   PFLFreeFileSpec( tempFileRef );
975319 ¤   if ( fileRef != kInvalidPFLFileSpecRef )
4b07e3 ¤   ¤   PFLFreeFileSpec( fileRef );
da2912 ¤   if ( IsntNull( mainFileName ) )
a4ba03 ¤   ¤   PGPFreeData( mainFileName );
5b5991 ¤   if ( IsntNull( fileName ) )
4d4dea ¤   ¤   PGPFreeData( fileName );
c33445 ¤   if ( IsntNull( stdFile ) )
b376bd ¤   ¤   pgpStdIOClose( stdFile );
dcb0de ¤   if ( weOpenedMainFile && IsntNull( mainStdFile ) )
07b26e ¤   ¤   pgpStdIOClose( mainStdFile );
da5ea8 ¤   return err;
4befe6 }
15af5a
b666dd ¤   static PGPError
9ece34 MakeTempCopy(
16b85d ¤   PFLFileSpecRef¤ ¤   ¤   mainFileRef,
53e874 ¤   FILE *¤ ¤   ¤   ¤   ¤   mainStdFile,
d54acc ¤   PGPFileType¤¤   ¤   ¤   fileType,
be18fb ¤   PFLFileSpecRef *¤   ¤   readFileRef )
f2bb36 {
a27d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
3d06f8 ¤   PGPMemoryMgrRef¤¤   context = PFLGetFileSpecMemoryMgr( mainFileRef );
c66bdd ¤   PFLFileSpecRef¤ ¤   fileRef = kInvalidPFLFileSpecRef;
568b4f ¤   FILE *¤ ¤   ¤   ¤   stdFile = NULL;
28b72e ¤   PGPBoolean¤ ¤   ¤   weOpenedMainFile = FALSE;
9faf5a
a8e32f ¤   err = PFLGetTempFileSpec( context, kInvalidPFLFileSpecRef, &fileRef );
ad054e ¤   if ( IsPGPError( err ) )
dd48b9 ¤   ¤   goto cleanup;
44af5a
c3240c ¤   err = pgpFileRefStdIOOpen( fileRef, kPGPFileOpenStdWriteFlags,
9cd478 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···fileType, &stdFile );
9e054e ¤   if ( IsPGPError( err ) )
5948b9 ¤   ¤   goto cleanup;
47af5a
e79c0d ¤   if ( IsNull( mainStdFile ) )
c7c7a1 ¤   {
e588ac ¤   ¤   err = pgpFileRefStdIOOpen( mainFileRef, kPGPFileOpenReadPerm,
038449 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileTypeNone, &mainStdFile );
e6be18 ¤   ¤   if ( IsPGPError( err ) )
f18f0c ¤   ¤   ¤   goto cleanup;
d5af5a
--a825 00077346a3040100228 Page 7 of pgpFileDB.c
94d159 ¤   ¤   weOpenedMainFile = TRUE;
959371 ¤   }
67af5a
11271a ¤   err = CopyStdFile( context, mainStdFile, stdFile );
72054e ¤   if ( IsPGPError( err ) )
c148b9 ¤   ¤   goto cleanup;
7caf5a
65212b ¤   *readFileRef = fileRef;
bdbe47 ¤   fileRef = NULL;¤¤   /* We're no longer responsible for it */
eeaf5a
1f68cb cleanup:
f05319 ¤   if ( fileRef != kInvalidPFLFileSpecRef )
7b07e3 ¤   ¤   PFLFreeFileSpec( fileRef );
fc3445 ¤   if ( IsntNull( stdFile ) )
7076bd ¤   ¤   pgpStdIOClose( stdFile );
e0b0de ¤   if ( weOpenedMainFile && IsntNull( mainStdFile ) )
4bb26e ¤   ¤   pgpStdIOClose( mainStdFile );
265ea8 ¤   return err;
36efe6 }
2baf5a
ad3a75 /* This struct is only used by PurgeOldBackups() */
e61741 typedef struct
7fbb36 {
2e0392 ¤   PFLFileSpecRef¤ fileRef;
072dde ¤   time_t¤ ¤   ¤   modTime;
3c9508 } PGPFileTimeInfo;
77af5a
f366dd ¤   static PGPError
dfd461 PurgeOldBackups(
abac0a ¤   PFLFileSpecRef¤ ¤   mainFileRef )
e8bb36 {
527d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
86cf4d ¤   const char *¤   ¤   separator;
3df9b8 ¤   PGPSize¤¤   ¤   ¤   maxFileLength;
86caac ¤   char *¤ ¤   ¤   ¤   mainFileName = NULL;
ac58a9 ¤   PFLFileInfo¤¤   ¤   mainFileInfo;
d16573 ¤   PFLDirectoryIterRef¤dirIter = kInvalidPFLDirectoryIterRef;
966bdd ¤   PFLFileSpecRef¤ ¤   fileRef = kInvalidPFLFileSpecRef;
2e02ef ¤   char *¤ ¤   ¤   ¤   fileName = NULL;
1d0bb2 ¤   PFLFileInfo¤¤   ¤   fileInfo;
f6acd4 ¤   PGPFileTimeInfo¤¤   newestFiles[4];
1ea929 ¤   int¤¤   ¤   ¤   ¤   maxNewest = sizeof(newestFiles) /
a1da73 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(newestFiles[0]);
0bc43e ¤   PGPFileTimeInfo¤¤   olderFiles[2][2];
82d821 ¤   long¤   ¤   ¤   ¤   olderFileAges[2] = { 60 * 60L, 24 * 60 * 60L };
66984d ¤   int¤¤   ¤   ¤   ¤   maxOlder = sizeof(olderFiles) / sizeof(olderFiles[0]);
54a2ee ¤   PFLFileSpecRef¤ ¤   filesToDelete[32];
99ae39 ¤   int¤¤   ¤   ¤   ¤   maxFilesToDelete = sizeof(filesToDelete) /
f10953 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···sizeof(filesToDelete[0]);
f26c1d ¤   int¤¤   ¤   ¤   ¤   numFilesToDelete = 0;
5a5d14 ¤   int¤¤   ¤   ¤   ¤   i;
023d3b ¤   time_t¤ ¤   ¤   ¤   now = time( NULL );
b01f1a ¤   PGPBoolean¤ ¤   ¤   valid;
a33819 ¤   PGPBoolean¤ ¤   ¤   deleteThisFile;
875e41 ¤   PGPUInt32¤  ¤   ¤   number;
14af5a
c2cf44 ¤   pgpAssert( maxOlder == sizeof(olderFileAges) / sizeof(olderFileAges[0]) );
6dc9b1 ¤   (void)olderFileAges;
1baf5a
82f6a3 ¤   for (i = 0; i < maxNewest; i++)
fa0978 ¤   ¤   newestFiles[i].fileRef = kInvalidPFLFileSpecRef;
9341c8 ¤   for (i = 0; i < maxOlder; i++)
b1bace ¤   ¤   olderFiles[i][0].fileRef = olderFiles[i][1].fileRef =
a52b00 ¤   ¤   ¤   ¤   kInvalidPFLFileSpecRef;
e267c5 ¤
b9375c ¤   err = PFLGetFileSpecName( mainFileRef, &mainFileName );
28054e ¤   if ( IsPGPError( err ) )
8b48b9 ¤   ¤   goto cleanup;
22af5a
daa4c3 ¤   err = PFLGetMaxFileSpecNameLength( mainFileRef, &maxFileLength );
e3054e ¤   if ( IsPGPError( err ) )
7748b9 ¤   ¤   goto cleanup;
--8295 000633a62e940100228 Page 8 of pgpFileDB.c
e0af5a
c0af23 ¤   separator = GetSeparator( maxFileLength );
1eaf5a
8b0ead ¤   err = PFLGetFileInfo( mainFileRef, &mainFileInfo );
19054e ¤   if ( IsPGPError( err ) )
9048b9 ¤   ¤   goto cleanup;
82af5a
7e7410 ¤   err = PFLGetParentDirectory( mainFileRef, &fileRef );
48054e ¤   if ( IsPGPError( err ) )
9a48b9 ¤   ¤   goto cleanup;
a4af5a
3c998f ¤   err = PFLNewDirectoryIter( fileRef, &dirIter );
be054e ¤   if ( IsPGPError( err ) )
6648b9 ¤   ¤   goto cleanup;
81af5a
d98c1f ¤   PFLFreeFileSpec( fileRef );
0c830a ¤   fileRef = NULL;
acaf5a
405a6f ¤   while ( IsntPGPError( err = PFLNextFileInDirectory( dirIter, &fileRef ) ) )
fcc7a1 ¤   {
0a2541 ¤   ¤   err = PFLGetFileSpecName( fileRef, &fileName );
cebe18 ¤   ¤   if ( IsPGPError( err ) )
988f0c ¤   ¤   ¤   goto cleanup;
ffaf5a
dabf7c ¤   ¤   err = PGPVerifyNumberFileName( mainFileName, separator, fileName,
458e50 ¤   ¤   ¤   ¤   ¤   maxFileLength + 1, &valid, &number );
0abe18 ¤   ¤   if ( IsPGPError( err ) )
228f0c ¤   ¤   ¤   goto cleanup;
56af5a
cefa54 ¤   ¤   if ( valid )
7b5b34 ¤   ¤   {
db0acc ¤   ¤   ¤   err = PFLGetFileInfo( fileRef, &fileInfo );
078370 ¤   ¤   ¤   if ( IsPGPError( err ) )
8e0658 ¤   ¤   ¤   ¤   goto cleanup;
8aaf5a
56deb8 ¤   ¤   ¤   deleteThisFile = TRUE;
d9af5a
9c1907 ¤   ¤   ¤   if ( fileInfo.modificationTime <= now )
7af776 ¤   ¤   ¤   {
37479c ¤   ¤   ¤   ¤   i = 0;
4c3046 ¤   ¤   ¤   ¤   while ( i < maxNewest &&
a0725a ¤   ¤   ¤   ¤   ¤   ¤   newestFiles[i].fileRef != kInvalidPFLFileSpecRef &&
f03fb9 ¤   ¤   ¤   ¤   ¤   ¤   newestFiles[i].modTime > fileInfo.modificationTime )
9771b6 ¤   ¤   ¤   ¤   ¤   i++;
9486af ¤   ¤   ¤   ¤   if ( i < maxNewest )
3672c3 ¤   ¤   ¤   ¤   {
7278b9 ¤   ¤   ¤   ¤   ¤   if ( newestFiles[ maxNewest - 1 ].fileRef
952e01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   != kInvalidPFLFileSpecRef )
554859 ¤   ¤   ¤   ¤   ¤   {
5d080c ¤   ¤   ¤   ¤   ¤   ¤   if ( numFilesToDelete >= maxFilesToDelete )
6fd46c ¤   ¤   ¤   ¤   ¤   ¤   ¤   goto overflow;
e08acd ¤   ¤   ¤   ¤   ¤   ¤   filesToDelete[ numFilesToDelete++ ] =
eb4013 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newestFiles[ maxNewest - 1 ].fileRef;
bf1c89 ¤   ¤   ¤   ¤   ¤   }
e0f130 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory( newestFiles + i, newestFiles + i + 1,
454efe ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···( maxNewest - i - 1 )
7b414d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···* sizeof( newestFiles[0] ) );
a1af5a
2d303f ¤   ¤   ¤   ¤   ¤   newestFiles[i].modTime = fileInfo.modificationTime;
52ecb7 ¤   ¤   ¤   ¤   ¤   err = PFLCopyFileSpec( fileRef,·
33bd7f ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newestFiles[ i ].fileRef );
698025 ¤   ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
23de23 ¤   ¤   ¤   ¤   ¤   ¤   goto cleanup;
3e456d ¤   ¤   ¤   ¤   ¤   deleteThisFile = FALSE;
532613 ¤   ¤   ¤   ¤   }
76a3a6 ¤   ¤   ¤   }
90cc15 ¤   ¤   ¤   if ( deleteThisFile )
b6f776 ¤   ¤   ¤   {
19f17e ¤   ¤   ¤   ¤   if ( numFilesToDelete >= maxFilesToDelete )
4a9bd3 ¤   ¤   ¤   ¤   ¤   goto overflow;
7b197e ¤   ¤   ¤   ¤   err = PFLCopyFileSpec( fileRef,
633966 ¤   ¤   ¤   ¤   ¤   ¤   &filesToDelete[ numFilesToDelete ] );
--dcc7 0008bcf9dee40100228 Page 9 of pgpFileDB.c
14869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
663150 ¤   ¤   ¤   ¤   ¤   goto cleanup;
b70940 ¤   ¤   ¤   ¤   numFilesToDelete++;
ada3a6 ¤   ¤   ¤   }
1a0fe4 ¤   ¤   }
83af5a
940184 ¤   ¤   if ( fileRef != kInvalidPFLFileSpecRef )
4f5b34 ¤   ¤   {
6bc2b6 ¤   ¤   ¤   PFLFreeFileSpec( fileRef );
400f9b ¤   ¤   ¤   fileRef = NULL;
d20fe4 ¤   ¤   }
45af5a
334dea ¤   ¤   PGPFreeData( fileName );
7242a0 ¤   ¤   fileName = NULL;
ac9371 ¤   }
b6d508 ¤   if ( err != kPGPError_EndOfIteration )
b848b9 ¤   ¤   goto cleanup;
cfaf5a
9da50c overflow:¤  /* Overflowing is currently ignored, we'll delete the rest later */
826493 ¤   err = kPGPError_NoErr;
547223 ¤   goto cleanup;
90af5a
8f68cb cleanup:
9f5319 ¤   if ( fileRef != kInvalidPFLFileSpecRef )
3e07e3 ¤   ¤   PFLFreeFileSpec( fileRef );
e7bd5a ¤   if ( dirIter != kInvalidPFLDirectoryIterRef )
33ff98 ¤   ¤   PFLFreeDirectoryIter( dirIter );
ed2912 ¤   if ( IsntNull( mainFileName ) )
07ba03 ¤   ¤   PGPFreeData( mainFileName );
ad5991 ¤   if ( IsntNull( fileName ) )
b24dea ¤   ¤   PGPFreeData( fileName );
3bb3c7 ¤   for ( i = 0; i < maxNewest; i++ )
fc65c7 ¤   ¤   if ( newestFiles[i].fileRef != kInvalidPFLFileSpecRef )
0b8bd2 ¤   ¤   ¤   PFLFreeFileSpec( newestFiles[i].fileRef );
ffdd29 ¤   for ( i = 0; i < numFilesToDelete; i++ )
f0c7a1 ¤   {
ae82e7 ¤   ¤   if ( filesToDelete[i] != kInvalidPFLFileSpecRef )
6b5b34 ¤   ¤   {
a31af4 ¤   ¤   ¤   PFLFileSpecDelete( filesToDelete[i] );
743d69 ¤   ¤   ¤   PFLFreeFileSpec( filesToDelete[i] );
990fe4 ¤   ¤   }
eb9371 ¤   }
e75ea8 ¤   return err;
0aefe6 }
25af5a
d795d7 /*·
bf2489 ·* Open the specified ringfile. ·If writeable flag is clear, it will be
81d0b2 ·* forced read-only, otherwise whether it is writeable will depend on
ee77ec ·* permissions. ·Returns a filled-in rdb structure.
930289 ·* Note that "private" is not a concept of the underlying library, but
ac99ea ·* is used in the add function to decide which objects to accept.
21495d ·*/
0266dd ¤   static PGPError
eb69e2 OpenKeyRing (
ae3163 ¤   PGPContextRef¤  cdkContext,
79a0f7 ¤   PFLConstFileSpecRef fileRef, PGPKeyRingOpenFlags openFlags,
73b38a ¤   RingPool *ringpool, RingDB *rdb)
1ebb36 {
9af117 ¤   PFLFileSpecRef¤ mainFileRef = kInvalidPFLFileSpecRef;¤  /* Main ring */
3f91e3 ¤   PFLFileSpecRef¤ readFileRef = kInvalidPFLFileSpecRef;¤  /* Latest backup */
657d2e ¤   FILE *¤ ¤   ¤   mainStdFile¤= NULL;¤/* Stdio file of main ring */
6a7e0e ¤   FILE *¤ ¤   ¤   readStdFile¤= NULL;¤/* Stdio file of latest backup */
feb979 ¤   PGPFile *¤  ¤   pgpFile¤¤   = NULL;
98f5c3 ¤   RingFile *¤ ¤   ringFile¤   = NULL;
20e117 ¤   RingSet const *¤immutableSet = NULL;
716cb6 ¤   RingSet *¤  ¤   mutableSet¤ = NULL;
d03ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
4000a6 ¤   PGPBoolean¤ ¤   fileExists;
0e67c5 ¤
60660e ¤   PGPBoolean¤ trusted¤¤   = !!( openFlags & kPGPKeyRingOpenFlags_Trusted );
7ff778 ¤   PGPBoolean¤ priv¤   ¤   = !!( openFlags & kPGPKeyRingOpenFlags_Private );
8b3089 ¤   PGPBoolean¤ writeable¤  = !!( openFlags & kPGPKeyRingOpenFlags_Mutable );
--25f7 000b41871cc40100228 Page 10 of pgpFileDB.c
cacfb0 ¤   PGPFileType¤fileType = priv ? kPGPFileTypePrivRing : kPGPFileTypePubRing;
bfaf5a
498de5 ¤   if( ( openFlags & kPGPKeyRingOpenFlags_Create ) != 0 && ! writeable )
b6c7a1 ¤   {
07edb9 ¤   ¤   pgpDebugMsg( "OpenKeyRing(): Cannot create read-only keyring" );
3819d3 ¤   ¤   err = kPGPError_BadParams;
9a48b9 ¤   ¤   goto cleanup;
de9371 ¤   }
c567c5 ¤
73fe2a ¤   err = PFLFileSpecExists( (PFLFileSpecRef) fileRef, &fileExists );
ae69c3 ¤   if( IsntPGPError( err ) && ! fileExists )
0ec7a1 ¤   {
e904ac ¤   ¤   if( ( openFlags & kPGPKeyRingOpenFlags_Create ) == 0 )
4f5b34 ¤   ¤   {
f3dba7 ¤   ¤   ¤   err = kPGPError_FileNotFound;
1a0fe4 ¤   ¤   }
289371 ¤   }
29054e ¤   if ( IsPGPError( err ) )
1d48b9 ¤   ¤   goto cleanup;
64af5a
649ff1 ¤   err = PFLCopyFileSpec(fileRef, &mainFileRef);
23054e ¤   if ( IsPGPError( err ) )
ef48b9 ¤   ¤   goto cleanup;
86af5a
c54e71 ¤   if ( writeable )
44c7a1 ¤   {
63394e ¤   ¤   PGPFileOpenFlags¤   fileOpenFlags;
3b1b52 ¤   ¤
6f252d ¤   ¤   mutableSet = ringSetCreate (ringpool);
e0ee6c ¤   ¤   if ( IsNull( mutableSet ) )
4e5b34 ¤   ¤   {
a3b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
938f0c ¤   ¤   ¤   goto cleanup;
510fe4 ¤   ¤   }
13af5a
64fd60 ¤   ¤   /* Lock the main keyring file to ensure exclusive access */
e07a7f ¤   ¤   fileOpenFlags = kPGPFileOpenReadWritePerm | kPGPFileOpenLockFile;
76af5a
9abdd6 ¤   ¤   err = pgpFileRefStdIOOpen( mainFileRef, fileOpenFlags, fileType,
05a56b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&mainStdFile );
c8af5a
cfbe18 ¤   ¤   if ( IsPGPError( err ) )
b75b34 ¤   ¤   {
7d031e ¤   ¤   ¤   if ( err == kPGPError_FileNotFound &&
263d6b ¤   ¤   ¤   ¤   ·( openFlags & kPGPKeyRingOpenFlags_Create ) )
6ef776 ¤   ¤   ¤   {
1e2321 ¤   ¤   ¤   ¤   err = pgpCreateFile( mainFileRef, fileType );
ae869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
d33150 ¤   ¤   ¤   ¤   ¤   goto cleanup;
f4af5a
c15d15 ¤   ¤   ¤   ¤   err = pgpFileRefStdIOOpen( mainFileRef, fileOpenFlags,
c12b56 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···fileType, &mainStdFile );
34a3a6 ¤   ¤   ¤   }
d88370 ¤   ¤   ¤   if ( IsPGPError( err ) )
4c0658 ¤   ¤   ¤   ¤   goto cleanup;
970fe4 ¤   ¤   }
e89371 ¤   }
a80e24 ¤   else
23c7a1 ¤   {
ec0654 ¤   ¤   /* Immutable keydb's don't need mutableSet */
82254f ¤   ¤   mutableSet = NULL;
5f9371 ¤   }
d8af5a
45af5a
d2e874 ¤   err = FindMatchingBackup( mainFileRef, &readFileRef );
7c054e ¤   if ( IsPGPError( err ) )
56c7a1 ¤   {
0ee375 ¤   ¤   err = MakeMatchingBackup( mainFileRef, mainStdFile, fileType,
4ccb13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&readFileRef );
553d2a ¤   ¤   if ( err == kPGPError_FileLocked )
e98f0c ¤   ¤   ¤   goto cleanup;
b49371 ¤   }
--fc88 000436fbae640100228 Page 11 of pgpFileDB.c
e0af5a
94a3a2 ¤   if ( IsPGPError( err ) || ( !writeable && PFL_PLATFORM_UNSAFE_DELETE ) )
a5c7a1 ¤   {
ab1b17 ¤   ¤   /*
2c00fd ¤   ¤   ·* If we failed to create a matching backup file, or
829e8b ¤   ¤   ·* if deletes aren't safe on this platform and we're not a writer,
5bf841 ¤   ¤   ·* then we need to make a local copy of the keyring as backing store.
a19de3 ¤   ¤   ·*/
2e41b3 ¤   ¤   err = MakeTempCopy( mainFileRef, mainStdFile, fileType, &readFileRef );
66be18 ¤   ¤   if ( IsPGPError( err ) )
848f0c ¤   ¤   ¤   goto cleanup;
5fc860 ¤   ¤   rdb->btempfile = TRUE;
c79371 ¤   }
360e24 ¤   else
36c7a1 ¤   {
a8528d ¤   ¤   rdb->btempfile = FALSE;
809371 ¤   }
95af5a
a29e9b ¤   /* Open the read-only file which will be used for backing store */
f115c0 ¤   err = pgpFileRefStdIOOpen( readFileRef, kPGPFileOpenReadPerm,
64dbdb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileTypeNone, &readStdFile );
50054e ¤   if ( IsPGPError( err ) )
1348b9 ¤   ¤   goto cleanup;
7faf5a
f6316e ¤   pgpFile = pgpFileReadOpen ( cdkContext, readStdFile, NULL, NULL );
fcaa3a ¤   if ( IsNull( pgpFile ) )
7dc7a1 ¤   {
bcf383 ¤   ¤   err = kPGPError_OutOfMemory;¤   /* XXX: Return better error */
6048b9 ¤   ¤   goto cleanup;
349371 ¤   }
03fb69 ¤   readStdFile = NULL;¤¤   /* pgpFile is now responsible for closing it */
75af5a
f388dc ¤   ringFile = ringFileOpen( ringpool, pgpFile, trusted, &err );
fc1305 ¤   if ( IsNull( ringFile ) )
4f48b9 ¤   ¤   goto cleanup;
aeaf5a
29b227 ¤   immutableSet = ringFileSet( ringFile );
6bed31 ¤   if ( IsntNull( mutableSet ) )
0f4bf2 ¤   ¤   ringSetAddSet( mutableSet, immutableSet );
edaf5a
78d694 ¤   rdb->mainFileRef¤   = mainFileRef;
349f2d ¤   rdb->mainStdFile¤   = mainStdFile;
d55905 ¤   rdb->readFileRef¤   = readFileRef;
7139a6 ¤   rdb->pgpFile¤   ¤   = pgpFile;
ac4524 ¤   rdb->ringFile¤  ¤   = ringFile;
e3553b ¤   rdb->immutableSet¤  = immutableSet;
8f3a0e ¤   rdb->mutableSet¤¤   = mutableSet;
7b42e4 ¤   rdb->openFlags¤ ¤   = openFlags;
5ff180 ¤   rdb->bwriteable¤¤   = writeable;
a679b5 ¤   rdb->bdirty¤¤   ¤   = ringFileIsDirty( ringFile );
3ef19e ¤   rdb->btrusted¤  ¤   = trusted;
aecba5 ¤   rdb->bprivate¤  ¤   = priv;
4daf5a
7c151e ¤   return kPGPError_NoErr;
81af5a
3868cb cleanup:
d1ed31 ¤   if ( IsntNull( mutableSet ) )
2b4ea0 ¤   ¤   ringSetDestroy( mutableSet );
b52b3a ¤   if ( IsntNull( ringFile ) )
7dc7a1 ¤   {
2c1d4d ¤   ¤   if( IsPGPError( ringFileClose( ringFile ) ) )
673c65 ¤   ¤   ¤   pgpDebugMsg( "Failed to close ringFile" );
c09371 ¤   }
a95e93 ¤   if ( IsntNull( pgpFile ) )
b90374 ¤   ¤   pgpFileClose( pgpFile );
e28ae1 ¤   if ( IsntNull( readStdFile ) )
0b67b9 ¤   ¤   pgpStdIOClose( readStdFile );
f3147b ¤   if ( readFileRef != kInvalidPFLFileSpecRef )
cef54c ¤   ¤   PFLFreeFileSpec( readFileRef );
362806 ¤   if ( IsntNull( mainStdFile ) )
38b26e ¤   ¤   pgpStdIOClose( mainStdFile );
437713 ¤   if ( mainFileRef != kInvalidPFLFileSpecRef )
--8c2d 00081f9f00040100228 Page 12 of pgpFileDB.c
dc209b ¤   ¤   PFLFreeFileSpec( mainFileRef );
af5ea8 ¤   return err;
82efe6 }
5eaf5a
b366dd ¤   static PGPError
473f7f WriteKeyRing( RingDB *¤ rdb )
71bb36 {
a5de46 ¤   PGPContextRef¤  cdkContext¤ = rdb->context;
e93ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
9baf5a
fac02e ¤   PGPFile *¤  ¤   oldPGPFile¤ = rdb->pgpFile;
a154a3 ¤   RingFile *¤ ¤   oldRingFile¤= rdb->ringFile;
c7af5a
4cc713 ¤   PFLFileSpecRef¤ tempFileRef¤= kInvalidPFLFileSpecRef;
f3ce15 ¤   FILE *¤ ¤   ¤   tempStdFile¤= NULL;¤¤   /* Stdio file for temp file */
3570f8 ¤   PGPFile *¤  ¤   tempPGPFile¤= NULL;¤¤   /* PGPFile for temp file */
dbaf5a
fb408a ¤   PFLFileSpecRef¤ newFileRef¤ = kInvalidPFLFileSpecRef;
b57e9c ¤   FILE *¤ ¤   ¤   newStdFile¤ = NULL;¤¤   /* Stdio file for new backup */
b1ee26 ¤   PGPFile *¤  ¤   newPGPFile¤ = NULL;¤¤   /* PGPFile for new backup file */
97f3b8 ¤   RingFile *¤ ¤   newRingFile¤= NULL;¤¤   /* RingFile for new backup file */
65af5a
b91c86 ¤   char *¤ ¤   ¤   mainFileName = NULL;
c0565d ¤   PGPFileType¤¤   fileType = rdb->bprivate ? kPGPFileTypePrivRing
b0003a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·: kPGPFileTypePubRing;
9fab82 ¤   int ············flags¤  = ( rdb->btrusted && !rdb->bprivate )
940125 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ? PGP_RINGSETWRITE_PUBTRUST : 0;
d5af5a
4aaf5a
9b604a ¤   /* Find a unique temporary file name */
5ffb55 ¤   err = PFLFileSpecGetUniqueSpec( rdb->mainFileRef, &tempFileRef );
f5054e ¤   if ( IsPGPError( err ) )
4548b9 ¤   ¤   goto cleanup;
b8af5a
d28aa0 ¤   /* Create and open the temp file */
c6dafe ¤   err = pgpFileRefStdIOOpen( tempFileRef,
40f4db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileOpenStdUpdateFlags
19aa3d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···| kPGPFileOpenLockFile,
53adc4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···fileType,
5e3b91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&tempStdFile );
02054e ¤   if ( IsPGPError( err ) )
bf48b9 ¤   ¤   goto cleanup;
5daf5a
c7d036 ¤   /* Create a PGPFile object for the temp file */
d469c6 ¤   tempPGPFile = pgpFileWriteOpen( cdkContext, tempStdFile, NULL );
2b76ee ¤   if ( IsNull( tempPGPFile ) )
01c7a1 ¤   {
8ff426 ¤   ¤   pgpStdIOClose( tempStdFile );
ddf383 ¤   ¤   err = kPGPError_OutOfMemory;¤   /* XXX: Return better error */
3a48b9 ¤   ¤   goto cleanup;
e69371 ¤   }
18af5a
b82e1a ¤   /* Write the key ring to the temp file, creating newRingFile */
0c15da ¤   err = ringSetWrite( rdb->mutableSet, tempPGPFile, &newRingFile,
ea1da8 ¤   ¤   ¤   ¤   ¤   ¤   PGPVERSION_4, flags );
72054e ¤   if ( IsPGPError( err ) )
f348b9 ¤   ¤   goto cleanup;
92af5a
b36d32 ¤   /* Make sure the data is written to disk */
71f553 ¤   err = pgpFileFlush( tempPGPFile );
01054e ¤   if ( IsPGPError( err ) )
f348b9 ¤   ¤   goto cleanup;
22af5a
0caf5a
52d8af ¤   /*
72db0f ¤   ·* Make a new read-only backup from the newly written temp file
46a4e3 ¤   ·*/
12f8d5 ¤   err = MakeMatchingBackup( rdb->mainFileRef, tempStdFile, fileType,
88fbcf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&newFileRef );
6c054e ¤   if ( IsPGPError( err ) )
4748b9 ¤   ¤   goto cleanup;
81af5a
--61c0 000b9dde11e40100228 Page 13 of pgpFileDB.c
d8c4af ¤   /* Open the new backup file which will be used for backing store */
a31784 ¤   err = pgpFileRefStdIOOpen( newFileRef, kPGPFileOpenReadPerm,
15a23c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileTypeNone, &newStdFile );
e7054e ¤   if ( IsPGPError( err ) )
b648b9 ¤   ¤   goto cleanup;
b1af5a
bb9a09 ¤   /* Create a PGPFile object for the new backup file */
1b875a ¤   newPGPFile = pgpFileReadOpen( cdkContext, newStdFile, NULL, NULL );
6a7d28 ¤   if ( IsNull( newPGPFile ) )
a9c7a1 ¤   {
350315 ¤   ¤   pgpStdIOClose( newStdFile );
24f383 ¤   ¤   err = kPGPError_OutOfMemory;¤   /* XXX: Return better error */
d748b9 ¤   ¤   goto cleanup;
a39371 ¤   }
b1af5a
11d8af ¤   /*
58ff91 ¤   ·* Switch the ringfile's backing store
163155 ¤   ·* from the temp file to the new backup file.
fba4e3 ¤   ·*/
7bd6cd ¤   ringFileSwitchFile( newRingFile, newPGPFile );
33af5a
38b017 ¤   pgpFileClose( tempPGPFile );
9d646f ¤   tempPGPFile = NULL;
96af5a
10af5a
7bd8af ¤   /*
d20483 ¤   ·* Delete the main ring file and move the temp file into its place.
579714 ¤   ·*
e5fd24 ¤   ·* XXX: Race condition here, we must release the lock momentarily
f5a4e3 ¤   ·*/
dcc7a1 ¤   {
708b84 ¤   ¤   /* We'll need this for renaming */
7c518a ¤   ¤   err = PFLGetFileSpecName( rdb->mainFileRef, &mainFileName );
b2be18 ¤   ¤   if ( IsPGPError( err ) )
f98f0c ¤   ¤   ¤   goto cleanup;
cbaf5a
053e08 ¤   ¤   /* Close the main ring file, releasing our lock */
bfdf3c ¤   ¤   if ( IsntNull( rdb->mainStdFile ) )
725b34 ¤   ¤   {
93189b ¤   ¤   ¤   err = pgpStdIOClose( rdb->mainStdFile );
108370 ¤   ¤   ¤   if ( IsPGPError( err ) )
750658 ¤   ¤   ¤   ¤   goto cleanup;
302871 ¤   ¤   ¤   rdb->mainStdFile = NULL;
ab0fe4 ¤   ¤   }
e0af5a
3a33fd ¤   ¤   /* Try to delete the main ring file, ignoring errors */
9b7d1c ¤   ¤   (void)PFLFileSpecDelete( rdb->mainFileRef );
78af5a
4736b4 ¤   ¤   /* Move the temp file into the main ring's place */
0c665b ¤   ¤   err = PFLFileSpecRename( tempFileRef, mainFileName );
43be18 ¤   ¤   if ( IsPGPError( err ) )
498f0c ¤   ¤   ¤   goto cleanup;
e6af5a
05183d ¤   ¤   /* Relock the main keyring file to ensure exclusive access */
e4f898 ¤   ¤   err = pgpFileRefStdIOOpen( rdb->mainFileRef,
2ef5b7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileOpenReadWritePerm |
3013af ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPFileOpenLockFile,
60ab7c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···fileType,
703707 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&rdb->mainStdFile );
f5be18 ¤   ¤   if ( IsPGPError( err ) )
7e8f0c ¤   ¤   ¤   goto cleanup;
6daf5a
69e1f8 ¤   ¤   /* XXX: We should swap fileIDs here on the Mac */
359371 ¤   }
43af5a
c5af5a
e74a6f ¤   /* We must close mutableSet in order to cleanly close oldRingFile */
a2b6aa ¤   ringSetDestroy( rdb->mutableSet );
bb798e ¤   rdb->mutableSet = NULL;
28af5a
83f18d ¤   /* Now close the old backup or temp file */
b94258 ¤   err = ringFileClose( oldRingFile );
--5c60 00033c41bfe40100228 Page 14 of pgpFileDB.c
a901d7 ¤   pgpFileClose( oldPGPFile );¤¤   /* Close the PGPFile regardless */
17054e ¤   if ( IsPGPError( err ) )
05c7a1 ¤   {
931b17 ¤   ¤   /*
aa39d2 ¤   ¤   ·* We shouldn't get here. ·Probably due to a pesky RingSet leak!
6e9de3 ¤   ¤   ·*/
ef9522 ¤   ¤   pgpDebugMsg( "Failed to close oldRingFile" );
009371 ¤   }
11af5a
eeaaf2 ¤   /* If it was a local temp file, delete it immediately */
7dd75c ¤   if ( rdb->btempfile )
0ac7a1 ¤   {
4bfbd2 ¤   ¤   PFLFileSpecDelete( rdb->readFileRef );
a9528d ¤   ¤   rdb->btempfile = FALSE;
a39371 ¤   }
e7af5a
55876b ¤   PGPFreeData( mainFileName );
e6af5a
4c50d8 ¤   PFLFreeFileSpec( rdb->readFileRef );
43de90 ¤   rdb->readFileRef = newFileRef;
08c3fd ¤   newFileRef = NULL;
26af5a
2da386 ¤   PFLFreeFileSpec( tempFileRef );
32a72f ¤   tempFileRef = NULL;
8baf5a
a5a026 ¤   rdb->ringFile = newRingFile;
25ce59 ¤   rdb->pgpFile = newPGPFile;
30af5a
ead041 ¤   PurgeOldBackups( rdb->mainFileRef );
daaf5a
87151e ¤   return kPGPError_NoErr;
c0af5a
0668cb cleanup:
fc03c6 ¤   if ( IsNull( rdb->mainStdFile ) )
8ec7a1 ¤   {
07ae64 ¤   ¤   /* If we lost our exclusive lock, we must forfeit write access */
03e745 ¤   ¤   rdb->bwriteable = FALSE;
940f61 ¤   ¤   rdb->openFlags &= ~kPGPKeyRingOpenFlags_Mutable;
2a9371 ¤   }
f7af5a
c15d70 ¤   if ( IsntNull( newRingFile ) )
78c7a1 ¤   {
02187e ¤   ¤   if( IsPGPError( ringFileClose( newRingFile ) ) )
4eb6f4 ¤   ¤   ¤   ¤   pgpDebugMsg( "Failed to close newRingFile" );
dc9371 ¤   }
5df589 ¤   if ( IsntNull( newPGPFile ) )
201f2f ¤   ¤   pgpFileClose( newPGPFile );
f1a190 ¤   if ( newFileRef != kInvalidPFLFileSpecRef )
f30d9d ¤   ¤   PFLFreeFileSpec( newFileRef );
e3af5a
21c2e5 ¤   if ( IsntNull( tempPGPFile ) )
838d7f ¤   ¤   pgpFileClose( tempPGPFile );
49e60c ¤   if ( IsntNull( tempStdFile ) )
5948b7 ¤   ¤   PFLFileSpecDelete( tempFileRef );
b0f1e5 ¤   if ( tempFileRef != kInvalidPFLFileSpecRef )
1a66d3 ¤   ¤   PFLFreeFileSpec( tempFileRef );
acaf5a
d12912 ¤   if ( IsntNull( mainFileName ) )
e2ba03 ¤   ¤   PGPFreeData( mainFileName );
47af5a
155ea8 ¤   return err;
83efe6 }
18af5a
da66dd ¤   static PGPError
4bbcba CloseKeyRing( RingDB *¤ rdb )
c7bb36 {
cd8a97 ¤   PGPContextRef¤  context;
2daf5a
22878e ¤   pgpAssertAddrValid( rdb, RingDB );
936e33 ¤   context¤= rdb->context;
47af5a
334138 ¤   if (rdb->frozenSet)
--0f21 000759626a240100228 Page 15 of pgpFileDB.c
f7c7a1 ¤   {
ece472 ¤   ¤   ringSetDestroy (rdb->frozenSet);
876329 ¤   ¤   rdb->frozenSet = 0;
e59371 ¤   }
75dad3 ¤   rdb->immutableSet = 0;
ae9774 ¤   if (rdb->mutableSet)
906f88 ¤   ¤   ringSetDestroy (rdb->mutableSet);
5df025 ¤   rdb->mutableSet = 0;
315c09 ¤   if( IsPGPError( ringFileClose (rdb->ringFile) ) )
f6ccba ¤   ¤   pgpDebugMsg( "Failed to close rdb->ringFile" );
b52e30 ¤   rdb->ringFile = 0;
b3d1b2 ¤   pgpFileClose (rdb->pgpFile);
329496 ¤   rdb->pgpFile = 0;
26af5a
30575a ¤   if ( IsntNull( rdb->mainStdFile ) )
a485d3 ¤   ¤   pgpStdIOClose( rdb->mainStdFile );
8eaf5a
94a46e ¤   if ( rdb->mainFileRef != kInvalidPFLFileSpecRef )
a8c7a1 ¤   {
a088b2 ¤   ¤   if ( rdb->bwriteable || !PFL_PLATFORM_UNSAFE_DELETE )
2b8464 ¤   ¤   ¤   PurgeOldBackups( rdb->mainFileRef );
3c83b7 ¤   ¤   PFLFreeFileSpec( rdb->mainFileRef );
31b3fa ¤   ¤   rdb->mainFileRef = kInvalidPFLFileSpecRef;
3e9371 ¤   }
cdc706 ¤   if ( rdb->readFileRef != kInvalidPFLFileSpecRef )
45c7a1 ¤   {
6b5e08 ¤   ¤   if ( rdb->btempfile )
8a2360 ¤   ¤   ¤   PFLFileSpecDelete( rdb->readFileRef );
ba5660 ¤   ¤   PFLFreeFileSpec( rdb->readFileRef );
93bd47 ¤   ¤   rdb->readFileRef = kInvalidPFLFileSpecRef;
159371 ¤   }
cd67c5 ¤
15151e ¤   return kPGPError_NoErr;
d0efe6 }
72af5a
58af5a
d3af5a
adaf5a
fbbf6d /******************** ·Virtual Functions ·************************/
04af5a
aeaf5a
f56c2c ¤   static PGPBoolean
0ab890 rdbIsMutable (PGPKeyDBRef kdb) {
63f244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
11af5a
e0f924 ¤   return rdb->bwriteable;
bfefe6 }
f4af5a
616c2c ¤   static PGPBoolean
3a0616 rdbObjIsMutable (PGPKeyDBRef kdb, RingObject *testObj)
c7cebb {¤
a9f244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
4eaf5a
8d467c ¤   return rdb->bwriteable && ringSetIsMember (rdb->mutableSet, testObj);
71efe6 }
85af5a
ec6c2c ¤   static PGPBoolean
c17a65 rdbIsDirty (PGPKeyDBRef kdb)
6dbb36 {
5bf244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
b2af5a
bdf350 ¤   return rdb->bdirty;
0befe6 }
f2af5a
aae40f /* Mark as dirty */
e733c8 ¤   static void
6a1df5 rdbDirty (RingDB *rdb)
89bb36 {
cee5ee ¤   rdb->bdirty = TRUE;
6ae098 ¤   if (rdb->frozenSet) {
6ae472 ¤   ¤   ringSetDestroy (rdb->frozenSet);
756329 ¤   ¤   rdb->frozenSet = 0;
--cf13 000b463be7140100228 Page 16 of pgpFileDB.c
a19371 ¤   }
c9efe6 }
a0af5a
bcb39c ¤   static const RingSet *
6b1779 rdbGetRingSet (PGPKeyDBRef kdb)
5cbb36 {
8ef244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
847b6e ¤   RingSet ·······*rset;
94af5a
1f04a5 ¤   if (!rdb->bwriteable) {
0ce855 ¤   ¤   return rdb->immutableSet;
c9b7ed ¤   } else if (!(rset = rdb->frozenSet)) {
fa7f0e ¤   ¤   rset = ringSetCreate (ringSetPool (rdb->mutableSet));
7b198d ¤   ¤   ringSetAddSet (rset, rdb->mutableSet);
55aa3f ¤   ¤   ringSetFreeze (rset);
e97469 ¤   ¤   rdb->frozenSet = rset;
e09371 ¤   }
bca428 ¤   return rset;
9cefe6 }
71af5a
6b66dd ¤   static PGPError
9a18c4 rdbAdd (PGPKeyDBRef kdb, RingSet *toAdd)
73bb36 {
aaf244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
d542f2 ¤   RingIterator ··*riAdd;¤ ¤   /* Iterator over toAdd set */
0b7486 ¤   RingObject ····*robj;¤  ¤   /* Object we are adding */
fab0e3 ¤   int ············level;¤ ¤   /* Level of iterator in hierarchy */
4ab0f7 ¤   int¤¤   ¤   ¤   type;¤  ¤   /* Type of robj */
209453 ¤   int ············added;¤ ¤   /* Number of objects added */
9949f3 ¤   int ············skipped;¤   /* Number of objects skipped */
908a93 ¤   PGPBoolean¤ ¤   skipparts; ·/* True if skipping, obj not for us */
d9af5a
11c0b2 ¤   if (!rdb->bwriteable)
907c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
35af5a
4b228f ¤   riAdd = ringIterCreate (toAdd);
f94b97 ¤   if (!riAdd) {
9d395e ¤   ¤   return ringSetError(toAdd)->error;
cb9371 ¤   }
b7af5a
802eb2 ¤   added = 0;
9f9788 ¤   skipped = 0;
2d5850 ¤   skipparts = FALSE;
86af5a
792ba8 ¤   while ((level = ringIterNextObjectAnywhere(riAdd)) > 0) {
571d1d ¤   ¤   robj = ringIterCurrentObject (riAdd, level);
a62488 ¤   ¤   type = ringObjectType (robj);
d8079b ¤   ¤   if (type==RINGTYPE_KEY) {
777aad ¤   ¤   ¤   /*
5afde9 ¤   ¤   ¤   ·* If key lacks secret object, put it only on the public
8c3a25 ¤   ¤   ¤   ·* ring, and if key comes only from a source where it is a
f9a585 ¤   ¤   ¤   ·* secret key, put it only on the secret ring. ·This is
f0a93d ¤   ¤   ¤   ·* important to prevent propagation of the 2.6.2 "version bug",
61b24a ¤   ¤   ¤   ·* where changing passphrase on a V2 secret key turns it into
126319 ¤   ¤   ¤   ·* V3. ·We must not let that get into the public keyring.
398753 ¤   ¤   ¤   ·*/
a147aa ¤   ¤   ¤   if (rdb->bprivate) {
072c7f ¤   ¤   ¤   ¤   skipparts = !ringKeyIsSec (toAdd, robj);
26ca80 ¤   ¤   ¤   ¤   if (skipparts && !ringKeyIsSubkey (toAdd, robj)) {
de6455 ¤   ¤   ¤   ¤   ¤   /* Don't skip if any subkey has a secret part */
bf3031 ¤   ¤   ¤   ¤   ¤   unsigned levelx;
40e606 ¤   ¤   ¤   ¤   ¤   RingObject *robjx;
9d03ee ¤   ¤   ¤   ¤   ¤   while ((levelx = ringIterNextObjectAnywhere(riAdd)) > 1) {
d0bce9 ¤   ¤   ¤   ¤   ¤   ¤   robjx = ringIterCurrentObject (riAdd, levelx);
8d147b ¤   ¤   ¤   ¤   ¤   ¤   if (ringObjectType(robjx) == RINGTYPE_KEY &&
a0986d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringKeyIsSec (toAdd, robjx)) {
2bfcc1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   skipparts = FALSE;
cf8c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
2fdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
291c89 ¤   ¤   ¤   ¤   ¤   }
4faadc ¤   ¤   ¤   ¤   ¤   ringIterSeekTo (riAdd, robj);
b42613 ¤   ¤   ¤   ¤   }
--0ef7 000e4d9d62440100228 Page 17 of pgpFileDB.c
99042d ¤   ¤   ¤   } else {
2ce108 ¤   ¤   ¤   ¤   skipparts = ringKeyIsSecOnly (toAdd, robj);
6bbd30 ¤   ¤   ¤   ¤   /* Go ahead and add to pubring if key has a signature */
242831 ¤   ¤   ¤   ¤   if (skipparts) {
da3031 ¤   ¤   ¤   ¤   ¤   unsigned levelx;
97e606 ¤   ¤   ¤   ¤   ¤   RingObject *robjx;
775421 ¤   ¤   ¤   ¤   ¤   int typex;
3b03ee ¤   ¤   ¤   ¤   ¤   while ((levelx = ringIterNextObjectAnywhere(riAdd)) > 1) {
12bce9 ¤   ¤   ¤   ¤   ¤   ¤   robjx = ringIterCurrentObject (riAdd, levelx);
d529ba ¤   ¤   ¤   ¤   ¤   ¤   typex = ringObjectType (robjx);
962e7c ¤   ¤   ¤   ¤   ¤   ¤   if (typex == RINGTYPE_KEY)
678c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
50d546 ¤   ¤   ¤   ¤   ¤   ¤   if (typex == RINGTYPE_SIG) {
54fcc1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   skipparts = FALSE;
3f8c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
c0db3c ¤   ¤   ¤   ¤   ¤   ¤   }
a71c89 ¤   ¤   ¤   ¤   ¤   }
63aadc ¤   ¤   ¤   ¤   ¤   ringIterSeekTo (riAdd, robj);
002613 ¤   ¤   ¤   ¤   }
69a3a6 ¤   ¤   ¤   }
090fe4 ¤   ¤   }
64a73a ¤   ¤   if (skipparts) {
22d77d ¤   ¤   ¤   skipped += 1;
f000ac ¤   ¤   } else if ((type==RINGTYPE_SEC) && !rdb->bprivate) {
32758b ¤   ¤   ¤   /* Secrets only go to private keyrings */
37d77d ¤   ¤   ¤   skipped += 1;
886e62 ¤   ¤   } else if ((type==RINGTYPE_SIG) && rdb->bprivate &&
ba6a72 ¤   ¤   ¤   ¤   ···!ringSigIsSelfSig( toAdd, robj )) {
fb7aad ¤   ¤   ¤   /*
8cf12a ¤   ¤   ¤   ·* Signatures only go to public keyrings, normally. ·The
ea3eb2 ¤   ¤   ¤   ·* exception is your own self-sigs. ·If you lose the one
3449a2 ¤   ¤   ¤   ·* on your subkey, people won't be able to encrypt to you.
0a16ed ¤   ¤   ¤   ·* If you lose the one on your username, you'll lose expiration
845b6c ¤   ¤   ¤   ·* or preferred algorithms.
808753 ¤   ¤   ¤   ·*/
e1d77d ¤   ¤   ¤   skipped += 1;
2945a6 ¤   ¤   } else {
d7a976 ¤   ¤   ¤   ringSetAddObject (rdb->mutableSet, robj);
d159b5 ¤   ¤   ¤   added += 1;
010fe4 ¤   ¤   }
969371 ¤   }
03fe37 ¤   ringIterDestroy (riAdd);
56af5a
0fa20e ¤   rdbDirty (rdb);
32151e ¤   return kPGPError_NoErr;
ecefe6 }
16af5a
51af5a
b066dd ¤   static PGPError
7da626 rdbRemove (PGPKeyDBRef kdb, RingObject *toRemove)
72bb36 {
4ff244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
d8af5a
55c0b2 ¤   if (!rdb->bwriteable)
447c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
e6af5a
da3618 ¤   if (ringSetIsMember (rdb->mutableSet, toRemove))
a1d8fa ¤   ¤   rdbDirty (rdb);
72cb80 ¤   return (PGPError)ringSetRemObject (rdb->mutableSet, toRemove);
d2efe6 }
c8af5a
5938e5 /*
cb39ab ·* Note that unions don't pass this call down, they take care of it
c907bb ·* themselves
7c495d ·*/
f966dd ¤   static PGPError
e905e3 rdbChanged (PGPKeyDBRef kdb, RingSet *changedkeys)
a4bb36 {
47f244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
78af5a
abc0b2 ¤   if (!rdb->bwriteable)
e47c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
--0449 0008dd7796f40100228 Page 18 of pgpFileDB.c
e0af5a
cea20e ¤   rdbDirty (rdb);
9e8593 ¤   return pgpReSortKeys (kdb, changedkeys);
1fefe6 }
aeaf5a
e566dd ¤   static PGPError
e4fb2d rdbCommit (PGPKeyDBRef kdb)
b4bb36 {
08f244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
6a7b6b ¤   RingPool¤   ···*ringpool = ringSetPool (rdb->immutableSet);
2e7804 ¤   PGPError ·······error;
02af5a
c1c0b2 ¤   if (!rdb->bwriteable)
cfb840 ¤   ¤   return kPGPError_NoErr;
23af5a
b26f65 ¤   /* ·Don't check for trust changed if untrusted file */
87598f ¤   if (!rdb->bdirty &&¤(!rdb->btrusted ||·
2e6e74 ¤   ¤   ¤   ¤   ·(rdb->btrusted && !ringFileIsTrustChanged(rdb->ringFile))))
1eb840 ¤   ¤   return kPGPError_NoErr;
60af5a
e4ce79 ¤   /* Must use frozen set for writing */
99af5a
f75a3c ¤   ringSetFreeze (rdb->mutableSet);
33e098 ¤   if (rdb->frozenSet) {
cbe472 ¤   ¤   ringSetDestroy (rdb->frozenSet);
306329 ¤   ¤   rdb->frozenSet = 0;
8c9371 ¤   }
3106d0 ¤   error = WriteKeyRing (rdb);
40af5a
41a673 ¤   if (error) {
911b17 ¤   ¤   /*
70734a ¤   ¤   ·* Sometimes on error we have fixed rdb->mutableSet, but possibly it
7dc5ea ¤   ¤   ·* may still be frozen as above. ·To be safe we will always make a
cee3e1 ¤   ¤   ·* copy here so it is writeable in the future.
4a9de3 ¤   ¤   ·*/
dd8527 ¤   ¤   RingSet *rset = ringSetCreate (ringpool);
9e28e9 ¤   ¤   pgpAssert (rset);
c67e45 ¤   ¤   pgpAssert (rdb->mutableSet);
68198d ¤   ¤   ringSetAddSet (rset, rdb->mutableSet);
576f88 ¤   ¤   ringSetDestroy (rdb->mutableSet);
9a4fa1 ¤   ¤   rdb->mutableSet = rset;
bcfcee ¤   ¤   return error;
ee9371 ¤   }
7caf5a
e46c54 ¤   rdb->immutableSet = ringFileSet (rdb->ringFile);
2e3237 ¤   rdb->mutableSet = ringSetCreate (ringpool);
43948f ¤   ringSetAddSet (rdb->mutableSet, rdb->immutableSet);
3625ea ¤   rdb->bdirty = 0;
e5af5a
7c151e ¤   return kPGPError_NoErr;
9fefe6 }
7aaf5a
56af5a
5366dd ¤   static PGPError
7302b9 rdbRevert (PGPKeyDBRef kdb)
a0bb36 {
89f244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
daaf5a
b1e9bc ¤   if (!rdb->bdirty)
deb840 ¤   ¤   return kPGPError_NoErr;
c925ea ¤   rdb->bdirty = 0;
10bce5 ¤   if (rdb->mutableSet) {
6d6f88 ¤   ¤   ringSetDestroy (rdb->mutableSet);
c43599 ¤   ¤   rdb->mutableSet = ringSetCreate (ringSetPool(rdb->immutableSet));
a34ba3 ¤   ¤   if (!rdb->mutableSet) {
fdcfa2 ¤   ¤   ¤   return ringSetError( rdb->immutableSet )->error;
ac0fe4 ¤   ¤   }
ed1bd8 ¤   ¤   ringSetAddSet (rdb->mutableSet, rdb->immutableSet);
ee9371 ¤   }
3ce098 ¤   if (rdb->frozenSet) {
d3e472 ¤   ¤   ringSetDestroy (rdb->frozenSet);
8d6329 ¤   ¤   rdb->frozenSet = 0;
--3167 000b721498640100228 Page 19 of pgpFileDB.c
a19371 ¤   }
a3151e ¤   return kPGPError_NoErr;
a1efe6 }
d9af5a
0166dd ¤   static PGPError
ab39c2 rdbReload (PGPKeyDBRef kdb)
8dbb36 {
2ef244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
a9cd2b ¤   PFLFileSpecRef ····¤fileRef;
d6b7bf ¤   PGPError ·······err¤= kPGPError_NoErr;
6cd90a ¤   PGPContextRef¤  cdkContext¤ = pgpGetKeyDBContext( kdb );
8667c5 ¤
26c801 ¤   if (rdb->bmembuf)
77b840 ¤   ¤   return kPGPError_NoErr;
483572 ¤   if ( IsPGPError(err = PFLCopyFileSpec(rdb->mainFileRef, &fileRef)))
fd4030 ¤   ¤   return kPGPError_OutOfMemory;
f2d945 ¤   err = CloseKeyRing (rdb);
588a50 ¤   if (err) {
09553f ¤   ¤   PFLFreeFileSpec(fileRef);
58c9db ¤   ¤   return err;
3e9371 ¤   }
f368be ¤   err = OpenKeyRing ( cdkContext, fileRef, rdb->openFlags,
f403e7 ¤   ¤   ¤   ¤   ¤   ···ringSetPool (rdb->immutableSet), rdb);
af25ea ¤   rdb->bdirty = 0;
91e098 ¤   if (rdb->frozenSet) {
ade472 ¤   ¤   ringSetDestroy (rdb->frozenSet);
c26329 ¤   ¤   rdb->frozenSet = 0;
a49371 ¤   }
1d6237 ¤   PFLFreeFileSpec(fileRef);
d85ea8 ¤   return err;
4cefe6 }
b4af5a
7b33c8 ¤   static void
c23204 rdbDestroy (PGPKeyDBRef kdb)
cfbb36 {
92f244 ¤   RingDB ········*rdb = (RingDB *)kdb->priv;
e28a97 ¤   PGPContextRef¤  context;
78af5a
763c32 ¤   pgpAssertAddrValid( kdb, RingDB );
666e33 ¤   context¤= rdb->context;
b8af5a
dc9694 ¤   CloseKeyRing (rdb);
9409d1 ¤   kdb->typeMagic¤ = ~ kdb->typeMagic;¤¤   /* mark as invalid */
8ea0c9 ¤   kdb->fixedMagic¤= ~ kdb->fixedMagic;¤   /* mark as invalid */
064d29 ¤   pgpContextMemFree( context, rdb);
71efe6 }
3faf5a
bfaf5a
ddb24e /**************************** ·Constructor ·**************************/
89af5a
e6d3ad ¤   PGPKeyDBRef·
fc3edc pgpCreateFileKeyDB (PGPContextRef context, PFLConstFileSpecRef fileRef,
2ebc06 ¤   PGPKeyRingOpenFlags openFlags, RingPool *ringpool,
85a900 ¤   PGPError *error)
1bbb36 {
abc567 ¤   PGPKeyDBRef ···kdb;
88e43c ¤   RingDB ········*rdb;
32af5a
799096 ¤   *error = kPGPError_NoErr;
84c175 ¤   kdb = pgpKeyDBCreateInternal (context);
901c34 ¤   if (!kdb) {
e6e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
717ed2 ¤   ¤   return NULL;
979371 ¤   }
ff1267 ¤   rdb = (RingDB *) pgpContextMemAlloc( context,
bffe96 ¤   ¤   sizeof (RingDB), kPGPMemoryMgrFlags_Clear);
e3e8c4 ¤   if (!rdb) {
dee2ed ¤   ¤   *error = kPGPError_OutOfMemory;
2ee534 ¤   ¤   pgpKeyDBDestroyInternal (kdb);
427ed2 ¤   ¤   return NULL;
9c9371 ¤   }
b7af5a
--381f 000f495ede540100228 Page 20 of pgpFileDB.c
c67b47 ¤   rdb->context¤   = context;
ae67c5 ¤
57915d ¤   *error = OpenKeyRing ( context, fileRef, openFlags, ringpool, rdb);
9e606c ¤   if (*error) {
1471c7 ¤   ¤   pgpContextMemFree( context, rdb);
72e534 ¤   ¤   pgpKeyDBDestroyInternal (kdb);
8b7ed2 ¤   ¤   return NULL;
0e9371 ¤   }
cfaf5a
ca1157 ¤   kdb->priv ···¤  ¤   = rdb;
74f95d ¤   kdb->typeMagic¤ ¤   ¤   = PGPKDBFILEMAGIC;
f1f4a6 ¤   kdb->fixedMagic¤¤   ¤   = kPGPKeyDBMagic;
116dab ¤   kdb->isMutable¤ ¤   ¤   = rdbIsMutable;
fe31eb ¤   kdb->objIsMutable¤  ¤   = rdbObjIsMutable;
de1ed0 ¤   kdb->isDirty ···¤   ¤   = rdbIsDirty;
fa8dd0 ¤   kdb->getRingSet¤¤   ¤   = rdbGetRingSet;
f3c178 ¤   kdb->add ·······¤   ¤   = rdbAdd;
cd61c5 ¤   kdb->remove ····¤   ¤   = rdbRemove;
4088ff ¤   kdb->changed¤   ¤   ¤   = rdbChanged;
ad576a ¤   kdb->commit ····¤   ¤   = rdbCommit;
c0eb89 ¤   kdb->revert ····¤   ¤   = rdbRevert;
7c225d ¤   kdb->reload ····¤   ¤   = rdbReload;
5a8968 ¤   kdb->destroy¤   ¤   ¤   = rdbDestroy;
93af5a
ec5ecf ¤   pgpKeyDBInitInternal(kdb);
6aaf5a
c632be ¤   return kdb;
fbefe6 }
69af5a
6538e5 /*
442e0f ·* Create a File type KeyDB from a memory buffer. ·This will be an
e473c0 ·* immutable KeyDB since we can't save our changes anywhere.
85485f ·* We make a copy of the buffer passed in, so caller can free it.
5c495d ·*/
d2d3ad ¤   PGPKeyDBRef·
af734b pgpCreateMemFileKeyDB (
0b520e ¤   PGPContextRef¤  context,
4220fc ¤   PGPByte *¤  ¤   buf,
168f79 ¤   size_t ¤¤   ¤   length,
4d80e4 ¤   RingPool *¤ ¤   ringpool,
2a6429 ¤   PGPError *¤ ¤   error)
dbbb36 {
a9c592 ¤   PGPKeyDBRef¤¤   kdb;
8ce43c ¤   RingDB ········*rdb;
6daf5a
899096 ¤   *error = kPGPError_NoErr;
66c175 ¤   kdb = pgpKeyDBCreateInternal (context);
961c34 ¤   if (!kdb) {
bce2ed ¤   ¤   *error = kPGPError_OutOfMemory;
347ed2 ¤   ¤   return NULL;
9e9371 ¤   }
561267 ¤   rdb = (RingDB *) pgpContextMemAlloc( context,
60fe96 ¤   ¤   sizeof (RingDB), kPGPMemoryMgrFlags_Clear);
4fe8c4 ¤   if (!rdb) {
80e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
6fe534 ¤   ¤   pgpKeyDBDestroyInternal (kdb);
987ed2 ¤   ¤   return NULL;
bb9371 ¤   }
31af5a
007b47 ¤   rdb->context¤   = context;
66af5a
be855c ¤   /* Memfile keydb's are immutable */
0b798e ¤   rdb->mutableSet = NULL;
edaf5a
5b9e6e ¤   rdb->pgpFile = pgpFileMemOpen ( context, buf, length);
65e0ab ¤   if (!rdb->pgpFile) {
e271c7 ¤   ¤   pgpContextMemFree( context, rdb);
16e534 ¤   ¤   pgpKeyDBDestroyInternal (kdb);
2ce2ed ¤   ¤   *error = kPGPError_OutOfMemory;
ae7ed2 ¤   ¤   return NULL;
419371 ¤   }
f4af5a
--f419 00139f9691840100228 Page 21 of pgpFileDB.c
052df0 ¤   rdb->ringFile = ringFileOpen (ringpool, rdb->pgpFile, 0, error);
94c8d2 ¤   if (!rdb->ringFile) {
b9ecda ¤   ¤   pgpFileClose (rdb->pgpFile);
ae71c7 ¤   ¤   pgpContextMemFree( context, rdb);
a6e534 ¤   ¤   pgpKeyDBDestroyInternal (kdb);
5672a6 ¤   ¤   *error¤ = ringPoolError(ringpool)->error;
eaa3c4 ¤   ¤   if (!*error)
466a8b ¤   ¤   ¤   *error = kPGPError_OutOfMemory;
b07ed2 ¤   ¤   return NULL;
6e9371 ¤   }
34af5a
876c54 ¤   rdb->immutableSet = ringFileSet (rdb->ringFile);
d03b12 ¤   rdb->bmembuf = TRUE;
efae4f ¤   rdb->mainStdFile = NULL;
2554a7 ¤   rdb->mainFileRef = rdb->readFileRef = NULL;
12af5a
2e4be9 ¤   kdb->priv ···¤  ¤   ¤   = rdb;
ddf95d ¤   kdb->typeMagic¤ ¤   ¤   = PGPKDBFILEMAGIC;
5cf4a6 ¤   kdb->fixedMagic¤¤   ¤   = kPGPKeyDBMagic;
f56dab ¤   kdb->isMutable¤ ¤   ¤   = rdbIsMutable;
8131eb ¤   kdb->objIsMutable¤  ¤   = rdbObjIsMutable;
fd1ed0 ¤   kdb->isDirty ···¤   ¤   = rdbIsDirty;
4d8dd0 ¤   kdb->getRingSet¤¤   ¤   = rdbGetRingSet;
96c178 ¤   kdb->add ·······¤   ¤   = rdbAdd;
7b61c5 ¤   kdb->remove ····¤   ¤   = rdbRemove;
2a88ff ¤   kdb->changed¤   ¤   ¤   = rdbChanged;
06576a ¤   kdb->commit ····¤   ¤   = rdbCommit;
78eb89 ¤   kdb->revert ····¤   ¤   = rdbRevert;
21225d ¤   kdb->reload ····¤   ¤   = rdbReload;
048968 ¤   kdb->destroy¤   ¤   ¤   = rdbDestroy;
04af5a
b65ecf ¤   pgpKeyDBInitInternal(kdb);
4faf5a
de32be ¤   return kdb;
08efe6 }
4eaf5a
c438e5 /*
68e6c5 ·* Local Variables:
1b9b19 ·* tab-width: 4
1ce7a4 ·* End:
04b612 ·* vi: ts=4 sw=4
c36c42 ·* vim: si
39495d ·*/
--dd0e 00048f93af040100229 Page 1 of pgpFilteredSet.c
bc38e5 /*
848c24 ·* pgpFilteredSet.c
6e6723 ·* Filtered variant of key sets
bf775e ·*
e794ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
8920c7 ·* All rights reserved
4e775e ·*
d133ac ·* $Id: pgpFilteredSet.c,v 1.29.12.1 1998/11/12 03:21:53 heller Exp $
2f495d ·*/
01af5a
19e2ff #include "pgpConfig.h"
10af5a
4aef82 #ifdef HAVE_STDLIB_H
31bea3 #include <stdlib.h>
fc7454 #endif
d8af5a
81324c #include <string.h>
00b1cb #include <ctype.h>
9eaf5a
56979a #include "pgpKDBInt.h"
bfa146 #include "pgpDebug.h"
582f8d #include "pgpErrors.h"
4c675a #include "pgpTypes.h"
fe0d08 #include "pgpMem.h"
b3c26c #include "pgpContext.h"
91af5a
faaf5a
5e1951 /* Private data for KeySet of type filter */
f80927 typedef struct FilteredSetPriv
4dbb36 {
521d95 ¤   PGPKeySetRef¤   origSet;
6c2245 ¤   PGPFilterRef¤   filter;
b67b29 } FilteredSetPriv;
3eaf5a
04af5a
ff6c2c ¤   static PGPBoolean
0574ea sFilteredSetIsMember(
b12645 ¤   PGPKeySetRef¤   keys,
504411 ¤   RingObject *¤   obj )
dbbb36 {
581671 ¤   FilteredSetPriv *¤  priv = (FilteredSetPriv *) keys->priv;
c8af5a
915e68 ¤   pgpa((
7d08d6 ¤   ¤   pgpaPGPKeySetValid( keys ),
beb72c ¤   ¤   pgpaAddrValid( priv, FilteredSetPriv )));
10af5a
34213d ¤   return priv->origSet->isMember( priv->origSet, obj )
e68554 ¤   ¤   && pgpKeyObjMatchesFilter( priv->filter,
87e3f3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···pgpKeyDBRingSet( keys->keyDB ),
bc0caa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···obj );
121862 }¤
17af5a
b533c8 ¤   static void
335174 sFilteredSetDestroy(
d6769f ¤   PGPKeySet *¤¤   keys )
30bb36 {
e44a32 ¤   PGPContextRef¤  ¤   context = PGPGetKeySetContext( keys );
2b983e ¤   FilteredSetPriv *¤  priv = (FilteredSetPriv *)keys->priv;
4caf5a
b85e68 ¤   pgpa((
67aabd ¤   ¤   pgpaAddrValid( keys, PGPKeySet ),
b4b72c ¤   ¤   pgpaAddrValid( priv, FilteredSetPriv )));
59af5a
8a7bd8 ¤   PGPFreeKeySet( priv->origSet );
293e41 ¤   PGPFreeFilter( priv->filter );
1ac171 ¤   pgpContextMemFree( context, priv);
48efe6 }
89af5a
c9af5a
1538e5 /*
1ea420 ·* Create a filtered KeySet based on the same KeyDB as the specified
4871f7 ·* original. ·The original must be unfiltered. ·The filtering is based
--c9d2 001e2ba8d2240100229 Page 2 of pgpFilteredSet.c
0114d5 ·* on a name substring (not keyid).
da495d ·*/
8ec744 ¤   PGPError
262f14 PGPFilterKeySet (
1efd8f ¤   PGPKeySetRef¤   ¤   origSet,
4e39e0 ¤   PGPFilterRef¤   ¤   filter,
4ad71f ¤   PGPKeySetRef *¤ ¤   outSet )
fbbb36 {
52fa93 ¤   PGPContextRef¤  ¤   context¤= PGPGetKeySetContext( origSet );
b237df ¤   PGPError¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
c198fa ¤   FilteredSetPriv *¤  priv¤   = NULL;
6eb989 ¤   PGPKeySetRef¤   ¤   newSet¤ = kInvalidPGPKeySetRef;
80af5a
db016b ¤   PGPValidatePtr( outSet );
5d1a2a ¤   *outSet¤= kInvalidPGPKeySetRef;
fe0583 ¤   PGPValidateKeySet( origSet );
234ffe ¤   PGPValidateFilter( filter );
98af5a
3c41cc ¤   priv = (FilteredSetPriv *)pgpContextMemAlloc( context,
dc9cf4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··sizeof( *priv ),
5fad4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··kPGPMemoryMgrFlags_Clear );
e27c2a ¤   if (priv == NULL)
ca4030 ¤   ¤   return kPGPError_OutOfMemory;
a6af5a
7f3b14 ¤   err = pgpNewKeySetInternal( origSet->keyDB, &newSet );
51054e ¤   if ( IsPGPError( err ) )
bbc7a1 ¤   {
9923c7 ¤   ¤   pgpContextMemFree( context, priv );
d0c9db ¤   ¤   return err;
439371 ¤   }
4baf5a
4941c1 ¤   priv->origSet¤  ¤   = origSet;
304f1a ¤   PGPIncKeySetRefCount(origSet);
ceaf5a
9c204c ¤   priv->filter¤   ¤   = filter;
e7d9ff ¤   PGPIncFilterRefCount(filter);
f6af5a
92a8aa ¤   newSet->priv¤   ¤   = priv;
2bea7b ¤   newSet->isMember¤   = sFilteredSetIsMember;
a5e279 ¤   newSet->makeUnion¤  = NULL;
82e763 ¤   newSet->destroy¤¤   = sFilteredSetDestroy;
d9af5a
ae5301 ¤   *outSet = newSet;
c47142 ¤   pgpAssertErrWithPtr( err, *outSet );
865ea8 ¤   return err;
9cefe6 }
52af5a
25af5a
bf7e4d /*__Editor_settings____
7daf5a
184126 ¤   Local Variables:
317b17 ¤   tab-width: 4
470e6c ¤   End:
ca5f8c ¤   vi: ts=4 sw=4
f79e9b ¤   vim: si
e2d062 _____________________*/
--c69e 000972721a84010022a Page 1 of pgpKDBInt.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
eee31a ¤   $Id: pgpKDBInt.h,v 1.49.12.1 1998/11/12 03:21:54 heller Exp $
d1f7f7 ____________________________________________________________________________*/
5daf5a
8180ed #ifndef Included_pgpKDBInt_h
1101db #define Included_pgpKDBInt_h
afaf5a
43feb2 #include <stdio.h>
a3af5a
d4af5a
46711b #include "pgpKeyDB.h"
302d40 #include "pgpEventPriv.h"
e9a4b2 #include "pgpFileRef.h"
07675a #include "pgpTypes.h"
e9d11f #include "pgpUsuals.h"
8e2f8d #include "pgpErrors.h"
ee0d08 #include "pgpMem.h"
b895a9 #include "pgpMemPool.h"
9626e3 #include "pgpRngPub.h"
60af5a
d3121d #include "pgpKeyFilterPriv.h"
b201ab #include "pgpKeyDBOpaqueStructs.h"
edaf5a
abaf5a
9b95d7 /*·
3a5369 ·* An internal object representing a source of keys, either a file,
b85d51 ·* some memory, or a union of other PGPKeyDBs
17495d ·*/
c6990a struct PGPKeyDB
dcbb36 {
91a6b1 #define PGPKDBFILEMAGIC¤¤   0x1000
882f8b #define PGPKDBUNIONMAGIC¤   0x2000
c13dde #define PGPKDBMEMMAGIC¤ ¤   0x3000
c172db ¤   PGPInt32¤   ¤   ¤   typeMagic;
b5af5a
4f2c2d #define kPGPKeyDBMagic¤ ¤   0x4B594442¤ /* 'KYDB' */
a12afe ¤   PGPUInt32¤  ¤   ¤   fixedMagic;
0867c5 ¤
03f76c ¤   void *¤ ¤   ¤   ¤   priv;
f4d457 ¤   PGPInt32¤   ¤   ¤   refCount;
ab7925 ¤   PGPContextRef¤  ¤   context;
201575 ¤   PGPKeySetRef¤   ¤   firstSetInDB;
30af5a
c67c8e ¤   MemPool¤¤   ¤   ¤   keyPool;
30e269 ¤   long¤   ¤   ¤   ¤   numKeys;
01a25b ¤   PGPKeyRef¤  ¤   ¤   firstKeyInDB;
1da21d ¤   PGPKeyRef¤  ¤   ¤   firstFreeKey;
613c3f ¤   PGPSubKeyRef¤   ¤   firstFreeSubKey;
f45234 ¤   PGPUserIDRef¤   ¤   firstFreeUserID;
b84cfa ¤   PGPSigRef¤  ¤   ¤   firstFreeCert;
deab92 ¤   PGPKeyListRef¤  ¤   keysByKeyID;
cfaf5a
4f6ac2 ¤   /* Array of (PGPKeyDB *)s which this PGPKeyDB depends on until commit */
481618 ¤   PGPKeyDB **¤¤   ¤   keyDBDependencies;
5df8d0 ¤   long¤   ¤   ¤   ¤   numKeyDBDependenciesAllocated;¤ /* number allocated */
89ba22 ¤   long¤   ¤   ¤   ¤   numKeyDBDependencies;¤  ¤   ¤   /* number used */
c9af5a
cdf163 ¤   PGPBoolean¤ ¤   ¤   (*isMutable)¤   (PGPKeyDBRef db);
ec113b ¤   PGPBoolean¤ ¤   ¤   (*objIsMutable)¤(PGPKeyDBRef db,
e5b346 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingObject *testObj);
e73ca2 ¤   PGPBoolean¤ ¤   ¤   (*isDirty)¤ ¤   (PGPKeyDBRef db);
1f871a ¤   RingSet const *¤¤   (*getRingSet)¤  (PGPKeyDBRef db);
89af5a
f6a584 ¤   /* The RingSet arguments below must be of whole keys */
9c2e2d ¤   PGPError¤   ¤   ¤   (*add)¤ ¤   ¤   (PGPKeyDBRef db,
46da82 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingSet *toAdd);
9782bd ¤   PGPError¤   ¤   ¤   (*changed)¤ ¤   (PGPKeyDBRef db,
--0c39 000c42505e94010022a Page 2 of pgpKDBInt.h
b3aac6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingSet *changed);
76b6ad ¤   PGPError¤   ¤   ¤   (*remove)¤  ¤   (PGPKeyDBRef db,
1e65fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingObject *toRemove);
05af5a
4afa62 ¤   PGPError¤   ¤   ¤   (*commit)¤  ¤   (PGPKeyDBRef db);
464310 ¤   PGPError¤   ¤   ¤   (*revert)¤  ¤   (PGPKeyDBRef db);
32ce2b ¤   PGPError¤   ¤   ¤   (*reload)¤  ¤   (PGPKeyDBRef db);
b3b43f ¤   void¤   ¤   ¤   ¤   (*destroy)¤ ¤   (PGPKeyDBRef db);
d9af5a
5247ef ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPKeyDB )
f72fa1 } ;
d1af5a
f5af5a
ef38e5 /*
353b3b ·* Objects that represent Aurora RingObjects.¤  If an attempt is made to
2eb615 ·* delete an object, and refCount > 0, then the removed flag should
e46b82 ·* be set to TRUE instead.¤ The object can be physically deleted when the·
678844 ·* refCount drops to zero.
61775e ·*
0263a2 ·* listhdr saves memory but not having to embed a PGPUserID in·
20022f ·* a PGPKey, or a PGPSig in a PGPUserID, to maintain the doubly-linked
added7 ·* lists.¤  It may be typecast to PGPUserID or PGPSig as required.
e4495d ·*/
630fe8 typedef struct listhdr
78bb36 {
dd0cd7 ¤   struct listhdr *¤   next;
b20ecf ¤   struct listhdr *¤   prev;
31df42 } listhdr;
66af5a
52f6e1 enum certtype {keycert, uidcert};
09af5a
240335 /*____________________________________________________________________________
7fea2b ¤   To save memory, some items use magic fields in DEBUG mode only. ·All
cd8e86 ¤   the code to set and check them depends on the flag 'PGP_OPTIONAL_MAGICS'.
9cf7f7 ____________________________________________________________________________*/
9f3b77 #define PGP_OPTIONAL_MAGICS¤¤   PGP_DEBUG
f0af5a
7b72a8 #if PGP_OPTIONAL_MAGICS
83d98f #define pgpOptionalMagicMatches( ref, mgc )¤( (ref)->magic == mgc ·)
35db21 #else
df63c8 #define pgpOptionalMagicMatches( ref, mgc )¤¤   TRUE
1c7454 #endif
0eaf5a
630e4f struct PGPSig
dfbb36 {
478a65 ¤   /* caution: these must be first; see "struct listhdr" comments */
cb7351 ¤   PGPSigRef¤  ¤   ¤   next;¤
f09816 ¤   PGPSigRef¤  ¤   ¤   prev;
efaf5a
68f731 ¤   RingObject *¤   ¤   cert;
a44b5a ¤   enum certtype¤  ¤   type;
e3f20a ¤   union
ffc7a1 ¤   {
2ed14b ¤   ¤   PGPUserIDRef¤   userID;¤/* type == uidcert */
83cb2c ¤   ¤   PGPKeyRef¤  ¤   key;¤   ¤   /* type == keycert */
504540 ¤   } up;
abd457 ¤   PGPInt32¤   ¤   ¤   refCount;
7bb152 ¤   PGPUserValue¤   ¤   userVal;
761f19 ¤   PGPBoolean¤ ¤   ¤   removed;
bf72a8 #if PGP_OPTIONAL_MAGICS
bc8a87 #define kPGPCertMagic¤  0x43455254¤ /* 'CERT' */
32b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
7d7454 #endif
a02fa1 } ;
97af5a
bcaf5a
2a58f3 struct PGPUserID
dbbb36 {
9e8a65 ¤   /* caution: these must be first; see "struct listhdr" comments */
061b3e ¤   PGPUserIDRef¤   ¤   next;
b11926 ¤   PGPUserIDRef¤   ¤   prev;
c40bb2 ¤   listhdr¤¤   certs;¤ ¤   /* doubly-linked list of UserID certs */
--01e1 000ac35dbfb4010022a Page 3 of pgpKDBInt.h
006a70 ¤   RingObject *¤   ¤   userID;
6323e3 ¤   PGPKeyRef¤  ¤   ¤   key;
92d457 ¤   PGPInt32¤   ¤   ¤   refCount;
e81f19 ¤   PGPBoolean¤ ¤   ¤   removed;
77b152 ¤   PGPUserValue¤   ¤   userVal;
a367c5 ¤
2572a8 #if PGP_OPTIONAL_MAGICS
bceed2 #define kPGPUserIDMagic¤0x55534552¤ /* 'USER' */
32b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
007454 #endif
6d1dc3 } ·;
d8af5a
44af5a
e23dcb struct PGPSubKey
cebb36 {
158a65 ¤   /* caution: these must be first; see "struct listhdr" comments */
78178b ¤   PGPSubKeyRef¤   ¤   next;
c71593 ¤   PGPSubKeyRef¤   ¤   prev;
c2d7de ¤   RingObject *¤   ¤   subKey;
c423e3 ¤   PGPKeyRef¤  ¤   ¤   key;
0fd457 ¤   PGPInt32¤   ¤   ¤   refCount;
551f19 ¤   PGPBoolean¤ ¤   ¤   removed;
beb152 ¤   PGPUserValue¤   ¤   userVal;
7967c5 ¤
4f72a8 #if PGP_OPTIONAL_MAGICS
371ea6 #define kPGPSubKeyMagic¤0x5355424B¤ /* 'SUBK' */
07b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
4f7454 #endif
b81dc3 } ·;
b5af5a
62af5a
20af5a
1b8214 struct PGPKey
2cbb36 {
8dd457 ¤   PGPInt32¤   ¤   ¤   refCount;
a1c76b ¤   PGPKeyDBRef¤¤   ¤   keyDB;
b59116 ¤   PGPKeyRef¤  ¤   ¤   nextKeyInDB;
f728d8 ¤   RingObject *¤   ¤   key;
3c46d4 ¤   listhdr¤¤   ¤   ¤   subKeys;¤   ¤   /* doubly linked list of Subkeys */
6053ca ¤   listhdr¤¤   ¤   ¤   userIDs;¤   ¤   /* doubly linked list of UserIDs */
82b152 ¤   PGPUserValue¤   ¤   userVal;
d267c5 ¤
ad72a8 #if PGP_OPTIONAL_MAGICS
6b948e #define kPGPKeyMagic¤   0x4B455920¤ /* 'KEY ' */
20b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
2d7454 #endif
1e2fa1 } ;
a8af5a
2aaf5a
6c38e5 /*
62da05 ·* The external object which represents a filtered PGPKeyDB
cc495d ·*/
eb71f3 struct PGPKeySet
33bb36 {
69bc16 #define kPGPKeySetMagic¤0x4B534554¤ /* 'KSET' */
98b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
1df76c ¤   void *¤ ¤   ¤   ¤   priv;
f2d457 ¤   PGPInt32¤   ¤   ¤   refCount;
2cc76b ¤   PGPKeyDBRef¤¤   ¤   keyDB;
74aafd ¤   PGPKeySetRef¤   ¤   prevSetInDB;
68c98e ¤   PGPKeySetRef¤   ¤   nextSetInDB;
1542bc ¤   PGPKeyListRef¤  ¤   firstListInSet;
91af5a
8a46ba ¤   PGPBoolean¤ ¤   ¤   (*isMember)¤(PGPKeySetRef set, RingObject *obj);
d23d9c ¤   PGPError¤   ¤   ¤   (*makeUnion)(PGPKeySetRef set1, PGPKeySetRef set2,
849ec5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPKeySetRef *newSet);
2bf2b0 ¤   void¤   ¤   ¤   ¤   (*removeKey)(PGPKeySetRef set, PGPKeyRef key);
0f44ae ¤   void¤   ¤   ¤   ¤   (*destroy)¤ (PGPKeySetRef set);
442fa1 } ;
f1af5a
89af5a
acaf5a
--2702 000eea38d594010022a Page 4 of pgpKDBInt.h
bc38e5 /*
2fdadf ·* The external object which represents a sorted PGPKeySet
6b495d ·*/
dfc566 struct PGPKeyList
7bbb36 {
8f5c3f #define kPGPKeyListMagic¤   0x4B4C5354¤ /* 'KLST' */
10b5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
acd457 ¤   PGPInt32¤   ¤   ¤   refCount;
0ed695 ¤   PGPKeySetRef¤   ¤   keySet;
3a12e0 ¤   PGPKeyOrdering¤ ¤   order;
faaf5a
fab62c ¤   PGPKeyListRef¤  ¤   prevListInSet;
a03d1d ¤   PGPKeyListRef¤  ¤   nextListInSet;
b797f5 ¤   PGPKeyIterRef¤  ¤   firstIterInList;
e9af5a
5ff063 ¤   long¤   ¤   ¤   ¤   keyCount;¤  ¤   /* size of keys array */
b1be07 ¤   PGPKeyRef*¤ ¤   ¤   keys;
802fa1 } ;
ddaf5a
6faf5a
3838e5 /*
2b3feb ·* The external object which represents a key iterator
d9495d ·*/
1aac80 struct PGPKeyIter
a8bb36 {
f27863 #define kPGPKeyIterMagic¤   0x4B495452¤ /* 'KITR' */
afb5f4 ¤   PGPUInt32¤  ¤   ¤   magic;
e267c5 ¤
30758b ¤   PGPKeyListRef¤  ¤   keyList;¤   ¤   /* parent keylist */
63a585 ¤   PGPKeyIterRef¤  ¤   prevIterInList;¤/* next iter in keylist */
b4f2ec ¤   PGPKeyIterRef¤  ¤   nextIterInList;¤/* next iter in keylist */
c4af5a
48cbeb ¤   long¤   ¤   ¤   ¤   keyIndex;¤  ¤   /* current key index in keylist */
88f971 ¤   PGPKeyRef¤  ¤   ¤   key;¤   ¤   ¤   /* ptr to current key */
e07ee0 ¤   PGPSubKeyRef¤   ¤   subKey;¤¤   ¤   /* ptr to current subkey */
49fdbd ¤   PGPUserIDRef¤   ¤   userID;¤¤   ¤   /* ptr to current userid */
659e6c ¤   PGPSigRef¤  ¤   ¤   uidCert;¤   ¤   /* ptr to current userid cert */
fd2fa1 } ;
6daf5a
4baf5a
99a17b #define CHECKREMOVED(x)¤¤   \
3b2140 if (!(x) || (x)->removed)¤  \
85643a ¤   return kPGPError_ItemWasDeleted
faaf5a
f3af5a
daaf5a
68360d /* Global variables: These aren't valid until PGPLibInit() is called */
08af5a
86af5a
acaf5a
0c99c6 PGP_BEGIN_C_DECLARATIONS
1aaf5a
54bd15 /* Internal functions */
a1af5a
cc8f01 PGPKeyDBRef ¤   pgpKeyDBCreateInternal(PGPContextRef context);
82af5a
a2aa68 void¤   ¤   ¤   pgpKeyDBInitInternal(PGPKeyDBRef db);
ffaf5a
a83d91 void¤   ¤   ¤   pgpKeyDBDestroyInternal (PGPKeyDBRef db);
79af5a
fa3167 PGPKeyDBRef ¤   pgpKeyDBCreate(PGPContextRef context);
1faf5a
75bd66 PGPKeySetRef¤   pgpKeyDBRootSet(PGPKeyDBRef db);
cdaf5a
9bf6fb RingSet const *¤pgpKeyDBRingSet(PGPKeyDBRef db);
f8af5a
276402 PGPBoolean¤ ¤   pgpKeyDBIsMutable(PGPKeyDBRef db);
ebaf5a
d5a264 PGPBoolean¤ ¤   pgpKeyDBIsDirty(PGPKeyDBRef db);
4daf5a
ad68d2 PGPError¤   ¤   pgpKeyDBChanged(PGPKeyDBRef db, RingSet *changedkeys);
eeaf5a
--f2f2 000a10d6d854010022a Page 5 of pgpKDBInt.h
e7a227 PGPError¤   ¤   pgpCommitKeyDB(PGPKeyDBRef db);
24af5a
50bb49 PGPError¤   ¤   pgpPropagateTrustKeyDB(PGPKeyDBRef db);
c8af5a
93f028 PGPError¤   ¤   pgpCheckKeyDB (PGPKeyDBRef dbToCheck, PGPKeyDBRef dbSigning,
6f33e1 ¤   ¤   ¤   ¤   ¤   PGPBoolean checkAll,
9c4e38 ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr progress, PGPUserValue userValue);
32af5a
3c2e2e PGPError¤   ¤   pgpRevertKeyDB(PGPKeyDBRef db);
b8af5a
881b76 PGPError¤   ¤   pgpReloadKeyDB(PGPKeyDBRef db);
73af5a
80bb37 PGPKeyDBRef ¤   pgpCreateFileKeyDB (PGPContextRef context,
429db7 ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileRef, PGPKeyRingOpenFlags openFlags,
6b17bc ¤   ¤   ¤   ¤   ¤   RingPool *ringpool, PGPError *error);
4aaf5a
615d92 PGPKeyDBRef ¤   pgpCreateMemFileKeyDB (PGPContextRef context,
b5fdfd ¤   ¤   ¤   ¤   ¤   PGPByte *buf, size_t length, RingPool *ringpool,
899613 ¤   ¤   ¤   ¤   ¤   PGPError *error);
f7af5a
51663c PGPKeyDBRef·
130325 pgpCreateUnionKeyDB (PGPContextRef context, PGPError *error);
a2af5a
9f6673 PGPError¤   pgpUnionKeyDBAdd (PGPKeyDBRef kdb, PGPKeyDBRef kdbnew);
a8af5a
18638a PGPError¤   pgpKeySetRingSet(PGPKeySet *keys, PGPBoolean freezeit,
a76451 ¤   ¤   ¤   ¤   RingSet const **ringset);
3daf5a
012c72 void¤   ¤   pgpKeyIterAddKey (PGPKeyListRef keys, long idx);
2caf5a
3b9059 void¤   ¤   pgpKeyIterRemoveKey (PGPKeyListRef keys, long idx);
e4af5a
7f959d PGPError¤   pgpCopyKey (RingSet const *src, union RingObject *obj,·
3020fd ¤   ¤   ¤   ¤   RingSet **dest);
092b85 ¤   ¤   ¤   ¤
4154dc PGPError¤   pgpCopyKeySet( PGPKeySetRef¤orig, PGPKeySetRef * newOut );
64af5a
c172a3 PGPKeyRef¤  pgpGetKeyByRingObject (PGPKeyDBRef keys, union RingObject *obj);
d2af5a
84e0ad void¤   ¤   pgpDeallocSubKey (PGPSubKeyRef subkey);
2caf5a
194709 void¤   ¤   pgpDeallocUserID (PGPUserIDRef userid);
63af5a
29a1b2 void ¤  ¤   pgpDeallocCert (PGPSigRef cert);
12af5a
065b98 PGPError¤   pgpExpandKey (PGPKeyRef key);
6baf5a
492add PGPError¤   pgpCollapseKey (PGPKeyRef key);
4aaf5a
58d04e PGPError¤   pgpAddObjects (PGPKeyDBRef keys, RingSet *addset);
14af5a
ccc225 PGPError¤   pgpRemoveObject (PGPKeyDBRef keys, union RingObject *obj);·
c9af5a
4569f7 void¤   ¤   pgpIncKeyDBRefCount(PGPKeyDBRef db);
b1af5a
2f77c0 void¤   ¤   pgpFreeKeyDB(PGPKeyDBRef db);
86af5a
b01d16 PGPError¤   ¤   pgpBuildKeyPool(PGPKeyDBRef db, PGPBoolean deleteFlag);
5eaf5a
8458b0 PGPError¤   ¤   pgpReSortKeys(PGPKeyDBRef db, RingSet *set);
bbaf5a
20dd34 PGPError¤   ¤   pgpDearmorKeyFile (PGPEnv *env, PFLFileSpecRef InputFileRef,
a524ae ¤   ¤   ¤   ¤   ¤   PGPByte **OutputBuffer, PGPSize *OutputBufferLen);
c1af5a
efcdd8 PGPError¤   ¤   pgpDearmorKeyBuffer (PGPEnv *env,
b5c8e8 ¤   ¤   ¤   ¤   ¤   PGPByte const *InputBuffer, PGPSize InputBufferLen,
8324ae ¤   ¤   ¤   ¤   ¤   PGPByte **OutputBuffer, PGPSize *OutputBufferLen);
39af5a
f56f13 PGPError¤   pgpWriteArmoredSetFile (FILE *fp,
213245 ¤   ¤   ¤   ¤   RingSet const *set, PGPEnv *env);
8faf5a
a1b1cd PGPError¤   ¤   pgpWriteArmoredSetBuffer (PGPByte *buf,
--358a 000e730beb24010022a Page 6 of pgpKDBInt.h
5151e6 ¤   ¤   ¤   ¤   ¤   PGPSize *buflen, RingSet const *set,
328642 ¤   ¤   ¤   ¤   ¤   PGPEnv *env);
aeaf5a
04af5a
67af5a
7b508a PGPContextRef¤  pgpGetKeyDBContext( PGPKeyDBRef ref );
31af5a
ffaf5a
fe0034 PGPError ¤  ¤   pgpIncKeyRefCount( PGPKeyRef key);
1aa1fc PGPError ¤  ¤   pgpFreeKey(PGPKeyRef iter);
fea791 PGPError ¤  ¤   pgpIncUserIDRefCount (PGPUserIDRef userid);
c9a5aa PGPError ¤  ¤   pgpFreeUserID(PGPUserIDRef userid);
62b7ae PGPError ¤  ¤   pgpIncSigRefCount (PGPSigRef cert);
a9edcf PGPError ¤  ¤   pgpFreeSig (PGPSigRef cert);
82af5a
763d34 PGPError ¤  ¤   pgpIncSubKeyRefCount (PGPSubKeyRef subkey);
cb32cb PGPError ¤  ¤   pgpFreeSubKey(PGPSubKeyRef subkey);
8caf5a
0dc88e PGPError¤   ¤   pgpImportX509Certificate( PGPContextRef context,
e76e26 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *keys, PGPOptionListRef optionList);
87af5a
e09dd4 PGPBoolean¤ ¤   pgpKeyDBIsValid( PGPKeyDB const *keyDB);
115260 PGPBoolean¤ ¤   pgpKeySetIsValid( PGPKeySet const *keySet);
18df87 PGPBoolean¤ ¤   pgpKeyListIsValid( PGPKeyList const *keyList);
6a05eb PGPBoolean¤ ¤   pgpKeyIterIsValid( PGPKeyIter const *keyIter);
092cd1 PGPBoolean¤ ¤   pgpKeyIsValid( PGPKey const *key);
2fb96c PGPBoolean¤ ¤   pgpSubKeyIsValid( PGPSubKey const *subKey);
baa593 PGPBoolean¤ ¤   pgpUserIDIsValid( PGPUserID const *userID);
84d303 PGPBoolean¤ ¤   pgpSigIsValid( PGPSig const *cert);
8daf5a
a115d3 #define PGPValidateKeyDB( keyDB ) \
19575b ¤   ¤   ¤   PGPValidateParam( pgpKeyDBIsValid( keyDB ) )
4fac05 #define PGPValidateKeySet( keySet ) \
f850f5 ¤   ¤   ¤   PGPValidateParam( pgpKeySetIsValid( keySet ) )
e1661d #define PGPValidateKeyList( keyList ) \
342dfc ¤   ¤   ¤   PGPValidateParam( pgpKeyListIsValid( keyList ) )
03fe8a #define PGPValidateKeyIter( keyIter ) \
c2291a ¤   ¤   ¤   PGPValidateParam( pgpKeyIterIsValid( keyIter ) )
53cc0c #define PGPValidateKey( key ) \
25c009 ¤   ¤   ¤   PGPValidateParam( pgpKeyIsValid( key ) )
fdbd84 #define PGPValidateSubKey( subKey ) \
a8a2f2 ¤   ¤   ¤   PGPValidateParam( pgpSubKeyIsValid( subKey ) )
8e3891 #define PGPValidateUserID( userID ) \
f72d77 ¤   ¤   ¤   PGPValidateParam( pgpUserIDIsValid( userID ) )
d00f0f #define PGPValidateCert( cert ) \
6c9123 ¤   ¤   ¤   PGPValidateParam( pgpSigIsValid( cert ) )
52af5a
74af5a
4ae85e #if PGP_DEBUG¤  /* [ */
deaf5a
5b38e5 /*
4b7fb8 ·* Debugging support
c6495d ·*/
110fcd #define pgpaPGPKeyDBValid(db)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
cc9aeb ¤   ¤   ¤   pgpaCall(pgpaInternalPGPKeyDBValid,( pgpaCallPrefix, db, #db))
e6b7c9 #define pgpaPGPKeySetValid(set)¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
bcea13 ¤   ¤   ¤   pgpaCall(pgpaInternalPGPKeySetValid,( pgpaCallPrefix, set, #set))
fdda61 #define pgpaPGPKeyListValid(list)¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
8acda2 ¤   ¤   ¤   pgpaCall(pgpaInternalPGPKeyListValid,( pgpaCallPrefix,list,#list))
f0cea4 #define pgpaPGPKeyIterValid(iter )¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
7850dc ¤   ¤   ¤   pgpaCall(pgpaInternalPGPKeyIterValid,(pgpaCallPrefix,iter,#iter ))
1c683d #define pgpaPGPKeyValid(key )¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
67ac40 ¤   ¤   ¤   pgpaCall(pgpaInternalPGPKeyValid,( pgpaCallPrefix, key, #key ))
6a342a #define pgpaPGPSubKeyValid(subKey )¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
82bcb6 ¤   ¤   ¤   pgpaCall(pgpaInternalPGPSubKeyValid,¤   ¤   ¤   ¤   ¤   ¤   ¤   \
19bff2 ¤   ¤   ¤   ¤   (pgpaCallPrefix, subKey, #subKey ))
6a0d80 #define pgpaPGPUserIDValid(userID)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
7b0a79 ¤   ¤   ¤   pgpaCall(pgpaInternalPGPUserIDValid,¤   ¤   ¤   ¤   ¤   ¤   ¤   \
47a44e ¤   ¤   ¤   ¤   (pgpaCallPrefix, userID, #userID))
527602 #define pgpaPGPCertValid(cert)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
886276 ¤   ¤   ¤   pgpaCall(pgpaInternalPGPCertValid,( pgpaCallPrefix, cert, #cert))
e7af5a
--65b9 001cd11da164010022a Page 7 of pgpKDBInt.h
e0af5a
aedb06 PGPBoolean¤ ¤   pgpaInternalPGPKeyDBValid(pgpaCallPrefixDef,
bf22bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyDB const *keyDB, char const *varName);
b2928f PGPBoolean¤ ¤   pgpaInternalPGPKeySetValid(pgpaCallPrefixDef,
723c26 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySet const *keySet, char const *varName);
95ec89 PGPBoolean¤ ¤   pgpaInternalPGPKeyListValid(pgpaCallPrefixDef,
df657a ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyList const *keyList, char const *varName);
ba9016 PGPBoolean¤ ¤   pgpaInternalPGPKeyIterValid(pgpaCallPrefixDef,
127de5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyIter const *keyIter, char const *varName);
452811 PGPBoolean¤ ¤   pgpaInternalPGPKeyValid(pgpaCallPrefixDef,
73e54e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKey const *key, char const *varName);
7bc5fa PGPBoolean¤ ¤   pgpaInternalPGPSubKeyValid(pgpaCallPrefixDef,
c3bb3b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKey const *subKey, char const *varName);
d6c56b PGPBoolean¤ ¤   pgpaInternalPGPUserIDValid(pgpaCallPrefixDef,
52b3e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserID const *userID, char const *varName);
3d2610 PGPBoolean¤ ¤   pgpaInternalPGPCertValid(pgpaCallPrefixDef,
a1522b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSig const *cert, char const *varName);
85af5a
b49e9f #endif /* ] PGP_DEBUG */
cbaf5a
1c0adc /* Access functions for internal use by other parts of the library */
3a3a37 PGPError¤   ¤   pgpGetKeyRingObject(PGPKey *key, PGPBoolean checkDead,
2902f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingObject **pRingKey);
9606df PGPError¤   ¤   pgpGetKeyRingSet(PGPKey *key, PGPBoolean checkDead,
7d4204 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingSet const **pRingSet);
03cf56 PGPError¤   ¤   pgpGetUserIDRingObject(PGPUserID *userid, PGPBoolean checkDead,
5a5a6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingObject **pRingName);
a39621 PGPError¤   ¤   pgpGetUserIDRingSet(PGPUserID *userid, PGPBoolean checkDead,
7a4204 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingSet const **pRingSet);
ac2934 PGPError¤   ¤   pgpGetUserIDKey(PGPUserID *userid, PGPBoolean checkDead,
c5e56b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKey **pKey);
78e56f PGPError¤   ¤   pgpGetCertRingObject(PGPSig *cert, PGPBoolean checkDead,
827bcd ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingObject **pRingSig);
4ae8a1 PGPError¤   ¤   pgpGetCertRingSet(PGPSig *cert, PGPBoolean checkDead,
744204 ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingSet const **pRingSet);
3ee2c6 PGPError¤   ¤   pgpGetCertUserID(PGPSig *cert, PGPBoolean checkDead,
2abfef ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserID **pUserid);
dba18d PGPError¤   ¤   pgpGetCertKey(PGPSig *cert, PGPBoolean checkDead,
cee56b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKey **pKey);
c6af5a
4140b2 PGPError¤   ¤   pgpNewKeySetInternal(PGPKeyDBRef db, PGPKeySetRef *newSet);
aecb74 PGPError¤   ¤   pgpGenericUnionOfKeySets(PGPKeySetRef set1, PGPKeySetRef set2,
12cff7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *newSet);
5aaf5a
eaaf5a
881254 PGP_END_C_DECLARATIONS
64af5a
76af5a
50af5a
bd8635 #endif /* PGPKBDINT.h */
a3af5a
cd38e5 /*
f4e6c5 ·* Local Variables:
869b19 ·* tab-width: 4
d8e7a4 ·* End:
0cb612 ·* vi: ts=4 sw=4
586c42 ·* vim: si
cd495d ·*/
--6923 0001987b9a74010022b Page 1 of pgpKeyDB.h
a70335 /*____________________________________________________________________________
4b4a50 ¤   pgpKeyDB.h
dd67c5 ¤
557edb ¤   Copyright( C) 1996,1997 Network Associates, Inc. and its affiliates.
224b0f ¤   All rights reserved.
df67c5 ¤
d4e89f ¤   Private definitions for PGP KeyDB Library
46af5a
6c6ce6 ¤   $Id: pgpKeyDB.h,v 1.38.12.1 1998/11/12 03:21:54 heller Exp $
7af7f7 ____________________________________________________________________________*/
039dea #ifndef Included_pgpKeyDB_h¤/* [ */
bf3088 #define Included_pgpKeyDB_h
99af5a
f7e2ff #include "pgpConfig.h"
ecaf5a
c7cbcf #if PRAGMA_IMPORT_SUPPORTED
f1b981 #pragma import on
d57454 #endif
50af5a
aca076 #include "pgpKeys.h"
085a03 #include "pgpTrust.h"
2e26e3 #include "pgpRngPub.h"
64af5a
da6e0b /* private entry points */
a7af5a
1199c6 PGP_BEGIN_C_DECLARATIONS
ceaf5a
07af5a
d56aa9 /* always returns PGPTRUST0 in this release */
9abcbf PgpTrustModel ¤ PGPGetTrustModel( PGPContextRef context );
c0af5a
0549f0 PGPError¤   ¤   pgpDearmorKey(PGPEnv *env, int fFilein,
d06326 ¤   ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef InputFileRef, PGPFileRead *pfrin,
54d3e1 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte const *InputBuffer, PGPSize InputBufferLen,
b4f405 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **OutputBuffer, PGPSize *OutputBufferLen);
94af5a
a8dc76 PGPUInt32 ¤ pgpKeyEntropyNeededInternal(PGPContextRef context,
23870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
26c5d9 PGPError ¤  pgpGenerateKeyInternal(PGPContextRef context,
1eae81 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *key, PGPOptionListRef optionList);
f7c7fa PGPError ¤  pgpGenerateSubKeyInternal(PGPContextRef context,
b2427d ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKeyRef *subkey, PGPOptionListRef optionList);
3df3f5 PGPError ¤  pgpExportKeySetInternal(PGPKeySet *keys,
20870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
663996 PGPError ¤  pgpImportKeySetInternal(PGPContextRef context,
f47890 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *keys, PGPOptionListRef optionList);
d14de7 PGPError ¤  pgpCertifyUserIDInternal(PGPUserID *userid,
d6d730 ¤   ¤   ¤   ¤   ¤   ¤   PGPKey *certifyingKey, PGPOptionListRef optionList);
f0b3aa PGPError¤   pgpImportKeyBinary(PGPContextRef cdkContext, PGPByte *buffer,
bf8117 ¤   ¤   ¤   ¤   ¤   ¤   size_t length, PGPKeySetRef *outRef);
0b5e15 PGPError¤   pgpAddUserIDInternal(PGPKeyRef key, char const *userID,
c8870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
20e3c1 PGPError¤   pgpAddAttributeInternal(PGPKeyRef key,
06f5d9 ¤   ¤   ¤   ¤   ¤   ¤   PGPAttributeType attributeType,
1a1bf1 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte const *attributeData, PGPSize attributeLength,
cb870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
ff5ef9 PGPError¤   pgpRevokeCertInternal(PGPSigRef cert, PGPKeySetRef allkeys,
41870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
ff750e PGPError¤   pgpRevokeKeyInternal(PGPKeyRef key, PGPOptionListRef optionList);
ffa29c PGPError¤   pgpRevokeSubKeyInternal(PGPSubKeyRef subkey,
f5870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
e64932 PGPError¤   pgpGetFirstSubKey(PGPKeyRef key, PGPSubKeyRef *subKey);
af4af7 PGPError¤   pgpChangePassphraseInternal(PGPKeyRef key,
61870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
ad7465 PGPError¤   pgpChangeSubKeyPassphraseInternal(PGPSubKeyRef subkey,
a5870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
03cf8b PGPBoolean¤ pgpPassphraseIsValidInternal(PGPKeyRef key,
45870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
c15b5a PGPError¤   pgpSetKeyAxiomaticInternal(PGPKeyRef key,
a8870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
94a6d5 PGPError¤   pgpGetKeyPasskeyBufferInternal(PGPKeyRef key,
19402a ¤   ¤   ¤   ¤   ¤   ¤   void *passkeyBuffer, PGPOptionListRef optionList);
--18d8 001bbfa9c074010022b Page 2 of pgpKeyDB.h
74c030 PGPError¤   pgpGetSubKeyPasskeyBufferInternal(PGPSubKeyRef subkey,
54402a ¤   ¤   ¤   ¤   ¤   ¤   void *passkeyBuffer, PGPOptionListRef optionList);
96af5a
d58957 PGPError¤   pgpAddKeyOptionsInternal (PGPKeyRef key,
8c870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
52e322 PGPError¤   pgpRemoveKeyOptionsInternal (PGPKeyRef key,
ba870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
f01fc3 PGPError¤   pgpUpdateKeyOptionsInternal (PGPKeyRef key,
81870b ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
3aaf5a
98af5a
3eaf5a
ca1254 PGP_END_C_DECLARATIONS
31af5a
abcbcf #if PRAGMA_IMPORT_SUPPORTED
2b2ced #pragma import reset
fa7454 #endif
48af5a
7b4ce6 #endif /* ] Included_pgpKeyDB_h */
2baf5a
917e4d /*__Editor_settings____
11af5a
9d4126 ¤   Local Variables:
857b17 ¤   tab-width: 4
c80e6c ¤   End:
d25f8c ¤   vi: ts=4 sw=4
e39e9b ¤   vim: si
bbd062 _____________________*/
--8d79 000b317baab4010022c Page 1 of pgpKeyFilter.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
12570b ¤   Key filtering routines implementing the PGPFilterRef abstract data type
5baf5a
eeb784 ¤   $Id: pgpKeyFilter.c,v 1.87.10.1 1998/11/12 03:21:56 heller Exp $
f3f7f7 ____________________________________________________________________________*/
c6e2ff #include "pgpConfig.h"
3baf5a
b7324c #include <string.h>
7bb1cb #include <ctype.h>
c8af5a
37a146 #include "pgpDebug.h"
272f8d #include "pgpErrors.h"
dfc26c #include "pgpContext.h"
2b979a #include "pgpKDBInt.h"
f6121d #include "pgpKeyFilterPriv.h"
cb7ca7 #include "pgpKeyIDPriv.h"
aa2266 #include "pgpTimeDate.h"
ce7ca7 #include "pgpKeyIDPriv.h"
9faf5a
8eaf5a
45af5a
4216ea ¤   PGPBoolean
7b2cab PGPFilterIsValid( PGPFilterRef¤ filter )
55bb36 {
5b44d6 ¤   return( IsntNull( filter ) && filter->magic == kPGPFilterMagic );
d8efe6 }
e2af5a
a4af5a
feaf5a
8cb296 #define PGPValidateMatchCriterion( m ) \
b7d477 ¤   pgpAssert( (m) == kPGPMatchEqual || (m) == kPGPMatchGreaterOrEqual || \
7e7bdf ¤   ¤   ¤   ···(m) == kPGPMatchLessOrEqual || (m) == kPGPMatchSubString )
4b67c5 ¤
7e67c5 ¤
dd38e5 /*
da000c ·* Stolen from pgpRngPub.c:
fd775e ·*
95ef15 ·* Return pointer to first instance of (s1,l1) in (s0,l0),
417692 ·* ignoring case. ·Uses a fairly simple-minded algorithm.
fb7a2b ·* Search for the first char of s1 in s0, and when we have it,
7684a0 ·* scan for the rest.
1d775e ·*
717937 ·* Is it worth mucking with Boyer-Moore or the like?
9b495d ·*/
52d10a static char const *
200d1d xmemimem(char const *s0, size_t l0, char const *s1, size_t l1)
c9bb36 {
e774c5 ¤   char c0, c1, c2;
bcb9b0 ¤   size_t l;
1faf5a
18d8af ¤   /*
54ddcb ¤   ·* The trivial cases - this means that NULL inputs are very legal
954bb4 ¤   ·* if the correspinding lengths are zero.
aca4e3 ¤   ·*/
42d7b6 ¤   if (l0 < l1)
657ed2 ¤   ¤   return NULL;
d5c859 ¤   if (!l1)
8b25b4 ¤   ¤   return s0;
7dc6c4 ¤   l0 -= l1;
98af5a
5299f1 ¤   c1 = tolower((unsigned char)*s1);
ae43ab ¤   do {
75f9c7 ¤   ¤   c0 = tolower((unsigned char)*s0);
e7d228 ¤   ¤   if (c0 == c1) {
e08cd6 ¤   ¤   ¤   l = 0;
dff603 ¤   ¤   ¤   do {
9d895a ¤   ¤   ¤   ¤   if (++l == l1)
0ce894 ¤   ¤   ¤   ¤   ¤   return s0;
b3108c ¤   ¤   ¤   ¤   c0 = tolower((unsigned char)s0[l]);
--6473 000ea85ab664010022c Page 2 of pgpKeyFilter.c
66952b ¤   ¤   ¤   ¤   c2 = tolower((unsigned char)s1[l]);
de7244 ¤   ¤   ¤   } while (c0 == c2);
a40fe4 ¤   ¤   }
77b5f1 ¤   ¤   s0++;
e47014 ¤   } while (l0--);
6c3f59 ¤   return NULL;
7eefe6 }
a1af5a
7eaf5a
9866dd ¤   static PGPError
ac4a96 sAllocateFilter(
c65a0a ¤   PGPContextRef¤  ¤   context,·
35d045 ¤   PGPFilterClass ¤¤   filterClass,·
d633fe ¤   PGPFilterType¤  ¤   filterType,
c34560 ¤   PGPMatchCriterion¤  match,
65e861 ¤   PGPFilterRef *¤ ¤   outFilter)
73bb36 {
391310 ¤   PGPFilterRef¤   newFilter¤  = NULL;
2c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1aaf5a
5dc263 ¤   PGPValidatePtr( outFilter );
8801da ¤   *outFilter¤ = NULL;
5cf3ca ¤   PGPValidateContext( context );
0687e6 ¤   PGPValidateParam( filterType < kPGPFilterTypeEnd );
75475f ¤   PGPValidateMatchCriterion( match );
cd67c5 ¤
bacc28 ¤   newFilter¤  = (PGPFilterRef)
bffc3f ¤   ¤   pgpContextMemAlloc( context, sizeof( PGPFilter),
25f048 ¤   ¤   kPGPMemoryMgrFlags_Clear);
1a075e ¤   if( IsntNull( newFilter ) )
96c7a1 ¤   {
df027b ¤   ¤   newFilter->magic¤   ¤   = kPGPFilterMagic;
3a4dbb ¤   ¤   newFilter->context¤ ¤   = context;
171a56 ¤   ¤   newFilter->refCount¤¤   = 1;
111209 ¤   ¤   newFilter->filterClass¤ = filterClass;
d9b648 ¤   ¤   newFilter->filterType¤  = filterType;
d6c3c9 ¤   ¤   newFilter->match¤   ¤   = match;
009371 ¤   }
9b0e24 ¤   else
59c7a1 ¤   {
d417a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
6e9371 ¤   }
6baf5a
0867c5 ¤
a80bbe ¤   *outFilter = newFilter;
40ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
b35ea8 ¤   return err;
1befe6 }
3eaf5a
41af5a
1ac744 ¤   PGPError
b0b110 PGPIncFilterRefCount( PGPFilterRef filter )
93bb36 {
6c4ffe ¤   PGPValidateFilter( filter );
96fcf2 ¤   filter->refCount++;
36151e ¤   return kPGPError_NoErr;
9fefe6 }
7baf5a
0caf5a
46c744 ¤   PGPError
69cce7 PGPFreeFilter( PGPFilterRef filter )
cdbb36 {
4526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2467c5 ¤
a94ffe ¤   PGPValidateFilter( filter );
4a67c5 ¤
cc3d04 ¤   pgpAssert( filter->refCount >= 1 );
5b67c5 ¤
9261b1 ¤   filter->refCount--;
03d374 ¤   if( filter->refCount == 0 )·
14c7a1 ¤   {
ea3334 ¤   ¤   PGPContextRef¤  context¤¤   = filter->context;
--d901 00097a3ac8d4010022c Page 3 of pgpKeyFilter.c
6e965e ¤   ¤   void *¤ ¤   ¤   ptrToFree¤  = NULL;
b51b52 ¤   ¤
9d1025 ¤   ¤   switch( filter->filterType)·
705b34 ¤   ¤   {
089ae3 ¤   ¤   default:
48cdcb ¤   ¤   ¤   break;
5ba537 ¤   ¤   case kPGPFilterTypeKeyKeyID:
aecdcb ¤   ¤   ¤   break;
edbbec ¤   ¤   case kPGPFilterTypeKeySubKeyID:
ffcdcb ¤   ¤   ¤   break;
abbe91 ¤   ¤   case kPGPFilterTypeKeyFingerPrint:
dd02ca ¤   ¤   ¤   ptrToFree¤  = filter->value.keyFingerPrint.keyFingerPrintData;
95cdcb ¤   ¤   ¤   break;
9730f7 ¤   ¤   case kPGPFilterTypeUserIDEmail:
7d94ff ¤   ¤   ¤   ptrToFree¤  = filter->value.userIDEmail;
25cdcb ¤   ¤   ¤   break;
4ba20d ¤   ¤   case kPGPFilterTypeUserIDName:
86a0ed ¤   ¤   ¤   ptrToFree¤  = filter->value.userIDName;
83cdcb ¤   ¤   ¤   break;
2023e6 ¤   ¤   case kPGPFilterTypeUserIDString:
1cec0e ¤   ¤   ¤   ptrToFree¤  = filter->value.userIDString;
02cdcb ¤   ¤   ¤   break;
9c3516 ¤   ¤   case kPGPFilterTypeSigKeyID:
83cdcb ¤   ¤   ¤   break;
4d87c7 ¤   ¤   ¤
ee6415 ¤   ¤   case kPGPFilterTypeNot:
f81d5a ¤   ¤   ¤   PGPFreeFilter( filter->value.notFilter );
03cdcb ¤   ¤   ¤   break;
4197c7 ¤   ¤   case kPGPFilterTypeAnd:
db782c ¤   ¤   ¤   PGPFreeFilter( filter->value.andFilter.andFilter1 );
e065e0 ¤   ¤   ¤   PGPFreeFilter( filter->value.andFilter.andFilter2 );
7bcdcb ¤   ¤   ¤   break;
03a0b9 ¤   ¤   case kPGPFilterTypeOr:
9dda03 ¤   ¤   ¤   PGPFreeFilter( filter->value.orFilter.orFilter1 );
f9c7cf ¤   ¤   ¤   PGPFreeFilter( filter->value.orFilter.orFilter2 );
becdcb ¤   ¤   ¤   break;
5f0fe4 ¤   ¤   }
d81b52 ¤   ¤
0a2a40 ¤   ¤   if ( IsntNull( ptrToFree ) )
7f5b34 ¤   ¤   {
4c5059 ¤   ¤   ¤   pgpContextMemFree( context, ptrToFree);
240fe4 ¤   ¤   }
681b52 ¤   ¤
666e5b ¤   ¤   pgpContextMemFree( context, filter );
a09371 ¤   }
7d67c5 ¤
c95ea8 ¤   return err;
32efe6 }
7faf5a
afaf5a
f20335 /*____________________________________________________________________________
3418db ¤   The passed in filter will be freed when the newly created filter is
00712a ¤   freed. ·Therefore, if an error occurs, the passed filter must
307ca7 ¤   also be freed. ·Caller should increment the passed-in filter·
ff02e0 ¤   ref count if the filter should persist.
14f7f7 ____________________________________________________________________________*/
a0c744 ¤   PGPError
f2bacf PGPNegateFilter(
acfadc ¤   PGPFilterRef¤   filter,
c75a1a ¤   PGPFilterRef *¤ outFilter)
06bb36 {
4f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
25af5a
e33e17 ¤   if ( IsntNull( outFilter ) )
24c7a1 ¤   {
e4f7bf ¤   ¤   *outFilter¤ = NULL;
e2c326 ¤   ¤   if ( ! PGPFilterIsValid( filter ) )
2dfdcd ¤   ¤   ¤   err¤= kPGPError_BadParams;
029371 ¤   }
4e0e24 ¤   else
5ac7a1 ¤   {
97bc3e ¤   ¤   err¤= kPGPError_BadParams;
--d49c 000deb3f9424010022c Page 4 of pgpKeyFilter.c
a19371 ¤   }
521b52 ¤   ¤
d7f1e7 ¤   if ( IsntPGPError( err ) )
bfc7a1 ¤   {
4443a6 ¤   ¤   err = sAllocateFilter( filter->context, filter->filterClass,
84cead ¤   ¤   ¤   ¤   kPGPFilterTypeNot, kPGPMatchDefault, outFilter);
e0b5d2 ¤   ¤   pgpAssertErrWithPtr( err, *outFilter );
59da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
7f7d98 ¤   ¤   if ( IsntPGPError( err ) )
7f5b34 ¤   ¤   {
4bdee2 ¤   ¤   ¤   (*outFilter)->value.notFilter¤  = filter;
120fe4 ¤   ¤   }
f19371 ¤   }
0567c5 ¤
d3fba4 ¤   /* careful to clean up in event of error */
2b054e ¤   if ( IsPGPError( err ) )
15c7a1 ¤   {
47cb91 ¤   ¤   if ( PGPFilterIsValid( filter ) )
e65b34 ¤   ¤   {
387b9c ¤   ¤   ¤   PGPFreeFilter( filter );
d39676 ¤   ¤   ¤   filter¤ = NULL;
910fe4 ¤   ¤   }
499371 ¤   }
9d67c5 ¤
77ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
905ea8 ¤   return err;
43efe6 }
78af5a
d3af5a
eb0335 /*____________________________________________________________________________
12c36b ¤   The passed in filters will be freed when the newly created filter is
2a8ff7 ¤   freed. ·Therefore, if an error occurs, the passed filters must
fd7ca7 ¤   also be freed. ·Caller should increment the passed-in filter·
d7f442 ¤   ref count if the filters should persist.
ddf7f7 ____________________________________________________________________________*/
f9c744 ¤   PGPError
b40f29 PGPIntersectFilters(
33c5e8 ¤   PGPFilterRef ¤  filter1,
77ce73 ¤   PGPFilterRef¤   filter2,·
d75a1a ¤   PGPFilterRef *¤ outFilter)
bcbb36 {
f9d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
2d1b52 ¤   ¤
cf3e17 ¤   if ( IsntNull( outFilter ) )
16f7bf ¤   ¤   *outFilter¤ = NULL;
7387c7 ¤   ¤   ¤
550b0e ¤   if ( IsntNull( outFilter ) &&
2dd983 ¤   ¤   PGPFilterIsValid( filter1 ) &&
c52180 ¤   ¤   PGPFilterIsValid( filter2 ) ·)
8cc7a1 ¤   {
a7997b ¤   ¤   PGPFilterClass¤ ¤   filterClass;
f167c5 ¤
7757ac ¤   ¤   filterClass = filter1->filterClass & filter2->filterClass;
37b596 ¤   ¤   if( filterClass == 0 )
490a42 ¤   ¤   ¤   err¤= kPGPError_InconsistentFilterClasses;
c087c7 ¤   ¤   ¤
dd7d98 ¤   ¤   if ( IsntPGPError( err ) )
1f5b34 ¤   ¤   {
51a5e9 ¤   ¤   ¤   err = sAllocateFilter( filter1->context, filterClass,
2bc6bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPFilterTypeAnd, kPGPMatchDefault,·
9ea115 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outFilter);
0d698b ¤   ¤   ¤   if( IsntPGPError( err ) )
b3f776 ¤   ¤   ¤   {
b66b2f ¤   ¤   ¤   ¤   (*outFilter)->value.andFilter.andFilter1 = filter1;
8e8abc ¤   ¤   ¤   ¤   (*outFilter)->value.andFilter.andFilter2 = filter2;
81a3a6 ¤   ¤   ¤   }
e50fe4 ¤   ¤   }
699371 ¤   }
990e24 ¤   else
48c7a1 ¤   {
7abc3e ¤   ¤   err¤= kPGPError_BadParams;
de9371 ¤   }
--9087 00022f4140f4010022c Page 5 of pgpKeyFilter.c
2a67c5 ¤
e567c5 ¤
e5fba4 ¤   /* careful to clean up in event of error */
37054e ¤   if ( IsPGPError( err ) )
12c7a1 ¤   {
6b5148 ¤   ¤   if ( PGPFilterIsValid( filter1 ) )
bf28f4 ¤   ¤   ¤   PGPFreeFilter( filter1 );
445d35 ¤   ¤   if ( PGPFilterIsValid( filter2 ) )
6a3538 ¤   ¤   ¤   PGPFreeFilter( filter2 );
2e9371 ¤   }
7067c5 ¤
46ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
bb5ea8 ¤   return err;
34efe6 }
d3af5a
b4af5a
de0335 /*____________________________________________________________________________
17c36b ¤   The passed in filters will be freed when the newly created filter is
e28ff7 ¤   freed. ·Therefore, if an error occurs, the passed filters must
7d7ca7 ¤   also be freed. ·Caller should increment the passed-in filter·
2cf442 ¤   ref count if the filters should persist.
dff7f7 ____________________________________________________________________________*/
ffc744 ¤   PGPError
19407c PGPUnionFilters(
a4be48 ¤   PGPFilterRef¤   filter1,
0cce73 ¤   PGPFilterRef¤   filter2,·
b85a1a ¤   PGPFilterRef *¤ outFilter)
23bb36 {
e79372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
dbaf5a
db3e17 ¤   if ( IsntNull( outFilter ) )
80f7bf ¤   ¤   *outFilter¤ = NULL;
4c1b52 ¤   ¤
230b0e ¤   if ( IsntNull( outFilter ) &&
c6d983 ¤   ¤   PGPFilterIsValid( filter1 ) &&
942180 ¤   ¤   PGPFilterIsValid( filter2 ) ·)
d3c7a1 ¤   {
e14c5d ¤   ¤   PGPFilterClass¤ filterClass;
d467c5 ¤
b0ed02 ¤   ¤   filterClass¤= filter1->filterClass & filter2->filterClass;
1ab596 ¤   ¤   if( filterClass == 0 )
d80a42 ¤   ¤   ¤   err¤= kPGPError_InconsistentFilterClasses;
7387c7 ¤   ¤   ¤
177d98 ¤   ¤   if ( IsntPGPError( err ) )
ae5b34 ¤   ¤   {
8a5f26 ¤   ¤   ¤   err = sAllocateFilter( filter1->context, filterClass,·
0587e0 ¤   ¤   ¤   ¤   ¤   kPGPFilterTypeOr, kPGPMatchDefault, ·outFilter);
af698b ¤   ¤   ¤   if( IsntPGPError( err ) )
49f776 ¤   ¤   ¤   {
b0b9ce ¤   ¤   ¤   ¤   (*outFilter)->value.orFilter.orFilter1 = filter1;
78585d ¤   ¤   ¤   ¤   (*outFilter)->value.orFilter.orFilter2 = filter2;
f8a3a6 ¤   ¤   ¤   }
650fe4 ¤   ¤   }
e59371 ¤   }
190e24 ¤   else
2ec7a1 ¤   {
59bc3e ¤   ¤   err¤= kPGPError_BadParams;
5b9371 ¤   }
c867c5 ¤
3bfba4 ¤   /* careful to clean up in event of error */
59054e ¤   if ( IsPGPError( err ) )
bec7a1 ¤   {
e05148 ¤   ¤   if ( PGPFilterIsValid( filter1 ) )
3e28f4 ¤   ¤   ¤   PGPFreeFilter( filter1 );
405d35 ¤   ¤   if ( PGPFilterIsValid( filter2 ) )
4f3538 ¤   ¤   ¤   PGPFreeFilter( filter2 );
a09371 ¤   }
1b67c5 ¤
0ead82 ¤   pgpAssertErrWithPtr( err, *outFilter );
9b5ea8 ¤   return err;
f6efe6 }
22af5a
--db05 0001a4cc6334010022c Page 6 of pgpKeyFilter.c
e0af5a
01c744 ¤   PGPError
4c269a PGPNewKeyIDFilter(·
4ba1bc ¤   PGPContextRef¤  ¤   context,
53f3c6 ¤   PGPKeyID const *¤   keyID, ·
ffe861 ¤   PGPFilterRef *¤ ¤   outFilter)
d2bb36 {
ec9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
901310 ¤   PGPFilterRef¤   newFilter¤  = NULL;
b5af5a
2ec263 ¤   PGPValidatePtr( outFilter );
a0b9b1 ¤   *outFilter = NULL;
a2f3ca ¤   PGPValidateContext( context );
66c2b5 ¤   PGPValidateKeyID( keyID );
6c67c5 ¤
a9d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
487ebd ¤   ¤   ¤   kPGPFilterTypeKeyKeyID, kPGPMatchDefault, &newFilter);
88b1f0 ¤   if( IsntPGPError( err ) )
b9c7a1 ¤   {
22f2a7 ¤   ¤   newFilter->value.keyKeyID¤  = *keyID;
7c9371 ¤   }
8a67c5 ¤
390bbe ¤   *outFilter = newFilter;
65ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
945ea8 ¤   return err;
8ba79b }·
e9af5a
30c744 ¤   PGPError
9bf265 PGPNewSubKeyIDFilter(·
b8a1bc ¤   PGPContextRef¤  ¤   context,
983aff ¤   PGPKeyID const *¤   subKeyID, ·
f5e861 ¤   PGPFilterRef *¤ ¤   outFilter)
22bb36 {
4d9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1a1310 ¤   PGPFilterRef¤   newFilter¤  = NULL;
54af5a
0cc263 ¤   PGPValidatePtr( outFilter );
afb9b1 ¤   *outFilter = NULL;
11f3ca ¤   PGPValidateContext( context );
ebbdf3 ¤   PGPValidateKeyID( subKeyID );
0867c5 ¤
93d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
946c4e ¤   ¤   ¤   kPGPFilterTypeKeySubKeyID, kPGPMatchDefault, &newFilter);
aeb1f0 ¤   if( IsntPGPError( err ) )
2ec7a1 ¤   {
596061 ¤   ¤   newFilter->value.keySubKeyID¤   = *subKeyID;
149371 ¤   }
c467c5 ¤
ff0bbe ¤   *outFilter = newFilter;
49ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
495ea8 ¤   return err;
f1efe6 }
a0af5a
61af5a
18c744 ¤   PGPError
8e0796 PGPNewKeyEncryptAlgorithmFilter(
3840e0 ¤   PGPContextRef¤  ¤   ¤   context,·
922bdd ¤   PGPPublicKeyAlgorithm¤  encryptAlgorithm,·
ab4dcb ¤   PGPFilterRef *¤ ¤   ¤   outFilter)
1cbb36 {
b79372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
bfaf5a
3fc263 ¤   PGPValidatePtr( outFilter );
f001da ¤   *outFilter¤ = NULL;
b3f3ca ¤   PGPValidateContext( context );
413ab6 ¤   PGPValidateParam( encryptAlgorithm >= kPGPPublicKeyAlgorithm_First &&
4e54b6 ¤   ¤   encryptAlgorithm <= kPGPPublicKeyAlgorithm_Last¤);
7967c5 ¤
e0d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
c1eaf4 ¤   ¤   ¤   kPGPFilterTypeKeyEncryptAlgorithm, ·kPGPMatchDefault, outFilter);
cfb1f0 ¤   if( IsntPGPError( err ) )
1ac7a1 ¤   {
--5c5f 0000fb533ae4010022c Page 7 of pgpKeyFilter.c
04602c ¤   ¤   (*outFilter)->value.keyEncryptAlgorithm¤= encryptAlgorithm;
679371 ¤   }
6767c5 ¤
bcad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
be5ea8 ¤   return err;
f5efe6 }
4faf5a
91af5a
b90335 /*____________________________________________________________________________
9ff7f7 ____________________________________________________________________________*/
59c744 ¤   PGPError
ee82c0 PGPNewKeyFingerPrintFilter(
d25a0a ¤   PGPContextRef¤  ¤   context,·
9773c2 ¤   void const *¤   ¤   fingerPrint, ·
931a9d ¤   PGPSize¤¤   ¤   ¤   fingerPrintLength,·
42e861 ¤   PGPFilterRef *¤ ¤   outFilter)
a4bb36 {
f21310 ¤   PGPFilterRef¤   newFilter¤  = NULL;
dc3ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
39af5a
4ec263 ¤   PGPValidatePtr( outFilter );
f8b9b1 ¤   *outFilter = NULL;
1af3ca ¤   PGPValidateContext( context );
89f618 ¤   PGPValidatePtr( fingerPrint );
720a4e ¤   PGPValidateParam( fingerPrintLength >= 1 );
0967c5 ¤
4bd2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
2c491c ¤   ¤   ¤   kPGPFilterTypeKeyFingerPrint, ·kPGPMatchDefault, &newFilter);
f1b1f0 ¤   if( IsntPGPError( err ) )
31c7a1 ¤   {
13b4a8 ¤   ¤   PGPByte *¤  ¤   value¤  ¤   = NULL;
bb67c5 ¤
b8212e ¤   ¤   value =( PGPByte *)
d757ca ¤   ¤   ¤   pgpContextMemAlloc( context, fingerPrintLength, 0);
0c7885 ¤   ¤   if( IsntNull( value ) )·
d55b34 ¤   ¤   {
fad211 ¤   ¤   ¤   pgpCopyMemory( fingerPrint, value, fingerPrintLength);
d91bc3 ¤   ¤   ¤   newFilter->value.keyFingerPrint.keyFingerPrintData¤ ¤   = value;
302b57 ¤   ¤   ¤   newFilter->value.keyFingerPrint.keyFingerPrintLength¤   =
8d80b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   fingerPrintLength;
c50fe4 ¤   ¤   }
d20e1d ¤   ¤   else
ce5b34 ¤   ¤   {
3c124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
52abb9 ¤   ¤   ¤   PGPFreeFilter( newFilter );
fbfceb ¤   ¤   ¤   newFilter¤  = NULL;
2e0fe4 ¤   ¤   }
599371 ¤   }
df67c5 ¤
3b67c5 ¤
1c0bbe ¤   *outFilter = newFilter;
7aad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
695ea8 ¤   return err;
a9efe6 }
2aaf5a
03af5a
c3c744 ¤   PGPError
d94237 PGPNewKeyCreationTimeFilter(
0ca1bc ¤   PGPContextRef¤  ¤   context,
d1bc0b ¤   PGPTime¤¤   ¤   ¤   creationTime,·
bf4560 ¤   PGPMatchCriterion¤  match,
0fe861 ¤   PGPFilterRef *¤ ¤   outFilter)
60bb36 {
6f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b4af5a
7fc263 ¤   PGPValidatePtr( outFilter );
7101da ¤   *outFilter¤ = NULL;
b6f3ca ¤   PGPValidateContext( context );
a9475f ¤   PGPValidateMatchCriterion( match );
e567c5 ¤
b9d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
0feb78 ¤   ¤   ¤   kPGPFilterTypeKeyCreationTime, match, outFilter);
--a108 0006fcfbfe84010022c Page 8 of pgpKeyFilter.c
54b1f0 ¤   if( IsntPGPError( err ) )
f1c7a1 ¤   {
1d01a6 ¤   ¤   (*outFilter)->value.keyCreationTime = creationTime;
259371 ¤   }
de67c5 ¤
a8ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
025ea8 ¤   return err;
64efe6 }
edaf5a
94af5a
0bc744 ¤   PGPError
000581 PGPNewKeyExpirationTimeFilter(
55a1bc ¤   PGPContextRef¤  ¤   context,
a5ef78 ¤   PGPTime¤¤   ¤   ¤   expirationTime,·
b14560 ¤   PGPMatchCriterion¤  match,
9be861 ¤   PGPFilterRef *¤ ¤   outFilter)
cabb36 {
059372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
58af5a
67c263 ¤   PGPValidatePtr( outFilter );
f6b9b1 ¤   *outFilter = NULL;
3df3ca ¤   PGPValidateContext( context );
1e475f ¤   PGPValidateMatchCriterion( match );
8067c5 ¤
8ed2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
8ac589 ¤   ¤   ¤   kPGPFilterTypeKeyExpirationTime, match, outFilter);
77da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
b2b1f0 ¤   if( IsntPGPError( err ) )
7bc7a1 ¤   {
98438b ¤   ¤   (*outFilter)->value.keyExpirationTime¤  = expirationTime;
e69371 ¤   }
d967c5 ¤
bdad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
445ea8 ¤   return err;
58efe6 }
9aaf5a
18af5a
6fc744 ¤   PGPError
e4d3bf PGPNewKeyRevokedFilter(
9b5a0a ¤   PGPContextRef¤  ¤   context,·
9d2af8 ¤   PGPBoolean¤ ¤   ¤   revoked,·
60e861 ¤   PGPFilterRef *¤ ¤   outFilter)
eebb36 {
169372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
03af5a
47c263 ¤   PGPValidatePtr( outFilter );
9501da ¤   *outFilter¤ = NULL;
c8f3ca ¤   PGPValidateContext( context );
2967c5 ¤
fcd2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
0f8047 ¤   ¤   ¤   kPGPFilterTypeKeyRevoked, kPGPMatchDefault, outFilter);
7bb1f0 ¤   if( IsntPGPError( err ) )
9ac7a1 ¤   {
390915 ¤   ¤   (*outFilter)->value.keyRevoked = revoked;
759371 ¤   }
2a67c5 ¤
33ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
6e5ea8 ¤   return err;
bfefe6 }
73af5a
b3c744 ¤   PGPError
23c2c1 PGPNewKeyDisabledFilter(
285a0a ¤   PGPContextRef¤  ¤   context,·
a17d8d ¤   PGPBoolean¤ ¤   ¤   disabled,·
89e861 ¤   PGPFilterRef *¤ ¤   outFilter)
efbb36 {
e89372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
8daf5a
92c263 ¤   PGPValidatePtr( outFilter );
e101da ¤   *outFilter¤ = NULL;
a2f3ca ¤   PGPValidateContext( context );
6f67c5 ¤
--608f 00048a19c364010022c Page 9 of pgpKeyFilter.c
6dd2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
71b336 ¤   ¤   ¤   kPGPFilterTypeKeyDisabled, kPGPMatchDefault, outFilter);
a8b1f0 ¤   if( IsntPGPError( err ) )
d7c7a1 ¤   {
607440 ¤   ¤   (*outFilter)->value.keyDisabled = disabled;
859371 ¤   }
f367c5 ¤
bdad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
975ea8 ¤   return err;
7defe6 }
0faf5a
30af5a
39c744 ¤   PGPError
c9a47a PGPNewKeySigAlgorithmFilter(
309a06 ¤   PGPContextRef¤  ¤   ¤   context,
b7e131 ¤   PGPPublicKeyAlgorithm¤  sigAlgorithm,·
c24dcb ¤   PGPFilterRef *¤ ¤   ¤   outFilter)
d5bb36 {
3b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
4faf5a
0ac263 ¤   PGPValidatePtr( outFilter );
7f01da ¤   *outFilter¤ = NULL;
21f3ca ¤   PGPValidateContext( context );
31c3e1 ¤   PGPValidateParam( sigAlgorithm >= kPGPPublicKeyAlgorithm_First &&
9700f1 ¤   ¤   sigAlgorithm <= kPGPPublicKeyAlgorithm_Last¤);
4f67c5 ¤
46d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
ea75ca ¤   ¤   ¤   kPGPFilterTypeKeySigAlgorithm, kPGPMatchDefault, outFilter);
76b1f0 ¤   if( IsntPGPError( err ) )
d5c7a1 ¤   {
3756bf ¤   ¤   (*outFilter)->value.keySigAlgorithm = sigAlgorithm;
209371 ¤   }
f167c5 ¤
b4ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
a85ea8 ¤   return err;
78efe6 }
13af5a
26af5a
80c744 ¤   PGPError
3fa88c PGPNewKeyEncryptKeySizeFilter(
e8a1bc ¤   PGPContextRef¤  ¤   context,
549e0d ¤   PGPUInt32¤  ¤   ¤   keySize,·
3e4560 ¤   PGPMatchCriterion¤  match,
70e861 ¤   PGPFilterRef *¤ ¤   outFilter)
1ebb36 {
879372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
91af5a
9bc263 ¤   PGPValidatePtr( outFilter );
eb01da ¤   *outFilter¤ = NULL;
27f3ca ¤   PGPValidateContext( context );
d2475f ¤   PGPValidateMatchCriterion( match );
2167c5 ¤
51d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
d7f447 ¤   ¤   ¤   kPGPFilterTypeKeyEncryptKeySize, match, outFilter);
13b1f0 ¤   if( IsntPGPError( err ) )
36c7a1 ¤   {
9dba0a ¤   ¤   (*outFilter)->value.keyEncryptKeySize = keySize;
809371 ¤   }
3b67c5 ¤
1bad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
d25ea8 ¤   return err;
76efe6 }
30af5a
05af5a
86c744 ¤   PGPError
e5e35c PGPNewKeySigKeySizeFilter(
7da1bc ¤   PGPContextRef¤  ¤   context,
7f9e0d ¤   PGPUInt32¤  ¤   ¤   keySize,·
dd4560 ¤   PGPMatchCriterion¤  match,
61e861 ¤   PGPFilterRef *¤ ¤   outFilter)
61bb36 {
489372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
--b77c 0004890ae844010022c Page 10 of pgpKeyFilter.c
e0af5a
14c263 ¤   PGPValidatePtr( outFilter );
7bb9b1 ¤   *outFilter = NULL;
1df3ca ¤   PGPValidateContext( context );
6e475f ¤   PGPValidateMatchCriterion( match );
6b67c5 ¤
f3d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
a5d061 ¤   ¤   ¤   kPGPFilterTypeKeySigKeySize, match, outFilter);
36b1f0 ¤   if( IsntPGPError( err ) )
24c7a1 ¤   {
9de4ee ¤   ¤   (*outFilter)->value.keySigKeySize = keySize;
c09371 ¤   }
3667c5 ¤
54ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
505ea8 ¤   return err;
96efe6 }
b3af5a
3daf5a
85af5a
55af5a
4cc744 ¤   PGPError
9fcb09 PGPNewUserIDStringFilter(
80a1bc ¤   PGPContextRef¤  ¤   context,
df43a6 ¤   char const *¤   ¤   userIDString,·
7f4560 ¤   PGPMatchCriterion¤  match,
34e861 ¤   PGPFilterRef *¤ ¤   outFilter)
bfbb36 {
457892 ¤   PGPFilterRef¤   newFilter;
e69372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
abaf5a
b1c263 ¤   PGPValidatePtr( outFilter );
0fb9b1 ¤   *outFilter = NULL;
04f3ca ¤   PGPValidateContext( context );
1f475f ¤   PGPValidateMatchCriterion( match );
1567c5 ¤
77302f ¤   err = sAllocateFilter( context, ·kPGPFilterClassDefault,
04b8b4 ¤   ¤   ¤   /*¤ kPGPFilterClassKey | kPGPFilterClassDefault, */
2f911b ¤   ¤   ¤   kPGPFilterTypeUserIDString, match, &newFilter);
61b1f0 ¤   if( IsntPGPError( err ) )
a8c7a1 ¤   {
767bca ¤   ¤   char *¤ ¤   ¤   value;
671b52 ¤   ¤
1ceb18 ¤   ¤   value = (char *)pgpContextMemAlloc( context,
37391c ¤   ¤   ¤   ¤   ¤   ¤   strlen( userIDString ) + 1, ·0);
ee2bfc ¤   ¤   if( IsntNull( value ))·
ed5b34 ¤   ¤   {
eba92b ¤   ¤   ¤   newFilter->value.userIDString = value;
cead89 ¤   ¤   ¤   strcpy( value, userIDString);
bd0fe4 ¤   ¤   }
a10e1d ¤   ¤   else
485b34 ¤   ¤   {
f4abb9 ¤   ¤   ¤   PGPFreeFilter( newFilter );
04fceb ¤   ¤   ¤   newFilter¤  = NULL;
c8124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
c50fe4 ¤   ¤   }
239371 ¤   }
c367c5 ¤
fd0bbe ¤   *outFilter = newFilter;
dbad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
d35ea8 ¤   return err;
79efe6 }
ceaf5a
00c744 ¤   PGPError
4de986 PGPNewUserIDEmailFilter(
dba1bc ¤   PGPContextRef¤  ¤   context,
5818dc ¤   char const *¤   ¤   eMail,·
0d4560 ¤   PGPMatchCriterion¤  match,
91e861 ¤   PGPFilterRef *¤ ¤   outFilter)
c3bb36 {
c27892 ¤   PGPFilterRef¤   newFilter;
229372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
48af5a
--1ccd 0002bde39ce4010022c Page 11 of pgpKeyFilter.c
a2c263 ¤   PGPValidatePtr( outFilter );
8fb9b1 ¤   *outFilter = NULL;
bdf3ca ¤   PGPValidateContext( context );
c9475f ¤   PGPValidateMatchCriterion( match );
f967c5 ¤
c7d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
d194f2 ¤   ¤   ¤   kPGPFilterTypeUserIDEmail, match, &newFilter);
53b1f0 ¤   if( IsntPGPError( err ) )
32c7a1 ¤   {
b57bca ¤   ¤   char *¤ ¤   ¤   value;
ecaf5a
43fa22 ¤   ¤   value = (char *)pgpContextMemAlloc( context, strlen( eMail ) + 1, 0);
9434af ¤   ¤   if( IsntNull( value ) )
5d5b34 ¤   ¤   {
71759d ¤   ¤   ¤   strcpy( value, eMail);
84bbf4 ¤   ¤   ¤   newFilter->value.userIDEmail = value;
db0fe4 ¤   ¤   }
e80e1d ¤   ¤   else
c55b34 ¤   ¤   {
2eabb9 ¤   ¤   ¤   PGPFreeFilter( newFilter );
20fceb ¤   ¤   ¤   newFilter¤  = NULL;
3e124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
800fe4 ¤   ¤   }
459371 ¤   }
2967c5 ¤
c30bbe ¤   *outFilter = newFilter;
f8ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
d85ea8 ¤   return err;
bbefe6 }
fcaf5a
37af5a
15c744 ¤   PGPError
68e4cd PGPNewUserIDNameFilter(
51a1bc ¤   PGPContextRef¤  ¤   context,
21aa6d ¤   char const *¤   ¤   name,·
324560 ¤   PGPMatchCriterion¤  match,
2ae861 ¤   PGPFilterRef *¤ ¤   outFilter)
84bb36 {
647892 ¤   PGPFilterRef¤   newFilter;
309372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b46fe2 ¤   char *¤ ¤   ¤   value;
7faf5a
59c263 ¤   PGPValidatePtr( outFilter );
2bb9b1 ¤   *outFilter = NULL;
07f3ca ¤   PGPValidateContext( context );
75475f ¤   PGPValidateMatchCriterion( match );
9867c5 ¤
59d2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
3c9e66 ¤   ¤   ¤   kPGPFilterTypeUserIDName, match, &newFilter);
fbb1f0 ¤   if( IsntPGPError( err ) )
95c7a1 ¤   {
778708 ¤   ¤   value = (char *)pgpContextMemAlloc( context, strlen( name) + 1, 0);
b67885 ¤   ¤   if( IsntNull( value ) )·
6f5b34 ¤   ¤   {
3fb1ee ¤   ¤   ¤   strcpy( value, name);
b7e25a ¤   ¤   ¤   newFilter->value.userIDName¤= value;
b70fe4 ¤   ¤   }
7e0e1d ¤   ¤   else
6e5b34 ¤   ¤   {
20abb9 ¤   ¤   ¤   PGPFreeFilter( newFilter );
d2fceb ¤   ¤   ¤   newFilter¤  = NULL;
06124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
fb0fe4 ¤   ¤   }
119371 ¤   }
8967c5 ¤
0069a5 ¤   *outFilter¤ = newFilter;
efad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
335ea8 ¤   return err;
52efe6 }
4baf5a
91af5a
2bc744 ¤   PGPError
--1634 000980445844010022c Page 12 of pgpKeyFilter.c
63fabd PGPNewSigKeyIDFilter(
4ba1bc ¤   PGPContextRef¤  ¤   context,
a1f3c6 ¤   PGPKeyID const *¤   keyID, ·
6ae861 ¤   PGPFilterRef *¤ ¤   outFilter)
2abb36 {
b37892 ¤   PGPFilterRef¤   newFilter;
609372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
62af5a
89c263 ¤   PGPValidatePtr( outFilter );
6db9b1 ¤   *outFilter = NULL;
41f3ca ¤   PGPValidateContext( context );
1f67c5 ¤
1ed2fe ¤   err = sAllocateFilter( context, kPGPFilterClassDefault,
a23b13 ¤   ¤   ¤   kPGPFilterTypeSigKeyID, kPGPMatchDefault, &newFilter);
2cf1e7 ¤   if ( IsntPGPError( err ) )
59c7a1 ¤   {
6e3518 ¤   ¤   newFilter->value.sigKeyID¤  = *keyID;
e19371 ¤   }
b267c5 ¤
310bbe ¤   *outFilter = newFilter;
bfad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
885ea8 ¤   return err;
adefe6 }
43af5a
58745a #if NOT_YET¤¤   /* [ */
cfaf5a
5d38e5 /*
66a420 ·* Create a filtered KeySet based on the same KeyDB as the specified
cffff4 ·* original. ·The original must be unfiltered. ·The filtering type
afd7d9 ·* is chosen automatically based on the string.
de775e ·*
447eab ·* Currently, a "0x" prefix looks up by keyID, otherwise
ec9570 ·* by userid name substring matching.
a1495d ·*/
5321ab ¤   PGPError·
952d4f PGPNewKeyFilterFromStringQuery(
f9a1bc ¤   PGPContextRef¤  ¤   context,
08dd47 ¤   char const *¤   ¤   query,
c8e861 ¤   PGPFilterRef *¤ ¤   outFilter)
28bb36 {
2a9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
93597b ¤   PGPFilterRef¤   filter = kInvalidPGPKeySetRef;
a3af5a
3ac263 ¤   PGPValidatePtr( outFilter );
f892b2 ¤   PGPValidatePtr( query );
a101da ¤   *outFilter¤ = NULL;
38f3ca ¤   PGPValidateContext( context );
fb67c5 ¤
a04c69 not yet
5faf5a
c7c038 ¤   if (query[0] == '0' && query[1] == 'x')
d8c7a1 ¤   {
eb3cf5 ¤   ¤   PGPKeyIDRef¤¤   keyID;
20af5a
21882d ¤   ¤   err = PGPNewKeyIDFromString( context, query, &keyID );
0e7d98 ¤   ¤   if ( IsntPGPError( err ) )
8b5b34 ¤   ¤   {
9165f8 ¤   ¤   ¤   err = PGPNewKeyIDFilter( context, keyID, &filter );
26d38a ¤   ¤   ¤   PGPFreeKeyID( keyID );
6a0fe4 ¤   ¤   }
5a9371 ¤   }
820e24 ¤   else
eec7a1 ¤   {
077f36 ¤   ¤   err = PGPNewUserIDStringFilter( context, query,
27566a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMatchSubString,
c30e6d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter );
d29371 ¤   }
a4af5a
4684d1 ¤   *outFilter¤ = filter;
74ad82 ¤   pgpAssertErrWithPtr( err, *outFilter );
b35ea8 ¤   return err;
98efe6 }
--aaf2 0001292d36b4010022c Page 13 of pgpKeyFilter.c
e0af5a
6f4afc #endif¤ /* ] NOT_YET */
b6af5a
a46c2c ¤   static PGPBoolean
a8ca8b sComparisonMatchesCriterion(
9d59d4 ¤   long¤   ¤   ¤   ¤   comparison,
9d0b6e ¤   PGPMatchCriterion¤  criterion )
bebb36 {
fda32f ¤   switch (criterion)
c2c7a1 ¤   {
2feb9e ¤   ¤   case kPGPMatchLessOrEqual:
5be991 ¤   ¤   ¤   return comparison <= 0;
4fdfdb ¤   ¤   case kPGPMatchGreaterOrEqual:
ebe1c7 ¤   ¤   ¤   return comparison >= 0;
56ed1f ¤   ¤   case kPGPMatchEqual:
5cedba ¤   ¤   ¤   return comparison == 0;
ea9ae3 ¤   ¤   default:
3ab783 ¤   ¤   ¤   pgpAssert(0);
f5cdcb ¤   ¤   ¤   break;
179371 ¤   }
d4a230 ¤   return FALSE;
0befe6 }
85af5a
3616ea ¤   PGPBoolean
4f5ed3 pgpKeyObjMatchesFilter(
b839e0 ¤   PGPFilterRef¤   ¤   filter,
00ae29 ¤   RingSet const *¤¤   ringSet,
9fcda7 ¤   RingObject *¤   ¤   keyObj)
5fbb36 {
a4804d ¤   PGPContextRef¤  ¤   context = NULL;
56814d ¤   long¤   ¤   ¤   ¤   comparison;
b93111 ¤   PGPBoolean¤ ¤   ¤   result = FALSE;
8d5197 ¤   PGPByte¤¤   ¤   ¤   pkAlg;
9baf5a
a04b40 ¤   if ( ! PGPFilterIsValid( filter ) )
85e20d ¤   ¤   return( FALSE );
60b6b1 ¤   context = filter->context;
5bd1d8 ¤   if ( ! pgpContextIsValid( context ) )
a3e20d ¤   ¤   return( FALSE );
b9af5a
5a3a5c ¤   pgpAssert(ringSet != NULL);
7f880d ¤   switch(filter->filterType)·
11c7a1 ¤   {
f5a537 ¤   ¤   case kPGPFilterTypeKeyKeyID:
9b5b34 ¤   ¤   {
e1a48c ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   keyID;
f967c5 ¤
67b048 ¤   ¤   ¤   ringKeyID8(ringSet, keyObj, &pkAlg, &keyID);
7faf5a
e7af3a ¤   ¤   ¤   result¤ = pgpKeyIDsEqual( &keyID, &filter->value.keyKeyID );
96cdcb ¤   ¤   ¤   break;
a30fe4 ¤   ¤   }
8caf5a
7abe91 ¤   ¤   case kPGPFilterTypeKeyFingerPrint:
955b34 ¤   ¤   {
29e9ad ¤   ¤   ¤   PGPSize¤¤   length;
ec9903 ¤   ¤   ¤   PGPByte¤¤   buffer[32];
97af5a
8e5c18 ¤   ¤   ¤   if (ringKeyV3(ringSet, keyObj))
b4f776 ¤   ¤   ¤   {
8ce4ae ¤   ¤   ¤   ¤   ringKeyFingerprint16(ringSet, keyObj, buffer);
931cc4 ¤   ¤   ¤   ¤   length = 16;
61a3a6 ¤   ¤   ¤   }
3fbb8c ¤   ¤   ¤   else
bff776 ¤   ¤   ¤   {
b5538a ¤   ¤   ¤   ¤   ringKeyFingerprint20(ringSet, keyObj, buffer);
79efd0 ¤   ¤   ¤   ¤   length = 20;
55a3a6 ¤   ¤   ¤   }
bea40f ¤   ¤   ¤   if (filter->value.keyFingerPrint.keyFingerPrintLength == length)
15f776 ¤   ¤   ¤   {
f4da0b ¤   ¤   ¤   ¤   result = !memcmp(buffer,
12bb29 ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.keyFingerPrint.keyFingerPrintData,
--f340 000ae2b02ec4010022c Page 14 of pgpKeyFilter.c
b87dea ¤   ¤   ¤   ¤   ¤   ¤   ¤   length);
a2a3a6 ¤   ¤   ¤   }
e7cdcb ¤   ¤   ¤   break;
170fe4 ¤   ¤   }
79af5a
8241fd ¤   ¤   /* Time filters, which utilize shared locals */
6e5b34 ¤   ¤   {
23f27f ¤   ¤   ¤   PGPTime¤¤   keyTime;
b56c6c ¤   ¤   ¤   PGPTime¤¤   filterTime;
1baf5a
52d15f ¤   ¤   case kPGPFilterTypeKeyCreationTime:
685248 ¤   ¤   ¤   keyTime = ringKeyCreation(ringSet, keyObj);
cc95e3 ¤   ¤   ¤   filterTime = filter->value.keyCreationTime;
10ce6a ¤   ¤   ¤   goto compareTimes;
36af5a
64b06f ¤   ¤   case kPGPFilterTypeKeyExpirationTime:
10aa95 ¤   ¤   ¤   keyTime = ringKeyExpiration(ringSet, keyObj);
4c22e2 ¤   ¤   ¤   filterTime = filter->value.keyExpirationTime;
72af5a
c2b33a ¤   ¤   ¤   /* FALL THROUGH */
ac6f48 ¤   ¤   compareTimes:
dabe0f ¤   ¤   ¤   if (keyTime == filterTime)
07e0b7 ¤   ¤   ¤   ¤   result = TRUE;¤ /* All match criteria include equality */
0c1893 ¤   ¤   ¤   else if (filter->match == kPGPMatchEqual)
753573 ¤   ¤   ¤   ¤   result = FALSE;
debb8c ¤   ¤   ¤   else
64f776 ¤   ¤   ¤   {
20980e ¤   ¤   ¤   ¤   /*
71c774 ¤   ¤   ¤   ¤   ·* Now we know that the two times are unequal,
f65c29 ¤   ¤   ¤   ¤   ·* and the match criterion is either <= or >=.
49427b ¤   ¤   ¤   ¤   ·* So we'll just evaluate <=, and then invert
31b4b3 ¤   ¤   ¤   ¤   ·* the result if the criterion was >=.
c51020 ¤   ¤   ¤   ¤   ·*/
09ce3e ¤   ¤   ¤   ¤   result = (keyTime <= filterTime);
d582a5 ¤   ¤   ¤   ¤   if (filter->filterType == kPGPFilterTypeKeyExpirationTime)
c172c3 ¤   ¤   ¤   ¤   {
c7014a ¤   ¤   ¤   ¤   ¤   if (filterTime == kPGPExpirationTime_Never)
7cddc8 ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
bea416 ¤   ¤   ¤   ¤   ¤   else if (keyTime == kPGPExpirationTime_Never)
197bda ¤   ¤   ¤   ¤   ¤   ¤   result = FALSE;
a12613 ¤   ¤   ¤   ¤   }
6daf5a
151209 ¤   ¤   ¤   ¤   if (filter->match == kPGPMatchGreaterOrEqual)
cc72c3 ¤   ¤   ¤   ¤   {
0650be ¤   ¤   ¤   ¤   ¤   result = !result;
602613 ¤   ¤   ¤   ¤   }
21fa07 ¤   ¤   ¤   ¤   else
d572c3 ¤   ¤   ¤   ¤   {
0ab29b ¤   ¤   ¤   ¤   ¤   pgpAssert(filter->match == kPGPMatchLessOrEqual);
4a2613 ¤   ¤   ¤   ¤   }
fea3a6 ¤   ¤   ¤   }
15cdcb ¤   ¤   ¤   break;
120fe4 ¤   ¤   }
afaf5a
a5dc9c ¤   ¤   case kPGPFilterTypeKeyRevoked:
e6b87b ¤   ¤   ¤   result = ((!filter->value.keyRevoked)
784eb7 ¤   ¤   ¤   ¤   ¤   ··== (!ringKeyRevoked(ringSet, keyObj)));
72cdcb ¤   ¤   ¤   break;
a4d77a ¤   ¤   case kPGPFilterTypeKeyDisabled:
e691a7 ¤   ¤   ¤   result = ((!filter->value.keyDisabled)
a87a68 ¤   ¤   ¤   ¤   ¤   ··== (!ringKeyDisabled(ringSet, keyObj)));
20cdcb ¤   ¤   ¤   break;
d6af5a
29a76d ¤   ¤   case kPGPFilterTypeKeyEncryptAlgorithm:
d85b34 ¤   ¤   {
d143aa ¤   ¤   ¤   RingIterator *¤ ringIter;
2ba7a2 ¤   ¤   ¤   RingObject *¤   subKeyObj;
50af5a
127384 ¤   ¤   ¤   ringKeyID8(ringSet, keyObj, &pkAlg, NULL);
bb66ae ¤   ¤   ¤   if (pkAlg == kPGPPublicKeyAlgorithm_RSA)
ecf776 ¤   ¤   ¤   {
aee3c3 ¤   ¤   ¤   ¤   result = (pkAlg == filter->value.keyEncryptAlgorithm);
--5ef9 000e8f6cd014010022c Page 15 of pgpKeyFilter.c
cfa3a6 ¤   ¤   ¤   }
41bb8c ¤   ¤   ¤   else
e6f776 ¤   ¤   ¤   {
de2e68 ¤   ¤   ¤   ¤   ringIter = ringIterCreate(ringSet);
a71196 ¤   ¤   ¤   ¤   if (ringIter != NULL)
1b72c3 ¤   ¤   ¤   ¤   {
3e960a ¤   ¤   ¤   ¤   ¤   ringIterSeekTo(ringIter, keyObj);
fea4e9 ¤   ¤   ¤   ¤   ¤   while (ringIterNextObject(ringIter, 2) == 2)
344859 ¤   ¤   ¤   ¤   ¤   {
1cc626 ¤   ¤   ¤   ¤   ¤   ¤   subKeyObj = ringIterCurrentObject(ringIter, 2);
3d047b ¤   ¤   ¤   ¤   ¤   ¤   if (ringObjectType(subKeyObj) == RINGTYPE_KEY)
9e8fec ¤   ¤   ¤   ¤   ¤   ¤   {
1e2c44 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringKeyID8(ringSet, subKeyObj, &pkAlg, NULL);
3bcd92 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (pkAlg == filter->value.keyEncryptAlgorithm)
8406b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
d1421c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
9ccd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
845268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
75db3c ¤   ¤   ¤   ¤   ¤   ¤   }
ae1c89 ¤   ¤   ¤   ¤   ¤   }
10dc23 ¤   ¤   ¤   ¤   ¤   ringIterDestroy(ringIter);
da2613 ¤   ¤   ¤   ¤   }
86a3a6 ¤   ¤   ¤   }
4ecdcb ¤   ¤   ¤   break;
d60fe4 ¤   ¤   }
4c68a5 ¤   ¤   case kPGPFilterTypeKeySigAlgorithm:
227384 ¤   ¤   ¤   ringKeyID8(ringSet, keyObj, &pkAlg, NULL);
53f04f ¤   ¤   ¤   result = (pkAlg == filter->value.keyEncryptAlgorithm);
153ac9 ¤   ¤   ¤   result = ((!filter->value.keySigAlgorithm)
c34eb7 ¤   ¤   ¤   ¤   ¤   ··== (!ringKeyRevoked(ringSet, keyObj)));
74cdcb ¤   ¤   ¤   break;
33bbec ¤   ¤   case kPGPFilterTypeKeySubKeyID:
905b34 ¤   ¤   {
ab43aa ¤   ¤   ¤   RingIterator *¤ ringIter;
12a7a2 ¤   ¤   ¤   RingObject *¤   subKeyObj;
3eaf5a
66b829 ¤   ¤   ¤   ringIter = ringIterCreate(ringSet);
5efee5 ¤   ¤   ¤   if (ringIter != NULL)
9df776 ¤   ¤   ¤   {
2f380b ¤   ¤   ¤   ¤   ringIterSeekTo(ringIter, keyObj);
557ec0 ¤   ¤   ¤   ¤   while (ringIterNextObject(ringIter, 2) == 2)
4c72c3 ¤   ¤   ¤   ¤   {
e48851 ¤   ¤   ¤   ¤   ¤   subKeyObj = ringIterCurrentObject(ringIter, 2);
cc17f7 ¤   ¤   ¤   ¤   ¤   if (ringObjectType(subKeyObj) == RINGTYPE_KEY)
2b4859 ¤   ¤   ¤   ¤   ¤   {
207abf ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
9b94aa ¤   ¤   ¤   ¤   ¤   ¤
76ae14 ¤   ¤   ¤   ¤   ¤   ¤   ringKeyID8(ringSet, subKeyObj, NULL, &keyID);
bd9456 ¤   ¤   ¤   ¤   ¤   ¤   if ( pgpKeyIDsEqual( &keyID,
361e54 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter->value.keySubKeyID ) )
158fec ¤   ¤   ¤   ¤   ¤   ¤   {
f0d384 ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
268c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
2fdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
dc1c89 ¤   ¤   ¤   ¤   ¤   }
e62613 ¤   ¤   ¤   ¤   }
514dbb ¤   ¤   ¤   ¤   ringIterDestroy(ringIter);
e0a3a6 ¤   ¤   ¤   }
c6cdcb ¤   ¤   ¤   break;
380fe4 ¤   ¤   }
643516 ¤   ¤   case kPGPFilterTypeSigKeyID:
e85b34 ¤   ¤   {
4143aa ¤   ¤   ¤   RingIterator *¤ ringIter;
4f687c ¤   ¤   ¤   RingObject *¤   sigObj;
e4af5a
d6b829 ¤   ¤   ¤   ringIter = ringIterCreate(ringSet);
0bfee5 ¤   ¤   ¤   if (ringIter != NULL)
5ef776 ¤   ¤   ¤   {
00380b ¤   ¤   ¤   ¤   ringIterSeekTo(ringIter, keyObj);
d3eec6 ¤   ¤   ¤   ¤   while (!result && ringIterNextObject(ringIter, 2) == 2)
ab72c3 ¤   ¤   ¤   ¤   {
e8b3c8 ¤   ¤   ¤   ¤   ¤   while (ringIterNextObject(ringIter, 3) == 3)
--eeb4 0004c1812734010022c Page 16 of pgpKeyFilter.c
e04859 ¤   ¤   ¤   ¤   ¤   {
a342f0 ¤   ¤   ¤   ¤   ¤   ¤   sigObj = ringIterCurrentObject(ringIter, 3);
880bed ¤   ¤   ¤   ¤   ¤   ¤   if (ringObjectType(sigObj) == RINGTYPE_SIG)
fb8fec ¤   ¤   ¤   ¤   ¤   ¤   {
9aeb27 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
d494aa ¤   ¤   ¤   ¤   ¤   ¤
27fb28 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSigID8(ringSet, sigObj, NULL, &keyID);
f0fb65 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if ( pgpKeyIDsEqual( &keyID,
168a86 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter->value.sigKeyID ))
5706b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
3e421c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
accd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
a55268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
a6db3c ¤   ¤   ¤   ¤   ¤   ¤   }
001c89 ¤   ¤   ¤   ¤   ¤   }
802613 ¤   ¤   ¤   ¤   }
564dbb ¤   ¤   ¤   ¤   ringIterDestroy(ringIter);
96a3a6 ¤   ¤   ¤   }
d0cdcb ¤   ¤   ¤   break;
5e0fe4 ¤   ¤   }
8d9f86 ¤   ¤   case kPGPFilterTypeKeyEncryptKeySize:
055b34 ¤   ¤   {
a943aa ¤   ¤   ¤   RingIterator *¤ ringIter;
c2a7a2 ¤   ¤   ¤   RingObject *¤   subKeyObj;
46af5a
1a7384 ¤   ¤   ¤   ringKeyID8(ringSet, keyObj, &pkAlg, NULL);
d266ae ¤   ¤   ¤   if (pkAlg == kPGPPublicKeyAlgorithm_RSA)
71f776 ¤   ¤   ¤   {
306a10 ¤   ¤   ¤   ¤   comparison = (ringKeyBits(ringSet, keyObj)
506e22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··- filter->value.keyEncryptKeySize);
0ce81f ¤   ¤   ¤   ¤   result = sComparisonMatchesCriterion(comparison,
d79fa9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·filter->match);
88a3a6 ¤   ¤   ¤   }
42bb8c ¤   ¤   ¤   else
2af776 ¤   ¤   ¤   {
362e68 ¤   ¤   ¤   ¤   ringIter = ringIterCreate(ringSet);
8e1196 ¤   ¤   ¤   ¤   if (ringIter != NULL)
bc72c3 ¤   ¤   ¤   ¤   {
65960a ¤   ¤   ¤   ¤   ¤   ringIterSeekTo(ringIter, keyObj);
c2a4e9 ¤   ¤   ¤   ¤   ¤   while (ringIterNextObject(ringIter, 2) == 2)
1d4859 ¤   ¤   ¤   ¤   ¤   {
edc626 ¤   ¤   ¤   ¤   ¤   ¤   subKeyObj = ringIterCurrentObject(ringIter, 2);
85047b ¤   ¤   ¤   ¤   ¤   ¤   if (ringObjectType(subKeyObj) == RINGTYPE_KEY)
968fec ¤   ¤   ¤   ¤   ¤   ¤   {
2fbf82 ¤   ¤   ¤   ¤   ¤   ¤   ¤   comparison = (ringKeyBits(ringSet, subKeyObj)
9b59b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   - filter->value.keyEncryptKeySize);
8b93a7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (sComparisonMatchesCriterion(comparison,
65c61b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->match))
d606b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
91421c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
d7cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
105268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
9bdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
5b1c89 ¤   ¤   ¤   ¤   ¤   }
21dc23 ¤   ¤   ¤   ¤   ¤   ringIterDestroy(ringIter);
842613 ¤   ¤   ¤   ¤   }
1ea3a6 ¤   ¤   ¤   }
7bcdcb ¤   ¤   ¤   break;
320fe4 ¤   ¤   }
888e8e ¤   ¤   case kPGPFilterTypeKeySigKeySize:
1f6d2b ¤   ¤   ¤   comparison = (ringKeyBits(ringSet, keyObj)
36dbcc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··- filter->value.keySigKeySize);
84f0b8 ¤   ¤   ¤   result = sComparisonMatchesCriterion(comparison, filter->match);
92cdcb ¤   ¤   ¤   break;
82af5a
54026a ¤   ¤   /* UserID filters, which utilize shared locals */
495b34 ¤   ¤   {
6a43aa ¤   ¤   ¤   RingIterator *¤ ringIter;
bf0362 ¤   ¤   ¤   RingObject *¤   nameObj;
c03061 ¤   ¤   ¤   char const *¤   nameStr;
554f6d ¤   ¤   ¤   PGPSize¤¤   ¤   nameLength;
4c6ecd ¤   ¤   ¤   char *¤ ¤   ¤   string;
--c1c5 000b3f2d9514010022c Page 17 of pgpKeyFilter.c
73e02f ¤   ¤   ¤   PGPSize¤¤   ¤   stringLength;
2b9dcc ¤   ¤   ¤   char const *¤   p;
a6af5a
2930f7 ¤   ¤   case kPGPFilterTypeUserIDEmail:
b1eaa9 ¤   ¤   ¤   string = filter->value.userIDEmail;
b46453 ¤   ¤   ¤   stringLength = strlen(string);
142b2a ¤   ¤   ¤   goto stringFilter;
c6af5a
9ba20d ¤   ¤   case kPGPFilterTypeUserIDName:
8a1940 ¤   ¤   ¤   string = filter->value.userIDName;
4c6453 ¤   ¤   ¤   stringLength = strlen(string);
4b2b2a ¤   ¤   ¤   goto stringFilter;
4387c7 ¤   ¤   ¤
0723e6 ¤   ¤   case kPGPFilterTypeUserIDString:
4ed100 ¤   ¤   ¤   string = filter->value.userIDString;·
b86453 ¤   ¤   ¤   stringLength = strlen(string);
5caf5a
66b33a ¤   ¤   ¤   /* FALL THROUGH */
b18a08 ¤   ¤   stringFilter:
fbb829 ¤   ¤   ¤   ringIter = ringIterCreate(ringSet);
21fee5 ¤   ¤   ¤   if (ringIter != NULL)
4af776 ¤   ¤   ¤   {
cb380b ¤   ¤   ¤   ¤   ringIterSeekTo(ringIter, keyObj);
c77ec0 ¤   ¤   ¤   ¤   while (ringIterNextObject(ringIter, 2) == 2)
6272c3 ¤   ¤   ¤   ¤   {
cced65 ¤   ¤   ¤   ¤   ¤   nameObj = ringIterCurrentObject(ringIter, 2);
4f8b09 ¤   ¤   ¤   ¤   ¤   if (ringObjectType(nameObj) == RINGTYPE_NAME &&
73462b ¤   ¤   ¤   ¤   ¤   ¤   !ringNameIsAttribute(ringSet, nameObj))
f04859 ¤   ¤   ¤   ¤   ¤   {
073b82 ¤   ¤   ¤   ¤   ¤   ¤   nameStr = ringNameName(ringSet, nameObj, &nameLength);
c7d89a ¤   ¤   ¤   ¤   ¤   ¤   switch (filter->filterType)
3b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
7bec7b ¤   ¤   ¤   ¤   ¤   ¤   ¤   case kPGPFilterTypeUserIDEmail:
a2185c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   p = (char *)memchr(nameStr, '<', nameLength);
581c1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (p == NULL)
3f31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
d25525 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameLength = 0;
97c32b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
b86560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
9626f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   p++;
29f708 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameLength -= (p - nameStr);
9bba25 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameStr = p;
f73842 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   p = (char *)memchr(nameStr, '>', nameLength);
37a3a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (p != NULL)
5f4749 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameLength = p - nameStr;
d7cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
5df377 ¤   ¤   ¤   ¤   ¤   ¤   ¤   case kPGPFilterTypeUserIDName:
6d185c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   p = (char *)memchr(nameStr, '<', nameLength);
d21c1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (p == NULL)
6ac32b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
9eafbf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   while (p > nameStr && p[-1] == ' ')
90be5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   p--;
12a549 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameLength = p - nameStr;
5ecd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
2a6d5e ¤   ¤   ¤   ¤   ¤   ¤   ¤   case kPGPFilterTypeUserIDString:
95cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
02d8da ¤   ¤   ¤   ¤   ¤   ¤   ¤   default:
fd37af ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* This should never happen */
21e387 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpAssert(0);
fbcd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
47db3c ¤   ¤   ¤   ¤   ¤   ¤   }
04d14d ¤   ¤   ¤   ¤   ¤   ¤   if (filter->match == kPGPMatchEqual)
e58fec ¤   ¤   ¤   ¤   ¤   ¤   {
961694 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (nameLength == stringLength &&
b1da7e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   xmemimem(nameStr, nameLength,
985b8e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   string, stringLength) != NULL)
f706b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
85421c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
d5cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
c75268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
76db3c ¤   ¤   ¤   ¤   ¤   ¤   }
b358d1 ¤   ¤   ¤   ¤   ¤   ¤   else if (filter->match == kPGPMatchSubString)
--9046 00016085e334010022c Page 18 of pgpKeyFilter.c
5b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
d4216c ¤   ¤   ¤   ¤   ¤   ¤   ¤   if (xmemimem(nameStr, nameLength,
b8bffb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·string, stringLength))
c506b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
81421c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = TRUE;
7dcd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
9c5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
3bdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
591c89 ¤   ¤   ¤   ¤   ¤   }
782613 ¤   ¤   ¤   ¤   }
9f4dbb ¤   ¤   ¤   ¤   ringIterDestroy(ringIter);
16a3a6 ¤   ¤   ¤   }
77cdcb ¤   ¤   ¤   break;
280fe4 ¤   ¤   }
8baf5a
025563 ¤   ¤   /* Compound filters */
3d6415 ¤   ¤   case kPGPFilterTypeNot:
072e39 ¤   ¤   ¤   result = !pgpKeyObjMatchesFilter(filter->value.notFilter,
7cc0cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·ringSet, keyObj);
1ecdcb ¤   ¤   ¤   break;
9d97c7 ¤   ¤   case kPGPFilterTypeAnd:
2235e6 ¤   ¤   ¤   result = pgpKeyObjMatchesFilter(filter->value.andFilter.andFilter1,
7e16b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSet, keyObj)
884415 ¤   ¤   ¤   ¤   ··&& pgpKeyObjMatchesFilter(filter->value.andFilter.andFilter2,
60a434 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSet, keyObj);
63cdcb ¤   ¤   ¤   break;
3ca0b9 ¤   ¤   case kPGPFilterTypeOr:
2202c6 ¤   ¤   ¤   result = pgpKeyObjMatchesFilter(filter->value.orFilter.orFilter1,
4116b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSet, keyObj)
678fbd ¤   ¤   ¤   ¤   ··|| pgpKeyObjMatchesFilter(filter->value.orFilter.orFilter2,
98a434 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSet, keyObj);
17cdcb ¤   ¤   ¤   break;
379ae3 ¤   ¤   default:
02a28f ¤   ¤   ¤   pgpAssertMsg(FALSE, "Unimplemented filter type");
fdcdcb ¤   ¤   ¤   break;
039371 ¤   }
c45d73 ¤   return result;
79efe6 }
06af5a
9f16ea ¤   PGPBoolean
c5d3f2 pgpKeyMatchesFilter(
6539e0 ¤   PGPFilterRef¤   ¤   filter,
8085c2 ¤   PGPKeyRef¤  ¤   ¤   key)
3cbb36 {
77a315 ¤   return pgpKeyObjMatchesFilter(filter, pgpKeyDBRingSet(key->keyDB),
81b720 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··key->key);
c9efe6 }
c7af5a
45f1ae static PGPError
1af3f6 pgpEncodeSearchTerms( PGPContextRef context,
f9b40b ¤   ¤   ¤   ¤   char *var,
fb3a78 ¤   ¤   ¤   ¤   char **newString )
1abb36 {
409b07 ¤   static char const badChars[] ··= "*()";
e0f637 ¤   char¤   ¤   *ptrBad;
2939e4 ¤   char¤   ¤   *ptrGood;
8cc137 ¤   PGPInt16¤   i;
3faf5a
bd5091 ¤   *newString = (char*) pgpContextMemAlloc( context,
3a8a0c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   2*strlen(var)+1,
8c1e0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
249be9 ¤   if ( *newString == NULL )
dfc7a1 ¤   {
7a4030 ¤   ¤   return kPGPError_OutOfMemory;
ac9371 ¤   }
8caf5a
98e342 ¤   ptrBad ·= var;
f15df7 ¤   ptrGood = *newString;
79af5a
65295e ¤   while ( *ptrBad != '\0' )·
63c7a1 ¤   {
16d830 ¤   ¤   for (i=0; badChars[i] != '\0'; i++ )
--c580 000c410edc64010022c Page 19 of pgpKeyFilter.c
e35b34 ¤   ¤   {
6cc2e8 ¤   ¤   ¤   if ( *ptrBad == badChars[i] )
76f776 ¤   ¤   ¤   {
711f77 ¤   ¤   ¤   ¤   *ptrGood++ = '\\';
d159cb ¤   ¤   ¤   ¤   *ptrGood++ = *ptrBad++;
35f622 ¤   ¤   ¤   ¤   break;
e5a3a6 ¤   ¤   ¤   }
a00fe4 ¤   ¤   }
f93c6e ¤   ¤   if (badChars[i] == '\0')
bd5b34 ¤   ¤   {
919c9e ¤   ¤   ¤   *ptrGood++ = *ptrBad++;
bc0fe4 ¤   ¤   }
f69371 ¤   }
2e8af6 ¤   *ptrGood = '\0';
78af5a
e0f9ca ¤   return kPGPError_NoErr;;
f3efe6 }
8baf5a
6daf5a
2af1ae static PGPError
87e836 pgpGrowQueryString(PGPContextRef context,
5ec45d ¤   ¤   ¤   char **query, PGPUInt16 *maxsize, PGPUInt16 growthfactor)
e3bb36 {
1a61e0 ¤   PGPError¤   err;
7baf5a
b714d2 ¤   if ( strlen(*query) + growthfactor + 1 > *maxsize )
e4c7a1 ¤   {
d2e009 ¤   ¤   if (growthfactor < 500)
8a5b34 ¤   ¤   {
fe7a87 ¤   ¤   ¤   growthfactor = 500;
d30fe4 ¤   ¤   }
add7b4 ¤   ¤   err = pgpContextMemRealloc( context, (void **)query,·
a35cee ¤   ¤   ¤   ¤   ¤   ¤   ¤   *maxsize + growthfactor + 1, 0 );
af97ab ¤   ¤   if ( IsPGPError(err) )
7f5b34 ¤   ¤   {
25b32f ¤   ¤   ¤   return err;
db0fe4 ¤   ¤   }
ce2caf ¤   ¤   *maxsize += 500;
799371 ¤   }
2a151e ¤   return kPGPError_NoErr;
5eefe6 }
84af5a
3ff1ae static PGPError
3c0a0d pgpBuildLDAPQuery(·
409d9e ¤   PGPFilterRef filter,·
cce8f1 ¤   PGPInt16 filterClass,
45c72e ¤   PGPBoolean *disableVisited,
65945d ¤   char **query,·
d20046 ¤   PGPUInt16 *maxsize ·)
4fbb36 {
707f23 ¤   PGPError¤   err¤¤   ¤   = kPGPError_NoErr;
c046b3 ¤   char¤   ¤   *newString ·= NULL;
b15ba5 ¤   char¤   ¤   buffer[500];
bdaf5a
389044 ¤   switch (filter->filterType)
4cc7a1 ¤   {
6d97c7 ¤   ¤   case kPGPFilterTypeAnd:
c75b34 ¤   ¤   {
eb1be1 ¤   ¤   ¤   err = pgpGrowQueryString(filter->context, query, maxsize, 10);
3e1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
6cf776 ¤   ¤   ¤   {
61451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
2fa3a6 ¤   ¤   ¤   }
6656dd ¤   ¤   ¤   strcat( *query, "(&" );
c9af5a
a49db9 ¤   ¤   ¤   err = pgpBuildLDAPQuery(filter->value.andFilter.andFilter1,
b487d9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filterClass, disableVisited, query, maxsize );
e72865 ¤   ¤   ¤   if (err != kPGPError_NoErr)
87f776 ¤   ¤   ¤   {
90454a ¤   ¤   ¤   ¤   return err;
e0a3a6 ¤   ¤   ¤   }
c472dd ¤   ¤   ¤   err = pgpBuildLDAPQuery(filter->value.andFilter.andFilter2,
--a3a8 00096959c254010022c Page 20 of pgpKeyFilter.c
2987d9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filterClass, disableVisited, query, maxsize );
5d2865 ¤   ¤   ¤   if (err != kPGPError_NoErr)
94f776 ¤   ¤   ¤   {
ea454a ¤   ¤   ¤   ¤   return err;
69a3a6 ¤   ¤   ¤   }
951be1 ¤   ¤   ¤   err = pgpGrowQueryString(filter->context, query, maxsize, 10);
0a1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
78f776 ¤   ¤   ¤   {
81451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
98a3a6 ¤   ¤   ¤   }
7aaf5a
5e7266 ¤   ¤   ¤   strcat( *query, ")" );
ddcdcb ¤   ¤   ¤   break;
d30fe4 ¤   ¤   }
54af5a
5fa0b9 ¤   ¤   case kPGPFilterTypeOr:
125b34 ¤   ¤   {
021be1 ¤   ¤   ¤   err = pgpGrowQueryString(filter->context, query, maxsize, 10);
701bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
89f776 ¤   ¤   ¤   {
3c451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
f7a3a6 ¤   ¤   ¤   }
dc191c ¤   ¤   ¤   strcat(*query, "(|");
21af5a
0e9c3a ¤   ¤   ¤   err = pgpBuildLDAPQuery(filter->value.orFilter.orFilter1,
bcba55 ¤   ¤   ¤   ¤   ¤   ¤   filterClass, disableVisited, query, maxsize );
472865 ¤   ¤   ¤   if (err != kPGPError_NoErr)
52f776 ¤   ¤   ¤   {
d6454a ¤   ¤   ¤   ¤   return err;
77a3a6 ¤   ¤   ¤   }
df9ec4 ¤   ¤   ¤   err = pgpBuildLDAPQuery(filter->value.orFilter.orFilter2,·
18ba55 ¤   ¤   ¤   ¤   ¤   ¤   filterClass, disableVisited, query, maxsize );
562865 ¤   ¤   ¤   if (err != kPGPError_NoErr)
abf776 ¤   ¤   ¤   {
2a454a ¤   ¤   ¤   ¤   return err;
1ba3a6 ¤   ¤   ¤   }
d9af5a
161be1 ¤   ¤   ¤   err = pgpGrowQueryString(filter->context, query, maxsize, 10);
141bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
0af776 ¤   ¤   ¤   {
37451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
87a3a6 ¤   ¤   ¤   }
3df35e ¤   ¤   ¤   strcat( *query, ")");
99cdcb ¤   ¤   ¤   break;
640fe4 ¤   ¤   }
7faf5a
686415 ¤   ¤   case kPGPFilterTypeNot:
835b34 ¤   ¤   {
a01be1 ¤   ¤   ¤   err = pgpGrowQueryString(filter->context, query, maxsize, 10);
9a1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
2bf776 ¤   ¤   ¤   {
25451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
dba3a6 ¤   ¤   ¤   }
df4a0c ¤   ¤   ¤   strcat( *query, "(!" );
9aaf5a
e13b81 ¤   ¤   ¤   err = pgpBuildLDAPQuery(filter->value.notFilter,·
37ba55 ¤   ¤   ¤   ¤   ¤   ¤   filterClass, disableVisited, query, maxsize );
a92865 ¤   ¤   ¤   if (err != kPGPError_NoErr)
1bf776 ¤   ¤   ¤   {
e5454a ¤   ¤   ¤   ¤   return err;
cea3a6 ¤   ¤   ¤   }
deaf5a
201be1 ¤   ¤   ¤   err = pgpGrowQueryString(filter->context, query, maxsize, 10);
3d1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
7ef776 ¤   ¤   ¤   {
2f451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
c6a3a6 ¤   ¤   ¤   }
2ff35e ¤   ¤   ¤   strcat( *query, ")");
0bcdcb ¤   ¤   ¤   break;
520fe4 ¤   ¤   }
8baf5a
96a76d ¤   ¤   case kPGPFilterTypeKeyEncryptAlgorithm:
--f918 0003d0a95b04010022c Page 21 of pgpKeyFilter.c
d2ed49 ¤   ¤   {¤
c66a76 ¤   ¤   ¤   *buffer = '\0';
1baf5a
91d4a2 ¤   ¤   ¤   switch ( filter->value.keyEncryptAlgorithm )
f3f776 ¤   ¤   ¤   {
d2a0f7 ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSA:
532741 ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
ab21f0 ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSASignOnly:
e66e50 ¤   ¤   ¤   ¤   {¤
04290d ¤   ¤   ¤   ¤   ¤   strcpy( buffer, "(pgpKeyType=RSA)");
3b14c3 ¤   ¤   ¤   ¤   ¤   break;
9a2613 ¤   ¤   ¤   ¤   }
f6004e ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_ElGamal:
902f2f ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_DSA:
b072c3 ¤   ¤   ¤   ¤   {
7a235d ¤   ¤   ¤   ¤   ¤   strcpy( buffer, "(pgpKeyType=DSS/DH)");
8314c3 ¤   ¤   ¤   ¤   ¤   break;
392613 ¤   ¤   ¤   ¤   }
efaf5a
ea6ab9 ¤   ¤   ¤   ¤   default:
5f07dd ¤   ¤   ¤   ¤   ¤   return kPGPError_InvalidFilterParameter;
fea3a6 ¤   ¤   ¤   }
93a01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
7215a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize, (PGPUInt16) strlen(buffer));
531bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
fbf776 ¤   ¤   ¤   {
2b451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
c2a3a6 ¤   ¤   ¤   }
51664c ¤   ¤   ¤   strcat( *query, buffer );
d3cdcb ¤   ¤   ¤   break;
7daf5a
790fe4 ¤   ¤   }
de68a5 ¤   ¤   case kPGPFilterTypeKeySigAlgorithm:
d3ed49 ¤   ¤   {¤
a96a76 ¤   ¤   ¤   *buffer = '\0';
b1af5a
631fe5 ¤   ¤   ¤   switch ( filter->value.keySigAlgorithm )
d6f776 ¤   ¤   ¤   {
24a0f7 ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSA:
642741 ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
4321f0 ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSASignOnly:
a46e50 ¤   ¤   ¤   ¤   {¤
30290d ¤   ¤   ¤   ¤   ¤   strcpy( buffer, "(pgpKeyType=RSA)");
0314c3 ¤   ¤   ¤   ¤   ¤   break;
692613 ¤   ¤   ¤   ¤   }
16004e ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_ElGamal:
422f2f ¤   ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_DSA:
6d72c3 ¤   ¤   ¤   ¤   {
cc235d ¤   ¤   ¤   ¤   ¤   strcpy( buffer, "(pgpKeyType=DSS/DH)");
1314c3 ¤   ¤   ¤   ¤   ¤   break;
ad2613 ¤   ¤   ¤   ¤   }
72af5a
7e6ab9 ¤   ¤   ¤   ¤   default:
b207dd ¤   ¤   ¤   ¤   ¤   return kPGPError_InvalidFilterParameter;
f0a3a6 ¤   ¤   ¤   }
5ca01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
dac05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
65b899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
fb1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
b3f776 ¤   ¤   ¤   {
95451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
68a3a6 ¤   ¤   ¤   }
78664c ¤   ¤   ¤   strcat( *query, buffer );
83cdcb ¤   ¤   ¤   break;
9c0fe4 ¤   ¤   }
fc87c7 ¤   ¤   ¤
42a537 ¤   ¤   case kPGPFilterTypeKeyKeyID:
6f5b34 ¤   ¤   {
46637e ¤   ¤   ¤   char¤   ¤   keyIDBuffer[ 128 ];
5067c5 ¤
d26a76 ¤   ¤   ¤   *buffer = '\0';
3daf5a
--d7f0 00004ebcf024010022c Page 22 of pgpKeyFilter.c
de4179 ¤   ¤   ¤   err = PGPGetKeyIDString(·
70afed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter->value.keyKeyID,
12cb31 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyIDString_Full,
5f7c22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDBuffer );
8fda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
340dfb ¤   ¤   ¤   if (IsPGPError(err))
fbf776 ¤   ¤   ¤   {
5a454a ¤   ¤   ¤   ¤   return err;
4ca3a6 ¤   ¤   ¤   }
6c9b30 ¤   ¤   ¤   if ( keyIDBuffer[0] == '0' && tolower(keyIDBuffer[1]) == 'x' ) {
8b4e98 ¤   ¤   ¤   ¤   if (strlen(keyIDBuffer) == 10) {
4664f3 ¤   ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpKeyID=%s)", &keyIDBuffer[2]);
f70770 ¤   ¤   ¤   ¤   }·
1d5109 ¤   ¤   ¤   ¤   else·
a572c3 ¤   ¤   ¤   ¤   {
843d00 ¤   ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpCertID=%s)", &keyIDBuffer[2]);
562613 ¤   ¤   ¤   ¤   }
97e5d3 ¤   ¤   ¤   }·
0b6b93 ¤   ¤   ¤   else·
72f776 ¤   ¤   ¤   {
275e6f ¤   ¤   ¤   ¤   if (strlen(keyIDBuffer) == 8) {
ec6dee ¤   ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpKeyID=%s)", keyIDBuffer);
932613 ¤   ¤   ¤   ¤   }
b2fa07 ¤   ¤   ¤   ¤   else
3f72c3 ¤   ¤   ¤   ¤   {
fc4743 ¤   ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpCertID=%s)", keyIDBuffer);
362613 ¤   ¤   ¤   ¤   }
a0a3a6 ¤   ¤   ¤   }
2baf5a
6da01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
1c15a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize, (PGPUInt16) strlen(buffer));
831bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
33f776 ¤   ¤   ¤   {
43451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
b9a3a6 ¤   ¤   ¤   }
68664c ¤   ¤   ¤   strcat( *query, buffer );
30cdcb ¤   ¤   ¤   break;
de0fe4 ¤   ¤   }
0caf5a
36bbec ¤   ¤   case kPGPFilterTypeKeySubKeyID:
e2ed49 ¤   ¤   {¤
17637e ¤   ¤   ¤   char¤   ¤   keyIDBuffer[ 128 ];
8f87c7 ¤   ¤   ¤
826a76 ¤   ¤   ¤   *buffer = '\0';
4baf5a
7c4179 ¤   ¤   ¤   err = PGPGetKeyIDString(·
6cf470 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter->value.keySubKeyID,
03cb31 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyIDString_Full,
477c22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDBuffer );
d7da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
cf0dfb ¤   ¤   ¤   if (IsPGPError(err))
54f776 ¤   ¤   ¤   {
cf454a ¤   ¤   ¤   ¤   return err;
69a3a6 ¤   ¤   ¤   }
e59b30 ¤   ¤   ¤   if ( keyIDBuffer[0] == '0' && tolower(keyIDBuffer[1]) == 'x' ) {
81bcd2 ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpSubKeyID=%s)", &keyIDBuffer[2]);
13e5d3 ¤   ¤   ¤   }·
f76b93 ¤   ¤   ¤   else·
bbf776 ¤   ¤   ¤   {
a87cd8 ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpSubKeyID=%s)", keyIDBuffer);
ffa3a6 ¤   ¤   ¤   }
17af5a
daa01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
8015a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize, (PGPUInt16) strlen(buffer));
e31bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
85f776 ¤   ¤   ¤   {
02451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
b8a3a6 ¤   ¤   ¤   }
b5664c ¤   ¤   ¤   strcat( *query, buffer );
86cdcb ¤   ¤   ¤   break;
300fe4 ¤   ¤   }
04af5a
--a7f0 0006d5e48214010022c Page 23 of pgpKeyFilter.c
3fd15f ¤   ¤   case kPGPFilterTypeKeyCreationTime:
0bed49 ¤   ¤   {¤
417aad ¤   ¤   ¤   /*
41a444 ¤   ¤   ¤   ·* format: YYYYMMDDHHMMSSZ
038753 ¤   ¤   ¤   ·*/
8eaf5a
2e4394 ¤   ¤   ¤   PGPTime tempTime;
4faf5a
336a76 ¤   ¤   ¤   *buffer = '\0';
613448 ¤   ¤   ¤   tempTime = filter->value.keyCreationTime;
c7af5a
2f64b3 ¤   ¤   ¤   if (filter->value.keyCreationTime != 0)·
d5f776 ¤   ¤   ¤   {
fb536c ¤   ¤   ¤   ¤   struct tm¤  *localTime;
8e7c48 ¤   ¤   ¤   ¤   char¤   ¤   timeString[20];
75af5a
124b4e ¤   ¤   ¤   ¤   localTime = pgpLocalTime(&tempTime);
a9af5a
87d45b ¤   ¤   ¤   ¤   if ( localTime == NULL )
9172c3 ¤   ¤   ¤   ¤   {
9f0a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
c72613 ¤   ¤   ¤   ¤   }
52af5a
6abd5c ¤   ¤   ¤   ¤   sprintf( timeString, "%4d%02d%02d%02d%02d%02dZ",
e92650 ¤   ¤   ¤   ¤   ¤   ¤   ¤   1900+localTime->tm_year, localTime->tm_mon+1,·
ba4273 ¤   ¤   ¤   ¤   ¤   ¤   ¤   localTime->tm_mday, localTime->tm_hour,·
61b0ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   localTime->tm_min, localTime->tm_sec );
76af5a
d768d6 ¤   ¤   ¤   ¤   switch ( filter->match )
e772c3 ¤   ¤   ¤   ¤   {
a66ecc ¤   ¤   ¤   ¤   ¤   case kPGPMatchEqual:
3eaf5a
92a57f ¤   ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
a24447 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "(pgpKeyCreateTime=%s)", timeString );
2b00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
71af5a
7e95ce ¤   ¤   ¤   ¤   ¤   case kPGPMatchGreaterOrEqual:
dcaf5a
77a57f ¤   ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
c9332b ¤   ¤   ¤   ¤   ¤   ¤   ¤   "(|(pgpKeyCreateTime>=%s)(pgpKeyCreateTime=%s))",·
917b66 ¤   ¤   ¤   ¤   ¤   ¤   ¤   timeString, timeString);
7e00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
20af5a
0535b9 ¤   ¤   ¤   ¤   ¤   case kPGPMatchLessOrEqual:
67af5a
34a57f ¤   ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
dab152 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "(|(pgpKeyCreateTime<=%s)(pgpKeyCreateTime=%s))",·
517b66 ¤   ¤   ¤   ¤   ¤   ¤   ¤   timeString, timeString);
7700eb ¤   ¤   ¤   ¤   ¤   ¤   break;
d6af5a
8a5ee4 ¤   ¤   ¤   ¤   ¤   default:
29ddf4 ¤   ¤   ¤   ¤   ¤   ¤   return kPGPError_InvalidFilterParameter;
cc2613 ¤   ¤   ¤   ¤   }
b5af5a
33a726 ¤   ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
579346 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
0162b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
385a27 ¤   ¤   ¤   ¤   if ( IsPGPError(err) )
b972c3 ¤   ¤   ¤   ¤   {
780a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
1a2613 ¤   ¤   ¤   ¤   }
87a3a6 ¤   ¤   ¤   }
5b664c ¤   ¤   ¤   strcat( *query, buffer );
5ccdcb ¤   ¤   ¤   break;
fe0fe4 ¤   ¤   }
89af5a
60b06f ¤   ¤   case kPGPFilterTypeKeyExpirationTime:
32ed49 ¤   ¤   {¤
ff7aad ¤   ¤   ¤   /*
82a444 ¤   ¤   ¤   ·* format: YYYYMMDDHHMMSSZ
838753 ¤   ¤   ¤   ·*/
6daf5a
--8dd8 000ad15c4324010022c Page 24 of pgpKeyFilter.c
3d1c40 ¤   ¤   ¤   PGPTime¤¤   tempTime;
7eaf5a
8a6a76 ¤   ¤   ¤   *buffer = '\0';
18dd36 ¤   ¤   ¤   tempTime = filter->value.keyExpirationTime;
ddaf5a
b4fe8e ¤   ¤   ¤   if (filter->value.keyExpirationTime != 0)·
1df776 ¤   ¤   ¤   {
2d536c ¤   ¤   ¤   ¤   struct tm¤  *localTime;
247c48 ¤   ¤   ¤   ¤   char¤   ¤   timeString[20];
96af5a
634b4e ¤   ¤   ¤   ¤   localTime = pgpLocalTime(&tempTime);
15af5a
c3d45b ¤   ¤   ¤   ¤   if ( localTime == NULL )
8d72c3 ¤   ¤   ¤   ¤   {
fa0a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
9b2613 ¤   ¤   ¤   ¤   }
abaf5a
aabd5c ¤   ¤   ¤   ¤   sprintf( timeString, "%4d%02d%02d%02d%02d%02dZ",
cb2650 ¤   ¤   ¤   ¤   ¤   ¤   ¤   1900+localTime->tm_year, localTime->tm_mon+1,·
ac4273 ¤   ¤   ¤   ¤   ¤   ¤   ¤   localTime->tm_mday, localTime->tm_hour,·
7ab0ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   localTime->tm_min, localTime->tm_sec );
a8af5a
fe68d6 ¤   ¤   ¤   ¤   switch ( filter->match )
c872c3 ¤   ¤   ¤   ¤   {
386ecc ¤   ¤   ¤   ¤   ¤   case kPGPMatchEqual:
c2af5a
f1a57f ¤   ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
78cfac ¤   ¤   ¤   ¤   ¤   ¤   ¤   "(pgpKeyExpireTime=%s)", timeString );
d500eb ¤   ¤   ¤   ¤   ¤   ¤   break;
83af5a
6095ce ¤   ¤   ¤   ¤   ¤   case kPGPMatchGreaterOrEqual:
39af5a
a2a57f ¤   ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
4e3c4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   "(|(pgpKeyExpireTime>=%s)(pgpKeyExpireTime=%s))",
a57b66 ¤   ¤   ¤   ¤   ¤   ¤   ¤   timeString, timeString);
be00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
83af5a
db35b9 ¤   ¤   ¤   ¤   ¤   case kPGPMatchLessOrEqual:
0aaf5a
81a57f ¤   ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
277dad ¤   ¤   ¤   ¤   ¤   ¤   ¤   "(|(pgpKeyExpireTime<=%s)(pgpKeyExpireTime=%s))",
f9cf25 ¤   ¤   ¤   ¤   ¤   ¤   ¤   timeString, timeString );
9700eb ¤   ¤   ¤   ¤   ¤   ¤   break;
b0af5a
c85ee4 ¤   ¤   ¤   ¤   ¤   default:
cfddf4 ¤   ¤   ¤   ¤   ¤   ¤   return kPGPError_InvalidFilterParameter;
f02613 ¤   ¤   ¤   ¤   }
aaaf5a
6ca726 ¤   ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
f89346 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
7a62b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
3a5a27 ¤   ¤   ¤   ¤   if ( IsPGPError(err) )
9572c3 ¤   ¤   ¤   ¤   {
e00a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
8e2613 ¤   ¤   ¤   ¤   }
38a3a6 ¤   ¤   ¤   }
cb664c ¤   ¤   ¤   strcat( *query, buffer );
8bcdcb ¤   ¤   ¤   break;
b40fe4 ¤   ¤   }
49af5a
11dc9c ¤   ¤   case kPGPFilterTypeKeyRevoked:
cd5b34 ¤   ¤   {
3c83a9 ¤   ¤   ¤   sprintf( buffer, "(pgpRevoked=%d)", filter->value.keyRevoked);
99af5a
d4a01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
b6c05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
ccb899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
1d1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
e7f776 ¤   ¤   ¤   {
43451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
e9a3a6 ¤   ¤   ¤   }
ad664c ¤   ¤   ¤   strcat( *query, buffer );
--6a94 00058e53c664010022c Page 25 of pgpKeyFilter.c
7ecdcb ¤   ¤   ¤   break;
690fe4 ¤   ¤   }
33af5a
21d77a ¤   ¤   case kPGPFilterTypeKeyDisabled:
c15b34 ¤   ¤   {
bb61c3 ¤   ¤   ¤   sprintf( buffer, "(pgpDisabled=%d)", filter->value.keyDisabled);
53af5a
e8a01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
e8c05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
ceb899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
f81bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
47f776 ¤   ¤   ¤   {
1c451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
87a3a6 ¤   ¤   ¤   }
35664c ¤   ¤   ¤   strcat( *query, buffer );
a78ee8 ¤   ¤   ¤   *disableVisited = TRUE;
81cdcb ¤   ¤   ¤   break;
df0fe4 ¤   ¤   }
98af5a
ba9f86 ¤   ¤   case kPGPFilterTypeKeyEncryptKeySize:
2ded49 ¤   ¤   {¤
266d3b ¤   ¤   ¤   switch ( filter->match )
2cf776 ¤   ¤   ¤   {
746b21 ¤   ¤   ¤   ¤   case kPGPMatchEqual:
6eaf5a
f559bb ¤   ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpKeySize=%05d)",
dbd4fe ¤   ¤   ¤   ¤   ¤   ¤   filter->value.keyEncryptKeySize );
ae14c3 ¤   ¤   ¤   ¤   ¤   break;
67af5a
fbdaf0 ¤   ¤   ¤   ¤   case kPGPMatchGreaterOrEqual:
49af5a
b49991 ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
f042aa ¤   ¤   ¤   ¤   ¤   ¤   "(|(pgpKeySize>=%05d)(pgpKeySize=%05d))",
c84462 ¤   ¤   ¤   ¤   ¤   ¤   filter->value.keyEncryptKeySize,
9d79cd ¤   ¤   ¤   ¤   ¤   ¤   filter->value.keyEncryptKeySize);
5714c3 ¤   ¤   ¤   ¤   ¤   break;
c4af5a
00a421 ¤   ¤   ¤   ¤   case kPGPMatchLessOrEqual:
79af5a
e69991 ¤   ¤   ¤   ¤   ¤   sprintf( buffer,·
9ed687 ¤   ¤   ¤   ¤   ¤   ¤   "(|(pgpKeySize<=%05d)(pgpKeySize=%05d))",
5e4462 ¤   ¤   ¤   ¤   ¤   ¤   filter->value.keyEncryptKeySize,
3d79cd ¤   ¤   ¤   ¤   ¤   ¤   filter->value.keyEncryptKeySize);
a014c3 ¤   ¤   ¤   ¤   ¤   break;
c6af5a
526ab9 ¤   ¤   ¤   ¤   default:
8f07dd ¤   ¤   ¤   ¤   ¤   return kPGPError_InvalidFilterParameter;
00a3a6 ¤   ¤   ¤   }
a3af5a
bca01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
5cc05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
bbb899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
de1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
21f776 ¤   ¤   ¤   {
20451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
c8a3a6 ¤   ¤   ¤   }
1b664c ¤   ¤   ¤   strcat( *query, buffer );
b0cdcb ¤   ¤   ¤   break;
560fe4 ¤   ¤   }
24af5a
d323e6 ¤   ¤   case kPGPFilterTypeUserIDString:
3ced49 ¤   ¤   {¤
c5806e ¤   ¤   ¤   err = pgpEncodeSearchTerms( filter->context,
004f73 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.userIDString, &newString );
6daf5a
941bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
8af776 ¤   ¤   ¤   {
ef451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
17a3a6 ¤   ¤   ¤   }
58af5a
e3f4db ¤   ¤   ¤   if ( filter->match == kPGPMatchSubString )
58f776 ¤   ¤   ¤   {
--992e 00088019ac94010022c Page 26 of pgpKeyFilter.c
2decbe ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpUserID=*%s*)", newString );
9be5d3 ¤   ¤   ¤   }·
73bb8c ¤   ¤   ¤   else
9ef776 ¤   ¤   ¤   {
30189d ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpUserID=%s)", newString );
7ea3a6 ¤   ¤   ¤   }
92af5a
db087b ¤   ¤   ¤   pgpContextMemFree( filter->context, newString);
0daf5a
22a01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
03c05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
85b899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
a91bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
a9f776 ¤   ¤   ¤   {
b2451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
54a3a6 ¤   ¤   ¤   }
8d664c ¤   ¤   ¤   strcat( *query, buffer );
48cdcb ¤   ¤   ¤   break;
900fe4 ¤   ¤   }
ecaf5a
b6a20d ¤   ¤   case kPGPFilterTypeUserIDName:
00ed49 ¤   ¤   {¤
a5806e ¤   ¤   ¤   err = pgpEncodeSearchTerms( filter->context,
55d03e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.userIDName, &newString );
4faf5a
d91bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
49f776 ¤   ¤   ¤   {
fd451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
51a3a6 ¤   ¤   ¤   }
c4af5a
a3dc81 ¤   ¤   ¤   sprintf( buffer, "(pgpUserID=%s)", newString );
87af5a
2f087b ¤   ¤   ¤   pgpContextMemFree( filter->context, newString);
0baf5a
3ba01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
5ec05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
3db899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
6a1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
62f776 ¤   ¤   ¤   {
f1451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
66a3a6 ¤   ¤   ¤   }
e1664c ¤   ¤   ¤   strcat( *query, buffer );
d4cdcb ¤   ¤   ¤   break;
f00fe4 ¤   ¤   }
a7af5a
7e30f7 ¤   ¤   case kPGPFilterTypeUserIDEmail:
1eed49 ¤   ¤   {¤
fb806e ¤   ¤   ¤   err = pgpEncodeSearchTerms( filter->context,
1e7603 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.userIDEmail,
170924 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newString);
cdaf5a
2d1bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
9bf776 ¤   ¤   ¤   {
91451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
52a3a6 ¤   ¤   ¤   }
b4af5a
90f4db ¤   ¤   ¤   if ( filter->match == kPGPMatchSubString )
87f776 ¤   ¤   ¤   {
12af5a
f314e7 ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpUserID=*<*%s*>*)", newString );
d2e5d3 ¤   ¤   ¤   }·
ee6b93 ¤   ¤   ¤   else·
37f776 ¤   ¤   ¤   {
96980e ¤   ¤   ¤   ¤   /*
1a94a9 ¤   ¤   ¤   ¤   ·* assume EXACT email address matching
e41020 ¤   ¤   ¤   ¤   ·*/
b0af5a
bb49c7 ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpUserID=*<%s>*)", newString );
7ca3a6 ¤   ¤   ¤   }
54af5a
45087b ¤   ¤   ¤   pgpContextMemFree( filter->context, newString);
88a01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
--5016 0005186c9174010022c Page 27 of pgpKeyFilter.c
16c05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
d9b899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
341bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
a7f776 ¤   ¤   ¤   {
3e451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
20a3a6 ¤   ¤   ¤   }
d2664c ¤   ¤   ¤   strcat( *query, buffer );
13cdcb ¤   ¤   ¤   break;
920fe4 ¤   ¤   }
deaf5a
be3516 ¤   ¤   case kPGPFilterTypeSigKeyID:
f15b34 ¤   ¤   {
f47c83 ¤   ¤   ¤   char¤   keyIDBuffer[ 128 ];
8687c7 ¤   ¤   ¤
d87aad ¤   ¤   ¤   /*
b5abc7 ¤   ¤   ¤   ·* This search supports ONLY the LONG 16 char
64dda8 ¤   ¤   ¤   ·* keyid search
168753 ¤   ¤   ¤   ·*/
6eaf5a
526a76 ¤   ¤   ¤   *buffer = '\0';
d9af5a
bc4179 ¤   ¤   ¤   err = PGPGetKeyIDString(·
d450ff ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter->value.sigKeyID,
d06530 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyIDString_Full,
b0edba ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDBuffer );
28531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
c1af5a
d42865 ¤   ¤   ¤   if (err != kPGPError_NoErr)
d2f776 ¤   ¤   ¤   {
5f454a ¤   ¤   ¤   ¤   return err;
96a3a6 ¤   ¤   ¤   }
06af5a
b09b30 ¤   ¤   ¤   if ( keyIDBuffer[0] == '0' && tolower(keyIDBuffer[1]) == 'x' ) {
bfca56 ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpSignerID=%s)", &keyIDBuffer[2]);
0ce5d3 ¤   ¤   ¤   }·
146b93 ¤   ¤   ¤   else·
29f776 ¤   ¤   ¤   {
b42a34 ¤   ¤   ¤   ¤   sprintf( buffer, "(pgpSignerID=%s)", keyIDBuffer);
37a3a6 ¤   ¤   ¤   }
b9af5a
b4a01d ¤   ¤   ¤   err = pgpGrowQueryString(filter->context,·
0ec05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query, maxsize,·
aeb899 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUInt16) strlen(buffer));
e51bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
51f776 ¤   ¤   ¤   {
29451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
b4a3a6 ¤   ¤   ¤   }
a2664c ¤   ¤   ¤   strcat( *query, buffer );
f3cdcb ¤   ¤   ¤   break;
d90fe4 ¤   ¤   }
13af5a
2d1b17 ¤   ¤   /*
c66ea0 ¤   ¤   ·* Searches which are not supported by LDAP
3c9de3 ¤   ¤   ·*/
4daf5a
f9be91 ¤   ¤   case kPGPFilterTypeKeyFingerPrint:
c88e8e ¤   ¤   case kPGPFilterTypeKeySigKeySize:
8a5b34 ¤   ¤   {
06689b ¤   ¤   ¤   return kPGPError_UnsupportedLDAPFilter;
0e0fe4 ¤   ¤   }
bfaf5a
739ae3 ¤   ¤   default:
635b34 ¤   ¤   {
a5db44 ¤   ¤   ¤   return kPGPError_UnknownFilterType;
320fe4 ¤   ¤   }
969371 ¤   }
13af5a
1eb7c6 ¤   return(0);
66af5a
e1efe6 }
b9af5a
518de9 PGPError·
--f700 000fa65373c4010022c Page 28 of pgpKeyFilter.c
1436e9 PGPLDAPQueryFromFilter(·
8dfadc ¤   PGPFilterRef¤   filter,
fbf4b6 ¤   char¤   ¤   ¤   **queryOut )
67bb36 {
7e6594 ¤   PGPUInt16¤  maxsize¤= 1000;
9ee662 ¤   PGPUInt16¤  bufLength = 0;
e730d4 ¤   PGPError¤   err¤¤   = kPGPError_NoErr;
5a13ff ¤   PGPBoolean¤ disableVisited = FALSE;
86a4ce ¤   char¤   ¤   *querybuf;
3167c5 ¤
ff43a5 ¤   PGPValidatePtr( queryOut );
84b65c ¤   *queryOut¤  = NULL;
464ffe ¤   PGPValidateFilter( filter );
60af5a
0e40ad ¤   querybuf = (char*) pgpContextMemAlloc( filter->context,·
2b4d58 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   maxsize, kPGPMemoryMgrFlags_Clear );
1a3093 ¤   if (querybuf == NULL)
4dc7a1 ¤   {
e04030 ¤   ¤   return kPGPError_OutOfMemory;
879371 ¤   }
12ae72 ¤   *querybuf = '\0';
8baf5a
52d4f8 ¤   err = pgpBuildLDAPQuery(filter,·
0a2990 ¤   ¤   ¤   ¤   ¤   ¤   kPGPFilterClassDefault,·
e262cf ¤   ¤   ¤   ¤   ¤   ¤   &disableVisited, &querybuf, &maxsize);
65af5a
72bb4c ¤   if ( IsntPGPError(err) )
15c7a1 ¤   {
0b1b17 ¤   ¤   /*
0ec6b6 ¤   ¤   ·* allocate a buffer big enough to hold the query and potentially
28fc9f ¤   ¤   ·* the extra pgpDisabled condition that is added at the end
8c9de3 ¤   ¤   ·*/
1eaf5a
1fd8c7 ¤   ¤   bufLength = strlen(querybuf);
6b4898 ¤   ¤   *queryOut = (char *)PGPNewData(
06dafa ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( filter->context ),
2abaf7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufLength + 41, 0);
41af5a
f7aeba ¤   ¤   if ( *queryOut != NULL )
055b34 ¤   ¤   {
0a0721 ¤   ¤   ¤   if (disableVisited == FALSE)
d6f776 ¤   ¤   ¤   {
dc4fad ¤   ¤   ¤   ¤   sprintf(*queryOut, "(&%s(pgpDisabled=0))", querybuf );
57a3a6 ¤   ¤   ¤   }
01bb8c ¤   ¤   ¤   else
0bf776 ¤   ¤   ¤   {
d07662 ¤   ¤   ¤   ¤   pgpCopyMemory( querybuf, *queryOut, bufLength);
32a2d6 ¤   ¤   ¤   ¤   (*queryOut)[bufLength] = '\0';
74a3a6 ¤   ¤   ¤   }
940fe4 ¤   ¤   }
030e1d ¤   ¤   else
d25b34 ¤   ¤   {
1ad9cc ¤   ¤   ¤   *queryOut = NULL;
20b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
2c0fe4 ¤   ¤   }
f09371 ¤   }
c54264 ¤   else·
53c7a1 ¤   {
f55098 ¤   ¤   *queryOut = NULL;
f79371 ¤   }
f56957 ¤   pgpContextMemFree( filter->context, querybuf );
ebaf5a
80c409 ¤   pgpAssertErrWithPtr( err, *queryOut );
265ea8 ¤   return err;
1befe6 }
11af5a
819578 static·
92c77d PGPError
efd4cb pgpUrlEncode( PGPContextRef context, char **Dest, char *Source )
74bb36 {
beed18 ····PGPError¤   err = kPGPError_NoErr;
faac9b ····char¤   ¤   *pSource, *pDest;
--b549 0006524fcda4010022c Page 29 of pgpKeyFilter.c
e0af5a
243195 ····/*Absolute worst case scenario is three times the source size. ·Rather
220ca9 ·····*than getting too precise, we'll allocate that much initially, and then
047835 ·····*realloc it down to actuality later.
dbd48d ·····*/
78af5a
7266d1 ····pgpAssert( Source );
750f0f ····pgpAssert( Dest );
47af5a
df81bd ····if ( Source && Dest )·
e8c7a1 ¤   {
fbb96f ¤   ¤   *Dest = (char *)pgpContextMemAlloc( context,·
29ee09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (strlen(Source) * 3) + 1,
d0915c ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
ff1d17 ¤   ¤   if ( Dest != NULL )
9e5b34 ¤   ¤   {
da44a4 ¤   ¤   ¤   pSource = Source;
11b576 ¤   ¤   ¤   pDest = *Dest;
8087c7 ¤   ¤   ¤
000a0e ¤   ¤   ¤   while(pSource && *pSource)·
b0f776 ¤   ¤   ¤   {
fb4938 ¤   ¤   ¤   ¤   /*Zeroth case: ·it's an alphabetic or numeric character*/
8b2974 ¤   ¤   ¤   ¤   if (!isalpha(*pSource) &&·
3b28ff ¤   ¤   ¤   ¤   ····!isdigit(*pSource) &&·
8ff970 ¤   ¤   ¤   ¤   ····*pSource != '-')·
a572c3 ¤   ¤   ¤   ¤   {
da7965 ¤   ¤   ¤   ¤   ¤   /*First case: ·Turn spaces into pluses.*/
14354c ¤   ¤   ¤   ¤   ¤   if(*pSource == ' ')·
e64859 ¤   ¤   ¤   ¤   ¤   {
5b48ef ¤   ¤   ¤   ¤   ¤   ¤   *pDest = '+';
501c89 ¤   ¤   ¤   ¤   ¤   }
8996bc ¤   ¤   ¤   ¤   ¤   else·
5a4859 ¤   ¤   ¤   ¤   ¤   {
9725f2 ¤   ¤   ¤   ¤   ¤   ¤   /*This is overkill, but works for our purposes*/
97e6ad ¤   ¤   ¤   ¤   ¤   ¤   *pDest = '%';
486026 ¤   ¤   ¤   ¤   ¤   ¤   ++pDest;
2399e6 ¤   ¤   ¤   ¤   ¤   ¤   sprintf(pDest, "%02X", *pSource);
7e6026 ¤   ¤   ¤   ¤   ¤   ¤   ++pDest;
9a1c89 ¤   ¤   ¤   ¤   ¤   }
0b2613 ¤   ¤   ¤   ¤   }
bbfa07 ¤   ¤   ¤   ¤   else
cb72c3 ¤   ¤   ¤   ¤   {
7afcf5 ¤   ¤   ¤   ¤   ¤   *pDest = *pSource;
362613 ¤   ¤   ¤   ¤   }
002b85 ¤   ¤   ¤   ¤
dfef2d ¤   ¤   ¤   ¤   ++pDest;
2903e5 ¤   ¤   ¤   ¤   ++pSource;
eda3a6 ¤   ¤   ¤   }
22af5a
7057ac ¤   ¤   ¤   *pDest = '\0';
3087c7 ¤   ¤   ¤
ac0fe4 ¤   ¤   }
530e1d ¤   ¤   else
925b34 ¤   ¤   {
c8b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
7f0fe4 ¤   ¤   }
4d9371 ¤   }
2d842c ····else
e1c7a1 ¤   {
e619d3 ¤   ¤   err = kPGPError_BadParams;
039371 ¤   }
8dace8 ····return err;
98efe6 }
9daf5a
1faf5a
248de9 PGPError·
d3b7f5 PGPHKSQueryFromFilter(·
1bfadc ¤   PGPFilterRef¤   filter,
d1f4b6 ¤   char¤   ¤   ¤   **queryOut )
36bb36 {
4b1398 ¤   PGPError¤   err¤¤   ¤   ¤   = kPGPError_NoErr;
657103 ¤   char¤   ¤   *encodedValue¤  = NULL;
--a25e 000c55dced84010022c Page 30 of pgpKeyFilter.c
c44e32 ¤   static const char ·prefix[]¤¤   ¤   = "exact=off&search=";
aeaf5a
7243a5 ¤   PGPValidatePtr( queryOut );
f0b65c ¤   *queryOut¤  = NULL;
874ffe ¤   PGPValidateFilter( filter );
37af5a
2bd8af ¤   /*
099e71 ¤   ·* HKS searches can only do 1 thing at a time
59a4e3 ¤   ·*/
fdaf5a
18d4b1 ¤   switch ( filter->filterType )
5cc7a1 ¤   {
b6a537 ¤   ¤   case kPGPFilterTypeKeyKeyID:
415b34 ¤   ¤   {
687c83 ¤   ¤   ¤   char¤   keyIDBuffer[ 128 ];
e787c7 ¤   ¤   ¤
664179 ¤   ¤   ¤   err = PGPGetKeyIDString(·
1350ff ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter->value.sigKeyID,
3f5dd7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyIDString_Abbreviated,
19edba ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDBuffer );
ee531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
07af5a
291bd4 ¤   ¤   ¤   if ( IsPGPError(err) )
27f776 ¤   ¤   ¤   {
ce454a ¤   ¤   ¤   ¤   return err;
4fa3a6 ¤   ¤   ¤   }
4481d5 ¤   ¤   ¤   *queryOut = (char*) PGPNewData( PGPGetContextMemoryMgr(
b60fa1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->context ),
5b718e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( keyIDBuffer ) +
3fbfbc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( prefix ) +1, 0);
da9835 ¤   ¤   ¤   if ( *queryOut == NULL )
33f776 ¤   ¤   ¤   {
de451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
37a3a6 ¤   ¤   ¤   }
54d2d4 ¤   ¤   ¤   sprintf( *queryOut, "%s%s", prefix, keyIDBuffer);
6ccdcb ¤   ¤   ¤   break;
560fe4 ¤   ¤   }
74af5a
8823e6 ¤   ¤   case kPGPFilterTypeUserIDString:
275b34 ¤   ¤   {
02f4db ¤   ¤   ¤   if ( filter->match == kPGPMatchSubString )
d4f776 ¤   ¤   ¤   {
1c8a0c ¤   ¤   ¤   ¤   err = pgpUrlEncode( filter->context, &encodedValue,·
e9a037 ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.userIDString);
cbaf5a
8b869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
9872c3 ¤   ¤   ¤   ¤   {
3f338a ¤   ¤   ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
bd2613 ¤   ¤   ¤   ¤   }
03af5a
fdcfa2 ¤   ¤   ¤   ¤   *queryOut = (char*) PGPNewData( PGPGetContextMemoryMgr(
3b0f43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->context ),
0f19bc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( encodedValue )+
2935f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( prefix ) +1, 0);
ee9dd8 ¤   ¤   ¤   ¤   if ( *queryOut == NULL )
1a72c3 ¤   ¤   ¤   ¤   {
18ec20 ¤   ¤   ¤   ¤   ¤   pgpContextMemFree( filter->context, encodedValue );
f60a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
a52613 ¤   ¤   ¤   ¤   }
152f39 ¤   ¤   ¤   ¤   sprintf( *queryOut, "%s%s", ·prefix,·
d70824 ¤   ¤   ¤   ¤   ¤   encodedValue);
b5af5a
8ca257 ¤   ¤   ¤   ¤   pgpContextMemFree( filter->context, encodedValue );
00a3a6 ¤   ¤   ¤   }
20bb8c ¤   ¤   ¤   else
cff776 ¤   ¤   ¤   {
3234b1 ¤   ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
51a3a6 ¤   ¤   ¤   }
c6cdcb ¤   ¤   ¤   break;
280fe4 ¤   ¤   }
d1af5a
c530f7 ¤   ¤   case kPGPFilterTypeUserIDEmail:
--8a49 000921e03da4010022c Page 31 of pgpKeyFilter.c
e35b34 ¤   ¤   {
3df4db ¤   ¤   ¤   if ( filter->match == kPGPMatchSubString )
88f776 ¤   ¤   ¤   {
7b8a0c ¤   ¤   ¤   ¤   err = pgpUrlEncode( filter->context, &encodedValue,·
85403b ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.userIDEmail);
0aaf5a
ed869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
d772c3 ¤   ¤   ¤   ¤   {
af338a ¤   ¤   ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
732613 ¤   ¤   ¤   ¤   }
53af5a
48cfa2 ¤   ¤   ¤   ¤   *queryOut = (char*) PGPNewData( PGPGetContextMemoryMgr(
f90f43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->context ),
ac19bc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( encodedValue )+
2e35f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( prefix ) +1, 0);
e99dd8 ¤   ¤   ¤   ¤   if ( *queryOut == NULL )
6472c3 ¤   ¤   ¤   ¤   {
60ec20 ¤   ¤   ¤   ¤   ¤   pgpContextMemFree( filter->context, encodedValue );
af0a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
752613 ¤   ¤   ¤   ¤   }
b72f39 ¤   ¤   ¤   ¤   sprintf( *queryOut, "%s%s", ·prefix,·
a40824 ¤   ¤   ¤   ¤   ¤   encodedValue);
61af5a
58a257 ¤   ¤   ¤   ¤   pgpContextMemFree( filter->context, encodedValue );
a0a3a6 ¤   ¤   ¤   }
2fbb8c ¤   ¤   ¤   else
8bf776 ¤   ¤   ¤   {
8934b1 ¤   ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
bea3a6 ¤   ¤   ¤   }
bdcdcb ¤   ¤   ¤   break;
600fe4 ¤   ¤   }
f1af5a
8ea20d ¤   ¤   case kPGPFilterTypeUserIDName:
515b34 ¤   ¤   {
85f4db ¤   ¤   ¤   if ( filter->match == kPGPMatchSubString )
20f776 ¤   ¤   ¤   {
338a0c ¤   ¤   ¤   ¤   err = pgpUrlEncode( filter->context, &encodedValue,·
a8918a ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->value.userIDName );
d9af5a
7f869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
6972c3 ¤   ¤   ¤   ¤   {
1b338a ¤   ¤   ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
982613 ¤   ¤   ¤   ¤   }
3aaf5a
07cfa2 ¤   ¤   ¤   ¤   *queryOut = (char*) PGPNewData( PGPGetContextMemoryMgr(
aa0f43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter->context ),
a319bc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( encodedValue )+
3035f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( prefix ) +1, 0);
529dd8 ¤   ¤   ¤   ¤   if ( *queryOut == NULL )
e672c3 ¤   ¤   ¤   ¤   {
2aec20 ¤   ¤   ¤   ¤   ¤   pgpContextMemFree( filter->context, encodedValue );
7e0a25 ¤   ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
002613 ¤   ¤   ¤   ¤   }
8b2f39 ¤   ¤   ¤   ¤   sprintf( *queryOut, "%s%s", ·prefix,·
f30824 ¤   ¤   ¤   ¤   ¤   encodedValue);
55af5a
aca257 ¤   ¤   ¤   ¤   pgpContextMemFree( filter->context, encodedValue );
eca3a6 ¤   ¤   ¤   }
03bb8c ¤   ¤   ¤   else
c7f776 ¤   ¤   ¤   {
ee34b1 ¤   ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
70a3a6 ¤   ¤   ¤   }
01cdcb ¤   ¤   ¤   break;
180fe4 ¤   ¤   }
79af5a
841b17 ¤   ¤   /*
5d870a ¤   ¤   ·* Searches which are not supported by HKP
009de3 ¤   ¤   ·*/
f2af5a
226415 ¤   ¤   case kPGPFilterTypeNot:
a297c7 ¤   ¤   case kPGPFilterTypeAnd:
92a0b9 ¤   ¤   case kPGPFilterTypeOr:
--839f 001fcda77f64010022c Page 32 of pgpKeyFilter.c
d5bbec ¤   ¤   case kPGPFilterTypeKeySubKeyID:
b0a76d ¤   ¤   case kPGPFilterTypeKeyEncryptAlgorithm:
6abe91 ¤   ¤   case kPGPFilterTypeKeyFingerPrint:
5bd15f ¤   ¤   case kPGPFilterTypeKeyCreationTime:
a4b06f ¤   ¤   case kPGPFilterTypeKeyExpirationTime:
d2dc9c ¤   ¤   case kPGPFilterTypeKeyRevoked:
f3d77a ¤   ¤   case kPGPFilterTypeKeyDisabled:
a468a5 ¤   ¤   case kPGPFilterTypeKeySigAlgorithm:
409f86 ¤   ¤   case kPGPFilterTypeKeyEncryptKeySize:
e98e8e ¤   ¤   case kPGPFilterTypeKeySigKeySize:
503516 ¤   ¤   case kPGPFilterTypeSigKeyID:
405b34 ¤   ¤   {
252596 ¤   ¤   ¤   return kPGPError_UnsupportedHKPFilter;
160fe4 ¤   ¤   }
0aaf5a
579ae3 ¤   ¤   default:
2e5b34 ¤   ¤   {
d0db44 ¤   ¤   ¤   return kPGPError_UnknownFilterType;
d9cdcb ¤   ¤   ¤   break;
2c0fe4 ¤   ¤   }
799371 ¤   }
d067c5 ¤
2bc409 ¤   pgpAssertErrWithPtr( err, *queryOut );
5e5ea8 ¤   return err;
b5efe6 }
c9af5a
1f38e5 /*
8ae6c5 ·* Local Variables:
909b19 ·* tab-width: 4
73e7a4 ·* End:
0bb612 ·* vi: ts=4 sw=4
526c42 ·* vim: si
fc495d ·*/
--7dc3 000dc12d48d4010022d Page 1 of pgpKeyID.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
0f0b53 ¤   $Id: pgpKeyID.c,v 1.30.10.1 1998/11/12 03:21:57 heller Exp $
88f7f7 ____________________________________________________________________________*/
e7e2ff #include "pgpConfig.h"
aaaf5a
83324c #include <string.h>
cc0d08 #include "pgpMem.h"
c06fbf #include "pgpHex.h"
082f8d #include "pgpErrors.h"
dac26c #include "pgpContext.h"
bc5430 #include "pgpUtilitiesPriv.h"
50af5a
6fa076 #include "pgpKeys.h"
bb7ca7 #include "pgpKeyIDPriv.h"
ae979a #include "pgpKDBInt.h"
2caf5a
0a6503 #define kMaxKeyBytes¤   ¤   ¤   8
4ca6b5 /* 0x + str + NULL */
33753a #define kMaxKeyStringLength¤¤   ( 2 + ( kMaxKeyBytes * 2 ) + 1 )
b0af5a
23af5a
4816ea ¤   PGPBoolean
57f448 pgpKeyIDIsValid( PGPKeyID const * id )
d8bb36 {
2912fe ¤   PGPKeyIDPriv const *¤   priv¤   = (PGPKeyIDPriv const *)id;
5667c5 ¤
38c7fc ¤   return( IsntNull( priv ) &&
e10084 ¤   ¤   ( priv->length == 4 || priv->length == 8 ) );
45efe6 }
806a20 #define PGPValidateKeyID( id )¤ PGPValidateParam( pgpKeyIDIsValid( id ) )
3baf5a
e0af5a
98af5a
bc33c8 ¤   static void
caa983 sNewKeyID(
d451c4 ¤   PGPUInt32¤  ¤   length,
7e1b9d ¤   PGPByte const *¤bytes,
f12b74 ¤   PGPKeyID *¤ ¤   outID )
62bb36 {
a40ead ¤   PGPKeyIDPriv *¤ priv¤   = (PGPKeyIDPriv *)outID;
9967c5 ¤
5418a8 ¤   pgpAssert( length == 4 || length == 8 );
02c2c2 ¤   priv->length¤   = length;
cf4468 ¤   priv->reserved¤ = 0;
698d5c ¤   pgpCopyMemory( bytes, priv->bytes, length );
99efe6 }
09af5a
d8af5a
a7af5a
b3c744 ¤   PGPError
7d5085 pgpNewKeyIDFromRawData(
8df9ae ¤   const void *¤   data,
cdbfe4 ¤   PGPSize¤¤   ¤   dataSize,
992b74 ¤   PGPKeyID *¤ ¤   outID )
c7bb36 {
7426d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6a67c5 ¤
ca1e12 ¤   PGPValidateParam( dataSize == 4 || dataSize == 8 );
6167c5 ¤
fd780e ¤   sNewKeyID( dataSize, (PGPByte const *)data, outID );
2467c5 ¤
1adeb7 ¤   return( err );
96efe6 }
942b85 ¤   ¤   ¤   ¤
112b85 ¤   ¤   ¤   ¤
a40335 /*____________________________________________________________________________
dc9a56 ¤   Convert a string into a key id.
--0d33 000f7d571844010022d Page 2 of pgpKeyID.c
2a67c5 ¤
556402 ¤   string must be of the form:
5b4d05 ¤   ¤   0xdddddddd
ea817e ¤   ¤   0xdddddddddddddddd
1daece ¤   ¤   dddddddd
2202f7 ¤   ¤   dddddddddddddddd
d2b0cc ¤   which represents either a 4 byte or 8 byte key id.
87f7f7 ____________________________________________________________________________*/
bc21ab ¤   PGPError·
766c33 PGPGetKeyIDFromString(
25a07a ¤   const char *¤   string,
9d2b74 ¤   PGPKeyID *¤ ¤   outID )
ddbb36 {
ab9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
4a33b2 ¤   PGPSize¤¤   ¤   stringLength;
cb1d2b ¤   const char *¤   cur¤= NULL;
dc6213 ¤   PGPByte *¤  ¤   outCur¤ = NULL;
0be945 ¤   PGPByte¤¤   ¤   keyBytes[ kMaxKeyBytes ];
c3e81e ¤   PGPSize¤¤   ¤   inputRemaining;
ea67c5 ¤
dedebf ¤   PGPValidatePtr( outID );
49ca7c ¤   pgpClearMemory( outID, sizeof( *outID ) );
73e174 ¤   PGPValidatePtr( string );
b367c5 ¤
b0591c ¤   /* optionally starts with "0x" */
609556 ¤   stringLength¤   = strlen( string );
f001de ¤   if ( string[ 0 ] == '0' && string[ 1 ] == 'x' )
19c7a1 ¤   {
9a4e51 ¤   ¤   stringLength¤   -= 2;
2b4dbf ¤   ¤   cur¤¤   ¤   ¤   = string + 2;
819371 ¤   }
4b0e24 ¤   else
efc7a1 ¤   {
24518f ¤   ¤   cur¤¤   = string;
c19371 ¤   }
0067c5 ¤
21b7ab ¤   /* two hex chars for each raw byte */
44dd56 ¤   PGPValidateParam( stringLength == 4 * 2 || stringLength == 8 * 2 );
3167c5 ¤
3d9839 ¤   outCur¤ = &keyBytes[ 0 ];
bc4974 ¤   inputRemaining¤ = stringLength;
1a9d55 ¤   while ( inputRemaining != 0 )
ecc7a1 ¤   {
621c94 ¤   ¤   const char¤ char1¤  = *cur++;
529faa ¤   ¤   const char¤ char2¤  = *cur++;
f81b52 ¤   ¤
9fb8f0 ¤   ¤   inputRemaining¤ -= 2;¤  /* we used 2 bytes */
fe1b52 ¤   ¤
3d4f02 ¤   ¤   PGPValidateParam( pgpIsValidHexChar( char1 ) &&
ef3946 ¤   ¤   ¤   pgpIsValidHexChar( char2 ) );
471b52 ¤   ¤
fa539d ¤   ¤   *outCur++¤  = (pgpHexCharToNibble( char1 ) << 4 ) |
3b0731 ¤   ¤   ¤   ¤   ¤   ¤   pgpHexCharToNibble( char2 );
449371 ¤   }
9467c5 ¤
5fe3c7 ¤   sNewKeyID( stringLength / 2, keyBytes, outID );
99deb7 ¤   return( err );
66efe6 }
05af5a
f61b52 ¤   ¤
92c744 ¤   PGPError
a48b29 PGPGetKeyIDFromKey(
491d0c ¤   PGPKeyRef¤  key,
c0e25c ¤   PGPKeyID *¤ outID )
c7bb36 {
42d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
6cbd10 ¤   RingSet const ·*¤   ringSet;
1967c5 ¤
23debf ¤   PGPValidatePtr( outID );
55ca7c ¤   pgpClearMemory( outID, sizeof( *outID ) );
9bd5b3 ¤   PGPValidateKey( key );
f767c5 ¤
--0019 0007371c3964010022d Page 3 of pgpKeyID.c
e6d535 ¤   ringSet¤= pgpKeyDBRingSet( key->keyDB );
2eaf5a
065f39 ¤   ringKeyID8( ringSet, key->key, NULL, outID );
8d67c5 ¤
5adeb7 ¤   return( err );
39efe6 }
01af5a
39af5a
b1c744 ¤   PGPError
fa92d4 PGPGetKeyIDFromSubKey(
7b3fa4 ¤   PGPSubKeyRef¤   subKey,
602b74 ¤   PGPKeyID *¤ ¤   outID )
8ebb36 {
0ed591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
42bd10 ¤   RingSet const ·*¤   ringSet;
6267c5 ¤
a5debf ¤   PGPValidatePtr( outID );
60ca7c ¤   pgpClearMemory( outID, sizeof( *outID ) );
8e3a11 ¤   PGPValidateSubKey( subKey );
fa67c5 ¤
614d21 ¤   ringSet¤= pgpKeyDBRingSet( subKey->key->keyDB );
e6af5a
8a40d3 ¤   ringKeyID8( ringSet, subKey->subKey, NULL, outID );
3f67c5 ¤
2cdeb7 ¤   return( err );
a5efe6 }
c5af5a
67af5a
7c4e5a ¤   PGPByte const *
2ea0df pgpGetKeyBytes( PGPKeyID const *keyID )
47bb36 {
ac5f1f ¤   PGPKeyIDPriv *¤ priv¤   = (PGPKeyIDPriv *)keyID;
9e67c5 ¤
ea4f78 ¤   return( &priv->bytes[ 0 ] );
d4efe6 }
1baf5a
41af5a
f2c744 ¤   PGPError
2b0b5d PGPGetKeyIDString(
b56625 ¤   PGPKeyID const *¤   keyID,
591ee7 ¤   PGPKeyIDStringType¤ type,
5363f9 ¤   char¤   ¤   ¤   ¤   outString[ 128 ] )
6fbb36 {
c09372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
315f1f ¤   PGPKeyIDPriv *¤ priv¤   = (PGPKeyIDPriv *)keyID;
c767c5 ¤
da310e ¤   PGPValidatePtr( outString );
07c2cc ¤   pgpClearMemory( outString, 128 );
f7c2b5 ¤   PGPValidateKeyID( keyID );
01c449 ¤   PGPValidateParam( type == kPGPKeyIDString_Abbreviated ||
9b7430 ¤   ¤   type == kPGPKeyIDString_Full );
d467c5 ¤
17c6a9 ¤   if ( type == kPGPKeyIDString_Full || priv->length == 4 )
f2c7a1 ¤   {
22a2c0 ¤   ¤   /* all the bytes */
ff6740 ¤   ¤   pgpBytesToHex( priv->bytes, priv->length, TRUE, outString );
d99371 ¤   }
df0e24 ¤   else
95c7a1 ¤   {
727938 ¤   ¤   /* abbreviated version */
5a1b77 ¤   ¤   pgpAssert( priv->length == 8 );
f67cbf ¤   ¤   pgpBytesToHex( priv->bytes + 4, 4, TRUE, outString );
c89371 ¤   }
cd67c5 ¤
40deb7 ¤   return( err );
27efe6 }
f3af5a
f9af5a
62af5a
f7af5a
310335 /*____________________________________________________________________________
735e16 ¤   Compare two key IDs. ·Return 0 if they are the same, -1 if key1 < key2,
--a78d 000adc0dc574010022d Page 4 of pgpKeyID.c
95da85 ¤   1 if key1 > key2.·
fcf7f7 ____________________________________________________________________________*/
309cb9 ¤   PGPInt32·
182a9c PGPCompareKeyIDs(
17a284 ¤   PGPKeyID const *¤   key1,
823358 ¤   PGPKeyID const *¤   key2)
a5bb36 {
f510bc ¤   PGPKeyIDPriv const *¤   priv1¤  = (PGPKeyIDPriv *)key1;
0ba5eb ¤   PGPKeyIDPriv const *¤   priv2¤  = (PGPKeyIDPriv *)key2;
4e67c5 ¤
cb3d54 ¤   pgpAssert( pgpKeyIDIsValid( key1 ) );
6b953a ¤   pgpAssert( pgpKeyIDIsValid( key2 ) );
e367c5 ¤
47f5ac ¤   if ( (! pgpKeyIDIsValid( key1 )) ||
7b056f ¤   ¤   ( ! pgpKeyIDIsValid( key2 )) )
e9abea ¤   ¤   return( 0 );
c467c5 ¤
8dc410 ¤   if ( priv1->length == priv2->length )
90c7a1 ¤   {
be6a79 ¤   ¤   PGPSize¤¤   numBytes¤   = priv1->length;
19505a ¤   ¤   PGPUInt32¤  idx;
8f1b52 ¤   ¤
51541b ¤   ¤   /* compare as if first byte is high order byte */
6265b1 ¤   ¤   for( idx = 0; idx < numBytes; ++idx )
f65b34 ¤   ¤   {
2abd69 ¤   ¤   ¤   if ( priv1->bytes[ idx ] < priv2->bytes[ idx ] )
0a071b ¤   ¤   ¤   ¤   return( -1 );
6c0be1 ¤   ¤   ¤   if ( priv1->bytes[ idx ] > priv2->bytes[ idx ] )
ae2522 ¤   ¤   ¤   ¤   return( 1 );
750fe4 ¤   ¤   }
7d9371 ¤   }
d20e24 ¤   else
2cc7a1 ¤   {
6a162e ¤   ¤   /* unequal sizes 4 vs 8 bytes */
639ced ¤   ¤   PGPByte const *¤ptr1;
617389 ¤   ¤   PGPByte const *¤ptr2;
7b2e82 ¤   ¤   PGPBoolean¤ ¤   priv1Is8Byte¤   = priv1->length == 8;
6a1b52 ¤   ¤
a5109c ¤   ¤   ptr1¤   = &priv1->bytes[ 0 ];
863e3a ¤   ¤   ptr2¤   = &priv2->bytes[ 0 ];
640414 ¤   ¤   if ( priv1Is8Byte )
48d40f ¤   ¤   ¤   ptr1¤   += 4;¤  /* use low order 4 bytes */
a50e1d ¤   ¤   else
0c7f67 ¤   ¤   ¤   ptr2¤   += 4;¤  /* use low order 4 bytes */
691b52 ¤   ¤
9ed5cf ¤   ¤   /* if not the same, arbitrarily say 4 byte ids are < 8 byte IDs */
ec400a ¤   ¤   if ( ! pgpMemoryEqual( ptr1, ptr2, 4 ) )
0a5daf ¤   ¤   ¤   return( priv1Is8Byte ? 1 : -1 );
cc9371 ¤   }
5e67c5 ¤
74ea61 ¤   return( 0 );
63efe6 }
58af5a
0416ea ¤   PGPBoolean
790c86 pgpKeyIDsEqual(
afa284 ¤   PGPKeyID const *¤   key1,
c23358 ¤   PGPKeyID const *¤   key2)
09bb36 {
70af50 ¤   return( PGPCompareKeyIDs( key1, key2 ) == 0 );
6eefe6 }
e0af5a
55af5a
206a25 enum PGPKeyIDType_
cbbb36 {
868e12 ¤   kKeyID4Byte = 13,
360d8d ¤   kKeyID8Byte = 14,
da67c5 ¤
a004ad ¤   PGP_ENUM_FORCE( PGPKeyIDType_ )
0f82f7 };
33b618 PGPENUM_TYPEDEF( PGPKeyIDType_, PGPKeyIDType );
a7af5a
adaf5a
--f63c 000f95672ff4010022d Page 5 of pgpKeyID.c
a70335 /*____________________________________________________________________________
574cd4 ¤   Caution: these exported IDs are used in client software. ·If changed,
65e537 ¤   they will break things like groups, which uses exported key IDs.
64f7f7 ____________________________________________________________________________*/
43c744 ¤   PGPError
3591ef PGPExportKeyID(
4d6625 ¤   PGPKeyID const *¤   keyID,
665554 ¤   PGPByte¤¤   ¤   ¤   exportedData[ kPGPMaxExportedKeyIDSize ],
a2302d ¤   PGPSize *¤  ¤   ¤   exportedLength )
80bb36 {
c49479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
bcb883 ¤   PGPSize¤¤   ¤   ¤   ¤   size¤   = 0;
dd9db0 ¤   PGPKeyIDType¤   ¤   ¤   type;
c27509 ¤   PGPKeyIDPriv const *¤   priv¤   = (PGPKeyIDPriv const *)keyID;
6f67c5 ¤
056f19 ¤   if ( IsntNull( exportedLength ) )
9cf023 ¤   ¤   *exportedLength¤= 0;
8f3b50 ¤   PGPValidatePtr( exportedData );
cbf608 ¤   pgpClearMemory( exportedData, kPGPMaxExportedKeyIDSize );
b2c2b5 ¤   PGPValidateKeyID( keyID );
bb67c5 ¤
c092e0 ¤   /* output one byte to indicate type, followed by bytes */
7d863d ¤   size¤   ¤   = 1 + priv->length;
134c24 ¤   type¤   ¤   = ( priv->length == 4 ) ? kKeyID4Byte : kKeyID8Byte;
fa02d6 ¤   exportedData[ 0 ]¤  = (PGPByte)type;
7f35b1 ¤   pgpCopyMemory( priv->bytes, &exportedData[ 1 ], priv->length );
9267c5 ¤
866f19 ¤   if ( IsntNull( exportedLength ) )
c966f4 ¤   ¤   *exportedLength¤= size;
6d67c5 ¤
a7deb7 ¤   return( err );
97efe6 }
e9af5a
7faf5a
6aaf5a
cfc744 ¤   PGPError
193fc8 PGPImportKeyID(
63166d ¤   void const *¤   dataParam,
714740 ¤   PGPKeyID *¤ ¤   id )
39bb36 {
fd9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
a450fc ¤   PGPKeyIDType¤   type;
8bb7ff ¤   PGPSize¤¤   ¤   length;
1428ef ¤   const PGPByte *¤data;
9d67c5 ¤
ab775f ¤   PGPValidatePtr( id );
bd550b ¤   pgpClearMemory( id, sizeof( *id ) );
468f88 ¤   PGPValidatePtr( dataParam );
2467c5 ¤
3a604a ¤   data = (const PGPByte *) dataParam;
1867c5 ¤
625c4d ¤   type¤   = (PGPKeyIDType)data[ 0 ];
5e6348 ¤   PGPValidateParam( type == kKeyID4Byte || type == kKeyID8Byte );
5467c5 ¤
6fc476 ¤   length¤ = ( type == kKeyID4Byte ) ? 4 : 8;
1b28b5 ¤   sNewKeyID( length, &data[ 1 ], id);
0867c5 ¤
54deb7 ¤   return( err );
f0efe6 }
b5af5a
10af5a
32af5a
52af5a
b6af5a
63af5a
d1af5a
4faf5a
7daf5a
87af5a
78af5a
efaf5a
f9af5a
--6e2d 0016abf08eb4010022d Page 6 of pgpKeyID.c
e0af5a
1aaf5a
17af5a
78af5a
cc7e4d /*__Editor_settings____
f0af5a
a94126 ¤   Local Variables:
587b17 ¤   tab-width: 4
3b0e6c ¤   End:
e85f8c ¤   vi: ts=4 sw=4
7c9e9b ¤   vim: si
6ad062 _____________________*/
--a58a 001920c99ed4010022e Page 1 of pgpKeyIDPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
e27010 ¤   $Id: pgpKeyIDPriv.h,v 1.5.22.1 1998/11/12 03:21:57 heller Exp $
d9f7f7 ____________________________________________________________________________*/
6d12af #ifndef Included_pgpKeyIDPriv_h¤/* [ */
2a4c7a #define Included_pgpKeyIDPriv_h
a0af5a
fbe82c #include "pgpPubTypes.h"
cdaf5a
de6911 /* the non-opaque PGPKeyID */
ae3798 struct PGPKeyIDPriv
79bb36 {
0be26f ¤   PGPByte¤¤   length;
ecf966 ¤   PGPByte¤¤   reserved;
603160 ¤   PGPByte¤¤   bytes[ 32 ];
7582f7 };
29af5a
4f23b6 PGPError¤   pgpNewKeyIDFromRawData( const void *data,
49225b ¤   ¤   ¤   ¤   PGPSize dataSize, PGPKeyID *outID );
4caf5a
20ec2e PGPBoolean¤ pgpKeyIDsEqual( const PGPKeyID *id1, const PGPKeyID *id2 );
6daf5a
eadfc5 PGPByte const *¤pgpGetKeyBytes( PGPKeyID const *keyID );
0caf5a
74ea89 PGPBoolean¤ pgpKeyIDIsValid( PGPKeyID const * id );
3e6a20 #define PGPValidateKeyID( id )¤ PGPValidateParam( pgpKeyIDIsValid( id ) )
02af5a
af1d2b #endif /* ] Included_pgpKeyIDPriv_h */
c6af5a
86af5a
fb7e4d /*__Editor_settings____
34af5a
2b4126 ¤   Local Variables:
dd7b17 ¤   tab-width: 4
000e6c ¤   End:
8c5f8c ¤   vi: ts=4 sw=4
c49e9b ¤   vim: si
92d062 _____________________*/
--9692 000c811fd644010022f Page 1 of pgpKeyIter.c
bc38e5 /*
fc363e ·* pgpKeyIter.c
e9d98d ·* PGP Key Iteration functions
2d775e ·*
0a94ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
5e20c7 ·* All rights reserved
bb775e ·*
3e936c ·* $Id: pgpKeyIter.c,v 1.36.12.1 1998/11/12 03:21:58 heller Exp $
337fe0 */
cdaf5a
10e2ff #include "pgpConfig.h"
edaf5a
06979a #include "pgpKDBInt.h"
1bc26c #include "pgpContext.h"
61af5a
baaf5a
9543e9 /* Internal functions to maintain reference counts. ·Incrementing
24e23c ···or decrementing a refcount on a sub-object will do the same to·
98bd62 ···its parent object (in fact, all superior objects), as a subobject
ed1140 ···cannot exist without its parent. ··
33af5a
266a95 ···When an iterator moves off an object or subobject, must make sure·
c26cb0 ···all child objects are properly adjusted (the decIterxxx functions),
e8c4df ···as the iterator implicitly moves off these subobjects also. */
5eaf5a
492978 static void
2a2fee decKeyRefCount (PGPKeyRef key)
cbbb36 {
e47c7b ¤   if ( IsntNull( key ) )
a2c7a1 ¤   {
354259 ¤   ¤   pgpa( pgpaPGPKeyValid( key ) );
c199bf ¤   ¤   pgpFreeKey(key);
659371 ¤   }
ceefe6 }
27af5a
8a2978 static void
c1ca7e decSubKeyRefCount (PGPSubKeyRef subkey)
9ebb36 {
b8c9eb ····if ( IsntNull( subkey ) )
4f3b37 ····{
134d64 ¤   ¤   pgpa( pgpaPGPSubKeyValid( subkey ) );
d31b52 ¤   ¤
5b62cb ¤   ····subkey->refCount--;
d6882f ¤   ¤   decKeyRefCount (subkey->key);
459371 ¤   }
52efe6 }
2eaf5a
6f2978 static void
b89600 decUserIDRefCount (PGPUserIDRef userid)
f9bb36 {
d60e94 ¤   if ( IsntNull( userid ) )
5dc7a1 ¤   {
8b98d6 ¤   ¤   pgpa( pgpaPGPUserIDValid( userid ) );
1a8e21 ¤   ¤   userid->refCount--;
feaab9 ¤   ¤   decKeyRefCount (userid->key);
739371 ¤   }
ddefe6 }
acaf5a
a42978 static void
812cb7 decCertRefCount (PGPSigRef cert)
09bb36 {
4206b5 ¤   if ( IsntNull( cert ) )
7dc7a1 ¤   {
4ca14c ¤   ¤   pgpa( pgpaPGPCertValid( cert ) );
111b52 ¤   ¤
89ff73 ¤   ¤   cert->refCount--;
0dc537 ¤   ¤   if (cert->type == uidcert)
61042f ¤   ¤   ····decUserIDRefCount (cert->up.userID);
1c0e1d ¤   ¤   else
03c798 ¤   ¤   ····decKeyRefCount (cert->up.key);
a09371 ¤   }
c8efe6 }
--bf9f 0002b1f08b94010022f Page 2 of pgpKeyIter.c
e0af5a
79daaa static void·
47cab2 decIterUIDCert (PGPKeyIterRef iter)
d5bb36 {
817930 ¤   decCertRefCount (iter->uidCert);
038cfd ¤   iter->uidCert = NULL;
aaefe6 }
b0af5a
50daaa static void·
10eebd decIterUserID (PGPKeyIterRef iter)
8cbb36 {
de471c ¤   decIterUIDCert (iter);
7fb43f ¤   decUserIDRefCount (iter->userID);
d1ef38 ¤   iter->userID = NULL;
15efe6 }
71af5a
522978 static void
e80159 decIterSubKey (PGPKeyIterRef iter)
e1bb36 {
34f407 ····decSubKeyRefCount (iter->subKey);
727b2a ¤   iter->subKey = NULL;
73efe6 }
47af5a
85daaa static void·
e1dc95 decIterKey (PGPKeyIterRef iter)
45bb36 {
1d9bc2 ····decIterSubKey (iter);
23ef48 ¤   decIterUserID (iter);
a2ff21 ¤   decKeyRefCount (iter->key);
882cdd ¤   iter->key = NULL;
ceefe6 }
88af5a
38f1ae static PGPError
8c9163 incKeyRefCount (PGPKeyRef key)
5dbb36 {
d47c7b ¤   if ( IsntNull( key ) )
9eebef ¤   ¤   return pgpIncKeyRefCount(key);
63151e ¤   return kPGPError_NoErr;
d9efe6 }
baaf5a
ae2978 static void
45151c incSubKeyRefCount (PGPSubKeyRef subkey)
f0bb36 {
48a6e9 ····incKeyRefCount (subkey->key);
f9ccf6 ¤   subkey->refCount++;
7aefe6 }
77af5a
cd2978 static void
744962 incUserIDRefCount (PGPUserIDRef userid)
d4bb36 {
3c1bc1 ¤   incKeyRefCount (userid->key);
cae507 ¤   userid->refCount++;
39efe6 }
0caf5a
f82978 static void
c14cf6 incCertRefCount (PGPSigRef cert)
f9bb36 {
4299f7 ····if (cert->type == uidcert)
d759f3 ¤   ····incUserIDRefCount (cert->up.userID);
820e24 ¤   else
e47759 ¤   ····incKeyRefCount (cert->up.key);
bca585 ¤   cert->refCount++;
70efe6 }
82af5a
15af5a
e4af5a
858fe2 /* ·Externally visible functions */
37af5a
362a49 /* ·Functions to increment and decrement sub-object reference
2bd992 ¤   counts. */
f5af5a
2b5a72 PGPError ·
--b9fa 000a3421f304010022f Page 3 of pgpKeyIter.c
36af2b pgpIncSubKeyRefCount (PGPSubKeyRef subkey)
f6bb36 {
549756 ····pgpa(pgpaPGPSubKeyValid(subkey));
eccd57 ¤   incSubKeyRefCount (subkey);
d267c5 ¤
272d68 ¤   return( kPGPError_NoErr );
9aefe6 }
c3af5a
075a72 PGPError ·
58f355 pgpIncUserIDRefCount (PGPUserIDRef userid)
98bb36 {
25ca71 ¤   PGPValidateUserID( userid );
e167c5 ¤
156586 ¤   incUserIDRefCount (userid);
2767c5 ¤
9e2d68 ¤   return( kPGPError_NoErr );
22efe6 }
05af5a
5b5a72 PGPError ·
1e7e91 pgpIncSigRefCount (PGPSigRef cert)
77bb36 {
5ec107 ¤   PGPValidateCert( cert );
cb67c5 ¤
ce3b48 ¤   incCertRefCount (cert);
6b67c5 ¤
052d68 ¤   return( kPGPError_NoErr );
ffefe6 }
caaf5a
f15a72 PGPError ·
721c3a pgpFreeSubKey (PGPSubKeyRef subkey)
f6bb36 {
d09756 ····pgpa(pgpaPGPSubKeyValid(subkey));
03869e ····
575992 ¤   PGPValidateSubKey( subkey );
ba67c5 ¤
c1172e ¤   decSubKeyRefCount (subkey);
8a2d68 ¤   return( kPGPError_NoErr );
49efe6 }
9caf5a
e35a72 PGPError ·
9fa2b8 pgpFreeUserID (PGPUserIDRef userid)
52bb36 {
fbca71 ¤   PGPValidateUserID( userid );
7467c5 ¤
62bfff ¤   decUserIDRefCount (userid);
e02d68 ¤   return( kPGPError_NoErr );
a5efe6 }
b2af5a
4c5a72 PGPError ·
c2832a pgpFreeSig (PGPSigRef cert)
82bb36 {
88c107 ¤   PGPValidateCert( cert );
4e67c5 ¤
153349 ¤   decCertRefCount (cert);
3e2d68 ¤   return( kPGPError_NoErr );
78efe6 }
cfaf5a
81af5a
9921ab ¤   PGPError·
da6598 PGPNewKeyIter (
edd6fa ¤   PGPKeyListRef¤  keys,
71235a ¤   PGPKeyIterRef *¤outRef)
edbb36 {
e462d2 ¤   PGPKeyIter * newIter = NULL;
7426d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2b628a ¤   PGPContextRef¤  context¤= PGPGetKeyListContext( keys );
18af5a
d43c76 ¤   PGPValidatePtr( outRef );
543652 ¤   *outRef¤= NULL;
85a961 ¤   PGPValidateKeyList( keys );
a7af5a
a38375 ¤   newIter = (PGPKeyIter *)pgpContextMemAlloc(
--8119 00097b76e604010022f Page 4 of pgpKeyIter.c
430fc3 ¤   ¤   context, sizeof (PGPKeyIter), kPGPMemoryMgrFlags_Clear );
c44168 ¤   if ( IsntNull( newIter ) )
42c7a1 ¤   {
aa8881 ¤   ¤   newIter->magic¤ = kPGPKeyIterMagic;
3cfa4a ¤   ····newIter->nextIterInList = keys->firstIterInList;
420d54 ¤   ¤   newIter->prevIterInList = NULL;
1c27f4 ¤   ¤   if (newIter->nextIterInList)
b3533b ¤   ¤   ····newIter->nextIterInList->prevIterInList = newIter;
40452a ¤   ¤   keys->firstIterInList = newIter;
ab9348 ¤   ¤   PGPIncKeyListRefCount(keys);
1aee12 ¤   ¤   newIter->keyList = keys;
56af5a
e9321d ¤   ¤   newIter->keyIndex = -1;
b56b84 ¤   ¤   newIter->key = NULL;
0f6fb9 ¤   ¤   newIter->subKey = NULL;
6cfbab ¤   ¤   newIter->userID = NULL;
132afb ¤   ¤   newIter->uidCert = NULL;
bd1b52 ¤   ¤
a4d0c5 ¤   ¤   *outRef¤= newIter;
d39371 ¤   }
990e24 ¤   else
a3c7a1 ¤   {
9917a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
759371 ¤   }
a267c5 ¤
504c5f ¤   pgpAssertErrWithPtr( err, *outRef );
c6deb7 ¤   return( err );
24efe6 }
e8af5a
40af5a
503bc8 ¤   PGPError ·
0936d7 PGPCopyKeyIter (
bdb1b2 ¤   PGPKeyIterRef ¤ orig,
e9235a ¤   PGPKeyIterRef *¤outRef)
0abb36 {
1bc120 ¤   PGPKeyIterRef¤  newIter = NULL;
9c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
56af5a
963c76 ¤   PGPValidatePtr( outRef );
ad3652 ¤   *outRef¤= NULL;
6d181e ¤   PGPValidateKeyIter( orig );
8b67c5 ¤
1a4250 ¤   err¤= PGPNewKeyIter (orig->keyList, &newIter );
23f1e7 ¤   if ( IsntPGPError( err ) )
40c7a1 ¤   {
a6c244 ¤   ¤   newIter->keyIndex = orig->keyIndex;
82af5a
487f50 ¤   ¤   newIter->key = orig->key;
8c4605 ¤   ¤   if (newIter->key)·
7da04d ¤   ¤   ¤   incKeyRefCount (newIter->key);
b0af5a
0cbb2c ¤   ¤   newIter->subKey = orig->subKey;
80b7ea ¤   ¤   if (newIter->subKey)
a75560 ¤   ¤   ····incSubKeyRefCount (newIter->subKey);
eaaf5a
210a37 ¤   ¤   newIter->userID = orig->userID;
930a44 ¤   ¤   if (newIter->userID)
39ca0c ¤   ¤   ····incUserIDRefCount (newIter->userID);
e1af5a
c555c8 ¤   ¤   newIter->uidCert = orig->uidCert;
00effb ¤   ¤   if (newIter->uidCert)
44cd53 ¤   ¤   ····incCertRefCount (newIter->uidCert);
f4af5a
4d7b73 ¤   ¤   *outRef = newIter;
009371 ¤   }
5f67c5 ¤
2c4c5f ¤   pgpAssertErrWithPtr( err, *outRef );
8d5ea8 ¤   return err;
d6efe6 }
3aaf5a
26af5a
978de9 PGPError·
--2ebd 000cdb54b574010022f Page 5 of pgpKeyIter.c
c09bc9 PGPFreeKeyIter (PGPKeyIterRef iter)
ccbb36 {
1bd04d ¤   PGPContextRef¤  context¤= NULL;
8a67c5 ¤
7dfe82 ¤   PGPValidateKeyIter( iter );
cbabb0 ¤   context¤= PGPGetKeyIterContext( iter );
0baf5a
de5e32 ¤   if (iter->keyList) {
9e647f ¤   ····if (iter->prevIterInList)
4d04f8 ¤   ¤   ····iter->prevIterInList->nextIterInList = iter->nextIterInList;
a80e1d ¤   ¤   else
347729 ¤   ¤   ····iter->keyList->firstIterInList = iter->nextIterInList;
294648 ¤   ¤   if (iter->nextIterInList)
79103c ¤   ¤   ····iter->nextIterInList->prevIterInList = iter->prevIterInList;
4099a5 ¤   ¤   PGPFreeKeyList (iter->keyList);
de9371 ¤   }
b7f6b1 ¤   decIterKey (iter);
92517a ¤   iter->magic¤¤   = ~ iter->magic;¤   /* mark as invalid */
4b28a7 ¤   pgpContextMemFree( context, iter);
7b67c5 ¤
f52d68 ¤   return( kPGPError_NoErr );
21efe6 }
671b52 ¤   ¤
efaf5a
ca30fb PGPInt32·
70f5a1 PGPKeyIterIndex (PGPKeyIterRef iter)
2bbb36 {
a637fe ···¤pgpa(pgpaPGPKeyIterValid(iter));
bd3967 ···¤
25e6ca ¤   if ( ! pgpKeyIterIsValid( iter ) )
67abea ¤   ¤   return( 0 );
071b52 ¤   ¤
d3cf9c ¤   return iter->keyIndex;
ceefe6 }
e9af5a
1faf5a
7b8de9 PGPError·
497930 PGPKeyIterRewind (PGPKeyIterRef iter)
f0bb36 {
7ff0d0 ¤   pgpa(pgpaPGPKeyIterValid(iter));
a7fe82 ¤   PGPValidateKeyIter( iter );
3a67c5 ¤
095e32 ¤   if (iter->keyList) {
de1450 ¤   ¤   decIterKey (iter);
3c12d3 ¤   ¤   iter->keyIndex = -1;
95eb68 ¤   ¤   iter->key = NULL;
7e9371 ¤   }
2267c5 ¤
8f2d68 ¤   return( kPGPError_NoErr );
f1efe6 }
7baf5a
7baf5a
2e30fb PGPInt32·
4790aa PGPKeyIterSeek (PGPKeyIterRef iter, PGPKeyRef key)
a2bb36 {
a8729b ¤   PGPKey¤ ¤   **keys;
d36bf9 ¤   long¤   ¤   i;
9eaf5a
9afe82 ¤   PGPValidateKeyIter( iter );
02d5b3 ¤   PGPValidateKey( key );
bc67c5 ¤
c3f6b1 ¤   decIterKey (iter);
4d268e ¤   iter->keyIndex = -1;
cb2cdd ¤   iter->key = NULL;
8a0a66 ¤   incKeyRefCount(key);
c3e863 ¤   keys = iter->keyList->keys;
dbe31e ¤   if (iter->keyList && (keys = iter->keyList->keys) != NULL) {
22f1ac ¤   ····for (i = 0; i < iter->keyList->keyCount; i++) {
f21a68 ¤   ¤   ····if (keys[i] == key) {
2019ec ¤   ¤   ¤   ····iter->keyIndex = i;
6da1cf ¤   ¤   ¤   ¤   iter->key = key;
cdf622 ¤   ¤   ¤   ¤   break;
--66f0 0002c4d9c7d4010022f Page 6 of pgpKeyIter.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
959371 ¤   }
70cf9c ¤   return iter->keyIndex;
0cefe6 }
41af5a
79af5a
5f8de9 PGPError·
9faa48 PGPKeyIterMove (
5e9fc2 ¤   PGPKeyIterRef¤  iter,
816116 ¤   PGPInt32¤   ¤   relOffset,
8f9403 ¤   PGPKeyRef *¤¤   outRef )
c1bb36 {
56e09e ····long ······¤¤   newOffset;
a321d7 ¤   PGPKeyListRef¤  keylist = NULL;
429372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
84af5a
45f0d0 ¤   pgpa(pgpaPGPKeyIterValid(iter));
ecf2e2 ¤   pgpAssertAddrValid( outRef, PGPKeyRef );
ac67c5 ¤
823c76 ¤   PGPValidatePtr( outRef );
e43652 ¤   *outRef¤= NULL;
7cfe82 ¤   PGPValidateKeyIter( iter );
b6af5a
8267c5 ¤
be636f ¤   if ( IsntNull( iter->keyList ) )
d0c7a1 ¤   {
218c70 ¤   ¤   keylist¤¤   = iter->keyList;
35608a ¤   ¤   newOffset¤  = iter->keyIndex + relOffset;
a2af5a
89abde ¤   ¤   /* ·Check for removed key */
fb1a18 ¤   ····if ( IsntNull( iter->key ) && iter->keyIndex >= 0 &&
8e75b7 ¤   ¤   ¤   ¤   ( iter->keyIndex >= keylist->keyCount ||
68c3e3 ¤   ····¤   ¤   ··keylist->keys[iter->keyIndex] != iter->key ) )
65a7a2 ¤   ····{
a29879 ¤   ¤   ····/* key removed from keylist */·
647b14 ¤   ¤   ····if (relOffset == 0)·
f2f776 ¤   ¤   ¤   {
900d05 ¤   ¤   ¤   ¤   /* pgpFixBeforeShip( "this is probably wrong" ); */
3d18df ¤   ¤   ¤   ¤   err¤= kPGPError_EndOfIteration;
d41397 ¤   ¤   ¤   ¤   return( err );
94a3a6 ¤   ¤   ¤   }
06250f ¤   ¤   ¤   else if (relOffset > 0)
4a47a5 ¤   ¤   ¤   ····newOffset--;
010fe4 ¤   ¤   }
3faf5a
0d1450 ¤   ¤   decIterKey (iter);
d1c0e3 ¤   ¤   iter->keyIndex = newOffset;
eabf39 ¤   ¤   if (newOffset >= 0 && newOffset < keylist->keyCount)
055b34 ¤   ¤   {
bbb995 ¤   ¤   ¤   iter->key = keylist->keys[newOffset];
f49008 ¤   ¤   ¤   incKeyRefCount(iter->key);
370fe4 ¤   ¤   }
b50e1d ¤   ¤   else
805b34 ¤   ¤   {
9e623c ¤   ¤   ¤   iter->key = NULL;
780fe4 ¤   ¤   }
259371 ¤   }
1767c5 ¤
e674f5 ¤   *outRef¤= iter->key;
7c0589 ¤   if ( IsNull( iter->key ) )
2888e9 ¤   ¤   err¤= kPGPError_EndOfIteration;
7e1b52 ¤   ¤
cf5ea8 ¤   return err;
d1efe6 }
00af5a
beaf5a
418de9 PGPError·
25958a PGPKeyIterNext (
e09fc2 ¤   PGPKeyIterRef¤  iter,
664e1b ¤   PGPKeyRef *¤¤   outRef)
2cbb36 {
--befe 000a584ca834010022f Page 7 of pgpKeyIter.c
a326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
0467c5 ¤
9f3c76 ¤   PGPValidatePtr( outRef );
5b3652 ¤   *outRef¤= NULL;
f5fe82 ¤   PGPValidateKeyIter( iter );
ba67c5 ¤
f7bec0 ¤   err¤= PGPKeyIterMove(iter, 1, outRef );
bc67c5 ¤
ce4c5f ¤   pgpAssertErrWithPtr( err, *outRef );
40deb7 ¤   return( err );
6cefe6 }
33af5a
d7af5a
428de9 PGPError·
0d0941 PGPKeyIterPrev (
bc9fc2 ¤   PGPKeyIterRef¤  iter,
414e1b ¤   PGPKeyRef *¤¤   outRef)
b6bb36 {
eb26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3a67c5 ¤
4f3c76 ¤   PGPValidatePtr( outRef );
1c3652 ¤   *outRef¤= NULL;
6cfe82 ¤   PGPValidateKeyIter( iter );
4267c5 ¤
710a17 ¤   err¤= PGPKeyIterMove( iter, -1, outRef);
5067c5 ¤
b84c5f ¤   pgpAssertErrWithPtr( err, *outRef );
b9deb7 ¤   return( err );
80efe6 }
2baf5a
b4af5a
95af5a
c08de9 PGPError·
272fe5 PGPKeyIterKey (
b59fc2 ¤   PGPKeyIterRef¤  iter,
3b4e1b ¤   PGPKeyRef *¤¤   outRef)
cbbb36 {
f626d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9d67c5 ¤
92f0d0 ¤   pgpa(pgpaPGPKeyIterValid(iter));
4ef2e2 ¤   pgpAssertAddrValid( outRef, PGPKeyRef );
2667c5 ¤
fc3c76 ¤   PGPValidatePtr( outRef );
e13652 ¤   *outRef¤= NULL;
7bfe82 ¤   PGPValidateKeyIter( iter );
9b67c5 ¤
eb64e1 ¤   /* pgpFixBeforeShip( "what if key has been deleted" ) */
1e0589 ¤   if ( IsNull( iter->key ) )
c8c7a1 ¤   {
9288e9 ¤   ¤   err¤= kPGPError_EndOfIteration;
439371 ¤   }
6c67c5 ¤
3574f5 ¤   *outRef¤= iter->key;
025ea8 ¤   return err;
8fefe6 }
63af5a
c08de9 PGPError·
40a152 PGPKeyIterSubKey (
509fc2 ¤   PGPKeyIterRef¤  iter,
19ff6e ¤   PGPSubKeyRef *¤ outRef)
76bb36 {
aa26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a167c5 ¤
e03c76 ¤   PGPValidatePtr( outRef );
063652 ¤   *outRef¤= NULL;
08fe82 ¤   PGPValidateKeyIter( iter );
5e67c5 ¤
7063fd ¤   if ( IsNull( iter->subKey ) )
86c7a1 ¤   {
e588e9 ¤   ¤   err¤= kPGPError_EndOfIteration;
c19371 ¤   }
a567c5 ¤
--7a17 000b226a2d14010022f Page 8 of pgpKeyIter.c
2c51cd ¤   *outRef¤= iter->subKey;
434c5f ¤   pgpAssertErrWithPtr( err, *outRef );
d25ea8 ¤   return err;
817889 } ···
06af5a
2f8de9 PGPError·
50ed9b PGPKeyIterUserID (
e49fc2 ¤   PGPKeyIterRef¤  iter,
9a6554 ¤   PGPUserIDRef *¤ outRef )
7bbb36 {
f226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9367c5 ¤
4d3c76 ¤   PGPValidatePtr( outRef );
263652 ¤   *outRef¤= NULL;
b9fe82 ¤   PGPValidateKeyIter( iter );
9167c5 ¤
7ff627 ¤   if ( IsNull( iter->userID ) )
08c7a1 ¤   {
8c88e9 ¤   ¤   err¤= kPGPError_EndOfIteration;
0c9371 ¤   }
f467c5 ¤
e5ec63 ¤   *outRef¤= iter->userID;
f64c5f ¤   pgpAssertErrWithPtr( err, *outRef );
655ea8 ¤   return err;
ddefe6 }
1eaf5a
8daf5a
758de9 PGPError·
6256de PGPKeyIterSig (
2c9fc2 ¤   PGPKeyIterRef¤  iter,
0fb01b ¤   PGPSigRef *¤outRef )
0cbb36 {
1026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7f67c5 ¤
05f0d0 ¤   pgpa(pgpaPGPKeyIterValid(iter));
5862c3 ¤   pgpAssertAddrValid( outRef, PGPSigRef );
43a4ab ¤   ·
803c76 ¤   PGPValidatePtr( outRef );
043652 ¤   *outRef¤= NULL;
f2fe82 ¤   PGPValidateKeyIter( iter );
5f67c5 ¤
599b31 ¤   if ( IsNull( iter->uidCert ) )
a7c7a1 ¤   {
c888e9 ¤   ¤   err¤= kPGPError_EndOfIteration;
5a9371 ¤   }
0e67c5 ¤
df2cac ¤   *outRef¤= iter->uidCert;
844c5f ¤   pgpAssertErrWithPtr( err, *outRef );
da5ea8 ¤   return err;
92efe6 }
97af5a
9d8de9 PGPError·
6db8be PGPKeyIterNextSubKey (
d89fc2 ¤   PGPKeyIterRef¤  iter,
25b098 ¤   PGPSubKeyRef *¤ outRef )
6abb36 {
63d4a1 ¤   PGPKey¤ ¤   ¤   *key;
c01da3 ¤   PGPSubKey ······*next = NULL;
8891a1 ¤   PGPError¤   ¤   err¤= kPGPError_EndOfIteration;
01af5a
c33c76 ¤   PGPValidatePtr( outRef );
fb3652 ¤   *outRef¤= NULL;
c9fe82 ¤   PGPValidateKeyIter( iter );
3567c5 ¤
a53652 ¤   *outRef¤= NULL;
8f1b52 ¤   ¤
e07028 ¤   key = iter->key;
970cec ¤   if (!iter->subKey)
5fec28 ¤   ¤   next = (PGPSubKeyRef ) key->subKeys.next;
7c0e24 ¤   else
9bd171 ¤   ¤   next = iter->subKey->next;
b2af5a
--ec59 0007ee6181f4010022f Page 9 of pgpKeyIter.c
1fc43f ¤   while (next != (PGPSubKeyRef ) &key->subKeys)
13c7a1 ¤   {
700986 ¤   ¤   if (next->removed)
322133 ¤   ¤   ¤   next = next->next;
8a0e1d ¤   ¤   else
f65b34 ¤   ¤   {
10259e ¤   ¤   ····decIterSubKey (iter);
6c7575 ¤   ¤   ····iter->subKey = next;
17246f ¤   ¤   ¤   incSubKeyRefCount (next);
9f87c7 ¤   ¤   ¤
969500 ¤   ¤   ¤   *outRef¤= next;
5c5403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
0dcdcb ¤   ¤   ¤   break;
670fe4 ¤   ¤   }
8f9371 ¤   }
05869e ····
2de0b2 ····pgpAssertErrWithPtr( err, *outRef );
7d9779 ····return( err );
d8efe6 }
1daf5a
74af5a
820335 /*____________________________________________________________________________
3c570c ¤   Get the first subkey on a key.
4b67c5 ¤
98bd88 ¤   If the key doesn't have a subkey, then return kPGPError_ItemNotFound.
14f7f7 ____________________________________________________________________________*/
7fc744 ¤   PGPError
7ccdba pgpGetFirstSubKey(
dfcd9b ¤   PGPKeyRef¤  ¤   key,
cb3762 ¤   PGPSubKeyRef *¤ outSubKey )
8fbb36 {
4aff31 ¤   PGPSubKeyRef¤   subKey¤ = NULL;
169372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
4daf5a
98c29c ¤   PGPValidatePtr(outSubKey);
f62a11 ¤   *outSubKey = NULL;
5daf5a
be89df ¤   subKey = (PGPSubKeyRef)key->subKeys.next;
489f67 ¤   while (¤subKey != (PGPSubKeyRef)&key->subKeys &&
c011c7 ¤   ¤   ¤   subKey->removed)
2ac7a1 ¤   {
1d0ff9 ¤   ¤   subKey = subKey->next;
449371 ¤   }
aaaf5a
4c5a5b ¤   if (subKey != (PGPSubKeyRef)&key->subKeys)
0bc7a1 ¤   {
05673c ¤   ¤   *outSubKey = subKey;
b09371 ¤   }
0267c5 ¤
fca128 ¤   if ( IsNull( *outSubKey ) )
b6c03d ···¤¤   err¤= kPGPError_ItemNotFound;
dd8d35 ···¤¤
325ea8 ¤   return err;
95efe6 }
fbaf5a
8f8de9 PGPError·
70dbcd PGPKeyIterPrevSubKey (
109fc2 ¤   PGPKeyIterRef¤  iter,
44b098 ¤   PGPSubKeyRef *¤ outRef )
49bb36 {
1215ed ¤   PGPKey¤ ¤   *key;
6c2652 ¤   PGPSubKey ··*prev;
3bfaa6 ¤   PGPError¤   err¤= kPGPError_EndOfIteration;
f4af5a
a03c76 ¤   PGPValidatePtr( outRef );
443652 ¤   *outRef¤= NULL;
b0fe82 ¤   PGPValidateKeyIter( iter );
841b52 ¤   ¤
e47028 ¤   key = iter->key;
960cec ¤   if (!iter->subKey)
2e2a35 ¤   ¤   prev = (PGPSubKeyRef ) key->subKeys.prev;
7e0e24 ¤   else
--4970 000fcc2ac714010022f Page 10 of pgpKeyIter.c
bcb856 ¤   ¤   prev = iter->subKey->prev;
d3af5a
981fb5 ¤   while (prev != (PGPSubKeyRef ) &key->subKeys)
d3c7a1 ¤   {
ab82b7 ¤   ¤   if (prev->removed)
052348 ¤   ¤   ¤   prev = prev->prev;
920e1d ¤   ¤   else
405b34 ¤   ¤   {
5c259e ¤   ¤   ····decIterSubKey (iter);
21d9fa ¤   ¤   ¤   iter->subKey = prev;
ffb8a4 ¤   ¤   ¤   incSubKeyRefCount (prev);
149718 ¤   ¤   ¤   *outRef¤= prev;
505403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
b7cdcb ¤   ¤   ¤   break;
930fe4 ¤   ¤   }
539371 ¤   }
cfaf5a
19e0b2 ····pgpAssertErrWithPtr( err, *outRef );
139779 ····return( err );
84efe6 }
25af5a
2daf5a
ae21ab ¤   PGPError·
1b35fc PGPKeyIterRewindSubKey (PGPKeyIterRef iter)
6ebb36 {
4ffe82 ¤   PGPValidateKeyIter( iter );
de67c5 ¤
887b5a ¤   decIterSubKey (iter);
b22d68 ¤   return( kPGPError_NoErr );
c5efe6 }
2daf5a
f8af5a
c58de9 PGPError·
b6f477 PGPKeyIterNextUserID (
9c9fc2 ¤   PGPKeyIterRef¤  iter,
4f6554 ¤   PGPUserIDRef *¤ outRef )
34bb36 {
a2d4a1 ¤   PGPKey¤ ¤   ¤   *key;
03b7cb ¤   PGPUserID ······*next = NULL;
8891a1 ¤   PGPError¤   ¤   err¤= kPGPError_EndOfIteration;
27af5a
c03c76 ¤   PGPValidatePtr( outRef );
b83652 ¤   *outRef¤= NULL;
b8fe82 ¤   PGPValidateKeyIter( iter );
531b52 ¤   ¤
9e7028 ¤   key = iter->key;
92b142 ¤   if (!iter->userID)
087729 ¤   ¤   next = (PGPUserIDRef ) key->userIDs.next;
b40e24 ¤   else
064ae1 ¤   ¤   next = iter->userID->next;
97af5a
32229e ¤   while (next != (PGPUserIDRef ) &key->userIDs)
d2c7a1 ¤   {
5f0986 ¤   ¤   if (next->removed)
7f2133 ¤   ¤   ¤   next = next->next;
d40e1d ¤   ¤   else
f35b34 ¤   ¤   {
dcb18c ¤   ¤   ····decIterUserID (iter);
05e167 ¤   ¤   ····iter->userID = next;
2d28da ¤   ¤   ¤   incUserIDRefCount (next);
6b9500 ¤   ¤   ¤   *outRef¤= next;
6f5403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
15cdcb ¤   ¤   ¤   break;
480fe4 ¤   ¤   }
3e9371 ¤   }
f3af5a
65e0b2 ····pgpAssertErrWithPtr( err, *outRef );
66deb7 ¤   return( err );
14efe6 }
38af5a
efaf5a
fc8de9 PGPError·
--72d2 000ee6c0b214010022f Page 11 of pgpKeyIter.c
609704 PGPKeyIterPrevUserID (
01b9cc ¤   PGPKeyIterRef ¤ iter,
f9a68d ¤   PGPUserIDRef *¤ outRef)
31bb36 {
3a15ed ¤   PGPKey¤ ¤   *key;
dd1555 ¤   PGPUserID ··*prev;
c491a1 ¤   PGPError¤   ¤   err¤= kPGPError_EndOfIteration;
02af5a
9ef0d0 ¤   pgpa(pgpaPGPKeyIterValid(iter));
c39328 ¤   pgpAssertAddrValid( outRef, PGPUserIDRef );
7067c5 ¤
c73c76 ¤   PGPValidatePtr( outRef );
3a3652 ¤   *outRef¤= NULL;
abfe82 ¤   PGPValidateKeyIter( iter );
8a1b52 ¤   ¤
f37028 ¤   key = iter->key;
2ab142 ¤   if (!iter->userID)
37b134 ¤   ¤   prev = (PGPUserIDRef ) key->userIDs.prev;
480e24 ¤   else
e823c6 ¤   ¤   prev = iter->userID->prev;
b7af5a
7ef914 ¤   while (prev != (PGPUserIDRef ) &key->userIDs)
9fc7a1 ¤   {
8682b7 ¤   ¤   if (prev->removed)
e82348 ¤   ¤   ¤   prev = prev->prev;
b20e1d ¤   ¤   else
4c5b34 ¤   ¤   {
1bb18c ¤   ¤   ····decIterUserID (iter);
da4de8 ¤   ¤   ¤   iter->userID = prev;
38b411 ¤   ¤   ¤   incUserIDRefCount (prev);
b09718 ¤   ¤   ¤   *outRef¤= prev;
515403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
0ccdcb ¤   ¤   ¤   break;
f80fe4 ¤   ¤   }
419371 ¤   }
b367c5 ¤
04e0b2 ····pgpAssertErrWithPtr( err, *outRef );
47deb7 ¤   return( err );
c1efe6 }
70af5a
7eaf5a
0e8de9 PGPError·
e9da18 PGPKeyIterRewindUserID (PGPKeyIterRef iter)
78bb36 {
dafe82 ¤   PGPValidateKeyIter( iter );
6467c5 ¤
63ef48 ¤   decIterUserID (iter);
8567c5 ¤
7b2d68 ¤   return( kPGPError_NoErr );
fcefe6 }
22af5a
5daf5a
548de9 PGPError·
38883e PGPKeyIterNextUIDSig (
2f9fc2 ¤   PGPKeyIterRef¤  iter,
24b01b ¤   PGPSigRef *¤outRef )
09bb36 {
e1d4a1 ¤   PGPKey¤ ¤   ¤   *key;
60de84 ¤   PGPUserID¤  ¤   *userid;
7461f3 ¤   PGPSig ········*next;
ac91a1 ¤   PGPError¤   ¤   err¤= kPGPError_EndOfIteration;
57af5a
c13c76 ¤   PGPValidatePtr( outRef );
433652 ¤   *outRef¤= NULL;
affe82 ¤   PGPValidateKeyIter( iter );
2267c5 ¤
4fe45b ¤   if ( IsNull( iter->userID ) ||
d383eb ¤   ¤   ¤   iter->userID->removed)
a6c7a1 ¤   {
9262b5 ¤   ¤   return kPGPError_BadParams;
e89371 ¤   }
ee1b52 ¤   ¤
--6184 0003877ec104010022f Page 12 of pgpKeyIter.c
6f7028 ¤   key = iter->key;
258129 ¤   userid = iter->userID;
058a76 ¤   if (!iter->uidCert)
581d35 ¤   ¤   next = (PGPSigRef ) userid->certs.next;
a00e24 ¤   else
3eac6e ¤   ¤   next = iter->uidCert->next;
6aaf5a
107e18 ¤   while (next != (PGPSigRef ) &userid->certs)
2cc7a1 ¤   {
3b0986 ¤   ¤   if (next->removed)
ee2133 ¤   ¤   ¤   next = next->next;
e60e1d ¤   ¤   else
4a5b34 ¤   ¤   {
e9c76a ¤   ¤   ····decIterUIDCert (iter);
e11d62 ¤   ¤   ¤   iter->uidCert = next;
c3dbba ¤   ¤   ¤   incCertRefCount (next);;
969500 ¤   ¤   ¤   *outRef¤= next;
065403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
73cdcb ¤   ¤   ¤   break;
690fe4 ¤   ¤   }
b69371 ¤   }
8367c5 ¤
684c5f ¤   pgpAssertErrWithPtr( err, *outRef );
2d5ea8 ¤   return err;
68efe6 }
d4af5a
faaf5a
308de9 PGPError·
cceb4d PGPKeyIterPrevUIDSig (
a09fc2 ¤   PGPKeyIterRef¤  iter,
71b01b ¤   PGPSigRef *¤outRef )
31bb36 {
5cd4a1 ¤   PGPKey¤ ¤   ¤   *key;
11de84 ¤   PGPUserID¤  ¤   *userid;
5963eb ¤   PGPSig ········*prev;
e991a1 ¤   PGPError¤   ¤   err¤= kPGPError_EndOfIteration;
91af5a
d5f0d0 ¤   pgpa(pgpaPGPKeyIterValid(iter));
e562c3 ¤   pgpAssertAddrValid( outRef, PGPSigRef );
9f67c5 ¤
ca3c76 ¤   PGPValidatePtr( outRef );
b03652 ¤   *outRef¤= NULL;
eefe82 ¤   PGPValidateKeyIter( iter );
0867c5 ¤
09b618 ¤   if ( !iter->userID || iter->userID->removed)
8c62b5 ¤   ¤   return kPGPError_BadParams;
c61b52 ¤   ¤
cb7028 ¤   key = iter->key;
778129 ¤   userid = iter->userID;
628a76 ¤   if (!iter->uidCert)
9434a4 ¤   ¤   prev = (PGPSigRef ) userid->certs.prev;
470e24 ¤   else
a16769 ¤   ¤   prev = iter->uidCert->prev;
81af5a
9e15b4 ¤   while (prev != (PGPSigRef ) &userid->certs)
9cc7a1 ¤   {
3f82b7 ¤   ¤   if (prev->removed)
be2348 ¤   ¤   ¤   prev = prev->prev;
9d0e1d ¤   ¤   else
b25b34 ¤   ¤   {
4ac76a ¤   ¤   ····decIterUIDCert (iter);
711f7a ¤   ¤   ¤   iter->uidCert = prev;
1fe3c6 ¤   ¤   ¤   incCertRefCount (prev);
655403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
5c9718 ¤   ¤   ¤   *outRef¤= prev;
12cdcb ¤   ¤   ¤   break;
cd0fe4 ¤   ¤   }
b29371 ¤   }
cc67c5 ¤
7d4c5f ¤   pgpAssertErrWithPtr( err, *outRef );
245ea8 ¤   return err;
38efe6 }
--0190 0017ecd5f304010022f Page 13 of pgpKeyIter.c
e0af5a
1aaf5a
f28de9 PGPError·
c6de07 PGPKeyIterRewindUIDSig (PGPKeyIterRef iter)
bcbb36 {
72fe82 ¤   PGPValidateKeyIter( iter );
6767c5 ¤
70bf05 ¤   if ( iter->userID && !iter->userID->removed)
b25334 ¤   ¤   decIterUIDCert (iter);
592d68 ¤   return( kPGPError_NoErr );
e3efe6 }
24af5a
8eaf5a
86af5a
d53607 /* ·Internal functions */
fbaf5a
c9026f /* ·Adjust iterators when a key is added to or removed from a keylist */·
2aaf5a
c8314a void
e3c45d pgpKeyIterAddKey (PGPKeyListRef keys, long idx)
02bb36 {
02d971 ¤   PGPKeyIterRef iter;
9faf5a
e15777 ¤   pgpa(pgpaPGPKeyListValid(keys));
f5c7a0 ¤   for (iter = keys->firstIterInList; iter; iter = iter->nextIterInList)
1dc7a1 ¤   {
452d73 ¤   ¤   if (iter->key == keys->keys[idx])
c06d4d ¤   ¤   ¤   iter->keyIndex = idx;
874de8 ¤   ¤   else if (iter->keyIndex > idx)
ceae55 ¤   ¤   ¤   iter->keyIndex++;
86ac26 ¤   ¤   else if (iter->keyIndex == idx && keys->order != kPGPAnyOrdering
3d5714 ¤   ¤   ¤   ¤   ¤   && iter->key != NULL
d413f6 ¤   ¤   ¤   ¤   ¤   && PGPCompareKeys(iter->key, keys->keys[idx],
360ac3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keys->order) > 0)
ebae55 ¤   ¤   ¤   iter->keyIndex++;
7b9371 ¤   }
80efe6 }
eaaf5a
b2314a void
1d0aab pgpKeyIterRemoveKey (PGPKeyListRef keys, long idx)
c0bb36 {
8dd971 ¤   PGPKeyIterRef iter;
aaaf5a
8e5777 ¤   pgpa(pgpaPGPKeyListValid(keys));
2ec7a0 ¤   for (iter = keys->firstIterInList; iter; iter = iter->nextIterInList)
9bf927 ¤   ¤   if (iter->keyIndex > idx)
573316 ¤   ¤   ¤   iter->keyIndex--;
e5efe6 }
72af5a
bcaf5a
adaf5a
4d38e5 /*
1ae6c5 ·* Local Variables:
a19b19 ·* tab-width: 4
87e7a4 ·* End:
42b612 ·* vi: ts=4 sw=4
3d6c42 ·* vim: si
7c495d ·*/
7eaf5a
--5d2c 0006cee202940100230 Page 1 of pgpKeyLib.c
bc38e5 /*
012046 ·* pgpKeyLib.c
8288f7 ·* Initialization and cleanup functions related to the keydb library
f4775e ·*
c494ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
8920c7 ·* All rights reserved
27775e ·*
9483b0 ·* $Id: pgpKeyLib.c,v 1.105.10.1 1998/11/12 03:21:59 heller Exp $
8d495d ·*/
5baf5a
f3e2ff #include "pgpConfig.h"
a5af5a
fdabff #if HAVE_UNISTD_H
da17c2 #include <unistd.h>
dc7454 #endif
1baf5a
2caf5a
e4c26c #include "pgpContext.h"
1a711b #include "pgpKeyDB.h"
c4a146 #include "pgpDebug.h"
05979a #include "pgpKDBInt.h"
a58b0d #include "pgpEncodePriv.h"
930d6d #include "pgpEnv.h"
222f8d #include "pgpErrors.h"
d97157 #include "pgpFileNames.h"
ffa4b2 #include "pgpFileRef.h"
ea894b #include "pgpFileSpec.h"
192c96 #include "pgpRandomX9_17.h"
e0adc0 #include "pgpRandomPoolPriv.h"
ccc77e #include "pgpRndSeed.h"
ec806a #include "pgpRngRead.h"
e7f5ab #include "pgpSigSpec.h"
90ae6d #include "pgpTrstPkt.h"
3991b9 #include "pgpSDKPrefs.h"
59fb31 #include "pgpOptionList.h"
b95430 #include "pgpUtilitiesPriv.h"
f2af5a
e9af5a
4d0ccc #if PGP_MACINTOSH
7f85c2 #include "MacStrings.h"
e0bbf4 #include "MacFiles.h"
7a7454 #endif
c0af5a
f9af5a
26fdbe #include "pgpDEBUGStartup.h"
49af5a
aad622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
94af5a
07af5a
8aafb9 #if PGP_WIN32
4caf5a
d52e6d /* ·In Windows, the DllMain function is called when a process or·
9f6ccd ····thread attaches to, or detaches from, the DLL. */
b1af5a
8b729d #include "windows.h"
faaf5a
6f83c5 BOOL WINAPI DllMain (HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved);
cbaf5a
d0d5f7 BOOL WINAPI DllMain (HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
38bb36 {
fc373b ¤   BOOL¤   ¤   success¤= TRUE;
cb26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2167c5 ¤
2bfad1 ¤   (void)hInst;¤   ¤   /* Avoid warnings */
a54e3d ¤   (void)lpReserved;
22af5a
af96fd ¤   switch (ul_reason_for_call)
71c7a1 ¤   {
bdc556 ¤   case DLL_PROCESS_ATTACH:
a5eb3b ¤   ¤   pgpLeaksBeginSession("PGPsdk");
b61b52 ¤   ¤
6cdedb ¤   ¤   err¤= PGPsdkInit();
--745b 000caec58c240100230 Page 2 of pgpKeyLib.c
28be18 ¤   ¤   if ( IsPGPError( err ) )
d4e4f7 ¤   ¤   ¤   success¤= FALSE;
c12f68 ¤   ¤   break;
d6af5a
cf782b ¤   case DLL_PROCESS_DETACH:
dd1a6f ¤   ¤   (void)pgpsdkCleanupForce();
371b52 ¤   ¤
025bc9 ¤   ¤   pgpLeaksEndSession();
4f2f68 ¤   ¤   break;
659371 ¤   }
067e96 ¤   return success;
9aefe6 }
42c5c0 #endif¤ /* PGP_WIN32 */
93af5a
55af5a
c110a4 /* See if the newly opened keyring appears to needs sig checking */
1e66dd ¤   static PGPError
46f730 sIsSigCheckNeeded( PGPKeySetRef set, PGPBoolean *sigCheckNeeded )
79bb36 {
f23bcc ¤   RingSet const *¤¤   rset;
59aae4 ¤   RingIterator *¤ ¤   riter;
598c7f ¤   int¤¤   ¤   ¤   ¤   level;
9c4647 ¤   PGPBoolean¤ ¤   ¤   needSigCheck;
10af5a
ea3008 ¤   *sigCheckNeeded = FALSE;
4a1022 ¤   needSigCheck = FALSE;
8eaf5a
3314f4 ¤   rset = pgpKeyDBRingSet( set->keyDB );
81262b ¤   riter = ringIterCreate( rset );
ed558b ¤   if ( !riter )
ec28b4 ¤   ¤   return ringSetError( rset )->error;
1baf5a
89d8af ¤   /*
7dc674 ¤   ·* We look for a key with a revocation signature which has not
2ac079 ¤   ·* been tried, such that the key's revoke bit is not set. ·This is
a5469f ¤   ·* how some old version of PGP leave revocations. ·We always set the
e40bc6 ¤   ·* key's revocation bit in the file, so this will not happen with
bddb4a ¤   ·* keyrings written by this library.
d4a4e3 ¤   ·*/
8970e2 ¤   while ( (level = ringIterNextObjectAnywhere( riter ) ) > 0 )
67c7a1 ¤   {
a60630 ¤   ¤   if ( level == 2 )
825b34 ¤   ¤   {
0c4828 ¤   ¤   ¤   RingObject *obj = ringIterCurrentObject( riter, level );
293ad0 ¤   ¤   ¤   if ( ringObjectType( obj ) == RINGTYPE_SIG ·&&
91b631 ¤   ¤   ¤   ¤   ·ringSigType( rset, obj ) == PGP_SIGTYPE_KEY_REVOKE &&
ac1924 ¤   ¤   ¤   ¤   ·ringSigTrust( rset, obj ) == PGP_SIGTRUST_UNTRIED )
6dff39 ¤   ¤   ¤   ·{
88aac7 ¤   ¤   ¤   ¤   RingObject *parent = ringIterCurrentObject( riter, level - 1 );
6b7c1d ¤   ¤   ¤   ¤   if ( ringObjectType( parent ) == RINGTYPE_KEY &&
694f2a ¤   ¤   ¤   ¤   ¤   ·!ringKeyRevoked( rset, parent ) )
a072c3 ¤   ¤   ¤   ¤   {
188477 ¤   ¤   ¤   ¤   ¤   /* Here we have our case we are looking for */
d4d4ae ¤   ¤   ¤   ¤   ¤   needSigCheck = TRUE;
9114c3 ¤   ¤   ¤   ¤   ¤   break;
ad2613 ¤   ¤   ¤   ¤   }
0ba3a6 ¤   ¤   ¤   }
b90fe4 ¤   ¤   }
819371 ¤   }
04f435 ¤   ringIterDestroy( riter );
caaf5a
319571 ¤   *sigCheckNeeded = needSigCheck;
90151e ¤   return kPGPError_NoErr;
deefe6 }
c2af5a
6666dd ¤   static PGPError
9f9f62 pgpGetDefaultRingFileRefs(
963163 ¤   PGPContextRef¤  cdkContext,
081659 ¤   PFLFileSpecRef¤ ¤   *pubRefOut,
fe1ab1 ¤   PFLFileSpecRef¤ ¤   *privRefOut )
48bb36 {
ca3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
--e849 00057d178f240100230 Page 3 of pgpKeyLib.c
e0af5a
2f8644 ¤   /* set outputs to default */
142847 ¤   if ( IsntNull( privRefOut ) )
081d2e ¤   ¤   *privRefOut = NULL;
c79073 ¤   if ( IsntNull( pubRefOut ) )
bfaf94 ¤   ¤   *pubRefOut = NULL;
751b52 ¤   ¤
660fff ¤   /* load preferences if not already loaded */
6d93df ¤   if ( IsNull( pgpContextGetPrefs( cdkContext ) ) )
e2c7a1 ¤   {
2ad06b ¤   ¤   err¤= PGPsdkLoadDefaultPrefs( cdkContext );
ec9371 ¤   }
6c67c5 ¤
4df1e7 ¤   if ( IsntPGPError( err ) )
d3c7a1 ¤   {
27c734 ¤   ¤   if ( IsntNull( privRefOut ) )
485b34 ¤   ¤   {
5cdbee ¤   ¤   ¤   err = PGPsdkPrefGetFileSpec( cdkContext,
358eeb ¤   ¤   ¤   ¤   kPGPsdkPref_PrivateKeyring, (PGPFileSpecRef *)privRefOut);
b40fe4 ¤   ¤   }
09af5a
e29191 ¤   ¤   if ( IsntPGPError( err ) && IsntNull( pubRefOut ) )
f05b34 ¤   ¤   {
3ddbee ¤   ¤   ¤   err = PGPsdkPrefGetFileSpec( cdkContext,
0efc70 ¤   ¤   ¤   ¤   kPGPsdkPref_PublicKeyring, (PGPFileSpecRef *)pubRefOut);
2d8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
b6f776 ¤   ¤   ¤   {
eabb43 ¤   ¤   ¤   ¤   PFLFreeFileSpec( *privRefOut );
afc0be ¤   ¤   ¤   ¤   *privRefOut¤= NULL;
b2a3a6 ¤   ¤   ¤   }
120fe4 ¤   ¤   }
1a9371 ¤   }
f067c5 ¤
df5ea8 ¤   return err;
7eefe6 }
27af5a
a438e5 /*
a2dbf1 ·* Open default keyrings for user, return keyset for it.
aa8742 ·* If isMutable is false, keyrings are read only.
36495d ·*/
61c744 ¤   PGPError
326cd4 PGPOpenDefaultKeyRings(
1a58f9 ¤   PGPContextRef¤  ¤   cdkContext,
1ee678 ¤   PGPKeyRingOpenFlags¤openFlags,
5b48e7 ¤   PGPKeySetRef *¤ ¤   keySetOut )
10bb36 {
83af0e ¤   PFLFileSpecRef¤ secFileRef = NULL;¤ /* File reference for secret keyring */
004fbd ¤   PFLFileSpecRef¤ pubFileRef = NULL;¤ /* File reference for public keyring */
033bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
a7746b ¤   PGPKeySetRef¤   set¤= NULL;
e8af5a
28d783 ¤   PGPValidatePtr( keySetOut );
6711dd ¤   *keySetOut¤ = NULL;
3e3c40 ¤   PGPValidateContext( cdkContext );
e6af5a
4c1669 ¤   err¤= pgpGetDefaultRingFileRefs( cdkContext, &pubFileRef, &secFileRef);
7ff1e7 ¤   if ( IsntPGPError( err ) )
3dc7a1 ¤   {
14dc69 ¤   ¤   pgpAssert( IsntNull( pubFileRef ) );
d19a46 ¤   ¤   pgpAssert( IsntNull( secFileRef ) );
a81b52 ¤   ¤
be4ffe ¤   ¤   err = PGPOpenKeyRingPair(cdkContext, openFlags,
83dafb ¤   ¤   ¤   ¤   ¤   (PGPFileSpecRef)pubFileRef,
a6797e ¤   ¤   ¤   ¤   ¤   (PGPFileSpecRef)secFileRef, &set);
1987c7 ¤   ¤   ¤
cda9d4 ¤   ¤   PFLFreeFileSpec( secFileRef );
ddf56f ¤   ¤   PFLFreeFileSpec( pubFileRef );
b29371 ¤   }
c81b52 ¤   ¤
153ff9 ¤   if ( IsPGPError( err ) && IsntNull( set ) )
dac7a1 ¤   {
579200 ¤   ¤   PGPFreeKeySet( set );
--8c54 000c9e5d10040100230 Page 4 of pgpKeyLib.c
5757f0 ¤   ¤   set¤= NULL;
769371 ¤   }
2567c5 ¤
8d6df6 ¤   *keySetOut¤ = set;
65b862 ¤   pgpAssertErrWithPtr( err, *keySetOut );
e45ea8 ¤   return err;
e5efe6 }
35af5a
9838e5 /*
3ddd73 ·* Open the specified keyrings for user, return keyset for it.
4d8742 ·* If isMutable is false, keyrings are read only.
53495d ·*/
1ac744 ¤   PGPError
d047e1 PGPOpenKeyRingPair(
7158f9 ¤   PGPContextRef¤  ¤   cdkContext,
afe678 ¤   PGPKeyRingOpenFlags¤openFlags,
7ca2b7 ¤   PGPFileSpecRef¤ ¤   pubFileRefIn,
a9296d ¤   PGPFileSpecRef¤ ¤   privFileRefIn,
a148e7 ¤   PGPKeySetRef *¤ ¤   keySetOut )
12bb36 {
b42757 ¤   PGPKeyDB¤   ···*dbsec = NULL,¤  ¤   /* KeyDB for secret keyring */
de2bbb ¤   ¤   ¤   ¤   ···*dbpub = NULL,¤  ¤   /* KeyDB for public keyring */
856bfc ¤   ¤   ¤   ¤   ···*dbunion = NULL;¤¤   /* KeyDB for union of both keyrings */
fbef4e ¤   RingPool¤   ···*pgpRingPool;¤   ¤   /* RingPool from cdkContext */
bfaa2b ¤   PGPKeySet¤  ···*set = NULL;
590f7b ¤   PGPBoolean¤ ¤   sigCheckNeeded;
c6fb19 ¤   PGPError¤   ¤   err;
72f8ba ¤   PFLFileSpecRef¤ pubFileRef¤ = (PFLFileSpecRef)pubFileRefIn;
860ba6 ¤   PFLFileSpecRef¤ privFileRef¤= (PFLFileSpecRef)privFileRefIn;
4baf5a
82d783 ¤   PGPValidatePtr( keySetOut );
2b11dd ¤   *keySetOut¤ = NULL;
a43c40 ¤   PGPValidateContext( cdkContext );
a0261f ¤   PFLValidateFileSpec( pubFileRef );
618a17 ¤   PFLValidateFileSpec( privFileRef );
b567c5 ¤
e81b16 ¤   pgpAssert( (openFlags & kPGPKeyRingOpenFlags_Reserved) == 0 );
f1e3c7 ¤   pgpAssert(0 == (openFlags & (kPGPKeyRingOpenFlags_Private |
6a1169 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPKeyRingOpenFlags_Trusted)));
ddaf5a
7f410e ¤   pgpRingPool = pgpContextGetRingPool( cdkContext );
f7af5a
a46fd9 ¤   /* Create key databases for these files. ·Don't bother with keypool.·
cbfda3 ¤   ···Private keyring is not trusted (no trust packets) */
542440 ¤   if ((dbsec = pgpCreateFileKeyDB(cdkContext, privFileRef,
a29c4e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyRingOpenFlags)
4a0cec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (openFlags | kPGPKeyRingOpenFlags_Private),
97db09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpRingPool, &err)) == NULL)
d597ed ¤   ¤   goto error;
1d7e84 ¤   if ((dbpub = pgpCreateFileKeyDB(cdkContext, pubFileRef,
ac9c4e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyRingOpenFlags)
46d941 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (openFlags | kPGPKeyRingOpenFlags_Trusted),
74db09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpRingPool, &err)) == NULL)
6f97ed ¤   ¤   goto error;
5faf5a
b2e0fb ¤   /* Create union database for these two files */
a22648 ¤   if ((dbunion = pgpCreateUnionKeyDB(cdkContext, &err)) == NULL)
4a97ed ¤   ¤   goto error;
d667c5 ¤
5b52a0 ¤   err¤= pgpUnionKeyDBAdd(dbunion, dbsec);
50054e ¤   if ( IsPGPError( err ) )
ba97ed ¤   ¤   goto error;
bcb03d ¤   dbsec = NULL;¤  /* dbunion now has responsibility for freeing dbsec */
c367c5 ¤
32f626 ¤   err¤= pgpUnionKeyDBAdd(dbunion, dbpub);
de054e ¤   if ( IsPGPError( err ) )
d497ed ¤   ¤   goto error;
8e4b18 ¤   dbpub = NULL;¤  /* dbunion now has responsibility for freeing dbpub */
3daf5a
3bd8af ¤   /*
2a2ae2 ¤   ·* Verify that we have sufficient ringsets to work with union.
c997a5 ¤   ·* It is easier to check for this now than to check everywhere we
--5a6e 000d4361a7d40100230 Page 5 of pgpKeyLib.c
c1b083 ¤   ·* ask for a ringset.
64a4e3 ¤   ·*/
0fdbdf ¤   if (dbunion->getRingSet(dbunion) == NULL) {
7d64e3 ¤   ¤   /* Insufficient ringsets */
8b48fe ¤   ¤   err = kPGPError_OutOfRings;
fd97ed ¤   ¤   goto error;
6f9371 ¤   }
85af5a
3cacb7 ¤   err¤= pgpBuildKeyPool(dbunion, 0);
06054e ¤   if ( IsPGPError( err ) )
2097ed ¤   ¤   goto error;
16af5a
e2e89f ¤   set = pgpKeyDBRootSet(dbunion);
e6b624 ¤   if ( IsNull( set ) )
f6c7a1 ¤   {
7e01ef ¤   ¤   err = kPGPError_OutOfMemory;¤   /* XXX Improve error */
7e97ed ¤   ¤   goto error;
b29371 ¤   }
72af5a
35d8af ¤   /*
14ca75 ¤   ·* Some earlier versions of PGP don't cache revocation info. ·We will
faa210 ¤   ·* check signatures if the keyring has unchecked revocation signatures
c5fb41 ¤   ·* where the key does not have the revoke flag cached.
dca4e3 ¤   ·*/
eb19a6 ¤   if( IsPGPError( err = sIsSigCheckNeeded( set, &sigCheckNeeded ) ) )
3197ed ¤   ¤   goto error;
992d81 ¤   if( sigCheckNeeded )
06c7a1 ¤   {
e99d1d ¤   ¤   if ( IsPGPError( err = PGPCheckKeyRingSigs( set, set, FALSE,
b5fdc8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL ) ) )
13ed19 ¤   ¤   ¤   goto error;
af2dc5 ¤   ¤   if ( IsPGPError( err = PGPPropagateTrust( set ) ) )
34ed19 ¤   ¤   ¤   goto error;
1afd3e ¤   ¤   if ( PGPKeySetIsMutable( set ) )
0e5b34 ¤   ¤   {
979bc8 ¤   ¤   ¤   if ( IsPGPError( err = PGPCommitKeyRingChanges( set ) ) )
681b7c ¤   ¤   ¤   ¤   goto error;
690fe4 ¤   ¤   }
909371 ¤   }
8eaf5a
676493 ¤   err = kPGPError_NoErr;
be67c5 ¤
8360ff error:
d344f6 ¤   if (dbsec != NULL)
946fc3 ¤   ¤   pgpFreeKeyDB(dbsec);
d40a48 ¤   if (dbpub != NULL)
fbcb45 ¤   ¤   pgpFreeKeyDB(dbpub);
c0c843 ¤   if (dbunion != NULL)
6269fa ¤   ¤   pgpFreeKeyDB(dbunion);
05fc28 ¤   if (set != NULL && IsPGPError( err ))
37c7a1 ¤   {
6b15a5 ¤   ¤   PGPFreeKeySet(set);
37acc2 ¤   ¤   set = NULL;
2c9371 ¤   }
c96df6 ¤   *keySetOut¤ = set;
3567c5 ¤
8ab862 ¤   pgpAssertErrWithPtr( err, *keySetOut );
895ea8 ¤   return err;
70efe6 }
48af5a
5b38e5 /*
f5dc70 ·* Open a single specified keyring for user, return keyset for it.
848742 ·* If isMutable is false, keyrings are read only.
88230a ·* If isTrusted is false, trust packets are ignored.
34495d ·*/
79c744 ¤   PGPError
27b157 PGPOpenKeyRing(
a658f9 ¤   PGPContextRef¤  ¤   cdkContext,
75e678 ¤   PGPKeyRingOpenFlags¤openFlags,
ae79c9 ¤   PGPFileSpecRef¤ ¤   fileRefIn,
2248e7 ¤   PGPKeySetRef *¤ ¤   keySetOut )
d4bb36 {
--6079 0005e3c31e240100230 Page 6 of pgpKeyLib.c
d62472 ¤   PGPKeyDB¤   ···*db = NULL;
5eaa2b ¤   PGPKeySet¤  ···*set = NULL;
863346 ¤   RingPool¤   ···*pgpRingPool;
840f7b ¤   PGPBoolean¤ ¤   sigCheckNeeded;
383bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
bd9b06 ¤   PFLFileSpecRef¤ fileRef¤= (PFLFileSpecRef)fileRefIn;
1baf5a
c6d783 ¤   PGPValidatePtr( keySetOut );
7211dd ¤   *keySetOut¤ = NULL;
913c40 ¤   PGPValidateContext( cdkContext );
e365f3 ¤   PFLValidateFileSpec( fileRef );
9267c5 ¤
491b16 ¤   pgpAssert( (openFlags & kPGPKeyRingOpenFlags_Reserved) == 0 );
1867c5 ¤
12af5a
44410e ¤   pgpRingPool = pgpContextGetRingPool( cdkContext );
acaf5a
df040c ¤   /* Create key database for this files. ·Don't bother with keypool. */
bdb758 ¤   if ((db = pgpCreateFileKeyDB(cdkContext, fileRef, openFlags,
dff005 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·pgpRingPool, &err)) == NULL)
e997ed ¤   ¤   goto error;
80af5a
cce0f0 ¤   err¤= pgpBuildKeyPool(db, 0);
66054e ¤   if ( IsPGPError( err ) )
ee97ed ¤   ¤   goto error;
0faf5a
d0e0f9 ¤   set = pgpKeyDBRootSet(db);
d5b624 ¤   if ( IsNull( set ) )
bdc7a1 ¤   {
8101ef ¤   ¤   err = kPGPError_OutOfMemory;¤   /* XXX Improve error */
6e97ed ¤   ¤   goto error;
8d9371 ¤   }
5caf5a
2dd8af ¤   /*
4dca75 ¤   ·* Some earlier versions of PGP don't cache revocation info. ·We will
05a210 ¤   ·* check signatures if the keyring has unchecked revocation signatures
d5fb41 ¤   ·* where the key does not have the revoke flag cached.
17a4e3 ¤   ·*/
ba19a6 ¤   if( IsPGPError( err = sIsSigCheckNeeded( set, &sigCheckNeeded ) ) )
6997ed ¤   ¤   goto error;
fc2d81 ¤   if( sigCheckNeeded )
15c7a1 ¤   {
f09d1d ¤   ¤   if ( IsPGPError( err = PGPCheckKeyRingSigs( set, set, FALSE,
defdc8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL ) ) )
bced19 ¤   ¤   ¤   goto error;
7c2dc5 ¤   ¤   if ( IsPGPError( err = PGPPropagateTrust( set ) ) )
b8ed19 ¤   ¤   ¤   goto error;
83fd3e ¤   ¤   if ( PGPKeySetIsMutable( set ) )
415b34 ¤   ¤   {
3f9bc8 ¤   ¤   ¤   if ( IsPGPError( err = PGPCommitKeyRingChanges( set ) ) )
101b7c ¤   ¤   ¤   ¤   goto error;
520fe4 ¤   ¤   }
599371 ¤   }
256493 ¤   err = kPGPError_NoErr;
ff67c5 ¤
db60ff error:
a9099b ¤   if (db != NULL)
559ea9 ¤   ¤   pgpFreeKeyDB(db);
09fc28 ¤   if (set != NULL && IsPGPError( err ))
01c7a1 ¤   {
cc15a5 ¤   ¤   PGPFreeKeySet(set);
01acc2 ¤   ¤   set = NULL;
d19371 ¤   }
c06df6 ¤   *keySetOut¤ = set;
f9b862 ¤   pgpAssertErrWithPtr( err, *keySetOut );
6e5ea8 ¤   return err;
c2efe6 }
79af5a
b938e5 /*
82ee00 ·* Add keys to a keyset from a dynamically allocated binary key buffer.
d99bef ·* Makes a copy of the binary key buffer data, so caller can dispose of
5eedf8 ·* it after this call.
--83f5 000986f76c740100230 Page 7 of pgpKeyLib.c
47495d ·*/
9dc744 ¤   PGPError
a288b3 pgpImportKeyBinary (
f03163 ¤   PGPContextRef¤  cdkContext,
22650f ¤   PGPByte¤¤   ···*buffer,
abffed ¤   size_t¤ ¤   ¤   length,
b22809 ¤   PGPKeySetRef *¤ outRef
d627e6 ¤   )
41bb36 {
abc592 ¤   PGPKeyDBRef¤¤   kdb;
f9746b ¤   PGPKeySetRef¤   set¤= NULL;
723346 ¤   RingPool¤   ···*pgpRingPool;
579372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
09af5a
263652 ¤   *outRef¤= NULL;
6c67c5 ¤
1bd843 ¤   /* Create a file type KeyDB from the buffer */
88410e ¤   pgpRingPool = pgpContextGetRingPool( cdkContext );
e27ddf ¤   kdb = pgpCreateMemFileKeyDB (cdkContext, buffer, length, pgpRingPool,
80cb84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&err);
e6057f ¤   if ( IsNull( kdb ) )
37c7a1 ¤   {
44d3cc ¤   ¤   pgpAssert( IsPGPError( err ) );
c49371 ¤   }
150e24 ¤   else
85c7a1 ¤   {
138832 ¤   ¤   err = pgpBuildKeyPool (kdb, 0);
d07d98 ¤   ¤   if ( IsntPGPError( err ) )
bb5b34 ¤   ¤   {
298ae4 ¤   ¤   ¤   set = pgpKeyDBRootSet (kdb);
510fe4 ¤   ¤   }
abfb6f ¤   ¤   pgpFreeKeyDB (kdb);
339371 ¤   }
b967c5 ¤
e0d0b0 ¤   *outRef¤= set;
b367c5 ¤
e35ea8 ¤   return err;
c1efe6 }
90af5a
1faf5a
2ddf53 static const PGPOptionType impkeyOptionSet[] = {
645ceb ¤   kPGPOptionType_InputFileRef,
07b15b ¤   kPGPOptionType_LocalEncoding,
cfd59a ¤   kPGPOptionType_InputBuffer,
97074a ¤   kPGPOptionType_EventHandler,
c4bf11 ¤   kPGPOptionType_SendNullEvents,
830367 ¤   kPGPOptionType_X509Encoding
5682f7 };
66af5a
3e52f1 /* Frees optionList, unlike most other internal functions */
c8c744 ¤   PGPError
527d7f pgpImportKeySetInternal (PGPContextRef context, PGPKeySetRef *keys,
220408 ¤   PGPOptionListRef optionList)
dfbb36 {
7f3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
bbfead ¤   PGPKeySetRef¤   keyset;
6c897d ¤   PGPUInt32¤  ¤   fDo509;
34af5a
3e4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
945937 ¤   ¤   ¤   ¤   ¤   ¤   impkeyOptionSet, elemsof( impkeyOptionSet ) ) ) )
a3c9db ¤   ¤   return err;
d6af5a
2db135 ¤   pgpAssertAddrValid( keys, PGPKeySetRef );
c0a388 ¤   *keys = NULL;
0267c5 ¤
b77bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
10ab00 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_X509Encoding, FALSE,
6e5fc2 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fDo509 ) ) )
7297ed ¤   ¤   goto error;
50af5a
e12a94 ¤   if( fDo509 ) {
98216c ¤   ¤   err = pgpImportX509Certificate( context, keys, optionList );
--a907 0003230332440100230 Page 8 of pgpKeyLib.c
bb153d ¤   ¤   PGPFreeOptionList( optionList );
fa97ed ¤   ¤   goto error;
1e9371 ¤   }
d1af5a
109ecf ¤   if( IsPGPError( err = PGPNewKeySet( context, &keyset ) ) )
b097ed ¤   ¤   goto error;
11af5a
0e68dc ¤   if( IsPGPError( err = PGPDecode( context, optionList,
e521f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPODiscardOutput(context, TRUE),
ad002f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOImportKeysTo(context, keyset),
5c6e58 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOLastOption(context) ) ) ) {
535899 ¤   ¤   PGPFreeKeySet( keyset );
7797ed ¤   ¤   goto error;
3e9371 ¤   }
af59fb ¤   *keys = keyset;
4067c5 ¤
f660ff error:
655ea8 ¤   return err;
c1efe6 }
8faf5a
37af5a
5d95d7 /*·
14ce86 ·* Filter function for extraction. ·Remove any secret objects.
630658 ·* If addarrs is true, also add any additional decryption key objects to
8e10b9 ·* the set. ·This will cause ADK's to be extracted with the keys
490e5b ·* that use them.
0c2e1d ·* XXX AUTOMATIC ADK EXTRACTION DOES NOT YET WORK.
26637c ·* There is no RingSet available in which
7926ca ·* to look for ADK's. ·The export functions typically are called with
1678eb ·* just a memory RingSet. ·We need to add versions which take an extra
68bb16 ·* PGPKeySet to flag that ADK's should be looked for there.
9f495d ·*/
f50dcb static RingSet *
4286ce filterPubRingSet (RingSet const *rset, PGPKeySet *keys,
b94832 ¤   PGPBoolean exportmastersecrets, PGPBoolean exportsubsecrets,
b1070b ¤   PGPBoolean addarks, PGPBoolean includeattributes)
41bb36 {
2d3dd8 ¤   RingSet¤¤   ···*rsetnew;¤   /* Set of recipients */
f793a6 ¤   RingSet¤¤   ···*adkeyset;¤  /* Set of additional decryption keys */
95a812 ¤   RingIterator ··*riter;¤ ¤   /* Iterator over adding sets */
42db12 ¤   int¤¤   ¤   ¤   level;
3e9a60 ¤   PGPBoolean¤ ¤   isMember = FALSE;
a22898 ¤   PGPBoolean¤ ¤   exportsecrets = exportmastersecrets;
629372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
39af5a
7fa822 ¤   if (!rset)
ac7ed2 ¤   ¤   return NULL;
2c27a2 ¤   adkeyset = NULL;
5b2e16 ¤   rsetnew = ringSetCreate (ringSetPool (rset));
6d5af3 ¤   if (!rsetnew)
757ed2 ¤   ¤   return NULL;
ed591e ¤   riter = ringIterCreate (rset);
61e68d ¤   if (!riter) {
c41590 ¤   ¤   ringSetDestroy (rsetnew);
ee7ed2 ¤   ¤   return NULL;
259371 ¤   }
c17869 ¤   /*·
768d5d ¤   ·* Copy objects in PGPKeySet to rsetnew except secret objects.
18e5f7 ¤   ·* At the same time, accumulate any additional decryption keys into
02704e ¤   ·* adkeyset.
09a4e3 ¤   ·*/
c4d6a6 ¤   while ((level = ringIterNextObjectAnywhere(riter)) > 0) {
a88b07 ¤   ¤   RingObject *obj = ringIterCurrentObject (riter, level);
32ca23 ¤   ¤   if (ringObjectType(obj) == RINGTYPE_KEY) {
cbc874 ¤   ¤   ¤   exportsecrets = ringKeyIsSubkey(rset, obj) ? exportsubsecrets :
009b17 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·exportmastersecrets;
670fe4 ¤   ¤   }
131372 ¤   ¤   /* Possibly skip secret objects */
464e62 ¤   ¤   if (!exportsecrets && ringObjectType (obj) == RINGTYPE_SEC)
f717f5 ¤   ¤   ¤   continue;
860754 ¤   ¤   /* Skip signatures if exporting secret keys */
32228b ¤   ¤   if (exportsecrets && ringObjectType (obj) == RINGTYPE_SIG)
--08f1 00098a70cfc40100230 Page 9 of pgpKeyLib.c
a017f5 ¤   ¤   ¤   continue;
d33147 ¤   ¤   if (!includeattributes && ringObjectType (obj) == RINGTYPE_NAME
876303 ¤   ¤   ¤   && ringNameIsAttribute (rset, obj))
6617f5 ¤   ¤   ¤   continue;
d518b5 ¤   ¤   if (!includeattributes && ringObjectType (obj) == RINGTYPE_SIG) {
97593f ¤   ¤   ¤   RingObject *parent = ringIterCurrentObject (riter, level-1);
2b0ae4 ¤   ¤   ¤   if (ringObjectType(parent) == RINGTYPE_NAME &&
c619b1 ¤   ¤   ¤   ¤   ringNameIsAttribute (rset, parent))
95d040 ¤   ¤   ¤   ¤   continue;
620fe4 ¤   ¤   }
a47395 ¤   ¤   /* Skip non-members */
a1bb40 ¤   ¤   if (ringObjectType(obj) == RINGTYPE_KEY
6b4891 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   && !ringKeyIsSubkey(rset, obj)) {
a3a53c ¤   ¤   ¤   /* Can only call isMember on top level key objects */
23b071 ¤   ¤   ¤   isMember = (*keys->isMember)(keys, obj);
af0fe4 ¤   ¤   }
874ad7 ¤   ¤   if (!isMember)
ad17f5 ¤   ¤   ¤   continue;
fd5e85 ¤   ¤   ringSetAddObject (rsetnew, obj);
ed20df ¤   ¤   /* For key objects, look for additional decryption keys */
f21630 ¤   ¤   if (addarks && ringObjectType (obj) == RINGTYPE_KEY)
845b34 ¤   ¤   {
79f9db ¤   ¤   ¤   RingObject¤ ···*rkey;¤  ¤   /* Decryption key */
3b65fe ¤   ¤   ¤   unsigned¤   ¤   nrkeys;¤¤   /* Number of decryption keys */
a387c7 ¤   ¤   ¤
8ced37 ¤   ¤   ¤   if (ringKeyAdditionalRecipientRequestKey (obj, rset, 0, NULL,
36d12b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, &nrkeys, &err) != NULL )
7ff776 ¤   ¤   ¤   {
b0448a ¤   ¤   ¤   ¤   /* Add to special set for additional decryption keys */
ef034b ¤   ¤   ¤   ¤   while (nrkeys-- > 0)
ba72c3 ¤   ¤   ¤   ¤   {
9a9477 ¤   ¤   ¤   ¤   ¤   rkey = ringKeyAdditionalRecipientRequestKey (obj, rset, 0,
63a27f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, NULL, &nrkeys, &err);
ed91a1 ¤   ¤   ¤   ¤   ¤   pgpAssert (rkey);
49dfbe ¤   ¤   ¤   ¤   ¤   if (!adkeyset)
da4859 ¤   ¤   ¤   ¤   ¤   {
8586be ¤   ¤   ¤   ¤   ¤   ¤   adkeyset = ringSetCreate (ringSetPool(rset));
4f9e4d ¤   ¤   ¤   ¤   ¤   ¤   if (!adkeyset)
a58fec ¤   ¤   ¤   ¤   ¤   ¤   {
a82af2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringIterDestroy (riter);
711ef7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringSetDestroy (rsetnew);
85788d ¤   ¤   ¤   ¤   ¤   ¤   ¤   return NULL;
f7db3c ¤   ¤   ¤   ¤   ¤   ¤   }
151c89 ¤   ¤   ¤   ¤   ¤   }
321f5f ¤   ¤   ¤   ¤   ¤   ringSetAddObjectChildren (adkeyset, rset, rkey);
d72613 ¤   ¤   ¤   ¤   }
46a3a6 ¤   ¤   ¤   }
070fe4 ¤   ¤   }
019371 ¤   }
85ae1f ¤   ringIterDestroy (riter);
9eaf5a
033763 ¤   /* Last, merge adkeyset into rsetnew, also stripping secrets */
903476 ¤   if (adkeyset) {
a9ca30 ¤   ¤   ringSetFreeze (adkeyset);
a634c4 ¤   ¤   riter = ringIterCreate (adkeyset);
f8dc17 ¤   ¤   if (!riter) {
68a9eb ¤   ¤   ¤   ringSetDestroy (adkeyset);
78fae3 ¤   ¤   ¤   ringSetDestroy (rsetnew);
2acf03 ¤   ¤   ¤   return NULL;
980fe4 ¤   ¤   }
0e9a64 ¤   ¤   /* Loop over rsetnew iterator, adding non-secret objects */
176add ¤   ¤   /* We will always strip ADK secrets, he can export those explicitly */
076abf ¤   ¤   while ((level = ringIterNextObjectAnywhere(riter)) > 0) {
7bb669 ¤   ¤   ¤   RingObject *obj = ringIterCurrentObject (riter, level);
ab0b1c ¤   ¤   ¤   if (ringObjectType (obj) == RINGTYPE_SEC)
69d040 ¤   ¤   ¤   ¤   continue;
f6583d ¤   ¤   ¤   ringSetAddObject (rsetnew, obj);
f80fe4 ¤   ¤   }
f61549 ¤   ¤   ringIterDestroy (riter);
7ce818 ¤   ¤   ringSetDestroy (adkeyset);
759371 ¤   }
98af5a
--a3fa 0003f4d2dba40100230 Page 10 of pgpKeyLib.c
e26262 ¤   /* Return new set in frozen form */
379cd5 ¤   ringSetFreeze (rsetnew);
f384c0 ¤   return rsetnew;
d6efe6 }
c6af5a
7aaf5a
e1af5a
308c97 static const PGPOptionType expkeyOptionSet[] = {
ea4ee8 ¤   kPGPOptionType_ExportPrivateKeys,
afcd2b ¤   kPGPOptionType_ExportPrivateSubkeys,
8e17e6 ¤   kPGPOptionType_ExportFormat,
31be74 ¤   kPGPOptionType_OutputFileRef,
be6c2f ¤   kPGPOptionType_OutputBuffer,
0a0a04 ¤   kPGPOptionType_OutputAllocatedBuffer,
8440be ¤   kPGPOptionType_DiscardOutput,
73092a ¤   kPGPOptionType_ArmorOutput,
d81811 ¤   kPGPOptionType_CommentString,
de6aaf ¤   kPGPOptionType_VersionString,
af074a ¤   kPGPOptionType_EventHandler,
e3bf11 ¤   kPGPOptionType_SendNullEvents,
6bae48 ¤   kPGPOptionType_OutputLineEndType
da82f7 };
f5af5a
1f0ccc #if PGP_MACINTOSH
a19221 #pragma global_optimizer on
2d7454 #endif
64af5a
d152f1 /* Frees optionList, unlike most other internal functions */
53c77d PGPError
00ff89 pgpExportKeySetInternal (PGPKeySet *keys, PGPOptionListRef optionList)
6dbb36 {
37c219 ¤   PGPUInt32¤  ¤   ¤   fExportSecrets;
c503fc ¤   PGPUInt32¤  ¤   ¤   fExportSubSecrets;
bc9a7b ¤   PGPBoolean¤ ¤   ¤   fExportAttributes;
82de11 ¤   PGPBoolean¤ ¤   ¤   fExportFormat;
ee255b ¤   PGPByte¤¤   ¤   ¤   *buf;
f2b949 ¤   PGPSize¤¤   ¤   ¤   bufSize;
bc8e26 ¤   PGPSize¤¤   ¤   ¤   bufSizeRead;
dc7925 ¤   PGPContextRef¤  ¤   context;
9de8b3 ¤   PGPFile¤¤   ¤   ¤   *pfile;
3040e3 ¤   RingSet const¤  ¤   *rset;
d68374 ¤   RingSet const¤  ¤   *rsetpub;
e53095 ¤   PGPOptionListRef¤   optList;
2e8220 ¤   PGPExportFormat¤¤   exportFormat = kPGPExportFormat_Complete;
73b869 ¤   PGPUInt32¤  ¤   ¤   wExportFormat;
dde6b6 ¤   PGPBoolean¤ ¤   ¤   armorop;
d17d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
27af5a
69f3ee ¤   context = PGPGetKeySetContext( keys );
1e8679 ¤   pgpAssert( pgpContextIsValid( context ) );
a0af5a
e84271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
874047 ¤   ¤   ¤   ¤   ¤   ¤   expkeyOptionSet, elemsof( expkeyOptionSet ) ) ) )
96c9db ¤   ¤   return err;
f6af5a
9f5065 ¤   buf = NULL;
61556d ¤   pfile = NULL;
894f04 ¤   rsetpub = NULL;
6a13eb ¤   rset = NULL;
acfff7 ¤   optList = NULL;
7caf5a
f43019 ¤   /* Read optional options */
c87bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e92158 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ExportPrivateKeys, FALSE,
e6f201 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fExportSecrets ) ) )
de97ed ¤   ¤   goto error;
11af5a
127bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
feb847 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ExportPrivateSubkeys, FALSE,
e34f04 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &fExportSubSecrets ) ) )
f897ed ¤   ¤   goto error;
3faf5a
--9bb0 000c9f9c70e40100230 Page 11 of pgpKeyLib.c
d27bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
4c1da0 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ExportFormat, FALSE,
df9350 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &fExportFormat, &wExportFormat ) ) )
e797ed ¤   ¤   goto error;
32af5a
ce280b ¤   if (fExportFormat)
2dffd8 ¤   ¤   exportFormat = (PGPExportFormat) wExportFormat;
bff8a9 ¤   fExportAttributes = (exportFormat > kPGPExportFormat_Basic);
bbaf5a
6f3c4c ¤   /* Create ringset to extract from */
b69762 ¤   if( IsPGPError( err = pgpKeySetRingSet( keys, TRUE, &rset ) ) )
f997ed ¤   ¤   goto error;
207c62 ¤   /* Output public or private portion */
f6ca41 ¤   rsetpub = filterPubRingSet (rset, keys, (PGPBoolean)fExportSecrets,
56cd29 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean)(fExportSubSecrets|fExportSecrets),
2aab54 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FALSE, fExportAttributes);
aa8384 ¤   if (!rsetpub) {
fbbce1 ¤   ¤   err = kPGPError_OutOfMemory;
e197ed ¤   ¤   goto error;
d49371 ¤   }
ebaf5a
72a3a5 ¤   /* Create memory buffer to write to */
4a9608 ¤   pfile = pgpFileMemOpen( context, NULL, 0 );
3c9f51 ¤   if( IsNull( pfile ) ) {
ebbce1 ¤   ¤   err = kPGPError_OutOfMemory;
d497ed ¤   ¤   goto error;
729371 ¤   }
e4af5a
d3add5 ¤   /* Output data to memory buffer */
f73574 ¤   if( IsPGPError( err = ringSetWrite (rsetpub, pfile, NULL, PGPVERSION_3,
dce76b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0) ) )
2597ed ¤   ¤   goto error;
ada0ff ¤   ringSetDestroy( (RingSet *)rsetpub );
2c4f04 ¤   rsetpub = NULL;
5eaf5a
358b4e ¤   /* Read data we just wrote */
7b679d ¤   bufSize = pgpFileTell (pfile );
f7971e ¤   buf = (PGPByte *)pgpContextMemAlloc( context, bufSize, 0 );
ac3024 ¤   if( IsNull( buf ) ) {
5ebce1 ¤   ¤   err = kPGPError_OutOfMemory;
8397ed ¤   ¤   goto error;
da9371 ¤   }
913481 ¤   (void)pgpFileSeek( pfile, 0, SEEK_SET );
85e227 ¤   bufSizeRead = pgpFileRead( buf, bufSize, pfile );
ccebe8 ¤   pgpAssert( bufSizeRead == bufSize );
15bd6b ¤   pgpFileClose( pfile );
8a556d ¤   pfile = NULL;
d5af5a
e263d1 ¤   /* Do ascii armoring */
e4c739 ¤   /* If user specified an ascii armor option, use his, else use TRUE */
b27bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
56ab04 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ArmorOutput, FALSE,
764877 ¤   ¤   ¤   ¤   ¤   ¤   "%b", &armorop ) ) )
2b97ed ¤   ¤   goto error;
81af5a
874661 ¤   /* This next call frees optionList */
3d1221 ¤   if( IsPGPError( err = PGPBuildOptionList( context, &optList, optionList,·
3d8ba5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(armorop ?
53a270 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPONullOption(context) :
74e963 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPOArmorOutput(context, TRUE)),
3609ba ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPORawPGPInput(context, TRUE),
99f1cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOCompression(context, FALSE),
ca8264 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOLastOption(context) ) ) )
2a97ed ¤   ¤   goto error;
ac59fc ¤   optionList = NULL;
99af5a
4322da ¤   if( IsPGPError( err = PGPEncode( context, optList,
28c2b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOInputBuffer(context, buf, bufSize),
b78264 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOLastOption(context) ) ) )
4d97ed ¤   ¤   goto error;
5eaf5a
c9aba2 ¤   pgpContextMemFree( context, buf );
--9604 0006975ccaf40100230 Page 12 of pgpKeyLib.c
1c5065 ¤   buf = NULL;
80af5a
59d8af ¤   /*
021714 ¤   ·* If exporting private keys, append public keys to the buffer.
a72f48 ¤   ·* We can't export them both together, as we end up with an output
657158 ¤   ·* which has private keys followed by names and sigs. ·This can not
28117e ¤   ·* be safely imported, because of the "version bug". ·The private key
f29101 ¤   ·* may have the incorrect version. ·So we instead output the public
6303b9 ¤   ·* part with names and sigs, after the private part with private keys
62d44d ¤   ·* and names.
30a4e3 ¤   ·*/
5c8346 ¤   if( fExportSecrets || fExportSubSecrets ) {
a9af5a
3dbbf3 ¤   ¤   /* Get ringset for public portion */
69c9fd ¤   ¤   rsetpub = filterPubRingSet (rset, keys, FALSE, FALSE, FALSE,
96a8be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   fExportAttributes);
a3f970 ¤   ¤   if (!rsetpub) {
f2b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
5fed19 ¤   ¤   ¤   goto error;
b90fe4 ¤   ¤   }
15af5a
80323d ¤   ¤   /* Create memory buffer to write to */
d40049 ¤   ¤   pfile = pgpFileMemOpen( context, NULL, 0 );
54320f ¤   ¤   if( IsNull( pfile ) ) {
37b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
03ed19 ¤   ¤   ¤   goto error;
8a0fe4 ¤   ¤   }
70af5a
c5a399 ¤   ¤   /* Output data to memory buffer */
b34392 ¤   ¤   if( IsPGPError( err = ringSetWrite (rsetpub, pfile, NULL,
ff6b55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPVERSION_3, 0) ) )
c7ed19 ¤   ¤   ¤   goto error;
db993a ¤   ¤   ringSetDestroy( (RingSet *)rsetpub );
4c35f0 ¤   ¤   rsetpub = NULL;
d8af5a
88643d ¤   ¤   /* Read data we just wrote */
d2a2c8 ¤   ¤   bufSize = pgpFileTell (pfile );
48aa70 ¤   ¤   buf = (PGPByte *)pgpContextMemAlloc( context, bufSize, 0 );
9db970 ¤   ¤   if( IsNull( buf ) ) {
75b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
80ed19 ¤   ¤   ¤   goto error;
c20fe4 ¤   ¤   }
91661c ¤   ¤   (void)pgpFileSeek( pfile, 0, SEEK_SET );
14e150 ¤   ¤   bufSizeRead = pgpFileRead( buf, bufSize, pfile );
34ed50 ¤   ¤   pgpAssert( bufSizeRead == bufSize );
52a943 ¤   ¤   pgpFileClose( pfile );
d26ff7 ¤   ¤   pfile = NULL;
d0af5a
2b5978 ¤   ¤   /* Do ascii armoring, append to existing output */
d5bafd ¤   ¤   PGPAppendOptionList( optList,
7f269a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOAppendOutput(context, TRUE),
5c7742 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPOLastOption(context) );
4625e1 ¤   ¤   if( IsPGPError( err = PGPEncode( context, optList,
82176a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOInputBuffer(context, buf, bufSize),
9879c6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption(context) ) ) )
27ed19 ¤   ¤   ¤   goto error;
37af5a
7ba5ee ¤   ¤   pgpContextMemFree( context, buf );
58c716 ¤   ¤   buf = NULL;
159371 ¤   }
3baf5a
4c6493 ¤   err = kPGPError_NoErr;
d4af5a
fc91b1 ¤   /* Fall through */
8060ff error:
a4ec81 ¤   if( IsntNull( optList ) )
307390 ¤   ¤   PGPFreeOptionList( optList );
aab95d ¤   if( IsntNull( optionList ) )
93153d ¤   ¤   PGPFreeOptionList( optionList );
12fb50 ¤   if( IsntNull( pfile ) )
81a943 ¤   ¤   pgpFileClose( pfile );
69f1cb ¤   if( IsntNull( rsetpub ) )
--72c5 00120bc47a340100230 Page 13 of pgpKeyLib.c
d5492f ¤   ¤   ringSetDestroy ( (RingSet *)rsetpub);
137c2d ¤   if( IsntNull( rset ) )
6ec8c9 ¤   ¤   ringSetDestroy ( (RingSet *)rset);
9c24c3 ¤   if( IsntNull( buf ) )
59a5ee ¤   ¤   pgpContextMemFree( context, buf );
005ea8 ¤   return err;
16efe6 }
0baf5a
400ccc #if PGP_MACINTOSH
fce4a1 #pragma global_optimizer reset
437454 #endif
6daf5a
48af5a
d1af5a
d738e5 /*
8be6c5 ·* Local Variables:
2e9b19 ·* tab-width: 4
a1e7a4 ·* End:
5cb612 ·* vi: ts=4 sw=4
0d6c42 ·* vim: si
20495d ·*/
--017a 000bde7672e40100231 Page 1 of pgpKeyMan.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
b79cba ¤   $Id: pgpKeyMan.c,v 1.181.2.4.2.1 1998/11/12 03:22:01 heller Exp $
a1f7f7 ____________________________________________________________________________*/
be324c #include <string.h>
d1af5a
94e2ff #include "pgpConfig.h"
7caf5a
97c26c #include "pgpContext.h"
848b0d #include "pgpEncodePriv.h"
f42d40 #include "pgpEventPriv.h"
f0979a #include "pgpKDBInt.h"
afa146 #include "pgpDebug.h"
f726e3 #include "pgpRngPub.h"
4d806a #include "pgpRngRead.h"
edcdc2 #include "pgpPubKey.h"
742c96 #include "pgpRandomX9_17.h"
eec9be #include "pgpRandomPool.h"
54f5ab #include "pgpSigSpec.h"
965579 #include "pgpStr2Key.h"
30c5b0 #include "pgpKeySpec.h"
daae6d #include "pgpTrstPkt.h"
855a03 #include "pgpTrust.h"
819f72 #include "pgpHash.h"
6f0d6d #include "pgpEnv.h"
3191b9 #include "pgpSDKPrefs.h"
4339fc #include "bn.h"
cf5d53 #include "pgpRegExp.h"
c026e3 #include "pgpRngPub.h"
ec5d28 #include "pgpRngMnt.h"
182266 #include "pgpTimeDate.h"
0d7ca7 #include "pgpKeyIDPriv.h"
665430 #include "pgpUtilitiesPriv.h"
050e2f #include "pgpSymmetricCipherPriv.h"
42af5a
d8af5a
8321e0 #define MAXRSABITS¤ ¤   2048
64af5a
5ad622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
03af5a
73c519 /* ·INTERNAL FUNCTIONS */
89af5a
f0231e /* ·Internal function for certifying a key or userid. ·Object to be signed·
f7be88 ¤   must be¤in dest. ·Signing key should be in src. ·selfsig should be
a2b30c ····set for self-certifying names. */
e2af5a
f9afd3 #define SIG_EXPORTABLE¤ ¤   ¤   TRUE
96327c #define SIG_NON_EXPORTABLE¤ ¤   FALSE
f5ead9 #define SIG_EXPORTABLEHASHED¤   TRUE
2ebf04 #define SIG_EXPORTABLEUNHASHED¤ FALSE
4aaf5a
eff1ae static PGPError
075068 pgpCertifyObject(
e9ba07 ¤   PGPContextRef ¤ ¤   context,
a8d7f0 ¤   union RingObject ¤  *to_sign,
6385ad ¤   RingSet¤ ¤  ¤   ¤   *dest,
82854a ¤   union RingObject ¤  *signer,
9cc12a ¤   RingSet const ¤ ¤   *src,·
94556e ¤   PGPByte ¤   ¤   ¤   sigtype,
31900e ¤   char const ¤¤   ¤   *passphrase,
8a03ab ¤   PGPSize ¤   ¤   ¤   passphraseLength,
3f5ed4 ¤   PGPBoolean ¤¤   ¤   hashedPhrase,
3cbc02 ¤   PGPBoolean ¤¤   ¤   selfsig,
bba286 ¤   PGPBoolean ¤¤   ¤   exportable,
0c7075 ¤   PGPBoolean ¤¤   ¤   exportableHashed,
af69b9 ¤   PGPTime¤¤   ¤   ¤   sigCreation,
73dc0f ¤   PGPUInt32 ¤ ¤   ¤   sigExpiration,
bd79d1 ¤   PGPByte ¤   ¤   ¤   trustDepth,
--0b4c 000cc2034f240100231 Page 2 of pgpKeyMan.c
96cbbb ¤   PGPByte ¤   ¤   ¤   trustValue,
322004 ¤   char const ¤¤   ¤   *sRegExp,
d5c4a7 ¤   RingSet const¤  ¤   *rakset,
270212 ¤   PGPUInt32¤  ¤   ¤   rakclass
4227e6 ¤   )
e0bb36 {
59fa53 ····PGPSecKey¤  ¤   *seckey = NULL;
d1451e ····PGPSigSpec¤ ¤   *sigspec = NULL;
17164d ¤   PGPEnv¤ ¤   ¤   *pgpEnv;
ee9d23 ¤   PGPRandomContext *pgpRng;
2ddf43 ¤   RingIterator¤   *rakIter;
c7cea1 ····PGPError¤   ¤   error = kPGPError_NoErr;
78af5a
f7e49e ¤   pgpEnv = pgpContextGetEnvironment( context );
c21988 ¤   pgpRng = pgpContextGetX9_17RandomContext( context );
cdaf5a
be1ad2 ¤   /* Error if not enough entropy for a safe signature */
244d81 ¤   if( ! PGPGlobalRandomPoolHasMinimumEntropy() )
efe843 ¤   ¤   return kPGPError_OutOfEntropy;
db67c5 ¤
7854a3 ¤   if (IsntNull(passphrase) && passphraseLength == 0)
5620bf ¤   ¤   passphrase = NULL;
40af5a
5b77be ¤   if (!signer || !ringKeyIsSec (src, signer) ||
10ddb0 ¤   ¤   !(ringKeyUse (src, signer) & PGP_PKUSE_SIGN))
38ea90 ¤   ····return kPGPError_SecretKeyNotFound;
bfaf5a
1d0e37 ····seckey = ringSecSecKey (src, signer, PGP_PKUSE_SIGN);
746484 ····if (!seckey)
2ca7ec ¤   ····return ringSetError(src)->error;
398aab ····if (pgpSecKeyIslocked (seckey)) {
fece59 ¤   ····if (IsNull( passphrase )) {
595d94 ¤   ¤   ····pgpSecKeyDestroy (seckey);
55222a ¤   ¤   ¤   return kPGPError_BadPassphrase;
840fe4 ¤   ¤   }
67cae1 ¤   ····error = (PGPError)pgpSecKeyUnlock (seckey, pgpEnv, passphrase,·
6ff879 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·passphraseLength, hashedPhrase);
fc8531 ¤   ¤   if (error != 1)
645b34 ¤   ¤   {
3c01fe ¤   ········pgpSecKeyDestroy (seckey);
d35acc ¤   ¤   ¤   if (error == 0)
982a9c ¤   ¤   ¤   ····error = kPGPError_BadPassphrase;
833b5b ¤   ¤   ¤   return error;
baf372 ¤   ····}
246fe7 ····}
411c70 ····sigspec = pgpSigSpecCreate (pgpEnv, seckey, sigtype);
f9541b ····if (!sigspec) {
5b1c67 ¤   ····pgpSecKeyDestroy (seckey);
c9df8e ¤   ····return kPGPError_OutOfMemory;
306fe7 ····}
114000 ¤   if (seckey->pkAlg > kPGPPublicKeyAlgorithm_RSA + 2 &&
bcbab3 ¤   ¤   ¤   sigtype == PGP_SIGTYPE_KEY_GENERIC && selfsig) {
f109d3 ¤   ¤   /* Propagate sig subpacket information */
e64cba ¤   ¤   PGPByte const *p;
2bc824 ¤   ¤   PGPSize plen;
3e6a04 ¤   ¤   pgpSigSpecSetVersion (sigspec, PGPVERSION_4);
65d12b ¤   ¤   if ((p=ringKeyFindSubpacket (signer, src,
3ce72b ¤   ¤   ¤   ¤   SIGSUB_PREFERRED_ENCRYPTION_ALGS, 0,
e1cd8a ¤   ¤   ¤   ¤   &plen, NULL, NULL, NULL, NULL, NULL)) != 0) {
d788f2 ¤   ¤   ¤   pgpSigSpecSetPrefAlgs (sigspec, 0, p, plen);
810fe4 ¤   ¤   }
a29bf7 ¤   ¤   if (ringKeyExpiration (src, signer)) {
489526 ¤   ¤   ¤   PGPUInt32 period = ringKeyExpiration (src, signer) -
e322f1 ¤   ¤   ¤   ¤   ringKeyCreation (src, signer);
062fa9 ¤   ¤   ¤   pgpSigSpecSetKeyExpiration (sigspec, 0, period);
720fe4 ¤   ¤   }
a69371 ¤   }
5b30e8 ¤   if (!exportable) {
5a6cf4 ¤   ¤   pgpSigSpecSetExportable (sigspec,
4e0453 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(exportableHashed ? 0 : kPGPSigFlags_Unhashed),
c924df ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·exportable);
cc9371 ¤   }
--9a93 000d05b4b5340100231 Page 3 of pgpKeyMan.c
2a67c5 ¤
3cefbe ¤   if( sigCreation != 0 )
45c7a1 ¤   {
b6f9f3 ¤   ¤   pgpSigSpecSetTimestamp( sigspec, sigCreation +
df8a9e ¤   ¤   ¤   ¤   (60 * 60 * pgpenvGetInt(pgpEnv, PGPENV_TZFIX, ·NULL, NULL)));
bd9371 ¤   }
6f67c5 ¤
d6e932 ¤   if (sigExpiration)
733c02 ¤   ¤   pgpSigSpecSetSigExpiration (sigspec, 0, sigExpiration);
c4f456 ¤   if( IsntNull( sRegExp ) )
a11f30 ¤   ¤   pgpSigSpecSetRegExp (sigspec, 0, sRegExp);
5daf5a
b6fe92 ¤   /* Ignore trustValue for ordinary level 0 signatures */
206f0f ¤   if (trustDepth != 0) {
8f2ea6 ¤   ¤   /* Convert trust value to extern format */
c3ff45 ¤   ¤   if (trustValue != 0)
d06071 ¤   ¤   ¤   trustValue = ringTrustOldToExtern(ringSetPool(dest), trustValue);
f7e157 ¤   ¤   /* Note that setting nonzero trustvalue forces V4 sigs */
09d5d8 ¤   ¤   pgpSigSpecSetTrustLevel (sigspec, 0, trustDepth, trustValue);
df9371 ¤   }
291988 ¤   pgpRng = pgpContextGetX9_17RandomContext( context );
63af5a
57182d ¤   /* Due to a bug in 5.0, all sigs directly on keys must be version 2_6.
eed33d ¤   ·* However the only signatures 5.0 handles directly on keys are key
208efc ¤   ·* revocations.
89a4e3 ¤   ·*/
68088f ¤   if (ringObjectType( to_sign ) == RINGTYPE_KEY &&
77f611 ¤   ¤   ¤   !ringKeyIsSubkey( dest, to_sign ) ·&&
f811c4 ¤   ¤   ¤   sigtype == PGP_SIGTYPE_KEY_REVOKE ) {
6e6778 ¤   ¤   pgpSigSpecSetVersion( sigspec, PGPVERSION_3 );
919371 ¤   }
17af5a
888c22 ¤   /* Handle revocation authorizations */
d949c7 ¤   if( IsntNull( rakset ) ) {
f84e46 ¤   ¤   rakIter = ringIterCreate (rakset);
c0666a ¤   ¤   if (!rakIter) {
528d2b ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
9f5c1d ¤   ¤   ¤   pgpSigSpecDestroy (sigspec);
e865d7 ¤   ¤   ¤   return ringSetError(rakset)->error;
ea0fe4 ¤   ¤   }
746be3 ¤   ¤   while (ringIterNextObject (rakIter, 1) > 0) {
d08bec ¤   ¤   ¤   PGPByte krinfo[22];
67cbeb ¤   ¤   ¤   PGPByte pkalg;
a88456 ¤   ¤   ¤   RingObject *krkey = ringIterCurrentObject (rakIter, 1);
4cde2d ¤   ¤   ¤   /* Note that rakclass must have 0x80 set to be effective */
1222fd ¤   ¤   ¤   ringKeyID8 (rakset, krkey, &pkalg, NULL);
26c30e ¤   ¤   ¤   krinfo[0] = rakclass;
483856 ¤   ¤   ¤   krinfo[1] = pkalg;
cd5c75 ¤   ¤   ¤   ringKeyFingerprint20 (rakset, krkey, krinfo+2);
7b31c0 ¤   ¤   ¤   error = pgpSigSpecSetRevocationKey (sigspec, 0, krinfo,
ee3a8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(krinfo) );
d609ae ¤   ¤   ¤   if (IsPGPError(error)) {
058367 ¤   ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
4d5aa5 ¤   ¤   ¤   ¤   pgpSigSpecDestroy (sigspec);
b58ec7 ¤   ¤   ¤   ¤   ringIterDestroy (rakIter);
84b20f ¤   ¤   ¤   ¤   return error;
4ba3a6 ¤   ¤   ¤   }
c40fe4 ¤   ¤   }
2fc178 ¤   ¤   ringIterDestroy (rakIter);
68cec9 ¤   ¤   /* Make this signature non-revocable */
b1978b ¤   ¤   pgpSigSpecSetRevocable (sigspec, 0, FALSE);
b59371 ¤   }
cfaf5a
6ac278 ¤   /* Do the signature at the Aurora level */
b9e7e6 ¤   error = ringSignObject (dest, to_sign, sigspec, pgpRng);
4b40a7 ¤   pgpSecKeyDestroy (seckey);
c96498 ¤   pgpSigSpecDestroy (sigspec);
68af5a
32c674 ¤   return error;
33efe6 }
3baf5a
d0af5a
--920f 00030d5f78840100231 Page 4 of pgpKeyMan.c
f99a4b /* ·Check for a 'dead' key. ·A dead key is revoked or expired.·
be287f ¤   There's not much you can do with such a key. */
05af5a
5866dd ¤   static PGPError
2236c7 pgpKeyDeadCheck( PGPKeyRef¤ key)
98bb36 {
84e5da ····PGPBoolean¤ revoked, expired;
7fee9f ····PGPError¤   err;
fe67c5 ¤
6f62c1 ¤   err¤= PGPGetKeyBoolean (key, kPGPKeyPropIsRevoked, &revoked);
52edac ¤   if ( IsntPGPError( err ) && revoked )
4d8f3a ¤   ¤   err¤= kPGPError_KeyRevoked;
6267c5 ¤
8af1e7 ¤   if ( IsntPGPError( err ) )
3dc7a1 ¤   {
0735c5 ¤   ¤   err¤= PGPGetKeyBoolean (key, kPGPKeyPropIsExpired, &expired);
941237 ¤   ¤   if ( IsntPGPError( err ) && expired )
c518af ¤   ¤   ¤   err¤= kPGPError_KeyExpired;
469371 ¤   }
9667c5 ¤
36fdcc ¤   return ( err );
45efe6 }
7baf5a
a1af5a
6aede0 /* Same for subkey... */
44af5a
4056b6 static PGPBoolean
a10982 pgpSubKeyIsDead (PGPSubKeyRef subkey)
3dbb36 {
08b918 ····PGPBoolean ··revoked, expired;
9b67c5 ¤
b28753 ¤   PGPGetSubKeyBoolean (subkey, kPGPKeyPropIsRevoked, &revoked);
2cc574 ¤   PGPGetSubKeyBoolean (subkey, kPGPKeyPropIsExpired, &expired);
16086e ¤   return (revoked || expired);
73efe6 }
3aaf5a
7caf5a
5e4782 /* ·Find the default private key. ·Get the name (or keyid) from the·
0ef60e ¤   environment, and find the PGPKey object. ·If there is no default·
426ffa ¤   key defined in the environment, return NULL unless there is·
b87906 ¤   only one private key in the key database.
6967c5 ¤
dcd1f8 ¤   The refCount on the key is incremented by this routine.
ba9faa ¤   */
1faf5a
2f66dd ¤   static PGPError
0e8456 pgpGetDefaultPrivateKeyInternal(
ee98e3 ¤   PGPKeyDBRef¤keyDB,
2c2814 ¤   PGPKey **¤  outKey)
86bb36 {
193333 ¤   PGPError¤   ¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
6652eb ¤   PGPByte *¤  ¤   ¤   keyIDData¤  = NULL;
17c87c ¤   PGPSize¤¤   ¤   ¤   keyIDSize¤  = 0;
e2aa0c ¤   PGPContextRef¤  ¤   context¤¤   = pgpGetKeyDBContext( keyDB );
4a67c5 ¤
66163a ¤   PGPValidatePtr( outKey );
e04c95 ¤   *outKey¤= kInvalidPGPKeyRef;
e267c5 ¤
1fd29b ¤   err¤= PGPsdkPrefGetData( context, kPGPsdkPref_DefaultKeyID,
becb3d ¤   ¤   ¤   ¤   &keyIDData, &keyIDSize );
45f1e7 ¤   if ( IsntPGPError( err ) )
80c7a1 ¤   {
97d4d7 ¤   ¤   PGPKeyID¤   ¤   keyID;
ca1b52 ¤   ¤
c4d569 ¤   ¤   err¤= PGPImportKeyID( keyIDData, &keyID );
767d98 ¤   ¤   if ( IsntPGPError( err ) )
b25b34 ¤   ¤   {
f90739 ¤   ¤   ¤   PGPKeySetRef kset = pgpKeyDBRootSet( keyDB );
2f87c7 ¤   ¤   ¤
051e5b ¤   ¤   ¤   err¤= PGPGetKeyByKeyID( kset, &keyID,
2fc1d2 ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyAlgorithm_Invalid, outKey );
30c0aa ¤   ¤   ¤   PGPFreeKeySet( kset );
--42f0 000d399773440100231 Page 5 of pgpKeyMan.c
b50fe4 ¤   ¤   }
3b1b52 ¤   ¤
ae126a ¤   ¤   /* we used public API call; must free using PGPFreeData() */
8347db ¤   ¤   PGPFreeData( keyIDData );
939371 ¤   }
bb67c5 ¤
a55ea8 ¤   return err;
34efe6 }
77af5a
3e70f7 /* ·END OF INTERNAL FUNCTIONS */
79af5a
46af5a
1e142b /* ·Copy an entire key to a new ringset. ·The newly created ringset is
35c9a0 ¤   returned. ·This function is necessary for two reasons:
670439 ····1. ringRaiseName requires all names to be present on the ringset to have·
e06abd ¤   ···any effect.·
55a08f ¤   2. to ensure a complete key (i.e. all it's sub-objects) are copied from·
8d5d1a ¤   ···a modified read-only key to a writable keyring.·
d37fe0 */
a5af5a
d6c77d PGPError
0b583d pgpCopyKey (RingSet const *src, union RingObject *obj, RingSet **dest)
65bb36 {
8e1170 ¤   RingIterator *iter = NULL;
5a8926 ¤   int¤¤   ¤   ¤   ¤   ·level;
b4af5a
ca699a ¤   if (!ringSetIsMember (src, obj))
da62b5 ¤   ¤   return kPGPError_BadParams;
15d9ce ¤   *dest = ringSetCreate (ringSetPool (src));
237d46 ¤   if (!*dest)
364030 ¤   ¤   return kPGPError_OutOfMemory;
e1ed65 ¤   iter = ringIterCreate (src);
6af222 ¤   if (!iter) {
ea9d3e ¤   ¤   ringSetDestroy (*dest);
774030 ¤   ¤   return kPGPError_OutOfMemory;
429371 ¤   }
7aaf5a
9e2a12 ¤   ringIterSeekTo (iter, obj);
dbd7c0 ¤   ringIterRewind (iter, 2); ··/* reset iterator to key object */
2e018b ¤   /* ·Loop adding objects until next key (level 1), or no more keys·
1f12a9 ¤   ¤   (level 0) */
0b7556 ¤   while ((level = ringIterNextObjectAnywhere (iter)) > 1) {
ad5950 ¤   ¤   obj = ringIterCurrentObject (iter, level);
a2e982 ¤   ¤   ringSetAddObject (*dest, obj);
e59371 ¤   }
a0fedf ¤   ringIterDestroy (iter);
f1151e ¤   return kPGPError_NoErr;
1defe6 }
88af5a
70af5a
c87aca /* ·Given a key ring object, find the corresponding PGPKey object. */
cfaf5a
30ebd0 PGPKey *
b1e0a0 pgpGetKeyByRingObject (PGPKeyDBRef keyDB, union RingObject *keyobj)
21bb36 {
b3be2f ¤   PGPKeyRef¤  keyptr;
76af5a
e908ac ¤   pgpAssert (ringObjectType (keyobj) == RINGTYPE_KEY);
d7af5a
99e98d ¤   for (keyptr = keyDB->firstKeyInDB; keyptr; keyptr = keyptr->nextKeyInDB) {
c5f33e ¤   ¤   if (keyobj == keyptr->key)
858cfa ¤   ¤   ¤   return keyptr;
b19371 ¤   }
3b3f59 ¤   return NULL;
bdefe6 }
efaf5a
73af5a
2ef1ae static PGPError
60cc4e sRevokeKey (
d2a1bc ¤   PGPContextRef¤  ¤   context,
6efb7a ¤   PGPKeyRef¤  ¤   ¤   key,
d3735d ¤   char const *¤   ¤   passphrase,
--36dc 0000e815cd940100231 Page 6 of pgpKeyMan.c
a49b39 ¤   PGPSize¤¤   ¤   ¤   passphraseLength,
993ce2 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase
6827e6 ¤   )
d0bb36 {
7b65c3 ····PGPKeyDBRef¤¤   ¤   ·keys = NULL;
ab97b2 ¤   RingSet¤const *¤¤   allset = NULL;
4fd7b7 ¤   RingSet *¤  ¤   ¤   addset = NULL;
389b72 ¤   union RingObject ···*keyobj;
e30381 ¤   union RingObject¤   *signkeyobj = NULL;
c6e9ed ¤   PGPUInt32¤  ¤   ¤   ·revnum;
bb6804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
1367c5 ¤
acd26b ¤   keys =¤ ¤   key->keyDB;
a34b52 ¤   keyobj =¤   key->key;
3baf5a
c2369b ¤   if ( !keys->objIsMutable( keys, keyobj ) )
227c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
d1bc97 ¤   if ( IsPGPError( pgpKeyDeadCheck(key) ) )
03408b ¤   ···return kPGPError_NoErr;¤ /* no need */
5f67c5 ¤
a6d640 ¤   allset = pgpKeyDBRingSet (keys);
44af5a
43cc68 ¤   error = pgpCopyKey (allset, keyobj, &addset);
240161 ¤   if (error)
d9fcee ¤   ¤   return error;
32af5a
ba1433 ¤   revnum = 0;
105870 ¤   for ( ; ; ) {
555ccd ¤   ¤   signkeyobj = keyobj;
e839d9 ¤   ¤   /* See if we have an authorized revocation signature */
04f17b ¤   ¤   if (!ringKeyIsSec (allset, keyobj)) {
927639 ¤   ¤   ¤   PGPByte revclass;
b182cc ¤   ¤   ¤   signkeyobj = ringKeyRevocationKey (keyobj, allset, revnum++,
5265d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL,
e5eb24 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&revclass, NULL, &error);
b15ed6 ¤   ¤   ¤   if( IsPGPError( error ) ) {
3d973f ¤   ¤   ¤   ¤   if( error == kPGPError_ItemNotFound )
eb032a ¤   ¤   ¤   ¤   ¤   error = kPGPError_NoErr;
11f622 ¤   ¤   ¤   ¤   break;
50a3a6 ¤   ¤   ¤   }
16e829 ¤   ¤   ¤   if( IsNull( signkeyobj ) )
76d040 ¤   ¤   ¤   ¤   continue;
feb96c ¤   ¤   ¤   if (!(revclass & 0x80))
c1d040 ¤   ¤   ¤   ¤   continue;
bb5c49 ¤   ¤   ¤   if (!ringKeyIsSec (allset, signkeyobj))
4ed040 ¤   ¤   ¤   ¤   continue;
bf0fe4 ¤   ¤   }
e99fc0 ¤   ¤   error = pgpCertifyObject (context, keyobj, addset, signkeyobj, allset,·
4d3d77 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGP_SIGTYPE_KEY_REVOKE, passphrase,
dfc922 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·passphraseLength, hashedPhrase, FALSE,
a7fb21 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·SIG_EXPORTABLE, 0, 0, kPGPExpirationTime_Never,
06dd3f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·0, 0, NULL, NULL, 0);
9ea1c9 ¤   ¤   /* Retry if bad passphrase and we are an authorized revoker */
ba231e ¤   ¤   if (error != kPGPError_BadPassphrase || signkeyobj == keyobj)
54cdcb ¤   ¤   ¤   break;
d29371 ¤   }
acaf5a
83a673 ¤   if (error) {
6bd98b ¤   ¤   ringSetDestroy (addset);
b4fcee ¤   ¤   return error;
669371 ¤   }
16af5a
1c15d8 ¤   /* ·Update the KeyDB */
48ca1f ¤   error = pgpAddObjects (keys, addset);
a462dd ¤   ringSetDestroy (addset);
b3af5a
2a63a2 ¤   /* Calculate trust changes as a result */
a3b2f3 ¤   if( error == kPGPError_NoErr )
310786 ¤   ¤   (void)pgpPropagateTrustKeyDB (keys);
72af5a
d1c674 ¤   return error;
0eefe6 }
--d644 000f0a3dbed40100231 Page 7 of pgpKeyMan.c
4bd83c ·
daaf5a
2bebc5 static const PGPOptionType revkeyOptionSet[] = {
254990 ¤   kPGPOptionType_Passphrase,
01e809 ¤   kPGPOptionType_Passkey
d482f7 };
6baf5a
3ec77d PGPError
cdc29a pgpRevokeKeyInternal(
5bfb7a ¤   PGPKeyRef¤  ¤   ¤   key,
fe0767 ¤   PGPOptionListRef¤   optionList )
4abb36 {
2f7925 ¤   PGPContextRef¤  ¤   context;
daca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
2643a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
30aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
107d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
54af5a
c84ed7 ¤   pgpa(pgpaPGPKeyValid(key));
f3d5b3 ¤   PGPValidateKey( key );
36af5a
7a7e18 ¤   context = key->keyDB->context;
b0af5a
da4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
582b3d ¤   ¤   ¤   ¤   ¤   ¤   revkeyOptionSet, elemsof( revkeyOptionSet ) ) ) )
bbc9db ¤   ¤   return err;
98af5a
9859d8 ¤   /* Pick up optional options */
e07bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
eaa6cc ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passphrase, FALSE,
40c4e4 ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
4297ed ¤   ¤   goto error;
000809 ¤   if (IsNull( passphrase )) {
365a97 ¤   ¤   hashedPhrase = TRUE;
115d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
df60d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
53c392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
3ced19 ¤   ¤   ¤   goto error;
219371 ¤   }
88af5a
6f930d ¤   err = sRevokeKey( context, key, passphrase, passphraseLength,
dec753 ¤   ¤   ¤   ¤   ¤   ··hashedPhrase );
7f60ff error:
145ea8 ¤   return err;
91efe6 }
daaf5a
92af5a
ecc4bc static const PGPOptionType keyentOptionSet[] = {
4ae23a ¤   kPGPOptionType_KeyGenParams,
963c7b ¤   kPGPOptionType_KeyGenFast
0382f7 };
26af5a
5e9504 /* Return the amount of entropy needed to create a key of the specified
4ac533 ···type and size. ·The application must call pgpRandpoolEntropy() itself
eb0867 ···until it has accumulated this much. */
a5af5a
a8bccf PGPUInt32
a29028 pgpKeyEntropyNeededInternal(
db520e ¤   PGPContextRef¤  context,
6b1efc ¤   PGPOptionListRef¤   optionList
cc27e6 ¤   )
43bb36 {
2e4ae4 ¤   PGPEnv¤ ¤   ¤   ¤   *pgpEnv;
53306b ¤   PGPUInt32¤  ¤   ¤   fastgen;
91229a ¤   PGPBoolean¤ ¤   ¤   fastgenop;
6c31d2 ¤   PGPUInt32¤  ¤   ¤   pkalg;
5935ad ¤   PGPUInt32¤  ¤   ¤   bits;
8a7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
fdaf5a
cc4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
27e84a ¤   ¤   ¤   ¤   ¤   ¤   keyentOptionSet, elemsof( keyentOptionSet ) ) ) )
f0c9db ¤   ¤   return err;
--b5d1 000932fce3140100231 Page 8 of pgpKeyMan.c
e0af5a
bde49e ¤   pgpEnv = pgpContextGetEnvironment( context );
997bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
a69a7a ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenParams, TRUE,
d0d2a6 ¤   ¤   ¤   ¤   ¤   ¤   "%d%d", &pkalg, &bits ) ) )
ab97ed ¤   ¤   goto error;
7b7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
6e8f8a ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenFast, FALSE,
1ed5bd ¤   ¤   ¤   ¤   ¤   ¤   "%b%d", &fastgenop, &fastgen ) ) )
d997ed ¤   ¤   goto error;
795282 ¤   if( !fastgenop ) {
e64cd6 ¤   ¤   fastgen = pgpenvGetInt (pgpEnv, PGPENV_FASTKEYGEN, NULL, NULL);
9a9371 ¤   }
8b02a1 ¤   fastgen = pgpenvGetInt (pgpEnv, PGPENV_FASTKEYGEN, NULL, NULL);
b6af5a
59de2a ¤   return pgpSecKeyEntropy (pgpPkalgByNumber ((PGPByte)pkalg), bits,
c1d897 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean)fastgen);
8faf5a
62f2c7 ¤   /* Should not have an error unless bad parameters */
4b60ff error:
704aac ¤   pgpAssert(0);
2b28c5 ¤   return ~(PGPUInt32)0;
8befe6 }
9faf5a
49af5a
344086 /* Internal function for passphraseIsValid */
6b66dd ¤   static PGPError
933906 sPassphraseIsValid(
80cd9b ¤   PGPKeyRef¤  ¤   key,
66c87c ¤   const char *¤   passphrase,
02ff79 ¤   PGPSize¤¤   ¤   passphraseLength,
8aaf5b ¤   PGPBoolean¤ ¤   hashedPhrase,
200d4c ¤   PGPBoolean *¤   isValid)
2dbb36 {
6c9203 ¤   RingObject *¤   keyobj;
247f3a ¤   PGPKeyDBRef¤¤   keys;
1449e8 ¤   RingSet const *¤ringset;
208a97 ¤   PGPContextRef¤  context;
f137d0 ¤   PGPEnv *¤   ¤   pgpEnv;
3aae43 ¤   PGPSecKey *¤¤   seckey;
e967c5 ¤
8b3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
42af5a
92d5b3 ¤   PGPValidateKey( key );
eef823 ¤   PGPValidateParam( passphrase );
8e55ab ¤   PGPValidateParam( isValid );
eeaf5a
d86029 ¤   /* Default return value */
29e9d8 ¤   *isValid = FALSE;
94af5a
2843ae ¤   /* Dig stuff out of key structure */
664b52 ¤   keyobj =¤   key->key;
1ad26b ¤   keys =¤ ¤   key->keyDB;
e1cf07 ¤   ringset =¤  pgpKeyDBRingSet (keys);
c976c2 ¤   context =¤  keys->context;
b91788 ¤   pgpEnv =¤   pgpContextGetEnvironment( context );
cfaf5a
90ec1c ¤   seckey = ringSecSecKey (ringset, keyobj, 0);
b2af5a
03df2b ¤   /* If not a secret key, just return */
60dcea ¤   if( !seckey )
9ac9db ¤   ¤   return err;
96af5a
15c864 ¤   /* Returns 1 on success, 0 on failure, else error */
403324 ¤   err = (PGPError)pgpSecKeyUnlock (seckey, pgpEnv, passphrase,·
c4cf95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passphraseLength, hashedPhrase);
e9aedd ¤   pgpSecKeyDestroy( seckey );
6a43c1 ¤   if (err == (PGPError)1) {
18d7ef ¤   ¤   *isValid = TRUE;
8470bb ¤   ¤   err = kPGPError_NoErr;
3f9371 ¤   }
935ea8 ¤   return err;
--abe6 0007044113740100231 Page 9 of pgpKeyMan.c
7aefe6 }
46af5a
4967c5 ¤
56af5a
ab496c static const PGPOptionType passphraseisvalidOptionSet[] = {
344990 ¤   kPGPOptionType_Passphrase,
80e809 ¤   kPGPOptionType_Passkey
9982f7 };
b4af5a
5c16ea ¤   PGPBoolean
4345e9 pgpPassphraseIsValidInternal(
44fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
401efc ¤   PGPOptionListRef¤   optionList
3627e6 ¤   )
dfbb36 {
a47925 ¤   PGPContextRef¤  ¤   context;
f0ca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
df43a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
21aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
6b5b5e ¤   PGPBoolean¤ ¤   ¤   rslt;
bf7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
beaf5a
014ed7 ¤   pgpa(pgpaPGPKeyValid(key));
35f25b ¤   if ( ! pgpKeyIsValid( key ) )
a5e20d ¤   ¤   return( FALSE );
de67c5 ¤
4d7e18 ¤   context = key->keyDB->context;
58af5a
564271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
029bf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passphraseisvalidOptionSet,
a2ac95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   elemsof( passphraseisvalidOptionSet ) ) ) )
4c98aa ¤   ¤   return FALSE;
f7af5a
55d2ab ¤   /* Pick up mandatory options */
207bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
0b4dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
3e8dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
4798aa ¤   ¤   return FALSE;
f70809 ¤   if (IsNull( passphrase )) {
d65a97 ¤   ¤   hashedPhrase = TRUE;
3b5d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
90b0c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, TRUE,
34c392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
905f1f ¤   ¤   ¤   return FALSE;
d39371 ¤   }
90af5a
7caef9 ¤   if( IsPGPError( sPassphraseIsValid( key, passphrase, passphraseLength,
4bebb1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   hashedPhrase, &rslt ) ) )
cb98aa ¤   ¤   return FALSE;
deaf5a
1e5d4b ¤   return rslt;
10efe6 }
8daf5a
8467c5 ¤
7aaf5a
9eaf5a
1a0335 /*____________________________________________________________________________
3d742f ¤   Key Generation
b9f7f7 ____________________________________________________________________________*/
4baf5a
f1af5a
bf38e5 /*
b9b1ba ·* Callback impedence matching, convert from internal state to callback
c17945 ·* state.
a5495d ·*/
ccfdd0 typedef struct PGPKeyGenProgressState {
05429f ¤   PGPContextRef¤  ¤   ¤   context;
bd9507 ¤   PGPEventHandlerProcPtr¤ progress;
3a7b2d ¤   PGPUserValue¤   ¤   ¤   userValue;
56debd } PGPKeyGenProgressState;
ab67c5 ¤
70c886 static int¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* Return < 0 to abort run */
--af32 000d4271f9440100231 Page 10 of pgpKeyMan.c
64bb0d genProgress(
88d60f ¤   void *arg,
e735a9 ¤   int c
7427e6 ¤   )
17bb36 {
fcd44f ¤   PGPKeyGenProgressState¤ *s = (PGPKeyGenProgressState *)arg;
d83cbe ¤   PGPError¤   ¤   ¤   ¤   err = kPGPError_NoErr;
161592 ¤   PGPOptionListRef¤   ¤   newOptionList = NULL;
26af5a
370592 ¤   if (IsntNull (s->progress)) {
598298 ¤   ¤   err = pgpEventKeyGen (s->context, &newOptionList,
eabf75 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·s->progress, s->userValue, (PGPUInt32)c);
7f259e ¤   ¤   if (IsntNull (newOptionList))
8d6dc7 ¤   ¤   ¤   pgpFreeOptionList (newOptionList);
279371 ¤   }
1c5ea8 ¤   return err;
17efe6 }
b4af5a
35af5a
d7af5a
79e0ea /* ·Common code for generating master keys and subkeys. *masterkey
558b20 ····is NULL when generating a master key, and is used to return
617d09 ¤   the master PGPKey object. ·If *masterkey contains a value,
32931e ¤   a subkey is to be generated associated with the PGPKey object. */
6baf5a
bf66dd ¤   static PGPError
c15a49 pgpDoGenerateKey (
787c45 ¤   PGPKeyDB *¤ ¤   keyDB,
7866b0 ¤   PGPKey **¤  ¤   masterkey,
702c88 ¤   PGPSubKey **¤   newsubkey,
f25ba0 ¤   PGPByte¤¤   ¤   pkalg,
81d042 ¤   unsigned¤   ¤   bits,
36fc0b ¤   PGPTime¤¤   ¤   creationDate,
f7a0cb ¤   PGPUInt16¤  ¤   expirationDays,
2f2d64 ¤   char const *¤   name,
79b140 ¤   int¤¤   ¤   ¤   name_len,·
cb0ce7 ¤   char const *¤   passphrase,
7eff79 ¤   PGPSize¤¤   ¤   passphraseLength,
9c439d ¤   PGPBoolean¤ ¤   passphraseIsKey,
025902 ¤   char const *¤   masterpass,·
a27b60 ¤   PGPSize¤¤   ¤   masterpassLength,
e147fa ¤   PGPEventHandlerProcPtr progress,
b83298 ¤   PGPUserValue¤   userValue,
0cd605 ¤   PGPBoolean¤ ¤   fastgen,
2aac8e ¤   RingSet const *¤adkset,
7916d2 ¤   PGPByte¤¤   ¤   adkclass,
d78d85 ¤   RingSet const *¤rakset,
33c2f1 ¤   PGPByte¤¤   ¤   rakclass,
ac4c52 ¤   PGPCipherAlgorithm const * prefalg,
29ab3b ¤   PGPSize¤¤   ¤   prefalgLength)
7dbb36 {
9a0748 ¤   RingSet const¤  ¤   ¤   *allset;
55c255 ¤   RingSet ¤   ¤   ¤   ¤   *addset = NULL;
35878f ¤   union RingObject ···¤   *newobj = NULL;
4ab964 ¤   PGPError¤   ··········¤ error = kPGPError_NoErr;
0a5fca ¤   PGPSecKey¤  ¤   ¤   ¤   *seckey = NULL, *masterseckey = NULL;
5f26ee ¤   PGPKeySpec¤ ¤   ¤   ¤   *keyspec = NULL;
7ce928 ¤   long ············¤  ¤   entropy_needed, entropy_available;
49b1e7 ¤   PGPBoolean ·············genMaster = (*masterkey == NULL);
2d37fa ¤   PGPEnv¤ ¤   ¤   ¤   ¤   *pgpEnv;
17f926 ¤   PGPRandomContext¤   ¤   *pgpRng;
cb66ac ¤   PGPKeyGenProgressState¤ progressState;
9d9e13 ¤   PGPContextRef¤  ¤   ¤   context¤= pgpGetKeyDBContext( keyDB );
9fce73 ¤   PGPByte¤¤   ¤   ¤   ¤   *prefalgByte;
6cde7c ¤   PGPUInt32¤  ¤   ¤   ¤   i;
891d03 ¤   const PGPPkAlg *¤   ¤   algInfo;
6567c5 ¤
594db7 ¤   if ( !pgpKeyDBIsMutable( keyDB ) )
ab7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
7caf5a
2a6412 ¤   algInfo = pgpPkalgByNumber( pkalg );
d410c8 ¤   if( IsntNull( algInfo ) )
--b4c4 0007acafbfa40100231 Page 11 of pgpKeyMan.c
f7c7a1 ¤   {
658e22 ¤   ¤   if( ( pgpKeyUse( algInfo ) & PGP_PKUSE_SIGN ) == 0 &&
d4381f ¤   ¤   ¤   genMaster )
fa5b34 ¤   ¤   {
348454 ¤   ¤   ¤   pgpDebugMsg( "Invalid master key algorithm" );
6ed03e ¤   ¤   ¤   error = kPGPError_BadParams;
aa0fe4 ¤   ¤   }
32a0ad ¤   ¤   else if( ( pgpKeyUse( algInfo ) & PGP_PKUSE_ENCRYPT ) == 0 &&
3b5013 ¤   ¤   ¤   ¤   ! genMaster )
425b34 ¤   ¤   {
dcc204 ¤   ¤   ¤   pgpDebugMsg( "Invalid subkey algorithm" );
77d03e ¤   ¤   ¤   error = kPGPError_BadParams;
fd0fe4 ¤   ¤   }
d09371 ¤   }
7b0e24 ¤   else
92c7a1 ¤   {
c8ef95 ¤   ¤   pgpDebugMsg( "Invaid public key algorithm" );
85d5d3 ¤   ¤   error = kPGPError_BadParams;
4b9371 ¤   }
7067c5 ¤
bd534a ¤   if( IsPGPError( error ) )
8748b9 ¤   ¤   goto cleanup;
db1b52 ¤   ¤
50183c ¤   pgpEnv = pgpContextGetEnvironment( keyDB->context );
678b0f ¤   /* Check we have sufficient random bits to generate the keypair */
5ef682 ¤   entropy_needed = pgpSecKeyEntropy (algInfo, bits, fastgen);
f7f891 ¤   entropy_available = PGPGlobalRandomPoolGetEntropy ( );
9c2416 ¤   if (entropy_needed > entropy_available)
d3c7a1 ¤   {
8d6660 ¤   ···¤error = kPGPError_OutOfEntropy;
1148b9 ¤   ¤   goto cleanup;
aa9371 ¤   }
bb67c5 ¤
dee162 ¤   /* Generate the secret key */
4e226d ¤   progressState.progress = progress;
3819af ¤   progressState.userValue = userValue;
178020 ¤   progressState.context = keyDB->context;
b00044 ¤   pgpRng = pgpContextGetX9_17RandomContext( keyDB->context );
101c7e ¤   seckey = pgpSecKeyGenerate( context, algInfo, bits, fastgen, pgpRng,·
9c8855 ¤   ¤   ¤   ¤   genProgress, &progressState, &error);
1b0161 ¤   if (error)
a148b9 ¤   ¤   goto cleanup;
f8ccfb ¤   pgpRandomStir (pgpRng);
aaaf5a
cf4582 ¤   /* Need to lock the SecKey with the passphrase. ·*/
46a34e ¤   if (passphrase && passphraseLength > 0) {
dd86ae ¤   ¤   PGPStringToKeyType s2ktype;
0d7e18 ¤   ¤   if (passphraseIsKey) {
143e53 ¤   ¤   ¤   s2ktype = kPGPStringToKey_LiteralShared;
eab3d8 ¤   ¤   } else if (seckey->pkAlg <= kPGPPublicKeyAlgorithm_RSA + 2) {
e1dc6b ¤   ¤   ¤   s2ktype = kPGPStringToKey_Simple;
9745a6 ¤   ¤   } else {
9ca842 ¤   ¤   ¤   s2ktype = kPGPStringToKey_IteratedSalted;
ee0fe4 ¤   ¤   }
cc132b ¤   ¤   error = (PGPError)pgpSecKeyChangeLock (seckey, pgpEnv, pgpRng,·
c5d1c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passphrase, passphraseLength,
d0226e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   s2ktype);
abe3c2 ¤   ¤   if (error)
dc8f0c ¤   ¤   ¤   goto cleanup;
019371 ¤   }
c9af5a
41940d ¤   /* ·Generate the keyring objects. ·Use keyspec defaults except for·
b294cc ¤   ¤   expiration (validity) period */
e7b3a3 ¤   keyspec = pgpKeySpecCreate (pgpEnv);
624b3b ¤   if (!keyspec) {
b3b081 ¤   ¤   error = kPGPError_OutOfMemory;
6948b9 ¤   ¤   goto cleanup;
359371 ¤   }
e067c5 ¤
198a8e ¤   if( creationDate != 0 )
8ac7a1 ¤   {
7afacf ¤   ¤   pgpKeySpecSetCreation(keyspec, creationDate +
--43f0 000decce2bf40100231 Page 12 of pgpKeyMan.c
6c8a9e ¤   ¤   ¤   ¤   (60 * 60 * pgpenvGetInt(pgpEnv, PGPENV_TZFIX, ·NULL, NULL)));
7c9371 ¤   }
e767c5 ¤
55d582 ¤   pgpKeySpecSetValidity (keyspec, expirationDays);
a0af5a
0dcf23 ¤   allset = pgpKeyDBRingSet (keyDB);
e5af5a
f38b51 ¤   if (genMaster) {
df1983 ¤   ···/* Generating master signing key */ ·
afb89c ¤   ···addset = ringSetCreate (ringSetPool (allset));
aa3b60 ¤   ¤   if (!addset) {
e88d6d ¤   ¤   ···error = kPGPError_OutOfMemory;
768f0c ¤   ¤   ¤   goto cleanup;
730fe4 ¤   ¤   }
309108 ¤   ¤   prefalgByte = NULL;
253acb ¤   ¤   if (prefalgLength > 0) {
5ed6c9 ¤   ¤   ¤   /* Convert preferred algorithm to byte array */
74ca85 ¤   ¤   ¤   prefalgLength /= sizeof(PGPCipherAlgorithm);
17500f ¤   ¤   ¤   prefalgByte = (PGPByte *)pgpContextMemAlloc( context,
11843d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   prefalgLength, 0);
260d9e ¤   ¤   ¤   if( IsNull( prefalgByte ) ) {
172f55 ¤   ¤   ¤   ¤   error = kPGPError_OutOfMemory;
d30658 ¤   ¤   ¤   ¤   goto cleanup;
8ca3a6 ¤   ¤   ¤   }
f17c7b ¤   ¤   ¤   for (i=0; i<prefalgLength; ++i) {
e8b2b5 ¤   ¤   ¤   ¤   prefalgByte[i] = (PGPByte)prefalg[i];
9ea3a6 ¤   ¤   ¤   }
9e0fe4 ¤   ¤   }
bc3b23 ¤   ···newobj = ringCreateKeypair (pgpEnv, seckey, keyspec, name,
0b7f1b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   name_len, pgpRng, addset, addset,
ffb410 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   rakset, rakclass,
5bb4e7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   prefalgByte, prefalgLength,
c04c48 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ····adkset, adkclass,
d5c22b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &error);
ef01e4 ¤   ¤   if( IsntNull( prefalgByte ) ) {
759be5 ¤   ¤   ¤   pgpContextMemFree( context, prefalgByte );
a00fe4 ¤   ¤   }
099371 ¤   }
a8665a ¤   else {
9732a6 ¤   ···/* Generating encryption subkey. ·Get the master seckey and·
4cb57e ¤   ¤   ··unlock it */
d07bfc ¤   ···error = pgpCopyKey (allset, (*masterkey)->key, &addset);
4ee3c2 ¤   ¤   if (error)
24759a ¤   ¤   ···goto cleanup;
bcdda6 ¤   ···masterseckey = ringSecSecKey (allset, (*masterkey)->key,·
667f38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGP_PKUSE_SIGN);
5c35e0 ¤   ¤   if (!masterseckey) {
2a45f5 ¤   ¤   ···error = ringSetError(allset)->error;
a98f0c ¤   ¤   ¤   goto cleanup;
700fe4 ¤   ¤   }
4fcf16 ¤   ¤   if (pgpSecKeyIslocked (masterseckey)) {
5f7d74 ¤   ¤   ···if (IsNull( masterpass )) {
76cc7a ¤   ¤   ¤   ···error = kPGPError_BadPassphrase;
6341c7 ¤   ¤   ¤   ···goto cleanup;
61a3a6 ¤   ¤   ¤   }
d3aeac ¤   ¤   ¤   error = (PGPError)pgpSecKeyUnlock (masterseckey, pgpEnv,
f4f6e5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   masterpass, masterpassLength, FALSE);
b03efc ¤   ¤   ¤   if (error != 1) {
b45af0 ¤   ¤   ¤   ···if (error == 0)·
555a3b ¤   ¤   ¤   ¤   ···error = kPGPError_BadPassphrase;
220658 ¤   ¤   ¤   ¤   goto cleanup;
8ca3a6 ¤   ¤   ¤   }
560fe4 ¤   ¤   }
8e0c3f ¤   ···newobj = ringCreateSubkeypair (pgpEnv, masterseckey, seckey,
c5725b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyspec, pgpRng, addset, addset, &error);
e19371 ¤   }
ba4b09 ¤   pgpRandomStir (pgpRng);¤¤   /* this helps us count randomness in pool */
370161 ¤   if (error)
7248b9 ¤   ¤   goto cleanup;
e6af5a
8a3822 ¤   /* ·Add objects to main KeyDB. ·Before doing so, locate
de5cf1 ¤   ···the master key object and return it. */
--a7d3 0005f01851540100231 Page 13 of pgpKeyMan.c
67fcd6 ¤   ringSetFreeze (addset);
677ace ¤   error = pgpAddObjects (keyDB, addset);
d64249 ¤   if (genMaster && !error) {
cc99b4 ¤   ···*masterkey = pgpGetKeyByRingObject (keyDB, newobj);
99fa1b ¤   } else if (!genMaster && !error && IsntNull( newsubkey ) ) {
3a8f45 ¤   ¤   PGPSubKey *subk = (PGPSubKey *) (*masterkey)->subKeys.next;
2b75be ¤   ¤   while( subk != (PGPSubKey *) &(*masterkey)->subKeys ) {
92f468 ¤   ¤   ¤   if( subk->subKey == newobj )
ddf622 ¤   ¤   ¤   ¤   break;
2b50a5 ¤   ¤   ¤   subk = subk->next;
240fe4 ¤   ¤   }
b032b5 ¤   ¤   pgpAssert( subk->subKey == newobj );
ccf80f ¤   ¤   *newsubkey = subk;
4d9371 ¤   }
a1af5a
ff68cb cleanup:
035e73 ¤   if (addset)
e2d98b ¤   ¤   ringSetDestroy (addset);
239c7f ¤   if (seckey)
a5ccd8 ¤   ¤   pgpSecKeyDestroy (seckey);
883960 ¤   if (masterseckey)
12e2c4 ¤   ···pgpSecKeyDestroy (masterseckey);
be2148 ¤   if (keyspec)
f79151 ¤   ¤   pgpKeySpecDestroy (keyspec);
b9c674 ¤   return error;
6cefe6 }
f1af5a
5caf5a
3dbccf static const PGPOptionType keygenOptionSet[] = {
d750c0 ¤   kPGPOptionType_KeySetRef,
c6e23a ¤   kPGPOptionType_KeyGenParams,
048623 ¤   kPGPOptionType_KeyGenName,
354990 ¤   kPGPOptionType_Passphrase,
514590 ¤   kPGPOptionType_Passkey,
265e67 ¤   kPGPOptionType_Expiration,
31a688 ¤   kPGPOptionType_CreationDate,
cf074a ¤   kPGPOptionType_EventHandler,
9b8c4e ¤   kPGPOptionType_PreferredAlgorithms,
1e3e71 ¤   kPGPOptionType_AdditionalRecipientRequestKeySet,
173cea ¤   kPGPOptionType_RevocationKeySet,
e43c7b ¤   kPGPOptionType_KeyGenFast
dc82f7 };
deaf5a
ccc77d PGPError
b2c571 pgpGenerateKeyInternal(
a7a1bc ¤   PGPContextRef¤  ¤   context,
4a8d16 ¤   PGPKeyRef¤  ¤   ¤   *key,
ae1efc ¤   PGPOptionListRef¤   optionList
5627e6 ¤   )
a1bb36 {
62b604 ¤   PGPKeySetRef¤   ¤   keyset;
0831d2 ¤   PGPUInt32¤  ¤   ¤   pkalg;
2935ad ¤   PGPUInt32¤  ¤   ¤   bits;
7ab778 ¤   PGPUInt32¤  ¤   ¤   expiration;
0c5c86 ¤   PGPTime¤¤   ¤   ¤   creationDate;
f5171a ¤   PGPByte¤¤   ¤   ¤   *name;
67a873 ¤   PGPUInt32¤  ¤   ¤   nameLength;
e877d2 ¤   PGPByte¤¤   ¤   ¤   *passphrase;
b742e3 ¤   PGPUInt32¤  ¤   ¤   passphraseLength;
1d8a02 ¤   PGPBoolean¤ ¤   ¤   passphraseIsKey = FALSE;
5c45e4 ¤   PGPKeySetRef¤   ¤   adkset;
a2e792 ¤   PGPUInt32¤  ¤   ¤   adkclass;
135f6e ¤   PGPKeySetRef¤   ¤   rakset = NULL;
d86bd8 ¤   PGPUInt32¤  ¤   ¤   rakclass = 0;
489f63 ¤   PGPEventHandlerProcPtr progress;
094e6a ¤   PGPUserValue¤   ¤   userValue;
580bce ¤   RingSet const¤  ¤   *adkringset = NULL;
8dc945 ¤   RingSet const¤  ¤   *rakringset = NULL;
50feb4 ¤   PGPKeyRef¤  ¤   ¤   newkey;
f2dc56 ¤   PGPCipherAlgorithm¤ *prefalg;
b45715 ¤   PGPSize¤¤   ¤   ¤   prefalgLength;
5f4ae4 ¤   PGPEnv¤ ¤   ¤   ¤   *pgpEnv;
--3b36 0009a6a2d6740100231 Page 14 of pgpKeyMan.c
f5229a ¤   PGPBoolean¤ ¤   ¤   fastgenop;
57306b ¤   PGPUInt32¤  ¤   ¤   fastgen;
6e8f52 ¤   PGPError¤   ¤   ¤   err;
9caf5a
de4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
50aca4 ¤   ¤   ¤   ¤   ¤   ¤   keygenOptionSet, elemsof( keygenOptionSet ) ) ) )
f9c9db ¤   ¤   return err;
4faf5a
4899da ¤   if( IsNull( key ) )
eb62b5 ¤   ¤   return kPGPError_BadParams;
b2af5a
72e49e ¤   pgpEnv = pgpContextGetEnvironment( context );
ffaf5a
4a366b ¤   /* First pick up mandatory options */
1b7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e4fc2f ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeySetRef, TRUE,
0bf473 ¤   ¤   ¤   ¤   ¤   ¤   "%p", &keyset ) ) )
b297ed ¤   ¤   goto error;
b467c5 ¤
f77bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
8a9a7a ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenParams, TRUE,
8bd2a6 ¤   ¤   ¤   ¤   ¤   ¤   "%d%d", &pkalg, &bits ) ) )
b697ed ¤   ¤   goto error;
11af5a
c37bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
894d80 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenName, TRUE,
bccb3f ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &name, &nameLength ) ) )
4997ed ¤   ¤   goto error;
69af5a
7aaa1d ¤   /* Now get optional parameters */
4a7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
45a6cc ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passphrase, FALSE,
fac4e4 ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
9697ed ¤   ¤   goto error;
160809 ¤   if (IsNull( passphrase )) {
775d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
1860d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
adc392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
82ed19 ¤   ¤   ¤   goto error;
211711 ¤   ¤   if( IsntNull( passphrase ) )
3ac813 ¤   ¤   ¤   passphraseIsKey = TRUE;
239371 ¤   }
97af5a
057bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
85499c ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_CreationDate, FALSE,
d06d76 ¤   ¤   ¤   ¤   ¤   ¤   "%T", &creationDate ) ) )
5797ed ¤   ¤   goto error;
ebaf5a
b17bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
58a8e4 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Expiration, FALSE,
e7655c ¤   ¤   ¤   ¤   ¤   ¤   "%d", &expiration ) ) )
a597ed ¤   ¤   goto error;
67af5a
037bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
d2bbd5 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_EventHandler, FALSE,
055612 ¤   ¤   ¤   ¤   ¤   ¤   "%p%p", &progress, &userValue ) ) )
e097ed ¤   ¤   goto error;
a667c5 ¤
047bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
046318 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PreferredAlgorithms, FALSE,
b96b6a ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &prefalg, &prefalgLength ) ) )
7597ed ¤   ¤   goto error;
7baf5a
267bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
bb20ed ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_AdditionalRecipientRequestKeySet,
fbf083 ¤   ¤   ¤   ¤   ¤   ¤   FALSE, "%p%d", &adkset, &adkclass ) ) )
0897ed ¤   ¤   goto error;
fa9dc3 ¤   if( IsntNull( adkset ) ) {
16cff6 ¤   ¤   if( IsPGPError( err = pgpKeySetRingSet( adkset, TRUE, &adkringset ) ) )
2eed19 ¤   ¤   ¤   goto error;
d59371 ¤   }
9aaf5a
--2982 00069d5bd2540100231 Page 15 of pgpKeyMan.c
d27bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
c8f8c4 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RevocationKeySet, FALSE,
fd7c13 ¤   ¤   ¤   ¤   ¤   ¤   "%p%d", &rakset, &rakclass ) ) )
0597ed ¤   ¤   goto error;
3449c7 ¤   if( IsntNull( rakset ) ) {
5c4f52 ¤   ¤   if( IsPGPError( err = pgpKeySetRingSet( rakset, TRUE, &rakringset ) ) )
13ed19 ¤   ¤   ¤   goto error;
db9371 ¤   }
90af5a
777bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
698f8a ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyGenFast, FALSE,
f1d5bd ¤   ¤   ¤   ¤   ¤   ¤   "%b%d", &fastgenop, &fastgen ) ) )
b497ed ¤   ¤   goto error;
8a5282 ¤   if( !fastgenop ) {
6f4cd6 ¤   ¤   fastgen = pgpenvGetInt (pgpEnv, PGPENV_FASTKEYGEN, NULL, NULL);
0c9371 ¤   }
f467c5 ¤
cdeda4 ¤   *key = NULL;
e683d5 ¤   newkey = NULL;¤ ¤   /* Necessary to flag masterkey vs subkey */
004a9f ¤   err = pgpDoGenerateKey( keyset->keyDB, &newkey, NULL, (PGPByte)pkalg,
6fea9c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··bits, creationDate, (PGPUInt16)expiration,
5efab6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(const char *)name, nameLength,
574e40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(const char *)passphrase, passphraseLength,
c5f1e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··passphraseIsKey, NULL, 0,
c9e12f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··progress, userValue,
481985 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPBoolean)fastgen,
6552be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··adkringset, (PGPByte)adkclass,
5a5163 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··rakringset, (PGPByte)rakclass,
57088d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···prefalg, prefalgLength );
c067c5 ¤
95b1f0 ¤   if( IsntPGPError( err ) )
6cb5e9 ¤   ····*key = newkey;
79af5a
6f60ff error:
ebb9a1 ¤   if( IsntNull( adkringset ) )
aafd18 ¤   ¤   ringSetDestroy( (RingSet *) adkringset );
834e68 ¤   if( IsntNull( rakringset ) )
a0bbe8 ¤   ¤   ringSetDestroy( (RingSet *) rakringset );
575ea8 ¤   return err;
7cefe6 }
45af5a
a1ee5c static const PGPOptionType subkeygenOptionSet[] = {
1b1f09 ¤   ·kPGPOptionType_KeyGenMasterKey,
8b551b ¤   ·kPGPOptionType_KeyGenParams,
b028df ¤   ·kPGPOptionType_Passphrase,
0c7fbb ¤   ·kPGPOptionType_Passkey,
6c3f28 ¤   ·kPGPOptionType_Expiration,
9011a9 ¤   ·kPGPOptionType_CreationDate,
10b06b ¤   ·kPGPOptionType_EventHandler,
1f6539 ¤   ·kPGPOptionType_KeyGenFast
8a82f7 };
6daf5a
cfc77d PGPError
e4547a pgpGenerateSubKeyInternal(
aca1bc ¤   PGPContextRef¤  ¤   context,
3671e9 ¤   PGPSubKeyRef¤   ¤   *subkey,
a41efc ¤   PGPOptionListRef¤   optionList
3b27e6 ¤   )
26bb36 {
3c31d2 ¤   PGPUInt32¤  ¤   ¤   pkalg;
3a35ad ¤   PGPUInt32¤  ¤   ¤   bits;
765c86 ¤   PGPTime¤¤   ¤   ¤   creationDate;
4db778 ¤   PGPUInt32¤  ¤   ¤   expiration;
7477d2 ¤   PGPByte¤¤   ¤   ¤   *passphrase;
0e42e3 ¤   PGPUInt32¤  ¤   ¤   passphraseLength;
798a02 ¤   PGPBoolean¤ ¤   ¤   passphraseIsKey = FALSE;
099f63 ¤   PGPEventHandlerProcPtr progress;
6e4e6a ¤   PGPUserValue¤   ¤   userValue;
0b06f7 ¤   PGPKeyRef¤  ¤   ¤   masterkey;
3844ab ¤   PGPSubKeyRef¤   ¤   newsubkey;
fe4ae4 ¤   PGPEnv¤ ¤   ¤   ¤   *pgpEnv;
69229a ¤   PGPBoolean¤ ¤   ¤   fastgenop;
--ba8b 000507ec92c40100231 Page 16 of pgpKeyMan.c
4b306b ¤   PGPUInt32¤  ¤   ¤   fastgen;
3f8f52 ¤   PGPError¤   ¤   ¤   err;
ebaf5a
1f4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
31ef22 ¤   ¤   ¤   ¤   ¤   ···subkeygenOptionSet, elemsof( subkeygenOptionSet ) ) ) )
8bc9db ¤   ¤   return err;
09af5a
970977 ¤   if( IsNull( subkey ) )
b962b5 ¤   ¤   return kPGPError_BadParams;
7eaf5a
5be49e ¤   pgpEnv = pgpContextGetEnvironment( context );
4faf5a
b8366b ¤   /* First pick up mandatory options */
9a7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
cebcab ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_KeyGenMasterKey, TRUE,
44e580 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &masterkey ) ) )
0b97ed ¤   ¤   goto error;
0167c5 ¤
ca7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
d9f89f ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_KeyGenParams, TRUE,
351f51 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d%d", &pkalg, &bits ) ) )
d697ed ¤   ¤   goto error;
e6af5a
c0af5a
38aa1d ¤   /* Now get optional parameters */
167bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
eb4dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
198dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
4e97ed ¤   ¤   goto error;
b70809 ¤   if (IsNull( passphrase )) {
225d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
9c60d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
4fc392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
97ed19 ¤   ¤   ¤   goto error;
dd1711 ¤   ¤   if( IsntNull( passphrase ) )
c0c813 ¤   ¤   ¤   passphraseIsKey = TRUE;
949371 ¤   }
a7af5a
f67bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
33f95d ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_CreationDate, FALSE,
9b2cb0 ¤   ¤   ¤   ¤   ¤   ¤   ·"%T", &creationDate ) ) )
d597ed ¤   ¤   goto error;
cdaf5a
ca7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
6b4395 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Expiration, FALSE,
65fb40 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &expiration ) ) )
7397ed ¤   ¤   goto error;
b1af5a
bd7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
600b14 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_EventHandler, FALSE,
0ce6d3 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%p", &progress, &userValue ) ) )
6e97ed ¤   ¤   goto error;
577bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
5b64fb ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_KeyGenFast, FALSE,
f9b758 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &fastgenop, &fastgen ) ) )
0c97ed ¤   ¤   goto error;
d05282 ¤   if( !fastgenop ) {
bb4cd6 ¤   ¤   fastgen = pgpenvGetInt (pgpEnv, PGPENV_FASTKEYGEN, NULL, NULL);
1b9371 ¤   }
4467c5 ¤
3967c5 ¤
e14d9e ¤   err¤= pgpKeyDeadCheck(masterkey);
e2054e ¤   if ( IsPGPError( err ) )
593b9b ¤   ····return err;
59af5a
81b177 #if 0
77cb4f ····if (bits < 512 || bits > 4096)
022f19 ¤   ····return kPGPError_BadParams;
f9ff4e ¤   PGPGetKeyNumber (masterkey, kPGPKeyPropAlgID, &pkalg);
406168 ¤   if (pkalg != kPGPPublicKeyAlgorithm_DSA)
9a2f19 ¤   ····return kPGPError_BadParams;
507454 #endif
--03aa 000500c336e40100231 Page 17 of pgpKeyMan.c
2a67c5 ¤
549f2e ¤   *subkey = NULL;
1fcd54 ¤   err = pgpDoGenerateKey (masterkey->keyDB, &masterkey, &newsubkey,
fa95ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPByte)pkalg, bits, creationDate,
a58b71 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPUInt16)expiration,
5626e2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, 0, (char const *)passphrase,
39be0c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···passphraseLength, passphraseIsKey,
86b918 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(char const *)passphrase, passphraseLength,
2b6ae6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···progress, userValue,
d12968 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPBoolean)fastgen, NULL, (PGPByte)0,
4b23b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, (PGPByte)0, NULL, 0);
c0b1f0 ¤   if( IsntPGPError( err ) )
0bb156 ¤   ····*subkey = newsubkey;
8eaf5a
cc60ff error:
a45ea8 ¤   return err;
4eefe6 }
78af5a
82af5a
646af1 /* ·Handle editing key properties which are held in self signatures ·*/
43af5a
16af5a
53b8f4 static const PGPOptionType keyoptionOptionSet[] = {
f34990 ¤   kPGPOptionType_Passphrase,
874590 ¤   kPGPOptionType_Passkey,
6a3cea ¤   kPGPOptionType_RevocationKeySet,
37b177 #if 0
6cc907 /* not yet implemented */
7f5e67 ¤   kPGPOptionType_Expiration,
fa8c4e ¤   kPGPOptionType_PreferredAlgorithms,
403e71 ¤   kPGPOptionType_AdditionalRecipientRequestKeySet,
0a7454 #endif
1382f7 };
9caf5a
60af5a
12c744 ¤   PGPError
7984e0 pgpAddKeyOptionsInternal (
50fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
f41efc ¤   PGPOptionListRef¤   optionList
6327e6 ¤   )
8ebb36 {
3dca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
4343a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
90aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
995f6e ¤   PGPKeySetRef¤   ¤   rakset = NULL;
8a6bd8 ¤   PGPUInt32¤  ¤   ¤   rakclass = 0;
a1c945 ¤   RingSet const¤  ¤   *rakringset = NULL;
8e6cce ¤   RingSet¤¤   ¤   ¤   *addset = NULL;
9d31b4 ¤   RingSet¤¤   ¤   ¤   *rak1set = NULL;
d3eaf1 ¤   RingIterator¤   ¤   *rakiter = NULL;
650723 ¤   PGPKeyDB¤   ¤   ¤   *keys;
b842e1 ¤   RingObject¤ ¤   ¤   *keyobj;
e9ff08 ¤   RingSet const¤  ¤   *allset;
ca7925 ¤   PGPContextRef¤  ¤   context;
027d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
a6af5a
724271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
6c3f7f ¤   ¤   ¤   ¤   ¤   ¤   keyoptionOptionSet, elemsof( keyoptionOptionSet ) ) ) )
dd97ed ¤   ¤   goto error;
d1af5a
552262 ¤   /* Pick up passphrase options */
b97bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
e74dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
368dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
0997ed ¤   ¤   goto error;
820809 ¤   if (IsNull( passphrase )) {
105a97 ¤   ¤   hashedPhrase = TRUE;
535d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
8a60d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
f3c392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
46ed19 ¤   ¤   ¤   goto error;
509371 ¤   }
--bf6a 000a33ec07740100231 Page 18 of pgpKeyMan.c
e0af5a
287cfe ¤   /* Get data to add (require revocationkeyset for now) */
097bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
074f98 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RevocationKeySet, TRUE,
e27c13 ¤   ¤   ¤   ¤   ¤   ¤   "%p%d", &rakset, &rakclass ) ) )
0697ed ¤   ¤   goto error;
f66b56 ¤   pgpAssert( IsntNull( rakset ) );
dfaf5a
06471c ¤   if( IsPGPError( err = pgpKeySetRingSet( rakset, TRUE, &rakringset ) ) ) {
9e97ed ¤   ¤   goto error;
c59371 ¤   }
b5af5a
c3af5a
9fd8af ¤   /*
267a8d ¤   ·* This code is temporary and will be redesigned to support a wider
c078fd ¤   ·* set of key options.
aea4e3 ¤   ·*/
41af5a
d6d26b ¤   keys =¤ ¤   key->keyDB;
8f4b52 ¤   keyobj =¤   key->key;
c40656 ¤   context = ¤ keys->context;
0daf5a
c86237 ¤   if ( !keys->objIsMutable( keys, keyobj ) ) {
027cfe ¤   ¤   err = kPGPError_ItemIsReadOnly;
6797ed ¤   ¤   goto error;
579371 ¤   }
c4e0c5 ¤   if ( IsPGPError( pgpKeyDeadCheck(key) ) ) {
3c5462 ¤   ¤   goto error;¤/* no need if already revoked */
139371 ¤   }
1b67c5 ¤
46d640 ¤   allset = pgpKeyDBRingSet (keys);
07af5a
124fe7 ¤   if( IsPGPError( err = pgpCopyKey (allset, keyobj, &addset) ) )
7697ed ¤   ¤   goto error;
1eaf5a
f11b52 ¤   ¤
d732b7 ¤   rakiter = ringIterCreate(rakringset);
339e45 ¤   if( IsNull( rakiter ) ) {
677e48 ¤   ¤   err = ringSetError(rakringset)->error;
fd97ed ¤   ¤   goto error;
099371 ¤   }
9daf5a
671312 ¤   /* Add 1 RAK key at a time in separate self signatures */
2a7dfd ¤   while (ringIterNextObject (rakiter, 1) == 1) {
19298a ¤   ¤   RingObject *rakkey = ringIterCurrentObject (rakiter, 1);
c81953 ¤   ¤   pgpAssert (ringObjectType(rakkey) == RINGTYPE_KEY);
349a06 ¤   ¤   rak1set = ringSetCreate (ringSetPool(rakringset));
ec70e3 ¤   ¤   if( IsNull( rak1set ) ) {
87a6fa ¤   ¤   ¤   err = ringSetError(rakringset)->error;
abed19 ¤   ¤   ¤   goto error;
da0fe4 ¤   ¤   }
191415 ¤   ¤   ringSetAddObject (rak1set, rakkey);
2416e7 ¤   ¤   ringSetFreeze (rak1set);
f9af5a
676d99 ¤   ¤   err = pgpCertifyObject (context, keyobj, addset, keyobj, allset,·
5f31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGP_SIGTYPE_KEY_PROPERTY, passphrase,
b70014 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passphraseLength, hashedPhrase, FALSE,
94e0d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   SIG_EXPORTABLE, 0,
af15cc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, kPGPExpirationTime_Never,
2ed26b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, 0, NULL, rak1set, rakclass);
6d37b3 ¤   ¤   if( IsPGPError( err ) ) {
05ed19 ¤   ¤   ¤   goto error;
df0fe4 ¤   ¤   }
4324f4 ¤   ¤   ringSetDestroy (rak1set);
275a2d ¤   ¤   rak1set = NULL;
a79371 ¤   }
a5af5a
0815d8 ¤   /* ·Update the KeyDB */
56eecd ¤   err = pgpAddObjects (keys, addset);
3baf5a
a963a2 ¤   /* Calculate trust changes as a result */
a3eeaf ¤   if( err == kPGPError_NoErr )
--3a7e 000d3520d4740100231 Page 19 of pgpKeyMan.c
160786 ¤   ¤   (void)pgpPropagateTrustKeyDB (keys);
a0af5a
4b60ff error:
f5af5a
dc0b29 ¤   if( IsntNull( addset ) )
1dd98b ¤   ¤   ringSetDestroy (addset);
a94e68 ¤   if( IsntNull( rakringset ) )
bf0393 ¤   ¤   ringSetDestroy ((RingSet *)rakringset);
d8b9b6 ¤   if( IsntNull( rakiter ) )
01a2fb ¤   ¤   ringIterDestroy (rakiter);
765b7f ¤   if( IsntNull( rak1set ) )
1b24f4 ¤   ¤   ringSetDestroy (rak1set);
e2af5a
b55ea8 ¤   return err;
1defe6 }
acaf5a
dbc744 ¤   PGPError
2ec89e pgpRemoveKeyOptionsInternal (
2efb7a ¤   PGPKeyRef¤  ¤   ¤   key,
b71efc ¤   PGPOptionListRef¤   optionList
6d27e6 ¤   )
73bb36 {
267151 ¤   (void) key;
7ae00f ¤   (void) optionList;
44e63f ¤   return kPGPError_FeatureNotAvailable;
b0efe6 }
c4af5a
49c744 ¤   PGPError
9f0f33 pgpUpdateKeyOptionsInternal (
3bfb7a ¤   PGPKeyRef¤  ¤   ¤   key,
e51efc ¤   PGPOptionListRef¤   optionList
7d27e6 ¤   )
48bb36 {
3d7151 ¤   (void) key;
9fe00f ¤   (void) optionList;
55e63f ¤   return kPGPError_FeatureNotAvailable;
a1efe6 }
c5af5a
c7af5a
e5af5a
ccaf5a
4469ab /* ·Disable the key. ·If key is not stored in a writeable KeySet, copy it·
82a9c9 ¤   locally. ·Private keys cannot be disabled. */
afaf5a
1ec77d PGPError
5f18f8 PGPDisableKey (PGPKey *key)
27bb36 {
7eefd8 ¤   PGPKeyDB¤   ¤   ···*keys = NULL;
fe7493 ¤   RingSet const ···*allset = NULL;
3a86dd ¤   RingSet¤¤   ¤   *addset = NULL;
718c6f ¤   union RingObject ··*keyobj;
4cbf13 ¤   PGPError¤   ¤   ¤   error = kPGPError_NoErr;
97af5a
f4d5b3 ¤   PGPValidateKey( key );
da67c5 ¤
f066d0 ¤   error¤  = pgpKeyDeadCheck( key ) ;
90135d ¤   if ( IsPGPError( error ) )
2efcee ¤   ¤   return error;
d91b52 ¤   ¤
ebd26b ¤   keys =¤ ¤   key->keyDB;
f54b52 ¤   keyobj =¤   key->key;
706ff8 ¤   allset =¤   pgpKeyDBRingSet (keys);
43af5a
5b72d3 ¤   /* ·Axiomatic keys cannot be disabled, but plain old private
3629eb ¤   ····keys can (because they may belong to someone else). ·*/
7f2631 ¤   if (ringKeyAxiomatic (allset, keyobj))
7862b5 ¤   ¤   return kPGPError_BadParams;
97e791 ¤   if (!keys->objIsMutable(keys, keyobj))
aa7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
ecaf5a
5b176e ¤   if ((error = pgpCopyKey (allset, keyobj, &addset)) != kPGPError_NoErr)
d3fcee ¤   ¤   return error;
--b335 0009ea221e040100231 Page 20 of pgpKeyMan.c
e2a610 ¤   if (!ringKeyDisabled (allset, keyobj)) {
7f0b61 ¤   ····ringKeyDisable (allset, keyobj);
fa138c ¤   ¤   pgpKeyDBChanged (keys, addset);
829371 ¤   }
6caf5a
485e73 ¤   if (addset)
6ed98b ¤   ¤   ringSetDestroy (addset);
95c674 ¤   return error;
69efe6 }
57af5a
e2af5a
825d87 /* ·Enable the key. */
ddaf5a
2ec77d PGPError
64349b PGPEnableKey (PGPKey *key)
06bb36 {
bd6225 ¤   PGPKeyDB¤   ¤   ···*keys;
dc65c9 ····RingSet const¤  *¤  allset;
74a11b ····RingSet *¤  ¤   ¤   addset;
2e8c6f ¤   union RingObject ··*keyobj;
bc1931 ¤   PGPError¤   ¤   ····error = kPGPError_NoErr;
9667c5 ¤
01d5b3 ¤   PGPValidateKey( key );
2aca71 ¤   error¤  = pgpKeyDeadCheck( key) ;
e0135d ¤   if ( IsPGPError( error ) )
9dfcee ¤   ¤   return error;
4e1b52 ¤   ¤
75d26b ¤   keys =¤ ¤   key->keyDB;
304b52 ¤   keyobj =¤   key->key;
0b6ff8 ¤   allset =¤   pgpKeyDBRingSet (keys);
9eaf5a
86e791 ¤   if (!keys->objIsMutable(keys, keyobj))
187c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
8faf5a
d55df6 ¤   if (ringKeyDisabled (allset, keyobj)) {
85fa49 ¤   ¤   if ((error = pgpCopyKey (allset, keyobj, &addset)) != kPGPError_NoErr)
b03b5b ¤   ¤   ¤   return error;
549b6c ¤   ··¤ ringKeyEnable (allset, keyobj);
08138c ¤   ¤   pgpKeyDBChanged (keys, addset);
5ed98b ¤   ¤   ringSetDestroy (addset);
b49371 ¤   }
14151e ¤   return kPGPError_NoErr;
64efe6 }
cdaf5a
e1af5a
d786c6 /* ·Change the passphrase. ·If the new passphrase is the same as the
bff416 ¤   old passphrase, we still unlock the key as the user may be trying to
80766f ¤   set the key's isAxiomatic flag. ·*/
f9af5a
0ff1ae static PGPError
5a4600 sChangePassphraseInternal (PGPKeyDB *keyDB, RingSet const *ringset,·
da0e5d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·RingObject *keyobj, RingObject *masterkeyobj,·
29b31f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·const char *oldphrase, PGPSize oldphraseLength,
f70802 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·const char *newphrase, PGPSize newphraseLength,
cd1cf0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPBoolean newPassphraseIsKey)
38bb36 {
700874 ¤   unsigned long¤  ¤   ·validity;
886cce ¤   RingSet¤¤   ¤   ¤   *addset = NULL;
feb09f ¤   union RingObject¤   *newsecobj, *oldsecobj = NULL;
9e7def ¤   PGPKeySpec¤ ¤   ¤   *keyspec = NULL;
646804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
929223 ¤   PGPSecKey¤  ¤   ¤   *seckey = NULL;
af4f46 ¤   PgpVersion¤ ¤   ¤   ·version;
344ae4 ¤   PGPEnv¤ ¤   ¤   ¤   *pgpEnv;
d78432 ¤   PGPRandomContext¤   *pgpRng;
fa2162 ¤   PGPStringToKeyType¤ ·s2ktype;
dc3327 ¤   PGPBoolean¤ ¤   ¤   ·locked = 0;
cbaf5a
55268b ¤   if (IsntNull(oldphrase) && oldphraseLength == 0)
0f6ef6 ¤   ¤   oldphrase = NULL;
f8f0c1 ¤   if (IsntNull(newphrase) && newphraseLength == 0)
9e3dcf ¤   ¤   newphrase = NULL;
--eda0 00071ec355e40100231 Page 21 of pgpKeyMan.c
e0af5a
379717 ¤   if (!keyDB->objIsMutable(keyDB, keyobj))
e47c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
32af5a
a525c3 ¤   if (!ringKeyIsSec (ringset, keyobj))
52ea90 ¤   ····return kPGPError_SecretKeyNotFound;
13af5a
1f95b9 ¤   /* Find old secret object */
811ab5 ¤   oldsecobj = ringBestSec (ringset, keyobj);
c55ff3 ¤   if( IsNull( oldsecobj ) )
14ea90 ¤   ····return kPGPError_SecretKeyNotFound;
72af5a
ed79ab ¤   /* Does the caller know the current passphrase? */
ee183c ¤   pgpEnv = pgpContextGetEnvironment( keyDB->context );
9e9254 ¤   seckey = ringSecSecKey (ringset, oldsecobj, 0);
0e2672 ¤   if (!seckey)
e5fdea ¤   ····return ringSetError(ringset)->error;
7e86cb ¤   if (pgpSecKeyIslocked (seckey)) {
2bf05d ¤   ¤   locked = 1;
301045 ¤   ····if (!oldphrase) {
987801 ¤   ¤   ····error = kPGPError_BadPassphrase;
528f0c ¤   ¤   ¤   goto cleanup;
ba0fe4 ¤   ¤   }
c9286e ¤   ¤   error = (PGPError)pgpSecKeyUnlock (seckey, pgpEnv, oldphrase,·
3e665c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·oldphraseLength, FALSE);
51b7a8 ¤   ¤   if (error != 1) {
80a609 ¤   ¤   ····if (error == 0)·
872a9c ¤   ¤   ¤   ····error = kPGPError_BadPassphrase;
c28f0c ¤   ¤   ¤   goto cleanup;
5f0fe4 ¤   ¤   }
939371 ¤   }
3e67c5 ¤
81d6b2 ¤   /* ·All done if passphrase has not changed */
5e18fb ¤   if ((!oldphrase && !newphrase) ||
4f09df ¤   ¤   (oldphrase && locked && newphrase && (oldphraseLength==newphraseLength)
f17784 ¤   ¤   ·&& strcmp (oldphrase, newphrase) == 0))
ecc7a1 ¤   {
b59b35 ¤   ····error = kPGPError_NoErr;
cb48b9 ¤   ¤   goto cleanup;
dd9371 ¤   }
d0af5a
474ae9 ¤   error = pgpCopyKey (ringset, keyobj, &addset);
570161 ¤   if (error)
8b48b9 ¤   ¤   goto cleanup;
afaf5a
850044 ¤   pgpRng = pgpContextGetX9_17RandomContext( keyDB->context );
75af5a
fc9d31 ¤   if (newPassphraseIsKey) {
bb6d48 ¤   ¤   s2ktype = kPGPStringToKey_LiteralShared;
eda6fb ¤   } else if (seckey->pkAlg <= kPGPPublicKeyAlgorithm_RSA + 2) {
6de5ae ¤   ¤   s2ktype = kPGPStringToKey_Simple;
54f037 ¤   } else {
470643 ¤   ¤   s2ktype = kPGPStringToKey_IteratedSalted;
aa9371 ¤   }
ddaf5a
8b1238 ····error = (PGPError)pgpSecKeyChangeLock (seckey, pgpEnv, pgpRng,·
1d3406 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·newphrase, newphraseLength, s2ktype);
a00161 ¤   if (error)
8eda42 ¤   ····goto cleanup;
9daf5a
2ab3a3 ¤   keyspec = pgpKeySpecCreate (pgpEnv);
414b3b ¤   if (!keyspec) {
76eceb ¤   ····error = kPGPError_OutOfMemory;
b848b9 ¤   ¤   goto cleanup;
109371 ¤   }
39af5a
dd9321 ¤   /* We need to make this keyspec just like the existing one */
aeee5e ¤   pgpKeySpecSetCreation (keyspec, ringKeyCreation (ringset, keyobj));
c1af5a
97b37a ¤   /* Fix "version bug", don't change version from earlier one. */
4f4d2c ¤   version = ringSecVersion (ringset, keyobj);
716cea ¤   pgpKeySpecSetVersion (keyspec, version);
--52f5 0004be724f540100231 Page 22 of pgpKeyMan.c
e0af5a
ebcf02 ¤   validity = ringKeyExpiration (ringset, keyobj);
07107f ¤   if (validity != 0) {
512007 ¤   ¤   ····validity -= ringKeyCreation (ringset, keyobj);
6aac5a ¤   ¤   ¤   validity /= 3600*24;
b79371 ¤   }
a12383 ¤   pgpKeySpecSetValidity (keyspec, (PGPUInt16) validity);
30af5a
2f2e64 ¤   newsecobj = ringCreateSec (addset, masterkeyobj, seckey, keyspec,·
406ff2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···seckey->pkAlg);
2d50d7 ¤   if (!newsecobj) {
744c4b ¤   ····error = ringSetError(addset)->error;
54da42 ¤   ····goto cleanup;
3a9371 ¤   }
fbbc90 ¤   pgpKeySpecDestroy (keyspec); keyspec = NULL;
9d1a23 ¤   pgpSecKeyDestroy (seckey); seckey = NULL;
ecaf5a
517ace ¤   error = pgpAddObjects (keyDB, addset);
aeaf5a
85f1aa ¤   /* This step is necessary for the RingFile to close cleanly */
d47d2c ¤   if (!error) {
f34169 ¤   ¤   /*·
198fc0 ¤   ¤   ·* pgpRemoveObject not appropriate since this is not an object
de8bd8 ¤   ¤   ·* type that it knows how to deal with.
779de3 ¤   ¤   ·*/
2d61f5 ¤   ¤   error = keyDB->remove(keyDB, oldsecobj);
5f9371 ¤   }
efaf5a
4468cb cleanup:
e89c7f ¤   if (seckey)
8dccd8 ¤   ¤   pgpSecKeyDestroy (seckey);
725e73 ¤   if (addset)
b8d98b ¤   ¤   ringSetDestroy (addset);
e12148 ¤   if (keyspec)
309151 ¤   ¤   pgpKeySpecDestroy (keyspec);
20c674 ¤   return error;
01efe6 }
19af5a
a5af5a
d135d0 static const PGPOptionType changepassphraseOptionSet[] = {
484990 ¤   kPGPOptionType_Passphrase,
36e809 ¤   kPGPOptionType_Passkey
c682f7 };
16af5a
91c77d PGPError
92dcbd pgpChangePassphraseInternal(
8efb7a ¤   PGPKeyRef¤  ¤   ¤   key,
351efc ¤   PGPOptionListRef¤   optionList
fb27e6 ¤   )
35bb36 {
237925 ¤   PGPContextRef¤  ¤   context;
2c801b ¤   PGPOption¤  ¤   ¤   oldOp, newOp;
caac11 ¤   RingSet¤const¤  ¤   *ringset;
9a7a6f ¤   void *¤ ¤   ¤   ¤   oldPassphrase;
3ff7eb ¤   void *¤ ¤   ¤   ¤   newPassphrase;
906284 ¤   PGPSize¤¤   ¤   ¤   oldPassphraseLength;
0481ab ¤   PGPSize¤¤   ¤   ¤   newPassphraseLength;
f90af0 ¤   PGPBoolean¤ ¤   ¤   oldWasPasskey;
398774 ¤   PGPBoolean¤ ¤   ¤   newWasPasskey;
0a7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
65af5a
a04ed7 ¤   pgpa(pgpaPGPKeyValid(key));
89d5b3 ¤   PGPValidateKey( key );
d467c5 ¤
137534 ¤   oldWasPasskey = FALSE;
01005a ¤   newWasPasskey = FALSE;
aeaf5a
267e18 ¤   context = key->keyDB->context;
80af5a
004271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
b5b447 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   changepassphraseOptionSet,
4b7a6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   elemsof( changepassphraseOptionSet ) ) ) )
--5cab 000f398749440100231 Page 23 of pgpKeyMan.c
ed97ed ¤   ¤   goto error;
ebaf5a
89d8af ¤   /*
61a703 ¤   ·* Can't use our regular parsing functions because we are allowing
04515c ¤   ·* the same option to be used more than once.
7aa4e3 ¤   ·*/
80af5a
2a22d5 ¤   /* Pick up old passphrase */
6c02c7 ¤   if( IsPGPError( err = pgpGetIndexedOption( optionList,
ecc094 ¤   ¤   ¤   ¤   ¤   ··0, TRUE, &oldOp ) ) )
7d97ed ¤   ¤   goto error;
bd67c5 ¤
8a09c9 ¤   oldWasPasskey = oldOp.type == kPGPOptionType_Passkey;
01af5a
e279b3 ¤   if( !oldWasPasskey && oldOp.type != kPGPOptionType_Passphrase )
1ec7a1 ¤   {
3219d3 ¤   ¤   err = kPGPError_BadParams;
c897ed ¤   ¤   goto error;
bb9371 ¤   }
e81b52 ¤   ¤
4871ec ¤   /* Pick up new passphrase */
0402c7 ¤   if( IsPGPError( err = pgpGetIndexedOption( optionList,
54a39c ¤   ¤   ¤   ¤   ¤   ··1, TRUE, &newOp ) ) )
8997ed ¤   ¤   goto error;
6a67c5 ¤
ca4b5c ¤   newWasPasskey = newOp.type == kPGPOptionType_Passkey;
b5af5a
0bab86 ¤   if( !newWasPasskey && newOp.type != kPGPOptionType_Passphrase )
53c7a1 ¤   {
d919d3 ¤   ¤   err = kPGPError_BadParams;
5097ed ¤   ¤   goto error;
8a9371 ¤   }
8f1b52 ¤   ¤
1d1625 ¤   pgpOptionPtrLength( &oldOp, &oldPassphrase, &oldPassphraseLength );
ec35a0 ¤   pgpOptionPtrLength( &newOp, &newPassphrase, &newPassphraseLength );
8faf5a
231644 ¤   ringset = pgpKeyDBRingSet (key->keyDB);
f28a27 ¤   err = sChangePassphraseInternal (key->keyDB, ringset, key->key, NULL,
d29d48 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(char const *)oldPassphrase, oldPassphraseLength,
7d713b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(char const *)newPassphrase, newPassphraseLength,
92d89d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·newWasPasskey);
ab741f ¤   if (!err) {
66364c ¤   ¤   /* Ringset for keydb may be changed by above call */
e60e14 ¤   ¤   ringset = pgpKeyDBRingSet (key->keyDB);
159371 ¤   }
caaf5a
e060ff error:
9daf5a
685ea8 ¤   return err;
d3efe6 }
92af5a
61af5a
b2c77d PGPError
7d0115 pgpChangeSubKeyPassphraseInternal(
99dc15 ¤   PGPSubKeyRef¤   ¤   subkey,
7e1efc ¤   PGPOptionListRef¤   optionList
0a27e6 ¤   )
51bb36 {
8f7925 ¤   PGPContextRef¤  ¤   context;
ea801b ¤   PGPOption¤  ¤   ¤   oldOp, newOp;
52ac11 ¤   RingSet¤const¤  ¤   *ringset;
347a6f ¤   void *¤ ¤   ¤   ¤   oldPassphrase;
15f7eb ¤   void *¤ ¤   ¤   ¤   newPassphrase;
326284 ¤   PGPSize¤¤   ¤   ¤   oldPassphraseLength;
3b81ab ¤   PGPSize¤¤   ¤   ¤   newPassphraseLength;
820af0 ¤   PGPBoolean¤ ¤   ¤   oldWasPasskey;
fb8774 ¤   PGPBoolean¤ ¤   ¤   newWasPasskey;
cb7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
13af5a
275992 ¤   PGPValidateSubKey( subkey );
ba67c5 ¤
f37534 ¤   oldWasPasskey = FALSE;
--9f04 000fbef4d2a40100231 Page 24 of pgpKeyMan.c
6f005a ¤   newWasPasskey = FALSE;
63af5a
5e7f94 ¤   context = subkey->key->keyDB->context;
e6af5a
d44271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
1bb447 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   changepassphraseOptionSet,
837a6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   elemsof( changepassphraseOptionSet ) ) ) )
a797ed ¤   ¤   goto error;
b4af5a
8fd8af ¤   /*
92a703 ¤   ·* Can't use our regular parsing functions because we are allowing
dd515c ¤   ·* the same option to be used more than once.
3fa4e3 ¤   ·*/
7eaf5a
5dd8af ¤   /*
ffa703 ¤   ·* Can't use our regular parsing functions because we are allowing
47515c ¤   ·* the same option to be used more than once.
fda4e3 ¤   ·*/
13af5a
b922d5 ¤   /* Pick up old passphrase */
b502c7 ¤   if( IsPGPError( err = pgpGetIndexedOption( optionList,
c2c094 ¤   ¤   ¤   ¤   ¤   ··0, TRUE, &oldOp ) ) )
a997ed ¤   ¤   goto error;
c167c5 ¤
a809c9 ¤   oldWasPasskey = oldOp.type == kPGPOptionType_Passkey;
1faf5a
2f79b3 ¤   if( !oldWasPasskey && oldOp.type != kPGPOptionType_Passphrase )
2ac7a1 ¤   {
e719d3 ¤   ¤   err = kPGPError_BadParams;
8097ed ¤   ¤   goto error;
a49371 ¤   }
9e1b52 ¤   ¤
e771ec ¤   /* Pick up new passphrase */
2902c7 ¤   if( IsPGPError( err = pgpGetIndexedOption( optionList,
03a39c ¤   ¤   ¤   ¤   ¤   ··1, TRUE, &newOp ) ) )
1097ed ¤   ¤   goto error;
7267c5 ¤
f24b5c ¤   newWasPasskey = newOp.type == kPGPOptionType_Passkey;
39af5a
73ab86 ¤   if( !newWasPasskey && newOp.type != kPGPOptionType_Passphrase )
3dc7a1 ¤   {
8819d3 ¤   ¤   err = kPGPError_BadParams;
0197ed ¤   ¤   goto error;
a29371 ¤   }
cd1b52 ¤   ¤
201625 ¤   pgpOptionPtrLength( &oldOp, &oldPassphrase, &oldPassphraseLength );
6c35a0 ¤   pgpOptionPtrLength( &newOp, &newPassphrase, &newPassphraseLength );
24af5a
a52ca4 ¤   CHECKREMOVED(subkey);
b04bad ¤   ringset = pgpKeyDBRingSet (subkey->key->keyDB);
1baf5a
c380cb ¤   err = sChangePassphraseInternal (subkey->key->keyDB, ringset,
0e0bec ¤   ¤   ¤   ¤   ¤   ¤   ·subkey->subKey, subkey->key->key,
c9706f ¤   ¤   ¤   ¤   ¤   ¤   ·(char const *)oldPassphrase, oldPassphraseLength,
149c1c ¤   ¤   ¤   ¤   ¤   ¤   ·(char const *)newPassphrase, newPassphraseLength,
88de25 ¤   ¤   ¤   ¤   ¤   ¤   ·newWasPasskey);
9360ff error:
94af5a
1a5ea8 ¤   return err;
d6efe6 }
f8af5a
44af5a
2bc3e6 /* ·Remove a subkey */
bbaf5a
c2c77d PGPError
2a30e7 PGPRemoveSubKey (PGPSubKeyRef subkey)
e9bb36 {
2550e7 ¤   PGPKeyDB¤   ¤   ¤   ··*keys;
0469c4 ¤   RingSet const ·······*allset;
23ac59 ¤   union RingObject ·····*subkeyobj;
0caf5a
fb9b36 ¤   pgpa(pgpaPGPSubKeyValid(subkey));
--eb6d 0006e63883340100231 Page 25 of pgpKeyMan.c
f65992 ¤   PGPValidateSubKey( subkey );
d467c5 ¤
c12ca4 ¤   CHECKREMOVED(subkey);
3074af ¤   keys = subkey->key->keyDB;
c867c5 ¤
f74c1f ¤   allset = ·pgpKeyDBRingSet (keys);
6bf52b ¤   subkeyobj = subkey->subKey;
79a94e ¤   if (!keys->objIsMutable(keys, subkeyobj))
c97c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
91af5a
6efe95 ¤   return pgpRemoveObject (keys, subkeyobj);
7befe6 }
0eaf5a
a6af5a
4af1ae static PGPError
0544d2 sRevokeSubKey (
0ea1bc ¤   PGPContextRef¤  ¤   context,
07dc15 ¤   PGPSubKeyRef¤   ¤   subkey,
2f735d ¤   char const *¤   ¤   passphrase,
ce9b39 ¤   PGPSize¤¤   ¤   ¤   passphraseLength,
263ce2 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase
4b27e6 ¤   )
c9bb36 {
58d79c ····PGPKeyDB¤   ¤   ¤   *keys;
45ff08 ¤   RingSet const¤  ¤   *allset;
79ecb7 ¤   RingSet *¤  ¤   ¤   addset;
4d17de ¤   union RingObject ···*subkeyobj, *keyobj;
500381 ¤   union RingObject¤   *signkeyobj = NULL;
0ee9ed ¤   PGPUInt32¤  ¤   ¤   ·revnum;
d26804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
e267c5 ¤
d82ca4 ¤   CHECKREMOVED(subkey);
f2cb59 ¤   keys =¤ ¤   subkey->key->keyDB;
93f21f ¤   subkeyobj =¤subkey->subKey;
0016ea ¤   keyobj = subkey->key->key;
3faf5a
87af5e ¤   if (pgpSubKeyIsDead (subkey))
b588d3 ¤   ····return kPGPError_NoErr;
b4a94e ¤   if (!keys->objIsMutable(keys, subkeyobj))
827c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
d267c5 ¤
b5d640 ¤   allset = pgpKeyDBRingSet (keys);
40af5a
33cc68 ¤   error = pgpCopyKey (allset, keyobj, &addset);
410161 ¤   if (error)
dcfcee ¤   ¤   return error;
dcaf5a
591433 ¤   revnum = 0;
0f5870 ¤   for ( ; ; ) {
9a5ccd ¤   ¤   signkeyobj = keyobj;
3d39d9 ¤   ¤   /* See if we have an authorized revocation signature */
84f17b ¤   ¤   if (!ringKeyIsSec (allset, keyobj)) {
bd7639 ¤   ¤   ¤   PGPByte revclass;
4c82cc ¤   ¤   ¤   signkeyobj = ringKeyRevocationKey (keyobj, allset, revnum++,
6065d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, NULL,
75eb24 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&revclass, NULL, &error);
935ed6 ¤   ¤   ¤   if( IsPGPError( error ) ) {
a3973f ¤   ¤   ¤   ¤   if( error == kPGPError_ItemNotFound )
65032a ¤   ¤   ¤   ¤   ¤   error = kPGPError_NoErr;
64f622 ¤   ¤   ¤   ¤   break;
3ea3a6 ¤   ¤   ¤   }
2c541a ¤   ¤   ¤   if( IsNull( signkeyobj ) ) {
21d040 ¤   ¤   ¤   ¤   continue;
fea3a6 ¤   ¤   ¤   }
0ab96c ¤   ¤   ¤   if (!(revclass & 0x80))
28d040 ¤   ¤   ¤   ¤   continue;
a05c49 ¤   ¤   ¤   if (!ringKeyIsSec (allset, signkeyobj))
67d040 ¤   ¤   ¤   ¤   continue;
5a0fe4 ¤   ¤   }
786ae3 ¤   ¤   /* ·Note special subkey revocation sigtype */
c81db3 ¤   ¤   error = pgpCertifyObject (context, subkeyobj, addset, signkeyobj,
6e7652 ¤   ¤   ¤   ¤   ¤   allset, PGP_SIGTYPE_KEY_SUBKEY_REVOKE, passphrase,
--caf5 000d124d5cf40100231 Page 26 of pgpKeyMan.c
5c9e86 ¤   ¤   ¤   ¤   ¤   passphraseLength, hashedPhrase, FALSE,
073067 ¤   ¤   ¤   ¤   ¤   SIG_EXPORTABLE, 0, 0, kPGPExpirationTime_Never, 0, 0, NULL,
7e346e ¤   ¤   ¤   ¤   ¤   NULL, 0);
48a1c9 ¤   ¤   /* Retry if bad passphrase and we are an authorized revoker */
76231e ¤   ¤   if (error != kPGPError_BadPassphrase || signkeyobj == keyobj)
facdcb ¤   ¤   ¤   break;
089371 ¤   }
1687c7 ¤   ¤   ¤
63a673 ¤   if (error) {
17d98b ¤   ¤   ringSetDestroy (addset);
edfcee ¤   ¤   return error;
f09371 ¤   }
ae67c5 ¤
7a15d8 ¤   /* ·Update the KeyDB */
d3cdf0 ¤   error = pgpAddObjects (keys, addset);·
1e62dd ¤   ringSetDestroy (addset);
dcaf5a
e963a2 ¤   /* Calculate trust changes as a result */
eeb2f3 ¤   if( error == kPGPError_NoErr )
880786 ¤   ¤   (void)pgpPropagateTrustKeyDB (keys);
fdaf5a
cec674 ¤   return error;
68efe6 }
4faf5a
dcaf5a
2bf55e static const PGPOptionType revsubkeyOptionSet[] = {
ba28df ¤   ·kPGPOptionType_Passphrase,
571882 ¤   ·kPGPOptionType_Passkey
d382f7 };
a6af5a
b9c77d PGPError
453975 pgpRevokeSubKeyInternal(
22dc15 ¤   PGPSubKeyRef¤   ¤   subkey,
aa1efc ¤   PGPOptionListRef¤   optionList
0d27e6 ¤   )
5cbb36 {
777925 ¤   PGPContextRef¤  ¤   context;
8aca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
a143a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
13aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
627d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
b3af5a
af9b36 ¤   pgpa(pgpaPGPSubKeyValid(subkey));
345992 ¤   PGPValidateSubKey( subkey );
58af5a
d87f94 ¤   context = subkey->key->keyDB->context;
4aaf5a
aa4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
798137 ¤   ¤   ¤   ¤   ¤   ···revsubkeyOptionSet, elemsof( revsubkeyOptionSet ) ) ) )
4dc9db ¤   ¤   return err;
a9af5a
da59d8 ¤   /* Pick up optional options */
ba7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
bf4dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
098dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
bf97ed ¤   ¤   goto error;
180809 ¤   if (IsNull( passphrase )) {
465a97 ¤   ¤   hashedPhrase = TRUE;
ec5d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
1560d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
6ac392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
33ed19 ¤   ¤   ¤   goto error;
ba9371 ¤   }
13af5a
9df2b0 ¤   err = sRevokeSubKey( context, subkey, passphrase, passphraseLength,
33499f ¤   ¤   ¤   ¤   ¤   ¤   ·hashedPhrase );
4960ff error:
7c5ea8 ¤   return err;
5aefe6 }
deaf5a
b5af5a
d10608 /* ·Convert a passphrase to a passkeybuffer, for a given key */
--b4d2 0008216e75640100231 Page 27 of pgpKeyMan.c
e0af5a
513942 static const PGPOptionType getpasskeyOptionSet[] = {
7f4990 ¤   kPGPOptionType_Passphrase,
ba82f7 };
b7af5a
bac77d PGPError
ebdca0 pgpGetKeyPasskeyBufferInternal (
04fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
020d88 ¤   void¤   ¤   ¤   ···*passkeyBuffer,
051efc ¤   PGPOptionListRef¤   optionList
df27e6 ¤   )
b1bb36 {
3a3daf ¤   RingObject¤ ¤   ···*keyObj;
64d1fe ¤   RingSet const¤  ···*ringSet;
0c3d47 ¤   PGPEnv¤ ¤   ¤   ···*pgpEnv;
0734fd ¤   PGPSecKey¤  ¤   ···*secKey;
448f52 ¤   PGPError¤   ¤   ¤   err;
9788ce ¤   char const¤ ¤   ···*passphrase;
9243a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
9067c5 ¤
f31b19 ¤   /* Pick up mandatory passphrase option */
e67bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
f7bd28 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, TRUE,
dc8dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
3bc9db ¤   ¤   return err;
f7af5a
d573b2 ¤   keyObj = key->key;
cb3e69 ¤   ringSet = pgpKeyDBRingSet( key->keyDB );
1bea11 ¤   pgpEnv = pgpContextGetEnvironment( key->keyDB->context );
926e86 ¤   secKey = ringSecSecKey( ringSet, keyObj, 0 );
982028 ¤   if( IsNull( secKey ) )
58e4a7 ¤   ¤   return ringSetError(ringSet)->error;
d46774 ¤   err = ·pgpSecKeyConvertPassphrase( secKey, pgpEnv, passphrase,
2909b0 ¤   ¤   ¤   ¤   ¤   ¤   ··passphraseLength, (PGPByte *) passkeyBuffer );
8dc5c7 ¤   pgpSecKeyDestroy (secKey);
99af5a
795ea8 ¤   return err;
95efe6 }
b0af5a
18c6d2 /* ·Convert a passphrase to a passkeybuffer, for a given subkey */
64af5a
78c77d PGPError
64789b pgpGetSubKeyPasskeyBufferInternal (
fcdc15 ¤   PGPSubKeyRef¤   ¤   subkey,
310d88 ¤   void¤   ¤   ¤   ···*passkeyBuffer,
461efc ¤   PGPOptionListRef¤   optionList
5027e6 ¤   )
a4bb36 {
ee3daf ¤   RingObject¤ ¤   ···*keyObj;
91d1fe ¤   RingSet const¤  ···*ringSet;
763d47 ¤   PGPEnv¤ ¤   ¤   ···*pgpEnv;
bb34fd ¤   PGPSecKey¤  ¤   ···*secKey;
f18f52 ¤   PGPError¤   ¤   ¤   err;
db88ce ¤   char const¤ ¤   ···*passphrase;
3a43a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
8e67c5 ¤
cd1b19 ¤   /* Pick up mandatory passphrase option */
8c7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
5ebd28 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, TRUE,
e48dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
6bc9db ¤   ¤   return err;
72af5a
e12871 ¤   keyObj = subkey->subKey;
54e4c2 ¤   ringSet = pgpKeyDBRingSet( subkey->key->keyDB );
a27bea ¤   pgpEnv = pgpContextGetEnvironment( subkey->key->keyDB->context );
1a6e86 ¤   secKey = ringSecSecKey( ringSet, keyObj, 0 );
282028 ¤   if( IsNull( secKey ) )
7de4a7 ¤   ¤   return ringSetError(ringSet)->error;
de6774 ¤   err = ·pgpSecKeyConvertPassphrase( secKey, pgpEnv, passphrase,
ffa20f ¤   ¤   ¤   ¤   ¤   ¤   passphraseLength, (PGPByte *) passkeyBuffer );
1ec5c7 ¤   pgpSecKeyDestroy (secKey);
82af5a
--1a41 000e368163440100231 Page 28 of pgpKeyMan.c
ec5ea8 ¤   return err;
2aefe6 }
e0af5a
bbaf5a
2ab0c8 /* ·Remove a User ID. ·If the KeySet is read-only, or the UserID object·
0e450e ¤   itself is read-only, we return an error. */
31af5a
d5c77d PGPError
3c8ed7 PGPRemoveUserID (PGPUserID *userid)
fdbb36 {
6250e7 ¤   PGPKeyDB¤   ¤   ¤   ··*keys;
2e2cb1 ¤   PGPUserID ············*uidtmp;
be736e ¤   int ···················uidcount = 0;
3369c4 ¤   RingSet const ·······*allset;
03646e ¤   union RingObject ·····*nameobj;
e0af5a
1eca71 ¤   PGPValidateUserID( userid );
0b67c5 ¤
b00acf ¤   CHECKREMOVED(userid);
8c069d ¤   /* ·Cannot remove only UserID */
50ea28 ¤   for (uidtmp = (PGPUserID *) userid->key->userIDs.next;
0bdcd3 ¤   ¤   ·uidtmp != (PGPUserID *) &userid->key->userIDs;
466295 ¤   ¤   ·uidtmp = uidtmp->next) {
8d218d ¤   ¤   if (!uidtmp->removed)
7bcf80 ¤   ¤   ¤   uidcount++;
ce9371 ¤   }
fd8077 ¤   if (uidcount == 1)
2d62b5 ¤   ¤   return kPGPError_BadParams;
695d5e ¤   keys = userid->key->keyDB;
0867c5 ¤
274c1f ¤   allset = ·pgpKeyDBRingSet (keys);
6cc02f ¤   nameobj = userid->userID;
6478cc ¤   if (!keys->objIsMutable(keys, nameobj))
187c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
a3af5a
1574da ¤   return pgpRemoveObject (keys, nameobj);
32efe6 }
8daf5a
37af5a
8338e5 /*
2339af ·*¤ Add a new User ID to a key. ·User IDs cannot be added to other than the·
4300d6 ·*¤ user's own keys. ·The new User ID is added to the end of the list. ·To
df8a70 ·*¤ make it the primary User ID, call PGPSetPrimaryUserID() below.
35495d ·*/
2aaf5a
b3f1ae static PGPError
b329d3 sAddUserID (
8c520e ¤   PGPContextRef¤  context,
0bcd9b ¤   PGPKeyRef¤  ¤   key,
357135 ¤   PGPBoolean¤ ¤   isAttribute,
7f6357 ¤   PGPAttributeType attributeType,
cc5926 ¤   char const *¤   userIDData,
f8f806 ¤   PGPSize¤¤   ···¤userIDLength,
110ce7 ¤   char const *¤   passphrase,
75ff79 ¤   PGPSize¤¤   ¤   passphraseLength,
024534 ¤   PGPBoolean¤ ¤   hashedPhrase
9b27e6 ¤   )
d2bb36 {
530723 ¤   PGPKeyDB¤   ¤   ¤   *keys;
c3c207 ¤   PGPUserID¤  ¤   ¤   *userid;
8dff08 ¤   RingSet const¤  ¤   *allset;
5becb7 ¤   RingSet *¤  ¤   ¤   addset;
91ddba ¤   union RingObject¤   *keyobj, *nameobj;
521a4f ¤   PGPError¤   ¤   ¤   ·error;
dfaf5a
5fca71 ¤   error¤  = pgpKeyDeadCheck( key) ;
98135d ¤   if ( IsPGPError( error ) )
effcee ¤   ¤   return error;
810a1d ¤   keys = key->keyDB;
ff67c5 ¤
ddd640 ¤   allset = pgpKeyDBRingSet (keys);
e338b3 ¤   keyobj = key->key;
--944a 000fe0e9c2c40100231 Page 29 of pgpKeyMan.c
e0af5a
e4e791 ¤   if (!keys->objIsMutable(keys, keyobj))
c17c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
c5af5a
60b93a ¤   /* ·Can only add User ID to our own keys */
3af47f ¤   if (!ringKeyIsSec (allset, keyobj))·
3e45a9 ¤   ¤   return kPGPError_SecretKeyNotFound;
9baf5a
8dcc68 ¤   error = pgpCopyKey (allset, keyobj, &addset);
1e0161 ¤   if (error)
b1fcee ¤   ¤   return error;
fd5640 ¤   if (isAttribute)
6373a1 ¤   ¤   nameobj = ringCreateAttribute (addset, keyobj, (PGPByte)attributeType,
f6d5e5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPByte *)userIDData, userIDLength);
280e24 ¤   else
06240d ¤   ¤   nameobj = ringCreateName (addset, keyobj, userIDData, userIDLength);
bf9753 ¤   if (!nameobj) {
71e0a6 ¤   ¤   error = ringSetError(addset)->error;
f3d98b ¤   ¤   ringSetDestroy (addset);
38fcee ¤   ¤   return error;
209371 ¤   }
4aaf5a
8ba291 ¤   /* ·ringCreateName will return a duplicate nameobj if·
c4ac77 ¤   ¤   the name already exists for this key. ·Check the
65c3ad ¤   ¤   list of PGPUserID objects to see if the nameobj
e2c4fe ¤   ¤   is already referenced. */
802742 ¤   for (userid = (PGPUserID *) key->userIDs.next;·
f8df33 ¤   ¤   ·userid != (PGPUserID *) &key->userIDs;
8bebf8 ¤   ¤   ·userid = userid->next) {
431220 ¤   ····if (!userid->removed && userid->userID == nameobj) {
7442c1 ¤   ¤   ····ringSetDestroy (addset);
db71b9 ¤   ¤   ¤   return kPGPError_DuplicateUserID;
950fe4 ¤   ¤   }
fe9371 ¤   }
22af5a
163cc1 ¤   /* Must self-certify here */
ff0be9 ¤   error = pgpCertifyObject (context, nameobj, addset, keyobj, allset,·
c586a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGP_SIGTYPE_KEY_GENERIC, ·passphrase,
83f012 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··passphraseLength, hashedPhrase, TRUE,
f72f47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··SIG_EXPORTABLE, 0, 0, kPGPExpirationTime_Never,
f556f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··0, 0, NULL, NULL, 0);
1ea673 ¤   if (error) {
b9d98b ¤   ¤   ringSetDestroy (addset);
22fcee ¤   ¤   return error;
1e9371 ¤   }
7eca1f ¤   error = pgpAddObjects (keys, addset);
0762dd ¤   ringSetDestroy (addset);
d0af5a
1e63a2 ¤   /* Calculate trust changes as a result */
50b2f3 ¤   if( error == kPGPError_NoErr )
420786 ¤   ¤   (void)pgpPropagateTrustKeyDB (keys);
92af5a
7bc674 ¤   return error;
61a79b }·
2aaf5a
15af5a
5b0906 static const PGPOptionType adduserOptionSet[] = {
924990 ¤   kPGPOptionType_Passphrase,
0ae809 ¤   kPGPOptionType_Passkey
1982f7 };
c9af5a
9ec77d PGPError
df4995 pgpAddUserIDInternal(
16cd9b ¤   PGPKeyRef¤  ¤   key,
8de767 ¤   char const *¤   userID,
ea1efc ¤   PGPOptionListRef¤   optionList
4827e6 ¤   )
b4bb36 {
c57925 ¤   PGPContextRef¤  ¤   context;
05ca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
2f43a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
feaba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
--027d 000e3d2198240100231 Page 30 of pgpKeyMan.c
4c0226 ¤   PGPSize¤¤   ¤   ¤   userIDLength;
607d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
6aaf5a
cb4ed7 ¤   pgpa(pgpaPGPKeyValid(key));
60d5b3 ¤   PGPValidateKey( key );
ef67c5 ¤
4c2a5d ¤   if( IsNull( userID ) )
cd62b5 ¤   ¤   return kPGPError_BadParams;
edaf5a
7b85d1 ¤   userIDLength = strlen(userID);
90af5a
537e18 ¤   context = key->keyDB->context;
34af5a
2c4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
ac1f2d ¤   ¤   ¤   ¤   ¤   ¤   adduserOptionSet, elemsof( adduserOptionSet ) ) ) )
c5c9db ¤   ¤   return err;
ffaf5a
3759d8 ¤   /* Pick up optional options */
f37bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
024dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
2c8dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
0897ed ¤   ¤   goto error;
240809 ¤   if (IsNull( passphrase )) {
b65a97 ¤   ¤   hashedPhrase = TRUE;
b75d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
f760d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
eec392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
78ed19 ¤   ¤   ¤   goto error;
a79371 ¤   }
85af5a
298460 ¤   err = sAddUserID( context, key, FALSE, (PGPAttributeType)0,
cddd89 ¤   ¤   ¤   ¤   ¤   ··userID, userIDLength, passphrase, passphraseLength,
674dee ¤   ¤   ¤   ¤   ¤   ··hashedPhrase);
d360ff error:
085ea8 ¤   return err;
63efe6 }
5eaf5a
88af5a
031f74 static const PGPOptionType addattrOptionSet[] = {
414990 ¤   kPGPOptionType_Passphrase,
b1e809 ¤   kPGPOptionType_Passkey
b482f7 };
0caf5a
c4c77d PGPError
3c0b48 pgpAddAttributeInternal(
3cfb7a ¤   PGPKeyRef¤  ¤   ¤   key,
cbe896 ¤   PGPAttributeType¤   attributeType,
59b122 ¤   PGPByte¤const¤  ···*attributeData,
1471fa ¤   PGPSize¤¤   ¤   ¤   attributeLength,
f51efc ¤   PGPOptionListRef¤   optionList
b627e6 ¤   )
c8bb36 {
e47925 ¤   PGPContextRef¤  ¤   context;
f7ca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
bf43a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
a7aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
ea7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
29af5a
134ed7 ¤   pgpa(pgpaPGPKeyValid(key));
7fd5b3 ¤   PGPValidateKey( key );
3d67c5 ¤
a17051 ¤   if( IsNull( attributeData ) )
8662b5 ¤   ¤   return kPGPError_BadParams;
f5af5a
fa7e18 ¤   context = key->keyDB->context;
3aaf5a
714271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
c91f2d ¤   ¤   ¤   ¤   ¤   ¤   adduserOptionSet, elemsof( adduserOptionSet ) ) ) )
eec9db ¤   ¤   return err;
cdaf5a
ab59d8 ¤   /* Pick up optional options */
e37bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
--d6cb 000740de52a40100231 Page 31 of pgpKeyMan.c
b54dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
788dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
8297ed ¤   ¤   goto error;
8b0809 ¤   if (IsNull( passphrase )) {
135a97 ¤   ¤   hashedPhrase = TRUE;
2e5d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
6f60d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
a0c392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
12ed19 ¤   ¤   ¤   goto error;
d59371 ¤   }
96af5a
feeb39 ¤   err = sAddUserID( context, key, TRUE, attributeType,
16b9ed ¤   ¤   ¤   ¤   ¤   ··(const char *)attributeData, attributeLength,
608ae6 ¤   ¤   ¤   ¤   ¤   ··passphrase, passphraseLength, hashedPhrase);
0460ff error:
015ea8 ¤   return err;
2aefe6 }
9daf5a
74af5a
8bee87 /*¤ Make the given User ID the primary User ID of the key */
6daf5a
1ac77d PGPError
c0d74b PGPSetPrimaryUserID (PGPUserID *userid)
fabb36 {
9bdee1 ¤   PGPKeyDB¤   ¤   ··*keys;
833da9 ¤   PGPKey¤ ¤   ¤   ··*key;
c892a7 ¤   RingSet const *¤¤   allset;
f8ecb7 ¤   RingSet *¤  ¤   ¤   addset;
e3b2b4 ¤   PGPError¤   ¤   ···error;
aeaf5a
63ca71 ¤   PGPValidateUserID( userid );
8967c5 ¤
2e0acf ¤   CHECKREMOVED(userid);
4e05c3 ¤   key = userid->key;
adca71 ¤   error¤  = pgpKeyDeadCheck( key) ;
51135d ¤   if ( IsPGPError( error ) )
60fcee ¤   ¤   return error;
e167c5 ¤
9d0a1d ¤   keys = key->keyDB;
bceefe ¤   if (!keys->objIsMutable(keys, key->key))
da7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
5b67c5 ¤
bed640 ¤   allset = pgpKeyDBRingSet (keys);
4667c5 ¤
a9cc04 ¤   error = pgpCopyKey (allset, key->key, &addset);
2b0161 ¤   if (error)
acfcee ¤   ¤   return error;
eb67c5 ¤
d984b7 ¤   /* Raise the name to the top */
4762e7 ····ringRaiseName (addset, userid->userID);
1f869e ····
1df1c4 ····/* Rearrange the circularly-linked list of userids */
ecef06 ····userid->prev->next = userid->next;
428863 ····userid->next->prev = userid->prev;
cb1d85 ····userid->prev = (PGPUserID *)&key->userIDs;
e1b203 ····userid->next = (PGPUserID *)key->userIDs.next;
1a67de ····userid->next->prev = userid;
cde2ad ····userid->prev->next = userid;
de67c5 ¤
cc3a84 ····error = pgpKeyDBChanged(keys, addset);
9062dd ¤   ringSetDestroy (addset);
87c674 ¤   return error;
c7efe6 }
36af5a
11af5a
1a4be3 /* ·Certify a User ID. ·Do not allow duplicate certification. If UserID
2dc1ee ····is already certified, but revoked, the old cert can
66c9be ¤   be removed and the UserID then recertified. */
98af5a
e966dd ¤   static PGPError
3f625c sCertifyUserID(
74520e ¤   PGPContextRef¤  context,
--e6b7 0006ec4548440100231 Page 32 of pgpKeyMan.c
6bc178 ¤   PGPUserID *¤¤   userid,
04328b ¤   PGPKeyRef¤  ¤   certifying_key,
b00ce7 ¤   char const *¤   passphrase,
2aff79 ¤   PGPSize¤¤   ¤   passphraseLength,
d0af5b ¤   PGPBoolean¤ ¤   hashedPhrase,
51bfa7 ¤   PGPBoolean¤ ¤   exportable,
3ffc0b ¤   PGPTime¤¤   ¤   creationDate,
93cba8 ¤   PGPUInt32¤  ¤   expiration,
88a358 ¤   PGPByte¤¤   ¤   trustDepth,
be1132 ¤   PGPByte¤¤   ¤   trustValue,
2a5afa ¤   char const *¤   sRegExp
fc27e6 ¤   )
d7bb36 {
dae2b1 ¤   PGPKeyDB¤   ¤   ····*keys;
b84bb1 ¤   RingSet const¤  ¤   *ringset;
c932b0 ¤   RingSet¤¤   ¤   ¤   *addset;
2381ba ¤   RingSet const¤  ¤   *signerset;
3a8915 ¤   union RingObject ···*keyobj, *nameobj, *sigobj;
7ad3aa ¤   RingIterator¤   ¤   *iter;
796804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
f7af5a
126d02 ¤   (void) context;
86af5a
bec7e8 ¤   error¤  = pgpKeyDeadCheck( userid->key ) ;
df135d ¤   if ( IsPGPError( error ) )
aefcee ¤   ¤   return error;
aeaf5a
3b7b93 ¤   pgpAssert( IsNull( certifying_key ) || pgpKeyIsValid(certifying_key) );
bcaf5a
5a0092 ¤   if (userid->removed)
3862b5 ¤   ¤   return kPGPError_BadParams;
f15d5e ¤   keys = userid->key->keyDB;
a8af5a
ee8c0f ¤   ringset = pgpKeyDBRingSet (keys);
ecc02f ¤   nameobj = userid->userID;
0aaf5a
8a78cc ¤   if (!keys->objIsMutable(keys, nameobj))
347c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
acaf5a
15e1a3 ¤   /* ·If certifying key was not passed, get the default */
7ade3a ¤   if (!certifying_key) {
dd0810 ¤   ¤   error = pgpGetDefaultPrivateKeyInternal(keys, &certifying_key);
ca9f22 ¤   ¤   if ( IsPGPError( error ) )
5a5b34 ¤   ¤   {
e9879d ¤   ¤   ¤   error¤  = kPGPError_SecretKeyNotFound;
053b5b ¤   ¤   ¤   return error;
a00fe4 ¤   ¤   }
f39371 ¤   }
e3af5a
68930a ¤   error¤  = pgpKeyDeadCheck( certifying_key ) ;
9d135d ¤   if ( IsPGPError( error ) )
a4fcee ¤   ¤   return error;
98af5a
13e67f ¤   /* ·Get RingSet for certifying key */
8fc2fe ¤   if (certifying_key->keyDB != keys)
cf2da8 ¤   ¤   signerset = pgpKeyDBRingSet (certifying_key->keyDB);
ed0e24 ¤   else
970002 ¤   ¤   signerset = ringset;
1c57c9 ¤   keyobj = certifying_key->key;
22af5a
634747 ¤   /* ·Check for duplicate certificate. ·There may be some
c75633 ¤   ¤   old revocation certs still laying around, which we
3e1259 ¤   ¤   should ignore. ·*/
24af5a
3c22f3 ¤   iter = ringIterCreate (ringset);
0a21b2 ¤   if (!iter)
76fdea ¤   ····return ringSetError(ringset)->error;
e31645 ¤   ringIterSeekTo (iter, nameobj);
9d4169 ¤   while ((error = (PGPError)ringIterNextObject (iter, 3)) > 0) {
23d04d ¤   ····sigobj = ringIterCurrentObject (iter, 3);
43e287 ¤   ¤   if (ringSigMaker (ringset, sigobj, signerset) == keyobj &&
6e1f4a ¤   ¤   ¤   ringSigType (ringset, sigobj) != PGP_SIGTYPE_KEY_UID_REVOKE) {
--1ff8 0000b908c0640100231 Page 33 of pgpKeyMan.c
4a870a ¤   ¤   ····error = kPGPError_DuplicateCert;
95cdcb ¤   ¤   ¤   break;
200fe4 ¤   ¤   }
219371 ¤   }
17fedf ¤   ringIterDestroy (iter);
ac0161 ¤   if (error)
366e15 ¤   ····return error;
79af5a
3d0700 ¤   error = pgpCopyKey (ringset, nameobj, &addset);
e30161 ¤   if (error)
4efcee ¤   ¤   return error;
0d19ad ¤   error = pgpCertifyObject (keys->context, nameobj, addset, keyobj,
eabefa ¤   ¤   ¤   ¤   ¤   ··signerset, PGP_SIGTYPE_KEY_GENERIC, passphrase,
568345 ¤   ¤   ¤   ¤   ¤   ··passphraseLength, hashedPhrase, FALSE,
bdd707 ¤   ¤   ¤   ¤   ¤   ··exportable, SIG_EXPORTABLEHASHED,
bd5368 ¤   ¤   ¤   ¤   ¤   ··creationDate, expiration,
2bd768 ¤   ¤   ¤   ¤   ¤   ··trustDepth, trustValue, sRegExp, NULL, 0);
d1a673 ¤   if (error) {
45d98b ¤   ¤   ringSetDestroy (addset);
0afcee ¤   ¤   return error;
c29371 ¤   }
a4ca1f ¤   error = pgpAddObjects (keys, addset);
4b62dd ¤   ringSetDestroy (addset);
dfaf5a
3c63a2 ¤   /* Calculate trust changes as a result */
3ab2f3 ¤   if( error == kPGPError_NoErr )
d30786 ¤   ¤   (void)pgpPropagateTrustKeyDB (keys);
1eaf5a
14c674 ¤   return error;
4aefe6 }
0baf5a
42af5a
173ed5 static const PGPOptionType signuserOptionSet[] = {
6d28df ¤   ·kPGPOptionType_Passphrase,
6d7fbb ¤   ·kPGPOptionType_Passkey,
d43f28 ¤   ·kPGPOptionType_Expiration,
8911a9 ¤   ·kPGPOptionType_CreationDate,
21c3ed ¤   ·kPGPOptionType_Exportable,
c28de6 ¤   ·kPGPOptionType_CertificateTrust,
2068c4 ¤   ·kPGPOptionType_CertificateRegularExpression
8682f7 };
7caf5a
95c744 ¤   PGPError
c0a24f pgpCertifyUserIDInternal (
add210 ¤   PGPUserID *¤¤   ¤   userid,
b567e4 ¤   PGPKey *¤   ¤   ¤   certifying_key,
321efc ¤   PGPOptionListRef¤   optionList
6a27e6 ¤   )
6ebb36 {
647925 ¤   PGPContextRef¤  ¤   context;
625c86 ¤   PGPTime¤¤   ¤   ¤   creationDate;
7eb778 ¤   PGPUInt32¤  ¤   ¤   expiration;
e64bbd ¤   PGPUInt32¤  ¤   ¤   exportable;
bb4f21 ¤   PGPUInt32¤  ¤   ¤   trustDepth;
50162e ¤   PGPUInt32¤  ¤   ¤   trustLevel;
3cca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
5443a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
d4aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
76ebdc ¤   char const *¤   ¤   sRegExp;
827d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
a1af5a
900283 ¤   context = userid->key->keyDB->context;
f5af5a
1c4271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
587622 ¤   ¤   ¤   ¤   ¤   ¤   signuserOptionSet, elemsof( signuserOptionSet ) ) ) )
ffc9db ¤   ¤   return err;
aaaf5a
7b7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
bb4dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
498dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
b997ed ¤   ¤   goto error;
0b0809 ¤   if (IsNull( passphrase )) {
--166f 00079c5847640100231 Page 34 of pgpKeyMan.c
6e5a97 ¤   ¤   hashedPhrase = TRUE;
b15d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
ff60d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
4cc392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
85ed19 ¤   ¤   ¤   goto error;
319371 ¤   }
851b52 ¤   ¤
7d7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
5cf95d ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_CreationDate, FALSE,
b22cb0 ¤   ¤   ¤   ¤   ¤   ¤   ·"%T", &creationDate ) ) )
d797ed ¤   ¤   goto error;
371b52 ¤   ¤
8f7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
684395 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Expiration, FALSE,
b1fb40 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &expiration ) ) )
cb97ed ¤   ¤   goto error;
b81b52 ¤   ¤
85ed61 ¤   /* Defaults exportable to false */
ba7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
64037a ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Exportable, FALSE,
13767c ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &exportable ) ) )
7497ed ¤   ¤   goto error;
ff7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
ac8dd8 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_CertificateTrust, FALSE,
a2d36e ¤   ¤   ¤   ¤   ¤   ¤   ·"%d%d", &trustDepth, &trustLevel ) ) )
6897ed ¤   ¤   goto error;
0f7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
fb0efd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_CertificateRegularExpression, FALSE,
d517a3 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &sRegExp ) ) )
ba97ed ¤   ¤   goto error;
dbaf5a
d1a7b9 ¤   /* Check regexp for validity */
55fdfb ¤   if( IsntNull( sRegExp ) ) {
a571ed ¤   ¤   regexp *rexp;
45223e ¤   ¤   if (IsPGPError( pgpRegComp( context, sRegExp, &rexp ) ) ) {
5e4d30 ¤   ¤   ¤   pgpDebugMsg( "Invalid regular expression" );
dc5820 ¤   ¤   ¤   err = kPGPError_BadParams;
64ed19 ¤   ¤   ¤   goto error;
450fe4 ¤   ¤   }
b5277a ¤   ¤   pgpContextMemFree( context, rexp );
c69371 ¤   }
6aaf5a
596bf8 ¤   /* Expiration is given as days from today, we will convert to seconds */
9290e0 ¤   if( expiration != 0 )
2d25b1 ¤   ¤   expiration *= (24*60*60);
a6af5a
109103 ¤   err = sCertifyUserID( context, userid, certifying_key,
44d5f5 ¤   ¤   ¤   ¤   ¤   ¤   ··passphrase, passphraseLength, hashedPhrase,
3e7a14 ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPBoolean)exportable, creationDate, expiration,
99e8b5 ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPByte) trustDepth, (PGPByte) trustLevel,
470b42 ¤   ¤   ¤   ¤   ¤   ¤   ··sRegExp);
95af5a
3660ff error:
dc5ea8 ¤   return err;
d6efe6 }
c7af5a
0caf5a
84da07 /* ·Given a cert, return the certifying key object. ·The signing key does not·
fab5f5 ¤   have to be in the same set as <cert>, and may be in the <allkeys> set. */
2faf5a
36c77d PGPError
72e3da PGPGetSigCertifierKey (
397c1c ¤   PGPSigRef¤  ¤   cert,
e98322 ¤   PGPKeySetRef¤   allkeys,
02df07 ¤   PGPKey **¤  ¤   certkey)
46bb36 {
ce3f1b ¤   PGPKeyID¤   ¤   ¤   ¤   keyID;
51fc86 ¤   PGPInt32¤   ¤   ¤   ¤   algTemp;
a99479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
dd48fb ¤   PGPPublicKeyAlgorithm¤  pubKeyAlg;
19429f ¤   PGPContextRef¤  ¤   ¤   context;
79af5a
--01b9 00086f165ab40100231 Page 35 of pgpKeyMan.c
6b4e4a ¤   PGPValidatePtr( certkey );
d3c894 ¤   *certkey¤   = NULL;
57c107 ¤   PGPValidateCert( cert );
719b92 ¤   PGPValidateKeySet( allkeys );
2967c5 ¤
184c88 ¤   CHECKREMOVED(cert);
0b67c5 ¤
29a358 ¤   context¤= PGPGetKeySetContext( allkeys );
8067c5 ¤
691915 ¤   err¤= PGPGetKeyIDOfCertifier( cert, &keyID);
d0f1e7 ¤   if ( IsntPGPError( err ) )
3cc7a1 ¤   {
94a2aa ¤   ¤   PGPGetSigNumber(cert, kPGPSigPropAlgID, &algTemp);
461b52 ¤   ¤
cb2f22 ¤   ¤   if (algTemp == 0)
59bab2 ¤   ¤   ¤   pubKeyAlg¤  = kPGPPublicKeyAlgorithm_Invalid;
c80e1d ¤   ¤   else
cc6abc ¤   ¤   ¤   pubKeyAlg¤  = (PGPPublicKeyAlgorithm)algTemp;
871b52 ¤   ¤
9bdd7f ¤   ¤   err¤= PGPGetKeyByKeyID(allkeys, &keyID, pubKeyAlg, certkey );
0dd087 ¤   ¤   /* PGPGetKeyByKeyID incremented the ref count */
fe9371 ¤   }
1c67c5 ¤
5ff2f9 ¤   pgpAssertErrWithPtr( err, *certkey );
ed5ea8 ¤   return err;
b0efe6 }
44af5a
77af5a
15dba0 /* ·Revoke a certification. ·If allkeys == NULL, the certifying key
829690 ¤   must be in the same keyDB as the certificate. */
f7af5a
49f1ae static PGPError
18ec57 sRevokeCert (
4c520e ¤   PGPContextRef¤  context,
077c1c ¤   PGPSigRef¤  ¤   cert,
b78322 ¤   PGPKeySetRef¤   allkeys,
c30ce7 ¤   char const *¤   passphrase,
e8ff79 ¤   PGPSize¤¤   ¤   passphraseLength,
f24534 ¤   PGPBoolean¤ ¤   hashedPhrase
2c27e6 ¤   )
0ebb36 {
ee0723 ¤   PGPKeyDB¤   ¤   ¤   *keys;
9d5877 ¤   PGPKey¤ ¤   ¤   ¤   *certkey;
dbff08 ¤   RingSet const¤  ¤   *allset;
a032b0 ¤   RingSet¤¤   ¤   ¤   *addset;
b05367 ¤   RingSet const ¤ ¤   *signerset;
e6d921 ¤   union RingObject¤   *sigobj, *nameobj;
36fe97 ¤   PGPBoolean¤ ¤   ¤   ·revoked;
63a4e5 ¤   PGPBoolean¤ ¤   ¤   ·exportable;
ad6804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
33af5a
e74c88 ¤   CHECKREMOVED(cert);
815daf ¤   keys = cert->up.userID->key->keyDB;
8d5c17 ¤   sigobj = cert->cert;
0e6f45 ¤   if (!keys->objIsMutable(keys, sigobj))
ff7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
acaf5a
48bd27 ¤   error = PGPGetSigBoolean (cert, kPGPSigPropIsRevoked, &revoked);
240161 ¤   if (error)
6dfcee ¤   ¤   return error;
1ff9f2 ¤   if (revoked)
bc2a4f ¤   ¤   return kPGPError_NoErr; ··/* already revoked */
88af5a
fbf06d ¤   /* ·Get certifying key and its RingSet */
1787cc ¤   error = PGPGetSigCertifierKey (cert, allkeys, &certkey);
5b0161 ¤   if (error)
11fcee ¤   ¤   return error;
ffeacd ¤   if (!certkey)
8b45a9 ¤   ¤   return kPGPError_SecretKeyNotFound;
58af5a
8ced8c ¤   error¤  = pgpKeyDeadCheck( certkey ) ;
86135d ¤   if ( IsPGPError( error ) )
--5387 000e16b759240100231 Page 36 of pgpKeyMan.c
a2fcee ¤   ¤   return error;
981b52 ¤   ¤
3f1b52 ¤   ¤
8bd7fa ¤   signerset = ·pgpKeyDBRingSet (certkey->keyDB);
5daf5a
91b7d8 ¤   /* ·Get signature RingSet and its name object */
b35046 ¤   allset = pgpKeyDBRingSet (cert->up.userID->key->keyDB);
34458c ¤   nameobj = cert->up.userID->userID;
58af5a
7f9207 ¤   error = pgpCopyKey (allset, nameobj, &addset);
e60161 ¤   if (error)
33fcee ¤   ¤   return error;
dbd54d ¤   /* Copy exportability attribute from cert we are revoking */
134b0a ¤   error = PGPGetSigBoolean (cert, kPGPSigPropIsExportable, &exportable);
b30161 ¤   if (error)
9dfcee ¤   ¤   return error;
de5b80 ¤   error = pgpCertifyObject (context, nameobj, addset, certkey->key,
355f17 ¤   ¤   ¤   ¤   ··signerset, PGP_SIGTYPE_KEY_UID_REVOKE, passphrase,
cda5f0 ¤   ¤   ¤   ¤   ··passphraseLength, hashedPhrase, FALSE,
2c82ab ¤   ¤   ¤   ¤   ··exportable, SIG_EXPORTABLEHASHED,
fc78b9 ¤   ¤   ¤   ¤   ··0, kPGPExpirationTime_Never, 0, 0, NULL,
76dbb2 ¤   ¤   ¤   ¤   ··NULL, 0);
19a673 ¤   if (error) {
1ad98b ¤   ¤   ringSetDestroy (addset);
91fcee ¤   ¤   return error;
8b9371 ¤   }
24ca1f ¤   error = pgpAddObjects (keys, addset);
0e62dd ¤   ringSetDestroy (addset);
3daf5a
3a63a2 ¤   /* Calculate trust changes as a result */
fcb2f3 ¤   if( error == kPGPError_NoErr )
d30786 ¤   ¤   (void)pgpPropagateTrustKeyDB (keys);
69af5a
b0c674 ¤   return error;
feefe6 }
42af5a
84af5a
cbc19b static const PGPOptionType revsigOptionSet[] = {
5228df ¤   ·kPGPOptionType_Passphrase,
d51882 ¤   ·kPGPOptionType_Passkey
6282f7 };
4daf5a
4ec77d PGPError
c8eeda pgpRevokeCertInternal(
b7abe6 ¤   PGPSigRef¤  ¤   ¤   cert,
7ebba1 ¤   PGPKeySetRef¤   ¤   allkeys,
e51efc ¤   PGPOptionListRef¤   optionList
8127e6 ¤   )
f4bb36 {
ab7925 ¤   PGPContextRef¤  ¤   context;
91ca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
0443a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
e4aba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
067d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
dbaf5a
3d757f ¤   pgpa(pgpaPGPCertValid(cert));
bdc107 ¤   PGPValidateCert( cert );
f79b92 ¤   PGPValidateKeySet( allkeys );
35af5a
69ec7b ¤   context = cert->up.userID->key->keyDB->context;
fbaf5a
674271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
f6b294 ¤   ¤   ¤   ¤   ¤   ¤   revsigOptionSet, elemsof( revsigOptionSet ) ) ) )
b0c9db ¤   ¤   return err;
efaf5a
0f59d8 ¤   /* Pick up optional options */
547bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
034dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
938dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
7097ed ¤   ¤   goto error;
400809 ¤   if (IsNull( passphrase )) {
e15a97 ¤   ¤   hashedPhrase = TRUE;
--b339 00016250e7a40100231 Page 37 of pgpKeyMan.c
535d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
4b60d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
5cc392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
02ed19 ¤   ¤   ¤   goto error;
bd9371 ¤   }
19af5a
9b683c ¤   err = sRevokeCert( context, cert, allkeys, passphrase, passphraseLength,
83c6cf ¤   ¤   ¤   ¤   ¤   ···hashedPhrase);
7a60ff error:
7d5ea8 ¤   return err;
45efe6 }
4baf5a
ffaf5a
01af5a
f0b94c /* ·Remove a certification. ·If the certification was revoked, the
9bdce9 ····revocation signature remains. ·This ensures that the same
2bcecf ¤   signature on someone else's keyring is properly revoked
374ab7 ¤   if this key is exported. ··A future certification will have
9c69c8 ¤   a later creation timestamp than the revocation and will therefore
c4f5ae ¤   not be affected. */
23af5a
cdc77d PGPError
9ae202 PGPRemoveSig (PGPSig *cert)
20bb36 {
ae0723 ¤   PGPKeyDB¤   ¤   ¤   *keys;
5d3941 ¤   union RingObject¤   *sigobj;
37af5a
acc107 ¤   PGPValidateCert( cert );
8f67c5 ¤
8d4c88 ¤   CHECKREMOVED(cert);
605daf ¤   keys = cert->up.userID->key->keyDB;
fe5c17 ¤   sigobj = cert->cert;
b86f45 ¤   if (!keys->objIsMutable(keys, sigobj))
607c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
298c3b ¤   return pgpRemoveObject (keys, sigobj);
04efe6 }
6baf5a
feaf5a
91c744 ¤   PGPError
65614c PGPCountAdditionalRecipientRequests(
845568 ¤   PGPKeyRef¤  ¤   basekey,
9ec5bc ····PGPUInt32 *¤¤   numARKeys)
e8bb36 {
bfc2a1 ¤   RingSet const¤  ¤   *ringset = NULL;/* Aurora ringset to look in */
a0ffa5 ¤   PGPUInt32¤  ¤   ¤   ·nadks;¤¤   ¤   /* Number ADK's available */
c5d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f367c5 ¤
7242c7 ¤   PGPValidatePtr( numARKeys );
849401 ¤   *numARKeys¤ = 0;
f9d183 ¤   PGPValidateKey( basekey );
d567c5 ¤
f6e4a6 ¤   ringset = pgpKeyDBRingSet (basekey->keyDB);
0ad9c7 ¤   if (IsNull( ringset ) )
e148fe ¤   ¤   err = kPGPError_OutOfRings;
c267c5 ¤
dfb1f0 ¤   if( IsntPGPError( err ) )
7fc7a1 ¤   {
1cd142 ¤   ¤   PGPByte¤ ¤  ¤   ¤   tclass;¤¤   /* Class code from ADK */
24c8da ¤   ¤   union RingObject ···*keyobj;¤   ¤   /* Aurora base key */
b21b52 ¤   ¤
4cd14b ¤   ¤   keyobj¤ = basekey->key;
fc1dbf ¤   ¤   (void)ringKeyAdditionalRecipientRequestKey (keyobj, ringset, 0,
a10765 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, NULL, &tclass, &nadks, &err);
bb0b79 ¤   ¤   if ( err == kPGPError_ItemNotFound )
fd5b34 ¤   ¤   {
e12283 ¤   ¤   ¤   nadks¤  = 0;
cab656 ¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
c00fe4 ¤   ¤   }
f89371 ¤   }
7a67c5 ¤
a52828 ¤   *numARKeys = nadks;
165ea8 ¤   return err;
--cf45 00074f3909340100231 Page 38 of pgpKeyMan.c
7aefe6 }
46af5a
8eaf5a
d68d5b /* ·Return the nth (0 based) additional decryption key and keyid,
bb0466 ¤   if one exists.
426f81 ¤   It is an error to use an index >= K, where K is the number of ARR key ids.
ec67c5 ¤
1f74eb ·¤  Also return the class of the ADK. ·The class is currently reserved
dd5bae ·¤  for use by PGP.
122e8e ·¤  Any of the return pointers may be NULL.
e56182 ·¤
639506 ¤   Note that it is *not* safe to use the keyID returned from this function
22c944 ¤   to get the ADK to use because KeyIDs are not unique.
fa1228 ¤   Instead, the keyID can be used to locate the actual key(s) with that
fe897a ¤   key id.
0b9566 ¤   Then call this function again to get the ADK;
bffc9a ¤   it will check the key fingerprint, which is unique.
12af5a
037fe0 */
cd66dd ¤   static PGPError
7b40fd pgpGetIndexedAdditionalRecipientRequestKey(
e15568 ¤   PGPKeyRef¤  ¤   basekey,
1d8322 ¤   PGPKeySetRef¤   allkeys,
f063b5 ¤   PGPUInt32¤  ¤   nth,
a9a5ee ····PGPKeyRef*¤ ¤   adkey,
514af2 ¤   PGPKeyID *¤ ¤   adkeyid,
a116ae ····PGPByte *¤  ¤   adclass)
eabb36 {
14127d ¤   RingSet const¤  ¤   *ringset;¤  ¤   /* Aurora ringset to look in */
5e74c3 ¤   union RingObject ···*keyobj;¤   ¤   /* Aurora base key */
353a03 ¤   union RingObject ···*rkey;¤ ¤   ¤   /* Aurora additional decryption key */
9fc68b ¤   unsigned¤   ¤   ¤   ·nadks;¤¤   ¤   /* Number ADK's available */
0d7bfb ¤   PGPByte¤¤   ¤   ¤   ·tclass;¤   ¤   /* Class code from ADK */
8c161f ¤   PGPError¤   ¤   ¤   ·error;¤¤   ¤   /* Error return from Aurora */
78320e ¤   PGPByte¤¤   ¤   ¤   ·pkalg;¤¤   ¤   /* pkalg of ADK */
9be5f5 ¤   PGPKeyID¤   ¤   ¤   keyid;¤ ¤   /* keyid of ADK */
5ae23e ¤   PGPError¤   ¤   ¤   ·err¤   = kPGPError_NoErr;
8a2f91 ¤   PGPContextRef¤  ¤   ·context;
3daf5a
c53166 ¤   if( IsntNull( adkeyid ) )
516a45 ¤   ¤   pgpClearMemory( adkeyid, sizeof( *adkeyid ) );
1d5e54 ¤   if ( IsntNull( adclass ) )
a566e5 ¤   ¤   *adclass¤   = 0;
6cddfe ¤   if ( IsntNull( adkey ) )
891d44 ¤   ¤   *adkey¤ = NULL;
9e1b52 ¤   ¤
7dd897 ¤   ringset = NULL;
ddaf5a
5fd183 ¤   PGPValidateKey( basekey );
9d9b92 ¤   PGPValidateKeySet( allkeys );
1a67c5 ¤
084931 ¤   context¤= PGPGetKeyContext( basekey );
0b67c5 ¤
394b7d ¤   error = pgpKeySetRingSet (allkeys, TRUE, &ringset);
23534a ¤   if( IsPGPError( error ) )
36fcee ¤   ¤   return error;
c6af5a
1eeb49 ¤   keyobj = basekey->key;
03363d ¤   rkey = ringKeyAdditionalRecipientRequestKey (keyobj, ringset, nth,
4e0c09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&pkalg, &keyid, &tclass, &nadks, &error);
7aaf5a
43534a ¤   if( IsPGPError( error ) )
5cc7a1 ¤   {
4e5bb5 ¤   ¤   ringSetDestroy( (RingSet *) ringset );
c0fcee ¤   ¤   return error;
1f9371 ¤   }
8c67c5 ¤
990d42 ¤   /* Success */
b9ddfe ¤   if ( IsntNull( adkey ) )
76c7a1 ¤   {
f4ad57 ¤   ¤   PGPKeyID¤   keyID;
741b52 ¤   ¤
--3dd7 0002dd0a7c540100231 Page 39 of pgpKeyMan.c
894cb6 ¤   ¤   if (IsNull( rkey ) ) {
57248c ¤   ¤   ¤   *adkey = NULL;
9a45a6 ¤   ¤   } else {
cc4f1a ¤   ¤   ¤   ringKeyID8 (ringset, rkey, &pkalg, &keyID);
87af5a
3a7b9e ¤   ¤   ¤   err = PGPGetKeyByKeyID (allkeys, &keyID,
944c1e ¤   ¤   ¤   ¤   ¤   (PGPPublicKeyAlgorithm)pkalg, adkey);
e00fe4 ¤   ¤   }
129371 ¤   }
a6af5a
907171 ¤   if ( IsntNull( adkeyid ) )
f2c7a1 ¤   {
97dce5 ¤   ¤   *adkeyid¤   = keyid;
4f9371 ¤   }
1267c5 ¤
cd5e54 ¤   if ( IsntNull( adclass ) )
ebf9dc ¤   ¤   *adclass = tclass;
beaf5a
3dc686 ¤   if( IsntNull( ringset ) )
ea5bb5 ¤   ¤   ringSetDestroy( (RingSet *) ringset );
ccaf5a
355ea8 ¤   return err;
6eefe6 }
55af5a
7baf5a
80af5a
5c639a /* Given a key, return the nth (0 based) additional decryption key, if
d23123 ·¤  one exists. ·Also return the keyid, the class of the ADK, and the
f5066d ·¤  number of ADK's for the base key. ·Any of the return pointers may
66e03d ·¤  be NULL. */
0daf5a
29c744 ¤   PGPError
0aad84 PGPGetIndexedAdditionalRecipientRequestKey(
615568 ¤   PGPKeyRef¤  ¤   basekey,
af8322 ¤   PGPKeySetRef¤   allkeys,
7263b5 ¤   PGPUInt32¤  ¤   nth,
b1eacb ····PGPKeyRef *¤¤   adkey,
f54af2 ¤   PGPKeyID *¤ ¤   adkeyid,
5a16ae ····PGPByte *¤  ¤   adclass)
56bb36 {
3426d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
7a95df ¤   PGPKeyID¤   tempKeyID;
3a67c5 ¤
6dddfe ¤   if ( IsntNull( adkey ) )
9f1d44 ¤   ¤   *adkey¤ = NULL;
687171 ¤   if ( IsntNull( adkeyid ) )
78b9c1 ¤   ¤   pgpClearMemory( adkeyid, sizeof( *adkeyid) );
ac5e54 ¤   if ( IsntNull( adclass ) )
2b66e5 ¤   ¤   *adclass¤   = 0;
60af5a
4dd183 ¤   PGPValidateKey( basekey );
a99b92 ¤   PGPValidateKeySet( allkeys );
0d67c5 ¤
9f840a ¤   err¤= pgpGetIndexedAdditionalRecipientRequestKey( basekey,
0492d4 ¤   ¤   ¤   allkeys, nth, adkey, &tempKeyID, adclass );
d7f1e7 ¤   if ( IsntPGPError( err ) )
52c7a1 ¤   {
e4a5a3 ¤   ¤   pgpAssert( pgpKeyIDIsValid( &tempKeyID ) );
ff066e ¤   ¤   if( IsntNull( adkeyid ) )
385b34 ¤   ¤   {
7deb02 ¤   ¤   ¤   *adkeyid¤   = tempKeyID;
a00fe4 ¤   ¤   }
0f9371 ¤   }
200e24 ¤   else
6dc7a1 ¤   {
96b9c1 ¤   ¤   pgpClearMemory( adkeyid, sizeof( *adkeyid) );
309371 ¤   }
fd67c5 ¤
e3deb7 ¤   return( err );
45efe6 }
d2af5a
2daf5a
--9f76 000e42f67af40100231 Page 40 of pgpKeyMan.c
d3c744 ¤   PGPError
318113 PGPCountRevocationKeys(
845568 ¤   PGPKeyRef¤  ¤   basekey,
c02ab6 ····PGPUInt32 *¤¤   numRevKeys)
93bb36 {
81c2a1 ¤   RingSet const¤  ¤   *ringset = NULL;/* Aurora ringset to look in */
7ce178 ¤   PGPUInt32¤  ¤   ¤   ·nrevs;¤¤   ¤   /* Number rev keys available */
a3d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
0367c5 ¤
c7880a ¤   PGPValidatePtr( numRevKeys );
2dca95 ¤   *numRevKeys¤= 0;
2cd183 ¤   PGPValidateKey( basekey );
1767c5 ¤
56e4a6 ¤   ringset = pgpKeyDBRingSet (basekey->keyDB);
26d9c7 ¤   if (IsNull( ringset ) )
1e48fe ¤   ¤   err = kPGPError_OutOfRings;
a267c5 ¤
d5b1f0 ¤   if( IsntPGPError( err ) )
bfc7a1 ¤   {
35c8da ¤   ¤   union RingObject ···*keyobj;¤   ¤   /* Aurora base key */
171b52 ¤   ¤
c7d14b ¤   ¤   keyobj¤ = basekey->key;
1ea5d0 ¤   ¤   (void)ringKeyRevocationKey (keyobj, ringset, 0, NULL, NULL, NULL,
4177e0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &nrevs, &err);
b60b79 ¤   ¤   if ( err == kPGPError_ItemNotFound )
205b34 ¤   ¤   {
fbc2e4 ¤   ¤   ¤   nrevs¤  = 0;
71b656 ¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
b30fe4 ¤   ¤   }
979371 ¤   }
3967c5 ¤
767022 ¤   *numRevKeys = nrevs;
2a5ea8 ¤   return err;
13efe6 }
12af5a
a9af5a
ccd67a /* ·Return the nth (0 based) revocation key and keyid,
540466 ¤   if one exists.
5f6f81 ¤   It is an error to use an index >= K, where K is the number of ARR key ids.
8367c5 ¤
c79bda ·¤  Also return the class of the revkey. ·The high bit is set for a
866d48 ¤   reocation key.
212e8e ·¤  Any of the return pointers may be NULL.
536182 ·¤
8d9506 ¤   Note that it is *not* safe to use the keyID returned from this function
ad6045 ¤   to get the revkey to use because KeyIDs are not unique.
211228 ¤   Instead, the keyID can be used to locate the actual key(s) with that
57897a ¤   key id.
2e6299 ¤   Then call this function again to get the revkey;
9bfc9a ¤   it will check the key fingerprint, which is unique.
66af5a
f07fe0 */
4266dd ¤   static PGPError
d68f76 pgpGetIndexedRevocationKey(
5e5568 ¤   PGPKeyRef¤  ¤   basekey,
f78322 ¤   PGPKeySetRef¤   allkeys,
d663b5 ¤   PGPUInt32¤  ¤   nth,
01600d ····PGPKeyRef*¤ ¤   revkey,
8c0c13 ¤   PGPKeyID *¤ ¤   revkeyid,
d1b3c6 ····PGPByte *¤  ¤   revclass)
47bb36 {
6f127d ¤   RingSet const¤  ¤   *ringset;¤  ¤   /* Aurora ringset to look in */
3a74c3 ¤   union RingObject ···*keyobj;¤   ¤   /* Aurora base key */
6f5cae ¤   union RingObject ···*rkey;¤ ¤   ¤   /* Aurora revocation key */
9bc031 ¤   unsigned¤   ¤   ¤   ·nrevks;¤   ¤   /* Number revkey's available */
12bada ¤   PGPByte¤¤   ¤   ¤   ·tclass;¤   ¤   /* Class code from revkey */
e5161f ¤   PGPError¤   ¤   ¤   ·error;¤¤   ¤   /* Error return from Aurora */
e79e2d ¤   PGPByte¤¤   ¤   ¤   ·pkalg;¤¤   ¤   /* pkalg of revkey */
6cc932 ¤   PGPKeyID¤   ¤   ¤   ·keyid;¤¤   ¤   /* keyid of revkey */
4ce23e ¤   PGPError¤   ¤   ¤   ·err¤   = kPGPError_NoErr;
212f91 ¤   PGPContextRef¤  ¤   ·context;
e4af5a
--7c03 00038f50c3640100231 Page 41 of pgpKeyMan.c
01da4a ¤   if( IsntNull( revkeyid ) )
f5c09e ¤   ¤   pgpClearMemory( revkeyid, sizeof( *revkeyid ) );
a69111 ¤   if ( IsntNull( revclass ) )
34c29f ¤   ¤   *revclass¤  = 0;
5d8cef ¤   if ( IsntNull( revkey ) )
8fcc71 ¤   ¤   *revkey¤= NULL;
f61b52 ¤   ¤
e6d897 ¤   ringset = NULL;
50af5a
53d183 ¤   PGPValidateKey( basekey );
449b92 ¤   PGPValidateKeySet( allkeys );
5a67c5 ¤
d34931 ¤   context¤= PGPGetKeyContext( basekey );
1d67c5 ¤
b54b7d ¤   error = pgpKeySetRingSet (allkeys, TRUE, &ringset);
2c534a ¤   if( IsPGPError( error ) )
b5fcee ¤   ¤   return error;
d2af5a
a3eb49 ¤   keyobj = basekey->key;
412635 ¤   rkey = ringKeyRevocationKey (keyobj, ringset, nth,
2680b7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&pkalg, &keyid, &tclass, &nrevks, &error);
bbaf5a
9b534a ¤   if( IsPGPError( error ) )
1bc7a1 ¤   {
a15bb5 ¤   ¤   ringSetDestroy( (RingSet *) ringset );
f5fcee ¤   ¤   return error;
e69371 ¤   }
1f67c5 ¤
800d42 ¤   /* Success */
0e8cef ¤   if ( IsntNull( revkey ) )
4dc7a1 ¤   {
c2ad57 ¤   ¤   PGPKeyID¤   keyID;
fa1b52 ¤   ¤
514cb6 ¤   ¤   if (IsNull( rkey ) ) {
edc126 ¤   ¤   ¤   *revkey = NULL;
4045a6 ¤   ¤   } else {
7d4f1a ¤   ¤   ¤   ringKeyID8 (ringset, rkey, &pkalg, &keyID);
1b1b52 ¤   ¤
dd7b9e ¤   ¤   ¤   err = PGPGetKeyByKeyID (allkeys, &keyID,
499be9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPPublicKeyAlgorithm)pkalg, revkey);
8e0fe4 ¤   ¤   }
df9371 ¤   }
38af5a
d3be34 ¤   if ( IsntNull( revkeyid ) )
66c7a1 ¤   {
304697 ¤   ¤   *revkeyid¤  = keyid;
d89371 ¤   }
1a67c5 ¤
819111 ¤   if ( IsntNull( revclass ) )
5e0e25 ¤   ¤   *revclass = tclass;
abaf5a
64c686 ¤   if( IsntNull( ringset ) )
1d5bb5 ¤   ¤   ringSetDestroy( (RingSet *) ringset );
15af5a
9d5ea8 ¤   return err;
02efe6 }
14af5a
71af5a
98af5a
573e48 /* Given a key, return the nth (0 based) revocation key, if
287b46 ·¤  one exists. ·Also return the keyid, the class of the revkey, and the
d919df ·¤  number of revkey's for the base key. ·Any of the return pointers may
31e03d ·¤  be NULL. */
56af5a
67c744 ¤   PGPError
fbff1c PGPGetIndexedRevocationKey(
8b5568 ¤   PGPKeyRef¤  ¤   basekey,
0c8322 ¤   PGPKeySetRef¤   allkeys,
d463b5 ¤   PGPUInt32¤  ¤   nth,
6e16ed ····PGPKeyRef *¤¤   revkey,
cc72ab ¤   PGPKeyID *¤ ¤   revkeyid)
38bb36 {
--1c1a 00077a7abd140100231 Page 42 of pgpKeyMan.c
a326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
0595df ¤   PGPKeyID¤   tempKeyID;
1f67c5 ¤
008cef ¤   if ( IsntNull( revkey ) )
06cc71 ¤   ¤   *revkey¤= NULL;
80be34 ¤   if ( IsntNull( revkeyid ) )
0c109e ¤   ¤   pgpClearMemory( revkeyid, sizeof( *revkeyid) );
1aaf5a
1ed183 ¤   PGPValidateKey( basekey );
ab9b92 ¤   PGPValidateKeySet( allkeys );
6a67c5 ¤
5e672f ¤   err¤= pgpGetIndexedRevocationKey( basekey,
1ec11e ¤   ¤   ¤   allkeys, nth, revkey, &tempKeyID, NULL );
56f1e7 ¤   if ( IsntPGPError( err ) )
f3c7a1 ¤   {
f2a5a3 ¤   ¤   pgpAssert( pgpKeyIDIsValid( &tempKeyID ) );
e75635 ¤   ¤   if( IsntNull( revkeyid ) )
555b34 ¤   ¤   {
327232 ¤   ¤   ¤   *revkeyid¤  = tempKeyID;
e60fe4 ¤   ¤   }
f79371 ¤   }
470e24 ¤   else
4ec7a1 ¤   {
63109e ¤   ¤   pgpClearMemory( revkeyid, sizeof( *revkeyid) );
2f9371 ¤   }
8e67c5 ¤
05deb7 ¤   return( err );
feefe6 }
88af5a
98af5a
85af5a
9be17d /* ·Trust-related functions */
e9af5a
e2ba55 #if 0¤  /* KEEP [ */
8fc744 ¤   PGPError
ff5c13 PGPSetUserIDConfidence(PGPUserID *userid, PGPUInt32 confidence)
f5bb36 {
860723 ¤   PGPKeyDB¤   ¤   ¤   *keys;
77d0d9 ¤   RingSet const¤  ¤   *allset = NULL;
6a6cce ¤   RingSet¤¤   ¤   ¤   *addset = NULL;
2187ca ¤   union RingObject ···*nameobj;
b150cd ¤   RingPool¤   ¤   ¤   *pgpRingPool;
8c6804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
bbaf5a
b99309 ¤   pgpa(pgpaPGPUserIDValid(userid));
8dca71 ¤   PGPValidateUserID( userid );
0d67c5 ¤
db5d5e ¤   keys = userid->key->keyDB;
e0af5a
fd7850 ¤   pgpRingPool = pgpContextGetRingPool( keys->context );
f983db ¤   pgpAssert (pgpTrustModel (pgpRingPool) > PGPTRUST0);
070acf ¤   CHECKREMOVED(userid);
6a5a9d ¤   err¤= pgpKeyDeadCheck( userid->key ) ;
37054e ¤   if ( IsPGPError( err ) )
30c9db ¤   ¤   return err;
66af5a
1d4c1f ¤   allset = ·pgpKeyDBRingSet (keys);
89c02f ¤   nameobj = userid->userID;
dbebf9 ¤   if (ringKeyIsSec (allset, userid->key->key))
7362b5 ¤   ¤   return kPGPError_BadParams;
c478cc ¤   if (!keys->objIsMutable(keys, nameobj))
b87c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
f6af5a
b09207 ¤   error = pgpCopyKey (allset, nameobj, &addset);
a90161 ¤   if (error)
63fcee ¤   ¤   return error;
729367 ¤   ringNameSetConfidence (allset, nameobj, (unsigned short) confidence);
acd6d9 ¤   pgpKeyDBChanged (keys, addset);
4668cb cleanup:
d75e73 ¤   if (addset)
52d98b ¤   ¤   ringSetDestroy (addset);
77c674 ¤   return error;
--8a96 0008c63251740100231 Page 43 of pgpKeyMan.c
7aefe6 }
46af5a
a964c3 #endif¤ /* ] KEEP */
06af5a
02f30c /* ·Set the trust on a key. ·Cannot be used to set undefined or·
b74d92 ¤   axiomatic trust. ··The key must be valid to assign trust. */
28af5a
0ec77d PGPError
e9eb2f PGPSetKeyTrust (PGPKey *key, PGPUInt32 trust)
7ebb36 {
a10723 ¤   PGPKeyDB¤   ¤   ¤   *keys;
e951e8 ¤   RingSet¤const¤  ¤   *allset;
596cce ¤   RingSet¤¤   ¤   ¤   *addset = NULL;
7b850d ¤   union RingObject¤   *keyobj;
0a50cd ¤   RingPool¤   ¤   ¤   *pgpRingPool;
af6804 ¤   PGPError¤   ¤   ¤   ·error = kPGPError_NoErr;
8ea5d4 #if ONLY_TRUST_VALID_KEYS
92c31b ¤   long ················validity;
e17454 #endif
37af5a
7ad5b3 ¤   PGPValidateKey( key );
7367c5 ¤
190a1d ¤   keys = key->keyDB;
7e7850 ¤   pgpRingPool = pgpContextGetRingPool( keys->context );
93af5a
fa4c1f ¤   allset = ·pgpKeyDBRingSet (keys);
1f9219 ¤   keyobj = ·key->key;
8caf5a
14e791 ¤   if (!keys->objIsMutable(keys, keyobj))
fc7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
6faf5a
4c74df ¤   if (trust <= kPGPKeyTrust_Undefined || trust > kPGPKeyTrust_Complete ||
b55afe ¤   ¤   ·ringKeyAxiomatic (allset, keyobj))
f0c7a1 ¤   {
362f19 ¤   ····return kPGPError_BadParams;
449371 ¤   }
ffda86 ¤   ····
054c35 ¤   error¤  = pgpKeyDeadCheck( key);
3f135d ¤   if ( IsPGPError( error ) )
55fcee ¤   ¤   return error;
0baf5a
f3a5d4 #if ONLY_TRUST_VALID_KEYS
520a34 ¤   /* ·Should not set trust on key that is not completely valid·
2ca0d4 ¤   ¤   (who is it we are trusting?) */
3c1daa ¤   PGPGetKeyNumber (key, kPGPKeyPropValidity, &validity);
4b3e46 ¤   if (validity != kPGPValidity_Complete)·
7f2f19 ¤   ····return kPGPError_BadParams;
ec7454 #endif
11af5a
efca73 ¤   if( pgpTrustModel( pgpRingPool ) == PGPTRUST0 ) {
4aaf5a
626269 ¤   ¤   error = pgpCopyKey (allset, keyobj, &addset);
f1e3c2 ¤   ¤   if (error)
fa3b5b ¤   ¤   ¤   return error;
1daf5a
911d66 ¤   ¤   ringKeySetTrust (allset, keyobj, (PGPByte)trust);
e0138c ¤   ¤   pgpKeyDBChanged (keys, addset);
aef037 ¤   } else {
bf6ae8 ¤   ¤   /* New trust model, set confidence on all userids */
f078b1 ¤   ¤   RingIterator *keyiter;
53c95f ¤   ¤   PGPUInt32 level;
6bb7a9 ¤   ¤   PGPUInt16 confidence;
c1af5a
5b6269 ¤   ¤   error = pgpCopyKey (allset, keyobj, &addset);
756442 ¤   ¤   if( IsPGPError( error ) )
bded19 ¤   ¤   ¤   goto error;
f25188 ¤   ¤   ringSetFreeze (addset);
a6af5a
39a7c9 ¤   ¤   confidence = ringTrustToIntern(
f7133b ¤   ¤   ¤   (PGPByte)ringTrustOldToExtern( pgpRingPool, (PGPByte)trust ) );
bcaf5a
8cda52 ¤   ¤   keyobj = key->key;
--ccc1 000fd40284e40100231 Page 44 of pgpKeyMan.c
06a1ce ¤   ¤   keyiter = ringIterCreate( addset );
cbefc4 ¤   ¤   if( IsNull( keyiter ) ) {
b1cc26 ¤   ¤   ¤   error = ringSetError( addset )->error;
7aed19 ¤   ¤   ¤   goto error;
a40fe4 ¤   ¤   }
69af5a
3863b4 ¤   ¤   ringIterSeekTo( keyiter, keyobj );
59a04d ¤   ¤   level = ringIterCurrentLevel( keyiter );
1fd817 ¤   ¤   ringIterRewind( keyiter, level+1 );
9966a6 ¤   ¤   while( ringIterNextObject( keyiter, level+1 ) > 0 ) {
3b0ec2 ¤   ¤   ¤   RingObject *nameobj = ringIterCurrentObject( keyiter, level+1 );
4dd050 ¤   ¤   ¤   if( ringObjectType( nameobj ) != RINGTYPE_NAME )
b5d040 ¤   ¤   ¤   ¤   continue;
cdb5da ¤   ¤   ¤   ringNameSetConfidence( addset, nameobj,
68091f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(unsigned short) confidence );
560fe4 ¤   ¤   }
9feb98 ¤   ¤   ringIterDestroy( keyiter );
20af5a
d660a6 ¤   ¤   /* Also set key trust for consistency */
e91d66 ¤   ¤   ringKeySetTrust (allset, keyobj, (PGPByte)trust);
b5af5a
df138c ¤   ¤   pgpKeyDBChanged (keys, addset);
399371 ¤   }
1eaf5a
9560ff error:
7e5e73 ¤   if (addset)
c3d98b ¤   ¤   ringSetDestroy (addset);
73c674 ¤   return error;
a7efe6 }
e2af5a
0faf5a
2202a2 /* ·Set a secret key as the axiomatic key. ·If checkPassphrase == TRUE,
98ab78 ¤   the user must prove knowledge of the passphrase in order to do·
29f2f5 ¤   this. */
0eaf5a
b366dd ¤   static PGPError
839ab3 sSetKeyAxiomatic (
7cf0d4 ¤   PGPKey *¤   ¤   key,
239116 ¤   PGPBoolean¤ ¤   checkPassphrase,
7f0ce7 ¤   char const *¤   passphrase,
0aff79 ¤   PGPSize¤¤   ¤   passphraseLength,
964534 ¤   PGPBoolean¤ ¤   hashedPhrase
4e27e6 ¤   )
c3bb36 {
0fe913 ····PGPBoolean ··············secret, axiomatic;
e7939e ¤   RingSet const ··········*allset;
57f079 ¤   RingSet¤¤   ¤   ¤   ¤   *addset = NULL;
74f21b ¤   union RingObject ·······*keyobj;
debd38 ¤   PGPSecKey ········¤ ¤   *seckey;
e637fa ¤   PGPEnv¤ ¤   ¤   ¤   ¤   *pgpEnv;
5ad37d ¤   PGPKeyDB ···············*keys;
169188 ¤   PGPError ················error = kPGPError_NoErr;
bfaf5a
5e3ef6 ¤   PGPGetKeyBoolean (key, kPGPKeyPropIsSecret, &secret);
b23c29 ¤   if (!secret)
fc2f19 ¤   ····return kPGPError_BadParams;
9269cd ¤   PGPGetKeyBoolean (key, kPGPKeyPropIsAxiomatic, &axiomatic);
d5ccc8 ¤   if (axiomatic)
a488d3 ¤   ····return kPGPError_NoErr;
48af5a
610a1d ¤   keys = key->keyDB;
08d640 ¤   allset = pgpKeyDBRingSet (keys);
f038b3 ¤   keyobj = key->key;
04af5a
63e791 ¤   if (!keys->objIsMutable(keys, keyobj))
1c7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
c7af5a
28f7cb ¤   if (checkPassphrase) {
8dc7a6 ¤   ····/* Get the secret key and attempt to unlock it */
4af573 ¤   ····seckey = ringSecSecKey (allset, keyobj, PGP_PKUSE_SIGN);
e367f9 ¤   ¤   if (!seckey)
fdb021 ¤   ¤   ····return ringSetError(allset)->error;
--cfec 00057374d6040100231 Page 45 of pgpKeyMan.c
1eba25 ¤   ¤   if (pgpSecKeyIslocked (seckey)) {
cd0b0c ¤   ¤   ····if (IsNull( passphrase )) {
4853d8 ¤   ¤   ¤   ····pgpSecKeyDestroy (seckey);
a4f67a ¤   ¤   ¤   ····return kPGPError_BadPassphrase;
faa3a6 ¤   ¤   ¤   }
5bb19b ¤   ¤   ¤   pgpEnv = pgpContextGetEnvironment( keys->context );
689e8c ¤   ¤   ¤   error = (PGPError)pgpSecKeyUnlock (seckey, pgpEnv, passphrase,·
3ded5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·passphraseLength, hashedPhrase);
a68d2b ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
bb3efc ¤   ¤   ¤   if (error != 1) {
01f792 ¤   ¤   ¤   ¤   if (error == 0)
e77987 ¤   ¤   ¤   ¤   ····error = kPGPError_BadPassphrase;
63b20f ¤   ¤   ¤   ¤   return error;
58a3a6 ¤   ¤   ¤   }
760fe4 ¤   ¤   }
189371 ¤   }
2faf5a
9e7dee ¤   /* ·Make sure it's enabled first before setting axiomatic */
376064 ¤   if ((error = PGPEnableKey (key)) != kPGPError_NoErr)
f56e15 ¤   ····return error;
78176e ¤   if ((error = pgpCopyKey (allset, keyobj, &addset)) != kPGPError_NoErr)
02fcee ¤   ¤   return error;
8323c3 ¤   ringKeySetAxiomatic (allset, keyobj);
9fd6d9 ¤   pgpKeyDBChanged (keys, addset);
88af5a
bb5e73 ¤   if (addset)
8a7fa9 ¤   ····ringSetDestroy (addset);
dec674 ¤   return error;
caefe6 }
3eaf5a
13af5a
46cc3d static const PGPOptionType setkeyaxiomaticOptionSet[] = {
ce28df ¤   ·kPGPOptionType_Passphrase,
1c1882 ¤   ·kPGPOptionType_Passkey
b682f7 };
30af5a
eec744 ¤   PGPError
b8b78e pgpSetKeyAxiomaticInternal(
96fb7a ¤   PGPKeyRef¤  ¤   ¤   key,
231efc ¤   PGPOptionListRef¤   optionList
bc27e6 ¤   )
4bbb36 {
bb7925 ¤   PGPContextRef¤  ¤   context;
9aca2f ¤   char *¤ ¤   ¤   ¤   passphrase;
5743a0 ¤   PGPSize¤¤   ¤   ¤   passphraseLength;
1eaba3 ¤   PGPBoolean¤ ¤   ¤   hashedPhrase = FALSE;
c77d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
6faf5a
9b4ed7 ¤   pgpa(pgpaPGPKeyValid(key));
64d5b3 ¤   PGPValidateKey( key );
bf67c5 ¤
8e7e18 ¤   context = key->keyDB->context;
8daf5a
924271 ¤   if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
cd3990 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   setkeyaxiomaticOptionSet,
cfd4e7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   elemsof( setkeyaxiomaticOptionSet ) ) ) )
be97ed ¤   ¤   goto error;
efaf5a
3f59d8 ¤   /* Pick up optional options */
cb7bbf ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
6b4dbd ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_Passphrase, FALSE,
188dc7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p%l", &passphrase, &passphraseLength ) ) )
3397ed ¤   ¤   goto error;
140809 ¤   if (IsNull( passphrase )) {
4c5a97 ¤   ¤   hashedPhrase = TRUE;
215d0a ¤   ¤   if( IsPGPError( err = pgpFindOptionArgs( optionList,
d460d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Passkey, FALSE,
0ac392 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passphrase, &passphraseLength ) ) )
fced19 ¤   ¤   ¤   goto error;
de9371 ¤   }
f1af5a
57c456 ¤   if( IsPGPError( err=sSetKeyAxiomatic( key, (PGPBoolean)(passphrase!=NULL),
--5d37 000d876337740100231 Page 46 of pgpKeyMan.c
467990 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···passphrase, passphraseLength,
75b752 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···hashedPhrase) ) )
5697ed ¤   ¤   goto error;
36af5a
d860ff error:
c8af5a
375ea8 ¤   return err;
24efe6 }
f7af5a
ecaf5a
deaf5a
69c77d PGPError
3d5627 PGPUnsetKeyAxiomatic (PGPKey *key)
7dbb36 {
74e85d ····PGPBoolean ·················axiomatic;
ec55c4 ····RingSet const ·········*allset;
e632d4 ····RingSet ¤   ¤   ¤   ¤   *addset = NULL;
a3f21b ¤   union RingObject ·······*keyobj;
393ccd ¤   PGPKeyDB ················*keys;
514270 ¤   PGPError ·················error = kPGPError_NoErr;
52af5a
f6d5b3 ¤   PGPValidateKey( key );
1867c5 ¤
6a69cd ¤   PGPGetKeyBoolean (key, kPGPKeyPropIsAxiomatic, &axiomatic);
d2f4a9 ¤   if (!axiomatic)
e32f19 ¤   ····return kPGPError_BadParams;
7baf5a
840a1d ¤   keys = key->keyDB;
04d640 ¤   allset = pgpKeyDBRingSet (keys);
b538b3 ¤   keyobj = key->key;
25af5a
99e791 ¤   if (!keys->objIsMutable(keys, keyobj))
927c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
59af5a
7dcc68 ¤   error = pgpCopyKey (allset, keyobj, &addset);
9c0161 ¤   if (error)
a5fcee ¤   ¤   return error;
1a73a9 ¤   ringKeyResetAxiomatic (allset, keyobj);
a1d6d9 ¤   pgpKeyDBChanged (keys, addset);
f8af5a
5d5e73 ¤   if (addset)
157fa9 ¤   ····ringSetDestroy (addset);
7fc674 ¤   return error;
f4efe6 }
c8af5a
8eaf5a
1aaf5a
b629d9 /* ·Get property functions. ·Internal GetKey functions work for both
81fd42 ····master keys and subkeys. ·*/
d0af5a
07af5a
73f1ae static PGPError
902604 pgpReturnPropBuffer (char const *src, void *prop,·
2fc518 ¤   ¤   ¤   ¤   ¤   ·PGPSize srclen, PGPSize proplen)
20bb36 {
cc1f4d ····PGPError result = kPGPError_NoErr;
c1af5a
0a8374 ····if (srclen > proplen) {
75a692 ¤   ····srclen = proplen;
33d020 ¤   ¤   result = kPGPError_BufferTooSmall;
749371 ¤   }
bb3bc0 ¤   if ( IsntNull( prop ) && srclen > 0)
fded30 ¤   ····pgpCopyMemory( src, prop, srclen);
455d73 ¤   return result;
9defe6 }
e4af5a
deaf5a
acf1ae static PGPError
b7ad5e pgpGetKeyNumberInternal (RingSet const *ringset, RingObject *keyobj,
e4227d ¤   ¤   ¤   ¤   ¤   ¤   ·PGPKeyPropName propname, PGPInt32 *prop,
a9fb0f ¤   ¤   ¤   ¤   ¤   ¤   ·PGPEnv const *env)
d8bb36 {
--45d3 00036ce8aec40100231 Page 47 of pgpKeyMan.c
c6bd13 ¤   unsigned char¤  ¤   ·pkalg;
4ca9ad ¤   PGPSecKey *¤¤   ¤   seckey = NULL;
58f8d0 ¤   PGPCipherAlgorithm¤ lockalg;
e5fec9 ¤   PGPSize¤¤   ¤   ¤   lockbytes;
068f52 ¤   PGPError¤   ¤   ¤   err;
daaf5a
98e156 ¤   switch (propname) {
fff611 ¤   case kPGPKeyPropAlgID:
c78162 ¤   ¤   ringKeyID8 (ringset, keyobj, &pkalg, NULL);
4b550e ¤   ¤   *prop = (long) pkalg;
bd2f68 ¤   ¤   break;
e0f42d ¤   case kPGPKeyPropBits:
7a482a ¤   ¤   *prop = (long) ringKeyBits (ringset, keyobj);
092f68 ¤   ¤   break;
5cd507 ¤   case kPGPKeyPropLockingAlgID:
03f02f ¤   case kPGPKeyPropLockingBits:
48d48d ¤   ¤   if( !ringKeyIsSec (ringset, keyobj) )
f6d70e ¤   ¤   ¤   return kPGPError_InvalidProperty;
28bf07 ¤   ¤   seckey = ringSecSecKey (ringset, keyobj, 0);
8de670 ¤   ¤   if( !seckey )
f9039a ¤   ¤   ¤   return ringSetError(ringset)->error;
638d37 ¤   ¤   if( !pgpSecKeyIslocked (seckey) ) {
33540c ¤   ¤   ¤   /* Use defaults if key is not locked */
6ce293 ¤   ¤   ¤   PGPCipherVTBL const *cipher = pgpCipherDefaultKey( env );
a95c79 ¤   ¤   ¤   if( propname == kPGPKeyPropLockingAlgID )
c5edf4 ¤   ¤   ¤   ¤   *prop = (long)cipher->algorithm;
95bb8c ¤   ¤   ¤   else
91306c ¤   ¤   ¤   ¤   *prop = (long) cipher->keysize * 8;
fc45a6 ¤   ¤   } else {
bc7900 ¤   ¤   ¤   err = pgpSecKeyLockingalgorithm( seckey, &lockalg, &lockbytes );
7959df ¤   ¤   ¤   if( IsPGPError( err ) )
48454a ¤   ¤   ¤   ¤   return err;
bf5c79 ¤   ¤   ¤   if( propname == kPGPKeyPropLockingAlgID )
2ded53 ¤   ¤   ¤   ¤   *prop = (long) lockalg;
bebb8c ¤   ¤   ¤   else
994780 ¤   ¤   ¤   ¤   *prop = (long) lockbytes * 8;
540fe4 ¤   ¤   }
2fccd8 ¤   ¤   pgpSecKeyDestroy (seckey);
9e2f68 ¤   ¤   break;
9d212b ¤   case kPGPKeyPropFlags:
6f5b34 ¤   ¤   {
13d6aa ¤   ¤   ¤   PGPUInt32 flags = 0;
6e2ac5 ¤   ¤   ¤   PGPByte const *pflags;
b4e46f ¤   ¤   ¤   PGPSize flaglen, i;
d4af5a
f540f2 ¤   ¤   ¤   pflags = ringKeyFindSubpacket( keyobj, ringset, SIGSUB_KEYFLAGS,
d5b636 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···0, &flaglen, NULL, NULL, NULL,
98fc22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL, &err );
1059df ¤   ¤   ¤   if( IsPGPError( err ) )
65454a ¤   ¤   ¤   ¤   return err;
472a1b ¤   ¤   ¤   if( IsNull( pflags ) )
f39830 ¤   ¤   ¤   ¤   return kPGPError_InvalidProperty;
4a87c7 ¤   ¤   ¤
8f5982 ¤   ¤   ¤   /* Only return first n bytes */
b11b6b ¤   ¤   ¤   if( flaglen > sizeof(flags) )
62e63f ¤   ¤   ¤   ¤   flaglen = sizeof(flags);
f887c7 ¤   ¤   ¤
5e4542 ¤   ¤   ¤   /* Pack bytes into flags word, first into LSB */
a78777 ¤   ¤   ¤   for( i=0; i<flaglen; ++i ) {
559573 ¤   ¤   ¤   ¤   flags |= pflags[i] << (i*8);
1ca3a6 ¤   ¤   ¤   }
6eaf5a
34f0a4 ¤   ¤   ¤   /* Return flags */
0b09af ¤   ¤   ¤   *prop = flags;
7e0fe4 ¤   ¤   }
c42f72 ¤   default:
b1eecb ¤   ¤   return kPGPError_InvalidProperty;
249371 ¤   }
5c151e ¤   return kPGPError_NoErr;
17efe6 }
cdaf5a
36af5a
--86b3 00024f55a6240100231 Page 48 of pgpKeyMan.c
d1c77d PGPError
5f835e PGPGetKeyNumber (PGPKey *key, PGPKeyPropName propname, PGPInt32 *prop)
54bb36 {
449026 ····PGPError ···········error = kPGPError_NoErr;
58db61 ¤   PGPUserIDRef¤   ¤   userid;
181621 ¤   RingSet const *¤¤   ringset;
3f1a5d ¤   RingPool *¤ ¤   ¤   pgpRingPool;
f9846e ¤   PGPInt32 ···········trustval;
4c270d ¤   PGPEnv const *¤ ¤   pgpEnv;
8caf5a
3e449d ¤   PGPValidatePtr( prop );
25d518 ¤   *prop¤  = 0;
56d5b3 ¤   PGPValidateKey( key );
9667c5 ¤
5f244d ····switch (propname) {
47c98c ¤   case kPGPKeyPropValidity:
bc4e00 ¤   ¤   pgpRingPool = pgpContextGetRingPool( key->keyDB->context );
8bceac ¤   ¤   *prop = kPGPValidity_Unknown;
0e9397 ¤   ¤   pgpIncKeyRefCount (key);
d172ee ¤   ¤   for (userid = (PGPUserID *) key->userIDs.next;·
0a1bc6 ¤   ¤   ¤   ·userid != (PGPUserID *) &key->userIDs; userid = userid->next)
d089f1 ¤   ¤   ¤   ·{·
5a9d20 ¤   ¤   ¤   if (!userid->removed) {
478553 ¤   ¤   ¤   ¤   PGPGetUserIDNumber (userid, kPGPUserIDPropValidity, &trustval);
2e2b50 ¤   ¤   ¤   ¤   if (trustval > *prop)
a7d6ff ¤   ¤   ¤   ¤   ¤   *prop = trustval;
72a3a6 ¤   ¤   ¤   }
410fe4 ¤   ¤   }
0d10f8 ¤   ¤   pgpFreeKey (key);
162f68 ¤   ¤   break;
767c53 ¤   case kPGPKeyPropTrust:
d44e00 ¤   ¤   pgpRingPool = pgpContextGetRingPool( key->keyDB->context );
8ffe95 ¤   ····ringset = pgpKeyDBRingSet (key->keyDB);
8df4e1 ¤   ¤   if (pgpTrustModel (pgpRingPool) == PGPTRUST0) {
3a41a7 ¤   ¤   ¤   PGPByte trust;
912fb9 ¤   ¤   ¤   trust = ringKeyTrust (ringset, key->key);
e410c0 ¤   ¤   ¤   if (trust == kPGPKeyTrust_Undefined ||
d5b77e ¤   ¤   ¤   ¤   trust == kPGPKeyTrust_Unknown)
353831 ¤   ¤   ¤   ····trust = kPGPKeyTrust_Never;
29e84a ¤   ¤   ¤   *prop = (long) trust;
becdcb ¤   ¤   ¤   break;
b3df6f ¤   ¤   } else { /* new trust model */
721d72 ¤   ¤   ¤   *prop = ringTrustExternToOld( pgpRingPool,
34baf2 ¤   ¤   ¤   ¤   ¤   ¤   ··ringTrustToExtern(
08a293 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringKeyConfidence( ringset, key->key ) ) );
700fe4 ¤   ¤   }
f02f68 ¤   ¤   break;
762f72 ¤   default:
4cfe95 ¤   ····ringset = pgpKeyDBRingSet (key->keyDB);
675608 ¤   ¤   pgpEnv = pgpContextGetEnvironment( key->keyDB->context );
c56d96 ¤   ¤   error = ·pgpGetKeyNumberInternal (ringset, key->key, propname, prop,
a3687f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··pgpEnv);
ad9371 ¤   }
29c674 ¤   return error;
29efe6 }
48af5a
fcc77d PGPError
36aae9 PGPGetSubKeyNumber (
36f02d PGPSubKeyRef subkey, PGPKeyPropName propname, PGPInt32 *prop)
59bb36 {
ce9026 ····PGPError ···········error = kPGPError_NoErr;
731621 ¤   RingSet const *¤¤   ringset;
8f270d ¤   PGPEnv const *¤ ¤   pgpEnv;
64af5a
15449d ¤   PGPValidatePtr( prop );
4fd518 ¤   *prop¤  = 0;
3a5992 ¤   PGPValidateSubKey( subkey );
5b67c5 ¤
462ca4 ¤   CHECKREMOVED(subkey);
49e156 ¤   switch (propname) {
fef611 ¤   case kPGPKeyPropAlgID:
24f42d ¤   case kPGPKeyPropBits:
--a3d6 000a0c4248740100231 Page 49 of pgpKeyMan.c
f1d507 ¤   case kPGPKeyPropLockingAlgID:
fff02f ¤   case kPGPKeyPropLockingBits:
ecc30d ¤   ····ringset = pgpKeyDBRingSet (subkey->key->keyDB);
6f6d5c ¤   ¤   pgpEnv = pgpContextGetEnvironment( subkey->key->keyDB->context );
f29c07 ¤   ····error = pgpGetKeyNumberInternal (ringset, subkey->subKey,
519346 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·propname, prop, pgpEnv);
5d2f68 ¤   ¤   break;
ec2f72 ¤   default:
a5eecb ¤   ¤   return kPGPError_InvalidProperty;
1e9371 ¤   }
4ec674 ¤   return error;
68efe6 }
a6af5a
d2af5a
f3f1ae static PGPError
422afc pgpGetKeyTimeInternal (RingSet const *ringset, RingObject *keyobj,
1a82d3 ¤   ¤   ¤   ¤   ¤   ···PGPKeyPropName propname, PGPTime *prop)
36bb36 {
07e156 ¤   switch (propname) {
5f948d ¤   case kPGPKeyPropCreation:
40827c ¤   ¤   *prop = ringKeyCreation (ringset, keyobj);
532f68 ¤   ¤   break;
926a8e ¤   case kPGPKeyPropExpiration:
14952b ¤   ¤   *prop = ringKeyExpiration (ringset, keyobj);
d72f68 ¤   ¤   break;
f32f72 ¤   default:
91eecb ¤   ¤   return kPGPError_InvalidProperty;
e29371 ¤   }
b8151e ¤   return kPGPError_NoErr;
e4efe6 }
dcaf5a
eeaf5a
c4c77d PGPError
3f2a3e PGPGetKeyTime (PGPKey *key, PGPKeyPropName propname, PGPTime *prop)
91bb36 {
6c2253 ····RingSet const ······*ringset;
4367c5 ¤
1b449d ¤   PGPValidatePtr( prop );
ded518 ¤   *prop¤  = 0;
d1d5b3 ¤   PGPValidateKey( key );
de67c5 ¤
f41644 ¤   ringset = pgpKeyDBRingSet (key->keyDB);
fd4b16 ¤   return pgpGetKeyTimeInternal (ringset, key->key, propname, prop);
25efe6 }
d4af5a
50af5a
f8c77d PGPError
9541b6 PGPGetSubKeyTime (PGPSubKeyRef subkey, PGPKeyPropName propname, PGPTime *prop)
babb36 {
961b2d ····RingSet const ·······*ringset;
9c67c5 ¤
97449d ¤   PGPValidatePtr( prop );
34d518 ¤   *prop¤  = 0;
a65992 ¤   PGPValidateSubKey( subkey );
9a67c5 ¤
4a2ca4 ¤   CHECKREMOVED(subkey);
024bad ¤   ringset = pgpKeyDBRingSet (subkey->key->keyDB);
c3417e ¤   return pgpGetKeyTimeInternal (ringset, subkey->subKey, propname, prop);
c0efe6 }
3faf5a
d6af5a
a666dd ¤   static PGPError
2053aa pgpGetKeyStringInternal(
b4ceb8 ¤   RingSet const *¤¤   ringset,
ea48e9 ¤   RingObject *¤   ¤   keyobj,·
c8902a ¤   ·PGPKeyPropName¤¤   propname,
fb496d ¤   ·void *¤¤   ¤   ¤   prop,
401517 ¤   ·PGPSize¤   ¤   ¤   bufferSize,
05b6f6 ¤   ·PGPSize *¤ ¤   ¤   actualLength)
cebb36 {
54686b ¤   uchar ···············buffer[20];
a084d4 ¤   PGPCipherAlgorithm * prefAlgsLong;
--fb90 000b528727b40100231 Page 50 of pgpKeyMan.c
3a0e68 ¤   PGPByte *¤  ¤   ¤   ·prefAlgs;
7db312 ¤   PGPUInt32¤  ¤   ¤   ·i;
562f91 ¤   PGPContextRef¤  ¤   ·context;
462259 ¤   PGPError¤   ¤   ¤   ·err;
25af5a
b1e156 ¤   switch (propname) {
2f2f72 ¤   default:
39eecb ¤   ¤   return kPGPError_InvalidProperty;
bb1b52 ¤   ¤
d0b935 ¤   case kPGPKeyPropFingerprint:
8dccfb ¤   ¤   if (ringKeyV3(ringset, keyobj)) {
4ddfc7 ¤   ¤   ¤   ringKeyFingerprint16 (ringset, keyobj, buffer);
a9c742 ¤   ¤   ¤   *actualLength = 16;
b50fe4 ¤   ¤   }
4207e0 ¤   ¤   else {
fdb856 ¤   ¤   ¤   ringKeyFingerprint20 (ringset, keyobj, buffer);
b33456 ¤   ¤   ¤   *actualLength = 20;
7c0fe4 ¤   ¤   }
252f68 ¤   ¤   break;
3aaf5a
a90c13 ¤   case kPGPKeyPropThirdPartyRevocationKeyID:
f3c7a1 ¤   {
0358bf ¤   ¤   PGPKeyID¤   ¤   keyid;
1c3714 ¤   ¤   PGPByte const *¤idBytes;
de67c5 ¤
0d83c6 ¤   ¤   if (!ringKeyHasThirdPartyRevocation (keyobj, ringset,
c5e607 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·NULL, NULL, &keyid, &err)) {
f0a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
c40fe4 ¤   ¤   }
943bda ¤   ¤   idBytes¤= pgpGetKeyBytes( &keyid );
c4a5de ¤   ¤   for (i = 0; i < 4; i++)
b84aef ¤   ¤   ¤   buffer[i] = idBytes[i+4];
0487c7 ¤   ¤   ¤
7bfb3c ¤   ¤   *actualLength = 4;
f32f68 ¤   ¤   break;
689371 ¤   }
cdaf5a
20d5d1 ¤   case kPGPKeyPropPreferredAlgorithms:
642226 ¤   ¤   /* Must convert from byte form to array of PGPCipherAlgorithm */
b882db ¤   ¤   prefAlgs = (PGPByte *)ringKeyFindSubpacket (
209a53 ¤   ¤   ¤   ¤   keyobj, ringset, SIGSUB_PREFERRED_ENCRYPTION_ALGS, 0,
ab2b35 ¤   ¤   ¤   ¤   actualLength, NULL, NULL, NULL, NULL, &err);
802099 ¤   ¤   if( IsNull( prefAlgs ) ) {
738c75 ¤   ¤   ¤   *actualLength = 0;
4433bc ¤   ¤   ¤   return kPGPError_NoErr;
2d0fe4 ¤   ¤   }
0a67a2 ¤   ¤   context = ringPoolContext(ringSetPool(ringset));
3ef7d3 ¤   ¤   prefAlgsLong = (PGPCipherAlgorithm *)pgpContextMemAlloc ( context,
e40659 ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufferSize * sizeof(PGPCipherAlgorithm), 0 );
a47b76 ¤   ¤   if( IsNull( prefAlgsLong ) )
4c7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
53249b ¤   ¤   for (i=0; i < bufferSize; ++i) {
9bd616 ¤   ¤   ¤   prefAlgsLong[i] = (PGPCipherAlgorithm)prefAlgs[i];
450fe4 ¤   ¤   }
95a63f ¤   ¤   *actualLength *= sizeof(PGPCipherAlgorithm);
a4ff1b ¤   ¤   err = pgpReturnPropBuffer (
42232e ¤   ¤   ¤   ¤   (char const *)prefAlgsLong, prop, *actualLength,
f1177d ¤   ¤   ¤   ¤   bufferSize );
ea2763 ¤   ¤   pgpContextMemFree( context, prefAlgsLong );
87c9db ¤   ¤   return err;
559371 ¤   }
8c67c5 ¤
dcbb2d ¤   return pgpReturnPropBuffer ( (char const *)buffer,
1a2286 ¤   ¤   ¤   prop, *actualLength, bufferSize);
34efe6 }
6caf5a
c0c744 ¤   PGPError
8078c0 PGPGetKeyPropertyBuffer(
25cd9b ¤   PGPKeyRef¤  ¤   key,
874fa4 ¤   PGPKeyPropName¤ propname,
fc9838 ¤   PGPSize¤¤   ¤   bufferSize,
b5771e ¤   void *¤ ¤   ¤   outData,
--60f4 0006f88dce140100231 Page 51 of pgpKeyMan.c
f9e897 ¤   PGPSize *¤  ¤   outLength )
68bb36 {
272253 ····RingSet const ······*ringset;
4bffa9 ····PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
1caf5a
0e1b90 ¤   PGPValidatePtr( outLength );
ef9f08 ¤   *outLength¤ = 0;
f8d5b3 ¤   PGPValidateKey( key );
f4b4eb ¤   /* outData is allowed to be NULL */
d5640b ¤   if ( IsntNull( outData ) )
11c7a1 ¤   {
8dfd21 ¤   ¤   pgpClearMemory( outData, bufferSize );
6a9371 ¤   }
2d67c5 ¤
1d1644 ¤   ringset = pgpKeyDBRingSet (key->keyDB);
ee67c5 ¤
107ecb ¤   err¤= pgpGetKeyStringInternal (ringset, key->key,
9fceff ¤   ¤   ¤   propname, outData, bufferSize, outLength );
fcaf5a
88deb7 ¤   return( err );
21efe6 }
c1af5a
11af5a
52c744 ¤   PGPError
9e10ec PGPGetSubKeyPropertyBuffer(
783fa4 ¤   PGPSubKeyRef¤   subKey,
834fa4 ¤   PGPKeyPropName¤ propname,
979838 ¤   PGPSize¤¤   ¤   bufferSize,
64771e ¤   void *¤ ¤   ¤   outData,
19e897 ¤   PGPSize *¤  ¤   outLength )
7abb36 {
622253 ····RingSet const ······*ringset;
e0ffa9 ····PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f5af5a
5e1b90 ¤   PGPValidatePtr( outLength );
d59f08 ¤   *outLength¤ = 0;
743a11 ¤   PGPValidateSubKey( subKey );
ca640b ¤   if ( IsntNull( outData ) )
c9fd21 ¤   ¤   pgpClearMemory( outData, bufferSize );
9b67c5 ¤
33a9c4 ¤   CHECKREMOVED(subKey);
35aea2 ¤   ringset = pgpKeyDBRingSet (subKey->key->keyDB);
df67c5 ¤
761e38 ¤   err¤= pgpGetKeyStringInternal (ringset, subKey->subKey,
8cceff ¤   ¤   ¤   propname, outData, bufferSize, outLength );
b0af5a
addeb7 ¤   return( err );
aaefe6 }
96af5a
be4643 /* Check other aspects of key usability for sign/encrypt etc. */
20f1ae static PGPError
2f38e5 sIsUsableKey (RingSet const *ringset, RingObject *keyobj,
30007c ¤   ¤   ¤   ··PGPKeyPropName propname, PGPBoolean *usable)
03bb36 {
4c4e48 ¤   PGPInt32¤   ¤   pkalg;
264811 ¤   PGPInt32¤   ¤   bits;
29af81 ¤   RingPool¤   ¤   *pool;
3eed6f ¤   PGPContextRef ¤ context;
5246b2 ¤   PGPEnv¤ ¤   ¤   *env;·
823bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
2faf5a
8b92b6 ¤   pgpAssert (IsntNull( usable ) );
12f8d0 ¤   (void) propname;
b2af5a
58b782 ¤   *usable = TRUE;
0caf5a
d962d3 ¤   /* Disallow RSA keys bigger than BSafe supports */
129d7b ¤   pool = ringSetPool( ringset );
c86b0f ¤   context = ringPoolContext( pool );
d3f78d ¤   env = pgpContextGetEnvironment( context );
d6af5a
6f1fa5 ¤   err = pgpGetKeyNumberInternal( ringset, keyobj, kPGPKeyPropAlgID,
--6481 000e0aa274d40100231 Page 52 of pgpKeyMan.c
04c4d9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&pkalg, env );
f33b4a ¤   if( IsPGPError( err) )
74c9db ¤   ¤   return err;
6a8ad5 ¤   err = pgpGetKeyNumberInternal( ringset, keyobj, kPGPKeyPropBits,
b59743 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&bits, env );
013b4a ¤   if( IsPGPError( err) )
f0c9db ¤   ¤   return err;
56af5a
27230a ¤   if( pkalg <= kPGPPublicKeyAlgorithm_RSA + 2 && bits > MAXRSABITS)
e8273f ¤   ¤   *usable = FALSE;
19af5a
d15ea8 ¤   return err;
82efe6 }
b3af5a
a3af5a
e8f1ae static PGPError
eaebdf pgpGetKeyBooleanInternal (RingSet const *ringset, RingObject *keyobj,
3ba1fc ¤   ¤   ¤   ¤   ¤   ¤   ··PGPKeyPropName propname, PGPBoolean *prop)
36bb36 {
58a9ad ¤   PGPSecKey *¤¤   ¤   seckey = NULL;
3db778 ¤   PGPUInt32¤  ¤   ¤   expiration;
837d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
2567c5 ¤
7dd8af ¤   /*
dfabbb ¤   ** Note: Some computed properties call this function recursively to get
d4dcf5 ¤   ** other properties. This is done so the logic of implementing a
b58cd6 ¤   ** particular property only occurrs in one location
e69faa ¤   */
0067c5 ¤
d8e156 ¤   switch (propname) {
88f0d4 ¤   case kPGPKeyPropIsSecret:
78c126 ¤   ¤   *prop = (ringKeyIsSec (ringset, keyobj) != 0);
b02f68 ¤   ¤   break;
25f29d ¤   case kPGPKeyPropIsAxiomatic:
184deb ¤   ¤   *prop = (ringKeyAxiomatic (ringset, keyobj) != 0);
9b2f68 ¤   ¤   break;
14db03 ¤   case kPGPKeyPropIsRevoked:
ba9e20 ¤   ¤   *prop = (ringKeyRevoked (ringset, keyobj) != 0);
068d13 ¤   ¤   /* "Or" in revocation status of master key on subkeys */
ec662f ¤   ¤   if (!*prop &&
564b0f ¤   ¤   ¤   ringKeyIsSubkey (ringset, keyobj))
e59a11 ¤   ¤   ¤   *prop = (ringKeyRevoked (ringset,
b588e7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringKeyMasterkey(ringset, keyobj))) != 0;
2a2f68 ¤   ¤   break;
0e8260 ¤   case kPGPKeyPropIsRevocable:
221046 ¤   ¤   if (ringKeyIsSec (ringset, keyobj)) {
ffbd4d ¤   ¤   ¤   *prop = TRUE;
4945a6 ¤   ¤   } else {
9d7076 ¤   ¤   ¤   RingObject *revobj;
e57639 ¤   ¤   ¤   PGPByte revclass;
bba1a6 ¤   ¤   ¤   PGPUInt32 i;
6daf5a
04a81f ¤   ¤   ¤   *prop = FALSE;
16864b ¤   ¤   ¤   if (ringKeyIsSubkey (ringset, keyobj))
daccd7 ¤   ¤   ¤   ¤   keyobj = ringKeyMasterkey (ringset, keyobj);
f89278 ¤   ¤   ¤   pgpAssert (IsntNull( keyobj ) );
80a024 ¤   ¤   ¤   for (i=0; ; ++i) {
4d44b5 ¤   ¤   ¤   ¤   revobj = ringKeyRevocationKey (keyobj, ringset, i, NULL, NULL,
b330bb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&revclass, NULL, &err);
52e42e ¤   ¤   ¤   ¤   if( IsPGPError( err ) ) {
6eaede ¤   ¤   ¤   ¤   ¤   if( err == kPGPError_ItemNotFound )
ce22e3 ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
c314c3 ¤   ¤   ¤   ¤   ¤   break;
e62613 ¤   ¤   ¤   ¤   }
76086a ¤   ¤   ¤   ¤   if( IsNull( revobj ) )
155914 ¤   ¤   ¤   ¤   ¤   continue;
2737ff ¤   ¤   ¤   ¤   if ((revclass & 0x80) == 0)
165914 ¤   ¤   ¤   ¤   ¤   continue;
0fff2f ¤   ¤   ¤   ¤   if (ringKeyIsSec (ringset, revobj)) {
bc0311 ¤   ¤   ¤   ¤   ¤   *prop = TRUE;
1214c3 ¤   ¤   ¤   ¤   ¤   break;
e02613 ¤   ¤   ¤   ¤   }
--34da 000be038b2640100231 Page 53 of pgpKeyMan.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
d62f68 ¤   ¤   break;
14af5a
c3e942 ¤   case kPGPKeyPropHasThirdPartyRevocation:
ebbd9f ¤   ¤   *prop = ringKeyHasThirdPartyRevocation (keyobj, ringset,
ff2c5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL, NULL, &err);
182f68 ¤   ¤   break;
f0af5a
b1d303 ¤   case kPGPKeyPropIsSecretShared:
9b5b34 ¤   ¤   {
01451c ¤   ¤   ¤   PGPBoolean isSecretShared = FALSE;
374b8d ¤   ¤   ¤   if( ringKeyIsSec (ringset, keyobj) )
b8f776 ¤   ¤   ¤   {
b6f681 ¤   ¤   ¤   ¤   seckey = ringSecSecKey (ringset, keyobj, 0);
358117 ¤   ¤   ¤   ¤   if (!seckey) {
4d10ea ¤   ¤   ¤   ¤   ¤   err = ringSetError(ringset)->error;
fb8d66 ¤   ¤   ¤   ¤   ¤   /* Don't return an error for unsupported key types */
fbd532 ¤   ¤   ¤   ¤   ¤   if (err == kPGPError_FeatureNotAvailable) {
f471bb ¤   ¤   ¤   ¤   ¤   ¤   *prop = FALSE;
8466df ¤   ¤   ¤   ¤   ¤   ¤   return kPGPError_NoErr;
5b1c89 ¤   ¤   ¤   ¤   ¤   }
4ee814 ¤   ¤   ¤   ¤   ¤   return err;
a42613 ¤   ¤   ¤   ¤   }
cabd27 ¤   ¤   ¤   ¤   if( pgpSecKeyIslocked (seckey) )
b972c3 ¤   ¤   ¤   ¤   {
b2d3cd ¤   ¤   ¤   ¤   ¤   PGPStringToKeyType s2ktype;
6d1c32 ¤   ¤   ¤   ¤   ¤   pgpSecKeyS2Ktype( seckey, &s2ktype );
023e32 ¤   ¤   ¤   ¤   ¤   if( s2ktype == kPGPStringToKey_LiteralShared )
665ad0 ¤   ¤   ¤   ¤   ¤   ¤   isSecretShared = TRUE;
0b2613 ¤   ¤   ¤   ¤   }
1a8367 ¤   ¤   ¤   ¤   pgpSecKeyDestroy (seckey);
40a3a6 ¤   ¤   ¤   }
aaff34 ¤   ¤   ¤   *prop = isSecretShared;
f50fe4 ¤   ¤   }
432f68 ¤   ¤   break;
a61cc5 ¤   case kPGPKeyPropHasUnverifiedRevocation:
e65b34 ¤   ¤   {
457b4e ¤   ¤   ¤   /* ·Must look for a revocation signature with the same signing·
69bfc0 ¤   ¤   ¤   ¤   key id. */
c228e4 ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   keyid;
da62b2 ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   revkeyid;
b14186 ¤   ¤   ¤   RingIterator *¤ ¤   iter = NULL;
72be26 ¤   ¤   ¤   RingObject *¤   ¤   obj;
8e3751 ¤   ¤   ¤   unsigned¤   ¤   ¤   level;
c5af5a
d8a81f ¤   ¤   ¤   *prop = FALSE;
85845a ¤   ¤   ¤   ringKeyID8 (ringset, keyobj, NULL, &keyid);
7321a6 ¤   ¤   ¤   iter = ringIterCreate (ringset);
4bf8f8 ¤   ¤   ¤   if (!iter)
98f776 ¤   ¤   ¤   {
a6bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
93f622 ¤   ¤   ¤   ¤   break;
e1a3a6 ¤   ¤   ¤   }
fd87c7 ¤   ¤   ¤
4bda21 ¤   ¤   ¤   ringIterSeekTo (iter, keyobj);
6db0be ¤   ¤   ¤   level = ringIterCurrentLevel (iter);
f536c7 ¤   ¤   ¤   ringIterRewind (iter, level+1);
20ff66 ¤   ¤   ¤   while (ringIterNextObject (iter, level+1) > 0) {
358e1c ¤   ¤   ¤   ¤   obj = ringIterCurrentObject (iter, level+1);
901f23 ¤   ¤   ¤   ¤   if (ringObjectType(obj) == RINGTYPE_SIG &&
23100e ¤   ¤   ¤   ¤   ¤   ringSigType (ringset, obj) == PGP_SIGTYPE_KEY_REVOKE) {
375a43 ¤   ¤   ¤   ¤   ¤   ringSigID8 (ringset, obj, NULL, &revkeyid);
ba8f0d ¤   ¤   ¤   ¤   ¤   if (pgpKeyIDsEqual( &keyid, &revkeyid )) {
18ec62 ¤   ¤   ¤   ¤   ¤   ¤   *prop = TRUE;
4200eb ¤   ¤   ¤   ¤   ¤   ¤   break;
951c89 ¤   ¤   ¤   ¤   ¤   }
542613 ¤   ¤   ¤   ¤   }
f5a3a6 ¤   ¤   ¤   }
d9d87d ¤   ¤   ¤   ringIterDestroy (iter);
220fe4 ¤   ¤   }
be2f68 ¤   ¤   break;
--ed0f 0008d32a1e340100231 Page 54 of pgpKeyMan.c
80bb03 ¤   case kPGPKeyPropIsDisabled:
90f533 ¤   ¤   *prop = (ringKeyDisabled (ringset, keyobj) != 0);
222f68 ¤   ¤   break;
afb677 ¤   case kPGPKeyPropNeedsPassphrase:
2d237b ¤   ¤   if (!ringKeyIsSec (ringset, keyobj))
215b34 ¤   ¤   {
3a7d4f ¤   ¤   ¤   err = kPGPError_SecretKeyNotFound;
89cdcb ¤   ¤   ¤   break;
970fe4 ¤   ¤   }
2abf07 ¤   ¤   seckey = ringSecSecKey (ringset, keyobj, 0);
3567f9 ¤   ¤   if (!seckey)
4c5b34 ¤   ¤   {
20d307 ¤   ¤   ¤   err = ringSetError(ringset)->error;
10cdcb ¤   ¤   ¤   break;
e50fe4 ¤   ¤   }
2e1b52 ¤   ¤
b8ce38 ¤   ¤   *prop = (pgpSecKeyIslocked (seckey) != 0);
9dccd8 ¤   ¤   pgpSecKeyDestroy (seckey);
ee2f68 ¤   ¤   break;
7489c3 ¤   case kPGPKeyPropIsExpired:
ddd01c ¤   ¤   expiration = ringKeyExpiration (ringset, keyobj);
2f8f05 ¤   ¤   if (expiration == 0)
32bdcd ¤   ¤   ¤   *prop = 0;
a30e1d ¤   ¤   else
34ace6 ¤   ¤   ¤   *prop = (expiration < (PGPUInt32) PGPGetTime());
522f68 ¤   ¤   break;
6ca224 ¤   case kPGPKeyPropIsNotCorrupt:
2b8510 ¤   ····*prop = (ringKeyError (ringset, keyobj) == 0);
882f68 ¤   ¤   break;
0f3ca1 ¤   case kPGPKeyPropIsSigningKey:
9fddef ¤   ····*prop = ((ringKeyUse (ringset, keyobj) & PGP_PKUSE_SIGN) != 0);
1a2f68 ¤   ¤   break;
5ae043 ¤   case kPGPKeyPropIsEncryptionKey:
986e9d ¤   ····*prop = ((ringKeyUse (ringset, keyobj) & PGP_PKUSE_ENCRYPT) != 0);
392f68 ¤   ¤   break;
de1b52 ¤   ¤
a26d2e ¤   case kPGPKeyPropCanEncrypt:
fed588 ¤   case kPGPKeyPropCanSign:
6ac7a1 ¤   {
c2a4f3 ¤   ¤   /* Not corrupted and not revoked and not expired and not disabled */
a9af5a
36e4ee ¤   ¤   PGPBoolean¤ notCorrupted;
971b52 ¤   ¤
704afe ¤   ¤   *prop = FALSE;
121b52 ¤   ¤
9e1256 ¤   ¤   if( propname == kPGPKeyPropCanSign )
195b34 ¤   ¤   {
77eb4a ¤   ¤   ¤   PGPBoolean¤ isSecretKey;
f387c7 ¤   ¤   ¤
873dd1 ¤   ¤   ¤   /* Quick reject non-secret keys in the signing case */
fa9fc4 ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
c6f9e6 ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsSecret, &isSecretKey );
3bf4c4 ¤   ¤   ¤   if( IsPGPError( err ) || ! isSecretKey )
83f622 ¤   ¤   ¤   ¤   break;
a40fe4 ¤   ¤   }
ae1b52 ¤   ¤
67b971 ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
0d95c1 ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsNotCorrupt, &notCorrupted );
ddc23f ¤   ¤   if( IsntPGPError( err ) && notCorrupted )
c15b34 ¤   ¤   {
f88c13 ¤   ¤   ¤   PGPBoolean¤ isRevoked;
be87c7 ¤   ¤   ¤
329fc4 ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
55fd01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsRevoked, &isRevoked );
5e7c43 ¤   ¤   ¤   if( IsntPGPError( err ) && ! isRevoked )
87f776 ¤   ¤   ¤   {
849f20 ¤   ¤   ¤   ¤   PGPBoolean¤ isExpired;
6b2b85 ¤   ¤   ¤   ¤
8845ed ¤   ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
07b156 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsExpired, &isExpired );
79d52e ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && ! isExpired )
8d72c3 ¤   ¤   ¤   ¤   {
--c414 000c772df9d40100231 Page 55 of pgpKeyMan.c
b8a5e2 ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ isDisabled;
cdae30 ¤   ¤   ¤   ¤   ¤
9dcfa8 ¤   ¤   ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
f9b83c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsDisabled, &isDisabled );
aabf4c ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && ! isDisabled )
7c4859 ¤   ¤   ¤   ¤   ¤   {
261af2 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean isUsable;
bcaf5a
392783 ¤   ¤   ¤   ¤   ¤   ¤   err = sIsUsableKey( ringset, keyobj, propname,
ad5b49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &isUsable );
4aa9e2 ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && isUsable )
948fec ¤   ¤   ¤   ¤   ¤   ¤   {
276a65 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( propname == kPGPKeyPropCanEncrypt )
cb06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
e34d8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *prop = ((ringKeyUnexpiredUse(ringset, keyobj)
208cb8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··& PGP_PKUSE_ENCRYPT) != 0);
5d5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
77c4dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   else
5606b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
cf43c8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset,
08cf4e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyobj, kPGPKeyPropIsSigningKey, prop );
715268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
50db3c ¤   ¤   ¤   ¤   ¤   ¤   }
b11c89 ¤   ¤   ¤   ¤   ¤   }
0d2613 ¤   ¤   ¤   ¤   }
b4a3a6 ¤   ¤   ¤   }
5b0fe4 ¤   ¤   }
361b52 ¤   ¤
892f68 ¤   ¤   break;
139371 ¤   }
07af5a
cc87bf ¤   case kPGPKeyPropCanDecrypt:
05c7a1 ¤   {
c2d622 ¤   ¤   PGPBoolean¤ isSecretKey;
5c1b52 ¤   ¤
c39b4b ¤   ¤   /* Is secret key and not corrupted and is encryption key */
57af5a
ef4afe ¤   ¤   *prop = FALSE;
3e1b52 ¤   ¤
61b971 ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
97df53 ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsSecret, &isSecretKey );
f59d34 ¤   ¤   if( IsntPGPError( err ) && isSecretKey )
d55b34 ¤   ¤   {
030b9d ¤   ¤   ¤   PGPBoolean¤ notCorrupted;
5987c7 ¤   ¤   ¤
b49fc4 ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
aa80e2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsNotCorrupt, &notCorrupted );
7d6c3e ¤   ¤   ¤   if( IsntPGPError( err ) && notCorrupted )
f9f776 ¤   ¤   ¤   {
7c19a7 ¤   ¤   ¤   ¤   PGPBoolean isUsable;
28af5a
92b9f3 ¤   ¤   ¤   ¤   err = sIsUsableKey( ringset, keyobj, propname,
a56761 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &isUsable );
354895 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && isUsable )
5f72c3 ¤   ¤   ¤   ¤   {
d9cfa8 ¤   ¤   ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
890d2c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsEncryptionKey, prop );
d32613 ¤   ¤   ¤   ¤   }
89a3a6 ¤   ¤   ¤   }
360fe4 ¤   ¤   }
a71b52 ¤   ¤
f12f68 ¤   ¤   break;
7c9371 ¤   }
9267c5 ¤
2d4a2a ¤   case kPGPKeyPropCanVerify:
9fc7a1 ¤   {
2e89bf ¤   ¤   /* Can verify if not corrupted and a signature key */
dbe4ee ¤   ¤   PGPBoolean¤ notCorrupted;
89af5a
0cb971 ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
3495c1 ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsNotCorrupt, &notCorrupted );
c7c23f ¤   ¤   if( IsntPGPError( err ) && notCorrupted )
--573c 00067c8703340100231 Page 56 of pgpKeyMan.c
e35b34 ¤   ¤   {
cf24cf ¤   ¤   ¤   PGPBoolean isUsable;
6baf5a
a7b911 ¤   ¤   ¤   err = sIsUsableKey( ringset, keyobj, propname,
ca35fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &isUsable );
8be694 ¤   ¤   ¤   if( IsntPGPError( err ) && isUsable )
47f776 ¤   ¤   ¤   {
9845ed ¤   ¤   ¤   ¤   err = pgpGetKeyBooleanInternal( ringset, keyobj,
ff26dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsSigningKey, prop );
13a3a6 ¤   ¤   ¤   }
2d0fe4 ¤   ¤   }
402f68 ¤   ¤   break;
fd9371 ¤   }
afaf5a
6a2f72 ¤   default:
a9239f ¤   ¤   err = kPGPError_InvalidProperty;
742f68 ¤   ¤   break;
fc9371 ¤   }
0a67c5 ¤
2a5ea8 ¤   return err;
ceefe6 }
63af5a
d6af5a
fcc77d PGPError
1377dd PGPGetKeyBoolean (PGPKey *key, PGPKeyPropName propname, PGPBoolean *prop)
a0bb36 {
ad2253 ····RingSet const ······*ringset;
eaaf5a
ad449d ¤   PGPValidatePtr( prop );
e9fdbf ¤   *prop¤  = FALSE;
40d5b3 ¤   PGPValidateKey( key );
e267c5 ¤
661644 ¤   ringset = pgpKeyDBRingSet (key->keyDB);
7f0e84 ¤   return pgpGetKeyBooleanInternal (ringset, key->key, propname, prop);
1cefe6 }
f7af5a
f9af5a
5bc77d PGPError
755d58 PGPGetSubKeyBoolean (
a89638 PGPSubKeyRef subkey, PGPKeyPropName propname, PGPBoolean *prop)
33bb36 {
1b2253 ····RingSet const ······*ringset;
52af5a
d29b36 ¤   pgpa(pgpaPGPSubKeyValid(subkey));
1667c5 ¤
e4449d ¤   PGPValidatePtr( prop );
62fdbf ¤   *prop¤  = FALSE;
055992 ¤   PGPValidateSubKey( subkey );
9267c5 ¤
4a2ca4 ¤   CHECKREMOVED(subkey);
af4bad ¤   ringset = pgpKeyDBRingSet (subkey->key->keyDB);
e896de ¤   if (propname == kPGPKeyPropIsAxiomatic)
a9e2ab ¤   ····return kPGPError_InvalidProperty;
97e94c ¤   return pgpGetKeyBooleanInternal (ringset, subkey->subKey, propname, prop);
6eefe6 }
e4af5a
89af5a
cbc77d PGPError
603efb PGPGetUserIDNumber (
4c6b8f PGPUserID *userid, PGPUserIDPropName propname, PGPInt32 *prop)
75bb36 {
e41369 ¤   RingSet const¤  ¤   *ringset = NULL;
2a4220 ¤   union RingObject ···*nameobj = NULL;
84c236 ¤   RingPool¤   ¤   ····*pgpRingPool;
84af5a
c49309 ¤   pgpa(pgpaPGPUserIDValid(userid));
6167c5 ¤
b0449d ¤   PGPValidatePtr( prop );
a4d518 ¤   *prop¤  = 0;
cbca71 ¤   PGPValidateUserID( userid );
5b67c5 ¤
670acf ¤   CHECKREMOVED(userid);
--19de 000965a7caa40100231 Page 57 of pgpKeyMan.c
e0df3f ¤   ringset¤¤   = pgpKeyDBRingSet (userid->key->keyDB);
f4d1e0 ¤   nameobj¤¤   = userid->userID;
271f01 ¤   pgpRingPool¤= ringSetPool( ringset );
a4af5a
1de156 ¤   switch (propname) {
d93eba ¤   case kPGPUserIDPropValidity:
b74092 ¤   ¤   if (pgpTrustModel (pgpRingPool) == PGPTRUST0)·
4ec523 ¤   ¤   ····*prop = (long) ringNameTrust (ringset, nameobj);
8207e0 ¤   ¤   else {
f92a76 ¤   ¤   ¤   PGPUInt32 namevalidity;
150ac5 ¤   ¤   ¤   namevalidity = ringTrustExternToOld( pgpRingPool,
8d8df9 ¤   ¤   ¤   ¤   ¤   ringTrustToExtern(
29d2c9 ¤   ¤   ¤   ¤   ¤   ¤   ringNameValidity( ringset, nameobj ) ) );
d26d3a ¤   ¤   ¤   /* namevalidity is keytrust scale */
5e6e69 ¤   ¤   ¤   if (namevalidity <= kPGPKeyTrust_Unknown)
0c3b3c ¤   ¤   ¤   ¤   *prop = kPGPNameTrust_Unknown;
28d412 ¤   ¤   ¤   else if (namevalidity < kPGPKeyTrust_Marginal)
68be7c ¤   ¤   ¤   ¤   *prop = kPGPNameTrust_Untrusted;
499252 ¤   ¤   ¤   else if (namevalidity == kPGPKeyTrust_Marginal)
692024 ¤   ¤   ¤   ¤   *prop = kPGPNameTrust_Marginal;
c5bb8c ¤   ¤   ¤   else
278092 ¤   ¤   ¤   ¤   *prop = kPGPNameTrust_Complete;
b10fe4 ¤   ¤   }
a72f68 ¤   ¤   break;
f9761d ¤   case kPGPUserIDPropConfidence:·
30ff87 ¤   ¤   if (pgpTrustModel (ringSetPool(ringset)) > PGPTRUST0) {
ca6e54 ¤   ¤   ¤   *prop = ringNameConfidence (ringset, nameobj);
11cdcb ¤   ¤   ¤   break;
4a0fe4 ¤   ¤   }
e29f05 ¤   case kPGPUserIDPropAttributeType:
a6db4d ¤   ¤   (void) ringNameAttributeSubpacket( nameobj, ringset, 0,
73adaa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPUInt32 *)prop, NULL, NULL );
262f68 ¤   ¤   break;
831b52 ¤   ¤
892f72 ¤   default:
37eecb ¤   ¤   return kPGPError_InvalidProperty;
189371 ¤   }
99151e ¤   return kPGPError_NoErr;
e0efe6 }
c7af5a
d1af5a
93c77d PGPError
7b6e5f PGPGetUserIDBoolean (
be202d PGPUserID *userid, PGPUserIDPropName propname, PGPBoolean *prop)
debb36 {
531369 ¤   RingSet const¤  ¤   *ringset = NULL;
3d4220 ¤   union RingObject ···*nameobj = NULL;
edc236 ¤   RingPool¤   ¤   ····*pgpRingPool;
42af5a
769309 ¤   pgpa(pgpaPGPUserIDValid(userid));
0067c5 ¤
32449d ¤   PGPValidatePtr( prop );
3cfdbf ¤   *prop¤  = FALSE;
72ca71 ¤   PGPValidateUserID( userid );
4267c5 ¤
1e0acf ¤   CHECKREMOVED(userid);
e3df3f ¤   ringset¤¤   = pgpKeyDBRingSet (userid->key->keyDB);
07d1e0 ¤   nameobj¤¤   = userid->userID;
b41f01 ¤   pgpRingPool¤= ringSetPool( ringset );
72af5a
78e156 ¤   switch (propname) {
d1af04 ¤   case kPGPUserIDPropIsAttribute:
83144e ¤   ¤   *prop = ringNameIsAttribute( ringset, nameobj ) != 0;
2d2f68 ¤   ¤   break;
382f72 ¤   default:
37eecb ¤   ¤   return kPGPError_InvalidProperty;
fa9371 ¤   }
95151e ¤   return kPGPError_NoErr;
aaefe6 }
a1af5a
31af5a
960335 /*____________________________________________________________________________
--e5a9 0002aad0cef40100231 Page 58 of pgpKeyMan.c
efe273 ¤   Name is always returned NULL terminated.
ac67c5 ¤
ab2440 ¤   if 'outString' is NULL, then just the size is returned.
9bf7f7 ____________________________________________________________________________*/
47c744 ¤   PGPError
36ec33 PGPGetUserIDStringBuffer(
4603f8 ¤   PGPUserIDRef¤   ¤   userid,
2b8427 ¤   PGPUserIDPropName¤  propname,
1b1799 ¤   PGPSize¤¤   ¤   ¤   bufferSize,
b601ce ¤   char *¤ ¤   ¤   ¤   outString,
b6dc06 ¤   PGPSize *¤  ¤   ¤   fullLengthOut )
e8bb36 {
311369 ¤   RingSet const¤  ¤   *ringset = NULL;
1a372a ¤   char const¤ ········*bufptr;
8fd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
62b589 ¤   PGPSize¤¤   ¤   ¤   fullLength;
74daff ¤   PGPSize¤¤   ¤   ¤   nullOffset;
26af5a
4d84f0 ¤   if ( IsntNull( fullLengthOut ) )
cca316 ¤   ¤   *fullLengthOut¤ = 0;
05ca71 ¤   PGPValidateUserID( userid );
df5a09 ¤   PGPValidateParam( bufferSize != 0 );
7e5c98 #if PGP_DEBUG
808607 ¤   if ( IsntNull( outString ) )
8b1a24 ¤   ¤   pgpClearMemory( outString, bufferSize );
407454 #endif
0a67c5 ¤
640acf ¤   CHECKREMOVED(userid);
b7c910 ¤   ringset¤=¤  pgpKeyDBRingSet (userid->key->keyDB);
8daf5a
dbcd47 ¤   switch( propname ) {
5e57d7 ¤   case kPGPUserIDPropName:
ba2e69 ¤   ¤   if (ringNameIsAttribute (ringset, userid->userID))
79d70e ¤   ¤   ¤   return kPGPError_InvalidProperty;
074a99 ¤   ¤   bufptr¤ = ringNameName (ringset, userid->userID, &fullLength );
c01db6 ¤   ¤   ++fullLength;¤  /* leave room for null terminator */
e92f68 ¤   ¤   break;
eaaf5a
032258 ¤   case kPGPUserIDPropAttributeData:
fe7ecc ¤   ¤   if (!ringNameIsAttribute (ringset, userid->userID))
04d70e ¤   ¤   ¤   return kPGPError_InvalidProperty;
de495a ¤   ¤   bufptr¤ = (const char *)ringNameAttributeSubpacket (userid->userID,
404611 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ringset, 0, NULL, &fullLength, &err );
16d223 ¤   ¤   if( IsPGPError( err ) )
b5b32f ¤   ¤   ¤   return err;
922f68 ¤   ¤   break;
c6af5a
6a2f72 ¤   default:
1aeecb ¤   ¤   return kPGPError_InvalidProperty;
619371 ¤   }
4eaf5a
f950cb ¤   err¤= pgpReturnPropBuffer ( bufptr,
70e393 ¤   ¤   (PGPByte *)outString, fullLength, bufferSize);
0e67c5 ¤
b3784c ¤   if ( IsntNull( outString ) && propname==kPGPUserIDPropName )
00c7a1 ¤   {
f9323b ¤   ¤   /* always null terminate since it's a string */
935d94 ·¤  ¤   nullOffset¤ ¤   ¤   ¤   = pgpMin( fullLength, bufferSize ) - 1;
23f66d ¤   ¤   outString[ nullOffset ]¤= '\0';
8b9371 ¤   }
8867c5 ¤
cb84f0 ¤   if ( IsntNull( fullLengthOut ) )
891a32 ¤   ¤   *fullLengthOut¤ = fullLength;
4067c5 ¤
afdeb7 ¤   return( err );
4eefe6 }
9aaf5a
64c77d PGPError
be096c PGPGetSigNumber (PGPSig *cert, PGPSigPropName propname, PGPInt32 *prop)
ddbb36 {
f71369 ¤   RingSet const¤  ¤   *ringset = NULL;
2a3ac5 ¤   union RingObject ···*sigobj = NULL;
--478d 000e868856740100231 Page 59 of pgpKeyMan.c
803106 ¤   PGPByte¤¤   ¤   ¤   pkalg;
40773a ¤   unsigned long¤  ¤   longkeyid;
5c4f69 ¤   int ················i;
36af5a
c8449d ¤   PGPValidatePtr( prop );
3ed518 ¤   *prop¤  = 0;
0fc107 ¤   PGPValidateCert( cert );
7d67c5 ¤
0f4c88 ¤   CHECKREMOVED(cert);
6793c3 ¤   ringset =¤  pgpKeyDBRingSet (cert->up.userID->key->keyDB);
226dd2 ¤   sigobj =¤   cert->cert;
eaaf5a
c6e156 ¤   switch (propname) {
79f55c ¤   case kPGPSigPropKeyID:
e8c7a1 ¤   {
4e58bf ¤   ¤   PGPKeyID¤   ¤   keyid;
e556b2 ¤   ¤   PGPByte const *¤idBytes;;
1767c5 ¤
bf48d4 ¤   ¤   ringSigID8 (ringset, sigobj, NULL, &keyid);
adaa62 ¤   ¤   longkeyid = 0;
133bda ¤   ¤   idBytes¤= pgpGetKeyBytes( &keyid );
b8b605 ¤   ¤   for (i = 4; i < 8; i++)
55e6e8 ¤   ¤   ¤   longkeyid = (longkeyid << 8) + idBytes[i];
c387c7 ¤   ¤   ¤
8d955b ¤   ¤   /* *prop should be cast to (unsigned long) */
3681ea ¤   ¤   *prop = (long) longkeyid; ·
102f68 ¤   ¤   break;
0c9371 ¤   }
dc67c5 ¤
f0ec80 ¤   case kPGPSigPropAlgID:
361840 ¤   ¤   ringSigID8 (ringset, sigobj, &pkalg, NULL);
1b550e ¤   ¤   *prop = (long) pkalg;
982f68 ¤   ¤   break;
65e186 ¤   case kPGPSigPropTrustLevel:
f7b9af ¤   ¤   *prop = (long)ringSigTrustLevel(ringset, sigobj);
762f68 ¤   ¤   break;
220ae3 ¤   case kPGPSigPropTrustValue:
97e829 ¤   ¤   *prop = (long)ringSigTrustValue(ringset, sigobj);
a72f68 ¤   ¤   break;
5d2f72 ¤   default:
58eecb ¤   ¤   return kPGPError_InvalidProperty;
a59371 ¤   }
b4151e ¤   return kPGPError_NoErr;
80efe6 }
90af5a
67af5a
de66dd ¤   static PGPError
ad79f4 pgpGetSigStringInternal(
8eceb8 ¤   RingSet const *¤¤   ringset,
6ec03d ¤   RingObject *¤   ¤   sigobj,·
82c8aa ¤   ·PGPSigPropName¤¤   propname,
58496d ¤   ·void *¤¤   ¤   ¤   prop,
c71517 ¤   ·PGPSize¤   ¤   ¤   bufferSize,
8cb6f6 ¤   ·PGPSize *¤ ¤   ¤   actualLength)
45bb36 {
fadb9a ¤   PGPByte *¤  ¤   ¤   ptr;
932097 ¤   PGPSize¤¤   ¤   ¤   len;
2baf5a
39e156 ¤   switch (propname) {
f52f72 ¤   default:
6aeecb ¤   ¤   return kPGPError_InvalidProperty;
861b52 ¤   ¤
32c96e ¤   case kPGPSigPropX509Certificate:
9b2d65 ¤   ¤   if (!ringSigIsX509 (ringset, sigobj))
9cd70e ¤   ¤   ¤   return kPGPError_InvalidProperty;
a5c32d ¤   ¤   ptr = ringSigX509Certificate(ringset, sigobj, &len);
a6eba5 ¤   ¤   if (IsNull( ptr ) )
f0d70e ¤   ¤   ¤   return kPGPError_InvalidProperty;
cc9934 ¤   ¤   *actualLength = len;
5f2f68 ¤   ¤   break;
319371 ¤   }
e867c5 ¤
--8ebe 000db9c9e3340100231 Page 60 of pgpKeyMan.c
5b713d ¤   return pgpReturnPropBuffer ( (char const *)ptr,
482286 ¤   ¤   ¤   prop, *actualLength, bufferSize);
8befe6 }
6eaf5a
dfaf5a
40c744 ¤   PGPError
14529e PGPGetSigPropertyBuffer(
fd7c1c ¤   PGPSigRef¤  ¤   cert,
3d44b1 ¤   PGPSigPropName¤ propname,
629838 ¤   PGPSize¤¤   ¤   bufferSize,
34771e ¤   void *¤ ¤   ¤   outData,
1ce897 ¤   PGPSize *¤  ¤   outLength )
93bb36 {
242253 ····RingSet const ······*ringset;
54ffa9 ····PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
5caf5a
b91b90 ¤   PGPValidatePtr( outLength );
f19f08 ¤   *outLength¤ = 0;
54c107 ¤   PGPValidateCert( cert );
8ab4eb ¤   /* outData is allowed to be NULL */
ba640b ¤   if ( IsntNull( outData ) )
b8c7a1 ¤   {
7afd21 ¤   ¤   pgpClearMemory( outData, bufferSize );
ba9371 ¤   }
1267c5 ¤
4d03e2 ¤   ringset = pgpKeyDBRingSet (cert->up.userID->key->keyDB);
2967c5 ¤
855cb0 ¤   err¤= pgpGetSigStringInternal (ringset, cert->cert,
8aceff ¤   ¤   ¤   propname, outData, bufferSize, outLength );
c8af5a
27deb7 ¤   return( err );
b2efe6 }
cfaf5a
1faf5a
dfc744 ¤   PGPError
5350af PGPGetKeyIDOfCertifier(
90c6d2 ¤   PGPSig *¤   ¤   cert,
b1e25c ¤   PGPKeyID *¤ outID )
0abb36 {
c95503 ¤   RingSet const *¤¤   ringset = NULL;
8105a0 ¤   union RingObject *¤ sigobj = NULL;
4fd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
fdaf5a
2edebf ¤   PGPValidatePtr( outID );
0cca7c ¤   pgpClearMemory( outID, sizeof( *outID ) );
05bd9b ¤   PGPValidatePtr( cert );
0f67c5 ¤
df757f ¤   pgpa(pgpaPGPCertValid(cert));
6a4c88 ¤   CHECKREMOVED(cert);
e22cdc ¤   ringset¤= pgpKeyDBRingSet (cert->up.userID->key->keyDB);
7a2168 ¤   sigobj¤ = cert->cert;
91af5a
d67936 ¤   ringSigID8( ringset, sigobj, NULL, outID );
fe5ea8 ¤   return err;
73efe6 }
90af5a
d6af5a
46af5a
2dc77d PGPError
cb8a7f PGPGetSigTime (PGPSig *cert, PGPSigPropName propname, PGPTime *prop)
0fbb36 {
c31369 ¤   RingSet const¤  ¤   *ringset = NULL;
ec3ac5 ¤   union RingObject ···*sigobj = NULL;
4aaf5a
39449d ¤   PGPValidatePtr( prop );
68d518 ¤   *prop¤  = 0;
3bc107 ¤   PGPValidateCert( cert );
c267c5 ¤
714c88 ¤   CHECKREMOVED(cert);
b893c3 ¤   ringset =¤  pgpKeyDBRingSet (cert->up.userID->key->keyDB);
276dd2 ¤   sigobj =¤   cert->cert;
dbaf5a
--be9b 00044bb366f40100231 Page 61 of pgpKeyMan.c
b2e156 ¤   switch (propname) {
d52fc9 ¤   case kPGPSigPropCreation:
128fd0 ¤   ¤   *prop = ringSigTimestamp (ringset, sigobj);
b12f68 ¤   ¤   break;
2540d0 ¤   case kPGPSigPropExpiration:
f1fadb ¤   ¤   *prop = ringSigExpiration (ringset, sigobj);
352f68 ¤   ¤   break;
1a2f72 ¤   default:
9aeecb ¤   ¤   return kPGPError_InvalidProperty;
1c9371 ¤   }
06151e ¤   return kPGPError_NoErr;
56efe6 }
88af5a
1eaf5a
a5af5a
05c77d PGPError
6e6eda PGPGetSigBoolean (PGPSig *cert, PGPSigPropName propname, PGPBoolean *prop)
26bb36 {
026835 ¤   RingSet¤const¤  ¤   *ringset = NULL;
dc3e60 ¤   union RingObject ···*sigobj = NULL, *obj = NULL;
88a831 ¤   PGPKeyID¤   ¤   ¤   ·keyid, revkeyid;
7caa93 ¤   RingIterator ¤  ¤   *iter = NULL;
89cc99 ¤   unsigned¤   ¤   ¤   ··level;
6dd5e7 ¤   PGPTime¤¤   ¤   ¤   expiration;
5967c5 ¤
97449d ¤   PGPValidatePtr( prop );
ccfdbf ¤   *prop¤  = FALSE;
f7c107 ¤   PGPValidateCert( cert );
f067c5 ¤
544c88 ¤   CHECKREMOVED(cert);
f893c3 ¤   ringset =¤  pgpKeyDBRingSet (cert->up.userID->key->keyDB);
d06dd2 ¤   sigobj =¤   cert->cert;
a8af5a
b8e156 ¤   switch (propname) {
cfdf98 ¤   case kPGPSigPropIsRevoked:
243625 ¤   case kPGPSigPropHasUnverifiedRevocation:
d16047 ¤   ¤   /* ·Must look for a revocation signature with the same signing·
0f82db ¤   ¤   ¤   key id. ·The revocation sig must be the newer than the certifying
fe39b6 ¤   ¤   ¤   sig to be considered. */
648624 ¤   ¤   *prop = 0;
7e48d4 ¤   ¤   ringSigID8 (ringset, sigobj, NULL, &keyid);
f3271e ¤   ¤   iter = ringIterCreate (ringset);
4ac311 ¤   ¤   if (!iter)
2b7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
745cb9 ¤   ¤   ringIterSeekTo (iter, sigobj);
45e223 ¤   ¤   level = ringIterCurrentLevel (iter);
4ed50b ¤   ¤   ringIterRewind (iter, level);
255f91 ¤   ¤   while (ringIterNextObject (iter, level) > 0) {
df4877 ¤   ¤   ¤   obj = ringIterCurrentObject (iter, level);
28aac6 ¤   ¤   ¤   if (ringSigType (ringset, obj) == PGP_SIGTYPE_KEY_UID_REVOKE) {
719e5f ¤   ¤   ¤   ¤   ringSigID8 (ringset, obj, NULL, &revkeyid);
e5c3da ¤   ¤   ¤   ¤   if (pgpKeyIDsEqual( &keyid, &revkeyid ) &&
da017c ¤   ¤   ¤   ¤   ¤   ····((propname==kPGPSigPropHasUnverifiedRevocation)
756571 ¤   ¤   ¤   ¤   ¤   ¤   ·|| ringSigChecked (ringset, obj)) &&
caa9e7 ¤   ¤   ¤   ¤   ¤   ·······ringSigTimestamp (ringset, obj) >=·
7aa997 ¤   ¤   ¤   ¤   ¤   ···········ringSigTimestamp (ringset, sigobj)) {
c411d8 ¤   ¤   ¤   ¤   ¤   *prop = 1;
ea14c3 ¤   ¤   ¤   ¤   ¤   break;
222613 ¤   ¤   ¤   ¤   }
c3a3a6 ¤   ¤   ¤   }
d90fe4 ¤   ¤   }
9d5381 ¤   ¤   ringIterDestroy (iter);
292f68 ¤   ¤   break;
e7659b ¤   case kPGPSigPropIsNotCorrupt:
efbea0 ¤   ¤   *prop = (ringSigError (ringset, sigobj) == 0);
f52f68 ¤   ¤   break;
322aab ¤   case kPGPSigPropIsTried:
935a4e ¤   ¤   *prop = ringSigTried (ringset, sigobj);
772f68 ¤   ¤   break;
8b32c5 ¤   case kPGPSigPropIsVerified:
2c5de6 ¤   ¤   *prop = ringSigChecked (ringset, sigobj);
442f68 ¤   ¤   break;
--4e59 0004aaeff1840100231 Page 62 of pgpKeyMan.c
921357 ¤   case kPGPSigPropIsMySig:
8341a2 ¤   ¤   obj = ringSigMaker (ringset, sigobj, ringset);
f0e83d ¤   ¤   if (!obj)
f2bdcd ¤   ¤   ¤   *prop = 0;
950e1d ¤   ¤   else
54dd72 ¤   ¤   ¤   *prop = ringKeyIsSec (ringset, obj);
8a2f68 ¤   ¤   break;
a5c655 ¤   case kPGPSigPropIsExportable:
910a78 ¤   ¤   *prop = ringSigExportable (ringset, sigobj);
872f68 ¤   ¤   break;
558d58 ¤   case kPGPSigPropIsExpired:
73bfec ¤   ¤   expiration = ringSigExpiration (ringset, sigobj);
ae8f05 ¤   ¤   if (expiration == 0)
f6bdcd ¤   ¤   ¤   *prop = 0;
070e1d ¤   ¤   else
4face6 ¤   ¤   ¤   *prop = (expiration < (PGPUInt32) PGPGetTime());
482f68 ¤   ¤   break;
ac43ca ¤   case kPGPSigPropIsX509:
ccc1b2 ¤   ¤   *prop = ringSigIsX509 (ringset, sigobj);
2b2f68 ¤   ¤   break;
732f72 ¤   default:
eeeecb ¤   ¤   return kPGPError_InvalidProperty;
c69371 ¤   }
22151e ¤   return kPGPError_NoErr;
10efe6 }
b2af5a
ceaf5a
69af5a
bd6a03 /* ·Get and Set default private key. ·The identification of
876e38 ¤   the key is stored as an ascii keyid in the preferences
268940 ¤   repository. */
7caf5a
2eaf5a
0721ab ¤   PGPError·
a8f51d PGPGetDefaultPrivateKey (
821d2b ¤   PGPKeySet *¤keyset,
73b480 ¤   PGPKeyRef *¤outRef )
b5bb36 {
3e26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
1567c5 ¤
cb3c76 ¤   PGPValidatePtr( outRef );
233652 ¤   *outRef¤= NULL;
1f5193 ¤   PGPValidateKeySet( keyset );
f967c5 ¤
e8803a ¤   err¤= pgpGetDefaultPrivateKeyInternal( keyset->keyDB, outRef );
d9ad8a ¤   /* refcount has been incremented */
4967c5 ¤
d14c5f ¤   pgpAssertErrWithPtr( err, *outRef );
6edeb7 ¤   return( err );
5eefe6 }
96af5a
31af5a
3caf5a
0dc77d PGPError
0d469f PGPSetDefaultPrivateKey (PGPKeyRef¤ key)
3ebb36 {
f4b5eb ¤   PGPBoolean¤ isSecret = 0;
f58081 ¤   PGPBoolean¤ cansign = 0;
7026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
184fb6 ¤   PGPKeyID¤   keyID;
d567c5 ¤
e7d5b3 ¤   PGPValidateKey( key );
ec67c5 ¤
2cd23c ¤   err¤= pgpKeyDeadCheck( key) ;
e2054e ¤   if ( IsPGPError( err ) )
eac9db ¤   ¤   return err;
60da86 ¤   ····
3a1b7a ¤   /* ·Default key must be secret and must be able to sign */
5b1655 ¤   PGPGetKeyBoolean( key, kPGPKeyPropIsSecret, &isSecret);
b25f1c ¤   PGPValidateParam( isSecret );
f567c5 ¤
4adbeb ¤   PGPGetKeyBoolean( key, kPGPKeyPropCanSign, &cansign);
--3905 000ab52d21640100231 Page 63 of pgpKeyMan.c
6a6ae6 ¤   PGPValidateParam( cansign );
e0af5a
03adca ¤   /* Set the default key axiomatic (note we don't require a passphrase) */
11e46a ¤   sSetKeyAxiomatic( key, FALSE, NULL, 0, FALSE );
be67c5 ¤
ee9851 ¤   err¤= PGPGetKeyIDFromKey( key, &keyID );
c5f1e7 ¤   if ( IsntPGPError( err ) )
24c7a1 ¤   {
098e60 ¤   ¤   PGPByte¤¤   data[ kPGPMaxExportedKeyIDSize ];
88f15e ¤   ¤   PGPSize¤¤   exportedSize;
071b52 ¤   ¤
ac1a23 ¤   ¤   err¤= PGPExportKeyID( &keyID, data, &exportedSize );
dc7d98 ¤   ¤   if ( IsntPGPError( err ) )
225b34 ¤   ¤   {
293781 ¤   ¤   ¤   err¤= PGPsdkPrefSetData( PGPGetKeyContext( key),
645771 ¤   ¤   ¤   ¤   ¤   kPGPsdkPref_DefaultKeyID, data, exportedSize );
780fe4 ¤   ¤   }
609371 ¤   }
9567c5 ¤
ed5ea8 ¤   return err;
96efe6 }
2caf5a
a8af5a
b10f96 PgpTrustModel
036075 PGPGetTrustModel (
66cf6e ¤   PGPContextRef¤  context
a127e6 ¤   )
c7bb36 {
4850cd ¤   RingPool¤   ¤   ¤   *pgpRingPool;
a4af5a
8538dc ¤   pgpRingPool = pgpContextGetRingPool( context );
737416 ¤   return pgpTrustModel (pgpRingPool);
83efe6 }
8aaf5a
8aaf5a
7dadac /* ·UserVal functions */
b7af5a
cdc77d PGPError
9728c7 PGPSetKeyUserVal (PGPKey *key, PGPUserValue userVal)
7fbb36 {
32d5b3 ¤   PGPValidateKey( key );
7afb66 ¤   key->userVal = userVal;
e9151e ¤   return kPGPError_NoErr;
1fefe6 }
baaf5a
c5af5a
8fc77d PGPError
690a7b PGPSetUserIDUserVal (PGPUserID *userid, PGPUserValue userVal)
39bb36 {
7bca71 ¤   PGPValidateUserID( userid );
64017c ¤   userid->userVal = userVal;
57151e ¤   return kPGPError_NoErr;
cfefe6 }
66af5a
2caf5a
2ac77d PGPError
3d3b3d PGPSetSubKeyUserVal (PGPSubKeyRef subkey, PGPUserValue userVal)
35bb36 {
8d5992 ¤   PGPValidateSubKey( subkey );
3aa9eb ¤   subkey->userVal = userVal;
bc151e ¤   return kPGPError_NoErr;
85efe6 }
4eaf5a
bbaf5a
b1c77d PGPError
db3b17 PGPSetSigUserVal (PGPSig *cert, PGPUserValue userVal)
dcbb36 {
3dc107 ¤   PGPValidateCert( cert );
2bb20b ¤   cert->userVal = userVal;
c9151e ¤   return kPGPError_NoErr;
83efe6 }
abaf5a
--356d 0006ffc9d8f40100231 Page 64 of pgpKeyMan.c
e0af5a
c6c77d PGPError
1022dd PGPGetKeyUserVal (PGPKey *key, PGPUserValue *userVal)
dcbb36 {
e8d5b3 ¤   PGPValidateKey( key );
2b4325 ¤   *userVal = key->userVal;
ab151e ¤   return kPGPError_NoErr;
c4efe6 }
3faf5a
12af5a
5ac77d PGPError
44c7a9 PGPGetUserIDUserVal (PGPUserID *userid, PGPUserValue *userVal)
51bb36 {
bcca71 ¤   PGPValidateUserID( userid );
a42dbf ¤   *userVal = userid->userVal;
a7151e ¤   return kPGPError_NoErr;
f5efe6 }
75af5a
4fc77d PGPError
2e000d PGPGetSubKeyUserVal (PGPSubKeyRef subkey, PGPUserValue *userVal)
87bb36 {
315992 ¤   PGPValidateSubKey( subkey );
a5629c ¤   *userVal = subkey->userVal;
82151e ¤   return kPGPError_NoErr;
46efe6 }
38af5a
2fc77d PGPError
4488bd PGPGetSigUserVal (PGPSig *cert, PGPUserValue *userVal)
85bb36 {
d4c107 ¤   PGPValidateCert( cert );
ba6f42 ¤   *userVal = cert->userVal;
9b151e ¤   return kPGPError_NoErr;
dfefe6 }
e2af5a
5566dd ¤   static PGPError
36880e sGetPrimaryUserID (
18b3a4 ¤   PGPKey *¤   ¤   ·key,
7aaae1 ¤   PGPBoolean¤ ¤   ·getAttribute,
cd6357 ¤   PGPAttributeType attributeType,
fca935 ¤   PGPUserIDRef *¤ ·outRef)
c6bb36 {
e47847 ¤   const PGPUserID *¤  userID;
a8f55c ¤   RingSet¤const¤  *ringset;
f6a5fd ¤   PGPBoolean¤ ¤   ·attributeOK = FALSE;
edef5c ¤   PGPUInt32¤  ¤   ·type;
efa3d6 ¤   PGPError¤   ¤   ·err¤   = kPGPError_NoErr;
9daf5a
0d0933 ¤   userID = (const PGPUserID *) &key->userIDs;
0d1644 ¤   ringset = pgpKeyDBRingSet (key->keyDB);
f4af5a
cacfa1 ¤   do
98c7a1 ¤   {
8c98dc ¤   ¤   userID = userID->next;
e41819 ¤   ¤   if (userID == (const PGPUserID *)&key->userIDs)
bc5b34 ¤   ¤   {
783c41 ¤   ¤   ¤   err¤¤   = kPGPError_ItemNotFound;
5db1d5 ¤   ¤   ¤   userID¤ = kInvalidPGPUserIDRef;
f6cdcb ¤   ¤   ¤   break;
380fe4 ¤   ¤   }
c66415 ¤   ¤   if( userID->removed )
0317f5 ¤   ¤   ¤   continue;
e04a25 ¤   ¤   if( getAttribute )
6b5b34 ¤   ¤   {
bc6350 ¤   ¤   ¤   if( ringNameIsAttribute( ringset, userID->userID ) )
34f776 ¤   ¤   ¤   {
0c9598 ¤   ¤   ¤   ¤   (void) ringNameAttributeSubpacket( userID->userID, ringset,
748683 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···0, &type, NULL, NULL );
b4da22 ¤   ¤   ¤   ¤   attributeOK = ((PGPAttributeType)type == attributeType);
d4a3a6 ¤   ¤   ¤   }
07bb8c ¤   ¤   ¤   else
abf776 ¤   ¤   ¤   {
6fd5ee ¤   ¤   ¤   ¤   attributeOK = FALSE;
--456f 000c5c5e5eb40100231 Page 65 of pgpKeyMan.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
850e1d ¤   ¤   else
325b34 ¤   ¤   {
34cae3 ¤   ¤   ¤   attributeOK = !ringNameIsAttribute( ringset, userID->userID );
180fe4 ¤   ¤   }
16af5a
aa7d5a ¤   } while( !attributeOK );
3caf5a
9c7bb2 ¤   *outRef¤= (PGPUserIDRef)userID;
bc67c5 ¤
b55ea8 ¤   return err;
69efe6 }
62af5a
9521ab ¤   PGPError·
4f2df6 PGPGetPrimaryUserID (
d8f0d4 ¤   PGPKey *¤   ¤   key,
b2a68d ¤   PGPUserIDRef *¤ outRef)
14bb36 {
873c76 ¤   PGPValidatePtr( outRef );
e13652 ¤   *outRef¤= NULL;
3dd5b3 ¤   PGPValidateKey( key );
60af5a
1c0889 ¤   return sGetPrimaryUserID (key, FALSE, (PGPAttributeType)0, outRef );
33efe6 }
5eaf5a
1faf5a
8a21ab ¤   PGPError·
5854c1 PGPGetPrimaryAttributeUserID (
cbf0d4 ¤   PGPKey *¤   ¤   key,
7e6357 ¤   PGPAttributeType attributeType,
d2a68d ¤   PGPUserIDRef *¤ outRef)
41bb36 {
f83c76 ¤   PGPValidatePtr( outRef );
1a3652 ¤   *outRef¤= NULL;
b9d5b3 ¤   PGPValidateKey( key );
51af5a
0ede44 ¤   return sGetPrimaryUserID( key, TRUE, attributeType, outRef );
6defe6 }
b7af5a
5baf5a
bf0335 /*____________________________________________________________________________
1be273 ¤   Name is always returned NULL terminated.
7c67c5 ¤
bb7b23 ¤   if name is null, then just the size is returned
1df7f7 ____________________________________________________________________________*/
fbc744 ¤   PGPError
e987f6 PGPGetPrimaryUserIDNameBuffer(
511d0c ¤   PGPKeyRef¤  key,
04c102 ¤   PGPSize¤¤   bufferSize,
9dced6 ¤   char *¤ ¤   name,
65093d ¤   PGPSize *¤  fullLength ·)
1abb36 {
805709 ¤   PGPUserIDRef¤   ¤   userID;
54d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f767c5 ¤
48d5b3 ¤   PGPValidateKey( key );
af2c75 ¤   PGPValidateParam( IsntNull( name ) || IsntNull( fullLength ) );
aaaf5a
653a61 ¤   err¤ = PGPGetPrimaryUserID (key, &userID );
3cf1e7 ¤   if ( IsntPGPError( err ) )
bcc7a1 ¤   {
7f998a ¤   ¤   err¤= PGPGetUserIDStringBuffer( userID,
d3d300 ¤   ¤   ¤   kPGPUserIDPropName, bufferSize, name, fullLength);
129371 ¤   }
6767c5 ¤
89deb7 ¤   return( err );
a2efe6 }
98af5a
1bc77d PGPError
b490dd PGPGetPrimaryUserIDValidity (PGPKey *key, PGPValidity *validity)
c5bb36 {
--3392 0002079278f40100231 Page 66 of pgpKeyMan.c
f69589 ¤   PGPUserID *¤¤   userID;
839372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
82af5a
cb5fce ¤   PGPValidatePtr( validity );
05ba63 ¤   *validity¤  = kPGPValidity_Unknown;
b4d5b3 ¤   PGPValidateKey( key );
27af5a
e4f81a ¤   err = PGPGetPrimaryUserID(key, &userID);
b3f1e7 ¤   if ( IsntPGPError( err ) )
f4c7a1 ¤   {
5a927a ¤   ¤   PGPInt32¤   temp;
ed1b52 ¤   ¤
848aca ¤   ¤   err¤= PGPGetUserIDNumber(userID, kPGPUserIDPropValidity, &temp);
9a7d98 ¤   ¤   if ( IsntPGPError( err ) )
29b258 ¤   ¤   ¤   *validity¤  = (PGPValidity)temp;
a39371 ¤   }
32deb7 ¤   return( err );
bfefe6 }
89af5a
4f38e5 /*
22c27e ·* XXX: This routine must be kept in sync with the hash algorithm
eaa3ab ·* ·····selection made in pgpSigSpecCreate (in pgpSigSpec.c)
78495d ·*/
3ec77d PGPError
964290 PGPGetHashAlgUsed (PGPKey *key, PGPHashAlgorithm *hashAlg)
2dbb36 {
fb4b09 ¤   PGPPublicKeyAlgorithm¤  pkAlg¤  = kPGPPublicKeyAlgorithm_Invalid;
8a0a69 ¤   PGPEnv*¤¤   ¤   ¤   ¤   pgpEnv;
c860f3 ¤   PGPInt32¤   ¤   ¤   ¤   temp;
9cba49 ¤   PGPError¤   ¤   ¤   ¤   err;
3eaf5a
50eb77 ¤   PGPValidatePtr( hashAlg );
f224e3 ¤   *hashAlg¤   = kPGPHashAlgorithm_Invalid;
b9d5b3 ¤   PGPValidateKey( key );
f1af5a
8ecfbf ¤   err = PGPGetKeyNumber(key, kPGPKeyPropAlgID, &temp);
8bf988 ¤   pkAlg¤  = (PGPPublicKeyAlgorithm)temp;
6cf1e7 ¤   if ( IsntPGPError( err ) )
2ac7a1 ¤   {
f81b52 ¤   ¤
d95608 ¤   ¤   pgpEnv = pgpContextGetEnvironment( key->keyDB->context );
6eba6d ¤   ¤   if (pkAlg == kPGPPublicKeyAlgorithm_DSA)
7bb684 ¤   ¤   ¤   *hashAlg = kPGPHashAlgorithm_SHA;
fb0e1d ¤   ¤   else
e5cb26 ¤   ¤   ¤   *hashAlg = (PGPHashAlgorithm)
2a161f ¤   ¤   ¤   ¤   pgpenvGetInt(pgpEnv, PGPENV_HASH, NULL, NULL);
559371 ¤   }
775ea8 ¤   return err;
1cefe6 }
43af5a
6938e5 /*
ad6682 ·* The following functions are for internal use within other parts of the
6482af ·* library, to access the lower level components of PGPKeys and associated
395c3a ·* structures.
ea495d ·*/
2caf5a
0fc77d PGPError
6d19e6 pgpGetKeyRingObject (PGPKey *key, PGPBoolean checkDead, RingObject **pRingKey)
13bb36 {
3061e0 ¤   PGPError¤   err;
9167c5 ¤
4e5e68 ¤   pgpa((
004cfa ¤   ¤   pgpaPGPKeyValid(key),
92c72a ¤   ¤   pgpaAddrValid(pRingKey, RingObject *)));
dd67c5 ¤
4c2651 ¤   *pRingKey = NULL;
40d27b ¤   if( checkDead ) {
7b3d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
12be18 ¤   ¤   if ( IsPGPError( err ) )
bbb32f ¤   ¤   ¤   return err;
169371 ¤   }
20af5a
--7ca1 000b910b93540100231 Page 67 of pgpKeyMan.c
0ccd00 ¤   *pRingKey = key->key;
72151e ¤   return kPGPError_NoErr;
64efe6 }
deaf5a
d1c77d PGPError
4feac5 pgpGetKeyRingSet (PGPKey *key, PGPBoolean checkDead, RingSet const**pRingSet)
8fbb36 {
4161e0 ¤   PGPError¤   err;
7b67c5 ¤
d05e68 ¤   pgpa((
514cfa ¤   ¤   pgpaPGPKeyValid(key),
0beb5d ¤   ¤   pgpaAddrValid(pRingSet, RingSet *)));
0967c5 ¤
7bccf7 ¤   *pRingSet = NULL;
dbd27b ¤   if( checkDead ) {
a83d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
1bbe18 ¤   ¤   if ( IsPGPError( err ) )
e0b32f ¤   ¤   ¤   return err;
4e9371 ¤   }
3caf5a
35ac4b ¤   *pRingSet = pgpKeyDBRingSet( key->keyDB );
a2151e ¤   return kPGPError_NoErr;
d9efe6 }
beaf5a
61c77d PGPError
f28c0d pgpGetUserIDRingObject (PGPUserID *userid, PGPBoolean checkDead,
9e6a58 ¤   RingObject **pRingName)
1bbb36 {
dfd4a1 ¤   PGPKey¤ ¤   ¤   *key;
f661e0 ¤   PGPError¤   err;
3baf5a
ea5e68 ¤   pgpa((
5e390e ¤   ¤   pgpaPGPUserIDValid(userid),
b45c61 ¤   ¤   pgpaAddrValid(pRingName, RingObject *)));
81af5a
bb009e ¤   *pRingName = NULL;
b10092 ¤   if (userid->removed)
702f19 ¤   ····return kPGPError_BadParams;
d105c3 ¤   key = userid->key;
cdd27b ¤   if( checkDead ) {
1f3d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
e4be18 ¤   ¤   if ( IsPGPError( err ) )
05b32f ¤   ¤   ¤   return err;
1e9371 ¤   }
0caf5a
d4222d ¤   *pRingName = userid->userID;
b4151e ¤   return kPGPError_NoErr;
1fefe6 }
a7af5a
a7c77d PGPError
98536f pgpGetUserIDRingSet (PGPUserID ·*userid, PGPBoolean checkDead,
23e175 ¤   RingSet const**pRingSet)
d4bb36 {
6c15ed ¤   PGPKey¤ ¤   *key;
0661e0 ¤   PGPError¤   err;
8faf5a
2a5e68 ¤   pgpa((
f3390e ¤   ¤   pgpaPGPUserIDValid(userid),
0feb5d ¤   ¤   pgpaAddrValid(pRingSet, RingSet *)));
6567c5 ¤
e5ccf7 ¤   *pRingSet = NULL;
f20092 ¤   if (userid->removed)
902f19 ¤   ····return kPGPError_BadParams;
f905c3 ¤   key = userid->key;
e3d27b ¤   if( checkDead ) {
2f3d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
d2be18 ¤   ¤   if ( IsPGPError( err ) )
8fb32f ¤   ¤   ¤   return err;
9a9371 ¤   }
0caf5a
03ac4b ¤   *pRingSet = pgpKeyDBRingSet( key->keyDB );
b9151e ¤   return kPGPError_NoErr;
--8fc4 000f939c5d340100231 Page 68 of pgpKeyMan.c
7aefe6 }
46af5a
9ec77d PGPError
68fa22 pgpGetUserIDKey (PGPUserID *userid, PGPBoolean checkDead, PGPKey **pKey)
10bb36 {
b7d4a1 ¤   PGPKey¤ ¤   ¤   *key;
b061e0 ¤   PGPError¤   err;
f5af5a
595e68 ¤   pgpa((
49390e ¤   ¤   pgpaPGPUserIDValid(userid),
0f267d ¤   ¤   pgpaAddrValid(pKey, PGPKey *)));
baaf5a
8e5e8b ¤   *pKey = NULL;
c30092 ¤   if (userid->removed)
d32f19 ¤   ····return kPGPError_BadParams;
7f05c3 ¤   key = userid->key;
29d27b ¤   if( checkDead ) {
cc3d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
7ebe18 ¤   ¤   if ( IsPGPError( err ) )
d2b32f ¤   ¤   ¤   return err;
cc9371 ¤   }
cdaf5a
a34674 ¤   *pKey = key;
1c151e ¤   return kPGPError_NoErr;
5aefe6 }
79af5a
55c77d PGPError
771a12 pgpGetCertRingObject (PGPSig *cert, PGPBoolean checkDead,
feb43a ¤   RingObject **pRingSig)
febb36 {
77d4a1 ¤   PGPKey¤ ¤   ¤   *key;
53de84 ¤   PGPUserID¤  ¤   *userid;
eefb19 ¤   PGPError¤   ¤   err;
31af5a
475e68 ¤   pgpa((
8f7297 ¤   ¤   pgpaPGPCertValid(cert),
e28a91 ¤   ¤   pgpaAddrValid(pRingSig, RingObject *)));
9caf5a
c28833 ¤   *pRingSig = NULL;
26fcb4 ¤   if (cert->removed)
6d2f19 ¤   ····return kPGPError_BadParams;
7baf05 ¤   if (cert->type==uidcert) {
d1cc6d ¤   ¤   userid = cert->up.userID;
1634cf ¤   ¤   if (userid->removed)
55a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
03e722 ¤   ¤   key = userid->key;
6df037 ¤   } else {
1d21e3 ¤   ¤   key = cert->up.key;
e89371 ¤   }
f4d27b ¤   if( checkDead ) {
aa3d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
42be18 ¤   ¤   if ( IsPGPError( err ) )
1fb32f ¤   ¤   ¤   return err;
589371 ¤   }
b0af5a
222f17 ¤   *pRingSig = cert->cert;
01151e ¤   return kPGPError_NoErr;
eaefe6 }
87af5a
84c77d PGPError
02306e pgpGetCertRingSet (PGPSig *cert, PGPBoolean checkDead,
c71c2f ¤   RingSet const **pRingSet)
39bb36 {
05d4a1 ¤   PGPKey¤ ¤   ¤   *key;
bfde84 ¤   PGPUserID¤  ¤   *userid;
61fb19 ¤   PGPError¤   ¤   err;
33af5a
f15e68 ¤   pgpa((
5e7297 ¤   ¤   pgpaPGPCertValid(cert),
b3eb5d ¤   ¤   pgpaAddrValid(pRingSet, RingSet *)));
e067c5 ¤
f9ccf7 ¤   *pRingSet = NULL;
--a209 0006cb1d36640100231 Page 69 of pgpKeyMan.c
43fcb4 ¤   if (cert->removed)
572f19 ¤   ····return kPGPError_BadParams;
b6af05 ¤   if (cert->type==uidcert) {
e6cc6d ¤   ¤   userid = cert->up.userID;
c534cf ¤   ¤   if (userid->removed)
92a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
f4e722 ¤   ¤   key = userid->key;
d2f037 ¤   } else {
b221e3 ¤   ¤   key = cert->up.key;
339371 ¤   }
36d27b ¤   if( checkDead ) {
a23d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
b7be18 ¤   ¤   if ( IsPGPError( err ) )
5eb32f ¤   ¤   ¤   return err;
c09371 ¤   }
52af5a
58ac4b ¤   *pRingSet = pgpKeyDBRingSet( key->keyDB );
91151e ¤   return kPGPError_NoErr;
92efe6 }
93af5a
7d3f96 /* This sets *pUserid to NULL but returns no error if cert is on a key */
d1c77d PGPError
f5c906 pgpGetCertUserID (PGPSig *cert, PGPBoolean checkDead, PGPUserID **pUserid)
18bb36 {
10d4a1 ¤   PGPKey¤ ¤   ¤   *key;
606615 ¤   PGPUserID¤  ¤   *userid = NULL;
57fb19 ¤   PGPError¤   ¤   err;
79af5a
025e68 ¤   pgpa((
927297 ¤   ¤   pgpaPGPCertValid(cert),
07120e ¤   ¤   pgpaAddrValid(pUserid, PGPUserID *)));
9faf5a
d33749 ¤   *pUserid = NULL;
fbfcb4 ¤   if (cert->removed)
ed2f19 ¤   ····return kPGPError_BadParams;
4aaf05 ¤   if (cert->type==uidcert) {
07cc6d ¤   ¤   userid = cert->up.userID;
ac34cf ¤   ¤   if (userid->removed)
bba7e0 ¤   ¤   ¤   return kPGPError_BadParams;
44e722 ¤   ¤   key = userid->key;
40f037 ¤   } else {
6621e3 ¤   ¤   key = cert->up.key;
8e9371 ¤   }
33d27b ¤   if( checkDead ) {
d63d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
babe18 ¤   ¤   if ( IsPGPError( err ) )
25b32f ¤   ¤   ¤   return err;
1c9371 ¤   }
eaaf5a
11e29d ¤   *pUserid = userid;¤ ¤   ¤   /* Will be NULL if keycert */
b4151e ¤   return kPGPError_NoErr;
c1efe6 }
8eaf5a
19c77d PGPError
4dca98 pgpGetCertKey (PGPSig *cert, PGPBoolean checkDead, PGPKey **pKey)
b1bb36 {
f1d4a1 ¤   PGPKey¤ ¤   ¤   *key;
13de84 ¤   PGPUserID¤  ¤   *userid;
54fb19 ¤   PGPError¤   ¤   err;
1caf5a
215e68 ¤   pgpa((
6c7297 ¤   ¤   pgpaPGPCertValid(cert),
12267d ¤   ¤   pgpaAddrValid(pKey, PGPKey *)));
4daf5a
4e5e8b ¤   *pKey = NULL;
55fcb4 ¤   if (cert->removed)
012f19 ¤   ····return kPGPError_BadParams;
30af05 ¤   if (cert->type==uidcert) {
83cc6d ¤   ¤   userid = cert->up.userID;
a134cf ¤   ¤   if (userid->removed)
30a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
6ce722 ¤   ¤   key = userid->key;
--b6a2 0002334ecc140100231 Page 70 of pgpKeyMan.c
faf037 ¤   } else {
2021e3 ¤   ¤   key = cert->up.key;
e89371 ¤   }
6fd27b ¤   if( checkDead ) {
4f3d4f ¤   ¤   err¤= pgpKeyDeadCheck( key) ;
b0be18 ¤   ¤   if ( IsPGPError( err ) )
d8b32f ¤   ¤   ¤   return err;
199371 ¤   }
28af5a
c54674 ¤   *pKey = key;
9d151e ¤   return kPGPError_NoErr;
ecefe6 }
0eaf5a
93af5a
34af5a
c1af5a
e4d8f8 ¤   PGPContextRef
bc722b pgpGetKeyDBContext( PGPKeyDBRef ref )
7abb36 {
fd21af ¤   pgpAssert( pgpKeyDBIsValid( ref ) );
9067c5 ¤
99a956 ¤   if ( ! pgpKeyDBIsValid( ref ) )
cdc2a5 ¤   ¤   return( kInvalidPGPContextRef );
461b52 ¤   ¤
b17d44 ¤   return( ref->context );
6cefe6 }
abaf5a
19d8f8 ¤   PGPContextRef
b549a6 PGPGetKeyListContext( PGPKeyListRef ref )
13bb36 {
0ddeee ¤   if ( ! pgpKeyListIsValid( ref ) )
45c2a5 ¤   ¤   return( kInvalidPGPContextRef );
261b52 ¤   ¤
839504 ¤   return( PGPGetKeySetContext( ref->keySet ) );
b6efe6 }
90af5a
73af5a
1dd8f8 ¤   PGPContextRef
05991c PGPGetKeySetContext( PGPKeySetRef ref )
c6bb36 {
14c2a1 ¤   if ( ! pgpKeySetIsValid( ref ) )
cbc2a5 ¤   ¤   return( kInvalidPGPContextRef );
1b1b52 ¤   ¤
2db1d7 ¤   return( pgpGetKeyDBContext( ref->keyDB ) );
d0efe6 }
94af5a
8cd8f8 ¤   PGPContextRef
573e7b PGPGetKeyIterContext( PGPKeyIterRef ref )
4bbb36 {
ffd498 ¤   if ( ! pgpKeyIterIsValid( ref ) )
fac2a5 ¤   ¤   return( kInvalidPGPContextRef );
8d1b52 ¤   ¤
49cf5b ¤   return( PGPGetKeyListContext( ref->keyList ) );
91efe6 }
63af5a
06d8f8 ¤   PGPContextRef
78b012 PGPGetKeyContext( PGPKeyRef ref )
92bb36 {
c37a19 ¤   if ( ! pgpKeyIsValid( ref ) )
06c2a5 ¤   ¤   return( kInvalidPGPContextRef );
3a1b52 ¤   ¤
e1b1d7 ¤   return( pgpGetKeyDBContext( ref->keyDB ) );
e1efe6 }
a8af5a
68d8f8 ¤   PGPContextRef
d79772 PGPGetSubKeyContext( PGPSubKeyRef ref )
b5bb36 {
d99a95 ¤   if ( ! pgpSubKeyIsValid( ref ) )
d2c2a5 ¤   ¤   return( kInvalidPGPContextRef );
941b52 ¤   ¤
334f6c ¤   return( pgpGetKeyDBContext( ref->key->keyDB ) );
23efe6 }
--d848 001ce546de740100231 Page 71 of pgpKeyMan.c
e0af5a
1aaf5a
a5d8f8 ¤   PGPContextRef
2777d0 PGPGetUserIDContext( PGPUserIDRef ref )
9cbb36 {
ba9620 ¤   if ( ! pgpUserIDIsValid( ref ) )
3ac2a5 ¤   ¤   return( kInvalidPGPContextRef );
141b52 ¤   ¤
e90338 ¤   return( PGPGetKeyContext( ref->key ) );
feefe6 }
c8af5a
72af5a
7aaf5a
0e38e5 /*
c3e6c5 ·* Local Variables:
1a9b19 ·* tab-width: 4
1fe7a4 ·* End:
25b612 ·* vi: ts=4 sw=4
b56c42 ·* vim: si
ce495d ·*/
--436f 000b09dc88540100232 Page 1 of pgpKeySet.c
bc38e5 /*
54c21a ·* PGPKeySet implementation
0d775e ·*
4794ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
d420c7 ·* All rights reserved
47775e ·*
f8516a ·* $Id: pgpKeySet.c,v 1.87.10.1 1998/11/12 03:22:03 heller Exp $
f3495d ·*/
c5af5a
b3e2ff #include "pgpConfig.h"
b0af5a
4bef82 #ifdef HAVE_STDLIB_H
d4bea3 #include <stdlib.h>
737454 #endif
0eaf5a
7a324c #include <string.h>
41b1cb #include <ctype.h>
85af5a
74979a #include "pgpKDBInt.h"
8f675a #include "pgpTypes.h"
5fa146 #include "pgpDebug.h"
150d08 #include "pgpMem.h"
832266 #include "pgpTimeDate.h"
03d11f #include "pgpUsuals.h"
9395a9 #include "pgpMemPool.h"
ab5d28 #include "pgpRngMnt.h"
b026e3 #include "pgpRngPub.h"
dec26c #include "pgpContext.h"
e67ca7 #include "pgpKeyIDPriv.h"
d60141 #include "pgpOptionListPriv.h"
10af5a
daaf5a
de33c8 ¤   static void
c1665d sGetKeyID(
5a1d0c ¤   PGPKeyRef¤  key,
a27494 ¤   PGPKeyID *¤ keyID )
a5bb36 {
9349e8 ¤   RingSet const *¤ringset;
9467c5 ¤
7a2468 ¤   ringset¤= pgpKeyDBRingSet (key->keyDB);
9367c5 ¤
602bcf ¤   ringKeyID8( ringset, key->key, NULL, keyID );
aeefe6 }
16af5a
5ed1b8 /* XXX Assumes that keyIDs are 8 bytes long */
19df0d ¤   static int
9937e6 compareKeyIDs(
435442 ¤   PGPKeyID const *¤   keyIDA,
c3c59e ¤   PGPKeyID const *¤   keyIDB)
8dbb36 {
c8b177 #if 0
04d312 ¤   int¤¤   ¤   ¤   i;
2d1b5b ¤   for (i = 4; i < 8; i++)
0bc7a1 ¤   {
902eb3 ¤   ¤   if (keyIDA->bytes[i] > keyIDB->bytes[i])
dfdb98 ¤   ¤   ¤   return 1;
bb9b73 ¤   ¤   else if (keyIDA->bytes[i] < keyIDB->bytes[i])
ad3fd5 ¤   ¤   ¤   return -1;
ad9371 ¤   }
fc0880 ¤   for (i = 0; i < 4; i++)
f8c7a1 ¤   {
882eb3 ¤   ¤   if (keyIDA->bytes[i] > keyIDB->bytes[i])
aedb98 ¤   ¤   ¤   return 1;
869b73 ¤   ¤   else if (keyIDA->bytes[i] < keyIDB->bytes[i])
b43fd5 ¤   ¤   ¤   return -1;
f99371 ¤   }
243e6b ¤   return 0;
e0db21 #else
6a0eb9 ¤   return( PGPCompareKeyIDs( keyIDA, keyIDB ) );
7e7454 #endif
4defe6 }
b0af5a
--2c50 000f5f3b66140100232 Page 2 of pgpKeySet.c
2fdf0d ¤   static int
d9c687 keyCompareByKeyID(void const *a, void const *b)
e1bb36 {
e2ca09 ¤   PGPKey *¤   keyA = *(PGPKey **)a;
a098a7 ¤   PGPKey *¤   keyB = *(PGPKey **)b;
b367c5 ¤
53abc2 ¤   PGPKeyID¤   rawA;
2844a6 ¤   PGPKeyID¤   rawB;
7767c5 ¤
8286a2 ¤   int¤¤   ¤   result¤ = 1;
7caf5a
bd9daf ¤   sGetKeyID( keyA, &rawA );
8f078d ¤   sGetKeyID( keyB, &rawB );
ecaf5a
2f0727 ¤   result¤ = compareKeyIDs( &rawA, &rawB);
d067c5 ¤
934c6e ¤   return( result );
94efe6 }
51af5a
dedf0d ¤   static int
abb635 keyCompareByReverseKeyID(void const *a, void const *b)
b0bb36 {
72db33 ¤   return -keyCompareByKeyID(a, b);
f6efe6 }
4caf5a
c21e7c ¤   PGPInt32
556fd7 PGPCompareUserIDStrings(char const *a, char const *b)
aebb36 {
144aac ¤   pgpAssert( IsntNull( a ) );
23e2c2 ¤   pgpAssert( IsntNull( b ) );
2067c5 ¤
6934e9 ¤   if ( IsNull( a ) || IsNull( b ) )
dcabea ¤   ¤   return( 0 );
311b52 ¤   ¤
401b52 ¤   ¤
773677 ¤   for (;;)
89c7a1 ¤   {
d7a7dd ¤   ¤   while (*a && tolower(*a) == tolower(*b))
7ef525 ¤   ¤   ¤   a++, b++;
524dc4 ¤   ¤   while (*a && !isalnum(*a))
e5dbcc ¤   ¤   ¤   a++;
e1d5c3 ¤   ¤   while (*b && !isalnum(*b))
e0c600 ¤   ¤   ¤   b++;
dbd4ea ¤   ¤   if (!*a || tolower(*a) != tolower(*b))
cbcdcb ¤   ¤   ¤   break;
0e6e5d ¤   ¤   a++;
e47391 ¤   ¤   b++;
b79371 ¤   }
17e260 ¤   return (uchar)tolower(*a) - (uchar)tolower(*b);
c7efe6 }
2aaf5a
fedf0d ¤   static int
995941 keyCompareByUserID(void const *a, void const *b)
13bb36 {
e3048f ¤   PGPKeyRef¤  ¤   keyA = *(PGPKey **)a;
3e5621 ¤   PGPKeyRef¤  ¤   keyB = *(PGPKey **)b;
2caf5a
b891fc ¤   char¤   ¤   ¤   nameA[ kPGPMaxUserIDSize ];
497c30 ¤   char¤   ¤   ¤   nameB[ kPGPMaxUserIDSize ];
deeff1 ¤   int¤¤   ¤   ¤   compareResult¤  = 0;
1eca44 ¤   PGPSize¤¤   ¤   actualLength;
bf67c5 ¤
3068cd ¤   /* if we get an error, it's OK; we'll just end up comparing the first
36df2c ¤   ¤   256 bytes */
920c45 ¤   (void)PGPGetPrimaryUserIDNameBuffer( keyA,
29ec86 ¤   ¤   sizeof( nameA ), nameA, &actualLength );
61e321 ¤   (void)PGPGetPrimaryUserIDNameBuffer( keyB,
69d534 ¤   ¤   ¤   sizeof( nameB ), nameB, &actualLength );
4287c7 ¤   ¤   ¤
063bb9 ¤   compareResult = PGPCompareUserIDStrings(nameA, nameB);
6667c5 ¤
f5804a ¤   if ( compareResult == 0 )
--5ab1 000dfd9736840100232 Page 3 of pgpKeySet.c
89cf99 ¤   ¤   compareResult¤  = keyCompareByKeyID(a, b);
ea1b52 ¤   ¤
f2eeff ¤   return compareResult;
3cefe6 }
b7af5a
e7df0d ¤   static int
d6cfa8 keyCompareByReverseUserID(void const *a, void const *b)
3bbb36 {
993c1d ¤   return -keyCompareByUserID(a, b);
33efe6 }
71af5a
25df0d ¤   static int
925964 keyCompareByValidity(void const *a, void const *b)
a2bb36 {
b8cb61 ¤   PGPKey *¤   ¤   keyA = *(PGPKey **)a;
b999cf ¤   PGPKey *¤   ¤   keyB = *(PGPKey **)b;
f4af5a
eabb4f ¤   PGPValidity¤¤   validityA;
35542b ¤   PGPValidity¤¤   validityB;
db5caa ¤   PGPError¤   ¤   result;
fb67c5 ¤
54af2b ¤   result = PGPGetPrimaryUserIDValidity(keyA, &validityA);
793775 ¤   pgpAssert(result == kPGPError_NoErr);
fe10c7 ¤   result = PGPGetPrimaryUserIDValidity(keyB, &validityB);
523775 ¤   pgpAssert(result == kPGPError_NoErr);
b5af5a
e4aca9 ¤   if (validityA < validityB)
50e102 ¤   ¤   return 1;
aed096 ¤   else if (validityA > validityB)
1f043c ¤   ¤   return -1;
7b0e24 ¤   else
ffff4d ¤   ¤   return keyCompareByKeyID(a, b);
20efe6 }
f9af5a
e8df0d ¤   static int
0b965a keyCompareByReverseValidity(void const *a, void const *b)
98bb36 {
eca968 ¤   return -keyCompareByValidity(a, b);
2cefe6 }
30af5a
fedf0d ¤   static int
db4f27 keyCompareByTrust(void const *a, void const *b)
94bb36 {
44cb61 ¤   PGPKey *¤   ¤   keyA = *(PGPKey **)a;
6999cf ¤   PGPKey *¤   ¤   keyB = *(PGPKey **)b;
b3af5a
b2b562 ¤   PGPInt32¤   ¤   trustA;
c95a06 ¤   PGPInt32¤   ¤   trustB;
475caa ¤   PGPError¤   ¤   result;
dd67c5 ¤
25cdd3 ¤   result = PGPGetKeyNumber(keyA, kPGPKeyPropTrust, &trustA);
083775 ¤   pgpAssert(result == kPGPError_NoErr);
43af53 ¤   result = PGPGetKeyNumber(keyB, kPGPKeyPropTrust, &trustB);
263775 ¤   pgpAssert(result == kPGPError_NoErr);
c3af5a
2ed174 ¤   if (trustA < trustB)
d0e102 ¤   ¤   return 1;
c09b4e ¤   else if (trustA > trustB)
42043c ¤   ¤   return -1;
a70e24 ¤   else
26ff4d ¤   ¤   return keyCompareByKeyID(a, b);
f0efe6 }
f6af5a
fadf0d ¤   static int
253f95 keyCompareByReverseTrust(void const *a, void const *b)
f8bb36 {
2e865a ¤   return -keyCompareByTrust(a, b);
abefe6 }
b6af5a
cfdf0d ¤   static int
fad38f keyCompareByEncryptKeySize(void const *a, void const *b)
dfbb36 {
--8931 000801a35f340100232 Page 4 of pgpKeySet.c
c5cb61 ¤   PGPKey *¤   ¤   keyA = *(PGPKey **)a;
ab99cf ¤   PGPKey *¤   ¤   keyB = *(PGPKey **)b;
07b833 ¤   PGPSubKey *¤¤   subKeyA = NULL;
bccc5a ¤   PGPSubKey *¤¤   subKeyB = NULL;
98af5a
acc85c ¤   PGPInt32¤   ¤   keySizeA;
192738 ¤   PGPInt32¤   ¤   keySizeB;
98fb19 ¤   PGPError¤   ¤   err;
1267c5 ¤
276674 ¤   err = pgpGetFirstSubKey(keyA, &subKeyA);
39f1e7 ¤   if ( IsntPGPError( err ) )
4744f2 ¤   ¤   err = PGPGetSubKeyNumber(subKeyA, kPGPKeyPropBits, &keySizeA);
490e24 ¤   else
38ae21 ¤   ¤   err = PGPGetKeyNumber(keyA, kPGPKeyPropBits, &keySizeA);
ef8c1a ¤   pgpAssertNoErr( err );
91af5a
c4c087 ¤   err = pgpGetFirstSubKey(keyB, &subKeyB);
8bf1e7 ¤   if ( IsntPGPError( err ) )
7df899 ¤   ¤   err = PGPGetSubKeyNumber(subKeyB, kPGPKeyPropBits, &keySizeB);
280e24 ¤   else
49124a ¤   ¤   err = PGPGetKeyNumber(keyB, kPGPKeyPropBits, &keySizeB);
a88c1a ¤   pgpAssertNoErr( err );
9267c5 ¤
b2bc37 ¤   if (keySizeA < keySizeB)
afe102 ¤   ¤   return 1;
cea608 ¤   else if (keySizeA > keySizeB)
6b043c ¤   ¤   return -1;
6aaf5a
343a18 ¤   return keyCompareByKeyID(a, b);
bdefe6 }
41af5a
82df0d ¤   static int
6a0c76 keyCompareByReverseEncryptKeySize(void const *a, void const *b)
52bb36 {
74d781 ¤   return -keyCompareByEncryptKeySize(a, b);
4aefe6 }
54af5a
fddf0d ¤   static int
8a8820 keyCompareBySigKeySize(void const *a, void const *b)
cfbb36 {
93cb61 ¤   PGPKey *¤   ¤   keyA = *(PGPKey **)a;
2699cf ¤   PGPKey *¤   ¤   keyB = *(PGPKey **)b;
c1af5a
1fc85c ¤   PGPInt32¤   ¤   keySizeA;
e22738 ¤   PGPInt32¤   ¤   keySizeB;
395caa ¤   PGPError¤   ¤   result;
1867c5 ¤
d38268 ¤   result = PGPGetKeyNumber(keyA, kPGPKeyPropBits, &keySizeA);
e43775 ¤   pgpAssert(result == kPGPError_NoErr);
9f3e03 ¤   result = PGPGetKeyNumber(keyB, kPGPKeyPropBits, &keySizeB);
733775 ¤   pgpAssert(result == kPGPError_NoErr);
23af5a
45bc37 ¤   if (keySizeA < keySizeB)
fbe102 ¤   ¤   return 1;
5fa608 ¤   else if (keySizeA > keySizeB)
58043c ¤   ¤   return -1;
5a0e24 ¤   else
17ff4d ¤   ¤   return keyCompareByKeyID(a, b);
69efe6 }
5daf5a
6ddf0d ¤   static int
8c9a69 keyCompareByReverseSigKeySize(void const *a, void const *b)
1dbb36 {
0e06b3 ¤   return -keyCompareBySigKeySize(a, b);
d2efe6 }
50af5a
cbdf0d ¤   static int
6e9b28 keyCompareByCreation(void const *a, void const *b)
94bb36 {
d6cb61 ¤   PGPKey *¤   ¤   keyA = *(PGPKey **)a;
7f99cf ¤   PGPKey *¤   ¤   keyB = *(PGPKey **)b;
80af5a
--67f1 00087f3c43840100232 Page 5 of pgpKeySet.c
9d12be ¤   PGPTime¤¤   ¤   creationA;
adfdda ¤   PGPTime¤¤   ¤   creationB;
ba5caa ¤   PGPError¤   ¤   result;
0d67c5 ¤
36fc32 ¤   result = PGPGetKeyTime(keyA, kPGPKeyPropCreation, &creationA);
813775 ¤   pgpAssert(result == kPGPError_NoErr);
811f0f ¤   result = PGPGetKeyTime(keyB, kPGPKeyPropCreation, &creationB);
153775 ¤   pgpAssert(result == kPGPError_NoErr);
94af5a
3570a7 ¤   if (creationA < creationB)
10e102 ¤   ¤   return 1;
060c98 ¤   else if (creationA > creationB)
5e043c ¤   ¤   return -1;
250e24 ¤   else
3dff4d ¤   ¤   return keyCompareByKeyID(a, b);
91efe6 }
11af5a
2edf0d ¤   static int
375416 keyCompareByReverseCreation(void const *a, void const *b)
9fbb36 {
03a455 ¤   return -keyCompareByCreation(a, b);
16efe6 }
c9af5a
d5df0d ¤   static int
36846a keyCompareByExpiration(void const *a, void const *b)
bbbb36 {
fbcb61 ¤   PGPKey *¤   ¤   keyA = *(PGPKey **)a;
dd99cf ¤   PGPKey *¤   ¤   keyB = *(PGPKey **)b;
f0af5a
3fab2d ¤   PGPTime¤¤   ¤   expirationA;
bc4449 ¤   PGPTime¤¤   ¤   expirationB;
275caa ¤   PGPError¤   ¤   result;
8067c5 ¤
2f2758 ¤   result = PGPGetKeyTime(keyA, kPGPKeyPropExpiration, &expirationA);
683775 ¤   pgpAssert(result == kPGPError_NoErr);
09a9fd ¤   result = PGPGetKeyTime(keyB, kPGPKeyPropExpiration, &expirationB);
133775 ¤   pgpAssert(result == kPGPError_NoErr);
0aaf5a
1db934 ¤   if (expirationA == expirationB)
e8ff4d ¤   ¤   return keyCompareByKeyID(a, b);
e3dae8 ¤   else if (expirationA == kPGPExpirationTime_Never)
bd043c ¤   ¤   return -1;
789da5 ¤   else if (expirationB == kPGPExpirationTime_Never)
bfe102 ¤   ¤   return 1;
c9ba57 ¤   else if (expirationA < expirationB)
7ce102 ¤   ¤   return 1;
e4557d ¤   else¤   /* expirationA > expirationB */
27043c ¤   ¤   return -1;
ffefe6 }
b2af5a
9cdf0d ¤   static int
1a9623 keyCompareByReverseExpiration(void const *a, void const *b)
0abb36 {
a7bb00 ¤   return -keyCompareByExpiration(a, b);
fdefe6 }
76af5a
a838e5 /*
043c67 ·* The compare functions must all return non-ambiguous answers (>0,<0)
c993fc ·* because the add-key functionality uses a binary search to install
1f8c21 ·* new keys. ·If things are ambiguous then the order can change if some
2854b7 ·* keys are tied under the main search. ·This is accomplished by doing
204dc1 ·* a secondary search on keyid if there is a tie on the main search
921af5 ·* field.
bd495d ·*/
49af5a
3f5e55 typedef int (*CompareFunc)(void const *, void const *);
ffaf5a
f4efbe static const CompareFunc compareFunc[] = {
66f34f ¤   NULL,
b7f34f ¤   NULL,
fc0942 ¤   keyCompareByUserID,
87881a ¤   keyCompareByReverseUserID,
--dbcf 000978e89f840100232 Page 6 of pgpKeySet.c
983c78 ¤   keyCompareByKeyID,
9444ad ¤   keyCompareByReverseKeyID,
8e41b9 ¤   keyCompareByValidity,
66c90f ¤   keyCompareByReverseValidity,
bdafe6 ¤   keyCompareByTrust,
0fd733 ¤   keyCompareByReverseTrust,
859627 ¤   keyCompareByEncryptKeySize,
6f9cda ¤   keyCompareByReverseEncryptKeySize,
8b1eb9 ¤   keyCompareBySigKeySize,
077847 ¤   keyCompareByReverseSigKeySize,
201cb8 ¤   keyCompareByCreation,
aa940e ¤   keyCompareByReverseCreation,
74e3ae ¤   keyCompareByExpiration,
a566eb ¤   keyCompareByReverseExpiration };
325c98 #if PGP_DEBUG
ade140 static PGPKeyOrdering sNumCompareFuncs = (PGPKeyOrdering)
f84eec ¤   ¤   (sizeof(compareFunc) / ·sizeof(compareFunc[0]));
7f7454 #endif
30af5a
ff1e7c ¤   PGPInt32
d30b23 PGPCompareKeys(PGPKey *a, PGPKey *b, PGPKeyOrdering order)
17bb36 {
185e68 ¤   pgpa((
303dab ¤   ¤   pgpaPGPKeyValid(a),
201866 ¤   ¤   pgpaPGPKeyValid(b),
c84d35 ¤   ¤   pgpaAssert(order > 0 && order < sNumCompareFuncs
b11dca ¤   ¤   ¤   ¤   ¤   && order != kPGPAnyOrdering)));
edaf5a
ef0b70 ¤   if ( ! ( pgpKeyIsValid( a ) && pgpKeyIsValid( b ) ) )
5eabea ¤   ¤   return( 0 );
551b52 ¤   ¤
214e84 ¤   return (*compareFunc[order])(&a, &b);
eeefe6 }
cdaf5a
7733c8 ¤   static void
a3c21e sortKeyList(PGPKeyList *list)
82bb36 {
e15e68 ¤   pgpa((
8afd91 ¤   ¤   pgpaPGPKeyListValid(list),
8914a3 ¤   ¤   pgpaAssert(list->order > 0 && list->order < sNumCompareFuncs)));
d3af5a
758c39 ¤   if (list->order != kPGPAnyOrdering)
f39942 ¤   ¤   qsort(list->keys, list->keyCount, sizeof(list->keys[0]),
52fccd ¤   ¤   ¤   ¤   compareFunc[list->order]);
4eefe6 }
caaf5a
3938e5 /*
6ad042 ·* Keep in mind that the comparison functions are not guaranteed to
a0b98f ·* be total orderings, and so even if an element of the list has a
e67d13 ·* perfect match with <key>, the index returned might not contain a
eeee8c ·* perfect match.
29495d ·*/
126d4d ¤   static long
473821 binarySearchKeyList(PGPKeyList *list, PGPKey *key)
e9bb36 {
2ee4d0 ¤   long¤   ¤   lo;
9840e5 ¤   long¤   ¤   hi;
466bf9 ¤   long¤   ¤   i;
cfd1d3 ¤   int¤¤   ¤   result;
358180 ¤   int¤¤   ¤   (*compare)(void const *, void const *);
a5af5a
a85e68 ¤   pgpa((
9cfd91 ¤   ¤   pgpaPGPKeyListValid(list),
7c4cfa ¤   ¤   pgpaPGPKeyValid(key),
fc14a3 ¤   ¤   pgpaAssert(list->order > 0 && list->order < sNumCompareFuncs)));
b0af5a
edbe39 ¤   if (list->order == kPGPAnyOrdering)
3d1c59 ¤   ¤   return list->keyCount;
62af5a
551418 ¤   compare = compareFunc[list->order];
57af5a
97b57a ¤   lo = 0;
--86ff 000e781431740100232 Page 7 of pgpKeySet.c
547aa8 ¤   hi = list->keyCount;
5aaf5a
38e7dd ¤   while (lo < hi)
c1c7a1 ¤   {
f448d1 ¤   ¤   i = (lo + hi) / 2;
5738c3 ¤   ¤   result = (*compare)(&key, &list->keys[i]);
e7c1a6 ¤   ¤   if (result > 0)
754154 ¤   ¤   ¤   lo = i + 1;
4835ac ¤   ¤   else if (result < 0)
196957 ¤   ¤   ¤   hi = i;
090e1d ¤   ¤   else
e99eb9 ¤   ¤   ¤   return i;
829371 ¤   }
987f6b ¤   return lo;
14efe6 }
23af5a
7838e5 /*
4678d6 ·* WARNING: This dependency reference counting scheme breaks down
c6fcfe ·* ··in the case of cyclical dependencies. ·For instance, if you have
a0c39a ·* ··two KeyDBs which both add keys to each other, then neither KeyDB
1fc482 ·* ··will ever be deallocated because they have each incremented the
8c52cf ·* ··other's refCount. ·We check below for cycles involving just two
0345df ·* ··KeyDBs, but cycles larger than that will cause a leak. ·This will
a79a89 ·* ··be fixed in a future implementation.
c5495d ·*/
c766dd ¤   static PGPError
b122be pgpKeyDBAddDependency(PGPKeyDB *db, PGPKeyDB *dependency)
02bb36 {
563613 ¤   PGPError¤   result¤ = kPGPError_NoErr;
9a6bf9 ¤   long¤   ¤   i;
81af5a
8b41f0 ¤   if (db == dependency)
e2b840 ¤   ¤   return kPGPError_NoErr;
107754 ¤   for (i = 0; i < db->numKeyDBDependencies; i++)
b6b615 ¤   ¤   if (db->keyDBDependencies[i] == dependency)
4933bc ¤   ¤   ¤   return kPGPError_NoErr;
ffaf5a
385c98 #if PGP_DEBUG
dd0cb6 ¤   /* Check for cycles involving two KeyDBs */
805128 ¤   for (i = 0; i < dependency->numKeyDBDependencies; i++)
966826 ¤   ¤   pgpAssert(dependency->keyDBDependencies[i] != db);
5c7454 #endif
f9af5a
323b85 ¤   if (db->numKeyDBDependencies >= db->numKeyDBDependenciesAllocated)
6dc7a1 ¤   {
0f2a25 ¤   ¤   result = pgpContextMemRealloc( pgpGetKeyDBContext( db ),
ead934 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **)&db->keyDBDependencies,
9daff3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   db->numKeyDBDependenciesAllocated * 2
38409c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   * sizeof(PGPKeyDB *),
80af16 ¤   ¤   ¤   ¤   ¤   ¤   ¤   0 );
c77673 ¤   ¤   if (IsPGPError(result))
c5847b ¤   ¤   ¤   return result;
36af5a
b8318a ¤   ¤   db->numKeyDBDependenciesAllocated *= 2;
229371 ¤   }
c611ee ¤   db->keyDBDependencies[db->numKeyDBDependencies++] = dependency;
2010e5 ¤   pgpIncKeyDBRefCount(dependency);
dd151e ¤   return kPGPError_NoErr;
2fefe6 }
a8af5a
5b33c8 ¤   static void
f74efa pgpKeyDBReleaseDependencies(PGPKeyDB *db)
9cbb36 {
bb6bf9 ¤   long¤   ¤   i;
45af5a
397754 ¤   for (i = 0; i < db->numKeyDBDependencies; i++)
acd560 ¤   ¤   pgpFreeKeyDB(db->keyDBDependencies[i]);
81880c ¤   db->numKeyDBDependencies = 0;
6aefe6 }
a1af5a
d4af5a
e7d372 /* Creates a new empty key database */
--7d5a 000cc02504240100232 Page 8 of pgpKeySet.c
f6969b ¤   PGPKeyDB *
cdc210 pgpKeyDBCreateInternal(PGPContextRef context)
32bb36 {
64a3f0 ¤   PGPKeyDB *¤ db;
1baf5a
ca46fe ¤   db = (PGPKeyDB *)pgpContextMemAlloc( context,
942daa ¤   ¤   sizeof(PGPKeyDB), kPGPMemoryMgrFlags_Clear);
19b620 ¤   if (db == NULL)
b87ed2 ¤   ¤   return NULL;
86af5a
db8659 ¤   db->priv = NULL;
35ddae ¤   db->refCount = 1;
e79956 ¤   db->firstSetInDB = NULL;
88d684 ¤   db->context = context;
38af5a
f145f6 ¤   db->numKeyDBDependenciesAllocated = 4;
82a850 ¤   db->keyDBDependencies = (PGPKeyDB **)pgpContextMemAlloc( context,
936a7b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   db->numKeyDBDependenciesAllocated
70a29c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   * sizeof(PGPKeyDB *),
79927e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0 );
5e04d3 ¤   if (db->keyDBDependencies == NULL)
6bc7a1 ¤   {
553fd4 ¤   ¤   pgpContextMemFree( context, db );
287ed2 ¤   ¤   return NULL;
289371 ¤   }
e2880c ¤   db->numKeyDBDependencies = 0;
41af5a
689fa6 ¤   memPoolInit( context, &db->keyPool);
5be869 ¤   db->numKeys = 0;
410a2a ¤   db->firstKeyInDB = NULL;
b195e1 ¤   db->firstFreeKey = NULL;
602143 ¤   db->firstFreeUserID = NULL;
b61ddd ¤   db->firstFreeCert = NULL;
5df904 ¤   db->keysByKeyID = NULL;
dcaf5a
9d65cc ¤   return db;
7fefe6 }
33af5a
22a879 /* Does any additional initialization necessary after DB is fully created */
d46d52 ¤   void
71a6fc pgpKeyDBInitInternal(PGPKeyDB *db)
b0bb36 {
cf9f90 ¤   /* Nothing for now */
d6a445 ¤   (void)db;
ceefe6 }
2caf5a
8ef8e6 /* Does the final destruction of a key database structure */
e56d52 ¤   void
d5e385 pgpKeyDBDestroyInternal(PGPKeyDB *db)
c7bb36 {
a97de3 ¤   PGPContextRef¤  context¤= db->context;
2daf5a
978679 ¤   pgpAssert( pgpContextIsValid( context ) );
6c67c5 ¤
56d12b ¤   pgpKeyDBReleaseDependencies( db );
6cffc5 ¤   pgpContextMemFree( context, db->keyDBDependencies );
a1af5a
e8c359 ¤   memPoolEmpty( &db->keyPool );
fa5dac ¤   pgpClearMemory( db, sizeof(*db) );
0fea0f ¤   pgpContextMemFree ( context, db );
82efe6 }
02af5a
914a70 ¤   static PGPKey *
ec73ae allocKey(PGPKeyDB *db)
acbb36 {
b9a8a8 ¤   PGPKey *¤   key;
b2af5a
fde35d ¤   pgpa(pgpaPGPKeyDBValid(db));
b5af5a
5e86ca ¤   if (db->firstFreeKey != NULL)
c2c7a1 ¤   {
cc9158 ¤   ¤   key = db->firstFreeKey;
--4e7c 000f69ab1f040100232 Page 9 of pgpKeySet.c
28ceeb ¤   ¤   db->firstFreeKey = key->nextKeyInDB;
d69371 ¤   }
710e24 ¤   else
18075b ¤   ¤   key = (PGPKey *)memPoolNew(&db->keyPool, PGPKey);
3167c5 ¤
677c7b ¤   if ( IsntNull( key ) )
dfc7a1 ¤   {
37849e ¤   ¤   pgpClearMemory(key, sizeof(*key));
091b52 ¤   ¤
da72a8 #if PGP_OPTIONAL_MAGICS
ba2819 ¤   ¤   key->magic¤ ¤   = kPGPKeyMagic;
ed7454 #endif
2f9371 ¤   }
4faf5a
1b8236 ¤   return key;
e4efe6 }
adaf5a
1733c8 ¤   static void
e04730 deallocKey(PGPKeyDB *db, PGPKey *key)
0bbb36 {
265e68 ¤   pgpa((
5302cf ¤   ¤   pgpaPGPKeyDBValid(db),
51ec74 ¤   ¤   pgpaAssert(db == key->keyDB)));
00af5a
7f72a8 #if PGP_OPTIONAL_MAGICS
0bd1e6 ¤   key->magic¤ ¤   = ~key->magic;
127454 #endif
75fcc4 ¤   key->nextKeyInDB = db->firstFreeKey;
c14869 ¤   db->firstFreeKey = key;
5defe6 }
15af5a
0866dd ¤   static PGPError
371c00 addKeyToList(PGPKeyList *list, PGPKey *key)
d8bb36 {
ff650b ¤   long¤   ¤   ¤   i;
e304c7 ¤   long¤   ¤   ¤   newKeyCount;
e33859 ¤   PGPKey **¤  ¤   newKeys;
3456cc ¤   PGPContextRef¤  context¤= PGPGetKeyListContext( list );
aa67c5 ¤
2f6331 ¤   pgpa(pgpaPGPKeyListValid(list));
0baf5a
2f493a ¤   i = binarySearchKeyList(list, key);
23af5a
8c127f ¤   newKeyCount = list->keyCount + 1;
5da60f ¤   newKeys = (PGPKey **)pgpContextMemAlloc( context,
722468 ¤   ¤   newKeyCount * sizeof(PGPKey *), kPGPMemoryMgrFlags_Clear );
f3abb2 ¤   if (!newKeys)
804030 ¤   ¤   return kPGPError_OutOfMemory;
aaaf5a
584286 ¤   pgpCopyMemory(list->keys, newKeys, i * sizeof(PGPKey *));
7798b5 ¤   pgpCopyMemory(list->keys + i, newKeys + i + 1,
aaf675 ¤   ¤   ¤   ¤   ¤   (list->keyCount - i) * sizeof(PGPKey *));
451fc4 ¤   pgpContextMemFree( context, list->keys);
b1af5a
95f574 ¤   list->keys = newKeys;
a3fb83 ¤   list->keyCount = newKeyCount;
b9af5a
a51674 ¤   newKeys[i] = key;
b82138 ¤   pgpKeyIterAddKey(list, i);
2667c5 ¤
04151e ¤   return kPGPError_NoErr;
cbefe6 }
f2af5a
3366dd ¤   static PGPError
42231d addKeyToLists(PGPKeyDB *db, PGPKey *key)
92bb36 {
3eb3e9 ¤   PGPKeySet *¤¤   set;
89df22 ¤   PGPKeyList *¤   list;
f35caa ¤   PGPError¤   ¤   result;
87af5a
23e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
f6af5a
--63b8 0004fb1c5ab40100232 Page 10 of pgpKeySet.c
f69d97 ¤   for (set = db->firstSetInDB; set; set = set->nextSetInDB)
b2c7a1 ¤   {
8381d5 ¤   ¤   pgpa(pgpaPGPKeySetValid(set));
3aaf5a
3092b9 ¤   ¤   if (PGPKeySetIsMember( key, set))
dfbd0e ¤   ¤   ¤   for (list = set->firstListInSet; list; list = list->nextListInSet)
5b35d0 ¤   ¤   ¤   ¤   if ((result = addKeyToList(list, key)) != kPGPError_NoErr)
1d1c2c ¤   ¤   ¤   ¤   ¤   return result;
899371 ¤   }
f4151e ¤   return kPGPError_NoErr;
7befe6 }
b0af5a
1366dd ¤   static PGPError
616bb1 removeKeyFromList(PGPKeyList *list, PGPKey *key)
49bb36 {
ff650b ¤   long¤   ¤   ¤   i;
15c642 ¤   PGPContextRef¤  cdkContext¤ = PGPGetKeyListContext( list );
5faf5a
0c6331 ¤   pgpa(pgpaPGPKeyListValid(list));
88af5a
6682c0 ¤   for (i = 0; i < list->keyCount; i++)
6c472c ¤   ¤   if (list->keys[i] == key)
abcdcb ¤   ¤   ¤   break;
7167c5 ¤
de671e ¤   if (i < list->keyCount)
4cc7a1 ¤   {
74620d ¤   ¤   pgpCopyMemory(list->keys + i + 1, list->keys + i,
68bbfa ¤   ¤   ¤   ¤   ¤   ¤   (list->keyCount - i - 1) * sizeof(PGPKey *));
21af5a
d55110 ¤   ¤   list->keyCount--;
cc1b17 ¤   ¤   /*
8c478f ¤   ¤   ·* Reducing the size of a block cannot fail, and·
4af344 ¤   ¤   ·* if it did fail we don't care anyway. ·Therefore,
3623c0 ¤   ¤   ·* we can ignore errors from the following realloc.
8b9de3 ¤   ¤   ·*/
8bd125 ¤   ¤   pgpContextMemRealloc(cdkContext, (void **)&list->keys,
922f46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·list->keyCount * sizeof(PGPKey *), 0);
c9af5a
52db39 ¤   ¤   pgpKeyIterRemoveKey(list, i);
039371 ¤   }
3367c5 ¤
88151e ¤   return kPGPError_NoErr;
4fefe6 }
09af5a
8966dd ¤   static PGPError
4b2292 removeKeyFromSets(PGPKeyDB *db, PGPKey *key)
43bb36 {
3cb3e9 ¤   PGPKeySet *¤¤   set;
08df22 ¤   PGPKeyList *¤   list;
065caa ¤   PGPError¤   ¤   result;
96af5a
76e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
25af5a
2f9d97 ¤   for (set = db->firstSetInDB; set; set = set->nextSetInDB)
75c7a1 ¤   {
bf81d5 ¤   ¤   pgpa(pgpaPGPKeySetValid(set));
c5af5a
af67e3 ¤   ¤   set->removeKey(set, key);
c6af5a
2b5029 ¤   ¤   for (list = set->firstListInSet; list; list = list->nextListInSet)
606b39 ¤   ¤   ¤   if ((result = removeKeyFromList(list, key)) != kPGPError_NoErr)
8b9053 ¤   ¤   ¤   ¤   return result;
479371 ¤   }
77151e ¤   return kPGPError_NoErr;
5aefe6 }
d2af5a
a5c744 ¤   PGPError
4d377a pgpReSortKeys(PGPKeyDB *db, RingSet *changed)
1ebb36 {
b4b3e9 ¤   PGPKeySet *¤¤   set;
35df22 ¤   PGPKeyList *¤   list;
4f284d ¤   PGPKey *¤   ¤   key;
--c661 0006560fabd40100232 Page 11 of pgpKeySet.c
139030 ¤   PGPKey **¤  ¤   movedKeys = NULL;
2d8896 ¤   long¤   ¤   ¤   numMovedKeys;
c3423a ¤   long¤   ¤   ¤   movedKeysAlloc;
35650b ¤   long¤   ¤   ¤   i;
eef23f ¤   int¤¤   ¤   ¤   (*compare)(void const *, void const *);
f383e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
1129a2 ¤   PGPContextRef¤  context¤= pgpGetKeyDBContext( db );
f3af5a
c3e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
0baf5a
f1eef9 ¤   movedKeysAlloc = 8;
bdfd20 ¤   movedKeys = (PGPKey **)pgpContextMemAlloc( context,
ff2b58 ¤   ¤   movedKeysAlloc * sizeof(PGPKey *), kPGPMemoryMgrFlags_Clear );
eb5bf9 ¤   if (!movedKeys)
dcc7a1 ¤   {
2b5e00 ¤   ¤   result = kPGPError_OutOfMemory;
74262d ¤   ¤   goto done;
539371 ¤   }
4d9d97 ¤   for (set = db->firstSetInDB; set; set = set->nextSetInDB)
82c7a1 ¤   {
8a81d5 ¤   ¤   pgpa(pgpaPGPKeySetValid(set));
beaf5a
a35029 ¤   ¤   for (list = set->firstListInSet; list; list = list->nextListInSet)
4d5b34 ¤   ¤   {
9ddd71 ¤   ¤   ¤   pgpa((
6cb22e ¤   ¤   ¤   ¤   pgpaPGPKeyListValid(list),
88dba9 ¤   ¤   ¤   ¤   pgpaAssert(list->order > 0 && list->order < sNumCompareFuncs)));
23af5a
5d1c0f ¤   ¤   ¤   if (list->order != kPGPAnyOrdering)
73f776 ¤   ¤   ¤   {
b6126f ¤   ¤   ¤   ¤   compare = compareFunc[list->order];
627ca5 ¤   ¤   ¤   ¤   numMovedKeys = 0;
b485fe ¤   ¤   ¤   ¤   for (i = 0; i < list->keyCount; i++)
473e8a ¤   ¤   ¤   ¤   ¤   if (ringSetIsMember(changed, list->keys[i]->key))
3e4859 ¤   ¤   ¤   ¤   ¤   {
55a8c7 ¤   ¤   ¤   ¤   ¤   ¤   if (numMovedKeys >= movedKeysAlloc)
e88fec ¤   ¤   ¤   ¤   ¤   ¤   {
0b8942 ¤   ¤   ¤   ¤   ¤   ¤   ¤   void *vmovedKeys;
ebaf5a
d6a519 ¤   ¤   ¤   ¤   ¤   ¤   ¤   movedKeysAlloc *= 2;
833562 ¤   ¤   ¤   ¤   ¤   ¤   ¤   vmovedKeys = movedKeys;
74b3e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   result = pgpContextMemRealloc(
78eb34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   context, &vmovedKeys,
063f8c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   movedKeysAlloc * sizeof(PGPKey *),
b9927e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0 );
ab2b9c ¤   ¤   ¤   ¤   ¤   ¤   ¤   movedKeys = (PGPKeyRef *)vmovedKeys;
afda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
17926e ¤   ¤   ¤   ¤   ¤   ¤   ¤   if ( IsPGPError( result ) )
ce28cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   goto done;
cedb3c ¤   ¤   ¤   ¤   ¤   ¤   }
fca19e ¤   ¤   ¤   ¤   ¤   ¤   key = movedKeys[numMovedKeys++] = list->keys[i];
61b291 ¤   ¤   ¤   ¤   ¤   ¤   result = removeKeyFromList(list, key);
97c7c2 ¤   ¤   ¤   ¤   ¤   ¤   if ( IsPGPError( result ) )
0c2681 ¤   ¤   ¤   ¤   ¤   ¤   ¤   goto done;
3cd8a8 ¤   ¤   ¤   ¤   ¤   ¤   i--;
1c1c89 ¤   ¤   ¤   ¤   ¤   }
81b568 ¤   ¤   ¤   ¤   for (i = 0; i < numMovedKeys; i++)
ef72c3 ¤   ¤   ¤   ¤   {
ed71fa ¤   ¤   ¤   ¤   ¤   result = addKeyToList(list, movedKeys[i]);
483a28 ¤   ¤   ¤   ¤   ¤   if (result)
356772 ¤   ¤   ¤   ¤   ¤   ¤   goto done;
102613 ¤   ¤   ¤   ¤   }
2ca3a6 ¤   ¤   ¤   }
2d0fe4 ¤   ¤   }
7a9371 ¤   }
79b38c done:
268f83 ¤   if (movedKeys != NULL)
e40396 ¤   ¤   pgpContextMemFree( context, movedKeys);
555d73 ¤   return result;
97efe6 }
04af5a
6538e5 /*
--3134 0006800c82d40100232 Page 12 of pgpKeySet.c
3f3cc2 ·* buildKeyPool can be used to either add keys or remove keys, but not both.
fccf7f ·* If you are removing keys, pass TRUE for <deleteFlag>, but if so there
5a079c ·* better not be any new keys or else it'll do the wrong thing. ·Likewise,
9b694d ·* if you pass FALSE for <deleteFlag>, there better not be any keys missing.
56495d ·*/
c5c744 ¤   PGPError
1ba818 pgpBuildKeyPool(PGPKeyDB *db, PGPBoolean deleteFlag)
0abb36 {
2422eb ¤   RingIterator *¤ iter;
94478c ¤   RingObject *¤   obj;
28284d ¤   PGPKey *¤   ¤   key;
de88c5 ¤   PGPKey **¤  ¤   prevPtr;
9783e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
36af5a
9be859 ¤   iter = ringIterCreate(pgpKeyDBRingSet(db));
ca7755 ¤   if (iter == NULL)
c64030 ¤   ¤   return kPGPError_OutOfMemory;
cc67c5 ¤
fb3237 ¤   prevPtr = &db->firstKeyInDB;
a567c5 ¤
c0a8bd ¤   while (ringIterNextObject(iter, 1) > 0)
1bc7a1 ¤   {
1521f4 ¤   ¤   obj = ringIterCurrentObject(iter, 1);
c2ec88 ¤   ¤   pgpAssertAddrValid(obj, VoidAlign);¤/* XXX use better align check */
5aaf5a
20e2b6 ¤   ¤   key = *prevPtr;
5baf5a
7db094 ¤   ¤   if (deleteFlag && key)
90a3a9 ¤   ¤   ¤   while (key->key != obj)
33f776 ¤   ¤   ¤   {
b78818 ¤   ¤   ¤   ¤   pgpa(pgpaPGPKeyValid(key));
3baf5a
07737c ¤   ¤   ¤   ¤   removeKeyFromSets(db, key);
fbaf5a
d9edde ¤   ¤   ¤   ¤   *prevPtr = key->nextKeyInDB;
8316b4 ¤   ¤   ¤   ¤   pgpFreeKey(key);
bcb98d ¤   ¤   ¤   ¤   key = *prevPtr;
6eaf5a
5137ad ¤   ¤   ¤   ¤   pgpAssert(db->numKeys > 0);
2fc00e ¤   ¤   ¤   ¤   db->numKeys--;
fba3a6 ¤   ¤   ¤   }
75af5a
ea875c ¤   ¤   if ((!key || key->key != obj) && !deleteFlag)
465b34 ¤   ¤   {
4582da ¤   ¤   ¤   key = allocKey(db);
5bb271 ¤   ¤   ¤   if (key == NULL)
29f776 ¤   ¤   ¤   {
f1ce36 ¤   ¤   ¤   ¤   result = kPGPError_OutOfMemory;
0af622 ¤   ¤   ¤   ¤   break;
b6a3a6 ¤   ¤   ¤   }
b6af5a
843746 ¤   ¤   ¤   key->refCount = 0;
1d1754 ¤   ¤   ¤   key->keyDB = db;
f358df ¤   ¤   ¤   key->key = obj;
56821e ¤   ¤   ¤   key->userVal = 0;
e404f8 ¤   ¤   ¤   key->subKeys.next = &key->subKeys;
6f22df ¤   ¤   ¤   key->subKeys.prev = key->subKeys.next;
bed931 ¤   ¤   ¤   key->userIDs.next = &key->userIDs;
9a6aea ¤   ¤   ¤   key->userIDs.prev = key->userIDs.next;
0433d7 ¤   ¤   ¤   key->nextKeyInDB = *prevPtr;
5caeff ¤   ¤   ¤   pgpIncKeyRefCount (key);
c16bfc ¤   ¤   ¤   *prevPtr = key;
83af5a
a94965 ¤   ¤   ¤   db->numKeys++;
41af5a
879d23 ¤   ¤   ¤   addKeyToLists(db, key);
100fe4 ¤   ¤   }
a4a819 ¤   ¤   prevPtr = &key->nextKeyInDB;
469371 ¤   }
e8af5a
75fdbc ¤   /* ·Reached end of RingSet. ·If we're in delete mode, there
6813dd ¤   ¤   may still be trailing PGPKey objects that need to be
--c298 00078c432ae40100232 Page 13 of pgpKeySet.c
fa3f1e ¤   ¤   freed. */
db67c5 ¤
fcd5a9 ¤   if (deleteFlag) {
dbcd8d ¤   ····key = *prevPtr;
fffa6d ¤   ¤   while (key != NULL) {
b64dd2 ¤   ¤   ····pgpa(pgpaPGPKeyValid(key));
bdfb1a ¤   ¤   ¤   removeKeyFromSets(db, key);
c3eb66 ¤   ¤   ¤   *prevPtr = key->nextKeyInDB;
f7ade2 ¤   ¤   ¤   pgpFreeKey(key);
9c14d3 ¤   ¤   ¤   key = *prevPtr;
1cbfcb ¤   ¤   ¤   pgpAssert(db->numKeys > 0);
69d426 ¤   ¤   ¤   db->numKeys--;
970fe4 ¤   ¤   }
2a9371 ¤   }
09af5a
c0d36a ¤   *prevPtr = NULL;
f91d89 ¤   ringIterDestroy(iter);
42af5a
615d73 ¤   return result;
97efe6 }
c4af5a
4a6d52 ¤   void
e9a99a pgpIncKeyDBRefCount(PGPKeyDB *db)
46bb36 {
bae35d ¤   pgpa(pgpaPGPKeyDBValid(db));
4faf5a
a0cbf3 ¤   db->refCount++;
f9efe6 }
70af5a
b46d52 ¤   void
3c01a6 pgpFreeKeyDB(PGPKeyDB *db)
4fbb36 {
a8e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
81af5a
cf56b0 ¤   db->refCount--;
99722c ¤   if (db->refCount <= 0)
65c7a1 ¤   {
21429f ¤   ¤   if (db->keysByKeyID != NULL)
915b34 ¤   ¤   {
d87aad ¤   ¤   ¤   /*
53d9fe ¤   ¤   ¤   ·* Move the refCount up by 2 while we destroy the keyList,
d3cf33 ¤   ¤   ¤   ·* so when pgpFreeKeyDB is called from PGPFreeKeySet from
048e40 ¤   ¤   ¤   ·* PGPFreeKeyList below, it does nothing but decrement the
d0f9a0 ¤   ¤   ¤   ·* refCount. ·Unfortunately this is more of a hack than I'd
d68b18 ¤   ¤   ¤   ·* like. ·refCounts don't work all that well with cycles.
058753 ¤   ¤   ¤   ·*/
646b3a ¤   ¤   ¤   db->refCount += 2;
e39661 ¤   ¤   ¤   PGPFreeKeyList(db->keysByKeyID);
e2da21 ¤   ¤   ¤   db->refCount--;
3c0fe4 ¤   ¤   }
fb4eb7 ¤   ¤   (*db->destroy)(db);
61a255 ¤   ¤   pgpKeyDBDestroyInternal (db);
f19371 ¤   }
e4efe6 }
14af5a
3116ea ¤   PGPBoolean
3d7168 PGPKeySetIsMember(PGPKey *key, PGPKeySet *set)
36bb36 {
d35e68 ¤   pgpa((
c8e8b8 ¤   ¤   pgpaPGPKeySetValid(set),
267648 ¤   ¤   pgpaPGPKeyValid(key)));
141b52 ¤   ¤
00b88a ¤   if ( ! ( pgpKeySetIsValid( set ) && pgpKeyIsValid( key ) ) )
43c7a1 ¤   {
22e20d ¤   ¤   return( FALSE );
fa9371 ¤   }
d867c5 ¤
7e4adf ¤   return set->isMember(set, key->key);
17efe6 }
03af5a
fbc744 ¤   PGPError
7831ad PGPUnionKeySets(PGPKeySetRef set1, PGPKeySetRef set2, PGPKeySetRef *newSet)
--7607 00099a9d93c40100232 Page 14 of pgpKeySet.c
2cbb36 {
cd26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
68af5a
ab5808 ¤   PGPValidatePtr( newSet );
d6a911 ¤   *newSet¤= NULL;
27ebb8 ¤   PGPValidateKeySet( set1 );
52f674 ¤   PGPValidateKeySet( set2 );
f4a386 ¤   if (set1->keyDB != set2->keyDB)
615657 ¤   ¤   return kPGPError_KeyDBMismatch;
56af5a
ca0f6b ¤   if (set1->makeUnion == set2->makeUnion && IsntNull(set1->makeUnion))
8fe817 ¤   ¤   err = set1->makeUnion(set1, set2, newSet);
720e24 ¤   else
3c6163 ¤   ¤   err = pgpGenericUnionOfKeySets(set1, set2, newSet);
cfaf5a
335ea8 ¤   return err;
e7efe6 }
84af5a
f933c8 ¤   static void
a25a0f defaultRemoveKeyFromKeySet(
077a49 ¤   PGPKeySetRef¤   set,
f8b323 ¤   PGPKeyRef¤  ¤   key)
7fbb36 {
cfb928 ¤   /* Do nothing */
35af5a
7b1dc7 ¤   (void)set;¤ ¤   /* Avoid warnings */
2d9b3e ¤   (void)key;
c3efe6 }
10af5a
47c744 ¤   PGPError
d7c9b1 pgpNewKeySetInternal(
fc1ea5 ¤   PGPKeyDBRef¤¤   db,
13388a ¤   PGPKeySetRef *¤ newSet)
53bb36 {
92b3e9 ¤   PGPKeySet *¤¤   set;
527e74 ¤   PGPContextRef¤  context¤= pgpGetKeyDBContext(db);
1baf5a
04e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
6faf5a
8a5049 ¤   *newSet = NULL;¤¤   /* In case there's an error */
99af5a
8965f3 ¤   set = (PGPKeySet *)pgpContextMemAlloc(context,
326289 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPKeySet), kPGPMemoryMgrFlags_Clear);
c5317d ¤   if (IsNull(set))
b54030 ¤   ¤   return kPGPError_OutOfMemory;
b0af5a
5f38b5 ¤   pgpIncKeyDBRefCount(db);
21af5a
748d41 ¤   set->priv¤  ¤   ¤   = NULL;
db50fc ¤   set->refCount¤  ¤   = 1;
3042c4 ¤   set->keyDB¤ ¤   ¤   = db;
8cdf2b ¤   set->firstListInSet = NULL;
7975a4 ¤   set->magic¤ ¤   ¤   = kPGPKeySetMagic;
07af5a
221ccb ¤   set->prevSetInDB = NULL;
447e1f ¤   set->nextSetInDB = db->firstSetInDB;
26de3b ¤   if (set->nextSetInDB)
7e9c76 ¤   ¤   set->nextSetInDB->prevSetInDB = set;·
e98eba ¤   db->firstSetInDB = set;
d5af5a
8965b9 ¤   set->removeKey = defaultRemoveKeyFromKeySet;
0faf5a
239fa7 ¤   *newSet = set;
56151e ¤   return kPGPError_NoErr;
70efe6 }
32af5a
216c2c ¤   static PGPBoolean
1a1977 rootSetIsMember(PGPKeySet *set, RingObject *obj)
8abb36 {
5e5e68 ¤   pgpa((
82e8b8 ¤   ¤   pgpaPGPKeySetValid(set),
99a607 ¤   ¤   pgpaAddrValid(obj, VoidAlign)));¤   /* XXX use better align check */
--f4e4 0000f9de78740100232 Page 15 of pgpKeySet.c
e0af5a
8ddf1c ¤   return ringSetIsMember(pgpKeyDBRingSet(set->keyDB), obj);
c9efe6 }
9aaf5a
3466dd ¤   static PGPError
1868a4 rootSetMakeUnion(PGPKeySetRef set1, PGPKeySetRef set2, PGPKeySetRef *newSet)
2fbb36 {
b75ab7 ¤   (void)set2;¤/* Avoid warning */
7daf5a
f9f9b6 ¤   PGPIncKeySetRefCount(set1);
5fa270 ¤   *newSet = set1;
a5151e ¤   return kPGPError_NoErr;
18efe6 }
e3af5a
5d33c8 ¤   static void
c5081b rootSetDestroy(PGPKeySet *set)
9bbb36 {
6df5b8 ¤   (void)set;¤ /* Avoid warning */
9befe6 }
21af5a
6d7c09 ¤   PGPKeySet *
dd0109 pgpKeyDBRootSet(
0d8a16 ¤   PGPKeyDB *¤ ¤   db)
55bb36 {
8cb3e9 ¤   PGPKeySet *¤¤   set;
14af5a
ec9674 ¤   pgpNewKeySetInternal(db, &set);
8317c6 ¤   if (IsntNull(set))
5fc7a1 ¤   {
53096e ¤   ¤   set->isMember = rootSetIsMember;
9e439a ¤   ¤   set->makeUnion = rootSetMakeUnion;
f06759 ¤   ¤   set->destroy = rootSetDestroy;
3d9371 ¤   }
529329 ¤   return set;
f6efe6 }
19af5a
0c33b4 ¤   RingSet const *
48a61f pgpKeyDBRingSet(PGPKeyDB *db)
cebb36 {
ffe35d ¤   pgpa(pgpaPGPKeyDBValid(db));
bdaf5a
5a4562 ¤   return (*db->getRingSet)(db);
18efe6 }
1faf5a
a038e5 /*
40d439 ·* Return a ringset holding the keys (and subsidiary objects) in the
6d6772 ·* corresponding keyset. ·This differs from pgpKeyDBRingSet in that it
c153f9 ·* only includes the keys in the keyset, not all those in the keydb.
434db6 ·* The returned ringset must be deleted after being used. ·If freezeit
ecc6f8 ·* is true, the ringset is returned frozen, else it is returned
de26d5 ·* mutable.
b6495d ·*/
53c744 ¤   PGPError
581531 pgpKeySetRingSet(PGPKeySet *keys, PGPBoolean freezeit, RingSet const **ringset)
2bbb36 {
0aae18 ¤   PGPKeyList¤ ¤   ¤   *list = NULL;
812e79 ¤   PGPKeyIter¤ ¤   ¤   *iter = NULL;
2c0564 ¤   PGPKey¤ ¤   ¤   ¤   *key;
da5e04 ¤   RingSet const¤  ¤   *kdbSet;
e2798c ¤   RingSet¤¤   ¤   ¤   *rset = NULL;
9b05a0 ¤   PGPError¤   ¤   ¤   ·err = kPGPError_NoErr;
81af5a
d4280e ¤   kdbSet = pgpKeyDBRingSet( keys->keyDB );
4b0a90 ¤   rset = ringSetCreate( ringSetPool( kdbSet ) );
47209f ¤   if( IsNull( rset ) ) {
aacb3b ¤   ¤   err = ringSetError( kdbSet )->error;
cd97ed ¤   ¤   goto error;
489371 ¤   }
55af5a
a377ed ¤   if (keys->isMember == rootSetIsMember) {
46e8b3 ¤   ¤   /* In simple case, can just make a copy of root set */
0fd7bd ¤   ¤   ringSetAddSet( rset, kdbSet );
--2efc 000995395b940100232 Page 16 of pgpKeySet.c
faf037 ¤   } else {
5989c2 ¤   ¤   /* Else iterate over all keys in set */
3a4289 ¤   ¤   if( IsPGPError( err = PGPOrderKeySet( keys, kPGPAnyOrdering,
d008ae ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&list ) ) )
b7ed19 ¤   ¤   ¤   goto error;
3ea29f ¤   ¤   if( IsPGPError( err = PGPNewKeyIter( list, &iter ) ) )
e2ed19 ¤   ¤   ¤   goto error;
cc7f4c ¤   ¤   while( IsntPGPError( PGPKeyIterNext( iter, &key ) ) ) {
08e27f ¤   ¤   ¤   RingObject *keyobj = key->key;
0c3676 ¤   ¤   ¤   pgpAssert( IsntNull( keyobj ) );
8a4c22 ¤   ¤   ¤   ringSetAddObjectChildren( rset, kdbSet, keyobj );
120fe4 ¤   ¤   }
85bc1b ¤   ¤   PGPFreeKeyIter( iter );
b5dfbe ¤   ¤   PGPFreeKeyList( list );
599371 ¤   }
161744 ¤   if( freezeit )
db1653 ¤   ¤   ringSetFreeze( rset );
616cfd ¤   *ringset = (RingSet const *) rset;
84151e ¤   return kPGPError_NoErr;
97af5a
d760ff error:
2bae80 ¤   if( IsntNull( iter ) )
2dbc1b ¤   ¤   PGPFreeKeyIter( iter );
61c8c3 ¤   if( IsntNull( list ) )
ecdfbe ¤   ¤   PGPFreeKeyList( list );
5f7c2d ¤   if( IsntNull( rset ) )
c67d1f ¤   ¤   ringSetDestroy( rset );
945ea8 ¤   return err;
c8efe6 }
17af5a
4b16ea ¤   PGPBoolean
3fd419 pgpKeyDBIsMutable(PGPKeyDB *db)
f5bb36 {
57e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
46af5a
2fea1c ¤   return (*db->isMutable)(db);
cfefe6 }
d9af5a
2c16ea ¤   PGPBoolean
a5344d pgpKeyDBIsDirty(PGPKeyDB *db)
6ebb36 {
c4e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
e4af5a
6fe400 ¤   return (*db->isDirty)(db);
71efe6 }
dcaf5a
9e38e5 /*
588387 ·* Call this when we have made a change to the keys in the changedkeys set,
718efb ·* to force those keys to be resorted in all lists depending on the db
52495d ·*/
3ec744 ¤   PGPError
b910a5 pgpKeyDBChanged(PGPKeyDB *db, RingSet *changedkeys)
32bb36 {
c10214 ¤   return db->changed(db, changedkeys);
57efe6 }
bfaf5a
a3c744 ¤   PGPError
515f80 pgpCommitKeyDB(PGPKeyDB *db)
f8bb36 {
ee544e ¤   RingSet const *¤rset;
1c1765 ¤   PGPError¤   ¤   error;
7d7566 ¤   int¤¤   ¤   ¤   count;
77af5a
f6e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
4aaf5a
28c6bb ¤   if ( !pgpKeyDBIsMutable( db ) )
3a7c85 ¤   ¤   return kPGPError_ItemIsReadOnly;
f0af5a
2bd8af ¤   /*
03eb59 ¤   ·* Don't do the automatic sigcheck and trust propagation on in-memory
8953a9 ¤   ·* db's. ·This is not only unnecessary, but it clears the axiomatic bit
99f589 ¤   ·* on any keys which are in the memory set as public keys but not as
--69e1 0007cb4f57c40100232 Page 17 of pgpKeySet.c
fd73d1 ¤   ·* secret keys.
0ea4e3 ¤   ·*/
42fd26 ¤   if( db->typeMagic != PGPKDBMEMMAGIC )
70c7a1 ¤   {
b31fa1 ¤   ¤   rset = pgpKeyDBRingSet (db);
284a81 ¤   ¤   if (!rset)
3b7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
83c32f ¤   ¤   /* XXX This can take a while, need a progress bar? */
21c459 ¤   ¤   error = ringPoolCheck (rset, rset, FALSE, FALSE, 0, 0);
f7e3c2 ¤   ¤   if (error)
de3b5b ¤   ¤   ¤   return error;
1ff4ff ¤   ¤   count = ringMnt (rset, 0, PGPGetTime());
e59efb ¤   ¤   if (count < 0)
912012 ¤   ¤   ¤   return (PGPError) count;
c99371 ¤   }
b22a85 ¤   error = db->commit(db);
150161 ¤   if (error)
77fcee ¤   ¤   return error;
ec9ed9 ¤   pgpKeyDBReleaseDependencies(db);
cb151e ¤   return kPGPError_NoErr;
55efe6 }
ccaf5a
7baf5a
fac744 ¤   PGPError
6cca0e pgpPropagateTrustKeyDB(PGPKeyDB *db)
40bb36 {
aff84c ¤   RingSet const ··*rset;
4bd1d3 ¤   int¤¤   ¤   result;
2826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
25af5a
d7e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
28af5a
cb22c9 ¤   rset = pgpKeyDBRingSet (db);
950279 ¤   result¤ = ringMnt (rset, 0, PGPGetTime());
c967c5 ¤
ee5a52 ¤   /* this is obviously extremely ugly rngMnt() should be fixed */
53fcc9 ¤   if ( result < 0 )
b0c1ec ¤   ¤   err¤= (PGPError)result;
a00e24 ¤   else
77d87c ¤   ¤   err¤= kPGPError_NoErr;
1c1b52 ¤   ¤
eddeb7 ¤   return( err );
f5efe6 }
d0af5a
7eaf5a
f1299a /* Callback for checking function */
7ec471 typedef struct PGPKeyCheckState {
2f429f ¤   PGPContextRef¤  ¤   ¤   context;
4c9507 ¤   PGPEventHandlerProcPtr¤ progress;
927b2d ¤   PGPUserValue¤   ¤   ¤   userValue;
593584 ¤   PGPUInt32¤  ¤   ¤   ¤   total;
03c5da ¤   PGPUInt32¤  ¤   ¤   ¤   sofar;
47109f } PGPKeyCheckState;
b1af5a
1866dd ¤   static PGPError
02e72e checkKeyDBCallback(void *arg, RingIterator *iter, int status)
27bb36 {
1e146b ¤   PGPKeyCheckState¤   ¤   *s = (PGPKeyCheckState *)arg;
403cbe ¤   PGPError¤   ¤   ¤   ¤   err = kPGPError_NoErr;
b71592 ¤   PGPOptionListRef¤   ¤   newOptionList = NULL;
74af5a
9a3af2 ¤   (void) iter;
6ade9d ¤   (void) status;
83af5a
810592 ¤   if (IsntNull (s->progress)) {
ea888e ¤   ¤   err = pgpEventNull (s->context, &newOptionList,
a3c7c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   s->progress, s->userValue, ++s->sofar, s->total);
54259e ¤   ¤   if (IsntNull (newOptionList))
436dc7 ¤   ¤   ¤   pgpFreeOptionList (newOptionList);
379371 ¤   }
c75ea8 ¤   return err;
7cefe6 }
--0310 0000f929fb840100232 Page 18 of pgpKeySet.c
2a67c5 ¤
c4af5a
f9c744 ¤   PGPError
139069 pgpCheckKeyDB (
c37e52 ¤   PGPKeyDB¤   ¤   ¤   ¤   *dbToCheck,
e6c712 ¤   PGPKeyDB¤   ¤   ¤   ¤   *dbSigning,
ea5975 ¤   PGPBoolean¤ ¤   ¤   ¤   checkAll,
874d9e ¤   PGPEventHandlerProcPtr¤ progress,
3fcaf8 ¤   PGPUserValue¤   ¤   ¤   userValue
1027e6 ¤   )
b8bb36 {
f9e389 ¤   RingSet const¤  ¤   ¤   *rsetToCheck,
e3ae90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *rsetSigning;
2075b8 ¤   PGPKeyCheckState¤   ¤   ·s;
3daf5a
57e679 ¤   pgpa(pgpaPGPKeyDBValid(dbToCheck));
da8855 ¤   pgpa(pgpaPGPKeyDBValid(dbSigning));
6f67c5 ¤
2affe8 ¤   rsetToCheck = pgpKeyDBRingSet (dbToCheck);
cf9afc ¤   rsetSigning = pgpKeyDBRingSet (dbSigning);
b4596f ¤   if (!rsetToCheck || !rsetSigning)
dc4030 ¤   ¤   return kPGPError_OutOfMemory;
aa3add ¤   pgpClearMemory (&s, sizeof(s));
9844ab ¤   if( IsntNull( progress ) ) {
bb4cc4 ¤   ¤   s.context = dbToCheck->context;
e0f796 ¤   ¤   s.progress = progress;
e8002f ¤   ¤   s.userValue = userValue;
cab852 ¤   ¤   s.sofar = 0;
8a8ae6 ¤   ¤   s.total = ringPoolCheckCount(rsetToCheck, rsetSigning, checkAll,
3cb0d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·FALSE);
399371 ¤   }
f48f8d ¤   return ringPoolCheck (rsetToCheck, rsetSigning, checkAll, FALSE,
e667a1 ¤   ¤   ¤   ¤   ¤   ¤   ··checkKeyDBCallback, &s);
99efe6 }
10af5a
aeaf5a
3cc744 ¤   PGPError
008dd4 pgpRevertKeyDB(PGPKeyDB *db)
3dbb36 {
abe35d ¤   pgpa(pgpaPGPKeyDBValid(db));
a2af5a
a10fab ¤   return db->revert(db);
5eefe6 }
32af5a
dac744 ¤   PGPError
4340bb pgpReloadKeyDB(PGPKeyDB *db)
e4bb36 {
ece35d ¤   pgpa(pgpaPGPKeyDBValid(db));
23af5a
016ccf ¤   return db->reload(db);
e9efe6 }
78af5a
b3c744 ¤   PGPError
260fbb PGPCommitKeyRingChanges(PGPKeySet *keys)
60bb36 {
db7f09 ¤   PGPValidateKeySet( keys );
45af5a
36d994 ¤   return pgpCommitKeyDB(keys->keyDB);
baefe6 }
d5af5a
d7af5a
7dc744 ¤   PGPError
ee32c4 PGPPropagateTrust(PGPKeySet *keys)
5fbb36 {
087f09 ¤   PGPValidateKeySet( keys );
d7af5a
4ac3ac ¤   return pgpPropagateTrustKeyDB(keys->keyDB);
2aefe6 }
b9af5a
62c744 ¤   PGPError
b4cd0c PGPRevertKeyRingChanges(PGPKeySet *keys)
0fbb36 {
--2c67 00028916a5740100232 Page 19 of pgpKeySet.c
eb7f09 ¤   PGPValidateKeySet( keys );
31af5a
e60bc0 ¤   return pgpRevertKeyDB(keys->keyDB);
f0efe6 }
b3af5a
797251 /* Check all sigs in keyset */
6dc744 ¤   PGPError
3791e8 PGPCheckKeyRingSigs(
54856d ¤   PGPKeySetRef¤   ¤   ¤   keysToCheck,
2a3c2d ¤   PGPKeySetRef¤   ¤   ¤   keysSigning,
715975 ¤   PGPBoolean¤ ¤   ¤   ¤   checkAll,
f74d9e ¤   PGPEventHandlerProcPtr¤ progress,
84caf8 ¤   PGPUserValue¤   ¤   ¤   userValue
2c27e6 ¤   )
eebb36 {
0d74ba ¤   RingSet const¤  ¤   ¤   *rsetToCheck = NULL,
2079ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   *rsetSigning = NULL;
5a75b8 ¤   PGPKeyCheckState¤   ¤   ·s;
de6ea7 ¤   PGPError¤   ¤   ¤   ¤   ·err = kPGPError_NoErr;
cfaf5a
de9d7e ¤   PGPValidateKeySet( keysToCheck );
0af352 ¤   PGPValidateKeySet( keysSigning );
2a67c5 ¤
23a736 ¤   err = pgpKeySetRingSet (keysToCheck, TRUE, &rsetToCheck);
387f7d ¤   if( IsPGPError( err ) )
4397ed ¤   ¤   goto error;
5d20ac ¤   err = pgpKeySetRingSet (keysSigning, TRUE, &rsetSigning);
9c7f7d ¤   if( IsPGPError( err ) )
0497ed ¤   ¤   goto error;
e7af5a
ff3add ¤   pgpClearMemory (&s, sizeof(s));
0344ab ¤   if( IsntNull( progress ) ) {
8c35f1 ¤   ¤   s.context = PGPGetKeySetContext( keysToCheck );
09f796 ¤   ¤   s.progress = progress;
9a002f ¤   ¤   s.userValue = userValue;
9db852 ¤   ¤   s.sofar = 0;
598ae6 ¤   ¤   s.total = ringPoolCheckCount(rsetToCheck, rsetSigning, checkAll,
70b0d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·FALSE);
9a9371 ¤   }
4e1fbd ¤   err = ringPoolCheck (rsetToCheck, rsetSigning, checkAll, FALSE,
f067a1 ¤   ¤   ¤   ¤   ¤   ¤   ··checkKeyDBCallback, &s);
acaf5a
1e60ff error:
e5af5a
c3452b ¤   if( IsntNull( rsetToCheck ) )
48782c ¤   ¤   ringSetDestroy( (RingSet *)rsetToCheck );
0aae2b ¤   if( IsntNull( rsetSigning ) )
e01600 ¤   ¤   ringSetDestroy( (RingSet *)rsetSigning );
385ea8 ¤   return err;
acefe6 }
1eaf5a
4dc744 ¤   PGPError
5de152 PGPReloadKeyRings(PGPKeySetRef keys)
eebb36 {
5c7f09 ¤   PGPValidateKeySet( keys );
7faf5a
53c6af ¤   return pgpReloadKeyDB(keys->keyDB);
f4efe6 }
00af5a
f6c744 ¤   PGPError
7d1405 PGPIncKeySetRefCount(PGPKeySetRef keys)
42bb36 {
607f09 ¤   PGPValidateKeySet( keys );
96af5a
1660e8 ¤   keys->refCount++;
d467c5 ¤
422d68 ¤   return( kPGPError_NoErr );
20efe6 }
a8af5a
23c744 ¤   PGPError
7a0657 PGPNewKeySet(
28520e ¤   PGPContextRef¤  context,
--620e 000da13a62c40100232 Page 20 of pgpKeySet.c
d7a3e2 ¤   PGPKeySetRef ··*newSetOut)
ccbb36 {
46f391 ¤   PGPKeyDB¤   ···*memdb;
e867c5 ¤
b08d47 ¤   PGPValidatePtr( newSetOut );
f53fc8 ¤   *newSetOut¤ = NULL;
f6f3ca ¤   PGPValidateContext( context );
6567c5 ¤
214b0c ¤   memdb = pgpKeyDBCreate(context);
559c88 ¤   if ( IsNull( memdb ) )
3e4030 ¤   ¤   return kPGPError_OutOfMemory;
af1b52 ¤   ¤
c0562c ¤   *newSetOut = pgpKeyDBRootSet (memdb);
4f0855 ¤   pgpFreeKeyDB( memdb );
d867c5 ¤
35151e ¤   return kPGPError_NoErr;
6cefe6 }
4baf5a
39af5a
a2ccac /* Add all the objects in the second key set into the first. */
bec744 ¤   PGPError
d89e3a PGPAddKeys (
1f1da2 ¤   PGPKeySetRef¤   keysToAdd,
5fdc1d ¤   PGPKeySetRef¤   set )
c5bb36 {
ade9ab ¤   PGPKeyList¤ ···*kladd = NULL;
ae51c3 ¤   PGPKeyIter¤ ···*kiadd = NULL;
b624b7 ¤   RingSet¤¤   ···*tmpset = NULL;
663bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
b9af5a
a71309 ¤   PGPValidateKeySet( set );
87373e ¤   PGPValidateKeySet( keysToAdd );
6faf5a
d967ad ¤   if ( !PGPKeySetIsMutable( set ) )
81c7a1 ¤   {
657cfe ¤   ¤   err = kPGPError_ItemIsReadOnly;
d697ed ¤   ¤   goto error;
e49371 ¤   }
64af5a
1567f9 ¤   err = pgpKeyDBAddDependency(set->keyDB, keysToAdd->keyDB);
71054e ¤   if ( IsPGPError( err ) )
c197ed ¤   ¤   goto error;
4367c5 ¤
f96655 ¤   err = pgpKeySetRingSet (keysToAdd, FALSE, (RingSet const **)&tmpset);
ff7f7d ¤   if( IsPGPError( err ) )
1ec7a1 ¤   {
d4bce1 ¤   ¤   err = kPGPError_OutOfMemory;
7797ed ¤   ¤   goto error;
619371 ¤   }
8d229d ¤   err = pgpAddObjects (set->keyDB, tmpset);
01054e ¤   if ( IsPGPError( err ) )
db97ed ¤   ¤   goto error;
deaf5a
9d60ff error:
90814f ¤   if (tmpset)
ca22bb ¤   ¤   ringSetDestroy (tmpset);
ffd200 ¤   if (kiadd)
17c13e ¤   ¤   PGPFreeKeyIter (kiadd);
28c687 ¤   if (kladd)
863f0d ¤   ¤   PGPFreeKeyList (kladd);
311b52 ¤   ¤
855ea8 ¤   return err;
42efe6 }
3eaf5a
da60f6 /* Remove all objects in the second set from the first */
38c744 ¤   PGPError
529912 PGPRemoveKeys (
6cfc2e ¤   PGPKeySetRef¤   keysToRemove,
b2dc1d ¤   PGPKeySetRef¤   set )
f2bb36 {
176b02 ¤   PGPKeyList¤ ···*klrem = NULL;
dad36a ¤   PGPKeyIter¤ ···*kirem = NULL;
--6432 0009e3b69e840100232 Page 21 of pgpKeySet.c
8d9d64 ¤   PGPKey¤ ¤   ···*key = NULL;
09e0a0 ¤   RingObject¤ ···*keyobj = NULL;
ba3bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
eeaf5a
b71309 ¤   PGPValidateKeySet( set );
23ac92 ¤   PGPValidateKeySet( keysToRemove );
7767c5 ¤
fe67ad ¤   if ( !PGPKeySetIsMutable( set ) )
80c7a1 ¤   {
207cfe ¤   ¤   err = kPGPError_ItemIsReadOnly;
9b97ed ¤   ¤   goto error;
099371 ¤   }
f8af5a
652e97 ¤   err¤= PGPOrderKeySet (keysToRemove, kPGPAnyOrdering, &klrem );
60054e ¤   if ( IsPGPError( err ) )
e397ed ¤   ¤   goto error;
4faf5a
9d707f ¤   err = PGPNewKeyIter (klrem, &kirem );
968e33 ¤   if ( IsPGPError( err ) )·
2097ed ¤   ¤   goto error;
0aaf5a
53f87d ¤   while ((err = PGPKeyIterNext( kirem, &key )) == kPGPError_NoErr )
abc7a1 ¤   {
d5da52 ¤   ¤   keyobj = key->key;
1566d6 ¤   ¤   err = pgpRemoveObject (set->keyDB, keyobj);
35be18 ¤   ¤   if ( IsPGPError( err ) )
8ded19 ¤   ¤   ¤   goto error;
889371 ¤   }
82766b ¤   pgpAssert( err == kPGPError_EndOfIteration );
55465f ¤   if ( err == kPGPError_EndOfIteration )
7ed87c ¤   ¤   err¤= kPGPError_NoErr;
7daf5a
c560ff error:
1ffb29 ¤   if (kirem)
087dd4 ¤   ¤   PGPFreeKeyIter (kirem);
40efae ¤   if (klrem)
fd83e7 ¤   ¤   PGPFreeKeyList (klrem);
ea5ea8 ¤   return err;
7cefe6 }
36af5a
e6af5a
5bc744 ¤   PGPError
836b47 PGPFreeKeySet(PGPKeySet *keys)
48bb36 {
c5d04d ¤   PGPContextRef¤  context¤= NULL;
1567c5 ¤
e57f09 ¤   PGPValidateKeySet( keys );
7544ed ¤   context¤= PGPGetKeySetContext( keys );
94f3ca ¤   PGPValidateContext( context );
0d67c5 ¤
9caf5a
88fdab ¤   keys->refCount--;
82df4c ¤   if (keys->refCount <= 0)
adc7a1 ¤   {
8f1ce5 ¤   ¤   (*keys->destroy)(keys);
3ff4b0 ¤   ¤   keys->magic¤= ~keys->magic;¤/* mark as invalid */
bb1b52 ¤   ¤
50961b ¤   ¤   if (keys->prevSetInDB)
2d08cc ¤   ¤   ¤   keys->prevSetInDB->nextSetInDB = keys->nextSetInDB;
6e0e1d ¤   ¤   else
ed9860 ¤   ¤   ¤   keys->keyDB->firstSetInDB = keys->nextSetInDB;
2ef568 ¤   ¤   if (keys->nextSetInDB)
f07015 ¤   ¤   ¤   keys->nextSetInDB->prevSetInDB = keys->prevSetInDB;
27af5a
447721 ¤   ¤   pgpAssert(keys->firstListInSet == NULL);
14af5a
ecd9a8 ¤   ¤   pgpFreeKeyDB (keys->keyDB);
de8800 ¤   ¤   pgpContextMemFree( context, keys);
b69371 ¤   }
1b67c5 ¤
f92d68 ¤   return( kPGPError_NoErr );
9eefe6 }
--fa2a 000f324dd6a40100232 Page 22 of pgpKeySet.c
e0af5a
4516ea ¤   PGPBoolean
e99aae PGPKeySetIsMutable(PGPKeySet *keys)
f8bb36 {
b50e28 ¤   pgpa(pgpaPGPKeySetValid(keys));
b867c5 ¤
170bdb ¤   if ( ! pgpKeySetIsValid( keys ) )
82e20d ¤   ¤   return( FALSE );
c4af5a
78f170 ¤   return pgpKeyDBIsMutable(keys->keyDB);
70efe6 }
d5af5a
c016ea ¤   PGPBoolean
d9dff0 PGPKeySetNeedsCommit(PGPKeySet *keys)
70bb36 {
6d0e28 ¤   pgpa(pgpaPGPKeySetValid(keys));
d00bdb ¤   if ( ! pgpKeySetIsValid( keys ) )
4de20d ¤   ¤   return( FALSE );
15af5a
f13cf0 ¤   return pgpKeyDBIsDirty(keys->keyDB);
8eefe6 }
1faf5a
30ab29 /* ·Defines when a key should be expanded or collapsed. ·If set to 1,·
1ec9f5 ¤   keys are expanded by pgpBuildKeyPool. ·If set to 2, they are expanded
6416ef ¤   when referenced by an iterator, or when the key refCount is explicitly·
a76fb4 ¤   incremented by the app. */
93af5a
90c744 ¤   PGPError
dbd907 pgpIncKeyRefCount(PGPKey *key)
9dbb36 {
55690a ¤   pgpa(pgpaAddrValid(key, PGPKey));
da67c5 ¤
dcf53f ¤   if ( IsNull( key ) )
f34023 ¤   ¤   return( kPGPError_BadParams );
3faf5a
f73adc ¤   key->refCount++;
ff1b40 ¤   if (key->refCount == 1)·
48a302 ¤   ¤   return pgpExpandKey (key);
3b151e ¤   return kPGPError_NoErr;
70efe6 }
68af5a
18c744 ¤   PGPError
086211 pgpFreeKey(PGPKey *key)
b2bb36 {
878e12 ¤   PGPError¤   err = kPGPError_NoErr;
b7af5a
424ed7 ¤   pgpa(pgpaPGPKeyValid(key));
17d5b3 ¤   PGPValidateKey( key );
a43ea6 ¤   PGPValidateParam( key->refCount >= 1 );
8daf5a
5ef7cf ¤   if (key->refCount == 1)
68edee ¤   ¤   err = pgpCollapseKey (key);
42a79f ¤   key->refCount--;
4ba938 ¤   if (key->refCount <= 0)
34ea49 ¤   ¤   deallocKey(key->keyDB, key);
025ea8 ¤   return err;
6fefe6 }
59af5a
0bc744 ¤   PGPError
a3e876 PGPCountKeys(
f92645 ¤   PGPKeySetRef¤   keys,
40f098 ¤   PGPUInt32 *¤¤   numKeys )
86bb36 {
73284d ¤   PGPKey *¤   ¤   key;
dac02b ¤   PGPUInt32¤  ¤   count = 0;
b99372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b667c5 ¤
80a73d ¤   PGPValidatePtr( numKeys );
90816e ¤   *numKeys¤   = 0;
797f09 ¤   PGPValidateKeySet( keys );
9aaf5a
f3f473 ¤   for (key = keys->keyDB->firstKeyInDB; key; key = key->nextKeyInDB)
--ed72 000e3922c5840100232 Page 23 of pgpKeySet.c
f7c7a1 ¤   {
68c52b ¤   ¤   pgpa(pgpaPGPKeyValid(key));
8b25f3 ¤   ¤   if (PGPKeySetIsMember(key, keys))
68ae59 ¤   ¤   ¤   count++;
7b9371 ¤   }
e267c5 ¤
022979 ¤   *numKeys = count;
bfaf5a
46deb7 ¤   return( err );
1eefe6 }
59af5a
9ac744 ¤   PGPError
bdd9d1 PGPOrderKeySet(
408a16 ¤   PGPKeySet *¤¤   keys,
cbb97e ¤   PGPKeyOrdering¤ order,
6457b4 ¤   PGPKeyListRef *¤outRef )
bbbb36 {
02df22 ¤   PGPKeyList *¤   list;
70284d ¤   PGPKey *¤   ¤   key;
1fdef7 ¤   PGPUInt32¤  ¤   count;
93d845 ¤   PGPUInt32¤  ¤   i;
3f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
588293 ¤   PGPContextRef¤  context¤= PGPGetKeySetContext( keys );
bc67c5 ¤
e03c76 ¤   PGPValidatePtr( outRef );
593652 ¤   *outRef¤= NULL;
cc7f09 ¤   PGPValidateKeySet( keys );
81af5a
24af5a
e06a31 /*¤ list = pgpNew(PGPKeyList); */
366bee ¤   list = (PGPKeyList *)pgpContextMemAlloc( context,
338503 ¤   ¤   sizeof(PGPKeyList), kPGPMemoryMgrFlags_Clear );
d579c5 ¤   if (list == NULL)
164030 ¤   ¤   return kPGPError_OutOfMemory;
ddaf5a
6abfbb ¤   list->magic¤= kPGPKeyListMagic;
5967c5 ¤
d109ef ¤   (void)PGPCountKeys(keys, &count );
bc22b6 ¤   list->keyCount = count;
78f995 ¤   list->keys = (PGPKey **)pgpContextMemAlloc( context,
fb0769 ¤   ¤   count * sizeof(PGPKey *), kPGPMemoryMgrFlags_Clear);
dd6863 ¤   if (list->keys == NULL)
56c7a1 ¤   {
d06565 ¤   ¤   pgpContextMemFree( context, list);
7b4030 ¤   ¤   return kPGPError_OutOfMemory;
cb9371 ¤   }
6b67c5 ¤
402a79 ¤   list->refCount = 1;
6a6c0e ¤   list->keySet = keys;
30f22a ¤   list->order = order;
9a6606 ¤   list->prevListInSet = NULL;
e6f267 ¤   list->nextListInSet = keys->firstListInSet;
37af5a
50b802 ¤   if( IsntNull( list->nextListInSet ) )
3075f6 ¤   ¤   list->nextListInSet->prevListInSet = list;
d71b52 ¤   ¤
0e4b30 ¤   keys->firstListInSet = list;
5cdc3e ¤   list->firstIterInList = NULL;
52af5a
6ac126 ¤   PGPIncKeySetRefCount(keys);
51af5a
e5ff6c ¤   i = 0;
d4f473 ¤   for (key = keys->keyDB->firstKeyInDB; key; key = key->nextKeyInDB)
71c7a1 ¤   {
f5c52b ¤   ¤   pgpa(pgpaPGPKeyValid(key));
7d6e71 ¤   ¤   if (PGPKeySetIsMember( key, keys ))
235b34 ¤   ¤   {
459a4a ¤   ¤   ¤   pgpAssert(i < count);
6ad982 ¤   ¤   ¤   list->keys[i++] = key;
c90fe4 ¤   ¤   }
5a9371 ¤   }
e3a9b3 ¤   pgpAssert(i == count);
--3ee2 000663a88e540100232 Page 24 of pgpKeySet.c
e0af5a
0131be ¤   sortKeyList(list);
6daf5a
a3a6e2 ¤   *outRef¤= list;
61deb7 ¤   return( err );
80efe6 }
80af5a
95c744 ¤   PGPError
8a846a PGPIncKeyListRefCount(PGPKeyList *list)
49bb36 {
5e9d27 ¤   PGPValidateKeyList( list );
fbaf5a
bbee09 ¤   list->refCount++;
d967c5 ¤
382d68 ¤   return( kPGPError_NoErr );
4eefe6 }
3faf5a
30c744 ¤   PGPError
62c562 PGPFreeKeyList(PGPKeyList *list)
22bb36 {
bbd04d ¤   PGPContextRef¤  context¤= NULL;
ff67c5 ¤
2a9d27 ¤   PGPValidateKeyList( list );
7f67c5 ¤
5bccf3 ¤   context¤= PGPGetKeyListContext( list );
bbaf5a
fa734a ¤   list->refCount--;
689aed ¤   if (list->refCount <= 0)
bec7a1 ¤   {
d58177 ¤   ¤   list->magic¤= ~ list->magic;¤   /* mark as invalid */
f51b52 ¤   ¤
b932ec ¤   ¤   if (list->prevListInSet)
610ac2 ¤   ¤   ¤   list->prevListInSet->nextListInSet = list->nextListInSet;
360e1d ¤   ¤   else
d516f5 ¤   ¤   ¤   list->keySet->firstListInSet = list->nextListInSet;
8bb9dd ¤   ¤   if (list->nextListInSet)
e26bb5 ¤   ¤   ¤   list->nextListInSet->prevListInSet = list->prevListInSet;
5eaf5a
8c261b ¤   ¤   pgpAssert(list->firstIterInList == NULL);
4daf5a
9d4d59 ¤   ¤   pgpContextMemFree( context, list->keys);
b625bc ¤   ¤   PGPFreeKeySet(list->keySet);
b76565 ¤   ¤   pgpContextMemFree( context, list);
8c9371 ¤   }
ed2d68 ¤   return( kPGPError_NoErr );
7defe6 }
aaaf5a
c4af5a
7e2842 ¤   static PGPError·
14161b pgpGetKeyByKeyID(
542645 ¤   PGPKeySetRef¤   keys,
761ba2 ¤   PGPKeyID const *keyIDIn,
b4a895 ¤   PGPPublicKeyAlgorithm¤  pubKeyAlgorithm,
909403 ¤   PGPKeyRef *¤¤   outRef )
38bb36 {
682c37 ¤   PGPKeyDB *¤ ¤   db;
092979 ¤   RingSet const *¤ringSet;
f23043 ¤   long¤   ¤   ¤   lo;
ca9476 ¤   long¤   ¤   ¤   hi;
05650b ¤   long¤   ¤   ¤   i;
88da29 ¤   PGPKey **¤  ¤   keyArray;
1cbcd3 ¤   PGPKeyID¤   ¤   keyIDABytes;
cd3603 ¤   PGPKeyID¤   ¤   keyIDBBytes;
91d153 ¤   PGPKeyID¤   ¤   keyIDMasterBytes;
a60a36 ¤   PGPKeyID¤   ¤   keyIDBytes;
d53bcd ¤   int¤¤   ¤   ¤   comparison;
3967c5 ¤
b75520 ¤   PGPError¤   err¤= kPGPError_ItemNotFound;
fbbf43 ¤   PGPKeyRef¤  resultKey¤  = NULL;
5567c5 ¤
473c76 ¤   PGPValidatePtr( outRef );
663652 ¤   *outRef¤= NULL;
--f260 000f15e851a40100232 Page 25 of pgpKeySet.c
eb7f09 ¤   PGPValidateKeySet( keys );
5b4607 ¤   PGPValidatePtr( keyIDIn );
9aaf5a
3d86fa ¤   PGPValidateParam( pubKeyAlgorithm == kPGPPublicKeyAlgorithm_Invalid ||
7415f0 ¤   ¤   (pubKeyAlgorithm >= kPGPPublicKeyAlgorithm_First &&
9ea62c ¤   ¤   ¤   pubKeyAlgorithm <= kPGPPublicKeyAlgorithm_Last ) );
ff67c5 ¤
c6314f ¤   keyIDBytes¤ = *keyIDIn;
5967c5 ¤
c6299b ¤   db = keys->keyDB;
87bedd ¤   ringSet¤= pgpKeyDBRingSet(db);
3caf5a
cc7095 ¤   /* We may be called to match a subkey; if so replace keyid with master's */
40560e ¤   if( pubKeyAlgorithm != kPGPPublicKeyAlgorithm_Invalid )
f0c7a1 ¤   {
85be09 ¤   ¤   RingObject const¤   *ringObj;
60af5a
5b4a93 ¤   ¤   if( ((PGPKeyIDPriv *) keyIDIn)->length == 4 )
905b34 ¤   ¤   {
15ed07 ¤   ¤   ¤   ringObj = ringKeyById4 (ringSet, (PGPByte)pubKeyAlgorithm,
6bcbbc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpGetKeyBytes( &keyIDBytes ) );
b00fe4 ¤   ¤   }
a30e1d ¤   ¤   else
675b34 ¤   ¤   {
a82810 ¤   ¤   ¤   ringObj = ringKeyById8 (ringSet, (PGPByte)pubKeyAlgorithm,
06cbbc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpGetKeyBytes( &keyIDBytes ) );
bd0fe4 ¤   ¤   }
da1b52 ¤   ¤
43cfb5 ¤   ¤   if( IsNull( ringObj ) )
399317 ¤   ¤   ¤   return( kPGPError_ItemNotFound );
1587c7 ¤   ¤   ¤
611c12 ¤   ¤   if( ringKeyIsSubkey( ringSet, ringObj ) )
575b34 ¤   ¤   {
642583 ¤   ¤   ¤   /* It's a subkey, replace it with the master key */
94a353 ¤   ¤   ¤   ringObj = ringKeyMasterkey( ringSet, ringObj );
8d9255 ¤   ¤   ¤   ringKeyID8( ringSet, ringObj, NULL, &keyIDMasterBytes );
0c247c ¤   ¤   ¤   keyIDBytes¤ = keyIDMasterBytes;
680fe4 ¤   ¤   }
779371 ¤   }
a3af5a
aec04c ¤   if (db->keysByKeyID == NULL)
77c7a1 ¤   {
f3c9f8 ¤   ¤   PGPKeySet *¤¤   rootSet;
7daf5a
47f6ad ¤   ¤   if ((rootSet = pgpKeyDBRootSet(db)) != NULL)
685b34 ¤   ¤   {
270f55 ¤   ¤   ¤   err = PGPOrderKeySet(rootSet, kPGPKeyIDOrdering, &db->keysByKeyID );
b68370 ¤   ¤   ¤   if ( IsPGPError( err ) )
d91397 ¤   ¤   ¤   ¤   return( err );
912b85 ¤   ¤   ¤   ¤
96fbb0 ¤   ¤   ¤   /* rootSet will stick around until the keylist is freed */
27b447 ¤   ¤   ¤   PGPFreeKeySet(rootSet);
edaf5a
587aad ¤   ¤   ¤   /*
b3a939 ¤   ¤   ¤   ·* Undo the additional refCount created by the existence of
1522fa ¤   ¤   ¤   ·* rootSet. ·Otherwise the keyDB will never be freed because
9f294f ¤   ¤   ¤   ·* of the cycle in the reference graph. ·When the keyDB is
796861 ¤   ¤   ¤   ·* actually freed, if keysByKeyID exists, refCount will be
19d19e ¤   ¤   ¤   ·* incremented again before freeing keysByKeyID.
d48753 ¤   ¤   ¤   ·*/
164772 ¤   ¤   ¤   if (db->keysByKeyID != NULL)
20777f ¤   ¤   ¤   ¤   db->refCount--;
360fe4 ¤   ¤   }
f5fd24 ¤   ¤   if (db->keysByKeyID == NULL)
257cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
3b9371 ¤   }
8faf5a
ae5e68 ¤   pgpa((
59d6dc ¤   ¤   pgpaPGPKeyListValid(db->keysByKeyID),
5333cc ¤   ¤   pgpaAssert(db->keysByKeyID->order == kPGPKeyIDOrdering)));
c2af5a
f13a5d ¤   keyArray = db->keysByKeyID->keys;
--348a 0001a34c91240100232 Page 26 of pgpKeySet.c
82ca4b ¤   keyIDABytes¤= keyIDBytes;
f8af5a
e0e492 ¤   if( ((PGPKeyIDPriv *) keyIDIn)->length == 4 )
5cc7a1 ¤   {
6f1b17 ¤   ¤   /*
72458d ¤   ¤   ** Search the list linearly in the 4-byte case because the list
451559 ¤   ¤   ** is sorted by the full 8-byute ID
955c12 ¤   ¤   */
241b52 ¤   ¤
33ed40 ¤   ¤   for( i = 0; i < db->keysByKeyID->keyCount; i++ )
fc5b34 ¤   ¤   {
0c4019 ¤   ¤   ¤   PGPKeyRef¤  key;
c987c7 ¤   ¤   ¤
fba01e ¤   ¤   ¤   key = keyArray[ i ];
aeac7b ¤   ¤   ¤   ringKeyID4( ringSet, key->key, NULL, &keyIDBBytes );
2daf5a
dc84e3 ¤   ¤   ¤   comparison = compareKeyIDs( &keyIDABytes, &keyIDBBytes);
5091df ¤   ¤   ¤   if( comparison == 0 && PGPKeySetIsMember( key, keys) )
98f776 ¤   ¤   ¤   {
5c5076 ¤   ¤   ¤   ¤   if( PGPKeyRefIsValid( resultKey ) )
6772c3 ¤   ¤   ¤   ¤   {
e560fb ¤   ¤   ¤   ¤   ¤   /* Only one match allowed. Fail */
f8f781 ¤   ¤   ¤   ¤   ¤   resultKey = kInvalidPGPKeyRef;
2014c3 ¤   ¤   ¤   ¤   ¤   break;
d42613 ¤   ¤   ¤   ¤   }
13fa07 ¤   ¤   ¤   ¤   else
d072c3 ¤   ¤   ¤   ¤   {
34ba78 ¤   ¤   ¤   ¤   ¤   resultKey = key;
dd2613 ¤   ¤   ¤   ¤   }
d7a3a6 ¤   ¤   ¤   }
150fe4 ¤   ¤   }
329371 ¤   }
950e24 ¤   else
0cc7a1 ¤   {
f4afca ¤   ¤   lo = 0;
25332d ¤   ¤   hi = db->keysByKeyID->keyCount;
9eaf5a
b39d29 ¤   ¤   while (lo < hi)
a35b34 ¤   ¤   {
644019 ¤   ¤   ¤   PGPKeyRef¤  key;
6987c7 ¤   ¤   ¤
e85cf9 ¤   ¤   ¤   i = (lo + hi) / 2;
3e87c7 ¤   ¤   ¤
b9a170 ¤   ¤   ¤   key¤¤   = keyArray[ i ];
e19f39 ¤   ¤   ¤   ringKeyID8( ringSet, key->key, NULL, &keyIDBBytes );
6787c7 ¤   ¤   ¤
8d84e3 ¤   ¤   ¤   comparison = compareKeyIDs( &keyIDABytes, &keyIDBBytes);
bef02e ¤   ¤   ¤   if (comparison > 0)
efb731 ¤   ¤   ¤   ¤   lo = i + 1;
04de91 ¤   ¤   ¤   else if (comparison < 0)
9913a3 ¤   ¤   ¤   ¤   hi = i;
1a826a ¤   ¤   ¤   else if (PGPKeySetIsMember( keyArray[i], keys))
b8f776 ¤   ¤   ¤   {
812219 ¤   ¤   ¤   ¤   resultKey¤  = keyArray[i];
b6f622 ¤   ¤   ¤   ¤   break;
0ba3a6 ¤   ¤   ¤   }
debb8c ¤   ¤   ¤   else
dbf622 ¤   ¤   ¤   ¤   break;
430fe4 ¤   ¤   }
a59371 ¤   }
8667c5 ¤
4a9b72 ¤   if ( IsNull( resultKey ) )
10c7a1 ¤   {
480886 ¤   ¤   err¤= kPGPError_ItemNotFound;
fa9371 ¤   }
270e24 ¤   else
e5c7a1 ¤   {
ff70bb ¤   ¤   err = kPGPError_NoErr;
4a9371 ¤   }
2167c5 ¤
136dc4 ¤   *outRef¤= resultKey;
1a67c5 ¤
--2b13 000a4d26b1740100232 Page 27 of pgpKeySet.c
cebe67 ¤   pgpAssert( ( IsntPGPError( err ) && IsntNull( *outRef ) ) ||
fc0d8f ¤   ¤   ( IsPGPError( err ) && IsNull( *outRef ) ));
f9deb7 ¤   return( err );
12efe6 }
3baf5a
5921ab ¤   PGPError·
cfa9d7 PGPGetKeyByKeyID(
c3a5b4 ¤   PGPKeySetRef¤   ¤   ¤   keys,
1ba4f6 ¤   PGPKeyID const *¤   ¤   keyIDIn,
83a895 ¤   PGPPublicKeyAlgorithm¤  pubKeyAlgorithm,
a8bd2a ¤   PGPKeyRef *¤¤   ¤   ¤   outRef )
84bb36 {
be26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5467c5 ¤
b43c76 ¤   PGPValidatePtr( outRef );
433652 ¤   *outRef¤= NULL;
fa7f09 ¤   PGPValidateKeySet( keys );
7d4607 ¤   PGPValidatePtr( keyIDIn );
4867c5 ¤
c2671d ¤   err¤= pgpGetKeyByKeyID( keys, keyIDIn, pubKeyAlgorithm, outRef );
f7f1e7 ¤   if ( IsntPGPError( err ) )
4fc7a1 ¤   {
f7a74e ¤   ¤   pgpIncKeyRefCount( *outRef );
679371 ¤   }
9b67c5 ¤
704c5f ¤   pgpAssertErrWithPtr( err, *outRef );
c6deb7 ¤   return( err );
86efe6 }
a3af5a
bcaf5a
6a16ea ¤   PGPBoolean
27e402 pgpKeyDBIsValid( PGPKeyDB const *¤  keyDB)
aebb36 {
b2c13c ¤   return( IsntNull( keyDB ) && keyDB->fixedMagic == kPGPKeyDBMagic );
50efe6 }
e8af5a
af16ea ¤   PGPBoolean
a75a40 pgpKeySetIsValid( PGPKeySet const *¤keySet)
4ebb36 {
987696 ¤   return( IsntNull( keySet ) && keySet->magic == kPGPKeySetMagic );
d2efe6 }
6faf5a
6b16ea ¤   PGPBoolean
cf6fb5 pgpKeyListIsValid( PGPKeyList const *¤  keyList)
5abb36 {
7d1dd6 ¤   return( IsntNull( keyList ) && keyList->magic == kPGPKeyListMagic );
e7efe6 }
59af5a
b216ea ¤   PGPBoolean
513e85 pgpKeyIterIsValid( PGPKeyIter const *¤  keyIter)
89bb36 {
d3f311 ¤   return( IsntNull( keyIter ) &&
5c8caf ¤   ¤   keyIter->magic == kPGPKeyIterMagic );
d0efe6 }
75af5a
7c16ea ¤   PGPBoolean
010f86 pgpKeyIsValid( PGPKey const *¤  ¤   key)
4dbb36 {
f00509 ¤   PGPBoolean¤ isValid;
6c67c5 ¤
43637d ¤   isValid¤= IsntNull( key ) &&
cd0c7b ¤   ¤   ¤   pgpOptionalMagicMatches( key, kPGPKeyMagic ) &&
3c47c0 ¤   ¤   ¤   key->refCount > 0 &&·
71acd9 ¤   ¤   ¤   pgpKeyDBIsValid( key->keyDB );
8c87c7 ¤   ¤   ¤
9d195c ¤   return( isValid );
34efe6 }
51af5a
fc16ea ¤   PGPBoolean
eb17e7 pgpSubKeyIsValid(
191cf2 ¤   PGPSubKey const *¤  subKey)
a4bb36 {
--aaa4 000ab8679af40100232 Page 28 of pgpKeySet.c
d10509 ¤   PGPBoolean¤ isValid;
a667c5 ¤
5f68ab ¤   isValid¤= IsntNull( subKey ) &&
836d31 ¤   ¤   ¤   pgpOptionalMagicMatches( subKey, kPGPSubKeyMagic ) &&
24102b ¤   ¤   ¤   pgpKeyIsValid( subKey->key );
7287c7 ¤   ¤   ¤
05195c ¤   return( isValid );
ddefe6 }
0caf5a
6216ea ¤   PGPBoolean
5e83f5 pgpUserIDIsValid(
822fe6 ¤   PGPUserID const *¤  userID)
fabb36 {
f80509 ¤   PGPBoolean¤ isValid;
4a67c5 ¤
8411e9 ¤   isValid¤= IsntNull( userID ) &&
d2b878 ¤   ¤   ¤   pgpOptionalMagicMatches( userID, kPGPUserIDMagic ) &&
f88439 ¤   ¤   ¤   pgpKeyIsValid( userID->key );
3e87c7 ¤   ¤   ¤
bc195c ¤   return( isValid );
77efe6 }
11af5a
1716ea ¤   PGPBoolean
92b9c4 pgpSigIsValid(
925f83 ¤   PGPSig const *¤ ¤   cert)
f6bb36 {
a9bc1e ¤   return( IsntNull( cert ) &&
607a51 ¤   ¤   pgpOptionalMagicMatches( cert, kPGPCertMagic ) );
9fefe6 }
feaf5a
caaf5a
c5af5a
2ce85e #if PGP_DEBUG¤  /* [ */
e3af5a
7016ea ¤   PGPBoolean
42bec1 pgpaInternalPGPKeyDBValid(
e63c2c ¤   pgpaCallPrefixDef,
6eb108 ¤   PGPKeyDB const *¤   keyDB,
38d620 ¤   char const *¤   ¤   varName)
87bb36 {
8e40a0 ¤   pgpaAddrValid(keyDB, PGPKeyDB);
feba8b ¤   pgpaFailIf(keyDB->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
d2bd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
2d0470 ¤   ¤   ¤   "pgpaPGPKeyDBValid failed on %s (%p)", varName, keyDB));
66af5a
f9750f ¤   return pgpaFailed;
a0efe6 }
70af5a
3a16ea ¤   PGPBoolean
93f782 pgpaInternalPGPKeySetValid(
d13c2c ¤   pgpaCallPrefixDef,
9ad0c2 ¤   PGPKeySet const *¤  keySet,
5ed620 ¤   char const *¤   ¤   varName)
c7bb36 {
53ec60 ¤   pgpaAddrValid(keySet, PGPKeySet);
cb11b5 ¤   pgpaFailIf(keySet->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
aebd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
fc3a60 ¤   ¤   ¤   "pgpaPGPKeySetValid failed on %s (%p)", varName, keySet));
b0af5a
99750f ¤   return pgpaFailed;
16efe6 }
e0af5a
6616ea ¤   PGPBoolean
5ad276 pgpaInternalPGPKeyListValid(
033c2c ¤   pgpaCallPrefixDef,
2724bc ¤   PGPKeyList const *¤ keyList,
d1d620 ¤   char const *¤   ¤   varName)
4cbb36 {
1009b6 ¤   pgpaAddrValid(keyList, PGPKeyList);
0a9ce3 ¤   pgpaFailIf(keyList->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
53bd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
ab659f ¤   ¤   ¤   "pgpaPGPKeyListValid failed on %s (%p)", varName, keyList));
--327d 000b03287f040100232 Page 29 of pgpKeySet.c
e0af5a
2e750f ¤   return pgpaFailed;
94efe6 }
85af5a
6b16ea ¤   PGPBoolean
35b848 pgpaInternalPGPKeyIterValid(
4a3c2c ¤   pgpaCallPrefixDef,
3cada3 ¤   PGPKeyIter const *¤ keyIter,
7ad620 ¤   char const *¤   ¤   varName)
bfbb36 {
a7da6f ¤   pgpaAddrValid(keyIter, PGPKeyIter);
3abd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
46593a ¤   ¤   ¤   "pgpaPGPKeyIterValid failed on %s (%p)", varName, keyIter));
beaf5a
c9750f ¤   return pgpaFailed;
f0efe6 }
27af5a
c616ea ¤   PGPBoolean
13f5d0 pgpaInternalPGPKeyValid(
d03c2c ¤   pgpaCallPrefixDef,
585e14 ¤   PGPKey const *¤ ¤   key,
e3d620 ¤   char const *¤   ¤   varName)
3cbb36 {
608e46 ¤   pgpaAddrValid(key, PGPKey);
5b2c9c ¤   pgpaFailIf(key->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));
eebd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
73b8fc ¤   ¤   ¤   "pgpaPGPKeyValid failed on %s (%p)", varName, key));
7eaf5a
83750f ¤   return pgpaFailed;
28efe6 }
1eaf5a
d416ea ¤   PGPBoolean
06a718 pgpaInternalPGPSubKeyValid(
303c2c ¤   pgpaCallPrefixDef,
b1624a ¤   PGPSubKey const *¤  subKey,
2dd620 ¤   char const *¤   ¤   varName)
07bb36 {
418688 ¤   pgpaAddrValid(subKey, PGPSubKey);
b0f2a5 /*¤ pgpaFailIf(subKey->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));¤   */
4fbd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
bf8307 ¤   ¤   ¤   "pgpaPGPSubKeyValid failed on %s (%p)", varName, subKey));
06af5a
45750f ¤   return pgpaFailed;
87efe6 }
07af5a
8216ea ¤   PGPBoolean
50c677 pgpaInternalPGPUserIDValid(
8e3c2c ¤   pgpaCallPrefixDef,
8a515e ¤   PGPUserID const *¤  userID,
4cd620 ¤   char const *¤   ¤   varName)
abbb36 {
e6f4aa ¤   pgpaAddrValid(userID, PGPUserID);
f9af03 /*¤ pgpaFailIf(userID->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0"));¤   */
7bbd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
f657c1 ¤   ¤   ¤   "pgpaPGPUserIDValid failed on %s (%p)", varName, userID));
b2af5a
56750f ¤   return pgpaFailed;
f8efe6 }
8faf5a
fd16ea ¤   PGPBoolean
6febda pgpaInternalPGPCertValid(
7c3c2c ¤   pgpaCallPrefixDef,
07213b ¤   PGPSig const *¤ ¤   cert,
aad620 ¤   char const *¤   ¤   varName)
9abb36 {
3521bf ¤   pgpaAddrValid(cert, PGPSig);
461a30 /*¤ pgpaFailIf(cert->refCount <= 0, (pgpaFmtPrefix, "refCount <= 0")); ¤*/
90bd5b ¤   pgpaFmtMsg((pgpaFmtPrefix,
1194d6 ¤   ¤   ¤   "pgpaPGPCertValid failed on %s (%p)", varName, cert));
0baf5a
a7750f ¤   return pgpaFailed;
b0efe6 }
--58d4 001a4f609b840100232 Page 30 of pgpKeySet.c
e0af5a
d79e9f #endif /* ] PGP_DEBUG */
b8af5a
8f38e5 /*
77e6c5 ·* Local Variables:
a59b19 ·* tab-width: 4
8de7a4 ·* End:
61b612 ·* vi: ts=4 sw=4
576c42 ·* vim: si
27495d ·*/
a4af5a
--eb33 000af0e32ff40100233 Page 1 of pgpKeyUpd.c
bc38e5 /*
6de93b ·* pgpKeyUpd.c
e26382 ·* Functions to update sub-objects of keys.
96775e ·*
cb94ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
3320c7 ·* All rights reserved
73775e ·*
07914d ·* $Id: pgpKeyUpd.c,v 1.15.10.1 1998/11/12 03:22:04 heller Exp $
8c495d ·*/
23af5a
72e2ff #include "pgpConfig.h"
2eaf5a
8cc26c #include "pgpContext.h"
49979a #include "pgpKDBInt.h"
12a146 #include "pgpDebug.h"
c126e3 #include "pgpRngPub.h"
7bf5ab #include "pgpSigSpec.h"
88af5a
51af5a
2f1de8 static PGPUserIDRef
bd16e5 allocUserID (PGPKeyDB *keyDB)
b7bb36 {
483969 ····PGPUserID¤  *userid;
f6af5a
778d08 ····if (keyDB->firstFreeUserID != NULL) {
c80ce7 ········userid = keyDB->firstFreeUserID;
d5ca2d ········keyDB->firstFreeUserID = userid->next;
606fe7 ····}
e4842c ····else
212f0e ········userid = (PGPUserID *)memPoolNew (&keyDB->keyPool, PGPUserID);
fd508e ········
5b72a8 #if PGP_OPTIONAL_MAGICS
c50e94 ¤   if ( IsntNull( userid ) )
63c7a1 ¤   {
d1f01b ¤   ¤   userid->magic¤  ¤   = kPGPUserIDMagic;
409371 ¤   }
dd7454 #endif
16af5a
07e4e3 ····return userid;
03efe6 }
74af5a
75af5a
09dbcd static PGPSubKeyRef·
07985f allocSubKey (PGPKeyDB *keyDB)
44bb36 {
00262e ····PGPSubKey¤  *subkey;
e3af5a
d4c318 ····if (keyDB->firstFreeSubKey != NULL) {
075a6e ········subkey = keyDB->firstFreeSubKey;
f8e40e ········keyDB->firstFreeSubKey = subkey->next;
656fe7 ····}
51842c ····else
ba55f3 ········subkey = (PGPSubKey *)memPoolNew (&keyDB->keyPool, PGPSubKey);
a7508e ········
3e72a8 #if PGP_OPTIONAL_MAGICS
bbcb5d ¤   if ( IsntNull( subkey ) )
18c7a1 ¤   {
2f64cf ¤   ¤   subkey->magic¤  ¤   = kPGPSubKeyMagic;
1a9371 ¤   }
267454 #endif
78af5a
e9b5b4 ····return subkey;
25efe6 }
c3af5a
9faf5a
feaf5a
9fa438 static PGPSig *
9cf6ce allocCert (PGPKeyDB *keyDB)
d4bb36 {
85218f ····PGPSig¤ ¤   *cert;
1baf5a
aff194 ····if (keyDB->firstFreeCert != NULL) {
--80d3 000479893c440100233 Page 2 of pgpKeyUpd.c
569cd0 ········cert¤   ¤   ¤   = keyDB->firstFreeCert;
2ade11 ¤   ¤   keyDB->firstFreeCert = cert->next;
d96fe7 ····}
d5842c ····else
c63b37 ····{
1d8c1e ········cert = (PGPSig *)memPoolNew (&keyDB->keyPool, PGPSig);
539371 ¤   }
d167c5 ¤
7972a8 #if PGP_OPTIONAL_MAGICS
1306b5 ¤   if ( IsntNull( cert ) )
94c7a1 ¤   {
444441 ¤   ¤   cert->magic¤¤   = kPGPCertMagic;
0c9371 ¤   }
ea7454 #endif
f9bb1d ····return cert;
f6efe6 }
d7af5a
21af5a
307ec5 /* ·Remove the PGPUserID from its doubly linked list and
cbd606 ····add it to the keydb free list. ·If it has PGPCerts·
e59c1d ····attached, deallocate them also. */
f3af5a
cd314a void
8d2590 pgpDeallocUserID (PGPUserID *userid)
80bb36 {
d0b750 ¤   pgpa(pgpaAssert(userid->refCount == 0));
e872a8 #if PGP_OPTIONAL_MAGICS
a988a5 ¤   userid->magic¤  ¤   ¤   = ~userid->magic;
587454 #endif
5f8c0c ¤   userid->prev->next = userid->next;
948863 ····userid->next->prev = userid->prev;
d56214 ····userid->next = userid->key->keyDB->firstFreeUserID;
fe9c9e ····userid->key->keyDB->firstFreeUserID = userid;
f2fabe ····/* ·Free subordinate certs */
9ad96d ····while (userid->certs.next != &userid->certs)
9ffdc5 ········pgpDeallocCert ((PGPSig *) userid->certs.next);
cbefe6 }
10af5a
fc3d04 /* ·Remove a subkey from its doubly linked list */
2eaf5a
40314a void
932050 pgpDeallocSubKey (PGPSubKeyRef subkey)
eebb36 {
055582 ¤   pgpa(pgpaAssert(subkey->refCount == 0));
9472a8 #if PGP_OPTIONAL_MAGICS
ea23d6 ¤   subkey->magic¤  ¤   = ~subkey->magic;
517454 #endif
419ad2 ¤   subkey->prev->next¤ = subkey->next;
519ff4 ····subkey->next->prev¤ = subkey->prev;
466a69 ····subkey->next = subkey->key->keyDB->firstFreeSubKey;
be4bb4 ····subkey->key->keyDB->firstFreeSubKey = subkey;
c4efe6 }
fdaf5a
c4c026 /* ·Remove the PGPSig from its doubly linked list and
c1ce46 ····add it to the keydb free list */
69af5a
d3314a void
3e9da8 pgpDeallocCert (PGPSig *cert)
41bb36 {
1ed6b1 ¤   pgpa(pgpaAssert(cert->refCount == 0));
b272a8 #if PGP_OPTIONAL_MAGICS
d555f9 ¤   cert->magic¤¤   ¤   = ~cert->magic;
8e7454 #endif
9cb711 ····cert->prev->next¤   = cert->next;
501d0e ····cert->next->prev¤   = cert->prev;
529c14 ¤   if (cert->type == uidcert) {
79fea7 ¤   ····cert->next = cert->up.userID->key->keyDB->firstFreeCert;
a93779 ¤   ¤   cert->up.userID->key->keyDB->firstFreeCert = cert;
0f9371 ¤   }
12665a ¤   else {
13605f ¤   ····/* no key certificates for now */
47d8fc ¤   ····pgpAssert (0);
--fe23 0002278db1640100233 Page 3 of pgpKeyUpd.c
c247d1 ¤   }·
7eefe6 }
28af5a
3baf5a
02f1ae static PGPError
56ab41 createNewUserID (PGPKey *key, PGPUserID *prev, union RingObject *nameobj)
65bb36 {
c88a55 ····PGPUserID¤  ¤   *newuid = NULL;
f1af5a
d16e00 ····newuid = allocUserID (key->keyDB);
3bef1b ····if (!newuid)
83d3ee ········return kPGPError_OutOfMemory;
08af5a
ec535e ····newuid->next = prev->next;
e9e46a ····newuid->prev = newuid->next->prev;
36fa3b ····newuid->next->prev = newuid;
137f48 ····newuid->prev->next = newuid;
f184c0 ····newuid->certs.next = &newuid->certs;
33a406 ····newuid->certs.prev = newuid->certs.next;
9b6307 ····newuid->userID = nameobj;
7cc0b8 ····newuid->key = key;
fbf698 ····newuid->refCount = 0;
58c69e ····newuid->removed = 0;
cd68a9 ····newuid->userVal = 0;
23258d ····return kPGPError_NoErr;
88efe6 }
18af5a
99af5a
61f1ae static PGPError
cf0448 createNewUidCert (PGPUserID *userid, PGPSig *prev, union RingObject *sigobj)
c3bb36 {
8c633b ····PGPSig¤ *newcert = NULL;
78af5a
457e0a ····newcert = allocCert (userid->key->keyDB);
3dd161 ····if (!newcert)
07d3ee ········return kPGPError_OutOfMemory;
93af5a
cbe1ba ····newcert->next = prev->next;
a3548f ····newcert->prev = newcert->next->prev;
da0564 ····newcert->next->prev = newcert;
6544fd ····newcert->prev->next = newcert;
792968 ¤   newcert->type = uidcert;
028ee6 ····newcert->cert = sigobj;
51f04b ····newcert->up.userID = userid;
3da428 ····newcert->refCount = 0;
b5f3ce ····newcert->removed = 0;
fd5df9 ····newcert->userVal = 0;
a4258d ····return kPGPError_NoErr;
dcefe6 }
75af5a
7daf5a
a7f1ae static PGPError
4c735a createNewSubKey (PGPKey *key, PGPSubKeyRef prev, union RingObject *subkeyobj)
aabb36 {
ea48b0 ····PGPSubKey¤  *newsubkey = NULL;
45af5a
e3c82b ····newsubkey = allocSubKey (key->keyDB);
557c7a ····if (!newsubkey)
ecd3ee ········return kPGPError_OutOfMemory;
54af5a
d225c4 ····newsubkey->next = prev->next;
e4d640 ····newsubkey->prev = newsubkey->next->prev;
4cf3e3 ····newsubkey->next->prev = newsubkey;
996e2b ····newsubkey->prev->next = newsubkey;
fa6fe5 ····newsubkey->subKey = subkeyobj;
3f37b2 ····newsubkey->key = key;
1eb4e2 ····newsubkey->refCount = 0;
b1b8de ····newsubkey->removed = 0;
0516e9 ····newsubkey->userVal = 0;
92258d ····return kPGPError_NoErr;
7aefe6 }
22af5a
--51e7 000f53e53fa40100233 Page 4 of pgpKeyUpd.c
e0af5a
1aaf5a
c493e0 /* ·Expand the sub-objects of the specified key. ·This function should be
ae1637 ····called when the refCount of a key goes from 0 to 1.·
ca6096 ····This function is also called to update an already expanded key with
5a3950 ····new userids and/or certs. */
15af5a
58c77d PGPError
d92122 pgpExpandKey (PGPKey *key)
e0bb36 {
115907 ····PGPKeyDB¤   ¤   ¤   *keyDB;
f2bf84 ····RingSet const¤  ¤   *ringset = NULL;
52ee0e ····RingIterator¤   *iter;
5d9665 ····union RingObject¤   *nameobj, *sigobj, *subkeyobj;
e0ad2c ····PGPUserID¤  ¤   ¤   *userid;
001f63 ····PGPSig¤ ¤   ¤   ¤   *cert;
d21dd9 ¤   PGPSubKey ··········*subkey;
239a76 ····int¤¤   ¤   ¤   ¤   sigtype;
bc576e ····PGPError¤   ¤   ¤   err = kPGPError_NoErr;
53af5a
33037b ····pgpa(pgpaPGPKeyValid(key));
4eaf5a
9bee8c ····keyDB = key->keyDB;
781680 ····ringset = pgpKeyDBRingSet (keyDB);
26223f ····iter = ringIterCreate (ringset);
7ec617 ····if (!iter)
95689b ········return ringSetError(ringset)->error;
46f708 ····if (ringIterSeekTo (iter, key->key) != 1)
ace319 ········return kPGPError_BadParams;
0eaf5a
841af7 ¤   /* ·Expand subkeys */
a1d59a ¤   subkey = (PGPSubKeyRef ) key->subKeys.next;
194b05 ¤   while (subkey != (PGPSubKeyRef ) &key->subKeys && subkey->removed)
17c639 ¤   ····subkey = subkey->next;
7d1328 ····while ((err = (PGPError)ringIterNextObject (iter, 2)) > 0) {
26b981 ········subkeyobj = ringIterCurrentObject (iter, 2);
46c860 ¤   ¤   if (ringObjectType (subkeyobj) != RINGTYPE_KEY)
ca07aa ¤   ¤   ¤   continue; ··/* secobj or nameobj */
81daf5 ¤   ¤   if (subkey == (PGPSubKeyRef ) &key->subKeys ||
e87e01 ¤   ¤   ¤   subkeyobj != subkey->subKey) { ··/* not found */
94cd1a ¤   ¤   ¤   err = createNewSubKey (key, subkey->prev, subkeyobj);
f75480 ¤   ¤   ¤   if (err)
0c0658 ¤   ¤   ¤   ¤   goto cleanup;
140fe4 ¤   ¤   }
d5a6dd ¤   ¤   else { ·····························/* found */
7c5267 ¤   ¤   ¤   subkey = subkey->next;
377689 ¤   ¤   ¤   while (subkey != (PGPSubKeyRef ) &key->subKeys && subkey->removed)
d11394 ¤   ¤   ¤   ¤   subkey = subkey->next;
bb0fe4 ¤   ¤   }
b79371 ¤   }
397f92 ¤   ringIterRewind (iter, 2); ··/* rewind to find names */
64af5a
5fdb57 ¤   /* ·Expand UserIDs */
a9c21b ····userid = (PGPUserID *) key->userIDs.next;
1e3a78 ¤   while (userid != (PGPUserID *) &key->userIDs && userid->removed)
6ede4d ¤   ¤   userid = userid->next;
bd1328 ····while ((err = (PGPError)ringIterNextObject (iter, 2)) > 0) {
2294aa ········nameobj = ringIterCurrentObject (iter, 2);
ccba7e ¤   ¤   if (ringObjectType (nameobj) != RINGTYPE_NAME)
f62989 ¤   ¤   ¤   continue; ··/* secobj or subkey */
b9fe33 ¤   ¤   if (userid == (PGPUserID *) &key->userIDs ||
24dc9b ¤   ¤   ¤   nameobj != userid->userID) { ··/* not found */
13308a ¤   ¤   ¤   err = createNewUserID (key, userid->prev, nameobj);
da5480 ¤   ¤   ¤   if (err)
180658 ¤   ¤   ¤   ¤   goto cleanup;
c50fe4 ¤   ¤   }
b8a6dd ¤   ¤   else { ·····························/* found */
4d5232 ¤   ¤   ¤   userid = userid->next;
d6a0d4 ¤   ¤   ¤   while (userid != (PGPUserID *) &key->userIDs && userid->removed)
6d13c1 ¤   ¤   ¤   ¤   userid = userid->next;
310fe4 ¤   ¤   }
f5af5a
--6350 000fe01b79040100233 Page 5 of pgpKeyUpd.c
fc5dc1 ¤   ¤   /* ·Expand certifications on UserID (userid->prev) */
8847c0 ¤   ¤   cert = (PGPSig *) userid->prev->certs.next;
c45bd5 ¤   ¤   while (cert != (PGPSig *) &userid->prev->certs && cert->removed)
e24ebe ¤   ¤   ¤   cert = cert->next;
049197 ¤   ¤   while ((err = (PGPError)ringIterNextObject (iter, 3)) > 0) {
521cd7 ¤   ¤   ¤   sigobj = ringIterCurrentObject (iter, 3);
27d58b ¤   ¤   ¤   pgpAssert (ringObjectType (sigobj) == RINGTYPE_SIG);
dcb733 ¤   ¤   ¤   sigtype = ringSigType (ringset, sigobj);
4e2948 ¤   ¤   ¤   if (sigtype < PGP_SIGTYPE_KEY_GENERIC ||·
d16436 ¤   ¤   ¤   ¤   sigtype > PGP_SIGTYPE_KEY_POSITIVE)
c6d040 ¤   ¤   ¤   ¤   continue;
9a67ae ¤   ¤   ¤   if (cert == (PGPSig *) &userid->prev->certs ||
fc087e ¤   ¤   ¤   ¤   sigobj != cert->cert) { ····/* not found */
880ad5 ¤   ¤   ¤   ¤   err = createNewUidCert (userid->prev, cert->prev, sigobj);
b9e551 ¤   ¤   ¤   ¤   if (err)
c13150 ¤   ¤   ¤   ¤   ¤   goto cleanup;
87a3a6 ¤   ¤   ¤   }
92e543 ¤   ¤   ¤   else {
46c2c1 ¤   ¤   ¤   ¤   cert = cert->next;
433f6f ¤   ¤   ¤   ¤   while (cert != (PGPSig *) &userid->prev->certs &&·
da5a89 ¤   ¤   ¤   ¤   ¤   ···cert->removed)
268332 ¤   ¤   ¤   ¤   ¤   cert = cert->next;
7fa3a6 ¤   ¤   ¤   }
2f0fe4 ¤   ¤   }
406fe7 ····}
8c68cb cleanup:
90023b ····if (iter)
062ebe ········ringIterDestroy (iter);
03ace8 ····return err;
b1efe6 }
53af5a
97af5a
603c0a /* ·Collapse the expanded subobjects. ·Refcount of all subobjects
7e76ce ¤   must be zero. */
9faf5a
47c77d PGPError
36f019 pgpCollapseKey (PGPKey *key)
1fbb36 {
9d656a ····pgpa(pgpaAddrValid(key, PGPKey));
6eaf5a
2002e6 ¤   while (key->subKeys.next != &key->subKeys)
a48d56 ¤   ····pgpDeallocSubKey ((PGPSubKeyRef ) key->subKeys.next);
86c416 ····while (key->userIDs.next != &key->userIDs)·
2869a2 ········pgpDeallocUserID ((PGPUserID *) key->userIDs.next);
c6258d ····return kPGPError_NoErr;
8befe6 }
d8af5a
ecaf5a
19af5a
cfcbf3 /* ·Remove a RingObject from the Key Database. ·*/
d9af5a
578de9 PGPError·
ee1d32 pgpRemoveObject (PGPKeyDB *keyDB, union RingObject *obj)
3fbb36 {
d24c45 ····int¤¤   ¤   ¤   ¤   type, sigtype = 0;
9cf7ea ····RingSet¤const¤  *ringset;
a4ee0e ····RingIterator¤   *iter;
297f9e ····union RingObject¤   *nameobj = NULL, *keyobj;
5a07d2 ····PGPKey¤ ¤   ¤   ¤   *key;
811dd9 ¤   PGPSubKey ··········*subkey;
3ead2c ····PGPUserID¤  ¤   ¤   *userid;
f51f63 ····PGPSig¤ ¤   ¤   ¤   *cert;
896d98 ¤   int ················level;
2650cd ¤   RingPool¤   ¤   ¤   *pgpRingPool;
c1576e ····PGPError¤   ¤   ¤   err = kPGPError_NoErr;
19869e ····
3a3596 ····pgpa(pgpaPGPKeyDBValid(keyDB));
4671c6 ····type = ringObjectType (obj);
0caf5a
de570f ····/* ·Get superior RingObjects before deleting the subject object */
a8758a ¤   ringset = pgpKeyDBRingSet (keyDB);
fe223f ····iter = ringIterCreate (ringset);
--97bd 0000bfdc8c440100233 Page 6 of pgpKeyUpd.c
64c617 ····if (!iter)
0c689b ········return ringSetError(ringset)->error;
0ab1ef ····level = ringIterSeekTo (iter, obj);
b0ea34 ····keyobj = ringIterCurrentObject (iter, 1);
85f9d2 ····if (type == RINGTYPE_SIG) {
2cda1c ¤   ····sigtype = ringSigType (ringset, obj);
4794aa ········nameobj = ringIterCurrentObject (iter, 2);
999371 ¤   }
88af5a
274608 ····/* ·Remove from master ringset. ·If it's still a member of the ringset,
19d3de ¤   ¤   then it could not be removed from at least one ringset that makes·
b99174 ¤   ¤   up the master ringset. In this case, we're done. ·*/
3caf5a
7d691f ····err = keyDB->remove(keyDB, obj);
05a09a ¤   if (err)
b2c9db ¤   ¤   return err;
ab1680 ····ringset = pgpKeyDBRingSet (keyDB);
445e2f ····if (ringSetIsMember (ringset, obj))
e7c57f ········return kPGPError_NoErr;
b8af5a
9beb0a ····/* ·Locate PGPKey object */
d9f03b ····key = pgpGetKeyByRingObject (keyDB, keyobj);
e419f3 ····if (!key) {
8eba0b ········err = kPGPError_FileCorrupt;
9948b9 ¤   ¤   goto cleanup;
c96fe7 ····}
e5af5a
65c943 ····if (type == RINGTYPE_KEY && level == 1)
f1681a ¤   ¤   pgpBuildKeyPool (keyDB, 1);
f9759b ¤   else if (type == RINGTYPE_KEY && level == 2) {
152336 ········subkey = (PGPSubKeyRef ) key->subKeys.next;
e32ed5 ¤   ¤   /* ·Search for the PGPSubKey object that references obj */
dcc52a ¤   ¤   while (subkey != (PGPSubKeyRef ) &key->subKeys &&·
bddd71 ¤   ¤   ¤   ¤   (subkey->removed || subkey->subKey != obj) )
0c5267 ¤   ¤   ¤   subkey = subkey->next;
0cf267 ¤   ¤   if (subkey != (PGPSubKeyRef ) &key->subKeys)
5839b1 ¤   ¤   ¤   subkey->removed = 1;
b707e0 ¤   ¤   else {
45bf2a ¤   ¤   ····err = kPGPError_FileCorrupt;
da8f0c ¤   ¤   ¤   goto cleanup;
3c0fe4 ¤   ¤   }
a19371 ¤   }
7e5f5c ····else if (type == RINGTYPE_NAME) {
8c130a ········userid = (PGPUserID *) key->userIDs.next;
a96dec ¤   ¤   /* ·Search for the PGPUserID object that references obj */
026212 ¤   ¤   while (userid != (PGPUserID *) &key->userIDs &&
44d65b ¤   ¤   ¤   ···!(userid->userID == obj && !userid->removed)) {
c35232 ¤   ¤   ¤   userid = userid->next;
6f0fe4 ¤   ¤   }
ca8832 ¤   ¤   if (userid != (PGPUserID *) &key->userIDs) {
bfdf9e ¤   ¤   ¤   userid->removed = 1;
ac81a1 ¤   ¤   ¤   /* ·Mark all attached certs as removed also */
bddfd8 ¤   ¤   ¤   for (cert = (PGPSig *) userid->certs.next; cert !=·
d15c7d ¤   ¤   ¤   ¤   ···(PGPSig *) &userid->certs;
3ee076 ¤   ¤   ¤   ¤   ·cert = cert->next)
148d79 ¤   ¤   ¤   ¤   cert->removed = 1;
4e0fe4 ¤   ¤   }
3f3684 ¤   ¤   else { ··/* not found */
71d001 ¤   ¤   ¤   err = kPGPError_FileCorrupt;
648f0c ¤   ¤   ¤   goto cleanup;
460fe4 ¤   ¤   }
479371 ¤   }
136d0a ····else if (type == RINGTYPE_SIG && sigtype != PGP_SIGTYPE_KEY_UID_REVOKE &&
6a191e ¤   ¤   ¤   ·sigtype != PGP_SIGTYPE_KEY_REVOKE) {
29130a ········userid = (PGPUserID *) key->userIDs.next;
1f9ea8 ¤   ¤   /* Search for parent PGPUserID */
fa16bd ¤   ¤   while (userid != (PGPUserID *) &key->userIDs &&·
f11bc8 ¤   ¤   ¤   ···!(userid->userID == nameobj && !userid->removed)) {
9e5232 ¤   ¤   ¤   userid = userid->next;
920fe4 ¤   ¤   }
746c18 ¤   ¤   if (userid == (PGPUserID *) &key->userIDs) {
0bd001 ¤   ¤   ¤   err = kPGPError_FileCorrupt;
--d588 0008befb31a40100233 Page 7 of pgpKeyUpd.c
a38f0c ¤   ¤   ¤   goto cleanup;
720fe4 ¤   ¤   }
0c7b54 ¤   ¤   cert = (PGPSig *) userid->certs.next;
5d92f3 ¤   ¤   /* Search for the PGPSig object that references obj */
3870db ¤   ¤   while (cert != (PGPSig *) &userid->certs &&
c4bc4b ¤   ¤   ¤   ···!(cert->cert == obj && !cert->removed)) {
234ebe ¤   ¤   ¤   cert = cert->next;
c50fe4 ¤   ¤   }
d51896 ¤   ¤   if (cert != (PGPSig *) &userid->certs)
560106 ¤   ¤   ¤   cert->removed = 1;
5d3684 ¤   ¤   else { ··/* not found */
66d001 ¤   ¤   ¤   err = kPGPError_FileCorrupt;
198f0c ¤   ¤   ¤   goto cleanup;
510fe4 ¤   ¤   }
9b6fe7 ····}
b4af5a
54c5fc ¤   /* ·Re-sort the keylist */
0ca054 ¤   if (type != RINGTYPE_KEY) {
5a764c ¤   ¤   RingSet *changedset;
539c54 ¤   ¤   pgpRingPool = pgpContextGetRingPool( keyDB->context );
1bde5f ¤   ¤   changedset = ringSetCreate (pgpRingPool);
fd9822 ¤   ¤   if (!changedset) {
49c991 ¤   ¤   ¤   err = ringPoolError(pgpRingPool)->error;
4d8f0c ¤   ¤   ¤   goto cleanup;
c50fe4 ¤   ¤   }
7d07cd ¤   ¤   ringSetAddObject (changedset, obj);
08b0bc ¤   ¤   err = pgpKeyDBChanged (keyDB, changedset);
d6dcc0 ¤   ¤   ringSetDestroy (changedset);
899371 ¤   }
2468cb cleanup:
49023b ····if (iter)
772ebe ········ringIterDestroy (iter);
d3ace8 ····return err;
7eefe6 }
42af5a
3faf5a
a20b7f /* ·Add PGPUserID and PGPSig sub-objects attached to a key. ··New·
ca2c3f ····objects are added in same the position at which they are found in·
139e5c ····the source RingSet. ·If the key being added does not exist, it
04d32a ····is created. ·Order of objects in the RingSet must match those in
5e81a3 ····the PGPUserID and PGPSig list.
4daf5a
ccecec ····Note that <addset> can contain multiple keys.
be7fe0 */
d811c9 ¤   ¤   ¤   ¤   ·
39c77d PGPError
889c71 pgpAddObjects (PGPKeyDB *keyDB, RingSet *addset)
a0bb36 {
4f634c ····union RingObject¤   *keyobj = NULL;
5ace8f ····RingIterator¤   *iter = NULL;
6a3439 ····PGPKey¤ ¤   ¤   *key;
570d32 ····PGPError¤   ¤   err = kPGPError_NoErr;
93af5a
a23596 ····pgpa(pgpaPGPKeyDBValid(keyDB));
9eaf5a
7f7637 ····/* Add the new objects to the key database. */
0fcc45 ····ringSetFreeze (addset);
31da60 ····err = keyDB->add(keyDB, addset);
953ad4 ····if (err)
93c7a1 ¤   {
d974a1 ¤   ¤   pgpBuildKeyPool (keyDB, 0);
2814a0 ········return err;
e39371 ¤   }
62591b ····err = pgpBuildKeyPool (keyDB, 0);
8c3ad4 ····if (err)
3e14a0 ········return err;
38af5a
f1a769 ····iter = ringIterCreate (addset);
aec617 ····if (!iter)
5de6e1 ········return ringSetError(addset)->error;
87af5a
8b78ab ····/* Loop for multiple keys to be added */
--b758 00134814d3d40100233 Page 8 of pgpKeyUpd.c
dced9b ····while ((err = (PGPError)ringIterNextObject (iter, 1)) > 0) {
993b25 ········keyobj = ringIterCurrentObject (iter, 1);
d62e19 ¤   ¤   pgpAssert (ringObjectType (keyobj) == RINGTYPE_KEY);
81551a ¤   ¤   key = pgpGetKeyByRingObject (keyDB, keyobj);
a77cc0 ¤   ¤   if (!key) {
30d001 ¤   ¤   ¤   err = kPGPError_FileCorrupt;
e58f0c ¤   ¤   ¤   goto cleanup;
390fe4 ¤   ¤   }
e294d6 ¤   ¤   /* ·if key expanded, update it */
4b9e26 ¤   ¤   if (key->userIDs.next != &key->userIDs) {
3bed89 ¤   ¤   ¤   err = pgpExpandKey (key);
4a5480 ¤   ¤   ¤   if (err)
4d0658 ¤   ¤   ¤   ¤   goto cleanup;
cb0fe4 ¤   ¤   }
c56fe7 ····}
08af5a
47412a ¤   /* Resort as necessary */
b8fc72 ¤   err = pgpKeyDBChanged (keyDB, addset);
f0af5a
3a68cb cleanup:
c4023b ····if (iter)
362ebe ········ringIterDestroy (iter);
d1ace8 ····return err;
ceefe6 }
96af5a
eeaf5a
22af5a
a738e5 /*
3ce6c5 ·* Local Variables:
409b19 ·* tab-width: 4
73e7a4 ·* End:
e8b612 ·* vi: ts=4 sw=4
536c42 ·* vim: si
34495d ·*/
--7e36 000fabbf38240100234 Page 1 of pgpMemDB.c
bc38e5 /*
d5b6df ·* Memory-based implementation of PGPKeyDB
870ff5 ·* This version allows committing changes and thence uses backing store.
5f775e ·*
f394ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
8720c7 ·* All rights reserved
bc775e ·*
37c8d6 ·* $Id: pgpMemDB.c,v 1.17.10.1 1998/11/12 03:22:04 heller Exp $
a0495d ·*/
dcaf5a
a5e2ff #include "pgpConfig.h"
dcaf5a
fdc26c #include "pgpContext.h"
de979a #include "pgpKDBInt.h"
7da146 #include "pgpDebug.h"
08675a #include "pgpTypes.h"
1d0d08 #include "pgpMem.h"
39d11f #include "pgpUsuals.h"
540d6d #include "pgpEnv.h"
8c95a9 #include "pgpMemPool.h"
d226e3 #include "pgpRngPub.h"
d4806a #include "pgpRngRead.h"
4baf5a
f138e5 /*
231c39 ·* Until the first commit, only rsmut and rsfrozen (and bdirty) are used.
24b8d1 ·* Only after that is there backing store.
b2495d ·*/
a515ab typedef struct MemDB
febb36 {
968a97 ¤   PGPContextRef¤  context;
ad5aee ¤   RingFile ······*rfile;¤ ¤   ¤   /* RingFile for backing store */
efce17 ¤   PGPFile ·······*pfile;¤ ¤   ¤   /* PGPFile for backing store */
65f1b5 ¤   RingSet ·······*rsmut;¤ ¤   ¤   /* Mutable ringset */
1420f0 ¤   RingSet const ·*rsimmut;¤   ¤   /* Immutable ringset (from rfile) */
f12503 ¤   RingSet ·······*rsfrozen;¤  ¤   /* Frozen copy of rsmut */
aa9c5a ¤   PGPBoolean ·····bdirty;¤¤   ¤   /* True if rsmut has been changed */
4a9e3a ¤   DEBUG_STRUCT_CONSTRUCTOR( MemDB )
74d891 } MemDB;
5eaf5a
f6af5a
7aed1e /* Close the open memdb object */
b0f1ae static PGPError
1cbd4f doClose (MemDB *mdb)
6abb36 {
6a8a97 ¤   PGPContextRef¤  context;
07af5a
252518 ¤   pgpAssertAddrValid( mdb, MemDB );
7f2700 ¤   context¤= mdb->context;
9467c5 ¤
f0bb71 ¤   if( IsntNull( mdb->rsfrozen ) ) {
0ae52e ¤   ¤   ringSetDestroy( mdb->rsfrozen );
527c1d ¤   ¤   mdb->rsfrozen = NULL;
b19371 ¤   }
853ef7 ¤   if( IsntNull( mdb->rsmut ) ) {
a66948 ¤   ¤   ringSetDestroy (mdb->rsmut);
91df36 ¤   ¤   mdb->rsmut = NULL;
5d9371 ¤   }
29e38e ¤   if( IsntNull( mdb->rfile ) ) {
27ffbe ¤   ¤   ringFileClose (mdb->rfile);
e2f582 ¤   ¤   mdb->rfile = NULL;
c59371 ¤   }
e99fb7 ¤   /* rsimmut is tied to the rfile */
086b6b ¤   mdb->rsimmut = NULL;
11e135 ¤   if( IsntNull( mdb->pfile ) ) {
045066 ¤   ¤   pgpFileClose (mdb->pfile);
800856 ¤   ¤   mdb->pfile = NULL;
059371 ¤   }
8b151e ¤   return kPGPError_NoErr;
17efe6 }
18af5a
81e40f /* Mark as dirty */
fa2978 static void
--fd64 0006e514c1340100234 Page 2 of pgpMemDB.c
9553d1 doMarkDirty (MemDB *mdb)
89bb36 {
aebe05 ¤   mdb->bdirty = TRUE;
dbbb71 ¤   if( IsntNull( mdb->rsfrozen ) ) {
a3e52e ¤   ¤   ringSetDestroy( mdb->rsfrozen );
e37c1d ¤   ¤   mdb->rsfrozen = NULL;
8b9371 ¤   }
4defe6 }
e5af5a
9856b6 static PGPBoolean
a41cfa memDBIsMutable(PGPKeyDB *db)
20bb36 {
816420 ¤   (void)db;¤  /* Avoid warning */
1bc2e7 ¤   return TRUE;
caefe6 }
a9af5a
7156b6 static PGPBoolean
843853 memDBObjIsMutable(PGPKeyDB *db, RingObject *testObj)
6fbb36 {
0d7dc3 ¤   (void)db;¤  ¤   /* Avoid warning */
36352e ¤   (void)testObj;¤ /* Avoid warning */
dbc2e7 ¤   return TRUE;
bbefe6 }
4eaf5a
7c56b6 static PGPBoolean
3bcb66 memDBIsDirty(PGPKeyDB *db)
b5bb36 {
e5b17d ¤   MemDB *¤¤   mdb;
ddaf5a
4fe35d ¤   pgpa(pgpaPGPKeyDBValid(db));
c405a0 ¤   mdb = (MemDB *)db->priv;
639cab ¤   return mdb->bdirty;
b0efe6 }
e6af5a
0c2751 static RingSet const *
aa3d66 memDBGetRingSet(PGPKeyDB *db)
a1bb36 {
83b17d ¤   MemDB *¤¤   mdb;
5dc94e ¤   RingSet ····*newset;
56af5a
6be35d ¤   pgpa(pgpaPGPKeyDBValid(db));
3a05a0 ¤   mdb = (MemDB *)db->priv;
2c0d74 ¤   if( IsNull( mdb->rsfrozen ) ) {
9f2fbd ¤   ····newset = ringSetCreate (ringSetPool (mdb->rsmut));
8af749 ¤   ¤   pgpAssert (newset);
45b9ab ¤   ¤   ringSetAddSet (newset, mdb->rsmut);
295bb8 ¤   ¤   ringSetFreeze (newset);
4bbea7 ¤   ¤   mdb->rsfrozen = newset;
249371 ¤   }
3ef255 ¤   return mdb->rsfrozen;
46efe6 }
1eaf5a
65f1ae static PGPError
9df5e9 memDBAdd(PGPKeyDB *db, RingSet *toAdd)
c3bb36 {
50b17d ¤   MemDB *¤¤   mdb;
00af5a
30e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
ff05a0 ¤   mdb = (MemDB *)db->priv;
780dcc ¤   doMarkDirty( mdb );
07be48 ¤   return (PGPError)ringSetAddSet(mdb->rsmut, toAdd);
12efe6 }
a5af5a
51f1ae static PGPError
7d5b1d memDBChanged(PGPKeyDB *db, RingSet *changedkeys)
6dbb36 {
6ab17d ¤   MemDB *¤¤   mdb;
a8af5a
21e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
ce05a0 ¤   mdb = (MemDB *)db->priv;
2b0dcc ¤   doMarkDirty( mdb );
6e1375 ¤   return pgpReSortKeys (db, changedkeys);
--1488 00020190b7e40100234 Page 3 of pgpMemDB.c
7aefe6 }
46af5a
9cf1ae static PGPError
ec41a7 memDBRemove(PGPKeyDB *db, RingObject *toRemove)
70bb36 {
39b17d ¤   MemDB *¤¤   mdb;
1caf5a
0ce35d ¤   pgpa(pgpaPGPKeyDBValid(db));
ed05a0 ¤   mdb = (MemDB *)db->priv;
c70dcc ¤   doMarkDirty( mdb );
d061a3 ¤   return (PGPError)ringSetRemObject(mdb->rsmut, toRemove);
4defe6 }
a7af5a
4e2978 static void
657adf memDBDestroy(PGPKeyDB *db)
2dbb36 {
21ca12 ¤   MemDB *¤¤   ¤   mdb;
f2ccc0 ¤   PGPContextRef¤  cdkContext¤ = pgpGetKeyDBContext( db );
5caf5a
57ad76 ¤   /* Can't assert pgpaPGPKeyDBValid because refCount == 0 now */
741056 ¤   pgpa((pgpaAddrValid(db, PGPKeyDB),pgpaAssert(db->refCount==0)));
2aaf5a
ad05a0 ¤   mdb = (MemDB *)db->priv;
8274d1 ¤   doClose( mdb );
31f428 ¤   pgpContextMemFree( cdkContext, mdb);
edefe6 }
c0af5a
2738e5 /*
da9680 ·* To do a commit, we write out rsmut to a new PGPFile memory buffer.
39c64c ·* We then close any old backing store, and switch to the new one.
cc495d ·*/
b3f1ae static PGPError
4b6909 memDBCommit (PGPKeyDB *db)
c8bb36 {
40b17d ¤   MemDB *¤¤   mdb;
ed66ac ¤   PGPFile *¤  pfile;
180ac2 ¤   RingFile *¤ rfile;
0b7dd3 ¤   RingSet const *rsimmut;
8e258f ¤   RingSet *¤  rsmut;
e561e0 ¤   PGPError¤   err;
d3af5a
55e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
de05a0 ¤   mdb = (MemDB *)db->priv;
d1af5a
d2d7d9 ¤   pfile = pgpFileMemOpen( mdb->context, NULL, 0 );
bc9f51 ¤   if( IsNull( pfile ) ) {
b04030 ¤   ¤   return kPGPError_OutOfMemory;
099371 ¤   }
e45f6d ¤   /* Make sure rsfrozen exists, and write it out, creating new rfile */
a494fa ¤   memDBGetRingSet( db );
793b43 ¤   err = ringSetWrite( mdb->rsfrozen, pfile, &rfile, PGPVERSION_4,
3f7504 ¤   ¤   ¤   ¤   ¤   ¤   PGP_RINGSETWRITE_EXPORTSIGS );
e800bb ¤   if( IsPGPError( err ) ) {
e1a943 ¤   ¤   pgpFileClose( pfile );
26c9db ¤   ¤   return err;
f99371 ¤   }
d955b6 ¤   pgpFileFlush( pfile );
fb9cf9 ¤   rsimmut = ringFileSet( rfile );
412935 ¤   rsmut = ringSetCreate( ringSetPool( rsimmut ) );
904093 ¤   if( IsNull( rsmut ) ) {
a5e665 ¤   ¤   err = ringSetError( rsimmut )->error;
60ff51 ¤   ¤   ringFileClose( rfile );
36a943 ¤   ¤   pgpFileClose( pfile );
66c9db ¤   ¤   return err;
d09371 ¤   }
06ae9f ¤   ringSetAddSet( rsmut, rsimmut );
e4af5a
12714c ¤   /* Free up previous state and set new values */
6874d1 ¤   doClose( mdb );
8ca7b9 ¤   mdb->rfile = rfile;
6a0056 ¤   mdb->pfile = pfile;
20e411 ¤   mdb->rsimmut = rsimmut;
--c316 0008625d8e340100234 Page 4 of pgpMemDB.c
7dca90 ¤   mdb->rsmut = rsmut;
995ea8 ¤   return err;
b61862 }¤
20af5a
2df1ae static PGPError
0954f3 memDBRevert (PGPKeyDB *db)
8cbb36 {
47ca12 ¤   MemDB *¤¤   ¤   mdb;
79af5a
67e35d ¤   pgpa(pgpaPGPKeyDBValid(db));
b305a0 ¤   mdb = (MemDB *)db->priv;
6baf5a
26dc9e ¤   if( !mdb->bdirty )
8cb840 ¤   ¤   return kPGPError_NoErr;
6aaf5a
86e817 ¤   if( IsNull( mdb->rsimmut ) ) {
f2b29a ¤   ¤   /* Can't revert unless we've done a commit */
7c9a84 ¤   ¤   return kPGPError_IllegalFileOp;
d49371 ¤   }
cf67c5 ¤
0d5420 ¤   ringSetDestroy (mdb->rsmut);
de1f78 ¤   mdb->rsmut = ringSetCreate( ringSetPool( mdb->rsimmut ) );
8688c6 ¤   if( IsNull( mdb->rsmut ) )
0cc7a1 ¤   {
eafde8 ¤   ¤   return ringSetError( mdb->rsimmut )->error;
529371 ¤   }
adf30d ¤   ringSetAddSet( mdb->rsmut, mdb->rsimmut );
83af5a
201529 ¤   if( mdb->rsfrozen )
7dc7a1 ¤   {
7655ca ¤   ¤   ringSetDestroy (mdb->rsfrozen);
6c7c1d ¤   ¤   mdb->rsfrozen = NULL;
f89371 ¤   }
83af5a
816650 ¤   mdb->bdirty = FALSE;
9a151e ¤   return kPGPError_NoErr;
4defe6 }
73af5a
a8af5a
19bce7 /* Creates a new empty memory-based key database */
e1f721 PGPKeyDB *
be3449 pgpKeyDBCreate(PGPContextRef context)
c0bb36 {
29a3f0 ¤   PGPKeyDB *¤ db;
e3b17d ¤   MemDB *¤¤   mdb;
dc804f ¤   RingPool *¤ pgpRingPool;
6baf5a
145a27 ¤   db = pgpKeyDBCreateInternal(context);
19b620 ¤   if (db == NULL)
937ed2 ¤   ¤   return NULL;
dfaf5a
d7f552 ¤   mdb = (MemDB *)pgpContextMemAlloc( context,
a3ca8d ¤   ¤   sizeof( MemDB ), kPGPMemoryMgrFlags_Clear);
ab9c1a ¤   if (mdb == NULL)
06c7a1 ¤   {
1b3de1 ¤   ¤   pgpContextMemFree( context, db);
167ed2 ¤   ¤   return NULL;
f89371 ¤   }
e2660a ¤   mdb->context = context;
9238dc ¤   pgpRingPool = pgpContextGetRingPool( context );
2ce2bd ¤   mdb->rsmut = (RingSet *)ringSetCreate( pgpRingPool );
2faf5a
1ce25a ¤   db->priv = mdb;
122037 ¤   db->typeMagic¤  ¤   = PGPKDBMEMMAGIC;
0c542e ¤   db->fixedMagic¤ ¤   = kPGPKeyDBMagic;
d62af4 ¤   db->isMutable¤  ¤   = memDBIsMutable;
c61704 ¤   db->objIsMutable¤   = memDBObjIsMutable;
6d1847 ¤   db->isDirty¤¤   ¤   = memDBIsDirty;
e906bf ¤   db->getRingSet¤ ¤   = memDBGetRingSet;
c6b3ef ¤   db->add¤¤   ¤   ¤   = memDBAdd;
d6c4d5 ¤   db->changed¤¤   ¤   = memDBChanged;
86f1e4 ¤   db->remove¤ ¤   ¤   = memDBRemove;
--8ab8 0017cd2aea240100234 Page 5 of pgpMemDB.c
c817d5 ¤   db->commit¤ ¤   ¤   = memDBCommit;
df8b38 ¤   db->revert¤ ¤   ¤   = memDBRevert;
a933ed ¤   db->reload¤ ¤   ¤   = memDBRevert;¤ /* same as revert for mem buffers */
572e4d ¤   db->destroy¤¤   ¤   = memDBDestroy;
40af5a
94a20b ¤   pgpKeyDBInitInternal(db);
efaf5a
ae65cc ¤   return db;
97efe6 }
deaf5a
ac38e5 /*
4de6c5 ·* Local Variables:
449b19 ·* tab-width: 4
8be7a4 ·* End:
66b612 ·* vi: ts=4 sw=4
476c42 ·* vim: si
7c495d ·*/
--7941 00008741abc40100235 Page 1 of pgpUnionDB.c
bc38e5 /*
39e0f5 ·* pgpUnionDB.c
d64914 ·* Manage PGPKeyDB's which are unions of others
2f775e ·*
e894ea ·* Copyright (C) 1996,1997 Network Associates, Inc. and its affiliates.
2320c7 ·* All rights reserved
57775e ·*
277de1 ·* $Id: pgpUnionDB.c,v 1.21.10.1 1998/11/12 03:22:05 heller Exp $
e8495d ·*/
67af5a
86e2ff #include "pgpConfig.h"
72af5a
99979a #include "pgpKDBInt.h"
1da146 #include "pgpDebug.h"
2ec26c #include "pgpContext.h"
ccaf5a
44623e /* One list element per unioned PGPKeyDB */
790992 typedef struct UnionDBRec {
4a8d1f ¤   struct UnionDBRec ·¤*next;
f914ab ¤   PGPKeyDB¤   ¤   ¤   *keyDB;
e1be37 } UnionDBRec;
78af5a
cfaf5a
5559f3 /* Private data for union type PGPKeyDB */
7aef6a typedef struct UnionDB
adbb36 {
a63882 ¤   PGPBoolean ····bdirty;
b37b6e ¤   RingSet ·······*rset;
6db770 ¤   UnionDBRec ·¤   ·*udbr;
386dba ¤   DEBUG_STRUCT_CONSTRUCTOR( UnionDB )
7778b8 } UnionDB;
26af5a
a4af5a
baaf5a
3daf5a
c0bf6d /******************** ·Virtual Functions ·************************/
0daf5a
80af5a
ee7145 /* Returns true if any component is mutable */
5156b6 static PGPBoolean
032fae udbIsMutable (PGPKeyDB *kdb)
0cbb36 {
5b2166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
08a3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
d8af5a
df7461 ¤   while (udbr) {
d7badd ¤   ¤   if (((udbr->keyDB)->isMutable)(udbr->keyDB)) {
1cdb98 ¤   ¤   ¤   return 1;
770fe4 ¤   ¤   }
1da886 ¤   ¤   udbr = udbr->next;
509371 ¤   }
533e6b ¤   return 0;
13efe6 }
e8af5a
75828a /* True if object is mutable in any component */
ab56b6 static PGPBoolean
4e5650 udbObjIsMutable (PGPKeyDB *kdb, RingObject *testObj)
03cebb {¤
4f2166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
29a3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
d8af5a
0a7461 ¤   while (udbr) {
2a0fb9 ¤   ¤   if ((udbr->keyDB)->objIsMutable (udbr->keyDB, testObj))
eadb98 ¤   ¤   ¤   return 1;
5ea886 ¤   ¤   udbr = udbr->next;
dc9371 ¤   }
033e6b ¤   return 0;
f4efe6 }
deaf5a
703538 /* Returns true if any component is dirty */
2a56b6 static PGPBoolean
088740 udbIsDirty (PGPKeyDB *kdb) {
--dc1a 0004e0fb16540100235 Page 2 of pgpUnionDB.c
e62166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
18af5a
77eb13 ¤   return udb->bdirty;
75efe6 }
27af5a
3f4e05 /* Mark it dirty */
2c2978 static void
eb6a86 udbDirty (UnionDB *udb)
5abb36 {
430f1b ¤   udb->bdirty = 1;
e9b25f ¤   if (udb->rset) {
c4bdd8 ¤   ¤   ringSetDestroy (udb->rset);
74dc84 ¤   ¤   udb->rset = NULL;
ba9371 ¤   }
34efe6 }
bcaf5a
d0fd44 /* Return a union of all keys in sets */
b42751 static RingSet const *
2859d6 udbGetRingSet (PGPKeyDB *kdb) {
a72166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
bfa3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
58141f ¤   RingSet ········*rset;
b68fd2 ¤   RingSet const ········*rs1;
01af5a
c7af5a
ff1578 ¤   if (udb->rset)
3f1563 ¤   ¤   return udb->rset;
c6af5a
95772e ¤   /* Must construct a new set */
9013eb ¤   rset = NULL;
021578 ¤   if (udb->rset)
65bdd8 ¤   ¤   ringSetDestroy (udb->rset);
2613fd ¤   udbr = udb->udbr;
a47461 ¤   while (udbr) {
4c7fad ¤   ¤   rs1 = (udbr->keyDB)->getRingSet (udbr->keyDB);
41fefe ¤   ¤   pgpAssert (rs1);
bbb33d ¤   ¤   if (!rset) {
e2d0db ¤   ¤   ¤   rset = ringSetCreate (ringSetPool (rs1));
0402ec ¤   ¤   ¤   if (!rset) {
e4cf45 ¤   ¤   ¤   ¤   /* Out of ringsets error */
14fb5e ¤   ¤   ¤   ¤   return NULL;
c4a3a6 ¤   ¤   ¤   }
390fe4 ¤   ¤   }
d761e5 ¤   ¤   ringSetAddSet (rset, rs1);
4ea886 ¤   ¤   udbr = udbr->next;
ae9371 ¤   }
a8236b ¤   ringSetFreeze (rset);
798040 ¤   udb->rset = rset;
1ea428 ¤   return rset;
eeefe6 }
96af5a
6695d7 /*·
069d48 ·* Big problem here - it's hard to tell whether an important
d1a332 ·* key addition failed. ·Could have a writeable pubring but due
a6252c ·* to some error a read-only secring. ·One of our add attempts
406ed1 ·* may return an error due to immutability, but others will succeed.
6ba9ea ·* How to distinguish this from the case of one writeable and one
c7ed90 ·* read-only pubring, which is OK but returns similar status.
5c495d ·*/
2aaf5a
bff1ae static PGPError
126220 udbAdd (PGPKeyDB *kdb, RingSet *toAdd)
e3bb36 {
042166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
51a3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
236936 ¤   PGPError ········err, err1;
37af5a
f12550 ¤   err = err1 = kPGPError_NoErr;
3d7461 ¤   while (udbr) {
3db130 ¤   ¤   err1 = (udbr->keyDB)->add (udbr->keyDB, toAdd);
455b90 ¤   ¤   if (err1)
4e984d ¤   ¤   ¤   err = err1;
--1a3e 0004234c22140100235 Page 3 of pgpUnionDB.c
73a886 ¤   ¤   udbr = udbr->next;
df9371 ¤   }
800c9c ¤   udbDirty (udb);
c85ea8 ¤   return err;
0fefe6 }
13af5a
f9f1ae static PGPError
a56161 udbRemove (PGPKeyDB *kdb, RingObject *toRemove)
09bb36 {
022166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
b5a3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
fb97eb ¤   PGPError ········err, err1; ···········
23af5a
3e2550 ¤   err = err1 = kPGPError_NoErr;
b37461 ¤   while (udbr) {
eeaad7 ¤   ¤   err1 = (udbr->keyDB)->remove (udbr->keyDB, toRemove);
385b90 ¤   ¤   if (err1)
bd984d ¤   ¤   ¤   err = err1;
03a886 ¤   ¤   udbr = udbr->next;
db9371 ¤   }
400c9c ¤   udbDirty (udb);
415ea8 ¤   return err;
bdefe6 }
90af5a
def1ae static PGPError
0f190d udbChanged (PGPKeyDB *kdb, RingSet *changedkeys)
b0bb36 {
ba2166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
e7a3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
946936 ¤   PGPError ········err, err1;
e567c5 ¤
002550 ¤   err = err1 = kPGPError_NoErr;
5c7461 ¤   while (udbr) {
2bac30 ¤   ¤   err1 = (udbr->keyDB)->changed (udbr->keyDB, changedkeys);
c75b90 ¤   ¤   if (err1)
1d984d ¤   ¤   ¤   err = err1;
eea886 ¤   ¤   udbr = udbr->next;
bb9371 ¤   }
dc0c9c ¤   udbDirty (udb);
ae89ad ¤   err1 = pgpReSortKeys (kdb, changedkeys);
dede25 ¤   if (err1)
62e2b9 ¤   ¤   err = err1;
275ea8 ¤   return err;
2aefe6 }
48af5a
c7f1ae static PGPError
27ecf1 udbCommit (PGPKeyDB *kdb)
c5bb36 {
aa2166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
4aa3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
4997eb ¤   PGPError ········err, err1; ···········
3caf5a
936493 ¤   err = kPGPError_NoErr;
de7461 ¤   while (udbr) {
31a919 ¤   ¤   err1 = (udbr->keyDB)->commit (udbr->keyDB);
6e5b90 ¤   ¤   if (err1)
36984d ¤   ¤   ¤   err = err1;
06a886 ¤   ¤   udbr = udbr->next;
049371 ¤   }
0e55c7 ¤   udb->bdirty = 0;
5bd36b ¤   /* Committing can eliminate redundant secret objects. */
aa069a ¤   /* We need to re-create our rset afterwards */
13b25f ¤   if (udb->rset) {
c3bdd8 ¤   ¤   ringSetDestroy (udb->rset);
b0d2d0 ¤   ¤   udb->rset = 0;
d09371 ¤   }
aa5ea8 ¤   return err;
81efe6 }
feaf5a
0ef1ae static PGPError
89b419 udbRevert (PGPKeyDB *kdb)
42bb36 {
--1f25 00032830bd240100235 Page 4 of pgpUnionDB.c
e62166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
eaa3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
1697eb ¤   PGPError ········err, err1; ···········
95af5a
8b6493 ¤   err = kPGPError_NoErr;
a37461 ¤   while (udbr) {
8694e3 ¤   ¤   err1 = (udbr->keyDB)->revert (udbr->keyDB);
1f5b90 ¤   ¤   if (err1)
93984d ¤   ¤   ¤   err = err1;
b6a886 ¤   ¤   udbr = udbr->next;
589371 ¤   }
8a55c7 ¤   udb->bdirty = 0;
c6b25f ¤   if (udb->rset) {
fabdd8 ¤   ¤   ringSetDestroy (udb->rset);
f3d2d0 ¤   ¤   udb->rset = 0;
279371 ¤   }
c85ea8 ¤   return err;
c0efe6 }
dbaf5a
5af1ae static PGPError
f64c64 udbReload (PGPKeyDB *kdb)
cbbb36 {
802166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
92a3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
2c97eb ¤   PGPError ········err, err1; ···········
95af5a
fa6493 ¤   err = kPGPError_NoErr;
7d7461 ¤   while (udbr) {
6f1eec ¤   ¤   err1 = (udbr->keyDB)->reload (udbr->keyDB);
e25b90 ¤   ¤   if (err1)
5b984d ¤   ¤   ¤   err = err1;
afa886 ¤   ¤   udbr = udbr->next;
0b9371 ¤   }
b655c7 ¤   udb->bdirty = 0;
ccb25f ¤   if (udb->rset) {
03bdd8 ¤   ¤   ringSetDestroy (udb->rset);
82d2d0 ¤   ¤   udb->rset = 0;
ce9371 ¤   }
255ea8 ¤   return err;
d9efe6 }
1daf5a
6e2978 static void
42eb25 udbDestroy (PGPKeyDB *kdb)
7abb36 {
da2166 ¤   UnionDB ········*udb = (UnionDB *)kdb->priv;
4ea3b5 ¤   UnionDBRec ·····*udbr = udb->udbr;
486a8b ¤   UnionDBRec ·····*udbrnext;
dd99fb ¤   PGPContextRef¤  context¤= pgpGetKeyDBContext( kdb );
8eaf5a
b41578 ¤   if (udb->rset)
3fc7a1 ¤   {
c6bdd8 ¤   ¤   ringSetDestroy (udb->rset);
30d2d0 ¤   ¤   udb->rset = 0;
a59371 ¤   }
384e7b ¤   while (udbr)
66c7a1 ¤   {
522697 ¤   ¤   pgpFreeKeyDB (udbr->keyDB);
396e28 ¤   ¤   udbrnext = udbr->next;
ff50d4 ¤   ¤   pgpContextMemFree( context, udbr);
bcfc4f ¤   ¤   udbr = udbrnext;
d29371 ¤   }
2951f8 ¤   pgpContextMemFree( context, udb);
f8efe6 }
d5af5a
52af5a
feb24e /**************************** ·Constructor ·**************************/
b8af5a
5baf5a
a9f721 PGPKeyDB *
f81d33 pgpCreateUnionKeyDB (PGPContextRef context, PGPError *error)
54bb36 {
32891e ¤   PGPKeyDB ······*kdb;
--77c4 001fbd0cba540100235 Page 5 of pgpUnionDB.c
34a8a1 ¤   UnionDB ·······*udb;
afaf5a
639096 ¤   *error = kPGPError_NoErr;
51c175 ¤   kdb = pgpKeyDBCreateInternal (context);
a61c34 ¤   if (!kdb) {
86e2ed ¤   ¤   *error = kPGPError_OutOfMemory;
447ed2 ¤   ¤   return NULL;
789371 ¤   }
762d04 ¤   udb = (UnionDB *) pgpContextMemAlloc( context,
fe1ef2 ¤   ¤   sizeof (UnionDB), kPGPMemoryMgrFlags_Clear );
7f2fdc ¤   if (!udb) {
1fe2ed ¤   ¤   *error = kPGPError_OutOfMemory;
cae534 ¤   ¤   pgpKeyDBDestroyInternal (kdb);
82ef86 ¤   ¤   return( NULL );
0f9371 ¤   }
66af5a
a5c69a ¤   kdb->priv ···¤  = udb;
92be51 ¤   kdb->typeMagic¤ ¤   = PGPKDBUNIONMAGIC;
d17528 ¤   kdb->fixedMagic¤¤   = kPGPKeyDBMagic;
fdf107 ¤   kdb->isMutable ·¤   = udbIsMutable;
7e71c5 ¤   kdb->objIsMutable¤  = udbObjIsMutable;
b4a1e3 ¤   kdb->isDirty ···¤   = udbIsDirty;
2f74b4 ¤   kdb->getRingSet¤¤   = udbGetRingSet;
c3f6cc ¤   kdb->add ·······¤   = udbAdd;
969219 ¤   kdb->remove ····¤   = udbRemove;
8863a8 ¤   kdb->changed¤   ¤   = udbChanged;
fff32d ¤   kdb->commit ····¤   = udbCommit;
afb7b4 ¤   kdb->revert ····¤   = udbRevert;
6d082f ¤   kdb->reload ····¤   = udbReload;
c04bd5 ¤   kdb->destroy¤   ¤   = udbDestroy;
c0af5a
265ecf ¤   pgpKeyDBInitInternal(kdb);
edaf5a
3e32be ¤   return kdb;
e6efe6 }
e3af5a
87c77d PGPError
fd881f pgpUnionKeyDBAdd (PGPKeyDB *kdb, PGPKeyDB *kdbnew)
d1bb36 {
f6f41d ¤   UnionDBRec ····*udbr;
3c701a ¤   UnionDB ·······*udb = (UnionDB *)kdb->priv;
5099fb ¤   PGPContextRef¤  context¤= pgpGetKeyDBContext( kdb );
53af5a
c6c591 ¤   udbr = (UnionDBRec *) pgpContextMemAlloc(
329963 ¤   ¤   context, sizeof (UnionDBRec), kPGPMemoryMgrFlags_Clear);
a2b197 ¤   if (!udbr)
cfc7a1 ¤   {
c04030 ¤   ¤   return kPGPError_OutOfMemory;
359371 ¤   }
bfaf5a
af3b89 ¤   udbr->keyDB = kdbnew;
7f329b ¤   udbr->next = udb->udbr;
625ec2 ¤   udb->udbr = udbr;
41af5a
16151e ¤   return kPGPError_NoErr;
a0efe6 }
baaf5a
5938e5 /*
77e6c5 ·* Local Variables:
fc9b19 ·* tab-width: 4
7be7a4 ·* End:
c1b612 ·* vi: ts=4 sw=4
2f6c42 ·* vim: si
fb495d ·*/
--3de9 000e2c8509b40100236 Page 1 of pgpUnionSet.c
bc38e5 /*
1d4348 ·* pgpUnionSet.c
d36683 ·* Arbitrary union variant of PGPKeySet.
95775e ·*
edbbeb ·* Copyright (C) 1997 Network Associates, Inc. and its affiliates.
3e20c7 ·* All rights reserved
6e775e ·*
7983a2 ·* $Id: pgpUnionSet.c,v 1.2.12.1 1998/11/12 03:22:06 heller Exp $
16495d ·*/
8eaf5a
d4e2ff #include "pgpConfig.h"
2eaf5a
a3ef82 #ifdef HAVE_STDLIB_H
39bea3 #include <stdlib.h>
027454 #endif
c1af5a
7b324c #include <string.h>
52b1cb #include <ctype.h>
bfaf5a
e8979a #include "pgpKDBInt.h"
f7a146 #include "pgpDebug.h"
962f8d #include "pgpErrors.h"
2a675a #include "pgpTypes.h"
570d08 #include "pgpMem.h"
74c26c #include "pgpContext.h"
6faf5a
83af5a
d04a08 /* Private data for the arbitrary union variant of PGPKeySet */
b8f06a typedef struct UnionSetPriv
2cbb36 {
d7a575 ¤   PGPKeySetRef¤   set1;
384a11 ¤   PGPKeySetRef¤   set2;
58f881 } UnionSetPriv;
93af5a
97af5a
6938e5 /*
7e6a75 ·* Check to see if a key is a member of an enumerated subset
80495d ·*/
f36c2c ¤   static PGPBoolean
f4fd21 IsMemberOfUnionSet(
13833d ¤   PGPKeySetRef¤   ¤   set,
139e39 ¤   RingObject *¤   ¤   obj)
f7bb36 {
edef41 ¤   UnionSetPriv *¤ ¤   priv = (UnionSetPriv *)set->priv;
acaf5a
aa5e68 ¤   pgpa((
3be8b8 ¤   ¤   pgpaPGPKeySetValid(set),
d80d53 ¤   ¤   pgpaAddrValid(priv, UnionSetPriv),
ebbf04 ¤   ¤   pgpaAddrValid(obj, VoidAlign)));
4faf5a
bb2883 ¤   return (priv->set1->isMember(priv->set1, obj)
0ce59f ¤   ¤   ·|| priv->set2->isMember(priv->set2, obj));
10efe6 }
96af5a
c233c8 ¤   static void
d724d8 DestroyUnionSet(
f6fd85 ¤   PGPKeySetRef¤   ¤   set)
35bb36 {
faef41 ¤   UnionSetPriv *¤ ¤   priv = (UnionSetPriv *)set->priv;
3eaf5a
fd5e68 ¤   pgpa((
7788c6 ¤   ¤   pgpaAddrValid(set, PGPKeySet),
ae5d22 ¤   ¤   pgpaAddrValid(priv, UnionSetPriv)));
8caf5a
223e0a ¤   PGPFreeKeySet(priv->set1);
541bc7 ¤   PGPFreeKeySet(priv->set2);
5aefe6 }
d5af5a
4ec744 ¤   PGPError
e6ecd2 pgpGenericUnionOfKeySets(
d348b6 ¤   PGPKeySetRef¤   ¤   set1,
e2a7d2 ¤   PGPKeySetRef¤   ¤   set2,
--cacc 001267cabc340100236 Page 2 of pgpUnionSet.c
9c6641 ¤   PGPKeySetRef *¤ ¤   newSet)
05bb36 {
052b13 ¤   PGPContextRef¤  ¤   context¤= PGPGetKeySetContext(set1);
3b06bb ¤   UnionSetPriv *¤ ¤   priv;
f75ba4 ¤   PGPKeySetRef¤   ¤   set;
0d8f52 ¤   PGPError¤   ¤   ¤   err;
7daf5a
985049 ¤   *newSet = NULL;¤¤   /* In case there's an error */
58af5a
67e069 ¤   priv = (UnionSetPriv *)pgpContextMemAlloc(context,
173a6f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(*priv), kPGPMemoryMgrFlags_Clear);
665786 ¤   if (IsNull(priv))
de4030 ¤   ¤   return kPGPError_OutOfMemory;
ebaf5a
afcba5 ¤   priv->set1 = set1;
2150a8 ¤   priv->set2 = set2;
50af5a
5403ff ¤   err = pgpNewKeySetInternal(set1->keyDB, &set);
fc82f0 ¤   if (IsPGPError(err))
41c9db ¤   ¤   return err;
8867c5 ¤
9ecf45 ¤   pgpAssertAddrValid(set, PGPKeySet);
80af5a
af1ac4 ¤   set->priv = priv;
87006c ¤   set->isMember = IsMemberOfUnionSet;
725a61 ¤   set->makeUnion = NULL;
a9c260 ¤   set->destroy = DestroyUnionSet;
1daf5a
c0f9b6 ¤   PGPIncKeySetRefCount(set1);
15dc7b ¤   PGPIncKeySetRefCount(set2);
e9af5a
509fa7 ¤   *newSet = set;
5d151e ¤   return kPGPError_NoErr;
06efe6 }
7aaf5a
9f7e4d /*__Editor_settings____
97af5a
934126 ¤   Local Variables:
ed7b17 ¤   tab-width: 4
490e6c ¤   End:
585f8c ¤   vi: ts=4 sw=4
e79e9b ¤   vim: si
26d062 _____________________*/
--8e4a 00034394f9f40100237 Page 1 of pgpX509Keys.c
bc38e5 /*
a71f31 ·* X509 Key importing
41775e ·*
80f923 ·* Copyright (C) 1996,1997,1998 Network Associates, Inc. and its affiliates.
ed20c7 ·* All rights reserved
1f775e ·*
c0e593 ·* $Id: pgpX509Keys.c,v 1.15.2.1.2.1 1998/11/12 03:22:07 heller Exp $
44495d ·*/
83af5a
41e2ff #include "pgpConfig.h"
ccaf5a
c4ef82 #ifdef HAVE_STDLIB_H
eabea3 #include <stdlib.h>
c87454 #endif
f0af5a
59324c #include <string.h>
36b1cb #include <ctype.h>
a0af5a
ec979a #include "pgpKDBInt.h"
11675a #include "pgpTypes.h"
4fa146 #include "pgpDebug.h"
bb0d08 #include "pgpMem.h"
4e26e3 #include "pgpRngPub.h"
327a44 #include "pgpRngPriv.h"
4b806a #include "pgpRngRead.h"
5cc26c #include "pgpContext.h"
36af5a
53d2c2 #include "pgpX509Priv.h"
135417 #include "pgpHashPriv.h"
79cdc2 #include "pgpPubKey.h"
a10141 #include "pgpOptionListPriv.h"
679c38 #include "pgpPktByte.h"
012ece #include "pgpPipeline.h"
ba3709 #include "pgpFileMod.h"
598b0d #include "pgpEncodePriv.h"
0f45ee #include "pgpVMemMod.h"
7c6aaa #include "pgpAnnotate.h"
edf5ab #include "pgpSigSpec.h"
dd2266 #include "pgpTimeDate.h"
3caf5a
05fdaa /* Whether or not to use short forms for X509 name conversions */
892aaf #ifndef PGP_X509SHORTNAMES
d95338 #define PGP_X509SHORTNAMES 1
6b7454 #endif
beaf5a
01af5a
e26c40 /* Error returns */
095108 #define k509Error_NeededCertNotAvailable¤   ¤   ¤   -10
b6d022 #define k509Error_SelfSignedCert¤   ¤   ¤   ¤   ¤   -20
0ff0e7 #define k509Error_InvalidCertificateSignature¤  ¤   -30
f202dd #define k509Error_InvalidCertificateFormat¤ ¤   ¤   -40
f2af5a
ffaf5a
286328 /* Size limit on cert */
948ec0 #define MAX_509_CERT_SIZE¤  ¤   65536
c6af5a
bf5076 /* Commonly used tag values */
19cc55 #define TAG_ZERO¤   ¤   0
59bbb8 #define TAG_INTEGER¤¤   2
c1fcf1 #define TAG_BITSTRING¤  3
a52666 #define TAG_OCTETSTRING¤4
052b19 #define TAG_NULL¤   ¤   5
f04424 #define TAG_OBJECT¤ ¤   6
90f24d #define TAG_SEQUENCE¤   16
a205db #define¤TAG_SET¤¤   ¤   17
a0207c #define TAG_PRINTABLE¤  19
4c28ac #define TAG_T61STRING¤  20
16de2d #define TAG_IA5STRING¤  22
860c4b #define TAG_UTCTIME¤¤   23
46af5a
34af5a
34f805 #define elemsof(arr) ·(sizeof(arr)/sizeof(arr[0]))
--3d9f 000065b2e7240100237 Page 2 of pgpX509Keys.c
e0af5a
f28831 #define EXPECT(t, v)¤   if (t != v) { \
5ce8e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_X509InvalidCertificateFormat; \
33b6ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   goto error; \
76db3c ¤   ¤   ¤   ¤   ¤   ¤   }
ccaf5a
3792cd /* RSA OID is (1, 2, 840, 113549, 1, 1, 1) */
7cea9d static PGPByte const rsaoid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
a34f63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··0x0d, 0x01, 0x01, 0x01};
5c971b /* RSA with MD5 OID is (1, 2, 840, 113549, 1, 1, 4) */
42b349 static PGPByte const rsamd5oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
db2134 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··0x0d, 0x01, 0x01, 0x04};
024ff7 /* RSA with MD2 OID is (1, 2, 840, 113549, 1, 1, 2) */
ac99ef static PGPByte const rsamd2oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
b86aae ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··0x0d, 0x01, 0x01, 0x02};
07c19c /* DSA OID is (1, 2, 840, 10040, 4, 1) */
fbe2bd static PGPByte const dsaoid[] = {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01};
f614be /* DSA with SHA-1 OID is (1, 2, 840, 10040, 4, 3) */
a8d77e static PGPByte const dsashaoid[] = {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x03};
0caf5a
189360 /* ElG OID is (1, 2, 840, 10046, 2, 1) */
c2949f static PGPByte const elgoid[] = {0x2a, 0x86, 0x48, 0xce, 0x3e, 0x02, 0x01};
84af5a
cab2de /* CN (common-name) OID is (2, 5, 4, 3) */
76bbc2 static PGPByte const cnoid[] = {0x55, 0x04, 0x03};
acd0af /* RSA's OID for email address in RDN's: (1, 2, 840, 113549, 1, 9, 1) */
ba723f static PGPByte const emailoid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
b4b748 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0x09, 0x01};
f3bfde static const char emailname[] = "EMAIL";
3aaf5a
4caf5a
3ba21b /* Table to convert DN field OID's to letter codes per RFC2253 */
af0fbb /* Indexed by the last value in a (2, 5, 4, X) OID */
6e504f static const char *dnnames[] = {
ab3c68 ¤   NULL, NULL, NULL,
c48c0b ¤   "CN",¤  ¤   ¤   /* 3 == commonName */
28583c ¤   NULL, NULL,
41c351 ¤   "C",¤   ¤   ¤   /* 6 == countryName */
d09ffd ¤   "L",¤   ¤   ¤   /* 7 == localityName */
210cf7 ¤   "ST",¤  ¤   ¤   /* 8 == stateOrProvinceName */
f5e0b5 ¤   "STREET",¤  ¤   /* 9 == streetAddress */
0a71f7 ¤   "O",¤   ¤   ¤   /* 10 == organizationName */
55807b ¤   "OU",¤  ¤   ¤   /* 11 == organizationalUnitName */
1e82f7 };
5baf5a
90af5a
013600 #if PRINTDEBUG509
52877f /* Used for debugging, to print out the tags as we see them */
2a4b17 static struct {
4bf2a6 ¤   int tag;
782d7d ¤   char *name;
65dc5f } const tagnames[] = {
167c98 ¤   {TAG_INTEGER,¤  ¤   "Integer"},
a4eec5 ¤   {TAG_BITSTRING,¤¤   "Bitstring"},
28b652 ¤   {TAG_OCTETSTRING,¤  "Octetstring"},
1875e3 ¤   {TAG_NULL,¤ ¤   ¤   "Null"},
fa99fa ¤   {TAG_OBJECT,¤   ¤   "Object"},
a06093 ¤   {TAG_SEQUENCE,¤ ¤   "Sequence"},
aae8c9 ¤   {TAG_SET,¤  ¤   ¤   "Set"},
4e1030 ¤   {TAG_PRINTABLE,¤¤   "Printablestring"},
d2d403 ¤   {TAG_T61STRING,¤¤   "T61string"},
b4be0f ¤   {TAG_IA5STRING,¤¤   "IA5string"},
b54b12 ¤   {TAG_UTCTIME,¤  ¤   "UTCTime"}
8982f7 };
217454 #endif
41af5a
f0af5a
2baf5a
843600 #if PRINTDEBUG509
092978 static void
23340a printtagname (int tag)
06bb36 {
--8aa5 00054743f7440100237 Page 3 of pgpX509Keys.c
6e4ba4 ¤   int i;
f27164 ¤   int printed = 0;
c47d8c ¤   printf ("0x%02x", tag);
53d449 ¤   for (i=0; i<sizeof(tagnames)/sizeof(tagnames[0]); ++i) {
750db8 ¤   ¤   if (tagnames[i].tag == tag) {
48a768 ¤   ¤   ¤   printf (" (%s)", tagnames[i].name);
79c5d4 ¤   ¤   ¤   printed = 1;
a0cdcb ¤   ¤   ¤   break;
a30fe4 ¤   ¤   }
eb9371 ¤   }
da088b ¤   if (!printed)
adc49f ¤   ¤   printf ("(<Unknown>)");
3fefe6 }
447454 #endif
92af5a
fb0bc3 /* Return bit number of highest bit in byte */
febeb7 static int
ebdcc2 hibit(int n)
7dbb36 {
bb488b ¤   int bit = 7;
1f74d6 ¤   int val = 0x80;
38af5a
ea9fce ¤   if (n == 0)
63043c ¤   ¤   return -1;
d92db9 ¤   while ((val & n) == 0) {
25b605 ¤   ¤   val >>= 1;
c79624 ¤   ¤   --bit;
0d9371 ¤   }
dfbb19 ¤   return bit;
00efe6 }
89af5a
eaaf5a
72620e /* Read start of an X.509 object */
94beb7 static int
a9d388 dotaglen(PGPByte **buf, PGPSize *length)
91bb36 {
3c1969 ¤   PGPByte tag = *(*buf)++ & 0x1f;
01b21b ¤   PGPSize len = *(*buf)++;
61de77 ¤   if (len & 0x80) {
66fc1a ¤   ¤   PGPByte lenlen = len & 0x7f;
8a5b71 ¤   ¤   len = 0;
236f5c ¤   ¤   while (lenlen--) {
c963b4 ¤   ¤   ¤   len <<= 8;
c133ec ¤   ¤   ¤   len |= *(*buf)++;
7f0fe4 ¤   ¤   }
b39371 ¤   }
e45c15 ¤   *length = len;
b23600 #if PRINTDEBUG509
22bafb printf ("tag ");
e07491 printtagname(tag);
d2cbd0 printf (", length 0x%x\n", len);
927454 #endif
3abbe8 ¤   return tag;
05efe6 }
f4af5a
11da1b /* Read a three byte value and skip past it */
c6beb7 static int
170957 dolen3(PGPByte **buf)
20bb36 {
8af234 ¤   int len;
658421 ¤   len = *(*buf)++;
65bafe ¤   len <<= 8;
007d0d ¤   len |= *(*buf)++;
0bbafe ¤   len <<= 8;
287d0d ¤   len |= *(*buf)++;
71bb7a ¤   return len;
97efe6 }
60af5a
75af5a
b038e5 /*
2f24e7 ·* Given an X509 integer (pointing past the tag/length), return a PGP
5436e0 ·* format MPI number. ·If the mpbuf pointer is NULL, just return the len.
--48c6 00092d3267d40100237 Page 4 of pgpX509Keys.c
15cac3 ·* If non-NULL, *mplen must equal the required length.
98495d ·*/
20f1ae static PGPError
5dcef5 sDecodeX509Integer (PGPByte const *buf, PGPSize len,
2bba8a ¤   ¤   PGPByte *mpbuf, PGPSize *mplen)
b2bb36 {
1bcb9c ¤   PGPUInt32 bits;
8f67c5 ¤
fc60e3 ¤   /* Skip past any zero padding */
620e48 ¤   while (*buf == '\0' && len > 0) {
9ab2ab ¤   ¤   ++buf;
b59647 ¤   ¤   --len;
ab9371 ¤   }
6367c5 ¤
08d318 ¤   /* Must be at least 1 byte long */
7783f3 ¤   if (len == 0)
b40806 ¤   ¤   return kPGPError_X509InvalidCertificateFormat;
f5af5a
5e6792 ¤   /* Set MPI with bitcount prefix */
7ade47 ¤   if( IsNull( mpbuf ) ) {
1ad57f ¤   ¤   *mplen = len + 2;
51b840 ¤   ¤   return kPGPError_NoErr;
0d9371 ¤   }
3aaf5a
15630f ¤   pgpAssert (len + 2 == *mplen);
331b52 ¤   ¤
e5cdf8 ¤   bits = (len-1) * 8 + hibit(*buf) + 1;
de7f61 ¤   mpbuf[0] = (PGPByte)(bits >> 8);
70c8f1 ¤   mpbuf[1] = (PGPByte)(bits >> 0);
51fc25 ¤   pgpCopyMemory( buf, mpbuf+2, len);
98af5a
ac151e ¤   return kPGPError_NoErr;
86efe6 }
4daf5a
f0af5a
a238e5 /*
9c3877 ·* Decode the given UTCTime buffer into a standard PGP timestamp
79495d ·*/
59f1ae static PGPError
99f7e7 sDecodeUTCTime (PGPByte const *buf, PGPSize len, PGPUInt32 *timestamp)
7bbb36 {
85baa7 ¤   PGPUInt32 datefield[6];¤¤   /* year, month, day, hour, min, second */
0451fc ¤   PGPUInt32 i;
d3e0c3 ¤   PGPUInt32 tstamp;
20c55b ¤   PGPError err = kPGPError_NoErr;
81af5a
7814cd ¤   pgpAssert( IsntNull( timestamp ) );
3665bd ¤   *timestamp = 0;
91af5a
252f90 ¤   pgpClearMemory (datefield, sizeof(datefield));
73af5a
d60191 ¤   for (i=0; i<elemsof(datefield); ++i) {
ea6933 ¤   ¤   if (len < 2 || !isdigit(buf[0]))
6ecdcb ¤   ¤   ¤   break;
0ed40f ¤   ¤   if (!isdigit(buf[1])) {
cb572b ¤   ¤   ¤   err = kPGPError_X509InvalidCertificateFormat;
7ded19 ¤   ¤   ¤   goto error;
220fe4 ¤   ¤   }
13eeaa ¤   ¤   datefield[i] = (buf[0]-'0') * 10 + (buf[1] - '0');
3dfc67 ¤   ¤   buf += 2;
54b74e ¤   ¤   len -= 2;
969371 ¤   }
2d2af5 ¤   if (len != 1 ·|| ·buf[0] != 'Z' ·|| ·i < 5) {
55545c ¤   ¤   err = kPGPError_X509InvalidCertificateFormat;
1797ed ¤   ¤   goto error;
c29371 ¤   }
3467c5 ¤
523303 ¤   /* Correct for Y2K problem */
dd8df9 ¤   datefield[0] += (datefield[0] > 50) ? 1900 : 2000;
25af5a
9280cb ¤   /* Get seconds since Jan 1, 1970 */
92c23f ¤   tstamp = pgpDateFromYMD (datefield[0], datefield[1], datefield[2]);
--5d15 000f4579c2a40100237 Page 5 of pgpX509Keys.c
c099de ¤   tstamp = (((tstamp*24 + datefield[3]) * 60) + datefield[4]) * 60
64ce4e ¤   ¤   + datefield[5];
14af5a
ff8631 ¤   *timestamp = tstamp;
9daf5a
8460ff error:
cfaf5a
f65ea8 ¤   return err;
e0efe6 }
ecaf5a
26af5a
e995d7 /*·
d6bf94 ·* TRUE if given DN string needs quoting per RFC1779.
d016d8 ·* Also return the number of internal backslashes needed.
e5495d ·*/
4356b6 static PGPBoolean
f4fad1 sNeedsDNQuoting(PGPByte const *buf, PGPSize length, PGPUInt32 *nslashes)
afbb36 {
17200f ¤   PGPByte c='\0', prevc='\0';
f1ce24 ¤   PGPUInt32 nslash = 0;
86c29b ¤   PGPBoolean outerquote = FALSE;
4eaf5a
f1526e ¤   if (*buf==' ')
537990 ¤   ¤   outerquote = TRUE;
ffa67a ¤   while (length--) {
9ae58f ¤   ¤   prevc = c;
be3800 ¤   ¤   c = *buf++;
8508f5 ¤   ¤   if (c==',' || c=='=' || c=='\r' || c=='+' || c=='<'
5da78b ¤   ¤   ¤   || c=='>' || c=='#' || c==';')
906db8 ¤   ¤   ¤   outerquote = TRUE;
4b7836 ¤   ¤   if (c==' ' && prevc==' ')
f56db8 ¤   ¤   ¤   outerquote = TRUE;
a74122 ¤   ¤   if (c=='"' || c=='\\')
90fba7 ¤   ¤   ¤   ++nslash;
8b9371 ¤   }
d4289b ¤   if (prevc==' ')
be7990 ¤   ¤   outerquote = TRUE;
d32027 ¤   if (IsntNull (nslashes) )
666cd8 ¤   ¤   *nslashes = nslash;
42186c ¤   return outerquote;
14efe6 }
d5af5a
10af5a
fc38e5 /*
ab3cfc ·* If out is non-NULL, apply RFC1779 DNS quoting to buf, outputting to out.
9703c9 ·* In either case, return the length of what the output string would be.
c409d3 ·* If the rev flag is set, out points at the end of the output buffer rather
a376b5 ·* than at the beginning.
3b495d ·*/
aa58ef static PGPUInt32
57eefd sDNQuoteString(PGPByte const *buf, PGPSize len, PGPByte *out, PGPBoolean rev)
fcbb36 {
8e4838 ¤   PGPUInt32 outlen;
8e1943 ¤   PGPBoolean needouterquote;
60a508 ¤   PGPByte c;
ebaf5a
b75a07 ¤   needouterquote = sNeedsDNQuoting( buf, len, &outlen);
2747fd ¤   outlen += len + (needouterquote ? 2 : 0);
157ec8 ¤   if (IsNull( out ))
b1c48f ¤   ¤   return outlen;
dcd3e7 ¤   if (rev)
d6148a ¤   ¤   out -= outlen;
1394f2 ¤   if (needouterquote)
26b2db ¤   ¤   *out++ = '"';
e9cae5 ¤   while (len--) {
383800 ¤   ¤   c = *buf++;
e84122 ¤   ¤   if (c=='"' || c=='\\')
184400 ¤   ¤   ¤   *out++ = '\\';
094e99 ¤   ¤   *out++ = c;
cd9371 ¤   }
7e94f2 ¤   if (needouterquote)
f4b2db ¤   ¤   *out++ = '"';
--f00b 000947a221240100237 Page 6 of pgpX509Keys.c
53ff66 ¤   return outlen;
8aefe6 }
4faf5a
92af5a
f738e5 /*
77150e ·* Called pointing at the OID for an algorithm identifier, see if it is one
f1306e ·* we know.
0d495d ·*/
cef1ae static PGPError
a6c6c6 sDecodeAlgorithmOID (PGPByte const *buf, PGPSize len,
bccba9 ¤   PGPPublicKeyAlgorithm *keyalgorithm, PGPHashAlgorithm *hashalgorithm)
40bb36 {
8cc55b ¤   PGPError err = kPGPError_NoErr;
a4af5a
c0bbe7 ¤   if( IsntNull( keyalgorithm ) )
59c051 ¤   ¤   *keyalgorithm = (PGPPublicKeyAlgorithm) 0;
3daf5a
8b0a30 ¤   if( IsntNull( hashalgorithm ) )
3d5eb2 ¤   ¤   *hashalgorithm = (PGPHashAlgorithm) 0;
95af5a
0e1694 ¤   if (len == sizeof(rsaoid) && memcmp (buf, rsaoid, len) == 0) {
69fa14 ¤   ¤   if( IsntNull( keyalgorithm ) )
67c9ea ¤   ¤   ¤   *keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
2539f4 ¤   } else if (len == sizeof(rsamd5oid) && memcmp (buf, rsamd5oid, len) == 0) {
77cf65 ¤   ¤   if( IsntNull( hashalgorithm ) )
05c231 ¤   ¤   ¤   *hashalgorithm = kPGPHashAlgorithm_MD5;
0cfa14 ¤   ¤   if( IsntNull( keyalgorithm ) )
35c9ea ¤   ¤   ¤   *keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
4f6d39 ¤   } else if (len == sizeof(rsamd2oid) && memcmp (buf, rsamd2oid, len) == 0) {
15cf65 ¤   ¤   if( IsntNull( hashalgorithm ) )
164761 ¤   ¤   ¤   *hashalgorithm = (PGPHashAlgorithm) kPGPHashAlgorithm_MD2;
1afa14 ¤   ¤   if( IsntNull( keyalgorithm ) )
b4c9ea ¤   ¤   ¤   *keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
4ef7cc ¤   } else if (len == sizeof(dsaoid) && memcmp (buf, dsaoid, len) == 0) {
e9fa14 ¤   ¤   if( IsntNull( keyalgorithm ) )
984632 ¤   ¤   ¤   *keyalgorithm = kPGPPublicKeyAlgorithm_DSA;
c57c82 ¤   } else if (len == sizeof(dsashaoid) && memcmp (buf, dsashaoid, len) == 0) {
4ccf65 ¤   ¤   if( IsntNull( hashalgorithm ) )
516344 ¤   ¤   ¤   *hashalgorithm = kPGPHashAlgorithm_SHA;
26fa14 ¤   ¤   if( IsntNull( keyalgorithm ) )
574632 ¤   ¤   ¤   *keyalgorithm = kPGPPublicKeyAlgorithm_DSA;
7a491e ¤   } else if (len == sizeof(elgoid) && memcmp (buf, elgoid, len) == 0) {
38fa14 ¤   ¤   if( IsntNull( keyalgorithm ) )
8eccc0 ¤   ¤   ¤   *keyalgorithm = kPGPPublicKeyAlgorithm_ElGamal;
47f037 ¤   } else {
aa545c ¤   ¤   err = kPGPError_X509InvalidCertificateFormat;
829371 ¤   }
775ea8 ¤   return err;
9defe6 }
09af5a
f738e5 /*
d398c5 ·* Call this after reading the tag and length for the SEQUENCE which holds
cacfd3 ·* the validity period
df814f ·* If vbuf is NULL, set *vlength to the necessary length. ·Else
07ebdc ·* store the data into vbuf, and treat *vlength as an input parameter
20750e ·* telling what the length needs to be.
4af127 ·* We create a pair of PGP signature subpackets expressing creation and
80a453 ·* expiration dates.
4f495d ·*/
79f1ae static PGPError
53dc89 sDecodeValidity(PGPByte *buf, PGPSize length, PGPByte *vbuf,
b32190 ¤   ·PGPSize *vlength)
26bb36 {
69875f ¤   PGPSize len;
3ab621 ¤   PGPByte tag;
595c72 ¤   PGPUInt32 creationtime;
5b4a3a ¤   PGPUInt32 expirationtime;
908725 ¤   PGPUInt32 o;
350040 ¤   PGPError err;
aeaf5a
7b3ac6 ¤   (void) length;
94fad7 ¤   pgpAssert( IsntNull( vlength ) );
--fb29 000e7d05d4140100237 Page 7 of pgpX509Keys.c
e0af5a
23607f ¤   /* Need to enhance to handle GENERALIZEDTIME */
21af5a
7b06b7 ¤   /* Should be notbefore UTCTIME */
356f74 ¤   tag = dotaglen(&buf, &len);
9f0d87 ¤   EXPECT(tag, TAG_UTCTIME);
3baf5a
ae0379 ¤   err = sDecodeUTCTime (buf, len, &creationtime);
de7f7d ¤   if( IsPGPError( err ) )
2c97ed ¤   ¤   goto error;
f7763f ¤   buf += len;
10af5a
302fe5 ¤   /* Should be notafter UTCTIME */
726f74 ¤   tag = dotaglen(&buf, &len);
530d87 ¤   EXPECT(tag, TAG_UTCTIME);
ceaf5a
f77515 ¤   err = sDecodeUTCTime (buf, len, &expirationtime);
5d7f7d ¤   if( IsPGPError( err ) )
0b97ed ¤   ¤   goto error;
a9763f ¤   buf += len;
c2af5a
d352c1 ¤   if (expirationtime < creationtime) {
96545c ¤   ¤   err = kPGPError_X509InvalidCertificateFormat;
3d97ed ¤   ¤   goto error;
b79371 ¤   }
30a68c ¤   expirationtime -= creationtime;
37af5a
023774 ¤   /* Two subpackets, each with 1 byte of len, 1 byte of type, 4 of time */
932f3c ¤   if( IsNull( vbuf ) ) {
e714b9 ¤   ¤   *vlength = 2 * 6;
fbb840 ¤   ¤   return kPGPError_NoErr;
109371 ¤   }
96af5a
6ca91a ¤   pgpAssert (*vlength == 2 * 6);
b6af5a
25a7a1 ¤   o = 0;
14c555 ¤   vbuf[o++] = 5;¤ /* length */
4478fa ¤   vbuf[o++] = SIGSUB_CREATION;
f40790 ¤   vbuf[o++] = (PGPByte)(creationtime >> 24);
0a232a ¤   vbuf[o++] = (PGPByte)(creationtime >> 16);
c73ca5 ¤   vbuf[o++] = (PGPByte)(creationtime >> ·8);
b1d97d ¤   vbuf[o++] = (PGPByte)(creationtime >> ·0);
0faf5a
63c555 ¤   vbuf[o++] = 5;¤ /* length */
4a732b ¤   vbuf[o++] = SIGSUB_EXPIRATION;
938f83 ¤   vbuf[o++] = (PGPByte)(expirationtime >> 24);
faab39 ¤   vbuf[o++] = (PGPByte)(expirationtime >> 16);
f9b4b6 ¤   vbuf[o++] = (PGPByte)(expirationtime >> ·8);
45516e ¤   vbuf[o++] = (PGPByte)(expirationtime >> ·0);
69af5a
17a0ef ¤   pgpAssert (o == *vlength);
3aaf5a
8360ff error:
a7af5a
cb5ea8 ¤   return err;
74efe6 }
9eaf5a
9eaf5a
5a38e5 /*
c7456b ·* Call this pointing AT the start of the cert to
8386e8 ·* create a PGP signature packet which embodies the cert.
75fda3 ·* If sigbuf is NULL, set *siglength to the necessary length. ·Else
6ae077 ·* store the data into sigbuf, and treat *siglength as an input parameter
c9750e ·* telling what the length needs to be.
b7495d ·*/
2bf1ae static PGPError
884ba6 sDecodeSig(PGPByte *buf, PGPByte *sigBuf, PGPSize *sigLength)
43bb36 {
63adba ¤   PGPByte *buf_validity;
f0a04d ¤   PGPSize len_validity;
ba04e5 ¤   PGPByte *certbuf;
e7cfbb ¤   PGPSize certlen;
--4613 00077aafa9e40100237 Page 8 of pgpX509Keys.c
2153a8 ¤   PGPByte *buf2;
7f504a ¤   PGPUInt32 tag;
3ff066 ¤   PGPSize siglen;
a84aaf ¤   PGPSize extralen;
bc6c23 ¤   PGPSize certlenlen;
ae251c ¤   PGPSize validitylen;
f1875f ¤   PGPSize len;
e98725 ¤   PGPUInt32 o;
2bc641 ¤   PGPPublicKeyAlgorithm sigalg;
0767a4 ¤   PGPHashAlgorithm hashalg;
d7c55b ¤   PGPError err = kPGPError_NoErr;
a9af5a
543977 ¤   pgpAssert( IsntNull( sigLength ) );
a2a08b ¤   if( IsNull( sigBuf ) )
8632f3 ¤   ¤   *sigLength = 0;
deaf5a
2d4b02 ¤   /* Save pointers to cert buf and len */
b48887 ¤   certbuf = buf;
5aaf5a
c16b70 ¤   /* Should be the overall certificate SEQUENCE */
a56f74 ¤   tag = dotaglen(&buf, &len);
38a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
105305 ¤   certlen = len + buf - certbuf;
06af5a
a48aed ¤   /* Should be certificate info SEQUENCE */
686f74 ¤   tag = dotaglen(&buf, &len);
3ca6cb ¤   EXPECT(tag, TAG_SEQUENCE);
70af5a
2402eb ¤   /* Save pointer to signature algorithm identifier after cert info */
42228e ¤   buf2 = buf + len;
7aaf5a
a0976b ¤   /* Parse cert info to get validity period */
44af5a
82a7fa ¤   /* May be X509 version number */
f36f74 ¤   tag = dotaglen(&buf, &len);
c3d36f ¤   if (tag == TAG_ZERO) {
f4e14c ¤   ¤   buf += len;
f2e488 ¤   ¤   tag = dotaglen(&buf, &len);
e29371 ¤   }
34af5a
6124f4 ¤   /* Should be serial number INTEGER */
c307ac ¤   EXPECT(tag, TAG_INTEGER);
ad763f ¤   buf += len;
19af5a
62b08b ¤   /* Should be signature algorithm identifier SEQUENCE */
2a6f74 ¤   tag = dotaglen(&buf, &len);
57a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
8f763f ¤   buf += len;
33af5a
06fde7 ¤   /* Should be issuer name SEQUENCE */
ac6f74 ¤   tag = dotaglen(&buf, &len);
6ea6cb ¤   EXPECT(tag, TAG_SEQUENCE);
33763f ¤   buf += len;
34af5a
9f43dc ¤   /* Should be validity SEQUENCE */
b86f74 ¤   tag = dotaglen(&buf, &len);
7ca6cb ¤   EXPECT(tag, TAG_SEQUENCE);
8195e1 ¤   buf_validity = buf;
596b7c ¤   len_validity = len;
f2894f ¤   err = sDecodeValidity (buf, len, NULL, &validitylen);
aa82f0 ¤   if (IsPGPError(err))
7297ed ¤   ¤   goto error;
70af5a
aeb3f7 ¤   /* Get type of signature */
64475e ¤   buf = buf2;
f6af5a
6cb08b ¤   /* Should be signature algorithm identifier SEQUENCE */
906f74 ¤   tag = dotaglen(&buf, &len);
8aa6cb ¤   EXPECT(tag, TAG_SEQUENCE);
cfaf5a
05f81f ¤   /* Should be signature algorithm OBJECT */
776f74 ¤   tag = dotaglen(&buf, &len);
--93eb 00078159e4940100237 Page 9 of pgpX509Keys.c
fbe5b7 ¤   EXPECT(tag, TAG_OBJECT);
3caf5a
93c600 ¤   err = sDecodeAlgorithmOID (buf, len, &sigalg, &hashalg);
75bdc8 ¤   if( IsPGPError(err) )
f897ed ¤   ¤   goto error;
7f763f ¤   buf += len;
e3af5a
fa7ba7 ¤   /* Calculate length of signature */
8a3b77 ¤   certlenlen = (certlen+1 < 192) ? 1 : 2;
da8170 ¤   extralen = validitylen + certlen + 1 + certlenlen;
a08764 ¤   siglen = 8 + extralen + 2 + 3;
3aaf5a
4f0619 ¤   if( IsNull( sigBuf ) ) {
e926e3 ¤   ¤   *sigLength = siglen;
74b840 ¤   ¤   return kPGPError_NoErr;
099371 ¤   }
cdaf5a
119c0b ¤   pgpAssert (*sigLength = siglen);
47af5a
8d96da ¤   /* Lay out signature packet */
e267c5 ¤
38a7a1 ¤   o = 0;
e6c333 ¤   sigBuf[o++] = PGPVERSION_4;
0dbfd0 ¤   sigBuf[o++] = PGP_SIGTYPE_KEY_GENERIC;
c72717 ¤   sigBuf[o++] = 0;¤   ¤   /* Use sigalgorithm of 0 to show nonstandard */
5c156f ¤   sigBuf[o++] = hashalg;¤ /* But use true hash algorithm */
dbaf5a
27654b ¤   sigBuf[o++] = (PGPByte) (extralen >> 8);
f38093 ¤   sigBuf[o++] = (PGPByte) (extralen >> 0);
d0c718 ¤   err = sDecodeValidity (buf_validity, len_validity,
db7cb8 ¤   ¤   ¤   ¤   ¤   ¤   ···sigBuf + o, &validitylen);
5fe83e ¤   o += validitylen;
4eaf5a
34834d ¤   if (certlenlen == 1)
010de1 ¤   ¤   sigBuf[o++] = certlen + 1;
ac665a ¤   else {
ad58a1 ¤   ¤   sigBuf[o++] = (PGPByte) (192 + ((certlen+1-192) >> 8));
4da2af ¤   ¤   sigBuf[o++] = (PGPByte) (certlen+1-192);
ad9371 ¤   }
42d7b6 ¤   sigBuf[o++] = SIGSUB_X509;
c8ebc2 ¤   pgpCopyMemory (certbuf, sigBuf+o, certlen);
cbded6 ¤   o += certlen;
feaf5a
cc592f ¤   /* No non-hashed data (yet) */
f25013 ¤   sigBuf[o++] = 0;
e65013 ¤   sigBuf[o++] = 0;
e0af5a
5277c3 ¤   /* End up with dummy 2-byte checksum and dummy MPI for old parsers */
ac5013 ¤   sigBuf[o++] = 0;
4f5013 ¤   sigBuf[o++] = 0;
515013 ¤   sigBuf[o++] = 0;
570acf ¤   sigBuf[o++] = 1;
690acf ¤   sigBuf[o++] = 1;
efaf5a
b911ae ¤   pgpAssert (o == siglen);
74af5a
a060ff error:
335ea8 ¤   return err;
57efe6 }
2caf5a
25af5a
0438e5 /*
2798c5 ·* Call this after reading the tag and length for the SEQUENCE which holds
04194f ·* the distinguished name.
e77a12 ·* If namebuf is NULL, set *namelength to the necessary length. ·Else
258627 ·* store the data into namebuf, and treat *namelength as an input parameter
2b750e ·* telling what the length needs to be.
0113eb ·* This versions uses long form for X509 names, in RFC2253 format.
60495d ·*/
eff1ae static PGPError
b2a3bf sDecodeNameLong(PGPByte *buf, PGPSize length, PGPByte *nameBuf,
783435 ¤   ·PGPSize *nameLength)
--3c81 0004067b48540100237 Page 10 of pgpX509Keys.c
2cbb36 {
241143 ¤   PGPByte *endname = buf + length;
d8875f ¤   PGPSize len;
afb621 ¤   PGPByte tag;
f15f40 ¤   PGPBoolean sizingPass;
c3feb6 ¤   PGPBoolean seenName = FALSE;
3f0040 ¤   PGPError err;
cd64d7 ¤   char const *oidName;
b4cfd0 ¤   PGPUInt32 lNameLength;
7ad2ef ¤   PGPUInt32 oidLength = 0;
123a88 ¤   static char const dfltname[] = "(Unknown X509 name)";
87af5a
118c91 ¤   sizingPass = (nameBuf==NULL);
9c0ab9 ¤   lNameLength = sizingPass ? 0 : *nameLength;
93af5a
54e4d5 ¤   while (buf < endname) {
fbce02 ¤   ¤   /* Should be SET */
e0d55c ¤   ¤   tag = dotaglen (&buf, &len);
d2e7c0 ¤   ¤   EXPECT(tag, TAG_SET);
25af5a
71dfa6 ¤   ¤   /* Set just holds a SEQUENCE */
e4d55c ¤   ¤   tag = dotaglen (&buf, &len);
762ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
68af5a
51d938 ¤   ¤   /* Sequence starts with an OID */
62d55c ¤   ¤   tag = dotaglen (&buf, &len);
c75ee1 ¤   ¤   EXPECT(tag, TAG_OBJECT);
6caf5a
122f33 ¤   ¤   oidName = NULL;
ec0089 ¤   ¤   if (len == 3 &&
a45239 ¤   ¤   ¤   (buf)[0] == cnoid[0] && (buf)[1] == cnoid[1] &&
22a21d ¤   ¤   ¤   (buf)[2] < sizeof(dnnames)/sizeof(dnnames[0])) {
850478 ¤   ¤   ¤   oidName = dnnames[(buf)[2]];
0c84d3 ¤   ¤   ¤   oidLength = strlen(oidName);
bc0fe4 ¤   ¤   }
9f7ad0 ¤   ¤   else if (len == sizeof(emailoid)
e55f9d ¤   ¤   ¤   ¤   ·&& memcmp(buf, emailoid, len)==0 ) {
f97830 ¤   ¤   ¤   oidName = emailname;
9184d3 ¤   ¤   ¤   oidLength = strlen(oidName);
e50fe4 ¤   ¤   }
30e14c ¤   ¤   buf += len;
a9af5a
22e247 ¤   ¤   /* Next comes the printablestring (may be variants like IA5) */
72d55c ¤   ¤   tag = dotaglen (&buf, &len);
e5ff3d ¤   ¤   /* EXPECT(tag, TAG_PRINTABLE); */
d7af5a
c3a3bd ¤   ¤   if( IsntNull( oidName ) ) {
a1de32 ¤   ¤   ¤   seenName = TRUE;
4c35d1 ¤   ¤   ¤   if (sizingPass) {
70f01c ¤   ¤   ¤   ¤   /* add 3 for equals, comma, space */
b5e8c6 ¤   ¤   ¤   ¤   lNameLength += strlen(oidName) + 3;
528d21 ¤   ¤   ¤   ¤   lNameLength += sDNQuoteString(buf, len, NULL, TRUE);
30042d ¤   ¤   ¤   } else {
5de325 ¤   ¤   ¤   ¤   /* Build name string in reverse order, per LDAP */
a66a0c ¤   ¤   ¤   ¤   lNameLength -= sDNQuoteString(buf, len,
a898e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·nameBuf+lNameLength, TRUE);
1ed5e1 ¤   ¤   ¤   ¤   nameBuf[--lNameLength] = '=';
6b354c ¤   ¤   ¤   ¤   lNameLength -= oidLength;
6bb998 ¤   ¤   ¤   ¤   pgpCopyMemory( oidName, nameBuf+lNameLength, oidLength );
4fb509 ¤   ¤   ¤   ¤   if( lNameLength > 0 ) {
85d2f1 ¤   ¤   ¤   ¤   ¤   nameBuf[--lNameLength] = ' ';
de45c5 ¤   ¤   ¤   ¤   ¤   nameBuf[--lNameLength] = ',';
822613 ¤   ¤   ¤   ¤   }
a3a3a6 ¤   ¤   ¤   }
960fe4 ¤   ¤   }
aee14c ¤   ¤   buf += len;
329371 ¤   }
45a540 ¤   if( sizingPass ) {
95cdca ¤   ¤   if (lNameLength == 0) {
c96e99 ¤   ¤   ¤   /* No name fields we recognized */
a9e0ac ¤   ¤   ¤   *nameLength = sizeof(dfltname);
4045a6 ¤   ¤   } else {
--b2a9 000efd6f07340100237 Page 11 of pgpX509Keys.c
ffe41f ¤   ¤   ¤   lNameLength -= 2;¤  /* Counted an initial ", " */
ca3710 ¤   ¤   ¤   *nameLength = lNameLength;
c50fe4 ¤   ¤   }
82f037 ¤   } else {
412c06 ¤   ¤   /* lNameLength should have counted down to zero */
80fca9 ¤   ¤   if( !seenName ) {
ce19a9 ¤   ¤   ¤   pgpAssert (lNameLength == sizeof(dfltname));
0c59c2 ¤   ¤   ¤   pgpCopyMemory (dfltname, nameBuf, lNameLength);
d245a6 ¤   ¤   } else {
dbe6c7 ¤   ¤   ¤   pgpAssert (lNameLength == 0);
bb0fe4 ¤   ¤   }
e99371 ¤   }
59af5a
09151e ¤   return kPGPError_NoErr;
3baf5a
af60ff error:
4c5ea8 ¤   return err;
23efe6 }
7caf5a
2aaf5a
a6af5a
f638e5 /*
8498c5 ·* Call this after reading the tag and length for the SEQUENCE which holds
64194f ·* the distinguished name.
6a7a12 ·* If namebuf is NULL, set *namelength to the necessary length. ·Else
fd8627 ·* store the data into namebuf, and treat *namelength as an input parameter
e7750e ·* telling what the length needs to be.
d72517 ·* This version uses short form for X509 names, in PGP format.
7c77a7 ·* E.g. just "John Doe <john@doe.com>".
22495d ·*/
9af1ae static PGPError
2715da sDecodeName(PGPByte *buf, PGPSize length, PGPByte *nameBuf,
0d3435 ¤   ·PGPSize *nameLength)
d9bb36 {
111ebc #if !PGP_X509SHORTNAMES
6daf5a
6e69b4 ¤   return sDecodeNameLong(buf, length, nameBuf, nameLength);
daaf5a
e32f97 #else /* PGP_X509SHORTNAMES */
7daf5a
661143 ¤   PGPByte *endname = buf + length;
da4ca4 ¤   PGPByte *inibuf = buf;
56875f ¤   PGPSize len;
52b621 ¤   PGPByte tag;
280040 ¤   PGPError err;
885f40 ¤   PGPBoolean sizingPass;
12feb6 ¤   PGPBoolean seenName = FALSE;
0471bc ¤   PGPBoolean seenEmail = FALSE;
96cfd0 ¤   PGPUInt32 lNameLength;
98af5a
6b8c91 ¤   sizingPass = (nameBuf==NULL);
af0ab9 ¤   lNameLength = sizingPass ? 0 : *nameLength;
ddaf5a
18e4d5 ¤   while (buf < endname) {
21ce02 ¤   ¤   /* Should be SET */
e6d55c ¤   ¤   tag = dotaglen (&buf, &len);
06e7c0 ¤   ¤   EXPECT(tag, TAG_SET);
c4af5a
dddfa6 ¤   ¤   /* Set just holds a SEQUENCE */
91d55c ¤   ¤   tag = dotaglen (&buf, &len);
c62ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
bfaf5a
05d938 ¤   ¤   /* Sequence starts with an OID */
8bd55c ¤   ¤   tag = dotaglen (&buf, &len);
935ee1 ¤   ¤   EXPECT(tag, TAG_OBJECT);
36af5a
64eb9e ¤   ¤   if (len == sizeof(cnoid)
1afda7 ¤   ¤   ¤   ¤   && memcmp(buf, cnoid, len)==0 ) {
dff94e ¤   ¤   ¤   /* Next comes the printablestring (may be variants like IA5) */
779bb8 ¤   ¤   ¤   buf += len;
bad0b1 ¤   ¤   ¤   tag = dotaglen (&buf, &len);
efc6f8 ¤   ¤   ¤   /* EXPECT(tag, TAG_PRINTABLE); */
--046c 000d59ae1a440100237 Page 12 of pgpX509Keys.c
e0af5a
a7de32 ¤   ¤   ¤   seenName = TRUE;
e335d1 ¤   ¤   ¤   if (sizingPass) {
61705f ¤   ¤   ¤   ¤   lNameLength += len;
94042d ¤   ¤   ¤   } else {
340fbb ¤   ¤   ¤   ¤   /* Put common name at beginning of buffer */
15a604 ¤   ¤   ¤   ¤   pgpAssert (lNameLength >= len);
83a220 ¤   ¤   ¤   ¤   pgpCopyMemory (buf, nameBuf, len);
cf598a ¤   ¤   ¤   ¤   /* Add a space if needed */
4abeca ¤   ¤   ¤   ¤   if (lNameLength > len)
3834bf ¤   ¤   ¤   ¤   ¤   nameBuf[len] = ' ';
17a3a6 ¤   ¤   ¤   }
2f0fe4 ¤   ¤   }
d67ad0 ¤   ¤   else if (len == sizeof(emailoid)
955f9d ¤   ¤   ¤   ¤   ·&& memcmp(buf, emailoid, len)==0 ) {
c9f94e ¤   ¤   ¤   /* Next comes the printablestring (may be variants like IA5) */
549bb8 ¤   ¤   ¤   buf += len;
88d0b1 ¤   ¤   ¤   tag = dotaglen (&buf, &len);
14c6f8 ¤   ¤   ¤   /* EXPECT(tag, TAG_PRINTABLE); */
86af5a
5c36d8 ¤   ¤   ¤   seenEmail = TRUE;
7735d1 ¤   ¤   ¤   if (sizingPass) {
74e9a7 ¤   ¤   ¤   ¤   /* Add 2 for angle brackets */
08a262 ¤   ¤   ¤   ¤   lNameLength += len + 2;
54042d ¤   ¤   ¤   } else {
71f9a2 ¤   ¤   ¤   ¤   /* Put email address at end of buffer */
0259b8 ¤   ¤   ¤   ¤   pgpAssert (lNameLength >= len+2);
80ebe7 ¤   ¤   ¤   ¤   nameBuf[lNameLength-1] = '>';
b2eff7 ¤   ¤   ¤   ¤   pgpCopyMemory (buf, nameBuf+lNameLength-1-len, len);
4ab0e9 ¤   ¤   ¤   ¤   nameBuf[lNameLength-len-2] = '<';
d8a3a6 ¤   ¤   ¤   }
3045a6 ¤   ¤   } else {
aeb549 ¤   ¤   ¤   /* Some other field of the DN which we are ignoring */
d69bb8 ¤   ¤   ¤   buf += len;
f5d0b1 ¤   ¤   ¤   tag = dotaglen (&buf, &len);
c80fe4 ¤   ¤   }
bee14c ¤   ¤   buf += len;
899371 ¤   }
97af5a
548c61 ¤   if (!seenName && !seenEmail) {
629f4d ¤   ¤   /* If we could not parse the name, use the long form */
f48071 ¤   ¤   return sDecodeNameLong(inibuf, length, nameBuf, nameLength);
389371 ¤   }
caaf5a
03a540 ¤   if( sizingPass ) {
427dea ¤   ¤   /* Count a space between name and email if have both */
ba2678 ¤   ¤   if (seenName && seenEmail)
8ea34f ¤   ¤   ¤   ++lNameLength;
2e76e3 ¤   ¤   *nameLength = lNameLength;
de9371 ¤   }
83af5a
c0151e ¤   return kPGPError_NoErr;
4aaf5a
d860ff error:
205ea8 ¤   return err;
6caf5a
e25619 #endif /* PGP_X509SHORTNAMES */
a9efe6 }
c3af5a
a0af5a
c8af5a
5f38e5 /*
0198c5 ·* Call this after reading the tag and length for the SEQUENCE which holds
f808b1 ·* the subjectpublickeyinfo.
3fd6b2 ·* If keybuf is NULL, set *keylength to the necessary length. ·Else
d3d154 ·* store the data into keybuf, and treat *keylength as an input parameter
75750e ·* telling what the length needs to be.
ac495d ·*/
a4f1ae static PGPError
5619aa sDecodeKey(PGPByte *buf, PGPSize length, PGPByte *keyBuf, PGPSize *keyLength)
dcbb36 {
d5504a ¤   PGPUInt32 tag;
--cf96 00082dedefb40100237 Page 13 of pgpX509Keys.c
2153a8 ¤   PGPByte *buf2;
ae875f ¤   PGPSize len;
d66a0c ¤   PGPPublicKeyAlgorithm keyalgorithm;
c025ab ¤   PGPByte *bnbuf[4];¤ ¤   /* buf offset for start of X.509 bignum */
d507b8 ¤   PGPSize bnlen[4];¤  ¤   /* buf length for X.509 bignum */
650e04 ¤   PGPSize bnlength[4];¤   /* length of PGP encoded bignum */
198603 ¤   PGPUInt32 i, o;
40d8c5 ¤   PGPSize keybuflength;
1dc55b ¤   PGPError err = kPGPError_NoErr;
d8af5a
813ac6 ¤   (void) length;
8baf5a
1eea22 ¤   /* Init bignum arrays */
c7adb4 ¤   pgpClearMemory (bnbuf, sizeof(bnbuf));
7214ad ¤   pgpClearMemory (bnlen, sizeof(bnlen));
8c9c4f ¤   pgpClearMemory (bnlength, sizeof(bnlength));
cdaf5a
eb90ba ¤   /* Should be algorithm identifier for key data SEQUENCE */
f36f74 ¤   tag = dotaglen(&buf, &len);
21a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
37228e ¤   buf2 = buf + len;
bbaf5a
11c19d ¤   /* Go within algorithm identifier to determine key type */
3aaf5a
f0336b ¤   /* Should be object identifier for RSA/DSS/ElGamal */
486f74 ¤   tag = dotaglen(&buf, &len);
78e5b7 ¤   EXPECT(tag, TAG_OBJECT);
bd8475 ¤   err = sDecodeAlgorithmOID (buf, len, &keyalgorithm, NULL);
a7bdc8 ¤   if( IsPGPError(err) )
1797ed ¤   ¤   goto error;
e1763f ¤   buf += len;
4faf5a
a8be72 ¤   if (keyalgorithm == kPGPPublicKeyAlgorithm_DSA
e602d3 ¤   ¤   ¤   || keyalgorithm == kPGPPublicKeyAlgorithm_ElGamal) {
dfe488 ¤   ¤   tag = dotaglen(&buf, &len);
332ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
dbaf5a
a09006 ¤   ¤   /* Should be prime p INTEGER */
a2e488 ¤   ¤   tag = dotaglen(&buf, &len);
c130a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
6b1b52 ¤   ¤
ab1683 ¤   ¤   bnbuf[0] = buf;
f8c36a ¤   ¤   bnlen[0] = len;
2d5714 ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[0]);
94d223 ¤   ¤   if( IsPGPError( err ) )
41ed19 ¤   ¤   ¤   goto error;
abe14c ¤   ¤   buf += len;
4aaf5a
859608 ¤   ¤   /* Should be generator g INTEGER if ElG, or subprime q for DSA */
d1e488 ¤   ¤   tag = dotaglen(&buf, &len);
3d30a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
3a1b52 ¤   ¤
1d3aa4 ¤   ¤   bnbuf[1] = buf;
c0ef4d ¤   ¤   bnlen[1] = len;
1c5c50 ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[1]);
edd223 ¤   ¤   if( IsPGPError( err ) )
5eed19 ¤   ¤   ¤   goto error;
77e14c ¤   ¤   buf += len;
ccaf5a
5784fa ¤   ¤   if (keyalgorithm == kPGPPublicKeyAlgorithm_DSA) {
fccf86 ¤   ¤   ¤   /* Should be generator g INTEGER */
0d21dd ¤   ¤   ¤   tag = dotaglen(&buf, &len);
afdfd7 ¤   ¤   ¤   EXPECT(tag, TAG_INTEGER);
7faf5a
a2b8a8 ¤   ¤   ¤   bnbuf[2] = buf;
056d41 ¤   ¤   ¤   bnlen[2] = len;
4ecbd9 ¤   ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[2]);
6359df ¤   ¤   ¤   if( IsPGPError( err ) )
aa1b7c ¤   ¤   ¤   ¤   goto error;
379bb8 ¤   ¤   ¤   buf += len;
de0fe4 ¤   ¤   }
82db83 ¤   } else /* RSA */ {
--cd79 0009d3df59540100237 Page 14 of pgpX509Keys.c
d765f7 ¤   ¤   /* Ignore any RSA parameters */
bd9371 ¤   }
3caf5a
3dd6c0 ¤   /* Back up to subject public key info */
ef475e ¤   buf = buf2;
adaf5a
c2b82b ¤   /* Should be key data as an encoded BITSTRING */
0f6f74 ¤   tag = dotaglen(&buf, &len);
5b8572 ¤   EXPECT(tag, TAG_BITSTRING);
3367c5 ¤
7fa2b9 ¤   /* Go within bitstring and decode the public key data */
00af5a
e9bf2c ¤   /* Bit string should be multiple of 8 bits, have a zero at the top */
1bd8f0 ¤   EXPECT(*buf, 0);
22d311 ¤   ++buf;
0df7fd ¤   --len;
17af5a
83878d ¤   if (keyalgorithm == kPGPPublicKeyAlgorithm_DSA) {
33abb8 ¤   ¤   /* Should be public y value INTEGER */
afe488 ¤   ¤   tag = dotaglen(&buf, &len);
e830a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
dfaf5a
ec62ea ¤   ¤   bnbuf[3] = buf;
54b703 ¤   ¤   bnlen[3] = len;
1b4ad8 ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[3]);
8ed223 ¤   ¤   if( IsPGPError( err ) )
84ed19 ¤   ¤   ¤   goto error;
0be14c ¤   ¤   buf += len;
c9af5a
196872 ¤   } else if( keyalgorithm == kPGPPublicKeyAlgorithm_ElGamal) {
b2abb8 ¤   ¤   /* Should be public y value INTEGER */
d3e488 ¤   ¤   tag = dotaglen(&buf, &len);
1630a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
dfaf5a
ad4ecd ¤   ¤   bnbuf[2] = buf;
6e9b24 ¤   ¤   bnlen[2] = len;
25419c ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[2]);
e6d223 ¤   ¤   if( IsPGPError( err ) )
deed19 ¤   ¤   ¤   goto error;
7ce14c ¤   ¤   buf += len;
53af5a
93db83 ¤   } else /* RSA */ {
31a522 ¤   ¤   /* Should be RSA public key SEQUENCE */
dee488 ¤   ¤   tag = dotaglen(&buf, &len);
872ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
d6af5a
2a64df ¤   ¤   /* Go within RSA public key */
34af5a
febc87 ¤   ¤   /* Should be modulus INTEGER */
b5e488 ¤   ¤   tag = dotaglen(&buf, &len);
5830a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
aeaf5a
081683 ¤   ¤   bnbuf[0] = buf;
84c36a ¤   ¤   bnlen[0] = len;
855714 ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[0]);
12d223 ¤   ¤   if( IsPGPError( err ) )
8eed19 ¤   ¤   ¤   goto error;
16e14c ¤   ¤   buf += len;
56af5a
765a67 ¤   ¤   /* Should be exponent INTEGER */
d0e488 ¤   ¤   tag = dotaglen(&buf, &len);
b030a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
90af5a
643aa4 ¤   ¤   bnbuf[1] = buf;
f5ef4d ¤   ¤   bnlen[1] = len;
2b5c50 ¤   ¤   err = sDecodeX509Integer (buf, len, NULL, &bnlength[1]);
bdd223 ¤   ¤   if( IsPGPError( err ) )
0aed19 ¤   ¤   ¤   goto error;
7ae14c ¤   ¤   buf += len;
089371 ¤   }
72af5a
9dbd46 ¤   keybuflength = 6; /* bytes preceding bignums */
--06c5 000275961b240100237 Page 15 of pgpX509Keys.c
e0af5a
a2c90c ¤   for (i=0; i<elemsof(bnlength); ++i) {
fe56cc ¤   ¤   if( bnlength[i] == 0 )
47cdcb ¤   ¤   ¤   break;
d4dd8d ¤   ¤   keybuflength += bnlength[i];
e59371 ¤   }
c6af5a
3746a3 ¤   if( IsNull( keyBuf ) ) {
0155cf ¤   ¤   *keyLength = keybuflength;
74f037 ¤   } else {
dd5bd6 ¤   ¤   pgpAssert (*keyLength == keybuflength);
c8512a ¤   ¤   /* public key packet */
28c61b ¤   ¤   o = 0;
b8e577 ¤   ¤   keyBuf[o++] = PGPVERSION_4;¤¤   /* Version */
3796a3 ¤   ¤   /* 1-4 are timestamp */
0fc7ee ¤   ¤   while (o < 5)
186edb ¤   ¤   ¤   keyBuf[o++] = 0;
e0c8c0 ¤   ¤   keyBuf[o++] = keyalgorithm;
06f0c9 ¤   ¤   for (i=0; i<elemsof(bnlength); ++i) {
22dab3 ¤   ¤   ¤   if( bnlength[i] == 0 )
41f622 ¤   ¤   ¤   ¤   break;
25f12f ¤   ¤   ¤   err = sDecodeX509Integer (bnbuf[i], bnlen[i],
5db75d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··keyBuf+o, &bnlength[i]);
2959df ¤   ¤   ¤   if( IsPGPError( err ) )
ba1b7c ¤   ¤   ¤   ¤   goto error;
30332f ¤   ¤   ¤   o += bnlength[i];
860fe4 ¤   ¤   }
303b06 ¤   ¤   pgpAssert (o == keybuflength);
d99371 ¤   }
6baf5a
4a60ff error:
a2af5a
515ea8 ¤   return err;
b6efe6 }
c4af5a
4faf5a
8338e5 /*
e43481 ·* Given an X509 cert, return a PGPKeySetRef containing a simple PGP key
d939e9 ·* with the same key material as the original cert. ·The userid on the
c884b9 ·* key is one of the 509 subject distinguished name fields, the common name
05bd16 ·* if it exists, else one of the other fields.
87495d ·*/
f5f1ae static PGPError
1a4f4d sDecode509(PGPByte *buf, PGPContextRef context, PGPKeySetRef *kset)
95bb36 {
cfb621 ¤   PGPByte tag;
7e875f ¤   PGPSize len;
0feba0 ¤   PGPByte *pgpkeybuf = NULL;
9c3eb7 ¤   PGPByte *buf_name, *buf_key, *buf_sig;
8a45a4 ¤   PGPSize len_name, len_key;
dd4c2a ¤   PGPSize keylen;
133e11 ¤   PGPSize namelen;
a4f066 ¤   PGPSize siglen;
0f8268 ¤   PGPSize pgpkeylen;
538725 ¤   PGPUInt32 o;
a7c9c8 ¤   PGPKeySetRef keyset;
250040 ¤   PGPError err;
f7af5a
81e6d2 ¤   *kset = NULL;
ecaf5a
9d3f56 ¤   /* Ignore errors from sig, we may just leave it off */
bb9e62 ¤   buf_sig = buf;
761336 ¤   (void)sDecodeSig (buf, NULL, &siglen);
5eaf5a
9d6b70 ¤   /* Should be the overall certificate SEQUENCE */
126f74 ¤   tag = dotaglen(&buf, &len);
a9a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
5aaf5a
bb8aed ¤   /* Should be certificate info SEQUENCE */
e06f74 ¤   tag = dotaglen(&buf, &len);
5ba6cb ¤   EXPECT(tag, TAG_SEQUENCE);
27af5a
--d0ca 000a0de709140100237 Page 16 of pgpX509Keys.c
c2a7fa ¤   /* May be X509 version number */
9f6f74 ¤   tag = dotaglen(&buf, &len);
88d36f ¤   if (tag == TAG_ZERO) {
ece14c ¤   ¤   buf += len;
77e488 ¤   ¤   tag = dotaglen(&buf, &len);
3f9371 ¤   }
b8af5a
fd24f4 ¤   /* Should be serial number INTEGER */
5507ac ¤   EXPECT(tag, TAG_INTEGER);
4d763f ¤   buf += len;
8aaf5a
16b08b ¤   /* Should be signature algorithm identifier SEQUENCE */
ac6f74 ¤   tag = dotaglen(&buf, &len);
cba6cb ¤   EXPECT(tag, TAG_SEQUENCE);
7d763f ¤   buf += len;
5aaf5a
a7fde7 ¤   /* Should be issuer name SEQUENCE */
586f74 ¤   tag = dotaglen(&buf, &len);
3ca6cb ¤   EXPECT(tag, TAG_SEQUENCE);
82b177 #if 0
fd97c3 ¤   /* For debugging, verify issuer name */
0be0cd ¤   err = sDecodeName (buf, len, NULL, &namelen);
8e82f0 ¤   if (IsPGPError(err))
af97ed ¤   ¤   goto error;
7665f1 ¤   namebuf = (PGPByte *) pgpContextMemAlloc( context, namelen, 0);
2e75bf ¤   if (IsNull(namebuf)) {
75bce1 ¤   ¤   err = kPGPError_OutOfMemory;
8f97ed ¤   ¤   goto error;
e39371 ¤   }
b47f17 ¤   err = sDecodeName (buf, len, namebuf, &namelen);
8282f0 ¤   if (IsPGPError(err))
5697ed ¤   ¤   goto error;
db39e8 ¤   /* Peek at it here if debugging, then trash it */
7cd704 ¤   pgpContextMemFree( context, namebuf );
e3b37b ¤   namebuf = NULL;
53db21 #else
48763f ¤   buf += len;
df7454 #endif
5caf5a
5043dc ¤   /* Should be validity SEQUENCE */
bc6f74 ¤   tag = dotaglen(&buf, &len);
dca6cb ¤   EXPECT(tag, TAG_SEQUENCE);
73763f ¤   buf += len;
d4af5a
79da96 ¤   /* Should be subject name SEQUENCE */
c86f74 ¤   tag = dotaglen(&buf, &len);
58a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
6baf5a
a61792 ¤   /* Decode subject name */
28a8c3 ¤   buf_name = buf;
8bed08 ¤   len_name = len;
81e0cd ¤   err = sDecodeName (buf, len, NULL, &namelen);
c682f0 ¤   if (IsPGPError(err))
5d97ed ¤   ¤   goto error;
28763f ¤   buf += len;
c9af5a
aecbf1 ¤   /* Should be subject public key info SEQUENCE */
e06f74 ¤   tag = dotaglen(&buf, &len);
a5a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
52af5a
3814a9 ¤   /* Decode subject public key info */
8bae79 ¤   buf_key = buf;
00d882 ¤   len_key = len;
96216c ¤   err = sDecodeKey (buf, len, NULL, &keylen);
4182f0 ¤   if (IsPGPError(err))
3897ed ¤   ¤   goto error;
edaf5a
707962 ¤   /* Now create the PGP key */
f0af5a
c3b509 ¤   pgpkeylen = 3 + keylen + 3 + namelen + ((siglen>0)?(3+siglen):0);
a80195 ¤   pgpkeybuf = (PGPByte *) pgpContextMemAlloc( context, pgpkeylen, 0);
a0790b ¤   if (IsNull(pgpkeybuf)) {
--6b97 000d492e42240100237 Page 17 of pgpX509Keys.c
e1bce1 ¤   ¤   err = kPGPError_OutOfMemory;
9097ed ¤   ¤   goto error;
da9371 ¤   }
dbaf5a
22fc74 ¤   /* public key packet */
15a7a1 ¤   o = 0;
2d7d05 ¤   pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1),
3b5b7d ¤   pgpkeybuf[o++] = (keylen >> 8) & 0xff;
8fe7d7 ¤   pgpkeybuf[o++] = (keylen >> 0) & 0xff;
78b5d7 ¤   err = sDecodeKey (buf_key, len_key, pgpkeybuf + o, &keylen);
db82f0 ¤   if (IsPGPError(err))
3097ed ¤   ¤   goto error;
5ea82b ¤   o += keylen;
9caf5a
f137dd ¤   /* userid packet */
2a4b4e ¤   pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_NAME, 1);
242c2c ¤   pgpkeybuf[o++] = (namelen >> 8) & 0xff;
909086 ¤   pgpkeybuf[o++] = (namelen >> 0) & 0xff;
10d2b5 ¤   err = sDecodeName (buf_name, len_name, pgpkeybuf + o, &namelen);
5a82f0 ¤   if (IsPGPError(err))
c597ed ¤   ¤   goto error;
ab2f7c ¤   o += namelen;
1eaf5a
481075 ¤   /* sig packet */
f2f32d ¤   if( siglen > 0 ) {
39ae46 ¤   ¤   pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_SIG, 1);
bb0d5a ¤   ¤   pgpkeybuf[o++] = (siglen >> 8) & 0xff;
0bb1f0 ¤   ¤   pgpkeybuf[o++] = (siglen >> 0) & 0xff;
e07515 ¤   ¤   err = sDecodeSig (buf_sig, pgpkeybuf + o, &siglen);
28b6ad ¤   ¤   if (IsPGPError(err))
3aed19 ¤   ¤   ¤   goto error;
3755ec ¤   ¤   o += siglen;
8a9371 ¤   }
1faf5a
165bd3 ¤   pgpAssert (o == pgpkeylen);
71af5a
a68879 ¤   err = pgpImportKeyBinary( context, pgpkeybuf, pgpkeylen, &keyset );
a87f7d ¤   if( IsPGPError( err ) )
0597ed ¤   ¤   goto error;
deaf5a
5962d5 ¤   *kset = keyset;
a991b1 ¤   /* Fall through */
df60ff error:
bbaf5a
42ea99 ¤   if( IsntNull(pgpkeybuf) )
bbedf1 ¤   ¤   pgpContextMemFree( context, pgpkeybuf );
885ea8 ¤   return err;
66efe6 }
ffaf5a
75af5a
9f97dd /* Entry point to import a 509 cert from the specified location */
98c744 ¤   PGPError
67f787 pgpImportX509Certificate( PGPContextRef context, PGPKeySetRef *keys,
d40408 ¤   PGPOptionListRef optionList)
cabb36 {
edfb19 ¤   PGPError¤   ¤   err;
56cced ¤   PGPPipeline¤ ··*head = NULL;
71be1f ¤   PGPFileRead¤¤   *pfrin;
e8c332 ¤   PFLConstFileSpecRef¤fileRef;
f48dc5 ¤   PGPByte¤¤   ···*bufPtr;
d3be20 ¤   PGPSize¤¤   ¤   bufLength;
305bc6 ¤   PGPFileDataType¤inFileDataType;
0267c5 ¤
5a0610 ¤   err = pgpSetupInput( context, optionList, NULL, NULL, FALSE, FALSE,
64b430 ¤   ¤   ¤   ¤   ¤   ¤   ·&fileRef, &pfrin, &inFileDataType, &bufPtr, &bufLength¶
f354c8 ·);
327f7d ¤   if( IsPGPError( err ) )
a697ed ¤   ¤   goto error;
2eaf5a
f34bba ¤   if( IsntNull( pfrin ) ) {
9af064 ¤   ¤   /* Read whole file into memory buffer */
d4fc1b ¤   ¤   pgpVariableMemModCreate( context, &head, MAX_509_CERT_SIZE );
--c9b1 0004613aa2b40100237 Page 18 of pgpX509Keys.c
d90c67 ¤   ¤   if( IsNull( head ) ) {
1c8ee0 ¤   ¤   ¤   pgpFileReadDestroy( pfrin );
077cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
a90fe4 ¤   ¤   }
52129c ¤   ¤   err = pgpFileReadPump( pfrin, head );
4d8b0d ¤   ¤   pgpFileReadDestroy( pfrin );
7637b3 ¤   ¤   if( IsPGPError( err ) ) {
264902 ¤   ¤   ¤   head->teardown( head );
d4b32f ¤   ¤   ¤   return err;
0f0fe4 ¤   ¤   }
18d4c9 ¤   ¤   err = head->annotate( head, NULL, PGPANN_MEM_BUFSIZE,
f8f72d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPByte *)&bufLength, sizeof( bufLength ) );
1837b3 ¤   ¤   if( IsPGPError( err ) ) {
304902 ¤   ¤   ¤   head->teardown( head );
93b32f ¤   ¤   ¤   return err;
c30fe4 ¤   ¤   }
cc1b52 ¤   ¤
384078 ¤   ¤   err = head->annotate( head, NULL, PGPANN_MEM_MEMBUF,
e21dd9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPByte *)&bufPtr, sizeof( bufPtr ) );
a4c2fe ¤   ¤   head->teardown( head );
d637b3 ¤   ¤   if( IsPGPError( err ) ) {
9ab32f ¤   ¤   ¤   return err;
590fe4 ¤   ¤   }
ba9371 ¤   }
2baf5a
c9a639 ¤   /* Now data is in bufPtr, of length bufLength */
fbab45 ¤   err = sDecode509( bufPtr, context, keys);
c14bba ¤   if( IsntNull( pfrin ) ) {
e3388b ¤   ¤   PGPFreeData( bufPtr );
da9371 ¤   }
62af5a
e360ff error:
1f5ea8 ¤   return err;
ddefe6 }
d6af5a
1caf5a
b5003b /* Given a distinguished name (e.g. an issuer name from a cert) search
05ca66 ·* the certs list and try to find a cert which has the given name as a
43d438 ·* subject. ·Return the cert length and a pointer to the start of the cert
e5bee6 ·* (to the SEQUENCE which is the whole cert). ·Return 0 if no cert matches.
a0495d ·*/
c2f1ae static PGPError
465cbb sLookup509 (PGPByte *certs, PGPByte *dname, PGPByte **rbuf, PGPUInt32 *rlen)
77bb36 {
501d02 ¤   PGPUInt32¤  totallen;
428818 ¤   PGPUInt32¤  certlen;
f1f1ae ¤   PGPSize¤¤   len;
4f0ef0 ¤   PGPByte¤¤   tag;
c6c8b6 ¤   PGPSize¤¤   dnamelen;
d515e5 ¤   PGPByte¤¤   *buf;
e74bd4 ¤   PGPByte¤¤   *subjname;
1161e0 ¤   PGPError¤   err;
caaf5a
18ff13 ¤   *rbuf = NULL;
ea0db3 ¤   *rlen = 0;
b2af5a
58c9c9 ¤   /* Get length of dname */
35480f ¤   buf = dname;
a0ee82 ¤   tag = dotaglen(&buf, &dnamelen);
c6a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
6cd60a ¤   dnamelen += buf - dname;
b6af5a
574ec6 ¤   totallen = dolen3 (&certs);
285bbd ¤   while (totallen > 0) {
106296 ¤   ¤   certlen = dolen3 (&certs);
ec1b52 ¤   ¤
20a22e ¤   ¤   /* Parse down to find subject name */
a723bb ¤   ¤   buf = certs;
83af5a
ab0443 ¤   ¤   /* Should be the overall certificate SEQUENCE */
dae488 ¤   ¤   tag = dotaglen(&buf, &len);
462ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
--c72a 000d338a4ac40100237 Page 19 of pgpX509Keys.c
e0af5a
f8c5d3 ¤   ¤   /* Should be certificate info SEQUENCE */
31e488 ¤   ¤   tag = dotaglen(&buf, &len);
a22ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
92af5a
21a217 ¤   ¤   /* May be X509 version number */
a5e488 ¤   ¤   tag = dotaglen(&buf, &len);
d7c747 ¤   ¤   if (tag == TAG_ZERO) {
129bb8 ¤   ¤   ¤   buf += len;
9321dd ¤   ¤   ¤   tag = dotaglen(&buf, &len);
150fe4 ¤   ¤   }
fcaf5a
ac1d31 ¤   ¤   /* Should be serial number INTEGER */
2e30a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
70e14c ¤   ¤   buf += len;
a5af5a
937497 ¤   ¤   /* Should be signature algorithm identifier SEQUENCE */
cfe488 ¤   ¤   tag = dotaglen(&buf, &len);
482ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
4de14c ¤   ¤   buf += len;
e6af5a
c5fb5f ¤   ¤   /* Should be issuer name SEQUENCE */
15e488 ¤   ¤   tag = dotaglen(&buf, &len);
6d2ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
c1e14c ¤   ¤   buf += len;
ffaf5a
2b7f32 ¤   ¤   /* Should be validity SEQUENCE */
94e488 ¤   ¤   tag = dotaglen(&buf, &len);
f82ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
7ae14c ¤   ¤   buf += len;
c8af5a
7ce353 ¤   ¤   /* Should be subject name SEQUENCE */
c2f27f ¤   ¤   subjname = buf;
00e488 ¤   ¤   tag = dotaglen(&buf, &len);
a52ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
17ee2a ¤   ¤   len += buf - subjname;
6caf5a
cb7361 ¤   ¤   if (dnamelen==len && memcmp (subjname, dname, len) == 0) {
de7351 ¤   ¤   ¤   /* Have a match */
57ad26 ¤   ¤   ¤   *rbuf = certs;
ff25b8 ¤   ¤   ¤   *rlen = certlen;
ad33bc ¤   ¤   ¤   return kPGPError_NoErr;
330fe4 ¤   ¤   }
5caf5a
24bea8 ¤   ¤   totallen -= certlen + 3;
121c80 ¤   ¤   certs += certlen;
de9371 ¤   }
85a914 ¤   return kPGPError_ItemNotFound;
1760ff error:
915ea8 ¤   return err;
dbefe6 }
3caf5a
30af5a
2b38e5 /*
e0e262 ·* Verify X.509 certificate chain.
41775e ·*
1ec175 ·* We have a certain number of root certificates, plus some in the chain.
cd6132 ·* Call with a TLS cert chain buffer. ·This has a three byte buffer length,
0fd460 ·* followed with 1 or more repetitions of a three byte certificate length
215b9b ·* plus a certificate. ·The certificates are from most local to most
16f5c7 ·* global. ·We are also passed a list of root certificates in the same form.
63c5de ·* Return 0 on success, error code on error.
0c495d ·*/
ffc77d PGPError
cb656e PGPVerifyX509CertificateChain (PGPContextRef context,
348185 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPByte *certchain, PGPByte *rootcerts)
bdbb36 {
0e53c8 ¤   PGPBoolean matchedinroot;
52d259 ¤   PGPByte *buf;
4353a8 ¤   PGPByte *buf2;
b847bf ¤   PGPByte *hashedbuf;
d34bb7 ¤   PGPByte *sigbuf;
--7bfb 0002b0aec3440100237 Page 20 of pgpX509Keys.c
3e2ce8 ¤   PGPByte *parentcert;
eb9906 ¤   PGPByte *childcert;
8023dd ¤   PGPByte *issuerbuf;
505a75 ¤   PGPUInt32 hashedlen;
47875f ¤   PGPSize len;
b8defb ¤   PGPUInt32 certchainlen;
1db6fe ¤   PGPUInt32 certlen;
205488 ¤   PGPUInt32 parentlen;
df5b3d ¤   PGPUInt32 sigbuflen;
f1504a ¤   PGPUInt32 tag;
ba7e88 ¤   PGPInt32 rslt;
dab948 ¤   PGPHashContextRef certhash = NULL;
800699 ¤   PGPKeySetRef parentkeyset;
9fa117 ¤   PGPKeyListRef keylist;
21302f ¤   PGPKeyIterRef keyiter;
dbe5ed ¤   PGPKeyRef parentkey;
580040 ¤   PGPError err;
2d67a4 ¤   PGPHashAlgorithm hashalg;
37f2fb ¤   PGPPubKey *pubkey = NULL;
9cb2a3 ¤   RingSet const *parentringset = NULL;
ec67c5 ¤
deaf5a
b0af5a
d2f43c ¤   childcert = certchain;
2b5937 ¤   certchainlen = dolen3 (&childcert);
1c399a ¤   certlen = dolen3 (&childcert);
2e43ab ¤   do {
514f95 ¤   ¤   /* Parse down to find issuer name */
323da4 ¤   ¤   buf = childcert;
50af5a
540443 ¤   ¤   /* Should be the overall certificate SEQUENCE */
39e488 ¤   ¤   tag = dotaglen(&buf, &len);
552ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
84af5a
22c5d3 ¤   ¤   /* Should be certificate info SEQUENCE */
27eccc ¤   ¤   hashedbuf = buf;
f7e488 ¤   ¤   tag = dotaglen(&buf, &len);
cc2ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
9dc61e ¤   ¤   hashedlen = len + buf - hashedbuf;
28af5a
bca217 ¤   ¤   /* May be X509 version number */
c0e488 ¤   ¤   tag = dotaglen(&buf, &len);
99c747 ¤   ¤   if (tag == TAG_ZERO) {
769bb8 ¤   ¤   ¤   buf += len;
3821dd ¤   ¤   ¤   tag = dotaglen(&buf, &len);
800fe4 ¤   ¤   }
56af5a
f81d31 ¤   ¤   /* Should be serial number INTEGER */
1830a4 ¤   ¤   EXPECT(tag, TAG_INTEGER);
1de14c ¤   ¤   buf += len;
faaf5a
937497 ¤   ¤   /* Should be signature algorithm identifier SEQUENCE */
a4e488 ¤   ¤   tag = dotaglen(&buf, &len);
112ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
4de53b ¤   ¤   buf2 = buf + len;
1c5723 ¤   ¤   /* Get hash algorithm for signature from it */
1be488 ¤   ¤   tag = dotaglen(&buf, &len);
1d5ee1 ¤   ¤   EXPECT(tag, TAG_OBJECT);
3db280 ¤   ¤   err = sDecodeAlgorithmOID (buf, len, NULL, &hashalg);
44d02d ¤   ¤   buf = buf2;
49af5a
fefb5f ¤   ¤   /* Should be issuer name SEQUENCE */
18ef88 ¤   ¤   issuerbuf = buf;
01e488 ¤   ¤   tag = dotaglen(&buf, &len);
0f2ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
7cb5a4 ¤   ¤   len += buf - issuerbuf;
59af5a
1908a8 ¤   ¤   /* See if we can match issuer in root list */
60abda ¤   ¤   err = sLookup509 (rootcerts, issuerbuf, &parentcert, &parentlen);
093376 ¤   ¤   matchedinroot = (parentlen != 0);
013e12 ¤   ¤   if (!parentlen) {
2b03a0 ¤   ¤   ¤   /* Failing that, see if we were given a parent cert */
--2078 0001e4dfd4340100237 Page 21 of pgpX509Keys.c
a9168f ¤   ¤   ¤   err = sLookup509 (certchain, issuerbuf, &parentcert, &parentlen);
3e87c7 ¤   ¤   ¤
590fe4 ¤   ¤   }
e13e12 ¤   ¤   if (!parentlen) {
dd9b49 ¤   ¤   ¤   /* Unable to complete the search, no parent available */
bc777c ¤   ¤   ¤   return (err == kPGPError_ItemNotFound) ?
66d43d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_X509NeededCertNotAvailable : err;
6f0fe4 ¤   ¤   }
abaf5a
1c1c4e ¤   ¤   /* Find signature data */
2573b2 ¤   ¤   buf = hashedbuf + hashedlen;
87af5a
377497 ¤   ¤   /* Should be signature algorithm identifier SEQUENCE */
3ce488 ¤   ¤   tag = dotaglen(&buf, &len);
0a2ab4 ¤   ¤   EXPECT(tag, TAG_SEQUENCE);
dfe14c ¤   ¤   buf += len;
641b52 ¤   ¤
857173 ¤   ¤   /* Should be signature data as an encoded BITSTRING */
0ee8dd ¤   ¤   sigbuf = buf;
dbe488 ¤   ¤   tag = dotaglen(&buf, &len);
c20e8e ¤   ¤   EXPECT(tag, TAG_BITSTRING);
25a774 ¤   ¤   sigbuflen = len + (buf - sigbuf);
73af5a
3b8a53 ¤   ¤   /* Parse parent cert to get key data */
05eef1 ¤   ¤   err = sDecode509 (parentcert, context, &parentkeyset);
78b6ad ¤   ¤   if (IsPGPError(err))
abed19 ¤   ¤   ¤   goto error;
e6af5a
01146f ¤   ¤   /* Get just the one key out of it */
30cb73 ¤   ¤   PGPOrderKeySet( parentkeyset, kPGPAnyOrdering, &keylist );
d9412d ¤   ¤   PGPNewKeyIter( keylist, &keyiter );
162fa8 ¤   ¤   PGPKeyIterNext( keyiter, &parentkey );
eda657 ¤   ¤   PGPFreeKeyIter( keyiter );
23d80b ¤   ¤   PGPFreeKeyList( keylist );
b61b52 ¤   ¤
1901a6 ¤   ¤   /* Hash data in child cert */
15142d ¤   ¤   certhash = pgpHashCreate( PGPGetContextMemoryMgr( context ),
af76e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··pgpHashByNumber( hashalg ) );
006be5 ¤   ¤   if( IsNull( certhash ) ) {
bd572b ¤   ¤   ¤   err = kPGPError_X509InvalidCertificateFormat;
8ced19 ¤   ¤   ¤   goto error;
620fe4 ¤   ¤   }
b2b02c ¤   ¤   PGPContinueHash(certhash, hashedbuf, hashedlen);
10af5a
7f811d ¤   ¤   /* Prepare to check signature */
d2040f ¤   ¤   parentringset = pgpKeyDBRingSet (parentkey->keyDB);
ab3adb ¤   ¤   pubkey = ringKeyPubKey(parentringset, parentkey->key, PGP_PKUSE_SIGN);
277d9c ¤   ¤   if (!pubkey) {
30920a ¤   ¤   ¤   err = ringSetError(parentringset)->error;
3ced19 ¤   ¤   ¤   goto error;
fd0fe4 ¤   ¤   }
3987c7 ¤   ¤   ¤
5b2e52 ¤   ¤   /* Verify the signature: rslt==1 means OK, else failure */
fcec2e ¤   ¤   rslt = pgpPubKeyVerify( pubkey, sigbuf, sigbuflen,
c8fe08 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpHashGetVTBL(certhash),
219011 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPByte *) pgpHashFinal(certhash),
ac2659 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyMessageFormat_X509 );
22af5a
69cfc8 ¤   ¤   PGPFreeHashContext (certhash);
20ec37 ¤   ¤   certhash = NULL;
193632 ¤   ¤   pgpPubKeyDestroy( pubkey );
70069d ¤   ¤   pubkey = NULL;
4a3af9 ¤   ¤   PGPFreeKeySet( parentkeyset );
f8af5a
46aadf ¤   ¤   if( rslt != 1 ) {
c6b1b1 ¤   ¤   ¤   return kPGPError_X509InvalidCertificateSignature;
220fe4 ¤   ¤   }
97af5a
71cc8b ¤   ¤   if (childcert == parentcert) {
8c0954 ¤   ¤   ¤   return kPGPError_X509SelfSignedCert;
4c0fe4 ¤   ¤   }
1eaf5a
--d92b 0008c698d4a40100237 Page 22 of pgpX509Keys.c
ff2042 ¤   ¤   /* Else try to validate parent cert */
10f1a3 ¤   ¤   childcert = parentcert;
744ccf ¤   ¤   certlen = parentlen;
e9af5a
4d7b22 ¤   } while (!matchedinroot);
14af5a
606dd4 ¤   return kPGPError_NoErr;¤/* Success */
a3af5a
5360ff error:
18b290 ¤   if( IsntNull( certhash ) )
91b06b ¤   ¤   PGPFreeHashContext(certhash);
aa368c ¤   if( IsntNull( pubkey ) )
6c3632 ¤   ¤   pgpPubKeyDestroy( pubkey );
e35ea8 ¤   return err;
c9efe6 }
fdaf5a
66af5a
b9af5a
e3d91c /**** ··Internal Functions ··****/
5baf5a
d8af5a
0a5dee /* Parse a certificate into its three parts, returning pointers and size */
3aaf5a
2ac77d PGPError
b23441 pgpX509CertPartition( PGPByte *buf, PGPSize len,
f5f1e4 ¤   PGPByte **certinfobuf, PGPSize *certinfolen,
e6a711 ¤   PGPByte **sigalgbuf, PGPSize *sigalglen,
ec70e5 ¤   PGPByte **sigbuf, PGPSize *siglen )
b9bb36 {
1253a8 ¤   PGPByte *buf2;
6319aa ¤   PGPSize buf2len;
30504a ¤   PGPUInt32 tag;
0cc55b ¤   PGPError err = kPGPError_NoErr;
e4af5a
4ed001 ¤   /* Prefix, prepare output with default values */
85a9c8 ¤   PGPValidatePtr( buf );
81e615 ¤   if( IsntNull (certinfobuf) )
bc58a7 ¤   ¤   *certinfobuf = NULL;
0b78a4 ¤   if( IsntNull (certinfolen) )
51ab05 ¤   ¤   *certinfolen = 0;
f9e83e ¤   if( IsntNull (sigalgbuf) )
81487f ¤   ¤   *sigalgbuf = NULL;
1a768f ¤   if( IsntNull (sigalglen) )
a9147e ¤   ¤   *sigalglen = 0;
d2a171 ¤   if( IsntNull (sigbuf) )
4abdbc ¤   ¤   *sigbuf = NULL;
c23fc0 ¤   if( IsntNull (siglen) )
079838 ¤   ¤   *siglen = 0;
3067c5 ¤
ca43f6 ¤   /* Should start with the overall certificate SEQUENCE */
c66f74 ¤   tag = dotaglen(&buf, &len);
b6a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
3daf5a
ef5591 ¤   /* Should be certificate info SEQUENCE, which is certinfo */
d3d1e6 ¤   buf2 = buf;
4c6f74 ¤   tag = dotaglen(&buf, &len);
2fa6cb ¤   EXPECT(tag, TAG_SEQUENCE);
4b763f ¤   buf += len;
bbcb71 ¤   buf2len = buf - buf2;
02af5a
12e615 ¤   if( IsntNull (certinfobuf) )
154f9c ¤   ¤   *certinfobuf = buf2;
8078a4 ¤   if( IsntNull (certinfolen) )
b07df1 ¤   ¤   *certinfolen = buf2len;
2aaf5a
83b08b ¤   /* Should be signature algorithm identifier SEQUENCE */
f9d1e6 ¤   buf2 = buf;
af6f74 ¤   tag = dotaglen(&buf, &len);
b6a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
c8763f ¤   buf += len;
bacb71 ¤   buf2len = buf - buf2;
8caf5a
--6132 00075fb92f940100237 Page 23 of pgpX509Keys.c
85e83e ¤   if( IsntNull (sigalgbuf) )
825f44 ¤   ¤   *sigalgbuf = buf2;
9a768f ¤   if( IsntNull (sigalglen) )
4aa1ad ¤   ¤   *sigalglen = buf2len;
8faf5a
737191 ¤   /* Should be signature data as an encoded BITSTRING */
c4d1e6 ¤   buf2 = buf;
6f6f74 ¤   tag = dotaglen(&buf, &len);
8b8572 ¤   EXPECT(tag, TAG_BITSTRING);
6a763f ¤   buf += len;
29cb71 ¤   buf2len = buf - buf2;
a1af5a
9fa171 ¤   if( IsntNull (sigbuf) )
edaa87 ¤   ¤   *sigbuf = buf2;
733fc0 ¤   if( IsntNull (siglen) )
fd46e3 ¤   ¤   *siglen = buf2len;
16af5a
c560ff error:
ac5ea8 ¤   return err;
1eefe6 }
7caf5a
c6252c /* Parse certificate info portion into parts, returning pointers and size */
14af5a
efc77d PGPError
34c657 pgpX509CertInfoPartition( PGPByte *buf, PGPSize len,
386b18 ¤   PGPByte **serialbuf, PGPSize *seriallen,
e8a711 ¤   PGPByte **sigalgbuf, PGPSize *sigalglen,
3872c4 ¤   PGPByte **issuerbuf, PGPSize *issuerlen,
80ab4b ¤   PGPByte **validitybuf, PGPSize *validitylen,
2f2960 ¤   PGPByte **subjectbuf, PGPSize *subjectlen,
42de2e ¤   PGPByte **publickeyinfobuf, PGPSize *publickeyinfolen )
8abb36 {
0753a8 ¤   PGPByte *buf2;
ec19aa ¤   PGPSize buf2len;
fb504a ¤   PGPUInt32 tag;
5dc55b ¤   PGPError err = kPGPError_NoErr;
f5af5a
1ad001 ¤   /* Prefix, prepare output with default values */
faa9c8 ¤   PGPValidatePtr( buf );
655eb2 ¤   if( IsntNull (serialbuf) )
419f1c ¤   ¤   *serialbuf = NULL;
dfc003 ¤   if( IsntNull (seriallen) )
d3e1af ¤   ¤   *seriallen = 0;
5be83e ¤   if( IsntNull (sigalgbuf) )
69487f ¤   ¤   *sigalgbuf = NULL;
e7768f ¤   if( IsntNull (sigalglen) )
c7147e ¤   ¤   *sigalglen = 0;
b93aa3 ¤   if( IsntNull (issuerbuf) )
2ccb10 ¤   ¤   *issuerbuf = NULL;
84a412 ¤   if( IsntNull (issuerlen) )
ec48c4 ¤   ¤   *issuerlen = 0;
fe73a6 ¤   if( IsntNull (validitybuf) )
219b77 ¤   ¤   *validitybuf = NULL;
c9ed17 ¤   if( IsntNull (validitylen) )
9f7827 ¤   ¤   *validitylen = 0;
d613bf ¤   if( IsntNull (subjectbuf) )
74584a ¤   ¤   *subjectbuf = NULL;
f58d0e ¤   if( IsntNull (subjectlen) )
db0499 ¤   ¤   *subjectlen = 0;
38d5b2 ¤   if( IsntNull (publickeyinfobuf) )
478022 ¤   ¤   *publickeyinfobuf = NULL;
304b03 ¤   if( IsntNull (publickeyinfolen) )
3c5e83 ¤   ¤   *publickeyinfolen = 0;
2e67c5 ¤
0ae9d4 ¤   /* Should start with the overall certificate info SEQUENCE */
7b6f74 ¤   tag = dotaglen(&buf, &len);
3ea6cb ¤   EXPECT(tag, TAG_SEQUENCE);
b1af5a
1ca7fa ¤   /* May be X509 version number */
c8d1e6 ¤   buf2 = buf;
c96f74 ¤   tag = dotaglen(&buf, &len);
75d36f ¤   if (tag == TAG_ZERO) {
--a18b 000a4e6317b40100237 Page 24 of pgpX509Keys.c
b2e14c ¤   ¤   buf += len;
b04695 ¤   ¤   buf2 = buf;
c4e488 ¤   ¤   tag = dotaglen(&buf, &len);
6e9371 ¤   }
2baf5a
8a24f4 ¤   /* Should be serial number INTEGER */
5e07ac ¤   EXPECT(tag, TAG_INTEGER);
ff763f ¤   buf += len;
efcb71 ¤   buf2len = buf - buf2;
adaf5a
ef5eb2 ¤   if( IsntNull (serialbuf) )
178827 ¤   ¤   *serialbuf = buf2;
65c003 ¤   if( IsntNull (seriallen) )
0259b7 ¤   ¤   *seriallen = buf2len;
17af5a
ddb08b ¤   /* Should be signature algorithm identifier SEQUENCE */
e7d1e6 ¤   buf2 = buf;
296f74 ¤   tag = dotaglen(&buf, &len);
72a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
fe763f ¤   buf += len;
7bcb71 ¤   buf2len = buf - buf2;
bbaf5a
0ee83e ¤   if( IsntNull (sigalgbuf) )
095f44 ¤   ¤   *sigalgbuf = buf2;
32768f ¤   if( IsntNull (sigalglen) )
16a1ad ¤   ¤   *sigalglen = buf2len;
2daf5a
bafde7 ¤   /* Should be issuer name SEQUENCE */
52d1e6 ¤   buf2 = buf;
046f74 ¤   tag = dotaglen(&buf, &len);
c1a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
31763f ¤   buf += len;
12cb71 ¤   buf2len = buf - buf2;
3aaf5a
e33aa3 ¤   if( IsntNull (issuerbuf) )
dfdc2b ¤   ¤   *issuerbuf = buf2;
9ca412 ¤   if( IsntNull (issuerlen) )
cd4883 ¤   ¤   *issuerlen = buf2len;
15af5a
5443dc ¤   /* Should be validity SEQUENCE */
07d1e6 ¤   buf2 = buf;
0e6f74 ¤   tag = dotaglen(&buf, &len);
b6a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
f7763f ¤   buf += len;
a6cb71 ¤   buf2len = buf - buf2;
50af5a
5b73a6 ¤   if( IsntNull (validitybuf) )
718c4c ¤   ¤   *validitybuf = buf2;
74ed17 ¤   if( IsntNull (validitylen) )
d3123c ¤   ¤   *validitylen = buf2len;
f6af5a
8eda96 ¤   /* Should be subject name SEQUENCE */
2cd1e6 ¤   buf2 = buf;
d26f74 ¤   tag = dotaglen(&buf, &len);
2da6cb ¤   EXPECT(tag, TAG_SEQUENCE);
1e763f ¤   buf += len;
9dcb71 ¤   buf2len = buf - buf2;
caaf5a
f613bf ¤   if( IsntNull (subjectbuf) )
784f71 ¤   ¤   *subjectbuf = buf2;
d58d0e ¤   if( IsntNull (subjectlen) )
4c8b2f ¤   ¤   *subjectlen = buf2len;
f3af5a
29cbf1 ¤   /* Should be subject public key info SEQUENCE */
b2d1e6 ¤   buf2 = buf;
446f74 ¤   tag = dotaglen(&buf, &len);
e4a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
7e763f ¤   buf += len;
14cb71 ¤   buf2len = buf - buf2;
daaf5a
0ed5b2 ¤   if( IsntNull (publickeyinfobuf) )
a49719 ¤   ¤   *publickeyinfobuf = buf2;
--c63b 0002bd7a1f340100237 Page 25 of pgpX509Keys.c
214b03 ¤   if( IsntNull (publickeyinfolen) )
1ad95b ¤   ¤   *publickeyinfolen = buf2len;
33af5a
8f60ff error:
965ea8 ¤   return err;
d7efe6 }
05af5a
37af5a
dfaf5a
9738e5 /*
fe1e65 ·* Given an X.509 cert, fill a buffer with a PGP formatted
6d5817 ·* userid packet in it corresponding to the name in the cert.
d1beb7 ·* Use the ringpool's reserve buffer.
d8a6cb ·* The packet does not include the PGP headers, just the body.
4a495d ·*/
90c77d PGPError
f6a1a5 pgpX509CertToNameBuffer (RingPool *pool, PGPByte *buf, PGPSize len,
4f8527 ¤   PGPSize *pktlen)
dcbb36 {
d6504a ¤   PGPUInt32 tag;
bef54f ¤   PGPByte *namebuf;
c13e11 ¤   PGPSize namelen;
1bc55b ¤   PGPError err = kPGPError_NoErr;
aeaf5a
956b70 ¤   /* Should be the overall certificate SEQUENCE */
436f74 ¤   tag = dotaglen(&buf, &len);
68a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
e6af5a
8c8aed ¤   /* Should be certificate info SEQUENCE */
c96f74 ¤   tag = dotaglen(&buf, &len);
80a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
b2af5a
4da7fa ¤   /* May be X509 version number */
946f74 ¤   tag = dotaglen(&buf, &len);
b4d36f ¤   if (tag == TAG_ZERO) {
b5e14c ¤   ¤   buf += len;
51e488 ¤   ¤   tag = dotaglen(&buf, &len);
209371 ¤   }
eeaf5a
7c24f4 ¤   /* Should be serial number INTEGER */
6707ac ¤   EXPECT(tag, TAG_INTEGER);
01763f ¤   buf += len;
6eaf5a
2fb08b ¤   /* Should be signature algorithm identifier SEQUENCE */
0f6f74 ¤   tag = dotaglen(&buf, &len);
a5a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
3f763f ¤   buf += len;
12af5a
55fde7 ¤   /* Should be issuer name SEQUENCE */
b66f74 ¤   tag = dotaglen(&buf, &len);
95a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
0c763f ¤   buf += len;
c0af5a
2243dc ¤   /* Should be validity SEQUENCE */
a76f74 ¤   tag = dotaglen(&buf, &len);
27a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
ea763f ¤   buf += len;
f1af5a
c5da96 ¤   /* Should be subject name SEQUENCE */
456f74 ¤   tag = dotaglen(&buf, &len);
94a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
18e0cd ¤   err = sDecodeName (buf, len, NULL, &namelen);
5382f0 ¤   if (IsPGPError(err))
9897ed ¤   ¤   goto error;
821241 ¤   namebuf = (PGPByte *)ringReserve(pool, namelen);
2475bf ¤   if (IsNull(namebuf)) {
5ebce1 ¤   ¤   err = kPGPError_OutOfMemory;
1797ed ¤   ¤   goto error;
d59371 ¤   }
ba7f17 ¤   err = sDecodeName (buf, len, namebuf, &namelen);
f982f0 ¤   if (IsPGPError(err))
2b97ed ¤   ¤   goto error;
--5ae0 0000fb45b4340100237 Page 26 of pgpX509Keys.c
e0af5a
e39936 ¤   *pktlen = namelen;
85af5a
d160ff error:
ddaf5a
dc5ea8 ¤   return err;
f6efe6 }
39af5a
7daf5a
ff38e5 /*
441e65 ·* Given an X.509 cert, fill a buffer with a PGP formatted
616516 ·* key packet in it corresponding to the key data in the cert.
8fbeb7 ·* Use the ringpool's reserve buffer.
fda6cb ·* The packet does not include the PGP headers, just the body.
42495d ·*/
ccc77d PGPError
524f91 pgpX509CertToKeyBuffer (RingPool *pool, PGPByte *buf, PGPSize len,
348527 ¤   PGPSize *pktlen)
88bb36 {
96504a ¤   PGPUInt32 tag;
48f7fb ¤   PGPByte *keybuf;
984c2a ¤   PGPSize keylen;
8ac55b ¤   PGPError err = kPGPError_NoErr;
57af5a
0d6b70 ¤   /* Should be the overall certificate SEQUENCE */
eb6f74 ¤   tag = dotaglen(&buf, &len);
3ca6cb ¤   EXPECT(tag, TAG_SEQUENCE);
50af5a
9f8aed ¤   /* Should be certificate info SEQUENCE */
0e6f74 ¤   tag = dotaglen(&buf, &len);
e0a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
3caf5a
12a7fa ¤   /* May be X509 version number */
0e6f74 ¤   tag = dotaglen(&buf, &len);
bbd36f ¤   if (tag == TAG_ZERO) {
72e14c ¤   ¤   buf += len;
0ae488 ¤   ¤   tag = dotaglen(&buf, &len);
af9371 ¤   }
fdaf5a
a424f4 ¤   /* Should be serial number INTEGER */
c807ac ¤   EXPECT(tag, TAG_INTEGER);
17763f ¤   buf += len;
18af5a
65b08b ¤   /* Should be signature algorithm identifier SEQUENCE */
c86f74 ¤   tag = dotaglen(&buf, &len);
4da6cb ¤   EXPECT(tag, TAG_SEQUENCE);
22763f ¤   buf += len;
f4af5a
c7fde7 ¤   /* Should be issuer name SEQUENCE */
d96f74 ¤   tag = dotaglen(&buf, &len);
5ca6cb ¤   EXPECT(tag, TAG_SEQUENCE);
9d763f ¤   buf += len;
e7af5a
2943dc ¤   /* Should be validity SEQUENCE */
826f74 ¤   tag = dotaglen(&buf, &len);
51a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
3b763f ¤   buf += len;
daaf5a
a2da96 ¤   /* Should be subject name SEQUENCE */
7b6f74 ¤   tag = dotaglen(&buf, &len);
94a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
dd763f ¤   buf += len;
73af5a
cfcbf1 ¤   /* Should be subject public key info SEQUENCE */
526f74 ¤   tag = dotaglen(&buf, &len);
87a6cb ¤   EXPECT(tag, TAG_SEQUENCE);
7faf5a
85216c ¤   err = sDecodeKey (buf, len, NULL, &keylen);
3c82f0 ¤   if (IsPGPError(err))
9597ed ¤   ¤   goto error;
c31d39 ¤   keybuf = (PGPByte *)ringReserve(pool, keylen);
0fb1b6 ¤   if (IsNull(keybuf)) {
--2ab3 001fc3477e640100237 Page 27 of pgpX509Keys.c
e1bce1 ¤   ¤   err = kPGPError_OutOfMemory;
9097ed ¤   ¤   goto error;
da9371 ¤   }
24eb44 ¤   err = sDecodeKey (buf, len, keybuf, &keylen);
2482f0 ¤   if (IsPGPError(err))
4097ed ¤   ¤   goto error;
c9af5a
3071a8 ¤   *pktlen = keylen;
8aaf5a
9360ff error:
26af5a
815ea8 ¤   return err;
a7efe6 }
05af5a
2caf5a
ccaf5a
1a38e5 /*
f11e65 ·* Given an X.509 cert, fill a buffer with a PGP formatted
1c406f ·* userid packet in it corresponding to the signature in the cert.
c4beb7 ·* Use the ringpool's reserve buffer.
98a6cb ·* The packet does not include the PGP headers, just the body.
48495d ·*/
9fc77d PGPError
76db56 pgpX509CertToSigBuffer (RingPool *pool, PGPByte *buf, PGPSize len,
038527 ¤   PGPSize *pktlen)
d3bb36 {
aaf066 ¤   PGPSize siglen;
574bb7 ¤   PGPByte *sigbuf;
cac55b ¤   PGPError err = kPGPError_NoErr;
5baf5a
8a481d ¤   (void) len;
67af5a
1e9c12 ¤   err = sDecodeSig(buf, NULL, &siglen);
7882f0 ¤   if (IsPGPError(err))
be97ed ¤   ¤   goto error;
b3cbfb ¤   sigbuf = (PGPByte *)ringReserve(pool, siglen);
2081ad ¤   if (IsNull(sigbuf)) {
09bce1 ¤   ¤   err = kPGPError_OutOfMemory;
6997ed ¤   ¤   goto error;
d29371 ¤   }
4fdd0e ¤   err = sDecodeSig (buf, sigbuf, &siglen);
cf82f0 ¤   if (IsPGPError(err))
0497ed ¤   ¤   goto error;
12af5a
b3cde4 ¤   *pktlen = siglen;
28af5a
0960ff error:
3faf5a
f75ea8 ¤   return err;
fcefe6 }
--7db9 00175aa91df40100238 Page 1 of pgpX509Priv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
1c714b ¤   $Id: pgpX509Priv.h,v 1.1.12.1 1998/11/12 03:22:08 heller Exp $
89f7f7 ____________________________________________________________________________*/
8faf5a
62d843 #ifndef Included_pgpX509Priv_h
99afb0 #define Included_pgpX509Priv_h
20af5a
a2af5a
8599c6 PGP_BEGIN_C_DECLARATIONS
b7af5a
f3bd15 /* Internal functions */
dfaf5a
6d25e6 PGPError¤   ¤   pgpX509CertToSigBuffer (RingPool *pool, PGPByte *buf,
cc83ed ¤   ¤   ¤   ¤   ¤   ¤   PGPSize len, PGPSize *pktlen);
e7af5a
a86048 PGPError¤   ¤   pgpX509CertToKeyBuffer (RingPool *pool, PGPByte *buf,
7683ed ¤   ¤   ¤   ¤   ¤   ¤   PGPSize len, PGPSize *pktlen);
e5af5a
6ab723 PGPError¤   ¤   pgpX509CertToNameBuffer (RingPool *pool, PGPByte *buf,
cf83ed ¤   ¤   ¤   ¤   ¤   ¤   PGPSize len, PGPSize *pktlen);
25af5a
f30036 PGPError¤   ¤   pgpX509CertInfoPartition( PGPByte *buf, PGPSize len,
f8f931 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **serialbuf, PGPSize *seriallen,
813538 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **sigalgbuf, PGPSize *sigalglen,
66e0ed ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **issuerbuf, PGPSize *issuerlen,
c1e1ba ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **validitybuf, PGPSize *validitylen,
636ad0 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **subjectbuf, PGPSize *subjectlen,
9a1d4d ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **publickeyinfobuf, PGPSize *publickeyinfolen);
0faf5a
045e8c PGPError¤   ¤   pgpX509CertPartition( PGPByte *buf, PGPSize len,
bbbb15 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **certinfobuf, PGPSize *certinfolen,
8b3538 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **sigalgbuf, PGPSize *sigalglen,
54fe4b ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **sigbuf, PGPSize *siglen );
2aaf5a
76af5a
c01254 PGP_END_C_DECLARATIONS
74af5a
c457f2 #endif /* pgpX509Priv.h */
a5af5a
ff38e5 /*
bae6c5 ·* Local Variables:
ac9b19 ·* tab-width: 4
67e7a4 ·* End:
8eb612 ·* vi: ts=4 sw=4
3d6c42 ·* vim: si
75495d ·*/
--4c10 0014fb49a0040100239 Page 1 of Makefile.in
5ea601 #
d5a90e # priv/networklib/
1fa601 #
42fef4 # $Id: Makefile.in,v 1.4 1998/08/05 05:36:56 heller Exp $
cfa601 #
63af5a
4ffd38 .SUFFIXES: .cpp .cp
59af5a
ebd0f7 .cpp.o:
34dfd6 ¤   g++ -c -fhandle-exceptions $(CFLAGS) $<
0caf5a
3b7631 LDAPDIR= $(top_srcdir)/../network/ldaplib
fdab19 LIBLBERDIR= $(LDAPDIR)/liblber
4b7076 LIBLDAPDIR= $(LDAPDIR)/libldap
f2af5a
8987c2 SUBDIRS= pgpsockets keyserver tls
0baf5a
e916eb LOCALDEFINES= -DPROTOTYPES -D_REENTRANT
d08597 LOCALINCLUDES= -I./pgpsockets/pub -I$(LDAPDIR)/include
1baf5a
056cce LIBDONE= DONE $(LIBLBERDIR)/DONE \
b2703b ¤   $(LIBLDAPDIR)/DONE keyserver/DONE pgpsockets/LIBDONE tls/DONE
6d41e7 LIBTDEPS= LIBDONE
729498 LIBTARGET= $(top_srcdir)/unix/libPGPsdkNetwork.a
9daf5a
199f6e INSTALLLIBS= $(LIBTARGET)
85af5a
c263c2 all depend clean::
24d353 ¤   @for i in $(LDAPDIR); do \
e03d10 ¤   ¤   echo Making $@ in $(SUB)$$i; \
62da87 ¤   ¤   (cd $$i; $(MAKE) $(MFLAGS) SUB=$(SUB)$$i/ \
29304d ¤   ¤   ¤   $@) || exit 1; \
1a5a47 ¤   done
8baf5a
2eb34c all:: LIBDONE $(LIBTARGET)
1daf5a
ea53f5 clean::
4f1b0f ¤   rm -f $(LIBTARGET)
--ad25 0002a43a4204010023a Page 1 of CHTTPKeyServer.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
48d579 ¤   $Id: CHTTPKeyServer.cpp,v 1.24.10.1 1998/11/12 03:22:14 heller Exp $
fdf7f7 ____________________________________________________________________________*/
18af5a
de324c #include <string.h>
44b1cb #include <ctype.h>
22af5a
e30d08 #include "pgpMem.h"
cefb31 #include "pgpOptionList.h"
be2d40 #include "pgpEventPriv.h"
faa076 #include "pgpKeys.h"
4f1b42 #include "pgpStrings.h"
7baf5a
5d0394 #include "CHTTPKeyServer.h"
43af5a
d2af5a
0daf5a
8ef6e5 static const PGPUInt32¤ kDefaultBufferSize = 4096;
2a4d84 static const char *¤¤   kQueryPrefix = "GET /pks/lookup?op=get&";
48bae7 static const char *¤¤   kQuerySuffix = " HTTP/1.0\x0D\x0A";
5a0ccc #if PGP_MACINTOSH
e63e21 static const char *¤¤   kUserAgent =·
1bc00e ¤   ¤   ¤   ¤   ¤   ¤   ¤   "User-Agent: PGP (Macintosh)\x0D\x0A";
8c14ea #elif PGP_WIN32
583e21 static const char *¤¤   kUserAgent =·
2e130a ¤   ¤   ¤   ¤   ¤   ¤   ¤   "User-Agent: PGP (Windows)\x0D\x0A";
42bac4 #elif PGP_UNIX
323e21 static const char *¤¤   kUserAgent =·
a27c8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   "User-Agent: PGP (UNIX)\x0D\x0A";
217454 #endif
339513 static const char *¤¤   kUploadPrefix = "POST /pks/add HTTP/1.0\x0D\x0A";
d815b0 static const char *¤¤   kContentLength = "Content-length: ";
46bcb6 static const char *¤¤   kContentType =·
0908a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "Content-type: application/x-www-form-urlencoded\x0¶
d0cd56 D\x0A\x0D\x0A";
1b84d8 static const char *¤¤   kPostPrefix = "keytext=";
d3ee3f static const char *¤¤   kHexString = "0123456789ABCDEF";
054b3c static const char *¤¤   kHeadBeginTag = "<head";
4c2dbc static const char *¤¤   kHeadEndTag = "</head>";
fb3988 static const char *¤¤   kTitleBeginTag = "<title";
c9a717 static const char *¤¤   kTitleEndTag = "</title>";
0b484b static const char *¤¤   kH1BeginTag = "<h1";
7ea00d static const char *¤¤   kH1EndTag = "</h1>";
370ebb static const char *¤¤   kPreBeginTag = "<pre>";
67af5a
97d252 static const char *¤¤   kKeyServerMessages[] =
93531a ¤   { "Key block corrupt: pubkey decode failed",
3441f2 ¤   ··"Key block added to key server database.\x0A"\
cf05dd ¤   ··¤ " ·New public keys added: ",
203c81 ¤   ··"Key block in add request contained no new\x0A"\
be20c9 ¤   ··¤ "keys, userid's, or signatures.",
ffcdc1 ¤   ··"Timed out waiting for LDAP response\x0A",
225198 ¤   ··"No matches\x0A",
34b313 ¤   ··"No matching keys in database",
f5b30c ¤   ··"-----BEGIN",
55ce3d ¤   ··NULL };
62c304 static const PGPError¤  kKeyServerErrors[] =
12d88e ¤   { kPGPError_ServerCorruptKeyBlock,
7ba2c8 ¤   ··kPGPError_NoErr,
623477 ¤   ··kPGPError_ServerKeyAlreadyExists,
041879 ¤   ··kPGPError_ServerTimedOut,
31a2c8 ¤   ··kPGPError_NoErr,
89a2c8 ¤   ··kPGPError_NoErr,
a9e4cb ¤   ··kPGPError_NoErr };
53af5a
c0af5a
2ae9b5 CHTTPKeyServer::CHTTPKeyServer(
--4251 000960813df4010023a Page 2 of CHTTPKeyServer.cpp
bff09f ¤   PGPContextRef¤  ¤   inContext,
a87b09 ¤   const char *¤   ¤   inHostName,
5b7687 ¤   PGPUInt32¤  ¤   ¤   inHostAddress,
39ee2f ¤   PGPUInt16¤  ¤   ¤   inHostPort,
6b401f ¤   PGPKeyServerType¤   inType)
bbd3ca ¤   : CKeyServer(inContext, inHostName, inHostAddress, inHostPort, inType),
61c579 ¤   ··mSocket(kInvalidPGPSocketRef)
32bb36 {
c0efe6 }
5aaf5a
80af5a
2caf5a
76307f CHTTPKeyServer::~CHTTPKeyServer()
edbb36 {
c8efe6 }
78af5a
b0af5a
7eaf5a
816d52 ¤   void
974d3d CHTTPKeyServer::Cancel()
85bb36 {
d5ace7 ¤   CKeyServer::Cancel();
3d15eb ¤   if (mIsBusy && (mSocket != kInvalidPGPSocketRef)) {
88938f ¤   ¤   PGPCloseSocket(mSocket);
70763e ¤   ¤   mSocket = kInvalidPGPSocketRef;
3e9371 ¤   }
24efe6 }
deaf5a
b6af5a
1daf5a
3c6d52 ¤   void
a5e2e2 CHTTPKeyServer::Query(
d96917 ¤   PGPFilterRef¤   inFilterRef,
82e331 ¤   PGPKeySetRef *¤ outFoundKeys)
e4bb36 {
abda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
86158c ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   query = NULL;
d30eb9 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   pgpError = kPGPError_NoErr;
38d564 ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   buffer = NULL;
a5ad9a ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   ¤   bufferSize = 0;
5e1b52 ¤   ¤
127452 ¤   SetErrorString(NULL);
8a7200 ¤   if (! mIsOpen) {
e9c8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
5f9371 ¤   }
c5af5a
cb5168 ¤   try {
d3fd06 ¤   ¤   // Establish connection
9c3381 ¤   ¤   PGPSocketAddressInternet¤   address;
cb767d ¤   ¤   PGPInt32¤   ¤   ¤   ¤   ¤   socketResult;
051b52 ¤   ¤
0b0b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
fd46a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
b77c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
d7a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
a8354a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Opening);
46f918 ¤   ¤   ThrowIfPGPError_(pgpError);
061b52 ¤   ¤
33dfe0 ¤   ¤   mSocket = PGPOpenSocket(¤   kPGPAddressFamilyInternet,
8424a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPSocketTypeStream,
f7ad1e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPTCPProtocol);
797e23 ¤   ¤   if (mSocket == kInvalidPGPSocketRef) {
a85b01 ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
cc0fe4 ¤   ¤   }
a8cd91 ¤   ¤   if (mCanceled) {
6a45f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
c30fe4 ¤   ¤   }
3f171e ¤   ¤   address.sin_family = kPGPAddressFamilyInternet;
9ffb7a ¤   ¤   address.sin_port = PGPHostToNetShort(mHostPort);
d3f7b0 ¤   ¤   address.sin_addr.s_addr = PGPHostToNetLong(mHostAddress);
72baa1 ¤   ¤   socketResult = PGPConnect(¤ mSocket,
961f79 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPSocketAddress *) &address,
--d8e0 000f86164be4010023a Page 3 of CHTTPKeyServer.cpp
cc3ca6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(address));
91386e ¤   ¤   if (socketResult == kPGPSockets_Error) {
745b01 ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
f50fe4 ¤   ¤   }
1a1b52 ¤   ¤
151e99 ¤   ¤   // Secure connection for HTTPS
7bc986 ¤   ¤   if (mType == kPGPKeyServerType_HTTPS) {
9a15cf ¤   ¤   ¤   if ((mTLSSession == kInvalidPGPtlsSessionRef)
63b53f ¤   ¤   ¤   || (PGPSocketsEstablishTLSSession(mSocket, mTLSSession) !=
43c099 ¤   ¤   ¤   kPGPError_NoErr)) {
c311c8 ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerTLS(
2bea91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
cd8f34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
bb6a72 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
cde9cb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
75c4ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_TLSUnableToSecureConnection,
c18e95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mTLSSession);
71042d ¤   ¤   ¤   } else {
dd11c8 ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerTLS(
2aea91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
9f8f34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
f66a72 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
0be9cb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
d5d56c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_TLSConnectionSecured,
a38e95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mTLSSession);
ba9ef8 ¤   ¤   ¤   ¤   mSecured = true;
7ca3a6 ¤   ¤   ¤   }
de3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
d40fe4 ¤   ¤   }
1e1b52 ¤   ¤
eb2be7 ¤   ¤   // Build and send query
fc0b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
e846a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
e37c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
cda280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
9859d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Querying);
56f918 ¤   ¤   ThrowIfPGPError_(pgpError);
b36ded ¤   ¤   pgpError = PGPHKSQueryFromFilter(inFilterRef, &query);
a4f918 ¤   ¤   ThrowIfPGPError_(pgpError);
4b3cae ¤   ¤   bufferSize = strlen(kQueryPrefix) + strlen(query) +
3fa18c ¤   ¤   ¤   ¤   ¤   ¤   strlen(kQuerySuffix) + strlen(kUserAgent) + 3;
6f2dfb ¤   ¤   buffer = new char[bufferSize];
7f9ebb ¤   ¤   if (buffer == NULL) {
6ace01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
3a0fe4 ¤   ¤   }
1ba419 ¤   ¤   sprintf(¤   buffer,
55139a ¤   ¤   ¤   ¤   ¤   "%s%s%s%s%s",
87041b ¤   ¤   ¤   ¤   ¤   kQueryPrefix,
d51b6d ¤   ¤   ¤   ¤   ¤   query,
9d45ae ¤   ¤   ¤   ¤   ¤   kQuerySuffix,
1ae479 ¤   ¤   ¤   ¤   ¤   kUserAgent,
156fb4 ¤   ¤   ¤   ¤   ¤   "\x0D\x0A");
60c136 ¤   ¤   PGPFreeData(query);
4579df ¤   ¤   query = NULL;
a1cf71 ¤   ¤   socketResult = PGPSend(¤mSocket,
48005e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer,
b55e78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufferSize - 1,
70a481 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPSendFlagNone);
26dbe0 ¤   ¤   if (socketResult != (PGPInt32) (bufferSize - 1)) {
ac5b01 ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
9c0fe4 ¤   ¤   }
6027ad ¤   ¤   delete[] buffer;
cdb516 ¤   ¤   buffer = NULL;
0d1b52 ¤   ¤
cfc466 ¤   ¤   // Receive results
640b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
5746a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
087c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
bda280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
c686c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_ProcessingResults);
08f918 ¤   ¤   ThrowIfPGPError_(pgpError);
f8ef23 ¤   ¤   bufferSize = ReceiveResult(&buffer);
--4c41 000d7a43c7c4010023a Page 4 of CHTTPKeyServer.cpp
f11b52 ¤   ¤
259248 ¤   ¤   // Close connection
410b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
e546a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
d47c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
c9a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
05ee11 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Closing);
01f918 ¤   ¤   ThrowIfPGPError_(pgpError);
c24722 ¤   ¤   if (mSecured) {
ada5e9 ¤   ¤   ¤   PGPtlsClose(mTLSSession, false);
657e29 ¤   ¤   ¤   mSecured = false;
520fe4 ¤   ¤   }
67938f ¤   ¤   PGPCloseSocket(mSocket);
73763e ¤   ¤   mSocket = kInvalidPGPSocketRef;
571b52 ¤   ¤
470dd3 ¤   ¤   // Import the keyset
3d63f3 ¤   ¤   pgpError = ProcessHTTPResult(buffer);
45f918 ¤   ¤   ThrowIfPGPError_(pgpError);
66730d ¤   ¤   pgpError = PGPImportKeySet(¤mContext,
ed74db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outFoundKeys,
ffb37c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOInputBuffer(¤   mContext,
e718ce ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer,
239bc6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufferSize),
df2d7c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption(mContext));
71f918 ¤   ¤   ThrowIfPGPError_(pgpError);
b327ad ¤   ¤   delete[] buffer;
509371 ¤   }
9167c5 ¤
fee0a3 ¤   catch (...) {
220d01 ¤   ¤   if (buffer != NULL) {
6013f0 ¤   ¤   ¤   delete[] buffer;
290fe4 ¤   ¤   }
db5870 ¤   ¤   if (query != NULL) {
546c68 ¤   ¤   ¤   PGPFreeData(query);
1e0fe4 ¤   ¤   }
ceb1a5 ¤   ¤   if (mSocket != kInvalidPGPSocketRef) {
a1aee7 ¤   ¤   ¤   PGPCloseSocket(mSocket);
b9fe58 ¤   ¤   ¤   mSocket = kInvalidPGPSocketRef;
d80fe4 ¤   ¤   }
aacd91 ¤   ¤   if (mCanceled) {
0e45f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
4345a6 ¤   ¤   } else {
094199 ¤   ¤   ¤   throw;
7b0fe4 ¤   ¤   }
2d9371 ¤   }
6fefe6 }
f067c5 ¤
a767c5 ¤
e267c5 ¤
806d52 ¤   void
d8f5b1 CHTTPKeyServer::Upload(
dad2e4 ¤   PGPKeyUploadPreference inSendPrivateKeys,
a908e0 ¤   PGPKeySetRef¤   inKeysToUpload,
6c6a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
12bb36 {
7eda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
9b0eb9 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   pgpError = kPGPError_NoErr;
c5ff8f ¤   PGPKeySetRef¤   ¤   ¤   ¤   ¤   errorKeySet = kInvalidPGPKeySetRef;
195fa7 ¤   PGPKeyListRef¤  ¤   ¤   ¤   ¤   keyList = kInvalidPGPKeyListRef;
73d193 ¤   PGPKeyIterRef¤  ¤   ¤   ¤   ¤   keyIter = kInvalidPGPKeyIterRef;
156802 ¤   PGPKeySetRef¤   ¤   ¤   ¤   ¤   singleKeySet = kInvalidPGPKeySetRef;
e7dbfa ¤   PGPByte *¤  ¤   ¤   ¤   ¤   ¤   buffer = NULL;
23aac0 ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   urlEncodedBuffer = NULL;
4b5c22 ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   sendBuffer = NULL;
c0a948 ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   receiveBuffer = NULL;
fff02b ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   partialFailure = false;
8a3432 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   keyAlreadyExists = false;
8e9a0b ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   exportPrivateKeys = false;
5767c5 ¤
df7452 ¤   SetErrorString(NULL);
1b7200 ¤   if (! mIsOpen) {
d7a115 ¤   ¤   ThrowIfPGPError_(kPGPError_ServerNotOpen);
--87f9 000261c6a004010023a Page 5 of CHTTPKeyServer.cpp
a19371 ¤   }
9967c5 ¤
88ed9d ¤   if (inSendPrivateKeys == kPGPPrivateKeyAllowed) {
6baf5a
f15ad1 ¤   ¤   if (mType != kPGPKeyServerType_HTTPS) {
84ffc7 ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOperationRequiresTLS);
630fe4 ¤   ¤   }
d6af5a
5a123f ¤   ¤   exportPrivateKeys = true;
449371 ¤   }
23af5a
c35168 ¤   try {
f13381 ¤   ¤   PGPSocketAddressInternet¤   address;
c675ea ¤   ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   bufSize;
b2c993 ¤   ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   key;
4d767d ¤   ¤   PGPInt32¤   ¤   ¤   ¤   ¤   socketResult;
05af5a
d51316 ¤   ¤   // Create error set
f50f1f ¤   ¤   pgpError = PGPNewKeySet(mContext, &errorKeySet);
51f918 ¤   ¤   ThrowIfPGPError_(pgpError);
fc1b52 ¤   ¤
9bd6ba ¤   ¤   // Iterate through keys uploading them one at a time
22b80f ¤   ¤   pgpError = PGPOrderKeySet(¤ inKeysToUpload,
0015b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPAnyOrdering,
ce3a97 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyList);
17f918 ¤   ¤   ThrowIfPGPError_(pgpError);
1f3433 ¤   ¤   pgpError = PGPNewKeyIter(keyList, &keyIter);
d2f918 ¤   ¤   ThrowIfPGPError_(pgpError);
f9171e ¤   ¤   address.sin_family = kPGPAddressFamilyInternet;
e6fb7a ¤   ¤   address.sin_port = PGPHostToNetShort(mHostPort);
6af7b0 ¤   ¤   address.sin_addr.s_addr = PGPHostToNetLong(mHostAddress);
bd1951 ¤   ¤   while ((pgpError = PGPKeyIterNext(keyIter, &key)) == kPGPError_NoErr) {
2b05c5 ¤   ¤   ¤   // Export the key
13a618 ¤   ¤   ¤   pgpError = PGPNewSingletonKeySet(key, &singleKeySet);
aa3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
dc98c1 ¤   ¤   ¤   pgpError = PGPExportKeySet(
5dce53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   singleKeySet,
051aee ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOExportPrivateKeys(mContext,
a3e9de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   exportPrivateKeys),
e2d830 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOAllocatedOutputBuffer(
91311c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
28482c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &buffer,
f1ac29 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   MAX_PGPSize,
fe5eb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &bufSize),
0acd64 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOExportFormat(mContext,
97867c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPExportFormat_Basic),
242aa5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption(mContext));
c2af5a
2c3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
1c87c7 ¤   ¤   ¤
bfb12a ¤   ¤   ¤   // URL encode the buffer
2720c2 ¤   ¤   ¤   urlEncodedBuffer = new char[(bufSize * 6) + 1];
e3dfc0 ¤   ¤   ¤   if (urlEncodedBuffer == NULL) {
51df26 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
e2a3a6 ¤   ¤   ¤   }
67e0a2 ¤   ¤   ¤   bufSize = URLEncode((char *) buffer, bufSize, urlEncodedBuffer);
a2dabd ¤   ¤   ¤   PGPFreeData(buffer);
d957f7 ¤   ¤   ¤   buffer = NULL;
5087c7 ¤   ¤   ¤
07adbf ¤   ¤   ¤   // Connect to server
68a58b ¤   ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
8e419a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
077c8c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
1b9fee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
37323c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Opening);
cc3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
31521c ¤   ¤   ¤   mSocket = PGPOpenSocket(¤   kPGPAddressFamilyInternet,
e0c6a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPSocketTypeStream,
baae69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPTCPProtocol);
d6a691 ¤   ¤   ¤   if (mSocket == kInvalidPGPSocketRef) {
5c5876 ¤   ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
26a3a6 ¤   ¤   ¤   }
--647e 000a6d53e634010023a Page 6 of CHTTPKeyServer.cpp
3ff9cc ¤   ¤   ¤   if (mCanceled) {
cc16e8 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
e0a3a6 ¤   ¤   ¤   }
5ae83c ¤   ¤   ¤   socketResult = PGPConnect(¤ mSocket,
020cf5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPSocketAddress *) &address,
853fd1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(address));
ff6b75 ¤   ¤   ¤   if (socketResult == kPGPSockets_Error) {
de5876 ¤   ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
03a3a6 ¤   ¤   ¤   }
2f87c7 ¤   ¤   ¤
bb10d5 ¤   ¤   ¤   // Secure connection for HTTPS
555fc7 ¤   ¤   ¤   if (mType == kPGPKeyServerType_HTTPS) {
26f7cf ¤   ¤   ¤   ¤   if ((mTLSSession == kInvalidPGPtlsSessionRef)
0c6594 ¤   ¤   ¤   ¤   || (PGPSocketsEstablishTLSSession(mSocket, mTLSSession) !=
134b65 ¤   ¤   ¤   ¤   kPGPError_NoErr)) {
b842d3 ¤   ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerTLS(
37d354 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
1a5786 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
567b55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
97669c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
09c4ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_TLSUnableToSecureConnection,
1fc1ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mTLSSession);
4ab5fc ¤   ¤   ¤   ¤   } else {
6542d3 ¤   ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerTLS(
18d354 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
de5786 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
c87b55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
54669c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
ed48b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_TLSConnectionSecured,
42c1ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mTLSSession);
50a390 ¤   ¤   ¤   ¤   ¤   mSecured = true;
2d2613 ¤   ¤   ¤   ¤   }
3cb42b ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
aaa3a6 ¤   ¤   ¤   }
1687c7 ¤   ¤   ¤
297266 ¤   ¤   ¤   // Send the buffer
bba58b ¤   ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
be419a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
087c8c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
379fee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
914775 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Uploading);
7b3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
8598ab ¤   ¤   ¤   sendBuffer = new char[bufSize + 256];
c6fddb ¤   ¤   ¤   if (sendBuffer == NULL) {
98df26 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
85a3a6 ¤   ¤   ¤   }
f4994b ¤   ¤   ¤   bufSize = sprintf(¤ sendBuffer,
66be1c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%s%s%s%lu%s%s%s%s",
301b9e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kUploadPrefix,
2322b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kUserAgent,
edad47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kContentLength,
158d53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (unsigned long) bufSize + strlen(kPostPrefix),
914adb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "\x0D\x0A",
286f11 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kContentType,
5ee801 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPostPrefix,
6131d5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   urlEncodedBuffer);
35e17a ¤   ¤   ¤   delete[] urlEncodedBuffer;
89f120 ¤   ¤   ¤   urlEncodedBuffer = NULL;
97c9c9 ¤   ¤   ¤   socketResult = PGPSend(¤mSocket,
a887bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sendBuffer,
21be2d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufSize,
76b5a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPSendFlagNone);
0307fc ¤   ¤   ¤   if (socketResult != (PGPInt16) bufSize) {
6f5876 ¤   ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
ada3a6 ¤   ¤   ¤   }
9f7f99 ¤   ¤   ¤   delete[] sendBuffer;
282e74 ¤   ¤   ¤   sendBuffer = NULL;
7387c7 ¤   ¤   ¤
471dfa ¤   ¤   ¤   // Receive result
02a5a7 ¤   ¤   ¤   pgpError = pgpEventKeyServer(
3bd354 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
a65786 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
--1864 000ebb784cc4010023a Page 7 of CHTTPKeyServer.cpp
167b55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
88669c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
936be3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_ProcessingResults);
9b3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
1575ef ¤   ¤   ¤   bufSize = ReceiveResult(&receiveBuffer);
568299 ¤   ¤   ¤   pgpError = ProcessHTTPResult(receiveBuffer);
ae3a58 ¤   ¤   ¤   delete[] receiveBuffer;
f23f06 ¤   ¤   ¤   receiveBuffer = NULL;
221d76 ¤   ¤   ¤   if (IsPGPError(pgpError)) {
6b23b7 ¤   ¤   ¤   ¤   PGPAddKeys(singleKeySet, errorKeySet);
5dede9 ¤   ¤   ¤   ¤   partialFailure = true;
a76eca ¤   ¤   ¤   ¤   if (pgpError == kPGPError_ServerKeyAlreadyExists) {
491e68 ¤   ¤   ¤   ¤   ¤   keyAlreadyExists = true;
782613 ¤   ¤   ¤   ¤   }
20a3a6 ¤   ¤   ¤   }
5d2453 ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
7770e0 ¤   ¤   ¤   singleKeySet = kInvalidPGPKeySetRef;
5c87c7 ¤   ¤   ¤
ec3f16 ¤   ¤   ¤   // Close connection
40a58b ¤   ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
52419a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
3e7c8c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
8f9fee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
35e967 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Closing);
c13c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
76b147 ¤   ¤   ¤   if (mSecured) {
9948a5 ¤   ¤   ¤   ¤   PGPtlsClose(mTLSSession, FALSE);
6c433b ¤   ¤   ¤   ¤   mSecured = FALSE;
6ea3a6 ¤   ¤   ¤   }
7daee7 ¤   ¤   ¤   PGPCloseSocket(mSocket);
3afe58 ¤   ¤   ¤   mSocket = kInvalidPGPSocketRef;
d50fe4 ¤   ¤   }
c01b52 ¤   ¤
084142 ¤   ¤   if (IsPGPError(pgpError) && (pgpError != kPGPError_EndOfIteration)) {
eb9c10 ¤   ¤   ¤   ThrowPGPError_(pgpError);
ec0fe4 ¤   ¤   }
3910bc ¤   ¤   PGPFreeKeyIter(keyIter);
ed3aa0 ¤   ¤   keyIter = kInvalidPGPKeyIterRef;
99c7b5 ¤   ¤   PGPFreeKeyList(keyList);
e930e1 ¤   ¤   keyList = kInvalidPGPKeyListRef;
4cf1eb ¤   ¤   if (partialFailure) {
b3f4f6 ¤   ¤   ¤   *outKeysThatFailed = errorKeySet;
eddc17 ¤   ¤   ¤   errorKeySet = kInvalidPGPKeySetRef;
326ab0 ¤   ¤   ¤   if (keyAlreadyExists) {
07d571 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyAlreadyExists);
a0042d ¤   ¤   ¤   } else {
8e23c6 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerPartialAddFailure);
a8a3a6 ¤   ¤   ¤   }
ea45a6 ¤   ¤   } else {
6be503 ¤   ¤   ¤   PGPFreeKeySet(errorKeySet);
130fe4 ¤   ¤   }
4b9371 ¤   }
a667c5 ¤
09e0a3 ¤   catch (...) {
18d447 ¤   ¤   if (singleKeySet != kInvalidPGPKeySetRef) {
f32453 ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
310fe4 ¤   ¤   }
960d01 ¤   ¤   if (buffer != NULL) {
8edabd ¤   ¤   ¤   PGPFreeData(buffer);
f40fe4 ¤   ¤   }
75a089 ¤   ¤   delete[] urlEncodedBuffer;
6fc4cf ¤   ¤   delete[] sendBuffer;
7bb1a4 ¤   ¤   delete[] receiveBuffer;
9a2643 ¤   ¤   if (keyIter != kInvalidPGPKeyIterRef) {
022dd4 ¤   ¤   ¤   PGPFreeKeyIter(keyIter);
0d0fe4 ¤   ¤   }
f53530 ¤   ¤   if (keyList != kInvalidPGPKeyListRef) {
20fadd ¤   ¤   ¤   PGPFreeKeyList(keyList);
300fe4 ¤   ¤   }
e85b78 ¤   ¤   if (errorKeySet != kInvalidPGPKeySetRef) {
e8e503 ¤   ¤   ¤   PGPFreeKeySet(errorKeySet);
eb0fe4 ¤   ¤   }
--c59e 0000231de8d4010023a Page 8 of CHTTPKeyServer.cpp
98b1a5 ¤   ¤   if (mSocket != kInvalidPGPSocketRef) {
d6aee7 ¤   ¤   ¤   PGPCloseSocket(mSocket);
e7fe58 ¤   ¤   ¤   mSocket = kInvalidPGPSocketRef;
4a0fe4 ¤   ¤   }
2ccd91 ¤   ¤   if (mCanceled) {
3c45f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
ac45a6 ¤   ¤   } else {
8e4199 ¤   ¤   ¤   throw;
1d0fe4 ¤   ¤   }
099371 ¤   }
e3efe6 }
e6af5a
70108d ¤   PGPUInt32
5e4296 CHTTPKeyServer::ReceiveResult(
35bf81 ¤   char **¤outBuffer)
b4bb36 {
291ac1 ¤   PGPSize¤¤   ¤   ¤   result = 0;
2caa3f ¤   PGPSize¤¤   ¤   ¤   bufferSize = kDefaultBufferSize;
6e1adf ¤   char *¤ ¤   ¤   ¤   buffer = NULL;
d6e4c1 ¤   char *¤ ¤   ¤   ¤   tempBuffer = NULL;
78d6c2 ¤   PGPInt32¤   ¤   ¤   socketResult = 0;
b8ea4a ¤   char *¤ ¤   ¤   ¤   temp = NULL;
6c67c5 ¤
365168 ¤   try {
39f4a0 ¤   ¤   // Receive the data
e7ba85 ¤   ¤   tempBuffer = new char[kDefaultBufferSize];
bc1cec ¤   ¤   if (tempBuffer == NULL) {
6bce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
300fe4 ¤   ¤   }
61cb75 ¤   ¤   buffer = new char[bufferSize + 1];
9a9ebb ¤   ¤   if (buffer == NULL) {
d9ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
770fe4 ¤   ¤   }
e734ed ¤   ¤   socketResult = PGPReceive(¤ mSocket,
ffb13f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempBuffer,
9bdfb0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kDefaultBufferSize,
6db92e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPReceiveFlagNone);
93de0c ¤   ¤   while (socketResult > 0) {
4d69d3 ¤   ¤   ¤   if ((result + socketResult) > bufferSize) {
58d421 ¤   ¤   ¤   ¤   temp = NULL;
d72b85 ¤   ¤   ¤   ¤
14eb8b ¤   ¤   ¤   ¤   bufferSize += kDefaultBufferSize;
a2fa4d ¤   ¤   ¤   ¤   temp = new char[bufferSize + 1];
dfe80e ¤   ¤   ¤   ¤   if (temp == NULL) {
89d81d ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
4d2613 ¤   ¤   ¤   ¤   }
e7874b ¤   ¤   ¤   ¤   pgpCopyMemory(buffer, temp, result);
f2a8a6 ¤   ¤   ¤   ¤   delete[] buffer;
c9c935 ¤   ¤   ¤   ¤   buffer = temp;
dfa3a6 ¤   ¤   ¤   }
6b9f03 ¤   ¤   ¤   pgpCopyMemory(tempBuffer, buffer + result, socketResult);
b7ac51 ¤   ¤   ¤   result += socketResult;
c86670 ¤   ¤   ¤   socketResult = PGPReceive(¤ mSocket,
fa277e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempBuffer,
7350e7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kDefaultBufferSize,
165b2e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPReceiveFlagNone);
000fe4 ¤   ¤   }
e4f24f ¤   ¤   delete[] tempBuffer;
bc636b ¤   ¤   tempBuffer = NULL;
611b52 ¤   ¤
4e1544 ¤   ¤   // Check for errors
2c26c6 ¤   ¤   if (socketResult != 0) {
39e891 ¤   ¤   ¤   ThrowIfPGPError_(PGPGetLastSocketsError());
d30fe4 ¤   ¤   }
e99ebb ¤   ¤   if (buffer == NULL) {
cc6ebf ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerRequestFailed);
240fe4 ¤   ¤   }
821b52 ¤   ¤
0f96e7 ¤   ¤   // Everything good
50d4c6 ¤   ¤   buffer[result] = '\0';
3de2ce ¤   ¤   *outBuffer = buffer;
029371 ¤   }
--14c1 0005963a7f94010023a Page 9 of CHTTPKeyServer.cpp
2a67c5 ¤
4734a2 ¤   catch (PGPError) {
44f24f ¤   ¤   delete[] tempBuffer;
7c27ad ¤   ¤   delete[] buffer;
23a33a ¤   ¤   throw;
319371 ¤   }
b367c5 ¤
ed5d73 ¤   return result;
71efe6 }
a0af5a
3faf5a
d5af5a
2e108d ¤   PGPUInt32
95fceb CHTTPKeyServer::URLEncode(
975373 ¤   char *¤ ¤   inBuffer,
29b625 ¤   PGPUInt32¤  inBufSize,
7dba24 ¤   char *¤ ¤   inURLEncodedBuffer)
55bb36 {
15fe47 ¤   char *¤ p = inURLEncodedBuffer;
0267c5 ¤
b13414 ¤   for (PGPUInt32 i = 0; i < inBufSize; i++) {
f64582 ¤   ¤   if ((! isalnum(inBuffer[i])) && (inBuffer[i] != '-')) {
9906aa ¤   ¤   ¤   if (inBuffer[i] == ' ') {
2c358e ¤   ¤   ¤   ¤   *p++ = '+';
e67f1e ¤   ¤   ¤   } else if (((inBuffer[i] == '\x0D') && (inBuffer[i+1] != '\x0A'))
cba8cd ¤   ¤   ¤   || ((inBuffer[i+1] == '\x0A') && (inBuffer[i] != '\x0D'))) {
ce9bcc ¤   ¤   ¤   ¤   *p++ = '%';
bc363a ¤   ¤   ¤   ¤   *p++ = '0';
1e1e93 ¤   ¤   ¤   ¤   *p++ = 'D';
459bcc ¤   ¤   ¤   ¤   *p++ = '%';
ae363a ¤   ¤   ¤   ¤   *p++ = '0';
6b70c4 ¤   ¤   ¤   ¤   *p++ = 'A';
c0042d ¤   ¤   ¤   } else {
a29bcc ¤   ¤   ¤   ¤   *p++ = '%';
b12b61 ¤   ¤   ¤   ¤   *p++ = kHexString[inBuffer[i] >> 4];;
4ac0da ¤   ¤   ¤   ¤   *p++ = kHexString[inBuffer[i] & 0x0F];
0ea3a6 ¤   ¤   ¤   }
1245a6 ¤   ¤   } else {
75f3d4 ¤   ¤   ¤   *p++ = inBuffer[i];
3bec70 ¤   ¤   }¤  ¤
219371 ¤   }
c067c5 ¤
d1ddb4 ¤   *p = '\0';
bc67c5 ¤
e54aa8 ¤   return (p - inURLEncodedBuffer);
07efe6 }
b3af5a
1faf5a
3d38e5 /*
29c744 ¤   PGPError
1a0713 CHTTPKeyServer::ProcessHTTPResult(
e512b9 ¤   char *¤ inResult)
8cbb36 {
f4c806 ¤   PGPError¤   result = kPGPError_ServerUnknownResponse;
66479e ¤   char *¤ ¤   currentItem;
dae44e ¤   char¤   ¤   endChar;
c3f42a ¤   char *¤ ¤   endOfItem;
fd67c5 ¤
fa6e36 ¤   // Skip over HTTP headers
b11b6b ¤   currentItem = strstr(inResult, "\x0D\x0A\x0D\x0A");
6b0974 ¤   if (currentItem != NULL) {
3985f2 ¤   ¤   while (isspace(*currentItem)) {
4e8cc5 ¤   ¤   ¤   currentItem++;
ea0fe4 ¤   ¤   }
781b52 ¤   ¤
3fc61b ¤   ¤   // Skip over title
4e6799 ¤   ¤   currentItem = strchr(currentItem, '\x0A');
ca850b ¤   ¤   if (currentItem != NULL) {
660d94 ¤   ¤   ¤   while (isspace(*currentItem)) {
ff98ed ¤   ¤   ¤   ¤   currentItem++;
57a3a6 ¤   ¤   ¤   }
5987c7 ¤   ¤   ¤
--2da5 0008b1094424010023a Page 10 of CHTTPKeyServer.cpp
69d0ff ¤   ¤   ¤   // Skip over header
7876be ¤   ¤   ¤   currentItem = strchr(currentItem, '\x0A');
1fc4f8 ¤   ¤   ¤   if (currentItem != NULL) {
2915c4 ¤   ¤   ¤   ¤   while (isspace(*currentItem)) {
d71492 ¤   ¤   ¤   ¤   ¤   currentItem++;
c02613 ¤   ¤   ¤   ¤   }
c92b85 ¤   ¤   ¤   ¤
5011f9 ¤   ¤   ¤   ¤   // Apparently some of the messages begin with <pre>
5b1241 ¤   ¤   ¤   ¤   if (strncmp(currentItem, "<pre>", 5) == 0) {
a69294 ¤   ¤   ¤   ¤   ¤   currentItem += 5;
138385 ¤   ¤   ¤   ¤   ¤   while (isspace(*currentItem)) {
635561 ¤   ¤   ¤   ¤   ¤   ¤   currentItem++;
b01c89 ¤   ¤   ¤   ¤   ¤   }
bc2613 ¤   ¤   ¤   ¤   }
432b85 ¤   ¤   ¤   ¤
1d6ee5 ¤   ¤   ¤   ¤   // To quote Mark McArdle's original code, "God willing and the
1f5529 ¤   ¤   ¤   ¤   // creek don't rise" we now point to the actual error message
17117c ¤   ¤   ¤   ¤   for (PGPUInt16 i = 0; kKeyServerMessages[i] != NULL; i++) {
1e35d0 ¤   ¤   ¤   ¤   ¤   if ( strncmp(kKeyServerMessages[i], currentItem,
a1bd2e ¤   ¤   ¤   ¤   ¤   strlen(kKeyServerMessages[i])) == 0) {
5b784f ¤   ¤   ¤   ¤   ¤   ¤   result = kKeyServerErrors[i];
4a00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
0d1c89 ¤   ¤   ¤   ¤   ¤   }
c22613 ¤   ¤   ¤   ¤   }
d72b85 ¤   ¤   ¤   ¤
a35d44 ¤   ¤   ¤   ¤   // Set the error string if necessary
d8634a ¤   ¤   ¤   ¤   if (result != kPGPError_NoErr) {
a1699d ¤   ¤   ¤   ¤   ¤   endOfItem = currentItem;
f18c02 ¤   ¤   ¤   ¤   ¤   while ((*endOfItem != '\0') && (*endOfItem != '\x0D')
e9f82b ¤   ¤   ¤   ¤   ¤   && (*endOfItem != '\x0A') && (*endOfItem != '<')) {
c41a3b ¤   ¤   ¤   ¤   ¤   ¤   endOfItem++;
1c1c89 ¤   ¤   ¤   ¤   ¤   }
95ae30 ¤   ¤   ¤   ¤   ¤
b2cb6a ¤   ¤   ¤   ¤   ¤   endChar = *endOfItem;
66d0d3 ¤   ¤   ¤   ¤   ¤   *endOfItem = '\0';
179833 ¤   ¤   ¤   ¤   ¤   SetErrorString(currentItem);
28d7e5 ¤   ¤   ¤   ¤   ¤   *endOfItem = endChar;
002613 ¤   ¤   ¤   ¤   }
f5a3a6 ¤   ¤   ¤   }
590fe4 ¤   ¤   }
a29371 ¤   }
de67c5 ¤
bc5d73 ¤   return result;
efefe6 }
5c7fe0 */
2daf5a
8caf5a
f0af5a
35c744 ¤   PGPError
9a0713 CHTTPKeyServer::ProcessHTTPResult(
2b12b9 ¤   char *¤ inResult)
52bb36 {
d2c806 ¤   PGPError¤   result = kPGPError_ServerUnknownResponse;
c9479e ¤   char *¤ ¤   currentItem;
9fe44e ¤   char¤   ¤   endChar;
66f42a ¤   char *¤ ¤   endOfItem;
0667c5 ¤
f86e36 ¤   // Skip over HTTP headers
081b6b ¤   currentItem = strstr(inResult, "\x0D\x0A\x0D\x0A");
250974 ¤   if (currentItem != NULL) {
136ff8 ¤   ¤   // Skip head
f41662 ¤   ¤   endOfItem = FindSubStringNoCase(currentItem, kHeadBeginTag);
2309f2 ¤   ¤   if (endOfItem != NULL) {
ca86b0 ¤   ¤   ¤   endOfItem = FindSubStringNoCase(endOfItem, kHeadEndTag);
fc349a ¤   ¤   ¤   if (endOfItem != NULL) {
f34503 ¤   ¤   ¤   ¤   currentItem = endOfItem + strlen(kHeadEndTag);
f2a3a6 ¤   ¤   ¤   }
350fe4 ¤   ¤   }
9687c7 ¤   ¤   ¤
c15d2f ¤   ¤   // Skip title
763df0 ¤   ¤   endOfItem = FindSubStringNoCase(currentItem, kTitleBeginTag);
8b09f2 ¤   ¤   if (endOfItem != NULL) {
--4608 0014e4499404010023a Page 11 of CHTTPKeyServer.cpp
e60f62 ¤   ¤   ¤   endOfItem = FindSubStringNoCase(endOfItem, kTitleEndTag);
a3349a ¤   ¤   ¤   if (endOfItem != NULL) {
b888b1 ¤   ¤   ¤   ¤   currentItem = endOfItem + strlen(kTitleEndTag);
eda3a6 ¤   ¤   ¤   }
be0fe4 ¤   ¤   }
6daf5a
4aaf5a
a41527 ¤   ¤   // Skip H1
1b09a2 ¤   ¤   endOfItem = FindSubStringNoCase(currentItem, kH1BeginTag);
8709f2 ¤   ¤   if (endOfItem != NULL) {
e3e365 ¤   ¤   ¤   endOfItem = FindSubStringNoCase(endOfItem, kH1EndTag);
74349a ¤   ¤   ¤   if (endOfItem != NULL) {
44e7c6 ¤   ¤   ¤   ¤   currentItem = endOfItem + strlen(kH1EndTag);
51a3a6 ¤   ¤   ¤   }
950fe4 ¤   ¤   }
4c1b52 ¤   ¤
214bb7 ¤   ¤   // Skip all prefix tags and whitespace
574a80 ¤   ¤   PGPBoolean¤ skip;
b94f73 ¤   ¤   PGPBoolean¤ inTag = false;
ea1b52 ¤   ¤
014392 ¤   ¤   do {
c29b2d ¤   ¤   ¤   skip = false;
27650e ¤   ¤   ¤   if (isspace(*currentItem)) {
170b31 ¤   ¤   ¤   ¤   skip = true;
76042d ¤   ¤   ¤   } else {
57d2b9 ¤   ¤   ¤   ¤   if (inTag) {
4fb067 ¤   ¤   ¤   ¤   ¤   skip = true;
186331 ¤   ¤   ¤   ¤   ¤   if (*currentItem == '>') {
797b78 ¤   ¤   ¤   ¤   ¤   ¤   inTag = false;
691c89 ¤   ¤   ¤   ¤   ¤   }
85b5fc ¤   ¤   ¤   ¤   } else {
cf6b67 ¤   ¤   ¤   ¤   ¤   if (*currentItem == '<') {
f88d0f ¤   ¤   ¤   ¤   ¤   ¤   skip = true;
1e5cfb ¤   ¤   ¤   ¤   ¤   ¤   inTag = true;
a81c89 ¤   ¤   ¤   ¤   ¤   }
fd2613 ¤   ¤   ¤   ¤   }
a2a3a6 ¤   ¤   ¤   }
7f5342 ¤   ¤   ¤   if (skip) {
c298ed ¤   ¤   ¤   ¤   currentItem++;
c8a3a6 ¤   ¤   ¤   }
5b7932 ¤   ¤   } while (skip);
7daf5a
7e5369 ¤   ¤   // To quote Mark McArdle's original code, "God willing and the
b13ad5 ¤   ¤   // creek don't rise" we now point to the actual error message
a24402 ¤   ¤   for (PGPUInt16 i = 0; kKeyServerMessages[i] != NULL; i++) {
3965bc ¤   ¤   ¤   if ( strncmp(kKeyServerMessages[i], currentItem,
83ab32 ¤   ¤   ¤   strlen(kKeyServerMessages[i])) == 0) {
7b9970 ¤   ¤   ¤   ¤   result = kKeyServerErrors[i];
f1f622 ¤   ¤   ¤   ¤   break;
59a3a6 ¤   ¤   ¤   }
310fe4 ¤   ¤   }
561b52 ¤   ¤
b95cc2 ¤   ¤   // Set the error string if necessary
c1376f ¤   ¤   if (result != kPGPError_NoErr) {
326ac8 ¤   ¤   ¤   endOfItem = currentItem;
568f97 ¤   ¤   ¤   while ((*endOfItem != '\0') && (*endOfItem != '\x0D')
ab8b32 ¤   ¤   ¤   && (*endOfItem != '\x0A') && (*endOfItem != '<')) {
fb9c05 ¤   ¤   ¤   ¤   endOfItem++;
b6a3a6 ¤   ¤   ¤   }
a687c7 ¤   ¤   ¤
8118f7 ¤   ¤   ¤   endChar = *endOfItem;
ca1d5f ¤   ¤   ¤   *endOfItem = '\0';
b4cc16 ¤   ¤   ¤   SetErrorString(currentItem);
c50478 ¤   ¤   ¤   *endOfItem = endChar;
540fe4 ¤   ¤   }
ce9371 ¤   }
1b67c5 ¤
c55d73 ¤   return result;
4eefe6 }
--3fc3 001edf1e38b4010023b Page 1 of CHTTPKeyServer.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
257865 ¤   $Id: CHTTPKeyServer.h,v 1.3.10.1 1998/11/12 03:22:15 heller Exp $
f9f7f7 ____________________________________________________________________________*/
55af5a
5557c0 #ifndef Included_CHTTPKeyServer_h
de895c #define Included_CHTTPKeyServer_h
49af5a
275519 #include "pgpSockets.h"
08af5a
0fef84 #include "CKeyServer.h"
4caf5a
08af5a
b5af5a
000199 class CHTTPKeyServer : public CKeyServer {
605ed4 public:
4d17b3 ¤   ¤   ¤   ¤   ¤   CHTTPKeyServer(PGPContextRef inContext,
982d2c ¤   ¤   ¤   ¤   ¤   ¤   const char * inHostName, PGPUInt32 inHostAddress,
e4c522 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 inHostPort, PGPKeyServerType inType);
7f7faa ¤   virtual¤¤   ¤   ~CHTTPKeyServer();
2267c5 ¤
5846d7 ¤   virtual void¤   Cancel();
b867c5 ¤
eac4a4 ¤   virtual void¤   Query(PGPFilterRef inFilterRef,
6c34e5 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outFoundKeys);
7834a6 ¤   virtual void¤   Upload(PGPKeyUploadPreference inSendPrivateKeys,
c96269 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToUpload,
25648a ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
d2af5a
bda2d3 protected:
21d21f ¤   PGPSocketRef¤   mSocket;
c067c5 ¤
965594 ¤   PGPUInt32¤  ¤   ReceiveResult(char ** outBuffer);
c8f35c ¤   PGPUInt32¤  ¤   URLEncode(char * inBuffer, PGPUInt32 inBufSize,
6a1de3 ¤   ¤   ¤   ¤   ¤   ¤   char * inURLEncodedBuffer);
a17666 ¤   PGPError¤   ¤   ProcessHTTPResult(char * inResult);
8982f7 };
d9af5a
7eaf5a
a2af5a
ed2841 #endif¶
--3f64 0009086a5784010023c Page 1 of CKeyServer.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
e5ca85 ¤   $Id: CKeyServer.cpp,v 1.36.10.1 1998/11/12 03:22:16 heller Exp $
f0f7f7 ____________________________________________________________________________*/
54af5a
f70ccc #if PGP_MACINTOSH
9f90a3 #include <Threads.h>
d82530 #include <map>
0eaf5a
f714ea #elif PGP_WIN32
315655 #include <windows.h>
b47454 #endif
4aaf5a
6bbaa5 #if PGP_WIN32 || PGP_UNIX
2c51b9 #include "pgpRMWOLock.h"
7a7454 #endif
d0af5a
73324c #include <string.h>
13af5a
8f1b42 #include "pgpStrings.h"
106773 #include "pgpMemoryMgr.h"
929f63 #include "pgpEncode.h"
5ac26c #include "pgpContext.h"
df0d08 #include "pgpMem.h"
54af5a
f95519 #include "pgpSockets.h"
38af5a
8d2057 #include "CLDAPKeyServer.h"
7d0394 #include "CHTTPKeyServer.h"
15ef84 #include "CKeyServer.h"
85af5a
91af5a
74e686 PGPBoolean¤ ¤   ¤   ¤   CKeyServer::sIsInitialized = FALSE;
80af5a
b16084 struct SThreadContext {
a5c027 ¤   PGPEventHandlerProcPtr¤ idleEventHandler;
759d65 ¤   PGPUserValue¤   ¤   ¤   idleEventHandlerData;
df82f7 };
47af5a
4aaf5a
32afb9 #if PGP_WIN32
d781e3 PGPRMWOLock¤¤   ¤   ¤   CKeyServer::sThreadLock;
6fb436 PGPInt32¤   ¤   ¤   ¤   CKeyServer::sIdleEventHandlerIndex = 0;
82b6b9 PGPInt32¤   ¤   ¤   ¤   CKeyServer::sIdleEventHandlerDataIndex = 0;
337454 #endif
1daf5a
e30ccc #if PGP_MACINTOSH
33b66e static map<ThreadID, SThreadContext>¤   sThreadContextMap;
44f803 extern ThreadID¤¤   ¤   ¤   ¤   ¤   ¤   gMainThreadID;
557454 #endif
1daf5a
5fba01 static const PGPUInt16¤ ¤   ¤   kPGPKeyServerPortLDAP = 389;
5b5f5d static const PGPUInt16¤ ¤   ¤   kPGPKeyServerPortLDAPS = 636;
c1a497 static const PGPUInt16¤ ¤   ¤   kPGPKeyServerPortHTTP = 11371;
9e5ea4 static const PGPUInt16¤ ¤   ¤   kPGPKeyServerPortHTTPS = 443;
e049f6 static const char *¤¤   ¤   ¤   kProtocolSeparator = "://";
a85cff static const char *¤¤   ¤   ¤   kProtocolTag[] = {¤ "LDAPS:", "HTTPS:",
2b540e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "LDAP:", "HTTP:",
f4b1d0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL};
909339 static const PGPKeyServerType¤  kProtocolType[] = {¤kPGPKeyServerType_LDAPS,
b53e06 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerType_HTTPS,
39c3e7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerType_LDAP,
c7f5bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerType_HTTP};
6baf5a
f7af5a
a33ecc #if PGP_UNIX¤   // No need to save the idle event handler
80a2ce StPreserveSocketsEventHandler::StPreserveSocketsEventHandler(
901026 ¤   CKeyServer * inKeyServer)
--2484 0000f56af554010023c Page 2 of CKeyServer.cpp
2cbb36 {
cbefe6 }
a7af5a
a5af5a
36af5a
aa9163 StPreserveSocketsEventHandler::~StPreserveSocketsEventHandler()
57bb36 {
03efe6 }
d2af5a
90db21 #else
08a2ce StPreserveSocketsEventHandler::StPreserveSocketsEventHandler(
591026 ¤   CKeyServer * inKeyServer)
b1bb36 {
ccafbe ¤   PGPError¤   ¤   ¤   ¤   pgpError = kPGPError_NoErr;
c34a51 ¤   PGPEventHandlerProcPtr¤ eventHandler;
e40e72 ¤   PGPUserValue¤   ¤   ¤   eventHandlerData;
ad67c5 ¤
8048ea ¤   CKeyServer::GetThreadIdleEventHandler(&eventHandler, &eventHandlerData);
6967c5 ¤
c1ae7e ¤   if (eventHandler != NULL) {
fa92fc ¤   ¤   pgpError = PGPSetSocketsIdleEventHandler(
818d74 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   CKeyServer::KeyServerIdleEventHandler,
b83e09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeyServer);
899371 ¤   }
1067c5 ¤
d4efe6 }
b7af5a
afaf5a
7faf5a
319163 StPreserveSocketsEventHandler::~StPreserveSocketsEventHandler()
9dbb36 {
26efe6 }
db6516 #endif¤ // idle event handler restoration
90af5a
676d52 ¤   void
2fe9f9 CKeyServer::CheckInitialization()
5fbb36 {
5eb9cd ¤   if (! sIsInitialized) {
63c0c7 ¤   ¤   ThrowPGPError_(kPGPError_ServerNotInitialized);
c09371 ¤   }
69efe6 }
baaf5a
616d52 ¤   void
198001 CKeyServer::Initialize()
e4bb36 {
81f5d1 ¤   PGPError¤   pgpError;
bd67c5 ¤
9dafb9 #if PGP_WIN32
318b1a ¤   InitializePGPRMWOLock(&sThreadLock);
c487a8 ¤   sIdleEventHandlerIndex = TlsAlloc();
9e1715 ¤   if (! TlsSetValue(sIdleEventHandlerIndex, NULL)) {
8b3a3a ¤   ¤   ThrowPGPError_(kPGPError_UnknownError);
ba9371 ¤   }
b0ff4f ¤   sIdleEventHandlerDataIndex = TlsAlloc();
eeed3e ¤   if (! TlsSetValue(sIdleEventHandlerDataIndex, NULL)) {
873a3a ¤   ¤   ThrowPGPError_(kPGPError_UnknownError);
ed9371 ¤   }
b77454 #endif
0faf5a
ad1213 ¤   pgpError = PGPSocketsInit();
1172e4 ¤   ThrowIfPGPError_(pgpError);
5167c5 ¤
e713b1 ¤   sIsInitialized = TRUE;
6befe6 }
baaf5a
5baf5a
a2af5a
0c6d52 ¤   void
04f265 CKeyServer::Cleanup()
37bb36 {
f4afb9 #if PGP_WIN32
0fe960 ¤   TlsFree(sIdleEventHandlerIndex);
--cb20 000c074d74b4010023c Page 3 of CKeyServer.cpp
c97dd4 ¤   sIdleEventHandlerIndex = 0;
2c7009 ¤   TlsFree(sIdleEventHandlerDataIndex);
95adc1 ¤   sIdleEventHandlerDataIndex = 0;
d726e7 ¤   DeletePGPRMWOLock(&sThreadLock);
da7454 #endif
e7af5a
c10ccc #if PGP_MACINTOSH
dfabfc ¤   sThreadContextMap.erase(¤   sThreadContextMap.begin(),
2eae52 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sThreadContextMap.end());
297454 #endif
7daf5a
71ba95 ¤   PGPSocketsCleanup();
269552 ¤   sIsInitialized = FALSE;
bdefe6 }
a867c5 ¤
bcaf5a
2eaf5a
80aae6 ¤   CKeyServer *
edcf2a CKeyServer::NewKeyServerFromURL(
94b8d1 ¤   PGPContextRef¤  ¤   ¤   inContext,
776dcf ¤   const char *¤   ¤   ¤   inURL,
7d2ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
0661b0 ¤   PGPKeyServerKeySpace¤   inKeySpace)
7dbb36 {
bc0362 ¤   CKeyServer *¤   ¤   ¤   ¤   ¤   result = NULL;
573c3b ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   url = NULL;
d967c5 ¤
705800 ¤   CheckInitialization();
7e67c5 ¤
e45168 ¤   try {
957e2e ¤   ¤   PGPKeyServerType¤   keyServerType = (PGPKeyServerType) 0;
0db31e ¤   ¤   char *¤ ¤   ¤   ¤   host;
2f6168 ¤   ¤   PGPUInt16¤  ¤   ¤   port;
49daa2 ¤   ¤   char *¤ ¤   ¤   ¤   currentItem = NULL;
ef86d2 ¤   ¤   char *¤ ¤   ¤   ¤   nextItem = NULL;
cf1b52 ¤   ¤
4b0bb0 ¤   ¤   url = new char[strlen(inURL) + 1];
710438 ¤   ¤   if (url == NULL) {
61ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
c20fe4 ¤   ¤   }
854f4b ¤   ¤   strcpy(url, inURL);
6c1b52 ¤   ¤
cb341f ¤   ¤   // Parse the URL
1f8c96 ¤   ¤   currentItem = url;
9f17eb ¤   ¤   nextItem = strchr(currentItem, ':');
021b52 ¤   ¤
883983 ¤   ¤   // Determine the protocol
9cbfa5 ¤   ¤   if (nextItem != NULL) {
73bc05 ¤   ¤   ¤   // Determine if we are at the port separator or protocol
eb633d ¤   ¤   ¤   // separator
efb350 ¤   ¤   ¤   if (pgpCompareStringsIgnoreCaseN(nextItem, kProtocolSeparator,
f9ac2b ¤   ¤   ¤   strlen(kProtocolSeparator)) == 0) {
69504c ¤   ¤   ¤   ¤   // Determine protocol
b5f814 ¤   ¤   ¤   ¤   for (PGPUInt16 i = 0; kProtocolTag[i] != NULL; i++) {
8ac7ad ¤   ¤   ¤   ¤   ¤   if (pgpCompareStringsIgnoreCaseN(currentItem,
dae899 ¤   ¤   ¤   ¤   ¤   kProtocolTag[i], strlen(kProtocolTag[i])) == 0) {
1cc258 ¤   ¤   ¤   ¤   ¤   ¤   keyServerType = kProtocolType[i];
e000eb ¤   ¤   ¤   ¤   ¤   ¤   break;
b91c89 ¤   ¤   ¤   ¤   ¤   }
982613 ¤   ¤   ¤   ¤   }
c77a69 ¤   ¤   ¤   ¤   if (keyServerType == 0) {
2c7758 ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerInvalidProtocol);
f7b5fc ¤   ¤   ¤   ¤   } else {
931ef5 ¤   ¤   ¤   ¤   ¤   nextItem += strlen(kProtocolSeparator);
632613 ¤   ¤   ¤   ¤   }
10042d ¤   ¤   ¤   } else {
4ba968 ¤   ¤   ¤   ¤   // Default to HTTP, colon must be for port
290d2c ¤   ¤   ¤   ¤   keyServerType = kPGPKeyServerType_HTTP;
349725 ¤   ¤   ¤   ¤   nextItem = url;
dea3a6 ¤   ¤   ¤   }
f645a6 ¤   ¤   } else {
c0e79d ¤   ¤   ¤   // Default to HTTP
--0d08 000bd52b24d4010023c Page 4 of CKeyServer.cpp
1b5880 ¤   ¤   ¤   keyServerType = kPGPKeyServerType_HTTP;
1e3a7b ¤   ¤   ¤   nextItem = url;
870fe4 ¤   ¤   }
3b1b52 ¤   ¤
ab58f7 ¤   ¤   // Determine the host name and port
c57f07 ¤   ¤   host = currentItem = nextItem;
7117eb ¤   ¤   nextItem = strchr(currentItem, ':');
eebfa5 ¤   ¤   if (nextItem != NULL) {
1b83a3 ¤   ¤   ¤   // Found port
3ed944 ¤   ¤   ¤   port = atoi(nextItem + 1);
f9b5a7 ¤   ¤   ¤   *nextItem = '\0';
db45a6 ¤   ¤   } else {
b2c938 ¤   ¤   ¤   switch (keyServerType) {
a74233 ¤   ¤   ¤   ¤   case kPGPKeyServerType_LDAP:
3172c3 ¤   ¤   ¤   ¤   {
902530 ¤   ¤   ¤   ¤   ¤   port = kPGPKeyServerPortLDAP;
572613 ¤   ¤   ¤   ¤   }
83f622 ¤   ¤   ¤   ¤   break;
3a2b85 ¤   ¤   ¤   ¤
1d2b85 ¤   ¤   ¤   ¤
1583f1 ¤   ¤   ¤   ¤   case kPGPKeyServerType_LDAPS:
eb72c3 ¤   ¤   ¤   ¤   {
f1f209 ¤   ¤   ¤   ¤   ¤   port = kPGPKeyServerPortLDAPS;
2f2613 ¤   ¤   ¤   ¤   }
1ff622 ¤   ¤   ¤   ¤   break;
6a2b85 ¤   ¤   ¤   ¤
9d2b85 ¤   ¤   ¤   ¤
464b29 ¤   ¤   ¤   ¤   case kPGPKeyServerType_HTTP:
7972c3 ¤   ¤   ¤   ¤   {
ab2c2a ¤   ¤   ¤   ¤   ¤   port = kPGPKeyServerPortHTTP;
be2613 ¤   ¤   ¤   ¤   }
13f622 ¤   ¤   ¤   ¤   break;
8f2b85 ¤   ¤   ¤   ¤
f72b85 ¤   ¤   ¤   ¤
783c23 ¤   ¤   ¤   ¤   case kPGPKeyServerType_HTTPS:
5772c3 ¤   ¤   ¤   ¤   {
364ddb ¤   ¤   ¤   ¤   ¤   port = kPGPKeyServerPortHTTPS;
a42613 ¤   ¤   ¤   ¤   }
71f622 ¤   ¤   ¤   ¤   break;
832b85 ¤   ¤   ¤   ¤
156ab9 ¤   ¤   ¤   ¤   default:
6c72c3 ¤   ¤   ¤   ¤   {
e2cfb1 ¤   ¤   ¤   ¤   ¤   pgpDebugMsg("NewKeyServerFromURL() Unknown server type");
a3d126 ¤   ¤   ¤   ¤   ¤   port = 0;
742613 ¤   ¤   ¤   ¤   }
2ff622 ¤   ¤   ¤   ¤   break;
08a3a6 ¤   ¤   ¤   }
150fe4 ¤   ¤   }
0e1b52 ¤   ¤
59639c ¤   ¤   // Trim paths
2885ff ¤   ¤   nextItem = strchr(currentItem, '/');
f7bfa5 ¤   ¤   if (nextItem != NULL) {
3cb5a7 ¤   ¤   ¤   *nextItem = '\0';
410fe4 ¤   ¤   }
69af5a
a9a0c5 ¤   ¤   result = NewKeyServerFromHostName(¤ inContext,
f58729 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   host,
e2f87a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   port,
2ccada ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyServerType,
4a5ab9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAccessType,
e9282b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySpace);
c59371 ¤   }
8f67c5 ¤
39e0a3 ¤   catch (...) {
9f89c2 ¤   ¤   delete[] url;
97a33a ¤   ¤   throw;
829371 ¤   }
6167c5 ¤
03b358 ¤   delete[] url;
6167c5 ¤
955d73 ¤   return result;
bdefe6 }
--878a 000055a9ca24010023c Page 5 of CKeyServer.cpp
e0af5a
1aaf5a
17af5a
b5aae6 ¤   CKeyServer *
94947a CKeyServer::NewKeyServerFromHostAddress(
cbb8d1 ¤   PGPContextRef¤  ¤   ¤   inContext,
4560d6 ¤   PGPUInt32¤  ¤   ¤   ¤   inHostAddress,
e8da82 ¤   PGPUInt16¤  ¤   ¤   ¤   inHostPort,
690e3d ¤   PGPKeyServerType¤   ¤   inType,
522ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
3461b0 ¤   PGPKeyServerKeySpace¤   inKeySpace)
8ebb36 {
46eb86 ¤   CKeyServer *¤   result = NULL;
d5af5a
d55800 ¤   CheckInitialization();
ff67c5 ¤
ae5168 ¤   try {
64eda4 ¤   ¤   if (inHostPort == 0) {
52dcf6 ¤   ¤   ¤   switch (inType) {
8c4233 ¤   ¤   ¤   ¤   case kPGPKeyServerType_LDAP:
8972c3 ¤   ¤   ¤   ¤   {
4f8dd4 ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortLDAP;
db2613 ¤   ¤   ¤   ¤   }
a9f622 ¤   ¤   ¤   ¤   break;
e12b85 ¤   ¤   ¤   ¤
902b85 ¤   ¤   ¤   ¤
1483f1 ¤   ¤   ¤   ¤   case kPGPKeyServerType_LDAPS:
af72c3 ¤   ¤   ¤   ¤   {
5e538b ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortLDAPS;
c22613 ¤   ¤   ¤   ¤   }
aff622 ¤   ¤   ¤   ¤   break;
592b85 ¤   ¤   ¤   ¤
ea2b85 ¤   ¤   ¤   ¤
e24b29 ¤   ¤   ¤   ¤   case kPGPKeyServerType_HTTP:
3f72c3 ¤   ¤   ¤   ¤   {
ed84ce ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortHTTP;
b12613 ¤   ¤   ¤   ¤   }
c6f622 ¤   ¤   ¤   ¤   break;
2f2b85 ¤   ¤   ¤   ¤
d12b85 ¤   ¤   ¤   ¤
3f3c23 ¤   ¤   ¤   ¤   case kPGPKeyServerType_HTTPS:
1c72c3 ¤   ¤   ¤   ¤   {
82ec59 ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortHTTPS;
192613 ¤   ¤   ¤   ¤   }
97f622 ¤   ¤   ¤   ¤   break;
bc2b85 ¤   ¤   ¤   ¤
016ab9 ¤   ¤   ¤   ¤   default:
c472c3 ¤   ¤   ¤   ¤   {
fccf18 ¤   ¤   ¤   ¤   ¤   pgpDebugMsg(
019a72 ¤   ¤   ¤   ¤   ¤   "NewKeyServerFromHostAddress(): Unknown server type" );
0780d3 ¤   ¤   ¤   ¤   ¤   inHostPort = 0;
5a2613 ¤   ¤   ¤   ¤   }
c7f622 ¤   ¤   ¤   ¤   break;
22a3a6 ¤   ¤   ¤   }
4d0fe4 ¤   ¤   }
0059d5 ¤   ¤   if ((inType == kPGPKeyServerType_LDAP)
e6bc66 ¤   ¤   || (inType == kPGPKeyServerType_LDAPS)) {
0ef640 ¤   ¤   ¤   result = new CLDAPKeyServer(¤   inContext,
513cad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL,
c72483 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostAddress,
c3c99b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostPort,
47d752 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inType,
b15ab9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAccessType,
21282b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySpace);
dc45a6 ¤   ¤   } else {
4c9437 ¤   ¤   ¤   result = new CHTTPKeyServer(¤   inContext,
ae3cad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL,
282483 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostAddress,
10c99b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostPort,
cd48dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inType);
8b0fe4 ¤   ¤   }
0591d2 ¤   ¤   if (result == NULL) {
--ca54 0004841815b4010023c Page 6 of CKeyServer.cpp
3bce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
ff0fe4 ¤   ¤   }
329371 ¤   }
7b67c5 ¤
86e0a3 ¤   catch (...) {
f3f6c4 ¤   ¤   delete result;
35a33a ¤   ¤   throw;
149371 ¤   }
de67c5 ¤
885d73 ¤   return result;
c6efe6 }
5eaf5a
edaf5a
b6af5a
d6aae6 ¤   CKeyServer *
61cc71 CKeyServer::NewKeyServerFromHostName(
2bb8d1 ¤   PGPContextRef¤  ¤   ¤   inContext,
a8529e ¤   const char *¤   ¤   ¤   inHostName,
92da82 ¤   PGPUInt16¤  ¤   ¤   ¤   inHostPort,
ab0e3d ¤   PGPKeyServerType¤   ¤   inType,
6d2ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
1061b0 ¤   PGPKeyServerKeySpace¤   inKeySpace)
9dbb36 {
2eeb86 ¤   CKeyServer *¤   result = NULL;
47af5a
e25800 ¤   CheckInitialization();
4f67c5 ¤
755168 ¤   try {
c0eda4 ¤   ¤   if (inHostPort == 0) {
c2dcf6 ¤   ¤   ¤   switch (inType) {
bf4233 ¤   ¤   ¤   ¤   case kPGPKeyServerType_LDAP:
1572c3 ¤   ¤   ¤   ¤   {
cd8dd4 ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortLDAP;
3d2613 ¤   ¤   ¤   ¤   }
0cf622 ¤   ¤   ¤   ¤   break;
ba2b85 ¤   ¤   ¤   ¤
022b85 ¤   ¤   ¤   ¤
4283f1 ¤   ¤   ¤   ¤   case kPGPKeyServerType_LDAPS:
4d72c3 ¤   ¤   ¤   ¤   {
2f538b ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortLDAPS;
5e2613 ¤   ¤   ¤   ¤   }
71f622 ¤   ¤   ¤   ¤   break;
202b85 ¤   ¤   ¤   ¤
722b85 ¤   ¤   ¤   ¤
a74b29 ¤   ¤   ¤   ¤   case kPGPKeyServerType_HTTP:
3872c3 ¤   ¤   ¤   ¤   {
0484ce ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortHTTP;
e92613 ¤   ¤   ¤   ¤   }
5df622 ¤   ¤   ¤   ¤   break;
662b85 ¤   ¤   ¤   ¤
a32b85 ¤   ¤   ¤   ¤
b33c23 ¤   ¤   ¤   ¤   case kPGPKeyServerType_HTTPS:
4372c3 ¤   ¤   ¤   ¤   {
15ec59 ¤   ¤   ¤   ¤   ¤   inHostPort = kPGPKeyServerPortHTTPS;
012613 ¤   ¤   ¤   ¤   }
e1f622 ¤   ¤   ¤   ¤   break;
de2b85 ¤   ¤   ¤   ¤
ee6ab9 ¤   ¤   ¤   ¤   default:
4472c3 ¤   ¤   ¤   ¤   {
08cf18 ¤   ¤   ¤   ¤   ¤   pgpDebugMsg(
020327 ¤   ¤   ¤   ¤   ¤   "NewKeyServerFromHostName(): Unknown server type" );
4580d3 ¤   ¤   ¤   ¤   ¤   inHostPort = 0;
df2613 ¤   ¤   ¤   ¤   }
7cf622 ¤   ¤   ¤   ¤   break;
64a3a6 ¤   ¤   ¤   }
a90fe4 ¤   ¤   }
2a59d5 ¤   ¤   if ((inType == kPGPKeyServerType_LDAP)
e3bc66 ¤   ¤   || (inType == kPGPKeyServerType_LDAPS)) {
5ef640 ¤   ¤   ¤   result = new CLDAPKeyServer(¤   inContext,
ad7d20 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostName,
ed9cf4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
48c99b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostPort,
--8821 0009f3992114010023c Page 7 of CKeyServer.cpp
78d752 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inType,
645ab9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAccessType,
80282b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySpace);
f245a6 ¤   ¤   } else {
f49437 ¤   ¤   ¤   result = new CHTTPKeyServer(¤   inContext,
9e7d20 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostName,
5d9cf4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
64c99b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostPort,
0648dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inType);
c40fe4 ¤   ¤   }
1791d2 ¤   ¤   if (result == NULL) {
00ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
3e0fe4 ¤   ¤   }
c99371 ¤   }
2067c5 ¤
18e0a3 ¤   catch (...) {
02f6c4 ¤   ¤   delete result;
1aa33a ¤   ¤   throw;
f19371 ¤   }
5367c5 ¤
615d73 ¤   return result;
b9efe6 }
33af5a
26af5a
d8af5a
6e16ea ¤   PGPBoolean
3112a7 CKeyServer::Free()
f1bb36 {
70a657 ¤   PGPBoolean¤ freedServer = FALSE;
7267c5 ¤
9e1c45 ¤   mRefCount--;
8667c5 ¤
181ed1 ¤   if (mRefCount == 0) {
97866a ¤   ¤   if (mIsOpen) {
1b9d7b ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpen);
bc0fe4 ¤   ¤   }
58af5a
514e34 ¤   ¤   delete this;
0f5295 ¤   ¤   freedServer = TRUE;
819371 ¤   }
e767c5 ¤
7e5b3b ¤   return( freedServer );
78efe6 }
08af5a
dcaf5a
637662 CKeyServer::CKeyServer(
96f09f ¤   PGPContextRef¤  ¤   inContext,
9f7b09 ¤   const char *¤   ¤   inHostName,
217687 ¤   PGPUInt32¤  ¤   ¤   inHostAddress,
21ee2f ¤   PGPUInt16¤  ¤   ¤   inHostPort,
c4401f ¤   PGPKeyServerType¤   inType)
ee9037 ¤   : mContext(inContext), mHostName(NULL), mHostPort(inHostPort),
285591 ¤   ··mHostAddress(inHostAddress), mType(inType), mEventHandler(NULL),
087f53 ¤   ··mEventHandlerData(NULL), ·mTLSSession(kInvalidPGPtlsSessionRef),
31db4b ¤   ··mErrorString(NULL), mSecured(false), mIsBusy(false), mIsOpen(false),
e6539b ¤   ··mCanceled(false), mRefCount(1)
54afb9 #if PGP_WIN32
8c3695 ¤   ··, mAsyncHostEntryRef(kPGPInvalidAsyncHostEntryRef)
6b7454 #endif
a3bb36 {
11fb52 ¤   if (inHostName != NULL) {
95ecdc ¤   ¤   mHostName = new char[strlen(inHostName) + 1];
b643e2 ¤   ¤   if (mHostName == NULL) {
e3ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
140fe4 ¤   ¤   }
da66d0 ¤   ¤   strcpy(mHostName, inHostName);
a89371 ¤   }
c7efe6 }
d5af5a
a7af5a
15af5a
9f7e34 CKeyServer::~CKeyServer()
--f513 00035b83bb94010023c Page 8 of CKeyServer.cpp
2cbb36 {
54eb76 ¤   delete[] mHostName;
6e98db ¤   delete[] mErrorString;
10efe6 }
5eaf5a
3faf5a
b3af5a
bb6d52 ¤   void
d1cfba CKeyServer::SetIdleEventHandler(
ced261 ¤   PGPEventHandlerProcPtr¤ inCallback,
acdbfa ¤   PGPUserValue¤   ¤   ¤   inUserData)
babb36 {
6a27af ¤   SetThreadIdleEventHandler(inCallback, inUserData);
a2efe6 }
25af5a
6faf5a
b4af5a
f66d52 ¤   void
517cf9 CKeyServer::GetIdleEventHandler(
aa286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
6b70d3 ¤   PGPUserValue *¤ ¤   ¤   ¤   outUserData)
2fbb36 {
2fcb04 ¤   GetThreadIdleEventHandler(outCallback, outUserData);
c5efe6 }
ceaf5a
62af5a
a9af5a
a5c744 ¤   PGPError
ba1870 CKeyServer::KeyServerIdleEventHandler(
b23c55 ¤   PGPContextRef¤  inContext,
442a19 ¤   PGPEvent *¤ ¤   inEvent,
b01ac2 ¤   PGPUserValue¤   callBackArg)
73bb36 {
c94a51 ¤   PGPEventHandlerProcPtr¤ eventHandler;
d20e72 ¤   PGPUserValue¤   ¤   ¤   eventHandlerData;
9a80f7 ¤   PGPError¤   ¤   ¤   ¤   result;
ed67c5 ¤
481098 ¤   (void) inContext;
0f9de1 ¤   (void) inEvent;
ee67c5 ¤
30333f ¤   GetThreadIdleEventHandler(&eventHandler, &eventHandlerData);
d367c5 ¤
24ae7e ¤   if (eventHandler != NULL) {
3fee2a ¤   ¤   PGPContextRef¤  context = NULL;
c079f7 ¤   ¤   PGPEvent¤   ¤   theEvent;
ec1b52 ¤   ¤
8c249d ¤   ¤   pgpClearMemory(&theEvent, sizeof(theEvent));
de5811 ¤   ¤   theEvent.type = kPGPEvent_KeyServerIdleEvent;
af0640 ¤   ¤   theEvent.job = NULL;
287250 ¤   ¤   theEvent.data.keyServerIdleData.keyServerRef =
e261b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) callBackArg;
f62a46 ¤   ¤   if (callBackArg != NULL) {
b473c5 ¤   ¤   ¤   context = ((CKeyServer *) callBackArg)->mContext;
6e0fe4 ¤   ¤   }
8d9e2d ¤   ¤   result = eventHandler(context, &theEvent, eventHandlerData);
212a46 ¤   ¤   if (callBackArg != NULL) {
1d31d7 ¤   ¤   ¤   if (result != kPGPError_NoErr) {
8aba87 ¤   ¤   ¤   ¤   ((CKeyServer *) callBackArg)->mCanceled = true;
db10ec ¤   ¤   ¤   } else if (((CKeyServer *) callBackArg)->mCanceled) {
93bb22 ¤   ¤   ¤   ¤   result = kPGPError_UserAbort;
43a3a6 ¤   ¤   ¤   }
e00fe4 ¤   ¤   }
7bf037 ¤   } else {
b43130 ¤   ¤   result = kPGPError_NoErr;
3b9371 ¤   }
bc67c5 ¤
645d73 ¤   return result;
1aefe6 }
bbaf5a
00af5a
3aaf5a
356d52 ¤   void
--8cbf 0006865624b4010023c Page 9 of CKeyServer.cpp
183ffc CKeyServer::Open(
fa8bfc ¤   PGPtlsSessionRef¤   inTLSSession)
dabb36 {
21bd83 ¤   if (mIsOpen) {
d7d245 ¤   ¤   ThrowPGPError_(kPGPError_ServerOpen);
239371 ¤   }
565fd8 ¤   mTLSSession = inTLSSession;
3e6023 ¤   InitializeHostNameAndAddress();
210a92 ¤   mIsOpen = true;
08efe6 }
33af5a
76af5a
b2af5a
d76d52 ¤   void
fdb21d CKeyServer::Close()
59bb36 {
3e5e72 ¤   mTLSSession = kInvalidPGPtlsSessionRef;
5d85e9 ¤   mIsOpen = false;
e230c8 ¤   mSecured = false;
4412b6 ¤   mCanceled = false;
22efe6 }
02af5a
4eaf5a
36af5a
096d52 ¤   void
4e34e8 CKeyServer::Cancel()
c0bb36 {
fdda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
dcaf5a
cfc431 ¤   mCanceled = true;
6dafb9 #if PGP_WIN32
ad997a ¤   if (PGPAsyncHostEntryRefIsValid(mAsyncHostEntryRef)) {
ebfb89 ¤   ¤   PGPCancelAsyncHostEntryRef(mAsyncHostEntryRef);
ad67b7 ¤   ¤   mAsyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
dc9371 ¤   }
3f7454 #endif
26efe6 }
ddaf5a
05af5a
9eaf5a
006d52 ¤   void
55acc5 CKeyServer::GetHostName(
aecda9 ¤   char **¤outHostName)
0fbb36 {
936023 ¤   InitializeHostNameAndAddress();
bcc405 ¤   *outHostName = (char *) PGPNewData(¤PGPGetContextMemoryMgr(mContext),
1c9f6d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen(mHostName) + 1,
7f92d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_None);
e87f07 ¤   if (*outHostName == NULL) {
6916b3 ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
ba9371 ¤   }
9706dd ¤   strcpy(*outHostName, mHostName);
c8efe6 }
36af5a
e3af5a
75af5a
d06d52 ¤   void
12c469 CKeyServer::GetAddress(
466648 ¤   PGPUInt32 &¤outAddress)
e0bb36 {
656023 ¤   InitializeHostNameAndAddress();
7e086f ¤   outAddress = mHostAddress;
3aefe6 }
faaf5a
5aaf5a
27af5a
2c6d52 ¤   void
ece0e6 CKeyServer::GetErrorString(
662e19 ¤   char **¤outErrorString)
03bb36 {
c2adf7 ¤   if (mErrorString != NULL) {
6848b8 ¤   ¤   *outErrorString = (char *) PGPNewData(
--c0e7 000653324194010023c Page 10 of CKeyServer.cpp
913e0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr(mContext),
8e8ece ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen(mErrorString) + 1,
e492d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_None);
6edb5c ¤   ¤   if (*outErrorString == NULL) {
65ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
870fe4 ¤   ¤   }
7253e4 ¤   ¤   strcpy(*outErrorString, mErrorString);
c89371 ¤   }
59efe6 }
a1af5a
a0af5a
19af5a
8e6d52 ¤   void
8b690c CKeyServer::SetErrorString(
4fbc8c ¤   const char *¤   inErrorString)
b0bb36 {
ea98db ¤   delete[] mErrorString;
b067c5 ¤
d80150 ¤   if (inErrorString == NULL) {
20c3e4 ¤   ¤   mErrorString = NULL;
40f037 ¤   } else {
3aef85 ¤   ¤   mErrorString = new char[strlen(inErrorString) + 1];
57260b ¤   ¤   if (mErrorString != NULL) {
450c7a ¤   ¤   ¤   strcpy(mErrorString, inErrorString);
380fe4 ¤   ¤   }
069371 ¤   }
f5efe6 }
75af5a
58af5a
9e6d52 ¤   void
63ab4e CKeyServer::InitializeHostNameAndAddress()
f2bb36 {
93da0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
466b56 ¤   PGPHostEntry *¤ ¤   ¤   ¤   ¤   hostEntry = NULL;
ba67c5 ¤
d96b0e ¤   if (mHostName != NULL) {
9ca1a2 ¤   ¤   PGPUInt32¤  tempAddress = PGPDottedToInternetAddress(mHostName);
a11b52 ¤   ¤
c2e0f2 ¤   ¤   if (tempAddress != kPGPSockets_Error) {
0a5544 ¤   ¤   ¤   mHostAddress = PGPNetToHostLong(tempAddress);
b2ed07 ¤   ¤   ¤   delete mHostName;
d07b21 ¤   ¤   ¤   mHostName = NULL;
6c0fe4 ¤   ¤   }
fa9371 ¤   }
6967c5 ¤
4eafb9 #if PGP_WIN32
578721 ¤   ¤   PGPError¤   ¤   ¤   ¤   err;
6d8589 ¤   ¤   char¤   ¤   ¤   ¤   ¤   h_name[256];
3f7454 #endif
c41b52 ¤   ¤
b3f8b4 ¤   if (mHostName == NULL) {
9fb729 ¤   ¤   PGPInternetAddress¤ theAddress;
ee030e ¤   ¤   char *¤ ¤   ¤   ¤   theHostName;
451b52 ¤   ¤
1d2ec7 ¤   ¤   theAddress.s_addr = PGPHostToNetLong(mHostAddress);
2eafb9 #if PGP_WIN32
1c96d3 ¤   ¤   err = PGPStartAsyncGetHostByAddress(theAddress.s_addr,
796d52 ¤   ¤   ¤   ¤   &mAsyncHostEntryRef);
10cff0 ¤   ¤   ThrowIfPGPError_(err);
e741a3 ¤   ¤   err = PGPWaitForGetHostByAddress(mAsyncHostEntryRef,
a02229 ¤   ¤   ¤   ¤   h_name, 256);
1d67b7 ¤   ¤   mAsyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
e1044d ¤   ¤   if (IsPGPError(err)) {
dadb21 #else
4fff3f ¤   ¤   hostEntry = PGPGetHostByAddress((const char *) &theAddress,
ae5592 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPInternetAddress),
7faccc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPProtocolFamilyInternet);
bc5f24 ¤   ¤   if (hostEntry == NULL) {
cc7454 #endif
832b3b ¤   ¤   ¤   PGPInternetAddress¤ address;
ce87c7 ¤   ¤   ¤
6515f0 ¤   ¤   ¤   address.s_addr = PGPHostToNetLong(mHostAddress);
--ced3 0006ea156934010023c Page 11 of CKeyServer.cpp
301e80 ¤   ¤   ¤   theHostName = PGPInternetAddressToDottedString(address);
4581a8 ¤   ¤   ¤   if (theHostName == NULL) {
00f9d7 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_UnknownError);
0da3a6 ¤   ¤   ¤   }
ec45a6 ¤   ¤   } else {
58afb9 #if PGP_WIN32
9bb884 ¤   ¤   ¤   theHostName = h_name;
5adb21 #else
de9fc9 ¤   ¤   ¤   theHostName = hostEntry->h_name;
a07454 #endif
ea0fe4 ¤   ¤   }
d9578c ¤   ¤   mHostName = new char[strlen(theHostName) + 1];
5c43e2 ¤   ¤   if (mHostName == NULL) {
e4ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
520fe4 ¤   ¤   }
931582 ¤   ¤   strcpy(mHostName, theHostName);
61a7e3 ¤   } else if (mHostAddress == 0) {
bdafb9 #if PGP_WIN32
9ca61f ¤   ¤   err = PGPStartAsyncGetHostByName(mHostName, &mAsyncHostEntryRef);
f2cff0 ¤   ¤   ThrowIfPGPError_(err);
feb6f2 ¤   ¤   err = PGPWaitForGetHostByName(mAsyncHostEntryRef, &mHostAddress);
a667b7 ¤   ¤   mAsyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
37cff0 ¤   ¤   ThrowIfPGPError_(err);
e50c2b ¤   ¤   mHostAddress = PGPNetToHostLong(mHostAddress);
0ddb21 #else
ff09b1 ¤   ¤   hostEntry = PGPGetHostByName(mHostName);
c95f24 ¤   ¤   if (hostEntry == NULL) {
fc5b01 ¤   ¤   ¤   ThrowPGPError_(PGPGetLastSocketsError());
100fe4 ¤   ¤   }
cba960 ¤   ¤   mHostAddress = PGPNetToHostLong(
83c7ea ¤   ¤   ¤   ¤   ¤   ¤   ¤   *((PGPUInt32 *)hostEntry->h_addr));
627454 #endif
089371 ¤   }
62efe6 }
cbaf5a
96af5a
72af5a
b00ccc #if PGP_MACINTOSH
736d52 ¤   void
2cb83e CKeyServer::CreateThreadStorage(
98694b ¤   SThreadContext **¤  outContext)
efbb36 {
604cd1 ¤   OSStatus¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err;
0546ba ¤   ThreadID¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theThreadID;
38348d ¤   map<ThreadID, SThreadContext>::iterator¤¤   theIterator;
b8a4a3 ¤   SThreadContext *¤   ¤   ¤   ¤   ¤   ¤   ¤   theResult = nil;
f1af5a
115168 ¤   try {
f84d98 ¤   ¤   err = ::GetCurrentThread(&theThreadID);
eb951b ¤   ¤   if (err != noErr) {
0a3afd ¤   ¤   ¤   ThrowPGPError_(err);
970fe4 ¤   ¤   }
4d6c46 ¤   ¤   theIterator = sThreadContextMap.find(theThreadID);
ebd9d4 ¤   ¤   if (theIterator != sThreadContextMap.end()) {
564206 ¤   ¤   ¤   theResult = new SThreadContext;
f78173 ¤   ¤   ¤   if (theResult == NULL) {
61df26 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
03a3a6 ¤   ¤   ¤   }
6c8503 ¤   ¤   ¤   *theResult = (*theIterator).second;
6245a6 ¤   ¤   } else {
3fdc85 ¤   ¤   ¤   SThreadContext¤ tempContext = {0, };
57af5a
4aa2dc ¤   ¤   ¤   pgpLeaksSuspend();
d05e53 ¤   ¤   ¤   sThreadContextMap[theThreadID] = tempContext;
aef60d ¤   ¤   ¤   pgpLeaksResume();
5787c7 ¤   ¤   ¤
c96ca4 ¤   ¤   ¤   theIterator = sThreadContextMap.find(theThreadID);
5349f4 ¤   ¤   ¤   if (theIterator == sThreadContextMap.end()) {
d8df26 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
60a3a6 ¤   ¤   ¤   }
c50fe4 ¤   ¤   }
6ee581 ¤   ¤   (*theIterator).second.idleEventHandler = NULL;
--fe15 000a495f4624010023c Page 12 of CKeyServer.cpp
a5fec3 ¤   ¤   (*theIterator).second.idleEventHandlerData = NULL;
039371 ¤   }
c067c5 ¤
4ee0a3 ¤   catch (...) {
390156 ¤   ¤   delete theResult;
2ca33a ¤   ¤   throw;
ad9371 ¤   }
e367c5 ¤
256c30 ¤   *outContext = theResult;
d5efe6 }
b8af5a
25af5a
39af5a
ab6d52 ¤   void
476845 CKeyServer::DisposeThreadStorage(
cc3e01 ¤   SThreadContext *¤   inContext)
6dbb36 {
dd6cde ¤   ThreadID¤   theThreadID;
caa21f ¤   OSStatus¤   err;¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
bf67c5 ¤
9855c8 ¤   err = ::GetCurrentThread(&theThreadID);
32637e ¤   if (err != noErr) {
6281ab ¤   ¤   ThrowPGPError_(err);
ec9371 ¤   }
6b91cf ¤   if (inContext != NULL) {
ad10d4 ¤   ¤   sThreadContextMap[theThreadID] = *inContext;
104482 ¤   ¤   delete inContext;
79f037 ¤   } else {
d51e37 ¤   ¤   map<ThreadID, SThreadContext>::iterator¤theIterator;
95af5a
3f6c46 ¤   ¤   theIterator = sThreadContextMap.find(theThreadID);
c2d9d4 ¤   ¤   if (theIterator != sThreadContextMap.end()) {
b6ba9a ¤   ¤   ¤   sThreadContextMap.erase(theThreadID);
870fe4 ¤   ¤   }
ae9371 ¤   }
5b1b52 ¤   ¤
12efe6 }
0dbd80 ¤   static SThreadContext *
c70b2d GetThreadContext()
b9bb36 {
634cd1 ¤   OSStatus¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err;
ea46ba ¤   ThreadID¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theThreadID;
5f348d ¤   map<ThreadID, SThreadContext>::iterator¤¤   theIterator;
84a4a3 ¤   SThreadContext *¤   ¤   ¤   ¤   ¤   ¤   ¤   theResult = nil;
fa67c5 ¤
435168 ¤   try {
464d98 ¤   ¤   err = ::GetCurrentThread(&theThreadID);
e1951b ¤   ¤   if (err != noErr) {
dd3afd ¤   ¤   ¤   ThrowPGPError_(err);
040fe4 ¤   ¤   }
dc6c46 ¤   ¤   theIterator = sThreadContextMap.find(theThreadID);
394a83 ¤   ¤   if (theIterator == sThreadContextMap.end()) {
6434da ¤   ¤   ¤   ThrowPGPError_(kPGPError_SocketsNoStaticStorage);
040fe4 ¤   ¤   }
5daf5a
cb4e3b ¤   ¤   theResult = &(*theIterator).second;
d19371 ¤   }
ce67c5 ¤
19e0a3 ¤   catch (...) {
669371 ¤   }
5d67c5 ¤
034c46 ¤   return theResult;
94efe6 }
d2af5a
27af5a
ebaf5a
066d52 ¤   void
4ae8c2 CKeyServer::GetThreadIdleEventHandler(
fe286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
bd70d3 ¤   PGPUserValue *¤ ¤   ¤   ¤   outUserData)
28bb36 {
a41ad0 ¤   SThreadContext *¤   theContext = GetThreadContext();
--5cd9 000bfabebd44010023c Page 13 of CKeyServer.cpp
2a67c5 ¤
1377ba ¤   if (theContext != NULL) {
5a22a0 ¤   ¤   *outCallback = theContext->idleEventHandler;
1fd685 ¤   ¤   *outUserData = theContext->idleEventHandlerData;
cdf037 ¤   } else {
58fa75 ¤   ¤   *outCallback = NULL;
e84104 ¤   ¤   *outUserData = NULL;
f09371 ¤   }
89efe6 }
e2af5a
64af5a
1daf5a
496d52 ¤   void
eba526 CKeyServer::SetThreadIdleEventHandler(
1bd261 ¤   PGPEventHandlerProcPtr¤ inCallback,
72dbfa ¤   PGPUserValue¤   ¤   ¤   inUserData)
84bb36 {
a81ad0 ¤   SThreadContext *¤   theContext = GetThreadContext();
bc67c5 ¤
3a77ba ¤   if (theContext != NULL) {
8c5bff ¤   ¤   theContext->idleEventHandler = inCallback;
177410 ¤   ¤   theContext->idleEventHandlerData = inUserData;
569371 ¤   }
8fefe6 }
dfaf5a
f8af5a
10af5a
8d14ea #elif PGP_WIN32
076d52 ¤   void
84e8c2 CKeyServer::GetThreadIdleEventHandler(
e9286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
cc70d3 ¤   PGPUserValue *¤ ¤   ¤   ¤   outUserData)
1cbb36 {
819d96 ¤   PGPRMWOLockStartReading(&sThreadLock);
4088f1 ¤   *outCallback = (PGPEventHandlerProcPtr)
eaa4b0 ¤   ¤   ¤   ¤   ¤   TlsGetValue(sIdleEventHandlerIndex);
221c6c ¤   *outUserData = (PGPUserValue) TlsGetValue(sIdleEventHandlerDataIndex);
9b6d8d ¤   PGPRMWOLockStopReading(&sThreadLock);
9befe6 }
9caf5a
71af5a
4daf5a
0a6d52 ¤   void
d0a526 CKeyServer::SetThreadIdleEventHandler(
60d261 ¤   PGPEventHandlerProcPtr¤ inCallback,
e9dbfa ¤   PGPUserValue¤   ¤   ¤   inUserData)
91bb36 {
098e4f ¤   PGPRMWOLockStartWriting(&sThreadLock);
fdac21 ¤   if (TlsSetValue(sIdleEventHandlerIndex, inCallback)) {
704c3f ¤   ¤   if (! TlsSetValue(sIdleEventHandlerDataIndex, inUserData)) {
9dfe49 ¤   ¤   ¤   TlsSetValue(sIdleEventHandlerIndex, NULL);
950fe4 ¤   ¤   }
f19371 ¤   }
397e54 ¤   PGPRMWOLockStopWriting(&sThreadLock);
02efe6 }
60af5a
a8af5a
7b6d52 ¤   void
ecb83e CKeyServer::CreateThreadStorage(
ff694b ¤   SThreadContext **¤  outContext)
9bbb36 {
0311fa ¤   *outContext = new SThreadContext;
725412 ¤   if (*outContext == NULL) {
6c16b3 ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
5c9371 ¤   }
d57d49 ¤   GetThreadIdleEventHandler(¤ &(*outContext)->idleEventHandler,
562d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &(*outContext)->idleEventHandlerData);
e1efe6 }
57af5a
51af5a
51af5a
bf6d52 ¤   void
--c374 001859e8fb64010023c Page 14 of CKeyServer.cpp
686845 CKeyServer::DisposeThreadStorage(
ad3e01 ¤   SThreadContext *¤   inContext)
92bb36 {
7f91cf ¤   if (inContext != NULL) {
423279 ¤   ¤   SetThreadIdleEventHandler(¤ inContext->idleEventHandler,
7876af ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inContext->idleEventHandlerData);
7f4482 ¤   ¤   delete inContext;
d79371 ¤   }
beefe6 }
16af5a
c1bac4 #elif PGP_UNIX
46af5a
156d52 ¤   void
e5e8c2 CKeyServer::GetThreadIdleEventHandler(
5e286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
3970d3 ¤   PGPUserValue *¤ ¤   ¤   ¤   outUserData)
3abb36 {
fdce71 ¤   (void) outCallback;
857514 ¤   (void) outUserData;
2b67c5 ¤
237076 ¤   ThrowPGPError_(kPGPError_ServerOperationNotSupported);
1befe6 }
6baf5a
14af5a
0aaf5a
756d52 ¤   void
12a526 CKeyServer::SetThreadIdleEventHandler(
a0d261 ¤   PGPEventHandlerProcPtr¤ inCallback,
fedbfa ¤   PGPUserValue¤   ¤   ¤   inUserData)
14bb36 {
524df8 ¤   (void) inCallback;
73f69d ¤   (void) inUserData;
1f67c5 ¤
257076 ¤   ThrowPGPError_(kPGPError_ServerOperationNotSupported);
7befe6 }
87af5a
4aaf5a
b56d6b ¤   ¤   void
6db83e CKeyServer::CreateThreadStorage(
a5694b ¤   SThreadContext **¤  outContext)
35bb36 {
aad4c6 ¤   *outContext = NULL;
32efe6 }
eeaf5a
65af5a
1eaf5a
176d52 ¤   void
d86845 CKeyServer::DisposeThreadStorage(
0f3e01 ¤   SThreadContext *¤   inContext)
31bb36 {
daefe6 }
ceaf5a
852841 #endif¶
--bc5c 000c700c3b94010023d Page 1 of CKeyServer.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
1ca88c ¤   $Id: CKeyServer.h,v 1.23.10.1 1998/11/12 03:22:17 heller Exp $
8ef7f7 ____________________________________________________________________________*/
29af5a
42128a #ifndef Included_CKeyServer_h
c546be #define Included_CKeyServer_h
dcaf5a
59afb9 #if PGP_WIN32
d25655 #include <windows.h>
6dffdc #include "PGPAsyncDNS.h"
da7454 #endif
a6af5a
e1baa5 #if PGP_WIN32 || PGP_UNIX
2e51b9 #include "pgpRMWOLock.h"
3d7454 #endif
93af5a
94624c #include "pgpException.h"
2aaf5a
71eb5b #include "pgpKeyServer.h"
7eaf5a
233887 /* Key ordering */
2693f2 enum PGPKeyUploadPreference_
64bb36 {
846873 ¤   kPGPInvalid¤¤   ¤   ¤   ¤   ¤   ¤   = 0,
51fdba ¤   kPGPPublicKeyOnly ¤ ¤   ¤   ¤   ¤   = 1,
c43d7a ¤   kPGPPrivateKeyAllowed¤  ¤   ¤   ¤   = 2,
7967c5 ¤
92b529 ¤   PGP_ENUM_FORCE( PGPKeyUploadPreference_ )
1c2fa1 } ;
bf6349 PGPENUM_TYPEDEF( PGPKeyUploadPreference_, PGPKeyUploadPreference );
69af5a
5faf5a
61af5a
725fea class StPreserveSocketsEventHandler;
86af5a
46896e struct SThreadContext;
b4af5a
c086f8 class CKeyServer {
843cf3 ¤   friend class StPreserveSocketsEventHandler;
6367c5 ¤
615ed4 public:
568958 ¤   static void¤¤   ¤   ¤   ¤   ¤   Initialize();
5ce3c9 ¤   static void¤¤   ¤   ¤   ¤   ¤   Cleanup();
d21b52 ¤   ¤
7e2769 ¤   static void¤¤   ¤   ¤   ¤   ¤   SetIdleEventHandler(
e7604d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr inCallback,
394015 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue inUserData);
b2942a ¤   static void¤¤   ¤   ¤   ¤   ¤   GetIdleEventHandler(
31ab0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr * outCallback,
e29225 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue * outUserData);
0667c5 ¤
0450ed ¤   static void¤¤   ¤   ¤   ¤   ¤   CreateThreadStorage(
bbc40c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   SThreadContext ** outContext);
c58cbb ¤   static void¤¤   ¤   ¤   ¤   ¤   DisposeThreadStorage(
f3475c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   SThreadContext * inContext);
b8af5a
92aa32 ¤   static CKeyServer *¤¤   ¤   ¤   NewKeyServerFromURL(
b38dc3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef inContext,·
e666a5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inURL,·
e2b37e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
5549a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace);
0eb698 ¤   static CKeyServer *¤¤   ¤   ¤   NewKeyServerFromHostAddress(
05ed7d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef inContext,
945703 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 inHostAddress,
0e899c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 inHostPort,
86dc0f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType inType,
c7b37e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
--2126 000b5598e3c4010023d Page 2 of CKeyServer.h
2f49a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace);
3ad5a2 ¤   static CKeyServer *¤¤   ¤   ¤   NewKeyServerFromHostName(
34ed7d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef inContext,
59c585 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inHostName,
61899c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 inHostPort,
b9dc0f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType inType,
ffb37e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
ba49a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace);
0e0230 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
588cd1 ¤   virtual PGPBoolean¤ ¤   ¤   ¤   Free();
d24bc6 ¤   virtual void¤   ¤   ¤   ¤   ¤   IncRefCount() { mRefCount++; }
230230 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
27a2dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   CKeyServer(PGPContextRef inContext,
11c585 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inHostName,
2f5703 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 inHostAddress,
6b899c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 inHostPort,
3ac1b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType inType);
24adf0 ¤   virtual¤¤   ¤   ¤   ¤   ¤   ¤   ~CKeyServer();
f367c5 ¤
fc6b61 ¤   virtual void¤   ¤   ¤   ¤   ¤   SetEventHandler(
01604d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr inCallback,
1f2162 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue inUserData)
9ceef0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { mEventHandler = inCallback;
740ef8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··mEventHandlerData = inUserData; }
d923bc ¤   virtual void¤   ¤   ¤   ¤   ¤   GetEventHandler(
d8d2c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr & outCallback,
59c53d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue & outUserData)
9c09b7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { outCallback = mEventHandler;
6ea9f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··outUserData = mEventHandlerData; }
467070 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··
803a3e ¤   virtual void¤   ¤   ¤   ¤   ¤   Open(PGPtlsSessionRef inTLSSession);
a91980 ¤   virtual void¤   ¤   ¤   ¤   ¤   Close();
3067c5 ¤
167d31 ¤   virtual void¤   ¤   ¤   ¤   ¤   Cancel();
1c67c5 ¤
77a1fa ¤   virtual void¤   ¤   ¤   ¤   ¤   GetTLSSession(
53aa79 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionRef & outTLSSession)
ccbebe ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { outTLSSession = mTLSSession; }
09b206 ¤   virtual void¤   ¤   ¤   ¤   ¤   GetType(PGPKeyServerType & outType)
470138 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { outType = mType; }
47c9c3 ¤   virtual void¤   ¤   ¤   ¤   ¤   GetAccessType(PGPKeyServerAccessType &·
eb9893 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outAccessType)
a5df49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {·
355d4d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) outAccessType;
b17309 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
e3bc03 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported);
afb6fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
a9c58c ¤   virtual void¤   ¤   ¤   ¤   ¤   GetKeySpace(
858f5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace & outKeySpace)
83df49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {·
d9cce5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) outKeySpace;
437309 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
60bc03 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported);
d3b6fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
f7094e ¤   virtual void¤   ¤   ¤   ¤   ¤   GetPort(PGPUInt16 & outPort)
37a337 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { outPort = mHostPort; }
9afa85 ¤   virtual void¤   ¤   ¤   ¤   ¤   GetHostName(char ** outHostName);
be4f36 ¤   virtual void¤   ¤   ¤   ¤   ¤   GetAddress(PGPUInt32 & outAddress);
236073 ¤   virtual void¤   ¤   ¤   ¤   ¤   GetErrorString(char ** outErrorString);
870230 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
0413c5 ¤   virtual PGPBoolean¤ ¤   ¤   ¤   IsBusy() { return mIsBusy; }
922f09 ¤   virtual void¤   ¤   ¤   ¤   ¤   SetBusy(PGPBoolean inIsBusy)
0caf88 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { mIsBusy = inIsBusy; }
b067c5 ¤
a25c20 ¤   virtual PGPBoolean¤ ¤   ¤   ¤   IsCanceled() { return mCanceled; }
689b8d ¤   virtual void¤   ¤   ¤   ¤   ¤   ResetCanceled()
74634f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { mCanceled = false; }
d70230 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
d31acb ¤   virtual void¤   ¤   Query(PGPFilterRef inFilterRef,·
640156 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outFoundKeys)
e72858 ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) inFilterRef;
b56bfb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) outFoundKeys;
--3be1 00046ff7cca4010023d Page 3 of CKeyServer.h
5e3fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
9065bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
5e6c70 ¤   virtual void¤   ¤   Upload(PGPKeyUploadPreference inSendPrivateKeys,·
610d5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToUpload,
0f7617 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed)
3baff2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) inSendPrivateKeys;
f15edc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) inKeysToUpload;
5381be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) outKeysThatFailed;
a83fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
5265bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
af819f ¤   virtual void¤   ¤   Delete(PGPKeySetRef inKeysToDelete,
7a7617 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed)
7d2a1f ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) inKeysToDelete;
7881be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) outKeysThatFailed;
933fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
a765bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
937929 ¤   virtual void¤   ¤   Disable(PGPKeySetRef inKeysToDisable,
897617 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed)
c58acc ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) inKeysToDisable;
2181be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void) outKeysThatFailed;
3e3fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
6d65bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
27f450 ¤   virtual void¤   ¤   SendGroups(
7ecda3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGroupSetRef inGroupSetRef)
6fcdbf ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) inGroupSetRef;
773fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
6965bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
6d50fb ¤   virtual void¤   ¤   RetrieveGroups(
618ba8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGroupSetRef * outGroupSetRef)
d9e8a9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) outGroupSetRef;
a73fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
8765bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
aa9e30 ¤   virtual void¤   ¤   NewMonitor(
3a86ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerMonitor ** outMonitor)
62991d ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) outMonitor;
683fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
3365bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
c83d07 ¤   virtual void¤   ¤   FreeMonitor(
42f721 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerMonitor * inMonitor)
75c23d ¤   ¤   ¤   ¤   ¤   ¤   ¤   { ¤ (void) inMonitor;
a53fb3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(
1765bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_ServerOperationNotSupported); }
ffaf5a
aca2d3 protected:
f2afb9 #if PGP_WIN32
3a6aa5 ¤   static PGPRMWOLock¤ ¤   ¤   ¤   sThreadLock;
d4b406 ¤   static PGPInt32¤¤   ¤   ¤   ¤   sIdleEventHandlerIndex;
44c0ca ¤   static PGPInt32¤¤   ¤   ¤   ¤   sIdleEventHandlerDataIndex;
b269e7 ¤   PGPAsyncHostEntryRef¤   ¤   ¤   mAsyncHostEntryRef;
677454 #endif
640e27 ¤   static PGPBoolean¤  ¤   ¤   ¤   sIsInitialized;
aeaf5a
a72e9f ¤   PGPContextRef¤  ¤   ¤   ¤   ¤   mContext;
2da95e ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   mHostName;
43c5b6 ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   mHostPort;
ba03bc ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   mHostAddress;
5ac9c3 ¤   PGPKeyServerType¤   ¤   ¤   ¤   mType;
172acd ¤   PGPEventHandlerProcPtr¤ ¤   ¤   mEventHandler;
a1ae9c ¤   PGPUserValue¤   ¤   ¤   ¤   ¤   mEventHandlerData;
01219a ¤   PGPtlsSessionRef¤   ¤   ¤   ¤   mTLSSession;
6a28f4 ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   mErrorString;
9c1615 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   mSecured;
61f920 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   mIsBusy;
dd6b00 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   mIsOpen;
ee27ee ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   mCanceled;
d77511 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   ¤   mRefCount;
2d67c5 ¤
690aa2 ¤   virtual void¤   ¤   ¤   ¤   ¤   InitializeHostNameAndAddress();
f36d18 ¤   virtual void¤   ¤   ¤   ¤   ¤   SetErrorString(
60476c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inErrorString);
9ad0ba ¤   static void¤¤   ¤   ¤   ¤   ¤   GetThreadIdleEventHandler(
46ab0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr * outCallback,
--7a34 001938addf94010023d Page 4 of CKeyServer.h
809225 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue * outUserData);
2e9d5e ¤   static void¤¤   ¤   ¤   ¤   ¤   SetThreadIdleEventHandler(
4f604d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr inCallback,
654015 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue inUserData);
b8de9d ¤   static PGPError¤¤   ¤   ¤   ¤   KeyServerIdleEventHandler(
5aed7d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef inContext,
1f522d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEvent * inEvent,
accc71 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue callBackArg);
6caf5a
cf0fb9 private:
ee7492 ¤   static void¤¤   ¤   ¤   ¤   ¤   CheckInitialization();
9682f7 };
00af5a
a5af5a
72a27e class StPreserveSocketsEventHandler {
cb5ed4 public:
4e0e73 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   StPreserveSocketsEventHandler(
4ad810 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   CKeyServer * inKeyServer);
70e24d ¤   virtual¤¤   ¤   ¤   ¤   ¤   ~StPreserveSocketsEventHandler();
0a67c5 ¤
b9a2d3 protected:
578593 ¤   StPGPPreserveSocketsStorage¤mSocketsStorage;
8b82f7 };
26af5a
932841 #endif¶
--8a5d 0009cb3b9f64010023e Page 1 of CLDAPKeyServer.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
4bd0a1 ¤   $Id: CLDAPKeyServer.cpp,v 1.26.10.1 1998/11/12 03:22:18 heller Exp $
edf7f7 ____________________________________________________________________________*/
7eaf5a
98324c #include <string.h>
2db1cb #include <ctype.h>
76bea3 #include <stdlib.h>
96af5a
dc1b42 #include "pgpStrings.h"
dcfb31 #include "pgpOptionList.h"
0b2d40 #include "pgpEventPriv.h"
d6a076 #include "pgpKeys.h"
1904f5 #include "pgpFeatures.h"
7c5519 #include "pgpSockets.h"
02af5a
ce2057 #include "CLDAPKeyServer.h"
6eaf5a
15af5a
b6af5a
9d14e9 #define ThrowIfLDAPCanceled_()¤ if (mCanceled) \
bb0874 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
b61552 #define ThrowIfPGPErrorOrLDAPCanceled_(x)¤  {¤  ThrowIfPGPError_(x); \
0f06e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowIfLDAPCanceled_(); }
5baf5a
495620 static const char *¤kBaseKeyspaceDN = "baseKeyspaceDN";
ee977b static const char *¤kBasePendingDN = "basePendingDN";
1f18e3 static const char *¤kVersionDN = "version";
81b4ef static const char *¤kPGPServerInfoCN = "cn=PGPServerInfo";
0685c4 static const char *¤kMonitorCN = "cn=monitor";
458102 static const char *¤kObjectClassAny = "(objectclass=*)";
970e96 static const char *¤kPGPKeyAttribute = "pgpKey";
cb5e18 static const char *¤kPGPKeyV2Attribute = "pgpKeyV2";
06266e static const char *¤kRequestPGPRequest = "PGPrequest";
50cae0 static const char *¤kDefaultPGPGroupspace =·
b62d63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "ou=default,o=pgp groupspace,c=us";
680052 static const char *¤kPGPSrvGroupFile = "pgpSrvGroupFile";
dc7a0e static const char *¤kRequestRequest = "Request: ";
751db8 static const char * kRequestLocation = "Location: ";
a4b3ec static const char * kRequestPending = "pending";
134809 static const char *¤kRequestActive = "active";
d3051f static const char *¤kAddAndRequestDNPrefix = "pgpcertid=virtual, ";
97f405 static const char *¤kAdd = "add";
5ea7c3 static const char *¤kDelete = "delete";
51463f static const char *¤kDisable = "disable";
b5df13 static const char *¤kObjectClass = "objectclass";
c8aa4d static const char * kPGPSrvGroupFileClass = "pgpsrvgroupfile";
15af5a
05af5a
d3af5a
02a3ca CLDAPKeyServer::CLDAPKeyServer(
afb8d1 ¤   PGPContextRef¤  ¤   ¤   inContext,
de529e ¤   const char *¤   ¤   ¤   inHostName,
3260d6 ¤   PGPUInt32¤  ¤   ¤   ¤   inHostAddress,
9ada82 ¤   PGPUInt16¤  ¤   ¤   ¤   inHostPort,
360e3d ¤   PGPKeyServerType¤   ¤   inType,
ff2ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
8761b0 ¤   PGPKeyServerKeySpace¤   inKeySpace)
31d3ca ¤   : CKeyServer(inContext, inHostName, inHostAddress, inHostPort, inType),
4956ee ¤   ··mAccessType(inAccessType), mKeySpace(inKeySpace), mLDAP(NULL),
54f825 ¤   ··mBaseKeySpaceDN(NULL), mBasePendingDN(NULL),
e7d0e8 ¤   ··mExportFormat(kPGPExportFormat_Basic)
7dbb36 {
64efe6 }
4aaf5a
caaf5a
aaaf5a
9c5cec CLDAPKeyServer::~CLDAPKeyServer()
--783d 000245194cb4010023e Page 2 of CLDAPKeyServer.cpp
2cbb36 {
cbefe6 }
a7af5a
a5af5a
36af5a
a16d52 ¤   void
7c83bb CLDAPKeyServer::Open(
4f8bfc ¤   PGPtlsSessionRef¤   inTLSSession)
c8bb36 {
76da0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
c3cd99 ¤   LDAPMessage *¤  ¤   ¤   ¤   ¤   message = NULL;
3d0b21 ¤   char **¤¤   ¤   ¤   ¤   ¤   ¤   value = NULL;
80af5a
a97452 ¤   SetErrorString(NULL);
b35168 ¤   try {
7a81d8 ¤   ¤   PGPError¤   ¤   ¤   pgpError = kPGPError_NoErr;
7cd812 ¤   ¤   int¤¤   ¤   ¤   ¤   ldapResult = 0;
b1b942 ¤   ¤   LDAPMessage *¤  ¤   nextMessage = NULL;
167ae0 ¤   ¤   char *¤ ¤   ¤   ¤   attribute;
f35d85 ¤   ¤   BerElement *¤   ¤   iterAttribute;
f3b154 ¤   ¤   static const char *¤attr[4] = { kBaseKeyspaceDN,
bc42b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kBasePendingDN, kVersionDN, NULL };
9faf5a
e311d1 ¤   ¤   CKeyServer::Open(inTLSSession);
ff1b52 ¤   ¤
45cd1c ¤   ¤   // Open ldap connection
d40b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
de46a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
897c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
32a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
9a354a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Opening);
7c687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
7c59cf ¤   ¤   mLDAP = ldap_open(mHostName, mHostPort);
da5ff2 ¤   ¤   if (mLDAP == NULL) {
698159 ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
670fe4 ¤   ¤   }
e8322a ¤   ¤   ThrowIfLDAPCanceled_();
0a1b52 ¤   ¤
e01e99 ¤   ¤   // Secure connection for HTTPS
5ce871 ¤   ¤   if (mType == kPGPKeyServerType_LDAPS) {
2415cf ¤   ¤   ¤   if ((mTLSSession == kInvalidPGPtlsSessionRef)
331bb1 ¤   ¤   ¤   || (PGPSocketsEstablishTLSSession(
cbaa3e ¤   ¤   ¤   ¤   ¤   (PGPSocketRef) mLDAP->ld_sb.sb_sd,
c02975 ¤   ¤   ¤   ¤   ¤   mTLSSession) != kPGPError_NoErr)) {
6411c8 ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerTLS(
c6ea91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
628f34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
456a72 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
12e9cb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
8ac4ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_TLSUnableToSecureConnection,
8a8e95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mTLSSession);
90042d ¤   ¤   ¤   } else {
e711c8 ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerTLS(
d6ea91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
728f34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
a36a72 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
35e9cb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
4dd56c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_TLSConnectionSecured,
448e95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mTLSSession);
fc9ef8 ¤   ¤   ¤   ¤   mSecured = true;
491d31 ¤   ¤   ¤   ¤   mLDAP->tlsSession = mTLSSession;
0aa3a6 ¤   ¤   ¤   }
32c67d ¤   ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
1c0fe4 ¤   ¤   }
261b52 ¤   ¤
8ae73c ¤   ¤   // Retrieve key space distinguished names
60f3ac ¤   ¤   ldapResult = ldap_search_s(¤mLDAP,
924dfc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kPGPServerInfoCN,
67f7e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   LDAP_SCOPE_BASE,
4d6d49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kObjectClassAny,
80ccb6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char **) attr,
240320 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
--d36a 000c92d07d34010023e Page 3 of CLDAPKeyServer.cpp
335c3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &message);
ea322a ¤   ¤   ThrowIfLDAPCanceled_();
c9ab3e ¤   ¤   if (ldapResult != LDAP_SUCCESS) {
8a8159 ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
e40fe4 ¤   ¤   }
d58cb4 ¤   ¤   nextMessage = ldap_first_entry(mLDAP, message);
ff54c1 ¤   ¤   while (nextMessage != NULL) {
682bc2 ¤   ¤   ¤   attribute = ldap_first_attribute(¤  mLDAP,
83799d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
b9b9bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &iterAttribute);
72f04d ¤   ¤   ¤   while (attribute != NULL) {
f4363e ¤   ¤   ¤   ¤   value = ldap_get_values(¤   mLDAP,
885f28 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
7632cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attribute);
12cf47 ¤   ¤   ¤   ¤   if ((value != NULL) && (*value != NULL)) {
70e388 ¤   ¤   ¤   ¤   ¤   if (pgpCompareStringsIgnoreCase(attribute,
b2a47a ¤   ¤   ¤   ¤   ¤   attr[0]) == 0) {
348735 ¤   ¤   ¤   ¤   ¤   ¤   mBaseKeySpaceDN = new char[strlen(*value) + 1];
363d3f ¤   ¤   ¤   ¤   ¤   ¤   if (mBaseKeySpaceDN == NULL) {
bb5503 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
f7db3c ¤   ¤   ¤   ¤   ¤   ¤   }
b49d2d ¤   ¤   ¤   ¤   ¤   ¤   strcpy(mBaseKeySpaceDN, *value);
979feb ¤   ¤   ¤   ¤   ¤   } else if (pgpCompareStringsIgnoreCase(attribute,
ab212f ¤   ¤   ¤   ¤   ¤   attr[1]) == 0) {
e823aa ¤   ¤   ¤   ¤   ¤   ¤   mBasePendingDN = new char[strlen(*value) + 1];
bdbe39 ¤   ¤   ¤   ¤   ¤   ¤   if (mBasePendingDN == NULL) {
215503 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
6ddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
87da29 ¤   ¤   ¤   ¤   ¤   ¤   strcpy(mBasePendingDN, *value);
f29feb ¤   ¤   ¤   ¤   ¤   } else if (pgpCompareStringsIgnoreCase(attribute,
eea6c1 ¤   ¤   ¤   ¤   ¤   attr[2]) == 0) {
d1ad53 ¤   ¤   ¤   ¤   ¤   ¤   if (atol(*value) > 1) {
4be5b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   mExportFormat = kPGPExportFormat_Complete;
34db3c ¤   ¤   ¤   ¤   ¤   ¤   }
b51c89 ¤   ¤   ¤   ¤   ¤   }
300196 ¤   ¤   ¤   ¤   ¤   ldap_value_free(value);
15186d ¤   ¤   ¤   ¤   ¤   value = NULL;
a20c4e ¤   ¤   ¤   ¤   } else if ((value == NULL)
eaedaf ¤   ¤   ¤   ¤   && (mLDAP->ld_errno != LDAP_SUCCESS)) {
64e3d6 ¤   ¤   ¤   ¤   ¤   if (mLDAP->ld_errno == LDAP_INSUFFICIENT_ACCESS) {
6cfb37 ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationFailed);
2581a1 ¤   ¤   ¤   ¤   ¤   } else {
e4f77c ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
a61c89 ¤   ¤   ¤   ¤   ¤   }
d52613 ¤   ¤   ¤   ¤   }
62aca8 ¤   ¤   ¤   ¤   attribute = ldap_next_attribute(¤   mLDAP,¤
0da3b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
d0c6f3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   iterAttribute);
53a3a6 ¤   ¤   ¤   }
e326f3 pgpFixBeforeShip(am getting errors here)
0238e5 /*
0650c8 ¤   ¤   ¤   if (mLDAP->ld_errno != LDAP_SUCCESS) {
360e0e ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
40a3a6 ¤   ¤   ¤   }
e7b4a8 */¤ ¤   ¤   nextMessage = ldap_next_entry(¤ mLDAP,
619488 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage);
700fe4 ¤   ¤   }
b88041 ¤   ¤   if (/*(mLDAP->ld_errno != LDAP_SUCCESS) ||*/ (mBaseKeySpaceDN == NULL)
3744fb ¤   ¤   || (mBasePendingDN == NULL)) {
8f8159 ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
8f0fe4 ¤   ¤   }
9e2f4b ¤   ¤   ldap_msgfree(message);
869371 ¤   }
ca67c5 ¤
87e0a3 ¤   catch (...) {
41f733 ¤   ¤   delete[] mBaseKeySpaceDN;
f33f82 ¤   ¤   mBaseKeySpaceDN = NULL;
dd42db ¤   ¤   delete[] mBasePendingDN;
80de75 ¤   ¤   mBasePendingDN = NULL;
86a964 ¤   ¤   if (value != NULL) {
604ca5 ¤   ¤   ¤   ldap_value_free(value);
c90fe4 ¤   ¤   }
--66f9 000272516f64010023e Page 4 of CLDAPKeyServer.cpp
a38055 ¤   ¤   if (message != NULL) {
4aa334 ¤   ¤   ¤   ldap_msgfree(message);
3b0fe4 ¤   ¤   }
f54622 ¤   ¤   mTLSSession = kInvalidPGPtlsSessionRef;
4e3438 ¤   ¤   mIsOpen = false;
0bf77d ¤   ¤   mSecured = false;
49cc48 ¤   ¤   if (mLDAP != NULL) {
80f3e7 ¤   ¤   ¤   if (!mCanceled) {
e873b4 ¤   ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
8ca3a6 ¤   ¤   ¤   }
9c5868 ¤   ¤   ¤   ldap_unbind(mLDAP);
0299f0 ¤   ¤   ¤   mLDAP = NULL;
850fe4 ¤   ¤   }
83cd91 ¤   ¤   if (mCanceled) {
a1e47f ¤   ¤   ¤   mCanceled = false;
f545f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
8e45a6 ¤   ¤   } else {
8b4199 ¤   ¤   ¤   throw;
750fe4 ¤   ¤   }
c79371 ¤   }
fcefe6 }
49af5a
33af5a
87af5a
e96d52 ¤   void
f9c694 CLDAPKeyServer::Close()
4bbb36 {
6eda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
6baf5a
5c4a8f ¤   pgpEventKeyServer(¤ mContext,
1710e0 ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
8a2358 ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
f72a26 ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
30f7fb ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Closing);
3494aa ¤   ¤   ¤   ¤   ¤   ¤
bec03b ¤   delete[] mBaseKeySpaceDN;
7292dc ¤   mBaseKeySpaceDN = NULL;
1bf98d ¤   delete[] mBasePendingDN;
26ca5d ¤   mBasePendingDN = NULL;
80f815 ¤   if (mLDAP != NULL) {
255b2d ¤   ¤   // Both the TLS close and the socket close are done in the LDAP unbind
95f536 ¤   ¤   ldap_unbind(mLDAP);
ccf77d ¤   ¤   mSecured = false;
fb5e45 ¤   ¤   mLDAP = NULL;
c09371 ¤   }
2f7a27 ¤   CKeyServer::Close();
f3efe6 }
87af5a
21af5a
4eaf5a
b56d52 ¤   void
612d55 CLDAPKeyServer::Cancel()
f1bb36 {
eaace7 ¤   CKeyServer::Cancel();
4d41ec ¤   if (mIsBusy && (mLDAP != NULL)
f18d31 ¤   && PGPSocketRefIsValid( (PGPSocketRef) mLDAP->ld_sb.sb_sd)) {
77c9f2 ¤   ¤   PGPCloseSocket((PGPSocketRef) mLDAP->ld_sb.sb_sd);
0b984c ¤   ¤   mLDAP->ld_sb.sb_sd = NULL;
6fafb9 #if PGP_WIN32
d8b17b ¤   ¤   if (PGPAsyncHostEntryRefIsValid(mLDAP->ld_sb.ref)) {
fbc46c ¤   ¤   ¤   PGPCancelAsyncHostEntryRef(mLDAP->ld_sb.ref);
1884f0 ¤   ¤   ¤   mLDAP->ld_sb.ref = kPGPInvalidAsyncHostEntryRef;
040fe4 ¤   ¤   }
b97454 #endif
7d9371 ¤   }
1defe6 }
60af5a
c5af5a
35af5a
d76d52 ¤   void
371ec7 CLDAPKeyServer::Query(
276917 ¤   PGPFilterRef¤   inFilterRef,
--6035 0005a57ccfb4010023e Page 5 of CLDAPKeyServer.cpp
2ee331 ¤   PGPKeySetRef *¤ outFoundKeys)
41bb36 {
27da0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
ec158c ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   query = NULL;
65cd99 ¤   LDAPMessage *¤  ¤   ¤   ¤   ¤   message = NULL;
7b0b21 ¤   char **¤¤   ¤   ¤   ¤   ¤   ¤   value = NULL;
4cb1fb ¤   PGPKeySetRef¤   ¤   ¤   ¤   ¤   foundKeys = kInvalidPGPKeySetRef;
fb6802 ¤   PGPKeySetRef¤   ¤   ¤   ¤   ¤   singleKeySet = kInvalidPGPKeySetRef;
a245e2 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   partialResults = false;
155df7 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   receivedBadKeys = false;
3cf84e ¤   int¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ldapResult ¤= 0;
58565d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   pgpError ¤  = kPGPError_NoErr;
6449e2 ¤   LDAPMessage *¤  ¤   ¤   ¤   ¤   nextMessage = NULL;
4567c5 ¤
bd7452 ¤   SetErrorString(NULL);
5a7200 ¤   if (! mIsOpen) {
01c8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
299371 ¤   }
6867c5 ¤
335168 ¤   try {
c17ae0 ¤   ¤   char *¤ ¤   ¤   ¤   attribute;
fa5d85 ¤   ¤   BerElement *¤   ¤   iterAttribute;
f3c2b4 ¤   ¤   const char *¤   ¤   attr[2] =
7c1b23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { (mExportFormat == kPGPExportFormat_Basic) ?
cda4d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyAttribute : kPGPKeyV2Attribute,
f71490 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL };
44af5a
04de71 ¤   ¤   pgpError = PGPLDAPQueryFromFilter(inFilterRef, &query);
18687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
b2af5a
840b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
4846a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
9d7c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
55a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
b259d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Querying);
7e687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
1a1b52 ¤   ¤
162e35 ¤   ¤   // Send the query
101b52 ¤   ¤
13f3ac ¤   ¤   ldapResult = ldap_search_s(¤mLDAP,
b4e402 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (mKeySpace ==·
514aae ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerKeySpace_Pending) ?
4c83ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mBasePendingDN : mBaseKeySpaceDN,
dd8e8a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   LDAP_SCOPE_SUBTREE,
cbcc85 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   query,
21ccb6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char **) attr,
780320 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
305c3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &message);
8f322a ¤   ¤   ThrowIfLDAPCanceled_();
2957de ¤   ¤   switch (ldapResult) {
ec619a ¤   ¤   ¤   case LDAP_SUCCESS:
92f776 ¤   ¤   ¤   {
cba3a6 ¤   ¤   ¤   }
b5cdcb ¤   ¤   ¤   break;
5d87c7 ¤   ¤   ¤
7487c7 ¤   ¤   ¤
4da1a5 ¤   ¤   ¤   case LDAP_INSUFFICIENT_ACCESS:
9bf776 ¤   ¤   ¤   {
1b619b ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationFailed);
d0a3a6 ¤   ¤   ¤   }
0ccdcb ¤   ¤   ¤   break;
6387c7 ¤   ¤   ¤
2387c7 ¤   ¤   ¤
bbb8d7 ¤   ¤   ¤   case LDAP_SIZELIMIT_EXCEEDED:
dcb84f ¤   ¤   ¤   case LDAP_TIMELIMIT_EXCEEDED:
00f776 ¤   ¤   ¤   {
ceaf59 ¤   ¤   ¤   ¤   partialResults = true;
67a3a6 ¤   ¤   ¤   }
adcdcb ¤   ¤   ¤   break;
5387c7 ¤   ¤   ¤
5287c7 ¤   ¤   ¤
5adb68 ¤   ¤   ¤   default:
--3b8f 000a28f4b744010023e Page 6 of CLDAPKeyServer.cpp
99f776 ¤   ¤   ¤   {
53d88f ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
20a3a6 ¤   ¤   ¤   }
f5cdcb ¤   ¤   ¤   break;
460fe4 ¤   ¤   }
47c136 ¤   ¤   PGPFreeData(query);
8279df ¤   ¤   query = NULL;
1d1b52 ¤   ¤
4db20b ¤   ¤   // Get the results
bd0b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
8d46a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
a37c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
cba280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
aa86c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_ProcessingResults);
39687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
c1a7aa ¤   ¤   pgpError = PGPNewKeySet(mContext, &foundKeys);
82687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
6c8cb4 ¤   ¤   nextMessage = ldap_first_entry(mLDAP, message);
fa54c1 ¤   ¤   while (nextMessage != NULL) {
d42bc2 ¤   ¤   ¤   attribute = ldap_first_attribute(¤  mLDAP,
57799d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
8cb9bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &iterAttribute);
b2f04d ¤   ¤   ¤   while (attribute != NULL) {
26363e ¤   ¤   ¤   ¤   value = ldap_get_values(¤   mLDAP,
b35f28 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
c732cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attribute);
33cf47 ¤   ¤   ¤   ¤   if ((value != NULL) && (*value != NULL)) {
a8e388 ¤   ¤   ¤   ¤   ¤   if (pgpCompareStringsIgnoreCase(attribute,
13a47a ¤   ¤   ¤   ¤   ¤   attr[0]) == 0) {
cccba5 ¤   ¤   ¤   ¤   ¤   ¤   pgpError = PGPImportKeySet(
349c6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
e69a72 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &singleKeySet,
15a65f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOInputBuffer(¤   mContext,
7e5fcb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *value,
6c6304 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen(*value)),
c4a080 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption(mContext));
851b01 ¤   ¤   ¤   ¤   ¤   ¤   if (IsPGPError(pgpError)) {
3357aa ¤   ¤   ¤   ¤   ¤   ¤   ¤   receivedBadKeys = true;
dea646 ¤   ¤   ¤   ¤   ¤   ¤   } else {·
6bc446 ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpError = PGPAddKeys(singleKeySet, foundKeys);
6a6f96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
17aadf ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpError = PGPCommitKeyRingChanges(foundKeys);
916f96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
c24c5e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
80b054 ¤   ¤   ¤   ¤   ¤   ¤   ¤   singleKeySet = kInvalidPGPKeySetRef;
91db3c ¤   ¤   ¤   ¤   ¤   ¤   }
641c89 ¤   ¤   ¤   ¤   ¤   }
030196 ¤   ¤   ¤   ¤   ¤   ldap_value_free(value);
a3186d ¤   ¤   ¤   ¤   ¤   value = NULL;
f20c4e ¤   ¤   ¤   ¤   } else if ((value == NULL)
99edaf ¤   ¤   ¤   ¤   && (mLDAP->ld_errno != LDAP_SUCCESS)) {
a56496 ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
ab2613 ¤   ¤   ¤   ¤   }
11aca8 ¤   ¤   ¤   ¤   attribute = ldap_next_attribute(¤   mLDAP,¤
67a3b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
c5c6f3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   iterAttribute);
3aa3a6 ¤   ¤   ¤   }
2426f3 pgpFixBeforeShip(am getting errors here)
4f38e5 /*
b950c8 ¤   ¤   ¤   if (mLDAP->ld_errno != LDAP_SUCCESS) {
c7d88f ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
eaa3a6 ¤   ¤   ¤   }
cb87c7 ¤   ¤   ¤
e5efde */¤ ¤   ¤
387158 ¤   ¤   ¤   nextMessage = ldap_next_entry(¤ mLDAP,
129488 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage);
f50fe4 ¤   ¤   }
aea09e /*¤ ¤   if (mLDAP->ld_errno != LDAP_SUCCESS) {
523a8f ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
0e0fe4 ¤   ¤   }
465ace */¤ ¤   ldap_msgfree(message);
a2f5e5 ¤   ¤   *outFoundKeys = foundKeys;
--152f 00062871f9f4010023e Page 7 of CLDAPKeyServer.cpp
a19371 ¤   }
9967c5 ¤
dae0a3 ¤   catch (...) {
edd447 ¤   ¤   if (singleKeySet != kInvalidPGPKeySetRef) {
1e2453 ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
0b0fe4 ¤   ¤   }
28d5d8 ¤   ¤   if (foundKeys != kInvalidPGPKeySetRef) {
b15543 ¤   ¤   ¤   PGPFreeKeySet(foundKeys);
ef0fe4 ¤   ¤   }
04a964 ¤   ¤   if (value != NULL) {
074ca5 ¤   ¤   ¤   ldap_value_free(value);
e90fe4 ¤   ¤   }
3e8055 ¤   ¤   if (message != NULL) {
c9a334 ¤   ¤   ¤   ldap_msgfree(message);
e50fe4 ¤   ¤   }
395870 ¤   ¤   if (query != NULL) {
c96c68 ¤   ¤   ¤   PGPFreeData(query);
900fe4 ¤   ¤   }
ffcd91 ¤   ¤   if (mCanceled) {
5945f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
a545a6 ¤   ¤   } else {
922129 ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
c34199 ¤   ¤   ¤   throw;
c70fe4 ¤   ¤   }
f49371 ¤   }
b267c5 ¤
28f2a0 ¤   if (receivedBadKeys) {
57809b ¤   ¤   ThrowPGPError_(kPGPError_ServerBadKeysInSearchResults);
6c9371 ¤   }
9a683e ¤   if (partialResults) {
b0ea29 ¤   ¤   ThrowPGPError_(kPGPError_ServerPartialSearchResults);
229371 ¤   }
08efe6 }
baaf5a
83af5a
47af5a
e76d52 ¤   void
4e83e2 CLDAPKeyServer::Upload(
76d2e4 ¤   PGPKeyUploadPreference inSendPrivateKeys,
a308e0 ¤   PGPKeySetRef¤   inKeysToUpload,
126a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
eebb36 {
2ada0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
9e67c5 ¤
31c922 ¤   char *¤ ¤   ¤   keySpace = NULL;
9564f5 ¤   char *¤ ¤   ¤   exportedKey = NULL;
fb9d1b ¤   PGPKeySetRef¤   errorKeySet = kInvalidPGPKeySetRef;
b550c2 ¤   PGPKeyListRef¤  keyList = kInvalidPGPKeyListRef;
ea2293 ¤   PGPKeyIterRef¤  keyIter = kInvalidPGPKeyIterRef;
babacd ¤   PGPKeySetRef¤   singleKeySet = kInvalidPGPKeySetRef;
210f1e ¤   PGPBoolean¤ ¤   sendRequest = false;
7bf0b0 ¤   PGPBoolean¤ ¤   authorizationFailed = false;
bc4efc ¤   PGPBoolean¤ ¤   partialFailure = false;
437af4 ¤   PGPBoolean¤ ¤   keyAlreadyExists = false;
97a178 ¤   PGPBoolean¤ ¤   failedPolicy = false;
ccbf73 ¤   PGPError¤   ¤   pgpError = kPGPError_NoErr;
890623 ¤   char *¤ ¤   ¤   keySpaceSuffix = NULL;
5d397f ¤   PGPBoolean¤ ¤   exportPrivateKeys = false;
7967c5 ¤
f16943 ¤   if( mKeySpace == kPGPKeyServerKeySpace_Pending )
fec7a1 ¤   {
013a3a ¤   ¤   keySpaceSuffix = mBasePendingDN;
2a9371 ¤   }
d30e24 ¤   else
f5c7a1 ¤   {
0f01cc ¤   ¤   keySpaceSuffix = mBaseKeySpaceDN;
f29371 ¤   }
9167c5 ¤
c87452 ¤   SetErrorString(NULL);
ab7200 ¤   if (! mIsOpen) {
38c8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
629371 ¤   }
--97f8 00052332bf74010023e Page 8 of CLDAPKeyServer.cpp
e0af5a
03ed9d ¤   if (inSendPrivateKeys == kPGPPrivateKeyAllowed) {
17af5a
657b26 ¤   ¤   if (mType != kPGPKeyServerType_LDAPS) {
41ffc7 ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOperationRequiresTLS);
600fe4 ¤   ¤   }
bfaf5a
fe123f ¤   ¤   exportPrivateKeys = true;
5c9371 ¤   }
36af5a
785168 ¤   try {
2298b5 ¤   ¤   PGPKeyRef¤  ¤   ¤   key;
558421 ¤   ¤   PGPSize¤¤   ¤   ¤   bufSize;
48243d ¤   ¤   int¤¤   ¤   ¤   ¤   ldapResult;
92afca ¤   ¤   char *¤ ¤   ¤   ¤   strVals[2] = { NULL, NULL };
2cea34 ¤   ¤   LDAPMod¤¤   ¤   ¤   mod = { 0,
8e14f4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) ((mExportFormat ==
c730b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPExportFormat_Basic) ?
bd4912 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyAttribute : kPGPKeyV2Attribute),
bfc21f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {strVals},
3184a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL };
861273 ¤   ¤   LDAPMod *¤  ¤   ¤   attrs[2] = { &mod, NULL };
ff1b52 ¤   ¤
dc0b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
d146a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
557c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
03a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
2097de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Uploading);
ba687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
d487c7 ¤   ¤   ¤
f31316 ¤   ¤   // Create error set
840f1f ¤   ¤   pgpError = PGPNewKeySet(mContext, &errorKeySet);
2bf918 ¤   ¤   ThrowIfPGPError_(pgpError);
3a1b52 ¤   ¤
e395a4 ¤   ¤   // Create keyspace
82110d ¤   ¤   keySpace = new char[strlen(kAddAndRequestDNPrefix) + strlen(
95b732 ¤   ¤   ¤   ¤   ¤   keySpaceSuffix) + 1];
fcda05 ¤   ¤   if (keySpace == NULL) {
14ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
300fe4 ¤   ¤   }
629a44 ¤   ¤   sprintf(keySpace, "%s%s", kAddAndRequestDNPrefix, keySpaceSuffix);
151b52 ¤   ¤
4ed6ba ¤   ¤   // Iterate through keys uploading them one at a time
76b80f ¤   ¤   pgpError = PGPOrderKeySet(¤ inKeysToUpload,
8515b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPAnyOrdering,
0e3a97 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyList);
12f918 ¤   ¤   ThrowIfPGPError_(pgpError);
703433 ¤   ¤   pgpError = PGPNewKeyIter(keyList, &keyIter);
a4f918 ¤   ¤   ThrowIfPGPError_(pgpError);
111951 ¤   ¤   while ((pgpError = PGPKeyIterNext(keyIter, &key)) == kPGPError_NoErr) {
ed0f26 ¤   ¤   ¤   // Send to server
45a618 ¤   ¤   ¤   pgpError = PGPNewSingletonKeySet(key, &singleKeySet);
ef3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
6e0312 ¤   ¤   ¤   if (! sendRequest) {
ad10a7 ¤   ¤   ¤   ¤   pgpError = PGPExportKeySet(
fff796 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   singleKeySet,
31def2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOExportPrivateKeys(mContext,
cfa7a9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   exportPrivateKeys),
50df0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOAllocatedOutputBuffer(
ead31c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
ecd7ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &exportedKey,
497600 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   MAX_PGPSize,
785e51 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &bufSize),
c1ca5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOExportFormat(mContext,
b371fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mExportFormat),
a22d9e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption(mContext));
51af5a
01b42b ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
f4c257 ¤   ¤   ¤   ¤   strVals[0] = exportedKey;
0b6dbb ¤   ¤   ¤   ¤   ldapResult = ldap_add_s(¤   mLDAP,
c1d612 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keySpace,
523a7d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attrs);
--c0b2 000edbf67284010023e Page 9 of CLDAPKeyServer.cpp
25484e ¤   ¤   ¤   ¤   PGPFreeData(exportedKey);
46ef50 ¤   ¤   ¤   ¤   exportedKey = NULL;
5eddc5 ¤   ¤   ¤   ¤   if (ldapResult != LDAP_SUCCESS) {
4fe3a5 ¤   ¤   ¤   ¤   ¤   partialFailure = true;
1d248c ¤   ¤   ¤   ¤   ¤   PGPAddKeys(singleKeySet, errorKeySet);
e5b34b ¤   ¤   ¤   ¤   ¤   switch (ldapResult) {
5836b3 ¤   ¤   ¤   ¤   ¤   ¤   case LDAP_ALREADY_EXISTS:
9f8fec ¤   ¤   ¤   ¤   ¤   ¤   {
cd1fee ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyAlreadyExists = true;
99db3c ¤   ¤   ¤   ¤   ¤   ¤   }
b900eb ¤   ¤   ¤   ¤   ¤   ¤   break;
0f94aa ¤   ¤   ¤   ¤   ¤   ¤
3194aa ¤   ¤   ¤   ¤   ¤   ¤
8cf9a8 ¤   ¤   ¤   ¤   ¤   ¤   case LDAP_INSUFFICIENT_ACCESS:
a28fec ¤   ¤   ¤   ¤   ¤   ¤   {
7f5f01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sendRequest = true;
40db3c ¤   ¤   ¤   ¤   ¤   ¤   }
0d00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
8594aa ¤   ¤   ¤   ¤   ¤   ¤
aa94aa ¤   ¤   ¤   ¤   ¤   ¤
850f72 ¤   ¤   ¤   ¤   ¤   ¤   case LDAP_INVALID_CREDENTIALS:
7b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
d29d57 ¤   ¤   ¤   ¤   ¤   ¤   ¤   failedPolicy = true;
e8db3c ¤   ¤   ¤   ¤   ¤   ¤   }
ad00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
cd1c89 ¤   ¤   ¤   ¤   ¤   }
b22613 ¤   ¤   ¤   ¤   }
04a3a6 ¤   ¤   ¤   }
4687c7 ¤   ¤   ¤
f92a9f ¤   ¤   ¤   // Need to send a signed request
045f59 ¤   ¤   ¤   if (sendRequest && (! mSecured)) {
cd8006 ¤   ¤   ¤   ¤   pgpError = SendRequest(kAdd, singleKeySet, NULL);
529510 ¤   ¤   ¤   ¤   if (IsPGPError(pgpError)) {
3ae3a5 ¤   ¤   ¤   ¤   ¤   partialFailure = true;
15248c ¤   ¤   ¤   ¤   ¤   PGPAddKeys(singleKeySet, errorKeySet);
bb7a09 ¤   ¤   ¤   ¤   ¤   switch (pgpError) {
ea4cc5 ¤   ¤   ¤   ¤   ¤   ¤   case kPGPError_ServerKeyAlreadyExists:
758fec ¤   ¤   ¤   ¤   ¤   ¤   {
961fee ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyAlreadyExists = true;
94db3c ¤   ¤   ¤   ¤   ¤   ¤   }
6b00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
b094aa ¤   ¤   ¤   ¤   ¤   ¤
0a94aa ¤   ¤   ¤   ¤   ¤   ¤
db2cd9 ¤   ¤   ¤   ¤   ¤   ¤   case kPGPError_ServerAuthorizationFailed:
4b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
2d0047 ¤   ¤   ¤   ¤   ¤   ¤   ¤   authorizationFailed = true;
65db3c ¤   ¤   ¤   ¤   ¤   ¤   }
8900eb ¤   ¤   ¤   ¤   ¤   ¤   break;
ca94aa ¤   ¤   ¤   ¤   ¤   ¤
d094aa ¤   ¤   ¤   ¤   ¤   ¤
fc6037 ¤   ¤   ¤   ¤   ¤   ¤   case kPGPError_ServerKeyFailedPolicy:
f08fec ¤   ¤   ¤   ¤   ¤   ¤   {
5b9d57 ¤   ¤   ¤   ¤   ¤   ¤   ¤   failedPolicy = true;
3adb3c ¤   ¤   ¤   ¤   ¤   ¤   }
5300eb ¤   ¤   ¤   ¤   ¤   ¤   break;
861c89 ¤   ¤   ¤   ¤   ¤   }
572613 ¤   ¤   ¤   ¤   }
cea3a6 ¤   ¤   ¤   }
532453 ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
2270e0 ¤   ¤   ¤   singleKeySet = kInvalidPGPKeySetRef;
a60fe4 ¤   ¤   }
f1412c ¤   ¤   delete[] keySpace;
5dc314 ¤   ¤   keySpace = NULL;
d410bc ¤   ¤   PGPFreeKeyIter(keyIter);
d23aa0 ¤   ¤   keyIter = kInvalidPGPKeyIterRef;
2cc7b5 ¤   ¤   PGPFreeKeyList(keyList);
6c30e1 ¤   ¤   keyList = kInvalidPGPKeyListRef;
c8f1eb ¤   ¤   if (partialFailure) {
f9f4f6 ¤   ¤   ¤   *outKeysThatFailed = errorKeySet;
72dc17 ¤   ¤   ¤   errorKeySet = kInvalidPGPKeySetRef;
1d064b ¤   ¤   ¤   if (failedPolicy) {
ed1852 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyFailedPolicy);
--fd9f 0000d616cb34010023e Page 10 of CLDAPKeyServer.cpp
f610a5 ¤   ¤   ¤   } else if (authorizationFailed) {
98619b ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationFailed);
03058d ¤   ¤   ¤   } else if (keyAlreadyExists) {
46d571 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyAlreadyExists);
ed042d ¤   ¤   ¤   } else {
c823c6 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerPartialAddFailure);
54a3a6 ¤   ¤   ¤   }
b145a6 ¤   ¤   } else {
3be503 ¤   ¤   ¤   PGPFreeKeySet(errorKeySet);
b20fe4 ¤   ¤   }
419371 ¤   }
7367c5 ¤
a4e0a3 ¤   catch (...) {
d0412c ¤   ¤   delete[] keySpace;
bc9fd9 ¤   ¤   if (exportedKey != NULL) {
c274a0 ¤   ¤   ¤   PGPFreeData(exportedKey);
f60fe4 ¤   ¤   }
78d447 ¤   ¤   if (singleKeySet != kInvalidPGPKeySetRef) {
6f2453 ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
3a0fe4 ¤   ¤   }
562643 ¤   ¤   if (keyIter != kInvalidPGPKeyIterRef) {
562dd4 ¤   ¤   ¤   PGPFreeKeyIter(keyIter);
b70fe4 ¤   ¤   }
c23530 ¤   ¤   if (keyList != kInvalidPGPKeyListRef) {
a6fadd ¤   ¤   ¤   PGPFreeKeyList(keyList);
1e0fe4 ¤   ¤   }
585b78 ¤   ¤   if (errorKeySet != kInvalidPGPKeySetRef) {
65e503 ¤   ¤   ¤   PGPFreeKeySet(errorKeySet);
770fe4 ¤   ¤   }
51cd91 ¤   ¤   if (mCanceled) {
5745f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
3745a6 ¤   ¤   } else {
412129 ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
d54199 ¤   ¤   ¤   throw;
380fe4 ¤   ¤   }
809371 ¤   }
f2efe6 }
6faf5a
e7af5a
feaf5a
a06d52 ¤   void
4ca7cd CLDAPKeyServer::Delete(
7a2ccf ¤   PGPKeySetRef¤   inKeysToDelete,
636a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
20bb36 {
95d2a3 ¤   DeleteOrDisable(true, inKeysToDelete, outKeysThatFailed);
6defe6 }
b2af5a
58af5a
b4af5a
9a6d52 ¤   void
62aad6 CLDAPKeyServer::Disable(
6d8d4e ¤   PGPKeySetRef¤   inKeysToDisable,
056a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
1ebb36 {
6280f7 ¤   DeleteOrDisable(false, inKeysToDisable, outKeysThatFailed);
e1efe6 }
b4af5a
e2af5a
96af5a
bb6d52 ¤   void
065c28 CLDAPKeyServer::DeleteOrDisable(
e747ee ¤   PGPBoolean¤ ¤   inDelete,
611641 ¤   PGPKeySetRef¤   inKeySet,
c86a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
41bb36 {
1dda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
84d36a ¤   const char *action = NULL;
af6aa0 ¤   PGPError¤   pgpError = kPGPError_NoErr;
94af5a
b27452 ¤   SetErrorString(NULL);
0d7200 ¤   if (! mIsOpen) {
--df34 0009fae42844010023e Page 11 of CLDAPKeyServer.cpp
f6c8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
3b9371 ¤   }
f9af5a
ae5168 ¤   try {
866a89 ¤   ¤   PGPKeyServerState¤  state;
501b52 ¤   ¤
29bf2e ¤   ¤   if (mAccessType != kPGPKeyServerAccessType_Administrator) {
f75f7d ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationRequired);
910fe4 ¤   ¤   }
be8a0d ¤   ¤   if (inDelete) {
3a49c3 ¤   ¤   ¤   action = kDelete;
b8e2b1 ¤   ¤   ¤   state = kPGPKeyServerState_Deleting;
9e45a6 ¤   ¤   } else {
eb964e ¤   ¤   ¤   action = kDisable;
86146b ¤   ¤   ¤   state = kPGPKeyServerState_Disabling;
630fe4 ¤   ¤   }
430b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
da46a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
d07c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
5ba1e6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,·
0419bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   state);
e2687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
8570ba ¤   ¤   pgpError = SendRequest(¤action,
f0e4f2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySet,
e0a57f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outKeysThatFailed);
34687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
249371 ¤   }
5567c5 ¤
38e0a3 ¤   catch (...) {
3bcd91 ¤   ¤   if (mCanceled) {
e645f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
5545a6 ¤   ¤   } else {
ce2129 ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
eb4199 ¤   ¤   ¤   throw;
ed0fe4 ¤   ¤   }
699371 ¤   }
68efe6 }
31af5a
21af5a
65af5a
02c744 ¤   PGPError
2fc6ae CLDAPKeyServer::SendRequest(
aea4b9 ¤   const char *¤   inAction,
6c34e0 ¤   PGPKeySetRef¤   inKeySetRef,
ce6a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
69bb36 {
9383e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
bd339c ¤   char *¤ ¤   ¤   request = NULL;
c91b83 ¤   char *¤ ¤   ¤   signedRequest = NULL;
1750c2 ¤   PGPKeyListRef¤  keyList = kInvalidPGPKeyListRef;
4f2293 ¤   PGPKeyIterRef¤  keyIter = kInvalidPGPKeyIterRef;
d1c922 ¤   char *¤ ¤   ¤   keySpace = NULL;
f53559 ¤   char *¤ ¤   ¤   error = NULL;
ddbacd ¤   PGPKeySetRef¤   singleKeySet = kInvalidPGPKeySetRef;
4867c5 ¤
445168 ¤   try {
282542 ¤   ¤   PGPUInt32¤  ¤   ¤   requestSize = 0;
d7e57f ¤   ¤   PGPKeyID¤   ¤   ¤   keyID;
d010a5 ¤   ¤   char¤   ¤   ¤   ¤   keyIDString[kPGPMaxKeyIDStringSize];
2e7cb4 ¤   ¤   const char *¤   ¤   location = NULL;
28f24a ¤   ¤   PGPUInt32¤  ¤   ¤   total;
8781d8 ¤   ¤   PGPError¤   ¤   ¤   pgpError = kPGPError_NoErr;
0b63a9 ¤   ¤   PGPOptionListRef¤   options;
c898b5 ¤   ¤   PGPKeyRef¤  ¤   ¤   key;
5a74d8 ¤   ¤   PGPSize¤¤   ¤   ¤   dummy;
ebafca ¤   ¤   char *¤ ¤   ¤   ¤   strVals[2] = { NULL, NULL };
105bbb ¤   ¤   LDAPMod¤¤   ¤   ¤   mod = { 0, (char *) kRequestPGPRequest,
b8c69e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {strVals}, NULL };
a71273 ¤   ¤   LDAPMod *¤  ¤   ¤   attrs[2] = { &mod, NULL };
c7d812 ¤   ¤   int¤¤   ¤   ¤   ¤   ldapResult = 0;
12ec02 ¤   ¤   PGPUInt32¤  ¤   ¤   numAlgorithms;
9f86d2 ¤   ¤   char *¤ ¤   ¤   ¤   nextItem = NULL;
--f311 00068f5b98e4010023e Page 12 of CLDAPKeyServer.cpp
5e9a0a ¤   ¤   PGPUInt32 ¤ ¤   ¤   i = 0;
ad8092 ¤   ¤   PGPPublicKeyAlgorithmInfo¤  algorithmInfo;
5e1b52 ¤   ¤
5c0670 ¤   ¤   if( mKeySpace == kPGPKeyServerKeySpace_Pending )
715b34 ¤   ¤   {
47cf93 ¤   ¤   ¤   location = kRequestPending;
830fe4 ¤   ¤   }
030e1d ¤   ¤   else
bd5b34 ¤   ¤   {
5e4030 ¤   ¤   ¤   location = kRequestActive;
c40fe4 ¤   ¤   }
131b52 ¤   ¤
756e5b ¤   ¤   // Allocate request buffer and add prefix
dc712f ¤   ¤   pgpError = PGPCountKeys(inKeySetRef, &total);
76f918 ¤   ¤   ThrowIfPGPError_(pgpError);
98ec2b ¤   ¤   request = new char[strlen(kRequestRequest) + strlen(inAction)
1460aa ¤   ¤   ¤   ¤   ¤   ¤   ¤   + strlen(kRequestLocation) + strlen(location)
2bcf5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   + ((kPGPMaxKeyIDStringSize + 2) * total) + 7];
827bc1 ¤   ¤   if (request == NULL) {
86ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
640fe4 ¤   ¤   }
d1f9c3 ¤   ¤   requestSize = sprintf(¤ request,
0a9d14 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%s%s\x0D\x0A%s%s\x0D\x0A\x0D\x0A",
a6b1af ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kRequestRequest,
7e1d0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAction,
2bb6cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kRequestLocation,
f5c71c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   location);
1a1b52 ¤   ¤
e956cd ¤   ¤   // Iterate through keys creating the request
44403f ¤   ¤   pgpError = PGPOrderKeySet(inKeySetRef, kPGPAnyOrdering, &keyList);
b3f918 ¤   ¤   ThrowIfPGPError_(pgpError);
1a3433 ¤   ¤   pgpError = PGPNewKeyIter(keyList, &keyIter);
d1f918 ¤   ¤   ThrowIfPGPError_(pgpError);
931951 ¤   ¤   while ((pgpError = PGPKeyIterNext(keyIter, &key)) == kPGPError_NoErr) {
6a52e6 ¤   ¤   ¤   pgpError = PGPGetKeyIDFromKey(key, &keyID);
0e3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
c8d73d ¤   ¤   ¤   pgpError = PGPGetKeyIDString(¤  &keyID,
26965f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyIDString_Full,
1a1b02 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDString);
0a3c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
04c3af ¤   ¤   ¤   requestSize += sprintf(¤request + requestSize,
c07a87 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "%s\x0D\x0A",
9fb674 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDString);
3b0fe4 ¤   ¤   }
9910bc ¤   ¤   PGPFreeKeyIter(keyIter);
a13aa0 ¤   ¤   keyIter = kInvalidPGPKeyIterRef;
5ec7b5 ¤   ¤   PGPFreeKeyList(keyList);
8f30e1 ¤   ¤   keyList = kInvalidPGPKeyListRef;
b48c09 ¤   ¤   if (pgpError != kPGPError_EndOfIteration) {
573c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
ff0fe4 ¤   ¤   }
ea1b52 ¤   ¤
0b7a8b ¤   ¤   // Now sign the request if we do not have a secure connection
6b4c3f ¤   ¤   if (! mSecured) {
20f603 ¤   ¤   ¤   do {
66e5ab ¤   ¤   ¤   ¤   pgpError = pgpEventKeyServerSign(¤  mContext,
48a19c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &options,
e0cc84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
9de2fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
9badde ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this);
cac50a ¤   ¤   ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
789e78 ¤   ¤   ¤   ¤   pgpError = PGPEncode(¤  mContext,
75cab8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOInputBuffer(mContext,
30ec90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   request,
d38adb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   requestSize),
7f5215 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOAllocatedOutputBuffer(
64d31c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mContext,
05156d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void**)&signedRequest,
d37600 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   MAX_PGPSize,
d4bdb1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &dummy),
98c336 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   options,
68a080 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption(mContext));
--ef16 000b191da894010023e Page 13 of CLDAPKeyServer.cpp
7eeeee ¤   ¤   ¤   } while (pgpError == kPGPError_BadPassphrase);
d83c4d ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
0d3f46 ¤   ¤   ¤   delete[] request;
aea353 ¤   ¤   ¤   request = NULL;
950fe4 ¤   ¤   }
d31b52 ¤   ¤
092d12 ¤   ¤   // Send the request
54e7ae ¤   ¤   mod.mod_values[0] = (mSecured) ? request : signedRequest;
fe7ac5 ¤   ¤   keySpace = new char[strlen(kAddAndRequestDNPrefix)
771b91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   + strlen(mBaseKeySpaceDN) + 1];
89da05 ¤   ¤   if (keySpace == NULL) {
57ce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
670fe4 ¤   ¤   }
27f5b9 ¤   ¤   sprintf(keySpace, "%s%s", kAddAndRequestDNPrefix, mBaseKeySpaceDN);
f02491 ¤   ¤   ldapResult = ldap_add_s(¤   mLDAP,
0b372d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keySpace,
23b46c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attrs);
93322a ¤   ¤   ThrowIfLDAPCanceled_();
c8412c ¤   ¤   delete[] keySpace;
33c314 ¤   ¤   keySpace = NULL;
154722 ¤   ¤   if (mSecured) {
9a3f46 ¤   ¤   ¤   delete[] request;
04a353 ¤   ¤   ¤   request = NULL;
6d45a6 ¤   ¤   } else {
1ede03 ¤   ¤   ¤   PGPFreeData(signedRequest);
6a1f6c ¤   ¤   ¤   signedRequest = NULL;
ad0fe4 ¤   ¤   }
9267c5 ¤
42bb0d ¤   ¤   // Scan for error keys
47ee1b ¤   ¤   if ((outKeysThatFailed != NULL) && (mLDAP->ld_error != NULL)
880c7d ¤   ¤   && (*mLDAP->ld_error != '\0')) {
e1f07d ¤   ¤   ¤   char *¤ currentItem = NULL;
cd1b52 ¤   ¤
6188b4 ¤   ¤   ¤   error = new char[strlen(mLDAP->ld_error) + 1];
664f59 ¤   ¤   ¤   if (error == NULL) {
bfdf26 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
b2a3a6 ¤   ¤   ¤   }
f5575a ¤   ¤   ¤   strcpy(error, mLDAP->ld_error);
53ca3d ¤   ¤   ¤   currentItem = strchr(error, ':');
fac4f8 ¤   ¤   ¤   if (currentItem != NULL) {
2398ed ¤   ¤   ¤   ¤   currentItem++;
e25265 ¤   ¤   ¤   ¤   while ((*currentItem != '\0') && isspace(*currentItem)) {
051492 ¤   ¤   ¤   ¤   ¤   currentItem++;
992613 ¤   ¤   ¤   ¤   }
94cf21 ¤   ¤   ¤   ¤   while (*currentItem != '\0') {
2141a4 ¤   ¤   ¤   ¤   ¤   nextItem = currentItem;
aedc7e ¤   ¤   ¤   ¤   ¤   while ((*nextItem != '\0') && (! isspace(*nextItem))) {
de8466 ¤   ¤   ¤   ¤   ¤   ¤   nextItem++;
dc1c89 ¤   ¤   ¤   ¤   ¤   }
43cd57 ¤   ¤   ¤   ¤   ¤   if (*nextItem != '\0') {
d3ae85 ¤   ¤   ¤   ¤   ¤   ¤   *nextItem++ = '\0';
6c1c89 ¤   ¤   ¤   ¤   ¤   }
98ccfe ¤   ¤   ¤   ¤   ¤   pgpError = PGPGetKeyIDFromString(currentItem, &keyID);
fbac7b ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
24adff ¤   ¤   ¤   ¤   ¤   pgpError = PGPCountPublicKeyAlgorithms(&numAlgorithms);
23ac7b ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
1fd852 ¤   ¤   ¤   ¤   ¤   for (i = 0; i < numAlgorithms; i++) {
4e1f17 ¤   ¤   ¤   ¤   ¤   ¤   pgpError = PGPGetIndexedPublicKeyAlgorithmInfo(¤i,
e57ffa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &algorithmInfo);
603a3a ¤   ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
159f1f ¤   ¤   ¤   ¤   ¤   ¤   pgpError = PGPGetKeyByKeyID(
b01ff8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySetRef,
9506c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyID,
3fc39a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   algorithmInfo.algID,
1dc619 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &key);
8d4453 ¤   ¤   ¤   ¤   ¤   ¤   if (IsntPGPError(pgpError)
6cdd57 ¤   ¤   ¤   ¤   ¤   ¤   && (key != kInvalidPGPKeyRef)) {
a98c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
a2db3c ¤   ¤   ¤   ¤   ¤   ¤   }
321c89 ¤   ¤   ¤   ¤   ¤   }
f52684 ¤   ¤   ¤   ¤   ¤   if (*outKeysThatFailed == kInvalidPGPKeySetRef) {
b1cc7d ¤   ¤   ¤   ¤   ¤   ¤   pgpError = PGPNewKeySet(mContext, outKeysThatFailed);
--f6bd 00086479b7e4010023e Page 14 of CLDAPKeyServer.cpp
193a3a ¤   ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
fb1c89 ¤   ¤   ¤   ¤   ¤   }
72a58d ¤   ¤   ¤   ¤   ¤   pgpError = PGPNewSingletonKeySet(key, &singleKeySet);
26ac7b ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
ee7300 ¤   ¤   ¤   ¤   ¤   pgpError = PGPAddKeys(singleKeySet, *outKeysThatFailed);
c8ac7b ¤   ¤   ¤   ¤   ¤   ThrowIfPGPError_(pgpError);
a07076 ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
634cc8 ¤   ¤   ¤   ¤   ¤   singleKeySet = kInvalidPGPKeySetRef;
acf5b6 ¤   ¤   ¤   ¤   ¤   currentItem = nextItem;
822b2f ¤   ¤   ¤   ¤   ¤   while ((*currentItem != '\0') && isspace(*currentItem)) {
e15561 ¤   ¤   ¤   ¤   ¤   ¤   currentItem++;
581c89 ¤   ¤   ¤   ¤   ¤   }
f92613 ¤   ¤   ¤   ¤   }
36a3a6 ¤   ¤   ¤   }
226a37 ¤   ¤   ¤   delete[] error;
e6cf6c ¤   ¤   ¤   error = NULL;
ee0fe4 ¤   ¤   }
5c87c7 ¤   ¤   ¤
ec57de ¤   ¤   switch (ldapResult) {
f6619a ¤   ¤   ¤   case LDAP_SUCCESS:
b4f776 ¤   ¤   ¤   {
95a3a6 ¤   ¤   ¤   }
49cdcb ¤   ¤   ¤   break;
0d87c7 ¤   ¤   ¤
2187c7 ¤   ¤   ¤
bb7ca6 ¤   ¤   ¤   case LDAP_ALREADY_EXISTS:
7ef776 ¤   ¤   ¤   {
50d571 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyAlreadyExists);
52a3a6 ¤   ¤   ¤   }
46cdcb ¤   ¤   ¤   break;
9287c7 ¤   ¤   ¤
6d87c7 ¤   ¤   ¤
e4a1a5 ¤   ¤   ¤   case LDAP_INSUFFICIENT_ACCESS:
2cf776 ¤   ¤   ¤   {
43619b ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationFailed);
65a3a6 ¤   ¤   ¤   }
b7cdcb ¤   ¤   ¤   break;
5f87c7 ¤   ¤   ¤
4287c7 ¤   ¤   ¤
0e577f ¤   ¤   ¤   case LDAP_INVALID_CREDENTIALS:
63f776 ¤   ¤   ¤   {
841852 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyFailedPolicy);
bfa3a6 ¤   ¤   ¤   }
81cdcb ¤   ¤   ¤   break;
0387c7 ¤   ¤   ¤
e487c7 ¤   ¤   ¤
3ddb68 ¤   ¤   ¤   default:
d0f776 ¤   ¤   ¤   {
f76e5d ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerRequestFailed);
e5a3a6 ¤   ¤   ¤   }
cdcdcb ¤   ¤   ¤   break;
9b0fe4 ¤   ¤   }
0b9371 ¤   }
c567c5 ¤
ee8170 ¤   catch (PGPError exception) {
169c52 ¤   ¤   delete[] error;
cdb612 ¤   ¤   delete[] request;
39412c ¤   ¤   delete[] keySpace;
99d447 ¤   ¤   if (singleKeySet != kInvalidPGPKeySetRef) {
0d2453 ¤   ¤   ¤   PGPFreeKeySet(singleKeySet);
6b0fe4 ¤   ¤   }
5f29b1 ¤   ¤   if (signedRequest != NULL) {
b7de03 ¤   ¤   ¤   PGPFreeData(signedRequest);
310fe4 ¤   ¤   }
9f2643 ¤   ¤   if (keyIter != kInvalidPGPKeyIterRef) {
b62dd4 ¤   ¤   ¤   PGPFreeKeyIter(keyIter);
100fe4 ¤   ¤   }
ba3530 ¤   ¤   if (keyList != kInvalidPGPKeyListRef) {
0ffadd ¤   ¤   ¤   PGPFreeKeyList(keyList);
960fe4 ¤   ¤   }
893614 ¤   ¤   result = exception;
869371 ¤   }
--9440 00021caa5f94010023e Page 15 of CLDAPKeyServer.cpp
2a67c5 ¤
2f5d73 ¤   return result;
9fefe6 }
0aaf5a
7daf5a
49af5a
006d52 ¤   void
d8b2a1 CLDAPKeyServer::SendGroups(
efd83f ¤   PGPGroupSetRef¤ inGroupSetRef)
f8bb36 {
4bda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
f1d539 ¤   void *¤ ¤   ¤   ¤   ¤   ¤   ¤   groupsBuffer = NULL;
930eb9 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   pgpError = kPGPError_NoErr;
4edf6d ¤   int¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ldapResult = 0;
0b67c5 ¤
817452 ¤   SetErrorString(NULL);
0a7200 ¤   if (! mIsOpen) {
25c8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
259371 ¤   }
7a5168 ¤   try {
ff80e1 ¤   ¤   struct berval¤  ¤   berVal = { 0, NULL };
31b747 ¤   ¤   struct berval *¤¤   berVals[2] = { &berVal, NULL };
f0a9d2 ¤   ¤   const char *¤   ¤   strVals[2] = { kPGPSrvGroupFileClass, NULL };
84d5df ¤   ¤   LDAPMod¤¤   ¤   ¤   mod = { LDAP_MOD_BVALUES,
fc646b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kPGPSrvGroupFile,
e85152 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   { (char **) berVals }, NULL };
491273 ¤   ¤   LDAPMod *¤  ¤   ¤   attrs[2] = { &mod, NULL };
d1753f ¤   ¤   PGPSize¤¤   ¤   ¤   groupsBufferSize;
f31b52 ¤   ¤
f71b52 ¤   ¤
fb8b78 ¤   ¤   // Export the groups
4c2bfe ¤   ¤   pgpError = PGPExportGroupSetToBuffer(¤  inGroupSetRef,
798c7b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &groupsBuffer,
97a7ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &groupsBufferSize);
75f918 ¤   ¤   ThrowIfPGPError_(pgpError);
690b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
7946a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
387c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
69a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
4297de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Uploading);
24687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
8c1b52 ¤   ¤
9e5a69 ¤   ¤   // Send them to the server
1eef36 ¤   ¤   berVals[0]->bv_len = groupsBufferSize;
7892de ¤   ¤   berVals[0]->bv_val = (char *) groupsBuffer;
aa2491 ¤   ¤   ldapResult = ldap_add_s(¤   mLDAP,
311a5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kDefaultPGPGroupspace,
90b46c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attrs);
80322a ¤   ¤   ThrowIfLDAPCanceled_();
b3ab3e ¤   ¤   if (ldapResult != LDAP_SUCCESS) {
ae60d6 ¤   ¤   ¤   switch (ldapResult) {
a54048 ¤   ¤   ¤   ¤   case LDAP_ALREADY_EXISTS:
5a72c3 ¤   ¤   ¤   ¤   {
d2c052 ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyAlreadyExists);
582613 ¤   ¤   ¤   ¤   }
9ff622 ¤   ¤   ¤   ¤   break;
8e2b85 ¤   ¤   ¤   ¤
ca2b85 ¤   ¤   ¤   ¤
52303d ¤   ¤   ¤   ¤   case LDAP_INSUFFICIENT_ACCESS:
4872c3 ¤   ¤   ¤   ¤   {
1f66ed ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationFailed);
482613 ¤   ¤   ¤   ¤   }
7ff622 ¤   ¤   ¤   ¤   break;
502b85 ¤   ¤   ¤   ¤
a92b85 ¤   ¤   ¤   ¤
53c6e7 ¤   ¤   ¤   ¤   case LDAP_INVALID_CREDENTIALS:
d772c3 ¤   ¤   ¤   ¤   {
4c9217 ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyFailedPolicy);
fc2613 ¤   ¤   ¤   ¤   }
a3f622 ¤   ¤   ¤   ¤   break;
052b85 ¤   ¤   ¤   ¤
212b85 ¤   ¤   ¤   ¤
--ccd4 0008826cd564010023e Page 16 of CLDAPKeyServer.cpp
976ab9 ¤   ¤   ¤   ¤   default:
eb72c3 ¤   ¤   ¤   ¤   {
9de3a1 ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerRequestFailed);
af2613 ¤   ¤   ¤   ¤   }
b4f622 ¤   ¤   ¤   ¤   break;
5fa3a6 ¤   ¤   ¤   }
110fe4 ¤   ¤   }
61181e ¤   ¤   PGPFreeData(groupsBuffer);
ae64a6 ¤   ¤   groupsBuffer = NULL;
da1b52 ¤   ¤
c5e8fa ¤   ¤   // Add the objectclass
558c65 ¤   ¤   mod.mod_op = 0;
d32cbd ¤   ¤   mod.mod_type = (char *) kObjectClass;
94edf0 ¤   ¤   mod.mod_values = (char **) strVals;
272491 ¤   ¤   ldapResult = ldap_add_s(¤   mLDAP,
1b1a5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kDefaultPGPGroupspace,
feb46c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attrs);
bc322a ¤   ¤   ThrowIfLDAPCanceled_();
2757de ¤   ¤   switch (ldapResult) {
ca619a ¤   ¤   ¤   case LDAP_SUCCESS:
0ff776 ¤   ¤   ¤   {
54a3a6 ¤   ¤   ¤   }
32cdcb ¤   ¤   ¤   break;
8487c7 ¤   ¤   ¤
2887c7 ¤   ¤   ¤
357ca6 ¤   ¤   ¤   case LDAP_ALREADY_EXISTS:
a2f776 ¤   ¤   ¤   {
35d571 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyAlreadyExists);
7ea3a6 ¤   ¤   ¤   }
e5cdcb ¤   ¤   ¤   break;
0787c7 ¤   ¤   ¤
2a87c7 ¤   ¤   ¤
69a1a5 ¤   ¤   ¤   case LDAP_INSUFFICIENT_ACCESS:
2ef776 ¤   ¤   ¤   {
32619b ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationFailed);
8ea3a6 ¤   ¤   ¤   }
2dcdcb ¤   ¤   ¤   break;
e387c7 ¤   ¤   ¤
9587c7 ¤   ¤   ¤
84577f ¤   ¤   ¤   case LDAP_INVALID_CREDENTIALS:
d4f776 ¤   ¤   ¤   {
351852 ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerKeyFailedPolicy);
32a3a6 ¤   ¤   ¤   }
75cdcb ¤   ¤   ¤   break;
2787c7 ¤   ¤   ¤
4e87c7 ¤   ¤   ¤
bbdb68 ¤   ¤   ¤   default:
bbf776 ¤   ¤   ¤   {
ad6e5d ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerRequestFailed);
a8a3a6 ¤   ¤   ¤   }
efcdcb ¤   ¤   ¤   break;
520fe4 ¤   ¤   }
549371 ¤   }
4c67c5 ¤
10e0a3 ¤   catch (...) {
af7732 ¤   ¤   if (groupsBuffer != NULL) {
2859ed ¤   ¤   ¤   PGPFreeData(groupsBuffer);
130fe4 ¤   ¤   }
cecd91 ¤   ¤   if (mCanceled) {
c145f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
e345a6 ¤   ¤   } else {
7e2129 ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
9c4199 ¤   ¤   ¤   throw;
d00fe4 ¤   ¤   }
239371 ¤   }
9befe6 }
77af5a
4faf5a
85af5a
d96d52 ¤   void
7febc4 CLDAPKeyServer::RetrieveGroups(
88fe62 ¤   PGPGroupSetRef *¤   outGroupSetRef)
--e55e 000308605bb4010023e Page 17 of CLDAPKeyServer.cpp
2cbb36 {
1eda0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
6fcd99 ¤   LDAPMessage *¤  ¤   ¤   ¤   ¤   message = NULL;
73def0 ¤   struct berval **¤   ¤   ¤   ¤   value = NULL;
5fb70c ¤   PGPGroupSetRef¤ ¤   ¤   ¤   ¤   groupSetRef = kInvalidPGPGroupSetRef;
5a0eb9 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   pgpError = kPGPError_NoErr;
f0df6d ¤   int¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ldapResult = 0;
27af5a
687452 ¤   SetErrorString(NULL);
9e7200 ¤   if (! mIsOpen) {
b1c8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
609371 ¤   }
d05168 ¤   try {
e49581 ¤   ¤   LDAPMessage *¤  ¤   nextMessage;
a67ae0 ¤   ¤   char *¤ ¤   ¤   ¤   attribute;
c85d85 ¤   ¤   BerElement *¤   ¤   iterAttribute;
cc1fb6 ¤   ¤   static const char *¤attr[2] = { kPGPSrvGroupFile, NULL };
461b52 ¤   ¤
880b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
c046a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
007c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
caa280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
5f59d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Querying);
5b687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
051b52 ¤   ¤
01f3ac ¤   ¤   ldapResult = ldap_search_s(¤mLDAP,
fc1a5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kDefaultPGPGroupspace,
e2f7e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   LDAP_SCOPE_BASE,
766d49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kObjectClassAny,
a1ccb6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char **) attr,
930320 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
eb5c3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &message);
43322a ¤   ¤   ThrowIfLDAPCanceled_();
1fab3e ¤   ¤   if (ldapResult != LDAP_SUCCESS) {
f33a8f ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
410fe4 ¤   ¤   }
1a8cb4 ¤   ¤   nextMessage = ldap_first_entry(mLDAP, message);
59ee3e ¤   ¤   if (nextMessage != NULL) {
9e2bc2 ¤   ¤   ¤   attribute = ldap_first_attribute(¤  mLDAP,
55799d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
31b9bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &iterAttribute);
7327bc ¤   ¤   ¤   if (attribute != NULL) {
0783ea ¤   ¤   ¤   ¤   value = ldap_get_values_len(¤   mLDAP,
13799d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
18bd98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attribute);
79cf47 ¤   ¤   ¤   ¤   if ((value != NULL) && (*value != NULL)) {
2de4fc ¤   ¤   ¤   ¤   ¤   pgpError = PGPImportGroupSetFromBuffer(¤mContext,
33c0e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*value)->bv_val,
32ff5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (*value)->bv_len,
8a1d13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &groupSetRef);
911a61 ¤   ¤   ¤   ¤   ¤   ldap_value_free_len(value);
fe186d ¤   ¤   ¤   ¤   ¤   value = NULL;
a12613 ¤   ¤   ¤   ¤   }
80a3a6 ¤   ¤   ¤   }
ad26f3 pgpFixBeforeShip(am getting errors here)
3238e5 /*
b250c8 ¤   ¤   ¤   if (mLDAP->ld_errno != LDAP_SUCCESS) {
780e0e ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
0ea3a6 ¤   ¤   ¤   }
e967fd */¤ ¤   }
29671c ¤   ¤   if (groupSetRef == kInvalidPGPGroupSetRef) {
023a8f ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
ba0fe4 ¤   ¤   }
542f4b ¤   ¤   ldap_msgfree(message);
fd4ba8 ¤   ¤   *outGroupSetRef = groupSetRef;
fc9371 ¤   }
cc67c5 ¤
1fe0a3 ¤   catch (...) {
5d81fb ¤   ¤   if (groupSetRef != kInvalidPGPGroupSetRef) {
456d3f ¤   ¤   ¤   PGPFreeGroupSet(groupSetRef);
270fe4 ¤   ¤   }
30a964 ¤   ¤   if (value != NULL) {
--6c99 0003d2b15264010023e Page 18 of CLDAPKeyServer.cpp
cc8a57 ¤   ¤   ¤   ldap_value_free_len(value);
590fe4 ¤   ¤   }
2f8055 ¤   ¤   if (message != NULL) {
a2a334 ¤   ¤   ¤   ldap_msgfree(message);
7e0fe4 ¤   ¤   }
a3cd91 ¤   ¤   if (mCanceled) {
4745f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
9045a6 ¤   ¤   } else {
6e2129 ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
9f4199 ¤   ¤   ¤   throw;
a30fe4 ¤   ¤   }
4d9371 ¤   }
c8efe6 }
5baf5a
99af5a
91af5a
6c6d52 ¤   void
85d8c1 CLDAPKeyServer::NewMonitor(
77bdc8 ¤   PGPKeyServerMonitor **¤ outMonitor)
6fbb36 {
f2da0d ¤   StPreserveSocketsEventHandler¤  preserve(this);
1fcd99 ¤   LDAPMessage *¤  ¤   ¤   ¤   ¤   message = NULL;
0f0b21 ¤   char **¤¤   ¤   ¤   ¤   ¤   ¤   value = NULL;
eb8f76 ¤   PGPKeyServerMonitor *¤  ¤   ¤   monitor = NULL;
5b0eb9 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   pgpError = kPGPError_NoErr;
11df6d ¤   int¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ldapResult = 0;
e0a903 ¤   PGPKeyServerMonitorValues *¤¤   currentMonitorValue = NULL;
3349e2 ¤   LDAPMessage *¤  ¤   ¤   ¤   ¤   nextMessage = NULL;
13eecb ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   attribute = NULL;
2f6d43 ¤   int¤¤   ¤   ¤   ¤   ¤   ¤   ¤   numValues = 0;
47ba51 ¤   int ¤   ¤   ¤   ¤   ¤   ¤   ¤   i = 0;
dcaf5a
9a7452 ¤   SetErrorString(NULL);
7b7200 ¤   if (! mIsOpen) {
9ac8ff ¤   ¤   ThrowPGPError_(kPGPError_ServerNotOpen);
9b9371 ¤   }
d25168 ¤   try {
8273ec ¤   ¤   BerElement *¤   ¤   ¤   ¤   iterAttribute;
59d3e7 ¤   ¤   static const char *¤¤   ¤   attr[1] = { NULL };
d6af5a
38bf2e ¤   ¤   if (mAccessType != kPGPKeyServerAccessType_Administrator) {
4c5f7d ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerAuthorizationRequired);
940fe4 ¤   ¤   }
550b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
1746a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
a97c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
89a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
2c59d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Querying);
94687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
a5f3ac ¤   ¤   ldapResult = ldap_search_s(¤mLDAP,
eeac0f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kMonitorCN,
16f7e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   LDAP_SCOPE_BASE,
f46d49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char *) kObjectClassAny,
5accb6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (char **) attr,
bc0320 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0,
a85c3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &message);
15322a ¤   ¤   ThrowIfLDAPCanceled_();
f8ab3e ¤   ¤   if (ldapResult != LDAP_SUCCESS) {
533a8f ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerSearchFailed);
930fe4 ¤   ¤   }
4e1b52 ¤   ¤
8e0b8a ¤   ¤   pgpError = pgpEventKeyServer(¤  mContext,
ab46a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandler,
9f7c6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mEventHandlerData,
c0a280 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerRef) this,
b386c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_ProcessingResults);
d8687c ¤   ¤   ThrowIfPGPErrorOrLDAPCanceled_(pgpError);
75204e ¤   ¤   monitor = new PGPKeyServerMonitor;
5b472f ¤   ¤   if (monitor == NULL) {
dfce01 ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
a20fe4 ¤   ¤   }
3d0275 ¤   ¤   monitor->keyServerRef = (PGPKeyServerRef) this;
--caee 000a3da4c564010023e Page 19 of CLDAPKeyServer.cpp
84e327 ¤   ¤   monitor->valuesHead = NULL;
9b8cb4 ¤   ¤   nextMessage = ldap_first_entry(mLDAP, message);
7754c1 ¤   ¤   while (nextMessage != NULL) {
642bc2 ¤   ¤   ¤   attribute = ldap_first_attribute(¤  mLDAP,
38799d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
4ab9bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &iterAttribute);
5bf04d ¤   ¤   ¤   while (attribute != NULL) {
0efc7d ¤   ¤   ¤   ¤   if (currentMonitorValue == NULL) {
1ad852 ¤   ¤   ¤   ¤   ¤   monitor->valuesHead = currentMonitorValue =·
50fbe8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   new PGPKeyServerMonitorValues;
25b5fc ¤   ¤   ¤   ¤   } else {
b03957 ¤   ¤   ¤   ¤   ¤   currentMonitorValue->next =
83fbe8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   new PGPKeyServerMonitorValues;
5b4221 ¤   ¤   ¤   ¤   ¤   currentMonitorValue = currentMonitorValue->next;
152613 ¤   ¤   ¤   ¤   }
60fc7d ¤   ¤   ¤   ¤   if (currentMonitorValue == NULL) {
4cd81d ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
712613 ¤   ¤   ¤   ¤   }
b72f9b ¤   ¤   ¤   ¤   currentMonitorValue->values = NULL;
0e4a93 ¤   ¤   ¤   ¤   currentMonitorValue->next = NULL;
c47263 ¤   ¤   ¤   ¤   currentMonitorValue->name = new char[strlen(attribute) + 1];
e4239b ¤   ¤   ¤   ¤   if (currentMonitorValue->name == NULL) {
5dd81d ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
702613 ¤   ¤   ¤   ¤   }
803344 ¤   ¤   ¤   ¤   /* copy the attribute */
6b158c ¤   ¤   ¤   ¤   strncpy( currentMonitorValue->name, attribute,
13f6e9 ¤   ¤   ¤   ¤   ¤   ¤   strlen(attribute) + 1);
0b2b85 ¤   ¤   ¤   ¤
04363e ¤   ¤   ¤   ¤   value = ldap_get_values(¤   mLDAP,
045f28 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
9c32cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   attribute);
1a2f5a ¤   ¤   ¤   ¤   if (value != NULL) {
a554d4 ¤   ¤   ¤   ¤   ¤   numValues = ldap_count_values(value);
c278f0 ¤   ¤   ¤   ¤   ¤   currentMonitorValue->values = new char*[numValues + 1];
185573 ¤   ¤   ¤   ¤   ¤   if (currentMonitorValue->values == NULL) {
dcd8ff ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
3f1c89 ¤   ¤   ¤   ¤   ¤   }
d55a2d ¤   ¤   ¤   ¤   ¤   for (i = 0; i < numValues; i++) {
e90246 ¤   ¤   ¤   ¤   ¤   ¤   currentMonitorValue->values[i] =
308ecc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   new char[strlen(value[i]) + 1];
47142a ¤   ¤   ¤   ¤   ¤   ¤   if (currentMonitorValue->values[i] == NULL) {
475503 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_OutOfMemory);
4fdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
8190b7 ¤   ¤   ¤   ¤   ¤   ¤   strcpy(currentMonitorValue->values[i], value[i]);
d71c89 ¤   ¤   ¤   ¤   ¤   }
312fb9 ¤   ¤   ¤   ¤   ¤   currentMonitorValue->values[numValues] = NULL;
530196 ¤   ¤   ¤   ¤   ¤   ldap_value_free(value);
92186d ¤   ¤   ¤   ¤   ¤   value = NULL;
7b2613 ¤   ¤   ¤   ¤   }
56aca8 ¤   ¤   ¤   ¤   attribute = ldap_next_attribute(¤   mLDAP,¤
86a3b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage,
1cc6f3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   iterAttribute);
bea3a6 ¤   ¤   ¤   }
ec26f3 pgpFixBeforeShip(am getting errors here)
1038e5 /*
8a50c8 ¤   ¤   ¤   if (mLDAP->ld_errno != LDAP_SUCCESS) {
7a0e0e ¤   ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerOpenFailed);
bba3a6 ¤   ¤   ¤   }
8fb4a8 */¤ ¤   ¤   nextMessage = ldap_next_entry(¤ mLDAP,
139488 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   nextMessage);
2c0fe4 ¤   ¤   }
e62f4b ¤   ¤   ldap_msgfree(message);
788410 ¤   ¤   *outMonitor = monitor;
3e9371 ¤   }
2967c5 ¤
ace0a3 ¤   catch (...) {
5cd495 ¤   ¤   if (monitor != NULL) {
ffd546 ¤   ¤   ¤   FreeMonitor(monitor);
da0fe4 ¤   ¤   }
6ca964 ¤   ¤   if (value != NULL) {
bc4ca5 ¤   ¤   ¤   ldap_value_free(value);
a30fe4 ¤   ¤   }
--a76f 0018685fd544010023e Page 20 of CLDAPKeyServer.cpp
a38055 ¤   ¤   if (message != NULL) {
4aa334 ¤   ¤   ¤   ldap_msgfree(message);
3b0fe4 ¤   ¤   }
77cd91 ¤   ¤   if (mCanceled) {
8845f3 ¤   ¤   ¤   ThrowPGPError_(kPGPError_UserAbort);
c745a6 ¤   ¤   } else {
e12129 ¤   ¤   ¤   SetErrorString(mLDAP->ld_error);
504199 ¤   ¤   ¤   throw;
a30fe4 ¤   ¤   }
c89371 ¤   }
aeefe6 }
58af5a
3daf5a
5faf5a
7e6d52 ¤   void
cfdb47 CLDAPKeyServer::FreeMonitor(
a71f3c ¤   PGPKeyServerMonitor *¤  inMonitor)
80bb36 {
7f7db0 ¤   PGPKeyServerMonitorValues *¤currentMonitorValue = inMonitor->valuesHead;
7ac6ea ¤   PGPKeyServerMonitorValues * tempMonitorValue;
94b4da ¤   char **¤¤   ¤   ¤   ¤   ¤   tempValue;
3367c5 ¤
d05401 ¤   while (currentMonitorValue != NULL) {
c0fd46 ¤   ¤   delete[] currentMonitorValue->name;
a5d037 ¤   ¤   if (currentMonitorValue->values != NULL) {
c498e5 ¤   ¤   ¤   tempValue = currentMonitorValue->values;
d374bb ¤   ¤   ¤   while (*tempValue != NULL) {
643311 ¤   ¤   ¤   ¤   delete[] *tempValue;
72942e ¤   ¤   ¤   ¤   tempValue++;
05a3a6 ¤   ¤   ¤   }
e62d8f ¤   ¤   ¤   delete[] currentMonitorValue->values;
ac0fe4 ¤   ¤   }
e73801 ¤   ¤   tempMonitorValue = currentMonitorValue;
b534f8 ¤   ¤   currentMonitorValue = currentMonitorValue->next;
cbc29b ¤   ¤   delete tempMonitorValue;
d29371 ¤   }
9c9a40 ¤   delete[] inMonitor;
86efe6 }
--e654 001215a967e4010023f Page 1 of CLDAPKeyServer.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
51b1a2 ¤   $Id: CLDAPKeyServer.h,v 1.4.10.1 1998/11/12 03:22:18 heller Exp $
8ef7f7 ____________________________________________________________________________*/
8daf5a
bd86c2 #ifndef Included_CLDAPKeyServer_h
e3585e #define Included_CLDAPKeyServer_h
46af5a
16e990 #include "ldap.h"
6faf5a
9cef84 #include "CKeyServer.h"
c5af5a
c0af5a
a6582a class CLDAPKeyServer : public CKeyServer {
165ed4 public:
728f08 ¤   ¤   ¤   ¤   ¤   ¤   ¤   CLDAPKeyServer(PGPContextRef inContext,
1c3919 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inHostName,
6449a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 inHostAddress,PGPUInt16 inHostPort,
972093 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType inType,
2829d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
0e4a34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace);
0e4573 ¤   virtual¤¤   ¤   ¤   ¤   ~CLDAPKeyServer();
ef67c5 ¤
62716b ¤   virtual void¤   ¤   ¤   Cancel();
daaf5a
a854d8 ¤   virtual void¤   ¤   ¤   Open(PGPtlsSessionRef inTLSSession);
19234c ¤   virtual void¤   ¤   ¤   Close();
f3af5a
527877 ¤   virtual void¤   ¤   ¤   Query(PGPFilterRef inFilterRef,
56d592 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outFoundKeys);
3bdee0 ¤   virtual void¤   ¤   ¤   Upload(PGPKeyUploadPreference inSendPrivateKeys,
e12bef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToUpload,
a1e994 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
7c7f62 ¤   virtual void¤   ¤   ¤   Delete(PGPKeySetRef inKeysToDelete,
52e994 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
46f098 ¤   virtual void¤   ¤   ¤   Disable(PGPKeySetRef inKeysToDelete,
82e994 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
bee05a ¤   virtual void¤   ¤   ¤   SendGroups(PGPGroupSetRef inGroupSetRef);
9224ea ¤   virtual void¤   ¤   ¤   RetrieveGroups(PGPGroupSetRef * outGroupSetRef);
87301e ¤   virtual void¤   ¤   ¤   NewMonitor(PGPKeyServerMonitor ** outMonitor);
847411 ¤   virtual void¤   ¤   ¤   FreeMonitor(PGPKeyServerMonitor * inMonitor);
8bda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
fea2d3 protected:
c62442 ¤   PGPKeyServerAccessType¤ mAccessType;
0c8df9 ¤   PGPKeyServerKeySpace¤   mKeySpace;
a018a5 ¤   LDAP *¤ ¤   ¤   ¤   ¤   mLDAP;
1685be ¤   char *¤ ¤   ¤   ¤   ¤   mBaseKeySpaceDN;
8a40ba ¤   char *¤ ¤   ¤   ¤   ¤   mBasePendingDN;
07b57e ¤   PGPExportFormat¤¤   ¤   mExportFormat;
0867c5 ¤
9a8aa5 ¤   void¤   ¤   ¤   ¤   ¤   DeleteOrDisable(PGPBoolean inDelete,
12c775 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeySet,
e3e994 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
6cd72c ¤   PGPError¤   ¤   ¤   ¤   SendRequest(const char * inAction,
a897cc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeySetRef,
fde994 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
1482f7 };
2aaf5a
19af5a
1baf5a
212841 #endif¶
--e890 001f6549aae40100240 Page 1 of Makefile.in
5ea601 #
093f71 # priv/networklib/keyserver/
66a601 #
69c099 # $Id: Makefile.in,v 1.6 1998/08/01 21:21:18 marcd Exp $
c4a601 #
14af5a
43fd38 .SUFFIXES: .cpp .cp
64af5a
2dd0f7 .cpp.o:
01dfd6 ¤   g++ -c -fhandle-exceptions $(CFLAGS) $<
c2af5a
c37631 LDAPDIR= $(top_srcdir)/../network/ldaplib
61af5a
f3e080 OBJS= CHTTPKeyServer.o CKeyServer.o CLDAPKeyServer.o pgpKeyServer.o
1daf5a
a28563 LOCALDEFINES= -DPROTOTYPES -D_REENTRANT -DPGPSOCKETSLDAP=1
b08c4f LOCALINCLUDES= -I$(PGPSOCKETSDIR)/pub -I$(LDAPDIR)/include
e7af5a
9155db LIBDONE= DONE
c7af5a
f6b7a3 all:: DONE
--2a4b 0003bfdb10e40100241 Page 1 of pgpKeyServer.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
714554 ¤   $Id: pgpKeyServer.cpp,v 1.20.10.1 1998/11/12 03:22:19 heller Exp $
3af7f7 ____________________________________________________________________________*/
7aaf5a
53c26c #include "pgpContext.h"
d7af5a
7daf5a
3a5519 #include "pgpSockets.h"
54af5a
28ef84 #include "CKeyServer.h"
d5eb5b #include "pgpKeyServer.h"
93af5a
a7afb9 #if PGP_WIN32
48d8f9 #include "PGPsdkNetworkLibDLLMain.h"
477454 #endif
f4af5a
63baa5 #if PGP_WIN32 || PGP_UNIX
4851b9 #include "pgpRMWOLock.h"
d8af5a
baf34c static PGPRMWOLock¤ ¤   ¤   sBusyLock;
8e0998 static PGPRMWOLock¤ ¤   ¤   sCancelLock;
d17454 #endif
18af5a
241fd1 static PGPInt32¤¤   ¤   ¤   sNumberOfInits = 0;
63af5a
4c35f5 class StKeyServerBusy {
305ed4 public:
ed1566 ¤   ¤   ¤   StKeyServerBusy(CKeyServer * inKeyServer,
3d31b1 ¤   ¤   ¤   ¤   PGPBoolean inClosing = false);
b65c5d ¤   virtual ~StKeyServerBusy();
cdaf5a
c7a2d3 protected:
a8c62f ¤   CKeyServer *¤   mKeyServer;
b805a5 ¤   PGPBoolean¤ ¤   mClosing;
4b82f7 };
54af5a
22af5a
27af5a
15178d StKeyServerBusy::StKeyServerBusy(
123a34 ¤   CKeyServer *¤   inKeyServer,
cc3802 ¤   PGPBoolean¤ ¤   inClosing)
3d6cba ¤   : mKeyServer(inKeyServer), mClosing(inClosing)
b9bb36 {
cdbaa5 #if PGP_WIN32 || PGP_UNIX
a9ba43 ¤   PGPRMWOLockStartWriting(&sBusyLock);
0d398d ¤   PGPRMWOLockStartReading(&sCancelLock);
7d7454 #endif
0c67c5 ¤
e9149f ¤   if (mKeyServer->IsBusy() || (! mClosing && mKeyServer->IsCanceled()))·
21c7a1 ¤   {
69d040 ¤   ¤   // Close locks for error -wjb
ebbaa5 #if PGP_WIN32 || PGP_UNIX
3dc996 ¤   PGPRMWOLockStopReading(&sCancelLock);
157f7a ¤   PGPRMWOLockStopWriting(&sBusyLock);
7b7454 #endif
9d67d1 ¤   ¤   ThrowPGPError_(kPGPError_ServerInProgress);
ca0fa6 ·¤  } else {
7b687f ·¤  ·¤  mKeyServer->SetBusy(true);
ea7af9 ·¤  }
5d67c5 ¤
92baa5 #if PGP_WIN32 || PGP_UNIX
67c996 ¤   PGPRMWOLockStopReading(&sCancelLock);
6e7f7a ¤   PGPRMWOLockStopWriting(&sBusyLock);
997454 #endif
98efe6 }
93af5a
3baf5a
--d51c 000cd00f8fa40100241 Page 2 of pgpKeyServer.cpp
e0af5a
ac6e95 StKeyServerBusy::~StKeyServerBusy()
22bb36 {
3da7a1 ¤   if (mClosing) {
1dbaa5 #if PGP_WIN32 || PGP_UNIX
032a54 ¤   PGPRMWOLockStartWriting(&sCancelLock);
b67454 #endif
05af5a
72c017 ¤   ¤   mKeyServer->ResetCanceled();
92af5a
70baa5 #if PGP_WIN32 || PGP_UNIX
82da4f ¤   PGPRMWOLockStopWriting(&sCancelLock);
e47454 #endif
ae9371 ¤   }
b0af5a
4dbaa5 #if PGP_WIN32 || PGP_UNIX
94ba43 ¤   PGPRMWOLockStartWriting(&sBusyLock);
a67454 #endif
7faf5a
9e04c7 ¤   mKeyServer->SetBusy(false);¤
1faf5a
cabaa5 #if PGP_WIN32 || PGP_UNIX
037f7a ¤   PGPRMWOLockStopWriting(&sBusyLock);
2b7454 #endif
b4efe6 }
5daf5a
d2af5a
5faf5a
b366dd ¤   static PGPError
58d915 MapErrors(
d0f701 ¤   PGPError¤   inError)
40bb36 {
216a76 ¤   PGPError¤   result = inError;
8f67c5 ¤
9148f2 ¤   switch (inError) {
53449c ¤   ¤   case kPGPError_SocketsInProgress:
1d5b34 ¤   ¤   {
0142f0 ¤   ¤   ¤   result = kPGPError_ServerInProgress;
650fe4 ¤   ¤   }
7f2f68 ¤   ¤   break;
af9371 ¤   }
e867c5 ¤
c95d73 ¤   return result;
2aefe6 }
e2af5a
feaf5a
23af5a
d8c744 ¤   PGPError
3aaa1e PGPSetKeyServerIdleEventHandler(
18d261 ¤   PGPEventHandlerProcPtr¤ inCallback,
b3dbfa ¤   PGPUserValue¤   ¤   ¤   inUserData)
1abb36 {
b044e1 ¤   PGPError¤   result = kPGPError_NoErr;
6367c5 ¤
185168 ¤   try {
3d6787 ¤   ¤   CKeyServer::SetIdleEventHandler(inCallback, inUserData);
789371 ¤   }
81af5a
e18170 ¤   catch (PGPError exception) {
0a5f80 ¤   ¤   result = MapErrors(exception);
939371 ¤   }
57af5a
e5e1fa #if ! PGP_WIN32
7de0a3 ¤   catch (...) {
df414a ¤   ¤   result = kPGPError_UnknownError;
e99371 ¤   }
3e7454 #endif
411b52 ¤   ¤
0d5d73 ¤   return result;
f3efe6 }
d7af5a
cdaf5a
--5fcf 000650f16d540100241 Page 3 of pgpKeyServer.cpp
e0af5a
01c744 ¤   PGPError
8f36c0 PGPGetKeyServerIdleEventHandler(
f5286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
f870d3 ¤   PGPUserValue *¤ ¤   ¤   ¤   outUserData)
bfbb36 {
a544e1 ¤   PGPError¤   result = kPGPError_NoErr;
8a67c5 ¤
695168 ¤   try {
383abc ¤   ¤   CKeyServer::GetIdleEventHandler(outCallback, outUserData);
449371 ¤   }
f2af5a
f68170 ¤   catch (PGPError exception) {
475f80 ¤   ¤   result = MapErrors(exception);
1e9371 ¤   }
1067c5 ¤
f7e1fa #if ! PGP_WIN32
3ee0a3 ¤   catch (...) {
ea414a ¤   ¤   result = kPGPError_UnknownError;
8b9371 ¤   }
9a7454 #endif
231b52 ¤   ¤
3d5d73 ¤   return result;
c2efe6 }
09af5a
56af5a
4aaf5a
2aaf5a
afc744 ¤   PGPError
d088e1 PGPKeyServerCreateThreadStorage(
51f823 ¤   PGPKeyServerThreadStorageRef *¤ outPreviousStorage)
9bbb36 {
d28e12 ¤   PGPError¤   err = kPGPError_NoErr;
b867c5 ¤
1d5168 ¤   try {
1ee2d3 ¤   ¤   if (outPreviousStorage == NULL) {
43fb36 ¤   ¤   ¤   ThrowPGPError_(kPGPError_BadParams);
ac0fe4 ¤   ¤   }
24fc9f ¤   ¤   *outPreviousStorage = kInvalidPGPKeyServerThreadStorageRef;
66ae30 ¤   ¤   ¤   ¤   ¤
3180bb ¤   ¤   CKeyServer::CreateThreadStorage(
807216 ¤   ¤   ¤   ¤   ¤   (SThreadContext **) outPreviousStorage);
a99371 ¤   }
5867c5 ¤
b38170 ¤   catch (PGPError exception) {
3d9835 ¤   ¤   err = MapErrors(exception);
4c9371 ¤   }
d467c5 ¤
aee1fa #if ! PGP_WIN32
2ae0a3 ¤   catch (...) {
efb72f ¤   ¤   err = kPGPError_UnknownError;
8f9371 ¤   }
fc7454 #endif
15af5a
1e5ea8 ¤   return err;
85efe6 }
2caf5a
20af5a
f5af5a
7ec744 ¤   PGPError
57460f PGPKeyServerDisposeThreadStorage(
75efea ¤   PGPKeyServerThreadStorageRef¤   inPreviousStorage)
a5bb36 {
548e12 ¤   PGPError¤   err = kPGPError_NoErr;
5867c5 ¤
415168 ¤   try {
6fbbd8 ¤   ¤   CKeyServer::DisposeThreadStorage(
26ae79 ¤   ¤   ¤   ¤   ¤   (SThreadContext *) inPreviousStorage);
689371 ¤   }
2c67c5 ¤
d48170 ¤   catch (PGPError exception) {
659835 ¤   ¤   err = MapErrors(exception);
--f976 0006989a12040100241 Page 4 of pgpKeyServer.cpp
a19371 ¤   }
9967c5 ¤
56e1fa #if ! PGP_WIN32
e7e0a3 ¤   catch (...) {
16b72f ¤   ¤   err = kPGPError_UnknownError;
d39371 ¤   }
447454 #endif
b5af5a
4f5ea8 ¤   return err;
53efe6 }
9faf5a
7baf5a
0ac744 ¤   PGPError
3dbbfd PGPKeyServerInit()
90bb36 {
8044e1 ¤   PGPError¤   result = kPGPError_NoErr;
8faf5a
b0afb9 #if PGP_WIN32
3ff24f ¤   EnterCriticalSection(&gKeyServerInitMutex);
bd7454 #endif
bcaf5a
0a0824 ¤   if (sNumberOfInits == 0) {
05fd2a ¤   ¤   try {
814006 ¤   ¤   ¤   CKeyServer::Initialize();
0d0fe4 ¤   ¤   }
a0af5a
34bc18 ¤   ¤   catch (PGPError exception) {
d351cc ¤   ¤   ¤   result = MapErrors(exception);
520fe4 ¤   ¤   }
711b52 ¤   ¤
33da39 ¤   ¤   catch (...) {
f847f2 ¤   ¤   ¤   result = kPGPError_UnknownError;
f7af5a
1eafb9 #if PGP_WIN32
9795b9 ¤   ¤   LeaveCriticalSection(&gKeyServerInitMutex);
65a33a ¤   ¤   throw;
477454 #endif
b40fe4 ¤   ¤   }
f2af5a
76baa5 #if PGP_WIN32 || PGP_UNIX
557568 ¤   ¤   if (IsntPGPError(result)) {
728709 ¤   ¤   ¤   InitializePGPRMWOLock(&sBusyLock);
137b24 ¤   ¤   ¤   InitializePGPRMWOLock(&sCancelLock);
940fe4 ¤   ¤   }
537454 #endif
edaf5a
089371 ¤   }
e3fe94 ¤   if (IsntPGPError(result)) {
5d35c2 ¤   ¤   sNumberOfInits++;
319371 ¤   }
77af5a
05afb9 #if PGP_WIN32
e503f8 ¤   LeaveCriticalSection(&gKeyServerInitMutex);
557454 #endif
6867c5 ¤
6e5d73 ¤   return result;
33efe6 }
0daf5a
c4af5a
8baf5a
d121ab ¤   PGPError·
ac7902 PGPKeyServerCleanup()
adbb36 {
cd44e1 ¤   PGPError¤   result = kPGPError_NoErr;
9567c5 ¤
e7afb9 #if PGP_WIN32
39f24f ¤   EnterCriticalSection(&gKeyServerInitMutex);
d87454 #endif
87af5a
646f34 ¤   sNumberOfInits--;
9e0824 ¤   if (sNumberOfInits == 0) {
69fd2a ¤   ¤   try {
--ec65 0001f25f47740100241 Page 5 of pgpKeyServer.cpp
5f4ecf ¤   ¤   ¤   CKeyServer::Cleanup();
4e0fe4 ¤   ¤   }
8aaf5a
c0bc18 ¤   ¤   catch (PGPError exception) {
4151cc ¤   ¤   ¤   result = MapErrors(exception);
7d0fe4 ¤   ¤   }
a91b52 ¤   ¤
45da39 ¤   ¤   catch (...) {
9447f2 ¤   ¤   ¤   result = kPGPError_UnknownError;
4caf5a
2bafb9 #if PGP_WIN32
cac015 ¤   ¤   ¤   LeaveCriticalSection(&gKeyServerInitMutex);
d74199 ¤   ¤   ¤   throw;
e87454 #endif
b90fe4 ¤   ¤   }
7e87c7 ¤   ¤   ¤
0dbaa5 #if PGP_WIN32 || PGP_UNIX
0f8711 ¤   ¤   DeletePGPRMWOLock(&sCancelLock);
02eabc ¤   ¤   DeletePGPRMWOLock(&sBusyLock);
ba7454 #endif
7a8df0 ¤   } else if (sNumberOfInits < 0) {
1a36f9 ¤   ¤   sNumberOfInits = 0;
089371 ¤   }
1867c5 ¤
f5afb9 #if PGP_WIN32
5a95b9 ¤   ¤   LeaveCriticalSection(&gKeyServerInitMutex);
2c7454 #endif
00af5a
275d73 ¤   return result;
c1efe6 }
7eaf5a
e4af5a
9eaf5a
85c744 ¤   PGPError
1165fa PGPNewKeyServerFromURL(
b0e2f0 ¤   PGPContextRef¤  ¤   ¤   inContext,·
611bda ¤   const char *¤   ¤   ¤   inURL,·
8b2ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
3e1f08 ¤   PGPKeyServerKeySpace¤   inKeySpace,
ee42cb ¤   PGPKeyServerRef *¤  ¤   outKeyServerRef)
53bb36 {
5461a7 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   result = kPGPError_NoErr;
9667c5 ¤
9e5168 ¤   try {
03977e ¤   ¤   // Validation
d441ae ¤   ¤   PGPValidatePtr(outKeyServerRef);
c6acd4 ¤   ¤   *outKeyServerRef = kInvalidPGPKeyServerRef;
541561 ¤   ¤   PGPValidateContext(inContext);
c0b7f9 ¤   ¤   PGPValidatePtr(inURL);
c0f8f7 ¤   ¤   PGPValidateParam((inAccessType >= kPGPKeyServerAccessType_Default) &&
17a1a9 ¤   ¤   ¤   (inAccessType <= kPGPKeyServerAccessType_Administrator));
ab7c0d ¤   ¤   PGPValidateParam((inKeySpace >= kPGPKeyServerKeySpace_Default) &&
20f7dc ¤   ¤   ¤   (inKeySpace <= kPGPKeyServerKeySpace_Pending));
df67c5 ¤
5709f3 ¤   ¤   *outKeyServerRef = (PGPKeyServerRef) CKeyServer::NewKeyServerFromURL(
5cad08 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inContext,
56fe8c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inURL,
b40735 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAccessType,
dc5984 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySpace);
c89371 ¤   }
7367c5 ¤
428170 ¤   catch (PGPError exception) {
285f80 ¤   ¤   result = MapErrors(exception);
fc9371 ¤   }
ddaf5a
425bd1 #if !PGP_WIN32
37e0a3 ¤   catch (...) {
51414a ¤   ¤   result = kPGPError_UnknownError;
159371 ¤   }
357454 #endif
1b67c5 ¤
1f5d73 ¤   return result;
--5c0a 0008b718c2e40100241 Page 6 of pgpKeyServer.cpp
7aefe6 }
46af5a
8eaf5a
79af5a
9ac744 ¤   PGPError
296dd8 PGPNewKeyServerFromHostAddress(
2cb8d1 ¤   PGPContextRef¤  ¤   ¤   inContext,
b5e0b5 ¤   PGPUInt32¤  ¤   ¤   ¤   inAddress,
b7dc01 ¤   PGPUInt16¤  ¤   ¤   ¤   inPort,
b00e3d ¤   PGPKeyServerType¤   ¤   inType,
212ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
661f08 ¤   PGPKeyServerKeySpace¤   inKeySpace,
de42cb ¤   PGPKeyServerRef *¤  ¤   outKeyServerRef)
15bb36 {
8f44e1 ¤   PGPError¤   result = kPGPError_NoErr;
4d67c5 ¤
795168 ¤   try {
4d977e ¤   ¤   // Validation
9841ae ¤   ¤   PGPValidatePtr(outKeyServerRef);
76acd4 ¤   ¤   *outKeyServerRef = kInvalidPGPKeyServerRef;
6d1561 ¤   ¤   PGPValidateContext(inContext);
8a7e9d ¤   ¤   PGPValidateParam((inType >= kPGPKeyServerType_LDAP) &&
b5932d ¤   ¤   ¤   (inType <= kPGPKeyServerType_HTTPS));
15f8f7 ¤   ¤   PGPValidateParam((inAccessType >= kPGPKeyServerAccessType_Default) &&
53a1a9 ¤   ¤   ¤   (inAccessType <= kPGPKeyServerAccessType_Administrator));
917c0d ¤   ¤   PGPValidateParam((inKeySpace >= kPGPKeyServerKeySpace_Default) &&
e0f7dc ¤   ¤   ¤   (inKeySpace <= kPGPKeyServerKeySpace_Pending));
d2af5a
557d75 ¤   ¤   *outKeyServerRef =
4cb85b ¤   ¤   ¤   (PGPKeyServerRef) CKeyServer::NewKeyServerFromHostAddress(
a8ad08 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inContext,
ec2c23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAddress,
b78d90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inPort,
37f4db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inType,
540735 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAccessType,
235984 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySpace);
069371 ¤   }
3567c5 ¤
428170 ¤   catch (PGPError exception) {
715f80 ¤   ¤   result = MapErrors(exception);
619371 ¤   }
2467c5 ¤
3b5bd1 #if !PGP_WIN32
00e0a3 ¤   catch (...) {
68414a ¤   ¤   result = kPGPError_UnknownError;
8c9371 ¤   }
fc7454 #endif
0b67c5 ¤
445d73 ¤   return result;
7cefe6 }
48af5a
b8af5a
73af5a
e5c744 ¤   PGPError
c54dd5 PGPNewKeyServerFromHostName(
40b8d1 ¤   PGPContextRef¤  ¤   ¤   inContext,
90529e ¤   const char *¤   ¤   ¤   inHostName,
d8dc01 ¤   PGPUInt16¤  ¤   ¤   ¤   inPort,
cf0e3d ¤   PGPKeyServerType¤   ¤   inType,
fd2ba5 ¤   PGPKeyServerAccessType¤ inAccessType,
b61f08 ¤   PGPKeyServerKeySpace¤   inKeySpace,
3742cb ¤   PGPKeyServerRef *¤  ¤   outKeyServerRef)
65bb36 {
d483e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
6267c5 ¤
e45168 ¤   try {
0a977e ¤   ¤   // Validation
8341ae ¤   ¤   PGPValidatePtr(outKeyServerRef);
46acd4 ¤   ¤   *outKeyServerRef = kInvalidPGPKeyServerRef;
8f1561 ¤   ¤   PGPValidateContext(inContext);
78ac8a ¤   ¤   PGPValidatePtr(inHostName);
8b7e9d ¤   ¤   PGPValidateParam((inType >= kPGPKeyServerType_LDAP) &&
--8169 00063eeca0c40100241 Page 7 of pgpKeyServer.cpp
48932d ¤   ¤   ¤   (inType <= kPGPKeyServerType_HTTPS));
0af8f7 ¤   ¤   PGPValidateParam((inAccessType >= kPGPKeyServerAccessType_Default) &&
e3a1a9 ¤   ¤   ¤   (inAccessType <= kPGPKeyServerAccessType_Administrator));
b07c0d ¤   ¤   PGPValidateParam((inKeySpace >= kPGPKeyServerKeySpace_Default) &&
cef7dc ¤   ¤   ¤   (inKeySpace <= kPGPKeyServerKeySpace_Pending));
1967c5 ¤
437d75 ¤   ¤   *outKeyServerRef =
59f0f2 ¤   ¤   ¤   ¤   (PGPKeyServerRef) CKeyServer::NewKeyServerFromHostName(
d7ad08 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inContext,
9e4572 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inHostName,
e98d90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inPort,
1bf4db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inType,
de0735 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inAccessType,
be5984 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeySpace);
0e9371 ¤   }
b867c5 ¤
168170 ¤   catch (PGPError exception) {
b85f80 ¤   ¤   result = MapErrors(exception);
f49371 ¤   }
eb67c5 ¤
fb5bd1 #if !PGP_WIN32
3ee0a3 ¤   catch (...) {
eb414a ¤   ¤   result = kPGPError_UnknownError;
159371 ¤   }
737454 #endif
6867c5 ¤
315d73 ¤   return result;
21efe6 }
a9af5a
60af5a
54af5a
8ac744 ¤   PGPError
64369d PGPFreeKeyServer(
7f995b ¤   PGPKeyServerRef¤inKeyServerRef)
afbb36 {
9483e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
c86bbd ¤   PGPBoolean¤ ¤   freed = false;
4867c5 ¤
245168 ¤   try {
fb977e ¤   ¤   // Validation
8d935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
3a67c5 ¤
85d87d ¤   ¤   if (((CKeyServer *) inKeyServerRef)->IsBusy()) {
0d327d ¤   ¤   ¤   ThrowPGPError_(kPGPError_ServerInProgress);
8dba37 ¤   ·¤  } else {
bc742f ¤   ·¤  ·¤  ((CKeyServer *) inKeyServerRef)->SetBusy(true);
7ee66c ¤   ·¤  }
1f81c8 ¤   ·¤
fea023 ¤   ·¤  try {
0fbc8e ¤   ·¤  ¤   freed = ((CKeyServer *) inKeyServerRef)->Free();
26e66c ¤   ·¤  }
2b81c8 ¤   ·¤
2c2aba ¤   ·¤  catch (...) {
27afb9 #if PGP_WIN32
a120aa ¤   ¤   ¤   if (! freed) {
0782f5 ¤   ¤   ¤   ¤   /* Server still refcounted. Clear busy flag */
b4178d ¤   ¤   ·¤  ·¤  ((CKeyServer *) inKeyServerRef)->SetBusy(false);
084a2e ¤   ¤   ·¤  }
d34199 ¤   ¤   ¤   throw;
3e7454 #endif
06e66c ¤   ·¤  }
d7af5a
c2c24b ¤   ¤   if (! freed) {
118217 ¤   ¤   ¤   /* Server still refcounted. Clear busy flag */
72cda4 ¤   ·¤  ·¤  ((CKeyServer *) inKeyServerRef)->SetBusy(false);
f7e66c ¤   ·¤  }
b19371 ¤   }
b067c5 ¤
988170 ¤   catch (PGPError exception) {
b65f80 ¤   ¤   result = MapErrors(exception);
e89371 ¤   }
63af5a
--1839 000b2add26440100241 Page 8 of pgpKeyServer.cpp
dd5bd1 #if !PGP_WIN32
9be0a3 ¤   catch (...) {
71414a ¤   ¤   result = kPGPError_UnknownError;
d09371 ¤   }
7a7454 #endif
9667c5 ¤
d15d73 ¤   return result;
cdefe6 }
75af5a
10af5a
4baf5a
d0c744 ¤   PGPError
ada035 PGPIncKeyServerRefCount(
92995b ¤   PGPKeyServerRef¤inKeyServerRef)
f0bb36 {
6f83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
ef67c5 ¤
115168 ¤   try {
23977e ¤   ¤   // Validation
dc935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
a267c5 ¤
2973be ¤   ¤   ((CKeyServer *) inKeyServerRef)->IncRefCount();
459371 ¤   }
ad67c5 ¤
728170 ¤   catch (PGPError exception) {
0e5f80 ¤   ¤   result = MapErrors(exception);
f89371 ¤   }
f667c5 ¤
4b5bd1 #if !PGP_WIN32
59e0a3 ¤   catch (...) {
60414a ¤   ¤   result = kPGPError_UnknownError;
b29371 ¤   }
ff7454 #endif
0b67c5 ¤
8d5d73 ¤   return result;
3defe6 }
f5af5a
4baf5a
00c744 ¤   PGPError
63452c PGPSetKeyServerEventHandler(
50b560 ¤   PGPKeyServerRef¤¤   ¤   inKeyServerRef,
dad261 ¤   PGPEventHandlerProcPtr¤ inCallback,
a4dbfa ¤   PGPUserValue¤   ¤   ¤   inUserData)
24bb36 {
4e83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
5967c5 ¤
a25168 ¤   try {
4f977e ¤   ¤   // Validation
15935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
b01b52 ¤   ¤
9b42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
b71b52 ¤   ¤
4bf7a9 ¤   ¤   ((CKeyServer *) inKeyServerRef)->SetEventHandler(¤  inCallback,
549c24 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inUserData);
6c9371 ¤   }
7967c5 ¤
218170 ¤   catch (PGPError exception) {
f65f80 ¤   ¤   result = MapErrors(exception);
a99371 ¤   }
8e67c5 ¤
db5bd1 #if !PGP_WIN32
d9e0a3 ¤   catch (...) {
5e414a ¤   ¤   result = kPGPError_UnknownError;
119371 ¤   }
487454 #endif
6767c5 ¤
ef5d73 ¤   return result;
66efe6 }
5aaf5a
7caf5a
f6af5a
b2c744 ¤   PGPError
--736f 000e8bf00e840100241 Page 9 of pgpKeyServer.cpp
dedd93 PGPGetKeyServerEventHandler(
dd327b ¤   PGPKeyServerRef¤¤   ¤   ¤   inKeyServerRef,
1d286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
6670d3 ¤   PGPUserValue *¤ ¤   ¤   ¤   outUserData)
61bb36 {
6383e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
8c67c5 ¤
e45168 ¤   try {
76977e ¤   ¤   // Validation
ebcce7 ¤   ¤   PGPValidatePtr(inKeyServerRef)
c94e24 ¤   ¤   PGPValidatePtr(outCallback)
d0fa75 ¤   ¤   *outCallback = NULL;
3df541 ¤   ¤   PGPValidatePtr(outUserData)
994104 ¤   ¤   *outUserData = NULL;
1f67c5 ¤
6042ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
6f1b52 ¤   ¤
0cd68a ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetEventHandler(¤  *outCallback,
8b03c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *outUserData);
899371 ¤   }
1567c5 ¤
258170 ¤   catch (PGPError exception) {
6f5f80 ¤   ¤   result = MapErrors(exception);
e39371 ¤   }
9567c5 ¤
e95bd1 #if !PGP_WIN32
9fe0a3 ¤   catch (...) {
0a414a ¤   ¤   result = kPGPError_UnknownError;
7a9371 ¤   }
687454 #endif
b667c5 ¤
ee5d73 ¤   return result;
f1efe6 }
a5af5a
2caf5a
44af5a
cbc744 ¤   PGPError
14b914 PGPKeyServerOpen(
070c83 ¤   PGPKeyServerRef¤¤   inKeyServerRef,
a7b014 ¤   PGPtlsSessionRef¤   inTLSSessionRef)
e0bb36 {
7b83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
b567c5 ¤
4c5168 ¤   try {
41977e ¤   ¤   // Validation
8b935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
ac4947 ¤   ¤   PGPValidateParam((inTLSSessionRef == kInvalidPGPtlsSessionRef)
b09b98 ¤   ¤   ¤   || PGPtlsSessionRefIsValid(inTLSSessionRef));
1a67c5 ¤
1242ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
0a1b52 ¤   ¤
54edc8 ¤   ¤   ((CKeyServer *) inKeyServerRef)->Open(inTLSSessionRef);
709371 ¤   }
fb67c5 ¤
b28170 ¤   catch (PGPError exception) {
f05f80 ¤   ¤   result = MapErrors(exception);
389371 ¤   }
2a67c5 ¤
a75bd1 #if !PGP_WIN32
e1e0a3 ¤   catch (...) {
0d414a ¤   ¤   result = kPGPError_UnknownError;
909371 ¤   }
517454 #endif
a367c5 ¤
1d5d73 ¤   return result;
5aefe6 }
d5af5a
8eaf5a
72af5a
21c744 ¤   PGPError
49d694 PGPKeyServerClose(
e8995b ¤   PGPKeyServerRef¤inKeyServerRef)
--9edf 000514b120340100241 Page 10 of pgpKeyServer.cpp
2cbb36 {
9283e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
1067c5 ¤
025168 ¤   try {
9a977e ¤   ¤   // Validation
1c935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
7b67c5 ¤
be081a ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef, true);
99af5a
b29b8b ¤   ¤   ((CKeyServer *) inKeyServerRef)->Close();
079371 ¤   }
2e67c5 ¤
1d8170 ¤   catch (PGPError exception) {
a75f80 ¤   ¤   result = MapErrors(exception);
ca9371 ¤   }
1d67c5 ¤
bf5bd1 #if !PGP_WIN32
08e0a3 ¤   catch (...) {
c6414a ¤   ¤   result = kPGPError_UnknownError;
0e9371 ¤   }
347454 #endif
f767c5 ¤
7e5d73 ¤   return result;
e6efe6 }
4daf5a
7caf5a
b1af5a
74c744 ¤   PGPError
c4bee5 PGPGetKeyServerTLSSession(
c50c83 ¤   PGPKeyServerRef¤¤   inKeyServerRef,
a63fc4 ¤   PGPtlsSessionRef *¤ outTLSSessionRef)
c2bb36 {
4b83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
3867c5 ¤
a15168 ¤   try {
6d977e ¤   ¤   // Validation
46b14d ¤   ¤   PGPValidatePtr(outTLSSessionRef);
e6e5ba ¤   ¤   *outTLSSessionRef = NULL;
0b935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
4867c5 ¤
9c42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
15af5a
e3de63 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetTLSSession(*outTLSSessionRef);
059371 ¤   }
9c67c5 ¤
708170 ¤   catch (PGPError exception) {
135f80 ¤   ¤   result = MapErrors(exception);
b49371 ¤   }
8067c5 ¤
eb5bd1 #if !PGP_WIN32
99e0a3 ¤   catch (...) {
8a414a ¤   ¤   result = kPGPError_UnknownError;
d39371 ¤   }
d67454 #endif
4767c5 ¤
065d73 ¤   return result;
afefe6 }
21af5a
f4af5a
eaaf5a
45c744 ¤   PGPError
c26e56 PGPGetKeyServerType(
940c83 ¤   PGPKeyServerRef¤¤   inKeyServerRef,
ce8e48 ¤   PGPKeyServerType *¤ outType)
b3bb36 {
db83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
0e67c5 ¤
5a5168 ¤   try {
48977e ¤   ¤   // Validation
3b2627 ¤   ¤   PGPValidatePtr(outType);
ad935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
5167c5 ¤
--3413 0002ea11c8740100241 Page 11 of pgpKeyServer.cpp
8342ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
c0af5a
829004 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetType(*outType);
c19371 ¤   }
3b67c5 ¤
3e8170 ¤   catch (PGPError exception) {
3d5f80 ¤   ¤   result = MapErrors(exception);
e69371 ¤   }
1567c5 ¤
a45bd1 #if !PGP_WIN32
45e0a3 ¤   catch (...) {
41414a ¤   ¤   result = kPGPError_UnknownError;
e89371 ¤   }
337454 #endif
3567c5 ¤
e85d73 ¤   return result;
5fefe6 }
cdaf5a
b4af5a
daaf5a
e7c744 ¤   PGPError
ff344b PGPGetKeyServerAccessType(
6c327b ¤   PGPKeyServerRef¤¤   ¤   ¤   inKeyServerRef,
3bd38f ¤   PGPKeyServerAccessType *¤   outAccessType)
03bb36 {
9483e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
8267c5 ¤
a15168 ¤   try {
bb977e ¤   ¤   // Validation
63382b ¤   ¤   PGPValidatePtr(outAccessType);
bf935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
1267c5 ¤
2d42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
10af5a
47d8f4 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetAccessType(*outAccessType);
449371 ¤   }
be67c5 ¤
cd8170 ¤   catch (PGPError exception) {
8d5f80 ¤   ¤   result = MapErrors(exception);
699371 ¤   }
9667c5 ¤
f55bd1 #if !PGP_WIN32
8fe0a3 ¤   catch (...) {
71414a ¤   ¤   result = kPGPError_UnknownError;
c29371 ¤   }
2c7454 #endif
9067c5 ¤
bb5d73 ¤   return result;
90efe6 }
5daf5a
f3af5a
06af5a
6ac744 ¤   PGPError
a82c7d PGPGetKeyServerKeySpace(
60b560 ¤   PGPKeyServerRef¤¤   ¤   inKeyServerRef,
5e3c36 ¤   PGPKeyServerKeySpace *¤ outKeySpace)
9fbb36 {
ca83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
5067c5 ¤
d45168 ¤   try {
9d977e ¤   ¤   // Validation
dc96f8 ¤   ¤   PGPValidatePtr(outKeySpace);
bb935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
0e67c5 ¤
3442ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
d7af5a
6d4f82 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetKeySpace(*outKeySpace);
dc9371 ¤   }
f167c5 ¤
a58170 ¤   catch (PGPError exception) {
585f80 ¤   ¤   result = MapErrors(exception);
2e9371 ¤   }
--ca6b 0005625ba9e40100241 Page 12 of pgpKeyServer.cpp
2a67c5 ¤
ce5bd1 #if !PGP_WIN32
28e0a3 ¤   catch (...) {
d3414a ¤   ¤   result = kPGPError_UnknownError;
db9371 ¤   }
ba7454 #endif
6967c5 ¤
4c5d73 ¤   return result;
50efe6 }
a5af5a
40af5a
16af5a
edc744 ¤   PGPError
cd171d PGPGetKeyServerPort(
c2e7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
3f84cf ¤   PGPUInt16 *¤¤   outPort)
d1bb36 {
b183e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
4c67c5 ¤
6a5168 ¤   try {
12977e ¤   ¤   // Validation
d4da89 ¤   ¤   PGPValidatePtr(outPort);
827ab9 ¤   ¤   *outPort = NULL;
75935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
8467c5 ¤
9c42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
c6af5a
8dfc68 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetPort(*outPort);
f29371 ¤   }
e467c5 ¤
378170 ¤   catch (PGPError exception) {
d15f80 ¤   ¤   result = MapErrors(exception);
e59371 ¤   }
0d67c5 ¤
e35bd1 #if !PGP_WIN32
f6e0a3 ¤   catch (...) {
38414a ¤   ¤   result = kPGPError_UnknownError;
9d9371 ¤   }
3d7454 #endif
4367c5 ¤
9f5d73 ¤   return result;
1eefe6 }
68af5a
96af5a
f9c744 ¤   PGPError
556e5c PGPGetKeyServerHostName(
5ae7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
98869a ¤   char **¤¤   ¤   outHostName)
d7bb36 {
ee83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
a567c5 ¤
ed5168 ¤   try {
12977e ¤   ¤   // Validation
4fa631 ¤   ¤   PGPValidatePtr(outHostName);
cd5a34 ¤   ¤   *outHostName = NULL;
da935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
db67c5 ¤
d742ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
acaf5a
d274cc ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetHostName(outHostName);
8d9371 ¤   }
8567c5 ¤
7a8170 ¤   catch (PGPError exception) {
cc5f80 ¤   ¤   result = MapErrors(exception);
a49371 ¤   }
4e67c5 ¤
ca5bd1 #if !PGP_WIN32
15e0a3 ¤   catch (...) {
17414a ¤   ¤   result = kPGPError_UnknownError;
d09371 ¤   }
777454 #endif
5667c5 ¤
--5749 0003442d0f140100241 Page 13 of pgpKeyServer.cpp
cf5d73 ¤   return result;
01efe6 }
3daf5a
90af5a
02af5a
e5c744 ¤   PGPError
6f71ed PGPGetKeyServerAddress(
91e7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
c06140 ¤   PGPUInt32 *¤¤   outAddress)
52bb36 {
2c83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
4467c5 ¤
f35168 ¤   try {
b4977e ¤   ¤   // Validation
441271 ¤   ¤   PGPValidatePtr(outAddress);
40362b ¤   ¤   *outAddress = NULL;
e2935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
3baf5a
0242ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
bbaf5a
f62867 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetAddress(*outAddress);
309371 ¤   }
ee67c5 ¤
b78170 ¤   catch (PGPError exception) {
cb5f80 ¤   ¤   result = MapErrors(exception);
c79371 ¤   }
0767c5 ¤
ce5bd1 #if !PGP_WIN32
d2e0a3 ¤   catch (...) {
66414a ¤   ¤   result = kPGPError_UnknownError;
ef9371 ¤   }
647454 #endif
5b67c5 ¤
ec5d73 ¤   return result;
3eefe6 }
33af5a
27af5a
04af5a
a8c744 ¤   PGPError
714057 PGPGetLastKeyServerErrorString(
efe7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
47e51d ¤   char **¤¤   ¤   outErrorString)
01bb36 {
9383e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
6167c5 ¤
1c5168 ¤   try {
ba977e ¤   ¤   // Validation
da0793 ¤   ¤   PGPValidatePtr(outErrorString);
68fe71 ¤   ¤   *outErrorString = NULL;
7a935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
c867c5 ¤
7842ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
a31b52 ¤   ¤
2e0bd5 ¤   ¤   ((CKeyServer *) inKeyServerRef)->GetErrorString(outErrorString);
409371 ¤   }
8f67c5 ¤
588170 ¤   catch (PGPError exception) {
be5f80 ¤   ¤   result = MapErrors(exception);
759371 ¤   }
7667c5 ¤
e45bd1 #if !PGP_WIN32
20e0a3 ¤   catch (...) {
2c414a ¤   ¤   result = kPGPError_UnknownError;
cf9371 ¤   }
5a7454 #endif
3967c5 ¤
e55d73 ¤   return result;
38efe6 }
d9af5a
7faf5a
eaaf5a
34c744 ¤   PGPError
--0d79 0006fcbfb3640100241 Page 14 of pgpKeyServer.cpp
3d81a7 PGPQueryKeyServer(
06f03e ¤   PGPKeyServerRef¤inKeyServerRef,·
e4411b ¤   PGPFilterRef¤   inFilterRef,·
1ce331 ¤   PGPKeySetRef *¤ outFoundKeys)
fcbb36 {
e883e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
1267c5 ¤
d35168 ¤   try {
73977e ¤   ¤   // Validation
881f91 ¤   ¤   PGPValidatePtr(outFoundKeys);
6b28d4 ¤   ¤   *outFoundKeys = NULL;
a1935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
5136c9 ¤   ¤   PGPValidateParam(PGPFilterRefIsValid(inFilterRef));
6f67c5 ¤
da42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
e61b52 ¤   ¤
77179d ¤   ¤   ((CKeyServer *) inKeyServerRef)->Query(¤inFilterRef,
824749 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outFoundKeys);
2d9371 ¤   }
da67c5 ¤
f48170 ¤   catch (PGPError exception) {
fa5f80 ¤   ¤   result = MapErrors(exception);
c49371 ¤   }
4767c5 ¤
bb5bd1 #if !PGP_WIN32
89e0a3 ¤   catch (...) {
9a414a ¤   ¤   result = kPGPError_UnknownError;
6b9371 ¤   }
057454 #endif
3367c5 ¤
395d73 ¤   return result;
ccefe6 }
bdaf5a
c1af5a
d9af5a
dfc744 ¤   PGPError
9bb379 PGPUploadToKeyServer(
6df03e ¤   PGPKeyServerRef¤inKeyServerRef,·
87c24a ¤   PGPKeySetRef¤   inKeysToUpload,·
eb6a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
55bb36 {
d783e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
0967c5 ¤
a45168 ¤   try {
40977e ¤   ¤   // Validation
04132f ¤   ¤   PGPValidatePtr(outKeysThatFailed);
19374a ¤   ¤   *outKeysThatFailed = NULL;
1a935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
793d4c ¤   ¤   PGPValidateParam(PGPKeySetRefIsValid(inKeysToUpload));
8d67c5 ¤
d142ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
601b52 ¤   ¤
44b8ff ¤   ¤   ((CKeyServer *) inKeyServerRef)->Upload(¤   kPGPPublicKeyOnly,
f4fa09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeysToUpload,
b8c881 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outKeysThatFailed);
659371 ¤   }
0967c5 ¤
eb8170 ¤   catch (PGPError exception) {
885f80 ¤   ¤   result = MapErrors(exception);
139371 ¤   }
5467c5 ¤
375bd1 #if !PGP_WIN32
3ae0a3 ¤   catch (...) {
1e414a ¤   ¤   result = kPGPError_UnknownError;
cb9371 ¤   }
fb7454 #endif
5967c5 ¤
445d73 ¤   return result;
53efe6 }
48af5a
08c744 ¤   PGPError
6f3b70 PGPUploadPrivateKeysToKeyServer(
--d3f3 0002827f11340100241 Page 15 of pgpKeyServer.cpp
ebf03e ¤   PGPKeyServerRef¤inKeyServerRef,·
a2c24a ¤   PGPKeySetRef¤   inKeysToUpload,·
816a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
88bb36 {
1583e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
a567c5 ¤
f95168 ¤   try {
64977e ¤   ¤   // Validation
17132f ¤   ¤   PGPValidatePtr(outKeysThatFailed);
d9374a ¤   ¤   *outKeysThatFailed = NULL;
82935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
8a3d4c ¤   ¤   PGPValidateParam(PGPKeySetRefIsValid(inKeysToUpload));
5c67c5 ¤
8842ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
0f1b52 ¤   ¤
fb80cd ¤   ¤   ((CKeyServer *) inKeyServerRef)->Upload(¤   kPGPPrivateKeyAllowed,
90fa09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inKeysToUpload,
22c881 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outKeysThatFailed);
299371 ¤   }
ca67c5 ¤
708170 ¤   catch (PGPError exception) {
da5f80 ¤   ¤   result = MapErrors(exception);
229371 ¤   }
1c67c5 ¤
735bd1 #if !PGP_WIN32
48e0a3 ¤   catch (...) {
99414a ¤   ¤   result = kPGPError_UnknownError;
959371 ¤   }
257454 #endif
4967c5 ¤
dc5d73 ¤   return result;
9fefe6 }
35af5a
8aaf5a
2eaf5a
34c744 ¤   PGPError
6ef05f PGPDeleteFromKeyServer(
41e7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
452ccf ¤   PGPKeySetRef¤   inKeysToDelete,
d26a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
7cbb36 {
6e83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
fa67c5 ¤
225168 ¤   try {
9d977e ¤   ¤   // Validation
f0132f ¤   ¤   PGPValidatePtr(outKeysThatFailed);
5c374a ¤   ¤   *outKeysThatFailed = NULL;
df935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
abfa91 ¤   ¤   PGPValidateParam(PGPKeySetRefIsValid(inKeysToDelete));
e667c5 ¤
c642ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
d11b52 ¤   ¤
98f2bc ¤   ¤   ((CKeyServer *) inKeyServerRef)->Delete(¤   inKeysToDelete,
efc881 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outKeysThatFailed);
c49371 ¤   }
5967c5 ¤
1d8170 ¤   catch (PGPError exception) {
3b5f80 ¤   ¤   result = MapErrors(exception);
109371 ¤   }
2367c5 ¤
955bd1 #if !PGP_WIN32
6ee0a3 ¤   catch (...) {
10414a ¤   ¤   result = kPGPError_UnknownError;
4f9371 ¤   }
457454 #endif
ac67c5 ¤
c05d73 ¤   return result;
3befe6 }
25af5a
d5af5a
70af5a
28c744 ¤   PGPError
--f39c 0000e00c83540100241 Page 16 of pgpKeyServer.cpp
1270f3 PGPDisableFromKeyServer(
67e7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
0d8d4e ¤   PGPKeySetRef¤   inKeysToDisable,
006a84 ¤   PGPKeySetRef *¤ outKeysThatFailed)
f4bb36 {
6f83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
fd67c5 ¤
235168 ¤   try {
af977e ¤   ¤   // Validation
03132f ¤   ¤   PGPValidatePtr(outKeysThatFailed);
19374a ¤   ¤   *outKeysThatFailed = NULL;
01935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
c96d45 ¤   ¤   PGPValidateParam(PGPKeySetRefIsValid(inKeysToDisable));
3267c5 ¤
5242ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
5a1b52 ¤   ¤
50f112 ¤   ¤   ((CKeyServer *) inKeyServerRef)->Disable(¤  inKeysToDisable,
a2c881 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outKeysThatFailed);
f79371 ¤   }
fb67c5 ¤
a88170 ¤   catch (PGPError exception) {
c95f80 ¤   ¤   result = MapErrors(exception);
bd9371 ¤   }
ea67c5 ¤
875bd1 #if !PGP_WIN32
78e0a3 ¤   catch (...) {
78414a ¤   ¤   result = kPGPError_UnknownError;
a69371 ¤   }
d47454 #endif
0e67c5 ¤
f75d73 ¤   return result;
28efe6 }
29af5a
97af5a
f0af5a
1ac744 ¤   PGPError
c90eaa PGPSendGroupsToServer(
89e7e3 ¤   PGPKeyServerRef¤inKeyServerRef,
28d83f ¤   PGPGroupSetRef¤ inGroupSetRef)
85bb36 {
9483e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
5967c5 ¤
9b5168 ¤   try {
d4977e ¤   ¤   // Validation
ff935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
c4608d ¤   ¤   PGPValidateParam(PGPGroupSetRefIsValid(inGroupSetRef));
e567c5 ¤
4442ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
ab1b52 ¤   ¤
a40715 ¤   ¤   ((CKeyServer *) inKeyServerRef)->SendGroups(inGroupSetRef);
159371 ¤   }
5467c5 ¤
c18170 ¤   catch (PGPError exception) {
8b5f80 ¤   ¤   result = MapErrors(exception);
859371 ¤   }
0c67c5 ¤
2b5bd1 #if !PGP_WIN32
08e0a3 ¤   catch (...) {
71414a ¤   ¤   result = kPGPError_UnknownError;
719371 ¤   }
e57454 #endif
c567c5 ¤
fa5d73 ¤   return result;
6eefe6 }
6394aa ¤   ¤   ¤   ¤   ¤   ¤
76c744 ¤   PGPError
7d13fb PGPRetrieveGroupsFromServer(
0d0c83 ¤   PGPKeyServerRef¤¤   inKeyServerRef,
66fe62 ¤   PGPGroupSetRef *¤   outGroupSetRef)
c7bb36 {
fb83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
0e67c5 ¤
--01fe 000fc98126240100241 Page 17 of pgpKeyServer.cpp
055168 ¤   try {
72977e ¤   ¤   // Validation
d6687b ¤   ¤   PGPValidatePtr(outGroupSetRef);
549675 ¤   ¤   *outGroupSetRef = NULL;
ce935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
ca67c5 ¤
5a42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
821b52 ¤   ¤
64d0c7 ¤   ¤   ((CKeyServer *) inKeyServerRef)->RetrieveGroups(outGroupSetRef);
a69371 ¤   }
3f67c5 ¤
7c8170 ¤   catch (PGPError exception) {
465f80 ¤   ¤   result = MapErrors(exception);
d79371 ¤   }
e567c5 ¤
ff5bd1 #if !PGP_WIN32
c6e0a3 ¤   catch (...) {
e5414a ¤   ¤   result = kPGPError_UnknownError;
f39371 ¤   }
af7454 #endif
1267c5 ¤
af5d73 ¤   return result;
b4efe6 }
40af5a
6daf5a
22af5a
edc744 ¤   PGPError
f8fd16 PGPNewServerMonitor(
5eb560 ¤   PGPKeyServerRef¤¤   ¤   inKeyServerRef,
e9bdc8 ¤   PGPKeyServerMonitor **¤ outMonitor)
0abb36 {
9b83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
9467c5 ¤
725168 ¤   try {
31977e ¤   ¤   // Validation
251ec1 ¤   ¤   PGPValidatePtr(outMonitor);
f08369 ¤   ¤   *outMonitor = NULL;
18935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
e167c5 ¤
fa42ab ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inKeyServerRef);
1e1b52 ¤   ¤
be8ef6 ¤   ¤   ((CKeyServer *) inKeyServerRef)->NewMonitor(outMonitor);
899371 ¤   }
2e67c5 ¤
8f8170 ¤   catch (PGPError exception) {
5c5f80 ¤   ¤   result = MapErrors(exception);
5d9371 ¤   }
2167c5 ¤
5c5bd1 #if !PGP_WIN32
48e0a3 ¤   catch (...) {
f6414a ¤   ¤   result = kPGPError_UnknownError;
969371 ¤   }
d67454 #endif
dd67c5 ¤
395d73 ¤   return result;
e1efe6 }
55af5a
2994aa ¤   ¤   ¤   ¤   ¤   ¤
3daf5a
5ac744 ¤   PGPError
03e328 PGPFreeServerMonitor(
9b1f3c ¤   PGPKeyServerMonitor *¤  inMonitor)
08bb36 {
ca83e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
a867c5 ¤
315168 ¤   try {
9b977e ¤   ¤   // Validation
88f56b ¤   ¤   PGPValidatePtr(inMonitor);
e6a52d ¤   ¤   PGPValidatePtr(inMonitor->keyServerRef);
c867c5 ¤
dd5fff ¤   ¤   StKeyServerBusy¤busyKeyServer((CKeyServer *) inMonitor->keyServerRef);
fc1b52 ¤   ¤
--2a62 0015a807d7e40100241 Page 18 of pgpKeyServer.cpp
7f6701 ¤   ¤   ((CKeyServer *) inMonitor->keyServerRef)->FreeMonitor(inMonitor);
639371 ¤   }
3167c5 ¤
378170 ¤   catch (PGPError exception) {
855f80 ¤   ¤   result = MapErrors(exception);
9d9371 ¤   }
1e67c5 ¤
1e5bd1 #if !PGP_WIN32
26e0a3 ¤   catch (...) {
49414a ¤   ¤   result = kPGPError_UnknownError;
5e9371 ¤   }
8f7454 #endif
9167c5 ¤
1f5d73 ¤   return result;
23efe6 }
03af5a
9baf5a
00af5a
15af5a
2dc744 ¤   PGPError
949a85 PGPCancelKeyServerCall(
64995b ¤   PGPKeyServerRef¤inKeyServerRef)
d2bb36 {
8e44e1 ¤   PGPError¤   result = kPGPError_NoErr;
d567c5 ¤
f05168 ¤   try {
dabaa5 #if PGP_WIN32 || PGP_UNIX
09bbcc ¤   ¤   PGPRMWOLockStartWriting(&sCancelLock);
5c7454 #endif
ebaf5a
91977e ¤   ¤   // Validation
fc935d ¤   ¤   PGPValidatePtr(inKeyServerRef);
d61b52 ¤   ¤
94c360 ¤   ¤   ((CKeyServer *) inKeyServerRef)->Cancel();
edaf5a
bebaa5 #if PGP_WIN32 || PGP_UNIX
22e38a ¤   ¤   PGPRMWOLockStopWriting(&sCancelLock);
5a7454 #endif
389371 ¤   }
9867c5 ¤
b88170 ¤   catch (PGPError exception) {
535f80 ¤   ¤   result = MapErrors(exception);
eb9371 ¤   }
e167c5 ¤
675bd1 #if !PGP_WIN32
74e0a3 ¤   catch (...) {
5f414a ¤   ¤   result = kPGPError_UnknownError;
d89371 ¤   }
f37454 #endif
0667c5 ¤
c75d73 ¤   return result;
5aefe6 }
--1173 001841c1e4640100242 Page 1 of Makefile.in
5ea601 #
cff06c # priv/networklib/pgpsockets/
c9a601 #
fbacaa # $Id: Makefile.in,v 1.1 1998/03/12 22:25:10 elowe Exp $
bca601 #
bfaf5a
6fc2c8 SUBDIRS=common
50b4a4 LIBDONE=common/DONE
3faf5a
a2211d all:: LIBDONE
84af5a
--b2e9 001cd71680540100243 Page 1 of Makefile.in
5ea601 #
a7b017 # priv/networklib/pgpsockets/unix/
1ba601 #
9a0496 # $Id: Makefile.in,v 1.3 1998/04/08 00:58:11 marcd Exp $
e2a601 #
64af5a
b14719 LOCALDEFINES=
e3af5a
cb95f2 OBJS= pgpSockets.o
9eaf5a
1c55db LIBDONE= DONE
eeaf5a
cdb7a3 all:: DONE
--a462 0004ac1763440100244 Page 1 of pgpSockets.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
2b0826 ¤   $Id: pgpSockets.c,v 1.18.10.1 1998/11/12 03:22:21 heller Exp $
7bf7f7 ____________________________________________________________________________*/
e0af5a
8cafb9 #if PGP_WIN32
3c7ef2 # include <windows.h>
de05f8 # include <winsock.h>
7f1905 # include "PGPsdkNetworkLibDLLMain.h"
56db21 #else
d419f8 # include <stdio.h>
f5bee3 # include <sys/types.h>
a908d3 # include <sys/socket.h>
030238 # include <netinet/in.h>
b8a42e # include <arpa/inet.h>
49cd1b # include <netdb.h>
2bae17 # include <errno.h>
83fa7b # include <unistd.h>
45531a # include <stdlib.h>
c67454 #endif
81af5a
49e2ff #include "pgpConfig.h"
d3e82c #include "pgpPubTypes.h"
9c0d08 #include "pgpMem.h"
499f63 #include "pgpEncode.h"
e72b46 #include "pgpBinaryTree.h"
0851b9 #include "pgpRMWOLock.h"
adaf5a
5f5519 #include "pgpSockets.h"
efaf5a
e6aea6 /* Unix specific things */
2b129a #if PGP_UNIX
51d596 # define FAR
756921 # define SOCKET_ERROR -1
53576f # define closesocket(x) close((x))
e3f266 # define ioctlsocket(a,b,c) ioctl((a),(b),(c))
546a89 typedef int¤¤   SOCKET;
875d1d #if PGP_UNIX_LINUX
9c4a9b int gethostname (char * name, size_t namelen);
c2db21 #else
b6d79b int gethostname (char * name, int namelen);
579ab3 #endif /* PGP_UNIX_LINUX */
e87454 #endif
88af5a
e96f2d /* Windows specific things */
0bafb9 #if PGP_WIN32
f77f23 ·static PGPInt32¤   ¤   sIdleEventHandlerIndex = 0;
ea3873 ·static PGPInt32¤   ¤   sIdleEventHandlerDataIndex = 0;
b34142 ·BOOL WINAPI SocketsBlockingHook();
8eb99c ·static PGPRMWOLock¤¤   sIdleEventHandlerLock;
837454 #endif
feaf5a
650338 PGPSocketAddressInternet kPGPAddressAny = {
d96f57 ¤   kPGPAddressFamilyInternet,
63432d ¤   0,
48c436 ¤   {{{kPGPInternetAddressAny}}},
b20634 ¤   {0,0,0,0,0,0,0,0}
a282f7 };
13071b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
041fd1 static PGPInt32¤¤   ¤   ¤   sNumberOfInits = 0;
9ef8aa static PGPMemoryMgrRef¤ ¤   sMemoryMgr = kInvalidPGPMemoryMgrRef;
22af5a
8dfcdb static PGPBinaryTreeRef¤¤   sErrorMap = kInvalidPGPBinaryTreeRef;
8bb407 static PGPBinaryTreeRef¤¤   sTLSMap = kInvalidPGPBinaryTreeRef;
edaf5a
537e28 static PGPRMWOLock¤ ¤   ¤   sTLSMapLock;
deaf5a
4a7350 void¤   ¤   InitErrorMap(void);
--9c49 0008ef32ce640100244 Page 2 of pgpSockets.c
1b46ce PGPError¤   MapPGPSocketsError(PGPError inErr);
465296 PGPInt32¤   PGPSocketsTLSReceive(void * inData, void * outBuffer,
7f58aa ¤   ¤   ¤   ¤   ¤   ·PGPInt32 inBufferSize);
e21d90 PGPInt32¤   PGPSocketsTLSSend(void * inData, const void * inBuffer,
fe116f ¤   ¤   ¤   ¤   ··PGPInt32 inBufferLength);
9aaf5a
9faf5a
1ec77d PGPError
0a99ab PGPSocketsInit()
48bb36 {
448e12 ¤   PGPError¤   err = kPGPError_NoErr;
89af5a
daafb9 #if PGP_WIN32
05df68 ¤   WSADATA¤wsaData;
3234e0 ¤   EnterCriticalSection(&gSocketsInitMutex);
7a7454 #endif
7667c5 ¤
520824 ¤   if (sNumberOfInits == 0) {
eab250 #if PGP_WIN32¤
c39e11 ¤   ¤   InitializePGPRMWOLock(&sIdleEventHandlerLock);
748e60 #endif¤
fd9c45 ¤   ¤   InitializePGPRMWOLock(&sTLSMapLock);
f7fd53 ¤   ¤   err = PGPNewMemoryMgr(0, &sMemoryMgr);
3c413e ¤   ¤   if (err != kPGPError_NoErr) {
4c1dc4 ¤   ¤   ¤   goto done;
be0fe4 ¤   ¤   }
3b856d ¤   ¤   err = PGPNewBinaryTree(sMemoryMgr, &sErrorMap);
99413e ¤   ¤   if (err != kPGPError_NoErr) {
031dc4 ¤   ¤   ¤   goto done;
4f0fe4 ¤   ¤   }
c2ec2b ¤   ¤   err = PGPNewBinaryTree(sMemoryMgr, &sTLSMap);
de413e ¤   ¤   if (err != kPGPError_NoErr) {
471dc4 ¤   ¤   ¤   goto done;
340fe4 ¤   ¤   }
8b67c5 ¤
f1b250 #if PGP_WIN32¤
f1f00f ¤   ¤   (void) PGPThreadKeyCreate(&sIdleEventHandlerIndex, NULL);
1e784a ¤   ¤   if (PGPThreadSetSpecific(sIdleEventHandlerIndex, NULL)) {
a28bc1 ¤   ¤   ¤   err = kPGPError_UnknownError;
4d1dc4 ¤   ¤   ¤   goto done;
140fe4 ¤   ¤   }
e9487e ¤   ¤   (void) PGPThreadKeyCreate(&sIdleEventHandlerDataIndex, NULL);
3bc55b ¤   ¤   if (PGPThreadSetSpecific(sIdleEventHandlerDataIndex, NULL)) {
8a8bc1 ¤   ¤   ¤   err = kPGPError_UnknownError;
491dc4 ¤   ¤   ¤   goto done;
d90fe4 ¤   ¤   }
d97454 #endif
8267c5 ¤
242b5e ¤   InitErrorMap();
4967c5 ¤
fdb250 #if PGP_WIN32¤
9c4d06 ¤   err = WSAStartup(MAKEWORD(1,1), &wsaData);
101e63 ¤   if (err != 0) {
ef8a0b ¤   ¤   err = MapPGPSocketsError(err);
5a262d ¤   ¤   goto done;
839371 ¤   }
457454 #endif
da67c5 ¤
0b9371 ¤   }
bdf277 ¤   sNumberOfInits++;
e967c5 ¤
1224c3 ·done:
c4afb9 #if PGP_WIN32
a9e268 ¤   LeaveCriticalSection(&gSocketsInitMutex);
8a8e60 #endif¤
e15ea8 ¤   return err;
bdefe6 }
43af5a
92af5a
6baf5a
36314a void
8e3cbb PGPSocketsCleanup()
--9d6c 000d2e167a340100244 Page 3 of pgpSockets.c
2cbb36 {
0cafb9 #if PGP_WIN32
6f34e0 ¤   EnterCriticalSection(&gSocketsInitMutex);
d07454 #endif
4167c5 ¤
dd6f34 ¤   sNumberOfInits--;
630824 ¤   if (sNumberOfInits == 0) {
5eafb9 #if PGP_WIN32
50774d ¤   ¤   WSACleanup();
198e60 #endif¤
96fafc ¤   ¤   if (PGPBinaryTreeRefIsValid(sTLSMap)) {
01d682 ¤   ¤   ¤   PGPRMWOLockStartWriting(&sTLSMapLock);
cc612c ¤   ¤   ¤   PGPDisposeBinaryTree(sTLSMap);
5ec9c0 ¤   ¤   ¤   sTLSMap = kInvalidPGPBinaryTreeRef;
601948 ¤   ¤   ¤   PGPRMWOLockStopWriting(&sTLSMapLock);
c40fe4 ¤   ¤   }
67d6e4 ¤   ¤   if (PGPBinaryTreeRefIsValid(sErrorMap)) {
6e9788 ¤   ¤   ¤   PGPDisposeBinaryTree(sErrorMap);
57d31b ¤   ¤   ¤   sErrorMap = kInvalidPGPBinaryTreeRef;
ec0fe4 ¤   ¤   }
e374d4 ¤   ¤   if (PGPMemoryMgrRefIsValid(sMemoryMgr)) {
d754f4 ¤   ¤   ¤   PGPFreeMemoryMgr(sMemoryMgr);
2461f2 ¤   ¤   ¤   sMemoryMgr = kInvalidPGPMemoryMgrRef;
f60fe4 ¤   ¤   }
3f67c5 ¤
dab250 #if PGP_WIN32¤
04ac75 ¤   ¤   PGPThreadKeyDelete(sIdleEventHandlerIndex);
d5f628 ¤   ¤   sIdleEventHandlerIndex = 0;
0ee234 ¤   ¤   PGPThreadKeyDelete(sIdleEventHandlerDataIndex);
726894 ¤   ¤   sIdleEventHandlerDataIndex = 0;
fd1140 ¤   ¤   DeletePGPRMWOLock(&sIdleEventHandlerLock);
997454 #endif
7167c5 ¤
3a32ed ¤   ¤   DeletePGPRMWOLock(&sTLSMapLock);
ec8df0 ¤   } else if (sNumberOfInits < 0) {
9036f9 ¤   ¤   sNumberOfInits = 0;
e19371 ¤   }
dcaf5a
6eafb9 #if PGP_WIN32
62e268 ¤   LeaveCriticalSection(&gSocketsInitMutex);
018e60 #endif¤
ceefe6 }
49af5a
83af5a
81af5a
9d4e47 PGPSocketRef
c82b03 PGPOpenSocket(
2841bc ¤   PGPInt32¤   inAddressFamily,
a58f2e ¤   PGPInt32¤   inSocketType,
289044 ¤   PGPInt32¤   inSocketProtocol)
8abb36 {
ea30bd ¤   return (PGPSocketRef) socket(inAddressFamily, inSocketType,
29bf58 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·inSocketProtocol);
4fefe6 }
37af5a
60af5a
2baf5a
9aaf5a
101e45 PGPInt32
88eec7 PGPCloseSocket(
7d4bee ¤   PGPSocketRef¤   inSocketRef)
31bb36 {
5f011b ¤   PGPUserValue¤   unused;
cf67c5 ¤
559fa8 ¤   PGPRMWOLockStartWriting(&sTLSMapLock);
097abb ¤   PGPDisposeNode(sTLSMap, (PGPInt32) inSocketRef, &unused);
d06fb3 ¤   PGPRMWOLockStopWriting(&sTLSMapLock);
3edf1b ¤   return closesocket((SOCKET) inSocketRef);
12efe6 }
81af5a
ecaf5a
d2af5a
--a47e 000739a076140100244 Page 4 of pgpSockets.c
b31e45 PGPInt32
9ec0c2 PGPBindSocket(
8a8b44 ¤   PGPSocketRef¤   ¤   ¤   ¤   inSocketRef,
6d7351 ¤   const PGPSocketAddress *¤   inAddress,
f8e238 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   inAddressLength)
dbbb36 {
99ac4e ¤   return bind((SOCKET) inSocketRef,
66d0e6 ¤   ¤   ¤   ¤   (struct sockaddr *) inAddress,
14bf28 ¤   ¤   ¤   ¤   inAddressLength);
ceefe6 }
8faf5a
44af5a
7baf5a
771e45 PGPInt32
23f8cc PGPConnect(
548b44 ¤   PGPSocketRef¤   ¤   ¤   ¤   inSocketRef,
fae8b3 ¤   const PGPSocketAddress *¤   inServerAddress,
11e238 ¤   PGPInt32¤   ¤   ¤   ¤   ¤   inAddressLength)
fbbb36 {
9bf79f ¤   return connect((SOCKET) inSocketRef,
081831 ¤   ¤   ¤   ¤   ···(struct sockaddr *) inServerAddress,
a75405 ¤   ¤   ¤   ¤   ···inAddressLength);
3befe6 }
9faf5a
80af5a
24af5a
ad1e45 PGPInt32
764a1f PGPSend(
113556 ¤   PGPSocketRef¤   inSocketRef,
854f2f ¤   const void *¤   inBuffer,
bdc775 ¤   PGPInt32¤   ¤   inBufferLength,
1ee388 ¤   PGPInt32¤   ¤   inFlags)
94bb36 {
90efa5 ¤   PGPInt32¤   ¤   ¤   result = kPGPSockets_Error;
02a715 ¤   PGPError¤   ¤   ¤   pgpError;
ed70d5 ¤   PGPtlsSessionRef¤   tlsSession;
fb67c5 ¤
778c71 ¤   PGPRMWOLockStartReading(&sTLSMapLock);
b8845d ¤   pgpError = PGPFindNode(sTLSMap, (PGPInt32) inSocketRef,
d41623 ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPUserValue*)&tlsSession);
4b7c6a ¤   PGPRMWOLockStopReading(&sTLSMapLock);
9f5475 ¤   if (IsntPGPError(pgpError)) {
1b4d6d ¤   ¤   pgpError = PGPtlsSend(tlsSession,
f14ee3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··inBuffer,
135d02 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··inBufferLength);
00bb06 ¤   ¤   if (IsntPGPError(pgpError)) {
98fa8e ¤   ¤   ¤   result = inBufferLength;
1ab81b ¤   ¤   } else if (pgpError != kPGPError_TLSUnexpectedClose) {
4dbd3e #if PGP_WIN32¤  ¤
f920a9 ¤   ¤   ¤   WSASetLastError(pgpError);
bbdb21 #else
7fc284 ¤   ¤   ¤   errno = pgpError;
ca1fa7 #endif¤ ¤
2d0fe4 ¤   ¤   }
32f037 ¤   } else {
1160d4 ¤   ¤   result = send((SOCKET) inSocketRef,
bc80ca ¤   ¤   ¤   ¤   ¤   ··(char*)inBuffer,
baa43c ¤   ¤   ¤   ¤   ¤   ··inBufferLength,
b30f16 ¤   ¤   ¤   ¤   ¤   ··inFlags);
c19371 ¤   }
4867c5 ¤
285d73 ¤   return result;
b9efe6 }
cdaf5a
66af5a
56af5a
ca1e45 PGPInt32
b96c86 PGPWrite(
d43556 ¤   PGPSocketRef¤   inSocketRef,
214f2f ¤   const void *¤   inBuffer,
78b9cd ¤   PGPInt32¤   ¤   inBufferLength)
73bb36 {
--3da6 00001d6c61940100244 Page 5 of pgpSockets.c
fd54f9 ¤   return PGPSend(inSocketRef, inBuffer, inBufferLength, kPGPSendFlagNone);
4defe6 }
f6af5a
84af5a
6aaf5a
ff1e45 PGPInt32
aa482f PGPSendTo(
a782aa ¤   PGPSocketRef¤   ¤   inSocketRef,
0d6914 ¤   const void *¤   ¤   inBuffer,
9839eb ¤   PGPInt32¤   ¤   ¤   inBufferLength,
133c1f ¤   PGPInt32¤   ¤   ¤   inFlags,
a11abb ¤   PGPSocketAddress *¤ inAddress,
2ef7fc ¤   PGPInt32¤   ¤   ¤   inAddressLength)
37bb36 {
128a57 ¤   return sendto((SOCKET) inSocketRef,
8c3ac8 ¤   ¤   ¤   ¤   ··(char *) inBuffer,
c34b4f ¤   ¤   ¤   ¤   ··inBufferLength,
33246f ¤   ¤   ¤   ¤   ··inFlags,
2c8a57 ¤   ¤   ¤   ¤   ··(struct sockaddr *) inAddress,
baa53e ¤   ¤   ¤   ¤   ··inAddressLength);
96efe6 }
e6af5a
a6af5a
f7af5a
511e45 PGPInt32
ce6a93 PGPReceive(
b33556 ¤   PGPSocketRef¤   inSocketRef,
a7398a ¤   void *¤ ¤   ¤   outBuffer,
631da1 ¤   PGPInt32¤   ¤   inBufferSize,
30e388 ¤   PGPInt32¤   ¤   inFlags)
6fbb36 {
c2efa5 ¤   PGPInt32¤   ¤   ¤   result = kPGPSockets_Error;
cba715 ¤   PGPError¤   ¤   ¤   pgpError;
9e70d5 ¤   PGPtlsSessionRef¤   tlsSession;
f75f7b ¤   PGPSize¤¤   ¤   ¤   bufferSize = inBufferSize;
bc67c5 ¤
358c71 ¤   PGPRMWOLockStartReading(&sTLSMapLock);
df845d ¤   pgpError = PGPFindNode(sTLSMap, (PGPInt32) inSocketRef,
8e3895 ¤   ¤   ¤   ¤   ¤   ¤   ···(PGPUserValue*) &tlsSession);
f07c6a ¤   PGPRMWOLockStopReading(&sTLSMapLock);
575475 ¤   if (IsntPGPError(pgpError)) {
4de38d ¤   ¤   pgpError = PGPtlsReceive(tlsSession,
174437 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·outBuffer,
835948 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·&bufferSize);
eabb06 ¤   ¤   if (IsntPGPError(pgpError)) {
71f188 ¤   ¤   ¤   result = bufferSize;
9eb81b ¤   ¤   } else if (pgpError != kPGPError_TLSUnexpectedClose) {
2bbd3e #if PGP_WIN32¤  ¤
a120a9 ¤   ¤   ¤   WSASetLastError(pgpError);
2ddb21 #else
18c284 ¤   ¤   ¤   errno = pgpError;
ad1fa7 #endif¤ ¤
7e0fe4 ¤   ¤   }
f5f037 ¤   } else {
0e2e4e ¤   ¤   result = recv((SOCKET) inSocketRef,
734e6b ¤   ¤   ¤   ¤   ¤   ··(char *) outBuffer,
fd113c ¤   ¤   ¤   ¤   ¤   ··inBufferSize,
0f0f16 ¤   ¤   ¤   ¤   ¤   ··inFlags);
0b9371 ¤   }
dd67c5 ¤
545d73 ¤   return result;
0befe6 }
e9af5a
66af5a
9daf5a
4a1e45 PGPInt32
08fccd PGPRead(
e73556 ¤   PGPSocketRef¤   inSocketRef,
d5398a ¤   void *¤ ¤   ¤   outBuffer,
216319 ¤   PGPInt32¤   ¤   inBufferSize)
d9bb36 {
01d837 ¤   return PGPReceive(inSocketRef,
--fdf0 0003bc8d7b640100244 Page 6 of pgpSockets.c
b4d5a5 ¤   ¤   ¤   ¤   ¤   ··outBuffer,
f8113c ¤   ¤   ¤   ¤   ¤   ··inBufferSize,
5ca8ff ¤   ¤   ¤   ¤   ¤   ··kPGPReceiveFlagNone);
b8efe6 }
ecaf5a
16af5a
a6af5a
5a1e45 PGPInt32
7bdf73 PGPReceiveFrom(
0682aa ¤   PGPSocketRef¤   ¤   inSocketRef,
55dc36 ¤   void *¤ ¤   ¤   ¤   outBuffer,
c0a94a ¤   PGPInt32¤   ¤   ¤   inBufferSize,
f23c1f ¤   PGPInt32¤   ¤   ¤   inFlags,
17758e ¤   PGPSocketAddress *¤ outAddress,
741136 ¤   PGPInt32 *¤ ¤   ¤   ioAddressLength)
1ebb36 {
058bd9 ¤   return recvfrom(¤   (SOCKET) inSocketRef,
5d412c ¤   ¤   ¤   ¤   ¤   ¤   (char *) outBuffer,
5f5999 ¤   ¤   ¤   ¤   ¤   ¤   inBufferSize,
830d51 ¤   ¤   ¤   ¤   ¤   ¤   inFlags,
5d3fc9 ¤   ¤   ¤   ¤   ¤   ¤   (struct sockaddr *) outAddress,
967cba ¤   ¤   ¤   ¤   ¤   ¤   ioAddressLength);
86efe6 }
7daf5a
0faf5a
b0af5a
d81e45 PGPInt32
d3dac5 PGPListen(
903556 ¤   PGPSocketRef¤   inSocketRef,
c1bb58 ¤   PGPInt32¤   ¤   inMaxBacklog)
d3bb36 {
7e8056 ¤   return listen((SOCKET) inSocketRef, inMaxBacklog);
ffefe6 }
efaf5a
cfaf5a
41af5a
8c4e47 PGPSocketRef
742fe2 PGPAccept(
cc82aa ¤   PGPSocketRef¤   ¤   inSocketRef,
dd758e ¤   PGPSocketAddress *¤ outAddress,
ac1136 ¤   PGPInt32 *¤ ¤   ¤   ioAddressLength)
1bbb36 {
e7b9d9 ¤   return (PGPSocketRef) accept(¤  (SOCKET) inSocketRef,
afefb1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (struct sockaddr FAR *) outAddress,
65a440 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ioAddressLength);
e0efe6 }
13af5a
cbaf5a
c11e45 PGPInt32
12fcdd PGPSelect(
adf19d ¤   PGPInt32¤   ¤   ¤   inNumSetCount,
eae3c0 ¤   PGPSocketSet *¤ ¤   ioReadSet,
28a6b6 ¤   PGPSocketSet *¤ ¤   ioWriteSet,
9b4d94 ¤   PGPSocketSet *¤ ¤   ioErrorSet,
e791d1 ¤   const PGPSocketsTimeValue *¤inTimeout)
12bb36 {
083255 ¤   return select(inNumSetCount,
c134ab ¤   ¤   ¤   ¤   ··(fd_set *) ioReadSet,
507bb4 ¤   ¤   ¤   ¤   ··(fd_set *) ioWriteSet,
309096 ¤   ¤   ¤   ¤   ··(fd_set *) ioErrorSet,
e1bff8 ¤   ¤   ¤   ¤   ··(struct timeval *) inTimeout);
b8efe6 }
90af5a
86af5a
caafb9 #if PGP_WIN32
f51e45 PGPInt32
e4799b __PGPSocketsIsSet(
973556 ¤   PGPSocketRef¤   inSocketRef,
f3f48c ¤   PGPSocketSet *¤ inSocketSet)
fabb36 {
2e016a ¤   PGPInt16 ¤  result = 0;
3b6338 ¤   PGPUInt16¤  i;
--ce50 000664ea2bf40100244 Page 7 of pgpSockets.c
2a67c5 ¤
1a76ec ¤   for (i = 0; i < inSocketSet->fd_count; i++) {
840877 ¤   ¤   if (inSocketSet->fd_array[i] == (SOCKET) inSocketRef) {
556a01 ¤   ¤   ¤   result = 1;
29cdcb ¤   ¤   ¤   break;
f80fe4 ¤   ¤   }
4a9371 ¤   }
b567c5 ¤
995d73 ¤   return result;
87efe6 }
da7454 #endif
c8af5a
56af5a
0f0048 PGPHostEntry *
d4ed0c PGPGetHostByName(
feb3d6 ¤   const char * inName)
1dbb36 {
69ebb3 ¤   struct hostent *hjet = 0;
cd67c5 ¤
1e5239 ¤   hjet = gethostbyname(inName);
0867c5 ¤
a7e69a ¤   return (PGPHostEntry *) hjet;
f3efe6 }
68af5a
67af5a
82af5a
620048 PGPHostEntry *
f4d136 PGPGetHostByAddress(
857ba7 ¤   const char *¤   inAddress,
9081f2 ¤   PGPInt32¤   ¤   inLength,
e229e0 ¤   PGPInt32¤   ¤   inType)
dfbb36 {
57c1bd ¤   return (PGPHostEntry *) gethostbyaddr(inAddress, inLength, inType);
01efe6 }
c1af5a
28af5a
05af5a
8e1e45 PGPInt32
75703c PGPGetHostName(
f33f28 ¤   char *¤ ¤   outName,
9cfb28 ¤   PGPInt32¤   inNameLength)
6cbb36 {
6525b8 ¤   return gethostname(outName, inNameLength);
e1efe6 }
27af5a
0daf5a
b2af5a
1f5428 PGPProtocolEntry *
0f956b PGPGetProtocolByName(
68c386 ¤   const char *¤   inName)
5dbb36 {
3e93f9 ¤   return (PGPProtocolEntry *) getprotobyname(inName);
4cefe6 }
68af5a
f8af5a
a8af5a
135428 PGPProtocolEntry *
4a3131 PGPGetProtocolByNumber(
424b5a ¤   PGPInt32¤   inNumber)
e5bb36 {
efca6f ¤   return (PGPProtocolEntry *) getprotobynumber(inNumber);
c2efe6 }
72af5a
60af5a
3daf5a
b0c801 PGPServiceEntry *
d1b159 PGPGetServiceByName(
0cbd3e ¤   const char *¤   inName,
2de23d ¤   const char *¤   inProtocol)
8dbb36 {
2b7ee5 ¤   return (PGPServiceEntry *) getservbyname(inName, inProtocol);
66efe6 }
--7b51 0007859bb4d40100244 Page 8 of pgpSockets.c
e0af5a
1aaf5a
17af5a
43c801 PGPServiceEntry *
6605e2 PGPGetServiceByPort(
f82e13 ¤   PGPInt32¤   ¤   inPort,
0ae23d ¤   const char *¤   inProtocol)
89bb36 {
330057 ¤   return (PGPServiceEntry *) getservbyport(inPort, inProtocol);
5cefe6 }
5baf5a
53af5a
821e45 PGPInt32
bdca89 PGPGetSocketName(
7382aa ¤   PGPSocketRef¤   ¤   inSocketRef,
5cc52c ¤   PGPSocketAddress *¤ outName,
06b6bf ¤   PGPInt32 *¤ ¤   ¤   ioNameLength)
c8bb36 {
6c72ff ¤   return getsockname(¤(SOCKET) inSocketRef,
af4b9a ¤   ¤   ¤   ¤   ¤   ¤   (struct sockaddr *) outName,
f77a8c ¤   ¤   ¤   ¤   ¤   ¤   ioNameLength);
37efe6 }
16af5a
551e45 PGPInt32
d73173 PGPGetPeerName(
0982aa ¤   PGPSocketRef¤   ¤   inSocketRef,
9ac52c ¤   PGPSocketAddress *¤ outName,
dab6bf ¤   PGPInt32 *¤ ¤   ¤   ioNameLength)
80bb36 {
b251ed ¤   return getpeername(¤(SOCKET) inSocketRef,
974b9a ¤   ¤   ¤   ¤   ¤   ¤   (struct sockaddr *) outName,
8d7a8c ¤   ¤   ¤   ¤   ¤   ¤   ioNameLength);
3befe6 }
38af5a
76bccf PGPUInt32
933043 PGPDottedToInternetAddress(
b2051f ¤   const char *¤   inAddress)
3dbb36 {
758193 ¤   return inet_addr(inAddress);
05efe6 }
a0af5a
7411e4 char *
bb29db PGPInternetAddressToDottedString(
206cbf ¤   PGPInternetAddress¤ inAddress)
7abb36 {
ad787c ¤   return inet_ntoa(*((struct in_addr *) &inAddress));
a5efe6 }
09af5a
f51e45 PGPInt32
406602 PGPIOControlSocket(
8e3556 ¤   PGPSocketRef¤   inSocketRef,
b42404 ¤   PGPInt32¤   ¤   inCommand,
821c45 ¤   PGPUInt32 *¤¤   ioParam)
c3bb36 {
52c87d ¤   return ioctlsocket((SOCKET) inSocketRef,·
ca35a3 ¤   ¤   ¤   ¤   ¤   ···inCommand,·
48b5b9 ¤   ¤   ¤   ¤   ¤   ···(unsigned long*)ioParam);
a0efe6 }
1baf5a
6f1e45 PGPInt32
bbc2f5 PGPGetSocketOptions(
c43556 ¤   PGPSocketRef¤   inSocketRef,
4d23ac ¤   PGPInt32¤   ¤   inLevel,
f61bd1 ¤   PGPInt32¤   ¤   inOptionName,
ded268 ¤   char *¤ ¤   ¤   outOptionValue,
287bbf ¤   PGPInt32 *¤ ¤   ioOptionLength)
9cbb36 {
2e68d7 ¤   return getsockopt(¤ (SOCKET) inSocketRef,
0ab3cd ¤   ¤   ¤   ¤   ¤   ¤   inLevel,
545fe9 ¤   ¤   ¤   ¤   ¤   ¤   inOptionName,
18a150 ¤   ¤   ¤   ¤   ¤   ¤   outOptionValue,
788b29 ¤   ¤   ¤   ¤   ¤   ¤   ioOptionLength);
--1c9e 0002c5fb91840100244 Page 9 of pgpSockets.c
7aefe6 }
46af5a
fc1e45 PGPInt32
eacfd5 PGPSetSocketOptions(
a43556 ¤   PGPSocketRef¤   inSocketRef,
d823ac ¤   PGPInt32¤   ¤   inLevel,
da1bd1 ¤   PGPInt32¤   ¤   inOptionName,
43d4a6 ¤   const char *¤   inOptionValue,
5a4d17 ¤   PGPInt32¤   ¤   inOptionLength)
60bb36 {
3fd42a ¤   return setsockopt((SOCKET) inSocketRef,
d08edb ¤   ¤   ¤   ¤   ¤   ··inLevel,
15174c ¤   ¤   ¤   ¤   ¤   ··inOptionName,
82696e ¤   ¤   ¤   ¤   ¤   ··inOptionValue,
79bbf5 ¤   ¤   ¤   ¤   ¤   ··inOptionLength);
84efe6 }
ecaf5a
a1af5a
13c77d PGPError
9a9839 PGPSocketsEstablishTLSSession(
803556 ¤   PGPSocketRef¤   inSocketRef,
2c8bfc ¤   PGPtlsSessionRef¤   inTLSSession)
31bb36 {
1061e0 ¤   PGPError¤   err;
97bcd9 ¤   int¤¤   ¤   optval;
a210c2 ¤   int¤¤   ¤   optlen = sizeof(optval);
7767c5 ¤
7ceca5 ¤   if (getsockopt((SOCKET) inSocketRef,·
f7e3b7 ¤   ¤   ¤   ¤   ···SOL_SOCKET,·
cdf0b8 ¤   ¤   ¤   ¤   ···SO_TYPE,·
478438 ¤   ¤   ¤   ¤   ···(char *) &optval,
4fb4e0 ¤   ¤   ¤   ¤   ···&optlen) == SOCKET_ERROR) {
ad3d0a ¤   ¤   err = PGPGetLastSocketsError();
7bcf01 ¤   } else if (optval != SOCK_STREAM) {
61ff6f ¤   ¤   err = kPGPError_SocketsOperationNotSupported;
bff037 ¤   } else {
af1f66 ¤   ¤   err = PGPtlsSetReceiveCallback(¤inTLSSession,
a35010 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSocketsTLSReceive,
cddeab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inSocketRef);
7153af ¤   ¤   if (err == kPGPError_NoErr) {
1a376d ¤   ¤   ¤   err = PGPtlsSetSendCallback(inTLSSession,
5c36e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSocketsTLSSend,
7fdeab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inSocketRef);
a06f41 ¤   ¤   ¤   if (err == kPGPError_NoErr) {
29510a ¤   ¤   ¤   ¤   PGPSocketAddressInternet address;
9725ee ¤   ¤   ¤   ¤   int ·addressLen = sizeof(address);
c22b85 ¤   ¤   ¤   ¤
566e76 ¤   ¤   ¤   ¤   err = getpeername((SOCKET) inSocketRef,
d3ae3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(struct sockaddr *) &address,
ff0a8b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&addressLen);
e61cfe ¤   ¤   ¤   ¤   if (err == SOCKET_ERROR) {
d73b7d ¤   ¤   ¤   ¤   ¤   err = PGPGetLastSocketsError();
59b5fc ¤   ¤   ¤   ¤   } else {
668156 ¤   ¤   ¤   ¤   ¤   err = PGPtlsSetRemoteUniqueID(inTLSSession,
b92aae ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··address.sin_addr.s_addr);
e219ba ¤   ¤   ¤   ¤   ¤   if (err == kPGPError_NoErr) {
41e76b ¤   ¤   ¤   ¤   ¤   ¤   err = PGPtlsHandshake(inTLSSession);
27b7bb ¤   ¤   ¤   ¤   ¤   ¤   if (err == kPGPError_NoErr) {
eb4d80 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPRMWOLockStartWriting(&sTLSMapLock);
7588ac ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPAddNode(sTLSMap,
77f299 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·(PGPInt32) inSocketRef,
53b640 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·inTLSSession);
82ea27 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPRMWOLockStopWriting(&sTLSMapLock);
2d6eb7 ¤   ¤   ¤   ¤   ¤   ¤   } else if (err == kPGPError_TLSUnexpectedClose) {
39e186 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetLastSocketsError();
a1db3c ¤   ¤   ¤   ¤   ¤   ¤   }
2e1c89 ¤   ¤   ¤   ¤   ¤   }
9d2613 ¤   ¤   ¤   ¤   }
37a3a6 ¤   ¤   ¤   }
000fe4 ¤   ¤   }
f49371 ¤   }
2c67c5 ¤
--60b1 00054cc5a1c40100244 Page 10 of pgpSockets.c
ec5ea8 ¤   return err;
2aefe6 }
e0af5a
bbaf5a
2faf5a
ce1e45 PGPInt32
96a489 PGPSocketsTLSReceive(
0637e0 ¤   void *¤ inData,
45c9d9 ¤   void *¤ outBuffer,
03ba4d ¤   PGPInt32¤   inBufferSize)
1dbb36 {
4f2c4f ¤   return recv((SOCKET) inData,
d40c1f ¤   ¤   ¤   ¤   (char *) outBuffer,
3b81e2 ¤   ¤   ¤   ¤   inBufferSize,
975e4d ¤   ¤   ¤   ¤   kPGPReceiveFlagNone);
c7efe6 }
9eaf5a
67af5a
62af5a
6f1e45 PGPInt32
640055 PGPSocketsTLSSend(
52454c ¤   void *¤ ¤   inData,
3a4f2f ¤   const void *¤   inBuffer,
d5b9cd ¤   PGPInt32¤   ¤   inBufferLength)
f3bb36 {
caa773 ¤   return send((SOCKET) inData,
bbf7da ¤   ¤   ¤   ¤   (const char *) inBuffer,
36f59e ¤   ¤   ¤   ¤   inBufferLength,
69a214 ¤   ¤   ¤   ¤   kPGPSendFlagNone);
b4efe6 }
65af5a
b0af5a
b1af5a
d3c77d PGPError
5d20ca PGPGetLastSocketsError(void)
6bbb36 {
8db250 #if PGP_WIN32¤
09ff4b ¤   return MapPGPSocketsError(WSAGetLastError());
4adb21 #else
96794b ¤   return MapPGPSocketsError(errno);
187454 #endif
e5efe6 }
6daf5a
91af5a
b3bd3e #if PGP_WIN32¤  ¤
dbc77d PGPError
67d0ad PGPSetSocketsIdleEventHandler(
4ad261 ¤   PGPEventHandlerProcPtr¤ inCallback,
4aed74 ¤   PGPUserValue¤   ¤   inUserData)
1fbb36 {
93e2bc ¤   PGPRMWOLockStartWriting(&sIdleEventHandlerLock);
18cc75 ¤   if (!PGPThreadSetSpecific(sIdleEventHandlerIndex, inCallback)) {
c25e8e ¤   ¤   if (!PGPThreadSetSpecific(sIdleEventHandlerDataIndex, inUserData)) {
0bd07c ¤   ¤   ¤   if (inCallback != NULL) {
8c2432 ¤   ¤   ¤   ¤   WSASetBlockingHook(SocketsBlockingHook);
95042d ¤   ¤   ¤   } else {
234aa7 ¤   ¤   ¤   ¤   WSAUnhookBlockingHook();
32a3a6 ¤   ¤   ¤   }
0245a6 ¤   ¤   } else {
450bc9 ¤   ¤   ¤   (void) PGPThreadSetSpecific(sIdleEventHandlerIndex, NULL);
4d0fe4 ¤   ¤   }
3f9371 ¤   }
9a07b7 ¤   PGPRMWOLockStopWriting(&sIdleEventHandlerLock);
a4af5a
7f151e ¤   return kPGPError_NoErr;
e8efe6 }
ebaf5a
11c77d PGPError
5271ca PGPGetSocketsIdleEventHandler(
f0286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
baf2c1 ¤   PGPUserValue *¤ ¤   outUserData)
54bb36 {
--80f0 0004c5ef6ce40100244 Page 11 of pgpSockets.c
c3affe ¤   PGPRMWOLockStartReading(&sIdleEventHandlerLock);
7c6a4f ¤   (void) PGPThreadGetSpecific(sIdleEventHandlerIndex, (void *) outCallback);
c4f0b4 ¤   (void) PGPThreadGetSpecific(sIdleEventHandlerDataIndex,
f183ba ¤   ¤   ¤   ¤   outUserData);
264af5 ¤   PGPRMWOLockStopReading(&sIdleEventHandlerLock);
8767c5 ¤
96151e ¤   return kPGPError_NoErr;
f1efe6 }
a6af5a
6d6084 struct SThreadContext {
4f09ab ¤   PGPEventHandlerProcPtr¤ callback;
16745f ¤   PGPUserValue¤   ¤   ¤   callbackData;
4582f7 };
90af5a
aec77d PGPError
81adce PGPSocketsCreateThreadStorage(
00a081 ¤   PGPSocketsThreadStorageRef *¤   outPreviousStorage)
57bb36 {
293cbe ¤   PGPError¤   ¤   ¤   ¤   err = kPGPError_NoErr;
947005 ¤   struct SThreadContext *¤context = NULL;
fdaf5a
937088 ¤   PGPValidatePtr(outPreviousStorage);
8b3f13 ¤   *outPreviousStorage = NULL;
ccaf5a
da3a5f ¤   context = malloc(sizeof(struct SThreadContext));
f10f7a ¤   if (context != NULL) {
3f605d ¤   ¤   err = PGPGetSocketsIdleEventHandler(&context->callback,
7708f3 ¤   ¤   ¤   ¤   ¤   &context->callbackData);
bff037 ¤   } else {
45bce1 ¤   ¤   err = kPGPError_OutOfMemory;
909371 ¤   }
f9af5a
ffbbc5 ¤   if (IsPGPError(err) && (context != NULL)) {
f118fe ¤   ¤   free(context);
85f037 ¤   } else {
7cb8ea ¤   ¤   *outPreviousStorage = (PGPSocketsThreadStorageRef) context;
6b9371 ¤   }
e067c5 ¤
2e5ea8 ¤   return err;
8fefe6 }
94af5a
74af5a
1ac77d PGPError
df9fdf PGPSocketsDisposeThreadStorage(
16cc9a ¤   PGPSocketsThreadStorageRef¤ inPreviousStorage)
1bbb36 {
be8e12 ¤   PGPError¤   err = kPGPError_NoErr;
70af5a
f809a0 ¤   if (inPreviousStorage != NULL) {
1ddd07 ¤   ¤   err = PGPSetSocketsIdleEventHandler(
1a2043 ¤   ¤   ¤   ¤   ((struct SThreadContext *) inPreviousStorage)->callback,
305c89 ¤   ¤   ¤   ¤   ((struct SThreadContext *) inPreviousStorage)->callbackData);
f6c61b ¤   ¤   free(inPreviousStorage);
2f9371 ¤   }
e8af5a
9d5ea8 ¤   return err;
35efe6 }
a9af5a
3a69ff #else /* !PGP_Win32 */
1baf5a
f8c77d PGPError
6ad0ad PGPSetSocketsIdleEventHandler(
bbd261 ¤   PGPEventHandlerProcPtr¤ inCallback,
c4ed74 ¤   PGPUserValue¤   ¤   inUserData)
b4bb36 {
ae4df8 ¤   (void) inCallback;
5af69d ¤   (void) inUserData;
6d67c5 ¤
ca151e ¤   return kPGPError_NoErr;
bbefe6 }
54af5a
4cc77d PGPError
--8f34 000b551019440100244 Page 12 of pgpSockets.c
5171ca PGPGetSocketsIdleEventHandler(
df286e ¤   PGPEventHandlerProcPtr *¤   outCallback,
7bf2c1 ¤   PGPUserValue *¤ ¤   outUserData)
94bb36 {
ec7559 ¤   *outUserData = NULL;
f3ce28 ¤   *outCallback = NULL;
6f151e ¤   return kPGPError_NoErr;
1fefe6 }
70af5a
85c77d PGPError
07adce PGPSocketsCreateThreadStorage(
1da081 ¤   PGPSocketsThreadStorageRef *¤   outPreviousStorage)
6fbb36 {
4f7088 ¤   PGPValidatePtr(outPreviousStorage);
333f13 ¤   *outPreviousStorage = NULL;
3a151e ¤   return kPGPError_NoErr;
6defe6 }
77af5a
b4af5a
d6c77d PGPError
9d9fdf PGPSocketsDisposeThreadStorage(
29cc9a ¤   PGPSocketsThreadStorageRef¤ inPreviousStorage)
babb36 {
c5b275 ¤   (void) inPreviousStorage;
ab151e ¤   return kPGPError_NoErr;
5defe6 }
e9af5a
038df7 #endif /* PGP_WIN32 */
f5af5a
fcaf5a
17c77d PGPError
8516f0 MapPGPSocketsError(
3b4f7a ¤   PGPError¤   inErr)
51bb36 {
5afbcb ¤   PGPError¤   result = kPGPError_UnknownError;
05f5d1 ¤   PGPError¤   pgpError;
1e4245 ¤   PGPError¤   tempError;
3167c5 ¤
602ce0 ¤   if ((inErr > kPGPError_FirstError) && (inErr < kPGPError_Last)) {
a564f1 ¤   ¤   result = inErr;
6bf037 ¤   } else {
e215a8 ¤   ¤   pgpError = PGPFindNode(sErrorMap, inErr, (PGPUserValue *) &tempError);
ea9e4c ¤   ¤   if (pgpError == kPGPError_NoErr) {
39621b ¤   ¤   ¤   result = tempError;
5b0fe4 ¤   ¤   }
689371 ¤   }
ee67c5 ¤
6f5d73 ¤   return result;
e6efe6 }
1aaf5a
61314a void
92ce29 InitErrorMap()
6abb36 {
988f00 ¤   PGPAddNode(sErrorMap, 0, (PGPUserValue) kPGPError_NoErr);
4f67c5 ¤
a8afb9 #if PGP_WIN32
96db4b ¤   PGPAddNode(sErrorMap, WSANOTINITIALISED,
50d970 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotInitialized);
2d0751 ¤   PGPAddNode(sErrorMap, WSAENETDOWN,
6e9b22 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNetworkDown);
a4b745 ¤   PGPAddNode(sErrorMap, WSAEFAULT,
bfc896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
83ecc0 ¤   PGPAddNode(sErrorMap, WSAEINPROGRESS,
b76226 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsInProgress);
11462c ¤   PGPAddNode(sErrorMap, WSAEINVAL,
57669c ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotBound);
67edb7 ¤   PGPAddNode(sErrorMap, WSAENOBUFS,
5b62e6 ¤   ¤   ···(PGPUserValue) kPGPError_OutOfMemory);
a4f713 ¤   PGPAddNode(sErrorMap, WSAENOTSOCK,
b4e718 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotASocket);
64214a ¤   PGPAddNode(sErrorMap, WSAEOPNOTSUPP,
b58018 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsOperationNotSupported);
--0211 00086b991fb40100244 Page 13 of pgpSockets.c
837ac0 ¤   PGPAddNode(sErrorMap, WSAEADDRINUSE,
876d52 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAddressInUse);
7f3174 ¤   PGPAddNode(sErrorMap, WSAEAFNOSUPPORT,
757761 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAddressFamilyNotSupported);
46ab87 ¤   PGPAddNode(sErrorMap, WSAEADDRNOTAVAIL,
49f902 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAddressNotAvailable);
02a4d3 ¤   PGPAddNode(sErrorMap, WSAECONNREFUSED,
7432ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
37a5f3 ¤   PGPAddNode(sErrorMap, WSAEDESTADDRREQ,
42c896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
32161b ¤   PGPAddNode(sErrorMap, WSAEISCONN,
caa5d2 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAlreadyConnected);
7ead09 ¤   PGPAddNode(sErrorMap, WSAENETUNREACH,
469b22 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNetworkDown);
67d6ed ¤   PGPAddNode(sErrorMap, WSAETIMEDOUT,
f5a78f ¤   ¤   ···(PGPUserValue) kPGPError_SocketsTimedOut);
95b461 ¤   PGPAddNode(sErrorMap, WSAENOPROTOOPT,
67c896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
d44de8 ¤   PGPAddNode(sErrorMap, WSAEMSGSIZE,
955c55 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsBufferOverflow);
597c7a ¤   PGPAddNode(sErrorMap, WSAECONNABORTED,
ca32ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
b1ca0c ¤   PGPAddNode(sErrorMap, WSAECONNRESET,
3d32ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
64f4a7 ¤   PGPAddNode(sErrorMap, WSAENETRESET,
1032ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
c77d72 ¤   PGPAddNode(sErrorMap, WSAEPROTONOSUPPORT,
fc3456 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsProtocolNotSupported);
dab166 ¤   PGPAddNode(sErrorMap, WSAEPROTOTYPE,
7f3456 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsProtocolNotSupported);
909fad ¤   PGPAddNode(sErrorMap, WSAESOCKTNOSUPPORT,
bfc896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
9ef417 ¤   PGPAddNode(sErrorMap, WSASYSNOTREADY,
b39b22 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNetworkDown);
76ffad ¤   PGPAddNode(sErrorMap, WSAVERNOTSUPPORTED,
e2c896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
4faf5a
659f54 ¤   PGPAddNode(sErrorMap, WSAHOST_NOT_FOUND,
726017 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsHostNotFound);
7a15a1 ¤   PGPAddNode(sErrorMap, WSATRY_AGAIN,
3259c3 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsDomainServerError);
01389d ¤   PGPAddNode(sErrorMap, WSANO_RECOVERY,
8d59c3 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsDomainServerError);
753b5c ¤   PGPAddNode(sErrorMap, WSANO_DATA,
b459c3 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsDomainServerError);
217454 #endif
2167c5 ¤
a9129a #if PGP_UNIX
e30510 ¤   PGPAddNode(sErrorMap, ENETDOWN,
509b22 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNetworkDown);
960826 ¤   PGPAddNode(sErrorMap, EFAULT,
bac896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
7283da ¤   PGPAddNode(sErrorMap, EINPROGRESS,
7f6226 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsInProgress);
e9f94f ¤   PGPAddNode(sErrorMap, EINVAL,
e8669c ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotBound);
c0bc95 ¤   PGPAddNode(sErrorMap, ENOBUFS,
0962e6 ¤   ¤   ···(PGPUserValue) kPGPError_OutOfMemory);
aaf552 ¤   PGPAddNode(sErrorMap, ENOTSOCK,
3de718 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotASocket);
785de6 ¤   PGPAddNode(sErrorMap, EOPNOTSUPP,
988018 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsOperationNotSupported);
42066c ¤   PGPAddNode(sErrorMap, EADDRINUSE,
856d52 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAddressInUse);
2a8ec0 ¤   PGPAddNode(sErrorMap, EAFNOSUPPORT,
7b7761 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAddressFamilyNotSupported);
6e5897 ¤   PGPAddNode(sErrorMap, EADDRNOTAVAIL,
2cf902 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAddressNotAvailable);
561b67 ¤   PGPAddNode(sErrorMap, ECONNREFUSED,
0f32ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
031a47 ¤   PGPAddNode(sErrorMap, EDESTADDRREQ,
86c896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
--839a 00043396bfa40100244 Page 14 of pgpSockets.c
264739 ¤   PGPAddNode(sErrorMap, EISCONN,
80a5d2 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsAlreadyConnected);
4ec213 ¤   PGPAddNode(sErrorMap, ENETUNREACH,
c59b22 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNetworkDown);
cf8562 ¤   PGPAddNode(sErrorMap, ETIMEDOUT,
08a78f ¤   ¤   ···(PGPUserValue) kPGPError_SocketsTimedOut);
0edb7b ¤   PGPAddNode(sErrorMap, ENOPROTOOPT,
06c896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
864fa9 ¤   PGPAddNode(sErrorMap, EMSGSIZE,
845c55 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsBufferOverflow);
24c3ce ¤   PGPAddNode(sErrorMap, ECONNABORTED,
0132ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
bab6a0 ¤   PGPAddNode(sErrorMap, ECONNRESET,
5032ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
c3a728 ¤   PGPAddNode(sErrorMap, ENETRESET,
cf32ac ¤   ¤   ···(PGPUserValue) kPGPError_SocketsNotConnected);
672df7 ¤   PGPAddNode(sErrorMap, EPROTONOSUPPORT,
a23456 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsProtocolNotSupported);
b2cdca ¤   PGPAddNode(sErrorMap, EPROTOTYPE,
ba3456 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsProtocolNotSupported);
15cf28 ¤   PGPAddNode(sErrorMap, ESOCKTNOSUPPORT,
e5c896 ¤   ¤   ···(PGPUserValue) kPGPError_BadParams);
ab8f26 ¤   PGPAddNode(sErrorMap, HOST_NOT_FOUND,
3d6017 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsHostNotFound);
d6462e ¤   PGPAddNode(sErrorMap, TRY_AGAIN,
9a59c3 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsDomainServerError);
e75787 ¤   PGPAddNode(sErrorMap, NO_RECOVERY,
8a59c3 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsDomainServerError);
6a6a7e ¤   PGPAddNode(sErrorMap, NO_DATA,
2159c3 ¤   ¤   ···(PGPUserValue) kPGPError_SocketsDomainServerError);
dd7454 #endif
f5efe6 }
0faf5a
8aafb9 #if PGP_WIN32
8cedad BOOL WINAPI
f2f7ed SocketsBlockingHook()
fcbb36 {
bf35da ¤   PGPEventHandlerProcPtr¤ eventHandler = NULL;
1a4e6a ¤   PGPUserValue¤   ¤   userValue;
b8a715 ¤   PGPError¤   ¤   ¤   pgpError;
2167c5 ¤
b4affe ¤   PGPRMWOLockStartReading(&sIdleEventHandlerLock);
6977db ¤   (void) PGPThreadGetSpecific(sIdleEventHandlerIndex, (void**)&eventHandler);
68b2b7 ¤   (void) PGPThreadGetSpecific(sIdleEventHandlerDataIndex, &userValue);
ed4af5 ¤   PGPRMWOLockStopReading(&sIdleEventHandlerLock);
8167c5 ¤
c7ae7e ¤   if (eventHandler != NULL) {
6c40dd ¤   ¤   PGPEvent theEvent;
dc67c5 ¤
6e249d ¤   ¤   pgpClearMemory(&theEvent, sizeof(theEvent));
a87f8b ¤   ¤   theEvent.type = kPGPEvent_SocketsIdleEvent;
a3e716 ¤   ¤   pgpError = eventHandler(NULL, &theEvent, userValue);
7bd823 ¤   ¤   if (IsPGPError(pgpError)) {
e50d35 ¤   ¤   ¤   WSACancelBlockingCall();
510fe4 ¤   ¤   }
aa1b52 ¤   ¤
fe9371 ¤   }
ea67c5 ¤
0ca230 ¤   return FALSE;
57efe6 }
70c5c0 #endif¤ /* PGP_WIN32 */
b4af5a
ad38e5 /*
c2207b ·* This fancy int flipping is needed for maximum compatability with 64-bit
8a2d6c ·* machines, which don't always do the right thing in ntohl, or htonl
4b55bd ·* This code correctly flips a 32 bit number on all platforms.
39495d ·*/
361e45 PGPInt32
9309db PGPHostToNetLong(PGPInt32 x)
65bb36 {
61f7d0 ¤   unsigned int y = x;
4386f7 ¤   unsigned char *s = (unsigned char *)&y;
--9e29 0017e9af39c40100244 Page 15 of pgpSockets.c
2a67c5 ¤
350553 ¤   return ((int)s[0]) << 24 | ((int)s[1]) << 16
6af12c ¤   | ((int)s[2]) << 8 | ((int)s[3]);
2fefe6 }
8aaf5a
51cc9d PGPInt16
53f1e5 PGPHostToNetShort(PGPInt16 x)
0ebb36 {
2ffedf ¤   return htons(x);
30efe6 }
adaf5a
a71e45 PGPInt32
9bc95c PGPNetToHostLong(PGPInt32 x)
15bb36 {
aff7d0 ¤   unsigned int y = x;
4286f7 ¤   unsigned char *s = (unsigned char *)&y;
6067c5 ¤
120553 ¤   return ((int)s[0]) << 24 | ((int)s[1]) << 16
a5cdc2 ¤   ¤   | ((int)s[2]) << 8 | ((int)s[3]);
c2efe6 }
f4af5a
9ecc9d PGPInt16
d60192 PGPNetToHostShort(PGPInt16 x)
d5bb36 {
3b4ec0 ¤   return ntohs(x);
7eefe6 }
--6c04 001d0f855db40100245 Page 1 of Makefile.in
5ea601 #
a7b017 # priv/networklib/pgpsockets/unix/
1ba601 #
a7a6f2 # $Id: Makefile.in,v 1.2 1998/04/08 00:58:15 marcd Exp $
a3a601 #
97af5a
404719 LOCALDEFINES=
fbaf5a
d33241 OBJS= pgpTLS.o pgpTLSPrimes.o
08af5a
5355db LIBDONE= DONE
5baf5a
d0b7a3 all:: DONE
--3e53 00092dab81140100246 Page 1 of pgpTLS.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
26a324 ¤   Platform independent state machine based implementation of
a1917c ¤   IETF Transport Layer Security 1.0 with support for OpenPGP/TLS.
6f67c5 ¤
a55862 ¤   TLS 1.0 is specified in IETF RFC 2XXX
86af5a
cccc1c ¤   $Id: pgpTLS.c,v 1.48.2.3.2.1 1998/11/12 03:22:48 heller Exp $
68f7f7 ____________________________________________________________________________*/
4daf5a
224c80 #include "pgpTLSPriv.h"
3c83af #include "pgpTLSPrimes.h"
39af5a
232f8d #include "pgpErrors.h"
afc26c #include "pgpContext.h"
b20d08 #include "pgpMem.h"
aa3d4b #include "pgpEndianConversion.h"
a09f72 #include "pgpHash.h"
a8a590 #include "pgpHMAC.h"
8c42aa #include "pgpPublicKey.h"
d9e603 #include "pgpSymmetricCipher.h"
2913b1 #include "pgpCBC.h"
88a076 #include "pgpKeys.h"
d204f5 #include "pgpFeatures.h"
5baf5a
1c0141 #include "pgpOptionListPriv.h"
70af5a
60324c #include <string.h>
a2af5a
3a460c #define PGPTLS_FORCESSL3¤   /* define this for all 6.0.X builds */
9c5864 #define noPGPTLS_DEBUG
38af5a
5598e9 #define CKERR¤  ¤   ¤   if( err ) goto done¤
3d6b79 #define FATALTLS( x )¤  {¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
cecf48 ¤   ¤   ¤   err = x;¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
27e99f ¤   ¤   ¤   session->state = kPGPtls_FatalErrorState;¤  ¤   \
afacb0 ¤   ¤   ¤   goto done;¤ }
78af5a
bb5637 #define TLSNUMCLIENTSTATES¤ 10
4b761f #define TLSNUMSERVERSTATES¤ 7
b1a47f #define TLSNUMEVENTS¤   ¤   15
e2af5a
ed4471 static PGPInt8 kPGPtls_ClientStateTable[TLSNUMCLIENTSTATES][TLSNUMEVENTS] =
23bb36 {
fefd0a ¤   /*¤ ¤   HR¤ CH¤ SH¤ CE¤ EC¤ SC¤ SKE¤CR¤ SHD¤CV¤ CKE¤FIN¤FAT¤NC¤ CC¤ */ 
b6c3ba {¤  /* 0 */¤-1,¤-2,¤1,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
7ec1b6 {¤  /* 1 */¤-1, -2,¤-2,¤2,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
a782d1 {¤  /* 2 */¤-1,¤-2,¤-2,¤-2,¤3,¤ 4,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
8e41ca {¤  /* 3 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤5,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
c641c0 {¤  /* 4 */¤-1, -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤6,¤ 7,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
e779dd {¤  /* 5 */¤-1, -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤6,¤ 7,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
cfdafc {¤  /* 6 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤7,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }, 
aeba3b {¤  /* 7 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤8¤  }, 
c386ee {¤  /* 8 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤9,¤ -2,¤-2,¤-2¤ }, 
41e2b3 {¤  /* 9 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ } 
b382f7 };
d5af5a
604f80 static PGPInt8 kPGPtls_ServerStateTable[TLSNUMSERVERSTATES][TLSNUMEVENTS] =
60bb36 {
2cfd0a ¤   /*¤ ¤   HR¤ CH¤ SH¤ CE¤ EC¤ SC¤ SKE¤CR¤ SHD¤CV¤ CKE¤FIN¤FAT¤NC¤ CC¤ */
f4a2b7 {¤  /* 0 */¤-1,¤1,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ },
ee6300 {¤  /* 1 */¤-1, -2,¤-2,¤2,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤3,¤ -2,¤-2,¤-2,¤-2¤ },
a47d23 {¤  /* 2 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤3,¤ -2,¤-2,¤-2,¤-2¤ },
db5380 {¤  /* 3 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤4,¤ -2,¤-2,¤-2,¤-2,¤5¤  },
36425e {¤  /* 4 */¤-1, -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤5¤  },
6352b3 {¤  /* 5 */¤-1, -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤6,¤ -2,¤-2,¤-2¤ },
2b56e0 {¤  /* 6 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }
f782f7 };
45af5a
92a459 static PGPInt8 kPGPtls_SSL3ServerStateTable[TLSNUMSERVERSTATES][TLSNUMEVENTS] =
--f4f3 000481d522140100246 Page 2 of pgpTLS.c
2cbb36 {
4ffd0a ¤   /*¤ ¤   HR¤ CH¤ SH¤ CE¤ EC¤ SC¤ SKE¤CR¤ SHD¤CV¤ CKE¤FIN¤FAT¤NC¤ CC¤ */
42a2b7 {¤  /* 0 */¤-1,¤1,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ },
dd1769 {¤  /* 1 */¤-1, -2,¤-2,¤2,¤ -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤3,¤ -2,¤-2,¤-1,¤-2¤ },
fb7d23 {¤  /* 2 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤3,¤ -2,¤-2,¤-2,¤-2¤ },
d327e9 {¤  /* 3 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤4,¤ -2,¤-2,¤-2,¤-1,¤5¤  },
df425e {¤  /* 4 */¤-1, -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤5¤  },
9152b3 {¤  /* 5 */¤-1, -2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤6,¤ -2,¤-2,¤-2¤ },
a956e0 {¤  /* 6 */¤-1,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2,¤-2¤ }
2282f7 };
271b52 ¤   ¤
d6d497 ¤   PGPInt8
fec3b7 pgpTLSNextState(
302665 ¤   PGPtlsSessionPriv *¤session,
e1d8e2 ¤   PGPByte¤¤   ¤   ¤   event )
03bb36 {
dd282a ¤   PGPInt8¤newState;
7667c5 ¤
0eaefe ¤   if( session->isClientSide )
1bab48 ¤   ¤   newState = kPGPtls_ClientStateTable[session->intState][event];
e46369 ¤   else if( session->minorVersion == kPGPtls_SSL3MinorVersion )
ba26c6 ¤   ¤   newState = kPGPtls_SSL3ServerStateTable[session->intState][event];
090e24 ¤   else
b395b7 ¤   ¤   newState = kPGPtls_ServerStateTable[session->intState][event];
9daff6 ¤   if( newState == -2 )
b0953f ¤   ¤   session->state = kPGPtls_FatalErrorState;
ba5dde ¤   else if( newState >= 0 )
4ae336 ¤   ¤   session->intState = newState;
6192d3 ¤   return newState;
92efe6 }
17af5a
85c744 ¤   PGPError
bf7eaf PGPNewTLSContext(
3aa1bc ¤   PGPContextRef¤  ¤   context,
7cc254 ¤   PGPtlsContextRef *¤ outRef )
22bb36 {
15d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
560b96 ¤   PGPtlsContextPriv *¤pContext;
3baf5a
5a4dac ¤   PGPValidatePtr( context );
4fcd60 ¤   *outRef = NULL;
9f67c5 ¤
d13e8b ¤   pContext = (PGPtlsContextPriv *) pgpContextMemAlloc( context,
ee0f41 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(PGPtlsContextPriv),
44a90e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
6b4377 ¤   if( IsntNull( pContext ) )
e6c7a1 ¤   {
dc51bc ¤   ¤   pContext->pgpContext = context;
6d848a ¤   ¤   pContext->useCache = TRUE;¤ ¤
7f1b52 ¤   ¤
e4b02a ¤   ¤   *outRef = ( PGPtlsContextRef ) pContext;
2d9371 ¤   }
5c0e24 ¤   else
a4bce1 ¤   ¤   err = kPGPError_OutOfMemory;
6a67c5 ¤
8e4c5f ¤   pgpAssertErrWithPtr( err, *outRef );
4a5ea8 ¤   return err;
d8efe6 }
1aaf5a
4cc744 ¤   PGPError
30d4e0 PGPFreeTLSContext(
881e11 ¤   PGPtlsContextRef¤   ref )
3bbb36 {
145eb1 ¤   PGPValidatePtr( ref );
78af5a
02feca ¤   return pgpContextMemFree( ((PGPtlsContextPriv *) ref)->pgpContext,
dc82c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ref );
5fefe6 }
3aaf5a
93c744 ¤   PGPError
40d8ac PGPtlsSetCache(
485acd ¤   PGPtlsContextRef¤   ref,
--4f99 0003001f41b40100246 Page 3 of pgpTLS.c
f08fbe ¤   PGPBoolean¤ ¤   ¤   useCache )
8fbb36 {
9c5eb1 ¤   PGPValidatePtr( ref );
0e67c5 ¤
75fad8 ¤   ((PGPtlsContextPriv *) ref)->useCache = useCache;
e390c7 ¤   /* not implemented yet */
c667c5 ¤
4c151e ¤   return kPGPError_NoErr;
63efe6 }
33af5a
dbc744 ¤   PGPError
7d859b PGPtlsClearCache(
751e11 ¤   PGPtlsContextRef¤   ref )
46bb36 {
ac5b27 ¤   (void) ref;
6167c5 ¤
0590c7 ¤   /* not implemented yet */
be151e ¤   return kPGPError_NoErr;
dbefe6 }
63af5a
b216ea ¤   PGPBoolean
a48411 pubAlgSupported(
43180b ¤   PGPPublicKeyAlgorithm¤  ¤   pubAlg )
8fbb36 {
fdd6fe ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numPubAlgs,
238efc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   algIndex;
866818 ¤   PGPPublicKeyAlgorithmInfo¤  info;
ce67c5 ¤
96a23b ¤   PGPCountPublicKeyAlgorithms( &numPubAlgs );
415879 ¤   for( algIndex = 0; algIndex < numPubAlgs; algIndex++ )
ddc7a1 ¤   {
95344f ¤   ¤   PGPGetIndexedPublicKeyAlgorithmInfo( algIndex, &info);
ec7a27 ¤   ¤   if( info.algID == pubAlg )
8832bd ¤   ¤   ¤   return TRUE;
229371 ¤   }
f8a230 ¤   return FALSE;
51efe6 }
a1af5a
73c744 ¤   PGPError
5635e0 PGPNewTLSSession(
452b62 ¤   PGPtlsContextRef¤   ¤   ref,
ee1cac ¤   PGPtlsSessionRef *¤ ¤   outRef )
83bb36 {
a2d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
a40b96 ¤   PGPtlsContextPriv *¤pContext;
dffefc ¤   PGPtlsSessionPriv *¤session;
3eaf5a
c95eb1 ¤   PGPValidatePtr( ref );
cacd60 ¤   *outRef = NULL;
b967c5 ¤
a70b5c ¤   pContext = ( PGPtlsContextPriv * ) ref;
e05f75 ¤   session = ( PGPtlsSessionPriv * ) pgpContextMemAlloc( pContext->pgpContext,
3aa0bc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( PGPtlsSessionPriv ),
bea90e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
3fb9df ¤   if( IsntNull( session ) )
b3c7a1 ¤   {
d0de10 ¤   ¤   session->pgpContext¤¤   ¤   = pContext->pgpContext;
ac1abb ¤   ¤   session->tlsContext¤¤   ¤   = pContext;
f1ec01 ¤   ¤   session->memMgr¤¤   ¤   ¤   =
b2bf29 ¤   ¤   ¤   PGPGetContextMemoryMgr( pContext->pgpContext );
6abe86 ¤   ¤   session->state¤ ¤   ¤   ¤   = kPGPtls_IdleState;
893e3f ¤   ¤   session->intState¤  ¤   ¤   = 0;
1db74d ¤   ¤   session->isClientSide¤  ¤   = TRUE;
5f70a7 ¤   ¤   session->blocking¤  ¤   ¤   = TRUE;
ec5953 ¤   ¤   session->minorVersion¤  ¤   = kPGPtls_MinorVersion;
811b52 ¤   ¤
9c01b8 ¤   ¤   session->localKeyAlg¤   ¤   = kPGPPublicKeyAlgorithm_Invalid;
21ecd7 ¤   ¤   session->requestedPrime¤¤   = kPGPtls_DHPrime2048;
67719e ¤   ¤   session->certRequested¤ ¤   = FALSE;
89dd8a ¤   ¤   session->certVerified¤  ¤   = FALSE;
eb1b52 ¤   ¤
30c371 ¤   ¤   session->tlsReceiveProc¤¤   = NULL;
--05b3 0004e3e486c40100246 Page 4 of pgpTLS.c
d51d91 ¤   ¤   session->tlsSendProc¤   ¤   = NULL;
8179e2 ¤   ¤   session->tlsReceiveUserData¤= NULL;
7400e8 ¤   ¤   session->tlsSendUserData¤   = NULL;
e4af5a
4f4aa2 #ifdef PGPTLS_DEBUG
fcf67e ¤   ¤   err = pgpTLSPRFTest( session );
52d223 ¤   ¤   if( IsPGPError( err ) )
b05b34 ¤   ¤   {
7bd2bf ¤   ¤   ¤   pgpAssert( 0 );
010fe4 ¤   ¤   }
a47454 #endif
121b52 ¤   ¤
818947 ¤   ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA,
70383e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->handshakeSHA);
d286f8 ¤   ¤   if( IsntPGPError( err ) )
6c5b34 ¤   ¤   {
07b5e8 ¤   ¤   ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5,
671cb5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->handshakeMD5);
590fe4 ¤   ¤   }
5586f8 ¤   ¤   if( IsntPGPError( err ) )
925b34 ¤   ¤   {
aa8222 ¤   ¤   ¤   session->cipherSuites = ( PGPtlsCipherSuite * )
7db191 ¤   ¤   ¤   ¤   pgpContextMemAlloc( pContext->pgpContext,
6596bc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( kPGPtls_CipherSuites ),
08da17 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
4173a6 ¤   ¤   ¤   if( IsntNull( session->cipherSuites ) )
9ff776 ¤   ¤   ¤   {
6a7f2b ¤   ¤   ¤   ¤   /* Determine which available cipher suites we can
b30472 ¤   ¤   ¤   ¤   ¤   actually perform given the underlying SDK
b52d33 ¤   ¤   ¤   ¤   ¤   algorithms. */
a15674 ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   suiteIndex,
96a854 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   numSymAlgs,
0e8e9f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   algIndex,
39deb2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   totalSuites;
ea3bc2 ¤   ¤   ¤   ¤   PGPSymmetricCipherInfo¤ ¤   symInfo;
064e3c ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   foundPub,
8595c6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   foundSym;
092b85 ¤   ¤   ¤   ¤
3043f2 ¤   ¤   ¤   ¤   totalSuites =¤  sizeof( kPGPtls_CipherSuites ) /
8cfb55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( PGPtlsCipherSuite );
612dda ¤   ¤   ¤   ¤   session->numCipherSuites = 0;
d58d87 ¤   ¤   ¤   ¤   PGPCountSymmetricCiphers( &numSymAlgs );
ce7f6d ¤   ¤   ¤   ¤   for( suiteIndex = 0; suiteIndex < totalSuites;
c3de80 ¤   ¤   ¤   ¤   ¤   ¤   suiteIndex++ )
2672c3 ¤   ¤   ¤   ¤   {
115555 ¤   ¤   ¤   ¤   ¤   foundPub = foundSym = FALSE;
b04912 ¤   ¤   ¤   ¤   ¤   if( pubAlgSupported(
f51388 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_CipherSuites[ suiteIndex ].sigAlg ) )
06c297 ¤   ¤   ¤   ¤   ¤   ¤   foundPub = TRUE;
772f71 ¤   ¤   ¤   ¤   ¤   if( kPGPtls_CipherSuites[ suiteIndex ].cipherID ==
e1ac55 ¤   ¤   ¤   ¤   ¤   ¤   kPGPCipherAlgorithm_None )
6a0a5a ¤   ¤   ¤   ¤   ¤   ¤   foundSym = TRUE;
62d67c ¤   ¤   ¤   ¤   ¤   else for( algIndex = 0; algIndex < numSymAlgs;
c040a9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   algIndex++ )
3b4859 ¤   ¤   ¤   ¤   ¤   {
8f8bd6 ¤   ¤   ¤   ¤   ¤   ¤   PGPGetIndexedSymmetricCipherInfo(¤  algIndex,
bb2146 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &symInfo );
fd9612 ¤   ¤   ¤   ¤   ¤   ¤   if( symInfo.algID ==
6d9bfa ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_CipherSuites[ suiteIndex ].cipherID )
eb8fec ¤   ¤   ¤   ¤   ¤   ¤   {
640ce2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   foundSym = TRUE;
6c8c94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
a7db3c ¤   ¤   ¤   ¤   ¤   ¤   }
e71c89 ¤   ¤   ¤   ¤   ¤   }
7f1198 ¤   ¤   ¤   ¤   ¤   if( foundPub && foundSym )
422e12 ¤   ¤   ¤   ¤   ¤   ¤   session->cipherSuites[ session->numCipherSuites++ ] =
806f10 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_CipherSuites[ suiteIndex ];
e62613 ¤   ¤   ¤   ¤   }
1aa3a6 ¤   ¤   ¤   }
94bb8c ¤   ¤   ¤   else
cfbfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
4e0fe4 ¤   ¤   }
--53d0 0004cdca2c940100246 Page 5 of pgpTLS.c
f11b52 ¤   ¤
2e62a5 ¤   ¤   session->fatalAlert¤¤   ¤   = kPGPtls_AT_None;
b41b52 ¤   ¤
a1a9ff ¤   ¤   *outRef = ( PGPtlsSessionRef ) session;
5d9371 ¤   }
690e24 ¤   else
d9bce1 ¤   ¤   err = kPGPError_OutOfMemory;
0a67c5 ¤
806245 ¤   if( IsPGPError( err ) && IsntNull( session ) )
97c7a1 ¤   {
4c281a ¤   ¤   if( PGPHashContextRefIsValid( session->handshakeSHA ) )
cf5b34 ¤   ¤   {
0fc197 ¤   ¤   ¤   (void)PGPFreeHashContext( session->handshakeSHA );
682f9c ¤   ¤   ¤   session->handshakeSHA = kInvalidPGPHashContextRef;
0a0fe4 ¤   ¤   }
2c2758 ¤   ¤   if( PGPHashContextRefIsValid( session->handshakeMD5 ) )
835b34 ¤   ¤   {
e8fb68 ¤   ¤   ¤   (void)PGPFreeHashContext( session->handshakeMD5 );
517374 ¤   ¤   ¤   session->handshakeMD5 = kInvalidPGPHashContextRef;
6d0fe4 ¤   ¤   }
88e5e7 ¤   ¤   if( IsntNull( session->cipherSuites ) )
e9754d ¤   ¤   ¤   (void)PGPFreeData( session->cipherSuites );
c61b52 ¤   ¤
c15ad4 ¤   ¤   pgpContextMemFree( pContext->pgpContext, session );
b0b794 ¤   ¤   *outRef = NULL;
9a9371 ¤   }
f04c5f ¤   pgpAssertErrWithPtr( err, *outRef );
e25ea8 ¤   return err;
f3efe6 }
67af5a
cec744 ¤   PGPError
2163d5 PGPFreeTLSSession( PGPtlsSessionRef ref )
dbbb36 {
24d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
5cfefc ¤   PGPtlsSessionPriv *¤session;
9baf5a
895eb1 ¤   PGPValidatePtr( ref );
d1af5a
3e94b1 ¤   session = (PGPtlsSessionPriv *) ref;
9167c5 ¤
891e9c ¤   if( session->state == kPGPtls_ClosedState )
e7c7a1 ¤   {
d707db ¤   ¤   /* Cache the session if applicable */
941b52 ¤   ¤
17a5b0 ¤   ¤   /* ##### */
489371 ¤   }
0867c5 ¤
7b6bea ¤   if( IsntNull( session->localKeyPassphrase ) )
efa4e0 ¤   ¤   (void)PGPFreeData( session->localKeyPassphrase );
053568 ¤   if( IsntNull( session->localKeyPasskeyBuffer ) )
688b94 ¤   ¤   (void)PGPFreeData( session->localKeyPasskeyBuffer );
f10640 ¤   if( PGPKeySetRefIsValid( session->remoteKeySet ) )
e48a6e ¤   ¤   (void)PGPFreeKeySet( session->remoteKeySet );
6aec06 ¤   if( PGPHashContextRefIsValid( session->handshakeSHA ) )
f6c175 ¤   ¤   (void)PGPFreeHashContext( session->handshakeSHA );
68e344 ¤   if( PGPHashContextRefIsValid( session->handshakeMD5 ) )
92fb8a ¤   ¤   (void)PGPFreeHashContext( session->handshakeMD5 );
3feaab ¤   if( PGPHashContextRefIsValid( session->lastHandSHA ) )
368423 ¤   ¤   (void)PGPFreeHashContext( session->lastHandSHA );
d4e5e9 ¤   if( PGPHashContextRefIsValid( session->lastHandMD5 ) )
5dbedc ¤   ¤   (void)PGPFreeHashContext( session->lastHandMD5 );
2067c5 ¤
3bf59b ¤   if( PGPHashContextRefIsValid( session->innerMACHash ) )
d395fc ¤   ¤   (void)PGPFreeHashContext( session->innerMACHash );
8d9d16 ¤   if( PGPHashContextRefIsValid( session->outerMACHash ) )
2b4627 ¤   ¤   (void)PGPFreeHashContext( session->outerMACHash );
5967c5 ¤
95e8fd ¤   if( PGPCBCContextRefIsValid( session->writeCipher ) )
1d953f ¤   ¤   (void)PGPFreeCBCContext( session->writeCipher );
ecf616 ¤   if( PGPCBCContextRefIsValid( session->readCipher ) )
d586c4 ¤   ¤   (void)PGPFreeCBCContext( session->readCipher );
4c4c8f ¤   if( IsntNull( session->writeActive ) )
--acc8 0008d7dc72040100246 Page 6 of pgpTLS.c
f7c7a1 ¤   {
272ce5 ¤   ¤   if( PGPHMACContextRefIsValid( session->writeActive->hmac ) )
d36a70 ¤   ¤   ¤   (void)PGPFreeHMACContext( session->writeActive->hmac );
00d29f ¤   ¤   (void)PGPFreeData( session->writeActive );
f89371 ¤   }
591e5a ¤   if( IsntNull( session->readActive ) )
52c7a1 ¤   {
d09491 ¤   ¤   if( PGPHMACContextRefIsValid( session->readActive->hmac ) )
3c4d89 ¤   ¤   ¤   (void)PGPFreeHMACContext( session->readActive->hmac );
361e8d ¤   ¤   (void)PGPFreeData( session->readActive );
c79371 ¤   }
6f4fc2 ¤   if( IsntNull( session->clientPending ) )
f7cd15 ¤   ¤   (void)PGPFreeData( session->clientPending );
79497e ¤   if( IsntNull( session->serverPending ) )
a14173 ¤   ¤   (void)PGPFreeData( session->serverPending );
0d1b52 ¤   ¤
c6b400 ¤   if( IsntNull( session->queuedSendData ) )
a1e31a ¤   ¤   (void)PGPFreeData( session->queuedSendData );
702d62 ¤   if( IsntNull( session->rcvdRawData ) )
9629dd ¤   ¤   (void)PGPFreeData( session->rcvdRawData );
815f75 ¤   if( IsntNull( session->rcvdAppData ) )
06b1bc ¤   ¤   (void)PGPFreeData( session->rcvdAppData );
f890a0 ¤   if( IsntNull( session->rcvdHandData ) )
0a416f ¤   ¤   (void)PGPFreeData( session->rcvdHandData );
a067c5 ¤
e4293c ¤   if( session->dhP != kPGPInvalidBigNumRef )
bcc7a1 ¤   {
9349ec ¤   ¤   err = PGPFreeBigNum( session->dhP );
bd9832 ¤   ¤   pgpAssertNoErr( err );
929371 ¤   }
d3d268 ¤   if( session->dhG != kPGPInvalidBigNumRef )
05c7a1 ¤   {
f2cd70 ¤   ¤   err = PGPFreeBigNum( session->dhG );
e39832 ¤   ¤   pgpAssertNoErr( err );
c39371 ¤   }
e06104 ¤   if( session->dhYs != kPGPInvalidBigNumRef )
ecc7a1 ¤   {
38a998 ¤   ¤   err = PGPFreeBigNum( session->dhYs );
299832 ¤   ¤   pgpAssertNoErr( err );
e69371 ¤   }
1d69aa ¤   if( session->dhX != kPGPInvalidBigNumRef )
7ac7a1 ¤   {
7c13cc ¤   ¤   err = PGPFreeBigNum( session->dhX );
b59832 ¤   ¤   pgpAssertNoErr( err );
8d9371 ¤   }
c0e028 ¤   if( session->dhYc != kPGPInvalidBigNumRef )
88c7a1 ¤   {
db1dd8 ¤   ¤   err = PGPFreeBigNum( session->dhYc );
739832 ¤   ¤   pgpAssertNoErr( err );
d19371 ¤   }
1afdb7 ¤   if( IsntNull( session->cipherSuites ) )
1920e1 ¤   ¤   (void)PGPFreeData( session->cipherSuites );
89af5a
3caf5a
fb6d3b ¤   err = pgpContextMemFree( session->pgpContext, session );
435ea8 ¤   return err;
bfefe6 }
39af5a
8ec744 ¤   PGPError
a17a4a pgpTLSBufferRawData(
3b2665 ¤   PGPtlsSessionPriv *¤session,
6c7fae ¤   PGPByte *¤  ¤   ¤   rawData,
347001 ¤   PGPSize¤¤   ¤   ¤   rawDataSize )
54bb36 {
1b7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
5c67c5 ¤
508aca ¤   err = pgpContextMemRealloc( session->pgpContext,
16ff69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &session->rcvdRawData,
94c2fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->rawDataSize + rawDataSize, 0 ); CKERR;
8a8451 ¤   pgpCopyMemory( rawData, session->rcvdRawData + session->rawDataSize,
8477fb ¤   ¤   ¤   ¤   ¤   rawDataSize );
8d284a ¤   session->rawDataSize += rawDataSize;
--9297 000c67f116d40100246 Page 7 of pgpTLS.c
e0af5a
7cb38c done:
005ea8 ¤   return err;
e1efe6 }
c2af5a
2fc744 ¤   PGPError
3801d7 pgpTLSExtractRawData(
2b2665 ¤   PGPtlsSessionPriv *¤session,
507fae ¤   PGPByte *¤  ¤   ¤   rawData,
ff08c7 ¤   PGPSize *¤  ¤   ¤   rawDataSize )
c5bb36 {
177d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
de7e48 ¤   PGPSize¤¤   ¤   ¤   maxSize = *rawDataSize;
8967c5 ¤
3496c4 ¤   *rawDataSize = 0;
ecbb01 ¤   if( ( maxSize > 0 ) && ( session->rawDataSize > 0 ) )
4bc7a1 ¤   {
b323c4 ¤   ¤   if( maxSize > session->rawDataSize )
513be9 ¤   ¤   ¤   maxSize = session->rawDataSize;
67c0bf ¤   ¤   pgpCopyMemory( session->rcvdRawData, rawData, maxSize );
876e04 ¤   ¤   *rawDataSize = maxSize;
d8d81e ¤   ¤   pgpCopyMemory( session->rcvdRawData + maxSize,
ba203e ¤   ¤   ¤   ¤   ¤   ¤   session->rcvdRawData, session->rawDataSize - maxSize );
e5dabc ¤   ¤   session->rawDataSize -= maxSize;
0be5f9 ¤   ¤   err = pgpContextMemRealloc( session->pgpContext,
81ff69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &session->rcvdRawData,
6de5b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->rawDataSize, 0 ); CKERR;
d09371 ¤   }
30b38c done:
bf5ea8 ¤   return err;
e6efe6 }
4faf5a
56c744 ¤   PGPError
f2115d pgpTLSBufferHandData(
512665 ¤   PGPtlsSessionPriv *¤session,
76b473 ¤   PGPByte *¤  ¤   ¤   handData,
970ac1 ¤   PGPSize¤¤   ¤   ¤   handDataSize )
91bb36 {
187d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
ed67c5 ¤
cc8aca ¤   err = pgpContextMemRealloc( session->pgpContext,
ad0640 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &session->rcvdHandData,
8d4b55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->handDataSize + handDataSize, 0 ); CKERR;
a11436 ¤   pgpCopyMemory( handData, session->rcvdHandData + session->handDataSize,
d8d5d9 ¤   ¤   ¤   ¤   ¤   handDataSize );
8b030b ¤   session->handDataSize += handDataSize;
f6af5a
38b38c done:
f05ea8 ¤   return err;
13efe6 }
f0af5a
01c744 ¤   PGPError
645e4a pgpTLSExtractHandData(
732665 ¤   PGPtlsSessionPriv *¤session,
8f7306 ¤   PGPByte **¤ ¤   ¤   handData,
8fa983 ¤   PGPSize *¤  ¤   ¤   handDataSize )
1fbb36 {
957d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
a867c5 ¤
e4efc8 ¤   if( session->handDataSize > 0 )
f1c7a1 ¤   {
04e5f9 ¤   ¤   err = pgpContextMemRealloc( session->pgpContext,
5259ca ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) handData,
f143d7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   *handDataSize + session->handDataSize, 0 ); CKERR;
55af5a
6af0d9 ¤   ¤   pgpCopyMemory( *handData, *handData + session->handDataSize, *handDataS¶
d56372 ize );
5ad057 ¤   ¤   pgpCopyMemory( session->rcvdHandData, *handData, session->handDataSize ¶
ff6275 );
4f4e55 ¤   ¤   *handDataSize += session->handDataSize;
7d3cc3 ¤   ¤   session->handDataSize = 0;
c69371 ¤   }
--adf4 000b31da9cc40100246 Page 8 of pgpTLS.c
d8b38c done:
ed5ea8 ¤   return err;
5defe6 }
82af5a
abc744 ¤   PGPError
6de1aa pgpTLSBufferSendData(
b02665 ¤   PGPtlsSessionPriv *¤session,
7e4484 ¤   PGPByte *¤  ¤   ¤   sendData,
b8d290 ¤   PGPSize¤¤   ¤   ¤   sendDataSize )
39bb36 {
a07d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
dc67c5 ¤
ec8aca ¤   err = pgpContextMemRealloc( session->pgpContext,
c61028 ¤   ¤   ¤   ¤   ¤   (void **) &session->queuedSendData,
2afc48 ¤   ¤   ¤   ¤   ¤   session->queuedSendSize + sendDataSize, 0 ); CKERR;
8329e0 ¤   pgpCopyMemory( sendData, session->queuedSendData + session->queuedSendSize,
4e960d ¤   ¤   ¤   ¤   ¤   sendDataSize );
ee45eb ¤   session->queuedSendSize += sendDataSize;
d8af5a
2eb38c done:
505ea8 ¤   return err;
17efe6 }
bfaf5a
98c744 ¤   PGPError
9229fb pgpTLSReceiveRecordLayer(
b42665 ¤   PGPtlsSessionPriv *¤session,
d6d57d ¤   PGPByte *¤  ¤   ¤   outType,
bfd9a3 ¤   PGPByte **¤ ¤   ¤   outBuffer,
b0a675 ¤   PGPSize *¤  ¤   ¤   outLength )
63bb36 {
7cd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
ccdcb1 ····PGPError ···········rerr = kPGPError_NoErr;
42d7e9 ¤   PGPByte¤¤   ¤   ¤   header[kPGPtls_RecordHeaderSize];
a3cdda ¤   PGPByte *¤  ¤   ¤   buffer = NULL;
9f4fe1 ¤   PGPSize¤¤   ¤   ¤   rcvd;
8ce888 ¤   PGPUInt16¤  ¤   ¤   length;
512d9f ¤   PGPInt32¤   ¤   ¤   bytesRead;
efaf5a
97ee22 ¤   *outType¤   = 0;
f6b1aa ¤   *outBuffer¤ = NULL;
a39f08 ¤   *outLength¤ = 0;
d367c5 ¤
ddedce ¤   rcvd = kPGPtls_RecordHeaderSize;
495bbf ¤   err = pgpTLSExtractRawData( session, header, &rcvd );¤  CKERR;
beb0d1 ¤   for(; rcvd < kPGPtls_RecordHeaderSize; rcvd += bytesRead)
16c7a1 ¤   {
a0566b ¤   ¤   bytesRead = (session->tlsReceiveProc)( session->tlsReceiveUserData,
aa51c2 ¤   ¤   ¤   ¤   ¤   ¤   header + rcvd,
c4e0c6 ¤   ¤   ¤   ¤   ¤   ¤   (PGPInt32)( kPGPtls_RecordHeaderSize - rcvd ) );
ecf638 ¤   ¤   if( bytesRead < 0 )
425b34 ¤   ¤   {
833f00 ¤   ¤   ¤   if( bytesRead != kPGPError_TLSWouldBlock )
9ef776 ¤   ¤   ¤   {
b385bf ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSUnexpectedClose );
c2a3a6 ¤   ¤   ¤   }
babb8c ¤   ¤   ¤   else
812cc2 ············{
588f8a ················rerr = kPGPError_TLSWouldBlock;
52f62d ¤   ¤   ¤   ¤   bytesRead = 0;
567812 ············}
440fe4 ¤   ¤   }
541879 ¤   ¤   if( bytesRead == 0 )
f75b34 ¤   ¤   {
67fe7c ¤   ¤   ¤   if( session->blocking )
f6f776 ¤   ¤   ¤   {
a885bf ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSUnexpectedClose );
0fa3a6 ¤   ¤   ¤   }
17bb8c ¤   ¤   ¤   else
dff776 ¤   ¤   ¤   {
0c87a8 ¤   ¤   ¤   ¤   if( rcvd )
a23b8c ················{
b3294c ····················err = pgpTLSBufferRawData( session, header, rcvd ); ·CKERR;
--28bd 0003a41dd9940100246 Page 9 of pgpTLS.c
a01f8d ····················if(rerr == kPGPError_TLSWouldBlock) ····/* check to see if ¶
522212 receive call returned a blocking error */
9d8ae9 ····················{
7f59a5 ························err = kPGPError_TLSWouldBlock;
cede39 ····················}
2d6f5c ················}
02f2ce ················else if(rerr == kPGPError_TLSWouldBlock) ···/* check for blocki¶
fddd7e ng error */
d43b8c ················{
650262 ····················err = kPGPError_TLSWouldBlock;
9a6f5c ················}
c9ff25 ¤   ¤   ¤   ¤   goto done;
c6a3a6 ¤   ¤   ¤   }
9b0fe4 ¤   ¤   }
f29371 ¤   }
5fdbc6 ¤   pgpAssert( rcvd == kPGPtls_RecordHeaderSize );
af67c5 ¤
b35279 ¤   switch( header[0] )
3dc7a1 ¤   {
46b66e ¤   ¤   case kPGPtls_RT_ChangeCipherSpec:
6d243d ¤   ¤   case kPGPtls_RT_Alert:
eabc73 ¤   ¤   case kPGPtls_RT_Handshake:
947c5f ¤   ¤   case kPGPtls_RT_ApplicationData:
26cdcb ¤   ¤   ¤   break;
329ae3 ¤   ¤   default:
4d956e ¤   ¤   ¤   /* Unknown Record Type, illegal, abort protocol */
fd0283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
a1eeec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
dd681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
549371 ¤   }
aa67c5 ¤
261ffa ¤   if( header[1] != kPGPtls_MajorVersion )
f9c7a1 ¤   {
6e8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
0085a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_ProtocolVersion );
f8d5a3 ¤   ¤   FATALTLS( kPGPError_TLSVersionUnsupported );
8b9371 ¤   }
3f71e7 ¤   length = PGPEndianToUInt16( kPGPBigEndian, &header[3] );
7a2357 ¤   if( length <= 0 || length > kPGPtls_MaximumPacketSize )
fcc7a1 ¤   {
2f8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
6c7d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
cd3db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
7a9371 ¤   }
14e181 ¤   buffer = (PGPByte *) pgpContextMemAlloc(session->pgpContext, length, 0 );
9685be ¤   if( IsNull( buffer ) )
85c7a1 ¤   {
ffbce1 ¤   ¤   err = kPGPError_OutOfMemory;
c5262d ¤   ¤   goto done;
319371 ¤   }
659076 ¤   rcvd = length;
a84716 ¤   err = pgpTLSExtractRawData( session, buffer, &rcvd );¤  CKERR;
d25150 ¤   for(; rcvd < length; rcvd += bytesRead)
bbc7a1 ¤   {
dd566b ¤   ¤   bytesRead = (session->tlsReceiveProc)( session->tlsReceiveUserData,
72dfff ¤   ¤   ¤   ¤   ¤   ¤   buffer + rcvd, (PGPInt32)( length - rcvd ) );
19f638 ¤   ¤   if( bytesRead < 0 )
5a5b34 ¤   ¤   {
a33f00 ¤   ¤   ¤   if( bytesRead != kPGPError_TLSWouldBlock )
f8f776 ¤   ¤   ¤   {
c583ba ¤   ¤   ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
5b43df ¤   ¤   ¤   ¤   buffer = NULL;
6c85bf ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSUnexpectedClose );
86a3a6 ¤   ¤   ¤   }
65bb8c ¤   ¤   ¤   else
c12cc2 ············{
86788e ················bytesRead = 0;
74a53e ················rerr = kPGPError_TLSWouldBlock; ·
bd7812 ············}
400fe4 ¤   ¤   }
501879 ¤   ¤   if( bytesRead == 0 )
3a5b34 ¤   ¤   {
--3d22 000110bde5b40100246 Page 10 of pgpTLS.c
fcfe7c ¤   ¤   ¤   if( session->blocking )
a7f776 ¤   ¤   ¤   {
fa85bf ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSUnexpectedClose );
7fa3a6 ¤   ¤   ¤   }
babb8c ¤   ¤   ¤   else
65f776 ¤   ¤   ¤   {
4e87a8 ¤   ¤   ¤   ¤   if( rcvd )
3872c3 ¤   ¤   ¤   ¤   {
88bdbe ¤   ¤   ¤   ¤   ¤   err = pgpTLSBufferRawData( session, header,
131e74 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RecordHeaderSize );CKER¶
14cb0b R;
f70ba9 ¤   ¤   ¤   ¤   ¤   err = pgpTLSBufferRawData( session, buffer, rcvd );¤CKERR;
612613 ¤   ¤   ¤   ¤   }
ed00bf ················if(rerr == kPGPError_TLSWouldBlock)
200262 ····················err = kPGPError_TLSWouldBlock;
6283ba ¤   ¤   ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
b143df ¤   ¤   ¤   ¤   buffer = NULL;
6bff25 ¤   ¤   ¤   ¤   goto done;
f7a3a6 ¤   ¤   ¤   }
700fe4 ¤   ¤   }
aa9371 ¤   }
b59b80 ¤   pgpAssert( rcvd == length );
8367c5 ¤
b31e5a ¤   if( IsntNull( session->readActive ) )
d9c7a1 ¤   {
999051 ¤   ¤   PGPByte¤¤   macCheck[32];
db1b52 ¤   ¤
24d0a3 ¤   ¤   if( PGPCBCContextRefIsValid( session->readCipher ) )
ac5b34 ¤   ¤   {
b40324 ¤   ¤   ¤   err = PGPCBCDecrypt( session->readCipher, buffer, length, buffer );
2ac020 ¤   ¤   ¤   CKERR;
ec4048 ¤   ¤   ¤   length -= ( buffer[length - 1] + 1 );
f60fe4 ¤   ¤   }
b02162 ¤   ¤   length -= session->hashSize;
03fd52 ¤   ¤   if( length > kPGPtls_MaximumPacketSize )
115b34 ¤   ¤   {
770283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
f2c161 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
ca681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
dd0fe4 ¤   ¤   }
0772c6 ¤   ¤   err = pgpTLSCalculateMAC( session, FALSE, header[0], buffer, length,
77aa74 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   macCheck ); CKERR;
9dacdb ¤   ¤   if( !pgpMemoryEqual( macCheck, buffer + length, session->hashSize ) )
235b34 ¤   ¤   {
920283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
4c869f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadRecordMAC );
1b681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
ca0fe4 ¤   ¤   }
fb9371 ¤   }
8867c5 ¤
120097 ¤   *outType¤   = header[0];
e758d5 ¤   *outBuffer¤ = buffer;
05e717 ¤   *outLength¤ = length;
99b38c done:
433bfb ¤   if( IsPGPError( err ) && IsntNull( buffer ) )
09c7a1 ¤   {
16f0a3 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
3388b5 ¤   ¤   *outBuffer = NULL;
2e9371 ¤   }
005ea8 ¤   return err;
cbefe6 }
d8af5a
8ec744 ¤   PGPError
1e90a3 pgpTLSReceiveHandshakePacket(
4c2665 ¤   PGPtlsSessionPriv *¤session,
24d57d ¤   PGPByte *¤  ¤   ¤   outType,
89d9a3 ¤   PGPByte **¤ ¤   ¤   outBuffer,
e8a675 ¤   PGPSize *¤  ¤   ¤   outLength )
29bb36 {
66d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
dc1cf1 ¤   PGPByte¤¤   ¤   ¤   rcvdType;
11cdda ¤   PGPByte *¤  ¤   ¤   buffer = NULL;
--3efd 000b4f9bcc340100246 Page 11 of pgpTLS.c
cfc4df ¤   PGPSize¤¤   ¤   ¤   rcvdLen = 0,
33a58e ¤   ¤   ¤   ¤   ¤   ¤   pktLen = 0;
ec67c5 ¤
aaee22 ¤   *outType¤   = 0;
e2b1aa ¤   *outBuffer¤ = NULL;
999f08 ¤   *outLength¤ = 0;
b167c5 ¤
d6efc8 ¤   if( session->handDataSize > 0 )
31c7a1 ¤   {
7a49c4 ¤   ¤   err = pgpTLSExtractHandData( session, &buffer, &rcvdLen );¤ CKERR;
3d9a33 ¤   ¤   rcvdType = kPGPtls_RT_Handshake;
139371 ¤   }
280e24 ¤   else
83c7a1 ¤   {
d1bf40 nextPkt:
4db6f6 ¤   ¤   err = pgpTLSReceiveRecordLayer( session, &rcvdType, &buffer, &rcvdLen );
119371 ¤   }
bfafb3 ¤   if( IsPGPError( err ) || IsNull( buffer ) )
49262d ¤   ¤   goto done;
f0d5f2 ¤   if( rcvdType == kPGPtls_RT_Alert )
2ec7a1 ¤   {
7dfa72 ¤   ¤   err = pgpTLSProcessAlert( session, buffer, rcvdLen ); CKERR;
34f0a3 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
e2b516 ¤   ¤   buffer = NULL;
969f32 ¤   ¤   goto nextPkt;
0b9371 ¤   }
5d9adf ¤   else if( rcvdType == kPGPtls_RT_ChangeCipherSpec )
93c7a1 ¤   {
d810ce ¤   ¤   pgpTLSNextState( session, kPGPtls_EV_ReceiveChangeCipherSpec );
2efa8e ¤   ¤   if( ( rcvdLen == 1 ) && ( buffer[0] == 1 ) &&
7ff8c8 ¤   ¤   ¤   ( session->readActive == NULL ) &&
97eecd ¤   ¤   ¤   ( session->state != kPGPtls_FatalErrorState ) &&
1c1bc2 ¤   ¤   ¤   ( session->isClientSide ? IsntNull( session->serverPending ) :
7c97de ¤   ¤   ¤   IsntNull( session->clientPending ) ) )
585b34 ¤   ¤   {
285534 ¤   ¤   ¤   err = pgpTLSActivateReadKeys( session ); CKERR;
2fcdcd ¤   ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
ec57f7 ¤   ¤   ¤   buffer = NULL;
ca5887 ¤   ¤   ¤   goto nextPkt;
0d0fe4 ¤   ¤   }
980e1d ¤   ¤   else
e65b34 ¤   ¤   {
ca0283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
aaeeec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
23681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
7c0fe4 ¤   ¤   }
839371 ¤   }
50e516 ¤   else if( rcvdType != kPGPtls_RT_Handshake )
41c7a1 ¤   {
d88f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
9aa09b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
d73db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
279371 ¤   }
f0996f ¤   err = pgpTLSExtractHandData( session, &buffer, &rcvdLen );¤ CKERR;
82f3a9 ¤   pktLen = ( buffer[1] << 16 ) | ( buffer[2] << 8 ) | buffer[3];
037faa ¤   if( pktLen + 4 > rcvdLen )
b4c7a1 ¤   {
5a20a7 ¤   ¤   /* handshake packet is fragmented */
4f5cf9 ¤   ¤   err = pgpTLSBufferHandData( session, buffer, rcvdLen );¤CKERR;
c89f32 ¤   ¤   goto nextPkt;
d29371 ¤   }
f37d11 ¤   if( pktLen + 4 < rcvdLen )
7bc7a1 ¤   {
c3e004 ¤   ¤   /* multiple handshake packets were in the record packet */
e7656b ¤   ¤   err = pgpTLSBufferHandData( session, buffer + pktLen + 4,
2fd39d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   rcvdLen - pktLen - 4 );¤CKERR;
099371 ¤   }
aba99f ¤   if( buffer[0] != kPGPtls_HT_HelloRequest )
fbc7a1 ¤   {
f015ca ¤   ¤   if( ( buffer[0] == kPGPtls_HT_Finished ) ||
0aba2d ¤   ¤   ¤   ( buffer[0] == kPGPtls_HT_CertificateVerify ) )
b45b34 ¤   ¤   {
--364b 0000c0b06d440100246 Page 12 of pgpTLS.c
625351 ¤   ¤   ¤   if( PGPHashContextRefIsValid( session->lastHandSHA ) ||
253a10 ¤   ¤   ¤   ¤   PGPHashContextRefIsValid( session->lastHandMD5 ) )
96f776 ¤   ¤   ¤   {
db110f ¤   ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
d0f5e5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
99e749 ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
76a3a6 ¤   ¤   ¤   }
699dd9 ¤   ¤   ¤   err = PGPCopyHashContext( session->handshakeSHA,
6732bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->lastHandSHA);¤CKERR;
ff3cac ¤   ¤   ¤   err = PGPCopyHashContext( session->handshakeMD5,
ab57ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->lastHandMD5);¤CKERR;
840fe4 ¤   ¤   }
c0e3ea ¤   ¤   (void)PGPContinueHash( session->handshakeMD5, buffer, pktLen + 4 );
4d3084 ¤   ¤   (void)PGPContinueHash( session->handshakeSHA, buffer, pktLen + 4 );
429371 ¤   }
8baf5a
e3ad21 ¤   *outType = buffer[0];
55d693 ¤   *outBuffer = buffer;
8edf3d ¤   *outLength = pktLen;
6a56c2 ¤   pgpCopyMemory( buffer + 4, buffer, pktLen );
d5b38c done:
b43bfb ¤   if( IsPGPError( err ) && IsntNull( buffer ) )
0ff0a3 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
165ea8 ¤   return err;
2befe6 }
b6af5a
95c744 ¤   PGPError
035aad pgpTLSProcessAlert(
192665 ¤   PGPtlsSessionPriv *¤session,
56a1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
ca0397 ¤   PGPSize¤¤   ¤   ¤   inLength )
b5bb36 {
a0d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
4e171c ¤   PGPByte¤¤   ¤   ¤   alertType;
25f6c5 ¤   PGPByte¤¤   ¤   ¤   alertLevel;
f367c5 ¤
d81e69 ¤   if( inLength != 2 )
983db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
ed5907 ¤   alertLevel = inBuffer[0];
cdee4a ¤   alertType = inBuffer[1];
b567c5 ¤
ea0bc7 ¤   /* Treat all alerts as fatal except close_notify and no_certificate */
e5865c ¤   if( alertType == kPGPtls_AT_CloseNotify )
f6c7a1 ¤   {
1ee034 ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_WarningAlert,
5776a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_CloseNotify );
9f22da ¤   ¤   session->state = kPGPtls_ClosedState;
099371 ¤   }
3d1976 ¤   else if( alertType == kPGPtls_AT_NoCertificate )
62c7a1 ¤   {
3b4ce8 ¤   ¤   pgpTLSNextState( session, kPGPtls_EV_ReceiveNoCertificate );
47d5f4 ¤   ¤   if( !session->isClientSide )
02d643 ¤   ¤   ¤   session->certRequested = FALSE;
2f9371 ¤   }
d80e24 ¤   else
92c7a1 ¤   {
1d6d1d ¤   ¤   session->fatalAlert = (PGPtlsAlert)alertType;
ea4aa2 #ifdef PGPTLS_DEBUG
3224da ¤   ¤   pgpAssert( 0 );
bf7454 #endif
a824d2 ¤   ¤   pgpTLSNextState( session, kPGPtls_EV_ReceiveFatalAlert );
e29371 ¤   }
ff2ce2 ¤   if( session->state == kPGPtls_FatalErrorState )
d81f14 ¤   ¤   err = kPGPError_TLSAlertReceived;
9767c5 ¤
27b38c done:
805ea8 ¤   return err;
59efe6 }
d0af5a
f9c744 ¤   PGPError
7ffd25 pgpTLSSendRecordLayer(
0c2665 ¤   PGPtlsSessionPriv *¤session,
--09bb 00066c9d7da40100246 Page 13 of pgpTLS.c
b3006a ¤   const PGPByte¤  ¤   inType,
d5f0fa ¤   const PGPByte *¤¤   inBuffer,
4b6183 ¤   const PGPSize¤  ¤   inLength )
56bb36 {
e1d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
c6cdda ¤   PGPByte *¤  ¤   ¤   buffer = NULL;
45222b ¤   PGPSize¤¤   ¤   ¤   bufLen = 0,
ce54ed ¤   ¤   ¤   ¤   ¤   ¤   payloadLen = 0,
926054 ¤   ¤   ¤   ¤   ¤   ¤   padLen = 0;
e46196 ¤   PGPInt32¤   ¤   ¤   serr;
1c67c5 ¤
f65f37 ¤   PGPValidatePtr( inBuffer );
9902d0 ¤   if( inLength > kPGPtls_MaximumPacketSize )
1bc7a1 ¤   {
815974 ¤   ¤   err = kPGPError_BufferTooSmall;
a9cbe8 ¤   ¤   goto done;¤ ¤   ¤   ¤   /* non-fatal */
519371 ¤   }
d28af1 ¤   pgpAssert(¤ ( inType == kPGPtls_RT_ChangeCipherSpec )¤  ||
6d985c ¤   ¤   ¤   ¤   ( inType == kPGPtls_RT_Alert )¤ ¤   ¤   ¤   ||
9d140a ¤   ¤   ¤   ¤   ( inType == kPGPtls_RT_Handshake )¤ ¤   ¤   ||
1802cd ¤   ¤   ¤   ¤   ( inType == kPGPtls_RT_ApplicationData ) );
66af5a
864c8f ¤   if( IsntNull( session->writeActive ) )
abc7a1 ¤   {
c80afd ¤   ¤   if( PGPCBCContextRefIsValid( session->writeCipher ) )
3b5b34 ¤   ¤   {
c4b3c7 ¤   ¤   ¤   padLen = (kPGPtls_CipherBlockSize -
58cce3 ¤   ¤   ¤   ¤   ((inLength + session->hashSize + 1) %
6e939f ¤   ¤   ¤   ¤   ¤   kPGPtls_CipherBlockSize ) );
77f97f ¤   ¤   ¤   if( padLen == kPGPtls_CipherBlockSize )
a146f6 ¤   ¤   ¤   ¤   padLen = 0;
1090e4 ¤   ¤   ¤   bufLen += padLen + 1;
ea0fe4 ¤   ¤   }
3dcc66 ¤   ¤   bufLen += session->hashSize;
249371 ¤   }
b43c87 ¤   bufLen += kPGPtls_RecordHeaderSize + inLength;
bf4594 ¤   payloadLen = bufLen - kPGPtls_RecordHeaderSize;
25497b ¤   buffer ·= PGPNewData( session->memMgr, bufLen, kPGPMemoryMgrFlags_Clear );
3485be ¤   if( IsNull( buffer ) )
b3c7a1 ¤   {
5fbce1 ¤   ¤   err = kPGPError_OutOfMemory;
42262d ¤   ¤   goto done;
ee9371 ¤   }
8e5116 ¤   buffer[0] = inType;
6269f9 ¤   buffer[1] = kPGPtls_MajorVersion;
d9c5b2 ¤   buffer[2] = session->minorVersion;
775376 ¤   PGPUInt16ToEndian( (PGPUInt16) payloadLen, kPGPBigEndian, &buffer[3] );
a4cbc0 ¤   pgpCopyMemory( inBuffer, &buffer[kPGPtls_RecordHeaderSize], inLength );
294c8f ¤   if( IsntNull( session->writeActive ) )
a3c7a1 ¤   {
cb71c4 ¤   ¤   err = pgpTLSCalculateMAC( session, TRUE, inType, inBuffer, inLength,
7d4e3b ¤   ¤   ¤   ¤   ¤   buffer + inLength + kPGPtls_RecordHeaderSize ); CKERR;
3d0afd ¤   ¤   if( PGPCBCContextRefIsValid( session->writeCipher ) )
2f5b34 ¤   ¤   {
ba9eda ¤   ¤   ¤   if( padLen )
b1b5fa ¤   ¤   ¤   ¤   pgpFillMemory( buffer + inLength + session->hashSize +
f4a1a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RecordHeaderSize, padLen + 1, padLen );
36a478 ¤   ¤   ¤   err = PGPCBCEncrypt( session->writeCipher,
8d806c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer + kPGPtls_RecordHeaderSize, payloadLen,
0547c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer + kPGPtls_RecordHeaderSize );CKERR;
590fe4 ¤   ¤   }
089371 ¤   }
f167c5 ¤
f44b68 ¤   err = pgpTLSSendQueueIdleInternal( session );
c53561 ¤   if( err == kPGPError_TLSWouldBlock )
d5a2f9 ¤   ¤   serr = err;
ea67c5 ¤
c905aa ¤   if( IsntPGPError( err ) && ( bufLen > 0 ) )
dcc7a1 ¤   {
155888 ¤   ¤   if( serr != kPGPError_TLSWouldBlock )
8ee71e ¤   ¤   ¤   serr = (session->tlsSendProc)( session->tlsSendUserData,
66bde2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, (PGPInt32) bufLen );
--f99f 00035c9212c40100246 Page 14 of pgpTLS.c
68be6f ¤   ¤   if( serr == kPGPError_TLSWouldBlock )
415b34 ¤   ¤   {
08d431 ¤   ¤   ¤   err = pgpTLSBufferSendData( session, buffer, bufLen ); CKERR;
a0b1fc ¤   ¤   ¤   err = kPGPError_TLSWouldBlock;
b00fe4 ¤   ¤   }
0cecb4 ¤   ¤   else if( (PGPSize)serr != bufLen )
7f86c8 ¤   ¤   ¤   FATALTLS( kPGPError_TLSUnexpectedClose );
5c9371 ¤   }
b4b38c done:
3e44f6 ¤   if( IsntNull( buffer ) )
af80b9 ¤   ¤   (void)PGPFreeData( buffer );
ae5ea8 ¤   return err;
c6efe6 }
2daf5a
d0c744 ¤   PGPError
902af7 pgpTLSSendHandshakePacket(
692665 ¤   PGPtlsSessionPriv *¤session,
30006a ¤   const PGPByte¤  ¤   inType,
6af0fa ¤   const PGPByte *¤¤   inBuffer,
926183 ¤   const PGPSize¤  ¤   inLength )
abbb36 {
6bd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
2ecdda ¤   PGPByte *¤  ¤   ¤   buffer = NULL;
9850fb ¤   PGPByte¤¤   ¤   ¤   prefix[4];
6d4bb3 ¤   PGPUInt16¤  ¤   ¤   pktLen;
1067c5 ¤
8b8a63 ¤   pktLen = inLength + sizeof(prefix);
782262 ¤   prefix[0] = inType;
b7eac0 ¤   prefix[1] = 0;¤ /* 24 bit length first byte */
599c76 ¤   PGPUInt16ToEndian( (PGPUInt16) inLength, kPGPBigEndian, &prefix[2] );
5367c5 ¤
cf9fe7 ¤   buffer = (PGPByte *) pgpContextMemAlloc( session->pgpContext, pktLen, 0 );
9785be ¤   if( IsNull( buffer ) )
5bc7a1 ¤   {
a6bce1 ¤   ¤   err = kPGPError_OutOfMemory;
43262d ¤   ¤   goto done;
b39371 ¤   }
742734 ¤   pgpCopyMemory( prefix, buffer, sizeof(prefix) );
606729 ¤   if( IsntNull( inBuffer ) )
31d93a ¤   ¤   pgpCopyMemory( inBuffer, buffer + sizeof(prefix), inLength );
b667c5 ¤
ecd12d ¤   if( inType != kPGPtls_HT_HelloRequest )
72c7a1 ¤   {
ace868 ¤   ¤   (void)PGPContinueHash(session->handshakeMD5, buffer, pktLen);
0863f8 ¤   ¤   (void)PGPContinueHash(session->handshakeSHA, buffer, pktLen);
569371 ¤   }
63af5a
67ffe1 ¤   err = pgpTLSSendRecordLayer( session, kPGPtls_RT_Handshake,
7194cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen ); CKERR;¤
59b38c done:
ad44f6 ¤   if( IsntNull( buffer ) )
2df0a3 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
365ea8 ¤   return err;
e8efe6 }
efaf5a
79c744 ¤   PGPError
d75d36 pgpTLSSendAlert(
902665 ¤   PGPtlsSessionPriv *¤session,
978037 ¤   PGPByte¤¤   ¤   ¤   level,
9d7dff ¤   PGPtlsAlert¤¤   ¤   type )
1dbb36 {
e4d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
2290a0 ¤   PGPByte¤¤   ¤   ¤   buffer[32];
7f5f55 ¤   PGPSize¤¤   ¤   ¤   pktLen = 0;
bf67c5 ¤
e63db8 ¤   buffer[0] = level;
975b90 ¤   buffer[1] = type;
7c2d76 ¤   pktLen = 2;
0e11c1 ¤   err = pgpTLSSendRecordLayer( session, kPGPtls_RT_Alert, buffer, pktLen );
1aa8c8 ¤   if( level == kPGPtls_AL_FatalAlert )
a1c7a1 ¤   {
352c28 ¤   ¤   session->state¤ ¤   = kPGPtls_FatalErrorState;
--c1c2 0008f7bd80840100246 Page 15 of pgpTLS.c
cffbdd ¤   ¤   session->fatalAlert¤= type;
509371 ¤   }
4e5ea8 ¤   return err;
6befe6 }
d4af5a
7fc744 ¤   PGPError
c1818a pgpTLSSendClientHello(
d5372f ¤   PGPtlsSessionPriv *¤session )
55bb36 {
efd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
585a01 ¤   PGPByte¤¤   ¤   ¤   buffer[384];
242046 ¤   PGPUInt16¤  ¤   ¤   suiteIndex,
65a58e ¤   ¤   ¤   ¤   ¤   ¤   pktLen = 0;
7a67c5 ¤
8408ab ¤   /* client_version */
daad71 ¤   buffer[pktLen++] = kPGPtls_MajorVersion;
b3a88b #ifdef PGPTLS_FORCESSL3
790225 ¤   buffer[pktLen++] = kPGPtls_SSL3MinorVersion;
4fdb21 #else
5f2700 ¤   buffer[pktLen++] = kPGPtls_MinorVersion;¤   /* always latest version */
127454 #endif
c960b1 ¤   /* random */
b62a86 ¤   *((PGPUInt32 *)&session->cRandom[0]) = PGPGetTime();
cc8986 ¤   err = PGPContextGetRandomBytes( session->pgpContext,
c96949 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->cRandom[4],
ad6a21 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSeedSize ); CKERR;
fa5e93 ¤   pgpCopyMemory( session->cRandom, &buffer[pktLen], kPGPtls_RandomSize );
0a9e9d ¤   pktLen += kPGPtls_RandomSize;
20b85c ¤   /* session ID ##### */
8560f0 ¤   buffer[pktLen++] = 0;
35d911 ¤   /* cipher_suites */
117c4b ¤   PGPUInt16ToEndian( (PGPUInt16)( session->numCipherSuites * 2 ),
0988b6 ¤   ¤   ¤   ¤   ¤   ¤   kPGPBigEndian, &buffer[pktLen] );
2e101f ¤   pktLen += sizeof(PGPUInt16);
07392b ¤   for( suiteIndex = 0; suiteIndex < session->numCipherSuites; suiteIndex++ )
59c7a1 ¤   {
9f228c ¤   ¤   buffer[pktLen++] = session->cipherSuites[suiteIndex].id[0];
623e37 ¤   ¤   buffer[pktLen++] = session->cipherSuites[suiteIndex].id[1];
f49371 ¤   }
a04cf6 ¤   /* compression_methods */
b83a2c ¤   buffer[pktLen++] = 1;
68c148 ¤   buffer[pktLen++] = kPGPtls_CT_None;
1b67c5 ¤
795311 ¤   pgpAssert( pktLen < sizeof(buffer) );
8367c5 ¤
d6dea6 ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ClientHello,
049b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
8bb38c done:
345ea8 ¤   return err;
4cefe6 }
1daf5a
92c744 ¤   PGPError
0175f8 pgpTLSSendServerHello(
08372f ¤   PGPtlsSessionPriv *¤session )
65bb36 {
37d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
1d89cb ¤   PGPByte¤¤   ¤   ¤   buffer[128];
bb14b4 ¤   PGPUInt16¤  ¤   ¤   pktLen = 0;
bd67c5 ¤
cc0e17 ¤   /* server_version */
95ad71 ¤   buffer[pktLen++] = kPGPtls_MajorVersion;
149705 ¤   buffer[pktLen++] = session->minorVersion;
a460b1 ¤   /* random */
a9abaa ¤   *((PGPUInt32 *)&session->sRandom[0]) = PGPGetTime();
018986 ¤   err = PGPContextGetRandomBytes( session->pgpContext,
617c91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->sRandom[4],
bf6a21 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSeedSize ); CKERR;
dca977 ¤   pgpCopyMemory( session->sRandom, &buffer[pktLen], kPGPtls_RandomSize );
389e9d ¤   pktLen += kPGPtls_RandomSize;
13c86c ¤   /* session_id ##### */
0660f0 ¤   buffer[pktLen++] = 0;
8f6f93 ¤   /* cipher_suite */
--f0f5 000f249a42440100246 Page 16 of pgpTLS.c
fe4a5a ¤   buffer[pktLen++] = session->cipherSuites[session->cipherSuiteIndex].id[0];
9b56e1 ¤   buffer[pktLen++] = session->cipherSuites[session->cipherSuiteIndex].id[1];
720912 ¤   /* compression_method */
d3c148 ¤   buffer[pktLen++] = kPGPtls_CT_None;
f467c5 ¤
9c5311 ¤   pgpAssert( pktLen < sizeof(buffer) );
ec67c5 ¤
ee2ad4 ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ServerHello,
2b9b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
2db38c done:
de5ea8 ¤   return err;
97efe6 }
5daf5a
06c744 ¤   PGPError
54b734 pgpTLSSendCertificate(
7d372f ¤   PGPtlsSessionPriv *¤session )
ccbb36 {
49d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
eccdda ¤   PGPByte *¤  ¤   ¤   buffer = NULL;
4b14b4 ¤   PGPUInt16¤  ¤   ¤   pktLen = 0;
1054ca ¤   PGPByte *¤  ¤   ¤   keyBuffer = NULL;
dafd04 ¤   PGPSize¤¤   ¤   ¤   keyBufferLen;
d2cc3f ¤   PGPKeySetRef¤   ¤   localKeySet = kInvalidPGPKeySetRef;
8767c5 ¤
1a49e0 ¤   if( session->isClientSide && !session->certMatched )
f4c7a1 ¤   {
b52f7c ¤   ¤   if( session->minorVersion == kPGPtls_SSL3MinorVersion )
535b34 ¤   ¤   {
0f5210 ¤   ¤   ¤   err = pgpTLSSendAlert( session,¤kPGPtls_AL_WarningAlert,
3ab1e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_NoCertificate ); CKERR;
471dc4 ¤   ¤   ¤   goto done;
060fe4 ¤   ¤   }
a44666 ¤   ¤   else if( !session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
6e5b34 ¤   ¤   {
2c98c3 ¤   ¤   ¤   buffer = PGPNewData( session->memMgr, 3, 0 );
411de9 ¤   ¤   ¤   if( IsNull( buffer ) )
65f776 ¤   ¤   ¤   {
06bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
85ff25 ¤   ¤   ¤   ¤   goto done;
81a3a6 ¤   ¤   ¤   }
27deac ¤   ¤   ¤   buffer[pktLen++] = 0;
cadeac ¤   ¤   ¤   buffer[pktLen++] = 0;
01deac ¤   ¤   ¤   buffer[pktLen++] = 0;
ea0fe4 ¤   ¤   }
989371 ¤   }
4be270 ¤   else if( session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
e9c7a1 ¤   {
f12802 ¤   ¤   pgpAssert( PGPKeyRefIsValid( session->localKey ) );
ea1b52 ¤   ¤
dfdb1e ¤   ¤   err = PGPNewSingletonKeySet( session->localKey, &localKeySet );CKERR;
1905a9 ¤   ¤   err = PGPExportKeySet( localKeySet,
2bd645 ¤   ¤   ¤   PGPOAllocatedOutputBuffer( session->pgpContext,
aba30a ¤   ¤   ¤   ¤   (void **) &keyBuffer, MAX_PGPUInt32, &keyBufferLen ),
7c6b90 ¤   ¤   ¤   PGPOArmorOutput( session->pgpContext, FALSE ),
56af12 ¤   ¤   ¤   PGPOLastOption( session->pgpContext ));¤CKERR;
b188b0 ¤   ¤   buffer = PGPNewData( session->memMgr, keyBufferLen + 4, 0 );
df9196 ¤   ¤   if( IsNull( buffer ) )
765b34 ¤   ¤   {
f7b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
661dc4 ¤   ¤   ¤   goto done;
9a0fe4 ¤   ¤   }
70c587 ¤   ¤   buffer[0] = ( keyBufferLen >> 16 ) & 0xFF;
d7fcba ¤   ¤   buffer[1] = ( keyBufferLen >> 8 ) & 0xFF;
824088 ¤   ¤   buffer[2] = keyBufferLen & 0xFF;
1a91fc ¤   ¤   pgpCopyMemory( keyBuffer, &buffer[3], keyBufferLen );
b5b55a ¤   ¤   pktLen = keyBufferLen + 3;
839371 ¤   }
b00e24 ¤   else
28c7a1 ¤   {
75a5b0 ¤   ¤   /* ##### */
2024da ¤   ¤   pgpAssert( 0 );
f29371 ¤   }
--fd89 000a1a82a9b40100246 Page 17 of pgpTLS.c
fde818 ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_Certificate,
e09b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
34b38c done:
4e44f6 ¤   if( IsntNull( buffer ) )
5180b9 ¤   ¤   (void)PGPFreeData( buffer );
eb66b9 ¤   if( IsntNull( keyBuffer ) )
2069bf ¤   ¤   (void)PGPFreeData( keyBuffer );
c62cfd ¤   if( PGPKeySetRefIsValid( localKeySet ) )
a85328 ¤   ¤   PGPFreeKeySet( localKeySet );
735ea8 ¤   return err;
f5efe6 }
6aaf5a
8cc744 ¤   PGPError
d724a1 pgpTLSSendCertVerify(
c975d6 ¤   PGPtlsSessionPriv *¤¤   session )
21bb36 {
6e9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
401778 ¤   PGPByte¤¤   ¤   ¤   ¤   buffer[640],
5888aa ¤   ¤   ¤   ¤   ¤   ¤   ¤   sigData[640];
e47f61 ¤   PGPSize¤¤   ¤   ¤   ¤   pktLen = 0,
e22cf3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sigDataLen;
fb51b5 ¤   PGPPrivateKeyContextRef¤privKeyCon = kInvalidPGPPrivateKeyContextRef;
9f987a ¤   PGPSize¤¤   ¤   ¤   ¤   sigSize,
9e7df3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   actSigSize;
3667c5 ¤
1e9478 ¤   err = PGPNewPrivateKeyContext( session->localKey,
c00808 ¤   ¤   kPGPPublicKeyMessageFormat_PKCS1,
438300 ¤   ¤   &privKeyCon,
8c3099 ¤   ¤   session->localKeyUsePasskey ?
00133b ¤   ¤   PGPOPasskeyBuffer( session->pgpContext, session->localKeyPasskeyBuffer,
4ac6fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->localKeyPasskeySize ) :
94eb28 ¤   ¤   PGPOPassphrase( session->pgpContext, session->localKeyPassphrase ),
0e324a ¤   ¤   PGPOLastOption( session->pgpContext ) );¤   CKERR;
a0c9bf ¤   err = PGPGetPrivateKeyOperationSizes( privKeyCon, NULL, NULL, &sigSize );
8b87ea ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   CKERR;
69af5a
21ae4d ¤   err = pgpTLSCalculateCertVerify( session, sigData, &sigDataLen ); CKERR;
44259e ¤   pgpAssert( sigDataLen < sizeof( sigData ) );
41883e ¤   /* Create the Signature */
ca8093 ¤   PGPUInt16ToEndian( (PGPUInt16) sigSize, kPGPBigEndian, &buffer[pktLen] );
5d101f ¤   pktLen += sizeof(PGPUInt16);
23f109 ¤   err = PGPPrivateKeySignRaw( privKeyCon, sigData, sigDataLen,
28a899 ¤   ¤   ¤   ¤   buffer + pktLen, &actSigSize ); CKERR;
fc3133 ¤   pgpAssert( actSigSize == sigSize );
21ff79 ¤   pktLen += sigSize;
9f5311 ¤   pgpAssert( pktLen < sizeof(buffer) );
60d704 ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_CertificateVerify,
239b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
b5b38c done:
a402d2 ¤   if( PGPPrivateKeyContextRefIsValid( privKeyCon ) )
751af4 ¤   ¤   (void)PGPFreePrivateKeyContext( privKeyCon );
325ea8 ¤   return err;
54efe6 }
9aaf5a
c6c744 ¤   PGPError
e609b2 pgpTLSSendCertificateRequest(
03372f ¤   PGPtlsSessionPriv *¤session )
4ebb36 {
7bd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
425805 ¤   PGPByte¤¤   ¤   ¤   buffer[512];
7a14b4 ¤   PGPUInt16¤  ¤   ¤   pktLen = 0;
f467c5 ¤
8e1c63 ¤   if( session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
c2c7a1 ¤   {
28ad1e ¤   ¤   /* allowed ClientCertificateTypes */
395c1c ¤   ¤   buffer[pktLen++] = 2;
215dfd ¤   ¤   buffer[pktLen++] = kPGPtls_CC_DSASign;
bf0676 ¤   ¤   buffer[pktLen++] = kPGPtls_CC_RSASign;
4e5263 ¤   ¤   /* that's all we need with OpenPGP keys */
2e9371 ¤   }
ed0e24 ¤   else
a1c7a1 ¤   {
--904b 000324d5fe540100246 Page 18 of pgpTLS.c
10a5b0 ¤   ¤   /* ##### */
8724da ¤   ¤   pgpAssert( 0 );
528de5 ¤   ¤   err = kPGPError_FeatureNotAvailable;
229371 ¤   }
3f5311 ¤   pgpAssert( pktLen < sizeof(buffer) );
5e67c5 ¤
c2b1f0 ¤   if( IsntPGPError( err ) )
c2c7a1 ¤   {
030475 ¤   ¤   err = pgpTLSSendHandshakePacket(¤   session,
febce7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HT_CertificateRequest,
d4798d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
9f00ac ¤   ¤   session->certRequested = TRUE;
2e9371 ¤   }
e567c5 ¤
665ea8 ¤   return err;
0defe6 }
e1af5a
23c744 ¤   PGPError
b6fb49 pgpTLSSendServerKeyExchange(
2575d6 ¤   PGPtlsSessionPriv *¤¤   session )
e4bb36 {
709479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
ccbd00 ¤   PGPByte *¤  ¤   ¤   ¤   buffer = NULL;
af2019 ¤   PGPUInt16¤  ¤   ¤   ¤   pktLen = 0;
bb483f ¤   PGPByte *¤  ¤   ¤   ¤   secretX = NULL;
f351b5 ¤   PGPPrivateKeyContextRef¤privKeyCon = kInvalidPGPPrivateKeyContextRef;
76987a ¤   PGPSize¤¤   ¤   ¤   ¤   sigSize,
487df3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   actSigSize;
2a140c ¤   PGPHashContextRef¤  ¤   skeHashSHA = kInvalidPGPHashContextRef,
f2e55c ¤   ¤   ¤   ¤   ¤   ¤   ¤   skeHashMD5 = kInvalidPGPHashContextRef;
a38ac0 ¤   DHPrime *¤  ¤   ¤   ¤   prime;
ecf82e ¤   PGPByte const¤  ¤   ¤   dhGenerator[1] = { 2 };
bdc7e0 ¤   PGPUInt32¤  ¤   ¤   ¤   modBits,
f35aec ¤   ¤   ¤   ¤   ¤   ¤   ¤   modBytes,
fc97b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   expBytes = 0,
85b8d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   expBits,
c033ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   pSize,
ca417a ¤   ¤   ¤   ¤   ¤   ¤   ¤   gSize,
c01bab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ySSize;
2967c5 ¤
449478 ¤   err = PGPNewPrivateKeyContext( session->localKey,
750808 ¤   ¤   kPGPPublicKeyMessageFormat_PKCS1,
428300 ¤   ¤   &privKeyCon,
663099 ¤   ¤   session->localKeyUsePasskey ?
8b133b ¤   ¤   PGPOPasskeyBuffer( session->pgpContext, session->localKeyPasskeyBuffer,
2dc6fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->localKeyPasskeySize ) :
d8eb28 ¤   ¤   PGPOPassphrase( session->pgpContext, session->localKeyPassphrase ),
62324a ¤   ¤   PGPOLastOption( session->pgpContext ) );¤   CKERR;
a1c9bf ¤   err = PGPGetPrivateKeyOperationSizes( privKeyCon, NULL, NULL, &sigSize );
f94339 ¤   CKERR;
7967c5 ¤
a9a3aa ¤   switch( session->requestedPrime )
2dc7a1 ¤   {
f2a9da ¤   ¤   case kPGPtls_DHPrime1024:
927a5e ¤   ¤   ¤   prime = &DH_1024bitPrime;
07cdcb ¤   ¤   ¤   break;
d6268d ¤   ¤   case kPGPtls_DHPrime1536:
e24730 ¤   ¤   ¤   prime = &DH_1536bitPrime;
e3cdcb ¤   ¤   ¤   break;
cf9ae3 ¤   ¤   default:
174b9e ¤   ¤   case kPGPtls_DHPrime2048:
de1c52 ¤   ¤   ¤   prime = &DH_2048bitPrime;
d5cdcb ¤   ¤   ¤   break;
b61902 ¤   ¤   case kPGPtls_DHPrime3072:
48f2de ¤   ¤   ¤   prime = &DH_3072bitPrime;
7bcdcb ¤   ¤   ¤   break;
d1c8f0 ¤   ¤   case kPGPtls_DHPrime4096:
b6d12d ¤   ¤   ¤   prime = &DH_4096bitPrime;
26cdcb ¤   ¤   ¤   break;
ce9371 ¤   }
9af570 ¤   /* Load up the prime modulus */
32464b ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhP ); CKERR;
--7269 000995d4e6340100246 Page 19 of pgpTLS.c
5f71b4 ¤   err = ·PGPBigNumInsertBigEndianBytes(¤  session->dhP,
9473a7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   prime->prime,
e3e581 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, prime->length ); CKERR;
a3709c ¤   /* We always use a generator of 2 for speed */
45d10b ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhG ); CKERR;
9f7824 ¤   err = ·PGPBigNumInsertBigEndianBytes(¤  session->dhG,
a40872 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dhGenerator,
5d678c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, sizeof(dhGenerator) ); CKERR;
5c0317 ¤   modBits¤ = PGPBigNumGetSignificantBits( session->dhP );
39240d ¤   modBytes = ( modBits + 7 ) / 8;
b75f72 ¤   (void)PGPDiscreteLogExponentBits(modBits, &expBytes);
c0c787 ¤   expBytes = ( expBytes * 3 / 2 + 7 ) / 8;
4e2cc0 ¤   expBits ·= 8 * expBytes;
677b01 ¤   secretX ·= PGPNewSecureData( session->memMgr, expBytes, 0 );
52cffe ¤   if( IsNull( secretX ) )
92c7a1 ¤   {
91bce1 ¤   ¤   err = kPGPError_OutOfMemory;
3a262d ¤   ¤   goto done;
9f9371 ¤   }
b96444 ¤   /* Generate the secret random X value */
d8afd9 ¤   err = PGPContextGetRandomBytes( session->pgpContext, secretX, expBytes );
ae4339 ¤   CKERR;
183767 ¤   secretX[0] |= 0x80;
a54ca7 ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhX ); CKERR;
abe42f ¤   err = PGPBigNumInsertBigEndianBytes(session->dhX, secretX, 0, expBytes );
064339 ¤   CKERR;
945161 ¤   /* Generate our server Y value */
57870c ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYs ); CKERR;
78c8b1 ¤   err = PGPBigNumExpMod( session->dhG, session->dhX, session->dhP,
bba793 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->dhYs ); CKERR;
07fb7b ¤   pSize = ( ( PGPBigNumGetSignificantBits( session->dhP ) + 7 ) / 8 );
13360d ¤   gSize = ( ( PGPBigNumGetSignificantBits( session->dhG ) + 7 ) / 8 );
f5b206 ¤   ySSize = ( ( PGPBigNumGetSignificantBits( session->dhYs ) + 7 ) / 8 );
2ab0ff ¤   buffer ·= PGPNewData( session->memMgr,
f90068 ¤   ¤   ¤   ¤   ¤   ¤   ¤   pSize + gSize + ySSize + 8 + sigSize, 0 );
a685be ¤   if( IsNull( buffer ) )
60c7a1 ¤   {
ddbce1 ¤   ¤   err = kPGPError_OutOfMemory;
01262d ¤   ¤   goto done;
9d9371 ¤   }
23b86e ¤   /* Write out p */
a8a2c1 ¤   PGPUInt16ToEndian( (PGPUInt16) pSize, kPGPBigEndian, &buffer[pktLen] );
85101f ¤   pktLen += sizeof(PGPUInt16);
9d04be ¤   err = PGPBigNumExtractBigEndianBytes( session->dhP,
7a665c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &buffer[pktLen],
9202e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, pSize ); CKERR;
afd16c ¤   pktLen += pSize;
343cf2 ¤   /* Write out g */
05c73e ¤   PGPUInt16ToEndian( (PGPUInt16) gSize, kPGPBigEndian, &buffer[pktLen] );
5b101f ¤   pktLen += sizeof(PGPUInt16);
210d2e ¤   err = PGPBigNumExtractBigEndianBytes( session->dhG,
b0665c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &buffer[pktLen],
17112a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, gSize ); CKERR;
84a3bd ¤   pktLen += gSize;
d4b04e ¤   /* Write out yS */
373ffc ¤   PGPUInt16ToEndian( (PGPUInt16) ySSize, kPGPBigEndian, &buffer[pktLen] );
7f101f ¤   pktLen += sizeof(PGPUInt16);
c5b40f ¤   err = PGPBigNumExtractBigEndianBytes( session->dhYs,
84665c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &buffer[pktLen],
4533b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, ySSize ); CKERR;
f9a06a ¤   pktLen += ySSize;
fc8e31 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA,
04f72d ¤   ¤   ¤   ¤   ¤   ¤   &skeHashSHA ); CKERR;
5ab76c ¤   (void)PGPContinueHash( skeHashSHA, session->cRandom, kPGPtls_RandomSize);
b0a87e ¤   (void)PGPContinueHash( skeHashSHA, session->sRandom, kPGPtls_RandomSize);
5151bc ¤   (void)PGPContinueHash( skeHashSHA, buffer, pktLen);
b00cfc ¤   switch( session->cipherSuites[session->cipherSuiteIndex].sigAlg )
27c7a1 ¤   {
317b0a ¤   ¤   case kPGPPublicKeyAlgorithm_DSA:
975b34 ¤   ¤   {
e9f438 ¤   ¤   ¤   PGPByte¤¤   signedData[ kPGPtls_HA_SHASize ];
9987c7 ¤   ¤   ¤
--d2fe 00090304e2d40100246 Page 20 of pgpTLS.c
8b4474 ¤   ¤   ¤   /* Create the Signature */¤ ¤   ¤
62817c ¤   ¤   ¤   (void)PGPFinalizeHash( skeHashSHA, signedData );
a46f90 ¤   ¤   ¤   PGPUInt16ToEndian( (PGPUInt16) sigSize, kPGPBigEndian,
57eb7b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &buffer[pktLen] );
b8289a ¤   ¤   ¤   pktLen += sizeof(PGPUInt16);
4de360 ¤   ¤   ¤   err = PGPPrivateKeySignRaw( privKeyCon, signedData,
eeab0d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_SHASize, buffer + pktLen,
6ffcb0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &actSigSize ); CKERR;
bacdcb ¤   ¤   ¤   break;
3d0fe4 ¤   ¤   }
b7f4d2 ¤   ¤   case kPGPPublicKeyAlgorithm_RSA:
155b34 ¤   ¤   {
184d97 ¤   ¤   ¤   PGPByte¤¤   signedData[kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize];
f887c7 ¤   ¤   ¤
fa0ebe ¤   ¤   ¤   /* Do the additional MD5 hash for RSA */
ffb5e8 ¤   ¤   ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5,
377669 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &skeHashMD5 ); CKERR;
e1b606 ¤   ¤   ¤   (void)PGPContinueHash( skeHashMD5, session->cRandom,
9dfe23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize);
f24992 ¤   ¤   ¤   (void)PGPContinueHash( skeHashMD5, session->sRandom,
20fe23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize);
969167 ¤   ¤   ¤   (void)PGPContinueHash( skeHashMD5, buffer, pktLen);
564a87 ¤   ¤   ¤   (void)PGPFinalizeHash( skeHashMD5, signedData );
f54f65 ¤   ¤   ¤   (void)PGPFinalizeHash( skeHashSHA, signedData +
cf2ec5 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size );
9987c7 ¤   ¤   ¤
db4474 ¤   ¤   ¤   /* Create the Signature */¤ ¤   ¤
426f90 ¤   ¤   ¤   PGPUInt16ToEndian( (PGPUInt16) sigSize, kPGPBigEndian,
a3eb7b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &buffer[pktLen] );
31289a ¤   ¤   ¤   pktLen += sizeof(PGPUInt16);
cde360 ¤   ¤   ¤   err = PGPPrivateKeySignRaw( privKeyCon, signedData,
85562f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize,
f0e19b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer + pktLen, &actSigSize ); CKERR;
bdcdcb ¤   ¤   ¤   break;
280fe4 ¤   ¤   }
741b52 ¤   ¤
d89ae3 ¤   ¤   default:
c2cdcb ¤   ¤   ¤   break;
299371 ¤   }
b93133 ¤   pgpAssert( actSigSize == sigSize );
44ff79 ¤   pktLen += sigSize;
ac67c5 ¤
1a21fd ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ServerKeyExchange,
ad9b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
46b38c done:
120173 ¤   if( IsntNull( secretX ) )
bc7fb5 ¤   ¤   (void)PGPFreeData( secretX );
7a44f6 ¤   if( IsntNull( buffer ) )
f080b9 ¤   ¤   (void)PGPFreeData( buffer );
e802d2 ¤   if( PGPPrivateKeyContextRefIsValid( privKeyCon ) )
c91af4 ¤   ¤   (void)PGPFreePrivateKeyContext( privKeyCon );
49f954 ¤   if( PGPHashContextRefIsValid( skeHashMD5 ) )
3bac6c ¤   ¤   (void)PGPFreeHashContext( skeHashMD5 );
b7f616 ¤   if( PGPHashContextRefIsValid( skeHashSHA ) )
aa9693 ¤   ¤   (void)PGPFreeHashContext( skeHashSHA );
865ea8 ¤   return err;
afefe6 }
a1af5a
4ec744 ¤   PGPError
7f84a8 pgpTLSSendClientKeyExchange(
a375d6 ¤   PGPtlsSessionPriv *¤¤   session )
84bb36 {
069479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
8d8447 ¤   PGPByte¤¤   ¤   ¤   ¤   buffer[1024];
77f880 ¤   PGPUInt16¤  ¤   ¤   ¤   pktLen = 0,
fc80f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   preMasterSize = 0;
f1483f ¤   PGPByte *¤  ¤   ¤   ¤   secretX = NULL;
642b10 ¤   PGPByte *¤  ¤   ¤   ¤   preMaster = NULL;
7ff372 ¤   PGPBigNumRef¤   ¤   ¤   dhSecret = kPGPInvalidBigNumRef;
5d1acb ¤   PGPPublicKeyContextRef¤ pubKeyCon = kInvalidPGPPublicKeyContextRef;
5067c5 ¤
909a13 ¤   if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
--3c76 00061c75cad40100246 Page 21 of pgpTLS.c
f7c7a1 ¤   {
eba58d ¤   ¤   PGPUInt32¤  ¤   modBits,
98b59f ¤   ¤   ¤   ¤   ¤   ¤   modBytes,
7dab5a ¤   ¤   ¤   ¤   ¤   ¤   expBytes = 0,
145d27 ¤   ¤   ¤   ¤   ¤   ¤   expBits;
f81b52 ¤   ¤
6a7741 ¤   ¤   /* Send ClientDiffieHellmanPublic */
a71b52 ¤   ¤
bbc70b ¤   ¤   modBits¤ = PGPBigNumGetSignificantBits( session->dhP );
f0e158 ¤   ¤   modBytes = ( modBits + 7 ) / 8;
f8bd72 ¤   ¤   (void)PGPDiscreteLogExponentBits(modBits, &expBytes);
ab951a ¤   ¤   expBytes = ( expBytes * 3 / 2 + 7 ) / 8;
ad9796 ¤   ¤   expBits ·= 8 * expBytes;
86f144 ¤   ¤   secretX ·= PGPNewSecureData( session->memMgr, expBytes, 0 );
ee62a0 ¤   ¤   if( IsNull( secretX ) )
c65b34 ¤   ¤   {
68b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
f81dc4 ¤   ¤   ¤   goto done;
e00fe4 ¤   ¤   }
2cfd6b ¤   ¤   err = PGPContextGetRandomBytes( session->pgpContext, secretX,
3accf5 ¤   ¤   ¤   ¤   ¤   expBytes );
042283 ¤   ¤   CKERR;
0fc102 ¤   ¤   secretX[0] |= 0x80;
aa9c0c ¤   ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhX ); CKERR;
93b1b4 ¤   ¤   err = PGPBigNumInsertBigEndianBytes(session->dhX, secretX, 0,
3bccf5 ¤   ¤   ¤   ¤   ¤   expBytes );
092283 ¤   ¤   CKERR;
5789dd ¤   ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYc ); CKERR;
77cfc7 ¤   ¤   err = PGPBigNumExpMod( session->dhG, session->dhX, session->dhP,
05e7e7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->dhYc ); CKERR;
d0de55 ¤   ¤   /* Setup outgoing packet, sending client Y with 2 byte length */
5aa5d3 ¤   ¤   PGPUInt16ToEndian( (PGPUInt16) modBytes, kPGPBigEndian, buffer );
ea172f ¤   ¤   err = PGPBigNumExtractBigEndianBytes( session->dhYc,
c58933 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer + sizeof(PGPUInt16),
e3eb98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, modBytes ); CKERR;
cfab1c ¤   ¤   pktLen = modBytes + sizeof(PGPUInt16);
a21b52 ¤   ¤
d7db94 ¤   ¤   /* Calculate the shared secret */
f14397 ¤   ¤   err = PGPNewBigNum( session->memMgr, TRUE, &dhSecret ); CKERR;
b54fa4 ¤   ¤   err = PGPBigNumExpMod( session->dhYs, session->dhX, session->dhP,
8654d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dhSecret ); CKERR;
bc1b52 ¤   ¤
172343 ¤   ¤   /* Load premastersecret with the shared secret */
4bb9ae ¤   ¤   preMasterSize = modBytes;
3a05fd ¤   ¤   preMaster = PGPNewSecureData( session->memMgr, preMasterSize, 0 );
020335 ¤   ¤   if( IsNull( preMaster ) )
ed5b34 ¤   ¤   {
a3b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
f81dc4 ¤   ¤   ¤   goto done;
d10fe4 ¤   ¤   }
2c5c02 ¤   ¤   (void)PGPBigNumExtractBigEndianBytes( dhSecret, preMaster,
831503 ¤   ¤   ¤   ¤   0, modBytes );
399371 ¤   }
260e24 ¤   else
29c7a1 ¤   {
4dedfd ¤   ¤   PGPSize¤¤   ¤   ¤   ¤   encSize;
f01b52 ¤   ¤
22b5df ¤   ¤   /* Send EncryptedPreMasterSecret */
d1c92f ¤   ¤   err = PGPNewPublicKeyContext(¤  session->remoteKey,
918e09 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyMessageFormat_PKCS1,
83c9c6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &pubKeyCon ); CKERR;
265078 ¤   ¤   err = PGPGetPublicKeyOperationSizes( pubKeyCon, NULL,
46ac43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &encSize, NULL );CKERR;
c7b0f3 ¤   ¤   preMasterSize = kPGPtls_MasterSecretSize;
f705fd ¤   ¤   preMaster = PGPNewSecureData( session->memMgr, preMasterSize, 0 );
ed0335 ¤   ¤   if( IsNull( preMaster ) )
dc5b34 ¤   ¤   {
64b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
fc1dc4 ¤   ¤   ¤   goto done;
e60fe4 ¤   ¤   }
0e6a93 ¤   ¤   preMaster[0] = kPGPtls_MajorVersion;
61a88b #ifdef PGPTLS_FORCESSL3
--5821 000a0a49d0c40100246 Page 22 of pgpTLS.c
27cc72 ¤   ¤   preMaster[1] = kPGPtls_SSL3MinorVersion;
d9db21 #else
d90b6b ¤   ¤   preMaster[1] = kPGPtls_MinorVersion;¤   /* always latest version */
027454 #endif
22af33 ¤   ¤   err = PGPContextGetRandomBytes( session->pgpContext,
e39110 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &preMaster[2],
71a46a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize - 2 ); CKERR;
e808b4 ¤   ¤   if( session->minorVersion > kPGPtls_SSL3MinorVersion )
d65b34 ¤   ¤   {
87b1ea ¤   ¤   ¤   PGPUInt16ToEndian( (PGPUInt16) encSize, kPGPBigEndian, buffer );
60289a ¤   ¤   ¤   pktLen += sizeof(PGPUInt16);
8e0fe4 ¤   ¤   }
e8d892 ¤   ¤   err = PGPPublicKeyEncrypt( pubKeyCon, preMaster, preMasterSize,
ba8a3b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer + pktLen, &encSize ); CKERR;
d6b56b ¤   ¤   pktLen += encSize;
649371 ¤   }
df5311 ¤   pgpAssert( pktLen < sizeof(buffer) );
ff67c5 ¤
d25e1c ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ClientKeyExchange,
b39b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
51af5a
e242aa ¤   /* Calculate the Master Secret */
f2ef3a ¤   err = pgpTLSCalculateMasterSecret( session, preMaster, preMasterSize );
ec67c5 ¤
6eb38c done:
c60173 ¤   if( IsntNull( secretX ) )
237fb5 ¤   ¤   (void)PGPFreeData( secretX );
af27fb ¤   if( IsntNull( preMaster ) )
8d37cc ¤   ¤   (void)PGPFreeData( preMaster );
755024 ¤   if( dhSecret != kPGPInvalidBigNumRef )
383b21 ¤   ¤   (void)PGPFreeBigNum( dhSecret );
85b98f ¤   if( PGPPublicKeyContextRefIsValid( pubKeyCon ) )
81b360 ¤   ¤   (void)PGPFreePublicKeyContext( pubKeyCon );
095ea8 ¤   return err;
acefe6 }
6baf5a
08c744 ¤   PGPError
a23359 pgpTLSSendFinished(
05372f ¤   PGPtlsSessionPriv *¤session )
0ebb36 {
f5d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
6289cb ¤   PGPByte¤¤   ¤   ¤   buffer[128];
895f55 ¤   PGPSize¤¤   ¤   ¤   pktLen = 0;
56af5a
92d589 ¤   err = pgpTLSCalculateFinished( session, session->isClientSide,
e0a6a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, &pktLen ); CKERR;
1b0c45 ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_Finished,
069b8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
e3b38c done:
3b5ea8 ¤   return err;
93efe6 }
a3af5a
78c744 ¤   PGPError
cd4bad pgpTLSSendFinalHandshake(·
4a372f ¤   PGPtlsSessionPriv *¤session )
99bb36 {
97d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
9067c5 ¤
325b0c ¤   /* Change the cipher spec */
0d2eba ¤   err = pgpTLSSendChangeCipherSpec( session ); CKERR;
4667c5 ¤
4c1871 ¤   /* Activate the pending client keys */
312ae4 ¤   err = pgpTLSActivateWriteKeys( session ); CKERR;
f967c5 ¤
fec1a1 ¤   /* Signal that our side of the handshake is complete */
93581b ¤   err = pgpTLSSendFinished( session ); CKERR;
5a67c5 ¤
10b38c done:
bb5ea8 ¤   return err;
86efe6 }
3baf5a
a0c744 ¤   PGPError
--19df 000371e4d0340100246 Page 23 of pgpTLS.c
8b694e pgpTLSSendChangeCipherSpec(
4a372f ¤   PGPtlsSessionPriv *¤session )
83bb36 {
fbd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
1af4c4 ¤   PGPByte¤¤   ¤   ¤   buffer[16];
7a14b4 ¤   PGPUInt16¤  ¤   ¤   pktLen = 0;
ff67c5 ¤
20be2a ¤   buffer[0]¤  = 1;
3d03ed ¤   pktLen¤ ¤   = 1;
1e67c5 ¤
c95311 ¤   pgpAssert( pktLen < sizeof(buffer) );
af67c5 ¤
d22667 ¤   err = pgpTLSSendRecordLayer( session, kPGPtls_RT_ChangeCipherSpec,
7198fa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   buffer, pktLen );
d35ea8 ¤   return err;
3fefe6 }
57af5a
f0c744 ¤   PGPError
e6a126 pgpTLSReceiveServerHello(
e72665 ¤   PGPtlsSessionPriv *¤session,
f6a1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
576183 ¤   const PGPSize¤  ¤   inLength )
e5bb36 {
c6d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
32f45d ¤   PGPUInt16¤  ¤   ¤   pktInx = 0,
c649e5 ¤   ¤   ¤   ¤   ¤   ¤   suiteIndex;
b7946c ¤   PGPtlsCipherSuiteID¤cipherID;
7a79bf ¤   Boolean¤¤   ¤   ¤   foundSuite = FALSE;
3167c5 ¤
d65f37 ¤   PGPValidatePtr( inBuffer );
325610 ¤   pgpAssert( inLength >= 38 );
b267c5 ¤
1287a2 ¤   if( inLength < 38 )
dfc7a1 ¤   {
ce8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
857d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
183db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
f99371 ¤   }
950e17 ¤   /* server_version */
85de7a ¤   if( ( inBuffer[pktInx++] != kPGPtls_MajorVersion ) ||
516243 ¤   ¤   ( inBuffer[pktInx] != kPGPtls_MinorVersion &&
05ba2b ¤   ¤   inBuffer[pktInx] != kPGPtls_SSL3MinorVersion ) )
e2c7a1 ¤   {
f48f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
1885a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_ProtocolVersion );
18d5a3 ¤   ¤   FATALTLS( kPGPError_TLSVersionUnsupported );
c89371 ¤   }
03a74d ¤   session->minorVersion = inBuffer[pktInx++];
5037bc ¤   /* server_random */
3e3276 ¤   pgpCopyMemory( &inBuffer[pktInx], session->sRandom,
c90184 ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize );
ead649 ¤   pktInx += kPGPtls_RandomSize;
74b328 ¤   /* session_id */
ecddd7 ¤   pktInx += inBuffer[pktInx] + 1; /* skip for now ##### */
086f93 ¤   /* cipher_suite */
6c1bd6 ¤   cipherID[0] = inBuffer[pktInx++];
791fad ¤   cipherID[1] = inBuffer[pktInx++];
b567c5 ¤
5f392b ¤   for( suiteIndex = 0; suiteIndex < session->numCipherSuites; suiteIndex++ )
76c7a1 ¤   {
d9ac68 ¤   ¤   if( ( cipherID[0] == session->cipherSuites[suiteIndex].id[0] ) &&
2d50d5 ¤   ¤   ¤   ( cipherID[1] == session->cipherSuites[suiteIndex].id[1] ) )
f35b34 ¤   ¤   {
31c85b ¤   ¤   ¤   session->cipherSuiteIndex = suiteIndex;
f62ba7 ¤   ¤   ¤   foundSuite = TRUE;
d5cdcb ¤   ¤   ¤   break;
830fe4 ¤   ¤   }
099371 ¤   }
4b9d4e ¤   if( !foundSuite )
e4c7a1 ¤   {
aa8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
37cae6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_InsufficientSecurity );
--201a 000b3b1b54940100246 Page 24 of pgpTLS.c
333db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
b59371 ¤   }
e90912 ¤   /* compression_method */
a3031a ¤   if( inBuffer[pktInx++] != kPGPtls_CT_None )
99c7a1 ¤   {
ab8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
ee7d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
a23db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
909371 ¤   }
9dc963 ¤   /*¤ do not verify that we have handled all data in this packet,
23052d ¤   ¤   this packet is allowed to contain data we do not understand. */
aab38c done:
625ea8 ¤   return err;
bf1862 }¤
2faf5a
cec744 ¤   PGPError
775554 pgpTLSReceiveClientHello(
bf2665 ¤   PGPtlsSessionPriv *¤session,
b0a1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
a56183 ¤   const PGPSize¤  ¤   inLength )
69bb36 {
4cd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
9cf45d ¤   PGPUInt16¤  ¤   ¤   pktInx = 0,
e2917c ¤   ¤   ¤   ¤   ¤   ¤   suiteIndex,
f279ea ¤   ¤   ¤   ¤   ¤   ¤   numSuites,
a7f5d2 ¤   ¤   ¤   ¤   ¤   ¤   intSuiteIndex;
db946c ¤   PGPtlsCipherSuiteID¤cipherID;
be79bf ¤   Boolean¤¤   ¤   ¤   foundSuite = FALSE;
8367c5 ¤
f45f37 ¤   PGPValidatePtr( inBuffer );
f810e1 ¤   pgpAssert( inLength >= 40 );
f067c5 ¤
2052a6 ¤   if( inLength < 40 )
c4c7a1 ¤   {
5c8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
457d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
f53db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
399371 ¤   }
6567c5 ¤
7708ab ¤   /* client_version */
f5c8f9 ¤   if( inBuffer[pktInx++] != kPGPtls_MajorVersion )
24c7a1 ¤   {
1e8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
9085a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_ProtocolVersion );
4fd5a3 ¤   ¤   FATALTLS( kPGPError_TLSVersionUnsupported );
c69371 ¤   }
57a88b #ifdef PGPTLS_FORCESSL3
4c2d9f ¤   if( inBuffer[pktInx] > kPGPtls_SSL3MinorVersion )
2e4c41 ¤   ¤   session->minorVersion = kPGPtls_SSL3MinorVersion;
a9db21 #else
ab95dc ¤   if( inBuffer[pktInx] > kPGPtls_MinorVersion )
7fd985 ¤   ¤   session->minorVersion = kPGPtls_MinorVersion;
937454 #endif
650e24 ¤   else
c98faa ¤   ¤   session->minorVersion = inBuffer[pktInx];
0daf50 ¤   session->originalClientVersion = inBuffer[pktInx];
724a9a ¤   pktInx++;
4ebbda ¤   /* client_random */
15cde2 ¤   pgpCopyMemory( &inBuffer[pktInx], session->cRandom,
3d0184 ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize );
21d649 ¤   pktInx += kPGPtls_RandomSize;
d8b328 ¤   /* session_id */
ebddd7 ¤   pktInx += inBuffer[pktInx] + 1; /* skip for now ##### */
f9d911 ¤   /* cipher_suites */
d5fc57 ¤   numSuites = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] ) / 2;
6990f5 ¤   pktInx += sizeof(PGPUInt16);
e9a8e3 ¤   if( pktInx + numSuites * sizeof(PGPUInt16) >= inLength )
b5c7a1 ¤   {
268f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
6e7d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
863db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
b39371 ¤   }
--31b5 000d950196540100246 Page 25 of pgpTLS.c
208670 ¤   for( suiteIndex = 0; suiteIndex < numSuites; suiteIndex++ )
62c7a1 ¤   {
962738 ¤   ¤   cipherID[0] = inBuffer[pktInx++];
b92343 ¤   ¤   cipherID[1] = inBuffer[pktInx++];
e9527e ¤   ¤   if( foundSuite )
e317f5 ¤   ¤   ¤   continue;
f00aa9 ¤   ¤   for( intSuiteIndex = 0; intSuiteIndex < session->numCipherSuites;
849478 ¤   ¤   ¤   ¤   intSuiteIndex++ )
fb5b34 ¤   ¤   {
da7167 ¤   ¤   ¤   if( ( cipherID[0] == session->cipherSuites[intSuiteIndex].id[0] ) &&
fd0a60 ¤   ¤   ¤   ·¤  ( cipherID[1] == session->cipherSuites[intSuiteIndex].id[1] ) )
b4f776 ¤   ¤   ¤   {
dfb398 ¤   ¤   ¤   ¤   if( session->localKeyAlg ==
1b4457 ¤   ¤   ¤   ¤   ¤   session->cipherSuites[intSuiteIndex].sigAlg )
fc72c3 ¤   ¤   ¤   ¤   {
67fd46 ¤   ¤   ¤   ¤   ¤   session->cipherSuiteIndex = intSuiteIndex;
a4e62b ¤   ¤   ¤   ¤   ¤   foundSuite = TRUE;
b12613 ¤   ¤   ¤   ¤   }
8ea3a6 ¤   ¤   ¤   }
060fe4 ¤   ¤   }
fa9371 ¤   }
839d4e ¤   if( !foundSuite )
87c7a1 ¤   {
fe8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
3dcae6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_InsufficientSecurity );
a14fe9 ¤   ¤   FATALTLS( kPGPError_TLSNoCommonCipher );
c99371 ¤   }
754cf6 ¤   /* compression_methods */
8efb91 ¤   /* Nobody actually supports this, it's only in the spec for looks */
a73cd8 ¤   pktInx += inBuffer[pktInx];
5067c5 ¤
a8c963 ¤   /*¤ do not verify that we have handled all data in this packet,
12052d ¤   ¤   this packet is allowed to contain data we do not understand. */
f867c5 ¤
a9dbe0 ¤   err = pgpTLSSendServerHello( session );¤CKERR;
5cd592 ¤   err = pgpTLSSendCertificate( session );¤CKERR;
a29a13 ¤   if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
85c7a1 ¤   {
1736ec ¤   ¤   err = pgpTLSSendServerKeyExchange( session );¤  CKERR;
3e9371 ¤   }
ca0fa2 ¤   if( session->requestCert )
58c7a1 ¤   {
eb858c ¤   ¤   err = pgpTLSSendCertificateRequest( session );¤ CKERR;
069371 ¤   }
67f544 ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_ServerHelloDone,
03ad55 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, 0 ); CKERR;
39b38c done:
135ea8 ¤   return err;
9e1862 }¤
c7af5a
c2c744 ¤   PGPError
b92aee pgpTLSReceiveClientKeyExchange(
6cdb25 ¤   PGPtlsSessionPriv *¤¤   session,
051fe2 ¤   PGPByte *¤  ¤   ¤   ¤   inBuffer,
b35820 ¤   const PGPSize¤  ¤   ¤   inLength )
44bb36 {
a79479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
5b1869 ¤   PGPUInt16¤  ¤   ¤   ¤   pktInx = 0;
3a50b7 ¤   PGPSize¤¤   ¤   ¤   ¤   preMasterSize = 0;
e2f372 ¤   PGPBigNumRef¤   ¤   ¤   dhSecret = kPGPInvalidBigNumRef;
d52b10 ¤   PGPByte *¤  ¤   ¤   ¤   preMaster = NULL;
9551b5 ¤   PGPPrivateKeyContextRef¤privKeyCon = kInvalidPGPPrivateKeyContextRef;
2867c5 ¤
ba5f37 ¤   PGPValidatePtr( inBuffer );
a867c5 ¤
149a13 ¤   if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
67c7a1 ¤   {
93845e ¤   ¤   PGPUInt32¤  ¤   modBytes,
89af5a
fda5e8 ¤   ¤   varLen = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] );
35ad9d ¤   ¤   pktInx += sizeof(PGPUInt16);
d989dd ¤   ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYc ); CKERR;
--0a55 00010999cfd40100246 Page 26 of pgpTLS.c
82151a ¤   ¤   err = PGPBigNumInsertBigEndianBytes(session->dhYc, &inBuffer[pktInx],
93b9f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, varLen ); CKERR;
43e31c ¤   ¤   pktInx += varLen;
531b52 ¤   ¤
f29340 ¤   ¤   if( pktInx != inLength )
755b34 ¤   ¤   {
b20283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
a0eeec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
f9681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
dc0fe4 ¤   ¤   }
a1af5a
2fdb94 ¤   ¤   /* Calculate the shared secret */
ce4397 ¤   ¤   err = PGPNewBigNum( session->memMgr, TRUE, &dhSecret ); CKERR;
bb7c28 ¤   ¤   err = PGPBigNumExpMod( session->dhYc, session->dhX, session->dhP,
c354d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dhSecret ); CKERR;
fa2343 ¤   ¤   /* Load premastersecret with the shared secret */
0cb576 ¤   ¤   modBytes = ( PGPBigNumGetSignificantBits( session->dhYc ) + 7 ) / 8;
ecb9ae ¤   ¤   preMasterSize = modBytes;
ad05fd ¤   ¤   preMaster = PGPNewSecureData( session->memMgr, preMasterSize, 0 );
db0335 ¤   ¤   if( IsNull( preMaster ) )
785b34 ¤   ¤   {
ebb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
cc1dc4 ¤   ¤   ¤   goto done;
fe0fe4 ¤   ¤   }
875c02 ¤   ¤   (void)PGPBigNumExtractBigEndianBytes( dhSecret, preMaster,
0b997c ¤   ¤   ¤   ¤   ¤   0, modBytes );
f29371 ¤   }
3a0e24 ¤   else
a0c7a1 ¤   {
cf3a0b ¤   ¤   PGPSize¤¤   decSize,
60068a ¤   ¤   ¤   ¤   ¤   encSize;
f81b52 ¤   ¤
b5970f ¤   ¤   err = PGPNewPrivateKeyContext( session->localKey,
4531cd ¤   ¤   ¤   kPGPPublicKeyMessageFormat_PKCS1,
dc32d1 ¤   ¤   ¤   &privKeyCon,
150c77 ¤   ¤   ¤   session->localKeyUsePasskey ?
5bb9db ¤   ¤   ¤   PGPOPasskeyBuffer( session->pgpContext,
c4ce4c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->localKeyPasskeyBuffer,
151cd5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->localKeyPasskeySize ) :
32be78 ¤   ¤   ¤   PGPOPassphrase( session->pgpContext, session->localKeyPassphrase ),
da32a8 ¤   ¤   ¤   PGPOLastOption( session->pgpContext ) );¤   CKERR;
6f9961 ¤   ¤   err = PGPGetPrivateKeyOperationSizes( privKeyCon, &decSize, &encSize,
354506 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL ); CKERR;
c51eec ¤   ¤   if( inLength != encSize )
275b34 ¤   ¤   {
5ec550 ¤   ¤   ¤   if( inLength == encSize + sizeof(PGPUInt16) )
1ff776 ¤   ¤   ¤   {
420d1f ¤   ¤   ¤   ¤   /* The TLS specification doesn't specify what to do here, wheth¶
ac50de er
102878 ¤   ¤   ¤   ¤   ¤   a length should be used or not, but it appears that TLS
afc62e ¤   ¤   ¤   ¤   ¤   implementations based on mailing list discussions have chan¶
995f5a ged
e4ee2b ¤   ¤   ¤   ¤   ¤   the protocol to put a length here. ·Since this is thoroughly
9e4943 ¤   ¤   ¤   ¤   ¤   irrelevant to anything, we always read both for now. */
4bf1dd ¤   ¤   ¤   ¤   if( encSize != PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktI¶
f917f9 nx] ) )
6d72c3 ¤   ¤   ¤   ¤   {
bfc1a4 ¤   ¤   ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
e62dcf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecryptionFailed );
8d2355 ¤   ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
ff2613 ¤   ¤   ¤   ¤   }
9bfa07 ¤   ¤   ¤   ¤   else
6efc55 ¤   ¤   ¤   ¤   ¤   pktInx += sizeof(PGPUInt16);
93a3a6 ¤   ¤   ¤   }
d6bb8c ¤   ¤   ¤   else
acf776 ¤   ¤   ¤   {
c3110f ¤   ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
48c0e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecryptionFailed );
fee749 ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
caa3a6 ¤   ¤   ¤   }
2d0fe4 ¤   ¤   }
1062bf ¤   ¤   preMasterSize = decSize;
--2924 0002e9ec99140100246 Page 27 of pgpTLS.c
783741 ¤   ¤   preMaster = PGPNewSecureData( session->memMgr, decSize, 0 );
f70335 ¤   ¤   if( IsNull( preMaster ) )
165b34 ¤   ¤   {
d4b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
531dc4 ¤   ¤   ¤   goto done;
3a0fe4 ¤   ¤   }
895a09 ¤   ¤   err = PGPPrivateKeyDecrypt( privKeyCon, &inBuffer[pktInx], encSize,
8a113e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   preMaster, &preMasterSize );
291b52 ¤   ¤
4ed78b ¤   ¤   /* The following code shifts all error conditions at this point
923a43 ¤   ¤   ¤   into a secret error condition that we do not explicitly
60d926 ¤   ¤   ¤   report here. ·This is designed to prevent the Bleichenbacher
b6655a ¤   ¤   ¤   attack against the PKCS-1 padding of SSL when using RSA
50948c ¤   ¤   ¤   keys. ·All errors at this stage set the preMaster secret to
59788b ¤   ¤   ¤   random data thus causing errors later in the protocol and
873c2d ¤   ¤   ¤   not allowing an attacker to get a specific protocol version
990565 ¤   ¤   ¤   alert or decryption failed alert here.¤ */
1aa25b ¤   ¤   if( IsPGPError( err ) ||
03c9c0 ¤   ¤   ¤   ( preMasterSize != kPGPtls_MasterSecretSize ) ||
6bc046 ¤   ¤   ¤   ( preMaster[0] != kPGPtls_MajorVersion ) ||
08b23c ¤   ¤   ¤   ( preMaster[1] != session->originalClientVersion ) )
4e5b34 ¤   ¤   {
5b1ef2 ¤   ¤   ¤   preMasterSize = kPGPtls_MasterSecretSize;
26751a ¤   ¤   ¤   err = PGPContextGetRandomBytes( session->pgpContext,
62898b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &preMaster, preMasterSize ); CKERR;
2f0fe4 ¤   ¤   }
9c9371 ¤   }
b542aa ¤   /* Calculate the Master Secret */
2def3a ¤   err = pgpTLSCalculateMasterSecret( session, preMaster, preMasterSize );
8b67c5 ¤
648f12 ¤   /* Calculate the Keys */
981ad9 ¤   err = pgpTLSCalculateKeys( session ); CKERR;
27af5a
d9b38c done:
6b5024 ¤   if( dhSecret != kPGPInvalidBigNumRef )
ce3b21 ¤   ¤   (void)PGPFreeBigNum( dhSecret );
c427fb ¤   if( IsntNull( preMaster ) )
d137cc ¤   ¤   (void)PGPFreeData( preMaster );
a002d2 ¤   if( PGPPrivateKeyContextRefIsValid( privKeyCon ) )
a71af4 ¤   ¤   (void)PGPFreePrivateKeyContext( privKeyCon );
8f5ea8 ¤   return err;
d21862 }¤
26af5a
f2c744 ¤   PGPError
6b6753 pgpTLSReceiveCertVerify(
6e2665 ¤   PGPtlsSessionPriv *¤session,
3aa1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
646183 ¤   const PGPSize¤  ¤   inLength )
debb36 {
869479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
e9420f ¤   PGPByte¤¤   ¤   ¤   ¤   sigData[640];
cd7a18 ¤   PGPUInt16¤  ¤   ¤   ¤   sigLen;
304711 ¤   PGPSize¤¤   ¤   ¤   ¤   pktInx = 0,
e82cf3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sigDataLen;
7d1acb ¤   PGPPublicKeyContextRef¤ pubKeyCon = kInvalidPGPPublicKeyContextRef;
fa67c5 ¤
71861d ¤   if( !PGPKeyRefIsValid( session->remoteKey ) )
42c7a1 ¤   {
bd8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
ed628a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
913db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
cc9371 ¤   }
9d4678 ¤   err = PGPNewPublicKeyContext(¤  session->remoteKey,
d298bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyMessageFormat_PKCS1,
77ef73 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &pubKeyCon ); CKERR;
0eaf5a
cdae4d ¤   err = pgpTLSCalculateCertVerify( session, sigData, &sigDataLen ); CKERR;
75259e ¤   pgpAssert( sigDataLen < sizeof( sigData ) );
8567c5 ¤
cbd392 ¤   /* Verify the Signature */
d29658 ¤   sigLen = PGPEndianToUInt16( kPGPBigEndian, inBuffer );
2e90f5 ¤   pktInx += sizeof(PGPUInt16);
--c090 000237146b540100246 Page 28 of pgpTLS.c
3f9f85 ¤   err = PGPPublicKeyVerifyRaw( pubKeyCon, sigData, sigDataLen,
31b365 ¤   ¤   ¤   ¤   inBuffer + pktInx, sigLen );
2c3b13 ¤   pktInx += sigLen;
9aa18a ¤   if( IsPGPError(err) || ( pktInx != inLength ) )
69c7a1 ¤   {
888f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
77628a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
583db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
069371 ¤   }
a4df47 ¤   session->certVerified = TRUE;
3ab38c done:
7ab98f ¤   if( PGPPublicKeyContextRefIsValid( pubKeyCon ) )
01b360 ¤   ¤   (void)PGPFreePublicKeyContext( pubKeyCon );
a65ea8 ¤   return err;
061862 }¤
deaf5a
42c744 ¤   PGPError
5363ea pgpTLSReceiveCertificate(
b12665 ¤   PGPtlsSessionPriv *¤session,
98a1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
5c6183 ¤   const PGPSize¤  ¤   inLength )
05bb36 {
0ed591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
31607f ¤   PGPUInt32¤  ¤   ¤   certListLen,
ae1339 ¤   ¤   ¤   ¤   ¤   ¤   certLen;
05f341 ¤   PGPUInt32¤  ¤   ¤   numKeys;
d7998a ¤   PGPKeyListRef¤  ¤   keyList = kInvalidPGPKeyListRef;
201670 ¤   PGPKeyIterRef¤  ¤   keyIter = kInvalidPGPKeyIterRef;
6240bc ¤   PGPBoolean¤ ¤   ¤   keyVerify;
6867c5 ¤
f85f37 ¤   PGPValidatePtr( inBuffer );
af67c5 ¤
2de89c ¤   if( !session->isClientSide )
31c7a1 ¤   {
120ad5 ¤   ¤   if( session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
775b34 ¤   ¤   {
a36c40 ¤   ¤   ¤   if( inLength == 0)
b0f776 ¤   ¤   ¤   {
69ce13 ¤   ¤   ¤   ¤   session->certRequested = FALSE;
36ff25 ¤   ¤   ¤   ¤   goto done;
0ea3a6 ¤   ¤   ¤   }
820fe4 ¤   ¤   }
a558e5 ¤   ¤   else if( inLength == 3 )
2c5b34 ¤   ¤   {
8030a8 ¤   ¤   ¤   certListLen = ( inBuffer[0] << 16 ) | ( inBuffer[1] << 8 )
d83473 ¤   ¤   ¤   ¤   ¤   ¤   | inBuffer[2];
05bdd7 ¤   ¤   ¤   if( certListLen == 0)
eef776 ¤   ¤   ¤   {
5fce13 ¤   ¤   ¤   ¤   session->certRequested = FALSE;
0aff25 ¤   ¤   ¤   ¤   goto done;
56a3a6 ¤   ¤   ¤   }
250fe4 ¤   ¤   }
ae9371 ¤   }
ed1c63 ¤   if( session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
89c7a1 ¤   {
9100bf ¤   ¤   certLen = ( inBuffer[0] << 16 ) | ( inBuffer[1] << 8 )
a87580 ¤   ¤   ¤   ¤   ¤   | inBuffer[2];
dcb797 ¤   ¤   if( certLen + 3 != inLength )
e25b34 ¤   ¤   {
c30283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
11c161 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
a0681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
670fe4 ¤   ¤   }
6225bb ¤   ¤   err = PGPImportKeySet( session->pgpContext, &session->remoteKeySet,
a61d90 ¤   ¤   ¤   ¤   ¤   PGPOInputBuffer( session->pgpContext,
ab914c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &inBuffer[3], certLen ),
e97017 ¤   ¤   ¤   ¤   ¤   PGPOLastOption( session->pgpContext ) );
24d223 ¤   ¤   if( IsPGPError( err ) )
a15b34 ¤   ¤   {
470283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
ebe8cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
23681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
--9ae6 000a9bb676d40100246 Page 29 of pgpTLS.c
b50fe4 ¤   ¤   }
0e1a55 ¤   ¤   err = PGPCountKeys( session->remoteKeySet, &numKeys );
e119c8 ¤   ¤   if( numKeys != 1 )
105b34 ¤   ¤   {
8df93f ¤   ¤   ¤   err = PGPFreeKeySet( session->remoteKeySet );
0931e2 ¤   ¤   ¤   session->remoteKeySet = kInvalidPGPKeySetRef;
910283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
00e8cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
15681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
740fe4 ¤   ¤   }
b39371 ¤   }
cf0e24 ¤   else
aac7a1 ¤   {
952324 ¤   ¤   certListLen = ( inBuffer[0] << 16 ) | ( inBuffer[1] << 8 )
587580 ¤   ¤   ¤   ¤   ¤   | inBuffer[2];
b32857 ¤   ¤   certLen = ·( inBuffer[3] << 16 ) | ( inBuffer[4] << 8 )
d722a1 ¤   ¤   ¤   ¤   ¤   | inBuffer[5];
fba0c1 ¤   ¤   if( certLen + 6 > inLength )
855b34 ¤   ¤   {
5c0283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
4fc161 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
98681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
cb0fe4 ¤   ¤   }
6925bb ¤   ¤   err = PGPImportKeySet( session->pgpContext, &session->remoteKeySet,
c81d90 ¤   ¤   ¤   ¤   ¤   PGPOInputBuffer( session->pgpContext,
19f1df ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &inBuffer[6], certLen ),
49005a ¤   ¤   ¤   ¤   ¤   PGPOX509Encoding( session->pgpContext, TRUE ),
0c7017 ¤   ¤   ¤   ¤   ¤   PGPOLastOption( session->pgpContext ) );
d1d223 ¤   ¤   if( IsPGPError( err ) )
cb5b34 ¤   ¤   {
8e0283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
77e8cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
7d681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
7b0fe4 ¤   ¤   }
ee1a55 ¤   ¤   err = PGPCountKeys( session->remoteKeySet, &numKeys );
0519c8 ¤   ¤   if( numKeys != 1 )
2d5b34 ¤   ¤   {
32f93f ¤   ¤   ¤   err = PGPFreeKeySet( session->remoteKeySet );
8131e2 ¤   ¤   ¤   session->remoteKeySet = kInvalidPGPKeySetRef;
160283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
54e8cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
4c681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
c90fe4 ¤   ¤   }
a59371 ¤   }
f712d7 ¤   /* Get just the one key out of it */
ebdaec ¤   err = PGPOrderKeySet( session->remoteKeySet, kPGPAnyOrdering,·
383726 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyList );¤CKERR;
36857d ¤   err = PGPNewKeyIter( keyList, &keyIter ); CKERR;
ae6da8 ¤   err = PGPKeyIterNext( keyIter, &session->remoteKey ); CKERR;
07bab7 ¤   err = PGPGetKeyNumber( session->remoteKey, kPGPKeyPropAlgID,
00e645 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ( PGPInt32 * ) &session->remoteKeyAlg );CKERR;
6496cc ¤   err = PGPGetKeyBoolean( session->remoteKey, kPGPKeyPropCanVerify,
ac1dea ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyVerify );¤  CKERR;
1c67c5 ¤
6380dc ¤   if( !keyVerify || !pubAlgSupported( session->remoteKeyAlg ) ||
f4aa0d ¤   ¤   ( session->isClientSide && ( session->remoteKeyAlg !=
b56cae ¤   ¤   session->cipherSuites[session->cipherSuiteIndex].sigAlg ) ) )
1dc7a1 ¤   {
f08f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
74628a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
983db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
969371 ¤   }
c9aefe ¤   if( session->isClientSide )
58c7a1 ¤   {
a39d65 ¤   ¤   if( session->cipherSuites[session->cipherSuiteIndex].ephemeral )
007fdc ¤   ¤   ¤   pgpTLSNextState( session, kPGPtls_EV_EphemeralCertificate );
e70e1d ¤   ¤   else
6898f1 ¤   ¤   ¤   pgpTLSNextState( session, kPGPtls_EV_StaticCertificate );
1b9371 ¤   }
6cb38c done:
ced0ad ¤   if( PGPKeyListRefIsValid( keyList ) )
a96efb ¤   ¤   PGPFreeKeyList( keyList );
--3342 00010a09bcc40100246 Page 30 of pgpTLS.c
10d661 ¤   if( PGPKeyIterRefIsValid( keyIter ) )
9910a7 ¤   ¤   PGPFreeKeyIter( keyIter );
3e5ea8 ¤   return err;
3aefe6 }
caaf5a
8ac744 ¤   PGPError
c0550f pgpTLSReceiveServerKeyExchange(
43db25 ¤   PGPtlsSessionPriv *¤¤   session,
361fe2 ¤   PGPByte *¤  ¤   ¤   ¤   inBuffer,
415820 ¤   const PGPSize¤  ¤   ¤   inLength )
bdbb36 {
6a9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
18c0f0 ¤   PGPUInt16¤  ¤   ¤   ¤   pktInx = 0,
d2d498 ¤   ¤   ¤   ¤   ¤   ¤   ¤   varLen;
34140c ¤   PGPHashContextRef¤  ¤   skeHashSHA = kInvalidPGPHashContextRef,
e8e55c ¤   ¤   ¤   ¤   ¤   ¤   ¤   skeHashMD5 = kInvalidPGPHashContextRef;
dc40e3 ¤   PGPSize¤¤   ¤   ¤   ¤   sigSize;
041acb ¤   PGPPublicKeyContextRef¤ pubKeyCon = kInvalidPGPPublicKeyContextRef;
9767c5 ¤
9b5f37 ¤   PGPValidatePtr( inBuffer );
fa67c5 ¤
664678 ¤   err = PGPNewPublicKeyContext(¤  session->remoteKey,
0998bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyMessageFormat_PKCS1,
c3ef73 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &pubKeyCon ); CKERR;
fb6341 ¤   err = PGPGetPublicKeyOperationSizes( pubKeyCon, NULL, NULL, &sigSize );
2f4339 ¤   CKERR;
fbaf5a
43dd71 ¤   /* Parse the p value */
23eb9f ¤   varLen = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] );
7d90f5 ¤   pktInx += sizeof(PGPUInt16);
b1464b ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhP ); CKERR;
7d71b4 ¤   err = ·PGPBigNumInsertBigEndianBytes(¤  session->dhP,
33ef10 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &inBuffer[pktInx],
63b9f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, varLen ); CKERR;
6224a9 ¤   pktInx += varLen;
c90cd2 ¤   /* Parse the g value */
9beb9f ¤   varLen = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] );
2a90f5 ¤   pktInx += sizeof(PGPUInt16);
e0d10b ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhG ); CKERR;
837824 ¤   err = ·PGPBigNumInsertBigEndianBytes(¤  session->dhG,
9bef10 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &inBuffer[pktInx],
77b9f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, varLen ); CKERR;
5724a9 ¤   pktInx += varLen;
4120be ¤   /* Parse the server y value */
edeb9f ¤   varLen = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] );
3390f5 ¤   pktInx += sizeof(PGPUInt16);
c5870c ¤   err = PGPNewBigNum( session->memMgr, TRUE, &session->dhYs ); CKERR;
bb1b20 ¤   err = ·PGPBigNumInsertBigEndianBytes(¤  session->dhYs,
3aef10 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &inBuffer[pktInx],
23b9f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, varLen ); CKERR;
7d24a9 ¤   pktInx += varLen;
37af5a
14eb9f ¤   varLen = PGPEndianToUInt16( kPGPBigEndian, &inBuffer[pktInx] );
f353f2 ¤   if( ( varLen != sigSize ) || ( pktInx + 2 + sigSize != inLength ) )
0bc7a1 ¤   {
6a8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
977d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
9a3db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
179371 ¤   }
cb8e31 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA,
49f72d ¤   ¤   ¤   ¤   ¤   ¤   &skeHashSHA ); CKERR;
e6b76c ¤   (void)PGPContinueHash( skeHashSHA, session->cRandom, kPGPtls_RandomSize);
0ea87e ¤   (void)PGPContinueHash( skeHashSHA, session->sRandom, kPGPtls_RandomSize);
0e2495 ¤   (void)PGPContinueHash( skeHashSHA, inBuffer, pktInx);
6467c5 ¤
110cfc ¤   switch( session->cipherSuites[session->cipherSuiteIndex].sigAlg )
40c7a1 ¤   {
837b0a ¤   ¤   case kPGPPublicKeyAlgorithm_DSA:
905b34 ¤   ¤   {
61f438 ¤   ¤   ¤   PGPByte¤¤   signedData[ kPGPtls_HA_SHASize ];
3f87c7 ¤   ¤   ¤
10a870 ¤   ¤   ¤   pktInx += sizeof(PGPUInt16);
--6db3 000cd01f9a240100246 Page 31 of pgpTLS.c
ba7d34 ¤   ¤   ¤   /* Verify the Signature */¤ ¤   ¤
76817c ¤   ¤   ¤   (void)PGPFinalizeHash( skeHashSHA, signedData );
3967d8 ¤   ¤   ¤   err = PGPPublicKeyVerifyRaw( pubKeyCon, signedData,
9cc4ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_SHASize, inBuffer + pktInx,
822b4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sigSize );
8acdcb ¤   ¤   ¤   break;
510fe4 ¤   ¤   }
0bf4d2 ¤   ¤   case kPGPPublicKeyAlgorithm_RSA:
d25b34 ¤   ¤   {
09144f ¤   ¤   ¤   PGPByte¤¤   signedData[ kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize ];
d987c7 ¤   ¤   ¤
4fa20e ¤   ¤   ¤   /* Hash the client/server randoms and the first part of packet */
2ab5e8 ¤   ¤   ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5,
3c7669 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &skeHashMD5 ); CKERR;
1fb606 ¤   ¤   ¤   (void)PGPContinueHash( skeHashMD5, session->cRandom,
90fe23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize);
984992 ¤   ¤   ¤   (void)PGPContinueHash( skeHashMD5, session->sRandom,
9bfe23 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize);
0a590a ¤   ¤   ¤   (void)PGPContinueHash( skeHashMD5, inBuffer, pktInx);
1287c7 ¤   ¤   ¤
1ea870 ¤   ¤   ¤   pktInx += sizeof(PGPUInt16);
717d34 ¤   ¤   ¤   /* Verify the Signature */¤ ¤   ¤
004a87 ¤   ¤   ¤   (void)PGPFinalizeHash( skeHashMD5, signedData );
7c4f65 ¤   ¤   ¤   (void)PGPFinalizeHash( skeHashSHA, signedData +
bd2ec5 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size );
5087c7 ¤   ¤   ¤
7c67d8 ¤   ¤   ¤   err = PGPPublicKeyVerifyRaw( pubKeyCon, signedData,
24562f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize,
64af1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   inBuffer + pktInx, sigSize );
72cdcb ¤   ¤   ¤   break;
4f0fe4 ¤   ¤   }
5c1b52 ¤   ¤
449ae3 ¤   ¤   default:
94cdcb ¤   ¤   ¤   break;
c79371 ¤   }
afbdc8 ¤   if( IsPGPError(err) )
d8c7a1 ¤   {
e98f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
ed628a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_BadCertificate );
c73db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
f49371 ¤   }
d3b38c done:
61f954 ¤   if( PGPHashContextRefIsValid( skeHashMD5 ) )
2fac6c ¤   ¤   (void)PGPFreeHashContext( skeHashMD5 );
48f616 ¤   if( PGPHashContextRefIsValid( skeHashSHA ) )
fe9693 ¤   ¤   (void)PGPFreeHashContext( skeHashSHA );
a1b98f ¤   if( PGPPublicKeyContextRefIsValid( pubKeyCon ) )
19b360 ¤   ¤   (void)PGPFreePublicKeyContext( pubKeyCon );
a11b52 ¤   ¤
8e5ea8 ¤   return err;
3d1862 }¤
8aaf5a
ddc744 ¤   PGPError
7fdc4d pgpTLSReceiveCertRequest(
c52665 ¤   PGPtlsSessionPriv *¤session,
4ea1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
416183 ¤   const PGPSize¤  ¤   inLength )
75bb36 {
4fd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
5e2cc4 ¤   PGPUInt16¤  ¤   ¤   pktInx = 0;
589cab ¤   PGPUInt16¤  ¤   ¤   numCertTypes;
0867c5 ¤
c75f37 ¤   PGPValidatePtr( inBuffer );
ea67c5 ¤
8c1bcf ¤   numCertTypes = inBuffer[pktInx++];
a0cb55 ¤   if( (PGPSize) ( pktInx + numCertTypes ) > inLength )
30c7a1 ¤   {
ef8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
3f7d78 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_DecodeError );
a73db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
1d9371 ¤   }
cd415f ¤   session->certRequested = TRUE;
--f0c4 000f8924d6a40100246 Page 32 of pgpTLS.c
2c1c63 ¤   if( session->cipherSuites[session->cipherSuiteIndex].usePGPKeys )
e8c7a1 ¤   {
3cc61c ¤   ¤   if( PGPKeyRefIsValid( session->localKey ) )
d65b34 ¤   ¤   {
e7157f ¤   ¤   ¤   while( numCertTypes-- )
19f776 ¤   ¤   ¤   {
4bef24 ¤   ¤   ¤   ¤   switch( inBuffer[pktInx++] )
fc72c3 ¤   ¤   ¤   ¤   {
78a97a ¤   ¤   ¤   ¤   ¤   case kPGPtls_CC_DSASign:
0be895 ¤   ¤   ¤   ¤   ¤   ¤   if( session->localKeyAlg == kPGPPublicKeyAlgorithm_DSA )
7daf43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->certMatched = TRUE;
bc00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
90f2f1 ¤   ¤   ¤   ¤   ¤   case kPGPtls_CC_RSASign:
dfb2df ¤   ¤   ¤   ¤   ¤   ¤   if( session->localKeyAlg == kPGPPublicKeyAlgorithm_RSA )
ffaf43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->certMatched = TRUE;
5e00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
772613 ¤   ¤   ¤   ¤   }
d6a3a6 ¤   ¤   ¤   }
5c0fe4 ¤   ¤   }
589371 ¤   }
310e24 ¤   else
e9c7a1 ¤   {
afa5b0 ¤   ¤   /* ##### */
fc24da ¤   ¤   pgpAssert( 0 );
3f9371 ¤   }
6767c5 ¤
f1b38c done:
625ea8 ¤   return err;
48efe6 }
15af5a
7cc744 ¤   PGPError
11e99f pgpTLSReceiveServerHelloDone(
db2665 ¤   PGPtlsSessionPriv *¤session,
efa1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
076183 ¤   const PGPSize¤  ¤   inLength )
d7bb36 {
5b26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
c267c5 ¤
515758 ¤   (void) inLength;
8f67c5 ¤
045f37 ¤   PGPValidatePtr( inBuffer );
a367c5 ¤
a162fa ¤   /* Now we send the ClientCertificate message if requested */
ac0bd3 ¤   if( session->certRequested )
22c7a1 ¤   {
f41989 ¤   ¤   err = pgpTLSSendCertificate( session ); CKERR;
ff9371 ¤   }
941e2b ¤   /* Now we send the ClientKeyExchange message */
334098 ¤   err = pgpTLSSendClientKeyExchange( session ); CKERR;
2867c5 ¤
bfda13 ¤   /* Now we send the CertificateVerify message if applicable */
60c573 ¤   if( session->certMatched )
5dc7a1 ¤   {
fe404c ¤   ¤   err = pgpTLSSendCertVerify( session ); CKERR;
b59371 ¤   }
d767c5 ¤
f18f12 ¤   /* Calculate the Keys */
d41ad9 ¤   err = pgpTLSCalculateKeys( session ); CKERR;
2167c5 ¤
37e50b ¤   err = pgpTLSSendFinalHandshake( session ); CKERR;
ff67c5 ¤
6cb38c done:
855ea8 ¤   return err;
0e1862 }¤
5daf5a
5ac744 ¤   PGPError
7fa530 pgpTLSReceiveFinished(
4c2665 ¤   PGPtlsSessionPriv *¤session,
95a1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
286183 ¤   const PGPSize¤  ¤   inLength )
d9bb36 {
f8d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
--d17b 000df814ff740100246 Page 33 of pgpTLS.c
1da8a4 ¤   PGPSize¤¤   ¤   ¤   checkSize;
f7a511 ¤   PGPByte¤¤   ¤   ¤   checkFin[64];
2a67c5 ¤
a65f37 ¤   PGPValidatePtr( inBuffer );
9767c5 ¤
412c96 ¤   if( IsNull( session->readActive ) )
d7c7a1 ¤   {
7a8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
2ea09b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
ca3db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
939371 ¤   }
de9ce9 ¤   err = pgpTLSCalculateFinished( session,
6ba6e8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPBoolean) !session->isClientSide,
7a5019 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   checkFin, &checkSize );
514339 ¤   CKERR;
9c5c93 ¤   if( ( inLength != checkSize ) ||
aa6ce7 ¤   ¤   !pgpMemoryEqual( checkFin, inBuffer, checkSize ) )
44c7a1 ¤   {
fb8f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
19f544 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_HandshakeFailure );
e53db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
919371 ¤   }
6440ae ¤   if( !session->isClientSide && session->certRequested &&
9a7594 ¤   ¤   ( !PGPKeyRefIsValid( session->remoteKey ) ||
ee1932 ¤   ¤   !session->certVerified ) )
d6c7a1 ¤   {
ca71f4 ¤   ¤   /*¤ We asked for a certificate but no response was returned,
80b430 ¤   ¤   ¤   or the CertificateVerify message never arrived,
59eee1 ¤   ¤   ¤   possible indication of active attack. */
018f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
f1f544 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_HandshakeFailure );
8e3db2 ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
269371 ¤   }
92af5a
e3b38c done:
f25ea8 ¤   return err;
291862 }¤
55af5a
01c744 ¤   PGPError
cab6f9 ssl3MasterSecret16(
122665 ¤   PGPtlsSessionPriv *¤session,
267929 ¤   PGPByte *¤  ¤   ¤   preMaster,
432438 ¤   PGPUInt16¤  ¤   ¤   preMasterSize,
deda20 ¤   PGPByte¤¤   ¤   ¤   mixer,
79de2f ¤   PGPByte *¤  ¤   ¤   masterSecret )
f9bb36 {
78d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
641e29 ¤   PGPHashContextRef¤  sha,
b0593b ¤   ¤   ¤   ¤   ¤   ¤   md5;
7d467c ¤   PGPByte¤¤   ¤   ¤   shaHash[kPGPtls_HA_SHASize],
1c6e74 ¤   ¤   ¤   ¤   ¤   ¤   mixerByte,
fac1da ¤   ¤   ¤   ¤   ¤   ¤   mixIters;
75af5a
328c59 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA, &sha );
947f7d ¤   if( IsPGPError( err ) )
51c9db ¤   ¤   return err;
a7b364 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5, &md5 );
a17f7d ¤   if( IsPGPError( err ) )
c9c9db ¤   ¤   return err;
d1af5a
01f83e ¤   /* Prefix with n bytes of 0x40 + n */
4d7ac8 ¤   mixerByte = 0x40 + mixer;
1d22e8 ¤   for( mixIters = 0; mixIters < mixer; mixIters++ )
3aad27 ¤   ¤   (void)PGPContinueHash( sha, &mixerByte, 1 );
33af5a
c53f81 ¤   /* Then premastersecret, client_random, server_random */
bd7ed2 ¤   (void)PGPContinueHash( sha, preMaster, preMasterSize );
2a5375 ¤   (void)PGPContinueHash( sha, session->cRandom, kPGPtls_RandomSize );
4660f9 ¤   (void)PGPContinueHash( sha, session->sRandom, kPGPtls_RandomSize );
0b1c2e ¤   (void)PGPFinalizeHash( sha, shaHash );
e1000c ¤   (void)PGPFreeHashContext( sha );
dfaf5a
--4ce9 000bc5f5e2f40100246 Page 34 of pgpTLS.c
178c5f ¤   /* MD5 gets premastersecret and shahash */
714522 ¤   (void)PGPContinueHash( md5, preMaster, preMasterSize );
1043aa ¤   (void)PGPContinueHash( md5, shaHash, kPGPtls_HA_SHASize );
1faf5a
567718 ¤   /* The output of this is 16 bytes of mastersecret */
b56be2 ¤   (void)PGPFinalizeHash( md5, masterSecret );
015a62 ¤   (void)PGPFreeHashContext( md5 );
8b67c5 ¤
f05ea8 ¤   return err;
12efe6 }
79af5a
91c744 ¤   PGPError
f4e6cd ssl3CalculateKeyBlock(
cb2665 ¤   PGPtlsSessionPriv *¤session,
d121bd ¤   PGPByte *¤  ¤   ¤   keyBlock,
2a5248 ¤   PGPSize¤¤   ¤   ¤   needed )
48bb36 {
21d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
12364e ¤   PGPHashContextRef¤  sha = kInvalidPGPHashContextRef,
7d82a0 ¤   ¤   ¤   ¤   ¤   ¤   md5 = kInvalidPGPHashContextRef;
7b49a7 ¤   PGPUInt16¤  ¤   ¤   iterations,
985b49 ¤   ¤   ¤   ¤   ¤   ¤   iterIndex,
fb49cc ¤   ¤   ¤   ¤   ¤   ¤   mixerIndex;
2e2c03 ¤   PGPByte¤¤   ¤   ¤   mixerByte;
d635ff ¤   PGPByte *¤  ¤   ¤   preBlockPos;
4d6a56 ¤   PGPByte *¤  ¤   ¤   preBlock = NULL;
809ee5 ¤   PGPByte¤¤   ¤   ¤   shaHash[kPGPtls_HA_SHASize];
de67c5 ¤
bb0b37 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA, &sha);
194339 ¤   CKERR;
87c5e9 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5, &md5);
8c4339 ¤   CKERR;
fb67c5 ¤
ee9390 ¤   iterations = needed / kPGPtls_HA_MD5Size;
270f69 ¤   if( needed % kPGPtls_HA_MD5Size )
91b7ee ¤   ¤   iterations++;
6a67c5 ¤
1faa11 ¤   preBlock ·= PGPNewSecureData( session->memMgr,
4d7717 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   iterations * kPGPtls_HA_MD5Size, 0 );
abdf1e ¤   if( IsNull( preBlock ) )
2cc7a1 ¤   {
5fbce1 ¤   ¤   err = kPGPError_OutOfMemory;
5f262d ¤   ¤   goto done;
fc9371 ¤   }
4d8119 ¤   preBlockPos = preBlock;
549590 ¤   for( iterIndex = 1; iterIndex <= iterations; iterIndex++ )
6cc7a1 ¤   {
02f6a9 ¤   ¤   mixerByte = 0x40 + iterIndex;
3d8688 ¤   ¤   for( mixerIndex = 0; mixerIndex < iterIndex; mixerIndex++ )
92c214 ¤   ¤   ¤   (void)PGPContinueHash( sha, &mixerByte, 1 );
fb38b1 ¤   ¤   (void)PGPContinueHash( sha, session->masterSecret,
e791b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize );
d37bf0 ¤   ¤   (void)PGPContinueHash( sha, session->sRandom, kPGPtls_RandomSize );
5b487c ¤   ¤   (void)PGPContinueHash( sha, session->cRandom, kPGPtls_RandomSize );
238db6 ¤   ¤   (void)PGPFinalizeHash( sha, shaHash );
d187c1 ¤   ¤   (void)PGPResetHash( sha );
fb1b52 ¤   ¤
c6d193 ¤   ¤   (void)PGPContinueHash( md5, session->masterSecret,
43c55f ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize );
1dce56 ¤   ¤   (void)PGPContinueHash( md5, shaHash, kPGPtls_HA_SHASize );
070920 ¤   ¤   (void)PGPFinalizeHash( md5, preBlockPos );
b8ddaf ¤   ¤   (void)PGPResetHash( md5 );
8203be ¤   ¤   preBlockPos += kPGPtls_HA_MD5Size;
bd9371 ¤   }
d167c5 ¤
5daa9e ¤   /* Finished generating KeyBlock, copy needed portion */
d12d50 ¤   pgpCopyMemory( preBlock, keyBlock, needed );
0b67c5 ¤
04b38c done:
05803d ¤   if( IsntNull( preBlock ) )
a99e76 ¤   ¤   (void)PGPFreeData( preBlock );
bcda7e ¤   if( PGPHashContextRefIsValid( sha ) )
--efc8 000dd6ca53f40100246 Page 35 of pgpTLS.c
4e05e1 ¤   ¤   (void)PGPFreeHashContext( sha );
37505c ¤   if( PGPHashContextRefIsValid( md5 ) )
395f8f ¤   ¤   (void)PGPFreeHashContext( md5 );
b65ea8 ¤   return err;
c7efe6 }
29af5a
cec744 ¤   PGPError
8d509b tlsCalculateKeyBlock(
952665 ¤   PGPtlsSessionPriv *¤session,
ff21bd ¤   PGPByte *¤  ¤   ¤   keyBlock,
d95248 ¤   PGPSize¤¤   ¤   ¤   needed )
0ebb36 {
aed591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
38a202 ¤   PGPByte¤¤   ¤   ¤   randoms[kPGPtls_RandomSize * 2];
2367c5 ¤
fce4bb ¤   pgpCopyMemory( session->sRandom, randoms, kPGPtls_RandomSize );
f83af2 ¤   pgpCopyMemory( session->cRandom, randoms + kPGPtls_RandomSize,
630184 ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize );
207f6a ¤   err = pgpTLSPRF( session, session->masterSecret, kPGPtls_MasterSecretSize,
3bd99b ¤   ¤   ¤   ¤   ¤   ¤   "key expansion", randoms, kPGPtls_RandomSize * 2,
3bec59 ¤   ¤   ¤   ¤   ¤   ¤   keyBlock, needed );
285ea8 ¤   return err;
53efe6 }
56af5a
08c744 ¤   PGPError
744be5 pgpTLSPRFTest(
7c372f ¤   PGPtlsSessionPriv *¤session )
7cbb36 {
16d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
d51ab8 ¤   PGPByte¤¤   ¤   ¤   secret[kPGPtls_MasterSecretSize];
94dc8b ¤   PGPByte¤¤   ¤   ¤   seed[kPGPtls_RandomSize * 2];
a8d0fb ¤   PGPByte¤¤   ¤   ¤   prfOut[104];
ddaceb ¤   PGPByte¤¤   ¤   ¤   hashOut[kPGPtls_HA_MD5Size];
8f1dcc ¤   PGPHashContextRef¤  hash;
9118ee ¤   PGPByte¤¤   ¤   ¤   testVector[kPGPtls_HA_MD5Size] =
6b9a98 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {¤  0xCD, 0x7C, 0xA2, 0xCB,
b53e2d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0x9A, 0x6A, 0x3C, 0x6F,
21d1c5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0x34, 0x5C, 0x46, 0x65,
e1fdaa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0xA8, 0xB6, 0x81, 0x6B };
7e67c5 ¤
dfd817 ¤   pgpFillMemory( secret, kPGPtls_MasterSecretSize, 0xAB );
fdd15d ¤   pgpFillMemory( seed, kPGPtls_RandomSize * 2, 0xCD );
1fae46 ¤   err = pgpTLSPRF( session, secret, kPGPtls_MasterSecretSize,
c795a2 ¤   ¤   ¤   ¤   ¤   "PRF Testvector", seed, kPGPtls_RandomSize * 2,
55c5be ¤   ¤   ¤   ¤   ¤   prfOut, sizeof(prfOut) );¤  CKERR;
d71a64 ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5, &hash );CK¶
32c01d ERR;
614358 ¤   err = PGPContinueHash( hash, prfOut, sizeof(prfOut) );¤ CKERR;
c845d0 ¤   err = PGPFinalizeHash( hash, hashOut );¤CKERR;
0bb947 ¤   err = PGPFreeHashContext( hash );¤  CKERR;
e867c5 ¤
85edd4 ¤   if( !pgpMemoryEqual( hashOut, testVector, kPGPtls_HA_MD5Size ) )
39790c ¤   ¤   err = kPGPError_CorruptData;
d267c5 ¤
4eb38c done:
645ea8 ¤   return err;
e1efe6 }
e2af5a
20c744 ¤   PGPError
ad90ec pgpTLSPRF(
c72665 ¤   PGPtlsSessionPriv *¤session,
42daec ¤   PGPByte *¤  ¤   ¤   secret,
6c8b99 ¤   PGPSize¤¤   ¤   ¤   secretLen,
978b4b ¤   const char *¤   ¤   label,
c1e3e8 ¤   PGPByte *¤  ¤   ¤   seedData,
d0e595 ¤   PGPSize¤¤   ¤   ¤   seedLen,
aa70ae ¤   PGPByte *¤  ¤   ¤   outputData,
75b743 ¤   PGPSize¤¤   ¤   ¤   outputLen )
b6bb36 {
b6d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
9be433 ¤   PGPHMACContextRef¤  hmac = kInvalidPGPHMACContextRef,
ddf0ac ¤   ¤   ¤   ¤   ¤   ¤   inHMAC = kInvalidPGPHMACContextRef;
--56a6 0005489aad340100246 Page 36 of pgpTLS.c
7b173f ¤   PGPByte¤¤   ¤   ¤   secret1[256],
096078 ¤   ¤   ¤   ¤   ¤   ¤   secret2[256],
0dac90 ¤   ¤   ¤   ¤   ¤   ¤   pSeed[256],
ad3744 ¤   ¤   ¤   ¤   ¤   ¤   pMD5Output[128],
ca98b7 ¤   ¤   ¤   ¤   ¤   ¤   pSHAOutput[128];
5d5aba ¤   PGPSize¤¤   ¤   ¤   halfSecLen,
42596b ¤   ¤   ¤   ¤   ¤   ¤   labelLen,
187c8d ¤   ¤   ¤   ¤   ¤   ¤   pSeedLen,
805711 ¤   ¤   ¤   ¤   ¤   ¤   hashOutLen;
23b100 ¤   PGPUInt32¤  ¤   ¤   hmacIters,
3cb514 ¤   ¤   ¤   ¤   ¤   ¤   bIndex;
7f8e96 ¤   PGPByte¤¤   ¤   ¤   inHMACOut[kPGPtls_HA_SHASize];
5b3046 ¤   PGPByte¤¤   ¤   ¤   inHMACOut2[kPGPtls_HA_SHASize];
5f67c5 ¤
5b1181 ¤   /*¤ This was definitely one of the more complex functions to
60c94b ¤   ¤   architect in this code, but once one fully understands this
25032f ¤   ¤   function, you will get a really good feeling about the security
aa5c35 ¤   ¤   provided by TLS.
8efc1a ¤   ¤   N.B. ·This function might look simple now, but try reading the
8bbce5 ¤   ¤   TLS spec to understand it first. ·That ought to thoroughly
315e6e ¤   ¤   confuse you.¤   */
5b67c5 ¤
953aba ¤   labelLen = strlen( label );
4667c5 ¤
7f5346 ¤   /* To avoid allocating memory we use fixed buffers which should
4f2bbd ¤   ¤   easily accomodate all TLS situations. */
8289e6 ¤   pgpAssert( outputLen < sizeof( pMD5Output ) );
cd5d3b ¤   pgpAssert( secretLen <= sizeof( secret1 ) * 2 );
6c8bdb ¤   pgpAssert( labelLen + seedLen < sizeof( pSeed ) );
0a67c5 ¤
464707 ¤   /* Divide secret into halves */
ea8e92 ¤   halfSecLen = secretLen / 2;
4bbbf9 ¤   if( secretLen % 2 )
5dbc8b ¤   ¤   halfSecLen++;
d9674b ¤   pgpCopyMemory( secret, secret1, halfSecLen );
1058bf ¤   pgpCopyMemory( secret + halfSecLen - ( secretLen % 2 ? 1 : 0 ),
76ac2c ¤   ¤   ¤   ¤   ¤   secret2, halfSecLen );
4a67c5 ¤
226654 ¤   /* Create seed value for P_Hash functions */
72d945 ¤   pgpCopyMemory( label, pSeed, labelLen );
2e5108 ¤   pgpCopyMemory( seedData, pSeed + labelLen, seedLen );
b0ed95 ¤   pSeedLen = labelLen + seedLen;
da67c5 ¤
e5aec9 ¤   /* Do P_MD5 */
83c197 ¤   hmacIters = outputLen / kPGPtls_HA_MD5Size;
73ef57 ¤   if( outputLen % kPGPtls_HA_MD5Size )
1a4913 ¤   ¤   hmacIters++;
0671e9 ¤   err = PGPNewHMACContext( session->memMgr, kPGPHashAlgorithm_MD5,
4084a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   secret1, halfSecLen, &hmac );¤  CKERR;
c171e9 ¤   err = PGPNewHMACContext( session->memMgr, kPGPHashAlgorithm_MD5,
a65639 ¤   ¤   ¤   ¤   ¤   ¤   ¤   secret1, halfSecLen, &inHMAC );¤CKERR;
e1e1e4 ¤   err = PGPContinueHMAC( inHMAC, pSeed, pSeedLen );¤  CKERR;
3035de ¤   err = PGPFinalizeHMAC( inHMAC, inHMACOut );
afd782 ¤   err = PGPResetHMAC( inHMAC );¤  CKERR;
44c0af ¤   hashOutLen = 0;
dab00a ¤   for( bIndex = 0; bIndex < hmacIters; bIndex++ )
5ec7a1 ¤   {
3e1bd4 ¤   ¤   pgpCopyMemory( inHMACOut, inHMACOut2, kPGPtls_HA_MD5Size );
da2126 ¤   ¤   err = PGPContinueHMAC( inHMAC, inHMACOut, kPGPtls_HA_MD5Size );¤CKERR;
d1a39f ¤   ¤   err = PGPFinalizeHMAC( inHMAC, inHMACOut );
88461a ¤   ¤   err = PGPResetHMAC( inHMAC );¤  CKERR;
161b52 ¤   ¤
ca3c6c ¤   ¤   /* Feed the HMAC */
97759d ¤   ¤   err = PGPContinueHMAC( hmac, inHMACOut2, kPGPtls_HA_MD5Size );¤ CKERR;
2246fa ¤   ¤   err = PGPContinueHMAC( hmac, pSeed, pSeedLen );¤CKERR;
ea920e ¤   ¤   err = PGPFinalizeHMAC( hmac, pMD5Output + hashOutLen );
36261b ¤   ¤   err = PGPResetHMAC( hmac );¤CKERR;
d203fd ¤   ¤   hashOutLen += kPGPtls_HA_MD5Size;
949371 ¤   }
bced0b ¤   err = PGPFreeHMACContext( inHMAC );¤CKERR;
892c20 ¤   inHMAC = kInvalidPGPHMACContextRef;
543f93 ¤   err = PGPFreeHMACContext( hmac );¤  CKERR;
--4066 0003292417940100246 Page 37 of pgpTLS.c
70e3c3 ¤   hmac = kInvalidPGPHMACContextRef;
7e67c5 ¤
e69436 ¤   /* Do P_SHA */
d3a08e ¤   hmacIters = outputLen / kPGPtls_HA_SHASize;
466276 ¤   if( outputLen % kPGPtls_HA_SHASize )
fa4913 ¤   ¤   hmacIters++;
8ad09c ¤   err = PGPNewHMACContext( session->memMgr, kPGPHashAlgorithm_SHA,
744404 ¤   ¤   ¤   ¤   ¤   ¤   ¤   secret2, halfSecLen, &hmac );¤  CKERR;
c8d09c ¤   err = PGPNewHMACContext( session->memMgr, kPGPHashAlgorithm_SHA,
7d969c ¤   ¤   ¤   ¤   ¤   ¤   ¤   secret2, halfSecLen, &inHMAC );¤CKERR;
3de1e4 ¤   err = PGPContinueHMAC( inHMAC, pSeed, pSeedLen );¤  CKERR;
f335de ¤   err = PGPFinalizeHMAC( inHMAC, inHMACOut );
c6d782 ¤   err = PGPResetHMAC( inHMAC );¤  CKERR;
1ec0af ¤   hashOutLen = 0;
20b00a ¤   for( bIndex = 0; bIndex < hmacIters; bIndex++ )
c4c7a1 ¤   {
302bd2 ¤   ¤   pgpCopyMemory( inHMACOut, inHMACOut2, kPGPtls_HA_SHASize );
02be3b ¤   ¤   err = PGPContinueHMAC( inHMAC, inHMACOut, kPGPtls_HA_SHASize );¤CKERR;
c1a39f ¤   ¤   err = PGPFinalizeHMAC( inHMAC, inHMACOut );
84461a ¤   ¤   err = PGPResetHMAC( inHMAC );¤  CKERR;
7d1b52 ¤   ¤
293c6c ¤   ¤   /* Feed the HMAC */
d9be66 ¤   ¤   err = PGPContinueHMAC( hmac, inHMACOut2, kPGPtls_HA_SHASize );¤ CKERR;
5746fa ¤   ¤   err = PGPContinueHMAC( hmac, pSeed, pSeedLen );¤CKERR;
80598b ¤   ¤   err = PGPFinalizeHMAC( hmac, pSHAOutput + hashOutLen );
ec261b ¤   ¤   err = PGPResetHMAC( hmac );¤CKERR;
a262e4 ¤   ¤   hashOutLen += kPGPtls_HA_SHASize;
679371 ¤   }
a0ed0b ¤   err = PGPFreeHMACContext( inHMAC );¤CKERR;
522c20 ¤   inHMAC = kInvalidPGPHMACContextRef;
b23f93 ¤   err = PGPFreeHMACContext( hmac );¤  CKERR;
79e3c3 ¤   hmac = kInvalidPGPHMACContextRef;
8a67c5 ¤
cb959e ¤   /* Create the final output */
a4a91a ¤   for( bIndex = 0; bIndex < outputLen; bIndex++ )
69ba61 ¤   ¤   outputData[bIndex] = pMD5Output[bIndex] ^ pSHAOutput[bIndex];
c567c5 ¤
32b38c done:
81f830 ¤   if( PGPHMACContextRefIsValid( hmac ) )
6099ef ¤   ¤   PGPFreeHMACContext( hmac );
c111b1 ¤   if( PGPHMACContextRefIsValid( inHMAC ) )
931a52 ¤   ¤   PGPFreeHMACContext( inHMAC );
b85ea8 ¤   return err;
acefe6 }
0daf5a
a0c744 ¤   PGPError
292c9f pgpTLSCalculateMasterSecret(
a32665 ¤   PGPtlsSessionPriv *¤session,
bf7929 ¤   PGPByte *¤  ¤   ¤   preMaster,
1739ac ¤   PGPSize¤¤   ¤   ¤   preMasterSize )
b0bb36 {
59d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
8b67c5 ¤
85eb60 ¤   if( session->minorVersion == kPGPtls_SSL3MinorVersion )
31c7a1 ¤   {
b661b3 ¤   ¤   /* The quaint little SSL3 master secret calculation */
4e1b52 ¤   ¤
1e0c75 ¤   ¤   ssl3MasterSecret16( session, preMaster, (PGPUInt16) preMasterSize,
e7b7b7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   1, session->masterSecret );
510c75 ¤   ¤   ssl3MasterSecret16( session, preMaster, (PGPUInt16) preMasterSize,
4f4955 ¤   ¤   ¤   ¤   ¤   ¤   ¤   2, session->masterSecret + kPGPtls_HA_MD5Size );
9a0c75 ¤   ¤   ssl3MasterSecret16( session, preMaster, (PGPUInt16) preMasterSize,
e532ae ¤   ¤   ¤   ¤   ¤   ¤   ¤   3, session->masterSecret + 2 * kPGPtls_HA_MD5Size );
4a9371 ¤   }
4e0e24 ¤   else
81c7a1 ¤   {
60de84 ¤   ¤   PGPByte¤¤   ¤   randoms[kPGPtls_RandomSize * 2];
b31b52 ¤   ¤
74bd16 ¤   ¤   /* The TLS mother of all master secret calculations */
b41b52 ¤   ¤
7e496c ¤   ¤   pgpCopyMemory( session->cRandom, randoms, kPGPtls_RandomSize );
32a7da ¤   ¤   pgpCopyMemory( session->sRandom, randoms + kPGPtls_RandomSize,
--d0ea 00010b715b240100246 Page 38 of pgpTLS.c
083841 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_RandomSize );
541b52 ¤   ¤
453c08 ¤   ¤   err = pgpTLSPRF( session, preMaster, preMasterSize,
3b075c ¤   ¤   ¤   ¤   ¤   ¤   ¤   "master secret", randoms, kPGPtls_RandomSize * 2,
abc77a ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->masterSecret, kPGPtls_MasterSecretSize );
e22283 ¤   ¤   CKERR;
b59371 ¤   }
3eb38c done:
435ea8 ¤   return err;
9befe6 }
c3af5a
21c744 ¤   PGPError
6ea809 pgpTLSCalculateKeys(
c9372f ¤   PGPtlsSessionPriv *¤session )
afbb36 {
d9d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
184939 ¤   PGPSize¤¤   ¤   ¤   needed = 0,
cfa1c9 ¤   ¤   ¤   ¤   ¤   ¤   hashSize = 0,
35be0d ¤   ¤   ¤   ¤   ¤   ¤   keySize = 0;
391a3a ¤   PGPByte *¤  ¤   ¤   keyBlock = NULL;
0dfec7 ¤   PGPByte *¤  ¤   ¤   keyBlockPos = NULL;
19af5a
c4d510 ¤   /* Figure out how much KeyBlock we need */
76e1ee ¤   switch( session->cipherSuites[session->cipherSuiteIndex].hashID )
31c7a1 ¤   {
ed7724 ¤   ¤   case kPGPHashAlgorithm_SHA:
4b1034 ¤   ¤   ¤   hashSize = kPGPtls_HA_SHASize;
9acdcb ¤   ¤   ¤   break;
cfea4f ¤   ¤   case kPGPHashAlgorithm_RIPEMD160:
590305 ¤   ¤   ¤   hashSize = kPGPtls_HA_RIPEMD160Size;
2dcdcb ¤   ¤   ¤   break;
a3d651 ¤   ¤   case kPGPHashAlgorithm_MD5:
2b712d ¤   ¤   ¤   hashSize = kPGPtls_HA_MD5Size;
47cdcb ¤   ¤   ¤   break;
b89ae3 ¤   ¤   default:
2ecdcb ¤   ¤   ¤   break;
ef9371 ¤   }
552402 ¤   session->hashSize = hashSize;
8a3f82 ¤   needed += hashSize * 2;
43bc86 ¤   switch( session->cipherSuites[session->cipherSuiteIndex].cipherID )
84c7a1 ¤   {
3e1673 ¤   ¤   case kPGPCipherAlgorithm_CAST5:
265b51 ¤   ¤   ¤   keySize = kPGPtls_SC_CASTKeySize;
f7cdcb ¤   ¤   ¤   break;
564b7e ¤   ¤   case kPGPCipherAlgorithm_IDEA:
ba379b ¤   ¤   ¤   keySize = kPGPtls_SC_IDEAKeySize;
73cdcb ¤   ¤   ¤   break;
e7975c ¤   ¤   case kPGPCipherAlgorithm_3DES:
7a1794 ¤   ¤   ¤   keySize = kPGPtls_SC_3DESKeySize;
c9cdcb ¤   ¤   ¤   break;
f29ae3 ¤   ¤   default:
8dcdcb ¤   ¤   ¤   break;
279371 ¤   }
aed6e2 ¤   session->keySize = keySize;
d0de1d ¤   needed += keySize * 2;
c8eaeb ¤   if( keySize > 0 )
9b385b ¤   ¤   needed += kPGPtls_CipherBlockSize * 2;¤ /* 2 IVs for CBC */
0867c5 ¤
da4950 ¤   /* Calculate KeyBlock */
82d83f ¤   keyBlock ·= PGPNewSecureData( session->memMgr, needed, 0 );
efa2ab ¤   if( IsNull( keyBlock ) )
f3c7a1 ¤   {
9dbce1 ¤   ¤   err = kPGPError_OutOfMemory;
07262d ¤   ¤   goto done;
139371 ¤   }
c4eb60 ¤   if( session->minorVersion == kPGPtls_SSL3MinorVersion )
1e9398 ¤   ¤   err = ssl3CalculateKeyBlock( session, keyBlock, needed );
d90e24 ¤   else
f036bb ¤   ¤   err = tlsCalculateKeyBlock( session, keyBlock, needed );
be4339 ¤   CKERR;
2067c5 ¤
10d015 ¤   session->clientPending = PGPNewSecureData( session->memMgr,
--6c52 000a9ecdca840100246 Page 39 of pgpTLS.c
42ce82 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( PGPtlsKeys ),
e1b207 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
15a0c2 ¤   session->serverPending = PGPNewSecureData( session->memMgr,
27ce82 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( PGPtlsKeys ),
25b207 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
8d0ee6 ¤   if( IsNull( session->clientPending ) || IsNull( session->serverPending ) )
7cc7a1 ¤   {
bebce1 ¤   ¤   err = kPGPError_OutOfMemory;
cf262d ¤   ¤   goto done;
b29371 ¤   }
67e879 ¤   keyBlockPos = keyBlock;
b07856 ¤   pgpCopyMemory( keyBlockPos, session->clientPending->macSecret, hashSize );
1b3958 ¤   keyBlockPos += hashSize;
83c714 ¤   pgpCopyMemory( keyBlockPos, session->serverPending->macSecret, hashSize );
143958 ¤   keyBlockPos += hashSize;
b7eaeb ¤   if( keySize > 0 )
b1c7a1 ¤   {
946f9c ¤   ¤   pgpCopyMemory( keyBlockPos, session->clientPending->cipherKey,
10c577 ¤   ¤   ¤   ¤   ¤   ¤   keySize );
1c2d3d ¤   ¤   keyBlockPos += keySize;
1d2a59 ¤   ¤   pgpCopyMemory( keyBlockPos, session->serverPending->cipherKey,
34c577 ¤   ¤   ¤   ¤   ¤   ¤   keySize );
a52d3d ¤   ¤   keyBlockPos += keySize;
81762a ¤   ¤   pgpCopyMemory( keyBlockPos, session->clientPending->iv,
e32df6 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_CipherBlockSize );
025307 ¤   ¤   keyBlockPos += kPGPtls_CipherBlockSize;
9d09cb ¤   ¤   pgpCopyMemory( keyBlockPos, session->serverPending->iv,
8e2df6 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_CipherBlockSize );
5a5307 ¤   ¤   keyBlockPos += kPGPtls_CipherBlockSize;
0b9371 ¤   }
ba376f ¤   pgpAssert( keyBlockPos == keyBlock + needed );
fb67c5 ¤
a4b38c done:
92fd88 ¤   if( IsntNull( keyBlock ) )
b9dce8 ¤   ¤   (void)PGPFreeData( keyBlock );
d05ea8 ¤   return err;
e8efe6 }
65af5a
0fc744 ¤   PGPError
026dcb pgpTLSCalculateMAC(
582665 ¤   PGPtlsSessionPriv *¤session,
43dd54 ¤   const PGPBoolean¤   inSending,
5a006a ¤   const PGPByte¤  ¤   inType,
0bf0fa ¤   const PGPByte *¤¤   inBuffer,
532f71 ¤   const PGPSize¤  ¤   inLength,
8da825 ¤   PGPByte *¤  ¤   ¤   outBuffer )
3cbb36 {
bed591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
cb021e ¤   PGPtlsKeys *¤   ¤   keys;
13c142 ¤   PGPUInt16¤  ¤   ¤   seqNumIndex;
4940dc ¤   PGPByte¤¤   ¤   ¤   stufBuf[5];
ff67c5 ¤
71d8de ¤   if( inSending )
010b7e ¤   ¤   keys = session->writeActive;
aa0e24 ¤   else
b0f18b ¤   ¤   keys = session->readActive;
7eeb60 ¤   if( session->minorVersion == kPGPtls_SSL3MinorVersion )
c2c7a1 ¤   {
1ebaee ¤   ¤   PGPUInt16¤  padSize,
a6131e ¤   ¤   ¤   ¤   ¤   padIndex;
f43e8e ¤   ¤   PGPByte¤¤   padBuffer[kPGPtls_SSL3MD5PaddingBytes];
431f39 ¤   ¤   PGPByte¤¤   innerHash[32];
9b1b52 ¤   ¤
f973b1 ¤   ¤   if( !PGPHashContextRefIsValid( session->innerMACHash ) )
955b34 ¤   ¤   {
6d996f ¤   ¤   ¤   err = PGPNewHashContext( session->memMgr,
784c76 ¤   ¤   ¤   ¤   ¤   session->cipherSuites[session->cipherSuiteIndex].hashID,
e54b26 ¤   ¤   ¤   ¤   ¤   &session->innerMACHash ); CKERR;
38996f ¤   ¤   ¤   err = PGPNewHashContext( session->memMgr,
8d4c76 ¤   ¤   ¤   ¤   ¤   session->cipherSuites[session->cipherSuiteIndex].hashID,
c680c8 ¤   ¤   ¤   ¤   ¤   &session->outerMACHash ); CKERR;
a90fe4 ¤   ¤   }
--7cf8 000a91713ff40100246 Page 40 of pgpTLS.c
94b655 ¤   ¤   (void)PGPContinueHash( session->innerMACHash, keys->macSecret,
55a181 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->hashSize );
57e476 ¤   ¤   if( session->cipherSuites[session->cipherSuiteIndex].hashID ==
dde521 ¤   ¤   ¤   kPGPHashAlgorithm_MD5 )
724d90 ¤   ¤   ¤   padSize = kPGPtls_SSL3MD5PaddingBytes;
e30e1d ¤   ¤   else
1f81bb ¤   ¤   ¤   padSize = kPGPtls_SSL3SHAPaddingBytes;
5cacdb ¤   ¤   for( padIndex = 0; padIndex < padSize; padIndex++ )
6186ee ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_ipad;
4698e4 ¤   ¤   (void)PGPContinueHash( session->innerMACHash, padBuffer, padSize );
696b98 ¤   ¤   (void)PGPContinueHash( session->innerMACHash, keys->seqNum,
b34655 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SequenceNumberSize );
b0c352 ¤   ¤   stufBuf[0] = inType;
96731c ¤   ¤   stufBuf[1] = (inLength >> 8) & 0xFF;
71ccf4 ¤   ¤   stufBuf[2] = (inLength >> 0) & 0xFF;
c306d2 ¤   ¤   (void)PGPContinueHash( session->innerMACHash, stufBuf, 3 );
bb3587 ¤   ¤   (void)PGPContinueHash( session->innerMACHash, inBuffer, inLength );
d3a452 ¤   ¤   (void)PGPFinalizeHash( session->innerMACHash, innerHash );
1117e5 ¤   ¤   (void)PGPResetHash( session->innerMACHash );
041b52 ¤   ¤
11a922 ¤   ¤   (void)PGPContinueHash( session->outerMACHash, keys->macSecret,
b9a181 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->hashSize );
d0acdb ¤   ¤   for( padIndex = 0; padIndex < padSize; padIndex++ )
fb9e14 ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_opad;
06cc93 ¤   ¤   (void)PGPContinueHash( session->outerMACHash, padBuffer, padSize );
64b305 ¤   ¤   (void)PGPContinueHash( session->outerMACHash, innerHash,
baf29a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->hashSize );
811cba ¤   ¤   (void)PGPFinalizeHash( session->outerMACHash, outBuffer );
1ec43e ¤   ¤   (void)PGPResetHash( session->outerMACHash );
b29371 ¤   }
760e24 ¤   else
2bc7a1 ¤   {
441d4c ¤   ¤   if( !PGPHMACContextRefIsValid( keys->hmac ) )
9b5b34 ¤   ¤   {
0f39f0 ¤   ¤   ¤   err = PGPNewHMACContext( session->memMgr,
484c76 ¤   ¤   ¤   ¤   ¤   session->cipherSuites[session->cipherSuiteIndex].hashID,
6a5a51 ¤   ¤   ¤   ¤   ¤   keys->macSecret, session->hashSize,
3ad9e2 ¤   ¤   ¤   ¤   ¤   &keys->hmac ); CKERR;
0d0fe4 ¤   ¤   }
4f6c5f ¤   ¤   (void)PGPContinueHMAC( keys->hmac, keys->seqNum,
28a455 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SequenceNumberSize );
a8c352 ¤   ¤   stufBuf[0] = inType;
684e07 ¤   ¤   stufBuf[1] = kPGPtls_MajorVersion;
33db64 ¤   ¤   stufBuf[2] = session->minorVersion;
df896f ¤   ¤   stufBuf[3] = (inLength >> 8) & 0xFF;
cdca70 ¤   ¤   stufBuf[4] = (inLength >> 0) & 0xFF;
a83a8d ¤   ¤   (void)PGPContinueHMAC( keys->hmac, stufBuf, 5 );
96c082 ¤   ¤   (void)PGPContinueHMAC( keys->hmac, inBuffer, inLength );
9f701e ¤   ¤   (void)PGPFinalizeHMAC( keys->hmac, outBuffer );
331b52 ¤   ¤
188bb0 ¤   ¤   (void)PGPResetHMAC( keys->hmac );
209371 ¤   }
68c2c0 ¤   for( seqNumIndex = 7; (PGPByte)++keys->seqNum[seqNumIndex] == 0;
a277ed ¤   ¤   ¤   --seqNumIndex )
ed1d52 ¤   ¤   ;
f8b38c done:
d65ea8 ¤   return err;
acefe6 }
3daf5a
b1c744 ¤   PGPError
6edf4d pgpTLSCalculateCertVerify(
ac2665 ¤   PGPtlsSessionPriv *¤session,
d8fd4e ¤   PGPByte *¤  ¤   ¤   outBuffer,
e9b386 ¤   PGPSize *¤  ¤   ¤   outSize )
edbb36 {
02d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f1adbb ¤   PGPHashContextRef¤  cvHashSHA = kInvalidPGPHashContextRef,
707507 ¤   ¤   ¤   ¤   ¤   ¤   cvHashMD5 = kInvalidPGPHashContextRef;
c367c5 ¤
4ccf1a ¤   *outSize = 0;
3f1c15 ¤   if( !PGPHashContextRefIsValid( session->lastHandSHA ) )
a9c7a1 ¤   {
--69db 0000c59cae040100246 Page 41 of pgpTLS.c
4cbb6c ¤   ¤   err = PGPCopyHashContext( session->handshakeSHA,
604d17 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->lastHandSHA ); CKERR;
881a19 ¤   ¤   err = PGPCopyHashContext( session->handshakeMD5,
1a2d6c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->lastHandMD5 ); CKERR;
d69371 ¤   }
aeeb60 ¤   if( session->minorVersion == kPGPtls_SSL3MinorVersion )
8fc7a1 ¤   {
569ea0 ¤   ¤   PGPUInt16¤  ¤   ¤   padIndex;
9db611 ¤   ¤   PGPByte¤¤   ¤   ¤   padBuffer[kPGPtls_SSL3MD5PaddingBytes],
08daf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempHashBuf[32];
031b52 ¤   ¤
6e2643 ¤   ¤   err = PGPContinueHash( session->lastHandSHA, session->masterSecret,
fdf36f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize ); CKERR;
3ff8dc ¤   ¤   for( padIndex = 0; padIndex < kPGPtls_SSL3SHAPaddingBytes; padIndex++ )
d586ee ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_ipad;
679d1f ¤   ¤   err = PGPContinueHash( session->lastHandSHA, padBuffer,
a6bbe9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3SHAPaddingBytes ); CKERR;
2674fc ¤   ¤   err = PGPFinalizeHash( session->lastHandSHA, tempHashBuf ); CKERR;
db8947 ¤   ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_SHA,
0f3402 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &cvHashSHA ); CKERR;
4bbbc0 ¤   ¤   err = PGPContinueHash( cvHashSHA, session->masterSecret,
b9f36f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize ); CKERR;
3af8dc ¤   ¤   for( padIndex = 0; padIndex < kPGPtls_SSL3SHAPaddingBytes; padIndex++ )
469e14 ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_opad;
e1b937 ¤   ¤   err = PGPContinueHash( cvHashSHA, padBuffer,
6cbbe9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3SHAPaddingBytes ); CKERR;
da9bf7 ¤   ¤   err = PGPContinueHash( cvHashSHA, tempHashBuf,
a1cb43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_SHASize ); CKERR;
1a1a4a ¤   ¤   switch( session->cipherSuites[session->cipherSuiteIndex].sigAlg )
2a5b34 ¤   ¤   {
cd7db2 ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_DSA:
c832a1 ¤   ¤   ¤   ¤   err = PGPFinalizeHash( cvHashSHA, outBuffer ); CKERR;
9de733 ¤   ¤   ¤   ¤   *outSize = kPGPtls_HA_SHASize;
e6f622 ¤   ¤   ¤   ¤   break;
4bf26a ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSA:
58a708 ¤   ¤   ¤   ¤   err = PGPContinueHash( session->lastHandMD5,
ad0163 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->masterSecret,
9b3048 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize ); CKERR;
a02a4b ¤   ¤   ¤   ¤   for( padIndex = 0; padIndex < kPGPtls_SSL3MD5PaddingBytes;
8468fd ¤   ¤   ¤   ¤   ¤   ¤   padIndex++ )
a34503 ¤   ¤   ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_ipad;
7d996c ¤   ¤   ¤   ¤   err = PGPContinueHash( session->lastHandMD5, padBuffer,
1a1f90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3MD5PaddingBytes ); CKERR;
89ef40 ¤   ¤   ¤   ¤   err = PGPFinalizeHash( session->lastHandMD5,
000970 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempHashBuf ); CKERR;
ffe738 ¤   ¤   ¤   ¤   err = PGPNewHashContext( session->memMgr, kPGPHashAlgorithm_MD5,
da3b4a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &cvHashMD5 ); CKERR;
fbbc58 ¤   ¤   ¤   ¤   err = PGPContinueHash( cvHashMD5, session->masterSecret,
e93048 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize ); CKERR;
e52a4b ¤   ¤   ¤   ¤   for( padIndex = 0; padIndex < kPGPtls_SSL3MD5PaddingBytes;
c568fd ¤   ¤   ¤   ¤   ¤   ¤   padIndex++ )
8f5df9 ¤   ¤   ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_opad;
3f87db ¤   ¤   ¤   ¤   err = PGPContinueHash( cvHashMD5, padBuffer,
841f90 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3MD5PaddingBytes ); CKERR;
d00333 ¤   ¤   ¤   ¤   err = PGPContinueHash( cvHashMD5, tempHashBuf,
cc0432 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size ); CKERR;
2fd3bc ¤   ¤   ¤   ¤   err = PGPFinalizeHash( cvHashMD5, outBuffer ); CKERR;
003a0a ¤   ¤   ¤   ¤   err = PGPFinalizeHash( cvHashSHA, outBuffer +
f20432 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size ); CKERR;
b123b1 ¤   ¤   ¤   ¤   *outSize = kPGPtls_HA_SHASize + kPGPtls_HA_MD5Size;
59f622 ¤   ¤   ¤   ¤   break;
c6af5a
3ddb68 ¤   ¤   ¤   default:
92f622 ¤   ¤   ¤   ¤   break;
df0fe4 ¤   ¤   }
c29371 ¤   }
2d0e24 ¤   else
eac7a1 ¤   {
601a4a ¤   ¤   switch( session->cipherSuites[session->cipherSuiteIndex].sigAlg )
b45b34 ¤   ¤   {
187db2 ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_DSA:
0c4391 ¤   ¤   ¤   ¤   err = PGPFinalizeHash( session->lastHandSHA, outBuffer ); CKERR;
--c39e 0000341ecba40100246 Page 42 of pgpTLS.c
1fe733 ¤   ¤   ¤   ¤   *outSize = kPGPtls_HA_SHASize;
37f622 ¤   ¤   ¤   ¤   break;
e4f26a ¤   ¤   ¤   case kPGPPublicKeyAlgorithm_RSA:
13a28c ¤   ¤   ¤   ¤   err = PGPFinalizeHash( session->lastHandMD5, outBuffer ); CKERR;
c21907 ¤   ¤   ¤   ¤   err = PGPFinalizeHash( session->lastHandSHA, outBuffer +
df0344 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size ); CKERR;
e523b1 ¤   ¤   ¤   ¤   *outSize = kPGPtls_HA_SHASize + kPGPtls_HA_MD5Size;
c1f622 ¤   ¤   ¤   ¤   break;
bedb68 ¤   ¤   ¤   default:
68f622 ¤   ¤   ¤   ¤   break;
740fe4 ¤   ¤   }
ef9371 ¤   }
c1b38c done:
d2f2c1 ¤   if( PGPHashContextRefIsValid( cvHashSHA ) )
2bea09 ¤   ¤   (void)PGPFreeHashContext( cvHashSHA );
06fd83 ¤   if( PGPHashContextRefIsValid( cvHashMD5 ) )
40d0f6 ¤   ¤   (void)PGPFreeHashContext( cvHashMD5 );
77eaab ¤   if( PGPHashContextRefIsValid( session->lastHandSHA ) )
3e8423 ¤   ¤   (void)PGPFreeHashContext( session->lastHandSHA );
3925dc ¤   session->lastHandSHA = kInvalidPGPHashContextRef;
43e5e9 ¤   if( PGPHashContextRefIsValid( session->lastHandMD5 ) )
44bedc ¤   ¤   (void)PGPFreeHashContext( session->lastHandMD5 );
b57934 ¤   session->lastHandMD5 = kInvalidPGPHashContextRef;
0a5ea8 ¤   return err;
61efe6 }
92af5a
d2c744 ¤   PGPError
80176a pgpTLSCalculateFinished(
5f2665 ¤   PGPtlsSessionPriv *¤session,
b1e864 ¤   PGPBoolean¤ ¤   ¤   clientSide,
a4a1f3 ¤   PGPByte *¤  ¤   ¤   inBuffer,
a9b386 ¤   PGPSize *¤  ¤   ¤   outSize )
7bbb36 {
13d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f15f55 ¤   PGPSize¤¤   ¤   ¤   pktLen = 0;
8f67c5 ¤
e3cf1a ¤   *outSize = 0;
571c15 ¤   if( !PGPHashContextRefIsValid( session->lastHandSHA ) )
fac7a1 ¤   {
ecbb6c ¤   ¤   err = PGPCopyHashContext( session->handshakeSHA,
e84d17 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->lastHandSHA ); CKERR;
761a19 ¤   ¤   err = PGPCopyHashContext( session->handshakeMD5,
582d6c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &session->lastHandMD5 ); CKERR;
069371 ¤   }
70eb60 ¤   if( session->minorVersion == kPGPtls_SSL3MinorVersion )
02c7a1 ¤   {
8f09ff ¤   ¤   PGPByte¤¤   ¤   ¤   clientSeed[] = {0x43, 0x4c, 0x4e, 0x54};
34ca80 ¤   ¤   PGPByte¤¤   ¤   ¤   serverSeed[] = {0x53, 0x52, 0x56, 0x52};
710725 ¤   ¤   PGPByte¤¤   ¤   ¤   padBuffer[64],
f390f0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   shaHash[kPGPtls_HA_SHASize],
6cc7b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   md5Hash[kPGPtls_HA_MD5Size];
c44639 ¤   ¤   PGPUInt16¤  ¤   ¤   padIndex,
cb7b92 ¤   ¤   ¤   ¤   ¤   ¤   ¤   padSize;
2c1b52 ¤   ¤
cd8728 ¤   ¤   padSize = ( kPGPtls_SSL3MD5PaddingBytes >
68e5b2 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3SHAPaddingBytes ) ?
4727cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3MD5PaddingBytes :
3873dd ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3SHAPaddingBytes;
6709b3 ¤   ¤   if( clientSide )
b25b34 ¤   ¤   {
b60079 ¤   ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, clientSeed, 4 );
148be9 ¤   ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, clientSeed, 4 );
5b0fe4 ¤   ¤   }
540e1d ¤   ¤   else
085b34 ¤   ¤   {
468c1f ¤   ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, serverSeed, 4 );
19078f ¤   ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, serverSeed, 4 );
680fe4 ¤   ¤   }
184b93 ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, session->masterSecret,
f71ee2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize );
f5c138 ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, session->masterSecret,
031ee2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize );
--8afd 000a9375c5c40100246 Page 43 of pgpTLS.c
59acdb ¤   ¤   for( padIndex = 0; padIndex < padSize; padIndex++ )
4786ee ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_ipad;
a237b6 ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, padBuffer,
6dbce4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3SHAPaddingBytes );
1840dc ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, padBuffer,
20771f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3MD5PaddingBytes );
ed7631 ¤   ¤   (void)PGPFinalizeHash( session->lastHandSHA, shaHash );
acc664 ¤   ¤   (void)PGPFinalizeHash( session->lastHandMD5, md5Hash );
161b52 ¤   ¤
5ba5c5 ¤   ¤   (void)PGPResetHash( session->lastHandSHA );
109f3a ¤   ¤   (void)PGPResetHash( session->lastHandMD5 );
ea1b52 ¤   ¤
fe4b93 ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, session->masterSecret,
3a1ee2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize );
d0c138 ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, session->masterSecret,
9e1ee2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize );
58acdb ¤   ¤   for( padIndex = 0; padIndex < padSize; padIndex++ )
839e14 ¤   ¤   ¤   padBuffer[padIndex] = kPGPtls_opad;
c137b6 ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, padBuffer,
6ebce4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3SHAPaddingBytes );
ca40dc ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, padBuffer,
69771f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_SSL3MD5PaddingBytes );
949ddc ¤   ¤   (void)PGPContinueHash( session->lastHandSHA, shaHash,
1ffffc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_SHASize );
2aff3d ¤   ¤   (void)PGPContinueHash( session->lastHandMD5, md5Hash,
fdcffa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size );
8d1b52 ¤   ¤
029f33 ¤   ¤   (void)PGPFinalizeHash( session->lastHandMD5, inBuffer );
47a49a ¤   ¤   pktLen += kPGPtls_HA_MD5Size;
fbf5ac ¤   ¤   (void)PGPFinalizeHash( session->lastHandSHA, inBuffer + pktLen );
05c583 ¤   ¤   pktLen += kPGPtls_HA_SHASize;
b99371 ¤   }
f00e24 ¤   else
e9c7a1 ¤   {
617712 ¤   ¤   PGPByte¤¤   handshakes[kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize];
1e1b52 ¤   ¤
3af1be ¤   ¤   (void)PGPFinalizeHash( session->lastHandMD5, handshakes );
21bef0 ¤   ¤   (void)PGPFinalizeHash( session->lastHandSHA,
0f310f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   handshakes + kPGPtls_HA_MD5Size );
fa7540 ¤   ¤   err = pgpTLSPRF( session, session->masterSecret,
5226c4 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_MasterSecretSize, clientSide ?
e16f19 ¤   ¤   ¤   ¤   ¤   ¤   "client finished" : "server finished", handshakes,
6346c6 ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_HA_MD5Size + kPGPtls_HA_SHASize,
cd1c7e ¤   ¤   ¤   ¤   ¤   ¤   inBuffer, kPGPtls_FinishedSize );¤  CKERR;
d7a180 ¤   ¤   pktLen = kPGPtls_FinishedSize;
a29371 ¤   }
6467c5 ¤
6533f2 ¤   *outSize = pktLen;
e4b38c done:
87eaab ¤   if( PGPHashContextRefIsValid( session->lastHandSHA ) )
e08423 ¤   ¤   (void)PGPFreeHashContext( session->lastHandSHA );
a825dc ¤   session->lastHandSHA = kInvalidPGPHashContextRef;
62e5e9 ¤   if( PGPHashContextRefIsValid( session->lastHandMD5 ) )
35bedc ¤   ¤   (void)PGPFreeHashContext( session->lastHandMD5 );
077934 ¤   session->lastHandMD5 = kInvalidPGPHashContextRef;
6e5ea8 ¤   return err;
dbefe6 }
b4af5a
12c744 ¤   PGPError
b9920e pgpTLSActivateWriteKeys(
6a5775 ¤   PGPtlsSessionPriv *¤¤   ¤   ¤   session )
a3bb36 {
5cf40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
abbb28 ¤   PGPSymmetricCipherContextRef¤   symmContext;
e5af5a
6c4c8f ¤   if( IsntNull( session->writeActive ) )
86c7a1 ¤   {
8d2ce5 ¤   ¤   if( PGPHMACContextRefIsValid( session->writeActive->hmac ) )
936a70 ¤   ¤   ¤   (void)PGPFreeHMACContext( session->writeActive->hmac );
72d29f ¤   ¤   (void)PGPFreeData( session->writeActive );
87c7ad ¤   ¤   session->writeActive = NULL;
a99371 ¤   }
--c025 0006074d6b540100246 Page 44 of pgpTLS.c
17e8fd ¤   if( PGPCBCContextRefIsValid( session->writeCipher ) )
21c7a1 ¤   {
fa953f ¤   ¤   (void)PGPFreeCBCContext( session->writeCipher );
448d5b ¤   ¤   session->writeCipher = kInvalidPGPCBCContextRef;
849371 ¤   }
e767c5 ¤
26aefe ¤   if( session->isClientSide )
57c7a1 ¤   {
5f18cf ¤   ¤   session->writeActive = session->clientPending;
72471d ¤   ¤   session->clientPending = NULL;
1d9371 ¤   }
c50e24 ¤   else
9ac7a1 ¤   {
ea6a10 ¤   ¤   session->writeActive = session->serverPending;
2a676c ¤   ¤   session->serverPending = NULL;
1d9371 ¤   }
3169fa ¤   if( session->cipherSuites[session->cipherSuiteIndex].cipherID !=
c0aac0 ¤   ¤   kPGPCipherAlgorithm_None )
4fc7a1 ¤   {
777b5b ¤   ¤   err = PGPNewSymmetricCipherContext( session->memMgr,
fdb6cb ¤   ¤   ¤   ¤   session->cipherSuites[session->cipherSuiteIndex].cipherID,
0399d7 ¤   ¤   ¤   ¤   session->keySize, &symmContext ); CKERR;
d6fbf4 ¤   ¤   err = PGPNewCBCContext( symmContext, &session->writeCipher ); CKERR;
fe74fb ¤   ¤   err = PGPInitCBC( session->writeCipher,
512731 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->writeActive->cipherKey,
1bfa38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->writeActive->iv ); CKERR;
019371 ¤   }
e5b38c done:
b55ea8 ¤   return err;
dbefe6 }
70af5a
4cc744 ¤   PGPError
960a0f pgpTLSActivateReadKeys(
5b5775 ¤   PGPtlsSessionPriv *¤¤   ¤   ¤   session )
b7bb36 {
04f40d ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
e0bb28 ¤   PGPSymmetricCipherContextRef¤   symmContext;
8faf5a
e31e5a ¤   if( IsntNull( session->readActive ) )
edc7a1 ¤   {
959491 ¤   ¤   if( PGPHMACContextRefIsValid( session->readActive->hmac ) )
4a4d89 ¤   ¤   ¤   (void)PGPFreeHMACContext( session->readActive->hmac );
2b1e8d ¤   ¤   (void)PGPFreeData( session->readActive );
fe6522 ¤   ¤   session->readActive = NULL;
a19371 ¤   }
04f616 ¤   if( PGPCBCContextRefIsValid( session->readCipher ) )
9cc7a1 ¤   {
1a86c4 ¤   ¤   (void)PGPFreeCBCContext( session->readCipher );
afa84b ¤   ¤   session->readCipher = kInvalidPGPCBCContextRef;
d49371 ¤   }
6867c5 ¤
52aefe ¤   if( session->isClientSide )
dac7a1 ¤   {
cb9513 ¤   ¤   session->readActive = session->serverPending;
41676c ¤   ¤   session->serverPending = NULL;
da9371 ¤   }
540e24 ¤   else
a4c7a1 ¤   {
bfe7cc ¤   ¤   session->readActive = session->clientPending;
99471d ¤   ¤   session->clientPending = NULL;
b59371 ¤   }
6c69fa ¤   if( session->cipherSuites[session->cipherSuiteIndex].cipherID !=
59aac0 ¤   ¤   kPGPCipherAlgorithm_None )
4ec7a1 ¤   {
407b5b ¤   ¤   err = PGPNewSymmetricCipherContext( session->memMgr,
ecb6cb ¤   ¤   ¤   ¤   session->cipherSuites[session->cipherSuiteIndex].cipherID,
ea99d7 ¤   ¤   ¤   ¤   session->keySize, &symmContext ); CKERR;
c6f9a3 ¤   ¤   err = PGPNewCBCContext( symmContext, &session->readCipher ); CKERR;
bb3c76 ¤   ¤   err = PGPInitCBC( session->readCipher, session->readActive->cipherKey,
4d5806 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->readActive->iv ); CKERR;
bb9371 ¤   }
60b38c done:
--0f0e 000a17eb20040100246 Page 45 of pgpTLS.c
ec5ea8 ¤   return err;
2aefe6 }
e0af5a
46d497 ¤   PGPInt8
f528c2 pgpTLSPacketToEvent(
4e5066 ¤   PGPByte¤¤   packetType )
f9bb36 {
292ba9 ¤   PGPInt8¤¤   event = 0;
7367c5 ¤
bde7d9 ¤   switch( packetType )
2ec7a1 ¤   {
e6a853 ¤   ¤   case kPGPtls_HT_HelloRequest:
d2f2cd ¤   ¤   ¤   event = kPGPtls_EV_ReceiveHelloRequest;
97cdcb ¤   ¤   ¤   break;
f7fb73 ¤   ¤   case kPGPtls_HT_ClientHello:
14a8fa ¤   ¤   ¤   event = kPGPtls_EV_ReceiveClientHello;
d3cdcb ¤   ¤   ¤   break;
cb0f01 ¤   ¤   case kPGPtls_HT_ServerHello:
2d5c88 ¤   ¤   ¤   event = kPGPtls_EV_ReceiveServerHello;
36cdcb ¤   ¤   ¤   break;
99cdcd ¤   ¤   case kPGPtls_HT_Certificate:
389e44 ¤   ¤   ¤   event = kPGPtls_EV_ReceiveCertificate;
35cdcb ¤   ¤   ¤   break;
ceb1f4 ¤   ¤   case kPGPtls_HT_ServerKeyExchange:
e261ec ¤   ¤   ¤   event = kPGPtls_EV_ReceiveServerKeyExchange;
63cdcb ¤   ¤   ¤   break;
d2f19a ¤   ¤   case kPGPtls_HT_CertificateRequest:
7f21e3 ¤   ¤   ¤   event = kPGPtls_EV_ReceiveCertRequest;
cbcdcb ¤   ¤   ¤   break;
4fc2e6 ¤   ¤   case kPGPtls_HT_ServerHelloDone:
d9679f ¤   ¤   ¤   event = kPGPtls_EV_ReceiveServerHelloDone;
9ccdcb ¤   ¤   ¤   break;
26470d ¤   ¤   case kPGPtls_HT_CertificateVerify:
3d8bea ¤   ¤   ¤   event = kPGPtls_EV_ReceiveCertVerify;
21cdcb ¤   ¤   ¤   break;
50ce15 ¤   ¤   case kPGPtls_HT_ClientKeyExchange:
311e0d ¤   ¤   ¤   event = kPGPtls_EV_ReceiveClientKeyExchange;
efcdcb ¤   ¤   ¤   break;
344528 ¤   ¤   case kPGPtls_HT_Finished:
b50fb2 ¤   ¤   ¤   event = kPGPtls_EV_ReceiveFinished;
33cdcb ¤   ¤   ¤   break;
6e9ae3 ¤   ¤   default:
bfd2bf ¤   ¤   ¤   pgpAssert( 0 );
7d9371 ¤   }
9e9826 ¤   return event;
a6efe6 }
bbaf5a
cec744 ¤   PGPError
89dcb0 pgpTLSClientHandshake(
dc372f ¤   PGPtlsSessionPriv *¤session )
6dbb36 {
0cd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
3f66b8 ¤   PGPByte¤¤   ¤   ¤   pktType;
09ab00 ¤   PGPByte *¤  ¤   ¤   packet = NULL;
674dfe ¤   PGPSize¤¤   ¤   ¤   pktLen;
4f81c8 ¤   PGPInt8¤¤   ¤   ¤   newState;
09e475 ¤   PGPBoolean¤ ¤   ¤   handshaking = TRUE;
8667c5 ¤
6a45af ¤   if( ( session->state == kPGPtls_IdleState ) ||·
dd5015 ¤   ¤   ( session->state == kPGPtls_ReadyState ) )
b6c7a1 ¤   {
456cc7 ¤   ¤   session->state = kPGPtls_HandshakeState;
fc6db5 ¤   ¤   err = pgpTLSSendClientHello( session );
dad223 ¤   ¤   if( IsPGPError( err ) )
471dc4 ¤   ¤   ¤   goto done;
5e9371 ¤   }
739b96 ¤   while( handshaking &&
7e8228 ¤   ¤   ¤   IsntPGPError( err = pgpTLSReceiveHandshakePacket( session,
ddc4a9 ¤   ¤   ¤   &pktType, &packet, &pktLen ) ) && IsntNull( packet ) )
c9c7a1 ¤   {
82fa5f ¤   ¤   newState = pgpTLSNextState( session, pgpTLSPacketToEvent( pktType ) );
a19bab ¤   ¤   if( newState == -2 )
--6702 0002a5e799740100246 Page 46 of pgpTLS.c
e35b34 ¤   ¤   {
960283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
9eeeec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
dd681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
650fe4 ¤   ¤   }
51af47 ¤   ¤   else if( newState == -1 )
4e5b34 ¤   ¤   {
48991b ¤   ¤   ¤   /* do nothing */
260fe4 ¤   ¤   }
98505f ¤   ¤   else switch( pktType )
dc5b34 ¤   ¤   {
880aec ¤   ¤   ¤   case kPGPtls_HT_ServerHello:
aed5e5 ¤   ¤   ¤   ¤   err = pgpTLSReceiveServerHello( session, packet, pktLen );
17f622 ¤   ¤   ¤   ¤   break;
56c820 ¤   ¤   ¤   case kPGPtls_HT_Certificate:
7d90dc ¤   ¤   ¤   ¤   err = pgpTLSReceiveCertificate( session, packet, pktLen );
67f622 ¤   ¤   ¤   ¤   break;
6e206c ¤   ¤   ¤   case kPGPtls_HT_ServerKeyExchange:
e9347c ¤   ¤   ¤   ¤   err = pgpTLSReceiveServerKeyExchange( session, packet, pktLen );
f1f622 ¤   ¤   ¤   ¤   break;
80e9ca ¤   ¤   ¤   case kPGPtls_HT_CertificateRequest:
902033 ¤   ¤   ¤   ¤   err = pgpTLSReceiveCertRequest( session, packet, pktLen );
1cf622 ¤   ¤   ¤   ¤   break;
d2c45e ¤   ¤   ¤   case kPGPtls_HT_ServerHelloDone:
4af60b ¤   ¤   ¤   ¤   err = pgpTLSReceiveServerHelloDone( session, packet, pktLen );
67f622 ¤   ¤   ¤   ¤   break;
2aaa5b ¤   ¤   ¤   case kPGPtls_HT_Finished:
8c31d5 ¤   ¤   ¤   ¤   err = pgpTLSReceiveFinished( session, packet, pktLen );
ec5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
8c72c3 ¤   ¤   ¤   ¤   {
a82128 ¤   ¤   ¤   ¤   ¤   session->state = kPGPtls_ReadyState;
5e400a ¤   ¤   ¤   ¤   ¤   if( PGPHashContextRefIsValid( session->handshakeSHA ) )
144859 ¤   ¤   ¤   ¤   ¤   {
6f8f4c ¤   ¤   ¤   ¤   ¤   ¤   (void)PGPFreeHashContext( session->handshakeSHA );
fb6147 ¤   ¤   ¤   ¤   ¤   ¤   session->handshakeSHA = kInvalidPGPHashContextRef;
6f1c89 ¤   ¤   ¤   ¤   ¤   }
174f48 ¤   ¤   ¤   ¤   ¤   if( PGPHashContextRefIsValid( session->handshakeMD5 ) )
f04859 ¤   ¤   ¤   ¤   ¤   {
ceb5b3 ¤   ¤   ¤   ¤   ¤   ¤   (void)PGPFreeHashContext( session->handshakeMD5 );
a53daf ¤   ¤   ¤   ¤   ¤   ¤   session->handshakeMD5 = kInvalidPGPHashContextRef;
231c89 ¤   ¤   ¤   ¤   ¤   }
45d5b7 ¤   ¤   ¤   ¤   ¤   handshaking = FALSE;
0f2613 ¤   ¤   ¤   ¤   }
34f622 ¤   ¤   ¤   ¤   break;
01db68 ¤   ¤   ¤   default:
957fe1 ¤   ¤   ¤   ¤   pgpAssert( 0 );
d00fe4 ¤   ¤   }
023878 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, packet );
e6d3cc ¤   ¤   packet = NULL;
9fd223 ¤   ¤   if( IsPGPError( err ) )
a11dc4 ¤   ¤   ¤   goto done;
ac2266 ¤   ¤   if( !session->blocking )
b7cdcb ¤   ¤   ¤   break;
b59371 ¤   }
32b38c done:
d62c60 ¤   if( IsntNull( packet ) )
cf3878 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, packet );
305ea8 ¤   return err;
75efe6 }
a3af5a
b6c744 ¤   PGPError
d950d6 pgpTLSServerHandshake(
8f372f ¤   PGPtlsSessionPriv *¤session )
70bb36 {
16d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
6466b8 ¤   PGPByte¤¤   ¤   ¤   pktType;
cfab00 ¤   PGPByte *¤  ¤   ¤   packet = NULL;
094dfe ¤   PGPSize¤¤   ¤   ¤   pktLen;
bd81c8 ¤   PGPInt8¤¤   ¤   ¤   newState;
68e475 ¤   PGPBoolean¤ ¤   ¤   handshaking = TRUE;
a767c5 ¤
2a689f ¤   if( session->state == kPGPtls_ReadyState )
--7669 00002a34c3840100246 Page 47 of pgpTLS.c
f7c7a1 ¤   {
fa6bf0 ¤   ¤   err = pgpTLSSendHandshakePacket( session, kPGPtls_HT_HelloRequest,
38c9c8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, 0 );
74d223 ¤   ¤   if( IsPGPError( err ) )
c71dc4 ¤   ¤   ¤   goto done;
3d9371 ¤   }
593e5a ¤   session->state = kPGPtls_HandshakeState;
c89b96 ¤   while( handshaking &&
b58228 ¤   ¤   ¤   IsntPGPError( err = pgpTLSReceiveHandshakePacket( session,
90c4a9 ¤   ¤   ¤   &pktType, &packet, &pktLen ) ) && IsntNull( packet ) )
75c7a1 ¤   {
5efa5f ¤   ¤   newState = pgpTLSNextState( session, pgpTLSPacketToEvent( pktType ) );
259bab ¤   ¤   if( newState == -2 )
575b34 ¤   ¤   {
e60283 ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
40eeec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
b3681e ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
f70fe4 ¤   ¤   }
94af47 ¤   ¤   else if( newState == -1 )
d35b34 ¤   ¤   {
47991b ¤   ¤   ¤   /* do nothing */
370fe4 ¤   ¤   }
c9505f ¤   ¤   else switch( pktType )
8e5b34 ¤   ¤   {
82fe9e ¤   ¤   ¤   case kPGPtls_HT_ClientHello:
5ded4f ¤   ¤   ¤   ¤   err = pgpTLSReceiveClientHello( session, packet, pktLen );
b8f622 ¤   ¤   ¤   ¤   break;
62c820 ¤   ¤   ¤   case kPGPtls_HT_Certificate:
fa90dc ¤   ¤   ¤   ¤   err = pgpTLSReceiveCertificate( session, packet, pktLen );
61f622 ¤   ¤   ¤   ¤   break;
a95f8d ¤   ¤   ¤   case kPGPtls_HT_ClientKeyExchange:
281341 ¤   ¤   ¤   ¤   err = pgpTLSReceiveClientKeyExchange( session, packet, pktLen );
ebf622 ¤   ¤   ¤   ¤   break;
abd695 ¤   ¤   ¤   case kPGPtls_HT_CertificateVerify:
d03907 ¤   ¤   ¤   ¤   err = pgpTLSReceiveCertVerify( session, packet, pktLen );
b2f622 ¤   ¤   ¤   ¤   break;
dfaa5b ¤   ¤   ¤   case kPGPtls_HT_Finished:
3831d5 ¤   ¤   ¤   ¤   err = pgpTLSReceiveFinished( session, packet, pktLen );
905565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
7f72c3 ¤   ¤   ¤   ¤   {
84d0f4 ¤   ¤   ¤   ¤   ¤   err = pgpTLSSendFinalHandshake( session );
506ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
3a4859 ¤   ¤   ¤   ¤   ¤   {
28079d ¤   ¤   ¤   ¤   ¤   ¤   session->state = kPGPtls_ReadyState;
77155a ¤   ¤   ¤   ¤   ¤   ¤   if( PGPHashContextRefIsValid( session->handshakeSHA ) )
948fec ¤   ¤   ¤   ¤   ¤   ¤   {
9f626b ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void)PGPFreeHashContext( session->handshakeSHA );
5c8c60 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->handshakeSHA = kInvalidPGPHashContextRef;
e5db3c ¤   ¤   ¤   ¤   ¤   ¤   }
861a18 ¤   ¤   ¤   ¤   ¤   ¤   if( PGPHashContextRefIsValid( session->handshakeMD5 ) )
bb8fec ¤   ¤   ¤   ¤   ¤   ¤   {
245894 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void)PGPFreeHashContext( session->handshakeMD5 );
80d088 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->handshakeMD5 = kInvalidPGPHashContextRef;
20db3c ¤   ¤   ¤   ¤   ¤   ¤   }
6dd30f ¤   ¤   ¤   ¤   ¤   ¤   handshaking = FALSE;
511c89 ¤   ¤   ¤   ¤   ¤   }
732613 ¤   ¤   ¤   ¤   }
ecf622 ¤   ¤   ¤   ¤   break;
06db68 ¤   ¤   ¤   default:
4f7fe1 ¤   ¤   ¤   ¤   pgpAssert( 0 );
f10fe4 ¤   ¤   }
db3878 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, packet );
1ad3cc ¤   ¤   packet = NULL;
95d223 ¤   ¤   if( IsPGPError( err ) )
341dc4 ¤   ¤   ¤   goto done;
692266 ¤   ¤   if( !session->blocking )
2dcdcb ¤   ¤   ¤   break;
469371 ¤   }
6db38c done:
962c60 ¤   if( IsntNull( packet ) )
e93878 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, packet );
025ea8 ¤   return err;
--71f5 00015829f9540100246 Page 48 of pgpTLS.c
7aefe6 }
46af5a
b0c744 ¤   PGPError
86cb85 PGPtlsHandshake(
108363 ¤   PGPtlsSessionRef¤   ref )
ffbb36 {
44d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f9fefc ¤   PGPtlsSessionPriv *¤session;
5367c5 ¤
345eb1 ¤   PGPValidatePtr( ref );
1caf5a
9194b1 ¤   session = (PGPtlsSessionPriv *) ref;
e5013f ¤   PGPValidatePtr( session->tlsReceiveProc );
215320 ¤   PGPValidatePtr( session->tlsSendProc );
11af5a
7d4756 ¤   if( ( session->state != kPGPtls_ReadyState ) &&
a461e1 ¤   ¤   ( session->state != kPGPtls_IdleState ) &&
09f8f0 ¤   ¤   ( ( session->state != kPGPtls_HandshakeState ) ||
6d8af5 ¤   ¤   session->blocking ) )
61c7a1 ¤   {
742753 ¤   ¤   err = kPGPError_TLSWrongState;
85262d ¤   ¤   goto done;
d59371 ¤   }
8967c5 ¤
b7aefe ¤   if( session->isClientSide )
ac9f49 ¤   ¤   err = pgpTLSClientHandshake( session );
a80e24 ¤   else
d33ef2 ¤   ¤   err = pgpTLSServerHandshake( session );
51f888 ¤   if(err == kPGPError_TLSWouldBlock)
62b840 ¤   ¤   return kPGPError_NoErr;
49749f ¤   if( IsPGPError( err ) && session->state != kPGPtls_FatalErrorState )
c78f7f ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
2ef691 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_InternalError );
9eb38c done:
7e5ea8 ¤   return err;
e0efe6 }
89af5a
5fc744 ¤   PGPError
348f56 PGPtlsClose(
d4e9c4 ¤   PGPtlsSessionRef¤   ref,
4b3ac8 ¤   PGPBoolean¤ ¤   ¤   dontCache )
8cbb36 {
4ed591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
9dfefc ¤   PGPtlsSessionPriv *¤session;
6b67c5 ¤
fd5eb1 ¤   PGPValidatePtr( ref );
b3af5a
5194b1 ¤   session = (PGPtlsSessionPriv *) ref;
7d67c5 ¤
70e9f2 ¤   if( dontCache )
29953f ¤   ¤   session->state = kPGPtls_FatalErrorState;
3897a6 ¤   else if( session->state == kPGPtls_ReadyState )
e9c7a1 ¤   {
544147 ¤   #define kPGPtlsFlags_DummyPacketSize¤   ¤   16
aaafdf ¤   ¤   PGPByte¤dummyPacket[kPGPtlsFlags_DummyPacketSize];
497e13 ¤   ¤   PGPSize¤packetSize = kPGPtlsFlags_DummyPacketSize;
341b52 ¤   ¤
83c5ab ¤   ¤   if( !session->closeInitiated )
65f956 ¤   ¤   ¤   err = pgpTLSSendAlert( session, kPGPtls_AL_WarningAlert,
632fb1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_CloseNotify ); CKERR;
816edb ¤   ¤   session->closeInitiated = TRUE;
ccaeb0 ¤   ¤   while( IsntPGPError( err ) &&
6a69b0 ¤   ¤   ¤   ¤   ( session->state != kPGPtls_ClosedState ) )
735b34 ¤   ¤   {
5ebfa6 ¤   ¤   ¤   session->appDataSize = 0;
dd1bdb ¤   ¤   ¤   err = PGPtlsReceive( ref, dummyPacket, &packetSize );
f31f0e ¤   ¤   ¤   if( !session->blocking )
56ff25 ¤   ¤   ¤   ¤   goto done;
f00fe4 ¤   ¤   }
b130a7 ¤   ¤   /* Throw away any errors here because the other side may not
eb10e2 ¤   ¤   ¤   have gotten their close through which is technically legal. ·*/
1570bb ¤   ¤   err = kPGPError_NoErr;
--5bef 000799cf7e540100246 Page 49 of pgpTLS.c
a19371 ¤   }
9dca05 ¤   if( session->state != kPGPtls_FatalErrorState )
ca22da ¤   ¤   session->state = kPGPtls_ClosedState;
9367c5 ¤
b8b38c done:
c05ea8 ¤   return err;
f1efe6 }
0faf5a
63c744 ¤   PGPError
9c0f25 PGPtlsReceive(
f7b727 ¤   PGPtlsSessionRef¤   ¤   ref,
051a82 ¤   void *¤ ¤   ¤   ¤   ¤   outBuffer,
d096ad ¤   PGPSize *¤  ¤   ¤   ¤   bufferSize )
90bb36 {
709479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
8f03bc ¤   PGPtlsSessionPriv *¤¤   session;
fcebb0 ¤   PGPByte¤¤   ¤   ¤   ¤   type;
10bd00 ¤   PGPByte *¤  ¤   ¤   ¤   buffer = NULL;
0b1ac6 ¤   PGPSize¤¤   ¤   ¤   ¤   pktLen,
185ac2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   useLen,
4bd91b ¤   ¤   ¤   ¤   ¤   ¤   ¤   maxLen,
690fe2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   outSize = 0;
25af5a
a45eb1 ¤   PGPValidatePtr( ref );
8169e5 ¤   PGPValidatePtr( outBuffer );
1167c5 ¤
f994b1 ¤   session = (PGPtlsSessionPriv *) ref;
16013f ¤   PGPValidatePtr( session->tlsReceiveProc );
e167c5 ¤
895b89 ¤   if( session->state != kPGPtls_ReadyState )
9cc7a1 ¤   {
362753 ¤   ¤   err = kPGPError_TLSWrongState;
28262d ¤   ¤   goto done;
0c9371 ¤   }
8c350c ¤   maxLen = *bufferSize;
16f071 ¤   *bufferSize = 0;
1eaf5a
2f42f2 ¤   if( session->appDataSize > 0 )
fac7a1 ¤   {
c4353f ¤   ¤   if( maxLen < session->appDataSize )
fe29fb ¤   ¤   ¤   outSize = maxLen;
ff0e1d ¤   ¤   else
1c024b ¤   ¤   ¤   outSize = session->appDataSize;
3a1120 ¤   ¤   pgpCopyMemory( session->rcvdAppData, outBuffer, outSize );
20005e ¤   ¤   pgpCopyMemory( session->rcvdAppData + outSize,
4731e0 ¤   ¤   ¤   ¤   ¤   ¤   session->rcvdAppData,
600324 ¤   ¤   ¤   ¤   ¤   ¤   session->appDataSize - outSize );
b2dfd2 ¤   ¤   session->appDataSize -= outSize;
41e5f9 ¤   ¤   err = pgpContextMemRealloc( session->pgpContext,
2f110c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &session->rcvdAppData,
0a708a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->appDataSize, 0 ); CKERR;
96fc6a ¤   ¤   *bufferSize = outSize;
919371 ¤   }
c30e24 ¤   else
66c7a1 ¤   {
af53ee ¤   ¤   err = pgpTLSReceiveRecordLayer( session, &type, &buffer, &pktLen );
a72283 ¤   ¤   CKERR;
979196 ¤   ¤   if( IsNull( buffer ) )
831dc4 ¤   ¤   ¤   goto done;
67f8eb ¤   ¤   switch( type )
4c5b34 ¤   ¤   {
197ae7 ¤   ¤   ¤   case kPGPtls_RT_ApplicationData:
c625c7 ¤   ¤   ¤   ¤   if( pktLen > maxLen - outSize )
209470 ¤   ¤   ¤   ¤   ¤   useLen = maxLen - outSize;
86fa07 ¤   ¤   ¤   ¤   else
042be1 ¤   ¤   ¤   ¤   ¤   useLen = pktLen;
ad4952 ¤   ¤   ¤   ¤   pgpCopyMemory( buffer, (PGPByte *)outBuffer + outSize, useLen );
2f5de0 ¤   ¤   ¤   ¤   outSize += useLen;
e92a1c ¤   ¤   ¤   ¤   if( pktLen > useLen )
7e72c3 ¤   ¤   ¤   ¤   {
749320 ¤   ¤   ¤   ¤   ¤   err = pgpContextMemRealloc( session->pgpContext,
799b49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void **) &session->rcvdAppData,
--812f 00051926d7c40100246 Page 50 of pgpTLS.c
bc229a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->appDataSize + pktLen - useLen,
ead0db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0 ); CKERR;
3cdd90 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory( buffer + useLen,
68f81b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->rcvdAppData + session->appDataSize,
2527f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   pktLen - useLen );
98fe60 ¤   ¤   ¤   ¤   ¤   session->appDataSize += pktLen - useLen;
af2613 ¤   ¤   ¤   ¤   }
5f31e6 ¤   ¤   ¤   ¤   *bufferSize = outSize;
1bf622 ¤   ¤   ¤   ¤   break;
91a842 ¤   ¤   ¤   case kPGPtls_RT_Alert:
8d690c ¤   ¤   ¤   ¤   err = pgpTLSProcessAlert( session, buffer, pktLen ); CKERR;
50f622 ¤   ¤   ¤   ¤   break;
19fd80 ¤   ¤   ¤   case kPGPtls_RT_Handshake:
8d7da8 ¤   ¤   ¤   ¤   if( ( buffer[0] == kPGPtls_HT_HelloRequest ) &&
7a7757 ¤   ¤   ¤   ¤   ¤   session->isClientSide )
e572c3 ¤   ¤   ¤   ¤   {
a0dc4f ¤   ¤   ¤   ¤   ¤   /* server side has requested renegotiation of the keys¤ */
0d1499 ¤   ¤   ¤   ¤   ¤   /* start up the handshake¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   */
88b34f ¤   ¤   ¤   ¤   ¤   if( session->blocking )
7317ef ¤   ¤   ¤   ¤   ¤   ¤   err = pgpTLSClientHandshake( session );
bb4bd6 ¤   ¤   ¤   ¤   ¤   else
1a4c8b ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_TLSRcvdHandshakeRequest;
0b14c3 ¤   ¤   ¤   ¤   ¤   break;
c52613 ¤   ¤   ¤   ¤   }
14db68 ¤   ¤   ¤   default:
ad8fab ¤   ¤   ¤   case kPGPtls_RT_ChangeCipherSpec:
5c110f ¤   ¤   ¤   ¤   (void)pgpTLSSendAlert( session,¤kPGPtls_AL_FatalAlert,
4af5e5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPtls_AT_UnexpectedMessage );
51e749 ¤   ¤   ¤   ¤   FATALTLS( kPGPError_TLSProtocolViolation );
3f0fe4 ¤   ¤   }
1c9371 ¤   }
32b38c done:
c944f6 ¤   if( IsntNull( buffer ) )
45f0a3 ¤   ¤   (void)pgpContextMemFree( session->pgpContext, buffer );
555ea8 ¤   return err;
3befe6 }
37af5a
33c744 ¤   PGPError
a7f4c0 PGPtlsSend(
efb727 ¤   PGPtlsSessionRef¤   ¤   ref,
043011 ¤   const void *¤   ¤   ¤   inBuffer,
075138 ¤   PGPSize¤¤   ¤   ¤   ¤   inBufferLength )
30bb36 {
509479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
a603bc ¤   PGPtlsSessionPriv *¤¤   session;
0054f1 ¤   PGPSize¤¤   ¤   ¤   ¤   sentLength = 0;
e8af5a
f65eb1 ¤   PGPValidatePtr( ref );
0d5f37 ¤   PGPValidatePtr( inBuffer );
77af5a
cb94b1 ¤   session = (PGPtlsSessionPriv *) ref;
4c5320 ¤   PGPValidatePtr( session->tlsSendProc );
5a67c5 ¤
885b89 ¤   if( session->state != kPGPtls_ReadyState )
79c7a1 ¤   {
552753 ¤   ¤   err = kPGPError_TLSWrongState;
ef262d ¤   ¤   goto done;
099371 ¤   }
d167c5 ¤
149255 ¤   while( sentLength < inBufferLength &&
e42b13 ¤   ¤   ( ( err == kPGPError_TLSWouldBlock ) || IsntPGPError( err ) ) )
7fc7a1 ¤   {
3ebf92 ¤   ¤   PGPSize¤¤   ¤   ¤   sizeToSend;
6a1b52 ¤   ¤
5871d0 ¤   ¤   sizeToSend = inBufferLength - sentLength;
31a2cb ¤   ¤   if( sizeToSend > kPGPtls_MaximumDataSize )
d0eae3 ¤   ¤   ¤   sizeToSend = kPGPtls_MaximumDataSize;
b17ecb ¤   ¤   err = pgpTLSSendRecordLayer( session, kPGPtls_RT_ApplicationData,
25ac2c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPByte *)inBuffer + sentLength,
54e097 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeToSend );
58e039 ¤   ¤   sentLength += sizeToSend;
519371 ¤   }
--2998 0002f0b73b540100246 Page 51 of pgpTLS.c
d8b38c done:
ed5ea8 ¤   return err;
5defe6 }
82af5a
abc744 ¤   PGPError
18b05b pgpTLSSendQueueIdleInternal(
f9372f ¤   PGPtlsSessionPriv *¤session )
73bb36 {
687d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
9d6196 ¤   PGPInt32¤   ¤   ¤   serr;
0567c5 ¤
ff9062 ¤   if( IsntNull( session->queuedSendData ) && ( session->queuedSendSize > 0 ) )
1ac7a1 ¤   {
9b6d5b ¤   ¤   serr = (session->tlsSendProc)( session->tlsSendUserData,
4cba27 ¤   ¤   ¤   ¤   ¤   ¤   ¤   session->queuedSendData,
5a0023 ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPInt32) session->queuedSendSize );
68be6f ¤   ¤   if( serr == kPGPError_TLSWouldBlock )
135b34 ¤   ¤   {
fcb1fc ¤   ¤   ¤   err = kPGPError_TLSWouldBlock;
710fe4 ¤   ¤   }
7b379d ¤   ¤   else if( serr == (PGPInt32) session->queuedSendSize )
a95b34 ¤   ¤   {
475e05 ¤   ¤   ¤   session->queuedSendSize = 0;
56c34c ¤   ¤   ¤   err = pgpContextMemRealloc( session->pgpContext,
a88438 ¤   ¤   ¤   ¤   ¤   (void **) &session->queuedSendData, 0, 0 ); CKERR;
310fe4 ¤   ¤   }
5e0e1d ¤   ¤   else
5886c8 ¤   ¤   ¤   FATALTLS( kPGPError_TLSUnexpectedClose );
e69371 ¤   }
3fb38c done:
425ea8 ¤   return err;
f1efe6 }
35af5a
63c744 ¤   PGPError
17b1b4 PGPtlsSendQueueIdle(
528363 ¤   PGPtlsSessionRef¤   ref )
cbbb36 {
20fefc ¤   PGPtlsSessionPriv *¤session;
827d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
dfaf5a
045eb1 ¤   PGPValidatePtr( ref );
5c67c5 ¤
4e94b1 ¤   session = (PGPtlsSessionPriv *) ref;
0467c5 ¤
874b68 ¤   err = pgpTLSSendQueueIdleInternal( session );
121b52 ¤   ¤
385ea8 ¤   return err;
41efe6 }
c2af5a
59c744 ¤   PGPError
281394 PGPtlsSetReceiveCallback(
37b727 ¤   PGPtlsSessionRef¤   ¤   ref,
bc6460 ¤   PGPtlsReceiveProcPtr¤   tlsReceiveProc,
7ea6f2 ¤   void *¤ ¤   ¤   ¤   ¤   inData )
59bb36 {
a7fefc ¤   PGPtlsSessionPriv *¤session;
9eaf5a
795eb1 ¤   PGPValidatePtr( ref );
a109ee ¤   PGPValidatePtr( tlsReceiveProc );
4467c5 ¤
0794b1 ¤   session = (PGPtlsSessionPriv *) ref;
0b93bc ¤   session->tlsReceiveProc¤¤   =¤  tlsReceiveProc;
0a44d1 ¤   session->tlsReceiveUserData¤=¤  inData;
5267c5 ¤
a3151e ¤   return kPGPError_NoErr;
edefe6 }
49af5a
7fc744 ¤   PGPError
43242b PGPtlsSetSendCallback(
a1b727 ¤   PGPtlsSessionRef¤   ¤   ref,
01e68f ¤   PGPtlsSendProcPtr¤  ¤   tlsSendProc,
2fa6f2 ¤   void *¤ ¤   ¤   ¤   ¤   inData )
--5414 000e9aaee4640100246 Page 52 of pgpTLS.c
2cbb36 {
6dfefc ¤   PGPtlsSessionPriv *¤session;
c2af5a
c95eb1 ¤   PGPValidatePtr( ref );
16d488 ¤   PGPValidatePtr( tlsSendProc );
3967c5 ¤
cd94b1 ¤   session = (PGPtlsSessionPriv *) ref;
092034 ¤   session->tlsSendProc¤   ¤   =¤  tlsSendProc;
3c84b9 ¤   session->tlsSendUserData¤   =¤  inData;
1367c5 ¤
dd151e ¤   return kPGPError_NoErr;
41efe6 }
42af5a
cbc744 ¤   PGPError
2bccd5 PGPtlsSetProtocolOptions(
30b727 ¤   PGPtlsSessionRef¤   ¤   ref,
7aa29f ¤   PGPtlsFlags¤¤   ¤   ¤   options )
d4bb36 {
f0fefc ¤   PGPtlsSessionPriv *¤session;
90af5a
7f5eb1 ¤   PGPValidatePtr( ref );
9067c5 ¤
3c94b1 ¤   session = (PGPtlsSessionPriv *) ref;
a567c5 ¤
b68d68 ¤   if( options & kPGPtlsFlags_ServerSide )
9c6650 ¤   ¤   session->isClientSide = FALSE;
5c791a ¤   if( options & kPGPtlsFlags_ClientSide )
b8be05 ¤   ¤   session->isClientSide = TRUE;
17b70b ¤   if( options & kPGPtlsFlags_RequestClientCert )
b98494 ¤   ¤   session->requestCert = TRUE;
16a523 ¤   if( options & kPGPtlsFlags_NonBlockingIO )
dc9e94 ¤   ¤   session->blocking = FALSE;
9daf5a
57151e ¤   return kPGPError_NoErr;
4fefe6 }
61af5a
f269b9 static const PGPOptionType sTLSOptionSet[] =
25bb36 {
f44990 ¤   kPGPOptionType_Passphrase,
b4e809 ¤   kPGPOptionType_Passkey
f582f7 };
22af5a
b2c744 ¤   PGPError
d3b3a7 PGPtlsSetLocalPrivateKey(
40b727 ¤   PGPtlsSessionRef¤   ¤   ref,
4e50ff ¤   PGPKeyRef¤  ¤   ¤   ¤   inKey,
21f256 ¤   PGPOptionListRef¤   ¤   firstOption,
a55825 ¤   ... )
20bb36 {
6f9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
b603bc ¤   PGPtlsSessionPriv *¤¤   session;
52009f ¤   PGPBoolean¤ ¤   ¤   ¤   secret,
4a3f03 ¤   ¤   ¤   ¤   ¤   ¤   ¤   disabled,
cb6775 ¤   ¤   ¤   ¤   ¤   ¤   ¤   revoked,
4335b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   expired,
98dade ¤   ¤   ¤   ¤   ¤   ¤   ¤   canSign;
43966b ¤   PGPInt32¤   ¤   ¤   ¤   algID;
e19e14 ¤   void¤   ¤   ¤   ¤   ¤   *passedPhrase = NULL;
d97f02 ¤   PGPSize¤¤   ¤   ¤   ¤   passedLength;
96e0ef ¤   PGPOptionListRef¤   ¤   optionList = kInvalidPGPOptionListRef;
bf3399 ¤   va_list¤¤   ¤   ¤   ¤   args;
5faf5a
115eb1 ¤   PGPValidatePtr( ref );
a2553b ¤   PGPValidatePtr( inKey );
23af5a
7994b1 ¤   session = (PGPtlsSessionPriv *) ref;
eb67c5 ¤
58430c ¤   va_start( args, firstOption );
6dea98 ¤   optionList = pgpBuildOptionListArgs(session->pgpContext,
82b1ca ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FALSE, firstOption, args);
47bee0 ¤   va_end( args );
e967c5 ¤
--e599 000f30df36240100246 Page 53 of pgpTLS.c
38704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
dbd37d ¤   err = pgpGetOptionListError( optionList );¤ CKERR;
79e73b ¤   err = pgpCheckOptionsInSet( optionList, sTLSOptionSet,
f2ef75 ¤   ¤   ¤   ¤   sizeof(sTLSOptionSet) / sizeof(PGPOptionType) ); CKERR;
0267c5 ¤
0ee102 ¤   err = PGPGetKeyBoolean( inKey, kPGPKeyPropIsSecret, &secret ); CKERR;
345218 ¤   err = PGPGetKeyBoolean( inKey, kPGPKeyPropIsDisabled, &disabled ); CKERR;
dfb0d7 ¤   err = PGPGetKeyBoolean( inKey, kPGPKeyPropIsExpired, &expired ); CKERR;
306a94 ¤   err = PGPGetKeyBoolean( inKey, kPGPKeyPropIsRevoked, &revoked ); CKERR;
aa7df8 ¤   err = PGPGetKeyBoolean( inKey, kPGPKeyPropCanSign, &canSign ); CKERR;
ca67c5 ¤
1ffe19 ¤   if( !secret || disabled || expired || revoked || !canSign )
5fc7a1 ¤   {
8ecaed ¤   ¤   err = kPGPError_TLSKeyUnusable;
09262d ¤   ¤   goto done;
b49371 ¤   }
fa76d3 ¤   err = PGPGetKeyNumber( inKey, kPGPKeyPropAlgID, &algID ); CKERR;
5467c5 ¤
179af7 ¤   session->localKey = inKey;
4184de ¤   session->localKeyAlg = (PGPPublicKeyAlgorithm)algID;
b667c5 ¤
eb3620 ¤   err = pgpFindOptionArgs( optionList, kPGPOptionType_Passphrase, FALSE,
9a3865 ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passedPhrase, &passedLength ); CKERR;
ec195c ¤   if( IsNull( passedPhrase ) )
8bc7a1 ¤   {
ac3dff ¤   ¤   err = pgpFindOptionArgs( optionList, kPGPOptionType_Passkey, FALSE,
7b3865 ¤   ¤   ¤   ¤   ¤   ¤   "%p%l", &passedPhrase, &passedLength ); CKERR;
4d9e47 ¤   ¤   session->localKeyPasskeyBuffer = PGPNewSecureData( session->memMgr,
d0c489 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passedLength,
bce779 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
77bf07 ¤   ¤   if( IsNull( session->localKeyPasskeyBuffer ) )
415b34 ¤   ¤   {
8fb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
ae1dc4 ¤   ¤   ¤   goto done;
240fe4 ¤   ¤   }
ac91b8 ¤   ¤   pgpCopyMemory( passedPhrase, session->localKeyPasskeyBuffer,
820e1c ¤   ¤   ¤   ¤   ¤   ¤   passedLength );
897df6 ¤   ¤   session->localKeyUsePasskey = TRUE;
f89371 ¤   }
ef0e24 ¤   else
97c7a1 ¤   {
577790 ¤   ¤   session->localKeyPassphrase = PGPNewSecureData( session->memMgr,
a3913f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   passedLength + 1,
19e779 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
a3892b ¤   ¤   if( IsNull( session->localKeyPassphrase ) )
655b34 ¤   ¤   {
74b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
7b1dc4 ¤   ¤   ¤   goto done;
a60fe4 ¤   ¤   }
c3932e ¤   ¤   pgpCopyMemory( passedPhrase, session->localKeyPassphrase,
f9cb49 ¤   ¤   ¤   ¤   ¤   passedLength );
12a95d ¤   ¤   session->localKeyPassphrase[passedLength] = '\0';
18a387 ¤   ¤   session->localKeyUsePasskey = FALSE;
b49371 ¤   }
4d67c5 ¤
2fb38c done:
032dd8 ¤   /* do not explicitly free passedPhrase, it is freed with the OptionList */
a0ce49 ¤   if( PGPOptionListRefIsValid( optionList ) )
07153d ¤   ¤   PGPFreeOptionList( optionList );
625ea8 ¤   return err;
72efe6 }
9cae30 ¤   ¤   ¤   ¤   ¤
abc744 ¤   PGPError
09f19d PGPtlsSetPreferredCipherSuite(
92b727 ¤   PGPtlsSessionRef¤   ¤   ref,
cff625 ¤   PGPtlsCipherSuiteNum¤   cipher )
15bb36 {
4b9479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
ec03bc ¤   PGPtlsSessionPriv *¤¤   session;
b7cc72 ¤   PGPUInt16¤  ¤   ¤   ¤   suiteIndex;
b4fe91 ¤   PGPBoolean¤ ¤   ¤   ¤   found = FALSE;
f3af5a
--5cf6 0000d0a862040100246 Page 54 of pgpTLS.c
5a5eb1 ¤   PGPValidatePtr( ref );
7c94b1 ¤   session = (PGPtlsSessionPriv *) ref;
9067c5 ¤
f4603e ¤   if( session->state == kPGPtls_IdleState )
93c7a1 ¤   {
27b16c ¤   ¤   for( suiteIndex = 0; suiteIndex < session->numCipherSuites;
5e130c ¤   ¤   ¤   ¤   suiteIndex++ )
b25b34 ¤   ¤   {
a617c4 ¤   ¤   ¤   if( cipher == session->cipherSuites[ suiteIndex ].suite )
cff776 ¤   ¤   ¤   {
a7b190 ¤   ¤   ¤   ¤   found = TRUE;
0cf622 ¤   ¤   ¤   ¤   break;
cca3a6 ¤   ¤   ¤   }
2d0fe4 ¤   ¤   }
2947f9 ¤   ¤   if( found )
f05b34 ¤   ¤   {
00fada ¤   ¤   ¤   PGPtlsCipherSuite¤  saved;
3387c7 ¤   ¤   ¤
f8269e ¤   ¤   ¤   saved = session->cipherSuites[ suiteIndex ];
812111 ¤   ¤   ¤   for( ; suiteIndex > 0; suiteIndex-- )
d03883 ¤   ¤   ¤   ¤   session->cipherSuites[ suiteIndex ] =
520912 ¤   ¤   ¤   ¤   ¤   session->cipherSuites[ suiteIndex - 1 ];
6e9dd2 ¤   ¤   ¤   session->cipherSuites[ 0 ] = saved;
a50fe4 ¤   ¤   }
970e1d ¤   ¤   else
9813f1 ¤   ¤   ¤   err = kPGPError_ItemNotFound;
219371 ¤   }
a50e24 ¤   else
e42753 ¤   ¤   err = kPGPError_TLSWrongState;
ab67c5 ¤
305ea8 ¤   return err;
65efe6 }
72af5a
40c744 ¤   PGPError
c53476 PGPtlsSetRemoteUniqueID(
55b727 ¤   PGPtlsSessionRef¤   ¤   ref,
842b36 ¤   PGPUInt32¤  ¤   ¤   ¤   remoteID )
9cbb36 {
5c5b27 ¤   (void) ref;
9ff34c ¤   (void) remoteID;
0967c5 ¤
e432c3 ¤   /* ##### */
35151e ¤   return kPGPError_NoErr;
22efe6 }
41af5a
c8c744 ¤   PGPError
4fb8e2 PGPtlsSetDHPrime(
fde9c4 ¤   PGPtlsSessionRef¤   ref,
359594 ¤   PGPtlsPrime¤¤   ¤   prime )
01bb36 {
abd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
b6fefc ¤   PGPtlsSessionPriv *¤session;
b3af5a
a15eb1 ¤   PGPValidatePtr( ref );
2194b1 ¤   session = (PGPtlsSessionPriv *) ref;
b7567d ¤   pgpAssert(¤ prime == kPGPtls_DHPrime1024 || prime == kPGPtls_DHPrime1536 ||
ea84b4 ¤   ¤   ¤   ¤   prime == kPGPtls_DHPrime2048 || prime == kPGPtls_DHPrime3072 ||
8d4f82 ¤   ¤   ¤   ¤   prime == kPGPtls_DHPrime4096 );
5067c5 ¤
cb603e ¤   if( session->state == kPGPtls_IdleState )
be79c6 ¤   ¤   session->requestedPrime = prime;
c20e24 ¤   else
172753 ¤   ¤   err = kPGPError_TLSWrongState;
4167c5 ¤
cc5ea8 ¤   return err;
a4efe6 }
6faf5a
b5c744 ¤   PGPError
6daa13 PGPtlsGetRemoteAuthenticatedKey(
7ce9c4 ¤   PGPtlsSessionRef¤   ref,
318900 ¤   PGPKeyRef *¤¤   ¤   outKey )
0dbb36 {
--5a61 0001784d22840100246 Page 55 of pgpTLS.c
a4d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
d1fefc ¤   PGPtlsSessionPriv *¤session;
a0af5a
005eb1 ¤   PGPValidatePtr( ref );
3994b1 ¤   session = (PGPtlsSessionPriv *) ref;
7067c5 ¤
40e275 ¤   *outKey = kInvalidPGPKeyRef;
d5689f ¤   if( session->state == kPGPtls_ReadyState )
2d76cd ¤   ¤   *outKey = session->remoteKey;
340e24 ¤   else
a42753 ¤   ¤   err = kPGPError_TLSWrongState;
e267c5 ¤
1c5ea8 ¤   return err;
5cefe6 }
55af5a
99c744 ¤   PGPError
b2d5b0 PGPtlsGetNegotiatedCipherSuite(
44b727 ¤   PGPtlsSessionRef¤   ¤   ref,
48a6b5 ¤   PGPtlsCipherSuiteNum *¤ outCipher )
3abb36 {
c49479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
2403bc ¤   PGPtlsSessionPriv *¤¤   session;
beaf5a
3b5eb1 ¤   PGPValidatePtr( ref );
2694b1 ¤   session = (PGPtlsSessionPriv *) ref;
7a67c5 ¤
2a82bd ¤   *outCipher = kPGPtls_TLS_NULL_WITH_NULL_NULL;
d8689f ¤   if( session->state == kPGPtls_ReadyState )
8c6b77 ¤   ¤   *outCipher = session->cipherSuites[session->cipherSuiteIndex].suite;
270e24 ¤   else
a02753 ¤   ¤   err = kPGPError_TLSWrongState;
9667c5 ¤
3b5ea8 ¤   return err;
1eefe6 }
8faf5a
33c744 ¤   PGPError
871b81 PGPtlsGetState(
44b727 ¤   PGPtlsSessionRef¤   ¤   ref,
ba77bc ¤   PGPtlsProtocolState *¤  outState )
e3bb36 {
8d03bc ¤   PGPtlsSessionPriv *¤¤   session;
27af5a
285eb1 ¤   PGPValidatePtr( ref );
4afbbd ¤   PGPValidatePtr( outState );
ea94b1 ¤   session = (PGPtlsSessionPriv *) ref;
3567c5 ¤
c8b772 ¤   *outState = session->state;
3467c5 ¤
dd151e ¤   return kPGPError_NoErr;
94efe6 }
27af5a
d3c744 ¤   PGPError
ad43d8 PGPtlsGetAlert(
c0e9c4 ¤   PGPtlsSessionRef¤   ref,
de5b4b ¤   PGPtlsAlert *¤  ¤   outAlert )
0fbb36 {
7afefc ¤   PGPtlsSessionPriv *¤session;
14af5a
ba5eb1 ¤   PGPValidatePtr( ref );
23219f ¤   PGPValidatePtr( outAlert );
a794b1 ¤   session = (PGPtlsSessionPriv *) ref;
c267c5 ¤
6345a9 ¤   *outAlert = session->fatalAlert;
a967c5 ¤
07151e ¤   return kPGPError_NoErr;
56efe6 }
55af5a
aeaf5a
347e4d /*__Editor_settings____
0faf5a
9a4126 ¤   Local Variables:
177b17 ¤   tab-width: 4
--cb68 001e49d6e0640100246 Page 56 of pgpTLS.c
490e6c ¤   End:
d25f8c ¤   vi: ts=4 sw=4
979e9b ¤   vim: si
e47c50 _____________________*/¶
--f216 000bc70f93740100247 Page 1 of pgpTLSPrimes.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
397888 ¤   These primes were initially generated for PGPfone. ·Documentation
595d1f ¤   on exactly how they were generated can be found in the PGPfone
097a9b ¤   Owner's Manual.
cdaf5a
29666f ¤   $Id: pgpTLSPrimes.c,v 1.3.10.1 1998/11/12 03:22:50 heller Exp $
b9f7f7 ____________________________________________________________________________*/
f683af #include "pgpTLSPrimes.h"
95af5a
8e6d4d DHPrime¤DH_256bitPrime = {256/8, {
b69b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
9a03a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
0ddc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
5a9be0 ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x28, 0x54, 0x03 }
8c82f7 };
a5af5a
c8f79a DHPrime¤DH_512bitPrime = {512/8, {
49d1b9 ········0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
5476d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
b12347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
87baa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
5f9b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
5d03a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
d7dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
ae0c1a ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2A, 0x05, 0x5F }
c082f7 };
13af5a
cb32eb DHPrime¤DH_768bitPrime = {768/8, {
0aca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
d2c156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
be7583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
ce55cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
f7fc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
c676d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
e62347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
17baa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
4d9b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
6803a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
f9dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
474d97 ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2B, 0x1A, 0xB3 }
0882f7 };
9faf5a
d4e8c2 DHPrime¤DH_1024bitPrime = {1024/8, {
4a11bf ········0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
4c0212 ········0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
6cc672 ········0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
d56d21 ········0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
2aca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
14c156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
877583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
fc55cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
26fc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
2276d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
022347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
1abaa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
a29b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
8a03a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
3fdc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
4883b8 ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2F, 0x78, 0xC7 }
7582f7 };
9eaf5a
8b79e7 DHPrime¤DH_1280bitPrime = {1280/8, {
78525e ········0xE1, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
0d74c8 ········0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
a6b7a0 ········0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
7438d0 ········0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
4b11bf ········0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
d00212 ········0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
bcc672 ········0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
--5a3c 0007557612b40100247 Page 2 of pgpTLSPrimes.c
cf6d21 ········0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
beca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
2ac156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
3f7583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
8455cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
8ffc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
0b76d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
ae2347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
ddbaa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
349b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
4703a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
d0dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
8e7ad5 ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2C, 0xA6, 0x6F }
9182f7 };
54af5a
9b798e DHPrime¤DH_1536bitPrime = {1536/8, {
3eb40c ········0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
4a4c1b ········0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
3ee38a ········0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
da8755 ········0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
f3d34e ········0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
3574c8 ········0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
c2b7a0 ········0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
3b38d0 ········0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
8111bf ········0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
b70212 ········0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
afc672 ········0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
3a6d21 ········0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
2cca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
05c156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
627583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
d255cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
cefc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
7b76d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
162347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
abbaa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
599b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
6503a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
90dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
3ff47a ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x58, 0x7C, 0x47 }
a482f7 };
03af5a
0ee5e2 DHPrime¤DH_2048bitPrime = {2048/8, {
ab4537 ········0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
81fac4 ········0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
f9ef70 ········0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
4b733f ········0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
f15b61 ········0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
87931d ········0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
5b93db ········0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
c4c4d5 ········0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
9fb40c ········0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
444c1b ········0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
c6e38a ········0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
ae8755 ········0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
83d34e ········0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
da74c8 ········0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
85b7a0 ········0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
4c38d0 ········0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
0311bf ········0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
150212 ········0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
21c672 ········0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
dd6d21 ········0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
c1ca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
a5c156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
d97583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
5555cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
2afc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
5776d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
002347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
26baa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
759b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
--6b85 0006ee8183b40100247 Page 3 of pgpTLSPrimes.c
eb03a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
d4dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
b158a2 ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x32, 0x0B, 0x3B }
1282f7 };
73af5a
97840d DHPrime DH_3072bitPrime = {3072/8, {
77e810 ········0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2,
675a25 ········0xC4, 0xF0, 0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E,
870131 ········0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB, 0x25, 0x0E,
9d77ae ········0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
f0bae9 ········0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
0fa53a ········0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60,
0bfb81 ········0xC3, 0xE3, 0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28,
992723 ········0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3, 0x65, 0x0F,
63f406 ········0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
53c294 ········0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
543a8f ········0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4,
bf6ce4 ········0x40, 0xE9, 0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D,
4d15a8 ········0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68, 0x5E, 0x9D,
d2eac0 ········0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
cd7cb2 ········0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
0bd9bb ········0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32,
e74537 ········0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
62fac4 ········0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
f4ef70 ········0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
f2733f ········0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
955b61 ········0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
b2931d ········0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
5193db ········0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
f8c4d5 ········0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
5fb40c ········0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
8c4c1b ········0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
07e38a ········0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
cb8755 ········0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
88d34e ········0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
7474c8 ········0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
31b7a0 ········0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
7c38d0 ········0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
9711bf ········0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
f90212 ········0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
02c672 ········0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
616d21 ········0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
c0ca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
b4c156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
b87583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
0e55cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
95fc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
aa76d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
3f2347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
d3baa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
f29b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
b203a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
36dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
f95f83 ········0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x4C, 0x32, 0x6F }
c782f7 };
e9af5a
6138e5 /*
32b97f ·* This prime was generated on a 275 MHz DEC Alpha - and it took 76 hours
6df5ad ·* (more than 3 days) on *that*. ·It performed 59592 modular exponentiations
5545ca ·* (dots printed) before it found the prime. ·You *can* verify it yourself,
fc555d ·* and I hope that someone does, but be warned! ·It will take a *long*
73c473 ·* time. ·Another run, started several days earlier on a 50 MHz SPARC,
81a48a ·* has used 9 days and 14 hours *of CPU time* and is not finished yet.
6a495d ·*/
28439c DHPrime DH_4096bitPrime = {4096/8, {
aefeb0 ········0xF9, 0x18, 0xA0, 0x7E, 0x5A, 0x06, 0x61, 0x7A,
281ecd ········0x43, 0x90, 0x95, 0xDC, 0x05, 0x6C, 0x87, 0x86,
f1ba43 ········0xEC, 0x61, 0xEC, 0xCD, 0x45, 0x1F, 0x0E, 0xD8,
6bbed0 ········0xE0, 0xA3, 0x79, 0xC6, 0xC9, 0xDC, 0x7A, 0x0B,
9337ba ········0xAC, 0xE4, 0x3F, 0xE3, 0x46, 0x94, 0xB6, 0x30,
0278dd ········0x4A, 0x53, 0xD7, 0x7C, 0x02, 0x16, 0x48, 0x80,
6e0d20 ········0xB5, 0x15, 0xE5, 0x29, 0x99, 0xA9, 0x9F, 0x07,
--fdd9 001f2e4743c40100247 Page 4 of pgpTLSPrimes.c
8c14b5 ········0x74, 0xD3, 0xFF, 0xE3, 0xA1, 0xC5, 0x96, 0x20,
0fa809 ········0x4E, 0x98, 0x65, 0xB8, 0xD8, 0x0D, 0xEE, 0x10,
85fde8 ········0x5D, 0xAB, 0xB6, 0x17, 0x1C, 0x51, 0xD8, 0x50,
82041c ········0xCA, 0x22, 0x57, 0x43, 0x29, 0xBE, 0x95, 0xE8,
bf9da1 ········0x56, 0x2B, 0x38, 0x78, 0x5C, 0x0B, 0xDB, 0xF8,
d18b68 ········0x4C, 0x4D, 0xD5, 0xE3, 0xAA, 0x46, 0xCC, 0xFB,
486a03 ········0xCE, 0x17, 0xE8, 0x2A, 0x9D, 0x14, 0x61, 0xE3,
9b2022 ········0x84, 0xA9, 0x4F, 0xD1, 0x83, 0x84, 0xA8, 0x79,
4eafaf ········0xB6, 0xEF, 0x8F, 0xA7, 0x43, 0x46, 0x08, 0xC6,
a5e810 ········0xCC, 0x1D, 0x77, 0x57, 0x24, 0x38, 0x4A, 0xE2,
055a25 ········0xC4, 0xF0, 0xE8, 0x8E, 0x13, 0x67, 0x97, 0x4E,
700131 ········0x92, 0x13, 0x61, 0xF6, 0xDB, 0xEB, 0x25, 0x0E,
f277ae ········0x17, 0xFD, 0xF6, 0x98, 0xF7, 0xC8, 0x7C, 0x79,
6ebae9 ········0xB0, 0x72, 0x1D, 0x38, 0x75, 0xFB, 0xF6, 0xC1,
9fa53a ········0x73, 0xC4, 0x83, 0x11, 0x26, 0x2B, 0x43, 0x60,
40fb81 ········0xC3, 0xE3, 0xE8, 0xD6, 0x0A, 0xFD, 0xA1, 0x28,
5c2723 ········0x26, 0x0B, 0xAE, 0xA9, 0xAE, 0xB3, 0x65, 0x0F,
91f406 ········0xA2, 0x00, 0x53, 0x01, 0xA0, 0x7C, 0xD6, 0xAB,
7dc294 ········0xA3, 0x12, 0x1E, 0xFA, 0x0F, 0x2A, 0xCE, 0x1F,
9a3a8f ········0x74, 0x84, 0x4F, 0xCA, 0xF3, 0x17, 0xF3, 0xA4,
176ce4 ········0x40, 0xE9, 0xD7, 0xD2, 0x77, 0xB6, 0x42, 0x2D,
de15a8 ········0x02, 0x36, 0xC1, 0x26, 0xCB, 0x68, 0x5E, 0x9D,
42eac0 ········0x7C, 0x98, 0x09, 0x0A, 0x8D, 0x7E, 0x2D, 0xED,
697cb2 ········0xE4, 0x5D, 0x79, 0xF5, 0xD4, 0x92, 0x4F, 0x9B,
e6d9bb ········0x18, 0x8E, 0xFC, 0x2A, 0xA7, 0x4B, 0x7C, 0x32,
744537 ········0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17,
ecfac4 ········0x72, 0xA2, 0xBA, 0xD6, 0xA9, 0x42, 0xF3, 0x05,
8eef70 ········0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
53733f ········0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7,
b95b61 ········0x56, 0xA3, 0x14, 0xE9, 0x8F, 0x40, 0x55, 0xF3,
a9931d ········0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
8993db ········0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83,
9fc4d5 ········0xBD, 0x65, 0xE9, 0x17, 0xD4, 0xA1, 0xD3, 0x50,
3ab40c ········0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
5a4c1b ········0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57,
abe38a ········0x92, 0x59, 0xCD, 0xFD, 0xB8, 0xAE, 0x74, 0x4F,
f48755 ········0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
f0d34e ········0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9,
0974c8 ········0xBB, 0xFD, 0x91, 0x5E, 0xC7, 0x01, 0xAA, 0xD3,
acb7a0 ········0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
0438d0 ········0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5,
3311bf ········0xF4, 0x88, 0xFD, 0x58, 0x4E, 0x49, 0xDB, 0xCD,
d70212 ········0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
d5c672 ········0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C,
be6d21 ········0x88, 0xB3, 0x1C, 0x7C, 0x5B, 0x2D, 0x8E, 0xF6,
3bca86 ········0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
54c156 ········0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D,
5a7583 ········0x38, 0xD3, 0x34, 0xFD, 0x7C, 0x17, 0x57, 0x43,
4155cc ········0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
60fc03 ········0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
1176d2 ········0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
d12347 ········0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
a6baa0 ········0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
899b6b ········0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
bc03a6 ········0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
05dc1d ········0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
f27e70 ········0xA2, 0x5E, 0xC3, 0x55, 0xEB, 0x3D, 0xD6, 0x17 }
7282f7 };
81af5a
42af5a
b87e4d /*__Editor_settings____
ceaf5a
844126 ¤   Local Variables:
bf7b17 ¤   tab-width: 4
8e0e6c ¤   End:
755f8c ¤   vi: ts=4 sw=4
cd9e9b ¤   vim: si
f2d062 _____________________*/
--5291 00102606f0940100248 Page 1 of pgpTLSPrimes.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
d39e1f ¤   $Id: pgpTLSPrimes.h,v 1.2.12.1 1998/11/12 03:22:51 heller Exp $
4df7f7 ____________________________________________________________________________*/
b43169 #ifndef Included_pgpTLSPrimes_h¤/* [ */
d68b02 #define Included_pgpTLSPrimes_h
7baf5a
03e82c #include "pgpPubTypes.h"
c6af5a
cd824b typedef struct DHPrime
7fbb36 {
94cabf ¤   PGPInt16¤   length;¤¤   // byte length of the prime
1ed8c8 ¤   PGPByte¤¤   prime[512];¤// the prime
23485e } DHPrime;
71af5a
4593ba extern DHPrime¤ DH_1024bitPrime;
4dcee2 extern DHPrime¤ DH_1280bitPrime;
d9aed4 extern DHPrime¤ DH_1536bitPrime;
63f5b6 extern DHPrime¤ DH_2048bitPrime;
7e1b3a extern DHPrime¤ DH_3072bitPrime;
3638c9 extern DHPrime¤ DH_4096bitPrime;
aeaf5a
84dc93 #endif /* ] Included_pgpTLSPrimes_h */
7baf5a
caaf5a
e07e4d /*__Editor_settings____
32af5a
174126 ¤   Local Variables:
8f7b17 ¤   tab-width: 4
460e6c ¤   End:
195f8c ¤   vi: ts=4 sw=4
859e9b ¤   vim: si
02d062 _____________________*/
--e4a5 000eb325eab40100249 Page 1 of pgpTLSPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
8d2603 ¤   $Id: pgpTLSPriv.h,v 1.28.2.1.2.1 1998/11/12 03:22:51 heller Exp $
84f7f7 ____________________________________________________________________________*/
2a97d3 #ifndef Included_pgpTLSPriv_h¤  /* [ */
0f7878 #define Included_pgpTLSPriv_h
b8af5a
89ec82 #include "pgpTLS.h"
f86773 #include "pgpMemoryMgr.h"
ff4447 #include "pgpBigNum.h"
64af5a
a134f6 #define¤kPGPtls_MajorVersion¤   ¤   ¤   ¤   3
c7d6f2 #define¤kPGPtls_MinorVersion¤   ¤   ¤   ¤   1
925eda #define¤kPGPtls_SSL3MinorVersion¤   ¤   ¤   0
b8af5a
f96a31 #define¤kPGPtls_MaximumPacketSize¤  ¤   ¤   18432/* 2^14+2048 ::6.2.3 */
6491e2 #define kPGPtls_MaximumDataSize¤¤   ¤   ¤   16384
4e20bb #define¤kPGPtls_RecordHeaderSize¤   ¤   ¤   5
93c2f3 #define¤kPGPtls_RandomSeedSize¤ ¤   ¤   ¤   28
ed9fd5 #define¤kPGPtls_RandomSize¤ ¤   ¤   ¤   ¤   32
5dd2a7 #define¤kPGPtls_MasterSecretSize¤   ¤   ¤   48
2b357a #define¤kPGPtls_CipherBlockSize¤¤   ¤   ¤   8
6f4d87 #define kPGPtls_FinishedSize¤   ¤   ¤   ¤   12
a1505b #define¤kPGPtls_SSL3MD5PaddingBytes¤¤   ¤   48
a34df5 #define¤kPGPtls_SSL3SHAPaddingBytes¤¤   ¤   40
82f847 #define¤kPGPtls_ipad¤   ¤   ¤   ¤   ¤   ¤   0x36
6329b9 #define¤kPGPtls_opad¤   ¤   ¤   ¤   ¤   ¤   0x5C
ede1df #define kPGPtls_MaxHashSize¤¤   ¤   ¤   ¤   20
8551db #define¤kPGPtls_SequenceNumberSize¤ ¤   ¤   8
a7af5a
8baf5a
6a8dba /* Record Types */
88076c #define¤kPGPtls_RT_ChangeCipherSpec¤¤   ¤   20
308ebd #define¤kPGPtls_RT_Alert¤   ¤   ¤   ¤   ¤   21
9da8ac #define¤kPGPtls_RT_Handshake¤   ¤   ¤   ¤   22
7c41d3 #define¤kPGPtls_RT_ApplicationData¤ ¤   ¤   23
e3af5a
e558d3 /* Handshake Types */
5ae1b5 #define¤kPGPtls_HT_HelloRequest¤¤   ¤   ¤   0
7f99ee #define¤kPGPtls_HT_ClientHello¤ ¤   ¤   ¤   1
402262 #define¤kPGPtls_HT_ServerHello¤ ¤   ¤   ¤   2
a8b76b #define¤kPGPtls_HT_Certificate¤ ¤   ¤   ¤   11
486950 #define¤kPGPtls_HT_ServerKeyExchange¤   ¤   12
e65e52 #define¤kPGPtls_HT_CertificateRequest¤  ¤   13
4656ba #define¤kPGPtls_HT_ServerHelloDone¤ ¤   ¤   14
92625c #define¤kPGPtls_HT_CertificateVerify¤   ¤   15
bfaf8b #define¤kPGPtls_HT_ClientKeyExchange¤   ¤   16
4f85fd #define¤kPGPtls_HT_Finished¤¤   ¤   ¤   ¤   20
c1af5a
85e19a /* Alert Levels */
2e1f3d #define¤kPGPtls_AL_FatalAlert¤  ¤   ¤   ¤   2
7f2b6c #define¤kPGPtls_AL_WarningAlert¤¤   ¤   ¤   1
20af5a
852f3f /* Compression Types */
3f532b #define¤kPGPtls_CT_None¤¤   ¤   ¤   ¤   ¤   0
c4af5a
85834e /* PGP Key Identifier Types */
414ab1 #define¤kPGPtls_KT_KeyID¤   ¤   ¤   ¤   ¤   0
3ad8fb #define¤kPGPtls_KT_Key¤ ¤   ¤   ¤   ¤   ¤   1
06af5a
bdd7e2 #define¤kPGPtls_HA_MD5Size¤ ¤   ¤   ¤   ¤   16
0ce6fd #define¤kPGPtls_HA_SHASize¤ ¤   ¤   ¤   ¤   20
5cb290 #define¤kPGPtls_HA_RIPEMD160Size¤   ¤   ¤   20
7faf5a
107244 #define¤kPGPtls_SC_CASTKeySize¤ ¤   ¤   ¤   16
44edaf #define¤kPGPtls_SC_IDEAKeySize¤ ¤   ¤   ¤   16
a23571 #define¤kPGPtls_SC_3DESKeySize¤ ¤   ¤   ¤   24
62af5a
eb1ee2 #define kPGPtls_CC_RSASign¤ ¤   ¤   ¤   ¤   1
--78e8 000e4104d7b40100249 Page 2 of pgpTLSPriv.h
eeddfe #define kPGPtls_CC_DSASign¤ ¤   ¤   ¤   ¤   2
6fda20 #define kPGPtls_CC_RSAFixedDH¤  ¤   ¤   ¤   3
477e5c #define kPGPtls_CC_DSAFixedDH¤  ¤   ¤   ¤   4
d5af5a
a6f214 /* Internal Events */
d0148e #define¤kPGPtls_EV_ReceiveHelloRequest¤ ¤   0
3aeab2 #define kPGPtls_EV_ReceiveClientHello¤  ¤   1
c23622 #define kPGPtls_EV_ReceiveServerHello¤  ¤   2
74d05e #define kPGPtls_EV_ReceiveCertificate¤  ¤   3
200f7b #define kPGPtls_EV_EphemeralCertificate¤¤   4
debfc8 #define kPGPtls_EV_StaticCertificate¤   ¤   5
d449b7 #define kPGPtls_EV_ReceiveServerKeyExchange¤6
bd6a43 #define kPGPtls_EV_ReceiveCertRequest¤  ¤   7
1c2fa6 #define kPGPtls_EV_ReceiveServerHelloDone¤  8
e17088 #define kPGPtls_EV_ReceiveCertVerify¤   ¤   9
7dd2c1 #define kPGPtls_EV_ReceiveClientKeyExchange¤10
7103b4 #define kPGPtls_EV_ReceiveFinished¤ ¤   ¤   11
fb5b13 #define kPGPtls_EV_ReceiveFatalAlert¤   ¤   12
ddf008 #define kPGPtls_EV_ReceiveNoCertificate¤¤   13
22d52a #define kPGPtls_EV_ReceiveChangeCipherSpec¤ 14
6faf5a
48af5a
f77496 typedef PGPByte PGPtlsCipherSuiteID[2];
42af5a
f92763 typedef struct PGPtlsCipherSuite
9dbb36 {
9447ce ¤   PGPtlsCipherSuiteID¤¤   id;
a573ed ¤   PGPPublicKeyAlgorithm¤  sigAlg;
22b7af ¤   PGPCipherAlgorithm¤ ¤   cipherID;
810786 ¤   PGPHashAlgorithm¤   ¤   hashID;
8fef3c ¤   PGPBoolean¤ ¤   ¤   ¤   ephemeral;
a48b57 ¤   PGPBoolean¤ ¤   ¤   ¤   usePGPKeys;
9db1e4 ¤   PGPtlsCipherSuiteNum¤   suite;
ff13f0 } PGPtlsCipherSuite;
0aaf5a
b3c57f /* Cipher Suites (in order of preference) */
8cc939 const PGPtlsCipherSuite kPGPtls_CipherSuites[] =
34c7a1 ¤   {
645b34 ¤   ¤   {
93a72b ¤   ¤   ¤   { 0x01, 0x01 },
654d50 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_DSA,
4a43c2 ¤   ¤   ¤   kPGPCipherAlgorithm_CAST5,
af23cb ¤   ¤   ¤   kPGPHashAlgorithm_SHA, TRUE, TRUE,
aed1fc ¤   ¤   ¤   kPGPtls_TLS_PGP_DHE_DSS_WITH_CAST_CBC_SHA
48799c ¤   ¤   },
4e5b34 ¤   ¤   {
33a844 ¤   ¤   ¤   { 0x01, 0x10 },
38c288 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_RSA,
5043c2 ¤   ¤   ¤   kPGPCipherAlgorithm_CAST5,
6b23cb ¤   ¤   ¤   kPGPHashAlgorithm_SHA, TRUE, TRUE,
edd07b ¤   ¤   ¤   kPGPtls_TLS_PGP_DHE_RSA_WITH_CAST_CBC_SHA
7e799c ¤   ¤   },
165b34 ¤   ¤   {
02a439 ¤   ¤   ¤   { 0x01, 0x20 },
a0c288 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_RSA,
8f43c2 ¤   ¤   ¤   kPGPCipherAlgorithm_CAST5,
fbd5e6 ¤   ¤   ¤   kPGPHashAlgorithm_SHA, FALSE, TRUE,
4bb6d0 ¤   ¤   ¤   kPGPtls_TLS_PGP_RSA_WITH_CAST_CBC_SHA
11799c ¤   ¤   },
7d5b34 ¤   ¤   {
0ae749 ¤   ¤   ¤   { 0x00, 0x0A },
b0c288 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_RSA,
d52f8d ¤   ¤   ¤   kPGPCipherAlgorithm_3DES,
da62a7 ¤   ¤   ¤   kPGPHashAlgorithm_SHA, FALSE, FALSE,
e703e9 ¤   ¤   ¤   kPGPtls_TLS_RSA_WITH_3DES_EDE_CBC_SHA
7d799c ¤   ¤   },
6e5b34 ¤   ¤   {
71e019 ¤   ¤   ¤   { 0x00, 0x13 },
6e4d50 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_DSA,
622f8d ¤   ¤   ¤   kPGPCipherAlgorithm_3DES,
2d98b6 ¤   ¤   ¤   kPGPHashAlgorithm_SHA, TRUE, FALSE,
e4bc6a ¤   ¤   ¤   kPGPtls_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
--f7da 000c654c6c040100249 Page 3 of pgpTLSPriv.h
25799c ¤   ¤   },
825b34 ¤   ¤   {
29c64d ¤   ¤   ¤   { 0x00, 0x16 },
abc288 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_RSA,
0d2f8d ¤   ¤   ¤   kPGPCipherAlgorithm_3DES,
db98b6 ¤   ¤   ¤   kPGPHashAlgorithm_SHA, TRUE, FALSE,
ce9cf9 ¤   ¤   ¤   kPGPtls_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
2b799c ¤   ¤   },
285b34 ¤   ¤   {
71c922 ¤   ¤   ¤   { 0x00, 0x07 },
1fc288 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_RSA,
e7f3af ¤   ¤   ¤   kPGPCipherAlgorithm_IDEA,
a662a7 ¤   ¤   ¤   kPGPHashAlgorithm_SHA, FALSE, FALSE,
5c55c0 ¤   ¤   ¤   kPGPtls_TLS_RSA_WITH_IDEA_CBC_SHA
02799c ¤   ¤   },
0b5b34 ¤   ¤   {
a57194 ¤   ¤   ¤   { 0x01, 0xF0 },
234d50 ¤   ¤   ¤   kPGPPublicKeyAlgorithm_DSA,
1ee71f ¤   ¤   ¤   kPGPCipherAlgorithm_None,
bc23cb ¤   ¤   ¤   kPGPHashAlgorithm_SHA, TRUE, TRUE,
86ffe4 ¤   ¤   ¤   kPGPtls_TLS_PGP_DHE_DSS_WITH_NULL_SHA
f60fe4 ¤   ¤   }
c962bd ¤   };
481b52 ¤   ¤
84af5a
09c764 typedef struct PGPtlsKeys
e5bb36 {
006509 ¤   PGPByte¤¤   ¤   ¤   macSecret[kPGPtls_MaxHashSize];
6b9978 ¤   PGPByte¤¤   ¤   ¤   cipherKey[24];
bd4b26 ¤   PGPByte¤¤   ¤   ¤   iv[kPGPtls_CipherBlockSize];
abf28a ¤   PGPByte¤¤   ¤   ¤   seqNum[kPGPtls_SequenceNumberSize];
21a118 ¤   PGPHMACContextRef¤  hmac;
e55256 } PGPtlsKeys;
3daf5a
b0ad84 /* the non-opaque PGPtlsContext */
7fce82 typedef struct PGPtlsContextPriv
06bb36 {
d088c5 ¤   PGPContextRef¤  ¤   ¤   pgpContext;
6f3f53 ¤   PGPBoolean¤ ¤   ¤   ¤   useCache;
c367c5 ¤
e266ec ¤   /* cached session keys stored here */
f4e59e } PGPtlsContextPriv;
7eaf5a
6b20fd typedef struct PGPtlsSessionPriv
70bb36 {
b1cb5e ¤   PGPtlsProtocolState¤¤   state;
5f4047 ¤   PGPInt8¤¤   ¤   ¤   ¤   intState;
ac88c5 ¤   PGPContextRef¤  ¤   ¤   pgpContext;
c88850 ¤   PGPtlsContextPriv¤  ¤   *tlsContext;
52a558 ¤   PGPMemoryMgrRef¤¤   ¤   memMgr;
7167c5 ¤
0cbcf9 ¤   PGPtlsReceiveProcPtr¤   tlsReceiveProc;
963e16 ¤   PGPtlsSendProcPtr¤  ¤   tlsSendProc;
79a5c4 ¤   void *¤ ¤   ¤   ¤   ¤   tlsReceiveUserData;
be9686 ¤   void *¤ ¤   ¤   ¤   ¤   tlsSendUserData;
5b1b52 ¤   ¤
daeea1 ¤   PGPBoolean¤ ¤   ¤   ¤   isClientSide;
019e9c ¤   PGPBoolean¤ ¤   ¤   ¤   blocking;
d0c6eb ¤   PGPBoolean¤ ¤   ¤   ¤   closeInitiated;
dca264 ¤   PGPBoolean¤ ¤   ¤   ¤   requestCert;
2db505 ¤   PGPByte¤¤   ¤   ¤   ¤   minorVersion;
a416fe ¤   PGPByte¤¤   ¤   ¤   ¤   originalClientVersion;
a9b1ea ¤   PGPUInt16¤  ¤   ¤   ¤   cipherSuiteIndex;
033f5c ¤   PGPtlsCipherSuite¤  ¤   *cipherSuites;
5a9f8a ¤   PGPUInt16¤  ¤   ¤   ¤   numCipherSuites;
4167c5 ¤
103dab ¤   PGPKeyRef¤  ¤   ¤   ¤   localKey;
9db262 ¤   PGPPublicKeyAlgorithm¤  localKeyAlg;
f65104 ¤   char *¤ ¤   ¤   ¤   ¤   localKeyPassphrase;
254a78 ¤   PGPByte *¤  ¤   ¤   ¤   localKeyPasskeyBuffer;
cd655b ¤   PGPSize¤¤   ¤   ¤   ¤   localKeyPasskeySize;
c6cc6e ¤   PGPBoolean¤ ¤   ¤   ¤   localKeyUsePasskey;
--a213 000030eef0c40100249 Page 4 of pgpTLSPriv.h
3fc876 ¤   PGPKeyRef¤  ¤   ¤   ¤   remoteKey;
537b8c ¤   PGPKeySetRef¤   ¤   ¤   remoteKeySet;
941c90 ¤   PGPPublicKeyAlgorithm¤  remoteKeyAlg;
6bf9b0 ¤   PGPBoolean¤ ¤   ¤   ¤   certRequested;
9f1f68 ¤   PGPBoolean¤ ¤   ¤   ¤   certMatched;
59706d ¤   PGPBoolean¤ ¤   ¤   ¤   certVerified;
8767c5 ¤
1e4b27 ¤   PGPtlsPrime¤¤   ¤   ¤   requestedPrime;
d767c5 ¤
a6d103 ¤   PGPHashContextRef¤  ¤   handshakeSHA;
527076 ¤   PGPHashContextRef¤  ¤   handshakeMD5;
a2c023 ¤   PGPHashContextRef¤  ¤   lastHandSHA;
116156 ¤   PGPHashContextRef¤  ¤   lastHandMD5;
a20cee ¤   PGPHashContextRef¤  ¤   innerMACHash;
f26643 ¤   PGPHashContextRef¤  ¤   outerMACHash;
7a67c5 ¤
01c533 ¤   PGPByte¤¤   ¤   ¤   ¤   cRandom[kPGPtls_RandomSize];
2a2edc ¤   PGPByte¤¤   ¤   ¤   ¤   sRandom[kPGPtls_RandomSize];
a667c5 ¤
ccdad2 ¤   PGPByte¤¤   ¤   ¤   ¤   masterSecret[kPGPtls_MasterSecretSize];
d567c5 ¤
20d479 ¤   PGPCBCContextRef¤   ¤   writeCipher;
77b898 ¤   PGPCBCContextRef¤   ¤   readCipher;
6067c5 ¤
a9eec8 ¤   PGPtlsKeys *¤   ¤   ¤   writeActive;
8a5949 ¤   PGPtlsKeys *¤   ¤   ¤   readActive;
3fc5d6 ¤   PGPtlsKeys *¤   ¤   ¤   clientPending;
a5b709 ¤   PGPtlsKeys *¤   ¤   ¤   serverPending;
84c837 ¤   PGPSize¤¤   ¤   ¤   ¤   keySize;
632db1 ¤   PGPSize¤¤   ¤   ¤   ¤   hashSize;
7267c5 ¤
9bbb1e ¤   PGPByte¤*¤  ¤   ¤   ¤   queuedSendData;
f9841a ¤   PGPSize¤¤   ¤   ¤   ¤   queuedSendSize;
5ce97b ¤   PGPByte *¤  ¤   ¤   ¤   rcvdRawData;¤   /* only used for non-blocking */
519471 ¤   PGPSize¤¤   ¤   ¤   ¤   rawDataSize;¤   /* only used for non-blocking */
1b43ed ¤   PGPByte *¤  ¤   ¤   ¤   rcvdAppData;
95e6b2 ¤   PGPSize¤¤   ¤   ¤   ¤   appDataSize;
249d85 ¤   PGPByte *¤  ¤   ¤   ¤   rcvdHandData;
d29740 ¤   PGPSize¤¤   ¤   ¤   ¤   handDataSize;
2567c5 ¤
c92df1 ¤   /* DH Parameters */
fa0f3d ¤   PGPBigNumRef¤   ¤   ¤   dhP;
c406ad ¤   PGPBigNumRef¤   ¤   ¤   dhG;
dcd39e ¤   PGPBigNumRef¤   ¤   ¤   dhYs;
06c9ff ¤   PGPBigNumRef¤   ¤   ¤   dhX;
54560b ¤   PGPBigNumRef¤   ¤   ¤   dhYc;
9867c5 ¤
eb77fe ¤   PGPtlsAlert¤¤   ¤   ¤   fatalAlert;
3e6e00 } PGPtlsSessionPriv;
83af5a
f0af5a
3513a6 PGPError pgpTLSReceiveRecordLayer( PGPtlsSessionPriv *¤ session,
09eac6 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   outType,
3fce11 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **¤ ¤   ¤   outBuffer,
e5494c ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   ¤   outLength );
396ce8 PGPError pgpTLSSendRecordLayer( PGPtlsSessionPriv *¤session,
ab48b4 ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte¤  ¤   inType,
21fb9d ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte *¤¤   inBuffer,
81205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
f41102 PGPError pgpTLSReceiveHandshakePacket( PGPtlsSessionPriv *¤ session,
4deac6 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   outType,
8bce11 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **¤ ¤   ¤   outBuffer,
99494c ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   ¤   outLength );
481580 PGPError pgpTLSSendHandshakePacket( PGPtlsSessionPriv *¤session,
4048b4 ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte¤  ¤   inType,
73fb9d ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte *¤¤   inBuffer,
09205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
8078f5 PGPError pgpTLSClientHandshake( PGPtlsSessionPriv *¤session );
a32b92 PGPError pgpTLSServerHandshake( PGPtlsSessionPriv *¤session );
5caf5a
987832 PGPError pgpTLSSendClientHello( PGPtlsSessionPriv *¤session );
0346cd PGPError pgpTLSSendServerHello( PGPtlsSessionPriv *¤session );
--8233 0003402cae540100249 Page 5 of pgpTLSPriv.h
e1cc97 PGPError pgpTLSSendCertificate( PGPtlsSessionPriv *¤session );
f26a96 PGPError pgpTLSSendCertVerify( PGPtlsSessionPriv *¤ session );
e2fe5b PGPError pgpTLSSendServerKeyExchange( PGPtlsSessionPriv * session );
b3f6b9 PGPError pgpTLSSendCertificateRequest( PGPtlsSessionPriv *¤ session );
6db618 PGPError pgpTLSSendClientKeyExchange( PGPtlsSessionPriv * session );
3128a7 PGPError pgpTLSSendChangeCipherSpec( PGPtlsSessionPriv *¤   session );
e170af PGPError pgpTLSSendFinished( PGPtlsSessionPriv *¤   session );
b9fd48 PGPError pgpTLSSendFinalHandshake( ·PGPtlsSessionPriv *¤session );
a4b2a2 PGPError pgpTLSSendAlert( PGPtlsSessionPriv *¤  session,
370add ¤   ¤   ¤   ¤   ¤   ¤   PGPByte¤¤   ¤   ¤   level,
1b47fb ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsAlert¤¤   ¤   type );
9eaf5a
efb22a PGPError pgpTLSReceiveServerHello( PGPtlsSessionPriv *¤ session,
20aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
dc205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
f1b6e5 PGPError pgpTLSReceiveClientHello( PGPtlsSessionPriv *¤ session,
d7aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
f1205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
8b9044 PGPError pgpTLSReceiveCertificate( PGPtlsSessionPriv *¤ session,
0eaa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
7f205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
fb7f9c PGPError pgpTLSReceiveServerKeyExchange( PGPtlsSessionPriv *session,
8baa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
34205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
8395dd PGPError pgpTLSReceiveClientKeyExchange( PGPtlsSessionPriv *session,
b2aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
e2205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
30e94c PGPError pgpTLSReceiveCertRequest( PGPtlsSessionPriv *¤ session,
99aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
e4205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
8383d7 PGPError pgpTLSReceiveCertVerify( PGPtlsSessionPriv *¤  session,
6eaa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
48205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
973710 PGPError pgpTLSReceiveServerHelloDone( PGPtlsSessionPriv *¤ session,
29aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
b0205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
fc57e9 PGPError pgpTLSReceiveFinished( PGPtlsSessionPriv *¤session,
f9aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
e2205c ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength );
f9af5a
9adbb1 PGPError ssl3MasterSecret16( PGPtlsSessionPriv *¤   session,
546e9b ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   preMaster,
a77542 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16¤  ¤   ¤   preMasterSize,
da50ca ¤   ¤   ¤   ¤   ¤   ¤   PGPByte¤¤   ¤   ¤   mixer,
c10587 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   masterSecret );
fc09d1 PGPError ssl3CalculateKeyBlock( PGPtlsSessionPriv *¤session,
7d2ada ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   keyBlock,
7ac559 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   needed );
fba43d PGPError tlsCalculateKeyBlock( PGPtlsSessionPriv *¤ session,
c12ada ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   keyBlock,
83c559 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   needed );
a9ebf1 PGPError pgpTLSCalculateMasterSecret( PGPtlsSessionPriv *¤  session,
eb6e9b ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   preMaster,
7321c7 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   preMasterSize );
2d657c PGPError pgpTLSCalculateKeys( PGPtlsSessionPriv *¤  session );
bcd0ca PGPError pgpTLSCalculateMAC( PGPtlsSessionPriv *¤   session,
bbcae6 ¤   ¤   ¤   ¤   ¤   ¤   const PGPBoolean¤   inSending,
4d48b4 ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte¤  ¤   inType,
cefb9d ¤   ¤   ¤   ¤   ¤   ¤   const PGPByte *¤¤   inBuffer,
262416 ¤   ¤   ¤   ¤   ¤   ¤   const PGPSize¤  ¤   inLength,
551bc7 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   outBuffer );
3315a5 PGPError pgpTLSCalculateCertVerify( PGPtlsSessionPriv *¤session,
c8eafc ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   outBuffer,
46f61f ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   ¤   outSize );
4d56cf PGPError pgpTLSCalculateFinished( PGPtlsSessionPriv *¤  session,
6d7eea ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   clientSide,
45aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
03f61f ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   ¤   outSize );
1f6dd7 PGPError pgpTLSPRF(
4e19de ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionPriv *¤session,
879232 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   secret,
349c2b ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   secretLen,
--4fd1 001279bc44040100249 Page 6 of pgpTLSPriv.h
9b01a1 ¤   ¤   ¤   ¤   ¤   ¤   const char *¤   ¤   label,
66e88f ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   seedData,
0fda2e ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   seedLen,
34e620 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   outputData,
441de8 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   outputLen );
ebb449 PGPError pgpTLSPRFTest(
64ce50 ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionPriv *¤session );
979150 PGPError pgpTLSActivateReadKeys( PGPtlsSessionPriv *¤   session );
47e42e PGPError pgpTLSActivateWriteKeys( PGPtlsSessionPriv *¤  session );
57594e PGPError pgpTLSProcessAlert( PGPtlsSessionPriv *¤   session,
67aa94 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   inBuffer,
5d769b ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   inLength );
5bf753 PGPInt8 pgpTLSNextState( PGPtlsSessionPriv *¤   session,
fcfb5f ¤   ¤   ¤   ¤   ¤   ¤   PGPByte¤¤   ¤   ¤   event );
144cad PGPInt8 pgpTLSPacketToEvent( PGPByte¤   ¤   packetType );
45a19b PGPError pgpTLSBufferRawData( PGPtlsSessionPriv *¤  session,
4a4015 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   rawData,
fd40a3 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   rawDataSize );
97f161 PGPError pgpTLSExtractRawData( PGPtlsSessionPriv *¤ session,
234015 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   rawData,
99e3e1 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   ¤   rawDataSize );
bab873 PGPError pgpTLSBufferHandData(
2f19de ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionPriv *¤session,
d7bf14 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   handData,
ae0b23 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   handDataSize );
83969f PGPError pgpTLSExtractHandData(
cd19de ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionPriv *¤session,
ba7861 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte **¤ ¤   ¤   handData,
cb6a96 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   ¤   handDataSize );
900fe6 PGPError pgpTLSBufferSendData( PGPtlsSessionPriv *¤ session,
b34fe3 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   sendData,
cd48f7 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   sendDataSize );
d84bbd PGPError pgpTLSSendQueueIdleInternal( PGPtlsSessionPriv *¤  session );
8caf5a
60ec5e PGPBoolean pubAlgSupported( PGPPublicKeyAlgorithm¤  ¤   pubAlg );
e8af5a
303322 #endif /* ] Included_pgpTLSPriv_h */
92af5a
91af5a
d27e4d /*__Editor_settings____
77af5a
334126 ¤   Local Variables:
7a7b17 ¤   tab-width: 4
e40e6c ¤   End:
835f8c ¤   vi: ts=4 sw=4
309e9b ¤   vim: si
27d062 _____________________*/
--664e 001a3b924f64010024a Page 1 of Makefile.in
5ea601 #
594c32 # priv/regexp/
f5a601 #
d5c7d1 # $Id: Makefile.in,v 1.1 1997/08/13 21:17:49 hal Exp $
27a601 #
7daf5a
af6640 OBJS= pgpRegExp.o
54bf09 PRIVHDRS= pgpRegExp.h
28af5a
a3b7a3 all:: DONE
--e32f 000379a89554010024b Page 1 of pgpRegExp.c
bc38e5 /*
08aaf5 ·* regcomp and regexec -- regsub and regerror are elsewhere
9272fc ·* @(#)regexp.c¤1.3 of 18 April 87
0c775e ·*
76e38e ·*¤ Copyright (c) 1986 by University of Toronto.
c97212 ·*¤ Written by Henry Spencer. ·Not derived from licensed software.
18775e ·*
649664 ·*¤ Permission is granted to anyone to use this software for any
8f775d ·*¤ purpose on any computer system, and to redistribute it freely,
106921 ·*¤ subject to the following restrictions:
41775e ·*
662688 ·*¤ 1. The author is not responsible for the consequences of use of
b7d82b ·*¤ ¤   this software, no matter how awful, even if they arise
6c49e9 ·*¤ ¤   from defects in it.
6c775e ·*
deea4d ·*¤ 2. The origin of this software must not be misrepresented, either
8cda99 ·*¤ ¤   by explicit claim or by omission.
44775e ·*
364523 ·*¤ 3. Altered versions must be plainly marked as such, and must not
9f5430 ·*¤ ¤   be misrepresented as being the original software.
7b775e ·*
2deaef ·* Beware that some of this code is subtly aware of the way operator
3c2b7f ·* precedence is structured in regular expressions. ·Serious changes in
4e59f9 ·* regular-expression syntax might require a total rethink.
df495d ·*/
3cfeb2 #include <stdio.h>
77324c #include <string.h>
0f5d53 #include "pgpRegExp.h"
76af5a
23a146 #include "pgpDebug.h"
e10d08 #include "pgpMem.h"
5aaf5a
b138e5 /*
de068f ·* The "internal use only" fields in regexp.h are present to pass info from
3e5c05 ·* compile to execute that permits the execute phase to run lots faster on
15f7a0 ·* simple cases. ·They are:
ec775e ·*
0703c0 ·* regstart¤char that must begin a match; '\0' if none obvious
f37e82 ·* reganch¤ is the match anchored (at beginning-of-line only)?
2920ad ·* regmust¤ string (pointer into program) that match must include, or NULL
0018e4 ·* regmlen¤ length of regmust string
15775e ·*
3fe995 ·* Regstart and reganch permit very fast decisions on suitable starting points
69ca84 ·* for a match, cutting down the work a lot. ·Regmust permits fast rejection
989788 ·* of lines that cannot possibly match. ·The regmust tests are costly enough
6e6134 ·* that regcomp() supplies a regmust only if the r.e. contains something
93ee4d ·* potentially expensive (at present, the only such thing detected is * or +
8ec817 ·* at the start of the r.e., which can involve a lot of backup). ·Regmlen is
0366a2 ·* supplied because the test in regexec() needs it and regcomp() is computing
eaa939 ·* it anyway.
96495d ·*/
d7af5a
406440 #define NSUBEXP ·10
79d307 struct regexp {
92929c ¤   char const *startp[NSUBEXP];
a03058 ¤   char const *endp[NSUBEXP];
fe4f30 ¤   char regstart;¤ ¤   /* Internal use only. */
3a4a3a ¤   char reganch;¤  ¤   /* Internal use only. */
3ce28d ¤   char const *regmust;/* Internal use only. */
c412a5 ¤   int regmlen;¤   ¤   /* Internal use only. */
256086 ¤   char program[1];¤   /* Unwarranted chumminess with compiler. */
ba82f7 };
94af5a
7738e5 /*
c19999 ·* The first byte of the regexp internal "program" is actually this magic
aab5ca ·* number; the start node begins in the second byte.
a3495d ·*/
fed2b1 #define¤MAGIC¤  ((unsigned char)0234)
22af5a
3aaf5a
1738e5 /*
37b446 ·* Structure for regexp "program". ·This is essentially a linear encoding
--6ede 0002e99a4454010024b Page 2 of pgpRegExp.c
fddc8a ·* of a nondeterministic finite-state machine (aka syntax charts or
145134 ·* "railroad normal form" in parsing technology). ·Each node is an opcode
8eb5cc ·* plus a "next" pointer, possibly plus an operand. ·"Next" pointers of
8e0703 ·* all nodes except BRANCH implement concatenation; a "next" pointer with
c0333b ·* a BRANCH on both ends of it is connecting two alternatives. ·(Here we
f9b949 ·* have one of the subtle syntax dependencies: ·an individual BRANCH (as
35c408 ·* opposed to a collection of them) is never concatenated with anything
a5bcc6 ·* because of operator precedence.) ·The operand of some types of node is
f14bc0 ·* a literal string; for others, it is a node leading into a sub-FSM. ·In
580151 ·* particular, the operand of a BRANCH node is the first node of the branch.
fc0119 ·* (NB this is *not* a tree structure: ·the tail of the branch connects
c433f3 ·* to the thing following the set of BRANCHes.) ·The opcodes are:
3e495d ·*/
40af5a
8b455c /* definition¤  number¤ opnd?¤  meaning */
f11a16 #define¤END¤0¤  /* no¤  End of program. */
aa8778 #define¤BOL¤1¤  /* no¤  Match "" at beginning of line. */
384ee9 #define¤EOL¤2¤  /* no¤  Match "" at end of line. */
c25d6d #define¤ANY¤3¤  /* no¤  Match any one character. */
584eec #define¤ANYOF¤  4¤  /* str¤ Match any character in this string. */
49fc81 #define¤ANYBUT¤ 5¤  /* str¤ Match any character not in this string. */
126e79 #define¤BRANCH¤ 6¤  /* node¤Match this alternative, or the next... */
30527b #define¤BACK¤   7¤  /* no¤  Match "", "next" ptr points backward. */
31eca1 #define¤EXACTLY¤8¤  /* str¤ Match this string. */
393f3d #define¤NOTHING¤9¤  /* no¤  Match empty string. */
9c0c25 #define¤STAR¤   10¤ /* node¤Match this (simple) thing 0 or more times. */
2ff988 #define¤PLUS¤   11¤ /* node¤Match this (simple) thing 1 or more times. */
dcb710 #define¤OPEN¤   20¤ /* no¤  Mark this point in input as start of #n. */
45148f ¤   ¤   ¤   /*¤ OPEN+1 is number 1, etc. */
c3cf56 #define¤CLOSE¤  30¤ /* no¤  Analogous to OPEN. */
64af5a
d338e5 /*
21b064 ·* Opcode notes:
bd775e ·*
901dd7 ·* BRANCH¤  The set of branches constituting a single choice are hooked
fa50b2 ·*¤ ¤   together with their "next" pointers, since precedence prevents
a7b5b7 ·*¤ ¤   anything being concatenated to any individual branch. ·The
84dff0 ·*¤ ¤   "next" pointer of the last BRANCH in a choice points to the
4a8e93 ·*¤ ¤   thing following the whole choice. ·This is also where the
cffa17 ·*¤ ¤   final "next" pointer of each individual branch points; each
f08554 ·*¤ ¤   branch starts with the operand node of a BRANCH node.
90775e ·*
a2089a ·* BACK¤¤   Normal "next" pointers all implicitly point forward; BACK
7e8e1e ·*¤ ¤   exists to make loop structures possible.
83775e ·*
0ab784 ·* STAR,PLUS¤   '?', and complex '*' and '+', are implemented as circular
177f49 ·*¤ ¤   BRANCH structures using BACK. ·Simple cases (one character
758cca ·*¤ ¤   per match) are implemented with STAR and PLUS for speed
37fee9 ·*¤ ¤   and to minimize recursive plunges.
cd775e ·*
47e51c ·* OPEN,CLOSE¤  ...are numbered at compile time.
5a495d ·*/
94af5a
b938e5 /*
d54d48 ·* A node is one char of opcode followed by two chars of "next" pointer.
6486a9 ·* "Next" pointers are stored as two 8-bit pieces, high order first. ·The
e02087 ·* value is a positive offset from the opcode of the node containing it.
bf1493 ·* An operand, if any, simply follows the node. ·(Note that much of the
a5b6dd ·* code generation knows about this implicit relationship.)
bd775e ·*
a4bd0e ·* Using two bytes for the "next" pointer is vast overkill for most things,
8aa351 ·* but allows patterns to get big without disasters.
fd495d ·*/
cfd3a8 #define¤OP(p)¤  (*(p))
34b17a #define¤NEXT(p)¤(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
95b376 #define¤OPERAND(p)¤ ((p) + 3)
e0af5a
3038e5 /*
7e0d11 ·* See regmagic.h for one further detail of program structure.
ab495d ·*/
2daf5a
2eaf5a
--ac2a 000bd3757404010024b Page 3 of pgpRegExp.c
bc38e5 /*
e6bf38 ·* Utility definitions.
2d495d ·*/
d931d8 #define¤UCHARAT(p)¤ ((int)*(unsigned char *)(p))
bfaf5a
eebf73 #define¤FAIL(m)¤{ pgpDebugMsg(m); return(NULL); }
8f7de7 #define¤ISMULT(c)¤  ((c) == '*' || (c) == '+' || (c) == '?')
6387bf #define¤META¤   "^$.[()|?+*\\"
56af5a
4838e5 /*
280abc ·* Flags to be passed up and down.
b6495d ·*/
a9d176 #define¤HASWIDTH¤   01¤ /* Known never to match null string. */
7236b8 #define¤SIMPLE¤ ¤   02¤ /* Simple enough to be STAR/PLUS operand. */
0c9657 #define¤SPSTART¤¤   04¤ /* Starts with * or +. */
ec2161 #define¤WORST¤  ¤   0¤  /* Worst case. */
79af5a
4138e5 /*
65ffe8 ·* Global work variables for regcomp().
7e495d ·*/
02579f static char regdummy;¤  ¤   ¤   /* Address for end of list */
52af5a
752b1d typedef struct regcompState {
3dbf28 ¤   char const *regparse;¤  /* Input-scan pointer. */
31e0af ¤   int regnpar;¤   ¤   ¤   /* () count. */
1bd930 ¤   char *regcode;¤ ¤   ¤   /* Code-emit pointer; * &regdummy = don't. */
713958 ¤   long regsize;¤  ¤   ¤   /* Code size. */
4e68ba } regcompState;
0faf5a
6938e5 /*
560801 ·* Forward declarations for regcomp()'s friends.
34495d ·*/
6b81ff static char *reg(regcompState *rcs, int paren, int *flagp);
e75a6d static char *regbranch(regcompState *rcs, int *flagp);
92dba6 static char *regpiece(regcompState *rcs, int *flagp);
338243 static char *regatom(regcompState *rcs, int *flagp);
033217 static char *regnode(regcompState *rcs, char op);
d1c236 static char *regnext(char const *p);
cd43f7 static void regc(regcompState *rcs, char b);
163fb3 static void reginsert(regcompState *rcs, char op, char *opnd);
c080fb static void regtail(char *p, char const *val);
579a20 static void regoptail(char *p, char const *val);
f4daa6 static int strcspn_(const char *s1, const char *s2);
0eaf5a
06af5a
bc38e5 /*
1a35cd ·- regcomp - compile a regular expression into internal code
84775e ·*
9ca3d3 ·* We can't allocate space until we know how big the compiled form will be,
c573b1 ·* but we can't compile it (and thus know how big it is) until we've got a
fabb44 ·* place to put the code. ·So we cheat: ·we compile it twice, once with code
c1cf51 ·* generation turned off and size counting turned on, and once "for real".
2e6836 ·* This also means that we don't allocate space until we are sure that the
f138b5 ·* thing really will compile successfully, and we never have to move the
f7ba23 ·* code and thus invalidate pointers into it. ·(Note that it has to be in
019dde ·* one piece because free() must be able to free it all.)
cc775e ·*
a9fe02 ·* Beware that the optimization-preparation code in here knows about some
e8d17b ·* of the structure of the compiled regexp.
25495d ·*/
71c744 ¤   PGPError
2d4166 pgpRegComp(PGPContextRef context, char const *exp, regexp **pregexp)
c1bb36 {
51b802 ¤   regexp *r;
e958bb ¤   char const *scan;
3d799f ¤   char const *longest;
54f234 ¤   int len;
f90033 ¤   int flags;
f87f38 ¤   regcompState s_rcs;
e49eb5 ¤   regcompState *rcs = &s_rcs;
03af5a
bdf3ca ¤   PGPValidateContext( context );
--2801 0001468fd474010024b Page 4 of pgpRegExp.c
a8d4d7 ¤   PGPValidatePtr( exp );
f7b0ef ¤   PGPValidatePtr( pregexp );
7daf5a
d288ed ¤   *pregexp = NULL;
c1af5a
6c7404 ¤   pgpClearMemory( &s_rcs, sizeof(s_rcs) );
4daf5a
1f5a0d ¤   /* First pass: determine size, legality. */
36bc8b ¤   rcs->regparse = exp;
a0898e ¤   rcs->regnpar = 1;
6cbde1 ¤   rcs->regsize = 0L;
e2f5cd ¤   rcs->regcode = &regdummy;
f45d85 ¤   regc(rcs, MAGIC);
7277e6 ¤   if (reg(rcs, 0, &flags) == NULL)
842216 ¤   ¤   return(kPGPError_OutOfMemory);
41af5a
7cd0af ¤   /* Small enough for pointer-storage convention? */
f22fc6 ¤   if (rcs->regsize >= 32767L)¤¤   /* Probably could be 65535L. */
a6bc45 ¤   ¤   return(kPGPError_BadParams);
cdaf5a
d24c72 ¤   /* Allocate space. */
76c6ac ¤   r = (regexp *)pgpContextMemAlloc(context,
229f1c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(regexp) + (unsigned)rcs->regsize, 0);
232847 ¤   if (r == NULL)
a24030 ¤   ¤   return kPGPError_OutOfMemory;
01af5a
58ff67 ¤   /* Second pass: emit code. */
e2bc8b ¤   rcs->regparse = exp;
b4898e ¤   rcs->regnpar = 1;
10ec47 ¤   rcs->regcode = r->program;
c45d85 ¤   regc(rcs, MAGIC);
5577e6 ¤   if (reg(rcs, 0, &flags) == NULL)
1e2216 ¤   ¤   return(kPGPError_OutOfMemory);
e4af5a
7bdff1 ¤   /* Dig out information for optimizations. */
69c72f ¤   r->regstart = '\0';¤/* Worst-case defaults. */
f604c0 ¤   r->reganch = 0;
8e8b5e ¤   r->regmust = NULL;
a403f3 ¤   r->regmlen = 0;
7ef816 ¤   scan = r->program+1;¤   ¤   ¤   /* First BRANCH. */
068102 ¤   if (OP(regnext(scan)) == END) {¤/* Only one top-level choice. */
63bc1f ¤   ¤   scan = OPERAND(scan);
a6af5a
fe024d ¤   ¤   /* Starting-point info. */
b99017 ¤   ¤   if (OP(scan) == EXACTLY)
0d481e ¤   ¤   ¤   r->regstart = *OPERAND(scan);
0ea958 ¤   ¤   else if (OP(scan) == BOL)
38f93a ¤   ¤   ¤   r->reganch++;
55af5a
aa1b17 ¤   ¤   /*
96eb00 ¤   ¤   ·* If there's something expensive in the r.e., find the
298756 ¤   ¤   ·* longest literal string that must appear and make it the
0e5ed7 ¤   ¤   ·* regmust. ·Resolve ties in favor of later strings, since
05d756 ¤   ¤   ·* the regstart check works with the beginning of the r.e.
9086e6 ¤   ¤   ·* and avoiding duplication strengthens checking. ·Not a
32d354 ¤   ¤   ·* strong reason, but sufficient in the absence of others.
e39de3 ¤   ¤   ·*/
51fa39 ¤   ¤   if (flags&SPSTART) {
39b7d3 ¤   ¤   ¤   longest = NULL;
4c1afa ¤   ¤   ¤   len = 0;
17f9c5 ¤   ¤   ¤   for (; scan != NULL; scan = regnext(scan))
5fe3ee ¤   ¤   ¤   ¤   if (OP(scan) == EXACTLY
cbc80a ¤   ¤   ¤   ¤   ¤   ¤   && strlen(OPERAND(scan)) >= (unsigned)len) {
4160f6 ¤   ¤   ¤   ¤   ¤   longest = OPERAND(scan);
d90db4 ¤   ¤   ¤   ¤   ¤   len = strlen(OPERAND(scan));
e02613 ¤   ¤   ¤   ¤   }
c0b730 ¤   ¤   ¤   r->regmust = longest;
c9c860 ¤   ¤   ¤   r->regmlen = len;
e10fe4 ¤   ¤   }
999371 ¤   }
8aaf5a
147532 ¤   *pregexp = r;
--426d 0007a6b158f4010024b Page 5 of pgpRegExp.c
1873eb ¤   return(kPGPError_NoErr);
65efe6 }
b0af5a
4938e5 /*
cdf37f ·- reg - regular expression, i.e. main body or parenthesized thing
01775e ·*
cd0c2f ·* Caller must absorb opening parenthesis.
60775e ·*
c24159 ·* Combining parenthesis handling with the base level of regular expression
3dfc7c ·* is a trifle forced, but the need to tie the tails of the branches to what
afecec ·* follows makes it hard to avoid.
b8495d ·*/
f4083f static char *
5727ed reg(regcompState *rcs, int paren, int *flagp)
60bb36 {
f0de1c ¤   char *ret;
affec7 ¤   char *br;
9d2868 ¤   char *ender;
9be669 ¤   int parno = 0;
5f0033 ¤   int flags;
5eaf5a
ef5b9e ¤   *flagp = HASWIDTH;¤ /* Tentatively. */
92af5a
7cf178 ¤   /* Make an OPEN node, if parenthesized. */
9c1029 ¤   if (paren) {
634e55 ¤   ¤   if (rcs->regnpar >= NSUBEXP)
f83671 ¤   ¤   ¤   FAIL("too many ()");
b56d90 ¤   ¤   parno = rcs->regnpar;
9d0686 ¤   ¤   rcs->regnpar++;
93ad5d ¤   ¤   ret = regnode(rcs, (char)(OPEN+parno));
502be7 ¤   } else
8e2997 ¤   ¤   ret = NULL;
ceaf5a
6206ac ¤   /* Pick up the branches, linking them together. */
d67940 ¤   br = regbranch(rcs, &flags);
d5c0a8 ¤   if (br == NULL)
08e850 ¤   ¤   return(NULL);
e34d3d ¤   if (ret != NULL)
f79f4b ¤   ¤   regtail(ret, br);¤  /* OPEN -> first. */
d30e24 ¤   else
bb3a7f ¤   ¤   ret = br;
ee2326 ¤   if (!(flags&HASWIDTH))
0fcde3 ¤   ¤   *flagp &= ~HASWIDTH;
1d24a0 ¤   *flagp |= flags&SPSTART;
ba23d9 ¤   while (*rcs->regparse == '|') {
44231d ¤   ¤   rcs->regparse++;
064428 ¤   ¤   br = regbranch(rcs, &flags);
c8ba5c ¤   ¤   if (br == NULL)
c22fe5 ¤   ¤   ¤   return(NULL);
d085b2 ¤   ¤   regtail(ret, br);¤  /* BRANCH -> BRANCH. */
de370e ¤   ¤   if (!(flags&HASWIDTH))
0c76b5 ¤   ¤   ¤   *flagp &= ~HASWIDTH;
639ff6 ¤   ¤   *flagp |= flags&SPSTART;
9e9371 ¤   }
51af5a
8ed939 ¤   /* Make a closing node, and hook it on the end. */
e52585 ¤   ender = regnode(rcs, (char)((paren) ? CLOSE+parno : END));¤
beb03e ¤   regtail(ret, ender);
15af5a
661dc4 ¤   /* Hook the tails of the branches to the closing node. */
6edcba ¤   for (br = ret; br != NULL; br = regnext(br))
76f207 ¤   ¤   regoptail(br, ender);
33af5a
bfc909 ¤   /* Check for proper termination. */
9ef083 ¤   if (paren && *rcs->regparse++ != ')') {
5a7014 ¤   ¤   FAIL("unmatched ()");
eebb43 ¤   } else if (!paren && *rcs->regparse != '\0') {
7a577b ¤   ¤   if (*rcs->regparse == ')') {
f2471c ¤   ¤   ¤   FAIL("unmatched ()");
f04a5d ¤   ¤   } else
159abb ¤   ¤   ¤   FAIL("junk on end");¤   /* "Can't happen". */
7a6d15 ¤   ¤   /* NOTREACHED */
--ff27 000a8353dde4010024b Page 6 of pgpRegExp.c
a19371 ¤   }
93af5a
af569a ¤   return(ret);
0eefe6 }
49af5a
6838e5 /*
bb2861 ·- regbranch - one alternative of an | operator
29775e ·*
0d3bf6 ·* Implements the concatenation operator.
9b495d ·*/
e5083f static char *
d05b4e regbranch(regcompState *rcs, int *flagp)
7fbb36 {
23de1c ¤   char *ret;
d6f909 ¤   char *chain;
5e480b ¤   char *latest;
7d0033 ¤   int flags;
1eaf5a
428579 ¤   *flagp = WORST;¤¤   /* Tentatively. */
b8af5a
32c634 ¤   ret = regnode(rcs, BRANCH);
6e2c6a ¤   chain = NULL;
1f1819 ¤   while (*rcs->regparse != '\0' && *rcs->regparse != '|'
53c0db ¤   ¤   ···&& *rcs->regparse != ')') {
92531d ¤   ¤   latest = regpiece(rcs, &flags);
37940e ¤   ¤   if (latest == NULL)
8b2fe5 ¤   ¤   ¤   return(NULL);
a0862f ¤   ¤   *flagp |= flags&HASWIDTH;
be4905 ¤   ¤   if (chain == NULL)¤ /* First piece. */
cfa29e ¤   ¤   ¤   *flagp |= flags&SPSTART;
1e0e1d ¤   ¤   else
1d1ebf ¤   ¤   ¤   regtail(chain, latest);
be449d ¤   ¤   chain = latest;
e99371 ¤   }
eae5d1 ¤   if (chain == NULL)¤ /* Loop ran zero times. */
148644 ¤   ¤   (void) regnode(rcs, NOTHING);
1baf5a
19569a ¤   return(ret);
97efe6 }
6daf5a
1338e5 /*
2e390f ·- regpiece - something followed by possible [*+?]
1a775e ·*
af3b0f ·* Note that the branching code sequences used for ? and the general cases
d7d716 ·* of * and + are somewhat optimized: ·they use the same NOTHING node as
9b56cd ·* both the endmarker for their branch list and the body of the last branch.
c96b3e ·* It might seem that this node could be dispensed with entirely, but the
d015af ·* endmarker role is not redundant.
b1495d ·*/
d5083f static char *
e45088 regpiece(regcompState *rcs, int *flagp)
85bb36 {
48de1c ¤   char *ret;
c3f9da ¤   char op;
ce72d2 ¤   char *next;
300033 ¤   int flags;
efaf5a
73950b ¤   ret = regatom(rcs, &flags);
cef286 ¤   if (ret == NULL)
1be850 ¤   ¤   return(NULL);
a6af5a
1425a8 ¤   op = *rcs->regparse;
ed059c ¤   if (!ISMULT(op)) {
e3a6c8 ¤   ¤   *flagp = flags;
6e1711 ¤   ¤   return(ret);
2c9371 ¤   }
10af5a
79fc96 ¤   if (!(flags&HASWIDTH) && op != '?')
66dbe8 ¤   ¤   FAIL("*+ operand could be empty");
19ee89 ¤   *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
3eaf5a
a86283 ¤   if (op == '*' && (flags&SIMPLE))
--3d98 0004da490e74010024b Page 7 of pgpRegExp.c
563234 ¤   ¤   reginsert(rcs, STAR, ret);
be5cb5 ¤   else if (op == '*') {
8b827a ¤   ¤   /* Emit x* as (x&|), where & means "self". */
664928 ¤   ¤   reginsert(rcs, BRANCH, ret);¤   ¤   ¤   /* Either x */
d992f3 ¤   ¤   regoptail(ret, regnode(rcs, BACK));¤¤   /* and loop */
141e6c ¤   ¤   regoptail(ret, ret);¤   ¤   ¤   ¤   /* back */
1620b3 ¤   ¤   regtail(ret, regnode(rcs, BRANCH));¤¤   /* or */
242398 ¤   ¤   regtail(ret, regnode(rcs, NOTHING));¤   /* null. */
112156 ¤   } else if (op == '+' && (flags&SIMPLE))
1b5706 ¤   ¤   reginsert(rcs, PLUS, ret);
b0589e ¤   else if (op == '+') {
62ba83 ¤   ¤   /* Emit x+ as x(&|), where & means "self". */
6e9c71 ¤   ¤   next = regnode(rcs, BRANCH);¤   ¤   ¤   /* Either */
6b0029 ¤   ¤   regtail(ret, next);
3cb430 ¤   ¤   regtail(regnode(rcs, BACK), ret);¤  ¤   /* loop back */
a248b4 ¤   ¤   regtail(next, regnode(rcs, BRANCH));¤   ¤   /* or */
fc02c4 ¤   ¤   regtail(ret, regnode(rcs, NOTHING));¤   ¤   /* null. */
51b36c ¤   } else if (op == '?') {
b81443 ¤   ¤   /* Emit x? as (x|) */
644928 ¤   ¤   reginsert(rcs, BRANCH, ret);¤   ¤   ¤   /* Either x */
e320b3 ¤   ¤   regtail(ret, regnode(rcs, BRANCH));¤¤   /* or */
bc1b30 ¤   ¤   next = regnode(rcs, NOTHING);¤  ¤   /* null. */
f00029 ¤   ¤   regtail(ret, next);
fee946 ¤   ¤   regoptail(ret, next);
759371 ¤   }
9892cc ¤   rcs->regparse++;
f551f5 ¤   if (ISMULT(*rcs->regparse))
cee417 ¤   ¤   FAIL("nested *?+");
a9af5a
d5569a ¤   return(ret);
27efe6 }
5caf5a
1338e5 /*
e47ef2 ·- regatom - the lowest level
57775e ·*
1ac681 ·* Optimization: ·gobbles an entire sequence of ordinary characters so that
b5c812 ·* it can turn them into a single node, which is smaller to store and
7dd67c ·* faster to run. ·Backslashed characters are exceptions, each becoming a
87ac2f ·* separate node; the code is simpler that way and it's not worth fixing.
43495d ·*/
ad083f static char *
074df4 regatom(regcompState *rcs, int *flagp)
e8bb36 {
ccde1c ¤   char *ret;
f10033 ¤   int flags;
4daf5a
2d8579 ¤   *flagp = WORST;¤¤   /* Tentatively. */
7daf5a
5773cd ¤   switch (*rcs->regparse++) {
85ea02 ¤   case '^':
94b48f ¤   ¤   ret = regnode(rcs, BOL);
242f68 ¤   ¤   break;
766ce9 ¤   case '$':
94a85e ¤   ¤   ret = regnode(rcs, EOL);
ee2f68 ¤   ¤   break;
0db047 ¤   case '.':
061e40 ¤   ¤   ret = regnode(rcs, ANY);
586563 ¤   ¤   *flagp |= HASWIDTH|SIMPLE;
f52f68 ¤   ¤   break;
f4a414 ¤   case '[': {
6daed9 ¤   ¤   ¤   int cclass;
27b64f ¤   ¤   ¤   int classend;
1faf5a
81b512 ¤   ¤   ¤   if (*rcs->regparse == '^') {¤   /* Complement of range. */
97377a ¤   ¤   ¤   ¤   ret = regnode(rcs, ANYBUT);
99ac16 ¤   ¤   ¤   ¤   rcs->regparse++;
22a8fe ¤   ¤   ¤   } else
3eaac8 ¤   ¤   ¤   ¤   ret = regnode(rcs, ANYOF);
c73b44 ¤   ¤   ¤   if (*rcs->regparse == ']' || *rcs->regparse == '-')
b0a502 ¤   ¤   ¤   ¤   regc(rcs, *rcs->regparse++);
577838 ¤   ¤   ¤   while (*rcs->regparse != '\0' && *rcs->regparse != ']') {
4d4482 ¤   ¤   ¤   ¤   if (*rcs->regparse == '-') {
--a19d 0006c0b7f704010024b Page 8 of pgpRegExp.c
c4917e ¤   ¤   ¤   ¤   ¤   rcs->regparse++;
03b505 ¤   ¤   ¤   ¤   ¤   if (*rcs->regparse == ']' || *rcs->regparse == '\0')
88dc9e ¤   ¤   ¤   ¤   ¤   ¤   regc(rcs, '-');
193c4b ¤   ¤   ¤   ¤   ¤   else {
c46217 ¤   ¤   ¤   ¤   ¤   ¤   cclass = UCHARAT(rcs->regparse-2)+1;
3d5358 ¤   ¤   ¤   ¤   ¤   ¤   classend = UCHARAT(rcs->regparse);
804800 ¤   ¤   ¤   ¤   ¤   ¤   if (cclass > classend+1)
6d5bec ¤   ¤   ¤   ¤   ¤   ¤   ¤   FAIL("invalid [] range");
69b529 ¤   ¤   ¤   ¤   ¤   ¤   for (; cclass <= classend; cclass++)
9e948f ¤   ¤   ¤   ¤   ¤   ¤   ¤   regc(rcs, (char)cclass);
f59493 ¤   ¤   ¤   ¤   ¤   ¤   rcs->regparse++;
181c89 ¤   ¤   ¤   ¤   ¤   }
139317 ¤   ¤   ¤   ¤   } else
fdf79f ¤   ¤   ¤   ¤   ¤   regc(rcs, *rcs->regparse++);
40a3a6 ¤   ¤   ¤   }
a22501 ¤   ¤   ¤   regc(rcs, '\0');
a305b3 ¤   ¤   ¤   if (*rcs->regparse != ']')
9d59f0 ¤   ¤   ¤   ¤   FAIL("unmatched []");
371740 ¤   ¤   ¤   rcs->regparse++;
082490 ¤   ¤   ¤   *flagp |= HASWIDTH|SIMPLE;
a00fe4 ¤   ¤   }
f82f68 ¤   ¤   break;
0dfbdd ¤   case '(':
a38975 ¤   ¤   ret = reg(rcs, 1, &flags);
ee4357 ¤   ¤   if (ret == NULL)
c72fe5 ¤   ¤   ¤   return(NULL);
38bb83 ¤   ¤   *flagp |= flags&(HASWIDTH|SPSTART);
a82f68 ¤   ¤   break;
2fc2e2 ¤   case '\0':
2b5c27 ¤   case '|':
58e766 ¤   case ')':
56c221 ¤   ¤   FAIL("internal urp");¤  /* Supposed to be caught earlier. */
a72f68 ¤   ¤   break;
5d6f5d ¤   case '?':
e1de10 ¤   case '+':
1cc2ab ¤   case '*':
808c1b ¤   ¤   FAIL("?+* follows nothing");
e82f68 ¤   ¤   break;
e0cc32 ¤   case '\\':
68d425 ¤   ¤   if (*rcs->regparse == '\0')
24db0e ¤   ¤   ¤   FAIL("trailing \\");
2a5dba ¤   ¤   ret = regnode(rcs, EXACTLY);
87a657 ¤   ¤   regc(rcs, *rcs->regparse++);
6b115c ¤   ¤   regc(rcs, '\0');
026563 ¤   ¤   *flagp |= HASWIDTH|SIMPLE;
182f68 ¤   ¤   break;
e5d1f6 ¤   default: {
ee062e ¤   ¤   ¤   int len;
86d414 ¤   ¤   ¤   char ender;
dcaf5a
fc8a03 ¤   ¤   ¤   rcs->regparse--;
b940d3 ¤   ¤   ¤   len = strcspn_(rcs->regparse, META);
3f7af7 ¤   ¤   ¤   if (len <= 0)
12aac8 ¤   ¤   ¤   ¤   FAIL("internal disaster");
30d1c7 ¤   ¤   ¤   ender = *(rcs->regparse+len);
20dd0e ¤   ¤   ¤   if (len > 1 && ISMULT(ender))
ebdc27 ¤   ¤   ¤   ¤   len--;¤ ¤   /* Back off clear of ?+* operand. */
6980a8 ¤   ¤   ¤   *flagp |= HASWIDTH;
362400 ¤   ¤   ¤   if (len == 1)
910bc1 ¤   ¤   ¤   ¤   *flagp |= SIMPLE;
fe5857 ¤   ¤   ¤   ret = regnode(rcs, EXACTLY);
82a1c8 ¤   ¤   ¤   while (len > 0) {
3da502 ¤   ¤   ¤   ¤   regc(rcs, *rcs->regparse++);
3f38a2 ¤   ¤   ¤   ¤   len--;
eda3a6 ¤   ¤   ¤   }
832501 ¤   ¤   ¤   regc(rcs, '\0');
550fe4 ¤   ¤   }
282f68 ¤   ¤   break;
1f9371 ¤   }
2eaf5a
87569a ¤   return(ret);
6cefe6 }
--dfd1 000c0027f644010024b Page 9 of pgpRegExp.c
e0af5a
d338e5 /*
7aa044 ·- regnode - emit a node
b9495d ·*/
b1b4ad static char *¤  ¤   ¤   /* Location. */
ac1ead regnode(regcompState *rcs, char op)
f7bb36 {
06de1c ¤   char *ret;
49c157 ¤   char *ptr;
c7af5a
53c90c ¤   ret = rcs->regcode;
9e9ea4 ¤   if (ret == &regdummy) {
89c4c0 ¤   ¤   rcs->regsize += 3;
061711 ¤   ¤   return(ret);
e79371 ¤   }
86af5a
03f4f0 ¤   ptr = ret;
ded0a6 ¤   *ptr++ = op;
4dc088 ¤   *ptr++ = '\0';¤ ¤   /* Null "next" pointer. */
d7d88b ¤   *ptr++ = '\0';
b5b77c ¤   rcs->regcode = ptr;
beaf5a
48569a ¤   return(ret);
3aefe6 }
2daf5a
0938e5 /*
051dbf ·- regc - emit (if appropriate) a byte of code
52495d ·*/
142978 static void
85ff38 regc(regcompState *rcs, char b)
18bb36 {
584448 ¤   if (rcs->regcode != &regdummy)
679d1a ¤   ¤   *rcs->regcode++ = b;
c30e24 ¤   else
88f8da ¤   ¤   rcs->regsize++;
0eefe6 }
5eaf5a
a338e5 /*
4fcbf5 ·- reginsert - insert an operator in front of already-emitted operand
c0775e ·*
40d863 ·* Means relocating the operand.
e3495d ·*/
572978 static void
721188 reginsert(regcompState *rcs, char op, char *opnd)
5ebb36 {
254848 ¤   char *src;
b0d9ff ¤   char *dst;
a1010a ¤   char *place;
8aaf5a
219edf ¤   if (rcs->regcode == &regdummy) {
06c4c0 ¤   ¤   rcs->regsize += 3;
4f99bf ¤   ¤   return;
829371 ¤   }
9baf5a
d38687 ¤   src = rcs->regcode;
029bf7 ¤   rcs->regcode += 3;
0488eb ¤   dst = rcs->regcode;
428df9 ¤   while (src > opnd)
e9f453 ¤   ¤   *--dst = *--src;
7daf5a
95c89d ¤   place = opnd;¤  ¤   /* Op node, where operand used to be. */
28125a ¤   *place++ = op;
cce83d ¤   *place++ = '\0';
bce83d ¤   *place++ = '\0';
9aefe6 }
beaf5a
2d38e5 /*
f63111 ·- regtail - set the next-pointer at the end of a node chain
5f495d ·*/
192978 static void
ae26af regtail(char *p, char const *val)
c0bb36 {
--7e3d 000d08dc2ab4010024b Page 10 of pgpRegExp.c
e0f208 ¤   char *scan;
87d7fb ¤   char *temp;
120767 ¤   int offset;
9baf5a
753969 ¤   if (p == &regdummy)
b899bf ¤   ¤   return;
cbaf5a
19f92c ¤   /* Find last node. */
e69fee ¤   scan = p;
ff220e ¤   for (;;) {
d7de42 ¤   ¤   temp = regnext(scan);
6ffab4 ¤   ¤   if (temp == NULL)
37cdcb ¤   ¤   ¤   break;
13759f ¤   ¤   scan = temp;
c79371 ¤   }
dcaf5a
cea21f ¤   if (OP(scan) == BACK)
b98a6b ¤   ¤   offset = scan - val;
140e24 ¤   else
65966c ¤   ¤   offset = val - scan;
8126fb ¤   *(scan+1) = (offset>>8)&0377;
a90cf0 ¤   *(scan+2) = offset&0377;
a5efe6 }
5aaf5a
8438e5 /*
597288 ·- regoptail - regtail on operand of first argument; nop if operandless
3f495d ·*/
0b2978 static void
6cf9a3 regoptail(char *p, char const *val)
e1bb36 {
714061 ¤   /* "Operandless" and "op != BRANCH" are synonymous in practice. */
42fa20 ¤   if (p == NULL || p == &regdummy || OP(p) != BRANCH)
ee99bf ¤   ¤   return;
ff11ad ¤   regtail(OPERAND(p), val);
18efe6 }
69af5a
4738e5 /*
72f7aa ·* regexec and friends
5e495d ·*/
feaf5a
ed38e5 /*
39185c ·* Global work variables for regexec().
d4495d ·*/
e0bdc9 typedef struct regexecState {
2f728f ¤   char const *reginput;¤  ¤   /* String-input pointer. */
a438c7 ¤   char const *regbol;¤¤   ¤   /* Beginning of input, for ^ check. */
bd58df ¤   char const **regstartp;¤¤   /* Pointer to startp array. */
0da9ab ¤   char const **regendp;¤  ¤   /* Ditto for endp. */
722508 } regexecState;
b7af5a
34bcd0 #undef FAIL
96d10c #define¤FAIL(m)¤{ pgpDebugMsg(m); return(kPGPError_BadParams); }
94af5a
5baf5a
b838e5 /*
118949 ·* Forwards.
b5495d ·*/
f6a3b8 static int regtry(regexecState *res, regexp *prog, char const *string);
fc1f44 static int regmatch(regexecState *res, char const *prog);
b1a4ac static int regrepeat(regexecState *res, char const *p);
76af5a
31af5a
c15ba9 #if REGEXP_DEBUG
e328e2 int regnarrate = 0;
144cdc void regdump();
81dee7 static char *regprop();
a07454 #endif
68af5a
7e38e5 /*
cc6cfc ·- regexec - match a regexp against a string
8c495d ·*/
d04d2f int
--a116 0007a237e2d4010024b Page 11 of pgpRegExp.c
dec182 pgpRegExec(regexp *prog, char const *string)
5abb36 {
659fb6 ¤   char const *s;
4243d0 ¤   regexecState s_res;
229d83 ¤   regexecState *res = &s_res;
30af5a
1f14b7 ¤   /* Be paranoid... */
4dd520 ¤   if (prog == NULL || string == NULL) {
83e33b ¤   ¤   FAIL("NULL parameter");
de9371 ¤   }
2baf5a
515082 ¤   /* Check validity of program. */
557d5d ¤   if (UCHARAT(prog->program) != MAGIC) {
98e5dd ¤   ¤   FAIL("corrupted program");
845565 ¤   ¤   return(0);
b19371 ¤   }
4faf5a
5a9fa1 ¤   pgpClearMemory( &s_res, sizeof(s_res) );
37af5a
1560e6 ¤   /* If there is a "must appear" string, look for it. */
9842b6 ¤   if (prog->regmust != NULL) {
5cff4e ¤   ¤   s = string;
26d152 ¤   ¤   while ((s = strchr(s, prog->regmust[0])) != NULL) {
80d843 ¤   ¤   ¤   if (strncmp(s, prog->regmust, prog->regmlen) == 0)
31aace ¤   ¤   ¤   ¤   break;¤ /* Found it. */
227904 ¤   ¤   ¤   s++;
c80fe4 ¤   ¤   }
374e7a ¤   ¤   if (s == NULL)¤ /* Not present. */
606e8c ¤   ¤   ¤   return(0);
a69371 ¤   }
b6af5a
6b4645 ¤   /* Mark beginning of line for ^ . */
52c023 ¤   res->regbol = string;
1eaf5a
578e98 ¤   /* Simplest case: ·anchored match need be tried only once. */
100645 ¤   if (prog->reganch)
5302f9 ¤   ¤   return(regtry(res, prog, string));
98af5a
1eacf5 ¤   /* Messy cases: ·unanchored match. */
99683d ¤   s = string;
0f727f ¤   if (prog->regstart != '\0')
b16746 ¤   ¤   /* We know what char it must start with. */
72a5af ¤   ¤   while ((s = strchr(s, prog->regstart)) != NULL) {
418696 ¤   ¤   ¤   if (regtry(res, prog, s))
af90d6 ¤   ¤   ¤   ¤   return(1);
4d7904 ¤   ¤   ¤   s++;
340fe4 ¤   ¤   }
8c0e24 ¤   else
79f333 ¤   ¤   /* We don't -- general case. */
e64392 ¤   ¤   do {
d58696 ¤   ¤   ¤   if (regtry(res, prog, s))
7090d6 ¤   ¤   ¤   ¤   return(1);
81eef0 ¤   ¤   } while (*s++ != '\0');
48af5a
4e9422 ¤   /* Failure. */
c6b7c6 ¤   return(0);
b3efe6 }
09af5a
7738e5 /*
a3c2ba ·- regtry - try match at specific point
4c495d ·*/
809a75 static int¤ ¤   ¤   /* 0 failure, 1 success */
b8bd11 regtry(regexecState *res, regexp *prog, char const *string)
3bbb36 {
014ba4 ¤   int i;
c5db5b ¤   char const **sp;
755360 ¤   char const **ep;
ceaf5a
5337a0 ¤   res->reginput = string;
21e58c ¤   res->regstartp = prog->startp;
497968 ¤   res->regendp = prog->endp;
7aaf5a
--9315 0006074b66c4010024b Page 12 of pgpRegExp.c
19841b ¤   sp = prog->startp;
141be5 ¤   ep = prog->endp;
268894 ¤   for (i = NSUBEXP; i > 0; i--) {
e58633 ¤   ¤   *sp++ = NULL;
9dc10d ¤   ¤   *ep++ = NULL;
b89371 ¤   }
c48a84 ¤   if (regmatch(res, prog->program + 1)) {
927e6d ¤   ¤   prog->startp[0] = string;
c4d5e6 ¤   ¤   prog->endp[0] = res->reginput;
3549de ¤   ¤   return(1);
4e2be7 ¤   } else
3b5565 ¤   ¤   return(0);
c3efe6 }
37af5a
2a38e5 /*
2582bf ·- regmatch - main matching routine
27775e ·*
08ef28 ·* Conceptually the strategy is simple: ·check to see whether the current
2b0cef ·* node matches, call self recursively to see whether the rest matches,
9bd60d ·* and then act accordingly. ·In practice we make some effort to avoid
40abe0 ·* recursion, in particular by going through "ordinary" nodes (that don't
b31f42 ·* need to know whether the rest of the match failed) by a loop instead of
d983cd ·* by recursion.
d5495d ·*/
8b9a75 static int¤ ¤   ¤   /* 0 failure, 1 success */
cdcf49 regmatch(regexecState *res, char const *prog)
82bb36 {
6b5bab ¤   char const *scan;¤  /* Current node. */
a0709c ¤   char const *next;¤  ¤   /* Next node. */
c8af5a
6790c2 ¤   scan = prog;
485ba9 #if REGEXP_DEBUG
d0abfe ¤   if (scan != NULL && regnarrate)
6544e1 ¤   ¤   fprintf(stderr, "%s(\n", regprop(scan));
807454 #endif
96ee30 ¤   while (scan != NULL) {
f55ba9 #if REGEXP_DEBUG
4d5d2c ¤   ¤   if (regnarrate)
928256 ¤   ¤   ¤   fprintf(stderr, "%s...\n", regprop(scan));
4b7454 #endif
0859a8 ¤   ¤   next = regnext(scan);
7eaf5a
4fabbc ¤   ¤   switch (OP(scan)) {
191ba1 ¤   ¤   case BOL:
2243c3 ¤   ¤   ¤   if (res->reginput != res->regbol)
cc8c6d ¤   ¤   ¤   ¤   return(0);
abcdcb ¤   ¤   ¤   break;
992b7d ¤   ¤   case EOL:
744d2d ¤   ¤   ¤   if (*res->reginput != '\0')
9a8c6d ¤   ¤   ¤   ¤   return(0);
e0cdcb ¤   ¤   ¤   break;
f6a6fe ¤   ¤   case ANY:
74f296 ¤   ¤   ¤   if (*res->reginput == '\0')
ac8c6d ¤   ¤   ¤   ¤   return(0);
2dc747 ¤   ¤   ¤   res->reginput++;
a0cdcb ¤   ¤   ¤   break;
132330 ¤   ¤   case EXACTLY: {
1eb7ff ¤   ¤   ¤   ¤   int len;
a23a19 ¤   ¤   ¤   ¤   char const *opnd;
4aaf5a
76136b ¤   ¤   ¤   ¤   opnd = OPERAND(scan);
6b9f01 ¤   ¤   ¤   ¤   /* Inline the first character, for speed. */
7b2ab5 ¤   ¤   ¤   ¤   if (*opnd != *res->reginput)
469845 ¤   ¤   ¤   ¤   ¤   return(0);
048a9f ¤   ¤   ¤   ¤   len = strlen(opnd);
b895f1 ¤   ¤   ¤   ¤   if (len > 1 && strncmp(opnd, res->reginput, len) != 0)
6a9845 ¤   ¤   ¤   ¤   ¤   return(0);
56e62d ¤   ¤   ¤   ¤   res->reginput += len;
bea3a6 ¤   ¤   ¤   }
84cdcb ¤   ¤   ¤   break;
09556b ¤   ¤   case ANYOF:
60c04c ¤   ¤   ¤   if (*res->reginput == '\0' ||
--b18e 0001a331faa4010024b Page 13 of pgpRegExp.c
0d7241 ¤   ¤   ¤   ¤   strchr(OPERAND(scan), *res->reginput) == NULL)
4c8c6d ¤   ¤   ¤   ¤   return(0);
0cc747 ¤   ¤   ¤   res->reginput++;
27cdcb ¤   ¤   ¤   break;
d64b36 ¤   ¤   case ANYBUT:
0fc04c ¤   ¤   ¤   if (*res->reginput == '\0' ||
10cdfa ¤   ¤   ¤   ¤   strchr(OPERAND(scan), *res->reginput) != NULL)
b88c6d ¤   ¤   ¤   ¤   return(0);
18c747 ¤   ¤   ¤   res->reginput++;
7dcdcb ¤   ¤   ¤   break;
05fe08 ¤   ¤   case NOTHING:
63cdcb ¤   ¤   ¤   break;
9ba425 ¤   ¤   case BACK:
26cdcb ¤   ¤   ¤   break;
128450 ¤   ¤   case OPEN+1:
be6b34 ¤   ¤   case OPEN+2:
9b31e8 ¤   ¤   case OPEN+3:
b9bded ¤   ¤   case OPEN+4:
02e731 ¤   ¤   case OPEN+5:
ba0855 ¤   ¤   case OPEN+6:
af5289 ¤   ¤   case OPEN+7:
2e184e ¤   ¤   case OPEN+8:
20808c ¤   ¤   case OPEN+9: {
3ca3d1 ¤   ¤   ¤   ¤   int no;
3f8afc ¤   ¤   ¤   ¤   char const *save;
28af5a
c54f45 ¤   ¤   ¤   ¤   no = OP(scan) - OPEN;
128d7c ¤   ¤   ¤   ¤   save = res->reginput;
08af5a
b20bcb ¤   ¤   ¤   ¤   if (regmatch(res, next)) {
eda3e7 ¤   ¤   ¤   ¤   ¤   /*
2eb8c1 ¤   ¤   ¤   ¤   ¤   ·* Don't set startp if some later
781293 ¤   ¤   ¤   ¤   ¤   ·* invocation of the same parentheses
191730 ¤   ¤   ¤   ¤   ¤   ·* already has.
eb6ad4 ¤   ¤   ¤   ¤   ¤   ·*/
c519c5 ¤   ¤   ¤   ¤   ¤   if (res->regstartp[no] == NULL)
e33e3e ¤   ¤   ¤   ¤   ¤   ¤   res->regstartp[no] = save;
b984fe ¤   ¤   ¤   ¤   ¤   return(1);
999317 ¤   ¤   ¤   ¤   } else
439845 ¤   ¤   ¤   ¤   ¤   return(0);
d7a3a6 ¤   ¤   ¤   }
1acdcb ¤   ¤   ¤   break;
580356 ¤   ¤   case CLOSE+1:
5dec32 ¤   ¤   case CLOSE+2:
5fb6ee ¤   ¤   case CLOSE+3:
da3aeb ¤   ¤   case CLOSE+4:
b56037 ¤   ¤   case CLOSE+5:
038f53 ¤   ¤   case CLOSE+6:
72d58f ¤   ¤   case CLOSE+7:
399f48 ¤   ¤   case CLOSE+8:
ba24eb ¤   ¤   case CLOSE+9: {
f6a3d1 ¤   ¤   ¤   ¤   int no;
b28afc ¤   ¤   ¤   ¤   char const *save;
12af5a
fc435d ¤   ¤   ¤   ¤   no = OP(scan) - CLOSE;
408d7c ¤   ¤   ¤   ¤   save = res->reginput;
ccaf5a
d10bcb ¤   ¤   ¤   ¤   if (regmatch(res, next)) {
6ba3e7 ¤   ¤   ¤   ¤   ¤   /*
ef3ef6 ¤   ¤   ¤   ¤   ¤   ·* Don't set endp if some later
5f1293 ¤   ¤   ¤   ¤   ¤   ·* invocation of the same parentheses
741730 ¤   ¤   ¤   ¤   ¤   ·* already has.
9f6ad4 ¤   ¤   ¤   ¤   ¤   ·*/
00fef3 ¤   ¤   ¤   ¤   ¤   if (res->regendp[no] == NULL)
73acd1 ¤   ¤   ¤   ¤   ¤   ¤   res->regendp[no] = save;
6384fe ¤   ¤   ¤   ¤   ¤   return(1);
ed9317 ¤   ¤   ¤   ¤   } else
a39845 ¤   ¤   ¤   ¤   ¤   return(0);
d5a3a6 ¤   ¤   ¤   }
85cdcb ¤   ¤   ¤   break;
6d4064 ¤   ¤   case BRANCH: {
1a8afc ¤   ¤   ¤   ¤   char const *save;
--b5b2 000d83762f74010024b Page 14 of pgpRegExp.c
e0af5a
58e93c ¤   ¤   ¤   ¤   if (OP(next) != BRANCH)¤¤   /* No choice. */
4a9a8c ¤   ¤   ¤   ¤   ¤   next = OPERAND(scan);¤  /* Avoid recursion. */
c6deaa ¤   ¤   ¤   ¤   else {
880659 ¤   ¤   ¤   ¤   ¤   do {
d08857 ¤   ¤   ¤   ¤   ¤   ¤   save = res->reginput;
0ee6f0 ¤   ¤   ¤   ¤   ¤   ¤   if (regmatch(res, OPERAND(scan)))
a94972 ¤   ¤   ¤   ¤   ¤   ¤   ¤   return(1);
eac1eb ¤   ¤   ¤   ¤   ¤   ¤   res->reginput = save;
76ece7 ¤   ¤   ¤   ¤   ¤   ¤   scan = regnext(scan);
52f285 ¤   ¤   ¤   ¤   ¤   } while (scan != NULL && OP(scan) == BRANCH);
189845 ¤   ¤   ¤   ¤   ¤   return(0);
1edf76 ¤   ¤   ¤   ¤   ¤   /* NOTREACHED */
122613 ¤   ¤   ¤   ¤   }
8aa3a6 ¤   ¤   ¤   }
5ecdcb ¤   ¤   ¤   break;
775057 ¤   ¤   case STAR:
1ebfa0 ¤   ¤   case PLUS: {
36cc3f ¤   ¤   ¤   ¤   char nextch;
eda3d1 ¤   ¤   ¤   ¤   int no;
8d8afc ¤   ¤   ¤   ¤   char const *save;
322b8f ¤   ¤   ¤   ¤   int min;
ffaf5a
a0980e ¤   ¤   ¤   ¤   /*
6b11df ¤   ¤   ¤   ¤   ·* Lookahead to avoid useless match attempts
5cc120 ¤   ¤   ¤   ¤   ·* when we know what character comes next.
1e1020 ¤   ¤   ¤   ¤   ·*/
0e9588 ¤   ¤   ¤   ¤   nextch = '\0';
11dea6 ¤   ¤   ¤   ¤   if (OP(next) == EXACTLY)
5169c9 ¤   ¤   ¤   ¤   ¤   nextch = *OPERAND(next);
2357b8 ¤   ¤   ¤   ¤   min = (OP(scan) == STAR) ? 0 : 1;
0e8d7c ¤   ¤   ¤   ¤   save = res->reginput;
3113c0 ¤   ¤   ¤   ¤   no = regrepeat(res, OPERAND(scan));
94e0b2 ¤   ¤   ¤   ¤   while (no >= min) {
391238 ¤   ¤   ¤   ¤   ¤   /* If it could work, try it. */
c457a0 ¤   ¤   ¤   ¤   ¤   if (nextch == '\0' || *res->reginput == nextch)
f3dae1 ¤   ¤   ¤   ¤   ¤   ¤   if (regmatch(res, next))
904972 ¤   ¤   ¤   ¤   ¤   ¤   ¤   return(1);
69017b ¤   ¤   ¤   ¤   ¤   /* Couldn't or didn't -- back up. */
f438d9 ¤   ¤   ¤   ¤   ¤   no--;
3b3437 ¤   ¤   ¤   ¤   ¤   res->reginput = save + no;
a82613 ¤   ¤   ¤   ¤   }
648c6d ¤   ¤   ¤   ¤   return(0);
1fa3a6 ¤   ¤   ¤   }
afcdcb ¤   ¤   ¤   break;
eef104 ¤   ¤   case END:
15debe ¤   ¤   ¤   return(1);¤ /* Success! */
1dcdcb ¤   ¤   ¤   break;
299ae3 ¤   ¤   default:
58161c ¤   ¤   ¤   FAIL("memory corruption");
026e8c ¤   ¤   ¤   return(0);
1dcdcb ¤   ¤   ¤   break;
020fe4 ¤   ¤   }
6faf5a
5dd0b6 ¤   ¤   scan = next;
489371 ¤   }
62af5a
64d8af ¤   /*
de65fc ¤   ·* We get here only if there's trouble -- normally "case END" is
7a780f ¤   ·* the terminating point.
bba4e3 ¤   ·*/
66197f ¤   FAIL("corrupted pointers");
a4b7c6 ¤   return(0);
06efe6 }
71af5a
ea38e5 /*
f238ce ·- regrepeat - repeatedly match something simple, report how many
96495d ·*/
dbbeb7 static int
4fccb3 regrepeat(regexecState *res, char const *p)
afbb36 {
d8c2cd ¤   int count = 0;
--59ec 000afe875a94010024b Page 15 of pgpRegExp.c
db58bb ¤   char const *scan;
2143f0 ¤   char const *opnd;
99af5a
d72470 ¤   scan = res->reginput;
c3e7d1 ¤   opnd = OPERAND(p);
3ac930 ¤   switch (OP(p)) {
0d234b ¤   case ANY:
efc8e3 ¤   ¤   count = strlen(scan);
43fe33 ¤   ¤   scan += count;
752f68 ¤   ¤   break;
5ca6aa ¤   case EXACTLY:
252aba ¤   ¤   while (*opnd == *scan) {
87ae59 ¤   ¤   ¤   count++;
07619b ¤   ¤   ¤   scan++;
b10fe4 ¤   ¤   }
262f68 ¤   ¤   break;
b9c218 ¤   case ANYOF:
8ca77c ¤   ¤   while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
e4ae59 ¤   ¤   ¤   count++;
1d619b ¤   ¤   ¤   scan++;
540fe4 ¤   ¤   }
c82f68 ¤   ¤   break;
e20abd ¤   case ANYBUT:
d134c6 ¤   ¤   while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
e6ae59 ¤   ¤   ¤   count++;
da619b ¤   ¤   ¤   scan++;
440fe4 ¤   ¤   }
3d2f68 ¤   ¤   break;
1d2f8a ¤   default:¤   ¤   /* Oh dear. ·Called inappropriately. */
58de77 ¤   ¤   FAIL("internal foulup");
5e9f59 ¤   ¤   count = 0;¤ /* Best compromise. */
a52f68 ¤   ¤   break;
c39371 ¤   }
e13e41 ¤   res->reginput = scan;
96af5a
dfa09a ¤   return(count);
bfefe6 }
99af5a
a038e5 /*
4d2ac4 ·- regnext - dig the "next" pointer out of a node
32495d ·*/
e7083f static char *
169ff8 regnext(char const *p)
51bb36 {
c80767 ¤   int offset;
cdaf5a
323969 ¤   if (p == &regdummy)
1fe850 ¤   ¤   return(NULL);
82af5a
ca647c ¤   offset = NEXT(p);
7a8a65 ¤   if (offset == 0)
c0e850 ¤   ¤   return(NULL);
e8af5a
5f7214 ¤   if (OP(p) == BACK)
affa89 ¤   ¤   return(char *)(p-offset);
900e24 ¤   else
54125b ¤   ¤   return(char *)(p+offset);
68efe6 }
57af5a
cb5ba9 #if REGEXP_DEBUG
b7af5a
6edee7 static char *regprop();
05af5a
0038e5 /*
c7401f ·- regdump - dump a regexp onto stdout in vaguely comprehensible form
6b495d ·*/
e8314a void
1f8c82 regdump(regexp const *r)
a8bb36 {
836e5e ¤   char *s;
f12178 ¤   char op = EXACTLY;¤ /* Arbitrary non-END op. */
af72d2 ¤   char *next;
--bdb3 000421453224010024b Page 16 of pgpRegExp.c
89ae8a ¤   extern char *strchr();
82af5a
9aaf5a
0117ea ¤   s = r->program + 1;
faba07 ¤   while (op != END) {¤/* While that wasn't END last time... */
378148 ¤   ¤   op = OP(s);
4555b8 ¤   ¤   printf("%2d%s", s-r->program, regprop(s));¤ /* Where, what. */
3ff694 ¤   ¤   next = regnext(s);
0e72a6 ¤   ¤   if (next == NULL)¤  ¤   /* Next ptr. */
63b2c7 ¤   ¤   ¤   printf("(0)");
42ee26 ¤   ¤   else·
928e07 ¤   ¤   ¤   printf("(%d)", (s-r->program)+(next-s));
8359b3 ¤   ¤   s += 3;
3875fb ¤   ¤   if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
e9d98e ¤   ¤   ¤   /* Literal string, where present. */
947f12 ¤   ¤   ¤   while (*s != '\0') {
f31281 ¤   ¤   ¤   ¤   putchar(*s);
7e388f ¤   ¤   ¤   ¤   s++;
62a3a6 ¤   ¤   ¤   }
f17904 ¤   ¤   ¤   s++;
d60fe4 ¤   ¤   }
d5728c ¤   ¤   putchar('\n');
ee9371 ¤   }
12af5a
29fea3 ¤   /* Header fields of interest. */
b2ea53 ¤   if (r->regstart != '\0')
272d83 ¤   ¤   printf("start `%c' ", r->regstart);
943391 ¤   if (r->reganch)
764347 ¤   ¤   printf("anchored ");
b6b2b8 ¤   if (r->regmust != NULL)
f3e327 ¤   ¤   printf("must have \"%s\"", r->regmust);
c5270d ¤   printf("\n");
70efe6 }
f5af5a
5938e5 /*
d53e0b ·- regprop - printable representation of opcode
89495d ·*/
55083f static char *
64a96e regprop(op)
d96cb2 char *op;
f4bb36 {
eb813a ¤   char *p;
7051e2 ¤   static char buf[50];
4aaf5a
ba6957 ¤   (void) strcpy(buf, ":");
c4af5a
eded05 ¤   switch (OP(op)) {
209e14 ¤   case BOL:
0ffdd8 ¤   ¤   p = "BOL";
1d2f68 ¤   ¤   break;
47aec8 ¤   case EOL:
28e109 ¤   ¤   p = "EOL";
a52f68 ¤   ¤   break;
40234b ¤   case ANY:
5e5717 ¤   ¤   p = "ANY";
942f68 ¤   ¤   break;
f8c218 ¤   case ANYOF:
d9ca07 ¤   ¤   p = "ANYOF";
f72f68 ¤   ¤   break;
fa0abd ¤   case ANYBUT:
85e052 ¤   ¤   p = "ANYBUT";
b22f68 ¤   ¤   break;
9f38eb ¤   case BRANCH:
8fd7d3 ¤   ¤   p = "BRANCH";
042f68 ¤   ¤   break;
ada6aa ¤   case EXACTLY:
4a1ac1 ¤   ¤   p = "EXACTLY";
792f68 ¤   ¤   break;
d5c492 ¤   case NOTHING:
f6a768 ¤   ¤   p = "NOTHING";
912f68 ¤   ¤   break;
424686 ¤   case BACK:
--5f98 000cc28803f4010024b Page 17 of pgpRegExp.c
a6704a ¤   ¤   p = "BACK";
e62f68 ¤   ¤   break;
3774b1 ¤   case END:
150f95 ¤   ¤   p = "END";
322f68 ¤   ¤   break;
6dc5db ¤   case OPEN+1:
e02abf ¤   case OPEN+2:
847063 ¤   case OPEN+3:
e8fc66 ¤   case OPEN+4:
f8a6ba ¤   case OPEN+5:
2149de ¤   case OPEN+6:
f11302 ¤   case OPEN+7:
4d59c5 ¤   case OPEN+8:
390319 ¤   case OPEN+9:
c68252 ¤   ¤   sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
c872c7 ¤   ¤   p = NULL;
102f68 ¤   ¤   break;
ad39cc ¤   case CLOSE+1:
29d6a8 ¤   case CLOSE+2:
898c74 ¤   case CLOSE+3:
420071 ¤   case CLOSE+4:
a05aad ¤   case CLOSE+5:
7ab5c9 ¤   case CLOSE+6:
efef15 ¤   case CLOSE+7:
16a5d2 ¤   case CLOSE+8:
d9ff0e ¤   case CLOSE+9:
92abed ¤   ¤   sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
6872c7 ¤   ¤   p = NULL;
ae2f68 ¤   ¤   break;
7fb2f4 ¤   case STAR:
ea202b ¤   ¤   p = "STAR";
862f68 ¤   ¤   break;
90bb78 ¤   case PLUS:
3f6e46 ¤   ¤   p = "PLUS";
412f68 ¤   ¤   break;
9c2f72 ¤   default:
ae06df ¤   ¤   regerror("corrupted opcode");
f02f68 ¤   ¤   break;
8d9371 ¤   }
0c3cde ¤   if (p != NULL)
382c60 ¤   ¤   (void) strcat(buf, p);
525abd ¤   return(buf);
36efe6 }
487454 #endif
04af5a
8d38e5 /*
9b16f9 ·* The following is provided for those people who do not have strcspn() in
7093e3 ·* their C libraries. ·They should get off their butts and do something
591a45 ·* about it; at least one public-domain implementation of those (highly
14f78d ·* useful) string routines has been published on Usenet.
7d495d ·*/
efaf5a
3e38e5 /*
a4b502 ·* strcspn_ - find length of initial segment of s1 consisting entirely
c3ee06 ·* of characters not from s2
16495d ·*/
7aaf5a
abbeb7 static int
37925f strcspn_(const char *s1, const char *s2)
b7bb36 {
15785a ¤   char const *scan1;
ab973e ¤   char const *scan2;
9510db ¤   int count;
5caf5a
3b381c ¤   count = 0;
9a1fae ¤   for (scan1 = s1; *scan1 != '\0'; scan1++) {
313017 ¤   ¤   for (scan2 = s2; *scan2 != '\0';)¤  /* ++ moved down. */
6632b6 ¤   ¤   ¤   if (*scan1 == *scan2++)
036dba ¤   ¤   ¤   ¤   return(count);
7cefd2 ¤   ¤   count++;
3b9371 ¤   }
cca09a ¤   return(count);
--3bd4 00123f18b5c4010024b Page 18 of pgpRegExp.c
7aefe6 }
46af5a
8eaf5a
79af5a
85af5a
1eaf5a
407e4d /*__Editor_settings____
ebaf5a
034126 ¤   Local Variables:
777b17 ¤   tab-width: 4
71f72f ¤   comment-column: 40
860e6c ¤   End:
a25f8c ¤   vi: ts=4 sw=4
b89e9b ¤   vim: si
23d062 _____________________*/
--ac49 001de03c8de4010024c Page 1 of pgpRegExp.h
bc38e5 /*
058a16 ·* pgpRegExp.h - regular expression package (see copyright info below)
95775e ·*
dae39d ·* This is a PRIVATE header file, for use only within the PGP Library.
462979 ·* You should not be using these functions in an application.
4f775e ·*
bec647 ·* $Id: pgpRegExp.h,v 1.1 1997/08/13 01:32:51 hal Exp $
13495d ·*/
4daf5a
2daf5a
5138e5 /*
fde38e ·*¤ Copyright (c) 1986 by University of Toronto.
067212 ·*¤ Written by Henry Spencer. ·Not derived from licensed software.
b7775e ·*
fb9664 ·*¤ Permission is granted to anyone to use this software for any
da775d ·*¤ purpose on any computer system, and to redistribute it freely,
926921 ·*¤ subject to the following restrictions:
77775e ·*
112688 ·*¤ 1. The author is not responsible for the consequences of use of
68d82b ·*¤ ¤   this software, no matter how awful, even if they arise
2e49e9 ·*¤ ¤   from defects in it.
b7775e ·*
4dea4d ·*¤ 2. The origin of this software must not be misrepresented, either
59da99 ·*¤ ¤   by explicit claim or by omission.
a4775e ·*
d94523 ·*¤ 3. Altered versions must be plainly marked as such, and must not
7a5430 ·*¤ ¤   be misrepresented as being the original software.
14775e ·*
f3eaef ·* Beware that some of this code is subtly aware of the way operator
682b7f ·* precedence is structured in regular expressions. ·Serious changes in
1459f9 ·* regular-expression syntax might require a total rethink.
59495d ·*/
72af5a
cdc26c #include "pgpContext.h"
69af5a
92af5a
8d99c6 PGP_BEGIN_C_DECLARATIONS
11af5a
c33829 /* Private context structure */
53b1b8 struct regexp;
14da4f #ifndef TYPE_regexp
11901d #define TYPE_regexp 1
8cf442 typedef struct regexp regexp;
8c7454 #endif
b4af5a
71f189 /* Compile a regular expression */
059e63 PGPError pgpRegComp(PGPContextRef context, char const *exp, regexp **pregexp);
b9af5a
2c09f7 /* Match a regular expression against a string */
0a732a int pgpRegExec(regexp *prog, char const *string);
d8af5a
17af5a
861254 PGP_END_C_DECLARATIONS
14af5a
92af5a
4caf5a
15af5a
80af5a
83af5a
957e4d /*__Editor_settings____
4caf5a
6f4126 ¤   Local Variables:
5f7b17 ¤   tab-width: 4
77f72f ¤   comment-column: 40
aa0e6c ¤   End:
705f8c ¤   vi: ts=4 sw=4
cc9e9b ¤   vim: si
ded062 _____________________*/
--5368 0019a327b944010024d Page 1 of Makefile.in
5ea601 #
c77e9f # priv/utilities/
2aa601 #
f53a97 # $Id: Makefile.in,v 1.12 1998/04/06 21:06:24 marcd Exp $
2ca601 #
dfaf5a
166e0a SUBDIRS=errors helper prefs utils
c26646 LIBDONE=errors/DONE helper/DONE prefs/DONE utils/DONE ./DONE
7545c7 PRIVHDRS=pgpContext.h pgpOptionList.h pgpUtilitiesPriv.h \
b7345c ¤   pgpGroupsPriv.h pgpOptionListPriv.h
98af5a
ff5594 OBJS=¤  pgpFeatures.o pgpContext.o pgpOptionList.o \
fcb2f9 ¤   pgpUtilities.o pgpTimeBomb.o pgpGroups.o pgpGroupsUtil.o
daaf5a
9a683a all:: DONE LIBDONE
--847e 00032ba03644010024e Page 1 of pgpContext.c
a70335 /*____________________________________________________________________________
89a16f ¤   pgpContext.c
aa67c5 ¤
3cc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
214b0f ¤   All rights reserved.
09af5a
fa4e27 ¤   $Id: pgpContext.c,v 1.74.10.1 1998/11/12 03:23:04 heller Exp $
a8f7f7 ____________________________________________________________________________*/
21feb2 #include <stdio.h>
66af5a
9e2f8d #include "pgpErrors.h"
f50d08 #include "pgpMem.h"
06af5a
36c26c #include "pgpContext.h"
d30d6d #include "pgpEnv.h"
11adc0 #include "pgpRandomPoolPriv.h"
800f03 #include "pgpRandomContext.h"
5b2c96 #include "pgpRandomX9_17.h"
54dd74 #include "pgpRnd.h"
60c77e #include "pgpRndSeed.h"
da26e3 #include "pgpRngPub.h"
aefdbe #include "pgpDEBUGStartup.h"
0fe8b2 #include "pflPrefs.h"
cd5430 #include "pgpUtilitiesPriv.h"
d361a1 #include "pgpMacFileMapping.h"
aa39fc #include "bn.h"
3c025a #include "pgpMemoryMgrPriv.h"
89eee9 #include "pgpTimeBomb.h"
c7af5a
97af5a
887353 enum
82bb36 {
04da5b ¤   kPGPContextMagic¤   = 0x436e7478¤   /* 'Cntx' */
e482f7 };
50af5a
c56f8f struct PGPContext
6ebb36 {
78f7f4 ¤   PGPMemoryMgrRef¤¤   memoryMgr;
b267c5 ¤
c839d5 ¤   PGPUInt32¤  ¤   magic;¤ ¤   ¤   ¤   /* Always kPGPContextMagic */
b22a1e ¤   PGPUInt32¤  ¤   clientAPIVersion;¤  /* version client compiled against */
e778b4 ¤   PGPUserValue¤   userValue;¤ ¤   ¤   /* Client storage */
d1e7b3 ¤   PGPKeySetRef¤   defaultKeySet;¤ ¤   /* Set by pgpOpenDefualtKeyRings() */
9a67c5 ¤
4aebe7 ¤   PGPEnv¤ ¤   ···*¤   pgpEnvironment;¤¤   /* State for within library */
c667c5 ¤
dfd222 ¤   PGPRandomContext *¤ randomPoolContext;¤ /* ctxt around global rand pool*/
a22939 ¤   PGPRandomContext *¤ randomPoolX9_17;¤   /* uses 'randomPoolContext' */
5ec162 ¤   PGPRandomContext *¤ dummyRandomContext;
9a67c5 ¤
d4da0c ¤   PGPBoolean¤ ¤   ¤   prefsChanged;¤  ¤   /* Have changed internal prefs */
3d00d5 ¤   PGPPrefRef¤ ¤   ¤   prefsRef;
6667c5 ¤
37742e ¤   RingPool¤   ···*¤   ringPool;¤  ¤   ¤   /* Keyring data structures */
a367c5 ¤
9a82f7 };
6baf5a
dbc580 typedef struct PGPContext¤  PGPContext;
95af5a
95af5a
76af5a
0a0335 /*____________________________________________________________________________
f988f1 ¤   This function validates a context data structure.
f0f7f7 ____________________________________________________________________________*/
64af5a
6716ea ¤   PGPBoolean
3cfb78 pgpContextIsValid(PGPContextRef context)
c7bb36 {
be7531 ¤   return( context != NULL &&
27a5c4 ¤   ¤   ¤   context->magic == kPGPContextMagic );
62efe6 }
32af5a
--62a6 000c33f4f8b4010024e Page 2 of pgpContext.c
e0af5a
7e0335 /*____________________________________________________________________________
d5d0d4 ¤   Allocate a new PGPContext using custom memory allocators.
96a973 ¤   This function es exported for the client library and should never be
cdbf07 ¤   called by the shared library.
f7f7f7 ____________________________________________________________________________*/
bf66dd ¤   static PGPError
52389d FinishInitContext( PGPContextRef ·context )
50bb36 {
478e12 ¤   PGPError¤   err = kPGPError_NoErr;
721b52 ¤   ¤
22902c ¤   err = pgpenvCreate( context, &context->pgpEnvironment );
fbf1e7 ¤   if ( IsntPGPError( err ) )
bfc7a1 ¤   {
4baf8b ¤   ¤   context->ringPool = ringPoolCreate( context->pgpEnvironment );
4fda1f ¤   ¤   if ( IsNull( context->ringPool ) )
e95b34 ¤   ¤   {
42124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
670fe4 ¤   ¤   }
4d9371 ¤   }
da67c5 ¤
47e4a9 ¤   /* only actually seeds it the first time */
69290f ¤   (void)pgpSeedGlobalRandomPool( context );
d667c5 ¤
66deb7 ¤   return( err );
4befe6 }
84af5a
0d0335 /*____________________________________________________________________________
59d0d4 ¤   Allocate a new PGPContext using custom memory allocators.
faa973 ¤   This function es exported for the client library and should never be
bebf07 ¤   called by the shared library.
72f7f7 ____________________________________________________________________________*/
c5af5a
9bc744 ¤   PGPError
46000b pgpNewContextCustomInternal(
38fe63 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   clientAPIVersion,
55e95a ¤   PGPNewContextStruct const *¤custom,
c4a012 ¤   PGPContextRef*¤ ¤   ¤   ¤   newContext)
3abb36 {
b07d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
f37b7f ¤   PGPContextRef¤  ¤   context¤= NULL;
1aaf5a
803275 ¤   PGPValidatePtr( newContext );
bc7a23 ¤   *newContext¤= NULL;
7d2c61 ¤   PGPValidatePtr( custom );
b0dd2a ¤   /*¤ Note: if the struct grows, then
8a8223 ¤   ¤   sizeof( PGPNewContextStruct ) will need to be a fixed number */·
9e3f46 ¤   PGPValidateParam( custom->sizeofStruct >= sizeof( PGPNewContextStruct ) );
679145 ¤   PGPValidateParam( PGPMemoryMgrIsValid( custom->memoryMgr ) );
9967c5 ¤
311168 ¤   if ( ! pgpsdkIsInited() )
9fc7a1 ¤   {
bafe5d ¤   ¤   return( kPGPError_ImproperInitialization );
569371 ¤   }
37af5a
36f660 ¤   if ( PGPMajorVersion( clientAPIVersion ) >
2f1405 ¤   ¤   ¤   PGPMajorVersion( kPGPsdkAPIVersion ) ||
65fed0 ¤   ¤   ¤   PGPMajorVersion( clientAPIVersion ) == 0 ·)
89c7a1 ¤   {
1d55fe ¤   ¤   return( kPGPError_IncompatibleAPI );
ea9371 ¤   }
2d67c5 ¤
ffc470 #if PGP_TIME_BOMB
1fd14a ¤   if ( pgpTimeBombHasExpired() )
3fc7a1 ¤   {
3b8c46 ¤   ¤   *newContext¤= NULL;
82b21f ¤   ¤   return( kPGPError_FeatureNotAvailable );
009371 ¤   }
7a7454 #endif
83af5a
336e37 ¤   PGPDebugStartup();
c3af5a
--5239 000843b8a314010024e Page 3 of pgpContext.c
912b98 ¤   context¤= (PGPContext *)PGPNewData( custom->memoryMgr,
ee3243 ¤   ¤   ¤   ¤   sizeof( PGPContext ), kPGPMemoryMgrFlags_Clear );
1567c5 ¤
b7b1f0 ¤   if( IsntPGPError( err ) )
4bc7a1 ¤   {
e558f3 ¤   ¤   context->memoryMgr¤ ¤   ¤   = custom->memoryMgr;
f59fbc ¤   ¤   context->magic¤ ¤   ¤   ¤   = kPGPContextMagic;
716581 ¤   ¤   context->clientAPIVersion¤  = clientAPIVersion;
18b7da ¤   ¤   context->defaultKeySet¤ ¤   = kInvalidPGPKeySetRef;
3c1b52 ¤   ¤
ec53d8 ¤   ¤   err¤= FinishInitContext( context );
71af5a
d3d223 ¤   ¤   if( IsPGPError( err ) )
975b34 ¤   ¤   {
ced288 ¤   ¤   ¤   PGPFreeContext( context );
f018f0 ¤   ¤   ¤   context = kInvalidPGPContextRef;
4c0fe4 ¤   ¤   }
669371 ¤   }
ef0e24 ¤   else
e6c7a1 ¤   {
52bce1 ¤   ¤   err = kPGPError_OutOfMemory;
079371 ¤   }
9167c5 ¤
370beb ¤   *newContext¤= context;
5b67c5 ¤
15deb7 ¤   return( err );
85efe6 }
71af5a
000335 /*____________________________________________________________________________
161047 ¤   Allocate a new PGPContext using the default PGPsdk memory allocators.
faa973 ¤   This function es exported for the client library and should never be
57bf07 ¤   called by the shared library.
9af7f7 ____________________________________________________________________________*/
2eaf5a
83c744 ¤   PGPError
715f6d pgpNewContextInternal(
282898 ¤   PGPUInt32 ¤ ¤   clientAPIVersion,
3b4e0f ¤   PGPContextRef *¤newContext)
aebb36 {
c1dc79 ¤   PGPNewContextStruct¤¤   custom;
529479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
8b67c5 ¤
5b2db5 ¤   pgpAssert( IsntNull( newContext ) );
c47a23 ¤   *newContext¤= NULL;
e967c5 ¤
8a2528 ¤   pgpClearMemory( &custom, sizeof( custom ) );
cbf0bb ¤   custom.sizeofStruct¤= sizeof( custom );
46aa55 ¤   err¤= PGPNewMemoryMgr( 0, &custom.memoryMgr );
ecf1e7 ¤   if ( IsntPGPError( err ) )
aec7a1 ¤   {
efdcdc ¤   ¤   err¤= pgpNewContextCustomInternal( clientAPIVersion,
c36038 ¤   ¤   ¤   ¤   &custom, newContext);
cd9371 ¤   }
e667c5 ¤
6fdeb7 ¤   return( err );
e9efe6 }
a7af5a
0baf5a
fbaf5a
c1af5a
790335 /*____________________________________________________________________________
ee1047 ¤   Allocate a new PGPContext using the default PGPsdk memory allocators.
c3f7f7 ____________________________________________________________________________*/
b2af5a
fc21ab ¤   PGPError·
679ae8 PGPNewContext(
14b13b ¤   PGPUInt32¤  ¤   clientAPIVersion,
644e0f ¤   PGPContextRef *¤newContext)
38bb36 {
0b3275 ¤   PGPValidatePtr( newContext );
ae7a23 ¤   *newContext¤= NULL;
8467c5 ¤
--c15f 00026724c4f4010024e Page 4 of pgpContext.c
5e6ef3 ¤   return( pgpNewContextInternal( clientAPIVersion, newContext ) );
91efe6 }
6caf5a
cbaf5a
9a0335 /*____________________________________________________________________________
a170e3 ¤   Allocate a new custom PGPContext.
ddf7f7 ____________________________________________________________________________*/
52c744 ¤   PGPError
d9cf3a PGPNewContextCustom(
074fbc ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   sdkVersion,
182ceb ¤   PGPNewContextStruct const *¤¤   custom,
35ea0c ¤   PGPContextRef ¤ ¤   ¤   ¤   ¤   *newContext)
6cbb36 {
d726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
b367c5 ¤
123275 ¤   PGPValidatePtr( newContext );
629f5e ¤   *newContext¤= kInvalidPGPContextRef;
362c61 ¤   PGPValidatePtr( custom );
e567c5 ¤
bc126b ¤   err¤= pgpNewContextCustomInternal( sdkVersion, custom, newContext );
c067c5 ¤
4edeb7 ¤   return( err );
bfefe6 }
dbaf5a
24af5a
7f33c8 ¤   static void
3a9161 sDestroyContext( PGPContextRef¤ context )
03bb36 {
8a8ae2 ¤   if ( IsntNull( context->ringPool ) )
f8c7a1 ¤   {
0c0543 ¤   ¤   ringPoolDestroy ( context->ringPool );
34d2fa ¤   ¤   context->ringPool¤  = NULL;
a49371 ¤   }
4f1b52 ¤   ¤
b7454d ¤   if( IsntNull( context->pgpEnvironment ) )
06c7a1 ¤   {
5e9922 ¤   ¤   pgpenvDestroy( context->pgpEnvironment );
fdc6e0 ¤   ¤   context->pgpEnvironment¤= NULL;
239371 ¤   }
2a67c5 ¤
9ca8bb ¤   if ( IsntNull( context->randomPoolContext ) )
02c7a1 ¤   {
0ab508 ¤   ¤   pgpRandomDestroy( context->randomPoolContext );
3d44c4 ¤   ¤   context->randomPoolContext¤ = NULL;
a69371 ¤   }
ec67c5 ¤
7d1cda ¤   if ( IsntNull( context->randomPoolX9_17 ) )
34c7a1 ¤   {
f1ed7c ¤   ¤   pgpRandomDestroy( context->randomPoolX9_17 );
ebbff8 ¤   ¤   context->randomPoolX9_17¤   = NULL;
969371 ¤   }
bc67c5 ¤
d36484 ¤   if ( IsntNull( context->dummyRandomContext ) )
a1c7a1 ¤   {
d0f6c9 ¤   ¤   pgpRandomDestroy( context->dummyRandomContext );
f7d007 ¤   ¤   context->dummyRandomContext¤= NULL;
969371 ¤   }
1967c5 ¤
87c16e ¤   if ( IsntNull( context->prefsRef ) )
c1c7a1 ¤   {
27c8ae ¤   ¤   PGPClosePrefFile( context->prefsRef );
df9371 ¤   }
f0efe6 }
4eaf5a
6a0335 /*____________________________________________________________________________
bfadac ¤   Delete an existing PGPContext and all resources associated with it.
d3f7f7 ____________________________________________________________________________*/
52af5a
4b21ab ¤   PGPError·
fab24c PGPFreeContext(PGPContextRef context)
a7bb36 {
263bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
--811f 000b6e81ba74010024e Page 5 of pgpContext.c
bebfd9 ¤   PGPMemoryMgrRef¤mgr;
ee67c5 ¤
7cf3ca ¤   PGPValidateContext( context );
8f67c5 ¤
3ed751 ¤   /* Get current time into rand pool */
12c36e ¤   PGPGlobalRandomPoolAddKeystroke( PGPGetTime() );
4c5297 ¤   err¤= pgpSaveGlobalRandomPool( context );
ed67c5 ¤
3e7e05 ¤   sDestroyContext( context );
2e67c5 ¤
e5c372 ¤   mgr¤= context->memoryMgr;
9f6cf3 ¤   PGPFreeData( context );
8419d3 ¤   PGPFreeMemoryMgr( mgr );
5667c5 ¤
82deb7 ¤   return( err );
6defe6 }
34af5a
5daf5a
59af5a
470335 /*____________________________________________________________________________
4f98c5 ¤   Allocate a block of memory using the allocator stored in a PGPContext.
11f7f7 ____________________________________________________________________________*/
6faf5a
f859fc ¤   void *
f69a53 pgpContextMemAlloc(
79ba07 ¤   PGPContextRef ¤ ¤   context,
e5cb76 ¤   PGPSize ¤   ¤   ¤   requestSize,
0c1bd1 ¤   PGPMemoryMgrFlags¤  flags)
78bb36 {
e03525 ¤   void¤   *¤  allocation = NULL;
bec267 ¤   PGPSize¤¤   allocationSize¤ = requestSize;
2167c5 ¤
6f8679 ¤   pgpAssert( pgpContextIsValid( context ) );
a967c5 ¤
4670f7 ¤   allocation = PGPNewData( context->memoryMgr,
5f42d4 ¤   ¤   ¤   ¤   ¤   allocationSize, flags );
9067c5 ¤
3cec77 ¤   return( allocation );
9befe6 }
0caf5a
4f0335 /*____________________________________________________________________________
db1643 ¤   Same as pgpContextMemAlloc(), but copies data into newly allocated block.
dcf7f7 ____________________________________________________________________________*/
5baf5a
cf59fc ¤   void *
73217e PGPContextMemAllocCopy(
e3ba07 ¤   PGPContextRef ¤ ¤   context,
90cb76 ¤   PGPSize ¤   ¤   ¤   requestSize,
216569 ¤   PGPMemoryMgrFlags¤  flags,
f2b02f ¤   const void *¤   ¤   dataToCopy )
9ebb36 {
b8d88d ¤   void *¤ allocation;
f867c5 ¤
b48679 ¤   pgpAssert( pgpContextIsValid( context ) );
e667c5 ¤
3970f7 ¤   allocation = PGPNewData( context->memoryMgr,
7290e7 ¤   ¤   ¤   ¤   ¤   requestSize, flags & ~kPGPMemoryMgrFlags_Clear );
6cf2e5 ¤   if ( IsntNull( allocation ) )
51c7a1 ¤   {
89d9f9 ¤   ¤   pgpCopyMemory( dataToCopy, allocation, requestSize );
649371 ¤   }
d567c5 ¤
3bec77 ¤   return( allocation );
f4efe6 }
1daf5a
aeaf5a
2c0335 /*____________________________________________________________________________
ab98c5 ¤   Allocate a block of memory using the allocator stored in a PGPContext.
e6f7f7 ____________________________________________________________________________*/
aaaf5a
c6c744 ¤   PGPError
b6957e pgpContextMemRealloc(
--8dc6 0006b4050944010024e Page 6 of pgpContext.c
afba07 ¤   PGPContextRef ¤ ¤   context,
5746b5 ¤   void¤   ¤   ¤   ¤   **allocation,
2fcb76 ¤   PGPSize ¤   ¤   ¤   requestSize,
fb1bd1 ¤   PGPMemoryMgrFlags¤  flags)
27bb36 {
e926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
c767c5 ¤
065dcc ¤   err = PGPReallocData( context->memoryMgr,
e7218e ¤   ¤   ¤   allocation, requestSize, flags );
5bdeb7 ¤   return( err );
41efe6 }
82af5a
510335 /*____________________________________________________________________________
d6680d ¤   Free a block of memory using the deallocator stored in a PGPContext.
a9f7f7 ____________________________________________________________________________*/
c4af5a
b1c744 ¤   PGPError
f8499a pgpContextMemFree(
b535f6 ¤   PGPContextRef ¤ context,
ec02b9 ¤   void * ¤¤   ¤   allocation)
76bb36 {
1961e0 ¤   PGPError¤   err;
ff67c5 ¤
70f3ca ¤   PGPValidateContext( context );
2f3cc4 ¤   (void)context;
3767c5 ¤
e3e2e5 ¤   err = PGPFreeData( allocation );
dd67c5 ¤
b5deb7 ¤   return( err );
b4efe6 }
0a67c5 ¤
6b21ab ¤   PGPError·
bf73eb PGPGetContextUserValue(
8135f6 ¤   PGPContextRef ¤ context,
a78e4a ¤   PGPUserValue ¤  *userValue)
f5bb36 {
538e12 ¤   PGPError¤   err = kPGPError_NoErr;
3767c5 ¤
09dab2 ¤   PGPValidatePtr( userValue );
6aae52 ¤   *userValue¤ = NULL;
fcf3ca ¤   PGPValidateContext( context );
1267c5 ¤
011afc ¤   *userValue = context->userValue;
e667c5 ¤
8cdeb7 ¤   return( err );
63efe6 }
9daf5a
d2af5a
2c5947 ¤   PGPMemoryMgrRef
db333e PGPGetContextMemoryMgr( PGPContextRef context )
5cbb36 {
e6d1d8 ¤   if ( ! pgpContextIsValid( context ) )
88ef86 ¤   ¤   return( NULL );
261b52 ¤   ¤
07dbfc ¤   return( context->memoryMgr );
43efe6 }
98af5a
8caf5a
8d21ab ¤   PGPError·
d9c0a8 PGPSetContextUserValue(
2335f6 ¤   PGPContextRef ¤ context,
182e8b ¤   PGPUserValue ¤  userValue)
fbbb36 {
108e12 ¤   PGPError¤   err = kPGPError_NoErr;
d167c5 ¤
63f3ca ¤   PGPValidateContext( context );
6c67c5 ¤
52a41f ¤   context->userValue = userValue;
9667c5 ¤
eadeb7 ¤   return( err );
2befe6 }
6baf5a
--2c6e 000717981544010024e Page 7 of pgpContext.c
f0275e ¤   PGPEnv *
cbea2d pgpContextGetEnvironment(PGPContextRef context)
78bb36 {
ad8679 ¤   pgpAssert( pgpContextIsValid( context ) );
82af5a
8955a2 ¤   return( context->pgpEnvironment );
4eefe6 }
7daf5a
d3af5a
8b66dd ¤   static PGPError
72f25d sCreateRandomContext(·
379a06 ¤   PGPContextRef¤  ¤   ¤   context,
ed4153 ¤   PGPRandomVTBL const *¤  vtbl,
4bf0b9 ¤   PGPRandomContext **¤¤   outRandom )
89bb36 {
e5d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
c3f69b ¤   PGPRandomContext *¤ newRandom¤  = NULL;
0b67c5 ¤
5e8679 ¤   pgpAssert( pgpContextIsValid( context ) );
aa67c5 ¤
851b52 ¤   ¤
6d931a ¤   newRandom¤  = (PGPRandomContext *)
8f86bd ¤   ¤   pgpContextMemAlloc( context, sizeof( *newRandom ),
5707d2 ¤   ¤   kPGPMemoryMgrFlags_Clear );
1e8d16 ¤   if ( IsntNull( newRandom ) )
bcc7a1 ¤   {
c4625b ¤   ¤   newRandom->context¤ = context;
7bb83d ¤   ¤   newRandom->vtbl¤¤   = vtbl;
330657 ¤   ¤   newRandom->priv¤¤   = NULL;
311229 ¤   ¤   newRandom->destroy¤ = NULL;
db9371 ¤   }
260e24 ¤   else
83c7a1 ¤   {
9a17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
3d9371 ¤   }
2daf5a
0217f5 ¤   *outRandom¤ = newRandom;
6edeb7 ¤   return( err );
63efe6 }
fcaf5a
6daf5a
31af5a
3d0334 ¤   PGPRandomContext *
30e269 pgpContextGetGlobalPoolRandomContext(PGPContextRef context)
98bb36 {
db8679 ¤   pgpAssert( pgpContextIsValid( context ) );
4667c5 ¤
5e27b8 ¤   if ( IsNull( context->randomPoolContext ) )
1ac7a1 ¤   {
52ecb7 ¤   ¤   PGPRandomContext *¤ randomContext¤  = NULL;
b31b52 ¤   ¤
4d820f ¤   ¤   (void)sCreateRandomContext( context,
ca48ef ¤   ¤   ¤   pgpGetGlobalRandomPoolVTBL(), &randomContext );
35bf9c ¤   ¤   context->randomPoolContext¤ = randomContext;
791b52 ¤   ¤
1606ba ¤   ¤   if ( IsntNull( context->randomPoolContext ) )
595b34 ¤   ¤   {
837aad ¤   ¤   ¤   /*
e0fc85 ¤   ¤   ¤   * in case there is a problem in reading the random pool,
dc522b ¤   ¤   ¤   * feed in some amount of "random" data to avoid a totally
9ba925 ¤   ¤   ¤   * predictible pool
4e3da8 ¤   ¤   ¤   */
2444da ¤   ¤   ¤   pgpRandomCollectEntropy( randomContext );
5444da ¤   ¤   ¤   pgpRandomCollectEntropy( randomContext );
9144da ¤   ¤   ¤   pgpRandomCollectEntropy( randomContext );
c644da ¤   ¤   ¤   pgpRandomCollectEntropy( randomContext );
e90fe4 ¤   ¤   }
be9371 ¤   }
d1a50a ¤   /* NOTE: someone must still call pgpSeedGlobalRandomPool() */
78af5a
d34a94 ¤   return( context->randomPoolContext );
71efe6 }
--a65c 000b98f5eab4010024e Page 8 of pgpContext.c
e0af5a
1aaf5a
17af5a
a10334 ¤   PGPRandomContext *
7e827d pgpContextGetDummyRandomContext(PGPContextRef context)
efbb36 {
a88679 ¤   pgpAssert( pgpContextIsValid( context ) );
ab67c5 ¤
9c5690 ¤   if ( IsNull( context->dummyRandomContext ) )
3bc7a1 ¤   {
26820f ¤   ¤   (void)sCreateRandomContext( context,
e6e447 ¤   ¤   ¤   pgpGetGlobalDummyRandomPoolVTBL(),
99359a ¤   ¤   ¤   &context->dummyRandomContext );
ff9371 ¤   }
d9af5a
9fa8d3 ¤   return( context->dummyRandomContext );
18efe6 }
9faf5a
faaf5a
c9af5a
730334 ¤   PGPRandomContext *
91e5d1 pgpContextGetX9_17RandomContext(PGPContextRef context)
c4bb36 {
ef8679 ¤   pgpAssert( pgpContextIsValid( context ) );
9f67c5 ¤
55aa9b ¤   if ( IsNull( context->randomPoolX9_17 ) )
55c7a1 ¤   {
c98b09 ¤   ¤   context->randomPoolX9_17¤   = pgpRandomCreate( context );
e89371 ¤   }
31af5a
d5183d ¤   return( context->randomPoolX9_17 );
a3efe6 }
c9af5a
39af5a
0e0335 /*____________________________________________________________________________
ab7790 ····Fill the user-specified buffer with random values from the global
0a6c7c ····random pool. ·If we were not able to initialize the random pool
171804 ····we return kPGPError_OutOfEntropy.
adf7f7 ____________________________________________________________________________*/
cfc744 ¤   PGPError
ac2030 PGPContextGetRandomBytes(
50520e ¤   PGPContextRef¤  context,
65ac9e ¤   void *¤ ¤   ¤   buf,
57b858 ¤   PGPSize¤¤   ¤   len
a827e6 ¤   )
cbbb36 {
a9bce6 ¤   PGPRandomContext *¤ randomContext;
34af5a
23a9c8 ¤   PGPValidatePtr( buf );
5fdfa9 ¤   PGPValidateParam( pgpContextIsValid( context ) );
60af5a
3bbb04 ¤   randomContext = pgpContextGetX9_17RandomContext( context );
c59118 ¤   if( IsNull( randomContext )
e2a6b6 ¤   ¤   || !PGPGlobalRandomPoolHasMinimumEntropy() )
60c7a1 ¤   {
a5e843 ¤   ¤   return kPGPError_OutOfEntropy;
e59371 ¤   }
f6af5a
68f4aa ¤   pgpRandomGetBytes( randomContext, buf, len );
5e67c5 ¤
b3151e ¤   return kPGPError_NoErr;
dfefe6 }
79af5a
baaf5a
7034d2 ¤   RingPool *
03b5ba pgpContextGetRingPool(PGPContextRef context)
cebb36 {
ee8679 ¤   pgpAssert( pgpContextIsValid( context ) );
95af5a
6401e3 ¤   return( context->ringPool );
e9efe6 }
b9af5a
--0132 00015de19694010024e Page 9 of pgpContext.c
3b6d52 ¤   void
f75485 pgpContextSetRingPool(
8bba07 ¤   PGPContextRef ¤ ¤   context,
eb4c6c ¤   RingPool¤   ¤   ¤   *ringPool)
9ebb36 {
c88679 ¤   pgpAssert( pgpContextIsValid( context ) );
e0af5a
742c40 ¤   context->ringPool = ringPool;
d1efe6 }
30af5a
0faf5a
ffd190 ¤   PGPKeySetRef
dfd4c5 pgpContextGetDefaultKeySet(PGPContextRef context)
8bbb36 {
d78679 ¤   pgpAssert( pgpContextIsValid( context ) );
60af5a
f5a0c6 ¤   return( context->defaultKeySet );
7defe6 }
08af5a
bb523b /* We may retire the prefs stuff, but this is for transition at least */
016d52 ¤   void
d936e2 pgpContextSetPrefsChanged(
51520e ¤   PGPContextRef¤  context,
033bad ¤   PGPBoolean¤ ¤   prefsChanged
6327e6 ¤   )
60bb36 {
e89f22 ¤   context->prefsChanged = prefsChanged;
b4efe6 }
62af5a
6716ea ¤   PGPBoolean
0be718 pgpContextArePrefsChanged(
f8cf6e ¤   PGPContextRef¤  context
0427e6 ¤   )
c0bb36 {
c3a39a ¤   return context->prefsChanged;
4defe6 }
55af5a
03af5a
400eaf ¤   PGPPrefRef
3df340 pgpContextGetPrefs( PGPContextRef¤  context)
8abb36 {
11c13a ¤   return( context->prefsRef );
dcefe6 }
86af5a
566d52 ¤   void
37421d pgpContextSetPrefs(
28520e ¤   PGPContextRef¤  context,
218596 ¤   PGPPrefRef¤ ¤   prefs )
04bb36 {
e1ae99 ¤   context->prefsRef = prefs;
cfefe6 }
0eaf5a
45af5a
f53add static PGPUInt32¤   sInitedCount¤   ¤   = 0;
cd8815 static PGPBoolean¤  sFreeMemoryMgrList¤ = FALSE;
2aaf5a
94c744 ¤   PGPError
ace8ca PGPsdkInit( void )
35bb36 {
bc26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
0467c5 ¤
acd238 ¤   if ( sInitedCount == 0 )
b2c7a1 ¤   {
612173 ¤   ¤   pgpLeaksBeginSession( "PGPsdk" );
ab1b52 ¤   ¤
917c03 ¤   ¤   if( IsNull( PGPGetDefaultMemoryMgr() ) )
c15b34 ¤   ¤   {
1b1490 ¤   ¤   ¤   PGPMemoryMgrRef¤memoryMgr;
8b87c7 ¤   ¤   ¤
f9333a ¤   ¤   ¤   sFreeMemoryMgrList = TRUE;
ed87c7 ¤   ¤   ¤
156ce6 ¤   ¤   ¤   err = PGPNewMemoryMgr( 0, &memoryMgr );
--1012 0003027039a4010024e Page 10 of pgpContext.c
87144d ¤   ¤   ¤   pgpAssertNoErr( err );
e9698b ¤   ¤   ¤   if( IsntPGPError( err ) )
19f776 ¤   ¤   ¤   {
d38841 ¤   ¤   ¤   ¤   err = PGPSetDefaultMemoryMgr( memoryMgr );
7355be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
09a3a6 ¤   ¤   ¤   }
e40fe4 ¤   ¤   }
7d1b52 ¤   ¤
a686f8 ¤   ¤   if( IsntPGPError( err ) )
d95b34 ¤   ¤   {
3493f6 ¤   ¤   ¤   err¤= pgpInitMacBinaryMappings();
cf144d ¤   ¤   ¤   pgpAssertNoErr( err );
af0fe4 ¤   ¤   }
3d1b52 ¤   ¤
2e86f8 ¤   ¤   if( IsntPGPError( err ) )
f85b34 ¤   ¤   {
0605eb ¤   ¤   ¤   bnInit();
ea0fe4 ¤   ¤   }
209371 ¤   }
4267c5 ¤
2ff1e7 ¤   if ( IsntPGPError( err ) )
e3c7a1 ¤   {
50117b ¤   ¤   ++sInitedCount;
059371 ¤   }
6267c5 ¤
c1deb7 ¤   return( err );
c8efe6 }
10af5a
afaf5a
c616ea ¤   PGPBoolean
504d90 pgpsdkIsInited( void )
a1bb36 {
caec91 ¤   return( sInitedCount != 0 );
2cefe6 }
deaf5a
cfc744 ¤   PGPError
797837 pgpsdkCleanupForce( void )
4fbb36 {
3f26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3b67c5 ¤
fbd66b ¤   if ( sInitedCount != 0 )
ebc7a1 ¤   {
8cd0a6 ¤   ¤   sInitedCount¤   = 1;
8d9371 ¤   }
f467c5 ¤
bd089a ¤   err¤= PGPsdkCleanup();
99deb7 ¤   return( err );
35efe6 }
2daf5a
7ec744 ¤   PGPError
980567 PGPsdkCleanup( void )
dbbb36 {
0a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a367c5 ¤
e160e5 ¤   pgpAssert( sInitedCount != 0 );
5cd66b ¤   if ( sInitedCount != 0 )
41c7a1 ¤   {
8395c5 ¤   ¤   --sInitedCount;
1b696e ¤   ¤   if ( sInitedCount == 0 )
c45b34 ¤   ¤   {
1291c2 ¤   ¤   ¤   pgpDisposeMacBinaryMappings();
0387c7 ¤   ¤   ¤
6f3560 ¤   ¤   ¤   if( sFreeMemoryMgrList )
0de7b9 ¤   ¤   ¤   ¤   pgpFreeDefaultMemoryMgrList();
cc2b85 ¤   ¤   ¤   ¤
496cc1 ¤   ¤   ¤   pgpLeaksEndSession();
6e0fe4 ¤   ¤   }
929371 ¤   }
eb0e24 ¤   else
07c7a1 ¤   {
a3bc3e ¤   ¤   err¤= kPGPError_BadParams;
309371 ¤   }
--cb4f 001ebb822254010024e Page 11 of pgpContext.c
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
40af5a
f97e4d /*__Editor_settings____
baaf5a
8f4126 ¤   Local Variables:
907b17 ¤   tab-width: 4
5a0e6c ¤   End:
865f8c ¤   vi: ts=4 sw=4
019e9b ¤   vim: si
ebd062 _____________________*/
--1cc4 000b3daa20f4010024f Page 1 of pgpContext.h
a70335 /*____________________________________________________________________________
6a45c7 ¤   pgpContext.h
7d67c5 ¤
65c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
a44b0f ¤   All rights reserved.
e167c5 ¤
8e159c ¤   This file contains the definition of the PGPContext data structure and
58b36f ¤   prototypes for private context manipulation functions. See pgpUtilities.h
4f6de9 ¤   for public PGPContext manipulation functions
4aaf5a
5a0543 ¤   $Id: pgpContext.h,v 1.33.12.1 1998/11/12 03:23:05 heller Exp $
1df7f7 ____________________________________________________________________________*/
7faf5a
b1f99e #ifndef Included_pgpContext_h¤  /* [ */
3dcc52 #define Included_pgpContext_h
95af5a
b76773 #include "pgpMemoryMgr.h"
23adb8 #include "pgpOpaqueStructs.h"
594919 #include "pgpUtilities.h"
362b62 #include "pgpPFLErrors.h"
31e8b2 #include "pflPrefs.h"
f9af5a
e199c6 PGP_BEGIN_C_DECLARATIONS
8bcbcf #if PRAGMA_IMPORT_SUPPORTED
bbb981 #pragma import on
9e7454 #endif
18af5a
b3a056 PGPBoolean ¤pgpContextIsValid( PGPContextRef context );
f22c3d #define PGPValidateContext( context )¤  \
ee4c49 ¤   PGPValidateParam( pgpContextIsValid( context ) )
49af5a
dfb16e PGPError ¤  pgpNewContextInternal( PGPUInt32 sdkVersion,
a3b51f ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef *newContext);
555e0d PGPError ¤  pgpNewContextCustomInternal(
761513 ¤   ¤   ¤   ¤   PGPUInt32 sdkVersion,
38ef2d ¤   ¤   ¤   ¤   PGPNewContextStruct const *¤custom,
90b3c3 ¤   ¤   ¤   ¤   PGPContextRef * newContext);
2b67c5 ¤
1d6744 PGPEnv *¤   pgpContextGetEnvironment(PGPContextRef context);
0baf5a
e64f44 PGPRandomContext *¤ pgpContextGetGlobalPoolRandomContext(
10c5b0 ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context);
11c0dd PGPRandomContext *¤ pgpContextGetDummyRandomContext(PGPContextRef context);
5cafdc PGPRandomContext *¤ pgpContextGetX9_17RandomContext(PGPContextRef context);
1bda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
386b87 RingPool ·*¤¤   pgpContextGetRingPool(PGPContextRef context);
5d272b void¤   ¤   ¤   ¤   pgpContextSetRingPool(PGPContextRef context,
194e54 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   RingPool *ringPool);
96071e PGPKeySetRef¤   ¤   pgpContextGetDefaultKeySet(PGPContextRef context);
b1ae42 PGPBoolean¤ ¤   ¤   pgpContextArePrefsChanged(PGPContextRef context);
829234 void¤   ¤   ¤   ¤   pgpContextSetPrefsChanged(PGPContextRef context,
e85ef0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean randomSeeded);
abaf5a
ccda95 void¤   ¤   ¤   ¤   pgpContextSetPrefs( PGPContextRef context,
94d641 ¤   ¤   ¤   ¤   ¤   ¤   PGPPrefRef prefs );
d1daa7 PGPPrefRef¤ ¤   ¤   pgpContextGetPrefs( PGPContextRef context );
0daf5a
81036c /* memory allocation and deallocation */
998f25 void ·*¤¤   pgpContextMemAlloc( PGPContextRef context,
c70b61 ¤   ¤   ¤   ¤   ¤   PGPSize allocationSize, PGPMemoryMgrFlags flags );
c18334 void ·*¤¤   PGPContextMemAllocCopy( PGPContextRef context,
3dc8ba ¤   ¤   ¤   ¤   ¤   PGPSize allocationSize, PGPMemoryMgrFlags flags,
7fd6c7 ¤   ¤   ¤   ¤   ¤   const void *dataToCopy);
597ad5 PGPError ¤  pgpContextMemRealloc( PGPContextRef context,
d8f46a ¤   ¤   ¤   ¤   ¤   void **allocation, PGPSize newAllocationSize,
e518d7 ¤   ¤   ¤   ¤   ¤   PGPMemoryMgrFlags flags );
bfff16 PGPError ¤  pgpContextMemFree( PGPContextRef context,
40b7eb ¤   ¤   ¤   ¤   ¤   void *allocation );
d3af5a
c5ae30 ¤   ¤   ¤   ¤   ¤
69cbcf #if PRAGMA_IMPORT_SUPPORTED
b32ced #pragma import reset
--f889 00121b3881f4010024f Page 2 of pgpContext.h
a07454 #endif
081254 PGP_END_C_DECLARATIONS
84af5a
1a1e6d #endif /* ] Included_pgpContext_h */
d2af5a
307e4d /*__Editor_settings____
0daf5a
644126 ¤   Local Variables:
fd7b17 ¤   tab-width: 4
8c0e6c ¤   End:
9e5f8c ¤   vi: ts=4 sw=4
0e9e9b ¤   vim: si
21d062 _____________________*/
--63bc 000855d750740100250 Page 1 of pgpFeatures.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
0baf5a
67987d ¤   $Id: pgpFeatures.c,v 1.27.2.2.2.1 1998/11/12 03:23:06 heller Exp $
23af5a
dfaf5a
f4af5a
6df7f7 ____________________________________________________________________________*/
803051 #include "pgpSDKBuildFlags.h"
e9e2ff #include "pgpConfig.h"
82324c #include <string.h>
a6a146 #include "pgpDebug.h"
42af5a
4a2f8d #include "pgpErrors.h"
610d08 #include "pgpMem.h"
c44919 #include "pgpUtilities.h"
f6af5a
4304f5 #include "pgpFeatures.h"
57eee9 #include "pgpTimeBomb.h"
0daf5a
cecdc2 #include "pgpPubKey.h"
0b1f0b #include "pgpDES3.h"
0e43b4 #include "pgpCAST5.h"
4baf5a
92ea6e #if PGP_IDEA
5d6332 #include "pgpIDEA.h"
377454 #endif
d9af5a
d2be7a #ifndef PGP_RSA
5231da #error "PGP_RSA requires a value"
207454 #endif
d3af5a
c521ab ¤   PGPError·
ad9eb7 PGPGetSDKVersion( PGPUInt32 *version )
f9bb36 {
1c32ec ¤   PGPValidatePtr( version );
0624ff ¤   *version¤   = kPGPsdkAPIVersion;
2567c5 ¤
442d68 ¤   return( kPGPError_NoErr );
1eefe6 }
8daf5a
c3af5a
74af5a
0eaf5a
daaf5a
3baf5a
4a0335 /*____________________________________________________________________________
a31944 ¤   Return a flags word for the feature selector
3af7f7 ____________________________________________________________________________*/
0121ab ¤   PGPError·
6430d6 PGPGetFeatureFlags(
de9766 ¤   PGPFeatureSelector¤ selector,
12f44b ¤   PGPFlags *¤ ¤   ¤   flagsPtr )
f9bb36 {
4030d4 ¤   PGPError¤   err¤¤   = kPGPError_NoErr;
8fc6a8 ¤   PGPFlags¤   flags¤  = 0;
c467c5 ¤
2cc4d6 ¤   PGPValidatePtr( flagsPtr );
6e81e2 ¤   *flagsPtr¤  = 0;
0367c5 ¤
23365b ¤   switch ( selector )
e1c7a1 ¤   {
e69ae3 ¤   ¤   default:
959a4f ¤   ¤   ¤   /* update comment in pgpFeatures.h if this changes */
063c41 ¤   ¤   ¤   err¤¤   = kPGPError_ItemNotFound;
065755 ¤   ¤   ¤   flags¤  = 0;
bccdcb ¤   ¤   ¤   break;
2687c7 ¤   ¤   ¤
fb722b ¤   ¤   case kPGPFeatures_GeneralSelector:
855b34 ¤   ¤   {
--80af 00064e8464540100250 Page 2 of pgpFeatures.c
e02920 ¤   ¤   ¤   flags¤  =¤  0
4dc75a #if !PGP_ENCRYPT_DISABLE
2019ec ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFeatureMask_CanEncrypt
587454 #endif
1ec046 #if !PGP_DECRYPT_DISABLE
14eed1 ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFeatureMask_CanDecrypt
8c7454 #endif
bd7163 #if !PGP_SIGN_DISABLE
affc21 ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFeatureMask_CanSign
2e7454 #endif
3b4d61 #if !PGP_VERIFY_DISABLE
3c2b02 ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFeatureMask_CanVerify
e67454 #endif
5dc98a ¤   ¤   ¤   ¤   ¤   ¤   ;
e6cdcb ¤   ¤   ¤   break;
200fe4 ¤   ¤   }
c287c7 ¤   ¤   ¤
a55a3d ¤   ¤   case kPGPFeatures_ImplementationSelector:
435b34 ¤   ¤   {
905755 ¤   ¤   ¤   flags¤  = 0;
9187c7 ¤   ¤   ¤
c7e3b7 ¤   ¤   #if PGP_DEBUG
2beaf4 ¤   ¤   ¤   flags¤  |= kPGPFeatureMask_IsDebugBuild;
79d656 ¤   ¤   #endif
401b52 ¤   ¤
6fa6bd ¤   ¤   #ifndef PGP_TIME_BOMB
d5fdbc ¤   ¤   #error PGP_TIME_BOMB must be defined
b1d656 ¤   ¤   #endif
151b52 ¤   ¤
2e395f ¤   ¤   #if PGP_TIME_BOMB
7f982a ¤   ¤   ¤   flags¤  |= kPGPFeatureMask_HasTimeout;
40d656 ¤   ¤   #endif
62cdcb ¤   ¤   ¤   break;
690fe4 ¤   ¤   }
b69371 ¤   }
9f67c5 ¤
e01708 ¤   *flagsPtr¤  = flags;
ca67c5 ¤
7adeb7 ¤   return( err );
a7efe6 }
01af5a
56af5a
2baf5a
ea0335 /*____________________________________________________________________________
d27502 ¤   Return a C string of the form:
13ac89 ¤   ¤   "PGPsdk version 1.0 (C) 1997 Pretty Good Privacy, Inc"
7bf7f7 ____________________________________________________________________________*/
8121ab ¤   PGPError·
aedde7 PGPGetSDKString( char theString[ 256 ] )
fbbb36 {
fc59da ¤   static const char¤  kVersionString[]¤   =
81d57f ¤   ¤   "PGPsdk version 1.5.2 (C) 1997-1998 Network Associates, Inc. and its "
2c7eab ¤   ¤   "affiliated companies."
6227e2 #if ! PGP_RSA
fa25a2 ¤   ¤   " (Diffie-Helman/DSS-only version)"
c87454 #endif
0d1d52 ¤   ¤   ;
3467c5 ¤
c3f382 ¤   PGPValidatePtr( theString );
940e4c ¤   /* leave this in even in non-debug; enforce having the space */
e6e801 ¤   pgpClearMemory( theString, 256 );
e267c5 ¤
71eda7 ¤   strcpy( theString, kVersionString );
9d67c5 ¤
d82d68 ¤   return( kPGPError_NoErr );
59efe6 }
b7af5a
5caf5a
95c127 static PGPPublicKeyAlgorithmInfo¤   sPublicKeyAlgs[] =
fdbb36 {
c3af5a
6499a4 #if PGP_RSA
--e5c5 000003aeda940100250 Page 3 of pgpFeatures.c
fd3ff2 ¤   #if PGP_USECAPIFORRSA
ddef6f ¤   ¤   #define kRSALongVersionString¤  "RSA (CAPI)"
3ce603 ¤   #elif PGP_USEBSAFEFORRSA
ecd16b ¤   ¤   #define kRSALongVersionString¤  "RSA (BSAFE)"
0e40e1 ¤   #elif PGP_USERSAREF
a3309e ¤   ¤   #define kRSALongVersionString¤  "RSA (RSAREF)"
d391af ¤   #elif PGP_USEPGPFORRSA
8e1898 ¤   ¤   #define kRSALongVersionString¤  "RSA (PGP)"
8b47b4 ¤   #else
828af5 ¤   ¤   #error Unknown RSA implementation
3cb7ec ¤   #endif
c667c5 ¤
15741c /* Must be first one, we skip it if not available at run time */
e9b08c ¤   {{ "RSA", kRSALongVersionString, "", 0, {0,} },
ce07dd ¤   ¤   kPGPPublicKeyAlgorithm_RSA,
356e79 ¤   ·¤  !PGP_ENCRYPT_DISABLE, !PGP_DECRYPT_DISABLE,
57a309 ¤   ·¤  !PGP_SIGN_DISABLE, !PGP_VERIFY_DISABLE, TRUE,
75ce57 ¤   ····0, 0, 0 },
397ead #endif /* PGP_RSA */
f11b52 ¤   ¤
21f5dc ¤   {{ "ElGamal",¤  "ElGamal",¤ "", 0, {0,} },
d84b6a ¤   ¤   kPGPPublicKeyAlgorithm_ElGamal,
252a65 ¤   ·¤  !PGP_ENCRYPT_DISABLE, !PGP_DECRYPT_DISABLE, FALSE, FALSE, TRUE,
f8ce57 ¤   ····0, 0, 0 },
ba1b52 ¤   ¤
ceb5b2 ¤   {{ "DSA",¤  ¤   "Digital Signature Standard",¤  "", 0, {0,} },
a68805 ¤   ¤   kPGPPublicKeyAlgorithm_DSA,
249b94 ¤   ·¤  FALSE, FALSE, !PGP_SIGN_DISABLE, !PGP_VERIFY_DISABLE, TRUE,
af8799 ········0, 0, 0 },
a082f7 };
2b6507 #define kNumPublicKeyAlgs¤  \
0d71b2 ( sizeof( sPublicKeyAlgs ) / sizeof( sPublicKeyAlgs[ 0 ] ) )
d2af5a
3daf5a
96c744 ¤   PGPError
6441c8 PGPCountPublicKeyAlgorithms( PGPUInt32 *numAlgs )
d2bb36 {
67bbc5 ¤   PGPValidatePtr( numAlgs );
7867c5 ¤
4d2ab8 ¤   *numAlgs¤   = kNumPublicKeyAlgs;
cb99a4 #if PGP_RSA
64920e ¤   if( pgpKeyUse( pgpPkalgByNumber( kPGPPublicKeyAlgorithm_RSA ) ) == 0 )
d4a85a ¤   ¤   *numAlgs -= 1;
487454 #endif
c32d68 ¤   return( kPGPError_NoErr );
c9efe6 }
03af5a
4eaf5a
7cc744 ¤   PGPError
008869 PGPGetIndexedPublicKeyAlgorithmInfo(
bcceb0 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   idx,
64fab3 ¤   PGPPublicKeyAlgorithmInfo *¤info)
0fbb36 {
eb4c7a ¤   PGPValidatePtr( info );
ad363d ¤   pgpClearMemory( info, sizeof( *info ) );
6aaf5a
7999a4 #if PGP_RSA
50c7a1 ¤   {
6d1f89 ¤   ¤   int rsause =
1d9b62 ¤   ¤   ¤   pgpKeyUse( pgpPkalgByNumber( kPGPPublicKeyAlgorithm_RSA ) );
9e0396 ¤   ¤   if (rsause == 0)
70edc5 ¤   ¤   ¤   idx += 1;
c59bbd ¤   ¤   if( idx == 0 ) {
ab4641 #if PGP_ENCRYPT_DISABLE
a49521 ¤   ¤   ¤   sPublicKeyAlgs[0].canEncrypt¤   = FALSE;
c6db21 #else
6e1b1d ¤   ¤   ¤   sPublicKeyAlgs[0].canEncrypt¤   = !!(rsause & PGP_PKUSE_ENCRYPT);
6e7454 #endif
89415d #if PGP_DECRYPT_DISABLE
524db1 ¤   ¤   ¤   sPublicKeyAlgs[0].canDecrypt¤   = FALSE;
d8db21 #else
008782 ¤   ¤   ¤   sPublicKeyAlgs[0].canDecrypt¤   = !!(rsause & PGP_PKUSE_ENCRYPT);
--39ff 000a18bb4de40100250 Page 4 of pgpFeatures.c
a07454 #endif
89db05 #if PGP_SIGN_DISABLE
14b2f2 ¤   ¤   ¤   sPublicKeyAlgs[0].canSign¤  ¤   = FALSE;
3edb21 #else
c2599c ¤   ¤   ¤   sPublicKeyAlgs[0].canSign¤  ¤   = !!(rsause & PGP_PKUSE_SIGN);
907454 #endif
7176b4 #if PGP_VERIFY_DISABLE
2f49ea ¤   ¤   ¤   sPublicKeyAlgs[0].canVerify¤= ¤ FALSE;
99db21 #else
d8ead8 ¤   ¤   ¤   sPublicKeyAlgs[0].canVerify¤¤   = !!(rsause & PGP_PKUSE_SIGN);
af7454 #endif
690fe4 ¤   ¤   }
799371 ¤   }
778e60 #endif¤
b6af5a
6dbcf9 ¤   PGPValidateParam( idx < kNumPublicKeyAlgs );
8faf5a
4dd99c ¤   *info¤  = sPublicKeyAlgs[ idx ];
6567c5 ¤
992d68 ¤   return( kPGPError_NoErr );
fdefe6 }
69af5a
e8af5a
6daf5a
7caf5a
e3af5a
36a75b static const PGPSymmetricCipherInfo¤sSymmetricCipherAlgs[] =
88bb36 {
4aea6e #if PGP_IDEA
f297c6 ¤   {{ "IDEA",¤ "IDEA",¤¤   "",¤0, {0,} },¤ ¤   kPGPCipherAlgorithm_IDEA},
917454 #endif
7daf5a
bc1a99 #if PGP_DES3
7e4e1e ¤   {{ "3DES",¤ "3DES",¤¤   "",¤0, {0,} },¤ ¤   kPGPCipherAlgorithm_3DES},
c47454 #endif
2a67c5 ¤
112beb #if PGP_CAST5
d68143 ¤   {{ "CAST5",¤"CAST5",¤   "",¤0, {0,} },¤ ¤   kPGPCipherAlgorithm_CAST5},
1a7454 #endif
5182f7 };
474896 #define kNumSymmetricCipherAlgs¤¤   \
8baee3 ¤   ( sizeof( sSymmetricCipherAlgs ) / sizeof( sSymmetricCipherAlgs[ 0 ] ) )
d8af5a
88af5a
430335 /*____________________________________________________________________________
b2e0fc ¤   The call to this routine ensures that these algorithms are actually
e85170 ¤   present; it's intended to make the programmer notice if one or more
c37974 ¤   of them are not linked in.
8bf7f7 ____________________________________________________________________________*/
6cc32f ¤   static const PGPCipherVTBL *
988666 sEnsureSymmetricCipherLinked( PGPCipherAlgorithm¤   alg)
23bb36 {
4e3815 ¤   PGPCipherVTBL const *vtbl¤  = NULL;
2567c5 ¤
7b8d76 ¤   switch( alg )
59c7a1 ¤   {
ba9ae3 ¤   ¤   default:
eecdcb ¤   ¤   ¤   break;
ff5fff ¤   #if PGP_IDEA
e05be3 ¤   ¤   case kPGPCipherAlgorithm_IDEA:¤ vtbl¤   = &cipherIDEA;¤ break;
37b7ec ¤   #endif
bf67c5 ¤
8eaf08 ¤   #if PGP_DES3
28adb6 ¤   ¤   case kPGPCipherAlgorithm_3DES:¤ vtbl¤   = &cipher3DES;¤ break;
07b7ec ¤   #endif
8d67c5 ¤
bfae5e ¤   #if PGP_CAST5
113f09 ¤   ¤   case kPGPCipherAlgorithm_CAST5:¤vtbl¤   = &cipherCAST5;¤break;
a7b7ec ¤   #endif
229371 ¤   }
3667c5 ¤
a17543 ¤   return( vtbl );
--a6e2 001c3a19a9c40100250 Page 5 of pgpFeatures.c
7aefe6 }
46af5a
b0c744 ¤   PGPError
35316c PGPCountSymmetricCiphers( PGPUInt32 *numAlgs )
4cbb36 {
52bbc5 ¤   PGPValidatePtr( numAlgs );
1d67c5 ¤
f0da1a ¤   *numAlgs¤   = kNumSymmetricCipherAlgs;
182d68 ¤   return( kPGPError_NoErr );
93efe6 }
0aaf5a
dfaf5a
27c744 ¤   PGPError
89d9a4 PGPGetIndexedSymmetricCipherInfo(
3bceb0 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   idx,
8e5d1c ¤   PGPSymmetricCipherInfo *¤   info)
b0bb36 {
a54c7a ¤   PGPValidatePtr( info );
e2363d ¤   pgpClearMemory( info, sizeof( *info ) );
ad0374 ¤   PGPValidateParam( idx < kNumSymmetricCipherAlgs );
91af5a
a9629d ¤   *info¤  = sSymmetricCipherAlgs[ idx ];
e367c5 ¤
33f54e ¤   sEnsureSymmetricCipherLinked( info->algID );
3b67c5 ¤
5c2d68 ¤   return( kPGPError_NoErr );
2fefe6 }
c02b85 ¤   ¤   ¤   ¤
8faf5a
33af5a
b0af5a
d91b52 ¤   ¤
387e4d /*__Editor_settings____
edaf5a
174126 ¤   Local Variables:
e47b17 ¤   tab-width: 4
610e6c ¤   End:
9e5f8c ¤   vi: ts=4 sw=4
589e9b ¤   vim: si
c3d062 _____________________*/
--9ed2 000260086ad40100251 Page 1 of pgpGroups.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
8a0198 ¤   Core groups-handling code. ·Does not, and should not have any
b958db ¤   connection to PGPsdk constructs. ·Code of that nature belongs
fb4bbe ¤   in pgpGroupsUtil.c.
dcaf5a
d85016 ¤   $Id: pgpGroups.c,v 1.12.10.1 1998/11/12 03:23:07 heller Exp $
8cf7f7 ____________________________________________________________________________*/
02af5a
8a324c #include <string.h>
71af5a
bec26c #include "pgpContext.h"
202f8d #include "pgpErrors.h"
66894b #include "pgpFileSpec.h"
caa076 #include "pgpKeys.h"
d30d08 #include "pgpMem.h"
713427 #include "pgpFileUtilities.h"
bb3d4b #include "pgpEndianConversion.h"
8ba4b2 #include "pgpFileRef.h"
c2af5a
3ec2ae #include "pgpGroups.h"
8d47c7 #include "pgpGroupsPriv.h"
ee1b42 #include "pgpStrings.h"
12fbe2 #include "pgpMemoryIO.h"
9faf5a
330ccc #if PGP_MACINTOSH
b4af5a
07eef1 #include <NumberFormatting.h>
a285c2 #include "MacStrings.h"
dcaf5a
6f2a4c /* because we include sort code twice */
b832db #pragma once off
a27454 #endif
e1af5a
bc0335 /*____________________________________________________________________________
417cc3 ¤   Notes:
0367c5 ¤
220716 ¤   All data structures are in-memory representations. ·On disk storage is
265ede ¤   completely different, including ommitting fields, changing the
83108e ¤   endian-ness, etc.
e967c5 ¤
cf24a0 ¤   Data structure explanation:
f867c5 ¤
31cfa6 ¤   A "group set" is a data structure which contains groups and all the stuff
f33e0f ¤   they reference. ·A group belongs to one and only one set, and whenever
c5c3e9 ¤   an operation is performed, the set is required. ·Groups are only
3e5f62 ¤   referred to by a PGPGroupID and thus can freely be rearranged internally.
d667c5 ¤
7f9200 ¤   A "group" contains other groups and/or a key ids, in no particular order.
e123a4 ¤   Each group has an ID, which is unique to the PGPGroupSet which contains
348497 ¤   it. ·The key ids are exported key data from the PGPsdk and the data
d10c83 ¤   is never interpreted, only stored.
9d67c5 ¤
c7fc3c ¤   These data structures are implemented using arrays. A few notes on this:
9467c5 ¤
47ecdc ¤   1. the goal was rapid, bug-free implementation. ·An assumption was made
5743cd ¤   that creating large numbers of groups would occur via user-interface
db8122 ¤   interaction and that the speed of adding them was not important. In fact,
93cb4b ¤   adding n groups is an O( n^2 ) operation. ·This sounds bad, but in
92a17c ¤   practice is irrelevant. ·The same holds true for items within a group.
8befb9 ¤   So DO NOT change the simple implementation unless there is a proven
d97ad5 ¤   reason that speed is a problem in the UI.
0e67c5 ¤
77350d ¤   2. Reading groups in and writing them out is O( n ). ·It can't get any
559ee1 ¤   faster in the big O sense.
4667c5 ¤
499706 ¤   3. PGPGroupIDs are used heavily. ·This is perhaps one relevant place
a67f35 ¤   to optimize, but again, this shouldn't be done unless there is a
a242b1 ¤   proven issue. ·Currently, a linear search is used; a binary search
2692f9 ¤   could be used, but the reality is that even with a few thousand
--f150 000a6a8462740100251 Page 2 of pgpGroups.c
de0994 ¤   groups (highly unlikely), the speed would probably still be
0bfeff ¤   reasonable. ·The correct way to optimize would be to keep the groups
c2d5d6 ¤   sorted by group ID and them implement a binary search.
abf7f7 ____________________________________________________________________________*/
d2af5a
2d6e16 typedef struct PGPExportedGroupItem
89bb36 {
21bcdf ¤   PGPGroupItemType¤   type;
d067c5 ¤
4df20a ¤   union
3cc7a1 ¤   {
084498 ¤   ¤   /* type selects which substructure */
35bbfc ¤   ¤   struct¤ /* if kGroupItem_Group */
de5b34 ¤   ¤   {
855f4a ¤   ¤   ¤   PGPGroupID¤ id;¤¤   ¤   ¤
26cc5b ¤   ¤   } group;
9f1b52 ¤   ¤
9dde44 ¤   ¤   struct¤ /* if kGroupItem_KeyID */
b05b34 ¤   ¤   {
e58e22 ¤   ¤   ¤   /* exported key IDs currently take 1 + 8 bytes */
a82ac5 ¤   ¤   ¤   PGPUInt32¤  algorithm;
acef15 ¤   ¤   ¤   PGPByte¤¤   length;¤¤   /* actual size of data */
08635b ¤   ¤   ¤   PGPByte¤¤   exportedKeyID[ 8 + 1 ];
b3e81b ¤   ¤   } key;
8bfef9 ¤   } u;
7467c5 ¤
257618 } PGPExportedGroupItem;
5eaf5a
45b360 typedef struct PGPGroup
edbb36 {
a545bb ¤   PGPGroupID¤ ¤   ¤   id;
90f138 ¤   PGPGroupName¤   ¤   name;
d8846b ¤   PGPGroupDescription¤description;
0267c5 ¤
ecfef9 ¤   /* array of group IDs */
0c4c59 ¤   PGPUInt32¤  ¤   ¤   numItems;
15bf82 ¤   PGPGroupItem *¤ ¤   itemsArray;
cf67c5 ¤
984208 ¤   /* these items are not stored to disk: */
9c3904 ¤   PGPGroupSetRef¤ ¤   set;
bf4e6a ¤   PGPUserValue¤   ¤   userValue;
40fcf0 } PGPGroup;
22af5a
26af5a
9dbafc #define kPGPGroupSetMagic¤  0x47524F55¤ /* 'GROU */
abfebb struct PGPGroupSet
5bbb36 {
f69d0d ¤   PGPUInt32¤  ¤   magic;
38e169 ¤   PGPUInt32¤  ¤   version;
843700 ¤   PGPUInt32¤  ¤   nextAvailGroupID;
1067c5 ¤
8657d8 ¤   char¤   ¤   ¤   pad[ 128 ];
1467c5 ¤
0ba770 ¤   /* groupArray is sorted by ascending group ID */
29ce4e ¤   PGPUInt32¤  ¤   numGroups;
fd8156 ¤   PGPGroup *¤ ¤   groupArray;
0667c5 ¤
638a97 ¤   PGPContextRef¤  context;
c57ecf ¤   PGPUInt32¤  ¤   lastAccessIndex;
733ce0 ¤   PGPBoolean¤ ¤   hasBeenModified;
7367c5 ¤
1d82f7 };
f0ebcf typedef struct PGPGroupSet¤ PGPGroupSet;
2aaf5a
56af5a
2f67c5 ¤
a016ea ¤   PGPBoolean
2a6fb1 PGPGroupSetIsValid( PGPGroupSetRef set )
40bb36 {
070509 ¤   PGPBoolean¤ isValid;
4367c5 ¤
a6cd6c ¤   isValid¤= IsntNull( set ) &&
--a473 000a1f06f5040100251 Page 3 of pgpGroups.c
6cf908 ¤   ¤   ¤   ¤   set->magic == kPGPGroupSetMagic;
c967c5 ¤
a7195c ¤   return( isValid );
5defe6 }
40af5a
bbaf5a
338a4c static PGPError¤sSortGroups( PGPGroupSetRef set );
7baf5a
bbaf5a
e7fe5f typedef PGPUInt16¤  CRC16;
20af5a
74cbbc ¤   static PGPUInt16
580284 sCalcCRC16Continue(
4bd2f4 ¤   PGPUInt16¤  ¤   startValue,
47f9ae ¤   const void *¤   data,
2d4b0e ¤   PGPInt32¤   ¤   len)
f8bb36 {
4ac943 ¤   const char *¤   dp¤ = (const char *)data;
a69834 ¤   PGPUInt16¤  ¤   crc¤= startValue;
fe67c5 ¤
14a8c5 ¤   while(len--)
dcc7a1 ¤   {
1d6edc ¤   ¤   PGPInt16¤   ¤   i;
ae67c5 ¤
226ee5 ¤   ¤   crc ^= (PGPUInt16)(*dp++) << 8;
4dfad8 ¤   ¤   for (i = 0; i < 8; ++i)
2b5b34 ¤   ¤   {
5b983e ¤   ¤   ¤   if (crc & 0x8000)
03bdd1 ¤   ¤   ¤   ¤   crc = (crc << 1) ^ 0x1021;
ccbb8c ¤   ¤   ¤   else
841a72 ¤   ¤   ¤   ¤   crc <<= 1;
070fe4 ¤   ¤   }
a09371 ¤   }
91001d ¤   return(crc);
66efe6 }
2faf5a
67af5a
669bea #define sChecksumBytes( checksum, bytes, numBytes ) \
23ee3d ¤   ¤   ¤   sCalcCRC16Continue( checksum, bytes, numBytes )
d9af5a
04687e ¤   static CRC16
e47daa sChecksumUInt32(
bd6e95 ¤   CRC16¤  checksum,
6a5fbb ¤   PGPUInt32¤  ¤   number )
1ebb36 {
ee021a ¤   PGPByte¤storage[ sizeof( PGPUInt32 ) ];
4167c5 ¤
618fc5 ¤   PGPUInt32ToStorage( number, storage );
e57700 ¤   checksum¤   = sChecksumBytes( checksum, storage, sizeof( PGPUInt32 ) );
5ec0bc ¤   return( checksum );
0befe6 }
1caf5a
deaf5a
74687e ¤   static CRC16
ba0e8f sComputeGroupChecksum( PGPGroup const * group)
62bb36 {
fbfd8e ¤   CRC16¤  ¤   checksum¤   = 0;
0667c5 ¤
e0cba9 ¤   /* these assumptions are made when writing out the data */
aa530d ¤   pgpAssert( sizeof( group->id ) == sizeof( PGPUInt32 ) &&
28f1fe ¤   ¤   sizeof( group->numItems ) == sizeof( PGPUInt32 ) );
8f1b52 ¤   ¤
56644d ¤   checksum¤   = sChecksumUInt32( checksum, (PGPUInt32)group->id );
ea67c5 ¤
9aa034 ¤   checksum¤   = sChecksumBytes( checksum,
96cf6a ¤   ¤   ¤   ¤   ¤   group->name, sizeof( group->name ) );
1aae30 ¤   ¤   ¤   ¤   ¤
2ba034 ¤   checksum¤   = sChecksumBytes( checksum,
e5407e ¤   ¤   ¤   ¤   ¤   group->description, sizeof( group->description ));
57ae30 ¤   ¤   ¤   ¤   ¤
48214e ¤   checksum¤   = sChecksumUInt32( checksum, group->numItems );
a167c5 ¤
--164e 000777ebc0540100251 Page 4 of pgpGroups.c
b9c0bc ¤   return( checksum );
edefe6 }
bcaf5a
c5687e ¤   static CRC16
f38bff sComputeGroupSetChecksum( PGPGroupSet const * set)
2bbb36 {
57fd8e ¤   CRC16¤  ¤   checksum¤   = 0;
9167c5 ¤
e6cba9 ¤   /* these assumptions are made when writing out the data */
7e0e8d ¤   pgpAssert( sizeof( set->magic ) == sizeof( PGPUInt32 ) &&
d4d28f ¤   ¤   sizeof( set->version ) == sizeof( PGPUInt32 ) &&
4114f3 ¤   ¤   sizeof( set->nextAvailGroupID ) == sizeof( PGPUInt32 ) &&
a25590 ¤   ¤   sizeof( set->numGroups ) == sizeof( PGPUInt32 ) );
531b52 ¤   ¤
8e6e7d ¤   checksum¤   = sChecksumUInt32( checksum, set->magic );
248c69 ¤   checksum¤   = sChecksumUInt32( checksum, set->version );
370461 ¤   checksum¤   = sChecksumUInt32( checksum, set->nextAvailGroupID );
12c339 ¤   checksum¤   = sChecksumUInt32( checksum, set->numGroups );
5367c5 ¤
85c0bc ¤   return( checksum );
c1efe6 }
0aaf5a
11af5a
b1687e ¤   static CRC16
f7bc04 sComputeExportedGroupItemChecksum( PGPExportedGroupItem const * item)
5ebb36 {
f0fd8e ¤   CRC16¤  ¤   checksum¤   = 0;
e167c5 ¤
88cba9 ¤   /* these assumptions are made when writing out the data */
2b43c1 ¤   pgpAssert( sizeof( item->type ) == sizeof( PGPUInt32 ) &&
7fb588 ¤   ¤   sizeof( item->u.group.id ) == sizeof( PGPUInt32 ) &&
3e433c ¤   ¤   sizeof( item->u.key.algorithm ) == sizeof( PGPUInt32 ) &&
69ccfd ¤   ¤   sizeof( item->u.key.length ) == 1 );
681b52 ¤   ¤
646289 ¤   checksum¤   = sChecksumUInt32( checksum, item->type );
6f37b1 ¤   if ( item->type == kPGPGroupItem_Group )
b6c7a1 ¤   {
6bac34 ¤   ¤   checksum¤   = sChecksumUInt32( checksum, item->u.group.id );
ab9371 ¤   }
644656 ¤   else if ( item->type == kPGPGroupItem_KeyID )
5cc7a1 ¤   {
e22498 ¤   ¤   checksum¤   = sChecksumUInt32( checksum, item->u.key.algorithm );
e56130 ¤   ¤   checksum¤   = sChecksumBytes( checksum, &item->u.key.length, 1 );
e6b864 ¤   ¤   checksum¤   = sChecksumBytes( checksum,
ccb1d7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->u.key.exportedKeyID,
da4630 ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->u.key.length );
429371 ¤   }
a767c5 ¤
bdc0bc ¤   return( checksum );
75efe6 }
13af5a
45af5a
38af5a
7aaf5a
3666dd ¤   static PGPError
04a043 sReadUInt32FromIO(
04ee9c ¤   PGPIORef¤   io,
cc523f ¤   PGPUInt32 *¤number)
d5bb36 {
611a0d ¤   PGPByte¤¤   endianBuf[ sizeof( PGPUInt32 ) ];
c361e0 ¤   PGPError¤   err;
1d67c5 ¤
a9247a ¤   err¤= PGPIORead( io, sizeof( endianBuf ), endianBuf, NULL );
9967c5 ¤
0fa652 ¤   *number¤= PGPStorageToUInt32( endianBuf );
a067c5 ¤
cedeb7 ¤   return( err );
79efe6 }
75af5a
21af5a
b866dd ¤   static PGPError
77c7e8 sReadUInt16FromIO(
--681e 000b03956b240100251 Page 5 of pgpGroups.c
6fee9c ¤   PGPIORef¤   io,
465c13 ¤   PGPUInt16 *¤number)
17bb36 {
b47e14 ¤   PGPByte¤¤   endianBuf[ sizeof( PGPUInt16 ) ];
3061e0 ¤   PGPError¤   err;
8567c5 ¤
d4247a ¤   err¤= PGPIORead( io, sizeof( endianBuf ), endianBuf, NULL );
7f67c5 ¤
f4ae2e ¤   *number¤= PGPStorageToUInt16( endianBuf );
fd67c5 ¤
56deb7 ¤   return( err );
1befe6 }
d7af5a
7066dd ¤   static PGPError
159d7c sWriteUInt32ToIO(
8e2a9c ¤   PGPUInt32¤  number,
445da9 ¤   PGPIORef¤   io )
cdbb36 {
c81a0d ¤   PGPByte¤¤   endianBuf[ sizeof( PGPUInt32 ) ];
4c67c5 ¤
b2fa4c ¤   PGPUInt32ToStorage( number, endianBuf );
8ddb40 ¤   return( PGPIOWrite( io, sizeof( endianBuf ), endianBuf ) );
94efe6 }
8daf5a
24af5a
4566dd ¤   static PGPError
56f965 sWriteUInt16ToIO(
3324b0 ¤   PGPUInt16¤  number,
925da9 ¤   PGPIORef¤   io )
c9bb36 {
f07e14 ¤   PGPByte¤¤   endianBuf[ sizeof( PGPUInt16 ) ];
2867c5 ¤
71506b ¤   PGPUInt16ToStorage( number, endianBuf );
f8db40 ¤   return( PGPIOWrite( io, sizeof( endianBuf ), endianBuf ) );
3fefe6 }
14af5a
86af5a
f2af5a
24bf5b #define sWriteChecksumToIO( checksum, io ) \
6c8dd4 ¤   sWriteUInt16ToIO( checksum, io )
3aaf5a
7d66dd ¤   static PGPError
30f3db sVerifyChecksumFromIO(
d96e95 ¤   CRC16¤  checksum,
bf36bc ¤   PGPIORef¤   ¤   io )
dabb36 {
72dbc5 ¤   CRC16¤  ioChecksum;
dd9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
3e1b52 ¤   ¤
ef43d2 ¤   err¤= sReadUInt16FromIO( io, &ioChecksum );
6d2710 ¤   if ( IsntPGPError( err ) && checksum != ioChecksum )
e6c7a1 ¤   {
96d24a ¤   ¤   err¤= kPGPError_CorruptData;
6a9371 ¤   }
28deb7 ¤   return( err );
8fefe6 }
7daf5a
a3af5a
e933c8 ¤   static void
35fb42 sInitGroup(
e3a976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
b04232 ¤   PGPGroupID¤ ¤   ¤   ¤   id,
d24d49 ¤   const char *¤   ¤   ¤   name,
31f678 ¤   const char *¤   ¤   ¤   description,
f04899 ¤   PGPGroup *¤ ¤   ¤   ¤   group)
15bb36 {
bb4bab ¤   pgpClearMemory( group, sizeof( *group ) );
10e405 ¤   group->id¤  ¤   ¤   = id;
83c0e4 ¤   group->itemsArray¤  = NULL;
da76f1 ¤   group->numItems¤¤   = 0;
0632af ¤   group->set¤ ¤   ¤   = set;
b0f71f ¤   if ( IsntNull( name ) )
--6b68 0001cdda9ad40100251 Page 6 of pgpGroups.c
f7c7a1 ¤   {
460675 ¤   ¤   strcpy( group->name, name );
889371 ¤   }
663866 ¤   if ( IsntNull( description ) )
25c7a1 ¤   {
3c4d54 ¤   ¤   strcpy( group->description, description );
849371 ¤   }
ebefe6 }
95af5a
7aaf5a
bd33c8 ¤   static void
861309 sDestroyGroup(
dc4899 ¤   PGPGroup *¤ ¤   ¤   ¤   group)
edbb36 {
086299 ¤   if ( IsntNull( group->itemsArray ) )
d5c7a1 ¤   {
7318f8 ¤   ¤   pgpAssert( IsntNull( group->set ) );
b4dbf0 ¤   ¤   pgpContextMemFree( group->set->context, group->itemsArray );
814b18 ¤   ¤   group->itemsArray¤  = NULL;
5f9371 ¤   }
9defe6 }
42af5a
caaf5a
7866dd ¤   static PGPError
947adb sNewGroupSet(
249a06 ¤   PGPContextRef¤  ¤   ¤   context,
85861c ¤   PGPGroupSetRef *¤   ¤   outSet )
1fbb36 {
719372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
600291 ¤   PGPGroupSet *¤  set¤= NULL;
a367c5 ¤
ff010e ¤   set¤= (PGPGroupSet *)pgpContextMemAlloc( context,
23d884 ¤   ¤   ¤   sizeof( *set ), kPGPMemoryMgrFlags_Clear );
eb3f60 ¤   if ( IsntNull( set ) )
a8c7a1 ¤   {
690b0f ¤   ¤   set->magic¤ ¤   ¤   ¤   = kPGPGroupSetMagic;
33e905 ¤   ¤   set->context¤   ¤   ¤   = context;
d0df33 ¤   ¤   set->nextAvailGroupID¤  = ((PGPUInt32)kPGPInvalidGroupID) + 1;
f1d6aa ¤   ¤   set->groupArray¤¤   ¤   = NULL;
a75a38 ¤   ¤   set->numGroups¤ ¤   ¤   = 0;
e670d0 ¤   ¤   set->hasBeenModified¤   = TRUE;
f09371 ¤   }
8a0e24 ¤   else
99c7a1 ¤   {
ac17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
279371 ¤   }
0967c5 ¤
41e14f ¤   *outSet¤= set;
97deb7 ¤   return( err );
a3efe6 }
82af5a
30af5a
4f6c2c ¤   static PGPBoolean
02a272 sSearchForID(
6feb08 ¤   PGPGroup const *¤   firstGroup,
cdb4e2 ¤   PGPGroup const *¤   lastGroup,
549d22 ¤   PGPGroupID¤ ¤   ¤   id,
9b4406 ¤   PGPUInt32 *¤¤   ¤   outIndex )
babb36 {
9328b6 ¤   PGPGroup const *¤   curGroup;
824953 ¤   PGPBoolean¤ ¤   ¤   foundIt¤= FALSE;
1567c5 ¤
e24d96 ¤   /* we could use a sentinel value, but if we're that concerned about
63daec ¤   speed we should implement a binary search */
0f4b01 ¤   curGroup¤   = firstGroup;
a881d9 ¤   while ( curGroup <= lastGroup )
18c7a1 ¤   {
14e26a ¤   ¤   if ( curGroup->id == id )
975b34 ¤   ¤   {
4c66f7 ¤   ¤   ¤   foundIt¤= TRUE;
bb9bf9 ¤   ¤   ¤   *outIndex¤  = curGroup - firstGroup;
1ccdcb ¤   ¤   ¤   break;
--964b 0005bc1634f40100251 Page 7 of pgpGroups.c
b50fe4 ¤   ¤   }
b75219 ¤   ¤   ++curGroup;
569371 ¤   }
0867c5 ¤
6a71b7 ¤   return( foundIt );
7fefe6 }
beaf5a
6a0335 /*____________________________________________________________________________
ac26dc ¤   Maybe to be implemented later as a binary search. ·But that requires
611628 ¤   making sure all the items are sorted and is probably not worth it.
ef67c5 ¤
47eae7 ¤   The algorithm here works well for sequential, forward access.
b1f7f7 ____________________________________________________________________________*/
3466dd ¤   static PGPError
b6d351 sGetGroupIndexByID(
f230d0 ¤   PGPGroupSetRef¤ set,
4e1ced ¤   PGPGroupID¤ ¤   id,
540f88 ¤   PGPUInt32 *¤¤   outIndex )
46bb36 {
025520 ¤   PGPError¤   err¤= kPGPError_ItemNotFound;
643391 ¤   PGPGroup const *¤   firstGroup;
a06c7b ¤   PGPGroup const *¤   lastGroup;
5628b6 ¤   PGPGroup const *¤   curGroup;
df4953 ¤   PGPBoolean¤ ¤   ¤   foundIt¤= FALSE;
5fc722 ¤   PGPUInt32¤  ¤   ¤   foundIndex¤ = 0;
4e67c5 ¤
4272e0 ¤   *outIndex¤  = 0;
d2e7dd ¤   if ( set->numGroups == 0 )
c6aad2 ¤   ¤   return( kPGPError_ItemNotFound );
f2af5a
f89928 ¤   firstGroup¤ = &set->groupArray[ 0 ];
c6422d ¤   lastGroup¤  = firstGroup + (set->numGroups - 1 );
c067c5 ¤
e1110b ¤   if ( set->lastAccessIndex < set->numGroups )
26c7a1 ¤   {
632ef2 ¤   ¤   /* search from last access forward */
34803c ¤   ¤   curGroup¤   = &set->groupArray[ set->lastAccessIndex ];
b80538 ¤   ¤   if ( sSearchForID( curGroup, lastGroup, id, &foundIndex ) )
175b34 ¤   ¤   {
de6b30 ¤   ¤   ¤   foundIt¤¤   = TRUE;
b1d3f7 ¤   ¤   ¤   foundIndex¤ += set->lastAccessIndex;
740fe4 ¤   ¤   }
1d1b52 ¤   ¤
4d2214 ¤   ¤   /* search items preceeding last access */
22426f ¤   ¤   if ( ( ! foundIt ) && set->lastAccessIndex != 0 )
9a5b34 ¤   ¤   {
30bbf1 ¤   ¤   ¤   foundIt¤= sSearchForID( firstGroup,
5ff013 ¤   ¤   ¤   ¤   ¤   ¤   curGroup - 1, id, &foundIndex );
cf0fe4 ¤   ¤   }
a09371 ¤   }
370e24 ¤   else
fec7a1 ¤   {
6267ba ¤   ¤   /* search entire array from beginning */
4ac3e6 ¤   ¤   foundIt¤= sSearchForID( firstGroup, lastGroup, id, &foundIndex );
8e9371 ¤   }
9667c5 ¤
efb363 ¤   if ( foundIt)
ddc7a1 ¤   {
3bb395 ¤   ¤   *outIndex¤  = foundIndex;
7980dc ¤   ¤   set->lastAccessIndex¤   = foundIndex;
06d87c ¤   ¤   err¤= kPGPError_NoErr;
f29371 ¤   }
f60e24 ¤   else
b2c7a1 ¤   {
5a0886 ¤   ¤   err¤= kPGPError_ItemNotFound;
599371 ¤   }
59af5a
a7deb7 ¤   return( err );
66efe6 }
17af5a
1faf5a
5baf5a
--7872 000e2a1a82440100251 Page 8 of pgpGroups.c
a70335 /*____________________________________________________________________________
e42750 ¤   to be implemented later as a binary search
53f7f7 ____________________________________________________________________________*/
2f66dd ¤   static PGPError
0a3810 sFindGroupByID(
8c30d0 ¤   PGPGroupSetRef¤ set,
061ced ¤   PGPGroupID¤ ¤   id,
7d389f ¤   PGPGroup **¤¤   outGroup )
67bb36 {
1626d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
cfc7f9 ¤   PGPUInt32¤  index;
d367c5 ¤
9c7865 ¤   err¤= sGetGroupIndexByID( set, id, &index );
85f1e7 ¤   if ( IsntPGPError( err ) )
6cc7a1 ¤   {
d9fcc6 ¤   ¤   *outGroup¤  = &set->groupArray[ index ];
669371 ¤   }
a2af5a
cbdeb7 ¤   return( err );
b1efe6 }
abaf5a
63af5a
24af5a
d6af5a
39d8f8 ¤   PGPContextRef
463018 PGPGetGroupSetContext( PGPGroupSetRef set )
b8bb36 {
de987e ¤   pgpAssert( PGPGroupSetIsValid( set ) );
65a50e ¤   if ( ! PGPGroupSetIsValid( set ) )
dcef86 ¤   ¤   return( NULL );
e1d857 ¤   return( set->context );
1cefe6 }
e7af5a
21af5a
0eaf5a
fa0335 /*____________________________________________________________________________
572486 ¤   create a new, empty groups collection
0cf7f7 ____________________________________________________________________________*/
83c744 ¤   PGPError
1700a5 PGPNewGroupSet(
b1a1bc ¤   PGPContextRef¤  ¤   context,
786a5d ¤   PGPGroupSetRef *¤   outRef )
14bb36 {
0526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3767c5 ¤
fa3c76 ¤   PGPValidatePtr( outRef );
3e3652 ¤   *outRef¤= NULL;
b0f3ca ¤   PGPValidateContext( context );
e267c5 ¤
2c07a3 ¤   err¤= sNewGroupSet( context, outRef );
6167c5 ¤
e2deb7 ¤   return( err );
b0efe6 }
10af5a
abaf5a
04c744 ¤   PGPError
286ed0 PGPCountGroupsInSet(
5630d0 ¤   PGPGroupSetRef¤ set,
3af850 ¤   PGPUInt32 *¤¤   ¤   numGroups)
3bbb36 {
7b26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9867c5 ¤
076db8 ¤   PGPValidatePtr( numGroups );
3dfee5 ¤   *numGroups¤ = 0;
31b620 ¤   PGPValidateGroupSet( set );
7667c5 ¤
4e2b1b ¤   *numGroups¤ = set->numGroups;
3267c5 ¤
cfdeb7 ¤   return( err );
beefe6 }
19af5a
e2af5a
--5531 000a1927f4340100251 Page 9 of pgpGroups.c
d3c744 ¤   PGPError
4504e0 PGPGetIndGroupID(
4830d0 ¤   PGPGroupSetRef¤ set,
9f1959 ¤   PGPUInt32¤  ¤   ¤   index,
eeb0cf ¤   PGPGroupID *¤   ¤   id)
2abb36 {
d326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a367c5 ¤
67775f ¤   PGPValidatePtr( id );
e39b63 ¤   *id¤= kPGPInvalidGroupID;
8cb620 ¤   PGPValidateGroupSet( set );
001a6b ¤   PGPValidateParam( index < set->numGroups );
3567c5 ¤
9a09b4 ¤   *id¤= set->groupArray[ index ].id;
6667c5 ¤
00deb7 ¤   return( err );
0eefe6 }
40af5a
51af5a
70af5a
6caf5a
93af5a
5faf5a
7aaf5a
e6af5a
05af5a
6b66dd ¤   static PGPError
d99ce4 sReadGroupSetHeaderFromIO(
ecbd74 ¤   PGPIORef¤   ¤   io,
aeb822 ¤   PGPGroupSet *¤  set )
7bbb36 {
ae26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d067c5 ¤
5fcd60 ¤   err¤= sReadUInt32FromIO( io, &set->magic);
f1f1e7 ¤   if ( IsntPGPError( err ) )
e8c7a1 ¤   {
e7c217 ¤   ¤   if ( set->magic != kPGPGroupSetMagic )
e8fdcd ¤   ¤   ¤   err¤= kPGPError_BadParams;
5c0e1d ¤   ¤   else
946d99 ¤   ¤   ¤   err¤= sReadUInt32FromIO( io, &set->numGroups );
cd9371 ¤   }
9af1e7 ¤   if ( IsntPGPError( err ) )
f2c7a1 ¤   {
2033bb ¤   ¤   err¤= sReadUInt32FromIO( io, &set->version );
079371 ¤   }
81f1e7 ¤   if ( IsntPGPError( err ) )
71c7a1 ¤   {
22d563 ¤   ¤   err¤= sReadUInt32FromIO( io, &set->nextAvailGroupID );
959371 ¤   }
d9f1e7 ¤   if ( IsntPGPError( err ) )
18c7a1 ¤   {
755847 ¤   ¤   err¤= PGPIORead( io, sizeof( set->pad ), set->pad, NULL );
8b9371 ¤   }
0067c5 ¤
ecf1e7 ¤   if ( IsntPGPError( err ) )
a6c7a1 ¤   {
40604d ¤   ¤   err¤= sVerifyChecksumFromIO( sComputeGroupSetChecksum( set ), io );
bd9371 ¤   }
d767c5 ¤
0cdeb7 ¤   return( err );
44efe6 }
ccaf5a
b5af5a
c7af5a
af66dd ¤   static PGPError
8faa82 sReadGroupItemFromIO(
7a80a1 ¤   PGPIORef¤   ¤   ¤   io,
438905 ¤   PGPGroupItem *¤ ¤   item )
54bb36 {
369479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
4230a8 ¤   PGPUInt32¤  ¤   ¤   ¤   temp;
a17706 ¤   PGPExportedGroupItem¤   exportedItem;
--0cd6 000905648b740100251 Page 10 of pgpGroups.c
2a67c5 ¤
478108 ¤   err¤= sReadUInt32FromIO( io, &temp );
abf1e7 ¤   if ( IsntPGPError( err ) )
1bc7a1 ¤   {
219e3e ¤   ¤   exportedItem.type = (PGPGroupItemType)temp;
001b52 ¤   ¤
d3d16b ¤   ¤   if ( exportedItem.type == kPGPGroupItem_Group )
b05b34 ¤   ¤   {
23f7f3 ¤   ¤   ¤   err¤= sReadUInt32FromIO( io, &temp );
1bfaa1 ¤   ¤   ¤   exportedItem.u.group.id¤= (PGPGroupID)temp;
5f8554 ¤   ¤   ¤   pgpAssert( exportedItem.u.group.id != kPGPInvalidGroupID );
e10fe4 ¤   ¤   }
2d6c13 ¤   ¤   else if ( exportedItem.type == kPGPGroupItem_KeyID )
755b34 ¤   ¤   {
3c2c45 ¤   ¤   ¤   err¤= sReadUInt32FromIO( io, &exportedItem.u.key.algorithm );
4c3c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
ec479d ¤   ¤   ¤   ¤   err¤= PGPIORead( io, 1, &exportedItem.u.key.length, NULL);
393c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
29f776 ¤   ¤   ¤   {
636e29 ¤   ¤   ¤   ¤   err¤= PGPIORead( io,
1d4c9a ¤   ¤   ¤   ¤   ¤   exportedItem.u.key.length,
3aedba ¤   ¤   ¤   ¤   ¤   exportedItem.u.key.exportedKeyID, NULL);
15a3a6 ¤   ¤   ¤   }
500fe4 ¤   ¤   }
389371 ¤   }
d067c5 ¤
58f1e7 ¤   if ( IsntPGPError( err ) )
1bc7a1 ¤   {
fa7481 ¤   ¤   err¤= sVerifyChecksumFromIO( sComputeExportedGroupItemChecksum(
86aae4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &exportedItem ), io );
5586f8 ¤   ¤   if( IsntPGPError( err ) )
565b34 ¤   ¤   {
8e961e ¤   ¤   ¤   item->type = exportedItem.type;
bc87c7 ¤   ¤   ¤
f91efa ¤   ¤   ¤   if( exportedItem.type == kPGPGroupItem_Group )
a2f776 ¤   ¤   ¤   {
ecce7f ¤   ¤   ¤   ¤   item->u.group.id = exportedItem.u.group.id;
9fa3a6 ¤   ¤   ¤   }
99bec9 ¤   ¤   ¤   else if( exportedItem.type == kPGPGroupItem_KeyID )
81f776 ¤   ¤   ¤   {
8120f5 ¤   ¤   ¤   ¤   item->u.key.algorithm =·
37efc1 ¤   ¤   ¤   ¤   ¤   ¤   (PGPPublicKeyAlgorithm) exportedItem.u.key.algorithm;
bc94aa ¤   ¤   ¤   ¤   ¤   ¤
9ab429 ¤   ¤   ¤   ¤   err = PGPImportKeyID( exportedItem.u.key.exportedKeyID,
c94398 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &item->u.key.keyID );
79a3a6 ¤   ¤   ¤   }
d40fe4 ¤   ¤   }
939371 ¤   }
8a67c5 ¤
24deb7 ¤   return( err );
f4efe6 }
ffaf5a
9daf5a
bf66dd ¤   static PGPError
628d9a sReadGroupFromIO(
8d520e ¤   PGPContextRef¤  context,
79bd74 ¤   PGPIORef¤   ¤   io,
648db5 ¤   PGPGroup *¤ ¤   group )
5ebb36 {
549372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
04e939 ¤   PGPUInt32¤  ¤   index;
357ec8 ¤   PGPUInt32¤  ¤   temp;
6667c5 ¤
538108 ¤   err¤= sReadUInt32FromIO( io, &temp );
01f1e7 ¤   if ( IsntPGPError( err ) )
e0c7a1 ¤   {
d7b1d6 ¤   ¤   group->id¤  = (PGPGroupID)temp;
b197ae ¤   ¤   err¤= PGPIORead( io, sizeof( group->name ), group->name, NULL);
0c9371 ¤   }
e1f1e7 ¤   if ( IsntPGPError( err ) )
2cc7a1 ¤   {
90e817 ¤   ¤   err¤= PGPIORead( io,
--15cf 00069902c2b40100251 Page 11 of pgpGroups.c
60b6d7 ¤   ¤   ¤   ¤   sizeof( group->description ), group->description, NULL);
729371 ¤   }
25f1e7 ¤   if ( IsntPGPError( err ) )
fcc7a1 ¤   {
2c77e8 ¤   ¤   err¤= sReadUInt32FromIO( io, &group->numItems);
509371 ¤   }
5867c5 ¤
08f1e7 ¤   if ( IsntPGPError( err ) )
b3c7a1 ¤   {
54cf6a ¤   ¤   err¤= sVerifyChecksumFromIO( sComputeGroupChecksum( group ), io );
069371 ¤   }
1367c5 ¤
4cf1e7 ¤   if ( IsntPGPError( err ) )
04c7a1 ¤   {
098285 ¤   ¤   if ( group->numItems != 0 )
335b34 ¤   ¤   {
ab529a ¤   ¤   ¤   group->itemsArray¤  = (PGPGroupItem *)pgpContextMemAlloc( context,
a010d5 ¤   ¤   ¤   ¤   ¤   ( group->numItems * sizeof(group->itemsArray[ 0 ]) ),
6052b1 ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
bfa3fc ¤   ¤   ¤   if ( IsNull( group->itemsArray ) )
08f776 ¤   ¤   ¤   {
0114f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
daa3a6 ¤   ¤   ¤   }
250fe4 ¤   ¤   }
281b52 ¤   ¤
a07d98 ¤   ¤   if ( IsntPGPError( err ) )
c45b34 ¤   ¤   {
371f1d ¤   ¤   ¤   /* now read all the items in */
7deb08 ¤   ¤   ¤   for ( index = 0; index < group->numItems; ++index )
58f776 ¤   ¤   ¤   {
30abf4 ¤   ¤   ¤   ¤   err¤= sReadGroupItemFromIO( io, &group->itemsArray[ index ] );
6c869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
dd14c3 ¤   ¤   ¤   ¤   ¤   break;
51a3a6 ¤   ¤   ¤   }
590fe4 ¤   ¤   }
1d9371 ¤   }
0367c5 ¤
ba8c1a ¤   pgpAssertNoErr( err );
c5deb7 ¤   return( err );
5fefe6 }
b9af5a
78af5a
8daf5a
df66dd ¤   static PGPError
b712e8 sReadGroupSetFromIO(
5cbd74 ¤   PGPIORef¤   ¤   io,
9cd51f ¤   PGPGroupSetRef¤ set )
e9bb36 {
ac9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0967c5 ¤
efc292 ¤   err¤= sReadGroupSetHeaderFromIO( io, set );
5fac23 ¤   if ( IsntPGPError( err ) ·)
7fc7a1 ¤   {
732f27 ¤   ¤   PGPUInt32¤  groupIndex;
af1b52 ¤   ¤
d30112 ¤   ¤   /* allocate the groups */
be6ff1 ¤   ¤   if ( set->numGroups != 0 )
ac5b34 ¤   ¤   {
2b4ada ¤   ¤   ¤   set->groupArray¤= (PGPGroup *)pgpContextMemAlloc( set->context,
8d525a ¤   ¤   ¤   ¤   ¤   ( set->numGroups * sizeof( set->groupArray[ 0 ] ) ),
ee52b1 ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
61e49e ¤   ¤   ¤   if ( IsNull( set->groupArray ) )
8114f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
c60fe4 ¤   ¤   }
7d1b52 ¤   ¤
997d98 ¤   ¤   if ( IsntPGPError( err ) )
8f5b34 ¤   ¤   {
4fdf0d ¤   ¤   ¤   for( groupIndex = 0; groupIndex < set->numGroups; ++groupIndex )
ecf776 ¤   ¤   ¤   {
9a70bc ¤   ¤   ¤   ¤   PGPGroup *¤ group;
242b85 ¤   ¤   ¤   ¤
6919ca ¤   ¤   ¤   ¤   group¤  = &set->groupArray[ groupIndex ];
--6bd0 0007fffd31240100251 Page 12 of pgpGroups.c
b78c19 ¤   ¤   ¤   ¤   sInitGroup( set, kPGPInvalidGroupID, NULL, NULL, group );
0770b1 ¤   ¤   ¤   ¤   err¤¤   = sReadGroupFromIO( set->context, io, group );
e0869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
b814c3 ¤   ¤   ¤   ¤   ¤   break;
4fa3a6 ¤   ¤   ¤   }
350fe4 ¤   ¤   }
769371 ¤   }
d667c5 ¤
c467c5 ¤
26deb7 ¤   return( err );
2defe6 }
08af5a
fcaf5a
7566dd ¤   static PGPError
5a1b32 sReadGroupSetFromFile(
43b830 ¤   PFLFileSpecRef¤ file,
77b822 ¤   PGPGroupSet *¤  set )
85bb36 {
3a9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
8e49b4 ¤   PGPFileIORef¤   io¤ = NULL;
b567c5 ¤
8cb620 ¤   PGPValidateGroupSet( set );
c72480 ¤   PFLValidateFileSpec( file );
274075 ¤   PGPValidateParam( set->hasBeenModified );
2567c5 ¤
3777dc ¤   /* open it, and write everything out */
20b6b0 ¤   err¤= PGPOpenFileSpec( file,
64ae84 ¤   ¤   ¤   kPFLFileOpenFlags_ReadOnly, &io );
26f1e7 ¤   if ( IsntPGPError( err ) )
cfc7a1 ¤   {
850049 ¤   ¤   err¤= sReadGroupSetFromIO( (PGPIORef)io, set);
fbd33c ¤   ¤   PGPFreeIO( (PGPIORef)io );
e31b52 ¤   ¤
48de1f ¤   ¤   /* we just read it in and there are no changes */
20e7be ¤   ¤   set->hasBeenModified¤   = FALSE;
719371 ¤   }
2c67c5 ¤
0edeb7 ¤   return( err );
b3efe6 }
c0af5a
77af5a
77af5a
a6af5a
10af5a
12c744 ¤   PGPError
ba754e PGPNewGroupSetFromFile(
f7a1bc ¤   PGPContextRef¤  ¤   context,
e0a1f7 ¤   PGPFileSpecRef¤ ¤   file,
4f94a1 ¤   PGPGroupSetRef *¤   outSet )
85bb36 {
ec9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
260291 ¤   PGPGroupSet *¤  set¤= NULL;
b5fabb ¤   PGPBoolean¤ ¤   exists¤ = FALSE;
2784bb ¤   PFLFileSpecRef¤ pflFile = (PFLFileSpecRef) file;
8d67c5 ¤
2b016b ¤   PGPValidatePtr( outSet );
24391b ¤   *outSet¤= NULL;
1ce84a ¤   PFLValidateFileSpec( pflFile );
e567c5 ¤
a00dfc ¤   err¤= PFLFileSpecExists( pflFile, &exists );
2b054e ¤   if ( IsPGPError( err ) )
81e55e ¤   ¤   return( err );
4c022d ¤   if ( ! exists )
a667b1 ¤   ¤   return( kPGPError_FileNotFound );
9c67c5 ¤
296fbd ¤   err¤= PGPNewGroupSet( context, &set );
43f1e7 ¤   if ( IsntPGPError( err ) )
1ac7a1 ¤   {
d97768 ¤   ¤   err¤= sReadGroupSetFromFile( pflFile, set );
d6d223 ¤   ¤   if( IsPGPError( err ) )
525b34 ¤   ¤   {
7f7f45 ¤   ¤   ¤   PGPFreeGroupSet( set );
--ed99 0000b79fbe040100251 Page 13 of pgpGroups.c
fabed2 ¤   ¤   ¤   set = kInvalidPGPGroupSetRef;
780fe4 ¤   ¤   }
bf9371 ¤   }
7567c5 ¤
e7e14f ¤   *outSet¤= set;
6cdeb7 ¤   return( err );
7befe6 }
54af5a
70af5a
340ccc #if PGP_MACINTOSH
baaf5a
ddc744 ¤   PGPError
f9e9ce PGPNewGroupSetFromFSSpec(
dfa1bc ¤   PGPContextRef¤  ¤   context,
f9f251 ¤   const FSSpec *¤ ¤   spec,
1994a1 ¤   PGPGroupSetRef *¤   outSet )
93bb36 {
d7fb19 ¤   PGPError¤   ¤   err;
de7606 ¤   PGPFileSpecRef¤ fileSpec;
fc67c5 ¤
92016b ¤   PGPValidatePtr( outSet );
68391b ¤   *outSet¤= NULL;
fbf3ca ¤   PGPValidateContext( context );
c97974 ¤   PGPValidatePtr( spec );
5767c5 ¤
8dbeac ¤   err¤= PGPNewFileSpecFromFSSpec( context, spec, &fileSpec );
bbf1e7 ¤   if ( IsntPGPError( err ) )
83c7a1 ¤   {
6fce90 ¤   ¤   err¤= PGPNewGroupSetFromFile( context, fileSpec, outSet );
840922 ¤   ¤   PGPFreeFileSpec( fileSpec );
4e9371 ¤   }
3c67c5 ¤
acdeb7 ¤   return( err );
09efe6 }
d7af5a
7d7454 #endif
78af5a
d9af5a
f6af5a
27af5a
da66dd ¤   static PGPError
76be6e sWriteGroupSetHeaderToIO(
8620b6 ¤   PGPGroupSet const *¤set,
4ab7a1 ¤   PGPIORef¤   ¤   ¤   io )
03bb36 {
609372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
e967c5 ¤
3acfcb ¤   err¤= sWriteUInt32ToIO( set->magic, io);
a2f1e7 ¤   if ( IsntPGPError( err ) )
9cc7a1 ¤   {
fffec9 ¤   ¤   err¤= sWriteUInt32ToIO( set->numGroups, io );
e49371 ¤   }
bbf1e7 ¤   if ( IsntPGPError( err ) )
bdc7a1 ¤   {
3e386d ¤   ¤   err¤= sWriteUInt32ToIO( set->version, io );
6b9371 ¤   }
c6f1e7 ¤   if ( IsntPGPError( err ) )
d5c7a1 ¤   {
201048 ¤   ¤   err¤= sWriteUInt32ToIO( set->nextAvailGroupID, io );
d89371 ¤   }
5ff1e7 ¤   if ( IsntPGPError( err ) )
aec7a1 ¤   {
9a29a3 ¤   ¤   err¤= PGPIOWrite( io, sizeof( set->pad ), set->pad );
249371 ¤   }
9967c5 ¤
49f1e7 ¤   if ( IsntPGPError( err ) )
7cc7a1 ¤   {
75be2c ¤   ¤   err¤= sWriteChecksumToIO( sComputeGroupSetChecksum( set ), io );
809371 ¤   }
aa67c5 ¤
43deb7 ¤   return( err );
0befe6 }
--43af 0005c54b93840100251 Page 14 of pgpGroups.c
e0af5a
1aaf5a
17af5a
2266dd ¤   static PGPError
ce5e5f sWriteGroupItemToIO(
b8619f ¤   PGPGroupItem const *¤   item,
52a9bf ¤   PGPIORef¤   ¤   ¤   ¤   io )
25bb36 {
309479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
6d7706 ¤   PGPExportedGroupItem¤   exportedItem;
5f67c5 ¤
7f5729 ¤   exportedItem.type = item->type;
0867c5 ¤
fff2b0 ¤   if( item->type == kPGPGroupItem_Group )
47c7a1 ¤   {
9adfa4 ¤   ¤   exportedItem.u.group.id = item->u.group.id;
f89371 ¤   }
7d52ce ¤   else if( item->type == kPGPGroupItem_KeyID )
dbc7a1 ¤   {
eb0c5b ¤   ¤   PGPSize¤dataSize;
39d8fb ¤   ¤   PGPByte¤exportedKeyID[kPGPMaxExportedKeyIDSize];
f31b52 ¤   ¤
0b1b17 ¤   ¤   /*
483aa5 ¤   ¤   ** PGPExportKeyID() whacks the complete array, so export to
0e9c3a ¤   ¤   ** a local buffer and then copy to the data structure
b15c12 ¤   ¤   */
9a1b52 ¤   ¤
dc5733 ¤   ¤   err = PGPExportKeyID( &item->u.key.keyID, exportedKeyID, &dataSize );
83cfff ¤   ¤   pgpAssert( dataSize <= sizeof( exportedItem.u.key.exportedKeyID ) );
d31b52 ¤   ¤
bb5eaa ¤   ¤   pgpCopyMemory( exportedKeyID, exportedItem.u.key.exportedKeyID,
a7128a ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( exportedItem.u.key.exportedKeyID ) );
222d0e ¤   ¤   exportedItem.u.key.length ¤ ¤   = (PGPByte) dataSize;
5685eb ¤   ¤   exportedItem.u.key.algorithm ¤  = item->u.key.algorithm;
6d1b52 ¤   ¤
9a9371 ¤   }
0d67c5 ¤
49b1f0 ¤   if( IsntPGPError( err ) )
02c7a1 ¤   {
3114f0 ¤   ¤   err¤= sWriteUInt32ToIO( exportedItem.type, io);
fe7d98 ¤   ¤   if ( IsntPGPError( err ) )
275b34 ¤   ¤   {
255e3c ¤   ¤   ¤   if ( exportedItem.type == kPGPGroupItem_Group )
40f776 ¤   ¤   ¤   {
f4aec3 ¤   ¤   ¤   ¤   err¤= sWriteUInt32ToIO( (PGPUInt32)exportedItem.u.group.id, io);
d6a3a6 ¤   ¤   ¤   }
75b63a ¤   ¤   ¤   else if ( exportedItem.type == kPGPGroupItem_KeyID )
2af776 ¤   ¤   ¤   {
b3370b ¤   ¤   ¤   ¤   err¤= sWriteUInt32ToIO( exportedItem.u.key.algorithm, io );
493227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
8333df ¤   ¤   ¤   ¤   ¤   err¤= PGPIOWrite( io, 1, &exportedItem.u.key.length);
df3227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
7d72c3 ¤   ¤   ¤   ¤   {
e5e354 ¤   ¤   ¤   ¤   ¤   err¤= PGPIOWrite( io, exportedItem.u.key.length,
56b63e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   exportedItem.u.key.exportedKeyID );
6e2613 ¤   ¤   ¤   ¤   }
3ca3a6 ¤   ¤   ¤   }
390fe4 ¤   ¤   }
599371 ¤   }
6367c5 ¤
99f1e7 ¤   if ( IsntPGPError( err ) )
5dc7a1 ¤   {
7cb89e ¤   ¤   err¤= sWriteChecksumToIO( sComputeExportedGroupItemChecksum(
46aae4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &exportedItem ), io );
109371 ¤   }
8667c5 ¤
c6deb7 ¤   return( err );
52efe6 }
93af5a
8faf5a
e666dd ¤   static PGPError
5c93c2 sWriteGroupToIO(
--d8ec 00027c05a5d40100251 Page 15 of pgpGroups.c
bdd2b6 ¤   PGPGroup const *¤   group,
02b7a1 ¤   PGPIORef¤   ¤   ¤   io )
4bbb36 {
a09372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
c267c5 ¤
daa5f5 ¤   err¤= sWriteUInt32ToIO( (PGPUInt32)group->id, io );
eaf1e7 ¤   if ( IsntPGPError( err ) )
66c7a1 ¤   {
cdafe9 ¤   ¤   err¤= PGPIOWrite( io, sizeof( group->name ), group->name );
509371 ¤   }
7ff1e7 ¤   if ( IsntPGPError( err ) )
7bc7a1 ¤   {
507f61 ¤   ¤   err¤= PGPIOWrite( io,
22471e ¤   ¤   ¤   sizeof( group->description ), group->description );
979371 ¤   }
8ff1e7 ¤   if ( IsntPGPError( err ) )
73c7a1 ¤   {
0fb848 ¤   ¤   err¤= sWriteUInt32ToIO( group->numItems, io);
3f9371 ¤   }
3467c5 ¤
5af1e7 ¤   if ( IsntPGPError( err ) )
adc7a1 ¤   {
a06332 ¤   ¤   err¤= sWriteChecksumToIO( sComputeGroupChecksum( group ), io );
149371 ¤   }
5767c5 ¤
0bf1e7 ¤   if ( IsntPGPError( err ) )
5bc7a1 ¤   {
0dfd11 ¤   ¤   PGPUInt32¤  ¤   index;
9c67c5 ¤
a60f64 ¤   ¤   /* now write all the items out */
e72f14 ¤   ¤   for ( index = 0; index < group->numItems; ++index )
795b34 ¤   ¤   {
34ac02 ¤   ¤   ¤   err¤= sWriteGroupItemToIO( &group->itemsArray[ index ], io );
5f8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
06f622 ¤   ¤   ¤   ¤   break;
090fe4 ¤   ¤   }
839371 ¤   }
7b67c5 ¤
36deb7 ¤   return( err );
b0efe6 }
4aaf5a
40af5a
d9af5a
1e66dd ¤   static PGPError
9f182a sWriteGroupSetToIO(
1e30d0 ¤   PGPGroupSetRef¤ set,
9536bc ¤   PGPIORef¤   ¤   io )
7cbb36 {
949372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
7967c5 ¤
dd7257 ¤   err¤= sWriteGroupSetHeaderToIO( set, io );
f5f3e5 ¤   if ( IsntPGPError( err ) && IsntNull( set->groupArray ) )
62c7a1 ¤   {
bf2f27 ¤   ¤   PGPUInt32¤  groupIndex;
8a1b52 ¤   ¤
f642d7 ¤   ¤   for( groupIndex = 0; groupIndex < set->numGroups; ++groupIndex )
d45b34 ¤   ¤   {
75fcc3 ¤   ¤   ¤   PGPGroup *¤ group;
cb87c7 ¤   ¤   ¤
7d1abd ¤   ¤   ¤   group¤  = &set->groupArray[ groupIndex ];
506c67 ¤   ¤   ¤   err¤= sWriteGroupToIO( group, io );
e78370 ¤   ¤   ¤   if ( IsPGPError( err ) )
b5f622 ¤   ¤   ¤   ¤   break;
570fe4 ¤   ¤   }
9c9371 ¤   }
9867c5 ¤
37deb7 ¤   return( err );
c4efe6 }
a6af5a
8aaf5a
26c744 ¤   PGPError
27201a PGPSaveGroupSetToFile(
--ae77 000823711d540100251 Page 16 of pgpGroups.c
5f30d0 ¤   PGPGroupSetRef¤ set,
3b9bf6 ¤   PGPFileSpecRef¤ file )
c1bb36 {
1c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b649b4 ¤   PGPFileIORef¤   io¤ = NULL;
733958 ¤   PFLFileSpecRef¤ tempSpec¤   = NULL;
34d0f9 ¤   PGPBoolean¤ ¤   fileExists¤ = TRUE;
fc84bb ¤   PFLFileSpecRef¤ pflFile = (PFLFileSpecRef) file;
3c67c5 ¤
21b620 ¤   PGPValidateGroupSet( set );
84e84a ¤   PFLValidateFileSpec( pflFile );
7067c5 ¤
27f8bc ¤   err¤= PFLFileSpecExists( pflFile, &fileExists );
f367c5 ¤
11011f ¤   /* get a temp file to work with */
3cf1e7 ¤   if ( IsntPGPError( err ) )
612320 ¤   ¤   err¤= PFLFileSpecGetUniqueSpec( pflFile, &tempSpec );
9e1b52 ¤   ¤
3ff1e7 ¤   if ( IsntPGPError( err ) )
94c7a1 ¤   {
0956ea ¤   ¤   /* create the temp file */
e3db6c ¤   ¤   err¤= pgpCreateFile( tempSpec, kPGPFileTypeGroups );
627d98 ¤   ¤   if ( IsntPGPError( err ) )
a85b34 ¤   ¤   {
87f9cd ¤   ¤   ¤   /* open it, and write everything out */
87a934 ¤   ¤   ¤   err¤= PGPOpenFileSpec( tempSpec,
7183c9 ¤   ¤   ¤   ¤   ¤   kPFLFileOpenFlags_ReadWrite, &io );
903c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
aff776 ¤   ¤   ¤   {
b077e4 ¤   ¤   ¤   ¤   err¤= sWriteGroupSetToIO( set, (PGPIORef)io);
929c83 ¤   ¤   ¤   ¤   PGPFreeIO( (PGPIORef)io );
f1a3a6 ¤   ¤   ¤   }
5b0fe4 ¤   ¤   }
b61b52 ¤   ¤
85d08f ¤   ¤   /* delete the original and rename the temp */
2ae83c ¤   ¤   if ( IsntPGPError( err ) && fileExists )
005b34 ¤   ¤   {
7351e9 ¤   ¤   ¤   char¤   name[ 512 ];
8c87c7 ¤   ¤   ¤
c66628 ¤   ¤   ¤   /* get original file name */
76eadf ¤   ¤   ¤   err¤= PFLGetFileSpecNameBuffer( pflFile,
5952bf ¤   ¤   ¤   ¤   ¤   sizeof( name ), name );
6c94aa ¤   ¤   ¤   ¤   ¤   ¤
593c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
7ef776 ¤   ¤   ¤   {
f4813b ¤   ¤   ¤   ¤   /* delete the original */
e1fb41 ¤   ¤   ¤   ¤   err¤= PFLFileSpecDelete( pflFile );
7ba3a6 ¤   ¤   ¤   }
b62b85 ¤   ¤   ¤   ¤
433c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
a6f776 ¤   ¤   ¤   {
06180d ¤   ¤   ¤   ¤   /* rename temp to original */
b6fd96 ¤   ¤   ¤   ¤   err¤= PFLFileSpecRename( tempSpec, name );
52a3a6 ¤   ¤   ¤   }
b3af5a
b60fe4 ¤   ¤   }
751b52 ¤   ¤
6b7d98 ¤   ¤   if ( IsntPGPError( err ) )
c55b34 ¤   ¤   {
444439 ¤   ¤   ¤   /* safely up to date on disk... */
58e106 ¤   ¤   ¤   set->hasBeenModified¤   = FALSE;
7a0fe4 ¤   ¤   }
ce1b52 ¤   ¤
935c8d ¤   ¤   PFLFreeFileSpec( tempSpec );
219371 ¤   }
a067c5 ¤
d6deb7 ¤   return( err );
94efe6 }
f0af5a
dfaf5a
9caf5a
82c744 ¤   PGPError
--1b93 0001fc5b2ca40100251 Page 17 of pgpGroups.c
9aefa2 PGPExportGroupSetToBuffer(
2730d0 ¤   PGPGroupSetRef¤ set,
685f07 ¤   void **¤¤   ¤   buffer,
6ad764 ¤   PGPSize *¤  ¤   bufferSize )
a8bb36 {
f59372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0abbfc ¤   PGPIORef¤   ¤   io¤ = NULL;
e31f3c ¤   void *¤ ¤   ¤   tempBuffer = NULL;
dc70e9 ¤   PGPFileOffset¤  bufSize;
1767c5 ¤
72b620 ¤   PGPValidateGroupSet( set );
92b99f ¤   PGPValidatePtr( buffer );
45f4db ¤   *buffer = NULL;
1a67c5 ¤
d302bf ¤   err = PGPNewMemoryIO( PGPGetContextMemoryMgr( set->context ),
0f7861 ¤   ¤   ¤   (PGPMemoryIORef *) &io );
68f1e7 ¤   if ( IsntPGPError( err ) )
c8c7a1 ¤   {
839693 ¤   ¤   err¤= sWriteGroupSetToIO( set, (PGPIORef)io);
c71b52 ¤   ¤
417d98 ¤   ¤   if ( IsntPGPError( err ) )
695b34 ¤   ¤   {
80ce7e ¤   ¤   ¤   err = PGPIOSetPos(¤ io,
a7ddc9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   0);
7387c7 ¤   ¤   ¤
a83c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
bef776 ¤   ¤   ¤   {
f48476 ¤   ¤   ¤   ¤   err = PGPIOGetEOF(¤ io,
334884 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &bufSize);
cf2b85 ¤   ¤   ¤   ¤
3e3227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
8672c3 ¤   ¤   ¤   ¤   {
3ee461 ¤   ¤   ¤   ¤   ¤   tempBuffer = pgpContextMemAlloc( set->context,
831102 ¤   ¤   ¤   ¤   ¤   ¤   (PGPSize)bufSize, kPGPMemoryMgrFlags_None );
0aae30 ¤   ¤   ¤   ¤   ¤
3f0666 ¤   ¤   ¤   ¤   ¤   if ( IsntNull( tempBuffer ) )
614859 ¤   ¤   ¤   ¤   ¤   {
db874c ¤   ¤   ¤   ¤   ¤   ¤   err = PGPIORead(¤   io,
8c8ba5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPSize)bufSize,
2a72d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempBuffer,
c53586 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   bufferSize);
fb94aa ¤   ¤   ¤   ¤   ¤   ¤
5d7b0d ¤   ¤   ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
4d8fec ¤   ¤   ¤   ¤   ¤   ¤   {
81baab ¤   ¤   ¤   ¤   ¤   ¤   ¤   *buffer = tempBuffer;
d8251b ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempBuffer = NULL;
29db3c ¤   ¤   ¤   ¤   ¤   ¤   }
9f94aa ¤   ¤   ¤   ¤   ¤   ¤
8a09d2 ¤   ¤   ¤   ¤   ¤   ¤   if ( tempBuffer != NULL )
2e8fec ¤   ¤   ¤   ¤   ¤   ¤   {
e35514 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeData( tempBuffer );
78db3c ¤   ¤   ¤   ¤   ¤   ¤   }
fa1c89 ¤   ¤   ¤   ¤   ¤   }
834bd6 ¤   ¤   ¤   ¤   ¤   else
2f4859 ¤   ¤   ¤   ¤   ¤   {
c2be32 ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
4b1c89 ¤   ¤   ¤   ¤   ¤   }
2c2613 ¤   ¤   ¤   ¤   }
b7a3a6 ¤   ¤   ¤   }
220fe4 ¤   ¤   }
fe1b52 ¤   ¤
49ccb3 ¤   ¤   PGPFreeIO( io );
d49371 ¤   }
5267c5 ¤
0fdeb7 ¤   return( err );
56efe6 }
5eaf5a
d6af5a
73af5a
e0c744 ¤   PGPError
4a1f1a PGPImportGroupSetFromBuffer(
1fa1bc ¤   PGPContextRef¤  ¤   context,
--6fd8 0006525687b40100251 Page 18 of pgpGroups.c
9b4984 ¤   void *¤ ¤   ¤   ¤   buffer,
d961d0 ¤   PGPSize¤¤   ¤   ¤   bufSize,
34ec1b ¤   PGPGroupSetRef *¤   outSet)
3abb36 {
0f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
a6bbfc ¤   PGPIORef¤   ¤   io¤ = NULL;
2b67c5 ¤
9af3ca ¤   PGPValidateContext( context );
60b99f ¤   PGPValidatePtr( buffer );
97016b ¤   PGPValidatePtr( outSet );
b2c229 ¤   *outSet = NULL;
ad67c5 ¤
f82bcd ¤   err¤= PGPNewMemoryIOFixedBuffer( PGPGetContextMemoryMgr( context ), buffer,
24d14e ¤   ¤   bufSize, (PGPMemoryIORef *) &io );
6ef1e7 ¤   if ( IsntPGPError( err ) )
49c7a1 ¤   {
2280b7 ¤   ¤   err¤= PGPNewGroupSet( context, outSet );
037d98 ¤   ¤   if ( IsntPGPError( err ) )
1a5b34 ¤   ¤   {
9b3764 ¤   ¤   ¤   err¤= sReadGroupSetFromIO( (PGPIORef)io, *outSet);
b359df ¤   ¤   ¤   if( IsPGPError( err ) )
dbf776 ¤   ¤   ¤   {
37239a ¤   ¤   ¤   ¤   PGPFreeGroupSet( *outSet );
774f4d ¤   ¤   ¤   ¤   *outSet = kInvalidPGPGroupSetRef;
51a3a6 ¤   ¤   ¤   }
0b0fe4 ¤   ¤   }
12af5a
d2d33c ¤   ¤   PGPFreeIO( (PGPIORef)io );
d79371 ¤   }
62af5a
d1deb7 ¤   return( err );
80efe6 }
d21b52 ¤   ¤
c2af5a
0faf5a
7a33c8 ¤   static void
235e97 sDeleteGroupsArray( PGPGroupSetRef set )
1abb36 {
b497b3 ¤   PGPContextRef¤  context¤= set->context;
5267c5 ¤
a6cefd ¤   if ( IsntNull( set->groupArray ) )
5dc7a1 ¤   {
1263e3 ¤   ¤   PGPUInt32¤  ¤   groupIndex;
1967c5 ¤
cf42d7 ¤   ¤   for( groupIndex = 0; groupIndex < set->numGroups; ++groupIndex )
ad5b34 ¤   ¤   {
07fcc3 ¤   ¤   ¤   PGPGroup *¤ group;
fc87c7 ¤   ¤   ¤
0d1abd ¤   ¤   ¤   group¤  = &set->groupArray[ groupIndex ];
7987c7 ¤   ¤   ¤
514106 ¤   ¤   ¤   sDestroyGroup( group );
c40fe4 ¤   ¤   }
761b52 ¤   ¤
8ab388 ¤   ¤   pgpContextMemFree( context, set->groupArray );
e63a1c ¤   ¤   set->groupArray¤= NULL;
869371 ¤   }
06efe6 }
7daf5a
a2c744 ¤   PGPError
c6c589 PGPFreeGroupSet( PGPGroupSetRef set )
00bb36 {
049372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
7d97b3 ¤   PGPContextRef¤  context¤= set->context;
2267c5 ¤
57b620 ¤   PGPValidateGroupSet( set );
ed67c5 ¤
94e044 ¤   sDeleteGroupsArray( set );
3b61c6 ¤   pgpContextMemFree( context, set );
8d67c5 ¤
2cdeb7 ¤   return( err );
95efe6 }
65af5a
--606f 00010509f3e40100251 Page 19 of pgpGroups.c
e0af5a
4516ea ¤   PGPBoolean
119bac PGPGroupSetNeedsCommit( PGPGroupSetRef set )
44bb36 {
e4987e ¤   pgpAssert( PGPGroupSetIsValid( set ) );
1eb624 ¤   if ( IsNull( set ) )
fde20d ¤   ¤   return( FALSE );
0b1b52 ¤   ¤
de4a4f ¤   return( set->hasBeenModified );
1aefe6 }
5faf5a
00af5a
66af5a
7433a3 ¤   static PGPGroupID
a967ce sGetNextAvailGroupID(PGPGroupSetRef¤set)
c2bb36 {
7f4a39 ¤   PGPGroupID¤ id;
ea67c5 ¤
09198b ¤   set->nextAvailGroupID¤  += 1;
47917f ¤   id¤ = (PGPGroupID)set->nextAvailGroupID;
be322b ¤   return( id );
e6efe6 }
6faf5a
9eaf5a
cfbfe5 ¤   static PGPInt32
ffd338 sCompareGroupsProc(
801b04 ¤   PGPGroup *¤ in1,
35f460 ¤   PGPGroup *¤ in2,
28a498 ¤   void *¤ ¤   userValue )
53bb36 {
7823d9 ¤   const PGPGroup *¤   group1¤ = (const PGPGroup *)in1;
fe968e ¤   const PGPGroup *¤   group2¤ = (const PGPGroup *)in2;
e565ee ¤   PGPInt32¤   ¤   ¤   result;
4e67c5 ¤
369024 ¤   (void)userValue;
f63785 ¤   result¤ = pgpCompareStringsIgnoreCase( group1->name, group2->name );
5967c5 ¤
634c6e ¤   return( result );
0fefe6 }
aeaf5a
00af5a
a82efe #define InsertionSortName¤  sInsertionSortGroups
784dea #define InsertionSortItem¤  PGPGroup
ea5986 #include "pgpInsertionSort.h"
e8b294 #undef InsertionSortName
bf27bc #undef InsertionSortItem
62af5a
0266dd ¤   static PGPError
f9655f sSortGroups( PGPGroupSetRef set )
a1cebb {¤
848e19 ¤   sInsertionSortGroups( set->groupArray,
477624 ¤   ¤   set->numGroups, sCompareGroupsProc, 0 );
2f1b52 ¤   ¤
e82d68 ¤   return( kPGPError_NoErr );
9fefe6 }
86af5a
adaf5a
92af5a
fa28ab #define InsertionSortName¤  sInsertionSortGroupItems
b123ed #define InsertionSortItem¤  PGPGroupItem
1a5986 #include "pgpInsertionSort.h"
99b294 #undef InsertionSortName
cc27bc #undef InsertionSortItem
0caf5a
28af5a
e2af5a
17c744 ¤   PGPError
7f9554 PGPSortGroupItems(
19a976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
604232 ¤   PGPGroupID¤ ¤   ¤   ¤   id,
2224f2 ¤   PGPGroupItemCompareProc¤compareProc,
10f0ae ¤   PGPUserValue¤   ¤   ¤   userValue )
--cbb8 00025cd07fb40100251 Page 20 of pgpGroups.c
2cbb36 {
cd26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
aa0a0a ¤   PGPGroup *¤ group;
5b67c5 ¤
df558c ¤   err¤= sFindGroupByID( set, id, &group );
b7f1e7 ¤   if ( IsntPGPError( err ) )
44c7a1 ¤   {
e191a8 ¤   ¤   sInsertionSortGroupItems( group->itemsArray,
3a30b8 ¤   ¤   ¤   group->numItems, compareProc, userValue );
7e9371 ¤   }
3c1b52 ¤   ¤
0bdeb7 ¤   return( err );
c0efe6 }
b7af5a
b6af5a
f1c744 ¤   PGPError
ac30e8 PGPSortGroupSet(
c2a976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
9524f2 ¤   PGPGroupItemCompareProc¤compareProc,
fef0ae ¤   PGPUserValue¤   ¤   ¤   userValue )
1abb36 {
64c7f9 ¤   PGPUInt32¤  index;
5a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
0e67c5 ¤
5ce6db ¤   sSortGroups( set );
d967c5 ¤
dbf0a0 ¤   for( index = 0; index < set->numGroups; ++index )
8cc7a1 ¤   {
a3db85 ¤   ¤   err¤= PGPSortGroupItems( set,
9f90e8 ¤   ¤   ¤   set->groupArray[ index ].id, compareProc, userValue );
dabe18 ¤   ¤   if ( IsPGPError( err ) )
97cdcb ¤   ¤   ¤   break;
5e9371 ¤   }
f1deb7 ¤   return( err );
56efe6 }
37af5a
fd0335 /*____________________________________________________________________________
f0ccc1 ¤   Add a group to the set. ·Caller has initialized the group.
52f7f7 ____________________________________________________________________________*/
1e66dd ¤   static PGPError
cbc620 sAddGroup(
b7e19d ¤   PGPGroupSetRef¤ ¤   set,
6bd3cd ¤   PGPGroup const *¤   group )
d6bb36 {
1a9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0697b3 ¤   PGPContextRef¤  context¤= set->context;
601682 ¤   PGPSize¤¤   ¤   newSize;
e567c5 ¤
6a6399 ¤   newSize¤= ( set->numGroups + 1 ) * sizeof( *group );
b5e51e ¤   err¤= pgpContextMemRealloc( context, (void **) &set->groupArray,
4b7540 ¤   ¤   ¤   newSize, 0);
72af5a
2af1e7 ¤   if ( IsntPGPError( err ) )
9dc7a1 ¤   {
1bb332 ¤   ¤   (set->groupArray)[ set->numGroups ]¤= *group;
0454b4 ¤   ¤   set->numGroups++;
a19371 ¤   }
d567c5 ¤
b4deb7 ¤   return( err );
70efe6 }
1faf5a
acaf5a
d0c744 ¤   PGPError
1d07e9 PGPNewGroup(
c1a976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
6e4d49 ¤   const char *¤   ¤   ¤   name,
06f678 ¤   const char *¤   ¤   ¤   description,
3d3123 ¤   PGPGroupID *¤   ¤   ¤   idOut )
5bbb36 {
d29372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b2eb9f ¤   PGPGroup¤   ¤   newGroup;
25906f ¤   PGPGroupID¤ ¤   newID;
--6d71 00023d440ca40100251 Page 21 of pgpGroups.c
636fe7 ¤   PGPGroup *¤ ¤   dummyGroup;
d467c5 ¤
00225a ¤   PGPValidatePtr( idOut );
5261da ¤   *idOut¤ = kPGPInvalidGroupID;
95a80d ¤   PGPValidatePtr( name );
3d13bb ¤   PGPValidatePtr( description );
844a8d ¤   PGPValidateParam( strlen( name ) <= kPGPMaxGroupNameLength );
2c6733 ¤   PGPValidateParam( strlen( description ) <= kPGPMaxGroupDescriptionLength );
9cb620 ¤   PGPValidateGroupSet( set );
9967c5 ¤
bfcfa1 ¤   do
45c7a1 ¤   {
cb0382 ¤   ¤   newID¤  = sGetNextAvailGroupID( set );
159371 ¤   }
8587e6 ¤   while ( IsntPGPError( err = sFindGroupByID( set, newID, &dummyGroup ) ));
56803f ¤   pgpAssert( newID != kPGPInvalidGroupID );
8f67c5 ¤
9a8653 ¤   sInitGroup( set, newID, name, description, &newGroup );
4bbc59 ¤   err¤= sAddGroup( set, &newGroup );
fef1e7 ¤   if ( IsntPGPError( err ) )
89c7a1 ¤   {
b641e6 ¤   ¤   *idOut¤ = newID;
7a70d0 ¤   ¤   set->hasBeenModified¤   = TRUE;
dd9371 ¤   }
c467c5 ¤
0ddeb7 ¤   return( err );
d4efe6 }
d4af5a
e7af5a
03af5a
d10335 /*____________________________________________________________________________
59e89b ¤   Eliminate any reference to the group with ID 'id' from 'group'.
3ef7f7 ____________________________________________________________________________*/
1e66dd ¤   static PGPError
221fd4 sEliminateGroupFromGroup(
cf4f2a ¤   PGPGroup *¤ ¤   group,
f03f55 ¤   PGPGroupID¤ ¤   id )
acbb36 {
f8c7f9 ¤   PGPUInt32¤  index;
b226d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
4867c5 ¤
151e40 ¤   pgpAssert( IsntNull( group->set ) );
ffd2af ¤   for (index = 0; index < group->numItems; ++index )
6ec7a1 ¤   {
035675 ¤   ¤   PGPGroupItem const *¤   item;
791b52 ¤   ¤
ba7789 ¤   ¤   item¤   = &group->itemsArray[ index ];
d7b1ad ¤   ¤   if (item->type == kPGPGroupItem_Group &&
b0f440 ¤   ¤   ¤   item->u.group.id == id )
5a5b34 ¤   ¤   {
70b8f5 ¤   ¤   ¤   err¤= PGPDeleteIndItemFromGroup( group->set, group->id, index );
d4bedb ¤   ¤   ¤   /* it can only be in there once so we're done */
79cdcb ¤   ¤   ¤   break;
870fe4 ¤   ¤   }
3f9371 ¤   }
8adeb7 ¤   return( err );
eeefe6 }
dcaf5a
baaf5a
500335 /*____________________________________________________________________________
33760f ¤   Eliminate references to this group from everything.
c8f7f7 ____________________________________________________________________________*/
bb66dd ¤   static PGPError
41beb6 sEliminateReferencesToGroup(
2430d0 ¤   PGPGroupSetRef¤ set,
eb3f55 ¤   PGPGroupID¤ ¤   id )
f3bb36 {
7ac7f9 ¤   PGPUInt32¤  index;
0926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
c267c5 ¤
e49e2c ¤   for (index = 0; index < set->numGroups; ++index )
23c7a1 ¤   {
--c428 00012be543440100251 Page 22 of pgpGroups.c
bce8eb ¤   ¤   PGPGroup *¤ group;
0b67c5 ¤
c77cdb ¤   ¤   group¤  = &set->groupArray[ index ];
1d0131 ¤   ¤   err¤= sEliminateGroupFromGroup( group, id );
6ebe18 ¤   ¤   if ( IsPGPError( err ) )
decdcb ¤   ¤   ¤   break;
6f9371 ¤   }
05deb7 ¤   return( err );
a5efe6 }
79af5a
faaf5a
11af5a
290335 /*____________________________________________________________________________
b343fe ¤   Determine if an item is already a member of the group
4cf7f7 ____________________________________________________________________________*/
f56c2c ¤   static PGPBoolean
55a7d7 sIsGroupMember(
80ae2e ¤   PGPGroup const *¤   ¤   group,
c8619f ¤   PGPGroupItem const *¤   item,
5de8fa ¤   PGPUInt32 *¤¤   ¤   ¤   outIndex )
3ebb36 {
b063f8 ¤   PGPBoolean¤ ¤   isMember¤   = FALSE;
afe939 ¤   PGPUInt32¤  ¤   index;
4e67c5 ¤
ce24fd ¤   *outIndex¤  = ~(PGPUInt32)0;
479ca5 ¤   for( index = 0; index < group->numItems; ++index )
00c7a1 ¤   {
c6ce51 ¤   ¤   PGPGroupItem const *¤   indItem;
d91b52 ¤   ¤
39066d ¤   ¤   indItem¤= &group->itemsArray[ index ];
6a9537 ¤   ¤   if ( indItem->type == item->type )
615b34 ¤   ¤   {
0f48a9 ¤   ¤   ¤   if ( indItem->type == kPGPGroupItem_Group )
91f776 ¤   ¤   ¤   {
3a1d6b ¤   ¤   ¤   ¤   if ( indItem->u.group.id == item->u.group.id )
2372c3 ¤   ¤   ¤   ¤   {
39dd86 ¤   ¤   ¤   ¤   ¤   *outIndex¤  = index;
6a749b ¤   ¤   ¤   ¤   ¤   isMember¤   = TRUE;
7e14c3 ¤   ¤   ¤   ¤   ¤   break;
372613 ¤   ¤   ¤   ¤   }
e6a3a6 ¤   ¤   ¤   }
ebe079 ¤   ¤   ¤   else if ( indItem->type == kPGPGroupItem_KeyID )
45f776 ¤   ¤   ¤   {
e76387 ¤   ¤   ¤   ¤   if( PGPCompareKeyIDs( &indItem->u.key.keyID,
e50b3f ¤   ¤   ¤   ¤   ¤   ¤   &item->u.key.keyID ) == 0 )
ca72c3 ¤   ¤   ¤   ¤   {
1bdd86 ¤   ¤   ¤   ¤   ¤   *outIndex¤  = index;
6a749b ¤   ¤   ¤   ¤   ¤   isMember¤   = TRUE;
ec14c3 ¤   ¤   ¤   ¤   ¤   break;
6c2613 ¤   ¤   ¤   ¤   }
8fa3a6 ¤   ¤   ¤   }
0b0fe4 ¤   ¤   }
da9371 ¤   }
0567c5 ¤
fc3195 ¤   return( isMember );
04efe6 }
79af5a
c7af5a
d00335 /*____________________________________________________________________________
d1b513 ¤   Delete a group. ·Since other groups may refer to it, search for and
f8238f ¤   eliminate all references to it.
30f7f7 ____________________________________________________________________________*/
55c744 ¤   PGPError
71897a PGPDeleteGroup(
3fe19d ¤   PGPGroupSetRef¤ ¤   set,
41012f ¤   PGPGroupID¤ ¤   ¤   id )
04bb36 {
009372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
f6e939 ¤   PGPUInt32¤  ¤   index;
1f67c5 ¤
0bb620 ¤   PGPValidateGroupSet( set );
1267c5 ¤
--bbbd 000f4e2ba2640100251 Page 23 of pgpGroups.c
020c4b ¤   /* find the group in our array */
9d7865 ¤   err¤= sGetGroupIndexByID( set, id, &index );
45f1e7 ¤   if ( IsntPGPError( err ) )
b9c7a1 ¤   {
c3e8eb ¤   ¤   PGPGroup *¤ group;
826fc5 ¤   ¤   PGPUInt32¤  bytesAfter;
e91b52 ¤   ¤
2f70d0 ¤   ¤   set->hasBeenModified¤   = TRUE;
8a1b52 ¤   ¤
6414e2 ¤   ¤   /* destroy the group, the remove it from the array */
b84794 ¤   ¤   group¤  ¤   = &set->groupArray[ index ];
461b52 ¤   ¤
57cafa ¤   ¤   sDestroyGroup( group );
4d505e ¤   ¤   /* shift bytes down */
757259 ¤   ¤   bytesAfter¤ = ( set->numGroups - index - 1 ) * sizeof( *group );
c5956c ¤   ¤   if ( bytesAfter != 0 )
065b34 ¤   ¤   {
46616c ¤   ¤   ¤   pgpCopyMemory( group + 1, group, bytesAfter);
060fe4 ¤   ¤   }
18ef16 ¤   ¤   set->numGroups¤ -= 1;
d64a5b ¤   ¤   /* we don't shrink the array */
439371 ¤   }
0a67c5 ¤
cdf7ae ¤   /* now eliminate this group from all other groups (yuck) */
813fb9 ¤   sEliminateReferencesToGroup( set, id );
db67c5 ¤
b3deb7 ¤   return( err );
aaefe6 }
dfaf5a
f2af5a
c90335 /*____________________________________________________________________________
bd9417 ¤   Delete an item from a group. ·The item may be of any valid kind.
0a67c5 ¤
718fe5 ¤   Afterwards, there will be one less item in the group.
b6f7f7 ____________________________________________________________________________*/
20c744 ¤   PGPError
98c689 PGPDeleteIndItemFromGroup(
ed30d0 ¤   PGPGroupSetRef¤ set,
2c1ced ¤   PGPGroupID¤ ¤   id,
61a699 ¤   PGPUInt32¤  ¤   index )
fabb36 {
c6d48f ¤   PGPGroup *¤ group¤  = NULL;
5d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
6667c5 ¤
d8b620 ¤   PGPValidateGroupSet( set );
f967c5 ¤
53558c ¤   err¤= sFindGroupByID( set, id, &group );
52f1e7 ¤   if ( IsntPGPError( err ) )
42c7a1 ¤   {
5f2eff ¤   ¤   PGPSize¤¤   ¤   bytesAfter;
bde75c ¤   ¤   PGPGroupItem *¤ item;
6c1b52 ¤   ¤
05031b ¤   ¤   PGPValidateParam( index < group->numItems );
3b67c5 ¤
6770d0 ¤   ¤   set->hasBeenModified¤   = TRUE;
b11b52 ¤   ¤
3a7789 ¤   ¤   item¤   = &group->itemsArray[ index ];
632160 ¤   ¤   bytesAfter¤ = ( group->numItems - index - 1 ) * sizeof( *item );
dc956c ¤   ¤   if ( bytesAfter != 0 )
1a5b34 ¤   ¤   {
43e859 ¤   ¤   ¤   pgpCopyMemory( item + 1, item, bytesAfter );
740fe4 ¤   ¤   }
8d1b52 ¤   ¤
c3af4c ¤   ¤   group->numItems¤-= 1;
671b52 ¤   ¤
701877 ¤   ¤   /* don't bother shrinking, but if nothing left, get rid of it */
2586d6 ¤   ¤   if ( group->numItems == 0 )
f75b34 ¤   ¤   {
2cdc86 ¤   ¤   ¤   pgpContextMemFree( group->set->context, group->itemsArray );
858e4d ¤   ¤   ¤   group->itemsArray¤  = NULL;
2d0fe4 ¤   ¤   }
f41b52 ¤   ¤
--05cf 0003cc0447140100251 Page 24 of pgpGroups.c
a19371 ¤   }
eadeb7 ¤   return( err );
3fefe6 }
2caf5a
eeaf5a
35af5a
71c744 ¤   PGPError
379977 PGPDeleteItemFromGroup(
01a976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
c04232 ¤   PGPGroupID¤ ¤   ¤   ¤   id,
9a6fbd ¤   PGPGroupItem const *¤   item )
ccbb36 {
5cd48f ¤   PGPGroup *¤ group¤  = NULL;
7e26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d567c5 ¤
29b620 ¤   PGPValidateGroupSet( set );
8a0a11 ¤   PGPValidatePtr( item );
65af5a
d2558c ¤   err¤= sFindGroupByID( set, id, &group );
e2f1e7 ¤   if ( IsntPGPError( err ) )
84c7a1 ¤   {
c32518 ¤   ¤   PGPUInt32¤  index;
561b52 ¤   ¤
bcd849 ¤   ¤   err¤= sIsGroupMember( group, item, &index );
5b7d98 ¤   ¤   if ( IsntPGPError( err ) )
e35b34 ¤   ¤   {
e530fa ¤   ¤   ¤   err¤= PGPDeleteIndItemFromGroup( set, id, index );
5f0fe4 ¤   ¤   }
729371 ¤   }
43deb7 ¤   return( err );
c4efe6 }
99af5a
43af5a
d4c744 ¤   PGPError
8907ef PGPGetGroupInfo(
e9e19d ¤   PGPGroupSetRef¤ ¤   set,
169d22 ¤   PGPGroupID¤ ¤   ¤   id,
8f123e ¤   PGPGroupInfo *¤ ¤   info )
cfbb36 {
9837df ¤   PGPError¤   ¤   ¤   err¤¤   = kPGPError_NoErr;
f951ae ¤   PGPGroup const *¤   group¤  = NULL;
be67c5 ¤
134c7a ¤   PGPValidatePtr( info );
80363d ¤   pgpClearMemory( info, sizeof( *info ) );
c7b620 ¤   PGPValidateGroupSet( set );
c267c5 ¤
723739 ¤   err¤= sFindGroupByID( set, id, (PGPGroup **)&group );
a4f1e7 ¤   if ( IsntPGPError( err ) )
eac7a1 ¤   {
b4fc57 ¤   ¤   info->id¤   ¤   = id;
0ba63b ¤   ¤   strcpy( info->name, group->name );
bcf597 ¤   ¤   strcpy( info->description, group->description );
66b78b ¤   ¤   info->userValue¤= group->userValue;
ed9371 ¤   }
2367c5 ¤
e4deb7 ¤   return( err );
9befe6 }
caaf5a
c9af5a
bfc744 ¤   PGPError
55e7c3 PGPSetGroupName(
6a30d0 ¤   PGPGroupSetRef¤ set,
801ced ¤   PGPGroupID¤ ¤   id,
f352e9 ¤   const char *¤   name )
38bb36 {
a79372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
f10085 ¤   PGPGroup *¤ ¤   group¤  = NULL;
9c67c5 ¤
03a80d ¤   PGPValidatePtr( name );
d5b620 ¤   PGPValidateGroupSet( set );
ac4a8d ¤   PGPValidateParam( strlen( name ) <= kPGPMaxGroupNameLength );
3c67c5 ¤
--24e3 0008785117c40100251 Page 25 of pgpGroups.c
f1558c ¤   err¤= sFindGroupByID( set, id, &group );
def1e7 ¤   if ( IsntPGPError( err ) )
1fc7a1 ¤   {
880675 ¤   ¤   strcpy( group->name, name );
ab70d0 ¤   ¤   set->hasBeenModified¤   = TRUE;
039371 ¤   }
9367c5 ¤
2fdeb7 ¤   return( err );
a9efe6 }
c6af5a
e3af5a
99c744 ¤   PGPError
ad687b PGPSetGroupDescription(
2630d0 ¤   PGPGroupSetRef¤ set,
051ced ¤   PGPGroupID¤ ¤   id,
1229ee ¤   const char *¤   description )
0abb36 {
359372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
380085 ¤   PGPGroup *¤ ¤   group¤  = NULL;
1f67c5 ¤
8f13bb ¤   PGPValidatePtr( description );
976733 ¤   PGPValidateParam( strlen( description ) <= kPGPMaxGroupDescriptionLength );
9eb620 ¤   PGPValidateGroupSet( set );
0e67c5 ¤
0d558c ¤   err¤= sFindGroupByID( set, id, &group );
b9f1e7 ¤   if ( IsntPGPError( err ) )
8bc7a1 ¤   {
8f4d54 ¤   ¤   strcpy( group->description, description );
7770d0 ¤   ¤   set->hasBeenModified¤   = TRUE;
b79371 ¤   }
e067c5 ¤
53deb7 ¤   return( err );
06efe6 }
faaf5a
d9af5a
d9c744 ¤   PGPError
d315dd PGPSetGroupUserValue(
7c30d0 ¤   PGPGroupSetRef¤ set,
e81ced ¤   PGPGroupID¤ ¤   id,
5d1b51 ¤   PGPUserValue¤   userValue )
69bb36 {
e59372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
940085 ¤   PGPGroup *¤ ¤   group¤  = NULL;
c967c5 ¤
09b620 ¤   PGPValidateGroupSet( set );
4367c5 ¤
42558c ¤   err¤= sFindGroupByID( set, id, &group );
6ef1e7 ¤   if ( IsntPGPError( err ) )
cbc7a1 ¤   {
fa1270 ¤   ¤   group->userValue¤   = userValue;
439371 ¤   }
bc67c5 ¤
4bdeb7 ¤   return( err );
86efe6 }
05af5a
93af5a
0caf5a
e1af5a
70af5a
9a0335 /*____________________________________________________________________________
dd9129 ¤   Return TRUE if group1 contains group 2, either directly or in a subgroup.
8ff7f7 ____________________________________________________________________________*/
d56c2c ¤   static PGPBoolean
b81f2c sGroupContainsGroup(
7130d0 ¤   PGPGroupSetRef¤ set,
8fffd8 ¤   PGPGroupID¤ ¤   mainGroupID,
2ca8d6 ¤   PGPGroupID¤ ¤   subGroup )
7fbb36 {
fad591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
73cceb ¤   PGPGroup ·*¤¤   ¤   mainGroup¤  = NULL;
37d4b9 ¤   PGPBoolean¤ ¤   ¤   containsGroup¤  = FALSE;
87c1c0 ¤   PGPUInt32¤  ¤   ¤   index;
--5339 000ee61a59740100251 Page 26 of pgpGroups.c
2a67c5 ¤
9b95dd ¤   err¤= sFindGroupByID( set, mainGroupID, &mainGroup );
e48c1a ¤   pgpAssertNoErr( err );
c5054e ¤   if ( IsPGPError( err ) )
28e20d ¤   ¤   return( FALSE );
af9e96 ¤   if ( mainGroupID == subGroup )
55c7a1 ¤   {
ba7ece ¤   ¤   /* can't add a group to itself */
ca6392 ¤   ¤   return( TRUE );
4d9371 ¤   }
e067c5 ¤
68ce49 ¤   for( index = 0; index < mainGroup->numItems; ++index )
cbc7a1 ¤   {
6e5675 ¤   ¤   PGPGroupItem const *¤   item;
201b52 ¤   ¤
09c94c ¤   ¤   item¤   = &mainGroup->itemsArray[ index ];
0b652c ¤   ¤   if ( item->type == kPGPGroupItem_Group )
8b5b34 ¤   ¤   {
8e9cf6 ¤   ¤   ¤   if ( item->u.group.id == subGroup )
30f776 ¤   ¤   ¤   {
2753da ¤   ¤   ¤   ¤   containsGroup¤  = TRUE;
fdf622 ¤   ¤   ¤   ¤   break;
0fa3a6 ¤   ¤   ¤   }
afc119 ¤   ¤   ¤   else if ( sGroupContainsGroup( set, item->u.group.id, subGroup ) )
b5f776 ¤   ¤   ¤   {
8953da ¤   ¤   ¤   ¤   containsGroup¤  = TRUE;
71f622 ¤   ¤   ¤   ¤   break;
aba3a6 ¤   ¤   ¤   }
8f0fe4 ¤   ¤   }
8c9371 ¤   }
b367c5 ¤
13a883 ¤   return( containsGroup );
87efe6 }
31af5a
b1af5a
080335 /*____________________________________________________________________________
2dfd2c ¤   Add an item to the group. ·Caller must completely fill in the item
1dc510 ¤   before adding.
edf7f7 ____________________________________________________________________________*/
c7c744 ¤   PGPError
5fdb51 PGPAddItemToGroup(
6fa976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
9c619f ¤   PGPGroupItem const *¤   item,
891171 ¤   PGPGroupID¤ ¤   ¤   ¤   id )
b8bb36 {
3b9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
cc0085 ¤   PGPGroup *¤ ¤   group¤  = NULL;
f0e939 ¤   PGPUInt32¤  ¤   index;
7067c5 ¤
85b620 ¤   PGPValidateGroupSet( set );
4e0a11 ¤   PGPValidatePtr( item );
33cc32 ¤   PGPValidateParam( item->type == kPGPGroupItem_KeyID ||
d0e3ea ¤   ¤   item->type == kPGPGroupItem_Group );
c7af5a
192d65 ¤   /* verify that the group being added to exists */
85558c ¤   err¤= sFindGroupByID( set, id, &group );
19054e ¤   if ( IsPGPError( err ) )
29e55e ¤   ¤   return( err );
d867c5 ¤
0837b1 ¤   if ( item->type == kPGPGroupItem_Group )
10c7a1 ¤   {
6142c1 ¤   ¤   /* verify that if the group being added that exists */
d8708a ¤   ¤   PGPGroup *¤ itemGroup;
fd2225 ¤   ¤   err¤= sFindGroupByID( set, item->u.group.id, &itemGroup );
15be18 ¤   ¤   if ( IsPGPError( err ) )
a707bf ¤   ¤   ¤   return( err );
dc9371 ¤   }
c467c5 ¤
5cba6f ¤   /* verify that the group doesn't already contain this item */
34e9ed ¤   if ( sIsGroupMember( group, item, &index ) ·)
749192 ¤   ¤   return( kPGPError_ItemAlreadyExists );
ee67c5 ¤
--5211 0006f4408c640100251 Page 27 of pgpGroups.c
3b20b7 ¤   /* verify that a cycle won't be created by adding */
fccb3b ¤   if ( item->type == kPGPGroupItem_Group &&
800f4d ¤   ¤   sGroupContainsGroup( set, item->u.group.id, id ) )
96c7a1 ¤   {
634023 ¤   ¤   return( kPGPError_BadParams );
559371 ¤   }
f067c5 ¤
64d107 ¤   /* OK, all verification is now done */
b767c5 ¤
10f1e7 ¤   if ( IsntPGPError( err ) )
bec7a1 ¤   {
048fe3 ¤   ¤   PGPContextRef¤  context¤= set->context;
7aadd4 ¤   ¤   PGPSize¤¤   ¤   newSize;
ae1b52 ¤   ¤
b466f3 ¤   ¤   newSize¤= ( group->numItems + 1 ) * sizeof( PGPGroupItem );
6e0b59 ¤   ¤   /* add the new item */
1e6c74 ¤   ¤   err¤= pgpContextMemRealloc( context, (void **) &group->itemsArray,
c5411d ¤   ¤   ¤   ¤   newSize, 0);
ab1b52 ¤   ¤
d27d98 ¤   ¤   if ( IsntPGPError( err ) )
d05b34 ¤   ¤   {
82a536 ¤   ¤   ¤   (group->itemsArray)[ group->numItems ]¤ = *item;
93612b ¤   ¤   ¤   group->numItems++;
38f8b6 ¤   ¤   ¤   set->hasBeenModified¤   = TRUE;
5d0fe4 ¤   ¤   }
fb9371 ¤   }
3667c5 ¤
71deb7 ¤   return( err );
b5efe6 }
b02b85 ¤   ¤   ¤   ¤
99af5a
e70335 /*____________________________________________________________________________
5bcd63 ¤   This can't use an iterator, because it is used to create an iterator.
0af7f7 ____________________________________________________________________________*/
ecc744 ¤   PGPError
effdf2 PGPCountGroupItems(
92e19d ¤   PGPGroupSetRef¤ ¤   set,
483853 ¤   PGPGroupID ¤¤   ¤   id,
acb2b2 ¤   PGPBoolean¤ ¤   ¤   recursive,
c8411e ¤   PGPUInt32 *¤¤   ¤   outNumKeys,
17e49b ¤   PGPUInt32 *¤¤   ¤   outTotal )
21bb36 {
9126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
d4d48f ¤   PGPGroup *¤ group¤  = NULL;
901886 ¤   PGPUInt32¤  numItems¤   = 0;
8a7ddf ¤   PGPUInt32¤  numKeys¤¤   = 0;
b367c5 ¤
e4e772 ¤   if ( IsntNull( outNumKeys ) )
fcf582 ¤   ¤   *outNumKeys¤= 0;
24160d ¤   if ( IsntNull( outTotal ) )
68236d ¤   ¤   *outTotal¤  = 0;
37b620 ¤   PGPValidateGroupSet( set );
f467c5 ¤
fe2b18 ¤   err¤= sFindGroupByID( set, id, &group);
51f1e7 ¤   if ( IsntPGPError( err ) )
46c7a1 ¤   {
dd2518 ¤   ¤   PGPUInt32¤  index;
9e87c7 ¤   ¤   ¤
99fb71 ¤   ¤   /* account for all items in this group right here */
69061a ¤   ¤   numItems¤   += group->numItems;
2a1b52 ¤   ¤
add594 ¤   ¤   for (index = 0; index < group->numItems; ++index )
d75b34 ¤   ¤   {
284e0d ¤   ¤   ¤   PGPGroupItem const *item;
d387c7 ¤   ¤   ¤
5baf3b ¤   ¤   ¤   item¤   = &group->itemsArray[ index ];
87b831 ¤   ¤   ¤   if ( item->type == kPGPGroupItem_KeyID )
9ef776 ¤   ¤   ¤   {
df8df3 ¤   ¤   ¤   ¤   ++numKeys;
eea3a6 ¤   ¤   ¤   }
6bc65f ¤   ¤   ¤   else if ( recursive && item->type == kPGPGroupItem_Group )
6ff776 ¤   ¤   ¤   {
--1e0d 000a6f4cb0540100251 Page 28 of pgpGroups.c
84da48 ¤   ¤   ¤   ¤   PGPUInt32¤  tempTotal;
2193d0 ¤   ¤   ¤   ¤   PGPUInt32¤  tempKeys;
df2b85 ¤   ¤   ¤   ¤
5a102a ¤   ¤   ¤   ¤   err¤= PGPCountGroupItems( set, item->u.group.id, TRUE,
6e48e9 ¤   ¤   ¤   ¤   ¤   &tempKeys, &tempTotal );
1b869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
b014c3 ¤   ¤   ¤   ¤   ¤   break;
821065 ¤   ¤   ¤   ¤   numKeys¤¤   += tempKeys;
ae574d ¤   ¤   ¤   ¤   numItems¤   += tempTotal;
a8a3a6 ¤   ¤   ¤   }
b20fe4 ¤   ¤   }
5c9371 ¤   }
7067c5 ¤
68f1e7 ¤   if ( IsntPGPError( err ) )
ebc7a1 ¤   {
939df1 ¤   ¤   if ( IsntNull( outTotal ) )
ddacb2 ¤   ¤   ¤   *outTotal¤  = numItems;
2287c7 ¤   ¤   ¤
590801 ¤   ¤   if ( IsntNull( outNumKeys ) )
0755e3 ¤   ¤   ¤   *outNumKeys¤= numKeys;
9d9371 ¤   }
d767c5 ¤
23deb7 ¤   return( err );
8befe6 }
c0af5a
82af5a
a4af5a
38af5a
ecc744 ¤   PGPError
e42db5 PGPGetIndGroupItem(
1a30d0 ¤   PGPGroupSetRef¤ set,
119d22 ¤   PGPGroupID¤ ¤   ¤   id,
211959 ¤   PGPUInt32¤  ¤   ¤   index,
8d8905 ¤   PGPGroupItem *¤ ¤   item )
6fbb36 {
2c9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
fb0085 ¤   PGPGroup *¤ ¤   group¤  = NULL;
0167c5 ¤
820a11 ¤   PGPValidatePtr( item );
04b88c ¤   pgpClearMemory( item, sizeof( *item ) );
a0b620 ¤   PGPValidateGroupSet( set );
6367c5 ¤
bb2b18 ¤   err¤= sFindGroupByID( set, id, &group);
75f1e7 ¤   if ( IsntPGPError( err ) )
e8c7a1 ¤   {
4c084c ¤   ¤   if ( index < group->numItems )
7b5b34 ¤   ¤   {
95a8a8 ¤   ¤   ¤   *item¤  = group->itemsArray[ index ];
b30fe4 ¤   ¤   }
c40e1d ¤   ¤   else
425b34 ¤   ¤   {
effdcd ¤   ¤   ¤   err¤= kPGPError_BadParams;
aa0fe4 ¤   ¤   }
1e9371 ¤   }
dc67c5 ¤
2fdeb7 ¤   return( err );
f1efe6 }
14af5a
edaf5a
17c744 ¤   PGPError
907cc2 PGPSetIndGroupItemUserValue(
b730d0 ¤   PGPGroupSetRef¤ set,
bf1ced ¤   PGPGroupID¤ ¤   id,
8a31a0 ¤   PGPUInt32¤  ¤   index,
6c1b51 ¤   PGPUserValue¤   userValue )
00bb36 {
c19372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1b0085 ¤   PGPGroup *¤ ¤   group¤  = NULL;
c167c5 ¤
fcb620 ¤   PGPValidateGroupSet( set );
fa67c5 ¤
a62b18 ¤   err¤= sFindGroupByID( set, id, &group);
--fb53 00046b2deba40100251 Page 29 of pgpGroups.c
e5f1e7 ¤   if ( IsntPGPError( err ) )
5ac7a1 ¤   {
a6084c ¤   ¤   if ( index < group->numItems )
4d5b34 ¤   ¤   {
3a2660 ¤   ¤   ¤   group->itemsArray[ index ].userValue¤   = userValue;
e10fe4 ¤   ¤   }
0b0e1d ¤   ¤   else
c35b34 ¤   ¤   {
5dfdcd ¤   ¤   ¤   err¤= kPGPError_BadParams;
ca0fe4 ¤   ¤   }
289371 ¤   }
3f67c5 ¤
82deb7 ¤   return( err );
35efe6 }
7aaf5a
d60335 /*____________________________________________________________________________
beb3f5 ¤   An iterator is implemented by creating an array of pointers to the
f60928 ¤   elements to be iterated. ·This uses a modest amount of memory relative
8e1ce8 ¤   to the overall structure, and results in very fast iteration.
5967c5 ¤
50f755 ¤   Its drawbacks include the inability to change the overall structure
bce0a0 ¤   while iterating (at least in this implementation).
d0f7f7 ____________________________________________________________________________*/
1aaf5a
f569f8 typedef struct PGPGroupIter¤PGPGroupIter;
5d6243 struct PGPGroupIter
11bb36 {
4c71ef ¤   PGPGroupSetRef¤ ¤   ¤   set;
05dc7d ¤   const PGPGroupItem ·**¤ items;
8f74ab ¤   #define kBeforeFirstItemIndex¤  0xFFFFFFFF
ed8dd5 ¤   PGPUInt32¤  ¤   ¤   ¤   curIndex;
b03e09 ¤   PGPUInt32¤  ¤   ¤   ¤   numItems;
4a82f7 };
07af5a
57af5a
d80335 /*____________________________________________________________________________
bd40c9 ¤   Fill the iter->items array with pointers to all items in the group.
d1f7f7 ____________________________________________________________________________*/
e41964 ¤   static PGPUInt32
98e112 sCollectPointersForIter(
2714ca ¤   PGPGroupIter *¤ iter,
651ced ¤   PGPGroupID¤ ¤   id,
8f60a3 ¤   PGPBoolean¤ ¤   recursive,
482fbc ¤   PGPFlags¤   ¤   flags,
755c3f ¤   PGPUInt32¤  ¤   startSlot )
2cbb36 {
3eb320 ¤   PGPUInt32¤  ¤   ¤   nextSlot¤   = startSlot;
63c1c0 ¤   PGPUInt32¤  ¤   ¤   index;
0151ae ¤   PGPGroup const *¤   group¤  = NULL;
afd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f067c5 ¤
21f38d ¤   pgpAssert( IsntNull( iter ) );
9667c5 ¤
1ca71d ¤   if ( startSlot >= iter->numItems )
87c7a1 ¤   {
bfdb01 ¤   ¤   /* if we've found all the items we could be pointing after·
ff84cf ¤   ¤   the end of the array, but we shouldn't find any more items
266793 ¤   ¤   of the desired kind, so no point in continuing */
69193e ¤   ¤   return( startSlot );
6b9371 ¤   }
5667c5 ¤
f9313b ¤   err¤= sFindGroupByID( iter->set, id, (PGPGroup **)&group );
448c1a ¤   pgpAssertNoErr( err );
8767c5 ¤
719ca5 ¤   for( index = 0; index < group->numItems; ++index )
4ac7a1 ¤   {
36a99e ¤   ¤   const PGPGroupItem *¤   item;
4b1b52 ¤   ¤
787789 ¤   ¤   item¤   = &group->itemsArray[ index ];
28eb2a ¤   ¤   if ( item->type == kPGPGroupItem_KeyID )
ef5b34 ¤   ¤   {
46d8f8 ¤   ¤   ¤   if ( ( flags & kPGPGroupIterFlags_Keys) != 0 )
--271c 000c966c6bf40100251 Page 30 of pgpGroups.c
99f776 ¤   ¤   ¤   {
da09c2 ¤   ¤   ¤   ¤   iter->items[ nextSlot ]¤= item;
dc6c90 ¤   ¤   ¤   ¤   ++nextSlot;
08a3a6 ¤   ¤   ¤   }
040fe4 ¤   ¤   }
790e1d ¤   ¤   else
eb5b34 ¤   ¤   {
3d1103 ¤   ¤   ¤   pgpAssert( item->type == kPGPGroupItem_Group );
d3f0c9 ¤   ¤   ¤   if ( ( flags & kPGPGroupIterFlags_Groups) != 0 )
81f776 ¤   ¤   ¤   {
7109c2 ¤   ¤   ¤   ¤   iter->items[ nextSlot ]¤= item;
b46c90 ¤   ¤   ¤   ¤   ++nextSlot;
1ea3a6 ¤   ¤   ¤   }
981b52 ¤   ¤
f6762e ¤   ¤   ¤   if ( recursive )
edf776 ¤   ¤   ¤   {
b0fe5a ¤   ¤   ¤   ¤   nextSlot¤   = sCollectPointersForIter( iter,
c8fea3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->u.group.id, TRUE, flags, nextSlot );
24a3a6 ¤   ¤   ¤   }
bf0fe4 ¤   ¤   }
5d9371 ¤   }
5367c5 ¤
802e38 ¤   return( nextSlot );
27efe6 }
ebaf5a
23af5a
c5af5a
8866dd ¤   static PGPError
96e080 sInitIter(
99e19d ¤   PGPGroupSetRef¤ ¤   set,
de9d22 ¤   PGPGroupID¤ ¤   ¤   id,
8cb493 ¤   PGPFlags¤   ¤   ¤   flags,
5cbb52 ¤   PGPGroupIter *¤ ¤   iter )
08bb36 {
b726d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
b2f7cd ¤   PGPUInt32¤  numKeys;
7b0239 ¤   PGPUInt32¤  numItems;
4bfff8 ¤   Boolean¤¤   recursive;
da4231 ¤   PGPGroupID¤ actualID¤   = id;
4b67c5 ¤
552768 ¤   recursive¤  = (flags & kPGPGroupIterFlags_Recursive) != 0;
1a67c5 ¤
d7f5d6 ¤   pgpClearMemory( iter, sizeof( *iter ) );
c067c5 ¤
81f1e7 ¤   if ( IsntPGPError( err ) )
7bc7a1 ¤   {
e59259 ¤   ¤   iter->set¤  ¤   = set;
a3f0b9 ¤   ¤   iter->items¤¤   = NULL;
3baf14 ¤   ¤   iter->curIndex¤ = kBeforeFirstItemIndex;
bdebd2 ¤   ¤   err¤= PGPCountGroupItems( set, actualID,
3ce977 ¤   ¤   ¤   ¤   recursive, &numKeys, &numItems );
3b7d98 ¤   ¤   if ( IsntPGPError( err ) )
025b34 ¤   ¤   {
8a468a ¤   ¤   ¤   iter->numItems¤ = 0;
f9d8f8 ¤   ¤   ¤   if ( ( flags & kPGPGroupIterFlags_Keys) != 0 )
a7ba5c ¤   ¤   ¤   ¤   iter->numItems¤ += numKeys;
c8f0c9 ¤   ¤   ¤   if ( ( flags & kPGPGroupIterFlags_Groups) != 0 )
a1a8b6 ¤   ¤   ¤   ¤   iter->numItems¤ += (numItems - numKeys);
4987c7 ¤   ¤   ¤
b71af5 ¤   ¤   ¤   /* create an array of pointers to the items */
6ae1e3 ¤   ¤   ¤   iter->items¤= (const PGPGroupItem **)pgpContextMemAlloc(
5d09e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   set->context,
6e4900 ¤   ¤   ¤   ¤   ¤   ¤   ¤   iter->numItems * sizeof( iter->items[ 0 ] ),
185635 ¤   ¤   ¤   ¤   ¤   ¤   ¤   0);
f715d7 ¤   ¤   ¤   if ( IsNull( iter->items ) )
2014f2 ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
f90fe4 ¤   ¤   }
d01b52 ¤   ¤
ba7d98 ¤   ¤   if ( IsntPGPError( err ) )
985b34 ¤   ¤   {
4a0a4b ¤   ¤   ¤   PGPUInt32¤  nextSlot;
c987c7 ¤   ¤   ¤
--7a24 000f18eec0540100251 Page 31 of pgpGroups.c
2547ed ¤   ¤   ¤   /* collect all the pointers we need */
ddd8ef ¤   ¤   ¤   nextSlot¤   = sCollectPointersForIter( iter,
c6285a ¤   ¤   ¤   ¤   ¤   ¤   ¤   actualID, recursive, flags, 0);
ab38a3 ¤   ¤   ¤   pgpAssert( nextSlot == iter->numItems ||
e07bf2 ¤   ¤   ¤   ¤   ¤   nextSlot == iter->numItems + 1);
b50fe4 ¤   ¤   }
b69371 ¤   }
6867c5 ¤
8edeb7 ¤   return( err );
04efe6 }
85af5a
92af5a
5dc744 ¤   PGPError
c5c69b PGPNewGroupItemIter(
48a976 ¤   PGPGroupSetRef¤ ¤   ¤   set,
de4232 ¤   PGPGroupID¤ ¤   ¤   ¤   id,
1229e6 ¤   PGPFlags¤   ¤   ¤   ¤   flags,
28bb4c ¤   PGPGroupItemIterRef *¤  iterOut )
f5bb36 {
39d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
80a8f8 ¤   PGPGroupIter *¤ ¤   iter¤   = NULL;
6667c5 ¤
559e41 ¤   PGPValidatePtr( iterOut );
a29b2a ¤   *iterOut¤   = NULL;
57b620 ¤   PGPValidateGroupSet( set );
17407b ¤   PGPValidateParam( (flags & kPGPGroupIterFlags_AllItems) != 0 );
27db69 ¤   PGPValidateParam( (flags & ~ kPGPGroupIterFlags_AllRecursive) == 0 );
7f67c5 ¤
8a10db ¤   iter¤   = (PGPGroupIter *)pgpContextMemAlloc( set->context,
4fd555 ¤   ¤   ¤   sizeof( *iter ), kPGPMemoryMgrFlags_Clear );
9f56c0 ¤   if ( IsNull( iter ) )
ae17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
5ff1e7 ¤   if ( IsntPGPError( err ) )
aec7a1 ¤   {
cc3f09 ¤   ¤   err¤= sInitIter( set, id, flags, iter );
66be18 ¤   ¤   if ( IsPGPError( err ) )
bd5b34 ¤   ¤   {
2b783a ¤   ¤   ¤   pgpContextMemFree( set->context, iter );
97126e ¤   ¤   ¤   iter¤   = NULL;
5e0fe4 ¤   ¤   }
919371 ¤   }
ff67c5 ¤
8f89cb ¤   *iterOut¤   = iter;
4ddeb7 ¤   return( err );
1eefe6 }
4faf5a
c8af5a
1ec744 ¤   PGPError
1f1d33 PGPFreeGroupItemIter( PGPGroupItemIterRef iter )
38bb36 {
7d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
9a67c5 ¤
0552ed ¤   PGPValidateParam( IsntNull( iter ) );
f29959 ¤   if ( IsntNull( iter->items ) )
44c7a1 ¤   {
8a2171 ¤   ¤   err¤= pgpContextMemFree( iter->set->context,
c4d11b ¤   ¤   ¤   ¤   (void *) iter->items );
7235d5 ¤   ¤   iter->items¤= NULL;
0a9371 ¤   }
5167c5 ¤
c3f1e7 ¤   if ( IsntPGPError( err ) )
7ec7a1 ¤   {
ad9aca ¤   ¤   err¤= pgpContextMemFree( iter->set->context, iter );
ea9371 ¤   }
d067c5 ¤
68deb7 ¤   return( err );
32efe6 }
afaf5a
69af5a
89af5a
1daf5a
f10335 /*____________________________________________________________________________
--d3b6 0005513df0140100251 Page 32 of pgpGroups.c
3721c5 ¤   Returns kPGPError_EndOfIteration when done
ccf7f7 ____________________________________________________________________________*/
9cc744 ¤   PGPError
0b716e PGPGroupItemIterNext(
52651d ¤   PGPGroupItemIterRef¤iter,
ce8905 ¤   PGPGroupItem *¤ ¤   item )
52bb36 {
c126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
5567c5 ¤
9b0a11 ¤   PGPValidatePtr( item );
0f52ed ¤   PGPValidateParam( IsntNull( iter ) );
0a4da2 ¤   PGPValidateGroupSet( iter->set );
e867c5 ¤
e1db55 ¤   pgpDebugWhackMemory( item, sizeof(*item) );
4367c5 ¤
524b78 ¤   if ( iter->curIndex == iter->numItems )
53c7a1 ¤   {
9d9701 ¤   ¤   /* already at end of list */
6488e9 ¤   ¤   err¤= kPGPError_EndOfIteration;
ce9371 ¤   }
d50e24 ¤   else
e8c7a1 ¤   {
116d72 ¤   ¤   if ( iter->curIndex == kBeforeFirstItemIndex )
558adc ¤   ¤   ¤   iter->curIndex¤ = 0;
ee0e1d ¤   ¤   else
763eee ¤   ¤   ¤   iter->curIndex¤ += 1;
8987c7 ¤   ¤   ¤
6c5328 ¤   ¤   if ( iter->curIndex == iter->numItems )
31008f ¤   ¤   ¤   err¤= kPGPError_EndOfIteration;
5b0e1d ¤   ¤   else
0c757c ¤   ¤   ¤   *item¤  = *(iter->items[ iter->curIndex ]);
949371 ¤   }
7f67c5 ¤
8267c5 ¤
08deb7 ¤   return( err );
e3efe6 }
efaf5a
69af5a
4eaf5a
36af5a
19af5a
ea66dd ¤   static PGPError
59078d sFindGroupByName(
7a30d0 ¤   PGPGroupSetRef¤ set,
d8d663 ¤   const char *¤   name,
e3fa0d ¤   PGPGroupID *¤   outID )
7bbb36 {
fcc7f9 ¤   PGPUInt32¤  index;
935520 ¤   PGPError¤   err¤= kPGPError_ItemNotFound;
8867c5 ¤
ff20a9 ¤   *outID¤ = kPGPInvalidGroupID;
8d67c5 ¤
a0f0a0 ¤   for( index = 0; index < set->numGroups; ++index )
2cc7a1 ¤   {
4a8650 ¤   ¤   PGPGroup const *¤   group;
961b52 ¤   ¤
f97cdb ¤   ¤   group¤  = &set->groupArray[ index ];
7799f4 ¤   ¤   if ( pgpCompareStringsIgnoreCase( group->name, name ) == 0 )
b15b34 ¤   ¤   {
84b207 ¤   ¤   ¤   *outID¤ = group->id;
325403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
05cdcb ¤   ¤   ¤   break;
df0fe4 ¤   ¤   }
4e9371 ¤   }
7b67c5 ¤
7edeb7 ¤   return( err );
0cefe6 }
f3af5a
54af5a
96af5a
1a0335 /*____________________________________________________________________________
55ef59 ¤   Recursively add a group into the destination set, merging all its
--ce98 00069c459a540100251 Page 33 of pgpGroups.c
71ec40 ¤   entries that don't exist in the destination.
baf7f7 ____________________________________________________________________________*/
f566dd ¤   static PGPError
8cafa3 sAddGroupIntoDifferentSet(
c51158 ¤   PGPGroup const *¤   srcGroup,
7693af ¤   PGPGroupSetRef¤ ¤   destSet,
162d0f ¤   PGPGroupID *¤   ¤   resultID )
c2bb36 {
0430d4 ¤   PGPError¤   err¤¤   = kPGPError_NoErr;
982b3f ¤   PGPGroupID¤ destID¤ = kPGPInvalidGroupID;
bb67c5 ¤
97670f ¤   /* first make sure the group exists in destination set */
f95855 ¤   if ( sFindGroupByName( destSet,
0c92aa ¤   ¤   ¤   srcGroup->name, &destID ) == kPGPError_ItemNotFound )
82c7a1 ¤   {
8c354c ¤   ¤   err¤= PGPNewGroup( destSet,
c33f83 ¤   ¤   ¤   ¤   srcGroup->name, srcGroup->description, &destID);
da9371 ¤   }
ecf1e7 ¤   if ( IsntPGPError( err ) )
4ec7a1 ¤   {
cf0e00 ¤   ¤   PGPUInt32¤  itemIndex;
ed67c5 ¤
9d81dd ¤   ¤   /* loop over all items in srcGroup */
ffc8b6 ¤   ¤   for( itemIndex = 0; itemIndex < srcGroup->numItems; ++itemIndex )
2c5b34 ¤   ¤   {
a46a9b ¤   ¤   ¤   PGPGroupItem const *¤   item;
5187c7 ¤   ¤   ¤
992720 ¤   ¤   ¤   item¤   = &srcGroup->itemsArray[ itemIndex ];
603637 ¤   ¤   ¤   if ( item->type == kPGPGroupItem_Group )
fdf776 ¤   ¤   ¤   {
daffa2 ¤   ¤   ¤   ¤   /* recursively add subgroup */
34c0f6 ¤   ¤   ¤   ¤   PGPGroup *¤ ¤   subGroup;
af49cb ¤   ¤   ¤   ¤   PGPGroupID¤ ¤   newID;
fe0d61 ¤   ¤   ¤   ¤   PGPGroupItem¤   newItem;
762b85 ¤   ¤   ¤   ¤
9681a0 ¤   ¤   ¤   ¤   err¤= sFindGroupByID( srcGroup->set,
0cf924 ¤   ¤   ¤   ¤   ¤   ¤   ¤   item->u.group.id, &subGroup );
0d869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
b514c3 ¤   ¤   ¤   ¤   ¤   break;
d0ae30 ¤   ¤   ¤   ¤   ¤
d1a19c ¤   ¤   ¤   ¤   err¤= sAddGroupIntoDifferentSet( subGroup, destSet, &newID );
90869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
2a14c3 ¤   ¤   ¤   ¤   ¤   break;
1aae30 ¤   ¤   ¤   ¤   ¤
3b0827 ¤   ¤   ¤   ¤   /* now add the newly created group to this group */
900c45 ¤   ¤   ¤   ¤   newItem.type¤   ¤   = kPGPGroupItem_Group;
bea589 ¤   ¤   ¤   ¤   newItem.userValue¤  = 0;
37f81b ¤   ¤   ¤   ¤   newItem.u.group.id¤ = newID;
afe863 ¤   ¤   ¤   ¤   item¤   ¤   ¤   ¤   = &newItem;
99a3a6 ¤   ¤   ¤   }
0087c7 ¤   ¤   ¤
5da9d7 ¤   ¤   ¤   /* add the key or group to dest set if it doesn't already exist */
85de3a ¤   ¤   ¤   err¤= PGPAddItemToGroup( destSet, item, destID );
860bb6 ¤   ¤   ¤   if ( err == kPGPError_ItemAlreadyExists )
8c15f0 ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
2a2b85 ¤   ¤   ¤   ¤
ca8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
70f622 ¤   ¤   ¤   ¤   break;
d80fe4 ¤   ¤   }
f59371 ¤   }
4c67c5 ¤
f7bc17 ¤   *resultID¤  = destID;
4ddeb7 ¤   return( err );
d7efe6 }
29af5a
8faf5a
ae0335 /*____________________________________________________________________________
4b2321 ¤   Merge a group from one set into another. ·If a group with the same name
ed54d8 ¤   exists, items found in the source set are all added (if not already there)
b5a839 ¤   into the destination set.
7b67c5 ¤
69abf2 ¤   Recursively adds everything.
--8e9f 000072deb5240100251 Page 34 of pgpGroups.c
eaf7f7 ____________________________________________________________________________*/
ccc744 ¤   PGPError
441da6 PGPMergeGroupIntoDifferentSet(
a7acb3 ¤   PGPGroupSetRef¤ ¤   fromSet,
ceac5c ¤   PGPGroupID¤ ¤   ¤   fromID,
de56a4 ¤   PGPGroupSetRef¤ ¤   toSet )
4dbb36 {
60d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
5a51ae ¤   PGPGroup const *¤   group¤  = NULL;
e467c5 ¤
d02e2e ¤   PGPValidateGroupSet( fromSet );
a195df ¤   PGPValidateGroupSet( toSet );
0b67c5 ¤
d3481e ¤   err¤= sFindGroupByID( fromSet, fromID, (PGPGroup **)&group );
7df1e7 ¤   if ( IsntPGPError( err ) )
8ec7a1 ¤   {
d59d5b ¤   ¤   PGPGroupID¤ newID;
b81b52 ¤   ¤
8f5293 ¤   ¤   err¤= sAddGroupIntoDifferentSet( group, toSet, &newID );
4e9371 ¤   }
6067c5 ¤
9adeb7 ¤   return( err );
0eefe6 }
49af5a
e4af5a
16c744 ¤   PGPError
eae34f PGPMergeGroupSets(
c6e458 ¤   PGPGroupSetRef¤ fromSet,
a90443 ¤   PGPGroupSetRef¤ intoSet )
a0bb36 {
5cc7f9 ¤   PGPUInt32¤  index;
dc26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
ee67c5 ¤
ed2e2e ¤   PGPValidateGroupSet( fromSet );
4964b3 ¤   PGPValidateGroupSet( intoSet );
0a67c5 ¤
cc5d7f ¤   for( index = 0; index < fromSet->numGroups; ++index )
46c7a1 ¤   {
8edc7f ¤   ¤   PGPGroupID¤ fromID;
aa1b52 ¤   ¤
c73b72 ¤   ¤   err¤= PGPGetIndGroupID( fromSet, index, &fromID );
adbe18 ¤   ¤   if ( IsPGPError( err ) )
42cdcb ¤   ¤   ¤   break;
0c1b52 ¤   ¤
a9c670 ¤   ¤   err¤= PGPMergeGroupIntoDifferentSet( fromSet, fromID, intoSet );
23be18 ¤   ¤   if ( IsPGPError( err ) )
1ccdcb ¤   ¤   ¤   break;
cb9371 ¤   }
2167c5 ¤
98deb7 ¤   return( err );
c5efe6 }
27af5a
edc744 ¤   PGPError
4b53ea PGPCopyGroupSet(
7ecceb ¤   PGPGroupSetRef¤ sourceSet,
ec5295 ¤   PGPGroupSetRef¤ *destSet)
9bbb36 {
bc61e0 ¤   PGPError¤   err;
3d67c5 ¤
fc1f0f ¤   PGPValidateGroupSet( sourceSet );
b8d783 ¤   PGPValidatePtr( destSet );
aa67c5 ¤
e1846f ¤   err = PGPNewGroupSet( PGPGetGroupSetContext( sourceSet ), destSet );
e1b1f0 ¤   if( IsntPGPError( err ) )
74c7a1 ¤   {
d613da ¤   ¤   err = PGPMergeGroupSets( sourceSet, *destSet );
22d223 ¤   ¤   if( IsPGPError( err ) )
745b34 ¤   ¤   {
086a60 ¤   ¤   ¤   (void) PGPFreeGroupSet( *destSet );
dae427 ¤   ¤   ¤   *destSet = kInvalidPGPGroupSetRef;
fe0fe4 ¤   ¤   }
079371 ¤   }
--9388 000d25236a540100251 Page 35 of pgpGroups.c
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
e2a7b1 #if PGP_DEBUG /* [ */
d00ccc #if PGP_MACINTOSH
e5af5a
5266dd ¤   static PGPError
29cd6a sTestCreate(
a6a1bc ¤   PGPContextRef¤  ¤   context,
8692a3 ¤   PGPGroupSetRef *¤   outSet,
a1977a ¤   PGPGroupID *¤   ¤   outMaster )
72bb36 {
859372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
b12d59 ¤   PGPGroupSetRef¤ set¤= NULL;
1167c5 ¤
c7c081 ¤   *outSet¤¤   = NULL;
0650e4 ¤   *outMaster¤ = kPGPInvalidGroupID;
4087c7 ¤   ¤   ¤
2d6fbd ¤   err¤= PGPNewGroupSet( context, &set );
16f1e7 ¤   if ( IsntPGPError( err ) )
7ac7a1 ¤   {
1cfd11 ¤   ¤   PGPUInt32¤  ¤   index;
f1dc4d ¤   ¤   PGPUInt32¤  ¤   kNumTestGroups¤ = 500;
816989 ¤   ¤   PGPBoolean¤ ¤   needsCommit;
7ccc3a ¤   ¤   PGPGroupItem¤   item;
ac7eb8 ¤   ¤   PGPGroupID¤ ¤   masterID;
d54e4d ¤   ¤   PGPUInt32¤  ¤   numKeys;
c18688 ¤   ¤   PGPUInt32¤  ¤   numItems;
f61b52 ¤   ¤
18daa6 ¤   ¤   *outSet¤= set;
141b52 ¤   ¤
60d219 ¤   ¤   needsCommit¤= PGPGroupSetNeedsCommit( set );
d7d550 ¤   ¤   pgpAssert( needsCommit );
8487c7 ¤   ¤   ¤
d154a8 ¤   ¤   for( index = 0; index < kNumTestGroups; ++index )
cc5b34 ¤   ¤   {
f78973 ¤   ¤   ¤   PGPGroupID¤ newID;
029df6 ¤   ¤   ¤   Str255¤ ¤   pStr;
0e3b82 ¤   ¤   ¤   char¤   ¤   name[ 256 ];
4987c7 ¤   ¤   ¤
edbe00 ¤   ¤   ¤   NumToString( index, pStr );
59e872 ¤   ¤   ¤   PToCString( pStr, name );
0d87c7 ¤   ¤   ¤
658350 ¤   ¤   ¤   err¤= PGPNewGroup( set, name, "test group", &newID );
14847c ¤   ¤   ¤   if ( IsPGPError( err ))
31f622 ¤   ¤   ¤   ¤   break;
342b85 ¤   ¤   ¤   ¤
30d29b ¤   ¤   ¤   /* add a key to the gruop */
021cc4 ¤   ¤   ¤   pgpClearMemory( &item, sizeof( item ));
c7eb99 ¤   ¤   ¤   item.type¤  = kPGPGroupItem_KeyID;
93b074 ¤   ¤   ¤   err¤= PGPAddItemToGroup( set, &item, newID );
3b847c ¤   ¤   ¤   if ( IsPGPError( err ))
eef622 ¤   ¤   ¤   ¤   break;
cd0fe4 ¤   ¤   }
ff1b52 ¤   ¤
a0c6b9 ¤   ¤   /* add all existing groups to the master group */
027d98 ¤   ¤   if ( IsntPGPError( err ) )
165b34 ¤   ¤   {
017ee0 ¤   ¤   ¤   PGPUInt32¤  numGroups;
6d87c7 ¤   ¤   ¤
efff83 ¤   ¤   ¤   err¤= PGPCountGroupsInSet( set, &numGroups );
62144d ¤   ¤   ¤   pgpAssertNoErr( err );
9787c7 ¤   ¤   ¤
253c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
c0f776 ¤   ¤   ¤   {
9833ae ¤   ¤   ¤   ¤   err¤= PGPNewGroup( set, "master group",
41e24b ¤   ¤   ¤   ¤   ¤   ¤   ¤   "contains all the other groups",
d42ea7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &masterID);
8055be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
8da3a6 ¤   ¤   ¤   }
d21b52 ¤   ¤
--ced6 0006472056840100251 Page 36 of pgpGroups.c
543c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
28f776 ¤   ¤   ¤   {
568d10 ¤   ¤   ¤   ¤   *outMaster¤ = masterID;
c42b85 ¤   ¤   ¤   ¤
b28e00 ¤   ¤   ¤   ¤   for( index = 0; index < numGroups; ++index )
7f72c3 ¤   ¤   ¤   ¤   {
a4e00a ¤   ¤   ¤   ¤   ¤   PGPGroupID¤ id;
36ae30 ¤   ¤   ¤   ¤   ¤
82e03f ¤   ¤   ¤   ¤   ¤   err¤= PGPGetIndGroupID( set, index, &id);
e95bf2 ¤   ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
72c94f ¤   ¤   ¤   ¤   ¤   if ( IsPGPError( err ))
b800eb ¤   ¤   ¤   ¤   ¤   ¤   break;
7294aa ¤   ¤   ¤   ¤   ¤   ¤
4e4d56 ¤   ¤   ¤   ¤   ¤   item.type¤  ¤   = kPGPGroupItem_Group;
f76a31 ¤   ¤   ¤   ¤   ¤   item.u.group.id¤= id;
e35eee ¤   ¤   ¤   ¤   ¤   err¤= PGPAddItemToGroup( set, &item, masterID );
995bf2 ¤   ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
11c94f ¤   ¤   ¤   ¤   ¤   if ( IsPGPError( err ))
6e00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
3c2613 ¤   ¤   ¤   ¤   }
3387c7 ¤   ¤   ¤
7b3227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
ef72c3 ¤   ¤   ¤   ¤   {
e0133c ¤   ¤   ¤   ¤   ¤   err¤= PGPCountGroupItems( set, masterID, TRUE,
42e698 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &numKeys, &numItems );
955bf2 ¤   ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
1260b8 ¤   ¤   ¤   ¤   ¤   pgpAssert( numItems - numKeys == numGroups );
ea2613 ¤   ¤   ¤   ¤   }
d4a3a6 ¤   ¤   ¤   }
990fe4 ¤   ¤   }
471b52 ¤   ¤
1cbe18 ¤   ¤   if ( IsPGPError( err ) )
695b34 ¤   ¤   {
ea7f45 ¤   ¤   ¤   PGPFreeGroupSet( set );
28b58a ¤   ¤   ¤   *outSet¤= NULL;
ce0fe4 ¤   ¤   }
149371 ¤   }
d3deb7 ¤   return( err );
58efe6 }
4daf5a
d1af5a
8966dd ¤   static PGPError
06a0ad sIteratorTest(
14e19d ¤   PGPGroupSetRef¤ ¤   set,
42012f ¤   PGPGroupID¤ ¤   ¤   id )
a8bb36 {
bdd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
f2bd84 ¤   PGPGroupItemIterRef¤iter;
65ff14 ¤   PGPGroupItem¤   ¤   item;
7267c5 ¤
ee305f ¤   /* test iterators */
37820a ¤   err¤= PGPNewGroupItemIter( set, id, kPGPGroupIterFlags_AllItems, &iter );
4a8c1a ¤   pgpAssertNoErr( err );
2b6ab5 ¤   while ( IsntPGPError( err = PGPGroupItemIterNext( iter, &item ) ) )
53c7a1 ¤   {
958ac5 ¤   ¤   /* just iterate through all */
139371 ¤   }
fa766b ¤   pgpAssert( err == kPGPError_EndOfIteration );
19d780 ¤   err¤= PGPFreeGroupItemIter( iter );
308c1a ¤   pgpAssertNoErr( err );
79af5a
486ad0 ¤   /* now do it recursively */
ac319d ¤   err¤= PGPNewGroupItemIter( set, id,
a0a23a ¤   ¤   ¤   ¤   kPGPGroupIterFlags_AllRecursive, &iter);
ce8c1a ¤   pgpAssertNoErr( err );
646ab5 ¤   while ( IsntPGPError( err = PGPGroupItemIterNext( iter, &item ) ) )
17c7a1 ¤   {
518ac5 ¤   ¤   /* just iterate through all */
d69371 ¤   }
33766b ¤   pgpAssert( err == kPGPError_EndOfIteration );
b3d780 ¤   err¤= PGPFreeGroupItemIter( iter );
648c1a ¤   pgpAssertNoErr( err );
--83c7 000537f9bd540100251 Page 37 of pgpGroups.c
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
40af5a
f966dd ¤   static PGPError
50d4f3 sSaveRestoreTest( PGPGroupSetRef ¤  set )
e1bb36 {
8b6403 ¤   FSSpec¤ ¤   ¤   fsSpec;
e1bc74 ¤   PGPFileSpecRef¤ fileSpec¤   = NULL;
6c3ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
000411 ¤   PGPContextRef¤  context¤¤   = PGPGetGroupSetContext( set );
5767c5 ¤
8c0ccc #if PGP_MACINTOSH
f16574 ¤   pgpAssert( PGPGroupSetNeedsCommit( set ) );
edaba5 ¤   FSMakeFSSpec( -1, fsRtDirID, "\pGroups Test", &fsSpec );
69cd1b ¤   err¤= PGPNewFileSpecFromFSSpec( context, &fsSpec, &fileSpec );
d68c1a ¤   pgpAssertNoErr( err );
0fdb21 #else
9e2fa3 ¤   err¤= kPGPError_FileNotFound;
197454 #endif
8caf5a
05f1e7 ¤   if ( IsntPGPError( err ) )
433793 ¤   ¤   err¤= PGPSaveGroupSetToFile( set, fileSpec );
f38c1a ¤   pgpAssertNoErr( err );
f0f1e7 ¤   if ( IsntPGPError( err ) )
a2c7a1 ¤   {
62645b ¤   ¤   PGPGroupSetRef¤ tempSet;
991b52 ¤   ¤
2df313 ¤   ¤   err¤= PGPNewGroupSetFromFile( context, fileSpec, &tempSet );
999832 ¤   ¤   pgpAssertNoErr( err );
501b52 ¤   ¤
6fb975 ¤   ¤   err¤= PGPFreeGroupSet( tempSet );
1a9832 ¤   ¤   pgpAssertNoErr( err );
b79371 ¤   }
75af5a
a0344a ¤   PGPFreeFileSpec( fileSpec );
e767c5 ¤
4bdeb7 ¤   return( err );
89efe6 }
b2af5a
5366dd ¤   static PGPError
31effb sMergeTest( PGPGroupSetRef set )
0ebb36 {
d39372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1852a4 ¤   PGPGroupSetRef¤ toSet;
f9ce4e ¤   PGPUInt32¤  ¤   numGroups;
5be939 ¤   PGPUInt32¤  ¤   index;
a067c5 ¤
2ff21a ¤   /* copy the entire group into another group */
be52f5 ¤   err¤= PGPCountGroupsInSet( set, &numGroups );
368c1a ¤   pgpAssertNoErr( err );
70f1e7 ¤   if ( IsntPGPError( err ) )
41c7a1 ¤   {
eaa2cb ¤   ¤   err¤= PGPNewGroupSet( PGPGetGroupSetContext(set), &toSet );
599832 ¤   ¤   pgpAssertNoErr( err );
337d98 ¤   ¤   if ( IsntPGPError( err ) )
dc5b34 ¤   ¤   {
7ba8b5 ¤   ¤   ¤   for( index = 0; index < numGroups; ++index )
d3f776 ¤   ¤   ¤   {
f96bf6 ¤   ¤   ¤   ¤   PGPGroupID¤ id;
bb2b85 ¤   ¤   ¤   ¤
850018 ¤   ¤   ¤   ¤   err¤= PGPGetIndGroupID( set, index, &id );
8355be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
bf869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
5814c3 ¤   ¤   ¤   ¤   ¤   break;
c12b85 ¤   ¤   ¤   ¤
a078b5 ¤   ¤   ¤   ¤   err¤= PGPMergeGroupIntoDifferentSet( set, id, toSet );
a155be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
a8869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
2314c3 ¤   ¤   ¤   ¤   ¤   break;
53a3a6 ¤   ¤   ¤   }
--ebf6 0000c222eec40100251 Page 38 of pgpGroups.c
213179 ¤   ¤   ¤   err¤= PGPFreeGroupSet( toSet );
5e144d ¤   ¤   ¤   pgpAssertNoErr( err );
e90fe4 ¤   ¤   }
b09371 ¤   }
e967c5 ¤
32deb7 ¤   return( err );
baefe6 }
52af5a
12af5a
9d66dd ¤   static PGPError
00c0ba sDeleteTest( PGPGroupSetRef set )
e8bb36 {
3026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
8bc7f9 ¤   PGPUInt32¤  index;
4de6b7 ¤   PGPUInt32¤  numGroups;
b467c5 ¤
e852f5 ¤   err¤= PGPCountGroupsInSet( set, &numGroups );
de67c5 ¤
81949d ¤   for( index = 0; index < numGroups; ++index )
f7c7a1 ¤   {
f830cd ¤   ¤   PGPGroupID¤ id;
821b52 ¤   ¤
a2a3fc ¤   ¤   err¤= PGPGetIndGroupID( set, 0, &id );
119832 ¤   ¤   pgpAssertNoErr( err );
4a7d98 ¤   ¤   if ( IsntPGPError( err ) )
435b34 ¤   ¤   {
5a8852 ¤   ¤   ¤   err¤= PGPDeleteGroup( set, id );
3a144d ¤   ¤   ¤   pgpAssertNoErr( err );
c10fe4 ¤   ¤   }
989371 ¤   }
badeb7 ¤   return( err );
b7efe6 }
0daf5a
f6af5a
a266dd ¤   static PGPError
f33abb sMiscTest( PGPGroupSetRef set )
21bb36 {
d826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
614a39 ¤   PGPGroupID¤ id;
48e6b7 ¤   PGPUInt32¤  numGroups;
4067c5 ¤
ed52f5 ¤   err¤= PGPCountGroupsInSet( set, &numGroups );
1e8c1a ¤   pgpAssertNoErr( err );
13f1e7 ¤   if ( IsntPGPError( err ) )
f1c7a1 ¤   {
fbfd11 ¤   ¤   PGPUInt32¤  ¤   index;
bcf489 ¤   ¤   PGPGroupInfo¤   info;
f11b52 ¤   ¤
7dc786 ¤   ¤   for( index = 0; index < numGroups; ++index )
ac5b34 ¤   ¤   {
1f7b4e ¤   ¤   ¤   err¤= PGPGetIndGroupID( set, 0, &id );
e8cd85 ¤   ¤   ¤   if (IsntPGPError( err ) )
32f776 ¤   ¤   ¤   {
9986f0 ¤   ¤   ¤   ¤   err¤= PGPGetGroupInfo( set, id, &info );
4c55be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
65a3a6 ¤   ¤   ¤   }
f00fe4 ¤   ¤   }
e19371 ¤   }
9667c5 ¤
11deb7 ¤   return( err );
93efe6 }
24af5a
896d52 ¤   void
0df82c TestGroups()
abbb36 {
92e849 ¤   PGPGroupSetRef¤ set;
bdfb19 ¤   PGPError¤   ¤   err;
c08a97 ¤   PGPContextRef¤  context;
8c67c5 ¤
ad9041 ¤   err¤= PGPNewContext( kPGPsdkAPIVersion, &context );
c6f1e7 ¤   if ( IsntPGPError( err ) )
0cc7a1 ¤   {
--90a5 001404dc0ec40100251 Page 39 of pgpGroups.c
ab1d28 ¤   ¤   PGPGroupID¤ ¤   ¤   masterID;
a787c7 ¤   ¤   ¤
5076b0 ¤   ¤   err¤= sTestCreate( context, &set, &masterID );
367d98 ¤   ¤   if ( IsntPGPError( err ) )
4e5b34 ¤   ¤   {
48b4a1 ¤   ¤   ¤   err¤= sIteratorTest( set, masterID );
28144d ¤   ¤   ¤   pgpAssertNoErr( err );
7d87c7 ¤   ¤   ¤
69cd85 ¤   ¤   ¤   if (IsntPGPError( err ) )
2df776 ¤   ¤   ¤   {
34f993 ¤   ¤   ¤   ¤   err¤= sMiscTest( set );
af55be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
55a3a6 ¤   ¤   ¤   }
c887c7 ¤   ¤   ¤
f0cd85 ¤   ¤   ¤   if (IsntPGPError( err ) )
13f776 ¤   ¤   ¤   {
beb4cd ¤   ¤   ¤   ¤   err¤= sSaveRestoreTest( set );
de55be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
7ca3a6 ¤   ¤   ¤   }
8287c7 ¤   ¤   ¤
2fcd85 ¤   ¤   ¤   if (IsntPGPError( err ) )
25f776 ¤   ¤   ¤   {
a63e26 ¤   ¤   ¤   ¤   err¤= sMergeTest( set );
1c55be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
96a3a6 ¤   ¤   ¤   }
7487c7 ¤   ¤   ¤
fecd85 ¤   ¤   ¤   if (IsntPGPError( err ) )
fbf776 ¤   ¤   ¤   {
c7852b ¤   ¤   ¤   ¤   err¤= sDeleteTest( set );
2c55be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
1aa3a6 ¤   ¤   ¤   }
6eaf5a
dfaf5a
e50591 ¤   ¤   ¤   err¤= PGPFreeGroupSet( set );
8a144d ¤   ¤   ¤   pgpAssertNoErr( err );
0c0fe4 ¤   ¤   }
1ed0d8 ¤   ¤   PGPFreeContext( context);
349371 ¤   }
548c1a ¤   pgpAssertNoErr( err );
14efe6 }
fcaf5a
2e7454 #endif
d4b437 #endif /* ] */
f2af5a
71af5a
41af5a
737e4d /*__Editor_settings____
8daf5a
4a4126 ¤   Local Variables:
6a7b17 ¤   tab-width: 4
040e6c ¤   End:
995f8c ¤   vi: ts=4 sw=4
579e9b ¤   vim: si
40d062 _____________________*/
--463f 0011c1e50c440100252 Page 1 of pgpGroupsPriv.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
2a3ebd ¤   $Id: pgpGroupsPriv.h,v 1.1.12.1 1998/11/12 03:23:08 heller Exp $
46f7f7 ____________________________________________________________________________*/
04af5a
48d079 #ifndef Included_pgpGroupsPriv_h¤   /* [ */
fc3830 #define Included_pgpGroupsPriv_h
9daf5a
d4c2ae #include "pgpGroups.h"
b3af5a
af320c #define PGPValidateGroupSet( set )¤ \
3b64ae ¤   ¤   PGPValidateParam( PGPGroupSetIsValid( set ) );
9aaf5a
5599c6 PGP_BEGIN_C_DECLARATIONS
46af5a
33cbcf #if PRAGMA_IMPORT_SUPPORTED
c3b981 #pragma import on
307454 #endif
7faf5a
524f22 PGPBoolean¤ PGPGroupSetIsValid( PGPGroupSetRef set );
4caf5a
c3fb18 void¤   ¤   TestGroups(void);
2f37ae PGPError¤   TestGroupsUtil(void);
faaf5a
42cbcf #if PRAGMA_IMPORT_SUPPORTED
3d2ced #pragma import reset
8e7454 #endif
6aaf5a
451254 PGP_END_C_DECLARATIONS
56af5a
99a36b #endif /* ] Included_pgpGroupsPriv_h */
49af5a
b5af5a
1e7e4d /*__Editor_settings____
2eaf5a
b84126 ¤   Local Variables:
f37b17 ¤   tab-width: 4
9f0e6c ¤   End:
695f8c ¤   vi: ts=4 sw=4
729e9b ¤   vim: si
72d062 _____________________*/
4daf5a
52af5a
acaf5a
43af5a
c2af5a
36af5a
72af5a
1caf5a
--37dd 0009576f91740100253 Page 1 of pgpGroupsUtil.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
a5cc4f ¤   $Id: pgpGroupsUtil.c,v 1.3.12.1 1998/11/12 03:23:09 heller Exp $
66f7f7 ____________________________________________________________________________*/
30324c #include <string.h>
92af5a
4c0d08 #include "pgpMem.h"
4daf5a
0ac26c #include "pgpContext.h"
5fc2ae #include "pgpGroups.h"
f547c7 #include "pgpGroupsPriv.h"
59a076 #include "pgpKeys.h"
b79f63 #include "pgpEncode.h"
3e1b42 #include "pgpStrings.h"
d0af5a
2caf5a
8a2f8d #include "pgpErrors.h"
e1af5a
0d0ccc #if PGP_MACINTOSH
2185c2 #include "MacStrings.h"
bd7454 #endif
51af5a
e7af5a
3caf5a
780335 /*____________________________________________________________________________
896ed3 ¤   Caller must call PGPFreeKey() on resulting key
fdf7f7 ____________________________________________________________________________*/
b3af5a
cd66dd ¤   static PGPError
427c1b sGroupItemToKey(
e5619f ¤   PGPGroupItem const *¤   item,
f295e6 ¤   PGPKeySetRef¤   ¤   ¤   keySet,
3eabb1 ¤   PGPKeyRef *¤¤   ¤   ¤   outKey )
cebb36 {
479372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
a98a97 ¤   PGPContextRef¤  context;
60b566 ¤   PGPKeyRef¤  ¤   key¤= kInvalidPGPKeyRef;
7167c5 ¤
ac33b9 ¤   context¤= PGPGetKeySetContext( keySet );
c367c5 ¤
68ba13 ¤   /* get the key ID into a PGPsdk form */
009d51 ¤   err¤= PGPGetKeyByKeyID( keySet, &item->u.key.keyID,
4f1e2c ¤   ¤   ¤   item->u.key.algorithm, &key );
9267c5 ¤
35306d ¤   *outKey¤= key;
ce67c5 ¤
0b4fa5 ¤   pgpAssert( ( IsntPGPError( err ) && IsntNull( *outKey ) ) ||
417019 ¤   ¤   ( IsPGPError( err ) && IsNull( *outKey ) ));
f2deb7 ¤   return( err );
eeefe6 }
7faf5a
08af5a
07af5a
36af5a
c4ca12 ¤   static PGPValidity
c850ad sMinValidity(
08789f ¤   PGPValidity¤validity1,
3d4a69 ¤   PGPValidity¤validity2 )
72bb36 {
b0f985 ¤   PGPValidity¤validity;
c867c5 ¤
dd491a ¤   if ( validity1 == kPGPValidity_Unknown ||
277429 ¤   ¤   validity2 == kPGPValidity_Unknown )
c1c7a1 ¤   {
99bc30 ¤   ¤   /* lowest we can get */
d68ce0 ¤   ¤   validity¤   = kPGPValidity_Invalid;
2e9b70 ¤   ¤   return( validity );
959371 ¤   }
--fe56 000e62186ba40100253 Page 2 of pgpGroupsUtil.c
2a67c5 ¤
62b154 ¤   /* asserts above guarantee we can use a simple MIN here */
093bc8 ¤   pgpAssert( kPGPValidity_Invalid < kPGPValidity_Marginal );
bd1d30 ¤   pgpAssert( kPGPValidity_Marginal < kPGPValidity_Complete );
85c715 ¤   if ( validity1 < validity2 )
9a4ad3 ¤   ¤   validity¤   = validity1;
700e24 ¤   else
bea5b7 ¤   ¤   validity¤   = validity2;
4a67c5 ¤
c76d15 ¤   return( validity );
f6efe6 }
fbaf5a
30af5a
100335 /*____________________________________________________________________________
dfa96d ¤   Return the lowest validity of any item in the group
0326dc ¤   keyset should contain all keys available
278b47 ¤   It is not an error if keys can't be found; you may want to check
df0569 ¤   the not found count.
cd67c5 ¤
8f90c0 ¤   The lowest validity is kPGPValidity_Invalid and kPGPValidity_Unknown
5e474b ¤   is never returned.
4df7f7 ____________________________________________________________________________*/
4ec744 ¤   PGPError
648873 PGPGetGroupLowestValidity(
de30d0 ¤   PGPGroupSetRef¤ set,
af1ced ¤   PGPGroupID¤ ¤   id,
f146a5 ¤   PGPKeySetRef¤   keySet,
2e05d3 ¤   PGPValidity *¤  lowestValidityOut,
49a769 ¤   PGPUInt32 *¤¤   numKeysNotFound )
66bb36 {
829372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
83bd84 ¤   PGPGroupItemIterRef¤iter;
2067c5 ¤
8c91c9 ¤   if ( IsntNull( lowestValidityOut ) )
e3b476 ¤   ¤   *lowestValidityOut¤ = kPGPValidity_Invalid;
5603ee ¤   if ( IsntNull( numKeysNotFound ) )
92d665 ¤   ¤   *numKeysNotFound¤   = 0;
1e6142 ¤   PGPValidatePtr( lowestValidityOut );
df3a71 ¤   PGPValidatePtr( numKeysNotFound );
5e1b52 ¤   ¤
1eb620 ¤   PGPValidateGroupSet( set );
750391 ¤   PGPValidateParam( IsntNull( keySet ) );
7367c5 ¤
1e319d ¤   err¤= PGPNewGroupItemIter( set, id,
0b6767 ¤   ¤   ¤   kPGPGroupIterFlags_Recursive | kPGPGroupIterFlags_Keys,
1adb56 ¤   ¤   ¤   &iter );
13ac23 ¤   if ( IsntPGPError( err ) ·)
20c7a1 ¤   {
abcc3a ¤   ¤   PGPGroupItem¤   item;
0b31c1 ¤   ¤   PGPContextRef¤  context;
4fa2a4 ¤   ¤   PGPValidity¤¤   lowestValidity¤ = kPGPValidity_Complete;
dc6df5 ¤   ¤   PGPBoolean¤ ¤   examinedAKey¤   = FALSE;
641b52 ¤   ¤
776124 ¤   ¤   context¤= PGPGetKeySetContext( keySet );
fe1b52 ¤   ¤
86de77 ¤   ¤   /* 'lowestValidity' can only decrease while looping */
25e899 ¤   ¤   while( IsntPGPError( err = PGPGroupItemIterNext( iter, &item ) ) )
d35b34 ¤   ¤   {
9f4019 ¤   ¤   ¤   PGPKeyRef¤  key;
2787c7 ¤   ¤   ¤
2d9d39 ¤   ¤   ¤   pgpAssert( item.type == kPGPGroupItem_KeyID );
b787c7 ¤   ¤   ¤
091dda ¤   ¤   ¤   err¤= sGroupItemToKey( &item, keySet, &key );
39211b ¤   ¤   ¤   if ( IsntPGPError( err) )
f3f776 ¤   ¤   ¤   {
9f7d7f ¤   ¤   ¤   ¤   PGPValidity¤¤   validity;
c42b85 ¤   ¤   ¤   ¤
885d48 ¤   ¤   ¤   ¤   examinedAKey¤   = TRUE;
7e87c7 ¤   ¤   ¤
8139ac ¤   ¤   ¤   ¤   err¤= PGPGetPrimaryUserIDValidity( key, &validity );
2d2b85 ¤   ¤   ¤   ¤
e6669e ¤   ¤   ¤   ¤   lowestValidity¤ = sMinValidity( validity, lowestValidity );
--7386 0009fbeef1840100253 Page 3 of pgpGroupsUtil.c
f97409 ¤   ¤   ¤   ¤   if ( lowestValidity == kPGPValidity_Invalid &&
1acfd1 ¤   ¤   ¤   ¤   ¤   IsNull( numKeysNotFound ))
f772c3 ¤   ¤   ¤   ¤   {
63d888 ¤   ¤   ¤   ¤   ¤   /* it doesn't get any lower than kPGPValidity_Invalid and
f94b8e ¤   ¤   ¤   ¤   ¤   ···the caller does not want the number of missing keys */
0114c3 ¤   ¤   ¤   ¤   ¤   break;
5a2613 ¤   ¤   ¤   ¤   }
912b85 ¤   ¤   ¤   ¤
aaa3a6 ¤   ¤   ¤   }
09bb8c ¤   ¤   ¤   else
19f776 ¤   ¤   ¤   {
3a0aff ¤   ¤   ¤   ¤   if ( err == kPGPError_ItemNotFound )
0b72c3 ¤   ¤   ¤   ¤   {
53187e ¤   ¤   ¤   ¤   ¤   /* just can't find the key; that's OK */
a01bbc ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
ddfca0 ¤   ¤   ¤   ¤   ¤   *numKeysNotFound¤   += 1;
a72613 ¤   ¤   ¤   ¤   }
f7a3a6 ¤   ¤   ¤   }
e987c7 ¤   ¤   ¤
658370 ¤   ¤   ¤   if ( IsPGPError( err ) )
b1f622 ¤   ¤   ¤   ¤   break;
8f0fe4 ¤   ¤   }
a0d7c7 ¤   ¤   if ( err == kPGPError_EndOfIteration )
b45403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
591b52 ¤   ¤
8fd66f ¤   ¤   /* if we examined keys, use the validity we found, otherwise
7e49e0 ¤   ¤   ¤   consider it invalid */
99dbd5 ¤   ¤   if ( examinedAKey )
ddeadc ¤   ¤   ¤   *lowestValidityOut¤ = lowestValidity;
4d0e1d ¤   ¤   else
28e1da ¤   ¤   ¤   *lowestValidityOut¤ = kPGPValidity_Invalid;
e287c7 ¤   ¤   ¤
97776c ¤   ¤   PGPFreeGroupItemIter( iter );
7c9371 ¤   }
7a67c5 ¤
4edeb7 ¤   return( err );
deefe6 }
7eaf5a
a3af5a
39af5a
4e0335 /*____________________________________________________________________________
7175a4 ¤   All all the keys in the group (and its subgroups) to the keyset
99f7f7 ____________________________________________________________________________*/
3cc744 ¤   PGPError
99d388 PGPNewKeySetFromGroup(
a330d0 ¤   PGPGroupSetRef¤ set,
b71ced ¤   PGPGroupID¤ ¤   id,
b4c1f6 ¤   PGPKeySetRef¤   masterSet,¤ ¤   /* resolve key IDs using the set */
cd55c6 ¤   PGPKeySetRef *¤ outKeys,
618101 ¤   PGPUInt32 *¤¤   numKeysNotFound
6127e6 ¤   )
d8bb36 {
b79372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
59bd84 ¤   PGPGroupItemIterRef¤iter;
74091b ¤   PGPKeySetRef¤   workingSet¤ = kInvalidPGPKeySetRef;
1567c5 ¤
b603ee ¤   if ( IsntNull( numKeysNotFound ) )
b4d665 ¤   ¤   *numKeysNotFound¤   = 0;
388054 ¤   if ( IsntNull( outKeys ) )
8d849e ¤   ¤   *outKeys¤   = kInvalidPGPKeySetRef;
0a3a71 ¤   PGPValidatePtr( numKeysNotFound );
243f0f ¤   PGPValidatePtr( outKeys );
3db620 ¤   PGPValidateGroupSet( set );
03eb81 ¤   PGPValidatePtr( masterSet );
e267c5 ¤
8a389c ¤   err¤= PGPNewEmptyKeySet( masterSet, &workingSet );
acf1e7 ¤   if ( IsntPGPError( err ) )
0fc7a1 ¤   {
d8b9fb ¤   ¤   err¤= PGPNewGroupItemIter( set, id,
e62910 ¤   ¤   ¤   ¤   kPGPGroupIterFlags_Recursive | kPGPGroupIterFlags_Keys,
d46a87 ¤   ¤   ¤   ¤   &iter );
9f9371 ¤   }
--68b6 000e492adcf40100253 Page 4 of pgpGroupsUtil.c
54ac23 ¤   if ( IsntPGPError( err ) ·)
e4c7a1 ¤   {
29cc3a ¤   ¤   PGPGroupItem¤   item;
851b52 ¤   ¤
b1e899 ¤   ¤   while( IsntPGPError( err = PGPGroupItemIterNext( iter, &item ) ) )
e95b34 ¤   ¤   {
be4019 ¤   ¤   ¤   PGPKeyRef¤  key;
f487c7 ¤   ¤   ¤
119d39 ¤   ¤   ¤   pgpAssert( item.type == kPGPGroupItem_KeyID );
2f87c7 ¤   ¤   ¤
329599 ¤   ¤   ¤   err¤= sGroupItemToKey( &item, masterSet, &key );
453c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
42f776 ¤   ¤   ¤   {
acb88a ¤   ¤   ¤   ¤   PGPKeySetRef¤   singleKeySet;
112b85 ¤   ¤   ¤   ¤
4e8975 ¤   ¤   ¤   ¤   err¤= PGPNewSingletonKeySet( key, &singleKeySet );
933227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
6772c3 ¤   ¤   ¤   ¤   {
ba7bb1 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   oldKeys¤= workingSet;
29ae30 ¤   ¤   ¤   ¤   ¤
ae7eac ¤   ¤   ¤   ¤   ¤   err = PGPUnionKeySets( workingSet,
683b3a ¤   ¤   ¤   ¤   ¤   ¤   ¤   singleKeySet, &workingSet );
05531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
8e80f2 ¤   ¤   ¤   ¤   ¤   (void) PGPFreeKeySet( singleKeySet );
592d70 ¤   ¤   ¤   ¤   ¤   (void) PGPFreeKeySet( oldKeys );
6e2613 ¤   ¤   ¤   ¤   }
e52b85 ¤   ¤   ¤   ¤
a02b85 ¤   ¤   ¤   ¤
48869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
5d14c3 ¤   ¤   ¤   ¤   ¤   break;
09a3a6 ¤   ¤   ¤   }
2c8aa7 ¤   ¤   ¤   else if ( err == kPGPError_ItemNotFound )
84f776 ¤   ¤   ¤   {
74c565 ¤   ¤   ¤   ¤   *numKeysNotFound¤   += 1;
72a3a6 ¤   ¤   ¤   }
c7bb8c ¤   ¤   ¤   else
66f776 ¤   ¤   ¤   {
80f622 ¤   ¤   ¤   ¤   break;
c1a3a6 ¤   ¤   ¤   }
da0fe4 ¤   ¤   }
4ed7c7 ¤   ¤   if ( err == kPGPError_EndOfIteration )
715403 ¤   ¤   ¤   err¤= kPGPError_NoErr;
2887c7 ¤   ¤   ¤
f2776c ¤   ¤   PGPFreeGroupItemIter( iter );
ee9371 ¤   }
4767c5 ¤
cc529d ¤   if ( IsPGPError( err ) && PGPKeySetRefIsValid( workingSet ) )
7dc7a1 ¤   {
d39dc6 ¤   ¤   (void) PGPFreeKeySet( workingSet );
e35047 ¤   ¤   workingSet¤ = kInvalidPGPKeySetRef;
5a9371 ¤   }
d567c5 ¤
983189 ¤   *outKeys¤   = workingSet;
2767c5 ¤
22deb7 ¤   return( err );
13efe6 }
8baf5a
58af5a
43af5a
6f1741 typedef struct
fbbb36 {
369e3c ¤   PGPKeySetRef¤   keySet;
d8e849 ¤   PGPGroupSetRef¤ set;
b287da } MySortInfo;
bdaf5a
18bfe5 ¤   static PGPInt32
ce4196 sCompareGroupItems(
8727e5 ¤   PGPGroupItem *¤ item1,
f1c881 ¤   PGPGroupItem *¤ item2,
35c41f ¤   void *¤ ¤   ¤   userValue )
abbb36 {
e4505d ¤   PGPKeyRef¤  ¤   key1;
--33d5 0007961f50940100253 Page 5 of pgpGroupsUtil.c
bcbf39 ¤   PGPKeyRef¤  ¤   key2;
bbfee1 ¤   PGPError¤   ¤   err1;
521185 ¤   PGPError¤   ¤   err2;
882635 ¤   MySortInfo const *¤ info¤   = (MySortInfo const *)userValue;
956b59 ¤   PGPKeySetRef¤   keySet¤ = info->keySet;
b7600a ¤   PGPInt32¤   ¤   result;
3067c5 ¤
4af97f ¤   pgpAssert( IsntNull( info ) );
a01b52 ¤   ¤
16ec24 ¤   keySet¤ = info->keySet;
a967c5 ¤
4cb09c ¤   if ( item1->type == kPGPGroupItem_Group ||
5551d6 ¤   ¤   ¤   item2->type == kPGPGroupItem_Group )
39c7a1 ¤   {
fbd1a4 ¤   ¤   PGPGroupInfo¤   groupInfo1;
c83ec0 ¤   ¤   PGPGroupInfo¤   groupInfo2;
ec1b52 ¤   ¤
03aaf1 ¤   ¤   /* for now, always make groups come before keys */
28b630 ¤   ¤   if ( item1->type == kPGPGroupItem_Group &&
19dfd0 ¤   ¤   ¤   item2->type == kPGPGroupItem_KeyID )
5b5b34 ¤   ¤   {
5b8e4f ¤   ¤   ¤   return( -1 );
2a0fe4 ¤   ¤   }
23a1af ¤   ¤   else if ( item1->type == kPGPGroupItem_KeyID &&
a451d6 ¤   ¤   ¤   item2->type == kPGPGroupItem_Group )
bc5b34 ¤   ¤   {
29117f ¤   ¤   ¤   return( 1 );
f00fe4 ¤   ¤   }
d49e22 ¤   ¤   /* both are groups */
458260 ¤   ¤   PGPGetGroupInfo( info->set, item1->u.group.id, &groupInfo1 );
09feb9 ¤   ¤   PGPGetGroupInfo( info->set, item2->u.group.id, &groupInfo2 );
7fc1b6 ¤   ¤   return( pgpCompareStringsIgnoreCase( groupInfo1.name,
3c8f40 ¤   ¤   ¤   ¤   ¤   groupInfo2.name ) );
2a9371 ¤   }
a567c5 ¤
527cda ¤   err1¤   = sGroupItemToKey( item1, keySet, &key1 );
8edf73 ¤   err2¤   = sGroupItemToKey( item2, keySet, &key2 );
2e67c5 ¤
5ed8af ¤   /*
b79cf4 ¤   ¤   Rules:
de99de ¤   ¤   errors on both: consider the same
0d544a ¤   ¤   error on one: it's always less than
d89faa ¤   */
01bd05 ¤   if ( IsPGPError( err1 ) && IsPGPError( err2 ) )
92c7a1 ¤   {
46d561 ¤   ¤   /* if we got errors on both, consider them the same */
41009e ¤   ¤   result¤ = 0;
e99371 ¤   }
1cbdc8 ¤   else if ( IsPGPError( err1 ) )
1cc7a1 ¤   {
a34683 ¤   ¤   result¤ = -1;
919371 ¤   }
3eb1b5 ¤   else if ( IsPGPError( err2 ) )
7fc7a1 ¤   {
d55a42 ¤   ¤   result¤ = 1;
de9371 ¤   }
b40e24 ¤   else
a5c7a1 ¤   {
c0a150 ¤   ¤   result¤ = PGPCompareKeys( key1, key2, kPGPUserIDOrdering );
d19371 ¤   }
3a67c5 ¤
b667c5 ¤
d44c6e ¤   return( result );
a0efe6 }
6aaf5a
4faf5a
b6c744 ¤   PGPError
7dfb5c PGPSortGroupSetStd(
4d30d0 ¤   PGPGroupSetRef¤ set,
24f143 ¤   PGPKeySetRef¤   keySet )
a3bb36 {
7926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
--8a2f 0008646126440100253 Page 6 of pgpGroupsUtil.c
6305b6 ¤   MySortInfo¤ info;
1167c5 ¤
da4405 ¤   info.set¤   = set;
cf1129 ¤   info.keySet¤= keySet;
5e67c5 ¤
cd2549 ¤   err¤= PGPSortGroupSet( set, sCompareGroupItems, &info );
fe67c5 ¤
d8deb7 ¤   return( err );
62efe6 }
41af5a
38c744 ¤   PGPError
7368d0 PGPNewFlattenedGroupFromGroup(
05cceb ¤   PGPGroupSetRef¤ sourceSet,
a0c04f ¤   PGPGroupID¤ ¤   sourceID,
0cdb44 ¤   PGPGroupSetRef¤ destSet,
fbbc7f ¤   PGPGroupID¤ ¤   *destID)
b9bb36 {
fd61e0 ¤   PGPError¤   err;
c0af5a
7bbb6f ¤   PGPValidatePtr( destID );
2cc91f ¤   *destID¤= kPGPInvalidGroupID;
b71f0f ¤   PGPValidateGroupSet( sourceSet );
3edb6b ¤   PGPValidateGroupSet( destSet );
eff937 ¤   PGPValidateParam( sourceSet != destSet );
63af5a
c5ac42 ¤   err = PGPNewGroup( destSet, "", "", destID );
8db1f0 ¤   if( IsntPGPError( err ) )
8dc7a1 ¤   {
5f3bc5 ¤   ¤   PGPGroupItemIterRef¤iterator;
ca1b52 ¤   ¤
8f1ed9 ¤   ¤   err¤= PGPNewGroupItemIter( sourceSet, sourceID,
ca3219 ¤   ¤   ¤   ¤   ¤   kPGPGroupIterFlags_Recursive | kPGPGroupIterFlags_Keys,
48fdd8 ¤   ¤   ¤   ¤   ¤   &iterator );
6e27df ¤   ¤   if ( IsntPGPError( err ) ·)
9c5b34 ¤   ¤   {
a5fb32 ¤   ¤   ¤   PGPGroupItem¤   item;
0f87c7 ¤   ¤   ¤
4a1b19 ¤   ¤   ¤   err = PGPGroupItemIterNext( iterator, &item );
a88f5a ¤   ¤   ¤   while( IsntPGPError( err ) )
b2f776 ¤   ¤   ¤   {
873571 ¤   ¤   ¤   ¤   err = PGPAddItemToGroup( destSet, &item, *destID );
7e9570 ¤   ¤   ¤   ¤   if( err == kPGPError_ItemAlreadyExists )
8ab37b ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
642b85 ¤   ¤   ¤   ¤
749c8a ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
c414c3 ¤   ¤   ¤   ¤   ¤   break;
c094aa ¤   ¤   ¤   ¤   ¤   ¤
521bfb ¤   ¤   ¤   ¤   err = PGPGroupItemIterNext( iterator, &item );
d2a3a6 ¤   ¤   ¤   }
5687c7 ¤   ¤   ¤
230f75 ¤   ¤   ¤   if ( err == kPGPError_EndOfIteration )
1815f0 ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
0c2b85 ¤   ¤   ¤   ¤
e6713e ¤   ¤   ¤   PGPFreeGroupItemIter( iterator );
100fe4 ¤   ¤   }
441b52 ¤   ¤
9ad223 ¤   ¤   if( IsPGPError( err ) )
c25b34 ¤   ¤   {
eae5fb ¤   ¤   ¤   (void) PGPDeleteGroup( destSet, *destID );
94fd22 ¤   ¤   ¤   *destID = kPGPInvalidGroupID;
f80fe4 ¤   ¤   }
7e9371 ¤   }
7a67c5 ¤
60deb7 ¤   return( err );
8befe6 }
4aaf5a
f7af5a
21af5a
64a7b1 #if PGP_DEBUG /* [ */
35af5a
0266dd ¤   static PGPError
86cd07 sAddAllKeysToGroup(
--40f1 000f71d740740100253 Page 7 of pgpGroupsUtil.c
5f30d0 ¤   PGPGroupSetRef¤ set,
4d1ced ¤   PGPGroupID¤ ¤   id,
68f143 ¤   PGPKeySetRef¤   keySet )
aebb36 {
1f9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
1e5445 ¤   PGPKeyListRef¤  keyList;
9367c5 ¤
182bbd ¤   err = PGPOrderKeySet( keySet, kPGPAnyOrdering, &keyList );
c3b1f0 ¤   if( IsntPGPError( err ) )
0dc7a1 ¤   {
aece0f ¤   ¤   PGPKeyIterRef¤  iter;
8e1b52 ¤   ¤
b6aaa0 ¤   ¤   err = PGPNewKeyIter( keyList, &iter );
cc86f8 ¤   ¤   if( IsntPGPError( err ) )
005b34 ¤   ¤   {
6d9a09 ¤   ¤   ¤   PGPKeyRef¤  ¤   key;
aa87c7 ¤   ¤   ¤
b8ab29 ¤   ¤   ¤   while( IsntPGPError( err = PGPKeyIterNext( iter, &key ) ) )
43f776 ¤   ¤   ¤   {
983500 ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
822b85 ¤   ¤   ¤   ¤
b2f6e4 ¤   ¤   ¤   ¤   err¤= PGPGetKeyIDFromKey( key, &keyID );
0b3227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
a072c3 ¤   ¤   ¤   ¤   {
8328af ¤   ¤   ¤   ¤   ¤   PGPGroupItem¤   item;
747bfc ¤   ¤   ¤   ¤   ¤   PGPInt32¤   ¤   algorithm;
c8ae30 ¤   ¤   ¤   ¤   ¤
f554ad ¤   ¤   ¤   ¤   ¤   item.type¤  ¤   ¤   ¤   = kPGPGroupItem_KeyID;
ff7f71 ¤   ¤   ¤   ¤   ¤   item.u.key.keyID¤   ¤   = keyID;
62e5fc ¤   ¤   ¤   ¤   ¤   PGPGetKeyNumber( key, kPGPKeyPropAlgID, &algorithm);
de02fa ¤   ¤   ¤   ¤   ¤   item.u.key.algorithm¤   = (PGPPublicKeyAlgorithm) algorithm;
7094aa ¤   ¤   ¤   ¤   ¤   ¤
9b6567 ¤   ¤   ¤   ¤   ¤   err¤= PGPAddItemToGroup( set, &item, id);
b3ae30 ¤   ¤   ¤   ¤   ¤
6e8025 ¤   ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
5500eb ¤   ¤   ¤   ¤   ¤   ¤   break;
3e2613 ¤   ¤   ¤   ¤   }
b3a3a6 ¤   ¤   ¤   }
5687c7 ¤   ¤   ¤
ad6ae1 ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
18bd37 ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
4d2b85 ¤   ¤   ¤   ¤
bc23a3 ¤   ¤   ¤   (void) PGPFreeKeyIter( iter );
030fe4 ¤   ¤   }
17812b ¤   ¤   (void) PGPFreeKeyList( keyList );
6c9371 ¤   }
dadeb7 ¤   return( err );
87efe6 }
a2af5a
7eaf5a
f066dd ¤   static PGPError
7618ae sTestGroupValidity( PGPKeySetRef¤   keySet )
36bb36 {
e899ea ¤   PGPValidity¤¤   validity;
86d19a ¤   PGPUInt32¤  ¤   numNotFound;
f69372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
9fe849 ¤   PGPGroupSetRef¤ set;
b5ca72 ¤   PGPContextRef¤  memoryMgr¤  = NULL;
dc67c5 ¤
97fcc8 ¤   err¤= PGPNewContext( kPGPsdkAPIVersion, &memoryMgr );
66f1e7 ¤   if ( IsntPGPError( err ) )
6fc7a1 ¤   {
0d2a36 ¤   ¤   err¤= PGPNewGroupSet( memoryMgr, &set );
fd7d98 ¤   ¤   if ( IsntPGPError( err ) )
a45b34 ¤   ¤   {
1bc6a8 ¤   ¤   ¤   PGPGroupID¤ id;
c487c7 ¤   ¤   ¤
e16df0 ¤   ¤   ¤   err¤= PGPNewGroup( set, "test group", "", &id );
603c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
cfdb23 ¤   ¤   ¤   ¤   err¤= sAddAllKeysToGroup( set, id, keySet );
0687c7 ¤   ¤   ¤
f73c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
--3e9f 001db5b76a240100253 Page 8 of pgpGroupsUtil.c
99f776 ¤   ¤   ¤   {
b35fc3 ¤   ¤   ¤   ¤   err¤= PGPGetGroupLowestValidity( set, id,·
e636ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   keySet, &validity, &numNotFound );
8ca3a6 ¤   ¤   ¤   }
4c87c7 ¤   ¤   ¤
0e7f45 ¤   ¤   ¤   PGPFreeGroupSet( set );
0a0fe4 ¤   ¤   }
baaf5a
8b8581 ¤   ¤   PGPFreeContext( memoryMgr );
239371 ¤   }
c667c5 ¤
17deb7 ¤   return( err );
d2efe6 }
58af5a
c6af5a
18c744 ¤   PGPError
81340b TestGroupsUtil()
d7bb36 {
5b8a97 ¤   PGPContextRef¤  context;
fc9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
8167c5 ¤
2e9041 ¤   err¤= PGPNewContext( kPGPsdkAPIVersion, &context );
78f1e7 ¤   if ( IsntPGPError( err ) )
2dc7a1 ¤   {
843362 ¤   ¤   PGPKeySetRef¤   keySet;
131b52 ¤   ¤
6b4e13 ¤   ¤   err¤= PGPOpenDefaultKeyRings( context, 0, &keySet );
367d98 ¤   ¤   if ( IsntPGPError( err ) )
e35b34 ¤   ¤   {
47c3e9 ¤   ¤   ¤   err¤= sTestGroupValidity( keySet );
8d87c7 ¤   ¤   ¤
ad0672 ¤   ¤   ¤   PGPFreeKeySet( keySet );
fe0fe4 ¤   ¤   }
40937b ¤   ¤   PGPFreeContext( context );
d39371 ¤   }
d967c5 ¤
118c1a ¤   pgpAssertNoErr( err );
12deb7 ¤   return( err );
59efe6 }
ffaf5a
96b437 #endif /* ] */
c4af5a
feaf5a
43af5a
467e4d /*__Editor_settings____
39af5a
d04126 ¤   Local Variables:
a47b17 ¤   tab-width: 4
e30e6c ¤   End:
8f5f8c ¤   vi: ts=4 sw=4
549e9b ¤   vim: si
dbd062 _____________________*/
--749c 00082e857a540100254 Page 1 of pgpOptionList.c
a70335 /*____________________________________________________________________________
b2198f ¤   pgpOptionList.c
fa67c5 ¤
72c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
9e4b0f ¤   All rights reserved.
4267c5 ¤
dbda0b ¤   $Id: pgpOptionList.c,v 1.63.10.1 1998/11/12 03:23:09 heller Exp $
c0f7f7 ____________________________________________________________________________*/
aeaf5a
34324c #include <string.h>
afaf5a
7f894b #include "pgpFileSpec.h"
6ac26c #include "pgpContext.h"
7afb31 #include "pgpOptionList.h"
318b0d #include "pgpEncodePriv.h"
402f8d #include "pgpErrors.h"
ecaf5a
a0547e #if PGP_CLIENT_LIBRARY
24c433 #include "pgpClientLib.h"¤  /* No PFL dependencies for client library */
55db21 #else
4ca146 #include "pgpDebug.h"
9e0d08 #include "pgpMem.h"
fc7454 #endif
6caf5a
1a7353 enum
1cbb36 {
67ea68 ¤   kPGPOptionList_Magic¤   ¤   = 0x4F4C7374,¤  /* 'OLst' */
0567c5 ¤
af05d4 ¤   kPGPOptionList_MajorVersion¤= 1,
ceadce ¤   kPGPOptionList_MinorVersion¤= 1,
ca67c5 ¤
7494e3 ¤   kPGPOptionList_NumGrowElements¤ = 5
7c82f7 };
54af5a
197353 enum
eebb36 {
07b3d7 ¤   kPGPOptionListFlag_PersistentList¤  = ( 1 << 0 )
9182f7 };
c5af5a
ba1141 struct PGPOptionList
a2bb36 {
3ecd45 ¤   PGPUInt32¤  ¤   magic;¤ ¤   ¤   /* Always kPGPOptionList_Magic */
b95b64 ¤   PGPVersion¤ ¤   version;
928a97 ¤   PGPContextRef¤  context;
c72791 ¤   PGPError¤   ¤   err;¤   ¤   ¤   /* Important that this field is second */
5df725 ¤   PGPFlags¤   ¤   flags;
5ad4bc ¤   PGPUInt16¤  ¤   maxOptions;
1632ab ¤   PGPUInt16¤  ¤   numOptions;
b067c5 ¤
eb64db ¤   PGPOption¤  ¤   *options;
be82f7 };
4baf5a
ca16ea ¤   PGPBoolean
b5cefd pgpOptionListIsReal(PGPOptionListRef optionList)
1abb36 {
4779c1 ¤   return( optionList != kPGPEndOfArgsOptionListRef &&
339df7 ¤   ¤   ¤   optionList != kPGPOutOfMemoryOptionListRef &&
c762bd ¤   ¤   ¤   optionList != kPGPBadParamsOptionListRef &&
540e6d ¤   ¤   ¤   optionList != kPGPNullOptionListRef );
6fefe6 }
e0af5a
04af5a
e5c744 ¤   PGPError
d55868 pgpOptionListToError( PGPOptionListRef optionList )
8bbb36 {
5d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
4967c5 ¤
c3d2d2 ¤   if ( optionList == kPGPEndOfArgsOptionListRef ||
7cd5dc ¤   ¤   optionList == kPGPBadParamsOptionListRef ||
00bd56 ¤   ¤   optionList == kPGPNullOptionListRef )
99c7a1 ¤   {
82bc3e ¤   ¤   err¤= kPGPError_BadParams;
--246b 000f793afd240100254 Page 2 of pgpOptionList.c
a19371 ¤   }
8e4dd2 ¤   else if ( optionList == kPGPOutOfMemoryOptionListRef )
eac7a1 ¤   {
1e17a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
1b9371 ¤   }
bd0e24 ¤   else
cdc7a1 ¤   {
cf8d36 ¤   ¤   pgpAssert( pgpOptionListIsReal( optionList ) );
8ed87c ¤   ¤   err¤= kPGPError_NoErr;
f19371 ¤   }
d767c5 ¤
60deb7 ¤   return( err );
4cefe6 }
f2af5a
516c2c ¤   static PGPBoolean
6fc631 pgpVerifyOptionList(PGPOptionListRef optionList)
acbb36 {
0d5b1f ¤   PGPBoolean¤ isValid = TRUE;
3c67c5 ¤
630993 ¤   if( pgpOptionListIsReal( optionList ) )
03c7a1 ¤   {
9ef62f ¤   ¤   if( optionList->numOptions <= optionList->maxOptions )
015b34 ¤   ¤   {
d41b1d ¤   ¤   ¤   PGPUInt32¤  optionIndex;
8f87c7 ¤   ¤   ¤
f2540c ¤   ¤   ¤   for( optionIndex = 0; optionIndex < optionList->numOptions;
b0a148 ¤   ¤   ¤   ¤   ¤   ++optionIndex )
b2f776 ¤   ¤   ¤   {
89b672 ¤   ¤   ¤   ¤   const PGPOption¤*curOption;
032b85 ¤   ¤   ¤   ¤
5afd15 ¤   ¤   ¤   ¤   curOption = &optionList->options[optionIndex];
1f2b85 ¤   ¤   ¤   ¤
24f1d1 ¤   ¤   ¤   ¤   if( ( (PGPInt32) curOption->type >=
ef585c ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_FirstSDKOption &&
f39424 ¤   ¤   ¤   ¤   ¤   ··curOption->type < kPGPOptionType_LastSDKOption ) ||
1a552d ¤   ¤   ¤   ¤   ¤   ( curOption->type >= kPGPOptionType_FirstUIOption &&
674cf3 ¤   ¤   ¤   ¤   ¤   ··curOption->type < kPGPOptionType_LastUIOption ) )
e872c3 ¤   ¤   ¤   ¤   {
bcaa3b ¤   ¤   ¤   ¤   ¤   /* OK */
602613 ¤   ¤   ¤   ¤   }
a4fa07 ¤   ¤   ¤   ¤   else
0a72c3 ¤   ¤   ¤   ¤   {
5072e4 ¤   ¤   ¤   ¤   ¤   isValid = FALSE;
d114c3 ¤   ¤   ¤   ¤   ¤   break;
8b2613 ¤   ¤   ¤   ¤   }
a02b85 ¤   ¤   ¤   ¤
9c63af ¤   ¤   ¤   ¤   if( PGPOptionListRefIsValid( curOption->subOptions ) )
1672c3 ¤   ¤   ¤   ¤   {
af34bd ¤   ¤   ¤   ¤   ¤   isValid = pgpVerifyOptionList( curOption->subOptions );
aa8eb3 ¤   ¤   ¤   ¤   ¤   if( ! isValid )
4200eb ¤   ¤   ¤   ¤   ¤   ¤   break;
ef2613 ¤   ¤   ¤   ¤   }
ffa3a6 ¤   ¤   ¤   }
b30fe4 ¤   ¤   }
310e1d ¤   ¤   else
dc5b34 ¤   ¤   {
21f4da ¤   ¤   ¤   isValid = FALSE;
370fe4 ¤   ¤   }
0c9371 ¤   }
a087c7 ¤   ¤   ¤
88195c ¤   return( isValid );
37efe6 }
a7af5a
d00335 /*____________________________________________________________________________
b11638 ¤   This function validates a PGPOptionList data structure. It does not assert
2460e8 ¤   so it can be used within assert macros.
9af7f7 ____________________________________________________________________________*/
03af5a
e216ea ¤   PGPBoolean
be41b8 pgpOptionListIsValid(PGPOptionListRef optionList)
4cbb36 {
f70509 ¤   PGPBoolean¤ isValid;
--a64e 000654d9eb440100254 Page 3 of pgpOptionList.c
2a67c5 ¤
d20993 ¤   if( pgpOptionListIsReal( optionList ) )
31c7a1 ¤   {
8c7d16 ¤   ¤   isValid = ( optionList != NULL &&
7d4d8f ¤   ¤   ¤   ¤   ¤   optionList->magic == kPGPOptionList_Magic );
d9af5a
58e85e #if PGP_DEBUG¤  /* [ */
1bad0e ¤   ¤   if( isValid )
2c5b34 ¤   ¤   {
eed86d ¤   ¤   ¤   /* Perform more stringent check */
fd7140 ¤   ¤   ¤   isValid = pgpVerifyOptionList( optionList );
d90fe4 ¤   ¤   }
ae3167 #endif¤ /* ] */
aa9371 ¤   }
580e24 ¤   else
dfc7a1 ¤   {
bf7b96 ¤   ¤   isValid = TRUE;
189371 ¤   }
3a67c5 ¤
3f195c ¤   return( isValid );
0befe6 }
49af5a
aec744 ¤   PGPError
2bd656 pgpGetOptionListError(PGPOptionListRef optionList)
81bb36 {
b861e0 ¤   PGPError¤   err;
dd67c5 ¤
d01189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
3faf5a
83e2d5 ¤   if( optionList == kPGPEndOfArgsOptionListRef ||
78bd56 ¤   ¤   optionList == kPGPNullOptionListRef )
f0c7a1 ¤   {
c070bb ¤   ¤   err = kPGPError_NoErr;
3a9371 ¤   }
5044fd ¤   else if( optionList == kPGPOutOfMemoryOptionListRef )
23c7a1 ¤   {
acbce1 ¤   ¤   err = kPGPError_OutOfMemory;
5d9371 ¤   }
4d0180 ¤   else if( optionList == kPGPBadParamsOptionListRef )
0dc7a1 ¤   {
9a19d3 ¤   ¤   err = kPGPError_BadParams;
809371 ¤   }
a20e24 ¤   else
27c7a1 ¤   {
956165 ¤   ¤   err = optionList->err;
099371 ¤   }
2467c5 ¤
29deb7 ¤   return( err );
d8efe6 }
ccaf5a
d8108d ¤   PGPUInt32
9b7df7 pgpGetOptionListCount(PGPOptionListRef optionList)
09bb36 {
b7704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
8767c5 ¤
fdc553 ¤   return( optionList->numOptions );
46efe6 }
5eaf5a
136d52 ¤   void
5139e3 pgpSetOptionListError(
14feff ¤   PGPOptionListRef ¤  optionList,
612230 ¤   PGPError ¤  ¤   ¤   err)
9abb36 {
dc704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
84af5a
c00993 ¤   if( pgpOptionListIsReal( optionList ) )
51c7a1 ¤   {
c9818f ¤   ¤   /* Set the err code iff there isn't already an err for the list */
1baf5a
54a7d7 ¤   ¤   if( IsntPGPError( optionList->err ) )
065b34 ¤   ¤   {
65c841 ¤   ¤   ¤   optionList->err = err;
--71ac 00005d3076840100254 Page 4 of pgpOptionList.c
b50fe4 ¤   ¤   }
6b9371 ¤   }
6cefe6 }
99af5a
fe33c8 ¤   static void
fff0ef pgpFreeOptionListInternal(
ebfeff ¤   PGPOptionListRef ¤  optionList,
ab039a ¤   PGPBoolean¤ ¤   ¤   freePersistentList)
06bb36 {
46704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
da67c5 ¤
af0993 ¤   if( pgpOptionListIsReal( optionList ) )
24c7a1 ¤   {
aee2f4 ¤   ¤   PGPBoolean¤ freeTheList = TRUE;
7a1b52 ¤   ¤
a597ef ¤   ¤   if( ( optionList->flags & kPGPOptionListFlag_PersistentList ) != 0 )
2f5b34 ¤   ¤   {
350e39 ¤   ¤   ¤   freeTheList = freePersistentList;
7b0fe4 ¤   ¤   }
c0af5a
bbdb46 ¤   ¤   if( freeTheList )
3b5b34 ¤   ¤   {
091b1d ¤   ¤   ¤   PGPUInt32¤  optionIndex;
9787c7 ¤   ¤   ¤
227aad ¤   ¤   ¤   /*
5e93b0 ¤   ¤   ¤   **¤ Free all of the allocations and suboption lists hanging
85fd40 ¤   ¤   ¤   **¤ off of the main option list
823da8 ¤   ¤   ¤   */
c687c7 ¤   ¤   ¤
ec540c ¤   ¤   ¤   for( optionIndex = 0; optionIndex < optionList->numOptions;
178749 ¤   ¤   ¤   ¤   ¤   ¤   optionIndex++ )
4af776 ¤   ¤   ¤   {
9adae1 ¤   ¤   ¤   ¤   PGPOption¤  *curOption = &optionList->options[optionIndex];
6b2b85 ¤   ¤   ¤   ¤
119685 ¤   ¤   ¤   ¤   if( IsntNull( curOption->handlerProc ) )
0472c3 ¤   ¤   ¤   ¤   {
61e3e1 ¤   ¤   ¤   ¤   ¤   (*curOption->handlerProc)(
e19fb5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   optionList->context,
0f4af9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionHandler_FreeDataOperation,
4ec179 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curOption->type,
e11634 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curOption->value, curOption->valueSize,
c2eedf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   NULL, NULL );
272613 ¤   ¤   ¤   ¤   }
a387c7 ¤   ¤   ¤
e1e2f9 ¤   ¤   ¤   ¤   if( IsntNull( curOption->subOptions ) )
0272c3 ¤   ¤   ¤   ¤   {
74ac70 ¤   ¤   ¤   ¤   ¤   pgpAssert( ( curOption->subOptions->flags &·
6e5980 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionListFlag_PersistentList ) == 0 );
ae531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
55d171 ¤   ¤   ¤   ¤   ¤   pgpFreeOptionListInternal( curOption->subOptions, TRUE );
a82613 ¤   ¤   ¤   ¤   }
80a3a6 ¤   ¤   ¤   }
7687c7 ¤   ¤   ¤
c77f17 ¤   ¤   ¤   pgpContextMemFree( optionList->context, optionList->options );
83d0a6 ¤   ¤   ¤   pgpContextMemFree( optionList->context, optionList );
d90fe4 ¤   ¤   }
959371 ¤   }
04efe6 }
41af5a
996d52 ¤   void
8489c6 pgpFreeOptionList(PGPOptionListRef optionList)
f7bb36 {
0e9b1f ¤   pgpFreeOptionListInternal( optionList, TRUE );
25efe6 }
c8af5a
a713fb ¤   PGPOptionListRef
01026d pgpNewOptionList(
b4520e ¤   PGPContextRef¤  context,
b9b7ea ¤   PGPBoolean¤ ¤   createPersistentList)
ecbb36 {
863ddd ¤   PGPOptionListRef¤   optionList;
0567c5 ¤
--fa96 0004581501e40100254 Page 5 of pgpOptionList.c
ac5402 ¤   optionList = (PGPOptionListRef)
08d793 ¤   ¤   pgpContextMemAlloc( context, sizeof( *optionList ), 0);
a7b95d ¤   if( IsntNull( optionList ) )
2fc7a1 ¤   {
a6c8c9 ¤   ¤   pgpClearMemory( optionList, sizeof( *optionList ) );
d7af5a
7c5127 ¤   ¤   optionList->options = (PGPOption *)
592a45 ¤   ¤   ¤   pgpContextMemAlloc( context, ·sizeof( PGPOption ), 0);
5b47cf ¤   ¤   if( IsntNull( optionList->options ) )
9a5b34 ¤   ¤   {
d32d08 ¤   ¤   ¤   pgpClearMemory( optionList->options, sizeof( PGPOption ) );
0aaf5a
f98d78 ¤   ¤   ¤   optionList->magic ¤ ¤   = kPGPOptionList_Magic;
2cdc42 ¤   ¤   ¤   optionList->maxOptions¤ = 1;
c4ba21 ¤   ¤   ¤   optionList->context¤¤   = context;
02af5a
12ef61 ¤   ¤   ¤   optionList->version.majorVersion¤   = kPGPOptionList_MajorVersion;
6244e7 ¤   ¤   ¤   optionList->version.minorVersion¤   = kPGPOptionList_MinorVersion;
7487c7 ¤   ¤   ¤
e47b75 ¤   ¤   ¤   if( createPersistentList )
1000f7 ¤   ¤   ¤   ¤   optionList->flags |= kPGPOptionListFlag_PersistentList;
2b0fe4 ¤   ¤   }
6e0e1d ¤   ¤   else
595b34 ¤   ¤   {
ced0a6 ¤   ¤   ¤   pgpContextMemFree( optionList->context, optionList );
d40abb ¤   ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
100fe4 ¤   ¤   }
a39371 ¤   }
020e24 ¤   else
42c7a1 ¤   {
571b17 ¤   ¤   /*
29c388 ¤   ¤   ** We ran out of memory allocating the PGPOptionList (very rare
1c04fe ¤   ¤   ** case). Point at the preallocated option list in the context
18e557 ¤   ¤   ** to handle this case.
b65c12 ¤   ¤   */
d71b52 ¤   ¤
311b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
939371 ¤   }
4f67c5 ¤
9e8233 ¤   return( optionList );
a8efe6 }
9aaf5a
b50335 /*____________________________________________________________________________
2e83f8 ¤   Grow an existing PGPOptionList by a specified number of PGPOption
f6c507 ¤   elements. The new elements are cleared out.
6df7f7 ____________________________________________________________________________*/
3baf5a
7e66dd ¤   static PGPError
3ed61c pgpGrowOptionList(
cae544 ¤   PGPOptionListRef¤   optionList,
b1f2dc ¤   PGPUInt32¤  ¤   ¤   numNewOptions)
74bb36 {
4361e0 ¤   PGPError¤   err;
2d67c5 ¤
aa704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
275ede ¤   pgpAssert( numNewOptions > 0 );
d2af5a
4cbd44 ¤   err = pgpGetOptionListError( optionList );
dfb1f0 ¤   if( IsntPGPError( err ) )
e7c7a1 ¤   {
1128ce ¤   ¤   PGPUInt32¤  ¤   existingListSize;
66c08c ¤   ¤   PGPUInt32¤  ¤   newListSize;
321b52 ¤   ¤
1861c5 ¤   ¤   existingListSize ¤  = sizeof( PGPOption ) * optionList->maxOptions;
0355db ¤   ¤   newListSize ¤   ¤   = existingListSize + ( sizeof( PGPOption ) *
47951b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   numNewOptions );
7e1b52 ¤   ¤
06f493 ¤   ¤   err = pgpContextMemRealloc( optionList->context,
2f454d ¤   ¤   ¤   ¤   ¤   (void **)&optionList->options, newListSize, 0);
1c86f8 ¤   ¤   if( IsntPGPError( err ) )
585b34 ¤   ¤   {
457aad ¤   ¤   ¤   /*
--adcc 0000c50a4c240100254 Page 6 of pgpOptionList.c
02a4cb ¤   ¤   ¤   ** Delete existing option list direct allocation only. Sub-option
9ec5c2 ¤   ¤   ¤   ** lists are still valid.
d13da8 ¤   ¤   ¤   */
cd87c7 ¤   ¤   ¤
be92d2 ¤   ¤   ¤   pgpClearMemory( ((char *)optionList->options) + existingListSize,
46b204 ¤   ¤   ¤   ¤   newListSize - existingListSize );
4294aa ¤   ¤   ¤   ¤   ¤   ¤
2ce9e9 ¤   ¤   ¤   optionList->maxOptions += numNewOptions;
ab0fe4 ¤   ¤   }
de9371 ¤   }
3e67c5 ¤
c8deb7 ¤   return( err );
a1efe6 }
d8af5a
7166dd ¤   static PGPError
05e246 pgpCopyOption(
dc520e ¤   PGPContextRef¤  context,
3b55a3 ¤   const PGPOption¤*sourceOption,
16261b ¤   PGPOption¤  ¤   *destOption)
8fbb36 {
c78e12 ¤   PGPError¤   err = kPGPError_NoErr;
a267c5 ¤
8cd9dd ¤   pgpAssertAddrValid( sourceOption, PGPOption );
78fdff ¤   pgpAssertAddrValid( destOption, PGPOption );
17af5a
05a9cf ¤   *destOption ¤   ¤   ¤   = *sourceOption;
9dfc55 ¤   destOption->subOptions¤ = kInvalidPGPOptionListRef;
5f7b39 ¤   destOption->handlerProc = NULL;
8767c5 ¤
593d1a ¤   if( IsntNull( sourceOption->handlerProc ) )
34c7a1 ¤   {
e4ee08 ¤   ¤   /* We have a handler proc, so a deep copy is possibly needed. */
acaf5a
37ec72 ¤   ¤   err = (*sourceOption->handlerProc)(
e0dd42 ¤   ¤   ¤   ¤   ¤   context,
4a791b ¤   ¤   ¤   ¤   ¤   kPGPOptionHandler_CopyDataOperation,
554333 ¤   ¤   ¤   ¤   ¤   sourceOption->type,
7019b5 ¤   ¤   ¤   ¤   ¤   sourceOption->value, sourceOption->valueSize,
d06207 ¤   ¤   ¤   ¤   ¤   &destOption->value, &destOption->valueSize );
de86f8 ¤   ¤   if( IsntPGPError( err ) )
805b34 ¤   ¤   {
a8a41c ¤   ¤   ¤   destOption->handlerProc = sourceOption->handlerProc;
240fe4 ¤   ¤   }
159371 ¤   }
77af5a
d39830 ¤   if( IsntPGPError( err ) &&
1dd358 ¤   ¤   PGPOptionListRefIsValid( sourceOption->subOptions ) )
afc7a1 ¤   {
61fec1 ¤   ¤   destOption->subOptions = pgpCopyOptionList( sourceOption->subOptions );
6e9ce0 ¤   ¤   err = pgpGetOptionListError( destOption->subOptions );
6a9371 ¤   }
2d67c5 ¤
4cdeb7 ¤   return( err );
9aefe6 }
2daf5a
240335 /*____________________________________________________________________________
27dbc7 ¤   Add a single PGPOption to a PGPOptionList. The option is added such that
4f7cc8 ¤   the options in the list are kept in ascending type order. No policy is
15f57f ¤   enforced at this point about which options are duplicates.
4af7f7 ____________________________________________________________________________*/
a4af5a
af66dd ¤   static PGPError
768592 pgpAddOptionToPGPOptionList(
7ce544 ¤   PGPOptionListRef¤   optionList,
dc36ef ¤   const PGPOption¤¤   *newOption)
c9bb36 {
2661e0 ¤   PGPError¤   err;
96af5a
21704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
ad61b3 ¤   pgpAssertAddrValid( newOption, PGPOption );
c7af5a
0cbd44 ¤   err = pgpGetOptionListError( optionList );
--3a7a 000fdc72aa740100254 Page 7 of pgpOptionList.c
54b1f0 ¤   if( IsntPGPError( err ) )
f1c7a1 ¤   {
94cd18 ¤   ¤   /* Do we need to grow the list? */
d83831 ¤   ¤   if( optionList->numOptions == optionList->maxOptions )
8c5b34 ¤   ¤   {
8d21d5 ¤   ¤   ¤   err = pgpGrowOptionList( optionList,
2074a2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionList_NumGrowElements );
450fe4 ¤   ¤   }
5a67c5 ¤
ee86f8 ¤   ¤   if( IsntPGPError( err ) )
5f5b34 ¤   ¤   {
4cfaa5 ¤   ¤   ¤   PGPOption¤  addedOption;
4687c7 ¤   ¤   ¤
5c0e2c ¤   ¤   ¤   addedOption = *newOption;
ab87c7 ¤   ¤   ¤
f9faf6 ¤   ¤   ¤   addedOption.flags &= ~(kPGPOptionFlag_Recognized |
5c34c3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Frozen );
6e87c7 ¤   ¤   ¤
0ffa4f ¤   ¤   ¤   optionList->options[optionList->numOptions] = addedOption;
2b6e5a ¤   ¤   ¤   ++optionList->numOptions;
840fe4 ¤   ¤   }
349371 ¤   }
3c67c5 ¤
4b4708 ¤   pgpSetOptionListError( optionList, err );
d867c5 ¤
b7deb7 ¤   return( err );
2fefe6 }
0caf5a
dbaf5a
7a13fb ¤   PGPOptionListRef
3856fb pgpCopyOptionList(PGPOptionListRef optionList)·
94bb36 {
e9f209 ¤   PGPOptionListRef¤   newOptionList;
9b8f52 ¤   PGPError¤   ¤   ¤   err;
0867c5 ¤
36d075 ¤   newOptionList = pgpNewOptionList( optionList->context, FALSE );
d6af5a
3c1a22 ¤   err = pgpGetOptionListError( newOptionList );¤
adb1f0 ¤   if( IsntPGPError( err ) )
aec7a1 ¤   {
ef65f6 ¤   ¤   err = pgpGetOptionListError( optionList );
e986f8 ¤   ¤   if( IsntPGPError( err ) )
0b5b34 ¤   ¤   {
461b1d ¤   ¤   ¤   PGPUInt32¤  optionIndex;
8987c7 ¤   ¤   ¤
e0540c ¤   ¤   ¤   for( optionIndex = 0; optionIndex < optionList->numOptions;
d1dccb ¤   ¤   ¤   ¤   ¤   optionIndex++)
c7f776 ¤   ¤   ¤   {
d62039 ¤   ¤   ¤   ¤   PGPOption¤  newOption;
9b2b85 ¤   ¤   ¤   ¤
6c8aab ¤   ¤   ¤   ¤   err = pgpCopyOption( optionList->context,
ce3b5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   &optionList->options[optionIndex],
19a446 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newOption );
865565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
f072c3 ¤   ¤   ¤   ¤   {
c25ac2 ¤   ¤   ¤   ¤   ¤   err = pgpAddOptionToPGPOptionList( newOptionList,
119d83 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newOption );
102613 ¤   ¤   ¤   ¤   }
832b85 ¤   ¤   ¤   ¤
3e9c8a ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
6f14c3 ¤   ¤   ¤   ¤   ¤   break;
70a3a6 ¤   ¤   ¤   }
ba0fe4 ¤   ¤   }
ac9371 ¤   }
cd67c5 ¤
d51d3d ¤   pgpSetOptionListError( newOptionList, err );
2267c5 ¤
3d8673 ¤   return( newOptionList );
f8efe6 }
82af5a
4f0335 /*____________________________________________________________________________
fdf6b0 ¤   Merge all of the OptionList records from sourceOptionList into
--5819 0005d9683cd40100254 Page 8 of pgpOptionList.c
6f1d4b ¤   destOptionList and dispose of sourceOptionList if it is not a persistent
835ba1 ¤   list. Assumes both option lists are real.
39f7f7 ____________________________________________________________________________*/
a1af5a
4466dd ¤   static PGPError
5b66bd pgpMergeOptionLists(
00f852 ¤   PGPOptionListRef¤   sourceOptionList,
e48c1f ¤   PGPOptionListRef¤   destOptionList)
9cbb36 {
318e12 ¤   PGPError¤   err = kPGPError_NoErr;
6b67c5 ¤
11be16 ¤   pgpAssert( pgpOptionListIsValid( sourceOptionList ) );
0853cb ¤   pgpAssert( pgpOptionListIsReal( sourceOptionList ) );
c307cc ¤   pgpAssert( pgpOptionListIsValid( destOptionList ) );
977d3b ¤   pgpAssert( pgpOptionListIsReal( destOptionList ) );
dc67c5 ¤
c8d71a ¤   err = pgpGetOptionListError( sourceOptionList );
f7b1f0 ¤   if( IsntPGPError( err ) )
45c7a1 ¤   {
50f90d ¤   ¤   err = pgpGetOptionListError( destOptionList );
1786f8 ¤   ¤   if( IsntPGPError( err ) )
6d5b34 ¤   ¤   {
361b1d ¤   ¤   ¤   PGPUInt32¤  optionIndex;
1f87c7 ¤   ¤   ¤
6ef806 ¤   ¤   ¤   if((sourceOptionList->flags & kPGPOptionListFlag_PersistentList)
48332f ¤   ¤   ¤   ¤   ¤   != 0)
b0f776 ¤   ¤   ¤   {
301133 ¤   ¤   ¤   ¤   /* Create a non-persistent copy of the source list */
83f69d ¤   ¤   ¤   ¤   sourceOptionList = pgpCopyOptionList(
cbfa93 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sourceOptionList );
e044b5 ¤   ¤   ¤   ¤   err = pgpGetOptionListError( sourceOptionList );
bea3a6 ¤   ¤   ¤   }
e287c7 ¤   ¤   ¤
ae698b ¤   ¤   ¤   if( IsntPGPError( err ) )
5af776 ¤   ¤   ¤   {
a2557b ¤   ¤   ¤   ¤   for( optionIndex = 0;
f997af ¤   ¤   ¤   ¤   ¤   ¤   optionIndex < sourceOptionList->numOptions;
2f641d ¤   ¤   ¤   ¤   ¤   ¤   ++optionIndex )
6672c3 ¤   ¤   ¤   ¤   {
ff7fe8 ¤   ¤   ¤   ¤   ¤   PGPOption¤  *curSourceOption;
aaae30 ¤   ¤   ¤   ¤   ¤
6353d1 ¤   ¤   ¤   ¤   ¤   curSourceOption = &sourceOptionList->options[optionIndex];
80ae30 ¤   ¤   ¤   ¤   ¤
838340 ¤   ¤   ¤   ¤   ¤   err = pgpAddOptionToPGPOptionList( destOptionList,
63f311 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curSourceOption );
b66ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
164859 ¤   ¤   ¤   ¤   ¤   {
e3a3e7 ¤   ¤   ¤   ¤   ¤   /*
176400 ¤   ¤   ¤   ¤   ¤   **¤ We have "moved" the option to the destination list.
c8485c ¤   ¤   ¤   ¤   ¤   **¤ At this point we need to clear the option in the
5b897d ¤   ¤   ¤   ¤   ¤   ** ¤source list so that allocated resources are not
6cc85b ¤   ¤   ¤   ¤   ¤   **¤ disposed when the list is freed. Those resources
bc5124 ¤   ¤   ¤   ¤   ¤   **¤ are now owned by the destination list.
b1e4e2 ¤   ¤   ¤   ¤   ¤   */
2c94aa ¤   ¤   ¤   ¤   ¤   ¤
98960a ¤   ¤   ¤   ¤   ¤   ¤   pgpClearMemory( curSourceOption,
3ee8c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof(*curSourceOption));
b11c89 ¤   ¤   ¤   ¤   ¤   }
dd4bd6 ¤   ¤   ¤   ¤   ¤   else
694859 ¤   ¤   ¤   ¤   ¤   {
5500eb ¤   ¤   ¤   ¤   ¤   ¤   break;
161c89 ¤   ¤   ¤   ¤   ¤   }
802613 ¤   ¤   ¤   ¤   }
c5a3a6 ¤   ¤   ¤   }
a80fe4 ¤   ¤   }
6c9371 ¤   }
ea67c5 ¤
7b7868 ¤   pgpFreeOptionListInternal( sourceOptionList, FALSE );
1d0559 ¤   pgpSetOptionListError( destOptionList, err );
8a67c5 ¤
4cdeb7 ¤   return( err );
5defe6 }
--7b44 000ee523a4740100254 Page 9 of pgpOptionList.c
e0af5a
7e0335 /*____________________________________________________________________________
6da407 ¤   Compose a new option list which is built from one or more component lists.
a2a9a7 ¤   The component lists are deleted.
35f7f7 ____________________________________________________________________________*/
73af5a
63c744 ¤   PGPError
9c969f pgpAppendOptionListArgs(
a2e544 ¤   PGPOptionListRef¤   optionList,
f241a1 ¤   PGPOptionListRef¤   firstOption,
2a8c91 ¤   va_list ¤   ¤   ¤   remainingOptions)·
b9bb36 {
c78f52 ¤   PGPError¤   ¤   ¤   err;
ba0626 ¤   PGPOptionListRef¤   curOptionList;
d667c5 ¤
0bce1b ¤   /* Initialize err to the initial state of the list */
38bd44 ¤   err = pgpGetOptionListError( optionList );
0aaf5a
1d6fed ¤   /* Always process all arguments even though the list may already be
fe0b28 ¤   ···in error. We do this because we may need to dispose of an input */
bf1b52 ¤   ¤
ef5fac ¤   curOptionList = firstOption;
8bc2f4 ¤   while( curOptionList != kPGPEndOfArgsOptionListRef )
61c7a1 ¤   {
c156c5 ¤   ¤   if( curOptionList != kPGPNullOptionListRef )
a05b34 ¤   ¤   {
f83b4c ¤   ¤   ¤   pgpAssert( pgpOptionListIsValid( curOptionList ) );
ec87c7 ¤   ¤   ¤
c94471 ¤   ¤   ¤   if( pgpOptionListIsValid( curOptionList ) )
aff776 ¤   ¤   ¤   {
6fbe41 ¤   ¤   ¤   ¤   PGPBoolean¤ freeCurOptionList = TRUE;
ac2b85 ¤   ¤   ¤   ¤
135565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
da72c3 ¤   ¤   ¤   ¤   {
ef5dfb ¤   ¤   ¤   ¤   ¤   err = pgpGetOptionListError( curOptionList );
f66ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
d64859 ¤   ¤   ¤   ¤   ¤   {
6f9acd ¤   ¤   ¤   ¤   ¤   ¤   err = pgpMergeOptionLists(
9996fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curOptionList,
e40174 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   optionList );
d094aa ¤   ¤   ¤   ¤   ¤   ¤
31eb7d ¤   ¤   ¤   ¤   ¤   ¤   freeCurOptionList = FALSE;
d51c89 ¤   ¤   ¤   ¤   ¤   }
662613 ¤   ¤   ¤   ¤   }
0b2b85 ¤   ¤   ¤   ¤
ce1516 ¤   ¤   ¤   ¤   if( freeCurOptionList )
5772c3 ¤   ¤   ¤   ¤   {
5f42ac ¤   ¤   ¤   ¤   ¤   pgpFreeOptionListInternal( curOptionList, FALSE );
772613 ¤   ¤   ¤   ¤   }
62a3a6 ¤   ¤   ¤   }
d73c7b ¤   ¤   ¤   else if( IsntPGPError( err ) )
31f776 ¤   ¤   ¤   {
9f566c ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
b3a3a6 ¤   ¤   ¤   }
a70fe4 ¤   ¤   }
151b52 ¤   ¤
43c283 ¤   ¤   curOptionList = va_arg( remainingOptions, PGPOptionListRef );
759371 ¤   }
f867c5 ¤
a34708 ¤   pgpSetOptionListError( optionList, err );
0567c5 ¤
75deb7 ¤   return( err );
11efe6 }
67af5a
c2af5a
7b0335 /*____________________________________________________________________________
74a407 ¤   Compose a new option list which is built from one or more component lists.
c9a9a7 ¤   The component lists are deleted.
83f7f7 ____________________________________________________________________________*/
47c744 ¤   PGPError
a46301 pgpFreeVarArgOptionList(
ee41a1 ¤   PGPOptionListRef¤   firstOption,
--1600 000ef220bdc40100254 Page 10 of pgpOptionList.c
71f176 ¤   va_list¤¤   ¤   ¤   args)·
a8bb36 {
2bd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
7d0626 ¤   PGPOptionListRef¤   curOptionList;
d5af5a
ce6fed ¤   /* Always process all arguments even though the list may already be
6b0b28 ¤   ···in error. We do this because we may need to dispose of an input */
631b52 ¤   ¤
8b5fac ¤   curOptionList = firstOption;
1cc2f4 ¤   while( curOptionList != kPGPEndOfArgsOptionListRef )
aec7a1 ¤   {
c456c5 ¤   ¤   if( curOptionList != kPGPNullOptionListRef )
1f5b34 ¤   ¤   {
9a3b4c ¤   ¤   ¤   pgpAssert( pgpOptionListIsValid( curOptionList ) );
9c4471 ¤   ¤   ¤   if( pgpOptionListIsValid( curOptionList ) )
d8f776 ¤   ¤   ¤   {
035120 ¤   ¤   ¤   ¤   pgpFreeOptionListInternal( curOptionList, FALSE );
12a3a6 ¤   ¤   ¤   }
843c7b ¤   ¤   ¤   else if( IsntPGPError( err ) )
1af776 ¤   ¤   ¤   {
283227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
abc7f4 ¤   ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
42a3a6 ¤   ¤   ¤   }
aa0fe4 ¤   ¤   }
851b52 ¤   ¤
9df291 ¤   ¤   curOptionList = va_arg( args, PGPOptionListRef );
be9371 ¤   }
9967c5 ¤
62deb7 ¤   return( err );
09efe6 }
ffaf5a
c8af5a
6e0335 /*____________________________________________________________________________
a9a407 ¤   Compose a new option list which is built from one or more component lists.
a2a9a7 ¤   The component lists are deleted.
74f7f7 ____________________________________________________________________________*/
45af5a
da13fb ¤   PGPOptionListRef
70b2f5 pgpBuildOptionListArgs(
18a1bc ¤   PGPContextRef¤  ¤   context,
9d9417 ¤   PGPBoolean¤ ¤   ¤   createPersistentList,
b341a1 ¤   PGPOptionListRef¤   firstOption,
048c91 ¤   va_list ¤   ¤   ¤   remainingOptions)·
96bb36 {
ebf209 ¤   PGPOptionListRef¤   newOptionList;
6167c5 ¤
05e610 ¤   /* Note that pgpNewOptionList can never return NULL */
b91075 ¤   newOptionList = pgpNewOptionList( context, createPersistentList );
9367c5 ¤
87faf7 ¤   pgpAppendOptionListArgs( newOptionList, firstOption, remainingOptions );
ab67c5 ¤
3c8673 ¤   return( newOptionList );
5aefe6 }
b9af5a
eaaf5a
29af5a
d9af5a
ba0335 /*____________________________________________________________________________
94d640 ¤   Find the first occurrence of an option in a list and return its value
7eb000 ¤   and how many options exist of that type.
caf7f7 ____________________________________________________________________________*/
a7af5a
02c744 ¤   PGPError
21a181 pgpGetIndexedOptionType(
78e544 ¤   PGPOptionListRef¤   optionList,
87d168 ¤   PGPOptionType¤  ¤   optionType,
aa807b ¤   PGPUInt32¤  ¤   ¤   searchIndex,
626a8b ¤   PGPBoolean¤ ¤   ¤   markAsRecognized,
6206b4 ¤   PGPOption¤  ¤   ¤   *optionData,
1ba6a8 ¤   PGPUInt32¤  ¤   ¤   *numFoundOptions)
02bb36 {
ef9d23 ¤   PGPUInt32¤  optionIndex;
--1b2a 0007a3e6bf640100254 Page 11 of pgpOptionList.c
b461e0 ¤   PGPError¤   err;
31438c ¤   PGPUInt32¤  foundOptions;
2c6cbb ¤   PGPOption¤  *curOption;
d767c5 ¤
fa1d07 ¤   if( IsntNull( numFoundOptions ) )
9aed78 ¤   ¤   *numFoundOptions = 0;
0f1b52 ¤   ¤
d41189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
a067c5 ¤
6337d0 ¤   foundOptions ¤  = 0;
5eba3f ¤   err¤¤   ¤   ¤   = kPGPError_OptionNotFound;
6e0767 ¤   curOption¤  ¤   = optionList->options;
7a67c5 ¤
1885f9 ¤   for(optionIndex = 0; optionIndex < optionList->numOptions; optionIndex++)
9bc7a1 ¤   {
79d628 ¤   ¤   if( curOption->type == optionType )
0e5b34 ¤   ¤   {
947478 ¤   ¤   ¤   if( foundOptions == searchIndex )
13f776 ¤   ¤   ¤   {
744439 ¤   ¤   ¤   ¤   if( IsntNull( optionData ) )
5172c3 ¤   ¤   ¤   ¤   {
e5d6ce ¤   ¤   ¤   ¤   ¤   pgpAssertAddrValid( optionData, PGPOption );
9b87c7 ¤   ¤   ¤
959858 ¤   ¤   ¤   ¤   ¤   if( markAsRecognized )
3c4859 ¤   ¤   ¤   ¤   ¤   {
0f86a9 ¤   ¤   ¤   ¤   ¤   ¤   curOption->flags |= kPGPOptionFlag_Recognized;
c81c89 ¤   ¤   ¤   ¤   ¤   }
aeae30 ¤   ¤   ¤   ¤   ¤
4a5b10 ¤   ¤   ¤   ¤   ¤   *optionData = *curOption;
632613 ¤   ¤   ¤   ¤   }
e8ae30 ¤   ¤   ¤   ¤   ¤
8cbd37 ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
36a3a6 ¤   ¤   ¤   }
2887c7 ¤   ¤   ¤
2fdd50 ¤   ¤   ¤   ++foundOptions;
ec0fe4 ¤   ¤   }
7d1b52 ¤   ¤
59f0d6 ¤   ¤   ++curOption;
379371 ¤   }
2087c7 ¤   ¤   ¤
f11d07 ¤   if( IsntNull( numFoundOptions ) )
bbc7a1 ¤   {
dd5cc7 ¤   ¤   pgpAssertAddrValid( numFoundOptions, PGPUInt32 );
f17c99 ¤   ¤   *numFoundOptions = foundOptions;
b99371 ¤   }
d267c5 ¤
4ddeb7 ¤   return( err );
d0efe6 }
49af5a
cf0335 /*____________________________________________________________________________
3b7a7e ¤   Get the Nth option in a list and return its value. Returns
c7687c ¤   kPGPError_OptionNotFound if the index is out of range
f0f7f7 ____________________________________________________________________________*/
f0af5a
42c744 ¤   PGPError
0ea360 pgpGetIndexedOption(
23e544 ¤   PGPOptionListRef¤   optionList,
23807b ¤   PGPUInt32¤  ¤   ¤   searchIndex,
106a8b ¤   PGPBoolean¤ ¤   ¤   markAsRecognized,
1b780c ¤   PGPOption¤  ¤   ¤   *optionData)
45bb36 {
4a8e12 ¤   PGPError¤   err = kPGPError_NoErr;
3267c5 ¤
da1189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
9f67c5 ¤
2141a1 ¤   if( searchIndex < optionList->numOptions )
67c7a1 ¤   {
d95b98 ¤   ¤   if( markAsRecognized )
3f5b34 ¤   ¤   {
e7bdd4 ¤   ¤   ¤   optionList->options[searchIndex].flags |=
b8c39e ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Recognized;
7a0fe4 ¤   ¤   }
--a9cb 000f21a562440100254 Page 12 of pgpOptionList.c
e0af5a
3a322b ¤   ¤   *optionData = optionList->options[searchIndex];
6c9371 ¤   }
000e24 ¤   else
74c7a1 ¤   {
a17e6d ¤   ¤   err = kPGPError_OptionNotFound;
de9371 ¤   }
bf67c5 ¤
c3deb7 ¤   return( err );
15efe6 }
2daf5a
ffaf5a
630335 /*____________________________________________________________________________
4a0c91 ····Test an option list and make sure all options are in the given set.
6f7ebd ····The option set is an array of option numbers. ·Returns kPGPError_BadParams
d52e03 ¤   if an option is not in the set.
ebf7f7 ____________________________________________________________________________*/
c5af5a
03c744 ¤   PGPError
2feb8e pgpCheckOptionsInSet(
dee544 ¤   PGPOptionListRef¤   optionList,
8a0f82 ¤   PGPOptionType const¤*optionSet,
be28a9 ¤   PGPUInt32¤  ¤   ¤   optionSetSize)
e1bb36 {
289d23 ¤   PGPUInt32¤  optionIndex;
7b8192 ¤   PGPUInt32¤  setIndex;
0026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
e567c5 ¤
5a1189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
da67c5 ¤
75678c ¤   for( optionIndex = 0; optionIndex < optionList->numOptions; optionIndex++)
aac7a1 ¤   {
ba06e8 ¤   ¤   PGPOptionType type;
45af5a
911600 ¤   ¤   type = optionList->options[optionIndex].type;
94af5a
733ad5 ¤   ¤   for( setIndex = 0; setIndex < optionSetSize; setIndex++ )
fe5b34 ¤   ¤   {
fed2c3 ¤   ¤   ¤   if (type == optionSet[setIndex])
86f622 ¤   ¤   ¤   ¤   break;
cd0fe4 ¤   ¤   }
08af5a
9f6cfd ¤   ¤   /* didn't find option in the list */
88d495 ¤   ¤   if( setIndex == optionSetSize )
825b34 ¤   ¤   {
429126 ¤   ¤   ¤   pgpDebugFmtMsg(( pgpaFmtPrefix,
136368 ¤   ¤   ¤   ¤   "Error: Illegal PGPO option #%ld",
b43e24 ¤   ¤   ¤   ¤   (long)type ));
a01b52 ¤   ¤
37fdcd ¤   ¤   ¤   err¤= kPGPError_BadParams;
f8cdcb ¤   ¤   ¤   break;
c10fe4 ¤   ¤   }
339371 ¤   }
46af5a
bd5ea8 ¤   return err;
f8efe6 }
e6af5a
20af5a
0daf5a
b7c744 ¤   PGPError
86afdf pgpAddJobOptionsArgs(
46cad7 ¤   PGPJobRef¤  ¤   ¤   job,
0041a1 ¤   PGPOptionListRef¤   firstOption,
762ffe ¤   va_list¤¤   ¤   ¤   remainingOptions)
32bb36 {
328008 ¤   PGPError¤   ¤   ¤   error;
903ddd ¤   PGPOptionListRef¤   optionList;
5d67c5 ¤
b035b0 ¤   pgpAssert( IsntNull( job ) );
ec67c5 ¤
410f44 ¤   optionList = pgpBuildOptionListArgs( job->context,
f2785d ¤   ¤   ¤   ¤   ¤   FALSE, firstOption, remainingOptions );
--6d4a 000a91d5c6340100254 Page 13 of pgpOptionList.c
2a67c5 ¤
89ebe1 ¤   error = pgpGetOptionListError( optionList );
f0408c ¤   if( IsntPGPError( error ) )
a5c7a1 ¤   {
960c50 ¤   ¤   job->newOptionList = optionList;
969371 ¤   }
fd67c5 ¤
be57f8 ¤   return( error );
b8efe6 }
98af5a
3e13fb ¤   PGPOptionListRef
dc2ea9 pgpNewOneOptionList(
6da1bc ¤   PGPContextRef¤  ¤   context,
77020b ¤   const PGPOption¤*¤  option)
43bb36 {
523ddd ¤   PGPOptionListRef¤   optionList;
3e67c5 ¤
4a01a1 ¤   pgpAssertAddrValid( option, PGPOption );
0967c5 ¤
f9ce59 ¤   optionList = pgpNewOptionList( context, FALSE );
d8f7c2 ¤   if( IsntPGPError( pgpGetOptionListError( optionList ) ) )
6ac7a1 ¤   {
d86ed6 ¤   ¤   (void) pgpAddOptionToPGPOptionList( optionList, option );
209371 ¤   }
4a1b52 ¤   ¤
c98233 ¤   return( optionList );
cfefe6 }
5caf5a
2cf6ce /* Read an option, marking it read, and only allow one instance of it */
e7af5a
61c744 ¤   PGPError
7bfa5c pgpSearchOptionSingle(
92e099 ¤   PGPOptionListRef¤   ·optionList,
7acdac ¤   PGPOptionType¤  ¤   ·optionType,
2e780c ¤   PGPOption¤  ¤   ¤   *optionData)
2cbb36 {
7040bf ¤   PGPUInt32¤  ¤   ¤   ·numFound;
fc05a0 ¤   PGPError¤   ¤   ¤   ·err = kPGPError_NoErr;
49af5a
3c837f ¤   pgpa( pgpaAddrValid( optionData, PGPOption ) );
0bab54 ¤   optionData->type = kPGPOptionType_InvalidOption;
c8af5a
d8ee6d ¤   numFound = 0;
5280b2 ¤   if( IsntNull( optionList ) ) {
42e8ab ¤   ¤   if( IsPGPError( err = pgpGetIndexedOptionType( optionList,
4232b1 ¤   ¤   ¤   ¤   ¤   ¤   ···optionType, 0, TRUE, optionData, &numFound ) ) ) {
d217eb ¤   ¤   ¤   if (err != kPGPError_OptionNotFound)
a5454a ¤   ¤   ¤   ¤   return err;
e4fcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
9a0fe4 ¤   ¤   }
f09371 ¤   }
35dd79 ¤   if( numFound > 1 ) {
bf8f66 ¤   ¤   err = kPGPError_RedundantOptions;
e79371 ¤   }
2766d9 ¤   if ( numFound < 1 ) {
59c467 ¤   ¤   optionData->type = kPGPOptionType_InvalidOption;
cb9371 ¤   }
355ea8 ¤   return err;
7befe6 }
13af5a
45c030 /* Read the nth (searchIndex'th) instance of an option, marking it read */
6faf5a
f8c744 ¤   PGPError
9a85cb pgpSearchOption(
5ae099 ¤   PGPOptionListRef¤   ·optionList,
8fcdac ¤   PGPOptionType¤  ¤   ·optionType,
f6a051 ¤   PGPUInt32¤  ¤   ¤   ·searchIndex,
77c058 ¤   PGPOption¤  ¤   ¤   *optionData
3627e6 ¤   )
b3bb36 {
fa40bf ¤   PGPUInt32¤  ¤   ¤   ·numFound;
a905a0 ¤   PGPError¤   ¤   ¤   ·err = kPGPError_NoErr;
--5372 000338fc8b840100254 Page 14 of pgpOptionList.c
e0af5a
ec837f ¤   pgpa( pgpaAddrValid( optionData, PGPOption ) );
9dab54 ¤   optionData->type = kPGPOptionType_InvalidOption;
dfaf5a
faee6d ¤   numFound = 0;
af80b2 ¤   if( IsntNull( optionList ) ) {
b2e8ab ¤   ¤   if( IsPGPError( err = pgpGetIndexedOptionType( optionList,
4a58bd ¤   ¤   ¤   ¤   ··optionType, searchIndex, TRUE, optionData, &numFound ) ) ) {
a417eb ¤   ¤   ¤   if (err != kPGPError_OptionNotFound)
48454a ¤   ¤   ¤   ¤   return err;
ecfcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
990fe4 ¤   ¤   }
b99371 ¤   }
4a4abd ¤   if( searchIndex >= numFound ) {
3ac467 ¤   ¤   optionData->type = kPGPOptionType_InvalidOption;
1c9371 ¤   }
045ea8 ¤   return err;
7befe6 }
64af5a
fbaf5a
41debc /* Find an option and return its arguments if any.
ac775e ·*
3c2c3e ·* Takes a parameter string consisting of "%d%p%t" values, where %d means
bbdca6 ·* a 32-bit scalar, %p means a pointer, and %t means a timeinterval.
9be03e ·* These are packed in a special way in the optionlist code, which this
9e5c3a ·* routine has to know about. ·A special case is "%p%l", meaning a pointer
660012 ·* and length pair.
b179be ·* If the first two characters are %b then we return a boolean telling whether
b395c7 ·* the option was found.
6a5d1e ·* If the fMandatory flag is set, returns an error if the option doesn't
5b77fd ·* exist.
f3495d ·*/
7caf5a
1cc744 ¤   PGPError
99a212 pgpFindOptionArgs(
88e099 ¤   PGPOptionListRef¤   ·optionList,
95cdac ¤   PGPOptionType¤  ¤   ·optionType,
99b424 ¤   PGPBoolean¤ ¤   ¤   ·fMandatory,
eecd3e ¤   const char¤ ¤   ¤   *str,
c0c9f6 ¤   ...
3827e6 ¤   )
5bbb36 {
4501d3 ¤   va_list¤¤   ¤   ¤   args;
5ef936 ¤   PGPOption¤  ¤   ¤   op;
5e112f ¤   PGPInt32¤   ¤   ¤   *ptrInt32;
ebc126 ¤   void¤   ¤   ¤   ¤   **ptrPtr;
e6f9cc ¤   PGPTime¤¤   ¤   ¤   *ptrTime;
f451b3 ¤   PGPTimeInterval¤¤   *ptrTimeInterval;
fc9ca5 ¤   PGPSize¤¤   ¤   ¤   *ptrSize;
2bd229 ¤   PGPBoolean¤ ¤   ¤   *ptrBool;
3a7ddc ¤   PGPByte¤¤   ¤   ¤   *ptr;
0e7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
1eaf5a
34650c ¤   pgpa( pgpaAddrValid( str, char ) );
aeaf5a
247e72 ¤   if( IsPGPError( err = pgpSearchOptionSingle( optionList,
82b53f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·optionType, &op ) ) )
3c97ed ¤   ¤   goto error;
f5af5a
814111 ¤   va_start( args, str );
5daf5a
9d2bf0 ¤   /* Handle %b */
3758af ¤   if( str[0] == '%' && str[1] == 'b' ) {
796013 ¤   ¤   ptrBool = va_arg( args, PGPBoolean * );
1f70f4 ¤   ¤   *ptrBool = IsOp( op );
480249 ¤   ¤   str += 2;
d19371 ¤   }
0518d9 ¤   /* Handle other options */
fb7343 ¤   if( IsOp( op ) ) {
06e294 ¤   ¤   if( strlen( str ) == 2 ) {
252f05 ¤   ¤   ¤   /* Single options get stored in simple form */
33ae38 ¤   ¤   ¤   if (str[0] != '%') {
--7942 000a7d62efe40100254 Page 15 of pgpOptionList.c
e1566c ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
381b7c ¤   ¤   ¤   ¤   goto error;
dea3a6 ¤   ¤   ¤   }
ff24ff ¤   ¤   ¤   switch( str[1] ) {
08c571 ¤   ¤   ¤   case 'd':
7c63f7 ¤   ¤   ¤   ¤   ptrInt32 = va_arg( args, PGPInt32 * );
73aee2 ¤   ¤   ¤   ¤   *ptrInt32 = op.value.asInt;
44f622 ¤   ¤   ¤   ¤   break;
1e743c ¤   ¤   ¤   case 'p':
0a0129 ¤   ¤   ¤   ¤   ptrPtr = va_arg( args, void ** );
cc5852 ¤   ¤   ¤   ¤   *ptrPtr = op.value.asPtr;
8cf622 ¤   ¤   ¤   ¤   break;
f006d0 ¤   ¤   ¤   case 't':
299902 ¤   ¤   ¤   ¤   ptrTimeInterval = va_arg( args, PGPTimeInterval * );
12ddaf ¤   ¤   ¤   ¤   *ptrTimeInterval = op.value.asInterval;
3af622 ¤   ¤   ¤   ¤   break;
338983 ¤   ¤   ¤   case 'T':
526403 ¤   ¤   ¤   ¤   ptrTime = va_arg( args, PGPTime * );
968865 ¤   ¤   ¤   ¤   *ptrTime = op.value.asTime;
bcf622 ¤   ¤   ¤   ¤   break;
f9db68 ¤   ¤   ¤   default:
4e566c ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
d31b7c ¤   ¤   ¤   ¤   goto error;
aea3a6 ¤   ¤   ¤   }
b23271 ¤   ¤   ¤   va_end( args );
8cfc52 ¤   ¤   } else if( strcmp( str, "%p%l" ) == 0 ) {
2341ed ¤   ¤   ¤   /* Special case, still uses simple form */
a04e17 ¤   ¤   ¤   ptrPtr = va_arg( args, void ** );
7964bc ¤   ¤   ¤   *ptrPtr = op.value.asPtr;
338bf1 ¤   ¤   ¤   ptrSize = va_arg( args, PGPSize * );
14f987 ¤   ¤   ¤   *ptrSize = op.valueSize;
273271 ¤   ¤   ¤   va_end( args );
b145a6 ¤   ¤   } else {
ccb1e9 ¤   ¤   ¤   /* Get data out of second-order block */
980191 ¤   ¤   ¤   ptr = ( PGPByte * ) op.value.asPtr;
8df23e ¤   ¤   ¤   while( *str++ == '%' ) {
470687 ¤   ¤   ¤   ¤   switch( *str++ ) {
5b02c4 ¤   ¤   ¤   ¤   case 'd':
c564cc ¤   ¤   ¤   ¤   ¤   ptrInt32 = va_arg( args, PGPInt32 * );
b5b6d2 ¤   ¤   ¤   ¤   ¤   *ptrInt32 = *( ( PGPInt32 * ) ptr );
5d8044 ¤   ¤   ¤   ¤   ¤   ptr += sizeof( PGPInt32 );
ee14c3 ¤   ¤   ¤   ¤   ¤   break;
c1b389 ¤   ¤   ¤   ¤   case 'p':
30af28 ¤   ¤   ¤   ¤   ¤   ptrPtr = va_arg( args, void ** );
72dbc0 ¤   ¤   ¤   ¤   ¤   *ptrPtr = *( ( void ** ) ptr );
3e7721 ¤   ¤   ¤   ¤   ¤   ptr += sizeof( void * );
ee14c3 ¤   ¤   ¤   ¤   ¤   break;
58c165 ¤   ¤   ¤   ¤   case 't':
5d9e74 ¤   ¤   ¤   ¤   ¤   ptrTimeInterval = va_arg( args, PGPTimeInterval * );
a4b1d0 ¤   ¤   ¤   ¤   ¤   *ptrTimeInterval = *( ( PGPTimeInterval * ) ptr );
bde92a ¤   ¤   ¤   ¤   ¤   ptr += sizeof( PGPTimeInterval );
d414c3 ¤   ¤   ¤   ¤   ¤   break;
c74e36 ¤   ¤   ¤   ¤   case 'T':
7b0b30 ¤   ¤   ¤   ¤   ¤   ptrTime = va_arg( args, PGPTime * );
4ede25 ¤   ¤   ¤   ¤   ¤   *ptrTime = *( ( PGPTime * ) ptr );
8983a8 ¤   ¤   ¤   ¤   ¤   ptr += sizeof( PGPTime );
0114c3 ¤   ¤   ¤   ¤   ¤   break;
046ab9 ¤   ¤   ¤   ¤   default:
32c7f4 ¤   ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
32b622 ¤   ¤   ¤   ¤   ¤   goto error;
9d2613 ¤   ¤   ¤   ¤   }
a5a3a6 ¤   ¤   ¤   }
ce3271 ¤   ¤   ¤   va_end( args );
cd0fe4 ¤   ¤   }
abf037 ¤   } else {
1d6ec1 ¤   ¤   /* Missing op, fill in parameters */
0319c1 ¤   ¤   ptr = ( PGPByte * ) op.value.asPtr;
cccf56 ¤   ¤   while( *str++ == '%' ) {
f48af8 ¤   ¤   ¤   switch( *str++ ) {
9cc571 ¤   ¤   ¤   case 'd':
af63f7 ¤   ¤   ¤   ¤   ptrInt32 = va_arg( args, PGPInt32 * );
a71634 ¤   ¤   ¤   ¤   *ptrInt32 = (PGPInt32) 0;
--14db 000c05037a240100254 Page 16 of pgpOptionList.c
72f622 ¤   ¤   ¤   ¤   break;
5a20a9 ¤   ¤   ¤   case 'l':
39d8ea ¤   ¤   ¤   ¤   ptrSize = va_arg( args, PGPSize * );
bfd89c ¤   ¤   ¤   ¤   *ptrSize = (PGPSize) 0;
f7f622 ¤   ¤   ¤   ¤   break;
9e743c ¤   ¤   ¤   case 'p':
a90129 ¤   ¤   ¤   ¤   ptrPtr = va_arg( args, void ** );
97c85b ¤   ¤   ¤   ¤   *ptrPtr = NULL;
61f622 ¤   ¤   ¤   ¤   break;
d306d0 ¤   ¤   ¤   case 't':
cd9902 ¤   ¤   ¤   ¤   ptrTimeInterval = va_arg( args, PGPTimeInterval * );
970bb6 ¤   ¤   ¤   ¤   *ptrTimeInterval = (PGPTimeInterval) 0;
80f622 ¤   ¤   ¤   ¤   break;
6e8983 ¤   ¤   ¤   case 'T':
f96403 ¤   ¤   ¤   ¤   ptrTime = va_arg( args, PGPTime * );
364337 ¤   ¤   ¤   ¤   *ptrTime = (PGPTime) 0;
41f622 ¤   ¤   ¤   ¤   break;
d5db68 ¤   ¤   ¤   default:
f8566c ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
8a1b7c ¤   ¤   ¤   ¤   goto error;
33a3a6 ¤   ¤   ¤   }
150fe4 ¤   ¤   }
379957 ¤   ¤   if( fMandatory ) {
ae1b52 ¤   ¤
c09126 ¤   ¤   ¤   pgpDebugFmtMsg(( pgpaFmtPrefix,
6c83ee ¤   ¤   ¤   ¤   "Error: Missing required PGPO option #%ld",
435556 ¤   ¤   ¤   ¤   (long)optionType ));
73af5a
f2f60b ¤   ¤   ¤   err = kPGPError_OptionNotFound;
3eed19 ¤   ¤   ¤   goto error;
eb0fe4 ¤   ¤   }
539371 ¤   }
3e151e ¤   return kPGPError_NoErr;
8760ff error:
d05ea8 ¤   return err;
8cefe6 }
b6af5a
89af5a
30908a /* Delete option list and null out the pointer to it */
31af5a
796d52 ¤   void
41ec67 pgpCleanupOptionList(PGPOptionListRef *optionList)
4cbb36 {
bdf90b ¤   /* XXX check to make sure we have no critical unused options */
e0ddc6 ¤   if( IsntNull( *optionList ) ) {
c52fdf ¤   ¤   pgpFreeOptionList( *optionList );
36a184 ¤   ¤   *optionList = NULL;
7a9371 ¤   }
8cefe6 }
c6af5a
7add0e /********************* Access functions for option data *********************/
7aaf5a
05af5a
99c744 ¤   PGPError
ebc2d3 pgpOptionInt(
d9350b ¤   PGPOption¤  ¤   ¤   *op,
67ffef ¤   PGPInt32¤   ¤   ¤   *pInt
cd2531 ¤   )¤  ¤   ¤   ·
d5bb36 {
79c2a6 ¤   *pInt = op->value.asInt;
55151e ¤   return kPGPError_NoErr;
d1efe6 }
e4af5a
e2c744 ¤   PGPError
ad414b pgpOptionUInt(
50350b ¤   PGPOption¤  ¤   ¤   *op,
a784aa ¤   PGPUInt32¤  ¤   ¤   *pUInt
fe2531 ¤   )¤  ¤   ¤   ·
60bb36 {
24a040 ¤   *pUInt = op->value.asInt;
8e151e ¤   return kPGPError_NoErr;
c0efe6 }
--2d17 000c9f46d8d40100254 Page 17 of pgpOptionList.c
e0af5a
01c744 ¤   PGPError
d9ee21 pgpOptionPtr(
b8a4fc ¤   PGPOption¤  ¤   ¤   ·*op,
e0c293 ¤   void¤   ¤   ¤   ¤   **pPtr
0f2531 ¤   )¤  ¤   ¤   ·
adbb36 {
e19b8d ¤   *pPtr = op->value.asPtr;
d3151e ¤   return kPGPError_NoErr;
55efe6 }
57af5a
2fc744 ¤   PGPError
f2a437 pgpOptionInterval(
80350b ¤   PGPOption¤  ¤   ¤   *op,
172a3a ¤   PGPTimeInterval¤¤   *pInterval
042531 ¤   )¤  ¤   ¤   ·
52bb36 {
bf7e37 ¤   *pInterval = op->value.asInterval;
4f151e ¤   return kPGPError_NoErr;
91efe6 }
5daf5a
1387f4 /* Access option data consisting of a pointer and a length */
786b4c /* This is a special case; the length is in the option itself */
d3c744 ¤   PGPError
0f3548 pgpOptionPtrLength(
54a4fc ¤   PGPOption¤  ¤   ¤   ·*op,
9e7e69 ¤   void¤   ¤   ¤   ¤   **pPtr,
4223ef ¤   PGPSize¤¤   ¤   ¤   ·*pLength
cd2531 ¤   )¤  ¤   ¤   ·
c1bb36 {
b89b8d ¤   *pPtr = op->value.asPtr;
8fa9fa ¤   *pLength = op->valueSize;
ff151e ¤   return kPGPError_NoErr;
cbefe6 }
85af5a
dff278 /* Access option data consisting of a pointer then a pointer */
72c744 ¤   PGPError
b1e673 pgpOptionPtrPtr(
bea4fc ¤   PGPOption¤  ¤   ¤   ·*op,
4d7e69 ¤   void¤   ¤   ¤   ¤   **pPtr,
c871e8 ¤   void¤   ¤   ¤   ¤   **pPtr2
a72531 ¤   )¤  ¤   ¤   ·
30bb36 {
19832c ¤   PGPByte *ptr = ( PGPByte * ) op->value.asPtr;
06bb71 ¤   *pPtr = *( ( void ** ) ptr );
a8f24a ¤   ptr += sizeof( void * );
a106ea ¤   *pPtr2 = *( ( void ** ) ptr );
86151e ¤   return kPGPError_NoErr;
8defe6 }
8aaf5a
9f2808 /* Access option data consisting of a pointer, length, then pointer */
04c744 ¤   PGPError
75c4b3 pgpOptionPtrLengthPtr(
3fa4fc ¤   PGPOption¤  ¤   ¤   ·*op,
497e69 ¤   void¤   ¤   ¤   ¤   **pPtr,
25c763 ¤   PGPSize¤¤   ¤   ¤   ·*pLength,
4c71e8 ¤   void¤   ¤   ¤   ¤   **pPtr2
1f2531 ¤   )¤  ¤   ¤   ·
11bb36 {
91832c ¤   PGPByte *ptr = ( PGPByte * ) op->value.asPtr;
b3bb71 ¤   *pPtr = *( ( void ** ) ptr );
03f24a ¤   ptr += sizeof( void * );
dfa8d3 ¤   *pLength = *( ( PGPSize * ) ptr );
079c97 ¤   ptr += sizeof( PGPSize );
db06ea ¤   *pPtr2 = *( ( void ** ) ptr );
a2151e ¤   return kPGPError_NoErr;
5eefe6 }
c1af5a
3baf5a
680ead /* Allocate and make a copy of a C String */
92af5a
c9d25c ¤   char *
--1fc4 000952a27c940100254 Page 18 of pgpOptionList.c
e7032e pgpAllocCString(
ab72f7 ¤   PGPContextRef¤  ·¤  ·context,
0c6c0b ¤   char const¤ ¤   ¤   *string
6827e6 ¤   )
36bb36 {
8b0a5b ¤   char¤   ¤   ¤   ¤   *ptr;
3c8bee ¤   PGPSize¤¤   ¤   ¤   ·length;
70af5a
a4ead2 ¤   length = strlen( string );
49b277 ¤   ptr = (char *)pgpContextMemAlloc( context, length+1, 0 );
80c6d4 ¤   if( IsntNull( ptr ) ) {
9865cb ¤   ¤   strcpy( ptr, string );
119371 ¤   }
d08726 ¤   return ptr;
2eefe6 }
d9af5a
3aaf5a
e638e5 /*
61f685 **¤ This is the handler proc for sensitive options like passphrase
a27fe0 */
feaf5a
7ec744 ¤   PGPError
6f23f1 pgpSensitiveOptionHandlerProc(
bb883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
4c0315 ¤   PGPOptionHandlerOperation ¤ operation,
e61a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
e4d276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
7ba79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
7e48db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
2c4ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
e3bb36 {
4f8e12 ¤   PGPError¤   err = kPGPError_NoErr;
dd67c5 ¤
046d02 ¤   (void) context;
5b958f ¤   (void) type;
3267c5 ¤
0cb643 ¤   switch( operation )
8ac7a1 ¤   {
2a4885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
ea5b34 ¤   ¤   {
1ad3ea ¤   ¤   ¤   /* This wipes as it frees since it is a secure buffer */
fed8c5 ¤   ¤   ¤   PGPFreeData( inputValue.asPtr );
7acdcb ¤   ¤   ¤   break;
440fe4 ¤   ¤   }
d087c7 ¤   ¤   ¤
750dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
dd5b34 ¤   ¤   {
35bd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
82cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
d8af5a
0df577 ¤   ¤   ¤   outputValue->asPtr = PGPNewSecureData(
a09376 ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( context ), inputValueSize, 0);
c2e724 ¤   ¤   ¤   if( IsNull( outputValue->asPtr ) ) {
67bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
90f622 ¤   ¤   ¤   ¤   break;
dba3a6 ¤   ¤   ¤   }
c0af5a
2435c8 ¤   ¤   ¤   pgpCopyMemory( inputValue.asPtr, outputValue->asPtr,
c6e542 ¤   ¤   ¤   ¤   ¤   ¤   ···inputValueSize );
d3f4b8 ¤   ¤   ¤   *outputValueSize = inputValueSize;
8187c7 ¤   ¤   ¤
11cdcb ¤   ¤   ¤   break;
df0fe4 ¤   ¤   }
f21b52 ¤   ¤
b99ae3 ¤   ¤   default:
055b34 ¤   ¤   {
18e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
a2cdcb ¤   ¤   ¤   break;
7f0fe4 ¤   ¤   }
0f9371 ¤   }
8baf5a
95deb7 ¤   return( err );
--13c7 000ee2f7ff840100254 Page 19 of pgpOptionList.c
7aefe6 }
46af5a
2e38e5 /*
7b9570 **¤ This is the handler proc for options which take buffers but aren't
9a874b **¤ sensitive.
717fe0 */
c6af5a
a6c744 ¤   PGPError
49840c pgpBufferOptionHandlerProc(
fc883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
7a0315 ¤   PGPOptionHandlerOperation ¤ operation,
561a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
7bd276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
5ca79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
2648db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
094ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
ebbb36 {
fd8e12 ¤   PGPError¤   err = kPGPError_NoErr;
1667c5 ¤
5b6d02 ¤   (void) context;
9b958f ¤   (void) type;
0267c5 ¤
ebb643 ¤   switch( operation )
93c7a1 ¤   {
c54885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
b25b34 ¤   ¤   {
724b83 ¤   ¤   ¤   pgpContextMemFree( context, inputValue.asPtr );
96cdcb ¤   ¤   ¤   break;
800fe4 ¤   ¤   }
6987c7 ¤   ¤   ¤
c50dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
1f5b34 ¤   ¤   {
2dbd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
f3cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
c1af5a
18a2ae ¤   ¤   ¤   outputValue->asPtr = pgpContextMemAlloc( context,
9f926f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·inputValueSize, 0 );
4ce724 ¤   ¤   ¤   if( IsNull( outputValue->asPtr ) ) {
43bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
1cf622 ¤   ¤   ¤   ¤   break;
57a3a6 ¤   ¤   ¤   }
e9af5a
1a35c8 ¤   ¤   ¤   pgpCopyMemory( inputValue.asPtr, outputValue->asPtr,
32e542 ¤   ¤   ¤   ¤   ¤   ¤   ···inputValueSize );
e4f4b8 ¤   ¤   ¤   *outputValueSize = inputValueSize;
f087c7 ¤   ¤   ¤
90cdcb ¤   ¤   ¤   break;
a10fe4 ¤   ¤   }
b91b52 ¤   ¤
0c9ae3 ¤   ¤   default:
3c5b34 ¤   ¤   {
a9e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
90cdcb ¤   ¤   ¤   break;
ae0fe4 ¤   ¤   }
089371 ¤   }
7faf5a
8ddeb7 ¤   return( err );
5cefe6 }
a7af5a
d338e5 /*
6cd356 **¤ This is the handler proc for options containing PGPFileRefs.
807fe0 */
6baf5a
41c744 ¤   PGPError
0a1b7f pgpFileRefOptionHandlerProc(
b3883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
110315 ¤   PGPOptionHandlerOperation ¤ operation,
9c1a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
31d276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
b1a79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
a948db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
ee4ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
--aa23 00084394db440100254 Page 20 of pgpOptionList.c
2cbb36 {
e88e12 ¤   PGPError¤   err = kPGPError_NoErr;
fb67c5 ¤
e66d02 ¤   (void) context;
4a958f ¤   (void) type;
7d67c5 ¤
1cb643 ¤   switch( operation )
30c7a1 ¤   {
aa4885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
565b34 ¤   ¤   {
df66bf ¤   ¤   ¤   err = PFLFreeFileSpec( inputValue.asFileRef );
b2cdcb ¤   ¤   ¤   break;
f10fe4 ¤   ¤   }
d287c7 ¤   ¤   ¤
a60dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
d65b34 ¤   ¤   {
38bd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
b4cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
f2af5a
90bdfd ¤   ¤   ¤   err = PFLCopyFileSpec( inputValue.asFileRef,
506d6e ¤   ¤   ¤   ¤   ¤   ¤   &outputValue->asFileRef );
14698b ¤   ¤   ¤   if( IsntPGPError( err ) )
6bf776 ¤   ¤   ¤   {
322c0a ¤   ¤   ¤   ¤   *outputValueSize = inputValueSize;
05a3a6 ¤   ¤   ¤   }
aa87c7 ¤   ¤   ¤
45cdcb ¤   ¤   ¤   break;
290fe4 ¤   ¤   }
e51b52 ¤   ¤
c49ae3 ¤   ¤   default:
635b34 ¤   ¤   {
26e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
13cdcb ¤   ¤   ¤   break;
690fe4 ¤   ¤   }
059371 ¤   }
fdaf5a
83deb7 ¤   return( err );
d9efe6 }
2caf5a
2e13fb ¤   PGPOptionListRef
bf64d5 pgpCreateCustomValueOptionList(
189a06 ¤   PGPContextRef¤  ¤   ¤   context,
1ef633 ¤   PGPOptionType¤  ¤   ¤   type,
1372fe ¤   PGPOptionFlags¤ ¤   ¤   flags,
11cbd2 ¤   const PGPOptionValue¤   *value,
75e762 ¤   PGPSize¤¤   ¤   ¤   ¤   valueSize,
4b09b2 ¤   PGPOptionListRef¤   ¤   subOptions,
52c280 ¤   PGPOptionHandlerProcPtr¤handlerProc)
0abb36 {
203ddd ¤   PGPOptionListRef¤   optionList;
1d577e ¤   PGPOption¤  ¤   ¤   option;
3267c5 ¤
8e1aa1 ¤   pgpValidateOptionContext( context );
1167c5 ¤
56f97b ¤   option.type¤¤   ¤   = type;
6f6a80 ¤   option.flags¤   ¤   = flags;
06e18f ¤   option.valueSize¤   = valueSize;
4be604 ¤   option.subOptions¤  = subOptions;
565f58 ¤   option.handlerProc¤ = handlerProc;
f167c5 ¤
64e546 ¤   if( IsNull( value ) )
c3c7a1 ¤   {
93501a ¤   ¤   pgpAssert( option.valueSize == 0 );
8c1b52 ¤   ¤
82116e ¤   ¤   option.value.asPtr = NULL;
1c9371 ¤   }
130e24 ¤   else
6fc7a1 ¤   {
b8e32d ¤   ¤   option.value = *value;
d99371 ¤   }
7d67c5 ¤
849045 ¤   optionList = pgpNewOneOptionList( context, &option );
--79df 000ce28f25240100254 Page 21 of pgpOptionList.c
2a67c5 ¤
422126 ¤   if( pgpOptionListIsValid( subOptions ) )
adc7a1 ¤   {
492fc9 ¤   ¤   /* Fetch the err from the subOptions list, if any */
b6df39 ¤   ¤   pgpSetOptionListError( optionList,
67aab8 ¤   ¤   ¤   ¤   ¤   pgpGetOptionListError( subOptions ) );
a59371 ¤   }
3267c5 ¤
c08233 ¤   return( optionList );
00efe6 }
f6af5a
3513fb ¤   PGPOptionListRef
e368f3 pgpCreateStandardValueOptionList(·
a29a06 ¤   PGPContextRef¤  ¤   ¤   context,
cff633 ¤   PGPOptionType¤  ¤   ¤   type,
d6cbd2 ¤   const PGPOptionValue¤   *value,
9be762 ¤   PGPSize¤¤   ¤   ¤   ¤   valueSize,
8fc280 ¤   PGPOptionHandlerProcPtr¤handlerProc)
53bb36 {
9382c9 ¤   return( pgpCreateCustomValueOptionList( context,
dc55d8 ¤   ¤   ¤   ¤   type, kPGPOptionFlag_Default,
2ef6d1 ¤   ¤   ¤   ¤   value, valueSize, NULL, handlerProc ) );
bbefe6 }
3daf5a
8a13fb ¤   PGPOptionListRef
b26132 pgpCreateFileRefOptionList(·
d4520e ¤   PGPContextRef¤  context,
ab4495 ¤   PGPOptionType¤  type,
b67be5 ¤   PGPFileSpecRef¤ fileRef)
bbbb36 {
753ddd ¤   PGPOptionListRef¤   optionList;
6c0cfd ¤   PGPOptionValue¤ ¤   value;
a967c5 ¤
581aa1 ¤   pgpValidateOptionContext( context );
c4e449 ¤   pgpValidateOptionParam( pflFileSpecIsValid( (PFLFileSpecRef)fileRef ) );
d367c5 ¤
17f406 ¤   if( IsntPGPError( PFLCopyFileSpec(
37619f ¤   ¤   ¤   (PFLConstFileSpecRef) fileRef, &value.asFileRef ) ) )
56c7a1 ¤   {
31b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
1c2457 ¤   ¤   ¤   ¤   ¤   ¤   ¤   type,
d8343f ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( fileRef ),
08b57f ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpFileRefOptionHandlerProc );
6a9371 ¤   }
8e0e24 ¤   else
5cc7a1 ¤   {
be8429 ¤   ¤   /* Inability to copy a ref means we're out of memory */
cd1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
899371 ¤   }
9267c5 ¤
998233 ¤   return( optionList );
dbefe6 }
3faf5a
1d13fb ¤   PGPOptionListRef
7ea580 pgpCreateSensitiveOptionList(·
f0a1bc ¤   PGPContextRef¤  ¤   context,
bbccc6 ¤   PGPOptionType¤  ¤   type,
3e0799 ¤   void const¤ ¤   ¤   *sensitiveData,
bd4926 ¤   PGPSize¤¤   ¤   ¤   sensitiveDataSize)
6cbb36 {
5d3ddd ¤   PGPOptionListRef¤   optionList;
970cfd ¤   PGPOptionValue¤ ¤   value;
9367c5 ¤
a01aa1 ¤   pgpValidateOptionContext( context );
f6a34a ¤   pgpValidateOptionParam( IsntNull( sensitiveData ) );
2a67c5 ¤
9bbde4 ¤   value.asPtr = PGPNewSecureData( PGPGetContextMemoryMgr( context ),
2e7394 ¤   ¤   ¤   ¤   ¤   sensitiveDataSize, 0 );
fe252d ¤   if( IsntNull( value.asPtr ) )
37c7a1 ¤   {
9e5c8d ¤   ¤   pgpCopyMemory( sensitiveData, value.asPtr, sensitiveDataSize );
ceb747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
--2977 0010f129a1340100254 Page 22 of pgpOptionList.c
332457 ¤   ¤   ¤   ¤   ¤   ¤   ¤   type,
c044a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sensitiveDataSize,
9df4a3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpSensitiveOptionHandlerProc );
bd9371 ¤   }
fb0e24 ¤   else
e2c7a1 ¤   {
f18429 ¤   ¤   /* Inability to copy a ref means we're out of memory */
f31b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
9c9371 ¤   }
8b67c5 ¤
778233 ¤   return( optionList );
6cefe6 }
17af5a
fc765f /* This is like pgpCreateSensitiveOptionList, but for non-sensitive data */
8e13fb ¤   PGPOptionListRef
0ac72d pgpCreateBufferOptionList(·
2fa1bc ¤   PGPContextRef¤  ¤   context,
45ccc6 ¤   PGPOptionType¤  ¤   type,
92befe ¤   void const¤ ¤   ¤   *bufferData,
458db7 ¤   PGPSize¤¤   ¤   ¤   bufferDataSize)
48bb36 {
663ddd ¤   PGPOptionListRef¤   optionList;
1d0cfd ¤   PGPOptionValue¤ ¤   value;
4e67c5 ¤
d11aa1 ¤   pgpValidateOptionContext( context );
dd9362 ¤   pgpValidateOptionParam( IsntNull( bufferData ) );
1b1b52 ¤   ¤
ea0294 ¤   value.asPtr = pgpContextMemAlloc( context, bufferDataSize, 0 );
a5252d ¤   if( IsntNull( value.asPtr ) )
72c7a1 ¤   {
91a13b ¤   ¤   pgpCopyMemory( bufferData, value.asPtr, bufferDataSize );
38b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
c82457 ¤   ¤   ¤   ¤   ¤   ¤   ¤   type,
357e60 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, bufferDataSize,
1ea043 ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpBufferOptionHandlerProc );
689371 ¤   }
e80e24 ¤   else
a1c7a1 ¤   {
a88429 ¤   ¤   /* Inability to copy a ref means we're out of memory */
441b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
fa9371 ¤   }
72af5a
ae8233 ¤   return( optionList );
ddefe6 }
0aaf5a
d2af5a
bf7e4d /*__Editor_settings____
abaf5a
c74126 ¤   Local Variables:
647b17 ¤   tab-width: 4
960e6c ¤   End:
265f8c ¤   vi: ts=4 sw=4
409e9b ¤   vim: si
0fd062 _____________________*/
--f69e 00013a3d28f40100255 Page 1 of pgpOptionListPriv.h
a70335 /*____________________________________________________________________________
e0eda5 ¤   pgpOptionListPriv.h
0667c5 ¤
65c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
dd4b0f ¤   All rights reserved.
e267c5 ¤
1552b4 ¤   This file contains the private types and prototypes for functions which
c4f788 ¤   manipulate PGPOptionList data structures.
42af5a
b2beae ¤   $Id: pgpOptionListPriv.h,v 1.26.10.1 1998/11/12 03:23:11 heller Exp $
56f7f7 ____________________________________________________________________________*/
05af5a
8d7eeb #ifndef Included_pgpOptionListPriv_h¤   /* [ */
5dd7bc #define Included_pgpOptionListPriv_h
abaf5a
77392c #include "pflTypes.h"
b49f63 #include "pgpEncode.h"
4fc2ae #include "pgpGroups.h"
43c26c #include "pgpContext.h"
11fb31 #include "pgpOptionList.h"
01e684 #include "pgpUserInterface.h"
5aaf5a
ca3a06 #define pgpValidateOptionParam( expr )¤ \
929e64 ¤   if ( ! (expr ) )¤   \
de9c39 ¤   {\
10080e ¤   ¤   pgpAssert( expr );\
6d2d46 ¤   ¤   return( kPGPBadParamsOptionListRef );\
ea9371 ¤   }
33af5a
b75656 #define pgpValidateOptionContext( context ) \
bc70e5 ¤   ¤   pgpValidateOptionParam( pgpContextIsValid( context ) )
f667c5 ¤
0eaf5a
299ef4 enum PGPOptionType_
4dbb36 {
2ee4bd ¤   kPGPOptionType_InvalidOption¤   ¤   = 0,
2530a2 ¤   kPGPOptionType_FirstSDKOption¤  ¤   = kPGPOptionType_InvalidOption,
e167c5 ¤
e5cc4e ¤   kPGPOptionType_InputFileRef¤¤   ¤   = 1,
3b621c ¤   kPGPOptionType_InputBuffer¤ ¤   ¤   = 2,
1d1a51 ¤   /* kPGPOptionType_InputPipe¤¤   ¤   = 3, */
fb67c5 ¤
56608f ¤   kPGPOptionType_OutputFileRef¤   ¤   = 4,
1ec036 ¤   kPGPOptionType_OutputBuffer¤¤   ¤   = 5,
690756 ¤   kPGPOptionType_OutputAllocatedBuffer= 6,
f7a21f ¤   /* kPGPOptionType_OutputPipe¤   ¤   ¤   = 7, */
72fcf3 ¤   kPGPOptionType_AppendOutput¤¤   ¤   = 8,
65dbf7 ¤   kPGPOptionType_DiscardOutput¤   ¤   = 9,
c23842 ¤   /* kPGPOptionType_AskUserForOutput¤ ¤   = 10, */
8767c5 ¤
a10f13 ¤   kPGPOptionType_LocalEncoding¤   ¤   = 11,
391ef0 ¤   kPGPOptionType_RawPGPInput¤ ¤   ¤   = 12,
20af5a
36b1a6 ¤   kPGPOptionType_EncryptToKey¤¤   ¤   = 13,
3fb946 ¤   kPGPOptionType_EncryptToKeySet¤ ¤   = 14,
2d0a21 ¤   kPGPOptionType_EncryptToUserID¤ ¤   = 15,
bf4b3a ¤   kPGPOptionType_SignWithKey¤ ¤   ¤   = 16,
3c7f6d ¤   kPGPOptionType_ConventionalEncrypt¤ = 17,
9567c5 ¤
3f5d8f ¤   kPGPOptionType_Passphrase¤  ¤   ¤   = 18,
342a1c ¤   kPGPOptionType_Passkey¤ ¤   ¤   ¤   = 19,
bd67c5 ¤
23c92d ¤   kPGPOptionType_DetachedSignature¤   = 20,
b35435 ¤   /* kPGPOptionType_MailHeaders¤  ¤   ¤   = 21, */
c3af5a
a54460 ¤   kPGPOptionType_CipherAlgorithm¤ ¤   = 22,
bb3e50 ¤   kPGPOptionType_HashAlgorithm¤   ¤   = 23,
6273e8 ¤   kPGPOptionType_FailBelowValidity¤   = 24,
06a9c4 ¤   kPGPOptionType_WarnBelowValidity¤   = 25,
feaf5a
cfa1e0 ¤   kPGPOptionType_X509Encoding¤¤   ¤   = 26,
13af5a
--1993 000b3cead6e40100255 Page 2 of pgpOptionListPriv.h
984972 ¤   kPGPOptionType_PGPMIMEEncoding¤ ¤   = 27,
11c768 ¤   /* kPGPOptionType_NoNewerThanVersion¤   = 28, */
3996c0 ¤   /* kPGPOptionType_OnePassEncoding¤  ¤   = 29, */
f92182 ¤   kPGPOptionType_OutputLineEndType¤   = 30,
5daf5a
f98986 ¤   kPGPOptionType_EventHandler¤¤   ¤   = 31,
de0e55 ¤   kPGPOptionType_SendNullEvents¤  ¤   = 32,
5ffc49 ¤   kPGPOptionType_ImportKeysTo¤¤   ¤   = 33,
ee7444 ¤   kPGPOptionType_SendEventIfKeyFound¤ = 34,
b7f339 ¤   kPGPOptionType_AskUserForEntropy¤   = 35,
d8af5a
99d92b ¤   kPGPOptionType_ArmorOutput¤ ¤   ¤   = 36,
59b5a7 ¤   kPGPOptionType_DataIsASCII¤ ¤   ¤   = 37,
a77328 ¤   kPGPOptionType_ClearSign¤   ¤   ¤   = 38,
e3d56d ¤   kPGPOptionType_ForYourEyesOnly¤ ¤   = 39,
9b67c5 ¤
8f4858 ¤   kPGPOptionType_DecodeOnlyOne¤   ¤   = 40,
8c257c ¤   kPGPOptionType_RecursivelyDecode¤   = 41,
4dc653 ¤   kPGPOptionType_PassThroughIfUnrecognized= 42,
a1af5a
579f29 ¤   kPGPOptionType_KeySetRef¤   ¤   ¤   = 43,
cb3892 ¤   /* kPGPOptionType_SignatureStatus¤  ¤   = 44, */
beaf5a
5b63d4 ¤   kPGPOptionType_KeyGenParams¤¤   ¤   = 45,
a571a0 ¤   kPGPOptionType_KeyGenName¤  ¤   ¤   = 46,
1d6472 ¤   kPGPOptionType_Expiration¤  ¤   ¤   = 47,
7644dd ¤   kPGPOptionType_AdditionalRecipientRequestKeySet¤= 48,
4cd0cd ¤   kPGPOptionType_KeyGenMasterKey¤ ¤   = 49,
27b35b ¤   kPGPOptionType_KeyGenFast¤  ¤   ¤   = 50,
daaf5a
b02d94 ¤   kPGPOptionType_RevocationKeySet¤¤   = 51,
25af5a
810c78 ¤   kPGPOptionType_PreferredAlgorithms¤ = 52,
3daf5a
eb0eda ¤   kPGPOptionType_CommentString¤   ¤   = 53,
9f09e0 ¤   kPGPOptionType_ExportPrivateKeys¤   = 54,
84cc35 ¤   kPGPOptionType_ExportPrivateSubkeys¤= 55,
5daf5a
9b4c42 ¤   kPGPOptionType_Exportable¤  ¤   ¤   = 56,
2abe8a ¤   kPGPOptionType_CertificateTrust¤¤   = 57,
ffaf5a
f7ff26 ¤   kPGPOptionType_Compression¤ ¤   ¤   = 58,
ed15c1 ¤   kPGPOptionType_VersionString¤   ¤   = 59,
4c6708 ¤   kPGPOptionType_OmitMIMEVersion¤ ¤   = 60,
a1af5a
e266ce ¤   kPGPOptionType_CertificateRegularExpression¤= 61,
1daf5a
1cde32 ¤   kPGPOptionType_PassThroughClearSigned ¤ = 62,
f55072 ¤   kPGPOptionType_PassThroughKeys¤ ¤   ¤   = 63,
f4af5a
fe3042 ¤   kPGPOptionType_CreationDate¤¤   ¤   ¤   = 64,
05af5a
6e8bb9 ¤   kPGPOptionType_InputFileName¤   ¤   ¤   = 65,
1baf5a
2b176a ¤   kPGPOptionType_ExportFormat¤¤   ¤   ¤   = 66,
f867c5 ¤
585a41 ¤   kPGPOptionType_LastSDKOption,
0567c5 ¤
581df2 ¤   kPGPOptionType_FirstUIOption¤   ¤   ¤   = 1000,
be67c5 ¤
55f021 ¤   /* Renumber Later */
81b7bb ¤   kPGPOptionType_DialogPrompt¤¤   ¤   ¤   = 1000,
3bb3ec ¤   kPGPOptionType_OutputPassphrase¤¤   ¤   = 1001,
62f9b6 ¤   kPGPOptionType_Checkbox¤¤   ¤   ¤   ¤   = 1002,
405569 ¤   kPGPOptionType_PopupList¤   ¤   ¤   ¤   = 1003,
0c3d43 ¤   kPGPOptionType_ShowPassphraseQuality¤   = 1004,
eff4b8 ¤   kPGPOptionType_DialogOptions¤   ¤   ¤   = 1005,
b67933 ¤   kPGPOptionType_MinPassphraseLength¤ ¤   = 1006,
4b2a50 ¤   kPGPOptionType_MinPassphraseQuality¤¤   = 1007,
384d48 ¤   kPGPOptionType_DefaultKey¤  ¤   ¤   ¤   = 1008,
aab6c8 ¤   kPGPOptionType_VerifyPassphrase¤¤   ¤   = 1009,
b38f97 ¤   kPGPOptionType_FindMatchingKey¤ ¤   ¤   = 1010,
--9676 00002f6767a40100255 Page 3 of pgpOptionListPriv.h
d90994 ¤   kPGPOptionType_DefaultRecipients¤   ¤   = 1011,
9545ce ¤   kPGPOptionType_DisplayMarginalValidity¤ = 1012,
7ca37a ¤   kPGPOptionType_IgnoreMarginalValidity¤  = 1013,
d1164d ¤   kPGPOptionType_RecipientGroups¤ ¤   ¤   = 1014,
40c2b9 ¤   kPGPOptionType_ParentWindowHandle ······= 1015,¤/* MS Windows only */
328645 ¤   kPGPOptionType_WindowTitle¤ ¤   ¤   ¤   = 1016,
689974 ¤   kPGPOptionType_ARREnforcement¤  ¤   ¤   = 1017,
be9431 ¤   kPGPOptionType_KeyServerUpdateParams¤   = 1018,
f5e1dd ¤   kPGPOptionType_KeyServerSearchKey¤  ¤   = 1019,
569973 ¤   kPGPOptionType_KeyServerSearchFilter¤   = 1020,
b5db72 ¤   kPGPOptionType_KeyServerSearchKeyIDList¤= 1021,
b2b782 ¤   kPGPOptionType_KeyServerSearchKeySet¤   = 1022,
708c59 ¤   kPGPOptionType_TextUI¤  ¤   ¤   ¤   ¤   = 1023,
0f0c17 ¤   kPGPOptionType_RecipientList¤   ¤   ¤   = 1024,
f167c5 ¤
26408e ¤   kPGPOptionType_LastUIOption,
6267c5 ¤
16a04f ¤   PGP_ENUM_FORCE( PGPOptionType_ )
ff82f7 };
cddc0f PGPENUM_TYPEDEF( PGPOptionType_, PGPOptionType );
9faf5a
407353 enum
debb36 {
74d8af ¤   /*
c16c0c ¤   ·* kPGPOptionFlag_Critical means it should be considered an
d0d83e ¤   ·* error if this option isn't recognized.
efa4e3 ¤   ·*/
87233a ¤   kPGPOptionFlag_Critical¤= ( 1 << 0 ),
62af5a
0ad8af ¤   /*
fd1fbc ¤   ·* kPGPOptionFlag_Recognized is used internally to detect
27202a ¤   ·* unrecognized critical options.
5ba4e3 ¤   ·*/
ed67b4 ¤   kPGPOptionFlag_Recognized = ( 1 << 1 ),
32af5a
2ad8af ¤   /*
c5d5bd ¤   ·* kPGPOptionFlag_Frozen means it cannot be changed,
be6541 ¤   ·* because it has already been read.
5ba4e3 ¤   ·*/
d2f5ba ¤   kPGPOptionFlag_Frozen = ( 1 << 2 ),
4b67c5 ¤
dca593 ¤   kPGPOptionFlag_Default¤ = kPGPOptionFlag_Critical
f382f7 };
63af5a
9e79ef typedef PGPFlags¤   PGPOptionFlags;
edaf5a
266e6d typedef struct PGPOOutputBufferDesc
1cbb36 {
54ee82 ¤   void¤   *buffer;
a51cf2 ¤   PGPSize¤bufferSize;
8c772f ¤   PGPSize¤*outputDataLength;
9b67c5 ¤
2abb4c } PGPOOutputBufferDesc;
beaf5a
d9ee4e typedef struct PGPOAllocatedOutputBufferDesc
a0bb36 {
5af788 ¤   void¤   **buffer;
e81507 ¤   PGPSize¤maximumBufferSize;
30311d ¤   PGPSize¤*actualBufferSize;
8f67c5 ¤
a4b914 } PGPOAllocatedOutputBufferDesc;
36af5a
c8d360 typedef struct PGPOEventHandlerDesc
f1bb36 {
046d93 ¤   PGPEventHandlerProcPtr¤ handlerProc;
597b2d ¤   PGPUserValue¤   ¤   ¤   userValue;
b667c5 ¤
af6014 } PGPOEventHandlerDesc;
96af5a
f6c499 typedef struct PGPOKeyGenParamsDesc
11bb36 {
027a63 ¤   PGPUInt32¤  ¤   ¤   ¤   pkalg;
--bf23 000fece3ae740100255 Page 4 of pgpOptionListPriv.h
8ec874 ¤   PGPUInt32¤  ¤   ¤   ¤   bits;
6daf5a
d10a4d } PGPOKeyGenParamsDesc;
ffaf5a
41f905 typedef struct PGPOAdditionalRecipientRequestKeySetDesc
a2bb36 {
61da08 ¤   PGPKeySetRef¤   ¤   ¤   arKeySetRef;
ebce49 ¤   PGPUInt32¤  ¤   ¤   ¤   arkclass;
2aaf5a
41adf9 } PGPOAdditionalRecipientRequestKeySetDesc;
69af5a
ce2706 typedef struct PGPOCertificateTrustDesc
53bb36 {
0a954c ¤   PGPUInt32¤  ¤   ¤   ¤   trustLevel;
4e7e29 ¤   PGPUInt32¤  ¤   ¤   ¤   trustValue;
23af5a
7d2264 } PGPOCertificateTrustDesc;
23af5a
306f8d typedef struct PGPOPGPMIMEEncodingDesc
b4bb36 {
6ac0eb ¤   PGPUInt32¤  ¤   ¤   ¤   mimeEncoding;
fa0830 ¤   PGPSize *¤  ¤   ¤   ¤   mimeBodyOffset;
cbd9f4 ¤   char *¤ ¤   ¤   ¤   ¤   mimeSeparator;
e226b7 } PGPOPGPMIMEEncodingDesc;
99af5a
615bfe typedef struct PGPOUICheckboxDesc
52bb36 {
b83448 ¤   PGPUInt32¤  ¤   itemID;
19aa82 ¤   const char *¤   title;
80ce02 ¤   const char *¤   description;
beace8 ¤   PGPUInt32 *¤¤   valuePtr;
13af5a
55d294 } PGPOUICheckboxDesc;
99af5a
9576b8 typedef struct PGPOUIPopupListDesc
6abb36 {
d63448 ¤   PGPUInt32¤  ¤   itemID;
60aa82 ¤   const char *¤   title;
2dce02 ¤   const char *¤   description;
1a3689 ¤   PGPUInt32¤  ¤   numListItems;
b53f78 ¤   const char **¤  listItems;
f6ace8 ¤   PGPUInt32 *¤¤   valuePtr;
04af5a
66c0a6 } PGPOUIPopupListDesc;
43af5a
9ffe3b typedef struct PGPOUIKeyServerParamsDesc
8bbb36 {
1cb48f ¤   struct PGPKeyServerSpec¤*serverList;
7ce793 ¤   PGPUInt32 ¤ ¤   ¤   ¤   serverCount;
c189ec ¤   PGPtlsContextRef¤   ¤   tlsContext;
b2c883 ¤   PGPBoolean ¤¤   ¤   ¤   searchBeforeDisplay;
0e3bf9 ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys;
f2af5a
d58ae1 } PGPOUIKeyServerParamsDesc;
afaf5a
fae049 typedef struct PGPOUIARRParamsDesc
90bb36 {
775806 ¤   PGPUInt32¤  displayDialog¤  : 1;
40f247 ¤   PGPUInt32¤  enforcement¤¤   : 31;
2167c5 ¤
982636 } PGPOUIARRParamsDesc;
c9af5a
87c649 typedef struct PGPOUIRecipientListDesc
98bb36 {
0ebefe ¤   PGPUInt32¤  ¤   ¤   *recipientCount;
7bc71b ¤   PGPRecipientSpec¤   **recipientList;
8c67c5 ¤
1ba636 } PGPOUIRecipientListDesc;
6daf5a
d7c7a5 typedef union
bdbb36 {
fe6007 ¤   PGPUInt32¤  ¤   ¤   asUInt;
--4b35 0007d77580540100255 Page 5 of pgpOptionListPriv.h
50a2df ¤   PGPInt32¤   ¤   ¤   asInt;
90a121 ¤   void *¤ ¤   ¤   ¤   asPtr;
db24a2 ¤   const void *¤   ¤   asConstPtr;
c597f2 ¤   PGPTime¤¤   ¤   ¤   asTime;
e7ba02 ¤   PGPTimeInterval¤¤   asInterval;
607bf3 ¤   PFLFileSpecRef¤ ¤   asFileRef;
b9c0e9 ¤   PGPUserIDRef¤   ¤   asUserIDRef;
f797b0 ¤   PGPKeyRef¤  ¤   ¤   asKeyRef;
2f16c9 ¤   PGPKeySetRef¤   ¤   asKeySetRef;
26cbc3 ¤   PGPCipherAlgorithm¤ asCipherAlgorithm;
42c8dd ¤   PGPHashAlgorithm¤   asHashAlgorithm;
fc96a9 ¤   PGPValidity¤¤   ¤   asValidity;
27afbf ¤   PGPGroupSetRef¤ ¤   asGroupSetRef;
a1be04 ¤   PGPFilterRef¤   ¤   asFilterRef;
ea5fd2 ¤   PGPtlsContextRef¤   asTLSContextRef;
41f598 ¤   PGPOUIARRParamsDesc¤asARRParams;
a667c5 ¤
a29cf7 } PGPOptionValue;
adaf5a
e77353 enum
9abb36 {
f61bba ¤   kPGPOptionHandler_InvalidOperation¤ ¤   = 0,
d6bc2e ¤   kPGPOptionHandler_FreeDataOperation¤¤   = 1,
4035e1 ¤   kPGPOptionHandler_CopyDataOperation¤¤   = 2
bf82f7 };
2caf5a
1464be typedef PGPUInt32¤  PGPOptionHandlerOperation;
75af5a
8bc01f typedef PGPError ¤  (*PGPOptionHandlerProcPtr)(
5533de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,
22d565 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionHandlerOperation operation,
0a3bf1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type,
93abd9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionValue inputValue,
edf8f6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize inputValueSize,
88a45c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionValue *outputValue,
79fe31 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outputValueSize );
cfaf5a
0bbf01 struct PGPOption
7abb36 {
682eaa ¤   PGPOptionType¤  ¤   ¤   type;
c9aa67 ¤   PGPOptionFlags¤ ¤   ¤   flags;
a3b5d7 ¤   PGPOptionValue¤ ¤   ¤   value;
633ffb ¤   PGPSize¤¤   ¤   ¤   ¤   valueSize;
cf3265 ¤   PGPOptionListRef¤   ¤   subOptions;¤¤   /* Can be NULL */
d30bcd ¤   PGPOptionHandlerProcPtr¤handlerProc;¤   /* Can be NULL */
8e82f7 };
17af5a
f953b7 typedef struct PGPOption¤   PGPOption;
75af5a
034818 #define kPGPEndOfArgsOptionListRef¤ ¤   ((PGPOptionListRef) -1L)
09b768 #define kPGPOutOfMemoryOptionListRef¤   ((PGPOptionListRef) -2L)
e63bbd #define kPGPBadParamsOptionListRef¤ ¤   ((PGPOptionListRef) -3L)
a5e2ac #define kPGPNullOptionListRef¤  ¤   ¤   ((PGPOptionListRef) -4L)
feaf5a
5299c6 PGP_BEGIN_C_DECLARATIONS
02af5a
2c7b30 PGPError¤   ¤   ¤   pgpAddJobOptionsArgs(PGPJobRef job,
66f885 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption,
6adc22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   va_list remainingOptions);
2ee17f PGPError¤   ¤   ¤   pgpAppendOptionListArgs(PGPOptionListRef optionList,
79f885 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption,
f9dc22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   va_list remainingOptions);
ea566f PGPOptionListRef¤   pgpBuildOptionListArgs(
5b22f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,
ca5f84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean createPersistentList,
dcf885 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption,
76dc22 ¤   ¤   ¤   ¤   ¤   ¤   ¤   va_list remainingOptions);
cf8485 PGPError¤   ¤   ¤   pgpFreeVarArgOptionList( PGPOptionListRef firstOption,
d77882 ¤   ¤   ¤   ¤   ¤   ¤   ¤   va_list args );
5667c5 ¤
c36c36 PGPOptionListRef¤   pgpCopyOptionList(PGPOptionListRef optionList);
7d3ba7 void¤   ¤   ¤   ¤   pgpFreeOptionList(PGPOptionListRef optionList);
--5da8 0005afb624d40100255 Page 6 of pgpOptionListPriv.h
9fe444 PGPOptionListRef¤   pgpNewOneOptionList(PGPContextRef context,
f14961 ¤   ¤   ¤   ¤   ¤   ¤   const PGPOption *option);
dab4ca PGPOptionListRef¤   pgpNewOptionList(PGPContextRef context,
6219ee ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean createPersistentList);
7cde64 PGPBoolean¤ ¤   ¤   pgpOptionListIsReal(PGPOptionListRef optionList);
f4de5e PGPBoolean¤ ¤   ¤   pgpOptionListIsValid(PGPOptionListRef optionList);
afd919 PGPError¤   ¤   ¤   pgpOptionListToError( PGPOptionListRef optionList );
44af5a
0b8fdc PGPUInt32¤  ¤   ¤   pgpGetOptionListCount(PGPOptionListRef optionList);
67a302 PGPError¤   ¤   ¤   pgpGetOptionListError(PGPOptionListRef optionList);
ea50a1 void¤   ¤   ¤   ¤   pgpSetOptionListError(PGPOptionListRef optionList,
3c830b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPError error);
2ac811 PGPError¤   ¤   ¤   pgpGetIndexedOption(PGPOptionListRef optionList,
ecae27 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 searchIndex,
2dc070 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean markAsRecognized,
b38c96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOption *optionData);
603635 PGPError¤   ¤   ¤   pgpGetIndexedOptionType(PGPOptionListRef optionList,
a37208 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType optionType, PGPUInt32¤searchIndex,
fda225 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean markAsRecognized, PGPOption *optionData,
115978 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 *numFoundOptions);
10af5a
b1f31a PGPError¤   ¤   ¤   pgpCheckOptionsInSet(PGPOptionListRef optionList,
1bc64d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType const *optionSet,
9fa7a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 optionSetSize);
aaaf5a
060582 /* Parsing Helper Functions */
3caf5a
cd483d PGPError¤   pgpSearchOptionSingle(PGPOptionListRef optionList,
723b39 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType optionType, PGPOption *optionData);
b3af5a
838252 PGPError¤   pgpSearchOption(PGPOptionListRef optionList,
c39ab5 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType optionType, PGPUInt32 searchIndex,
d81ad7 ¤   ¤   ¤   ¤   ¤   ¤   PGPOption *optionData);
83af5a
493a5a PGPError¤   pgpFindOptionArgs(PGPOptionListRef optionList,
92c7f6 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType optionType, PGPBoolean fMandatory,
8f5ef2 ¤   ¤   ¤   ¤   ¤   ¤   const char *str, ...);
0baf5a
469cdf void¤   ¤   pgpCleanupOptionList(PGPOptionListRef *optionList);
acaf5a
452656 PGPError¤   pgpOptionInt(PGPOption *op, PGPInt32 *pInt);
4eaf5a
8b80ff PGPError¤   pgpOptionUInt(PGPOption *op, PGPUInt32 *pUInt);
43af5a
2e5631 PGPError¤   pgpOptionPtr(PGPOption *op, void **pPtr);
71af5a
9eefe3 PGPError¤   pgpOptionInterval(PGPOption *op, PGPTimeInterval *pInterval);
37af5a
69a35e PGPError¤   pgpOptionPtrLength(PGPOption *op, void **pPtr, PGPSize *pLength);
2faf5a
7a5617 PGPError¤   pgpOptionPtrPtr(PGPOption *op, void **pPtr, void **pPtr2);
f4af5a
6ddb7b PGPError¤   pgpOptionPtrLengthPtr(PGPOption *op, void **pPtr, PGPSize *pLength,
131247 ¤   ¤   ¤   ¤   ¤   ¤   void **pPtr2) ;
39af5a
af5756 char *¤ ¤   pgpAllocCString(PGPContextRef context, char const *string);
abaf5a
13126e /* PGPO Creation Utilities */
07af5a
380d97 PGPOptionListRef¤   pgpCreateCustomValueOptionList(PGPContextRef context,
57a8e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, PGPOptionFlags flags,
163f87 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const PGPOptionValue *value, PGPSize valueSize,
388a18 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef subOptions,
a6017e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionHandlerProcPtr¤handlerProc);
9067c5 ¤
718633 PGPOptionListRef¤   pgpCreateStandardValueOptionList(PGPContextRef context,
b93260 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, const PGPOptionValue *value,
b7e5cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize valueSize,
7516b2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionHandlerProcPtr handlerProc);
5967c5 ¤
af7668 PGPOptionListRef¤   pgpCreateFileRefOptionList(PGPContextRef context,
5ac042 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, PGPFileSpecRef fileRef);
--facd 001bd6e662240100255 Page 7 of pgpOptionListPriv.h
2a67c5 ¤
21259a PGPOptionListRef¤   pgpCreateSensitiveOptionList(PGPContextRef context,
598420 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, void const *sensitiveData,
71ff7c ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize sensitiveDataSize);
ef67c5 ¤
33e832 PGPOptionListRef¤   pgpCreateBufferOptionList(PGPContextRef context,
8e725d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, void const *bufferData,
0b664f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize bufferDataSize);
7167c5 ¤
e7ae30 ¤   ¤   ¤   ¤   ¤
b26e7e PGPError¤   pgpSensitiveOptionHandlerProc(PGPContextRef context,
bc8509 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionHandlerOperation operation,
5f01f0 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, PGPOptionValue inputValue,
0b91ee ¤   ¤   ¤   ¤   ¤   ¤   PGPSize inputValueSize, PGPOptionValue *outputValue,
33fa4a ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outputValueSize);
2aaf5a
8d82a4 PGPError¤   pgpBufferOptionHandlerProc(PGPContextRef context,
948509 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionHandlerOperation operation,
8d01f0 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, PGPOptionValue inputValue,
0d91ee ¤   ¤   ¤   ¤   ¤   ¤   PGPSize inputValueSize, PGPOptionValue *outputValue,
bafa4a ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outputValueSize);
62af5a
94d07f PGPError¤   pgpFileRefOptionHandlerProc(PGPContextRef context,
cb8509 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionHandlerOperation operation,
0f01f0 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionType type, PGPOptionValue inputValue,
6291ee ¤   ¤   ¤   ¤   ¤   ¤   PGPSize inputValueSize, PGPOptionValue *outputValue,
26fa4a ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outputValueSize);
5e67c5 ¤
691b52 ¤   ¤
6d1254 PGP_END_C_DECLARATIONS
89af5a
7876f9 #endif /* ] Included_pgpOptionListPriv_h */
09af5a
aa7e4d /*__Editor_settings____
36af5a
9b4126 ¤   Local Variables:
3a7b17 ¤   tab-width: 4
d40e6c ¤   End:
115f8c ¤   vi: ts=4 sw=4
fb9e9b ¤   vim: si
bdd062 _____________________*/
--fba8 001feee4f1040100256 Page 1 of pgpOptionMem.c
a70335 /*____________________________________________________________________________
3da03b ¤   pgpOptionMem.c
cf67c5 ¤
9fc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
6b4b0f ¤   All rights reserved.
d867c5 ¤
b46151 ¤   Memory allocation functions for use by optionlist package
efaf5a
8d3489 ¤   $Id: pgpOptionMem.c,v 1.3.30.1 1998/11/12 03:23:11 heller Exp $
c1f7f7 ____________________________________________________________________________*/
e2af5a
812f8d #include "pgpErrors.h"
850d08 #include "pgpMem.h"
dbaf5a
5ec26c #include "pgpContext.h"
d5fb31 #include "pgpOptionList.h"
7c8b0d #include "pgpEncodePriv.h"
81af5a
76af5a
f23a71 ········void *
b930c8 PGPOptionListMemAlloc( PGPSize allocationSize )
65bb36 {
486185 ········return( pgpAlloc( allocationSize ) );
21efe6 }
f6af5a
1572d5 ¤   ¤   PGPError
7db7b7 PGPOptionListMemRealloc(
afce18 ········void ···**oldAllocation,
41fd16 ········PGPSize newAllocationSize )
94bb36 {
e70ecf ¤   ¤   return( pgpRealloc( oldAllocation, newAllocationSize ) );
25efe6 }
2faf5a
577d2d ········void
2624f2 PGPOptionListMemFree(void *allocation)
81bb36 {
640877 ········pgpFree( allocation );
f4efe6 }
14af5a
a5af5a
2baf5a
9e7e4d /*__Editor_settings____
caaf5a
634126 ¤   Local Variables:
8b7b17 ¤   tab-width: 4
3c0e6c ¤   End:
415f8c ¤   vi: ts=4 sw=4
629e9b ¤   vim: si
fed062 _____________________*/
--35cb 00160caaded40100257 Page 1 of pgpTimeBomb.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
1e65ef ¤   $Id: pgpTimeBomb.c,v 1.8.28.1 1998/11/12 03:23:12 heller Exp $
34f7f7 ____________________________________________________________________________*/
bbaf5a
c9e2ff #include "pgpConfig.h"
89eee9 #include "pgpTimeBomb.h"
70af5a
fe9ac6 #if PGP_TIME_BOMB¤  /* [ */
2caf5a
e60a8b #include <time.h>
9a0d08 #include "pgpMem.h"
d6af5a
ea16ea ¤   PGPBoolean
a61521 pgpTimeBombHasExpired( void )
9bbb36 {
0bb419 ¤   time_t¤ ¤   currentTime¤= time( NULL );
c99fa7 ¤   time_t¤ ¤   expirationTime;
16d035 ¤   struct tm¤  tm;
af67c5 ¤
765a76 ¤   pgpAssert( kPGPTimeBombMonth >= 1 && kPGPTimeBombMonth <= 12 );
8c96a7 ¤   pgpAssert( kPGPTimeBombYear >= 1997 && kPGPTimeBombYear <= 1999 );
efbb37 ¤   pgpAssert( kPGPTimeBombDay >= 0 && kPGPTimeBombDay <= 31 );
5767c5 ¤
f3eef4 ¤   pgpClearMemory( &tm, sizeof( tm ) );
f4b603 ¤   tm.tm_year¤ = kPGPTimeBombYear - 1900;¤ /* API requires just "97" */
85287e ¤   tm.tm_mon¤  = kPGPTimeBombMonth - 1;¤   /* months are [0,11] */
6f7d95 ¤   tm.tm_mday¤ = kPGPTimeBombDay;
7967c5 ¤
673d89 ¤   expirationTime¤ = mktime( &tm );
6f67c5 ¤
2bb67f ¤   return ( currentTime >= expirationTime );
b9efe6 }
65af5a
62af5a
ed3167 #endif¤ /* ] */
92af5a
efaf5a
0d7e4d /*__Editor_settings____
c5af5a
2e4126 ¤   Local Variables:
0c7b17 ¤   tab-width: 4
670e6c ¤   End:
1d5f8c ¤   vi: ts=4 sw=4
b99e9b ¤   vim: si
60d062 _____________________*/
--8ebb 001f78c27db40100258 Page 1 of pgpTimeBomb.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
51ecd4 ¤   $Id: pgpTimeBomb.h,v 1.9.10.1 1998/11/12 03:23:13 heller Exp $
9ef7f7 ____________________________________________________________________________*/
182cb5 #ifndef Included_pgpTimeBomb_h¤ /* [ */
006f5d #define Included_pgpTimeBomb_h
a0af5a
7dfe43 #include "pgpPubTypes.h"¤   /* for PGP_BEGIN_C_DECLARATIONS */
93af5a
650335 /*____________________________________________________________________________
72377c ¤   set PGP_TIME_BOMB to 0 to disable time bomb, 1 to enable
1d67c5 ¤
5aeb03 ¤   If you enable it, set the year, month, day appropriately.
e0f7f7 ____________________________________________________________________________*/
4ef58c #define PGP_TIME_BOMB¤  ¤   0
abc324 #define kPGPTimeBombYear¤   1997
0b9a84 #define kPGPTimeBombMonth¤  9¤  /* 1-12 */
7c1bcf #define kPGPTimeBombDay¤¤   30¤ /* 1-31 */
f5af5a
f7af5a
51af5a
10c470 #if PGP_TIME_BOMB
d2af5a
ea99c6 PGP_BEGIN_C_DECLARATIONS
23af5a
86af5a
fa1ffd PGPBoolean¤ ¤   pgpTimeBombHasExpired( void );
26af5a
65af5a
10af5a
241254 PGP_END_C_DECLARATIONS
5aaf5a
767454 #endif
47af5a
89af5a
2b86f0 #endif /* ] Included_pgpTimeBomb_h */
83af5a
b8af5a
c47e4d /*__Editor_settings____
d0af5a
2b4126 ¤   Local Variables:
627b17 ¤   tab-width: 4
d10e6c ¤   End:
955f8c ¤   vi: ts=4 sw=4
619e9b ¤   vim: si
f7d062 _____________________*/
--9cc6 00037e1980140100259 Page 1 of pgpUtilities.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
d9af5a
fa6793 ¤   $Id: pgpUtilities.c,v 1.43.10.1 1998/11/12 03:23:14 heller Exp $
1bf7f7 ____________________________________________________________________________*/
06e2ff #include "pgpConfig.h"
0c2f8d #include "pgpErrors.h"
290d08 #include "pgpMem.h"
e2af5a
4cc26c #include "pgpContext.h"
f5894b #include "pgpFileSpec.h"
6a4919 #include "pgpUtilities.h"
125430 #include "pgpUtilitiesPriv.h"
10fb31 #include "pgpOptionList.h"
922012 #include "pgpMacBinary.h"
0d61a1 #include "pgpMacFileMapping.h"
87af5a
060ccc #if PGP_MACINTOSH
eaaf5a
ff8bd8 #include "MacEnvirons.h"
6bbbf4 #include "MacFiles.h"
df85c2 #include "MacStrings.h"
caaf5a
8b14ea #elif PGP_WIN32
edaf5a
082a68 #define WIN32_LEAN_AND_MEAN
d25655 #include <windows.h>
6baf5a
8f7454 #endif
59af5a
fcaf5a
d7af5a
311b52 ¤   ¤
11af5a
ecaf5a
03c744 ¤   PGPError
efeb5d PGPCopyFileSpec(
d8055d ¤   PGPFileSpecRef¤ fileRef,
8175aa ¤   PGPFileSpecRef *outRef )
40bb36 {
313c76 ¤   PGPValidatePtr( outRef );
e03652 ¤   *outRef¤= NULL;
3bc866 ¤   PFLValidateFileSpec( (PFLConstFileSpecRef)fileRef );
2767c5 ¤
257585 ¤   return( PFLCopyFileSpec( (PFLConstFileSpecRef)fileRef,
644a58 ¤   ¤   (PFLFileSpecRef*)outRef ) );
4befe6 }
12af5a
2cc744 ¤   PGPError
14d358 PGPFreeFileSpec( PGPFileSpecRef¤¤   fileRef)
9cbb36 {
f673ba ¤   PFLValidateFileSpec( (PFLFileSpecRef)fileRef );
aa67c5 ¤
9b2f4e ¤   return( PFLFreeFileSpec( (PFLFileSpecRef)fileRef ) );
d5efe6 }
04af5a
83af5a
f4af5a
86af5a
08c21c #if PGP_MACINTOSH¤  /* [ */
3faf5a
fc21ab ¤   PGPError·
3f429a PGPNewFileSpecFromFSSpec(
a3a1bc ¤   PGPContextRef¤  ¤   context,
47f521 ¤   FSSpec const *¤ ¤   spec,
8897b8 ¤   PGPFileSpecRef *¤   outRef )
91bb36 {
e88ee4 ¤   return( PFLNewFileSpecFromFSSpec( PGPGetContextMemoryMgr( context ),
48d241 ¤   ¤   spec, (PFLFileSpecRef*)outRef ) );
39efe6 }
37af5a
--deb6 000ee108ea040100259 Page 2 of pgpUtilities.c
e0af5a
01c744 ¤   PGPError
9476b3 PGPGetFSSpecFromFileSpec(
7a055d ¤   PGPFileSpecRef¤ fileRef,
ad04f5 ¤   FSSpec *¤   ¤   spec)
71bb36 {
8891ba ¤   return( PFLGetFSSpecFromFileSpec( (PFLFileSpecRef)fileRef, spec ) );
12efe6 }
d4af5a
139860 #else /* ] PGP_MACINTOSH [ */
8daf5a
daaf5a
a921ab ¤   PGPError·
8bfbd5 PGPNewFileSpecFromFullPath(
5aa1bc ¤   PGPContextRef¤  ¤   context,
c8cf94 ¤   char const *¤   ¤   path,
8cd176 ¤   PGPFileSpecRef *¤   ¤   outRef )
1abb36 {
9326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
8b67c5 ¤
73211d ¤   err¤= PFLNewFileSpecFromFullPath( PGPGetContextMemoryMgr( context ),
4787b4 ¤   ¤   path, (PFLFileSpecRef *)outRef );
025ea8 ¤   return err;
34efe6 }
dbaf5a
5baf5a
65af5a
c121ab ¤   PGPError·
b2634e PGPGetFullPathFromFileSpec(
ae8074 ¤   PGPFileSpecRef¤ fileRefIn,
7bc056 ¤   char **¤¤   ¤   fullPathPtr)
02bb36 {
e58f52 ¤   PGPError¤   ¤   ¤   err;
95dc05 ¤   PGPMemoryMgrRef¤¤   memoryMgr¤  = NULL;
5a2f9c ¤   char *¤ ¤   ¤   ¤   tempPath¤   = NULL;
af48d7 ¤   char *¤ ¤   ¤   ¤   fullPath¤   = NULL;
a4a468 ¤   PFLConstFileSpecRef¤fileRef¤= (PFLConstFileSpecRef)fileRefIn;
5167c5 ¤
04f65f ¤   PGPValidatePtr( fullPathPtr );
0a8917 ¤   *fullPathPtr¤   = NULL;
3c65f3 ¤   PFLValidateFileSpec( fileRef );
6f67c5 ¤
9ab3eb ¤   memoryMgr¤  = PFLGetFileSpecMemoryMgr( fileRef );
4b67c5 ¤
892404 ¤   err¤= PFLGetFullPathFromFileSpec( fileRef, &tempPath );
b0f1e7 ¤   if ( IsntPGPError( err ) )
0fc7a1 ¤   {
ed646b ¤   ¤   fullPath¤   = (char *)
d06812 ¤   ¤   ¤   PGPNewData( memoryMgr, strlen( tempPath ) + 1, 0);
34684f ¤   ¤   if ( IsntNull( fullPath ) )
975b34 ¤   ¤   {
45e4d7 ¤   ¤   ¤   strcpy( fullPath, tempPath );
270fe4 ¤   ¤   }
be0e1d ¤   ¤   else
ea5b34 ¤   ¤   {
56124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
c10fe4 ¤   ¤   }
00691f ¤   ¤   PGPFreeData( tempPath );
8f9371 ¤   }
c467c5 ¤
1fb919 ¤   *fullPathPtr¤   = fullPath;
88deb7 ¤   return( err );
e0efe6 }
a2af5a
ebaf5a
aeaf5a
2bddc8 #endif¤ /* ] PGP_MACINTOSH */
6baf5a
70af5a
eeaf5a
1eaf5a
eeaf5a
--ebae 0007e991d9d40100259 Page 3 of pgpUtilities.c
a70335 /*____________________________________________________________________________
b02bb2 ¤   Examine the input file to see if it's a MacBinary file. ·If it is
a4ac51 ¤   not a MacBinary file, then nothing is done. ·Otherwise, it is
43b508 ¤   converted, the original file is deleted and the resulting file is
8a99a3 ¤   designated by 'outPGPSpec'.
f067c5 ¤
bd61c8 ¤   creator and type code pointers may be
f9e1a9 ¤   null but otherwise contain the mac creator and type.
5e67c5 ¤
1b75f0 ¤   The output file may have a different name than the original because
3a6fd4 ¤   its Mac creator/type codes may be mapped into a file name extension.
4667c5 ¤
b88a92 ¤   Example (assuming it's an MS-Word file):
2ed332 ¤   ¤   MyStuff.doc¤=> MyStuff.doc
627efb ¤   ¤   MyStuff.bin => MyStuff.doc
c7ba8e ¤   ¤   MyStuff¤¤   => MyStuff.doc
fef7f7 ____________________________________________________________________________*/
acc744 ¤   PGPError
68c772 PGPMacBinaryToLocal(
98d43c ¤   PGPFileSpecRef¤ ¤   inPGPSpec,
e5b9b0 ¤   PGPFileSpecRef *¤   outPGPSpec,
baf4af ¤   PGPUInt32 *¤¤   ¤   macCreator,
aeb072 ¤   PGPUInt32 *¤¤   ¤   macType )
e8bb36 {
f98f52 ¤   PGPError¤   ¤   ¤   err;
4167c5 ¤
0f733a ¤   if ( IsntNull( macCreator ) )
153b5a ¤   ¤   *macCreator¤= 0;
8ca98d ¤   if ( IsntNull( macType ) )
c967cf ¤   ¤   *macType¤   = 0;
4846b7 ¤   if ( IsntNull( outPGPSpec ) )
d68461 ¤   ¤   *outPGPSpec¤= NULL;
3f1b52 ¤   ¤
3794d4 ¤   PGPValidatePtr( outPGPSpec );
23bbda ¤   PFLValidateFileSpec( (PFLFileSpecRef)inPGPSpec );
6567c5 ¤
ba3787 ¤   err = pgpMacBinaryToLocal( (PFLFileSpecRef)inPGPSpec,
652c8f ¤   ¤   ¤   (PFLFileSpecRef *)outPGPSpec, macCreator, macType );
8c67c5 ¤
a5deb7 ¤   return( err );
eaefe6 }
0caf5a
97af5a
98af5a
bfaf5a
4eaf5a
b0af5a
39af5a
37af5a
18af5a
cdaf5a
b6af5a
bcaf5a
53af5a
e90335 /*____________________________________________________________________________
4fa4e4 ¤   Determine where the preference file resides, and create a PFLFileSpecRef
bb71cf ¤   which locates it.
31f7f7 ____________________________________________________________________________*/
61c21c #if PGP_MACINTOSH¤  /* [ */
18c744 ¤   PGPError
686288 pgpGetPrefsSpec(
9b2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
4f9620 ¤   PFLFileSpecRef *¤   outRef )
e9bb36 {
d1d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
03986a ¤   FSSpec¤ ¤   ¤   ¤   fsSpec;
324009 ¤   const unsigned char¤kCDKPrefsFileName[] = "\pPGPsdkPreferences";
c065f3 ¤   PFLFileSpecRef¤ ¤   newRef¤ = NULL;
b967c5 ¤
866592 ¤   *outRef¤¤   = NULL;
ae67c5 ¤
7eaf7e ¤   err¤= FindPGPPreferencesFolder( -1, &fsSpec.vRefNum, &fsSpec.parID );
--1ab7 000b6124ee240100259 Page 4 of pgpUtilities.c
e5f1e7 ¤   if ( IsntPGPError( err ) )
5ac7a1 ¤   {
b3eb55 ¤   ¤   CopyPString( kCDKPrefsFileName, fsSpec.name );
0767c5 ¤
b34b86 ¤   ¤   err¤= PFLNewFileSpecFromFSSpec( memoryMgr, &fsSpec, &newRef );
9a7d98 ¤   ¤   if ( IsntPGPError( err ) )
e25b34 ¤   ¤   {
540785 ¤   ¤   ¤   PFLFileSpecMacMetaInfo¤ info;
fb9ca3 ¤   ¤   ¤   #define kCDKPrefsCreator¤   kPGPMacFileCreator_Keys
a54721 ¤   ¤   ¤   #define kCDKPrefsType¤  ¤   'pref'
ce87c7 ¤   ¤   ¤
bcdb2c ¤   ¤   ¤   pgpClearMemory( &info, sizeof( info ) );
a6e3d0 ¤   ¤   ¤   info.fInfo.fdCreator¤   = kCDKPrefsCreator;
b3e4dc ¤   ¤   ¤   info.fInfo.fdType¤  ¤   = kCDKPrefsType;
2490fb ¤   ¤   ¤   PFLSetFileSpecMetaInfo( newRef, &info );
630fe4 ¤   ¤   }
0e9371 ¤   }
a467c5 ¤
87cdaf ¤   *outRef¤= newRef;
1967c5 ¤
f3deb7 ¤   return( err );
2defe6 }
d1af5a
42b7ca #elif PGP_UNIX¤ ¤   /* ] PGP_MACINTOSH [ */
67af5a
9e0335 /*____________________________________________________________________________
e6a4e4 ¤   Determine where the preference file resides, and create a PFLFileSpecRef
ab71cf ¤   which locates it.
18f7f7 ____________________________________________________________________________*/
60c744 ¤   PGPError
b66288 pgpGetPrefsSpec(
ac2f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
009620 ¤   PFLFileSpecRef *¤   outRef )
9fbb36 {
90d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
bf3c82 ¤   const char¤ ¤   ¤   kCDKPrefsFileName[] = "PGPsdkPreferences";
25661c ¤   const char *¤   ¤   pgppath1;
3c572e ¤   const char *¤   ¤   pgppath2 = "/";
4cb5ed ¤   char *¤ ¤   ¤   ¤   prefpath;
bb67c5 ¤
f16592 ¤   *outRef¤¤   = NULL;
4567c5 ¤
e8a860 ¤   pgppath1¤   = getenv( "PGPPATH" );
8e0df9 ¤   if( IsNull( pgppath1 ) ) {
4b14ad ¤   ¤   pgppath1 = getenv( "HOME" );
d543b0 ¤   ¤   if( IsNull( pgppath1 ) )
060200 ¤   ¤   ¤   pgppath1 = ".";
150e1d ¤   ¤   else
0cacb7 ¤   ¤   ¤   pgppath2 = "/.pgp/";
139371 ¤   }
04af5a
a997bd ¤   prefpath = PGPNewData( memoryMgr,
443dd6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···strlen(pgppath1)+strlen(pgppath2)+
2fb8a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen(kCDKPrefsFileName)+1,
d611da ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···0 );
44322d ¤   if( IsNull( prefpath ) )
e94030 ¤   ¤   return kPGPError_OutOfMemory;
5b67c5 ¤
410a42 ¤   strcpy( prefpath, pgppath1 );
bd595d ¤   strcat( prefpath, pgppath2 );
9c1601 ¤   strcat( prefpath, kCDKPrefsFileName );
b2af5a
368223 ¤   err = PFLNewFileSpecFromFullPath( memoryMgr, prefpath, outRef );
f5af5a
2b82ce ¤   PGPFreeData( prefpath );
cbaf5a
d85ea8 ¤   return err;
38efe6 }
00af5a
0556e8 #elif PGP_WIN32¤/* ] PGP_UNIX [ */
a8af5a
b60335 /*____________________________________________________________________________
--7bbf 0019e1eb5ed40100259 Page 5 of pgpUtilities.c
82a4e4 ¤   Determine where the preference file resides, and create a PFLFileSpecRef
f571cf ¤   which locates it.
fbf7f7 ____________________________________________________________________________*/
2ac744 ¤   PGPError
3b6288 pgpGetPrefsSpec(
552f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
c59620 ¤   PFLFileSpecRef *¤   outRef )
fcbb36 {
c0d591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
39d1a7 ¤   const char¤ ¤   ¤   kCDKPrefsFileName[] = "PGP_sdk.prf";
f10228 ¤   char¤   ¤   ¤   ¤   winpath[MAX_PATH];
d4b5ed ¤   char *¤ ¤   ¤   ¤   prefpath;
7e67c5 ¤
306592 ¤   *outRef¤¤   = NULL;
8067c5 ¤
b42ba2 ¤   if( GetWindowsDirectory( winpath, sizeof(winpath) ) == 0)
b0c7a1 ¤   {
276d90 ¤   ¤   strcpy( winpath, "." );
d19371 ¤   }
79af5a
8aaf68 ¤   prefpath = (char *)PGPNewData( memoryMgr, strlen(winpath)+1+
93808a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···strlen(kCDKPrefsFileName)+1, 0);
00322d ¤   if( IsNull( prefpath ) )
2c4030 ¤   ¤   return kPGPError_OutOfMemory;
e467c5 ¤
bad2d3 ¤   strcpy( prefpath, winpath );
5616cb ¤   strcat( prefpath, "\\" );
0a1601 ¤   strcat( prefpath, kCDKPrefsFileName );
59af5a
958223 ¤   err = PFLNewFileSpecFromFullPath( memoryMgr, prefpath, outRef );
24af5a
1782ce ¤   PGPFreeData( prefpath );
31af5a
305ea8 ¤   return err;
e3efe6 }
3eaf5a
6baf5a
ebcf17 #else¤  /* ] PGP_WIN32 [ */
6c9816 #error Unsupported operating system
1618c1 #endif¤ /* ] OTHER OS */
11af5a
edaf5a
f4af5a
0baf5a
b8af5a
d67e4d /*__Editor_settings____
92af5a
3c4126 ¤   Local Variables:
b77b17 ¤   tab-width: 4
670e6c ¤   End:
f15f8c ¤   vi: ts=4 sw=4
9b9e9b ¤   vim: si
9ed062 _____________________*/
--bb52 0010f7089a54010025a Page 1 of pgpUtilitiesPriv.h
a70335 /*____________________________________________________________________________
39eb91 ¤   pgpUtilities.h
ff67c5 ¤
67c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
bf4b0f ¤   All rights reserved.
1167c5 ¤
a8d533 ¤   This file contains miscellaneous utility functions needed for the PGPsdk.
f6af5a
24a2fd ¤   $Id: pgpUtilitiesPriv.h,v 1.15.12.1 1998/11/12 03:23:14 heller Exp $
ecf7f7 ____________________________________________________________________________*/
35af5a
ed6a29 #ifndef Included_pgpUtilitiesPriv_h¤/* [ */
d3657c #define Included_pgpUtilitiesPriv_h
beaf5a
764919 #include "pgpUtilities.h"
3e392c #include "pflTypes.h"
156773 #include "pgpMemoryMgr.h"
f8af5a
1199c6 PGP_BEGIN_C_DECLARATIONS
58ae30 ¤   ¤   ¤   ¤   ¤
740c9a PGPError¤   pgpGetPrefsSpec( PGPMemoryMgrRef context, PFLFileSpecRef*outRef );
79af5a
e9af5a
bc8969 PGPError¤   pgpsdkCleanupForce( void );
490ee8 PGPBoolean¤ pgpsdkIsInited( void );
30af5a
b25194 #define pgpValidatePGPContextRef( context ) \
614c49 ¤   PGPValidateParam( pgpContextIsValid( context ) )
37af5a
531254 PGP_END_C_DECLARATIONS
60af5a
9daf5a
8f02af #endif /* ] Included_pgpUtilitiesPriv_h */
4faf5a
2a7e4d /*__Editor_settings____
b2af5a
994126 ¤   Local Variables:
377b17 ¤   tab-width: 4
dc0e6c ¤   End:
245f8c ¤   vi: ts=4 sw=4
309e9b ¤   vim: si
0fd062 _____________________*/
--5766 0015f44e94d4010025b Page 1 of Makefile.in
5ea601 #
8e97f1 # priv/utilities/errors/
b4a601 #
abd5c0 # $Id: Makefile.in,v 1.3 1997/05/13 01:19:38 mhw Exp $
caa601 #
4eaf5a
049ba3 OBJS=¤  pgpErrors.o
7e231a PRIVHDRS= pgpErrorsPriv.h
bfaf5a
41b7a3 all:: DONE
5faf5a
--c8d0 000dbc98d9d4010025c Page 1 of pgpErrors.c
a70335 /*____________________________________________________________________________
8ad75b ¤   pgpErrors.c
ee67c5 ¤
ddc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
a24b0f ¤   All rights reserved.
2667c5 ¤
6067c5 ¤
32af5a
6c93e4 ¤   $Id: pgpErrors.c,v 1.56.10.1 1998/11/12 03:23:16 heller Exp $
f9f7f7 ____________________________________________________________________________*/
63e2ff #include "pgpConfig.h"
2eaf5a
0cfeb2 #include <stdio.h>
63324c #include <string.h>
54af5a
f8a146 #include "pgpDebug.h"
e7e82c #include "pgpPubTypes.h"
162f8d #include "pgpErrors.h"
2e0d08 #include "pgpMem.h"
21af5a
9baf5a
711b87 #include "pgpErrorsPriv.h"
3eaf5a
74af5a
576ea5 typedef struct ErrorEntry
46bb36 {
49cd5c ¤   PGPError const¤ ¤   number;
f32e82 ¤   const char * const¤ string;
cc857a } ErrorEntry;
edaf5a
2bc5d1 #define EN(number, string)¤ ¤   { number, string }
c8af5a
5faf5a
6ea4ef static const ErrorEntry sErrors[] =
0dbb36 {
6b6e3b /* later, if necessary, this table can be moved into its own file */
3774b5 EN( kPGPError_NoErr,¤   ¤   ¤   ¤   ¤   "not an error"),
d6d025 EN( kPGPError_BadParams,¤   ¤   ¤   ¤   "bad parameters"),
aff5de EN( kPGPError_OutOfMemory,¤ ¤   ¤   "out of memory"),
41b96c EN( kPGPError_BufferTooSmall,¤  ¤   "buffer too small"),
15af5a
c9ebe9 EN( kPGPError_FileNotFound,¤¤   ¤   "file not found"),
538efb EN( kPGPError_CantOpenFile,¤¤   ¤   "can't open file"),
15fa09 EN( kPGPError_FilePermissions,¤ ¤   "file permissions"),
d8b819 EN( kPGPError_FileLocked,¤  ¤   ¤   "file locked"),
38254e EN( kPGPError_DiskFull,¤¤   ¤   ¤   "disk full"),
ddbed7 EN( kPGPError_IllegalFileOp,¤   ¤   ¤   "illegal file operation"),
3b6a40 EN( kPGPError_FileOpFailed,¤¤   ¤   "file operation error"),
593105 EN( kPGPError_ReadFailed,¤  ¤   ¤   "read failed"),
5cd790 EN( kPGPError_WriteFailed,¤ ¤   ¤   "write failed"),
3cedb1 EN( kPGPError_EOF,¤ ¤   ¤   ¤   ¤   "end of file"),
4aaf5a
c36c31 EN( kPGPError_UserAbort,¤   ¤   ¤   ¤   "user cancelled"),
b17747 EN( kPGPError_UnknownRequest,¤  ¤   "unrecognized request"),
e077b1 EN( kPGPError_LazyProgrammer,¤  ¤   "unknown error"),
9278dc EN( kPGPError_ItemNotFound,¤¤   ¤   "item not found"),
53390f EN( kPGPError_ItemAlreadyExists,¤   ¤   "item already exists"),
e31f06 EN( kPGPError_AssertFailed,¤¤   ¤   "assert failed"),
eb2723 EN( kPGPError_BadMemAddress,¤   ¤   ¤   "bad memory address"),
19d59a EN( kPGPError_UnknownError,¤¤   ¤   "unknown error"),
90af5a
bea410 EN( kPGPError_PrefNotFound,¤¤   ¤   "preference not found"),
10eba8 EN( kPGPError_EndOfIteration,¤  ¤   "end of iteration"),
3302dd EN( kPGPError_ImproperInitialization,¤  "improper initialization"),
876129 EN( kPGPError_CorruptData,¤ ¤   ¤   "corrupt data"),
5367a4 EN( kPGPError_FeatureNotAvailable,¤ "feature not available"),
3daf5a
44af5a
b0c176 /* __________________________________________________________________ */
436e3b /* later, if necessary, this table can be moved into its own file */
72af5a
dbaf5a
--205a 0005bced14e4010025c Page 2 of pgpErrors.c
ab0116 EN( kPGPError_BadPassphrase,¤   ¤   ¤   "bad passphrase"),
c5bfdb EN( kPGPError_RedundantOptions,¤¤   "redundant options"),
12eb67 EN( kPGPError_OptionNotFound,¤  ¤   "option not found"),
01b6d6 EN( kPGPError_CAPIUnsupportedKey,
2d0ff5 ¤   ¤   ¤   ¤   ¤   ¤   "key is not supported by Microsoft CAPI library"),
53af5a
85e97f EN( kPGPError_KeyRevoked,¤  ¤   ¤   ¤   "key has been revoked"),
5d608c EN( kPGPError_KeyExpired,¤  ¤   ¤   ¤   "key has expired"),
af1c9c EN( kPGPError_KeyDisabled,¤ ¤   ¤   ¤   "key has been disabled"),
8e0891 EN( kPGPError_KeyInvalid,¤  ¤   ¤   ¤   "key validity is low or none"),
9039fe EN( kPGPError_KeyUnusableForEncryption,¤"key can't be used for encryption"),
aa3ed0 EN( kPGPError_KeyUnusableForSignature,¤ "key can't be used for signing"),
98621f EN( kPGPError_OutputBufferTooSmall,¤¤   "space for output was too small"),
6c2663 EN( kPGPError_InconsistentEncryptionAlgorithms,"No alg for all recips"),
0ade3f EN( kPGPError_MissingPassphrase,¤   ¤   ¤   "needed passphrase is missing"),
19cc30 EN( kPGPError_CombinedConventionalAndPublicEncryption,"conv & pk no go"),
74af6f EN( kPGPError_DetachedSignatureWithoutSigningKey,"Bad option combo"),
9b90c5 EN( kPGPError_DetachedSignatureWithEncryption,"Bad option combination"),
a5dbb6 EN( kPGPError_NoInputOptions,¤  ¤   ¤   "wo input was specified"),
634f9b EN( kPGPError_MultipleInputOptions,¤¤   "only one input option allowed"),
6c7bd3 EN( kPGPError_InputFile,¤   ¤   ¤   ¤   ¤   "problem opening input file"),
9c0480 EN( kPGPError_NoOutputOptions,¤ ¤   ¤   "No output was specified"),
321761 EN( kPGPError_MultipleOutputOptions,¤   ¤   "only one output option allowed"),
2fa939 EN( kPGPError_MissingEventHandler,¤ ¤   "requested events but no handler"),
95b8aa EN( kPGPError_MissingKeySet,¤   ¤   ¤   ¤   "need keyset for decoding"),
f94026 EN( kPGPError_DetachedSignatureFound,¤  "found detached sig, no callback"),
1c463f EN( kPGPError_NoDecryptionKeyFound,¤¤   "unable to decrypt, no key"),
b64a16 EN( kPGPError_CorruptSessionKey,¤   ¤   ¤   "encrypted session key is bad"),
e9efe9 EN( kPGPError_SkipSection,¤ ¤   ¤   ¤   "user says to skip this section"),
809270 EN( kPGPError_Interrupted,¤ ¤   ¤   ¤   "non-fatal interruption of job"),
15df81 EN( kPGPError_TooManyARRKs,¤¤   ¤   ¤   "exceeded ARR limit on keygen"),
241467 EN( kPGPError_KeyUnusableForDecryption,¤"key can't be used for decryption"),
d678d2 EN( kPGPError_IncompatibleAPI,¤ ¤   ¤   "library version too old or too new"),
e1af5a
d86b53 EN( kPGPError_NotMacBinary,¤¤   ¤   ¤   ¤   ¤   "not a MacBinary file"),
694927 EN( kPGPError_NoMacBinaryTranslationAvailable,
e5b24e ¤   ¤   "MacBinary file can't be translated"),
63af5a
baaf5a
797985 EN( kPGPError_InconsistentFilterClasses,¤   "inconsisten filter classes"),
af0d52 EN( kPGPError_UnsupportedLDAPFilter,¤   ¤   "this search unavailable for LDAP"),
8f04e4 EN( kPGPError_UnsupportedHKPFilter,¤¤   "this search unavailable for HTTP"),
20a2e0 EN( kPGPError_UnknownFilterType,¤   ¤   ¤   "unknown filter type"),
e9419d EN( kPGPError_InvalidFilterParameter,¤  "invalid filter parameter"),
d3af5a
59af5a
62bf0c /* old errors: */
146911 EN( kPGPError_OutOfRings,¤  ¤   ¤   ¤   "internal keyring bits exhausted"),
eb382c EN( kPGPError_BadHashNumber,¤   ¤   ¤   ¤   "unknown hash number"),
65d7c9 EN( kPGPError_BadCipherNumber,¤ ¤   ¤   "unknown cipher number"),
563aed EN( kPGPError_BadKeyLength,¤¤   ¤   ¤   "illegal key length for cipher"),
3740e3 EN( kPGPError_SizeAdviseFailure,¤   ¤   ¤   "sizeAdvise promise not kept"),
b9f55a EN( kPGPError_ConfigParseFailure,¤  ¤   "error parsing configuration"),
084fbb EN( kPGPError_ConfigParseFailureBadFunction,"invalid configuration function"),
35a111 EN( kPGPError_ConfigParseFailureBadOptions,"unknown configuration option"),
09caf0 EN( kPGPError_KeyIsLocked,¤ ¤   ¤   ¤   "key requires passphrase to unlock"),
4d8e08 EN( kPGPError_CantDecrypt,¤ ¤   ¤   ¤   "cannot decrypt message"),
0bcb1c EN( kPGPError_BadSessionKeySize,
55bacd ¤   "encrypted session key too short"),
7a4ef3 EN( kPGPError_BadSessionKeyAlgorithm,
af7caa ¤   "encrypted session key algorithm unknown"),
9307a5 EN( kPGPError_UnknownSignatureType,¤¤   "unknown signature type"),
356825 EN( kPGPError_BadSignatureSize,¤"signature size too long or too short"),
a6bee6 EN( kPGPError_SignatureBitsWrong,¤  "wrong number of bits in signature"),
c3c368 EN( kPGPError_ExtraDateOnSignature,¤¤   "invalid Extra Data for Signature"),
ba6982 EN( kPGPError_SecretKeyNotFound,¤   ¤   ¤   "no secret key found"),
c6c0aa EN( kPGPError_AdditionalRecipientRequestKeyNotFound,
5f359c ¤   ¤   ¤   ¤   ¤   ¤   ¤   "additional recipient request key not found"),
c7ea95 EN( kPGPError_InvalidCommit,¤   ¤   ¤   ¤   "invalid commit response"),
41f1c4 EN( kPGPError_CantHash,¤¤   ¤   ¤   ¤   "cannot hash message"),
3ff2e5 EN( kPGPError_UnbalancedScope,¤ ¤   ¤   "unbalanced scope"),
5bde6a EN( kPGPError_WrongScope,¤  ¤   ¤   ¤   "data sent in wrong scope"),
--363d 000ca9e943d4010025c Page 3 of pgpErrors.c
43b64c EN( kPGPError_PublicKeyTooSmall,¤   ¤   ¤   "public Key too small for data"),
3c3cc1 EN( kPGPError_PublicKeyTooLarge,¤   ¤   ¤   "public Key too big for Library"),
26e0a4 EN( kPGPError_PublicKeyUnimplemented,"unimplemented public key operation"),
a2797e EN( kPGPError_FIFOReadError,¤   ¤   ¤   ¤   "incomplete read from Fifo"),
95b835 EN( kPGPError_RandomSeedTooSmall,¤  ¤   "not enough data in randseed file"),
f588f2 EN( kPGPError_EnvPriorityTooLow,¤   ¤   "env var not set: priority too low"),
37eec5 EN( kPGPError_UnknownCharMap,¤  ¤   ¤   "unknown charset"),
02f752 EN( kPGPError_AsciiParseIncomplete,¤¤   "ascii armor input incomplete"),
b9af5a
41af5a
b9af5a
9d4301 EN( kPGPError_TroubleKeySubKey,¤¤   ¤   "key matches subkey"),
e1f31a EN( kPGPError_TroubleSigSubKey,¤¤   ¤   "signature by subkey"),
15878b EN( kPGPError_TroubleBadTrust,¤ ¤   ¤   "trust packet malformed"),
817ab6 EN( kPGPError_TroubleUnknownPacketByte,¤"unknown packet PGPByte in keyring"),
8406a1 EN( kPGPError_TroubleUnexpectedSubKey,¤ "unexpected subkey (before key),"),
f672d1 EN( kPGPError_TroubleUnexpectedName,¤   ¤   "unexpected name (before key),"),
380338 EN( kPGPError_TroubleUnexpectedSignature,"unexpected sig (before key),"),
4c6493 EN( kPGPError_TroubleUnexpectedUnknown,
84bac7 ¤   "packet of unknown type in unexpected location (before key),"),
e96489 EN( kPGPError_TroubleUnexpectedTrust,¤  "unexpected trust packet"),
050ebc EN( kPGPError_TroubleKeyTooBig,¤¤   ¤   "key grossly oversized"),
715ee0 EN( kPGPError_TroubleSecretKeyTooBig,¤  "secret key grossly oversized"),
90c417 EN( kPGPError_TroubleNameTooBig,¤   ¤   ¤   "name grossly oversized"),
ae8c0f EN( kPGPError_TroubleSignatureTooBig,¤  "sig grossly oversized"),
2f8cae EN( kPGPError_TroubleUnknownTooBig,
cb2b9e ¤   "packet of unknown type too large to handle"),
dc1a2a EN( kPGPError_TroubleDuplicateKeyID,¤   ¤   "duplicate KeyID, different keys"),
6988fb EN( kPGPError_TroubleDuplicateKey,¤ ¤   "duplicate key (in same keyring)"),
03dbdd EN( kPGPError_TroubleDuplicateSecretKey,"duplicate secret (in same keyring)"),
25ee11 EN( kPGPError_TroubleDuplicateName,¤¤   "duplicate name (in same keyring)"),
405fad EN( kPGPError_TroubleDuplicateSignature,
bdb1b2 ¤   "duplicate signature (in same keyring)"),
e700b4 EN( kPGPError_TroubleDuplicateUnknown,"duplicate unknown \"thing\" in keyring"),
435028 EN( kPGPError_TroubleBareKey,¤  ¤   ¤   "key found with no names"),
d9864e EN( kPGPError_TroubleVersionBugPrev,¤   "bug introduced by legal_kludge"),
ebd7b5 EN( kPGPError_TroubleVersionBugCur,¤¤   "bug introduced by legal_kludge"),
3d5f1c EN( kPGPError_TroubleOldSecretKey,¤ ¤   "passphrase is out of date"),
95a3fb EN( kPGPError_TroubleNewSecretKey,¤ ¤   "passphrase is newer than another"),
c52f41 EN( kPGPError_BadPacket,¤   ¤   ¤   ¤   ¤   "bad packet" ),
812a2e /*¤
d2539d * Errors that can be encountered when parsing a key.
c0d3c2 * If multiple errors apply, only the last is reported.
4d7119 *
e77f6b * Note: Obviously the modulus n = p*q must be odd, if p and q
5348ab * are both large primes, since all primes greater than 2 are odd.
a4f409 * The exponent e must have a corresponding decryption exponent
9824ee * d such that e*d mod gcd(p-1,q-1), = 1.¤   Since p-1 and q-1 are both
184889 * even, their gcd must also be even and thus e*d mod 2 = 1, implying
94b21e * that e mod 2 = 1.
3e5ba0 * I.e. if e were even, the message would not be decryptable.
217fe0 */
41af5a
e3e653 /* kPGPError_KEY_LONG is a warning only */
4aaf5a
778249 EN( kPGPError_KEY_LONG,¤¤   ¤   ¤   ¤   "key packet has trailing junk"),
ebd64e EN( kPGPError_KeyPacketTruncated,¤  ¤   "key packet truncated"),
25670d EN( kPGPError_UnknownKeyVersion,¤   ¤   ¤   "key version unknown"),
ce3bb5 EN( kPGPError_UnknownPublicKeyAlgorithm,¤   "key algorithm unknown"),
0b899c EN( kPGPError_MalformedKeyModulus,¤ ¤   "key modulus mis-formatted"),
1f13c4 EN( kPGPError_MalformedKeyExponent,¤¤   "key exponent mis-formatted"),
984508 EN( kPGPError_RSAPublicModulusIsEven,¤  "RSA public modulus is even"),
cf2a09 EN( kPGPError_RSAPublicExponentIsEven,¤ "RSA public exponent is even"),
c50d0a EN( kPGPError_MalformedKeyComponent,¤   ¤   "key component mis-formatted"),
50af5a
7f38e5 /*
7c323e * Errors that can be encountered when parsing a signature.
9cd3c2 * If multiple errors apply, only the last is reported.
747fe0 */
d4af5a
9daf5a
ca0740 EN( kPGPError_SIG_LONG,¤¤   ¤   ¤   ¤   "signature packet has trailing junk"),
--5b10 000ef7f0fa44010025c Page 4 of pgpErrors.c
5b5b5a EN( kPGPError_TruncatedSignature,¤  ¤   "signature truncated"),
00a12b EN( kPGPError_MalformedSignatureInteger,¤   "signature integer mis-formatted"),
2edf9d EN( kPGPError_UnknownSignatureAlgorithm,¤   "signature algorithm unknown"),
501420 EN( kPGPError_ExtraSignatureMaterial,¤  "bad signature extra material (not 5)"),
3b0429 EN( kPGPError_UnknownSignatureVersion,¤ "signature version unknown"),
4caf5a
2ee91a /*¤ Mid-level key manipulation API error codes */
053ba0 EN( kPGPError_OutOfEntropy,¤¤   ¤   "insufficient random bits"),
36c86d EN( kPGPError_ItemIsReadOnly,¤  ¤   "object is read-only"),
87ecf2 EN( kPGPError_InvalidProperty,¤ ¤   "invalid property name"),
b84164 EN( kPGPError_FileCorrupt,¤ ¤   ¤   "key database is corrupt"),
956fe5 EN( kPGPError_UnknownVersion,¤  ¤   "unknown version"),
372b33 EN( kPGPError_DuplicateCert,¤   ¤   ¤   "duplicate certification"),
5dda6a EN( kPGPError_DuplicateUserID,¤ ¤   "duplicate UserID"),
b53eb1 EN( kPGPError_CertifyingKeyDead,¤   ¤   "certifying key no longer valid"),
98a69a EN( kPGPError_ItemWasDeleted,¤  ¤   "Object has been deleted"),
e0af5a
d2e1f2 /*¤ Certificate Server error codes */
9557b1 EN( kPGPError_ServerInProgress,¤"server operation in progress"),
e09b37 EN( kPGPError_ServerOperationNotSupported,¤ "server operation not supported"),
c998e6 EN( kPGPError_ServerInvalidProtocol,¤   "invalid server protocol"),
0784ab EN( kPGPError_ServerRequestFailed,¤ "the request was rejected by the server"),
0c4657 EN( kPGPError_ServerOpen,¤  "server already open"),
ef783b EN( kPGPError_ServerNotOpen, "server not open"),
edc7d4 EN( kPGPError_ServerKeyAlreadyExists,
0566b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "the exact key already exists on the server"),
3cd87c EN( kPGPError_ServerNotInitialized,¤"server not initialized"),
25f638 EN( kPGPError_ServerPartialAddFailure,
ef407c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "some keys could not be added to the server"),
508370 EN( kPGPError_ServerCorruptKeyBlock,¤   "corrupt keyblock"),
e8b630 EN( kPGPError_ServerUnknownResponse, "unknown response from server"),
5ec6e8 EN( kPGPError_ServerTimedOut,¤  "server request timed out"),
dcdf41 EN( kPGPError_ServerOpenFailed,¤¤   "server open failed"),
3b018c EN( kPGPError_ServerAuthorizationRequired,·
acb988 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "authorization required for this operation"),
889d7a EN( kPGPError_ServerAuthorizationFailed,·
bccf6b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "authorization failed for this operation"),
c27072 EN( kPGPError_ServerSearchFailed,¤  "server search failed"),
38ebae EN( kPGPError_ServerPartialSearchResults,¤  "server returned partial results"),
6322a0 EN( kPGPError_ServerBadKeysInSearchResults,
6e52d3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "the server returned 1 or more corrupt keys"),
7f416c EN( kPGPError_ServerKeyFailedPolicy, "the key failed the server policy check"),
e69bd2 EN( kPGPError_ServerOperationRequiresTLS, "the operation requires TLS"),
e1edb3 EN( kPGPError_ServerNoStaticStorage,
74981a ¤   ¤   "server static storage not allocated for thread"),
f9af5a
738e72 /* TLS error codes */
692b9a EN( kPGPError_TLSUnexpectedClose,
5bf703 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "the TLS connection was unexpectedly shutdown"),
ee046f EN( kPGPError_TLSProtocolViolation,
8673e8 ¤   ¤   ¤   ¤   ¤   "the remote system violated the TLS connection protocol"),
8c01ee EN( kPGPError_TLSVersionUnsupported,
0035da ¤   ¤   ¤   ¤   ¤   "the TLS version of the remote system is not compatible"),
6e7033 EN( kPGPError_TLSWrongState,
9d8a80 ¤   ¤   ¤   ¤   ¤   "the remote system violated the TLS handshake sequence"),
c1b9d0 EN( kPGPError_TLSAlertReceived, "the remote system aborted the TLS connection"),
fa78b5 EN( kPGPError_TLSKeyUnusable,
ab4151 ¤   ¤   ¤   ¤   ¤   "the selected key is not capable of TLS authentication."),
43d3a1 EN( kPGPError_TLSNoCommonCipher,
72ccc1 ¤   ¤   ¤   "the encryption suggested by the remote TLS system is not usable"),
dde8d0 EN( kPGPError_TLSWouldBlock,
eb9930 ¤   ¤   ¤   "TLS would block"),
3bce3d EN( kPGPError_TLSRcvdHandshakeRequest,
e44258 ¤   ¤   ¤   "the remote system requested a renegotiation of the key schedules"),
5aaf5a
a56254 /* Sockets error codes */
6b6373 EN( kPGPError_SocketsNetworkDown,¤  "network down"),
ce1c6f EN( kPGPError_SocketsNotInitialized, "sockets not initialized"),
99aeeb EN( kPGPError_SocketsInProgress,¤   "sockets call already in progress"),
8495e3 EN( kPGPError_SocketsNotConnected,¤ "socket is not connected"),
8996ba EN( kPGPError_SocketsNotBound, "socket has not been bound"),
ef6c6e EN( kPGPError_SocketsOperationNotSupported,
--e93e 000e7bc72424010025c Page 5 of pgpErrors.c
777862 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "operation not supported on this socket"),
35a1ff EN( kPGPError_SocketsProtocolNotSupported,
6401ba ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "protocol not supported by sockets"),
41d7e3 EN( kPGPError_SocketsAddressFamilyNotSupported,
a8147b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "address family not supported by sockets"),
a3ea6d EN( kPGPError_SocketsNotASocket,¤   "not a socket"),
76aeb2 EN( kPGPError_SocketsAddressInUse,¤ "address already in use by another socket"),
14d487 EN( kPGPError_SocketsBufferOverflow,¤   "buffer overflow"),
7ff92c EN( kPGPError_SocketsListenQueueFull,¤  "listen queue is full"),
b006e3 EN( kPGPError_SocketsAddressNotAvailable,¤  "address not available to socket"),
47b7da EN( kPGPError_SocketsAlreadyConnected,¤ "socket is already connected"),
af703d EN( kPGPError_SocketsTimedOut,¤ "socket timed out during operation"),
ca39bd EN( kPGPError_SocketsHostNotFound,¤ "host not found"),
5a053d EN( kPGPError_SocketsDomainServerError,¤"error in domain name system"),
d6887b EN( kPGPError_SocketsNoStaticStorage,
4a1c16 ¤   ¤   "sockets static storage not allocated for thread")
a682f7 };
8f0c7a #define kPGPErrors_NumErrorTableEntries¤¤   \
cadc6e ¤   ( sizeof( sErrors ) / sizeof( sErrors[ 0 ] ) )
e6af5a
00a65c #undef EN
e5af5a
18af5a
1d67c5 ¤
3721ab ¤   PGPError·
400657 PGPGetErrorString(
50c7e5 ¤   PGPError¤   theError,
68c102 ¤   PGPSize¤¤   bufferSize,
c56e0a ¤   char *¤ ¤   theString )
fabb36 {
e0cdc4 ¤   PGPUInt32¤  ¤   idx;
793423 ¤   char¤   ¤   ¤   temp[ 256 ];
08dc2c ¤   char const *¤   errStr¤ = NULL;
5b4e6e ¤   PGPSize¤¤   ¤   len¤= 0;
8f5a23 ¤   PGPBoolean¤ ¤   bufferBigEnough¤= FALSE;
7967c5 ¤
ccbb87 ¤   PGPValidateParam( bufferSize >= 1 );
31f382 ¤   PGPValidatePtr( theString );
584a4b ¤   *theString¤ = '\0';
bc67c5 ¤
c95b53 ¤   for( idx = 0; idx < kPGPErrors_NumErrorTableEntries; ++idx )
b0c7a1 ¤   {
808ea0 ¤   ¤   const ErrorEntry *¤ entry;
4a1b52 ¤   ¤
b1287f ¤   ¤   entry¤  = &sErrors[ idx ];
090504 ¤   ¤   if ( entry->number == theError )
775b34 ¤   ¤   {
3086e4 ¤   ¤   ¤   errStr¤ = entry->string;
5ccdcb ¤   ¤   ¤   break;
e00fe4 ¤   ¤   }
0b9371 ¤   }
d367c5 ¤
728dc0 ¤   if ( IsNull( errStr ) )
69c7a1 ¤   {
d7e8a8 ¤   ¤   /* Produce something for missing errors */
cbd8d0 ¤   ¤   sprintf( temp, "PGPError #%ld", (long)theError );
ad5187 ¤   ¤   errStr¤ = temp;
819371 ¤   }
1067c5 ¤
7a7128 ¤   len¤= strlen( errStr );
420bb4 ¤   bufferBigEnough¤= ( len + 1 <= bufferSize );
28b274 ¤   if ( bufferBigEnough )
ffc7a1 ¤   {
af0262 ¤   ¤   strcpy( theString, errStr );
d49371 ¤   }
770e24 ¤   else
ffc7a1 ¤   {
e08369 ¤   ¤   pgpCopyMemory( errStr, theString, bufferSize - 1 );
96bdfb ¤   ¤   theString[ bufferSize - 1 ]¤= '\0';
de9371 ¤   }
de67c5 ¤
e711d3 ¤   return( bufferBigEnough¤? kPGPError_NoErr : kPGPError_BufferTooSmall );
--c30e 0018560336a4010025c Page 6 of pgpErrors.c
7aefe6 }
46af5a
8eaf5a
79af5a
707e4d /*__Editor_settings____
8caf5a
734126 ¤   Local Variables:
3a7b17 ¤   tab-width: 4
1e0e6c ¤   End:
175f8c ¤   vi: ts=4 sw=4
379e9b ¤   vim: si
85d062 _____________________*/
--0ac4 0013bde0f744010025d Page 1 of pgpErrorsPriv.h
a70335 /*____________________________________________________________________________
917db0 ¤   pgpErrorsPriv.h
b667c5 ¤
19c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
424b0f ¤   All rights reserved.
7f67c5 ¤
b4a564 ¤   Error codes for all PGP errors can be found in this file.
0aaf5a
3906af ¤   $Id: pgpErrorsPriv.h,v 1.9.24.1 1998/11/12 03:23:17 heller Exp $
44f7f7 ____________________________________________________________________________*/
f8d8da #ifndef Included_pgpErrorsPriv_h¤   /* [ */
2d8d8e #define Included_pgpErrorsPriv_h
ffaf5a
ccc5d5 #include "pgpBase.h"
24af5a
6699c6 PGP_BEGIN_C_DECLARATIONS
89af5a
c7af5a
822990 char const ·*pgperrString(PGPError¤ error);
62af5a
72af5a
efaf5a
3f1254 PGP_END_C_DECLARATIONS
98af5a
e97de4 #endif /* ] Included_pgpErrorsPriv_h */
18af5a
347e4d /*__Editor_settings____
93af5a
5f4126 ¤   Local Variables:
907b17 ¤   tab-width: 4
7d0e6c ¤   End:
6b5f8c ¤   vi: ts=4 sw=4
eb9e9b ¤   vim: si
3bd062 _____________________*/
--376d 0014b601cc14010025e Page 1 of Makefile.in
5ea601 #
a0340f # priv/utilities/helper/
52a601 #
6deeca # $Id: Makefile.in,v 1.5 1997/08/20 01:49:37 lloyd Exp $
77a601 #
0daf5a
d747a2 OBJS=¤  pgpAnnotate.o pgpByteFIFO.o pgpCharMap.o pgpFIFO.o \
9ded54 ¤   pgpPassCach.o pgpPipeFile.o pgpFile.o pgpMemFile.o pgpMsg.o \
e76253 ¤   pgpStr2Key.o pgpTimeDate.o pgpFileFIFO.o pgpFlexFIFO.o \
9b7d65 ¤   pgpFileNames.o pgpFileRef.o pgpMacBinary.o pgpMacFileMapping.o
f91130 PRIVHDRS= pgpFIFO.h pgpPassCach.h pgpFile.h pgpStr2Key.h pgpTimeDate.h \
99dc8b ¤   pgpFileNames.h pgpFileRef.h pgpByteFIFO.h pgpCharMap.h pgpMacBinary.h \
6413f6 ¤   pgpMacFileMapping.h
3daf5a
64b7a3 all:: DONE
4baf5a
--e138 001dc743ce44010025f Page 1 of pgpAnnotate.c
bc38e5 /*
ea36b6 ·* pgpAnnotate.c -- convert an annotation type to a string.
4a775e ·*
3c7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
0c775e ·*
342cae ·* $Id: pgpAnnotate.c,v 1.2 1997/05/02 22:45:57 lloyd Exp $
d7495d ·*/
50af5a
6ae2ff #include "pgpConfig.h"
1faf5a
d06aaa #include "pgpAnnotate.h"
63af5a
c7673a const char *
31d92a pgpScopeName (int type)
16bb36 {
dc3468 ¤   if (!PGP_IS_BEGIN_SCOPE (type))
1da927 ¤   ¤   return "Not a Begin Scope type";
f4af5a
471609 ¤   switch (type) {
4e24fb ¤   case PGPANN_UNKNOWN_BEGIN:
dedef5 ¤   ¤   return "Unknown";
106a68 ¤   case PGPANN_LITERAL_BEGIN:
067f56 ¤   ¤   return "Literal";¤
61f02c ¤   case PGPANN_CIPHER_BEGIN:
7fbade ¤   ¤   return "Encrypted";
5be6ef ¤   case PGPANN_COMPRESSED_BEGIN:
8d0125 ¤   ¤   return "Compressed";
484168 ¤   case PGPANN_COMMENT_BEGIN:
00cf72 ¤   ¤   return "Comment";
561f47 ¤   case PGPANN_SIGNED_BEGIN:
ebda4b ¤   ¤   return "Signed";
941e89 ¤   case PGPANN_NONPACKET_BEGIN:
615db8 ¤   ¤   return "Non";
799950 ¤   case PGPANN_NONPGP_BEGIN:
15f07c ¤   ¤   return "Unprotected";
2bb3c7 ¤   case PGPANN_ARMOR_BEGIN:
ee39e4 ¤   ¤   return "Ascii Armored";
93f708 ¤   case PGPANN_CLEARSIG_BEGIN:
36c819 ¤   ¤   return "Clearsigned";
afc23d ¤   case PGPANN_PGPKEY_BEGIN:
842f07 ¤   ¤   return "PGP Key";
ad05ec ¤   case PGPANN_INPUT_BEGIN:
37dc5e ¤   ¤   return "Input";
c9aa6d ¤   case PGPANN_FILE_BEGIN:
90b13d ¤   ¤   return "File";
3a2f72 ¤   default:
89a8a8 ¤   ¤   return "HUH? Weird Packet";
569371 ¤   }
dcefe6 }
--330a 0001cb18fcc40100260 Page 1 of pgpByteFIFO.c
bc38e5 /*
2f1e25 ·* Bytefifo.c - an infinitely-expandable FIFO structure for bytes.
24775e ·*
1b3785 ·* $Id: pgpByteFIFO.c,v 1.20.4.1 1998/09/14 21:48:15 hal Exp $
fc495d ·*/
1fe2ff #include "pgpConfig.h"
37af5a
e77df1 #include <stdio.h>¤ /* For BUFSIZ */
5d324c #include <string.h>
03af5a
62a146 #include "pgpDebug.h"
c483d5 #include "pgpByteFIFO.h"
340d08 #include "pgpMem.h"
fed11f #include "pgpUsuals.h"
e0c26c #include "pgpContext.h"
1baf5a
e0ec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
239d4e #define kPGPFIFOPageSize¤   16384
79db21 #else
73f055 #define kPGPFIFOPageSize¤   BUFSIZ
9e7454 #endif
6aaf5a
22cef2 typedef struct ByteFifoPage {
9fd1f2 ¤   struct ByteFifoPage *next;
fbebd6 ¤   PGPByte buf[kPGPFIFOPageSize-sizeof(struct ByteFifoPage *)];
5e472d ¤   DEBUG_STRUCT_CONSTRUCTOR( ByteFifoPage )
429978 } ByteFifoPage;
75af5a
1caeff struct PGPFifoContext {
5bd91c ¤   PGPMemoryMgrRef¤memoryMgr;
348b3f ¤   ByteFifoPage *head, *tail;
cd5057 ¤   PGPByte *putp;
53e197 ¤   PGPByte const *getp;
d77fd1 ¤   PGPSize pages;
518c4a ¤   PGPBoolean secure;
9bb44f ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPFifoContext )
2f82f7 };
33af5a
912978 static void
3738ee byteFifoInit(
882f6d ¤   PGPMemoryMgrRef¤¤   memoryMgr,
d2c5b4 ¤   PGPFifoContext *¤   fifo,
8304e8 ¤   PGPBoolean¤ ¤   ¤   secure)
03bb36 {
4e193c ¤   fifo->memoryMgr¤= memoryMgr;
3b7e9a ¤   fifo->head = 0;
57b9c8 ¤   fifo->tail = 0;
482cd3 ¤   fifo->putp = 0;
43c5e0 ¤   fifo->getp = 0;
5beca3 ¤   fifo->pages = 0;
701521 ¤   fifo->secure = secure;
21efe6 }
01af5a
db314a void
64c7cc byteFifoFlush(PGPFifoContext *fifo)
11bb36 {
66e7cc ¤   ByteFifoPage *page;
e1af5a
bf04bf ¤   while ((page = fifo->head) != 0) {
608f21 ¤   ¤   fifo->head = page->next;
fef53d ¤   ¤   pgpClearMemory( page, ·sizeof(page));
52a440 ¤   ¤   PGPFreeData( page );
a99371 ¤   }
33b9c8 ¤   fifo->tail = 0;
c02cd3 ¤   fifo->putp = 0;
85c5e0 ¤   fifo->getp = 0;
4beca3 ¤   fifo->pages = 0;
45efe6 }
ebaf5a
6731ca PGPSize
e34b7f byteFifoSize(PGPFifoContext const *fifo)
1cbb36 {
--b329 0005d4fd3d940100260 Page 2 of pgpByteFIFO.c
e26f56 ¤   PGPSize¤space;
79919c ¤   if (!fifo->pages)
23bbde ¤   ¤   return 0;
9daa89 ¤   space = (fifo->putp - fifo->tail->buf) +
719c72 ¤   ¤   (fifo->head->buf + sizeof(fifo->head->buf) - fifo->getp);
8580fa ¤   space += (fifo->pages-1) * sizeof(fifo->head->buf);
4d7dcd ¤   return space - sizeof(fifo->head->buf);
8fefe6 }
25af5a
a574a2 PGPFifoContext *
e688fb byteFifoCreate( PGPContextRef context ·)
68bb36 {
303566 ¤   PGPFifoContext *fifo;
67cf69 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( context );
c1af5a
0585ac ¤   fifo = (PGPFifoContext *)
f2a8d7 ¤   ¤   PGPNewData( memoryMgr, sizeof(*fifo), 0);
680341 ¤   if (fifo)
10c7a1 ¤   {
3285c6 ¤   ¤   byteFifoInit( memoryMgr, fifo, FALSE);
939371 ¤   }
048722 ¤   return fifo;
97efe6 }
4faf5a
3374a2 PGPFifoContext *
618386 byteFifoCreateSecure( PGPContextRef context ·)
55bb36 {
873566 ¤   PGPFifoContext *fifo;
4ccf69 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( context );
1baf5a
e985ac ¤   fifo = (PGPFifoContext *)
bda8d7 ¤   ¤   PGPNewData( memoryMgr, sizeof(*fifo), 0);
120341 ¤   if (fifo)
40c7a1 ¤   {
ae41fe ¤   ¤   byteFifoInit( memoryMgr, fifo, TRUE);
2c9371 ¤   }
de8722 ¤   return fifo;
4befe6 }
38af5a
e1314a void
5461ed byteFifoDestroy(PGPFifoContext *fifo)
1abb36 {
10450a ¤   byteFifoFlush(fifo);
2040bb ¤   PGPFreeData( fifo );
41efe6 }
84af5a
4e1f9c PGPByte *
f3648e byteFifoGetSpace(PGPFifoContext *fifo, PGPSize *len)
48bb36 {
c36852 ¤   PGPSize avail;
f7e7cc ¤   ByteFifoPage *page;
a9af5a
dfa06b ¤   if (fifo->head) {
f5dae8 ¤   ¤   pgpAssert(fifo->putp);
25adc4 ¤   ¤   avail = fifo->tail->buf + sizeof(fifo->tail->buf) - fifo->putp;
bb1e66 ¤   ¤   if (avail) {
28d641 ¤   ¤   ¤   *len = avail;
219d04 ¤   ¤   ¤   return fifo->putp;
830fe4 ¤   ¤   }
c09371 ¤   }
2767b3 ¤   if (fifo->secure) {
ae6cdf ¤   ¤   page = (ByteFifoPage *)
9c2800 ¤   ¤   ¤   PGPNewSecureData( fifo->memoryMgr, sizeof(ByteFifoPage), 0);
bcf037 ¤   } else {
c26cdf ¤   ¤   page = (ByteFifoPage *)
219de1 ¤   ¤   ¤   PGPNewData( fifo->memoryMgr, sizeof(ByteFifoPage), 0);
d29371 ¤   }
861b52 ¤   ¤
bbc472 ¤   if (!page) {¤   /* Out of memory */
ec5afc ¤   ¤   *len = 0;
5ebbde ¤   ¤   return 0;
5d9371 ¤   }
--a829 0009124ec4d40100260 Page 3 of pgpByteFIFO.c
67b250 ¤   fifo->pages++;
15a06b ¤   if (fifo->head) {
6b0f77 ¤   ¤   pgpAssert(fifo->pages > 1);
c1717f ¤   ¤   fifo->tail->next = page;
6ff037 ¤   } else {
d07146 ¤   ¤   pgpAssert(fifo->pages == 1);
9d9ae6 ¤   ¤   fifo->head = page;
303df5 ¤   ¤   fifo->getp = page->buf;
209371 ¤   }
c2c9fe ¤   fifo->tail = page;
83408b ¤   page->next = 0;
9eed82 ¤   *len = sizeof(fifo->head->buf);
975558 ¤   return fifo->putp = page->buf;
6cefe6 }
8caf5a
3f314a void
926e3b byteFifoSkipSpace(PGPFifoContext *fifo, PGPSize len)
57bb36 {
5d4404 ¤   if (!len)
8999bf ¤   ¤   return;
b767c5 ¤
f6c40c ¤   pgpAssert(fifo->head);
a1cec0 ¤   pgpAssert(fifo->putp);
80efab ¤   pgpAssert(len <= (PGPSize)(fifo->tail->buf + sizeof(fifo->tail->buf)
ddb241 ¤   ·························- fifo->putp));
5faf5a
85f3a2 ¤   fifo->putp += len;
32efe6 }
08af5a
d8d929 PGPByte const *
4c1a3e byteFifoPeek(PGPFifoContext *fifo, PGPSize *len)
e8bb36 {
6c8798 ¤   if (!fifo->head) {
8e5afc ¤   ¤   *len = 0;
f7bf50 ¤   ¤   return 0;¤  /* No bytes available */
949371 ¤   }
cefea1 ¤   pgpAssert(fifo->getp);
a9edf5 ¤   /* Head and tail on same page? */
59e8be ¤   if (fifo->tail == fifo->head)
8130e0 ¤   ¤   *len = fifo->putp - fifo->getp;
bd0e24 ¤   else
ca4f23 ¤   ¤   *len = fifo->head->buf + sizeof(fifo->head->buf) - fifo->getp;
e614b0 ¤   return *len ? fifo->getp : 0;
2defe6 }
f2af5a
7d314a void
23cf76 byteFifoSeek(PGPFifoContext *fifo, PGPSize len)
63bb36 {
e4e7cc ¤   ByteFifoPage *page;
d1af5a
584404 ¤   if (!len)
7999bf ¤   ¤   return;
f9af5a
b1c40c ¤   pgpAssert(fifo->head);
a85886 ¤   pgpAssert(len <= (PGPSize)(fifo->head->buf + sizeof(fifo->head->buf)
b8c0fe ¤   ·························- fifo->getp));
9baf5a
eccba0 ¤   if (fifo->head == fifo->tail) {
be7146 ¤   ¤   pgpAssert(fifo->pages == 1);
90453f ¤   ¤   pgpAssert(fifo->head->next == 0);
1e8339 ¤   ¤   pgpAssert(len <= (PGPSize)(fifo->putp - fifo->getp));
5d99f5 ¤   ¤   if (len < (PGPSize)(fifo->putp - fifo->getp)) {
205220 ¤   ¤   ¤   fifo->getp += len;
6f45a6 ¤   ¤   } else {
f43091 ¤   ¤   ¤   pgpClearMemory(fifo->head, sizeof(*fifo->head));
725e13 ¤   ¤   ¤   PGPFreeData( fifo->head);
3f5077 ¤   ¤   ¤   byteFifoInit( fifo->memoryMgr, fifo, fifo->secure);
330fe4 ¤   ¤   }
ff99bf ¤   ¤   return;
979371 ¤   }
4caf5a
91848b ¤   pgpAssert(fifo->pages > 1);
--c08c 000c68a972140100260 Page 4 of pgpByteFIFO.c
e0af5a
7127f2 ¤   if (len < (PGPSize)(fifo->head->buf + sizeof(fifo->head->buf)
fec5f9 ¤   ·····················- fifo->getp))
c1c7a1 ¤   {
2b4608 ¤   ¤   fifo->getp += len;
c9f037 ¤   } else {
aae656 ¤   ¤   page = fifo->head;
655223 ¤   ¤   fifo->head = fifo->head->next;
0cd024 ¤   ¤   pgpAssert(fifo->head);
d31b17 ¤   ¤   pgpClearMemory( page, ·sizeof(*page));
10f79b ¤   ¤   PGPFreeData( page);¤
cd14fa ¤   ¤   fifo->pages--;
b4544f ¤   ¤   pgpAssert(fifo->pages);
4e4a1c ¤   ¤   fifo->getp = fifo->head->buf;
4b9371 ¤   }
39efe6 }
f8af5a
ac31ca PGPSize
755199 byteFifoWrite(PGPFifoContext *fifo, PGPByte const *buf, PGPSize len)
41bb36 {
ac6852 ¤   PGPSize avail;
828ade ¤   PGPByte *ptr;
f9fff5 ¤   PGPSize len0 = len;
baaf5a
f685aa ¤   while (len) {
bd1e45 ¤   ¤   ptr = byteFifoGetSpace(fifo, &avail);
53fded ¤   ¤   if (!ptr)
80d9f1 ¤   ¤   ¤   return len0 - len;
2e96e0 ¤   ¤   if (avail > len)
f9695a ¤   ¤   ¤   avail = len;
fa9f47 ¤   ¤   memcpy(ptr, buf, avail);
cce36d ¤   ¤   byteFifoSkipSpace(fifo, avail);
a0d19b ¤   ¤   buf += avail;
18887b ¤   ¤   len -= avail;
9a9371 ¤   }
2af5e0 ¤   return len0;
3befe6 }
35af5a
fc31ca PGPSize
39d2e1 byteFifoRead(PGPFifoContext *fifo, PGPByte *buf, PGPSize len)
25bb36 {
0d6852 ¤   PGPSize avail;
0ca617 ¤   PGPByte const *ptr;
0afff5 ¤   PGPSize len0 = len;
10af5a
9285aa ¤   while (len) {
62340f ¤   ¤   ptr = byteFifoPeek (fifo, &avail);
68fded ¤   ¤   if (!ptr)
58d9f1 ¤   ¤   ¤   return len0 - len;
8d96e0 ¤   ¤   if (avail > len)
57695a ¤   ¤   ¤   avail = len;
e72a1d ¤   ¤   memcpy (buf, ptr, avail);
6ad19b ¤   ¤   buf += avail;
11887b ¤   ¤   len -= avail;
492a0e ¤   ¤   byteFifoSeek (fifo, avail);
9b9371 ¤   }
c7f5e0 ¤   return len0;
75efe6 }
82af5a
cc814a #if UNITTEST
8d0227 /* Test driver */
c8feb2 #include <stdio.h>
66af5a
ea2978 static void
435c50 byteFifoDump(PGPFifoContext *fifo)
5abb36 {
a2a617 ¤   PGPByte const *ptr;
8b6852 ¤   PGPSize avail;
2daf5a
7679eb ¤   while ((ptr = byteFifoPeek(fifo, &avail)) != 0) {
7133cf ¤   ¤   fwrite(ptr, 1, avail, stdout);
c6d3b2 ¤   ¤   byteFifoSeek(fifo, avail);
--7671 001505dbd1240100260 Page 5 of pgpByteFIFO.c
a19371 ¤   }
c9efe6 }
a0af5a
5b4d2f int
7353a5 main(int argc, char **argv)
2dbb36 {
ce26dd ¤   PGPFifoContext fifo;
463489 ¤   PGPByte const c = ' ';
74927e ¤   int i, j;
75af5a
1cf3bb ¤   byteFifoInit(&fifo);
77af5a
90e9eb ¤   for (i = 1; i < argc; i++) {
23353f ¤   ¤   for (j = 1; j <= i; j++) {
472a4c ¤   ¤   ¤   byteFifoWrite(&fifo, argv[j], strlen(argv[j]));
5c6d9a ¤   ¤   ¤   if (i != j)
59813d ¤   ¤   ¤   ¤   byteFifoWrite(&fifo, &c, 1);
c40fe4 ¤   ¤   }
574eec ¤   ¤   printf("argv[1..%d] = (%lu) \"", i, byteFifoSize(&fifo));
e18f84 ¤   ¤   byteFifoDump(&fifo);
c10aa4 ¤   ¤   puts("\"");
f59371 ¤   }
573e6b ¤   return 0;
efefe6 }
aaaf5a
507454 #endif
--78d7 0013c55877940100261 Page 1 of pgpByteFIFO.h
bc38e5 /*
0909e8 ·* pgpByteFIFO.h -- A first-in-first-out pipe of bytes.
e3775e ·*
4de39d ·* This is a PRIVATE header file, for use only within the PGP Library.
2c2979 ·* You should not be using these functions in an application.
d9775e ·*
a005b1 ·* $Id: pgpByteFIFO.h,v 1.11.4.1 1998/09/14 21:48:20 hal Exp $
0d495d ·*/
73af5a
f25220 #ifndef Included_pgpByteFIFO_h
2f25d3 #define Included_pgpByteFIFO_h
7caf5a
d9e82c #include "pgpPubTypes.h"
8cadb8 #include "pgpOpaqueStructs.h"
226773 #include "pgpMemoryMgr.h"
a3af5a
e999c6 PGP_BEGIN_C_DECLARATIONS
baaf5a
dfaf5a
0ebe71 PGPFifoContext *byteFifoCreate ( PGPContextRef context );
28dc95 PGPFifoContext *byteFifoCreateSecure ( PGPContextRef context );
38f7fb void byteFifoDestroy (PGPFifoContext *fifo);
34af5a
05490b PGPByte *byteFifoGetSpace (PGPFifoContext *fifo, PGPSize *len);
f02684 void byteFifoSkipSpace (PGPFifoContext *fifo, PGPSize len);
dbaf5a
7a7070 PGPByte const *byteFifoPeek (PGPFifoContext *fifo, PGPSize *len);
c8d531 void byteFifoSeek (PGPFifoContext *fifo, PGPSize len);
f1af5a
0545c6 PGPSize byteFifoWrite (PGPFifoContext *fifo, PGPByte const *buf,
7f77c4 ¤   ¤   ······PGPSize len);
7f6ceb PGPSize byteFifoRead (PGPFifoContext *fifo, PGPByte *buf, PGPSize len);
60af5a
f5acfb void byteFifoFlush(PGPFifoContext *fifo);
2dec69 PGPSize byteFifoSize (PGPFifoContext const *fifo);
81af5a
001254 PGP_END_C_DECLARATIONS
f1af5a
3c1e2b #endif /* Included_pgpByteFIFO_h */
--ebf1 00082fd4a7c40100262 Page 1 of pgpCharMap.c
bc38e5 /*
187eac ·* Charmap.c
b9775e ·*
a5c49b ·* Mapping tables between different character sets.
fc775e ·*
a5dd62 ·* Written by colin Plumb.
a3775e ·*
d3cd55 ·* $Id: pgpCharMap.c,v 1.8 1997/09/15 21:21:54 hal Exp $
ac495d ·*/
fe324c #include <string.h>
d2af5a
67e2ff #include "pgpConfig.h"
afaf5a
d4b1cb #include <ctype.h>
fbaf5a
d27abc #include "pgpCharMap.h"
162f8d #include "pgpErrors.h"
71af5a
bb4d6c /**********************************************************************/
361df9 /* *INDENT-OFF* */
07a946 unsigned char const charMapIdentity[256] = {
6fb8d5 ··0, ··1, ··2, ··3, ··4, ··5, ··6, ··7, ··8, ··9, ·10, ·11, ·12, ·13, ·14, ·15,
863e0a ·16, ·17, ·18, ·19, ·20, ·21, ·22, ·23, ·24, ·25, ·26, ·27, ·28, ·29, ·30, ·31,
04f53d ·32, ·33, ·34, ·35, ·36, ·37, ·38, ·39, ·40, ·41, ·42, ·43, ·44, ·45, ·46, ·47,
7e2bda ·48, ·49, ·50, ·51, ·52, ·53, ·54, ·55, ·56, ·57, ·58, ·59, ·60, ·61, ·62, ·63,
163b96 ·64, ·65, ·66, ·67, ·68, ·69, ·70, ·71, ·72, ·73, ·74, ·75, ·76, ·77, ·78, ·79,
83a0a1 ·80, ·81, ·82, ·83, ·84, ·85, ·86, ·87, ·88, ·89, ·90, ·91, ·92, ·93, ·94, ·95,
134b4f ·96, ·97, ·98, ·99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
8926cf 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
e54f00 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
34fee8 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
99a3e9 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
14230a 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
e63418 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
7b5eaf 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
834ee3 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
22295d 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
ed82f7 };
b940df /* *INDENT-ON* */
99af5a
0d6068 /* Conversion table from `latin1' charset to `cp850' charset.
b344ed ·* Generated mechanically by GNU recode 3.4.
8f775e ·*
b15d84 ·* The recoding should be reversible.
99495d ·*/
f77124 static unsigned char const latin1_to_cp850[256] =
c2bb36 {
af2c4b ······0, ··1, ··2, ··3, ··4, ··5, ··6, ··7,¤/* ··0 - ··7 */
d5d97c ······8, ··9, ·10, ·11, ·12, ·13, ·14, ·15,¤/* ··8 - ·15 */
ccea6e ·····16, ·17, ·18, ·19, ·20, ·21, ·22, ·23,¤/* ·16 - ·23 */
ca84a8 ·····24, ·25, ·26, ·27, ·28, ·29, ·30, ·31,¤/* ·24 - ·31 */
efbc87 ·····32, ·33, ·34, ·35, ·36, ·37, ·38, ·39,¤/* ·32 - ·39 */
ef2d89 ·····40, ·41, ·42, ·43, ·44, ·45, ·46, ·47,¤/* ·40 - ·47 */
62ec79 ·····48, ·49, ·50, ·51, ·52, ·53, ·54, ·55,¤/* ·48 - ·55 */
0db90e ·····56, ·57, ·58, ·59, ·60, ·61, ·62, ·63,¤/* ·56 - ·63 */
e1d7c8 ·····64, ·65, ·66, ·67, ·68, ·69, ·70, ·71,¤/* ·64 - ·71 */
b9efe7 ·····72, ·73, ·74, ·75, ·76, ·77, ·78, ·79,¤/* ·72 - ·79 */
8ed829 ·····80, ·81, ·82, ·83, ·84, ·85, ·86, ·87,¤/* ·80 - ·87 */
b619d9 ·····88, ·89, ·90, ·91, ·92, ·93, ·94, ·95,¤/* ·88 - ·95 */
905d3a ·····96, ·97, ·98, ·99, 100, 101, 102, 103,¤/* ·96 - 103 */
d97183 ····104, 105, 106, 107, 108, 109, 110, 111,¤/* 104 - 111 */
8849ac ····112, 113, 114, 115, 116, 117, 118, 119,¤/* 112 - 119 */
738bc2 ····120, 121, 122, 123, 124, 125, 126, 127,¤/* 120 - 127 */
b4473c ····195, 179, 218, 200, 186, 203, 213, 204,¤/* 128 - 135 */
1dbecf ····219, 217, 254, 180, 238, 178, 196, 197,¤/* 136 - 143 */
b19a24 ····201, 230, 202, 194, 247, 242, 185, 191,¤/* 144 - 151 */
05353a ····223, 205, 220, 176, 250, 177, 206, 159,¤/* 152 - 159 */
3663f2 ····255, 173, 189, 156, 207, 190, 221, 245,¤/* 160 - 167 */
934fa5 ····249, 184, 166, 174, 170, 240, 169, 187,¤/* 168 - 175 */
56a1fd ····248, 241, 253, 252, 239, 193, 244, 192,¤/* 176 - 183 */
6670d3 ····188, 251, 167, 175, 172, 171, 243, 168,¤/* 184 - 191 */
824fa4 ····183, 181, 182, 199, 142, 143, 146, 128,¤/* 192 - 199 */
--3bde 00093e228d640100262 Page 2 of pgpCharMap.c
f0f672 ····212, 144, 210, 211, 222, 214, 215, 216,¤/* 200 - 207 */
92087d ····209, 165, 227, 224, 226, 229, 153, 158,¤/* 208 - 215 */
382deb ····157, 235, 233, 234, 154, 237, 231, 225,¤/* 216 - 223 */
8f959f ····133, 160, 131, 198, 132, 134, 145, 135,¤/* 224 - 231 */
8fe24a ····138, 130, 136, 137, 141, 161, 140, 139,¤/* 232 - 239 */
4c1b0a ····208, 164, 149, 162, 147, 228, 148, 246,¤/* 240 - 247 */
4fc909 ····155, 151, 163, 150, 129, 236, 232, 152¤ /* 248 - 255 */
9e82f7 };
62af5a
c392be /* Conversion table from `cp850' charset to `latin1' charset.
1044ed ·* Generated mechanically by GNU recode 3.4.
28775e ·*
be5d84 ·* The recoding should be reversible.
00495d ·*/
6929c7 static unsigned char const cp850_to_latin1[256] =
d2bb36 {
222c4b ······0, ··1, ··2, ··3, ··4, ··5, ··6, ··7,¤/* ··0 - ··7 */
89d97c ······8, ··9, ·10, ·11, ·12, ·13, ·14, ·15,¤/* ··8 - ·15 */
a4ea6e ·····16, ·17, ·18, ·19, ·20, ·21, ·22, ·23,¤/* ·16 - ·23 */
3584a8 ·····24, ·25, ·26, ·27, ·28, ·29, ·30, ·31,¤/* ·24 - ·31 */
3dbc87 ·····32, ·33, ·34, ·35, ·36, ·37, ·38, ·39,¤/* ·32 - ·39 */
3a2d89 ·····40, ·41, ·42, ·43, ·44, ·45, ·46, ·47,¤/* ·40 - ·47 */
9aec79 ·····48, ·49, ·50, ·51, ·52, ·53, ·54, ·55,¤/* ·48 - ·55 */
35b90e ·····56, ·57, ·58, ·59, ·60, ·61, ·62, ·63,¤/* ·56 - ·63 */
50d7c8 ·····64, ·65, ·66, ·67, ·68, ·69, ·70, ·71,¤/* ·64 - ·71 */
9defe7 ·····72, ·73, ·74, ·75, ·76, ·77, ·78, ·79,¤/* ·72 - ·79 */
94d829 ·····80, ·81, ·82, ·83, ·84, ·85, ·86, ·87,¤/* ·80 - ·87 */
1019d9 ·····88, ·89, ·90, ·91, ·92, ·93, ·94, ·95,¤/* ·88 - ·95 */
eb5d3a ·····96, ·97, ·98, ·99, 100, 101, 102, 103,¤/* ·96 - 103 */
297183 ····104, 105, 106, 107, 108, 109, 110, 111,¤/* 104 - 111 */
de49ac ····112, 113, 114, 115, 116, 117, 118, 119,¤/* 112 - 119 */
a78bc2 ····120, 121, 122, 123, 124, 125, 126, 127,¤/* 120 - 127 */
f3ffd7 ····199, 252, 233, 226, 228, 224, 229, 231,¤/* 128 - 135 */
156433 ····234, 235, 232, 239, 238, 236, 196, 197,¤/* 136 - 143 */
6384c5 ····201, 230, 198, 244, 246, 242, 251, 249,¤/* 144 - 151 */
d52b7d ····255, 214, 220, 248, 163, 216, 215, 159,¤/* 152 - 159 */
8f1629 ····225, 237, 243, 250, 241, 209, 170, 186,¤/* 160 - 167 */
717e8a ····191, 174, 172, 189, 188, 161, 171, 187,¤/* 168 - 175 */
d44a07 ····155, 157, 141, 129, 139, 193, 194, 192,¤/* 176 - 183 */
2737db ····169, 150, 132, 175, 184, 162, 165, 151,¤/* 184 - 191 */
295c49 ····183, 181, 147, 128, 142, 143, 227, 195,¤/* 192 - 199 */
d4a1b8 ····131, 144, 146, 133, 135, 153, 158, 164,¤/* 200 - 207 */
c42190 ····240, 208, 202, 203, 200, 134, 205, 206,¤/* 208 - 215 */
6104ed ····207, 137, 130, 136, 154, 166, 204, 152,¤/* 216 - 223 */
265682 ····211, 223, 212, 210, 245, 213, 145, 222,¤/* 224 - 231 */
8050c4 ····254, 218, 219, 217, 253, 221, 140, 180,¤/* 232 - 239 */
41f475 ····173, 177, 149, 190, 182, 167, 247, 148,¤/* 240 - 247 */
309b14 ····176, 168, 156, 185, 179, 178, 138, 160¤ /* 248 - 255 */
1682f7 };
96af5a
80f00b /* Conversion table from `latin1' charset to `ebcdic' charset.
2b1ecf ···Generated mechanically by GNU recode 3.4.
5baf5a
52805c ···The recoding should be reversible.
377fe0 */
62af5a
090273 static unsigned char const latin1_to_ebcdic[256] =
738bcc ··{
00d7ef ······0, ··1, ··2, ··3, ·55, ·45, ·46, ·47,¤/* ··0 - ··7 */
10edf7 ·····22, ··5, ·37, ·11, ·12, ·13, ·14, ·15,¤/* ··8 - ·15 */
8f2e3f ·····16, ·17, ·18, ·19, ·60, ·61, ·50, ·38,¤/* ·16 - ·23 */
063220 ·····24, ·25, ·63, ·39, ·28, ·29, ·30, ·31,¤/* ·24 - ·31 */
e3dd55 ·····64, ·79, 127, 123, ·91, 108, ·80, 125,¤/* ·32 - ·39 */
3d7a2f ·····77, ·93, ·92, ·78, 107, ·96, ·75, ·97,¤/* ·40 - ·47 */
24136d ····240, 241, 242, 243, 244, 245, 246, 247,¤/* ·48 - ·55 */
1676e2 ····248, 249, 122, ·94, ·76, 126, 110, 111,¤/* ·56 - ·63 */
040a56 ····124, 193, 194, 195, 196, 197, 198, 199,¤/* ·64 - ·71 */
3f551e ····200, 201, 209, 210, 211, 212, 213, 214,¤/* ·72 - ·79 */
80c9ab ····215, 216, 217, 226, 227, 228, 229, 230,¤/* ·80 - ·87 */
15152e ····231, 232, 233, ·74, 224, ·90, ·95, 109,¤/* ·88 - ·95 */
91a9f7 ····121, 129, 130, 131, 132, 133, 134, 135,¤/* ·96 - 103 */
93b2d0 ····136, 137, 145, 146, 147, 148, 149, 150,¤/* 104 - 111 */
--f412 000db07ea8c40100262 Page 3 of pgpCharMap.c
69f71b ····151, 152, 153, 162, 163, 164, 165, 166,¤/* 112 - 119 */
4e7a2a ····167, 168, 169, 192, 106, 208, 161, ··7,¤/* 120 - 127 */
28149d ·····32, ·33, ·34, ·35, ·36, ·21, ··6, ·23,¤/* 128 - 135 */
a6f3af ·····40, ·41, ·42, ·43, ·44, ··9, ·10, ·27,¤/* 136 - 143 */
bdb258 ·····48, ·49, ·26, ·51, ·52, ·53, ·54, ··8,¤/* 144 - 151 */
eda5cc ·····56, ·57, ·58, ·59, ··4, ·20, ·62, 225,¤/* 152 - 159 */
af2baa ·····65, ·66, ·67, ·68, ·69, ·70, ·71, ·72,¤/* 160 - 167 */
bb8153 ·····73, ·81, ·82, ·83, ·84, ·85, ·86, ·87,¤/* 168 - 175 */
278bc6 ·····88, ·89, ·98, ·99, 100, 101, 102, 103,¤/* 176 - 183 */
4201c0 ····104, 105, 112, 113, 114, 115, 116, 117,¤/* 184 - 191 */
7249e1 ····118, 119, 120, 128, 138, 139, 140, 141,¤/* 192 - 199 */
f61f2e ····142, 143, 144, 154, 155, 156, 157, 158,¤/* 200 - 207 */
eda0fd ····159, 160, 170, 171, 172, 173, 174, 175,¤/* 208 - 215 */
16b96b ····176, 177, 178, 179, 180, 181, 182, 183,¤/* 216 - 223 */
9d5083 ····184, 185, 186, 187, 188, 189, 190, 191,¤/* 224 - 231 */
33e2b9 ····202, 203, 204, 205, 206, 207, 218, 219,¤/* 232 - 239 */
398d61 ····220, 221, 222, 223, 234, 235, 236, 237,¤/* 240 - 247 */
e25740 ····238, 239, 250, 251, 252, 253, 254, 255,¤/* 248 - 255 */
34da12 ··};
baaf5a
c30697 /* Conversion table from `ebcdic' charset to `latin1' charset.
4d1ecf ···Generated mechanically by GNU recode 3.4.
c9af5a
03805c ···The recoding should be reversible.
b47fe0 */
d8af5a
dc849f static unsigned char const ebcdic_to_latin1[256] =
c98bcc ··{
0a5f0b ······0, ··1, ··2, ··3, 156, ··9, 134, 127,¤/* ··0 - ··7 */
b0cc59 ····151, 141, 142, ·11, ·12, ·13, ·14, ·15,¤/* ··8 - ·15 */
a4f302 ·····16, ·17, ·18, ·19, 157, 133, ··8, 135,¤/* ·16 - ·23 */
58caa9 ·····24, ·25, 146, 143, ·28, ·29, ·30, ·31,¤/* ·24 - ·31 */
a66a5b ····128, 129, 130, 131, 132, ·10, ·23, ·27,¤/* ·32 - ·39 */
b9b4e7 ····136, 137, 138, 139, 140, ··5, ··6, ··7,¤/* ·40 - ·47 */
fb80db ····144, 145, ·22, 147, 148, 149, 150, ··4,¤/* ·48 - ·55 */
b3c990 ····152, 153, 154, 155, ·20, ·21, 158, ·26,¤/* ·56 - ·63 */
a9aad1 ·····32, 160, 161, 162, 163, 164, 165, 166,¤/* ·64 - ·71 */
334d08 ····167, 168, ·91, ·46, ·60, ·40, ·43, ·33,¤/* ·72 - ·79 */
1516ef ·····38, 169, 170, 171, 172, 173, 174, 175,¤/* ·80 - ·87 */
06c3dd ····176, 177, ·93, ·36, ·42, ·41, ·59, ·94,¤/* ·88 - ·95 */
7c705c ·····45, ·47, 178, 179, 180, 181, 182, 183,¤/* ·96 - 103 */
c5728f ····184, 185, 124, ·44, ·37, ·95, ·62, ·63,¤/* 104 - 111 */
a4d578 ····186, 187, 188, 189, 190, 191, 192, 193,¤/* 112 - 119 */
03b6f6 ····194, ·96, ·58, ·35, ·64, ·39, ·61, ·34,¤/* 120 - 127 */
b0fd7e ····195, ·97, ·98, ·99, 100, 101, 102, 103,¤/* 128 - 135 */
9139ab ····104, 105, 196, 197, 198, 199, 200, 201,¤/* 136 - 143 */
b48afa ····202, 106, 107, 108, 109, 110, 111, 112,¤/* 144 - 151 */
ff42c8 ····113, 114, 203, 204, 205, 206, 207, 208,¤/* 152 - 159 */
c26a4b ····209, 126, 115, 116, 117, 118, 119, 120,¤/* 160 - 167 */
1d37ca ····121, 122, 210, 211, 212, 213, 214, 215,¤/* 168 - 175 */
8051dc ····216, 217, 218, 219, 220, 221, 222, 223,¤/* 176 - 183 */
c93080 ····224, 225, 226, 227, 228, 229, 230, 231,¤/* 184 - 191 */
462df5 ····123, ·65, ·66, ·67, ·68, ·69, ·70, ·71,¤/* 192 - 199 */
3de3fa ·····72, ·73, 232, 233, 234, 235, 236, 237,¤/* 200 - 207 */
c52b6a ····125, ·74, ·75, ·76, ·77, ·78, ·79, ·80,¤/* 208 - 215 */
4a7879 ·····81, ·82, 238, 239, 240, 241, 242, 243,¤/* 216 - 223 */
832970 ·····92, 159, ·83, ·84, ·85, ·86, ·87, ·88,¤/* 224 - 231 */
6b2e7a ·····89, ·90, 244, 245, 246, 247, 248, 249,¤/* 232 - 239 */
fee175 ·····48, ·49, ·50, ·51, ·52, ·53, ·54, ·55,¤/* 240 - 247 */
e690ca ·····56, ·57, 250, 251, 252, 253, 254, 255,¤/* 248 - 255 */
38da12 ··};
79af5a
79b2f2 /* Crude, non-invertible accent-dropping mapping from Latin1 to Ascii */
db7295 static unsigned char const latin1_to_ascii[256] =
ebbb36 {
432c4b ······0, ··1, ··2, ··3, ··4, ··5, ··6, ··7,¤/* ··0 - ··7 */
85d97c ······8, ··9, ·10, ·11, ·12, ·13, ·14, ·15,¤/* ··8 - ·15 */
5bea6e ·····16, ·17, ·18, ·19, ·20, ·21, ·22, ·23,¤/* ·16 - ·23 */
3584a8 ·····24, ·25, ·26, ·27, ·28, ·29, ·30, ·31,¤/* ·24 - ·31 */
5dbc87 ·····32, ·33, ·34, ·35, ·36, ·37, ·38, ·39,¤/* ·32 - ·39 */
512d89 ·····40, ·41, ·42, ·43, ·44, ·45, ·46, ·47,¤/* ·40 - ·47 */
dbec79 ·····48, ·49, ·50, ·51, ·52, ·53, ·54, ·55,¤/* ·48 - ·55 */
--002e 0002fe13a9e40100262 Page 4 of pgpCharMap.c
cfb90e ·····56, ·57, ·58, ·59, ·60, ·61, ·62, ·63,¤/* ·56 - ·63 */
1dd7c8 ·····64, ·65, ·66, ·67, ·68, ·69, ·70, ·71,¤/* ·64 - ·71 */
43efe7 ·····72, ·73, ·74, ·75, ·76, ·77, ·78, ·79,¤/* ·72 - ·79 */
1dd829 ·····80, ·81, ·82, ·83, ·84, ·85, ·86, ·87,¤/* ·80 - ·87 */
b819d9 ·····88, ·89, ·90, ·91, ·92, ·93, ·94, ·95,¤/* ·88 - ·95 */
a75d3a ·····96, ·97, ·98, ·99, 100, 101, 102, 103,¤/* ·96 - 103 */
0b7183 ····104, 105, 106, 107, 108, 109, 110, 111,¤/* 104 - 111 */
1849ac ····112, 113, 114, 115, 116, 117, 118, 119,¤/* 112 - 119 */
a18bc2 ····120, 121, 122, 123, 124, 125, 126, 127,¤/* 120 - 127 */
4638e5 /*
6914e6 ·* The high 128 characters:
b7cf15 ·* ·······dec ·oct hex ···ch ··ISO_8859-1:1987
d9495d ·*/
18edd1 ···0, /* ·128 ·200 ·80 ···PA ··padding character (pad) */
3001b0 ·'?', /* ·129 ·201 ·81 ···HO ··high octet preset (hop) */
895b28 ·'?', /* ·130 ·202 ·82 ···BH ··break permitted here (bph) */
754652 ·'?', /* ·131 ·203 ·83 ···NH ··no break here (nbh) */
240008 ·'?', /* ·132 ·204 ·84 ···IN ··index (ind) */
48a930 ·'?', /* ·133 ·205 ·85 ···NL ··next line (nel) */
715726 ·'?', /* ·134 ·206 ·86 ···SA ··start of selected area (ssa) */
ec394f ·'?', /* ·135 ·207 ·87 ···ES ··end of selected area (esa) */
f3cd45 ·'?', /* ·136 ·210 ·88 ···HS ··character tabulation set (hts) */
3164a7 ·'?', /* ·137 ·211 ·89 ···HJ ··character tabulation with justification (htj) */
c44975 ·'?', /* ·138 ·212 ·8a ···VS ··line tabulation set (vts) */
a73a79 ·'?', /* ·139 ·213 ·8b ···PD ··partial line forward (pld) */
b44665 ·'?', /* ·140 ·214 ·8c ···PU ··partial line backward (plu) */
934d6b ·'?', /* ·141 ·215 ·8d ···RI ··reverse line feed (ri) */
4108cb ·'?', /* ·142 ·216 ·8e ···S2 ··single-shift two (ss2) */
7ad306 ·'?', /* ·143 ·217 ·8f ···S3 ··single-shift three (ss3) */
7f58bf ·'?', /* ·144 ·220 ·90 ···DC ··device control string (dcs) */
8430de ·'?', /* ·145 ·221 ·91 ···P1 ··private use one (pu1) */
df8be6 ·'?', /* ·146 ·222 ·92 ···P2 ··private use two (pu2) */
94e2c8 ·'?', /* ·147 ·223 ·93 ···TS ··set transmit state (sts) */
745846 ·'?', /* ·148 ·224 ·94 ···CC ··cancel character (cch) */
bab713 ·'?', /* ·149 ·225 ·95 ···MW ··message waiting (mw) */
e8a0c5 ·'?', /* ·150 ·226 ·96 ···SG ··start of guarded area (spa) */
5c055b ·'?', /* ·151 ·227 ·97 ···EG ··end of guarded area (epa) */
cf9570 ·'?', /* ·152 ·230 ·98 ···SS ··start of string (sos) */
3f7bd8 ·'?', /* ·153 ·231 ·99 ···GC ··single graphic character introducer (sgci) */
31e265 ·'?', /* ·154 ·232 ·9a ···SC ··single character introducer (sci) */
082145 ·'?', /* ·155 ·233 ·9b ···CI ··control sequence introducer (csi) */
3d4f7c ·'?', /* ·156 ·234 ·9c ···ST ··string terminator (st) */
9de711 ·'?', /* ·157 ·235 ·9d ···OC ··operating system command (osc) */
e0bf7e ·'?', /* ·158 ·236 ·9e ···PM ··privacy message (pm) */
808efc ·'?', /* ·159 ·237 ·9f ···AC ··application program command (apc) */
e59be4 ·' ', /* ·160 ·240 ·a0 ···NS ··no-break space */
f5641f ·'!', /* ·161 ·241 ·a1 ···!I ··inverted exclamation mark */
b0dc9f ·'c', /* ·162 ·242 ·a2 ···Ct ··cent sign */
e46c06 ·'#', /* ·163 ·243 ·a3 ···Pd ··pound sign */
43c275 ·'$', /* ·164 ·244 ·a4 ···Cu ··currency sign */
74c79e ·'Y', /* ·165 ·245 ·a5 ···Ye ··yen sign */
f394e7 ·'|', /* ·166 ·246 ·a6 ···BB ··broken bar */
572952 ·'S', /* ·167 ·247 ·a7 ···SE ··section sign */
e14e31 ·'"', /* ·168 ·250 ·a8 ···': ··diaeresis */
1e7290 ·'C', /* ·169 ·251 ·a9 ···Co ··copyright sign */
f1dc66 ·'a', /* ·170 ·252 ·aa ···-a ··feminine ordinal indicator */
19c2a8 ·'<', /* ·171 ·253 ·ab ···<< ··left-pointing double angle quotation mark */
b7d406 ·'~', /* ·172 ·254 ·ac ···NO ··not sign */
d7fa44 ·'-', /* ·173 ·255 ·ad ···-- ··soft hyphen */
e083b7 ·'R', /* ·174 ·256 ·ae ···Rg ··registered sign */
c98353 ·'_', /* ·175 ·257 ·af ···'- ··overline */
de1f8c ·'o', /* ·176 ·260 ·b0 ···DG ··degree sign */
30d0a8 ·'?', /* ·177 ·261 ·b1 ···+- ··plus-minus sign */
2ed475 ·'2', /* ·178 ·262 ·b2 ···2S ··superscript two */
6ef340 ·'3', /* ·179 ·263 ·b3 ···3S ··superscript three */
f820c3 '\'', /* ·180 ·264 ·b4 ···'' ··acute accent */
f5b4e4 ·'u', /* ·181 ·265 ·b5 ···My ··micro sign */
afaf6e ·'P', /* ·182 ·266 ·b6 ···PI ··pilcrow sign */
aad489 ·'.', /* ·183 ·267 ·b7 ···.M ··middle dot */
60d88a ·',', /* ·184 ·270 ·b8 ···', ··cedilla */
80b1c4 ·'1', /* ·185 ·271 ·b9 ···1S ··superscript one */
2fe735 ·'o', /* ·186 ·272 ·ba ···-o ··masculine ordinal indicator */
--5024 000aedc0d2640100262 Page 5 of pgpCharMap.c
d52c7c ·'>', /* ·187 ·273 ·bb ···>> ··right-pointing double angle quotation mark */
5e9218 ·'?', /* ·188 ·274 ·bc ···14 ··vulgar fraction one quarter */
a01228 ·'?', /* ·189 ·275 ·bd ···12 ··vulgar fraction one half */
0d3a11 ·'?', /* ·190 ·276 ·be ···34 ··vulgar fraction three quarters */
8eeb55 ·'?', /* ·191 ·277 ·bf ···?I ··inverted question mark */
924f0f ·'A', /* ·192 ·300 ·c0 ···A! ··latin capital letter a with grave */
0ef91f ·'A', /* ·193 ·301 ·c1 ···A' ··latin capital letter a with acute */
4fb1b5 ·'A', /* ·194 ·302 ·c2 ···A> ··latin capital letter a with circumflex */
fa0948 ·'A', /* ·195 ·303 ·c3 ···A? ··latin capital letter a with tilde */
a57101 ·'A', /* ·196 ·304 ·c4 ···A: ··latin capital letter a with diaeresis */
33fd76 ·'A', /* ·197 ·305 ·c5 ···AA ··latin capital letter a with ring above */
107374 ·'E', /* ·198 ·306 ·c6 ···AE ··latin capital letter ae */
405337 ·'C', /* ·199 ·307 ·c7 ···C, ··latin capital letter c with cedilla */
68f788 ·'E', /* ·200 ·310 ·c8 ···E! ··latin capital letter e with grave */
054198 ·'E', /* ·201 ·311 ·c9 ···E' ··latin capital letter e with acute */
98f9a4 ·'E', /* ·202 ·312 ·ca ···E> ··latin capital letter e with circumflex */
6377b2 ·'E', /* ·203 ·313 ·cb ···E: ··latin capital letter e with diaeresis */
18662d ·'I', /* ·204 ·314 ·cc ···I! ··latin capital letter i with grave */
ebc7bf ·'I', /* ·205 ·315 ·cd ···I' ··latin capital letter i with acute */
9690e4 ·'I', /* ·206 ·316 ·ce ···I> ··latin capital letter i with circumflex */
2b6178 ·'I', /* ·207 ·317 ·cf ···I: ··latin capital letter i with diaeresis */
790294 ·'D', /* ·208 ·320 ·d0 ···D- ··latin capital letter eth (icelandic) */
f604d5 ·'N', /* ·209 ·321 ·d1 ···N? ··latin capital letter n with tilde */
e5284d ·'O', /* ·210 ·322 ·d2 ···O! ··latin capital letter o with grave */
379e5d ·'O', /* ·211 ·323 ·d3 ···O' ··latin capital letter o with acute */
8d9e3f ·'O', /* ·212 ·324 ·d4 ···O> ··latin capital letter o with circumflex */
84759b ·'O', /* ·213 ·325 ·d5 ···O? ··latin capital letter o with tilde */
5ed788 ·'O', /* ·214 ·326 ·d6 ···O: ··latin capital letter o with diaeresis */
7c5ac4 ·'x', /* ·215 ·327 ·d7 ···*X ··multiplication sign */
da6fd7 ·'O', /* ·216 ·330 ·d8 ···O/ ··latin capital letter o with stroke */
d76d92 ·'U', /* ·217 ·331 ·d9 ···U! ··latin capital letter u with grave */
f398fd ·'U', /* ·218 ·332 ·da ···U' ··latin capital letter u with acute */
f1bfdb ·'U', /* ·219 ·333 ·db ···U> ··latin capital letter u with circumflex */
4dd4f6 ·'U', /* ·220 ·334 ·dc ···U: ··latin capital letter u with diaeresis */
e0e0e4 ·'Y', /* ·221 ·335 ·dd ···Y' ··latin capital letter y with acute */
a4feb4 ·'T', /* ·222 ·336 ·de ···TH ··latin capital letter thorn (icelandic) */
2b0456 ·'s', /* ·223 ·337 ·df ···ss ··latin small letter sharp s (german) */
164372 ·'a', /* ·224 ·340 ·e0 ···a! ··latin small letter a with grave */
f1e2c4 ·'a', /* ·225 ·341 ·e1 ···a' ··latin small letter a with acute */
b4f12c ·'a', /* ·226 ·342 ·e2 ···a> ··latin small letter a with circumflex */
ce49d8 ·'a', /* ·227 ·343 ·e3 ···a? ··latin small letter a with tilde */
9ae5a1 ·'a', /* ·228 ·344 ·e4 ···a: ··latin small letter a with diaeresis */
86103b ·'a', /* ·229 ·345 ·e5 ···aa ··latin small letter a with ring above */
57d1f5 ·'e', /* ·230 ·346 ·e6 ···ae ··latin small letter ae */
7fa15c ·'e', /* ·231 ·347 ·e7 ···c, ··latin small letter c with cedilla */
790620 ·'e', /* ·232 ·350 ·e8 ···e! ··latin small letter e with grave */
faa796 ·'e', /* ·233 ·351 ·e9 ···e' ··latin small letter e with acute */
7a4856 ·'e', /* ·234 ·352 ·ea ···e> ··latin small letter e with circumflex */
97c7c6 ·'e', /* ·235 ·353 ·eb ···e: ··latin small letter e with diaeresis */
348718 ·'i', /* ·236 ·354 ·ec ···i! ··latin small letter i with grave */
169234 ·'i', /* ·237 ·355 ·ed ···i' ··latin small letter i with acute */
68efc4 ·'i', /* ·238 ·356 ·ee ···i> ··latin small letter i with circumflex */
774f44 ·'i', /* ·239 ·357 ·ef ···i: ··latin small letter i with diaeresis */
b2c3e1 ·'d', /* ·240 ·360 ·f0 ···d- ··latin small letter eth (icelandic) */
599e29 ·'n', /* ·241 ·361 ·f1 ···n? ··latin small letter n with tilde */
c18684 ·'o', /* ·242 ·362 ·f2 ···o! ··latin small letter o with grave */
0a2732 ·'o', /* ·243 ·363 ·f3 ···o' ··latin small letter o with acute */
93a200 ·'o', /* ·244 ·364 ·f4 ···o> ··latin small letter o with circumflex */
e073c4 ·'o', /* ·245 ·365 ·f5 ···o? ··latin small letter o with tilde */
407810 ·'o', /* ·246 ·366 ·f6 ···o: ··latin small letter o with diaeresis */
ba9ece ·'/', /* ·247 ·367 ·f7 ···-: ··division sign */
ee0b22 ·'o', /* ·248 ·370 ·f8 ···o/ ··latin small letter o with stroke */
0c69a2 ·'u', /* ·249 ·371 ·f9 ···u! ··latin small letter u with grave */
403eb6 ·'u', /* ·250 ·372 ·fa ···u' ··latin small letter u with acute */
63ecee ·'u', /* ·251 ·373 ·fb ···u> ··latin small letter u with circumflex */
daa7ab ·'u', /* ·252 ·374 ·fc ···u: ··latin small letter u with diaeresis */
e587eb ·'t', /* ·253 ·375 ·fd ···y' ··latin small letter y with acute */
330153 ·'t', /* ·254 ·376 ·fe ···th ··latin small letter thorn (icelandic) */
a26353 ·'y' ·/* ·255 ·377 ·ff ···y: ··latin small letter y with diaeresis */
ce82f7 };
c4af5a
ae95d7 /*·
--eda2 001b823625f40100262 Page 6 of pgpCharMap.c
ad3433 ·* Characters not recognized (mapped to '?'):
0662f4 ·* - Control characters 129-159
d12056 ·* - Plus-minus (Mapping to either + or - could be *very* misleading!)
e46cc0 ·* - Fractions 1/4, 1/2, 3/4
55775e ·*
d0020f ·* Differences from PGP 2.x's encoding:
62f2c3 ·* - 128 (pad) is mapped to 0 (nul), the usual pad character
f945cb ·* - << and >> are mapped to '<' and '>' instead of '"' and '"'
70fe90 ·* - Pilcrow (paragraph symbol) is mapped to 'P' rather than '-'
6674cf ·* - AE and ae are mapped to 'E' and 'e' rather than 'A' and 'a', based
b0f02f ·* ··on english conventions like encyclopaedia -> encyclopedia
1c495d ·*/
bf40df /* *INDENT-ON* */
124d6c /**********************************************************************/
7eaf5a
660609 /* Charset tables */
b79fcc static struct ConfMapping {
4a87ce ¤   char const *name;
ae6b6e ¤   unsigned char const *toLatin1, *toLocal;
9a3fb5 } confMappings[] = {
26e45d ¤   { "noconv",¤charMapIdentity,¤   charMapIdentity },
051e6f ¤   { "ascii",¤ charMapIdentity,¤   latin1_to_ascii },
002401 ¤   { "cp850",¤ cp850_to_latin1,¤   latin1_to_cp850 },
b7912d ¤   { "ebcdic",¤ebcdic_to_latin1,¤  latin1_to_ebcdic },
49ea79 ¤   { (char const *)0, 0, 0 }
f382f7 };
1faf5a
6b0cfc /* Case-insensitive memory compare */
08beb7 static int
f208d1 xmemicmp (char const *in1, char const *in2, int len)
fcbb36 {
4fcae5 ¤   while (len--) {
d81fb4 ¤   ¤   if (tolower(*in1) != tolower(*in2))
22db98 ¤   ¤   ¤   return 1;
a6beb3 ¤   ¤   in1++;
7fa37f ¤   ¤   in2++;
199371 ¤   }
c83e6b ¤   return 0;
9befe6 }
70af5a
91c77d PGPError
23811e pgpCharmaps (char const *charset, int setlen,
56faa4 ¤   ·····PGPByte const **toLocalP, PGPByte const **toLatin1P)
e4bb36 {
cc4ba4 ¤   int i;
4faf5a
e180e7 ¤   if (!charset || !toLocalP || !toLatin1P)
7562b5 ¤   ¤   return kPGPError_BadParams;
b7af5a
801a5e ¤   for (i=0; confMappings[i].name; i++) {
de4769 ¤   ¤   if ((size_t)setlen != strlen (confMappings[i].name) ||
120573 ¤   ¤   ····xmemicmp (charset, confMappings[i].name, setlen) != 0)
3617f5 ¤   ¤   ¤   continue;
80af5a
fb5d52 ¤   ¤   *toLocalP = confMappings[i].toLocal;
1482bb ¤   ¤   *toLatin1P = confMappings[i].toLatin1;
68b840 ¤   ¤   return kPGPError_NoErr;
e59371 ¤   }
136e42 ¤   return kPGPError_UnknownCharMap;
e4efe6 }
24af5a
4e314a void
44779f pgpCharmapConvert (PGPByte const *input, size_t inlen, PGPByte *output,
0b8166 ¤   ¤   ···PGPByte const *charmap)
fcbb36 {
4bba99 ¤   while (inlen--)
a333c2 ¤   ¤   output[inlen] = charmap[input[inlen]];
b8efe6 }
--e5e5 00164827c1a40100263 Page 1 of pgpCharMap.h
bc38e5 /*
fb9a04 ·* Charmap.h
ce775e ·*
49c49b ·* Mapping tables between different character sets.
98775e ·*
db5d84 ·* $Id: pgpCharMap.h,v 1.6 1997/06/25 19:41:05 lloyd Exp $
f4495d ·*/
62ab0b #ifndef Included_pgpCharMap_h
3eff3f #define Included_pgpCharMap_h
f9af5a
b6d11f #include "pgpUsuals.h"
40af5a
f399c6 PGP_BEGIN_C_DECLARATIONS
6aaf5a
30bd6d struct PGPEnv;
7baf5a
fb77b6 /* The identity charmap; maps all characters onto themselves */
192656 extern unsigned char const charMapIdentity[256];
c0af5a
2c38e5 /*
59c20d ·* Fills in the charmaps associated with the charset and returns 0
6f9186 ·* or returns a PGP error if the set isn't found or a paramter is
eb87ac ·* invalid.
d0495d ·*/
e42fec PGPError pgpCharmaps (char const *charset, int setlen,
5d9c74 ¤   ¤   ¤   ·PGPByte const **toLocal, PGPByte const **toLatin1);
9aaf5a
4e38e5 /*
023864 ·* Converts a string from one charset to another using the input
fbc365 ·* charmap. ·The input, of size inlen, is converted through the map
babdf6 ·* and put into output.
03495d ·*/
a3cf52 void pgpCharmapConvert (PGPByte const *input, size_t inlen, PGPByte *output,
d7acb5 ¤   ¤   ¤   PGPByte const *charmap);
d1af5a
72277b /* Two macros to convert strings between the local and latin1 charsets */
3d8cbd #define PGP_CONVERT_TO_LOCAL(in,len,out,env) \
bac4aa ¤   pgpCharmapConvert (in,len,out,\
a747fb ¤   ¤   pgpenvGetPointer (env, PGPENV_CHARMAPTOLOCAL,NULL))
90af5a
cd5822 #define PGP_CONVERT_TO_LATIN1(in,len,out,env) \
d9c4aa ¤   pgpCharmapConvert (in,len,out,\
d8d52b ¤   ¤   pgpenvGetPointer (env, PGPENV_CHARMAPTOLATIN1,NULL))
bcaf5a
491254 PGP_END_C_DECLARATIONS
c6af5a
64b14b #endif /* Included_pgpCharMap_h */
--d739 001943a312b40100264 Page 1 of pgpFIFO.c
bc38e5 /*
7a32ad ·* pgpFIFO.c -- This is just an abstraction on top of the bytefifo.
0aa372 ·* Yes, I am forcing the issue. ·I don't care, since the bytefifo
a29cd7 ·* is going to be there anyways, so I might as well put this code
0abe8c ·* here.
a2775e ·*
2d00c5 ·* $Id: pgpFIFO.c,v 1.4.22.1 1998/09/14 21:48:25 hal Exp $
dc495d ·*/
0daf5a
ffe2ff #include "pgpConfig.h"
f9af5a
bd83d5 #include "pgpByteFIFO.h"
96910a #include "pgpFIFO.h"
ebaf5a
8f80ee PGPFifoDesc const pgpByteFifoDesc = {
c6bc86 ¤   "Byte Fifo",
e1f030 ¤   byteFifoCreate,
48920f ¤   byteFifoRead,
988df7 ¤   byteFifoWrite,
4ba272 ¤   byteFifoPeek,
ccae0f ¤   byteFifoSeek,
52b7d7 ¤   byteFifoFlush,
ba2105 ¤   byteFifoDestroy,
9fdb53 ¤   byteFifoSize
a282f7 };
3faf5a
3669b2 PGPFifoDesc const pgpSecureByteFifoDesc = {
4fb727 ¤   "Secure Byte Fifo",
ad1ead ¤   byteFifoCreateSecure,
42920f ¤   byteFifoRead,
d78df7 ¤   byteFifoWrite,
dea272 ¤   byteFifoPeek,
beae0f ¤   byteFifoSeek,
10b7d7 ¤   byteFifoFlush,
8b2105 ¤   byteFifoDestroy,
eddb53 ¤   byteFifoSize
9482f7 };
--232e 001b542317d40100265 Page 1 of pgpFIFO.h
bc38e5 /*
3440db ·* pgpFIFO.h -- A general interface to a First-In First-Out system used
496233 ·* by PGP. ·There can be many FIFO implementations, and this is the
bf5a3b ·* interface that each must support.
b2775e ·*
922b44 ·* $Id: pgpFIFO.h,v 1.13.4.1 1998/09/14 21:48:29 hal Exp $
96495d ·*/
79af5a
3942ea #ifndef Included_pgpFIFO_h
d4269c #define Included_pgpFIFO_h
e1af5a
f4d11f #include "pgpUsuals.h"
c1af5a
8499c6 PGP_BEGIN_C_DECLARATIONS
5faf5a
c2adb8 #include "pgpOpaqueStructs.h"
1fe82c #include "pgpPubTypes.h"
986773 #include "pgpMemoryMgr.h"
feaf5a
bb10a9 struct PGPFifoDesc
60bb36 {
dea9a2 ¤   char const *¤   ¤   name;
85d87b ¤   PGPFifoContext *¤   (*create) ( PGPContextRef context );
daaf5a
92d2e2 ¤   PGPSize (*read)¤¤   (PGPFifoContext *fifo, PGPByte *buf, PGPSize len);
7eedbb ¤   PGPSize (*write)¤   (PGPFifoContext *fifo, PGPByte const *buf,
4ed381 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPSize len);
3eaf5a
88e413 ¤   PGPByte const *¤¤   (*peek) (PGPFifoContext *fifo, PGPSize *len);
c6f03e ¤   void (*seek)¤   ¤   (PGPFifoContext *fifo, PGPSize len);
cdaf5a
c9549b ¤   void (*flush)¤  ¤   (PGPFifoContext *fifo);
e2ef04 ¤   void (*destroy)¤¤   (PGPFifoContext *fifo);
f8af5a
e0d9f5 ¤   PGPSize¤¤   ¤   ¤   (*size)¤(PGPFifoContext const *fifo);
1f82f7 };
4aaf5a
e9af5a
15049b #define pgpFifoCreate(context, fd) (fd)->create( context )
bfd752 #define pgpFifoRead(fd,f,b,l) (fd)->read(f,b,l)
50e7b0 #define pgpFifoWrite(fd,f,b,l) (fd)->write(f,b,l)
539975 #define pgpFifoPeek(fd,f,l) (fd)->peek(f,l)
a3ee5e #define pgpFifoSeek(fd,f,l) (fd)->seek(f,l)
53dfe2 #define pgpFifoFlush(fd,f) (fd)->flush(f)
4d2f9c #define pgpFifoDestroy(fd,f) (fd)->destroy(f)
df0d2e #define pgpFifoSize(fd,f) (fd)->size(f)
afaf5a
8c1ee6 extern PGPFifoDesc const ·pgpByteFifoDesc;
d42d05 extern PGPFifoDesc const ·pgpSecureByteFifoDesc;
41a8bb extern PGPFifoDesc const ·pgpFileFifoDesc;
23f230 extern PGPFifoDesc const ·pgpFlexFifoDesc;
95af5a
a91254 PGP_END_C_DECLARATIONS
dcaf5a
b5c247 #endif /* Included_pgpFIFO_h */
--7514 0000703433440100266 Page 1 of pgpFile.c
bc38e5 /*
8b6547 ·* pgpFile.c -- An abstraction to files
83775e ·*
e77ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
77775e ·*
8a8c8b ·* $Id: pgpFile.c,v 1.27.4.1 1998/10/06 01:20:45 heller Exp $
88495d ·*/
e9af5a
45e2ff #include "pgpConfig.h"
faaf5a
1c495d #include <errno.h>
98feb2 #include <stdio.h>
900ccc #if PGP_MACINTOSH
0294b4 #include <unix.h>
4183f3 #include <stat.h>
b93b7a #include <unix.mac.h>¤  ¤   /* For fileno() */
6e7454 #endif
5aaf5a
36be68 #if HAVE_SYS_STAT_H
e1c382 #include <sys/types.h>¤ ¤   /* required for Ultrix */
b4d4f4 #include <sys/stat.h>
2c7454 #endif
4caf5a
5ba146 #include "pgpDebug.h"
c872de #include "pgpFile.h"
1e1e2d #include "pgpCFBPriv.h"
aa0d08 #include "pgpMem.h"
ed2f8d #include "pgpErrors.h"
bbc26c #include "pgpContext.h"
faaf5a
d35d59 struct File {
44f92c ¤   PGPError¤   (*doClose) (FILE *file, void *arg);
899920 ¤   void *¤ ¤   closeArg;
130606 ¤   PGPFileError err;
49cfbe ¤   PGPCFBContext *cfb;
30f6d5 ¤   FILE *f;
ae87a6 ¤   PGPError¤   error;
5d0033 ¤   int flags;
3b0ee6 ¤   long maybeSize;¤¤   /* Size or -1 if not a regular file, for sizeAdvise */
11489e ¤   DEBUG_STRUCT_CONSTRUCTOR( File )
a882f7 };
eb7e7c typedef struct File File;
9daf5a
6e38e5 /*
3594ff ·* These are the different flags, which define the various operations
ab9576 ·* * * and types.
98495d ·*/
fae773 #define FLAGS_READ¤ ¤   0x01
75c907 #define FLAGS_WRITE¤¤   0x02
2ab468 #define FLAGS_FILE¤ ¤   0x04
d6b471 #define FLAGS_PROC¤ ¤   0x08
5eac9a #define FLAGS_DONTCLOSE¤¤   0x10
64af5a
35efc6 #define PGP_FILE_READ¤  (FLAGS_FILE|FLAGS_READ)
3572be #define PGP_FILE_WRITE¤ (FLAGS_FILE|FLAGS_WRITE)
3cbd9c #define PGP_PROC_WRITE¤ (FLAGS_PROC|FLAGS_WRITE)
41af5a
f9979c /***************************************************/
7c0860 /* Stdio Functions */
2aaf5a
e12978 static void
ad4f1a setError (PGPFile *file, int code)
dcbb36 {
bf8974 ¤   File *fp = (File *)file->priv;
77af5a
22c45b ¤   fp->err.f = file;
943620 ¤   fp->err.syserrno = errno;
88e382 ¤   fp->err.error = (PGPError)code;
1c31ab ¤   fp->error = (PGPError)ferror (fp->f);
cdbcdd ¤   if (fp->error) {
6d8d62 ¤   ¤   fp->err.fpos = pgpFileTell (file);
079371 ¤   }
--44b8 0003fc7dbae40100266 Page 2 of pgpFile.c
7aefe6 }
46af5a
c45d09 static size_t
e0c3ac stdioRead (void *ptr, size_t size, PGPFile *file)
8ebb36 {
618974 ¤   File *fp = (File *)file->priv;
04d11b ¤   size_t ret;
baaf5a
44ae7d ¤   if (! (fp->flags & FLAGS_READ)) {
e534c5 ¤   ¤   setError (file, kPGPError_IllegalFileOp);
e5c90f ¤   ¤   fp->error = kPGPError_IllegalFileOp;
bbbbde ¤   ¤   return 0;
709371 ¤   }
46af5a
61d9f7 ¤   ret = fread (ptr, 1, size, fp->f);
64af5a
a50731 ¤   if (!ret)·
230dbb ¤   ¤   setError (file, kPGPError_FileOpFailed);
c1af5a
63986d ¤   return ret;
88efe6 }
4caf5a
0e5d09 static size_t
22471f stdioWrite (void const *ptr, size_t size, PGPFile *file)
23bb36 {
948974 ¤   File *fp = (File *)file->priv;
ecd11b ¤   size_t ret;
edaf5a
a31951 ¤   if (! (fp->flags & FLAGS_WRITE)) {
9986c6 ¤   ¤   setError (file, kPGPError_FileLocked);
875c0c ¤   ¤   fp->error = kPGPError_FileLocked;
4cbbde ¤   ¤   return 0;
169371 ¤   }
d4af5a
b2485c ¤   ret = fwrite (ptr, 1, size, fp->f);
2aaf5a
ff6713 ¤   if (!ret)
050dbb ¤   ¤   setError (file, kPGPError_FileOpFailed);
89af5a
67986d ¤   return ret;
08efe6 }
4daf5a
8df1ae static PGPError
f4ed08 stdioFlush (PGPFile *file)
ccbb36 {
638974 ¤   File *fp = (File *)file->priv;
5a72eb ¤   PGPError¤   ·ret;
b9af5a
06e47f ¤   if (! (fp->flags & FLAGS_WRITE))
e5ad5e ¤   ¤   return kPGPError_FileLocked;
15af5a
44c4c3 ¤   ret = (PGPError)fflush (fp->f);
4aaf5a
a50ccc #if PGP_MACINTOSH
ed6337 ¤   if (!ret) {
d13616 ¤   ¤   IOParam¤¤   pb;
99af5a
2cfddb ¤   ¤   pb.ioRefNum = fileno( fp->f );
60d8b6 ¤   ¤   ret = (PGPError)PBFlushFileSync( (ParamBlockRec *)&pb );
d69371 ¤   }
4c7454 #endif
ebaf5a
0d9d78 ¤   if (ret) {
988092 ¤   ¤   ret = kPGPError_FileOpFailed;
eb2889 ¤   ¤   setError (file, ret);
716fca ¤   ¤   fp->error = ret;
d59371 ¤   }
3faf5a
6c986d ¤   return ret;
55efe6 }
eaaf5a
3f77fd static long
--a59a 000d0036eee40100266 Page 3 of pgpFile.c
52d9a1 stdioTell (PGPFile *file)
dbbb36 {
378974 ¤   File *fp = (File *)file->priv;
efaf5a
3d6577 ¤   return ftell (fp->f);
36efe6 }
d1af5a
5bf1ae static PGPError
696aa0 stdioSeek (PGPFile *file, long offset, int whence)
25bb36 {
c78974 ¤   File *fp = (File *)file->priv;
ff8929 ¤   PGPError code;
b8af5a
bbeded ¤   if (! (fp->flags & FLAGS_READ))
a89a84 ¤   ¤   return kPGPError_IllegalFileOp;
17af5a
2f08e0 ¤   code = (PGPError)fseek (fp->f, offset, whence);
a6af5a
ab2d00 ¤   if (code) {
537ea7 ¤   ¤   code = kPGPError_FileOpFailed;
221f3d ¤   ¤   setError (file, code);
583373 ¤   ¤   fp->error = code;
cf9371 ¤   }
cbaf5a
05e231 ¤   return code;
daefe6 }
ddaf5a
253bfb /**********************************************************/
4eb22e /* Non-specific functions (stdio or encrypted) */
35af5a
97f1ae static PGPError
1066d9 fileClose (PGPFile *file)
abbb36 {
0e8974 ¤   File *fp = (File *)file->priv;
89328c ¤   PGPError code = kPGPError_NoErr;
15af5a
43c8f4 ¤   pgpAssertAddrValid( file, PGPFile );
84af5a
1fdc5e ¤   if ((fp->flags & FLAGS_FILE) && !(fp->flags & FLAGS_DONTCLOSE))
e07c62 ¤   ¤   code = (PGPError)fclose (fp->f);
e37e84 ¤   else if (fp->flags & FLAGS_PROC) {
78fab6 ¤   ¤   if (fp->doClose)
3c832c ¤   ¤   ¤   code = (PGPError)fp->doClose (fp->f, fp->closeArg);
73f998 ¤   ¤   /* We may not be able to 'close' here.. I hope that is ok */
509371 ¤   }
4caf5a
182d00 ¤   if (code) {
e37ea7 ¤   ¤   code = kPGPError_FileOpFailed;
f65541 ¤   ¤   setError (file, (PGPError)code);
83f0b6 ¤   ¤   fp->error = (PGPError)code;
bda3ba ¤   ¤   return code;
cd9371 ¤   }
f5af5a
331ca9 ¤   if (fp->cfb)
442cb5 ¤   ¤   PGPFreeCFBContext(fp->cfb);
f6af5a
01a03b ¤   pgpClearMemory( fp, ·sizeof (*fp));
1fe696 ¤   PGPFreeData( fp);
ce6cce ¤   pgpClearMemory( file, ·sizeof (*file));
a5255b ¤   PGPFreeData( file);
88af5a
74e231 ¤   return code;
0befe6 }
7faf5a
2256b6 static PGPBoolean
39e9e2 fileEof (PGPFile const *file)
b3bb36 {
fc8974 ¤   File *fp = (File *)file->priv;
e5af5a
c46834 ¤   return feof (fp->f);
63efe6 }
d0af5a
--eb35 0006b4379d940100266 Page 4 of pgpFile.c
4b77fd static long
8f8d9c fileSizeAdvise (PGPFile const *file)
dabb36 {
a98974 ¤   File *fp = (File *)file->priv;
18af5a
a7f9da ¤   return fp->maybeSize;
beefe6 }
58af5a
74d6a2 static PGPFileError const *
e02bdf fileError (PGPFile const *file)
f5bb36 {
c88974 ¤   File *fp = (File *)file->priv;
c9af5a
b65cdd ¤   if (fp->error)
621de8 ¤   ¤   return &(fp->err);
69af5a
fc3f59 ¤   return NULL;
5cefe6 }
f7af5a
a32978 static void
48f01d fileClearError (PGPFile *file)
c7bb36 {
df8974 ¤   File *fp = (File *)file->priv;
6baf5a
29d397 ¤   clearerr (fp->f);
9543a9 ¤   fp->error = kPGPError_NoErr;
c1efe6 }
e5af5a
d33625 /* Converts a writing file to a reading file */
4ef1ae static PGPError
d9a48e fileWrite2read (PGPFile *file)
6ebb36 {
078974 ¤   File *fp = (File *)file->priv;
6caf5a
c4e766 ¤   if ((fp->flags & PGP_FILE_WRITE) != PGP_FILE_WRITE)
70ad5e ¤   ¤   return kPGPError_FileLocked;
38af5a
0f32f8 ¤   fp->flags &= ~FLAGS_READ;
137191 ¤   fp->flags |= FLAGS_WRITE;
7eaf5a
b675d0 ¤   /* XXX -- should I rewind this file? */
1ad8b5 ¤   /* return pgpFileSeek (file, 0, SEEK_SET); */
08151e ¤   return kPGPError_NoErr;
87efe6 }
27af5a
dafc7b /* Creates a new PGPCFBContext and returns it.
cc3698 ·Returns NULL otherwise */
c1dd24 static PGPCFBContextRef
ad1482 fileCfb (PGPFile const *file)
4abb36 {
458974 ¤   File *fp = (File *)file->priv;
33af5a
3c61e7 ¤   if ( IsntNull( fp->cfb ))
4bc7a1 ¤   {
9a7b7d ¤   ¤   PGPCFBContextRef¤   newRef;
05cf44 ¤   ¤   PGPError¤   ¤   err;
da1b52 ¤   ¤
5b9286 ¤   ¤   err¤= PGPCopyCFBContext( fp->cfb, &newRef );
b7b5c2 ¤   ¤   return( newRef );
ed9371 ¤   }
4aaf5a
5a3f59 ¤   return NULL;
6eefe6 }
57af5a
5a217f /*************************************************************/
79d9cd /* Open functions */
f5af5a
cb7c9e /* take a FILE* and convert it to a PGPFile* */
fe381a static PGPFile *
dbf249 doOpen(
6c3163 ¤   PGPContextRef¤  cdkContext,
6ba752 ¤   FILE *file, int fflags)
--c5d5 000405b3a5740100266 Page 5 of pgpFile.c
2cbb36 {
67c586 ¤   PGPFile *fp;
a80e2d ¤   File *ffp;
2f9e7e ¤   struct stat buf;
dcc3f1 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
9eaf5a
8724fc ¤   if (!file)
a07ed2 ¤   ¤   return NULL;
00af5a
a62519 ¤   fp = (PGPFile *)PGPNewData( memoryMgr,
9cb0e9 ¤   ¤   sizeof (*fp), kPGPMemoryMgrFlags_Clear);
40485d ¤   if (!fp)
697ed2 ¤   ¤   return NULL;
a3dced ¤   fp->context¤¤   = cdkContext;
922cc8 ¤   fp->dataType ¤  = kPGPFileDataType_Unknown;
53af5a
15beaa ¤   ffp = (File *)PGPNewData( memoryMgr,
790a44 ¤   ¤   sizeof (*ffp), kPGPMemoryMgrFlags_Clear);
5f98e5 ¤   if (!ffp) {
7adad6 ¤   ¤   PGPFreeData( fp );
b37ed2 ¤   ¤   return NULL;
b89371 ¤   }
f3af5a
9a744e ¤   if (fstat (fileno (file), &buf) == 0 &&
4a6f16 ¤   ¤   ¤   (S_IFMT & buf.st_mode) == S_IFREG)
e24a9d ¤   ¤   ffp->maybeSize = buf.st_size;
570e24 ¤   else
e21787 ¤   ¤   ffp->maybeSize = -1;
0267c5 ¤
c9504a ¤   rewind (file);
84e5cb ¤   ffp->f = file;
486c8d ¤   ffp->flags = fflags;
26af5a
798a6c ¤   fp->priv = ffp;
141300 ¤   fp->read = stdioRead;
d3e371 ¤   fp->write = stdioWrite;
4d5ace ¤   fp->flush = stdioFlush;
81e7ea ¤   fp->close = fileClose;
11e303 ¤   fp->tell = stdioTell;
3f5e30 ¤   fp->seek = stdioSeek;
f1d7e5 ¤   fp->eof = fileEof;
c1a5e3 ¤   fp->sizeAdvise = fileSizeAdvise;
327a96 ¤   fp->error = fileError;
dd9212 ¤   fp->clearError = fileClearError;
a7a139 ¤   fp->write2read = fileWrite2read;
7f49af ¤   fp->cfb = fileCfb;
19af5a
7f6c97 ¤   return fp;
2defe6 }
97af5a
d7de83 /* Convert a FILE* to PGPFile* in Write Mode */
fcdc3a PGPFile *
1be8e2 pgpFileWriteOpen (PGPContextRef¤cdkContext,
b6fbbb ¤   FILE *file, PGPCFBContext *cfbp)
9bbb36 {
c7ec46 ¤   (void)cfbp;¤¤   /* Avoid warning */
ef848b ¤   pgpAssert (cfbp == NULL);
6890f0 ¤   return doOpen ( cdkContext, file, PGP_FILE_WRITE);
94a79b }·
41af5a
f9d51a /* Same as above, but don't close the FILE automatically */
aedc3a PGPFile *
1831a1 pgpFileWriteOpenDontClose (PGPContextRef context,
fdfbbb ¤   FILE *file, PGPCFBContext *cfbp)
5fbb36 {
40ec46 ¤   (void)cfbp;¤¤   /* Avoid warning */
f1848b ¤   pgpAssert (cfbp == NULL);
e6d5b4 ¤   return doOpen ( context,
27333a ¤   ¤   ¤   file, PGP_FILE_WRITE | FLAGS_DONTCLOSE);
88a79b }·
7daf5a
402880 /* Convert a FILE* to PGPFile* in Read Mode */
--8fba 0017471f80b40100266 Page 6 of pgpFile.c
b9dc3a PGPFile *
ca15e5 pgpFileReadOpen ( PGPContextRef context,
506370 ¤   FILE *file, PGPUICb const *ui, void *ui_arg)
77bb36 {
e752f9 ¤   (void)ui;
b9de7a ¤   (void)ui_arg;
0dd8af ¤   /*
67e9dd ¤   ·* We still need to check the file for encryption and obtain
8b8d09 ¤   ·* the decryption key, somehow.
d8a4e3 ¤   ·*/
2eaf5a
cc87b2 ¤   return doOpen ( context, file, PGP_FILE_READ);
63efe6 }
dbaf5a
ecdc3a PGPFile *
8ae4a8 pgpFileProcWriteOpen ( ¤PGPContextRef context,
cdbe88 ¤   FILE *file, PGPError (*doClose) (FILE *file, void *arg),
2aed91 ¤   ¤   ······void *arg)
5abb36 {
e0c586 ¤   PGPFile *fp;
dfa6c6 ¤   File *f;
d8af5a
c0a43c ¤   fp = doOpen ( context, file, PGP_PROC_WRITE);
4af563 ¤   f = (File *)fp->priv;
553457 ¤   pgpAssert (f);
6caf5a
521fcf ¤   f->doClose = doClose;
18261e ¤   f->closeArg = arg;
806c97 ¤   return fp;
c2efe6 }
8baf5a
42af5a
90af5a
c0af5a
74af5a
--60b4 00042c0a39b40100267 Page 1 of pgpFile.h
bc38e5 /*
7ea7c1 ·* pgpFile.h -- an abstraction to files
15775e ·*
955a45 ·* Written By:¤ Derek Atkins <warlord@MIT.EDU>
e7775e ·*
fd7553 ·* $Id: pgpFile.h,v 1.19.4.1 1998/10/06 01:20:46 heller Exp $
2e495d ·*/
19af5a
d3b84e #ifndef Included_pgpFile_h
10dc38 #define Included_pgpFile_h
a9af5a
74feb2 #include <stdio.h>
59af5a
86675a #include "pgpTypes.h"
5e4919 #include "pgpUtilities.h"
83af5a
6a99c6 PGP_BEGIN_C_DECLARATIONS
00af5a
c0adb8 #include "pgpOpaqueStructs.h"
89af5a
2f54ea struct PGPFileError {
03b0bd ¤   PGPFile *¤  f;¤ /* The PGPFile for I/O Errors */
8740b0 ¤   long¤   ¤   fpos;¤  ¤   /* file position */
a3dca1 ¤   PGPError¤   error;¤ ¤   /* PGP error code (kPGPError_*) */
ce8c8b ¤   int¤¤   ¤   syserrno;¤  /* don't use errno; that's a macro! */
1f82f7 };
52af5a
0faf5a
025939 enum PGPFileDataType_
9abb36 {
8605ed ¤   kPGPFileDataType_Unknown¤   = 0,
05e542 ¤   kPGPFileDataType_ASCII,
eab030 ¤   kPGPFileDataType_Binary,
a967c5 ¤
2f27e6 ¤   PGP_ENUM_FORCE( PGPFileDataType )
302fa1 } ;
d59d6c PGPENUM_TYPEDEF( PGPFileDataType_, PGPFileDataType );
75af5a
1c4737 struct PGPFile {
058a97 ¤   PGPContextRef¤  context;
1c65bd ¤   PGPFileDataType¤dataType;
0a67c5 ¤
67e041 ¤   void *priv;
c324b3 ¤   size_t (*read) (void *ptr, size_t size, PGPFile *file);
c5033a ¤   size_t (*write) (void const *ptr, size_t size, PGPFile *file);
a1cb4d ¤   PGPError (*flush) (PGPFile *file);
bc788f ¤   PGPError (*close) (PGPFile *file);
270697 ¤   long (*tell) (PGPFile *file);
86a03a ¤   PGPError (*seek) (PGPFile *file, long offset, int whence);
186b0e ¤   PGPBoolean (*eof) (PGPFile const *file);
14a0a4 ¤   long (*sizeAdvise) (PGPFile const *file);
2ec0b0 ¤   PGPFileError const * (*error) (PGPFile const *file);
cc9c19 ¤   void (*clearError) (PGPFile *file);
c48e40 ¤   PGPError (*write2read) (PGPFile *file);
3d5bca ¤   PGPCFBContext * (*cfb) (PGPFile const *file);
0482f7 };
02af5a
10af5a
565fa8 PGPFile ·*pgpFileReadOpen ( PGPContextRef context, FILE *file,
1f6cd4 ¤   PGPUICb const *ui, void *ui_arg);
ed13fb PGPFile ·*pgpFileWriteOpen (PGPContextRef context, FILE *file,
e86c37 ¤   PGPCFBContext *cfb);
c7af5a
57aaa1 PGPFile ·*pgpFileProcWriteOpen ( PGPContextRef context, FILE *file,
766aa6 ¤   ¤   ¤   ¤   ······PGPError (*doClose) (FILE *file, void *arg),
5b3b91 ¤   ¤   ¤   ¤   ······void *arg);
00af5a
76d51a /* Same as above, but don't close the FILE automatically */
5ded4c PGPFile *pgpFileWriteOpenDontClose (PGPContextRef context,
f90b83 ¤   FILE *file, PGPCFBContext *cfbp);
27af5a
429587 PGPFile ·*pgpFilePipelineOpen (PGPPipeline *head);
--d96c 00140830c4d40100267 Page 2 of pgpFile.h
e0af5a
1463b1 PGPFile ·*pgpFileMemOpen ( PGPContextRef¤   context,
11aee8 ¤   ¤   ¤   void *base, size_t len);
f4af5a
081254 PGP_END_C_DECLARATIONS
09af5a
a285d0 #define pgpFileRead(p,s,f) (f)->read(p,s,f)
a9053f #define pgpFileWrite(p,s,f) (f)->write(p,s,f)
bde45c #define pgpFileFlush(f) (f)->flush(f)
67cf78 #define pgpFileClose(f) (f)->close(f)
dad863 #define pgpFileTell(f) (f)->tell(f)
41589e #define pgpFileSeek(f,o,w) (f)->seek(f,o,w)
cbd1ff #define pgpFileEof(f) (f)->eof(f)
cbba02 #define pgpFileSizeAdvise(f) (f)->sizeAdvise(f)
4f9168 #define pgpFileError(f) (f)->error(f)
622b06 #define pgpFileClearError(f) (f)->clearError(f)
acceb2 #define pgpFileWrite2Read(f) (f)->write2read(f)
b7b540 #define pgpFileCfb(f) (f)->cfb(f)
7daf5a
402f89 #endif /* Included_pgpFile_h */
--b162 00064ac282d40100268 Page 1 of pgpFileFIFO.c
bc38e5 /*
ec7beb ·* pgpFileFIFO.c
102b50 ·* Use a disk file as a fifo.
ea775e ·*
72c242 ·* File grows indefinitely until fifo empties, at which pointers reset
20a813 ·* to the beginning. ·(File never shrinks though.)
6475c6 ·* So file size will be the maximum of the number of bytes written since
74d299 ·* the previous time the fifo was empty.
1e775e ·*
5ee422 ·* $Id: pgpFileFIFO.c,v 1.39 1997/12/11 23:13:53 lloyd Exp $
5b495d ·*/
ebaf5a
75e2ff #include "pgpConfig.h"
a3af5a
2a7df1 #include <stdio.h>¤ /* For BUFSIZ */
c3af5a
e6a146 #include "pgpDebug.h"
791e2d #include "pgpCFBPriv.h"
130e2f #include "pgpSymmetricCipherPriv.h"
68910a #include "pgpFIFO.h"
bd0d08 #include "pgpMem.h"
02d11f #include "pgpUsuals.h"
7e2f8d #include "pgpErrors.h"
ce2c96 #include "pgpRandomX9_17.h"
dba4b2 #include "pgpFileRef.h"
80894b #include "pgpFileSpec.h"
acc26c #include "pgpContext.h"
d6af5a
52ec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
75a1d8 #define kPGPFIFOBufSize¤¤   16384
afdb21 #else
1e01d6 #define kPGPFIFOBufSize¤¤   BUFSIZ
3a7454 #endif
25af5a
7473dd /* Use this cipher for encrypting data to disk. ·*/
12ace2 #define DEFAULTCIPHER¤  ¤   kPGPCipherAlgorithm_CAST5
25af5a
c238e5 /*
22d116 ·* putoff is offset in file where next written byte will go
6f8b01 ·* getoff is offset in file where next read byte will come from
82c6e6 ·* peekoff-getoff is # bytes in buf we have read and decrypted
f1495d ·*/
98aeff struct PGPFifoContext {
a78a97 ¤   PGPContextRef¤  context;
45f6d5 ¤   FILE *f;
b60392 ¤   PFLFileSpecRef¤ fileRef;
ccd259 ¤   PGPByte *buf;
89a7af ¤   PGPSize¤ putoff, getoff, peekoff;
8d8a2e ¤   PGPCFBContext *rdcfb, *wrcfb;
5ab44f ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPFifoContext )
1d82f7 };
d3af5a
232978 static void
021e0d fileFifoFlush(PGPFifoContext *fifo)
87bb36 {
99fcc8 ¤   fifo->putoff = 0;
9d1acd ¤   fifo->getoff = 0;
e133a8 ¤   fifo->peekoff = 0;
bcefe6 }
99af5a
4e598d static PGPSize
090a57 fileFifoSize(PGPFifoContext const *fifo)
20bb36 {
e4cfc5 ¤   return (PGPSize)(fifo->putoff - fifo->getoff);
f4efe6 }
27af5a
162978 static void
4004db fileFifoFreeCfbs(PGPFifoContext *fifo)
34bb36 {
0a5c71 ¤   PGPFreeCFBContext(fifo->rdcfb);
572614 ¤   PGPFreeCFBContext(fifo->wrcfb);
64efe6 }
--6a79 000093f68ed40100268 Page 2 of pgpFileFIFO.c
e0af5a
4a3aac /* Return negative on error, 0 on success */
d8beb7 static int
2987de fileFifoInitCfbs(PGPFifoContext *fifo)
19bb36 {
f76743 ¤   PGPRandomContext *rc;
7608c6 ¤   PGPCipherVTBL const *cipher;
9f88eb ¤   PGPSize cfbkeysize;
c9402b ¤   PGPByte *cfbkey;
c3d758 ¤   PGPByte cfbiv[PGP_CFB_MAXBLOCKSIZE];
d48a97 ¤   PGPContextRef¤  context;
b29372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
f167c5 ¤
51cb62 ¤   pgpAssertAddrValid( fifo, PGPFifoContext );
7d993d ¤   context¤= fifo->context;
b5af5a
8d1cbe ¤   /* XXX Interface doesn't provide env to choose dflt cipher */
c95c01 ¤   cipher = pgpCipherGetVTBL(DEFAULTCIPHER);
a2e060 ¤   if (!cipher) {
3edffa ¤   ¤   return kPGPError_FeatureNotAvailable;
f89371 ¤   }
1877ca ¤   cfbkeysize = cipher->keysize;
e534ca ¤   cfbkey = (PGPByte *)pgpContextMemAlloc( context,
4a19dd ¤   ¤   cfbkeysize, 0);
c5d14f ¤   if (!cfbkey)
c05b34 ¤   ¤   {
484030 ¤   ¤   return kPGPError_OutOfMemory;
689371 ¤   }
82baea ¤   rc = pgpRandomCreate( context );
594292 ¤   pgpAssert(rc);
0b98d6 ¤   pgpRandomGetBytes(rc, cfbkey, cfbkeysize);
f29961 ¤   pgpRandomGetBytes(rc, cfbiv, sizeof(cfbiv));
4d8657 ¤   pgpRandomDestroy(rc);
05abaf ¤   fifo->rdcfb = pgpCFBCreate( PGPGetContextMemoryMgr( context ), cipher);
b06028 ¤   PGPInitCFB(fifo->rdcfb, cfbkey, cfbiv);
b6986c ¤   pgpClearMemory(cfbkey, cfbkeysize);
c25e7f ¤   pgpClearMemory(cfbiv, sizeof(cfbiv));
52d39d ¤   pgpContextMemFree( context, cfbkey);
fdaf5a
3f8800 ¤   err¤= PGPCopyCFBContext( fifo->rdcfb, &fifo->wrcfb );
ed40ac ¤   if ( IsPGPError( err ) ) {
ea2120 ¤   ¤   fileFifoFreeCfbs(fifo);
ffc9db ¤   ¤   return err;
6f9371 ¤   }
502d68 ¤   return( kPGPError_NoErr );
e9efe6 }
dbaf5a
a2859e static PGPFifoContext *
7bcde1 fileFifoCreate( PGPContextRef¤  context )
f2bb36 {
483566 ¤   PGPFifoContext *fifo;
cf0040 ¤   PGPError err;
b7af5a
328e1c ¤   fifo = (PGPFifoContext *)pgpContextMemAlloc(
31044e ¤   ¤   ¤   context, sizeof(*fifo), 0);
808b28 ¤   if (!fifo)
9c7ed2 ¤   ¤   return NULL;
c13700 ¤   fifo->context¤  = context;
3a67c5 ¤
f96cda ¤   fifo->buf = (PGPByte *)pgpContextMemAlloc( context,
321669 ¤   ¤   ¤   kPGPFIFOBufSize, 0);
8c47f5 ¤   if (!fifo->buf) {
531d92 ¤   ¤   pgpContextMemFree( context, fifo);
087ed2 ¤   ¤   return NULL;
1c9371 ¤   }
523700 ¤   fifo->context¤  = context;
b967c5 ¤
399c6a ¤   if (fileFifoInitCfbs(fifo) < 0) {
9ba38b ¤   ¤   pgpContextMemFree( context, fifo->buf);
ed1d92 ¤   ¤   pgpContextMemFree( context, fifo);
727ed2 ¤   ¤   return NULL;
099371 ¤   }
--ec06 000e9e5c19340100268 Page 3 of pgpFileFIFO.c
64dc56 ¤   fifo->f = pgpStdIOOpenTempFile( context, &fifo->fileRef, &err);
183bd6 ¤   if (!fifo->f) {
e72120 ¤   ¤   fileFifoFreeCfbs(fifo);
43999e ¤   ¤   pgpContextMemFree(context, fifo->buf);
2eb932 ¤   ¤   pgpContextMemFree(context, fifo);
b27ed2 ¤   ¤   return NULL;
7c9371 ¤   }
64fcc8 ¤   fifo->putoff = 0;
d61acd ¤   fifo->getoff = 0;
d233a8 ¤   fifo->peekoff = 0;
e91b52 ¤   ¤
8c8722 ¤   return fifo;
3aefe6 }
8eaf5a
8c2978 static void
79f9d3 fileFifoDestroy(PGPFifoContext *fifo)
efbb36 {
e15231 ¤   fclose(fifo->f);
1cae06 ¤   if (fifo->fileRef != NULL)
b1c7a1 ¤   {
082ae5 ¤   ¤   PFLFileSpecDelete(fifo->fileRef);
e90481 ¤   ¤   PFLFreeFileSpec(fifo->fileRef);
139371 ¤   }
488c7e ¤   fileFifoFreeCfbs(fifo);
c4cccd ¤   pgpClearMemory(fifo->buf, kPGPFIFOBufSize);
086f68 ¤   pgpContextMemFree( fifo->context, fifo->buf);
00041f ¤   pgpContextMemFree( fifo->context, fifo);
21efe6 }
60af5a
f7af5a
46afee /* This could definitely use some optimizing */
fd5abf static PGPByte const *
32d9a1 fileFifoPeek(PGPFifoContext *fifo, PGPSize *len)
3ebb36 {
585a7a ¤   PGPSize dsklen;
38af5a
e87e1d ¤   if (fifo->putoff == fifo->getoff) {
915afc ¤   ¤   *len = 0;
b27ed2 ¤   ¤   return NULL;
2a9371 ¤   }
a6af5a
2cbe68 ¤   if (fifo->peekoff > fifo->getoff) {
856b9e ¤   ¤   /* Have peeked data in buffer already */
86c0d5 ¤   ¤   *len = fifo->peekoff - fifo->getoff;
c55c76 ¤   ¤   return fifo->buf;
f29371 ¤   }
79af5a
940051 ¤   if (fifo->putoff - fifo->getoff > kPGPFIFOBufSize)
4b847a ¤   ¤   dsklen = kPGPFIFOBufSize;
460e24 ¤   else
dbfdb3 ¤   ¤   dsklen = (PGPSize)(fifo->putoff - fifo->getoff);
b2af5a
b27cda ¤   if (fseek(fifo->f, fifo->getoff, SEEK_SET) != 0) {
825afc ¤   ¤   *len = 0;
a17ed2 ¤   ¤   return NULL;
5f9371 ¤   }
c8af5a
eb403b ¤   if (fread(fifo->buf, 1, dsklen, fifo->f) != dsklen) {
c55afc ¤   ¤   *len = 0;
9d7ed2 ¤   ¤   return NULL;
2c9371 ¤   }
1faf5a
37128c ¤   PGPCFBDecrypt(fifo->rdcfb, fifo->buf, dsklen, fifo->buf);
a9e1f8 ¤   fifo->peekoff = fifo->getoff + dsklen;
31af5a
02a1d6 ¤   *len = dsklen;
359bc3 ¤   return fifo->buf;
82efe6 }
49af5a
562978 static void
b774e3 fileFifoSeek(PGPFifoContext *fifo, PGPSize len)
e9bb36 {
--514e 000f5d273a540100268 Page 4 of pgpFileFIFO.c
074404 ¤   if (!len)
2f99bf ¤   ¤   return;
adaf5a
e74a06 ¤   pgpAssert(fifo->putoff - fifo->getoff >= (PGPSize)len);
a3e3e4 ¤   pgpAssert(fifo->peekoff - fifo->getoff >= (PGPSize)len);
e7e173 ¤   pgpAssert(fifo->putoff >= fifo->peekoff);
c1af5a
dd845e ¤   fifo->getoff += len;
7b3a4e ¤   if (fifo->getoff < fifo->peekoff) {
0a2a27 ¤   ¤   /* Move data in fifo down */
3d94f2 ¤   ¤   pgpCopyMemory(fifo->buf+len, fifo->buf, fifo->peekoff-fifo->getoff);
579371 ¤   }
80af5a
a50fd5 ¤   /* If fifo becomes empty, reset pointers to beginning of file */
f08e86 ¤   if (fifo->putoff == fifo->getoff)
7ea6af ¤   ¤   fifo->putoff = fifo->getoff = fifo->peekoff = 0;
a6efe6 }
06af5a
2d5d09 static size_t
46bde4 fileFifoWrite(PGPFifoContext *fifo, PGPByte const *buf, size_t len)
2ebb36 {
81f5d0 ¤   size_t lenleft;
c1c822 ¤   size_t buflen;
7caf5a
ebe187 ¤   if (fseek(fifo->f, fifo->putoff, SEEK_SET) != 0)
291a9d ¤   ¤   return kPGPError_FileOpFailed;
f25162 ¤   lenleft = len;
c443ee ¤   while (lenleft) {
b90390 ¤   ¤   buflen = (lenleft < kPGPFIFOBufSize) ? lenleft : kPGPFIFOBufSize;
5713a1 ¤   ¤   PGPCFBEncrypt(fifo->wrcfb, buf, buflen, fifo->buf);
d43b2b ¤   ¤   if (fwrite(fifo->buf, 1, buflen, fifo->f) != buflen)
94d165 ¤   ¤   ¤   return kPGPError_WriteFailed;
4a71ad ¤   ¤   buf += buflen;
f6c4e0 ¤   ¤   lenleft -= buflen;
94f3ca ¤   ¤   fifo->putoff += buflen;
ab9371 ¤   }
47bb7a ¤   return len;
8fefe6 }
dfaf5a
8c5d09 static size_t
80f658 fileFifoRead(PGPFifoContext *fifo, PGPByte *buf, size_t len)
70bb36 {
43b5e7 ¤   size_t avail;
d4af5a
36187e ¤   /* First get data out of peekahead buffer if any */
64be68 ¤   if (fifo->peekoff > fifo->getoff) {
1adef0 ¤   ¤   avail = fifo->peekoff - fifo->getoff;
a796e0 ¤   ¤   if (avail > len)
50695a ¤   ¤   ¤   avail = len;
9ce71b ¤   ¤   pgpCopyMemory(fifo->buf, buf, avail);
f0887b ¤   ¤   len -= avail;
a8d19b ¤   ¤   buf += avail;
935739 ¤   ¤   fifo->getoff += avail;
6a360e ¤   ¤   if (fifo->peekoff > fifo->getoff) {
da2fca ¤   ¤   ¤   /* Move data in fifo down */
c67e88 ¤   ¤   ¤   pgpCopyMemory(fifo->buf+avail, fifo->buf,
b64440 ¤   ¤   ¤   ·······fifo->peekoff-fifo->getoff);
e20fe4 ¤   ¤   }
edb969 ¤   ¤   if (len == 0)
ce3319 ¤   ¤   ¤   return avail;
3c9371 ¤   }
0baf5a
36fcf0 ¤   avail = fifo->putoff - fifo->getoff;
ae2731 ¤   if (avail > len)
68d88b ¤   ¤   avail = len;
a1af5a
a22947 ¤   if (fseek(fifo->f, fifo->getoff, SEEK_SET) != 0)
9b1a9d ¤   ¤   return kPGPError_FileOpFailed;
8b51d0 ¤   if (fread(buf, 1, avail, fifo->f) != avail)
805e40 ¤   ¤   return kPGPError_ReadFailed;
f3af5a
f595c0 ¤   PGPCFBDecrypt(fifo->rdcfb, buf, avail, buf);
--7660 001377df4a740100268 Page 5 of pgpFileFIFO.c
2a67c5 ¤
ec4311 ¤   fifo->getoff += avail;
3d8e86 ¤   if (fifo->putoff == fifo->getoff)
0a8433 ¤   ¤   fifo->putoff = fifo->getoff = 0;
85af5a
e1ce36 ¤   return avail;
2eefe6 }
b4af5a
e392cc PGPFifoDesc const pgpFileFifoDesc = {
9c73ce ¤   "File Fifo",
e54302 ¤   fileFifoCreate,
4c2452 ¤   fileFifoRead,
b10421 ¤   fileFifoWrite,
9f142f ¤   fileFifoPeek,
a21852 ¤   fileFifoSeek,
dc3e01 ¤   fileFifoFlush,
353327 ¤   fileFifoDestroy,
5815d0 ¤   fileFifoSize
3782f7 };
--4c1c 000c92dd4e740100269 Page 1 of pgpFileNames.c
bc38e5 /*
b1f78e ·* pgpFileNames.c
00cccf ·* Utility functions to work with filenames in different OS's
df8fc0 ·* These functions all return newly allocated character arrays
05d846 ·* which it is the responsibility of the caller to free.
eb775e ·*
baeb9e ·* Based on pgpAppFile,
753490 ·* ·written by:¤Colin Plumb and Derek Atkins <warlord@MIT.EDU>
4b775e ·*
1f2f3b ·* $Id: pgpFileNames.c,v 1.14 1998/05/21 14:34:36 pbj Exp $
43495d ·*/
aaaf5a
19e2ff #include "pgpConfig.h"
3baf5a
82d92d #include <stdarg.h>
94feb2 #include <stdio.h>
db324c #include <string.h>
c0af5a
70a146 #include "pgpDebug.h"
b17157 #include "pgpFileNames.h"
b00d08 #include "pgpMem.h"
a0af5a
2eaf5a
d338e5 /*
86a94d ·* DIRSEPS is a string of possible directory-separation characters
6c2a42 ·* The first one is the preferred one, which goes in between
29e44d ·* PGPPATH and the file name if PGPPATH is not terminated with a
12ad06 ·* directory separator.
11775e ·*
010e66 ·* PATHSEP is a the directory separator within a PATH of directories.
fb4c43 ·* Only one character per platform, please
78495d ·*/
09af5a
ec8229 #if defined(MSDOS) || defined(ATARI) || defined(_WIN32)
3e4267 static char const DIRSEPS[] = "\\/";
fcf6aa #define PATHSEP ';'
4a0395 #define SINGLE_EXT 1
d5af5a
24de2b #elif defined(PGP_UNIX)
95fcab static char const DIRSEPS[] = "/";
e7ac76 #define PATHSEP ':'
0caf5a
871317 #elif defined(AMIGA)
4e24f7 static char const DIRSEPS[] = "/:";
23f6aa #define PATHSEP ';'
46af5a
d200e2 #elif defined(VMS)
d65ed6 static char const DIRSEPS[] = "]:";¤/* Any more? */
8ef6aa #define PATHSEP ';'
620395 #define SINGLE_EXT 1
ecaf5a
2ef51d #elif defined(PGP_MACINTOSH)
15515d static char const DIRSEPS[] = ":";
aef6aa #define PATHSEP ';'
3daf5a
03db21 #else
a0ccd9 #error Unknown operating system - need one of\
bd0d8a ·PGP_UNIX, MSDOS, AMIGA, ATARI, VMS, or PGP_MACINTOSH.
837454 #endif
b6af5a
cf38e5 /*
1cc580 ·* Build a path name out of a number of segments.
182ab4 ·* Each segment is separated from the next with DIRSEPS[0] if
1f6ad0 ·* it does not end in a directory separator already.
88775e ·*
8acd49 ·* A first pass over the argument list adds up the length of the result,
3b4d31 ·* then space is allocated for it, then a second pass copies the result
847850 ·* to the allocated space.
16775e ·*
99034a ·* The first pass records in "flag" whether the previous segment did NOT end
a59ab2 ·* in a directory separator and, if the current segment exists, adds space
c9a5ea ·* for a separator if flag is true.
--82cc 000b1aff68d40100269 Page 2 of pgpFileNames.c
4f775e ·*
2cac84 ·* Then, if there was only one segment of note, that is returned directly.
3a1b8b ·* Otherwise, space is allocated in the MiscPool.
3b8f99 ·* Finally, the loop is repeated, copying to the allocated space and inserting
90d33a ·* directory separators as needed.
f2775e ·*
94cd67 ·* This function always returns a newly allocated buffer. ·It is the
0099a0 ·* responsibility of the caller to free it when finished.
44495d ·*/
d311e4 char *
6aae64 pgpFileNameBuild(PGPContextRef cdkContext, char const *seg, ...)
15bb36 {
cdfa20 ¤   va_list ap;
b71657 ¤   unsigned seglen, len, flag;
c28375 ¤   char const *curseg, *prevseg;
9d6422 ¤   char *p, *ret;
56af5a
c96579 ¤   /* Start by counting the length of the result */
a512c1 ¤   va_start (ap, seg);
39775a ¤   prevseg = 0;
a8ccf6 ¤   len = seglen = flag = 0;
65c46e ¤   for (curseg = seg; curseg; curseg = va_arg(ap, char const *)) {
843107 ¤   ¤   seglen = strlen (curseg);
1a4e19 ¤   ¤   if (!seglen)
3817f5 ¤   ¤   ¤   continue;
d269a8 ¤   ¤   prevseg = curseg;
5ba030 ¤   ¤   len += seglen + flag;
e15d42 ¤   ¤   /* Does curseg need a directory separator added? */
ea2fc8 ¤   ¤   flag = (strchr(DIRSEPS, curseg[seglen-1]) == 0);
3f9371 ¤   }
ad468e ¤   va_end (ap);
56af5a
939389 ¤   /* Allocate space for the combined string */
0bc8bd ¤   p = (char *)pgpContextMemAlloc (cdkContext, len+1,
0536ee ¤   ¤   ¤   ¤   ¤   ¤   ·0); /* +1 for trailing null */
d44dda ¤   if (!p)
a0bbde ¤   ¤   return 0;
169049 ¤   ret = p;
18af5a
7526d8 ¤   /* Combine the elements together */
c812c1 ¤   va_start (ap, seg);
d90060 ¤   flag = 0;
385626 ¤   for (curseg = seg; curseg; curseg = va_arg (ap, char const *)) {
5e3107 ¤   ¤   seglen = strlen (curseg);
334e19 ¤   ¤   if (!seglen)
8217f5 ¤   ¤   ¤   continue;
0b3143 ¤   ¤   if (flag)
a2e810 ¤   ¤   ¤   *p++ = DIRSEPS[0];
24b6a4 ¤   ¤   memcpy (p, curseg, seglen);
638b8d ¤   ¤   p += seglen;
9e5d42 ¤   ¤   /* Does curseg need a directory separator added? */
8c5670 ¤   ¤   flag = (strchr (DIRSEPS, curseg[seglen-1]) == 0);
189371 ¤   }
715ddc ¤   va_end(ap);
99af5a
9e51f2 ¤   *p = '\0';¤ /* Null-terminate the string */
2367c5 ¤
ef0ccc #if PGP_MACINTOSH
c770d3 ¤   pgpAssert( strlen( ret ) <= 255 );
8e7454 #endif
23986d ¤   return ret;
e7efe6 }
c8af5a
a9af5a
5bb177 #if 0
3211e4 char *
26d760 pgpFileNameExtend (PGPContextRef cdkContext, char const *base, char const *ext)
66bb36 {
c0e7ea ¤   char *name = (char *)pgpContextMemAlloc (cdkContext,
19f12c ¤   ¤   ¤   ¤   ··strlen (base) + strlen (ext) + 1, 0);
1daf5a
b1433f ¤   if (!name)
--83f2 0000fa8e47c40100269 Page 3 of pgpFileNames.c
327ed2 ¤   ¤   return NULL;
60af5a
d7c473 ¤   strcpy (name, base);
c6fabb ¤   strcat (name, ext);
b567c5 ¤
a70ccc #if PGP_MACINTOSH
d757f3 ¤   pgpAssert( strlen( name ) <= 255 );
d27454 #endif
ccaf5a
414f35 ¤   return name;
91efe6 }
dcaf5a
2c7454 #endif
bfaf5a
b911e4 char *
8d7f1e pgpFileNameContract (PGPContextRef cdkContext, char const *base)
e3bb36 {
1f813a ¤   char *p;
54dceb ¤   char *name = (char *)pgpContextMemAlloc (cdkContext, strlen (base) + 1,
59493e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···0);
c3af5a
ea433f ¤   if (!name)
567ed2 ¤   ¤   return NULL;
feaf5a
e4c473 ¤   strcpy (name, base);
3210ba ¤   /* remove an ending */
9290d1 ¤   p = strrchr (name, '.');
5f68fc ¤   if (p)
393f17 ¤   ¤   *p = '\0';
7daf5a
334f35 ¤   return name;
2cefe6 }
a3af5a
b5a41a /* Return the directory part of the path holding the file */
cf11e4 char *
010e6f pgpFileNameDirectory (PGPContextRef cdkContext, char const *base)
3cbb36 {
3f862f ¤   char *end1=0, *end2=0;
02d0ea ¤   char const *ds = DIRSEPS;
9b0273 ¤   char c;
971029 ¤   char *dir;
f1af5a
4bb7d2 ¤   while ((c = *ds++) != '\0') {
3db4f9 ¤   ¤   if ((end2 = strrchr (base, c)) != NULL) {
5fe10e ¤   ¤   ¤   if (!end1 || end1 < end2)
b95309 ¤   ¤   ¤   ¤   end1 = end2;
210fe4 ¤   ¤   }
679371 ¤   }
488986 ¤   /* If no path info, return . */
054d1b ¤   if (!end1) {
5e3a8c ¤   ¤   dir = (char *)pgpContextMemAlloc (cdkContext, 2, ·0);
a8455e ¤   ¤   if ( IsntNull( dir ) )
235b34 ¤   ¤   {
27a448 ¤   ¤   ¤   dir[0] = '.';
5d2c94 ¤   ¤   ¤   dir[1] = '\0';
de0fe4 ¤   ¤   }
d4c12b ¤   ¤   return dir;
989371 ¤   }
be67c5 ¤
05c03e ¤   dir = (char *)
918be8 ¤   ¤   pgpContextMemAlloc (cdkContext, end1 - base + 1, 0);
485176 ¤   if ( IsntNull( dir ) )
e0c7a1 ¤   {
c2a288 ¤   ¤   strncpy (dir, base, end1-base);
9b0777 ¤   ¤   dir[end1-base] = '\0';
9a9371 ¤   }
fc5658 ¤   return dir;
11efe6 }
e6af5a
b3af5a
b311e4 char *
0f3747 pgpFileNameNextDirectory (PGPContextRef cdkContext, char const *path,
--fc2c 000ac863ded40100269 Page 4 of pgpFileNames.c
cafdad ¤   ¤   ¤   ¤   ¤   ¤   ··char const **rest)
ebbb36 {
1b9626 ¤   char const *d;
b32d7d ¤   char *name;
afc6b5 ¤   unsigned len;
0467c5 ¤
fafc21 ¤   d = strchr (path, PATHSEP);
1268c1 ¤   if (d) {
86b6cc ¤   ¤   len = d - path;
f74809 ¤   ¤   d++;
9c2be7 ¤   } else
3edf37 ¤   ¤   len = strlen (path);
a1af5a
1d27a8 ¤   if (rest)
8327f2 ¤   ¤   *rest = d;
57af5a
88c150 ¤   name = (char *)pgpContextMemAlloc (cdkContext, len + 1,
f94772 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···0);
5a433f ¤   if (!name)
757ed2 ¤   ¤   return NULL;
00af5a
994be2 ¤   memcpy (name, path, len);
8dc1e3 ¤   name[len] = '\0';
774f35 ¤   return name;
e9efe6 }
51af5a
4011e4 char *
307140 pgpFileNameExtendPath (PGPContextRef cdkContext, char const *path,
78544f ¤   ¤   ¤   ¤   ¤   ···char const *dir, int front)
85bb36 {
5b0484 ¤   char *¤ p¤  = NULL;
6501f2 ¤   char *¤ t¤  = NULL;
064f7f ¤   PGPUInt32¤  length;
86af5a
d5def7 ¤   pgpAssert (dir);
a4af5a
8a22c7 ¤   length¤ = IsntNull( path ) ? strlen (path) : 0;
599da7 ¤   length¤ += strlen (dir) + 2;
b067c5 ¤
c17cc1 ¤   p = (char *)pgpContextMemAlloc ( cdkContext,
434003 ¤   ¤   length, 0);
9317ec ¤   if ( IsntNull( p ) ) {
b00326 ¤   ¤   t = p;
7495ca ¤   ¤   if (front) {
8b9735 ¤   ¤   ¤   memcpy (t, dir, strlen (dir));
deb0cc ¤   ¤   ¤   t += strlen (dir);
86a9ca ¤   ¤   ¤   if (path) {
64fb3d ¤   ¤   ¤   ¤   *(t++) = PATHSEP;
3fbd4c ¤   ¤   ¤   ¤   memcpy (t, path, strlen (path));
6b7d52 ¤   ¤   ¤   ¤   t += strlen (path);
06a3a6 ¤   ¤   ¤   }
42b462 ¤   ¤   ¤   *t = '\0';
0545a6 ¤   ¤   } else {
02a9ca ¤   ¤   ¤   if (path) {
d7bd4c ¤   ¤   ¤   ¤   memcpy (t, path, strlen (path));
a27d52 ¤   ¤   ¤   ¤   t += strlen (path);
bbfb3d ¤   ¤   ¤   ¤   *(t++) = PATHSEP;
d5a3a6 ¤   ¤   ¤   }
f69735 ¤   ¤   ¤   memcpy (t, dir, strlen (dir));
2eb0cc ¤   ¤   ¤   t += strlen (dir);
9bb462 ¤   ¤   ¤   *t = '\0';
4e0fe4 ¤   ¤   }
709371 ¤   }
fe381d ¤   return p;
1eefe6 }
4eaf5a
b238e5 /*
9e10db ·* This returns the filename (not including directory path)
3bc50f ·* It returns a pointer within <path>, rather than dynamically allocating it
e5495d ·*/
3711e4 char *
acc348 pgpFileNameTail (PGPContextRef cdkContext, char const *path)
--5bee 0013398626040100269 Page 5 of pgpFileNames.c
2cbb36 {
9e70b1 ¤   char const *¤   tail;
60e39e ¤   char const *¤   lastTail = path;
d671bb ¤   char const *¤   dirSep;
af67c5 ¤
c2ebc3 ¤   (void)cdkContext;
3aaf5a
216d5f ¤   for (dirSep = DIRSEPS; *dirSep; dirSep++)
fcc7a1 ¤   {
2d5001 ¤   ¤   tail = strrchr(lastTail, *dirSep);
56c577 ¤   ¤   if (tail != NULL)
e01427 ¤   ¤   ¤   lastTail = tail + 1;
429371 ¤   }
46abc6 ¤   return (char *)lastTail;
9befe6 }
33af5a
--5080 001718b4c634010026a Page 1 of pgpFileNames.h
bc38e5 /*
521326 ·* pgpFileNames.h
c4775e ·*
f1cccf ·* Utility functions to work with filenames in different OS's
bc775e ·*
2deb9e ·* Based on pgpAppFile,
663490 ·* ·written by:¤Colin Plumb and Derek Atkins <warlord@MIT.EDU>
13775e ·*
21ea72 ·* $Id: pgpFileNames.h,v 1.5 1997/06/25 01:17:26 hal Exp $
a6495d ·*/
eaaf5a
35c26c #include "pgpContext.h"
6daf5a
0d99c6 PGP_BEGIN_C_DECLARATIONS
24af5a
225b54 char ·*
be8958 pgpFileNameBuild (PGPContextRef cdkContext, char const *seg, ...);
a3af5a
835b54 char ·*
5f1993 pgpFileNameExtend (PGPContextRef cdkContext, char const *base,
ff4042 ¤   ¤   ¤   ¤   ¤   char const *ext);
86af5a
175b54 char ·*
a1f9a0 pgpFileNameContract (PGPContextRef cdkContext, char const *base);
77af5a
655b54 char ·*
b79bdf pgpFileNameDirectory (PGPContextRef cdkContext, char const *base);
d7af5a
f35b54 char ·*
8c3747 pgpFileNameNextDirectory (PGPContextRef cdkContext, char const *path,
b8c0d6 ¤   ¤   ¤   ¤   ¤   char const **rest);
48af5a
eb5b54 char ·*
da7140 pgpFileNameExtendPath (PGPContextRef cdkContext, char const *path,
fe69c7 ¤   ¤   ¤   ¤   ¤   char const *dir, int front);
94af5a
d738e5 /*
6710db ·* This returns the filename (not including directory path)
cfc50f ·* It returns a pointer within <path>, rather than dynamically allocating it
34495d ·*/
725b54 char ·*
24ceaf pgpFileNameTail (PGPContextRef cdkContext, char const *path);
24af5a
711254 PGP_END_C_DECLARATIONS
--939c 00072e10cd34010026b Page 1 of pgpFileRef.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
7e1b77 ¤   $Id: pgpFileRef.c,v 1.73.4.1.2.1 1998/11/12 03:23:18 heller Exp $
4af7f7 ____________________________________________________________________________*/
32af5a
d8e2ff #include "pgpConfig.h"
66af5a
b6abff #if HAVE_UNISTD_H
2717c2 #include <unistd.h>
047454 #endif
5daf5a
43cd8f #if HAVE_PATHS_H
ac963e #include <paths.h>
ed7454 #endif
e0af5a
58c755 #if PGP_UNIX || PGP_WIN32
1bf15e #include <sys/types.h>
53d4f4 #include <sys/stat.h>
ee656b #if HAVE_FCNTL_H
5b37bc #include <fcntl.h>
d97454 #endif
937454 #endif
49af5a
42fa58 #if __MWERKS__
45a907 #define HAVE_SHARE_H¤   0
3ddb21 #else
67a907 #define HAVE_SHARE_H¤   0
3a7454 #endif
1caf5a
6aafb9 #if PGP_WIN32
085655 #include <windows.h>
6d1044 #include <io.h>
512082 #if HAVE_SHARE_H
5b4d36 #include <share.h>
287454 #endif
607454 #endif
c5af5a
1e495d #include <errno.h>
3bfeb2 #include <stdio.h>
26324c #include <string.h>
9caf5a
940ccc #if PGP_MACINTOSH
3094b4 #include <unix.h>
cbb2bf #include <Errors.h>
521ef3 #include <Folders.h>
d35a11 #include <Script.h>
237454 #endif
7daf5a
bba4b2 #include "pgpFileRef.h"
e17157 #include "pgpFileNames.h"
0a3427 #include "pgpFileUtilities.h"
ac2f8d #include "pgpErrors.h"
2f675a #include "pgpTypes.h"
3ea146 #include "pgpDebug.h"
4a0d08 #include "pgpMem.h"
9fc26c #include "pgpContext.h"
53af5a
2a894b #include "pgpFileSpec.h"
d1af5a
baaf5a
6d0ccc #if PGP_MACINTOSH
c6af5a
b9bbf4 #include "MacFiles.h"
5785c2 #include "MacStrings.h"
f9bdfd #include "pgpMacFile.h"
7f52af #include "pgpMacUtils.h"
09af5a
727454 #endif
--7b5b 000d33292304010026b Page 2 of pgpFileRef.c
e0af5a
1aaf5a
7cffae #if !defined(_PATH_TMP) && PGP_UNIX && HAVE_MKSTEMP
6b3323 #define _PATH_TMP¤  "/tmp/"
ac7454 #endif
f5af5a
f0c360 #if HAVE_MKSTEMP && defined(sparc)
9eef9e extern int¤ mkstemp (char *__template);
617454 #endif
5caf5a
97ae4c #define pgpaPGPFileTypeValid(fileType)¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
d8e4e4 ¤   ¤   pgpaAssert(fileType > kPGPFileTypeNone¤ ¤   ¤   ¤   ¤   ¤   \
f2b27b ¤   ¤   ¤   ¤   && fileType < kPGPFileTypeNumTypes)
3eaf5a
731a2c /* These must be kept in sync with the PGPFileType decl in pgpFileRef.h */
f6af5a
d08556 #if PGP_UNIX¤   /* [ */
84af5a
4dd923 static struct UnixFileTypeEntry
55bb36 {
bc1eb6 ¤   mode_t¤ mask;¤  /* umask value for permissions */
bb139d } sUnixFileTypeTable[kPGPFileTypeNumTypes] = {
41664f ¤   { 0 },¤ ¤   /* kPGPFileTypeNone */
5cd015 ¤   { 0077 },¤  /* kPGPFileTypePrefs */
b98f3d ¤   { 0077 },¤  /* kPGPFileTypePubRing */
54d120 ¤   { 0077 },¤  /* kPGPFileTypePrivRing */
2a53c1 ¤   { 0077 },¤  /* kPGPFileTypeDetachedSig */
21c9ea ¤   { 0077 },¤  /* kPGPFileTypeRandomSeed */
d1c9eb ¤   { 0077 },¤  /* kPGPFileTypeExportedKeys */
c55d55 ¤   { 0077 },¤  /* kPGPFileTypeArmorFile */
94d8a6 ¤   { 0077 },¤  /* kPGPFileTypeEncryptedData */
4c193e ¤   { 0077 },¤  /* kPGPFileTypeGroups */
6295a2 ¤   { 0077 },¤  /* kPGPFileTypeDecryptedText */
d6ac34 ¤   { 0077 },¤  /* kPGPFileTypeDecryptedBin */
33564e ¤   { 0077 }¤   /* kPGPFileTypeSignedData */
2582f7 };
28af5a
514bf8 #endif¤ /* ] PGP_UNIX */
deaf5a
a6af5a
b0af5a
80af5a
385947 ¤   PGPMemoryMgrRef
1abac3 pgpGetFileRefMemoryMgr( PFLConstFileSpecRef fileRef )
bfbb36 {
40b7c9 ¤   return(·
613896 ¤   ¤   PFLGetFileSpecMemoryMgr( (PFLConstFileSpecRef)fileRef ) );
33efe6 }
6aaf5a
58af5a
ecaf5a
bf38e5 /*
9aba8f ·* pgpGetFileRefName returns a string allocated with pgpContextMemAlloc(),
1fdc58 ·* which the caller is responsible for freeing.
e8495d ·*/
ced25c ¤   char *
697e9f pgpGetFileRefName( PFLConstFileSpecRef¤ fileRef)
7dbb36 {
37bd3a ¤   char *¤ name¤   = NULL;
7926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
8167c5 ¤
cf3ce8 ¤   err¤= PFLGetFileSpecName( fileRef, &name );
c467c5 ¤
ed2a00 ¤   return( name );
4fefe6 }
5aaf5a
d3af5a
5dc744 ¤   PGPError
24a5b3 pgpSetFileRefName(
99db0b ¤   PFLFileSpecRef¤ fileRef,
680370 ¤   char const *¤   newName)
d3bb36 {
--c2b4 000912324994010026b Page 3 of pgpFileRef.c
3bf30d ¤   return( PFLSetFileSpecName( fileRef, newName ) );
eaefe6 }
42af5a
f237fc ¤   uchar *
9a6774 pgpExportFileRef(
6ab622 ¤   PFLConstFileSpecRef¤¤   fileRef,
f12ecd ¤   size_t *¤   ¤   ¤   ¤   size)
2fbb36 {
2e26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2ed7f0 ¤   PGPByte *¤  data¤   = NULL;
7d829d ¤   PGPSize¤¤   dataSize;
5b67c5 ¤
4fabe4 ¤   err¤= PFLExportFileSpec( fileRef, &data, &dataSize );
0166ad ¤   *size¤  = dataSize;
8b67c5 ¤
2e4600 ¤   return( data );
ebefe6 }
79af5a
77c744 ¤   PGPError
20453b pgpImportFileRef(
99a1bc ¤   PGPContextRef¤  ¤   context,
3a9da4 ¤   uchar const *¤  ¤   buffer,
a0eefe ¤   size_t¤ ¤   ¤   ¤   size,
8e80bd ¤   PFLFileSpecRef *¤   ¤   outRef )
b9bb36 {
b926d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
a267c5 ¤
7fb8c2 ¤   err¤= PFLImportFileSpec( PGPGetContextMemoryMgr( context ),
13422f ¤   ¤   ¤   ¤   buffer, size, outRef );
d867c5 ¤
73deb7 ¤   return( err );
31efe6 }
87af5a
d2af5a
e5c21c #if PGP_MACINTOSH¤  /* [ */
54af5a
b9c744 ¤   PGPError
c2f2eb pgpCalcFileSize(
c1b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
69afa5 ¤   PGPFileOpenFlags¤   flags,
43bd0c ¤   size_t *¤   ¤   ¤   fileSize)
5cbb36 {
c9cb5d ¤   return pgpMacCalcFileSize(fileRef, flags, fileSize);
3fefe6 }
ddaf5a
adc744 ¤   PGPError
df26b9 pgpCreateFile(
e4b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
4f9310 ¤   PGPFileType¤¤   ¤   fileType)
b1bb36 {
3e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
9e496c ¤   FSSpec¤ ¤   spec;
22b6f9 ¤   OSErr¤  ¤   macErr;
5867c5 ¤
4065f3 ¤   PFLValidateFileSpec( fileRef );
1067c5 ¤
605ab6 ¤   err¤= PFLGetFSSpecFromFileSpec(fileRef, &spec);
9df1e7 ¤   if ( IsntPGPError( err ) )
dbc7a1 ¤   {
35e030 ¤   ¤   macErr = FSpCreate( &spec,
7aab16 ¤   ¤   ¤   ¤   ¤   pgpGetMacFileCreatorFromPGPFileType( fileType ),
289f75 ¤   ¤   ¤   ¤   ¤   pgpGetMacFileTypeFromPGPFileType( fileType ),
3a550b ¤   ¤   ¤   ¤   ¤   smSystemScript );
8a3533 ¤   ¤   if (macErr != noErr)
728017 ¤   ¤   ¤   err = pgpErrorFromMacError(macErr, kPGPError_CantOpenFile);
639371 ¤   }
e45ea8 ¤   return err;
72efe6 }
9daf5a
69af5a
a3c701 ¤   FILE *
91031f pgpStdIOOpenTempFile(
--9e56 000b68cf4564010026b Page 4 of pgpFileRef.c
e3a1bc ¤   PGPContextRef¤  ¤   context,
5a2b78 ¤   PFLFileSpecRef *¤   tempFileRef,
246bae ¤   PGPError *¤ ¤   ¤   errorCode)
2ebb36 {
2f496c ¤   FSSpec¤ ¤   spec;
1eeeb0 ¤   FILE *¤ ¤   stdIOFile = NULL;
3e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
fdb6f9 ¤   OSErr¤  ¤   macErr;
366bf9 ¤   long¤   ¤   i;
7c67c5 ¤
58db93 ¤   pgpa(pgpaAddrValid(tempFileRef, PFLFileSpecRef));
7667c5 ¤
836c45 ¤   *tempFileRef = NULL;
e8b9ea ¤   if ((macErr = FindFolder(kOnSystemDisk, kTemporaryFolderType,
7d29b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kCreateFolder, &spec.vRefNum,
67c3c6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &spec.parID)) != noErr)
981de7 ¤   ¤   goto macError;
ac67c5 ¤
0e31f6 ¤   for (i = 0; ; i++)
30c7a1 ¤   {
9e2efc ¤   ¤   pgpFormatPStr(spec.name, sizeof(spec.name), 0, "PGP Temp %d", i);
731a5d ¤   ¤   macErr = FSpCreate( &spec, '????', 'BINA', smSystemScript );
ab3ed4 ¤   ¤   if (macErr == noErr)
3dcdcb ¤   ¤   ¤   break;
4d6c43 ¤   ¤   else if (macErr != dupFNErr)
fbff06 ¤   ¤   ¤   goto macError;
b99371 ¤   }
5667c5 ¤
ad27a9 ¤   err¤= PFLNewFileSpecFromFSSpec( PGPGetContextMemoryMgr( context ),
0e4287 ¤   ¤   &spec, tempFileRef );
a97a91 ¤   if ( IsErr( err ) )
cb97ed ¤   ¤   goto error;
bd67c5 ¤
6c8396 ¤   *errorCode¤ = pgpFileRefStdIOOpen(*tempFileRef, kPGPFileOpenStdUpdateFlags,
280cf7 ¤   ¤   ¤   ¤   ¤   ¤   kPGPFileTypeDecryptedBin, &stdIOFile);
4d6ba3 ¤   return( stdIOFile );
9667c5 ¤
9e0e56 macError:
c0f30e ¤   err = pgpErrorFromMacError(macErr, kPGPError_CantOpenFile);
3f60ff error:
265a63 ¤   if (*tempFileRef != NULL)
6bc7a1 ¤   {
30262c ¤   ¤   PFLFreeFileSpec(*tempFileRef);
535818 ¤   ¤   *tempFileRef = NULL;
209371 ¤   }
9bf3b3 ¤   if (errorCode != NULL)
a3c7a1 ¤   {
bc03c0 ¤   ¤   pgpAssertAddrValid(errorCode, PGPError);
ce24c7 ¤   ¤   *errorCode = err;
4e9371 ¤   }
503f59 ¤   return NULL;
ceefe6 }
43af5a
49c69d #else¤  /* ] PGP_MACINTOSH [ */
63af5a
f4c744 ¤   PGPError
c2f2eb pgpCalcFileSize(
68b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
8e82bd ¤   PGPFileOpenFlags¤   ¤   flags,
d31a4c ¤   size_t *¤   ¤   ¤   ¤   fileSize)
36bb36 {
793bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
61078b ¤   char *¤ ¤   ¤   fullPath = NULL;
e394df ¤   struct stat¤¤   statBuf;
8f67c5 ¤
7a65f3 ¤   PFLValidateFileSpec( fileRef );
023dc7 ¤   PGPValidatePtr( fileSize );
7367c5 ¤
cf6ca5 ¤   (void)flags;¤   /* Avoid warning */
e873f8 ¤   *fileSize = 0;¤ /* In case there's an error */
ce67c5 ¤
b65c18 ¤   err = PFLGetFullPathFromFileSpec(fileRef, &fullPath);
--4a73 000bc71b19c4010026b Page 5 of pgpFileRef.c
e5f1e7 ¤   if ( IsntPGPError( err ) )
5ac7a1 ¤   {
955a89 ¤   ¤   /* XXX Maybe make this more portable. ·Does this work on MSDOS? */
115bfc ¤   ¤   if (stat(fullPath, &statBuf) != 0)
a17f09 ¤   ¤   ¤   err = kPGPError_CantOpenFile;
4b12d9 ¤   ¤   else if ((S_IFMT & statBuf.st_mode) == S_IFREG)
2060c3 ¤   ¤   ¤   *fileSize = statBuf.st_size;
3d7514 ¤   ¤   /* XXX Maybe return a special err if it's not a regular file */
ec9371 ¤   }
3867c5 ¤
201b52 ¤   ¤
ea27f3 ¤   PGPFreeData( fullPath );
1d5ea8 ¤   return err;
f8efe6 }
1faf5a
55af5a
6aaf5a
07c744 ¤   PGPError
f226b9 pgpCreateFile(
9db622 ¤   PFLConstFileSpecRef¤¤   fileRef,
dd9310 ¤   PGPFileType¤¤   ¤   fileType)
67bb36 {
5b8e12 ¤   PGPError¤   err = kPGPError_NoErr;
f0df90 ¤   char *¤ ¤   fullPath = NULL;
c467c5 ¤
3465f3 ¤   PFLValidateFileSpec( fileRef );
93b048 ¤   (void)fileType;
0767c5 ¤
065c18 ¤   err = PFLGetFullPathFromFileSpec(fileRef, &fullPath);
9ef1e7 ¤   if ( IsntPGPError( err ) )
ffc7a1 ¤   {
918556 #if PGP_UNIX¤   /* [ */
78e03b ¤   ¤   int¤¤   ¤   fileDes;
5c1b52 ¤   ¤
5a1b17 ¤   ¤   /*
7fc36a ¤   ¤   ·* XXX Beware that calling this routine could be a security flaw,
71a433 ¤   ¤   ·* ····because there is a window between creating and opening
8e1bd5 ¤   ¤   ·* ····the file, in between which the file might have been moved
e71bcd ¤   ¤   ·* ····out of the way, thus possibly having you open a new file
50f031 ¤   ¤   ·* ····with the wrong permissions.
1a9de3 ¤   ¤   ·*/
4f06a6 ¤   ¤   fileDes = open(fullPath,
9f5de3 ¤   ¤   ¤   ¤   ¤   ¤   O_WRONLY | O_CREAT | O_EXCL,
fc6805 ¤   ¤   ¤   ¤   ¤   ¤   0666 & ~sUnixFileTypeTable[fileType].mask);
bf660c ¤   ¤   if (fileDes > 0)
1aa802 ¤   ¤   ¤   close(fileDes);
f20e1d ¤   ¤   else
285921 ¤   ¤   ¤   err = kPGPError_CantOpenFile;¤  /* XXX Use better error */
d55532 #else¤  /* ] PGP_UNIX [ */
667159 ¤   ¤   FILE *¤ ¤   stdIOFile;
d71b52 ¤   ¤
e12a77 ¤   ¤   stdIOFile = fopen(fullPath, "ab+");
46b17b ¤   ¤   if (stdIOFile != NULL)
61d7f6 ¤   ¤   ¤   fclose(stdIOFile);
f70e1d ¤   ¤   else
635921 ¤   ¤   ¤   err = kPGPError_CantOpenFile;¤  /* XXX Use better error */
fb4bf8 #endif¤ /* ] PGP_UNIX */
049371 ¤   }
67db79 ¤   PGPFreeData( fullPath);
4c5ea8 ¤   return err;
cbefe6 }
b3af5a
eeaf5a
1aaf5a
5caf5a
8ac701 ¤   FILE *
a7031f pgpStdIOOpenTempFile(
56a1bc ¤   PGPContextRef¤  ¤   context,
452b78 ¤   PFLFileSpecRef *¤   tempFileRef,
056bae ¤   PGPError *¤ ¤   ¤   errorCode)
4cbb36 {
bcb388 ¤   char¤   ¤   fileName[L_tmpnam];
--e0a3 0005a15d6f84010026b Page 6 of pgpFileRef.c
868e12 ¤   PGPError¤   err = kPGPError_NoErr;
c0eeb0 ¤   FILE *¤ ¤   stdIOFile = NULL;
0267c5 ¤
3adb93 ¤   pgpa(pgpaAddrValid(tempFileRef, PFLFileSpecRef));
6c67c5 ¤
fc6c45 ¤   *tempFileRef = NULL;
53af5a
0321d4 #if defined(_PATH_TMP) && HAVE_MKSTEMP¤ /* [ */
45af5a
06c7a1 ¤   {
a88141 ¤   ¤   int¤¤   ¤   fd = -1;
2eaf5a
054a55 ¤   ¤   strncpy(fileName, _PATH_TMP "ptmpXXXXXX", sizeof(fileName));
bc03ac ¤   ¤   fileName[sizeof(fileName) - 1] = '\0';
41b626 ¤   ¤   if ((fd = mkstemp(fileName)) == -1 ||
864d30 ¤   ¤   ¤   ¤   (stdIOFile = fdopen(fd, "w+b")) == NULL)
cf5b34 ¤   ¤   {
efd108 ¤   ¤   ¤   if (fd != -1)
d7c9c5 ¤   ¤   ¤   ¤   close(fd);
d16521 ¤   ¤   ¤   goto fileError;
1d0fe4 ¤   ¤   }
10bcc7 ¤   ¤   err¤= PFLNewFileSpecFromFullPath( PGPGetContextMemoryMgr( context ),
2ca9be ¤   ¤   ¤   ¤   fileName, tempFileRef);
3533b8 ¤   ¤   if (IsPGPError( err ))
30ed19 ¤   ¤   ¤   goto error;
4d9371 ¤   }
92af5a
dd6f36 #else¤  /* ] defined(_PATH_TMP) && HAVE_MKSTEMP [ */
3467c5 ¤
58de54 ¤   if (tmpnam(fileName) != fileName)
659344 ¤   ¤   goto fileError;
68af5a
378b40 ¤   if (IsPGPError(err = PFLNewFileSpecFromFullPath(
d89e2f ¤   ¤   PGPGetContextMemoryMgr( context ), fileName, tempFileRef)))
3ec7a1 ¤   {
fcbce1 ¤   ¤   err = kPGPError_OutOfMemory;
4397ed ¤   ¤   goto error;
b39371 ¤   }
f567c5 ¤
d1ef12 ¤   /* XXX Perhaps check for an error and retry if necessary */
f491f0 ¤   *errorCode = pgpFileRefStdIOOpen(*tempFileRef,
d5d3bc ¤   ¤   ¤   kPGPFileOpenStdUpdateFlags,
dc1a09 ¤   ¤   ¤   kPGPFileTypeDecryptedBin, &stdIOFile);
59af5a
6596b8 #endif¤ /* ] defined(_PATH_TMP) && HAVE_MKSTEMP */
4eaf5a
241ae8 ¤   if (stdIOFile == NULL)
80c7a1 ¤   {
f115eb ¤   fileError:
1b43e7 ¤   ¤   err = kPGPError_CantOpenFile;
8b97ed ¤   ¤   goto error;
109371 ¤   }
78af5a
1c1314 ¤   return stdIOFile;
3767c5 ¤
6860ff error:
205a63 ¤   if (*tempFileRef != NULL)
05c7a1 ¤   {
59262c ¤   ¤   PFLFreeFileSpec(*tempFileRef);
df5818 ¤   ¤   *tempFileRef = NULL;
c49371 ¤   }
a8f3b3 ¤   if (errorCode != NULL)
fdc7a1 ¤   {
cd03c0 ¤   ¤   pgpAssertAddrValid(errorCode, PGPError);
5b24c7 ¤   ¤   *errorCode = err;
b19371 ¤   }
4d3f59 ¤   return NULL;
d8efe6 }
2baf5a
d3ddc8 #endif¤ /* ] PGP_MACINTOSH */
10af5a
5aaf5a
--32dd 000e335708d4010026b Page 7 of pgpFileRef.c
a70335 /*____________________________________________________________________________
5bd7df ¤   A stupid API routine called in several places by one file.
e3d7f7 ¤   Get RID OF IT as soon as possible.
a167c5 ¤
7b4fae ¤   - the file is renamed to have the name found in "newRef". ·The rest of
d6329f ¤   the path is ignored (so why pass it?)
ece14f ¤   - you can't change either file ref
4ff7f7 ____________________________________________________________________________*/
77c744 ¤   PGPError
e38dac pgpRenameFile(
0be0c1 ¤   PFLConstFileSpecRef¤oldRef,
721032 ¤   PFLConstFileSpecRef¤newRef)
bcbb36 {
aa8e12 ¤   PGPError¤   err = kPGPError_NoErr;
2af6a7 ¤   char *¤ ¤   newName¤= NULL;
7e67c5 ¤
ad4f21 ¤   PFLValidateFileSpec( oldRef );
358099 ¤   PFLValidateFileSpec( newRef );
bc67c5 ¤
201651 ¤   err¤= PFLGetFileSpecName( newRef, &newName);
c9f1e7 ¤   if ( IsntPGPError( err ) )
efc7a1 ¤   {
c62e2a ¤   ¤   PFLFileSpecRef¤ tempRef;
2b1b52 ¤   ¤
f998aa ¤   ¤   /* need to copy it because PFLFileSpecRename() changes the name·
ccb874 ¤   ¤   as well as renaming the file */
4a5c88 ¤   ¤   err¤= PFLCopyFileSpec( oldRef, &tempRef );
307d98 ¤   ¤   if ( IsntPGPError( err ) )
675b34 ¤   ¤   {
c2d309 ¤   ¤   ¤   err¤= PFLFileSpecRename( tempRef, newName );
3be77c ¤   ¤   ¤   (void)PFLFreeFileSpec( tempRef );
070fe4 ¤   ¤   }
67c719 ¤   ¤   PGPFreeData( newName );
e89371 ¤   }
af67c5 ¤
285ea8 ¤   return err;
4befe6 }
cbaf5a
a8af5a
dbaf5a
42af5a
117078 ¤   PGPFile *
0bfb31 pgpFileRefOpen(
01a1bc ¤   PGPContextRef¤  ¤   context,
541bab ¤   PFLConstFileSpecRef¤fileRef,
c9afa5 ¤   PGPFileOpenFlags¤   flags,
5aeda8 ¤   PGPFileType¤¤   ¤   fileType,
566bae ¤   PGPError *¤ ¤   ¤   errorCode)
2bbb36 {
e61eb8 ¤   FILE *¤ ¤   ¤   stdIOFile;
45d91c ¤   PGPMemoryMgrRef¤memoryMgr;
3e67c5 ¤
ee7aaa ¤   pgpAssertAddrValid( fileRef, PFLFileSpecRef );
7bb3eb ¤   memoryMgr¤  = PFLGetFileSpecMemoryMgr( fileRef );
89af5a
43c21c #if PGP_MACINTOSH¤  /* [ */
7e72fb ¤   switch (flags & (kPGPFileOpenReadWritePerm |
595abf ¤   ¤   ¤   ¤   ¤   kPGPFileOpenAppend | kPGPFileOpenTruncate |
5a4ec8 ¤   ¤   ¤   ¤   ¤   kPGPFileOpenCreate | kPGPFileOpenTextMode))
66c7a1 ¤   {
d22c51 ¤   ¤   case kPGPFileOpenReadPerm:
9800c2 ¤   ¤   ¤   return pgpFileRefMacReadOpen( context, fileRef, flags, errorCode);
9fe5ec ¤   ¤   case kPGPFileOpenStdWriteFlags:
e66f9d ¤   ¤   ¤   return pgpFileRefMacWriteOpen( context, fileRef, fileType, flags,
7307e6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   errorCode);
d39ae3 ¤   ¤   default:
e2cdcb ¤   ¤   ¤   break;
b79371 ¤   }
6e8c94 ¤   pgpAssertMsg((flags & (kPGPFileOpenMaybeLocalEncode |
31595c ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPFileOpenForceLocalEncode)) == 0,
2092fe ¤   ¤   ¤   ¤   "This combination of flags not currently supported");
e3ddc8 #endif¤ /* ] PGP_MACINTOSH */
--2cfb 0005f45884e4010026b Page 8 of pgpFileRef.c
2a67c5 ¤
748adc ¤   *errorCode = pgpFileRefStdIOOpen(fileRef, flags, fileType, &stdIOFile);
dccdc5 ¤   if ( IsPGPError( *errorCode ) )
917ed2 ¤   ¤   return NULL;
de67c5 ¤
cedb35 ¤   switch (flags & kPGPFileOpenReadWritePerm)
7ac7a1 ¤   {
ef2c51 ¤   ¤   case kPGPFileOpenReadPerm:
236c48 ¤   ¤   ¤   return pgpFileReadOpen( context, stdIOFile, NULL, NULL);
426c95 ¤   ¤   case kPGPFileOpenWritePerm:
ef0215 ¤   ¤   ¤   return pgpFileWriteOpen( context, stdIOFile, NULL);
179ae3 ¤   ¤   default:
f3fddd ¤   ¤   ¤   pgpAssertMsg(0, "No support for simultaneous read/write yet");
bdcdcb ¤   ¤   ¤   break;
699371 ¤   }
ec213f ¤   fclose(stdIOFile);
d33f59 ¤   return NULL;
c9efe6 }
98af5a
08599f ¤   PGPFileRead *
787e77 pgpFileRefReadCreate(
24a1bc ¤   PGPContextRef¤  ¤   context,
e01bab ¤   PFLConstFileSpecRef¤fileRef,
06afa5 ¤   PGPFileOpenFlags¤   flags,
ce1516 ¤   PGPError *¤ ¤   ¤   errorCode,
1377fe ¤   PGPFileDataType¤*¤  fileDataType)
6ebb36 {
106b27 ¤   PGPFile *¤  ¤   pgpFile;
0b0821 ¤   PGPFileRead *¤  pgpFileRead;
8067c5 ¤
4a4ba4 ¤   *fileDataType = kPGPFileDataType_Unknown;
de67c5 ¤
caeb4a ¤   if ((pgpFile = pgpFileRefOpen( context, fileRef, flags,
592783 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPFileTypeNone, errorCode)) == NULL)
367ed2 ¤   ¤   return NULL;
4e67c5 ¤
f74dde ¤   pgpFileRead = pgpPGPFileReadCreate( context, pgpFile, TRUE);
e367c5 ¤
82ab4c ¤   if ( pgpFileRead == NULL)
1ec7a1 ¤   {
3f3da1 ¤   ¤   pgpFileClose(pgpFile);
587ed2 ¤   ¤   return NULL;
cf9371 ¤   }
0a67c5 ¤
908e13 ¤   *fileDataType = pgpFile->dataType;
1d67c5 ¤
41a3b5 ¤   return pgpFileRead;
30efe6 }
03af5a
341c0e /* XXX Compatibility routines follow, intended to be phased out */
13af5a
b238e5 /*
6566ac ·* pgpFileRefStdIOOpen is currently the heart of the implementation
eaadc0 ·* for opening files, but this may change later.
94495d ·*/
d3af5a
a0c744 ¤   PGPError
d0ecfa pgpFileRefStdIOOpen(
5e1bab ¤   PFLConstFileSpecRef¤fileRef,
8aafa5 ¤   PGPFileOpenFlags¤   flags,
3eeda8 ¤   PGPFileType¤¤   ¤   fileType,
fabbc3 ¤   FILE **¤¤   ¤   ¤   outFile )
f4bb36 {
f1a0ba ¤   char¤   ¤   mode[5];
d9eeb0 ¤   FILE *¤ ¤   stdIOFile = NULL;
048e12 ¤   PGPError¤   err = kPGPError_NoErr;
295d5e ¤   const char *¤   kModeStr¤   = NULL;
3167c5 ¤
e9b048 ¤   (void)fileType;
c55c98 #if PGP_DEBUG
5be462 ¤   if (flags & kPGPFileOpenCreate)
5f55a3 ¤   ¤   pgpa(pgpaPGPFileTypeValid(fileType));
--efc3 000f31bad714010026b Page 9 of pgpFileRef.c
a07454 #endif
ac275a ¤   *outFile¤   = NULL;
fb67c5 ¤
a634df ¤   switch (flags & ~(kPGPFileOpenTextMode |
352ca9 ¤   ¤   ¤   ¤   ¤   ·kPGPFileOpenMaybeLocalEncode |
4ae829 ¤   ¤   ¤   ¤   ¤   ·kPGPFileOpenForceLocalEncode |
0b561b ¤   ¤   ¤   ¤   ¤   ·kPGPFileOpenLocalEncodeHashOnly |
e72bcf ¤   ¤   ¤   ¤   ¤   ·kPGPFileOpenNoMacBinCRCOkay |
b3d11b ¤   ¤   ¤   ¤   ¤   ·kPGPFileOpenLockFile))
acc7a1 ¤   {
2c0114 ¤   ¤   case kPGPFileOpenReadPerm:¤ ¤   kModeStr¤   = "r";¤ break;
9304d9 ¤   ¤   case kPGPFileOpenStdWriteFlags:¤kModeStr¤   = "w";¤ break;
a96f32 ¤   ¤   case kPGPFileOpenStdAppendFlags:kModeStr¤   = "a";¤ break;
3e5876 ¤   ¤   case kPGPFileOpenReadWritePerm:¤kModeStr¤   = "r+";¤break;
978ae6 ¤   ¤   case kPGPFileOpenStdUpdateFlags:kModeStr¤   = "w+";¤break;
e4e24f ¤   ¤   case kPGPFileOpenStdAppendFlags | kPGPFileOpenReadPerm:
d58729 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kModeStr¤   = "a+";¤break;
d59ae3 ¤   ¤   default:
5501f0 ¤   ¤   ¤   pgpAssertMsg(0, "Unsupported open mode");
4c5820 ¤   ¤   ¤   err = kPGPError_BadParams;
8fed19 ¤   ¤   ¤   goto error;
499371 ¤   }
12f1b4 ¤   strcpy( mode, kModeStr );
5f67c5 ¤
8876df ¤   if (!(flags & kPGPFileOpenTextMode))
9341e0 ¤   ¤   strcat(mode, "b");
0267c5 ¤
14afb9 #if PGP_WIN32
40ea1e ¤   strcat (mode, "c");¤¤   ¤   /* Commit-to-disk mode, flushes writes out */
b97454 #endif
deaf5a
0ec21c #if PGP_MACINTOSH¤  /* [ */
c2c7a1 ¤   {
488ed9 ¤   ¤   FSSpec¤ ¤   spec;
cd5342 ¤   ¤   short¤  ¤   refNum;
c2d922 ¤   ¤   SInt8¤  ¤   perm¤   = fsRdPerm;
4a1b52 ¤   ¤
ec0f1a ¤   ¤   err¤= PFLGetFSSpecFromFileSpec(fileRef, &spec);
c77d98 ¤   ¤   if ( IsntPGPError( err ) )
225b34 ¤   ¤   {
ebedc2 ¤   ¤   ¤   OSErr¤  ¤   macErr;
0e87c7 ¤   ¤   ¤
69a951 ¤   ¤   ¤   if (flags & kPGPFileOpenCreate)
07f776 ¤   ¤   ¤   {
54af8f ¤   ¤   ¤   ¤   macErr = FSpCreate( &spec,
8a31ba ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpGetMacFileCreatorFromPGPFileType( fileType ),
b29ce0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpGetMacFileTypeFromPGPFileType( fileType ),
5d5020 ¤   ¤   ¤   ¤   ¤   ¤   ¤   smSystemScript );
3b0877 ¤   ¤   ¤   ¤   if (macErr != noErr && macErr != dupFNErr)
2a72c3 ¤   ¤   ¤   ¤   {
b912fe ¤   ¤   ¤   ¤   ¤   err = pgpErrorFromMacError(macErr,
ff36dc ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPError_CantOpenFile);
cab622 ¤   ¤   ¤   ¤   ¤   goto error;
a82613 ¤   ¤   ¤   ¤   }
f4a3a6 ¤   ¤   ¤   }
0287c7 ¤   ¤   ¤
a412a0 ¤   ¤   ¤   switch (flags & kPGPFileOpenReadWritePerm)
f3f776 ¤   ¤   ¤   {
78396f ¤   ¤   ¤   ¤   case kPGPFileOpenReadPerm:¤ ¤   perm = fsRdPerm;¤   break;
229f7e ¤   ¤   ¤   ¤   case kPGPFileOpenWritePerm:¤¤   perm = fsWrPerm;¤   break;
47a182 ¤   ¤   ¤   ¤   case kPGPFileOpenReadWritePerm:¤perm = fsRdWrPerm;¤ break;
716ab9 ¤   ¤   ¤   ¤   default:
0ae087 ¤   ¤   ¤   ¤   ¤   pgpAssertMsg(0, "Unsupported open mode");
e3c7f4 ¤   ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
99b622 ¤   ¤   ¤   ¤   ¤   goto error;
70a3a6 ¤   ¤   ¤   }
8887c7 ¤   ¤   ¤
ea081e ¤   ¤   ¤   if ((macErr = FSpOpenDF(&spec, perm, &refNum)) != noErr)
15f776 ¤   ¤   ¤   {
559b1e ¤   ¤   ¤   ¤   err = pgpErrorFromMacError(macErr, kPGPError_CantOpenFile);
e61b7c ¤   ¤   ¤   ¤   goto error;
f3a3a6 ¤   ¤   ¤   }
--a902 0005aa777474010026b Page 10 of pgpFileRef.c
b6c089 ¤   ¤   ¤   stdIOFile = fdopen(refNum, mode);
f082bf ¤   ¤   ¤   if (stdIOFile == NULL)
4571a7 ¤   ¤   ¤   ¤   FSClose(refNum);
380fe4 ¤   ¤   }
3e9371 ¤   }
7bb6e1 #elif PGP_WIN32¤¤   /* ] [ */
69c7a1 ¤   {
9ae2f8 ¤   ¤   char *¤ ¤   fullPath = NULL;
8d4587 ¤   ¤   int¤¤   ¤   fileHandle¤ = -1;
8086a8 ¤   ¤   int¤¤   ¤   oFlags = 0;
d96109 ¤   #if HAVE_SHARE_H
a008ad ¤   ¤   int¤¤   ¤   shFlags = 0;
92b7ec ¤   #endif
f0af5a
afbe18 ¤   ¤   err = PFLGetFullPathFromFileSpec(fileRef, &fullPath);
da7d98 ¤   ¤   if ( IsntPGPError( err ) )
6f5b34 ¤   ¤   {
0b6ed2 ¤   ¤   ¤   /* 'kPGPFileOpenReadWritePerm' is a mask */
c38f2a ¤   ¤   ¤   if ( ( flags & kPGPFileOpenReadWritePerm ) ==
fcab83 ¤   ¤   ¤   ¤   ¤   kPGPFileOpenReadWritePerm )
6569fb ¤   ¤   ¤   ¤   oFlags |= _O_RDWR;
c1b922 ¤   ¤   ¤   else if ( flags & kPGPFileOpenReadPerm )
2d5a4c ¤   ¤   ¤   ¤   oFlags |= _O_RDONLY;
99be6e ¤   ¤   ¤   else if ( flags & kPGPFileOpenWritePerm )
252029 ¤   ¤   ¤   ¤   oFlags |= _O_WRONLY;
9d388b ¤   ¤   ¤   if ( flags & kPGPFileOpenAppend )
552a12 ¤   ¤   ¤   ¤   oFlags |= _O_APPEND;
d6ea1d ¤   ¤   ¤   if ( flags & kPGPFileOpenTruncate )
134f95 ¤   ¤   ¤   ¤   oFlags |= _O_TRUNC;
26198b ¤   ¤   ¤   if ( flags & kPGPFileOpenCreate )
a4326d ¤   ¤   ¤   ¤   oFlags |= _O_CREAT;
ace483 ¤   ¤   ¤   if ( flags & kPGPFileOpenTextMode )
c41e65 ¤   ¤   ¤   ¤   oFlags |= _O_TEXT;
4ebb8c ¤   ¤   ¤   else
612c4f ¤   ¤   ¤   ¤   oFlags |= _O_BINARY;
29af5a
c67aad ¤   ¤   ¤   /*
e9a967 ¤   ¤   ¤   ·* XXX: In the future, we may decide to lock by default,
214996 ¤   ¤   ¤   ·* ·····but for now we're playing it safe and keeping the
49badf ¤   ¤   ¤   ·* ·····existing behavior.
6f8753 ¤   ¤   ¤   ·*/
61d0d8 ¤   ¤   #if HAVE_SHARE_H
355a83 ¤   ¤   ¤   if ( !( flags & kPGPFileOpenLockFile ) )
6871f8 ¤   ¤   ¤   ¤   shFlags |= _SH_DENYNO;
b8be6e ¤   ¤   ¤   else if ( flags & kPGPFileOpenWritePerm )
8d663a ¤   ¤   ¤   ¤   shFlags |= _SH_DENYRW;
bcbb8c ¤   ¤   ¤   else
e131d0 ¤   ¤   ¤   ¤   shFlags |= _SH_DENYWR;
8faf5a
5c8736 ¤   ¤   ¤   fileHandle = sopen( fullPath, oFlags, shFlags,
dfa04a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   _S_IREAD | _S_IWRITE );
7cebf6 ¤   ¤   #else
738c7f ¤   ¤   ¤   fileHandle¤ = open( fullPath, oFlags, _S_IREAD | _S_IWRITE );
c2d656 ¤   ¤   #endif
a11b52 ¤   ¤
b1fff5 ¤   ¤   ¤   /* Free the path buffer regardless */
24fddb ¤   ¤   ¤   PGPFreeData( fullPath);
3daf5a
389edd ¤   ¤   ¤   /* Check for error in sopen */
28489a ¤   ¤   ¤   if ( fileHandle == -1 )
5cf776 ¤   ¤   ¤   {
af7ff6 ¤   ¤   ¤   ¤   if ( errno == EACCES )
ee2925 ¤   ¤   ¤   ¤   ¤   err = kPGPError_FilePermissions;
49ccb5 ¤   ¤   ¤   ¤   else if ( errno == ENOENT )
c1ad5c ¤   ¤   ¤   ¤   ¤   err = kPGPError_FileNotFound;
64fa07 ¤   ¤   ¤   ¤   else
3409f2 ¤   ¤   ¤   ¤   ¤   err = kPGPError_CantOpenFile;
9e1b7c ¤   ¤   ¤   ¤   goto error;
36a3a6 ¤   ¤   ¤   }
91af5a
be4c31 ¤   ¤   ¤   stdIOFile = fdopen( fileHandle, mode );
5a82bf ¤   ¤   ¤   if (stdIOFile == NULL)
--2d5f 000ba3e80884010026b Page 11 of pgpFileRef.c
431b7c ¤   ¤   ¤   ¤   goto error;
070fe4 ¤   ¤   }
ff9371 ¤   }
d3f754 #else¤  /* ] [ */
55c7a1 ¤   {
38e2f8 ¤   ¤   char *¤ ¤   fullPath = NULL;
ba129a #if PGP_UNIX
6dbffa ¤   ¤   mode_t¤ ¤   oldMask;
487454 #endif
44be18 ¤   ¤   err = PFLGetFullPathFromFileSpec(fileRef, &fullPath);
267d98 ¤   ¤   if ( IsntPGPError( err ) )
4e5b34 ¤   ¤   {
71129a #if PGP_UNIX
9cbc19 ¤   ¤   ¤   oldMask = umask(sUnixFileTypeTable[fileType].mask);
fa7454 #endif
1f77b9 ¤   ¤   ¤   stdIOFile = fopen(fullPath, mode);
82af5a
e7fff5 ¤   ¤   ¤   /* Free the path buffer regardless */
a6a1cd ¤   ¤   ¤   PGPFreeData( fullPath );
7caf5a
ab82bf ¤   ¤   ¤   if (stdIOFile == NULL)
5bf776 ¤   ¤   ¤   {
c2c006 ¤   ¤   ¤   ¤   if (errno == EACCES
7e467d #ifdef EROFS
91bc6b ¤   ¤   ¤   ¤   ¤   || errno == EROFS
257454 #endif
2c6fab ¤   ¤   ¤   ¤   ¤   ¤   )
b472c3 ¤   ¤   ¤   ¤   {
ef2925 ¤   ¤   ¤   ¤   ¤   err = kPGPError_FilePermissions;
652613 ¤   ¤   ¤   ¤   }
45d8fd ¤   ¤   ¤   ¤   else if (errno == ENOENT)
cd72c3 ¤   ¤   ¤   ¤   {
5dad5c ¤   ¤   ¤   ¤   ¤   err = kPGPError_FileNotFound;
d52613 ¤   ¤   ¤   ¤   }
87fa07 ¤   ¤   ¤   ¤   else
7472c3 ¤   ¤   ¤   ¤   {
fe09f2 ¤   ¤   ¤   ¤   ¤   err = kPGPError_CantOpenFile;
812613 ¤   ¤   ¤   ¤   }
44a3a6 ¤   ¤   ¤   }
95129a #if PGP_UNIX
490e5f ¤   ¤   ¤   umask(oldMask);
e57454 #endif
d1af5a
e182bf ¤   ¤   ¤   if (stdIOFile == NULL)
d51b7c ¤   ¤   ¤   ¤   goto error;
b80fe4 ¤   ¤   }
ed9371 ¤   }
8bddc8 #endif¤ /* ] PGP_MACINTOSH */
a1af5a
8b14f7 ¤   if ( IsntNull( stdIOFile ) && ( flags & kPGPFileOpenLockFile ) )
0dc7a1 ¤   {
629612 ¤   ¤   err = PFLLockFILE( stdIOFile,
0805bf ¤   ¤   ¤   ¤   ¤   ¤   ···( kPFLFileOpenFlags_LockFile |
42ea48 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·( ( flags & kPGPFileOpenWritePerm )
718742 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ? kPFLFileOpenFlags_ReadWrite
ffc076 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   : kPFLFileOpenFlags_ReadOnly ) ) );
e8be18 ¤   ¤   if ( IsPGPError( err ) )
535b34 ¤   ¤   {
b368cd ¤   ¤   ¤   fclose( stdIOFile );
3f2028 ¤   ¤   ¤   stdIOFile = NULL;
090fe4 ¤   ¤   }
959371 ¤   }
83af5a
7c1b52 ¤   ¤
a060ff error:
9468e4 ¤   if ( IsNull( stdIOFile ) || IsPGPError( err ) )
b2c7a1 ¤   {
447d98 ¤   ¤   if ( IsntPGPError( err ) )
cc7f09 ¤   ¤   ¤   err = kPGPError_CantOpenFile;
829371 ¤   }
97af5a
ba28a1 ¤   *outFile¤   = stdIOFile;
--e06a 001d4b74b3a4010026b Page 12 of pgpFileRef.c
2a67c5 ¤
2e0f1e ¤   /* we should have an error and no file, or no error and a file */
4b900b ¤   pgpAssert( ( IsntPGPError( err ) && IsntNull( *outFile ) ) ||
df595e ¤   ¤   ( IsPGPError( err ) && IsNull( *outFile ) ) );
0867c5 ¤
aa5ea8 ¤   return err;
03efe6 }
fdaf5a
1baf5a
8738e5 /*
52d0ea ·* Due to the way memory is handled on PGP_WIN32 systems with static linking,
612336 ·* fclose must be called from the same library which called fopen.
194088 ·* This function servers that purpose. ·It should be called by external
d12016 ·* libraries and apps to close FILE * handles returned by this module.
36495d ·*/
ffc744 ¤   PGPError
cef5c6 pgpStdIOClose(
88b899 ¤   FILE *¤ ¤   ¤   stdIOFile)
94bb36 {
130a0b ¤   if (fclose (stdIOFile)) {
321a9d ¤   ¤   return kPGPError_FileOpFailed;
d99371 ¤   }
c2151e ¤   return kPGPError_NoErr;
91efe6 }
42af5a
05af5a
7838e5 /*
82e6c5 ·* Local Variables:
6a9b19 ·* tab-width: 4
43e7a4 ·* End:
17b612 ·* vi: ts=4 sw=4
566c42 ·* vim: si
d4495d ·*/
--8709 00074211a034010026c Page 1 of pgpFileRef.h
bc38e5 /*
3e55fc ·* pgpFileRef.h
89c3b8 ·* Platform independent filename handling module
5d775e ·*
babbeb ·* Copyright (C) 1997 Network Associates, Inc. and its affiliates.
8d20c7 ·* All rights reserved
47775e ·*
23ea00 ·* $Id: pgpFileRef.h,v 1.33.4.1.2.1 1998/11/12 03:23:20 heller Exp $
4c495d ·*/
3caf5a
2831db #ifndef Included_pgpFileRef_h¤  /* [ */
5b3c67 #define Included_pgpFileRef_h
b3af5a
83feb2 #include <stdio.h>
6c392c #include "pflTypes.h"
6472de #include "pgpFile.h"
3e3709 #include "pgpFileMod.h"
c62f8d #include "pgpErrors.h"
23af5a
034560 /* This must be kept in sync with the tables in pgpFileRef.c and pgpMacFile.c*/
5e95aa enum PGPFileType_
0cbb36 {
fadc18 ¤   kPGPFileTypeNone,
ecab2e ¤   kPGPFileTypePrefs,
112642 ¤   kPGPFileTypePubRing,
5ff768 ¤   kPGPFileTypePrivRing,
172890 ¤   kPGPFileTypeDetachedSig,
6b069c ¤   kPGPFileTypeRandomSeed,
58eb29 ¤   kPGPFileTypeExportedKeys,
b96a81 ¤   kPGPFileTypeArmorFile,
0c0d3c ¤   kPGPFileTypeEncryptedData,
f2bb73 ¤   kPGPFileTypeGroups,
356df7 ¤   kPGPFileTypeDecryptedText,
bb9327 ¤   kPGPFileTypeDecryptedBin,
376c61 ¤   kPGPFileTypeSignedData,
636445 ¤   kPGPFileTypeNumTypes,
d067c5 ¤
938c96 ¤   PGP_ENUM_FORCE( PGPFileType )
a22fa1 } ;
09d102 PGPENUM_TYPEDEF( PGPFileType_, PGPFileType );
13af5a
1caf5a
937f99 typedef PGPInt16 PGPFileOpenFlags;
0aaf5a
08d370 #define kPGPFileOpenReadPerm¤   ¤   ¤   0x001
6eaec5 #define kPGPFileOpenWritePerm¤  ¤   ¤   0x002
47e8ae #define kPGPFileOpenReadWritePerm¤  ¤   (kPGPFileOpenReadPerm¤  ¤   \
04c42a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFileOpenWritePerm)
f8cf8e #define kPGPFileOpenAppend¤ ¤   ¤   ¤   0x004
5b6de3 #define kPGPFileOpenTruncate¤   ¤   ¤   0x008
c43723 #define kPGPFileOpenCreate¤ ¤   ¤   ¤   0x010
1d8a7f #define kPGPFileOpenTextMode¤   ¤   ¤   0x020¤  /* XXX To be phased out */
6b8316 #define kPGPFileOpenMaybeLocalEncode¤   0x040¤  /* eg, MacBin on Mac */
2b33e1 #define kPGPFileOpenForceLocalEncode¤   0x080¤  /* eg, MacBin on Mac */
5938e5 /*
09148d ·* The following flag modifies one of the two flags above to strip out
69d83d ·* volatile information such as dates, filenames, icon colors, etc.
9609d5 ·* It is not necessarily suitable for recreating a file, and should only
9cf807 ·* be used for detached signatures.
0a495d ·*/
7579b3 #define kPGPFileOpenLocalEncodeHashOnly¤0x100
8f38e5 /*
e41e30 ·* The following flag modifies the behavior of LocalEncode on the
6d6c1c ·* Mac (MacBinary) to accept a CRC of 0 in the header.
e8495d ·*/
df13a4 #define kPGPFileOpenNoMacBinCRCOkay¤¤   0x200
8638e5 /*
7a68a6 ·* The following flag causes additional file locking to be used, if
349992 ·* the normal platform file locking is lacking. ·Currently, this only
ff6b9c ·* affects Un*x systems, which perform no locking by default.
50495d ·*/
74c4bd #define kPGPFileOpenLockFile¤   ¤   ¤   0x400
--762a 0009deea8ae4010026c Page 2 of pgpFileRef.h
e0af5a
142d3b #define kPGPFileOpenStdWriteFlags¤  (kPGPFileOpenWritePerm¤ ¤   ¤   \
6b64d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFileOpenTruncate¤ ¤   ¤   \
f69f6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFileOpenCreate)
3cd018 #define kPGPFileOpenStdAppendFlags¤ (kPGPFileOpenWritePerm¤ ¤   ¤   \
9b804e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFileOpenAppend¤   ¤   ¤   \
709f6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFileOpenCreate)
783286 #define kPGPFileOpenStdUpdateFlags¤ (kPGPFileOpenStdWriteFlags¤ ¤   \
65a8d3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   | kPGPFileOpenReadPerm)
75af5a
3699c6 PGP_BEGIN_C_DECLARATIONS
5baf5a
05c5f9 /* get publicly available routines */
404919 #include "pgpUtilities.h"
69af5a
ecaf5a
72e6d4 PGPMemoryMgrRef¤pgpGetFileRefMemoryMgr( PFLConstFileSpecRef fileRef );
f7af5a
5989ff uchar ·*¤   ¤   pgpExportFileRef(PFLConstFileSpecRef fileRef,
2ee02c ¤   ¤   ¤   ¤   ¤   ¤   size_t *size);
8779e6 PGPError ¤  ¤   pgpImportFileRef( PGPContextRef context,
5fa002 ¤   ¤   ¤   ¤   ¤   uchar const *buffer, size_t size, PFLFileSpecRef *ref );
d1af5a
5238e5 /*
05ba8f ·* pgpGetFileRefName returns a string allocated with pgpContextMemAlloc(),
2edc58 ·* which the caller is responsible for freeing.
3e495d ·*/
3b3a9c char ·*¤¤   ¤   pgpGetFileRefName(PFLConstFileSpecRef fileRef);
691673 PGPError ¤  ¤   pgpSetFileRefName(PFLFileSpecRef fileRef,
537bff ¤   ¤   ¤   ¤   ¤   ¤   char const *newName);
30af5a
27af5a
a2af5a
97bcac PGPError ¤  ¤   pgpCalcFileSize(PFLConstFileSpecRef fileRef,
877f81 ¤   ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags, size_t *fileSize);
dd94aa ¤   ¤   ¤   ¤   ¤   ¤
d1310e PGPError ¤  ¤   pgpCreateFile(PFLConstFileSpecRef fileRef,
59fdcb ¤   ¤   ¤   ¤   ¤   ¤   PGPFileType fileType);
78af5a
523fa2 /* depracated, do *not* use. Use PFLFileSpecRename() */
8679d6 PGPError¤   ¤   pgpRenameFile( PFLConstFileSpecRef oldRef,
7a7e01 ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef¤newRef);
ecaf5a
df38e5 /*
b72c4d ·* Create and open a temporary file in a platform-saavy manner.
bc80e3 ·* The caller is responsible for deleting the file when finished.
16495d ·*/
c5be0e FILE ·*¤¤   ¤   pgpStdIOOpenTempFile( PGPContextRef¤context,
48aca3 ¤   ¤   ¤   ¤   ¤   PFLFileSpecRef *tempFileRef, PGPError *error);
3daf5a
5f26f3 PGPFile ·*¤ ¤   pgpFileRefOpen(
62fa4b ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,
b0367a ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileRef,
81454b ¤   ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags,
b887bc ¤   ¤   ¤   ¤   ¤   ¤   PGPFileType fileType, PGPError *error);
6294aa ¤   ¤   ¤   ¤   ¤   ¤
092c8a PGPFileRead ·*¤ pgpFileRefReadCreate(
77fa4b ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,
1c367a ¤   ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileRef,
a9d631 ¤   ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags, PGPError *error,
e63973 ¤   ¤   ¤   ¤   ¤   ¤   PGPFileDataType¤*fileDataType);
2caf5a
881c0e /* XXX Compatibility routines follow, intended to be phased out */
06af5a
143ebb PGPError¤   ¤   pgpFileRefStdIOOpen(PFLConstFileSpecRef fileRef,
305d1b ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags,
bf71ec ¤   ¤   ¤   ¤   ¤   PGPFileType fileType, FILE **file);
a9ae30 ¤   ¤   ¤   ¤   ¤
a8db74 PGPError ¤  ¤   pgpStdIOClose(FILE *stdIOFile);
c0af5a
3cc2e5 #if 0¤  /* [ */
9daf5a
--f594 001b2b3ca3b4010026c Page 3 of pgpFileRef.h
b9e323 PGPFile *¤  ¤   pgpFileRefReadOpen(PFLConstFileSpecRef fileRef,
d4655b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUICb const *ui, void *ui_arg,
ccac84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPError *error );
51737c PGPFile *¤  ¤   pgpFileRefWriteOpen(PFLConstFileSpecRef fileRef,
4dabdd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFileType fileType,
1f04c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPCFBContext *cfb,
09dc06 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPError *error);
4a63eb PGPFile *¤  ¤   pgpFileRefProcWriteOpen(PFLConstFileSpecRef fileRef,
e7abdd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFileType fileType,
7ad049 ¤   ¤   ¤   ¤   ······¤ ¤   ¤   int (*doClose) (FILE *file, void *arg),
a22868 ¤   ¤   ¤   ¤   ······¤ ¤   ¤   void *arg, PGPError *error);
843167 #endif¤ /* ] */
a9af5a
291254 PGP_END_C_DECLARATIONS
b4af5a
4990a0 #endif¤ /* ] Included_pgpFileRef_h */
60af5a
d238e5 /*
c6e6c5 ·* Local Variables:
d99b19 ·* tab-width: 4
2ae7a4 ·* End:
eab612 ·* vi: ts=4 sw=4
516c42 ·* vim: si
b2495d ·*/
--a891 000657045464010026d Page 1 of pgpFlexFIFO.c
bc38e5 /*
4134c2 ·* pgpFlexFIFO.c
2ed6df ·* Use a memory buffer as a fifo unless it runs out, at which point we
8bdabd ·* switch to a disk file fifo.
a8775e ·*
8dfd95 ·* $Id: pgpFlexFIFO.c,v 1.20 1997/08/27 00:23:18 lloyd Exp $
fa495d ·*/
b9af5a
9be2ff #include "pgpConfig.h"
a3af5a
047df1 #include <stdio.h>¤ /* For BUFSIZ */
06af5a
41abff #if HAVE_UNISTD_H
2dec7b #include <unistd.h>¤/* For unlink() */
a27454 #endif
a1af5a
9aa146 #include "pgpDebug.h"
e6910a #include "pgpFIFO.h"
8d2f8d #include "pgpErrors.h"
580d08 #include "pgpMem.h"
f2d11f #include "pgpUsuals.h"
35c26c #include "pgpContext.h"
c9af5a
67ec9b #if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
85a1d8 #define kPGPFIFOBufSize¤¤   16384
b1db21 #else
fd01d6 #define kPGPFIFOBufSize¤¤   BUFSIZ
f17454 #endif
d7af5a
c938e5 /*
d051e9 ·* Size at which we will switch from byte to disk fifos. ·Will also
bb2311 ·* do so if we run out of memory so set this very large to switch only
d09774 ·* in that case.
b2495d ·*/
8bbe5b #define MAXBYTEFIFOSIZE (48*1024L)¤ /* We might want to adjust this */
a5af5a
8cecd2 PGPFifoDesc const *bf = &pgpByteFifoDesc;
d56d89 PGPFifoDesc const *ff = &pgpFileFifoDesc;
2caf5a
4caeff struct PGPFifoContext {
ad8a97 ¤   PGPContextRef¤  context;
af3240 ¤   PGPFifoContext *bytefifo;
5d0b8c ¤   PGPFifoContext *filefifo;
24bb17 ¤   PGPByte infile;
976afc ¤   size_t bytefifosize;
f7bf8f ¤   size_t maxbytefifosize;
1db44f ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPFifoContext )
a682f7 };
caaf5a
832978 static void
e33f2c flexFifoInit(PGPFifoContext *fifo)
40bb36 {
d03f1c ¤   fifo->bytefifo = NULL;
1a2d3e ¤   fifo->filefifo = NULL;
06f54b ¤   fifo->infile = 0;
2beebc ¤   fifo->bytefifosize = 0;
ef1d48 ¤   fifo->maxbytefifosize = MAXBYTEFIFOSIZE;
5aefe6 }
7daf5a
7f2978 static void
7e9477 flexFifoFlush(PGPFifoContext *fifo)
71bb36 {
f6909f ¤   if (fifo->infile)
d9df72 ¤   ¤   pgpFifoFlush(ff, fifo->filefifo);
c80e24 ¤   else
a80e9b ¤   ¤   pgpFifoFlush(bf, fifo->bytefifo);
4a2ac5 ¤   flexFifoInit(fifo);
b3efe6 }
d1af5a
36598d static PGPSize
26a2cc flexFifoSize(PGPFifoContext const *fifo)
65bb36 {
--3f3d 000c6011b374010026d Page 2 of pgpFlexFIFO.c
cb909f ¤   if (fifo->infile)
080dfc ¤   ¤   return pgpFifoSize(ff, fifo->filefifo);
880e24 ¤   else
9ddc15 ¤   ¤   return pgpFifoSize(bf, fifo->bytefifo);
f8efe6 }
d4af5a
2c859e static PGPFifoContext *
a9e713 flexFifoCreate( PGPContextRef¤  context )
3fbb36 {
ac3566 ¤   PGPFifoContext *fifo;
76af5a
37756b ¤   fifo = (PGPFifoContext *)pgpContextMemAlloc( context,
5e6284 ¤   ¤   sizeof(*fifo), 0 );
3ca652 ¤   if (fifo) {
cbbb7f ¤   ¤   fifo->context¤  = context;
9632fe ¤   ¤   fifo->infile = 0;
0f3916 ¤   ¤   fifo->filefifo = NULL;
26044d ¤   ¤   fifo->bytefifo = pgpFifoCreate( context, bf);
896be6 ¤   ¤   if (!fifo->bytefifo) {
348c0a ¤   ¤   ¤   pgpContextMemFree( context, fifo);
46cf03 ¤   ¤   ¤   return NULL;
bf0fe4 ¤   ¤   }
8943e2 ¤   ¤   fifo->bytefifosize = 0;
dd4fd5 ¤   ¤   fifo->maxbytefifosize = MAXBYTEFIFOSIZE;
919371 ¤   }
fd8722 ¤   return fifo;
32efe6 }
5eaf5a
762978 static void
00df35 flexFifoDestroy(PGPFifoContext *fifo)
97bb36 {
71909f ¤   if (fifo->infile)
743ea6 ¤   ¤   pgpFifoDestroy(ff, fifo->filefifo);
430e24 ¤   else
78ef4f ¤   ¤   pgpFifoDestroy(bf, fifo->bytefifo);
1a041f ¤   pgpContextMemFree( fifo->context, fifo);
f1efe6 }
13af5a
fdaf5a
d95abf static PGPByte const *
02d525 flexFifoPeek(PGPFifoContext *fifo, PGPSize *len)
f5bb36 {
4d909f ¤   if (fifo->infile)
e2a011 ¤   ¤   return pgpFifoPeek(ff, fifo->filefifo, len);
4a0e24 ¤   else
e33e50 ¤   ¤   return pgpFifoPeek(bf, fifo->bytefifo, len);
3eefe6 }
8baf5a
862978 static void
73902f flexFifoSeek(PGPFifoContext *fifo, PGPSize len)
82bb36 {
43909f ¤   if (fifo->infile)
3f3f6b ¤   ¤   pgpFifoSeek(ff, fifo->filefifo, len);
76665a ¤   else {
6ba12a ¤   ¤   pgpFifoSeek(bf, fifo->bytefifo, len);
42d4fc ¤   ¤   fifo->bytefifosize -= len;
f79371 ¤   }
3cefe6 }
97af5a
145d09 static size_t
b9bf11 flexFifoRead(PGPFifoContext *fifo, PGPByte *buf, size_t len)
e0bb36 {
08909f ¤   if (fifo->infile)
c325c1 ¤   ¤   return pgpFifoRead(ff, fifo->filefifo, buf, len);
bd665a ¤   else {
b7e971 ¤   ¤   size_t nread = pgpFifoRead(bf, fifo->bytefifo, buf, len);
b4e332 ¤   ¤   if (nread > 0)
118f64 ¤   ¤   ¤   fifo->bytefifosize -= nread;
28f3fe ¤   ¤   return nread;
e59371 ¤   }
0defe6 }
c6af5a
--5c12 00057c021f74010026d Page 3 of pgpFlexFIFO.c
bc38e5 /*
04c9ea ·* If bytefifo fails to take the requested data, assume that memory is
7911c8 ·* full. ·Switch to using a file fifo and transfer all data from the
ae4735 ·* byte fifo to the file. ·Hopefully this will free up enough memory
7d743b ·* that we can complete.
75775e ·*
80e104 ·* We can also be configured to have a maximum size for the byte fifo
cd1c6f ·* and if we exceed that we will switch over.
6d495d ·*/
2c5d09 static size_t
491c79 flexFifoWrite(PGPFifoContext *fifo, PGPByte const *buf, size_t len)
74bb36 {
8bd390 ¤   PGPByte *xbuf = NULL;
64ac29 ¤   size_t written;
955359 ¤   PGPSize¤n;
77265e ¤   long err;
ef8060 ¤   PGPContextRef¤  ¤   cdkContext;
1067c5 ¤
b3cb62 ¤   pgpAssertAddrValid( fifo, PGPFifoContext );
e1bad7 ¤   cdkContext¤ = fifo->context;
6baf5a
49909f ¤   if (fifo->infile)
81d7a0 ¤   ¤   return pgpFifoWrite(ff, fifo->filefifo, buf, len);
12af5a
347d73 ¤   written = 0;
d3cdf7 ¤   if (fifo->bytefifosize + len <= fifo->maxbytefifosize)
e84f98 ¤   ¤   written = pgpFifoWrite(bf, fifo->bytefifo, buf, len);
9348de ¤   fifo->bytefifosize += written;
89cb9f ¤   if (written < len) {
71a244 ¤   ¤   /* switch to file fifo */
793847 ¤   ¤   if (xbuf == NULL) {
84a411 ¤   ¤   ¤   xbuf = (PGPByte *)pgpContextMemAlloc( cdkContext,
decf4f ¤   ¤   ¤   ¤   kPGPFIFOBufSize * 2, 0);
2bec7f ¤   ¤   ¤   if (xbuf == NULL)
01451b ¤   ¤   ¤   ¤   return kPGPError_OutOfMemory;
860fe4 ¤   ¤   }
d25041 ¤   ¤   /* Try to free up some memory from byte fifo */
95b5a1 ¤   ¤   n = pgpFifoRead(bf, fifo->bytefifo, xbuf, sizeof(xbuf));
4d34ee ¤   ¤   fifo->filefifo = pgpFifoCreate( fifo->context, ff);
93a4ae ¤   ¤   if (!fifo->filefifo) {
0f25a2 ¤   ¤   ¤   if( IsntNull( xbuf ) )
ee380b ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, xbuf);
14f71f ¤   ¤   ¤   pgpFifoDestroy(bf, fifo->bytefifo);
bf7cde ¤   ¤   ¤   return kPGPError_OutOfMemory;
8d0fe4 ¤   ¤   }
d8d178 ¤   ¤   /* Transfer data from byte to file fifo */
584392 ¤   ¤   do {
187c8e ¤   ¤   ¤   pgpAssert (n <= sizeof(xbuf));
683d93 ¤   ¤   ¤   err = (long)pgpFifoWrite(ff, fifo->filefifo, xbuf, n);
c1555a ¤   ¤   ¤   if (err < 0)
eaf776 ¤   ¤   ¤   {
776451 ¤   ¤   ¤   ¤   if( IsntNull( xbuf ) )
6b3b7c ¤   ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, xbuf);
b41876 ¤   ¤   ¤   ¤   return (size_t)err;
61a3a6 ¤   ¤   ¤   }
48e25e ¤   ¤   } while ((n = pgpFifoRead(bf, fifo->bytefifo, xbuf,
7308ae ¤   ¤   ¤   ¤   ¤   ··sizeof(xbuf))) > 0);
3fef4f ¤   ¤   pgpFifoDestroy(bf, fifo->bytefifo);
1e2b34 ¤   ¤   fifo->bytefifo = NULL;
9743e2 ¤   ¤   fifo->bytefifosize = 0;
3c6822 ¤   ¤   fifo->infile = 1;
b164f1 ¤   ¤   written += pgpFifoWrite(ff, fifo->filefifo, buf+written,
7e45cd ¤   ¤   ¤   ¤   ¤   len-written);
db9371 ¤   }
78bdf5 ¤   if( IsntNull( xbuf ) )
f2d934 ¤   ¤   pgpContextMemFree( cdkContext, xbuf);
a6279e ¤   return written;
f2efe6 }
16af5a
d39901 PGPFifoDesc const pgpFlexFifoDesc = {
52096c ¤   "Flex Byte/File Fifo",
57d6b9 ¤   flexFifoCreate,
--a170 00159abfa1c4010026d Page 4 of pgpFlexFIFO.c
507ed9 ¤   flexFifoRead,
c83ea0 ¤   flexFifoWrite,
b64ea4 ¤   flexFifoPeek,
a442d9 ¤   flexFifoSeek,
570480 ¤   flexFifoFlush,
4938ea ¤   flexFifoDestroy,
265b08 ¤   flexFifoSize
5982f7 };
--1466 00036fb014e4010026e Page 1 of pgpMacBinary.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
ef8201 ¤   $Id: pgpMacBinary.c,v 1.20.10.1 1998/11/12 03:23:20 heller Exp $
31f7f7 ____________________________________________________________________________*/
31af5a
00e2ff #include "pgpConfig.h"
0a324c #include <string.h>
1daf5a
b10d08 #include "pgpMem.h"
6e2f8d #include "pgpErrors.h"
2faf5a
d2a9cb #include "pgpIO.h"
16b274 #include "pgpLineEndIO.h"
f9ebac #include "pgpIOUtilities.h"
e23427 #include "pgpFileUtilities.h"
722012 #include "pgpMacBinary.h"
f261a1 #include "pgpMacFileMapping.h"
8e1b42 #include "pgpStrings.h"
ccaf5a
3a3d4b #include "pgpEndianConversion.h"
07af5a
e0af5a
76af5a
18f98f #define RawToUInt16( data )¤PGPEndianToUInt16( kPGPBigEndian, data )
8d93e6 #define RawToUInt32( data )¤PGPEndianToUInt32( kPGPBigEndian, data )
cbaf5a
bc0335 /*____________________________________________________________________________
a4aa3a ¤   Convert the raw bytes of the header into an in-memory structure. ·Fields
25422f ¤   in the structure use the approprite endian-ness.
f867c5 ¤
099a26 ¤   For example, the file type will be big-endian on a Mac and little-endian
74ceb2 ¤   on a PC.
00f7f7 ____________________________________________________________________________*/
4c33c8 ¤   static void
b25e92 sRawDataToHeader(
339c01 ¤   PGPByte const *¤¤   rawData,
0e14f0 ¤   MacBinaryHeader *¤  header
0427e6 ¤   )
06bb36 {
b0d7df ¤   pgpClearMemory( header, sizeof( *header ) );
8567c5 ¤
359318 ¤   header->oldVersion¤ = rawData[ kMacBinaryOffset_Version ];
6867c5 ¤
e3b606 ¤   pgpCopyMemory( &rawData[ kMacBinaryOffset_NameLength ], header->name, 64 );
7367c5 ¤
adec18 ¤   header->info1.fdType¤   =
56bdb0 ¤   ¤   RawToUInt32( &rawData[ kMacBinaryOffset_FileType ] );
cd1b52 ¤   ¤
629ded ¤   header->info1.fdCreator¤=
560e89 ¤   ¤   RawToUInt32( &rawData[ kMacBinaryOffset_FileCreator ] );
211b52 ¤   ¤
b3f8a3 ¤   header->info1.fdFlags¤  =
401e3f ¤   ¤   RawToUInt16( &rawData[ kMacBinaryOffset_FinderFlags ] );
a71b52 ¤   ¤
a10e19 ¤   header->info1.fdLocation.v¤ =
d23539 ¤   ¤   RawToUInt16( &rawData[ kMacBinaryOffset_VPos ] );
731b52 ¤   ¤
56dbe1 ¤   header->info1.fdLocation.h¤ =
4e6690 ¤   ¤   RawToUInt16( &rawData[ kMacBinaryOffset_HPos ] );
601b52 ¤   ¤
5cd4ff ¤   header->info1.fdFldr¤   =
c65d6f ¤   ¤   RawToUInt16( &rawData[ kMacBinaryOffset_Folder ] );
3067c5 ¤
ba212e ¤   header->protectedBit¤   = rawData[ kMacBinaryOffset_ProtectedBit ];
0467c5 ¤
a50de2 ¤   header->zero1¤  ¤   = rawData[ kMacBinaryOffset_Zero1 ];
d367c5 ¤
3662e8 ¤   header->dLength¤¤   =
--42d3 000100de67d4010026e Page 2 of pgpMacBinary.c
565019 ¤   ¤   RawToUInt32( &rawData[ kMacBinaryOffset_DataForkLength ] );
9b67c5 ¤
aaba52 ¤   header->rLength¤¤   =
a6baa3 ¤   ¤   RawToUInt32( &rawData[ kMacBinaryOffset_ResForkLength ] );
ba67c5 ¤
8e5088 ¤   header->creationDate¤   ¤   =
4be5c0 ¤   ¤   RawToUInt32( &rawData[ kMacBinaryOffset_CreationDate ] );
f767c5 ¤
061dbe ¤   header->modificationDate¤   ¤   =
711a17 ¤   ¤   RawToUInt32( &rawData[ kMacBinaryOffset_ModificationDate ] );
6f67c5 ¤
c74c28 ¤   header->crc1¤   ¤   = rawData[ kMacBinaryOffset_crc1 ];
6e0ba9 ¤   header->crc2¤   ¤   = rawData[ kMacBinaryOffset_crc2 ];
d4efe6 }
f9af5a
d7af5a
10af5a
84cbbc ¤   static PGPUInt16
830284 sCalcCRC16Continue(
18969d ¤   PGPUInt16¤  ¤   crc,
46f9ae ¤   const void *¤   data,
644b0e ¤   PGPInt32¤   ¤   len)
b9bb36 {
82c943 ¤   const char *¤   dp¤ = (const char *)data;
9eaf5a
73a8c5 ¤   while(len--)
a9c7a1 ¤   {
546edc ¤   ¤   PGPInt16¤   ¤   i;
2c67c5 ¤
e26ee5 ¤   ¤   crc ^= (PGPUInt16)(*dp++) << 8;
abfad8 ¤   ¤   for (i = 0; i < 8; ++i)
1a5b34 ¤   ¤   {
e7983e ¤   ¤   ¤   if (crc & 0x8000)
f2bdd1 ¤   ¤   ¤   ¤   crc = (crc << 1) ^ 0x1021;
7ebb8c ¤   ¤   ¤   else
2a1a72 ¤   ¤   ¤   ¤   crc <<= 1;
860fe4 ¤   ¤   }
9f9371 ¤   }
1c001d ¤   return(crc);
a2efe6 }
10af5a
14cbbc ¤   static PGPUInt16
82bd3b sCalcCRC16(
fdd4c6 ¤   const void *data, PGPInt32 len)
9dbb36 {
07c5ba ¤   return sCalcCRC16Continue( 0, data, len);
dbefe6 }
7baf5a
b5af5a
090335 /*____________________________________________________________________________
4cf978 ¤   Return TRUE if the raw header bytes are valid (CRC matches)
0bf7f7 ____________________________________________________________________________*/
4d6c2c ¤   static PGPBoolean
6e536e sHeaderIsValid(
72975f ¤   const PGPByte *rawBytes )
7abb36 {
c8ee80 ¤   PGPUInt16¤  crc;
bbcb04 ¤   PGPBoolean¤ isValid¤= FALSE;
7067c5 ¤
cbc59b ¤   /* CRCs don't include themselves */
0c9bd5 ¤   #define kLengthOfDataToCRC¤ ¤   ( kPGPMacBinaryHeaderSize - (2+2) )
a43361 ¤   crc¤= sCalcCRC16( rawBytes, kLengthOfDataToCRC );
3467c5 ¤
070a84 ¤   isValid¤= ( ( crc >> 8) == rawBytes[ kMacBinaryOffset_crc1 ] &&
7a4427 ¤   ¤   (crc & 0xFF) == rawBytes[ kMacBinaryOffset_crc2 ] );
069191 ¤   if ( ! isValid )
17c7a1 ¤   {
067255 ¤   ¤   /* we can be more liberal, but our code always sets the CRC */
f9d3d1 ¤   ¤   /* so we may as well require that the CRC be valid */
5f9371 ¤   }
9367c5 ¤
10195c ¤   return( isValid );
--e8d1 000c7d67a444010026e Page 3 of pgpMacBinary.c
7aefe6 }
46af5a
8eaf5a
090335 /*____________________________________________________________________________
b4ccc4 ¤   Read the header into a structure. ·The struct
1ffac4 ¤   produced is an in-memory representation; not necessarily the exact
85c409 ¤   byte order on disk (primarily for big/little endian reasons, but also
c10b08 ¤   because different compilers on different platforms may pad structures
8c94dc ¤   differently).
f7f7f7 ____________________________________________________________________________*/
6b66dd ¤   static PGPError
0a77af sReadMacBinaryHeader(
ec0a33 ¤   PFLFileSpecRef¤ ¤   spec,
142f22 ¤   MacBinaryHeader *¤  header,
8737d8 ¤   PGPBoolean *¤   ¤   isValid
ab27e6 ¤   )
b9bb36 {
6126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
183605 ¤   PGPIORef¤   io;
0367c5 ¤
2af5d4 ¤   *isValid¤   = FALSE;
8967c5 ¤
282a19 ¤   err¤= PGPOpenFileSpec( spec,
c51193 ¤   ¤   ¤   kPFLFileOpenFlags_ReadOnly, (PGPFileIORef *)&io );
0af1e7 ¤   if ( IsntPGPError( err ) )
07c7a1 ¤   {
9afd00 ¤   ¤   PGPByte¤buffer[ kPGPMacBinaryHeaderSize ];
c01b52 ¤   ¤
d8a697 ¤   ¤   err¤= PGPIORead( io, sizeof( buffer ), buffer, NULL );
7b7d98 ¤   ¤   if ( IsntPGPError( err ) )
be5b34 ¤   ¤   {
3876ff ¤   ¤   ¤   *isValid¤   = sHeaderIsValid( buffer );
7b1d9d ¤   ¤   ¤   /* convert, even if not valid */
3573d8 ¤   ¤   ¤   sRawDataToHeader( buffer, header );
900fe4 ¤   ¤   }
d11b52 ¤   ¤
c7ccb3 ¤   ¤   PGPFreeIO( io );
45871a ¤   ¤   io¤ = NULL;
ab9371 ¤   }
a467c5 ¤
31deb7 ¤   return( err );
c3efe6 }
5baf5a
9caf5a
f3af5a
ad96f8 #if PGP_MACINTOSH¤  /* PGP_MACINTOSH [ */
d3af5a
075a11 #include <Script.h>
e9af5a
291613 #include "pgpFileSpecMac.h"
59bbf4 #include "MacFiles.h"
1a76b7 #include "MacErrors.h"
8a85c2 #include "MacStrings.h"
84af5a
080335 /*____________________________________________________________________________
3f0efb ¤   Mac Version
5967c5 ¤
e4095f ¤   Create a file from the MacBinary original
09f7f7 ____________________________________________________________________________*/
8e2473 ¤   static OSStatus
a2080f sCreateFromMacBinary(
6b6d1f ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr,
0f8a5c ¤   short¤  ¤   ¤   ¤   ¤   fileRef,
ea62f8 ¤   MacBinaryHeader¤const *¤header,
ea6749 ¤   const FSSpec *¤ ¤   ¤   tempSpec )
87bb36 {
eadc42 ¤   OSStatus¤   err;
dc4f27 ¤   CInfoPBRec¤ cpb;
ba67c5 ¤
a4213c ¤   err¤= FSpCreate( tempSpec,
b81315 ¤   ¤   ¤   ¤   ¤   header->info1.fdCreator, header->info1.fdType,
c7550b ¤   ¤   ¤   ¤   ¤   smSystemScript );
--da57 0008a6450694010026e Page 4 of pgpMacBinary.c
2a67c5 ¤
c81622 ¤   if ( IsntErr( err ) && header->dLength != 0 )
b3c7a1 ¤   {
628721 ¤   ¤   short¤  outRef;
8f1b52 ¤   ¤
d6e2bb ¤   ¤   err¤= FSpOpenDF( tempSpec, fsRdWrPerm, &outRef );
f1d798 ¤   ¤   if ( IsntErr( err ) )
555b34 ¤   ¤   {
2c019b ¤   ¤   ¤   err¤= FSCopyBytes( memoryMgr, fileRef, kPGPMacBinaryHeaderSize,
97e068 ¤   ¤   ¤   ¤   ¤   outRef, 0, header->dLength );
e187c7 ¤   ¤   ¤
10f4ed ¤   ¤   ¤   FSClose( outRef );
390fe4 ¤   ¤   }
fa9371 ¤   }
2867c5 ¤
e80c2b ¤   if ( IsntErr( err ) && header->rLength != 0 )
76c7a1 ¤   {
3c8721 ¤   ¤   short¤  outRef;
821b52 ¤   ¤
be9a01 ¤   ¤   err¤= FSpOpenRF( tempSpec, fsRdWrPerm, &outRef );
9bd798 ¤   ¤   if ( IsntErr( err ) )
d95b34 ¤   ¤   {
11da19 ¤   ¤   ¤   err¤= FSCopyBytes( memoryMgr, fileRef,
b32fb6 ¤   ¤   ¤   ¤   ¤   kPGPMacBinaryHeaderSize + header->dLength,
51645a ¤   ¤   ¤   ¤   ¤   outRef, 0, header->rLength );
6087c7 ¤   ¤   ¤
68f4ed ¤   ¤   ¤   FSClose( outRef );
980fe4 ¤   ¤   }
e59371 ¤   }
9e67c5 ¤
8bcfbe ¤   /* set file meta information */
ef5ecc ¤   if ( IsntErr( err ) )
d3c7a1 ¤   {
a3a013 ¤   ¤   err¤= FSpGetCatInfo( tempSpec, &cpb );
5cd94a ¤   ¤   if ( IsntErr( err ))
d05b34 ¤   ¤   {
6a4a19 ¤   ¤   ¤   #define kFinderFlagsIgnoreMask¤ ·\
20ae31 ¤   ¤   ¤   ¤   ( kHasBeenInited | kNameLocked | kIsInvisible | kIsOnDesk )
dd5244 ¤   ¤   ¤   cpbFInfo( &cpb ).fdFlags¤   =
d233bc ¤   ¤   ¤   ¤   header->info1.fdFlags & ~kFinderFlagsIgnoreMask;
4d25a9 ¤   ¤   ¤   cpbFInfo( &cpb ).fdLocation¤= header->info1.fdLocation;
a82b85 ¤   ¤   ¤   ¤
59f6fd ¤   ¤   ¤   cpbModificationDate( &cpb )¤= header->modificationDate;
7c6a9d ¤   ¤   ¤   cpbCreationDate( &cpb )¤¤   = header->creationDate;
242b85 ¤   ¤   ¤   ¤
7be47f ¤   ¤   ¤   err¤= FSpSetCatInfo( tempSpec, &cpb );
8d0fe4 ¤   ¤   }
f79371 ¤   }
a767c5 ¤
8c09b7 ¤   /* cleanup if error */
b77a91 ¤   if ( IsErr( err ) )
60c7a1 ¤   {
f7a15e ¤   ¤   (void)FSpDelete( tempSpec );
489371 ¤   }
3567c5 ¤
f6deb7 ¤   return( err );
fdefe6 }
b5af5a
a687c7 ¤   ¤   ¤
a20335 /*____________________________________________________________________________
f30efb ¤   Mac Version
5df7f7 ____________________________________________________________________________*/
9466dd ¤   static PGPError
d17c8d sDeMacBinarize(
12e316 ¤   PFLFileSpecRef¤ ¤   ¤   ¤   inSpec,
addc2f ¤   MacBinaryHeader const *¤¤   header,
c279ff ¤   PFLFileSpecRef *¤   ¤   ¤   outSpec )
08bb36 {
7526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
771eb6 ¤   FSSpec¤ ¤   fsSpec;
dc67c5 ¤
8a8497 ¤   *outSpec¤   = kInvalidPFLFileSpecRef;
--df9c 000bcd57ee94010026e Page 5 of pgpMacBinary.c
2a67c5 ¤
38cd3e ¤   err¤= PFLGetFSSpecFromFileSpec( inSpec, &fsSpec );
2ef1e7 ¤   if ( IsntPGPError( err ) )
21c7a1 ¤   {
b5126d ¤   ¤   short¤  ¤   fileRef;
01c656 ¤   ¤   OSStatus¤   macErr;
d01b52 ¤   ¤
335c59 ¤   ¤   macErr¤ = FSpOpenDF( &fsSpec, fsRdPerm, &fileRef );
b35eda ¤   ¤   if ( IsntErr( macErr ) )
b75b34 ¤   ¤   {
e79aaa ¤   ¤   ¤   FSSpec¤ tempSpec;
2087c7 ¤   ¤   ¤
0a5352 ¤   ¤   ¤   macErr¤ = FSpGetUniqueSpec( &fsSpec, &tempSpec );
a863b2 ¤   ¤   ¤   if ( IsntErr( macErr ) )
e5f776 ¤   ¤   ¤   {
beb641 ¤   ¤   ¤   ¤   macErr = sCreateFromMacBinary(
581b99 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PFLGetFileSpecMemoryMgr( inSpec ), fileRef,
04869b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   header, &tempSpec );
49a3a6 ¤   ¤   ¤   }
cf87c7 ¤   ¤   ¤
f101e0 ¤   ¤   ¤   FSClose( fileRef );
f027fb ¤   ¤   ¤   fileRef¤= 0;
e887c7 ¤   ¤   ¤
e263b2 ¤   ¤   ¤   if ( IsntErr( macErr ) )
20f776 ¤   ¤   ¤   {
15f7c8 ¤   ¤   ¤   ¤   const unsigned char¤kBinExtension[]¤= "\p.bin";
642b85 ¤   ¤   ¤   ¤
e0a48e ¤   ¤   ¤   ¤   /* delete original and move output into its place */
b1cdba ¤   ¤   ¤   ¤   (void)FSpDelete( &fsSpec );
342b85 ¤   ¤   ¤   ¤
78bafd ¤   ¤   ¤   ¤   if ( PStringHasSuffix( fsSpec.name, kBinExtension, FALSE ) )
3572c3 ¤   ¤   ¤   ¤   {
6b73a3 ¤   ¤   ¤   ¤   ¤   fsSpec.name[ 0 ]¤   -= StrLength( kBinExtension );
86ae30 ¤   ¤   ¤   ¤   ¤
c962f8 ¤   ¤   ¤   ¤   ¤   macErr¤ = FSpGetUniqueSpec( &fsSpec, &fsSpec );
102613 ¤   ¤   ¤   ¤   }
022b85 ¤   ¤   ¤   ¤
14665f ¤   ¤   ¤   ¤   if ( IsntErr( macErr ) )
93eb06 ¤   ¤   ¤   ¤   ¤   macErr¤ = FSpRename( &tempSpec, fsSpec.name );
80a3a6 ¤   ¤   ¤   }
a30fe4 ¤   ¤   }
6a1b52 ¤   ¤
7ca5a0 ¤   ¤   err¤= MacErrorToPGPError( macErr );
7c9371 ¤   }
0467c5 ¤
5af1e7 ¤   if ( IsntPGPError( err ) )
bbc7a1 ¤   {
f24838 ¤   ¤   err¤= PFLNewFileSpecFromFSSpec(
0a9283 ¤   ¤   ¤   PFLGetFileSpecMemoryMgr( inSpec ), &fsSpec, outSpec );
8d9371 ¤   }
7267c5 ¤
90deb7 ¤   return( err );
bfefe6 }
82af5a
62af5a
6fc69d #else¤  /* ] PGP_MACINTOSH [ */
cbaf5a
9aaf5a
3f0335 /*____________________________________________________________________________
25827c ¤   Non-Mac Version
5367c5 ¤
b3f3a3 ¤   Copy from input to output, converting mac line endings to PC line endings.
01f7f7 ____________________________________________________________________________*/
7e66dd ¤   static PGPError
a49971 sCopyAndLineEndConvert(
208299 ¤   PGPIORef¤   ¤   ¤   ¤   inRef,
4fcfe1 ¤   PGPSize¤¤   ¤   ¤   ¤   requestCount,
475867 ¤   PGPIORef¤   ¤   ¤   ¤   outRef)
29bb36 {
10d36c ¤   PGPLineEndIORef¤¤   convertIO¤  = NULL;
9cd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
bcd2c2 ¤   ConvertLineEndType¤ toType;
--54ef 00094dbe89f4010026e Page 6 of pgpMacBinary.c
2a67c5 ¤
ce947a ¤   /* wrap a PGPLineEndIO around the given IO */
57129a #if PGP_UNIX
631c88 ¤   toType¤ = kLFLineEndType;
1714ea #elif PGP_WIN32
ff0f6b ¤   toType¤ = kCRLFLineEndType;
70db21 #else
7b40fc ¤   #error unknown platform
f07454 #endif
688829 ¤   err¤= PGPNewLineEndIO( outRef, FALSE, toType, &convertIO );
7767c5 ¤
50f1e7 ¤   if ( IsntPGPError( err ) )
d7c7a1 ¤   {
498f87 ¤   ¤   err¤= PGPCopyIO( inRef, requestCount, (PGPIORef)convertIO );
57daf6 ¤   ¤   PGPFreeIO( (PGPIORef)convertIO );
ab54d3 ¤   ¤   convertIO¤  = NULL;
289371 ¤   }
d767c5 ¤
e467c5 ¤
7edeb7 ¤   return( err );
10efe6 }
cbaf5a
04af5a
e10335 /*____________________________________________________________________________
c6827c ¤   Non-Mac Version
9ff7f7 ____________________________________________________________________________*/
3866dd ¤   static PGPError
3d080f sCreateFromMacBinary(
ef8299 ¤   PGPIORef¤   ¤   ¤   ¤   inRef,
5662f8 ¤   MacBinaryHeader¤const *¤header,
ea8fed ¤   PFLFileSpecRef¤ ¤   ¤   outSpec )
7fbb36 {
ac61e0 ¤   PGPError¤   err;
9f67c5 ¤
dcc499 ¤   err¤= PFLFileSpecCreate( outSpec );
25aa10 ¤   if ( IsntPGPError( err ) && header->dLength != 0 )
ccc7a1 ¤   {
454007 ¤   ¤   PGPIORef¤   outRef;
9b1b52 ¤   ¤
7d8ac0 ¤   ¤   err¤= PGPOpenFileSpec( outSpec, kPFLFileOpenFlags_ReadWrite,
e35881 ¤   ¤   ¤   ¤   (PGPFileIORef *)&outRef );
f97d98 ¤   ¤   if ( IsntPGPError( err ) )
f05b34 ¤   ¤   {
d15927 ¤   ¤   ¤   err¤= PGPIOSetPos( inRef, kPGPMacBinaryHeaderSize );
a63c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
3cf776 ¤   ¤   ¤   {
a6b5a6 ¤   ¤   ¤   ¤   #define kFileTypeText¤  ((OSType)0x54455854)¤   /* 'TEXT' */
c6f0dc ¤   ¤   ¤   ¤   if ( header->info1.fdType != kFileTypeText )
3572c3 ¤   ¤   ¤   ¤   {
be2dc2 ¤   ¤   ¤   ¤   ¤   err¤= PGPCopyIO( inRef, header->dLength, outRef );
672613 ¤   ¤   ¤   ¤   }
2efa07 ¤   ¤   ¤   ¤   else
af72c3 ¤   ¤   ¤   ¤   {
50cd33 ¤   ¤   ¤   ¤   ¤   err¤= sCopyAndLineEndConvert( inRef,
9bfc87 ¤   ¤   ¤   ¤   ¤   ¤   header->dLength, outRef );
a22613 ¤   ¤   ¤   ¤   }
aca3a6 ¤   ¤   ¤   }
4e87c7 ¤   ¤   ¤
a1aeb7 ¤   ¤   ¤   PGPFreeIO( outRef );
470fe4 ¤   ¤   }
679371 ¤   }
4e67c5 ¤
7cdeb7 ¤   return( err );
2befe6 }
86af5a
f7af5a
c50335 /*____________________________________________________________________________
ec827c ¤   Non-Mac Version
e167c5 ¤
3aaeb4 ¤   Get a unique filename using the baseSpec as a directory specifier and
0322b3 ¤   first choice for file name.
9467c5 ¤
--1668 000c09871f54010026e Page 7 of pgpMacBinary.c
b29d97 ¤   If baseSpec does not exist, then an equivalent spec will be created with
6e7847 ¤   that name.
78f7f7 ____________________________________________________________________________*/
e666dd ¤   static PGPError
9754c3 sGetUniqueTempSpec(
1dd1dd ¤   PFLFileSpecRef¤ ¤   baseSpec,
cdccc0 ¤   PFLFileSpecRef *¤   outSpec)
80bb36 {
b4fb19 ¤   PGPError¤   ¤   err;
df3958 ¤   PFLFileSpecRef¤ tempSpec¤   = NULL;
9567c5 ¤
c71502 ¤   err¤= PFLCopyFileSpec( baseSpec, &tempSpec );
fdf1e7 ¤   if ( IsntPGPError( err ) )
a1c7a1 ¤   {
7c3317 ¤   ¤   static const char ¤ kTempFileBase[]¤¤   ¤   = "temp";
e021cd ¤   ¤   static const char ¤ kTempFileExtension[]¤   = "tmp";
3eebee ¤   ¤   char¤   ¤   tempName[ 64 ];
420919 ¤   ¤   PGPUInt32¤  number¤ = 0;
8f1b52 ¤   ¤
d15c5a ¤   ¤   /* loop until name is unique */
910c19 ¤   ¤   do
e05b34 ¤   ¤   {
19cfb6 ¤   ¤   ¤   PGPBoolean¤ exists;
5d87c7 ¤   ¤   ¤
d48736 ¤   ¤   ¤   err¤= PFLFileSpecExists( tempSpec, &exists );
8a8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
93f622 ¤   ¤   ¤   ¤   break;
b98ebc ¤   ¤   ¤   if ( ! exists )
f5d617 ¤   ¤   ¤   ¤   break; /* good, done */
56c459 ¤   ¤   ¤   ++number;
1487c7 ¤   ¤   ¤
6e63a9 ¤   ¤   ¤   /* generate "temp 1.tmp", "temp 2.tmp", etc */
3968d2 ¤   ¤   ¤   sprintf( tempName, "%s%d.%s",
f0355b ¤   ¤   ¤   ¤   kTempFileBase, (int)number, kTempFileExtension );
43d2cc ¤   ¤   ¤   err¤= PFLSetFileSpecName( tempSpec, tempName );
e18370 ¤   ¤   ¤   if ( IsPGPError( err ) )
9df622 ¤   ¤   ¤   ¤   break;
482b85 ¤   ¤   ¤   ¤
bd0d89 ¤   ¤   } while ( TRUE );
241b52 ¤   ¤
821b52 ¤   ¤
a6be18 ¤   ¤   if ( IsPGPError( err ) )
3c5b34 ¤   ¤   {
a85960 ¤   ¤   ¤   PFLFreeFileSpec( tempSpec );
4d12da ¤   ¤   ¤   tempSpec¤   = kInvalidPFLFileSpecRef;
170fe4 ¤   ¤   }
1b9371 ¤   }
e167c5 ¤
789b0a ¤   *outSpec¤   = tempSpec;
8edeb7 ¤   return( err );
baefe6 }
a2af5a
ecaf5a
f9af5a
96af5a
460335 /*____________________________________________________________________________
27827c ¤   Non-Mac Version
1467c5 ¤
84e293 ¤   Remove the existing file name extension (if any) and add the new one.
f6f7f7 ____________________________________________________________________________*/
f166dd ¤   static PGPError
d96706 sCreateNewName(
88c2c8 ¤   PFLFileSpecRef¤ inSpec,
426b03 ¤   char const *¤   extension,
b41736 ¤   PGPSize¤¤   ¤   maxSize,
a6afc7 ¤   char *¤ ¤   ¤   newName )
8cbb36 {
c99372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
373ce4 ¤   PGPSize¤¤   ¤   newLength;
4aaf5a
1f892f ¤   newName[ 0 ]¤   = '\0';
c067c5 ¤
--c661 0007a842cca4010026e Page 8 of pgpMacBinary.c
f4a75b ¤   err¤= PFLGetFileSpecNameBuffer( inSpec, maxSize, newName );
75f1e7 ¤   if ( IsntPGPError( err ) )
afc7a1 ¤   {
db9cae ¤   ¤   char const *¤   existingExtension;
e467c5 ¤
269fd1 ¤   ¤   existingExtension¤  = PGPGetFileNameExtension( newName );
e31ac2 ¤   ¤   if ( IsntNull( existingExtension ) )
d15b34 ¤   ¤   {
6f9998 ¤   ¤   ¤   newLength¤  = strlen( newName ) -
7b7bd0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   strlen( existingExtension );
a694fd ¤   ¤   ¤   newLength¤  -= 1;¤  /* account for '.' */
dfc62a ¤   ¤   ¤   newName[ newLength ]¤   = '\0';
b97468 ¤   ¤   ¤   existingExtension¤  = NULL;
740fe4 ¤   ¤   }
c967c5 ¤
516376 ¤   ¤   /* add the appropriate extension */
32c3c0 ¤   ¤   strcat( newName, "." );¤
f47970 ¤   ¤   strcat( newName, extension );
319371 ¤   }
af67c5 ¤
14deb7 ¤   return( err );
b0efe6 }
d0af5a
1aaf5a
51af5a
21af5a
030335 /*____________________________________________________________________________
a09f54 ¤   Determine if the existing file name extension is already suitable for
932ce4 ¤   this type of file.
9bf7f7 ____________________________________________________________________________*/
726c2c ¤   static PGPBoolean
d6ea6b sHasSuitableExtensionForType(
637d53 ¤   OSType¤ ¤   ¤   creator,
0ffa46 ¤   OSType¤ ¤   ¤   type,
560ace ¤   PFLFileSpecRef¤ spec )
a6bb36 {
959372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0b90e8 ¤   PGPBoolean¤ ¤   isSuitable¤ = FALSE;
fa6059 ¤   char ¤  ¤   ¤   name[ 512 ];
ce67c5 ¤
ea1990 ¤   err¤= PFLGetFileSpecNameBuffer( spec, sizeof( name ), name );
96f1e7 ¤   if ( IsntPGPError( err ) )
67c7a1 ¤   {
ef0d9c ¤   ¤   char const *extension;
1d1b52 ¤   ¤
576a42 ¤   ¤   extension¤  = PGPGetFileNameExtension( name );
3ae57f ¤   ¤   if ( IsntNull( extension ) )
3e5b34 ¤   ¤   {
f76a45 ¤   ¤   ¤   isSuitable¤ = pgpIsValidExtensionForMacType( creator, type,
d98f2c ¤   ¤   ¤   ¤   ¤   ¤   ¤   extension );
760fe4 ¤   ¤   }
769371 ¤   }
7567c5 ¤
8bf1df ¤   return( isSuitable );
b0efe6 }
a8af5a
c3af5a
330335 /*____________________________________________________________________________
6aa559 ¤   Non-Mac version.
c167c5 ¤
aeb669 ¤   De-MacBinarize the file giving the new file a suitable file name extension
e3f7f7 ____________________________________________________________________________*/
6b66dd ¤   static PGPError
2b7c8d sDeMacBinarize(
5ae316 ¤   PFLFileSpecRef¤ ¤   ¤   ¤   inSpec,
c1dc2f ¤   MacBinaryHeader const *¤¤   header,
e179ff ¤   PFLFileSpecRef *¤   ¤   ¤   outSpec )
82bb36 {
f59372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
4c1b22 ¤   PGPIORef¤   ¤   inRef¤  ¤   = kInvalidPGPIORef;
789138 ¤   PFLFileSpecRef¤ tempSpec¤   = kInvalidPFLFileSpecRef;
7a67c5 ¤
--3dc4 000e3e9e34d4010026e Page 9 of pgpMacBinary.c
6b8497 ¤   *outSpec¤   = kInvalidPFLFileSpecRef;
f567c5 ¤
8bce2f ¤   /* open the MacBinary file */
5cbed9 ¤   err¤= PGPOpenFileSpec( inSpec, kPFLFileOpenFlags_ReadOnly,
558a8e ¤   ¤   ¤   (PGPFileIORef *)&inRef );
89f1e7 ¤   if ( IsntPGPError( err ) )
d2c7a1 ¤   {
a56940 ¤   ¤   /* we'll put the output into a temp file */
742e90 ¤   ¤   err¤= sGetUniqueTempSpec( inSpec, &tempSpec );
4c7d98 ¤   ¤   if ( IsntPGPError( err ) )
f25b34 ¤   ¤   {
292038 ¤   ¤   ¤   err¤= sCreateFromMacBinary( inRef, header, tempSpec );
700fe4 ¤   ¤   }
191b52 ¤   ¤
46e5c7 ¤   ¤   /* all done with input */
b4aadf ¤   ¤   PGPFreeIO( inRef );
1af1e0 ¤   ¤   inRef¤  = NULL;
ea1b52 ¤   ¤
507d98 ¤   ¤   if ( IsntPGPError( err ) )
795b34 ¤   ¤   {
33047d ¤   ¤   ¤   char¤   ¤   ¤   extension[ 3 + 1 ];
6178e1 ¤   ¤   ¤   PGPBoolean¤ ¤   haveExtension;
9a1490 ¤   ¤   ¤   PGPMemoryMgrRef¤memoryMgr;
3779f1 ¤   ¤   ¤   char¤   ¤   ¤   newName[ 512 ];
3a87c7 ¤   ¤   ¤
48e3b5 ¤   ¤   ¤   memoryMgr¤  = PFLGetFileSpecMemoryMgr( inSpec );
b487c7 ¤   ¤   ¤
272ecb ¤   ¤   ¤   /* delete original and move output into its place */
b31cfa ¤   ¤   ¤   (void)PFLFileSpecDelete( inSpec );
4287c7 ¤   ¤   ¤
f9914e ¤   ¤   ¤   if ( sHasSuitableExtensionForType( header->info1.fdCreator,
673041 ¤   ¤   ¤   ¤   ¤   header->info1.fdType, inSpec ) )
50f776 ¤   ¤   ¤   {
e2e790 ¤   ¤   ¤   ¤   haveExtension¤  = FALSE;
d9a3a6 ¤   ¤   ¤   }
98bb8c ¤   ¤   ¤   else
25f776 ¤   ¤   ¤   {
ba9325 ¤   ¤   ¤   ¤   err¤= pgpMapMacCreatorTypeToExtension(
17b411 ¤   ¤   ¤   ¤   ¤   ¤   header->info1.fdCreator,·
406a1d ¤   ¤   ¤   ¤   ¤   ¤   header->info1.fdType, extension );
cc4f5d ¤   ¤   ¤   ¤   /* ok if mapping failed */
0b354b ¤   ¤   ¤   ¤   haveExtension¤  = IsntPGPError( err );
db15f0 ¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
caa3a6 ¤   ¤   ¤   }
3a87c7 ¤   ¤   ¤
abdc2d ¤   ¤   ¤   if ( haveExtension )
87f776 ¤   ¤   ¤   {
9cc2e9 ¤   ¤   ¤   ¤   err¤= sCreateNewName( inSpec,
7cb0d2 ¤   ¤   ¤   ¤   ¤   extension, sizeof( newName ), newName );
f8a3a6 ¤   ¤   ¤   }
40bb8c ¤   ¤   ¤   else
0af776 ¤   ¤   ¤   {
399980 ¤   ¤   ¤   ¤   /* just give it the same name as the original */
3cd8a5 ¤   ¤   ¤   ¤   err¤= PFLGetFileSpecNameBuffer( inSpec,
42a509 ¤   ¤   ¤   ¤   ¤   sizeof( newName ), newName );
19a3a6 ¤   ¤   ¤   }
ee87c7 ¤   ¤   ¤
803c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
f6f776 ¤   ¤   ¤   {
7a0fe4 ¤   ¤   ¤   ¤   /* this changes the name and renames the file */
414688 ¤   ¤   ¤   ¤   err¤= PFLFileSpecRename( tempSpec, newName );
d6a3a6 ¤   ¤   ¤   }
6a144d ¤   ¤   ¤   pgpAssertNoErr( err );
6d0fe4 ¤   ¤   }
969371 ¤   }
ae67c5 ¤
869b0a ¤   *outSpec¤   = tempSpec;
de67c5 ¤
07deb7 ¤   return( err );
8defe6 }
8aaf5a
e3af5a
--8356 0002c36cde54010026e Page 10 of pgpMacBinary.c
9addc8 #endif¤ /* ] PGP_MACINTOSH */
8baf5a
00af5a
4e0335 /*____________________________________________________________________________
3d7f19 ¤   Internal routine to convert a MacBinary format file to something most
1239b3 ¤   appropriate for the local machine.
86f7f7 ____________________________________________________________________________*/
71c744 ¤   PGPError
55d1ed pgpMacBinaryToLocal(
c7583b ¤   PFLFileSpecRef¤ ¤   inSpec,
14b278 ¤   PFLFileSpecRef *¤   outSpec,
6ef4af ¤   PGPUInt32 *¤¤   ¤   macCreator,
21b072 ¤   PGPUInt32 *¤¤   ¤   macType )
c2bb36 {
e29372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
7cf93f ¤   PGPBoolean¤ ¤   ¤   isValid;
35b2ba ¤   MacBinaryHeader¤header;
e067c5 ¤
390069 ¤   (void)inSpec;
0717c5 ¤   (void)outSpec;
b9733a ¤   if ( IsntNull( macCreator ) )
026538 ¤   ¤   *macCreator¤¤   = 0;
2fa98d ¤   if ( IsntNull( macType ) )
fbc3e0 ¤   ¤   *macType¤   ¤   = 0;
4f67c5 ¤
b4254b ¤   err¤= sReadMacBinaryHeader( inSpec, &header, &isValid );
e6f1e7 ¤   if ( IsntPGPError( err ) )
4fc7a1 ¤   {
a0e503 ¤   ¤   if ( isValid )
6c5b34 ¤   ¤   {
cbc314 ¤   ¤   ¤   /* if there's no data fork, don't de-macbinarize it */
b0f9cc ¤   ¤   ¤   if ( header.dLength == 0 )
3832f8 ¤   ¤   ¤   ¤   err¤= kPGPError_NoMacBinaryTranslationAvailable;
250fe4 ¤   ¤   }
110e1d ¤   ¤   else
925b34 ¤   ¤   {
be37ab ¤   ¤   ¤   err¤= kPGPError_NotMacBinary;
ac0fe4 ¤   ¤   }
ca9371 ¤   }
051b52 ¤   ¤
53f1e7 ¤   if ( IsntPGPError( err ) )
4fc7a1 ¤   {
fc9c49 ¤   ¤   if ( IsntNull( macCreator ) )
e86ae3 ¤   ¤   ¤   *macCreator¤= header.info1.fdCreator;
d325f2 ¤   ¤   if ( IsntNull( macType ) )
474cf8 ¤   ¤   ¤   *macType¤   = header.info1.fdType;
ff1b52 ¤   ¤
b9f740 ¤   ¤   err¤= sDeMacBinarize( inSpec, &header, outSpec );
f49371 ¤   }
77deb7 ¤   return( err );
00efe6 }
c7af5a
b7af5a
0aaf5a
3faf5a
99af5a
77af5a
beaf5a
14af5a
0caf5a
f3af5a
49af5a
f7af5a
a6af5a
d6af5a
17af5a
a1af5a
2baf5a
adaf5a
86af5a
efaf5a
2caf5a
--8681 0010eb14b0f4010026e Page 11 of pgpMacBinary.c
e0af5a
1aaf5a
17af5a
78af5a
32af5a
a47e4d /*__Editor_settings____
b0af5a
014126 ¤   Local Variables:
0d7b17 ¤   tab-width: 4
da0e6c ¤   End:
a15f8c ¤   vi: ts=4 sw=4
ad9e9b ¤   vim: si
0ed062 _____________________*/
--3466 0007e5e2fe14010026f Page 1 of pgpMacBinary.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
f6cb90 ¤   $Id: pgpMacBinary.h,v 1.3.24.1 1998/11/12 03:23:21 heller Exp $
c0f7f7 ____________________________________________________________________________*/
c1c3ce #ifndef Included_pgpMacBinary_h¤/* [ */
d00cc4 #define Included_pgpMacBinary_h
0faf5a
bfaf5a
5b0335 /*____________________________________________________________________________
fd8dd6 ¤   'MacBinaryHeader' is defined once for Macintosh and once for other
04dc2f ¤   platforms. ·Because compilers may pad structs differently, only the Mac
784a8a ¤   version is an accurate on-disk description.
bbf7f7 ____________________________________________________________________________*/
19af5a
9eaf5a
02fd29 #if PGP_MACINTOSH /* [ */
1baf5a
e7fa23 #if PRAGMA_ALIGN_SUPPORTED
8daf46 #pragma options align=mac68k
277454 #endif
42af5a
0186e4 typedef struct MacBinaryHeader
8abb36 {
9aed85 ¤   uchar¤  NOT_PART_OF_STRUCT;¤/* NOT part of the struct; used to pad */
9138fa ¤   uchar¤  oldVersion;¤¤   ¤   /* 000: Must be zero for compatibility */
4506f1 ¤   uchar¤  name[64];¤  ¤   ¤   /* 001: Pascal string */
903820 ¤   FInfo¤  info1;¤ ¤   ¤   ¤   /* 065: Original Finder info: */
02cb7c ¤   uchar¤  protectedBit;¤  ¤   /* 081: Low order bit */
4d01a3 ¤   uchar¤  zero1;¤ ¤   ¤   ¤   /* 082: Must be zero for compatibility */
8685bd ¤   long¤   dLength;¤   ¤   ¤   /* 083: Data fork length (in bytes) */
24ec4c ¤   long¤   rLength;¤   ¤   ¤   /* 087: Resource fork length (in bytes) */
5e497b ¤   ulong¤  creationDate;¤  ¤   /* 091: Creation date */
11edd7 ¤   ulong¤  modificationDate;¤  /* 095: Modification date */
f52b77 ¤   short¤  getInfoLength;¤ ¤   /* 099:¤Get info length */
ab2844 ¤   uchar¤  info2;¤ ¤   ¤   ¤   /* 101: Finder flags, low byte */
104e16 ¤   uchar¤  dummy1;
8cd0da ¤   uchar¤  dummy2[18];¤¤   ¤   /* 103: Not used */
3bfbae ¤   uchar¤  dummy3;
53f258 ¤   uchar¤  newVersion;¤¤   ¤   /* 122: Uploading program version number */
6bf8d4 ¤   uchar¤  minimumVersion;¤¤   /* 123: Minimum version number needed */
a157d3 ¤   uchar¤  crc1;
67b8b7 ¤   uchar¤  crc2;
5ec999 ¤   uchar¤  endFiller[2];¤  ¤   /* To pad out to 128 bytes */
198f31 } MacBinaryHeader;
c8af5a
69fa23 #if PRAGMA_ALIGN_SUPPORTED
dc7c46 #pragma options align=reset
4a7454 #endif
51af5a
78af5a
1a68d8 #else¤  /* ][ */
8daf5a
c78c22 /* definitions for non-Mac */
d82f2a typedef struct FInfo
60bb36 {
2386ee ¤   PGPUInt32¤  ¤   fdType;
c8b127 ¤   PGPUInt32¤  ¤   fdCreator;
0725b6 ¤   PGPUInt16¤  ¤   fdFlags;
8b4a89 ¤   struct
7ac7a1 ¤   {
20358c ¤   ¤   PGPInt16¤   v;
92a002 ¤   ¤   PGPInt16¤   h;
38e3b9 ¤   } fdLocation;
a10ee8 ¤   PGPInt16¤   ¤   fdFldr;
314d2a } FInfo;
9faf5a
8686e4 typedef struct MacBinaryHeader
7ebb36 {
--db56 001027d47b44010026f Page 2 of pgpMacBinary.h
5c9124 ¤   /* NOT part of the struct; used to pad */
955ee3 ¤   PGPUInt8¤   NOT_PART_OF_STRUCT;¤¤
dbab4c ¤   PGPUInt8¤   oldVersion;¤
f7f83d ¤   PGPUInt8¤   name[64];
6177a7 ¤   FInfo¤  ¤   info1;
de04c5 ¤   PGPUInt8¤   protectedBit;¤
5fb724 ¤   PGPUInt8¤   zero1;
d66501 ¤   PGPInt32¤   dLength;
6e3e8a ¤   PGPInt32¤   rLength;
af098e ¤   PGPUInt32¤  creationDate;
b6a175 ¤   PGPUInt32¤  modificationDate;
a488ab ¤   PGPInt16¤   getInfoLength;
3af192 ¤   PGPUInt8¤   info2;
5f50a9 ¤   PGPUInt8¤   dummy1;
8e4cb9 ¤   PGPUInt8¤   dummy2[18];
95e511 ¤   PGPUInt8¤   dummy3;
cab065 ¤   PGPUInt8¤   newVersion;
1c1a55 ¤   PGPUInt8¤   minimumVersion;
56cd5f ¤   PGPUInt8¤   crc1;
62223b ¤   PGPUInt8¤   crc2;
3e2a4c ¤   PGPUInt8¤   endFiller[2];
6b8f31 } MacBinaryHeader;
89af5a
b5af5a
313167 #endif¤ /* ] */
bdaf5a
c8af5a
a6af5a
6a94b7 #define kMacBinaryOffset_Version¤   ¤   ¤   ¤   0
2c0fe3 #define kMacBinaryOffset_NameLength¤¤   ¤   ¤   1
6c8f56 #define kMacBinaryOffset_Name¤  ¤   ¤   ¤   ¤   2
537288 #define kMacBinaryOffset_FInfo¤ ¤   ¤   ¤   ¤   65
f5b9f4 #define kMacBinaryOffset_FileType¤  ¤   ¤   ¤   kMacBinaryOffset_FInfo
bc09c6 #define kMacBinaryOffset_FileCreator¤   ¤   ¤   69
fe295f #define kMacBinaryOffset_FinderFlags¤   ¤   ¤   73
8ff125 #define kMacBinaryOffset_VPos¤  ¤   ¤   ¤   ¤   75
77927d #define kMacBinaryOffset_HPos¤  ¤   ¤   ¤   ¤   77
f82bb9 #define kMacBinaryOffset_Folder¤¤   ¤   ¤   ¤   79
9009ae #define kMacBinaryOffset_ProtectedBit¤  ¤   ¤   81
0ec1a4 #define kMacBinaryOffset_Zero1¤ ¤   ¤   ¤   ¤   82
d57082 #define kMacBinaryOffset_DataForkLength¤¤   ¤   83
b1760c #define kMacBinaryOffset_ResForkLength¤ ¤   ¤   87
2756e6 #define kMacBinaryOffset_CreationDate¤  ¤   ¤   91
69d2f9 #define kMacBinaryOffset_ModificationDate¤  ¤   95
368c26 #define kMacBinaryOffset_Zero2¤ ¤   ¤   ¤   ¤   99
9e21dd #define kMacBinaryOffset_crc1¤  ¤   ¤   ¤   ¤   124
8cd5c9 #define kMacBinaryOffset_crc2¤  ¤   ¤   ¤   ¤   125
b6b3e2 #define kMacBinaryOffset_EndFiller¤ ¤   ¤   ¤   126
f8af5a
4db6e5 #define kPGPMacBinaryHeaderSize¤¤   128
51af5a
e3af5a
66af5a
65af5a
2a1ac0 PGPError¤   pgpMacBinaryToLocal( PFLFileSpecRef inPGPSpec,
2473e1 ¤   ¤   ¤   ¤   PFLFileSpecRef * outPGPSpec,
1fe19a ¤   ¤   ¤   ¤   PGPUInt32 * macCreator, PGPUInt32 * macTypeCode );
3b67c5 ¤
df67c5 ¤
dec114 #endif /* ] Included_pgpMacBinary_h */
b5af5a
ceaf5a
957e4d /*__Editor_settings____
43af5a
a74126 ¤   Local Variables:
cf7b17 ¤   tab-width: 4
340e6c ¤   End:
895f8c ¤   vi: ts=4 sw=4
f89e9b ¤   vim: si
10d062 _____________________*/
02af5a
--24dc 00001c1745b40100270 Page 1 of pgpMacFile.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
2171c4 ¤   $Id: pgpMacFile.c,v 1.56.4.1.2.1 1998/11/12 03:23:22 heller Exp $
6cf7f7 ____________________________________________________________________________*/
22e2ff #include "pgpConfig.h"
1eaf5a
a42363 #include <Devices.h>
9f49ca #include <Files.h>
b75a11 #include <Script.h>
d6af5a
2e495d #include <errno.h>
08feb2 #include <stdio.h>
50af5a
d2fd29 #if PGP_MACINTOSH /* [ */
29af5a
e9b2bf #include <Errors.h>
daaf5a
0185c2 #include "MacStrings.h"
62bbf4 #include "MacFiles.h"
2c675a #include "pgpTypes.h"
0472de #include "pgpFile.h"
0fbdfd #include "pgpMacFile.h"
9752af #include "pgpMacUtils.h"
cda4b2 #include "pgpFileRef.h"
9b894b #include "pgpFileSpec.h"
a73709 #include "pgpFileMod.h"
6d0859 #include "pgpCFB.h"
9a0d08 #include "pgpMem.h"
122f8d #include "pgpErrors.h"
d7d11f #include "pgpUsuals.h"
1cc26c #include "pgpContext.h"
f161a1 #include "pgpMacFileMapping.h"
38af5a
ffaf5a
c9af5a
e2a789 /* XXX Is this stuff still necessary? */
3aed48 #define CHANGED¤¤   0x0200¤ /* ---- --1- ---- ---- */
88af5a
3d8f59 #define kFinderFlagsIgnore¤ (kIsOnDesk | kHasBeenInited | CHANGED )
17af5a
9bfa23 #if PRAGMA_ALIGN_SUPPORTED
2eaf46 #pragma options align=mac68k
ba7454 #endif
38af5a
d086e4 typedef struct MacBinaryHeader
b9bb36 {
78f3c2 ¤   uchar¤  filler;
5c38fa ¤   uchar¤  oldVersion;¤¤   ¤   /* 000: Must be zero for compatibility */
7a06f1 ¤   uchar¤  name[64];¤  ¤   ¤   /* 001: Pascal string */
fa3820 ¤   FInfo¤  info1;¤ ¤   ¤   ¤   /* 065: Original Finder info: */
bc7a11 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ¤   File type (long) */
839ce4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ¤   File creator (long) */
c5f484 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ¤   Flags (word, low byte must be zero) */
08111c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ¤   File's location (Point) */
56f9b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*¤ ¤   File's window (short) */
89cb7c ¤   uchar¤  protectedBit;¤  ¤   /* 081: Low order bit */
1201a3 ¤   uchar¤  zero1;¤ ¤   ¤   ¤   /* 082: Must be zero for compatibility */
3085bd ¤   long¤   dLength;¤   ¤   ¤   /* 083: Data fork length (in bytes) */
21ec4c ¤   long¤   rLength;¤   ¤   ¤   /* 087: Resource fork length (in bytes) */
af497b ¤   ulong¤  creationDate;¤  ¤   /* 091: Creation date */
0aedd7 ¤   ulong¤  modificationDate;¤  /* 095: Modification date */
962b77 ¤   short¤  getInfoLength;¤ ¤   /* 099:¤Get info length */
9b2844 ¤   uchar¤  info2;¤ ¤   ¤   ¤   /* 101: Finder flags, low byte */
db4e16 ¤   uchar¤  dummy1;
f5d0da ¤   uchar¤  dummy2[18];¤¤   ¤   /* 103: Not used */
99fbae ¤   uchar¤  dummy3;
6df258 ¤   uchar¤  newVersion;¤¤   ¤   /* 122: Uploading program version number */
01f8d4 ¤   uchar¤  minimumVersion;¤¤   /* 123: Minimum version number needed */
--02ae 0005050580b40100270 Page 2 of pgpMacFile.c
8b57d3 ¤   uchar¤  crc1;
61b8b7 ¤   uchar¤  crc2;
9dc999 ¤   uchar¤  endFiller[2];¤  ¤   /* To pad out to 128 bytes */
0aaf5a
cbb901 ¤   DEBUG_STRUCT_CONSTRUCTOR( MacBinaryHeader )
ed8f31 } MacBinaryHeader;
42af5a
43fa23 #if PRAGMA_ALIGN_SUPPORTED
b37c46 #pragma options align=reset
f07454 #endif
54af5a
840335 /*____________________________________________________________________________
e6bab9 ¤   A MacFileTypeEntry maps a pgp file type to a mac creator/type pair.
41f7f7 ____________________________________________________________________________*/
75f920 typedef struct MacFileTypeEntry
54bb36 {
10b485 ¤   PGPFileType¤¤   pgpFileType;
54a5ca ¤   OSType¤ ¤   ¤   creator;
bf22df ¤   OSType¤ ¤   ¤   type;
1d4f9b } MacFileTypeEntry;
3caf5a
2bac9c static MacFileTypeEntry¤sMacFileTypeTable[kPGPFileTypeNumTypes] =
62bb36 {
c9f870 ¤   { kPGPFileTypePrefs,
fab55c ¤   ¤   kPGPMacFileCreator_Keys, kPGPMacFileType_Preferences },
ea1b52 ¤   ¤
8c0fbb ¤   { kPGPFileTypePubRing,
75028a ¤   ¤   kPGPMacFileCreator_Keys, kPGPMacFileType_PubRing },
7b1b52 ¤   ¤
d39d0f ¤   { kPGPFileTypePrivRing,
9a5844 ¤   ¤   kPGPMacFileCreator_Keys, kPGPMacFileType_PrivRing },
a31b52 ¤   ¤
7239fd ¤   { kPGPFileTypeDetachedSig,
ee08ed ¤   ¤   kPGPMacFileCreator_Tools, kPGPMacFileType_DetachedSig },
131b52 ¤   ¤
b1e29d ¤   { kPGPFileTypeRandomSeed,
a697eb ¤   ¤   kPGPMacFileCreator_Keys, kPGPMacFileType_RandomSeed },
7c1b52 ¤   ¤
8053db ¤   { kPGPFileTypeExportedKeys,
912e35 ¤   ¤   kPGPMacFileCreator_Keys, kPGPMacFileType_ExportedKeys },
771b52 ¤   ¤
e37d52 ¤   { kPGPFileTypeArmorFile,
afa964 ¤   ¤   kPGPMacFileCreator_Tools, kPGPMacFileType_ArmorFile },
1b1b52 ¤   ¤
d9d919 ¤   { kPGPFileTypeEncryptedData,
fefb9e ¤   ¤   kPGPMacFileCreator_Tools, kPGPMacFileType_EncryptedData },
92af5a
0d00db ¤   { kPGPFileTypeGroups,
f467cd ¤   ¤   kPGPMacFileCreator_Keys, kPGPMacFileType_Groups },
0aaf5a
1cbfce ¤   /* XXX: The below should be user preferences */
01ddff ¤   /* but these are the defaults */
77b9d2 ¤   { kPGPFileTypeDecryptedText,
ab57db ¤   ¤   kPGPMacFileCreator_DecryptedText, kPGPMacFileType_DecryptedText },
121b52 ¤   ¤
112bd5 ¤   { kPGPFileTypeDecryptedBin,
2adf6f ¤   ¤   kPGPMacFileCreator_DecryptedBinary, kPGPMacFileType_DecryptedBinary },
211b52 ¤   ¤
2c8860 ¤   { kPGPFileTypeSignedData,
ee8bda ¤   ¤   kPGPMacFileCreator_Tools, kPGPMacFileType_SignedData }
d882f7 };
8e6567 #define kNumMacFileTypeEntries¤ \
1ebf73 ¤   ( sizeof( sMacFileTypeTable ) / sizeof( sMacFileTypeTable[ 0 ] ) )
4aaf5a
d8af5a
18af5a
6eaf5a
deaf5a
f5a708 #define kPGPMacRead¤¤   ¤   0x01L
244726 #define kPGPMacWrite¤   ¤   0x02L
38b058 #define kPGPMacBinMode¤ ¤   0x04L
50e649 /* For write mode only: whether we should check */
--28a9 000cef5705e40100270 Page 3 of pgpMacFile.c
c59bfc #define kPGPCheckMacBin¤¤   0x08L
1d4d9c /* Strip out volatile information for detached sig */
b5afdc #define kPGPMacBinHashOnly¤ 0x10L
5463d9 /* CRC 0 in MacBin header is okay */
2d4522 #define kPGPNoMacBinCRCOkay¤0x20L
20af5a
37a3c9 /* This is the private data for macfiles */
996442 typedef struct MacFile
e7bb36 {
752334 ¤   ulong¤  ¤   ¤   flags;
dbc6c3 ¤   short¤  ¤   ¤   dataRef, resRef;
8ace5f ¤   long¤   ¤   ¤   dataOffset, resOffset, totalSize;
edaae1 ¤   long¤   ¤   ¤   filePos;
05e59f ¤   PGPFileError¤   err;
391765 ¤   PGPError¤   ¤   error;
b8c61c ¤   PFLFileSpecRef¤ ¤   fileRef;
af5e3c ¤   PGPFileType¤¤   fileType;
f6c4bd ¤   MacBinaryHeader¤macBinHeader;
21ba92 ¤   DEBUG_STRUCT_CONSTRUCTOR( MacFile )
fbd579 } MacFile;
ecaf5a
2af233 static PGPError PrepareToWrite(PGPFile *file, PGPBoolean autoMapMacTypes );
793dec static PGPError SetFileInfo( PGPFile *file);
d8af5a
5e33c8 ¤   static void
346fc1 macSetError(
025370 ¤   PGPFile *¤  ¤   file,
cce0b7 ¤   PGPError¤   ¤   code)
96bb36 {
625ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
10af5a
a451a6 ¤   pgpAssert( pgpContextIsValid( file->context ) );
2aaf5a
7152ef ¤   mf->err.f = file;
a31e67 ¤   mf->err.fpos = mf->filePos;
f10276 ¤   mf->error = mf->err.error = code;
f04ff2 ¤   mf->err.syserrno = 0;
06efe6 }
efaf5a
40d140 ¤   static OSErr
efa641 macFileReadFork(
ee5370 ¤   PGPFile *¤  ¤   file,
d080cd ¤   short¤  ¤   ¤   refNum,
0cf752 ¤   long¤   ¤   ¤   forkOffset,
57e2bc ¤   long¤   ¤   ¤   forkEnd,
435c93 ¤   long *¤ ¤   ¤   sizeLeftPtr,
918c32 ¤   void **¤¤   ¤   ptrPtr)
88bb36 {
965ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
886f3a ¤   long¤   ¤   chunkSize;
f306b9 ¤   OSErr¤  ¤   err = noErr;
c5af5a
9751a6 ¤   pgpAssert( pgpContextIsValid( file->context ) );
83af5a
647da5 ¤   if (mf->filePos >= forkOffset &&
168b6d ¤   ¤   (chunkSize = pgpMin(*sizeLeftPtr, forkEnd - mf->filePos)) > 0)
7dc7a1 ¤   {
0dea20 ¤   ¤   UInt32¤ actualCount;
56af5a
d4572b ¤   ¤   err¤= FSReadAtOffset( refNum, mf->filePos - forkOffset,
3efcca ¤   ¤   ¤   ¤   ¤   chunkSize, *ptrPtr, &actualCount, FALSE );
4daf5a
6b2fe4 ¤   ¤   mf->filePos¤¤   += actualCount;
f1b82e ¤   ¤   *(Ptr *)ptrPtr¤ += actualCount;
f85eb7 ¤   ¤   *sizeLeftPtr¤   -= actualCount;
626966 ¤   ¤   if ((mf->flags & kPGPMacBinMode) && err == eofErr)
605b34 ¤   ¤   {
037aad ¤   ¤   ¤   /*
ee416a ¤   ¤   ¤   ·* Clear any memory which was beyond the EOF. ·This is expected
8c32f4 ¤   ¤   ¤   ·* in MacBinary because each fork is padded to a multiple of
b11bed ¤   ¤   ¤   ·* 128-bytes.
ce8753 ¤   ¤   ¤   ·*/
--9220 000d151fce440100270 Page 4 of pgpMacFile.c
a6f5e9 ¤   ¤   ¤   chunkSize¤  -= actualCount;
d44575 ¤   ¤   ¤   pgpClearMemory((uchar *)*ptrPtr, chunkSize);
1ce6ae ¤   ¤   ¤   mf->filePos += chunkSize;
72c02e ¤   ¤   ¤   *(Ptr *)ptrPtr += chunkSize;
517c63 ¤   ¤   ¤   *sizeLeftPtr -= chunkSize;
d3d5ab ¤   ¤   ¤   err = noErr;
280fe4 ¤   ¤   }
30873d ¤   ¤   else if (err != noErr)
ee4669 ¤   ¤   ¤   macSetError(file, kPGPError_FileOpFailed);
879371 ¤   }
a25ea8 ¤   return err;
b4efe6 }
55af5a
22d8bc ¤   static size_t
ae88b2 macFileRead(
f4f419 ¤   void *¤ ¤   ¤   ptr,
f939e0 ¤   size_t¤ ¤   ¤   size,
092dc8 ¤   PGPFile *¤  ¤   file)
eebb36 {
815ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
6a7227 ¤   long¤   ¤   sizeLeft = (long)size;
626f3a ¤   long¤   ¤   chunkSize;
f514d9 ¤   OSErr¤  ¤   result = noErr;
2baf5a
194127 ¤   pgpAssert(mf->filePos >= 0);
aaaf5a
e4375b ¤   if (!(mf->flags & kPGPMacRead))
1bc7a1 ¤   {
b994bd ¤   ¤   macSetError(file, kPGPError_IllegalFileOp);
4fbbde ¤   ¤   return 0;
4a9371 ¤   }
c8af5a
4d7ddf ¤   /* Handle portion in the MacBinary header, if any */
1ac703 ¤   chunkSize¤  = pgpMin(sizeLeft, mf->dataOffset - mf->filePos);
9919b3 ¤   if ( chunkSize > 0 )
5ec7a1 ¤   {
be5f25 ¤   ¤   pgpCopyMemory( ((uchar *)&mf->macBinHeader) + 1 + mf->filePos,
0910a4 ¤   ¤   ¤   ¤   ¤   ¤   ptr, chunkSize);
7d09dd ¤   ¤   mf->filePos += chunkSize;
6a1f58 ¤   ¤   ptr = (void *)((Ptr)ptr + chunkSize);
a8484d ¤   ¤   sizeLeft -= chunkSize;
239371 ¤   }
4faf5a
626438 ¤   /* Handle portion in the data fork, if any */
1e757f ¤   if (result == noErr && sizeLeft > 0)
de13a5 ¤   ¤   result = macFileReadFork(file, mf->dataRef, mf->dataOffset,
39f075 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mf->resOffset, &sizeLeft, &ptr);
7aaf5a
10d8af ¤   /*
17ae23 ¤   ·* Handle zeroing the first 128 bytes of the resource fork,
56d2aa ¤   ·* but only if kPGPMacBinHashOnly is set.
8ea4e3 ¤   ·*/
bb418b ¤   chunkSize = pgpMin(sizeLeft,
afcaaf ¤   ¤   ¤   pgpMin(mf->resOffset + 128, mf->totalSize) - mf->filePos);
2175a6 ¤   if (result == noErr
857a68 ¤   ¤   ¤   && (mf->flags & kPGPMacBinMode) && (mf->flags & kPGPMacBinHashOnly)
d8054f ¤   ¤   ¤   && ( chunkSize > 0 ))
e6c7a1 ¤   {
7a6239 ¤   ¤   pgpClearMemory(ptr, chunkSize);
0609dd ¤   ¤   mf->filePos += chunkSize;
981f58 ¤   ¤   ptr = (void *)((Ptr)ptr + chunkSize);
ce484d ¤   ¤   sizeLeft -= chunkSize;
2b9371 ¤   }
b6af5a
c772c4 ¤   /* Handle portion in the resource fork, if any */
40420e ¤   if (result == noErr && sizeLeft > 0 && (mf->flags & kPGPMacBinMode))
f23469 ¤   ¤   result = macFileReadFork(file, mf->resRef, mf->resOffset,
5ebb24 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mf->totalSize, &sizeLeft, &ptr);
a1af5a
56c6b6 ¤   return (size_t)(size - sizeLeft);
eaefe6 }
d1af5a
--4a17 000853c22e140100270 Page 5 of pgpMacFile.c
1dd140 ¤   static OSErr
6ba539 macFileWriteFork(
9f5370 ¤   PGPFile *¤  ¤   file,
c680cd ¤   short¤  ¤   ¤   refNum,
97f752 ¤   long¤   ¤   ¤   forkOffset,
bbf906 ¤   long¤   ¤   ¤   forkEnd,¤   /* Ignored unless kPGPMacBinMode flag set */
2a6f86 ¤   long¤   ¤   ¤   forkLen,¤   /* Ignored unless kPGPMacBinMode flag set */
415c93 ¤   long *¤ ¤   ¤   sizeLeftPtr,
b7a141 ¤   void const **¤  ptrPtr)
d0bb36 {
2d5ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
286f3a ¤   long¤   ¤   chunkSize;
e214d9 ¤   OSErr¤  ¤   result = noErr;
b1af5a
a1460c ¤   chunkSize = *sizeLeftPtr;
04aa7d ¤   if (mf->flags & kPGPMacBinMode)
c5389e ¤   ¤   chunkSize = pgpMin(chunkSize, forkEnd - mf->filePos);
f7af5a
b28721 ¤   if (mf->filePos >= forkOffset && chunkSize > 0)
e8c7a1 ¤   {
f63616 ¤   ¤   IOParam¤¤   pb;
c8af5a
a78327 ¤   ¤   pb.ioRefNum¤¤   = refNum;
e73503 ¤   ¤   pb.ioBuffer¤¤   = (Ptr)*ptrPtr;
318ddc ¤   ¤   pb.ioPosMode¤   = fsFromStart;
e5ed87 ¤   ¤   pb.ioPosOffset¤ = mf->filePos - forkOffset;
7f8704 ¤   ¤   pb.ioReqCount¤  = chunkSize;
c66f28 ¤   ¤   if (mf->flags & kPGPMacBinMode)
8d162d ¤   ¤   ¤   pb.ioReqCount = pgpMin(pb.ioReqCount, forkLen - pb.ioPosOffset);
a79588 ¤   ¤   result¤ = PBWriteSync((ParmBlkPtr)&pb);
cb7ae0 ¤   ¤   mf->filePos¤¤   += chunkSize;
911429 ¤   ¤   *(Ptr *)ptrPtr¤ += chunkSize;
133402 ¤   ¤   *sizeLeftPtr¤   -= chunkSize;
e359f2 ¤   ¤   if (result != noErr)
094669 ¤   ¤   ¤   macSetError(file, kPGPError_FileOpFailed);
5e9371 ¤   }
6957f5 ¤   if (mf->totalSize < mf->filePos)
5044c2 ¤   ¤   mf->totalSize = mf->filePos;
655d73 ¤   return result;
3befe6 }
0daf5a
37d8bc ¤   static size_t
cee782 macFileWrite(
e4a2ac ¤   void const *¤   ptr,
1939e0 ¤   size_t¤ ¤   ¤   size,
ee2dc8 ¤   PGPFile *¤  ¤   file)
f4bb36 {
275ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
d67227 ¤   long¤   ¤   sizeLeft = (long)size;
046f3a ¤   long¤   ¤   chunkSize;
56ab46 ¤   OSErr¤  ¤   macErr = noErr;
44af5a
d44127 ¤   pgpAssert(mf->filePos >= 0);
a57c55 ¤   pgpAssert( ( mf->flags & kPGPMacWrite) != 0 );
95bb4b ¤   if (!(mf->flags & kPGPMacWrite))
f2c7a1 ¤   {
dfd5e7 ¤   ¤   macSetError(file, kPGPError_FileLocked);
91bbde ¤   ¤   return 0;
3b9371 ¤   }
b9af5a
187ddf ¤   /* Handle portion in the MacBinary header, if any */
87c703 ¤   chunkSize¤  = pgpMin(sizeLeft, mf->dataOffset - mf->filePos);
4ebe02 ¤   if ( chunkSize > 0)
aac7a1 ¤   {
14df1d ¤   ¤   pgpAssert(mf->filePos + chunkSize <= 128);
0b7bba ¤   ¤   pgpCopyMemory(ptr, ((uchar *)&mf->macBinHeader) + 1 + mf->filePos,
02f6d0 ¤   ¤   ¤   ¤   ¤   ¤   chunkSize);
e309dd ¤   ¤   mf->filePos += chunkSize;
de1f58 ¤   ¤   ptr = (void *)((Ptr)ptr + chunkSize);
82484d ¤   ¤   sizeLeft -= chunkSize;
055218 ¤   ¤   if (mf->totalSize < mf->filePos)
85412f ¤   ¤   ¤   mf->totalSize = mf->filePos;
--4236 00080a7b0a040100270 Page 6 of pgpMacFile.c
a19371 ¤   }
93af5a
ce6438 ¤   /* Handle portion in the data fork, if any */
bbe6d8 ¤   if (macErr == noErr && sizeLeft > 0)
87c7a1 ¤   {
c2f0bc ¤   ¤   if ( IsPGPError( PrepareToWrite(file, TRUE ) ) )
441a3b ¤   ¤   ¤   return( 0 );
de87c7 ¤   ¤   ¤
8cad8a ¤   ¤   macErr = macFileWriteFork(file, mf->dataRef, mf->dataOffset,
53e1c0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mf->resOffset, mf->macBinHeader.dLength,
f5f1ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &sizeLeft, &ptr);
f49371 ¤   }
b2af5a
0d72c4 ¤   /* Handle portion in the resource fork, if any */
2873cc ¤   if (macErr == noErr &&
bdaee2 ¤   ¤   sizeLeft > 0 &&
d89c1d ¤   ¤   (mf->flags & kPGPMacBinMode))
57c7a1 ¤   {
92e822 ¤   ¤   macErr = macFileWriteFork(file, mf->resRef, mf->resOffset,
4ab4f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   mf->totalSize, mf->macBinHeader.rLength,
49f1ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &sizeLeft, &ptr);
5b9371 ¤   }
2aaf5a
b1c6b6 ¤   return (size_t)(size - sizeLeft);
33efe6 }
faaf5a
7266dd ¤   static PGPError
23dda2 macFileFlush(
dc2dc8 ¤   PGPFile *¤  ¤   file)
65bb36 {
015ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
4b4ce2 ¤   IOParam¤¤   pb;
55af5a
acc079 ¤   pb.ioRefNum = mf->dataRef;
f4d968 ¤   PBFlushFileSync((ParmBlkPtr)&pb);
b80eed ¤   pb.ioRefNum = mf->resRef;
b3d968 ¤   PBFlushFileSync((ParmBlkPtr)&pb);
8a151e ¤   return kPGPError_NoErr;
c8efe6 }
86af5a
5966dd ¤   static PGPError
092a96 macFileClose(
2f2dc8 ¤   PGPFile *¤  ¤   file)
54bb36 {
c45ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
35e9fa ¤   PGPContextRef¤  cdkContext;
69af5a
2ec8f4 ¤   pgpAssertAddrValid( file, PGPFile );
1a94b2 ¤   cdkContext¤ = file->context;
0d3b14 ¤   pgpAssert( pgpContextIsValid( cdkContext ) );
fcaf5a
2756f0 ¤   if ( ( mf->flags & kPGPMacWrite) != 0 )
e9c7a1 ¤   {
0934c1 ¤   ¤   PrepareToWrite(file, TRUE );
489371 ¤   }
7267c5 ¤
7b62db ¤   if (mf->dataRef > 0)
6770b2 ¤   ¤   FSClose(mf->dataRef);
642c39 ¤   if (mf->resRef > 0)
ae67f3 ¤   ¤   FSClose(mf->resRef);
5eac2a ¤   SetFileInfo(file);
fed9a1 ¤   PFLFreeFileSpec(mf->fileRef);
b06173 ¤   pgpClearMemory((void *)mf, sizeof(*mf));
2d2f44 ¤   pgpContextMemFree( cdkContext, mf);
553ed5 ¤   pgpContextMemFree( cdkContext, file);
44151e ¤   return kPGPError_NoErr;
32efe6 }
4caf5a
076d4d ¤   static long
b2dd05 macFileTell(
002dc8 ¤   PGPFile *¤  ¤   file)
80bb36 {
--3a3e 0002c5fdd8a40100270 Page 7 of pgpMacFile.c
665ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
46af5a
5fc1fc ¤   return mf->filePos;
1aefe6 }
18af5a
6b66dd ¤   static PGPError
07b4b2 macFileSeek(
3e5370 ¤   PGPFile *¤  ¤   file,
997ed7 ¤   long¤   ¤   ¤   offset,
d16f32 ¤   int¤¤   ¤   ¤   whence)
d4bb36 {
a45ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
fdaf5a
e1b28b ¤   switch (whence)
5ec7a1 ¤   {
3c9a49 ¤   ¤   case SEEK_SET:
2a6b67 ¤   ¤   ¤   /* offset is correct, as is */
c1cdcb ¤   ¤   ¤   break;
353b71 ¤   ¤   case SEEK_CUR:
a7c36a ¤   ¤   ¤   offset += mf->filePos;
b4cdcb ¤   ¤   ¤   break;
245011 ¤   ¤   case SEEK_END:
a8194d ¤   ¤   ¤   offset += mf->totalSize;
43cdcb ¤   ¤   ¤   break;
b89371 ¤   }
7aaf5a
724b02 ¤   if (offset < 0 || offset > mf->totalSize)
2bc7a1 ¤   {
b0574e ¤   ¤   macSetError(file, kPGPError_FileOpFailed);
361a9d ¤   ¤   return kPGPError_FileOpFailed;
f69371 ¤   }
fdaf5a
fc97f7 ¤   mf->filePos = offset;
63151e ¤   return kPGPError_NoErr;
e9efe6 }
96af5a
126c2c ¤   static PGPBoolean
4be3a7 macFileEof(
188f97 ¤   PGPFile const *¤file)
d7bb36 {
575ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
7caf5a
76d8af ¤   /*
0d654e ¤   ·* XXX This will always return TRUE when writing files.
282978 ¤   ·* ····Is that semantically correct?
52a4e3 ¤   ·*/
b41a4d ¤   return mf->filePos >= mf->totalSize;
0cefe6 }
75af5a
ac6d4d ¤   static long
858e4f macFileSizeAdvise(
cf8f97 ¤   PGPFile const *¤file)
e3bb36 {
7f5ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
44af5a
dc77d2 ¤   return mf->totalSize;
a1efe6 }
9eaf5a
2d7bfc ¤   static PGPFileError const *
149c78 macFileError(
378f97 ¤   PGPFile const *¤file)
b1bb36 {
ad5ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
a3af5a
96a4a2 ¤   if (mf->error != kPGPError_NoErr)
5b6df5 ¤   ¤   return &mf->err;
5d0e24 ¤   else
7d7ed2 ¤   ¤   return NULL;
75efe6 }
6daf5a
df33c8 ¤   static void
2cf533 macFileClearError(
--b116 000f147f3d740100270 Page 8 of pgpMacFile.c
e52dc8 ¤   PGPFile *¤  ¤   file)
68bb36 {
a45ca0 ¤   MacFile *¤  mf = (MacFile *)file->priv;
ebaf5a
fa845e ¤   mf->error = kPGPError_NoErr;
5befe6 }
89af5a
a366dd ¤   static PGPError
c064ec macFileWrite2Read(
dc2dc8 ¤   PGPFile *¤  ¤   file)
b0bb36 {
4702fc ¤   macSetError(file, kPGPError_IllegalFileOp);
635fd1 ¤   return kPGPError_IllegalFileOp;
32efe6 }
23af5a
954a24 ¤   static PGPCFBContext *
02423d macFileCfb(
f68f97 ¤   PGPFile const *¤file)
c9bb36 {
11c763 ¤   (void)file;¤/* Quiet compiler warning */
3476d4 ¤   /* XXX: I'm not really sure what should be done here */
763f59 ¤   return NULL;
a4efe6 }
7faf5a
25adac #ifndef __powerc
aaaf5a
be4223 static ushort asm CalcCRC16Contin(ushort start, const void *data, long len)
b2bb36 {
7d2112 ¤   fralloc +
846da5 ¤   move.l¤ D3, -(SP)
e94fea ¤   move.w¤ #0x1021, D3
547168 ¤   clr.l¤  D0
f7a8d6 ¤   move.w¤ start, D0
8d13ff ¤   move.l¤ data, A0
a14766 ¤   move.l¤ len, D2
fd0191 ¤   bra¤¤   Loop1
0a3f88 Loop0:
f3da88 ¤   move.b¤ (A0)+, D1
d9e41c ¤   lsl.w¤  #8, D1
a00229 ¤   eor.w¤  D1, D0
800845 ¤   moveq¤  #7, D1
40fad9 ShiftLoop0:
3ed8b7 ¤   lsl.w¤  #1, D0
5e0192 ¤   bcc¤¤   ShiftLoop1
020a7f ¤   eor.w¤  D3, D0
0fa005 ShiftLoop1:
56cab9 ¤   dbra¤   D1, ShiftLoop0
0b6554 Loop1:
777822 ¤   dbra¤   D2, Loop0
8a6ed1 ¤   move.l¤ (SP)+, D3
a683f8 ¤   frfree
618f76 #if GENERATINGCFM || defined(__CFM68K__)
8881df ¤   rtd¤¤   #12
a8db21 #else
3b68ac ····rts
d77454 #endif
ecefe6 }
6daf5a
f8609f static uchar asm CalcChecksum8Contin(uchar start, const void *data, long len)
16bb36 {
c2aac2 ¤   FRALLOC¤+
1cabed ¤   CLR.L¤  D0
f5a6aa ¤   MOVE.B¤ start, D0
b28aea ¤   MOVE.L¤ data, A0
bf9943 ¤   MOVE.L¤ len, D1
573a3e ¤   BRA¤¤   Loop1
a13f88 Loop0:
5e86b3 ¤   ADD.B¤  (A0)+, D0
286554 Loop1:
215c30 ¤   DBRA¤   D1, Loop0
02aad1 ¤   FRFREE
f18f76 #if GENERATINGCFM || defined(__CFM68K__)
--0864 000dfeac14840100270 Page 9 of pgpMacFile.c
3381df ¤   rtd¤¤   #12
c1db21 #else
1168ac ····rts
757454 #endif
5befe6 }
25af5a
c4ace4 static ulong asm CalcCRC32(const void *data, long len)
eebb36 {
db4e9f ¤   fralloc¤+
3d13ff ¤   move.l¤ data, A0
387168 ¤   clr.l¤  D0
c26d0e ¤   move.l¤ len, D1
d89418 ¤   lsr.l¤  #2, D1
820191 ¤   bra¤¤   Loop1
3e3f88 Loop0:
0d6a9d ¤   rol.l¤  #1, D0
137dce ¤   add.l¤  (A0)+, D0
376554 Loop1:
42ae25 ¤   dbra¤   D1, Loop0
db3281 ¤   moveq¤  #3, D2
026d0e ¤   move.l¤ len, D1
3435bd ¤   and.l¤  D2, D1
f2ae8f ¤   lsl.w¤  D2, D1
c842d8 ¤   clr.l¤  D2
d325c0 ¤   not.l¤  D2
6ad190 ¤   lsr.l¤  D1, D2
bd25c0 ¤   not.l¤  D2
548668 ¤   and.l¤  (A0), D2
826a9d ¤   rol.l¤  #1, D0
563ed2 ¤   add.l¤  D2, D0
7783f8 ¤   frfree
5e8f76 #if GENERATINGCFM || defined(__CFM68K__)
35950c ¤   rtd¤¤   #8
4adb21 #else
9868ac ····rts
207454 #endif
8fefe6 }
7daf5a
b3db21 #else
b1af5a
3c7539 static ushort CalcCRC16Contin(ushort crc, const void *data, long len)
eabb36 {
911421 ¤   const char *dp=(const char *)data;
3e65d8 ¤   short i;
8caf5a
e5a8c5 ¤   while(len--)
55c7a1 ¤   {
49fcde ¤   ¤   crc ^= (ushort)(*dp++) << 8;
06fad8 ¤   ¤   for (i = 0; i < 8; ++i)
3b5b34 ¤   ¤   {
9e983e ¤   ¤   ¤   if (crc & 0x8000)
93bdd1 ¤   ¤   ¤   ¤   crc = (crc << 1) ^ 0x1021;
63bb8c ¤   ¤   ¤   else
641a72 ¤   ¤   ¤   ¤   crc <<= 1;
e40fe4 ¤   ¤   }
929371 ¤   }
db001d ¤   return(crc);
5befe6 }
3caf5a
4b8526 static uchar CalcChecksum8Contin(uchar start, const void *data, long len)
69bb36 {
a158c5 ¤   const char *dp=(char *)data;
42af5a
1ea8c5 ¤   while(len--)
bb9cfe ¤   ¤   start+=*dp++;
7b04f1 ¤   return start;
37efe6 }
00af5a
dac094 static ulong CalcCRC32(const void *data, register long len)
1fbb36 {
7d83ab ¤   const ulong *dp=(const ulong *)data;
dfd884 ¤   ulong crc=0, x;
--cee5 000f2e9de6340100270 Page 10 of pgpMacFile.c
dfd299 ¤   long len2;
78e850 ¤   ulong highSet;
64af5a
fed2bf ¤   len2=len;
4975a8 ¤   len>>=2;
e9e854 ¤   while(--len>=0)
b7c7a1 ¤   {
6e2ac1 ¤   ¤   highSet=(crc & 0x80000000);
3f4e92 ¤   ¤   crc<<=1;
7c92fd ¤   ¤   if(highSet)
e9c4b5 ¤   ¤   ¤   crc|=1;
5893a2 ¤   ¤   crc+=*dp++;
629371 ¤   }
68402c ¤   x=3;
984bd8 ¤   len2 &=x;
ebc074 ¤   len2<<=x;
5aaf48 ¤   x=0;
e79f24 ¤   x=~x;
50d44d ¤   x>>=len2;
449f24 ¤   x=~x;
407153 ¤   x &= *dp;
91a13d ¤   highSet=(crc & 0x80000000);
76fb03 ¤   crc<<=1;
bc058e ¤   if(highSet)
1553c6 ¤   ¤   crc|=1;
2d96a0 ¤   crc+=x;
b2ba79 ¤   return crc;
64efe6 }
9faf5a
5f7454 #endif
58af5a
bf9248 static uchar CalcChecksum8(const void *data, long len)
5fbb36 {
09c55d ¤   return CalcChecksum8Contin(0, data, len);
45efe6 }
27af5a
7d429a static ushort CalcCRC16(const void *data, long len)
3ebb36 {
82ae5b ¤   return CalcCRC16Contin(0, data, len);
a6efe6 }
baaf5a
1338e5 /*
4d217c ·* This routine is called each time before writing to an actual fork. ·If
ff04c1 ·* the kPGPCheckMacBin flag is set, it determines whether or not it's a
ff222c ·* valid MacBinary header. ·If so, it creates the file and opens both the
bc2a7c ·* data and resource forks. ·Otherwise it creates and opens the data fork,
8ea702 ·* and writes false header information to the data fork, using whatever
d29072 ·* hints it can find to create the file with the correct type and creator.
fa495d ·*/
9c66dd ¤   static PGPError
ffc3ed PrepareToWrite(
4b5370 ¤   PGPFile *¤  ¤   file,
9c48ad ¤   PGPBoolean¤ ¤   autoMapMacTypes )
e7bb36 {
cdb1d4 ¤   MacFile *¤  ¤   mf = (MacFile *)file->priv;
186f85 ¤   FSSpec¤ ¤   ¤   spec;
143bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
781d51 ¤   OSErr¤  ¤   ¤   macResult;
dbc3d4 ¤   long¤   ¤   ¤   length;
75af5a
fb49da ¤   pgpAssert( (mf->flags & kPGPMacWrite) != 0 );
d4bb4b ¤   if (!(mf->flags & kPGPMacWrite))
74b840 ¤   ¤   return kPGPError_NoErr;
a9af5a
7dc66a ¤   if (mf->flags & kPGPCheckMacBin)
58c7a1 ¤   {
4919e6 ¤   ¤   mf->flags &= ~(kPGPMacBinMode | kPGPCheckMacBin);
7fe075 ¤   ¤   if (mf->totalSize >= 126 && mf->macBinHeader.oldVersion == 0 &&
061c2f ¤   ¤   ¤   ¤   ¤   mf->macBinHeader.minimumVersion <= 129 &&
0c673f ¤   ¤   ¤   ¤   ¤   (mf->macBinHeader.info1.fdFlags & 0xFF) == 0 &&
c5e38f ¤   ¤   ¤   ¤   ¤   mf->macBinHeader.zero1 == 0 &&
f2dd11 ¤   ¤   ¤   ¤   ¤   mf->macBinHeader.name[0] < 64)
--6169 00037b8665b40100270 Page 11 of pgpMacFile.c
e35b34 ¤   ¤   {
9d4b4d ¤   ¤   ¤   ushort¤ ¤   crc;
edaf5a
d6678b ¤   ¤   ¤   pgpAssert(sizeof(crc) == 2);
0480f9 ¤   ¤   ¤   pgpCopyMemory(&mf->macBinHeader.crc1, &crc, sizeof(crc));
aae657 ¤   ¤   ¤   if (crc == CalcCRC16((uchar *)&mf->macBinHeader + 1, 124)
564b3f ¤   ¤   ¤   ¤   ¤   || ((mf->flags & kPGPNoMacBinCRCOkay) && crc == 0))
c6f776 ¤   ¤   ¤   {
3a2c1f ¤   ¤   ¤   ¤   mf->flags ¤ ¤   |= kPGPMacBinMode;
39f8a7 ¤   ¤   ¤   ¤   file->dataType ¤= kPGPFileDataType_Binary;
cea3a6 ¤   ¤   ¤   }
f50fe4 ¤   ¤   }
ca9371 ¤   }
ddaf5a
26a31a ¤   if (mf->dataRef != 0)
4fb840 ¤   ¤   return kPGPError_NoErr;
24af5a
8ffe53 ¤   if ((err = PFLGetFSSpecFromFileSpec(mf->fileRef, &spec)) != kPGPError_NoErr)
3e97ed ¤   ¤   goto error;
beaf5a
46aa7d ¤   if (mf->flags & kPGPMacBinMode)
43c7a1 ¤   {
0e1da5 ¤   ¤   /* XXX Reconsider using a different file type for this */
8d0c2a ¤   ¤   macResult = FSpCreate( &spec,
01d9c7 ¤   ¤   ¤   pgpGetMacFileCreatorFromPGPFileType( kPGPFileTypeDecryptedBin ),
836a07 ¤   ¤   ¤   pgpGetMacFileTypeFromPGPFileType( kPGPFileTypeDecryptedBin ),
df2a26 ¤   ¤   ¤   smSystemScript);
8fa72e ¤   ¤   if ( IsPGPError( macResult ) )
5bff06 ¤   ¤   ¤   goto macError;
ffaf5a
bf6014 ¤   ¤   if ((macResult = FSpOpenDF(&spec, fsWrPerm, &mf->dataRef)) != noErr)
11ff06 ¤   ¤   ¤   goto macError;
daaf5a
40a43a ¤   ¤   if ((macResult = FSpOpenRF(&spec, fsWrPerm, &mf->resRef)) != noErr)
36ff06 ¤   ¤   ¤   goto macError;
78af5a
4ff870 ¤   ¤   mf->dataOffset = 128;
bf7b6c ¤   ¤   mf->resOffset = mf->dataOffset +
28ec52 ¤   ¤   ¤   ¤   ¤   ¤   (mf->macBinHeader.dLength + 127) & ~127L;
073ad5 ¤   ¤   mf->totalSize = mf->resOffset +
8ea3ce ¤   ¤   ¤   ¤   ¤   ¤   (mf->macBinHeader.rLength + 127) & ~127L;
9b9371 ¤   }
4c0e24 ¤   else
c4c7a1 ¤   {
8b1e9c ¤   ¤   OSType¤ ¤   ¤   creator;
52ab8b ¤   ¤   OSType¤ ¤   ¤   type;
55af5a
1e0962 ¤   ¤   if ( autoMapMacTypes )
7b5b34 ¤   ¤   {
cd4563 ¤   ¤   ¤   err¤= pgpMapFileNameToMacCreatorType( spec.name,
4d87a9 ¤   ¤   ¤   ¤   ¤   &creator, &type );
4694aa ¤   ¤   ¤   ¤   ¤   ¤
3c8370 ¤   ¤   ¤   if ( IsPGPError( err ) )
a5f776 ¤   ¤   ¤   {
5cda23 ¤   ¤   ¤   ¤   err¤= pgpMapFileDataToMacCreatorType(
dbea1b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ((uchar *)&mf->macBinHeader) + 1,
56187d ¤   ¤   ¤   ¤   ¤   ¤   ¤   &creator, &type );
68a3a6 ¤   ¤   ¤   }
1d0fe4 ¤   ¤   }
3caf5a
94bd9a ¤   ¤   if ( IsPGPError( err ) || ! autoMapMacTypes )
885b34 ¤   ¤   {
cc2cfa ¤   ¤   ¤   /* if no mapping, use default types */
4ebb53 ¤   ¤   ¤   creator¤= pgpGetMacFileCreatorFromPGPFileType( mf->fileType );
db9814 ¤   ¤   ¤   type¤   = pgpGetMacFileTypeFromPGPFileType( mf->fileType );
c09d94 ¤   ¤   ¤   err¤¤   = noErr;
cd0fe4 ¤   ¤   }
74af5a
592519 ¤   ¤   macResult = FSpCreate( &spec, creator,
0c7cbf ¤   ¤   ¤   ¤   ¤   type, smSystemScript);
42a72e ¤   ¤   if ( IsPGPError( macResult ) )
37ff06 ¤   ¤   ¤   goto macError;
--1184 0006dde875740100270 Page 12 of pgpMacFile.c
e0af5a
ab6014 ¤   ¤   if ((macResult = FSpOpenDF(&spec, fsWrPerm, &mf->dataRef)) != noErr)
21ff06 ¤   ¤   ¤   goto macError;
48af5a
af02f6 ¤   ¤   mf->dataOffset = mf->resOffset = 0;
beaf5a
a3d087 ¤   ¤   length = mf->totalSize;
dd69f5 ¤   ¤   if ((macResult = FSWrite(mf->dataRef, &length,
6e5b5e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (Ptr)&mf->macBinHeader + 1)) != noErr)
fdff06 ¤   ¤   ¤   goto macError;
ce9371 ¤   }
e4af5a
86151e ¤   return kPGPError_NoErr;
a30e56 macError:
46c71a ¤   err = pgpErrorFromMacError(macResult, kPGPError_FileOpFailed);
ca60ff error:
ed2125 ¤   macSetError(file, err);
0b5ea8 ¤   return err;
53efe6 }
a9af5a
9338e5 /*
7db8b0 ·* This routine is called after closing a MacBinary file for writing. ·It
a44f2e ·* sets the finder information including type and creator.
da495d ·*/
1b66dd ¤   static PGPError
a3d56f SetFileInfo(
2e2dc8 ¤   PGPFile *¤  ¤   file)
a1bb36 {
96abb8 ¤   const MacFile *¤mf = (MacFile *)file->priv;
5b6f85 ¤   FSSpec¤ ¤   ¤   spec;
be1903 ¤   CInfoPBRec¤ ¤   cpb;
a8c389 ¤   FInfo¤  ¤   ¤   fInfo;
bfaf5a
b55313 ¤   if (!(mf->flags & kPGPMacWrite) || !(mf->flags & kPGPMacBinMode))
70b840 ¤   ¤   return kPGPError_NoErr;
2aaf5a
7d3c73 ¤   if (PFLGetFSSpecFromFileSpec(mf->fileRef, &spec) != kPGPError_NoErr)
2797ed ¤   ¤   goto error;
80af5a
694b21 ¤   cpbCreationDate( &cpb )¤¤   = mf->macBinHeader.creationDate;
70b4fc ¤   cpbModificationDate( &cpb )¤= mf->macBinHeader.modificationDate;
e6af5a
b1d8b9 ¤   fInfo¤  ¤   ¤   ¤   = mf->macBinHeader.info1;
af7b8d ¤   fInfo.fdFlags ¤ ¤   &= 0xFF00;
f29217 ¤   fInfo.fdFlags ¤ ¤   |= mf->macBinHeader.info2;
278891 ¤   fInfo.fdFlags¤  ¤   &= ~kFinderFlagsIgnore;
098e66 ¤   fInfo.fdLocation.h¤ = 0;
d8e513 ¤   fInfo.fdLocation.v¤ = 0;
48cd5d ¤   fInfo.fdFldr ¤  ¤   = 0;
1d2ca7 ¤   cpbFInfo( &cpb )¤   = fInfo;
e6a940 ¤   if ( FSpSetCatInfo( &spec, &cpb ) != noErr)
6697ed ¤   ¤   goto error;
2faf5a
ff151e ¤   return kPGPError_NoErr;
36af5a
3260ff error:
8bb553 ¤   /* XXX Improve error reporting */
5e8ffc ¤   macSetError(file, kPGPError_FileOpFailed);
9d5b6e ¤   return kPGPError_FileOpFailed;
0defe6 }
b0af5a
ec38e5 /*
1f93ad ·* It should be noted that writing to MacBinary files won't work if seeking
8ae347 ·* is used in certain ways. ·The MacBinary header only interpreted the first
db962d ·* time data is written past the first 128 bytes, and then the fork lengths
3c8795 ·* and offsets are fixed and immutable. ·This could be fixed at some point,
2993db ·* but there's no need for it now.
48775e ·*
2eeaac ·* The filename used to create the file is always the <fileRef> passed in,
d6f9ca ·* not the name in the MacBinary header.
9f495d ·*/
6d7078 ¤   PGPFile *
--d223 0003873c1b740100270 Page 13 of pgpMacFile.c
f16701 pgpFileRefMacWriteOpen(
92f3cb ¤   PGPContextRef¤  ¤   ¤   cdkContext,
95b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
deeda8 ¤   PGPFileType¤¤   ¤   fileType,
d6afa5 ¤   PGPFileOpenFlags¤   flags,
da6bae ¤   PGPError *¤ ¤   ¤   errorCode)
45bb36 {
ffb839 ¤   PGPFile *¤  ¤   file = NULL;
ef159b ¤   MacFile *¤  ¤   mf = NULL;
c56f85 ¤   FSSpec¤ ¤   ¤   spec;
683bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
ef36b0 ¤   PGPMemoryMgrRef¤memoryMgr¤  = pgpGetFileRefMemoryMgr( fileRef );
9caf5a
308e06 ¤   if ((file = (PGPFile *)PGPNewData( memoryMgr,
5baeb7 ¤   ¤   sizeof(*file), kPGPMemoryMgrFlags_Clear)) == NULL)
5bc7a1 ¤   {
c7bce1 ¤   ¤   err = kPGPError_OutOfMemory;
f197ed ¤   ¤   goto error;
c49371 ¤   }
d694d9 ¤   file->context¤  = cdkContext;
0c06ad ¤   file->dataType ¤= kPGPFileDataType_Unknown;
4caf5a
4f4679 ¤   if ((mf = (MacFile *)PGPNewData( memoryMgr,
ba7397 ¤   ¤   sizeof(*mf), kPGPMemoryMgrFlags_Clear)) == NULL)
36c7a1 ¤   {
981140 ¤   ¤   PGPFreeData( file );
6dbce1 ¤   ¤   err = kPGPError_OutOfMemory;
cf97ed ¤   ¤   goto error;
ba9371 ¤   }
06af5a
488aa7 ¤   err = PFLCopyFileSpec(fileRef, &mf->fileRef );
19fe53 ¤   if ((err = PFLGetFSSpecFromFileSpec(mf->fileRef, &spec)) != kPGPError_NoErr)
8997ed ¤   ¤   goto error;
a6dc5d ¤   mf->fileType = fileType;
c3af5a
edd7f1 ¤   /* Try to delete the file first, in case it already exists */
bea23a ¤   /* XXX Maybe we should check the error, and/or truncate the file instead */
9fed38 ¤   FSpDelete( &spec );
80af5a
f78056 ¤   pgpAssert(sizeof(mf->macBinHeader) >= 129);
7818fc ¤   pgpAssert((flags & kPGPFileOpenLocalEncodeHashOnly) == 0);
09af5a
f47db2 ¤   mf->flags = kPGPMacWrite;
4caf5a
df1fd6 ¤   if (flags & (kPGPFileOpenMaybeLocalEncode | kPGPFileOpenForceLocalEncode))
35c7a1 ¤   {
742b14 ¤   ¤   mf->flags |= kPGPCheckMacBin;
b95737 ¤   ¤   if (flags & kPGPFileOpenNoMacBinCRCOkay)
f39c00 ¤   ¤   ¤   mf->flags |= kPGPNoMacBinCRCOkay;
6937ab ¤   ¤   mf->dataOffset = mf->resOffset = 128;
109371 ¤   }
e30e24 ¤   else
7602f6 ¤   ¤   mf->dataOffset = mf->resOffset = 0;
91af5a
73b13b ¤   mf->dataRef = mf->resRef = 0;
8c51c1 ¤   mf->totalSize = 0;
b323f5 ¤   mf->filePos = 0;
edaf5a
553e8c ¤   file->priv = mf;
10114e ¤   file->read¤ ¤   ¤   = macFileRead;
6d44ef ¤   file->write¤¤   ¤   = macFileWrite;
5ab167 ¤   file->flush¤¤   ¤   = macFileFlush;
1e0a3e ¤   file->close¤¤   ¤   = macFileClose;
9c8980 ¤   file->tell¤ ¤   ¤   = macFileTell;
f1bd3a ¤   file->seek¤ ¤   ¤   = macFileSeek;
c452a3 ¤   file->eof¤  ¤   ¤   = macFileEof;
b69e43 ¤   file->sizeAdvise¤   = macFileSizeAdvise;
d24559 ¤   file->error¤¤   ¤   = macFileError;
f86350 ¤   file->clearError¤   = macFileClearError;
b9f57c ¤   file->write2read¤   = macFileWrite2Read;
abba06 ¤   file->cfb¤  ¤   ¤   = macFileCfb;
38af5a
--96bf 000275b86da40100270 Page 14 of pgpMacFile.c
ebe218 ¤   if ( !( mf->flags & kPGPCheckMacBin) )
1cc7a1 ¤   {
869ab5 ¤   ¤   if ((err = PrepareToWrite(file, FALSE )) != kPGPError_NoErr)
5ded19 ¤   ¤   ¤   goto error;
b89371 ¤   }
61af5a
9a28f6 ¤   return file;
e660ff error:
6fd877 ¤   if (mf != NULL)
b4c7a1 ¤   {
7f8332 ¤   ¤   if (mf->fileRef != NULL)
490a3c ¤   ¤   ¤   PFLFreeFileSpec(mf->fileRef);
b9a722 ¤   ¤   pgpContextMemFree( cdkContext, mf);
109371 ¤   }
786db1 ¤   if (file != NULL)
bf0710 ¤   ¤   pgpContextMemFree( cdkContext, file);
cbf3b3 ¤   if (errorCode != NULL)
dfc7a1 ¤   {
4c03c0 ¤   ¤   pgpAssertAddrValid(errorCode, PGPError);
6f24c7 ¤   ¤   *errorCode = err;
819371 ¤   }
ff3f59 ¤   return NULL;
f2efe6 }
02af5a
727078 ¤   PGPFile *
dcb323 pgpFileRefMacReadOpen(
b63163 ¤   PGPContextRef¤  cdkContext,
f6b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
69afa5 ¤   PGPFileOpenFlags¤   flags,
576bae ¤   PGPError *¤ ¤   ¤   errorCode)
73bb36 {
30b839 ¤   PGPFile *¤  ¤   file = NULL;
f8159b ¤   MacFile *¤  ¤   mf = NULL;
c76f85 ¤   FSSpec¤ ¤   ¤   spec;
fa1903 ¤   CInfoPBRec¤ ¤   cpb;
6b4733 ¤   ushort¤ ¤   ¤   crc;
411d51 ¤   OSErr¤  ¤   ¤   macResult;
7283e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
77af5a
423b14 ¤   pgpAssert( pgpContextIsValid( cdkContext ) );
6caf5a
6b84c6 ¤   if ((file = (PGPFile *)pgpContextMemAlloc( cdkContext,
86aeb7 ¤   ¤   sizeof(*file), kPGPMemoryMgrFlags_Clear)) == NULL)
24c7a1 ¤   {
005e00 ¤   ¤   result = kPGPError_OutOfMemory;
d997ed ¤   ¤   goto error;
dd9371 ¤   }
0994d9 ¤   file->context¤  = cdkContext;
1806ad ¤   file->dataType ¤= kPGPFileDataType_Unknown;
ba67c5 ¤
057f8f ¤   if ((mf = (MacFile *)pgpContextMemAlloc( cdkContext,
d87397 ¤   ¤   sizeof(*mf), kPGPMemoryMgrFlags_Clear)) == NULL)
55c7a1 ¤   {
c2d9e8 ¤   ¤   pgpContextMemFree( cdkContext, file );
5b5e00 ¤   ¤   result = kPGPError_OutOfMemory;
b797ed ¤   ¤   goto error;
c39371 ¤   }
b6af5a
708c05 ¤   result = PFLCopyFileSpec(fileRef, &mf->fileRef);
b4291e ¤   if ( result != noErr )
fa97ed ¤   ¤   goto error;
5daf5a
9859c7 ¤   result = PFLGetFSSpecFromFileSpec(mf->fileRef, &spec);
ed8f1c ¤   if ( IsPGPError( result ) )
a997ed ¤   ¤   goto error;
4b632a ¤   mf->fileType = kPGPFileTypeNone;
8baf5a
4fe4f9 ¤   macResult¤  = FSpGetCatInfo( &spec, &cpb );
06fb7c ¤   if ( macResult != noErr )
281de7 ¤   ¤   goto macError;
23af5a
278056 ¤   pgpAssert(sizeof(mf->macBinHeader) >= 129);
--12c9 0005a200d9b40100270 Page 15 of pgpMacFile.c
93846e ¤   pgpClearMemory(&mf->macBinHeader, sizeof(mf->macBinHeader));
a7248b ¤   CopyPString(spec.name, mf->macBinHeader.name);
713451 ¤   mf->macBinHeader.info2 = cpbFInfo( &cpb ).fdFlags & 0x00FF;
8cd317 ¤   cpbFInfo( &cpb ).fdFlags &= 0xFF00;
310ac9 ¤   cpbFInfo( &cpb ).fdLocation.h = 0;
2e3921 ¤   cpbFInfo( &cpb ).fdLocation.v = 0;
15b929 ¤   cpbFInfo( &cpb ).fdFldr = 0;
22ceb4 ¤   mf->macBinHeader.info1¤ ¤   ¤   ¤   = cpbFInfo( &cpb );
8cbb7e ¤   mf->macBinHeader.dLength¤   ¤   ¤   = cpbDataForkSize( &cpb );
e6e26e ¤   mf->macBinHeader.rLength¤   ¤   ¤   = cpbResForkSize( &cpb );
14ef9d ¤   mf->macBinHeader.creationDate¤  ¤   = cpbCreationDate( &cpb );
2c3c33 ¤   mf->macBinHeader.modificationDate¤  = cpbModificationDate( &cpb );
1204e9 ¤   mf->macBinHeader.newVersion¤¤   ¤   = 129;
0ca1ec ¤   mf->macBinHeader.minimumVersion¤¤   = 129;
e525ad ¤   crc = CalcCRC16((const uchar *)&mf->macBinHeader + 1, 124);
ac5f0e ¤   pgpAssert(sizeof(crc) == 2);
f8e939 ¤   pgpCopyMemory(&crc, &mf->macBinHeader.crc1, sizeof(crc));
69af5a
c5dc2f ¤   mf->flags = kPGPMacRead;
be968d ¤   if ( flags & kPGPFileOpenForceLocalEncode)
e3c7a1 ¤   {
206535 ¤   ¤   mf->flags ¤ ¤   |= kPGPMacBinMode;
92eebb ¤   ¤   file->dataType ¤= kPGPFileDataType_Binary;
7e9371 ¤   }
5042ec ¤   else if (flags & kPGPFileOpenMaybeLocalEncode)
0cc7a1 ¤   {
3307cc ¤   ¤   if ( pgpOKToEncodeFSSpecWithoutMacBinary( &spec ) )
795b34 ¤   ¤   {
b23eca ¤   ¤   ¤   mf->flags¤  &= ~ kPGPMacBinMode;
0b0fe4 ¤   ¤   }
1c0e1d ¤   ¤   else
5e5b34 ¤   ¤   {
e863a5 ¤   ¤   ¤   mf->flags¤  ¤   |= kPGPMacBinMode;
49ff9c ¤   ¤   ¤   file->dataType ¤= kPGPFileDataType_Binary;
f60fe4 ¤   ¤   }
979371 ¤   }
d167c5 ¤
d7af5a
ebc13a ¤   if ((macResult = FSpOpenDF(&spec, fsRdPerm, &mf->dataRef)) != noErr)
4e1de7 ¤   ¤   goto macError;
0eaf5a
7daa7d ¤   if (mf->flags & kPGPMacBinMode)
d9c7a1 ¤   {
c3bbd7 ¤   ¤   if ((macResult = FSpOpenRF(&spec, fsRdPerm, &mf->resRef)) != noErr)
14ff06 ¤   ¤   ¤   goto macError;
0eaf5a
b0f870 ¤   ¤   mf->dataOffset = 128;
c52afa ¤   ¤   mf->resOffset =
e34c83 ¤   ¤   ¤   mf->dataOffset + (cpbDataForkSize( &cpb ) + 127) & ~127L;
0a1815 ¤   ¤   mf->totalSize = mf->resOffset + (cpbResForkSize( &cpb ) + 127) & ~127L;
2b3bf2 ¤   ¤   if (flags & kPGPFileOpenLocalEncodeHashOnly)
a75b34 ¤   ¤   {
1e92cc ¤   ¤   ¤   mf->flags |= kPGPMacBinHashOnly;
df3fc4 ¤   ¤   ¤   /* Clear the finder flags */
544ec5 ¤   ¤   ¤   mf->macBinHeader.info1.fdFlags = 0;
830772 ¤   ¤   ¤   mf->macBinHeader.info2 = 0;
5d4e8b ¤   ¤   ¤   /* Clear the creation and modification dates */
fb121d ¤   ¤   ¤   mf->macBinHeader.creationDate = 0;
ac3443 ¤   ¤   ¤   mf->macBinHeader.modificationDate = 0;
b9aea4 ¤   ¤   ¤   /* Clear the filename */
cabd3a ¤   ¤   ¤   pgpClearMemory(mf->macBinHeader.name,
005e7b ¤   ¤   ¤   ¤   sizeof(mf->macBinHeader.name));
d07aad ¤   ¤   ¤   /*
b7daff ¤   ¤   ¤   ·* Clear the CRC so that if this output gets used to
1474d6 ¤   ¤   ¤   ·* recreate a file (which it shouldn't), it won't work
33ba9e ¤   ¤   ¤   ·* properly and someone will notice the problem.
1b8753 ¤   ¤   ¤   ·*/
d4d093 ¤   ¤   ¤   pgpClearMemory(&mf->macBinHeader.crc1, sizeof(crc));
610fe4 ¤   ¤   }
649371 ¤   }
800e24 ¤   else
5ac7a1 ¤   {
--aeb4 0008a56b4fa40100270 Page 16 of pgpMacFile.c
a4478d ¤   ¤   mf->resRef = 0;
108add ¤   ¤   mf->dataOffset = 0;
f72c14 ¤   ¤   mf->totalSize = mf->resOffset = cpbDataForkSize( &cpb );
8d9371 ¤   }
86af5a
3f23f5 ¤   mf->filePos = 0;
65af5a
e53e8c ¤   file->priv = mf;
32e0d2 ¤   file->read = macFileRead;
a47725 ¤   file->write = macFileWrite;
126103 ¤   file->flush = macFileFlush;
2d97ed ¤   file->close = macFileClose;
7e1acc ¤   file->tell = macFileTell;
84087e ¤   file->seek = macFileSeek;
d12a42 ¤   file->eof = macFileEof;
6e312d ¤   file->sizeAdvise = macFileSizeAdvise;
7cda59 ¤   file->error = macFileError;
9e5604 ¤   file->clearError = macFileClearError;
c243f8 ¤   file->write2read = macFileWrite2Read;
f431bd ¤   file->cfb = macFileCfb;
6228f6 ¤   return file;
6daf5a
ba0e56 macError:
2e4311 ¤   result = pgpErrorFromMacError(macResult, kPGPError_CantOpenFile);
cdaf5a
8660ff error:
66d877 ¤   if (mf != NULL)
7ec7a1 ¤   {
b78332 ¤   ¤   if (mf->fileRef != NULL)
740a3c ¤   ¤   ¤   PFLFreeFileSpec(mf->fileRef);
49a722 ¤   ¤   pgpContextMemFree( cdkContext, mf);
a69371 ¤   }
ec6db1 ¤   if (file != NULL)
340710 ¤   ¤   pgpContextMemFree( cdkContext, file);
68f3b3 ¤   if (errorCode != NULL)
79c7a1 ¤   {
6103c0 ¤   ¤   pgpAssertAddrValid(errorCode, PGPError);
551f4d ¤   ¤   *errorCode = result;
179371 ¤   }
ef3f59 ¤   return NULL;
93efe6 }
b0af5a
61c744 ¤   PGPError
92842e pgpMacCalcFileSize(
61b622 ¤   PFLConstFileSpecRef¤¤   fileRef,
b5afa5 ¤   PGPFileOpenFlags¤   flags,
82bd0c ¤   size_t *¤   ¤   ¤   fileSize)
86bb36 {
db6f85 ¤   FSSpec¤ ¤   ¤   spec;
591903 ¤   CInfoPBRec¤ ¤   cpb;
7824ce ¤   PGPBoolean¤ ¤   macBinMode;
4283e5 ¤   PGPError¤   ¤   result = kPGPError_NoErr;
cbaf5a
e673f8 ¤   *fileSize = 0;¤ /* In case there's an error */
adaf5a
f25ebd ¤   if ((result = PFLGetFSSpecFromFileSpec(fileRef, &spec)) != kPGPError_NoErr)
bf669a ¤   ¤   return result;
caaf5a
12f181 ¤   if ( (result = FSpGetCatInfo( &spec, &cpb )) != noErr)
01e701 ¤   ¤   return pgpErrorFromMacError( result, kPGPError_CantOpenFile);
04af5a
0b487c ¤   macBinMode = FALSE;
da6564 ¤   if ( flags & kPGPFileOpenForceLocalEncode )
99c7a1 ¤   {
070a3b ¤   ¤   macBinMode = TRUE;
199371 ¤   }
fd42ec ¤   else if (flags & kPGPFileOpenMaybeLocalEncode)
88c7a1 ¤   {
86391f ¤   ¤   macBinMode¤ = ! pgpOKToEncodeFSSpecWithoutMacBinary( &spec );
109371 ¤   }
67af5a
8a9204 ¤   if (macBinMode)
--95ee 00135a4638440100270 Page 17 of pgpMacFile.c
f7c7a1 ¤   {
0eee8e ¤   ¤   *fileSize = 128 +¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   /* MacBinary header */
29c568 ¤   ¤   ¤   ¤   ¤   ((cpbDataForkSize( &cpb ) + 127) & ~127L) +¤/* Data fork */
3bdbdc ¤   ¤   ¤   ¤   ¤   ((cpbResForkSize( &cpb ) + 127) & ~127L);¤  /* Res fork */
139371 ¤   }
750e24 ¤   else
bac7a1 ¤   {
865d71 ¤   ¤   *fileSize = cpbDataForkSize( &cpb );
4a9371 ¤   }
d9af5a
12151e ¤   return kPGPError_NoErr;
69efe6 }
30af5a
da83a8 ¤   static MacFileTypeEntry const *
28a294 sFindMacFileTypeEntry( PGPFileType type )
55bb36 {
080d9a ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   index;
04490f ¤   MacFileTypeEntry const *¤   entry¤  = NULL;
2667c5 ¤
fd1a10 ¤   entry¤  = &sMacFileTypeTable[ 0 ];
42acec ¤   for( index = 0; index < kNumMacFileTypeEntries; ++index, ++entry )
6ac7a1 ¤   {
3a250d ¤   ¤   if ( entry->pgpFileType == type )
915b34 ¤   ¤   {
06da20 ¤   ¤   ¤   return( entry );
0b0fe4 ¤   ¤   }
8c9371 ¤   }
7e67c5 ¤
a8782e ¤   pgpDebugMsg( "can't find entry for PGPFileType" );
f79572 ¤   return( NULL );
12efe6 }
70af5a
2daf5a
ac9e6d ¤   OSType
ba3bb3 pgpGetMacFileTypeFromPGPFileType( PGPFileType pgpType )
56bb36 {
16490f ¤   MacFileTypeEntry const *¤   entry¤  = NULL;
e067c5 ¤
7818e3 ¤   entry¤  = sFindMacFileTypeEntry( pgpType );
641149 ¤   if ( IsntNull( entry ) )
669bc5 ¤   ¤   return( entry->type );
a1ea61 ¤   return( 0 );
aeefe6 }
59af5a
c99e6d ¤   OSType
150519 pgpGetMacFileCreatorFromPGPFileType( PGPFileType pgpType )
5abb36 {
5d490f ¤   MacFileTypeEntry const *¤   entry¤  = NULL;
1167c5 ¤
7e18e3 ¤   entry¤  = sFindMacFileTypeEntry( pgpType );
101149 ¤   if ( IsntNull( entry ) )
723f3f ¤   ¤   return( entry->creator );
34ea61 ¤   return( 0 );
b5efe6 }
41af5a
4caf5a
08ddc8 #endif¤ /* ] PGP_MACINTOSH */
d8af5a
c938e5 /*
e7e6c5 ·* Local Variables:
a49b19 ·* tab-width: 4
b4e7a4 ·* End:
69b612 ·* vi: ts=4 sw=4
066c42 ·* vim: si
35495d ·*/
--db35 00166f1c95940100271 Page 1 of pgpMacFile.h
bc38e5 /*
bcb1c1 ·* pgpMacFile.h -- Header for MacBinarizing PGPFile implementation
46775e ·*
5d9fcf ·* $Id: pgpMacFile.h,v 1.12 1997/12/11 23:14:04 lloyd Exp $
69495d ·*/
a6af5a
06b6eb #ifndef Included_pgpMacFile_h¤  /* [ */
bcbaee #define Included_pgpMacFile_h
67af5a
68675a #include "pgpTypes.h"
65a4b2 #include "pgpFileRef.h"
1272de #include "pgpFile.h"
573709 #include "pgpFileMod.h"
1daf5a
c699c6 PGP_BEGIN_C_DECLARATIONS
a8af5a
bc38e5 /*
6dc2fc ·* The <flags> params below are only used to convey MacBinary mode:
e3a001 ·*¤ ¤   kPGPFileOpenMaybeLocalEncode or kPGPFileOpenForceLocalEncode
36495d ·*/
d618e0 PGPFile ·*¤ ¤   pgpFileRefMacWriteOpen(
e9effc ¤   ¤   ¤   ¤   ¤   PGPContextRef¤  cdkContext,
ba6561 ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileRef,
7a7327 ¤   ¤   ¤   ¤   ¤   PGPFileType fileType,
d0a558 ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags, PGPError *error);
eeb59f PGPFile ·*¤ ¤   pgpFileRefMacReadOpen(
abeffc ¤   ¤   ¤   ¤   ¤   PGPContextRef¤  cdkContext,
ea6561 ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileRef,
04a558 ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags, PGPError *error);
6d2202 PGPError ¤  ¤   pgpMacCalcFileSize(·
9c6561 ¤   ¤   ¤   ¤   ¤   PFLConstFileSpecRef fileRef,
a7f27d ¤   ¤   ¤   ¤   ¤   PGPFileOpenFlags flags, size_t *fileSize);
357d3a OSType¤ ¤   ¤   pgpGetMacFileTypeFromPGPFileType( PGPFileType fileType );
31a7d2 OSType¤ ¤   ¤   pgpGetMacFileCreatorFromPGPFileType( PGPFileType fileType );
c4ae30 ¤   ¤   ¤   ¤   ¤
e61254 PGP_END_C_DECLARATIONS
b0af5a
80d84e #endif¤ /* ] Included_pgpMacFile_h */
49af5a
3138e5 /*
f2e6c5 ·* Local Variables:
0c9b19 ·* tab-width: 4
6de7a4 ·* End:
f6b612 ·* vi: ts=4 sw=4
216c42 ·* vim: si
66495d ·*/
--c61b 000b100ce6640100272 Page 1 of pgpMacFileMapping.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
1a00c2 ¤   Map file name extension to mac creator/type codes
974f3c ¤   Map file data to mac creator/type codes
cdaf5a
b4d542 ¤   $Id: pgpMacFileMapping.c,v 1.44.10.1 1998/11/12 03:23:23 heller Exp $
aff7f7 ____________________________________________________________________________*/
86e2ff #include "pgpConfig.h"
c3af5a
ec324c #include <string.h>
a11b42 #include "pgpStrings.h"
90af5a
ba2f8d #include "pgpErrors.h"
640d08 #include "pgpMem.h"
cb61a1 #include "pgpMacFileMapping.h"
f55430 #include "pgpUtilitiesPriv.h"
776fbf #include "pgpHex.h"
496773 #include "pgpMemoryMgr.h"
b8af5a
7caf5a
d9feb2 #include <stdio.h>
12b1cb #include <ctype.h>
633427 #include "pgpFileUtilities.h"
b9fbe2 #include "pgpMemoryIO.h"
3baf5a
99af5a
68af5a
d90335 /*____________________________________________________________________________
bcfb2f ¤   Run-time data structure used for mapping.
601972 ____________________________________________________________________________*/¤
1f8456 typedef struct CreatorTypeToExtensionEntry
edbb36 {
7c350a ¤   OSType¤ creator;
86d039 ¤   OSType¤ type;
6266df ¤   char¤   extension[ 3 + 1 ];
4e8627 } CreatorTypeToExtensionEntry;
7eaf5a
8389b5 typedef struct CreatorTypeToExtensionTable
edbb36 {
dc4674 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numEntries;
758d03 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numAllocated;
b1e6c7 ¤   CreatorTypeToExtensionEntry¤entries[ 1 ];¤  /* dynamic */
a753bf } CreatorTypeToExtensionTable;
a6af5a
e1af5a
43bb52 /* global table; one for whole SDK */
5447a2 static CreatorTypeToExtensionTable¤ *sMappingTable¤ = NULL;
ebaf5a
2caf5a
b30335 /*____________________________________________________________________________
0c5bae ¤   CreatorTypeToExtensionBuiltInEntry maps a mac creator/type code to a
7c29e8 ¤   suggested file name extension.
b267c5 ¤
f3f745 ¤   Used for the following:
99b2d3 ¤   1. when de-macbinarizing a file on a non-Mac to map to a useful
704ba0 ¤   ¤   file name extension.
a62112 ¤   2. ·To map a file name extension on a Mac to a creator type.
8bb8b5 ¤   3.¤ To decide which files "Smart" MacBinary applies to
b767c5 ¤
ac2e43 IMPORTANT:
d5592e ¤   Because this table can map many creator/type pairs to a single extension,
3c48e4 ¤   and an extension to a single creator/type pair,
ed4166 ¤   the preferred mapping from a suffix to a creator/type pair should be
a15829 ¤   listed FIRST in the table before all other mappings for that extension.
1d67c5 ¤
7d9349 ¤   A similar principle applies to wildcards. ·They should be listed after
75ebaf ¤   any specific mappings.
4f1972 ____________________________________________________________________________*/¤
0b026f #define kWildCard¤  0x2A2A2A2A¤ /* '****' */
b1af5a
--ea2e 000cffa3f6540100272 Page 2 of pgpMacFileMapping.c
2e0ccc #if PGP_MACINTOSH
8cf32f #define kEndOfLineString¤   "\r"
ff14ea #elif PGP_WIN32
59481d #define kEndOfLineString¤   "\r\n"
49bac4 #elif PGP_UNIX
85d319 #define kEndOfLineString¤   "\n"
60db21 #else
e99cf1 #error unknown OS
827454 #endif
c9af5a
a4af5a
286048 static const char
b9d435 sCreatorTypeToExtensionDefaults[] =
a4bb36 {
b25639 ¤   "# Mapping table for MacBinary and file name extension conversion"
c3a28b ¤   ¤   kEndOfLineString
3224d8 ¤   "# Format: " kEndOfLineString
53ad0e ¤   "# ····<4 char Mac creator><tab>"
d5ea8f ¤   "<4 char Mac type><tab><1-3 letter DOS extension>"
b2a28b ¤   ¤   kEndOfLineString
bca28b ¤   ¤   kEndOfLineString
852a6e ¤   "# The special code **** indicates a wild card for creator or type"
8ea28b ¤   ¤   kEndOfLineString
9fd37c ¤   "# Hex may be used for creator & type in the format 0xHHHHHHHH"
57a28b ¤   ¤   kEndOfLineString
fb0b50 ¤   "# Comment lines begin with '#'"
6ea28b ¤   ¤   kEndOfLineString
57a28b ¤   ¤   kEndOfLineString
6367c5 ¤
06af5a
91af5a
d93829 #define MappingLine( creator,¤  ·type,¤ ·ext )¤ ·\
03208d ¤   creator "\t" type "\t" ext kEndOfLineString
6567c5 ¤
17fc5d /* BEGIN preferred mappings */
efc633 /* IMPORTANT: list preferred mappings first */
a4aba6 ¤   MappingLine( "CWIE",¤   "TEXT",¤"h")¤   /* MetroWerks CodeWarrior */
351d4b ¤   MappingLine( "CWIE",¤   "TEXT",¤"c")¤   /* MetroWerks CodeWarrior */
f63801 ¤   MappingLine( "CWIE",¤   "TEXT",¤"cp")¤  /* MetroWerks CodeWarrior */
e05065 ¤   MappingLine( "CWIE",¤   "TEXT",¤"cpp")¤ /* MetroWerks CodeWarrior */
f2b1a7 ¤   MappingLine( "ttxt",¤   "TEXT",¤"txt")¤ /* SimpleText */
a3d491 ¤   MappingLine( "MOSS",¤   "TEXT",¤"htm")¤ /* Navigator */
a11b1a ¤   MappingLine( "SITx",¤   "TEXT",¤"hqx")¤ /* StuffIt Expander */
ac67c5 ¤
5050a1 ¤   /* graphics */
6d2062 ¤   MappingLine( "JVWR",¤   "JPEG",¤"jpg")¤
72b407 ¤   MappingLine( "JVWR",¤   "GIFf",¤"gif")¤
ce67c5 ¤
254e6d /* types that StuffIt can expand: */
ad0968 ¤   MappingLine( "SIT!",¤   "BINA",¤"zip")¤ /* StuffIt */
44059c ¤   MappingLine( "SIT!",¤   "BINA",¤"gz")¤  /* StuffIt */
73ed24 ¤   MappingLine( "SIT!",¤   "BINA",¤"tar")¤ /* StuffIt */
c9c3e1 ¤   MappingLine( "SIT!",¤   "BINA",¤"uu")¤  /* StuffIt */
fb616a ¤   MappingLine( "SIT!",¤   "BINA",¤"bin")¤ /* StuffIt */
10721d ¤   MappingLine( "SIT!",¤   "BINA",¤"arc")¤ /* StuffIt */
61bc64 ¤   MappingLine( "SIT!",¤   "BINA",¤"z")¤   ¤   /* StuffIt */
f5af5a
3923bc /* END preferred mappings */
fe67c5 ¤
638242 ¤   /* NOTE: creator wild cards should usually come last in the last */
186503 ¤   /* that's so a more specific mapping can be found first */
4b67c5 ¤
190172 ¤   MappingLine( "8BIM",¤   "GIFf",¤"gif")¤ /* Photoshop gif */
fc0c8d ¤   MappingLine( "8BIM",¤   "8BPS",¤"psd")¤ /* Photoshop ·*/
922fb2 ¤   MappingLine( "8BIM",¤   "TPIC",¤"tga")¤ /* Photoshop ·*/
e69a1e ¤   MappingLine( "8BIM",¤   "JPEG",¤"jpg")¤ /* Photoshop ·*/
6b67c5 ¤
ca1fe6 ¤   MappingLine( "ALD3",¤   "ALB3",¤"pm3")¤ /* PageMaker */
9e3a2e ¤   MappingLine( "ALD4",¤   "ALB4",¤"pm4")¤
f83df6 ¤   MappingLine( "ALD5",¤   "ALB5",¤"pm5")¤
75359e ¤   MappingLine( "ALD6",¤   "ALB6",¤"pm6")¤
cf67c5 ¤
--b86c 0003de1056a40100272 Page 3 of pgpMacFileMapping.c
438a82 ¤   MappingLine( "MSPJ",¤   "MPP ",¤"mpp")¤ /* Microsoft Project */
3a5414 ¤   MappingLine( "MSPJ",¤   "MPX ",¤"mpp")¤
e067c5 ¤
1bc1ca ¤   MappingLine( "AnVw",¤   "****",¤"gl")¤
b8e43b ¤   MappingLine( "arc*",¤   "mArc",¤"arc")¤
d36679 ¤   MappingLine( "BnHq",¤   "TEXT",¤"hqx")¤
9c9e94 ¤   MappingLine( "Booz",¤   "Zoo ",¤"zoo")¤
529f8a ¤   MappingLine( "CARO",¤   "PDF ",¤"pdf")¤ /* Acrobat */
8ad7cd ¤   MappingLine( "CPCT",¤   "PACT",¤"cpt")¤
ba0783 ¤   MappingLine( "DAD2",¤   "drw2",¤"cvs")¤
52a302 ¤   MappingLine( "DArj",¤   "BINA",¤"arj")¤
1d9c6c ¤   MappingLine( "dCpy",¤   "dlmg",¤"ima")¤
52ee2b ¤   MappingLine( "dPro",¤   "EPSF",¤"eps")¤
a90a86 ¤   MappingLine( "dPro",¤   "PICT",¤"mac")¤
8f56c3 ¤   MappingLine( "FMPR",¤   "FMPR",¤"fm")¤  /* FileMaker Pro */
a567c5 ¤
fbda2a ¤   MappingLine( "GKON",¤   "CGMm",¤"cgm")¤
6d2acd ¤   MappingLine( "GKON",¤   "DLdI",¤"dl")¤
06ed69 ¤   MappingLine( "GKON",¤   "FLI ",¤"fli")¤
3ed133 ¤   MappingLine( "GKON",¤   "ICO ",¤"ico")¤
27c35a ¤   MappingLine( "GKON",¤   "ILBM",¤"iff")¤
05ab2f ¤   MappingLine( "GKON",¤   "IMGg",¤"img")¤
4964b9 ¤   MappingLine( "GKON",¤   "ILBM",¤"lbm")¤
fbf164 ¤   MappingLine( "GKON",¤   "MSPp",¤"msp")¤
345065 ¤   MappingLine( "GKON",¤   "STAD",¤"PAC")¤
050242 ¤   MappingLine( "GKON",¤   "PPGM",¤"pbm")¤
669a82 ¤   MappingLine( "GKON",¤   "PICS",¤"pcs")¤
501024 ¤   MappingLine( "GKON",¤   "PCXx",¤"pcx")¤
e816c5 ¤   MappingLine( "GKON",¤   "PPGM",¤"pgm")¤
5ea807 ¤   MappingLine( "GKON",¤   "HPGL",¤"plt")¤
ffff27 ¤   MappingLine( "GKON",¤   "PMpm",¤"pm")¤
8148a4 ¤   MappingLine( "GKON",¤   "PPGM",¤"ppm")¤
c60095 ¤   MappingLine( "GKON",¤   "RIFF",¤"rif")¤
07f167 ¤   MappingLine( "GKON",¤   "RLE ",¤"rle")¤
3b5ce8 ¤   MappingLine( "GKON",¤   "SHPp",¤"shp")¤
c964d8 ¤   MappingLine( "GKON",¤   "Spec",¤"spc")¤
71149a ¤   MappingLine( "GKON",¤   "SUNn",¤"sr")¤
c13837 ¤   MappingLine( "GKON",¤   "SUNn",¤"sun")¤
327fc9 ¤   MappingLine( "GKON",¤   "SCRN",¤"sup")¤
cdcf99 ¤   MappingLine( "GKON",¤   "TARG",¤"tga")¤
4308ad ¤   MappingLine( "GKON",¤   "WMF ",¤"wmf")¤
76a1c1 ¤   MappingLine( "GKON",¤   "FLI ",¤"flc")¤
8a67c5 ¤
dd89e2 ¤   MappingLine( "Gzip",¤   "Gzip",¤"gz")¤
892062 ¤   MappingLine( "JVWR",¤   "JPEG",¤"jpg")¤
475164 ¤   MappingLine( "JVWR",¤   "BMPp",¤"vga")¤
d8a259 ¤   MappingLine( "L123",¤   "WKS ",¤"wks")¤ /* Lotus 123 */
7bc7fd ¤   MappingLine( "LARC",¤   "LHA ",¤"lha")¤
92dc7f ¤   MappingLine( "LARC",¤   "LHA ",¤"lzh")¤
ed3ae5 ¤   MappingLine( "LZIV",¤   "ZIVU",¤"z")¤
96b2c1 ¤   MappingLine( "mdos",¤   "BINA",¤"exe")¤
538459 ¤   MappingLine( "mMPG",¤   "MPEG",¤"mpg")¤
b867c5 ¤
50037b ¤   /* NOTE: wildcards should generally be at the bottom of the list */
40ff74 ¤   MappingLine( "MSWD",¤   "W8BN",¤"doc")¤ /* Word 98 */
59eb59 ¤   MappingLine( "MSWD",¤   "W6BN",¤"doc")¤ /* Word 6 */
0cfe78 ¤   MappingLine( "MSWD",¤   "WDBN",¤"doc")¤ /* Word ·*/
452d57 ¤   MappingLine( "MSWD",¤   "WTBN",¤"dot")¤ /* Word Template */
6beaae ¤   MappingLine( "MSWD",¤   "TEXT",¤"txt")¤
1e37a7 ¤   MappingLine( "MSWD",¤   "RTF ",¤"rtf")¤
3b0275 ¤   MappingLine( "MSWD",¤   "****",¤"doc")¤ /* MS Word (all")¤  ·*/
be67c5 ¤
b0743d ¤   MappingLine( "OTEX",¤   "ODVI",¤"dvi")¤
eecaae ¤   MappingLine( "OTEX",¤   "TEXT",¤"tex")¤
6e67c5 ¤
48e1cc ¤   /* PGP */
fe1730 ¤   MappingLine( "pgpM",¤   "pgDS",¤"sig")¤ /* detached sig */
ba7e62 ¤   MappingLine( "pgpM",¤   "pgEF",¤"pgp")¤ /* encrypted file */
91b481 ¤   MappingLine( "pgpM",¤   "pgSF",¤"pgp")¤ /* signed file */
c87a94 ¤   MappingLine( "pgpM",¤   "TEXT",¤"asc")¤ /* message */
94fe4a ¤   MappingLine( "pgpK",¤   "pgPR",¤"pkr") ¤/* public ring */
3d9aa1 ¤   MappingLine( "pgpK",¤   "pgRR",¤"skr")¤ /* secret ring */
--5c34 00052772e9b40100272 Page 4 of pgpMacFileMapping.c
58671e ¤   MappingLine( "pgpK",¤   "pgRS",¤"rnd")¤ /* random seed */
a8cb0d ¤   MappingLine( "pgpK",¤   "TEXT",¤"asc")¤ /* data */
2717e4 ¤   MappingLine( "pgpK",¤   "pgGR",¤"pgr")¤ /* groups */
720488 ¤   MappingLine( "pgpK",¤   "pgSK", "shf")¤ /* split key share file */
2367c5 ¤
4317f9 ¤   MappingLine( "PPT3",¤   "SLD8",¤"ppt")¤ /* PowerPoint 98 */
49547d ¤   MappingLine( "PPT3",¤   "SLD3",¤"ppt")¤ /* PowerPoint */
cdbf9e ¤   MappingLine( "PPT3",¤   "PPOT",¤"pot")¤ /* PowerPoint Template */
f367c5 ¤
a454ff ¤   MappingLine( "pZIP",¤   "pZIP",¤"zip")¤
a51996 ¤   MappingLine( "SCPL",¤   "AIFF",¤"aif")¤
f331f5 ¤   MappingLine( "SCPL",¤   "ULAW",¤"au")¤
257892 ¤   MappingLine( "SCPL",¤   "STrk",¤"mod")¤
cddabb ¤   MappingLine( "SCPL",¤   "8SVX",¤"svx")¤
8f49de ¤   MappingLine( "SCPL",¤   "WAVE",¤"wav")¤
afb14e ¤   MappingLine( "SITx",¤   "SIT!",¤"sit")¤
ba4dbd ¤   MappingLine( "SITx",¤   "SITD",¤"sit")¤
edc810 ¤   MappingLine( "TAR ",¤   "TARF",¤"tar")¤
2d6a5e ¤   MappingLine( "ttxt",¤   "PICT",¤"pct")¤
c7c7cc ¤   MappingLine( "ttxt",¤   "PICT",¤"pic")¤
8a4336 ¤   MappingLine( "TVOD",¤   "MooV",¤"qt")¤
ef3ec4 ¤   MappingLine( "UPIT",¤   "PIT ",¤"pit")
1c9f3d ¤   MappingLine( "WPC2",¤   ".WP5",¤"wp")¤  /* Word Perfect */
daa0b8 ¤   MappingLine( "WPC2",¤   ".WP5",¤"wp5")¤ /* Word Perfect */
a267c5 ¤
d83e1a ¤   MappingLine( "XCEL",¤   "XLS8",¤"xls")¤ /* MS Excel 98 */
6aeb3d ¤   MappingLine( "XCEL",¤   "XLS5",¤"xls")¤ /* MS Excel */
a0b975 ¤   MappingLine( "XCEL",¤   "XLS4",¤"xls")¤ /* MS Excel */
e5120d ¤   MappingLine( "XCEL",¤   "XLC3",¤"xlc")¤ /* MS Excel */
79fffd ¤   MappingLine( "XCEL",¤   "XLM3",¤"xlm")¤ /* MS Excel */
7cb1b1 ¤   MappingLine( "XCEL",¤   "XLW ",¤"xlw")¤ /* MS Excel */
31cb85 ¤   MappingLine( "XCEL",¤   "TEXT",¤"slk")¤ /* MS Excel */
25b140 ¤   MappingLine( "XCEL",¤   "****",¤"xls")¤ /* MS Excel */
3c67c5 ¤
55b08f ¤   MappingLine( "XPRS",¤   "XDOC",¤"qxd")¤ /* Quark */
8f67c5 ¤
b867c5 ¤
92dfc4 ¤   /* general wildcards should be *last* in the list so they are found last */
9367e1 ¤   MappingLine( "****",¤   "TEXT",¤"txt")¤
7dfc13 ¤   MappingLine( "****",¤   "pZIP",¤"zip")¤
54cadd ¤   MappingLine( "****",¤   "ZIVU",¤"zip")¤
3b4ab3 ¤   MappingLine( "****",¤   "Midi",¤"mdi")¤
a252b1 ¤   MappingLine( "****",¤   "PAK ",¤"pak")¤
c9a5a7 ¤   MappingLine( "****",¤   "mArc",¤"arc")¤
2c99c8 ¤   MappingLine( "****",¤   "ZOO ",¤"zoo")¤
2aaed0 ¤   MappingLine( "****",¤   "GIFf",¤"gif")¤
363ab5 ¤   MappingLine( "****",¤   "JPEG",¤"jpg")¤
d5e25d ¤   MappingLine( "****",¤   "TIFF",¤"tif")¤
ded9cf ¤   MappingLine( "****",¤   "EPSF",¤"eps")¤
9eaf5a
2582f7 };
f0af5a
3daf5a
34c21c #if PGP_MACINTOSH¤  /* [ */
a3af5a
adaf5a
07af5a
2e0335 /*____________________________________________________________________________
0220a8 ¤   DataMappingEntry is used to look at actual file data at the front of a file
102a2f ¤   being decrypted/verified and to assign it a Mac creator/type.
6367c5 ¤
382f31 ¤   It is generally consulted last after looking at the file extension because
0dc93f ¤   the file data could match just by chance, thus possibly giving a file a
6dc716 ¤   type which is inappropriate.
95f7f7 ____________________________________________________________________________*/
de0265 typedef struct DataMappingEntry
25bb36 {
090032 ¤   const OSType¤   ¤   ¤   creator;
eabfa8 ¤   const OSType¤   ¤   ¤   type;
7eedc4 ¤   const int¤  ¤   ¤   ¤   length;
b105a2 ¤   PGPByte const *¤const¤  ident;
525ac9 } DataMappingEntry;
--0fe2 0003dfb94c640100272 Page 5 of pgpMacFileMapping.c
e0af5a
4fcbfe static const DataMappingEntry ·sDataMappingEntries[] =
b5bb36 {
964ae8 #define DmEntry( cr, ty, len, id ) \
337d29 ¤   { cr, ty, len, (PGPByte const *)(id) }
7867c5 ¤
e18af1 ¤   DmEntry('pZIP', 'pZIP', ·2, "PK" ),
af19b9 ¤   DmEntry('LZIV', 'ZIVU', ·3, "\x1F\x9D\x90" ),
3e7319 ¤   DmEntry('MIDI', 'Midi', ·4, "MThd" ),
fb92b1 ¤   DmEntry('PAK ', 'PAK ', ·2, "\x1A\x0A" ),
3d3b1f ¤   DmEntry('BOOZ', 'ZOO ', ·4, "ZOO " ),
57d181 ¤   DmEntry('JVWR', 'GIFf', ·4, "GIF8" ),
08cd9d ¤   DmEntry('SIT!', 'SIT!', ·4, "SIT!" ),
2da433 ¤   DmEntry('CPCT', 'PACT', ·2, "\x01\x01" ),
1ea89c ¤   DmEntry('arc*', 'mArc', ·2, "\x1A\x08" ),
53acb7 ¤   DmEntry('arc*', 'mArc', ·2, "\x1A\x09" ),
ebe724 ¤   DmEntry('JVWR', 'JPEG', 10, "\xFF\xD8\xFF\xE0\0\x10JFIF" ),
e06be5 ¤   DmEntry(0, 0, 0, NULL )
4382f7 };
afaf5a
f6af5a
75af5a
6addc8 #endif¤ /* ] PGP_MACINTOSH */
d8af5a
29af5a
80ef0c ¤   static CreatorTypeToExtensionEntry const *
054b44 sMatchMacBinaryCreatorAndType(
56ed93 ¤   OSType¤ creator,
5aa6a0 ¤   OSType¤ type )
31bb36 {
c3e18b ¤   PGPUInt32¤  idx;
b5af5a
b656a1 ¤   for( idx = 0; idx < sMappingTable->numEntries; ++idx )
d4c7a1 ¤   {
f4a24f ¤   ¤   CreatorTypeToExtensionEntry const *¤entry;
0a1b52 ¤   ¤
e24744 ¤   ¤   entry¤  = &sMappingTable->entries[ idx ];
961b52 ¤   ¤
e3156e ¤   ¤   if ( entry->creator == creator ||
77ccf3 ¤   ¤   ¤   entry->creator == kWildCard )
e55b34 ¤   ¤   {
515e43 ¤   ¤   ¤   if ( entry->type == type ||
d15117 ¤   ¤   ¤   ¤   entry->type == kWildCard )
c4f776 ¤   ¤   ¤   {
776176 ¤   ¤   ¤   ¤   return( entry );
b1a3a6 ¤   ¤   ¤   }
010fe4 ¤   ¤   }
4e9371 ¤   }
e167c5 ¤
509572 ¤   return( NULL );
1eefe6 }
a2af5a
4daf5a
4eaf5a
8a0335 /*____________________________________________________________________________
65e388 ¤   map a creator/type pair to a file name extension
af67c5 ¤
27e810 ¤   extension is of the form "doc", "bin", etc + null char.
4e6ae4 ¤   The period is *not* included
00f7f7 ____________________________________________________________________________*/
a7c744 ¤   PGPError
0af050 pgpMapMacCreatorTypeToExtension(
d1ed93 ¤   OSType¤ creator,
d108a0 ¤   OSType¤ type,
68d135 ¤   char¤   extension[ 3 + 1 ]
0d27e6 ¤   )
60bb36 {
4326d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
c59f0d ¤   CreatorTypeToExtensionEntry const *¤entry¤  = NULL;
fc67c5 ¤
d87e11 ¤   PGPValidatePtr( sMappingTable );
3d67c5 ¤
--8f43 00049bae15240100272 Page 6 of pgpMacFileMapping.c
6c55cc ¤   extension[ 0 ]¤ = '\0';
57af5a
24dbfa ¤   entry¤  = sMatchMacBinaryCreatorAndType( creator, type );
641149 ¤   if ( IsntNull( entry ) )
b5c7a1 ¤   {
042427 ¤   ¤   strcpy( extension, entry->extension );
51bd2c ¤   ¤   pgpAssert( extension[ 0 ] != '.' );
99d87c ¤   ¤   err¤= kPGPError_NoErr;
419371 ¤   }
6a0e24 ¤   else
2cc7a1 ¤   {
03bd21 ¤   ¤   static const char¤  kDefaultExtension[] = "bin";
a21b52 ¤   ¤
634bf8 ¤   ¤   strcpy( extension, kDefaultExtension );
97ce64 ¤   ¤   err¤= kPGPError_NoMacBinaryTranslationAvailable;
919371 ¤   }
e867c5 ¤
78deb7 ¤   return( err );
e2efe6 }
9faf5a
e2af5a
ffaf5a
a60335 /*____________________________________________________________________________
fdd849 ¤   Return TRUE if the extension (without the ".") is a suitable file name
a30d21 ¤   extension for the specified creator and type.
2067c5 ¤
ecd433 ¤   Only ambiguous types need be added here; TEXT is the best example.
ea7888 ¤   Other mac creator/type pairs need not be added since they generally only
6b61d4 ¤   map to one possible extension.
e4f7f7 ____________________________________________________________________________*/
8816ea ¤   PGPBoolean
4ff27f pgpIsValidExtensionForMacType(
687d53 ¤   OSType¤ ¤   ¤   creator,
abfa46 ¤   OSType¤ ¤   ¤   type,
723152 ¤   char const *¤   extension )
4fbb36 {
0c90e8 ¤   PGPBoolean¤ ¤   isSuitable¤ = FALSE;
64ae98 ¤   char const **¤  extensionList¤  = NULL;
1d7f9b ¤   PGPUInt32¤  ¤   numExtensions¤  = 0;
9467c5 ¤
ad0089 ¤   (void)creator;
487f66 #define kFileTypeText¤  ((OSType)0x54455854)¤   /* 'TEXT' */
98a64b ¤   if ( type == kFileTypeText )
adc7a1 ¤   {
8209cf ¤   ¤   /* array of pointers to strings */
986c87 ¤   ¤   static const char *¤sSuitableExtensions[] =
7f5b34 ¤   ¤   {
7c23a7 ¤   ¤   ¤   "c", "h", "cpp", "cp", "cc", "cxx", "asm", "txt",
f5d00c ¤   ¤   ¤   "slk", "tex", "tx8", "rtf", "htm", "asc", "bas", "bat",
941f47 ¤   ¤   ¤   "cmd", "csv", "dif", "faq", "hqx", "ini",
f20970 ¤   ¤   ¤   "mak", "me", "p", "pas", "prn",
60a105 ¤   ¤   };
ee5bcc ¤   ¤   numExtensions¤  = sizeof( sSuitableExtensions ) /
d1bd91 ¤   ¤   ¤   ¤   ¤   ¤   sizeof( sSuitableExtensions[ 0 ] );
14379e ¤   ¤   extensionList¤  = sSuitableExtensions;
7d9371 ¤   }
be67c5 ¤
fa6a0d ¤   if ( numExtensions != 0 )
8cc7a1 ¤   {
f8505a ¤   ¤   PGPUInt32¤  idx;
941b52 ¤   ¤
ae16aa ¤   ¤   pgpAssert( IsntNull( extensionList ) );
288e6e ¤   ¤   for( idx = 0; idx < numExtensions; ++idx )
d05b34 ¤   ¤   {
b26005 ¤   ¤   ¤   if ( pgpCompareStringsIgnoreCase( extensionList[ idx ],
9fa089 ¤   ¤   ¤   ¤   ¤   extension ) == 0 )
def776 ¤   ¤   ¤   {
200e7a ¤   ¤   ¤   ¤   isSuitable¤ = TRUE;
fcf622 ¤   ¤   ¤   ¤   break;
5ea3a6 ¤   ¤   ¤   }
fd0fe4 ¤   ¤   }
499371 ¤   }
--8c4c 000b280085540100272 Page 7 of pgpMacFileMapping.c
2a67c5 ¤
b4f1df ¤   return( isSuitable );
33efe6 }
1baf5a
5baf5a
84af5a
78af5a
32af5a
ebaf5a
66af5a
b4c21c #if PGP_MACINTOSH¤  /* [ */
f9af5a
b2af5a
da67c5 ¤
6485c2 #include "MacStrings.h"
bdbbf4 #include "MacFiles.h"
ccaf5a
85af5a
48af5a
66c744 ¤   PGPError
f3a943 pgpMapFileDataToMacCreatorType(
08ebf7 ¤   const void *¤   dataIn,
eddebe ¤   OSType *¤   ¤   creator,
0067ab ¤   OSType *¤   ¤   type )
39bb36 {
52cb00 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_ItemNotFound;
b1ca58 ¤   PGPByte const *¤¤   ¤   data¤   = (PGPByte const *)dataIn;
60f333 ¤   DataMappingEntry const *¤   rec;
6b67c5 ¤
f44097 ¤   rec¤= &sDataMappingEntries[ 0 ];
50c0ef ¤   while ( IsntNull( rec->ident ) )
14c7a1 ¤   {
461fe4 ¤   ¤   if ( rec->ident[ 0 ] == data[ 0 ] &&
0969b3 ¤   ¤   ¤   pgpMemoryEqual( data, rec->ident, rec->length))
2e5b34 ¤   ¤   {
bec4e4 ¤   ¤   ¤   *creator¤   = rec->creator;
295eb0 ¤   ¤   ¤   *type¤  ¤   = rec->type;
76c7c1 ¤   ¤   ¤   err¤= noErr;
1acdcb ¤   ¤   ¤   break;
580fe4 ¤   ¤   }
61fcf7 ¤   ¤   ++rec;
759371 ¤   }
261b52 ¤   ¤
5edeb7 ¤   return( err );
f4efe6 }
78af5a
5daf5a
49af5a
250335 /*____________________________________________________________________________
4033d2 ¤   Map a filename (generally just the extension) to a mac creator and type.
f567c5 ¤
9b823c ¤   Two tables are consulted here.
e867c5 ¤
c2ee2b ¤   The first, 'sSuffixMap', contains mapping from a suffix to a creator/type.
e5d800 ¤   This table allows us to give a preferred mapping from a suffix to a
d90db3 ¤   mac creator type. If we find an entry in this table, then we'll use it.
83513d ¤   The mapping in this table is one-to-one; a single suffix can map to
4c522f ¤   only one creator/type pair.
4e67c5 ¤
51b04a ¤   The second table is the one used on non-Mac systems to map the
9af4cb ¤   creator/type code to an extension.
daa0b7 ¤   Since multiple creator/type pairs can map to the same suffix, and
086e07 ¤   since the entries in this table will be searched in order, the first
5a3666 ¤   matching suffix found will match. ·
e0af5a
43b9f3 ¤   A third fact is important: mappings in the second table may be
10b74c ¤   wildcarded. ·Without a mapping in the sSuffixMap, we wouldn't be able
dd8a7d ¤   to generate an appropriate creator/type pair.
17f7f7 ____________________________________________________________________________*/
48c744 ¤   PGPError
15446e pgpMapFileNameToMacCreatorType(
b24bea ¤   const unsigned char *¤  name,
--249b 000ef6985cf40100272 Page 8 of pgpMacFileMapping.c
810f5a ¤   OSType *¤   ¤   ¤   ¤   creator,
895dc8 ¤   OSType *¤   ¤   ¤   ¤   type )
65bb36 {
0da153 ¤   PGPError¤   ¤   err¤= kPGPError_ItemNotFound;
04cdc4 ¤   PGPUInt32¤  ¤   idx;
1a44b8 ¤   char¤   ¤   ¤   cName[ 256 ];
3c3478 ¤   const char *¤   extension;
a767c5 ¤
60e7b4 ¤   /* not really a param, but does desired thing */
977e11 ¤   PGPValidatePtr( sMappingTable );
2e67c5 ¤
0f0929 ¤   PToCString( name, cName );
ad809a ¤   extension¤  = PGPGetFileNameExtension( cName );
d067c5 ¤
3a56a1 ¤   for( idx = 0; idx < sMappingTable->numEntries; ++idx )
c3c7a1 ¤   {
34a24f ¤   ¤   CreatorTypeToExtensionEntry const *¤entry;
7f1b52 ¤   ¤
124744 ¤   ¤   entry¤  = &sMappingTable->entries[ idx ];
331b52 ¤   ¤
c686da ¤   ¤   if ( pgpCompareStringsIgnoreCase( entry->extension,
ece17a ¤   ¤   ¤   ¤   extension ) == 0 )
d75b34 ¤   ¤   {
d68a73 ¤   ¤   ¤   /* extension matches. ·If the type and creator are
184321 ¤   ¤   ¤   not wild cards, the use it */
182f24 ¤   ¤   ¤   if (¤   entry->creator != kWildCard &&
1b1ba0 ¤   ¤   ¤   ¤   ¤   entry->type != kWildCard )
d2f776 ¤   ¤   ¤   {
40eb24 ¤   ¤   ¤   ¤   err¤¤   ¤   = noErr;
729fe6 ¤   ¤   ¤   ¤   *creator¤   = entry->creator;
e295af ¤   ¤   ¤   ¤   *type¤  ¤   = entry->type;
fdf622 ¤   ¤   ¤   ¤   break;
4da3a6 ¤   ¤   ¤   }
c30fe4 ¤   ¤   }
f39371 ¤   }
9567c5 ¤
2fdeb7 ¤   return( err );
d1efe6 }
42af5a
abaf5a
5216ea ¤   PGPBoolean
268e89 pgpOKToEncodeFSSpecWithoutMacBinary( const FSSpec *spec )
9ebb36 {
f7dc42 ¤   OSStatus¤   err;
d14f27 ¤   CInfoPBRec¤ cpb;
35c4da ¤   PGPBoolean¤ encodeAsMacBinary¤  = TRUE;
af67c5 ¤
876759 ¤   pgpAssert( IsntNull( sMappingTable ) );
fea658 ¤   if ( IsNull( sMappingTable ) )
dde20d ¤   ¤   return( FALSE );
0167c5 ¤
9a2244 ¤   err¤= FSpGetCatInfo( spec, &cpb );
e78c1a ¤   pgpAssertNoErr( err );
dbf1e7 ¤   if ( IsntPGPError( err ) )
a9c7a1 ¤   {
74a24f ¤   ¤   CreatorTypeToExtensionEntry const *¤entry;
301b52 ¤   ¤
d7ce02 ¤   ¤   entry¤  = sMatchMacBinaryCreatorAndType( cpbFileCreator( &cpb ),
2063e5 ¤   ¤   ¤   ¤   cpbFileType( &cpb ) );
ec2b85 ¤   ¤   ¤   ¤
15aa1f ¤   ¤   if ( IsntNull( entry ) )
cc5b34 ¤   ¤   {
15886a ¤   ¤   ¤   encodeAsMacBinary¤  = FALSE;
970fe4 ¤   ¤   }
680e1d ¤   ¤   else
735b34 ¤   ¤   {
aa484c ¤   ¤   ¤   #define kMaxResForkSize¤¤   400
30c814 ¤   ¤   ¤   /* programatically determine */
5ab47b ¤   ¤   ¤   /* should we allow files without resource forks? */
530285 ¤   ¤   ¤   if ( cpbResForkSize( &cpb ) < kMaxResForkSize )
48f776 ¤   ¤   ¤   {
ef8ed2 ¤   ¤   ¤   ¤   encodeAsMacBinary¤  = FALSE;
--4b68 0008659d2fd40100272 Page 9 of pgpMacFileMapping.c
cfa3a6 ¤   ¤   ¤   }
290fe4 ¤   ¤   }
959371 ¤   }
0767c5 ¤
7a423f ¤   return( ! encodeAsMacBinary );
a1efe6 }
50af5a
4aaf5a
cbddc8 #endif¤ /* ] PGP_MACINTOSH */
b9af5a
0baf5a
41af5a
13af5a
4b0ccc #if PGP_MACINTOSH
63e443 const char¤ kMappingFileName[]¤ = "PGP MacBinary Mappings";
d1db21 #else
bac29a const char¤ kMappingFileName[]¤ = "PGPMacBinaryMappings.txt";
007454 #endif
ddaf5a
5e66dd ¤   static PGPError
7ac08c sGetMacBinaryFileSpec(
5bd8a8 ¤   PGPMemoryMgrRef¤¤   context,
aed8f1 ¤   PFLFileSpecRef *¤   spec )
0fbb36 {
2026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2467c5 ¤
092690 ¤   err¤= pgpGetPrefsSpec( context, spec );
7bf1e7 ¤   if ( IsntPGPError( err ) )
d1c7a1 ¤   {
9b295c ¤   ¤   err¤= PFLSetFileSpecName( *spec, kMappingFileName );
2ebe18 ¤   ¤   if ( IsPGPError( err ) )
7d5b34 ¤   ¤   {
bf2195 ¤   ¤   ¤   PFLFreeFileSpec( *spec );
4440eb ¤   ¤   ¤   *spec¤  = NULL;
1e0fe4 ¤   ¤   }
fc9371 ¤   }
5f67c5 ¤
35deb7 ¤   return( err );
8eefe6 }
28af5a
caaf5a
14af5a
829757 #define IsEndOfLine( c ) ¤  ¤   ((c) == '\r' || (c) == '\n' )
a6af5a
13900c ¤   static const char *
685296 sSkipWhite(
5c39fb ¤   const char *¤   cur,
f36fb0 ¤   const char *¤   last )
acbb36 {
915bf6 ¤   while ( cur <= last )
25c7a1 ¤   {
e5ab1e ¤   ¤   if ( isspace( *cur ) )
b1bdb8 ¤   ¤   ¤   ++cur;
240e1d ¤   ¤   else
3ccdcb ¤   ¤   ¤   break;
fa9371 ¤   }
ba9aab ¤   return( cur );
37efe6 }
4faf5a
3a900c ¤   static const char *
8c953f sSkipToNextLine(
9939fb ¤   const char *¤   cur,
ca6fb0 ¤   const char *¤   last )
b6bb36 {
0b5bf6 ¤   while ( cur <= last )
1cc7a1 ¤   {
c30960 ¤   ¤   if ( ! IsEndOfLine( *cur ) )
3bbdb8 ¤   ¤   ¤   ++cur;
b30e1d ¤   ¤   else
77cdcb ¤   ¤   ¤   break;
659371 ¤   }
8667c5 ¤
--24ae 0000bc8999840100272 Page 10 of pgpMacFileMapping.c
ea5bf6 ¤   while ( cur <= last )
bfc7a1 ¤   {
118d34 ¤   ¤   if ( IsEndOfLine( *cur ) )
18bdb8 ¤   ¤   ¤   ++cur;
220e1d ¤   ¤   else
85cdcb ¤   ¤   ¤   break;
549371 ¤   }
0267c5 ¤
d69aab ¤   return( cur );
71efe6 }
81af5a
cdaf5a
0d1964 ¤   static PGPUInt32
6c71b6 sGetLineLength(
3939fb ¤   const char *¤   cur,
d06fb0 ¤   const char *¤   last )
33bb36 {
ff0107 ¤   PGPUInt32¤  length¤ = 0;
b267c5 ¤
775bf6 ¤   while ( cur <= last )
11c7a1 ¤   {
048d34 ¤   ¤   if ( IsEndOfLine( *cur ) )
d1cdcb ¤   ¤   ¤   break;
ae43b9 ¤   ¤   ++length;
b35f1b ¤   ¤   ++cur;
fd9371 ¤   }
09dc88 ¤   return( length );
7cefe6 }
0eaf5a
0eaf5a
5baf5a
0067c5 ¤
a9af5a
aaaf5a
ad900c ¤   static const char *
6380c6 sParseOSType(
1839fb ¤   const char *¤   cur,
3c6c9f ¤   const char *¤   last,
02f63b ¤   OSType *¤   ¤   osType,
ee62a6 ¤   PGPBoolean *¤   valid )
d3bb36 {
d9ac24 ¤   PGPUInt32¤  lineLength;
c9c317 ¤   PGPByte¤¤   buffer[ 4 ];
34f7e2 ¤   PGPUInt32¤  result;
f567c5 ¤
9c7fb3 ¤   *valid¤ = FALSE;
5967c5 ¤
f4c95e ¤   lineLength¤ = sGetLineLength( cur, last );
c267c5 ¤
c1b096 ¤   /* does it start with "0x"? */
1a7ea2 ¤   if ( ( *cur == '0' && *(cur + 1) == 'x' ) ·)
8ac7a1 ¤   {
06748d ¤   ¤   cur¤+= 2;
d1e379 ¤   ¤   if ( lineLength >= 8 )
ad5b34 ¤   ¤   {
44c2d9 ¤   ¤   ¤   pgpHexToBytes( cur, 4, buffer );
f83d6d ¤   ¤   ¤   cur¤+= 8;
5e181d ¤   ¤   ¤   *valid¤ = TRUE;
0c0fe4 ¤   ¤   }
b99371 ¤   }
b5c452 ¤   else if ( lineLength >= 4 )
4ec7a1 ¤   {
488067 ¤   ¤   buffer[ 0 ]¤= *cur++;
55fe8d ¤   ¤   buffer[ 1 ]¤= *cur++;
8b7db3 ¤   ¤   buffer[ 2 ]¤= *cur++;
370359 ¤   ¤   buffer[ 3 ]¤= *cur++;
f3af5a
e2ee78 ¤   ¤   *valid¤ = TRUE;
759371 ¤   }
dc67c5 ¤
01eeb6 ¤   result¤ = buffer[ 0 ];
0bc88e ¤   result¤ = ( result << 8 ) | buffer[ 1 ];
--485f 000402503e740100272 Page 11 of pgpMacFileMapping.c
6dd542 ¤   result¤ = ( result << 8 ) | buffer[ 2 ];
6ade06 ¤   result¤ = ( result << 8 ) | buffer[ 3 ];
6267c5 ¤
be5255 ¤   *osType¤= result;
b11b52 ¤   ¤
559aab ¤   return( cur );
78efe6 }
e4af5a
54af5a
b9900c ¤   static const char *
de6259 sParseExtension(
7039fb ¤   const char *¤   cur,
d16c9f ¤   const char *¤   last,
a54cd2 ¤   char¤   ¤   ¤   extension[ 3 + 1 ],
0962a6 ¤   PGPBoolean *¤   valid )
31bb36 {
9d0107 ¤   PGPUInt32¤  length¤ = 0;
b167c5 ¤
ce7fb3 ¤   *valid¤ = FALSE;
6967c5 ¤
470c69 ¤   pgpFillMemory( extension, 3 + 1, '\0' );
925bf6 ¤   while ( cur <= last )
80c7a1 ¤   {
8cab1e ¤   ¤   if ( isspace( *cur ) )
2dcdcb ¤   ¤   ¤   break;
cd1b52 ¤   ¤
4958ea ¤   ¤   extension[ length ]¤= *cur++;
1b43b9 ¤   ¤   ++length;
20ee78 ¤   ¤   *valid¤ = TRUE;
d84f30 ¤   ¤   if ( length == 3 )
a9cdcb ¤   ¤   ¤   break;
499371 ¤   }
e6644f ¤   extension[ length ]¤= '\0';
8367c5 ¤
92c48d ¤   if ( cur <= last &&
f5a691 ¤   ¤   ! (isspace( *cur ) || IsEndOfLine( *cur ) ) )
08c7a1 ¤   {
a94058 ¤   ¤   pgpDebugMsg( "malformed line" );
58ce62 ¤   ¤   *valid¤ = FALSE;
3c9371 ¤   }
681b52 ¤   ¤
929aab ¤   return( cur );
f5efe6 }
8baf5a
adaf5a
fb0335 /*____________________________________________________________________________
464677 ¤   Return TRUE if a valid line was found
7cf7f7 ____________________________________________________________________________*/
1b900c ¤   static const char *
102af9 sParseLine(
ba0277 ¤   const char *¤   ¤   ¤   ¤   ¤   cur,
b022c0 ¤   const char *¤   ¤   ¤   ¤   ¤   last,
3786c0 ¤   CreatorTypeToExtensionEntry *¤  entry,
ea0ef8 ¤   PGPBoolean *¤   ¤   ¤   ¤   ¤   foundEntry )
5bbb36 {
1732b3 ¤   *foundEntry¤= FALSE;
4167c5 ¤
db0124 ¤   pgpClearMemory( entry, sizeof( *entry ) );
405d22 ¤   #define kCommentChar¤   ¤   '#'
8567c5 ¤
b8ce63 ¤   /* skip comment and blank lines */
08abe6 ¤   if ( *cur == kCommentChar || IsEndOfLine( *cur ))
65c7a1 ¤   {
b5fdd1 ¤   ¤   cur¤= sSkipToNextLine( cur, last );
949371 ¤   }
d10e24 ¤   else
48c7a1 ¤   {
cce2e2 ¤   ¤   /* potentially a valid line */
73017a ¤   ¤   PGPUInt32¤  lineLength;
7d1b52 ¤   ¤
5a11ec ¤   ¤   lineLength¤ = sGetLineLength( cur, last );
401b52 ¤   ¤
--fec9 000323d3d3140100272 Page 12 of pgpMacFileMapping.c
3e37a3 ¤   ¤   /* CCCCTTTTExx with no space */
093bd7 ¤   ¤   /* or hex variants of such of form 0xHHHHHHHH */
bfdace ¤   ¤   #define kMinLineLength (4 + 4 + 3)
57a4be ¤   ¤   if ( lineLength >= kMinLineLength )
575b34 ¤   ¤   {
948acd ¤   ¤   ¤   PGPBoolean¤ ¤   valid;
2887c7 ¤   ¤   ¤
6ebf12 ¤   ¤   ¤   cur¤= sParseOSType( cur, last, &entry->creator, &valid );
0ab112 ¤   ¤   ¤   cur¤= sSkipWhite( cur, last );
7f87c7 ¤   ¤   ¤
0b4b85 ¤   ¤   ¤   if ( valid )
b5f776 ¤   ¤   ¤   {
cb63ca ¤   ¤   ¤   ¤   cur¤= sParseOSType( cur, last, &entry->type, &valid );
8b208a ¤   ¤   ¤   ¤   cur¤= sSkipWhite( cur, last );
47af5a
f37fd8 ¤   ¤   ¤   ¤   if ( valid )
9572c3 ¤   ¤   ¤   ¤   {
af6ac5 ¤   ¤   ¤   ¤   ¤   cur¤= sParseExtension( cur,
e59925 ¤   ¤   ¤   ¤   ¤   ¤   ¤   last, entry->extension, &valid );
ea2613 ¤   ¤   ¤   ¤   }
e4a3a6 ¤   ¤   ¤   }
6887c7 ¤   ¤   ¤
00c759 ¤   ¤   ¤   pgpDebugMsgIf( ! valid, "malformed line" );
5c47b8 ¤   ¤   ¤   *foundEntry¤= valid;
3a0fe4 ¤   ¤   }
d80e1d ¤   ¤   else
315b34 ¤   ¤   {
b33326 ¤   ¤   ¤   pgpDebugMsgIf( lineLength != 0, "malformed line" );
4a0fe4 ¤   ¤   }
c11b52 ¤   ¤
3efdd1 ¤   ¤   cur¤= sSkipToNextLine( cur, last );
449371 ¤   }
3267c5 ¤
3a9aab ¤   return( cur );
8fefe6 }
74af5a
7aaf5a
6d66dd ¤   static PGPError
514390 sAddEntryToMappingTable(
cadcdc ¤   CreatorTypeToExtensionEntry const *¤entry)
bfbb36 {
5126d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
8d56e5 ¤   CreatorTypeToExtensionTable *¤  ¤   table;
e867c5 ¤
0159ba ¤   table¤  = sMappingTable;
e267c5 ¤
fa5c6b ¤   if ( table->numEntries + 1 > table->numAllocated )
9ec7a1 ¤   {
670f12 ¤   ¤   PGPUInt32¤  newNumAllocated;
50dc1d ¤   ¤   PGPSize¤¤   newSize;
a71b52 ¤   ¤
cd24ee ¤   ¤   /* allocate them 10 at a time to save space */
dd9451 ¤   ¤   newNumAllocated¤= table->numAllocated + 10;
c51b52 ¤   ¤
85dc15 ¤   ¤   newSize¤= sizeof( CreatorTypeToExtensionTable ) +
8f2f24 ¤   ¤   ¤   ¤   ¤   newNumAllocated * sizeof( table->entries[ 0 ] );
41a48f ¤   ¤   err¤= pgpRealloc( (void **) &table, newSize );
2a7d98 ¤   ¤   if ( IsntPGPError( err ) )
e95b34 ¤   ¤   {
8239a2 ¤   ¤   ¤   table->numAllocated¤= newNumAllocated;
e00fe4 ¤   ¤   }
7a9371 ¤   }
3e67c5 ¤
acf1e7 ¤   if ( IsntPGPError( err ) )
bfc7a1 ¤   {
f20842 ¤   ¤   pgpAssert( table->numAllocated > table->numEntries );
8b2069 ¤   ¤   table->entries[ table->numEntries ]¤= *entry;
546635 ¤   ¤   table->numEntries++;
109371 ¤   }
5e67c5 ¤
848419 ¤   sMappingTable¤  = table;
3267c5 ¤
--5e41 000706eebd640100272 Page 13 of pgpMacFileMapping.c
afdeb7 ¤   return( err );
b7efe6 }
35af5a
adaf5a
8daf5a
8866dd ¤   static PGPError
81ea72 sParseMappings(
d037b0 ¤   void const *¤   memIn,
c705fd ¤   PGPSize¤¤   ¤   length )
21bb36 {
cc9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
d567c5 ¤
e5364e ¤   pgpAssert( IsntNull( memIn ) );
65e332 ¤   pgpAssert( IsNull( sMappingTable ) );
7a67c5 ¤
ad6328 ¤   /* special case: use pgpAlloc() since we don't have a user context */
0528fc ¤   sMappingTable¤  = (CreatorTypeToExtensionTable *)
059618 ¤   ¤   ¤   ¤   ¤   ¤   pgpAlloc( sizeof( *sMappingTable ) );
d9b15f ¤   if ( IsntNull( sMappingTable ) )
a9c7a1 ¤   {
738415 ¤   ¤   CreatorTypeToExtensionEntry¤entry;
8cd53f ¤   ¤   const char *¤   cur;
2b3d52 ¤   ¤   const char *¤   last;
281b52 ¤   ¤
9578c0 ¤   ¤   pgpClearMemory( sMappingTable, sizeof( *sMappingTable) );
7600ee ¤   ¤   sMappingTable->numEntries¤  = 0;
c4e108 ¤   ¤   sMappingTable->numAllocated¤= 0;
6faf5a
040490 ¤   ¤   cur¤¤   = (char const *)memIn;
edecad ¤   ¤   last¤   = cur + (length -1);
891b52 ¤   ¤
f9d2a2 ¤   ¤   while ( cur <= last )
765b34 ¤   ¤   {
04b240 ¤   ¤   ¤   PGPBoolean¤ foundEntry;
a287c7 ¤   ¤   ¤
d74aba ¤   ¤   ¤   cur¤= sParseLine( cur, last, &entry, &foundEntry );
363113 ¤   ¤   ¤   if ( foundEntry )
bcf776 ¤   ¤   ¤   {
56b4d6 ¤   ¤   ¤   ¤   err¤= sAddEntryToMappingTable( &entry );
a7869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
3214c3 ¤   ¤   ¤   ¤   ¤   break;
94a3a6 ¤   ¤   ¤   }
8a0fe4 ¤   ¤   }
3c9371 ¤   }
6c0e24 ¤   else
edc7a1 ¤   {
2417a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
a69371 ¤   }
2a67c5 ¤
08deb7 ¤   return( err );
30efe6 }
f5af5a
afaf5a
f066dd ¤   static PGPError
8e15c8 sReadMappingsFromIO( PGPIORef¤  io)
7fbb36 {
a49372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
3f8039 ¤   PGPFileOffset¤  eof;
7c67c5 ¤
9107c3 ¤   err¤= PGPIOGetEOF( io, &eof );
a9f1e7 ¤   if ( IsntPGPError( err ) )
e8c7a1 ¤   {
49c0a1 ¤   ¤   void *¤ ¤   ¤   mem;
3b5563 ¤   ¤   PGPMemoryMgrRef¤memoryMgr;
77cb5d ¤   ¤   PGPSize¤¤   ¤   bufferSize;
be1b52 ¤   ¤
101c85 ¤   ¤   bufferSize¤ = (PGPSize)eof;
1491ea ¤   ¤   memoryMgr¤  = PGPIOGetMemoryMgr( io );
6b9ad8 ¤   ¤   mem¤¤   = PGPNewData( memoryMgr, bufferSize, 0 );
0a27fe ¤   ¤   if ( IsntNull( mem ) )
b85b34 ¤   ¤   {
707d86 ¤   ¤   ¤   err¤= PGPIORead( io, bufferSize, mem, NULL );
--fccf 000dc682ce040100272 Page 14 of pgpMacFileMapping.c
543c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
28f776 ¤   ¤   ¤   {
4b453f ¤   ¤   ¤   ¤   err¤= sParseMappings( mem, bufferSize );
9da3a6 ¤   ¤   ¤   }
c04ab2 ¤   ¤   ¤   PGPFreeData( mem );
e00fe4 ¤   ¤   }
d40e1d ¤   ¤   else
325b34 ¤   ¤   {
84124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
210fe4 ¤   ¤   }
a49371 ¤   }
e167c5 ¤
f9deb7 ¤   return( err );
94efe6 }
b0af5a
7d66dd ¤   static PGPError
b6ef99 pgpReadMacBinaryMappings( PFLFileSpecRef spec )
52bb36 {
3526d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
323605 ¤   PGPIORef¤   io;
7a67c5 ¤
af2a19 ¤   err¤= PGPOpenFileSpec( spec,
6c1171 ¤   ¤   kPFLFileOpenFlags_ReadOnly, (PGPFileIORef *)&io );
31f1e7 ¤   if ( IsntPGPError( err ) )
57c7a1 ¤   {
c17776 ¤   ¤   err¤= sReadMappingsFromIO( io );
25ccb3 ¤   ¤   PGPFreeIO( io );
51871a ¤   ¤   io¤ = NULL;
099371 ¤   }
c267c5 ¤
1cdeb7 ¤   return( err );
00efe6 }
19af5a
c5af5a
2667c5 ¤
8966dd ¤   static PGPError
fec8e8 sWriteBuiltInMappingsToIO( PGPIORef¤io )
b0bb36 {
ba26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2067c5 ¤
a5f635 ¤   err¤= PGPIOWrite( io,
74ee2b ¤   ¤   ¤   strlen( sCreatorTypeToExtensionDefaults ),
c73b33 ¤   ¤   ¤   sCreatorTypeToExtensionDefaults );
ef67c5 ¤
68deb7 ¤   return( err );
2befe6 }
39af5a
b3af5a
030335 /*____________________________________________________________________________
bcf0ac ¤   Initialize the mappings from the built-in table. ·Generally called only if
59617e ¤   (a) the mapping file can't be found and
098f5c ¤   (b) we couldn't create a mapping file.
6f67c5 ¤
a7201a ¤   Here we use a trick: first write them into a memory io, then init them
b31b75 ¤   from this memory IO.
53f7f7 ____________________________________________________________________________*/
5666dd ¤   static PGPError
d13e8f sInitFromBuiltIn( PGPMemoryMgrRef¤  context)
1bbb36 {
6d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
253605 ¤   PGPIORef¤   io;
7567c5 ¤
b8383a ¤   err¤= PGPNewMemoryIO( context, (PGPMemoryIORef *)&io );
2cf1e7 ¤   if ( IsntPGPError( err ) )
61c7a1 ¤   {
89c626 ¤   ¤   err¤= sWriteBuiltInMappingsToIO( io );
947d98 ¤   ¤   if ( IsntPGPError( err ) )
4e5b34 ¤   ¤   {
ae2284 ¤   ¤   ¤   err¤= PGPIOSetPos( io, 0 );
b13c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
c32353 ¤   ¤   ¤   ¤   err¤= sReadMappingsFromIO( io );
dc0fe4 ¤   ¤   }
--0840 000d5898b2840100272 Page 15 of pgpMacFileMapping.c
f11b52 ¤   ¤
78ccb3 ¤   ¤   PGPFreeIO( io );
b69371 ¤   }
f267c5 ¤
7adeb7 ¤   return( err );
95efe6 }
d2af5a
7caf5a
1aaf5a
00af5a
6d66dd ¤   static PGPError
c7303f sWriteBuiltInMappingsToFile( PFLFileSpecRef¤spec )
40bb36 {
929372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
31bbfc ¤   PGPIORef¤   ¤   io¤ = NULL;
4367c5 ¤
ae3b69 ¤   err¤= PFLFileSpecCreate( spec );
3df1e7 ¤   if ( IsntPGPError( err ) )
2ac7a1 ¤   {
271771 ¤   ¤   err¤= PGPOpenFileSpec( spec,
a67e06 ¤   ¤   ¤   kPFLFileOpenFlags_ReadWrite, (PGPFileIORef *)&io );
eb7d98 ¤   ¤   if ( IsntPGPError( err ) )
825b34 ¤   ¤   {
d61e94 ¤   ¤   ¤   err¤= sWriteBuiltInMappingsToIO( io );
09f8ee ¤   ¤   ¤   PGPFreeIO( io );
7ffdee ¤   ¤   ¤   io¤ = NULL;
e90fe4 ¤   ¤   }
e29371 ¤   }
5867c5 ¤
7fdeb7 ¤   return( err );
a8efe6 }
a0af5a
68af5a
cd0ccc #if PGP_MACINTOSH
2066dd ¤   static PGPError
909620 sAddFileInfoToSpec( PFLFileSpecRef spec )
4dbb36 {
262420 ¤   PFLFileSpecMacMetaInfo¤ metaInfo;
d99479 ¤   PGPError¤   ¤   ¤   ¤   err¤= kPGPError_NoErr;
1d67c5 ¤
b7fdf4 ¤   metaInfo.fInfo.fdCreator¤   = 'ttxt';
050387 ¤   metaInfo.fInfo.fdType¤  ¤   = 'TEXT';
80f3d7 ¤   metaInfo.fInfo.fdFlags¤ ¤   = 0;
7b3fb7 ¤   metaInfo.fInfo.fdLocation.h¤= -1;
7254c2 ¤   metaInfo.fInfo.fdLocation.v¤= -1;
2167c5 ¤
1cde8c ¤   err¤= PFLSetFileSpecMetaInfo( spec, &metaInfo );
a1deb7 ¤   return( err );
81efe6 }
12db21 #else
bc9963 #define sAddFileInfoToSpec( spec )¤ kPGPError_NoErr
6e7454 #endif
57af5a
2966dd ¤   static PGPError
5d404a pgpWriteMacBinaryMappings( PFLFileSpecRef toFile )
b6bb36 {
a69372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0e67c5 ¤
4b89f8 ¤   err¤= sAddFileInfoToSpec( toFile );
22f1e7 ¤   if ( IsntPGPError( err ) )
52c7a1 ¤   {
ddaa26 ¤   ¤   err¤= sWriteBuiltInMappingsToFile( toFile );
ce9371 ¤   }
43af5a
f7deb7 ¤   return( err );
99efe6 }
13af5a
24af5a
50c744 ¤   PGPError
0a8887 pgpInitMacBinaryMappings( void )
71bb36 {
d53ecb ¤   PGPError¤   ¤   err¤¤   ¤   = kPGPError_NoErr;
--af4b 000958b1c2540100272 Page 16 of pgpMacFileMapping.c
6a3030 ¤   PFLFileSpecRef¤ spec¤   ¤   = NULL;
f5897e ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetDefaultMemoryMgr();
de67c5 ¤
55d8b0 ¤   err¤= sGetMacBinaryFileSpec( memoryMgr, &spec );
93f1e7 ¤   if ( IsntPGPError( err ) )
bdc7a1 ¤   {
fc5c9d ¤   ¤   PGPBoolean¤ ¤   exists;
e21b52 ¤   ¤
748e5b ¤   ¤   err¤= PFLFileSpecExists( spec, &exists );
be3aa5 ¤   ¤   /* if file doesn't exist, then create it */
d37d98 ¤   ¤   if ( IsntPGPError( err ) )
575b34 ¤   ¤   {
218ebc ¤   ¤   ¤   if ( ! exists )
19f776 ¤   ¤   ¤   {
1a3020 ¤   ¤   ¤   ¤   err¤= pgpWriteMacBinaryMappings( spec );
96a3a6 ¤   ¤   ¤   }
1d3c6b ¤   ¤   ¤   if ( IsntPGPError( err ) )
5cf776 ¤   ¤   ¤   {
e79d6a ¤   ¤   ¤   ¤   err¤= pgpReadMacBinaryMappings( spec );
23a3a6 ¤   ¤   ¤   }
210fe4 ¤   ¤   }
6f87c7 ¤   ¤   ¤
6dd446 ¤   ¤   PFLFreeFileSpec( spec );
a076b2 ¤   ¤   spec¤   = NULL;
d89371 ¤   }
2167c5 ¤
58ff6b ¤   /* "soft" failure: init from built-in if we have to */
03054e ¤   if ( IsPGPError( err ) )
7ac7a1 ¤   {
4f2ed6 ¤   ¤   err¤= sInitFromBuiltIn( memoryMgr );
dc9832 ¤   ¤   pgpAssertNoErr( err );
6f9371 ¤   }
4f1b52 ¤   ¤
8b8c1a ¤   pgpAssertNoErr( err );
53deb7 ¤   return( err );
b0efe6 }
aaaf5a
e8af5a
ddc744 ¤   PGPError
aa6f01 pgpDisposeMacBinaryMappings( void )
a4bb36 {
859372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
9467c5 ¤
8cb15f ¤   if ( IsntNull( sMappingTable ) )
bfc7a1 ¤   {
e2a0bf ¤   ¤   pgpFree( sMappingTable );
f3e00c ¤   ¤   sMappingTable¤  = NULL;
4e9371 ¤   }
4267c5 ¤
dadeb7 ¤   return( err );
f8efe6 }
aaaf5a
01af5a
b3af5a
48af5a
96af5a
f6af5a
b3af5a
efaf5a
20af5a
5faf5a
d7af5a
a9af5a
31af5a
64af5a
abaf5a
2faf5a
40af5a
a6af5a
38af5a
34af5a
95af5a
--e1d8 00177d8b61540100272 Page 17 of pgpMacFileMapping.c
e0af5a
9d7e4d /*__Editor_settings____
89af5a
a94126 ¤   Local Variables:
9f7b17 ¤   tab-width: 4
bb0e6c ¤   End:
575f8c ¤   vi: ts=4 sw=4
f79e9b ¤   vim: si
77d062 _____________________*/
--856d 001e346fdd340100273 Page 1 of pgpMacFileMapping.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
046e5a ¤   $Id: pgpMacFileMapping.h,v 1.4.22.1 1998/11/12 03:23:24 heller Exp $
48f7f7 ____________________________________________________________________________*/
6412e3 #ifndef Included_pgpMacmapping_h¤   /* [ */
b80ed9 #define Included_pgpMacmapping_h
04af5a
5fc5d5 #include "pgpBase.h"
1eaf5a
d7af5a
b899c6 PGP_BEGIN_C_DECLARATIONS
0caf5a
60af5a
ecc21c #if PGP_MACINTOSH¤  /* [ */
54af5a
754fda /* determine if turning off MacBinary is appropriate for this file */
bae887 PGPBoolean¤ pgpOKToEncodeFSSpecWithoutMacBinary( const FSSpec *spec );
f0af5a
e71b9b /* map actual file data into mac creator/type pair */
e9b200 PGPError¤   pgpMapFileDataToMacCreatorType( const void *data,
040c44 ¤   ¤   ¤   ¤   OSType *creator, OSType *type );
702b85 ¤   ¤   ¤   ¤
43af5a
411d4f /* map file name extension into mac creator/type pair */
36d17b /* name is a pascal string */
9e8ffa PGPError¤   pgpMapFileNameToMacCreatorType( const unsigned char *name,
4b0c44 ¤   ¤   ¤   ¤   OSType *creator, OSType *type );
d8af5a
03af5a
3f9860 #else /* ] PGP_MACINTOSH [ */
22af5a
da0b81 typedef PGPUInt32¤  OSType;
d2af5a
41ddc8 #endif¤ /* ] PGP_MACINTOSH */
40af5a
ccaf5a
e660ea /* map a creator/type pair to a file name extension */
fd1f41 /* extension is of the form "doc", "bin", etc + null char */
0453af PGPError¤   pgpMapMacCreatorTypeToExtension( OSType creator, OSType type,
792220 ¤   ¤   ¤   ¤   char¤   extension[ 3 + 1 ] );
8baf5a
42c94c PGPBoolean¤ pgpIsValidExtensionForMacType( OSType creator, OSType type,
5d6219 ¤   ¤   ¤   ¤   char const * extension );
b22b85 ¤   ¤   ¤   ¤
f1af5a
ebaf5a
11f987 PGPError¤   pgpInitMacBinaryMappings( void );
e28965 PGPError¤   pgpDisposeMacBinaryMappings( void );
6faf5a
b71254 PGP_END_C_DECLARATIONS
f2af5a
7aaf5a
e5af5a
9dd4a6 #endif /* ] Included_pgpMacmapping_h */
f4af5a
3baf5a
457e4d /*__Editor_settings____
f5af5a
6b4126 ¤   Local Variables:
027b17 ¤   tab-width: 4
9d0e6c ¤   End:
db5f8c ¤   vi: ts=4 sw=4
c59e9b ¤   vim: si
e3d062 _____________________*/
--7443 001fe07bf0140100274 Page 1 of pgpMacUtils.c
bc38e5 /*
72979d ·* pgpMacUtils.c -- Various Macintosh utilities
a6775e ·*
79e28b ·* $Id: pgpMacUtils.c,v 1.8 1997/08/25 18:17:59 lloyd Exp $
10495d ·*/
52af5a
04e2ff #include "pgpConfig.h"
d0af5a
7cc21c #if PGP_MACINTOSH¤  /* [ */
43af5a
f976b7 #include "MacErrors.h"
9a2f8d #include "pgpErrors.h"
f052af #include "pgpMacUtils.h"
91af5a
11af5a
e1c744 ¤   PGPError
791549 pgpErrorFromMacError(
66bf84 ¤   OSErr¤  ¤   macError,
dff13b ¤   PGPError¤   defaultError)
64bb36 {
4826d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
2d67c5 ¤
5609b3 ¤   if (macError == noErr)
a7b840 ¤   ¤   return kPGPError_NoErr;
c067c5 ¤
327bf0 ¤   err¤= MacErrorToPGPError( macError );
443cda ¤   if ( err == kPGPError_UnknownError )
b9c7a1 ¤   {
e46174 ¤   ¤   pgpAssert( defaultError != kPGPError_NoErr );
40e92f ¤   ¤   err¤= defaultError;
b39371 ¤   }
ff67c5 ¤
8a5ea8 ¤   return err;
ffefe6 }
f4af5a
98db21 #else
05af5a
b32595 #error you shouldn't be compiling this file unless you're on a Mac
51af5a
dc520c #endif¤ PGP_MACINTOSH /* ] */
4038e5 /*
dee6c5 ·* Local Variables:
bd9b19 ·* tab-width: 4
02e7a4 ·* End:
e4b612 ·* vi: ts=4 sw=4
b06c42 ·* vim: si
fe495d ·*/
--cfb8 00110d29e9b40100275 Page 1 of pgpMacUtils.h
bc38e5 /*
454402 ·* pgpMacUtils.h -- Various Macintosh utilities
b2775e ·*
8d0fa8 ·* $Id: pgpMacUtils.h,v 1.7 1997/06/16 22:49:00 lloyd Exp $
a1495d ·*/
a2af5a
8ab538 #ifndef Included_pgpMacUtils_h¤ /* [ */
10ea74 #define Included_pgpMacUtils_h
ebaf5a
36728f #include <Types.h>
55af5a
abc5d5 #include "pgpBase.h"
5c2f8d #include "pgpErrors.h"
56af5a
7199c6 PGP_BEGIN_C_DECLARATIONS
d6af5a
1af0e2 PGPError ¤  ¤   pgpErrorFromMacError(OSErr macError,
9c6d49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPError defaultError);
47af5a
d51254 PGP_END_C_DECLARATIONS
7aaf5a
775857 #endif¤ /* ] Included_pgpMacUtils_h */
26af5a
0e38e5 /*
efe6c5 ·* Local Variables:
a19b19 ·* tab-width: 4
d3e7a4 ·* End:
79b612 ·* vi: ts=4 sw=4
f96c42 ·* vim: si
10495d ·*/
--7c12 000b22dd80140100276 Page 1 of pgpMemFile.c
bc38e5 /*
5e1b82 ·* pgpMemFile.c -- PGPFile implementation for memory files, based on PFL IO
f8775e ·*
0275f6 ·* $Id: pgpMemFile.c,v 1.15 1997/12/19 19:09:45 lloyd Exp $
6a495d ·*/
48af5a
9ce2ff #include "pgpConfig.h"
27af5a
0d495d #include <errno.h>
6afeb2 #include <stdio.h>
e1af5a
e472de #include "pgpFile.h"
d90859 #include "pgpCFB.h"
0a0d08 #include "pgpMem.h"
1c2f8d #include "pgpErrors.h"
aac26c #include "pgpContext.h"
f3a9cb #include "pgpIO.h"
80fbe2 #include "pgpMemoryIO.h"
a9af5a
5d7c67 /* This is the private data for memfiles */
d0f398 typedef struct MemFile_
47bb36 {
ad8a97 ¤   PGPContextRef¤  context;
77183d ¤   PGPIORef¤   ¤   ioRef;
ade59f ¤   PGPFileError¤   err;
ef1765 ¤   PGPError¤   ¤   error;
5d4586 } MemFile;
f1af5a
c33ef5 static long memFileTell(PGPFile *file);
74af5a
ce33c8 ¤   static void
a6e0a7 memSetError(PGPFile *file, PGPError code)
1ebb36 {
e1232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
5faf5a
1352ef ¤   mf->err.f = file;
b75f9b ¤   mf->err.fpos = memFileTell(file);
250276 ¤   mf->error = mf->err.error = code;
114ff2 ¤   mf->err.syserrno = 0;
7befe6 }
b4af5a
afd8bc ¤   static size_t
3435a5 memFileRead(void *ptr, size_t size, PGPFile *file)
26bb36 {
63232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
c4b744 ¤   PGPSize¤¤   bytesRead = 0;
4261e0 ¤   PGPError¤   err;
7caf5a
edbb75 ¤   if( IsPGPError( err = PGPIORead( mf->ioRef, size, ptr, &bytesRead ) ) )
7bb770 ¤   ¤   memSetError( file, err );
0241b5 ¤   return (size_t)bytesRead;
84efe6 }
b6af5a
53d8bc ¤   static size_t
e3f26c memFileWrite(void const *ptr, size_t size, PGPFile *file)
91bb36 {
64232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
8c61e0 ¤   PGPError¤   err;
61af5a
ceff47 ¤   if( IsPGPError( err = PGPIOWrite( mf->ioRef, size, ptr ) ) )
7db770 ¤   ¤   memSetError( file, err );
8e7b2c ¤   return (size_t)size;
f8efe6 }
7faf5a
c266dd ¤   static PGPError
5ba222 memFileFlush(PGPFile *file)
f5bb36 {
52232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
1b61e0 ¤   PGPError¤   err;
64af5a
48858a ¤   if( IsPGPError( err = PGPIOFlush( mf->ioRef ) ) )
b2b770 ¤   ¤   memSetError( file, err );
--b0a2 0009223db7a40100276 Page 2 of pgpMemFile.c
ec5ea8 ¤   return err;
2aefe6 }
e0af5a
2766dd ¤   static PGPError
a67033 memFileClose(PGPFile *file)
12bb36 {
50232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
7167c5 ¤
0bc8f4 ¤   pgpAssertAddrValid( file, PGPFile );
41af5a
c9b627 ¤   (void)PGPFreeIO( mf->ioRef );
d59aca ¤   PGPFreeData( mf );
f3251d ¤   PGPFreeData( file );
5a151e ¤   return kPGPError_NoErr;
97efe6 }
20af5a
856d4d ¤   static long
f04260 memFileTell(PGPFile *file)
ebbb36 {
02232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
6a7757 ¤   PGPFileOffset curPos = (PGPFileOffset)-1;
91af5a
239ffc ¤   /* Ignore error as we are called from error-setting routine */
879e19 ¤   (void)PGPIOGetPos( mf->ioRef, &curPos );
52a161 ¤   return (long) curPos;
c4efe6 }
13af5a
0e66dd ¤   static PGPError
e7c1e9 memFileSeek(PGPFile *file, long offset, int whence)
71bb36 {
ac288b ¤   MemFile *¤  ¤   mf = (MemFile *)file->priv;
b01ddc ¤   PGPFileOffset¤  newPos;
10fb19 ¤   PGPError¤   ¤   err;
12af5a
31b28b ¤   switch (whence)
2dc7a1 ¤   {
619a49 ¤   ¤   case SEEK_SET:
79b807 ¤   ¤   ¤   newPos = (PGPFileOffset)offset;
9bcdcb ¤   ¤   ¤   break;
cb3b71 ¤   ¤   case SEEK_CUR:
9ab820 ¤   ¤   ¤   PGPIOGetPos( mf->ioRef, &newPos );
c4d7f7 ¤   ¤   ¤   newPos += offset;
f0cdcb ¤   ¤   ¤   break;
fd5011 ¤   ¤   case SEEK_END:
fc1942 ¤   ¤   ¤   PGPIOGetEOF( mf->ioRef, &newPos );
47d7f7 ¤   ¤   ¤   newPos += offset;
53cdcb ¤   ¤   ¤   break;
f99371 ¤   }
e9af5a
d1f46a ¤   if( IsPGPError( err = PGPIOSetPos( mf->ioRef, newPos ) ) )
cdb770 ¤   ¤   memSetError( file, err );
24af5a
525ea8 ¤   return err;
ceefe6 }
ebaf5a
726c2c ¤   static PGPBoolean
d5b617 memFileEof(PGPFile const *file)
edbb36 {
e6232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
34af5a
67e2ab ¤   return PGPIOIsAtEOF( mf->ioRef );
ebefe6 }
69af5a
846d4d ¤   static long
de95aa memFileSizeAdvise(PGPFile const *file)
cdbb36 {
77a4a7 ¤   (void)file;
1fd116 ¤   return 0L;
21efe6 }
7baf5a
3e7bfc ¤   static PGPFileError const *
9230cb memFileError(PGPFile const *file)
--daec 0006a1cc63440100276 Page 3 of pgpMemFile.c
2cbb36 {
a8232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
6aaf5a
ada4a2 ¤   if (mf->error != kPGPError_NoErr)
6f6df5 ¤   ¤   return &mf->err;
350e24 ¤   else
787ed2 ¤   ¤   return NULL;
bfefe6 }
81af5a
1e33c8 ¤   static void
18f2d9 memFileClearError(PGPFile *file)
6ebb36 {
3f232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
1aaf5a
c6845e ¤   mf->error = kPGPError_NoErr;
14efe6 }
6baf5a
a066dd ¤   static PGPError
b3e784 memFileWrite2Read(PGPFile *file)
d2bb36 {
a8232f ¤   MemFile *¤  mf = (MemFile *)file->priv;
b061e0 ¤   PGPError¤   err;
e6af5a
6cec52 ¤   /* Just rewind */
c3c2f3 ¤   if( IsPGPError( err = PGPIOSetPos( mf->ioRef, 0 ) ) )
52b770 ¤   ¤   memSetError( file, err );
3a5ea8 ¤   return err;
56efe6 }
35af5a
9d4a24 ¤   static PGPCFBContext *
c2094d memFileCfb(PGPFile const *file)
8abb36 {
17f005 ¤   /* For future expansion */
e9a4a7 ¤   (void)file;
183f59 ¤   return NULL;
adefe6 }
e5af5a
567078 ¤   PGPFile *
6de40f pgpFileMemOpen(
50520e ¤   PGPContextRef¤  context,
29bcb9 ¤   void *base, size_t len)
d2bb36 {
07292d ¤   PGPFile *¤  file;
bed0a0 ¤   MemFile *¤  mf;
0c61e0 ¤   PGPError¤   err;
b6af5a
88a4e0 ¤   file = (PGPFile *)pgpContextMemAlloc( context,
b6301e ¤   ¤   sizeof(*file), kPGPMemoryMgrFlags_Clear);
fad20a ¤   if (file == NULL)
0a7ed2 ¤   ¤   return NULL;
be60a4 ¤   file->context¤  = context;
52af5a
3136db ¤   mf = (MemFile *)pgpContextMemAlloc( context,
6a30ce ¤   ¤   sizeof(*mf), kPGPMemoryMgrFlags_Clear);
0967cc ¤   if (mf == NULL)
0cc7a1 ¤   {
a68d94 ¤   ¤   pgpContextMemFree( context, file);
ca7ed2 ¤   ¤   return NULL;
229371 ¤   }
36af5a
f72fa1 ¤   mf->context¤= context;
58af5a
1eeff0 ¤   /* Allocate ioRef structure */
2965ad ¤   if( IsPGPError( err = PGPNewMemoryIO( PGPGetContextMemoryMgr( context ),
5c1949 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··(PGPMemoryIORef *)&mf->ioRef ) ) )
35c7a1 ¤   {
3837b7 ¤   ¤   pgpContextMemFree( context, mf );
ac1b4e ¤   ¤   pgpContextMemFree( context, file );
117ed2 ¤   ¤   return NULL;
d09371 ¤   }
9baf5a
6a0b0c ¤   /* Load ioRef with our data */
--3632 0018028971240100276 Page 4 of pgpMemFile.c
fcdc5f ¤   if( len != 0 )
68c7a1 ¤   {
02d28e ¤   ¤   if( IsPGPError( err = PGPIOWrite( mf->ioRef, len, base ) ) ||
4842a3 ¤   ¤   ¤   IsPGPError( err = PGPIOSetPos( mf->ioRef, 0 ) ) )
845b34 ¤   ¤   {
e41aa4 ¤   ¤   ¤   PGPFreeIO( mf->ioRef );
f00e72 ¤   ¤   ¤   pgpContextMemFree( context, mf );
79031e ¤   ¤   ¤   pgpContextMemFree( context, file );
79cf03 ¤   ¤   ¤   return NULL;
760fe4 ¤   ¤   }
bb9371 ¤   }
4daf5a
d43e8c ¤   file->priv = mf;
26ac79 ¤   file->read = memFileRead;
f56cb0 ¤   file->write = memFileWrite;
da7a96 ¤   file->flush = memFileFlush;
328c78 ¤   file->close = memFileClose;
d25667 ¤   file->tell = memFileTell;
3144d5 ¤   file->seek = memFileSeek;
5af5ec ¤   file->eof = memFileEof;
6f2ad8 ¤   file->sizeAdvise = memFileSizeAdvise;
d6c1cc ¤   file->error = memFileError;
a74df1 ¤   file->clearError = memFileClearError;
99580d ¤   file->write2read = memFileWrite2Read;
e7ee13 ¤   file->cfb = memFileCfb;
0a28f6 ¤   return file;
4defe6 }
80af5a
--7e27 00192c4d50d40100277 Page 1 of pgpMsg.c
bc38e5 /*
27fb25 ·* pgpMsg.c -- a way to obtain the list of PGP Messages
8e775e ·*
ed7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
de775e ·*
d0fb3b ·* $Id: pgpMsg.c,v 1.4 1997/06/16 22:49:00 lloyd Exp $
0f495d ·*/
b8af5a
464d3e #include <stdio.h>¤ /* For sprintf() */
6baf5a
8de2ff #include "pgpConfig.h"
88af5a
57122a #define PGPMSG(msg, string) { msg, string },
15af5a
ba1b4e /* List of all message codes */
414fda struct pgpmsg_t {
1bed55 ¤   int msg;
53b0e8 ¤   char const *string;
e082f7 };
c3af5a
2249c2 static struct pgpmsg_t const pgpmsglist[] = {
431bea #include "pgpMsg.h"
203f0e ¤   { 0, 0 }¤   /* End-of-list placeholder */
3a82f7 };
9baf5a
cc382f /* Get rid of warning from gcc about missing prototype */
e3650d char const ·*pgpmsgString (int code);
0daf5a
bb5cc8 char const *
8a9a83 pgpmsgString (int code)
7abb36 {
a4743f ¤   unsigned i;
31e0af ¤   static char buf[] = "Unknown msg code xxxxxxxxx";
7c90f9 ¤   /* ··················1234567890123456789 */
ccaf5a
0dd4ca ¤   for (i = 0; i < sizeof (pgpmsglist)/sizeof (*pgpmsglist); i++) {
4ddf50 ¤   ¤   if (pgpmsglist[i].msg == code)
f52ff2 ¤   ¤   ¤   return pgpmsglist[i].string;
b59371 ¤   }
6ad3a1 ¤   sprintf (buf+19, "%+d", code);
37dfa1 ¤   return buf;
92efe6 }
--3f42 000b73a81a740100278 Page 1 of pgpPassCach.c
bc38e5 /*
e80385 ·* pgpPassCach.c -- A Passphrase Cache -- keep a cache of passphrases and
658e9d ·* try them against ESKs and Secret Keys. ·This way you only have to
3011f1 ·* type your passphrase once, it gets cached, and then it gets used
ed78b5 ·* again and again.
0e775e ·*
e97ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
43775e ·*
039e0f ·* $Id: pgpPassCach.c,v 1.17 1998/02/24 22:38:28 hal Exp $
ae495d ·*/
3d324c #include <string.h>
92af5a
b3e2ff #include "pgpConfig.h"
14af5a
dbfeb2 #include <stdio.h>
e6af5a
6d57c7 #include "pgpESK.h"
6b0d08 #include "pgpMem.h"
ef2d83 #include "pgpPassCach.h"
772f8d #include "pgpErrors.h"
c6cdc2 #include "pgpPubKey.h"
910d6d #include "pgpEnv.h"
21c26c #include "pgpContext.h"
09af5a
4a532f typedef struct PgpPass {
530a43 ¤   char *¤ ¤   ¤   ¤   pass;
ec4417 ¤   size_t ¤¤   ¤   ¤   passlen;
947b2e ¤   struct PgpPass *¤   next;
4d723e ¤   DEBUG_STRUCT_CONSTRUCTOR( PgpPass )
078a2c } PgpPass ;
30af5a
913c81 struct PGPPassCache {
3d8a97 ¤   PGPContextRef¤  context;
5127f1 ¤   PGPEnv const *¤ env;
a1911f ¤   PgpPass *¤  ¤   passlist;
7d70d6 ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPPassCache )
d282f7 };
a1af5a
35491a PGPPassCache *
18d77a pgpPassCacheCreate (PGPEnv const *env)
36bb36 {
2c2dec ¤   PGPPassCache *cache;
b3fbaf ¤   PGPContextRef¤  ¤   context¤= pgpenvGetContext( env );
7caf5a
d86e02 ¤   cache = (PGPPassCache *) pgpContextMemAlloc( context,
7cde43 ¤   ¤   sizeof (*cache), kPGPMemoryMgrFlags_Clear);
396195 ¤   if (cache) {
092854 ¤   ¤   cache->env = env;
30e26a ¤   ¤   cache->context¤ = context;
799371 ¤   }
6d1b52 ¤   ¤
6831c1 ¤   return cache;
afefe6 }
abaf5a
36314a void
d41f50 pgpPassCacheDestroy (PGPPassCache *cache)
b2bb36 {
2b629d ¤   PgpPass *p, *t;
b37925 ¤   PGPContextRef¤  ¤   context;
e3af5a
a5089b ¤   if (!cache)
b199bf ¤   ¤   return;
eaaf5a
a1e42a ¤   context¤= cache->context;
71af5a
19e8fc ¤   for (p = cache->passlist; p; p = t) {
bfe723 ¤   ¤   t = p->next;
5eaf5a
613d24 ¤   ¤   pgpClearMemory (p->pass, p->passlen);
403cfe ¤   ¤   pgpContextMemFree( context, p->pass);
882fcc ¤   ¤   pgpClearMemory( p, ·sizeof (*p));
b71a40 ¤   ¤   pgpContextMemFree( context, p);
--d8ed 000cccbdc5b40100278 Page 2 of pgpPassCach.c
a19371 ¤   }
eed0e4 ¤   pgpClearMemory( cache, ·sizeof (*cache));
3de3b8 ¤   pgpContextMemFree( context, cache);
5eefe6 }
46af5a
654d2f int
083ff3 pgpPassCacheAdd (PGPPassCache *cache, char const *pass, size_t passlen)
96bb36 {
c78d0e ¤   PgpPass *p;
ac99d0 ¤   char *buf;
5f7925 ¤   PGPContextRef¤  ¤   context;
5567c5 ¤
a7d67d ¤   pgpAssertAddrValid( cache, PGPPassCache );
f9af5a
33e320 ¤   if (!cache || !pass || ! passlen)
d062b5 ¤   ¤   return kPGPError_BadParams;
76e42a ¤   context¤= cache->context;
cdaf5a
a3e42a ¤   context¤= cache->context;
b967c5 ¤
9eaa5c ¤   p = (PgpPass *) pgpContextMemAlloc( context,
f0eea6 ¤   ¤   sizeof (*p), kPGPMemoryMgrFlags_Clear);
dd4dda ¤   if (!p)
a64030 ¤   ¤   return kPGPError_OutOfMemory;
42af5a
e712b0 ¤   buf = (char *)pgpContextMemAlloc( context,
d2d128 ¤   ¤   passlen + 1, kPGPMemoryMgrFlags_Clear);
dc3686 ¤   if (!buf) {
321a40 ¤   ¤   pgpContextMemFree( context, p);
274030 ¤   ¤   return kPGPError_OutOfMemory;
af9371 ¤   }
3faf5a
440c4d ¤   memcpy (buf, pass, passlen);
4e6b81 ¤   buf[passlen] = '\0';
721322 ¤   pgpClearMemory( p, ·sizeof (*p));
07af5a
ca9807 ¤   p->pass = buf;
677551 ¤   p->passlen = passlen;
abe2bf ¤   p->next = cache->passlist;
edb928 ¤   cache->passlist = p;
5daf5a
453e6b ¤   return 0;
34efe6 }
01af5a
f9af5a
6138e5 /*
829dbf ·* Returns:
ae0083 ·* < 0 : error
db00bd ·* = 0 : no phrases worked
f703f0 ·* > 0 : a pass phrase worked -- session key in key, size in keylen
d9495d ·*/
024d2f int
7b6deb pgpPassCacheTryEsk (PGPPassCache const *cache, PGPESK const *esk,
cabfa6 ¤   ¤   ····int (*tryKey) (void *arg, PGPByte const *key, size_t keylen),
431f1a ¤   ¤   ····void *tryarg, PGPByte *key, size_t *keylen)
a2bb36 {
318d0e ¤   PgpPass *p;
764ba4 ¤   int i;
eeaf5a
c2bcff ¤   if (!cache || !esk || !key || !keylen || !tryKey)
1b62b5 ¤   ¤   return kPGPError_BadParams;
c8af5a
925023 ¤   if (pgpEskType (esk) != PGP_ESKTYPE_PASSPHRASE)
eb62b5 ¤   ¤   return kPGPError_BadParams;
a0af5a
cd29f6 ¤   for (p = cache->passlist; p; p = p->next) {
b2bd93 ¤   ¤   i = pgpEskConvDecrypt (esk, cache->env, p->pass, p->passlen,
800f72 ¤   ¤   ¤   ¤   ·······key);
1eaf5a
b9195b ¤   ¤   if (i < 0)¤ ¤   /* error */
c79eb9 ¤   ¤   ¤   return i;
ccaf5a
--fc47 001fa388d3440100278 Page 3 of pgpPassCach.c
2a3f9a ¤   ¤   if (i > 0) {¤   ¤   /* got a key -- try it */
759876 ¤   ¤   ¤   *keylen = i;
127a5f ¤   ¤   ¤   i = tryKey (tryarg, key, *keylen);
35b4a3 ¤   ¤   ¤   if (!i)¤¤   /* it worked */
121c2d ¤   ¤   ¤   ¤   return 1;
0f0fe4 ¤   ¤   }
319371 ¤   }
4b3283 ¤   /* none of the cached passphrases worked */
8d3e6b ¤   return 0;
6defe6 }
31af5a
6538e5 /*
f23e20 ·* ·Returns:
250083 ·* < 0 : error
9eabcf ·* = 0 : could not unlock key
54f3c1 ·* > 0 : success -- key unlocked
0c495d ·*/
e44d2f int
ab0772 pgpPassCacheTryKey (PGPPassCache const *cache, PGPSecKey *seckey)
11bb36 {
9a8d0e ¤   PgpPass *p;
a14ba4 ¤   int i;
48af5a
d3af32 ¤   if (!cache || !seckey)
4b62b5 ¤   ¤   return kPGPError_BadParams;
d6af5a
d529f6 ¤   for (p = cache->passlist; p; p = p->next) {
084ccb ¤   ¤   i = pgpSecKeyUnlock (seckey, cache->env, p->pass, p->passlen, FALSE);
8110cd ¤   ¤   if (i)
b19eb9 ¤   ¤   ¤   return i;
2f9371 ¤   }
683e6b ¤   return 0;
faefe6 }
--ce41 00125f45a5640100279 Page 1 of pgpPassCach.h
bc38e5 /*
5de56d ·* pgpPassCach.h -- A Passphrase Cache
a1775e ·*
5b7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
9d775e ·*
a9daf6 ·* $Id: pgpPassCach.h,v 1.8 1997/06/25 19:41:27 lloyd Exp $
e6495d ·*/
adaf5a
72563b #ifndef Included_pgpPassCach_h
df21c8 #define Included_pgpPassCach_h
4aaf5a
14d11f #include "pgpUsuals.h"
deaf5a
ba99c6 PGP_BEGIN_C_DECLARATIONS
8caf5a
8cadb8 #include "pgpOpaqueStructs.h"
1baf5a
30af5a
b982e1 PGPPassCache ·*pgpPassCacheCreate (PGPEnv const *env);
9211a2 void ·pgpPassCacheDestroy (PGPPassCache *cache);
31e29f int ·pgpPassCacheAdd (PGPPassCache *cache, char const *pass,
2b6348 ¤   ¤   ·····size_t passlen);
d8091f int ·pgpPassCacheTryEsk (PGPPassCache const *cache,
283d2d ¤   ¤   ¤   PGPESK const *esk,
414cd3 ¤   ¤   ¤   int (*tryKey) (void *arg, PGPByte const *key,
fb60a0 ¤   ¤   ¤   ¤   ·······size_t keylen),
ac49de ¤   ¤   ¤   void *tryarg, PGPByte *key, size_t *keylen);
e37283 int ·pgpPassCacheTryKey (PGPPassCache const *cache,
6f779c ¤   ¤   ¤   PGPSecKey *seckey);
0daf5a
3e1254 PGP_END_C_DECLARATIONS
58af5a
25d578 #endif /* Included_pgpPassCach_h */
--0a60 000803523df4010027a Page 1 of pgpPipeFile.c
bc38e5 /*
bd9d86 ·* pgpPipeFile.c -- a PGPFile interface to write to Pipelines
ad775e ·*
ec7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
67775e ·*
a88959 ·* $Id: pgpPipeFile.c,v 1.19 1997/12/12 01:14:52 heller Exp $
bc495d ·*/
56af5a
81e2ff #include "pgpConfig.h"
61af5a
42feb2 #include <stdio.h>
77af5a
b372de #include "pgpFile.h"
790d08 #include "pgpMem.h"
842ece #include "pgpPipeline.h"
eb2f8d #include "pgpErrors.h"
4ec26c #include "pgpContext.h"
56af5a
0e32a5 typedef struct File {
4c0606 ¤   PGPFileError err;
8408fe ¤   PGPPipeline *head;
4587a6 ¤   PGPError¤   error;
b9489e ¤   DEBUG_STRUCT_CONSTRUCTOR( File )
b474ab } File;
ebaf5a
a72978 static void
bc0880 setError (PGPFile *file, PGPError code)
a5bb36 {
cb8974 ¤   File *fp = (File *)file->priv;
d0af5a
bec45b ¤   fp->err.f = file;
5b313f ¤   fp->err.error = code;
c6f4c6 ¤   fp->error = code;
74efe6 }
5daf5a
1d5d09 static size_t
152221 pipeRead (void *ptr, size_t size, PGPFile *file)
46bb36 {
547441 ¤   (void) ptr;
bbe1b0 ¤   (void) size;
af7bfb ¤   setError (file, kPGPError_IllegalFileOp);
cf3e6b ¤   return 0;
a3efe6 }
3daf5a
575d09 static size_t
a26975 pipeWrite (void const *ptr, size_t size, PGPFile *file)
4ebb36 {
b6f786 ¤   File *fp = (File *) file->priv;
a6328c ¤   PGPError code = kPGPError_NoErr;
acaf5a
281084 ¤   size = fp->head->write (fp->head, (PGPByte const *)ptr, size, &code);
7b0b15 ¤   setError (file, code);
38f6fa ¤   return size;
61efe6 }
95af5a
aef1ae static PGPError
e95e1b pipeFlush (PGPFile *file)
78bb36 {
9bf786 ¤   File *fp = (File *) file->priv;
eb2c42 ¤   PGPError¤   code;
42af5a
5233ec ¤   code = fp->head->flush (fp->head);
cc0b15 ¤   setError (file, code);
61e231 ¤   return code;
15efe6 }
07af5a
9bf1ae static PGPError
695fc1 pipeClose (PGPFile *file)
d9bb36 {
1ff786 ¤   File *fp = (File *) file->priv;
58328c ¤   PGPError code = kPGPError_NoErr;
80e9fa ¤   PGPContextRef¤  cdkContext;
--4c4d 000141007744010027a Page 2 of pgpPipeFile.c
e0af5a
31c8f4 ¤   pgpAssertAddrValid( file, PGPFile );
7c94b2 ¤   cdkContext¤ = file->context;
4daf5a
5b02e1 ¤   code = fp->head->sizeAdvise (fp->head, 0);
860b15 ¤   setError (file, code);
5f6652 ¤   if (code)
8da3ba ¤   ¤   return code;
08af5a
6387c2 ¤   fp->head->teardown (fp->head);
20af5a
bba03b ¤   pgpClearMemory( fp, ·sizeof (*fp));
5fe093 ¤   pgpContextMemFree( cdkContext, fp);
de6cce ¤   pgpClearMemory( file, ·sizeof (*file));
c13ed5 ¤   pgpContextMemFree( cdkContext, file);
56151e ¤   return kPGPError_NoErr;
caefe6 }
a3af5a
b277fd static long
577177 pipeTell (PGPFile *file)
33bb36 {
583fbc ¤   (void) file;
613e6b ¤   return 0;
22efe6 }
faaf5a
5cf1ae static PGPError
5c35ac pipeSeek (PGPFile *file, long offset, int whence)
c8bb36 {
873fbc ¤   (void) file;
d75f5c ¤   (void) offset;
26ff23 ¤   (void) whence;
5faf5a
a85fd1 ¤   return kPGPError_IllegalFileOp;
f7efe6 }
d4af5a
4256b6 static PGPBoolean
f7d52b pipeEof (PGPFile const *file)
cbbb36 {
4d3fbc ¤   (void) file;
84a230 ¤   return FALSE;
c0efe6 }
56af5a
07d6a2 static PGPFileError const *
18cd82 pipeError (PGPFile const *file)
5dbb36 {
5af786 ¤   File *fp = (File *) file->priv;
97af5a
685cdd ¤   if (fp->error)
4d1de8 ¤   ¤   return &(fp->err);
e93f59 ¤   return NULL;
bfefe6 }
bcaf5a
ea2978 static void
72abec pipeClearError (PGPFile *file)
d9bb36 {
dff786 ¤   File *fp = (File *) file->priv;
44af5a
a143a9 ¤   fp->error = kPGPError_NoErr;
8cefe6 }
bbaf5a
d7f1ae static PGPError
b2ff7f pipeWrite2read (PGPFile *file)
1dbb36 {
813fbc ¤   (void) file;
965fd1 ¤   return kPGPError_IllegalFileOp;
6fefe6 }
7aaf5a
c2a8c5 static PGPCFBContext *
6b284b pipeCfb (PGPFile const *file)
1bbb36 {
df3fbc ¤   (void) file;
143f59 ¤   return NULL;
--d67b 001dbe1c7fc4010027a Page 3 of pgpPipeFile.c
7aefe6 }
46af5a
4cdc3a PGPFile *
53929f pgpFilePipelineOpen (PGPPipeline *mod)
5bbb36 {
34c586 ¤   PGPFile *fp;
e80e2d ¤   File *ffp;
c88060 ¤   PGPContextRef¤  ¤   cdkContext;
a7af5a
dbd512 ¤   pgpAssertAddrValid( mod, PGPPipeline );
5f8679 ¤   cdkContext¤ = mod->cdkContext;
6067c5 ¤
2fe094 ¤   if (!mod)
f57ed2 ¤   ¤   return NULL;
78af5a
013704 ¤   fp = (PGPFile *)pgpContextMemAlloc( cdkContext,
dbb0e9 ¤   ¤   sizeof (*fp), kPGPMemoryMgrFlags_Clear);
a8485d ¤   if (!fp)
b37ed2 ¤   ¤   return NULL;
11af5a
4c1a8f ¤   ffp = (File *)pgpContextMemAlloc( cdkContext,
310a44 ¤   ¤   sizeof (*ffp), kPGPMemoryMgrFlags_Clear);
dc98e5 ¤   if (!ffp) {
1e68f5 ¤   ¤   pgpContextMemFree( cdkContext, fp);
697ed2 ¤   ¤   return NULL;
ad9371 ¤   }
f2af5a
5b955b ¤   ffp->head = mod;
09af5a
628a6c ¤   fp->priv = ffp;
0ece5c ¤   fp->read = pipeRead;
06e9a9 ¤   fp->write = pipeWrite;
417c7e ¤   fp->flush = pipeFlush;
c2dc63 ¤   fp->close = pipeClose;
29254b ¤   fp->tell = pipeTell;
7d550e ¤   fp->seek = pipeSeek;
e5883d ¤   fp->eof = pipeEof;
f2411f ¤   fp->error = pipeError;
8cc5c4 ¤   fp->clearError = pipeClearError;
c2f6ef ¤   fp->write2read = pipeWrite2read;
ea1677 ¤   fp->cfb = pipeCfb;
1224ab ¤   fp->context = cdkContext;
c3af5a
816c97 ¤   return fp;
9fefe6 }
a5af5a
adaf5a
637e4d /*__Editor_settings____
99af5a
464126 ¤   Local Variables:
e27b17 ¤   tab-width: 4
370e6c ¤   End:
f45f8c ¤   vi: ts=4 sw=4
3a9e9b ¤   vim: si
dbd062 _____________________*/
--e2bd 00083dbb6294010027b Page 1 of pgpStr2Key.c
bc38e5 /*
4a8c41 ·* pgpStr2Key.c -- A prototype string-to-key framework.
e6775e ·*
89cfe3 ·* $Id: pgpStr2Key.c,v 1.26 1998/06/11 18:28:25 hal Exp $
d2495d ·*/
4daf5a
6be2ff #include "pgpConfig.h"
d1af5a
62324c #include <string.h>
ae733c #include <stddef.h>¤/* For offsetof() */
3baf5a
2fa146 #include "pgpDebug.h"
ab5579 #include "pgpStr2Key.h"
055417 #include "pgpHashPriv.h"
930d08 #include "pgpMem.h"
e42f8d #include "pgpErrors.h"
602c96 #include "pgpRandomX9_17.h"
640d6d #include "pgpEnv.h"
a8c26c #include "pgpContext.h"
44af5a
9f8d2a /* Number of chars to hash when creating default S2K */
4614bf #define SALT_CHARS_DEFAULT¤ ¤   32768
ceaf5a
0f5faa /* It turns out that they all use the same private context structure */
3d96ec typedef struct StringToKeyPriv {
47ee3d ¤   PGPEnv const *env;
923d22 ¤   PGPHashVTBL const *hash;
4ae791 ¤   PGPByte buf[1];¤/* Variable-sized */
638b5d ¤   DEBUG_STRUCT_CONSTRUCTOR( StringToKeyPriv )
70beca } StringToKeyPriv ;
a8af5a
a7a49b /* And it can be destroyed with a common routine */
c12978 static void
09b8ec s2kDestroy(PGPStringToKey *s2k)
77bb36 {
6267c5 ¤
89d0c3 ¤   StringToKeyPriv *priv = (StringToKeyPriv *)s2k->priv;
8767c5 ¤
76d591 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( priv->env );
0867c5 ¤
40734a ¤   pgpClearMemory( priv, ·s2k->encodelen+offsetof(StringToKeyPriv, buf));
f97c7c ¤   pgpContextMemFree( cdkContext, priv);
9ecb43 ¤   pgpClearMemory( s2k, ·sizeof(*s2k));
3c38a3 ¤   pgpContextMemFree( cdkContext, s2k);
84efe6 }
fcaf5a
608ee6 static PGPStringToKey *
a991a4 s2kAlloc(PGPEnv const *env, PGPHashVTBL const *h, unsigned size)
96bb36 {
bcfc2b ¤   StringToKeyPriv *priv;
005cb3 ¤   PGPStringToKey *s2k = NULL;
04c520 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( env );
2faf5a
75c7db ¤   priv = (StringToKeyPriv *)
46dd05 ¤   ¤   pgpContextMemAlloc( cdkContext,
ddf247 ¤   ¤   ¤   offsetof(StringToKeyPriv, buf) + size, kPGPMemoryMgrFlags_Clear);
e4fb7d ¤   if (priv) {
1f10de ¤   ¤   s2k = (PGPStringToKey *)pgpContextMemAlloc( cdkContext,
7c02f9 ¤   ¤   ¤   sizeof(*s2k), kPGPMemoryMgrFlags_Clear);
cfc6df ¤   ¤   if ( IsntNull( s2k ) ) {
c24c62 ¤   ¤   ¤   s2k->priv = priv;
19bd6b ¤   ¤   ¤   s2k->encoding = priv->buf;
3dfb5c ¤   ¤   ¤   s2k->encodelen = size;
e380e6 ¤   ¤   ¤   s2k->destroy = s2kDestroy;
5e1df1 ¤   ¤   ¤   priv->env = env;
eb3280 ¤   ¤   ¤   priv->hash = h;
b5a8b2 ¤   ¤   ¤   if (h)
006852 ¤   ¤   ¤   ¤   priv->buf[1] = h->algorithm;
4a0fe4 ¤   ¤   }
a40e1d ¤   ¤   else
555b34 ¤   ¤   {
8339d3 ¤   ¤   ¤   pgpContextMemFree( cdkContext, priv );
--1d64 000a207b45d4010027b Page 2 of pgpStr2Key.c
dddfb1 ¤   ¤   ¤   priv¤   = NULL;
120fe4 ¤   ¤   }
629371 ¤   }
42de4c ¤   return s2k;
98efe6 }
dfaf5a
c5fa70 /* Allocate an array of "num" hash private buffers, all sharing the same hash*/
e1e094 static void **
071ece multiHashCreate(
e63163 ¤   PGPContextRef¤  cdkContext,
cc5126 ¤   PGPHashVTBL const *h, unsigned num)
febb36 {
8c097a ¤   void **v;
a0141e ¤   void *p;
6607cb ¤   unsigned i, j;
6d68b3 ¤   PGPByte const b = 0;
aeaf5a
559059 ¤   v = (void **)pgpContextMemAlloc( cdkContext,
82b4f4 ¤   ¤   num * sizeof(*v), kPGPMemoryMgrFlags_Clear);
a79b03 ¤   if (!v)
ff7ed2 ¤   ¤   return NULL;
44af5a
d8f910 ¤   for (i = 0; i < num; i++) {
ac160e ¤   ¤   p = pgpContextMemAlloc( cdkContext,
d2fa64 ¤   ¤   ¤   h->context_size, kPGPMemoryMgrFlags_Clear);
827568 ¤   ¤   if (!p) {
88db06 ¤   ¤   ¤   while (i) {
56cb50 ¤   ¤   ¤   ¤   pgpClearMemory(v[--i], h->context_size);
95131e ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, v[i]);
88a3a6 ¤   ¤   ¤   }
dc603e ¤   ¤   ¤   pgpContextMemFree( cdkContext, v);
fdcf03 ¤   ¤   ¤   return NULL;
210fe4 ¤   ¤   }
80a3f6 ¤   ¤   h->init(p);
97f4c8 ¤   ¤   /* Initialze the PGPHashContext with leading null bytes */
d30662 ¤   ¤   for (j = 0; j < i; j++)
f04b7d ¤   ¤   ¤   h->update(p, &b, 1);
9aa21f ¤   ¤   v[i] = p;
bc9371 ¤   }
aceec4 ¤   return v;
c2efe6 }
70af5a
198513 /* Update an array of hash private buffers, all sharing the same hash */
122978 static void
416909 multiHashUpdate(PGPHashVTBL const *h, void * const *v, unsigned num,
138c2a ¤   PGPByte const *string, size_t len)
a0bb36 {
eb80b9 ¤   while (num--)
eda622 ¤   ¤   h->update(*v++, string, len);
2eefe6 }
59af5a
7c38e5 /*
befa81 ·* Extract the final combined string from an array of hash private buffers,
5cd351 ·* then wipe and free them.
e3495d ·*/
792978 static void
d55077 multiHashFinal(
733163 ¤   PGPContextRef¤  cdkContext,
8f7f32 ¤   PGPHashVTBL const *h, void **v, PGPByte *key, size_t klen)
44bb36 {
96f673 ¤   void **v0 = v;
4281de ¤   unsigned hsize = h->hashsize;
e1af5a
9c404a ¤   while (klen > hsize) {
9ed496 ¤   ¤   memcpy(key, h->final(*v), hsize);
0af282 ¤   ¤   key += hsize;
c5c495 ¤   ¤   klen -= hsize;
1c5617 ¤   ¤   pgpClearMemory(*v, h->context_size);
124c57 ¤   ¤   pgpContextMemFree( cdkContext, *(v++) );
519371 ¤   }
303ac1 ¤   memcpy(key, h->final(*v), klen);
a250af ¤   pgpClearMemory(*v, h->context_size);
--b798 000fb3634014010027b Page 3 of pgpStr2Key.c
d61d1b ¤   pgpContextMemFree( cdkContext, *v);
07af5a
ed4264 ¤   pgpContextMemFree( cdkContext, v0);
52efe6 }
33af5a
e2beb7 static int
7beb55 s2kSimple(PGPStringToKey const *s2k, char const *str,
dd4d27 ¤   size_t slen, PGPByte *key, size_t klen)
61bb36 {
e1fcf8 ¤   unsigned num;
fbefa5 ¤   StringToKeyPriv const *priv;
bb602d ¤   PGPHashVTBL const *h;
b1097a ¤   void **v;
5a8060 ¤   PGPContextRef¤  ¤   cdkContext;
1aaf5a
a4ac75 ¤   pgpAssert(s2k->encodelen == 2);
5caf5a
8ee7b2 ¤   if (!klen)
bd3d7d ¤   ¤   return 0;¤  /* Okay, I guess... */
8baf5a
a18fec ¤   priv = (StringToKeyPriv *)s2k->priv;
748c6b ¤   h = priv->hash;
9ffebb ¤   pgpAssert(h->algorithm == priv->buf[1]);
8bae46 ¤   cdkContext¤ = pgpenvGetContext( priv->env );
5267c5 ¤
421039 ¤   num = (klen-1)/h->hashsize + 1;
c6c530 ¤   v = multiHashCreate( cdkContext, h, num);
c49b03 ¤   if (!v)
214030 ¤   ¤   return kPGPError_OutOfMemory;
1baadd ¤   multiHashUpdate (h, v, num, (PGPByte const *)str, slen);
4dddab ¤   multiHashFinal( cdkContext, h, v, key, klen);
14af5a
353e6b ¤   return 0;
65efe6 }
10af5a
cbaf5a
3bbeb7 static int
6534f1 s2kSalted(PGPStringToKey const *s2k, char const *str,
264d27 ¤   size_t slen, PGPByte *key, size_t klen)
c6bb36 {
51fcf8 ¤   unsigned num;
33efa5 ¤   StringToKeyPriv const *priv;
5a602d ¤   PGPHashVTBL const *h;
df097a ¤   void **v;
6718f8 ¤   PGPContextRef¤  ¤   cdkContext¤ = NULL;
1aaf5a
bf3385 ¤   pgpAssert(s2k->encodelen == 10);
bdaf5a
9ee7b2 ¤   if (!klen)
803d7d ¤   ¤   return 0;¤  /* Okay, I guess... */
fcaf5a
fb8fec ¤   priv = (StringToKeyPriv *)s2k->priv;
4eae46 ¤   cdkContext¤ = pgpenvGetContext( priv->env );
248c6b ¤   h = priv->hash;
5afebb ¤   pgpAssert(h->algorithm == priv->buf[1]);
831039 ¤   num = (klen-1)/h->hashsize + 1;
eec530 ¤   v = multiHashCreate( cdkContext, h, num);
039b03 ¤   if (!v)
d44030 ¤   ¤   return kPGPError_OutOfMemory;
eacfee ¤   multiHashUpdate ( h, v, num, priv->buf+2, 8);
31aa08 ¤   multiHashUpdate ( h, v, num, (PGPByte const *)str, slen);
2cddab ¤   multiHashFinal( cdkContext, h, v, key, klen);
9caf5a
2b3e6b ¤   return 0;
0eefe6 }
d9af5a
b838e5 /*
66416b ·* The count is stored as 4.4 bit normalized floating-point. ·The high
f96c59 ·* 4 bits are the exponent (with a bias of 6), and the low 4 bits
37fc36 ·* are the mantissa. ·0x12 corresponds to (16+0x2) << (0x1+6).
41f4bf ·* The minimum value is (16+0) << (0+6) = 0x400 = 1024.
fb95a7 ·* The maximum is (16+0xf) << (0xf+6) = 0x3e00000 = 65011712.
--42be 0008318c1404010027b Page 4 of pgpStr2Key.c
685975 ·* These functions convert between the expanded count and a
79ccbb ·* floating-point approximation.
82495d ·*/
2655a5 #define EXPBIAS¤6
ec58ef static PGPUInt32
4b16ec c_to_bytes(PGPByte c)
22bb36 {
c79818 ¤   return ((PGPUInt32)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
25efe6 }
93af5a
533533 static PGPByte
961d3d bytes_to_c(PGPUInt32 bytes)
24bb36 {
b40745 ¤   unsigned c;
27af5a
ab38fb ¤   if (bytes <= (PGPUInt32)16 << EXPBIAS)
71bbde ¤   ¤   return 0;
1378bc ¤   if (bytes >= (PGPUInt32)31 << (15+EXPBIAS))
27bd28 ¤   ¤   return 0xff;
b4ef5f ¤   /* Normalize mantissa to 32..63 */
38163b ¤   c = 0;
33cdbd ¤   for (bytes >>= EXPBIAS-1; bytes >= 64; bytes >>= 1)
9b78d5 ¤   ¤   c++;
3cc4ed ¤   /* Round to 4 bits by adding in low-order bit */
14cd09 ¤   bytes += (bytes & 1);
2bac57 ¤   /* Add exponent and mantissa */
53d960 ¤   return (PGPByte)((c<<4) + ((unsigned)bytes >> 1));
d0efe6 }
4faf5a
1ebeb7 static int
c566b8 s2kIterSalt(PGPStringToKey const *s2k, char const *str,
304d27 ¤   size_t slen, PGPByte *key, size_t klen)
cebb36 {
19fcf8 ¤   unsigned num;
78efa5 ¤   StringToKeyPriv const *priv;
ca602d ¤   PGPHashVTBL const *h;
f05431 ¤   PGPUInt32 bytes;
9a097a ¤   void **v;
6418f8 ¤   PGPContextRef¤  ¤   cdkContext¤ = NULL;
7caf5a
262f3e ¤   pgpAssert(s2k->encodelen == 11);
01af5a
64e7b2 ¤   if (!klen)
113d7d ¤   ¤   return 0;¤  /* Okay, I guess... */
c2af5a
038fec ¤   priv = (StringToKeyPriv *)s2k->priv;
deae46 ¤   cdkContext¤ = pgpenvGetContext( priv->env );
118c6b ¤   h = priv->hash;
6efebb ¤   pgpAssert(h->algorithm == priv->buf[1]);
ef1039 ¤   num = (klen-1)/h->hashsize + 1;
efc530 ¤   v = multiHashCreate( cdkContext, h, num);
4d9b03 ¤   if (!v)
864030 ¤   ¤   return kPGPError_OutOfMemory;
5ef2a4 ¤   /* Find the length of the material to hash */
a7b37b ¤   bytes = c_to_bytes(priv->buf[10]);
78585b ¤   /* Always hash a least the whole passphrase! */
b736a5 ¤   if (bytes < slen + 8)
25d44c ¤   ¤   bytes = (PGPUInt32)(slen + 8);
c5af5a
dd3de9 ¤   /* Hash len bytes of (salt, passphrase) repeated... */
c42cbe ¤   while (bytes > slen + 8) {
05e9b7 ¤   ¤   multiHashUpdate (h, v, num, priv->buf+2, 8);
8570f4 ¤   ¤   multiHashUpdate (h, v, num, (PGPByte const *)str, slen);
1e08e5 ¤   ¤   bytes -= slen + 8;
ed9371 ¤   }
e9afa6 ¤   if (bytes <= 8) {
403a77 ¤   ¤   multiHashUpdate (h, v, num, priv->buf+2, (size_t)bytes);
e3f037 ¤   } else {
b3e9b7 ¤   ¤   multiHashUpdate (h, v, num, priv->buf+2, 8);
6c167b ¤   ¤   multiHashUpdate (h, v, num, (PGPByte const *)str,
f9d6a3 ¤   ¤   ¤   ¤   ·(size_t)bytes-8);
839371 ¤   }
--9305 000fd6484ee4010027b Page 5 of pgpStr2Key.c
37ddab ¤   multiHashFinal( cdkContext, h, v, key, klen);
b9af5a
ff3e6b ¤   return 0;
7defe6 }
8baf5a
91beb7 static int
c342a5 s2kLiteral(PGPStringToKey const *s2k, char const *str,
e54d27 ¤   size_t slen, PGPByte *key, size_t klen)
90bb36 {
33c744 ¤   (void)s2k;
7b89b8 ¤   pgpAssert(s2k->encodelen == 1);
35af5a
fc2d2b ¤   (void) s2k;
5267c5 ¤
45e7b2 ¤   if (!klen)
b53d7d ¤   ¤   return 0;¤  /* Okay, I guess... */
3aaf5a
e3f899 ¤   /* We will use the str literally, so sizes must match */
c96631 ¤   if (klen != slen)
8962b5 ¤   ¤   return kPGPError_BadParams;
3eaf5a
3dc4a6 ¤   pgpCopyMemory( str, key, klen );
803e6b ¤   return 0;
60efe6 }
71af5a
49af5a
fd190f /* Encoded as \000 + hash specifier */
a27fda PGPStringToKey *
13db68 pgpS2Ksimple(PGPEnv const *env, PGPHashVTBL const *h)
64bb36 {
09bfb0 ¤   PGPStringToKey *s2k;
61b32a ¤   PGPByte *buff;
acaf5a
d77c3a ¤   s2k = s2kAlloc(env, h, 2);
ed80a1 ¤   if (s2k) {
6fa4f8 ¤   ¤   s2k->stringToKey = s2kSimple;
f4c7fb ¤   ¤   buff = ((StringToKeyPriv *)s2k->priv)->buf;
51628d ¤   ¤   buff[0] = kPGPStringToKey_Simple;
d99371 ¤   }
09de4c ¤   return s2k;
cbefe6 }
ddaf5a
9ead4b /* Encoded as \001 + hash specifier + salt8 */
337fda PGPStringToKey *
b80a5d pgpS2Ksalted(PGPEnv const *env, PGPHashVTBL const *h,
30cfa3 ¤   ·····PGPByte const *salt8)
f4bb36 {
5dbfb0 ¤   PGPStringToKey *s2k;
47b32a ¤   PGPByte *buff;
3daf5a
1a89a6 ¤   s2k = s2kAlloc(env, h, 10);
2580a1 ¤   if (s2k) {
36f090 ¤   ¤   s2k->stringToKey = s2kSalted;
c9c7fb ¤   ¤   buff = ((StringToKeyPriv *)s2k->priv)->buf;
3a36e5 ¤   ¤   buff[0] = kPGPStringToKey_Salted;
a9fc76 ¤   ¤   memcpy(buff+2, salt8, 8);
fe9371 ¤   }
0fde4c ¤   return s2k;
8fefe6 }
eeaf5a
1bc281 /* Encoded as \003 + hash specifier + salt8 + (compressed) count */
9e8ee6 static PGPStringToKey *
f26f21 pgpS2Kiterintern(PGPEnv const *env, PGPHashVTBL const *h,
338e7e ¤   ¤   ·PGPByte const *salt8, PGPByte c)
42bb36 {
60bfb0 ¤   PGPStringToKey *s2k;
e1b32a ¤   PGPByte *buff;
85af5a
1b951d ¤   s2k = s2kAlloc(env, h, 11);
1180a1 ¤   if (s2k) {
48627f ¤   ¤   s2k->stringToKey = s2kIterSalt;
fdc7fb ¤   ¤   buff = ((StringToKeyPriv *)s2k->priv)->buf;
--6950 000be64a95a4010027b Page 6 of pgpStr2Key.c
777b66 ¤   ¤   buff[0] = kPGPStringToKey_IteratedSalted;
eafc76 ¤   ¤   memcpy(buff+2, salt8, 8);
3e4528 ¤   ¤   buff[10] = c;
b59371 ¤   }
18de4c ¤   return s2k;
7aefe6 }
eb7fda PGPStringToKey *
cbd4a3 pgpS2Kitersalt(PGPEnv const *env, PGPHashVTBL const *h,
0dcd5c ¤   ·······PGPByte const *salt8, PGPUInt32 bytes)
6bbb36 {
d5d84d ¤   return pgpS2Kiterintern(env, h, salt8, bytes_to_c(bytes));
f9efe6 }
ceaf5a
23f13f /* Encoded as \004 */
607fda PGPStringToKey *
d68242 pgpS2Kliteral(PGPEnv const *env)
d0bb36 {
6dbfb0 ¤   PGPStringToKey *s2k;
5bb32a ¤   PGPByte *buff;
2aaf5a
094299 ¤   s2k = s2kAlloc(env, NULL, 1);
3480a1 ¤   if (s2k) {
1818ca ¤   ¤   s2k->stringToKey = s2kLiteral;
93c7fb ¤   ¤   buff = ((StringToKeyPriv *)s2k->priv)->buf;
e03c26 ¤   ¤   buff[0] = kPGPStringToKey_Literal;
ef9371 ¤   }
ddde4c ¤   return s2k;
14efe6 }
d4af5a
ef10b9 /* Encoded as \005, like literal but flags secret sharing */
077fda PGPStringToKey *
db5a6e pgpS2KliteralShared(PGPEnv const *env)
00bb36 {
48bfb0 ¤   PGPStringToKey *s2k;
35b32a ¤   PGPByte *buff;
07af5a
4e4299 ¤   s2k = s2kAlloc(env, NULL, 1);
c980a1 ¤   if (s2k) {
3c18ca ¤   ¤   s2k->stringToKey = s2kLiteral;
12c7fb ¤   ¤   buff = ((StringToKeyPriv *)s2k->priv)->buf;
88bfd6 ¤   ¤   buff[0] = kPGPStringToKey_LiteralShared;
b49371 ¤   }
83de4c ¤   return s2k;
55efe6 }
1daf5a
75af5a
8c38e5 /*
732872 ·* Returns either an error <0 or the length >=0 of the encoded
a4b341 ·* string2key data found in the buffer. ·If s2k is non-NULL, a
812213 ·* structure is allocated and returned.
5b495d ·*/
f84d2f int
fafecb pgpS2Kdecode(PGPStringToKey **s2kp, PGPEnv const *env,
b9abe2 ¤   ·····PGPByte const *buff, size_t len)
d7bb36 {
d9602d ¤   PGPHashVTBL const *h;
b6af5a
a34404 ¤   if (!len)
0662b5 ¤   ¤   return kPGPError_BadParams;
e3fc5e ¤   switch (buff[0]) {
a23322 ¤   case (int)kPGPStringToKey_Simple:
58a021 ¤   ¤   if (len < 2)
d0a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
9a92a4 ¤   ¤   h = pgpHashByNumber( (PGPHashAlgorithm) buff[1]);
1c143d ¤   ¤   if (!h)
63ce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
281927 ¤   ¤   if (!s2kp || (*s2kp = pgpS2Ksimple(env, h)) != 0)
a134fc ¤   ¤   ¤   return 2;
3c2f68 ¤   ¤   break;
d3674a ¤   case (int)kPGPStringToKey_Salted:
0faa6c ¤   ¤   if (len < 10)
bea7e0 ¤   ¤   ¤   return kPGPError_BadParams;
--14ea 000e51260904010027b Page 7 of pgpStr2Key.c
7492a4 ¤   ¤   h = pgpHashByNumber( (PGPHashAlgorithm) buff[1]);
21143d ¤   ¤   if (!h)
b7ce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
7845c2 ¤   ¤   if (!s2kp || (*s2kp = pgpS2Ksalted(env, h, buff+2)) != 0)
c8319c ¤   ¤   ¤   return 10;
482f68 ¤   ¤   break;
4e6f23 ¤   case (int)kPGPStringToKey_IteratedSalted:
a5f0b0 ¤   ¤   if (len < 11)
faa7e0 ¤   ¤   ¤   return kPGPError_BadParams;
f892a4 ¤   ¤   h = pgpHashByNumber( (PGPHashAlgorithm) buff[1]);
26143d ¤   ¤   if (!h)
f0ce1a ¤   ¤   ¤   return kPGPError_BadHashNumber;
055cb2 ¤   ¤   if (!s2kp || (*s2kp = pgpS2Kiterintern(env, h, buff+2,
9c61d4 ¤   ¤   ¤   ¤   ¤   ¤   ·······buff[10])) != 0)
456b40 ¤   ¤   ¤   return 11;
892f68 ¤   ¤   break;
a9228e ¤   case (int)kPGPStringToKey_Literal:
c44f45 ¤   ¤   if (len < 1)
41a7e0 ¤   ¤   ¤   return kPGPError_BadParams;
ae1994 ¤   ¤   if (!s2kp || (*s2kp = pgpS2Kliteral(env)) != 0)
b5db98 ¤   ¤   ¤   return 1;
f02f68 ¤   ¤   break;
8753d3 ¤   case (int)kPGPStringToKey_LiteralShared:
f44f45 ¤   ¤   if (len < 1)
5ba7e0 ¤   ¤   ¤   return kPGPError_BadParams;
6c4407 ¤   ¤   if (!s2kp || (*s2kp = pgpS2KliteralShared(env)) != 0)
4fdb98 ¤   ¤   ¤   return 1;
bf2f68 ¤   ¤   break;
952f72 ¤   default:
6403ff ¤   ¤   return kPGPError_UnknownString2Key;
829371 ¤   }
c41d73 ¤   /* Tried to allocate and failed */
86af43 ¤   return kPGPError_OutOfMemory;
daefe6 }
e7af5a
6baf5a
c638e5 /*
5e8ba8 ·* Return the default StringToKey based on the setting in the
7de9ae ·* environment. ·This is expected to be the usual way to get
c8fa3c ·* such structures.
6f495d ·*/
597fda PGPStringToKey *
c5597b pgpS2Kdefault(PGPEnv const *env, PGPRandomContext const *rc)
28bb36 {
dc398b ¤   PGPByte salt[8];
98af5a
c6454a ¤   pgpAssert (rc);
c7af5a
6cdc78 ¤   pgpRandomGetBytes(rc, salt, sizeof(salt));
7799db ¤   return pgpS2Kitersalt(env, pgpHashByNumber(kPGPHashAlgorithm_SHA),
fda0d4 ¤   ¤   salt, SALT_CHARS_DEFAULT);
4befe6 }
aaaf5a
1b38e5 /*
eb73e8 ·* Return the default StringToKey for PGP version 2.X
08495d ·*/
fb7fda PGPStringToKey *
1a2016 pgpS2KdefaultV3(PGPEnv const *env, PGPRandomContext const *rc)
33bb36 {
2f7a20 ¤   /* Kludge for now */
2476a2 ¤   (void)rc;
9c4676 ¤   return pgpS2Ksimple(env, pgpHashByNumber(kPGPHashAlgorithm_MD5));
e9efe6 }
f6af5a
f038e5 /*
ecf19d ·* Return a new StringToKey object of the specified type
0a495d ·*/
597fda PGPStringToKey *
b46ee5 pgpS2Kcreate(PGPEnv const *env, PGPRandomContext const *rc,
a6ab73 ¤   PGPStringToKeyType s2ktype)
fcbb36 {
e53b02 ¤   PGPHashAlgorithm hashalg = kPGPHashAlgorithm_SHA;
--f653 00125d61d9f4010027b Page 8 of pgpStr2Key.c
e0af5a
a91f78 ¤   if (s2ktype == kPGPStringToKey_Simple) {
6ca124 ¤   ¤   return pgpS2Ksimple(env, pgpHashByNumber(hashalg));
26c71c ¤   } else if (s2ktype == kPGPStringToKey_Literal) {
a7bf26 ¤   ¤   return pgpS2Kliteral(env);
42ec1e ¤   } else if (s2ktype == kPGPStringToKey_LiteralShared) {
ff7d9b ¤   ¤   return pgpS2KliteralShared(env);
5af037 ¤   } else {
36c10b ¤   ¤   /* Need a salt */
3f885a ¤   ¤   PGPByte salt[8];
d0af5a
543fbe ¤   ¤   pgpAssert (rc);
c704ca ¤   ¤   pgpRandomGetBytes(rc, salt, sizeof(salt));
3bf2d1 ¤   ¤   if (s2ktype == kPGPStringToKey_Salted) {
9b31e8 ¤   ¤   ¤   return pgpS2Ksalted(env, pgpHashByNumber(hashalg), salt);
e3b535 ¤   ¤   } else if (s2ktype == kPGPStringToKey_IteratedSalted) {
530525 ¤   ¤   ¤   return pgpS2Kitersalt(env, pgpHashByNumber(hashalg),
87814b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··salt, SALT_CHARS_DEFAULT);
d20fe4 ¤   ¤   }
8e9371 ¤   }
d8c7c5 ¤   /* Unknown stringtokey type */
223f59 ¤   return NULL;
4cefe6 }
45af5a
42af5a
6a2bd7 /* Returns 1 if this is simple/md5, 0 otherwise */
b1602d int pgpS2KisOldVers (PGPStringToKey const *s2k)
b4bb36 {
f4a617 ¤   PGPByte const *ptr;
4aaf5a
6f6945 ¤   if (s2k->encodelen != 2)
cfbbde ¤   ¤   return 0;
a1af5a
69eed9 ¤   ptr = s2k->encoding;
9ca6f0 ¤   if (ptr[0] == 0 && ptr[1] == kPGPHashAlgorithm_MD5)
60e102 ¤   ¤   return 1;
2faf5a
a93e6b ¤   return 0;
25efe6 }
--dfe6 0001f8a10434010027c Page 1 of pgpStr2Key.h
bc38e5 /*
13a01c ·* pgpStr2Key.h -- A PGP String to Key Conversion System
1e775e ·*
3979e2 ·* $Id: pgpStr2Key.h,v 1.14 1998/06/11 18:28:25 hal Exp $
66495d ·*/
891cc5 #ifndef Included_pgpStr2Key_h
1e48f1 #define Included_pgpStr2Key_h
d2af5a
88398d #include "pgpUsuals.h"¤ /* For PGPByte */
dbaf5a
8238e5 /*
7e63c8 ·* The PGPStringToKey objects are encoded using the follow table:
b2775e ·*
5c673a ·* type¤¤   number¤ s2k arguments
9adbbb ·* ----¤¤   -----¤  -------------
2c122f ·* simple¤  \000¤   hash specifier
138c7d ·* salted¤  \001¤   hash specifier + salt8
703cfa ·* itersalt¤\003¤   hash specifier + salt8 + (compressed) count
b3116f ·* literal¤ \004¤   no arguments, just use input as output
ea643d ·* literalshared \005¤  like literal but flags secret-sharing at higher level
6f775e ·*
92495d ·*/
14af5a
ec242f enum PGPStringToKeyType_
c9bb36 {
2c14df ¤   kPGPStringToKey_Simple = 0,
78d2bd ¤   kPGPStringToKey_Salted = 1,
1469fa ¤   kPGPStringToKey_IteratedSalted = 3,
463415 ¤   kPGPStringToKey_Literal = 4,
031aae ¤   kPGPStringToKey_LiteralShared = 5,
0daf5a
c6f79b ¤   PGP_ENUM_FORCE( PGPStringToKeyType )
2582f7 };
767f2b PGPENUM_TYPEDEF( PGPStringToKeyType_, PGPStringToKeyType );
aaaf5a
53af5a
1f99c6 PGP_BEGIN_C_DECLARATIONS
9faf5a
11adb8 #include "pgpOpaqueStructs.h"
40af5a
30af5a
46a587 struct PGPStringToKey {
29e041 ¤   void *priv;
dc2345 ¤   PGPByte const *encoding;¤   /* For transmission */
f10f40 ¤   unsigned encodelen;
d44de3 ¤   void (*destroy) (struct PGPStringToKey *s2k);
615053 ¤   int (*stringToKey) (struct PGPStringToKey const *s2k, char const *str,
d3ae14 ¤   ¤   ¤   ····size_t slen, PGPByte *key, size_t klen);
3082f7 };
04af5a
35af5a
e05461 /* Deallocate the structure */
ca9202 #define pgpS2Kdestroy(s2k) (s2k)->destroy(s2k)
08af5a
38d250 /* Turn a string into a key */
f1e61a #define pgpStringToKey(s2k,s,sl,k,kl) (s2k)->stringToKey(s2k,s,sl,k,kl)
7baf5a
5438e5 /*
fc6a22 ·* Decodes a byte string into a PGPStringToKey object. ·Returns either an
ca9227 ·* error <0 or the length >=0 of the encoded string2key data found in
c8b50e ·* the buffer. ·If s2k is non-NULL, a structure is allocated and
ca119e ·* returned.
48495d ·*/
c0c2d3 int ·pgpS2Kdecode (PGPStringToKey **s2k,
8700c0 ¤   PGPEnv const *env, PGPByte const *buf, size_t len);
a3af5a
1b38e5 /*
5185b0 ·* Returns the default PGPStringToKey based on the setting in the
3eb830 ·* environment. ·This is expected to be the usual way to get such
095c3a ·* structures.
70495d ·*/
1f61cc PGPStringToKey ·*pgpS2Kdefault (PGPEnv const *env,
--8980 0013cb11e8f4010027c Page 2 of pgpStr2Key.h
41f19d ¤   ¤   ¤   ¤   ······PGPRandomContext const *rc);
9daf5a
5a38e5 /*
6ba9fa ·* Return old default PGPStringToKey compatible with PGP V3 */
d24092 PGPStringToKey ·*pgpS2KdefaultV3(PGPEnv const *env,
51adf7 ¤   ¤   ¤   ¤   ¤   ··PGPRandomContext const *rc);
22af5a
3d8493 /* Allocate a structure given the type, using default for hash */
b5c948 PGPStringToKey *pgpS2Kcreate(PGPEnv const *env,
0c36f4 ¤   PGPRandomContext const *rc, PGPStringToKeyType s2ktype);
6aaf5a
419ab9 int ·pgpS2KisOldVers (PGPStringToKey const *s2k);
13af5a
9838e5 /*
5d98b1 ·* Specific PGPStringToKey creation functions. ·Use these functions to
fbcf5d ·* specifically request a certain string to key algorithm.
2d495d ·*/
a1ae14 PGPStringToKey ·*pgpS2Ksimple (PGPEnv const *env,
b86103 ¤   ¤   ¤   ¤   ·····PGPHashVTBL const *h);
7edb10 PGPStringToKey ·*pgpS2Ksalted (PGPEnv const *env,
934bfa ¤   ¤   ¤   ¤   ·····PGPHashVTBL const *h,
8851b1 ¤   ¤   ¤   ¤   ·····PGPByte const *salt8);
03572c PGPStringToKey ·*pgpS2Kitersalt (PGPEnv const *env,
a36dda ¤   ¤   ¤   ¤   ·······PGPHashVTBL const *h,
db54fb ¤   ¤   ¤   ¤   ·······PGPByte const *salt8,
3c29ed ¤   ¤   ¤   ¤   ·······PGPUInt32 bytes);
d57aba PGPStringToKey ·*pgpS2Kliteral (PGPEnv const *env);
f91d1a PGPStringToKey ·*pgpS2KliteralShared (PGPEnv const *env);
dcaf5a
1faf5a
561254 PGP_END_C_DECLARATIONS
1faf5a
3cdcac #endif /* Included_pgpStr2Key_h */
--ac8a 00069f012e14010027d Page 1 of pgpTimeDate.c
bc38e5 /*
140467 ·* pgpTimeDate.c -- conversions between a PGPUInt32 timestamp and year,
8ce82e ·* month, day, and time. ·A bunch of convenience functions.
92775e ·*
1d6f09 ·* $Id: pgpTimeDate.c,v 1.19 1998/04/24 21:01:33 heller Exp $
67495d ·*/
41af5a
e7324c #include <string.h>
7de2ff #include "pgpConfig.h"
61af5a
81feb2 #include <stdio.h>
db0a8b #include <time.h>
81af5a
e42266 #include "pgpTimeDate.h"
fcd11f #include "pgpUsuals.h"
f6675a #include "pgpTypes.h"
500d08 #include "pgpMem.h"
04af5a
98819a static PGPBoolean¤  offsetsComputed = FALSE;
acaf5a
d6b5b4 #define kSecondsPerDay¤ (24UL * 60UL * 60UL )
b4af5a
6238e5 /*
b725a8 ·* Offset in seconds from UTC
c3495d ·*/
0fb103 static long¤¤   tzDiff;
d2af5a
e338e5 /*
7e32f9 ·* Compute local time_t representation of
428d58 ·* Midnight Jan 1 1970 local time.
08495d ·*/
1b4dcd static time_t¤  ¤   stdEpochLocal;
fcadeb typedef struct tm¤  PGPtm;
eeaf5a
1533c8 ¤   static void
5227c8 pgpComputeOffsets(void)
36bb36 {
464221 ¤   static¤ PGPtm¤  stdEpochStruct = { 0, 0, 0, 1, 0, 70, 0, 0, 0 };
fc1f21 ¤   time_t¤ ¤   ¤   testTime = 10000000;
39f4f2 ¤   PGPtm *¤¤   ¤   utcTime;
1777a2 ¤   PGPtm¤  ¤   ¤   timeStruct;
2567c5 ¤
d33ccd ¤   if (!offsetsComputed)
ccc7a1 ¤   {
74b406 ¤   ¤   stdEpochLocal = mktime(&stdEpochStruct);
b81b52 ¤   ¤
7f5111 ¤   ¤   utcTime = gmtime(&testTime);
a6fde4 ¤   ¤   if (utcTime == NULL)
b05b34 ¤   ¤   {
b57aad ¤   ¤   ¤   /*
3d79b7 ¤   ¤   ¤   ·* Time zone information not available,
fb4e48 ¤   ¤   ¤   ·* so just pretend we're in UTC.
df8753 ¤   ¤   ¤   ·*/
2efb11 ¤   ¤   ¤   tzDiff = 0;
d80fe4 ¤   ¤   }
f30e1d ¤   ¤   else
a15b34 ¤   ¤   {
4de0a0 ¤   ¤   ¤   pgpCopyMemory(utcTime, &timeStruct, sizeof(timeStruct));
4c1cdb ¤   ¤   ¤   tzDiff = testTime - mktime(&timeStruct);
9a0fe4 ¤   ¤   }
31723f ¤   ¤   offsetsComputed = TRUE;
9c9371 ¤   }
ddefe6 }
10af5a
bcaf5a
de9b38 ¤   static time_t
cc1bc6 pgpStdEpoch(void)
e8bb36 {
02e3d5 ¤   pgpComputeOffsets();
3fc077 ¤   return stdEpochLocal + tzDiff;
f6efe6 }
69af5a
--9b94 0003aafea344010027d Page 2 of pgpTimeDate.c
e0af5a
a01f5c ¤   PGPtm *
eda481 pgpLocalTime(
c5458a ¤   PGPTime const *¤theTime)
6bbb36 {
d83fec ¤   time_t¤ ¤   stdTime = PGPGetStdTimeFromPGPTime(*theTime);
8a67c5 ¤
595d6e ¤   return localtime(&stdTime);
84efe6 }
5aaf5a
3fd25c ¤   char *
dafc1d pgpCTime(
bf458a ¤   PGPTime const *¤theTime)
75bb36 {
313fec ¤   time_t¤ ¤   stdTime = PGPGetStdTimeFromPGPTime(*theTime);
0c67c5 ¤
92fb4d ¤   return ctime(&stdTime);
a8efe6 }
e5af5a
9faf5a
cbaf5a
8daf5a
f4af5a
d8af5a
e4a53f /* System clock must be broken if it isn't past this date: */
db6801 #define REASONABLE_DATE ((unsigned long) 0x27804180L) ·/* 91 Jan 01 00:00:00 */
feaf5a
3a38e5 /*
b6dfb8 ·* Convert a year-month-day to a number of days since Jan 1, 1970
6757b0 ·* Month and day are 1-based.
82775e ·*
bfd800 ·* To compute the day of the week, note that Jan 1, 1970 is a Thursday.
fc495d ·*/
63536c unsigned
3a176e pgpDateFromYMD (int y, int m, int d)
e1bb36 {
640ed5 ¤   unsigned t;
fb235f ¤   static const unsigned startday[12] = {
b4df6c ¤   ¤   0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
9b06d9 ¤   /*¤ ·J ··F ··M ··A ···M ···J ···J ···A ···S ···O ···N ···D */
d9af5a
0f9728 ¤   /* Number of 4-years since 1968 */
5b1453 ¤   t = (y - 1968)/4;
b32aba ¤   /* Number of days in the 4-years */
b56be9 ¤   t *= 365*4+1;
e1ecea ¤   /* Add days in years since */
6cf529 ¤   t += 365 * (y%4);
cf8ac6 ¤   /* Add leap day unless before march in year 0 of cycle */
61e126 ¤   if (y % 4 != 0 || m > 2)
82fc49 ¤   ¤   t++;
798ce2 ¤   /* Adjust to 1970 base */
37d2e9 ¤   t -= 365*2+1;
fe10e9 ¤   /* Add month and day offset */
e69c2a ¤   t += startday[m-1] + d-1;
ecaf5a
425b7c ¤   return t;
77efe6 }
46af5a
b238e5 /*
9e291c ·* Given timestamp as days elapsed since 1970 Jan 1,
25fe2d ·* returns year (1970-2106), month (1-12), and day (1-31).
9ffa93 ·* Not valid for dates after 2100 Feb 28 (no leap day that year).
0b495d ·*/
ee314a void
b25709 pgpDateToYMD (unsigned days, int *year, int *month, int *day)
98bb36 {
5b5ccb ¤   int y, m;
e21a68 ¤   static const PGPByte mdays[12] =¤   /* March..February */
fb2089 ¤   ¤   {31,30,31,30,31,31,30,31,30,31,31,29};
d0af5a
1adeff ¤   days += 365+365-31-28;¤ /* Days since Fri 1 Mar 1968 */
3aaf5a
--b1c3 000374753fe4010027d Page 3 of pgpTimeDate.c
ed7a9f ¤   /* Locate to within a leap-year cycle */
eb8175 ¤   y = days / 1461;
e8047a ¤   days %= 1461;
01edfe ¤   y *= 4;
68af5a
8e636e ¤   /* Find the year within the cycle */
877f1c ¤   if (days >= 730) {
2f25bc ¤   ¤   y += 2;
595163 ¤   ¤   days -= 730;
459371 ¤   }
8f22b9 ¤   if (days >= 365) {
4a803d ¤   ¤   y++;
5d2b99 ¤   ¤   days -= 365;
299371 ¤   }
beaf5a
c3aa21 ¤   *year = y;
a5af5a
c2046f ¤   /* days is now in the range [0..365] */
56154f ¤   /* Compute month, based on March=0 */
28901a ¤   m = 0;
a1c9f2 ¤   while (days >= mdays[m])
0eb7d1 ¤   ¤   days -= mdays[m++];
69af5a
1af5a3 ¤   /* Now, fix the month so March = 2, with carry into the year */
8c72aa ¤   m += 2;
6a7f12 ¤   if (m >= 12) {¤ /* January or February of the next year */
425e8d ¤   ¤   m -= 12;
bc803d ¤   ¤   y++;
5f9371 ¤   }
a8af5a
65c4b9 ¤   /* Save the final (1-based) results */
b1ab15 ¤   *year = y + 1968;
63c16d ¤   *month = m+1;
48a8b8 ¤   *day = days+1;
83efe6 }
b4af5a
17af5a
fdaf5a
7a6d52 ¤   void
c4c19e PGPGetYMDFromPGPTime(
9472df ¤   PGPTime¤¤   theTime,
cf5781 ¤   PGPUInt16 *¤yearPtr,
fd5185 ¤   PGPUInt16 *¤monthPtr,
c51bf2 ¤   PGPUInt16 *¤dayPtr )
9cbb36 {
bfe04e ¤   int¤¤   year;
1215ea ¤   int¤¤   month;
c63066 ¤   int¤¤   day;
eb67c5 ¤
1478b4 ¤   pgpDateToYMD( theTime / kSecondsPerDay, &year, &month, &day );
dc67c5 ¤
3cc7fa ¤   if ( IsntNull( yearPtr ) )
73a2fe ¤   ¤   *yearPtr¤   = year;
f11b52 ¤   ¤
9ebd14 ¤   if ( IsntNull( monthPtr ) )
1331bb ¤   ¤   *monthPtr¤  = month;
971b52 ¤   ¤
1563b4 ¤   if ( IsntNull( dayPtr ) )
35420e ¤   ¤   *dayPtr¤¤   = day;
76efe6 }
27af5a
ccaf5a
cb94aa ¤   ¤   ¤   ¤   ¤   ¤
6594aa ¤   ¤   ¤   ¤   ¤   ¤
6a3186 ¤   PGPTime
4ee97c pgpTimeStamp (int tzFix)
c9bb36 {
cd6ed7 ¤   return (PGPUInt32)(PGPGetTime() + (60 * 60 * tzFix));
f0efe6 }
64af5a
ca9cb9 /* XXX: The routine below fails on Mac's when the timezone isn't set */
37c2e5 #if 0¤  /* [ */
--c497 0000207db124010027d Page 4 of pgpTimeDate.c
bc38e5 /*
aa6b26 ·* It's a bit annoying that we have to go through these shenanigans
46a737 ·* to get seconds since Jan 1, 1970 0:00:00 GMT (okay, okay, UTC),
4014b1 ·* when time() on half the platforms in the world returns this value
323c85 ·* already, but some platforms (e.g. Microsoft C, version 7.0 - but
9a6461 ·* not earlier versions!) return different values.
8f775e ·*
06cf25 ·* So this uses the ANSI C functions. ·tm_yday could be used to reduce the
d6721e ·* work, but this is hardly a time-critical function and tm_yday is
5530d4 ·* infrequently used, so it might be buggy.
ca775e ·*
c1497e ·* ANSI allows the time() and gmtime() to fail, so this returns 0 in that
2ea202 ·* case.
b9495d ·*/
b40886 PGPTime
edbd69 pgpTimeStamp (PGPInt32 tzFix)
20bb36 {
7cd1b6 ¤   time_t const t = time((time_t *)0);
3f1616 ¤   PGPtm const *g;
85babc ¤   unsigned days;
baaf5a
a1b927 ¤   if (t == (time_t)-1)
cbbbde ¤   ¤   return 0;
5612ea ·¤  g = gmtime(&t);
78444a ¤   if (!g)
a3bbde ¤   ¤   return 0;
68af5a
5b0658 ¤   /* tm_year is 1900-based, tm_mon is 0-based, tm_day is 1-based */
30f9c7 ¤   /* Some systems do tm_year oddly, though... */
a9f2d9 ¤   days = pgpDateFromYMD(g->tm_year + (g->tm_year > 1900 ? 0 : 1900),
565640 ¤   ······················g->tm_mon+1, g->tm_mday);
ad1ac3 ¤   return g->tm_sec+60*(g->tm_min+60*(g->tm_hour+tzFix+24*(PGPUInt32)days));
beefe6 }
d04edc #endif¤ /* ] 0 */
d4af5a
8438e5 /*
47de34 ·* Create a date string, given a 32-bit timestamp. ·Returns characters
2184c0 ·* printed. ·Format: "yyyy-mm-dd"
dcf097 ·* ···················1234567890
ebb12e ·* This format is specified by some international ISO standard, but I
0ca565 ·* forget which one.
a0495d ·*/
694d2f int
435f24 pgpDateString (PGPTime tstamp, char buf[PGPDATESTRINGLEN+1])
27bb36 {
7a58d8 ¤   int month, day, year;
38af5a
76c17b ¤   if (tstamp == 0) {
6d3cce ¤   ¤   pgpFillMemory (buf, 10, ' ');
e9fad3 ¤   ¤   buf[10] = '\0';
5f0a75 ¤   ¤   return 10;
159371 ¤   }
74af5a
0d7dc2 ¤   pgpDateToYMD((unsigned)(tstamp/86400), &year, &month, &day);
de4158 ¤   sprintf (buf, "%4d-%02d-%02d", year, month, day);
ed5534 ¤   return PGPDATESTRINGLEN;
51efe6 }
95af5a
4338e5 /*
184cf0 ·* Create a "date and time" string, given a 32-bit timestamp.
84703f ·* Returns number of characters printed.
447f93 ·* Format: "yyyy-mm-dd hh:mm GMT"
ae42af ·* ·········12345678901234567890
7e495d ·*/
1b4d2f int
63d28b pgpTimeString (PGPTime tstamp, char buf[PGPTIMESTRINGLEN+1])
aabb36 {
035ac5 ¤   unsigned min;
d9af5a
1aeff0 ¤   pgpDateString (tstamp, buf);
43cf46 ¤   tstamp /= 60;¤  /* Minutes since 00:00 Jan 1, 1970 */
0242d0 ¤   min = (unsigned)(tstamp % 1440);¤   /* Minutes since 0:00 today */
--fe3a 0009d3c72b34010027d Page 5 of pgpTimeDate.c
ac5f7e ¤   sprintf (buf+PGPDATESTRINGLEN, " %02d:%02d GMT", min/60, min%60);
726aa6 ¤   return PGPTIMESTRINGLEN;
bdefe6 }
f4af5a
0eaf5a
a3c21c #if PGP_MACINTOSH¤  /* [ */
a7af5a
f66d4d ¤   static long
fca99e pgpTZDiff(void)
01bb36 {
bde3d5 ¤   pgpComputeOffsets();
b0180d ¤   return tzDiff;
caefe6 }
d2af5a
74af5a
92af5a
8338e5 /*
2f69aa ·* Number of seconds between Midnight Jan 1, 1904 (Mac time base)
ab1fe0 ·* and Midnight Jan 1, 1970 (Un*x time base)
5b495d ·*/
175106 #define kMacTimeDiff¤   2082844800
82af5a
d3108d ¤   PGPUInt32
bdb764 PGPTimeToMacTime(PGPTime theTime)
89bb36 {
aa74ff ¤   return theTime + kMacTimeDiff + pgpTZDiff();
eaefe6 }
c9af5a
e23186 ¤   PGPTime
f23463 PGPTimeFromMacTime(PGPUInt32 theTime)
6dbb36 {
f00e38 ¤   return theTime - kMacTimeDiff - pgpTZDiff();
d2efe6 }
baaf5a
32ddc8 #endif¤ /* ] PGP_MACINTOSH */
dbaf5a
4baf5a
ecaf5a
69c4ee ¤   time_t
1efda3 PGPGetStdTimeFromPGPTime(
b2cc64 ¤   PGPTime¤¤   ¤   theTime)
38bb36 {
bbe423 ¤   return theTime + pgpStdEpoch();
63efe6 }
1daf5a
aaaf5a
0aaf5a
d23186 ¤   PGPTime
29aed8 PGPGetPGPTimeFromStdTime( time_t¤   theTime)
72bb36 {
298401 ¤   return theTime - pgpStdEpoch();
49efe6 }
74af5a
89af5a
673186 ¤   PGPTime
055830 PGPGetTime(void)
06bb36 {
270d4b ¤   return PGPGetPGPTimeFromStdTime(time((time_t *) NULL));
b1efe6 }
cbaf5a
5daf5a
b3af5a
19bca5 #ifdef TESTMAIN
a9bea3 #include <stdlib.h>
75af5a
594d2f int
c07f68 main(void)
3fbb36 {
429245 ¤   unsigned i, t;
601576 ¤   int y, m, d;
f1af5a
9d7be7 ¤   puts("Starting test...");
--51ac 001dfb144e64010027d Page 6 of pgpTimeDate.c
c1e133 ¤   for (i = 0; i < 65535; i++) {
010ea1 ¤   ¤   if (i % 1000 == 0)
9092dd ¤   ¤   ¤   printf("% 5u\r", i);
86deda ¤   ¤   pgpDateToYMD(i, &y, &m, &d);
807fd9 ¤   ¤   t = pgpDateFromYMD(y, m, d);
8985f4 ¤   ¤   if (i != t) {
bc5c18 ¤   ¤   ¤   printf("\ni = %u != t = %u ··y/m/d = %04d/%02d/%02d\n",
c7c435 ¤   ¤   ¤   ¤   i, t, y, m, d);
540fe4 ¤   ¤   }
f99371 ¤   }
2568b1 ¤   puts("\nDone!");
403e6b ¤   return 0;
a1efe6 }
d8af5a
df7454 #endif
--a93d 001e60aa5e64010027e Page 1 of pgpTimeDate.h
bc38e5 /*
3f873a ·* pgpTimeDate.h -- functions to convert between a PGPUInt32 timestamp and
ab8e04 ·* various time and date values (uncluding ISO string represenations
a8775e ·*
8a68be ·* $Id: pgpTimeDate.h,v 1.12 1997/06/30 21:15:46 lloyd Exp $
34495d ·*/
e7af5a
10cbc4 #ifndef Included_pgpTimeDate_h
94bc37 #define Included_pgpTimeDate_h
fdaf5a
aa0a8b #include <time.h>
79af5a
4cd11f #include "pgpUsuals.h"
40675a #include "pgpTypes.h"
a2af5a
1199c6 PGP_BEGIN_C_DECLARATIONS
ebaf5a
40e446 struct tm ·*¤   pgpLocalTime(PGPTime const *theTime);
49afce char ·*¤¤   ¤   pgpCTime(PGPTime const *theTime);
e2af5a
3f4919 #include "pgpUtilities.h"
52af5a
9e2a31 /* Convert between number of days since 1970 Jan 1 and year/month/day */
95d847 unsigned¤   pgpDateFromYMD (int y, int m, int d);
fc4519 void¤   ¤   pgpDateToYMD (unsigned days, int *year, int *month, int *day);
cdaf5a
7338e5 /*
77f35a ·* Return the current timestamp. ·tzFix is +/- #hours to off from GMT
8c8c3a ·* if local conversions don't work properly. ·(c.f. TZFIX
d851d8 ·* configuration variable)
fc495d ·*/
637712 PGPTime¤¤   pgpTimeStamp (PGPInt32 tzFix);
79af5a
fea95d /* Create strings for the Date or Time-and-date */
bca481 #define PGPDATESTRINGLEN 10
a1bc72 int¤¤   ¤   pgpDateString (PGPTime tstamp, char buf[PGPDATESTRINGLEN+1]);
53af5a
cea87c #define PGPTIMESTRINGLEN 20
fee102 int¤¤   ¤   pgpTimeString (PGPTime tstamp, char buf[PGPTIMESTRINGLEN+1]);
f2af5a
f41254 PGP_END_C_DECLARATIONS
9caf5a
e6baae #endif /* Included_pgpTimeDate_h */
--4312 0016a5708154010027f Page 1 of Makefile.in
5ea601 #
c80e18 # priv/utilities/prefs/
dda601 #
7d2148 # $Id: Makefile.in,v 1.5 1997/08/15 23:09:17 hal Exp $
d3a601 #
07af5a
755f27 OBJS=¤  ·pgpSDKPrefs.o
ab0507 PRIVHDRS= pgpSDKPrefsPriv.h
68af5a
e7b7a3 all:: DONE
6aaf5a
--6935 000920824f240100280 Page 1 of pgpSDKPrefs.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
320eb6 ¤   $Id: pgpSDKPrefs.c,v 1.19.2.1.2.1 1998/11/12 03:23:25 heller Exp $
7df7f7 ____________________________________________________________________________*/
8fe2ff #include "pgpConfig.h"
77af5a
18a093 #if HAVE_STDLIB_H
1ebea3 #include <stdlib.h>
c97454 #endif
c0af5a
39894b #include "pgpFileSpec.h"
b7e8b2 #include "pflPrefs.h"
f50d08 #include "pgpMem.h"
182f8d #include "pgpErrors.h"
920d6d #include "pgpEnv.h"
49c26c #include "pgpContext.h"
285430 #include "pgpUtilitiesPriv.h"
59af5a
210ccc #if PGP_MACINTOSH
181613 #include "pgpFileSpecMac.h"
5914ea #elif PGP_WIN32
6a729d #include "windows.h"
d87454 #endif
c3af5a
6191b9 #include "pgpSDKPrefs.h"
9eaf5a
a9af5a
58af5a
cbaf5a
0a0335 /*____________________________________________________________________________
fbc67f ¤   If prefs for the various file locations do not exist, then create a
8811e5 ¤   file spec for the location and set it in the prefs.
f7f7f7 ____________________________________________________________________________*/
dd65ed typedef struct DefaultLocInfo
a4bb36 {
bb859f ¤   PGPsdkPrefSelector¤ selector;
6759ea ¤   const char *¤   ¤   defaultName;
ecfb71 } DefaultLocInfo;
b3af5a
7166dd ¤   static PGPError
c8b1aa sSetDefaultFileLocations(
ab520e ¤   PGPContextRef¤  context,
536127 ¤   PGPBoolean *¤   didAddPrefs )
74bb36 {
7fb23e ¤   static const DefaultLocInfo¤sInfo[] =
74c7a1 ¤   {
d09a50 #if PGP_MACINTOSH¤  ¤   /* [ */
21d7a4 ¤   ¤   { kPGPsdkPref_PublicKeyring,¤   "PGP Public Keys" },
b09261 ¤   ¤   { kPGPsdkPref_PrivateKeyring,¤  "PGP Private Keys" },
e0c104 ¤   ¤   { kPGPsdkPref_RandomSeedFile,¤  "PGP Random Seed" },
45fd26 ¤   ¤   { kPGPsdkPref_GroupsFile,¤  ¤   "PGP Groups" }
bcac70 #else¤  ¤   ¤   ¤   ¤   /* ] PGP_MACINTOSH [ */
1e01c8 ¤   ¤   { kPGPsdkPref_PublicKeyring,¤   "pubring.pkr" },
aeb7fb ¤   ¤   { kPGPsdkPref_PrivateKeyring,¤  "secring.skr" },
abee0d ¤   ¤   { kPGPsdkPref_RandomSeedFile,¤  "randseed.rnd" },
a3e2c8 ¤   ¤   { kPGPsdkPref_GroupsFile,¤  ¤   "PGPgroup.pgr" }
071c0a #endif¤ ¤   ¤   ¤   ¤   /* ] PGP_MACINTOSH */
ad62bd ¤   };
d25c89 ¤   #define kNumLocations¤  sizeof( sInfo ) / sizeof( sInfo[ 0 ] )
7d7369 ¤   PFLFileSpecRef¤ locSpec;
449372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
dc67c5 ¤
ff6fe4 ¤   *didAddPrefs¤   = FALSE;
ba67c5 ¤
b330b9 ¤   /* by default, we'll place the files in the same directory
c8a2f3 ¤   as the prefs file itself */
1ef325 ¤   err¤= pgpGetPrefsSpec( PGPGetContextMemoryMgr( context ), &locSpec );
92f1e7 ¤   if ( IsntPGPError( err ) )
--f4d7 0004e17ccea40100280 Page 2 of pgpSDKPrefs.c
f7c7a1 ¤   {
9680f3 ¤   ¤   PGPUInt32¤  ¤   infoIndex;
cb1b52 ¤   ¤
0a608a ¤   ¤   for( infoIndex = 0; infoIndex < kNumLocations; ++infoIndex )
c05b34 ¤   ¤   {
73b267 ¤   ¤   ¤   PGPFileSpecRef¤ ¤   ¤   tempRef;
d9d694 ¤   ¤   ¤   const DefaultLocInfo *¤ info;
d287c7 ¤   ¤   ¤
f0380b ¤   ¤   ¤   info¤   = &sInfo[ infoIndex ];
0b87c7 ¤   ¤   ¤
6b4188 ¤   ¤   ¤   err¤= PGPsdkPrefGetFileSpec( context, info->selector, &tempRef );
d4f1e3 ¤   ¤   #if PGP_MACINTOSH
d2698b ¤   ¤   ¤   if( IsntPGPError( err ) )
cef776 ¤   ¤   ¤   {
a7980e ¤   ¤   ¤   ¤   /*
fb8260 ¤   ¤   ¤   ¤   ** On the Mac, a file spec can become invalid, and
810862 ¤   ¤   ¤   ¤   ** "unrecoverable", if the directory ID containing the file·
2e3f95 ¤   ¤   ¤   ¤   ** no longer exists. To fix this, we validate the existence·
cd43e5 ¤   ¤   ¤   ¤   ** of the dir ID and revert to the default location if the·
e9fbc6 ¤   ¤   ¤   ¤   ** directory no longer exists. Note that we only do this for·
397e92 ¤   ¤   ¤   ¤   ** the random seed and groups files.
dcdf0b ¤   ¤   ¤   ¤   */
752b85 ¤   ¤   ¤   ¤
a69f27 ¤   ¤   ¤   ¤   if( info->selector == kPGPsdkPref_RandomSeedFile ||
f598db ¤   ¤   ¤   ¤   ¤   info->selector == kPGPsdkPref_GroupsFile )
0172c3 ¤   ¤   ¤   ¤   {
3c3a44 ¤   ¤   ¤   ¤   ¤   FSSpec¤ macSpec;
6aae30 ¤   ¤   ¤   ¤   ¤
fd3c4f ¤   ¤   ¤   ¤   ¤   err = PFLGetFSSpecFromFileSpec( (PFLFileSpecRef) tempRef,
e2af91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &macSpec );
866ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
c14859 ¤   ¤   ¤   ¤   ¤   {
a04978 ¤   ¤   ¤   ¤   ¤   ¤   CInfoPBRec¤ cpb;
b894aa ¤   ¤   ¤   ¤   ¤   ¤
156a1c ¤   ¤   ¤   ¤   ¤   ¤   pgpClearMemory( &cpb, sizeof( cpb ) );
3e94aa ¤   ¤   ¤   ¤   ¤   ¤
996f19 ¤   ¤   ¤   ¤   ¤   ¤   cpb.dirInfo.ioVRefNum ¤ = macSpec.vRefNum;
c82dc0 ¤   ¤   ¤   ¤   ¤   ¤   cpb.dirInfo.ioDrDirID ¤ = macSpec.parID;
693db9 ¤   ¤   ¤   ¤   ¤   ¤   cpb.dirInfo.ioFDirIndex = -1;
b894aa ¤   ¤   ¤   ¤   ¤   ¤
6a0827 ¤   ¤   ¤   ¤   ¤   ¤   if( IsErr( PBGetCatInfoSync( &cpb ) ) )
d68fec ¤   ¤   ¤   ¤   ¤   ¤   {
d1facb ¤   ¤   ¤   ¤   ¤   ¤   ¤   PFLFreeFileSpec( (PFLFileSpecRef) tempRef );
0d24cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempRef = kInvalidPGPFileSpecRef;
7b531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
00d0d5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_PrefNotFound;
23db3c ¤   ¤   ¤   ¤   ¤   ¤   }
821c89 ¤   ¤   ¤   ¤   ¤   }
9b2613 ¤   ¤   ¤   ¤   }
b4a3a6 ¤   ¤   ¤   }
7f464b ¤   ¤   #endif¤ /* PGP_MACINTOSH */
b81b52 ¤   ¤
106137 ¤   ¤   ¤   if ( err == kPGPError_PrefNotFound )
3cf776 ¤   ¤   ¤   {
5db69c ¤   ¤   ¤   ¤   /* one doesn't exist yet */
7d97ea ¤   ¤   ¤   ¤   pgpAssert( IsNull( tempRef ) );
340d2b ¤   ¤   ¤   ¤   err¤= PFLSetFileSpecName( locSpec, info->defaultName );
ff3227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
4672c3 ¤   ¤   ¤   ¤   {
298ede ¤   ¤   ¤   ¤   ¤   PGPsdkPrefSetFileSpec( context,
0054d7 ¤   ¤   ¤   ¤   ¤   ¤   info->selector, (PGPFileSpecRef)locSpec );
95290d ¤   ¤   ¤   ¤   ¤   *didAddPrefs¤   = TRUE;
db2613 ¤   ¤   ¤   ¤   }
26a3a6 ¤   ¤   ¤   }
d2cbb1 ¤   ¤   ¤   else if ( IsntPGPError( err ) )
d3f776 ¤   ¤   ¤   {
62de6c ¤   ¤   ¤   ¤   /* no error; there is one already set */
e5ccc0 ¤   ¤   ¤   ¤   PFLFreeFileSpec( (PFLFileSpecRef)tempRef );
11a3a6 ¤   ¤   ¤   }
3e0fe4 ¤   ¤   }
871b52 ¤   ¤
4eecc4 ¤   ¤   PFLFreeFileSpec( locSpec );
--7cb6 000e05eaceb40100280 Page 3 of pgpSDKPrefs.c
a19371 ¤   }
9967c5 ¤
c7deb7 ¤   return( err );
6aefe6 }
baaf5a
aeaf5a
02af5a
3ec744 ¤   PGPError
c59558 PGPsdkLoadPrefs(
b0520e ¤   PGPContextRef¤  context,
b80600 ¤   PGPFileSpecRef¤ prefsSpecIn )
aebb36 {
ee9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
2ec9dc ¤   PGPPrefRef¤ ¤   prefsRef¤   = NULL;
d89c1f ¤   PFLFileSpecRef¤ prefsSpec¤  = (PFLFileSpecRef)prefsSpecIn;
8167c5 ¤
e9f3ca ¤   PGPValidateContext( context );
c00ee3 ¤   PFLValidateFileSpec( prefsSpec );
e967c5 ¤
ee5fc5 ¤   /* create it, if it doesn't already exist */
00af1b ¤   (void)PFLFileSpecCreate( prefsSpec );
9367c5 ¤
eaea9e ¤   err¤= PGPOpenPrefFile( prefsSpec, NULL, 0, &prefsRef );
bef1e7 ¤   if ( IsntPGPError( err ) )
92c7a1 ¤   {
7f752a ¤   ¤   PGPPrefRef¤ ¤   oldPrefs¤   = NULL;
e4cd6d ¤   ¤   PGPBoolean¤ ¤   didAddPrefs;
f667c5 ¤
7fc10a ¤   ¤   oldPrefs¤   = pgpContextGetPrefs( context );
cc56e9 ¤   ¤   if ( IsntNull( oldPrefs ) )
a65b34 ¤   ¤   {
fdd807 ¤   ¤   ¤   PGPClosePrefFile( oldPrefs );
39b27c ¤   ¤   ¤   pgpContextSetPrefs( context, NULL );
1f0fe4 ¤   ¤   }
cf67c5 ¤
b4bbf6 ¤   ¤   pgpContextSetPrefs( context, prefsRef );
c41b52 ¤   ¤
210aed ¤   ¤   (void)sSetDefaultFileLocations( context, &didAddPrefs );
11cde7 ¤   ¤   if ( didAddPrefs )
f35b34 ¤   ¤   {
d405cb ¤   ¤   ¤   /* prefs were added so save them now */
5a7f53 ¤   ¤   ¤   PGPsdkSavePrefs( context );
0a0fe4 ¤   ¤   }
879371 ¤   }
d767c5 ¤
5bdeb7 ¤   return( err );
c8efe6 }
72af5a
28af5a
afc744 ¤   PGPError
25c7f5 PGPsdkLoadDefaultPrefs( PGPContextRef context )
50bb36 {
8d9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
6378c0 ¤   PFLFileSpecRef¤ prefsSpec¤  = NULL;
d167c5 ¤
69f3ca ¤   PGPValidateContext( context );
1a67c5 ¤
356faa ¤   err¤= pgpGetPrefsSpec( PGPGetContextMemoryMgr( context ), &prefsSpec);
02f1e7 ¤   if ( IsntPGPError( err ) )
5bc7a1 ¤   {
2c6491 ¤   ¤   err¤= PGPsdkLoadPrefs( context, (PGPFileSpecRef)prefsSpec );
db1b52 ¤   ¤
acdb66 ¤   ¤   PFLFreeFileSpec( prefsSpec );
029371 ¤   }
2bdeb7 ¤   return( err );
7eefe6 }
a1af5a
e1c744 ¤   PGPError
0429b9 PGPsdkSavePrefs( PGPContextRef context )
62bb36 {
2a26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
e0eced ¤   PGPPrefRef¤ prefsRef¤   = NULL;
--d26a 000d6882c5a40100280 Page 4 of pgpSDKPrefs.c
2a67c5 ¤
12f3ca ¤   PGPValidateContext( context );
db67c5 ¤
44312c ¤   prefsRef¤   = pgpContextGetPrefs( context );
ff93ae ¤   if ( IsNull( prefsRef ) )
bd3cb2 ¤   ¤   err¤= kPGPError_ImproperInitialization;
f00e24 ¤   else
badddf ¤   ¤   err¤= PGPSavePrefFile( prefsRef );
b767c5 ¤
cbdeb7 ¤   return( err );
d6efe6 }
5faf5a
33af5a
240335 /*____________________________________________________________________________
a97c46 ¤   Set the prefs to contain data representing a PFLFileSpecRef
fdf7f7 ____________________________________________________________________________*/
c8c744 ¤   PGPError
32f17e PGPsdkPrefSetFileSpec(
dea1bc ¤   PGPContextRef¤  ¤   context,
735d06 ¤   PGPsdkPrefSelector¤ selector,
be22ac ¤   PGPFileSpecRef¤ ¤   fileSpecIn )
edbb36 {
799372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
57c9dc ¤   PGPPrefRef¤ ¤   prefsRef¤   = NULL;
14f074 ¤   PGPByte *¤  ¤   data¤   = NULL;
8da12a ¤   PGPSize¤¤   ¤   dataLength;
10d91c ¤   PGPMemoryMgrRef¤memoryMgr;
9f3d69 ¤   PFLConstFileSpecRef¤fileSpec¤   = (PFLConstFileSpecRef)fileSpecIn;
1a67c5 ¤
d3f3ca ¤   PGPValidateContext( context );
85976e ¤   PGPValidateParam(
41cd96 ¤   ¤   selector == kPGPsdkPref_PublicKeyring ||
870c89 ¤   ¤   selector == kPGPsdkPref_PrivateKeyring ||
385b72 ¤   ¤   selector == kPGPsdkPref_RandomSeedFile ||
ed89fd ¤   ¤   selector == kPGPsdkPref_GroupsFile );
851859 ¤   PFLValidateFileSpec( fileSpec );
0367c5 ¤
0f312c ¤   prefsRef¤   = pgpContextGetPrefs( context );
9493ae ¤   if ( IsNull( prefsRef ) )
cffe5d ¤   ¤   return( kPGPError_ImproperInitialization );
6367c5 ¤
549cc2 ¤   memoryMgr¤  = PGPGetContextMemoryMgr( context );
4767c5 ¤
055e6d ¤   err¤= PFLExportFileSpec( fileSpec, &data, &dataLength );
95f1e7 ¤   if ( IsntPGPError( err ) )
a7c7a1 ¤   {
f7b589 ¤   ¤   err¤= PGPSetPrefData( prefsRef,
a36f4b ¤   ¤   ¤   ¤   (PGPPrefIndex)selector, dataLength, data );
831b52 ¤   ¤
fc8a3b ¤   ¤   PGPFreeData( data );
cb9371 ¤   }
9e67c5 ¤
c8deb7 ¤   return( err );
f0efe6 }
78af5a
e6af5a
920335 /*____________________________________________________________________________
f3896c ¤   Construct a PFLFileSpecRef from prefs data and return it.
53f7f7 ____________________________________________________________________________*/
36c744 ¤   PGPError
d2bd1a PGPsdkPrefGetFileSpec(
b8a1bc ¤   PGPContextRef¤  ¤   context,
735d06 ¤   PGPsdkPrefSelector¤ selector,
afe41f ¤   PGPFileSpecRef *¤   outSpec )
eebb36 {
959372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
04c9dc ¤   PGPPrefRef¤ ¤   prefsRef¤   = NULL;
97f074 ¤   PGPByte *¤  ¤   data¤   = NULL;
00a12a ¤   PGPSize¤¤   ¤   dataLength;
15d91c ¤   PGPMemoryMgrRef¤memoryMgr;
6b67c5 ¤
d6cba5 ¤   PGPValidatePtr( outSpec );
--e495 000f77b94ba40100280 Page 5 of pgpSDKPrefs.c
94177b ¤   *outSpec¤   = NULL;
38f3ca ¤   PGPValidateContext( context );
30976e ¤   PGPValidateParam(
6fcd96 ¤   ¤   selector == kPGPsdkPref_PublicKeyring ||
340c89 ¤   ¤   selector == kPGPsdkPref_PrivateKeyring ||
835b72 ¤   ¤   selector == kPGPsdkPref_RandomSeedFile ||
0189fd ¤   ¤   selector == kPGPsdkPref_GroupsFile );
d467c5 ¤
aa312c ¤   prefsRef¤   = pgpContextGetPrefs( context );
6e93ae ¤   if ( IsNull( prefsRef ) )
9bfe5d ¤   ¤   return( kPGPError_ImproperInitialization );
fc67c5 ¤
f19cc2 ¤   memoryMgr¤  = PGPGetContextMemoryMgr( context );
4f67c5 ¤
439bc2 ¤   err¤= PGPGetPrefData( prefsRef,
8ca908 ¤   ¤   ¤   (PGPPrefIndex)selector, &dataLength, (void**)&data );
d01b52 ¤   ¤
e9f1e7 ¤   if ( IsntPGPError( err ) )
bec7a1 ¤   {
c22e2a ¤   ¤   PFLFileSpecRef¤ tempRef;
631b52 ¤   ¤
94d951 ¤   ¤   err¤= PFLImportFileSpec( memoryMgr, data, dataLength, &tempRef );
983998 ¤   ¤   *outSpec¤   = (PGPFileSpecRef)tempRef;
cf1b52 ¤   ¤
cdcb87 ¤   ¤   PGPDisposePrefData( prefsRef, data );
b89371 ¤   }
c667c5 ¤
de7716 ¤   pgpAssertErrWithPtr( err, *outSpec );
6fdeb7 ¤   return( err );
a1efe6 }
d2af5a
4aaf5a
830335 /*____________________________________________________________________________
da4e33 ¤   Get raw pref data.
ff67c5 ¤
c5dd17 ¤   Caller must dispose of data with PGPFreeData.
32f7f7 ____________________________________________________________________________*/
0dc744 ¤   PGPError
83de91 PGPsdkPrefGetData(
4da1bc ¤   PGPContextRef¤  ¤   context,
6f5d06 ¤   PGPsdkPrefSelector¤ selector,
38bb06 ¤   void **¤¤   ¤   ¤   outData,
0fb386 ¤   PGPSize *¤  ¤   ¤   outSize )
8dbb36 {
eb9372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
c4c9dc ¤   PGPPrefRef¤ ¤   prefsRef¤   = NULL;
130f9a ¤   void *¤ ¤   ¤   data¤   = NULL;
0238c5 ¤   void *¤ ¤   ¤   prefData = NULL;
29a12a ¤   PGPSize¤¤   ¤   dataLength;
a5bfd9 ¤   PGPMemoryMgrRef¤mgr;
5a67c5 ¤
b0c94c ¤   if ( IsntNull( outSize ) )
b745e0 ¤   ¤   *outSize¤   = 0;
f2640b ¤   if ( IsntNull( outData ) )
42bb7c ¤   ¤   *outData¤   = NULL;
df76dc ¤   PGPValidatePtr( outData );
807bf4 ¤   PGPValidatePtr( outSize );
56f3ca ¤   PGPValidateContext( context );
f3b9bb ¤   PGPValidateParam( selector == kPGPsdkPref_DefaultKeyID );
3167c5 ¤
e4312c ¤   prefsRef¤   = pgpContextGetPrefs( context );
7a93ae ¤   if ( IsNull( prefsRef ) )
52fe5d ¤   ¤   return( kPGPError_ImproperInitialization );
8667c5 ¤
8dfaf1 ¤   mgr¤= PGPGetContextMemoryMgr( context );
a367c5 ¤
3b9bc2 ¤   err¤= PGPGetPrefData( prefsRef,
488a07 ¤   ¤   ¤   (PGPPrefIndex)selector, &dataLength, &prefData );
5c1b52 ¤   ¤
b2f1e7 ¤   if ( IsntPGPError( err ) )
adc7a1 ¤   {
f72405 ¤   ¤   /* we must allocate data with PGPNewData */
--9fb8 000f70aaeb640100280 Page 6 of pgpSDKPrefs.c
da7ec8 ¤   ¤   data¤   = PGPNewData( mgr, dataLength, 0);
7b7a8e ¤   ¤   if ( IsNull( data ) )
785b34 ¤   ¤   {
1f124a ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
31a663 ¤   ¤   ¤   dataLength¤ = 0;
290fe4 ¤   ¤   }
840e1d ¤   ¤   else
6f5b34 ¤   ¤   {
9f8dbf ¤   ¤   ¤   pgpCopyMemory( prefData, data, dataLength );
610fe4 ¤   ¤   }
4087c7 ¤   ¤   ¤
4939a8 ¤   ¤   PGPDisposePrefData( prefsRef, prefData );
319371 ¤   }
2267c5 ¤
434dd8 ¤   *outData¤   = data;
3c3d6c ¤   *outSize¤   = dataLength;
8867c5 ¤
f2ca6f ¤   pgpAssertErrWithPtr( err, *outData );
38deb7 ¤   return( err );
bfefe6 }
50af5a
33af5a
a4af5a
aa0335 /*____________________________________________________________________________
8c4e33 ¤   Get raw pref data.
8267c5 ¤
b8dd17 ¤   Caller must dispose of data with PGPFreeData.
76f7f7 ____________________________________________________________________________*/
ebc744 ¤   PGPError
e91ee0 PGPsdkPrefSetData(
d0a1bc ¤   PGPContextRef¤  ¤   context,
e95d06 ¤   PGPsdkPrefSelector¤ selector,
e27387 ¤   void const *¤   ¤   data,
9f530c ¤   PGPSize¤¤   ¤   ¤   dataSize )
23bb36 {
009372 ¤   PGPError¤   ¤   err¤= kPGPError_NoErr;
0cc9dc ¤   PGPPrefRef¤ ¤   prefsRef¤   = NULL;
3667c5 ¤
bcc40d ¤   PGPValidatePtr( data );
7b8bf4 ¤   PGPValidateParam( dataSize != 0 );
64f3ca ¤   PGPValidateContext( context );
9fb9bb ¤   PGPValidateParam( selector == kPGPsdkPref_DefaultKeyID );
c167c5 ¤
f3312c ¤   prefsRef¤   = pgpContextGetPrefs( context );
f793ae ¤   if ( IsNull( prefsRef ) )
12fe5d ¤   ¤   return( kPGPError_ImproperInitialization );
8267c5 ¤
4f70dc ¤   err¤= PGPSetPrefData( prefsRef,
322aaa ¤   ¤   ¤   (PGPPrefIndex)selector, dataSize, data );
e467c5 ¤
47deb7 ¤   return( err );
1befe6 }
a9af5a
52af5a
6aaf5a
b5af5a
66af5a
deaf5a
91af5a
cbaf5a
b8af5a
09af5a
57af5a
6daf5a
8baf5a
3daf5a
30af5a
a6af5a
ecaf5a
24af5a
68af5a
f7af5a
--ef1f 0014e15106440100280 Page 7 of pgpSDKPrefs.c
e0af5a
1aaf5a
17af5a
78af5a
32af5a
93af5a
37af5a
a6af5a
33af5a
24af5a
e27e4d /*__Editor_settings____
38af5a
c14126 ¤   Local Variables:
6e7b17 ¤   tab-width: 4
b10e6c ¤   End:
495f8c ¤   vi: ts=4 sw=4
139e9b ¤   vim: si
4ed062 _____________________*/
--811e 0015f33ba2240100281 Page 1 of Makefile.in
5ea601 #
e64ddf # priv/utilities/utils/
37a601 #
5de6a6 # $Id: Makefile.in,v 1.2 1997/05/04 10:30:34 mhw Exp $
a2a601 #
00af5a
5555dc OBJS=¤  pgpConf.o pgpDecPipe.o pgpEncPipe.o pgpFileType.o pgpEnv.o \
530567 ¤   pgpSigPipe.o pgpSigSpec.o
5c7d7f PRIVHDRS= pgpConf.h pgpDecPipe.h pgpEncPipe.h pgpFileType.h pgpEnv.h \
3bb8a8 ¤   pgpSigPipe.h pgpSigSpec.h
0faf5a
36b7a3 all:: DONE
5faf5a
--3d98 0001f82c92740100282 Page 1 of pgpConf.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
209341 ¤   $Id: pgpConf.c,v 1.14.12.1 1998/11/12 03:23:27 heller Exp $
89f7f7 ____________________________________________________________________________*/
3fe2ff #include "pgpConfig.h"
33af5a
b7b1cb #include <ctype.h>
ebfeb2 #include <stdio.h>
6797f5 #include <stdlib.h>¤/* For strtol() */
88324c #include <string.h>
dbaf5a
dca8e8 #include "pgpConf.h"
3f0d6d #include "pgpEnv.h"
0e2f8d #include "pgpErrors.h"
c41bea #include "pgpMsg.h"
0ae117 #include "pgpUI.h"
c9af5a
254fe0 typedef struct Config
d8bb36 {
9987ce ¤   char const *name;
185806 ¤   int var;
3be280 ¤   unsigned flags;
2be6f9 ¤   int min, max;
8d4fc0 } Config;
3daf5a
9c43ac /* The following are in the flags: */
5dce8c #define OPT_TYPEMASK¤   3
0a6390 #define OPT_IGNORE¤ 0¤  /* Ignore if encountered */
f5acd1 #define OPT_BINARY¤ 1¤  /* PGPBoolean options: min = false, max = true */
8fde35 #define OPT_INT¤¤   2¤  /* Integer option, in range [min,max] */
caec8d #define OPT_STRING¤ 3¤  /* String, of length <= max */
5492d0 /* The following additional flags are also used: */
800744 #define OPT_CMD¤¤   4¤  /* Command line only */
c6b08c #define OPT_LOWER¤  8¤  /* Lowercase strings before storing */
c13609 #define OPT_FUNC¤   16¤ /* Call function rather than set conf */
6baf5a
36b19f /* Up to this many errors are ignored when reading a config file. */
591379 #define MAX_ERRORS 3¤   /* Don't give up right away on error. */
abaf5a
e4ad41 #define FUNC_RANDSOURCE¤2
ceaf5a
3d3a6f /* The options list. ·Indexes in the left margin are used in configInit. */
122fdc static Config·
0d0207 EnvOptions[] = {
f102f1 ¤   { "armor", ···········PGPENV_ARMOR, ······OPT_BINARY, ····0, 1 },
5ad0f5 ¤   { "armorlines", ······PGPENV_ARMORLINES, ·OPT_INT, ·······0, INT_MAX },
3d36d8 ¤   { "bakring", ·········PGPENV_BAKRING, ····OPT_STRING, ····0, 0 },
89f2b6 ¤   { "cert_depth", ······PGPENV_CERTDEPTH, ··OPT_INT, ·······0, 8 },
cf8a22 ·¤  { "charset", ·········PGPENV_CHARSET, ····OPT_STRING, ····0, 0 },
10aaab ¤   { "clearsig", ········PGPENV_CLEARSIG, ···OPT_BINARY, ····0, 1 },
334edf ¤   { "comment", ·········PGPENV_COMMENT, ····OPT_STRING, ····0, 70 },
d8d3a2 ¤   { "completes_needed", PGPENV_COMPLETES, ··OPT_INT, ·······1, 4 },
a5dd8c ¤   { "compress", ········PGPENV_COMPRESS, ···OPT_BINARY, ····0, 1 },
85b1af ¤   { "companykey", ······PGPENV_COMPANYKEY, ·OPT_STRING, ····0, 255 },
2ed7e0 ¤   { "encrypttoself", ···PGPENV_ENCRYPTTOSELF,OPT_BINARY, ····0, 1 },
a47ef0 /*¤ { "interactive", ·····PGPENV_INTERACTIVE, OPT_BINARY, ····0, 1 },*/
bd70e8 /*¤ { "keepbinary", ······PGPENV_KEEPBINARY, ·OPT_BINARY, ····0, 1 },*/
178fd3 ¤   { "language", ········PGPENV_LANGUAGE, ·OPT_STRING|OPT_LOWER, ·0, 16 },
58fb94 ¤   { "marginals_needed", PGPENV_MARGINALS, ··OPT_INT, ·······1, 4 },
58d09b ¤   { "myname", ··········PGPENV_MYNAME, ·····OPT_STRING, ····0, 255 },
96225d /*¤ { "pager", ···········PGPENV_PAGER, ······OPT_STRING, ····0, 255 },*/
883af1 /*¤ { "pkcs_compat", ·····PGPENV_PKCS_COMPAT, OPT_INT, ·····0, INT_MAX },*/
d858d3 ¤   { "pgp_mime", ········PGPENV_PGPMIME, ····OPT_BINARY, ····0, 1 },
7d482c ¤   { "pgp_mimeparse", ···PGPENV_PGPMIMEPARSEBODY, OPT_BINARY,0, 1 },
15a2eb ¤   { "pubring", ·········PGPENV_PUBRINGnolongerused, ····OPT_STRING,0, 0 },
3529b1 ¤   { "randomdevice", ····PGPENV_RANDOMDEVICE, OPT_STRING, ···0, 0 },
3e77d3 ¤   { "randseed", ········PGPENV_RANDSEEDnolongerused, ···OPT_STRING, ·0, 0 },
1f129a #if PGP_UNIX
--6bfb 0002cb9561540100282 Page 2 of pgpConf.c
49fa3b /*¤ { "randsource", ······FUNC_RANDSOURCE, ·OPT_STRING|OPT_FUNC, ·0, 0 },*/
be7454 #endif
42a988 ¤   { "secring", ·········PGPENV_SECRINGnolongerused, ····OPT_STRING, 0, 0 },
484e86 ¤   { "showpass", ········PGPENV_SHOWPASS, ···OPT_BINARY, ····0, 1 },
eff4fc ¤   { "textmode", ········PGPENV_TEXTMODE, ···OPT_BINARY, ····0, 1 },·
118dbe ¤   { "tmp", ·············PGPENV_TMP, ········OPT_STRING, ····0, 0 },
93f553 /* Temp for new trust - change to something better */
55739e ¤   { "trusted", ·········PGPENV_TRUSTED, ····OPT_INT, ·······0, 255 },
719a10 ¤   { "tzfix", ···········PGPENV_TZFIX, ······OPT_INT, ·······-24, 24 },
06a280 ¤   { "verbose", ·········PGPENV_VERBOSE, ····OPT_INT, ·······0, INT_MAX },
b4f044 /* Experimental XXX@@@ */
65550e ¤   { "version", ·········PGPENV_VERSION, ····OPT_INT, ·······2, 4 },
42fcd2 ¤   { "ciphernum",¤ ······PGPENV_CIPHER,¤   ··OPT_INT,¤ ··1, INT_MAX },
f41946 ¤   { "hashnum",¤   ······PGPENV_HASH,¤ ··OPT_INT,¤ ··1, INT_MAX },
55cc52 ¤   { "fastkeygen", ······PGPENV_FASTKEYGEN, ·OPT_BINARY,¤  ··0, 1 },
5baf5a
49ac41 ¤   /* command line only */
0c9f96 ¤   { "batchmode", ·······PGPENV_BATCHMODE, ··OPT_BINARY|OPT_CMD, ·0, 1 },
5cdc0e ¤   { "force", ···········PGPENV_FORCE, ······OPT_BINARY|OPT_CMD, ·0, 1 },
310cf3 ¤   { "magic", ···········PGPENV_MAGIC, ······OPT_BINARY|OPT_CMD, ·0, 1 },
410da7 ¤   { "noout", ···········PGPENV_NOOUT, ······OPT_BINARY|OPT_CMD, ·0, 1 },
eade64 ¤   /* Null-terminated */
a297dc ¤   { (char const *)0, ···0, ··············0,¤  0, 0 }
6282f7 };
43af5a
8d0cfc /* Case-insensitive memory compare */
75beb7 static int
6d08d1 xmemicmp (char const *in1, char const *in2, int len)
19bb36 {
fdcae5 ¤   while (len--) {
aa1fb4 ¤   ¤   if (tolower(*in1) != tolower(*in2))
b3db98 ¤   ¤   ¤   return 1;
15beb3 ¤   ¤   in1++;
19a37f ¤   ¤   in2++;
059371 ¤   }
813e6b ¤   return 0;
c4efe6 }
82af5a
3c38e5 /*
7dea16 ·* Find a keyword in a null-terminated options list.
932b07 ·* Returns the option, or NULL if the option is ambiguous,
6bae04 ·* or a pointer to the null option if it is not found.
78d24a ·* optmask is a mask of bits in the opt->flags list which cause
1561bc ·* entries with any of those bits set to be ignored.
ca495d ·*/
f701d4 static Config const *
5feb81 configLookup (PGPUICb const *ui, void *arg, unsigned linenum,
e865b9 ¤   ·····char const *key, unsigned keylen, int optmask)
13bb36 {
e9ef07 ¤   Config *hit = NULL;
7a4ba4 ¤   int i;
d3de7f ¤   PgpUICbArg msgarg1, msgarg2, msgarg3, msgarg4;
5faf5a
32632b ¤   for (i=0; EnvOptions[i].name; i++) {
9881db ¤   ¤   if ((EnvOptions[i].flags & optmask) != 0)
2d17f5 ¤   ¤   ¤   continue;
508050 ¤   ¤   if (xmemicmp(EnvOptions[i].name, key, keylen) != 0)
e017f5 ¤   ¤   ¤   continue;
0a256a ¤   ¤   /* We have a match! */
95b6b9 ¤   ¤   if (strlen(EnvOptions[i].name) == keylen)·
905fb2 ¤   ¤   ¤   return (&(EnvOptions[i])); /* exact match */
50e131 ¤   ¤   /* Do we have a double match? */
b112b1 ¤   ¤   if (hit) {
6b5aeb ¤   ¤   ¤   msgarg1.type = PGP_UI_ARG_UNSIGNED;
69ed9e ¤   ¤   ¤   msgarg1.val.u = linenum;
fc12cf ¤   ¤   ¤   msgarg2.type = PGP_UI_ARG_BUFFER;
9b4ddd ¤   ¤   ¤   msgarg2.val.buf.buf = (PGPByte *)key;
bc667d ¤   ¤   ¤   msgarg2.val.buf.len = keylen;
1ddd1e ¤   ¤   ¤   msgarg3.type = PGP_UI_ARG_STRING;
6a2213 ¤   ¤   ¤   msgarg3.val.s = hit->name;
a7a766 ¤   ¤   ¤   msgarg4.type = PGP_UI_ARG_STRING;
2c9567 ¤   ¤   ¤   msgarg4.val.s = EnvOptions[i].name;
--745e 0009e8376e440100282 Page 3 of pgpConf.c
cca8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
fca242 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_AMBIGUOUS, 4, &msgarg1,
a1a876 ¤   ¤   ¤   ¤   ·····&msgarg2, &msgarg3, &msgarg4);
c9af5a
3b9d63 ¤   ¤   ¤   return (Config const *)0;
4c0fe4 ¤   ¤   }
8f1ff0 ¤   ¤   /* Remember this match */
f7463d ¤   ¤   hit = &(EnvOptions[i]);
8431e8 ¤   ¤   /* Keep looking for an exact match or ambiguity. */
7e9371 ¤   }
ddaf5a
43f012 ¤   if (hit) {
cf60c2 ¤   ¤   return hit;
799371 ¤   }
d8af5a
3fcadd ¤   msgarg1.type = PGP_UI_ARG_UNSIGNED;
926ba0 ¤   msgarg1.val.u = linenum;
1a17e4 ¤   msgarg2.type = PGP_UI_ARG_BUFFER;
d33b26 ¤   msgarg2.val.buf.buf = (PGPByte *)key;
e1b5e0 ¤   msgarg2.val.buf.len = keylen;
1b723d ¤   ui->message (arg, kPGPError_ConfigParseFailure,
6279de ¤   ¤   ¤   PGPMSG_CONFIG_UNKNOWN_KEYWORD,
ed167e ¤   ¤   ·····2, &msgarg1, &msgarg2);
7daf5a
02927e ¤   return (&EnvOptions[i]);
6cefe6 }
94af5a
93beb7 static int
69a1ea configCallFunci (PGPEnv *env, int varnum, int val, int pri)
79bb36 {
397054 ¤   (void)env;
8b9dce ¤   (void)val;
197987 ¤   (void)pri;
f3ec86 ¤   switch (varnum) {
312f72 ¤   default:
c7adf7 ¤   ¤   return kPGPError_ConfigParseFailureBadFunction;
c19371 ¤   }
ddefe6 }
d8af5a
1bbeb7 static int
4c52a6 configCallFuncs (PGPEnv *env, int varnum, char const *string, int len,
d6beca ¤   ¤   ·int pri)
a6bb36 {
317054 ¤   (void)env;
4fe647 ¤   (void)string;
03a272 ¤   (void)len;
367987 ¤   (void)pri;
eaec86 ¤   switch (varnum) {
1c6021 ¤   case FUNC_RANDSOURCE:
b32f72 ¤   default:
9dadf7 ¤   ¤   return kPGPError_ConfigParseFailureBadFunction;
859371 ¤   }
afefe6 }
eaaf5a
485957 /* Return the number of leading whitespace characters in a buffer */
8765bf static unsigned
15d3e1 skipWhite(char const *buf)
cebb36 {
146287 ¤   unsigned i = 0;
82af5a
99320e ¤   while (isspace(buf[i]))
e4347d ¤   ¤   i++;
5faf5a
9c2196 ¤   return i;
13efe6 }
3aaf5a
2038e5 /*
844a1a ·* Reduce "len" by the amount of trailing whitespace characters in the
ea4225 ·* string starting at buf and len characters long.
89495d ·*/
7465bf static unsigned
9e730a unskipWhite(char const *buf, unsigned len)
--d9c9 000c2a37a3340100282 Page 4 of pgpConf.c
2cbb36 {
2a428a ¤   while (len && isspace(buf[len-1]))
bd9647 ¤   ¤   --len;
c2af5a
7fbb7a ¤   return len;
9defe6 }
5faf5a
1138e5 /*
76c399 ·* Get a word up to the next non-graphic character, comment symbol (#)
1b8afa ·* or delimiter (such as '='). ·Set delimiter to a non-graphic character
d9965a ·* (0 works well) to not use it.
3e0f54 ·* Returns the length of the word found.
18495d ·*/
8d65bf static unsigned
d88b81 getWord(char const *buf, char delimiter)
3dbb36 {
a30273 ¤   char c;
cb8034 ¤   int i = 0;
15af5a
5f43ab ¤   do {
2b81d2 ¤   ¤   c = buf[i++];
545906 ¤   } while (isgraph(c) && c != '#' && c != delimiter);
35af5a
d0a765 ¤   return i-1;
c0efe6 }
37af5a
2138e5 /*
819b53 ·* Get a string in the nasty non-quoted format.
8d8c31 ·* Spaces are allowed, but the string ends at a comment and
e26c38 ·* trailing whitespace is suppresed.
ad8bd6 ·* Returns the length of the string found.
e1495d ·*/
c365bf static unsigned
cdc77b getString(char const *buf)
40bb36 {
7c0273 ¤   char c;
bb6287 ¤   unsigned i = 0;
47af5a
56cfa1 ¤   do
1481d2 ¤   ¤   c = buf[i++];
70057b ¤   while (isprint(c) && c != '#');
22af5a
a0edef ¤   return unskipWhite(buf, i-1);
34efe6 }
d8af5a
cf38e5 /*
dc2007 ·* Get a quoted string. ·Anything is allowed up to a trailing double
ff97b0 ·* quote. ·Returns the length of the string found, or -1 on error.
2a495d ·*/
dd65bf static unsigned
c84a44 getQString(PGPUICb const *ui, void *arg, unsigned linenum,
ee539f ¤   ···char const *buf)
c9bb36 {
9f0273 ¤   char c;
816287 ¤   unsigned i = 0;
edea31 ¤   PgpUICbArg msgarg1, msgarg2;
8aaf5a
36cfa1 ¤   do
1981d2 ¤   ¤   c = buf[i++];
ef805c ¤   while (c && c != '"');
bbaf5a
3d2022 ¤   --i;
0baf5a
b12aea ¤   if (c == '"')
8da423 ¤   ¤   return i;
f2af5a
484414 ¤   /* Error case - drop trailing whitespace (like NL) when printing */
59cadd ¤   msgarg1.type = PGP_UI_ARG_UNSIGNED;
a46ba0 ¤   msgarg1.val.u = linenum;
fe17e4 ¤   msgarg2.type = PGP_UI_ARG_BUFFER;
6766b1 ¤   msgarg2.val.buf.buf = (PGPByte *)buf;
c2e272 ¤   msgarg2.val.buf.len = unskipWhite (buf, i);
--f21e 0004059f24540100282 Page 5 of pgpConf.c
2ab18a ¤   ui->message (arg, kPGPError_ConfigParseFailure, PGPMSG_CONFIG_STRINGEND,
49167e ¤   ¤   ·····2, &msgarg1, &msgarg2);
36af5a
cd5572 ¤   return (unsigned)-1;
acefe6 }
f5af5a
b5af5a
f538e5 /*
16bc52 ·* Parse a line of input. ·linenum == 0 indicates the command line,
bdfc79 ·* and causes a few changes in activity:
5f3acd ·* - some extra parameters are recognized (OPT_CMD)
e4f657 ·* - "=ON" is implicit for boolean options
b37ffd ·* - error messages are printed differently
7c5c1a ·* - Unknown keywords are fatal
86c2ff ·* - Strings need not be copied, since the argv array isn't going away
9e775e ·*
ba4674 ·* Note that the input "line" array is not permanently modified, but it
2b7fa8 ·* is occasionally modified in place temporarily to install a trailing
e50be3 ·* null character in the middle.
ce775e ·*
00b77e ·* Returns 0 on success, a kPGPError_* on failure.
bd495d ·*/
adbeb7 static int
d726d2 configLineParse(PGPUICb const *ui, void *arg, PGPEnv *env,
012616 ¤   ¤   unsigned linenum, char *line, int pri)
c0bb36 {
350518 ¤   char const *key;
75694f ¤   unsigned keylen;
f4743f ¤   unsigned i;
47d1ee ¤   Config const *opt;
fafc30 ¤   long val;
6e813a ¤   char *p;
d0802a ¤   PgpUICbArg msgarg1, msgarg2, msgarg3, msgarg4, msgarg5;
00af5a
387f5a ¤   line += skipWhite (line);
89af5a
fe2b44 ¤   keylen = getWord (line, '=');
5e0244 ¤   if (!keylen)
649238 ¤   ¤   return 0;¤  /* Blank line */
ebaf5a
c2d6c0 ¤   key = line;
ddaf5a
fadc45 ¤   opt = configLookup (ui, arg, linenum, key, keylen,
926ea0 ¤   ¤   ¤   ····linenum ? OPT_CMD : 0);
7a02d1 ¤   if (!opt)
6e641a ¤   ¤   return kPGPError_ConfigParseFailureBadOptions;
649df5 ¤   if (!opt->name)¤/* In the config file, not found isn't fatal */
a79b79 ¤   ¤   return linenum ? 0 : kPGPError_ConfigParseFailureBadOptions;
974192 ¤   if ((opt->flags & OPT_TYPEMASK) == OPT_IGNORE)
2dbbde ¤   ¤   return 0;
c3af5a
61cadd ¤   msgarg1.type = PGP_UI_ARG_UNSIGNED;
916ba0 ¤   msgarg1.val.u = linenum;
3617e4 ¤   msgarg2.type = PGP_UI_ARG_BUFFER;
dc3b26 ¤   msgarg2.val.buf.buf = (PGPByte *)key;
eab5e0 ¤   msgarg2.val.buf.len = keylen;
9caf5a
23c1b3 ¤   line += keylen;
faf9ca ¤   line += skipWhite(line);
f6e924 ¤   if (*line != '=') {
ae6de5 ¤   ¤   /* On the command line, "armor" means "armor=on" */
9ad615 ¤   ¤   if (!linenum && *line == '\0' &&
45010e ¤   ¤   ····(opt->flags & OPT_TYPEMASK) == OPT_BINARY)
0d5b34 ¤   ¤   {
814878 ¤   ¤   ¤   if (opt->flags & OPT_FUNC)
480a3e ¤   ¤   ¤   ¤   (void)configCallFunci(env, opt->var, opt->max,
0b402d ¤   ¤   ¤   ¤   ¤   ¤   ······pri);
d8bb8c ¤   ¤   ¤   else
08f888 ¤   ¤   ¤   ¤   (void)pgpenvSetInt(env,
117f2c ¤   ¤   ¤   ¤   ¤   ¤   ···(PgpEnvInts)opt->var,
fa1bea ¤   ¤   ¤   ¤   ¤   ¤   ···opt->max, pri);
408144 ¤   ¤   ¤   return 0;
--6850 000ae4d2fe140100282 Page 6 of pgpConf.c
b50fe4 ¤   ¤   }
e6af5a
8e2791 ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
ffa053 ¤   ¤   ¤   ¤   PGPMSG_CONFIG_MISSING_EQUAL,
351393 ¤   ¤   ¤   ·····2, &msgarg1, &msgarg2);
03af5a
71dd48 ¤   ¤   return kPGPError_ConfigParseFailure;
ce9371 ¤   }
ec244d ¤   line++; ·/* skip '=' */
d8af5a
06d4fa ¤   /* Skip assignment and following whitespace */
f2f9ca ¤   line += skipWhite(line);
2eaf5a
11eb92 ¤   switch (opt->flags & OPT_TYPEMASK) {
8c3054 ¤   ··case OPT_BINARY:
1a401b ¤   ¤   i = getWord(line, 0);
53cb35 ¤   ¤   if ((i == 3 && xmemicmp("off", line, 3) == 0) ||
4c90af ¤   ¤   ····(i == 1 && line[0] == '0'))
6c5b34 ¤   ¤   {
274878 ¤   ¤   ¤   if (opt->flags & OPT_FUNC)
6abcaa ¤   ¤   ¤   ¤   (void)configCallFunci(env, opt->var, opt->min,
bb402d ¤   ¤   ¤   ¤   ¤   ¤   ······pri);
33bb8c ¤   ¤   ¤   else
07f888 ¤   ¤   ¤   ¤   (void)pgpenvSetInt(env,
8c7f2c ¤   ¤   ¤   ¤   ¤   ¤   ···(PgpEnvInts)opt->var,
302948 ¤   ¤   ¤   ¤   ¤   ¤   ···opt->min, pri);
15cdcb ¤   ¤   ¤   break;
4e373a ¤   ¤   } else if ((i == 2 && xmemicmp("on", line, 2) == 0) ||
7f4426 ¤   ¤   ···········(i == 1 && line[0] == '1'))
135b34 ¤   ¤   {
554878 ¤   ¤   ¤   if (opt->flags & OPT_FUNC)
5b0a3e ¤   ¤   ¤   ¤   (void)configCallFunci(env, opt->var, opt->max,
e0402d ¤   ¤   ¤   ¤   ¤   ¤   ······pri);
e6bb8c ¤   ¤   ¤   else
08f888 ¤   ¤   ¤   ¤   (void)pgpenvSetInt(env,
607f2c ¤   ¤   ¤   ¤   ¤   ¤   ···(PgpEnvInts)opt->var,
041bea ¤   ¤   ¤   ¤   ¤   ¤   ···opt->max, pri);
70cdcb ¤   ¤   ¤   break;
e888e7 ¤   ¤   } else if (i == 0) {
c4a8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
0f06db ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_MISSING_BOOLEAN, 2,
a5db21 ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2);
5acdcb ¤   ¤   ¤   break;
af0fe4 ¤   ¤   }
09c704 ¤   ¤   /* Fall through: default case */
c6e514 ¤   ¤   msgarg3.type = PGP_UI_ARG_BUFFER;
57f94d ¤   ¤   msgarg3.val.buf.buf = (PGPByte *)line;
9e9c65 ¤   ¤   msgarg3.val.buf.len = i;
1daf5a
072791 ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
47c18f ¤   ¤   ¤   ·····PGPMSG_CONFIG_UNKNOWN_BOOLEAN, 3, &msgarg1,
a5784a ¤   ¤   ¤   ·····&msgarg2, &msgarg3);
42dd48 ¤   ¤   return kPGPError_ConfigParseFailure;
39af5a
d919a3 ¤   ··case OPT_INT:
b3eebe ¤   ¤   val = strtol (line, &p, 0);
bdecdf ¤   ¤   i = getWord (line, 0);
31af5a
bce514 ¤   ¤   msgarg3.type = PGP_UI_ARG_BUFFER;
f7f94d ¤   ¤   msgarg3.val.buf.buf = (PGPByte *)line;
179c65 ¤   ¤   msgarg3.val.buf.len = i;
02af5a
921fa9 ¤   ¤   if (!isspace(*p) && *p != '\0') {
54e0af ¤   ¤   ¤   if (i) {
4fe08b ¤   ¤   ¤   ¤   ui->message
c8ef0c ¤   ¤   ¤   ¤   ¤   (arg, kPGPError_ConfigParseFailure,
ce7d4d ¤   ¤   ¤   ¤   ¤   ·PGPMSG_CONFIG_UNKNOWN_INTEGER, 3,
88a071 ¤   ¤   ¤   ¤   ¤   ·&msgarg1, &msgarg2, &msgarg3);
78042d ¤   ¤   ¤   } else {
6de08b ¤   ¤   ¤   ¤   ui->message
09ef0c ¤   ¤   ¤   ¤   ¤   (arg, kPGPError_ConfigParseFailure,
ae573a ¤   ¤   ¤   ¤   ¤   ·PGPMSG_CONFIG_MISSING_INTEGER, 2,
--2703 000cc023bfa40100282 Page 7 of pgpConf.c
fa3bb9 ¤   ¤   ¤   ¤   ¤   ·&msgarg1, &msgarg2);
4fa3a6 ¤   ¤   ¤   }
178fd5 ¤   ¤   ¤   return kPGPError_ConfigParseFailure;
180fe4 ¤   ¤   }
7beb55 ¤   ¤   msgarg4.type = PGP_UI_ARG_INT;
7a4c37 ¤   ¤   msgarg4.val.i = val;
c24bbc ¤   ¤   if (val > (long)opt->max) {
17e162 ¤   ¤   ¤   msgarg5.type = PGP_UI_ARG_INT;
08dff0 ¤   ¤   ¤   msgarg5.val.i = opt->max;
3ba8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
446c9f ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_INT_TOO_HIGH, 4,
bcf1dd ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2, &msgarg4, &msgarg5);
93d798 ¤   ¤   ¤   val = (long)opt->max;
998fbb ¤   ¤   } else if (val < (long)opt->min) {
2ae162 ¤   ¤   ¤   msgarg5.type = PGP_UI_ARG_INT;
fea369 ¤   ¤   ¤   msgarg5.val.u = opt->min;
e3a8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
ae0f30 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_INT_TOO_LOW, 4,
b8f1dd ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2, &msgarg4, &msgarg5);
25610c ¤   ¤   ¤   val = (long)opt->min;
cd0fe4 ¤   ¤   }
c2e8f5 ¤   ¤   if ((opt->flags & OPT_FUNC) == 0) {
cf1bff ¤   ¤   ¤   (void)pgpenvSetInt(env, (PgpEnvInts)opt->var,
3e3b12 ¤   ¤   ¤   ¤   ¤   ···(int)val, pri);
7746c9 ¤   ¤   } else if (configCallFunci(env, opt->var, (int)val, pri) < 0) {
caa8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
5b1577 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_INVALID_INTEGER, 3,
e96c71 ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2, &msgarg3);
098fd5 ¤   ¤   ¤   return kPGPError_ConfigParseFailure;
f10fe4 ¤   ¤   }
762f68 ¤   ¤   break;
7eaf5a
80996a ¤   ··case OPT_STRING:
f16b9f ¤   ¤   if (*line == '"') {
84d731 ¤   ¤   ¤   i = getQString(ui, arg, linenum, ++line);
6d8373 ¤   ¤   ¤   if (i == (unsigned)-1)
c8dcce ¤   ¤   ¤   ¤   return kPGPError_ConfigParseFailure;
9745a6 ¤   ¤   } else {
fa4b29 ¤   ¤   ¤   i = getString(line);
6d0fe4 ¤   ¤   }
69af5a
bce514 ¤   ¤   msgarg3.type = PGP_UI_ARG_BUFFER;
23f94d ¤   ¤   msgarg3.val.buf.buf = (PGPByte *)line;
429c65 ¤   ¤   msgarg3.val.buf.len = i;
23af5a
ba84a5 ¤   ¤   if (i > (unsigned)opt->max-1) {
62e519 ¤   ¤   ¤   msgarg4.type = PGP_UI_ARG_INT;
82214c ¤   ¤   ¤   msgarg4.val.i = opt->max-1;
5ca8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
fd7369 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_STRING_TOO_LONG, 3,
123b50 ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2, &msgarg4);
ee8fd5 ¤   ¤   ¤   return kPGPError_ConfigParseFailure;
c44921 ¤   ¤   ¤   /* Call function to set: never any need to copy */
3f0fe4 ¤   ¤   }
5e5b34 ¤   ¤   {
268fb0 ¤   ¤   ¤   char c;
6d6b21 ¤   ¤   ¤   int status;
46af5a
5a7249 ¤   ¤   ¤   c = line[i];
ae80e6 ¤   ¤   ¤   line[i] = '\0';¤/* Null-terminate the string */
6aaf5a
a84878 ¤   ¤   ¤   if (opt->flags & OPT_FUNC)
df2a95 ¤   ¤   ¤   ¤   status = configCallFuncs (env, opt->var,
9d74fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··line, i, pri);
45bb8c ¤   ¤   ¤   else
d3aeda ¤   ¤   ¤   ¤   status = pgpenvSetString
a1f1a0 ¤   ¤   ¤   ¤   ¤   (env, (PgpEnvStrings) opt->var,
287b41 ¤   ¤   ¤   ¤   ¤   ·line, pri);
38af5a
44737e ¤   ¤   ¤   line[i] = c;¤   /* Restore the string */
507272 ¤   ¤   ¤   if (status >= 0)
cca394 ¤   ¤   ¤   ¤   break;¤ /* Success */
--6866 000461425a440100282 Page 8 of pgpConf.c
cca8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
e85646 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_INVALID_STRING, 3,
616c71 ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2, &msgarg3);
598fd5 ¤   ¤   ¤   return kPGPError_ConfigParseFailure;
6f0fe4 ¤   ¤   }
3b2f68 ¤   ¤   break;
289371 ¤   }
f6af5a
553e6b ¤   return 0;
b0efe6 }
7aaf5a
c638e5 /*
1069a9 ·* "option" may be modified temporarily, but it is restored prior to
dea719 ·* returning.
e2495d ·*/
144d2f int
effa30 pgpConfigLineProcess(PGPUICb const *ui, void *arg,
fc668f ¤   ¤   ·····PGPEnv *env, char *option, int pri)
e9bb36 {
e088c6 ¤   if (!ui || !ui->message)
3962b5 ¤   ¤   return kPGPError_BadParams;
06af5a
d9d7e1 ¤   return configLineParse (ui, arg, env, 0, option, pri);
99efe6 }
8eaf5a
236291 #define CPM_EOF¤26¤ /* ^Z - accept this as a file terminator. */
a438e5 /*
26b6c2 ·* Read a line from file f, into buf, up to the given length. ·Anything after
c951de ·* that is ignored. ·Strips trailing spaces and line terminator, can read
60f65e ·* LF, CRLF and CR terminated lines. ·Also accepts CPM_EOF (^Z) as a file
71ef93 ·* terminator.
76495d ·*/
f0083f static char *
9a1d58 configLineGet(FILE *f, char *buf, unsigned len)
ebbb36 {
5438de ¤   int c;
38aa04 ¤   char *p = buf;
faaf5a
6715ef ¤   /* Skip leading whitespace */
1943ab ¤   do {
124c2c ¤   ¤   c = getc(f);
08a467 ¤   } while (c == ' ' || c == '\t');
10af5a
82c92a ¤   while (len > 0 && c != '\n' && c != '\r' && ·c != EOF && c != CPM_EOF)
50c7a1 ¤   {
4eeb99 ¤   ¤   *p++ = c;
789647 ¤   ¤   --len;
cd4c2c ¤   ¤   c = getc(f);
119371 ¤   }
82af5a
b0671c ¤   /* Return NULL on EOF */
819e80 ¤   if (p == buf && (c == EOF || c == CPM_EOF)) {
783f61 ¤   ¤   *buf = '\0';
179e22 ¤   ¤   return (char *)0;
b79371 ¤   }
f067c5 ¤
f6d8af ¤   /*
39112f ¤   * Skip to end of line, setting len to non-zero if anything trailing is
a304e9 ¤   * not a space (meaning that any trailing whitespace in the buffer is
308a93 ¤   * not trailing whitespace on the line and should not be stripped).
a49faa ¤   */
e2eee0 ¤   len = 0;
3eb0ba ¤   while (c != '\n' && c != '\r' && c != EOF && c != CPM_EOF) {
75f38e ¤   ¤   len |= c ^ ' ';¤/* Avoid branches for fast processors */
0e4c2c ¤   ¤   c = getc(f);
119371 ¤   }
89af5a
7c6b00 ¤   /* Put back CPM_EOF, and character after \r if it's not \n */
21aae0 ¤   if (c == CPM_EOF || (c == '\r' && (c = getc(f)) != '\n'))
8495fb ¤   ¤   ungetc(c, f);
81524c ¤   /* If line wasn't too long, skip trailing WS and null-terminate */
46d517 ¤   if (!len) { ··/* Skip trailing whitespace, as described above */
--2b93 0007cbdc38c40100282 Page 9 of pgpConf.c
fd1c8b ¤   ¤   while (p >= buf && p[-1] == ' ')
dc8c01 ¤   ¤   ¤   --p;
233f17 ¤   ¤   *p = '\0';
bb9371 ¤   }
4edfa1 ¤   return buf;
7fefe6 }
46af5a
9c4d2f int
3b9638 pgpConfigFileProcess(PGPUICb const *ui, void *arg,
91bcfc ¤   ¤   ·····PGPEnv *env, char const *filename, int pri)
ecbb36 {
19f6d5 ¤   FILE *f;
b0c790 ¤   unsigned linenum = 0;
31091d ¤   unsigned errors = 0;
a34ba4 ¤   int i;
4e15b6 ¤   char buf[130];¤ /* Maximum allowable line size */
6a9013 ¤   PgpUICbArg msgarg1, msgarg2, msgarg3;
20af5a
8988c6 ¤   if (!ui || !ui->message)
6662b5 ¤   ¤   return kPGPError_BadParams;
0daf5a
12bea1 ¤   f = fopen (filename, "r");
c42137 ¤   if (f == NULL) {
0a70f6 ¤   ¤   msgarg1.type = PGP_UI_ARG_STRING;
0eac84 ¤   ¤   msgarg1.val.s = filename;
982791 ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
929769 ¤   ¤   ¤   ·····PGPMSG_CONFIG_NO_FILE, 1, &msgarg1);
bfb93e ¤   ¤   return 0;¤  /* treat like empty config file */
679371 ¤   }
6baf5a
5ae1fa ¤   buf[sizeof(buf)-1] = '\0';
fd39e0 ¤   while (errors < MAX_ERRORS && configLineGet(f, buf, sizeof(buf))) {
01fee1 ¤   ¤   ++linenum;
1242bb ¤   ¤   msgarg1.type = PGP_UI_ARG_UNSIGNED;
91d0f6 ¤   ¤   msgarg1.val.u = linenum;
cf2ac5 ¤   ¤   msgarg2.type = PGP_UI_ARG_STRING;
d1b419 ¤   ¤   msgarg2.val.s = buf;
98af5a
d42bdb ¤   ¤   /* Line too long? */
30cf90 ¤   ¤   if (buf[sizeof(buf)-1] != '\0') {
7f2c76 ¤   ¤   ¤   buf[sizeof(buf)-1] = '\0';
afa8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
3dcd8f ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_LINE_TOO_LONG, 2,
cfdb21 ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2);
6c64a8 ¤   ¤   ¤   errors++;
6217f5 ¤   ¤   ¤   continue;
120fe4 ¤   ¤   }
8aeaaf ¤   ¤   /* Illegal character? */
0eeee0 ¤   ¤   for (i = 0; buf[i] != '\0'; i++) {
1923eb ¤   ¤   ¤   if (!isprint(buf[i]) && buf[i] != '\t')
6ef622 ¤   ¤   ¤   ¤   break;
340fe4 ¤   ¤   }
03631d ¤   ¤   if (buf[i] != '\0') {
6bf878 ¤   ¤   ¤   msgarg3.type = PGP_UI_ARG_INT;
5843e4 ¤   ¤   ¤   msgarg3.val.i = i;
7da8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
8c6d22 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_BAD_CHAR, 3,
756c71 ¤   ¤   ¤   ¤   ·····&msgarg1, &msgarg2, &msgarg3);
2964a8 ¤   ¤   ¤   errors++;
ae17f5 ¤   ¤   ¤   continue;
ba0fe4 ¤   ¤   }
32ea81 ¤   ¤   if (configLineParse (ui, arg, env, linenum, buf, pri)
0792d5 ¤   ¤   ····< 0)
4164a8 ¤   ¤   ¤   errors++;
e69371 ¤   }
42af5a
4c4acd ¤   fclose (f);
87af5a
609d78 ¤   if (errors > 0) {
0caf5a
86fec2 ¤   ¤   msgarg1.type = PGP_UI_ARG_INT;
7c243b ¤   ¤   msgarg1.val.i = errors;
--fa55 0019be77aec40100282 Page 10 of pgpConf.c
e0af5a
3d5e71 ¤   ¤   if (errors >= MAX_ERRORS)
48a8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
076834 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_MAX_ERRORS, 1, &msgarg1);
100e1d ¤   ¤   else
20a8c6 ¤   ¤   ¤   ui->message (arg, kPGPError_ConfigParseFailure,
e8c3d9 ¤   ¤   ¤   ¤   ·····PGPMSG_CONFIG_NUM_ERRORS, 1, &msgarg1);
e0af5a
8edd48 ¤   ¤   return kPGPError_ConfigParseFailure;
439371 ¤   }
67af5a
6b3e6b ¤   return 0;
9befe6 }
--ed41 00175c1513140100283 Page 1 of pgpConf.h
bc38e5 /*
a1c6ae ·* pgpConf.h - Parse configuration files and lines.
9c775e ·*
2c7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
8e775e ·*
d87618 ·* $Id: pgpConf.h,v 1.9 1997/06/25 19:41:43 lloyd Exp $
af495d ·*/
efaf5a
ac6352 #ifndef Included_pgpConf_h
1d0724 #define Included_pgpConf_h
5faf5a
44c5d5 #include "pgpBase.h"
a4af5a
2f99c6 PGP_BEGIN_C_DECLARATIONS
50af5a
3aadb8 #include "pgpOpaqueStructs.h"
c2af5a
2e1ca1 /* Process a single line */
ef9645 int ·pgpConfigLineProcess (PGPUICb const *ui, void *arg,
4c40fe ¤   ¤   ¤   ·PGPEnv *env, char *option, int pri);
1278fe /* Process a whole file */
221a61 int ·pgpConfigFileProcess (PGPUICb const *ui, void *arg,
73a350 ¤   ¤   ¤   ·PGPEnv *env, char const *filename, int pri);
96af5a
571254 PGP_END_C_DECLARATIONS
fbaf5a
75b42c #endif /* Included_pgpConf_h */
--4c8a 00165098c2d40100284 Page 1 of pgpDecPipe.c
bc38e5 /*
8daa0f ·* pgpDecPipe.c -- setup the Decryption Pipeline, given the arguments
bee100 ·* of the UI. ·This is just a helper function to setup the decryption
77443c ·* pipeline. ·It would be just as easy for an application to do it.
1e775e ·*
197ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
d1775e ·*
49ad37 ·* $Id: pgpDecPipe.c,v 1.5 1997/06/25 19:41:44 lloyd Exp $
82495d ·*/
8daf5a
91e2ff #include "pgpConfig.h"
42af5a
d2feb2 #include <stdio.h>
8baf5a
ced1d7 #include "pgpDecPipe.h"
b6910a #include "pgpFIFO.h"
e4b512 #include "pgpPrsAsc.h"
49b4d8 #include "pgpReadAnn.h"
b7af5a
0b41cd PGPPipeline **
6d106e pgpDecryptPipelineCreate (
f658f9 ¤   PGPContextRef¤  ¤   cdkContext,
330d82 ¤   PGPPipeline **¤ ¤   head,
3e6c5c ¤   PGPEnv *¤   ¤   ¤   env,
5ef138 ¤   PGPFifoDesc const *¤fd,
fa0e11 ¤   PGPUICb const *¤¤   ui,
500ece ¤   void *¤ ¤   ¤   ¤   ui_arg)
bcbb36 {
9cbb3d ¤   if (!head)
887ed2 ¤   ¤   return NULL;
77af5a
68aea9 ¤   if (!fd)
0a438c ¤   ¤   fd = &pgpByteFifoDesc;
acaf5a
a6916d ¤   head = pgpParseAscCreate ( cdkContext, head, env, fd, ui, ui_arg);
08bb3d ¤   if (!head)
8e7ed2 ¤   ¤   return NULL;
d4af5a
338474 ¤   return pgpAnnotationReaderCreate ( cdkContext, head, env, ui, ui_arg);
65efe6 }
--021c 0018b4680de40100285 Page 1 of pgpDecPipe.h
bc38e5 /*
4c4433 ·* pgpDecPipe.h -- Create a Decryption Pipeline
c0775e ·*
e67ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
a5775e ·*
ab8190 ·* This is a Public API Function Header.
28775e ·*
1061ec ·* $Id: pgpDecPipe.h,v 1.9 1997/06/25 19:41:45 lloyd Exp $
2d495d ·*/
31af5a
05ba45 #ifndef Included_pgpDecPipe_h
30ee71 #define Included_pgpDecPipe_h
ceaf5a
d6c5d5 #include "pgpBase.h"
beaf5a
4699c6 PGP_BEGIN_C_DECLARATIONS
94af5a
54adb8 #include "pgpOpaqueStructs.h"
eae82c #include "pgpPubTypes.h"
91af5a
c6f481 PGPPipeline ·**
7f4dfa pgpDecryptPipelineCreate ( PGPContextRef cdkContext,
fad27a ¤   ¤   ¤   PGPPipeline **head,
fbb508 ¤   ¤   ¤   PGPEnv *env, ·PGPFifoDesc const *fd,
4969ff ¤   ¤   ¤   PGPUICb const *ui, void *ui_arg);
94af5a
d31254 PGP_END_C_DECLARATIONS
89af5a
8b2b6f #endif /* Included_pgpDecPipe_h */
--a275 0009153311c40100286 Page 1 of pgpEncPipe.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
259c91 ¤   $Id: pgpEncPipe.c,v 1.43.2.1.2.1 1998/11/12 03:23:28 heller Exp $
fbf7f7 ____________________________________________________________________________*/
3eaf5a
bae2ff #include "pgpConfig.h"
6daf5a
3efeb2 #include <stdio.h>
3e324c #include <string.h>
18af5a
249906 #include "pgpEncPipe.h"
82f476 #include "pgpArmor.h"
440e2f #include "pgpSymmetricCipherPriv.h"
d8d9c5 #include "pgpCiphrMod.h"
8f1e2d #include "pgpCFBPriv.h"
ddc19b #include "pgpCompress.h"
6e55fb #include "pgpCompMod.h"
0c27ba #include "pgpConvKey.h"
799e4d #include "pgpConvMod.h"
40115d #include "pgpDevNull.h"
a79f63 #include "pgpEncode.h"
35910a #include "pgpFIFO.h"
1b9f72 #include "pgpHash.h"
273e66 #include "pgpHeader.h"
890ce3 #include "pgpLiteral.h"
ed0d08 #include "pgpMem.h"
542ece #include "pgpPipeline.h"
b40d6d #include "pgpEnv.h"
978db3 #include "pgpPKEMod.h"
94cdc2 #include "pgpPubKey.h"
8fadc0 #include "pgpRandomPoolPriv.h"
822886 #include "pgpSigMod.h"
74f5ab #include "pgpSigSpec.h"
e727c0 #include "pgpSplit.h"
645579 #include "pgpStr2Key.h"
2c3576 #include "pgpTextFilt.h"
fc0e2f #include "pgpSymmetricCipherPriv.h"
bcc26c #include "pgpContext.h"
bb2c96 #include "pgpRandomX9_17.h"
a2af5a
00014d /* Forward */
ff0d20 static PGPByte * createHashList( PGPContextRef context,
d6d28a ¤   PGPSigSpec const *sigspecs, int *count);
1eaf5a
29af5a
4441cd PGPPipeline **
51b76c pgpEncryptPipelineCreate (
444f5a ¤   PGPContextRef¤  ¤   cdkContext,·
370d82 ¤   PGPPipeline **¤ ¤   head,
a214ad ¤   PGPEnv const *¤ ¤   env,
08f138 ¤   PGPFifoDesc const *¤fd,
406904 ¤   PGPRandomContext const *rng,
efe99b ¤   PGPConvKey *¤   ¤   convkeys,
bcb41c ¤   PGPPubKey *¤¤   ¤   pubkeys,
c10a03 ¤   PGPSigSpec *¤   ¤   sigspecs,
d145fb ¤   PgpLiteralParams *¤ literal,
9566ba ¤   int¤¤   ¤   ¤   ¤   sepsig,
a246e1 ¤   PGPBoolean¤ ¤   ¤   knownBinaryInput,
6e9da4 ¤   int¤¤   ¤   ¤   ¤   (*progress)(void *arg, int c),
c34268 ¤   void *¤ ¤   ¤   ¤   arg,
0f82f0 ¤   PGPError *¤ ¤   ¤   error)
68bb36 {
85a4fc ¤   PGPPipeline **tail = head;
e9557f ¤   PGPPipeline *sighead = NULL, **sigtail = NULL;
2ea9fa ¤   PGPPipeline **texttail = NULL;
266ecb ¤   PGPBoolean clearsig, compress, text, armor, pgpmime;
758e12 ¤   PGPError¤   err = kPGPError_NoErr;
91c5ae ¤   PgpVersion version;
--95dd 00043c4a63940100286 Page 2 of pgpEncPipe.c
65c3f1 ¤   PGPMemoryMgrRef¤memoryMgr¤  = PGPGetContextMemoryMgr( cdkContext );
d0af5a
1fc2f7 ¤   version = pgpenvGetInt (env, PGPENV_VERSION, NULL, &err);
588bba ¤   compress = pgpenvGetInt (env, PGPENV_COMPRESS, NULL, &err);
c65c06 ¤   text = pgpenvGetInt (env, PGPENV_TEXTMODE, NULL, &err) && ! knownBinaryInpu¶
b11ee9 t;
60f7a4 ¤   armor = pgpenvGetInt (env, PGPENV_ARMOR, NULL, &err);
f4af5a
724cf7 ¤   /* Force 1-pass sig packets if encrypting to only non-RSA keys */
e15965 ¤   /* Don't do it if just signing, may be going to PGP 2.6 user */
2d299a ¤   if (version <= PGPVERSION_3) {
43bfa6 ¤   ¤   PGPPubKey *pklist;
263040 ¤   ¤   pklist = pubkeys;
2cd38f ¤   ¤   if (pklist) {
fc50b3 ¤   ¤   ¤   int oldkey = 0;
f7ba62 ¤   ¤   ¤   while (pklist && !oldkey) {
fb6f52 ¤   ¤   ¤   ¤   if ((PGPPublicKeyAlgorithm)pklist->pkAlg <=
ef4490 ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyAlgorithm_RSA + 2)
b672c3 ¤   ¤   ¤   ¤   {
64f7bc ¤   ¤   ¤   ¤   ¤   oldkey = 1;
942613 ¤   ¤   ¤   ¤   }
51f4f2 ¤   ¤   ¤   ¤   pklist = pklist->next;
46a3a6 ¤   ¤   ¤   }
c230e1 ¤   ¤   ¤   if (!oldkey) {
b7980e ¤   ¤   ¤   ¤   /*
730c62 ¤   ¤   ¤   ¤   ·* Upgrade version if all post-RSA.
74844e ¤   ¤   ¤   ¤   ·* An earlier version changed sigspec here, but now setting
ff11cf ¤   ¤   ¤   ¤   ·* version_3 in sigspec makes it use subpacket format, and
1a2436 ¤   ¤   ¤   ¤   ·* that is not accepted in messages by earlier versions of
ac3411 ¤   ¤   ¤   ¤   ·* the library.
c31020 ¤   ¤   ¤   ¤   ·*/
54dd90 ¤   ¤   ¤   ¤   version = PGPVERSION_4;
bca3a6 ¤   ¤   ¤   }
820fe4 ¤   ¤   }
a09371 ¤   }
66af5a
700d46 ¤   /* Use version 3 packets if doing non-2.6 style conventional encryption */
46b331 ¤   if (version <= PGPVERSION_3 && IsntNull( convkeys ) ) {
c287a7 ¤   ¤   PGPByte ciphernum = pgpenvGetInt (env, PGPENV_CIPHER, NULL, NULL);
c1dca0 ¤   ¤   if (ciphernum != kPGPCipherAlgorithm_IDEA ||
566624 ¤   ¤   ¤   ¤   ¤   ¤   IsntNull( convkeys->next ) || IsntNull( pubkeys ) ) {
e718c5 ¤   ¤   ¤   version = PGPVERSION_4;
33cb3c ¤   ¤   } else if (IsntNull( convkeys->stringToKey ) &&
db65a6 ¤   ¤   ¤   ¤   ···!pgpS2KisOldVers (convkeys->stringToKey) ) {
2518c5 ¤   ¤   ¤   version = PGPVERSION_4;
160fe4 ¤   ¤   }
e49371 ¤   }
13af5a
37bb3d ¤   if (!head)
491dec ¤   ¤   goto err;
e9af5a
222b07 ¤   /* Turn off literal and compression for sepsig creation */
56b81f ¤   if (sepsig) {
1de7bd ¤   ¤   compress = 0;
40c03d ¤   ¤   literal = NULL;
e49371 ¤   }
b6af5a
f78d27 ¤   /* disallow separate signatures when we have these other types */
2df42a ¤   if (sepsig &&
13ccfa ¤   ¤   (!sigspecs || compress || literal || convkeys || pubkeys)) {
ac19d3 ¤   ¤   err = kPGPError_BadParams;
b31dec ¤   ¤   goto err;
d49371 ¤   }
91af5a
4c945a ¤   /* This is how we define when to do a clearsigned message */
fafe04 ¤   /* Now allow wrapping clearsigned messages in encryption */
8a3047 ¤   clearsig = (text && sigspecs && armor &&·
6ef46e ¤   ¤   ¤   ¤   pgpenvGetInt (env, PGPENV_CLEARSIG, NULL, &err) && !sepsig);
53af5a
e82525 ¤   pgpmime = pgpenvGetInt (env, PGPENV_PGPMIME, NULL, &err);
d9af5a
43aea9 ¤   if (!fd)
--c151 000b6bd3b3540100286 Page 3 of pgpEncPipe.c
a6af5a ¤   ¤   fd = &pgpFlexFifoDesc;
88af5a
b9d8af ¤   /*
5263f3 ¤   ·* If we can clearsign, then we do something special. ·Do not add
a21a85 ¤   ·* the literal packet type, do not compress, and create a split
a5f314 ¤   ·* for the input data.
aaa4e3 ¤   ·*/
a90b6d ¤   if (clearsig) {
72c03d ¤   ¤   literal = NULL;
6fe7bd ¤   ¤   compress = 0;
b5edaf ¤   ¤   if (!pgpmime) {
fbcf6e ¤   ¤   ¤   ¤   texttail = pgpSplitCreate ( cdkContext, tail);
ca02cc ¤   ¤   ¤   ¤   tail = pgpSplitAdd (*tail);
3b0fe4 ¤   ¤   }
e39371 ¤   }
a0af5a
abcf61 ¤   if (text) {
47fae4 ¤   ¤   PGPByte const *charmap;
dcaf5a
b4cc8f ¤   ¤   if (!literal && !clearsig && !sepsig) {
de5820 ¤   ¤   ¤   err = kPGPError_BadParams;
8c2776 ¤   ¤   ¤   goto err;
110fe4 ¤   ¤   }
7aaf5a
b51b17 ¤   ¤   /*
f54ef7 ¤   ¤   ·* Use the appropriate charmap. ·Stripspaces if we
17677f ¤   ¤   ·* are clearsigning or if it was requested.
823b34 ¤   ¤   ·* Always add CRLF.
339de3 ¤   ¤   ·*/
89318d ¤   ¤   charmap = (PGPByte const *)
b1930a ¤   ¤   ¤   pgpenvGetPointer (env, PGPENV_CHARMAPTOLATIN1, NULL);
cbf348 ¤   ¤   tail = pgpTextFiltCreate ( cdkContext, tail, charmap, clearsig ? 1 : 0,
7a5c9c ¤   ¤   ¤   ¤   ¤   ··kPGPLineEnd_CRLF);
bc9371 ¤   }
8b7f64 ¤   if (sigspecs) {
6dd9c7 ¤   ¤   PGPPipeline **temptail = NULL;
49af5a
97521a ¤   ¤   sigtail = tail;
8d6a87 ¤   ¤   tail = pgpSigCreate( cdkContext, sigtail, version, fd, rng);
f3af5a
0b8382 ¤   ¤   sighead = *sigtail;
f0af5a
dfaf83 ¤   ¤   /* XXX: should I do this? */
0f643b ¤   ¤   temptail = pgpSigSignature (sighead, sigspecs, clearsig);
471669 ¤   ¤   if (temptail)
034d5c ¤   ¤   ¤   sigtail = temptail;
659371 ¤   }
13af5a
850cf9 ¤   if (literal) {
9bd62e ¤   ¤   PGPByte len = 0;
e8af5a
7f4a12 ¤   ¤   if (literal->filename)
a53995 ¤   ¤   ¤   len = strlen (literal->filename);
bf1b52 ¤   ¤
4361ed ¤   ¤   tail = pgpLiteralCreate ( cdkContext, tail, version, fd,
2ff4bf ¤   ¤   ¤   ¤   ¤   ·(PGPByte)(text ? PGP_LITERAL_TEXT
fe6091 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   : PGP_LITERAL_BINARY),
3143fd ¤   ¤   ¤   ¤   ¤   ·(PGPByte *) literal->filename, len,
b6d003 ¤   ¤   ¤   ¤   ¤   ·literal->timestamp);
229371 ¤   }
8daf5a
da7f64 ¤   if (sigspecs) {
0186ab ¤   ¤   if (clearsig || sepsig) {
6115d7 ¤   ¤   ¤   if (!pgpDevNullCreate ( cdkContext, tail))
d984e5 ¤   ¤   ¤   ¤   tail = NULL;
70e543 ¤   ¤   ¤   else {
abcc64 ¤   ¤   ¤   ¤   if (sepsig) {
03a80d ¤   ¤   ¤   ¤   ¤   tail = sigtail;
e6b5fc ¤   ¤   ¤   ¤   } else {
c71919 ¤   ¤   ¤   ¤   ¤   /* create clearsig armor here */
f8371e ¤   ¤   ¤   ¤   ¤   PGPByte *hashlist;
b6f2b7 ¤   ¤   ¤   ¤   ¤   int hashcount;
--28a6 00094e6784840100286 Page 4 of pgpEncPipe.c
92fd66 ¤   ¤   ¤   ¤   ¤   hashlist = createHashList( cdkContext, sigspecs,
4ef69d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··&hashcount);
f1ee65 ¤   ¤   ¤   ¤   ¤   if (pgpmime) {
5a120f ¤   ¤   ¤   ¤   ¤   ¤   tail = pgpArmorWriteCreatePgpMimesig
8ed0db ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (head, sigtail, env,
54e2bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·fd, rng, version, hashlist, hashcount);
6481a1 ¤   ¤   ¤   ¤   ¤   } else {
9539ab ¤   ¤   ¤   ¤   ¤   ¤   tail = pgpArmorWriteCreateClearsig·
d0e642 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (texttail, sigtail, env,
b1e25f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·fd, version, hashlist,
7e43da ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·hashcount);
ae1c89 ¤   ¤   ¤   ¤   ¤   }
24829e ¤   ¤   ¤   ¤   ¤   pgpContextMemFree( cdkContext, hashlist);
c52613 ¤   ¤   ¤   ¤   }
242b85 ¤   ¤   ¤   ¤
6da3a6 ¤   ¤   ¤   }
874a5d ¤   ¤   } else
b7b6ee ¤   ¤   ¤   tail = pgpSigTextInsert (sighead, tail);
4c9371 ¤   }
1aaf5a
733174 ¤   if (compress) {
fe5803 ¤   ¤   PGPByte alg = pgpenvGetInt (env, PGPENV_COMPRESSALG, NULL, NULL);
4cb487 ¤   ¤   int qual = pgpenvGetInt (env, PGPENV_COMPRESSQUAL, NULL, NULL);
b21b52 ¤   ¤
c37a29 ¤   ¤   tail = pgpCompressModCreate ( cdkContext, tail, version, fd, alg, qual);
679371 ¤   }
23af5a
ade7ff ¤   if (convkeys || pubkeys) {
1835ae ¤   ¤   PGPCipherVTBL const *cipher;
6b39db ¤   ¤   PGPCFBContext *cfb;
70d74f ¤   ¤   PGPStringToKey *s2k = NULL;
ad1dbb ¤   ¤   PGPByte iv[IVLEN-2];
5b8d2e ¤   ¤   PGPByte *sessionKey = NULL;
c487a7 ¤   ¤   PGPByte ciphernum = pgpenvGetInt (env, PGPENV_CIPHER, NULL, NULL);
839ba4 ¤   ¤   PGPByte passkey = 0;
ebaf5a
9a7199 ¤   ¤   if (clearsig) {
17f74e ¤   ¤   ¤   /* Insert a literal packet */
e0eba8 ¤   ¤   ¤   tail = pgpLiteralCreate ( cdkContext, tail, version, fd,
f895ea ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGP_LITERAL_TEXT,
0e5cf4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··NULL, 0, 0 );
5d0fe4 ¤   ¤   }
72af5a
09b8df ¤   ¤   /* Default for errors in this section */
22bce1 ¤   ¤   err = kPGPError_OutOfMemory;
97af5a
f55e17 ¤   ¤   sessionKey = (PGPByte *)PGPNewSecureData(
148e01 ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( cdkContext ),
e6d434 ¤   ¤   ¤   ¤   ¤   PGP_CIPHER_MAXKEYSIZE, 0 );
46e708 ¤   ¤   if (!sessionKey)
432776 ¤   ¤   ¤   goto err;
18af5a
0d4842 ¤   ¤   if (!rng)
fee853 ¤   ¤   ¤   rng = pgpContextGetX9_17RandomContext( cdkContext );
e9af5a
dcf943 ¤   ¤   cipher = pgpCipherGetVTBL ( (PGPCipherAlgorithm)ciphernum);
f4db89 ¤   ¤   if (!cipher) {
a21855 ¤   ¤   ¤   PGPFreeData( sessionKey );
742776 ¤   ¤   ¤   goto err;
020fe4 ¤   ¤   }
331b52 ¤   ¤
b2130f ¤   ¤   cfb = pgpCFBCreate ( memoryMgr, cipher);
505dfd ¤   ¤   if (!cfb) {
f41855 ¤   ¤   ¤   PGPFreeData( sessionKey );
ed2776 ¤   ¤   ¤   goto err;
b00fe4 ¤   ¤   }
e187c7 ¤   ¤   ¤
e64583 ¤   ¤   if (convkeys) {
ee7fc2 ¤   ¤   ¤   s2k = pgpS2KdefaultV3 (env, rng);
c39369 ¤   ¤   ¤   if (!s2k) {
1eced8 ¤   ¤   ¤   ¤   PGPFreeCFBContext (cfb);
941619 ¤   ¤   ¤   ¤   PGPFreeData( sessionKey );
--1165 0009e2a507240100286 Page 5 of pgpEncPipe.c
41e0c3 ¤   ¤   ¤   ¤   goto err;
09a3a6 ¤   ¤   ¤   }
c00fe4 ¤   ¤   }
0baf5a
ee3ffb ¤   ¤   /* Generate the key (randomly or not) */
5dedaf ¤   ¤   sessionKey[0] = ciphernum;
8e6e33 ¤   ¤   if (convkeys && !convkeys->next && !pubkeys) {
d2af5a
e66d58 ¤   ¤   ¤   /* Use the pass phrase as the session key */
8d7131 ¤   ¤   ¤   err = pgpStringToKey ((convkeys->stringToKey ?
70416c ¤   ¤   ¤   ¤   ¤   ·······convkeys->stringToKey : s2k),
1f776d ¤   ¤   ¤   ¤   ¤   ······convkeys->pass,
716e62 ¤   ¤   ¤   ¤   ¤   ······convkeys->passlen, sessionKey+1,
9c4988 ¤   ¤   ¤   ¤   ¤   ······cipher->keysize);
ed8832 ¤   ¤   ¤   if (IsPGPError(err)) {
8df6bf ¤   ¤   ¤   ¤   PGPFreeData( sessionKey );¤ ¤   /* Will wipe data */
49ced8 ¤   ¤   ¤   ¤   PGPFreeCFBContext (cfb);
9de0c3 ¤   ¤   ¤   ¤   goto err;
c5a3a6 ¤   ¤   ¤   }
e445a6 ¤   ¤   } else {
e48cee ¤   ¤   ¤   /* Generate a random session key */
bb7499 ¤   ¤   ¤   pgpRandomGetBytes (rng, sessionKey+1, cipher->keysize);
f7e4d5 ¤   ¤   ¤   passkey = 1;
ba0fe4 ¤   ¤   }
d7af5a
d659b0 ¤   ¤   /* Initialize the Cfb */
35fc53 ¤   ¤   PGPInitCFB (cfb, sessionKey+1, NULL);
3faf5a
b5d6d6 ¤   ¤   /* Generate the random IV and create the cipher module */
8021e3 ¤   ¤   pgpRandomGetBytes (rng, iv, sizeof (iv));
91ff5e ¤   ¤   tail = pgpCipherModEncryptCreate ( cdkContext, tail, version, fd,
9bd439 ¤   ¤   ¤   ¤   ¤   ¤   ··cfb, iv, env);
93af5a
9a4583 ¤   ¤   if (convkeys) {
7d0acc ¤   ¤   ¤   tail = pgpConvModCreate ( cdkContext, tail, version, fd, s2k,
94030c ¤   ¤   ¤   ¤   ¤   ¤   ·convkeys,
d9fedc ¤   ¤   ¤   ¤   ¤   ¤   ·ciphernum,
c6a9af ¤   ¤   ¤   ¤   ¤   ¤   ·(passkey ? sessionKey : NULL));
e872a7 ¤   ¤   ¤   pgpS2Kdestroy (s2k);
2c0fe4 ¤   ¤   }
dba798 ¤   ¤   ¤   ¤   ¤   ¤   ··
f00b4e ¤   ¤   if (pubkeys) {
125e7d ¤   ¤   ¤   PGPPipeline **pketail;
d1af5d ¤   ¤   ¤   PGPPubKey const *thiskey;
cae2a3 ¤   ¤   ¤   PGPUInt32¤  ¤   keySize;
bf224b ¤   ¤   ¤   int¤¤   ¤   ¤   encCount = 0;
08af5a
fd4391 ¤   ¤   ¤   /* Save off the tail so we can talk to the PkeMod */
c953de ¤   ¤   ¤   pketail = tail;
40af5a
7b695a ¤   ¤   ¤   keySize¤= pgpCFBGetKeySize( cfb );
1aebcd ¤   ¤   ¤   tail = pgpPkeCreate ( cdkContext,
ab953b ¤   ¤   ¤   ¤   pketail, version, sessionKey, keySize + 1);
31af5a
7642bb ¤   ¤   ¤   if (!tail) {
22f6bf ¤   ¤   ¤   ¤   PGPFreeData( sessionKey );¤ ¤   /* Will wipe data */
f5bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
2ee0c3 ¤   ¤   ¤   ¤   goto err;
22a3a6 ¤   ¤   ¤   }
8baf5a
c64069 ¤   ¤   ¤   for (thiskey = pubkeys; thiskey; thiskey = thiskey->next) {
e436d5 ¤   ¤   ¤   ¤   if (thiskey->encrypt) {
609884 ¤   ¤   ¤   ¤   ¤   err = pgpPkeAddKey (*pketail, thiskey, rng);
9cd50a ¤   ¤   ¤   ¤   ¤   if (IsntPGPError(err) && IsntNull(progress)) {
a9b674 ¤   ¤   ¤   ¤   ¤   ¤   ·err = progress( arg, encCount++ );
191c89 ¤   ¤   ¤   ¤   ¤   }
a7a368 ¤   ¤   ¤   ¤   ¤   if (IsPGPError (err) ) {
b25f33 ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeData( sessionKey );
785e9f ¤   ¤   ¤   ¤   ¤   ¤   goto err;
f31c89 ¤   ¤   ¤   ¤   ¤   }
122613 ¤   ¤   ¤   ¤   }
9ea3a6 ¤   ¤   ¤   }
--7286 00083f06bd640100286 Page 6 of pgpEncPipe.c
b50fe4 ¤   ¤   }
79a6d3 ¤   ¤   PGPFreeData( sessionKey );¤ ¤   /* Will wipe data */
4a9371 ¤   }
20af5a
cf288b ¤   /* Allow clearsig wrapped in encryption */
ae7374 ¤   if (!clearsig || convkeys || pubkeys) {
5ec12f ¤   ¤   tail = pgpHeaderCreate ( cdkContext, tail);
a09371 ¤   }
3daf5a
d8288b ¤   /* Allow clearsig wrapped in encryption */
f51a2c ¤   if (armor && (!clearsig || convkeys || pubkeys)) {
d6cdad ¤   ¤   PGPByte¤¤   armorType = PGP_ARMOR_SEPSIG;
65af5a
e62768 ¤   ¤   switch (sepsig) {
5e75ac ¤   ¤   ¤   case 0:
712e3b ¤   ¤   ¤   ¤   armorType = PGP_ARMOR_NORMAL;
4df622 ¤   ¤   ¤   ¤   break;
2e7aad ¤   ¤   ¤   /*
14bdf2 ¤   ¤   ¤   ·* XXX: This case is a hack until PGP/MIME is properly
903d2d ¤   ¤   ¤   ·* implemented in the library. ·It indicates that the
6c816a ¤   ¤   ¤   ·* separate signature should say "BEGIN PGP MESSAGE"
5dab8a ¤   ¤   ¤   ·* instead of "BEGIN PGP SIGNATURE", so that it can be
6ae1a9 ¤   ¤   ¤   ·* used to form a PGP/MIME clear-signed message.
6c8753 ¤   ¤   ¤   ·*/
9c1713 ¤   ¤   ¤   case PGP_SEPSIGMSG:
f2971c ¤   ¤   ¤   ¤   armorType = PGP_ARMOR_SEPSIGMSG;
31f622 ¤   ¤   ¤   ¤   break;
fcdb68 ¤   ¤   ¤   default:
303719 ¤   ¤   ¤   ¤   armorType = PGP_ARMOR_SEPSIG;
67f622 ¤   ¤   ¤   ¤   break;
d50fe4 ¤   ¤   }
4241fe ¤   ¤   tail = pgpArmorWriteCreate ( cdkContext, tail, env, fd, rng, version,
960f38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   armorType);
d39371 ¤   }
3baf5a
e4b2e1 ¤   if (!tail) {
dbbce1 ¤   ¤   err = kPGPError_OutOfMemory;
691dec ¤   ¤   goto err;
809371 ¤   }
82af5a
734385 ¤   /* Everything is OK */
5d6493 ¤   err = kPGPError_NoErr;
f60161 ¤   if (error)
7491c3 ¤   ¤   *error = err;
4fca79 ¤   return tail;
ceaf5a
13353c err:
597b8a ¤   /* Clean up on error */
2427aa ¤   if (head && *head) {
3fba46 ¤   ¤   (*head)->teardown (*head);
5b4cad ¤   ¤   *head = NULL;
1b9371 ¤   }
b20161 ¤   if (error)
b291c3 ¤   ¤   *error = err;
193f59 ¤   return NULL;
55efe6 }
b8af5a
26af5a
806d1e /* Create a list of hash bytes from a sigspec list, and return the length */
7afbbc static PGPByte *
78524c createHashList(
963163 ¤   PGPContextRef¤  cdkContext,
df0794 ¤   PGPSigSpec const *sigspecs, int *count)
fdbb36 {
d8ae32 ¤   int cnt;
5238f3 ¤   PGPSigSpec const *ss1, *ss2;
b4d423 ¤   PGPByte *list;
6eaf5a
5c833a ¤   cnt = 0;
ce3e6d ¤   /* Count unique hash types */
b0856d ¤   for (ss1=sigspecs; ss1; ss1=pgpSigSpecNext(ss1)) {
8312cf ¤   ¤   for (ss2=sigspecs; ss2!=ss1; ss2=pgpSigSpecNext(ss2)) {
--8628 001a207969940100286 Page 7 of pgpEncPipe.c
68660f ¤   ¤   ¤   if (pgpSigSpecHashtype(ss2)==pgpSigSpecHashtype(ss1))
19f622 ¤   ¤   ¤   ¤   break;
470fe4 ¤   ¤   }
1b099c ¤   ¤   if (ss2==ss1)
9768d5 ¤   ¤   ¤   ++cnt;
519371 ¤   }
96af5a
1bfd42 ¤   /* Allocate list */
69711d ¤   list = (PGPByte *)pgpContextMemAlloc( cdkContext,
17ba8d ¤   ¤   ¤   ¤   cnt, kPGPMemoryMgrFlags_Clear);
329f17 ¤   if (!list) {
16f782 ¤   ¤   *count = 0;
c07ed2 ¤   ¤   return NULL;
659371 ¤   }
08af5a
6bdcad ¤   /* Put unique hash types on list */
cf833a ¤   cnt = 0;
75856d ¤   for (ss1=sigspecs; ss1; ss1=pgpSigSpecNext(ss1)) {
de12cf ¤   ¤   for (ss2=sigspecs; ss2!=ss1; ss2=pgpSigSpecNext(ss2)) {
2f660f ¤   ¤   ¤   if (pgpSigSpecHashtype(ss2)==pgpSigSpecHashtype(ss1))
b9f622 ¤   ¤   ¤   ¤   break;
3e0fe4 ¤   ¤   }
22099c ¤   ¤   if (ss2==ss1)
d02e6c ¤   ¤   ¤   list[cnt++] = pgpSigSpecHashtype(ss1);
aa9371 ¤   }
30b8aa ¤   *count = cnt;
2cafe9 ¤   return list;
a2efe6 }
e5af5a
b038e5 /*
27e6c5 ·* Local Variables:
109b19 ·* tab-width: 4
c7e7a4 ·* End:
41b612 ·* vi: ts=4 sw=4
246c42 ·* vim: si
a2495d ·*/
--62c8 000e9a1515540100287 Page 1 of pgpEncPipe.h
bc38e5 /*
1a8daf ·* pgpEncPipe.h -- setup the Encryption Pipeline, given a set of arguments
c531cf ·* from the UI. ·This will setup a pipeline, or return NULL if there is
b96b9a ·* any error along the way.
b3775e ·*
ca7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
fa775e ·*
1d8190 ·* This is a Public API Function Header.
ad775e ·*
6cced7 ·* $Id: pgpEncPipe.h,v 1.13.22.1 1998/10/06 01:20:50 heller Exp $
8f495d ·*/
48af5a
c93faf #ifndef Included_pgpEncPipe_h
836b9b #define Included_pgpEncPipe_h
81af5a
5dadb8 #include "pgpOpaqueStructs.h"
bfe82c #include "pgpPubTypes.h"
f1af5a
3199c6 PGP_BEGIN_C_DECLARATIONS
3faf5a
f6af5a
8faf5a
cc2162 typedef struct PgpLiteralParams
6ebb36 {
dfe35c ¤   char const *filename;
8ef858 ¤   PGPUInt32¤  timestamp;
39a915 } PgpLiteralParams ;
82af5a
c038e5 /*
fba0fd ·* Create the encryption pipeline. ·This function will use parameters
7dcc08 ·* set in the environment and parameters passed in to determine which
c251e3 ·* filters to create. ·This will perform some limited sanity checking
72c392 ·* on the arguments. ·For example, it is illegal to create a separate
104c96 ·* signature while encrypting.
18775e ·*
d17c1d ·* Pass in a pointer to where the head of the pipeline should go.
ac9037 ·* This function will return you pointer to the tail of the pipeline.
fb775e ·*
a51484 ·* If you pass in needoutput, it will be filled in with 0 or 1, depending
bcaee6 ·* on if the pipeline requires an output module. ·When using multipart
94e281 ·* armor, for example, no output file is required -- the armor module will
148da6 ·* open the appropriate files.
44775e ·*
154f9f ·* Arguments:
16b431 ·*¤ head: The head of the pipeline created.
70955b ·*¤ env: The current PGP Environment
dcf82a ·*¤ fd: The Fifo Descriptor to use for buffering
cbf6f4 ·*¤ rng: The Random Number Generator to use for padding and randomness
b0e76d ·*¤ convkeys: The list of Conventional Keys to use for conventional
bb4d75 ·*¤ ¤   encryption (encrypting with a passphrase)
28a572 ·*¤ pubkeys: The list of Public Keys to use for public key encryption.
4ef9c2 ·*¤ sigspecs: The list of Signature Specifications to use for making
b23153 ·*¤ ¤   signatures.
0b8fa6 ·*¤ literal: should this be processed as a literal packet, or is it
9413e4 ·*¤ ¤   a PGP message or a clearsigned message, or a separate
29edce ·*¤ ¤   signature? ·This includes the input filename to be included
5285ae ·*¤ ¤   in the literal packet, and other literal information.
98a413 ·*¤ sepsig: perform a separate signature. ·Only valid with a few other
cf8e6f ·*¤ ¤   options. ·If the special value PGP_SEPSIGMSG is passed,·
2dd7e6 ·*¤ ¤   separate signature will say "BEGIN PGP MESSAGE" instead of
3e4f8c ·*¤ ¤   "BEGIN PGP SIGNATURE", so that it can be used to form a PGP/MIME
0563f1 ·*¤ ¤   clear-signed message. ·XXX: This is a hack until PGP/MIME is
5bf802 ·*¤ ¤   properly implemented in the library.
6f495d ·*/
0bf481 PGPPipeline ·**
47b76c pgpEncryptPipelineCreate (
2b196c ¤   ¤   ¤   ¤   PGPContextRef cdkContext,
015986 ¤   ¤   ¤   ¤   PGPPipeline **head,
264c12 ¤   ¤   ¤   ¤   PGPEnv const *env,
1925bd ¤   ¤   ¤   ¤   PGPFifoDesc const *fd,
135739 ¤   ¤   ¤   ¤   PGPRandomContext const *rng,
e90479 ¤   ¤   ¤   ¤   PGPConvKey *convkeys,
--77a3 0010d34a55140100287 Page 2 of pgpEncPipe.h
5e1f79 ¤   ¤   ¤   ¤   PGPPubKey *pubkeys,
ff47a0 ¤   ¤   ¤   ¤   PGPSigSpec *sigspecs,
a918b4 ¤   ¤   ¤   ¤   PgpLiteralParams *literal,
46abe7 ¤   ¤   ¤   ¤   int sepsig,
aa82af ¤   ¤   ¤   ¤   PGPBoolean knownBinaryInput,
9391f7 ¤   ¤   ¤   ¤   int (*progress)(void *arg, int c),
47eda4 ¤   ¤   ¤   ¤   void *arg,
937960 ¤   ¤   ¤   ¤   PGPError *error);
f4af5a
78990b #define PGP_SEPSIGMSG¤  7361
edaf5a
b81254 PGP_END_C_DECLARATIONS
49af5a
0da3c0 #endif /* Included_pgpEncPipe_h */
--3b31 000d3110e7e40100288 Page 1 of pgpEnv.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
2b4f94 ·* pgpEnv.c -- Handle PGP Environments. ·This contains much of the
b3ad33 ·* "global" PGP environment code. ·This contains the information that
ca6bc3 ·* is obtains from the configuration file or command-line or some
d7d2ff ·* other means. ·It defines the environment in which it operates. ·It
8cfd6a ·* is possible to have multiple threads operating in the same
626d42 ·* environment, but in general each thread would have its own
9e921a ·* environment. ·For example, a PGP Server would have one of these
5aefee ·* for each client.
f5af5a
9696a3 ¤   $Id: pgpEnv.c,v 1.48.10.1 1998/11/12 03:23:28 heller Exp $
3ef7f7 ____________________________________________________________________________*/
daaf5a
0aaf5a
dae2ff #include "pgpConfig.h"
9baf5a
a3feb2 #include <stdio.h>
5212ef #include <string.h>¤
0faf5a
a6a12d #include "pgpCharMap.h"¤¤   /* for pgpCharmaps() */
65c6c6 #include "pgpSymmetricCipher.h"¤¤   /* for kPGPCipherAlgorithm_IDEA */
e92dce #include "pgpCompress.h"¤   /* for PGP_COMPRESSALG_ZIP */
5c9587 #include "pgpHash.h"¤   ¤   /* for kPGPHashAlgorithm_MD5 */
3b0d08 #include "pgpMem.h"
052f8d #include "pgpErrors.h"
a90d6d #include "pgpEnv.h"
f5c26c #include "pgpContext.h"
22894b #include "pgpFileSpec.h"
a2af5a
878ef2 typedef struct Conf
56bb36 {
a6f20a ¤   union
6ac7a1 ¤   {
196afc ¤   ¤   int¤¤   num;
6ba704 ¤   ¤   char *¤ string;
828f51 ¤   } val;
e39022 ¤   int¤¤   ¤   pri;
888da6 } Conf;
92af5a
bc8638 struct PGPEnv
c2bb36 {
dbb9cc ¤   Conf ¤  confInt[ PGPENV_MAX_INT- PGPENV_BASE_INT ];
4570fc ¤   Conf ¤  confString[PGPENV_MAX_STRING-
48b294 ¤   ¤   ¤   ¤   ¤   ¤   PGPENV_BASE_STRING];
9cc3ac ¤   void *¤ ¤   ¤   pointers[PGPENV_MAX_POINTER -
1fd758 ¤   ¤   ¤   ¤   ¤   ¤   PGPENV_BASE_POINTER];
d5e9e3 ¤   size_t¤ ¤   ¤   pointerSize[PGPENV_MAX_POINTER -
14d758 ¤   ¤   ¤   ¤   ¤   ¤   PGPENV_BASE_POINTER];
5167c5 ¤
8d8a97 ¤   PGPContextRef¤  context;
942fa1 } ;
13af5a
7a21ab ¤   PGPError·
0823f5 pgpenvCreate(
e2520e ¤   PGPContextRef¤  context,
72b6ab ¤   PGPEnv **¤  ¤   outEnv)
d6bb36 {
4a89c5 ¤   PGPEnv *¤   env¤= NULL;
5d26d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
23af5a
9f11be ¤   pgpAssertAddrValid( outEnv, PGPEnv * );
4267c5 ¤
153159 ¤   *outEnv¤= NULL;
ba67c5 ¤
436617 ¤   env = (PGPEnv *)pgpContextMemAlloc( context, sizeof(*env),
d0f048 ¤   ¤   kPGPMemoryMgrFlags_Clear);
d7077d ¤   if ( IsntNull( env ) )
d3c7a1 ¤   {
--2ceb 000c5ae1fe140100288 Page 2 of pgpEnv.c
b5d20f ¤   ¤   env->context¤   = context;
acaf5a
d550b9 ¤   ¤   /* Now initialize the environment pointers as appropriate */
7e49a0 ¤   ¤   pgpenvSetInt (env, PGPENV_CIPHER, kPGPCipherAlgorithm_IDEA,
cac34c ¤   ¤   ¤   ······PGPENV_PRI_PUBDEFAULT);
ea93df ¤   ¤   pgpenvSetInt (env, PGPENV_HASH, kPGPHashAlgorithm_MD5,
1ff36e ¤   ¤   ¤   ¤   ¤   ¤   PGPENV_PRI_PUBDEFAULT);
03bcdd ¤   ¤   pgpenvSetInt (env, PGPENV_COMPRESS, 1, PGPENV_PRI_PUBDEFAULT);
67c414 ¤   ¤   pgpenvSetInt (env, PGPENV_COMPRESSALG, PGP_COMPRESSALG_ZIP,
5bc34c ¤   ¤   ¤   ······PGPENV_PRI_PUBDEFAULT);
a8319e ¤   ¤   pgpenvSetInt (env, PGPENV_COMPRESSQUAL, 5, PGPENV_PRI_PUBDEFAULT);
8dd686 ¤   ¤   pgpenvSetInt (env, PGPENV_ARMORLINES, 0, PGPENV_PRI_PUBDEFAULT);
87ddfb ¤   ¤   pgpenvSetInt (env, PGPENV_CERTDEPTH, 4, PGPENV_PRI_PUBDEFAULT);
ed33a8 ¤   ¤   pgpenvSetInt (env, PGPENV_COMPLETES, 1, PGPENV_PRI_PUBDEFAULT);
26ac55 ¤   ¤   pgpenvSetInt (env, PGPENV_MARGINALS, 2, PGPENV_PRI_PUBDEFAULT);
20fa24 ¤   ¤   pgpenvSetInt (env, PGPENV_TRUSTED, 120, PGPENV_PRI_PUBDEFAULT);
8e0c6a ¤   ¤   pgpenvSetInt (env, PGPENV_CLEARSIG, 1, PGPENV_PRI_PUBDEFAULT);
314135 ¤   ¤   pgpenvSetInt (env, PGPENV_VERSION, PGPVERSION_3,
85c34c ¤   ¤   ¤   ······PGPENV_PRI_PUBDEFAULT);
c1af5a
c6e215 ¤   ¤   pgpenvSetString (env, PGPENV_PGPPATH, "", PGPENV_PRI_PUBDEFAULT);
4f49d2 ¤   ¤   pgpenvSetString (env, PGPENV_UPATH,·
2e2bf7 ¤   ¤   ¤   ¤   ·"/home/ch/keyserver", PGPENV_PRI_PUBDEFAULT);
cdaf5a
8585fb ¤   #ifdef MSDOS
b33f3f ¤   ¤   pgpenvSetString (env, PGPENV_CHARSET, "cp850", PGPENV_PRI_PUBDEFAULT);
bd47b4 ¤   #else
c822f4 ¤   ¤   pgpenvSetString (env, PGPENV_CHARSET, "noconv", PGPENV_PRI_PUBDEFAULT);
e0b7ec ¤   #endif
349371 ¤   }
a60e24 ¤   else
a5c7a1 ¤   {
d817a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
b69371 ¤   }
4f67c5 ¤
ff19b2 ¤   *outEnv¤= env;
a75ea8 ¤   return err;
9befe6 }
c6af5a
ccd8f8 ¤   PGPContextRef
2c78ca pgpenvGetContext( PGPEnv const *env )
09bb36 {
f33154 ¤   return( env->context );
06efe6 }
35af5a
25af5a
bdaf5a
7838e5 /*
8ee505 ·* Copy an environment. ·WARNING: Although the strings will be copied,
949193 ·* the "pointers" will not. ·Take care when destroying an environment;
eeea4f ·* you can only destroy the pointers from the first one. ·Since the
d801c5 ·* environment doesn't do this on its own, this is not a problem for
906a2e ·* this code.
f5495d ·*/
e821ab ¤   PGPError·
e73086 pgpenvCopy (
02ff68 ¤   PGPEnv const *¤ env,
302170 ¤   PGPEnv **¤  ¤   outEnv )
9bbb36 {
44eda7 ¤   PGPEnv *¤   ¤   ¤   tmp¤= NULL;
217925 ¤   PGPContextRef¤  ¤   context;
b5870b ¤   char const *¤   ¤   s;
ce16b2 ¤   char *¤ ¤   ¤   ¤   s2;
0fc088 ¤   int¤¤   ¤   ·¤  ¤   i;
6bd591 ¤   PGPError¤   ¤   ¤   err¤= kPGPError_NoErr;
aa04c6 ¤   PGPBoolean¤ ¤   ¤   allocationFailure¤  = FALSE;
04af5a
3623ce ¤   pgpAssertAddrValid( env, PGPEnv );
3aaf5a
fc23ce ¤   pgpAssertAddrValid( env, PGPEnv );
2511be ¤   pgpAssertAddrValid( outEnv, PGPEnv * );
c567c5 ¤
--7114 0007040fc0b40100288 Page 3 of pgpEnv.c
033159 ¤   *outEnv¤= NULL;
acfeff ¤   context¤= env->context;
cfaf5a
99af58 ¤   /* Create the new env */
c8c7cc ¤   tmp = (PGPEnv *)pgpContextMemAlloc ( context,
44c1ce ¤   ¤   ¤   sizeof (*tmp), 0 );
b06d2e ¤   if ( IsntNull( tmp ) )
6dc7a1 ¤   {
cdd786 ¤   ¤   /* Clone the old env */
4a6617 ¤   ¤   pgpCopyMemory( env, tmp, sizeof(*env) );
d4af5a
dbdbed ¤   ¤   /* Alloc and copy the strings */
a7cc45 ¤   ¤   for (i=0; i < PGPENV_MAX_STRING-PGPENV_BASE_STRING; i++)
ac5b34 ¤   ¤   {
399fb2 ¤   ¤   ¤   s = tmp->confString[i].val.string;
6fdd72 ¤   ¤   ¤   if ( IsntNull( s ) )
97f776 ¤   ¤   ¤   {
1674d9 ¤   ¤   ¤   ¤   s2 = (char *)pgpContextMemAlloc( context, strlen (s) + 1,
fce985 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·0);
0467c5 ¤   ¤   ¤   ¤   if ( IsntNull( s2 ) )
4272c3 ¤   ¤   ¤   ¤   {
777ab6 ¤   ¤   ¤   ¤   ¤   pgpCopyMemory( s, s2, strlen (s) + 1);
be2613 ¤   ¤   ¤   ¤   }
17fa07 ¤   ¤   ¤   ¤   else
c872c3 ¤   ¤   ¤   ¤   {
a7a3e7 ¤   ¤   ¤   ¤   ¤   /*
1a01be ¤   ¤   ¤   ¤   ¤   ·* if we fail, continue loop to fully clear or form
df57e9 ¤   ¤   ¤   ¤   ¤   ·* duplicate so we can dispose of the whole thing later
9de4e2 ¤   ¤   ¤   ¤   ¤   */
891e1a ¤   ¤   ¤   ¤   ¤   allocationFailure¤  = TRUE;
a5466f ¤   ¤   ¤   ¤   ¤   err¤= kPGPError_OutOfMemory;
972613 ¤   ¤   ¤   ¤   }
18af5a
e83418 ¤   ¤   ¤   ¤   tmp->confString[i].val.string = s2;
e8a3a6 ¤   ¤   ¤   }
690fe4 ¤   ¤   }
019371 ¤   }
ab0e24 ¤   else
1dc7a1 ¤   {
c317a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
4e9371 ¤   }
ba67c5 ¤
869733 ¤   /* return an error if we couldn't fully form the environment */
f98c29 ¤   if ( allocationFailure )
fec7a1 ¤   {
59711c ¤   ¤   pgpenvDestroy( tmp );
8bd95e ¤   ¤   tmp¤= NULL;
1217a7 ¤   ¤   err¤= kPGPError_OutOfMemory;
f79371 ¤   }
4867c5 ¤
9855a2 ¤   *outEnv¤= tmp;
5d5ea8 ¤   return err;
34efe6 }
3daf5a
93af5a
7f6d52 ¤   void
20bd6a pgpenvDestroy (PGPEnv *env)
06bb36 {
f1e595 ¤   int¤¤   i;
f57925 ¤   PGPContextRef¤  ¤   context;
c8af5a
6823ce ¤   pgpAssertAddrValid( env, PGPEnv );
1dfeff ¤   context¤= env->context;
7a67c5 ¤
6a23ce ¤   pgpAssertAddrValid( env, PGPEnv );
75af5a
0e6120 ¤   /* De-allocate all the string variables */
e3166c ¤   for (i=0; i < PGPENV_MAX_STRING-PGPENV_BASE_STRING; i++)
a9c7a1 ¤   {
de0cf5 ¤   ¤   char *¤ s;
1a9f03 ¤   ¤   s = env->confString[i].val.string;
70e622 ¤   ¤   if (s)
--b8e6 000b3f82c9640100288 Page 4 of pgpEnv.c
e35b34 ¤   ¤   {
32a90a ¤   ¤   ¤   pgpClearMemory( s, ·strlen (s));
f0b7eb ¤   ¤   ¤   pgpContextMemFree( context, s);
760fe4 ¤   ¤   }
799371 ¤   }
1267c5 ¤
6baf5a
44eaf0 ¤   pgpClearMemory( env, ·sizeof (*env));
180798 ¤   pgpContextMemFree ( context, env);
a2efe6 }
72af5a
3638e5 /*
6910c3 ·* Set an Integer Value for the environment variable var in the
3a2130 ·* environment env to num with priority pri.
9e495d ·*/
28c744 ¤   PGPError
02482e pgpenvSetInt (
bfd1be ¤   PGPEnv *¤   env,
8a0833 ¤   PgpEnvInts¤ var,
c01339 ¤   PGPInt32¤   num,
dd8c39 ¤   PGPInt32¤   pri)
b1bb36 {
029b97 ¤   int idx;
3967c5 ¤
e923ce ¤   pgpAssertAddrValid( env, PGPEnv );
daaf5a
edf9c9 ¤   if (var < PGPENV_BASE_INT || var >= PGPENV_MAX_INT)
5462b5 ¤   ¤   return kPGPError_BadParams;
a9af5a
eeb6ac ¤   idx = (int)var - PGPENV_BASE_INT;
04af5a
4a8311 ¤   if (pri < env->confInt[idx].pri)
4663db ¤   ¤   return kPGPError_EnvPriorityTooLow;
f7af5a
6e69ec ¤   env->confInt[idx].val.num = num;
1d7e46 ¤   env->confInt[idx].pri = pri;
3e151e ¤   return kPGPError_NoErr;
41efe6 }
19af5a
e966dd ¤   static PGPError
61b72f DoSetString (
7bb46f ¤   PGPEnv *¤   ¤   env,
2a1df9 ¤   PgpEnvStrings¤  var,
f3a42e ¤   char const *¤   string,
b7eb5b ¤   PGPInt32 ¤  ¤   pri)
44bb36 {
d026d5 ¤   PGPError¤   err¤= kPGPError_NoErr;
3caf5a
3f23ce ¤   pgpAssertAddrValid( env, PGPEnv );
7f67c5 ¤
b7d094 ¤   var = (PgpEnvStrings) ( (PGPUInt32)var - (PGPUInt32)PGPENV_BASE_STRING );
08b3eb ¤   if (string)
fcc7a1 ¤   {
1eeeef ¤   ¤   if( IsNull( env->confString[var].val.string ) ) {
627f95 ¤   ¤   ¤   env->confString[var].val.string = (char *)
946444 ¤   ¤   ¤   ··pgpContextMemAlloc( env->context, strlen(string) + 1,
7b871e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··0);
aa1818 ¤   ¤   ¤   if( IsNull( env->confString[var].val.string ) )
73bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
1245a6 ¤   ¤   } else {
2eb45b ¤   ¤   ¤   err = pgpContextMemRealloc( env->context,
2e0b24 ¤   ¤   ¤   ¤   ¤   ¤   ·(void **)&env->confString[var].val.string,
e2dcda ¤   ¤   ¤   ¤   ¤   ¤   ·strlen(string) + 1,
2f6d68 ¤   ¤   ¤   ¤   ¤   ¤   ·0);
2f87c7 ¤   ¤   ¤
fe0fe4 ¤   ¤   }
88be18 ¤   ¤   if ( IsPGPError( err ) )
bbb32f ¤   ¤   ¤   return err;
e5af5a
0dd4ca ¤   ¤   strcpy (env->confString[var].val.string, string);
6f9371 ¤   }
b30e24 ¤   else
--a4f2 0005496782240100288 Page 5 of pgpEnv.c
f7c7a1 ¤   {
ac791d ¤   ¤   if (env->confString[var].val.string)
ac24ec ¤   ¤   ¤   pgpContextMemFree( env->context, env->confString[var].val.string);
57730c ¤   ¤   env->confString[var].val.string = NULL;
579371 ¤   }
e1af5a
1e98da ¤   env->confString[var].pri = pri;
48151e ¤   return kPGPError_NoErr;
32efe6 }
86af5a
1766dd ¤   static PGPError
9e549c SetPointer (PGPEnv *env, unsigned var, void *ptr, size_t size)
8ebb36 {
0423ce ¤   pgpAssertAddrValid( env, PGPEnv );
0467c5 ¤
a2c43f ¤   var -= PGPENV_BASE_POINTER;
11bec8 ¤   env->pointers[var] = ptr;
3afec2 ¤   env->pointerSize[var] = size;
79151e ¤   return kPGPError_NoErr;
94efe6 }
b4af5a
da38e5 /*
a864e7 ·* Set a String Value for the environment variable var in the
5eec65 ·* environment env to string with priority pri. ·Space is allocated
81009f ·* for the string.
a2775e ·*
13b898 ·* If the string is null, free the old string (if one existed) and
6d78a7 ·* then set the placeholder to NULL.
bf495d ·*/
d0c744 ¤   PGPError
fc758b pgpenvSetString (PGPEnv *env, PgpEnvStrings var,
6617d7 ¤   ¤   ·char const *string, int pri)
c8bb36 {
e4c55b ¤   PGPError err = kPGPError_NoErr;
83af5a
e723ce ¤   pgpAssertAddrValid( env, PGPEnv );
78337e ¤   if ( env == NULL )
ef62b5 ¤   ¤   return kPGPError_BadParams;
15af5a
a03306 ¤   if (var < PGPENV_BASE_STRING || var >= PGPENV_MAX_STRING)
2462b5 ¤   ¤   return kPGPError_BadParams;
b3af5a
395ff7 ¤   if (pri < env->confString[var-PGPENV_BASE_STRING].pri)
2ff94c ¤   ¤   return kPGPError_EnvPriorityTooLow;¤/* not assigned */
b6af5a
8db26b ¤   switch (var) {
3d00de ¤   case PGPENV_CHARSET:
b65b34 ¤   ¤   {
2602a4 ¤   ¤   ¤   PGPByte const *toLocal, *toLatin1;
2daf5a
08d538 ¤   ¤   ¤   err = pgpCharmaps (string, strlen (string), &toLocal,
18911e ¤   ¤   ¤   ¤   ¤   ···&toLatin1);
799998 ¤   ¤   ¤   if (!err) {
ed0267 ¤   ¤   ¤   ¤   DoSetString (env, PGPENV_CHARSET, string, pri);
ceac28 ¤   ¤   ¤   ¤   SetPointer (env, PGPENV_CHARMAPTOLOCAL,
0d2c8c ¤   ¤   ¤   ¤   ¤   ····(void *)toLocal, 256);
fcb4a3 ¤   ¤   ¤   ¤   SetPointer (env, PGPENV_CHARMAPTOLATIN1,
3c0674 ¤   ¤   ¤   ¤   ¤   ····(void *)toLatin1, 256);
4aa3a6 ¤   ¤   ¤   }
f70fe4 ¤   ¤   }
dd2f68 ¤   ¤   break;
b32f72 ¤   default:
2187e8 ¤   ¤   err = DoSetString (env, var, string, pri);
879371 ¤   }
40af5a
f75ea8 ¤   return err;
bfefe6 }
8faf5a
f038e5 /*
b95033 ·* Set a Pointer Value for the environment variable var in the
158982 ·* environment env to the Pointer passed in
54495d ·*/
--87ca 0000d59201340100288 Page 6 of pgpEnv.c
d3c744 ¤   PGPError
8903fd pgpenvSetPointer (
68b46f ¤   PGPEnv *¤   ¤   env,
5b77aa ¤   PgpEnvPointers¤ var,
adf419 ¤   void *¤ ¤   ¤   ptr,
054758 ¤   size_t¤ ¤   ¤   size)
d0bb36 {
0f23ce ¤   pgpAssertAddrValid( env, PGPEnv );
f4af5a
b1ed50 ¤   if (var < PGPENV_BASE_POINTER || var >= PGPENV_MAX_POINTER)
2662b5 ¤   ¤   return kPGPError_BadParams;
1faf5a
f26382 ¤   if (var == PGPENV_CHARMAPTOLOCAL || var == PGPENV_CHARMAPTOLATIN1)
5562b5 ¤   ¤   return kPGPError_BadParams;
3eaf5a
26fca6 ¤   return SetPointer (env, var, ptr, size);
29efe6 }
86af5a
9d1e7c ¤   PGPInt32
4725f7 pgpenvGetInt (PGPEnv const *env, PgpEnvInts var, PGPInt32 *pri,
4ac7c4 ¤   ······PGPError *error)
9fbb36 {
2dc55b ¤   PGPError err = kPGPError_NoErr;
244266 ¤   int val = 0;
849b97 ¤   int idx;
0aaf5a
bd9622 ¤   if (!env)
09c7a1 ¤   {
c219d3 ¤   ¤   err = kPGPError_BadParams;
3ab09a ¤   ¤   goto getint_end;
0e9371 ¤   }
50af5a
f8f9c9 ¤   if (var < PGPENV_BASE_INT || var >= PGPENV_MAX_INT)
f8c7a1 ¤   {
0819d3 ¤   ¤   err = kPGPError_BadParams;
38b09a ¤   ¤   goto getint_end;
909371 ¤   }
34af5a
4cb6ac ¤   idx = (int)var - PGPENV_BASE_INT;
2aaf5a
dc9ebd ¤   if (pri)
5ef279 ¤   ¤   *pri = env->confInt[idx].pri;
7baf5a
582474 ¤   val = ·env->confInt[idx].val.num;
73af5a
0285c4 ·getint_end:
135f91 ¤   if ( error != NULL )
1191c3 ¤   ¤   *error = err;
c0af5a
4884c6 ¤   return val;
40efe6 }
eeaf5a
87e164 ¤   const char ·*
909af5 pgpenvGetCString(
65ff68 ¤   PGPEnv const *¤ env,
bf1df9 ¤   PgpEnvStrings¤  var,
78251a ¤   int *¤  ¤   ¤   pri)
91bb36 {
0249d3 ¤   char const *¤   s ¤ = NULL;
10ede8 ¤   int¤¤   ¤   ¤   idx;
ceaf5a
b523ce ¤   pgpAssertAddrValid( env, PGPEnv );
ee7ab2 ¤   pgpAssert( var >= PGPENV_BASE_STRING || var < PGPENV_MAX_STRING );
2267c5 ¤
42ed06 ¤   idx = (int)var - PGPENV_BASE_STRING;
feaf5a
259ebd ¤   if (pri)
c673f2 ¤   ¤   *pri = env->confString[idx].pri;
3daf5a
49b1a1 ¤   s¤  = env->confString[idx].val.string;
e4af5a
0dd779 ¤   return s;
--32a6 00148468a9240100288 Page 7 of pgpEnv.c
7aefe6 }
46af5a
8eaf5a
79af5a
86c7d5 ¤   void ·*
a74f99 pgpenvGetPointer (
cfff68 ¤   PGPEnv const *¤ env,
9877aa ¤   PgpEnvPointers¤ var,
0f8a09 ¤   size_t *¤   ¤   size)
45bb36 {
098ab7 ¤   void *ptr = NULL;
487899 ¤   int¤¤   idx;
4caf5a
3e23ce ¤   pgpAssertAddrValid( env, PGPEnv );
123cbf ¤   pgpAssert( var >= PGPENV_BASE_POINTER && var < PGPENV_MAX_POINTER );
5567c5 ¤
8cc8bf ¤   idx = (int)var - PGPENV_BASE_POINTER;
1267c5 ¤
f47299 ¤   if (size)
7d89d3 ¤   ¤   *size = env->pointerSize[idx];
b9af5a
864be2 ¤   ptr = env->pointers[idx];
95af5a
678726 ¤   return ptr;
44efe6 }
b1af5a
68af5a
f4af5a
48af5a
--f8fe 0006b8d7eb840100289 Page 1 of pgpEnv.h
bc38e5 /*
478f76 ·* pgpEnv.h -- The PGPlib Environment.
d7775e ·*
15959b ·* Keep track of what used to be "global" state; these values are valid
60e5da ·* only within a working environment. ·Multiple environments can co-exist
4ee91a ·* within a single application, however each one would have its own unique
87467e ·* environment structure and should pass it on to its children.
09775e ·*
879d09 ·* The main purpose of this structure is to gather together a lot of
15985b ·* little fiddly things that a user might want to adjust into a single
3c9238 ·* variable so code that doesn't want to fiddle with them doesn't have to
14e637 ·* think about the issue. ·It makes passing a different value of an
53ce62 ·* environment variable to a function more awkward (you have to
13cc45 ·* copy a parent environment and set the value(s) of interest), but
ea31be ·* it's quite possible if you want more detailed control.
35775e ·*
63191a ·* The big win is that to add an extra control parameter to a function
c91f62 ·* that already gets some parameters from an environment, you can just
0d0ef2 ·* add it to the environment and change the function to get its parmaeter
84259f ·* from the environment and all of the code in between can just be
ac3619 ·* relinked.
07775e ·*
b07ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
ae775e ·*
e78190 ·* This is a Public API Function Header.
4d775e ·*
fc1fda ·* $Id: pgpEnv.h,v 1.25 1997/08/25 20:24:23 lloyd Exp $
85495d ·*/
f9af5a
eec0a3 #ifndef Included_pgpEnv_h
6b88b4 #define Included_pgpEnv_h
13af5a
a4c5d5 #include "pgpBase.h"
d7e82c #include "pgpPubTypes.h"
40af5a
0299c6 PGP_BEGIN_C_DECLARATIONS
35af5a
d2adb8 #include "pgpOpaqueStructs.h"
35af5a
a284c3 #define PGPENV_BASE_INT¤1000
4e75df enum PgpEnvInts_
24bb36 {
60a6f2 ¤   PGPENV_ARMOR¤   = PGPENV_BASE_INT,
c39d13 ¤   PGPENV_ARMORLINES,
c60035 ¤   PGPENV_CERTDEPTH,
9bbf2c ¤   PGPENV_CIPHER,
784681 ¤   PGPENV_CLEARSIG,
b7cee5 ¤   PGPENV_COMPLETES,
6be105 ¤   PGPENV_COMPRESS,
0ae6ac ¤   PGPENV_COMPRESSALG,
ad5e7a ¤   PGPENV_COMPRESSQUAL,
18f929 ¤   PGPENV_ENCRYPTTOSELF,
7ba194 ¤   PGPENV_HASH,
771ef8 ¤   PGPENV_MARGINALS,
483384 ¤   PGPENV_SHOWPASS,
4944a0 ¤   PGPENV_TEXTMODE,
18ae37 ¤   PGPENV_TRUSTED,
2a0c65 ¤   PGPENV_TZFIX,
aa5273 ¤   PGPENV_VERBOSE,
b55243 ¤   PGPENV_VERSION,
14f4f1 ¤   PGPENV_BATCHMODE,
a0e734 ¤   PGPENV_FORCE,
d03077 ¤   PGPENV_MAGIC,
79a69e ¤   PGPENV_NOOUT,
85a14a ¤   PGPENV_PGPMIME,
32c548 ¤   PGPENV_MAILWORDWRAPENABLE,
86f92d ¤   PGPENV_MAILWORDWRAPWIDTH,
db9996 ¤   PGPENV_MAILPASSCACHEENABLE,
98af52 ¤   PGPENV_MAILPASSCACHEDURATION,
686d16 ¤   PGPENV_MAILENCRYPTPGPMIME,
b43975 ¤   PGPENV_MAILSIGNPGPMIME,
6b4af1 ¤   PGPENV_FASTKEYGEN,
--b459 00067fd91f140100289 Page 2 of pgpEnv.h
f5ac52 ¤   PGPENV_SIGNCACHEENABLE,
c664b6 ¤   PGPENV_SIGNCACHEDURATION,
167291 ¤   PGPENV_WARNONMIXRSAELGAMAL,
787a7a ¤   PGPENV_MAILENCRYPTDEFAULT,
822e19 ¤   PGPENV_MAILSIGNDEFAULT,
2ca319 ¤   PGPENV_DATEOFLASTSPLASHSCREEN,
9cb7e9 ¤   PGPENV_MARGINALLYVALIDWARNING,
12f037 ¤   PGPENV_PGPMIMEPARSEBODY,
8d2eb1 ¤   PGPENV_FIRSTKEYGENERATED,
f1054e ¤   PGPENV_HTTPKEYSERVERPORT,
4c3a80 ¤   PGPENV_WARNONRSARECIPANDNONRSASIGNER,
242d68 ¤   PGPENV_PGPMIMEVERSIONLINE,
082033 ¤   PGPENV_MAX_INT,
8367c5 ¤
e939a4 ¤   PGP_ENUM_FORCE( PgpEnvInts_ )
b582f7 };
c47ab4 PGPENUM_TYPEDEF( PgpEnvInts_, PgpEnvInts );
27af5a
9eaf5a
ba60ff #define PGPENV_BASE_STRING¤ 2000
3243ef enum PgpEnvStrings_
75bb36 {
b014e0 ¤   PGPENV_BAKRING¤ = PGPENV_BASE_STRING,
45ae37 ¤   PGPENV_CHARSET,
bdb357 ¤   PGPENV_COMMENT,
9bc1b2 ¤   PGPENV_COMPANYKEY,
11668e ¤   PGPENV_RANDOMDEVICE,
f1bccd ¤   PGPENV_LANGUAGE,
18fcd6 ¤   PGPENV_MYNAME,
a449b8 ¤   PGPENV_PGPPATH,
c04ab0 ¤   PGPENV_PUBRINGnolongerused,
e5cbcc ¤   PGPENV_RANDSEEDnolongerused,
061df0 ¤   PGPENV_SECRINGnolongerused,
68bde4 ¤   PGPENV_SYSDIR,
b943cf ¤   PGPENV_TMP,
0a47d9 ¤   PGPENV_UPATH,
41b732 ¤   PGPENV_OWNERNAME,
3a5f68 ¤   PGPENV_COMPANYNAME,
766579 ¤   PGPENV_LICENSENUMBER,
537a1d ¤   PGPENV_HTTPKEYSERVERHOST,
4e5f9b ¤   PGPENV_VERSION_STRING,
5b3f30 ¤   PGPENV_MAX_STRING,
c167c5 ¤
9adc1e ¤   PGP_ENUM_FORCE( PgpEnvStrings_ )
5982f7 };
9c1480 PGPENUM_TYPEDEF( PgpEnvStrings_, PgpEnvStrings );
81af5a
20af5a
b6c066 #define PGPENV_BASE_POINTER¤3000
c1c386 enum PgpEnvPointers_
2fbb36 {
ab681b ¤   PGPENV_CHARMAPTOLATIN1¤ = PGPENV_BASE_POINTER,
0a24ac ¤   PGPENV_CHARMAPTOLOCAL,
26d0a1 ¤   PGPENV_PGPKEYSMACMAINWINPOS,
a76ac0 ¤   PGPENV_PGPAPPMACPRIVATEDATA,
aeaaed ¤   PGPENV_ENCRYPTIONCALLBACK,
491adf ¤   PGPENV_PGPMENUMACAPPSIGNATURES,
18dc26 ¤   PGPENV_RANDSEEDREF,
3e4dd1 ¤   PGPENV_MAX_POINTER,
6f67c5 ¤
c1e058 ¤   PGP_ENUM_FORCE( PgpEnvPointers_ )
9582f7 };
97f59e PGPENUM_TYPEDEF( PgpEnvPointers_, PgpEnvPointers );
1aaf5a
5d08a3 /* Configuration priorities */
7f6f9e #define PGPENV_PRI_FORCE¤   25
995251 #define PGPENV_PRI_CMDLINE¤ 20
b7ddbc #define PGPENV_PRI_CONFIG¤  15
7b1c3b #define PGPENV_PRI_PRIVDEFAULT¤ 10
2cf6c5 #define PGPENV_PRI_SYSCONF¤ 5
20cb2c #define PGPENV_PRI_PUBDEFAULT¤  0
67af5a
--e1be 001deb06ca140100289 Page 3 of pgpEnv.h
3e22b6 /* Exported Functions */
0aaf5a
6e5ad5 /* create and initialize, copy, and destroy an environment */
618b39 PGPError ·¤ pgpenvCreate ( PGPContextRef, PGPEnv **outEnv);
334976 PGPError ·¤ pgpenvCopy ( PGPEnv const *env, PGPEnv **outEnv);
d6ee76 void ¤  ¤   pgpenvDestroy (PGPEnv *env);
2caf5a
9338e5 /*
1f6dde ·* Set Integer and String configuration parameters. ·Strings are
19182b ·* copied by the environment; the caller need not preserve them.
4abd68 ·* (They must, of course, be null-terminated.)
b2495d ·*/
5035e4 PGPError ¤  pgpenvSetInt(PGPEnv *env,
188ad2 ¤   ¤   ¤   ¤   ¤   PgpEnvInts var, PGPInt32 num, PGPInt32 pri);
1eebe8 PGPError ¤  pgpenvSetString (PGPEnv *env, PgpEnvStrings var,
97b639 ¤   ¤   ····¤   ¤   ·char const *string, PGPInt32 pri);
3daf5a
fc38e5 /*
344e9b ·* Retrieve Integer and String configuration parameters.
6e495d ·*/
d46079 PGPInt32 ¤  ¤   pgpenvGetInt (PGPEnv const *env, PgpEnvInts var,
71d8a1 ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 *pri, PGPError *error);
125d76 const char ··*¤ pgpenvGetCString(PGPEnv const *env,
a66391 ¤   ¤   ¤   ¤   ¤   ¤   PgpEnvStrings var, PGPInt32 *pri);
98af5a
63af5a
16a607 PGPContextRef¤  pgpenvGetContext( PGPEnv const *env );
9caf5a
2a38e5 /*
508925 ·* Set and get Pointer parameters -- these are not configuration values,
7cc8ad ·* in general, so they are treated somewhat differently. ·Note:
e8c993 ·* the environment code does *not* copy the objects associated with the
196607 ·* pointers, since it doesn't know how large they are or what other
013314 ·* dependent objects they may contain. ·It is up to the caller to
74a18f ·* ensure that the pointers remain valid as long as a copy of them
0d025c ·* might exist, and to free them when a pointer no longer exists.
ef495d ·*/
1a3a35 PGPError ¤  pgpenvSetPointer (PGPEnv *env, PgpEnvPointers var,
235715 ¤   ¤   ¤   ¤   ¤   void *ptr, size_t size);
a86920 void ··*¤   pgpenvGetPointer(PGPEnv const *env,
947b07 ¤   ¤   ¤   ¤   ¤   PgpEnvPointers var, size_t *optionalSize );
80af5a
b61254 PGP_END_C_DECLARATIONS
42af5a
ae6f82 #endif /* Included_pgpEnv_h */
9baf5a
4daf5a
d2af5a
62af5a
29af5a
0baf5a
deaf5a
--5064 000479cdf154010028a Page 1 of pgpFileType.c
bc38e5 /*
6662e0 ·* Figure out the type of a file.
a7775e ·*
fb68c2 ·* Written by Colin Plumb.
f7775e ·*
fd7149 ·* $Id: pgpFileType.c,v 1.10 1998/06/03 20:12:06 hal Exp $
2e495d ·*/
cfe2ff #include "pgpConfig.h"
1aaf5a
5c5f11 #include <string.h>¤/* For strcmp */
8839d3 #include "pgpFileType.h"
0b9c38 #include "pgpPktByte.h"
a9af5a
084ded #define FILETYPELEN¤8¤  /* # of characters needed */
52af5a
55af5a
12af5a
167d6e /* A character that does not appear in any pattern */
aaeb03 #define ANY¤(unsigned char)255
12af5a
ebaf5a
8d96eb static unsigned char const PGPPattern[] = { 5, 168, 3, 80, 71, 80 };
fbaf5a
b9beb7 static int
edd3b7 fileTypeMatch (PGPByte const *bytes, PGPByte const *prefix, unsigned len)
71bb36 {
28f455 ¤   unsigned l = *bytes++;
35743f ¤   unsigned i;
05af5a
774a37 ¤   if (l > len)
28bbde ¤   ¤   return 0;
0e1bb5 ¤   for (i = 0; i < l; i++)
e07f17 ¤   ¤   if (bytes[i] != prefix[i] && bytes[i] != ANY)
2c8144 ¤   ¤   ¤   return 0;
41bab2 ¤   return 1;¤  /* Success */
58efe6 }
b3af5a
9838e5 /*
a4a578 ·* Figure out if a file is a binary PGP file.
599f71 ·* Returns 1 if it is a PGP file, 0 if it is not.
35495d ·*/
294d2f int
07cb76 pgpFileTypePGP (PGPByte const *prefix, unsigned len)
30bb36 {
2d0436 ¤   PGPUInt32 type;
62af5a
294404 ¤   if (!len)
73bbde ¤   ¤   return 0;
03af5a
5fa83b ¤   /* Check first byte */
f6e78f ¤   if (!IS_OLD_PKTBYTE (*prefix) && !IS_NEW_PKTBYTE(*prefix))
65bbde ¤   ¤   return 0;
95af5a
ad633f ¤   /* Check for a new-style PGP file, using the PGP file header */
bc9e42 ¤   if (fileTypeMatch (PGPPattern, prefix, len))
a4e102 ¤   ¤   return 1;
c31b52 ¤   ¤
b8d8af ¤   /*
192e1e ¤   ·* Check PGP packet type, checking the tag bits for
44ca70 ¤   ·* known packet types. ·This needs to match pgpPktByte.h
43a4e3 ¤   ·*/
7fbdab ¤   type = PKTBYTE_TYPE (*prefix);
61d9a3 ¤   if (type > 0 && type <= PKTBYTE_MAXIMUM)
14e102 ¤   ¤   return 1;
fa3e6b ¤   return 0;
2cefe6 }
e0af5a
c7af5a
b6af5a
a4af5a
2eaf5a
47af5a
--4bdb 0006c363ff84010028a Page 2 of pgpFileType.c
e0af5a
1aaf5a
17af5a
7dba55 #if 0¤  /* KEEP [ */
7caf5a
a48f77 struct PGPFileTypeStruct {
77ab1e ¤   char const *¤   typeName;¤  /* Noun/adjective to modify "file" */
d8e623 ¤   char const *¤   ext;¤   /* .zip, .lha, .gz, etc. */
cedce5 ¤   PGPBoolean¤ ¤   compressible;/* Can it be further compressed (.tar) */
8a82f7 };
471b52 ¤   ¤
c21b52 ¤   ¤
fdaf5a
439c03 typedef struct PGPFileTypeStruct¤   PGPFileTypeStruct;
4caf5a
638332 typedef struct FileTypeInternal {
8a95e6 ¤   unsigned char const pattern[FILETYPELEN]; /* First char is length */
f8ddf2 ¤   PGPFileTypeStruct¤  ·type;
d47f8a } FileTypeInternal;
b1af5a
0daf5a
994cf7 static FileTypeInternal patterns[] =
0ebb36 {
49e27e ¤   { { 2, ·26, ·11 }, ·························{ "PAK", ····".pak", 0 } },
370882 ¤   { { 2, ·31, 139 }, ·························{ "gzip", ····".gz", 0 } },
3ab636 ¤   { { 2, ·31, 157 }, ·························{ "compressed",".Z", 0 } },
51bbc2 ¤   { { 2, 234, ·96 }, ·························{ "Arj", ····".arj", 0 } },
4911ea ¤   ¤   /* ^Z H P % */
57fdbc ¤   { { 4, ·26, ·72, ·80, ·37 }, ···············{ "Hyper", ··".hyp", 0 } },
76fa4d ¤   ¤   /* G I F 8 */
88d348 ¤   { { 4, ·71, ·73, ·70, ·56 }, ···············{ "GIF", ····".gif", 0 } },
185d31 ¤   ¤   /* HPAK */
5b6633 ¤   { { 4, ·72, ·80, ·65, ·75 }, ···············{ "Hpack", ··".hpk", 0 } },
24771b ¤   ¤   /* P K ^C ^D */
c78334 ¤   { { 4, ·80, ·75, ·3, ··4 ·}, ···············{ "Zip", ····".zip", 0 } },
e88007 ¤   ¤   /* Z O O ··*/
cb8cb5 ¤   { { 4, ·90, ·79, ·79, ·32 }, ···············{ "Zoo", ····".zoo", 0 } },
fd80bf ¤   ¤   /* ? ? - l h a 0 - ··-lha1- -lha2- and -lha3- */
c727d9 ¤   { { 7, ANY, ANY, ·45, 108, 104, ·48, ·45 }, { "LHArc", ··".lzh", 0 } },
8d8d11 ¤   { { 7, ANY, ANY, ·45, 108, 104, ·49, ·45 }, { "LHArc", ··".lzh", 0 } },
d51322 ¤   { { 7, ANY, ANY, ·45, 108, 104, ·50, ·45 }, { "LHArc", ··".lzh", 0 } },
55b9ea ¤   { { 7, ANY, ANY, ·45, 108, 104, ·51, ·45 }, { "LHArc", ··".lzh", 0 } },
802ecb ¤   ¤   /* ? ? - l h a ? - */
7600e8 ¤   { { 7, ANY, ANY, ·45, 108, 104, ANY, ·45 }, { "LHArc", ··".lha", 0 } }
6682f7 };
1daf5a
9b0c3c static PGPFileTypeStruct sPGPFile = {"PGP", ".pgp", 0};
5934fc ¤   ¤   ¤   ¤   ¤   /* \250 3 P G P */
79af5a
ecaf5a
b1af5a
dfec5f /* Figure out if the file is a recognized type */
c26ebe ¤   static PGPFileTypeStruct const *
2459f9 pgpFileType (PGPByte const *prefix, unsigned len)
8abb36 {
51743f ¤   unsigned i;
56af5a
14b860 ¤   for (i = 0; i < sizeof(patterns)/sizeof(*patterns); i++) {
7056bc ¤   ¤   if (fileTypeMatch(patterns[i].pattern, prefix, len))
539b66 ¤   ¤   ¤   return &patterns[i].type;
3a9371 ¤   }
2daf5a
16ef78 ¤   if (pgpFileTypePGP (prefix, len))
ab0ca8 ¤   ¤   return &sPGPFile;
deaf5a
743f59 ¤   return NULL;
78efe6 }
37af5a
d2af5a
9238e5 /*
598334 ·* Figure out if a file is human-readable or not.
6caee5 ·* Returns 0 if text, 1 if binary.
--28ef 0002fe0a6294010028a Page 3 of pgpFileType.c
4f775e ·*
f4757c ·* A file is considered binary if it contains any illegal control characters
f697f4 ·* or "too many" characters with the 8th bit set. ·If you're using Latin-1,
e94893 ·* you might have some such characters, but a binary file probably averages
98f5e1 ·* about half odd characters. ·This test assumes a file is binary if the
89de34 ·* number of bytes with the high bit set exceeds a quarter of the buffer.
76fbc2 ·* EXCEPTION: If working in Russian, Cyrillic is usually placed in the high
a7a106 ·* half, so ignore this test in that case.
aa775e ·*
4354fd ·* The legal control characters are:
2223b0 ·* ·0 ·NU ··null (nul) ······················ILLEGAL
cd5e9d ·* ·1 ·SH ··start of heading (soh) ··········ILLEGAL
9bfd9f ·* ·2 ·SX ··start of text (stx)¤¤   ·····ILLEGAL
649505 ·* ·3 ·EX ··end of text (etx) ···············ILLEGAL
7bc4cb ·* ·4 ·ET ··end of transmission (eot) ·······ILLEGAL
1bf41a ·* ·5 ·EQ ··enquiry (enq) ···················ILLEGAL
e4f41a ·* ·5 ·EQ ··enquiry (enq) ···················ILLEGAL
19f9f2 ·* ·6 ·AK ··acknowledge (ack) ···············ILLEGAL
937b2b ·* ·7 ·BL ··bell (bel) ······················legal¤ '\a'
856ce5 ·* ·8 ·BS ··backspace (bs) ··················legal¤ '\b'
bcc8fe ·* ·9 ·HT ··character tabulation (ht) ·······legal¤ '\t'
a5701f ·* 10 ·LF ··line feed (lf) ··················legal¤ '\n'
235362 ·* 11 ·VT ··line tabulation (vt) ············legal¤ '\v'
b44532 ·* 12 ·FF ··form feed (ff) ··················legal¤ '\f'
f5e973 ·* 13 ·CR ··carriage return (cr) ············legal¤ '\r'
38d5c8 ·* 14 ·SO ··shift out (so) ··················ILLEGAL
cfcf3b ·* 15 ·SI ··shift in (si) ···················ILLEGAL
58fd5b ·* 16 ·DL ··datalink escape (dle) ···········ILLEGAL
8e7a11 ·* 17 ·D1 ··device control one (dc1) ········ILLEGAL
7ee2f0 ·* 18 ·D2 ··device control two (dc2) ········ILLEGAL
1698fd ·* 19 ·D3 ··device control three (dc3) ······ILLEGAL
023355 ·* 20 ·D4 ··device control four (dc4) ·······ILLEGAL
26d5b4 ·* 21 ·NK ··negative acknowledge (nak) ······ILLEGAL
190a01 ·* 22 ·SY ··syncronous idle (syn) ···········ILLEGAL
09c806 ·* 23 ·EB ··end of transmission block (etb) ·ILLEGAL
08b868 ·* 24 ·CN ··cancel (can) ····················ILLEGAL
530523 ·* 25 ·EM ··end of medium (em) ··············ILLEGAL
a80ac0 ·* 26 ·SB ··substitute (sub) ················legal (CP/M & MS-DOS EOF)
efcac0 ·* 27 ·EC ··escape (esc) ····················ILLEGAL
c131f2 ·* 28 ·FS ··file separator (is4) ············ILLEGAL
2724c0 ·* 29 ·GS ··group separator (is3) ···········ILLEGAL
ad440b ·* 30 ·RS ··record separator (is2) ··········ILLEGAL
1827cf ·* 31 ·US ··unit separator (is1) ············ILLEGAL
d5775e ·*
d9a778 ·* TODO: Worry about EBCDIC
96fa9e ·* TODO: Use the charset rather than the language to decide.
6c3845 ·* TODO: Worry about shift-JIS and other heavy top-8-bit uses.
24495d ·*/
ecd83c ·
8baf5a
06a357 ·/* this appears to not be called. KEEP (as static) for now */
a2df0d ¤   static int
49ac23 pgpFileTypeBinary(char const *lang, PGPByte const *buf, unsigned len)
53bb36 {
9c5ab7 ¤   unsigned highlimit;
d4a508 ¤   PGPByte c;
c6af5a
e24404 ¤   if (!len)
990cbc ¤   ¤   return 1;¤  /* empty file or error, not a text file */
b99835 ¤   if (pgpFileType(buf, len))
19e102 ¤   ¤   return 1;
d5af5a
5a588b ¤   /* Limit on number of 8th-bit-set characters allowed */
d7d164 ¤   highlimit = len/4;
23a8cc ¤   if (lang && strcmp(lang, "ru") == 0)
f48341 ¤   ¤   highlimit = len;
17af5a
1843ab ¤   do {
823800 ¤   ¤   c = *buf++;
d75960 ¤   ¤   if (c < ' ' && (c < '\a' || c > '\r') && c != 26)
ed2c4a ¤   ¤   ¤   return 1;¤  /* Illegal control char */
2f0b65 ¤   ¤   if ((c & 0x80) && highlimit-- == 0)
--95aa 0012fea046b4010028a Page 4 of pgpFileType.c
17a955 ¤   ¤   ¤   return 1;¤  /* Too many 8th bits set */
67c57e ¤   } while (--len);
18af5a
5b3e6b ¤   return 0;
49efe6 }
c3af5a
2f64c3 #endif¤ /* ] KEEP */
--e2f7 00136fc15154010028b Page 1 of pgpFileType.h
bc38e5 /*
7bf8fb ·* pgpFileType.h - classify files
e1775e ·*
5fa16a ·* $Id: pgpFileType.h,v 1.10 1997/12/01 19:35:17 lloyd Exp $
7a495d ·*/
38af5a
85a76f #ifndef Included_pgpFileType_h
e2d09c #define Included_pgpFileType_h
32af5a
62c5d5 #include "pgpBase.h"
f3af5a
8799c6 PGP_BEGIN_C_DECLARATIONS
0a67c5 ¤
8bd834 int¤¤   pgpFileTypePGP (PGPByte const *prefix, unsigned len);
ecaf5a
441254 PGP_END_C_DECLARATIONS
72af5a
36502a #endif /* Included_pgpFileType_h */
--17d8 001a5db42714010028c Page 1 of pgpSigPipe.c
bc38e5 /*
3e19f7 ·* pgpSigPipe.c -- Create a Signature Verification Pipeline
dd775e ·*
b87ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
a6775e ·*
6258d5 ·* $Id: pgpSigPipe.c,v 1.6 1997/06/25 19:42:04 lloyd Exp $
bc495d ·*/
12af5a
cce2ff #include "pgpConfig.h"
caaf5a
a9feb2 #include <stdio.h>
6caf5a
4be624 #include "pgpSigPipe.h"
e5910a #include "pgpFIFO.h"
b4b512 #include "pgpPrsAsc.h"
6c9bb3 #include "pgpVerifyRa.h"
59af5a
daf07b PGPPipeline *
ae7b07 pgpSignatureVerifyCreate (
213163 ¤   PGPContextRef¤  cdkContext,
f6b6aa ¤   PGPPipeline **¤ texthead,
6acfc7 ¤   PGPPipeline **¤ sighead,
02ff68 ¤   PGPEnv const *¤ env,
aefc19 ¤   PGPFifoDesc const *fd,
f3b799 ¤   PGPByte const *hashlist, unsigned hashlen,
2736c2 ¤   int textmode,
5f8a9f ¤   PGPUICb const *ui, void *ui_arg)
febb36 {
c55d76 ¤   if (!texthead || !sighead)
807ed2 ¤   ¤   return NULL;
13af5a
4daea9 ¤   if (!fd)
9e438c ¤   ¤   fd = &pgpByteFifoDesc;
f9af5a
b00009 ¤   sighead = pgpParseAscCreate ( cdkContext, sighead, env, fd, ui, ui_arg);
3a71ab ¤   if (!sighead)
937ed2 ¤   ¤   return NULL;
3eaf5a
4778c5 ¤   return pgpVerifyReaderCreate ( cdkContext, texthead, sighead, env, fd,
14dd4e ¤   ¤   ¤   ¤   ······hashlist, hashlen, textmode, ui, ui_arg);
d1efe6 }
a5af5a
--2c3c 001c7642c084010028d Page 1 of pgpSigPipe.h
bc38e5 /*
f6db38 ·* pgpSigPipe.h -- Create a Signature Verification Pipeline
36775e ·*
4c7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
a4775e ·*
4a8190 ·* This is a Public API Function Header.
3c775e ·*
446669 ·* $Id: pgpSigPipe.h,v 1.9 1997/06/25 19:42:05 lloyd Exp $
f7495d ·*/
41af5a
84fa13 #ifndef Included_pgpSigPipe_h
c2ae27 #define Included_pgpSigPipe_h
93af5a
a5adb8 #include "pgpOpaqueStructs.h"
02e82c #include "pgpPubTypes.h"
16af5a
af99c6 PGP_BEGIN_C_DECLARATIONS
d8af5a
b6af5a
72af5a
9e37cb PGPPipeline ·*
c57b07 pgpSignatureVerifyCreate (
c0ba9f ¤   ¤   PGPContextRef¤  cdkContext,
3f617d ¤   ¤   PGPPipeline **texthead,
0d9d06 ¤   ¤   PGPPipeline **sighead,
d4d445 ¤   ¤   PGPEnv const *env,
3fe831 ¤   ¤   PGPFifoDesc const *fd,
e26de0 ¤   ¤   PGPByte const *hashlist,
94324d ¤   ¤   unsigned hashlen, int textmode,
c17d72 ¤   ¤   PGPUICb const *ui,
1c3068 ¤   ¤   void *ui_arg);
a7af5a
111254 PGP_END_C_DECLARATIONS
98af5a
c73833 #endif /* Included_pgpSigPipe_h */
--4ffe 000b62b3e9b4010028e Page 1 of pgpSigSpec.c
bc38e5 /*
7c4541 ·* pgpSigSpec.c -- Signature Specification
3e775e ·*
8454c5 ·* Code to specify a PGP signature and signature attributes
14775e ·*
1a7ae0 ·* Written by:¤ Derek Atkins <warlord@MIT.EDU>
0a775e ·*
4254ea ·* $Id: pgpSigSpec.c,v 1.40 1998/08/05 05:37:26 heller Exp $
82495d ·*/
02af5a
20e2ff #include "pgpConfig.h"
a9af5a
41feb2 #include <stdio.h>
870a8b #include <time.h>
81324c #include <string.h>
8faf5a
bba146 #include "pgpDebug.h"
2c5417 #include "pgpHashPriv.h"
f50d08 #include "pgpMem.h"
960d6d #include "pgpEnv.h"
4a2f8d #include "pgpErrors.h"
2bba29 #include "pgpPktList.h"
eecdc2 #include "pgpPubKey.h"
4426e3 #include "pgpRngPub.h"
182266 #include "pgpTimeDate.h"
64d11f #include "pgpUsuals.h"
1bf5ab #include "pgpSigSpec.h"
81c26c #include "pgpContext.h"
58af5a
782bd4 struct PGPSigSpec {
aee9fa ¤   PGPContextRef¤  cdkContext;
acabea ¤   PGPSigSpec *next;
6f4bdc ¤   PGPSecKey *seckey;
92c5ae ¤   PgpVersion version;
dcfee2 ¤   PGPByte hashtype;
82f5b9 ¤   PGPByte extra[5];¤  ¤   ¤   /* Sigtype, timestamp */
82af5a
5cbddf ¤   PktList¤*pkl;¤  ¤   ¤   ¤   /* Other subpackets */
b0a01a ¤   PktList¤*pki;¤  ¤   ¤   ¤   /* Pointer into pkl for iteration */
8577c3 ¤   DEBUG_STRUCT_CONSTRUCTOR( PGPSigSpec )
8f82f7 };
7eaf5a
3c9d57 PGPSigSpec *
db3bfc pgpSigSpecCreate (PGPEnv const *env, PGPSecKey *sec,
dd60b9 ¤   ¤   ··PGPByte sigtype)
32bb36 {
8e007a ¤   PGPSigSpec *ss;
c7c520 ¤   PGPContextRef¤  ¤   cdkContext¤ = pgpenvGetContext( env );
f667c5 ¤
bac65e ¤   if (!env || !sec)
427ed2 ¤   ¤   return NULL;
d5af5a
13e3b9 ¤   ss = (PGPSigSpec *)pgpContextMemAlloc( cdkContext,
f71b08 ¤   ¤   sizeof (*ss), kPGPMemoryMgrFlags_Clear);
25a526 ¤   if (ss) {
0f1b17 ¤   ¤   /*
36e52d ¤   ¤   ·* XXX: This hash algorithm selection must be kept in sync
8ed05a ¤   ¤   ·* ·····with pgpHashAlgUsedForSignatures (in pgpKeyMan.c)
1e9de3 ¤   ¤   ·*/
ef8604 ¤   ¤   int tzFix = pgpenvGetInt (env, PGPENV_TZFIX, NULL, NULL);
e5f5c3 ¤   ¤   PGPByte hash = pgpenvGetInt (env, PGPENV_HASH, NULL, NULL);
5e5913 ¤   ¤   PgpVersion version = pgpenvGetInt (env, PGPENV_VERSION, NULL,
55adb9 ¤   ¤   ¤   ¤   ¤   ¤   ···NULL);
fe9643 ¤   ¤   /* Force SHA-1 hash with DSA */
d48767 ¤   ¤   if (sec->pkAlg == kPGPPublicKeyAlgorithm_DSA) {
2e7edf ¤   ¤   ¤   hash = kPGPHashAlgorithm_SHA;
ee0fe4 ¤   ¤   }
05af5a
d3f95f ¤   ¤   ss->cdkContext¤ = cdkContext;
a0e2ae ¤   ¤   ss->seckey = sec;
67b177 #if 0
b6a008 ¤   ¤   ss->exportable = TRUE;
--7076 0009bcb6e604010028e Page 2 of pgpSigSpec.c
c130d0 ¤   ¤   ss->revocable = TRUE;
807454 #endif
5cf820 ¤   ¤   if (pgpSigSpecSetHashtype (ss, hash) ||
a9221f ¤   ¤   ····pgpSigSpecSetSigtype (ss, sigtype) ||
39ae26 ¤   ¤   ····pgpSigSpecSetTimestamp (ss, pgpTimeStamp (tzFix)) ||
8103be ¤   ¤   ····pgpSigSpecSetVersion (ss, version)) {
25c77c ¤   ¤   ¤   pgpContextMemFree( cdkContext, ss);
7f37d0 ¤   ¤   ¤   ss = NULL;
8a0fe4 ¤   ¤   }
ac9371 ¤   }
4b2e05 ¤   return ss;
21efe6 }
f0af5a
0f9d57 PGPSigSpec *
97ac6e pgpSigSpecCopy (PGPSigSpec const *spec)
2abb36 {
55007a ¤   PGPSigSpec *ss;
77f5ed ¤   PktList *pki, *sspk, **psspk;
40af5a
eeb855 ¤   if (!spec)
af7ed2 ¤   ¤   return NULL;
7baf5a
4143dd ¤   ss = (PGPSigSpec *)pgpContextMemAlloc( spec->cdkContext,
59b91e ¤   ¤   sizeof (*ss), 0);
1fa526 ¤   if (ss) {
f7b379 ¤   ¤   memcpy (ss, spec, sizeof (*ss));
f6e150 ¤   ¤   ss->next = NULL;
e09371 ¤   }
ca7895 ¤   /* Copy over packetlist */
39579f ¤   ss->pkl = ss->pki = NULL;
1aea8a ¤   psspk = &ss->pkl;¤  /* Point at "next" of last entry in ss->pkl */
446941 ¤   for (pki = spec->pkl; pki; pki = pki->next) {
21dc02 ¤   ¤   sspk = pgpPktListNew( spec->cdkContext, pki->type, pki->buf,
7c91cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··pki->len );
8f7751 ¤   ¤   if( IsNull( sspk ) )
e28705 ¤   ¤   ¤   return NULL;¤   /* out of memory */
963e94 ¤   ¤   *psspk = sspk;
773395 ¤   ¤   psspk = &sspk->next;
44d906 ¤   ¤   /* Copy iterator position in new list */
62d8b6 ¤   ¤   if (pki == spec->pki)
a07ccc ¤   ¤   ¤   ss->pki = sspk;
b49371 ¤   }
9d2e05 ¤   return ss;
d4efe6 }
2eaf5a
46314a void
ead36c pgpSigSpecDestroy (PGPSigSpec *spec)
12bb36 {
67007a ¤   PGPSigSpec *ss;
e7af5a
febf45 ¤   for (ss = spec; ss; ss = spec)
2ec7a1 ¤   {
324535 ¤   ¤   PGPContextRef¤  ¤   cdkContext;
951b52 ¤   ¤
fe9d40 ¤   ¤   cdkContext¤ = ss->cdkContext;
231106 ¤   ¤   spec = ss->next;
59fba7 ¤   ¤   pgpPktListFreeList( ss->pkl );
5bf9ec ¤   ¤   pgpClearMemory( ss, ·sizeof (*ss));
4cdf2c ¤   ¤   pgpContextMemFree( cdkContext, ss);
269371 ¤   }
8eefe6 }
b3af5a
772441 /* Lists... ·Add a spec to a list; get the next spec from the list */
b14d2f int
ae61ff pgpSigSpecAdd (PGPSigSpec **list, PGPSigSpec *spec)
25bb36 {
65a3e3 ¤   if (!list)
3562b5 ¤   ¤   return kPGPError_BadParams;
baaf5a
95296b ¤   spec->next = *list;
79ec2a ¤   *list = spec;
9b3e6b ¤   return 0;
--4221 000f4d4930c4010028e Page 3 of pgpSigSpec.c
7aefe6 }
46af5a
f89d57 PGPSigSpec *
82c16f pgpSigSpecNext (PGPSigSpec const *list)
c5bb36 {
f0a3e3 ¤   if (!list)
be7ed2 ¤   ¤   return NULL;
c7af5a
20402d ¤   return list->next;
49efe6 }
a9af5a
a438e5 /*
f7ad06 ·* Access functions and Modifier functions follow below
9f495d ·*/
94af5a
2616c2 /* The SecKey cannot be changed */
39521e PGPSecKey *
cf617c pgpSigSpecSeckey (PGPSigSpec const *spec)
13bb36 {
8b90eb ¤   return spec->seckey;
7fefe6 }
ddaf5a
e31251 /* Set and get the hash */
4b4d2f int
978487 pgpSigSpecSetHashtype (PGPSigSpec *spec, PGPByte hashtype)
97bb36 {
01e874 ¤   pgpAssert (spec);
c6af5a
70ef3c ¤   if (!pgpHashByNumber( (PGPHashAlgorithm)hashtype))
da467c ¤   ¤   return kPGPError_BadHashNumber;
9baf5a
629e06 ¤   spec->hashtype = hashtype;
e83e6b ¤   return 0;
52efe6 }
79af5a
55f0c9 PGPHashVTBL const *
fc3127 pgpSigSpecHash (PGPSigSpec const *spec)
e7bb36 {
165f5d ¤   return pgpHashByNumber( (PGPHashAlgorithm) spec->hashtype);
afefe6 }
c6af5a
da5d74 PGPByte
32a676 pgpSigSpecHashtype (PGPSigSpec const *spec)
c4bb36 {
6eb8ba ¤   return spec->hashtype;
e9efe6 }
72af5a
ef30e1 /* Set and get the version */
1b4d2f int
6c1659 pgpSigSpecSetVersion (PGPSigSpec *spec, PgpVersion version)
7cbb36 {
59e874 ¤   pgpAssert (spec);
fbaf5a
e5f5b3 ¤   spec->version = version;
e93e6b ¤   return 0;
d3efe6 }
bcaf5a
92a6d1 PgpVersion
b967d3 pgpSigSpecVersion (PGPSigSpec const *spec)
1bbb36 {
c727d4 ¤   return spec->version;
fdefe6 }
dfaf5a
a5ceb5 /* Make sure we have a version new enough for subpackets */
4b2978 static void
27487b sSubPacketVersion(PGPSigSpec *spec)
cabb36 {
3f7b68 ¤   if (spec->version < PGPVERSION_4)
c3a84b ¤   ¤   spec->version = PGPVERSION_4;
65efe6 }
28af5a
f44f62 /* Set the sigtype and timestamp; get the "extra" bytes which result */
--b099 0005c872abf4010028e Page 4 of pgpSigSpec.c
af4d2f int
16de36 pgpSigSpecSetSigtype (PGPSigSpec *spec, PGPByte sigtype)
e9bb36 {
aae874 ¤   pgpAssert (spec);
74af5a
d2714b ¤   spec->extra[0] = sigtype;
db3e6b ¤   return 0;
84efe6 }
7faf5a
5a4d2f int
1380e5 pgpSigSpecSetTimestamp (PGPSigSpec *spec, PGPUInt32 timestamp)
c2bb36 {
cfe874 ¤   pgpAssert (spec);
59af5a
3ee276 ¤   spec->extra[1] = (PGPByte)(timestamp>>24);
4f8181 ¤   spec->extra[2] = (PGPByte)(timestamp>>16);
a63136 ¤   spec->extra[3] = (PGPByte)(timestamp>>8);
8aa1ce ¤   spec->extra[4] = (PGPByte)timestamp;
363e6b ¤   return 0;
ebefe6 }
38af5a
da38e5 /*
e383bc ·* The timestamp is external for now because it is a part of the
220cdd ·* SigParams structure from the environment. ·Everything else is
336213 ·* a part of the PGPSigSpec structure·
a3495d ·*/
d2d929 PGPByte const *
edbe30 pgpSigSpecExtra (PGPSigSpec const *spec, size_t *extralen)
9ebb36 {
dde8cf ¤   if (extralen)
2c0064 ¤   ¤   *extralen = 5;
f5af5a
2c5056 ¤   return spec->extra;
28efe6 }
72af5a
fdaf5a
a246c5 /* Remaining functions use packetlist */
e6af5a
f2c7d3 static PktList *
236e8e sSearchPkts( PGPSigSpec const *spec, int type, int nth )
18bb36 {
675fa5 ¤   PktList *pki;
bfaf5a
c9538f ¤   for( pki = spec->pkl; pki; pki = pki->next ) {
2b49c6 ¤   ¤   if( (pki->type & kPGPSigFlags_Type) == type )
0d332e ¤   ¤   ¤   if (nth-- == 0)
8bf622 ¤   ¤   ¤   ¤   break;
4a9371 ¤   }
6d5a4d ¤   return pki;
16efe6 }
1baf5a
a61e9b #define sSigFlags(flags) \
b9ae42 ¤   (((flags) & ~kPGPSigFlags_Type) | kPGPSigFlags_Present)
c0af5a
beaf5a
43a1c4 /* Get expiration */
acbccf PGPUInt32
42a175 pgpSigSpecSigExpiration (PGPSigSpec const *spec, PGPUInt32 *sigExpire)
b2bb36 {
00254f ¤   PktList *pkt;
97af5a
09cfd8 ¤   pkt = sSearchPkts( spec, SIGSUB_EXPIRATION, 0 );
60ce6e ¤   if( IsNull( pkt ) ) {
f6c0e3 ¤   ¤   *sigExpire = 0;
dcbbde ¤   ¤   return 0;
989371 ¤   }
5f1264 ¤   pgpAssert (pkt->len == sizeof (*sigExpire));
1a5df9 ¤   *sigExpire = *(PGPUInt32 *)pkt->buf;
299825 ¤   return sSigFlags( pkt->type );
6cefe6 }
6aaf5a
5cc77d PGPError
--48b3 000283348b14010028e Page 5 of pgpSigSpec.c
e84a0c pgpSigSpecSetSigExpiration (PGPSigSpec *spec, PGPUInt32 flags,
fbdb3e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 sigExpire)
84bb36 {
27254f ¤   PktList *pkt;
58af5a
835d02 ¤   flags |= SIGSUB_EXPIRATION;
5f701f ¤   pkt = pgpPktListNew( spec->cdkContext, flags, (PGPByte *)&sigExpire,
53a897 ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(sigExpire) );
94d630 ¤   if( IsNull( pkt ) )
b34030 ¤   ¤   return kPGPError_OutOfMemory;
b1abdd ¤   pkt->next = spec->pkl;
3f2a77 ¤   spec->pkl = pkt;
42fcd5 ¤   sSubPacketVersion(spec);
4e151e ¤   return kPGPError_NoErr;
d1efe6 }
c8af5a
fdaf5a
bcbccf PGPUInt32
23ca0b pgpSigSpecExportable (PGPSigSpec const *spec, PGPBoolean *exportable)
87bb36 {
24254f ¤   PktList *pkt;
02af5a
ed42e4 ¤   pkt = sSearchPkts( spec, SIGSUB_EXPORTABLE, 0 );
d7ce6e ¤   if( IsNull( pkt ) ) {
d999e7 ¤   ¤   *exportable = 0;
bdbbde ¤   ¤   return 0;
489371 ¤   }
4af52e ¤   pgpAssert (pkt->len == sizeof (*exportable));
53be92 ¤   *exportable = *(PGPBoolean *)pkt->buf;
f39825 ¤   return sSigFlags( pkt->type );
93efe6 }
4aaf5a
c1c77d PGPError
dfff4e pgpSigSpecSetExportable (PGPSigSpec *spec, PGPUInt32 flags,
bd580c ¤   ¤   ¤   ¤   ¤   ¤   ·PGPBoolean exportable)
5ebb36 {
21254f ¤   PktList *pkt;
33af5a
4da1c7 ¤   flags |= SIGSUB_EXPORTABLE;
efbc66 ¤   pkt = pgpPktListNew( spec->cdkContext, flags, (PGPByte *)&exportable,
f25a6e ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(exportable) );
1fd630 ¤   if( IsNull( pkt ) )
014030 ¤   ¤   return kPGPError_OutOfMemory;
2cabdd ¤   pkt->next = spec->pkl;
a52a77 ¤   spec->pkl = pkt;
bffcd5 ¤   sSubPacketVersion(spec);
67151e ¤   return kPGPError_NoErr;
52efe6 }
7eaf5a
69bccf PGPUInt32
c5161e pgpSigSpecRevocable (PGPSigSpec const *spec, PGPBoolean *revocable)
81bb36 {
a5254f ¤   PktList *pkt;
d7af5a
9a3ec6 ¤   pkt = sSearchPkts( spec, SIGSUB_REVOCABLE, 0 );
28ce6e ¤   if( IsNull( pkt ) ) {
a1e718 ¤   ¤   *revocable = 0;
35bbde ¤   ¤   return 0;
909371 ¤   }
72205b ¤   pgpAssert (pkt->len == sizeof (*revocable));
2663f1 ¤   *revocable = *(PGPBoolean *)pkt->buf;
4e9825 ¤   return sSigFlags( pkt->type );
89efe6 }
66af5a
60c77d PGPError
6dfe9d pgpSigSpecSetRevocable (PGPSigSpec *spec, PGPUInt32 flags,
040a9b ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean revocable)
2cbb36 {
fa254f ¤   PktList *pkt;
d9af5a
b8a6f7 ¤   flags |= SIGSUB_REVOCABLE;
2871ae ¤   pkt = pgpPktListNew( spec->cdkContext, flags, (PGPByte *)&revocable,
--e7d5 000ac586a524010028e Page 6 of pgpSigSpec.c
4a61d1 ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(revocable) );
f3d630 ¤   if( IsNull( pkt ) )
ac4030 ¤   ¤   return kPGPError_OutOfMemory;
7eabdd ¤   pkt->next = spec->pkl;
9d2a77 ¤   spec->pkl = pkt;
7cfcd5 ¤   sSubPacketVersion(spec);
3d151e ¤   return kPGPError_NoErr;
c1efe6 }
5caf5a
50bccf PGPUInt32
b947a5 pgpSigSpecTrustLevel (PGPSigSpec const *spec, PGPByte *trustLevel,
ade07c ¤   ¤   ¤   ¤   ¤   ··PGPByte *trustValue)
81bb36 {
45254f ¤   PktList *pkt;
30af5a
fa3db0 ¤   pkt = sSearchPkts( spec, SIGSUB_TRUST, 0 );
c4ce6e ¤   if( IsNull( pkt ) ) {
c22e79 ¤   ¤   *trustLevel = 0;
ccf9cd ¤   ¤   *trustValue = 0;
6dbbde ¤   ¤   return 0;
519371 ¤   }
b87ed7 ¤   pgpAssert (pkt->len == sizeof (*trustLevel) + sizeof (*trustValue));
da2fda ¤   *trustLevel = pkt->buf[0];
256b2e ¤   *trustValue = pkt->buf[1];
949825 ¤   return sSigFlags( pkt->type );
42efe6 }
9aaf5a
b2c77d PGPError
3af490 pgpSigSpecSetTrustLevel (PGPSigSpec *spec, PGPUInt32 flags,
49de6d ¤   ¤   ¤   ¤   ¤   ¤   ·PGPByte trustLevel, PGPByte trustValue)
bcbb36 {
1f254f ¤   PktList *pkt;
d43095 ¤   PGPByte trustArray[2];
6daf5a
cc0ddf ¤   flags |= SIGSUB_TRUST;
ad4cc7 ¤   trustArray[0] = trustLevel;
7ab7ad ¤   trustArray[1] = trustValue;
5ffe69 ¤   pkt = pgpPktListNew( spec->cdkContext, flags, trustArray,
c19387 ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(trustArray) );
54d630 ¤   if( IsNull( pkt ) )
9d4030 ¤   ¤   return kPGPError_OutOfMemory;
e1abdd ¤   pkt->next = spec->pkl;
fd2a77 ¤   spec->pkl = pkt;
9efcd5 ¤   sSubPacketVersion(spec);
53151e ¤   return kPGPError_NoErr;
bbefe6 }
78af5a
33bccf PGPUInt32
0957a4 pgpSigSpecRegExp (PGPSigSpec const *spec, char **regExp)
20bb36 {
1c254f ¤   PktList *pkt;
a1af5a
ada2cf ¤   pkt = sSearchPkts( spec, SIGSUB_REGEXP, 0 );
02ce6e ¤   if( IsNull( pkt ) ) {
44e8d1 ¤   ¤   *regExp = 0;
a2bbde ¤   ¤   return 0;
6b9371 ¤   }
63f8ec ¤   *regExp = (char *)pkt->buf;
279825 ¤   return sSigFlags( pkt->type );
31efe6 }
12af5a
d1c77d PGPError
c8ef97 pgpSigSpecSetRegExp (PGPSigSpec *spec, PGPUInt32 flags, char const *regExp)
5cbb36 {
c1254f ¤   PktList *pkt;
31875f ¤   PGPSize len;
cfaf5a
fe3fd6 ¤   flags |= SIGSUB_REGEXP;
6cafcb ¤   len = strlen( regExp ) + 1;¤/* include null */
8204b4 ¤   pkt = pgpPktListNew( spec->cdkContext, flags,
b1304c ¤   ¤   ¤   ¤   (const PGPByte *) regExp, len );
acd630 ¤   if( IsNull( pkt ) )
--743c 00004e16c174010028e Page 7 of pgpSigSpec.c
c34030 ¤   ¤   return kPGPError_OutOfMemory;
32abdd ¤   pkt->next = spec->pkl;
cf2a77 ¤   spec->pkl = pkt;
05fcd5 ¤   sSubPacketVersion(spec);
a6151e ¤   return kPGPError_NoErr;
eeefe6 }
bdaf5a
a90cbf /* Access functions for self-sig related signature subpackets */
13af5a
b0bccf PGPUInt32
a240d3 pgpSigSpecKeyExpiration (PGPSigSpec const *spec, PGPUInt32 *keyExpire)
0bbb36 {
d1254f ¤   PktList *pkt;
93af5a
9f85d7 ¤   pkt = sSearchPkts( spec, SIGSUB_KEY_EXPIRATION, 0 );
4ece6e ¤   if( IsNull( pkt ) ) {
6b45f9 ¤   ¤   *keyExpire = 0;
ddbbde ¤   ¤   return 0;
549371 ¤   }
f752de ¤   pgpAssert (pkt->len == sizeof (*keyExpire));
859932 ¤   *keyExpire = *(PGPUInt32 *)pkt->buf;
579825 ¤   return sSigFlags( pkt->type );
ddefe6 }
77af5a
bbc77d PGPError
a150a7 pgpSigSpecSetKeyExpiration (PGPSigSpec *spec, PGPUInt32 flags,
feeb25 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyExpire)
59bb36 {
1a254f ¤   PktList *pkt;
60af5a
c00299 ¤   flags |= SIGSUB_KEY_EXPIRATION;
2d4004 ¤   pkt = pgpPktListNew( spec->cdkContext, flags, (PGPByte *)&keyExpire,
05b206 ¤   ¤   ¤   ¤   ¤   ¤   ·sizeof(keyExpire) );
9dd630 ¤   if( IsNull( pkt ) )
924030 ¤   ¤   return kPGPError_OutOfMemory;
68abdd ¤   pkt->next = spec->pkl;
ec2a77 ¤   spec->pkl = pkt;
8afcd5 ¤   sSubPacketVersion(spec);
2e151e ¤   return kPGPError_NoErr;
07efe6 }
89af5a
0bbccf PGPUInt32
e2ebd2 pgpSigSpecPrefAlgs (PGPSigSpec const *spec, PGPByte **prefalgs,
388ac8 ¤   ¤   ¤   ¤   ¤   PGPSize *preflen)
d7bb36 {
09254f ¤   PktList *pkt;
23af5a
bfe5b1 ¤   pkt = sSearchPkts( spec, SIGSUB_PREFERRED_ENCRYPTION_ALGS, 0 );
d6ce6e ¤   if( IsNull( pkt ) ) {
ea6b1b ¤   ¤   *prefalgs = 0;
60303b ¤   ¤   *preflen = 0;
94bbde ¤   ¤   return 0;
9c9371 ¤   }
42d935 ¤   *preflen = pkt->len;
050e20 ¤   *prefalgs = pkt->buf;
789825 ¤   return sSigFlags( pkt->type );
f3efe6 }
c9af5a
60c77d PGPError
e969bd pgpSigSpecSetPrefAlgs (PGPSigSpec *spec, PGPUInt32 flags,
1daf05 ¤   ¤   ¤   ¤   ¤   ···PGPByte const *algs, size_t len)
e0bb36 {
c3254f ¤   PktList *pkt;
f1af5a
b53ee8 ¤   flags |= SIGSUB_PREFERRED_ENCRYPTION_ALGS;
305370 ¤   pkt = pgpPktListNew( spec->cdkContext, flags, algs, len );
c8d630 ¤   if( IsNull( pkt ) )
244030 ¤   ¤   return kPGPError_OutOfMemory;
67abdd ¤   pkt->next = spec->pkl;
1b2a77 ¤   spec->pkl = pkt;
a2fcd5 ¤   sSubPacketVersion(spec);
04151e ¤   return kPGPError_NoErr;
--d39d 0001ac904314010028e Page 8 of pgpSigSpec.c
7aefe6 }
46af5a
13bccf PGPUInt32
dfbb2d pgpSigSpecAdditionalRecipientRequest (PGPSigSpec const *spec,
54627a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPByte **arr, size_t *arrlen,
2deed0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··int nth)
7cbb36 {
07254f ¤   PktList *pkt;
c3af5a
c104eb ¤   pkt = sSearchPkts( spec, SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST, nth );
09ce6e ¤   if( IsNull( pkt ) ) {
7f940b ¤   ¤   *arr = 0;
84f2ee ¤   ¤   *arrlen = 0;
49bbde ¤   ¤   return 0;
e89371 ¤   }
161059 ¤   *arrlen = pkt->len;
047e46 ¤   *arr = pkt->buf;
769825 ¤   return sSigFlags( pkt->type );
bdefe6 }
fbaf5a
2dc77d PGPError
b75f74 pgpSigSpecSetAdditionalRecipientRequest ·(PGPSigSpec *spec, PGPUInt32 flags,
2c7717 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPByte const *krinfo, PGPSize len)
13bb36 {
b9254f ¤   PktList *pkt;
9baf5a
b9a2ca ¤   flags |= SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST;
6339c5 ¤   pkt = pgpPktListNew( spec->cdkContext, flags, krinfo, len );
01d630 ¤   if( IsNull( pkt ) )
a44030 ¤   ¤   return kPGPError_OutOfMemory;
f6abdd ¤   pkt->next = spec->pkl;
292a77 ¤   spec->pkl = pkt;
54fcd5 ¤   sSubPacketVersion(spec);
45151e ¤   return kPGPError_NoErr;
f4efe6 }
68af5a
e3bccf PGPUInt32
e38742 pgpSigSpecRevocationKey (PGPSigSpec const *spec, PGPByte **rev,
b2905c ¤   ¤   ¤   ¤   ¤   ¤   ·PGPSize *revlen, int nth)
1fbb36 {
f4254f ¤   PktList *pkt;
f6af5a
ac720a ¤   pkt = sSearchPkts( spec, SIGSUB_KEY_REVOCATION_KEY, nth );
adce6e ¤   if( IsNull( pkt ) ) {
501598 ¤   ¤   *rev = 0;
4201e7 ¤   ¤   *revlen = 0;
9fbbde ¤   ¤   return 0;
549371 ¤   }
c59dbe ¤   *revlen = pkt->len;
37e475 ¤   *rev = pkt->buf;
b79825 ¤   return sSigFlags( pkt->type );
56efe6 }
e5af5a
b2c77d PGPError
627e01 pgpSigSpecSetRevocationKey ·(PGPSigSpec *spec, PGPUInt32 flags,
862624 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPByte const *krinfo, size_t len)
efbb36 {
45254f ¤   PktList *pkt;
f6af5a
9366e2 ¤   flags |= SIGSUB_KEY_REVOCATION_KEY;
6b39c5 ¤   pkt = pgpPktListNew( spec->cdkContext, flags, krinfo, len );
13d630 ¤   if( IsNull( pkt ) )
ef4030 ¤   ¤   return kPGPError_OutOfMemory;
61abdd ¤   pkt->next = spec->pkl;
0a2a77 ¤   spec->pkl = pkt;
74fcd5 ¤   sSubPacketVersion(spec);
62151e ¤   return kPGPError_NoErr;
44efe6 }
25af5a
46a72a /* Unrecognized subpacket type which we will copy over blindly */
1abccf PGPUInt32
1a6995 pgpSigSpecPacket (PGPSigSpec const *spec, PGPByte **extradata,
--fbff 00179578d9d4010028e Page 9 of pgpSigSpec.c
f6e94e ¤   ¤   ¤   ¤   ··PGPSize *len, int nth)
e2bb36 {
a3254f ¤   PktList *pkt;
e8af5a
937524 ¤   pkt = sSearchPkts( spec, SIGSUB_UNRECOGNIZED, nth );
f3ce6e ¤   if( IsNull( pkt ) ) {
526dbd ¤   ¤   *extradata = 0;
2b5afc ¤   ¤   *len = 0;
a6bbde ¤   ¤   return 0;
ba9371 ¤   }
8c7405 ¤   *len = pkt->len;
6336f5 ¤   *extradata = pkt->buf;
ee9825 ¤   return sSigFlags( pkt->type );
641862 }¤
c8af5a
35a72a /* Unrecognized subpacket type which we will copy over blindly */
d0c77d PGPError
50ff39 pgpSigSpecSetPacket (PGPSigSpec *spec, PGPUInt32 flags,
3cec8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPByte const *extradata, size_t len)
d2bb36 {
16254f ¤   PktList *pkt;
9eaf5a
e866fd ¤   flags |= SIGSUB_UNRECOGNIZED;
a7bc4a ¤   pkt = pgpPktListNew( spec->cdkContext, flags, extradata, len );
60d630 ¤   if( IsNull( pkt ) )
dc4030 ¤   ¤   return kPGPError_OutOfMemory;
1eabdd ¤   pkt->next = spec->pkl;
5c2a77 ¤   spec->pkl = pkt;
effcd5 ¤   sSubPacketVersion(spec);
52151e ¤   return kPGPError_NoErr;
c7efe6 }
7baf5a
8baf5a
6b38e5 /*
940d4b ·* Search for and remove packet of specified type. ·Returns flags associated
4af219 ·* with packet, including kPGPSigFlags_Present; returns 0 if not found.
c4495d ·*/
acbccf PGPUInt32
8ea99c pgpSigSpecRemove (PGPSigSpec *spec, PGPUInt32 type)
c8bb36 {
aa5fa5 ¤   PktList *pki;
e47b22 ¤   PktList **pkip;
26af5a
039222 ¤   pkip = &spec->pkl;
11538f ¤   for( pki = spec->pkl; pki; pki = pki->next ) {
084aeb ¤   ¤   if( (PGPUInt32)(pki->type & kPGPSigFlags_Type) == type )
78cdcb ¤   ¤   ¤   break;
5f3e58 ¤   ¤   pkip = &pki->next;
4e9371 ¤   }
1ba533 ¤   if (!pki)
3dbbde ¤   ¤   return 0;
cd756d ¤   *pkip = pki->next;
8ce4a7 ¤   type = pki->type;
d14d10 ¤   pgpPktListFreeOne( pki );
8be66c ¤   return sSigFlags( type );
79efe6 }
--e600 0005650c6b74010028f Page 1 of pgpSigSpec.h
bc38e5 /*
6a7953 ·* pgpSigSpec.h -- Signature Specification; specify the attributes of a
efd8eb ·* signature or list of signatures
d4775e ·*
805a45 ·* Written By:¤ Derek Atkins <warlord@MIT.EDU>
27775e ·*
a57b43 ·* $Id: pgpSigSpec.h,v 1.24 1998/06/09 00:07:21 hal Exp $
c6495d ·*/
8baf5a
adec30 #ifndef Included_pgpSigSpec_h
89b804 #define Included_pgpSigSpec_h
efaf5a
aa38e5 /*
d54031 ·* Signature type values
08495d ·*/
a92935 #define PGP_SIGTYPE_BINARY¤ ¤   0
a6df62 #define PGP_SIGTYPE_TEXT¤   ¤   1
ca439a #define PGP_SIGTYPE_KEY_GENERIC¤¤   0x10
356c00 #define PGP_SIGTYPE_KEY_PERSONA¤¤   0x11
4586ba #define PGP_SIGTYPE_KEY_CASUAL¤ ¤   0x12
f2ce64 #define PGP_SIGTYPE_KEY_POSITIVE¤   0x13
f7a499 #define PGP_SIGTYPE_KEY_SUBKEY¤ ¤   0x18
33cf06 #define PGP_SIGTYPE_KEY_PROPERTY¤   0x1f
094cc3 #define PGP_SIGTYPE_KEY_REVOKE¤ 0x20
70769b #define PGP_SIGTYPE_KEY_SUBKEY_REVOKE ··0x28
567af0 #define PGP_SIGTYPE_KEY_UID_REVOKE¤ 0x30
584be9 #define PGP_SIGTYPE_NOTARY¤ ¤   0x40
9938e5 /*
dbf34c ·* A signature with this bit set is considered "extended" and allows us to
64be26 ·* parse "extra" information > 5 bytes without fear of being bitten by the
596aec ·* PGP 2.X aliasing problem.
c8495d ·*/
9cf809 #define PGP_SIGTYPEF_EXTENDED¤  ¤   0x80
14af5a
60fff3 /* Sig flags for access and modification of SigSpec structures */
2fdb37 /* Must keep low byte free for type byte */
e799cf #define kPGPSigFlags_Type¤  ¤   ¤   0xff
caaa2a #define kPGPSigFlags_Present¤   ¤   0x100
f487d1 #define kPGPSigFlags_Unhashed¤  ¤   0x200
67e0e6 #define kPGPSigFlags_Critical¤  ¤   0x400
48af5a
26d11f #include "pgpUsuals.h"
a0af5a
8299c6 PGP_BEGIN_C_DECLARATIONS
41af5a
51adb8 #include "pgpOpaqueStructs.h"
77af5a
f038e5 /*
ec4345 ·* Create and Destroy a signature specification. ·Required parameters
cdcb36 ·* are passed into this function. ·Some parameters are assumed from
6fa56e ·* the PGPEnv.
37495d ·*/
037f48 PGPSigSpec ·*pgpSigSpecCreate (PGPEnv const *env,
5385ef ¤   PGPSecKey *seckey, PGPByte sigtype);
9f3e2a PGPSigSpec ·*pgpSigSpecCopy (PGPSigSpec const *spec);
4c67f5 void ·pgpSigSpecDestroy (PGPSigSpec *spec);
09af5a
472c03 /* Deal with lists of signature specifications */
6d3d8d int ·pgpSigSpecAdd (PGPSigSpec **list,
83e9f7 ¤   PGPSigSpec *spec);
772fce PGPSigSpec ·*pgpSigSpecNext (PGPSigSpec const *list);
bfaf5a
118767 /* Access functions for sigspec parameters */
eace0b PgpVersion ·pgpSigSpecVersion (PGPSigSpec const *spec);
16ccca PGPSecKey ·*pgpSigSpecSeckey (PGPSigSpec const *spec);
e676d4 PGPHashVTBL const ·*pgpSigSpecHash (
5dbb49 ¤   PGPSigSpec const *spec);
bffefd PGPByte ·pgpSigSpecHashtype (PGPSigSpec const *spec);
6fee36 PGPByte const ·*pgpSigSpecExtra (PGPSigSpec const *spec,
ff7211 ·····size_t *extralen);
bfaf5a
56ae49 /* Modification functions for sigspec parameters */
--fe92 0008617ec504010028f Page 2 of pgpSigSpec.h
2dd9a3 int ·pgpSigSpecSetHashtype (PGPSigSpec *spec, PGPByte hashtype);
605bee int ·pgpSigSpecSetSigtype (PGPSigSpec *spec, PGPByte sigtype);
789fe3 int ·pgpSigSpecSetTimestamp (PGPSigSpec *spec,
ff1df2 ¤   PGPUInt32 timestamp);
b6ebb5 int ·pgpSigSpecSetVersion (PGPSigSpec *spec,
867cbc ¤   PgpVersion version);
31af5a
971b0b PGPUInt32·
1424ab pgpSigSpecSigExpiration (PGPSigSpec const *spec, PGPUInt32 *sigExpire);
4bc77d PGPError
fb4a0c pgpSigSpecSetSigExpiration (PGPSigSpec *spec, PGPUInt32 flags,
5fd806 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 sigExpire);
d8c77d PGPError
79ff4e pgpSigSpecSetExportable (PGPSigSpec *spec, PGPUInt32 flags,
c6ca14 ¤   ¤   ¤   ¤   ¤   ¤   ·PGPBoolean exportable);
72bccf PGPUInt32
0abe39 pgpSigSpecExportable (PGPSigSpec const *spec, PGPBoolean *exportable);
fec77d PGPError
18fe9d pgpSigSpecSetRevocable (PGPSigSpec *spec, PGPUInt32 flags,
2c2a70 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean revocable);
08bccf PGPUInt32
51f9c9 pgpSigSpecRevocable (PGPSigSpec const *spec, PGPBoolean *revocable);
b4c77d PGPError
f6f490 pgpSigSpecSetTrustLevel (PGPSigSpec *spec, PGPUInt32 flags,
fbb81d ¤   ¤   ¤   ¤   ¤   ¤   ·PGPByte trustLevel, PGPByte trustValue);
fdbccf PGPUInt32
3647a5 pgpSigSpecTrustLevel (PGPSigSpec const *spec, PGPByte *trustLevel,
5fb92b ¤   ¤   ¤   ¤   ¤   ··PGPByte *trustValue);
57c77d PGPError
63e0f9 pgpSigSpecSetRegExp (PGPSigSpec *spec, PGPUInt32 flags, char const *regExp);
c0bccf PGPUInt32
3de359 pgpSigSpecRegExp (PGPSigSpec const *spec, char **regExp);
45af5a
e7416f /* Access functions for self-sig subpackets */
2f1b0b PGPUInt32·
26e476 pgpSigSpecKeyExpiration (PGPSigSpec const *spec, PGPUInt32 *keyExpire);
dfc77d PGPError
e950a7 pgpSigSpecSetKeyExpiration (PGPSigSpec *spec, PGPUInt32 flags,
fd7664 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyExpire);
22bccf PGPUInt32
85ebd2 pgpSigSpecPrefAlgs (PGPSigSpec const *spec, PGPByte **prefalgs,
6d4aee ¤   ¤   ¤   ¤   ¤   PGPSize *preflen);
77c77d PGPError
c169bd pgpSigSpecSetPrefAlgs (PGPSigSpec *spec, PGPUInt32 flags,
8d5722 ¤   ¤   ¤   ¤   ¤   ···PGPByte const *algs, size_t len);
28bccf PGPUInt32
3bbb2d pgpSigSpecAdditionalRecipientRequest (PGPSigSpec const *spec,
9c627a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPByte **arr, size_t *arrlen,
4dd643 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··int nth);
f8c77d PGPError
355f74 pgpSigSpecSetAdditionalRecipientRequest ·(PGPSigSpec *spec, PGPUInt32 flags,
8d6469 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPByte const *krinfo, PGPSize len);
0dbccf PGPUInt32
578742 pgpSigSpecRevocationKey (PGPSigSpec const *spec, PGPByte **rev,
709859 ¤   ¤   ¤   ¤   ¤   ¤   ·PGPSize *revlen, int nth);
dcc77d PGPError
dd7e01 pgpSigSpecSetRevocationKey ·(PGPSigSpec *spec, PGPUInt32 flags,
5b6720 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPByte const *krinfo, size_t len);
bfbccf PGPUInt32
a5696c pgpSigSpecPacket (PGPSigSpec const *spec, PGPByte **extradata, PGPSize *len,
c7a582 ¤   ¤   ¤   ¤   ··int nth);
9fc77d PGPError
edff39 pgpSigSpecSetPacket (PGPSigSpec *spec, PGPUInt32 flags,
695f21 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPByte const *extradata, size_t len);
25af5a
2faf5a
4abccf PGPUInt32
c55e6c pgpSigSpecRemove (PGPSigSpec *spec, PGPUInt32 type);
0faf5a
17af5a
c41254 PGP_END_C_DECLARATIONS
86af5a
--5b6d 0016e7b84a34010028f Page 3 of pgpSigSpec.h
6e152d #endif /* Included_pgpSigSpec_h */
--384b 0012db8658640100290 Page 1 of Makefile.in
5ea601 #
c34d9e # priv/ui/
96a601 #
11ac6b # $Id: Makefile.in,v 1.3 1998/08/05 05:37:19 heller Exp $
08a601 #
7eaf5a
34704d .SUFFIXES: .c .cpp
84af5a
69d0f7 .cpp.o:
45dfd6 ¤   g++ -c -fhandle-exceptions $(CFLAGS) $<
3eaf5a
93c33b OBJS= pgpDialogOptions.o pgpDialogs.o pgpKeyServerDialogCommon.o \
9aedd2 ¤   ¤   pgpRecipientDialogCommon.o
5ea900 PRIVHDRS=·
70af5a
5ab7a3 all:: DONE
baaf5a
2daf5a
--8424 000fabcfe4740100291 Page 1 of pgpDialogOptions.c
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
b6f704 ¤   $Id: pgpDialogOptions.c,v 1.26.10.1 1998/11/12 03:22:58 heller Exp $
0df7f7 ____________________________________________________________________________*/
45af5a
88324c #include <string.h>
0faf5a
a4a076 #include "pgpKeys.h"
bfeb5b #include "pgpKeyServer.h"
9a0d08 #include "pgpMem.h"
85e684 #include "pgpUserInterface.h"
f2af5a
400141 #include "pgpOptionListPriv.h"
6daf5a
f4d622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
74af5a
3913fb ¤   PGPOptionListRef
3341b8 PGPOUIDialogPrompt(
3b35f6 ¤   PGPContextRef ¤ context,
84968e ¤   const char¤ ¤   *prompt)
84bb36 {
6c3ddd ¤   PGPOptionListRef¤   optionList;
abaf5a
0c1aa1 ¤   pgpValidateOptionContext( context );
56637e ¤   pgpValidateOptionParam( IsntNull( prompt ) );
6467c5 ¤
2bba60 ¤   optionList = pgpCreateBufferOptionList( context,
cb551b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DialogPrompt,
eacf2f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   prompt, strlen( prompt ) + 1 );
a9da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
478233 ¤   return( optionList );
e1efe6 }
8caf5a
2813fb ¤   PGPOptionListRef
1ff5d8 PGPOUIWindowTitle(
9a35f6 ¤   PGPContextRef ¤ context,
433472 ¤   const char¤ ¤   *title)
16bb36 {
903ddd ¤   PGPOptionListRef¤   optionList;
1faf5a
4c1aa1 ¤   pgpValidateOptionContext( context );
d3995e ¤   pgpValidateOptionParam( IsntNull( title ) );
8767c5 ¤
9bba60 ¤   optionList = pgpCreateBufferOptionList( context,
9bd6c8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_WindowTitle,
37544e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   title, strlen( title ) + 1 );
dbda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
f08233 ¤   return( optionList );
8eefe6 }
8daf5a
2813fb ¤   PGPOptionListRef
80884c PGPOUIOutputPassphrase(
da35f6 ¤   PGPContextRef ¤ context,
077e23 ¤   char¤   ¤   ¤   **passphrase)
78bb36 {
713ddd ¤   PGPOptionListRef¤   optionList;
bf0cfd ¤   PGPOptionValue¤ ¤   value;
4667c5 ¤
b328b0 ¤   pgpValidateOptionParam( IsntNull( passphrase ) );
66cc43 ¤   *passphrase = NULL;
a41aa1 ¤   pgpValidateOptionContext( context );
c667c5 ¤
41fb6e ¤   /* buffer size may be 0 */
cb67c5 ¤
bd79db ¤   value.asPtr¤= passphrase;
f6e20a ¤   optionList ¤= pgpCreateStandardValueOptionList( context,·
f56218 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_OutputPassphrase,
236d78 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( passphrase), NULL );
3eaf5a
fa8233 ¤   return( optionList );
--0da4 000724cebb240100291 Page 2 of pgpDialogOptions.c
7aefe6 }
46af5a
b1fac1 /* MS Windows only.*/
5780df /* Option takes parent's HWND and uses for child windows */
82af5a
4fafb9 #if PGP_WIN32
8113fb ¤   PGPOptionListRef
dc77cc PGPOUIParentWindowHandle(
f035f6 ¤   PGPContextRef ¤ context,
b70a78 ¤   HWND hwndParent)
bfbb36 {
753ddd ¤   PGPOptionListRef¤   optionList;
6a0cfd ¤   PGPOptionValue¤ ¤   value;
3a67c5 ¤
aa1aa1 ¤   pgpValidateOptionContext( context );
06af5a
0dfb6e ¤   /* buffer size may be 0 */
1667c5 ¤
f74d5e ¤   value.asUInt = (UINT)hwndParent;
7b67c5 ¤
eb0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
9b9e83 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ParentWindowHandle,
1126bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
8f67c5 ¤
8d8233 ¤   return( optionList );
5defe6 }
527454 #endif
d8af5a
dd33c8 ¤   static void
513fbd FreePGPOUICheckboxDesc(
fca1bc ¤   PGPContextRef¤  ¤   context,
cc1176 ¤   PGPOUICheckboxDesc¤ *desc)
e0bb36 {
4651f4 ¤   pgpAssertAddrValid( desc, PGPOUICheckboxDesc );
9067c5 ¤
e05ace ¤   if( IsntNull( desc->title ) )
edc7a1 ¤   {
f7267b ¤   ¤   pgpContextMemFree( context, (void *) desc->title );
aa9287 ¤   ¤   desc->title = NULL;
9a9371 ¤   }
f9af5a
ec0890 ¤   if( IsntNull( desc->description ) )
62c7a1 ¤   {
fa3c8f ¤   ¤   pgpContextMemFree( context, (void *) desc->description );
167617 ¤   ¤   desc->description = NULL;
1c9371 ¤   }
4167c5 ¤
ca6d7c ¤   pgpContextMemFree( context, desc );
ecefe6 }
26af5a
9666dd ¤   static PGPError
ded460 CopyPGPOUICheckboxDesc(
40883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
c88079 ¤   const PGPOUICheckboxDesc¤   *srcDesc,
676e66 ¤   PGPOUICheckboxDesc¤ ¤   ¤   **destDesc)
e4bb36 {
d27759 ¤   PGPError¤   ¤   ¤   err = kPGPError_OutOfMemory;
8b7419 ¤   PGPOUICheckboxDesc¤ *outDesc;
f767c5 ¤
4f5d79 ¤   pgpAssertAddrValid( srcDesc, PGPOUICheckboxDesc );
ddedc8 ¤   pgpAssertAddrValid( destDesc, PGPOUICheckboxDesc * );
4267c5 ¤
d06b25 ¤   *destDesc = NULL;
ca67c5 ¤
80089a ¤   outDesc = (PGPOUICheckboxDesc *) pgpContextMemAlloc( context,
7c8d85 ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *outDesc ), kPGPMemoryMgrFlags_Clear );
1cfd8c ¤   if( IsntNull( outDesc ) )
32c7a1 ¤   {
e86bbf ¤   ¤   *outDesc = *srcDesc;
651b52 ¤   ¤
e79c9f ¤   ¤   pgpAssertAddrValid( srcDesc->title, char );
725d26 ¤   ¤   pgpAssertAddrValid( srcDesc->description, char );
--29cd 00052db9f2a40100291 Page 3 of pgpDialogOptions.c
f11b52 ¤   ¤
abde9b ¤   ¤   outDesc->title ¤¤   ¤   = pgpAllocCString( context, srcDesc->title );
d07392 ¤   ¤   outDesc->description ¤  = pgpAllocCString( context,
f8f02e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   srcDesc->description );
1fd0ec ¤   ¤   if( IsntNull( outDesc->title ) &&
8f44f6 ¤   ¤   ¤   IsntNull( outDesc->description ) )
d45b34 ¤   ¤   {
26fcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
730fe4 ¤   ¤   }
d40e1d ¤   ¤   else
0f5b34 ¤   ¤   {
5006b0 ¤   ¤   ¤   FreePGPOUICheckboxDesc( context, outDesc );
b827a0 ¤   ¤   ¤   outDesc = NULL;
2d0fe4 ¤   ¤   }
199371 ¤   }
eb67c5 ¤
573e34 ¤   *destDesc = outDesc;
8eaf5a
e7deb7 ¤   return( err );
deefe6 }
2baf5a
7d66dd ¤   static PGPError
1db580 CheckboxOptionHandlerProc(
6e883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
690315 ¤   PGPOptionHandlerOperation ¤ operation,
c41a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
70d276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
30a79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
1d48db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
5e4ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
f2bb36 {
607d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
0c4374 ¤   PGPOUICheckboxDesc¤ *inputDesc;
ae67c5 ¤
7847bf ¤   pgpAssert( inputValueSize == sizeof( *inputDesc ) );
bcaf5a
90958f ¤   (void) type;
8ea835 ¤   (void) inputValueSize;
ff67c5 ¤
f15b19 ¤   inputDesc = (PGPOUICheckboxDesc *) inputValue.asPtr;
574144 ¤   pgpAssertAddrValid( inputDesc, PGPOUICheckboxDesc );
dc67c5 ¤
6db643 ¤   switch( operation )
e5c7a1 ¤   {
3e4885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
5d5b34 ¤   ¤   {
dd9ef6 ¤   ¤   ¤   FreePGPOUICheckboxDesc( context, inputDesc );
bbcdcb ¤   ¤   ¤   break;
110fe4 ¤   ¤   }
3087c7 ¤   ¤   ¤
900dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
555b34 ¤   ¤   {
a21f66 ¤   ¤   ¤   PGPOUICheckboxDesc¤ *outputDesc;
3baf5a
19bd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
b9cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
b0af5a
131ef1 ¤   ¤   ¤   err = CopyPGPOUICheckboxDesc( context, inputDesc, &outputDesc );
e1698b ¤   ¤   ¤   if( IsntPGPError( err ) )
a6f776 ¤   ¤   ¤   {
4c9c89 ¤   ¤   ¤   ¤   outputValue->asPtr ¤= outputDesc;
f54629 ¤   ¤   ¤   ¤   *outputValueSize ¤  = sizeof( *outputDesc );
61a3a6 ¤   ¤   ¤   }
bfaf5a
fccdcb ¤   ¤   ¤   break;
ac0fe4 ¤   ¤   }
7f1b52 ¤   ¤
ac9ae3 ¤   ¤   default:
0a5b34 ¤   ¤   {
a9e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
3ccdcb ¤   ¤   ¤   break;
520fe4 ¤   ¤   }
--2794 000717c70f840100291 Page 4 of pgpDialogOptions.c
a19371 ¤   }
93af5a
9bdeb7 ¤   return( err );
39efe6 }
9baf5a
c613fb ¤   PGPOptionListRef
5a4890 PGPOUICheckbox(
c935f6 ¤   PGPContextRef ¤ context,
9a8e7a ¤   PGPUInt32 ¤ ¤   itemID,
1befbb ¤   const char ¤¤   *title,
4d80da ¤   const char ¤¤   *description,¤  /* Can be NULL */
7a1be6 ¤   PGPUInt32 ¤ ¤   initialValue,
dbee6a ¤   PGPUInt32 ¤ ¤   *resultPtr)
92bb36 {
cd3ddd ¤   PGPOptionListRef¤   optionList;
b411b5 ¤   PGPOUICheckboxDesc¤ descriptor;
3098bd ¤   PGPOUICheckboxDesc¤ *allocatedDesc;
eb9eed ¤   char¤   ¤   ¤   ¤   emptyString[] = "";
a167c5 ¤
c99da5 ¤   pgpValidateOptionParam( IsntNull( resultPtr ) );
6e569d ¤   *resultPtr = 0;
0d1aa1 ¤   pgpValidateOptionContext( context );
68995e ¤   pgpValidateOptionParam( IsntNull( title ) );
cd67c5 ¤
32fa1a ¤   /* Booleanize value */
c575b6 ¤   if( initialValue > 0 )
ba8614 ¤   ¤   initialValue = 1;
7767c5 ¤
fa6c6e ¤   *resultPtr = initialValue;
cb67c5 ¤
9def60 ¤   pgpClearMemory( &descriptor, sizeof( descriptor ) );
ae67c5 ¤
9d9354 ¤   descriptor.itemID¤  ¤   = itemID;
eb2bb1 ¤   descriptor.valuePtr ¤   = resultPtr;
929ac3 ¤   descriptor.title¤   ¤   = title;
d367c5 ¤
97aa90 ¤   if( IsntNull( description ) )
ebc7a1 ¤   {
db5aa1 ¤   ¤   descriptor.description = description;
069371 ¤   }
c10e24 ¤   else
c0c7a1 ¤   {
d9284b ¤   ¤   descriptor.description = emptyString;
f99371 ¤   }
eb67c5 ¤
74ab0c ¤   if( IsntPGPError( CopyPGPOUICheckboxDesc( context, &descriptor,
8659dc ¤   ¤   ¤   ¤   &allocatedDesc ) ) )
34c7a1 ¤   {
598082 ¤   ¤   PGPOptionValue¤ ¤   value;
2d1b52 ¤   ¤
2a1ddc ¤   ¤   value.asPtr = allocatedDesc;
8a1b52 ¤   ¤
06b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
81f7f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_Checkbox,
977b37 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *allocatedDesc ),
4571e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   CheckboxOptionHandlerProc );
8c9371 ¤   }
b20e24 ¤   else
7bc7a1 ¤   {
3d1b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
7f9371 ¤   }
7f67c5 ¤
ef8233 ¤   return( optionList );
3defe6 }
58af5a
cb33c8 ¤   static void
eda980 FreePGPOUIPopupListDesc(
e2a1bc ¤   PGPContextRef¤  ¤   context,
a92639 ¤   PGPOUIPopupListDesc¤*desc)
28bb36 {
2213bb ¤   pgpAssertAddrValid( desc, PGPOUIPopupListDesc );
7167c5 ¤
--d2a1 0009b978cae40100291 Page 5 of pgpDialogOptions.c
dc5ace ¤   if( IsntNull( desc->title ) )
bcc7a1 ¤   {
7f267b ¤   ¤   pgpContextMemFree( context, (void *) desc->title );
b69287 ¤   ¤   desc->title = NULL;
819371 ¤   }
13af5a
450890 ¤   if( IsntNull( desc->description ) )
d9c7a1 ¤   {
fa3c8f ¤   ¤   pgpContextMemFree( context, (void *) desc->description );
737617 ¤   ¤   desc->description = NULL;
399371 ¤   }
9caf5a
989c25 ¤   if( IsntNull( desc->listItems ) )
29c7a1 ¤   {
e58ef4 ¤   ¤   PGPUInt32¤  listIndex;
e91b52 ¤   ¤
4f1099 ¤   ¤   for( listIndex = 0; listIndex < desc->numListItems; listIndex++ )
da5b34 ¤   ¤   {
495e65 ¤   ¤   ¤   if( IsntNull( desc->listItems[listIndex] ) )
cff776 ¤   ¤   ¤   {
24fcf5 ¤   ¤   ¤   ¤   pgpContextMemFree( context,·
adda0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   (void *) desc->listItems[listIndex] );
1fe372 ¤   ¤   ¤   ¤   desc->listItems[listIndex] = NULL;
a9a3a6 ¤   ¤   ¤   }
3f0fe4 ¤   ¤   }
ad1b52 ¤   ¤
343b60 ¤   ¤   pgpContextMemFree( context, (void *) desc->listItems );
1bb090 ¤   ¤   desc->listItems = NULL;
569371 ¤   }
1f67c5 ¤
906d7c ¤   pgpContextMemFree( context, desc );
69efe6 }
78af5a
a4a7b6 ¤   static char **
0f72b9 CopyPopupListItems(
29883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
684ecc ¤   const PGPOUIPopupListDesc¤  *srcDesc)
bcbb36 {
13b939 ¤   char¤   ¤   **listItems;
528e12 ¤   PGPError¤   err = kPGPError_NoErr;
d367c5 ¤
284c5a ¤   pgpAssertAddrValid( srcDesc, PGPOUIPopupListDesc );
7706e9 ¤   pgpAssert( srcDesc->numListItems > 0 );
3a062b ¤   pgpAssertAddrValid( srcDesc->listItems, char * );
dcaf5a
e56e18 ¤   listItems = (char **) pgpContextMemAlloc( context, srcDesc->numListItems *
7af718 ¤   ¤   ¤   ¤   ¤   ¤   sizeof( srcDesc->listItems[0] ),
fdc4f0 ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
1fd026 ¤   if( IsntNull( listItems ) )
14c7a1 ¤   {
a78ef4 ¤   ¤   PGPUInt32¤  listIndex;
831b52 ¤   ¤
49e434 ¤   ¤   for( listIndex = 0; listIndex < srcDesc->numListItems; listIndex++ )
0e5b34 ¤   ¤   {
dd8914 ¤   ¤   ¤   if( IsntNull( srcDesc->listItems[listIndex] ) )
1af776 ¤   ¤   ¤   {
6f62ea ¤   ¤   ¤   ¤   listItems[listIndex] = pgpAllocCString( context,
990f6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   srcDesc->listItems[listIndex] );
e71f5c ¤   ¤   ¤   ¤   if( IsNull( listItems[listIndex] ) )
7872c3 ¤   ¤   ¤   ¤   {
0bed29 ¤   ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
0914c3 ¤   ¤   ¤   ¤   ¤   break;
d62613 ¤   ¤   ¤   ¤   }
38a3a6 ¤   ¤   ¤   }
9c0fe4 ¤   ¤   }
2667c5 ¤
32d223 ¤   ¤   if( IsPGPError( err ) )
385b34 ¤   ¤   {
7db6e4 ¤   ¤   ¤   for( listIndex = 0; listIndex < srcDesc->numListItems; listIndex++ )
dcf776 ¤   ¤   ¤   {
674c3d ¤   ¤   ¤   ¤   if( IsntNull( listItems[listIndex] ) )
9b6a41 ¤   ¤   ¤   ¤   ¤   pgpContextMemFree( context, listItems[listIndex] );
--d61f 000b4a7084a40100291 Page 6 of pgpDialogOptions.c
cfa3a6 ¤   ¤   ¤   }
7987c7 ¤   ¤   ¤
0d68d5 ¤   ¤   ¤   pgpContextMemFree( context, listItems );
594c0e ¤   ¤   ¤   listItems = NULL;
c20fe4 ¤   ¤   }
2b9371 ¤   }
5067c5 ¤
1c1644 ¤   return( listItems );¤
bfefe6 }
15af5a
f466dd ¤   static PGPError
53a403 CopyPGPOUIPopupListDesc(
00883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
053074 ¤   const PGPOUIPopupListDesc¤  *srcDesc,
c184ec ¤   PGPOUIPopupListDesc¤¤   ¤   **destDesc)
3bbb36 {
f27759 ¤   PGPError¤   ¤   ¤   err = kPGPError_OutOfMemory;
7ac302 ¤   PGPOUIPopupListDesc¤*outDesc;
aa67c5 ¤
104c5a ¤   pgpAssertAddrValid( srcDesc, PGPOUIPopupListDesc );
f29b4f ¤   pgpAssertAddrValid( destDesc, PGPOUIPopupListDesc * );
a967c5 ¤
cf6b25 ¤   *destDesc = NULL;
2c67c5 ¤
7faf5c ¤   outDesc = (PGPOUIPopupListDesc *) pgpContextMemAlloc( context,
2a8d85 ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *outDesc ), kPGPMemoryMgrFlags_Clear );
3afd8c ¤   if( IsntNull( outDesc ) )
b2c7a1 ¤   {
606bbf ¤   ¤   *outDesc = *srcDesc;
aa1b52 ¤   ¤
959c9f ¤   ¤   pgpAssertAddrValid( srcDesc->title, char );
d45d26 ¤   ¤   pgpAssertAddrValid( srcDesc->description, char );
ee1b52 ¤   ¤
d2de9b ¤   ¤   outDesc->title ¤¤   ¤   = pgpAllocCString( context, srcDesc->title );
a37392 ¤   ¤   outDesc->description ¤  = pgpAllocCString( context,
5ef02e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   srcDesc->description );
53bd5b ¤   ¤   outDesc->listItems¤ ¤   = CopyPopupListItems( context, srcDesc );
8594aa ¤   ¤   ¤   ¤   ¤   ¤
d1d0ec ¤   ¤   if( IsntNull( outDesc->title ) &&
edfdf3 ¤   ¤   ¤   IsntNull( outDesc->description ) &&
d0a317 ¤   ¤   ¤   IsntNull( outDesc->listItems ) )
495b34 ¤   ¤   {
82fcc4 ¤   ¤   ¤   err = kPGPError_NoErr;
e20fe4 ¤   ¤   }
070e1d ¤   ¤   else
865b34 ¤   ¤   {
a99a72 ¤   ¤   ¤   FreePGPOUIPopupListDesc( context, outDesc );
c627a0 ¤   ¤   ¤   outDesc = NULL;
310fe4 ¤   ¤   }
569371 ¤   }
af67c5 ¤
0c3e34 ¤   *destDesc = outDesc;
8caf5a
6fdeb7 ¤   return( err );
f6efe6 }
2baf5a
8166dd ¤   static PGPError
bf082d PopupListOptionHandlerProc(
bb883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
fd0315 ¤   PGPOptionHandlerOperation ¤ operation,
6e1a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
1ad276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
31a79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
2948db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
954ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
bcbb36 {
277d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
b2f379 ¤   PGPOUIPopupListDesc¤*inputDesc;
f167c5 ¤
0c47bf ¤   pgpAssert( inputValueSize == sizeof( *inputDesc ) );
5aaf5a
b4958f ¤   (void) type;
--95a5 000086e535140100291 Page 7 of pgpDialogOptions.c
68a835 ¤   (void) inputValueSize;
8667c5 ¤
c9d5af ¤   inputDesc = (PGPOUIPopupListDesc *) inputValue.asPtr;
dfa620 ¤   pgpAssertAddrValid( inputDesc, PGPOUIPopupListDesc );
1867c5 ¤
f1b643 ¤   switch( operation )
c2c7a1 ¤   {
984885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
055b34 ¤   ¤   {
4b3909 ¤   ¤   ¤   FreePGPOUIPopupListDesc( context, inputDesc );
24cdcb ¤   ¤   ¤   break;
910fe4 ¤   ¤   }
bb87c7 ¤   ¤   ¤
900dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
fd5b34 ¤   ¤   {
91c433 ¤   ¤   ¤   PGPOUIPopupListDesc¤*outputDesc;
7baf5a
54bd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
86cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
fbaf5a
8fe7b1 ¤   ¤   ¤   err = CopyPGPOUIPopupListDesc( context, inputDesc, &outputDesc );
39698b ¤   ¤   ¤   if( IsntPGPError( err ) )
41f776 ¤   ¤   ¤   {
049c89 ¤   ¤   ¤   ¤   outputValue->asPtr ¤= outputDesc;
874629 ¤   ¤   ¤   ¤   *outputValueSize ¤  = sizeof( *outputDesc );
54a3a6 ¤   ¤   ¤   }
8eaf5a
02cdcb ¤   ¤   ¤   break;
380fe4 ¤   ¤   }
3a1b52 ¤   ¤
349ae3 ¤   ¤   default:
a55b34 ¤   ¤   {
22e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
8ecdcb ¤   ¤   ¤   break;
2e0fe4 ¤   ¤   }
909371 ¤   }
b0af5a
d6deb7 ¤   return( err );
99efe6 }
44af5a
8b13fb ¤   PGPOptionListRef
13091a PGPOUIPopupList(
4435f6 ¤   PGPContextRef ¤ context,
408e7a ¤   PGPUInt32 ¤ ¤   itemID,
14efbb ¤   const char ¤¤   *title,
0b80da ¤   const char ¤¤   *description,¤  /* Can be NULL */
75ee10 ¤   PGPUInt32¤  ¤   numListItems,
cd2087 ¤   const char¤ ¤   *listItems[],
ec1be6 ¤   PGPUInt32 ¤ ¤   initialValue,
0bee6a ¤   PGPUInt32 ¤ ¤   *resultPtr)
d9bb36 {
893ddd ¤   PGPOptionListRef¤   optionList;
eba1b8 ¤   PGPOUIPopupListDesc¤descriptor;
cc9970 ¤   PGPOUIPopupListDesc¤*allocatedDesc;
ca9eed ¤   char¤   ¤   ¤   ¤   emptyString[] = "";
9367c5 ¤
969da5 ¤   pgpValidateOptionParam( IsntNull( resultPtr ) );
4c569d ¤   *resultPtr = 0;
641aa1 ¤   pgpValidateOptionContext( context );
52995e ¤   pgpValidateOptionParam( IsntNull( title ) );
7e9e90 ¤   pgpValidateOptionParam( numListItems > 0 );
e4b404 ¤   pgpValidateOptionParam( IsntNull( listItems ) );
788125 ¤   pgpValidateOptionParam( initialValue <= numListItems );
6167c5 ¤
796c6e ¤   *resultPtr = initialValue;
8a67c5 ¤
06ef60 ¤   pgpClearMemory( &descriptor, sizeof( descriptor ) );
dc67c5 ¤
ed9354 ¤   descriptor.itemID¤  ¤   = itemID;
bf2bb1 ¤   descriptor.valuePtr ¤   = resultPtr;
299ac3 ¤   descriptor.title¤   ¤   = title;
08c33d ¤   descriptor.numListItems¤= numListItems;
--07c4 000241459e540100291 Page 8 of pgpDialogOptions.c
7c470a ¤   descriptor.listItems¤   = listItems;
c367c5 ¤
9faa90 ¤   if( IsntNull( description ) )
37c7a1 ¤   {
535aa1 ¤   ¤   descriptor.description = description;
a99371 ¤   }
6e0e24 ¤   else
81c7a1 ¤   {
57284b ¤   ¤   descriptor.description = emptyString;
869371 ¤   }
97af5a
45fe31 ¤   if( IsntPGPError( CopyPGPOUIPopupListDesc( context, &descriptor,
8859dc ¤   ¤   ¤   ¤   &allocatedDesc ) ) )
05c7a1 ¤   {
b88082 ¤   ¤   PGPOptionValue¤ ¤   value;
f21b52 ¤   ¤
611ddc ¤   ¤   value.asPtr = allocatedDesc;
131b52 ¤   ¤
1bb747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
ec7f2b ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_PopupList,
357b37 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( *allocatedDesc ),
abd4cc ¤   ¤   ¤   ¤   ¤   ¤   ¤   PopupListOptionHandlerProc );
cd9371 ¤   }
960e24 ¤   else
c7c7a1 ¤   {
f71b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
7f9371 ¤   }
d667c5 ¤
778233 ¤   return( optionList );
24efe6 }
a1af5a
ea08b7 static const PGPOptionType dialogOptionSet[] =
a2bb36 {
4a731c ¤   kPGPOptionType_Checkbox,
890c6f ¤   kPGPOptionType_PopupList
ae82f7 };
1baf5a
7913fb ¤   PGPOptionListRef
005c99 PGPOUIDialogOptions(
80a1bc ¤   PGPContextRef¤  ¤   context,
d14ae2 ¤   PGPOptionListRef ¤  firstOption,
593471 ¤   ...)
7bbb36 {
3a3ddd ¤   PGPOptionListRef¤   optionList;
c19dfd ¤   PGPOptionListRef¤   subOptions;
a201d3 ¤   va_list¤¤   ¤   ¤   args;
e567c5 ¤
f28679 ¤   pgpAssert( pgpContextIsValid( context ) );
30af5a
539b55 ¤   if ( pgpContextIsValid( context ) )
a1c7a1 ¤   {
9902ff ¤   ¤   va_start( args, firstOption );
6774c8 ¤   ¤   ¤   subOptions = pgpBuildOptionListArgs( context,
b5be6e ¤   ¤   ¤   ¤   ¤   ¤   FALSE, firstOption, args );
75c414 ¤   ¤   va_end( args );
cbaf5a
b06c1a ¤   ¤   if( IsntPGPError( pgpCheckOptionsInSet( subOptions,
6b154d ¤   ¤   ¤   ¤   dialogOptionSet, elemsof( dialogOptionSet ) ) ) )
d15b34 ¤   ¤   {
cfae28 ¤   ¤   ¤   optionList = pgpCreateCustomValueOptionList(
fb1d4f ¤   ¤   ¤   ¤   ¤   ¤   ¤   context, ·
b62d1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DialogOptions,
97ad40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Default, NULL,
e3af67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   0, subOptions, NULL);
df0fe4 ¤   ¤   }
d20e1d ¤   ¤   else
7f5b34 ¤   ¤   {
10e776 ¤   ¤   ¤   optionList = kPGPBadParamsOptionListRef;
c387c7 ¤   ¤   ¤
4895bc ¤   ¤   ¤   PGPFreeOptionList( subOptions );
a40fe4 ¤   ¤   }
249371 ¤   }
--7446 0003da4220840100291 Page 9 of pgpDialogOptions.c
060e24 ¤   else
c2c7a1 ¤   {
0f02ff ¤   ¤   va_start( args, firstOption );
8bed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
a1c414 ¤   ¤   va_end( args );
741b52 ¤   ¤
c6b46d ¤   ¤   optionList = kPGPBadParamsOptionListRef;
e89371 ¤   }
3567c5 ¤
788233 ¤   return( optionList );
d3efe6 }
66af5a
1c13fb ¤   PGPOptionListRef
4c5142 PGPOUIMinimumPassphraseLength(
5135f6 ¤   PGPContextRef ¤ context,
e0face ¤   PGPUInt32¤  ¤   minimumPassphraseLength)
f1bb36 {
5c3ddd ¤   PGPOptionListRef¤   optionList;
990cfd ¤   PGPOptionValue¤ ¤   value;
6e67c5 ¤
a91aa1 ¤   pgpValidateOptionContext( context );
3b67c5 ¤
cb9afb ¤   value.asUInt = minimumPassphraseLength;
2b67c5 ¤
b60b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
c3dace ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_MinPassphraseLength,
ad26bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
6367c5 ¤
578233 ¤   return( optionList );
5cefe6 }
0aaf5a
2213fb ¤   PGPOptionListRef
7806ef PGPOUIMinimumPassphraseQuality(
6835f6 ¤   PGPContextRef ¤ context,
e30b24 ¤   PGPUInt32¤  ¤   minimumPassphraseQuality)
35bb36 {
ea3ddd ¤   PGPOptionListRef¤   optionList;
690cfd ¤   PGPOptionValue¤ ¤   value;
8267c5 ¤
ac1aa1 ¤   pgpValidateOptionContext( context );
5ff804 ¤   pgpValidateOptionParam( minimumPassphraseQuality <= 100 );
1267c5 ¤
97fb66 ¤   value.asUInt = minimumPassphraseQuality;
4d67c5 ¤
1b0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
154c01 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_MinPassphraseQuality,
4826bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
7c67c5 ¤
eb8233 ¤   return( optionList );
55efe6 }
f3af5a
e013fb ¤   PGPOptionListRef
c234f8 PGPOUIShowPassphraseQuality(
c935f6 ¤   PGPContextRef ¤ context,
1d6789 ¤   PGPBoolean¤ ¤   showPassphraseQuality)
6cbb36 {
5b3ddd ¤   PGPOptionListRef¤   optionList;
770cfd ¤   PGPOptionValue¤ ¤   value;
0467c5 ¤
ea1aa1 ¤   pgpValidateOptionContext( context );
1267c5 ¤
104379 ¤   value.asUInt = showPassphraseQuality;
6067c5 ¤
0b0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
310cb8 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ShowPassphraseQuality,
f626bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
cf67c5 ¤
5e8233 ¤   return( optionList );
c0efe6 }
eaaf5a
4013fb ¤   PGPOptionListRef
3d9dfd PGPOUIVerifyPassphrase(
--67ba 0006121856640100291 Page 10 of pgpDialogOptions.c
ac35f6 ¤   PGPContextRef ¤ context,
4eb842 ¤   PGPBoolean¤ ¤   verifyPassphrase)
1ebb36 {
fb3ddd ¤   PGPOptionListRef¤   optionList;
890cfd ¤   PGPOptionValue¤ ¤   value;
f867c5 ¤
701aa1 ¤   pgpValidateOptionContext( context );
5067c5 ¤
eb7b33 ¤   value.asUInt = verifyPassphrase;
6f67c5 ¤
de0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
ad77a9 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_VerifyPassphrase,
6226bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
7a67c5 ¤
c58233 ¤   return( optionList );
abefe6 }
8eaf5a
dc13fb ¤   PGPOptionListRef
74cd7f PGPOUIFindMatchingKey(
1335f6 ¤   PGPContextRef ¤ context,
88584a ¤   PGPBoolean¤ ¤   findMatchingKey)
70bb36 {
2f3ddd ¤   PGPOptionListRef¤   optionList;
f70cfd ¤   PGPOptionValue¤ ¤   value;
3967c5 ¤
541aa1 ¤   pgpValidateOptionContext( context );
7167c5 ¤
07986d ¤   value.asUInt = findMatchingKey;
c767c5 ¤
cd0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
40de06 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_FindMatchingKey,
1d26bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
2467c5 ¤
858233 ¤   return( optionList );
21efe6 }
f7af5a
155270 PGPOptionListRef
ff75d6 PGPOUITextUI(
3035f6 ¤   PGPContextRef ¤ context,
ba06d8 ¤   PGPBoolean¤ ¤   textUI)
2ebb36 {
533ddd ¤   PGPOptionListRef¤   optionList;
5e0cfd ¤   PGPOptionValue¤ ¤   value;
9767c5 ¤
991aa1 ¤   pgpValidateOptionContext( context );
f567c5 ¤
eed9bf ¤   value.asUInt = textUI;
1767c5 ¤
970b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
c052e0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···kPGPOptionType_TextUI,
66d473 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···&value,
74ec33 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···sizeof( PGPUInt32 ),
14f100 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···NULL );
dd67c5 ¤
6d8233 ¤   return( optionList );
61efe6 }
aeaf5a
f113fb ¤   PGPOptionListRef
13f685 PGPOUIDefaultKey(
5d35f6 ¤   PGPContextRef ¤ context,
1aa402 ¤   PGPKeyRef¤  ¤   defaultKey)
5cbb36 {
a53ddd ¤   PGPOptionListRef¤   optionList;
bc0cfd ¤   PGPOptionValue¤ ¤   value;
6967c5 ¤
971aa1 ¤   pgpValidateOptionContext( context );
3067c5 ¤
faa441 ¤   value.asKeyRef = defaultKey;
b567c5 ¤
800b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
dec3df ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DefaultKey,
61ae94 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPKeyRef ), NULL );
--55e7 000a5155db440100291 Page 11 of pgpDialogOptions.c
2a67c5 ¤
c28233 ¤   return( optionList );
08efe6 }
faaf5a
d913fb ¤   PGPOptionListRef
dd61ba PGPOUIDefaultRecipients(
f797bc ¤   PGPContextRef ¤ ¤   ¤   context,
56ef02 ¤   PGPUInt32 ¤ ¤   ¤   ¤   numRecipients,
658a9a ¤   const PGPRecipientSpec ¤recipients[])
90bb36 {
ff710b ¤   PGPOptionListRef¤   ¤   optionList;
6a75d6 ¤   PGPBoolean¤ ¤   ¤   ¤   badList = FALSE;
c206fa ¤   PGPUInt32¤  ¤   ¤   ¤   recipientIndex;
0c8599 ¤   const PGPRecipientSpec¤ *curRecipient;
ae67c5 ¤
c51aa1 ¤   pgpValidateOptionContext( context );
c5799b ¤   pgpValidateOptionParam( numRecipients > 0 );
351a19 ¤   pgpValidateOptionParam( IsntNull( recipients ) );
9567c5 ¤
bbc0e8 ¤   curRecipient = &recipients[0];
4f67c5 ¤
da3348 ¤   for( recipientIndex = 0; recipientIndex < numRecipients; recipientIndex++ )
c6c7a1 ¤   {
e28e8d ¤   ¤   switch( curRecipient->type )
045b34 ¤   ¤   {
d0f6c5 ¤   ¤   ¤   case kPGPRecipientSpecType_Key:
bef776 ¤   ¤   ¤   {
022a7e ¤   ¤   ¤   ¤   if( ! PGPKeyRefIsValid( curRecipient->u.key ) )
0c72c3 ¤   ¤   ¤   ¤   {
b104c5 ¤   ¤   ¤   ¤   ¤   pgpDebugMsg( "PGPOUIDefaultRecipients() Invalid key ref" );
c862d5 ¤   ¤   ¤   ¤   ¤   badList = TRUE;
2c2613 ¤   ¤   ¤   ¤   }
532b85 ¤   ¤   ¤   ¤
70f622 ¤   ¤   ¤   ¤   break;
1aa3a6 ¤   ¤   ¤   }
24af5a
e1c72d ¤   ¤   ¤   case kPGPRecipientSpecType_UserID:
87f776 ¤   ¤   ¤   {
4b9eda ¤   ¤   ¤   ¤   if( curRecipient->u.userIDStr[0] == 0 )
eb72c3 ¤   ¤   ¤   ¤   {
9e8006 ¤   ¤   ¤   ¤   ¤   pgpDebugMsg( "PGPOUIDefaultRecipients() Empty user ID" );
7a62d5 ¤   ¤   ¤   ¤   ¤   badList = TRUE;
1d2613 ¤   ¤   ¤   ¤   }
532b85 ¤   ¤   ¤   ¤
2af622 ¤   ¤   ¤   ¤   break;
a3a3a6 ¤   ¤   ¤   }
7c87c7 ¤   ¤   ¤
9aabc6 ¤   ¤   ¤   case kPGPRecipientSpecType_KeyID:
c8f622 ¤   ¤   ¤   ¤   break;
4a2b85 ¤   ¤   ¤   ¤
5cdb68 ¤   ¤   ¤   default:
0cf776 ¤   ¤   ¤   {
3b8833 ¤   ¤   ¤   ¤   pgpDebugMsg( "PGPOUIDefaultRecipients(): Unknown spec type" );
6387c7 ¤   ¤   ¤
c6e929 ¤   ¤   ¤   ¤   badList = TRUE;
f5f622 ¤   ¤   ¤   ¤   break;
40a3a6 ¤   ¤   ¤   }
ea0fe4 ¤   ¤   }
b967c5 ¤
3450c5 ¤   ¤   if( badList )
6fcdcb ¤   ¤   ¤   break;
dc87c7 ¤   ¤   ¤
16eabd ¤   ¤   ++curRecipient;
409371 ¤   }
6f67c5 ¤
0cd94b ¤   if( ! badList )
47c7a1 ¤   {
b0d553 ¤   ¤   optionList = pgpCreateBufferOptionList( context,
4993f0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DefaultRecipients,
009d4f ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients, numRecipients *
631a50 ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( recipients[0] ) );
a59371 ¤   }
--02f7 0005124eab940100291 Page 12 of pgpDialogOptions.c
060e24 ¤   else
c2c7a1 ¤   {
63b46d ¤   ¤   optionList = kPGPBadParamsOptionListRef;
819371 ¤   }
d48233 ¤   return( optionList );
6fefe6 }
75af5a
7c13fb ¤   PGPOptionListRef
5f7446 PGPOUIDisplayMarginalValidity(
e935f6 ¤   PGPContextRef ¤ context,
6cf827 ¤   PGPBoolean¤ ¤   displayMarginalValidity)
f4bb36 {
933ddd ¤   PGPOptionListRef¤   optionList;
eb0cfd ¤   PGPOptionValue¤ ¤   value;
9267c5 ¤
141aa1 ¤   pgpValidateOptionContext( context );
0467c5 ¤
cabfff ¤   value.asUInt = displayMarginalValidity;
2867c5 ¤
7a0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
b59a67 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DisplayMarginalValidity,
4c26bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
dd67c5 ¤
ff8233 ¤   return( optionList );
3fefe6 }
81af5a
2813fb ¤   PGPOptionListRef
f8a066 PGPOUIIgnoreMarginalValidity(
e135f6 ¤   PGPContextRef ¤ context,
7a813f ¤   PGPBoolean¤ ¤   ignoreMarginalValidity)
6bbb36 {
b53ddd ¤   PGPOptionListRef¤   optionList;
870cfd ¤   PGPOptionValue¤ ¤   value;
5e67c5 ¤
1d1aa1 ¤   pgpValidateOptionContext( context );
5267c5 ¤
3fe098 ¤   value.asUInt = ignoreMarginalValidity;
7467c5 ¤
590b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
cee65b ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_IgnoreMarginalValidity,
9c26bd ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPUInt32 ), NULL );
7267c5 ¤
4f8233 ¤   return( optionList );
13efe6 }
83af5a
7766dd ¤   static PGPError
975110 GroupSetOptionHandlerProc(
a7883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
df0315 ¤   PGPOptionHandlerOperation ¤ operation,
bd1a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
84d276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
7ca79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
1a48db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
0a4ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
17bb36 {
6b8e12 ¤   PGPError¤   err = kPGPError_NoErr;
0067c5 ¤
f56d02 ¤   (void) context;
42958f ¤   (void) type;
59a835 ¤   (void) inputValueSize;
0367c5 ¤
c7b643 ¤   switch( operation )
f6c7a1 ¤   {
234885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
955b34 ¤   ¤   {
223814 ¤   ¤   ¤   PGPFreeGroupSet( inputValue.asGroupSetRef );
76cdcb ¤   ¤   ¤   break;
3a0fe4 ¤   ¤   }
9c87c7 ¤   ¤   ¤
110dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
665b34 ¤   ¤   {
511d81 ¤   ¤   ¤   err = PGPCopyGroupSet( inputValue.asGroupSetRef,
--2ea3 000fe1b252e40100291 Page 13 of pgpDialogOptions.c
d5207e ¤   ¤   ¤   ¤   ¤   ¤   &outputValue->asGroupSetRef );
09698b ¤   ¤   ¤   if( IsntPGPError( err ) )
d6f776 ¤   ¤   ¤   {
93f058 ¤   ¤   ¤   ¤   *outputValueSize = sizeof( outputValue->asGroupSetRef );
63a3a6 ¤   ¤   ¤   }
d5af5a
3ccdcb ¤   ¤   ¤   break;
d20fe4 ¤   ¤   }
171b52 ¤   ¤
0c9ae3 ¤   ¤   default:
3a5b34 ¤   ¤   {
99e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
70cdcb ¤   ¤   ¤   break;
af0fe4 ¤   ¤   }
c59371 ¤   }
4aaf5a
84deb7 ¤   return( err );
9befe6 }
dcaf5a
0413fb ¤   PGPOptionListRef
76d3d6 PGPOUIRecipientGroups(
a035f6 ¤   PGPContextRef ¤ context,
a1c345 ¤   PGPGroupSetRef¤ groupSet)
2cbb36 {
c93ddd ¤   PGPOptionListRef¤   optionList;
990cfd ¤   PGPOptionValue¤ ¤   value;
9167c5 ¤
761aa1 ¤   pgpValidateOptionContext( context );
3c9888 ¤   pgpValidateOptionParam( PGPGroupSetRefIsValid( groupSet ) );
7767c5 ¤
fb5993 ¤   if( IsntPGPError( PGPCopyGroupSet( groupSet, &value.asGroupSetRef ) ) )
9dc7a1 ¤   {
57b747 ¤   ¤   optionList = pgpCreateStandardValueOptionList( context, ·
464ff8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RecipientGroups,
a78bc4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( groupSet ),
2ec994 ¤   ¤   ¤   ¤   ¤   ¤   ¤   GroupSetOptionHandlerProc );
a59371 ¤   }
d80e24 ¤   else
c6c7a1 ¤   {
e21b9c ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
4a9371 ¤   }
e467c5 ¤
4e8233 ¤   return( optionList );
44efe6 }
f4af5a
4a13fb ¤   PGPOptionListRef
f75ca8 PGPOUIEnforceAdditionalRecipientRequests(
dc7aa2 ¤   PGPContextRef ¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   context,
95eebd ¤   PGPAdditionalRecipientRequestEnforcement ¤  enforcement,
5ecac0 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   alwaysDisplayDialogWithARRs)
d0bb36 {
6f3ddd ¤   PGPOptionListRef¤   optionList;
820cfd ¤   PGPOptionValue¤ ¤   value;
3167c5 ¤
151aa1 ¤   pgpValidateOptionContext( context );
9667c5 ¤
025e6f ¤   value.asARRParams.enforcement ¤ = enforcement;
f75561 ¤   value.asARRParams.displayDialog = ( alwaysDisplayDialogWithARRs != 0 );
c3af5a
b80b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
1b6a69 ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_ARREnforcement,
784740 ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( PGPOUIARRParamsDesc ), NULL );
7367c5 ¤
a98233 ¤   return( optionList );
5fefe6 }
83af5a
4c66dd ¤   static PGPError
05d750 KeyServerOptionHandlerProc(
da883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
b30315 ¤   PGPOptionHandlerOperation ¤ operation,
e71a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
fed276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
--4602 0006c71cfe740100291 Page 14 of pgpDialogOptions.c
4ba79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
6748db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
f14ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
d4bb36 {
a38e12 ¤   PGPError¤   err = kPGPError_NoErr;
d167c5 ¤
416d02 ¤   (void) context;
eda835 ¤   (void) inputValueSize;
699fb0 ¤   (void) outputValueSize;
ffa57e ¤   (void) outputValue;
a067c5 ¤
a2b643 ¤   switch( operation )
55c7a1 ¤   {
064885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
4f5b34 ¤   ¤   {
0d1a0a ¤   ¤   ¤   switch( type )
05f776 ¤   ¤   ¤   {
6a625f ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchFilter:
4e4c0f ¤   ¤   ¤   ¤   ¤   PGPFreeFilter( inputValue.asFilterRef );
1514c3 ¤   ¤   ¤   ¤   ¤   break;
f42b85 ¤   ¤   ¤   ¤
66b9bb ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchKeySet:
2b2edf ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( inputValue.asKeySetRef );
5614c3 ¤   ¤   ¤   ¤   ¤   break;
5a2b85 ¤   ¤   ¤   ¤
706ab9 ¤   ¤   ¤   ¤   default:
0214c3 ¤   ¤   ¤   ¤   ¤   break;
94a3a6 ¤   ¤   ¤   }
5687c7 ¤   ¤   ¤
77cdcb ¤   ¤   ¤   break;
270fe4 ¤   ¤   }
b987c7 ¤   ¤   ¤
540dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
dc5b34 ¤   ¤   {
a41a0a ¤   ¤   ¤   switch( type )
f4f776 ¤   ¤   ¤   {
79625f ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchFilter:
07e8d2 ¤   ¤   ¤   ¤   ¤   PGPIncFilterRefCount( inputValue.asFilterRef );
d714c3 ¤   ¤   ¤   ¤   ¤   break;
2b2b85 ¤   ¤   ¤   ¤
59b9bb ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchKeySet:
a8d781 ¤   ¤   ¤   ¤   ¤   PGPIncKeySetRefCount( inputValue.asKeySetRef );
3114c3 ¤   ¤   ¤   ¤   ¤   break;
de2b85 ¤   ¤   ¤   ¤
596ab9 ¤   ¤   ¤   ¤   default:
cd14c3 ¤   ¤   ¤   ¤   ¤   break;
83a3a6 ¤   ¤   ¤   }
c00fe4 ¤   ¤   }
381b52 ¤   ¤
049ae3 ¤   ¤   default:
7f5b34 ¤   ¤   {
c6e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
19cdcb ¤   ¤   ¤   break;
aa0fe4 ¤   ¤   }
139371 ¤   }
60af5a
7adeb7 ¤   return( err );
f2efe6 }
97af5a
fa13fb ¤   PGPOptionListRef
fbcedd PGPOUIKeyServerSearchFilter(
e7520e ¤   PGPContextRef¤  context,
12e39c ¤   PGPFilterRef ¤  filter)
aabb36 {
053ddd ¤   PGPOptionListRef¤   optionList;
930cfd ¤   PGPOptionValue¤ ¤   value;
2867c5 ¤
171aa1 ¤   pgpValidateOptionContext( context );
d645db ¤   pgpValidateOptionParam( PGPFilterRefIsValid( filter ) );
5067c5 ¤
778d9b ¤   value.asFilterRef = filter;
6caf5a
--4982 0008e18e96e40100291 Page 15 of pgpDialogOptions.c
e871b6 ¤   PGPIncFilterRefCount( filter );
60af5a
2e0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
624a84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyServerSearchFilter,
741a51 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( filter ),
97ba0a ¤   ¤   ¤   ¤   ¤   ¤   ¤   KeyServerOptionHandlerProc );
9e67c5 ¤
818233 ¤   return( optionList );
68efe6 }
f2af5a
7c13fb ¤   PGPOptionListRef
421539 PGPOUIKeyServerSearchKeySet(
46520e ¤   PGPContextRef¤  context,
355fe5 ¤   PGPKeySetRef ¤  keySet)
03bb36 {
f83ddd ¤   PGPOptionListRef¤   optionList;
2f0cfd ¤   PGPOptionValue¤ ¤   value;
1f67c5 ¤
7c1aa1 ¤   pgpValidateOptionContext( context );
d05c8a ¤   pgpValidateOptionParam( PGPKeySetRefIsValid( keySet ) );
5067c5 ¤
d5ed5b ¤   value.asKeySetRef = keySet;
59af5a
451bb5 ¤   PGPIncKeySetRefCount( keySet );
17af5a
eb0b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
729160 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyServerSearchKeySet,
5efcf6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( keySet ),
f7ba0a ¤   ¤   ¤   ¤   ¤   ¤   ¤   KeyServerOptionHandlerProc );
0067c5 ¤
618233 ¤   return( optionList );
5aefe6 }
65af5a
b513fb ¤   PGPOptionListRef
a95ebc PGPOUIKeyServerSearchKeyIDList(
4f520e ¤   PGPContextRef¤  context,
5382f8 ¤   PGPUInt32 ¤ ¤   keyIDCount,
bc6cd5 ¤   const PGPKeyID ¤keyIDList[])
2ebb36 {
d63ddd ¤   PGPOptionListRef¤   optionList;
e067c5 ¤
611aa1 ¤   pgpValidateOptionContext( context );
75866e ¤   pgpValidateOptionParam( IsntNull( keyIDList ) );
0732af ¤   pgpValidateOptionParam( keyIDCount > 0 );
9167c5 ¤
21ba60 ¤   optionList = pgpCreateBufferOptionList( context,
dce09d ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyServerSearchKeyIDList,
583086 ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDList, keyIDCount * sizeof( keyIDList[0] ) );
4267c5 ¤
118233 ¤   return( optionList );
97efe6 }
77af5a
bf13fb ¤   PGPOptionListRef
1f7518 PGPOUIKeyServerSearchKey(
ab520e ¤   PGPContextRef¤  context,
19d4db ¤   PGPKeyRef ¤ ¤   key)
39bb36 {
ff3ddd ¤   PGPOptionListRef¤   optionList;
250cfd ¤   PGPOptionValue¤ ¤   value;
5667c5 ¤
961aa1 ¤   pgpValidateOptionContext( context );
b8141f ¤   pgpValidateOptionParam( PGPKeyRefIsValid( key ) );
3367c5 ¤
ecadde ¤   value.asKeyRef = key;
88af5a
d60b5e ¤   optionList = pgpCreateStandardValueOptionList( context, ·
939cb5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyServerSearchKey,
5a3158 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &value, sizeof( key ), NULL );
b567c5 ¤
108233 ¤   return( optionList );
a6efe6 }
8eaf5a
--691d 0003780a3e440100291 Page 16 of pgpDialogOptions.c
2633c8 ¤   static void
ce89fd FreePGPOUIKeyServerParamsDesc(
22ca71 ¤   PGPContextRef ¤ ¤   ¤   ¤   context,
770918 ¤   PGPOUIKeyServerParamsDesc ¤ *desc)
61bb36 {
66e354 ¤   pgpAssertAddrValid( desc, PGPOUIKeyServerParamsDesc );
ab67c5 ¤
31970c ¤   if( IsntNull( desc->serverList ) )
63c7a1 ¤   {
f9e85c ¤   ¤   PGPUInt32¤  specIndex;
a9af5a
520ecb ¤   ¤   for( specIndex = 0; specIndex < desc->serverCount; specIndex++)
285b34 ¤   ¤   {
f821fb ¤   ¤   ¤   PGPKeyServerSpec¤   *spec = &desc->serverList[specIndex];
4987c7 ¤   ¤   ¤
130916 ¤   ¤   ¤   if( IsntNull( spec->serverName ) )
7d9ddd ¤   ¤   ¤   ¤   pgpContextMemFree( context, (char *) spec->serverName );
032b85 ¤   ¤   ¤   ¤
1320df ¤   ¤   ¤   if( PGPKeyServerRefIsValid( spec->server ) )
2ae5bf ¤   ¤   ¤   ¤   PGPFreeKeyServer( spec->server );
5c0fe4 ¤   ¤   }
b51b52 ¤   ¤
b653f2 ¤   ¤   PGPFreeData( (PGPKeyServerSpec *) desc->serverList );
3b94fc ¤   ¤   desc->serverList = NULL;
fa9371 ¤   }
0067c5 ¤
71db49 ¤   PGPFreeData( desc );
f5efe6 }
c0af5a
2066dd ¤   static PGPError
3bfc56 CopyPGPOUIKeyServerParamsDesc(
58284d ¤   PGPContextRef¤  ¤   ¤   ¤   ¤   context,
0a13cc ¤   const PGPOUIKeyServerParamsDesc¤*srcDesc,
4de287 ¤   PGPOUIKeyServerParamsDesc¤  ¤   **destDesc)
7abb36 {
ce3146 ¤   PGPError¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
f841be ¤   PGPOUIKeyServerParamsDesc¤  *outDesc;
ea67c5 ¤
337af2 ¤   pgpAssertAddrValid( srcDesc, PGPOUIKeyServerParamsDesc );
350759 ¤   pgpAssertAddrValid( destDesc, PGPOUIKeyServerParamsDesc * );
ed67c5 ¤
cd6b25 ¤   *destDesc = NULL;
2b67c5 ¤
100b08 ¤   outDesc = (PGPOUIKeyServerParamsDesc *) PGPNewData(
08803b ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( context ),
228d85 ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *outDesc ), kPGPMemoryMgrFlags_Clear );
aafd8c ¤   if( IsntNull( outDesc ) )
09c7a1 ¤   {
f90c5b ¤   ¤   PGPSize¤dataSize;
171b52 ¤   ¤
da94ff ¤   ¤   pgpAssertAddrValid( srcDesc->serverList, PGPKeyServerSpec );
511b52 ¤   ¤
386bbf ¤   ¤   *outDesc = *srcDesc;
4bdc17 ¤   ¤   dataSize = srcDesc->serverCount * sizeof( PGPKeyServerSpec );
be1b52 ¤   ¤
2db4e9 ¤   ¤   outDesc->serverList = (PGPKeyServerSpec *) PGPNewData(
43ce02 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( context ),
316b95 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize, 0 );
80f902 ¤   ¤   if( IsntNull( outDesc->serverList ) )
795b34 ¤   ¤   {
fb6423 ¤   ¤   ¤   PGPUInt32¤  specIndex;
b187c7 ¤   ¤   ¤
1e8c95 ¤   ¤   ¤   pgpCopyMemory( srcDesc->serverList,
26fd06 ¤   ¤   ¤   ¤   ¤   ¤   (PGPKeyServerSpec *) outDesc->serverList, dataSize );
e687c7 ¤   ¤   ¤
06bf6f ¤   ¤   ¤   /* Need to copy server names and domains */
9b096d ¤   ¤   ¤   for(specIndex = 0; specIndex < srcDesc->serverCount; specIndex++)
8bf776 ¤   ¤   ¤   {
cca75f ¤   ¤   ¤   ¤   PGPKeyServerSpec¤   *spec = &outDesc->serverList[specIndex];
592b85 ¤   ¤   ¤   ¤
29633e ¤   ¤   ¤   ¤   spec->serverName = NULL;
372b85 ¤   ¤   ¤   ¤
--0f50 000d4ff558340100291 Page 17 of pgpDialogOptions.c
7d066a ¤   ¤   ¤   ¤   if( PGPKeyServerRefIsValid( spec->server ) )
3c72c3 ¤   ¤   ¤   ¤   {
c214cd ¤   ¤   ¤   ¤   ¤   PGPIncKeyServerRefCount( spec->server );
592613 ¤   ¤   ¤   ¤   }
4fa3a6 ¤   ¤   ¤   }
f5af5a
2b096d ¤   ¤   ¤   for(specIndex = 0; specIndex < srcDesc->serverCount; specIndex++)
e3f776 ¤   ¤   ¤   {
2bb5f0 ¤   ¤   ¤   ¤   PGPKeyServerSpec¤   *srcSpec;
341d9a ¤   ¤   ¤   ¤   PGPKeyServerSpec¤   *destSpec;
ef2b85 ¤   ¤   ¤   ¤
847bab ¤   ¤   ¤   ¤   srcSpec ¤   = &srcDesc->serverList[specIndex];
204a03 ¤   ¤   ¤   ¤   destSpec ¤  = &outDesc->serverList[specIndex];
2eaf5a
b70c73 ¤   ¤   ¤   ¤   if( IsntNull( srcSpec->serverName ) )
4d72c3 ¤   ¤   ¤   ¤   {
873838 ¤   ¤   ¤   ¤   ¤   destSpec->serverName = pgpAllocCString( context,
4422d4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   srcSpec->serverName );
1fd2ce ¤   ¤   ¤   ¤   ¤   if( IsNull( destSpec->serverName ) )
9dbe32 ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
b52613 ¤   ¤   ¤   ¤   }
8c2b85 ¤   ¤   ¤   ¤
639c8a ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
2b14c3 ¤   ¤   ¤   ¤   ¤   break;
c9a3a6 ¤   ¤   ¤   }
f10fe4 ¤   ¤   }
660e1d ¤   ¤   else
945b34 ¤   ¤   {
ccb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
fb0fe4 ¤   ¤   }
c01b52 ¤   ¤
d7d223 ¤   ¤   if( IsPGPError( err ) )
ca5b34 ¤   ¤   {
4ea2c0 ¤   ¤   ¤   FreePGPOUIKeyServerParamsDesc( context, outDesc );
9027a0 ¤   ¤   ¤   outDesc = NULL;
cd0fe4 ¤   ¤   }
9f9371 ¤   }
1a0e24 ¤   else
eac7a1 ¤   {
4bbce1 ¤   ¤   err = kPGPError_OutOfMemory;
dc9371 ¤   }
4267c5 ¤
ef3e34 ¤   *destDesc = outDesc;
43af5a
c9deb7 ¤   return( err );
43efe6 }
0faf5a
8966dd ¤   static PGPError
9a4274 KeyServerParamsOptionHandlerProc(
0e883c ¤   PGPContextRef¤  ¤   ¤   ¤   context,
430315 ¤   PGPOptionHandlerOperation ¤ operation,
491a9b ¤   PGPOptionType¤  ¤   ¤   ¤   type,
07d276 ¤   PGPOptionValue¤ ¤   ¤   ¤   inputValue,
e8a79f ¤   PGPSize ¤   ¤   ¤   ¤   ¤   inputValueSize,
a048db ¤   PGPOptionValue ¤¤   ¤   ¤   *outputValue,
944ea9 ¤   PGPSize¤¤   ¤   ¤   ¤   ¤   *outputValueSize)
d7bb36 {
483146 ¤   PGPError¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
59c7ad ¤   PGPOUIKeyServerParamsDesc¤  *inputDesc;
f867c5 ¤
8347bf ¤   pgpAssert( inputValueSize == sizeof( *inputDesc ) );
8eaf5a
55958f ¤   (void) type;
8fa835 ¤   (void) inputValueSize;
9167c5 ¤
8894d6 ¤   inputDesc = (PGPOUIKeyServerParamsDesc *) inputValue.asPtr;
4df1b3 ¤   pgpAssertAddrValid( inputDesc, PGPOUIKeyServerParamsDesc );
f067c5 ¤
33b643 ¤   switch( operation )
ccc7a1 ¤   {
734885 ¤   ¤   case kPGPOptionHandler_FreeDataOperation:
d45b34 ¤   ¤   {
--fd2e 00043521b7240100291 Page 18 of pgpDialogOptions.c
678d1c ¤   ¤   ¤   FreePGPOUIKeyServerParamsDesc( context, inputDesc );
5bcdcb ¤   ¤   ¤   break;
f30fe4 ¤   ¤   }
a887c7 ¤   ¤   ¤
740dbe ¤   ¤   case kPGPOptionHandler_CopyDataOperation:
195b34 ¤   ¤   {
15567d ¤   ¤   ¤   PGPOUIKeyServerParamsDesc¤  *outputDesc;
07af5a
70bd20 ¤   ¤   ¤   pgpAssertAddrValid( outputValue, PGPOptionValue );
d3cdea ¤   ¤   ¤   pgpAssertAddrValid( outputValueSize, PGPSize );
35af5a
d2d973 ¤   ¤   ¤   err = CopyPGPOUIKeyServerParamsDesc( context, inputDesc,
b88177 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &outputDesc );
66698b ¤   ¤   ¤   if( IsntPGPError( err ) )
72f776 ¤   ¤   ¤   {
769c89 ¤   ¤   ¤   ¤   outputValue->asPtr ¤= outputDesc;
594629 ¤   ¤   ¤   ¤   *outputValueSize ¤  = sizeof( *outputDesc );
b0a3a6 ¤   ¤   ¤   }
f0af5a
9acdcb ¤   ¤   ¤   break;
9e0fe4 ¤   ¤   }
861b52 ¤   ¤
1b9ae3 ¤   ¤   default:
7f5b34 ¤   ¤   {
91e119 ¤   ¤   ¤   err = kPGPError_UnknownRequest;
fecdcb ¤   ¤   ¤   break;
a60fe4 ¤   ¤   }
459371 ¤   }
bbaf5a
42deb7 ¤   return( err );
6aefe6 }
0faf5a
2613fb ¤   PGPOptionListRef
4a53fe PGPOUIKeyServerUpdateParams(
4b97bc ¤   PGPContextRef ¤ ¤   ¤   context,
683f0a ¤   PGPUInt32 ¤ ¤   ¤   ¤   serverCount,
ddcc83 ¤   const PGPKeyServerSpec ¤serverList[],
625175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
f2101a ¤   PGPBoolean ¤¤   ¤   ¤   searchBeforeDisplay,
95e360 ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys,
86e88a ¤   PGPOptionListRef ¤  ¤   firstOption,
ce3471 ¤   ...)
c4bb36 {
773ddd ¤   PGPOptionListRef¤   optionList;
7501d3 ¤   va_list¤¤   ¤   ¤   args;
7367c5 ¤
bba362 ¤   if( IsntNull( foundKeys ) )
fbb2f9 ¤   ¤   *foundKeys = kInvalidPGPKeySetRef;
1067c5 ¤
770a1f ¤   pgpAssert( IsntNull( foundKeys ) );
faa76d ¤   pgpAssert( PGPContextRefIsValid( context ) );
0960d1 ¤   pgpAssert( IsntNull( serverList ) );
acb3a5 ¤   pgpAssert( serverCount > 0 );
2067c5 ¤
e901cf ¤   if( PGPContextRefIsValid( context ) &&
b32996 ¤   ¤   IsntNull( foundKeys ) &&
f0de06 ¤   ¤   IsntNull( serverList ) &&
f7ea57 ¤   ¤   serverCount > 0 )
1ec7a1 ¤   {
d6d94c ¤   ¤   PGPOptionListRef¤   ¤   ¤   subOptions;
8a8d3c ¤   ¤   PGPOUIKeyServerParamsDesc¤  descriptor;
d9606a ¤   ¤   PGPOUIKeyServerParamsDesc¤  *allocatedDesc;
1baf5a
2d02ff ¤   ¤   va_start( args, firstOption );
f674c8 ¤   ¤   ¤   subOptions = pgpBuildOptionListArgs( context,
51307f ¤   ¤   ¤   ¤   FALSE, firstOption, args );
01c414 ¤   ¤   va_end( args );
e0af5a
11c9d5 ¤   ¤   pgpClearMemory( &descriptor, sizeof( descriptor ) );
6b1b52 ¤   ¤
4f14a5 ¤   ¤   descriptor.serverList¤  ¤   ¤   = (PGPKeyServerSpec *) serverList;
43d8e8 ¤   ¤   descriptor.serverCount ¤¤   ¤   = serverCount;
--9ad8 001361b7ea440100291 Page 19 of pgpDialogOptions.c
34b914 ¤   ¤   descriptor.tlsContext¤  ¤   ¤   = tlsContext;
bf53f0 ¤   ¤   descriptor.searchBeforeDisplay¤ = searchBeforeDisplay;
fd0b7a ¤   ¤   descriptor.foundKeys¤   ¤   ¤   = foundKeys;
491b52 ¤   ¤
873178 ¤   ¤   if( IsntPGPError( CopyPGPOUIKeyServerParamsDesc( context, &descriptor,
5d5c31 ¤   ¤   ¤   ¤   ¤   &allocatedDesc ) ) )
c45b34 ¤   ¤   {
79c171 ¤   ¤   ¤   PGPOptionValue¤ ¤   value;
b187c7 ¤   ¤   ¤
1f1831 ¤   ¤   ¤   value.asPtr = allocatedDesc;
30af5a
07c1ae ¤   ¤   ¤   optionList = pgpCreateCustomValueOptionList( context,·
0fd432 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_KeyServerUpdateParams,
6362b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionFlag_Default, &value,
00b447 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *allocatedDesc ), subOptions,
53acb9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   KeyServerParamsOptionHandlerProc );
590fe4 ¤   ¤   }
c30e1d ¤   ¤   else
f85b34 ¤   ¤   {
5c95bc ¤   ¤   ¤   PGPFreeOptionList( subOptions );
c40abb ¤   ¤   ¤   optionList = kPGPOutOfMemoryOptionListRef;
fb0fe4 ¤   ¤   }
589371 ¤   }
b60e24 ¤   else
16c7a1 ¤   {
3502ff ¤   ¤   va_start( args, firstOption );
66ed0d ¤   ¤   pgpFreeVarArgOptionList( firstOption, args);
dcc414 ¤   ¤   va_end( args );
b21b52 ¤   ¤
7fb46d ¤   ¤   optionList = kPGPBadParamsOptionListRef;
9d9371 ¤   }
b667c5 ¤
fe8233 ¤   return( optionList );
03efe6 }
3faf5a
4413fb ¤   PGPOptionListRef
a92be9 PGPOUIRecipientList(
b4ba07 ¤   PGPContextRef ¤ ¤   context,
676667 ¤   PGPUInt32¤  ¤   ¤   *recipientCount,
dc613a ¤   PGPRecipientSpec¤   **recipientList)
aebb36 {
48cfb7 ¤   PGPOUIRecipientListDesc¤desc;
ff710b ¤   PGPOptionListRef¤   ¤   optionList;
42af5a
ce1aa1 ¤   pgpValidateOptionContext( context );
a40c0f ¤   pgpValidateOptionParam( IsntNull( recipientCount ) );
9bc5d5 ¤   pgpValidateOptionParam( IsntNull( recipientList ) );
6167c5 ¤
37de65 ¤   desc.recipientCount¤= recipientCount;
4e8b76 ¤   desc.recipientList¤ = recipientList;
0b67c5 ¤
2cba60 ¤   optionList = pgpCreateBufferOptionList( context,
efb86d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPOptionType_RecipientList,
2404ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &desc, sizeof( desc ) );
cdda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
838233 ¤   return( optionList );
36efe6 }
--83d3 000a0cdcc3740100292 Page 1 of pgpDialogs.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
70fcb1 ¤   $Id: pgpDialogs.cpp,v 1.49.10.1 1998/11/12 03:22:59 heller Exp $
bff7f7 ____________________________________________________________________________*/
b2af5a
97324c #include <string.h>
feaf5a
2c0d08 #include "pgpMem.h"
21e684 #include "pgpUserInterface.h"
87af5a
6bc26c #include "pgpContext.h"
3acc06 #include "pgpDialogs.h"
fd2f8d #include "pgpErrors.h"
e7a076 #include "pgpKeys.h"
73eb5b #include "pgpKeyServer.h"
aa0141 #include "pgpOptionListPriv.h"
41af5a
0cd622 #define elemsof(x) ((unsigned)(sizeof(x)/sizeof(*x)))
55af5a
38fcd9 #define¤kCommonAllowedOptions¤  ¤   ¤   ¤   ¤   ¤   \
3a5fcd ¤   ¤   ¤   kPGPOptionType_ParentWindowHandle, ·····\
97dd75 ¤   ¤   ¤   kPGPOptionType_TextUI, ·····\
685094 ¤   ¤   ¤   kPGPOptionType_WindowTitle
f9af5a
f58d27 #define¤kCommonAllowedPassphraseOptions¤¤   ¤   ¤   \
8f3eb4 ¤   ¤   ¤   kCommonAllowedOptions,¤ ¤   ¤   ¤   ¤   \
933d0f ¤   ¤   ¤   kPGPOptionType_DialogOptions,¤  ¤   ¤   \
976ed5 ¤   ¤   ¤   kPGPOptionType_DialogPrompt,¤   ¤   ¤   \
2a0136 ¤   ¤   ¤   kPGPOptionType_OutputPassphrase,¤   ¤   \
911a05 ¤   ¤   ¤   kPGPOptionType_MinPassphraseLength,¤¤   \
cc7d2a ¤   ¤   ¤   kPGPOptionType_MinPassphraseQuality
4caf5a
123521 #define¤kCommonAllowedKeyServerOptions¤ ¤   ¤   ¤   \
80e8cf ¤   ¤   ¤   kCommonAllowedOptions
abaf5a
d887c7 ¤   ¤   ¤
c0b767 CPGPDialogOptions::CPGPDialogOptions(void)
b8bb36 {
a5a1a3 ¤   mContext¤   ¤   ¤   ¤   = kInvalidPGPContextRef;
3ea28a ¤   mClientOptions ¤¤   ¤   = kInvalidPGPOptionListRef;
fa7856 ¤   mWindowTitle¤   ¤   ¤   = NULL;
c8403e ¤   mServerList¤¤   ¤   ¤   = NULL;
1c6751 ¤   mServerCount¤   ¤   ¤   = 0;
dbeaeb ¤   mSearchBeforeDisplay¤   = FALSE;
cdee03 ¤   mTextUI¤¤   ¤   ¤   ¤   = FALSE;
f2cd9d ¤   mNewKeys¤   ¤   ¤   ¤   = NULL;
fc02b1 ¤   mTLSContext¤¤   ¤   ¤   = kInvalidPGPtlsContextRef;
d3f472 ¤   mPrompt¤¤   ¤   ¤   ¤   = NULL;
a867c5 ¤
04afb9 #if PGP_WIN32
660fb8 ¤   ·mHwndParent¤   = NULL;
8d7454 #endif
59efe6 }
e3af5a
94039e CPGPDialogOptions::~CPGPDialogOptions(void)
c5bb36 {
88efe6 }
7667c5 ¤
04c744 ¤   PGPError
80a221 CPGPDialogOptions::GatherOptions(
e8ba07 ¤   PGPContextRef ¤ ¤   context,
199bfc ¤   PGPOptionListRef¤   optionList)
c8bb36 {
e58e12 ¤   PGPError¤   err = kPGPError_NoErr;
7567c5 ¤
41f3ca ¤   PGPValidateContext( context );
d61189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
48af5a
821802 ¤   mContext¤   ¤   = context;
a003f3 ¤   mClientOptions¤ = optionList;
--2641 000024c273340100292 Page 2 of pgpDialogs.cpp
e0af5a
85784e ¤   err = pgpFindOptionArgs( optionList,
02a92f ¤   ¤   ¤   ¤   kPGPOptionType_WindowTitle, FALSE, "%p",
b82719 ¤   ¤   ¤   ¤   &mWindowTitle );
67af5a
9eb1f0 ¤   if( IsntPGPError( err ) )
4fc7a1 ¤   {
3f7ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
36bff6 ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DialogPrompt, FALSE, "%p",
9b1630 ¤   ¤   ¤   ¤   ¤   &mPrompt );
f69371 ¤   }
1067c5 ¤
cab1f0 ¤   if( IsntPGPError( err ) )
bfc7a1 ¤   {
a775a5 ¤   ¤   PGPBoolean¤ haveOption;
8ef617 ¤   ¤   PGPUInt32¤  textUI;
571b52 ¤   ¤
857ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
372edf ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_TextUI, FALSE,
503cde ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &textUI );
361b52 ¤   ¤
f54292 ¤   ¤   if( haveOption )
1e4b73 ¤   ¤   {¤  ·
2f4686 ¤   ¤   ¤   mTextUI = ( textUI != 0 );
4b0fe4 ¤   ¤   }
b49371 ¤   }
b4af5a
d4afb9 #if PGP_WIN32
56b1f0 ¤   if( IsntPGPError( err ) )
46c7a1 ¤   {
f57ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
5758c6 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ParentWindowHandle, FALSE,
ff777f ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &mHwndParent );
339371 ¤   }
ae7454 #endif
c1af5a
999830 ¤   if( IsntPGPError( err ) &&
c89ace ¤   ¤   IsntPGPError( pgpCheckNetworklibAvailability() ) )
4bc7a1 ¤   {
499d5a ¤   ¤   PGPOUIKeyServerParamsDesc¤  *desc = NULL;
ab1b52 ¤   ¤
19f546 ¤   ¤   // Key server params are stored at this level because this is the
afe896 ¤   ¤   // class common to all users of key servers. The legal option
34b261 ¤   ¤   // checking will filter out illegal calls.
f167c5 ¤
ed7ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
f76018 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_KeyServerUpdateParams, FALSE,
5522bb ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &desc );
a81b52 ¤   ¤
64c622 ¤   ¤   if( IsntNull( desc ) )
3f5b34 ¤   ¤   {
d90787 ¤   ¤   ¤   mServerList ¤   ¤   ¤   = desc->serverList;
0e5677 ¤   ¤   ¤   mServerCount ¤  ¤   ¤   = desc->serverCount;
325be2 ¤   ¤   ¤   mTLSContext¤¤   ¤   ¤   = desc->tlsContext;
d0d1eb ¤   ¤   ¤   mSearchBeforeDisplay ¤  = desc->searchBeforeDisplay;
5e1c20 ¤   ¤   ¤   mNewKeys ¤  ¤   ¤   ¤   = desc->foundKeys;
8b0fe4 ¤   ¤   }
d89371 ¤   }
7eaf5a
cadeb7 ¤   return( err );
79efe6 }
aaaf5a
6759f8 CPGPRecipientDialogOptions::CPGPRecipientDialogOptions(void)
9ebb36 {
0c9c41 ¤   mDialogOptions¤ ¤   ¤   ¤   = kInvalidPGPOptionListRef;
9d077b ¤   mNumDefaultRecipients¤  ¤   = 0;
887a54 ¤   mDefaultRecipients¤ ¤   ¤   = NULL;
11aa5c ¤   mDisplayMarginalValidity¤   = FALSE;
9a2a0b ¤   mIgnoreMarginalValidity¤¤   = FALSE;
768315 ¤   mGroupSet¤  ¤   ¤   ¤   ¤   = kInvalidPGPGroupSetRef;
7d9434 ¤   mClientKeySet¤  ¤   ¤   ¤   = kInvalidPGPKeySetRef;
024325 ¤   mRecipientKeysPtr¤  ¤   ¤   = NULL;
--528c 000d625113c40100292 Page 3 of pgpDialogs.cpp
3dc843 ¤   mEnforcement¤   ¤   ¤   ¤   = kPGPARREnforcement_None;
1a40f8 ¤   mAlwaysDisplay¤ ¤   ¤   ¤   = FALSE;
efc214 ¤   mAlwaysDisplayWithARRs¤ ¤   = FALSE;
3b546f ¤   mRecipientCount¤¤   ¤   ¤   = NULL;
c37e13 ¤   mRecipientList¤ ¤   ¤   ¤   = NULL;
9aefe6 }
71af5a
15ac51 CPGPRecipientDialogOptions::~CPGPRecipientDialogOptions(void)
7cbb36 {
4d83d4 ¤   if( IsntNull( mDefaultRecipients ) )
04c7a1 ¤   {
f882a3 ¤   ¤   PGPFreeData( (void *) mDefaultRecipients );
477b2a ¤   ¤   mDefaultRecipients = NULL;
2d9371 ¤   }
42efe6 }
cbaf5a
aec744 ¤   PGPError
258973 CPGPRecipientDialogOptions::GatherOptions(
4cba07 ¤   PGPContextRef ¤ ¤   context,
1a9bfc ¤   PGPOptionListRef¤   optionList)
9dbb36 {
808e12 ¤   PGPError¤   err = kPGPError_NoErr;
6567c5 ¤
12f3ca ¤   PGPValidateContext( context );
661189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
17af5a
241a42 ¤   err = CPGPDialogOptions::GatherOptions( context, optionList );
b8b1f0 ¤   if( IsntPGPError( err ) )
18c7a1 ¤   {
18b2b5 ¤   ¤   PGPOption¤  optionData;
1daf5a
29a81b ¤   ¤   err = pgpSearchOptionSingle( optionList,
173c38 ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DialogOptions, &optionData );
ad144f ¤   ¤   if( IsntPGPError( err ) &&
626696 ¤   ¤   ¤   optionData.type == kPGPOptionType_DialogOptions &&
9de874 ¤   ¤   ¤   PGPOptionListRefIsValid( optionData.subOptions ) )
bb5b34 ¤   ¤   {
cb8aa8 ¤   ¤   ¤   mDialogOptions = optionData.subOptions;
de0fe4 ¤   ¤   }
9d9371 ¤   }
a3af5a
4fb1f0 ¤   if( IsntPGPError( err ) )
93c7a1 ¤   {
319ec5 ¤   ¤   PGPUInt32¤  optionIndex = 0;
1fb2b5 ¤   ¤   PGPOption¤  optionData;
f91b52 ¤   ¤
27f0b9 ¤   ¤   // Multiple default recipient options are allowed, so we
47afe6 ¤   ¤   // loop and look for all of them.
881b52 ¤   ¤
15348f ¤   ¤   while( IsntPGPError( pgpGetIndexedOptionType( optionList,
883a78 ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DefaultRecipients, optionIndex, TRUE,
a08528 ¤   ¤   ¤   ¤   ¤   &optionData, NULL ) ) )
8f5b34 ¤   ¤   {
140053 ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   numNewRecipients;
5c2a8f ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   numTotalRecipients;
40170a ¤   ¤   ¤   PGPRecipientSpec¤   *newRecipientList;
8187c7 ¤   ¤   ¤
720371 ¤   ¤   ¤   numNewRecipients = optionData.valueSize /
7f38c7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( PGPRecipientSpec );
776ccf ¤   ¤   ¤   numTotalRecipients¤ = numNewRecipients + mNumDefaultRecipients;
a087c7 ¤   ¤   ¤
9e21bf ¤   ¤   ¤   newRecipientList = (PGPRecipientSpec *) PGPNewData(
d8ce02 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( context ),
08f466 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   numTotalRecipients *
95a813 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( PGPRecipientSpec ), 0 );
45b3be ¤   ¤   ¤   if( IsNull( newRecipientList ) )
abf776 ¤   ¤   ¤   {
78bfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
9df622 ¤   ¤   ¤   ¤   break;
00a3a6 ¤   ¤   ¤   }
5787c7 ¤   ¤   ¤
d6d7f1 ¤   ¤   ¤   if( IsntNull( mDefaultRecipients ) )
--9dcd 00055aabc8240100292 Page 4 of pgpDialogs.cpp
99f776 ¤   ¤   ¤   {
312027 ¤   ¤   ¤   ¤   pgpCopyMemory( mDefaultRecipients, newRecipientList,
038f83 ¤   ¤   ¤   ¤   ¤   ¤   mNumDefaultRecipients * sizeof( PGPRecipientSpec ) );
a85858 ¤   ¤   ¤   ¤   PGPFreeData( (void *) mDefaultRecipients );
b93495 ¤   ¤   ¤   ¤   mDefaultRecipients = NULL;
64a3a6 ¤   ¤   ¤   }
e387c7 ¤   ¤   ¤
a2125c ¤   ¤   ¤   pgpCopyMemory( ¤optionData.value.asPtr,
a4c013 ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newRecipientList[mNumDefaultRecipients],
3480a7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   numNewRecipients * sizeof( PGPRecipientSpec ) );
0e87c7 ¤   ¤   ¤
e7b5f4 ¤   ¤   ¤   mNumDefaultRecipients ¤ = numTotalRecipients;
0eaef4 ¤   ¤   ¤   mDefaultRecipients¤ ¤   = newRecipientList;
9e1b52 ¤   ¤
f89819 ¤   ¤   ¤   ++optionIndex;
380fe4 ¤   ¤   }
da9371 ¤   }
daaf5a
9eb1f0 ¤   if( IsntPGPError( err ) )
3ac7a1 ¤   {
4e75a5 ¤   ¤   PGPBoolean¤ haveOption;
59c0cb ¤   ¤   PGPUInt32¤  displayMarginalValidity;
8faf5a
2e7ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
768ec6 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_DisplayMarginalValidity, FALSE,
297c63 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &displayMarginalValidity );
8667c5 ¤
df4292 ¤   ¤   if( haveOption )
bd4b73 ¤   ¤   {¤  ·
d25ac9 ¤   ¤   ¤   mDisplayMarginalValidity = displayMarginalValidity;
990fe4 ¤   ¤   }
ef9371 ¤   }
43af5a
2eb1f0 ¤   if( IsntPGPError( err ) )
c9c7a1 ¤   {
1f9871 ¤   ¤   PGPBoolean¤ ¤   ¤   haveOption;
36b809 ¤   ¤   PGPOUIARRParamsDesc¤arrOptions;
68af5a
3e7ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
ee7823 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ARREnforcement, FALSE,
262bbe ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &arrOptions );
8967c5 ¤
a84292 ¤   ¤   if( haveOption )
414b73 ¤   ¤   {¤  ·
85be7f ¤   ¤   ¤   mEnforcement = (PGPAdditionalRecipientRequestEnforcement)
3e15e2 ¤   ¤   ¤   ¤   ¤   arrOptions.enforcement;
dbdeae ¤   ¤   ¤   mAlwaysDisplayWithARRs = arrOptions.displayDialog;
be0fe4 ¤   ¤   }
579371 ¤   }
47af5a
49b1f0 ¤   if( IsntPGPError( err ) )
84c7a1 ¤   {
f575a5 ¤   ¤   PGPBoolean¤ haveOption;
6c3324 ¤   ¤   PGPUInt32¤  ignoreMarginalValidity;
1daf5a
557ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
cfd8ad ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_IgnoreMarginalValidity, FALSE,
969b52 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &ignoreMarginalValidity );
c767c5 ¤
3e4292 ¤   ¤   if( haveOption )
0d4b73 ¤   ¤   {¤  ·
ba7537 ¤   ¤   ¤   mIgnoreMarginalValidity = ignoreMarginalValidity;
a20fe4 ¤   ¤   }
b89371 ¤   }
12af5a
b6b1f0 ¤   if( IsntPGPError( err ) )
37c7a1 ¤   {
a57ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
bdc4e8 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_RecipientGroups, FALSE,
c4ce56 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &mGroupSet );
af9371 ¤   }
55af5a
--36c7 000eeba460640100292 Page 5 of pgpDialogs.cpp
54b1f0 ¤   if( IsntPGPError( err ) )
f1c7a1 ¤   {
d2654e ¤   ¤   PGPOUIRecipientListDesc¤*desc = NULL;
48af5a
e47ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
eabb60 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_RecipientList, FALSE,
e322bb ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &desc );
c567c5 ¤
90c622 ¤   ¤   if( IsntNull( desc ) )
9aed49 ¤   ¤   {¤
ac5796 ¤   ¤   ¤   mRecipientCount = desc->recipientCount;
cc3b1a ¤   ¤   ¤   mRecipientList¤ = desc->recipientList;
890fe4 ¤   ¤   }
b89371 ¤   }
7c67c5 ¤
07deb7 ¤   return( err );
c6efe6 }
85af5a
7222f2 CPGPRandomDataDialogOptions::CPGPRandomDataDialogOptions(void)
d2bb36 {
c004b1 ¤   mNeededEntropyBits ¤= 0;
baefe6 }
61af5a
67d457 CPGPRandomDataDialogOptions::~CPGPRandomDataDialogOptions(void)
a2bb36 {
2fefe6 }
c1af5a
d1b6f0 CPGPKeyServerDialogOptions::CPGPKeyServerDialogOptions(void)
8ebb36 {
12efe6 }
e9af5a
b67b75 CPGPKeyServerDialogOptions::~CPGPKeyServerDialogOptions(void)
e6bb36 {
fcefe6 }
5baf5a
ceaf5a
c3437e CPGPSearchKeyServerDialogOptions::CPGPSearchKeyServerDialogOptions(void)
eabb36 {
be8295 ¤   mSearchAllServers ¤ = FALSE;
2defe5 ¤   mServerList¤¤   ¤   = NULL;
e3d56d ¤   mServerCount¤   ¤   = 0;
017c92 ¤   mFilter¤¤   ¤   ¤   = kInvalidPGPFilterRef;
0d22db ¤   mKeyDescription[0] ¤= 0;
37efe6 }
c5af5a
995233 CPGPSearchKeyServerDialogOptions::~CPGPSearchKeyServerDialogOptions(void)
d4bb36 {
f661a1 ¤   if( PGPFilterRefIsValid( mFilter ) )
d628b8 ¤   ¤   PGPFreeFilter( mFilter );
33efe6 }
a2af5a
62c744 ¤   PGPError
5865e7 CPGPSearchKeyServerDialogOptions::NewKeyIDListSearchFilter(
d1520e ¤   PGPContextRef¤  context,
e97f20 ¤   const PGPKeyID¤ *keyIDList,
065025 ¤   PGPUInt32¤  ¤   keyIDCount,
9286d3 ¤   PGPFilterRef¤   *filter)
8ebb36 {
0837a4 ¤   PGPError¤   ¤   err ¤   ¤   = kPGPError_NoErr;
f58c04 ¤   PGPFilterRef¤   outFilter ¤ = kInvalidPGPFilterRef;
23bf72 ¤   PGPUInt32¤  ¤   keyIDIndex;
5367c5 ¤
ab6c12 ¤   for( keyIDIndex = 0; keyIDIndex < keyIDCount; keyIDIndex++ )
c8c7a1 ¤   {
5ee3c9 ¤   ¤   PGPFilterRef¤   curFilter;
a61b52 ¤   ¤
71f107 ¤   ¤   err = PGPNewKeyIDFilter( context, &keyIDList[keyIDIndex], &curFilter );
9486f8 ¤   ¤   if( IsntPGPError( err ) )
3a5b34 ¤   ¤   {
808253 ¤   ¤   ¤   if( PGPFilterRefIsValid( outFilter ) )
7af776 ¤   ¤   ¤   {
eebb52 ¤   ¤   ¤   ¤   PGPFilterRef¤   newFilter;
--0f23 000b67f744340100292 Page 6 of pgpDialogs.cpp
9f2b85 ¤   ¤   ¤   ¤
64bd56 ¤   ¤   ¤   ¤   err = PGPUnionFilters( curFilter, outFilter, &newFilter );
e05565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
e872c3 ¤   ¤   ¤   ¤   {
758463 ¤   ¤   ¤   ¤   ¤   outFilter = newFilter;
b62613 ¤   ¤   ¤   ¤   }
f2a3a6 ¤   ¤   ¤   }
debb8c ¤   ¤   ¤   else
2cf776 ¤   ¤   ¤   {
ef9d0b ¤   ¤   ¤   ¤   outFilter = curFilter;
a3a3a6 ¤   ¤   ¤   }
c60fe4 ¤   ¤   }
2667c5 ¤
a3d223 ¤   ¤   if( IsPGPError( err ) )
28cdcb ¤   ¤   ¤   break;
409371 ¤   }
2567c5 ¤
a8c713 ¤   if( IsPGPError( err ) &&
496e0f ¤   ¤   PGPFilterRefIsValid( outFilter ) )
08c7a1 ¤   {
17802a ¤   ¤   PGPFreeFilter( outFilter );
2f9108 ¤   ¤   outFilter = kInvalidPGPFilterRef;
e49371 ¤   }
5667c5 ¤
2afa5e ¤   *filter = outFilter;
f367c5 ¤
8fdeb7 ¤   return( err );
ecefe6 }
0daf5a
65c744 ¤   PGPError
264adb CPGPSearchKeyServerDialogOptions::NewKeySetSearchFilter(
3f520e ¤   PGPContextRef¤  context,
6846a5 ¤   PGPKeySetRef¤   keySet,
0486d3 ¤   PGPFilterRef¤   *filter)
e8bb36 {
a937a4 ¤   PGPError¤   ¤   err ¤   ¤   = kPGPError_NoErr;
4e8c04 ¤   PGPFilterRef¤   outFilter ¤ = kInvalidPGPFilterRef;
825445 ¤   PGPKeyListRef¤  keyList;
1a67c5 ¤
d22bbd ¤   err = PGPOrderKeySet( keySet, kPGPAnyOrdering, &keyList );
94b1f0 ¤   if( IsntPGPError( err ) )
1cc7a1 ¤   {
43ce0f ¤   ¤   PGPKeyIterRef¤  iter;
c91b52 ¤   ¤
0faaa0 ¤   ¤   err = PGPNewKeyIter( keyList, &iter );
de86f8 ¤   ¤   if( IsntPGPError( err ) )
885b34 ¤   ¤   {
383754 ¤   ¤   ¤   PGPKeyRef¤  theKey;
5c87c7 ¤   ¤   ¤
a0282e ¤   ¤   ¤   err = PGPKeyIterNext( iter, &theKey );
308f5a ¤   ¤   ¤   while( IsntPGPError( err ) )
e2f776 ¤   ¤   ¤   {
033500 ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
d42b85 ¤   ¤   ¤   ¤
48acf3 ¤   ¤   ¤   ¤   err = PGPGetKeyIDFromKey( theKey, &keyID );
395565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
c272c3 ¤   ¤   ¤   ¤   {
b76121 ¤   ¤   ¤   ¤   ¤   PGPFilterRef¤   keyIDFilter;
97ae30 ¤   ¤   ¤   ¤   ¤
11801c ¤   ¤   ¤   ¤   ¤   err = PGPNewKeyIDFilter( context, &keyID, &keyIDFilter );
546ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
404859 ¤   ¤   ¤   ¤   ¤   {
de94ad ¤   ¤   ¤   ¤   ¤   ¤   if( PGPFilterRefIsValid( outFilter ) )
7d8fec ¤   ¤   ¤   ¤   ¤   ¤   {
ece35f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef¤   newFilter;
a5531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
ff12bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPUnionFilters( outFilter, keyIDFilter,
c1f32d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newFilter );
398d9f ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
c306b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
19dc6e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   outFilter = newFilter;
b65268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
--ab5d 00075bb51fb40100292 Page 7 of pgpDialogs.cpp
0ddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
8e7f8b ¤   ¤   ¤   ¤   ¤   ¤   else
e18fec ¤   ¤   ¤   ¤   ¤   ¤   {
4f5434 ¤   ¤   ¤   ¤   ¤   ¤   ¤   outFilter = keyIDFilter;
dadb3c ¤   ¤   ¤   ¤   ¤   ¤   }
ff1c89 ¤   ¤   ¤   ¤   ¤   }
022613 ¤   ¤   ¤   ¤   }
e32b85 ¤   ¤   ¤   ¤
2e5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
523e32 ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNext( iter, &theKey );
eda3a6 ¤   ¤   ¤   }
b487c7 ¤   ¤   ¤
9b6ae1 ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
f2bd37 ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
c22b85 ¤   ¤   ¤   ¤
9f37e7 ¤   ¤   ¤   PGPFreeKeyIter( iter );
230fe4 ¤   ¤   }
4f1b52 ¤   ¤
436efb ¤   ¤   PGPFreeKeyList( keyList );
9d9371 ¤   }
8c67c5 ¤
bac713 ¤   if( IsPGPError( err ) &&
046e0f ¤   ¤   PGPFilterRefIsValid( outFilter ) )
77c7a1 ¤   {
d6802a ¤   ¤   PGPFreeFilter( outFilter );
1b9108 ¤   ¤   outFilter = kInvalidPGPFilterRef;
389371 ¤   }
3c67c5 ¤
82fa5e ¤   *filter = outFilter;
8967c5 ¤
0ddeb7 ¤   return( err );
9fefe6 }
8eaf5a
f3c744 ¤   PGPError
4f789d CPGPSearchKeyServerDialogOptions::GatherOptions(
1bba07 ¤   PGPContextRef ¤ ¤   context,
449bfc ¤   PGPOptionListRef¤   optionList)
84bb36 {
c58e12 ¤   PGPError¤   err = kPGPError_NoErr;
eb67c5 ¤
2ef3ca ¤   PGPValidateContext( context );
541189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
e6af5a
0bd401 ¤   err = CPGPKeyServerDialogOptions::GatherOptions( context, optionList );
f9b1f0 ¤   if( IsntPGPError( err ) )
8dc7a1 ¤   {
5d990f ¤   ¤   PGPFilterRef¤   filter = kInvalidPGPFilterRef;
747921 ¤   ¤   PGPUInt32¤  ¤   optionIndex = 0;
cb14ea ¤   ¤   PGPOption¤  ¤   optionData;
90a424 ¤   ¤   char¤   ¤   ¤   keyDescription[256];
4f37d4 ¤   ¤   PGPUInt32¤  ¤   numSearchOptions = 0;
6e1b52 ¤   ¤
a5b2b6 ¤   ¤   // Multiple search source options are allowed, so we
58b431 ¤   ¤   // loop and look for all of them. If there is a single
0863a2 ¤   ¤   // search key or a key list with one item, we grab a string
cdf700 ¤   ¤   // description of the item for display in the dialog.
c2af5a
52b3f6 ¤   ¤   keyDescription[0] = 0;
ef1b52 ¤   ¤
9663c3 ¤   ¤   while( IsntPGPError( pgpGetIndexedOption( optionList, optionIndex,
a7cf68 ¤   ¤   ¤   ¤   ¤   TRUE, &optionData ) ) && IsntPGPError( err ) )
085b34 ¤   ¤   {
875cb4 ¤   ¤   ¤   PGPFilterRef¤   curFilter = kInvalidPGPFilterRef;
b5af5a
1adb45 ¤   ¤   ¤   switch( optionData.type )
d2f776 ¤   ¤   ¤   {
90625f ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchFilter:
8e72c3 ¤   ¤   ¤   ¤   {
253f10 ¤   ¤   ¤   ¤   ¤   curFilter = optionData.value.asFilterRef;
9189d8 ¤   ¤   ¤   ¤   ¤   (void) PGPIncFilterRefCount( curFilter );
c9af5a
75a6aa ¤   ¤   ¤   ¤   ¤   ++numSearchOptions;
--519e 000fbc3e26b40100292 Page 8 of pgpDialogs.cpp
f014c3 ¤   ¤   ¤   ¤   ¤   break;
092613 ¤   ¤   ¤   ¤   }
cc2b85 ¤   ¤   ¤   ¤
804f6c ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchKey:
9472c3 ¤   ¤   ¤   ¤   {
3a4e3e ¤   ¤   ¤   ¤   ¤   PGPKeyRef¤  keyRef = optionData.value.asKeyRef;
7bae30 ¤   ¤   ¤   ¤   ¤
891b8d ¤   ¤   ¤   ¤   ¤   if( numSearchOptions == 0 )
9a4859 ¤   ¤   ¤   ¤   ¤   {
84d068 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤len;
a694aa ¤   ¤   ¤   ¤   ¤   ¤
65aefe ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetPrimaryUserIDNameBuffer( keyRef,·
6c2a14 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( keyDescription ),
df7f54 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyDescription, &len );
6168ae ¤   ¤   ¤   ¤   ¤   ¤   keyDescription[len] = 0;
ab1c89 ¤   ¤   ¤   ¤   ¤   }
3dae30 ¤   ¤   ¤   ¤   ¤
566ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
844859 ¤   ¤   ¤   ¤   ¤   {
6a7abf ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
7394aa ¤   ¤   ¤   ¤   ¤   ¤
2d7bf4 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyIDFromKey( keyRef, &keyID );
70239e ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
438fec ¤   ¤   ¤   ¤   ¤   ¤   {
3a3b5c ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPNewKeyIDFilter( context, &keyID,
0fd340 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &curFilter );
35db3c ¤   ¤   ¤   ¤   ¤   ¤   }
751c89 ¤   ¤   ¤   ¤   ¤   }
47ae30 ¤   ¤   ¤   ¤   ¤
43a6aa ¤   ¤   ¤   ¤   ¤   ++numSearchOptions;
b514c3 ¤   ¤   ¤   ¤   ¤   break;
6c2613 ¤   ¤   ¤   ¤   }
e12b85 ¤   ¤   ¤   ¤
fbe55e ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchKeyIDList:
6e72c3 ¤   ¤   ¤   ¤   {
080b99 ¤   ¤   ¤   ¤   ¤   PGPKeyID¤   *keyIDList;
6d894b ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  keyIDCount;
e2ae30 ¤   ¤   ¤   ¤   ¤
c6124d ¤   ¤   ¤   ¤   ¤   keyIDList ¤ = (PGPKeyID *) optionData.value.asPtr;
24a86f ¤   ¤   ¤   ¤   ¤   keyIDCount ¤= optionData.valueSize / sizeof( *keyIDList );
f3ae30 ¤   ¤   ¤   ¤   ¤
c8496a ¤   ¤   ¤   ¤   ¤   if( numSearchOptions == 0 && keyIDCount == 1 )
594859 ¤   ¤   ¤   ¤   ¤   {
56682c ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyIDString( keyIDList,
9ea14b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyIDString_Abbreviated,
8fbfc1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyDescription );
ec1c89 ¤   ¤   ¤   ¤   ¤   }
a2af5a
fa6ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
ed4859 ¤   ¤   ¤   ¤   ¤   {
d1d37c ¤   ¤   ¤   ¤   ¤   ¤   err = NewKeyIDListSearchFilter( context, keyIDList,
38a432 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIDCount, &curFilter );
061c89 ¤   ¤   ¤   ¤   ¤   }
d7ae30 ¤   ¤   ¤   ¤   ¤
16a6aa ¤   ¤   ¤   ¤   ¤   ++numSearchOptions;
4b14c3 ¤   ¤   ¤   ¤   ¤   break;
472613 ¤   ¤   ¤   ¤   }
8caf5a
97b9bb ¤   ¤   ¤   ¤   case kPGPOptionType_KeyServerSearchKeySet:
d372c3 ¤   ¤   ¤   ¤   {
abfeb3 ¤   ¤   ¤   ¤   ¤   err = NewKeySetSearchFilter( context,
a5028e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   optionData.value.asKeySetRef, &curFilter );
0bae30 ¤   ¤   ¤   ¤   ¤
29a6aa ¤   ¤   ¤   ¤   ¤   ++numSearchOptions;
5e14c3 ¤   ¤   ¤   ¤   ¤   break;
2d2613 ¤   ¤   ¤   ¤   }
4aa3a6 ¤   ¤   ¤   }
a387c7 ¤   ¤   ¤
736bb7 ¤   ¤   ¤   if( PGPFilterRefIsValid( curFilter ) &&
e457a0 ¤   ¤   ¤   ¤   IsntPGPError( err ) )
20f776 ¤   ¤   ¤   {
fb40f8 ¤   ¤   ¤   ¤   if( PGPFilterRefIsValid( filter ) )
--4817 000837c4ec440100292 Page 9 of pgpDialogs.cpp
d072c3 ¤   ¤   ¤   ¤   {
eb2aca ¤   ¤   ¤   ¤   ¤   PGPFilterRef¤   newFilter;
95ae30 ¤   ¤   ¤   ¤   ¤
36c39c ¤   ¤   ¤   ¤   ¤   err = PGPUnionFilters( filter, curFilter, &newFilter );
866ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
f04859 ¤   ¤   ¤   ¤   ¤   {
69fd04 ¤   ¤   ¤   ¤   ¤   ¤   filter = newFilter;
0c1c89 ¤   ¤   ¤   ¤   ¤   }
d92613 ¤   ¤   ¤   ¤   }
0efa07 ¤   ¤   ¤   ¤   else
4f72c3 ¤   ¤   ¤   ¤   {
896246 ¤   ¤   ¤   ¤   ¤   filter = curFilter;
142613 ¤   ¤   ¤   ¤   }
13a3a6 ¤   ¤   ¤   }
4c87c7 ¤   ¤   ¤
489819 ¤   ¤   ¤   ++optionIndex;
240fe4 ¤   ¤   }
c21b52 ¤   ¤
7686f8 ¤   ¤   if( IsntPGPError( err ) )
5c5b34 ¤   ¤   {
838bbb ¤   ¤   ¤   if( numSearchOptions == 0 )
08f776 ¤   ¤   ¤   {
5e056d ¤   ¤   ¤   ¤   pgpDebugMsg( "No key server subjects found" );
0d566c ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
14a3a6 ¤   ¤   ¤   }
b4bb8c ¤   ¤   ¤   else
e9f776 ¤   ¤   ¤   {
33f82c ¤   ¤   ¤   ¤   pgpAssert( PGPFilterRefIsValid( filter ) );
f1ae30 ¤   ¤   ¤   ¤   ¤
291eaf ¤   ¤   ¤   ¤   mFilter = filter;
0687c7 ¤   ¤   ¤
67ed54 ¤   ¤   ¤   ¤   if( numSearchOptions == 1 && keyDescription[0] != 0 )
3828ba ¤   ¤   ¤   ¤   ¤   strcpy( mKeyDescription, keyDescription );
95a3a6 ¤   ¤   ¤   }
4e0fe4 ¤   ¤   }
e90e1d ¤   ¤   else
cb5b34 ¤   ¤   {
4bd6b9 ¤   ¤   ¤   if( PGPFilterRefIsValid( filter ) )
cd7e71 ¤   ¤   ¤   ¤   PGPFreeFilter( filter );
310fe4 ¤   ¤   }
1e9371 ¤   }
01af5a
d7deb7 ¤   return( err );
c0efe6 }
88af5a
3a5b7d CPGPSendToKeyServerDialogOptions::CPGPSendToKeyServerDialogOptions(void)
b2bb36 {
937765 ¤   mKeysToSend¤= kInvalidPGPKeySetRef;
367057 ¤   mFailedKeys¤= NULL;
5befe6 }
6faf5a
7d6bd4 CPGPSendToKeyServerDialogOptions::~CPGPSendToKeyServerDialogOptions(void)
34bb36 {
f2efe6 }
d0af5a
effb6f CPGPPassphraseDialogOptions::CPGPPassphraseDialogOptions(void)
76bb36 {
9ffcd0 ¤   mPassphrasePtr¤ ¤   ¤   = NULL;
b1ed4b ¤   mDialogOptions¤ ¤   ¤   = kInvalidPGPOptionListRef;
9d356c ¤   mMinPassphraseLength¤   = 0;
270895 ¤   mMinPassphraseQuality¤  = 0;
daefe6 }
f5af5a
cb5c19 CPGPPassphraseDialogOptions::~CPGPPassphraseDialogOptions(void)
43bb36 {
c0efe6 }
e2af5a
e0c744 ¤   PGPError
1b8e1d CPGPPassphraseDialogOptions::GatherOptions(
98ba07 ¤   PGPContextRef ¤ ¤   context,
c19bfc ¤   PGPOptionListRef¤   optionList)
83bb36 {
--035e 0003149a91c40100292 Page 10 of pgpDialogs.cpp
868e12 ¤   PGPError¤   err = kPGPError_NoErr;
1767c5 ¤
b7f3ca ¤   PGPValidateContext( context );
bb1189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
05af5a
f61a42 ¤   err = CPGPDialogOptions::GatherOptions( context, optionList );
acb1f0 ¤   if( IsntPGPError( err ) )
6bc7a1 ¤   {
a57ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
2ea64b ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_OutputPassphrase, TRUE,
bb30fc ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &mPassphrasePtr );
679371 ¤   }
1baf5a
fdb1f0 ¤   if( IsntPGPError( err ) )
ebc7a1 ¤   {
11b2b5 ¤   ¤   PGPOption¤  optionData;
b31b52 ¤   ¤
efa81b ¤   ¤   err = pgpSearchOptionSingle( optionList,
f73c38 ¤   ¤   ¤   ¤   ¤   kPGPOptionType_DialogOptions, &optionData );
3e144f ¤   ¤   if( IsntPGPError( err ) &&
6d6696 ¤   ¤   ¤   optionData.type == kPGPOptionType_DialogOptions &&
d4e874 ¤   ¤   ¤   PGPOptionListRefIsValid( optionData.subOptions ) )
db5b34 ¤   ¤   {
628aa8 ¤   ¤   ¤   mDialogOptions = optionData.subOptions;
180fe4 ¤   ¤   }
d69371 ¤   }
65af5a
09b1f0 ¤   if( IsntPGPError( err ) )
b0c7a1 ¤   {
597ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
ede292 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_MinPassphraseLength, FALSE,
dfbf5a ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &mMinPassphraseLength );
2b9371 ¤   }
bfaf5a
78b1f0 ¤   if( IsntPGPError( err ) )
d2c7a1 ¤   {
767ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
7086d2 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_MinPassphraseQuality, FALSE,
5addf7 ¤   ¤   ¤   ¤   ¤   ¤   ·"%d", &mMinPassphraseQuality );
989371 ¤   }
7faf5a
6adeb7 ¤   return( err );
b6efe6 }
0baf5a
6978cd CPGPConfirmationPassphraseDialogOptions::
fcd218 ¤   CPGPConfirmationPassphraseDialogOptions(void)
20bb36 {
a88319 ¤   mShowPassphraseQuality = TRUE;
bdefe6 }
10af5a
bd78cd CPGPConfirmationPassphraseDialogOptions::
057c2f ¤   ~CPGPConfirmationPassphraseDialogOptions(void)
d4bb36 {
e9efe6 }
85af5a
11c744 ¤   PGPError
bb7ea7 CPGPConfirmationPassphraseDialogOptions::GatherOptions(
bfba07 ¤   PGPContextRef ¤ ¤   context,
6a9bfc ¤   PGPOptionListRef¤   optionList)
50bb36 {
cd61e0 ¤   PGPError¤   err;
9a67c5 ¤
5af3ca ¤   PGPValidateContext( context );
891189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
7567c5 ¤
ddc801 ¤   err = CPGPPassphraseDialogOptions::GatherOptions( context, optionList );
59b1f0 ¤   if( IsntPGPError( err ) )
51c7a1 ¤   {
3275a5 ¤   ¤   PGPBoolean¤ haveOption;
895afc ¤   ¤   PGPUInt32¤  showPassphraseQuality;
e3af5a
317ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
--7178 00048e34fc840100292 Page 11 of pgpDialogs.cpp
58a3b5 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_ShowPassphraseQuality, FALSE,
99d484 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &showPassphraseQuality );
e567c5 ¤
494292 ¤   ¤   if( haveOption )
d74b73 ¤   ¤   {¤  ·
cc5e79 ¤   ¤   ¤   mShowPassphraseQuality = ( showPassphraseQuality != 0 );
670fe4 ¤   ¤   }
9b9371 ¤   }
0867c5 ¤
c8deb7 ¤   return( err );
c7efe6 }
aeaf5a
ced879 CPGPKeyPassphraseDialogOptions::CPGPKeyPassphraseDialogOptions(void)
98bb36 {
cac704 ¤   mVerifyPassphrase ¤ = TRUE;
a08ca1 ¤   mDefaultKey¤¤   ¤   = kInvalidPGPKeyRef;
d5efe6 }
a4af5a
2b42e9 CPGPKeyPassphraseDialogOptions::~CPGPKeyPassphraseDialogOptions(void)
42bb36 {
3befe6 }
6baf5a
bac744 ¤   PGPError
f95ff7 CPGPKeyPassphraseDialogOptions::GatherOptions(
1cba07 ¤   PGPContextRef ¤ ¤   context,
be9bfc ¤   PGPOptionListRef¤   optionList)
19bb36 {
bc61e0 ¤   PGPError¤   err;
5067c5 ¤
f6f3ca ¤   PGPValidateContext( context );
491189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
1eaf5a
2ec801 ¤   err = CPGPPassphraseDialogOptions::GatherOptions( context, optionList );
20b1f0 ¤   if( IsntPGPError( err ) )
86c7a1 ¤   {
467ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
4b5880 ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_DefaultKey, FALSE,
11af99 ¤   ¤   ¤   ¤   ¤   ¤   ·"%p", &mDefaultKey );
f69371 ¤   }
c0af5a
cdb1f0 ¤   if( IsntPGPError( err ) )
6bc7a1 ¤   {
6375a5 ¤   ¤   PGPBoolean¤ haveOption;
e37d48 ¤   ¤   PGPUInt32¤  verifyPassphrase;
e61b52 ¤   ¤
8d7ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
04858e ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_VerifyPassphrase, FALSE,
e6d100 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &verifyPassphrase );
841b52 ¤   ¤
ea4292 ¤   ¤   if( haveOption )
da4b73 ¤   ¤   {¤  ·
79539c ¤   ¤   ¤   mVerifyPassphrase = ( verifyPassphrase != 0 );
8c0fe4 ¤   ¤   }
d09371 ¤   }
201b52 ¤   ¤
18deb7 ¤   return( err );
84efe6 }
95af5a
756e78 CPGPKeySetPassphraseDialogOptions::CPGPKeySetPassphraseDialogOptions(void)
67bb36 {
19ac51 ¤   mFindMatchingKey¤   = TRUE;
09e784 ¤   mKeySet¤¤   ¤   ¤   = kInvalidPGPKeySetRef;
6d47a2 ¤   mPassphraseKeyPtr¤  = NULL;
a0efe6 }
60af5a
44fbcf CPGPKeySetPassphraseDialogOptions::~CPGPKeySetPassphraseDialogOptions(void)
2ebb36 {
22efe6 }
0aaf5a
4bc744 ¤   PGPError
f3eaaf CPGPKeySetPassphraseDialogOptions::GatherOptions(
48ba07 ¤   PGPContextRef ¤ ¤   context,
--d2e4 000e4bcc56640100292 Page 12 of pgpDialogs.cpp
889bfc ¤   PGPOptionListRef¤   optionList)
5bbb36 {
2861e0 ¤   PGPError¤   err;
5f67c5 ¤
8bf3ca ¤   PGPValidateContext( context );
6b1189 ¤   PGPValidateParam( pgpOptionListIsValid( optionList ) );
82af5a
030acb ¤   err = CPGPKeyPassphraseDialogOptions::GatherOptions(context, optionList);
94b1f0 ¤   if( IsntPGPError( err ) )
29c7a1 ¤   {
2275a5 ¤   ¤   PGPBoolean¤ haveOption;
34d30b ¤   ¤   PGPUInt32¤  findMatchingKey;
ef1b52 ¤   ¤
2a7ef6 ¤   ¤   err = pgpFindOptionArgs( optionList,
991b5d ¤   ¤   ¤   ¤   ¤   ¤   ·kPGPOptionType_FindMatchingKey, FALSE,
2d43a1 ¤   ¤   ¤   ¤   ¤   ¤   ·"%b%d", &haveOption, &findMatchingKey );
e71b52 ¤   ¤
2e4292 ¤   ¤   if( haveOption )
4f4b73 ¤   ¤   {¤  ·
c2fbb3 ¤   ¤   ¤   mFindMatchingKey = ( findMatchingKey != 0 );
290fe4 ¤   ¤   }
c19371 ¤   }
3b1b52 ¤   ¤
79deb7 ¤   return( err );
58efe6 }
94af5a
bbb780 CPGPSigningPassphraseDialogOptions::CPGPSigningPassphraseDialogOptions(void)
a4bb36 {
bfefe6 }
98af5a
956558 CPGPSigningPassphraseDialogOptions::~CPGPSigningPassphraseDialogOptions(void)
fabb36 {
72efe6 }
adaf5a
246091 CPGPDecryptionPassphraseDialogOptions::
fb8403 ¤   CPGPDecryptionPassphraseDialogOptions(void)
e6bb36 {
242b8c ¤   mMissingKeyIDList ¤ = NULL;
81f165 ¤   mMissingKeyIDCount¤ = 0;
2fefe6 }
d9af5a
f96091 CPGPDecryptionPassphraseDialogOptions::
a1a905 ¤   ~CPGPDecryptionPassphraseDialogOptions(void)
8bbb36 {
464ef2 ¤   if( IsntNull( mMissingKeyIDList ) )
3a4453 ¤   ¤   PGPFreeData( mMissingKeyIDList );
83efe6 }
2eaf5a
c0c744 ¤   PGPError
b075a4 CPGPDecryptionPassphraseDialogOptions::RemoveFoundKeysFromSet(
660f78 ¤   PGPKeySetRef keySet)
7abb36 {
0e84de ¤   PGPInt32¤   keyIDIndex;
a28e12 ¤   PGPError¤   err = kPGPError_NoErr;
b167c5 ¤
b1d8af ¤   /*
aea4ee ¤   ** Process keySet and remove any keys in the set from the missing
6d655a ¤   ** keys list. The following is ugly N-squared behavior. We need to
5497d5 ¤   ** walk the key ID list and eliminate keys already in mKeySet, however
5b3b7b ¤   ** PGPGetKeyByKeyID requires an algorithm, which we do not have.
1b3fb0 ¤   ** In addition, the key ID list contains subkey IDs, not the
2a26ef ¤   ** signing key IDs. There is no lookup function for this case.
3a1541 ¤   ** Thus, we walk the key id list and then iterate the key set
4826fe ¤   ** to see if we have the key. If not, the key ID is added to the
99483e ¤   ** list of missing keys.
8c9faa ¤   */
91af5a
30c4db ¤   for( keyIDIndex = mMissingKeyIDCount - 1; keyIDIndex >= 0; keyIDIndex-- )
12c7a1 ¤   {
71ef13 ¤   ¤   PGPKeyListRef¤  keyList;
1c10f4 ¤   ¤   PGPBoolean¤ ¤   foundKeyID = FALSE;
e41b52 ¤   ¤
--4f5c 000a4a17e4c40100292 Page 13 of pgpDialogs.cpp
b4a641 ¤   ¤   err = PGPOrderKeySet( keySet, kPGPAnyOrdering, &keyList );
3886f8 ¤   ¤   if( IsntPGPError( err ) )
225b34 ¤   ¤   {
1df907 ¤   ¤   ¤   PGPKeyIterRef¤  iter;
6c87c7 ¤   ¤   ¤
fb7212 ¤   ¤   ¤   err = PGPNewKeyIter( keyList, &iter );
52698b ¤   ¤   ¤   if( IsntPGPError( err ) )
aaf776 ¤   ¤   ¤   {
d6bca8 ¤   ¤   ¤   ¤   PGPKeyRef¤  theKey;
1b2b85 ¤   ¤   ¤   ¤
0b3909 ¤   ¤   ¤   ¤   err = PGPKeyIterNext( iter, &theKey );
7389e2 ¤   ¤   ¤   ¤   while( IsntPGPError( err ) )
0572c3 ¤   ¤   ¤   ¤   {
0a74f3 ¤   ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
4fda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
3768ef ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyIDFromKey( theKey, &keyID );
636ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
fd4859 ¤   ¤   ¤   ¤   ¤   {
a25f00 ¤   ¤   ¤   ¤   ¤   ¤   if( PGPCompareKeyIDs( &keyID,
1d1b87 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mMissingKeyIDList[keyIDIndex] ) == 0 )
fa8fec ¤   ¤   ¤   ¤   ¤   ¤   {
ddab70 ¤   ¤   ¤   ¤   ¤   ¤   ¤   foundKeyID = TRUE;
e7db3c ¤   ¤   ¤   ¤   ¤   ¤   }
447f8b ¤   ¤   ¤   ¤   ¤   ¤   else
458fec ¤   ¤   ¤   ¤   ¤   ¤   {
9c02bd ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKeyRef¤   subKey;
2c531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
89068a ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNextSubKey( iter, &subKey );
b0e757 ¤   ¤   ¤   ¤   ¤   ¤   ¤   while( IsntPGPError( err ) )
5b06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
1170a2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyIDFromSubKey( subKey, &keyID );
e18ee8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
c731b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
b7026e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( PGPCompareKeyIDs( &keyID,
9f4ed7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mMissingKeyIDList[keyIDIndex] ) == 0 )
d5dec3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
5065de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   foundKeyID = TRUE;
f852b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
718a13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
fdaf5a
d1c652 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNextSubKey(iter, &subKey);
006560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
5d5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
acaf5a
c5998e ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
59eb76 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
eddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
401c89 ¤   ¤   ¤   ¤   ¤   }
2094aa ¤   ¤   ¤   ¤   ¤   ¤
656ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
833ed0 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNext( iter, &theKey );
bf2613 ¤   ¤   ¤   ¤   }
8a2b85 ¤   ¤   ¤   ¤
dcc4e0 ¤   ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
9bb37b ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
9fae30 ¤   ¤   ¤   ¤   ¤
a4f2b2 ¤   ¤   ¤   ¤   PGPFreeKeyIter( iter );
78a3a6 ¤   ¤   ¤   }
6287c7 ¤   ¤   ¤
322f08 ¤   ¤   ¤   PGPFreeKeyList( keyList );
ff0fe4 ¤   ¤   }
ae67c5 ¤
64137d ¤   ¤   if( IsntPGPError( err ) && foundKeyID )
515b34 ¤   ¤   {
5f2d6a ¤   ¤   ¤   PGPUInt32¤  keysToMove;
b187c7 ¤   ¤   ¤
6869de ¤   ¤   ¤   keysToMove = mMissingKeyIDCount - keyIDIndex - 1;
68575c ¤   ¤   ¤   if( keysToMove != 0 )
dcf776 ¤   ¤   ¤   {
657264 ¤   ¤   ¤   ¤   pgpCopyMemory( &mMissingKeyIDList[keyIDIndex + 1],
3b32ed ¤   ¤   ¤   ¤   ¤   ¤   &mMissingKeyIDList[keyIDIndex],
a45c7c ¤   ¤   ¤   ¤   ¤   ¤   keysToMove * sizeof( mMissingKeyIDList[0] ) );
--16a2 0009a3b4e8640100292 Page 14 of pgpDialogs.cpp
cfa3a6 ¤   ¤   ¤   }
7987c7 ¤   ¤   ¤
159e42 ¤   ¤   ¤   --mMissingKeyIDCount;
600fe4 ¤   ¤   }
5367c5 ¤
49d223 ¤   ¤   if( IsPGPError( err ) )
f1cdcb ¤   ¤   ¤   break;
0c9371 ¤   }
6867c5 ¤
f2deb7 ¤   return( err );
6cefe6 }
caaf5a
1fc744 ¤   PGPError
b8994d CPGPDecryptionPassphraseDialogOptions::GatherMissingKeys()
a3bb36 {
7e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
30af5a
7a4ef2 ¤   if( IsntNull( mMissingKeyIDList ) )
76c7a1 ¤   {
a24453 ¤   ¤   PGPFreeData( mMissingKeyIDList );
2c1b52 ¤   ¤
55a070 ¤   ¤   mMissingKeyIDList ¤ = NULL;
be4a33 ¤   ¤   mMissingKeyIDCount¤ = 0;
319371 ¤   }
ddaf5a
c8f4b5 ¤   if( IsntNull( mKeyIDList ) && mKeyIDCount != 0 )
bcc7a1 ¤   {
f06657 ¤   ¤   PGPSize¤dataSize = mKeyIDCount * sizeof( mKeyIDList[0] );
af1b52 ¤   ¤
8bd433 ¤   ¤   /* Assume all keys are missing. Make a copy of the key ID list */
841b52 ¤   ¤
1f9600 ¤   ¤   mMissingKeyIDList = (PGPKeyID *) PGPNewData(
e529ab ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetContextMemoryMgr( mContext ),
c6708b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   dataSize, kPGPMemoryMgrFlags_Clear );
63c694 ¤   ¤   if( IsntNull( mMissingKeyIDList ) )
025b34 ¤   ¤   {
cf4e24 ¤   ¤   ¤   pgpCopyMemory( mKeyIDList, mMissingKeyIDList, dataSize );
ebf059 ¤   ¤   ¤   mMissingKeyIDCount = mKeyIDCount;
1887c7 ¤   ¤   ¤
2605a0 ¤   ¤   ¤   err = RemoveFoundKeysFromSet( mKeySet );
ee55bc ¤   ¤   ¤   if( IsntPGPError( err ) &&
1bb699 ¤   ¤   ¤   ¤   IsntNull( mNewKeys ) &&
574e61 ¤   ¤   ¤   ¤   PGPKeySetRefIsValid( *mNewKeys ) )
76f776 ¤   ¤   ¤   {
5e292c ¤   ¤   ¤   ¤   err = RemoveFoundKeysFromSet( *mNewKeys );
e7a3a6 ¤   ¤   ¤   }
a287c7 ¤   ¤   ¤
ce13d1 ¤   ¤   ¤   if( IsPGPError( err ) || mMissingKeyIDCount == 0 )
5cf776 ¤   ¤   ¤   {
2f32a8 ¤   ¤   ¤   ¤   PGPFreeData( mMissingKeyIDList );
aded43 ¤   ¤   ¤   ¤   mMissingKeyIDList ¤ = NULL;
938ed3 ¤   ¤   ¤   ¤   mMissingKeyIDCount ¤= 0;
7ea3a6 ¤   ¤   ¤   }
3f0fe4 ¤   ¤   }
0f0e1d ¤   ¤   else
935b34 ¤   ¤   {
42b90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
d10fe4 ¤   ¤   }
939371 ¤   }
5767c5 ¤
0cdeb7 ¤   return( err );
e4efe6 }
79af5a
57c744 ¤   PGPError
7e682a CPGPDecryptionPassphraseDialogOptions::SearchForMissingKeys(
a6e7b6 ¤   void¤   ¤   *hwndParent,
c78fb2 ¤   PGPBoolean¤ *foundNewKeys)
98bb36 {
ad0ccc #if PGP_MACINTOSH
24a834 ¤   (void) hwndParent;
847454 #endif
9aaf5a
--f18f 000fdf6210540100292 Page 15 of pgpDialogs.cpp
868e12 ¤   PGPError¤   err = kPGPError_NoErr;
1767c5 ¤
7ea834 ¤   (void) hwndParent;
d067c5 ¤
6bb948 ¤   pgpAssert( IsntNull( foundNewKeys ) );
6aeb52 ¤   *foundNewKeys = FALSE;
f7af5a
6096f2 ¤   if( IsntNull( mServerList ) &&
10e452 ¤   ¤   IsntNull( mMissingKeyIDList ) &&
aaafa3 ¤   ¤   IsntNull( mNewKeys ) )
16c7a1 ¤   {
e2406a ¤   ¤   pgpAssert( ! PGPKeySetRefIsValid( *mNewKeys ) );
e11b52 ¤   ¤
9e2727 ¤   ¤   err = PGPNewKeySet( mContext, mNewKeys );
7186f8 ¤   ¤   if( IsntPGPError( err ) )
1a5b34 ¤   ¤   {
77e139 ¤   ¤   ¤   PGPUInt32¤  serverIndex;
b21044 ¤   ¤   ¤   PGPUInt32¤  numNewKeys = 0;
de87c7 ¤   ¤   ¤
bd8865 ¤   ¤   ¤   for( serverIndex = 0; serverIndex < mServerCount; serverIndex++ )
1bf776 ¤   ¤   ¤   {
cc4885 ¤   ¤   ¤   ¤   if( IsntNull( mMissingKeyIDList ) )
1572c3 ¤   ¤   ¤   ¤   {
aec02f ¤   ¤   ¤   ¤   ¤   PGPKeyServerType¤   ¤   serverType;
ea10f3 ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec¤ *serverSpec;
fcae30 ¤   ¤   ¤   ¤   ¤
62709c ¤   ¤   ¤   ¤   ¤   serverSpec = &mServerList[serverIndex];
24ae30 ¤   ¤   ¤   ¤   ¤
20b4ed ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyServerType( serverSpec->server,
5efd93 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &serverType );
4cca68 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
b711bc ¤   ¤   ¤   ¤   ¤   ¤   serverType != kPGPKeyServerType_HTTP &&
c33b25 ¤   ¤   ¤   ¤   ¤   ¤   serverType != kPGPKeyServerType_HTTPS )
b54859 ¤   ¤   ¤   ¤   ¤   {
cb00a6 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef¤   filter = kInvalidPGPFilterRef;
57a1e3 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   keyIndex;
9094aa ¤   ¤   ¤   ¤   ¤   ¤
539531 ¤   ¤   ¤   ¤   ¤   ¤   for( keyIndex = 0; keyIndex < mMissingKeyIDCount;
f5d1ba ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyIndex++ )
d28fec ¤   ¤   ¤   ¤   ¤   ¤   {
14f47b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef¤   curFilter;
cf531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
27bced ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPNewSubKeyIDFilter( mContext,
421597 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &mMissingKeyIDList[keyIndex],
add340 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &curFilter );
b28d9f ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
c006b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
8a6371 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( PGPFilterRefIsValid( filter ) )
e831b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
0ee486 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef¤   newFilter;
dbed43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
b80b84 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPUnionFilters( curFilter, filter,
74125a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &newFilter );
216ce8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
fbdec3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
b7a9ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter = newFilter;
a38a13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
506560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
45f9b5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   else
3831b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
64319d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter = curFilter;
d26560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
f55268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
01531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
a99afd ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
f1cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
a3db3c ¤   ¤   ¤   ¤   ¤   ¤   }
9494aa ¤   ¤   ¤   ¤   ¤   ¤
a1239e ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
eb8fec ¤   ¤   ¤   ¤   ¤   ¤   {
9d1e34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   foundKeys = kInvalidPGPKeySetRef;
fd531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
--476c 000fcd5fc5540100292 Page 16 of pgpDialogs.cpp
10c6fb ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPSearchKeyServerDialog( mContext, 1,
59ff47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   serverSpec, mTLSContext, TRUE, &foundKeys,
9494e5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOUIKeyServerSearchFilter( mContext,
45ca38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   filter ),
12d723 ¤   ¤   ¤   #if PGP_WIN32
592542 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOUIParentWindowHandle( mContext,
2462b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   hwndParent),
df34f5 ¤   ¤   ¤   #endif
b3e8d4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption( mContext ) );
8403fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
aed6c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRefIsValid( foundKeys ) )
e406b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
d7186a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPAddKeys( foundKeys, *mNewKeys );
0d8ee8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
7c31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
37e37a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges( *mNewKeys );
536ce8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
70dec3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
3cace3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = GatherMissingKeys();
cc8a13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
af6560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
6eda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
4e2e19 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( foundKeys );
a75268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
79db3c ¤   ¤   ¤   ¤   ¤   ¤   }
3094aa ¤   ¤   ¤   ¤   ¤   ¤
589a03 ¤   ¤   ¤   ¤   ¤   ¤   if( PGPFilterRefIsValid( filter ) )
e8794f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeFilter( filter );
cd1c89 ¤   ¤   ¤   ¤   ¤   }
05ae30 ¤   ¤   ¤   ¤   ¤
0c0770 ¤   ¤   ¤   ¤   }·
0587c7 ¤   ¤   ¤
249c8a ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
b314c3 ¤   ¤   ¤   ¤   ¤   break;
1ba3a6 ¤   ¤   ¤   }
c987c7 ¤   ¤   ¤
b16097 ¤   ¤   ¤   (void) PGPCountKeys( *mNewKeys, &numNewKeys );
1897eb ¤   ¤   ¤   if( numNewKeys != 0 )
2df776 ¤   ¤   ¤   {
13ad33 ¤   ¤   ¤   ¤   *foundNewKeys = TRUE;
1ba3a6 ¤   ¤   ¤   }
9abb8c ¤   ¤   ¤   else
f6f776 ¤   ¤   ¤   {
efc5c0 ¤   ¤   ¤   ¤   PGPFreeKeySet( *mNewKeys );
47cb26 ¤   ¤   ¤   ¤   *mNewKeys = kInvalidPGPKeySetRef;
f7a3a6 ¤   ¤   ¤   }
d70fe4 ¤   ¤   }
179371 ¤   }
1e67c5 ¤
43deb7 ¤   return( err );
a1efe6 }
c0af5a
81b32d CPGPOptionsDialogOptions::CPGPOptionsDialogOptions(void)
00bb36 {
aaefe6 }
2faf5a
5e7719 CPGPOptionsDialogOptions::~CPGPOptionsDialogOptions(void)
73bb36 {
caefe6 }
69af5a
b8b329 static const PGPOptionType sPassphraseOptionSet[] =
2cbb36 {
9fac7c ¤   kCommonAllowedPassphraseOptions
2282f7 };
58af5a
4c66dd ¤   static PGPError
d9b8bb pgpPassphraseDialog(
38a1bc ¤   PGPContextRef¤  ¤   context,
538047 ¤   PGPOptionListRef ¤  optionList)
5ebb36 {
6c61e0 ¤   PGPError¤   err;
fcaf5a
--5d68 000eb19609040100292 Page 17 of pgpDialogs.cpp
308679 ¤   pgpAssert( pgpContextIsValid( context ) );
be704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
a467c5 ¤
e5bd44 ¤   err = pgpGetOptionListError( optionList );
45b1f0 ¤   if( IsntPGPError( err ) )
48c7a1 ¤   {
e034da ¤   ¤   err = pgpCheckOptionsInSet( optionList, sPassphraseOptionSet,
861c74 ¤   ¤   ¤   ¤   ¤   elemsof( sPassphraseOptionSet ) );
7a86f8 ¤   ¤   if( IsntPGPError( err ) )
c55b34 ¤   ¤   {
73bd29 ¤   ¤   ¤   CPGPPassphraseDialogOptions¤options;
d887c7 ¤   ¤   ¤
63e5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
04698b ¤   ¤   ¤   if( IsntPGPError( err ) )
61f776 ¤   ¤   ¤   {
183982 ¤   ¤   ¤   ¤   err = pgpPassphraseDialogPlatform( context, &options );
2ba3a6 ¤   ¤   ¤   }
2a0fe4 ¤   ¤   }
c99371 ¤   }
cf67c5 ¤
54deb7 ¤   return( err );
b9efe6 }
e7af5a
fdc744 ¤   PGPError
08ae24 PGPPassphraseDialog(
f0a1bc ¤   PGPContextRef¤  ¤   context,
cd41a1 ¤   PGPOptionListRef¤   firstOption,
3f3471 ¤   ...)
2ebb36 {
698e12 ¤   PGPError¤   err = kPGPError_NoErr;
a346e9 ¤   va_list¤¤   args;
50af5a
b98679 ¤   pgpAssert( pgpContextIsValid( context ) );
cc67c5 ¤
ece8d2 ¤   if( pgpContextIsValid( context ) )
98c7a1 ¤   {
82f888 ¤   ¤   PGPOptionListRef¤   optionList;
ea1b52 ¤   ¤
2c02ff ¤   ¤   va_start( args, firstOption );
616387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
64c414 ¤   ¤   va_end( args );
c367c5 ¤
2349c8 ¤   ¤   err = pgpPassphraseDialog( context, optionList );
8867c5 ¤
4b153d ¤   ¤   PGPFreeOptionList( optionList );
e39371 ¤   }
d10e24 ¤   else
fac7a1 ¤   {
4802ff ¤   ¤   va_start( args, firstOption );
7e1266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
05c414 ¤   ¤   va_end( args );
381b52 ¤   ¤
4419d3 ¤   ¤   err = kPGPError_BadParams;
149371 ¤   }
4c67c5 ¤
e7deb7 ¤   return( err );
d9efe6 }
f3af5a
d7c744 ¤   PGPError
97f64e PGPConventionalDecryptionPassphraseDialog(
54a1bc ¤   PGPContextRef¤  ¤   context,
0c41a1 ¤   PGPOptionListRef¤   firstOption,
a93471 ¤   ...)
1abb36 {
7a8e12 ¤   PGPError¤   err = kPGPError_NoErr;
e146e9 ¤   va_list¤¤   args;
83af5a
988679 ¤   pgpAssert( pgpContextIsValid( context ) );
8167c5 ¤
4fe8d2 ¤   if( pgpContextIsValid( context ) )
5dc7a1 ¤   {
ebf888 ¤   ¤   PGPOptionListRef¤   optionList;
--f7a5 000b443f16d40100292 Page 18 of pgpDialogs.cpp
f11b52 ¤   ¤
3002ff ¤   ¤   va_start( args, firstOption );
c26387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
33c414 ¤   ¤   va_end( args );
1267c5 ¤
9049c8 ¤   ¤   err = pgpPassphraseDialog( context, optionList );
f767c5 ¤
74153d ¤   ¤   PGPFreeOptionList( optionList );
519371 ¤   }
110e24 ¤   else
53c7a1 ¤   {
7302ff ¤   ¤   va_start( args, firstOption );
f41266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
42c414 ¤   ¤   va_end( args );
2c1b52 ¤   ¤
db19d3 ¤   ¤   err = kPGPError_BadParams;
689371 ¤   }
c967c5 ¤
a0deb7 ¤   return( err );
a2efe6 }
d7af5a
db9ecc static const PGPOptionType sOptionsOptionSet[] =
f8bb36 {
b37efd ¤   kCommonAllowedOptions,
642326 ¤   kPGPOptionType_DialogPrompt,
11731c ¤   kPGPOptionType_Checkbox,
ed0c6f ¤   kPGPOptionType_PopupList
5f82f7 };
b5af5a
8d66dd ¤   static PGPError
9dd8da pgpOptionsDialog(
caa1bc ¤   PGPContextRef¤  ¤   context,
789bfc ¤   PGPOptionListRef¤   optionList)
4abb36 {
678f52 ¤   PGPError¤   ¤   ¤   err;
b567c5 ¤
978679 ¤   pgpAssert( pgpContextIsValid( context ) );
37704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
2f67c5 ¤
78bd44 ¤   err = pgpGetOptionListError( optionList );
d8b1f0 ¤   if( IsntPGPError( err ) )
f1c7a1 ¤   {
28399b ¤   ¤   err = pgpCheckOptionsInSet( optionList, sOptionsOptionSet,
2976d0 ¤   ¤   ¤   ¤   ¤   elemsof( sOptionsOptionSet ) );
f286f8 ¤   ¤   if( IsntPGPError( err ) )
b85b34 ¤   ¤   {
c9fbb8 ¤   ¤   ¤   CPGPOptionsDialogOptions¤   options;
3e87c7 ¤   ¤   ¤
f5e5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
53698b ¤   ¤   ¤   if( IsntPGPError( err ) )
faf776 ¤   ¤   ¤   {
49e7bc ¤   ¤   ¤   ¤   err = pgpOptionsDialogPlatform( context, &options );
baa3a6 ¤   ¤   ¤   }
3e0fe4 ¤   ¤   }
8d9371 ¤   }
c167c5 ¤
64deb7 ¤   return( err );
83efe6 }
baaf5a
b2c744 ¤   PGPError
d96716 PGPOptionsDialog(
c4a1bc ¤   PGPContextRef¤  ¤   context,
8941a1 ¤   PGPOptionListRef¤   firstOption,
da3471 ¤   ...)
30bb36 {
8661e0 ¤   PGPError¤   err;
c946e9 ¤   va_list¤¤   args;
26af5a
628679 ¤   pgpAssert( pgpContextIsValid( context ) );
ca67c5 ¤
88e8d2 ¤   if( pgpContextIsValid( context ) )
b4c7a1 ¤   {
--b874 0004830763340100292 Page 19 of pgpDialogs.cpp
cbf888 ¤   ¤   PGPOptionListRef¤   optionList;
2a1b52 ¤   ¤
7402ff ¤   ¤   va_start( args, firstOption );
336387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
5bc414 ¤   ¤   va_end( args );
98af5a
a67a44 ¤   ¤   err = pgpOptionsDialog( context, optionList );
ec1b52 ¤   ¤
fc153d ¤   ¤   PGPFreeOptionList( optionList );
5d9371 ¤   }
ee0e24 ¤   else
65c7a1 ¤   {
4b02ff ¤   ¤   va_start( args, firstOption );
6d1266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
99c414 ¤   ¤   va_end( args );
2a1b52 ¤   ¤
0719d3 ¤   ¤   err = kPGPError_BadParams;
9047d1 ¤   }·
7467c5 ¤
cadeb7 ¤   return( err );
dbefe6 }
ebaf5a
4a8827 static const PGPOptionType sKeyOptionSet[] =
1abb36 {
6c61fe ¤   kCommonAllowedPassphraseOptions,
1ddc84 ¤   kPGPOptionType_VerifyPassphrase
5582f7 };
e1af5a
0a66dd ¤   static PGPError
2f85b1 pgpKeyPassphraseDialog(
c4a1bc ¤   PGPContextRef¤  ¤   context,
055fbe ¤   PGPKeyRef¤  ¤   ¤   theKey,
619bfc ¤   PGPOptionListRef¤   optionList)
06bb36 {
468f52 ¤   PGPError¤   ¤   ¤   err;
0067c5 ¤
798679 ¤   pgpAssert( pgpContextIsValid( context ) );
30704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
2367c5 ¤
8ebd44 ¤   err = pgpGetOptionListError( optionList );
6fb1f0 ¤   if( IsntPGPError( err ) )
62c7a1 ¤   {
2d1068 ¤   ¤   err = pgpCheckOptionsInSet( optionList, sKeyOptionSet,
d73398 ¤   ¤   ¤   ¤   ¤   elemsof( sKeyOptionSet ) );
6c86f8 ¤   ¤   if( IsntPGPError( err ) )
7b5b34 ¤   ¤   {
c88c59 ¤   ¤   ¤   CPGPKeyPassphraseDialogOptions¤ options;
c587c7 ¤   ¤   ¤
c7e5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
39698b ¤   ¤   ¤   if( IsntPGPError( err ) )
baf776 ¤   ¤   ¤   {
9db9f6 ¤   ¤   ¤   ¤   options.mDefaultKey¤= theKey;¤  /* Overloading mDefaultKey */
a32b85 ¤   ¤   ¤   ¤
7a379f ¤   ¤   ¤   ¤   err = pgpKeyPassphraseDialogPlatform( context, &options );
bea3a6 ¤   ¤   ¤   }
da0fe4 ¤   ¤   }
f29371 ¤   }
ae67c5 ¤
93deb7 ¤   return( err );
40efe6 }
e6af5a
5bc744 ¤   PGPError
89874e PGPKeyPassphraseDialog(
4ba1bc ¤   PGPContextRef¤  ¤   context,
895fbe ¤   PGPKeyRef¤  ¤   ¤   theKey,
bd41a1 ¤   PGPOptionListRef¤   firstOption,
5b3471 ¤   ...)
1bbb36 {
ab61e0 ¤   PGPError¤   err;
5646e9 ¤   va_list¤¤   args;
abaf5a
488679 ¤   pgpAssert( pgpContextIsValid( context ) );
--a818 0005cc1b58140100292 Page 20 of pgpDialogs.cpp
435977 ¤   pgpAssert( PGPKeyRefIsValid( theKey ) );
76af5a
b69a79 ¤   if( pgpContextIsValid( context ) &&
22dc22 ¤   ¤   PGPKeyRefIsValid( theKey ) )
aec7a1 ¤   {
5ef888 ¤   ¤   PGPOptionListRef¤   optionList;
821b52 ¤   ¤
3302ff ¤   ¤   va_start( args, firstOption );
786387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
e6c414 ¤   ¤   va_end( args );
dfaf5a
a180ac ¤   ¤   err = pgpKeyPassphraseDialog( context, theKey, optionList );
6e1b52 ¤   ¤
61153d ¤   ¤   PGPFreeOptionList( optionList );
689371 ¤   }
290e24 ¤   else
7cc7a1 ¤   {
b802ff ¤   ¤   va_start( args, firstOption );
061266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
21c414 ¤   ¤   va_end( args );
fe1b52 ¤   ¤
8e19d3 ¤   ¤   err = kPGPError_BadParams;
389371 ¤   }
2767c5 ¤
a7deb7 ¤   return( err );
3fefe6 }
46af5a
b566dd ¤   static PGPError
a61573 FindValidSecretKey(
f0215d ¤   PGPKeySetRef ¤  keySet,
a2620f ¤   Boolean¤¤   ¤   signing,
bb93ef ¤   PGPKeyRef¤  ¤   preferredKey,
3ee095 ¤   PGPKeyRef¤  ¤   *secretKeyPtr)
f3bb36 {
13fb19 ¤   PGPError¤   ¤   err;
725445 ¤   PGPKeyListRef¤  keyList;
b67aeb ¤   PGPKeyPropName¤ keyProperty;
b065c8 ¤   PGPKeyRef¤  ¤   splitKeyRef ¤   ¤   = kInvalidPGPKeyRef;
29fc51 ¤   PGPKeyRef¤  ¤   secretKeyRef ¤  ¤   = kInvalidPGPKeyRef;
84de17 ¤   PGPKeyRef¤  ¤   defaultKey¤ ¤   ¤   = kInvalidPGPKeyRef;
a5b7c4 ¤   PGPBoolean¤ ¤   foundDefaultKey¤¤   = FALSE;
a6bb65 ¤   PGPBoolean¤ ¤   foundPreferredKey¤  = FALSE;
8673dd ¤   PGPBoolean¤ ¤   preferredIsSplitKey¤= FALSE;
fec369 ¤   PGPBoolean¤ ¤   defaultIsSplitKey¤  = FALSE;
4767c5 ¤
d58b51 ¤   *secretKeyPtr = kInvalidPGPKeyRef;
b367c5 ¤
938068 ¤   /* Note that defaultKey may be a split key */
c58130 ¤   (void) PGPGetDefaultPrivateKey( keySet, &defaultKey );
f61575 ¤   if( ! PGPKeyRefIsValid( preferredKey ) )
d4d6ff ¤   ¤   preferredKey = defaultKey;
cf1b52 ¤   ¤
fb1b50 ¤   if( signing )
d9c7a1 ¤   {
b17373 ¤   ¤   keyProperty = kPGPKeyPropCanSign;
ec9371 ¤   }
7f0e24 ¤   else
45c7a1 ¤   {
13cb9e ¤   ¤   keyProperty = kPGPKeyPropCanDecrypt;
cf9371 ¤   }
2d67c5 ¤
792bbd ¤   err = PGPOrderKeySet( keySet, kPGPAnyOrdering, &keyList );
81b1f0 ¤   if( IsntPGPError( err ) )
8ac7a1 ¤   {
5520b4 ¤   ¤   PGPKeyIterRef¤  keyIterator;
c91b52 ¤   ¤
eb46e0 ¤   ¤   err = PGPNewKeyIter( keyList, &keyIterator );
e486f8 ¤   ¤   if( IsntPGPError( err ) )
3d5b34 ¤   ¤   {
b43754 ¤   ¤   ¤   PGPKeyRef¤  theKey;
8a87c7 ¤   ¤   ¤
5ca048 ¤   ¤   ¤   err = PGPKeyIterNext( keyIterator, &theKey );
--c2ad 000f36ec50340100292 Page 21 of pgpDialogs.cpp
ca8f5a ¤   ¤   ¤   while( IsntPGPError( err ) )
69f776 ¤   ¤   ¤   {
196fe4 ¤   ¤   ¤   ¤   PGPBoolean¤ canOperate;
652b85 ¤   ¤   ¤   ¤
595c77 ¤   ¤   ¤   ¤   err = PGPGetKeyBoolean( theKey, keyProperty, &canOperate );
505565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
5572c3 ¤   ¤   ¤   ¤   {
b99be3 ¤   ¤   ¤   ¤   ¤   if( canOperate )
684859 ¤   ¤   ¤   ¤   ¤   {
d8e352 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ isSplitKey = FALSE;
ec94aa ¤   ¤   ¤   ¤   ¤   ¤
cf7518 ¤   ¤   ¤   ¤   ¤   ¤   (void) PGPGetKeyBoolean( theKey,
717858 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropIsSecretShared, &isSplitKey );
70af5a
447ca9 ¤   ¤   ¤   ¤   ¤   ¤   if( theKey == defaultKey )
3b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
e7628e ¤   ¤   ¤   ¤   ¤   ¤   ¤   foundDefaultKey = TRUE;
56c596 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( isSplitKey )
b2a3de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   defaultIsSplitKey = TRUE;
dfdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
0694aa ¤   ¤   ¤   ¤   ¤   ¤
982863 ¤   ¤   ¤   ¤   ¤   ¤   if( theKey == preferredKey )
7e8fec ¤   ¤   ¤   ¤   ¤   ¤   {
1f4b14 ¤   ¤   ¤   ¤   ¤   ¤   ¤   foundPreferredKey = TRUE;
73c596 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( isSplitKey )
040ae6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   preferredIsSplitKey = TRUE;
43db3c ¤   ¤   ¤   ¤   ¤   ¤   }
f194aa ¤   ¤   ¤   ¤   ¤   ¤
d6c32e ¤   ¤   ¤   ¤   ¤   ¤   if( isSplitKey )
fa8fec ¤   ¤   ¤   ¤   ¤   ¤   {
800079 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( ! PGPKeyRefIsValid( splitKeyRef ) )
9718b1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   splitKeyRef = theKey;
65db3c ¤   ¤   ¤   ¤   ¤   ¤   }
127f8b ¤   ¤   ¤   ¤   ¤   ¤   else
628fec ¤   ¤   ¤   ¤   ¤   ¤   {
3cb47d ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( ! PGPKeyRefIsValid( secretKeyRef ) )
cfef6c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   secretKeyRef = theKey;
f8af5a
c8552e ¤   ¤   ¤   ¤   ¤   ¤   ¤   /*
db7371 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ** If we've found the preferred key and we have
2b96c1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ** at least one non-split key, we can stop
eb122b ¤   ¤   ¤   ¤   ¤   ¤   ¤   */
e3531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
f282a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( foundPreferredKey )
00cd67 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   break;
84db3c ¤   ¤   ¤   ¤   ¤   ¤   }
7a1c89 ¤   ¤   ¤   ¤   ¤   }
57ae30 ¤   ¤   ¤   ¤   ¤
69fe51 ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNext( keyIterator, &theKey );
602613 ¤   ¤   ¤   ¤   }
eaa3a6 ¤   ¤   ¤   }
d287c7 ¤   ¤   ¤
5d6ae1 ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
f5bd37 ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
db2b85 ¤   ¤   ¤   ¤
7e3433 ¤   ¤   ¤   PGPFreeKeyIter( keyIterator );
790fe4 ¤   ¤   }
231b52 ¤   ¤
6c6efb ¤   ¤   PGPFreeKeyList( keyList );
509371 ¤   }
eeaf5a
fcb1f0 ¤   if( IsntPGPError( err ) )
10c7a1 ¤   {
bceadb ¤   ¤   if( PGPKeyRefIsValid( secretKeyRef ) )
6d5b34 ¤   ¤   {
327aad ¤   ¤   ¤   /*
cda15b ¤   ¤   ¤   ** Do not allow a split key as the best secret key
9aa368 ¤   ¤   ¤   ** if we're decrypting and at least one other secret
d1982e ¤   ¤   ¤   ** key is available.
fe3da8 ¤   ¤   ¤   */
a887c7 ¤   ¤   ¤
f324d5 ¤   ¤   ¤   if( ! signing )
--fb34 000df16d02940100292 Page 22 of pgpDialogs.cpp
99f776 ¤   ¤   ¤   {
4c12dc ¤   ¤   ¤   ¤   if( preferredIsSplitKey )
2eae38 ¤   ¤   ¤   ¤   ¤   foundPreferredKey = FALSE;
f4af5a
01999f ¤   ¤   ¤   ¤   if( defaultIsSplitKey )
ee5dd1 ¤   ¤   ¤   ¤   ¤   foundDefaultKey = FALSE;
35a3a6 ¤   ¤   ¤   }
7e87c7 ¤   ¤   ¤
954182 ¤   ¤   ¤   if( foundPreferredKey )
d9f776 ¤   ¤   ¤   {
cdc3f5 ¤   ¤   ¤   ¤   *secretKeyPtr = preferredKey;
d7a3a6 ¤   ¤   ¤   }
b16b5a ¤   ¤   ¤   else if( foundDefaultKey )
26f776 ¤   ¤   ¤   {
73200f ¤   ¤   ¤   ¤   *secretKeyPtr = defaultKey;
b5a3a6 ¤   ¤   ¤   }
ddbb8c ¤   ¤   ¤   else
4d8cf3 ¤   ¤   ¤   {¤
469208 ¤   ¤   ¤   ¤   *secretKeyPtr = secretKeyRef;
3ea3a6 ¤   ¤   ¤   }
810fe4 ¤   ¤   }
796db0 ¤   ¤   else if( PGPKeyRefIsValid( splitKeyRef ) )
955b34 ¤   ¤   {
3c4182 ¤   ¤   ¤   if( foundPreferredKey )
bef776 ¤   ¤   ¤   {
b7c3f5 ¤   ¤   ¤   ¤   *secretKeyPtr = preferredKey;
0fa3a6 ¤   ¤   ¤   }
8a6b5a ¤   ¤   ¤   else if( foundDefaultKey )
70f776 ¤   ¤   ¤   {
cc200f ¤   ¤   ¤   ¤   *secretKeyPtr = defaultKey;
bca3a6 ¤   ¤   ¤   }
84bb8c ¤   ¤   ¤   else
458cf3 ¤   ¤   ¤   {¤
af1fa3 ¤   ¤   ¤   ¤   *secretKeyPtr = splitKeyRef;
9ca3a6 ¤   ¤   ¤   }
b087c7 ¤   ¤   ¤
62e67f ¤   ¤   ¤   if( signing )
23f776 ¤   ¤   ¤   {
635054 ¤   ¤   ¤   ¤   err = kPGPError_KeyUnusableForSignature;
92a3a6 ¤   ¤   ¤   }
e6bb8c ¤   ¤   ¤   else
d9f776 ¤   ¤   ¤   {
84e68c ¤   ¤   ¤   ¤   err = kPGPError_KeyUnusableForDecryption;
bba3a6 ¤   ¤   ¤   }
e10fe4 ¤   ¤   }
a20e1d ¤   ¤   else
5c5b34 ¤   ¤   {
f37d4f ¤   ¤   ¤   err = kPGPError_SecretKeyNotFound;
720fe4 ¤   ¤   }
369371 ¤   }
4567c5 ¤
9edeb7 ¤   return( err );
4befe6 }
c0af5a
cfc7e8 static const PGPOptionType sSigningOptionSet[] =
e3bb36 {
d861fe ¤   kCommonAllowedPassphraseOptions,
304935 ¤   kPGPOptionType_DefaultKey,
4c1a49 ¤   kPGPOptionType_VerifyPassphrase,
8f98d4 ¤   kPGPOptionType_FindMatchingKey
1c82f7 };
f5af5a
a566dd ¤   static PGPError
5a2b00 pgpSigningPassphraseDialog(
50a1bc ¤   PGPContextRef¤  ¤   context,
2a3ec1 ¤   PGPKeySetRef¤   ¤   allKeys,
63e544 ¤   PGPOptionListRef¤   optionList,
3ad85d ¤   PGPKeyRef¤  ¤   ¤   *signingKey)
03bb36 {
0d61e0 ¤   PGPError¤   err;
5867c5 ¤
df8679 ¤   pgpAssert( pgpContextIsValid( context ) );
--4294 0006c37fa3c40100292 Page 23 of pgpDialogs.cpp
38704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
5067c5 ¤
21bd44 ¤   err = pgpGetOptionListError( optionList );
82b1f0 ¤   if( IsntPGPError( err ) )
bfc7a1 ¤   {
be86cf ¤   ¤   err = pgpCheckOptionsInSet( optionList, sSigningOptionSet,
b111af ¤   ¤   ¤   ¤   ¤   elemsof( sSigningOptionSet ) );
8886f8 ¤   ¤   if( IsntPGPError( err ) )
0a5b34 ¤   ¤   {
4769e7 ¤   ¤   ¤   CPGPSigningPassphraseDialogOptions¤ options;
3687c7 ¤   ¤   ¤
1fe5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
50698b ¤   ¤   ¤   if( IsntPGPError( err ) )
9cf776 ¤   ¤   ¤   {
09c312 ¤   ¤   ¤   ¤   err = FindValidSecretKey( allKeys, TRUE, options.mDefaultKey,
20a871 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &options.mDefaultKey );
4b5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
db72c3 ¤   ¤   ¤   ¤   {
da2e93 ¤   ¤   ¤   ¤   ¤   options.mKeySet¤¤   ¤   ¤   = allKeys;
6c658b ¤   ¤   ¤   ¤   ¤   options.mPassphraseKeyPtr¤  = signingKey;
7bae30 ¤   ¤   ¤   ¤   ¤
abbd8d ¤   ¤   ¤   ¤   ¤   err = pgpSigningPassphraseDialogPlatform( context,
160ae3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &options );
b02613 ¤   ¤   ¤   ¤   }
31af2e ¤   ¤   ¤   ¤   else if( err == kPGPError_KeyUnusableForSignature )
5972c3 ¤   ¤   ¤   ¤   {
ac822b ¤   ¤   ¤   ¤   ¤   /* Special case. We return a split key, if found */
22197c ¤   ¤   ¤   ¤   ¤   *signingKey = options.mDefaultKey;
f82613 ¤   ¤   ¤   ¤   }
afa3a6 ¤   ¤   ¤   }
a70fe4 ¤   ¤   }
dd9371 ¤   }
7d67c5 ¤
0bdeb7 ¤   return( err );
c8efe6 }
daaf5a
7ac744 ¤   PGPError
9b5b6a PGPSigningPassphraseDialog(
21a1bc ¤   PGPContextRef¤  ¤   context,
223ec1 ¤   PGPKeySetRef¤   ¤   allKeys,
62a6e5 ¤   PGPKeyRef¤  ¤   ¤   *signingKey,
5641a1 ¤   PGPOptionListRef¤   firstOption,
b83471 ¤   ...)
2bbb36 {
7d61e0 ¤   PGPError¤   err;
0346e9 ¤   va_list¤¤   args;
6daf5a
6b8679 ¤   pgpAssert( pgpContextIsValid( context ) );
8b076a ¤   pgpAssert( PGPKeySetRefIsValid( allKeys ) );
07af5a
1e3d54 ¤   if( IsntNull( signingKey ) )
727c93 ¤   ¤   *signingKey = kInvalidPGPKeyRef;
72af5a
599a79 ¤   if( pgpContextIsValid( context ) &&
21ecdb ¤   ¤   PGPKeySetRefIsValid( allKeys ) &&
453b7b ¤   ¤   IsntNull( signingKey ) )
71c7a1 ¤   {
e9f888 ¤   ¤   PGPOptionListRef¤   optionList;
c11b52 ¤   ¤
a302ff ¤   ¤   va_start( args, firstOption );
056387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
14c414 ¤   ¤   va_end( args );
96af5a
e7ffea ¤   ¤   err = pgpSigningPassphraseDialog( context, allKeys,
4a4d34 ¤   ¤   ¤   ¤   ¤   ¤   optionList, signingKey );
611b52 ¤   ¤
a5153d ¤   ¤   PGPFreeOptionList( optionList );
479371 ¤   }
770e24 ¤   else
95c7a1 ¤   {
d602ff ¤   ¤   va_start( args, firstOption );
6c1266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
--9b63 0003363f6fa40100292 Page 24 of pgpDialogs.cpp
c0c414 ¤   ¤   va_end( args );
511b52 ¤   ¤
2619d3 ¤   ¤   err = kPGPError_BadParams;
f69371 ¤   }
4c67c5 ¤
23deb7 ¤   return( err );
37efe6 }
c3af5a
a58e82 static const PGPOptionType sDecryptionOptionSet[] =
e7bb36 {
1261fe ¤   kCommonAllowedPassphraseOptions,
624935 ¤   kPGPOptionType_DefaultKey,
011a49 ¤   kPGPOptionType_VerifyPassphrase,
724888 ¤   kPGPOptionType_FindMatchingKey,
e3f26e ¤   kPGPOptionType_KeyServerUpdateParams
5882f7 };
19af5a
d666dd ¤   static PGPError
841208 pgpDecryptionPassphraseDialog(
6fa1bc ¤   PGPContextRef¤  ¤   context,
780ae9 ¤   PGPKeySetRef¤   ¤   recipientKeys,
362a30 ¤   const PGPKeyID¤ ¤   keyIDList[],
b0f46c ¤   PGPUInt32¤  ¤   ¤   keyIDCount,
40e544 ¤   PGPOptionListRef¤   optionList,
27752f ¤   PGPKeyRef¤  ¤   ¤   *decryptionKey)
76bb36 {
ca61e0 ¤   PGPError¤   err;
0c67c5 ¤
2b8679 ¤   pgpAssert( pgpContextIsValid( context ) );
86704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
d467c5 ¤
65bd44 ¤   err = pgpGetOptionListError( optionList );
ffb1f0 ¤   if( IsntPGPError( err ) )
f3c7a1 ¤   {
21bca7 ¤   ¤   err = pgpCheckOptionsInSet( optionList, sDecryptionOptionSet,
9e0790 ¤   ¤   ¤   ¤   ¤   elemsof( sDecryptionOptionSet ) );
6286f8 ¤   ¤   if( IsntPGPError( err ) )
265b34 ¤   ¤   {
4a4ff2 ¤   ¤   ¤   CPGPDecryptionPassphraseDialogOptions¤  options;
7faf5a
bbe5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
72698b ¤   ¤   ¤   if( IsntPGPError( err ) )
30f776 ¤   ¤   ¤   {
d9c06f ¤   ¤   ¤   ¤   err = FindValidSecretKey( recipientKeys, FALSE,
d72576 ¤   ¤   ¤   ¤   ¤   ¤   ¤   options.mDefaultKey, &options.mDefaultKey );
132b85 ¤   ¤   ¤   ¤
3ff29a ¤   ¤   ¤   ¤   /* Proceed with dialog even when no keys are found */
16770a ¤   ¤   ¤   ¤   if( err == kPGPError_SecretKeyNotFound )
f3b37b ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
b5ae30 ¤   ¤   ¤   ¤   ¤
795565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
4272c3 ¤   ¤   ¤   ¤   {
43e971 ¤   ¤   ¤   ¤   ¤   options.mKeySet¤¤   ¤   ¤   = recipientKeys;
0ba206 ¤   ¤   ¤   ¤   ¤   options.mPassphraseKeyPtr¤  = decryptionKey;
5d3192 ¤   ¤   ¤   ¤   ¤   options.mKeyIDList¤ ¤   ¤   = keyIDList;
34099e ¤   ¤   ¤   ¤   ¤   options.mKeyIDCount¤¤   ¤   = keyIDCount;
7dae30 ¤   ¤   ¤   ¤   ¤
17b899 ¤   ¤   ¤   ¤   ¤   err = options.GatherMissingKeys();
0a6ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
f04859 ¤   ¤   ¤   ¤   ¤   {
435e41 ¤   ¤   ¤   ¤   ¤   ¤   err = pgpDecryptionPassphraseDialogPlatform( context,
669ca2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &options );
e41c89 ¤   ¤   ¤   ¤   ¤   }
ecae30 ¤   ¤   ¤   ¤   ¤
0b4278 ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err ) &&
d7fe3d ¤   ¤   ¤   ¤   ¤   ¤   IsntNull( options.mNewKeys ) &&
6551ab ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRefIsValid( *options.mNewKeys ) )
5e4859 ¤   ¤   ¤   ¤   ¤   {
d9075c ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( *options.mNewKeys );
692b40 ¤   ¤   ¤   ¤   ¤   ¤   *options.mNewKeys = kInvalidPGPKeySetRef;
681c89 ¤   ¤   ¤   ¤   ¤   }
332613 ¤   ¤   ¤   ¤   }
--20d6 0000481332a40100292 Page 25 of pgpDialogs.cpp
6678ea ¤   ¤   ¤   ¤   else if( err == kPGPError_KeyUnusableForDecryption )
9a72c3 ¤   ¤   ¤   ¤   {
6b822b ¤   ¤   ¤   ¤   ¤   /* Special case. We return a split key, if found */
ad28cd ¤   ¤   ¤   ¤   ¤   *decryptionKey = options.mDefaultKey;
7d2613 ¤   ¤   ¤   ¤   }
b3a3a6 ¤   ¤   ¤   }
870fe4 ¤   ¤   }
6e9371 ¤   }
7067c5 ¤
8fdeb7 ¤   return( err );
c1efe6 }
deaf5a
95c744 ¤   PGPError
5594fb PGPDecryptionPassphraseDialog(
9fa1bc ¤   PGPContextRef¤  ¤   context,
920ae9 ¤   PGPKeySetRef¤   ¤   recipientKeys,
28f46c ¤   PGPUInt32¤  ¤   ¤   keyIDCount,
872a30 ¤   const PGPKeyID¤ ¤   keyIDList[],
520b97 ¤   PGPKeyRef¤  ¤   ¤   *decryptionKey,
ba41a1 ¤   PGPOptionListRef¤   firstOption,
c93471 ¤   ...)
27bb36 {
d78e12 ¤   PGPError¤   err = kPGPError_NoErr;
3e46e9 ¤   va_list¤¤   args;
ff67c5 ¤
3d8679 ¤   pgpAssert( pgpContextIsValid( context ) );
ced406 ¤   pgpAssert( PGPKeySetRefIsValid( recipientKeys ) );
e467c5 ¤
415d14 ¤   if( IsntNull( decryptionKey ) )
7f0b13 ¤   ¤   *decryptionKey = kInvalidPGPKeyRef;
d1af5a
ac9a79 ¤   if( pgpContextIsValid( context ) &&
ec66f6 ¤   ¤   PGPKeySetRefIsValid( recipientKeys ) &&
2a4038 ¤   ¤   IsntNull( decryptionKey ) )
fdc7a1 ¤   {
a7f888 ¤   ¤   PGPOptionListRef¤   optionList;
2e1b52 ¤   ¤
cd02ff ¤   ¤   va_start( args, firstOption );
9b6387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
47c414 ¤   ¤   va_end( args );
f0af5a
ff7b9c ¤   ¤   err = pgpDecryptionPassphraseDialog( context, recipientKeys, keyIDList,
2313e5 ¤   ¤   ¤   ¤   ¤   ¤   keyIDCount, optionList, decryptionKey );
8f1b52 ¤   ¤
5a153d ¤   ¤   PGPFreeOptionList( optionList );
249371 ¤   }
fd0e24 ¤   else
bec7a1 ¤   {
df02ff ¤   ¤   va_start( args, firstOption );
051266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
f2c414 ¤   ¤   va_end( args );
c11b52 ¤   ¤
5519d3 ¤   ¤   err = kPGPError_BadParams;
979371 ¤   }
f167c5 ¤
60deb7 ¤   return( err );
99efe6 }
93af5a
1aaf5a
6c3a31 static const PGPOptionType sConfirmationPassphraseOptionSet[] =
79bb36 {
6861fe ¤   kCommonAllowedPassphraseOptions,
59d24a ¤   kPGPOptionType_ShowPassphraseQuality
d782f7 };
1caf5a
ef66dd ¤   static PGPError
e2146d pgpConfirmationPassphraseDialog(
35a1bc ¤   PGPContextRef¤  ¤   context,
4efeff ¤   PGPOptionListRef ¤  optionList,
107405 ¤   PGPUInt32¤  ¤   ¤   minPassphraseLength)
5cbb36 {
0461e0 ¤   PGPError¤   err;
--6ef1 000f6be580240100292 Page 26 of pgpDialogs.cpp
e0af5a
7d8679 ¤   pgpAssert( pgpContextIsValid( context ) );
d5704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
f367c5 ¤
01bd44 ¤   err = pgpGetOptionListError( optionList );
60b1f0 ¤   if( IsntPGPError( err ) )
c1c7a1 ¤   {
b82f35 ¤   ¤   err = pgpCheckOptionsInSet( optionList,
6b8b32 ¤   ¤   ¤   ¤   ¤   sConfirmationPassphraseOptionSet,
10974a ¤   ¤   ¤   ¤   ¤   elemsof( sConfirmationPassphraseOptionSet ) );
5c86f8 ¤   ¤   if( IsntPGPError( err ) )
6e5b34 ¤   ¤   {
c41777 ¤   ¤   ¤   CPGPConfirmationPassphraseDialogOptions¤options;
c287c7 ¤   ¤   ¤
fae5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
2c698b ¤   ¤   ¤   if( IsntPGPError( err ) )
5cf776 ¤   ¤   ¤   {
2cc145 ¤   ¤   ¤   ¤   if( options.mMinPassphraseLength < minPassphraseLength )
c472c3 ¤   ¤   ¤   ¤   {
4a0937 ¤   ¤   ¤   ¤   ¤   options.mMinPassphraseLength = minPassphraseLength;
332613 ¤   ¤   ¤   ¤   }
21ae30 ¤   ¤   ¤   ¤   ¤
9b550e ¤   ¤   ¤   ¤   err = pgpConfirmationPassphraseDialogPlatform( context,·
6e0ae3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &options );
fea3a6 ¤   ¤   ¤   }
940fe4 ¤   ¤   }
519371 ¤   }
d367c5 ¤
fddeb7 ¤   return( err );
97efe6 }
89af5a
a2c744 ¤   PGPError
3ea333 PGPConfirmationPassphraseDialog(
88a1bc ¤   PGPContextRef¤  ¤   context,
0e41a1 ¤   PGPOptionListRef¤   firstOption,
923471 ¤   ...)
55bb36 {
a68e12 ¤   PGPError¤   err = kPGPError_NoErr;
2a46e9 ¤   va_list¤¤   args;
feaf5a
f88679 ¤   pgpAssert( pgpContextIsValid( context ) );
1767c5 ¤
87e8d2 ¤   if( pgpContextIsValid( context ) )
07c7a1 ¤   {
17f888 ¤   ¤   PGPOptionListRef¤   optionList;
e01b52 ¤   ¤
7602ff ¤   ¤   va_start( args, firstOption );
386387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
96c414 ¤   ¤   va_end( args );
ce67c5 ¤
3d18b9 ¤   ¤   err = pgpConfirmationPassphraseDialog( context, optionList, 0 );
8067c5 ¤
8c153d ¤   ¤   PGPFreeOptionList( optionList );
449371 ¤   }
220e24 ¤   else
3dc7a1 ¤   {
ec02ff ¤   ¤   va_start( args, firstOption );
db1266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
94c414 ¤   ¤   va_end( args );
011b52 ¤   ¤
dc19d3 ¤   ¤   err = kPGPError_BadParams;
139371 ¤   }
e367c5 ¤
46deb7 ¤   return( err );
4defe6 }
8daf5a
25c744 ¤   PGPError
594cea PGPConventionalEncryptionPassphraseDialog(
54a1bc ¤   PGPContextRef¤  ¤   context,
5c41a1 ¤   PGPOptionListRef¤   firstOption,
133471 ¤   ...)
f6bb36 {
--88ee 0003ea2766740100292 Page 27 of pgpDialogs.cpp
868e12 ¤   PGPError¤   err = kPGPError_NoErr;
5c46e9 ¤   va_list¤¤   args;
e1af5a
a18679 ¤   pgpAssert( pgpContextIsValid( context ) );
f967c5 ¤
dfe8d2 ¤   if( pgpContextIsValid( context ) )
89c7a1 ¤   {
e2f888 ¤   ¤   PGPOptionListRef¤   optionList;
951b52 ¤   ¤
bd02ff ¤   ¤   va_start( args, firstOption );
0c6387 ¤   ¤   optionList = pgpBuildOptionListArgs(context, FALSE, firstOption, args);
20c414 ¤   ¤   va_end( args );
a767c5 ¤
7718b9 ¤   ¤   err = pgpConfirmationPassphraseDialog( context, optionList, 0 );
6f67c5 ¤
5c153d ¤   ¤   PGPFreeOptionList( optionList );
769371 ¤   }
450e24 ¤   else
45c7a1 ¤   {
8b02ff ¤   ¤   va_start( args, firstOption );
7d1266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
52c414 ¤   ¤   va_end( args );
8f1b52 ¤   ¤
0719d3 ¤   ¤   err = kPGPError_BadParams;
bd9371 ¤   }
5e67c5 ¤
94deb7 ¤   return( err );
2aefe6 }
d2af5a
f1ebaa static const PGPOptionType sRecipientOptionSet[] =
46bb36 {
ea7efd ¤   kCommonAllowedOptions,
4f2326 ¤   kPGPOptionType_DialogPrompt,
a5250d ¤   kPGPOptionType_DialogOptions,
809693 ¤   kPGPOptionType_DefaultRecipients,
e70a91 ¤   kPGPOptionType_DisplayMarginalValidity,
9bb98f ¤   kPGPOptionType_IgnoreMarginalValidity,
055621 ¤   kPGPOptionType_RecipientGroups,
027ddb ¤   kPGPOptionType_ARREnforcement,
f75233 ¤   kPGPOptionType_KeyServerUpdateParams,
e4bc6e ¤   kPGPOptionType_RecipientList
ea82f7 };
65af5a
6c66dd ¤   static PGPError
f22549 pgpRecipientDialog(
34a1bc ¤   PGPContextRef¤  ¤   context,
7d3ec1 ¤   PGPKeySetRef¤   ¤   allKeys,
2f381b ¤   PGPBoolean¤ ¤   ¤   alwaysDisplay,
32e544 ¤   PGPOptionListRef¤   optionList,
8e29f1 ¤   PGPKeySetRef ¤  ¤   *recipientKeys)
89bb36 {
928f52 ¤   PGPError¤   ¤   ¤   err;
5167c5 ¤
f08679 ¤   pgpAssert( pgpContextIsValid( context ) );
97704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
be67c5 ¤
34bd44 ¤   err = pgpGetOptionListError( optionList );
01b1f0 ¤   if( IsntPGPError( err ) )
13c7a1 ¤   {
ce100d ¤   ¤   err = pgpCheckOptionsInSet( optionList, sRecipientOptionSet,
ceb21a ¤   ¤   ¤   ¤   ¤   elemsof( sRecipientOptionSet ) );
9886f8 ¤   ¤   if( IsntPGPError( err ) )
bb5b34 ¤   ¤   {
20698b ¤   ¤   ¤   CPGPRecipientDialogOptions¤ options;
b187c7 ¤   ¤   ¤
3de5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
b8698b ¤   ¤   ¤   if( IsntPGPError( err ) )
49f776 ¤   ¤   ¤   {
859038 ¤   ¤   ¤   ¤   PGPKeySetRef¤   workingKeySet;
002b85 ¤   ¤   ¤   ¤
82de7f ¤   ¤   ¤   ¤   // Copy the set of known keys into an in-memory set so we can
3e1b00 ¤   ¤   ¤   ¤   // make additions via key server searches
--9ea4 000b5c5886440100292 Page 28 of pgpDialogs.cpp
9f2b85 ¤   ¤   ¤   ¤
c31ab6 ¤   ¤   ¤   ¤   err = PGPNewKeySet( context, &workingKeySet );
1c5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
6672c3 ¤   ¤   ¤   ¤   {
63e272 ¤   ¤   ¤   ¤   ¤   err = PGPAddKeys( allKeys, workingKeySet );
736ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
7f4859 ¤   ¤   ¤   ¤   ¤   {
ad4422 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges( workingKeySet );
50239e ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
b38fec ¤   ¤   ¤   ¤   ¤   ¤   {
17f6df ¤   ¤   ¤   ¤   ¤   ¤   ¤   options.mClientKeySet¤  ¤   = workingKeySet;
762367 ¤   ¤   ¤   ¤   ¤   ¤   ¤   options.mAlwaysDisplay¤ ¤   = alwaysDisplay;
93d0ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   options.mRecipientKeysPtr¤  = recipientKeys;
30531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
ceaeea ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = pgpRecipientDialogPlatform( context,
efc90e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &options );
f34825 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
7443fe ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err ) &&
88b576 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   IsntNull( options.mNewKeys ) &&
cd928c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRefIsValid( *options.mNewKeys ) )
bd06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
4cfe2e ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( *options.mNewKeys );
7828d5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *options.mNewKeys = kInvalidPGPKeySetRef;
a25268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
d7531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
484159 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( workingKeySet );
fadb3c ¤   ¤   ¤   ¤   ¤   ¤   }
7d1c89 ¤   ¤   ¤   ¤   ¤   }
9a2613 ¤   ¤   ¤   ¤   }
1ea3a6 ¤   ¤   ¤   }
fa0fe4 ¤   ¤   }
a39371 ¤   }
f167c5 ¤
56deb7 ¤   return( err );
afefe6 }
b9af5a
c9c744 ¤   PGPError
140b3f PGPRecipientDialog(
25a1bc ¤   PGPContextRef¤  ¤   context,
f13ec1 ¤   PGPKeySetRef¤   ¤   allKeys,
5cc1b7 ¤   PGPBoolean¤ ¤   ¤   alwaysDisplayDialog,
625749 ¤   PGPKeySetRef ¤  ¤   *recipientKeys,
f541a1 ¤   PGPOptionListRef¤   firstOption,
5f3471 ¤   ...)
00bb36 {
7461e0 ¤   PGPError¤   err;
ed46e9 ¤   va_list¤¤   args;
c7af5a
978679 ¤   pgpAssert( pgpContextIsValid( context ) );
f1076a ¤   pgpAssert( PGPKeySetRefIsValid( allKeys ) );
01aa93 ¤   pgpAssert( IsntNull( recipientKeys ) );
c2af5a
609a79 ¤   if( pgpContextIsValid( context ) &&
52ecdb ¤   ¤   PGPKeySetRefIsValid( allKeys ) &&
1fad4b ¤   ¤   IsntNull( recipientKeys ) )
33c7a1 ¤   {
a6f888 ¤   ¤   PGPOptionListRef¤   optionList;
f71b52 ¤   ¤
5702ff ¤   ¤   va_start( args, firstOption );
802e8f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE, firstOption,
f4d195 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   args );
3dc414 ¤   ¤   va_end( args );
e2af5a
aa9331 ¤   ¤   err = pgpRecipientDialog( context, allKeys, alwaysDisplayDialog,
e1c127 ¤   ¤   ¤   ¤   ¤   ¤   optionList, recipientKeys );
9e1b52 ¤   ¤
ef153d ¤   ¤   PGPFreeOptionList( optionList );
1f9371 ¤   }
740e24 ¤   else
2dc7a1 ¤   {
a902ff ¤   ¤   va_start( args, firstOption );
b51266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
--f1bb 0009a83565c40100292 Page 29 of pgpDialogs.cpp
c0c414 ¤   ¤   va_end( args );
511b52 ¤   ¤
2619d3 ¤   ¤   err = kPGPError_BadParams;
dc47d1 ¤   }·
cb67c5 ¤
37deb7 ¤   return( err );
d4efe6 }
88af5a
a24a34 static const PGPOptionType sRandomDataOptionSet[] =
fbbb36 {
847efd ¤   kCommonAllowedOptions,
e2703c ¤   kPGPOptionType_DialogPrompt
1e82f7 };
87af5a
1966dd ¤   static PGPError
1ea260 pgpCollectRandomDataDialog(
85a1bc ¤   PGPContextRef¤  ¤   context,
1a7de6 ¤   PGPUInt32¤  ¤   ¤   neededEntropyBits,
879bfc ¤   PGPOptionListRef¤   optionList)
c8bb36 {
2761e0 ¤   PGPError¤   err;
4567c5 ¤
de8679 ¤   pgpAssert( pgpContextIsValid( context ) );
48704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
2467c5 ¤
65bd44 ¤   err = pgpGetOptionListError( optionList );
90b1f0 ¤   if( IsntPGPError( err ) )
8cc7a1 ¤   {
204a73 ¤   ¤   err = pgpCheckOptionsInSet( optionList, sRandomDataOptionSet,
8bd7e9 ¤   ¤   ¤   ¤   ¤   elemsof( sRandomDataOptionSet ) );
6586f8 ¤   ¤   if( IsntPGPError( err ) )
ee5b34 ¤   ¤   {
71a0f7 ¤   ¤   ¤   CPGPRandomDataDialogOptions¤options;
2187c7 ¤   ¤   ¤
3fe5ee ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
f9698b ¤   ¤   ¤   if( IsntPGPError( err ) )
9cf776 ¤   ¤   ¤   {
5460f4 ¤   ¤   ¤   ¤   options.mNeededEntropyBits = neededEntropyBits;
962b85 ¤   ¤   ¤   ¤
319817 ¤   ¤   ¤   ¤   err = pgpCollectRandomDataDialogPlatform( context, &options );
3aa3a6 ¤   ¤   ¤   }
da0fe4 ¤   ¤   }
c69371 ¤   }
3467c5 ¤
0edeb7 ¤   return( err );
0cefe6 }
57af5a
bcc744 ¤   PGPError
fbd20a PGPCollectRandomDataDialog(
8dba07 ¤   PGPContextRef ¤ ¤   context,
257de6 ¤   PGPUInt32¤  ¤   ¤   neededEntropyBits,
934ae2 ¤   PGPOptionListRef ¤  firstOption,
5b5825 ¤   ... )
fdbb36 {
4361e0 ¤   PGPError¤   err;
2f46e9 ¤   va_list¤¤   args;
9eaf5a
018679 ¤   pgpAssert( pgpContextIsValid( context ) );
6367c5 ¤
4de8d2 ¤   if( pgpContextIsValid( context ) )
8dc7a1 ¤   {
52f888 ¤   ¤   PGPOptionListRef¤   optionList;
261b52 ¤   ¤
6b02ff ¤   ¤   va_start( args, firstOption );
b92e8f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE, firstOption,
d0d195 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   args );
07c414 ¤   ¤   va_end( args );
c5af5a
74aa3b ¤   ¤   err = pgpCollectRandomDataDialog( context, neededEntropyBits,
5f4b61 ¤   ¤   ¤   ¤   ¤   ¤   optionList );
9d1b52 ¤   ¤
9a153d ¤   ¤   PGPFreeOptionList( optionList );
--108f 00046d8a0f640100292 Page 30 of pgpDialogs.cpp
a19371 ¤   }
0e0e24 ¤   else
96c7a1 ¤   {
7202ff ¤   ¤   va_start( args, firstOption );
d51266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
6bc414 ¤   ¤   va_end( args );
091b52 ¤   ¤
0419d3 ¤   ¤   err = kPGPError_BadParams;
c447d1 ¤   }·
ce67c5 ¤
0cdeb7 ¤   return( err );
16efe6 }
2baf5a
c60a89 static const PGPOptionType sSearchKeyServerOptionSet[] =
abbb36 {
ade72a ¤   kCommonAllowedKeyServerOptions,
95cf10 ¤   kPGPOptionType_KeyServerSearchFilter,
15f8f1 ¤   kPGPOptionType_KeyServerSearchKeyIDList,
9acd2d ¤   kPGPOptionType_KeyServerSearchKey,
54116a ¤   kPGPOptionType_KeyServerSearchKeySet
4482f7 };
3baf5a
78afb9 #if PGP_WIN32
ebc744 ¤   PGPError
4131d3 pgpCheckNetworklibAvailability(void)
3bbb36 {
126900 ¤   // We're simply static linking for now.
d22d68 ¤   return( kPGPError_NoErr );
beefe6 }
0baf5a
f57454 #endif
10af5a
6c66dd ¤   static PGPError
6a0fbf pgpSearchKeyServerDialog(
9597bc ¤   PGPContextRef ¤ ¤   ¤   context,
46cc83 ¤   const PGPKeyServerSpec ¤serverList[],
b211fc ¤   PGPUInt32¤  ¤   ¤   ¤   serverCount,
c35175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
ce7089 ¤   PGPBoolean¤ ¤   ¤   ¤   searchAllServers,
5fe360 ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys,
ded72a ¤   PGPOptionListRef¤   ¤   optionList)
09bb36 {
3861e0 ¤   PGPError¤   err;
bf67c5 ¤
51704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
7167c5 ¤
f3bd44 ¤   err = pgpGetOptionListError( optionList );
82b1f0 ¤   if( IsntPGPError( err ) )
f6c7a1 ¤   {
f8e195 ¤   ¤   err = pgpCheckNetworklibAvailability();
f086f8 ¤   ¤   if( IsntPGPError( err ) )
7e5b34 ¤   ¤   {
23791e ¤   ¤   ¤   err = pgpCheckOptionsInSet( optionList, sSearchKeyServerOptionSet,
a1ca05 ¤   ¤   ¤   ¤   ¤   ¤   elemsof( sSearchKeyServerOptionSet ) );
aa698b ¤   ¤   ¤   if( IsntPGPError( err ) )
91f776 ¤   ¤   ¤   {
c04420 ¤   ¤   ¤   ¤   CPGPSearchKeyServerDialogOptions¤   options;
c32b85 ¤   ¤   ¤   ¤
f9d880 ¤   ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
895565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
ff72c3 ¤   ¤   ¤   ¤   {
cb710e ¤   ¤   ¤   ¤   ¤   options.mServerList¤¤   ¤   = serverList;
eeb09b ¤   ¤   ¤   ¤   ¤   options.mServerCount¤   ¤   = serverCount;
97bb40 ¤   ¤   ¤   ¤   ¤   options.mTLSContext¤¤   ¤   = tlsContext;
cde3fa ¤   ¤   ¤   ¤   ¤   options.mSearchAllServers¤  = searchAllServers;
1cb002 ¤   ¤   ¤   ¤   ¤   options.mNewKeys¤   ¤   ¤   = foundKeys;
23ae30 ¤   ¤   ¤   ¤   ¤
557d7f ¤   ¤   ¤   ¤   ¤   err = pgpSearchKeyServerDialogPlatform(context, &options);
b52613 ¤   ¤   ¤   ¤   }
4aa3a6 ¤   ¤   ¤   }
a60fe4 ¤   ¤   }
469371 ¤   }
--60e5 000c0c3e08b40100292 Page 31 of pgpDialogs.cpp
2a67c5 ¤
4fdeb7 ¤   return( err );
29efe6 }
02af5a
ccc744 ¤   PGPError
6dd36d PGPSearchKeyServerDialog(
2f97bc ¤   PGPContextRef ¤ ¤   ¤   context,
8311fc ¤   PGPUInt32¤  ¤   ¤   ¤   serverCount,
a5cc83 ¤   const PGPKeyServerSpec ¤serverList[],
d85175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
f17089 ¤   PGPBoolean¤ ¤   ¤   ¤   searchAllServers,
c4e360 ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys,
c7e88a ¤   PGPOptionListRef ¤  ¤   firstOption,
cd5825 ¤   ... )
e0bb36 {
8f61e0 ¤   PGPError¤   err;
9846e9 ¤   va_list¤¤   args;
20af5a
5b8679 ¤   pgpAssert( pgpContextIsValid( context ) );
2060d1 ¤   pgpAssert( IsntNull( serverList ) );
f05d48 ¤   pgpAssert( serverCount >= 1 );
050a1f ¤   pgpAssert( IsntNull( foundKeys ) );
dc67c5 ¤
1da362 ¤   if( IsntNull( foundKeys ) )
22b2f9 ¤   ¤   *foundKeys = kInvalidPGPKeySetRef;
fc1b52 ¤   ¤
419a79 ¤   if( pgpContextIsValid( context ) &&
7fde06 ¤   ¤   IsntNull( serverList ) &&
ce37db ¤   ¤   serverCount >= 1 &&
9fbc04 ¤   ¤   IsntNull( foundKeys ) )
fac7a1 ¤   {
e8f888 ¤   ¤   PGPOptionListRef¤   optionList;
151b52 ¤   ¤
b502ff ¤   ¤   va_start( args, firstOption );
ce2e8f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE, firstOption,
7dd195 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   args );
68c414 ¤   ¤   va_end( args );
34af5a
3b0333 ¤   ¤   err = pgpSearchKeyServerDialog( context, serverList, serverCount,
12a321 ¤   ¤   ¤   ¤   ¤   ¤   tlsContext, searchAllServers, foundKeys, optionList );
311b52 ¤   ¤
69153d ¤   ¤   PGPFreeOptionList( optionList );
b79371 ¤   }
620e24 ¤   else
3bc7a1 ¤   {
a602ff ¤   ¤   va_start( args, firstOption );
261266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
70c414 ¤   ¤   va_end( args );
d11b52 ¤   ¤
0b19d3 ¤   ¤   err = kPGPError_BadParams;
9047d1 ¤   }·
d467c5 ¤
c4deb7 ¤   return( err );
8aefe6 }
98af5a
693609 ¤   PGPKeyRef
4c17c8 GetKeyForPassphrase(
2d46a5 ¤   PGPKeySetRef¤   keySet,
0ec87c ¤   const char *¤   passphrase,
b8843f ¤   PGPBoolean¤ ¤   signing)
2abb36 {
c1f87f ¤   PGPKeyRef¤  ¤   theKey¤ = kInvalidPGPKeyRef;
52fb19 ¤   PGPError¤   ¤   err;
bb7e52 ¤   PGPKeyListRef¤  keyListRef;
2d9ca2 ¤   PGPBoolean¤ ¤   foundValidKey¤  = FALSE;
ca67c5 ¤
579fea ¤   err = PGPOrderKeySet( keySet, kPGPAnyOrdering, &keyListRef );
e1b1f0 ¤   if( IsntPGPError( err ) )
abc7a1 ¤   {
6320b4 ¤   ¤   PGPKeyIterRef¤  keyIterator;
7e67c5 ¤
c007aa ¤   ¤   err = PGPNewKeyIter( keyListRef, &keyIterator );
--c84c 000691e15df40100292 Page 32 of pgpDialogs.cpp
2e86f8 ¤   ¤   if( IsntPGPError( err ) )
d75b34 ¤   ¤   {
80a048 ¤   ¤   ¤   err = PGPKeyIterNext( keyIterator, &theKey );
c38f5a ¤   ¤   ¤   while( IsntPGPError( err ) )
64f776 ¤   ¤   ¤   {
6a13e8 ¤   ¤   ¤   ¤   PGPBoolean¤ tryKey = FALSE;
0a2b85 ¤   ¤   ¤   ¤
856f2b ¤   ¤   ¤   ¤   if( signing )
ae72c3 ¤   ¤   ¤   ¤   {
073aec ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ canSign;
87ae30 ¤   ¤   ¤   ¤   ¤
76d81a ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( PGPGetKeyBoolean( theKey,
4e71ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropCanSign, &canSign ) ) && canSign )
664859 ¤   ¤   ¤   ¤   ¤   {
91caa7 ¤   ¤   ¤   ¤   ¤   ¤   tryKey = TRUE;
4f1c89 ¤   ¤   ¤   ¤   ¤   }
ca2613 ¤   ¤   ¤   ¤   }
0ffa07 ¤   ¤   ¤   ¤   else
0472c3 ¤   ¤   ¤   ¤   {
4f995e ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ canDecrypt;
e0ae30 ¤   ¤   ¤   ¤   ¤
90d81a ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( PGPGetKeyBoolean( theKey,
31cd5d ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyPropCanDecrypt, &canDecrypt ) ) &&
aecbcd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   canDecrypt )
2e4859 ¤   ¤   ¤   ¤   ¤   {
8ecaa7 ¤   ¤   ¤   ¤   ¤   ¤   tryKey = TRUE;
021c89 ¤   ¤   ¤   ¤   ¤   }
e42613 ¤   ¤   ¤   ¤   }
822b85 ¤   ¤   ¤   ¤
6cc59a ¤   ¤   ¤   ¤   if ( tryKey )
6072c3 ¤   ¤   ¤   ¤   {
b125f3 ¤   ¤   ¤   ¤   ¤   PGPContextRef¤  context¤= PGPGetKeyContext( theKey );
33ae30 ¤   ¤   ¤   ¤   ¤
ad12e6 ¤   ¤   ¤   ¤   ¤   if ( PGPPassphraseIsValid( theKey,
b035fc ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOPassphrase( context, passphrase),
2ba784 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption( context ) ) )
fc4859 ¤   ¤   ¤   ¤   ¤   {
683db8 ¤   ¤   ¤   ¤   ¤   ¤   foundValidKey¤  = TRUE;
3100eb ¤   ¤   ¤   ¤   ¤   ¤   break;
311c89 ¤   ¤   ¤   ¤   ¤   }
7f2613 ¤   ¤   ¤   ¤   }
f42b85 ¤   ¤   ¤   ¤
424248 ¤   ¤   ¤   ¤   err = PGPKeyIterNext( keyIterator, &theKey );
34a3a6 ¤   ¤   ¤   }
8f87c7 ¤   ¤   ¤
303433 ¤   ¤   ¤   PGPFreeKeyIter( keyIterator );
d80fe4 ¤   ¤   }
731b52 ¤   ¤
bd779b ¤   ¤   PGPFreeKeyList( keyListRef );
1a9371 ¤   }
e5af5a
63c701 ¤   return( foundValidKey ? theKey : NULL );
93efe6 }
ecaf5a
5b6870 static const PGPOptionType sSendToKeyServerOptionSet[] =
6dbb36 {
b760de ¤   kCommonAllowedKeyServerOptions
6d82f7 };
3baf5a
d166dd ¤   static PGPError
76e8e1 pgpSendToKeyServerDialog(
bb97bc ¤   PGPContextRef ¤ ¤   ¤   context,
97744e ¤   const PGPKeyServerSpec ¤*server,
6c5175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
4a1258 ¤   PGPKeySetRef ¤  ¤   ¤   keysToSend,
d0f36c ¤   PGPKeySetRef ¤  ¤   ¤   *failedKeys,
e7d72a ¤   PGPOptionListRef¤   ¤   optionList)
10bb36 {
ab61e0 ¤   PGPError¤   err;
5467c5 ¤
60704c ¤   pgpAssert( pgpOptionListIsValid( optionList ) );
6967c5 ¤
--3f60 0003d9bf61840100292 Page 33 of pgpDialogs.cpp
29bd44 ¤   err = pgpGetOptionListError( optionList );
22b1f0 ¤   if( IsntPGPError( err ) )
8cc7a1 ¤   {
ede195 ¤   ¤   err = pgpCheckNetworklibAvailability();
8e86f8 ¤   ¤   if( IsntPGPError( err ) )
575b34 ¤   ¤   {
9c4e77 ¤   ¤   ¤   err = pgpCheckOptionsInSet( optionList, sSendToKeyServerOptionSet,
47a029 ¤   ¤   ¤   ¤   ¤   ¤   elemsof( sSendToKeyServerOptionSet ) );
d7698b ¤   ¤   ¤   if( IsntPGPError( err ) )
a0f776 ¤   ¤   ¤   {
2d88fc ¤   ¤   ¤   ¤   CPGPSendToKeyServerDialogOptions¤   options;
1a2b85 ¤   ¤   ¤   ¤
5ed880 ¤   ¤   ¤   ¤   err = options.GatherOptions( context, optionList );
c35565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
6672c3 ¤   ¤   ¤   ¤   {
dfa2f3 ¤   ¤   ¤   ¤   ¤   options.mServerList¤¤   = server;
02e248 ¤   ¤   ¤   ¤   ¤   options.mServerCount¤   = 1;
c68388 ¤   ¤   ¤   ¤   ¤   options.mTLSContext¤¤   = tlsContext;
92ee08 ¤   ¤   ¤   ¤   ¤   options.mKeysToSend¤¤   = keysToSend;
220295 ¤   ¤   ¤   ¤   ¤   options.mFailedKeys¤¤   = failedKeys;
73ae30 ¤   ¤   ¤   ¤   ¤
0b7501 ¤   ¤   ¤   ¤   ¤   err = pgpSendToKeyServerDialogPlatform(context, &options);
fa2613 ¤   ¤   ¤   ¤   }
15a3a6 ¤   ¤   ¤   }
9f0fe4 ¤   ¤   }
469371 ¤   }
5967c5 ¤
29deb7 ¤   return( err );
5defe6 }
efaf5a
8cc744 ¤   PGPError
823433 PGPSendToKeyServerDialog(
ad97bc ¤   PGPContextRef ¤ ¤   ¤   context,
6f744e ¤   const PGPKeyServerSpec ¤*server,
2c5175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
ce1258 ¤   PGPKeySetRef ¤  ¤   ¤   keysToSend,
8cf36c ¤   PGPKeySetRef ¤  ¤   ¤   *failedKeys,
3ce88a ¤   PGPOptionListRef ¤  ¤   firstOption,
fb5825 ¤   ... )
94bb36 {
9a61e0 ¤   PGPError¤   err;
5346e9 ¤   va_list¤¤   args;
4faf5a
998679 ¤   pgpAssert( pgpContextIsValid( context ) );
fa0ddf ¤   pgpAssert( IsntNull( server ) );
a01f73 ¤   pgpAssert( PGPKeySetRefIsValid( keysToSend ) );
7268d9 ¤   pgpAssert( IsntNull( failedKeys ) );
ca67c5 ¤
7eed53 ¤   if( IsntNull( failedKeys ) )
1b71e9 ¤   ¤   *failedKeys = kInvalidPGPKeySetRef;
701b52 ¤   ¤
339a79 ¤   if( pgpContextIsValid( context ) &&
35bf4a ¤   ¤   IsntNull( server ) &&
82584f ¤   ¤   PGPKeySetRefIsValid( keysToSend ) &&
7beb7c ¤   ¤   IsntNull( failedKeys ) )
47c7a1 ¤   {
fbf888 ¤   ¤   PGPOptionListRef¤   optionList;
401b52 ¤   ¤
a802ff ¤   ¤   va_start( args, firstOption );
2f2e8f ¤   ¤   optionList = pgpBuildOptionListArgs( context, FALSE, firstOption,
93d195 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   args );
1cc414 ¤   ¤   va_end( args );
7daf5a
d48d02 ¤   ¤   err = pgpSendToKeyServerDialog( context, server, tlsContext,
76861b ¤   ¤   ¤   ¤   ¤   ¤   keysToSend, failedKeys, optionList );
3b1b52 ¤   ¤
85153d ¤   ¤   PGPFreeOptionList( optionList );
cb9371 ¤   }
db0e24 ¤   else
67c7a1 ¤   {
4002ff ¤   ¤   va_start( args, firstOption );
3d1266 ¤   ¤   pgpFreeVarArgOptionList( firstOption, args );
--0866 001d4a26bd240100292 Page 34 of pgpDialogs.cpp
c0c414 ¤   ¤   va_end( args );
511b52 ¤   ¤
2619d3 ¤   ¤   err = kPGPError_BadParams;
dc47d1 ¤   }·
cb67c5 ¤
37deb7 ¤   return( err );
d4efe6 }
--eec3 000031a841040100293 Page 1 of pgpDialogs.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
bcbd49 ¤   $Id: pgpDialogs.h,v 1.30.10.1 1998/11/12 03:23:00 heller Exp $
04f7f7 ____________________________________________________________________________*/
c2af5a
573cf9 #ifndef Included_pgpDialogs_h¤  /* [ */
1bd6bc #define Included_pgpDialogs_h
bbaf5a
6e0141 #include "pgpOptionListPriv.h"
a3e684 #include "pgpUserInterface.h"
6faf5a
264893 struct PGPRecipientSpec;
8faf5a
8b962f class CPGPDialogOptions
58bb36 {
9a5ed4 public:
26af5a
bfd2fa ¤   PGPContextRef¤  ¤   ¤   mContext;
4fac22 ¤   PGPOptionListRef¤   ¤   mClientOptions;
c00106 ¤   char¤   ¤   ¤   ¤   ¤   *mWindowTitle;
d930d2 ¤   const PGPKeyServerSpec¤ *mServerList;
4cfddf ¤   PGPUInt32¤  ¤   ¤   ¤   mServerCount;
4f3d83 ¤   PGPBoolean¤ ¤   ¤   ¤   mSearchBeforeDisplay;
4a45f7 ¤   PGPBoolean¤ ¤   ¤   ¤   mTextUI;
ddfedf ¤   PGPKeySetRef¤   ¤   ¤   *mNewKeys;¤ ¤   ¤   /* Server search results */
b50996 ¤   PGPtlsContextRef¤   ¤   mTLSContext;
fe0111 ¤   const char *¤   ¤   ¤   mPrompt;
2767c5 ¤
a4afb9 #if PGP_WIN32
e49a3c ¤   HWND ···············mHwndParent;
847454 #endif
39af5a
c5363b ¤   ¤   ¤   ¤   ¤   ¤   CPGPDialogOptions(void);
6ae185 ¤   virtual¤¤   ¤   ¤   ~CPGPDialogOptions(void);
3767c5 ¤
907aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
09667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
2582f7 };
1aaf5a
cdfa57 class CPGPRecipientDialogOptions : public CPGPDialogOptions
2bbb36 {
cf5ed4 public:
b4af5a
2e80cd ¤   PGPOptionListRef¤   ¤   mDialogOptions;
d01f61 ¤   PGPUInt32¤  ¤   ¤   ¤   mNumDefaultRecipients;
f7af09 ¤   const PGPRecipientSpec¤ *mDefaultRecipients;
f7e138 ¤   PGPBoolean¤ ¤   ¤   ¤   mDisplayMarginalValidity;
1ac204 ¤   PGPBoolean¤ ¤   ¤   ¤   mIgnoreMarginalValidity;
14ad4b ¤   PGPGroupSetRef¤ ¤   ¤   mGroupSet;
d611ef ¤   PGPKeySetRef¤   ¤   ¤   mClientKeySet;
45159a ¤   PGPBoolean¤ ¤   ¤   ¤   mAlwaysDisplay;
a4ef57 ¤   PGPBoolean¤ ¤   ¤   ¤   mAlwaysDisplayWithARRs;
3021ba ¤   PGPKeySetRef¤   ¤   ¤   *mRecipientKeysPtr;¤¤   /* Output */
4b09cc ¤   PGPUInt32¤  ¤   ¤   ¤   *mRecipientCount;¤  ¤   /* Output */
67e828 ¤   PGPRecipientSpec¤   ¤   **mRecipientList;¤  ¤   /* Output */
7767c5 ¤
11eed1 ¤   PGPAdditionalRecipientRequestEnforcement¤   mEnforcement;
c367c5 ¤
1d70ba ¤   ¤   ¤   ¤   ¤   ¤   CPGPRecipientDialogOptions(void);
1e0e70 ¤   virtual¤¤   ¤   ¤   ~CPGPRecipientDialogOptions(void);
a7af5a
617aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
2b667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
3782f7 };
bdaf5a
d350d9 class CPGPRandomDataDialogOptions : public CPGPDialogOptions
94bb36 {
885ed4 public:
34af5a
03db3e ¤   PGPUInt32¤  ¤   ¤   mNeededEntropyBits;
--1723 00093b8b16c40100293 Page 2 of pgpDialogs.h
2a67c5 ¤
850f22 ¤   ¤   ¤   ¤   ¤   ¤   CPGPRandomDataDialogOptions(void);
a4660a ¤   virtual¤¤   ¤   ¤   ~CPGPRandomDataDialogOptions(void);
8182f7 };
b7af5a
7f32c4 class CPGPKeyServerDialogOptions : public CPGPDialogOptions
29bb36 {
535ed4 public:
9aaf5a
9279a0 ¤   ¤   ¤   ¤   ¤   ¤   CPGPKeyServerDialogOptions(void);
72076a ¤   virtual¤¤   ¤   ¤   ~CPGPKeyServerDialogOptions(void);
9d82f7 };
27af5a
6c1f91 class CPGPSearchKeyServerDialogOptions : public CPGPKeyServerDialogOptions
0dbb36 {
e65ed4 public:
a9af5a
40a146 ¤   PGPBoolean¤ ¤   ¤   mSearchAllServers;
fe62af ¤   PGPFilterRef¤   ¤   mFilter;
fbac10 ¤   char¤   ¤   ¤   ¤   mKeyDescription[256];
d067c5 ¤
df14fb ¤   ¤   ¤   ¤   ¤   ¤   CPGPSearchKeyServerDialogOptions(void);
ac4ecd ¤   virtual¤¤   ¤   ¤   ~CPGPSearchKeyServerDialogOptions(void);
afaf5a
3d7aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
d6667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
80da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
800fb9 private:
06af5a
e16151 ¤   PGPError¤   ¤   ¤   NewKeyIDListSearchFilter(PGPContextRef context,
b54b86 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const PGPKeyID *keyIDList,
1c7cb2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyIDCount,
74303c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *filter);
5084df ¤   PGPError¤   ¤   ¤   NewKeySetSearchFilter(PGPContextRef context,
3eaad3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keySet, PGPFilterRef *filter);
3582f7 };
06af5a
8e6de2 class CPGPSendToKeyServerDialogOptions : public CPGPKeyServerDialogOptions
a4bb36 {
7b5ed4 public:
eaaf5a
5a2059 ¤   PGPKeySetRef¤   ¤   mKeysToSend;
6ae534 ¤   PGPKeySetRef¤   ¤   *mFailedKeys;
3867c5 ¤
184d74 ¤   ¤   ¤   ¤   ¤   ¤   CPGPSendToKeyServerDialogOptions(void);
b11742 ¤   virtual¤¤   ¤   ¤   ~CPGPSendToKeyServerDialogOptions(void);
ad82f7 };
03af5a
2faf5a
9bcdc3 class CPGPPassphraseDialogOptions : public CPGPDialogOptions
21bb36 {
685ed4 public:
64af5a
95ac8f ¤   char **¤¤   ¤   ¤   mPassphrasePtr;
2790fa ¤   PGPOptionListRef¤   mDialogOptions;
9e1763 ¤   PGPUInt32¤  ¤   ¤   mMinPassphraseLength;
9de32a ¤   PGPUInt32¤  ¤   ¤   mMinPassphraseQuality;
5daf5a
7d7174 ¤   ¤   ¤   ¤   ¤   ¤   CPGPPassphraseDialogOptions(void);
50185c ¤   virtual¤¤   ¤   ¤   ~CPGPPassphraseDialogOptions(void);
8d67c5 ¤
da7aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
13667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
d082f7 };
afaf5a
17f96f class CPGPConfirmationPassphraseDialogOptions :
43ecdf ¤   ¤   ¤   public CPGPPassphraseDialogOptions
04bb36 {
005ed4 public:
6eaf5a
b1da2a ¤   PGPBoolean¤ ¤   ¤   mShowPassphraseQuality;
93af5a
--adc0 000256aaf8b40100293 Page 3 of pgpDialogs.h
9114b5 ¤   ¤   ¤   ¤   ¤   ¤   CPGPConfirmationPassphraseDialogOptions(void);
d2f35d ¤   virtual¤¤   ¤   ¤   ~CPGPConfirmationPassphraseDialogOptions(void);
9767c5 ¤
d37aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
fb667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
5c82f7 };
96af5a
93e434 class CPGPKeyPassphraseDialogOptions : public CPGPPassphraseDialogOptions
56bb36 {
565ed4 public:
58af5a
5b2df9 ¤   PGPBoolean¤ ¤   ¤   mVerifyPassphrase;
a3f802 ¤   PGPKeyRef¤  ¤   ¤   mDefaultKey;
95af5a
c06ebe ¤   ¤   ¤   ¤   ¤   ¤   CPGPKeyPassphraseDialogOptions(void);
d6190a ¤   virtual¤¤   ¤   ¤   ~CPGPKeyPassphraseDialogOptions(void);
a567c5 ¤
a47aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
3c667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
a782f7 };
5baf5a
3502c2 class CPGPKeySetPassphraseDialogOptions :
b5b053 ¤   ¤   ¤   public CPGPKeyPassphraseDialogOptions
abbb36 {
b15ed4 public:
ccaf5a
5cf779 ¤   PGPBoolean¤ ¤   ¤   mFindMatchingKey;
4535ef ¤   PGPKeySetRef¤   ¤   mKeySet;
5460ab ¤   PGPKeyRef *¤¤   ¤   mPassphraseKeyPtr;
68af5a
a8ab90 ¤   ¤   ¤   ¤   ¤   ¤   CPGPKeySetPassphraseDialogOptions(void);
56ff7f ¤   virtual¤¤   ¤   ¤   ~CPGPKeySetPassphraseDialogOptions(void);
d667c5 ¤
2a7aed ¤   virtual PGPError¤   GatherOptions(PGPContextRef context,
01667c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef optionList);
ae82f7 };
4baf5a
10a670 class CPGPSigningPassphraseDialogOptions :
3edbb3 ¤   ¤   ¤   public CPGPKeySetPassphraseDialogOptions
b2bb36 {
cd5ed4 public:
6caf5a
c2bf31 ¤   ¤   ¤   ¤   ¤   ¤   CPGPSigningPassphraseDialogOptions(void);
40a09c ¤   virtual¤¤   ¤   ¤   ~CPGPSigningPassphraseDialogOptions(void);
ae82f7 };
70af5a
49c443 class CPGPDecryptionPassphraseDialogOptions :
21dbb3 ¤   ¤   ¤   public CPGPKeySetPassphraseDialogOptions
e6bb36 {
ec5ed4 public:
a8af5a
19cb45 ¤   const PGPKeyID¤ ¤   *mKeyIDList;
e7fe65 ¤   PGPUInt32¤  ¤   ¤   mKeyIDCount;
7c1752 ¤   PGPKeyID¤   ¤   ¤   *mMissingKeyIDList;
0e2935 ¤   PGPUInt32¤  ¤   ¤   mMissingKeyIDCount;
5967c5 ¤
ff78ce ¤   ¤   ¤   ¤   ¤   ¤   CPGPDecryptionPassphraseDialogOptions(void);
219e3f ¤   virtual¤¤   ¤   ¤   ~CPGPDecryptionPassphraseDialogOptions(void);
1567c5 ¤
cad2b3 ¤   PGPError¤   ¤   ¤   GatherMissingKeys(void);
ef6754 ¤   PGPError¤   ¤   ¤   SearchForMissingKeys(void *hwndParent,
f0d180 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *foundNewKeys);
ef67c5 ¤
a90fb9 private:
99af5a
053182 ¤   PGPError¤   ¤   ¤   RemoveFoundKeysFromSet(PGPKeySetRef keySet);
0a82f7 };
f0af5a
8d3b4f class CPGPOptionsDialogOptions : public CPGPDialogOptions
7dbb36 {
055ed4 public:
25af5a
--8d85 001a74445b840100293 Page 4 of pgpDialogs.h
68076f ¤   ¤   ¤   ¤   ¤   ¤   CPGPOptionsDialogOptions(void);
ff880b ¤   virtual¤¤   ¤   ¤   ~CPGPOptionsDialogOptions(void);
5e82f7 };
f5af5a
daaf5a
f699c6 PGP_BEGIN_C_DECLARATIONS
e3af5a
1891d2 /* Platform specific handler functions */
2daf5a
7d02eb PGPError¤   pgpRecipientDialogPlatform(PGPContextRef context,
f81bf7 ¤   ¤   ¤   ¤   ¤   CPGPRecipientDialogOptions *options);
2a437e PGPError¤   pgpPassphraseDialogPlatform(PGPContextRef context,
283652 ¤   ¤   ¤   ¤   ¤   CPGPPassphraseDialogOptions *options);
076fcf PGPError¤   pgpKeyPassphraseDialogPlatform(PGPContextRef context,
68a28c ¤   ¤   ¤   ¤   ¤   CPGPKeyPassphraseDialogOptions *options);
db1b9d PGPError¤   pgpSigningPassphraseDialogPlatform(PGPContextRef context,
9f41f2 ¤   ¤   ¤   ¤   ¤   CPGPSigningPassphraseDialogOptions *options);
e5266d PGPError¤   pgpDecryptionPassphraseDialogPlatform(PGPContextRef context,
6c10ea ¤   ¤   ¤   ¤   ¤   CPGPDecryptionPassphraseDialogOptions *options);
854d84 PGPError¤   pgpConfirmationPassphraseDialogPlatform(PGPContextRef context,
c6fd89 ¤   ¤   ¤   ¤   ¤   CPGPConfirmationPassphraseDialogOptions *options);
8acf4b PGPError¤   pgpOptionsDialogPlatform(PGPContextRef context,
66ec52 ¤   ¤   ¤   ¤   ¤   CPGPOptionsDialogOptions *options);
ae3630 PGPError¤   pgpCollectRandomDataDialogPlatform(PGPContextRef context,
3f381d ¤   ¤   ¤   ¤   ¤   CPGPRandomDataDialogOptions *options);
104501 PGPError¤   pgpSearchKeyServerDialogPlatform(PGPContextRef context,
86a8b9 ¤   ¤   ¤   ¤   ¤   CPGPSearchKeyServerDialogOptions *options);
9b1b02 PGPError¤   pgpSendToKeyServerDialogPlatform(PGPContextRef context,
7328d3 ¤   ¤   ¤   ¤   ¤   CPGPSendToKeyServerDialogOptions *options);
a7075c PGPError¤   pgpGetMissingRecipientKeyIDStringPlatform(PGPContextRef context,
65e686 ¤   ¤   ¤   ¤   ¤   const PGPKeyID¤ *keyID, char keyIDString[256]);
9aae30 ¤   ¤   ¤   ¤   ¤
88ea01 /* Utilitiy functions */
31af5a
c3730e PGPError¤   pgpCheckNetworklibAvailability(void);
de8732 PGPKeyRef ··GetKeyForPassphrase(PGPKeySetRef keySet, const char *passphrase,
97ac12 ¤   ¤   ¤   ¤   ¤   PGPBoolean signing);
0faf5a
8caf5a
931254 PGP_END_C_DECLARATIONS
2baf5a
006f36 #endif /* ] Included_pgpDialogs_h */
e2af5a
287e4d /*__Editor_settings____
c3af5a
684126 ¤   Local Variables:
c77b17 ¤   tab-width: 4
e70e6c ¤   End:
795f8c ¤   vi: ts=4 sw=4
fb9e9b ¤   vim: si
a7d062 _____________________*/
--55d1 000f30a142c40100294 Page 1 of pgpKeyServerDialogCommon.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
602d9c ¤   $Id: pgpKeyServerDialogCommon.cpp,v 1.11.2.1.2.1 1998/11/12 03:23:00 heller¶
9c7cbd ·Exp $
2bf7f7 ____________________________________________________________________________*/
e2af5a
50a076 #include "pgpKeys.h"
47eb5b #include "pgpKeyServer.h"
3b0d08 #include "pgpMem.h"
1ae684 #include "pgpUserInterface.h"
afaf5a
cef76a #include "pgpKeyServerDialogCommon.h"
50af5a
c14c26 typedef struct KeyServerCallbackInfo
fcbb36 {
2a877a ¤   PGPEventHandlerProcPtr¤ dialogHandler;
49f801 ¤   PGPUserValue¤   ¤   ¤   dialogUserValue;
1167c5 ¤
94a673 ¤   PGPEventHandlerProcPtr¤ clientIdleHandler;
d09ec8 ¤   PGPUserValue¤   ¤   ¤   clientIdleUserValue;
4367c5 ¤
c98507 ¤   PGPEventHandlerProcPtr¤ clientEventHandler;
0b16ca ¤   PGPUserValue¤   ¤   ¤   clientEventUserValue;
02af5a
1db2dc } KeyServerCallbackInfo;
94af5a
2d8f33 typedef struct KeyServerOpInfo
fdbb36 {
812f4b ¤   enum
d0c7a1 ¤   {
40d1fb ¤   ¤   kSearchServerOp,
08da7b ¤   ¤   kSendToServerOp
305a4f ¤   } op;
5d67c5 ¤
30f20a ¤   union
35c7a1 ¤   {
e92b33 ¤   ¤   struct
045b34 ¤   ¤   {
7004e7 ¤   ¤   ¤   PGPFilterRef¤   filter;
7f958c ¤   ¤   ¤   PGPKeySetRef¤   *searchResults;
cc5058 ¤   ¤   } search;
dd1b52 ¤   ¤
e52b33 ¤   ¤   struct
d55b34 ¤   ¤   {
9f9534 ¤   ¤   ¤   PGPKeySetRef¤   keysToSend;
e98b88 ¤   ¤   ¤   PGPKeySetRef¤   *failedKeys;
8a90d6 ¤   ¤   } send;
d662bd ¤   };
d967c5 ¤
912d0a } KeyServerOpInfo;
d2af5a
1e66dd ¤   static PGPError
442d23 KeyServerCallbackProc(
3735f6 ¤   PGPContextRef ¤ context,
aa12c1 ¤   struct PGPEvent *event,
052e8b ¤   PGPUserValue ¤  userValue)
37bb36 {
1a3cbe ¤   PGPError¤   ¤   ¤   ¤   err = kPGPError_NoErr;
93e084 ¤   KeyServerCallbackInfo¤  *info;
f867c5 ¤
a27f0d ¤   info = (KeyServerCallbackInfo *) userValue;
6667c5 ¤
7ca505 ¤   switch( event->type )
8fc7a1 ¤   {
09deeb ¤   ¤   case kPGPEvent_KeyServerIdleEvent:
f55b34 ¤   ¤   {
ba32e0 ¤   ¤   ¤   if( IsntNull( info->clientIdleHandler ) )
1af776 ¤   ¤   ¤   {
a42bde ¤   ¤   ¤   ¤   err = (*info->clientIdleHandler)( context, event,
f3a869 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   info->clientIdleUserValue );
--1622 000dc63549240100294 Page 2 of pgpKeyServerDialogCommon.cpp
cfa3a6 ¤   ¤   ¤   }
7987c7 ¤   ¤   ¤
89cdcb ¤   ¤   ¤   break;
650fe4 ¤   ¤   }
5987c7 ¤   ¤   ¤
a79ae3 ¤   ¤   default:
655b34 ¤   ¤   {
a8c17d ¤   ¤   ¤   if( IsntNull( info->clientEventHandler ) )
46f776 ¤   ¤   ¤   {
93764b ¤   ¤   ¤   ¤   err = (*info->clientEventHandler)( context, event,
24eae6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   info->clientEventUserValue );
7ea3a6 ¤   ¤   ¤   }
0c2b85 ¤   ¤   ¤   ¤
6ccdcb ¤   ¤   ¤   break;
ef0fe4 ¤   ¤   }
9b9371 ¤   }
ecaf5a
c7b1f0 ¤   if( IsntPGPError( err ) )
47c7a1 ¤   {
a2a3cf ¤   ¤   err = (*info->dialogHandler)( context, event, info->dialogUserValue );
9d9371 ¤   }
db1b52 ¤   ¤
e7deb7 ¤   return( err );
51efe6 }
b8af5a
9366dd ¤   static PGPError
b46914 DoKeyServerOp(
489a06 ¤   PGPContextRef¤  ¤   ¤   context,
fca067 ¤   const PGPKeyServerSpec¤ *serverSpec,
1b5175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
c1419c ¤   KeyServerOpInfo¤¤   ¤   *opInfo,
7e92c8 ¤   PGPEventHandlerProcPtr¤ eventHandler,
e82011 ¤   PGPUserValue¤   ¤   ¤   eventUserValue)
2dbb36 {
b9dc13 ¤   PGPError¤   ¤   ¤   ¤   ¤   ¤   err;
296c56 ¤   KeyServerCallbackInfo¤  ¤   ¤   info;
199a5c ¤   PGPKeyServerThreadStorageRef¤   previousStorage;
c4af5a
2e67c5 ¤
7f5605 ¤   PGPKeyServerInit();
8cde4f ¤   PGPKeyServerCreateThreadStorage(&previousStorage);
7aaf5a
d8daaa ¤   pgpClearMemory( &info, sizeof( info ) );
1167c5 ¤
53beef ¤   info.dialogHandler ¤¤   = eventHandler;
b28ff9 ¤   info.dialogUserValue¤   = eventUserValue;
4967c5 ¤
7ae360 ¤   /* Override the event handlers with ours and query the server. */
af67c5 ¤
dff623 ¤   err = PGPGetKeyServerIdleEventHandler( &info.clientIdleHandler,
a1e6af ¤   ¤   ¤   ¤   ¤   &info.clientIdleUserValue );
72b1f0 ¤   if( IsntPGPError( err ) )
3dc7a1 ¤   {
b06308 ¤   ¤   err = PGPGetKeyServerEventHandler( serverSpec->server,
9fd3ef ¤   ¤   ¤   ¤   ¤   ¤   &info.clientEventHandler,
a8e793 ¤   ¤   ¤   ¤   ¤   ¤   &info.clientEventUserValue );
e39371 ¤   }
6a67c5 ¤
5fb1f0 ¤   if( IsntPGPError( err ) )
d0c7a1 ¤   {
78e1fa #if ! PGP_WIN32
30448d ¤   ¤   err = PGPSetKeyServerIdleEventHandler( KeyServerCallbackProc,
c245de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &info );
787454 #endif
0286f8 ¤   ¤   if( IsntPGPError( err ) )
675b34 ¤   ¤   {
3475a6 ¤   ¤   ¤   err = PGPSetKeyServerEventHandler( serverSpec->server,
e24444 ¤   ¤   ¤   ¤   ¤   ¤   KeyServerCallbackProc, &info );
dd698b ¤   ¤   ¤   if( IsntPGPError( err ) )
4df776 ¤   ¤   ¤   {
11931a ¤   ¤   ¤   ¤   PGPtlsSessionRef¤   tls = kInvalidPGPtlsSessionRef;
dcf9d1 ¤   ¤   ¤   ¤   PGPEvent¤   ¤   ¤   theEvent;
--416d 0002532027640100294 Page 3 of pgpKeyServerDialogCommon.cpp
9f2b85 ¤   ¤   ¤   ¤
0b980e ¤   ¤   ¤   ¤   /*
83d3c9 ¤   ¤   ¤   ¤   ** Generate "fake" connecting event to give UI a chance to
45e10b ¤   ¤   ¤   ¤   ** make key server calls when the server is not really busy
24df0b ¤   ¤   ¤   ¤   */
1b2b85 ¤   ¤   ¤   ¤
3ba602 ¤   ¤   ¤   ¤   pgpClearMemory( &theEvent, sizeof( theEvent ) );
592b85 ¤   ¤   ¤   ¤
0f09b3 ¤   ¤   ¤   ¤   theEvent.type = kPGPEvent_KeyServerEvent;
8e8d4b ¤   ¤   ¤   ¤   theEvent.data.keyServerData.keyServerRef =
65caab ¤   ¤   ¤   ¤   ¤   ¤   ¤   serverSpec->server;
ea6605 ¤   ¤   ¤   ¤   theEvent.data.keyServerData.state =
f61970 ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPKeyServerState_Opening;
4e2b85 ¤   ¤   ¤   ¤
b2610a ¤   ¤   ¤   ¤   err = KeyServerCallbackProc( context, &theEvent, &info);
395bf0 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
9c8ab3 ¤   ¤   ¤   ¤   ¤   PGPtlsContextRefIsValid( tlsContext ) )
9b72c3 ¤   ¤   ¤   ¤   {
51e419 ¤   ¤   ¤   ¤   ¤   PGPKeyServerType¤   serverType;
d1ae30 ¤   ¤   ¤   ¤   ¤
5ab4ed ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyServerType( serverSpec->server,
58fd93 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &serverType );
ffca68 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
d828e2 ¤   ¤   ¤   ¤   ¤   ¤   serverType == kPGPKeyServerType_LDAPS )
f24859 ¤   ¤   ¤   ¤   ¤   {
da20b2 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPNewTLSSession( tlsContext, &tls );
d31c89 ¤   ¤   ¤   ¤   ¤   }
1f2613 ¤   ¤   ¤   ¤   }
ff2b85 ¤   ¤   ¤   ¤
8c5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
da72c3 ¤   ¤   ¤   ¤   {
575c52 ¤   ¤   ¤   ¤   ¤   err = PGPKeyServerOpen( serverSpec->server, tls );
356ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
3c4859 ¤   ¤   ¤   ¤   ¤   {
9d1233 ¤   ¤   ¤   ¤   ¤   ¤   if( opInfo->op == KeyServerOpInfo::kSearchServerOp )
e68fec ¤   ¤   ¤   ¤   ¤   ¤   {
911f4a ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPQueryKeyServer( serverSpec->server,
2e0a21 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   opInfo->search.filter,
75c6f1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   opInfo->search.searchResults );
d0db3c ¤   ¤   ¤   ¤   ¤   ¤   }
5f7f8b ¤   ¤   ¤   ¤   ¤   ¤   else
a38fec ¤   ¤   ¤   ¤   ¤   ¤   {
30518a ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpAssert( opInfo->op ==
6520f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   KeyServerOpInfo::kSendToServerOp );
6ced43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
2a40d7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPUploadToKeyServer( serverSpec->server,
9f9ad1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   opInfo->send.keysToSend,
1aa06a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   opInfo->send.failedKeys );
85db3c ¤   ¤   ¤   ¤   ¤   ¤   }
0c94aa ¤   ¤   ¤   ¤   ¤   ¤
f41985 ¤   ¤   ¤   ¤   ¤   ¤   (void) PGPKeyServerClose( serverSpec->server );
1a1c89 ¤   ¤   ¤   ¤   ¤   }
532613 ¤   ¤   ¤   ¤   }
872b85 ¤   ¤   ¤   ¤
4d1e2d ¤   ¤   ¤   ¤   if( PGPtlsSessionRefIsValid( tls ) )
2d1cbe ¤   ¤   ¤   ¤   ¤   (void) PGPFreeTLSSession( tls );
78ae30 ¤   ¤   ¤   ¤   ¤
54ed42 ¤   ¤   ¤   ¤   (void) PGPSetKeyServerEventHandler( serverSpec->server,
becb1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   info.clientEventHandler,
27e502 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   info.clientEventUserValue);
19a3a6 ¤   ¤   ¤   }
c60fe4 ¤   ¤   }
ef1b52 ¤   ¤
ca709a ¤   ¤   (void) PGPSetKeyServerIdleEventHandler( info.clientIdleHandler,
0a0d92 ¤   ¤   ¤   ¤   ¤   ¤   info.clientIdleUserValue );
529371 ¤   }
8367c5 ¤
3a095b ¤   PGPKeyServerDisposeThreadStorage(previousStorage);
9caf5a
21c1aa ¤   PGPKeyServerCleanup();
8eaf5a
25deb7 ¤   return( err );
--3a2a 000bf76366a40100294 Page 4 of pgpKeyServerDialogCommon.cpp
7aefe6 }
46af5a
b0c744 ¤   PGPError
2c6395 PGPSearchKeyServerDialogCommon(
8597bc ¤   PGPContextRef ¤ ¤   ¤   context,
9fcc83 ¤   const PGPKeyServerSpec ¤serverList[],
1e11fc ¤   PGPUInt32¤  ¤   ¤   ¤   serverCount,
265175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
3be48e ¤   PGPFilterRef ¤  ¤   ¤   filterRef,
5892c8 ¤   PGPEventHandlerProcPtr¤ eventHandler,
b15ea9 ¤   PGPUserValue¤   ¤   ¤   eventUserValue,
e37089 ¤   PGPBoolean¤ ¤   ¤   ¤   searchAllServers,
5c9dd8 ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys)
6bbb36 {
8a8e12 ¤   PGPError¤   err = kPGPError_NoErr;
cc67c5 ¤
b52235 ¤   err = PGPNewKeySet( context, foundKeys );
b5b1f0 ¤   if( IsntPGPError( err ) )
c5c7a1 ¤   {
845c35 ¤   ¤   PGPUInt32¤  ¤   serverIndex;
c2ab50 ¤   ¤   PGPBoolean¤ ¤   doneSearching = FALSE;
af5c4a ¤   ¤   PGPBoolean¤ ¤   foundSomeKeys = FALSE;
a1596b ¤   ¤   KeyServerOpInfo¤opInfo;
141b52 ¤   ¤
ac198f ¤   ¤   opInfo.op ¤ ¤   ¤   ¤   ¤   = KeyServerOpInfo::kSearchServerOp;
c4ed00 ¤   ¤   opInfo.search.filter ¤  ¤   = filterRef;
be1b52 ¤   ¤
dea213 ¤   ¤   for( serverIndex = 0; serverIndex < serverCount; serverIndex++ )
915b34 ¤   ¤   {
e20551 ¤   ¤   ¤   PGPKeySetRef¤   searchResults = kInvalidPGPKeySetRef;
d3a2a4 ¤   ¤   ¤   PGPError¤   ¤   searchError;
1587c7 ¤   ¤   ¤
3a872c ¤   ¤   ¤   opInfo.search.searchResults = &searchResults;
7daf5a
d03000 ¤   ¤   ¤   searchError = DoKeyServerOp( context, &serverList[serverIndex],
f2b3c5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   tlsContext, &opInfo, eventHandler,
7a8634 ¤   ¤   ¤   ¤   ¤   ¤   ¤   eventUserValue );
be07c4 ¤   ¤   ¤   if( IsntPGPError( searchError ) )
8ef776 ¤   ¤   ¤   {
8445ae ¤   ¤   ¤   ¤   PGPUInt32¤  numKeys;
e22b85 ¤   ¤   ¤   ¤
e72f48 ¤   ¤   ¤   ¤   pgpAssert( PGPKeySetRefIsValid( searchResults ) );
d92b85 ¤   ¤   ¤   ¤
36bb2f ¤   ¤   ¤   ¤   err = PGPCountKeys( searchResults, &numKeys );
a49720 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && numKeys > 0 )
e172c3 ¤   ¤   ¤   ¤   {
428517 ¤   ¤   ¤   ¤   ¤   foundSomeKeys = TRUE;
41ae30 ¤   ¤   ¤   ¤   ¤
73c1ae ¤   ¤   ¤   ¤   ¤   err = PGPAddKeys( searchResults, *foundKeys );
266ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
a41450 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges( *foundKeys );
ea94aa ¤   ¤   ¤   ¤   ¤   ¤
ca90ec ¤   ¤   ¤   ¤   ¤   if( ! searchAllServers )
f02922 ¤   ¤   ¤   ¤   ¤   ¤   doneSearching = TRUE;
be2613 ¤   ¤   ¤   ¤   }
bd2b85 ¤   ¤   ¤   ¤
847944 ¤   ¤   ¤   ¤   PGPFreeKeySet( searchResults );
23a3a6 ¤   ¤   ¤   }
d8da39 ¤   ¤   ¤   else if( searchError == kPGPError_UserAbort )
d4f776 ¤   ¤   ¤   {
594067 ¤   ¤   ¤   ¤   err = kPGPError_UserAbort;
83a3a6 ¤   ¤   ¤   }
49bb8c ¤   ¤   ¤   else
93f776 ¤   ¤   ¤   {
b8980e ¤   ¤   ¤   ¤   /*
3ac346 ¤   ¤   ¤   ¤   ** If this is the last (or only) server in the list and we
bfd316 ¤   ¤   ¤   ¤   ** get an error, propagate this error to the user if no keys
fbfe07 ¤   ¤   ¤   ¤   ** have been found. Otherwise, fail silently and search the
8261cc ¤   ¤   ¤   ¤   ** next server.
d6df0b ¤   ¤   ¤   ¤   */
bc2b85 ¤   ¤   ¤   ¤
bf284a ¤   ¤   ¤   ¤   if( serverIndex == serverCount - 1 && ! foundSomeKeys )
--4358 001d777293140100294 Page 5 of pgpKeyServerDialogCommon.cpp
569ce2 ¤   ¤   ¤   ¤   ¤   err = searchError;
b5a3a6 ¤   ¤   ¤   }
6f87c7 ¤   ¤   ¤
cf2f9f ¤   ¤   ¤   if( IsPGPError( err ) || doneSearching )
9df622 ¤   ¤   ¤   ¤   break;
100fe4 ¤   ¤   }
a767c5 ¤
29d223 ¤   ¤   if( IsPGPError( err ) )
425b34 ¤   ¤   {
91c063 ¤   ¤   ¤   PGPFreeKeySet( *foundKeys );
502361 ¤   ¤   ¤   *foundKeys = kInvalidPGPKeySetRef;
fd0fe4 ¤   ¤   }
a19371 ¤   }
ab67c5 ¤
81deb7 ¤   return( err );
86efe6 }
71af5a
2ec744 ¤   PGPError
9c016c PGPSendToKeyServerDialogCommon(
da97bc ¤   PGPContextRef ¤ ¤   ¤   context,
be744e ¤   const PGPKeyServerSpec ¤*server,
465175 ¤   PGPtlsContextRef¤   ¤   tlsContext,
c45015 ¤   PGPKeySetRef¤   ¤   ¤   keysToSend,
dc8973 ¤   PGPEventHandlerProcPtr ¤eventHandler,
87705f ¤   PGPUserValue ¤  ¤   ¤   eventUserValue,
998dd4 ¤   PGPKeySetRef ¤  ¤   ¤   *failedKeys)
18bb36 {
753bb5 ¤   PGPError¤   ¤   err = kPGPError_NoErr;
21f435 ¤   KeyServerOpInfo¤opInfo;
5c67c5 ¤
0b2cfa ¤   opInfo.op ¤ ¤   ¤   ¤   = KeyServerOpInfo::kSendToServerOp;
47a263 ¤   opInfo.send.keysToSend ¤= keysToSend;
d12e86 ¤   opInfo.send.failedKeys ¤= failedKeys;
4c87c7 ¤   ¤   ¤
53dc5a ¤   err = DoKeyServerOp( context, server, tlsContext, &opInfo,
ceeb68 ¤   ¤   ¤   ¤   ¤   eventHandler, eventUserValue );
5067c5 ¤
e1deb7 ¤   return( err );
d7be43 }¶
--5c08 001d73b105e40100295 Page 1 of pgpKeyServerDialogCommon.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
043fd2 ¤   $Id: pgpKeyServerDialogCommon.h,v 1.3.12.1 1998/11/12 03:23:01 heller Exp $
61f7f7 ____________________________________________________________________________*/
70af5a
76e5bd #ifndef Included_pgpKeyServerDialogCommon_h¤/* [ */
705675 #define Included_pgpKeyServerDialogCommon_h
46af5a
fee684 #include "pgpUserInterface.h"
4aaf5a
7099c6 PGP_BEGIN_C_DECLARATIONS
37af5a
754723 PGPError¤   PGPSearchKeyServerDialogCommon(
b4956f ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   ¤   context,
1b170e ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec ¤serverList[],
c05707 ¤   ¤   ¤   ¤   ¤   PGPUInt32 ¤ ¤   ¤   ¤   serverCount,
dc02ae ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef¤   ¤   tlsContext,
0cb2cf ¤   ¤   ¤   ¤   ¤   PGPFilterRef ¤  ¤   ¤   filterRef,
bf52fe ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr ¤eventHandler,
4a24b5 ¤   ¤   ¤   ¤   ¤   PGPUserValue ¤  ¤   ¤   eventUserValue,
0170c1 ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   searchAllServers,
833275 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys);
ecaf5a
3825da PGPError¤   PGPSendToKeyServerDialogCommon(
bd956f ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   ¤   context,
c9769d ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec ¤*server,
5c02ae ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef¤   ¤   tlsContext,
bf03ce ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   ¤   ¤   keysToSend,
4352fe ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr ¤eventHandler,
1524b5 ¤   ¤   ¤   ¤   ¤   PGPUserValue ¤  ¤   ¤   eventUserValue,
f64b89 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   ¤   *failedKeys);
04ae30 ¤   ¤   ¤   ¤   ¤
5e1254 PGP_END_C_DECLARATIONS
62af5a
5407b8 #endif /* ] Included_pgpKeyServerDialogCommon_h */
e0af5a
787e4d /*__Editor_settings____
f2af5a
584126 ¤   Local Variables:
787b17 ¤   tab-width: 4
ad0e6c ¤   End:
605f8c ¤   vi: ts=4 sw=4
389e9b ¤   vim: si
d7d062 _____________________*/
--ef33 0004b62c6ce40100296 Page 1 of pgpRecipientDialogCommon.cpp
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
a25105 ¤   $Id: pgpRecipientDialogCommon.cpp,v 1.32.10.1 1998/11/12 03:23:02 heller Ex¶
02b277 p $
7af7f7 ____________________________________________________________________________*/
37af5a
0eb1cb #include <ctype.h>
4b324c #include <string.h>
a3af5a
082f8d #include "pgpErrors.h"
fca076 #include "pgpKeys.h"
600d08 #include "pgpMem.h"
614919 #include "pgpUtilities.h"
cbaf5a
fbcc06 #include "pgpDialogs.h"
4ba45e #include "pgpRecipientDialogCommon.h"
2faf5a
afca2c #define¤UserIsVisible(user)¤¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
b804ce ¤   ( IsntNull( user ) &&¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
a4aa49 ¤   ¤   ( user->location == kPGPRecipientUserLocation_UserList ) ||¤¤   \
76e10e ¤   ¤   ( user->location == kPGPRecipientUserLocation_RecipientList ) )
a8af5a
ae8cd2 #define kMandatoryARRMask¤  ¤   0x80
84ab62 #define¤IsMandatoryARRClass(x)¤ (((x) & kMandatoryARRMask) != 0)
7aaf5a
f31964 ¤   static PGPUInt32
279558 GetNextMarkValue(void)
3abb36 {
2cbe89 ¤   static PGPUInt32¤   sMarkValue = 0;
0a67c5 ¤
a1455a ¤   return( ++sMarkValue );
2befe6 }
1caf5a
c7900c ¤   static const char *
a30df7 FindSubstring(
7bbf9f ¤   const char * inBuffer,
d8feb0 ¤   const char * inSearchStr)
77bb36 {
e93abd ¤   const char *¤   currBuffPointer = inBuffer;
8167c5 ¤
df7c13 ¤   while (*currBuffPointer != 0)
edc7a1 ¤   {
65d40a ¤   ¤   const char * compareOne = currBuffPointer;
16303b ¤   ¤   const char * compareTwo = inSearchStr;
d01b52 ¤   ¤
4be7b7 ¤   ¤   while ( tolower(*compareOne) == tolower(*compareTwo) )
065b34 ¤   ¤   {
9bc94b ¤   ¤   ¤   compareOne++;
e9216b ¤   ¤   ¤   compareTwo++;
9b39fb ¤   ¤   ¤   if (*compareTwo == 0)
c2f776 ¤   ¤   ¤   {
4bbb76 ¤   ¤   ¤   ¤   return (char *) currBuffPointer;
c9a3a6 ¤   ¤   ¤   }
5c0fe4 ¤   ¤   }
a6985e ¤   ¤   currBuffPointer++;
5d9371 ¤   }
0f3f59 ¤   return NULL;
79efe6 }
9faf5a
d766dd ¤   static PGPError
36a111 AllocateNewUsers(PGPRecipientsList *recipients)
b1bb36 {
473cbe ¤   PGPError¤   ¤   ¤   ¤   err = kPGPError_NoErr;
c87e33 ¤   PGPRecipientUserList¤   *userList;
c067c5 ¤
91ae17 ¤   userList = (PGPRecipientUserList *) PGPNewData( recipients->memoryMgr,
28e77c ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *userList ), 0 );
6e48ee ¤   if( IsntNull( userList ) )
73c7a1 ¤   {
4bb385 ¤   ¤   PGPUInt32¤  userIndex;
--2a9f 0007f52b4c140100296 Page 2 of pgpRecipientDialogCommon.cpp
f11b52 ¤   ¤
e127da ¤   ¤   // Add user list to recipients.
0e67ff ¤   ¤   userList->nextUserList¤ = recipients->userLists;
4f2fc3 ¤   ¤   recipients->userLists¤  = userList;
e667c5 ¤
414fa4 ¤   ¤   // Thread new users into recipients free list
ac6b2b ¤   ¤   for( userIndex = 0; userIndex < kPGPNumUserListUsers; userIndex++ )
895b34 ¤   ¤   {
4c53a7 ¤   ¤   ¤   userList->users[userIndex].nextUser = recipients->freeUsers;
eed7bb ¤   ¤   ¤   recipients->freeUsers¤  ¤   ¤   ¤   = &userList->users[userIndex];
c00fe4 ¤   ¤   }
789371 ¤   }
a40e24 ¤   else
17c7a1 ¤   {
22bce1 ¤   ¤   err = kPGPError_OutOfMemory;
a99371 ¤   }
ad67c5 ¤
38deb7 ¤   return( err );
82efe6 }
e7af5a
c366dd ¤   static PGPError
bd7321 NewUser(
6bc16d ¤   PGPRecipientsList¤  *recipients,
e6697c ¤   PGPRecipientUser¤   **newUser)
a6bb36 {
5c8e12 ¤   PGPError¤   err = kPGPError_NoErr;
4167c5 ¤
3f5488 ¤   *newUser = NULL;
f167c5 ¤
7b629f ¤   if( IsNull( recipients->freeUsers ) )
7ac7a1 ¤   {
ef841f ¤   ¤   err = AllocateNewUsers( recipients );
a29371 ¤   }
7b67c5 ¤
c0b1f0 ¤   if( IsntPGPError( err ) )
08c7a1 ¤   {
a46d1a ¤   ¤   pgpAssert( IsntNull( recipients->freeUsers ) );
881b52 ¤   ¤
05ac88 ¤   ¤   *newUser¤   ¤   ¤   ¤   = recipients->freeUsers;
c627d3 ¤   ¤   recipients->freeUsers ¤ = recipients->freeUsers->nextUser;
d21b52 ¤   ¤
3a8cac ¤   ¤   pgpClearMemory( *newUser, sizeof( **newUser ) );
2e1b52 ¤   ¤
15c6e0 ¤   ¤   (**newUser).recipients = recipients;
619371 ¤   }
2267c5 ¤
b3deb7 ¤   return( err );
38efe6 }
16af5a
fd66dd ¤   static PGPError
428674 AllocateNewKeys(PGPRecipientsList *recipients)
b8bb36 {
f07d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
f59153 ¤   PGPRecipientKeyList¤*keyList;
0867c5 ¤
ec2152 ¤   keyList = (PGPRecipientKeyList *) PGPNewData( recipients->memoryMgr,
cb9f3e ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( *keyList ), 0 );
0f66e4 ¤   if( IsntNull( keyList ) )
0bc7a1 ¤   {
680960 ¤   ¤   PGPUInt32¤  keyIndex;
cd1b52 ¤   ¤
8926bb ¤   ¤   // Add key list to recipients.
45f2ed ¤   ¤   keyList->nextKeyList¤   = recipients->keyLists;
ce9d5b ¤   ¤   recipients->keyLists¤   = keyList;
1767c5 ¤
adbcb5 ¤   ¤   // Thread new keys into recipients free list
9106d9 ¤   ¤   for( keyIndex = 0; keyIndex < kPGPNumKeyListKeys; keyIndex++ )
975b34 ¤   ¤   {
26c49a ¤   ¤   ¤   keyList->keys[keyIndex].nextKey = recipients->freeKeys;
6982b3 ¤   ¤   ¤   recipients->freeKeys¤   ¤   ¤   = &keyList->keys[keyIndex];
e10fe4 ¤   ¤   }
7f9371 ¤   }
--14ec 0008b22ddcf40100296 Page 3 of pgpRecipientDialogCommon.cpp
060e24 ¤   else
c2c7a1 ¤   {
b1bce1 ¤   ¤   err = kPGPError_OutOfMemory;
e09371 ¤   }
eb67c5 ¤
c3deb7 ¤   return( err );
44efe6 }
6baf5a
7666dd ¤   static PGPError
90f718 NewKey(
afc16d ¤   PGPRecipientsList¤  *recipients,
ed7760 ¤   PGPRecipientKey¤¤   **newKey)
e3bb36 {
d38e12 ¤   PGPError¤   err = kPGPError_NoErr;
0267c5 ¤
abb885 ¤   *newKey = NULL;
6567c5 ¤
c03ad9 ¤   if( IsNull( recipients->freeKeys ) )
a9c7a1 ¤   {
8c4eef ¤   ¤   err = AllocateNewKeys( recipients );
eb9371 ¤   }
be67c5 ¤
58b1f0 ¤   if( IsntPGPError( err ) )
59c7a1 ¤   {
d06547 ¤   ¤   pgpAssert( IsntNull( recipients->freeKeys ) );
75af5a
ea898b ¤   ¤   *newKey ¤   ¤   ¤   ¤   = recipients->freeKeys;
5db2b4 ¤   ¤   recipients->freeKeys ¤  = recipients->freeKeys->nextKey;
c51b52 ¤   ¤
375985 ¤   ¤   pgpClearMemory( *newKey, sizeof( **newKey ) );
0c9371 ¤   }
a067c5 ¤
9fdeb7 ¤   return( err );
6eefe6 }
05af5a
8c33c8 ¤   static void
946d36 FreeKey(PGPRecipientKey *key)
c1bb36 {
889dd5 ¤   pgpAssert( IsntNull( key ) );
3667c5 ¤
c4f065 ¤   if( IsntNull( key->arrKeys ) )
43c7a1 ¤   {
86aada ¤   ¤   PGPFreeData( key->arrKeys );
a40566 ¤   ¤   key->arrKeys = NULL;
159371 ¤   }
4567c5 ¤
c2f978 ¤   /* The key is not individually allocated, so no disposal is necessary */
baefe6 }
87af5a
e566dd ¤   static PGPError
a5620d RememberName(
92c16d ¤   PGPRecipientsList¤  *recipients,
cb0ec2 ¤   const char¤ ¤   ¤   *name,
cce9fa ¤   PGPUInt32¤  ¤   ¤   *nameOffset)
a6bb36 {
ae8e12 ¤   PGPError¤   err = kPGPError_NoErr;
f8665c ¤   PGPUInt32¤  nameLength;
7b67c5 ¤
87c0ca ¤   pgpAssert( IsntNull( recipients) );
d535fa ¤   pgpAssert( IsntNull( name) );
7df470 ¤   pgpAssert( IsntNull( nameOffset) );
c87ab2 ¤   pgpAssert( recipients->nextNameOffset <= recipients->nameListSize );
b1af5a
d540f7 ¤   *nameOffset¤= 0;
079ab7 ¤   nameLength ¤= strlen( name ) + 1;¤  /* Account for trailing '\0' */
82af5a
f08a8a ¤   /* Limit the names to 128 characters in case name is corrupted */
1ed31c ¤   if( nameLength > 128 )
6bd1f9 ¤   ¤   nameLength = 128;
a267c5 ¤
d62f86 ¤   if( nameLength > recipients->nameListSize -
8be6a5 ¤   ¤   ¤   ¤   recipients->nextNameOffset )
--666e 0008a14bd0b40100296 Page 4 of pgpRecipientDialogCommon.cpp
f7c7a1 ¤   {
811ff9 ¤   ¤   PGPUInt32¤  newNameListSize;
86146e ¤   ¤   char¤   ¤   *newNameList;
e41b52 ¤   ¤
9ebf6a ¤   ¤   // Need to grow/allocate the names list.
2f1b52 ¤   ¤
c630f1 ¤   ¤   #define kNameListGrowSize¤  1024L
1e67c5 ¤
12e6a4 ¤   ¤   newNameListSize = recipients->nameListSize + kNameListGrowSize;
1d1b52 ¤   ¤
468e60 ¤   ¤   newNameList = (char *) PGPNewData( recipients->memoryMgr,
65e56c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   newNameListSize, 0 );
f8e37e ¤   ¤   if( IsntNull( newNameList ) )
e35b34 ¤   ¤   {
a65b53 ¤   ¤   ¤   if( IsntNull( recipients->nameList ) )
1cf776 ¤   ¤   ¤   {
c95ed6 ¤   ¤   ¤   ¤   pgpCopyMemory( recipients->nameList, newNameList,
12bdd5 ¤   ¤   ¤   ¤   ¤   ¤   recipients->nameListSize );
cd94aa ¤   ¤   ¤   ¤   ¤   ¤
4c0815 ¤   ¤   ¤   ¤   PGPFreeData( recipients->nameList );
a1a3a6 ¤   ¤   ¤   }
07bb8c ¤   ¤   ¤   else
a8f776 ¤   ¤   ¤   {
745334 ¤   ¤   ¤   ¤   // Special case. Offset zero is invalid and is an empty string
07eff7 ¤   ¤   ¤   ¤   // Start at offset 1
092b85 ¤   ¤   ¤   ¤
630efe ¤   ¤   ¤   ¤   pgpAssert( recipients->nextNameOffset == 0 );
722b85 ¤   ¤   ¤   ¤
5160ac ¤   ¤   ¤   ¤   recipients->nextNameOffset = 1;
b253fd ¤   ¤   ¤   ¤   newNameList[0] = 0;
2aa3a6 ¤   ¤   ¤   }
df87c7 ¤   ¤   ¤
fcc0a8 ¤   ¤   ¤   recipients->nameList ¤  ¤   = newNameList;
2e1fcf ¤   ¤   ¤   recipients->nameListSize¤   = newNameListSize;
dc0fe4 ¤   ¤   }
bd0e1d ¤   ¤   else
185b34 ¤   ¤   {
ecb90c ¤   ¤   ¤   err = kPGPError_OutOfMemory;
110fe4 ¤   ¤   }
0d9371 ¤   }
e967c5 ¤
cbb1f0 ¤   if( IsntPGPError( err ) )
06c7a1 ¤   {
90e8f4 ¤   ¤   pgpAssert( nameLength <= recipients->nameListSize -
925b13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->nextNameOffset );
741b52 ¤   ¤
fc83bf ¤   ¤   pgpCopyMemory( name, &recipients->nameList[recipients->nextNameOffset],
39bb88 ¤   ¤   ¤   ¤   ¤   ¤   ¤   nameLength );
b31b52 ¤   ¤
99d125 ¤   ¤   *nameOffset = recipients->nextNameOffset;
c76de5 ¤   ¤   recipients->nextNameOffset += nameLength;
949371 ¤   }
7067c5 ¤
77deb7 ¤   return( err );
93efe6 }
7baf5a
3866dd ¤   static PGPError
345bfa FindARRKeys(
72c16d ¤   PGPRecipientsList¤  *recipients,
cdf3df ¤   PGPRecipientKey¤¤   *theKey)
1ebb36 {
078e12 ¤   PGPError¤   err = kPGPError_NoErr;
9467c5 ¤
eb64e3 ¤   if( IsntNull( theKey->arrKeys ) )
46c7a1 ¤   {
a7d76d ¤   ¤   PGPFreeData( theKey->arrKeys );
c61b52 ¤   ¤
6fc776 ¤   ¤   theKey->arrKeys ¤   ¤   = NULL;
41ecb1 ¤   ¤   theKey->numARRKeys¤ ¤   = 0;
59022c ¤   ¤   theKey->haveMissingARRs¤= FALSE;
c59371 ¤   }
8a67c5 ¤
--1685 0006020ff7a40100296 Page 5 of pgpRecipientDialogCommon.cpp
73ca57 ¤   if( recipients->arrEnforcement != kPGPARREnforcement_None )
3bc7a1 ¤   {
7cf63a ¤   ¤   PGPUInt32¤  numARRKeys;
00af5a
29a274 ¤   ¤   err = PGPCountAdditionalRecipientRequests( theKey->keyRef,
412bec ¤   ¤   ¤   ¤   ¤   ¤   &numARRKeys );
14314e ¤   ¤   if( IsntPGPError( err ) && numARRKeys != 0)
c15b34 ¤   ¤   {
d18d1e ¤   ¤   ¤   theKey->numARRKeys = (PGPUInt16) numARRKeys;
0eaf5a
0d4542 ¤   ¤   ¤   theKey->arrKeys = (PGPRecipientKeyARRInfo *) PGPNewData(
746b53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->memoryMgr,
1be015 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->numARRKeys *
62a009 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   sizeof( theKey->arrKeys[0] ),
31e779 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
2e61c8 ¤   ¤   ¤   if( IsntNull( theKey->arrKeys ) )
97f776 ¤   ¤   ¤   {
535166 ¤   ¤   ¤   ¤   PGPUInt32¤  arrIndex;
a52b85 ¤   ¤   ¤   ¤
e0836c ¤   ¤   ¤   ¤   for( arrIndex = 0; arrIndex < theKey->numARRKeys;
b2a64b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++arrIndex )
0972c3 ¤   ¤   ¤   ¤   {
b9d4b6 ¤   ¤   ¤   ¤   ¤   PGPRecipientKeyARRInfo¤ *arrInfo;
5d5df2 ¤   ¤   ¤   ¤   ¤   PGPKeyRef¤  ¤   ¤   ¤   arrKeyRef = kInvalidPGPKeyRef;
e5ae30 ¤   ¤   ¤   ¤   ¤
849a5c ¤   ¤   ¤   ¤   ¤   arrInfo = &theKey->arrKeys[arrIndex];
bfae30 ¤   ¤   ¤   ¤   ¤
353941 ¤   ¤   ¤   ¤   ¤   err = PGPGetIndexedAdditionalRecipientRequestKey(
918707 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->keyRef, recipients->keySet, arrIndex,
582dbc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &arrKeyRef, &arrInfo->keyID,
894710 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &arrInfo->arrClass );
1f6ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
c64859 ¤   ¤   ¤   ¤   ¤   {
a0022e ¤   ¤   ¤   ¤   ¤   ¤   if( PGPKeyRefIsValid( arrKeyRef ) )
3e8fec ¤   ¤   ¤   ¤   ¤   ¤   {
fbbecd ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyUserVal( arrKeyRef,
0fef11 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUserValue *) &arrInfo->key );
5cdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
c094aa ¤   ¤   ¤   ¤   ¤   ¤
1051ed ¤   ¤   ¤   ¤   ¤   ¤   if( IsNull( arrInfo->key ) )
8b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
84474a ¤   ¤   ¤   ¤   ¤   ¤   ¤   arrInfo->keyMissing = TRUE;
42db3c ¤   ¤   ¤   ¤   ¤   ¤   }
88c0e4 ¤   ¤   ¤   ¤   ¤   ¤   else if( ! arrInfo->key->isVisible )
9a8fec ¤   ¤   ¤   ¤   ¤   ¤   {
a075d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   arrInfo->key = NULL;
97db3c ¤   ¤   ¤   ¤   ¤   ¤   }
71ae30 ¤   ¤   ¤   ¤   ¤
3dde86 ¤   ¤   ¤   ¤   ¤   ¤   if( IsMandatoryARRClass( arrInfo->arrClass ) &&
dd57c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   IsNull( arrInfo->key ) )
f48fec ¤   ¤   ¤   ¤   ¤   ¤   {
c8dbac ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->haveMissingARRs = TRUE;
97db3c ¤   ¤   ¤   ¤   ¤   ¤   }
4a1c89 ¤   ¤   ¤   ¤   ¤   }
37ae30 ¤   ¤   ¤   ¤   ¤
a614ec ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
1014c3 ¤   ¤   ¤   ¤   ¤   break;
682613 ¤   ¤   ¤   ¤   }
12a3a6 ¤   ¤   ¤   }
37bb8c ¤   ¤   ¤   else
cef776 ¤   ¤   ¤   {
fabfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
47a3a6 ¤   ¤   ¤   }
640fe4 ¤   ¤   }
4f9371 ¤   }
4667c5 ¤
cfdeb7 ¤   return( err );
55efe6 }
6caf5a
4966dd ¤   static PGPError
9497b2 AddKey(
60c16d ¤   PGPRecipientsList¤  *recipients,
--ad93 000e3eda98840100296 Page 6 of pgpRecipientDialogCommon.cpp
39dd48 ¤   PGPKeyIterRef¤  ¤   iterator,
4ec209 ¤   PGPKeyRef¤  ¤   ¤   keyRef,
ceec3f ¤   PGPBoolean¤ ¤   ¤   isDefaultKey,
424e13 ¤   PGPBoolean¤ ¤   ¤   markAsNew,
13f6ef ¤   PGPRecipientKey¤¤   **recipientKey)
57bb36 {
787d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
fa55fe ¤   PGPRecipientKey¤¤   *theKey;
9467c5 ¤
32f521 ¤   err = NewKey( recipients, &theKey );
c2b1f0 ¤   if( IsntPGPError( err ) )
72c7a1 ¤   {
ee8080 ¤   ¤   PGPUserIDRef¤   primaryUserID;
491b52 ¤   ¤
f02c6d ¤   ¤   theKey->keyRef¤ ¤   ¤   = keyRef;
bd5cc9 ¤   ¤   theKey->isDefaultKey¤   = isDefaultKey;
7c1ec6 ¤   ¤   theKey->isNewKey¤   ¤   = markAsNew;
15b078 ¤   ¤   theKey->isVisible¤  ¤   = FALSE;¤   ¤   /* Assume not visible */
a61b52 ¤   ¤
a31eb3 ¤   ¤   (void) PGPGetPrimaryUserID( keyRef, &primaryUserID );
e31b52 ¤   ¤
9df739 ¤   ¤   if( recipients->arrEnforcement != kPGPARREnforcement_None )
635b34 ¤   ¤   {
63466a ¤   ¤   ¤   err = FindARRKeys( recipients, theKey );
1e0fe4 ¤   ¤   }
2d1b52 ¤   ¤
c686f8 ¤   ¤   if( IsntPGPError( err ) )
345b34 ¤   ¤   {
8e7da6 ¤   ¤   ¤   PGPInt32¤   algorithm;
28af5a
ed1c45 ¤   ¤   ¤   err = PGPGetKeyNumber( keyRef, kPGPKeyPropAlgID, &algorithm );
601b52 ¤   ¤
f1288e ¤   ¤   ¤   theKey->algorithm = (PGPPublicKeyAlgorithm)algorithm;
310fe4 ¤   ¤   }
b21b52 ¤   ¤
a786f8 ¤   ¤   if( IsntPGPError( err ) )
2c5b34 ¤   ¤   {
d64420 ¤   ¤   ¤   PGPBoolean¤ isAxiomaticKey;
7f87c7 ¤   ¤   ¤
763650 ¤   ¤   ¤   err = PGPGetKeyBoolean( keyRef, kPGPKeyPropIsAxiomatic,
f4ad91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &isAxiomaticKey );
42da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
dafda9 ¤   ¤   ¤   theKey->isAxiomaticKey = isAxiomaticKey;
730fe4 ¤   ¤   }
f6af5a
aa86f8 ¤   ¤   if( IsntPGPError( err ) )
1c5b34 ¤   ¤   {
27eb4a ¤   ¤   ¤   PGPBoolean¤ isSecretKey;
c087c7 ¤   ¤   ¤
512d90 ¤   ¤   ¤   err = PGPGetKeyBoolean( keyRef, kPGPKeyPropIsSecret,
a4e8c0 ¤   ¤   ¤   ¤   ¤   ¤   &isSecretKey );
8587c7 ¤   ¤   ¤
64e1f8 ¤   ¤   ¤   theKey->isSecretKey = isSecretKey;
903b90 ¤   ¤   }¤
3a1b52 ¤   ¤
0886f8 ¤   ¤   if( IsntPGPError( err ) )
0e5b34 ¤   ¤   {
0b3efc ¤   ¤   ¤   PGPBoolean¤ canEncrypt;
3887c7 ¤   ¤   ¤
d8083a ¤   ¤   ¤   err = PGPGetKeyBoolean( keyRef, kPGPKeyPropCanEncrypt,
4d6e76 ¤   ¤   ¤   ¤   ¤   ¤   &canEncrypt );
2bda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
457044 ¤   ¤   ¤   theKey->canEncrypt = canEncrypt;
990fe4 ¤   ¤   }
97af5a
c386f8 ¤   ¤   if( IsntPGPError( err ) )
7d5b34 ¤   ¤   {
381b9d ¤   ¤   ¤   PGPInt32¤   keyBits;
a587c7 ¤   ¤   ¤
c04ada ¤   ¤   ¤   err = PGPGetKeyNumber( keyRef, kPGPKeyPropBits, &keyBits );
4aaf5a
e32a1f ¤   ¤   ¤   theKey->keyBits = (PGPUInt16) keyBits;
--ec70 0003baebb3c40100296 Page 7 of pgpRecipientDialogCommon.cpp
b50fe4 ¤   ¤   }
be87c7 ¤   ¤   ¤
8d86f8 ¤   ¤   if( IsntPGPError( err ) )
845b34 ¤   ¤   {
e1a15a ¤   ¤   ¤   // Iterate our one-key set to the first key
0d87c7 ¤   ¤   ¤
98603e ¤   ¤   ¤   if( theKey->algorithm == kPGPPublicKeyAlgorithm_DSA )
4ef776 ¤   ¤   ¤   {
0f04ca ¤   ¤   ¤   ¤   PGPSubKeyRef¤   subKey;
a4af5a
8fb8e7 ¤   ¤   ¤   ¤   // Get the subkey to determine the
32a4f9 ¤   ¤   ¤   ¤   // encryption key bits.
3eae30 ¤   ¤   ¤   ¤   ¤
55e07c ¤   ¤   ¤   ¤   err = PGPKeyIterNextSubKey( iterator, &subKey );
6a5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
4a72c3 ¤   ¤   ¤   ¤   {
5a2318 ¤   ¤   ¤   ¤   ¤   PGPInt32¤   keyBits;
d4ae30 ¤   ¤   ¤   ¤   ¤
8af73a ¤   ¤   ¤   ¤   ¤   err = PGPGetSubKeyNumber( subKey, kPGPKeyPropBits,
962d32 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyBits );
ccae30 ¤   ¤   ¤   ¤   ¤
4df9f3 ¤   ¤   ¤   ¤   ¤   theKey->subKeyBits = (PGPUInt16) keyBits;
3e2613 ¤   ¤   ¤   ¤   }
aa2b85 ¤   ¤   ¤   ¤
04c4e0 ¤   ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
52b37b ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
90a3a6 ¤   ¤   ¤   }
1a87c7 ¤   ¤   ¤
79698b ¤   ¤   ¤   if( IsntPGPError( err ) )
0df776 ¤   ¤   ¤   {
18bc35 ¤   ¤   ¤   ¤   PGPUserIDRef¤   curUserID;
f72b85 ¤   ¤   ¤   ¤
18860d ¤   ¤   ¤   ¤   err = PGPKeyIterNextUserID( iterator, &curUserID );
0989e2 ¤   ¤   ¤   ¤   while( IsntPGPError( err ) )
5972c3 ¤   ¤   ¤   ¤   {
828f86 ¤   ¤   ¤   ¤   ¤   PGPRecipientUser¤   *user;
04ae30 ¤   ¤   ¤   ¤   ¤
7e2cb5 ¤   ¤   ¤   ¤   ¤   err = NewUser( recipients, &user );
0e6ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
874859 ¤   ¤   ¤   ¤   ¤   {
4a6a5a ¤   ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   bufferSize;
a1eab3 ¤   ¤   ¤   ¤   ¤   ¤   char¤   ¤   tempName[ 256 ];
8baf5a
994012 ¤   ¤   ¤   ¤   ¤   ¤   user->kind¤ ¤   ¤   ¤   = kPGPRecipientUserKind_Key;
b90f95 ¤   ¤   ¤   ¤   ¤   ¤   user->userInfo.key ¤¤   = theKey;
483e78 ¤   ¤   ¤   ¤   ¤   ¤   user->userInfo.userID¤  = curUserID;
1294aa ¤   ¤   ¤   ¤   ¤   ¤
0da618 ¤   ¤   ¤   ¤   ¤   ¤   if( theKey->canEncrypt )
d28fec ¤   ¤   ¤   ¤   ¤   ¤   {
0f8cca ¤   ¤   ¤   ¤   ¤   ¤   ¤   user->location =
2b6a30 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_UserList;
1adb3c ¤   ¤   ¤   ¤   ¤   ¤   }
8a7f8b ¤   ¤   ¤   ¤   ¤   ¤   else
e08fec ¤   ¤   ¤   ¤   ¤   ¤   {
098cca ¤   ¤   ¤   ¤   ¤   ¤   ¤   user->location =
e7c234 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_Hidden;
29db3c ¤   ¤   ¤   ¤   ¤   ¤   }
c094aa ¤   ¤   ¤   ¤   ¤   ¤
c40110 ¤   ¤   ¤   ¤   ¤   ¤   if( curUserID == primaryUserID )
7b3bb8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   user->userInfo.isPrimaryUser = TRUE;
c394aa ¤   ¤   ¤   ¤   ¤   ¤
fc1a2f ¤   ¤   ¤   ¤   ¤   ¤   tempName[0] = 0;
4394aa ¤   ¤   ¤   ¤   ¤   ¤
b4be0e ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetUserIDStringBuffer( curUserID,
f2f6de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPUserIDPropName, sizeof( tempName ),
09fa25 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   tempName, &bufferSize );
a0ccc4 ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) ||
d46dd6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err == kPGPError_BufferTooSmall )
798fec ¤   ¤   ¤   ¤   ¤   ¤   {
28496d ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = RememberName( recipients, tempName,·
b86e01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &user->nameOffset );
3bdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
--c3c5 000c85abd4740100296 Page 8 of pgpRecipientDialogCommon.cpp
e694aa ¤   ¤   ¤   ¤   ¤   ¤
3e239e ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
4f8fec ¤   ¤   ¤   ¤   ¤   ¤   {
29bd75 ¤   ¤   ¤   ¤   ¤   ¤   ¤   // Link the user to the key
891f37 ¤   ¤   ¤   ¤   ¤   ¤   ¤   user->nextUser ¤= theKey->users;
4c91e3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->users ¤ = user;
16531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
554e4c ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( UserIsVisible( user ) )
0906b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
0e2b6b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->isVisible = TRUE;
5cda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
41c686 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( user->userInfo.isPrimaryUser )
6f31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
f8afff ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->primaryUser = user;
b96560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
beed00 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   else if( IsNull( theKey->primaryUser ))
e231b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
41afff ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   theKey->primaryUser = user;
466560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
ba5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
1adb3c ¤   ¤   ¤   ¤   ¤   ¤   }
2b94aa ¤   ¤   ¤   ¤   ¤   ¤
b1d373 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNextUserID( iterator, &curUserID );
811c89 ¤   ¤   ¤   ¤   ¤   }
2f2613 ¤   ¤   ¤   ¤   }
1387c7 ¤   ¤   ¤
97c4e0 ¤   ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
7ab37b ¤   ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
46a3a6 ¤   ¤   ¤   }
a00fe4 ¤   ¤   }
a91b52 ¤   ¤
ec86f8 ¤   ¤   if( IsntPGPError( err ) )
b65b34 ¤   ¤   {
146900 ¤   ¤   ¤   pgpAssert( IsntNull( theKey->users ) );
e587c7 ¤   ¤   ¤
a85238 ¤   ¤   ¤   // Set the primary user to the first user in the list if
309e57 ¤   ¤   ¤   // no explicit or visible primary user was found.
8087c7 ¤   ¤   ¤
82c2eb ¤   ¤   ¤   if( IsNull( theKey->primaryUser ) )
0bfad1 ¤   ¤   ¤   ¤   theKey->primaryUser = theKey->users;
882b85 ¤   ¤   ¤   ¤
ab4e28 ¤   ¤   ¤   // Finally, link key into the list
924ad3 ¤   ¤   ¤   theKey->nextKey¤¤   = recipients->keys;
a55acc ¤   ¤   ¤   recipients->keys¤   = theKey;
860fe4 ¤   ¤   }
a20e1d ¤   ¤   else
42ed49 ¤   ¤   {¤
b45738 ¤   ¤   ¤   FreeKey( theKey );
b04bd1 ¤   ¤   ¤   theKey = NULL;
d00fe4 ¤   ¤   }
a89371 ¤   }
a967c5 ¤
41e755 ¤   *recipientKey = theKey;
ea67c5 ¤
76deb7 ¤   return( err );
70efe6 }
10af5a
3a66dd ¤   static PGPError
fcd2f4 UpdateDynamicRecipientValues(PGPRecipientsList *recipients)
44bb36 {
87576f ¤   PGPRecipientKey¤¤   *curKey;
64a522 ¤   PGPRecipientUser¤   *curUser;
2d7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
3867c5 ¤
3ac575 ¤   curKey = recipients->keys;
e10a69 ¤   while( IsntNull( curKey ) && IsntPGPError( err ) )
9dc7a1 ¤   {
cb791a ¤   ¤   curUser = curKey->users;
837ebc ¤   ¤   while( IsntNull( curUser ) )
5e5b34 ¤   ¤   {
c4ce4d ¤   ¤   ¤   PGPInt32¤   userValidity;
c8531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
--3ffe 00018f9868540100296 Page 9 of pgpRecipientDialogCommon.cpp
78f1a5 ¤   ¤   ¤   if( IsntPGPError( PGPGetUserIDNumber( curUser->userInfo.userID,
52c12b ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPUserIDPropValidity, &userValidity ) ) )
dbf776 ¤   ¤   ¤   {
fad734 ¤   ¤   ¤   ¤   curUser->validity = (PGPValidity) userValidity;
d5a3a6 ¤   ¤   ¤   }
9fbb8c ¤   ¤   ¤   else
c3f776 ¤   ¤   ¤   {
70897f ¤   ¤   ¤   ¤   curUser->validity = kPGPValidity_Invalid;
93a3a6 ¤   ¤   ¤   }
b2da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
7c09b3 ¤   ¤   ¤   curUser = curUser->nextUser;
d10fe4 ¤   ¤   }
8b1b52 ¤   ¤
a9f739 ¤   ¤   if( recipients->arrEnforcement != kPGPARREnforcement_None )
dc5b34 ¤   ¤   {
8c65fd ¤   ¤   ¤   err = FindARRKeys( recipients, curKey );
4859df ¤   ¤   ¤   if( IsPGPError( err ) )
eaf622 ¤   ¤   ¤   ¤   break;
470fe4 ¤   ¤   }
751b52 ¤   ¤
8fcf46 ¤   ¤   curKey = curKey->nextKey;
e59371 ¤   }
62af5a
e43d92 ¤   curUser = recipients->groups;
eb7d5c ¤   while( IsntNull( curUser ) && IsntPGPError( err ) )
28c7a1 ¤   {
138371 ¤   ¤   PGPUInt32¤  groupItemIndex;
c81b52 ¤   ¤
addc38 ¤   ¤   curUser->validity ¤ ¤   ¤   ¤   ¤   = kPGPValidity_Complete;
b48edf ¤   ¤   curUser->groupInfo.numMissingKeys¤  = 0;
52e247 ¤   ¤   curUser->groupInfo.haveMissingARRs ¤= FALSE;
cc1f21 ¤   ¤   curUser->groupInfo.numARRKeys¤  ¤   = 0;
e81b52 ¤   ¤
d23318 ¤   ¤   for( groupItemIndex = 0; groupItemIndex < curUser->groupInfo.numKeys;
d731ba ¤   ¤   ¤   ¤   ¤   ++groupItemIndex )
e85b34 ¤   ¤   {
80fb32 ¤   ¤   ¤   PGPGroupItem¤   item;
e887c7 ¤   ¤   ¤
a9c326 ¤   ¤   ¤   err = PGPGetIndGroupItem( recipients->groupSet,
be355e ¤   ¤   ¤   ¤   ¤   ¤   curUser->groupInfo.groupID, groupItemIndex, &item );
83698b ¤   ¤   ¤   if( IsntPGPError( err ) )
30f776 ¤   ¤   ¤   {
2bc7d5 ¤   ¤   ¤   ¤   PGPRecipientKey¤*key = NULL;
a3af5a
5ccb83 ¤   ¤   ¤   ¤   if( item.userValue == NULL )
3d72c3 ¤   ¤   ¤   ¤   {
cf79fd ¤   ¤   ¤   ¤   ¤   PGPKeyRef¤  theKey;
30ae30 ¤   ¤   ¤   ¤   ¤
c8c382 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( PGPGetKeyByKeyID( recipients->keySet,
631dda ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &item.u.key.keyID,
49a427 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   item.u.key.algorithm, &theKey ) ) )
044859 ¤   ¤   ¤   ¤   ¤   {
e0d575 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyUserVal( theKey,
3c90cb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUserValue *) &key );
851c89 ¤   ¤   ¤   ¤   ¤   }
d1ae30 ¤   ¤   ¤   ¤   ¤
1a6d9f ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && IsntNull( key ) )
6e4859 ¤   ¤   ¤   ¤   ¤   {
e68c8a ¤   ¤   ¤   ¤   ¤   ¤   err = PGPSetIndGroupItemUserValue( recipients->groupSet,
5b3f13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->groupInfo.groupID, groupItemIndex,
4694f7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUserValue) key );
5a1c89 ¤   ¤   ¤   ¤   ¤   }
ab2613 ¤   ¤   ¤   ¤   }
6ffa07 ¤   ¤   ¤   ¤   else
f572c3 ¤   ¤   ¤   ¤   {
fa9db7 ¤   ¤   ¤   ¤   ¤   key = (PGPRecipientKey *) item.userValue;
c82613 ¤   ¤   ¤   ¤   }
452b85 ¤   ¤   ¤   ¤
f2131f ¤   ¤   ¤   ¤   if( IsntNull( key ) )
a772c3 ¤   ¤   ¤   ¤   {
ed1f33 ¤   ¤   ¤   ¤   ¤   if( key->primaryUser->validity < curUser->validity )
18f541 ¤   ¤   ¤   ¤   ¤   ¤   curUser->validity = key->primaryUser->validity;
--b6fb 0003539d81840100296 Page 10 of pgpRecipientDialogCommon.cpp
e694aa ¤   ¤   ¤   ¤   ¤   ¤
b8f2e6 ¤   ¤   ¤   ¤   ¤   if( key->haveMissingARRs )
77e5ac ¤   ¤   ¤   ¤   ¤   ¤   curUser->groupInfo.haveMissingARRs = TRUE;
f794aa ¤   ¤   ¤   ¤   ¤   ¤
08fa45 ¤   ¤   ¤   ¤   ¤   curUser->groupInfo.numARRKeys += key->numARRKeys;
e92613 ¤   ¤   ¤   ¤   }
13fa07 ¤   ¤   ¤   ¤   else
6b72c3 ¤   ¤   ¤   ¤   {
db07e9 ¤   ¤   ¤   ¤   ¤   ++curUser->groupInfo.numMissingKeys;
5d2613 ¤   ¤   ¤   ¤   }
48a3a6 ¤   ¤   ¤   }
4287c7 ¤   ¤   ¤
ac59df ¤   ¤   ¤   if( IsPGPError( err ) )
18f622 ¤   ¤   ¤   ¤   break;
f20fe4 ¤   ¤   }
d567c5 ¤
c40c5e ¤   ¤   curUser = curUser->nextUser;
ae9371 ¤   }
8467c5 ¤
f1deb7 ¤   return( err );
8defe6 }
cdaf5a
4966dd ¤   static PGPError
48b84a UpdateNewKeys(
eac16d ¤   PGPRecipientsList¤  *recipients,
3430ab ¤   PGPBoolean¤ ¤   ¤   markAsNew)
2fbb36 {
a7fb19 ¤   PGPError¤   ¤   err;
c75445 ¤   PGPKeyListRef¤  keyList;
a8af5a
1ca0d1 ¤   err = PGPOrderKeySet( recipients->keySet, kPGPAnyOrdering, &keyList );
b7b1f0 ¤   if( IsntPGPError( err ) )
23c7a1 ¤   {
b15671 ¤   ¤   PGPKeyIterRef¤  iterator;
713ed2 ¤   ¤   PGPKeyRef¤  ¤   defaultKey = kInvalidPGPKeyRef;
c41b52 ¤   ¤
580c17 ¤   ¤   (void) PGPGetDefaultPrivateKey( recipients->keySet, &defaultKey );
a61b52 ¤   ¤
9c9466 ¤   ¤   err = PGPNewKeyIter( keyList, &iterator );
b986f8 ¤   ¤   if( IsntPGPError( err ) )
a35b34 ¤   ¤   {
263754 ¤   ¤   ¤   PGPKeyRef¤  theKey;
ac87c7 ¤   ¤   ¤
2e0f67 ¤   ¤   ¤   err = PGPKeyIterNext( iterator, &theKey );
398f5a ¤   ¤   ¤   while( IsntPGPError( err ) )
9ff776 ¤   ¤   ¤   {
6213da ¤   ¤   ¤   ¤   PGPRecipientKey¤*recipientKey;
41af5a
d21698 ¤   ¤   ¤   ¤   err = PGPGetKeyUserVal( theKey,
63ab32 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (PGPUserValue *) &recipientKey );
4364f3 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && IsNull( recipientKey ) )
4b72c3 ¤   ¤   ¤   ¤   {
370e8f ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ isDefault = ( theKey == defaultKey );
d32b85 ¤   ¤   ¤   ¤
a2dfd4 ¤   ¤   ¤   ¤   ¤   err = AddKey( recipients, iterator, theKey, isDefault,
3570b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   markAsNew, &recipientKey );
f16ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
d14859 ¤   ¤   ¤   ¤   ¤   {
28f49a ¤   ¤   ¤   ¤   ¤   ¤   err = PGPSetKeyUserVal( theKey, recipientKey );
3b1c89 ¤   ¤   ¤   ¤   ¤   }
442613 ¤   ¤   ¤   ¤   }
2d2b85 ¤   ¤   ¤   ¤
135565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
1972c3 ¤   ¤   ¤   ¤   {
1c08be ¤   ¤   ¤   ¤   ¤   err = PGPKeyIterNext( iterator, &theKey );
9b2613 ¤   ¤   ¤   ¤   }
57a3a6 ¤   ¤   ¤   }
5687c7 ¤   ¤   ¤
2b6ae1 ¤   ¤   ¤   if( err == kPGPError_EndOfIteration )
60bd37 ¤   ¤   ¤   ¤   err = kPGPError_NoErr;
c82b85 ¤   ¤   ¤   ¤
35a3f6 ¤   ¤   ¤   PGPFreeKeyIter( iterator );
--f060 0006b19d8bf40100296 Page 11 of pgpRecipientDialogCommon.cpp
b50fe4 ¤   ¤   }
3b1b52 ¤   ¤
cd6efb ¤   ¤   PGPFreeKeyList( keyList );
769371 ¤   }
8167c5 ¤
55deb7 ¤   return( err );
5aefe6 }
a4af5a
cd66dd ¤   static PGPError
08b3bd AddKeySet(
30c16d ¤   PGPRecipientsList¤  *recipients,
9b70b4 ¤   PGPKeySetRef¤   ¤   keySet)
64bb36 {
a8d98e ¤   pgpAssert( ! PGPKeySetRefIsValid( recipients->keySet ) );
0b67c5 ¤
084c29 ¤   recipients->keySet = keySet;
d967c5 ¤
0c78a6 ¤   return( UpdateNewKeys( recipients, FALSE ) );
09efe6 }
daaf5a
6466dd ¤   static PGPError
41671f AddNewKeys(
6cc16d ¤   PGPRecipientsList¤  *recipients,
db70b4 ¤   PGPKeySetRef¤   ¤   keySet)
ccbb36 {
6b61e0 ¤   PGPError¤   err;
2067c5 ¤
d7da03 ¤   err = PGPAddKeys( keySet, recipients->keySet );
c9b1f0 ¤   if( IsntPGPError( err ) )
b5c7a1 ¤   {
e0c220 ¤   ¤   err = PGPCheckKeyRingSigs( keySet, recipients->keySet,
d4d9e0 ¤   ¤   ¤   ¤   FALSE, NULL, 0 );
fa86f8 ¤   ¤   if( IsntPGPError( err ) )
685b34 ¤   ¤   {
34664e ¤   ¤   ¤   err = PGPPropagateTrust( recipients->keySet );
b6698b ¤   ¤   ¤   if( IsntPGPError( err ) )
e4f776 ¤   ¤   ¤   {
c849c2 ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges( recipients->keySet );
d45565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
7772c3 ¤   ¤   ¤   ¤   {
5e30d4 ¤   ¤   ¤   ¤   ¤   err = UpdateNewKeys( recipients, TRUE );
176ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
524859 ¤   ¤   ¤   ¤   ¤   {
49ce95 ¤   ¤   ¤   ¤   ¤   ¤   err = UpdateDynamicRecipientValues( recipients );
081c89 ¤   ¤   ¤   ¤   ¤   }
7c2613 ¤   ¤   ¤   ¤   }
52a3a6 ¤   ¤   ¤   }
390fe4 ¤   ¤   }
c29371 ¤   }
e967c5 ¤
1fdeb7 ¤   return( err );
ffefe6 }
a6af5a
ec66dd ¤   static PGPError
8cfb07 CountUniqueGroupItems(
f9bdfd ¤   PGPGroupSetRef¤ groupSet,
79b302 ¤   PGPGroupID¤ ¤   groupID,
8b2c23 ¤   PGPUInt32 *¤¤   outNumKeys,
4a8b81 ¤   PGPUInt32 *¤¤   outTotal)
f4bb36 {
66ba1e ¤   PGPGroupSetRef¤ flattenedSet;
d5fb19 ¤   PGPError¤   ¤   err;
cc67c5 ¤
f4e772 ¤   if ( IsntNull( outNumKeys ) )
d2f582 ¤   ¤   *outNumKeys¤= 0;
961b52 ¤   ¤
4d160d ¤   if ( IsntNull( outTotal ) )
572222 ¤   ¤   *outTotal = 0;
1f67c5 ¤
0561a9 ¤   err = PGPNewGroupSet( PGPGetGroupSetContext( groupSet ), &flattenedSet );
5bb1f0 ¤   if( IsntPGPError( err ) )
6bc7a1 ¤   {
--c9b9 0003bab9d7740100296 Page 12 of pgpRecipientDialogCommon.cpp
0c276f ¤   ¤   PGPGroupID¤ flattenedID;
8e1b52 ¤   ¤
c07232 ¤   ¤   err = PGPNewFlattenedGroupFromGroup( groupSet, groupID, flattenedSet,
ff63fc ¤   ¤   ¤   ¤   ¤   &flattenedID );
2886f8 ¤   ¤   if( IsntPGPError( err ) )
645b34 ¤   ¤   {
848d8a ¤   ¤   ¤   err = PGPCountGroupItems( flattenedSet, flattenedID, TRUE,
bd9f34 ¤   ¤   ¤   ¤   ¤   outNumKeys, outTotal );
d60fe4 ¤   ¤   }
8d1b52 ¤   ¤
538b6c ¤   ¤   PGPFreeGroupSet( flattenedSet );
ec9371 ¤   }
9567c5 ¤
5edeb7 ¤   return( err );
1defe6 }
3daf5a
8766dd ¤   static PGPError
796659 AddGroup(
8bc16d ¤   PGPRecipientsList¤  *recipients,
03e468 ¤   PGPGroupSetRef¤ ¤   groupSet,
bcdde4 ¤   PGPGroupID¤ ¤   ¤   groupID)
adbb36 {
4d8f52 ¤   PGPError¤   ¤   ¤   err;
47ddde ¤   PGPRecipientUser¤   *user;
9767c5 ¤
577f6e ¤   err = NewUser( recipients, &user );
a3b1f0 ¤   if( IsntPGPError( err ) )
eec7a1 ¤   {
2e81d5 ¤   ¤   user->kind = kPGPRecipientUserKind_Group;
861b52 ¤   ¤
979947 ¤   ¤   err = PGPNewFlattenedGroupFromGroup( groupSet, groupID,
b6c9f1 ¤   ¤   ¤   ¤   ¤   recipients->groupSet, &user->groupInfo.groupID );
c886f8 ¤   ¤   if( IsntPGPError( err ) )
fd5b34 ¤   ¤   {
293ad8 ¤   ¤   ¤   err = PGPCountGroupItems( recipients->groupSet,
69e623 ¤   ¤   ¤   ¤   ¤   ¤   user->groupInfo.groupID, TRUE,
213a8f ¤   ¤   ¤   ¤   ¤   ¤   &user->groupInfo.numKeys, NULL );
e8ec8a ¤   ¤   ¤   if( IsntPGPError( err ) && user->groupInfo.numKeys > 0 )
86f776 ¤   ¤   ¤   {
872cf2 ¤   ¤   ¤   ¤   PGPGroupInfo¤   info;
9c87c7 ¤   ¤   ¤
d2e94c ¤   ¤   ¤   ¤   err¤= PGPGetGroupInfo( groupSet, groupID, &info );
825565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
1b72c3 ¤   ¤   ¤   ¤   {
9d2308 ¤   ¤   ¤   ¤   ¤   err = RememberName( recipients, info.name,
9b2787 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &user->nameOffset );
b72613 ¤   ¤   ¤   ¤   }
30a3a6 ¤   ¤   ¤   }
f40fe4 ¤   ¤   }
ad1b52 ¤   ¤
4f86f8 ¤   ¤   if( IsntPGPError( err ) )
ef5b34 ¤   ¤   {
3e80cf ¤   ¤   ¤   if( user->groupInfo.numKeys > 0 )
01f776 ¤   ¤   ¤   {
eb50a3 ¤   ¤   ¤   ¤   user->location = kPGPRecipientUserLocation_UserList;
a5a3a6 ¤   ¤   ¤   }
54bb8c ¤   ¤   ¤   else
4cf776 ¤   ¤   ¤   {
fa1dde ¤   ¤   ¤   ¤   user->location = kPGPRecipientUserLocation_Hidden;
35a3a6 ¤   ¤   ¤   }
c087c7 ¤   ¤   ¤
e9fc63 ¤   ¤   ¤   user->nextUser ¤¤   = recipients->groups;
12c070 ¤   ¤   ¤   recipients->groups ¤= user;
bd0fe4 ¤   ¤   }
7e9371 ¤   }
9d531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
3edeb7 ¤   return( err );
3eefe6 }
a0af5a
ec66dd ¤   static PGPError
6cf66a AddGroupSet(
3ba1bc ¤   PGPContextRef¤  ¤   context,
--89c2 000c79db2c940100296 Page 13 of pgpRecipientDialogCommon.cpp
66c16d ¤   PGPRecipientsList¤  *recipients,
159ad0 ¤   PGPGroupSetRef¤ ¤   groupSet)
15bb36 {
80e6b7 ¤   PGPUInt32¤  numGroups;
4461e0 ¤   PGPError¤   err;
b567c5 ¤
1def4a ¤   err = PGPNewGroupSet( context, &recipients->groupSet );
42b1f0 ¤   if( IsntPGPError( err ) )
1bc7a1 ¤   {
a59fa7 ¤   ¤   err¤= PGPCountGroupsInSet( groupSet, &numGroups );
7e86f8 ¤   ¤   if( IsntPGPError( err ) )
3f5b34 ¤   ¤   {
433130 ¤   ¤   ¤   PGPUInt32¤  index;
aa87c7 ¤   ¤   ¤
c1a8b5 ¤   ¤   ¤   for( index = 0; index < numGroups; ++index )
65f776 ¤   ¤   ¤   {
08e782 ¤   ¤   ¤   ¤   PGPGroupID¤ groupID;
632b85 ¤   ¤   ¤   ¤
b53646 ¤   ¤   ¤   ¤   err¤= PGPGetIndGroupID( groupSet, index, &groupID );
e13227 ¤   ¤   ¤   ¤   if ( IsntPGPError( err ) )
3972c3 ¤   ¤   ¤   ¤   {
627d34 ¤   ¤   ¤   ¤   ¤   err = AddGroup( recipients, groupSet, groupID );
de2613 ¤   ¤   ¤   ¤   }
6b2b85 ¤   ¤   ¤   ¤
66869d ¤   ¤   ¤   ¤   if ( IsPGPError( err ) )
1914c3 ¤   ¤   ¤   ¤   ¤   break;
b1a3a6 ¤   ¤   ¤   }
280fe4 ¤   ¤   }
539371 ¤   }
7267c5 ¤
63deb7 ¤   return( err );
b2efe6 }
baaf5a
801767 ¤   static PGPRecipientKey *
dccbce FindKeyFromKeyRef(
066e21 ¤   const PGPRecipientsList¤¤   *recipients,
341ef1 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   searchKeyRef)
46bb36 {
e88d08 ¤   PGPRecipientKey¤*curKey;
c9af5a
0dc575 ¤   curKey = recipients->keys;
02ef78 ¤   while( IsntNull( curKey ) )
35c7a1 ¤   {
0c5c22 ¤   ¤   if( PGPCompareKeys( curKey->keyRef, searchKeyRef,
3c3a49 ¤   ¤   ¤   ¤   ¤   kPGPKeyIDOrdering ) == 0 )
75cdcb ¤   ¤   ¤   break;
2e1b52 ¤   ¤
e2cf46 ¤   ¤   curKey = curKey->nextKey;
049371 ¤   }
4faf5a
7dc55c ¤   return( curKey );
fbefe6 }
45af5a
f8a11c /* Must use PGPFreeData to dispose of foundUsers */
c8af5a
0766dd ¤   static PGPError
f290ba FindUsersFromUserID(
e1c16d ¤   PGPRecipientsList¤  *recipients,
630fd1 ¤   const char¤ ¤   ¤   *userID,
015ab1 ¤   PGPBoolean¤ ¤   ¤   matchBestSecretKey,
f93d93 ¤   PGPUInt32¤  ¤   ¤   *numFoundUsers,
85e5cf ¤   PGPRecipientUser¤   ***foundUsers)
ebbb36 {
797d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
69576f ¤   PGPRecipientKey¤¤   *curKey;
12734a ¤   PGPRecipientKey¤¤   *bestSecretKey;
1ea522 ¤   PGPRecipientUser¤   *curUser;
c810c4 ¤   PGPUInt32¤  ¤   ¤   markValue;
0367c5 ¤
6be00f ¤   *numFoundUsers ¤= 0;
fdd046 ¤   *foundUsers¤¤   = NULL;
c7af4f ¤   bestSecretKey¤  = NULL;
--8077 00052eefd6e40100296 Page 14 of pgpRecipientDialogCommon.cpp
3a8ef6 ¤   markValue¤  ¤   = GetNextMarkValue();
4467c5 ¤
24beeb ¤   /* Tabulate and mark matches first */
c4c575 ¤   curKey = recipients->keys;
84ef78 ¤   while( IsntNull( curKey ) )
f1c7a1 ¤   {
c06364 ¤   ¤   PGPRecipientUser¤   *foundUser = NULL;
11af5a
9d791a ¤   ¤   curUser = curKey->users;
667ebc ¤   ¤   while( IsntNull( curUser ) )
3c5b34 ¤   ¤   {
fe53d7 ¤   ¤   ¤   if( UserIsVisible( curUser ) &&·
aae0e6 ¤   ¤   ¤   ¤   IsntNull( FindSubstring( PGPGetRecipientUserNamePtr( curUser ),
10fcba ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   userID ) ) )
92f776 ¤   ¤   ¤   {
3e7ca2 ¤   ¤   ¤   ¤   if( curUser->userInfo.isPrimaryUser)
1672c3 ¤   ¤   ¤   ¤   {
23bd7e ¤   ¤   ¤   ¤   ¤   foundUser = curUser;
e314c3 ¤   ¤   ¤   ¤   ¤   break;
442613 ¤   ¤   ¤   ¤   }
4ece47 ¤   ¤   ¤   ¤   else if( IsNull( foundUser ) )
5772c3 ¤   ¤   ¤   ¤   {
70bd7e ¤   ¤   ¤   ¤   ¤   foundUser = curUser;
f32613 ¤   ¤   ¤   ¤   }
13a3a6 ¤   ¤   ¤   }
2c1b52 ¤   ¤
2009b3 ¤   ¤   ¤   curUser = curUser->nextUser;
670fe4 ¤   ¤   }
5f1b52 ¤   ¤
6b4a6e ¤   ¤   if( IsntNull( foundUser ) )
dc5b34 ¤   ¤   {
9181fb ¤   ¤   ¤   if( curKey->isSecretKey && matchBestSecretKey )
d8f776 ¤   ¤   ¤   {
807bf0 ¤   ¤   ¤   ¤   // The best secret key is (1) the default key or
2acc23 ¤   ¤   ¤   ¤   // (2) a DH/DSA key instead of anything else
a82b85 ¤   ¤   ¤   ¤
c6c6f5 ¤   ¤   ¤   ¤   if( IsNull( bestSecretKey ) )
2472c3 ¤   ¤   ¤   ¤   {
0d4947 ¤   ¤   ¤   ¤   ¤   bestSecretKey = curKey;
882613 ¤   ¤   ¤   ¤   }
95fa07 ¤   ¤   ¤   ¤   else
766e50 ¤   ¤   ¤   ¤   {¤
a844d6 ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ switchBestKey = FALSE;
c4ae30 ¤   ¤   ¤   ¤   ¤
5a74d7 ¤   ¤   ¤   ¤   ¤   if( curKey->isDefaultKey )
af4859 ¤   ¤   ¤   ¤   ¤   {
4cab76 ¤   ¤   ¤   ¤   ¤   ¤   pgpAssert( ! bestSecretKey->isDefaultKey );
f494aa ¤   ¤   ¤   ¤   ¤   ¤
aa5b12 ¤   ¤   ¤   ¤   ¤   ¤   switchBestKey = TRUE;
131c89 ¤   ¤   ¤   ¤   ¤   }
a7c2ff ¤   ¤   ¤   ¤   ¤   else if( curKey->algorithm ==
0f2697 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPPublicKeyAlgorithm_DSA &&
2ec37b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·bestSecretKey->algorithm !=
35ddca ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·¤  ¤   kPGPPublicKeyAlgorithm_DSA )
e74859 ¤   ¤   ¤   ¤   ¤   {
9c5b12 ¤   ¤   ¤   ¤   ¤   ¤   switchBestKey = TRUE;
f01c89 ¤   ¤   ¤   ¤   ¤   }
58ae30 ¤   ¤   ¤   ¤   ¤
43f5d5 ¤   ¤   ¤   ¤   ¤   if( switchBestKey )
d34859 ¤   ¤   ¤   ¤   ¤   {
03b6f4 ¤   ¤   ¤   ¤   ¤   ¤   bestSecretKey->markValue ¤  = 0;
f7631b ¤   ¤   ¤   ¤   ¤   ¤   *numFoundUsers ¤¤   ¤   ¤   -= 1;
f794aa ¤   ¤   ¤   ¤   ¤   ¤
4e5117 ¤   ¤   ¤   ¤   ¤   ¤   bestSecretKey = curKey;
8b1c89 ¤   ¤   ¤   ¤   ¤   }
b84bd6 ¤   ¤   ¤   ¤   ¤   else
074859 ¤   ¤   ¤   ¤   ¤   {
3a2dbd ¤   ¤   ¤   ¤   ¤   ¤   // bestSecretKey is a better match. Skip this one.
0e64a2 ¤   ¤   ¤   ¤   ¤   ¤   foundUser = NULL;
3b1c89 ¤   ¤   ¤   ¤   ¤   }
a52613 ¤   ¤   ¤   ¤   }
52a3a6 ¤   ¤   ¤   }
--3bce 00034d0fd3d40100296 Page 15 of pgpRecipientDialogCommon.cpp
b50fe4 ¤   ¤   }
3b1b52 ¤   ¤
c34a6e ¤   ¤   if( IsntNull( foundUser ) )
075b34 ¤   ¤   {
ddb127 ¤   ¤   ¤   foundUser->markValue¤   = markValue;
e27318 ¤   ¤   ¤   curKey->markValue ¤ ¤   = markValue;
4d1b52 ¤   ¤
ac0df3 ¤   ¤   ¤   *numFoundUsers += 1;
f50fe4 ¤   ¤   }
a21b52 ¤   ¤
91cf46 ¤   ¤   curKey = curKey->nextKey;
ca9371 ¤   }
8eaf5a
933d92 ¤   curUser = recipients->groups;
1943d4 ¤   while( IsntNull( curUser ) )
6cc7a1 ¤   {
11e885 ¤   ¤   if( UserIsVisible( curUser ) )
a75b34 ¤   ¤   {
826d81 ¤   ¤   ¤   char¤   groupUserID[256];
ee87c7 ¤   ¤   ¤
61a4ce ¤   ¤   ¤   /* Surround the group name with "<>" to simulate an email address */
1587c7 ¤   ¤   ¤
61c356 ¤   ¤   ¤   strcpy( groupUserID, "<" );
b28586 ¤   ¤   ¤   strcat( groupUserID, PGPGetRecipientUserNamePtr( curUser ) );
a7dc92 ¤   ¤   ¤   strcat( groupUserID, ">" );
3d87c7 ¤   ¤   ¤
3b2c1e ¤   ¤   ¤   if( IsntNull( FindSubstring( groupUserID, userID ) ) )
26f776 ¤   ¤   ¤   {
531251 ¤   ¤   ¤   ¤   curUser->markValue = markValue;
cd309b ¤   ¤   ¤   ¤   *numFoundUsers += 1;
445a2a ¤   ¤   ¤   }¤
bb0fe4 ¤   ¤   }
fd67c5 ¤
ec0c5e ¤   ¤   curUser = curUser->nextUser;
e79371 ¤   }
1967c5 ¤
5ec44f ¤   *foundUsers = (PGPRecipientUser **) PGPNewData( recipients->memoryMgr,
91e02c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *numFoundUsers * sizeof( **foundUsers ),
671e0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
5ea603 ¤   if( IsntNull( *foundUsers ) )
ddc7a1 ¤   {
e9592a ¤   ¤   PGPUInt32¤  userIndex = 0;
a01b52 ¤   ¤
67490a ¤   ¤   curKey = recipients->keys;
ac6484 ¤   ¤   while( IsntNull( curKey ) )
a15b34 ¤   ¤   {
c2fc96 ¤   ¤   ¤   if( curKey->markValue == markValue )
2ef776 ¤   ¤   ¤   {
604f7a ¤   ¤   ¤   ¤   PGPRecipientUser¤   *curUser;
38af5a
01419f ¤   ¤   ¤   ¤   curUser = curKey->users;
5f7de9 ¤   ¤   ¤   ¤   while( IsntNull( curUser ) )
6872c3 ¤   ¤   ¤   ¤   {
ac0fcc ¤   ¤   ¤   ¤   ¤   if( curUser->markValue == markValue )
254859 ¤   ¤   ¤   ¤   ¤   {
7f52a1 ¤   ¤   ¤   ¤   ¤   ¤   (*foundUsers)[userIndex] = curUser;
2ad1fc ¤   ¤   ¤   ¤   ¤   ¤   ++userIndex;
191c89 ¤   ¤   ¤   ¤   ¤   }
632b85 ¤   ¤   ¤   ¤
845d96 ¤   ¤   ¤   ¤   ¤   curUser = curUser->nextUser;
ec2613 ¤   ¤   ¤   ¤   }
41a3a6 ¤   ¤   ¤   }
db87c7 ¤   ¤   ¤
b12035 ¤   ¤   ¤   curKey = curKey->nextKey;
3e0fe4 ¤   ¤   }
70af5a
01d2e1 ¤   ¤   curUser = recipients->groups;
007ebc ¤   ¤   while( IsntNull( curUser ) )
b05b34 ¤   ¤   {
89a2ba ¤   ¤   ¤   if( curUser->markValue == markValue )
82f776 ¤   ¤   ¤   {
34885a ¤   ¤   ¤   ¤   (*foundUsers)[userIndex] = curUser;
--14e8 0008425ca8440100296 Page 16 of pgpRecipientDialogCommon.cpp
ca57c2 ¤   ¤   ¤   ¤   ++userIndex;
1da3a6 ¤   ¤   ¤   }
cf1b52 ¤   ¤
ed09b3 ¤   ¤   ¤   curUser = curUser->nextUser;
150fe4 ¤   ¤   }
349371 ¤   }
e70e24 ¤   else
27c7a1 ¤   {
53bce1 ¤   ¤   err = kPGPError_OutOfMemory;
aa9371 ¤   }
6d67c5 ¤
c1deb7 ¤   return( err );
69efe6 }
2eaf5a
8366dd ¤   static PGPError
6fc783 FindUserFromKeyID(
55f2fb ¤   PGPRecipientsList¤  ¤   *recipients,
8d4632 ¤   const PGPKeyID¤ ¤   ¤   *searchKeyID,
5e8ef0 ¤   PGPPublicKeyAlgorithm¤  searchAlgorithm,
2f013c ¤   PGPRecipientUser¤   ¤   **foundUser)
9dbb36 {
d27d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
5d576f ¤   PGPRecipientKey¤¤   *curKey;
8667c5 ¤
55a338 ¤   *foundUser = NULL;
7667c5 ¤
dbc575 ¤   curKey = recipients->keys;
080a69 ¤   while( IsntNull( curKey ) && IsntPGPError( err ) )
e8c7a1 ¤   {
c7ad57 ¤   ¤   PGPKeyID¤   keyID;
011b52 ¤   ¤
4ec7c1 ¤   ¤   err = PGPGetKeyIDFromKey( curKey->keyRef, &keyID );
cd144f ¤   ¤   if( IsntPGPError( err ) &&
36b482 ¤   ¤   ¤   PGPCompareKeyIDs( &keyID, searchKeyID ) == 0 &&
c16b24 ¤   ¤   ¤   curKey->algorithm == searchAlgorithm )
525b34 ¤   ¤   {
f94939 ¤   ¤   ¤   if( UserIsVisible( curKey->primaryUser ) )
41f776 ¤   ¤   ¤   {
60520f ¤   ¤   ¤   ¤   *foundUser = curKey->primaryUser;
07a3a6 ¤   ¤   ¤   }
9287c7 ¤   ¤   ¤
becdcb ¤   ¤   ¤   break;
4f0fe4 ¤   ¤   }
531b52 ¤   ¤
45cf46 ¤   ¤   curKey = curKey->nextKey;
899371 ¤   }
d467c5 ¤
f3deb7 ¤   return( err );
42efe6 }
59af5a
578f77 /* Must use PGPFreeData to dispose of foundGroups */
21af5a
6b66dd ¤   static PGPError
5803c6 FindGroupsFromUserID(
8ec16d ¤   PGPRecipientsList¤  *recipients,
bd0fd1 ¤   const char¤ ¤   ¤   *userID,
1c446f ¤   PGPUInt32¤  ¤   ¤   *numFoundGroups,
2f9b5b ¤   PGPRecipientUser¤   ***foundGroups)
a1bb36 {
b17d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
e6a522 ¤   PGPRecipientUser¤   *curUser;
2c10c4 ¤   PGPUInt32¤  ¤   ¤   markValue;
4367c5 ¤
ea3f07 ¤   *numFoundGroups = 0;
271f75 ¤   *foundGroups¤   = NULL;
ff8ef6 ¤   markValue¤  ¤   = GetNextMarkValue();
3167c5 ¤
46beeb ¤   /* Tabulate and mark matches first */
163d92 ¤   curUser = recipients->groups;
cd43d4 ¤   while( IsntNull( curUser ) )
24c7a1 ¤   {
84bc43 ¤   ¤   if( UserIsVisible( curUser ) &&
--e4d8 0005164fbec40100296 Page 17 of pgpRecipientDialogCommon.cpp
01b5b6 ¤   ¤   ¤   IsntNull( FindSubstring( PGPGetRecipientUserNamePtr( curUser ),
c9fa02 ¤   ¤   ¤   ¤   ¤   ¤   ¤   userID ) ) )
155b34 ¤   ¤   {
3326ef ¤   ¤   ¤   curUser->markValue ¤= markValue;
ec3caa ¤   ¤   ¤   *numFoundGroups ¤   += 1;
ee0fe4 ¤   ¤   }
2067c5 ¤
ff0c5e ¤   ¤   curUser = curUser->nextUser;
c59371 ¤   }
3467c5 ¤
7c6c75 ¤   *foundGroups = (PGPRecipientUser **) PGPNewData( recipients->memoryMgr,
38eb21 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *numFoundGroups * sizeof( **foundGroups ),
901e0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
60ca29 ¤   if( IsntNull( *foundGroups ) )
1ac7a1 ¤   {
24592a ¤   ¤   PGPUInt32¤  userIndex = 0;
feaf5a
4dd2e1 ¤   ¤   curUser = recipients->groups;
977ebc ¤   ¤   while( IsntNull( curUser ) )
385b34 ¤   ¤   {
afa2ba ¤   ¤   ¤   if( curUser->markValue == markValue )
4ff776 ¤   ¤   ¤   {
288f7d ¤   ¤   ¤   ¤   (*foundGroups)[userIndex] = curUser;
7d57c2 ¤   ¤   ¤   ¤   ++userIndex;
22a3a6 ¤   ¤   ¤   }
191b52 ¤   ¤
5309b3 ¤   ¤   ¤   curUser = curUser->nextUser;
570fe4 ¤   ¤   }
1e9371 ¤   }
0f0e24 ¤   else
bac7a1 ¤   {
f3bce1 ¤   ¤   err = kPGPError_OutOfMemory;
9c9371 ¤   }
b667c5 ¤
efdeb7 ¤   return( err );
00efe6 }
efaf5a
4266dd ¤   static PGPError
c93cd5 AddMissingRecipient(
6ff2fb ¤   PGPRecipientsList¤  ¤   *recipients,
263e82 ¤   const PGPRecipientSpec¤ *spec)¤ // Assumed client allocated
c6bb36 {
45ddde ¤   PGPRecipientUser¤   *user;
738f52 ¤   PGPError¤   ¤   ¤   err;
ac67c5 ¤
547f6e ¤   err = NewUser( recipients, &user );
44b1f0 ¤   if( IsntPGPError( err ) )
98c7a1 ¤   {
731090 ¤   ¤   char¤   userIDString[256];
451b52 ¤   ¤
f5cc8c ¤   ¤   user->kind ¤¤   ¤   ¤   = kPGPRecipientUserKind_MissingRecipient;
e29b88 ¤   ¤   user->location ¤¤   ¤   = kPGPRecipientUserLocation_RecipientList;
6b8de9 ¤   ¤   user->missingUser.type ¤= spec->type;
b31b52 ¤   ¤
aea665 ¤   ¤   if( spec->locked )
1f5d0c ¤   ¤   ¤   ++user->lockRefCount;
c71b52 ¤   ¤
e068a8 ¤   ¤   switch( spec->type )
785b34 ¤   ¤   {
6ec72d ¤   ¤   ¤   case kPGPRecipientSpecType_UserID:
9e8624 ¤   ¤   ¤   ¤   strcpy( userIDString, spec->u.userIDStr );
27f622 ¤   ¤   ¤   ¤   break;
cf87c7 ¤   ¤   ¤
9dabc6 ¤   ¤   ¤   case kPGPRecipientSpecType_KeyID:
028bcd ¤   ¤   ¤   ¤   user->missingUser.keyID¤¤   = &spec->u.id.keyID;
b4f38d ¤   ¤   ¤   ¤   user->missingUser.algorithm¤= spec->u.id.algorithm;
542b85 ¤   ¤   ¤   ¤
2c9e05 ¤   ¤   ¤   ¤   err = pgpGetMissingRecipientKeyIDStringPlatform(
73015a ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->context, &spec->u.id.keyID,
c92391 ¤   ¤   ¤   ¤   ¤   ¤   ¤   userIDString );
92f622 ¤   ¤   ¤   ¤   break;
5187c7 ¤   ¤   ¤
--e564 000cf22806340100296 Page 18 of pgpRecipientDialogCommon.cpp
05db68 ¤   ¤   ¤   default:
0d9d31 ¤   ¤   ¤   ¤   pgpDebugMsg( "Unknown recipient type" );
0ef622 ¤   ¤   ¤   ¤   break;
dc0fe4 ¤   ¤   }
60af5a
0686f8 ¤   ¤   if( IsntPGPError( err ) )
7c5b34 ¤   ¤   {
9b864f ¤   ¤   ¤   err = RememberName( recipients, userIDString, &user->nameOffset );
50698b ¤   ¤   ¤   if( IsntPGPError( err ) )
07f776 ¤   ¤   ¤   {
a8efb5 ¤   ¤   ¤   ¤   user->nextUser = recipients->missingRecipients;
ca94a5 ¤   ¤   ¤   ¤   recipients->missingRecipients = user;
6aa3a6 ¤   ¤   ¤   }
770fe4 ¤   ¤   }
cc9371 ¤   }
9067c5 ¤
4f5662 ¤   // Don't need to free user upon error because it is in a larger,
9842b0 ¤   // allocated block which is freed as a single item
c167c5 ¤
5fdeb7 ¤   return( err );
cdefe6 }
76af5a
5366dd ¤   static PGPError
e84eda MoveDefaultRecipients(
cbf2fb ¤   PGPRecipientsList¤  ¤   *recipients,
2b14e4 ¤   PGPUInt32¤  ¤   ¤   ¤   numDefaultRecipients,
c83c16 ¤   const PGPRecipientSpec¤ defaultRecipients[],
0d3b85 ¤   PGPBoolean¤ ¤   ¤   ¤   *movedARRs)
40bb36 {
188e12 ¤   PGPError¤   err = kPGPError_NoErr;
d162cb ¤   PGPUInt32¤  recipientIndex;
9267c5 ¤
2d5113 ¤   *movedARRs = FALSE;
a367c5 ¤
1615bc ¤   for( recipientIndex = 0; recipientIndex < numDefaultRecipients;
de1a41 ¤   ¤   ¤   ¤   recipientIndex++ )
95c7a1 ¤   {
7f1401 ¤   ¤   const PGPRecipientSpec¤ *curRecipient;
8092e7 ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   movedAnARR = FALSE;
ad1b52 ¤   ¤
b8baaf ¤   ¤   curRecipient = &defaultRecipients[recipientIndex];
001b52 ¤   ¤
548e8d ¤   ¤   switch( curRecipient->type )
575b34 ¤   ¤   {
78f6c5 ¤   ¤   ¤   case kPGPRecipientSpecType_Key:
5eabc6 ¤   ¤   ¤   case kPGPRecipientSpecType_KeyID:
f7f776 ¤   ¤   ¤   {
9d5de4 ¤   ¤   ¤   ¤   PGPKeyRef¤  ¤   theKey = kInvalidPGPKeyRef;
362b85 ¤   ¤   ¤   ¤
c40597 ¤   ¤   ¤   ¤   if( curRecipient->type == kPGPRecipientSpecType_Key )
4c72c3 ¤   ¤   ¤   ¤   {
4aa0b2 ¤   ¤   ¤   ¤   ¤   theKey = curRecipient->u.key;
a62613 ¤   ¤   ¤   ¤   }
79fa07 ¤   ¤   ¤   ¤   else
c872c3 ¤   ¤   ¤   ¤   {
908c83 ¤   ¤   ¤   ¤   ¤   (void) PGPGetKeyByKeyID( recipients->keySet,
2646dc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &curRecipient->u.id.keyID,
60c007 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curRecipient->u.id.algorithm, &theKey );
f92613 ¤   ¤   ¤   ¤   }
f02b85 ¤   ¤   ¤   ¤
f46699 ¤   ¤   ¤   ¤   if( PGPKeyRefIsValid( theKey ) )
3872c3 ¤   ¤   ¤   ¤   {
2a4bbf ¤   ¤   ¤   ¤   ¤   PGPRecipientKey¤*key;
b9af5a
4a1cc8 ¤   ¤   ¤   ¤   ¤   key = FindKeyFromKeyRef( recipients, theKey );
80d503 ¤   ¤   ¤   ¤   ¤   if( IsntNull( key ) && key->isVisible &&
9139cd ¤   ¤   ¤   ¤   ¤   ¤   IsntNull( key->primaryUser ) )
6d4859 ¤   ¤   ¤   ¤   ¤   {
c5aa6a ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  numMovedUsers;
4394aa ¤   ¤   ¤   ¤   ¤   ¤
afee8c ¤   ¤   ¤   ¤   ¤   ¤   err = PGPMoveRecipients( recipients,
cfe634 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList,
--a7b7 0002918672540100296 Page 19 of pgpRecipientDialogCommon.cpp
a7b2c2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   1, &key->primaryUser, &numMovedUsers,
b7e601 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &movedAnARR );
7494aa ¤   ¤   ¤   ¤   ¤   ¤
a0cfca ¤   ¤   ¤   ¤   ¤   ¤   if( curRecipient->locked )
67ea69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++key->primaryUser->lockRefCount;
6d1c89 ¤   ¤   ¤   ¤   ¤   }
112613 ¤   ¤   ¤   ¤   }
33fa07 ¤   ¤   ¤   ¤   else
af72c3 ¤   ¤   ¤   ¤   {
7cd3ca ¤   ¤   ¤   ¤   ¤   err = AddMissingRecipient( recipients, curRecipient );
362613 ¤   ¤   ¤   ¤   }
042b85 ¤   ¤   ¤   ¤
89f622 ¤   ¤   ¤   ¤   break;
04a3a6 ¤   ¤   ¤   }
5387c7 ¤   ¤   ¤
d1c72d ¤   ¤   ¤   case kPGPRecipientSpecType_UserID:
b2f776 ¤   ¤   ¤   {
784dcb ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   numMovedUsers = 0;
4eb7d9 ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   numMatchedUsers;
b6a40b ¤   ¤   ¤   ¤   PGPRecipientUser¤   **matchedUserList;
d82b85 ¤   ¤   ¤   ¤
8111da ¤   ¤   ¤   ¤   err = FindUsersFromUserID( recipients,
e88ee8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   curRecipient->u.userIDStr, TRUE, &numMatchedUsers,
7f743d ¤   ¤   ¤   ¤   ¤   ¤   ¤   &matchedUserList );
485565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
7372c3 ¤   ¤   ¤   ¤   {
592080 ¤   ¤   ¤   ¤   ¤   if( numMatchedUsers != 0 )
554859 ¤   ¤   ¤   ¤   ¤   {
29aa6a ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  numMovedUsers;
f794aa ¤   ¤   ¤   ¤   ¤   ¤
baee8c ¤   ¤   ¤   ¤   ¤   ¤   err = PGPMoveRecipients( recipients,
5e7bee ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList,
b59f93 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   numMatchedUsers, matchedUserList,
5d9d4c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &numMovedUsers, &movedAnARR );
1eae30 ¤   ¤   ¤   ¤   ¤
67e0da ¤   ¤   ¤   ¤   ¤   ¤   if( numMatchedUsers == 1 )
898fec ¤   ¤   ¤   ¤   ¤   ¤   {
52deed ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( curRecipient->locked )
203ae1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++matchedUserList[0]->lockRefCount;
abdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
6b7f8b ¤   ¤   ¤   ¤   ¤   ¤   else
4b8fec ¤   ¤   ¤   ¤   ¤   ¤   {
60396f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  userIndex;
13531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
51ab6a ¤   ¤   ¤   ¤   ¤   ¤   ¤   for( userIndex = 0; userIndex < numMatchedUsers;
2f7d15 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++userIndex )
5b06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
a1b5e0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   matchedUserList[userIndex]->multipleMatch =
0a56b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   TRUE;
865268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
29db3c ¤   ¤   ¤   ¤   ¤   ¤   }
6e1c89 ¤   ¤   ¤   ¤   ¤   }
894bd6 ¤   ¤   ¤   ¤   ¤   else
3f4859 ¤   ¤   ¤   ¤   ¤   {
4d3eed ¤   ¤   ¤   ¤   ¤   ¤   err = AddMissingRecipient( recipients, curRecipient );
241c89 ¤   ¤   ¤   ¤   ¤   }
74ae30 ¤   ¤   ¤   ¤   ¤
7839f9 ¤   ¤   ¤   ¤   ¤   PGPFreeData( matchedUserList );
6c2613 ¤   ¤   ¤   ¤   }
e22b85 ¤   ¤   ¤   ¤
1bf622 ¤   ¤   ¤   ¤   break;
3ea3a6 ¤   ¤   ¤   }
b787c7 ¤   ¤   ¤
b1db68 ¤   ¤   ¤   default:
85744e ¤   ¤   ¤   ¤   pgpDebugMsg(
086ed6 ¤   ¤   ¤   ¤   ¤   "MoveDefaultRecipients(): Unknown PGPRecipientSpecType" );
79566c ¤   ¤   ¤   ¤   err = kPGPError_BadParams;
6cf622 ¤   ¤   ¤   ¤   break;
540fe4 ¤   ¤   }
9a1b52 ¤   ¤
c4d223 ¤   ¤   if( IsPGPError( err ) )
29cdcb ¤   ¤   ¤   break;
--5f2f 0005dc8fa0340100296 Page 20 of pgpRecipientDialogCommon.cpp
e587c7 ¤   ¤   ¤
fce5ac ¤   ¤   if( movedAnARR )
00b89a ¤   ¤   ¤   *movedARRs = TRUE;
4f9371 ¤   }
1daf5a
5ddeb7 ¤   return( err );
fdefe6 }
4767c5 ¤
1cd2ab ¤   const char *
240944 PGPGetRecipientUserNamePtr(
53db56 ¤   const PGPRecipientUser *user)
acbb36 {
761188 ¤   pgpAssert( IsntNull( user ) );
6f67c5 ¤
f41e38 ¤   return( &user->recipients->nameList[user->nameOffset] );
03efe6 }
41af5a
086d52 ¤   void
f1ef3b PGPGetRecipientUserName(
88d6e2 ¤   const PGPRecipientUser ¤*user,
07aca4 ¤   char¤   ¤   ¤   ¤   ¤   name[256])
9fbb36 {
5b1188 ¤   pgpAssert( IsntNull( user ) );
98e599 ¤   pgpAssert( IsntNull( name ) );
f967c5 ¤
b6d7d3 ¤   strcpy( name, PGPGetRecipientUserNamePtr( user ) );
67efe6 }
d1af5a
fdc744 ¤   PGPError
8c1e2d PGPBuildRecipientsList(
d100db ¤   void *¤ ¤   ¤   ¤   ¤   ¤   ¤   hwndParent,
da284d ¤   PGPContextRef¤  ¤   ¤   ¤   ¤   context,
a339d1 ¤   PGPKeySetRef¤   ¤   ¤   ¤   ¤   allKeys,
e72140 ¤   PGPGroupSetRef¤ ¤   ¤   ¤   ¤   groupSet,
546e73 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   numDefaultRecipients,
ac6f48 ¤   const PGPRecipientSpec¤ ¤   ¤   *defaultRecipients,
3a65f6 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   serverCount,
1e86c1 ¤   const PGPKeyServerSpec¤ ¤   ¤   *serverList,
fea3e7 ¤   PGPtlsContextRef¤   ¤   ¤   ¤   tlsContext,
34d169 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   syncUnknownKeys,
36b62c ¤   PGPAdditionalRecipientRequestEnforcement¤   arrEnforcement,
b1229a ¤   PGPRecipientEventHandlerProcPtr¤eventHandler,
f2ee98 ¤   PGPUserValue¤   ¤   ¤   ¤   ¤   eventUserValue,
08cd6b ¤   PGPRecipientsList¤  ¤   ¤   ¤   *recipients,
0e34fd ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   *haveDefaultARRs)
f5bb36 {
9e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
6867c5 ¤
a8a76d ¤   pgpAssert( PGPContextRefIsValid( context ) );
13076a ¤   pgpAssert( PGPKeySetRefIsValid( allKeys ) );
63d4ef ¤   pgpAssert( IsntNull( recipients ) );
ffaf5a
27fa04 ¤   pgpClearMemory( recipients, sizeof( *recipients ) );
aaaf5a
8f5feb ¤   recipients->context¤¤   ¤   = context;
4a2690 ¤   recipients->memoryMgr¤  ¤   = PGPGetContextMemoryMgr( context );
85c01a ¤   recipients->arrEnforcement¤ = arrEnforcement;
84052a ¤   recipients->eventHandler¤   = eventHandler;
ae3d3a ¤   recipients->eventUserValue¤ = eventUserValue;
ec7aaa ¤   recipients->serverList¤ ¤   = serverList;
3945b9 ¤   recipients->serverCount¤¤   = serverCount;
8a0507 ¤   recipients->tlsContext¤ ¤   = tlsContext;
e267c5 ¤
eb7be2 ¤   *haveDefaultARRs = FALSE;
1b67c5 ¤
b8f9bd ¤   err = AddKeySet( recipients, allKeys );
881ecb ¤   if( IsntPGPError( err ) && PGPGroupSetRefIsValid( groupSet ) )
23c7a1 ¤   {
8f3875 ¤   ¤   err = AddGroupSet( context, recipients, groupSet );
fb9371 ¤   }
6567c5 ¤
5db1f0 ¤   if( IsntPGPError( err ) )
--1495 000ecf4cd1e40100296 Page 21 of pgpRecipientDialogCommon.cpp
f7c7a1 ¤   {
1b9319 ¤   ¤   err = UpdateDynamicRecipientValues( recipients );
959371 ¤   }
e2af5a
3ae463 ¤   if( IsntPGPError( err ) && numDefaultRecipients != 0 )
22c7a1 ¤   {
c8a2d9 ¤   ¤   err = MoveDefaultRecipients( recipients, numDefaultRecipients,
924c61 ¤   ¤   ¤   ¤   ¤   ¤   defaultRecipients, haveDefaultARRs );
979371 ¤   }
64af5a
aee9a3 ¤   if( IsntPGPError( err ) && syncUnknownKeys )
c1c7a1 ¤   {
804ed2 ¤   ¤   PGPBoolean¤ haveNewKeys;
091b52 ¤   ¤
599116 ¤   ¤   err = PGPUpdateMissingRecipients( hwndParent, recipients,
6a495c ¤   ¤   ¤   ¤   ¤   &haveNewKeys );
e19371 ¤   }
f1af5a
c5deb7 ¤   return( err );
cbefe6 }
5baf5a
846d52 ¤   void
14074e PGPDisposeRecipientsList(PGPRecipientsList *recipients)
b0bb36 {
573d4b ¤   PGPRecipientKeyList¤¤   *curKeyList;
48f891 ¤   PGPRecipientUserList¤   *curUserList;
a765df ¤   PGPRecipientKey¤¤   ¤   *curKey;
1867c5 ¤
1fd4ef ¤   pgpAssert( IsntNull( recipients ) );
c38531 ¤   pgpAssert( PGPContextRefIsValid( recipients->context ) );
83c489 ¤   pgpAssert( PGPMemoryMgrRefIsValid( recipients->memoryMgr ) );
7167c5 ¤
7bc575 ¤   curKey = recipients->keys;
23ef78 ¤   while( IsntNull( curKey ) )
e9c7a1 ¤   {
406087 ¤   ¤   FreeKey( curKey );
cb1b52 ¤   ¤
6ccf46 ¤   ¤   curKey = curKey->nextKey;
919371 ¤   }
a967c5 ¤
d9bfdb ¤   curKeyList = recipients->keyLists;
d46523 ¤   while( IsntNull( curKeyList ) )
cac7a1 ¤   {
c54e5d ¤   ¤   PGPRecipientKeyList¤*nextKeyList;
5567c5 ¤
fd0f45 ¤   ¤   nextKeyList = curKeyList->nextKeyList;
b973c5 ¤   ¤   ¤   PGPFreeData( curKeyList );
d9931e ¤   ¤   curKeyList = nextKeyList;
ff9371 ¤   }
e5af5a
7ff9a1 ¤   curUserList = recipients->userLists;
c3fa5e ¤   while( IsntNull( curUserList ) )
28c7a1 ¤   {
326982 ¤   ¤   PGPRecipientUserList¤   *nextUserList;
0d67c5 ¤
60e0f9 ¤   ¤   nextUserList = curUserList->nextUserList;
4b2544 ¤   ¤   ¤   PGPFreeData( curUserList );
6fb71d ¤   ¤   curUserList = nextUserList;
ed9371 ¤   }
b067c5 ¤
2f1279 ¤   if( IsntNull( recipients->nameList ) )
350993 ¤   ¤   PGPFreeData( recipients->nameList );
1967c5 ¤
cf0ac0 ¤   if( PGPGroupSetRefIsValid( recipients->groupSet ) )
5ed640 ¤   ¤   PGPFreeGroupSet( recipients->groupSet );
661b52 ¤   ¤
5cfa04 ¤   pgpClearMemory( recipients, sizeof( *recipients ) );
b7efe6 }
24af5a
af66dd ¤   static PGPError
77e250 SendUserEvent(
ecf2fb ¤   PGPRecipientsList¤  ¤   *recipients,
--835d 000edaf4a6240100296 Page 22 of pgpRecipientDialogCommon.cpp
24b881 ¤   PGPRecipientEventType¤  eventType,
a5951b ¤   PGPRecipientUser¤   ¤   *user)
86bb36 {
7e8e12 ¤   PGPError¤   err = kPGPError_NoErr;
0167c5 ¤
aa2b9d ¤   if( IsntNull( recipients->eventHandler ) )
c0c7a1 ¤   {
b813fe ¤   ¤   PGPRecipientEvent¤  event;
0d1b52 ¤   ¤
2c500b ¤   ¤   pgpClearMemory( &event, sizeof( event ) );
a61b52 ¤   ¤
499962 ¤   ¤   event.type ·= eventType;
342e8a ¤   ¤   event.user ¤= user;
4b67c5 ¤
7ce662 ¤   ¤   err = (*recipients->eventHandler)( recipients, &event,
3c3da2 ¤   ¤   ¤   ¤   ¤   ¤   recipients->eventUserValue );·
6b9371 ¤   }
f9af5a
ebdeb7 ¤   return( err );
1eefe6 }
abaf5a
9c6c2c ¤   static PGPBoolean
ae7137 MarkKeyARRsForUserToRecipientMove(
12c16d ¤   PGPRecipientsList¤  *recipients,
baaef0 ¤   PGPRecipientKey¤¤   *key,
ccc85d ¤   PGPUInt32¤  ¤   ¤   markValue,
afb9b4 ¤   PGPBoolean¤ ¤   ¤   *markedARRs,
cdf8a2 ¤   PGPBoolean¤ ¤   ¤   *missingARRs)
b0bb36 {
663f00 ¤   PGPBoolean¤ ¤   moveUser;
dc67c5 ¤
86b2e6 ¤   pgpAssert( recipients->arrEnforcement != kPGPARREnforcement_None );
f4af5a
399860 ¤   moveUser ¤  ¤   = TRUE;
19601a ¤   *missingARRs ¤  = FALSE;
2683c6 ¤   *markedARRs¤¤   = FALSE;
db67c5 ¤
502623 ¤   if( key->numARRKeys != 0 )
8dc7a1 ¤   {
79e8e9 ¤   ¤   PGPBoolean¤ markARRs = TRUE;
ea1b52 ¤   ¤
3e2cc1 ¤   ¤   if( key->haveMissingARRs )
805b34 ¤   ¤   {
03a1ae ¤   ¤   ¤   *missingARRs = TRUE;
0487c7 ¤   ¤   ¤
657aad ¤   ¤   ¤   /*
07b29d ¤   ¤   ¤   ** In the strict case, the user cannot be moved because an ARR
22c606 ¤   ¤   ¤   ** was not found. In the warn case, we move what we can.
aa3da8 ¤   ¤   ¤   */
3d87c7 ¤   ¤   ¤
df4027 ¤   ¤   ¤   if( recipients->arrEnforcement == kPGPARREnforcement_Strict )
0df776 ¤   ¤   ¤   {
263d38 ¤   ¤   ¤   ¤   moveUser = FALSE;
07609d ¤   ¤   ¤   ¤   markARRs = FALSE;
a0a3a6 ¤   ¤   ¤   }
0c0fe4 ¤   ¤   }
f21b52 ¤   ¤
455121 ¤   ¤   if( markARRs )
9f5b34 ¤   ¤   {
83be15 ¤   ¤   ¤   PGPUInt32¤  arrIndex;
6a87c7 ¤   ¤   ¤
eded1b ¤   ¤   ¤   for( arrIndex = 0; arrIndex < key->numARRKeys; arrIndex++ )
bdf776 ¤   ¤   ¤   {
627ab7 ¤   ¤   ¤   ¤   PGPRecipientKeyARRInfo¤ *arrInfo;
2e2b85 ¤   ¤   ¤   ¤
d855d7 ¤   ¤   ¤   ¤   arrInfo = &key->arrKeys[arrIndex];
08d3cb ¤   ¤   ¤   ¤   if( IsntNull( arrInfo->key ) )
9572c3 ¤   ¤   ¤   ¤   {
303d27 ¤   ¤   ¤   ¤   ¤   PGPRecipientUser¤   *user = arrInfo->key->primaryUser;
e3ae30 ¤   ¤   ¤   ¤   ¤
e946e1 ¤   ¤   ¤   ¤   ¤   pgpAssert( arrInfo->key->isVisible );
edae30 ¤   ¤   ¤   ¤   ¤
--17de 000c9c5827a40100296 Page 23 of pgpRecipientDialogCommon.cpp
86b5c6 ¤   ¤   ¤   ¤   ¤   ++user->userInfo.arrRefCount;
5bbf59 ¤   ¤   ¤   ¤   ¤   user->markValue = markValue;
59af5a
4ac651 ¤   ¤   ¤   ¤   ¤   *markedARRs = TRUE;
deae30 ¤   ¤   ¤   ¤   ¤
eb3078 ¤   ¤   ¤   ¤   ¤   if( IsMandatoryARRClass( arrInfo->arrClass ) )
354859 ¤   ¤   ¤   ¤   ¤   {
9776c8 ¤   ¤   ¤   ¤   ¤   ¤   ++user->userInfo.enforcedARRRefCount;
2994aa ¤   ¤   ¤   ¤   ¤   ¤
78d7a2 ¤   ¤   ¤   ¤   ¤   ¤   if( recipients->arrEnforcement ==
a8fd07 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPARREnforcement_Strict)
008fec ¤   ¤   ¤   ¤   ¤   ¤   {
c2f86a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++user->lockRefCount;
4ddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
d01c89 ¤   ¤   ¤   ¤   ¤   }
082613 ¤   ¤   ¤   ¤   }
cea3a6 ¤   ¤   ¤   }
720fe4 ¤   ¤   }
849371 ¤   }
f167c5 ¤
452ed6 ¤   return( moveUser );
fbefe6 }
5caf5a
8533c8 ¤   static void
ed466a MarkKeyARRsForRecipientToUserMove(
8cc16d ¤   PGPRecipientsList¤  *recipients,
36aef0 ¤   PGPRecipientKey¤¤   *key,
02b6e5 ¤   PGPUInt32¤  ¤   ¤   markValue)
d7bb36 {
687507 ¤   (void) recipients;
d5af5a
c2b2e6 ¤   pgpAssert( recipients->arrEnforcement != kPGPARREnforcement_None );
50af5a
b02623 ¤   if( key->numARRKeys != 0 )
30c7a1 ¤   {
57891d ¤   ¤   PGPUInt32¤  arrIndex;
be1b52 ¤   ¤
aba36c ¤   ¤   for( arrIndex = 0; arrIndex < key->numARRKeys; arrIndex++ )
8c5b34 ¤   ¤   {
ee3589 ¤   ¤   ¤   PGPRecipientKeyARRInfo¤ *arrInfo;
e087c7 ¤   ¤   ¤
738d65 ¤   ¤   ¤   arrInfo = &key->arrKeys[arrIndex];
3b4253 ¤   ¤   ¤   if( IsntNull( arrInfo->key ) )
cbf776 ¤   ¤   ¤   {
e4da16 ¤   ¤   ¤   ¤   PGPRecipientKey¤¤   *arrKey ¤   = arrInfo->key;
636ad7 ¤   ¤   ¤   ¤   PGPRecipientUser¤   *arrUser¤   = arrKey->primaryUser;
842b85 ¤   ¤   ¤   ¤
1b309b ¤   ¤   ¤   ¤   pgpAssert( arrKey->isVisible );
6e7a58 ¤   ¤   ¤   ¤   pgpAssert( arrUser->userInfo.arrRefCount != 0 );
752b85 ¤   ¤   ¤   ¤
5ebd84 ¤   ¤   ¤   ¤   if( IsMandatoryARRClass( arrInfo->arrClass ) )
7172c3 ¤   ¤   ¤   ¤   {
4510bc ¤   ¤   ¤   ¤   ¤   --arrUser->userInfo.enforcedARRRefCount;
a9ae30 ¤   ¤   ¤   ¤   ¤
52d4d5 ¤   ¤   ¤   ¤   ¤   if( recipients->arrEnforcement ==
9cfd07 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPARREnforcement_Strict)
b54859 ¤   ¤   ¤   ¤   ¤   {
6b82bf ¤   ¤   ¤   ¤   ¤   ¤   --arrUser->lockRefCount;
a01c89 ¤   ¤   ¤   ¤   ¤   }
e92613 ¤   ¤   ¤   ¤   }
f92b85 ¤   ¤   ¤   ¤
b4be89 ¤   ¤   ¤   ¤   --arrUser->userInfo.arrRefCount;
bebd49 ¤   ¤   ¤   ¤   if( arrUser->userInfo.arrRefCount == 0 )
5672c3 ¤   ¤   ¤   ¤   {
825bbd ¤   ¤   ¤   ¤   ¤   if( ! arrUser->movedManually )
194859 ¤   ¤   ¤   ¤   ¤   {
3a74d6 ¤   ¤   ¤   ¤   ¤   ¤   arrUser->markValue = markValue;
1b1c89 ¤   ¤   ¤   ¤   ¤   }
852613 ¤   ¤   ¤   ¤   }
16a3a6 ¤   ¤   ¤   }
310fe4 ¤   ¤   }
c99371 ¤   }
--9b39 00006c7261240100296 Page 24 of pgpRecipientDialogCommon.cpp
7aefe6 }
46af5a
ca6c2c ¤   static PGPBoolean
2d26c1 MarkGroupARRsForUserToRecipientMove(
7dc16d ¤   PGPRecipientsList¤  *recipients,
445597 ¤   PGPRecipientUser¤   *group,
58c85d ¤   PGPUInt32¤  ¤   ¤   markValue,
05b9b4 ¤   PGPBoolean¤ ¤   ¤   *markedARRs,
d6f8a2 ¤   PGPBoolean¤ ¤   ¤   *missingARRs)
f0bb36 {
12b21f ¤   PGPBoolean¤ ¤   moveGroup;
3867c5 ¤
f0b2e6 ¤   pgpAssert( recipients->arrEnforcement != kPGPARREnforcement_None );
a3c908 ¤   pgpAssert( group->kind == kPGPRecipientUserKind_Group );
75af5a
e603b5 ¤   moveGroup ¤ ¤   = TRUE;
74601a ¤   *missingARRs ¤  = FALSE;
0283c6 ¤   *markedARRs¤¤   = FALSE;
3b67c5 ¤
f8732c ¤   if( group->groupInfo.numARRKeys != 0 )
50c7a1 ¤   {
cfe8e9 ¤   ¤   PGPBoolean¤ markARRs = TRUE;
de1b52 ¤   ¤
496429 ¤   ¤   if( group->groupInfo.haveMissingARRs )
ca5b34 ¤   ¤   {
7aa1ae ¤   ¤   ¤   *missingARRs = TRUE;
c287c7 ¤   ¤   ¤
3c7aad ¤   ¤   ¤   /*
85b6cb ¤   ¤   ¤   ** In the strict case, the group cannot be moved because an ARR
d1c606 ¤   ¤   ¤   ** was not found. In the warn case, we move what we can.
b13da8 ¤   ¤   ¤   */
9787c7 ¤   ¤   ¤
164027 ¤   ¤   ¤   if( recipients->arrEnforcement == kPGPARREnforcement_Strict )
48f776 ¤   ¤   ¤   {
5ec6d3 ¤   ¤   ¤   ¤   moveGroup = FALSE;
8c609d ¤   ¤   ¤   ¤   markARRs = FALSE;
28a3a6 ¤   ¤   ¤   }
5c0fe4 ¤   ¤   }
6b1b52 ¤   ¤
275121 ¤   ¤   if( markARRs )
5d5b34 ¤   ¤   {
4f4624 ¤   ¤   ¤   PGPUInt32¤  groupItemIndex;
6687c7 ¤   ¤   ¤
d96bf5 ¤   ¤   ¤   for( groupItemIndex = 0;
bb1cdd ¤   ¤   ¤   ¤   ¤   groupItemIndex < group->groupInfo.numKeys;
433ff6 ¤   ¤   ¤   ¤   ¤   ¤   ++groupItemIndex )
b6f776 ¤   ¤   ¤   {
8d1441 ¤   ¤   ¤   ¤   PGPGroupItem¤   item;
e7497a ¤   ¤   ¤   ¤   PGPError¤   ¤   err;
ac2b85 ¤   ¤   ¤   ¤
17073a ¤   ¤   ¤   ¤   err = PGPGetIndGroupItem( recipients->groupSet,
4d190e ¤   ¤   ¤   ¤   ¤   ¤   ¤   group->groupInfo.groupID, groupItemIndex, &item );
6b55be ¤   ¤   ¤   ¤   pgpAssertNoErr( err );
805565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
5a72c3 ¤   ¤   ¤   ¤   {
1a9548 ¤   ¤   ¤   ¤   ¤   PGPRecipientKey¤*key = NULL;
92af5a
389db7 ¤   ¤   ¤   ¤   ¤   key = (PGPRecipientKey *) item.userValue;
072ff1 ¤   ¤   ¤   ¤   ¤   if( IsntNull( key ) )
b44859 ¤   ¤   ¤   ¤   ¤   {
b968e5 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ keyMissingARRs;
c794aa ¤   ¤   ¤   ¤   ¤   ¤
8c03e0 ¤   ¤   ¤   ¤   ¤   ¤   (void) MarkKeyARRsForUserToRecipientMove(
aecb85 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients,
d2ce18 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   key, markValue, markedARRs,
bf3b30 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &keyMissingARRs );
d0ed43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
72a74a ¤   ¤   ¤   ¤   ¤   ¤   if( keyMissingARRs )
a8cd0e ¤   ¤   ¤   ¤   ¤   ¤   ¤   *missingARRs = TRUE;
081c89 ¤   ¤   ¤   ¤   ¤   }
042613 ¤   ¤   ¤   ¤   }
06a3a6 ¤   ¤   ¤   }
--2009 000862f7f6540100296 Page 25 of pgpRecipientDialogCommon.cpp
b50fe4 ¤   ¤   }
6b9371 ¤   }
3c67c5 ¤
8a1fce ¤   return( moveGroup );
09efe6 }
56af5a
5033c8 ¤   static void
28119c MarkGroupARRsForRecipientToUserMove(
a0c16d ¤   PGPRecipientsList¤  *recipients,
6c5597 ¤   PGPRecipientUser¤   *group,
44b6e5 ¤   PGPUInt32¤  ¤   ¤   markValue)
adbb36 {
dcb2e6 ¤   pgpAssert( recipients->arrEnforcement != kPGPARREnforcement_None );
eac908 ¤   pgpAssert( group->kind == kPGPRecipientUserKind_Group );
40af5a
01732c ¤   if( group->groupInfo.numARRKeys != 0 )
cac7a1 ¤   {
2b8371 ¤   ¤   PGPUInt32¤  groupItemIndex;
7f1b52 ¤   ¤
028fb4 ¤   ¤   for( groupItemIndex = 0; groupItemIndex < group->groupInfo.numKeys;
5931ba ¤   ¤   ¤   ¤   ¤   ++groupItemIndex )
4a5b34 ¤   ¤   {
eafb32 ¤   ¤   ¤   PGPGroupItem¤   item;
787412 ¤   ¤   ¤   PGPError¤   ¤   err;
9587c7 ¤   ¤   ¤
ebc326 ¤   ¤   ¤   err = PGPGetIndGroupItem( recipients->groupSet,
83f429 ¤   ¤   ¤   ¤   ¤   ¤   group->groupInfo.groupID, groupItemIndex, &item );
8f144d ¤   ¤   ¤   pgpAssertNoErr( err );
13698b ¤   ¤   ¤   if( IsntPGPError( err ) )
39f776 ¤   ¤   ¤   {
25c7d5 ¤   ¤   ¤   ¤   PGPRecipientKey¤*key = NULL;
c4af5a
fc7fb7 ¤   ¤   ¤   ¤   key = (PGPRecipientKey *) item.userValue;
6a131f ¤   ¤   ¤   ¤   if( IsntNull( key ) )
5772c3 ¤   ¤   ¤   ¤   {
c08433 ¤   ¤   ¤   ¤   ¤   (void) MarkKeyARRsForRecipientToUserMove( recipients,
d02b88 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   key, markValue );
c42613 ¤   ¤   ¤   ¤   }
cba3a6 ¤   ¤   ¤   }
120fe4 ¤   ¤   }
c59371 ¤   }
acefe6 }
3faf5a
0bc744 ¤   PGPError
708eef PGPMoveRecipients(
653e64 ¤   PGPRecipientsList¤  ¤   ¤   *recipients,
170968 ¤   PGPRecipientUserLocation¤   destinationList,
756f3c ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   numUsers,
7d32d8 ¤   PGPRecipientUser¤   ¤   ¤   **userList,
fed832 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   *numMovedUsers,
6677e8 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   *movedARRs)
8ebb36 {
fc7d56 ¤   PGPError¤   ¤   ¤   err = kPGPError_NoErr;
e0c4e5 ¤   PGPUInt32¤  ¤   ¤   userIndex;
2e10c4 ¤   PGPUInt32¤  ¤   ¤   markValue;
90576f ¤   PGPRecipientKey¤¤   *curKey;
c1a522 ¤   PGPRecipientUser¤   *curUser;
0f67c5 ¤
0677a0 ¤   pgpAssert(¤ destinationList == kPGPRecipientUserLocation_UserList ||
2aceb1 ¤   ¤   ¤   ¤   destinationList == kPGPRecipientUserLocation_RecipientList );
dd2a11 ¤   pgpAssert( numUsers > 0 );
83c2d0 ¤   pgpAssert( IsntNull( userList ) );
b001aa ¤   pgpAssert( IsntNull( numMovedUsers ) );
ef67c5 ¤
27e445 ¤   *numMovedUsers ¤= 0;
812c2e ¤   *movedARRs¤ ¤   = FALSE;
9567c5 ¤
427349 ¤   markValue = GetNextMarkValue();
e2af5a
411c0e ¤   /* First pass. Mark items to move and skip/remove invalid items */
e4d3c7 ¤   for( userIndex = 0; userIndex < numUsers; userIndex++ )
86c7a1 ¤   {
--8975 000ea747d4e40100296 Page 26 of pgpRecipientDialogCommon.cpp
563368 ¤   ¤   curUser = userList[userIndex];
ec1b52 ¤   ¤
6df698 ¤   ¤   pgpAssert( UserIsVisible( curUser ) );
f87634 ¤   ¤   pgpAssert( curUser->location != destinationList );
42af5a
1f186a ¤   ¤   if( curUser->lockRefCount > 0 )
2c5b34 ¤   ¤   {
0be01b ¤   ¤   ¤   pgpAssert(
a5d6ee ¤   ¤   ¤   ¤   curUser->location == kPGPRecipientUserLocation_RecipientList );
ec0fe4 ¤   ¤   }
592c87 ¤   ¤   else if( curUser->kind == kPGPRecipientUserKind_MissingRecipient )
ba5b34 ¤   ¤   {
50e01b ¤   ¤   ¤   pgpAssert(
41d6ee ¤   ¤   ¤   ¤   curUser->location == kPGPRecipientUserLocation_RecipientList );
4a87c7 ¤   ¤   ¤
145bd9 ¤   ¤   ¤   /*·
841cea ¤   ¤   ¤   ** Missing recipients are never allowed in the user list.
d1ebe4 ¤   ¤   ¤   ** Remove from view
1d3da8 ¤   ¤   ¤   */
02922c ¤   ¤   ¤   curUser->location = kPGPRecipientUserLocation_Hidden;
3e09b9 ¤   ¤   ¤   *numMovedUsers += 1;
7e0fe4 ¤   ¤   }
240e1d ¤   ¤   else
c45b34 ¤   ¤   {
1ab5ab ¤   ¤   ¤   PGPBoolean¤ moveUser = TRUE;
d5af5a
7ec488 ¤   ¤   ¤   if( destinationList == kPGPRecipientUserLocation_RecipientList )
17f776 ¤   ¤   ¤   {
0e3eaa ¤   ¤   ¤   ¤   PGPBoolean¤ missingARRs = FALSE;
62b4e5 ¤   ¤   ¤   ¤   PGPBoolean¤ markedARRs ¤= FALSE;
1b2b85 ¤   ¤   ¤   ¤
45a247 ¤   ¤   ¤   ¤   if( recipients->arrEnforcement != kPGPARREnforcement_None )
2a72c3 ¤   ¤   ¤   ¤   {
7f85b7 ¤   ¤   ¤   ¤   ¤   if( curUser->kind == kPGPRecipientUserKind_Key )
274859 ¤   ¤   ¤   ¤   ¤   {
2a4ebc ¤   ¤   ¤   ¤   ¤   ¤   moveUser = MarkKeyARRsForUserToRecipientMove(
7c0de7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients, curUser->userInfo.key,
0f9a15 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   markValue, &markedARRs, &missingARRs );
3e1c89 ¤   ¤   ¤   ¤   ¤   }
9d4bd6 ¤   ¤   ¤   ¤   ¤   else
854859 ¤   ¤   ¤   ¤   ¤   {
737d19 ¤   ¤   ¤   ¤   ¤   ¤   pgpAssert( curUser->kind ==
8bfc53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserKind_Group );
58af5a
1087d1 ¤   ¤   ¤   ¤   ¤   ¤   moveUser = MarkGroupARRsForUserToRecipientMove(
dc41a6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients, curUser,
2c9a15 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   markValue, &markedARRs, &missingARRs );
011c89 ¤   ¤   ¤   ¤   ¤   }
9f2613 ¤   ¤   ¤   ¤   }
18af5a
f38ab9 ¤   ¤   ¤   ¤   if( moveUser )
d172c3 ¤   ¤   ¤   ¤   {
2fcdd9 ¤   ¤   ¤   ¤   ¤   curUser->markValue ¤¤   = markValue;
2184c2 ¤   ¤   ¤   ¤   ¤   curUser->movedManually¤ = TRUE;
adae30 ¤   ¤   ¤   ¤   ¤
85313c ¤   ¤   ¤   ¤   ¤   *numMovedUsers += 1;
b5ae30 ¤   ¤   ¤   ¤   ¤
554e7e ¤   ¤   ¤   ¤   ¤   if( markedARRs )
6a7b5a ¤   ¤   ¤   ¤   ¤   ¤   *movedARRs = TRUE;
3894aa ¤   ¤   ¤   ¤   ¤   ¤
c5d517 ¤   ¤   ¤   ¤   ¤   if( missingARRs )
f84859 ¤   ¤   ¤   ¤   ¤   {
1b531d ¤   ¤   ¤   ¤   ¤   ¤   err = SendUserEvent( recipients,
00c3d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientEvent_MoveUserWarningEvent,
6966ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser );
b71c89 ¤   ¤   ¤   ¤   ¤   }
2c2613 ¤   ¤   ¤   ¤   }
dbfa07 ¤   ¤   ¤   ¤   else
de72c3 ¤   ¤   ¤   ¤   {
df368c ¤   ¤   ¤   ¤   ¤   pgpAssert( ! markedARRs );
a1ae30 ¤   ¤   ¤   ¤   ¤
ea3c2e ¤   ¤   ¤   ¤   ¤   err = SendUserEvent( recipients,
--69cb 000217a5bb540100296 Page 27 of pgpRecipientDialogCommon.cpp
a6feec ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientEvent_MoveUserFailedEvent,
7066ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser );
3f2613 ¤   ¤   ¤   ¤   }
59a3a6 ¤   ¤   ¤   }
4abb8c ¤   ¤   ¤   else
c8f776 ¤   ¤   ¤   {
1ba247 ¤   ¤   ¤   ¤   if( recipients->arrEnforcement != kPGPARREnforcement_None )
9c72c3 ¤   ¤   ¤   ¤   {
be85b7 ¤   ¤   ¤   ¤   ¤   if( curUser->kind == kPGPRecipientUserKind_Key )
044859 ¤   ¤   ¤   ¤   ¤   {
1e1e7d ¤   ¤   ¤   ¤   ¤   ¤   if( curUser->movedManually )
358fec ¤   ¤   ¤   ¤   ¤   ¤   {
015601 ¤   ¤   ¤   ¤   ¤   ¤   ¤   MarkKeyARRsForRecipientToUserMove(
9e0de7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients, curUser->userInfo.key,
73b016 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   markValue );
90db3c ¤   ¤   ¤   ¤   ¤   ¤   }
9748e6 ¤   ¤   ¤   ¤   ¤   ¤   else if( curUser->userInfo.enforcedARRRefCount != 0 )
e48fec ¤   ¤   ¤   ¤   ¤   ¤   {
b975a8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = SendUserEvent( recipients,
a50498 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientEvent_MovedARRWarningEvent,
7c66ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser );
fadb3c ¤   ¤   ¤   ¤   ¤   ¤   }
d01c89 ¤   ¤   ¤   ¤   ¤   }
e64bd6 ¤   ¤   ¤   ¤   ¤   else
784859 ¤   ¤   ¤   ¤   ¤   {
077d19 ¤   ¤   ¤   ¤   ¤   ¤   pgpAssert( curUser->kind ==
3dfc53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserKind_Group );
a8ae30 ¤   ¤   ¤   ¤   ¤
d7f755 ¤   ¤   ¤   ¤   ¤   ¤   MarkGroupARRsForRecipientToUserMove( recipients,
fedd53 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser, markValue );
7b1c89 ¤   ¤   ¤   ¤   ¤   }
e42613 ¤   ¤   ¤   ¤   }
a22b85 ¤   ¤   ¤   ¤
af8ab9 ¤   ¤   ¤   ¤   if( moveUser )
2f72c3 ¤   ¤   ¤   ¤   {
e6cdd9 ¤   ¤   ¤   ¤   ¤   curUser->markValue ¤¤   = markValue;
44d4d9 ¤   ¤   ¤   ¤   ¤   curUser->movedManually¤ = FALSE;
7faf5a
99313c ¤   ¤   ¤   ¤   ¤   *numMovedUsers += 1;
8c2613 ¤   ¤   ¤   ¤   }
72a3a6 ¤   ¤   ¤   }
3b0fe4 ¤   ¤   }
821b52 ¤   ¤
85d223 ¤   ¤   if( IsPGPError( err ) )
9dcdcb ¤   ¤   ¤   break;
5f9371 ¤   }
8faf5a
229ae4 ¤   /* Second pass. Move all users with correct mark value */
16c575 ¤   curKey = recipients->keys;
110a69 ¤   while( IsntNull( curKey ) && IsntPGPError( err ) )
5dc7a1 ¤   {
d5791a ¤   ¤   curUser = curKey->users;
cb7ebc ¤   ¤   while( IsntNull( curUser ) )
895b34 ¤   ¤   {
9e757d ¤   ¤   ¤   if( curUser->markValue == markValue &&
177aac ¤   ¤   ¤   ¤   curUser->location != destinationList )
26f776 ¤   ¤   ¤   {
eb2455 ¤   ¤   ¤   ¤   curUser->location = destinationList;
a52b85 ¤   ¤   ¤   ¤
c66f35 ¤   ¤   ¤   ¤   err = SendUserEvent( recipients,
b0b47b ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientEvent_MovedUserEvent, curUser );
219c8a ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
8014c3 ¤   ¤   ¤   ¤   ¤   break;
8ca3a6 ¤   ¤   ¤   }
eb1b52 ¤   ¤
1909b3 ¤   ¤   ¤   curUser = curUser->nextUser;
010fe4 ¤   ¤   }
d31b52 ¤   ¤
09cf46 ¤   ¤   curKey = curKey->nextKey;
299371 ¤   }
46af5a
213d92 ¤   curUser = recipients->groups;
--9470 000085a36be40100296 Page 28 of pgpRecipientDialogCommon.cpp
f56f15 ¤   while( IsntNull( curUser ) && IsntPGPError( err ))
70c7a1 ¤   {
92adcf ¤   ¤   if( curUser->markValue == markValue &&
0c6b8b ¤   ¤   ¤   curUser->location != destinationList )
ca5b34 ¤   ¤   {
30774e ¤   ¤   ¤   curUser->location = destinationList;
5987c7 ¤   ¤   ¤
ac3da8 ¤   ¤   ¤   err = SendUserEvent( recipients,
e7b47b ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientEvent_MovedUserEvent, curUser );
2959df ¤   ¤   ¤   if( IsPGPError( err ) )
17f622 ¤   ¤   ¤   ¤   break;
a10fe4 ¤   ¤   }
8f67c5 ¤
760c5e ¤   ¤   curUser = curUser->nextUser;
f89371 ¤   }
2667c5 ¤
c6deb7 ¤   return( err );
40efe6 }
1faf5a
f066dd ¤   static PGPError
9e962f pgpAddKeyToSet(
69eeb1 ¤   PGPKeyRef¤  ¤   theKey,
2b46a5 ¤   PGPKeySetRef¤   keySet,
d4d271 ¤   PGPBoolean¤ ¤   commitKeySet)
f6bb36 {
fafb19 ¤   PGPError¤   ¤   err;
f7b9de ¤   PGPKeySetRef¤   singletonSet;
5867c5 ¤
209ad1 ¤   err = PGPNewSingletonKeySet( theKey, &singletonSet );
a7b1f0 ¤   if( IsntPGPError( err ) )
bec7a1 ¤   {
3114ba ¤   ¤   err = PGPAddKeys( singletonSet, keySet );
a6c034 ¤   ¤   if( IsntPGPError( err ) && commitKeySet )
825b34 ¤   ¤   {
8fa365 ¤   ¤   ¤   err = PGPCommitKeyRingChanges( keySet );
730fe4 ¤   ¤   }
3a1b52 ¤   ¤
9f92c7 ¤   ¤   (void) PGPFreeKeySet( singletonSet );
089371 ¤   }
2867c5 ¤
acdeb7 ¤   return( err );
38efe6 }
e8af5a
3fc744 ¤   PGPError
bfeaf0 PGPGetRecipientKeys(
61c16d ¤   PGPRecipientsList¤  *recipients,
d8beff ¤   PGPKeySetRef¤   ¤   *keySetPtr,
ea6448 ¤   PGPKeySetRef¤   ¤   *newKeysPtr,
0815b8 ¤   PGPUInt32¤  ¤   ¤   *keyListCountPtr,
995490 ¤   PGPRecipientSpec¤   **keyListPtr)
3fbb36 {
f073ec ¤   PGPError¤   ¤   ¤   err¤¤   ¤   ¤   = kPGPError_NoErr;
541cfc ¤   PGPKeySetRef¤   ¤   keySet¤ ¤   ¤   = kInvalidPGPKeySetRef;
05cf42 ¤   PGPBoolean¤ ¤   ¤   haveNewKeys¤¤   = FALSE;
9a323d ¤   PGPUInt32¤  ¤   ¤   keyListCount¤   = 0;
09a204 ¤   PGPRecipientSpec¤   *keyList¤   ¤   = NULL;
4067c5 ¤
cf440d ¤   PGPValidatePtr( keySetPtr );
210e04 ¤   *keySetPtr¤ = NULL;
7b67c5 ¤
1a3202 ¤   err = PGPNewKeySet( recipients->context, &keySet );
8eb1f0 ¤   if( IsntPGPError( err ) )
b0c7a1 ¤   {
4d6a07 ¤   ¤   PGPRecipientKey¤¤   *curKey;
f34a51 ¤   ¤   PGPRecipientUser¤   *curUser;
065137 ¤   ¤   PGPUInt32¤  ¤   ¤   markValue;
db1b52 ¤   ¤
04b61c ¤   ¤   markValue = GetNextMarkValue();
791b52 ¤   ¤
d008d7 ¤   ¤   /* Mark keys in recipient list */
ad490a ¤   ¤   curKey = recipients->keys;
086484 ¤   ¤   while( IsntNull( curKey ) )
--bce9 00068f4865440100296 Page 29 of pgpRecipientDialogCommon.cpp
e35b34 ¤   ¤   {
ec9f18 ¤   ¤   ¤   if( curKey->isNewKey )
f0c27a ¤   ¤   ¤   ¤   haveNewKeys = TRUE;
672b85 ¤   ¤   ¤   ¤
964472 ¤   ¤   ¤   curUser = curKey->users;
867b51 ¤   ¤   ¤   while( IsntNull( curUser ) )
c8f776 ¤   ¤   ¤   {
8bb081 ¤   ¤   ¤   ¤   if( curUser->location ==
a11b1f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList )
4e72c3 ¤   ¤   ¤   ¤   {
e0c320 ¤   ¤   ¤   ¤   ¤   curKey->markValue = markValue;
8714c3 ¤   ¤   ¤   ¤   ¤   break;
b12613 ¤   ¤   ¤   ¤   }
012b85 ¤   ¤   ¤   ¤
b30f0b ¤   ¤   ¤   ¤   curUser = curUser->nextUser;
70a3a6 ¤   ¤   ¤   }
601b52 ¤   ¤
0e2035 ¤   ¤   ¤   curKey = curKey->nextKey;
8f0fe4 ¤   ¤   }
e01b52 ¤   ¤
3b99e6 ¤   ¤   /* Mark group keys in recipient list */
30d2e1 ¤   ¤   curUser = recipients->groups;
b8f20b ¤   ¤   while( IsntNull( curUser ) && IsntPGPError( err ) )
3b5b34 ¤   ¤   {
8d043a ¤   ¤   ¤   if( curUser->location == kPGPRecipientUserLocation_RecipientList )
dbf776 ¤   ¤   ¤   {
17f111 ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   itemIndex;
572b85 ¤   ¤   ¤   ¤
e728d2 ¤   ¤   ¤   ¤   for( itemIndex = 0; itemIndex < curUser->groupInfo.numKeys;
4ae418 ¤   ¤   ¤   ¤   ¤   ¤   ++itemIndex )
4e72c3 ¤   ¤   ¤   ¤   {
a928af ¤   ¤   ¤   ¤   ¤   PGPGroupItem¤   item;
acae30 ¤   ¤   ¤   ¤   ¤
413a54 ¤   ¤   ¤   ¤   ¤   err = PGPGetIndGroupItem( recipients->groupSet,
6733ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->groupInfo.groupID, itemIndex, &item );
fa6ca0 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
3155b9 ¤   ¤   ¤   ¤   ¤   {¤
5e03bc ¤   ¤   ¤   ¤   ¤   ¤   if( item.userValue != 0 )
068fec ¤   ¤   ¤   ¤   ¤   ¤   {
45e87a ¤   ¤   ¤   ¤   ¤   ¤   ¤   curKey = (PGPRecipientKey *) item.userValue;
712afc ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( curKey->isVisible )
4d06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
f1d5de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curKey->markValue = markValue;
d15268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
d6db3c ¤   ¤   ¤   ¤   ¤   ¤   }
b81c89 ¤   ¤   ¤   ¤   ¤   }
3a4bd6 ¤   ¤   ¤   ¤   ¤   else
bf4859 ¤   ¤   ¤   ¤   ¤   {
ab00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
8d1c89 ¤   ¤   ¤   ¤   ¤   }
0e2613 ¤   ¤   ¤   ¤   }
e3a3a6 ¤   ¤   ¤   }
9287c7 ¤   ¤   ¤
c109b3 ¤   ¤   ¤   curUser = curUser->nextUser;
8c0fe4 ¤   ¤   }
75af5a
7b35ad ¤   ¤   /* If creating a key list, count the marked keys and allocate the
aeb830 ¤   ¤   ¤   list */
015953 ¤   ¤   if( IsntNull( keyListPtr ) )
585b34 ¤   ¤   {
0408f9 ¤   ¤   ¤   curKey = recipients->keys;
a1a1d1 ¤   ¤   ¤   while( IsntNull( curKey ) )
97f776 ¤   ¤   ¤   {
afaf8d ¤   ¤   ¤   ¤   if( curKey->markValue == markValue )
b972c3 ¤   ¤   ¤   ¤   {
b52f49 ¤   ¤   ¤   ¤   ¤   ++keyListCount;
d82613 ¤   ¤   ¤   ¤   }
4387c7 ¤   ¤   ¤
aa1cdb ¤   ¤   ¤   ¤   curKey = curKey->nextKey;
51a3a6 ¤   ¤   ¤   }
4487c7 ¤   ¤   ¤
6826f8 ¤   ¤   ¤   /* Count missing items as well */
--020b 0006c734bff40100296 Page 30 of pgpRecipientDialogCommon.cpp
e587c7 ¤   ¤   ¤
dae560 ¤   ¤   ¤   curUser = recipients->missingRecipients;
907b51 ¤   ¤   ¤   while( IsntNull( curUser ) )
adf776 ¤   ¤   ¤   {
14b081 ¤   ¤   ¤   ¤   if( curUser->location ==
321b1f ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList )
fb72c3 ¤   ¤   ¤   ¤   {
1a2f49 ¤   ¤   ¤   ¤   ¤   ++keyListCount;
3e2613 ¤   ¤   ¤   ¤   }
3c2b85 ¤   ¤   ¤   ¤
6e0f0b ¤   ¤   ¤   ¤   curUser = curUser->nextUser;
05a3a6 ¤   ¤   ¤   }
ae87c7 ¤   ¤   ¤
6a96b0 ¤   ¤   ¤   keyList = (PGPRecipientSpec *) PGPNewData( recipients->memoryMgr,·
5b91ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   keyListCount * sizeof( PGPRecipientSpec ),
291e0b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMemoryMgrFlags_Clear );
4c8ecb ¤   ¤   ¤   if( IsNull( keyList ) )
6abfb4 ¤   ¤   ¤   ¤   err = kPGPError_OutOfMemory;
680fe4 ¤   ¤   }
401b52 ¤   ¤
2e5e0d ¤   ¤   if( IsntPGPError( err ) )·
955b34 ¤   ¤   {
4b8073 ¤   ¤   ¤   PGPRecipientSpec¤   *curKeySpec = keyList;
2987c7 ¤   ¤   ¤
aded53 ¤   ¤   ¤   /* Final pass. Add marked keys to result set */
f008f9 ¤   ¤   ¤   curKey = recipients->keys;
c70db0 ¤   ¤   ¤   while( IsntNull( curKey ) && IsntPGPError( err ) )
d9f776 ¤   ¤   ¤   {
feaf8d ¤   ¤   ¤   ¤   if( curKey->markValue == markValue )
2172c3 ¤   ¤   ¤   ¤   {
62ff9b ¤   ¤   ¤   ¤   ¤   err = pgpAddKeyToSet( curKey->keyRef, keySet, FALSE );
64112e ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && IsntNull( curKeySpec ) )
124859 ¤   ¤   ¤   ¤   ¤   {
927abf ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID¤   keyID;
9e94aa ¤   ¤   ¤   ¤   ¤   ¤
8b4106 ¤   ¤   ¤   ¤   ¤   ¤   /*
a67e74 ¤   ¤   ¤   ¤   ¤   ¤   ** If we're creating a recipient list, we need to get
d991bf ¤   ¤   ¤   ¤   ¤   ¤   ** the value of curKey->keyRef as it appears in keySet,
9cd3aa ¤   ¤   ¤   ¤   ¤   ¤   ** _not_ our working set, so we have to search by key ID
990603 ¤   ¤   ¤   ¤   ¤   ¤   */
3594aa ¤   ¤   ¤   ¤   ¤   ¤
0e6bcd ¤   ¤   ¤   ¤   ¤   ¤   err = PGPGetKeyIDFromKey( curKey->keyRef, &keyID );
c312da ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
602498 ¤   ¤   ¤   ¤   ¤   ¤   ¤   IsntPGPError( PGPGetKeyByKeyID( keySet, &keyID,
4f9269 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curKey->algorithm, &curKeySpec->u.key ) ) )
de8fec ¤   ¤   ¤   ¤   ¤   ¤   {
d44886 ¤   ¤   ¤   ¤   ¤   ¤   ¤   curKeySpec->type = kPGPRecipientSpecType_Key;
fc94aa ¤   ¤   ¤   ¤   ¤   ¤
fe71fa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++curKeySpec;
e4db3c ¤   ¤   ¤   ¤   ¤   ¤   }
141c89 ¤   ¤   ¤   ¤   ¤   }
f82613 ¤   ¤   ¤   ¤   }
c587c7 ¤   ¤   ¤
071cdb ¤   ¤   ¤   ¤   curKey = curKey->nextKey;
14a3a6 ¤   ¤   ¤   }
63af5a
476237 ¤   ¤   ¤   if( IsntPGPError( err ) && IsntNull( curKeySpec ) )
18f776 ¤   ¤   ¤   {
738a53 ¤   ¤   ¤   ¤   curUser = recipients->missingRecipients;
147de9 ¤   ¤   ¤   ¤   while( IsntNull( curUser ) )
5e72c3 ¤   ¤   ¤   ¤   {
d9b639 ¤   ¤   ¤   ¤   ¤   if( curUser->location ==
580da9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList )
804859 ¤   ¤   ¤   ¤   ¤   {
3497d8 ¤   ¤   ¤   ¤   ¤   ¤   curKeySpec->type = curUser->missingUser.type;
9194aa ¤   ¤   ¤   ¤   ¤   ¤
87f205 ¤   ¤   ¤   ¤   ¤   ¤   if( curUser->missingUser.type ==
c1fd85 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientSpecType_UserID )
cc8fec ¤   ¤   ¤   ¤   ¤   ¤   {
682f69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   strcpy( curKeySpec->u.userIDStr,
4b1196 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetRecipientUserNamePtr( curUser ) );
6cdb3c ¤   ¤   ¤   ¤   ¤   ¤   }
--96a4 0008c6ae8a740100296 Page 31 of pgpRecipientDialogCommon.cpp
ba1071 ¤   ¤   ¤   ¤   ¤   ¤   else if( curUser->missingUser.type ==
990059 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientSpecType_KeyID )
278fec ¤   ¤   ¤   ¤   ¤   ¤   {
d6aec3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   curKeySpec->u.id.keyID =
992d14 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *curUser->missingUser.keyID;
62be74 ¤   ¤   ¤   ¤   ¤   ¤   ¤   curKeySpec->u.id.algorithm =
f4cb38 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->missingUser.algorithm;
fadb3c ¤   ¤   ¤   ¤   ¤   ¤   }
c67f8b ¤   ¤   ¤   ¤   ¤   ¤   else
ac8fec ¤   ¤   ¤   ¤   ¤   ¤   {
8c9181 ¤   ¤   ¤   ¤   ¤   ¤   ¤   pgpDebugMsg( "PGPGetRecipientKeys(): Unknown "
b27ada ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   "missing recipient type" );
15db3c ¤   ¤   ¤   ¤   ¤   ¤   }
9994aa ¤   ¤   ¤   ¤   ¤   ¤
204d14 ¤   ¤   ¤   ¤   ¤   ¤   ++curKeySpec;
661c89 ¤   ¤   ¤   ¤   ¤   }
58ae30 ¤   ¤   ¤   ¤   ¤
695d96 ¤   ¤   ¤   ¤   ¤   curUser = curUser->nextUser;
082613 ¤   ¤   ¤   ¤   }
86a3a6 ¤   ¤   ¤   }
230fe4 ¤   ¤   }
8a1b52 ¤   ¤
6086f8 ¤   ¤   if( IsntPGPError( err ) )
8ca365 ¤   ¤   ¤   err = PGPCommitKeyRingChanges( keySet );
5c87c7 ¤   ¤   ¤
3bd223 ¤   ¤   if( IsPGPError( err ) )
c95b34 ¤   ¤   {
860672 ¤   ¤   ¤   PGPFreeKeySet( keySet );
2458d9 ¤   ¤   ¤   keySet = kInvalidPGPKeySetRef;
500fe4 ¤   ¤   }
549371 ¤   }
8467c5 ¤
248c4a ¤   *keySetPtr ¤¤   ¤   = keySet;
4a67c5 ¤
1a643b ¤   if( IsntNull( keyListPtr ) )
176224 ¤   ¤   *keyListPtr¤¤   ¤   = keyList;
4baf5a
03aec0 ¤   if( IsntNull( keyListCountPtr ) )
349c36 ¤   ¤   *keyListCountPtr¤   = keyListCount;
a367c5 ¤
649830 ¤   if( IsntPGPError( err ) &&
0d8ae3 ¤   ¤   IsntNull( newKeysPtr ) )
10c7a1 ¤   {
8d74c0 ¤   ¤   *newKeysPtr = kInvalidPGPKeySetRef;
c81b52 ¤   ¤
90afcc ¤   ¤   if( haveNewKeys )
4d5b34 ¤   ¤   {
fa7949 ¤   ¤   ¤   err = PGPNewKeySet( recipients->context, &keySet );
54698b ¤   ¤   ¤   if( IsntPGPError( err ) )
19f776 ¤   ¤   ¤   {
886952 ¤   ¤   ¤   ¤   PGPRecipientKey¤¤   *curKey;
d0af5a
8a06b5 ¤   ¤   ¤   ¤   curKey = recipients->keys;
a3804c ¤   ¤   ¤   ¤   while( IsntNull( curKey ) && IsntPGPError( err ) )
f572c3 ¤   ¤   ¤   ¤   {
32d0a7 ¤   ¤   ¤   ¤   ¤   if( curKey->isNewKey )
9b4859 ¤   ¤   ¤   ¤   ¤   {
0312bc ¤   ¤   ¤   ¤   ¤   ¤   err = pgpAddKeyToSet( curKey->keyRef, keySet, FALSE );
f51c89 ¤   ¤   ¤   ¤   ¤   }
6c2b85 ¤   ¤   ¤   ¤
eb251e ¤   ¤   ¤   ¤   ¤   curKey = curKey->nextKey;
ac2613 ¤   ¤   ¤   ¤   }
1f2b85 ¤   ¤   ¤   ¤
cb5565 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
cdeae3 ¤   ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges( keySet );
10ae30 ¤   ¤   ¤   ¤   ¤
e19c8a ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
5f72c3 ¤   ¤   ¤   ¤   {
910527 ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( keySet );
3f11f3 ¤   ¤   ¤   ¤   ¤   keySet = kInvalidPGPKeySetRef;
542613 ¤   ¤   ¤   ¤   }
8ca3a6 ¤   ¤   ¤   }
--c084 0007aa6623640100296 Page 32 of pgpRecipientDialogCommon.cpp
e587c7 ¤   ¤   ¤
b4356c ¤   ¤   ¤   *newKeysPtr = keySet;
770fe4 ¤   ¤   }
949371 ¤   }
dd67c5 ¤
cedeb7 ¤   return( err );
f2efe6 }
c9af5a
d866dd ¤   static PGPError
a0d3ad pgpUpdateMissingRecipients(
2137db ¤   void¤   ¤   ¤   ¤   *hwndParent,
e0c16d ¤   PGPRecipientsList¤  *recipients,
9f5e28 ¤   PGPBoolean¤ ¤   ¤   *haveNewKeys)
a6bb36 {
879232 ¤   PGPError¤   ¤   ¤   err ¤   = kPGPError_NoErr;
31a522 ¤   PGPRecipientUser¤   *curUser;
960fa9 ¤   PGPKeySetRef¤   ¤   searchResults;
ad7925 ¤   PGPContextRef¤  ¤   context;
3e200d ¤   PGPBoolean¤ ¤   ¤   haveNewUsers = FALSE;
7f67c5 ¤
b8a834 ¤   (void) hwndParent;
fd67c5 ¤
02b661 ¤   context ¤   ¤   = recipients->context;
ce0318 ¤   *haveNewKeys ¤  = FALSE;
db67c5 ¤
7f78ef ¤   err = PGPNewKeySet( context, &searchResults );
05b1f0 ¤   if( IsntPGPError( err ) )
f9c7a1 ¤   {
f14e15 ¤   ¤   /* Search for missing recipients */
42b67b ¤   ¤   curUser = recipients->missingRecipients;
9cf20b ¤   ¤   while( IsntNull( curUser ) && IsntPGPError( err ) )
335b34 ¤   ¤   {
57043a ¤   ¤   ¤   if( curUser->location == kPGPRecipientUserLocation_RecipientList )
e2f776 ¤   ¤   ¤   {
f29ed6 ¤   ¤   ¤   ¤   PGPFilterRef¤   filter = kInvalidPGPFilterRef;
912b85 ¤   ¤   ¤   ¤
54c356 ¤   ¤   ¤   ¤   if( curUser->missingUser.type == kPGPRecipientSpecType_UserID )
2e72c3 ¤   ¤   ¤   ¤   {
679106 ¤   ¤   ¤   ¤   ¤   err = PGPNewUserIDStringFilter( context,
0b9846 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetRecipientUserNamePtr( curUser ),
518c91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPMatchSubString,
b64747 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &filter );
c02613 ¤   ¤   ¤   ¤   }
6df106 ¤   ¤   ¤   ¤   else if( curUser->missingUser.type ==
46a963 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientSpecType_KeyID )
6372c3 ¤   ¤   ¤   ¤   {
7e92e7 ¤   ¤   ¤   ¤   ¤   err = PGPNewKeyIDFilter( context,
b4c060 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->missingUser.keyID, &filter );
d42613 ¤   ¤   ¤   ¤   }
42fa07 ¤   ¤   ¤   ¤   else
3a72c3 ¤   ¤   ¤   ¤   {
7c4e41 ¤   ¤   ¤   ¤   ¤   pgpDebugMsg( "pgpUpdateMissingRecipients(): Unknown "
9f3191 ¤   ¤   ¤   ¤   ¤   ¤   ¤   "missing recipient type" );
772613 ¤   ¤   ¤   ¤   }
9e2b85 ¤   ¤   ¤   ¤
f65bf0 ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
7d2275 ¤   ¤   ¤   ¤   ¤   PGPFilterRefIsValid( filter ) )
c872c3 ¤   ¤   ¤   ¤   {
bd38c6 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   tempSet;
98ae30 ¤   ¤   ¤   ¤   ¤
9fc97d ¤   ¤   ¤   ¤   ¤   err = PGPSearchKeyServerDialog( context,
722c20 ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->serverCount, recipients->serverList,
24859d ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->tlsContext, FALSE, &tempSet,
033d3e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOUIKeyServerSearchFilter( context, filter ),
7cafb9 #if PGP_WIN32
7e8104 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOUIParentWindowHandle(context,hwndParent),
7d7454 #endif
fcfc28 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption( context ) );
9f4a06 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && PGPKeySetRefIsValid( tempSet ) )
bd4859 ¤   ¤   ¤   ¤   ¤   {
1246fb ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  numKeys;
7a94aa ¤   ¤   ¤   ¤   ¤   ¤
--488b 0003aa81edf40100296 Page 33 of pgpRecipientDialogCommon.cpp
4dcb79 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCountKeys( tempSet, &numKeys );
1a6bbc ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && numKeys > 0 )
d28fec ¤   ¤   ¤   ¤   ¤   ¤   {
0c3a7c ¤   ¤   ¤   ¤   ¤   ¤   ¤   *haveNewKeys = TRUE;
9e531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
09f86b ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPAddKeys( tempSet, searchResults );
1b8d9f ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
1206b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
6b7edc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges( searchResults );
3c5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
f6db3c ¤   ¤   ¤   ¤   ¤   ¤   }
fb94aa ¤   ¤   ¤   ¤   ¤   ¤
bcd2de ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( tempSet );
711c89 ¤   ¤   ¤   ¤   ¤   }
a3ae30 ¤   ¤   ¤   ¤   ¤
e278c9 ¤   ¤   ¤   ¤   ¤   PGPFreeFilter( filter );
7f2613 ¤   ¤   ¤   ¤   }
79a3a6 ¤   ¤   ¤   }
8187c7 ¤   ¤   ¤
2a09b3 ¤   ¤   ¤   curUser = curUser->nextUser;
1b0fe4 ¤   ¤   }
561b52 ¤   ¤
36b89a ¤   ¤   /* Search for incomplete groups */
55d2e1 ¤   ¤   curUser = recipients->groups;
37f20b ¤   ¤   while( IsntNull( curUser ) && IsntPGPError( err ) )
4e5b34 ¤   ¤   {
e9f1d3 ¤   ¤   ¤   if( curUser->location == kPGPRecipientUserLocation_RecipientList &&
e13fb8 ¤   ¤   ¤   ¤   curUser->groupInfo.numMissingKeys > 0 )
15f776 ¤   ¤   ¤   {
b7f111 ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   itemIndex;
012b85 ¤   ¤   ¤   ¤
d128d2 ¤   ¤   ¤   ¤   for( itemIndex = 0; itemIndex < curUser->groupInfo.numKeys;
20e418 ¤   ¤   ¤   ¤   ¤   ¤   ++itemIndex )
0572c3 ¤   ¤   ¤   ¤   {
b728af ¤   ¤   ¤   ¤   ¤   PGPGroupItem¤   item;
c0ae30 ¤   ¤   ¤   ¤   ¤
513a54 ¤   ¤   ¤   ¤   ¤   err = PGPGetIndGroupItem( recipients->groupSet,
b233ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->groupInfo.groupID, itemIndex, &item );
5dccb9 ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && item.userValue == 0 )
0f4859 ¤   ¤   ¤   ¤   ¤   {
f86a5b ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   tempSet;
5b531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
ba1354 ¤   ¤   ¤   ¤   ¤   ¤   err = PGPSearchKeyServerDialog( context,
9a733b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->serverCount,·
5f5bf9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->serverList,
3c1f31 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   recipients->tlsContext, FALSE, &tempSet,
ed3796 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOUIKeyServerSearchKeyIDList( context,
7eeecc ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   1, &item.u.key.keyID ),
07afb9 #if PGP_WIN32
5a48d2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOUIParentWindowHandle(context,
7962b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   hwndParent),
cd7454 #endif
9700b4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOLastOption( context ) );
6312da ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) &&
dab273 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRefIsValid( tempSet ) )
8e8fec ¤   ¤   ¤   ¤   ¤   ¤   {
791466 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  numKeys;
e5531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
5c413c ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCountKeys( tempSet, &numKeys );
7ee1f9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && numKeys > 0 )
4f06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
d56967 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   *haveNewKeys = TRUE;
89ed43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
a5e362 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPAddKeys( tempSet, searchResults );
fc8ee8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
5e31b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
df8d1d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPCommitKeyRingChanges(
c82b47 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   searchResults );
166560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
c95268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
5a531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
3a7cdf ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeKeySet( tempSet );
--7dd0 00019a4455140100296 Page 34 of pgpRecipientDialogCommon.cpp
0ddb3c ¤   ¤   ¤   ¤   ¤   ¤   }
fc1c89 ¤   ¤   ¤   ¤   ¤   }
96ae30 ¤   ¤   ¤   ¤   ¤
4b14ec ¤   ¤   ¤   ¤   ¤   if( IsPGPError( err ) )
ff00eb ¤   ¤   ¤   ¤   ¤   ¤   break;
e02613 ¤   ¤   ¤   ¤   }
31a3a6 ¤   ¤   ¤   }
7387c7 ¤   ¤   ¤
d909b3 ¤   ¤   ¤   curUser = curUser->nextUser;
3f0fe4 ¤   ¤   }
511b52 ¤   ¤
4dea51 ¤   ¤   if( IsntPGPError( err ) && *haveNewKeys )
de5b34 ¤   ¤   {
51a796 ¤   ¤   ¤   err = AddNewKeys( recipients, searchResults );
c11b52 ¤   ¤
3ae560 ¤   ¤   ¤   curUser = recipients->missingRecipients;
f33617 ¤   ¤   ¤   while( IsntNull( curUser ) && IsntPGPError( err ) )
02f776 ¤   ¤   ¤   {
ab7751 ¤   ¤   ¤   ¤   if( UserIsVisible( curUser ) )
d272c3 ¤   ¤   ¤   ¤   {
017164 ¤   ¤   ¤   ¤   ¤   if( curUser->missingUser.type ==·
287079 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientSpecType_UserID )
4c4859 ¤   ¤   ¤   ¤   ¤   {
a8fe5f ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   numMatchedUsers;
7ba3d2 ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientUser¤   **matchedUserList;
8b94aa ¤   ¤   ¤   ¤   ¤   ¤
451603 ¤   ¤   ¤   ¤   ¤   ¤   err = FindUsersFromUserID( recipients,
1348ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGetRecipientUserNamePtr( curUser ),
453af2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   FALSE, &numMatchedUsers,
d9fc9b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &matchedUserList );
98239e ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
b38fec ¤   ¤   ¤   ¤   ¤   ¤   {
00e915 ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( numMatchedUsers != 0 )
e006b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
ebaf89 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ movedARRs;
93410b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  numMovedUsers = 0;
29da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
d7bee0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPMoveRecipients( recipients,
aab4e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList,
f740e6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   numMatchedUsers, matchedUserList,·
701ff7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &numMovedUsers, &movedARRs );
1a8ee8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
0931b0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
14f277 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( numMatchedUsers != 1 )
c4dec3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
212f91 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  userIndex;
7a0230 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
9fb0ef ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   for( userIndex = 0;
135322 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   userIndex < numMatchedUsers;
2c8e7a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ++userIndex )
5ee22d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
e445d8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   matchedUserList[userIndex]->
c4b727 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   multipleMatch = TRUE;
40b6fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
868a13 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
16ed43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
bc46be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->location =
45adc8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_Hidden;
af6560 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
2d5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
38531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
e7e302 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFreeData( matchedUserList );
59db3c ¤   ¤   ¤   ¤   ¤   ¤   }
851c89 ¤   ¤   ¤   ¤   ¤   }
e547b0 ¤   ¤   ¤   ¤   ¤   else if( curUser->missingUser.type ==·
04a963 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientSpecType_KeyID )
f84859 ¤   ¤   ¤   ¤   ¤   {
0b5a1c ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientUser¤   *matchedUser;
0894aa ¤   ¤   ¤   ¤   ¤   ¤
6db9f8 ¤   ¤   ¤   ¤   ¤   ¤   err = FindUserFromKeyID( recipients,
f9cdeb ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->missingUser.keyID,
1913a1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->missingUser.algorithm,
--b22d 00175f805e340100296 Page 35 of pgpRecipientDialogCommon.cpp
e82665 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &matchedUser );
acc7b5 ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) && IsntNull( matchedUser ) )
df8fec ¤   ¤   ¤   ¤   ¤   ¤   {
52beae ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ movedARRs;
9a41e9 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  numMovedUsers = 0;
de531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
7534a5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   err = PGPMoveRecipients( recipients,
3ee634 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_RecipientList,
0c21cf ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   1, &matchedUser, &numMovedUsers,
033c35 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   &movedARRs );
718d9f ¤   ¤   ¤   ¤   ¤   ¤   ¤   if( IsntPGPError( err ) )
bc06b8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   {
c31312 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   curUser->location =
83d482 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   kPGPRecipientUserLocation_Hidden;
5d5268 ¤   ¤   ¤   ¤   ¤   ¤   ¤   }
84db3c ¤   ¤   ¤   ¤   ¤   ¤   }
5a1c89 ¤   ¤   ¤   ¤   ¤   }
1d4bd6 ¤   ¤   ¤   ¤   ¤   else
e14859 ¤   ¤   ¤   ¤   ¤   {
5ce31f ¤   ¤   ¤   ¤   ¤   ¤   pgpDebugMsg( "Unknown missing recipient type" );
041c89 ¤   ¤   ¤   ¤   ¤   }
102613 ¤   ¤   ¤   ¤   }
f42b85 ¤   ¤   ¤   ¤
ab0f0b ¤   ¤   ¤   ¤   curUser = curUser->nextUser;
47a3a6 ¤   ¤   ¤   }
e20fe4 ¤   ¤   }
871b52 ¤   ¤
5ee972 ¤   ¤   PGPFreeKeySet( searchResults );
029371 ¤   }
c067c5 ¤
84deb7 ¤   return( err );
27efe6 }
14af5a
a5c744 ¤   PGPError
aba3c7 PGPUpdateMissingRecipients(
9837db ¤   void¤   ¤   ¤   ¤   *hwndParent,
39c16d ¤   PGPRecipientsList¤  *recipients,
e55e28 ¤   PGPBoolean¤ ¤   ¤   *haveNewKeys)
43bb36 {
268e12 ¤   PGPError¤   err = kPGPError_NoErr;
3a67c5 ¤
5826d5 ¤   PGPValidatePtr( recipients );
76b3a4 ¤   PGPValidatePtr( haveNewKeys );
f1af5a
1193a8 ¤   *haveNewKeys = FALSE;
9d67c5 ¤
a9d823 ¤   if( IsntNull( recipients->serverList ) &&
0bcf82 ¤   ¤   recipients->serverCount != 0 )
72c7a1 ¤   {
e431c1 ¤   ¤   err = pgpUpdateMissingRecipients( hwndParent, recipients, haveNewKeys );
389371 ¤   }
6767c5 ¤
40deb7 ¤   return( err );
92efe6 }
75af5a
--3cf2 000be5370b340100297 Page 1 of pgpRecipientDialogCommon.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
b41d77 ¤   $Id: pgpRecipientDialogCommon.h,v 1.15.10.1 1998/11/12 03:23:03 heller Exp $
fbf7f7 ____________________________________________________________________________*/
19af5a
e7109d #ifndef Included_pgpRecipientDialogCommon_h¤/* [ */
8aef34 #define Included_pgpRecipientDialogCommon_h
30af5a
836773 #include "pgpMemoryMgr.h"
58e82c #include "pgpPubTypes.h"
cbe684 #include "pgpUserInterface.h"
07af5a
213f73 #define kPGPNumKeyListKeys¤ ¤   20
1f1fe3 #define kPGPNumUserListUsers¤   30
7eaf5a
1915b9 typedef enum PGPRecipientUserKind
f5bb36 {
2dc3f0 ¤   kPGPRecipientUserKind_Invalid = 0,
4eb66a ¤   kPGPRecipientUserKind_Key,
b50fa2 ¤   kPGPRecipientUserKind_MissingRecipient,
024caa ¤   kPGPRecipientUserKind_Group
8267c5 ¤
60823f } PGPRecipientUserKind;
d2af5a
3de115 typedef enum PGPRecipientUserLocation
89bb36 {
17c675 ¤   kPGPRecipientUserLocation_Invalid = 0,
bdd920 ¤   kPGPRecipientUserLocation_UserList,
e164f4 ¤   kPGPRecipientUserLocation_RecipientList,
c723bd ¤   kPGPRecipientUserLocation_Hidden
2b67c5 ¤
d52df7 } PGPRecipientUserLocation;
abaf5a
e6e509 typedef enum PGPRecipientEventType
85bb36 {
a5d5b7 ¤   kPGPRecipientEvent_InvalidEvent¤= 0,
fffc56 ¤   kPGPRecipientEvent_MovedUserEvent,
af4111 ¤   kPGPRecipientEvent_MoveUserWarningEvent,
6f060a ¤   kPGPRecipientEvent_MoveUserFailedEvent,
6a049c ¤   kPGPRecipientEvent_MovedARRWarningEvent
5267c5 ¤
7adfaa } PGPRecipientEventType;
1baf5a
6f6dac typedef struct PGPRecipientEvent
87bb36 {
91e7ef ¤   PGPRecipientEventType¤  ¤   type;
26ec75 ¤   struct PGPRecipientUser¤¤   *user;
7faf5a
372d41 } PGPRecipientEvent;
bbaf5a
1f8a04 typedef PGPError¤   (*PGPRecipientEventHandlerProcPtr)(
115f46 ¤   ¤   ¤   ¤   ¤   ¤   ¤   struct PGPRecipientsList *recipients,
bec0ad ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientEvent *event, PGPUserValue userValue );
94af5a
a9a65b typedef struct PGPRecipientUser
90bb36 {
9170e6 ¤   struct PGPRecipientUser¤¤   *nextUser;
f67f7c ¤   struct PGPRecipientsList¤   *recipients;
0567c5 ¤
aa82e7 ¤   PGPRecipientUserKind¤   ¤   kind;
b776ef ¤   PGPRecipientUserLocation¤   location;
92aaa7 ¤   PGPValidity¤¤   ¤   ¤   ¤   validity;
ec0d91 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   nameOffset;
c1ec4d ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   markValue;¤ ¤   ¤   /* Temp use only */
a800e3 ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   lockRefCount;¤  ¤   /* Cannot be moved ·*/
e467c5 ¤
e4349d ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   movedManually¤  : 1;
46b22f ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   multipleMatch¤  : 1;
2f67c5 ¤
bef20a ¤   union
--e732 000438690bc40100297 Page 2 of pgpRecipientDialogCommon.h
f7c7a1 ¤   {
df2b33 ¤   ¤   struct
7f5b34 ¤   ¤   {
ce8cd2 ¤   ¤   ¤   struct PGPRecipientKey¤ *key;
4a599e ¤   ¤   ¤   PGPUserIDRef¤   ¤   ¤   userID;
29b714 ¤   ¤   ¤   PGPUInt16¤  ¤   ¤   ¤   arrRefCount;
515d77 ¤   ¤   ¤   PGPUInt16¤  ¤   ¤   ¤   enforcedARRRefCount;
a387c7 ¤   ¤   ¤
39f2de ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   isPrimaryUser¤  : 1;
c31b52 ¤   ¤
31e2fa ¤   ¤   } userInfo;
401b52 ¤   ¤
3e2b33 ¤   ¤   struct
825b34 ¤   ¤   {
208651 ¤   ¤   ¤   PGPGroupID¤ ¤   ¤   ¤   groupID;
0e2f75 ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   numKeys;
a5e16c ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   numMissingKeys;
b75c27 ¤   ¤   ¤   PGPUInt16¤  ¤   ¤   ¤   numARRKeys;
9d2d01 ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   haveMissingARRs;
3587c7 ¤   ¤   ¤
249b6a ¤   ¤   } groupInfo;
f51b52 ¤   ¤
922b33 ¤   ¤   struct
745b34 ¤   ¤   {
721b84 ¤   ¤   ¤   PGPRecipientSpecType¤   type;
f187c7 ¤   ¤   ¤
ec32a8 ¤   ¤   ¤   const PGPKeyID¤ ¤   ¤   *keyID;
2e75e3 ¤   ¤   ¤   PGPPublicKeyAlgorithm¤  algorithm;
7e87c7 ¤   ¤   ¤
b01958 ¤   ¤   } missingUser;
e162bd ¤   };
caaf5a
2a8290 } PGPRecipientUser;
8aaf5a
2fbf44 typedef struct PGPRecipientKeyARRInfo
a0bb36 {
e53f1b ¤   PGPKeyID¤   ¤   ¤   ¤   keyID;
f75f4f ¤   struct PGPRecipientKey¤ *key;
f140e1 ¤   PGPBoolean¤ ¤   ¤   ¤   keyMissing;
6bc115 ¤   PGPByte¤¤   ¤   ¤   ¤   arrClass;
83af5a
2ac665 } PGPRecipientKeyARRInfo;
3eaf5a
e7b4c8 typedef struct PGPRecipientKey
93bb36 {
308125 ¤   struct PGPRecipientKey¤ ¤   ¤   *nextKey;
a0a31f ¤   struct PGPRecipientUser¤¤   ¤   *users;
1ef4e8 ¤   struct PGPRecipientUser¤¤   ¤   *primaryUser;
b2af5a
537e9f ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   numARRKeys;
52c8c3 ¤   struct PGPRecipientKeyARRInfo¤  *arrKeys;
4167c5 ¤
a1daf6 ¤   PGPKeyRef¤  ¤   ¤   ¤   ¤   ¤   keyRef;
27531b ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   keyBits;
10152f ¤   PGPUInt16¤  ¤   ¤   ¤   ¤   ¤   subKeyBits;
95978a ¤   PGPPublicKeyAlgorithm¤  ¤   ¤   algorithm;
be6680 ¤   PGPUInt32¤  ¤   ¤   ¤   ¤   ¤   markValue;¤ ¤   ¤   /* Temp use only */
3267c5 ¤
4329a9 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   isDefaultKey¤   : 1;
03fe9b ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   isSecretKey¤¤   : 1;
e30e77 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   isAxiomaticKey¤ : 1;
700598 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   canEncrypt¤ ¤   : 1;
c45d4b ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   isNewKey¤   ¤   : 1;
942009 ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   isVisible¤  ¤   : 1;
e92e8d ¤   PGPBoolean¤ ¤   ¤   ¤   ¤   ¤   haveMissingARRs¤: 1;
33af5a
ee646d } PGPRecipientKey;
5eaf5a
990172 typedef struct PGPRecipientUserList
e4bb36 {
d30f5a ¤   struct PGPRecipientUserList¤*nextUserList;
434a32 ¤   struct PGPRecipientUser¤¤   users[kPGPNumUserListUsers];
--cd45 0008c2e6d2b40100297 Page 3 of pgpRecipientDialogCommon.h
e0af5a
325355 } PGPRecipientUserList;
c6af5a
66fa5d typedef struct PGPRecipientKeyList
78bb36 {
7f3bf9 ¤   struct PGPRecipientKeyList¤ *nextKeyList;
0b77c2 ¤   struct PGPRecipientKey¤ ¤   keys[kPGPNumKeyListKeys];
7faf5a
de7089 } PGPRecipientKeyList;
93af5a
c5c721 typedef struct PGPRecipientsList
c5bb36 {
784f25 ¤   PGPContextRef ¤ ¤   ¤   context;
9bb586 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr;
954d7f ¤   PGPKeySetRef¤   ¤   ¤   keySet;
a067c5 ¤
af7a38 ¤   struct PGPRecipientKey¤ *keys;
4a75af ¤   struct PGPRecipientUser¤*missingRecipients;
c91809 ¤   struct PGPRecipientUser¤*groups;
f0af5a
a80bf6 ¤   struct PGPRecipientKey¤ *freeKeys;
bb871d ¤   struct PGPRecipientUser¤*freeUsers;
72af5a
ac10c5 ¤   char¤   ¤   ¤   ¤   ¤   *nameList;
158596 ¤   PGPUInt32¤  ¤   ¤   ¤   nameListSize;
e07e0c ¤   PGPUInt32¤  ¤   ¤   ¤   nextNameOffset;
8267c5 ¤
c8a394 ¤   PGPGroupSetRef¤ ¤   ¤   groupSet;
d96348 ¤   const PGPKeyServerSpec¤ *serverList;
03e793 ¤   PGPUInt32 ¤ ¤   ¤   ¤   serverCount;
8c89ec ¤   PGPtlsContextRef¤   ¤   tlsContext;
8467c5 ¤
725249 ¤   PGPRecipientKeyList¤¤   *keyLists;
59c3f2 ¤   PGPRecipientUserList¤   *userLists;
8867c5 ¤
270fc5 ¤   PGPRecipientEventHandlerProcPtr¤¤   ¤   ¤   eventHandler;
2493ba ¤   PGPUserValue¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   eventUserValue;
6467c5 ¤
636eb5 ¤   PGPAdditionalRecipientRequestEnforcement¤   arrEnforcement;
6267c5 ¤
e17206 } PGPRecipientsList;
e1af5a
eb99c6 PGP_BEGIN_C_DECLARATIONS
a1af5a
feaf31 PGPError¤   ¤   PGPBuildRecipientsList(void *hwndParent,PGPContextRef context,
8ffc17 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef allKeys, PGPGroupSetRef groupSet,
0bf3c6 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 numDefaultRecipients,
9d2e40 ¤   ¤   ¤   ¤   ¤   ¤   const PGPRecipientSpec *defaultRecipients,
48a785 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 serverCount,
e7143b ¤   ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec *serverList,
ba5ee2 ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef tlsContext,
f7ab6a ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean syncUnknownKeys,
971606 ¤   ¤   ¤   ¤   ¤   ¤   PGPAdditionalRecipientRequestEnforcement arrEnforcement,
bfd31a ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientEventHandlerProcPtr eventHandler,
63b31a ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue eventUserValue,
b5eaf2 ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientsList *recipients,
3cdacb ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *haveDefaultARRs);
ea36b8 void¤   ¤   ¤   PGPDisposeRecipientsList(PGPRecipientsList *recipients);
86fd23 PGPError¤   ¤   PGPGetRecipientKeys(PGPRecipientsList *recipients,
c5aa63 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *keySetPtr, PGPKeySetRef *newKeysPtr,
be6357 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 *keyListCountPtr,
293354 ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientSpec **keyListPtr);
1a5183 void¤   ¤   ¤   PGPGetRecipientUserName(const PGPRecipientUser *user,·
f73661 ¤   ¤   ¤   ¤   ¤   ¤   char name[256]);
38627a const char *¤   PGPGetRecipientUserNamePtr(const PGPRecipientUser *user);
804795 PGPError¤   ¤   PGPMoveRecipients(PGPRecipientsList *recipients,
2e5ba1 ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientUserLocation destinationList,
b6fcf2 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 numUsers, PGPRecipientUser **userList,
4501d6 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 *numMovedUsers, PGPBoolean *movedARRs);
e65612 PGPError¤   ¤   PGPUpdateMissingRecipients(void *hwndParent,
77eaf2 ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientsList *recipients,
8cadeb ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *haveNewKeys);
--62a9 001655fe49b40100297 Page 4 of pgpRecipientDialogCommon.h
e694aa ¤   ¤   ¤   ¤   ¤   ¤
411254 PGP_END_C_DECLARATIONS
d7af5a
2ab664 #endif /* ] Included_pgpRecipientDialogCommon_h */
0daf5a
ad7e4d /*__Editor_settings____
beaf5a
9f4126 ¤   Local Variables:
577b17 ¤   tab-width: 4
c20e6c ¤   End:
e75f8c ¤   vi: ts=4 sw=4
249e9b ¤   vim: si
65d062 _____________________*/
--b956 001c1061cb740100298 Page 1 of Makefile.in
5ea601 #
cfd038 # pub/
b5a601 #
4fc789 # $Id: Makefile.in,v 1.3 1997/07/28 23:43:22 mhw Exp $
8fa601 #
6eaf5a
6702a4 SUBDIRS= clientlib include
c1af5a
--b1dd 0013c1dcfb740100299 Page 1 of Makefile.in
5ea601 #
a441e7 # pub/include/
40a601 #
fb35be # $Id: Makefile.in,v 1.2 1997/07/28 23:43:23 mhw Exp $
1ea601 #
3caf5a
--6f7f 000fb94ce644010029a Page 1 of pgpBigNum.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
404139 ¤   $Id: pgpBigNum.h,v 1.8.10.1 1998/11/12 03:23:30 heller Exp $
6af7f7 ____________________________________________________________________________*/
24af5a
7baf5a
80f868 #ifndef Included_pgpBigNum_h
b0795e #define Included_pgpBigNum_h
20af5a
3dc5d5 #include "pgpBase.h"
03af5a
094919 #include "pgpUtilities.h"
91af5a
d96773 #include "pgpMemoryMgr.h"
1eaf5a
0699c6 PGP_BEGIN_C_DECLARATIONS
d7af5a
49cbcf #if PRAGMA_IMPORT_SUPPORTED
17b981 #pragma import on
9c7454 #endif
afaf5a
44af5a
13537c typedef struct PGPBigNum *¤ ¤   ¤   PGPBigNumRef;
742239 #define kPGPInvalidBigNumRef¤   ¤   ( (PGPBigNumRef)NULL )
ceaf5a
68af5a
a5dcc1 /* Creates a new bignum, secure, or plain s*/
3dadb7 PGPError¤   PGPNewBigNum( PGPMemoryMgrRef mgr,
616bc5 ¤   ¤   ¤   ¤   PGPBoolean secure, PGPBigNumRef *newBN );
e5af5a
73d49b /* destoys the bignum and all memory it uses */
2c9283 PGPError¤   PGPFreeBigNum( PGPBigNumRef bn );
15af5a
32af5a
cf7026 /* Create a new big num with same value as src */
76c7ea PGPError ¤  PGPCopyBigNum( PGPBigNumRef src, PGPBigNumRef * dest );
6aaf5a
72ac73 /* Make existing bignum dest have same value as source */
b0c17e PGPError ¤  PGPAssignBigNum( PGPBigNumRef src, PGPBigNumRef dest );
73af5a
1caf5a
0618ce /* Swap two BigNums. ·Very fast. */
7a432d PGPError¤   PGPSwapBigNum( PGPBigNumRef a, PGPBigNumRef b);
46af5a
c0af5a
e838e5 /*
5ab555 ·* Move bytes between the given buffer and the given BigNum encoded in
3f5965 ·* base 256. ·I.e. after either of these, the buffer will be equal to
0eea08 ·* (bn / 256^lsbyte) % 256^len. ·The difference is which is altered to
583b60 ·* match the other!
db495d ·*/
260ef5 PGPError¤   PGPBigNumExtractBigEndianBytes( PGPBigNumRef bn,
6f9ec5 ¤   ¤   ¤   ¤   PGPByte *dest, PGPUInt32 lsbyte, PGPUInt32¤ len );
d72b85 ¤   ¤   ¤   ¤
856c10 PGPError¤   PGPBigNumInsertBigEndianBytes(PGPBigNumRef bn,
bbba4a ¤   ¤   ¤   ¤   PGPByte const *src, PGPUInt32 lsbyte, PGPUInt32 len );
f0af5a
6c684c /* The same, but the buffer is little-endian. */
4e5dd4 PGPError¤   PGPBigNumExtractLittleEndianBytes( PGPBigNumRef bn,
7f9ec5 ¤   ¤   ¤   ¤   PGPByte *dest, PGPUInt32 lsbyte, PGPUInt32¤ len );
492b85 ¤   ¤   ¤   ¤
086d0c PGPError¤   PGPBigNumInsertLittleEndianBytes(PGPBigNumRef bn,
abba4a ¤   ¤   ¤   ¤   PGPByte const *src, PGPUInt32 lsbyte, PGPUInt32 len );
43af5a
f40b69 /* Return the least-significant bits (at least 16) of the BigNum */
65f99e PGPUInt16¤  PGPBigNumGetLSWord( PGPBigNumRef bn );
72af5a
8f38e5 /*
6a810c ·* Return the number of significant bits in the BigNum.
fbd5d9 ·* 0 or 1+floor(log2(src))
--eb11 000edf403cc4010029a Page 2 of pgpBigNum.h
47495d ·*/
0b2d3b PGPUInt32¤  PGPBigNumGetSignificantBits( PGPBigNumRef bn );
33af5a
c438e5 /*
0b4362 ·* Adds two bignums into dest. ·Faster if dest is same as lhs or rhs.
4f495d ·*/
32639e PGPError¤   PGPBigNumAdd( PGPBigNumRef lhs,
f297b7 ¤   ¤   ¤   ¤   PGPBigNumRef rhs, PGPBigNumRef dest );
58af5a
8338e5 /*
9c92ed ·* lhs-rhs. ·dest and src may be the same, but bnSetQ(dest, 0) is faster.
eb869a ·* if dest < src, returns error and dest is undefined.
16495d ·*/
140a99 PGPError¤   PGPBigNumSubtract( PGPBigNumRef lhs,
fc2955 ¤   ¤   ¤   ¤   PGPBigNumRef rhs, PGPBigNumRef dest,
a8af6f ¤   ¤   ¤   ¤   PGPBoolean *underflow );
c0af5a
d2af5a
685a0c /* Return sign (-1, 0, +1) of a-b. ·a <=> b --> bnCmpQ(a, b) <=> 0 */
90abd3 PGPInt32¤   PGPBigNumCompareQ( PGPBigNumRef bn, PGPUInt16 sm );
3caf5a
70848c /* dest = src, where 0 <= src < 2^16. */
b0c6f9 PGPError¤   PGPBigNumSetQ( PGPBigNumRef dest, PGPUInt16 sm );
7daf5a
e5f8c6 /* dest = bn + sm, where 0 <= sm < 2^16 */
287260 PGPError¤   PGPBigNumAddQ( PGPBigNumRef bn, PGPUInt16 sm,
99ff02 ¤   ¤   ¤   ¤   PGPBigNumRef dest);
10af5a
bff8c6 /* dest = bn + sm, where 0 <= sm < 2^16 */
a3fcd3 PGPError¤   PGPBigNumSubtractQ( PGPBigNumRef bn, PGPUInt16 sm,
85a087 ¤   ¤   ¤   ¤   PGPBigNumRef dest, PGPBoolean *underflow);
d5af5a
198dd9 /* Return sign (-1, 0, +1) of a-b. ·a <=> b --> bnCmp(a, b) <=> 0 */
06eacf PGPInt32¤   PGPBigNumCompare( PGPBigNumRef lhs, PGPBigNumRef rhs);
adaf5a
8fec3b /* dest = src * src. ·dest may be the same as src, but it costs time. */
f65d02 PGPError¤   PGPBigNumSquare( PGPBigNumRef src, PGPBigNumRef dest);
dfaf5a
c62854 /* dest = a * b. ·dest may be the same as a or b, but it costs time. */
11d5d8 PGPError¤   PGPBigNumMultiply( PGPBigNumRef lhs, PGPBigNumRef rhs,
e3ff02 ¤   ¤   ¤   ¤   PGPBigNumRef dest);
48af5a
4a804c /* dest = a * b, where 0 <= b < 2^16. ·dest and a may be the same. */
b01af0 PGPError¤   PGPBigNumMultiplyQ( PGPBigNumRef lhs, PGPUInt16 sm,
0eff02 ¤   ¤   ¤   ¤   PGPBigNumRef dest);
faaf5a
c938e5 /*
af7a36 ·* q = n/d, r = n%d. ·r may be the same as n, but not d,
37eb22 ·* and q may not be the same as n or d.
edad6f ·* re-entrancy issue: this temporarily modifies d, but restores
c9bf83 ·* it for return.
d4495d ·*/
d000ce PGPError¤   PGPBigNumDivide( PGPBigNumRef numerator,
af536b ¤   ¤   ¤   ¤   PGPBigNumRef denominator,
d0a06c ¤   ¤   ¤   ¤   PGPBigNumRef quotient,
9dc045 ¤   ¤   ¤   ¤   PGPBigNumRef remainder);
2938e5 /*
2c65ee ·* dest = n % d. ·dest and src may be the same, but not dest and d.
5ead6f ·* re-entrancy issue: this temporarily modifies d, but restores
b4bf83 ·* it for return.
df495d ·*/
29fb5e PGPError¤   PGPBigNumMod( PGPBigNumRef numerator,
56536b ¤   ¤   ¤   ¤   PGPBigNumRef denominator,
39ea83 ¤   ¤   ¤   ¤   PGPBigNumRef dest );
ceaf5a
f25662 /* return src % d, where 0 <= d < 2^16. ·*/
923791 PGPUInt16¤  PGPBigNumModQ( PGPBigNumRef numerator,
55f84a ¤   ¤   ¤   ¤   PGPUInt16 denominator );
caaf5a
89b223 /* n = n^exp, modulo "mod" ··"mod" *must* be odd */
0f2d76 PGPError¤   PGPBigNumExpMod(
edbddf ¤   ¤   ¤   ¤   PGPBigNumRef n,
--cddc 0013bded9c84010029a Page 3 of pgpBigNum.h
44fa20 ¤   ¤   ¤   ¤   PGPBigNumRef exponent,
cdacb4 ¤   ¤   ¤   ¤   PGPBigNumRef mod,
efea83 ¤   ¤   ¤   ¤   PGPBigNumRef dest );
ceaf5a
0c38e5 /*
a57329 ·* dest = n1^e1 * n2^e2, modulo "mod". ·"mod" *must* be odd.
dbf0f0 ·* dest may be the same as n1 or n2.
d6495d ·*/
0f82f2 PGPError¤   PGPBigNumDoubleExpMod(
f48c94 ¤   ¤   ¤   ¤   PGPBigNumRef n1,
5e83ab ¤   ¤   ¤   ¤   PGPBigNumRef exponent1,
bd63f0 ¤   ¤   ¤   ¤   PGPBigNumRef n2,
a66ccf ¤   ¤   ¤   ¤   PGPBigNumRef exponent2,
b8acb4 ¤   ¤   ¤   ¤   PGPBigNumRef mod,
c9ea83 ¤   ¤   ¤   ¤   PGPBigNumRef dest );
b5af5a
0a20ba /* dest = 2^exp, modulo "mod" ··"mod" *must* be odd */
779ecb PGPError¤   PGPBigNumTwoExpMod(·
77fa20 ¤   ¤   ¤   ¤   PGPBigNumRef exponent,
53acb4 ¤   ¤   ¤   ¤   PGPBigNumRef mod,
49ea83 ¤   ¤   ¤   ¤   PGPBigNumRef dest );
89af5a
505c5b /* dest = gcd(a, b). ·The inputs may overlap arbitrarily. */
e1346c PGPError¤   PGPBigNumGCD( PGPBigNumRef a, PGPBigNumRef b,
1fea83 ¤   ¤   ¤   ¤   PGPBigNumRef dest );
23af5a
ae1893 /* dest = src^-1, modulo "mod". ·dest may be the same as src. */
353cf4 PGPError¤   PGPBigNumInv( PGPBigNumRef src,·
fcacb4 ¤   ¤   ¤   ¤   PGPBigNumRef mod,
05ea83 ¤   ¤   ¤   ¤   PGPBigNumRef dest );
40af5a
2daf5a
aa6138 /* Shift dest left "amt" places */
a8b5c5 PGPError¤   PGPBigNumLeftShift( PGPBigNumRef dest, PGPUInt32 amt );
9baf5a
8270f6 /* Shift dest right "amt" places, discarding low-order bits */
2c5afb PGPError¤   PGPBigNumRightShift( PGPBigNumRef dest, PGPUInt32 amt );
ecaf5a
d74dd1 /* right shift all low order 0-bits, return number of bits shifted */
cc0c5d PGPUInt16¤  PGPBigNumMakeOdd( PGPBigNumRef dest );
49af5a
37af5a
d2cbcf #if PRAGMA_IMPORT_SUPPORTED
e92ced #pragma import reset
ba7454 #endif
32af5a
8d1254 PGP_END_C_DECLARATIONS
e2af5a
f33e59 #endif¤ /* Included_pgpBigNum_h */
19af5a
38af5a
a4af5a
c6af5a
b5af5a
97af5a
d0af5a
c8af5a
2aaf5a
28af5a
c5af5a
41af5a
29af5a
b0af5a
3baf5a
--fa06 000549680434010029b Page 1 of pgpCBC.h
a70335 /*____________________________________________________________________________
974d27 ¤   pgpCBC.h
7367c5 ¤
e7c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
414b0f ¤   All rights reserved.
e467c5 ¤
3167c5 ¤
5caf5a
ecd949 ¤   $Id: pgpCBC.h,v 1.4.22.1 1998/11/12 03:23:30 heller Exp $
caf7f7 ____________________________________________________________________________*/
d106ef #ifndef Included_pgpCBC_h¤  /* [ */
d0a54a #define Included_pgpCBC_h
94af5a
23e603 #include "pgpSymmetricCipher.h"
89af5a
a9af5a
1b99c6 PGP_BEGIN_C_DECLARATIONS
5ecbcf #if PRAGMA_IMPORT_SUPPORTED
d7b981 #pragma import on
797454 #endif
ecaf5a
760335 /*____________________________________________________________________________
6e78b6 ¤   A CBC context requires use of a symmetric cipher which has been created
6e721e ¤   and whose key has been set. An error will be returned if this is not
8e0e0b ¤   the case.
e467c5 ¤
2b3757 ¤   After the call, the CBCContextRef "owns" the
c624cd ¤   symmetric ref and will dispose of it properly (even if an error
9fa3f7 ¤   occurs). ·The caller should no longer reference it.
10f7f7 ____________________________________________________________________________*/
8a89cf PGPError ¤  PGPNewCBCContext( PGPSymmetricCipherContextRef ref,
8c022f ¤   ¤   ¤   ¤   ¤   PGPCBCContextRef *outRef );
d8af5a
5daf5a
3b0335 /*____________________________________________________________________________
e5ea66 ¤   Disposal clears all data in memory before releasing it.
98f7f7 ____________________________________________________________________________*/
f6a04d PGPError ¤  PGPFreeCBCContext( PGPCBCContextRef ref );
18af5a
9caf5a
430335 /*____________________________________________________________________________
8c08cb ¤   Make an exact copy, including current state. ·Original is not changed.
cef7f7 ____________________________________________________________________________*/
4e7635 PGPError ¤  PGPCopyCBCContext( PGPCBCContextRef ref, PGPCBCContextRef *outRef );
1daf5a
f7af5a
bdaf5a
dc0335 /*____________________________________________________________________________
797242 ¤   IV size is implicit (same size as the symmetric cipher block size).
d9889c ¤   IV is *copied*.
ffeb3a ¤   Caller may want to destroy the original after passing it in.
c9f7f7 ____________________________________________________________________________*/
48bda7 PGPError ¤  PGPInitCBC( PGPCBCContextRef ref,
50b811 ¤   ¤   ¤   ¤   ¤   const void *key,
e632f6 ¤   ¤   ¤   ¤   ¤   const void *initializationVector );
29af5a
37af5a
f80335 /*____________________________________________________________________________
38b9a2 ¤   Call repeatedly to process arbitrary amounts of data. ·Each call must
2dfc8a ¤   have bytesIn be a multiple of the cipher block size.
31f7f7 ____________________________________________________________________________*/
d4ccfd PGPError ¤  PGPCBCEncrypt( PGPCBCContextRef ref,
4028b0 ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize bytesIn, void *out );
baae30 ¤   ¤   ¤   ¤   ¤
436755 PGPError ¤  PGPCBCDecrypt( PGPCBCContextRef ref,
db28b0 ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize bytesIn, void *out );
77af5a
8daf5a
d9af5a
cb0335 /*____________________________________________________________________________
696c7c ¤   Get the symmetric cipher being used for this CBC context.
541488 ¤   You can use this to determine useful things about the underlying cipher
--5d8b 001956861ac4010029b Page 2 of pgpCBC.h
f152ad ¤   such as its block size.
3bf7f7 ____________________________________________________________________________*/
e1589f PGPError ¤  PGPCBCGetSymmetricCipher( PGPCBCContextRef ref,
bdc44f ¤   ¤   ¤   ¤   ¤   PGPSymmetricCipherContextRef *outRef );
edaf5a
daaf5a
c8af5a
54cbcf #if PRAGMA_IMPORT_SUPPORTED
972ced #pragma import reset
1f7454 #endif
991254 PGP_END_C_DECLARATIONS
22af5a
07cde4 #endif /* ] Included_pgpCBC_h */
f2af5a
efaf5a
db7e4d /*__Editor_settings____
68af5a
644126 ¤   Local Variables:
8c7b17 ¤   tab-width: 4
d50e6c ¤   End:
f95f8c ¤   vi: ts=4 sw=4
239e9b ¤   vim: si
95d062 _____________________*/
--c506 0003d8a05434010029c Page 1 of pgpCFB.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
edb850 ¤   $Id: pgpCFB.h,v 1.5.22.1 1998/11/12 03:23:31 heller Exp $
75f7f7 ____________________________________________________________________________*/
8b50bc #ifndef Included_pgpCFB_h¤  /* [ */
b994e1 #define Included_pgpCFB_h
77af5a
24e603 #include "pgpSymmetricCipher.h"
a2af5a
b4af5a
c699c6 PGP_BEGIN_C_DECLARATIONS
6dcbcf #if PRAGMA_IMPORT_SUPPORTED
fdb981 #pragma import on
957454 #endif
2daf5a
ca0335 /*____________________________________________________________________________
f875e8 ¤   A CFB context requires use of a symmetric cipher which has been created
26721e ¤   and whose key has been set. An error will be returned if this is not
ed0e0b ¤   the case.
0667c5 ¤
cdbec1 ¤   After the call, the CFBRef "owns" the symmetric ref and will
1492da ¤   dispose of it properly (even if an error occurs).
37c260 ¤   The caller should no longer reference it.
ebf7f7 ____________________________________________________________________________*/
3bd164 PGPError ¤  PGPNewCFBContext( PGPSymmetricCipherContextRef ref,
131869 ¤   ¤   ¤   ¤   ¤   PGPUInt16 interleaveFactor,
35eee7 ¤   ¤   ¤   ¤   ¤   PGPCFBContextRef *outRef );
f2af5a
caaf5a
7f0335 /*____________________________________________________________________________
5aea66 ¤   Disposal clears all data in memory before releasing it.
2df7f7 ____________________________________________________________________________*/
793356 PGPError ¤  PGPFreeCFBContext( PGPCFBContextRef ref );
33af5a
1faf5a
da0335 /*____________________________________________________________________________
5308cb ¤   Make an exact copy, including current state. ·Original is not changed.
9bf7f7 ____________________________________________________________________________*/
3ff46b PGPError ¤  PGPCopyCFBContext( PGPCFBContextRef ref,
2deee7 ¤   ¤   ¤   ¤   ¤   PGPCFBContextRef *outRef );
f7af5a
52af5a
7caf5a
ec0335 /*____________________________________________________________________________
e87242 ¤   IV size is implicit (same size as the symmetric cipher block size).
0f889c ¤   IV is *copied*.
36eb3a ¤   Caller may want to destroy the original after passing it in.
a491e3 ¤   Calling this implicitly calls PGPResetCFB().
42f7f7 ____________________________________________________________________________*/
ca7f0f PGPError ¤  PGPInitCFB( PGPCFBContextRef ref,
c2b811 ¤   ¤   ¤   ¤   ¤   const void *key,
0e32f6 ¤   ¤   ¤   ¤   ¤   const void *initializationVector );
24af5a
bdaf5a
ee0335 /*____________________________________________________________________________
63380d ¤   Call repeatedly to process arbitrary amounts of data.
def7f7 ____________________________________________________________________________*/
cc59a2 PGPError ¤  PGPCFBEncrypt( PGPCFBContextRef ref,
0f28b0 ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize bytesIn, void *out );
4fae30 ¤   ¤   ¤   ¤   ¤
22f20a PGPError ¤  PGPCFBDecrypt( PGPCFBContextRef ref,
c828b0 ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize bytesIn, void *out );
1caf5a
4aaf5a
f6af5a
7a0335 /*____________________________________________________________________________
f53c9b ¤   Get the symmetric cipher being used for this CFB context.
3d1488 ¤   You can use this to determine useful things about the underlying cipher
--6cdd 001b650d4aa4010029c Page 2 of pgpCFB.h
f152ad ¤   such as its block size.
3bf7f7 ____________________________________________________________________________*/
ba9439 PGPError ¤  PGPCFBGetSymmetricCipher(
8ef288 ¤   ¤   ¤   ¤   ¤   PGPCFBContextRef ref,
16c44f ¤   ¤   ¤   ¤   ¤   PGPSymmetricCipherContextRef *outRef );
79af5a
72af5a
eaaf5a
f50335 /*____________________________________________________________________________
dc3e59 ¤   Reset the feedback mechanism to use whatever we have so far, plus previous
cf4636 ¤   bytes for a total of the cipher block size bytes. ·This effectively
97798c ¤   changes the cipher block boundary.
0cf7f7 ____________________________________________________________________________*/
05f90d PGPError ¤  PGPCFBSync( PGPCFBContextRef ref );
eeaf5a
73af5a
fcaf5a
170335 /*____________________________________________________________________________
9c5a52 ¤   Fetch random bytes from the cipher. ·Returns the actual number of
dd2108 ¤   random bytes obtained.
31f7f7 ____________________________________________________________________________*/
4c40c8 PGPError ¤  PGPCFBGetRandom( PGPCFBContextRef ref,
0d26ca ¤   ¤   ¤   ¤   ¤   PGPSize requestCount, void *out, PGPSize *outCount);
70ae30 ¤   ¤   ¤   ¤   ¤
bcae30 ¤   ¤   ¤   ¤   ¤
f20335 /*____________________________________________________________________________
237993 ¤   Make more random bytes available using the supplied salt, which must
86f942 ¤   be the same as the symmetric cipher block size.
44f7f7 ____________________________________________________________________________*/
d5cb76 PGPError ¤  PGPCFBRandomCycle( PGPCFBContextRef ref,
0e7dd6 ¤   ¤   ¤   ¤   ¤   const void *salt);
7fae30 ¤   ¤   ¤   ¤   ¤
85ae30 ¤   ¤   ¤   ¤   ¤
fb0335 /*____________________________________________________________________________
417993 ¤   Make more random bytes available using the supplied salt, which must
a0f942 ¤   be the same as the symmetric cipher block size.
09f7f7 ____________________________________________________________________________*/
169033 PGPError ¤  PGPCFBRandomWash( PGPCFBContextRef ref,
b2a75b ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize bytesIn );
e1af5a
85af5a
9acbcf #if PRAGMA_IMPORT_SUPPORTED
732ced #pragma import reset
117454 #endif
ff1254 PGP_END_C_DECLARATIONS
0caf5a
3944ef #endif /* ] Included_pgpCFB_h */
e6af5a
56af5a
267e4d /*__Editor_settings____
ffaf5a
404126 ¤   Local Variables:
d37b17 ¤   tab-width: 4
600e6c ¤   End:
b25f8c ¤   vi: ts=4 sw=4
d69e9b ¤   vim: si
b6d062 _____________________*/
--0f80 00037cb1e3c4010029d Page 1 of pgpEncode.h
a70335 /*____________________________________________________________________________
197e16 ¤   pgpEncode.h
6e67c5 ¤
c7c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
1a4b0f ¤   All rights reserved.
4e67c5 ¤
1919f0 ¤   This file contains the prototypes for functions which encode/decode files
7ba1f9 ¤   and buffers.
41af5a
18abae ¤   $Id: pgpEncode.h,v 1.101.10.1 1998/11/12 03:23:32 heller Exp $
75f7f7 ____________________________________________________________________________*/
68af5a
5be43e #ifndef Included_pgpEncode_h¤   /* [ */
3db853 #define Included_pgpEncode_h
37af5a
61e82c #include "pgpPubTypes.h"
05ec82 #include "pgpTLS.h"
d4af5a
47fa23 #if PRAGMA_ALIGN_SUPPORTED
b7af46 #pragma options align=mac68k
767454 #endif
88af5a
b938e5 /*
9a7d5c ·* The PGPEvent structure is used to notify clients of the encode API of
e08159 ·* various events.
df495d ·*/
80af5a
e21bc3 /* PGP Event types */
e1af5a
bdc6cc enum PGPEventType_
aebb36 {
5d8fcc ¤   kPGPEvent_NullEvent¤¤   ¤   = ·0,¤  ¤   /* Nothing happened */
794f82 ¤   kPGPEvent_InitialEvent¤ ¤   = ·1,¤  ¤   /* Final event */
5669d5 ¤   kPGPEvent_FinalEvent¤   ¤   = ·2,¤  ¤   /* Final event */
7dfae9 ¤   kPGPEvent_ErrorEvent¤   ¤   = ·3,¤  ¤   /* An error occurred */
0becc5 ¤   kPGPEvent_WarningEvent¤ ¤   = ·4,¤  ¤   /* Warning event */
7d0c3d ¤   kPGPEvent_EntropyEvent¤ ¤   = ·5,¤  ¤   /* More entropy is needed */
23ccee ¤   kPGPEvent_PassphraseEvent¤  = ·6,¤  ¤   /* A passphrase is needed */
ca4cd2 ¤   kPGPEvent_InsertKeyEvent¤   = ·7,¤  ¤   /* Smart card must be inserted */
5643bb ¤   kPGPEvent_AnalyzeEvent¤ ¤   = ·8,¤  ¤   /* Initial analysis event,
b165be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···before any output */
5950df ¤   kPGPEvent_RecipientsEvent¤  = ·9,¤  ¤   /* Recipient list report,
4565be ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···before any output */
f2222a ¤   kPGPEvent_KeyFoundEvent¤¤   = 10,¤  ¤   /* Key packet found */
2524c7 ¤   kPGPEvent_OutputEvent¤  ¤   = 11,¤  ¤   /* Output specification needed */
bed526 ¤   kPGPEvent_SignatureEvent¤   = 12,¤  ¤   /* Signature status report */
6638c2 ¤   kPGPEvent_BeginLexEvent¤¤   = 13,¤  ¤   /* Initial event per lexical unit*/
6a88e3 ¤   kPGPEvent_EndLexEvent¤  ¤   = 14,¤  ¤   /* Final event per lexical unit */
28268a ¤   kPGPEvent_RecursionEvent¤   = 15,¤  ¤   /* Notification of recursive
a90495 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···job creation */
c7569e ¤   kPGPEvent_DetachedSignatureEvent = 16,¤ /* Need input for verification of
4f830a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···detached signature */
1e43dd ¤   kPGPEvent_KeyGenEvent¤  ¤   = 17,¤  ¤   /* Key generation progress */
3367c5 ¤
9c2b07 ¤   kPGPEvent_KeyServerEvent¤   = 18,¤  ¤   /* Key Server progress */
be7f61 ¤   kPGPEvent_KeyServerSignEvent= 19,¤  ¤   /* Key Server passphrase */
6f1d14 ¤   kPGPEvent_KeyServerTLSEvent¤= 20,¤  ¤   /* Key Server TLS event */
bacf89 ¤   kPGPEvent_KeyServerIdleEvent= 21,¤  ¤   /* Idle during keyserver call */
e367c5 ¤
416c05 ¤   kPGPEvent_SocketsIdleEvent¤ = 22,¤  ¤   /* Idle during sockets */
210386 ¤   kPGPEvent_DecryptionEvent¤  = 23,¤  ¤   /* Decryption data report */
a6554a ¤   PGP_ENUM_FORCE( PGPEventType_ )
9f82f7 };
e21574 PGPENUM_TYPEDEF( PGPEventType_, PGPEventType );
ceaf5a
1aaf5a
f1329e /* PGP Analyze event callback codes */
97af5a
729b2e enum PGPAnalyzeType_
d4bb36 {
0238d6 ¤   kPGPAnalyze_Encrypted¤  ¤   ¤   = ·0,¤  /* Encrypted message */
376971 ¤   kPGPAnalyze_Signed¤ ¤   ¤   ¤   = ·1,¤  /* Signed message */
--322a 0008ac2dbf84010029d Page 2 of pgpEncode.h
09289d ¤   kPGPAnalyze_DetachedSignature¤  = ·2,¤  /* Detached signature */
138428 ¤   kPGPAnalyze_Key¤¤   ¤   ¤   ¤   = ·3,¤  /* Key data */
3898d1 ¤   kPGPAnalyze_Unknown¤¤   ¤   ¤   = ·4,¤  /* Non-pgp message */
d4af5a
3e5faa ¤   PGP_ENUM_FORCE( PGPAnalyzeType_ )
4f82f7 };
b33bc6 PGPENUM_TYPEDEF( PGPAnalyzeType_, PGPAnalyzeType );
fcaf5a
0eaf5a
95af5a
e0af5a
de21d4 /* Individual event information structs, combined as a union in PGPEvent */
95af5a
c78e2a typedef struct PGPEventNullData_
00bb36 {
241357 ¤   PGPFileOffset¤  ¤   ¤   bytesWritten;
87f022 ¤   PGPFileOffset¤  ¤   ¤   bytesTotal;
afe25f } PGPEventNullData;
16af5a
6e1289 typedef struct PGPEventErrorData_
e8bb36 {
42971f ¤   PGPError¤   ¤   ¤   ¤   error;
5bc004 ¤   void¤   ¤   ¤   ¤   ···*errorArg;
6452d6 } PGPEventErrorData;
4daf5a
5f4273 typedef struct PGPEventWarningData_
0ebb36 {
98080d ¤   PGPError¤   ¤   ¤   ¤   warning;
e417ef ¤   void¤   ¤   ¤   ¤   ···*warningArg;
d9b975 } PGPEventWarningData;
4aaf5a
8c999f typedef struct PGPEventEntropyData_
48bb36 {
6d2c0f ¤   PGPUInt32¤  ¤   ¤   ¤   entropyBitsNeeded;
be6299 } PGPEventEntropyData;
31af5a
831cca typedef struct PGPEventPassphraseData_
c1bb36 {
96911b ¤   PGPBoolean¤ ¤   ¤   ¤   fConventional;
c22dee ¤   PGPKeySetRef¤   ¤   ¤   keyset;
34dc25 } PGPEventPassphraseData;
43af5a
062e63 typedef struct PGPEventRecipientsData_
13bb36 {
58b6c9 ¤   PGPKeySetRef¤   ¤   ¤   recipientSet;
0b467c ¤   PGPUInt32¤  ¤   ¤   ¤   conventionalPassphraseCount;
718bca ¤   PGPUInt32¤  ¤   ¤   ¤   keyCount;
d39367 ¤   PGPKeyID const *¤   ¤   keyIDArray;
a5ee8c } PGPEventRecipientsData;
95af5a
0b056b typedef struct PGPEventKeyFoundData_
6cbb36 {
ce4d7f ¤   PGPKeySetRef¤   ¤   ¤   keySet;
dc04bf } PGPEventKeyFoundData;
ceaf5a
59ca0f typedef struct PGPEventSignatureData_
18bb36 {
7e2b4d ¤   PGPKeyID¤   ¤   ¤   ¤   signingKeyID;
f7c8a8 ¤   PGPKeyRef¤  ¤   ¤   ¤   signingKey;
504957 ¤   PGPBoolean¤ ¤   ¤   ¤   checked;
a6dc39 ¤   PGPBoolean¤ ¤   ¤   ¤   verified;
3ba821 ¤   PGPBoolean¤ ¤   ¤   ¤   keyRevoked;
0efa64 ¤   PGPBoolean¤ ¤   ¤   ¤   keyDisabled;
c0fae1 ¤   PGPBoolean¤ ¤   ¤   ¤   keyExpired;
fc2728 ¤   PGPBoolean¤ ¤   ¤   ¤   keyMeetsValidityThreshold;
e7f7d5 ¤   PGPValidity¤¤   ¤   ¤   keyValidity;
068983 ¤   PGPTime¤¤   ¤   ¤   ¤   creationTime;
243ebe } PGPEventSignatureData;
a9af5a
fcad35 typedef struct PGPEventDecryptionData_
4ebb36 {
8a81cf ¤   PGPCipherAlgorithm¤ ¤   cipherAlgorithm;
--ef1a 0000284b8b24010029d Page 3 of pgpEncode.h
746dda } PGPEventDecryptionData;
53af5a
8ddf08 typedef struct PGPEventAnalyzeData_
bfbb36 {
c89d81 ¤   PGPAnalyzeType¤ ¤   ¤   sectionType;
fb240e } PGPEventAnalyzeData;
72af5a
f740e5 typedef struct PGPEventOutputData_
95bb36 {
678dc4 ¤   PGPUInt32¤  ¤   ¤   ¤   messageType;
0b53ac ¤   char¤   ¤   ¤   ¤   ···*suggestedName;
400993 ¤   PGPBoolean¤ ¤   ¤   ¤   forYourEyesOnly;
158ece } PGPEventOutputData;
92af5a
5fc75f typedef struct PGPEventBeginLexData_
b8bb36 {
3556c6 ¤   PGPUInt32¤  ¤   ¤   ¤   sectionNumber;
26feb8 ¤   PGPSize¤¤   ¤   ¤   ¤   sectionOffset;
4fc68b } PGPEventBeginLexData;
86af5a
d60bdc typedef struct PGPEventEndLexData_
95bb36 {
f856c6 ¤   PGPUInt32¤  ¤   ¤   ¤   sectionNumber;
e2c5f7 } PGPEventEndLexData;
ceaf5a
3827ed typedef struct PGPEventKeyGenData_
efbb36 {
413ef5 ¤   PGPUInt32¤  ¤   ¤   ¤   state;
a7e9c6 } PGPEventKeyGenData;
4aaf5a
262e95 typedef struct PGPEventKeyServerData_
ebbb36 {
802719 ¤   PGPKeyServerRef¤¤   ¤   keyServerRef;
e663aa ¤   PGPUInt32¤  ¤   ¤   ¤   state;¤ ¤   ¤   /* PGPKeyServerState */
31da24 } PGPEventKeyServerData;
1faf5a
4a331e typedef struct PGPEventKeyServerSignData_
e8bb36 {
ae2719 ¤   PGPKeyServerRef¤¤   ¤   keyServerRef;
6b3444 } PGPEventKeyServerSignData;
95af5a
142eb8 typedef struct PGPEventKeyServerTLSData_
32bb36 {
282719 ¤   PGPKeyServerRef¤¤   ¤   keyServerRef;
a663aa ¤   PGPUInt32¤  ¤   ¤   ¤   state;¤ ¤   ¤   /* PGPKeyServerState */
f583e0 ¤   PGPtlsSessionRef¤   ¤   tlsSession;
9e6bd8 } PGPEventKeyServerTLSData;
43af5a
e90c17 typedef struct PGPEventKeyServerIdleData_
04bb36 {
002719 ¤   PGPKeyServerRef¤¤   ¤   keyServerRef;
fa0b4d } PGPEventKeyServerIdleData;
9aaf5a
b1af5a
d138e5 /*
7bc0e1 ·* The following events have no event-specific data defined for them:
e5b199 ·*¤ kPGPEvent_InsertKeyEvent
734510 ·*¤ kPGPEvent_RecursionEvent
668702 ·*¤ kPGPEvent_DetachedSignatureEvent
4849e7 ·*¤ kPGPEvent_InitialEvent
f10f80 ·*¤ kPGPEvent_FinalEvent
500816 ·*¤ kPGPEvent_SocketsIdleEvent
67495d ·*/
39af5a
c8f970 /* Union of all event data structures above */
71fc43 typedef union PGPEventData_
22bb36 {
380878 ¤   PGPEventNullData¤   ¤   ¤   nullData;
5ad6ad ¤   PGPEventErrorData¤  ¤   ¤   errorData;
21b934 ¤   PGPEventWarningData¤¤   ¤   warningData;
832ef5 ¤   PGPEventEntropyData¤¤   ¤   entropyData;
0217b3 ¤   PGPEventPassphraseData¤ ¤   passphraseData;
--3fb4 000dae593994010029d Page 4 of pgpEncode.h
a264c5 ¤   PGPEventRecipientsData¤ ¤   recipientsData;
7cc763 ¤   PGPEventKeyFoundData¤   ¤   keyFoundData;
2dc1a1 ¤   PGPEventSignatureData¤  ¤   signatureData;
068a9f ¤   PGPEventDecryptionData¤ ¤   decryptionData;
69bf43 ¤   PGPEventAnalyzeData¤¤   ¤   analyzeData;
69d6d8 ¤   PGPEventOutputData¤ ¤   ¤   outputData;
c5e027 ¤   PGPEventBeginLexData¤   ¤   beginLexData;
14d944 ¤   PGPEventEndLexData¤ ¤   ¤   endLexData;
229bed ¤   PGPEventKeyGenData¤ ¤   ¤   keyGenData;
82ac1b ¤   PGPEventKeyServerData¤  ¤   keyServerData;
487f52 ¤   PGPEventKeyServerSignData¤  keyServerSignData;
ca3735 ¤   PGPEventKeyServerTLSData¤   keyServerTLSData;
d78b00 ¤   PGPEventKeyServerIdleData¤  keyServerIdleData;
eaa6ef } PGPEventData;
b9af5a
266422 /* Refs to internal "job" structure */
727f6e typedef struct PGPJob *¤¤   ¤   ¤   PGPJobRef;
43af5a
279e52 #define¤kInvalidPGPJobRef¤  ¤   ¤   ((PGPJobRef) NULL)
0f9217 #define PGPJobRefIsValid( ref )¤¤   ( (ref) != kInvalidPGPJobRef )
12af5a
7d2cc6 /* PGPEvent structure */
e6af5a
55cf82 struct PGPEvent
2abb36 {
234ee6 ¤   PGPVersion¤ ¤   ¤   ¤   ·version;¤  ¤   /* Version of event structure */
2072ad ¤   struct PGPEvent_¤   ¤   *nextEvent;¤¤   /* Allow lists of events */
e877bb ¤   PGPJobRef¤  ¤   ¤   ¤   ·job;¤  ¤   ¤   /* Associated with what job */
43f044 ¤   PGPEventType¤   ¤   ¤   ·type;¤ ¤   ¤   /* Type of event */
0243e2 ¤   PGPEventData¤   ¤   ¤   ·data;¤ ¤   ¤   /* Event specific data */
fc82f7 };
49b660 typedef struct PGPEvent PGPEvent;
e7af5a
63af5a
95fa23 #if PRAGMA_ALIGN_SUPPORTED
c57c46 #pragma options align=reset
537454 #endif
65af5a
4899c6 PGP_BEGIN_C_DECLARATIONS
9daf5a
86cbcf #if PRAGMA_IMPORT_SUPPORTED
0cb981 #pragma import on
a77454 #endif
42af5a
1d38e5 /*
472f9f **¤ Functions to encode and decode. The variable parameters are one or more
ded5df **¤ PGPOptionListRef's which describe the inputs, outputs, and options.
f57fe0 */
e8af5a
9e51a1 PGPError ¤  ¤   PGPEncode(PGPContextRef context,
b0a0f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
7d83ef PGPError ¤  ¤   PGPDecode(PGPContextRef context,
dba0f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
faaf5a
1695c8 PGPError ¤  ¤   PGPAddJobOptions(PGPJobRef job,
17a0f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
79af5a
a9cbcf #if PRAGMA_IMPORT_SUPPORTED
662ced #pragma import reset
f27454 #endif
b31254 PGP_END_C_DECLARATIONS
6faf5a
00b310 #endif /* ] Included_pgpEncode_h */
6daf5a
b3af5a
287e4d /*__Editor_settings____
b6af5a
c94126 ¤   Local Variables:
d47b17 ¤   tab-width: 4
a40e6c ¤   End:
035f8c ¤   vi: ts=4 sw=4
da9e9b ¤   vim: si
--8339 001177e2b6c4010029d Page 5 of pgpEncode.h
17d062 _____________________*/
--c905 00045545a1e4010029e Page 1 of pgpErrors.h
a70335 /*____________________________________________________________________________
6933f3 ¤   pgpErrors.h
9aaf5a
61c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
4d4b0f ¤   All rights reserved.
90af5a
e8a564 ¤   Error codes for all PGP errors can be found in this file.
11af5a
3fdeb6 ¤   $Id: pgpErrors.h,v 1.80.10.1 1998/11/12 03:23:33 heller Exp $
f4f7f7 ____________________________________________________________________________*/
66f687 #ifndef Included_pgpErrors_h¤   /* [ */
ebf5b6 #define Included_pgpErrors_h
0caf5a
2fe82c #include "pgpPubTypes.h"
2baf5a
cbaf5a
462b62 #include "pgpPFLErrors.h"
c9af5a
db9c51 #define kPGPErrorRange¤ ¤   1000
b4af5a
8b903b enum PGPError_
5bbb36 {
a5d8af ¤   /*
6a13ab ¤   ¤   NOTE: error code values must not be changed;
1d8d72 ¤   ¤   compiled client code depends on them.
fc9faa ¤   */
e9223f ¤   kPGPError_FirstError¤   ¤   = -11500,
757fed ¤   kPGPError_Last¤ ¤   ¤   ¤   = -10500,
ecaf5a
7b519c ¤   kPGPError_BadPassphrase¤¤   = -11500,
d4f899 ¤   kPGPError_OptionNotFound¤   = -11499,
8baf5a
76fbbe /* Errors from pgpEncode */
bb5785 ¤   kPGPError_RedundantOptions¤ = -11498,
eda476 ¤   kPGPError_KeyRevoked¤   ¤   = -11497,
abe5bf ¤   kPGPError_KeyExpired¤   ¤   = -11496,
3e9808 ¤   kPGPError_KeyDisabled¤  ¤   = -11495,
e5a2c0 ¤   kPGPError_KeyInvalid¤   ¤   = -11494,
1f5b01 ¤   kPGPError_KeyUnusableForEncryption¤ ¤   ¤   = -11493,
bad84f ¤   kPGPError_KeyUnusableForSignature¤  ¤   ¤   = -11492,
4be31e ¤   kPGPError_OutputBufferTooSmall¤ ¤   ¤   ¤   = -11491,
06b312 ¤   kPGPError_InconsistentEncryptionAlgorithms¤ = -11490,·
89730f ¤   kPGPError_MissingPassphrase¤¤   ¤   ¤   ¤   = -11489,
f90485 ¤   kPGPError_CombinedConventionalAndPublicEncryption= -11488,·
fd6a91 ¤   kPGPError_DetachedSignatureWithoutSigningKey= -11487,·
e55719 ¤   kPGPError_DetachedSignatureWithEncryption¤  = -11486,·
1843ed ¤   kPGPError_NoInputOptions¤   ¤   ¤   ¤   ¤   = -11485,
4ec72a ¤   kPGPError_MultipleInputOptions¤ ¤   ¤   ¤   = -11484,
d963a8 ¤   kPGPError_InputFile¤¤   ¤   ¤   ¤   ¤   ¤   = -11483,
70d5e8 ¤   kPGPError_NoOutputOptions¤  ¤   ¤   ¤   ¤   = -11482,
e9cc61 ¤   kPGPError_MultipleOutputOptions¤¤   ¤   ¤   = -11481,
d4368d ¤   kPGPError_MissingEventHandler¤  ¤   ¤   ¤   = -11480,
9cace5 ¤   kPGPError_MissingKeySet¤¤   ¤   ¤   ¤   ¤   = -11479,
6a0ec3 ¤   kPGPError_DetachedSignatureFound¤   ¤   ¤   = -11478,
64e9ae ¤   kPGPError_NoDecryptionKeyFound¤ ¤   ¤   ¤   = -11477,
7e3ee2 ¤   kPGPError_CorruptSessionKey¤¤   ¤   ¤   ¤   = -11476,
87b8b6 ¤   kPGPError_SkipSection¤  ¤   ¤   ¤   ¤   ¤   = -11475,
d6b6da ¤   kPGPError_Interrupted¤  ¤   ¤   ¤   ¤   ¤   = -11474,
a2c880 ¤   kPGPError_TooManyARRKs¤ ¤   ¤   ¤   ¤   ¤   = -11473,
747dd1 ¤   kPGPError_KeyUnusableForDecryption¤ ¤   ¤   = -11472,
7867c5 ¤
87f7f4 ¤   kPGPError_IncompatibleAPI¤  ¤   ¤   ¤   ¤   = -11460,
d1af5a
cc0e3e /* misc errors */
694d7d ¤   kPGPError_NotMacBinary¤ ¤   ¤   ¤   ¤   ¤   = -11450,
70e970 ¤   kPGPError_NoMacBinaryTranslationAvailable¤  = -11449,
aa35bb ¤   kPGPError_BadSignature¤ ¤   ¤   ¤   ¤   ¤   = -11448,
ed1123 ¤   kPGPError_CAPIUnsupportedKey¤   ¤   ¤   ¤   = -11447,
bbaf5a
ad122e /* filter errors */
7caf5a
45e63b ¤   kPGPError_InconsistentFilterClasses¤¤   ¤   = -11440,
--7745 00082b616324010029e Page 2 of pgpErrors.h
e3271c ¤   kPGPError_UnsupportedLDAPFilter¤¤   ¤   ¤   = -11439,
7b2b4d ¤   kPGPError_UnsupportedHKPFilter¤ ¤   ¤   ¤   = -11438,
4ef071 ¤   kPGPError_UnknownFilterType¤¤   ¤   ¤   ¤   = -11437,
3f8452 ¤   kPGPError_InvalidFilterParameter¤   ¤   ¤   = -11436,
aaaf5a
38bf0c /* old errors: */
efaf5a
39b812 ¤   kPGPError_OutOfRings¤   ¤   ¤   ¤   ¤   ¤   = -11420,
93494a ¤   kPGPError_BadHashNumber¤¤   ¤   ¤   ¤   ¤   = -11419,
da6319 ¤   kPGPError_BadCipherNumber¤  ¤   ¤   ¤   ¤   = -11418,
faf11e ¤   kPGPError_BadKeyLength¤ ¤   ¤   ¤   ¤   ¤   = -11417,
0b0742 ¤   kPGPError_SizeAdviseFailure¤¤   ¤   ¤   ¤   = -11416,
7b1622 ¤   kPGPError_ConfigParseFailure¤   ¤   ¤   ¤   = -11415,
a4a1be ¤   kPGPError_ConfigParseFailureBadFunction¤¤   = -11414,
21b197 ¤   kPGPError_ConfigParseFailureBadOptions¤ ¤   = -11413,
260d5f ¤   kPGPError_KeyIsLocked¤  ¤   ¤   ¤   ¤   ¤   = -11412,
103a88 ¤   kPGPError_CantDecrypt¤  ¤   ¤   ¤   ¤   ¤   = -11411,
157ede ¤   kPGPError_UnknownString2Key¤¤   ¤   ¤   ¤   = -11410,
eaedb7 ¤   kPGPError_BadSessionKeySize¤¤   ¤   ¤   ¤   = -11409,
ab8c8e ¤   kPGPError_UnknownVersion¤   ¤   ¤   ¤   ¤   = -11408,
a63108 ¤   kPGPError_BadSessionKeyAlgorithm¤   ¤   ¤   = -11407,
61a57f ¤   kPGPError_UnknownSignatureType¤ ¤   ¤   ¤   = -11406,
b78ab4 ¤   kPGPError_BadSignatureSize¤ ¤   ¤   ¤   ¤   = -11405,
655822 ¤   kPGPError_SignatureBitsWrong¤   ¤   ¤   ¤   = -11404,
24b5c3 ¤   kPGPError_ExtraDateOnSignature¤ ¤   ¤   ¤   = -11403,
962c59 ¤   kPGPError_SecretKeyNotFound¤¤   ¤   ¤   ¤   = -11402,
94c781 ¤   kPGPError_AdditionalRecipientRequestKeyNotFound¤= -11401,
b9d587 ¤   kPGPError_InvalidCommit¤¤   ¤   ¤   ¤   ¤   = -11400,
902423 ¤   kPGPError_CantHash¤ ¤   ¤   ¤   ¤   ¤   ¤   = -11399,
9b34e3 ¤   kPGPError_UnbalancedScope¤  ¤   ¤   ¤   ¤   = -11398,
993924 ¤   kPGPError_WrongScope¤   ¤   ¤   ¤   ¤   ¤   = -11397,
c76535 ¤   kPGPError_FIFOReadError¤¤   ¤   ¤   ¤   ¤   = -11396,
6128a9 ¤   kPGPError_RandomSeedTooSmall¤   ¤   ¤   ¤   = -11395,
72067a ¤   kPGPError_EnvPriorityTooLow¤¤   ¤   ¤   ¤   = -11394,
91797c ¤   kPGPError_UnknownCharMap¤   ¤   ¤   ¤   ¤   = -11393,
df65da ¤   kPGPError_AsciiParseIncomplete¤ ¤   ¤   ¤   = -11392,
0eeb15 ¤   kPGPError_BadPacket¤¤   ¤   ¤   ¤   ¤   ¤   = -11391,
12af5a
eebfb5 ¤   kPGPError_TroubleKeySubKey¤ ¤   ¤   ¤   ¤   = -11390,
2e470b ¤   kPGPError_TroubleSigSubKey¤ ¤   ¤   ¤   ¤   = -11389,
0cc57d ¤   kPGPError_TroubleBadTrust¤  ¤   ¤   ¤   ¤   = -11388,
59385c ¤   kPGPError_TroubleUnknownPacketByte¤ ¤   ¤   = -11387,
de1e53 ¤   kPGPError_TroubleUnexpectedSubKey¤  ¤   ¤   = -11386,
35cdc9 ¤   kPGPError_TroubleUnexpectedName¤¤   ¤   ¤   = -11385,
7ac5ae ¤   kPGPError_TroubleUnexpectedSignature¤   ¤   = -11384,
100a8e ¤   kPGPError_TroubleUnexpectedUnknown¤ ¤   ¤   = -11383,
53cedf ¤   kPGPError_TroubleUnexpectedTrust¤   ¤   ¤   = -11382,
90bca3 ¤   kPGPError_TroubleKeyTooBig¤ ¤   ¤   ¤   ¤   = -11381,
18342f ¤   kPGPError_TroubleSecretKeyTooBig¤   ¤   ¤   = -11380,
0d2b74 ¤   kPGPError_TroubleNameTooBig¤¤   ¤   ¤   ¤   = -11379,
fbaa90 ¤   kPGPError_TroubleSignatureTooBig¤   ¤   ¤   = -11378,
215990 ¤   kPGPError_TroubleUnknownTooBig¤ ¤   ¤   ¤   = -11377,
fcee3d ¤   kPGPError_TroubleDuplicateKeyID¤¤   ¤   ¤   = -11376,
8751e9 ¤   kPGPError_TroubleDuplicateKey¤  ¤   ¤   ¤   = -11375,
64adb1 ¤   kPGPError_TroubleDuplicateSecretKey¤¤   ¤   = -11374,
6d2a0e ¤   kPGPError_TroubleDuplicateName¤ ¤   ¤   ¤   = -11373,
d397e5 ¤   kPGPError_TroubleDuplicateSignature¤¤   ¤   = -11372,
b0ab10 ¤   kPGPError_TroubleDuplicateUnknown¤  ¤   ¤   = -11371,
9caf0d ¤   kPGPError_TroubleBareKey¤   ¤   ¤   ¤   ¤   = -11370,
3a4386 ¤   kPGPError_TroubleVersionBugPrev¤¤   ¤   ¤   = -11369,
62a6b3 ¤   kPGPError_TroubleVersionBugCur¤ ¤   ¤   ¤   = -11368,
f46fe5 ¤   kPGPError_TroubleOldSecretKey¤  ¤   ¤   ¤   = -11367,
abaddf ¤   kPGPError_TroubleNewSecretKey¤  ¤   ¤   ¤   = -11366,
b4f51f ¤   kPGPError_TroubleImportingNonexportableSignature= -11365,
5faf5a
cdd8af ¤   /*
ca4c93 ¤   ·* The set of errors in this range are the ones which will NOT abort
13d329 ¤   ·* a keyring check operation. ·These errors just make us skip the key
dcb3b9 ¤   ·* and go on to the next.
7fa4e3 ¤   ·*/
2bf4e0 kPGPError_KEY_MIN¤  ¤   ¤   ¤   ¤   ¤   ¤   = -11350,
827c91 ¤   kPGPError_KEY_LONG¤ ¤   ¤   ¤   ¤   ¤   ¤   = kPGPError_KEY_MIN,
--30ae 000f7bcbea34010029e Page 3 of pgpErrors.h
d53886 ¤   kPGPError_KeyPacketTruncated¤   ¤   ¤   ¤   = -11349,
fa618d ¤   kPGPError_UnknownKeyVersion¤¤   ¤   ¤   ¤   = -11348,
b5cb15 ¤   kPGPError_UnknownPublicKeyAlgorithm¤¤   ¤   = -11347,
f6ee57 ¤   kPGPError_MalformedKeyModulus¤  ¤   ¤   ¤   = -11346,
d6e850 ¤   kPGPError_MalformedKeyExponent¤ ¤   ¤   ¤   = -11345,
e0924d ¤   kPGPError_RSAPublicModulusIsEven¤   ¤   ¤   = -11344,
84fbed ¤   kPGPError_RSAPublicExponentIsEven¤  ¤   ¤   = -11343,
587939 ¤   kPGPError_MalformedKeyComponent¤¤   ¤   ¤   = -11342,
e318cb ¤   kPGPError_KeyTooLarge¤  ¤   ¤   ¤   ¤   ¤   = -11341,
06367f ¤   kPGPError_PublicKeyTooSmall¤¤   ¤   ¤   ¤   = -11340,
3d4b1c ¤   kPGPError_PublicKeyTooLarge¤¤   ¤   ¤   ¤   = -11339,
017e70 ¤   kPGPError_PublicKeyUnimplemented¤   ¤   ¤   = -11338,
8c2c36 kPGPError_KEY_MAX¤  ¤   ¤   ¤   = kPGPError_PublicKeyUnimplemented,
abaf5a
74af5a
774b78 /* kPGPError_SIG_MAX */
690b9d ¤   kPGPError_SIG_LONG¤ ¤   ¤   ¤   ¤   ¤   ¤   = -11330,
2eef6f ¤   kPGPError_TruncatedSignature¤   ¤   ¤   ¤   = -11329,
ca83fb ¤   kPGPError_MalformedSignatureInteger¤¤   ¤   = -11328,
426ac7 ¤   kPGPError_UnknownSignatureAlgorithm¤¤   ¤   = -11327,
81197c ¤   kPGPError_ExtraSignatureMaterial¤   ¤   ¤   = -11326,
8cbfaf ¤   kPGPError_UnknownSignatureVersion¤  ¤   ¤   = -11325,
39a730 ¤   kPGPError_RevocationKeyNotFound¤¤   ¤   ¤   = -11324,
32e5f8 /* kPGPError_SIG_MIN */
a5af5a
b2f8d6 /* ·kPGPError_KEYDB_MAX */
868977 ¤   kPGPError_OutOfEntropy¤ ¤   ¤   ¤   ¤   ¤   = -11320,
9e8a10 ¤   kPGPError_ItemIsReadOnly¤   ¤   ¤   ¤   ¤   = -11319,
579c89 ¤   kPGPError_InvalidProperty¤  ¤   ¤   ¤   ¤   = -11318,
571869 ¤   kPGPError_FileCorrupt¤  ¤   ¤   ¤   ¤   ¤   = -11317,
0f2ed3 ¤   kPGPError_DuplicateCert¤¤   ¤   ¤   ¤   ¤   = -11316,
7efdb6 ¤   kPGPError_DuplicateUserID¤  ¤   ¤   ¤   ¤   = -11315,
f74157 ¤   kPGPError_CertifyingKeyDead¤¤   ¤   ¤   ¤   = -11314,
c95a53 ¤   kPGPError_ItemWasDeleted¤   ¤   ¤   ¤   ¤   = -11313,
c7fc6e ¤   kPGPError_KeyDBMismatch¤¤   ¤   ¤   ¤   ¤   = -11312,
4c88fa /* kPGPError_KEYDB_MIN = kPGPError_KeyDBMismatch */
9caf5a
3f5610 /* kPGPError_SERVER_MAX */
eb97bb ¤   kPGPError_ServerInProgress¤ ¤   ¤   ¤   ¤   = -11300,
7249bf ¤   kPGPError_ServerOperationNotSupported¤  ¤   = -11299,
9e79a7 ¤   kPGPError_ServerInvalidProtocol¤¤   ¤   ¤   = -11298,
489895 ¤   kPGPError_ServerRequestFailed¤  ¤   ¤   ¤   = -11297,
bf17cc ¤   kPGPError_ServerOpen¤   ¤   ¤   ¤   ¤   ¤   = -11296,
8f1977 ¤   kPGPError_ServerNotOpen¤¤   ¤   ¤   ¤   ¤   = -11295,
bcf242 ¤   kPGPError_ServerKeyAlreadyExists¤   ¤   ¤   = -11294,
e80541 ¤   kPGPError_ServerNotInitialized¤ ¤   ¤   ¤   = -11293,
e82fa7 ¤   kPGPError_ServerPartialAddFailure¤  ¤   ¤   = -11292,
23a14f ¤   kPGPError_ServerCorruptKeyBlock¤¤   ¤   ¤   = -11291,
66fb95 ¤   kPGPError_ServerUnknownResponse¤¤   ¤   ¤   = -11290,
42ec78 ¤   kPGPError_ServerTimedOut¤   ¤   ¤   ¤   ¤   = -11289,
2ba067 ¤   kPGPError_ServerOpenFailed¤ ¤   ¤   ¤   ¤   = -11288,
2866c3 ¤   kPGPError_ServerAuthorizationRequired¤  ¤   = -11287,
394955 ¤   kPGPError_ServerAuthorizationFailed¤¤   ¤   = -11286,
1a8ef2 ¤   kPGPError_ServerSearchFailed¤   ¤   ¤   ¤   = -11285,
8659ae ¤   kPGPError_ServerPartialSearchResults¤   ¤   = -11284,
6f83ef ¤   kPGPError_ServerBadKeysInSearchResults¤ ¤   = -11283,
1780f5 ¤   kPGPError_ServerKeyFailedPolicy¤¤   ¤   ¤   = -11282,
e169c6 ¤   kPGPError_ServerOperationRequiresTLS¤   ¤   = -11281,
235d5d ¤   kPGPError_ServerNoStaticStorage¤¤   ¤   ¤   = -11280,
89af5a
0ea517 /* TLS errors */
c7a90d ¤   kPGPError_TLSUnexpectedClose¤   ¤   ¤   ¤   = -11250,
7104e8 ¤   kPGPError_TLSProtocolViolation¤ ¤   ¤   ¤   = -11249,
fdbf84 ¤   kPGPError_TLSVersionUnsupported¤¤   ¤   ¤   = -11248,
9e888c ¤   kPGPError_TLSWrongState¤¤   ¤   ¤   ¤   ¤   = -11247,
9c83e5 ¤   kPGPError_TLSAlertReceived¤ ¤   ¤   ¤   ¤   = -11246,
e507c9 ¤   kPGPError_TLSKeyUnusable¤   ¤   ¤   ¤   ¤   = -11245,
85de96 ¤   kPGPError_TLSNoCommonCipher¤¤   ¤   ¤   ¤   = -11244,
390f7e ¤   kPGPError_TLSWouldBlock¤¤   ¤   ¤   ¤   ¤   = -11243,
1286a8 ¤   kPGPError_TLSRcvdHandshakeRequest¤  ¤   ¤   = -11242,
65af5a
f718fd /* X509 certificate errors */
--3288 0011a0533c04010029e Page 4 of pgpErrors.h
454bd5 ¤   kPGPError_X509NeededCertNotAvailable¤   ¤   = -11240,
acd6e4 ¤   kPGPError_X509SelfSignedCert¤   ¤   ¤   ¤   = -11239,
d1126c ¤   kPGPError_X509InvalidCertificateSignature¤  = -11238,
56f738 ¤   kPGPError_X509InvalidCertificateFormat¤ ¤   = -11237,
f0af5a
bb83d9 ¤   kPGPError_BigNumNoInverse¤  ¤   ¤   ¤   ¤   = -11150,
9967c5 ¤
450b92 /* PGPSockets errors */
e422fc ¤   kPGPError_SocketsNetworkDown¤   ¤   ¤   ¤   = -11100,
6a967f ¤   kPGPError_SocketsNotInitialized¤¤   ¤   ¤   = -11099,
7eb290 ¤   kPGPError_SocketsInProgress¤¤   ¤   ¤   ¤   = -11098,
67e693 ¤   kPGPError_SocketsNotConnected¤  ¤   ¤   ¤   = -11097,
1e7e37 ¤   kPGPError_SocketsNotBound¤  ¤   ¤   ¤   ¤   = -11096,
1b286d ¤   kPGPError_SocketsOperationNotSupported¤ ¤   = -11095,
9652f5 ¤   kPGPError_SocketsProtocolNotSupported¤  ¤   = -11094,
4d0e96 ¤   kPGPError_SocketsAddressFamilyNotSupported¤ = -11093,
f01a26 ¤   kPGPError_SocketsNotASocket¤¤   ¤   ¤   ¤   = -11092,
8906a3 ¤   kPGPError_SocketsAddressInUse¤  ¤   ¤   ¤   = -11091,
bdb503 ¤   kPGPError_SocketsBufferOverflow¤¤   ¤   ¤   = -11090,
d3920b ¤   kPGPError_SocketsListenQueueFull¤   ¤   ¤   = -11089,
7dc484 ¤   kPGPError_SocketsAddressNotAvailable¤   ¤   = -11088,
0f15ed ¤   kPGPError_SocketsAlreadyConnected¤  ¤   ¤   = -11087,
54b7a9 ¤   kPGPError_SocketsTimedOut¤  ¤   ¤   ¤   ¤   = -11086,
1e38c9 ¤   kPGPError_SocketsNoStaticStorage¤   ¤   ¤   = -11085,
0867c5 ¤
838336 ¤   kPGPError_SocketsHostNotFound¤  ¤   ¤   ¤   = -11050,
b2ccab ¤   kPGPError_SocketsDomainServerError¤ ¤   ¤   = -11049,
d867c5 ¤
4327db ¤   kPGPError_DummyEnumValue
9f8e80 ¤   /* kPGPError_Last */
de2fa1 } ;
c9af5a
20af5a
be99c6 PGP_BEGIN_C_DECLARATIONS
f9cbcf #if PRAGMA_IMPORT_SUPPORTED
8eb981 #pragma import on
df7454 #endif
30af5a
a8108c PGPError ¤  PGPGetErrorString( PGPError theError,
fd290d ¤   ¤   ¤   ¤   PGPSize bufferSize, char * theString );
14af5a
98cbcf #if PRAGMA_IMPORT_SUPPORTED
412ced #pragma import reset
e57454 #endif
681254 PGP_END_C_DECLARATIONS
24af5a
8caf5a
0b7512 #endif /* ] Included_pgpErrors_h */
a8af5a
68af5a
2b7e4d /*__Editor_settings____
b3af5a
874126 ¤   Local Variables:
767b17 ¤   tab-width: 4
e40e6c ¤   End:
065f8c ¤   vi: ts=4 sw=4
219e9b ¤   vim: si
1ad062 _____________________*/
--4384 000fc8d5c984010029f Page 1 of pgpFeatures.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
74f1c2 ¤   Determine which features are present in the PGPsdk. ·This is the only
ea2a0c ¤   way to correctly determine which features are present. ·The version
c2f63c ¤   number may be the same for different builds that lack some features.
f4af5a
5ae577 ¤   $Id: pgpFeatures.h,v 1.16.10.1 1998/11/12 03:23:33 heller Exp $
3af7f7 ____________________________________________________________________________*/
2f8760 #ifndef Included_pgpFeatures_h¤ /* [ */
2a1560 #define Included_pgpFeatures_h
adaf5a
b0af5a
35e82c #include "pgpPubTypes.h"
1caf5a
44af5a
81af5a
fdfa23 #if PRAGMA_ALIGN_SUPPORTED
d26071 #pragma options align=mac68k¤   /* [ */
277454 #endif
d9af5a
59af5a
280335 /*____________________________________________________________________________
f2250d ¤   Each selector designates a PGPFlags word, which can be obtained via
9aab4a ¤   PGPGetFeatureFlags(). ·The flags can be tested using the·
6784ec ¤   supplied masks. ·We can add more selectors as needed. ·The masks
25c6fb ¤   are not intended to be restricted to a single bit.
d2e9c2 ¤   Flags should not be used for attributes that have unknown length.
2e67c5 ¤
0de918 ¤   A kPGPError_ItemNotFound will be returned if the caller specifies
b139c7 ¤   a selector which is not recognized by the PGPsdk. ·This could
b724b6 ¤   occur if an app links to an older version of the SDK.
d8f7f7 ____________________________________________________________________________*/
57af5a
cad73f /* selectors which are passed to PGPGetFeatureFlags */
c04ba1 enum PGPFeatureSelector_
02bb36 {
3ca9a1 ¤   kPGPFeatures_GeneralSelector¤   ¤   = 1,
26094c ¤   kPGPFeatures_ImplementationSelector¤= 2,
8b7523 ¤   PGP_ENUM_FORCE( PGPFeatureSelector_ )
b382f7 };
dacb0a PGPENUM_TYPEDEF( PGPFeatureSelector_, PGPFeatureSelector );
62af5a
d5af5a
293480 /* flags for kPGPFeatures_GeneralSelector */
9f7353 enum
9fbb36 {
7981b4 ¤   kPGPFeatureMask_CanEncrypt¤ ¤   ¤   = 0x1,
f9c9d2 ¤   kPGPFeatureMask_CanDecrypt¤ ¤   ¤   = 0x2,
1a48cb ¤   kPGPFeatureMask_CanSign¤¤   ¤   ¤   = 0x4,
37b531 ¤   kPGPFeatureMask_CanVerify¤  ¤   ¤   = 0x8,
845783 ¤   kPGPFeatureMask_CanGenerate¤¤   ¤   = 0x10
9482f7 };
f6af5a
56af5a
74e9a9 /* flags for kPGPFeatures_ImplementationSelector */
d47353 enum
35bb36 {
9b3480 ¤   kPGPFeatureMask_IsDebugBuild¤   = 0x1,
95431b ¤   kPGPFeatureMask_HasTimeout¤ ¤   = 0x2
1f82f7 };
15af5a
efaf5a
c9af5a
b7d722 typedef struct PGPAlgorithmInfo
56bb36 {
6394b6 ¤   char¤   ¤   shortName[ 32 ];
42bad4 ¤   char¤   ¤   longName[ 96 ];
a516df ¤   char¤   ¤   copyright[ 128 ];
d6434c ¤   PGPFlags¤   flags;¤ ¤   ¤   /* reserved; 0 for now */
fc881e ¤   PGPUInt32¤  reserved[ 16 ];¤/* reserved; 0 for now */
--8c44 000413a22504010029f Page 2 of pgpFeatures.h
c26ca7 } PGPAlgorithmInfo;
86af5a
d9af5a
525abf typedef struct PGPPublicKeyAlgorithmInfo
1ebb36 {
957359 ¤   PGPAlgorithmInfo¤   ¤   info;
0367c5 ¤
7986f3 ¤   PGPPublicKeyAlgorithm¤  algID;
9a67c5 ¤
04e38b ¤   PGPBoolean¤ ¤   ¤   ¤   canEncrypt;
a0091a ¤   PGPBoolean¤ ¤   ¤   ¤   canDecrypt;
6e0882 ¤   PGPBoolean¤ ¤   ¤   ¤   canSign;
23bf51 ¤   PGPBoolean¤ ¤   ¤   ¤   canVerify;
9e024e ¤   PGPBoolean¤ ¤   ¤   ¤   canGenerate;
5b5288 ¤   PGPBoolean¤ ¤   ¤   ¤   reserved1;
68bdec ¤   PGPBoolean¤ ¤   ¤   ¤   reserved2;
0ee730 ¤   PGPBoolean¤ ¤   ¤   ¤   reserved3;
ba67c5 ¤
329325 ¤   PGPUInt32¤  ¤   ¤   ¤   reserved[ 8 ];
e14869 } PGPPublicKeyAlgorithmInfo;
c6af5a
7aaf5a
6b2257 typedef struct PGPSymmetricCipherInfo
85bb36 {
834ca6 ¤   PGPAlgorithmInfo¤   info;
2067c5 ¤
3d92e0 ¤   PGPCipherAlgorithm¤ algID;
7f67c5 ¤
108574 ¤   PGPUInt32¤  ¤   ¤   reserved[ 8 ];
b5e4e2 } PGPSymmetricCipherInfo;
85af5a
7caf5a
adaf5a
36fa23 #if PRAGMA_ALIGN_SUPPORTED
e0c366 #pragma options align=reset¤¤   ¤   /* ] */
0b7454 #endif
d7af5a
63af5a
89af5a
edaf5a
86af5a
aa99c6 PGP_BEGIN_C_DECLARATIONS
0fcbcf #if PRAGMA_IMPORT_SUPPORTED
29b981 #pragma import on
e97454 #endif
38af5a
a2af5a
532541 /* see kPGPsdkAPIVersion in pgpUtilities.h for version format */
42362f PGPError ¤  PGPGetSDKVersion( PGPUInt32 *version );
43af5a
72af5a
b90335 /*____________________________________________________________________________
117502 ¤   Return a C string of the form:
bbaf5a
7aac89 ¤   ¤   "PGPsdk version 1.0 (C) 1997 Pretty Good Privacy, Inc"
3df7f7 ____________________________________________________________________________*/
4a6f53 PGPError¤   PGPGetSDKString( char theString[ 256 ] );
33af5a
d8af5a
c8af5a
4a0a21 /* return a flags word for the feature selector */
16710d PGPError ¤  PGPGetFeatureFlags( PGPFeatureSelector selector,
004da5 ¤   ¤   ¤   ¤   ¤   PGPFlags *flags );
d3af5a
791415 /* use this to test whether a feature exists after getting flags */
c46880 #define PGPFeatureExists( flags, maskValue )¤   ¤   ¤   ¤   ¤   ¤   ¤   \
638641 ¤   ¤   ¤   ( ( (flags) & (maskValue) ) != 0 )
9eaf5a
f8af5a
620335 /*____________________________________________________________________________
364329 ¤   Routines to determine which algorithms are present.
4167c5 ¤
--c6c9 001f021f1ed4010029f Page 3 of pgpFeatures.h
37347d ¤   To determine if a specific algorithm is available, you will need to
53b0a0 ¤   index through the available algorithms and check the algorithm ID.
79f7f7 ____________________________________________________________________________*/
0a5ba0 PGPError¤   PGPCountPublicKeyAlgorithms( PGPUInt32 *numPKAlgs );
b5194e PGPError¤   PGPGetIndexedPublicKeyAlgorithmInfo( PGPUInt32 theIndex,
0c16ee ¤   ¤   ¤   ¤   PGPPublicKeyAlgorithmInfo *info);
932b85 ¤   ¤   ¤   ¤
d33205 PGPError¤   PGPCountSymmetricCiphers( PGPUInt32 *numPKAlgs );
f3cf7a PGPError¤   PGPGetIndexedSymmetricCipherInfo( PGPUInt32 theIndex,
0988a7 ¤   ¤   ¤   ¤   PGPSymmetricCipherInfo *info);
f3af5a
4faf5a
12af5a
15cbcf #if PRAGMA_IMPORT_SUPPORTED
dd2ced #pragma import reset
197454 #endif
0b1254 PGP_END_C_DECLARATIONS
ccaf5a
88af5a
3caf5a
04af5a
e2f295 #endif /* ] Included_pgpFeatures_h */
f3af5a
b77e4d /*__Editor_settings____
22af5a
ec4126 ¤   Local Variables:
247b17 ¤   tab-width: 4
600e6c ¤   End:
805f8c ¤   vi: ts=4 sw=4
049e9b ¤   vim: si
f0d062 _____________________*/
--65f3 000f247b5e6401002a0 Page 1 of pgpGroups.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
12aee2 ¤   $Id: pgpGroups.h,v 1.5.12.1 1998/11/12 03:23:34 heller Exp $
55f7f7 ____________________________________________________________________________*/
c2af5a
61f604 #ifndef Included_pgpGroups_h¤   /* [ */
ee88fc #define Included_pgpGroups_h
2faf5a
02e82c #include "pgpPubTypes.h"
589f63 #include "pgpEncode.h"
93af5a
bffa23 #if PRAGMA_ALIGN_SUPPORTED
f5af46 #pragma options align=mac68k
2e7454 #endif
5baf5a
741a08 #define kPGPMaxGroupNameLength¤ ¤   ¤   ¤   63
7d92dc #define kPGPMaxGroupDescriptionLength¤  ¤   63
46af5a
ca0d64 typedef char¤   PGPGroupName[ kPGPMaxGroupNameLength + 1 ];
5fe66e typedef char¤   PGPGroupDescription[ kPGPMaxGroupDescriptionLength + 1 ];
63af5a
7baf5a
c04a2d typedef struct PGPGroupSet *¤   ¤   PGPGroupSetRef;
2b7f31 typedef struct PGPGroupIter *¤  ¤   PGPGroupItemIterRef;
74af5a
db4f55 #define¤kInvalidPGPGroupSetRef¤ ¤   ¤   ((PGPGroupSetRef) NULL)
afdd27 #define¤kInvalidPGPGroupItemIterRef¤¤   ((PGPGroupItemIterRef) NULL)
08af5a
9cf041 #define PGPGroupSetRefIsValid(ref)¤ ¤   ((ref) != kInvalidPGPGroupSetRef)
33b9f6 #define PGPGroupItemIterRefIsValid(ref)¤((ref) != kInvalidPGPGroupItemIterRef)
a5af5a
92452f /* any type will do that is distinct */
184c2f typedef PGPUInt32¤  ¤   ¤   ¤   PGPGroupID;
0b0e89 #define kPGPInvalidGroupID¤ ¤   ( (PGPGroupID)0 )
4aaf5a
5d77d3 enum PGPGroupItemType_
42bb36 {
60d597 ¤   kPGPGroupItem_KeyID = 1,
2f2200 ¤   kPGPGroupItem_Group,
9367c5 ¤
d09712 ¤   PGP_ENUM_FORCE( PGPGroupItemType_)
0d82f7 };
bc408e PGPENUM_TYPEDEF( PGPGroupItemType_, PGPGroupItemType );
ddaf5a
d80335 /*____________________________________________________________________________
129f7c ¤   A run-time group item, used when iterating through a group.
9e74b2 ¤   For client use; not necessarily the internal storage format.
f567c5 ¤
c687c9 ¤   'userValue' is *not* saved to disk.
e9f7f7 ____________________________________________________________________________*/
1faf5a
ae4e02 typedef struct PGPGroupItem
71bb36 {
b4bcdf ¤   PGPGroupItemType¤   type;
1c4e6a ¤   PGPUserValue¤   ¤   userValue;
1367c5 ¤
86f20a ¤   union
9dc7a1 ¤   {
984498 ¤   ¤   /* type selects which substructure */
e0bbfc ¤   ¤   struct¤ /* if kGroupItem_Group */
aa5b34 ¤   ¤   {
19c6a8 ¤   ¤   ¤   PGPGroupID¤ id;
93cc5b ¤   ¤   } group;
a21b52 ¤   ¤
85de44 ¤   ¤   struct¤ /* if kGroupItem_KeyID */
0f5b34 ¤   ¤   {
5075e3 ¤   ¤   ¤   PGPPublicKeyAlgorithm¤  algorithm;
7670a4 ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   ¤   keyID;
c6e81b ¤   ¤   } key;
f2fef9 ¤   } u;
--4d4f 00091660f7d401002a0 Page 2 of pgpGroups.h
2a67c5 ¤
4d4e1c ¤   PGPUInt32 reserved[4];
2967c5 ¤
c21771 } PGPGroupItem;
47af5a
87af5a
4a2f5c typedef PGPInt32¤   (*PGPGroupItemCompareProc)( PGPGroupItem *,
61ee76 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGroupItem *, PGPUserValue userValue );
feaf5a
bd0335 /*____________________________________________________________________________
947aff ¤   Info obtained via PGPGetGroupInfo.
ccf7f7 ____________________________________________________________________________*/
3faf5a
b58dd9 typedef struct PGPGroupInfo
00bb36 {
a9c474 ¤   PGPGroupID¤ ¤   id;
ed67b9 ¤   PGPGroupName¤   name;
9403a8 ¤   PGPGroupName¤   description;
efea01 ¤   PGPUserValue¤   userValue;
d467c5 ¤
a67fec } PGPGroupInfo;
7daf5a
6daf5a
1b7ff1 typedef PGPFlags¤   PGPGroupItemIterFlags;
e7df14 /* flag (1UL << 0 ) is reserved */
25c533 #define kPGPGroupIterFlags_Recursive¤   (PGPFlags)(1UL << 1 )
24f9ba #define kPGPGroupIterFlags_Keys¤¤   ¤   (PGPFlags)(1UL << 2 )
1b231d #define kPGPGroupIterFlags_Groups¤  ¤   (PGPFlags)(1UL << 3 )
7aaf5a
a64095 #define kPGPGroupIterFlags_AllKeysRecursive¤¤   ¤   \
27337b ¤   ( kPGPGroupIterFlags_Recursive | kPGPGroupIterFlags_Keys )
9467c5 ¤
3cc09a #define kPGPGroupIterFlags_AllGroupsRecursive¤  ¤   ¤   \
443239 ¤   ( kPGPGroupIterFlags_Recursive | kPGPGroupIterFlags_Groups )
0967c5 ¤
a3788d #define kPGPGroupIterFlags_AllItems¤¤   ¤   \
dfa718 ¤   ( kPGPGroupIterFlags_Keys | kPGPGroupIterFlags_Groups )
a267c5 ¤
affcd5 #define kPGPGroupIterFlags_AllRecursive¤\
697ffa ¤   ( kPGPGroupIterFlags_Recursive | kPGPGroupIterFlags_AllItems )
9d67c5 ¤
e367c5 ¤
4eaf5a
40fa23 #if PRAGMA_ALIGN_SUPPORTED
e07c46 #pragma options align=reset
c27454 #endif
2eaf5a
f999c6 PGP_BEGIN_C_DECLARATIONS
0baf5a
13cbcf #if PRAGMA_IMPORT_SUPPORTED
f8b981 #pragma import on
de7454 #endif
edaf5a
37af5a
b60335 /*____________________________________________________________________________
5542c4 ¤   Manipulating pgp group sets (PGPGroupSetRef)
ecf7f7 ____________________________________________________________________________*/
9f5bbb /* create a new, empty groups collection */
65b3b2 PGPError¤   PGPNewGroupSet( PGPContextRef context, PGPGroupSetRef *outRef );
20af5a
c04fa9 /* file is *not* left open; all data is loaded into memory */
05505d PGPError¤   PGPNewGroupSetFromFile( PGPContextRef context,
059bee ¤   ¤   ¤   ¤   PGPFileSpecRef file,
f64545 ¤   ¤   ¤   ¤   PGPGroupSetRef *outRef );
f1af5a
670ccc #if PGP_MACINTOSH
1eea15 PGPError¤   PGPNewGroupSetFromFSSpec( PGPContextRef context,
400901 ¤   ¤   ¤   ¤   const FSSpec *spec, PGPGroupSetRef *outRef );
287454 #endif
7faf5a
865741 /* overwrites existing. ·Don't bother unless PGPGroupSetNeedsCommit() */
9109f9 PGPError¤   PGPSaveGroupSetToFile( PGPGroupSetRef set, PGPFileSpecRef file );
--4a3e 000743ead04401002a0 Page 3 of pgpGroups.h
e0af5a
8458de /* free all data structures; be sure to save first if you want */
af847a PGPError¤   PGPFreeGroupSet( PGPGroupSetRef set );
b2af5a
88af5a
ce09d3 /* has the group changed? */
bb164a PGPBoolean¤ ¤   PGPGroupSetNeedsCommit( PGPGroupSetRef set );
41af5a
1a9821 PGPContextRef¤  PGPGetGroupSetContext( PGPGroupSetRef set );
121b52 ¤   ¤
7ab17c /* export the groupset to a buffer. Use PGPFreeData to free the buffer */
e12a90 PGPError¤   PGPExportGroupSetToBuffer( PGPGroupSetRef set, void **buffer,
fa369e ¤   ¤   ¤   ¤   PGPSize *bufferSize );
0baf5a
94cbc1 /* import a groupset from a buffer */
1abf21 PGPError¤   PGPImportGroupSetFromBuffer(PGPContextRef context, void *buffer,
56416a ¤   ¤   ¤   ¤   PGPSize bufSize, PGPGroupSetRef *outSet );
1a1b52 ¤   ¤
890335 /*____________________________________________________________________________
89fa66 ¤   Manipulating groups
0b67c5 ¤
a73ea6 ¤   Groups are always referred to by IDs which remain valid until the set
990ff2 ¤   is disposed.
def7f7 ____________________________________________________________________________*/
6aaf5a
4fcd70 /* initial parent ID is kPGPInvalidGroupID */
6aef85 PGPError¤   PGPNewGroup( PGPGroupSetRef set,
d2e5ac ¤   ¤   ¤   ¤   const char * name, const char *description, PGPGroupID *id );
0baf5a
6d6563 PGPError¤   PGPCountGroupsInSet( PGPGroupSetRef set,
04d4f8 ¤   ¤   ¤   ¤   PGPUInt32 *numGroups);
f0005f PGPError¤   PGPGetIndGroupID( PGPGroupSetRef set,
5d02ac ¤   ¤   ¤   ¤   PGPUInt32 groupIndex, PGPGroupID *id );
7eaf5a
40225c /* delete this group from the set */
060fd4 /* All references to it are removed in all sets */
32c136 PGPError¤   PGPDeleteGroup( PGPGroupSetRef set, PGPGroupID id );
6baf5a
ae928e /* delete the indexed item from the group */
ce03e9 /* the item may be a group or a key */
98c705 PGPError¤   PGPDeleteIndItemFromGroup( PGPGroupSetRef set,
476ff5 ¤   ¤   ¤   ¤   PGPGroupID¤ id, PGPUInt32 item );
07af5a
d65728 /* same as PGPDeleteIndItemFromGroup, but accepts an item */
c8104c PGPError¤   PGPDeleteItemFromGroup( PGPGroupSetRef set,
8a57e9 ¤   ¤   ¤   ¤   PGPGroupID id, PGPGroupItem const *item );
c7af5a
06af5a
687469 PGPError¤   PGPGetGroupInfo( PGPGroupSetRef set,
97a66d ¤   ¤   ¤   ¤   PGPGroupID id, PGPGroupInfo *info );
1b2b85 ¤   ¤   ¤   ¤
0010e3 PGPError¤   PGPSetGroupName( PGPGroupSetRef set,
4e8b13 ¤   ¤   ¤   ¤   PGPGroupID id, const char * name );
5c5a34 PGPError¤   PGPSetGroupUserValue( PGPGroupSetRef set,
70fa55 ¤   ¤   ¤   ¤   PGPGroupID id, PGPUserValue userValue );
42a8ed PGPError¤   PGPSetGroupDescription( PGPGroupSetRef set,
fd8b13 ¤   ¤   ¤   ¤   PGPGroupID id, const char * name );
6daf5a
f0968c /* 'item' specifies a group or a key id */
b85169 /* you must fill the item in completely */
7c90ab PGPError¤   PGPAddItemToGroup( PGPGroupSetRef set,
6682d8 ¤   ¤   ¤   ¤   PGPGroupItem const *item, PGPGroupID group );
9eaf5a
09af5a
5b2ef5 PGPError¤   PGPMergeGroupIntoDifferentSet( PGPGroupSetRef fromSet,
458f39 ¤   ¤   ¤   ¤   PGPGroupID fromID, PGPGroupSetRef toSet );
b9af5a
99f674 PGPError¤   PGPMergeGroupSets( PGPGroupSetRef fromSet,
fad620 ¤   ¤   ¤   ¤   PGPGroupSetRef intoSet );
f1af5a
66bd6b PGPError¤   PGPCopyGroupSet(PGPGroupSetRef sourceSet,
7465cd ¤   ¤   ¤   ¤   PGPGroupSetRef *destSet);
--2faa 000f61883e9401002a0 Page 4 of pgpGroups.h
2a67c5 ¤
240335 /*____________________________________________________________________________
ed2057 ¤   Manipulating group items
a0f7f7 ____________________________________________________________________________*/
a3af5a
91fd5b /* count how many items there are in a group */
10335a /* totalItems includes keys and groups */
e92668 PGPError¤   PGPCountGroupItems( PGPGroupSetRef set,
a2995a ¤   ¤   ¤   ¤   ¤   PGPGroupID id, PGPBoolean recursive,
5024e4 ¤   ¤   ¤   ¤   ¤   PGPUInt32 * numKeys,
a50543 ¤   ¤   ¤   ¤   ¤   PGPUInt32 * totalItems );
d8af5a
ce7958 /* non-recursive call; index only applies to group itself */
fc3079 PGPError¤   PGPGetIndGroupItem( PGPGroupSetRef set,
45e1f3 ¤   ¤   ¤   ¤   PGPGroupID id, PGPUInt32 groupIndex, PGPGroupItem * item );
28af5a
ad514f /* use PGPGetIndGroupItem() if you want to get the user value */
b189c8 PGPError¤   PGPSetIndGroupItemUserValue( PGPGroupSetRef set,
98c108 ¤   ¤   ¤   ¤   PGPGroupID id, PGPUInt32 groupIndex, PGPUserValue userValue );
f3af5a
94b9a2 PGPError¤   PGPSortGroupItems( PGPGroupSetRef set, PGPGroupID id,
8a23fa ¤   ¤   ¤   ¤   PGPGroupItemCompareProc, PGPUserValue userValue );
262b85 ¤   ¤   ¤   ¤
cd1c3e PGPError¤   PGPSortGroupSet( PGPGroupSetRef set,
8323fa ¤   ¤   ¤   ¤   PGPGroupItemCompareProc, PGPUserValue userValue );
cfaf5a
dd0335 /*____________________________________________________________________________
a43cfb ¤   PGPGroupItemIterRef--iterator through group items.
0c67c5 ¤
049a74 ¤   Special note: this is not a full-fledged iterator. ·You may *not* add
83b2d2 ¤   or delete items while iterating and you may only move forward. ·However,
d9fcf9 ¤   you may change the values of items.
25f7f7 ____________________________________________________________________________*/
9daf5a
f19348 PGPError¤   PGPNewGroupItemIter( PGPGroupSetRef set, PGPGroupID id,
044b93 ¤   ¤   ¤   ¤   PGPGroupItemIterFlags flags, PGPGroupItemIterRef *iter );
992b85 ¤   ¤   ¤   ¤
c2cf24 PGPError¤   PGPFreeGroupItemIter( PGPGroupItemIterRef iter );
81af5a
14468e /* returns kPGPError_EndOfIteration when done */
a33610 PGPError¤   PGPGroupItemIterNext( PGPGroupItemIterRef iter,
014d4a ¤   ¤   ¤   ¤   PGPGroupItem * item );
87af5a
6a0335 /*____________________________________________________________________________
5a81d6 ¤   Group utilities
edf7f7 ____________________________________________________________________________*/
38af5a
1e0335 /*____________________________________________________________________________
0ca96d ¤   Return the lowest validity of any item in the group
1526dc ¤   keyset should contain all keys available
e28b47 ¤   It is not an error if keys can't be found; you may want to check
a40569 ¤   the not found count.
3f67c5 ¤
9290c0 ¤   The lowest validity is kPGPValidity_Invalid and kPGPValidity_Unknown
65474b ¤   is never returned.
84f7f7 ____________________________________________________________________________*/
5a0bfd PGPError¤   PGPGetGroupLowestValidity( PGPGroupSetRef set, PGPGroupID id,
97bbe7 ¤   ¤   ¤   ¤   PGPKeySetRef keySet, PGPValidity * lowestValidity,
6f6c4a ¤   ¤   ¤   ¤   PGPUInt32 * numKeysNotFound);
feaf5a
350335 /*____________________________________________________________________________
8475a4 ¤   All all the keys in the group (and its subgroups) to the keyset
4ef7f7 ____________________________________________________________________________*/
5635fc PGPError¤   PGPNewKeySetFromGroup( PGPGroupSetRef set, PGPGroupID id,
535423 ¤   ¤   ¤   ¤   PGPKeySetRef masterSet, PGPKeySetRef * resultSet,
0c6c4a ¤   ¤   ¤   ¤   PGPUInt32 * numKeysNotFound);
09af5a
c90335 /*____________________________________________________________________________
205e12 ¤   Create a simple, flattened group of unique key IDs from the source group.
832212 ¤   Note that sourceSet and destSet must be different.
fff7f7 ____________________________________________________________________________*/
f61106 PGPError¤   PGPNewFlattenedGroupFromGroup(PGPGroupSetRef sourceSet,
--1445 0017df1ce59401002a0 Page 5 of pgpGroups.h
dc831a ¤   ¤   ¤   ¤   PGPGroupID sourceID, PGPGroupSetRef destSet,
0bffaa ¤   ¤   ¤   ¤   PGPGroupID *destID);
41af5a
7f0335 /*____________________________________________________________________________
3717a6 ¤   Perform a "standard" sort on a group
81f7f7 ____________________________________________________________________________*/
e4131e PGPError¤   PGPSortGroupSetStd( PGPGroupSetRef set, PGPKeySetRef keys );
8e2b85 ¤   ¤   ¤   ¤
8eaf5a
c5cbcf #if PRAGMA_IMPORT_SUPPORTED
d52ced #pragma import reset
e87454 #endif
cdaf5a
d11254 PGP_END_C_DECLARATIONS
19af5a
0f40a2 #endif /* ] Included_pgpGroups_h */
bfaf5a
2daf5a
e27e4d /*__Editor_settings____
30af5a
704126 ¤   Local Variables:
e27b17 ¤   tab-width: 4
100e6c ¤   End:
8d5f8c ¤   vi: ts=4 sw=4
fa9e9b ¤   vim: si
9fd062 _____________________*/
85af5a
f0af5a
0eaf5a
1caf5a
adaf5a
e9af5a
f6af5a
7daf5a
--8b8b 000bfff28da401002a1 Page 1 of pgpHMAC.h
a70335 /*____________________________________________________________________________
113308 ¤   pgpHMAC.h
0f67c5 ¤
19c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
104b0f ¤   All rights reserved.
e867c5 ¤
c4de9d ¤   $Id: pgpHMAC.h,v 1.2.12.1 1998/11/12 03:23:35 heller Exp $
00f7f7 ____________________________________________________________________________*/
4ee21c #ifndef Included_pgpHMAC_h¤ /* [ */
1217f9 #define Included_pgpHMAC_h
04af5a
f6e82c #include "pgpPubTypes.h"
2f6773 #include "pgpMemoryMgr.h"
bdaf5a
73af5a
bf99c6 PGP_BEGIN_C_DECLARATIONS
76cbcf #if PRAGMA_IMPORT_SUPPORTED
a1b981 #pragma import on
2b7454 #endif
75af5a
670335 /*____________________________________________________________________________
e2f8f1 ¤   Create a new HMAC of the specified algorithm.
7867c5 ¤
af2571 ¤   If the algorithm is not available then kPGPError_AlgorithmNotAvailable is
644d20 ¤   returned.
58f7f7 ____________________________________________________________________________*/
d0ae9f PGPError ¤  PGPNewHMACContext( PGPMemoryMgrRef memoryMgr,
f319e1 ¤   ¤   ¤   ¤   ¤   PGPHashAlgorithm¤   algorithm,
780473 ¤   ¤   ¤   ¤   ¤   PGPByte *¤  ¤   ¤   secret,
f68d0c ¤   ¤   ¤   ¤   ¤   PGPSize¤¤   ¤   ¤   secretLen,
834150 ¤   ¤   ¤   ¤   ¤   PGPHMACContextRef *¤outRef );
abaf5a
db0335 /*____________________________________________________________________________
e7d03a ¤   Any existing intermediate HMAC is lost.
c1f7f7 ____________________________________________________________________________*/
dcf7ba PGPError ¤  PGPFreeHMACContext( PGPHMACContextRef ref );
80af5a
d00335 /*____________________________________________________________________________
cb1563 ¤   Reset an HMAC as if it had been created anew. ·Any existing intermediate
d33b29 ¤   hash is lost.
1df7f7 ____________________________________________________________________________*/
abd987 PGPError ¤  PGPResetHMAC( PGPHMACContextRef ref );
75af5a
750335 /*____________________________________________________________________________
23802c ¤   Continue the HMAC, accumulating an intermediate result
f9f7f7 ____________________________________________________________________________*/
510d4e PGPError ¤  PGPContinueHMAC( PGPHMACContextRef ref,
02da20 ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize numBytes );
1eaf5a
1aaf5a
b80335 /*____________________________________________________________________________
b87f26 ¤   Finalize the HMAC, depositing the result into 'hmacOut'.
3b67c5 ¤
8b4131 ¤   This size of the output will be the same size as the hash
bdbee8 ¤   algorithm output.
d4f7f7 ____________________________________________________________________________*/
6825e9 PGPError ¤  PGPFinalizeHMAC( PGPHMACContextRef ref, void *hmacOut );
30af5a
f9af5a
c1cbcf #if PRAGMA_IMPORT_SUPPORTED
af2ced #pragma import reset
ca7454 #endif
3a1254 PGP_END_C_DECLARATIONS
33af5a
857272 #endif /* ] Included_pgpHMAC_h */
deaf5a
03af5a
607e4d /*__Editor_settings____
f0af5a
5a4126 ¤   Local Variables:
757b17 ¤   tab-width: 4
bf0e6c ¤   End:
--a943 0018e2c01f0401002a1 Page 2 of pgpHMAC.h
e65f8c ¤   vi: ts=4 sw=4
949e9b ¤   vim: si
8ed062 _____________________*/
--b7db 000884770aa401002a2 Page 1 of pgpHash.h
a70335 /*____________________________________________________________________________
cd0a83 ¤   pgpHash.h
f367c5 ¤
bac97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
2b4b0f ¤   All rights reserved.
c267c5 ¤
9c67c5 ¤
e4af5a
fbcd5c ¤   $Id: pgpHash.h,v 1.14.10.1 1998/11/12 03:23:35 heller Exp $
3df7f7 ____________________________________________________________________________*/
dc6641 #ifndef Included_pgpHashing_h¤  /* [ */
a8b771 #define Included_pgpHashing_h
a9af5a
6fe82c #include "pgpPubTypes.h"
286773 #include "pgpMemoryMgr.h"
b0af5a
c9af5a
3d99c6 PGP_BEGIN_C_DECLARATIONS
b7cbcf #if PRAGMA_IMPORT_SUPPORTED
2eb981 #pragma import on
177454 #endif
bcaf5a
db0335 /*____________________________________________________________________________
f4d858 ¤   Create a new hash of the specified algorithm.
7b67c5 ¤
ee2571 ¤   If the algorithm is not available then kPGPError_AlgorithmNotAvailable is
b74d20 ¤   returned.
68f7f7 ____________________________________________________________________________*/
9a4009 PGPError ¤  PGPNewHashContext( PGPMemoryMgrRef memoryMgr,
3219e1 ¤   ¤   ¤   ¤   ¤   PGPHashAlgorithm¤   algorithm,
69829f ¤   ¤   ¤   ¤   ¤   PGPHashContextRef *¤outRef );
d9af5a
f4af5a
5d0335 /*____________________________________________________________________________
7767b9 ¤   Any existing intermediate hash is lost.
89f7f7 ____________________________________________________________________________*/
d56794 PGPError ¤  PGPFreeHashContext( PGPHashContextRef ref );
58af5a
8eaf5a
850335 /*____________________________________________________________________________
797e1b ¤   An exact duplicate of the hash is made.
ebf7f7 ____________________________________________________________________________*/
40a2fe PGPError ¤  PGPCopyHashContext( PGPHashContextRef ref,
fbafb3 ¤   ¤   ¤   ¤   ¤   PGPHashContextRef * outRef);
b3af5a
77af5a
80af5a
9d0335 /*____________________________________________________________________________
dae0b1 ¤   Reset a hash as if it had been created anew. ·Any existing intermediate
883b29 ¤   hash is lost.
eaf7f7 ____________________________________________________________________________*/
91e1c1 PGPError ¤  PGPResetHash( PGPHashContextRef ref );
beaf5a
44af5a
d70335 /*____________________________________________________________________________
843705 ¤   Continue the hash, accumulating an intermediate result
a8f7f7 ____________________________________________________________________________*/
dfe457 PGPError ¤  PGPContinueHash( PGPHashContextRef ref,
e3da20 ¤   ¤   ¤   ¤   ¤   const void *in, PGPSize numBytes );
ccaf5a
0aaf5a
270335 /*____________________________________________________________________________
b62c83 ¤   Finalize the hash, depositing the result into 'hashOut'.
4e67c5 ¤
3fc7e9 ¤   After calling this routine, the hash is reset via PGPResetHash().
421288 ¤   If you want an intermediate result, use PGPCopyHash() and finalize the
d78cec ¤   copy.
dff7f7 ____________________________________________________________________________*/
07800a PGPError ¤  PGPFinalizeHash( PGPHashContextRef ref, void *hashOut );
f8af5a
a2af5a
880335 /*____________________________________________________________________________
--211b 001be552630401002a2 Page 2 of pgpHash.h
c5870d ¤   Determine size of resulting hash in bytes e.g. a 160 bit hash yields 20.
f42db3 ¤   Used for generic code which may not know how big a hash is being produced.
cc67c5 ¤
d3b553 ¤   Question: can we reasonably assume 8 bits per byte? ·If not, how does
d589d4 ¤   PGPFinalizeHash return its result?
a3f7f7 ____________________________________________________________________________*/
9a8337 PGPError ¤  PGPGetHashSize( PGPHashContextRef ref, PGPSize *hashSize );
c7af5a
42af5a
d6cbcf #if PRAGMA_IMPORT_SUPPORTED
e52ced #pragma import reset
427454 #endif
d21254 PGP_END_C_DECLARATIONS
07af5a
98e65e #endif /* ] Included_pgpHashing_h */
1faf5a
a1af5a
c07e4d /*__Editor_settings____
b9af5a
7d4126 ¤   Local Variables:
ff7b17 ¤   tab-width: 4
930e6c ¤   End:
805f8c ¤   vi: ts=4 sw=4
c89e9b ¤   vim: si
bed062 _____________________*/
--55b4 000192f2a8c401002a3 Page 1 of pgpKeyServer.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
730c40 ¤   $Id: pgpKeyServer.h,v 1.31.10.1 1998/11/12 03:23:36 heller Exp $
c1f7f7 ____________________________________________________________________________*/
36af5a
6de4ba #ifndef Included_pgpKeyServer_h
6021d9 #define Included_pgpKeyServer_h
26af5a
4999c6 PGP_BEGIN_C_DECLARATIONS
29cbcf #if PRAGMA_IMPORT_SUPPORTED
5db981 #pragma import on
627454 #endif
c9af5a
5ffb31 #include "pgpOptionList.h"
b92f8d #include "pgpErrors.h"
15c2ae #include "pgpGroups.h"
00ec82 #include "pgpTLS.h"
e3af5a
3daf5a
d32da1 enum PGPKeyServerState_
d5bb36 {
ead74e ¤   kPGPKeyServerState_Invalid¤ ¤   ¤   ¤   ¤   ¤   = 0,
f55e78 ¤   kPGPKeyServerState_Opening¤ ¤   ¤   ¤   ¤   ¤   = 1,
b2ff96 ¤   kPGPKeyServerState_Querying¤¤   ¤   ¤   ¤   ¤   = 2,
d8347d ¤   kPGPKeyServerState_ProcessingResults¤   ¤   ¤   = 3,
50483e ¤   kPGPKeyServerState_Uploading¤   ¤   ¤   ¤   ¤   = 4,
cd7e0f ¤   kPGPKeyServerState_Deleting¤¤   ¤   ¤   ¤   ¤   = 5,
4f4a0e ¤   kPGPKeyServerState_Disabling¤   ¤   ¤   ¤   ¤   = 6,
4dcba7 ¤   kPGPKeyServerState_Closing¤ ¤   ¤   ¤   ¤   ¤   = 7,
55af5a
a6ce65 ¤   kPGPKeyServerState_TLSUnableToSecureConnection¤ = 8,
102d72 ¤   kPGPKeyServerState_TLSConnectionSecured¤¤   ¤   = 9,
81af5a
c501dc ¤   PGP_ENUM_FORCE(PGPKeyServerState_)
8682f7 };
c1af5a
896c54 PGPENUM_TYPEDEF(PGPKeyServerState_, PGPKeyServerState);
04af5a
3aedea enum PGPKeyServerType_
c1bb36 {
9ce119 ¤   kPGPKeyServerType_Invalid¤  ¤   ¤   = 0,
daee76 ¤   kPGPKeyServerType_LDAP¤ ¤   ¤   ¤   = 1,
b97741 ¤   kPGPKeyServerType_HTTP¤ ¤   ¤   ¤   = 2,
e248f7 ¤   kPGPKeyServerType_LDAPS¤¤   ¤   ¤   = 3,
f7b2a1 ¤   kPGPKeyServerType_HTTPS¤¤   ¤   ¤   = 4,
7967c5 ¤
015372 ¤   PGP_ENUM_FORCE( PGPKeyServerType_ )
c382f7 };
54af5a
ea0195 PGPENUM_TYPEDEF( PGPKeyServerType_, PGPKeyServerType );
e3af5a
212c6c enum PGPKeyServerKeySpace_ /* These are only valid for LDAP keyservers */
c1bb36 {
640278 ¤   kPGPKeyServerKeySpace_Invalid¤  = 0,
eea499 ¤   kPGPKeyServerKeySpace_Default¤  = 1,
9ef49e ¤   kPGPKeyServerKeySpace_Normal¤   = 2,
ccd450 ¤   kPGPKeyServerKeySpace_Pending¤  = 3,
90af5a
2668ba ¤   PGP_ENUM_FORCE( PGPKeyServerKeySpace_ )
2182f7 };
e5af5a
b864f6 PGPENUM_TYPEDEF( PGPKeyServerKeySpace_, PGPKeyServerKeySpace );
63af5a
28492b enum PGPKeyServerAccessType_ /* These are only valid for LDAP keyservers */
b9bb36 {
991356 ¤   kPGPKeyServerAccessType_Invalid¤¤   ¤   = 0,
de5313 ¤   kPGPKeyServerAccessType_Default¤¤   ¤   = 1,
1903c3 ¤   kPGPKeyServerAccessType_Normal¤ ¤   ¤   = 2,
--7bad 0005bc31ff0401002a3 Page 2 of pgpKeyServer.h
f85cba ¤   kPGPKeyServerAccessType_Administrator¤  = 3,
18af5a
cf5c9c ¤   PGP_ENUM_FORCE( PGPKeyServerAccessType_ )
5d82f7 };
77af5a
c07bfe PGPENUM_TYPEDEF( PGPKeyServerAccessType_, PGPKeyServerAccessType );
3eaf5a
1fe8ef /*¤ PGPKeyServerMonitorValues are null terminated linked lists.
3911f4 ¤   The values member is a null terminated array of char*s.
667fe0 */
a8af5a
50340f typedef struct PGPKeyServerMonitorValues
21bb36 {
b5bb5f ¤   char *¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   name;
c76dca ¤   char **¤¤   ¤   ¤   ¤   ¤   ¤   ¤   values;
5e83d4 ¤   struct PGPKeyServerMonitorValues *¤ next;
6dfd8c } PGPKeyServerMonitorValues;
74af5a
08a723 typedef struct PGPKeyServerMonitor·
d1bb36 {
02cca2 ¤   PGPKeyServerRef¤¤   ¤   ¤   keyServerRef;
681148 ¤   PGPKeyServerMonitorValues *¤valuesHead;
317b7c } PGPKeyServerMonitor;
3caf5a
31af5a
8607ff typedef struct PGPKeyServerThreadStorage *¤ PGPKeyServerThreadStorageRef;
b3b64d # define kInvalidPGPKeyServerThreadStorageRef¤  ¤   ¤   ¤   \
86407c ¤   ¤   ¤   ((PGPKeyServerThreadStorageRef) NULL)
bc509a #define PGPKeyServerThreadStorageRefIsValid(ref)¤   ¤   ¤   \
01130e ¤   ¤   ¤   ((ref) != kInvalidPGPKeyServerThreadStorageRef)
65af5a
bdaf5a
28af5a
2807f8 /*¤ Use the idle event handler to receive periodic idle events during
252c0f ¤   network calls. Usually this is used only in non-preemptive multi-tasking
022371 ¤   OSes to allow yielding in threads. Pre-emptive multi-tasking systems
648c74 ¤   should probably not use the call as it interrupts the efficient wait state
65db91 ¤   of threads waiting on network calls.
4b67c5 ¤
ac6766 ¤   Idle event handlers need to be added on a per thread basis.
7167c5 ¤
eb9a9d ¤   Returning an error from the idle event handler will cause the keyserver
7631bc ¤   to quit processing and to return a kPGPError_UserAbort. */
5a5ad0 PGPError¤   ¤   ¤   PGPSetKeyServerIdleEventHandler(
1e2e74 ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr inCallback,
27b37a ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue inUserData);
40af5a
d7c60e PGPError¤   ¤   ¤   PGPGetKeyServerIdleEventHandler(
746dcd ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr * outCallback,
3d8bcf ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue * outUserData);
37af5a
96af5a
7b83a8 /* Static storage creation */
ea2d2a PGPError¤   ¤   PGPKeyServerCreateThreadStorage(
9afe85 ¤   ¤   ¤   ¤   ¤   PGPKeyServerThreadStorageRef * outPreviousStorage);
2a3e75 PGPError¤   ¤   PGPKeyServerDisposeThreadStorage(
316da8 ¤   ¤   ¤   ¤   ¤   PGPKeyServerThreadStorageRef inPreviousStorage);
18ae30 ¤   ¤   ¤   ¤   ¤
c7324b /* Initialize and close the keyserver library */
16bc71 PGPError¤   ¤   ¤   PGPKeyServerInit(void);
a2af5a
7eb496 PGPError¤   ¤   ¤   PGPKeyServerCleanup(void);
bcaf5a
14af5a
55e08a /*¤ Creating and freeing a keyserver ref. */
b2cb48 PGPError ¤  ¤   ¤   PGPNewKeyServerFromURL(PGPContextRef inContext,·
312ea5 ¤   ¤   ¤   ¤   ¤   ¤   const char * inURL,·
8379be ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
28d2ec ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace,
8e4a1c ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef * outKeyServerRef);
afaf5a
5b6939 PGPError¤   ¤   ¤   PGPNewKeyServerFromHostName(PGPContextRef inContext,
--29f2 0001b16e580401002a3 Page 3 of pgpKeyServer.h
0e0531 ¤   ¤   ¤   ¤   ¤   ¤   const char * inHostName,
2b0f98 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 inPort, /* default for protocol if 0 */
ae1cbb ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType inType,
ac79be ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
fdd2ec ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace,
704a1c ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef * outKeyServerRef);
be94aa ¤   ¤   ¤   ¤   ¤   ¤
4cb0fe PGPError¤   ¤   ¤   PGPNewKeyServerFromHostAddress(PGPContextRef inContext,
620588 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 inAddress,
f80f98 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 inPort, /* default for protocol if 0 */
d41cbb ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType inType,
7d79be ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType inAccessType,
06d2ec ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace inKeySpace,
264a1c ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef * outKeyServerRef);
82af5a
da087c PGPError ¤  ¤   ¤   PGPFreeKeyServer(PGPKeyServerRef inKeyServerRef);
64db6d PGPError¤   ¤   ¤   PGPIncKeyServerRefCount(PGPKeyServerRef inKeyServerRef);
24af5a
abaf5a
550a7c /*¤ Set and get the keyserver's event handler. Note that returning an error
edb74b ¤   for a keyserver event will abort the current call. */
b45bb1 PGPError¤   ¤   ¤   PGPSetKeyServerEventHandler(
ff7659 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef inKeyServerRef,
cf2e74 ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr inCallback,
d0b37a ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue inUserData);
e6af5a
a8c30e PGPError¤   ¤   ¤   PGPGetKeyServerEventHandler(
567659 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef inKeyServerRef,
df6dcd ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr * outCallback,
108bcf ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue * outUserData);
ec94aa ¤   ¤   ¤   ¤   ¤   ¤
f194aa ¤   ¤   ¤   ¤   ¤   ¤
022926 /*¤ Canceling a call to a keyserver. This is the only call that can be made
b658b6 ¤   to a keyserver that is currently in another call. Also, once you have
03e37f ¤   returned from a canceled call, you may only close the keyserver. */
ff6276 PGPError¤   ¤   ¤   PGPCancelKeyServerCall(PGPKeyServerRef inKeyServerRef);
ac94aa ¤   ¤   ¤   ¤   ¤   ¤
f094aa ¤   ¤   ¤   ¤   ¤   ¤
b223a1 /*¤ Opening and closing the keyserver. A keyserver ref can be opened and
5f1047 ¤   closed multiple times as necessary. */
a87a05 PGPError¤   ¤   ¤   PGPKeyServerOpen(PGPKeyServerRef inKeyServerRef,
02ad8e ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionRef inTLSSessionRef);
ceaf5a
0ae548 PGPError¤   ¤   ¤   PGPKeyServerClose(PGPKeyServerRef inKeyServerRef);
a3af5a
42af5a
1ce3c1 /*¤ Get keyserver info. */
bccb42 PGPError¤   ¤   ¤   PGPGetKeyServerTLSSession(PGPKeyServerRef inKeyServerRef,
1de4ec ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsSessionRef * outTLSSessionRef);
acaf5a
074e62 PGPError¤   ¤   ¤   PGPGetKeyServerType(PGPKeyServerRef inKeyServerRef,
4d315b ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerType * outType);
67af5a
f71988 PGPError¤   ¤   ¤   PGPGetKeyServerAccessType(PGPKeyServerRef inKeyServerRef,
7e6273 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerAccessType * outAccessType);
01af5a
2b7596 PGPError¤   ¤   ¤   PGPGetKeyServerKeySpace(PGPKeyServerRef inKeyServerRef,
c618bb ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerKeySpace * outKeySpace);
d5af5a
7facdd PGPError¤   ¤   ¤   PGPGetKeyServerPort(PGPKeyServerRef inKeyServerRef,
6ae36f ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 * outPort);
ecaf5a
51ea14 PGPError¤   ¤   ¤   PGPGetKeyServerHostName(PGPKeyServerRef inKeyServerRef,
0e1aab ¤   ¤   ¤   ¤   ¤   ¤   char ** outHostName); /* Use PGPFreeData to free */
d3af5a
d14247 PGPError¤   ¤   ¤   PGPGetKeyServerAddress(PGPKeyServerRef inKeyServerRef,
b61550 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 * outAddress);
f5af5a
aade75 /*¤ If there was an error string returned from the server, you can get it with
3b4721 ¤   this function. Note that if there is no string, the function will return
1b735b ¤   kPGPError_NoErr and *outErrorString will be¤NULL */
1b39d0 PGPError¤   ¤   ¤   PGPGetLastKeyServerErrorString(
--cfb1 0011d99ed31401002a3 Page 4 of pgpKeyServer.h
df7659 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef inKeyServerRef,
d4278b ¤   ¤   ¤   ¤   ¤   ¤   char ** outErrorString); /* Use PGPFreeData to free */
32af5a
8faf5a
f36621 /* These functions may be used with both HTTP and LDAP keyservers */
e2b569 PGPError ¤  ¤   ¤   PGPQueryKeyServer(PGPKeyServerRef inKeyServerRef,·
3b0133 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef inFilterRef,·
7b34e5 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outFoundKeys);
91af5a
72161f PGPError ¤  ¤   ¤   PGPUploadToKeyServer(PGPKeyServerRef inKeyServerRef,·
f0dbe9 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToUpload,·
8f648a ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
c594aa ¤   ¤   ¤   ¤   ¤   ¤
1cf1a5 PGPError ¤  ¤   ¤   PGPUploadPrivateKeysToKeyServer(
8fea7e ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef inKeyServerRef,·
54dbe9 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToUpload,·
32648a ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
1294aa ¤   ¤   ¤   ¤   ¤   ¤
82af5a
506b59 /* These functions may only be used with LDAP keyservers */
33d8b8 PGPError¤   ¤   ¤   PGPDeleteFromKeyServer(PGPKeyServerRef inKeyServerRef,
4a4646 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToDelete,
94648a ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
dcaf5a
4099a4 PGPError¤   ¤   ¤   PGPDisableFromKeyServer(PGPKeyServerRef inKeyServerRef,
5d94ed ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef inKeysToDisable,
ec648a ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef * outKeysThatFailed);
d894aa ¤   ¤   ¤   ¤   ¤   ¤
da5a7a PGPError¤   ¤   ¤   PGPSendGroupsToServer(PGPKeyServerRef inKeyServerRef,
e29047 ¤   ¤   ¤   ¤   ¤   ¤   PGPGroupSetRef inGroupSetRef);
d494aa ¤   ¤   ¤   ¤   ¤   ¤
2f0d66 PGPError¤   ¤   ¤   PGPRetrieveGroupsFromServer(
f27659 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerRef inKeyServerRef,
d2cbe9 ¤   ¤   ¤   ¤   ¤   ¤   PGPGroupSetRef * outGroupSetRef);
68af5a
e006c5 PGPError¤   ¤   ¤   PGPNewServerMonitor(PGPKeyServerRef inKeyServerRef,
0bdb43 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyServerMonitor ** outMonitor);
dc94aa ¤   ¤   ¤   ¤   ¤   ¤
fd1a7f PGPError¤   ¤   ¤   PGPFreeServerMonitor(PGPKeyServerMonitor * inMonitor);
18af5a
01af5a
16cbcf #if PRAGMA_IMPORT_SUPPORTED
022ced #pragma import reset
f87454 #endif
bd1254 PGP_END_C_DECLARATIONS
80af5a
1d7454 #endif
--52cb 00016e384c8401002a4 Page 1 of pgpKeys.h
a70335 /*____________________________________________________________________________
aafd5d ¤   pgpKeys.h
8367c5 ¤
dae837 ¤   Copyright(C) 1996,1997 Network Associates, Inc. and its affiliates.
9e4b0f ¤   All rights reserved.
d067c5 ¤
70e771 ¤   Public definitions for PGP KeyDB Library
b5af5a
1059ee ¤   $Id: pgpKeys.h,v 1.111.10.1 1998/11/12 03:23:37 heller Exp $
06f7f7 ____________________________________________________________________________*/
1017ed #ifndef Included_pgpKeys_h¤ /* [ */
62d9ac #define Included_pgpKeys_h
17af5a
4faf5a
ddaf5a
86e82c #include "pgpPubTypes.h"
449f72 #include "pgpHash.h"
b5fb31 #include "pgpOptionList.h"
7aaf5a
d8af5a
6aaf5a
fa3887 /* Key ordering */
741614 enum PGPKeyOrdering_
65bb36 {
4b625d ¤   kPGPInvalidOrdering¤¤   ¤   ¤   ¤   = 0,
7afa05 ¤   kPGPAnyOrdering ¤   ¤   ¤   ¤   ¤   = 1,
d7f5cb ¤   kPGPUserIDOrdering¤ ¤   ¤   ¤   ¤   = 2,
797796 ¤   kPGPReverseUserIDOrdering¤  ¤   ¤   = 3,
92c461 ¤   kPGPKeyIDOrdering¤  ¤   ¤   ¤   ¤   = 4,
aee161 ¤   kPGPReverseKeyIDOrdering¤   ¤   ¤   = 5,
b8e446 ¤   kPGPValidityOrdering¤   ¤   ¤   ¤   = 6,
422fa1 ¤   kPGPReverseValidityOrdering¤¤   ¤   = 7,
edc441 ¤   kPGPTrustOrdering¤  ¤   ¤   ¤   ¤   = 8,
b627cf ¤   kPGPReverseTrustOrdering¤   ¤   ¤   = 9,
72ff89 ¤   kPGPEncryptKeySizeOrdering¤ ¤   ¤   = 10,
068d27 ¤   kPGPReverseEncryptKeySizeOrdering¤  = 11,
5384fe ¤   kPGPSigKeySizeOrdering¤ ¤   ¤   ¤   = 12,
6a00de ¤   kPGPReverseSigKeySizeOrdering¤  ¤   = 13,
3a8b9d ¤   kPGPCreationOrdering¤   ¤   ¤   ¤   = 14,
2482e8 ¤   kPGPReverseCreationOrdering¤¤   ¤   = 15,
10e52d ¤   kPGPExpirationOrdering¤ ¤   ¤   ¤   = 16,
925efd ¤   kPGPReverseExpirationOrdering¤  ¤   = 17,
0967c5 ¤
a64b95 ¤   PGP_ENUM_FORCE( PGPKeyOrdering_ )
5d2fa1 } ;
704f65 PGPENUM_TYPEDEF( PGPKeyOrdering_, PGPKeyOrdering );
0eaf5a
b0af5a
56af5a
f5f5f8 /* Key properties */
63af5a
fab7ed enum PGPKeyPropName_
3bcebb {¤
24873c /* String properties */
2a5359 ¤   kPGPKeyPropFingerprint¤ ¤   ¤   ¤   = 1,
103b2f ¤   kPGPKeyPropPreferredAlgorithms¤ ¤   = 2,
6d7feb ¤   kPGPKeyPropThirdPartyRevocationKeyID= 3,
5467c5 ¤
77f67c ¤   /* Number properties */
ff894e ¤   kPGPKeyPropAlgID ¤  ¤   ¤   ¤   ¤   = 20,
058707 ¤   kPGPKeyPropBits¤¤   ¤   ¤   ¤   ¤   = 21,¤
411c13 ¤   kPGPKeyPropTrust¤   ¤   ¤   ¤   ¤   = 22,¤  /* old trust model only */
539fe5 ¤   kPGPKeyPropValidity¤¤   ¤   ¤   ¤   = 23,¤  /* both trust models */
ff0487 ¤   kPGPKeyPropLockingAlgID¤¤   ¤   ¤   = 24,
496804 ¤   kPGPKeyPropLockingBits¤ ¤   ¤   ¤   = 25,
f9d99a ¤   kPGPKeyPropFlags¤   ¤   ¤   ¤   ¤   = 26,
fcaf5a
5566ac ¤   /* Time properties */
170ab0 ¤   kPGPKeyPropCreation ¤   ¤   ¤   ¤   = 40,
475e3a ¤   kPGPKeyPropExpiration¤  ¤   ¤   ¤   = 41,
91af5a
1655ff ¤   /* PGPBoolean properties */
--bdc4 0006b558cfd401002a4 Page 2 of pgpKeys.h
d95a23 ¤   kPGPKeyPropIsSecret ¤   ¤   ¤   ¤   = 60,
483fc7 ¤   kPGPKeyPropIsAxiomatic¤ ¤   ¤   ¤   = 61,
39a4c9 ¤   kPGPKeyPropIsRevoked¤   ¤   ¤   ¤   = 62,
911ea4 ¤   kPGPKeyPropIsDisabled¤  ¤   ¤   ¤   = 63,
419970 ¤   kPGPKeyPropIsNotCorrupt¤¤   ¤   ¤   = 64,
8f2909 ¤   kPGPKeyPropIsExpired¤   ¤   ¤   ¤   = 65,
92d984 ¤   kPGPKeyPropNeedsPassphrase¤ ¤   ¤   = 66,
b85801 ¤   kPGPKeyPropHasUnverifiedRevocation¤ = 67,
3e01ac ¤   kPGPKeyPropCanEncrypt¤  ¤   ¤   ¤   = 68,
26e1d4 ¤   kPGPKeyPropCanDecrypt¤  ¤   ¤   ¤   = 69,
6b1c0e ¤   kPGPKeyPropCanSign¤ ¤   ¤   ¤   ¤   = 70,
c266c6 ¤   kPGPKeyPropCanVerify¤   ¤   ¤   ¤   = 71,
d502e0 ¤   kPGPKeyPropIsEncryptionKey¤ ¤   ¤   = 72,
e3f7ff ¤   kPGPKeyPropIsSigningKey¤¤   ¤   ¤   = 73,
71c476 ¤   kPGPKeyPropIsSecretShared¤  ¤   ¤   = 74,
2adb3d ¤   kPGPKeyPropIsRevocable¤ ¤   ¤   ¤   = 75,
f2bee7 ¤   kPGPKeyPropHasThirdPartyRevocation¤ = 76,
6a67c5 ¤
ba5406 ¤   PGP_ENUM_FORCE( PGPKeyPropName_ )
fb2fa1 } ;
d46c01 PGPENUM_TYPEDEF( PGPKeyPropName_, PGPKeyPropName );
63af5a
78af5a
f5cf72 /* kPGPKeyPropFlags bits */
6b86d8 enum¤   /* PGPKeyPropFlags */
e0bb36 {
1ae555 ¤   kPGPKeyPropFlags_UsageSignUserIDs¤  ¤   ¤   = (1UL << 0 ),
681eb9 ¤   kPGPKeyPropFlags_UsageSignMessages¤ ¤   ¤   = (1UL << 1 ),
ce09ab ¤   kPGPKeyPropFlags_UsageEncryptCommunications¤= (1UL << 2 ),
875c8f ¤   kPGPKeyPropFlags_UsageEncryptStorage¤   ¤   = (1UL << 3 ),
f8af5a
63c74e ¤   kPGPKeyPropFlags_PrivateSplit¤  ¤   ¤   ¤   = (1UL << 4 ),
3494bd ¤   kPGPKeyPropFlags_PrivateShared¤ ¤   ¤   ¤   = (1UL << 7 )
6a2fa1 } ;
b17729 typedef PGPFlags¤   ¤   PGPKeyPropFlags;
bdaf5a
53af5a
99af5a
fac105 /* User ID properties */
49af5a
126e60 enum PGPUserIDPropName_
2ecebb {¤
937159 ¤   /* String properties */
840175 ¤   kPGPUserIDPropName ¤¤   ¤   ¤   ¤   = 80,
92b1d1 ¤   kPGPUserIDPropAttributeData¤¤   ¤   = 81,
5267c5 ¤
24f67c ¤   /* Number properties */
9d8db8 ¤   kPGPUserIDPropValidity ¤¤   ¤   ¤   = 100,¤ /* both trust models */
4e4abb ¤   kPGPUserIDPropConfidence¤   ¤   ¤   = 101,¤ /* new trust model only */
402776 ¤   kPGPUserIDPropAttributeType¤¤   ¤   = 102,
bbaf5a
a866ac ¤   /* Time properties */
89af5a
0155ff ¤   /* PGPBoolean properties */
6b0432 ¤   kPGPUserIDPropIsAttribute¤  ¤   ¤   = 110,
9567c5 ¤
638649 ¤   PGP_ENUM_FORCE( PGPUserIDPropName_ )
f62fa1 } ;
3787ec PGPENUM_TYPEDEF( PGPUserIDPropName_, PGPUserIDPropName );
4baf5a
62cddc /* Signature properties */
ddaf5a
5ff757 enum PGPSigPropName_
12bb36 {
d17159 ¤   /* String properties */
c3ba94 ¤   kPGPSigPropKeyID ¤  ¤   ¤   ¤   ¤   = 120,
8236c9 ¤   kPGPSigPropX509Certificate¤ ¤   ¤   = 121,
4367c5 ¤
d6f67c ¤   /* Number properties */
33b2aa ¤   kPGPSigPropAlgID ¤  ¤   ¤   ¤   ¤   = 140,
0d41bc ¤   kPGPSigPropTrustLevel¤  ¤   ¤   ¤   = 141,
6bbec2 ¤   kPGPSigPropTrustValue¤  ¤   ¤   ¤   = 142,
--6630 0007130851b401002a4 Page 3 of pgpKeys.h
2a67c5 ¤
9e66ac ¤   /* Time properties */
67ae36 ¤   kPGPSigPropCreation ¤   ¤   ¤   ¤   = 160,
5cc357 ¤   kPGPSigPropExpiration¤  ¤   ¤   ¤   = 161,
4067c5 ¤
a655ff ¤   /* PGPBoolean properties */
258822 ¤   kPGPSigPropIsRevoked ¤  ¤   ¤   ¤   = 180,
46f853 ¤   kPGPSigPropIsNotCorrupt¤¤   ¤   ¤   = 181,
0a2d91 ¤   kPGPSigPropIsTried¤ ¤   ¤   ¤   ¤   = 182,
56ad80 ¤   kPGPSigPropIsVerified¤  ¤   ¤   ¤   = 183,
b8faf1 ¤   kPGPSigPropIsMySig¤ ¤   ¤   ¤   ¤   = 184,
344ed6 ¤   kPGPSigPropIsExportable¤¤   ¤   ¤   = 185,
a43354 ¤   kPGPSigPropHasUnverifiedRevocation¤ = 186,
ebdcc7 ¤   kPGPSigPropIsExpired¤   ¤   ¤   ¤   = 187,
b80019 ¤   kPGPSigPropIsX509¤  ¤   ¤   ¤   ¤   = 188,
de67c5 ¤
4dd11c ¤   PGP_ENUM_FORCE( PGPSigPropName_ )
7c2fa1 } ;
d2c3fb PGPENUM_TYPEDEF( PGPSigPropName_, PGPSigPropName );
cf38e5 /*
8f35aa ·* Note on kPGPSigPropIsMySig. ·This is a convenience property for
a75767 ·* determining whether the certification was made by one of the
ea299b ·* caller's own private keys. ·This can only return true if the
ffbc8c ·* signing key is in the same base keyset as the certification. If the
09098d ·* signing key is( suspected to be) in a different base keyset, call
11be27 ·* PGPGetSigCertifierKey( certset, signerset, &key) followed by
a8a5cf ·* PGPGetKeyBoolean( key, kPGPKeyPropIsSecret, &secret).
9a495d ·*/
0eaf5a
67af5a
29b454 /* Attribute types, for use with kPGPUserIDPropAttributeType */
db5ad9 enum PGPAttributeType_
84bb36 {
727248 ¤   kPGPAttribute_Image¤¤   ¤   ¤   ¤   ¤   = 1,
b62198 ¤   kPGPAttribute_Notation¤ ¤   ¤   ¤   ¤   = 20,
c3af5a
660e8c ¤   PGP_ENUM_FORCE( PGPAttributeType_ )
fc2fa1 } ;
abd930 PGPENUM_TYPEDEF( PGPAttributeType_, PGPAttributeType );
77af5a
d1af5a
17494f enum¤   /* PGPKeyRingOpenFlags */
19bb36 {
82ebe8 ¤   kPGPKeyRingOpenFlags_Reserved¤  ¤   ¤   = (1UL << 0 ),
6a9182 ¤   kPGPKeyRingOpenFlags_Mutable¤   ¤   ¤   = (1UL << 1 ),
ee2808 ¤   kPGPKeyRingOpenFlags_Create¤¤   ¤   ¤   = (1UL << 2 ),
2aaf5a
fadbab ¤   /* The following flags are only used by PGPOpenKeyRing */
a4f081 ¤   kPGPKeyRingOpenFlags_Private¤   ¤   ¤   = (1UL << 8 ),
96115a ¤   kPGPKeyRingOpenFlags_Trusted¤   ¤   ¤   = (1UL << 9 )
e42fa1 } ;
3f73cb typedef PGPFlags¤   ¤   PGPKeyRingOpenFlags;
daaf5a
fc38e5 /*
9df09a ·* Used by filtering functions to specify type of match.
20495d ·*/
0baf5a
86f3d7 enum PGPMatchCriterion_
04bb36 {
a4762f ¤   kPGPMatchDefault = 1,
1758b1 ¤   kPGPMatchEqual = 1,¤¤   ¤   ·/* searched val == supplied val */
aa1f66 ¤   kPGPMatchGreaterOrEqual = 2, /* searched val >= supplied val */
89082e ¤   kPGPMatchLessOrEqual = 3, /* searched val <= supplied val */
83e5b2 ¤   kPGPMatchSubString = 4,¤ /* searched val is contained in supplied val */
8daf5a
7dbe43 ¤   PGP_ENUM_FORCE( PGPMatchCriterion_ )
e52fa1 } ;
c7fd9a PGPENUM_TYPEDEF( PGPMatchCriterion_, PGPMatchCriterion );
dbaf5a
93af5a
3e5194 /* This is the value of the expiration time which means "never expires" */
717895 #define kPGPExpirationTime_Never¤   ( (PGPTime)0 )
--13d1 000481e747a401002a4 Page 4 of pgpKeys.h
e0af5a
890abf /* Secret sharing header size */
6901c1 #define kPGPShareHeaderSize¤¤   4
afaf5a
4905e5 /* Public entry points */
ccaf5a
df99c6 PGP_BEGIN_C_DECLARATIONS
f6cbcf #if PRAGMA_IMPORT_SUPPORTED
cfb981 #pragma import on
1e7454 #endif
21af5a
90af5a
02ec70 /* Functions for setting up key filters. */
e4af5a
b4faaf PGPError ¤  ¤   PGPIncFilterRefCount ( PGPFilterRef filter );
dfaf5a
0e74d6 PGPError ¤  ¤   PGPFreeFilter ( PGPFilterRef filter );
f0af5a
841bc2 PGPError ¤  ¤   PGPNewKeyIDFilter( PGPContextRef context,·
bc734b ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID const * keyID, PGPFilterRef *outFilter);
e1af5a
7eda4e PGPError¤   ¤   PGPNewSubKeyIDFilter( PGPContextRef¤¤   context,
1aac71 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID const *¤   subKeyID, ·
95e4c9 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *¤ ¤   outFilter);
38af5a
6da5bf PGPError ¤  ¤   PGPNewKeyEncryptAlgorithmFilter( PGPContextRef context,·
b35555 ¤   ¤   ¤   ¤   ¤   ¤   PGPPublicKeyAlgorithm encryptAlgorithm,
273e59 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *outFilter );
d0af5a
9fb4c3 PGPError ¤  ¤   PGPNewKeyFingerPrintFilter( PGPContextRef context,·
2d6ecf ¤   ¤   ¤   ¤   ¤   ¤   void const *fingerPrint,·
36039a ¤   ¤   ¤   ¤   ¤   ¤   PGPSize fingerPrintLength, PGPFilterRef *outFilter );
86af5a
c22caf PGPError ¤  ¤   PGPNewKeyCreationTimeFilter( PGPContextRef context,·
5eb1ca ¤   ¤   ¤   ¤   ¤   ¤   PGPTime creationTime, PGPMatchCriterion match,·
1a3e59 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *outFilter );
0caf5a
78b3e6 PGPError ¤  ¤   PGPNewKeyExpirationTimeFilter( PGPContextRef context,·
567342 ¤   ¤   ¤   ¤   ¤   ¤   PGPTime expirationTime,·
5427c2 ¤   ¤   ¤   ¤   ¤   ¤   PGPMatchCriterion match, PGPFilterRef *outFilter );
30af5a
04af2d PGPError ¤  ¤   PGPNewKeyRevokedFilter( PGPContextRef context,
92b823 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean revoked, PGPFilterRef *outFilter );
edaf5a
57caee PGPError¤   ¤   PGPNewKeyDisabledFilter( PGPContextRef context,·
446a3f ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   disabled,·
f1e4c9 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *¤ ¤   outFilter);
e6af5a
52687c PGPError ¤  ¤   PGPNewKeySigAlgorithmFilter( PGPContextRef context,
2806c8 ¤   ¤   ¤   ¤   ¤   ¤   PGPPublicKeyAlgorithm sigAlgorithm,·
d63e59 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *outFilter );
bcaf5a
1d0494 PGPError ¤  ¤   PGPNewKeyEncryptKeySizeFilter( PGPContextRef context,
23b058 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keySize, PGPMatchCriterion match,
503e59 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *outFilter );
08af5a
a2caa7 PGPError ¤  ¤   PGPNewKeySigKeySizeFilter( PGPContextRef context,
72b058 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keySize, PGPMatchCriterion match,
863e59 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *outFilter );
c4af5a
e21845 PGPError¤   ¤   PGPNewUserIDStringFilter( PGPContextRef context,
3312dc ¤   ¤   ¤   ¤   ¤   ¤   char const *¤   ¤   userIDString,·
53cf8a ¤   ¤   ¤   ¤   ¤   ¤   PGPMatchCriterion¤  match,
56e4c9 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *¤ ¤   outFilter);
efaf5a
7e4e05 PGPError ¤  ¤   PGPNewUserIDEmailFilter( PGPContextRef context,
5989b9 ¤   ¤   ¤   ¤   ¤   ¤   char const *¤   ¤   emailString,·
08cf8a ¤   ¤   ¤   ¤   ¤   ¤   PGPMatchCriterion¤  match,
4fe4c9 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *¤ ¤   outFilter);
86af5a
0cb1fb PGPError ¤  ¤   PGPNewUserIDNameFilter( PGPContextRef context,
4838cf ¤   ¤   ¤   ¤   ¤   ¤   char const *¤   ¤   nameString,·
--97bc 0003b83efd0401002a4 Page 5 of pgpKeys.h
3bcf8a ¤   ¤   ¤   ¤   ¤   ¤   PGPMatchCriterion¤  match,
b6e4c9 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *¤ ¤   outFilter);
a7af5a
7edb2d PGPError ¤  ¤   PGPNewSigKeyIDFilter( PGPContextRef context,
1e35ca ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID const * keyID, PGPFilterRef *outFilter );
10af5a
9daf5a
7956e0 /* freeing outfilter will call PGPFreeFilter on filter */
40a0c4 PGPError ¤  ¤   PGPNegateFilter( PGPFilterRef filter,
a9b8f0 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef *outFilter);
3caf5a
6cce8e /* freeing outfilter will call PGPFreeFilter on filter1, filter2 */
1f3e3d PGPError ¤  ¤   PGPIntersectFilters( PGPFilterRef filter1,
5ed5d5 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef filter2, PGPFilterRef *outFilter);
afaf5a
b7ce8e /* freeing outfilter will call PGPFreeFilter on filter1, filter2 */
413fce PGPError ¤  ¤   PGPUnionFilters( PGPFilterRef filter1,
0ed5d5 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef filter2, PGPFilterRef *outFilter);
e1af5a
3baf5a
e8e565 PGPError ¤  ¤   PGPFilterKeySet( PGPKeySetRef origSet,
0ca217 ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef filter, PGPKeySetRef *resultSet);
daaf5a
4aaf5a
e4ec2e /* Keyserver filter functions */
5baf5a
0f7388 PGPError ¤  ¤   PGPLDAPQueryFromFilter( PGPFilterRef filter,
0d1b2b ¤   ¤   ¤   ¤   ¤   ¤   char **queryOut );
c3af5a
2abf1c PGPError ¤  ¤   PGPHKSQueryFromFilter( PGPFilterRef¤filter,
871b2b ¤   ¤   ¤   ¤   ¤   ¤   char **queryOut );
94af5a
60d2e4 /* KeySet manipulations */
23af5a
9aaf5a
7a1d87 /* Creates a new memory-based KeyDB and returns its root set */
4fd1bb PGPError ·¤ ¤   PGPNewKeySet(PGPContextRef context, PGPKeySetRef *keySet);
3daf5a
e5af5a
00c905 /* Used for building arbitrary subsets of an existing KeyDB */
a905b2 PGPError ·¤ ¤   PGPNewEmptyKeySet(PGPKeySetRef origSet, PGPKeySetRef *newSet);
475dfa PGPError ·¤ ¤   PGPNewSingletonKeySet(PGPKeyRef key, PGPKeySetRef *keySet);
c37c54 PGPError¤   ¤   PGPUnionKeySets(PGPKeySetRef set1, PGPKeySetRef set2,
68ded0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *newSet);
3daf5a
b10b4d PGPError ·¤ ¤   PGPOpenDefaultKeyRings( PGPContextRef context,
6aa68b ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRingOpenFlags openFlags, PGPKeySetRef *keySet);
f8af5a
937533 PGPError ·¤ ¤   PGPOpenKeyRingPair( PGPContextRef context,
ed9cfd ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRingOpenFlags openFlags,·
46b565 ¤   ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef pubFileRef, PGPFileSpecRef secFileRef,
96e37c ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *keySet);
f4af5a
a72570 PGPError ·¤ ¤   PGPOpenKeyRing (PGPContextRef context,
a15e07 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRingOpenFlags openFlags, PGPFileSpecRef fileRef,
56e37c ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *keySet);
3aaf5a
36589f PGPError ¤  ¤   PGPCommitKeyRingChanges (PGPKeySetRef keys);
5faf5a
bd0c2a PGPError ¤  ¤   PGPPropagateTrust (PGPKeySetRef keys);
41af5a
0dd100 PGPError ¤  ¤   PGPRevertKeyRingChanges (PGPKeySetRef keys);
66af5a
0d90a3 PGPError ¤  ¤   PGPCheckKeyRingSigs (PGPKeySetRef keysToCheck,
f1fb57 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keysSigning, PGPBoolean checkAll,
0d4402 ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr eventHandler,
365c51 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue eventHandlerData);
64af5a
6f0775 PGPError ¤  ¤   PGPReloadKeyRings (PGPKeySetRef keys);
ccaf5a
84f545 PGPError ¤  ¤   PGPGetKeyByKeyID (PGPKeySetRef keys,
3bae5b ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyID const * keyID,
--3dd7 00068076b04401002a4 Page 6 of pgpKeys.h
7d9034 ¤   ¤   ¤   ¤   ¤   ¤   PGPPublicKeyAlgorithm pubKeyAlgorithm,
ba8513 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *outRef);
61af5a
25d5ec PGPBoolean ¤¤   PGPKeySetIsMember(PGPKeyRef key, PGPKeySetRef set);
7eaf5a
6ab99c PGPError ¤  ¤   PGPCountKeys( PGPKeySetRef keys, PGPUInt32 *numKeys);
c7af5a
8ce3b8 PGPError ¤  ¤   PGPIncKeySetRefCount( PGPKeySetRef keys);
4daf5a
19a89d PGPError ¤  ¤   PGPFreeKeySet( PGPKeySetRef keys);
a5af5a
2fc1d1 PGPBoolean ¤¤   PGPKeySetIsMutable( PGPKeySetRef keys);
36af5a
fcc93e PGPBoolean ¤¤   PGPKeySetNeedsCommit( PGPKeySetRef keys);
3caf5a
29af5a
7d81fa PGPError ¤  ¤   PGPAddKeys( PGPKeySetRef keysToAdd, PGPKeySetRef set );
3baf5a
013743 PGPError ¤  ¤   PGPRemoveKeys( PGPKeySetRef keysToRemove, PGPKeySetRef set );
8daf5a
48af5a
22af5a
f6de3f /* Key manipulation functions */
37af5a
c28527 PGPError ¤  ¤   PGPDisableKey( PGPKeyRef key);
0daf5a
6a1206 PGPError ¤  ¤   PGPEnableKey( PGPKeyRef key);
beaf5a
de3e89 PGPError ¤  ¤   PGPRemoveSubKey( PGPSubKeyRef subkey);
7daf5a
d776ef PGPError ¤  ¤   PGPRemoveUserID( PGPUserIDRef userID);
69af5a
7de0e9 PGPError ¤  ¤   PGPSetPrimaryUserID( PGPUserIDRef userid);
23af5a
f888be PGPError ¤  ¤   PGPGetSigCertifierKey( PGPSigRef cert, PGPKeySetRef allkeys,
d9e334 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *certkey);
0baf5a
d0eb31 PGPError ¤  ¤   PGPRemoveSig( PGPSigRef cert);
4aaf5a
d3f0ef PGPError¤   ¤   PGPCountAdditionalRecipientRequests( PGPKeyRef basekey,
a092fb ¤   ¤   ¤   ¤   ¤   PGPUInt32 * numARKeys);
79ae30 ¤   ¤   ¤   ¤   ¤
370fee PGPError ¤  ¤   PGPGetIndexedAdditionalRecipientRequestKey(
d92ad3 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef basekey, PGPKeySetRef allkeys, PGPUInt32 nth,
2afaaa ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *arkey, PGPKeyID *arkeyid,
e305e2 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *arclass );
85af5a
4eebcc PGPError¤   ¤   PGPCountRevocationKeys( PGPKeyRef basekey,
dfba14 ¤   ¤   ¤   ¤   ¤   PGPUInt32 * numRevKeys);
0daf5a
9acd7c PGPError ¤  ¤   PGPGetIndexedRevocationKey(
c62ad3 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef basekey, PGPKeySetRef allkeys, PGPUInt32 nth,
1a491a ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *revkey, PGPKeyID *revkeyid );
b3af5a
23af5a
cec87d /* Wrapper functions */
0b383a PGPError¤   ¤   ¤   PGPGenerateKey( PGPContextRef context, PGPKeyRef *key,
5a64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
174ccc PGPError¤   ¤   ¤   PGPGenerateSubKey( PGPContextRef context,
feca74 ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKeyRef *subkey,
2364e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
4f5185 PGPUInt32¤  ¤   ¤   PGPGetKeyEntropyNeeded( PGPContextRef context,
5f64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
10afe1 PGPError¤   ¤   ¤   PGPExportKeySet( PGPKeySetRef keys,
3564e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
1f3831 PGPError¤   ¤   ¤   PGPImportKeySet( PGPContextRef context,
08311f ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef *keys,
3864e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
332973 PGPError¤   ¤   ¤   PGPSignUserID( PGPUserIDRef userID,
62b329 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef certifyingKey,
bf64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
686b0e PGPError¤   ¤   ¤   PGPAddUserID( PGPKeyRef key, char const *userID,
--a096 000dbfce617401002a4 Page 7 of pgpKeys.h
8f64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
7949ef PGPError¤   ¤   ¤   PGPAddAttributeUserID( PGPKeyRef key,
2ff5d9 ¤   ¤   ¤   ¤   ¤   ¤   PGPAttributeType attributeType,
aa82b2 ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *attributeData, PGPSize attributeLength,
4464e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
c123b7 PGPError¤   ¤   ¤   PGPRevokeSig( PGPSigRef cert, PGPKeySetRef allkeys,
8f64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
cdde93 PGPError¤   ¤   ¤   PGPRevokeKey( PGPKeyRef key,
d664e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
4d097c PGPError¤   ¤   ¤   PGPRevokeSubKey( PGPSubKeyRef subkey,
0764e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
ca7bcb PGPError¤   ·¤  ¤   PGPChangePassphrase( PGPKeyRef key,
4164e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
c62461 PGPError¤   ·¤  ¤   PGPChangeSubKeyPassphrase( PGPSubKeyRef subkey,
3c64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
c6908e PGPBoolean¤ ¤   ¤   PGPPassphraseIsValid( PGPKeyRef key,
ae64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
710566 PGPError¤   ·¤  ¤   PGPSetKeyAxiomatic( PGPKeyRef key,
6164e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
88af5a
06af5a
a1af5a
6538e5 /*
b11fa0 ·* Trust values for PGPSetKeyTrust and kPGPKeyPropTrust property:
939ec0 ·*·
e9c79f ·* kPGPKeyTrust_Undefined¤  (do not pass to PGPSetKeyTrust)
5a4a85 ·* kPGPKeyTrust_Unknown¤¤   (unknown)
c47e4d ·* kPGPKeyTrust_Never¤  ¤   (never)
93d6ce ·* kPGPKeyTrust_Marginal¤   (sometimes)
017603 ·* kPGPKeyTrust_Complete¤   (always)
867f51 ·* kPGPKeyTrust_Ultimate¤   (do not pass to PGPSetKeyTrust)
ad495d ·*/
e1af5a
b080ac ·/* old trust model */
2769c7 PGPError ¤  ¤   PGPSetKeyTrust( PGPKeyRef key, PGPUInt32 trust);
7faf5a
93725f PGPError ¤  ¤   PGPUnsetKeyAxiomatic( PGPKeyRef key);
e2af5a
2a1879 /* ·Get property functions */
eaaf5a
4cba0c PGPError ¤  ¤   PGPGetKeyBoolean( PGPKeyRef key, PGPKeyPropName propname,
f14a73 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean *prop);
66af5a
0fb6a1 PGPError ¤  ¤   PGPGetKeyNumber( PGPKeyRef key, PGPKeyPropName propname,
092ae2 ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 *prop);
47af5a
5f6bc7 /* 'buffer' is NOT null-terminated */
40f5f5 /* returns kPGPError_BufferTooSmall if buffer is too small, but
47187d fill buffer to capacity */
6f0048 PGPError ¤  ¤   PGPGetKeyPropertyBuffer( PGPKeyRef key,
6d1336 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyPropName propname,
604996 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize bufferSize, void *data, PGPSize *fullSize);
a8af5a
b6abff PGPError ¤  ¤   PGPGetKeyTime( PGPKeyRef key, PGPKeyPropName propname,
2f5ce4 ¤   ¤   ¤   ¤   ¤   ¤   PGPTime *prop);
53af5a
93a88c PGPError ¤  ¤   PGPGetSubKeyBoolean( PGPSubKeyRef subkey,
8c0bba ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyPropName propname, PGPBoolean *prop);
a0af5a
fc98e1 PGPError ¤  ¤   PGPGetSubKeyNumber( PGPSubKeyRef subkey,
eecc01 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyPropName propname, PGPInt32 *prop);
5baf5a
d9f5f5 /* returns kPGPError_BufferTooSmall if buffer is too small, but
c2187d fill buffer to capacity */
0184e3 PGPError ¤  ¤   PGPGetSubKeyPropertyBuffer( PGPSubKeyRef subkey,
fb1336 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyPropName propname,
bf741e ¤   ¤   ¤   ¤   ¤   ¤   PGPSize bufferSize, void *prop, PGPSize *fullSize);
36af5a
dd137c PGPError ¤  ¤   PGPGetSubKeyTime( PGPSubKeyRef subkey,
87b915 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyPropName propname, PGPTime *prop);
3baf5a
dbf9ba PGPError ¤  ¤   PGPGetUserIDNumber( PGPUserIDRef userID,
--5da8 000345f560a401002a4 Page 8 of pgpKeys.h
8810c7 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDPropName propname, PGPInt32 *prop);
edaf5a
930ef2 PGPError ¤  ¤   PGPGetUserIDBoolean( PGPUserIDRef userID,
ab8921 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDPropName propname, PGPBoolean *prop);
91af5a
d5634f /* 'string' is always NULL-terminated */
76f5f5 /* returns kPGPError_BufferTooSmall if buffer is too small, but
20187d fill buffer to capacity */
97a405 PGPError ¤  ¤   PGPGetUserIDStringBuffer( PGPUserIDRef userID,
6e99eb ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDPropName propname,
458989 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize bufferSize,
4fe591 ¤   ¤   ¤   ¤   ¤   ¤   char *¤ ¤   string,
306506 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *¤  fullSize);
4faf5a
fd6bc7 /* 'buffer' is NOT null-terminated */
17f5f5 /* returns kPGPError_BufferTooSmall if buffer is too small, but
89187d fill buffer to capacity */
6525c1 PGPError ¤  ¤   PGPGetSigPropertyBuffer( PGPSigRef cert,
945e8d ¤   ¤   ¤   ¤   ¤   ¤   PGPSigPropName propname,
724996 ¤   ¤   ¤   ¤   ¤   ¤   PGPSize bufferSize, void *data, PGPSize *fullSize);
6daf5a
fbc463 PGPError ¤  ¤   PGPGetSigBoolean( PGPSigRef cert,
624e14 ¤   ¤   ¤   ¤   ¤   ¤   PGPSigPropName propname, PGPBoolean *prop);
efaf5a
f082a0 PGPError ¤  ¤   PGPGetSigNumber( PGPSigRef cert, PGPSigPropName propname,
442ae2 ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 *prop);
4594aa ¤   ¤   ¤   ¤   ¤   ¤
2f0e2a PGPError ¤  ¤   PGPGetKeyIDOfCertifier( PGPSigRef sig, PGPKeyID *outID );
ef67c5 ¤
f5d761 PGPError ¤  ¤   PGPGetSigTime( PGPSigRef cert, PGPSigPropName propname,
975ce4 ¤   ¤   ¤   ¤   ¤   ¤   PGPTime *prop);
36af5a
a747b8 PGPError ¤  ¤   PGPGetHashAlgUsed( PGPKeyRef key, PGPHashAlgorithm *hashAlg);
6eaf5a
cc84a9 /* Convenience property functions */
60af5a
5a6ba9 PGPError ·¤ ¤   PGPGetPrimaryUserID( PGPKeyRef key, PGPUserIDRef *outRef );
bf6a9d PGPError¤   ¤   PGPGetPrimaryAttributeUserID (PGPKeyRef key,
22d5aa ¤   ¤   ¤   ¤   ¤   ¤   PGPAttributeType attributeType, PGPUserIDRef *outRef);
27af5a
8f5733 /* 'string' is always a C string and
cb7970 ¤   *fullSize includes the '\0' terminator */
7bf5f5 /* returns kPGPError_BufferTooSmall if buffer is too small, but
75187d fill buffer to capacity */
f7d7cf PGPError ¤  ¤   PGPGetPrimaryUserIDNameBuffer( PGPKeyRef key,·
6d01ef ¤   ¤   ¤   ¤   ¤   PGPSize bufferSize,
8a12b5 ¤   ¤   ¤   ¤   ¤   char *¤ string, PGPSize *fullSize );
11af5a
d36f5d PGPError ¤  ¤   PGPGetPrimaryUserIDValidity(PGPKeyRef key,
2999f1 ¤   ¤   ¤   ¤   ¤   PGPValidity *validity);
c0af5a
8aaf5a
0980fe PGPInt32 ¤  ¤   PGPCompareKeys(PGPKeyRef a, PGPKeyRef b,
21fcab ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyOrdering order);
0faf5a
99f9c3 PGPInt32 ¤  ¤   PGPCompareUserIDStrings(char const *a, char const *b);
77af5a
bb6ed7 PGPError ·¤ ¤   PGPOrderKeySet( PGPKeySetRef src,
b85fed ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyOrdering order, PGPKeyListRef *outRef );
aeaf5a
52e7e0 PGPError ¤  ¤   PGPIncKeyListRefCount( PGPKeyListRef keys);
3aaf5a
710b45 PGPError ¤  ¤   PGPFreeKeyList( PGPKeyListRef keys);
78af5a
19af5a
dfdbf8 /* Key iteration functions */
f2af5a
b2af5a
9caf5a
45ae5c PGPError ¤  ¤   PGPNewKeyIter (PGPKeyListRef keys, PGPKeyIterRef *outRef);
2faf5a
346447 PGPError ¤  ¤   PGPCopyKeyIter (PGPKeyIterRef orig, PGPKeyIterRef *outRef);
--faaa 0003f0f2a7f401002a4 Page 9 of pgpKeys.h
2a67c5 ¤
b1accb PGPError ¤  ¤   PGPFreeKeyIter (PGPKeyIterRef iter);
aaaf5a
9d2553 PGPInt32 ¤  ¤   PGPKeyIterIndex (PGPKeyIterRef iter);
b7af5a
9738fc PGPError ¤  ¤   PGPKeyIterRewind (PGPKeyIterRef iter);
d1af5a
241e6c PGPInt32 ¤  ¤   PGPKeyIterSeek (PGPKeyIterRef iter, PGPKeyRef key);
37af5a
3011fa PGPError ¤  ¤   PGPKeyIterMove (PGPKeyIterRef iter, PGPInt32 relOffset,
378513 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *outRef);
9caf5a
3a5a09 PGPError ¤  ¤   PGPKeyIterNext (PGPKeyIterRef iter, PGPKeyRef *outRef);
0baf5a
105da5 PGPError ¤  ¤   PGPKeyIterPrev (PGPKeyIterRef iter, PGPKeyRef *outRef);
2eaf5a
96e9c9 PGPError ¤  ¤   PGPKeyIterKey (PGPKeyIterRef iter, PGPKeyRef *outRef);
0aaf5a
f255a4 PGPError ·¤ ¤   PGPKeyIterSubKey (PGPKeyIterRef iter,
df7c28 ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKeyRef *outRef );
abaf5a
3cba40 PGPError ·¤ ¤   PGPKeyIterUserID (PGPKeyIterRef iter,
3a25cb ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDRef *outRef );
7a16a6 PGPError ·¤ ¤   PGPKeyIterSig (PGPKeyIterRef iter,
64ef6a ¤   ¤   ¤   ¤   ¤   ¤   PGPSigRef *outRef );
caaf5a
11a676 PGPError ·¤ ¤   PGPKeyIterNextSubKey (PGPKeyIterRef iter,
e17c28 ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKeyRef *outRef );
beaf5a
5841aa PGPError ·¤ ¤   PGPKeyIterPrevSubKey (PGPKeyIterRef iter,
8fcdb0 ¤   ¤   ¤   ¤   ¤   ¤   PGPSubKeyRef *outRef);
10af5a
33f108 PGPError ¤  ¤   PGPKeyIterRewindSubKey (PGPKeyIterRef iter);
59af5a
ea4992 PGPError ·¤ ¤   PGPKeyIterNextUserID (PGPKeyIterRef iter,
3ff35b ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDRef *outRef);
4daf5a
7fae4e PGPError ·¤ ¤   PGPKeyIterPrevUserID (PGPKeyIterRef iter,
66f35b ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDRef *outRef);
9aaf5a
5650cd PGPError ¤  ¤   PGPKeyIterRewindUserID (PGPKeyIterRef iter);
61af5a
e04d8d PGPError ·¤ ¤   PGPKeyIterNextUIDSig (PGPKeyIterRef iter,
783e57 ¤   ¤   ¤   ¤   ¤   ¤   PGPSigRef *outRef);
fcaf5a
98aa51 PGPError ·¤ ¤   PGPKeyIterPrevUIDSig (PGPKeyIterRef iter,
f83e57 ¤   ¤   ¤   ¤   ¤   ¤   PGPSigRef *outRef);
2aaf5a
68b8bf PGPError ¤  ¤   PGPKeyIterRewindUIDSig (PGPKeyIterRef iter);
79af5a
b6af5a
c42c21 /* Get/set default private key */
e9af5a
89c8e9 PGPError ¤  ¤   PGPGetDefaultPrivateKey( PGPKeySetRef keyset,
f6ebf1 ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef *outRef );
38af5a
6c05fa PGPError ¤  ¤   PGPSetDefaultPrivateKey( PGPKeyRef key);
0eaf5a
adaf5a
2faf5a
e01710 /* Get/set user value */
e4af5a
231ca1 PGPError ¤  ¤   PGPSetKeyUserVal( PGPKeyRef key, PGPUserValue userValue);
76af5a
74b43a PGPError ¤  ¤   PGPSetUserIDUserVal( PGPUserIDRef userid,
c0f0bd ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue);
c8af5a
9e9e2c PGPError ¤  ¤   PGPSetSubKeyUserVal( PGPSubKeyRef subkey,
43f0bd ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue);
e2af5a
e06b5c PGPError ¤  ¤   PGPSetSigUserVal( PGPSigRef cert,
3ff0bd ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue);
--a0ca 00073b32d00401002a4 Page 10 of pgpKeys.h
e0af5a
31868b PGPError ¤  ¤   PGPGetKeyUserVal( PGPKeyRef key,
350274 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue *userValue);
26af5a
431937 PGPError ¤  ¤   PGPGetUserIDUserVal( PGPUserIDRef userid,
530274 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue *userValue);
88af5a
5a3321 PGPError ¤  ¤   PGPGetSubKeyUserVal( PGPSubKeyRef subkey,
580274 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue *userValue);
e9af5a
0d5433 PGPError ¤  ¤   PGPGetSigUserVal( PGPSigRef cert,
9d0274 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue *userValue);
b7af5a
37f378 /* Passphrase conversion to passkeybuffer */
76a390 /* The size of the output buffer is from the kPGPKeyPropLockingBits property */
25af5a
4affc0 PGPError¤   ¤   PGPGetKeyPasskeyBuffer ( PGPKeyRef key,
73eebc ¤   ¤   ¤   ¤   ¤   ¤   void *passkeyBuffer, PGPOptionListRef firstOption,...);
d0af5a
d1d4dc PGPError¤   ¤   PGPGetSubKeyPasskeyBuffer ( PGPSubKeyRef subkey,
6ceebc ¤   ¤   ¤   ¤   ¤   ¤   void *passkeyBuffer, PGPOptionListRef firstOption,...);
a3af5a
14af5a
976ad7 /* Change key options which are stored in self signatures internally */
33af5a
28c545 PGPError¤   ¤   PGPAddKeyOptions( PGPKeyRef key,
4f64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
0caf5a
2f8b84 PGPError¤   ¤   PGPRemoveKeyOptions( PGPKeyRef key,
3a64e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
22af5a
4c4532 PGPError¤   ¤   PGPUpdateKeyOptions( PGPKeyRef key,
5064e4 ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
74af5a
19af5a
86af5a
0e0335 /*____________________________________________________________________________
03d06d ¤   Key IDs
50f7f7 ____________________________________________________________________________*/
e3a97f PGPError ¤  PGPGetKeyIDFromString(
7e2bd1 ¤   ¤   ¤   ¤   const char *string, PGPKeyID *id );
13ae30 ¤   ¤   ¤   ¤   ¤
b63fd7 PGPError ¤  PGPGetKeyIDFromKey( PGPKeyRef key, PGPKeyID *id );
49af5a
a40c34 PGPError ¤  PGPGetKeyIDFromSubKey( PGPSubKeyRef key, PGPKeyID * id );
baaf5a
443a1c enum PGPKeyIDStringType_
bebb36 {
80d4e5 ¤   kPGPKeyIDString_Abbreviated = 2,
325ac4 ¤   kPGPKeyIDString_Full = 3,
069d3b ¤   PGP_ENUM_FORCE( PGPKeyIDStringType_ )
8d82f7 };
79ac57 PGPENUM_TYPEDEF( PGPKeyIDStringType_, PGPKeyIDStringType );
9caf5a
dbaf5a
0d8d5c #define kPGPMaxKeyIDStringSize¤ ¤   ( 127 + 1 )
833bc9 PGPError ¤  PGPGetKeyIDString( PGPKeyID const * ref,
adc64c ¤   ¤   ¤   ¤   ¤   PGPKeyIDStringType type,
1389fe ¤   ¤   ¤   ¤   ¤   char outString[ kPGPMaxKeyIDStringSize ] );
ffaf5a
59af5a
842964 /* outputs opaque string of bytes for storage of maximum size as keyID*/
f65a02 /* do NOT attempt to parse the output; it is opaque to you */
f74f16 #define kPGPMaxExportedKeyIDSize¤   ¤   ( sizeof( PGPKeyID ) )
132f0d PGPError ¤  PGPExportKeyID( PGPKeyID const * keyID,
b7e80d ¤   ¤   ¤   ¤   ¤   PGPByte exportedData[ kPGPMaxExportedKeyIDSize ],
b1fde3 ¤   ¤   ¤   ¤   ¤   PGPSize *exportedLength );
8faf5a
329cb7 /* must be in format output by PGPExportKeyID */
152088 PGPError ¤  PGPImportKeyID( ·void const * data, PGPKeyID * id );
efaf5a
735b21 /* returns 0 if equal, -1 if key1 < key2, 1 if key1 > key2 */
--c1dc 0011f6d1c7f401002a4 Page 11 of pgpKeys.h
708b55 PGPInt32 ¤  PGPCompareKeyIDs( PGPKeyID const * key, PGPKeyID const * key2);
c6af5a
9caf5a
63af5a
afaf5a
e10335 /*____________________________________________________________________________
ad9df5 ¤   Getting contexts back from key related items. ·If the key is invalid,
ffc578 ¤   you get kPGPInvalidRef back.
b0f7f7 ____________________________________________________________________________*/
75af5a
6a796b PGPContextRef¤  PGPGetKeyListContext( PGPKeyListRef ref );
4033b7 PGPContextRef¤  PGPGetKeySetContext( PGPKeySetRef ref );
e57474 PGPContextRef¤  PGPGetKeyIterContext( PGPKeyIterRef ref );
fe960a PGPContextRef¤  PGPGetKeyContext( PGPKeyRef ref );
ecb9c1 PGPContextRef¤  PGPGetSubKeyContext( PGPSubKeyRef ref );
223f39 PGPContextRef¤  PGPGetUserIDContext( PGPUserIDRef ref );
49af5a
c6af5a
870335 /*____________________________________________________________________________
62a84f ····Secret sharing functionality
30f7f7 ____________________________________________________________________________*/
64af5a
c8e4f8 PGPError¤   ¤   PGPSecretShareData(PGPContextRef context,
689e05 ¤   ¤   ¤   ¤   ¤   ¤   void const * input, PGPSize inputBytes,
23c63a ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 threshold, PGPUInt32 nShares, void * output);
32af5a
bcc7fa PGPError¤   ¤   PGPSecretReconstructData(PGPContextRef context,
454439 ¤   ¤   ¤   ¤   ¤   ¤   void * input, PGPSize outputBytes,
9947f3 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 nShares, void * output);
bbaf5a
67af5a
f50335 /*____________________________________________________________________________
8c918f ····X509 certificate specific
a6f7f7 ____________________________________________________________________________*/
3faf5a
861727 PGPError¤   ¤   PGPVerifyX509CertificateChain (PGPContextRef context,
06fdbc ¤   ¤   ¤   ¤   ¤   ¤   PGPByte *certchain, PGPByte *rootcerts);
c9af5a
e4af5a
8ccbcf #if PRAGMA_IMPORT_SUPPORTED
f12ced #pragma import reset
b77454 #endif
5e1254 PGP_END_C_DECLARATIONS
3baf5a
c1af5a
469896 #endif /* ] Included_pgpKeys_h */
06af5a
2b7e4d /*__Editor_settings____
30af5a
494126 ¤   Local Variables:
857b17 ¤   tab-width: 4
0a0e6c ¤   End:
555f8c ¤   vi: ts=4 sw=4
f69e9b ¤   vim: si
1fd062 _____________________*/
--78bb 000a4a815e7401002a5 Page 1 of pgpOptionList.h
a70335 /*____________________________________________________________________________
51fd27 ¤   pgpOptionList.h
2d67c5 ¤
2bc97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
1b4b0f ¤   All rights reserved.
4067c5 ¤
286a17 ¤   This file contains the types and prototypes for functions which manipulate
b4ca28 ¤   PGPOptionList data structures.
bbaf5a
e3f815 ¤   $Id: pgpOptionList.h,v 1.12.10.1 1998/11/12 03:23:38 heller Exp $
83f7f7 ____________________________________________________________________________*/
7faf5a
743994 #ifndef Included_pgpOptionList_h¤   /* [ */
920d19 #define Included_pgpOptionList_h
8aaf5a
94d92d #include <stdarg.h>
67af5a
09e82c #include "pgpPubTypes.h"
5aaf5a
e40ccc #if PGP_MACINTOSH
c549ca #include <Files.h>
b17454 #endif
c1af5a
2b1a83 /* Standard event callback declaration */
b8a7f5 struct PGPEvent;
0d1076 typedef PGPError (*PGPEventHandlerProcPtr)(PGPContextRef context,
35b3c1 ¤   ¤   ¤   ¤   ¤   ¤   struct PGPEvent *event, PGPUserValue userValue);
53af5a
1d99c6 PGP_BEGIN_C_DECLARATIONS
acaf5a
6bcbcf #if PRAGMA_IMPORT_SUPPORTED
0bb981 #pragma import on
037454 #endif
22af5a
58a966 PGPError¤   PGPNewOptionList(PGPContextRef context,
85e457 ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *outList);
19a8c1 PGPError ¤  PGPAppendOptionList(PGPOptionListRef optionList,
eeebb3 ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
087039 PGPError ¤  PGPBuildOptionList( PGPContextRef context,
9f1f6b ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *outList,
beebb3 ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
b1354c PGPError¤   PGPCopyOptionList(PGPOptionListRef optionList,
cfefb0 ¤   ¤   ¤   ¤   ¤   PGPOptionListRef *outList );
6f4c51 PGPError ¤  PGPFreeOptionList(PGPOptionListRef optionList);
23af5a
3a38e5 /*
9a67bc **¤ The following functions are used to create PGPOptionListRef's for
f16a93 **¤ specifying the various options to several SDK functions. The
aec68e **¤ functions can be used as inline parameters in a temporary manner or
df378b **¤ used with PGPBuildOptionList() to create persistent lists.
b97fe0 */
55af5a
5738e5 /*
17d30b ** Special PGPOptionListRef to mark last option passed to those functions
48cc31 ** which take variable lists of PGPOptionListRef's:
c67fe0 */
54af5a
8f580d PGPOptionListRef ¤  ¤   PGPOLastOption( PGPContextRef context );
80af5a
0538e5 /*
3d651e ** Special PGPOptionListRef which is always ignored:
0a7fe0 */
39af5a
bb563d PGPOptionListRef ¤  ¤   PGPONullOption( PGPContextRef context);
03af5a
ee05e4 /* Data input (required): */
59af5a
dfa2db PGPOptionListRef ¤  ¤   PGPOInputFile( PGPContextRef context,
813ace ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef fileRef);
f36a49 PGPOptionListRef ¤  ¤   PGPOInputBuffer( PGPContextRef context,
9b3922 ¤   ¤   ¤   ¤   ¤   ¤   ¤   void const *buffer, PGPSize bufferSize);
a40ccc #if PGP_MACINTOSH
--ef6a 0004244e4f5401002a5 Page 2 of pgpOptionList.h
5d2ed3 PGPOptionListRef ¤  ¤   PGPOInputFileFSSpec( PGPContextRef context,
e857c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const FSSpec *fileSpec);
587454 #endif
e467c5 ¤
37e1f2 /* Data output (optional, generates event if missing): */
9baf5a
58b75d PGPOptionListRef ¤  ¤   PGPOOutputFile( PGPContextRef context,
543ace ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef fileRef);
e0f579 PGPOptionListRef ¤  ¤   PGPOOutputBuffer( PGPContextRef context,
8a04b6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   void *buffer, PGPSize bufferSize,
0b46e6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *outputDataLength);
610ccc #if PGP_MACINTOSH
b4a19f PGPOptionListRef ¤  ¤   PGPOOutputFileFSSpec( PGPContextRef context,
5257c4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const FSSpec *fileSpec);
a47454 #endif
bbaf5a
1a5a77 /* '*buffer' must be disposed of via PGPFreeData() */
c67b1c /* maximum memory usage will be no more than maximumBufferSize */
c4623d PGPOptionListRef ¤  ¤   PGPOAllocatedOutputBuffer(PGPContextRef context,
63692d ¤   ¤   ¤   ¤   ¤   ¤   ¤   void **buffer,
a0fe94 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize maximumBufferSize,
bb5431 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPSize *actualBufferSize);
5264c1 PGPOptionListRef ¤  ¤   PGPOAppendOutput( PGPContextRef context,
27b402 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean appendOutput );
a41dc1 PGPOptionListRef ¤  ¤   PGPODiscardOutput( PGPContextRef context,
b32c40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean discardOutput );
5eaf5a
36add3 /* Encrypting and signing */
41af5a
28a0ed PGPOptionListRef ¤  ¤   PGPOEncryptToKey( PGPContextRef context,
5e2814 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef keyRef);
19b7b1 PGPOptionListRef ¤  ¤   PGPOEncryptToKeySet( PGPContextRef context,
aee2d7 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keySetRef);
17e055 PGPOptionListRef ¤  ¤   PGPOEncryptToUserID( PGPContextRef context,
4ba0d1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserIDRef userIDRef);
3ff0ec PGPOptionListRef ¤  ¤   PGPOSignWithKey( PGPContextRef context,
120001 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef keyRef,
7ea0f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
1543e0 PGPOptionListRef ¤  ¤   PGPOConventionalEncrypt( PGPContextRef context,
87f885 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption,
93e7ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ...);
02af5a
1f584a PGPOptionListRef ¤  ¤   PGPOPassphraseBuffer( PGPContextRef context,
6e0598 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const void *passphrase, PGPSize passphraseLength);
18ef4b PGPOptionListRef ¤  ¤   PGPOPassphrase( PGPContextRef context,
87891b ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char *passphrase);
3fa9b7 PGPOptionListRef ¤  ¤   PGPOPasskeyBuffer( PGPContextRef context,
14fbcc ¤   ¤   ¤   ¤   ¤   ¤   ¤   const void *passkey, PGPSize passkeyLength);
19ce16 PGPOptionListRef ¤  ¤   PGPOAskUserForEntropy( PGPContextRef context,
c49092 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean askUserForEntropy );
b69af6 PGPOptionListRef ¤  ¤   PGPORawPGPInput( PGPContextRef context,
4aa5bf ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean rawPGPInput );
206476 PGPOptionListRef ¤  ¤   PGPOCompression( PGPContextRef context,
a9e9e4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean compression );
daaf5a
133085 PGPOptionListRef¤   ¤   PGPOLocalEncoding( PGPContextRef context,
e7bf08 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPLocalEncodingFlags localEncode);
eb7587 PGPOptionListRef¤   ¤   PGPOOutputLineEndType(PGPContextRef context,
3424fd ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPLineEndType lineEnd);
bcb989 PGPOptionListRef¤   ¤   PGPOPGPMIMEEncoding(PGPContextRef context,
9763a0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean mimeEncoding, PGPSize *mimeBodyOffset,
776dfd ¤   ¤   ¤   ¤   ¤   ¤   ¤   char mimeSeparator[ kPGPMimeSeparatorSize ]);
2270e5 PGPOptionListRef¤   ¤   PGPOOmitMIMEVersion( PGPContextRef context,
115104 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean omitVersion);
d78097 PGPOptionListRef¤   ¤   PGPOX509Encoding( PGPContextRef context,
5e5cee ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean x509Encoding);
28531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
5cdb18 PGPOptionListRef ¤  ¤   PGPODetachedSig( PGPContextRef context,
c5f885 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption,
e6e7ed ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ...);
15af5a
425eba PGPOptionListRef ¤  ¤   PGPOCipherAlgorithm( PGPContextRef context,
--b21a 000bd983fe2401002a5 Page 3 of pgpOptionList.h
3cb050 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPCipherAlgorithm algorithm);
b517a9 PGPOptionListRef ¤  ¤   PGPOHashAlgorithm( PGPContextRef context,
120c40 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPHashAlgorithm algorithm);
cfaf5a
7b6d6f PGPOptionListRef ¤  ¤   PGPOFailBelowValidity( PGPContextRef context,
be0bc5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPValidity minValidity);
b4a04b PGPOptionListRef ¤  ¤   PGPOWarnBelowValidity( PGPContextRef context,
bc0bc5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPValidity minValidity);
08af5a
91af5a
ef8db1 PGPOptionListRef ¤  ¤   PGPOEventHandler( PGPContextRef context,
0c9e2b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr eventHandler,
ea171a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue eventHandlerData);
a61454 PGPOptionListRef ¤  ¤   PGPOSendNullEvents( PGPContextRef context,
edc0db ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPTimeInterval approxInterval);
8a67c5 ¤
c2d22a PGPOptionListRef ¤  ¤   PGPOArmorOutput( PGPContextRef context,
97929e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean armorOutput );
b33be4 PGPOptionListRef ¤  ¤   PGPODataIsASCII( PGPContextRef context,
b79347 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean dataIsASCII );
509110 PGPOptionListRef ¤  ¤   PGPOClearSign( PGPContextRef context,
ffba8e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean clearSign );
85846c PGPOptionListRef ¤  ¤   PGPOForYourEyesOnly( PGPContextRef context,
35e04d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean forYourEyesOnly );
350084 PGPOptionListRef ¤  ¤   PGPOKeySetRef( PGPContextRef context,
8815ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keysetRef);
11af5a
5d446c PGPOptionListRef ¤  ¤   PGPOImportKeysTo( PGPContextRef context,
e015ee ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keysetRef);
da0f83 PGPOptionListRef ¤  ¤   PGPOSendEventIfKeyFound( PGPContextRef context,
fdbc49 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean sendEventIfKeyFound );
d4d904 PGPOptionListRef ¤  ¤   PGPOPassThroughIfUnrecognized( PGPContextRef context,
d83968 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean passThroughIfUnrecognized );
75c430 PGPOptionListRef ¤  ¤   PGPOPassThroughClearSigned( PGPContextRef context,
be8649 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean passThroughClearSigned );
04865d PGPOptionListRef ¤  ¤   PGPOPassThroughKeys( PGPContextRef context,
9f6a1f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean passThroughKeys );
f0335f PGPOptionListRef ¤  ¤   PGPORecursivelyDecode( PGPContextRef context,
c361d3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean recurse );
e7af5a
5df738 PGPOptionListRef¤   ¤   PGPOKeyGenParams( PGPContextRef context,
6e8365 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPPublicKeyAlgorithm pubKeyAlg,
0c6ec4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 bits);
e0da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
611c0e PGPOptionListRef¤   ¤   PGPOKeyGenName( PGPContextRef context,
371d01 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const void *name, PGPSize nameLength);
03531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
21e8a9 PGPOptionListRef¤   ¤   PGPOCreationDate( PGPContextRef context,
03be69 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPTime creationDate);
29f2f1 PGPOptionListRef¤   ¤   PGPOExpiration( PGPContextRef context,
72d32a ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 expirationDays);
0c531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
26842e PGPOptionListRef¤   ¤   PGPOAdditionalRecipientRequestKeySet(
3d4f20 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,·
07bcfd ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef arKeySetRef, PGPByte arkClass);
f3da4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
00b633 PGPOptionListRef¤   ¤   PGPORevocationKeySet(PGPContextRef¤ context,
83bdf0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef raKeySetRef);
74af5a
0a2af5 PGPOptionListRef¤   ¤   PGPOKeyGenMasterKey( PGPContextRef context,
3b09a5 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef masterKeyRef);
31531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
e27f6e PGPOptionListRef¤   ¤   PGPOPreferredAlgorithms(
9f4f20 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,·
490f96 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPCipherAlgorithm const *prefAlg,
c3336d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 numAlgs);
bcda4b ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
c9fe7b PGPOptionListRef¤   ¤   PGPOKeyGenFast( PGPContextRef context,
f9da61 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean fastGen);
42531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
7a7fea PGPOptionListRef¤   ¤   PGPOCommentString( PGPContextRef context,
bd415f ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *comment);
--9810 001c8728fe2401002a5 Page 4 of pgpOptionList.h
e0af5a
849113 PGPOptionListRef¤   ¤   PGPOVersionString( PGPContextRef context,
27171b ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *version);
ce531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
bfdf24 PGPOptionListRef¤   ¤   PGPOFileNameString( PGPContextRef context,
7c5546 ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *fileName);
de531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
6b6e6c PGPOptionListRef¤   ¤   PGPOSigRegularExpression(PGPContextRef context,
f04bae ¤   ¤   ¤   ¤   ¤   ¤   ¤   char const *regularExpression);
26531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
b16363 PGPOptionListRef¤   ¤   PGPOExportPrivateKeys( PGPContextRef context,
ea4e63 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean exportKeys);
9c531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
657cf5 PGPOptionListRef¤   ¤   PGPOExportPrivateSubkeys( PGPContextRef context,
d9c05d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean exportSubkeys);
b1531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
b5e7d4 PGPOptionListRef¤   ¤   PGPOExportFormat(PGPContextRef context,
997296 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPExportFormat exportFormat);
5daf5a
6672d2 PGPOptionListRef¤   ¤   PGPOExportable( PGPContextRef context,
67c249 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean exportable);
1f531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
a065aa PGPOptionListRef¤   ¤   PGPOSigTrust( PGPContextRef context,
3fe868 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 trustLevel,
afe27b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 trustValue);
a7af5a
bacbcf #if PRAGMA_IMPORT_SUPPORTED
6f2ced #pragma import reset
007454 #endif
e467c5 ¤
8f1254 PGP_END_C_DECLARATIONS
b7af5a
f1f454 #endif /* ] Included_pgpOptionList_h */
e9af5a
4b7e4d /*__Editor_settings____
47af5a
7f4126 ¤   Local Variables:
f17b17 ¤   tab-width: 4
e00e6c ¤   End:
595f8c ¤   vi: ts=4 sw=4
309e9b ¤   vim: si
c8d062 _____________________*/
--6657 000d0aab5c6401002a6 Page 1 of pgpPubTypes.h
a70335 /*____________________________________________________________________________
04c56c ¤   pgpPubTypes.h
4d67c5 ¤
19c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
5c4b0f ¤   All rights reserved.
7b67c5 ¤
56927b ¤   Opaque types for various modules go in this file.
a6af5a
ab1548 ¤   $Id: pgpPubTypes.h,v 1.43.10.1 1998/11/12 03:23:39 heller Exp $
03f7f7 ____________________________________________________________________________*/
154d0a #ifndef Included_pgpPubTypes_h¤ /* [ */
669a3b #define Included_pgpPubTypes_h
54af5a
14af5a
a9e2ff #include "pgpConfig.h"
aac5d5 #include "pgpBase.h"
41af5a
f2af5a
ea0335 /*____________________________________________________________________________
d9c84e ¤   General data types used by PGPsdk
e5f7f7 ____________________________________________________________________________*/
58420f typedef struct PGPContext *¤¤   PGPContextRef;
c7231b typedef struct PGPFileSpec *¤   PGPFileSpecRef;
2aa86c typedef struct PGPOptionList * ¤PGPOptionListRef;
4faf5a
1d0335 /*____________________________________________________________________________
e5525c ¤   Data types used by the key manipulation functions
29f7f7 ____________________________________________________________________________*/
10af5a
ec7411 typedef struct PGPKeyDB *¤  ¤   PGPKeyDBRef;
c4047f typedef struct PGPKey *¤¤   ¤   PGPKeyRef;
b6d3f7 typedef struct PGPSubKey * ·¤   PGPSubKeyRef;
ae65b0 typedef struct PGPUserID *¤ ¤   PGPUserIDRef;
a8edc9 typedef struct PGPSig *¤¤   ¤   PGPSigRef;
20dc7e typedef struct PGPKeySet *¤ ¤   PGPKeySetRef;
87746a typedef struct PGPKeyList *¤¤   PGPKeyListRef;
01e0ec typedef struct PGPKeyIter *¤¤   PGPKeyIterRef;
a08bd6 typedef struct PGPFilter *¤ ¤   PGPFilterRef;
e7af5a
2c7cfc typedef struct PGPKeyID
f9bb36 {
d020cb ¤   /* do not attempt to interpret these bytes; they *will* change */
5fee98 ¤   PGPByte¤¤   opaqueBytes[ 34 ];
c3a2da } PGPKeyID;
b9af5a
b5af5a
100335 /*____________________________________________________________________________
103690 ¤   Data types used by symmetric ciphers, cipher modes, hashing
1ff7f7 ____________________________________________________________________________*/
62b95e typedef struct PGPHashContext *¤¤   ¤   ¤   PGPHashContextRef;
f78a8a typedef struct PGPHMACContext *¤¤   ¤   ¤   PGPHMACContextRef;
2f3a7f typedef struct PGPPublicKeyContext *¤   ¤   PGPPublicKeyContextRef;
4c1ab6 typedef struct PGPPrivateKeyContext *¤  ¤   PGPPrivateKeyContextRef;
154544 typedef struct PGPCBCContext *¤ ¤   ¤   ¤   PGPCBCContextRef;
7fa6fd typedef struct PGPCFBContext *¤ ¤   ¤   ¤   PGPCFBContextRef;
564d7c typedef struct PGPSymmetricCipherContext *¤ PGPSymmetricCipherContextRef;
44af5a
270335 /*____________________________________________________________________________
dbdcd5 ¤   Data types used by keyserver code
49f7f7 ____________________________________________________________________________*/
66af5a
1e9f66 typedef struct PGPKeyServer *¤  PGPKeyServerRef;
eaaf5a
f60335 /*____________________________________________________________________________
5ed71d ¤   Invalid values for each of the "ref" data types. Use these for assignment
9bfb48 ¤   and initialization only. Use the PGPXXXRefIsValid macros (below) to test
5a96cc ¤   for valid/invalid values.
f8f7f7 ____________________________________________________________________________*/
f4af5a
d836bd #define¤kInvalidPGPContextRef¤  ¤   ((PGPContextRef) NULL)
8ec278 #define¤kInvalidPGPFileSpecRef¤ ¤   ((PGPFileSpecRef) NULL)
d07bec #define¤kInvalidPGPOptionListRef¤   ((PGPOptionListRef) NULL)
--5b05 0002bbcd40b401002a6 Page 2 of pgpPubTypes.h
e0af5a
0fe7fc #define¤kInvalidPGPKeyDBRef¤¤   ¤   ((PGPKeyDBRef) NULL)
4ad88d #define¤kInvalidPGPKeyRef¤  ¤   ¤   ((PGPKeyRef) NULL)
b7889e #define¤kInvalidPGPSubKeyRef¤   ¤   ((PGPSubKeyRef) NULL)
b5ed37 #define¤kInvalidPGPUserIDRef¤   ¤   ((PGPUserIDRef) NULL)
2806d7 #define¤kInvalidPGPSigRef¤  ¤   ¤   ((PGPSigRef) NULL)
1993d3 #define¤kInvalidPGPKeySetRef¤   ¤   ((PGPKeySetRef) NULL)
6588bb #define¤kInvalidPGPKeyListRef¤  ¤   ((PGPKeyListRef) NULL)
dc9dc2 #define¤kInvalidPGPKeyIterRef¤  ¤   ((PGPKeyIterRef) NULL)
daef50 #define¤kInvalidPGPFilterRef¤   ¤   ((PGPFilterRef) NULL)
120aaf #define¤kInvalidPGPKeyServerRef¤¤   ((PGPKeyServerRef) NULL)
deaf5a
32af5a
e9527b #define¤kInvalidPGPHashContextRef¤  ¤   ¤   ¤   ¤   \
0bba11 ¤   ¤   ¤   ((PGPHashContextRef) NULL)
87a4af #define¤kInvalidPGPHMACContextRef¤  ¤   ¤   ¤   ¤   \
65ee89 ¤   ¤   ¤   ((PGPHMACContextRef) NULL)
cde987 #define¤kInvalidPGPCFBContextRef¤   ¤   ¤   \
1a5588 ¤   ¤   ¤   ((PGPCFBContextRef) NULL)
9ac08f #define¤kInvalidPGPCBCContextRef¤   ¤   ¤   \
3ca3aa ¤   ¤   ¤   ((PGPCBCContextRef) NULL)
3666a8 #define¤kInvalidPGPSymmetricCipherContextRef¤   ¤   \
e1dfe9 ¤   ¤   ¤   ((PGPSymmetricCipherContextRef) NULL)
c7d139 #define kInvalidPGPPublicKeyContextRef¤ ¤   \
f4d840 ¤   ¤   ¤   ((PGPPublicKeyContextRef) NULL)
59309d #define kInvalidPGPPrivateKeyContextRef¤¤   \
ff2bcd ¤   ¤   ¤   ((PGPPrivateKeyContextRef) NULL)
9faf5a
f49813 /*¤ kPGPInvalidRef is deprecated. Please use a type-specific version ·*/
f0d390 #define kPGPInvalidRef¤ ¤   ¤   ¤   NULL
6baf5a
360335 /*____________________________________________________________________________
9cd9db ¤   Macros to test for ref validity. Use these in preference to comparing
8967f8 ¤   directly with the kInvalidXXXRef values.
05f7f7 ____________________________________________________________________________*/
abaf5a
ce30ec #define PGPContextRefIsValid( ref )¤¤   ( (ref) != kInvalidPGPContextRef )
b0e4a3 #define PGPFileSpecRefIsValid( ref )¤   ( (ref) != kInvalidPGPFileSpecRef )
06e349 #define PGPOptionListRefIsValid( ref )¤ ( (ref) != kInvalidPGPOptionListRef )
19af5a
73e927 #define PGPKeyDBRefIsValid( ref )¤  ¤   ( (ref) != kInvalidPGPKeyDBRef )
2d55f1 #define PGPKeyRefIsValid( ref )¤¤   ¤   ( (ref) != kInvalidPGPKeyRef )
f4f16e #define PGPSubKeyRefIsValid( ref )¤ ¤   ( (ref) != kInvalidPGPSubKeyRef )
39d383 #define PGPUserIDRefIsValid( ref )¤ ¤   ( (ref) != kInvalidPGPUserIDRef )
1ad582 #define PGPSigRefIsValid( ref )¤¤   ¤   ( (ref) != kInvalidPGPSigRef )
200941 #define PGPKeySetRefIsValid( ref )¤ ¤   ( (ref) != kInvalidPGPKeySetRef )
322bf7 #define PGPKeyListRefIsValid( ref )¤¤   ( (ref) != kInvalidPGPKeyListRef )
4b175e #define PGPKeyIterRefIsValid( ref )¤¤   ( (ref) != kInvalidPGPKeyIterRef )
5ed9df #define PGPFilterRefIsValid( ref )¤ ¤   ( (ref) != kInvalidPGPFilterRef )
37eea8 #define PGPKeyServerRefIsValid( ref )¤  ( (ref) != kInvalidPGPKeyServerRef )
37af5a
f3e8b2 #define PGPHashContextRefIsValid( ref )¤¤   ¤   ¤   ¤   ¤   ¤   \
4ea92c ¤   ¤   ¤   ( (ref) != kInvalidPGPHashContextRef )
ad4cce #define PGPHMACContextRefIsValid( ref )¤¤   ¤   ¤   ¤   ¤   ¤   \
e92c00 ¤   ¤   ¤   ( (ref) != kInvalidPGPHMACContextRef )
a34c83 #define PGPCFBContextRefIsValid( ref )¤ ¤   ¤   ¤   \
67928c ¤   ¤   ¤   ( (ref) != kInvalidPGPCFBContextRef )
4c48c6 #define PGPCBCContextRefIsValid( ref )¤ ¤   ¤   ¤   \
f8c4df ¤   ¤   ¤   ( (ref) != kInvalidPGPCBCContextRef )
01898c #define PGPSymmetricCipherContextRefIsValid( ref )¤ ¤   ¤   ¤   \
9cd89a ¤   ¤   ¤   ( (ref) != kInvalidPGPSymmetricCipherContextRef )
658186 #define PGPPublicKeyContextRefIsValid( ref )¤   ¤   ¤   ¤   \
fd87d5 ¤   ¤   ¤   ( (ref) != kInvalidPGPPublicKeyContextRef )
502d9c #define PGPPrivateKeyContextRefIsValid( ref )¤  ¤   ¤   ¤   \
18d6fa ¤   ¤   ¤   ( (ref) != kInvalidPGPPrivateKeyContextRef )
17af5a
9bc281 /*¤ PGPRefIsValid() is deprecated. Please use a type-specific version ·*/
615087 #define PGPRefIsValid( ref )¤   ¤   ¤   ( (ref) != kPGPInvalidRef )
20af5a
220335 /*____________________________________________________________________________
a8c868 ¤   Symmetric Ciphers
2bf7f7 ____________________________________________________________________________*/
--03be 000a279cb93401002a6 Page 3 of pgpPubTypes.h
e0af5a
0da445 enum PGPCipherAlgorithm_
77bb36 {
26c144 ¤   /* do NOT change these values */
3978e6 ¤   kPGPCipherAlgorithm_None¤   = 0,
352071 ¤   kPGPCipherAlgorithm_IDEA¤   = 1,
a6ef1a ¤   kPGPCipherAlgorithm_3DES¤   = 2,
9b5281 ¤   kPGPCipherAlgorithm_CAST5¤  = 3,
a767c5 ¤
08e423 ¤   PGP_ENUM_FORCE( PGPCipherAlgorithm_ )
2482f7 };
94d54d PGPENUM_TYPEDEF( PGPCipherAlgorithm_, PGPCipherAlgorithm );
e3af5a
770335 /*____________________________________________________________________________
3d27a4 ¤   Hash algorithms
3cf7f7 ____________________________________________________________________________*/
e6af5a
7c4679 enum PGPHashAlgorithm_
5cbb36 {
c1c144 ¤   /* do NOT change these values */
cd7e56 ¤   kPGPHashAlgorithm_Invalid¤  = 0,
3a6b19 ¤   kPGPHashAlgorithm_MD5¤  ¤   = 1,
814949 ¤   kPGPHashAlgorithm_SHA¤  ¤   = 2,
3d578b ¤   kPGPHashAlgorithm_RIPEMD160¤= 3,
d0af5a
607b9e ¤   PGP_ENUM_FORCE( PGPHashAlgorithm_ )
0a82f7 };
282c6f PGPENUM_TYPEDEF( PGPHashAlgorithm_, PGPHashAlgorithm );
daaf5a
b00335 /*____________________________________________________________________________
ee901b ¤   Public/Private key algorithms
d6f7f7 ____________________________________________________________________________*/
d4763b enum PGPPublicKeyAlgorithm_
fbbb36 {
ae9755 ¤   /* note: do NOT change these values */
35e28f ¤   kPGPPublicKeyAlgorithm_Invalid¤ ¤   ¤   = 0xFFFFFFFF,
8ccb6b ¤   kPGPPublicKeyAlgorithm_RSA¤ ¤   ¤   ¤   = 1,
ddf8d9 ¤   kPGPPublicKeyAlgorithm_RSAEncryptOnly¤  = 2,
132d8e ¤   kPGPPublicKeyAlgorithm_RSASignOnly¤ ¤   = 3,
6f1797 ¤   kPGPPublicKeyAlgorithm_ElGamal¤ ¤   ¤   = 0x10, /* A.K.A.Diffie-Hellman */
177546 ¤   kPGPPublicKeyAlgorithm_DSA¤ ¤   ¤   ¤   = 0x11,
a167c5 ¤
93dcdf ¤   kPGPPublicKeyAlgorithm_First¤   ¤   ¤   = kPGPPublicKeyAlgorithm_RSA,
a72af3 ¤   kPGPPublicKeyAlgorithm_Last¤¤   ¤   ¤   = kPGPPublicKeyAlgorithm_DSA,
6b67c5 ¤
1f7bbf ¤   PGP_ENUM_FORCE( PGPPublicKeyAlgorithm_ )
1582f7 };
5e2e3e PGPENUM_TYPEDEF( PGPPublicKeyAlgorithm_, PGPPublicKeyAlgorithm );
36af5a
920335 /*____________________________________________________________________________
56077f ¤   Trust values, used to set validity values
41f7f7 ____________________________________________________________________________*/
baaf5a
5f28c7 #define kPGPKeyTrust_Mask ······0x7u
994e12 #define kPGPKeyTrust_Undefined¤ 0x0u
6eea99 #define kPGPKeyTrust_Unknown¤   0x1u
c3ef9b #define kPGPKeyTrust_Never¤ ¤   0x2u
7604b7 #define kPGPKeyTrust_Marginal¤  0x5u
29db9f #define kPGPKeyTrust_Complete¤  0x6u
ec2aad #define kPGPKeyTrust_Ultimate¤  0x7u
85af5a
ef3091 #define kPGPNameTrust_Mask ·····0x3u
1ff768 #define kPGPNameTrust_Unknown¤  0x0u
f5872a #define kPGPNameTrust_Untrusted¤0x1u
024dc9 #define kPGPNameTrust_Marginal¤ 0x2u
05d034 #define kPGPNameTrust_Complete¤ 0x3u
bdaf5a
150335 /*____________________________________________________________________________
7b82fc ¤   Validity levels, used for thresholds in options
b0f7f7 ____________________________________________________________________________*/
b9af5a
a2a8e2 enum PGPValidity_
--e749 00131858eaa401002a6 Page 4 of pgpPubTypes.h
2cbb36 {
523326 ¤   kPGPValidity_Unknown¤   = kPGPNameTrust_Unknown,
f5b525 ¤   kPGPValidity_Invalid¤   = kPGPNameTrust_Untrusted,
e27711 ¤   kPGPValidity_Marginal¤  = kPGPNameTrust_Marginal,
5ca46d ¤   kPGPValidity_Complete¤  = kPGPNameTrust_Complete,
47af5a
384150 ¤   PGP_ENUM_FORCE( PGPValidity_ )
bc2fa1 } ;
d5abd8 PGPENUM_TYPEDEF( PGPValidity_, PGPValidity );
97af5a
300335 /*____________________________________________________________________________
79b5f2 ¤   Line endings types
d5f7f7 ____________________________________________________________________________*/
24af5a
6ce474 enum PGPLineEndType_
eabb36 {
efa179 ¤   kPGPLineEnd_Default¤= 0,
31350a ¤   kPGPLineEnd_LF¤ ¤   = 1,
fdffeb ¤   kPGPLineEnd_CR¤ ¤   = 2,
3b35a4 ¤   kPGPLineEnd_CRLF¤   = (kPGPLineEnd_LF | kPGPLineEnd_CR),
73fa5d ¤   PGP_ENUM_FORCE( PGPLineEndType_ )
a782f7 };
5a5ad5 PGPENUM_TYPEDEF( PGPLineEndType_, PGPLineEndType );
69af5a
6d0335 /*____________________________________________________________________________
c7fd0a ¤   Key export formats
f4f7f7 ____________________________________________________________________________*/
faaf5a
1af756 enum PGPExportFormat_
f9bb36 {
3882c5 ¤   kPGPExportFormat_Basic¤ ¤   ¤   ¤   = 1,
9221d7 ¤   kPGPExportFormat_Complete¤  ¤   ¤   = 255,
85fa55 ¤   PGP_ENUM_FORCE( PGPExportFormat_ )
3e2fa1 } ;
c56d8e PGPENUM_TYPEDEF( PGPExportFormat_, PGPExportFormat );
71af5a
170335 /*____________________________________________________________________________
3414cb ¤   Local encoding types
b367c5 ¤
17e367 ¤   Only one of Force or Auto should be used. The other values are modifiers
67f7f7 ____________________________________________________________________________*/
72af5a
2929a2 #define kPGPLocalEncoding_None¤ ¤   ¤   ¤   0x0¤/* nothing on */
a788c2 #define kPGPLocalEncoding_Force¤¤   ¤   ¤   0x01
5302f8 #define kPGPLocalEncoding_Auto¤ ¤   ¤   ¤   0x02
05feff #define kPGPLocalEncoding_NoMacBinCRCOkay¤  0x04
30af5a
e8f49b typedef PGPFlags¤   PGPLocalEncodingFlags;
5baf5a
b2af5a
792e43 /* max length is 255; the +1 is for the trailing \0 */
041846 #define kPGPMaxUserIDSize¤  ¤   ( (PGPSize)255 + 1 )
8eaf5a
825029 /* Size of buffer for PGP-MIME separator (null terminated) */
5ba0c1 #define kPGPMimeSeparatorSize¤  81
37af5a
f857d4 #endif /* ] Included_pgpPubTypes_h */
28af5a
227e4d /*__Editor_settings____
d8af5a
6e4126 ¤   Local Variables:
c17b17 ¤   tab-width: 4
500e6c ¤   End:
ed5f8c ¤   vi: ts=4 sw=4
1d9e9b ¤   vim: si
31d062 _____________________*/
--6472 000aceddfa3401002a7 Page 1 of pgpPublicKey.h
a70335 /*____________________________________________________________________________
1f002a ¤   pgpPublicKey.h
0567c5 ¤
59c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
5b4b0f ¤   All rights reserved.
7067c5 ¤
a867c5 ¤
25af5a
ede17a ¤   $Id: pgpPublicKey.h,v 1.8.10.1 1998/11/12 03:23:40 heller Exp $
1af7f7 ____________________________________________________________________________*/
b0c292 #ifndef Included_pgpPublicKey_h¤/* [ */
38bab5 #define Included_pgpPublicKey_h
ccaf5a
abe82c #include "pgpPubTypes.h"
78fb31 #include "pgpOptionList.h"
f6af5a
b6af5a
b9af5a
430335 /*____________________________________________________________________________
08529d ¤   Encryption/Signature Message Formats
f7f7f7 ____________________________________________________________________________*/
faaf5a
4bd1f3 enum PGPPublicKeyMessageFormat_
47bb36 {
368511 ¤   kPGPPublicKeyMessageFormat_PGP¤ ¤   = 1,
c251dd ¤   kPGPPublicKeyMessageFormat_PKCS1¤   = 2,
67623b ¤   kPGPPublicKeyMessageFormat_X509¤¤   = 3,
45af5a
e462be ¤   PGP_ENUM_FORCE( PGPPublicKeyMessageFormat_ )
bc82f7 };
9ec90b PGPENUM_TYPEDEF( PGPPublicKeyMessageFormat_, PGPPublicKeyMessageFormat );
d8af5a
36af5a
8daf5a
4c99c6 PGP_BEGIN_C_DECLARATIONS
bfcbcf #if PRAGMA_IMPORT_SUPPORTED
01b981 #pragma import on
0b7454 #endif
e5af5a
f9af5a
b1af5a
160335 /*____________________________________________________________________________
9a6c49 ¤   Public-key operations
f7f7f7 ____________________________________________________________________________*/
f7af5a
55af5a
24af5a
d90335 /*____________________________________________________________________________
580bfa ¤   Return a context for public-key operations based on the specified key.
2ad06b ¤   The specified message format is used for all operations with this
d49f64 ¤   context.
9ef7f7 ____________________________________________________________________________*/
095898 PGPError ¤  PGPNewPublicKeyContext( PGPKeyRef publicKeyRef,
772d88 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat messageFormat,
77b9c9 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyContextRef *outRef );
28af5a
61af5a
520335 /*____________________________________________________________________________
c7d3cd ¤   Dispose of a public-key context.
fff7f7 ____________________________________________________________________________*/
992166 PGPError ¤  PGPFreePublicKeyContext( PGPPublicKeyContextRef ref );
10af5a
3baf5a
5b0335 /*____________________________________________________________________________
71f177 ¤   Determine maximum sizes for inputs and outputs.
74f7f7 ____________________________________________________________________________*/
16a9c7 PGPError¤   PGPGetPublicKeyOperationSizes( PGPPublicKeyContextRef ref,
8fdead ¤   ¤   ¤   ¤   ¤   PGPSize *maxDecryptedBufferSize,
494afc ¤   ¤   ¤   ¤   ¤   PGPSize *maxEncryptedBufferSize,
f895ab ¤   ¤   ¤   ¤   ¤   PGPSize *maxSignatureSize );
51af5a
acaf5a
--6534 000693d6dc9401002a7 Page 2 of pgpPublicKey.h
a70335 /*____________________________________________________________________________
ea2835 ¤   Encrypt one block of data, using PKCS-1 padding. ·Output buffer must
db0ba0 ¤   be of size maxEncryptedBufferSize from PGPGetPublicKeyEncryptionSize.
d1e174 ¤   outSize is a return parameter. ·For some formatting modes the actual
4dd4e1 ¤   output size may be less than the maximum possible.
1cf7f7 ____________________________________________________________________________*/
685ab0 PGPError¤   PGPPublicKeyEncrypt( PGPPublicKeyContextRef ref,
7707fe ¤   ¤   ¤   ¤   ¤   void const *in, PGPSize inSize, void *out,
c36e5e ¤   ¤   ¤   ¤   ¤   PGPSize *outSize );
0faf5a
a8af5a
df0335 /*____________________________________________________________________________
410e50 ¤   Verify a signature on a message hash. ·Returns kPGPError_NoErr on
984734 ¤   correct verification, else an error code. ·The message hash is
9bd50a ¤   finalized and freed by this call (and should not have been finalized
28b3e1 ¤   prior to the call).
92f7f7 ____________________________________________________________________________*/
6967c5 ¤
e231c8 PGPError¤   PGPPublicKeyVerifySignature( PGPPublicKeyContextRef ref,
ebf9a3 ¤   ¤   ¤   ¤   ¤   PGPHashContextRef hashContext,
201770 ¤   ¤   ¤   ¤   ¤   void const *signature, PGPSize signatureSize );
eaaf5a
79af5a
300335 /*____________________________________________________________________________
a2c815 ¤   Verify a signature on a low-level buffer. ·Returns kPGPError_NOErr
644eeb ¤   correct verification, else an error code. ·Not valid with
e3eca4 ····kPGPPublicKeyMessageFormat_PGP contexts.
f7f7f7 ____________________________________________________________________________*/
ddaf5a
8eb755 PGPError¤   PGPPublicKeyVerifyRaw( PGPPublicKeyContextRef ref,
c24082 ¤   ¤   ¤   ¤   ¤   void const *signedData, PGPSize signedDataSize,
e11770 ¤   ¤   ¤   ¤   ¤   void const *signature, PGPSize signatureSize );
72af5a
36af5a
090335 /*____________________________________________________________________________
02c315 ¤   Private-key operations
1df7f7 ____________________________________________________________________________*/
aeaf5a
17af5a
4baf5a
ad0335 /*____________________________________________________________________________
bc3078 ¤   Return a context for private-key operations based on the specified
a81daf ¤   key (which must have a private part). ·The specified message
ba77e4 ¤   format is used for all operations with this context. ·Unlocks key
75f349 ¤   data using passphrase.
09f7f7 ____________________________________________________________________________*/
aa67c5 ¤
ec67c5 ¤
ddf1ba PGPError¤   PGPNewPrivateKeyContext( PGPKeyRef privateKeyRef,
e72d88 ¤   ¤   ¤   ¤   ¤   PGPPublicKeyMessageFormat messageFormat,
ccf580 ¤   ¤   ¤   ¤   ¤   PGPPrivateKeyContextRef *outRef,
40ebb3 ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
73af5a
cc0335 /*____________________________________________________________________________
66c1f5 ¤   Dispose of a private-key context. ·All sensitive data is wiped before
5530f5 ¤   being deleted.
08f7f7 ____________________________________________________________________________*/
0f9ee5 PGPError ¤  PGPFreePrivateKeyContext( PGPPrivateKeyContextRef ref );
1caf5a
c7af5a
7d0335 /*____________________________________________________________________________
3bf177 ¤   Determine maximum sizes for inputs and outputs.
fdf7f7 ____________________________________________________________________________*/
9a678b PGPError¤   PGPGetPrivateKeyOperationSizes( PGPPrivateKeyContextRef ref,
44dead ¤   ¤   ¤   ¤   ¤   PGPSize *maxDecryptedBufferSize,
0f4afc ¤   ¤   ¤   ¤   ¤   PGPSize *maxEncryptedBufferSize,
bb30be ¤   ¤   ¤   ¤   ¤   PGPSize *maxSignatureSize);
fdaf5a
e0af5a
150335 /*____________________________________________________________________________
660fc8 ¤   Decrypt one block of data. ·Output buffer must be of size at least
6954c6 ¤   maxDecryptedBufferSize from PGPGetPrivateKeyDecryptionSize.
--bcfc 00130ab2763401002a7 Page 3 of pgpPublicKey.h
55e174 ¤   outSize is a return parameter. ·For some formatting modes the actual
3cd4e1 ¤   output size may be less than the maximum possible.
5cf7f7 ____________________________________________________________________________*/
221146 PGPError¤   PGPPrivateKeyDecrypt( PGPPrivateKeyContextRef ref,
5e07fe ¤   ¤   ¤   ¤   ¤   void const *in, PGPSize inSize, void *out,
e86e5e ¤   ¤   ¤   ¤   ¤   PGPSize *outSize );
59af5a
bcaf5a
4e0335 /*____________________________________________________________________________
552267 ¤   Sign a message hash. ·Output signature buffer must be of size at
f85660 ¤   least maxSignatureSize from PGPGetPrivateKeyDecryptionSize.
6d83e6 ¤   signatureSize is a return parameter. ·For some formatting modes
316a8b ¤   the actual signature size may be less than the maximum possible.
5858dd ¤   The message hash is finalized and freed by this call (and should
a89466 ¤   not have been finalized prior to the call).
aef7f7 ____________________________________________________________________________*/
1a67c5 ¤
ea67c5 ¤
6cf073 PGPError¤   PGPPrivateKeySign( PGPPrivateKeyContextRef ref,
08f9a3 ¤   ¤   ¤   ¤   ¤   PGPHashContextRef hashContext,
cdbe19 ¤   ¤   ¤   ¤   ¤   void *signature, PGPSize *signatureSize );
a8af5a
2b0335 /*____________________________________________________________________________
fba25c ¤   Sign a low level signedData buffer. ·Output signature buffer must be
408be4 ····of size at least maxSignatureSize from PGPGetPrivateKeyDecryptionSize.
f5ae4b ¤   signatureSize is a return parameter. ·Not valid with
65eca4 ····kPGPPublicKeyMessageFormat_PGP contexts.
dbf7f7 ____________________________________________________________________________*/
1baf5a
ca7560 PGPError¤   PGPPrivateKeySignRaw( PGPPrivateKeyContextRef ref,
c44082 ¤   ¤   ¤   ¤   ¤   void const *signedData, PGPSize signedDataSize,
9a53a6 ¤   ¤   ¤   ¤   ¤   void const *signature, PGPSize *signatureSize );
d5af5a
a2af5a
5b0335 /*____________________________________________________________________________
da1a10 ¤   Miscellaneous operations
f7f7f7 ____________________________________________________________________________*/
8eaf5a
ccaf5a
77af5a
860335 /*____________________________________________________________________________
0edc55 Given the size of a prime modulus in bits, this returns an appropriate
23c9a2 size for an exponent in bits, such that the work factor to find a
295dcd discrete log modulo the modulus is approximately equal to half the
d37f2d length of the exponent. ·This makes the exponent an appropriate size
4ad396 for a subgroup in a discrete log signature scheme. ·For encryption
68eb5a schemes, where decryption attacks can be stealthy and undetected, we
b8c567 use 3/2 times the returned exponent size.
abf7f7 ____________________________________________________________________________*/
2caf5a
d2bba4 PGPError¤   PGPDiscreteLogExponentBits( PGPUInt32 modulusBits,
36f8cb ¤   ¤   ¤   ¤   ¤   PGPUInt32 *exponentBits );
cdaf5a
4daf5a
4ecbcf #if PRAGMA_IMPORT_SUPPORTED
5e2ced #pragma import reset
177454 #endif
9b1254 PGP_END_C_DECLARATIONS
dcaf5a
3e75ae #endif /* ] Included_pgpPublicKey_h */
68af5a
3faf5a
cb7e4d /*__Editor_settings____
feaf5a
434126 ¤   Local Variables:
c97b17 ¤   tab-width: 4
b70e6c ¤   End:
f55f8c ¤   vi: ts=4 sw=4
689e9b ¤   vim: si
30d062 _____________________*/
--a2a1 00153136f32401002a8 Page 1 of pgpRandomPool.h
a70335 /*____________________________________________________________________________
44e924 ¤   pgpRandomPool.h
5667c5 ¤
76c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
b34b0f ¤   All rights reserved.
2367c5 ¤
7867c5 ¤
7faf5a
c0555a ¤   $Id: pgpRandomPool.h,v 1.10.30.1 1998/11/12 03:23:40 heller Exp $
43f7f7 ____________________________________________________________________________*/
faa5e9 #ifndef Included_pgpRandomPool_h¤   /* [ */
d0191a #define Included_pgpRandomPool_h
7aaf5a
6c99c6 PGP_BEGIN_C_DECLARATIONS
a9cbcf #if PRAGMA_IMPORT_SUPPORTED
09b981 #pragma import on
ba7454 #endif
f3af5a
e18729 PGPUInt32 ¤ PGPGlobalRandomPoolAddKeystroke( PGPInt32 event);
442cbe PGPUInt32 ¤ PGPGlobalRandomPoolAddMouse( PGPUInt32 x, PGPUInt32 y);
b6af5a
8be451 /* Extra functions for entropy estimation */
31db4a PGPUInt32 ¤ PGPGlobalRandomPoolGetEntropy( void );
56141d PGPUInt32 ¤ PGPGlobalRandomPoolGetSize( void );
820052 PGPUInt32¤  PGPGlobalRandomPoolGetMinimumEntropy( void );
67598c PGPBoolean¤ PGPGlobalRandomPoolHasMinimumEntropy( void );
85af5a
afaf5a
e7af5a
1aaf5a
f6af5a
49cbcf #if PRAGMA_IMPORT_SUPPORTED
832ced #pragma import reset
4a7454 #endif
bb1254 PGP_END_C_DECLARATIONS
daaf5a
a9e9c1 #endif /* ] Included_pgpRandomPool_h */
0aaf5a
ebaf5a
6f7e4d /*__Editor_settings____
a4af5a
a44126 ¤   Local Variables:
fb7b17 ¤   tab-width: 4
e10e6c ¤   End:
955f8c ¤   vi: ts=4 sw=4
129e9b ¤   vim: si
53d062 _____________________*/
--b74a 000b4f34371401002a9 Page 1 of pgpSDKPrefs.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
adaf5a
385002 ¤   $Id: pgpSDKPrefs.h,v 1.5.10.1 1998/11/12 03:23:41 heller Exp $
d7f7f7 ____________________________________________________________________________*/
058739 #ifndef Included_pgpCDKPrefs_h¤ /* [ */
b0a9a4 #define Included_pgpCDKPrefs_h
d9af5a
ece2ff #include "pgpConfig.h"
17e82c #include "pgpPubTypes.h"
2daf5a
5eaf5a
9a6a31 enum PGPsdkPrefSelector_
85bb36 {
f96c47 ¤   kPGPsdkPref_First = 0,
0a67c5 ¤
150afb ¤   kPGPsdkPref_PublicKeyring¤  = kPGPsdkPref_First,
931c12 ¤   kPGPsdkPref_PrivateKeyring¤ = 1,
91c81b ¤   kPGPsdkPref_RandomSeedFile¤ = 2,
1167c5 ¤
5ed0b2 ¤   kPGPsdkPref_DefaultKeyID¤   = 3,
e5f14a ¤   kPGPsdkPref_GroupsFile¤ ¤   = 4,
e667c5 ¤
dfe68a ¤   kPGPsdkPref_LastPlusOne,
4467c5 ¤
b45cf5 ¤   PGP_ENUM_FORCE( PGPsdkPrefSelector_ )
4b82f7 };
d2c5da PGPENUM_TYPEDEF( PGPsdkPrefSelector_, PGPsdkPrefSelector );
98af5a
91af5a
f0af5a
3899c6 PGP_BEGIN_C_DECLARATIONS
b5cbcf #if PRAGMA_IMPORT_SUPPORTED
01b981 #pragma import on
0e7454 #endif
0faf5a
d261e2 /* call this if you want the CDK to use prefs stored in the prefs file */
65d466 PGPError PGPsdkLoadPrefs( PGPContextRef context,
51e22f ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef prefSpec );
c5aca6 PGPError PGPsdkLoadDefaultPrefs( PGPContextRef context );
99af5a
cf9c95 /* save any changed preferences to disk */
c82b04 PGPError PGPsdkSavePrefs( PGPContextRef context );
41af5a
85af5a
0502d5 PGPError PGPsdkPrefSetFileSpec( PGPContextRef context,
1bdb06 ¤   ¤   ¤   ¤   ¤   PGPsdkPrefSelector selector, PGPFileSpecRef ref );
c8ae30 ¤   ¤   ¤   ¤   ¤
49088d /* caller must deallocate *outRef with PGPFreeFileSpec */
113791 PGPError PGPsdkPrefGetFileSpec( PGPContextRef context,
090f5c ¤   ¤   ¤   ¤   ¤   PGPsdkPrefSelector selector, PGPFileSpecRef * outRef );
1eae30 ¤   ¤   ¤   ¤   ¤
50ae30 ¤   ¤   ¤   ¤   ¤
c651c2 PGPError PGPsdkPrefSetData( PGPContextRef context,
3cf251 ¤   ¤   ¤   ¤   ¤   PGPsdkPrefSelector selector,
44ea0a ¤   ¤   ¤   ¤   ¤   void const *data, PGPSize size );
42af5a
65eb60 /* caller must deallocate *dataOut with PGPFreeData */
a1ca0c PGPError PGPsdkPrefGetData( PGPContextRef context,
aef251 ¤   ¤   ¤   ¤   ¤   PGPsdkPrefSelector selector,
4cbf79 ¤   ¤   ¤   ¤   ¤   void **dataOut, PGPSize *sizeOut );
aeaf5a
11cbcf #if PRAGMA_IMPORT_SUPPORTED
7f2ced #pragma import reset
cb7454 #endif
331254 PGP_END_C_DECLARATIONS
f5af5a
f808a0 #endif /* ] Included_pgpCDKPrefs_h */
b4af5a
--8823 00177d8b615401002a9 Page 2 of pgpSDKPrefs.h
e0af5a
9d7e4d /*__Editor_settings____
89af5a
a94126 ¤   Local Variables:
9f7b17 ¤   tab-width: 4
bb0e6c ¤   End:
575f8c ¤   vi: ts=4 sw=4
f79e9b ¤   vim: si
77d062 _____________________*/
--4dd7 000745a7987401002aa Page 1 of pgpSockets.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
ea67c5 ¤
0767c5 ¤
89c885 ¤   $Id: pgpSockets.h,v 1.24.10.1 1998/11/12 03:23:42 heller Exp $
c3f7f7 ____________________________________________________________________________*/
4faf5a
12af5a
c269dc #ifndef Included_pgpSockets_h¤  /* [ */
6f28f1 #define Included_pgpSockets_h
71af5a
22feb2 #include <stdio.h>
d7af5a
98fb31 #include "pgpOptionList.h"
66ec82 #include "pgpTLS.h"
c12f8d #include "pgpErrors.h"
f8af5a
e1129a #if PGP_UNIX
77bee3 # include <sys/types.h>
5408d3 # include <sys/socket.h>
775d1d #if PGP_UNIX_LINUX
34b93b # include <sys/ioctl.h>¤¤   /* Need FIONREAD */
567da0 #else /* ! PGP_UNIX_LINUX */¤   /* need elif PGP_UNIX_SOLARIS here ?? */
3c7722 # include <sys/filio.h>
dbe881 #endif /* ! PGP_UNIX_LINUX */
6f0238 # include <netinet/in.h>
17cd1b # include <netdb.h>
4d7454 #endif
2eaf5a
0dafb9 #if PGP_WIN32
5f05f8 # include <winsock.h>
c97454 #endif
f4af5a
1099c6 PGP_BEGIN_C_DECLARATIONS
4caf5a
2bcbcf #if PRAGMA_IMPORT_SUPPORTED
a3fd61 # pragma import on
847454 #endif
30af5a
b7e0bd typedef struct PGPSocket *¤ ¤   ¤   PGPSocketRef;
7caf5a
2a38e5 /*
4e1853 ·* Unix and Windows share the same Berkley socket interface. This isn't
3e4b40 ·* the most efficient Windows implmentation of TCP/IP, but it is
f177a9 ·* compatable with UNIX berkley sockets, making cross-platform possible.
62775e ·*
fa652c ·* Trying to write cross-platform win32 TCP/IP code using all the fancy
801029 ·* dancy Win32 network functions would be nearly impossible IMHO
d1775e ·*
2cd81a ·* The Mac doesn't have the berkley stuff, so we roll our own for all
7a3436 ·* of the structures.
9e775e ·*
2fc5c1 ·* Start with Unix and Win32
ac495d ·*/
eec755 #if PGP_UNIX || PGP_WIN32
c4af5a
49f674 # define kInvalidPGPSocketRef¤  ¤   ((PGPSocketRef) (~0))
a6af5a
e1847b ·typedef struct hostent¤¤   PGPHostEntry;
b1a608 ·typedef struct protoent¤   PGPProtocolEntry;
a4e5fe ·typedef struct servent¤¤   PGPServiceEntry;
054395 ·typedef struct sockaddr_in¤PGPSocketAddressInternet;
28a559 ·typedef struct sockaddr¤   PGPSocketAddress;
c076ad ·typedef struct in_addr¤¤   PGPInternetAddress;
08783d ·typedef fd_set ¤   ¤   ¤   PGPSocketSet;
4cd332 ·typedef struct timeval¤¤   PGPSocketsTimeValue;
44af5a
6bc09b # define PGPSOCKETSET_CLEAR(socketRef, set) FD_CLR((int) (socketRef), (set))
954d12 # define PGPSOCKETSET_SET(socketRef, set) ··FD_SET((int) (socketRef), (set))
74dfa2 # define PGPSOCKETSET_ZERO(set)¤¤   ¤   ¤   FD_ZERO((set))
--dbc0 0001305eee1401002aa Page 2 of pgpSockets.h
c86816 # define PGPSOCKETSET_ISSET(socketRef, set) FD_ISSET((int) (socketRef), (set))
edaf5a
c34782 ·/* Address families */
7fc990 ·enum {
800391 ¤   kPGPAddressFamilyUnspecified¤   =¤  AF_UNSPEC,
ad0561 ¤   kPGPAddressFamilyInternet¤  ¤   =¤  AF_INET
81b44a ·};
06af5a
53efea ·/* Protocol families */
41c990 ·enum {
2543a7 ¤   kPGPProtocolFamilyInternet¤ =¤  PF_INET
8eb44a ·};
3aaf5a
78b37c ·/* Types */
3dc990 ·enum {
01a7b2 ¤   kPGPSocketTypeStream¤   ¤   ¤   =¤  SOCK_STREAM,
1f552a ¤   kPGPSocketTypeDatagram¤ ¤   ¤   =¤  SOCK_DGRAM
15b44a ·};
80af5a
ec5978 ·/* Commands for PGPIOControlSocket */
77c990 ·enum {
e6a590 ¤   kPGPSocketCommandGetUnreadData¤ =¤  FIONREAD
9bb44a ·};
5daf5a
0c7109 ·/* Levels for PGPGetSocketOptions and PGPSetSocketOptions */
f2c990 ·enum {
74c983 ¤   kPGPSocketOptionLevelSocket¤=¤  SOL_SOCKET
9fb44a ·};
2baf5a
4fd95c ·/* Options for PGPGetSocketOptions and PGPSetSocketOptions */
7769cb /* On Linux (2.0.24), include <asm/socket.h> has SOL_SOCKET and SO_TYPE, */
a91478 /* but unclear as to what would correspond to SO_ACCEPTCONN, if any. */
af516a #if¤PGP_UNIX_LINUX
0143d0 /* #ifndef¤ SO_ACCEPTCONN */
4e6f53 #define¤SO_ACCEPTCONN¤  0
0d7d5f /* #endif */¤   /* SO_ACCEPTCONN */
ed8dd1 #endif¤ /* PGP_UNIX_LINUX */
fac990 ·enum {
dbde0b ¤   kPGPSocketOptionAcceptingConnections¤   =¤  SO_ACCEPTCONN,
a7cf32 ¤   kPGPSocketOptionType¤   ¤   ¤   ¤   ¤   =¤  SO_TYPE
4db44a ·};
89af5a
dc7d2a ·/* Protocols */
24c990 ·enum {
6fb2f3 ¤   kPGPTCPProtocol¤=¤  IPPROTO_TCP,
2aedb0 ¤   kPGPUDPProtocol¤=¤  IPPROTO_UDP
92b44a ·};
66af5a
1cbcc8 ·/* Send flags */
80c990 ·enum {
1bf357 ¤   kPGPSendFlagNone¤   ¤   =¤  0
d4b44a ·};
f4af5a
ff2c1c ·/* Receive flags */
84c990 ·enum {
4b5fa6 ¤   kPGPReceiveFlagNone¤¤   =¤  0
b8b44a ·};
59af5a
c47624 ·/* Internet Addresses */
5bc990 ·enum {
f9cbf2 ·¤  kPGPInternetAddressAny = INADDR_ANY
aeb44a ·};
22af5a
6f9b33 #endif /* PGP_UNIX || PGP_WIN32 */
0aaf5a
8c38e5 /*
483d47 ·* Onto the Mac, where we need to create our own versions of the various
e75c3a ·* structures.
eb495d ·*/
a10ccc #if PGP_MACINTOSH
f0af5a
13ffe0 # define¤   kInvalidPGPSocketRef¤   ¤   ((PGPSocketRef) NULL)
--f007 000fdceea1a401002aa Page 3 of pgpSockets.h
e0af5a
f7b053 ·typedef struct PGPInternetAddress {
26e29a ¤   union {
a4c86c ¤   ¤   struct {
ad0dd5 ¤   ¤   ¤   PGPByte¤¤   s_b1;
90e2b1 ¤   ¤   ¤   PGPByte¤¤   s_b2;
e6b86d ¤   ¤   ¤   PGPByte¤¤   s_b3;
4a3468 ¤   ¤   ¤   PGPByte¤¤   s_b4;
83efde ¤   ¤   }¤  ¤   ¤   ¤   ¤   S_un_b;
95c86c ¤   ¤   struct {
175645 ¤   ¤   ¤   PGPUInt16¤  s_w1;
bfb921 ¤   ¤   ¤   PGPUInt16¤  s_w2;
ed53f6 ¤   ¤   }¤  ¤   ¤   ¤   ¤   S_un_w;
31522f ¤   ¤   PGPUInt32¤  ¤   S_addr;
89e7b1 ¤   } S_un;
2c4207 # define s_addr¤S_un.S_addr
985da0 ·} PGPInternetAddress;
3daf5a
2581cf ·typedef struct PGPSocketAddressInternet {
f69e1d ¤   PGPInt16¤   ¤   ¤   sin_family;
b1bc7a ¤   PGPUInt16¤  ¤   ¤   sin_port;
852acf ¤   PGPInternetAddress¤ sin_addr;
174ed3 ¤   PGPByte¤¤   ¤   ¤   sin_zero[8];
07278d ·} PGPSocketAddressInternet;
6aaf5a
7f1693 ·typedef struct PGPSocketAddress {
632bac ¤   PGPUInt16¤  sa_family;
78cc0a ¤   PGPByte¤¤   sa_data[14];
994005 ·} PGPSocketAddress;
39af5a
db3b10 ·typedef struct PGPHostEntry {
f4f0f8 ¤   char *¤ ¤   h_name;
dd9d5d ¤   char **¤¤   unused;
8c1daa ¤   PGPInt16¤   h_addrtype;
41b30e ¤   PGPInt16¤   h_length;
3a4447 ¤   char **¤¤   h_addr_list;
f8a742 # define h_addr¤h_addr_list[0]
43f1d3 ·} PGPHostEntry;
77af5a
e3458b ·typedef struct PGPProtocolEntry {
d8863c ¤   char *¤ ¤   p_name;
4b21e8 ¤   char **¤¤   p_aliases;
0ff73e ¤   PGPInt16¤   p_proto;
f1d544 ·} PGPProtocolEntry;
90af5a
416b23 ·typedef struct PGPServiceEntry {
540cec ¤   char *¤ ¤   s_name;
b6df5b ¤   char **¤¤   s_aliases;
cade1a ¤   PGPUInt16¤  s_port;
89797b ¤   char *¤ ¤   s_proto;
7eaf87 ·} PGPServiceEntry;
97af5a
6b3b37 ·/* Select types and defines */
1aa818 # ifndef PGPSOCKETSET_SETSIZE
790a14 # ·define PGPSOCKETSET_SETSIZE¤ 64
38e01a # endif
e4af5a
7264e8 ·typedef struct PGPSocketSet {
74a1c2 ¤   PGPUInt16¤  ¤   fd_count;
cfacc2 ¤   PGPSocketRef¤   fd_array[PGPSOCKETSET_SETSIZE];
34e45e ·} PGPSocketSet;
34af5a
3b98e1 # define PGPSOCKETSET_CLEAR(socketRef, set)¤do {¤   ¤   ¤   ¤   ¤   ¤   \
8ae372 ····PGPUInt16¤  __i;¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
f3864a ¤   for (__i = 0; __i < ((PGPSocketSet * (set))->fd_count; __i++) {¤¤   \
62e315 ¤   ¤   if (((PGPSocketSet *) (set))->fd_array[__i] == socketRef) {¤¤   \
dea4c1 ¤   ¤   ¤   while (__i < (((PGPSocketSet *) (set))->fd_count - 1)) {¤   \
f4a312 ¤   ¤   ¤   ¤   ((PGPSocketSet *) (set))->fd_array[__i] =¤  ¤   ¤   ¤   \
a89f7a ¤   ¤   ¤   ¤   ¤   ((PGPSocketSet *) (set))->fd_array[__i + 1];¤   ¤   \
014056 ¤   ¤   ¤   ¤   __i++;¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
8fad09 ¤   ¤   ¤   }¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
fdd8d1 ¤   ¤   ¤   ((PGPSocketSet *) (set))->fd_count--;¤  ¤   ¤   ¤   ¤   ¤   \
--d230 000805e2022401002aa Page 4 of pgpSockets.h
a8eb33 ¤   ¤   ¤   break;¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
39e426 ¤   ¤   }¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
4a43e4 ¤   }¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
7d9bcb ·} while (0)
270230 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
b8dc93 # define PGPSOCKETSET_SET(socketRef, set)¤  do {¤   ¤   ¤   ¤   ¤   \
abc471 ····if (((PGPSocketSet *) (set))->fd_count < PGPSOCKETSET_SETSIZE) {¤   \
ec21c3 ¤   ····((PGPSocketSet *) (set))->fd_array[((PGPSocketSet *)¤   ¤   ¤   \
6f4466 ¤   ····(set))->fd_count++] = (socketRef);¤ ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
b77f27 ····}¤  ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   \
569bcb ·} while (0)
c2af5a
aaa0d3 # define PGPSOCKETSET_ZERO(set)¤(((PGPSocketSet *) (set))->fd_count = 0)
d8af5a
b92243 ·PGPInt32 __PGPSocketsIsSet(PGPSocketRef, PGPSocketSet *);
3f67c5 ¤
ec3816 # define PGPSOCKETSET_ISSET(socketRef, set)¤__PGPSocketsIsSet(¤ \
e2506c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   (socketRef),(set))
e1531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
50d790 ·typedef struct PGPSocketsTimeValue {
1af6ca ········PGPInt32 ···tv_sec; ········/* seconds */
553780 ········PGPInt32 ···tv_usec; ·······/* and microseconds */
f0f98d ·} PGPSocketsTimeValue;
6baf5a
c24782 ·/* Address families */
2ac990 ·enum {
a37ac7 ¤   kPGPAddressFamilyUnspecified¤   =¤  0,
9c697d ¤   kPGPAddressFamilyInternet¤  ¤   =¤  2
26b44a ·};
b9af5a
cbefea ·/* Protocol families */
dfc990 ·enum {
c9e3fe ¤   kPGPProtocolFamilyInternet¤ =¤  kPGPAddressFamilyInternet
66b44a ·};
82af5a
48b37c ·/* Types */
cdc990 ·enum {
a463bf ¤   kPGPSocketTypeStream¤   ¤   ¤   =¤  1,
0fd49b ¤   kPGPSocketTypeDatagram¤ ¤   ¤   =¤  2
e4b44a ·};
3aaf5a
305978 ·/* Commands for PGPIOControlSocket */
cdc990 ·enum {
dde190 ¤   kPGPSocketCommandGetUnreadData¤ =¤  (0x40000000
4ec8bc ¤   ¤   | (((long) sizeof(PGPUInt32) & 0x7F) << 16) | ('f' << 8) | 127)
a1b44a ·};
a0af5a
287109 ·/* Levels for PGPGetSocketOptions and PGPSetSocketOptions */
12c990 ·enum {
0f3561 ¤   kPGPSocketOptionLevelSocket¤=¤  0xFFFFFFFF
cfb44a ·};
b7af5a
d6d95c ·/* Options for PGPGetSocketOptions and PGPSetSocketOptions */
efc990 ·enum {
7a834b ¤   kPGPSocketOptionAcceptingConnections¤   =¤  0x00000002,
9cc8d3 ¤   kPGPSocketOptionType¤   ¤   ¤   ¤   ¤   =¤  0x00001008
e5b44a ·};
28af5a
247d2a ·/* Protocols */
1cc990 ·enum {
f37e7a ¤   kPGPTCPProtocol¤=¤  6,
91ea98 ¤   kPGPUDPProtocol¤=¤  17
08b44a ·};
32af5a
9fbcc8 ·/* Send flags */
1ac990 ·enum {
82f357 ¤   kPGPSendFlagNone¤   ¤   =¤  0
28b44a ·};
56af5a
422c1c ·/* Receive flags */
4cc990 ·enum {
805fa6 ¤   kPGPReceiveFlagNone¤¤   =¤  0
--d509 000aa102b40401002aa Page 5 of pgpSockets.h
00b44a ·};
09af5a
2e7624 ·/* Internet Addresses */
a6c990 ·enum {
5c26ef ¤   kPGPInternetAddressAny¤ =¤  0x00000000
6bb44a ·};
c2af5a
ddbb8e #endif /* PGP_MACINTOSH */
e1af5a
2f38e5 /*
96dfc8 ·* Some global things for all platforms
bd495d ·*/
53af5a
209328 #define PGPSocketRefIsValid(ref)¤   ((ref) != kInvalidPGPSocketRef)
c7af5a
701225 typedef struct PGPSocketsThreadStorage *¤   PGPSocketsThreadStorageRef;
81af4a # define kInvalidPGPSocketsThreadStorageRef¤¤   ¤   ¤   \
2e6176 ¤   ¤   ¤   ((PGPSocketsThreadStorageRef) NULL)
422f3b #define PGPSocketsThreadStorageRefIsValid(ref)¤ ¤   ¤   \
cc1ea5 ¤   ¤   ¤   ((ref) != kInvalidPGPSocketsThreadStorageRef)
b8af5a
54c2c0 extern PGPSocketAddressInternet¤kPGPAddressAny;
82af5a
c5f2ae /* Errors */
1231f7 #define kPGPSockets_Error¤  -1
f2af5a
cda4c4 /* Net byte ordering macros (PGP_WORDSBIGENDIAN defined by configure) */
b3f94d #if PGP_WORDSBIGENDIAN
98199d # define PGPHostToNetLong(x)¤   (x)
52ebd5 # define PGPHostToNetShort(x)¤  (x)
7744c3 # define PGPNetToHostLong(x)¤   (x)
0eb68b # define PGPNetToHostShort(x)¤  (x)
8bdb21 #else
387935 ·PGPInt32¤  PGPHostToNetLong(PGPInt32 x);
91b51e ·PGPInt16¤  PGPHostToNetShort(PGPInt16 x);
a38942 ·PGPInt32¤  PGPNetToHostLong(PGPInt32 x);
2bb2d6 ·PGPInt16¤  PGPNetToHostShort(PGPInt16 x);
bfc0d8 #endif /* PGP_WORDSBIGENDIAN */
62af5a
9338e5 /*
416efa ·* Shared function interface (except for idle handler code)
74495d ·*/
9baf5a
8538e5 /*
0fc56a ·* Use the idle event handler to receive periodic idle events during
853045 ·* network calls. Usually this is used only in non-preemptive multi-tasking
2f45cf ·* OSes to allow yielding in threads. Pre-emptive multi-tasking systems
ceed8f ·* should probably not use the call as it interrupts the efficient wait state
42cace ·* of threads waiting on network calls.
5a775e ·*
6c744a ·* Idle event handlers need to be added on a per thread basis.
71775e ·*
df3692 ·* Returning an error from the idle event handler will cause the socket
fa06f5 ·* that is blocking to close.
d0775e ·*
85495d ·*/
e6441a PGPError¤   ¤   PGPSetSocketsIdleEventHandler(
0b2e74 ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr inCallback,
10b37a ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue inUserData);
1294aa ¤   ¤   ¤   ¤   ¤   ¤
6ee57d PGPError¤   ¤   PGPGetSocketsIdleEventHandler(
996dcd ¤   ¤   ¤   ¤   ¤   ¤   PGPEventHandlerProcPtr * outCallback,
ca8bcf ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue * outUserData);
1eaf5a
6783a8 /* Static storage creation */
dd3979 PGPError¤   ¤   PGPSocketsCreateThreadStorage(
7531a2 ¤   ¤   ¤   ¤   ¤   PGPSocketsThreadStorageRef * outPreviousStorage);
7e5e7f PGPError¤   ¤   PGPSocketsDisposeThreadStorage(
47e025 ¤   ¤   ¤   ¤   ¤   PGPSocketsThreadStorageRef inPreviousStorage);
13ae30 ¤   ¤   ¤   ¤   ¤
9d327f /* Stack based class for saving and restoring thread storage */
aa09eb #ifdef __cplusplus¤ /* [ */
--b601 000a51c7275401002aa Page 6 of pgpSockets.h
d2564f class StPGPPreserveSocketsStorage {
065ed4 public:
2e7ccf ¤   ¤   ¤   StPGPPreserveSocketsStorage() : mStorage(NULL)
e3f530 ¤   ¤   ¤   ¤   { PGPSocketsCreateThreadStorage(&mStorage); }
e54593 ¤   ¤   ¤   ~StPGPPreserveSocketsStorage()
9e6bb3 ¤   ¤   ¤   ¤   { PGPSocketsDisposeThreadStorage(mStorage); }
82af5a
94a2d3 protected:
554f36 ¤   PGPSocketsThreadStorageRef¤ mStorage;
8882f7 };
9179c3 #endif¤ /* ] __cplusplus */
e8af5a
25af5a
0066b0 /* Initialization and termination */
5f0bf5 PGPError¤   ¤   PGPSocketsInit(void);
465d18 void¤   ¤   ¤   PGPSocketsCleanup(void);
2eaf5a
d87d43 /* Socket creation and destruction */
ed0295 PGPSocketRef¤   PGPOpenSocket(PGPInt32 inAddressFamily, PGPInt32 inSocketType,
5e6384 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPInt32 inSocketProtocol);
c8ba5e PGPInt32¤   ¤   PGPCloseSocket(PGPSocketRef inSocketRef);
29af5a
c5a03b /* Endpoint binding */
761cd1 PGPInt32¤   ¤   PGPBindSocket(PGPSocketRef inSocketRef,
0e554a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··const PGPSocketAddress * inAddress,
7a2647 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPInt32 inAddressLength);
98c2b8 PGPInt32¤   ¤   PGPConnect(PGPSocketRef inSocketRef,
6deda3 ¤   ¤   ¤   ¤   ¤   ¤   ···const PGPSocketAddress * inServerAddress,
49ca89 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPInt32 inAddressLength);
41af5a
c178b3 /* Send functions */
226d54 PGPInt32¤   ¤   PGPSend(PGPSocketRef inSocketRef, const void * inBuffer,
fae99c ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inBufferLength, PGPInt32 inFlags);
d872bc PGPInt32¤   ¤   PGPWrite(PGPSocketRef inSocketRef, const void * inBuffer,
143c05 ¤   ¤   ¤   ¤   ¤   ¤   ·PGPInt32 inBufferLength);
7a4d3d PGPInt32¤   ¤   PGPSendTo(PGPSocketRef inSocketRef, const void * inBuffer,
50dff1 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPInt32 inBufferLength, PGPInt32 inFlags,
587ec6 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPSocketAddress * inAddress,
f74974 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPInt32 inAddressLength);
73af5a
c099c4 /* Receive functions */
8dfcec PGPInt32¤   ¤   PGPReceive(PGPSocketRef inSocketRef, void * outBuffer,
9e667e ¤   ¤   ¤   ¤   ¤   ¤   ···PGPInt32 inBufferSize, PGPInt32 inFlags);
e3c491 PGPInt32¤   ¤   PGPRead(PGPSocketRef inSocketRef, void * outBuffer,
e7942b ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inBufferSize);
0bddba PGPInt32¤   ¤   PGPReceiveFrom(PGPSocketRef inSocketRef, void * outBuffer,
a840fa ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPInt32 inBufferSize, PGPInt32 inFlags,
2720a4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPSocketAddress * outAddress,
1bec2f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPInt32 * ioAddressLength);
9caf5a
76905a /* Server functions */
6a88a2 PGPInt32¤   ¤   PGPListen(PGPSocketRef inSocketRef, PGPInt32 inMaxBacklog);
d85353 PGPSocketRef¤   PGPAccept(PGPSocketRef inSocketRef,
ecdd88 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPSocketAddress * outAddress,
c2199b ¤   ¤   ¤   ¤   ¤   ¤   ··PGPInt32 * ioAddressLength);
c2af5a
d92a3d /* Select */
cccb9a /* Note that inNumSetCount is not used under Mac and Windows */
1e2075 PGPInt32 ¤  ¤   PGPSelect(PGPInt32 inNumSetCount,
8450aa ¤   ¤   ¤   ¤   ¤   ¤   ··PGPSocketSet * ioReadSet,
566a59 ¤   ¤   ¤   ¤   ¤   ¤   ··PGPSocketSet * ioWriteSet,
76817b ¤   ¤   ¤   ¤   ¤   ¤   ··PGPSocketSet * ioErrorSet,
dc0bda ¤   ¤   ¤   ¤   ¤   ¤   ··const PGPSocketsTimeValue * inTimeout);
e7af5a
31556c /* DNS and protocol services */
894aff PGPHostEntry *¤ ¤   PGPGetHostByName(const char * inName);
791e0d PGPHostEntry *¤ ¤   PGPGetHostByAddress(const char* inAddress,
77d43c ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inLength,
b39420 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inType);
95690e PGPInt32¤   ¤   ¤   PGPGetHostName(char * outName, PGPInt32 inNameLength);
ce6dd7 PGPProtocolEntry *¤ PGPGetProtocolByName(const char * inName);
a562fc PGPProtocolEntry *¤ PGPGetProtocolByNumber(PGPInt32 inNumber);
--0d99 00116e1b32f401002aa Page 7 of pgpSockets.h
2e39b9 PGPServiceEntry *¤  PGPGetServiceByName(const char * inName,
49a482 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inProtocol);
03d359 PGPServiceEntry *¤  PGPGetServiceByPort(PGPInt32 inPort,
dca482 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inProtocol);
3baf5a
ff4b1f /* Error reporting */
a7d54e PGPError¤   PGPGetLastSocketsError(void);
edaf5a
7b1723 /* Utilities */
dff316 PGPInt32¤   PGPGetSocketName(PGPSocketRef inSocketRef,
1c32b3 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPSocketAddress * outName,
ff74ca ¤   ¤   ¤   ¤   ¤   ¤   ¤   ·PGPInt32 * ioNameLength);
b32d42 PGPInt32¤   PGPGetPeerName(PGPSocketRef inSocketRef,
b7f294 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPSocketAddress * outName,
160b61 ¤   ¤   ¤   ¤   ¤   ¤   ···PGPInt32 * ioNameLength);
dd736d PGPUInt32¤  PGPDottedToInternetAddress(const char * inAddress);
c433fc char *¤ ¤   PGPInternetAddressToDottedString(PGPInternetAddress inAddress);
c7af5a
90bf7f /* Control and options */
8dd145 PGPInt32¤   PGPIOControlSocket(PGPSocketRef inSocketRef,
442640 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ···PGPInt32 inCommand, PGPUInt32 * ioParam);
93a3be PGPInt32¤   PGPGetSocketOptions(PGPSocketRef inSocketRef, PGPInt32 inLevel,
3533cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inOptionName,
8bbe5f ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   char * outOptionValue,
a808de ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 * ioOptionLength);
b236e8 PGPInt32¤   PGPSetSocketOptions(PGPSocketRef inSocketRef, PGPInt32 inLevel,
e833cd ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inOptionName,
05f14d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char * inOptionValue,
15a996 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inOptionLength);
94af5a
a61211 /* TLS */
3ad273 PGPError¤   PGPSocketsEstablishTLSSession(PGPSocketRef inSocketRef,
1cfc5a ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ··PGPtlsSessionRef inTLSSession);
a3af5a
f5af5a
9dcbcf #if PRAGMA_IMPORT_SUPPORTED
f32ced #pragma import reset
5d7454 #endif
a3af5a
8f1254 PGP_END_C_DECLARATIONS
25af5a
16b9f9 #endif /* Included_pgpSockets_h */
--f476 00091dc05a7401002ab Page 1 of pgpSymmetricCipher.h
a70335 /*____________________________________________________________________________
c91913 ¤   pgpSymmetricCipher.h
b767c5 ¤
45c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
354b0f ¤   All rights reserved.
4a67c5 ¤
9a3461 ¤   public header file for symmetric ciphers
38af5a
bb6ead ¤   $Id: pgpSymmetricCipher.h,v 1.21.12.1 1998/11/12 03:23:43 heller Exp $
fcf7f7 ____________________________________________________________________________*/
9b507a #ifndef Included_pgpSymmetricCipher_h¤  /* [ */
bb0893 #define Included_pgpSymmetricCipher_h
1caf5a
32e82c #include "pgpPubTypes.h"
566773 #include "pgpMemoryMgr.h"
c3af5a
df99c6 PGP_BEGIN_C_DECLARATIONS
28cbcf #if PRAGMA_IMPORT_SUPPORTED
cab981 #pragma import on
267454 #endif
6caf5a
9daf5a
6daf5a
c50335 /*____________________________________________________________________________
7c36b3 ¤   Create a new cipher of the specified algorithm. ·Cannot be used until
52ecf7 ¤   PGPSetSymmetricCipherKey() has been called.
6067c5 ¤
dc2571 ¤   If the algorithm is not available then kPGPError_AlgorithmNotAvailable is
ad4d20 ¤   returned.
5667c5 ¤
fbb6c5 ¤   Existing algorithms have only one key size. ·Values:
b14955 ¤   ¤   kPGPCipherAlgorithm_CAST5¤  ¤   128 / 8 = 16
69c781 ¤   ¤   kPGPCipherAlgorithm_3DES¤   ¤   192 / 8 = 24
7aeb21 ¤   ¤   kPGPCipherAlgorithm_IDEA¤   ¤   128 / 8 = 16
c375a6 ¤   In the future symmetric ciphers could be added that have different key
855d59 ¤   sizes for the same algorithm.
9bf7f7 ____________________________________________________________________________*/
3a191c PGPError ¤  PGPNewSymmetricCipherContext( PGPMemoryMgrRef memoryMgr,
eb4c31 ¤   ¤   ¤   ¤   ¤   PGPCipherAlgorithm¤ algorithm, PGPSize keySizeInBytes,
bfc44f ¤   ¤   ¤   ¤   ¤   PGPSymmetricCipherContextRef *outRef );
06af5a
42af5a
100335 /*____________________________________________________________________________
e0ea66 ¤   Disposal clears all data in memory before releasing it.
6ff7f7 ____________________________________________________________________________*/
5e9b73 PGPError ¤  PGPFreeSymmetricCipherContext( PGPSymmetricCipherContextRef ref );
51af5a
87af5a
de0335 /*____________________________________________________________________________
501f23 ¤   Make an exact copy of the cipher, including the key.
94f7f7 ____________________________________________________________________________*/
c3b447 PGPError ¤  PGPCopySymmetricCipherContext( PGPSymmetricCipherContextRef ref,
a4c44f ¤   ¤   ¤   ¤   ¤   PGPSymmetricCipherContextRef *outRef );
a0af5a
13af5a
830335 /*____________________________________________________________________________
1c5467 ¤   The key must be set before using; a cipher can be repeatedly reset and
c01052 ¤   reused with different keys to avoid having to create and destroy new
bbeade ¤   contexts each time (and it's also cryptographically better not to reuse
590f34 ¤   a key).
9567c5 ¤
bb124c ¤   kKey size is implicit based on algorithm. ·'key' is *copied*. ·Caller
aa8d20 ¤   may want to destroy the original after passing it in.
7df7f7 ____________________________________________________________________________*/
65b104 PGPError ¤  PGPInitSymmetricCipher( PGPSymmetricCipherContextRef ref,
8933b1 ¤   ¤   ¤   ¤   ¤   const void *key );
b3ae30 ¤   ¤   ¤   ¤   ¤
020335 /*____________________________________________________________________________
245ad1 ¤   Wipe any sensitive data in the cipher. ·Cipher remains alive, but
556f32 ¤   key must be set before any data is encrypted.
0bf7f7 ____________________________________________________________________________*/
91a7ff PGPError ¤  PGPWipeSymmetricCipher( PGPSymmetricCipherContextRef ref );
--c2e6 001ea14e6dd401002ab Page 2 of pgpSymmetricCipher.h
e0af5a
1aaf5a
7d0335 /*____________________________________________________________________________
a313c1 ¤   "Wash" the symmetric cipher
a7f7f7 ____________________________________________________________________________*/
749dc6 PGPError ¤  PGPWashSymmetricCipher( PGPSymmetricCipherContextRef ref,
015708 ¤   ¤   ¤   ¤   ¤   void const *buf, PGPSize len);
b1af5a
6faf5a
640335 /*____________________________________________________________________________
8cbdec ¤   Encrypt or decrypt one "block" of data. ·The block size is determined
e92d96 ¤   by the cipher (see PGPGetSymmetricCipherBlockSize()).
e5f7f7 ____________________________________________________________________________*/
4abbbf PGPError ¤  PGPSymmetricCipherEncrypt( PGPSymmetricCipherContextRef ref,
689480 ¤   ¤   ¤   ¤   ¤   const void *in, void *out );
3bae30 ¤   ¤   ¤   ¤   ¤
fc06ab PGPError ¤  PGPSymmetricCipherDecrypt( PGPSymmetricCipherContextRef ref,
179480 ¤   ¤   ¤   ¤   ¤   const void *in, void *out );
02af5a
99af5a
1baf5a
c4ae30 ¤   ¤   ¤   ¤   ¤
230335 /*____________________________________________________________________________
515f21 ¤   Determine key and block size for specified algorithm. ·Stateless routine
cf4f3f ¤   does not need a context.
04f7f7 ____________________________________________________________________________*/
c9ebb9 PGPError ¤  PGPGetSymmetricCipherSizes(
e5e1bb ¤   ¤   ¤   ¤   ¤   PGPSymmetricCipherContextRef¤   ref,
de8031 ¤   ¤   ¤   ¤   ¤   PGPSize *keySize , PGPSize *blockSize );
fcaf5a
f8af5a
93af5a
84cbcf #if PRAGMA_IMPORT_SUPPORTED
092ced #pragma import reset
e47454 #endif
0a1254 PGP_END_C_DECLARATIONS
b5af5a
20af5a
19af5a
ead012 #endif /* ] Included_pgpSymmetricCipher_h */
6baf5a
0caf5a
627e4d /*__Editor_settings____
61af5a
7d4126 ¤   Local Variables:
647b17 ¤   tab-width: 4
170e6c ¤   End:
565f8c ¤   vi: ts=4 sw=4
dc9e9b ¤   vim: si
ead062 _____________________*/
--aaec 0008d897e4d401002ac Page 1 of pgpTLS.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
914999 ¤   $Id: pgpTLS.h,v 1.25.2.1.2.1 1998/11/12 03:23:44 heller Exp $
4ef7f7 ____________________________________________________________________________*/
6185d4 #ifndef Included_PGPtls_h¤  /* [ */
3311da #define Included_PGPtls_h
25af5a
08e82c #include "pgpPubTypes.h"
61af5a
9099c6 PGP_BEGIN_C_DECLARATIONS
87cbcf #if PRAGMA_IMPORT_SUPPORTED
9db981 #pragma import on
cd7454 #endif
71af5a
17af5a
82ce63 typedef struct PGPtlsContext *¤ ¤   ¤   PGPtlsContextRef;
7f764e typedef const struct PGPtlsContext *¤   PGPtlsConstContextRef;
14af5a
73417c #define¤kInvalidPGPtlsContextRef¤   ¤   ((PGPtlsContextRef) NULL)
c21a57 #define PGPtlsContextRefIsValid( ref )¤ ( (ref) != kInvalidPGPtlsContextRef )
9aaf5a
9f498e typedef struct PGPtlsSession *¤ ¤   ¤   PGPtlsSessionRef;
255cfb typedef const struct PGPtlsSession *¤   PGPtlsConstSessionRef;
f6af5a
c35507 #define¤kInvalidPGPtlsSessionRef¤   ¤   ((PGPtlsSessionRef) NULL)
546c09 #define PGPtlsSessionRefIsValid( ref )¤ ( (ref) != kInvalidPGPtlsSessionRef )
fbaf5a
81af5a
d2ed71 typedef PGPFlags¤   ¤   PGPtlsFlags;
aa1a89 #define kPGPtlsFlags_ServerSide¤¤   ¤   ¤   0x01
c7915a #define kPGPtlsFlags_ClientSide¤¤   ¤   ¤   0x02
9f5ddd #define kPGPtlsFlags_RequestClientCert¤ ¤   0x04
fede6b #define kPGPtlsFlags_NonBlockingIO¤ ¤   ¤   0x08
58af5a
c7c23a enum PGPtlsCipherSuiteNum_
b6bb36 {
384699 ¤   kPGPtls_TLS_NULL_WITH_NULL_NULL¤¤   ¤   ¤   ¤   = 0,
389b71 ¤   kPGPtls_TLS_PGP_DHE_DSS_WITH_CAST_CBC_SHA¤  ¤   = 1,
b66acf ¤   kPGPtls_TLS_PGP_DHE_RSA_WITH_CAST_CBC_SHA¤  ¤   = 2,
ac30bc ¤   kPGPtls_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA¤  ¤   = 3,
236c3f ¤   kPGPtls_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA¤  ¤   = 4,¤
a3850c ¤   kPGPtls_TLS_RSA_WITH_3DES_EDE_CBC_SHA¤  ¤   ¤   = 5,
928a38 ¤   kPGPtls_TLS_RSA_WITH_IDEA_CBC_SHA¤  ¤   ¤   ¤   = 6,
53be34 ¤   kPGPtls_TLS_PGP_RSA_WITH_CAST_CBC_SHA¤  ¤   ¤   = 7,
d9e191 ¤   kPGPtls_TLS_PGP_DHE_DSS_WITH_NULL_SHA¤  ¤   ¤   = 8,
cdaf5a
a310a8 ¤   PGP_ENUM_FORCE( PGPtlsCipherSuiteNum_ )
7882f7 };
1ef386 PGPENUM_TYPEDEF( PGPtlsCipherSuiteNum_, PGPtlsCipherSuiteNum );
4caf5a
3e72dd enum PGPtlsProtocolState_
c6bb36 {
4aba0f ¤   kPGPtls_IdleState¤  ¤   ¤   = 0,
80b1eb ¤   kPGPtls_FatalErrorState¤¤   = 1,
31bceb ¤   kPGPtls_ClosedState¤¤   ¤   = 2,
d1e3a3 ¤   kPGPtls_HandshakeState¤ ¤   = 3,
7ed851 ¤   kPGPtls_ReadyState¤ ¤   ¤   = 4,
08af5a
974167 ¤   PGP_ENUM_FORCE( PGPtlsProtocolState_ )
f382f7 };
a41b5d PGPENUM_TYPEDEF( PGPtlsProtocolState_, PGPtlsProtocolState );
21af5a
506ccc enum PGPtlsPrime_
e7bb36 {
ae2cd9 ¤   kPGPtls_DHPrime1024¤¤   = 0,
fb4b6b ¤   kPGPtls_DHPrime1536¤¤   = 1,
6dff6d ¤   kPGPtls_DHPrime2048¤¤   = 2,
f34b3d ¤   kPGPtls_DHPrime3072¤¤   = 3,
81e4cb ¤   kPGPtls_DHPrime4096¤¤   = 4,
8daf5a
--9fd2 00006e4ceb8401002ac Page 2 of pgpTLS.h
d4785b ¤   PGP_ENUM_FORCE( PGPtlsPrime_ )
f982f7 };
8a393b PGPENUM_TYPEDEF( PGPtlsPrime_, PGPtlsPrime );
d9af5a
dce4e3 enum PGPtlsAlert_
9abb36 {
023430 ¤   kPGPtls_AT_CloseNotify¤ ¤   ¤   = 0,
86ecd0 ¤   kPGPtls_AT_UnexpectedMessage¤   = 10,¤  /* FATAL */
188033 ¤   kPGPtls_AT_BadRecordMAC¤¤   ¤   = 20,¤  /* FATAL */
85d5b2 ¤   kPGPtls_AT_DecryptionFailed¤¤   = 21,¤  /* FATAL */
37bc21 ¤   kPGPtls_AT_RecordOverflow¤  ¤   = 22,¤  /* FATAL */
bf77dc ¤   kPGPtls_AT_DecompressionFailure¤= 30,¤  /* FATAL */
3194d9 ¤   kPGPtls_AT_HandshakeFailure¤¤   = 40,¤  /* FATAL */
7b4ba5 ¤   kPGPtls_AT_NoCertificate¤   ¤   = 41,¤  /* SSL3 ·*/
6405d6 ¤   kPGPtls_AT_BadCertificate¤  ¤   = 42,
680a82 ¤   kPGPtls_AT_UnsupportedCert¤ ¤   = 43,
554f95 ¤   kPGPtls_AT_CertRevoked¤ ¤   ¤   = 44,
2ce223 ¤   kPGPtls_AT_CertExpired¤ ¤   ¤   = 45,
d5d412 ¤   kPGPtls_AT_CertUnknown¤ ¤   ¤   = 46,
10b5f6 ¤   kPGPtls_AT_IllegalParameter¤¤   = 47,¤  /* FATAL */
7f359d ¤   kPGPtls_AT_UnknownCA¤   ¤   ¤   = 48,¤  /* FATAL */
58c18f ¤   kPGPtls_AT_AccessDenied¤¤   ¤   = 49,¤  /* FATAL */
4619a2 ¤   kPGPtls_AT_DecodeError¤ ¤   ¤   = 50,¤  /* FATAL */
9c28cb ¤   kPGPtls_AT_DecryptError¤¤   ¤   = 51,
5e7fed ¤   kPGPtls_AT_ExportRestriction¤   = 60,¤  /* FATAL */
6bb6b4 ¤   kPGPtls_AT_ProtocolVersion¤ ¤   = 70,¤  /* FATAL */
70e98f ¤   kPGPtls_AT_InsufficientSecurity¤= 71,¤  /* FATAL */
4d46ab ¤   kPGPtls_AT_InternalError¤   ¤   = 80,¤  /* FATAL */
f09eb4 ¤   kPGPtls_AT_UserCancelled¤   ¤   = 90,
8b6c8b ¤   kPGPtls_AT_NoRenegotiation¤ ¤   = 100,
5b67c5 ¤
440954 ¤   kPGPtls_AT_None¤¤   ¤   ¤   ¤   = 255,
1daf5a
ead0e0 ¤   PGP_ENUM_FORCE( PGPtlsAlert_ )
0282f7 };
315601 PGPENUM_TYPEDEF( PGPtlsAlert_, PGPtlsAlert );
19af5a
2826c6 /* The Send and Receive function pointers should return
4564b1 ¤   kPGPError_TLSWouldBlock when the socket is non-blocking and the
5a9f60 ¤   call would block. ·The Send and Receive functions passed in will
8878dd ¤   need to translate the platform-specific socket error in appropriate
a576ff ¤   cases by using calls such as WSAGetLastError() on Win32. ·Remember
c9a75a ¤   to call PGPtlsSendQueueIdle for non-blocking sockets also if
3de7d5 ¤   kPGPError_TLSWouldBlock is returned from a send on a non-blocking
ac52f0 ¤   socket. */
35af5a
ba6f2b typedef PGPInt32 (* PGPtlsReceiveProcPtr)(void *inData, void *outBuffer,
dd1c8d ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inBufferSize);
9684b6 typedef PGPInt32 (* PGPtlsSendProcPtr)(void *inData, const void *inBuffer,
ea8eac ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPInt32 inBufferLength);
a4af5a
b9af5a
8a8cf8 PGPError ¤  PGPNewTLSContext( PGPContextRef context,
f39217 ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef *outRef );
abaf5a
e48273 PGPError ¤  PGPFreeTLSContext( PGPtlsContextRef ref );
70af5a
280335 /*____________________________________________________________________________
c96536 ¤   The following function activates or deactivates the session key cache
203b9e ¤   for TLS sessions. ·This defaults to on but can be deactivated with this
5bec59 ¤   function to force all connections to proceed through the entire
0eea62 ¤   handshake.
9ff7f7 ____________________________________________________________________________*/
7bf88f PGPError¤   PGPtlsSetCache( PGPtlsContextRef ref, PGPBoolean useCache );
09af5a
d2af12 PGPError¤   PGPtlsClearCache( PGPtlsContextRef ref );
9caf5a
7d6215 PGPError¤   PGPNewTLSSession( PGPtlsContextRef¤ ref,
12029f ¤   ¤   ¤   ¤   ¤   PGPtlsSessionRef¤   ¤   ¤   *outRef );
d3af5a
528609 PGPError ¤  PGPFreeTLSSession( PGPtlsSessionRef ref );
06af5a
--3c88 00037d42849401002ac Page 3 of pgpTLS.h
2b9d5a /* Default options are client side and no client cert request */
710834 PGPError¤   PGPtlsSetProtocolOptions( PGPtlsSessionRef ref,
bc9e98 ¤   ¤   ¤   ¤   ¤   PGPtlsFlags options );
34ae30 ¤   ¤   ¤   ¤   ¤
adaf5a
9f0335 /*____________________________________________________________________________
833084 ¤   The following function must be called to cleanly close a TLS
e9e245 ¤   connection. ·If it is not called, the session will not be able
9f0a02 ¤   to be resumed from the session cache.
c767c5 ¤
dacd76 ¤   In the event the application determines any problem with the
2f7a69 ¤   connection such as the remote key not being valid, call this
36eac2 ¤   function with dontCache set to true in order to not cache the
f7f556 ¤   session keys.
46f7f7 ____________________________________________________________________________*/
aba3ac PGPError¤   PGPtlsClose( PGPtlsSessionRef¤  ref,
658d77 ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   dontCache );
4eaf5a
5a0335 /*____________________________________________________________________________
db61f6 ¤   The following function must be called to initiate the PGPtls session.
fec52a ¤   Once a TLS session has been assigned to a socket, no data can be sent
3078c5 ¤   over that socket by the application until the handshake is completed.
9211f3 ¤   Handshake completion is indicated by completion of this call without
97b85b ¤   error or by checking the state of the PGPtlsSession. ·It will be
2b3ce3 ¤   kPGPtls_ReadyState when the application layer may send and receive
fecb87 ¤   data securely.
2a67c5 ¤
81bd2b ¤   This function performs all negotiation of the TLS connection.
81f7f7 ____________________________________________________________________________*/
7c86d4 PGPError¤   PGPtlsHandshake( PGPtlsSessionRef ref );
11af5a
480335 /*____________________________________________________________________________
ef84e1 ¤   The following function should be called before PGPtlsHandshake.
137473 ¤   In the general case, the remoteID will be an IP address. ·This
c9cdf8 ¤   is provided to PGPtls in order to allow it to cache the current
5e4053 ¤   session and be able to look it up later. ·If the remoteID passed
533240 ¤   into a future session is the same as a previously cached session,
2e5e98 ¤   PGPtls will attempt to resume the session.
6df7f7 ____________________________________________________________________________*/
76178f PGPError¤   PGPtlsSetRemoteUniqueID( PGPtlsSessionRef ref,
3e87f8 ¤   ¤   ¤   ¤   ¤   PGPUInt32 remoteID );
d9af5a
5b0335 /*____________________________________________________________________________
cec38c ¤   The following function sets the local private authenticating key.
1167c5 ¤
2d7c1b ¤   The passphrase and key are retained in memory. ·By default, no
617dd9 ¤   key is specified and a client side session will return no key in the
24ea90 ¤   client key exchange message to the server.
df7151 ¤   It is an error not to specify a key on a server side TLS session.
0358a0 ¤   This function must be passed either PGPOPassphrase or PGPOPasskeyBuffer.
f8f7f7 ____________________________________________________________________________*/
8c2f66 PGPError¤   PGPtlsSetLocalPrivateKey( PGPtlsSessionRef ref,
d76bd6 ¤   ¤   ¤   ¤   ¤   PGPKeyRef¤  ¤   ¤   inKey,
7f0d17 ¤   ¤   ¤   ¤   ¤   PGPOptionListRef¤   firstOption, ... );
3fae30 ¤   ¤   ¤   ¤   ¤
ce0335 /*____________________________________________________________________________
50fb66 ¤   The following function sets the preferred cipher suite.
1767c5 ¤
51d3f7 ¤   There is no guarantee that cipher will actually be negotiated,
7f42cc ¤   but it will be attempted in preference to others.
eff7f7 ____________________________________________________________________________*/
1b2393 PGPError¤   PGPtlsSetPreferredCipherSuite( PGPtlsSessionRef ref,
bec288 ¤   ¤   ¤   ¤   ¤   PGPtlsCipherSuiteNum cipher );
77af5a
7f0335 /*____________________________________________________________________________
7e9e68 ¤   The following function sets the desired DH prime.
b167c5 ¤
a3cc79 ¤   The requested primes are drawn from a set of primes hard-coded
b4a044 ¤   into PGPtls. ·New primes can be added in a fully compatible
bacb54 ¤   fashion since the server sends the prime to the client, but this
6188e6 ¤   version of the API does not support passing in a desired prime. ·The
371139 ¤   default prime if this function is not called is kPGPtls_DHPrime2048.
--8616 000aca11136401002ac Page 4 of pgpTLS.h
eaf7f7 ____________________________________________________________________________*/
8d74f2 PGPError¤   PGPtlsSetDHPrime( PGPtlsSessionRef ref,
c02f08 ¤   ¤   ¤   ¤   ¤   PGPtlsPrime prime );
42af5a
010335 /*____________________________________________________________________________
cde478 ¤   The following function gets the authenticated remote key after a
b9436b ¤   successful handshake.
4167c5 ¤
5ec932 ¤   The key returned must already have been approved through the callback
c74691 ¤   mechanism. ·The PGPEvent mechanism is used to request approval from the
eb8919 ¤   client of the remote key received during the TLS handshake. ·The
1cbbb6 ¤   callback should be set through the standard PGPSockets callback
0ba9bd ¤   mechanism. ·The event kPGPEvent_TLSRemoteKeyApprovalEvent will be
9003b7 ¤   used in this case. ·In some cases, the
12528b ¤   kPGPEvent_TLSRemoteKeyApprovalEvent may only pass a Key ID to the
b3ab2f ¤   caller, and it will be up to the caller to resolve the Key ID into a
7554bf ¤   key and pass the PGPKeyRef back to TLS.
50f7f7 ____________________________________________________________________________*/
fa1cf1 PGPError¤   PGPtlsGetRemoteAuthenticatedKey( PGPtlsSessionRef ref,
90c705 ¤   ¤   ¤   ¤   ¤   PGPKeyRef *outKey );
cfaf5a
530335 /*____________________________________________________________________________
991583 ¤   The following function returns the negotiated symmetric cipher.
9167c5 ¤
8e65c1 ¤   This function will return an error if called before a successful
53ea62 ¤   handshake.
85f7f7 ____________________________________________________________________________*/
e655c2 PGPError¤   PGPtlsGetNegotiatedCipherSuite( PGPtlsSessionRef ref,
860457 ¤   ¤   ¤   ¤   ¤   PGPtlsCipherSuiteNum *outCipher );
4aaf5a
1543e4 PGPError¤   PGPtlsGetState( PGPtlsSessionRef ref,
540e0f ¤   ¤   ¤   ¤   ¤   PGPtlsProtocolState *outState );
58af5a
6e0335 /*____________________________________________________________________________
6a362f ¤   The following two functions process data through TLS.
e467c5 ¤
36b7c4 ¤   It is an error to call these functions without having set a
fe9df9 ¤   Read function pointer or Write function pointer. ·Most applications
ff6de2 ¤   will never need to use these functions as the function pointers
78d8bc ¤   are automatically configured by PGPsockets, and these functions
8bddf2 ¤   are automatically called by the PGPsockets implementations of
2d0357 ¤   PGPWrite and PGPRead whenever a PGPtlsSessionRef has been set for
9df060 ¤   a given socket.
5af7f7 ____________________________________________________________________________*/
62d308 PGPError¤   PGPtlsReceive( PGPtlsSessionRef ref,
b86bd2 ¤   ¤   ¤   ¤   ¤   void *¤ ¤   ¤   outBuffer,
1480b3 ¤   ¤   ¤   ¤   ¤   PGPSize *¤  ¤   bufferSize );
a3af5a
a04f16 PGPError¤   PGPtlsSend( PGPtlsSessionRef ref,
c3927f ¤   ¤   ¤   ¤   ¤   const void *¤   inBuffer,
216aec ¤   ¤   ¤   ¤   ¤   PGPSize ¤   ¤   inBufferLength );
7cae30 ¤   ¤   ¤   ¤   ¤
59cc87 PGPError¤   PGPtlsSetReceiveCallback( PGPtlsSessionRef¤ ref,
53308a ¤   ¤   ¤   ¤   ¤   PGPtlsReceiveProcPtr¤   tlsReceiveProc,
d9300f ¤   ¤   ¤   ¤   ¤   void *¤ ¤   ¤   ¤   ¤   inData );
91af5a
1beb32 PGPError¤   PGPtlsSetSendCallback( PGPtlsSessionRef ref,
318e82 ¤   ¤   ¤   ¤   ¤   PGPtlsSendProcPtr¤  ¤   tlsSendProc,
ab300f ¤   ¤   ¤   ¤   ¤   void *¤ ¤   ¤   ¤   ¤   inData );
e9af5a
90af5a
b30335 /*____________________________________________________________________________
ca33cf ¤   The following function is necessary *only* on a non-blocking socket.
669cee ¤   If a call to PGPtlsSend returns kPGPError_TLSWouldBlock, call
79c92f ¤   the following function repeatedly until that error is no longer
636231 ¤   returned in order to make sure data is sent. ·Another call to
1e5b43 ¤   PGPtlsSend will also call this function automatically and queue
3d1c8f ¤   any new data if necessary.
60f7f7 ____________________________________________________________________________*/
34d2ea PGPError¤   PGPtlsSendQueueIdle( PGPtlsSessionRef ref );
dfae30 ¤   ¤   ¤   ¤   ¤
ac0335 /*____________________________________________________________________________
--b397 00187ac687e401002ac Page 5 of pgpTLS.h
955b3b ¤   The following function gets the ID of the fatal alert which caused
dbd333 ¤   the TLS session to abort and go into the kPGPtls_FatalErrorState.
28f7f7 ____________________________________________________________________________*/
2f10da PGPError¤   PGPtlsGetAlert( PGPtlsSessionRef ref, PGPtlsAlert *outAlert );
ccaf5a
09af5a
01cbcf #if PRAGMA_IMPORT_SUPPORTED
f32ced #pragma import reset
bf7454 #endif
a21254 PGP_END_C_DECLARATIONS
f4af5a
7a1993 #endif /* ] Included_PGPtls_h */
eeaf5a
4eaf5a
b47e4d /*__Editor_settings____
7baf5a
d34126 ¤   Local Variables:
d27b17 ¤   tab-width: 4
e80e6c ¤   End:
af5f8c ¤   vi: ts=4 sw=4
7c9e9b ¤   vim: si
87d062 _____________________*/
--7c1c 000d0ee2119401002ad Page 1 of pgpUserInterface.h
a70335 /*____________________________________________________________________________
d4c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
374b0f ¤   All rights reserved.
3b67c5 ¤
f6bd78 ¤   This file contains the prototypes for functions which use UI to interact
f2c4f1 ¤   with the user.
c6af5a
6733ec ¤   $Id: pgpUserInterface.h,v 1.38.10.1 1998/11/12 03:23:44 heller Exp $
28f7f7 ____________________________________________________________________________*/
79af5a
c59f2c #ifndef Included_pgpUserInterface_h¤/* [ */
6862bb #define Included_pgpUserInterface_h
7aaf5a
b0e82c #include "pgpPubTypes.h"
1cc2ae #include "pgpGroups.h"
95af5a
c2afb9 #if PGP_WIN32
e5729d #include "windows.h"
187454 #endif
84af5a
aa99c6 PGP_BEGIN_C_DECLARATIONS
7eaf5a
a4cbcf #if PRAGMA_IMPORT_SUPPORTED
4cb981 #pragma import on
f17454 #endif
39af5a
c4fa23 #if PRAGMA_ALIGN_SUPPORTED
3faf46 #pragma options align=mac68k
167454 #endif
01af5a
e54e3a enum PGPAdditionalRecipientRequestEnforcement_
35bb36 {
268dd9 ¤   kPGPARREnforcement_Invalid¤ = 0,
81ccc8 ¤   kPGPARREnforcement_None¤¤   = 1,
640c2f ¤   kPGPARREnforcement_Warn¤¤   = 2,
a07b01 ¤   kPGPARREnforcement_Strict¤  = 3,
b0af5a
351fa5 ¤   PGP_ENUM_FORCE( PGPAdditionalRecipientRequestEnforcement_ )
eb82f7 };
88bfaf PGPENUM_TYPEDEF( PGPAdditionalRecipientRequestEnforcement_,
f37c05 ¤   ¤   ¤   ¤   PGPAdditionalRecipientRequestEnforcement );
d9af5a
ed473e enum PGPRecipientSpecType_
47bb36 {
49d179 ¤   kPGPRecipientSpecType_Invalid¤  = 0,
7cff03 ¤   kPGPRecipientSpecType_Key¤  ¤   = 1,
f982f9 ¤   kPGPRecipientSpecType_UserID¤   = 2,
1171d4 ¤   kPGPRecipientSpecType_KeyID¤¤   = 3,
ee67c5 ¤
5ca46d ¤   PGP_ENUM_FORCE( PGPRecipientSpecType_ )
ef82f7 };
98a806 PGPENUM_TYPEDEF( PGPRecipientSpecType_, PGPRecipientSpecType );
7eaf5a
cc3447 typedef struct PGPRecipientSpec
7bbb36 {
78c819 ¤   PGPRecipientSpecType¤   type;
b4bb2a ¤   PGPBoolean¤ ¤   ¤   ¤   locked;
f65cca ¤   PGPBoolean¤ ¤   ¤   ¤   reserved8[3];¤  /* Must be zero */
4c6228 ¤   PGPUInt32¤  ¤   ¤   ¤   reserved32[3];¤ /* Must be zero */
d467c5 ¤
19f20a ¤   union
52c7a1 ¤   {
d97444 ¤   ¤   PGPKeyRef¤  key;
298001 ¤   ¤   char¤   ¤   userIDStr[256];¤¤   /* Null terminated string */
c41b52 ¤   ¤
652b33 ¤   ¤   struct
f75b34 ¤   ¤   {
3d70a4 ¤   ¤   ¤   PGPKeyID¤   ¤   ¤   ¤   keyID;
e775e3 ¤   ¤   ¤   PGPPublicKeyAlgorithm¤  algorithm;
1e5b63 ¤   ¤   } id;
7f1b52 ¤   ¤
d0fef9 ¤   } u;
--7bd0 000dd625959401002ad Page 2 of pgpUserInterface.h
e0af5a
6658ef } PGPRecipientSpec;
d2af5a
1e4db1 typedef struct PGPKeyServerSpec
2cbb36 {
98218f ¤   PGPKeyServerRef¤¤   server;
e073d1 ¤   const char¤ ¤   ¤   *serverName;¤   /* Optional */
2c95ac ¤   PGPUInt32¤  ¤   ¤   reserved[5];¤   /* Must be zero */
3caf5a
48ca2f } PGPKeyServerSpec;
53af5a
8cfa23 #if PRAGMA_ALIGN_SUPPORTED
fa7c46 #pragma options align=reset
3a7454 #endif
b7af5a
ad8925 PGPError¤   PGPRecipientDialog(
ffd6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
405922 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   allKeys,
bc89b7 ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   alwaysDisplayDialog,
a20492 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   *recipientKeys,
d44f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
c4af5a
41117d PGPError¤   PGPPassphraseDialog(
f2d6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
ae4f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
0faf5a
df73aa PGPError¤   PGPConfirmationPassphraseDialog(
9ed6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
bf4f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
47af5a
322115 PGPError¤   PGPKeyPassphraseDialog(
92d6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
b68121 ¤   ¤   ¤   ¤   ¤   PGPKeyRef¤  ¤   ¤   theKey,
504f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
40af5a
da9767 PGPError¤   PGPSigningPassphraseDialog(
97d6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
055261 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   ¤   allKeys,
62a436 ¤   ¤   ¤   ¤   ¤   PGPKeyRef¤  ¤   ¤   *signingKey,
694f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
0daf5a
73088e PGPError¤   PGPDecryptionPassphraseDialog(
64ba11 ¤   ¤   ¤   ¤   ¤   PGPContextRef¤  ¤   context,¤   ¤   ¤   ¤   ¤   ¤   ¤
2e5ca8 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef¤   ¤   recipientKeys,
25374e ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   keyIDCount,
aa6efd ¤   ¤   ¤   ¤   ¤   const PGPKeyID¤ ¤   keyIDList[],¤   ¤
cfd493 ¤   ¤   ¤   ¤   ¤   PGPKeyRef ¤ ¤   ¤   *decryptionKey,
7e4f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
83af5a
d0a460 PGPError¤   PGPConventionalEncryptionPassphraseDialog(
38d6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
514f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
8caf5a
2e1ec4 PGPError¤   PGPConventionalDecryptionPassphraseDialog(
f8cbed ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,¤   ¤   ¤   ¤   ¤   ¤   ¤
ee4f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
55af5a
739b05 PGPError¤   PGPOptionsDialog(
dbd6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
864f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
92af5a
5e1e07 PGPError¤   PGPCollectRandomDataDialog(
d7d6a7 ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   context,
1422d0 ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   neededEntropyBits,
584f5a ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  firstOption, ... );
4faf5a
77240e PGPError¤   PGPSearchKeyServerDialog(
e7956f ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   ¤   context,
c479f1 ¤   ¤   ¤   ¤   ¤   PGPUInt32¤  ¤   ¤   ¤   serverCount,
65170e ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec ¤serverList[],
5302ae ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef¤   ¤   tlsContext,
dd70c1 ¤   ¤   ¤   ¤   ¤   PGPBoolean¤ ¤   ¤   ¤   searchAllServers,
--65cb 000f95ba845401002ad Page 3 of pgpUserInterface.h
37b0bb ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys,
1061eb ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  ¤   firstOption, ... );
92af5a
12c350 PGPError¤   PGPSendToKeyServerDialog(
d1956f ¤   ¤   ¤   ¤   ¤   PGPContextRef ¤ ¤   ¤   context,
de769d ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec ¤*server,
2d02ae ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef¤   ¤   tlsContext,
064183 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   ¤   keysToSend,
7f9b61 ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   ¤   *failedKeys,
1661eb ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  ¤   firstOption, ... );
dced43 ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤   ¤
3638e5 /*
cbd175 ** Returns a value in the range 0-100 which crudely estimates
db0d54 ** the "quality" of a passphrase.
f17fe0 */
f9af5a
a2ddf6 PGPUInt32¤  PGPEstimatePassphraseQuality(const char *passphrase);
31af5a
271c29 /* General dialog options */
c3af5a
92d812 PGPOptionListRef¤   PGPOUIDialogPrompt(PGPContextRef context,
5c2364 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char *prompt);
e8af5a
4c21bb PGPOptionListRef¤   PGPOUIWindowTitle(PGPContextRef context,
71900d ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char *title);
8caf5a
72cdcb PGPOptionListRef¤   PGPOUIDialogOptions(PGPContextRef context,
a6a0f8 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef firstOption, ...);
95af5a
3fafb9 #if PGP_WIN32
0e71be PGPOptionListRef¤   PGPOUIParentWindowHandle(PGPContextRef context,
976c54 ¤   ¤   ¤   ¤   ¤   ¤   ¤   HWND hwndParent);
507454 #endif
d4af5a
96e001 /* All passphrase dialogs */
3aaf5a
41f10b /* Caller should free passphrase with PGPFreeData() */
831745 PGPOptionListRef¤   PGPOUIOutputPassphrase(PGPContextRef context,
fa6a4a ¤   ¤   ¤   ¤   ¤   ¤   ¤   char **passphrase);
27af5a
1572fd PGPOptionListRef¤   PGPOUIMinimumPassphraseQuality(PGPContextRef context,
ad397b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 minimumPassphraseQuality);
d6af5a
ac06bf PGPOptionListRef¤   PGPOUIMinimumPassphraseLength(PGPContextRef context,
35bc34 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 minimumPassphraseLength);
7daf5a
eb1220 /* PGPConfirmationPassphraseDialog() options */
09af5a
e635ed PGPOptionListRef¤   PGPOUIShowPassphraseQuality(PGPContextRef context,
f3e3da ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean showPassphraseQuality);
ffaf5a
3f5d25 /* PGPSigningPassphraseDialog() and PGPDecryptionPassphraseDialog() options */
41af5a
f0f02c PGPOptionListRef¤   PGPOUIDefaultKey(PGPContextRef context,
896cc2 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef defaultKey);
acaf5a
13661e PGPOptionListRef¤   PGPOUIVerifyPassphrase(PGPContextRef context,
7f31d6 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean verifyPassphrase);
15af5a
c5e15c PGPOptionListRef¤   PGPOUIFindMatchingKey(PGPContextRef context,
f62054 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean findMatchingKey);
81af5a
ac3cb0 PGPOptionListRef¤   PGPOUITextUI(PGPContextRef context, PGPBoolean textUI);
11af5a
36b30d /* PGPRecipientDialog() options: */
77af5a
be0343 PGPOptionListRef¤   PGPOUIRecipientList(PGPContextRef context,
303765 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 *recipientCount,
89ef44 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPRecipientSpec **recipientList);
5caf5a
944ed2 PGPOptionListRef¤   PGPOUIDefaultRecipients(PGPContextRef context,
f935d4 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 recipientCount,
--3e23 00153a1614b401002ad Page 4 of pgpUserInterface.h
dac3e1 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const PGPRecipientSpec recipientList[]);
81af5a
1584d3 PGPOptionListRef¤   PGPOUIDisplayMarginalValidity(PGPContextRef context,
efb927 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean displayMarginalValidity);
01af5a
c3880f PGPOptionListRef¤   PGPOUIIgnoreMarginalValidity(PGPContextRef context,
c7dd8e ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean ignoreMarginalValidity);
69af5a
c0dd05 PGPOptionListRef¤   PGPOUIRecipientGroups(PGPContextRef context,
c46b2b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPGroupSetRef groupSet);
abaf5a
2b15ca PGPOptionListRef¤   PGPOUIEnforceAdditionalRecipientRequests(
e1fa4b ¤   ¤   ¤   ¤   ¤   ¤   PGPContextRef context,
b4e64e ¤   ¤   ¤   ¤   ¤   ¤   PGPAdditionalRecipientRequestEnforcement enforcement,
3479b3 ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean alwaysDisplayDialogWithARRs);
98af5a
61f5d6 /* PGPDecryptionPassphraseDialog() and PGPRecipientDialog() only: */
8faf5a
78302f PGPOptionListRef¤   PGPOUIKeyServerUpdateParams(PGPContextRef context,
13ab9b ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 ¤ ¤   ¤   ¤   serverCount,
494917 ¤   ¤   ¤   ¤   ¤   ¤   ¤   const PGPKeyServerSpec ¤serverList[],
f6445f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPtlsContextRef ¤  ¤   tlsContext,
4f5d9d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPBoolean ¤¤   ¤   ¤   searchBeforeDisplay,
8dfbf0 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef ¤  ¤   ¤   *foundKeys,
00790d ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPOptionListRef ¤  ¤   firstOption, ...);
71af5a
efdbdd /* Key server search dialog options */
5baf5a
f019c9 PGPOptionListRef¤   PGPOUIKeyServerSearchFilter(PGPContextRef context,
f29a75 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPFilterRef filter);
b9af5a
497927 PGPOptionListRef¤   PGPOUIKeyServerSearchKey(PGPContextRef context,
5e4bce ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeyRef key);
99af5a
3a6057 PGPOptionListRef¤   PGPOUIKeyServerSearchKeySet(PGPContextRef context,
56e4da ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPKeySetRef keySet);
1eaf5a
9227f5 PGPOptionListRef¤   PGPOUIKeyServerSearchKeyIDList(PGPContextRef context,
c63b1a ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 keyIDCount, const PGPKeyID keyIDList[] );
ffaf5a
2c38e5 /*
417cf7 ** These options are used to build the options dialog and are only
01e7d7 ** applicable for the PGPOptionsDialog() and PGPOUIDialogOptions() calls.
154f76 ** The "description" parameters are optional.·
b07fe0 */
c7af5a
950cff PGPOptionListRef¤   PGPOUICheckbox(PGPContextRef context, PGPUInt32 itemID,
d5dfeb ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char *title, const char *description,
0ab500 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 initialValue, PGPUInt32 *resultPtr);
12af5a
ede039 PGPOptionListRef¤   PGPOUIPopupList(PGPContextRef context, PGPUInt32 itemID,
49dfeb ¤   ¤   ¤   ¤   ¤   ¤   ¤   const char *title, const char *description,
24b68f ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 listItemCount, const char *listItems[],
b3b500 ¤   ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt32 initialValue, PGPUInt32 *resultPtr);
94531f ¤   ¤   ¤   ¤   ¤   ¤   ¤
61cbcf #if PRAGMA_IMPORT_SUPPORTED
592ced #pragma import reset
ea7454 #endif
beaf5a
161254 PGP_END_C_DECLARATIONS
8faf5a
00c938 #endif /* ] Included_pgpUserInterface_h */
18af5a
38af5a
6e7e4d /*__Editor_settings____
5faf5a
e24126 ¤   Local Variables:
5d7b17 ¤   tab-width: 4
ba0e6c ¤   End:
1b5f8c ¤   vi: ts=4 sw=4
769e9b ¤   vim: si
53d062 _____________________*/
--073c 000ef06f3a3401002ae Page 1 of pgpUtilities.h
a70335 /*____________________________________________________________________________
39eb91 ¤   pgpUtilities.h
ff67c5 ¤
67c97d ¤   Copyright (C) 1997 Network Associates, Inc. and its affiliates.
bf4b0f ¤   All rights reserved.
1167c5 ¤
a8d533 ¤   This file contains miscellaneous utility functions needed for the PGPsdk.
f6af5a
8236bc ¤   $Id: pgpUtilities.h,v 1.62.2.1.2.1 1998/11/12 03:23:45 heller Exp $
adf7f7 ____________________________________________________________________________*/
00af5a
78178e #ifndef Included_pgpUtilities_h¤/* [ */
59510e #define Included_pgpUtilities_h
84af5a
ddc21c #if PGP_MACINTOSH¤  /* [ */
0e49ca #include <Files.h>
d1ddc8 #endif¤ /* ] PGP_MACINTOSH */
adaf5a
85e82c #include "pgpPubTypes.h"
2b6773 #include "pgpMemoryMgr.h"
55af5a
420a8b #include <time.h>
92af5a
50af5a
b9fa23 #if PRAGMA_ALIGN_SUPPORTED
2d6071 #pragma options align=mac68k¤   /* [ */
b47454 #endif
fbaf5a
9aaf5a
75c21c #if PGP_MACINTOSH¤  /* [ */
cdaf5a
c95dfa #define kPGPMacFileCreator_Keys¤¤   ¤   ¤   'pgpK'
110383 #define kPGPMacFileCreator_DecryptedBinary¤ '????'
fcf6d0 #define kPGPMacFileCreator_DecryptedText¤   'ttxt'
d66930 #define kPGPMacFileCreator_Tools¤   ¤   ¤   'pgpM'
4faf5a
8d958f #define kPGPMacFileType_ArmorFile¤  ¤   'TEXT'
c9996f #define kPGPMacFileType_EncryptedData¤  'pgEF'
7fd227 #define kPGPMacFileType_SignedData¤ ¤   'pgSF'
a22734 #define kPGPMacFileType_DetachedSig¤¤   'pgDS'
bcc5a2 #define kPGPMacFileType_RandomSeed¤ ¤   'pgRS'
7047f6 #define kPGPMacFileType_PrivRing¤   ¤   'pgRR'
5845ee #define kPGPMacFileType_PubRing¤¤   ¤   'pgPR'
ce8ff2 #define kPGPMacFileType_Groups¤ ¤   ¤   'pgGR'
1adcec #define kPGPMacFileType_Preferences¤¤   'pref'
5c1c11 #define kPGPMacFileType_ExportedKeys¤   'TEXT'
d2af43 #define kPGPMacFileType_DecryptedText¤  'TEXT'
000229 #define kPGPMacFileType_DecryptedBinary¤'BINA'
59b62b #define kPGPMacFileType_KeyShares¤  ¤   'pgSK'
e2af5a
3addc8 #endif¤ /* ] PGP_MACINTOSH */
b0af5a
4699c6 PGP_BEGIN_C_DECLARATIONS
13cbcf #if PRAGMA_IMPORT_SUPPORTED
b7b981 #pragma import on
0b7454 #endif
4daf5a
5d0335 /*____________________________________________________________________________
6e3644 ¤   Context routines
19f7f7 ____________________________________________________________________________*/
d8af5a
e10335 /*____________________________________________________________________________
6ed270 ¤   API version:
380f98 ¤   Top byte is major, next 3 nibbles minor, next 2 bug fix,
66d110 ¤   last nibble reserved: ·0xMMmmmrrR
b067c5 ¤
789a85 ¤   example: 1.0.0 = 0x01000000
c667c5 ¤
7c923f ¤   0x01000000¤ ¤   SDK 1.0.0
0e1cce ¤   0x02000000¤ ¤   SDK 1.1.0
c5fdf1 ¤   0x02000010¤ ¤   SDK 1.1.1
ef93d4 ¤   0x03000000¤ ¤   SDK 1.5
--70f7 000ebe9b740401002ae Page 2 of pgpUtilities.h
2106d4 ¤   0x03000010¤ ¤   SDK 1.5.1
c02d84 ¤   0x03000020¤ ¤   SDK 1.5.2
70f7f7 ____________________________________________________________________________*/
c1ced3 #define kPGPsdkAPIVersion¤  ¤   ( (PGPUInt32)0x03000020 )
98530d #define PGPMajorVersion( v )¤   ( ( ((PGPUInt32)(v)) & 0xFF000000 ) >> 24 )
1e8f0a #define PGPMinorVersion( v )¤   ( ( ((PGPUInt32)(v)) & 0x00FFF000 ) >> 16 )
1dbeb5 #define PGPRevVersion( v )¤ ¤   ( ( ((PGPUInt32)(v)) & 0x00000FF0 ) >> 4 )
4baf5a
02187e typedef struct PGPNewContextStruct
fbbb36 {
31ee47 ¤   /* sizeofStruct must be inited to sizeof( PGPNewContextStruct ) */
87d4ed ¤   PGPUInt32¤  ¤   ¤   ¤   sizeofStruct;
84b586 ¤   PGPMemoryMgrRef¤¤   ¤   memoryMgr;
3f63f2 } PGPNewContextStruct;
4aaf5a
edaf5a
c9af5a
15a1c7 /* always pass kPGPsdkVersion */
732aed PGPError ¤  PGPNewContext( PGPUInt32 clientAPIVersion,
8b202b ¤   ¤   ¤   ¤   PGPContextRef *newContext );
c3b7ab PGPError ¤  PGPNewContextCustom( PGPUInt32 clientAPIVersion,
9935ac ¤   ¤   ¤   ¤   PGPNewContextStruct¤const *custom,
f8202b ¤   ¤   ¤   ¤   PGPContextRef *newContext );
b2af5a
a2379f PGPError ¤  PGPFreeContext( PGPContextRef context );
a8af5a
ac9604 PGPError ¤  PGPGetContextUserValue( PGPContextRef context,
3ffccf ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue *userValue );
d4c3c2 PGPError ¤  PGPSetContextUserValue( PGPContextRef context,
a4a7f0 ¤   ¤   ¤   ¤   ¤   ¤   PGPUserValue userValue );
78af5a
142683 PGPError¤   PGPContextGetRandomBytes(PGPContextRef context,
700074 ¤   ¤   ¤   ¤   ¤   ¤   void *buf, PGPSize len );
e9af5a
85af5a
16521b PGPMemoryMgrRef¤PGPGetContextMemoryMgr( PGPContextRef context );
60af5a
edaf5a
3eaf5a
360335 /*____________________________________________________________________________
d18955 ¤   FileRefs
eaf7f7 ____________________________________________________________________________*/
56af5a
a3012a PGPError ¤  ¤   PGPCopyFileSpec(PGPFileSpecRef fileRef,
116638 ¤   ¤   ¤   ¤   ¤   PGPFileSpecRef *ref);
0cf55e PGPError ¤  ¤   PGPFreeFileSpec(PGPFileSpecRef fileRef);
baaf5a
dcc21c #if PGP_MACINTOSH¤  /* [ */
5faf5a
6defaf PGPError ¤  ¤   PGPNewFileSpecFromFSSpec(PGPContextRef context,
0378fc ¤   ¤   ¤   ¤   ¤   ¤   const FSSpec *spec, PGPFileSpecRef *ref);
96d960 PGPError ¤  ¤   PGPGetFSSpecFromFileSpec(PGPFileSpecRef fileRef,
7e66c6 ¤   ¤   ¤   ¤   ¤   ¤   FSSpec *spec);
59db21 #else
d6af5a
36cdb6 PGPError ¤  ¤   PGPNewFileSpecFromFullPath( PGPContextRef context,
979ca7 ¤   ¤   ¤   ¤   ¤   ¤   char const *path, PGPFileSpecRef *ref);
4aaf5a
4848d8 /* *fullPathPtr ***must*** be freed with PGPFreeData */
dd885b PGPError ¤  ¤   PGPGetFullPathFromFileSpec( PGPFileSpecRef¤ fileRef,
b577c8 ¤   ¤   ¤   ¤   ¤   ¤   char ** fullPathPtr);
2e94aa ¤   ¤   ¤   ¤   ¤   ¤
f4ddc8 #endif¤ /* ] PGP_MACINTOSH */
90af5a
abaf5a
f694aa ¤   ¤   ¤   ¤   ¤   ¤
870335 /*____________________________________________________________________________
6b2a68 ¤   Time
43f7f7 ____________________________________________________________________________*/
3c7262 PGPTime ¤   ¤   ¤   PGPGetTime(void);
97af5a
eb0e8e /* these use time_t type as returned by time() in Std C libraries */
--fdd4 00027227331401002ae Page 3 of pgpUtilities.h
e67dd7 time_t ¤¤   ¤   PGPGetStdTimeFromPGPTime(PGPTime theTime);
4db6c9 PGPTime ¤   ¤   PGPGetPGPTimeFromStdTime(time_t theTime);
9aaf5a
33af5a
65f512 /* year, month, day may be NULL if desired */
8045f2 void ¤  ¤   ¤   PGPGetYMDFromPGPTime( PGPTime theTime,
7a5e07 ¤   ¤   ¤   ¤   ¤   ¤   PGPUInt16 *year, PGPUInt16 *month, PGPUInt16 *day );
54af5a
b5af5a
63c21c #if PGP_MACINTOSH¤  /* [ */
4ed6d0 PGPUInt32 ¤ ¤   PGPTimeToMacTime(PGPTime theTime);
92c3c7 PGPTime ¤   ¤   PGPTimeFromMacTime(PGPUInt32 theTime);
59ddc8 #endif¤ /* ] PGP_MACINTOSH */
1eaf5a
5daf5a
f6af5a
4d0335 /*____________________________________________________________________________
de7fc0 ¤   MacBinary support
c9f7f7 ____________________________________________________________________________*/
faaf5a
3caf5a
200335 /*____________________________________________________________________________
7d2bb2 ¤   Examine the input file to see if it's a MacBinary file. ·If it is
0371e6 ¤   not a MacBinary file, then the original file is unaltered.
d009a4 ¤   Otherwise, the file is converted and the original file is deleted.
4867c5 ¤
9f27bd ¤   The resulting file is designated by 'outPGPSpec' and may have a different
41c199 ¤   name than the original.
1b67c5 ¤
971947 ¤   If the file is a TEXT file, appropriate line-end conversion is done.
8367c5 ¤
5461c8 ¤   creator and type code pointers may be
84e1a9 ¤   null but otherwise contain the mac creator and type.
8967c5 ¤
6e7ccf ¤   This routine can be called on a Mac, but generally doesn't need to be.
52f7f7 ____________________________________________________________________________*/
640710 PGPError¤   PGPMacBinaryToLocal( PGPFileSpecRef inSpec,
0436e5 ¤   ¤   ¤   ¤   PGPFileSpecRef * outSpec,
7be19a ¤   ¤   ¤   ¤   PGPUInt32 * macCreator, PGPUInt32 * macTypeCode );
66af5a
b6af5a
c1af5a
caaf5a
670335 /*____________________________________________________________________________
8e591e ¤   Call PGPsdkInit() before using the SDK. ·Call PGPsdkCleanup() when you are
836396 ¤   done (but after disposing of any PGPContexts).
5367c5 ¤
1a900f ¤   You may call multiple times (with no effect), but be sure to call
66d636 ¤   PGPsdkCleanup() for each call to PGPsdkInit().
c7f7f7 ____________________________________________________________________________*/
eaeb84 PGPError¤   PGPsdkInit( void );
435e0f PGPError¤   PGPsdkCleanup( void );
59af5a
17cbcf #if PRAGMA_IMPORT_SUPPORTED
b32ced #pragma import reset
097454 #endif
4a1254 PGP_END_C_DECLARATIONS
c4af5a
61af5a
57af5a
72fa23 #if PRAGMA_ALIGN_SUPPORTED
dcc366 #pragma options align=reset¤¤   ¤   /* ] */
087454 #endif
92af5a
46db7b #endif /* ] Included_pgpUtilities_h */
acaf5a
c17e4d /*__Editor_settings____
87af5a
9e4126 ¤   Local Variables:
037b17 ¤   tab-width: 4
6e0e6c ¤   End:
275f8c ¤   vi: ts=4 sw=4
--71da 00133d4bd53401002ae Page 4 of pgpUtilities.h
b99e9b ¤   vim: si
33d062 _____________________*/
